Skip to content

Commit

Permalink
refactor: SD card SPI HAL (#3957)
Browse files Browse the repository at this point in the history
* refactor: SD card SPI driver

* Removed SPI and DMA StdPeriph drivers

* Allow for disabling SPI DMA support

* Disable SPI sdcard CRC support

* Fix 2MHz timer on NV14

* Shared VS1053b driver

* Fix: SPI2 uses PCLK1

* feat: new generic diskio API

* More generic SD_CARD_PRESENT()

* Fixes

* Flush incoming block on token mismatch

* Scratch buffer test

* Incredible hack to re-sync sd card

* fix: SDIO driver
  • Loading branch information
raphaelcoeffic authored Sep 23, 2023
1 parent 870fe7e commit 87df8a4
Show file tree
Hide file tree
Showing 61 changed files with 2,676 additions and 2,607 deletions.
9 changes: 1 addition & 8 deletions radio/src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -84,12 +84,6 @@ set(GVARS_VARIANT 1)
set(FRSKY_VARIANT 2)
set(3POS_VARIANT 4)

set(FATFS_SRC
${FATFS_DIR}/ff.c
${FATFS_DIR}/ffunicode.c
${FATFS_DIR}/fattime.c
)

if(PCB STREQUAL X12S OR PCB STREQUAL X10)
include(targets/horus/CMakeLists.txt)
elseif(PCB STREQUAL NV14)
Expand Down Expand Up @@ -252,9 +246,8 @@ endif()

if(SDCARD)
add_definitions(-DSDCARD)
include_directories(${FATFS_DIR} ${FATFS_DIR}/option)
set(SRC ${SRC} sdcard.cpp rtc.cpp logs.cpp thirdparty/libopenui/src/libopenui_file.cpp)
set(FIRMWARE_SRC ${FIRMWARE_SRC} ${FATFS_SRC})
set(FIRMWARE_SRC ${FIRMWARE_SRC})
endif()

if(SHUTDOWN_CONFIRMATION)
Expand Down
18 changes: 11 additions & 7 deletions radio/src/cli.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
#include <FreeRTOS/include/stream_buffer.h>

#include "opentx.h"
#include "diskio.h"
#include "timers_driver.h"
#include "watchdog_driver.h"

Expand All @@ -33,6 +32,8 @@

#include "hal/adc_driver.h"
#include "hal/module_port.h"
#include "hal/fatfs_diskio.h"
#include "hal/storage.h"

#include "tasks.h"
#include "tasks/mixer_task.h"
Expand Down Expand Up @@ -347,8 +348,9 @@ int cliReadSD(const char ** argv)
uint32_t bytesRead = numberOfSectors * 512;
tmr10ms_t start = get_tmr10ms();

auto drv = storageGetDefaultDriver();
while (numberOfSectors > 0) {
DRESULT res = __disk_read(0, buffer, startSector, bufferSectors);
DRESULT res = drv->read(0, buffer, startSector, bufferSectors);
if (res != RES_OK) {
cliSerialPrint("disk_read error: %d, sector: %d(%d)", res, startSector, numberOfSectors);
}
Expand Down Expand Up @@ -385,10 +387,11 @@ int cliReadSD(const char ** argv)
int cliTestSD(const char ** argv)
{
// Do the read test on the SD card and report back the result
auto drv = storageGetDefaultDriver();

// get sector count
uint32_t sectorCount;
if (disk_ioctl(0, GET_SECTOR_COUNT, &sectorCount) != RES_OK) {
if (drv->ioctl(0, GET_SECTOR_COUNT, &sectorCount) != RES_OK) {
cliSerialPrint("Error: can't read sector count");
return 0;
}
Expand All @@ -401,8 +404,9 @@ int cliTestSD(const char ** argv)
cliSerialPrint("Not enough memory");
return 0;
}

for (uint32_t s = sectorCount - 16; s<sectorCount; ++s) {
DRESULT res = __disk_read(0, buffer, s, 1);
DRESULT res = drv->read(0, buffer, s, 1);
if (res != RES_OK) {
cliSerialPrint("sector %d read FAILED, err: %d", s, res);
}
Expand All @@ -421,8 +425,8 @@ int cliTestSD(const char ** argv)
}

cliSerialPrint("Starting multiple sector read test, reading two sectors at the time");
for (uint32_t s = sectorCount - 16; s<sectorCount; s+=2) {
DRESULT res = __disk_read(0, buffer, s, 2);
for (uint32_t s = sectorCount - 16; s < sectorCount; s += 2) {
DRESULT res = drv->read(0, buffer, s, 2);
if (res != RES_OK) {
cliSerialPrint("sector %d-%d read FAILED, err: %d", s, s+1, res);
}
Expand All @@ -441,7 +445,7 @@ int cliTestSD(const char ** argv)
}

cliSerialPrint("Starting multiple sector read test, reading 16 sectors at the time");
DRESULT res = __disk_read(0, buffer, sectorCount-16, 16);
DRESULT res = drv->read(0, buffer, sectorCount - 16, 16);
if (res != RES_OK) {
cliSerialPrint("sector %d-%d read FAILED, err: %d", sectorCount-16, sectorCount-1, res);
}
Expand Down
4 changes: 2 additions & 2 deletions radio/src/crc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,8 @@ uint16_t crc16(uint8_t index, const uint8_t * buf, uint32_t len, uint16_t start)
{
uint16_t crc = start;
const unsigned short * tab = crc16tab[index];
for (uint32_t i=0; i<len; i++) {
crc = (crc<<8) ^ tab[((crc>>8) ^ *buf++) & 0x00FF];
for (uint32_t i = 0; i < len; i++) {
crc = (crc << 8) ^ tab[((crc >> 8) ^ *buf++) & 0x00FF];
}
return crc;
}
Expand Down
69 changes: 37 additions & 32 deletions radio/src/disk_cache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,6 @@

#include <string.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
#include "debug.h"
#define TRACE_DISK_CACHE(...) TRACE(__VA_ARGS__)
Expand All @@ -47,15 +42,16 @@ DiskCache diskCache;

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

private:
private:
uint8_t data[DISK_CACHE_BLOCK_SIZE];
DWORD startSector;
DWORD endSector;
Expand All @@ -77,16 +73,17 @@ bool DiskCacheBlock::read(BYTE * buff, DWORD sector, UINT count)
return false;
}

DRESULT DiskCacheBlock::fill(BYTE drv, BYTE * buff, DWORD sector, UINT count)
DRESULT DiskCacheBlock::fill(const diskio_driver_t* drv, BYTE lun, BYTE * buff,
DWORD sector, UINT count)
{
DRESULT res = __disk_read(drv, data, sector, DISK_CACHE_BLOCK_SECTORS);
DRESULT res = drv->read(lun, data, sector, DISK_CACHE_BLOCK_SECTORS);
if (res != RES_OK) {
return res;
}
startSector = sector;
endSector = sector + DISK_CACHE_BLOCK_SECTORS;
memcpy(buff, data, count * BLOCK_SIZE);
TRACE_DISK_CACHE("\tcache %p FILLED from read(%u, %u)", this, (uint32_t)sector, (uint32_t)count);
TRACE_DISK_CACHE("cache %p FILLED from read(%u, %u)", this, (uint32_t)sector, (uint32_t)count);
return RES_OK;
}

Expand All @@ -108,13 +105,17 @@ bool DiskCacheBlock::empty() const
return (endSector == 0);
}

DiskCache::DiskCache():
lastBlock(0)
DiskCache::DiskCache() : lastBlock(0), blocks(nullptr), diskDrv(nullptr)
{
stats.noHits = 0;
stats.noMisses = 0;
stats.noWrites = 0;
}

void DiskCache::initialize(const diskio_driver_t* drv)
{
blocks = new DiskCacheBlock[DISK_CACHE_BLOCKS_NUM];
diskDrv = drv;
}

void DiskCache::clear()
Expand All @@ -128,24 +129,28 @@ void DiskCache::clear()
}
}

DRESULT DiskCache::read(BYTE drv, BYTE * buff, DWORD sector, UINT count)
uint32_t DiskCache::getSectors(uint8_t lun)
{
// TODO: check if not caching first sectors would improve anything
// if (sector < 1000) {
// ++stats.noMisses;
// return __disk_read(drv, buff, sector, count);
// }
if (sectors == 0) {
diskDrv->ioctl(lun, GET_SECTOR_COUNT, &sectors);
}
return sectors;
}

DRESULT DiskCache::read(BYTE lun, BYTE * buff, DWORD sector, UINT count)
{
// if read is bigger than cache block, then read it directly without using cache
if (count > DISK_CACHE_BLOCK_SECTORS) {
TRACE_DISK_CACHE("\t\t big read(%u, %u)", (uint32_t)sector, (uint32_t)count);
return __disk_read(drv, buff, sector, count);
TRACE_DISK_CACHE("big read(%u, %u)", (uint32_t)sector, (uint32_t)count);
return diskDrv->read(lun, buff, sector, 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()) {
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);
// 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 >= getSectors(lun)) {
TRACE_DISK_CACHE("cache would be beyond end of disk %u (%u)",
(uint32_t)sector, getSectors(lun));
return diskDrv->read(lun, buff, sector, count);
}

for (int n = 0; n < DISK_CACHE_BLOCKS_NUM; ++n) {
Expand All @@ -161,7 +166,7 @@ DRESULT DiskCache::read(BYTE drv, BYTE * buff, DWORD sector, UINT count)
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);
return blocks[n].fill(diskDrv, lun, buff, sector, count);
}
}

