[SAM] "EEPROM" dealings - Page 1
Forum section: electronics / general

author: Simon
author_rank: Unknown
timestamp: December 22, 2021, 03:19:31 pm
content: I've had a look at the sections of the SAMC datasheet that deal with the self writing capability. I gather this is probably the same as the SAMD series.Am I right in that the datasheet's references to writing of the NVM (non volatile memory) apply also to the section dedicated to RWWEE (EEPROM). I see there are some differences but in the two but they seem to not talk much about the RWWEE so I assume the general NVM procedures apply such as "27.6.4.3 NVM Write""27.6.5 NVM User Configuration" refers to selecting how many rows are to be EEPROM. one row is 256 bytes, this correlates with "Table 9-3. SAM C20/C21 RWW Section Parameters" that says the pages are 64 bytes as there are 4 pages to one row (27.6.2 Memory Organization).Where I get confused is: "27.8.3 NVM Parameter" register. Here I can choose how many bytes are in a page. But pages are 64 bytes.... and there is a page write buffer that is limited to one page in that I have to read out 4 pages to erase the 4 page row before I write the one page buffer to a page. This makes the page buffer completely useless as I still have to act like I don't have it and buffer myself in RAM or another EEPROM location the entire row of 4 pages.So as the page buffer is so limited how can I now go around deciding the page size?If I understand correctly I have to write to the RWWEE space directly which will be caught by the buffer so I need to make sure I stay in the same page and then write it to memory when I am done. Further the writing into the buffer is done with another buffer that while visible to me serves no purpose I just need to make sure I stay inside it. So I have a buffer of a buffer, or I guess a 2 word/64 bit window into the buffer at a time. So I have to make sure I do not write data chunks that crosses the 8 byte window boundary or I go from writing in one 8 byte window to writing in another 8 byte window loosing the data that never got written properly......

author: ataradov
author_rank: Super Contributor
timestamp: December 22, 2021, 05:13:11 pm
content: RWEE section is the same exact flash technology as the main flash array. It is just a separate plane that can be written while main array is available for code execution.NVM Parameter is a read-only register with information about the device.You have 256 byte rows, which is the minimum erase unit and then you have 64 byte pages (4 in each row), which are a minimum write unit. But pages also support partial writes, you can always change 1->0, but not the other way around. Typical for flash devices. There is also a limit on maximum 8 writes to a row before a erase is needed, but it is not enforced anywhere in the device, writing more may make data less reliable, but I have not been able to observe that in practice under normal conditions.Page buffer is not for you to temporarily store the data, it is for the flash controller to have all the data at the same time. If you want to update a few bytes in a row you have to buffer them anyway.And none of the things about 8 byte boundaries are correct. You do need to fill and write one page (64 bytes) at a time.

author: Simon
author_rank: Unknown
timestamp: December 22, 2021, 08:29:43 pm
content: You mean the detailed description in the datasheet about the page buffers buffer of 2 words is not true? Yes I understand that the page buffer is for the internal controller. Because of the indirect way it works, while I just write to the memory address space that implicitly sets the buffer up for a page. I am not actually writing to the memory until I use the write command (or the automatic write), so I have to make sure I do everything I want on that page and then write it.Before I do anything I will have to copy out the entire row as I have to erase before writing.

author: ataradov
author_rank: Super Contributor
timestamp: December 22, 2021, 08:47:36 pm
content: The only place I see two words are mentioned is the internal organization of the page buffer, which consists of 64-bit words, but since you are writing one 32-bit word at a time, first half gets buffered until the second half arrives. All this is to say that you should always write the page buffer linearly and all 64 bytes (16 words). Do not write in random non-linear locations.Otherwise the buffer is described as "The page buffer contains the same number of bytes as an NVM page."

author: Simon
author_rank: Unknown
timestamp: December 23, 2021, 03:02:22 pm
content: Right, so basically I will just buffer the 4 pages and then rewrite them one at a time from start to end once I am done.

