cancel
Showing results for 
Search instead for 
Did you mean: 

mt25ql512abb in memory mapped mode not working

fhumphrys
Associate II

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

1 ACCEPTED SOLUTION

Accepted Solutions

I mean you print the content to the console using a pointer to 0x90000000, so you can observe it reading content.

Or you inspect in the debugger AFTER the memory has been mapped.

On the CM7 you need to configure the MPU for code/execution access, I don't recall if the L4 / CM4 needs this, and found no example on the CubeL4 GitHub

Have a viable Hard Fault Handler to report / dump issue if you end up there.

The linker script just directs what content is placed in external memory, getting code there and calling it is more involved. It does need to be mapped first. Generally one would build a boot loader to bring up the system, pins and memory and then transfer control.

The CM4 not being a particularly good choice as it lacks a cache, so code/data from external memory will be relatively slow.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

View solution in original post

6 REPLIES 6

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

 

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

sorry fixed the code import, could you explain what you mean by dumping the memory content, and do you mean configure the MPU for external flash as i have put this  QSPI (rx) : ORIGIN = 0x90000000, LENGTH = 64M in my linker script, along with this

  .extFlashMem :
  {
  	*(.extFlashMem)
  } >QSPI

I mean you print the content to the console using a pointer to 0x90000000, so you can observe it reading content.

Or you inspect in the debugger AFTER the memory has been mapped.

On the CM7 you need to configure the MPU for code/execution access, I don't recall if the L4 / CM4 needs this, and found no example on the CubeL4 GitHub

Have a viable Hard Fault Handler to report / dump issue if you end up there.

The linker script just directs what content is placed in external memory, getting code there and calling it is more involved. It does need to be mapped first. Generally one would build a boot loader to bring up the system, pins and memory and then transfer control.

The CM4 not being a particularly good choice as it lacks a cache, so code/data from external memory will be relatively slow.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

Having inspected in the debugger all i see is the data is there, slightly corrupt but i think that is due to dodgy wiring, thanks

still i don't know why this memcmp function isnt working as thats the reason i thought my memory mapped mode wasnt working

  if (memcmp(read_buffer, (uint8_t*) (0x90000000 + MEMORY_PAGE_SIZE), MEMORY_PAGE_SIZE) != HAL_OK) {
		while (1)
			;  //breakpoint - error detected - otherwise QSPI works properly
	}

I keep ending up in the while loop and this function is what the STM recommend to test the external flash

Also will switching to the F412 give me better performance or make no difference as it is also CM4

never mind i was being *** didnt realise it was mem compare instead of memcpy, was failing due to using high frequency on a breadboard

Plus memcmp() doesn't return HAL statuses..

Also memory mapping can only support READ, it doesn't support WRITE. Most QSPI NOR FLASH uses WRITE PAGE where up to 256 bytes can be written and you can't cross 256-byte page boundaries. An you must wait for BUSY/READY for Write-In-Progress bit in status register

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..