Expand All @@ -171,16 +176,16 @@ DRESULT DiskCache::read(BYTE drv, BYTE * buff, DWORD sector, UINT count)
lastBlock = 0;
}

return blocks[lastBlock].fill(drv, buff, sector, count);
return blocks[lastBlock].fill(diskDrv, lun, buff, sector, count);
}

DRESULT DiskCache::write(BYTE drv, const BYTE* buff, DWORD sector, UINT count)
DRESULT DiskCache::write(BYTE lun, const BYTE* buff, DWORD sector, UINT count)
{
++stats.noWrites;
for(int n = 0; n < DISK_CACHE_BLOCKS_NUM; ++n) {
blocks[n].free(sector, count);
}
return __disk_write(drv, buff, sector, count);
return diskDrv->write(lun, buff, sector, count);
}

const DiskCacheStats & DiskCache::getStats() const
Expand All @@ -195,13 +200,13 @@ int DiskCache::getHitRate() const
return (stats.noHits * 1000) / all;
}

DRESULT disk_read(BYTE drv, BYTE * buff, DWORD sector, UINT count)
DRESULT disk_cache_read(BYTE drv, BYTE * buff, DWORD sector, UINT count)
{
return diskCache.read(drv, buff, sector, count);
}


DRESULT disk_write(BYTE drv, const BYTE * buff, DWORD sector, UINT count)
DRESULT disk_cache_write(BYTE drv, const BYTE * buff, DWORD sector, UINT count)
{
return diskCache.write(drv, buff, sector, count);
}