author: Simon
author_rank: Unknown
timestamp: January 28, 2022, 09:41:17 am
content: Right, I am in the thick of trying toe get it to work now.Code:#define d_eeprom_size 256ul // user EEPROM size in bytes#define d_eeprom_word_size 4u // in bytes#define d_eeprom_row_size ( FLASH_USER_PAGE_SIZE * 4u )#define d_eeprom_words ( d_eeprom_size / d_eeprom_word_size )#define d_eeprom_rows ( d_eeprom_size / d_eeprom_row_size )void read_eeprom_nvv(){uint8_t wordcounter = 0 ;while ( wordcounter < d_eeprom_words ){if ( REG_NVMCTRL_INTFLAG & 0x01 ){nvv.eeprom = register32( FLASH_USER_PAGE_ADDR + wordcounter * d_eeprom_word_size ) ;wordcounter ++ ;}}}If I make d_eeprom_word_size 2 after 2 consecutive reads the chip crashes from what I can tell. I say this because I have a display updating routine running in the background on a 100µs interrupt. it takes 2 clycles to complete a command to the display.If I put a character into my display buffer array it never appears on the screen as before the 2 cycles have occurred the thing has totally crashed it would seem.If I use a word size of 4 bytes it works, I get some gibberish read out onto the display that supposedly came from the EEPROM, as the EEPROM was presumably erased when the chip was programmed it has obviously not actually read the EEPROM an this is simply the contents of the RAM occupied by what should be the EEPROM copied into variables.

author: Simon
author_rank: Unknown
timestamp: January 28, 2022, 03:28:21 pm
content: OK so I have grown up slightly and am now using pointer-y magic:Code:#define d_eeprom_size 256ul // user EEPROM size in bytes#define d_eeprom_word_size 4u // in bytes#define d_eeprom_row_size ( FLASH_USER_PAGE_SIZE * 4u )#define d_eeprom_words ( d_eeprom_size / d_eeprom_word_size )#define d_eeprom_rows ( d_eeprom_size / d_eeprom_row_size )void read_eeprom_nvv(){uint16_t wordcounter = 0 ;uint32_t *p_flashaddress = ( uint32_t * ) FLASH_USER_PAGE_ADDR ;while ( wordcounter < d_eeprom_words ){if (wordcounter == 16 ) pinclr(PB11);// debug codenvv.eeprom = *p_flashaddress ;p_flashaddress += 4 ;wordcounter ++ ;}}So one row is 256 bytes, I am reading in units of 32 bit words, so 64 cycles to be made.The 16th cycle completes (wordcounter at 15).This would be the end of the first 64 byte page of 16 4 byte words (page 0).As soon as I try to read the 17th word which is the first 4 bytes of page 1 the micro crashes as the pin is never turned off.

author: Simon
author_rank: Unknown
timestamp: January 28, 2022, 03:38:33 pm
content: So back to my original version that works - well it gets gone through and out the other side.Code:#define register32(x) ( *(volatile uint32_t * )( x ) )#define d_eeprom_size 256ul // user EEPROM size in bytes#define d_eeprom_word_size 4u // in bytes#define d_eeprom_row_size ( FLASH_USER_PAGE_SIZE * 4u ) //#define d_eeprom_words ( d_eeprom_size / d_eeprom_word_size )#define d_eeprom_rows ( d_eeprom_size / d_eeprom_row_size )void read_eeprom_nvv(){uint16_t wordcounter = 0 ;while ( wordcounter < d_eeprom_words ){if (wordcounter == 63u ) pinclr(PB11);nvv.eeprom = register32( FLASH_USER_PAGE_ADDR + wordcounter * d_eeprom_word_size ) ;wordcounter ++ ;}}

author: ataradov
author_rank: Super Contributor
timestamp: January 28, 2022, 05:22:57 pm
content: You are using pointers wrong: "p_flashaddress += 4" // This will increment the pointer by 16 bytes. Pointers are incremented in units of the pointed data type.

author: Simon
author_rank: Unknown
timestamp: January 28, 2022, 05:44:46 pm
content: right, makes sense, maybe stick to my tried and tested method of wrapping it in a define and calculating it like a function instead of being clever.

author: Simon
author_rank: Unknown
timestamp: January 28, 2022, 10:02:21 pm
content: I suppose the first pointer version fixed will run faster as the address pointer is incremented rather than being calculated in a more long winded way.

author: ataradov
author_rank: Super Contributor
timestamp: January 28, 2022, 10:29:08 pm
content: Or you can do something like this and get readable code:Code:void read_eeprom_nvv(){volatile uint32_t *flash = (volatile uint32_t * ) FLASH_USER_PAGE_ADDR ;for (int i = 0; i < d_eeprom_words; i++)nvv.eeprom = flash;}

