feat(color): Use DMA for SPI flash access (#4478)

This commit is contained in:
richardclli
2024-01-21 12:01:24 +10:00
committed by GitHub
parent b0824f902c
commit 4c2ea7a60a
13 changed files with 119 additions and 24 deletions
+43 -3
View File
@@ -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
@@ -541,6 +545,42 @@ 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;
@@ -548,7 +588,7 @@ static bool programPage(FrFTL* ftl, PageBuffer* buffer, bool doErase)
if (doErase && getPhysicalPageState(ftl, buffer->physicalPageNo) != ERASED) {
// Do erase on the fly
if (!cb->flashErase(pageAddr)) {
if (!quickErase(ftl, pageAddr)) {
return false;
}
}
@@ -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);
@@ -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);
+1
View File
@@ -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;
@@ -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
@@ -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
@@ -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;
@@ -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);
@@ -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)
{
@@ -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,
@@ -23,4 +23,6 @@
#include "hal/fatfs_diskio.h"
void spiFlashDiskEraseAll();
extern const diskio_driver_t spi_flash_diskio_driver;
@@ -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;
@@ -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;
@@ -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;
@@ -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();
@@ -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);
@@ -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);
@@ -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) {
+8
View File
@@ -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
@@ -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
+4
View File
@@ -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)
+4 -8
View File
@@ -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