• AVR Freaks

simplest table access

Author
MoltenVoltage
New Member
  • Total Posts : 22
  • Reward points : 0
  • Joined: 2008/11/02 22:22:56
  • Location: 0
  • Status: offline
2009/07/09 10:25:12 (permalink)
0

simplest table access

Hi all,

I need to read and write forty-five (45) 16-bit variables to non-volatile memory.  The variables store user-defined programs and will probably updated less than 1000 times in the life of the product.

I have read everything I can find on table read and write and it appears there is no simple way to accomplish this task.

From my understanding, the TBLPAG has 128 separate locations for user memory, then each of those locations has another 32K words.

From my understanding you must write a whole chunk of data at a time, though the exact dimensions of this data block are unclear to me.

My question:
Given the limited amount of data I need to read and write, can I simply use a separate TBLPAG for each variable and just use the first word of that page to store the variable?

Has anyone done this, or come up with some other simple method of managing a limited number of variables in non-volatile memory on the dsPIC33F chips?

Thank you.
post edited by MoltenVoltage - 2009/07/09 11:16:23
#1

11 Replies Related Threads

    nice
    Super Member
    • Total Posts : 1079
    • Reward points : 0
    • Joined: 2004/09/18 11:42:25
    • Location: Germany
    • Status: offline
    RE: simplest table access 2009/07/09 12:15:41 (permalink)
    0
    Given the limited amount of data I need to read and write, can I simply use a separate TBLPAG for each variable and just use the first word of that page to store the variable?

    No. First you must consider that the data is written to FLASH program memory. The highest implemented FLASH program memory address on a 256kB device is 0x02ABFE. Hence only 0, 1 and 2 are possible values for TBLPAG.

    Perhaps the following helps to understand the relation between FLASH memory address, rows, instructions and bytes (each FLASH word address can hold three bytes):

      FLASH memory
      address

      0x00000 ---
      ...       |- first row (64 instructions or 192 bytes)
      0x0007E ---

      0x00080 ---
      ...       |- second row (64 instructions or 192 bytes)
      0x000FE ---

      ...
    From my understanding you must write a whole chunk of data at a time

    No, you can write one program word at a time if the program word is in its erased state. Erasing can only be done in blocks of 8 rows (512 instructions or 1536 Bytes). Changing a program word without prior erasing isn't possible.

    One possible approach:

    Reserve the last 512 instruction of FLASH program memory for storing the values (be sure to tell your compiler / assembler not to use this memory reagion). This gives you 512 / 45 = 11 storing locations for each 16-bit variable (first eleven word adresses for the first variable, next eleven word addresses for the second one and so on). Everytime a variable is updated, use the next empty address. The next empty address can easily be found if the unused upper byte (<23:16>) of the program word is cleared when writing a value (the erased state is '0xFF'). If there is no empty address left for any variable, you have to read all values, erase the block and write them back.

    If one variable changes more often than others, it may be wise to reserve more FLASH adresses for this particular variable. Be sure to check the FLASH endurance of your device. Some dsPIC33F devices only guarantee 100 E/W operations which may be easily exceeded with the approach provided above. Also see the device's errata (some dsPIC33F have a nasty bug with RTSP).


    Best regards,
    Bernd
    post edited by nice - 2009/07/09 12:32:59
    #2
    lbodnar
    Super Member
    • Total Posts : 1148
    • Reward points : 0
    • Joined: 2005/12/18 06:06:09
    • Location: UK
    • Status: offline
    RE: simplest table access 2009/07/09 13:05:26 (permalink)
    0
    Freescale has a writeup about EEPROM emulation in Flash memory. This avoids constant re-writing of the whole page and premature wearing of out the flash.
    I can't remember exactly but I recall Microchip had similar appnote.
    http://www.freescale.com/files/microcontrollers/doc/app_note/AN2302.pdf


    Edit, ah, here it is: http://ww1.microchip.com/downloads/en/AppNotes/01095b.pdf
    post edited by lbodnar - 2009/07/09 13:12:45

    Leo
    #3
    nice
    Super Member
    • Total Posts : 1079
    • Reward points : 0
    • Joined: 2004/09/18 11:42:25
    • Location: Germany
    • Status: offline
    RE: simplest table access 2009/07/09 13:25:08 (permalink)
    0
    And here's the Source Code.

    #4
    Neiwiertz
    Super Member
    • Total Posts : 2094
    • Reward points : 0
    • Joined: 2004/09/01 02:58:52
    • Status: offline
    RE: simplest table access 2009/07/09 14:03:21 (permalink)

    Flying With --|Explorer 16|HardWare|SoftWare|-- Fav(s) Gallery Lists
    #5
    MoltenVoltage
    New Member
    • Total Posts : 22
    • Reward points : 0
    • Joined: 2008/11/02 22:22:56
    • Location: 0
    • Status: offline
    RE: simplest table access 2009/07/09 21:44:56 (permalink)
    0
    Thanks for the feedback everyone - esp. nice

    I had read the EEPROM emulation app note and was hoping (naively apparently) for a simple workaround.

    That app note actually states that table read/write is one of three ways to store non-volatile data:

    "Many applications store nonvolatile information in the
    Flash program memory using table write and read
    operations. Applications that need to frequently update
    this data may have greater endurance requirements
    than the specified Flash endurance for the device.
    The alternate solution of using an external, serial
    EEPROM device may not be appropriate for
    cost-sensitive or pin-constrained applications.
    This application note presents a third alternative that
    addresses these issues."

    I was hoping that table read/write was simpler than the EEPROM emulation, but it appears that they are basically the same thing without the cycling of the data space to reduce the number of writes on a particular data field for EEPROM emulation.

    The chip I am programming says data can be written 10,000 times, but if I need to read out the data an re-write it every time I want to update a single word, then that 10,000 is very misleading.


    #6
    MoltenVoltage
    New Member
    • Total Posts : 22
    • Reward points : 0
    • Joined: 2008/11/02 22:22:56
    • Location: 0
    • Status: offline
    RE: simplest table access 2009/07/22 21:06:16 (permalink)
    0

    ORIGINAL: nice

    Reserve the last 512 instruction of FLASH program memory for storing the values (be sure to tell your compiler / assembler not to use this memory reagion).




    OK, I think I have everything else figured out, except how do you tell the compiler to reserve a specific range of addresses for storing the values?

    CE109 and everything else I can find let the complier choose the location.

    Thank you!
    post edited by MoltenVoltage - 2009/07/22 21:07:20
    #7
    nice
    Super Member
    • Total Posts : 1079
    • Reward points : 0
    • Joined: 2004/09/18 11:42:25
    • Location: Germany
    • Status: offline
    RE: simplest table access 2009/07/23 09:39:32 (permalink)
    0
    Reserve the last 512 instruction of FLASH program memory for storing the values (be sure to tell your compiler / assembler not to use this memory reagion).

    I must correct myself here. Don't use the very last 512 instructions of FLASH memory, since this 8-row erase block contains the configuration words. Erasing this block erases the configuration words, which leads to disaster.

    how do you tell the compiler to reserve a specific range of addresses for storing the values?

    CE109 and everything else I can find let the complier choose the location.

    I would choose an approach very similar to CE109 (array emulationPages), but with a fixed address.

    #define NUMBER_OF_INSTRUCTIONS_IN_PAGE    512

    // NUM_8_ROW_BLOCK_START determines the start address of the reserved region
    // start address = NUM_8_ROW_BLOCK_START * NUMBER_OF_INSTRUNCTIONS_IN_PAGE * 2 
    #define NUM_8_ROW_BLOCK_START  20    
                                                                                               
    // NUM_8_ROW_BLOCKS determines the length of the reserved region
    // reserves NUM_8_ROW_BLOCKS * NUMBER_OF_INSTRUNCTIONS_IN_PAGE instructions
    #define NUM_8_ROW_BLOCKS  1    
                                                
    unsigned char dummy[NUM_8_ROW_BLOCKS * NUMBER_OF_INSTRUCTIONS_IN_PAGE * 2]
       __attribute__ ((space(psv), address(NUM_8_ROW_BLOCK_START * NUMBER_OF_INSTRUCTIONS_IN_PAGE * 2), section("dummy"), noload));


    The section attribute isn't needed, but by adding it the reserved region is easy to identify in the linker output.

    section                    address   length (PC units)   length (bytes) (dec)
    -------                    -------   -----------------   --------------------
    ...
    dummy                       0x5000               0x400           0x600  (1536)
    ...


    Best regards,
    Bernd
    #8
    MoltenVoltage
    New Member
    • Total Posts : 22
    • Reward points : 0
    • Joined: 2008/11/02 22:22:56
    • Location: 0
    • Status: offline
    RE: simplest table access 2009/07/23 11:35:25 (permalink)
    0
    Thank you very much for the response Bernd!

    But wouldn't you need to use:

    __attribute__ ((space(prog), address(NUM_8_ROW_BLOCK_START * NUMBER_OF_INSTRUCTIONS_IN_PAGE * 2), section("dummy"), noload));

    rather than space(psv)

    As I understand it, space(psv) is to reserve space for constants, while space(prog) is used for variables that will be written using table instructions.

    Please correct me if I am wrong.

    - Karl
    #9
    nice
    Super Member
    • Total Posts : 1079
    • Reward points : 0
    • Joined: 2004/09/18 11:42:25
    • Location: Germany
    • Status: offline
    RE: simplest table access 2009/07/23 13:21:58 (permalink)
    0
    Hi Karl,

    As I understand it, space(psv) is to reserve space for constants, while space(prog) is used for variables that will be written using table instructions.

    first of all this difference doesn't matter at all, since the only purpose of dummy is to reserve code space, although you may use this symbol to get the start address of the reserved memory via __builtin_tblpage() and __builtin_tbloffset() at run time. This will work in both spaces.

    In the current implemention of the compiler space(prog) is intended to be used with the fillupper attribute (which allows the 8 uppermost bits of the program memory word to be initialized with a value other than '0'). Accessing this uppermost byte with ordinary C statements isn't possible. Currently there's no difference between the amount of memory allocated with space(prog) and space(psv).

    The reason why I've choosen space(psv) (and perhaps the author of CE109 as well) is safety. It's not guarenteed that future C30 revisions of the compiler will arrange arrays like dummy in space(prog) without using the uppermost byte of the program memory. If such a change occurs, the definition of dummy would only reserve 342 instruction words (1024 / 3), which will break your code. Using space(psv) is safe, because the 16-Bit PIC Hardware has no mechanism to access the uppermost byte of the program memory word via PSV. Therefore the required amount of reserved program space is always guaranteed when using space(psv).

    Best regards,
    Bernd
    post edited by nice - 2009/07/23 15:30:13
    #10
    MoltenVoltage
    New Member
    • Total Posts : 22
    • Reward points : 0
    • Joined: 2008/11/02 22:22:56
    • Location: 0
    • Status: offline
    RE: simplest table access 2009/07/25 09:00:03 (permalink)
    0
    Well after about 40 hours of work I have it all working.

    The final piece of the puzzle was to use the aligned(1024) attribute to make sure the table lines up properly.

    The CE109 example uses 8 64-word arrays with aligned(128).  If you fail to use the aligned function when you set up your own variable, it will not line up on a page and you will pull your hair out.

    Also, no need to tell the compiler where to put the data, just use the name of the array in the tblpage(&ArrayName[0]) function and it will find it automatically.

    Also, if you stick the array at the end of the program memory it takes about 8 times longer to program the chip (assuming you have a fairly short program) so that is another reason to let the compiler choose.

    Thanks again Bernd.  I really appreciate your feedback.
    #11
    aschen0866
    Super Member
    • Total Posts : 4478
    • Reward points : 0
    • Joined: 2006/01/08 22:18:32
    • Location: San Diego
    • Status: offline
    RE: simplest table access 2009/07/25 10:33:06 (permalink)
    0
    ...Currently there's no difference between the amount of memory allocated with space(prog) and space(psv). ...

    Just want to point out that the most significant difference between space(prog) and space(psv) is that the object allocated using the space(prog) attribute can be anywhere in the program memory space, while the object allocated using the space(psv) attribute can't cross the PSV page boundary. If the read access is done via table read, then these two attributes make no difference whatsoever. However, if the __prog__ or __psv__ qualifier is used, then they should go with either space(prog) or space(psv) respectively.
    #12
    Jump to:
    © 2019 APG vNext Commercial Version 4.5