Skip to content

Commit

Permalink
feat(color): Use DMA for SPI flash access (#4478)
Browse files Browse the repository at this point in the history
  • Loading branch information
richardclli authored Jan 21, 2024
1 parent b0824f9 commit 4c2ea7a
Show file tree
Hide file tree
Showing 13 changed files with 119 additions and 24 deletions.
46 changes: 43 additions & 3 deletions radio/src/drivers/frftl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@

#define SECTOR_SIZE 512
#define PAGE_SIZE 4096
#define BLOCK_SIZE 32768
#define BLOCK_MASK (BLOCK_SIZE - 1)
#define PAGES_PER_BLOCK (BLOCK_SIZE / PAGE_SIZE)
#define USE_BLOCK_ERASE_THRESHOLD 4
#define SECTORS_PER_PAGE (PAGE_SIZE / SECTOR_SIZE)
#define TT_PAGE_MAGIC 0xEF87364A
#define TT_RECORDS_PER_PAGE 1024
Expand Down Expand Up @@ -541,14 +545,50 @@ static uint16_t allocatePhysicalPage(FrFTL* ftl)
return physicalPageNo;
}

static bool quickErase(FrFTL* ftl, uint32_t addr)
{

const FrFTLOps* cb = ftl->callbacks;
if ((addr & BLOCK_MASK) == 0) {
// Block aligned

uint16_t ppn = addr / PAGE_SIZE;
uint8_t count = 0;
bool hasUsed = false;

// Check state of the whole jumbo page
for (uint8_t i = 0; i < PAGES_PER_BLOCK; i++) {
PhysicalPageState state = getPhysicalPageState(ftl, ppn + i);
if (state == UNKNOWN || state == ERASE_REQUIRED) {
count++;
}
if (state == USED) {
hasUsed = true;
break; // Cannot use block erase
}
}

if (!hasUsed && count >= USE_BLOCK_ERASE_THRESHOLD) {
bool ret = cb->flashBlockErase(addr);
if (ret) {
for (uint8_t i = 0; i < PAGES_PER_BLOCK; i++) {
setPhysicalPageState(ftl, ppn + i, ERASED);
}
}
return ret;
}
}
return cb->flashErase(addr);
}

