Skip to content

Commit

Permalink
Expansion to nand flash driver
Browse files Browse the repository at this point in the history
This expansion helps support higher density devices which have multiple
dies, logical units and planes on top of the standard block and page
structures of standard nand flash ICs.

- Included stm32f723xx targets
- Bug fix (STM32_NAND_USE_NAND1)
- changed map_cmd and map_addr to 8 bits in struct NANDDriver
- Bug fix (dmaStreamAlloc returns dma_stream_t)
- DSB assembly instruction added for fixing issues with M7 processor
- added nand_lld_read_id() function
  • Loading branch information
sabdulqadir committed Jan 2, 2021
1 parent 61baa6b commit 34bb526
Show file tree
Hide file tree
Showing 5 changed files with 373 additions and 79 deletions.
4 changes: 3 additions & 1 deletion os/hal/include/hal_fsmc.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@
*/
#if (defined(STM32F427xx) || defined(STM32F437xx) || \
defined(STM32F429xx) || defined(STM32F439xx) || \
defined(STM32F722xx) || defined(STM32F723xx) || \
defined(STM32F732xx) || defined(STM32F733xx) || \
defined(STM32F745xx) || defined(STM32F746xx) || \
defined(STM32F756xx) || defined(STM32F767xx) || \
defined(STM32F769xx) || defined(STM32F777xx) || \
Expand Down Expand Up @@ -321,7 +323,7 @@ struct FSMCDriver {
#if STM32_NAND_USE_NAND1
FSMC_NAND_TypeDef *nand1;
#endif
#if STM32_NAND_USE_NAND1
#if STM32_NAND_USE_NAND2
FSMC_NAND_TypeDef *nand2;
#endif
#endif
Expand Down
32 changes: 22 additions & 10 deletions os/hal/include/hal_nand.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,22 +108,34 @@ extern "C" {
void nandObjectInit(NANDDriver *nandp);
void nandStart(NANDDriver *nandp, const NANDConfig *config, bitmap_t *bb_map);
void nandStop(NANDDriver *nandp);
uint8_t nandErase(NANDDriver *nandp, uint32_t block);
void nandReadPageWhole(NANDDriver *nandp, uint32_t block, uint32_t page,
uint8_t nandErase(NANDDriver *nandp, uint32_t die, uint32_t logun,
uint32_t plane, uint32_t block);
void nandReadPageWhole(NANDDriver *nandp, uint32_t die, uint32_t logun,
uint32_t plane, uint32_t block, uint32_t page,
void *data, size_t datalen);
void nandReadPageData(NANDDriver *nandp, uint32_t block, uint32_t page,
void nandReadPageData(NANDDriver *nandp, uint32_t die, uint32_t logun,
uint32_t plane, uint32_t block, uint32_t page,
void *data, size_t datalen, uint32_t *ecc);
void nandReadPageSpare(NANDDriver *nandp, uint32_t block, uint32_t page,
void nandReadPageSpare(NANDDriver *nandp, uint32_t die, uint32_t logun,
uint32_t plane, uint32_t block, uint32_t page,
void *spare, size_t sparelen);
uint8_t nandWritePageWhole(NANDDriver *nandp, uint32_t block, uint32_t page,
uint8_t nandWritePageWhole(NANDDriver *nandp, uint32_t die, uint32_t logun,
uint32_t plane, uint32_t block, uint32_t page,
const void *data, size_t datalen);
uint8_t nandWritePageData(NANDDriver *nandp, uint32_t block, uint32_t page,
uint8_t nandWritePageData(NANDDriver *nandp, uint32_t die, uint32_t logun,
uint32_t plane, uint32_t block, uint32_t page,
const void *data, size_t datalen, uint32_t *ecc);
uint8_t nandWritePageSpare(NANDDriver *nandp, uint32_t block, uint32_t page,
uint8_t nandWritePageSpare(NANDDriver *nandp, uint32_t die, uint32_t logun,
uint32_t plane, uint32_t block, uint32_t page,
const void *spare, size_t sparelen);
uint16_t nandReadBadMark(NANDDriver *nandp, uint32_t block, uint32_t page);
void nandMarkBad(NANDDriver *nandp, uint32_t block);
bool nandIsBad(NANDDriver *nandp, uint32_t block);
uint16_t nandReadBadMark(NANDDriver *nandp, uint32_t die, uint32_t logun,
uint32_t plane, uint32_t block, uint32_t page);
void nandMarkBad(NANDDriver *nandp, uint32_t die, uint32_t logun,
uint32_t plane, uint32_t block);
bool nandIsBad(NANDDriver *nandp, uint32_t die, uint32_t logun,
uint32_t plane, uint32_t block, uint32_t page);
bool readIsBlockBad(NANDDriver *nandp, uint32_t die, uint32_t logun,
uint32_t plane, size_t block);
#if NAND_USE_MUTUAL_EXCLUSION
void nandAcquireBus(NANDDriver *nandp);
void nandReleaseBus(NANDDriver *nandp);
Expand Down
52 changes: 43 additions & 9 deletions os/hal/ports/STM32/LLD/FSMCv1/hal_nand_lld.c
Original file line number Diff line number Diff line change
Expand Up @@ -290,11 +290,11 @@ void nand_lld_init(void) {
NANDD1.rxdata = NULL;
NANDD1.datalen = 0;
NANDD1.thread = NULL;
NANDD1.dma = STM32_DMA_STREAM(STM32_NAND_DMA_STREAM);
NANDD1.dma = NULL;
NANDD1.nand = FSMCD1.nand1;
NANDD1.map_data = (void *)FSMC_Bank2_MAP_COMMON_DATA;
NANDD1.map_cmd = (uint16_t *)FSMC_Bank2_MAP_COMMON_CMD;
NANDD1.map_addr = (uint16_t *)FSMC_Bank2_MAP_COMMON_ADDR;
NANDD1.map_cmd = (uint8_t *)FSMC_Bank2_MAP_COMMON_CMD;
NANDD1.map_addr = (uint8_t *)FSMC_Bank2_MAP_COMMON_ADDR;
NANDD1.bb_map = NULL;
#endif /* STM32_NAND_USE_NAND1 */

Expand All @@ -304,11 +304,11 @@ void nand_lld_init(void) {
NANDD2.rxdata = NULL;
NANDD2.datalen = 0;
NANDD2.thread = NULL;
NANDD2.dma = STM32_DMA_STREAM(STM32_NAND_DMA_STREAM);
NANDD2.dma = NULL;
NANDD2.nand = FSMCD1.nand2;
NANDD2.map_data = (void *)FSMC_Bank3_MAP_COMMON_DATA;
NANDD2.map_cmd = (uint16_t *)FSMC_Bank3_MAP_COMMON_CMD;
NANDD2.map_addr = (uint16_t *)FSMC_Bank3_MAP_COMMON_ADDR;
NANDD2.map_cmd = (uint8_t *)FSMC_Bank3_MAP_COMMON_CMD;
NANDD2.map_addr = (uint8_t *)FSMC_Bank3_MAP_COMMON_ADDR;
NANDD2.bb_map = NULL;
#endif /* STM32_NAND_USE_NAND2 */
}
Expand All @@ -322,19 +322,18 @@ void nand_lld_init(void) {
*/
void nand_lld_start(NANDDriver *nandp) {

bool b;
uint32_t dmasize;
uint32_t pcr_bus_width;

if (FSMCD1.state == FSMC_STOP)
fsmcStart(&FSMCD1);

if (nandp->state == NAND_STOP) {
b = dmaStreamAlloc(nandp->dma,
nandp->dma = dmaStreamAlloc(STM32_NAND_DMA_STREAM,
STM32_EMC_FSMC1_IRQ_PRIORITY,
(stm32_dmaisr_t)nand_lld_serve_transfer_end_irq,
(void *)nandp);
osalDbgAssert(!b, "stream already allocated");
osalDbgAssert(nandp->dma != NULL, "stream already allocated");

#if AHB_TRANSACTION_WIDTH == 4
dmasize = STM32_DMA_CR_PSIZE_WORD | STM32_DMA_CR_MSIZE_WORD;
Expand Down Expand Up @@ -409,9 +408,12 @@ void nand_lld_read_data(NANDDriver *nandp, uint16_t *data, size_t datalen,

set_16bit_bus(nandp);
nand_lld_write_cmd(nandp, NAND_CMD_READ0);
__DSB();
nand_lld_write_addr(nandp, addr, addrlen);
__DSB();
osalSysLock();
nand_lld_write_cmd(nandp, NAND_CMD_READ0_CONFIRM);
__DSB();
set_8bit_bus(nandp);

/* Here NAND asserts busy signal and starts transferring from memory
Expand Down Expand Up @@ -459,8 +461,10 @@ uint8_t nand_lld_write_data(NANDDriver *nandp, const uint16_t *data,

set_16bit_bus(nandp);
nand_lld_write_cmd(nandp, NAND_CMD_WRITE);
__DSB();
osalSysLock();
nand_lld_write_addr(nandp, addr, addrlen);
__DSB();
set_8bit_bus(nandp);

/* Now start DMA transfer to NAND buffer and put thread in sleep state.
Expand Down Expand Up @@ -526,9 +530,12 @@ uint8_t nand_lld_erase(NANDDriver *nandp, uint8_t *addr, size_t addrlen) {

set_16bit_bus(nandp);
nand_lld_write_cmd(nandp, NAND_CMD_ERASE);
__DSB();
nand_lld_write_addr(nandp, addr, addrlen);
__DSB();
osalSysLock();
nand_lld_write_cmd(nandp, NAND_CMD_ERASE_CONFIRM);
__DSB();
set_8bit_bus(nandp);

nand_lld_suspend_thread(nandp);
Expand Down Expand Up @@ -580,12 +587,39 @@ uint8_t nand_lld_read_status(NANDDriver *nandp) {

set_16bit_bus(nandp);
nand_lld_write_cmd(nandp, NAND_CMD_STATUS);
__DSB();
set_8bit_bus(nandp);
status = nandp->map_data[0];

return status & 0xFF;
}

/**
* @brief Read ID of the nand flash
*
* @param[in] nandp pointer to the @p NANDDriver object
*
* @return 4 bytes ID of the nandflash
*
* @notapi
*/
uint32_t nand_lld_read_id(NANDDriver *nandp) {

uint8_t addr;
uint32_t data;

//set_16bit_bus(nandp);
nand_lld_write_cmd(nandp, NAND_CMD_READID);
/* Address sent to read ID based on ONFI code */
addr = 0x20;
nand_lld_write_addr(nandp, &addr, 1);
//set_8bit_bus(nandp);
__DSB();
data = *(uint32_t *)(&nandp->map_data[0]);

return data;
}

#endif /* HAL_USE_NAND */

/** @} */
Expand Down
19 changes: 16 additions & 3 deletions os/hal/ports/STM32/LLD/FSMCv1/hal_nand_lld.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,18 @@ typedef void (*nandisrhandler_t)(NANDDriver *nandp);
* @note It could be empty on some architectures.
*/
typedef struct {
/**
* @brief Number of dies in NAND device.
*/
uint32_t dies;
/**
* @brief Number of logical units in NAND device.
*/
uint32_t loguns;
/**
* @brief Number of planes in NAND device.
*/
uint32_t planes;
/**
* @brief Number of erase blocks in NAND device.
*/
Expand Down Expand Up @@ -232,15 +244,15 @@ struct NANDDriver {
/**
* @brief Memory mapping for data.
*/
uint16_t *map_data;
uint8_t *map_data;
/**
* @brief Memory mapping for commands.
*/
uint16_t *map_cmd;
uint8_t *map_cmd;
/**
* @brief Memory mapping for addresses.
*/
uint16_t *map_addr;
uint8_t *map_addr;
/**
* @brief Pointer to bad block map.
* @details One bit per block. All memory allocation is user's responsibility.
Expand Down Expand Up @@ -279,6 +291,7 @@ extern "C" {
size_t datalen, uint8_t *addr, size_t addrlen, uint32_t *ecc);
uint8_t nand_lld_read_status(NANDDriver *nandp);
void nand_lld_reset(NANDDriver *nandp);
uint32_t nand_lld_read_id(NANDDriver *nandp);
#ifdef __cplusplus
}
#endif
Expand Down
Loading

0 comments on commit 34bb526

Please sign in to comment.