STM32WB + QSPI for nand flash
- April 13, 2023
- 8 replies
- 10361 views
My development environment is stm32cubeMX and IAR.
First of all, the configuration I programmed is like this.
1. Init (write Status Register WP-E set 1)
2. Block Erase (to the address where i will store the data)
3. Write data to buffer
4. Program Execute
5. Load data (load data in physical memory page to data buffer)
6. Read data
If Delay is not used between 2 and 5, HAL_QSPI_Command_IT function is passed to Error_Handler.
I want to make it work without this delay.
If a delay is inserted or executed line by line, it operates normally without going over to Error_Handler.
Are QSPI commands not usable consecutively?
void Flash_Init(void)
{
sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE;
sCommand.AddressSize = QSPI_ADDRESS_24_BITS;
sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
sCommand.DdrMode = QSPI_DDR_MODE_DISABLE;
sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
Flash_Write_Status_Register(0x02); //set WP-E 1
}
void Flash_Erase(uint32_t address)
{
QSPI_AutoPollingMemReady(&hqspi);
QSPI_WriteEnable(&hqspi);
sCommand.Instruction = SECTOR_ERASE_CMD;
sCommand.AddressMode = QSPI_ADDRESS_1_LINE;
sCommand.AddressSize = QSPI_ADDRESS_24_BITS;
sCommand.Address = address;
sCommand.DataMode = QSPI_DATA_NONE;
sCommand.DummyCycles = 0;
sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
if (HAL_QSPI_Command_IT(&hqspi, &sCommand) != HAL_OK)
{
Error_Handler();
}
Flash_Wait_Busy();
}
void Flash_Write(void)
{
uint32_t address = 0x0000;
QSPI_AutoPollingMemReady(&hqspi);
QSPI_WriteEnable(&hqspi);
Flash_Wait_Busy();
sCommand.Instruction = PAGE_PROG_CMD;
sCommand.AddressMode = QSPI_ADDRESS_1_LINE;
sCommand.AddressSize = QSPI_ADDRESS_16_BITS;
sCommand.Address = address;
sCommand.DataMode = QSPI_DATA_1_LINE;
sCommand.NbData = BUFFERSIZE;
sCommand.DummyCycles = 0;
sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
if (HAL_QSPI_Command(&hqspi, &sCommand, HAL_QSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
Error_Handler();
}
if (HAL_QSPI_Transmit_IT(&hqspi, aTxBuffer) != HAL_OK)
{
Error_Handler();
}
}
void Flash_Program_Execute(uint32_t address)
{
QSPI_AutoPollingMemReady(&hqspi);
QSPI_WriteEnable(&hqspi);
sCommand.Instruction = PROGRAM_EXECUTE;
sCommand.AddressMode = QSPI_ADDRESS_1_LINE;
sCommand.AddressSize = QSPI_ADDRESS_24_BITS;
sCommand.Address = address;
sCommand.DataMode = QSPI_DATA_NONE;
sCommand.DummyCycles = 0;
sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
if (HAL_QSPI_Command_IT(&hqspi, &sCommand) != HAL_OK)
{
Error_Handler();
}
}
void Flash_Load_StorageData(uint32_t address)
{
QSPI_AutoPollingMemReady(&hqspi);
Flash_Wait_Busy();
sCommand.Instruction = PAGE_DATA_READ;
sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE;
sCommand.AddressMode = QSPI_ADDRESS_1_LINE;
sCommand.Address = address;
sCommand.AddressSize = QSPI_ADDRESS_24_BITS;
sCommand.DataMode = QSPI_DATA_NONE;
sCommand.DummyCycles = 0;
sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
if (HAL_QSPI_Command_IT(&hqspi, &sCommand) != HAL_OK)
{
Error_Handler();
}
}
void Flash_Read(void)
{
uint16_t address = 0x0000;
Flash_Wait_Busy();
QSPI_AutoPollingMemReady(&hqspi);
sCommand.Instruction = READ_CMD;
sCommand.AddressMode = QSPI_ADDRESS_1_LINE;
sCommand.AddressSize = QSPI_ADDRESS_16_BITS;
sCommand.Address = address;
sCommand.DataMode = QSPI_DATA_1_LINE;
sCommand.NbData = BUFFERSIZE;
sCommand.DummyCycles = 8;
sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
if (HAL_QSPI_Command(&hqspi, &sCommand, HAL_QSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
Error_Handler();
}
if (HAL_QSPI_Receive_IT(&hqspi, aRxBuffer) != HAL_OK)
{
Error_Handler();
}
}
--------------------------------------------------------------------Add 14/04/2023
void Flash_Wait_Busy(void)
{
while((Flash_Read_BusyBeat(0xC0) & 0x01) == 0x01);
}
uint8_t Flash_Read_BusyBeat(uint8_t address)
{
QSPI_WriteDisable(&hqspi);
sCommand.Instruction = READ_STATUS_REG_CMD;
sCommand.AddressMode = QSPI_ADDRESS_1_LINE;
sCommand.AddressSize = QSPI_ADDRESS_8_BITS;
sCommand.Address = address;
sCommand.DataMode = QSPI_DATA_1_LINE;
sCommand.DummyCycles = 0;
sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
sCommand.DdrMode = QSPI_DDR_MODE_DISABLE;
if (HAL_QSPI_Command(&hqspi, &sCommand, HAL_QSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
Error_Handler();
}
if (HAL_QSPI_Receive_IT(&hqspi, &BusyBeat) != HAL_OK)
{
Error_Handler();
}
QSPI_WriteEnable(&hqspi);
return BusyBeat;
}