static bool programPage(FrFTL* ftl, PageBuffer* buffer, bool doErase)
{
const FrFTLOps* cb = ftl->callbacks;
uint32_t pageAddr = buffer->physicalPageNo * PAGE_SIZE;

if (doErase && getPhysicalPageState(ftl, buffer->physicalPageNo) != ERASED) {
// Do erase on the fly
if (!cb->flashErase(pageAddr)) {
if (!quickErase(ftl, pageAddr)) {
return false;
}
}
Expand Down Expand Up @@ -991,7 +1031,7 @@ void createFTL(FrFTL* ftl)
const FrFTLOps* cb = ftl->callbacks;
do {
if (getPhysicalPageState(ftl, i) != ERASED) {
cb->flashErase(addr);
quickErase(ftl, addr);
}
cb->flashProgram(addr, (const uint8_t*)&tt, PAGE_SIZE);
setPhysicalPageState(ftl, i, USED);
Expand All @@ -1010,7 +1050,7 @@ void createFTL(FrFTL* ftl)
} while(++i < ftl->ttPageCount);

if (getPhysicalPageState(ftl, 0) != ERASED) {
cb->flashErase(0);
quickErase(ftl, 0);
}

cb->flashProgram(0, (const uint8_t*)&tt, PAGE_SIZE);
Expand Down
1 change: 1 addition & 0 deletions radio/src/drivers/frftl.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ typedef struct {
bool (*flashRead)(uint32_t addr, uint8_t* buf, uint32_t len);
bool (*flashProgram)(uint32_t addr, const uint8_t* buf, uint32_t len);
bool (*flashErase)(uint32_t addr);
bool (*flashBlockErase)(uint32_t addr);
bool (*isFlashErased)(uint32_t addr);
} FrFTLOps;

Expand Down
6 changes: 4 additions & 2 deletions radio/src/targets/common/arm/stm32/bootloader/boot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@
#endif

#if defined(SPI_FLASH)
#include "spi_flash.h"
#include "diskio_spi_flash.h"
#define SEL_CLEAR_FLASH_STORAGE_MENU_LEN 2
#endif

Expand Down Expand Up @@ -537,7 +537,9 @@ int bootloaderMain()
lcdRefresh();
if(event != EVT_KEY_BREAK(KEY_ENTER))
continue;
flashSpiEraseAll();
sdDone();
spiFlashDiskEraseAll();
sdInit();
vpos = 0;
state = ST_START;
#endif
Expand Down
4 changes: 4 additions & 0 deletions radio/src/targets/common/arm/stm32/diskio_spi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ static const stm32_spi_t _sd_spi_hw = {
.DMA_Channel = SD_SPI_DMA_CHANNEL,
.txDMA_Stream = SD_SPI_DMA_TX_STREAM,
.rxDMA_Stream = SD_SPI_DMA_RX_STREAM,
.DMA_FIFOMode = LL_DMA_FIFOMODE_ENABLE,
.DMA_FIFOThreshold = LL_DMA_FIFOTHRESHOLD_1_2,
.DMA_MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_HALFWORD,
.DMA_MemBurst = LL_DMA_MBURST_INC4,
};

static uint32_t _sdcard_sectors;
Expand Down
20 changes: 19 additions & 1 deletion radio/src/targets/common/arm/stm32/diskio_spi_flash.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,12 @@ static bool flashErase(uint32_t addr)
return true;
}

static bool flashBlockErase(uint32_t addr)
{
flashSpiBlockErase(addr);
return true;
}

static bool isFlashErased(uint32_t addr)
{
return flashSpiIsErased(addr);
Expand All @@ -73,9 +79,10 @@ static const FrFTLOps _frftl_cb = {
.flashRead = flashRead,
.flashProgram = flashWrite,
.flashErase = flashErase,
.flashBlockErase = flashBlockErase,
.isFlashErased = isFlashErased,
};
#endif
#endif // USE_FLASH_FTL

static DSTATUS spi_flash_initialize(BYTE lun)
{
Expand Down Expand Up @@ -188,6 +195,17 @@ static DRESULT spi_flash_ioctl(BYTE lun, BYTE ctrl, void *buff)
return res;
}

void spiFlashDiskEraseAll()
{
#if defined(USE_FLASH_FTL)
if (frftlInitDone) {
ftlDeInit(&_frftl);
frftlInitDone = false;
}
#endif
flashSpiEraseAll();
}

const diskio_driver_t spi_flash_diskio_driver = {
.initialize = spi_flash_initialize,
.status = spi_flash_status,
Expand Down
2 changes: 2 additions & 0 deletions radio/src/targets/common/arm/stm32/diskio_spi_flash.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,6 @@

#include "hal/fatfs_diskio.h"

void spiFlashDiskEraseAll();

extern const diskio_driver_t spi_flash_diskio_driver;
28 changes: 21 additions & 7 deletions radio/src/targets/common/arm/stm32/spi_flash.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,14 @@ const stm32_spi_t _flash_spi = {
.SPI_Pins = FLASH_SPI_SCK_GPIO_PIN | FLASH_SPI_MISO_GPIO_PIN | FLASH_SPI_MOSI_GPIO_PIN,
.CS_GPIOx = FLASH_SPI_CS_GPIO,
.CS_Pin = FLASH_SPI_CS_GPIO_PIN,
.DMA = nullptr,
.DMA_Channel = 0,
.txDMA_Stream = 0,
.rxDMA_Stream = 0,
.DMA = FLASH_SPI_DMA,
.DMA_Channel = FLASH_SPI_DMA_CHANNEL,
.txDMA_Stream = FLASH_SPI_DMA_TX_STREAM,
.rxDMA_Stream = FLASH_SPI_DMA_RX_STREAM,
.DMA_FIFOMode = LL_DMA_FIFOMODE_ENABLE,
.DMA_FIFOThreshold = LL_DMA_FIFOTHRESHOLD_1_2,
.DMA_MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_HALFWORD,
.DMA_MemBurst = LL_DMA_MBURST_INC4,
};

static SpiFlashDescriptor _flashDescriptor;
Expand All @@ -95,11 +99,21 @@ static inline uint8_t flash_read_byte()
return flash_rw_byte(0xFF);
}

static void flash_rw_bytes(const uint8_t* tx, uint8_t* rx, uint16_t count)
static inline void flash_rw_bytes(const uint8_t* tx, uint8_t* rx, uint16_t count)
{
stm32_spi_transfer_bytes(&_flash_spi, tx, rx, count);
}

static inline void flash_dma_read_bytes(uint8_t* buffer, uint16_t count)
{
stm32_spi_dma_receive_bytes(&_flash_spi, buffer, count);
}

static inline void flash_dma_write_bytes(const uint8_t* buffer, uint16_t count)
{
stm32_spi_dma_transmit_bytes(&_flash_spi, buffer, count);
}

static inline void flash_put_cmd_addr(uint8_t cmd, uint32_t addr)
{
addr |= cmd << 24;
Expand Down Expand Up @@ -293,7 +307,7 @@ uint32_t flashSpiRead(uint32_t address, uint8_t* data, uint32_t size)
} else {
flash_put_cmd_addr(FLASH_CMD_READ, address);
}
flash_rw_bytes(0, data, size);
flash_dma_read_bytes(data, size);

flash_unselect();
return size;
Expand All @@ -317,7 +331,7 @@ uint32_t flashSpiWrite(uint32_t address, const uint8_t* data, uint32_t size)
} else {
flash_put_cmd_addr(FLASH_CMD_WRITE, address);
}
flash_rw_bytes(data, 0, size);
flash_dma_write_bytes(data, size);
flash_unselect();

flash_wait_for_not_busy();
Expand Down
6 changes: 4 additions & 2 deletions radio/src/targets/common/arm/stm32/stm32_spi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -151,8 +151,10 @@ static void _config_dma_streams(const stm32_spi_t* spi)
dmaInit.PeriphOrM2MSrcAddress = (uint32_t)&spi->SPIx->DR;
dmaInit.MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT;
dmaInit.Priority = LL_DMA_PRIORITY_VERYHIGH;
dmaInit.FIFOMode = LL_DMA_FIFOMODE_ENABLE;
dmaInit.FIFOThreshold = LL_DMA_FIFOTHRESHOLD_FULL;
dmaInit.FIFOMode = spi->DMA_FIFOMode;
dmaInit.FIFOThreshold = spi->DMA_FIFOThreshold;
dmaInit.MemoryOrM2MDstDataSize = spi->DMA_MemoryOrM2MDstDataSize;
dmaInit.MemBurst = spi->DMA_MemBurst;

dmaInit.Direction = LL_DMA_DIRECTION_PERIPH_TO_MEMORY;
LL_DMA_Init(spi->DMA, spi->rxDMA_Stream, &dmaInit);
Expand Down
4 changes: 4 additions & 0 deletions radio/src/targets/common/arm/stm32/stm32_spi.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ struct stm32_spi_t {
uint32_t DMA_Channel;
uint32_t txDMA_Stream;
uint32_t rxDMA_Stream;
uint32_t DMA_FIFOMode;
uint32_t DMA_FIFOThreshold;
uint32_t DMA_MemoryOrM2MDstDataSize;
uint32_t DMA_MemBurst;
};

void stm32_spi_enable_clock(SPI_TypeDef *SPIx);
Expand Down
2 changes: 1 addition & 1 deletion radio/src/targets/common/arm/stm32/usbd_storage_msd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ int8_t STORAGE_Read_FS (uint8_t lun,
*/
int8_t STORAGE_Write_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
{
WATCHDOG_SUSPEND(100/*1s*/);
WATCHDOG_SUSPEND(500/*5s*/);

#if defined(FWDRIVE)
if (lun == STORAGE_EEPROM_LUN) {
Expand Down
8 changes: 8 additions & 0 deletions radio/src/targets/horus/hal.h
Original file line number Diff line number Diff line change
Expand Up @@ -649,6 +649,10 @@
#define FLASH_SPI_SCK_GPIO_PIN LL_GPIO_PIN_5 // PA.05
#define FLASH_SPI_MISO_GPIO_PIN LL_GPIO_PIN_6 // PA.06
#define FLASH_SPI_MOSI_GPIO_PIN LL_GPIO_PIN_7 // PA.07
#define FLASH_SPI_DMA DMA2
#define FLASH_SPI_DMA_CHANNEL LL_DMA_CHANNEL_3
#define FLASH_SPI_DMA_TX_STREAM LL_DMA_STREAM_3
#define FLASH_SPI_DMA_RX_STREAM LL_DMA_STREAM_5
// SPI1_TX: DMA2 Stream 3 (SDIO) / Stream 5 (Ext. module timer)
// #define FLASH_SPI_TX_DMA_CHANNEL DMA_Channel_3
// #define FLASH_SPI_TX_DMA_STREAM DMA2_Stream3
Expand All @@ -671,6 +675,10 @@
#define FLASH_SPI_SCK_GPIO_PIN LL_GPIO_PIN_1 // PI.01
#define FLASH_SPI_MISO_GPIO_PIN LL_GPIO_PIN_2 // PI.02
#define FLASH_SPI_MOSI_GPIO_PIN LL_GPIO_PIN_3 // PI.03
#define FLASH_SPI_DMA DMA1
#define FLASH_SPI_DMA_CHANNEL LL_DMA_CHANNEL_0
#define FLASH_SPI_DMA_TX_STREAM LL_DMA_STREAM_4
#define FLASH_SPI_DMA_RX_STREAM LL_DMA_STREAM_3
// #define FLASH_SPI_TX_DMA_CHANNEL DMA_Channel_0
// #define FLASH_SPI_TX_DMA_STREAM DMA1_Stream4
// #define FLASH_SPI_TX_DMA_IRQn DMA1_Stream4_IRQn
Expand Down
4 changes: 4 additions & 0 deletions radio/src/targets/nv14/hal.h
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,10 @@
#define FLASH_SPI_SCK_GPIO_PIN LL_GPIO_PIN_13 // PG.13
#define FLASH_SPI_MISO_GPIO_PIN LL_GPIO_PIN_12 // PG.12
#define FLASH_SPI_MOSI_GPIO_PIN LL_GPIO_PIN_14 // PG.14
#define FLASH_SPI_DMA DMA2
#define FLASH_SPI_DMA_CHANNEL LL_DMA_CHANNEL_1
#define FLASH_SPI_DMA_TX_STREAM LL_DMA_STREAM_5
#define FLASH_SPI_DMA_RX_STREAM LL_DMA_STREAM_6

// SDRAM
#define SDRAM_RCC_AHB1Periph (RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_GPIOE | RCC_AHB1Periph_GPIOF | RCC_AHB1Periph_GPIOG | RCC_AHB1Periph_GPIOH)
Expand Down
12 changes: 4 additions & 8 deletions radio/src/targets/pl18/hal.h
Original file line number Diff line number Diff line change
Expand Up @@ -465,14 +465,10 @@
#define FLASH_SPI_SCK_GPIO_PIN LL_GPIO_PIN_13 // PG.13
#define FLASH_SPI_MISO_GPIO_PIN LL_GPIO_PIN_12 // PG.12
#define FLASH_SPI_MOSI_GPIO_PIN LL_GPIO_PIN_14 // PG.14
// #define FLASH_SPI_DMA DMA2
// #define FLASH_SPI_DMA_CHANNEL LL_DMA_CHANNEL_1
// #define FLASH_SPI_DMA_TX_STREAM LL_DMA_STREAM_5
// #define FLASH_SPI_DMA_TX_IRQn DMA2_Stream5_IRQn
// #define FLASH_SPI_DMA_TX_IRQHandler DMA2_Stream5_IRQHandler
// #define FLASH_SPI_DMA_RX_STREAM LL_DMA_STREAM_6
// #define FLASH_SPI_DMA_RX_IRQn DMA2_Stream6_IRQn
// #define FLASH_SPI_DMA_RX_IRQHandler DMA2_Stream6_IRQHandler
#define FLASH_SPI_DMA DMA2
#define FLASH_SPI_DMA_CHANNEL LL_DMA_CHANNEL_1
#define FLASH_SPI_DMA_TX_STREAM LL_DMA_STREAM_5
#define FLASH_SPI_DMA_RX_STREAM LL_DMA_STREAM_6
#define STORAGE_USE_SPI_FLASH

// SDRAM
Expand Down

0 comments on commit 4c2ea7a

Please sign in to comment.