37 changes: 22 additions & 15 deletions radio/src/disk_cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,9 @@
* GNU General Public License for more details.
*/

#ifndef _DISK_CACHE_H_
#define _DISK_CACHE_H_
#pragma once

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

// tunable parameters
#define DISK_CACHE_BLOCKS_NUM 32 // no cache blocks
Expand All @@ -39,23 +38,31 @@ class DiskCacheBlock;

class DiskCache
{
public:
DiskCache();
public:
DiskCache();

void clear();
void initialize(const diskio_driver_t* drv);
void clear();

DRESULT read(BYTE drv, BYTE* buff, DWORD sector, UINT count);
DRESULT write(BYTE drv, const BYTE* buff, DWORD sector, UINT count);
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;
const DiskCacheStats& getStats() const;
int getHitRate() const;

private:
DiskCacheStats stats;
uint32_t lastBlock;
DiskCacheBlock * blocks;
private:
DiskCacheStats stats;
uint32_t lastBlock;
DiskCacheBlock* blocks;
const diskio_driver_t* diskDrv;
uint32_t sectors;

uint32_t getSectors(uint8_t lun);
};

extern DiskCache diskCache;

#endif // _DISK_CACHE_H_
DRESULT disk_cache_read(BYTE drv, BYTE* buff, DWORD sector, UINT count);
DRESULT disk_cache_write(BYTE drv, const BYTE* buff, DWORD sector, UINT count);


