cancel
Showing results for 
Search instead for 
Did you mean: 

Writing in Quad flash (W25Q128) inside a for(;;) loop (in a task) has a non intended behavior

frontinus
Associate II

I am Writing in a W25Q128 flash memory with a Cortex M4 microcontroller and FreeRtos operative system.

I created a task to write data in my W25Q128 flash.

However I noticed that when writing data in the flash thanks to the function Flash_Write (will post it and every lower level function) at a memory address saved in a variable and then incrementing the variable from one for(;;) iteration to another then the data saving in the flash would not occur as it should. In fact while debugging the code and only doing 1 iteration of the for(;;) loop the data is written multiple times with the address incrementing, when it should only write it once, it's also very disturbing that the address increases before the line is executed

Here is an example of the code

 

    gg = 100;
    for(;;){
    	uint32_t *pointer = ≫

    	Flash_Write(gg,(uint8_t*)"bang",4);
    	uint32_t temp = *pointer;
    	*pointer = temp + 4;
    }

 

and here what only 1 ieteration of flash_write (while debugging) saves

photo_2024-10-06_17-48-19.jpg

Worth also mentionning that outside of thoses for(;;) loops everything works correctly, I a priori also cannot fix my problem simply by removing the for(;;) loop because it's inside a FreeRtos task

now Flash_Write: 

 

void Flash_Write(uint32_t addr, uint8_t* data, uint32_t dataSize){
uint8_t buffer[4];
uint16_t quota;
uint32_t inpage_addr;

	if (dataSize==0)
		return;

	// quota is the data size trasferred until now
	quota=0;

	// define the starting write position inside the first Flash page to write...
	inpage_addr=addr & (EXT_FLASH_PAGE_SIZE-1);

	// ... so I can detect if more than 1 Flash page has still to be written
	while ((dataSize-quota+inpage_addr)>EXT_FLASH_PAGE_SIZE){
	//loop here inside, until more than 1 Flash page...

		Flash_Select();
		buffer[0] = W25_W_ENABLE;
		Flash_Transmit(buffer, 1);
		Flash_UnSelect();
		Flash_SimpleWriteAPage(addr+quota,data+quota,(EXT_FLASH_PAGE_SIZE-inpage_addr));
		quota+=(EXT_FLASH_PAGE_SIZE-inpage_addr);
		// having aligned data to page border on the first writing
		// next writings start from 0 position inside a page
		inpage_addr=0;
		Flash_WaitForWritingComplete();
	}
	// now just the final Flash page...
	if (dataSize-quota) {
		Flash_Select();
		buffer[0] = W25_W_ENABLE;
		Flash_Transmit(buffer, 1);
		Flash_UnSelect();
		Flash_SimpleWriteAPage(addr+quota,data+quota,dataSize-quota);
		Flash_WaitForWritingComplete();
	}
}

 

 

void Flash_SimpleWriteAPage(uint32_t addr, uint8_t* data, uint16_t dataSize){
uint8_t buffer[4];
	buffer[0] = W25_PAGE_P;
	buffer[1] = (addr >> 16) & 0xFF;
	buffer[2] = (addr >>  & 0xFF;
	buffer[3] = addr & 0xFF;
	Flash_Select();
	Flash_Transmit(buffer, 4);
	Flash_Transmit(data, dataSize);
	Flash_UnSelect();
}
void Flash_Transmit(uint8_t* data, uint16_t dataSize){
#ifndef	EXT_FLASH_SPI_POLLING_MODE
	if (dataSize<EXT_FLASH_DMA_CUTOFF) {
#endif //FLASH_SPI_POLLING_MODE
		HAL_SPI_Transmit(&FLASH_SPI_PORT , data, dataSize, HAL_MAX_DELAY);
#ifndef	EXT_FLASH_SPI_POLLING_MODE
	} else {
		HAL_SPI_Transmit_DMA(&EXT_FLASH_SPI_PORT , data, dataSize);
	}
#endif  //FLASH_SPI_POLLING_MODE
}

 

If you feel that you need more context ask me, thank you in advance for your time

4 REPLIES 4
TDK
Guru

How do you know only one iteration took place? Looks like you're debugging in STM32CubeProgrammer. Would be more useful to step through in STM32CubeIDE. Or write code that actually only executes a single loop. The code posted is consistent with the results you show.

If you feel a post has answered your question, please click "Accept as Solution".

I'm debugging step by step from stm32 cubde ide, I put a breakpoint at the for cycle, then take 3 steps over with the debugger, interrupt the debugging and open prg to see what's inside the flash. Isn't that 1 iteration?

The transition from debugging in STM32CubeIDE to connecting with STM32CubeProgrammer requires that the debugger be disconnected first, which lets the code free run.

 

Use the Memory viewer in CubeIDE (Window -> Show View -> Memory) to do the same thing while debugging.

TDK_0-1728255430177.png

 

I would initialize the memory with 0x00 and verify at the start of the loop that the memory isn't already written with "bang", then execute one iteration and verify the results. If it writes more than once it's a logic error in Flash_Write that you should be able to track down.

If you feel a post has answered your question, please click "Accept as Solution".

I will try this asap and let you know afterwards