MMi203: NVEM0
NVEM0 (page 0 NVEM) in the MMi203 is part of the same memory where your application program is stored. In fact, your program and NVEM0 share the same contiguous block of memory, called User Flash. The bigger your program, the less is available for NVEM0, and visa versa. In the MMi203 there is approximately 21K of user flash. The exact amount is reported in the SPLat/PC Module window when you connect to a board. The amount may reduce in future Firmware versions as we use more of the total flash memory to implement new features.
In the following description for the MMi203, the block size is 512 bytes and the endurance is 10,000 writes (this varies from product to product). For the MMi201, the block size is 128 bytes and the endurance is 10,000 writes (this varies from product to product).
The endurance figures given above are the chip maker's worst case ratings over all legal temperatures and supply voltages. They are very conservative but no guarantee is given that the chips can survive more writes. Exceeding the FLASH memory write endurance will be construed as mis-use and void our product warranty.
Boards with language dialect 15 or later implement NVEM0. This page provide details specific to the implementation in the SL99/100, MMi2xx, MS12x, CC16/18, RFD18, and HD8. General NVEM0 documentation is located elsewhere.
NVEM0 in these controllers is implemented using the processor's main FLASH memory. This memory can only be written in fixed size blocks. The block size differs between products.
What we have done, therefore is to create some "smoke and mirrors" to simulate byte-writable memory. That means your program can write to individual bytes, and they will be updated correctly. However, there are downsides:
- Every time you write one byte all the bytes in the same block must also be written. That has a serious consequence for the endurance of the memory. Endurance refers to the unavoidable fact that FLASH memory wears out after a certain number of writes. What this means is that you must be very careful when using NVEM0 not to write to it too often.
Our Firmware is smart enough to know that several bytes being written from one instruction only requires one single block write. Hence, writing a multi-byte record or a floating point number only counts as one "hit" on the endurance, but it does hit every byte in the block. But so does writing one single byte! - Because the processor must write a whole block at a time (actually, erase and then re-write the whole block), writes to NVEM0 are quite slow. Also, there is no way you can know where the block boundaries are relative to your program, so any write operation involving more than 1 byte could cross a boundary and therefore require 2 writes.
Whenever you change you program, and hence its size, the absolute addresses of all your NVEM0 data will change. That means a particular multibyte write operation could suddenly wind up straddling a block boundary and take twice as long. Be very cautious when evaluating the effect of write times on your program.
- NVEM0 is located in the processor's Flash memory, directly after your program. There is a big danger in reading, erasing, modifying and re-writing the block that contains the end of your program and/or any block containing read-only tables. If the power should fail during the write you will not only lose your data, you will also damage your program (or tables) and most likely wreck your product. For this reason this NVEM0 implementation will not permit writing to the memory block that contains the end of your program. If that is attempted the board will suffer a fatal runtime error. You should therefore make sure that there are at least one block's worth bytes of not-written-to NVEM immediately before any NVEM0 that gets written to by your program. The best policy is to place all read-only tables directly after you program, then to pad out with one block of unused NVEM0.
Examples:
;Example 1: Padding with unused space, because I have no read-only tables: NV0BlockSize EQU XXXXX ;<<<<<<<< Fill in the block size for your controller ... Return ;The last program instruction NVEM0 ;Start of NVEM page 0 memory NV0Space XXXXX ;Force new XXXXX byte block NVData ;Start defining any writable NVEM0 areas here ********* ********* ********* ********* ********* ********* ********* ********* ;Example 2: Place read-only lookup tables first, then force a new byte block. NV0BlockSize EQU XXXXX ;<<<<<<<< Fill in the block size for your controller ... Return ;The last program instruction NVEM0 ;Start of NVEM ;Table of sines 0-90', 10' increments (takes 40 bytes) SineTable NV0fNum 0 ; sin(0) NV0fNum 1.74E-1 ; sin(10) NV0fNum 3.42E-1 ; sin(20) NV0fNum 5E-1 ; sin(30) NV0fNum 6.43E-1 ; sin(40) NV0fNum 7.66E-1 ; sin(50) NV0fNum 8.66E-1 ; sin(60) NV0fNum 9.40E-1 ; sin(70) NV0fNum 9.85E-1 ; sin(80) NV0fNum 1 ; sin(90) Padding NV0Space XXXXX ;Force new block ;Any NVEM that gets written during program execution gets placed below this point. ;That would typically be large parameter tables that can be changed by an end-user.