Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: SDIO conversion to HAL #3182

Merged
merged 2 commits into from
Aug 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions radio/src/boards/generic_stm32/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ set(BOARD_LIB_SRC
)

add_library(minimal_board_lib OBJECT EXCLUDE_FROM_ALL ${MINIMAL_BOARD_LIB_SRC})

add_library(board_lib OBJECT EXCLUDE_FROM_ALL ${BOARD_LIB_SRC})
add_dependencies(board_lib minimal_board_lib)

set(FIRMWARE_SRC ${FIRMWARE_SRC}
$<TARGET_OBJECTS:minimal_board_lib>
Expand Down
4 changes: 4 additions & 0 deletions radio/src/cli.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1259,6 +1259,10 @@ void printAudioVars()

#include "hal/switch_driver.h"

#if defined(DISK_CACHE)
#include "disk_cache.h"
#endif

int cliDisplay(const char ** argv)
{
long long int address = 0;
Expand Down
40 changes: 33 additions & 7 deletions radio/src/disk_cache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,22 +19,48 @@
* GNU General Public License for more details.
*/

#include "disk_cache.h"
#include "sdcard.h"

#include <string.h>
#include "opentx.h"

#if defined(SIMU) && !defined(SIMU_DISKIO)
#define __disk_read(...) (RES_OK)
#define __disk_write(...) (RES_OK)
#endif

#if 0 // set to 1 to enable traces
#if 0 // set to 1 to enable traces
#include "debug.h"
#define TRACE_DISK_CACHE(...) TRACE(__VA_ARGS__)
#else
#define TRACE_DISK_CACHE(...)
#endif

#if FF_MAX_SS != FF_MIN_SS
#error "Variable sector size is not supported"
#endif

#define BLOCK_SIZE FF_MAX_SS
#define DISK_CACHE_BLOCK_SIZE (DISK_CACHE_BLOCK_SECTORS * BLOCK_SIZE)

DiskCache diskCache;

class DiskCacheBlock
{
public:
DiskCacheBlock();
bool read(BYTE* buff, DWORD sector, UINT count);
DRESULT fill(BYTE drv, BYTE* buff, DWORD sector, UINT count);
void free(DWORD sector, UINT count);
void free();
bool empty() const;

private:
uint8_t data[DISK_CACHE_BLOCK_SIZE];
DWORD startSector;
DWORD endSector;
};

DiskCacheBlock::DiskCacheBlock():
startSector(0),
endSector(0)
Expand Down Expand Up @@ -97,7 +123,7 @@ void DiskCache::clear()
stats.noHits = 0;
stats.noMisses = 0;
stats.noWrites = 0;
for (int n=0; n<DISK_CACHE_BLOCKS_NUM; ++n) {
for (int n = 0; n < DISK_CACHE_BLOCKS_NUM; ++n) {
blocks[n].free();
}
}
Expand All @@ -117,12 +143,12 @@ DRESULT DiskCache::read(BYTE drv, BYTE * buff, DWORD sector, UINT count)
}

// if block + cache block size is beyond the end of the disk, then read it directly without using cache
if (sector+DISK_CACHE_BLOCK_SECTORS >= sdGetNoSectors()) {
if (sector + DISK_CACHE_BLOCK_SECTORS >= sdGetNoSectors()) {
TRACE_DISK_CACHE("\t\t cache would be beyond end of disk %u (%u)", (uint32_t)sector, sdGetNoSectors());
return __disk_read(drv, buff, sector, count);
}

for (int n=0; n<DISK_CACHE_BLOCKS_NUM; ++n) {
for (int n = 0; n < DISK_CACHE_BLOCKS_NUM; ++n) {
if (blocks[n].read(buff, sector, count)) {
++stats.noHits;
return RES_OK;
Expand All @@ -132,7 +158,7 @@ DRESULT DiskCache::read(BYTE drv, BYTE * buff, DWORD sector, UINT count)
++stats.noMisses;

// find free block
for (int n=0; n<DISK_CACHE_BLOCKS_NUM; ++n) {
for (int n = 0; n < DISK_CACHE_BLOCKS_NUM; ++n) {
if (blocks[n].empty()) {
TRACE_DISK_CACHE("\t\t using free block");
return blocks[n].fill(drv, buff, sector, count);
Expand All @@ -151,7 +177,7 @@ DRESULT DiskCache::read(BYTE drv, BYTE * buff, DWORD sector, UINT count)
DRESULT DiskCache::write(BYTE drv, const BYTE* buff, DWORD sector, UINT count)
{
++stats.noWrites;
for(int n=0; n < DISK_CACHE_BLOCKS_NUM; ++n) {
for(int n = 0; n < DISK_CACHE_BLOCKS_NUM; ++n) {
blocks[n].free(sector, count);
}
return __disk_write(drv, buff, sector, count);
Expand Down
27 changes: 7 additions & 20 deletions radio/src/disk_cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,46 +22,33 @@
#ifndef _DISK_CACHE_H_
#define _DISK_CACHE_H_

#include "diskio.h"
#include "FatFs/diskio.h"

// tunable parameters
#define DISK_CACHE_BLOCKS_NUM 32 // no cache blocks
#define DISK_CACHE_BLOCK_SECTORS 16 // no sectors

#define DISK_CACHE_BLOCK_SIZE (DISK_CACHE_BLOCK_SECTORS * BLOCK_SIZE)

class DiskCacheBlock
{
public:
DiskCacheBlock();
bool read(BYTE* buff, DWORD sector, UINT count);
DRESULT fill(BYTE drv, BYTE* buff, DWORD sector, UINT count);
void free(DWORD sector, UINT count);
void free();
bool empty() const;

private:
uint8_t data[DISK_CACHE_BLOCK_SIZE];
DWORD startSector;
DWORD endSector;
};

struct DiskCacheStats
{
uint32_t noHits;
uint32_t noMisses;
uint32_t noWrites;
};

class DiskCacheBlock;

class DiskCache
{
public:
DiskCache();

void clear();

DRESULT read(BYTE drv, BYTE* buff, DWORD sector, UINT count);
DRESULT write(BYTE drv, const BYTE* buff, DWORD sector, UINT count);

const DiskCacheStats & getStats() const;
int getHitRate() const;
void clear();

private:
DiskCacheStats stats;
Expand Down
2 changes: 1 addition & 1 deletion radio/src/gui/screenshot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ const char * writeScreenshot()
UINT written;
char filename[42]; // /SCREENSHOTS/screen-2013-01-01-123540.bmp

if (IS_SDCARD_FULL()) {
if (sdIsFull()) {
POPUP_WARNING(STR_SDCARD_FULL_EXT);
return STR_SDCARD_FULL_EXT;
}
Expand Down
2 changes: 1 addition & 1 deletion radio/src/logs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ void logsWrite()
{
#endif

bool sdCardFull = IS_SDCARD_FULL();
bool sdCardFull = sdIsFull();

// check if file needs to be opened
if (!g_oLogFile.obj.fs) {
Expand Down
5 changes: 3 additions & 2 deletions radio/src/opentx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ void per10ms()
if (mixWarning & 4) if(((g_tmr10ms&0xFF)==128) || ((g_tmr10ms&0xFF)==136) || ((g_tmr10ms&0xFF)==144)) AUDIO_MIX_WARNING(3);
#endif

#if defined(SDCARD)
#if defined(SDCARD) && defined(PCBTARANIS)
sdPoll10ms();
#endif

Expand Down Expand Up @@ -645,8 +645,9 @@ static void checkRTCBattery()
}

void checkSDfreeStorage() {
if(IS_SDCARD_FULL())
if(sdIsFull()) {
ALERT(STR_SD_CARD, STR_SDCARD_FULL, AU_ERROR);
}
}

#if defined(PCBFRSKY) || defined(PCBFLYSKY)
Expand Down
7 changes: 0 additions & 7 deletions radio/src/opentx.h
Original file line number Diff line number Diff line change
Expand Up @@ -246,9 +246,6 @@ enum RotaryEncoderMode {
#define CASE_JACK_DETECT(x)
#endif

#if defined(DISK_CACHE)
#include "disk_cache.h"
#endif

#include "debug.h"

Expand Down Expand Up @@ -1052,10 +1049,6 @@ inline bool IS_TXBATT_WARNING()
return g_vbat100mV <= g_eeGeneral.vBatWarn;
}

inline bool IS_SDCARD_FULL() {
return sdGetFreeSectors() < ((50 *1024*1024) / BLOCK_SIZE); // 50MB safety margin
}

enum TelemetryViews {
TELEMETRY_CUSTOM_SCREEN_1,
TELEMETRY_CUSTOM_SCREEN_2,
Expand Down
140 changes: 140 additions & 0 deletions radio/src/sdcard.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

#include <stdio.h>
#include <stdint.h>

#include "opentx.h"
#include "diskio.h"

Expand All @@ -30,6 +31,12 @@
#include "libopenui/src/libopenui_file.h"
#endif

#if FF_MAX_SS != FF_MIN_SS
#error "Variable sector size is not supported"
#endif

#define BLOCK_SIZE FF_MAX_SS

#define SDCARD_MIN_FREE_SPACE_MB 50 // Maintain a 50MB free space buffer to prevent crashes

const char * sdCheckAndCreateDirectory(const char * path)
Expand Down Expand Up @@ -451,6 +458,13 @@ uint32_t sdGetFreeSectors()
return nofree * fat->csize;
}

uint32_t sdGetFreeKB()
{
return sdGetFreeSectors() * (1024 / BLOCK_SIZE);
}

bool sdIsFull() { return sdGetFreeKB() < SDCARD_MIN_FREE_SPACE_MB * 1024; }

#else // #if !defined(SIMU) || defined(SIMU_DISKIO)

uint32_t sdGetNoSectors()
Expand All @@ -468,4 +482,130 @@ uint32_t sdGetFreeSectors()
return ((SDCARD_MIN_FREE_SPACE_MB*1024*1024)/BLOCK_SIZE)+1; // SIMU SD card is always above threshold
}

uint32_t sdGetFreeKB() { return SDCARD_MIN_FREE_SPACE_MB * 1024 + 1; }
bool sdIsFull() { return false; }

#endif // #if !defined(SIMU) || defined(SIMU_DISKIO)


static bool _g_FATFS_init = false;
static FATFS g_FATFS_Obj __DMA; // this is in uninitialised section !!!

#if defined(LOG_TELEMETRY)
FIL g_telemetryFile = {};
#endif

#if defined(LOG_BLUETOOTH)
FIL g_bluetoothFile = {};
#endif

#include "audio.h"
#include "sdcard.h"
#include "disk_cache.h"

/*-----------------------------------------------------------------------*/
/* Lock / unlock functions */
/*-----------------------------------------------------------------------*/
static RTOS_MUTEX_HANDLE ioMutex;
uint32_t ioMutexReq = 0, ioMutexRel = 0;
int ff_cre_syncobj (BYTE vol, FF_SYNC_t * mutex)
{
*mutex = ioMutex;
return 1;
}

int ff_req_grant (FF_SYNC_t mutex)
{
ioMutexReq += 1;
RTOS_LOCK_MUTEX(mutex);
return 1;
}

void ff_rel_grant (FF_SYNC_t mutex)
{
ioMutexRel += 1;
RTOS_UNLOCK_MUTEX(mutex);
}

int ff_del_syncobj (FF_SYNC_t mutex)
{
return 1;
}

void sdInit()
{
TRACE("sdInit");
RTOS_CREATE_MUTEX(ioMutex);
sdMount();
}

void sdMount()
{
TRACE("sdMount");

#if defined(DISK_CACHE)
diskCache.clear();
#endif

if (f_mount(&g_FATFS_Obj, "", 1) == FR_OK) {
// call sdGetFreeSectors() now because f_getfree() takes a long time first time it's called
_g_FATFS_init = true;
sdGetFreeSectors();

#if defined(LOG_TELEMETRY)
f_open(&g_telemetryFile, LOGS_PATH "/telemetry.log", FA_OPEN_ALWAYS | FA_WRITE);
if (f_size(&g_telemetryFile) > 0) {
f_lseek(&g_telemetryFile, f_size(&g_telemetryFile)); // append
}
#endif

#if defined(LOG_BLUETOOTH)
f_open(&g_bluetoothFile, LOGS_PATH "/bluetooth.log", FA_OPEN_ALWAYS | FA_WRITE);
if (f_size(&g_bluetoothFile) > 0) {
f_lseek(&g_bluetoothFile, f_size(&g_bluetoothFile)); // append
}
#endif
}
else {
TRACE("f_mount() failed");
}
}

void sdDone()
{
TRACE("sdDone");

if (sdMounted()) {
audioQueue.stopSD();

#if defined(LOG_TELEMETRY)
f_close(&g_telemetryFile);
#endif

#if defined(LOG_BLUETOOTH)
f_close(&g_bluetoothFile);
#endif

f_mount(nullptr, "", 0); // unmount SD
}
}

uint32_t sdMounted()
{
return _g_FATFS_init && (g_FATFS_Obj.fs_type != 0);
}


uint32_t sdIsHC()
{
// defined in diskio
#define CT_BLOCK 0x08
extern uint32_t SD_GetCardType();

return SD_GetCardType() & CT_BLOCK;
}

uint32_t sdGetSpeed()
{
return 330000;
}
Loading