STM32F746ZG - How to update some part of 256 KB sector in flash - stm32

I'm using STM32F103 and moving my code to STM32F746. The F103 was able to update Flash on a per-page basis in 1KB and 2KB.
I have STM32F746ZG Nucleo-board and my code size is big, flash took up to 0x08038000. I want to save other small applications on 0x08040000(sector_5). This applications consist of several 2KB sizes. I need to store multiple applications in Sector_5 and M7 cannot use Flash in 1KB or 2KB increments.
The followings are sector sizes of STM32F746ZG.
#define ADDR_FLASH_SECTOR_0 ((uint32_t)0x08000000) // 32 Kbytes
#define ADDR_FLASH_SECTOR_1 ((uint32_t)0x08008000) // 32 Kbytes
#define ADDR_FLASH_SECTOR_2 ((uint32_t)0x08010000) // 32 Kbytes
#define ADDR_FLASH_SECTOR_3 ((uint32_t)0x08018000) // 32 Kbytes
#define ADDR_FLASH_SECTOR_4 ((uint32_t)0x08020000) // 128 Kbytes
#define ADDR_FLASH_SECTOR_5 ((uint32_t)0x08040000) // 256 Kbytes
#define ADDR_FLASH_SECTOR_6 ((uint32_t)0x08080000) // 256 Kbytes
#define ADDR_FLASH_SECTOR_7 ((uint32_t)0x080C0000) // 256 Kbytes
STM32F746 consists of flash in a sector size of 256 KB each from Sector_5 to Sector7. If I want to use the Sector_5, I have to erase the whole of one sector. What if I want to update only about 2KB in the front of the Sector_5 and keep the area after 2KB intact? It means I only update the content from 0x08040000 to 0x08042000. I have to keep from 0x08042001 to 0x0807FFFF.
I can't even copy 256 KB of Flash to RAM. Because F746 only have 240KB of internal RAM and my many tasks already used RAM, so there is not enough RAM to copy one sector. In this case, please let me know how to update part of 256KB in flash.

On the ST's flash technology, there is no way to update anywhere in the sector without first erasing it. So if there are content in the first 2KB, you cannot update it without erasing the rest of the sector.
One possibility is that you can keep one sector as a temporary buffer and never use it for real storage. Let's say you use sector 7 for that. So when you want to update sector 5, erase sector 7, copy sector 5 into sector 7, and then erase sector 5 and copy relevant content back.
Another possibility is to add an external EEPROM or SRAM for this purpose. SPI flash EEPROM is fairly inexpensive and they have a typical 100,000 write cycles, so also perfect for this use.

That depends. On many STM32 microcontrollers you can zero the bits of the FLASH without erasing it. But you cant set the bits of course - it can only be done by the erase operation. Some chips do not allow it as the flash sector has its own CRC.
If your chip allows the writing to the 0xff filled FLASH you can store the data in another place of this sector. If not You need to copy data to another sector, arase the sector and the write the data back.

Related

How far is it safe to regularly write to the ESP32 flash, considering the flash MTBF?

What would be the best practice for writing to the flash on a regular basis.
Considering the hardware I am working on is supposed to have 10 to 20 years longevity, what would be your recommandation? For example, is it ok I write some state variables every 15 minutes thru Preferences?
That depends on
number of erase cycles your Flash supports,
size of the NVS partition where you store data and
size and structure of the data that you store.
Erase cycles mean how many times a single sector of Flash can be erased before it's no longer guaranteed to work. The number is found in the datasheet of the Flash chip that you use. It's usually 10K or 100K.
Preferences library uses the ESP-IDF NVS library. This requires an NVS partition to store data, the size of which determines how many Flash sectors get reserved for this purpose. Every time you store a value, NVS writes the data together with its own overhead (total of 32 bytes for primitive data types like ints and floats, more for strings and blobs) into the current Flash sector. When the current sector is full, it erases the next sector and proceeds to write there; thereby using up sectors in a round robin fashion as write requests come in.
If we assume that your Flash has 100K erase cycles, size your NVS partition is 128 KiB and you store a set of 8 primitive values (any int or float) every 15 minutes:
Each store operation uses 8 * 32 = 256 bytes (32 B per data value).
You can repeat that operation 131072 / 256 = 512 times before you've written to every sector of your 128KiB NVS partition (i.e. erased every sector once)
You can repeat that cycle 100K times so you can do 512 * 100000 = 51200000 or roughly 5.1M store operations before you've erased every sector its permitted maximum number of times.
Considering the interval of 15 minutes creates 365 * 24 * 4 = 35040 operations per year, you'd have 51200000 / 35040 = 1461 years until Flash is dead.
Obviously, if your Flash chip is rated at 10K erase cycles, it drops to only 146 years.
There's probably some NVS overhead in there somewhere that I didn't account for, and the Flash erase cycle ratings are not 100% reliable so I'd cut it in half for good measure - I would expect 700 or 70 years in real life.
If you store non-primitive values (strings, blobs) then the estimate changes based on the length of that data. I don't know to calculate the exact Flash space used by those but I'd guess 32B plus length of your data multiplied by 10% of NVS overhead. Plug in the numbers, see for yourself.

