2025-08-14 7:00 AM
I am writing a custom driver for the mt25ql512abb as the one on STM's github doesnt work for my STM32L412KB, I have gotten reading, writing and erasing working but when I try enter memory mapped mode DQ[0-3] on the flash just goes high
Here is my function that im using, I am setting the XIP bit on the Volatile configuration register first (i have confirmed this is working) then I enter memory mapped mode, i have set the dummy cycles to 10 on the volatile and non-volatile configuration registers as well.
uint8_t CSP_QSPI_EnableMemoryMappedMode(void) {
QSPI_CommandTypeDef sCommand;
QSPI_MemoryMappedTypeDef sMemMappedCfg;
/* Enable Memory-Mapped mode-------------------------------------------------- */
sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE;
sCommand.AddressSize = QSPI_ADDRESS_32_BITS;
sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
sCommand.DdrMode = QSPI_DDR_MODE_DISABLE;
sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
sCommand.AddressMode = QSPI_ADDRESS_4_LINES;
sCommand.DataMode = QSPI_DATA_4_LINES;
sCommand.NbData = 0;
sCommand.Address = 0;
sCommand.Instruction = 0xeb;
sCommand.DummyCycles = 10;
sMemMappedCfg.TimeOutActivation = QSPI_TIMEOUT_COUNTER_DISABLE;
uint8_t config = 0xa3;
if(QSPI_WriteVCR(&config) != HAL_OK) {
return HAL_ERROR;
}
if (HAL_QSPI_MemoryMapped(&hqspi, &sCommand, &sMemMappedCfg) != HAL_OK) {
return HAL_ERROR;
}
return HAL_OK;
}
Here is my working read memory function
uint8_t CSP_QSPI_ReadMemory(uint8_t* buffer, uint32_t address, uint32_t buffer_size) {
QSPI_CommandTypeDef sCommand;
uint32_t end_addr, current_size, current_addr;
/* Calculation of the size between the write address and the end of the page */
current_addr = 0;
while (current_addr <= address) {
current_addr += MEMORY_PAGE_SIZE;
}
current_size = current_addr - address;
/* Check if the size of the data is less than the remaining place in the page */
if (current_size > buffer_size) {
current_size = buffer_size;
}
/* Initialize the adress variables */
current_addr = address;
end_addr = address + buffer_size;
sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE;
sCommand.AddressSize = QSPI_ADDRESS_32_BITS;
sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
sCommand.DdrMode = QSPI_DDR_MODE_DISABLE;
sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
sCommand.Instruction = 0xeb;
sCommand.AddressMode = QSPI_ADDRESS_4_LINES;
sCommand.DataMode = QSPI_DATA_4_LINES;
sCommand.NbData = buffer_size;
sCommand.Address = address;
sCommand.DummyCycles = 10;
/* Perform the write page by page */
do {
sCommand.Address = current_addr;
sCommand.NbData = current_size;
if (current_size == 0) {
return HAL_OK;
}
/* Configure the command */
if (HAL_QSPI_Command(&hqspi, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE)
!= HAL_OK) {
return HAL_ERROR;
}
/* Transmission of the data */
if (HAL_QSPI_Receive(&hqspi, buffer, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) {
return HAL_ERROR;
}
/* Configure automatic polling mode to wait for end of program */
if (QSPI_AutoPollingMemReady(HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) {
return HAL_ERROR;
}
/* Update the address and size variables for next page programming */
current_addr += current_size;
buffer += current_size;
current_size =
((current_addr + MEMORY_PAGE_SIZE) > end_addr) ?
(end_addr - current_addr) : MEMORY_PAGE_SIZE;
} while (current_addr <= end_addr);
return HAL_OK;
}
any help would be great thanks
2025-08-14 8:31 AM
Use the Code Format </> icon to post code inline, that way it retains formatting and indentation, and doesn't appear as a wall of text. Use the 'V' icon in upper right of pane to edit you initial post to fix it.
QSPI_CommandTypeDef sCommand = {0};
QSPI_MemoryMappedTypeDef sMemMappedCfg = {0};
I'd clear the local/auto variables to ensure there's not random stack junk in them.
If the Read method works properly, the template for the Memory Mapped should too. I don't think you need to set the VCR to XIP for this to work.
If you dump the 0x90000000 memory content from your app what does that look like? Does it Hard Fault?
You might want to configure the MPU for execution, but there's probably an example in CubeL4