I am programming the STM32fM4 Discovery board with a Cortex M4F ARM CPU. I have two large tables, which, after the initialization, are just read-only. I would like to place them in Flash memory, to free some RAM.
I tried this :
float sintab[8192] __attribute__((at(0x08010000))); float costab[8192] __attribute__((at(0x08018000)));
but the linker complains with this error message :
Error: L6985E: Unable to automatically place AT section main.o(.ARM.__AT_0x08010000) with required base address 0x08010000. Please manually place in the scatter file using the --no_autoat option.
I am not particularly expert of this compiler/linker, so the above message is not much clear to me. Could please somebody explains how to accomplish what I want ? I don't know what a scatter file is, nor how to code one to relocate in Flash memory my two tables.
Thanks
I have two large tables, which, after the initialization, are just read-only.
That's puzzling. Are you saying that you are going to initialize them at run time? Normally, the contents of the tables would be known at compile time. Then you would declare them as const and they would be placed in flash memory automatically.
That's puzzling. Are you saying that you are going to initialize them at run time?
Thanks for the answer. Yes, they are initialized at run time, as the contents depend on some conditions. So cannot fill them at compile time. Is there any way to have them allocated in Flash memory, where they will be written just once, and then only read ?
Thanks.
You would have to erase the flash and write the tables there, using the FLASH_xxx API provided by the STM32 library, or equivalent routines you have created.
You could use your tables float *sintab = (float *)0x08010000; float *costab = (float *)0x08018000;
Yes, this compiles and links without errors. But do I still need to first erase the Flash ? Those address are above the area used by my code (which is placed by the linker at 0x8000000), and the loader does an erase when loading the program in memory.
Can I programmatically write to those locations with a simple instruction, like, e.g.
sintab[k] = <some float value>;
I seem to recall having read that writing to Flash was a bit more involved... Until yesterday I have programmed Pentium CPUs, where things are a bit different.
Some more effort and error handling involved, but along the lines of
FLASH_Status status = FLASH_COMPLETE; FLASH_Unlock(); // Clear any pending status status = FLASH_WaitForLastOperation(); /* Wait for last operation to be completed */ status = FLASH_EraseSector(FLASH_Sector_4, VoltageRange_3); // 64 KB @ 0x8010000 status = FLASH_WaitForLastOperation(); /* Wait for last operation to be completed */ if (status == FLASH_COMPLETE) { FLASH->CR &= CR_PSIZE_MASK; FLASH->CR |= FLASH_PSIZE_WORD; FLASH->CR |= FLASH_CR_PG; i = 0x08010000; // Flash table base { // some table generation loop for sin/cos *(__IO uint32_t*)i = Data; // Write to Flash 32-bit word status = FLASH_WaitForLastOperation(); /* Wait for last operation to be completed */ if (status != FLASH_COMPLETE) break; i += 4; } // end of table gen loop FLASH->CR &= (~FLASH_CR_PG); } FLASH_Lock();
Thanks guys. I can do now what I need to do. Being the write operation done only in the initialization phase, I don't care if it is a bit slow. What counts is that accessing the tables in read mode is fast. I am counting every cycle spent in the various phases... I am sampling at 1.4 Ms/sec, and have some heavy computations to do with those samples...
TNX
What counts is that accessing the tables in read mode is fast
Random accesses to flash memory incur several-cycle delays. It could still be fast enough. On-chip RAM is definitely faster. I hope you did not forget about the CCM (core-coupled memory) that is present in STM32F4 MCU's.
I hope you did not forget about the CCM (core-coupled memory) that is present in STM32F4 MCU's.
Oh, this is an interesting sentence... Yes, I read on the datasheet of the CPU about the existence of that CCM, but frankly I don't know how to use it, nor if it could be of advantage to me... but from your sentence I presume the answer is yes...
Would you mind please to spend just a few words about how can I use it, and possibily about which speed advantage I could expect from using it ?
Well, it's on-chip RAM. Unlike the rest or the on-chip RAM, it is not connected to the bus matrix, so it cannot be used with DMA, and code cannot be executed from it. But you don't need either of those, and it's good for data tables. Accesses should not involve any delay cycles. You use it just like you would use flash memory as described above, only writing to it is just like writing to any RAM. There must be a way to configure the linker to place the tables in the CCM. I just don't have the time to explore this. As a shortcut, the following should work (as suggested above):
float *sintab = (float *)0x10000000; float *costab = (float *)0x10008000;
As a shortcut, the following should work (as suggested above):
Thanks for the tip, I will surely explore this possibility. Seems the ideal place where to put those tables, if the dimension of this CCM will accommodate them.