• AVR Freaks

Hot!Finding the address of a const variable, PIC24FJ64GB004?

Page: 12 > Showing page 1 of 2
Author
AndersG
Super Member
  • Total Posts : 241
  • Reward points : 0
  • Joined: 2008/08/05 04:51:24
  • Location: 0
  • Status: offline
2020/10/09 10:19:57 (permalink)
0

Finding the address of a const variable, PIC24FJ64GB004?

OK. So I need to store just one byte of config data. It probably will be stored once and never changed. The PIC has no EEPROM so I thought I'd put it in program memory. There are examples in the manual, but I am at a loss how to find the address of a const integer (unless I read the map file). Ie:
 
// PIC24FJ64GB004 Family
//
#include <xc.h>
// This word should be in program flash
const int config;

void FlashWrite(int w, char b);
//
// C example using MPLAB C30, from DS39940D-page 61
//
void FlashWrite(int w, char b)
{
    unsigned int offset;
    unsigned long progAddr = 0xXXXXXX; // Address of word to program
    unsigned int progDataL = w; // Data to program lower word
    unsigned char progDataH = b; // Data to program upper byte

    //Set up NVMCON for word programming
    NVMCON = 0x4003; // Initialize NVMCON
    //Set up pointer to the first memory location to be written
    TBLPAG = progAddr>>16; // Initialize PM Page Boundary SFR
    offset = progAddr & 0xFFFF; // Initialize lower word of address
    //Perform TBLWT instructions to write latches
    __builtin_tblwtl(offset, w); // Write to address low word
    __builtin_tblwth(offset, b); // Write to upper byte
    asm("DISI #5"); // Block interrupts with priority < 7
    // for next 5 instructions
    __builtin_write_NVM(); // C30 function to perform unlock
    // sequence and set WR
}

 
How do I find the value to plug into progAddr?
post edited by AndersG - 2020/10/09 10:28:04
#1