2 changes: 1 addition & 1 deletion radio/src/gui/colorlcd/radio_sdmanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ class FileNameEditWindow : public Page
};

RadioSdManagerPage::RadioSdManagerPage() :
PageTab(SD_IS_HC() ? STR_SDHC_CARD : STR_SD_CARD, ICON_RADIO_SD_MANAGER)
PageTab(STR_SD_CARD, ICON_RADIO_SD_MANAGER)
{
}

Expand Down
28 changes: 9 additions & 19 deletions radio/src/gui/common/stdlcd/radio_sdmanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include "io/multi_firmware_update.h"
#include "io/bootloader_flash.h"
#include "libopenui/src/libopenui_file.h"
#include "hal/storage.h"

#define NODE_TYPE(fname) fname[SD_SCREEN_FILE_LENGTH+1]
#define IS_DIRECTORY(fname) ((bool)(!NODE_TYPE(fname)))
Expand All @@ -39,26 +40,15 @@ void menuRadioSdManagerInfo(event_t event)
{
SIMPLE_SUBMENU(STR_SD_INFO_TITLE, 1);

lcdDrawTextAlignedLeft(2*FH, STR_SD_TYPE);
lcdDrawText(10*FW, 2*FH, SD_IS_HC() ? STR_SDHC_CARD : STR_SD_CARD);

lcdDrawTextAlignedLeft(3*FH, STR_SD_SIZE);
lcdDrawNumber(10*FW, 3*FH, sdGetSize(), LEFT);
lcdDrawTextAlignedLeft(2*FH, STR_SD_SIZE);
lcdDrawNumber(10*FW, 2*FH, sdGetSize(), LEFT);
lcdDrawChar(lcdLastRightPos, 3*FH, 'M');

lcdDrawTextAlignedLeft(4*FH, STR_SD_SECTORS);
#if defined(SD_GET_FREE_BLOCKNR)
lcdDrawNumber(10*FW, 4*FH, SD_GET_FREE_BLOCKNR()/1000, LEFT);
lcdDrawChar(lcdLastRightPos, 4*FH, '/');
lcdDrawNumber(lcdLastRightPos+FW, 4*FH, sdGetNoSectors()/1000, LEFT);
#else
lcdDrawNumber(10*FW, 4*FH, sdGetNoSectors()/1000, LEFT);
#endif
lcdDrawChar(lcdLastRightPos, 4*FH, 'k');

lcdDrawTextAlignedLeft(5*FH, STR_SD_SPEED);
lcdDrawNumber(10*FW, 5*FH, SD_GET_SPEED()/1000, LEFT);
lcdDrawText(lcdLastRightPos, 5*FH, "kb/s");
lcdDrawTextAlignedLeft(3*FH, STR_SD_SECTORS);
lcdDrawNumber(10*FW, 3*FH, sdGetFreeSectors()/1000, LEFT);
lcdDrawChar(lcdLastRightPos, 3*FH, '/');
lcdDrawNumber(lcdLastRightPos+FW, 3*FH, sdGetNoSectors()/1000, LEFT);
lcdDrawChar(lcdLastRightPos, 3*FH, 'k');
}

inline bool isFilenameGreater(bool isfile, const char * fn, const char * line)
Expand Down Expand Up @@ -298,7 +288,7 @@ void menuRadioSdManager(event_t _event)

event_t event = (EVT_KEY_MASK(_event) == KEY_ENTER ? 0 : _event);
uint8_t old_editMode = s_editMode;
SIMPLE_MENU(SD_IS_HC() ? STR_SDHC_CARD : STR_SD_CARD, menuTabGeneral, MENU_RADIO_SD_MANAGER, HEADER_LINE + reusableBuffer.sdManager.count);
SIMPLE_MENU(STR_SD_CARD, menuTabGeneral, MENU_RADIO_SD_MANAGER, HEADER_LINE + reusableBuffer.sdManager.count);

switch (_event) {
case EVT_ENTRY:
Expand Down
Loading

0 comments on commit 87df8a4

Please sign in to comment.