Hot!Custom persistent linker script section

Author
jgvicke
Super Member
  • Total Posts : 458
  • Reward points : 0
  • Joined: 2010/09/28 20:18:24
  • Location: 0
  • Status: offline
2015/04/25 23:52:19 (permalink)
0

Custom persistent linker script section

I have an application with a bootloader that will be deployed in the field and will not be updated.
 
In this application I need a hunk of data that will be persistent across reboots. Currently this section will be used for holding exception data, so after the reboot I can log it to my external flash chip. I know there is now the __attribute__((persistent)); tag, but that will not work in my case because I need to have a hunk that will not be initialized in the boot loader.
 
Here is the question, how do I add a section in the linker script that is reserved for my non-initialized data, and how do I define in the code that a structure should reside there. That way I can reserve more room in the linker than I need right now for the structure, and I will have room to grow in the future.
 
Thanks,
John Vickers

PIC32 Helpful Tools I have made:
https://rebrand.ly/PIC32MZ144PinMapping
https://rebrand.ly/PIC32MX100PinMapping

Feel free to email me if you have any suggestions for any of these tools.
#1

19 Replies Related Threads

    timijk
    Super Member
    • Total Posts : 1216
    • Reward points : 0
    • Joined: 2007/11/26 00:30:07
    • Location: Taiwan
    • Status: offline
    Re: Custom persistent linker script section 2015/04/26 00:13:41 (permalink)
    2 (2)
    You can initialize the data with 0xFFFFFFFF, then you can program the data later on.  There might be better solutions anyway.
    #2
    jgvicke
    Super Member
    • Total Posts : 458
    • Reward points : 0
    • Joined: 2010/09/28 20:18:24
    • Location: 0
    • Status: offline
    Re: Custom persistent linker script section 2015/04/26 00:15:51 (permalink)
    0
    As I said in my first post, I need it to not be initialized on reboot so that I can retrieve the exception data stored there. Please read the question before posting.

    PIC32 Helpful Tools I have made:
    https://rebrand.ly/PIC32MZ144PinMapping
    https://rebrand.ly/PIC32MX100PinMapping

    Feel free to email me if you have any suggestions for any of these tools.
    #3
    timijk
    Super Member
    • Total Posts : 1216
    • Reward points : 0
    • Joined: 2007/11/26 00:30:07
    • Location: Taiwan
    • Status: offline
    Re: Custom persistent linker script section 2015/04/26 00:20:43 (permalink)
    0
    I don't know if you are aware of this, when you populate it with 0xFFFFFFFF, it's like blank.
    #4
    jgvicke
    Super Member
    • Total Posts : 458
    • Reward points : 0
    • Joined: 2010/09/28 20:18:24
    • Location: 0
    • Status: offline
    Re: Custom persistent linker script section 2015/04/26 00:23:57 (permalink)
    0
    It is still not addressing the question of how to reserve a block of ram in the linkerscript of both my project and bootloader at the same place in ram, then in the program set a structure to reside at that address.
     
    If I cannot always use the hunk of memory reserved in this way, it doesn't matter what I do in the program, the bootloader will stomp all over it.

    PIC32 Helpful Tools I have made:
    https://rebrand.ly/PIC32MZ144PinMapping
    https://rebrand.ly/PIC32MX100PinMapping

    Feel free to email me if you have any suggestions for any of these tools.
    #5
    timijk
    Super Member
    • Total Posts : 1216
    • Reward points : 0
    • Joined: 2007/11/26 00:30:07
    • Location: Taiwan
    • Status: offline
    Re: Custom persistent linker script section 2015/04/26 02:58:04 (permalink)
    0
    Here is my idea: change the size of kseg1_data_mem in the linker for both bootloader and app
     
    kseg1_data_mem (w!x) : ORIGIN = 0xA0000000, LENGTH = 0x10000   <--- original is 0x20000

     
    and in c program [XC32 C/C++ UG, ch9.7.3],
    #pragma region name="ext_mem" origin=0xA0010000 size=0x10000
    int ext_array[256] __attribute__((region("ext_mem")));

     
    if the init process still wipe out the data, you can use _on_reset() to do something before it [ch9.7.3.4]
    * * *
    another way is to define those data in assembly within the app defined memory region.
    #6
    maxruben
    Super Member
    • Total Posts : 3300
    • Reward points : 0
    • Joined: 2011/02/22 03:35:11
    • Location: Sweden
    • Status: offline
    Re: Custom persistent linker script section 2015/04/26 04:01:28 (permalink)
    0
    Doesn't this work?
    static WORD SomeStruct __attribute__((address(0xA0010000), persistent));

     
    /Ruben
    #7
    Darrell Thayer
    Super Member
    • Total Posts : 58
    • Reward points : 0
    • Joined: 2014/05/12 10:03:47
    • Location: 0
    • Status: offline
    Re: Custom persistent linker script section 2015/04/27 07:05:36 (permalink)
    4 (1)
    Here is what I do for "communicating" between my bootloader and application - PIC32MX795.
     
    Using this reserved RAM:
    • App can tell bootloader to go into "re-flash" mode on reset, allowed reset due to handled exception, and more.
    • Boot can tell App why App is being run: power-up, Watchdog-Test, "code lockup" (Watchdog RST during normal App execution!), exception-handled (info BACK to APP - with exception type & address), and more.
    This linker change reserves a fixed space at the end of RAM for your "private" use (access from boot and App via pointers to this known address - mine is "ORIGIN = 0xA001FFE0"). I only needed 32 bytes, but it could be any size. Note that this RAM is totally ignored by the compiler (as though it does not exist - is not init - is not zeroed). Do note that this "new end of RAM" (as far as the compiler now knows) does effect where the default stack now starts ("grows" from the end of kseg1_data_mem and NOT the end of physical RAM).
     
    kseg1_data_mem (w!x) : ORIGIN = 0xA0000000, LENGTH = 0x1FFE0 /* All RAM, but leaves 32 bytes at end of RAM */
    kseg1_comm_mem (w!x) : ORIGIN = 0xA001FFE0, LENGTH = 0x20 /* separate 32 byte segment - for Boot/App "COMM" */
     
    I do similar things in the linker file with FLASH - to reserve space for a full CRC-32 store. A modified bootloader calculates and writes the CRC32, boot and App can read it.
    #8
    jgvicke
    Super Member
    • Total Posts : 458
    • Reward points : 0
    • Joined: 2010/09/28 20:18:24
    • Location: 0
    • Status: offline
    Re: Custom persistent linker script section 2015/04/27 07:12:19 (permalink)
    0
    This is exactly what I am trying to do, and had something close, but it was not working. Do you have any other reference to kseg1_comm_mem in your linker, or is that line all that is needed?
     
    How do you declare your variable in your code to the known address? Can you give me some sample code?
     
    Thanks,
    John Vickers

    PIC32 Helpful Tools I have made:
    https://rebrand.ly/PIC32MZ144PinMapping
    https://rebrand.ly/PIC32MX100PinMapping

    Feel free to email me if you have any suggestions for any of these tools.
    #9
    Darrell Thayer
    Super Member
    • Total Posts : 58
    • Reward points : 0
    • Joined: 2014/05/12 10:03:47
    • Location: 0
    • Status: offline
    Re: Custom persistent linker script section 2015/04/27 07:57:37 (permalink)
    3.5 (2)
    Here is some code to access the reserved RAM. It will not be touched through an MCU reset. But be warned that if power is cycled, that RAM could have ANYthing in it... so.... if that info is important, at least use some form of Checksum or CRC to validate the data in that RAM. Below I am only using a few special 32 bit "signatures"... that hopefully only have a few chances in about 4.2 billion of happening by chance (as good and a CRC32 !?).
     
    The main idea is that you must know how to use pointers in 'C' (as any 'C' programmer must).  Any decent 'C' tutorial online will show how to code using pointers.
     
    Note that I am only showing use of the first 4 bytes... as a "32 bit signature".... to talk between Boot and App; however, you can use you RAM any way you like. For more info, best would be to use a data structure... and typecast a pointer to the data structure the same way as this simple UINT32. Note that your boot and App code must have the same linker script modification - to reserve the RAM for both to use.
     
    Note that kseg1_data_mem (linker script) is the segment that the compiler already knows to use for all of its RAM allocation. The new kseg1_comm_mem is just the name I gave the reserved RAM. It will show up in your memory map in just one place (Memory Configuration Section of Map file). You access it in your code via its known address (and size) that you gave it.

    Name           Origin       Length
    kseg1_comm_mem 0xa001ffe0   0x00000020

     
    Note that there are various opinions (debates even) of how to reserve "special" RAM & FLASH (like using compiler attributes); however, ... even though linker files can be a bit complicated... linker files/scripts are ALWAYS be able to reserve both RAM and FLASH for every compiler/linker I have come across.
     
    #define BOOT_APP_COMM_RAM_BYTES 32 // 32 bytes of RAM reserved by linker script
    #define BOOT_APP_COMM_RAM_ADDR  0xA001FFE0 // at this address

    #define BOOT_APP_COMM_RAM_BYTES 32 // 32 bytes of RAM reserved by linker script
    #define BOOT_APP_COMM_RAM_ADDR 0xA001FFE0 // at this address

    UINT32 signature_save;

    UINT32 signature_get(void)
    {
        UINT32 sig;
        sig = *((UINT32 *)BOOT_APP_COMM_RAM_ADDR);
        signature_save = sig;
        return sig;
    }
    UINT32 signature_get_saved(void)
    {
        return signature_save;
    }
    void signature_set(UINT32 sig)
    {
       *((UINT32 *)BOOT_APP_COMM_RAM_ADDR) = sig;
    }



    #10
    jgvicke
    Super Member
    • Total Posts : 458
    • Reward points : 0
    • Joined: 2010/09/28 20:18:24
    • Location: 0
    • Status: offline
    Re: Custom persistent linker script section 2015/04/27 19:58:33 (permalink)
    0
    Thanks for you in depth reply, but I must still be doing something wrong. I have set aside a hunk of memory in the linker like this:

        kseg0_data_mem (w!x) : ORIGIN = 0x80000000, LENGTH = 0x7F000
        kseg1_comm_mem (w!x) : ORIGIN = 0x8007F000, LENGTH = 0x1000 /* 0x1000 reserved for non volatile memory */

     
    Then in my c code I have the following:
     

    #define PERSISTANT_MEMORY_ADDRESS 0x8007F000

    typedef volatile struct
    {
        UINT32 ResetRegister;
        UINT8 ExcCode;
        UINT32 ExcAddr;
        bool ExcOccured;
    // UINT16_VAL ExcCheckSum;
    }EXCEPTION_INFO;

    typedef volatile struct
    {
        EXCEPTION_INFO ExceptionInfo;
    }PERSISTENT_MEMORY;

    PERSISTENT_MEMORY * Persistent = (PERSISTENT_MEMORY * )PERSISTANT_MEMORY_ADDRESS;

    //will be called on normal startup or on watchdog or BOR or software reset or on Power-up ....
    void _on_reset (void)
    {
        Persistent->ExceptionInfo.ResetRegister = RCON;
        RCON =0;//clear
    }

     
    When I put a break point in the _on_reset (void) function, ResetRegister is equal to 0x0 before and after the line that should be storing RCON in ResetRegister. I have checked and RCON does have a non-zero value in it. Am I trying to access the struct incorrectly? Any suggestions would be appreciated!
     
    Thanks,
    John Vickers

    PIC32 Helpful Tools I have made:
    https://rebrand.ly/PIC32MZ144PinMapping
    https://rebrand.ly/PIC32MX100PinMapping

    Feel free to email me if you have any suggestions for any of these tools.
    #11
    timijk
    Super Member
    • Total Posts : 1216
    • Reward points : 0
    • Joined: 2007/11/26 00:30:07
    • Location: Taiwan
    • Status: offline
    Re: Custom persistent linker script section 2015/04/27 20:38:20 (permalink)
    0
    Hi John,
    I have the same experience with the _on_reset() problem, what I found out is, the _on_reset is an XC32 feature, _on_reset is called in the _start_up script, crt0.S.
     
    I used the other PIC32 C/C++ compiler within MPIDE, the _on_reset would not be called, because it's commented out.  Btw, the one within MPIDE is  a little bit old, or I should say it's forked.  So the initialization process is a little different to the latest XC32 compiler.
     
    I was planning to do some tests with XC32, but have not setup the board yet...
    #12
    aschen0866
    Super Member
    • Total Posts : 4415
    • Reward points : 0
    • Joined: 2006/01/08 22:18:32
    • Location: San Diego
    • Status: offline
    Re: Custom persistent linker script section 2015/04/27 22:58:20 (permalink)
    0
    jgvicke
    Thanks for you in depth reply, but I must still be doing something wrong. I have set aside a hunk of memory in the linker like this:

        kseg0_data_mem (w!x) : ORIGIN = 0x80000000, LENGTH = 0x7F000
        kseg1_comm_mem (w!x) : ORIGIN = 0x8007F000, LENGTH = 0x1000 /* 0x1000 reserved for non volatile memory */

     
    Then in my c code I have the following:
     

    #define PERSISTANT_MEMORY_ADDRESS 0x8007F000

    typedef volatile struct
    {
        UINT32 ResetRegister;
        UINT8 ExcCode;
        UINT32 ExcAddr;
        bool ExcOccured;
    // UINT16_VAL ExcCheckSum;
    }EXCEPTION_INFO;

    typedef volatile struct
    {
        EXCEPTION_INFO ExceptionInfo;
    }PERSISTENT_MEMORY;

    PERSISTENT_MEMORY * Persistent = (PERSISTENT_MEMORY * )PERSISTANT_MEMORY_ADDRESS;

    //will be called on normal startup or on watchdog or BOR or software reset or on Power-up ....
    void _on_reset (void)
    {
        Persistent->ExceptionInfo.ResetRegister = RCON;
        RCON =0;//clear
    }

     
    When I put a break point in the _on_reset (void) function, ResetRegister is equal to 0x0 before and after the line that should be storing RCON in ResetRegister. I have checked and RCON does have a non-zero value in it. Am I trying to access the struct incorrectly? Any suggestions would be appreciated!
     
    Thanks,
    John Vickers


    What's your cache policy set? Try

    #define PERSISTANT_MEMORY_ADDRESS 0xA007F000

    When you are working with the MZ chip, it is important to understand how cache works and the difference between KSEG0 and KSEG1 addressing.
     
    To do what you want, you don't have to use a custom linker script. All it takes is:

    typedef struct
    {
        UINT32 ResetRegister;
        UINT8 ExcCode;
        UINT32 ExcAddr;
        BOOL ExcOccured;
        UINT16_VAL ExcCheckSum;
    }EXCEPTION_INFO;

    typedef struct
    {
        EXCEPTION_INFO ExceptionInfo;
    }PERSISTENT_MEMORY;

    PERSISTENT_MEMORY __attribute__((coherent, address(0x8007F000), persistent)) persistInfo;

    Make sure you have the exact same definition in both the bootloader and the application.
    #13
    jgvicke
    Super Member
    • Total Posts : 458
    • Reward points : 0
    • Joined: 2010/09/28 20:18:24
    • Location: 0
    • Status: offline
    Re: Custom persistent linker script section 2015/04/28 04:01:39 (permalink)
    0
    I do not know how to check the cache policy, where is it at?
     
    Regardless of which address I use (0xA007F000 or 0x8007F000), when I debug the project and look at the address of the variables, it is at 0x800002CC. This tells me there is something wrong with this line:
     
    PERSISTENT_MEMORY * Persistent = (PERSISTENT_MEMORY * )PERSISTANT_MEMORY_ADDRESS;
     
    The reason I am trying to do this with the linker instead of the persistent attribute is listed in my original post. I would like to reserve room to expand in the future, and once my boot loader is released, I will not be able to allocate additional memory. Obviously the main program will update with when the firmware is flashed, but if the boot loader doesn't know to leave that memory alone, then it will not help.
     
    John Vickers

    PIC32 Helpful Tools I have made:
    https://rebrand.ly/PIC32MZ144PinMapping
    https://rebrand.ly/PIC32MX100PinMapping

    Feel free to email me if you have any suggestions for any of these tools.
    #14
    timijk
    Super Member
    • Total Posts : 1216
    • Reward points : 0
    • Joined: 2007/11/26 00:30:07
    • Location: Taiwan
    • Status: offline
    Re: Custom persistent linker script section 2015/04/28 06:07:23 (permalink)
    0
    I think the compiler is kind of "smart", if you don't use "persistent", the data initialization process will clear the data.  I did some tests...  if you want to define an area in the linker, what I did is
    .commBL :
    {
    _commBL_begin = 0x7000;   //<--- relative address to the beginning of kseg1_data_mem
    . = ALIGN(4);
    _commBL_end = .;
    } >kseg1_data_mem

    so in the C,
    PERSISTENT_MEMORY perMEM __attribute__((persistent,section("commBL")));

    here is the map file
    .commBL 0xa0000000 0x0
    0x00007000 _commBL_begin = 0x7000
    0xa0000000 . = ALIGN (0x4)
    0xa0000000 _commBL_end = .

    the testing C code
    void _on_reset() {
     perMEM.ExceptionInfo.ResetRegister= 0x101;
     perMEM.ExceptionInfo.ExcCode='B';
    return;
    }
     
    void main() {
    // perMEM.ExceptionInfo.ResetRegister == 0x101 here
    // perMEM.ExceptionInfo.ExcCode=='B' here
     
    perMEM.ExceptionInfo.ResetRegister &= 0xFF0;
    perMEM.ExceptionInfo.ExcCode='Z';
    }

     
    -- compiled with XC32 ver 1.34
    #15
    aschen0866
    Super Member
    • Total Posts : 4415
    • Reward points : 0
    • Joined: 2006/01/08 22:18:32
    • Location: San Diego
    • Status: offline
    Re: Custom persistent linker script section 2015/04/28 07:11:13 (permalink)
    0
    jgvicke
    I do not know how to check the cache policy, where is it at?

    Is there a SYS_DEVCON_CacheCoherencySet() call anywhere in your code? And please read this:
    http://ww1.microchip.com/...00001600A.pdf?from=rss
     
    jgvicke 
    Regardless of which address I use (0xA007F000 or 0x8007F000), when I debug the project and look at the address of the variables, it is at 0x800002CC.

    Not sure what you are talking about, but if you use the correct attributes, you should get the right result:

     
    jgvicke  
    The reason I am trying to do this with the linker instead of the persistent attribute is listed in my original post. I would like to reserve room to expand in the future, and once my boot loader is released, I will not be able to allocate additional memory. Obviously the main program will update with when the firmware is flashed, but if the boot loader doesn't know to leave that memory alone, then it will not help.

    Make a union, easy enough?

    typedef struct
    {
        UINT32 ResetRegister;
        UINT8 ExcCode;
        UINT32 ExcAddr;
        BOOL ExcOccured;
        UINT16_VAL ExcCheckSum;
    }EXCEPTION_INFO;

    typedef union
    {
        UINT8 reserve[4096];
        EXCEPTION_INFO ExceptionInfo;
    }PERSISTENT_MEMORY;

    PERSISTENT_MEMORY __attribute__((coherent, address(0x8007F000), persistent)) persistInfo;

     
    #16
    Darrell Thayer
    Super Member
    • Total Posts : 58
    • Reward points : 0
    • Joined: 2014/05/12 10:03:47
    • Location: 0
    • Status: offline
    Re: Custom persistent linker script section 2015/04/28 07:19:24 (permalink)
    0
    It "should" be simple. When you reserve a hunk of RAM in the linker script (at the end of physical RAM), the linker will ensure that RAM does not even "exist". The compiled code will not touch it in any way... even the "C Startup" code that zeroes uninitialized static vars and initialized static vars. If the reserved RAM really did NOT exist, when you use a pointer to access it, you would get an address exception (I think). But is does actually exist... so you can read from it and write to it just fine. We have to use a pointer because we did not define (instantiate) any objects (variables, arrays, structures) at compile time that are to reside in said RAM... otherwise the compiler WOULD try to init that RAM. 
     
    I don't know why one would add the use of the "persistent" attribute to declare data in reserved RAM... when one only needs a pointer to access it? Maybe the persistent attribute is "confusing" the compiler/linker somehow?
     
    I am not savvy about physical vs virtual memory on the PIC32MX (you are on the MX, not the MZ?). I simply modified (shortened) the "data_mem" linker segment and added my reserved segment... both with as "kseg1..." and both starting with 0xa00... as the RAM address.  Here is my map file for my build. You can see that I simply have 0x20 bytes reserved at the end what used to be part of the total "data ram". And I can read/write it without any compiler interference. By the way, I noticed the comment " /* 0x1000 reserved for non volatile memory */"... and I hope we are only talking about RAM info surviving through an MCU reset and not full loss of power. "non volatile" really means retaining data through a full loss of power. RAM "comes up" with random data in it.
     
    As I understand it (quite a limited understanding), using the 0xA00... memory address is directly accessing RAM without the cache. Boot code normally uses these addresses... so they do not have to setup the cache to execute. When we typecast a pointer to 0xA00..., we are bypassing the cache (and any cache "issues"). I read that cache is a major issue with DMA... as DMA controllers only access physical non-cached RAM?
     
    Note that you MUST also reserve the RAM in the same way with any bootloader code (its linker script), otherwise the bootloader will most likely have its stack right on top of your "reserved" RAM.... and de-referencing a pointer to reserved RAM would simply be observing what the boot code put on its stack... not what your app put there before letting/forcing an MCU reset into boot.
    My stack (map file). The linker "smartly" reserves ALL of available RAM to the stack (really big) and it goes from the end of my allocated static vars up to my reserved RAM space (0xa000b788 + 0x14850 = 0x1FFDF)... showing the linker knows to leave my RAM alone.
     
    Dynamic Data-Memory Reservation
    section                    address  length [bytes]      (dec)  Description
    -------                 ----------  -------------------------  -----------
    heap                    0xa000b770              0           0  Reserved for heap      <------ I use NO HEAP
    stack                   0xa000b788        0x14850       84048  Reserved for stack


     
    Memory Configuration
    Name Origin Length Attributes
    kseg0_program_mem 0x9d009490 0x00076a70 xr
    kseg0_crc_mem 0x9d07ff00 0x00000100 r
    exception_mem 0x9d008000 0x00001000
    kseg1_boot_mem 0x9d009000 0x00000490
    kseg0_boot_mem 0x9d000490 0x00000000
    debug_exec_mem 0xbfc02000 0x00000ff0
    config3 0xbfc02ff0 0x00000004
    config2 0xbfc02ff4 0x00000004
    config1 0xbfc02ff8 0x00000004
    config0 0xbfc02ffc 0x00000004
    kseg1_data_mem 0xa0000000 0x0001ffe0 w !x     <---- 0x20 shorter
    kseg1_comm_mem 0xa001ffe0 0x00000020 w !x     <---- 0x20 long
    sfrs 0xbf800000 0x00100000
    configsfrs 0xbfc02ff0 0x00000010
    *default* 0x00000000 0xffffffff

     
    I hope this helps !
    #17
    jgvicke
    Super Member
    • Total Posts : 458
    • Reward points : 0
    • Joined: 2010/09/28 20:18:24
    • Location: 0
    • Status: offline
    Re: Custom persistent linker script section 2015/04/28 09:36:09 (permalink)
    0
    Well, I still didn't get the linker script to work correctly, but the union idea above worked like a charm. So for those looking for something that will work in this manner, here is the code I ended up using:
     
     

    #define PERSISTANT_MEMORY_ADDRESS 0x8007F000

    enum {
        EXCEP_IRQ = 0x00, // Assertion of unmasked hardware or software interrupt signal
        EXCEP_TLBL = 0x02, // Load TLB miss or load TLB hit to page with V = 0
        EXCEP_TLBS = 0x03, // Store TLB miss or store TLB hit to page with V = 0
        EXCEP_AdEL = 0x04, // Load address alignment error.
        EXCEP_AdES = 0x05, // Store address alignment error
        EXCEP_IBE = 0x06, // Instruction fetch bus error.
        EXCEP_DBE = 0x07, // Load or store bus error.
        EXCEP_TRAP = 0x0D, // Execution of a trap (when trap condition is true).
        EXCEP_TLBLExeInhibit = 0x14, // An instruction fetch matched a valid TLB entry that had the XI bit set.
        EXCEP_Watch = 0x17, // A reference to an address that is in one of the Watch registers (fetch)
        EXCEP_MachineCheck = 0x18, // TLB write that conflicts with an existing entry.
        EXCEP_CacheError = 0x1E, // Instruction or data reference detects a cache tag or data error.
    } EXCEPTION_CODE;

    typedef volatile struct
    {
        UINT32 ResetRegister;
        UINT8 ExcCode;
        UINT32 ExcAddr;
        bool ExcOccured;
    // UINT16_VAL ExcCheckSum;
    }EXCEPTION_INFO;

    typedef volatile struct
    {
        EXCEPTION_INFO ExceptionInfo;
    }PERSISTENT_MEMORY;

    typedef union
    {
        UINT8 reserve[4096];
        PERSISTENT_MEMORY Memory;
    }PERSISTENT_MEMORY_UNION;

    PERSISTENT_MEMORY_UNION __attribute__((coherent, address(PERSISTANT_MEMORY_ADDRESS), persistent)) Persistent;

    //will be called on normal startup or on watchdog or BOR or software reset or on Power-up ....
    void _on_reset (void)
    {
        Persistent.Memory.ExceptionInfo.ResetRegister = RCON;
        RCON =0;//clear
    }

     
    Thanks for all the input everyone!
     
    John Vickers

    PIC32 Helpful Tools I have made:
    https://rebrand.ly/PIC32MZ144PinMapping
    https://rebrand.ly/PIC32MX100PinMapping

    Feel free to email me if you have any suggestions for any of these tools.
    #18
    Emcy
    Super Member
    • Total Posts : 564
    • Reward points : 0
    • Joined: 2008/01/09 03:37:06
    • Location: 0
    • Status: offline
    Re: Custom persistent linker script section 2019/04/16 00:52:06 (permalink)
    0
    Hello,
     
    Why do you define PERSISTANT_MEMORY_ADDRESS with 0x80007550 ?
     
    I try to use 0x80000000 but I have compiler error (PIC32MZ2048EFM100 with FreeRTOS) : min value for my project is 0x80007550 => do you know why ?
     
     
    #19
    Emcy
    Super Member
    • Total Posts : 564
    • Reward points : 0
    • Joined: 2008/01/09 03:37:06
    • Location: 0
    • Status: offline
    Re: Custom persistent linker script section 2019/04/16 04:36:17 (permalink)
    0
    jgvicke
    Well, I still didn't get the linker script to work correctly, but the union idea above worked like a charm. So for those looking for something that will work in this manner, here is the code I ended up using:
     
     

    #define PERSISTANT_MEMORY_ADDRESS 0x8007F000

    enum {
        EXCEP_IRQ = 0x00, // Assertion of unmasked hardware or software interrupt signal
        EXCEP_TLBL = 0x02, // Load TLB miss or load TLB hit to page with V = 0
        EXCEP_TLBS = 0x03, // Store TLB miss or store TLB hit to page with V = 0
        EXCEP_AdEL = 0x04, // Load address alignment error.
        EXCEP_AdES = 0x05, // Store address alignment error
        EXCEP_IBE = 0x06, // Instruction fetch bus error.
        EXCEP_DBE = 0x07, // Load or store bus error.
        EXCEP_TRAP = 0x0D, // Execution of a trap (when trap condition is true).
        EXCEP_TLBLExeInhibit = 0x14, // An instruction fetch matched a valid TLB entry that had the XI bit set.
        EXCEP_Watch = 0x17, // A reference to an address that is in one of the Watch registers (fetch)
        EXCEP_MachineCheck = 0x18, // TLB write that conflicts with an existing entry.
        EXCEP_CacheError = 0x1E, // Instruction or data reference detects a cache tag or data error.
    } EXCEPTION_CODE;

    typedef volatile struct
    {
        UINT32 ResetRegister;
        UINT8 ExcCode;
        UINT32 ExcAddr;
        bool ExcOccured;
    // UINT16_VAL ExcCheckSum;
    }EXCEPTION_INFO;

    typedef volatile struct
    {
        EXCEPTION_INFO ExceptionInfo;
    }PERSISTENT_MEMORY;

    typedef union
    {
        UINT8 reserve[4096];
        PERSISTENT_MEMORY Memory;
    }PERSISTENT_MEMORY_UNION;
     

    PERSISTENT_MEMORY_UNION __attribute__((coherent, address(PERSISTANT_MEMORY_ADDRESS), persistent)) Persistent;

    //will be called on normal startup or on watchdog or BOR or software reset or on Power-up ....
    void _on_reset (void)
    {
        Persistent.Memory.ExceptionInfo.ResetRegister = RCON;
        RCON =0;//clear
    }
     

     
    Thanks for all the input everyone!
     
    John Vickers


    Warning : if Persistent vairiable is unused in bootloader code, compiler can delete memory allocation.
    #20
    Jump to:
    © 2019 APG vNext Commercial Version 4.5