author: Siwastaja
author_rank: Super Contributor
timestamp: January 29, 2022, 07:39:55 am
content: The whole appeal of ARM is that everything is memory mapped in single address space so standard C language works without any tricks, special instructions or special accessor macros. Therefore, just write normal C, it's easiest to read. Avoid NIHilims patterns like theregister32macro.

author: Simon
author_rank: Unknown
timestamp: January 29, 2022, 08:14:23 am
content: Quote from: ataradov on January 28, 2022, 10:29:08 pmYes that is much more elegant. It looks like the pointer properties of arrays are used, I didn't think you could do that without a compiler complaint. I mean the whole goal was to treat a memory space like an array.

author: Siwastaja
author_rank: Super Contributor
timestamp: January 29, 2022, 11:41:24 am
content: Almost every project in existence, even the simplest (ignoring hello worlds), use the [] indexing of pointer.Typically like this:Code:int process_data(int* buffer, size_t len){for(size_t i = 0; i < len; i++){... buffer ...}}[] indexing works because compiler knows the type and therefore the size of each array element.This is all in C standard and one of the earliest and most fundamental features of the language, pretty much defining what C is.You can always use pointer arithmetic, too, and remember that even just pointer + and - operations take the size of the type into account, too: meaning, +1 on the pointer does the same as indexing , even if the type is larger than 1 byte.But [] indexing is more readable to most, use it whenever possible.

author: Simon
author_rank: Unknown
timestamp: January 29, 2022, 02:11:23 pm
content: what I mean is a pointer variable is created, but it is then used with an index like an array. I understand arrays, I use them all the time especially when I want to use to math to determine with variable I want.

author: Simon
author_rank: Unknown
timestamp: January 31, 2022, 08:42:23 am
content: If I erase the EEPROM then read it the result should be 11111111111111111....... ?

author: Simon
author_rank: Unknown
timestamp: January 31, 2022, 09:29:44 am
content: The NVM Address bit field in the Address register (ADDR.ADDR) uses 16-bit addressingSo are they saying that the address locations go in 2 bytes rather than 1? I am going in circles clearly not addressing the right location and this is getting silly. The datasheet is so cryptic when with the same amount of words they could have said much more.

author: ataradov
author_rank: Super Contributor
timestamp: January 31, 2022, 05:08:48 pm
content: ADDR register should contain the offset of a 16-bit word, so ADDR must be written the value of a physical address / 2. In your case physical address is FLASH_USER_PAGE_ADDR.You only need ADDR for writes, so it does not matter, as you write entire pages anyway most of the time.This is trivial to test and debug. Just specify whatever address, do the programming, read the device contents using a debugger and see where it was written.

author: Simon
author_rank: Unknown
timestamp: January 31, 2022, 07:37:55 pm
content: i worked it all out in the end, I was using the wrong address for the eeprom, there are two diagrams of memory, one showing eeprom and one RWW section. Totally confusing. Not very well explained but I worked it out and my hunch that given the diagrams the address of the first page moves down as you increase space.That section of the datasheet is truly awful, the only worse stuff I have read for comprehension was my uni modules that were simply put not written in English as most of us understand.

