2022-03-31 03:52 AM
I am trying to initialize my W25Q128jv External Flash in my project, but I am not able to write on it and I think it could be because of the Memory Mapping Mode but I really don't know. For this project I will need my QUADSPI when I will add TouchGFX to save some items, but for now I am only trying to do a for cycle to verify that it works and its performance. If I disable MemoryMappingMode to write, it goes in HardFault.
uint32_t *flashbuffer = (uint32_t*)0x90000000;
const uint32_t size = 1000;
int begin = HAL_GetTick();
for(i = 0; i < size; i++)
{
flashbuffer[i]=i;
}
int end = HAL_GetTick();
Here is MX_QUADSPI_Init
static void MX_QUADSPI_Init(void)
{
/* USER CODE BEGIN QUADSPI_Init 0 */
/* USER CODE END QUADSPI_Init 0 */
/* USER CODE BEGIN QUADSPI_Init 1 */
/* USER CODE END QUADSPI_Init 1 */
/* QUADSPI parameter configuration*/
hqspi.Instance = QUADSPI;
hqspi.Init.ClockPrescaler = 1;
hqspi.Init.FifoThreshold = 4;
hqspi.Init.SampleShifting = QSPI_SAMPLE_SHIFTING_HALFCYCLE;
hqspi.Init.FlashSize = 23;
hqspi.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_6_CYCLE;
hqspi.Init.ClockMode = QSPI_CLOCK_MODE_0;
hqspi.Init.FlashID = QSPI_FLASH_ID_1;
hqspi.Init.DualFlash = QSPI_DUALFLASH_DISABLE;
if (HAL_QSPI_Init(&hqspi) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN QUADSPI_Init 2 */
BSP_QSPI_Init();
/* USER CODE END QUADSPI_Init 2 */
}
And here is my initialization
uint8_t BSP_QSPI_Init(void)
{
QSPI_CommandTypeDef s_command;
uint8_t value = W25Q128JV_FSR_QE;
/* QSPI memory reset */
if (QSPI_ResetMemory() != QSPI_OK)
{
return QSPI_NOT_SUPPORTED;
}
/* Enable write operations */
if (QSPI_WriteEnable() != QSPI_OK)
{
return QSPI_ERROR;
}
/* Set status register for Quad Enable,the Quad IO2 and IO3 pins are enable */
s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE;
s_command.Instruction = WRITE_STATUS_REG2_CMD;
s_command.AddressMode = QSPI_ADDRESS_NONE;
s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
s_command.DataMode = QSPI_DATA_1_LINE;
s_command.DummyCycles = 0;
s_command.NbData = 1;
s_command.DdrMode = QSPI_DDR_MODE_DISABLE;
s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
/* Configure the command */
if (HAL_QSPI_Command(&hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
return QSPI_ERROR;
}
/* Transmit the data */
if (HAL_QSPI_Transmit(&hqspi, &value, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
return QSPI_ERROR;
}
/* automatic polling mode to wait for memory ready */
if (QSPI_AutoPollingMemReady(W25Q128JV_WRITE_STATUS_REG_TIME_MS) != QSPI_OK)
{
return QSPI_ERROR;
}
BSP_QSPI_MemoryMappedMode();
return QSPI_OK;
}
/*BSP_QSPI_Init*/
And here my driver
static uint8_t QSPI_WriteEnable(void) {
QSPI_CommandTypeDef sCommand;
QSPI_AutoPollingTypeDef sConfig;
/* Enable write operations ------------------------------------------ */
sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE;
sCommand.Instruction = WRITE_ENABLE_CMD;
sCommand.AddressMode = QSPI_ADDRESS_NONE;
sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
sCommand.DataMode = QSPI_DATA_NONE;
sCommand.DummyCycles = 0;
sCommand.DdrMode = QSPI_DDR_MODE_DISABLE;
sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
if (HAL_QSPI_Command(&hqspi, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) {
return (QSPI_ERROR);
}
/* Configure automatic polling mode to wait for write enabling ---- */
sConfig.Match = W25Q128JV_FSR_WREN;
sConfig.Mask = W25Q128JV_FSR_WREN;
sConfig.MatchMode = QSPI_MATCH_MODE_AND;
sConfig.StatusBytesSize = 1;
sConfig.Interval = 0x10;
sConfig.AutomaticStop = QSPI_AUTOMATIC_STOP_ENABLE;
sCommand.Instruction = READ_STATUS_REG1_CMD;
sCommand.DataMode = QSPI_DATA_1_LINE;
sCommand.NbData = 1;
if (HAL_QSPI_AutoPolling(&hqspi, &sCommand, &sConfig, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) {
return (QSPI_ERROR);
}
return (QSPI_OK);
} /* QSPI_WriteEnable */
static uint8_t BSP_QSPI_Write(const uint8_t * pData, uint32_t WriteAddr, uint32_t Size) {
QSPI_CommandTypeDef s_command;
uint32_t end_addr, current_size, current_addr;
/* Calculation of the size between the write address and the end of the page */
current_addr = 0U;
while (current_addr <= WriteAddr) {
current_addr += W25Q128JV_PAGE_SIZE;
}
current_size = current_addr - WriteAddr;
/* Check if the size of the data is less than the remaining place in the page */
if (current_size > Size) {
current_size = Size;
}
/* Initialize the address variables */
current_addr = WriteAddr;
end_addr = WriteAddr + Size;
/* Initialize the program command */
s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE;
s_command.Instruction = QUAD_INPUT_PAGE_PROG_CMD;
s_command.AddressMode = QSPI_ADDRESS_1_LINE;
s_command.AddressSize = QSPI_ADDRESS_24_BITS;
s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
s_command.DataMode = QSPI_DATA_4_LINES;
s_command.DummyCycles = 0;
s_command.DdrMode = QSPI_DDR_MODE_DISABLE;
s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
/* Perform the write page by page */
do {
s_command.Address = current_addr;
s_command.NbData = current_size;
/* Enable write operations */
QSPI_WriteEnable();
/* Configure the command */
if (HAL_QSPI_Command(&hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) {
return (QSPI_ERROR);
}
/* Transmission of the data */
if (HAL_QSPI_Transmit(&hqspi, (uint8_t *)((uint32_t)pData), HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) {
return (QSPI_ERROR);
}
/* Configure automatic polling mode to wait for end of program */
if (QSPI_AutoPollingMemReady(HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != QSPI_OK) {
return (QSPI_ERROR);
}
/* Update the address and size variables for next page programming */
current_addr += current_size;
pData += current_size;
current_size = ((current_addr + W25Q128JV_PAGE_SIZE) > end_addr) ? (end_addr - current_addr) : W25Q128JV_PAGE_SIZE;
} while (current_addr < end_addr);
return (QSPI_OK);
} /* BSP_QSPI_Write */
uint8_t BSP_QSPI_Read(uint8_t* pData, uint32_t ReadAddr, uint32_t Size) {
QSPI_CommandTypeDef s_command;
/* Initialize the read command */
s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE;
s_command.Instruction = READ_CMD;
s_command.AddressMode = QSPI_ADDRESS_1_LINE;
s_command.AddressSize = QSPI_ADDRESS_24_BITS;
s_command.Address = ReadAddr;
s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
s_command.DataMode = QSPI_DATA_1_LINE;
s_command.DummyCycles = 0;
s_command.NbData = Size;
s_command.DdrMode = QSPI_DDR_MODE_DISABLE;
s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
/* Configure the command */
if (HAL_QSPI_Command(&hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) {
return (QSPI_ERROR);
}
/* Reception of the data */
if (HAL_QSPI_Receive(&hqspi, pData, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) {
return (QSPI_ERROR);
}
return (QSPI_OK);
} /* BSP_QSPI_Read */
static void BSP_QSPI_MemoryMappedMode(void) {
QSPI_CommandTypeDef s_command;
QSPI_MemoryMappedTypeDef s_mem_mapped_cfg;
/* Configure the command for the read instruction */
s_command.Instruction = QUAD_INOUT_FAST_READ_CMD;
s_command.Address = 0U;
s_command.AlternateBytes = 0xF0;
s_command.AddressSize = QSPI_ADDRESS_24_BITS;
s_command.AlternateBytesSize = QSPI_ALTERNATE_BYTES_8_BITS;
s_command.DummyCycles = W25Q128JV_DUMMY_CYCLES_READ_QUAD;
s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE;
s_command.AddressMode = QSPI_ADDRESS_4_LINES;
s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_4_LINES;
s_command.DataMode = QSPI_DATA_4_LINES;
s_command.NbData = 0U;
s_command.DdrMode = QSPI_DDR_MODE_DISABLE;
s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
/* Configure the memory mapped mode */
s_mem_mapped_cfg.TimeOutPeriod = 0;
s_mem_mapped_cfg.TimeOutActivation = QSPI_TIMEOUT_COUNTER_DISABLE;
if (HAL_QSPI_MemoryMapped(&hqspi, &s_command, &s_mem_mapped_cfg) != HAL_OK) {
Error_Handler();
}
} /* BSP_QSPI_MemoryMappedMode */
Solved! Go to Solution.
2022-04-01 04:20 AM
Thanks for your suggestions. I used the two functions Write and Read, and disabling the Memory Mapping Mode it works. Thank you again!
2022-03-31 10:02 AM
If i good understand in memory mapped mode is read only , cant write.
And in your question i dont see where is returned QSPI_ERROR...
2022-03-31 10:56 AM
That's not how you write to this type of NOR Flash memory.
Memory Mapped mode here does not support writing.
If you access un-mapped/un-decoded memory on a Cortex-Mx it will Hard Fault / Bus Fault.
Writing of this type of memory is done in direct command mode, with specific commands, which you then wait on completion. See BSP_QSPI_Write()
Pull a manual/data-sheet for the W25Q128 parts and review it.
2022-04-01 04:20 AM
Thanks for your suggestions. I used the two functions Write and Read, and disabling the Memory Mapping Mode it works. Thank you again!