[SAMC] Microcontroller non volatile pages and rows - Page 1
Forum section: electronics / general

author: Simon
author_rank: Unknown
timestamp: May 28, 2025, 08:00:55 pm
content: I'm writing some code to deal with writing to non volatile memory on the SAMC. So far what I have done has been mostly aimed at particular projects but now I want to write something a little more generic. This is to save variables that have either been updated at run time or that have been updated over say a comms link.The memory is divided into rows (256 bytes in this case), each page is made up of 4 pages. While I can write one page at a time I can only erase the entire row of 4 pages. So why exactly do I have pages anyway? Is there a use case for this? So far I have never stored anything larger than a page. Now that I am looking to do so I wonder if I should say store my checksum on each page or just do that for the whole row. I mean surely I may as well just work with a page as the smallest memory unit.

author: ataradov
author_rank: Super Contributor
timestamp: May 28, 2025, 09:26:23 pm
content: This is just how all flash ends up being designed, so it is exposed to the user to prevent additional wear if use case allows. If you write incremental values (like a log), it helps to have smaller pages. You can erase the whole row and then write only affected pages.But keep in mind that there is additional limitation of maximum 8 writes per row before you have to erase the row. So, in case of that incremental log example, you can do 2 writes into each page.

author: Simon
author_rank: Unknown
timestamp: May 29, 2025, 06:17:46 am
content: Yes I am not surprised if this is the same on others. I guess there is some manufacturing or reason like you suggest for incremental logs that are probably a common use.At the moment I am looking at storing structures of 32 bit values so without looking at how a new value compares to the old and if an overwrite will work it will be simpler to erase and rewrite the entire row. I could implement at some point a mechanism to count the writes and then mow to the next row.If I am only using one page does erasing other already blank pages count towards the total amount of cycles? I think that the "effort" is in flipping a "0" back to a "1" but if the space is all 1's already does it count? if it does not I guess this is how a page and row division like this could help.

author: ataradov
author_rank: Super Contributor
timestamp: May 29, 2025, 01:37:27 pm
content: I'm not sure about technicalities of erasing already erased page. I personally would count it as a wear cycle.And wear leveling is another common use. If your structure is less than a page in size, you can write it into free pages. In this case you can write 4 or 8 times until you need a erase. To determine where you need to write or read your data, add a counter field to your structure. A place with the highest counter (that is not 0xffffffff) is the last written value. I usually add CRC as well to detect partially written pages.

author: Simon
author_rank: Unknown
timestamp: May 29, 2025, 06:33:22 pm
content: Well the life span of the flash is plenty for what I need, Yes wear leveling is a good idea, I do keep a count of the writes and a basic checksum. I know the SANC has a CRC unit but this seems to be as part of the system and not directly accessible unless I can't find it on the datasheet.

author: ataradov
author_rank: Super Contributor
timestamp: May 29, 2025, 06:40:21 pm
content: CRC is part of the DSU peripheral. It is accessible just like any other peripheral. CRC is very easy to use. Here is the basic blocking example for SAM D21. C21 will be similar with minor adjustments.Code:PM->AHBMASK.reg |= PM_AHBMASK_DSU;PM->APBBMASK.reg |= PM_APBBMASK_DSU;DSU->ADDR.reg = addr;DSU->LENGTH.reg = size;DSU->DATA.reg = 0xffffffff;DSU->STATUSA.reg = DSU->STATUSA.reg;DSU->CTRL.reg = DSU_CTRL_CRC;while (0 == DSU->STATUSA.bit.DONE);if (0 == DSU->STATUSA.bit.BERR)// DSU->DATA.reg contains CRCelse// there was some error

author: Simon
author_rank: Unknown
timestamp: May 30, 2025, 06:50:23 am
content: Yes looks simple enough, but why are you doing DSU->STATUSA.reg = DSU->STATUSA.reg; ? This is to reset the register? each error is signaled with a "1" and a "1" resets it so I think that is it right?

author: ataradov
author_rank: Super Contributor
timestamp: May 30, 2025, 01:38:52 pm
content: Yes, it clears the register. Specifically DONE bit from the last time CRC is used. You can write a constant mask. I think this code comes from a highly optimized bootloader and this was smaller in code size,