author: Siwastaja
author_rank: Super Contributor
timestamp: January 31, 2022, 07:56:18 pm
content: They indeed seem to have overcomplicated it a bit. And I think the marketing idea to call flash "eeprom" is a huge mistake, it only causes confusion because it's actual lying, EEPROM is EEPROM, it's a distinct technology, which the chip doesn't have. (I know they somewhere call it "eeprom emulation", but some other places just "eeprom". Huge waste of time. Especially since they don't do any eeprom emulation, you have to do it yourself. Which they offer appnotes for, just like every manufacturer.)Fundamentally, the key concepts in flash are:* Erase turns bits to '1'* By writing, those can be only turned to '0'* Erasing is SLOW* Erasing affects large part at once, this is callederase granularity. The term for smallesterasable unitvaries, I like "page".* There might be some limitation on write granularity, too. The term for smallest writable unit varies, too. I like "word".MCU flashusuallycomes with multiple pages (I mean: erasable units) so that you don't need to erase the firmware if you want to just update settings.Some implementations have fairly small page size which is handy, you can update smaller sections of settings / calibration / whatever. Sometimes pages are of different sizes; it makes sense, it's enough to have a bunch of small pages for non-volatile storage of data, but the firmware itself can go into a larger page no problems.Rest is just trying to make sense with the terminology choices and how these fundamental basics are represented in the manuals. I prefer shorter over longer. Surprisingly, ST seems to do better job here. The best I have seen: Nordic Semiconductor, as usual, their register-level datasheets are excellent (same can't be said about SDKs and example code). Fine erase granularity, very simple register interface with no BS, and short datasheet that explains exactly what is necessary, and no more.

author: Simon
author_rank: Unknown
timestamp: January 31, 2022, 08:00:15 pm
content: Things like the address register, they use the term "section" this is a very generic word and it's definition is further back, you have to be really determined to piece together all the snippets. To the NVMC a section is a very defined thing, their wording could have been much clearer with a restatement of the casually given definition further up.The problem is that these data sheets are written by those that know the chip and take their knowledge for granted which means they pass very little on in the datasheet.

author: ataradov
author_rank: Super Contributor
timestamp: January 31, 2022, 11:57:23 pm
content: There will always be a way to misunderstand the datasheet, any of them. I have never seen a "golden" datasheet that is an example of clarity that nobody ever got confused about.Also, use reference code to see how it does things. This usually clarifies it readily.EEPROM here is always used in conjunction with emulation. There are two things that are implemented towards that goal - RWEE section, which is separate from the main flash array and does not block reads from the main flash array when written. And then you have ability to reserve some part of the main flash array via fuses, and it will affect device behaviour, but ultimately it will remain the same flash array.

author: Simon
author_rank: Unknown
timestamp: February 01, 2022, 08:03:06 am
content: I searched for reference code an eventually found some, but really I feel that having to copy how someone else did it means that the datasheet is not serving it's purpose and skips vital detail in writing good code. Anything in the way of app notes from microchip/atmel just talked about the libraries they offer and I'm not even going to try and work out how to invoke those, as soon as I go near supplied code I find that it's and infinite rabbit hole of one bit of code referencing another and soon I am spending time trying to understand the code rather than the peripheral.So it sounds like there are 2 "EEPROM" memories? what is the RWEE section? that is the one I was trying to use at one point. In the end I had to guess that what I was aiming for was the address of the rows working down from the top of the address space of the main flash "section".

author: ataradov
author_rank: Super Contributor
timestamp: February 01, 2022, 08:10:17 am
content: The documentation was pretty clear to me. I had no issues interpreting it. And where it is not clear, it is usually easy enough to setup and experiment and see what happens.There is EEPROM section in the main flash, which size you can setup using User Row setting. The only thing that this size affects on a hardware level is how CRC calculation works. Mostly it is useless, and you can just allocate however much you feel for data storage.Then there is a completely separate chunk of flash called RWEE. This can be written while code is executing from the main flash array. As far as writing goes, it works mostly like the regular flash, but it uses different commands for erase and write.Keep in mind that ADDR specifies an offset into the respective flash memory (main flash or RWEE), and not an absolute address. So, to write the first page of the RWEE memory you need to specify address 0. And which memory is written depends on the command used.

author: Simon
author_rank: Unknown
timestamp: February 01, 2022, 08:40:25 am
content: So what is the purpose of the RWEE section? is this the 4kB on my SAMC21J17 ? The fuse settings let me allocate up to 16kB to "EEPROM" which comes out of the main flash (128 kB in my case so I could have as little as 112kB)

author: ataradov
author_rank: Super Contributor
timestamp: February 01, 2022, 04:55:46 pm
content: You can write RWEE section while program is running from the main flash, so execution of your program is not blocked while emulated EEPROM is written.You can use however much you like for the EEPROM in the main flash, you can completely ignore that user row setting and just keep it disabled. It does not do much of anything.

author: Simon
author_rank: Unknown
timestamp: February 02, 2022, 08:05:29 am
content: OK, so if you read the datasheet, you will find that it confuses the main NVM space allocated to EEPROM emulation with the dedicated write while read space. Sorry but not good enough. It's a mess, you have to make multiple passes at this trying to remember statements that seem innocuous because suddenly later they mean a lot.It calls the RWWEE array EEPROM emulation and it calls the allocable amount of main NWM array EEPROM emulation. I don't actually understand why there are the two sections other than this being a trade off for those that want to store a lot of stuff exceeding the "EEPROM" space so get to use up to 16kB of the main flash space but as this also "emulates EEPROM" suddenly we don't know which bit of space we are taking about.The address register makes it more of a mess because now instead of just sticking the 32 bit address in there of where you want to do something to you have to figure out where this bit is and put it's offset in using the right command......I've spent several days on this, and most of the issues was understanding where exactly am I trying to write to. Much is left to the imagination. No I don't have prior experience, but if all data-sheets are like this I have little chance of getting any.....Next up the utter mess made in the ADC register description.

author: ataradov
author_rank: Super Contributor
timestamp: February 02, 2022, 08:12:55 am
content: All datasheets are confusing in one way or the other. The goal is to not complain (because there won't be a fix), but to train yourself to read and extract the necessary information from what you have. In many cases you need to recognize and mentally skip BS. I personally did not even know that it mention EEPROM that much until this thread forced me to read the datasheet closely. I know that no modern MCU has EEPROM and no modern MCU will ever have true EEPROM, as it is fundamentally incompatible with manufacturing processes. So, anything "EEPROM" would be emulation to a certain extent, so your goal is to figure out to what extent. And it does not take a lot of time to recognize that in case of this device it is almost none, so you can just assume you are working with the flash.And this is the best case scenario. SAM D51 has more of a hardware-driven EEPROM emulation, and it is a total mess. Thankfully you can bypass and not use it.As far as how address is specified - different flash controllers have different APIs, and from a lot of experience, this one is one of the better ones.RWEE section is not present on all devices, it was added later as a way to avoid blocking while flash is written. It probably adds to confusion, but again, it is not that uncommon to have strange flash partitioning. There are some really confusing and complicated schemes out there. And there are good reasons why things are done this way, and you have to figure out a way to live with them.

author: Simon
author_rank: Unknown
timestamp: February 02, 2022, 08:21:17 am
content: I have no knowledge of EEPROM, I don't care what it is in this context and never needed to know, but apparently I have to build on it as an artefact of history to understand the datasheet.As far as I am concerned as a new comer to this stuff I have a micro-controller and it can store stuff when it is powered off, that is all I care about. I don't care for historic terminology that will only help me if I know about stuff that is actually not relevant to the product at hand but gives some a warm fuzzy feelingSo the RWE section or whatever it is called was added when? is this something that I need to be careful about when buying these chips? like was it added after first release as a revision or do all SAMC21...... have it? I wouldn't think that they would make such a significant change so it sounds like we are caught up in history again.

author: ataradov
author_rank: Super Contributor
timestamp: February 02, 2022, 08:28:36 am
content: That's why it is actually useful to know history. A lot of design of modern stuff is directly influenced by things first appearing in the 70s. You can complain about this, but it will not change the facts, so it is much easier to understand why things the way they are. And hardware designers and datasheet authors will assume some familiarity with the industry standards. There are probably more educational books on the topic. The datasheet is a technical document never intended to be understood by people completely unfamiliar with the subject.All C20/C21 have RWW section (size varies with memory variant). Some other similar devices do not (D20, some versions of D21).

author: Siwastaja
author_rank: Super Contributor
timestamp: February 02, 2022, 08:54:05 am
content: In this case,notknowing what EEPROM is, is actually helpful, because the device has no EEPROM.There's nothing fundamentally wrong with that datasheet, it's just a tad more complicated than it needs to be. But it shouldn't take days or weeks to decipher. Just understand the basics of FLASH as I explained in above reply, and decipher their terminology. Find what are the smallest erasable and writable units. Work from there.

author: Simon
author_rank: Unknown
timestamp: February 10, 2022, 08:08:49 am
content: So I've come back to revisit my previous experiment and now armed with which section is actually which I am trying to work with the RWWEE section this time. I see that again things are not quite going to plan. The command to erase the RWWEE section is 0x1A but this is also the start of the previous reserved range of numbers that do nothing. Could it be that the start of that reserved range was meant to be 0x10? Following on from the 0x0F before it? not sure why they didn't have one section of reserved numbers but I suppose it's a case of the datasheet being "assembled" for different chips with similar documentation.Still mystified about it. I suppose the next possibility is that the RWWEE section does not support the automatic page write on writing to the last address? As always vagueness forcing assumptions that one thing applies to another combined with small portions of highly specific wording in the datasheet leave me non the wiser when it is not all spelled out as to which 3 sections of NVM space any statement applies to.I'll probably have to use the main NVM space for now if I can work out how to erase that. I take it the address register must really be set to 0x0 if I want to erase the first RWWEE section? I think the reason things seemed to work with the main NVM is that it starts at 0x00000000 so I will always be using the actual global address in the address register for things like erasure

author: Siwastaja
author_rank: Super Contributor
timestamp: February 10, 2022, 08:34:07 am
content: It's clearly a typo, should be 0x10 as you say.

author: Simon
author_rank: Unknown
timestamp: February 10, 2022, 02:38:43 pm
content: Right so I am back up and running saving data to the main NMW space. But..... if I trigger the write to memory from an interrupt when power down happens it does not retain the data. I saw some vague mention of this online. It is certainly not an issue with power as I retain power for quite some seconds (10 maybe) with numbers on the screen. I turn the backlight off when the interrupt first fires to save power then write to memory, except I don't.Is there a way around this? The only thing I can think of if it literally cannot write to memory from an interrupt is to use the interrupt to turn off anything using power as I planned, then return to the main program with a flag set. The flag variable is constantly tested in the main while loop so given the seconds I have of stored power to the ms I need to save data I should be able to save the data in time.

author: ataradov
author_rank: Super Contributor
timestamp: February 10, 2022, 05:24:04 pm
content: This is just a typo. You can at least download the vendor header files that have all those things enumerated. In most cases if there is a discrepancy between the datasheet and a header file, the header file is correct.But also, what stops you from trying a few things and checking which one works? Even based on the info with a typo, there is only one reasonable assumption here. All you need is test it.I don't understand the question about interrupt stuff. If the write completes in time before the power dies, then the data will be retained. If the write does not have enough time to complete, then it will not be preserved. The write takes time, it is not an instant process.

author: Simon
author_rank: Unknown
timestamp: February 10, 2022, 05:45:36 pm
content: i can't do a write from an interrupt routine. So I use the non maskable interrupt to do housekeeping when power is pulled and using capacitance it saves the data. But if I call my data saving from the interrupt routine it will not work. It does work if I set a flag instead and return to the main program where I see the flag and do a data save.I have found that not always all values are written out in the header files. the files of the atmel start stuff I downloaded did but not the files called by including samc21.h, these tend to be a bit more minimal.

author: ataradov
author_rank: Super Contributor
timestamp: February 10, 2022, 05:59:52 pm
content: There is nothing special about running from the interrupt, so something is wrong with your code. Hard to tell what without looking at the code.

author: Simon
author_rank: Unknown
timestamp: February 10, 2022, 07:49:28 pm
content: Well same code, I can post something tomorrow, the same function to write to the NWM will run from the main program but not from the interrupt routine, so it is not the problem and everything else in the interrupt routine works so it does fire. I am writing to the main memory space not RWWEE, maybe that was partly the point of the RWWEE ?

author: ataradov
author_rank: Super Contributor
timestamp: February 10, 2022, 07:54:35 pm
content: Interrupt code is the same code. Nothing in the MCU state changes significantly when an interrupt is executed.Writing main flash array by the code running from that flash will block execution for the duration of a write. But it should not cause any issues directly, all it will do is make the loop that waits for the flash ready bit run only once - it will block immediately after the command, and execution will unblock when the flash is ready.Run it under the debugger and step though the code. What is the memory contents before and after the flash command is executed?

author: Simon
author_rank: Unknown
timestamp: February 11, 2022, 08:25:16 am
content: Uh, yea, I need to learn to to the debug thing. But as the data is not retained at power on clearly the flashing of the data does not happen and the value I tested with was the first. as soon as I put the write to flash routine in the main program it retains the data.

author: ataradov
author_rank: Super Contributor
timestamp: February 11, 2022, 08:48:38 am
content: You can at least read out the device memory before and after and compare them. This is trivial, just do it.There is no difference between running from the interrupt handler and the regular code. You will have to share your code, I have no idea what is going on.

author: Simon
author_rank: Unknown
timestamp: February 11, 2022, 03:03:53 pm
content: Well I display the numbers store on a screen so I have effectively already done that, inside the interrupt it does not update. Outside of the interrupt it does. Once this project over I'll have time to look at using the debugger.