feat(color): Use DMA for SPI flash access (#4478)
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user