35 Replies Related Threads

    AndersG
    Super Member
    • Total Posts : 241
    • Reward points : 0
    • Joined: 2008/08/05 04:51:24
    • Location: 0
    • Status: offline
    Re: Finding the address of a const variable, PIC24FJ64GB004? 2020/10/09 10:25:22 (permalink)
    0
    Or is this the way to do it?
     
    // PIC24FJ64GB004 Family
    //
    #include <xc.h>
    // This word should be in program flash
    const int config;

    void FlashWrite(int w, char b);
    //
    // C example using MPLAB C30, from DS39940D-page 61
    //
    void FlashWrite(int w, char b)
    {
        unsigned int offset;
        unsigned long progAddr = 0xXXXXXX; // Address of word to program
        unsigned int progDataL = w; // Data to program lower word
        unsigned char progDataH = b; // Data to program upper byte

        //Set up NVMCON for word programming
        NVMCON = 0x4003; // Initialize NVMCON
        //Set up pointer to the first memory location to be written
        //TBLPAG = progAddr>>16; // Initialize PM Page Boundary SFR
        TBLPAG = __builtin_tblpage(&config);
        //offset = progAddr & 0xFFFF; // Initialize lower word of address
        offset = __builtin_tbloffset(&config);
        //Perform TBLWT instructions to write latches
        __builtin_tblwtl(offset, w); // Write to address low word
        __builtin_tblwth(offset, b); // Write to upper byte
        asm("DISI #5"); // Block interrupts with priority < 7
        // for next 5 instructions
        __builtin_write_NVM(); // C30 function to perform unlock
        // sequence and set WR
    }

     
    post edited by AndersG - 2020/10/09 10:28:32
    #2
    NorthGuy
    Super Member
    • Total Posts : 6407
    • Reward points : 0
    • Joined: 2014/02/23 14:23:23
    • Location: Northern Canada
    • Status: offline
    Re: Finding the address of a const variable, PIC24FJ64GB004? 2020/10/09 10:36:40 (permalink)
    2 (1)
    EEPROM is much more suitable for this.
     
    If you want to write flash, you need to erase the previous content first. You can only erase in pages. One page is 512 instructions (1024 addresses). You can only erase the whole page. So, you first need to allocate 1024 addresses of program memory at the page boundary, then you need to erase the page. Then you can write the words within the page. Once a word is written, the only way to re-write it is to erase the whole page.
    #3
    NKurzman
    A Guy on the Net
    • Total Posts : 19034
    • Reward points : 0
    • Joined: 2008/01/16 19:33:48
    • Location: 0
    • Status: offline
    Re: Finding the address of a const variable, PIC24FJ64GB004? 2020/10/09 11:10:47 (permalink)
    0
    It is Often convenient to use the last page in the Memory.
    Make sure you hold the entire page.  Either with the linker, or with a variable.  you need _attribute_ to locate the variable.
     __attribute__((address(0x1234567))); 
    the variable should be const, and possibly volatile   
    #4
    T Yorky
    Super (Thick) Member
    • Total Posts : 574
    • Reward points : 0
    • Joined: 2012/08/28 02:07:35
    • Location: UK
    • Status: offline
    Re: Finding the address of a const variable, PIC24FJ64GB004? 2020/10/09 12:33:19 (permalink)
    5 (1)
    Hi NKurzman, not on this type of PIC24. The config is in the last page. 2nd to last if needed.
    #5
    AndersG
    Super Member
    • Total Posts : 241
    • Reward points : 0
    • Joined: 2008/08/05 04:51:24
    • Location: 0
    • Status: offline
    Re: Finding the address of a const variable, PIC24FJ64GB004? 2020/10/09 12:35:28 (permalink)
    4 (1)
    EEPROM is much more suitable for this.
    Absolutely, but this PIC has no EEPROM. So, in this case, I need to reserve an entire page, just to write a single byte or integer? Ie erase the entire page first and then write the value? Hm, I need to rethink this. Perhaps use an SPI EEPROM or fins a PIC that has similar capabilities as this one, but with an EEPROM.
    #6
    ric
    Super Member
    • Total Posts : 28975
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: offline
    Re: Finding the address of a const variable, PIC24FJ64GB004? 2020/10/09 13:02:16 (permalink)
    0
    Answering the two questions:
    Yes and yes.

    I also post at: PicForum
    Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
    NEW USERS: Posting images, links and code - workaround for restrictions.
    To get a useful answer, always state which PIC you are using!
    #7
    dan1138
    Super Member
    • Total Posts : 3998
    • Reward points : 0
    • Joined: 2007/02/21 23:04:16
    • Location: 0
    • Status: offline
    Re: Finding the address of a const variable, PIC24FJ64GB004? 2020/10/09 13:24:55 (permalink)
    0
    AndersG
    OK. So I need to store just one byte of config data. It probably will be stored once and never changed.

    So you are in luck. The PIC24FJ64GB004 has two instruction words in the program flash space that are unusable for anything much at addresses 0x100 and 0x102. These locations are at the start of the Alternate Interrupt Vector Table.
     
    It is possible to store up to six bytes in these two instruction words.
    #8
    ric
    Super Member
    • Total Posts : 28975
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: offline
    Re: Finding the address of a const variable, PIC24FJ64GB004? 2020/10/09 13:32:06 (permalink)
    5 (1)
    "Probably never" is the kicker here.
    If it was "never", then this would be trivial.
    If it "ever" has to be changed, you have to deal with erasing and rewriting the entire page containing it.
     

    I also post at: PicForum
    Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
    NEW USERS: Posting images, links and code - workaround for restrictions.
    To get a useful answer, always state which PIC you are using!
    #9
    Mysil
    Super Member
    • Total Posts : 3952
    • Reward points : 0
    • Joined: 2012/07/01 04:19:50
    • Location: Norway
    • Status: offline
    Re: Finding the address of a const variable, PIC24FJ64GB004? 2020/10/09 13:47:14 (permalink)
    0
    Hi,
    If you ensure that the Flash memory location have value 0xFFFFFF from programming the chip,
    then there is no need to erase a whole page before writing a single value, one time.
    But then you should not do a second write to the same location with a different value.
    If you want to rewrite a small number of times, it may be easier to arrange an array,
    and write the replacement value in the next location.
     
        Mysil
     
    #10
    ric
    Super Member
    • Total Posts : 28975
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: offline
    Re: Finding the address of a const variable, PIC24FJ64GB004? 2020/10/09 13:54:47 (permalink)
    0
    Mysil
    Hi,
    If you ensure that the Flash memory location have value 0xFFFFFF from programming the chip,
    then there is no need to erase a whole page before writing a single value, one time.
    But then you should not do a second write to the same location with a different value.
    If you want to rewrite a small number of times, it may be easier to arrange an array,
    and write the replacement value in the next location.

    and overwrite the old value with 0x000000, and make sure that value is ignored.
     

    I also post at: PicForum
    Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
    NEW USERS: Posting images, links and code - workaround for restrictions.
    To get a useful answer, always state which PIC you are using!
    #11
    dan1138
    Super Member
    • Total Posts : 3998
    • Reward points : 0
    • Joined: 2007/02/21 23:04:16
    • Location: 0
    • Status: offline
    Re: Finding the address of a const variable, PIC24FJ64GB004? 2020/10/09 15:22:15 (permalink)
    5 (1)
    @AndersG,
     
    This is how I would do it:
    /*
     * File:   main.c
     * Author: dan1138
     * Target: PIC24FJ64GB004
     * Compiler: XC16v1.41
     * IDEP MPLABX v5.40
     *
     * Created on October 9, 2020, 1:42 PM
     *
     * Description:
     *
     *                                                          PIC24FJ64GB004
     *               +------------+               +------------+               +------------+               +------------+
     *         <>  1 : RB9/PMPD3  :         <> 12 : RA10       :         <> 23 : RB2/PMPD2  :         <> 34 : RA4/SOSCO  :
     *         <>  2 : RC6/RP22   :         <> 13 : RA7        :         <> 24 : RB3/PMPWR  :         <> 35 : RA9        :
     *         <>  3 : RC7/PMPA0  :         <> 14 : RB14/RP14  :         <> 25 : RC0/AN6    :         <> 36 : RC3/RP19   :
     *         <>  4 : RC8/RP24   :         <> 15 : RB15/RP15  :         <> 26 : RC1/AN7    :         <> 37 : RC4/RP20   :
     *         <>  5 : RC9/RP25   :     GND -> 16 : AVSS       :         <> 27 : RC2/RP18   :         <> 38 : RC5/RP21   :
     *     GND <>  6 : DISVREG    :     3v3 -> 17 : AVDD       :     3v3 -> 28 : VDD        :     GND -> 39 : VSS        :
     *    10uf ->  7 : VCAP       :    MCLR -> 18 : MCLR       :     GND -> 29 : VSS        :     3v3 -> 40 : VDD        :
     *         <>  8 : RB10/PGD2  :         <> 19 : RA0/PMPD7  :         <> 30 : RA2/OSCI   :         <> 41 : RB5        :
     *         <>  9 : RB11/PGC2  :         <> 20 : RA1/PMPD6  :         <> 31 : RA3/OSCO   :     3v3 -> 42 : VBUS       :
     *     3v3 -> 10 : VUSB       :         <> 21 : RB0/PMPD0  :         <> 32 : RA8        :         <> 43 : RB7/PMPD5  :
     *         <> 11 : RB13/PMPRD :         <> 22 : RB1/PMPD1  :         <> 33 : RB4/SOSCI  :         <> 44 : RB8/PMPD4  :
     *               +------------+               +------------+               +------------+               +------------+
     *                                                             TQFP-44
     *
     */

    #pragma config DSWDTPS = DSWDTPS6, DSWDTOSC = LPRC, RTCOSC = LPRC
    #pragma config DSBOREN = OFF, DSWDTEN = OFF, WPFP = WPFP63
    #pragma config SOSCSEL = IO, WUTSEL = LEG, WPDIS = WPDIS
    #pragma config WPCFG = WPCFGDIS, WPEND = WPENDMEM, POSCMOD = NONE
    #pragma config I2C1SEL = PRI, IOL1WAY = OFF, OSCIOFNC = ON
    #pragma config FCKSM = CSDCMD, FNOSC = FRCDIV, PLL96MHZ = OFF
    #pragma config PLLDIV = NODIV, IESO = OFF, WDTPS = PS8192
    #pragma config FWPSA = PR128, WINDIS = OFF, FWDTEN = ON, ICS = PGx1
    #pragma config GWRP = OFF, GCP = OFF, JTAGEN = OFF

    #include <xc.h>
    /*  
    ** Initialize this PIC
    **  
    ** Returns Power On Reset state
    */  
    void PIC_init(void)
    {   
        //
        // Disable all interrupt sources
        //
        __builtin_disi(0x3FFF); /* disable interrupts for 16383 cycles */
        IEC0 = 0;
        IEC1 = 0;
        IEC2 = 0;
        IEC3 = 0;
        IEC4 = 0;
        IEC5 = 0;
        __builtin_disi(0x0000); /* enable interrupts */
        
        CLKDIV = 0x0100;    /* set for 4MHz FRC oscillator */
        
        AD1PCFG = 0xffff;   /* Set for digital I/O */
        
        CM1CON  = 0x0000;
        CM2CON  = 0x0000;
        CM3CON  = 0x0000;
        
        _NSTDIS = 1;        /* disable interrupt nesting */
        
        TRISA   = 0xFFFF;
        TRISB   = 0xFFFF;
        TRISC   = 0xFFFF;
    }
    const __attribute__((noload, space(prog), address(0x00100))) unsigned short Code24bits;
    /*
     * Write one instruction word at location Code24Bits
     */
    #define NUM_INSTRUCTION_PER_ROW 64
    void PutCode24bits(unsigned long Data)
    {
        unsigned int page;
        unsigned int offset;

        page   = __builtin_tblpage(&Code24bits);
        offset = __builtin_tbloffset(&Code24bits);
        NVMCON = 0x4001;
        TBLPAG = page;
        offset &= ~(2*NUM_INSTRUCTION_PER_ROW-1);
        do
        {
            __builtin_tblwtl(offset,0xFFFF);
            __builtin_tblwth(offset,0xFFFF);
            offset += 2;
        } while (offset & (2*NUM_INSTRUCTION_PER_ROW-1));

        offset = __builtin_tbloffset(&Code24bits);
         __builtin_tblwtl(offset,(unsigned short)(Data));
         __builtin_tblwth(offset,(unsigned char )(Data>>16));
         asm("DISI #5");
         __builtin_write_NVM();
    }
    /*
     * Read one instruction word at location Code24Bits
     */
    unsigned long GetCode24bits(void)
    {
        unsigned long result = 0;
        TBLPAG = __builtin_tblpage(&Code24bits);
        result = __builtin_tblrdh(__builtin_tbloffset(&Code24bits));
        result <<= 16;
        result |= __builtin_tblrdl(__builtin_tbloffset(&Code24bits));
        return result;
    }
    /*
     * Test unit
     */
    volatile unsigned long CheckIt;
    int main(void)
    {
        PIC_init();

        CheckIt = GetCode24bits();
        if(CheckIt == 0xFFFFFF)
        {
            PutCode24bits(125);
            CheckIt = GetCode24bits();
        }
        for(;;)
        {
        }
        return 0;
    }

    Remember this code can write to location 0x100 one time after the PIC has been programmed.
     
    Write to that location again a value that tries to change a zero to a one and it will corrupt the stored value.
    post edited by dan1138 - 2020/10/11 13:43:13
    #12
    NorthGuy
    Super Member
    • Total Posts : 6407
    • Reward points : 0
    • Joined: 2014/02/23 14:23:23
    • Location: Northern Canada
    • Status: offline
    Re: Finding the address of a const variable, PIC24FJ64GB004? 2020/10/09 16:19:35 (permalink)
    4 (1)
    dan1138
    The PIC24FJ64GB004 has two instruction words in the program flash space that are unusable for anything much at addresses 0x100 and 0x102.



    That's true, but the erase page is 1024 addresses from 0x0 to 0x400. You don't want to erase that.
    #13
    NorthGuy
    Super Member
    • Total Posts : 6407
    • Reward points : 0
    • Joined: 2014/02/23 14:23:23
    • Location: Northern Canada
    • Status: offline
    Re: Finding the address of a const variable, PIC24FJ64GB004? 2020/10/09 16:25:12 (permalink)
    0
    AndersG
    So, in this case, I need to reserve an entire page, just to write a single byte or integer? Ie erase the entire page first and then write the value? Hm, I need to rethink this. Perhaps use an SPI EEPROM or fins a PIC that has similar capabilities as this one, but with an EEPROM.



    You can reserve the page, and then write only the first word. Next time you write the second word etc. Once the page fills, you can erase it and then start filling it in word by word. When you need, you just find the last written word (which is not 0xffffff). But you need to reserve the whole page because you cannot erase a part of the page.
    #14
    dan1138
    Super Member
    • Total Posts : 3998
    • Reward points : 0
    • Joined: 2007/02/21 23:04:16
    • Location: 0
    • Status: offline
    Re: Finding the address of a const variable, PIC24FJ64GB004? 2020/10/09 16:45:35 (permalink)
    5 (1)
    NorthGuy
    AndersG
    So, in this case, I need to reserve an entire page, just to write a single byte or integer? Ie erase the entire page first and then write the value? Hm, I need to rethink this. Perhaps use an SPI EEPROM or fins a PIC that has similar capabilities as this one, but with an EEPROM.



    You can reserve the page, and then write only the first word. Next time you write the second word etc. Once the page fills, you can erase it and then start filling it in word by word. When you need, you just find the last written word (which is not 0xffffff). But you need to reserve the whole page because you cannot erase a part of the page.



    So you guys are trying to talk the new kid into doing an EEPROM emulator when what he asked for is a simple way to write a byte or word to nonvolatile memory one time over the lifetime of his application.
     
    Talk about advocates for overkill. :)
     
    Why don't you ask him to do a simple thing like finding a sane Republican elected to the US federal government.
    #15
    ric
    Super Member
    • Total Posts : 28975
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: offline
    Re: Finding the address of a const variable, PIC24FJ64GB004? 2020/10/09 19:13:11 (permalink)
    4.5 (2)
    It's the "probably" qualifier on the "only once" that complicates it.
    If he wants to change that to simply "only once", then this is trivial.
     

    I also post at: PicForum
    Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
    NEW USERS: Posting images, links and code - workaround for restrictions.
    To get a useful answer, always state which PIC you are using!
    #16
    NKurzman
    A Guy on the Net
    • Total Posts : 19034
    • Reward points : 0
    • Joined: 2008/01/16 19:33:48
    • Location: 0
    • Status: offline
    Re: Finding the address of a const variable, PIC24FJ64GB004? 2020/10/09 19:46:16 (permalink)
    4 (1)
    If he wants to change it more than once, the only addition is reserving an entire page of flash. And an erase function.
    But it certainly can get more complicated from there if it’s simple isn’t that simple.
    If he uses the align() __attribute__, then it’s not even a concern about where to place it.

    But if he wants to go with an external a EEPROM, those are pretty cheap these days.
    post edited by NKurzman - 2020/10/09 19:48:32
    #17
    AndersG
    Super Member
    • Total Posts : 241
    • Reward points : 0
    • Joined: 2008/08/05 04:51:24
    • Location: 0
    • Status: offline
    Re: Finding the address of a const variable, PIC24FJ64GB004? 2020/10/10 00:23:24 (permalink)
    5 (1)
    So you guys are trying to talk the new kid into doing an EEPROM emulator when what he asked for is a simple way to write a byte or word to nonvolatile memory one time over the lifetime of his application.
     
    Harumph.. "new kid" :) I Joined 2008, but yes, in some respects I feel like a newbie at times. Anyway I greatly appreciate all the answers. I have learned a lot and I hope that this thread might help others as well. But let me explain:
     
    You (I) tend to work with what you know and have. That is, it is easier to use a PIC you happen to have in that big box of sundry PICs than to order another one. Also: This particular design evolved from another one, that indeed used USB, but here I ran into the snag of having to support  two units, a keyboard AND a mouse, but I had already written all of the other protocol code.
     
    First question: There is no other suitable F24-series that has EEPROM?
     
    I could possiby port the code. The requirements are:
    at least 6 5V tolerant pins
    2 output compares
    3 interrupts controlled by the 5V tolerant pins
    SPI
     
    The config value I need to store os 0..1F and I have more than five free pins, so I could just stick a DIL-switch there. That would be an easier solution. Or I could use a small 128-bit SPI EEPROM. Or rewrite the code for a different PIC.
     
    What course I should take depends a lot on how many units I plan to make. If this was something that was to be manufactured in the thousands, then it would be a rewrite, but in this case it will probably end up as a bare PCB for hobbyists to assemble so that factors in.
     
    #18
    T Yorky
    Super (Thick) Member
    • Total Posts : 574
    • Reward points : 0
    • Joined: 2012/08/28 02:07:35
    • Location: UK
    • Status: offline
    Re: Finding the address of a const variable, PIC24FJ64GB004? 2020/10/10 05:33:18 (permalink)
    5 (1)
    "You (I) tend to work with what you know and have." ... now this could work to your advantage. If you learn how to use the self programming you will be able to work with it. grin: grin
    I am unsure as to how much memory you are using, but if you can free up the 2K (actually 1.5K?) then just go with reprogramming (2nd to last page). And if you are intending on using as EEPROM don't worry about wear. Just erase and re-write the same mem location. Start simple.
    Look up in the MLA (MAL?) for the USB internal MSD application this has a useful erase and program function. Think one of the build options is GB004 (just from memory!).
    Give it a go independent of your application then merge.
    T Yorky.
    #19
    NorthGuy
    Super Member
    • Total Posts : 6407
    • Reward points : 0
    • Joined: 2014/02/23 14:23:23
    • Location: Northern Canada
    • Status: offline
    Re: Finding the address of a const variable, PIC24FJ64GB004? 2020/10/10 06:46:06 (permalink)
    3 (2)
    There's no PIC24FJ with EEPROM.
     
    However, if you really need to write only once and it is Ok that you can never re-write it afterwards, then you do not need to erase. Just initialize your word to the erased state - 0xffffff. Any variable located in program memory will do and you can write it as you do in your post #2. This will work once. If you want to do it the second time, you'll have to re-program the PIC. If this is what you wanted, please accept my apologies for bringing up the erasing issue.
     
     
    #20
    Page: 12 > Showing page 1 of 2
    Jump to:
    © 2020 APG vNext Commercial Version 4.5