If a 32 bit address processor can access 4GB how does this processor deal with hard disk of size 500 Gb?

A 32-bit register can store 232 different values. The signed range of integer values that can be stored in 32 bits is -2,147,483,648 through 2,147,483,647 (unsigned: 0 through 4,294,967,295). Hence, a processor with 32-bit memory addresses can directly access 4 GiB of byte-addressable memory. so how this kind of processor deal with disk of size more than 4 gb?
Hence, a processor with 32-bit memory addresses can directly access 4 GiB of byte-addressable memory. so how this kind of processor deal with disk of size more than 4 gb?
For disks; typically they're not byte addressable and the smallest amount that can be read or written (the block size) is 512 bytes or larger (maybe 4096 bytes). Block numbers may also be larger than 32 bits (e.g. maybe 48 bit block numbers).
With 512-byte blocks and 48 bit block numbers (which was common in the late 1990s; for ATA and SATA, etc) you'd end up with a maximum disk size of 134217728 GiB.
Of course the CPU probably (see note) can't directly access any of the data on disk. Software (file system) has to ask a device driver to fetch the block/s it wants, and device driver asks hardware (disk controller) to copy data between disk and memory. Depending on OS; this software interface (used by file system to ask device driver to read or write blocks) most likely uses 64-bit block numbers (e.g. two 32-bit registers joined together).
Note: More recently, the possibility of using non-volatile RAM (e.g. https://en.wikipedia.org/wiki/3D_XPoint ) as storage changed things (it is byte addressable and does use physical addresses); but modern hardware is all "64-bit" (with physical addresses that may be 48 bits or larger in practice) so even though the theoretical limit is much smaller it's still large enough in practice (e.g. maybe 200000 GiB).
On x86-64, the main CPU architecture of most desktop computers, an interface is standardized in the AHCI (Advanced Host Controller Interface). The computer accesses the hard-disk using this interface which is, in practice, a PCI-Express device compliant with the PCI-Express specification.
With PCI, the CPU has a memory controller which will write to the PCI devices registers instead of RAM when writing to some portions of RAM. Software (the operating-system) will write in uncached RAM and it will instead write to the registers of the PCI device. This way it can tell the devices, including an AHCI, to do some operations like a DMA operation from the hard-disk to RAM and vice-versa.
I didn't read the specification in full but the specification probably holds 64 bits registers that can be written as 2 32 bits words. More often, software will write to the lower part of the register then to the higher part of the register. This allows any 32 bits computers to still be able to interact with AHCI. On a 64 bits computer, the registers will be written as one 64 bits write.
A 32 bits computer is thus still able to trigger DMA writes to some portions of the hard-disk which are much higher than 4GB.

How much flash memory is there in the microcontroller?

I have an STM32F303CBT6 microcontroller.
On the ST site, the volume of the flush is 128 kB.
In reference manual flash up 256 kB.
In this case, register "Flash memory size data register" contains the value 128 [kB].
There is also 128 kb in the stlink utility.
But in the cleaning window, the page costs 128 pages of 2 kB. This amounts to 256 KB.
I didn't get it. What is the size of the flash?
The "B" in STM32F303CBT6 stands for "128KB" (see STM32 Part Number Decoding).
The 256KB version would be STM32F303CCT6.
I can't tell you what the cleaning window indicates.

Using Datalogger- and EepromService together

I am trying to store some data on the device that I do not want to be overwritten by when the datalogger is full. And have run into some minor issues. I was looking for the "eeprom_logbook_app" but could not find it in firmware version 1.6.2 of the device-lib.
I have defined how much space I want for my persistent data and in App.cpp I have used the LOGBOOK_MEMORY_AREA(offset, size) macro.
where I have used the size of what I want to store as the offset and set the size to be
(2097152 + 1048576) - (size of data I want to store)
as this was what was returned when I asked the sensor for the eeprom size. (The eeprom is devided between 2 ICs one with 1MB capasity and one with 2MB capacity?)
Then I remembered that there was some talk about ExtflashChunkStorage::StorageHeader being stored as the first 256 bytes in this answer.
So my question is where the data will be offset from and what is the max size I can set as size so that I can subtract the correct amount to fit my data? I presume I at least need to take another 256 bytes off from the size to get my correct storage size.
As stated in my comment I got this working the only thing you need to do is using the LOGBOOK_MEMORY_AREA(offset, size) function.
let's say you want to set aside 256 bits for your own config you could then do this:
#define RESERVED_CONFIG 256
#define TOTAL_MEMMORY_SIZE (2097152 + 1048576)
static const uint32_t offset = RESERVED_CONFIG;
static const uint32_t size = TOTAL_MEMMORY_SIZE -offset;
LOGBOK_MEMORY_AREA(offset, size);
This will set aside 256 bytes on the start of the EEPROM memory and offset the logbook to accommodate this. As a result, the logbook header will also be moved to the start of the logbook's memory area.

Addressing a word inside memory frames

Suppose we have a 64 bit processor with 8GB ram with frame size 1KB.
Now main memory size is 2^33 B
So number of frames is 2^33 / 2^10 which is 2^23 frames.
So we need 23 bits to uniquely identify every frame.
So the address split would be 23 | 10 where 10 bits are required to identify each byte in a frame (total 1024 bytes)
As it is word addressable with each word = 8B, will the address split now be 23 | 7 as we have 2^7 words in each frame?
Also can the data bus size be different than word size ?
If suppose data bus size is 128 bits then does it mean that we can address two words and transfer 2 words at a time in a single bus cycle but can only perform 64 bit operations?
Most of the answers are dependent on how the system is designed. Also there is bit more picture to your question.
There is something called available addressable space on a system. In a 32 bit application this would be 2^32 and in a 64 bit application this would be 2^64. This is called virtual memory. And there is physical memory which commonly refereed as RAM. If the application is built as 64 bits, then it is able work as if there is 2^64 memory is available. The underlying hardware may not have 2^64 RAM available, which taken care by the memory management unit. Basically it breaks both virtual memory and physical memory into pages( you have refereed to this as frames) and keeps the most frequently used pages in RAM. Rest are stored in the hard disk.
Now you state, the RAM is 8GB which supports 2^33 addressable locations. When you say the processor is 64 bits, I presume you are talking about a 64 bit system which supports 2^64 addressable locations. Now remember the applications is free to access any of these 2^64 locations. Number of pages available are 2^64/2^10 = 2^54. Now we need to know which virtual page is mapped to which physical page. There is a table called page table which has this information. So we take the first 54 bits of the address and index in to this table which will return the physical page number which will be 2^33/2^10 = 23 bits. We combine this 23 bits to the least 10 bits of the virtual address which gives us the physical address. In a general CPU, once the address is calculated, we don't just go an fetch it. First we check if its available in the cache, all the way down the hierarchy. If its not available a fetch request will be issued. When a cache issues a fetch request to main memory, it fetches an entire cache line (which is usually a few words)
I'm not sure what you mean by the following question.
As it is word addressable with each word = 8B, will the address split now be 23 | 7 as we have 2^7 words in each frame?
Memories are typically designed to be byte addressable. Therefore you'll need all the 33 bits to locate a byte within the page.
Also can the data bus size be different than word size ?
Yes you can design a data bus to have any width, but having it less than a byte would be painful.
If suppose data bus size is 128 bits then does it mean that we can
address two words and transfer 2 words at a time in a single bus cycle
but can only perform 64 bit operations?
Again the question is bit unclear, if the data but is 128 bits wide, and your cache line is wider than 128 bits, it'll take multiple cycles to return data as a response to a cache miss. You wont be doing operations on partial data in the cache (at least to the best of my knowledge), so you'll wait until the entire cache line is returned. And once its there, there is no restriction of what operations you can do on that line.