cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F7 QSPI Flash External Flash Loader

yldzmuhammed
Associate III

Hello to everyone.

I am currently developing a project using STM32F750N8 and W25Q128. As you can guess, the project has an LCD. So the project is too big to fit into the internal memory. That's why I need an external memory integrated programming.

I develop the software with Keil and use the Jlink programmer.

I know that i need to the External Flash Loader for this operation. That's why I developed one.

But it doesn't work as it should. I also added UART for debug purposes. It works quite unstable.

Sometimes Init function doesn't work, sometimes the sector erase fails, sometimes the full chip erase fails, sometimes everything works, but the verification fails. Verification is never successful, though.

I have developed an application that runs on the internal memory, and I can sector/full chip erase and write any data in the external memory.

I also monitored the voltage from the flash chip ic from VCC pin using an oscilloscope. 3.3V. Just as it should be. When wiping, writing, reading, the voltage is exactly as it should be. But I didn't get a stable result.

I have prepared the attached project.

Can someone take a hand?

36 REPLIES 36
AVI-crak
Senior

Externally managing exact memory addresses is a very bad idea. After some time, you may change the design of the breadboard, at this point you will have to rewrite two programs - for the breadboard and for the big machine.

However, if the recording algorithm is made easier, then its reliability will increase.

You need to transfer data blocks of an acceptable size from a large machine, so that the correction of transmission errors does not freeze data transmission for a long time. The data block is located after the data packet level.

Data blocks must be collected up to the level of one physical data block of flash memory (not a whole sector !!!). Here you can have three blocks of physical size: the first is assembled, the second is a buffer, the third is written to flash memory. Three blocks allow you to perform data transfer and write operations - completely asynchronously, without waiting cycles.

Clearing flash memory from data, and checking for 0xFF - can be done on the machine, without exact addresses.

To verify data through direct reading, you already have part of the algorithm.

Feedback is not always needed as much as you want. Too detailed a report will only be annoying. It makes sense a detailed report in the failure mode, once.

I propose the option of writing a data block without controlling the sector address. If you change a little, it will work with any flash memory chip.

https://bitbucket.org/AVI-crak/system_f746/src/default/qspi_driver_S25FL256S/qspi_rw.c

yldzmuhammed
Associate III

Hello @AVI-crak​ 

I did not get your point. Sorry. Are you talking about (mainly) road map? Did you see any wrong part in my code?

I looked at your code, it is based on HAL functions. I see address management but cannot see the contents of HAL functions. To do this, you must run your code on physical debugging - not available to me.

Address management is a mistake. You must hide address management behind the physical driver.

The transition between direct and indirect addressing is the operation "address & 0x0FFFFFFF". It does not matter the location of the memory bank and its size - there is no access above the address 0x0FFFFFFF.

yldzmuhammed
Associate III

By address management you mean:

#define SRAM_ADDRESS1	((uint32_t *)(SRAM2_BASE + 4))
#define SRAM_ADDRESS2	((uint32_t *)(SRAM2_BASE + 8))
 
/* Private macro -------------------------------------------------------------*/
#define M8(adr)  		(*((volatile uint8_t  *) (adr)))
#define M16(adr) 		(*((volatile uint16_t *) (adr)))
#define M32(adr) 		(*((volatile uint32_t *) (adr)))
 
 
 
 
	M32(SRAM_ADDRESS1)++;
	M32(SRAM_ADDRESS2) += (uint32_t)sz;

If it is, they just keep some variables.

Can you explain with more details?

Additionally.

About writing a block to flash memory.

The internal external memory machine does not allow the clock to stop during a write operation. This means that the data must come in one piece, without pauses !!! This mode can only provide a working DMA. In the event of a failure, the write operation will be performed, but with errors. Errors are read through the state registers of the external flash memory.

In case of using DMA - a protective timer is not required. Because there are no external physical dependencies, everything is done inside the microprocessor.

Look at my code, there is a hardware check for state flags. There are no errors reading flags, I just check the contents of the memory by direct reading.

All modern flash memory chips already have a hardware anti-freeze timer. It resets the last operation and sets error flags on internal registers. The software protection timer is required only for debugging the program algorithm, after which it must be deleted.

AVI-crak
Senior

I have a line

#define SDRAM __attribute __ ((section (". qsdram")))

You can write like this

#define QSPIROM __attribute __ ((section (". qspirom")))

This means the declared name section in the linker, where all the necessary data is placed. There is no need to accurately calculate the address; the machine will do this.

I do not know how your data is indicated in the external flash memory. I make the notation through the structure

#ifdef __cplusplus
 extern "C" {
#endif /* __cplusplus */
 
#ifndef     image_h
#define     graphics_package  0
 
#if (graphics_package == 1U)
#define QSPIROM   __attribute__((section(".qspirom")))
QSPIROM static const struct
{
     uint16_t image01[0x25800];
     uint16_t image02[0x25800];
...
 
}grafik={
    #include "image0_1.h"
    #include "image0_2.h"
...
} ;
#else
 
 
typedef struct
{
     uint16_t image01[0x25800];
     uint16_t image02[0x25800];
...
}grafik_TypeDef;
#define grafik               ((grafik_TypeDef*) (0x90000000))
 
#endif
 
#endif /* image_h */
#define image_h
 
#ifdef __cplusplus
}
#endif /* __cplusplus */ 

yldzmuhammed
Associate III

Firts of all, thanks alot for your support.

Secondly, i dont think this will help me to write firmware or anything to the flash memory with jlink. Am i correct?

AVI-crak
Senior

Look at my example, there is no exact binding to addresses. The compiler collects all the firmware at one time, tens of hundreds of separate pieces of data with a symbolic name in the addresses of external flash memory. This is a long time, but only once.

After that, the memory dump can be flashed with an external programmer, or with a separate project - using flash memory as a data storage device.

A symbolic name is much easier to use than exact addresses - which are very easy to get confused about.

If you need to add new data, just add it to the project under the write operation to your symbolic name. As a rule, these are small pieces of data that easily fit into the RAM memory in debug mode.

There is an option to use the file system, but this adds overhead when reading. And it almost completely prohibits the creation of one whole memory dump. This is convenient for the slow development of the project, and a huge crutch when replicating finished devices.

yldzmuhammed
Associate III

Dear @AVI-crak​ please forgive me.But i still don get that how to write external flash memory?i want to write all my firmware to the my external flash memory. How am i going to do that? That is all i need for now.

Thanks.