This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

How to read/write Info page at CC1310 like Smart RF flash programmer 2

Other Parts Discussed in Thread: CC1310

Hi

    How to read/write Info page at CC1310 base on RTOS 2.1.6  , just  like Smart RF flash programmer 2 control the info page.

Lin Kejian

  • Hi,

    what you see on the info page, is the customer configuration (CCFG) section. It is physically located in the last flash page, but also memory mapped to the CCFG module. Do you want to access the CCFG from within a running TI-RTOS application? Here is a example code snippet for read access:

    // Access the CCFG_O_EXT_LF_CLK in the CCFG section
    #include <inc/hw_ccfg.h>
    
    uint32 value = (uint8*)(CCFG_BASE + CCFG_O_EXT_LF_CLK)
    
    
    // Alternative method
    #include <inc/hw_ccfg.h>
    #include <inc/hw_ccfg_simple_struct.h>
    
    extern const ccfg_t __ccfg;
    uint32 value = __ccfg.CCFG_EXT_LF_CLK;
    
    

    Please refer to section 9.1 in the Technical Reference Manual for further details.

    Write access is usually done during application build. Please refer to the ccfg.c file to see how this works. It creates a struct in the section ".ccfg" which is placed at the correct address by the linker script. Writing to the CCFG at application run-time requires more work. Please find attached an example that demonstrates write access to flash from TI-RTOS in general.

    [Update] flashdemo_v1.1.zip contains additions and fixes that were reported during this thread. It is still based on TI-RTOS 2.16.

    flashdemo_v1.1.zip

  • Richard,

    Gary posted on the forum an example that demonstrates another mechanism for writing to flash called NVS. Can you explain the pros and cons of the two approaches? In particular, will both of them work under TI-RTOS?

    Thanks, Sivan Toledo
  • The NVS driver is not officially released yet. It's there in TI-RTOS, but I don't know how much functionality is implemented and whether it works reliable. The NVS driver allows you to organize your memory in blocks and provides an abstraction layer for read and write operations. A block may be smaller than a page. In that case, the NVS driver preserves memory on the same page and outside of the block by copying it into a scratch area in RAM, merging old and new content there and writing everything back to the original page.

    Feel free to try it out and judge yourself whether it fits into your application.
  • Thanks a lot Richard, I now understand. I see the utility of the functionality in the NVS driver, but for my needs the existing flash driver is good enough.

    Thanks, Sivan
  • Richard W. said:

    Hi,

    what you see on the info page, is the customer configuration (CCFG) section. It is physically located in the last flash page, but also memory mapped to the CCFG module. Do you want to access the CCFG from within a running TI-RTOS application? Here is a example code snippet for read access:

    // Access the CCFG_O_EXT_LF_CLK in the CCFG section
    #include <inc/hw_ccfg.h>
    
    uint32 value = (uint8*)(CCFG_BASE + CCFG_O_EXT_LF_CLK)
    
    
    // Alternative method
    #include <inc/hw_ccfg.h>
    #include <inc/hw_ccfg_simple_struct.h>
    
    extern const ccfg_t __ccfg;
    uint32 value = __ccfg.CCFG_EXT_LF_CLK;
    
    

    Please refer to section 9.1 in the Technical Reference Manual for further details.

    Write access is usually done during application build. Please refer to the ccfg.c file to see how this works. It creates a struct in the section ".ccfg" which is placed at the correct address by the linker script. Writing to the CCFG at application run-time requires more work. Please find attached an example that demonstrates write access to flash from TI-RTOS in general.

    (Please visit the site to view this file)

    Hi Richard,

    I ran your example and it worked well.

    Now, I would like to stored a whole page, instead of the led struct.

    I made the following changes:

    /*
    The page in SRAM. It is used during
    run-time.
     */
    uint8_t pageInRam[FLASH_PAGE_SIZE];
    
    /*
    The same page in FLASH.
    It is linked automatically into the .flashdata section and initialized
    for the first use.
     */
    #pragma DATA_SECTION(pageInFlash, ".flashdata");
    const uint8_t pageInFlash[FLASH_PAGE_SIZE];

    Then, my test is the following:

        memset(pageInRam, 0xAA, sizeof(pageInRam));
        updateMemoryInFlash((void *)pageInFlash, pageInRam, sizeof(pageInRam));
    
        memset(pageInRam, 0x00, sizeof(pageInRam));
        memcpy(pageInRam, pageInFlash, sizeof(pageInRam));

    These are the only changes I did in the example.

    The code compiles without any error, but I can't run the debbuger with it. The button remains "disabled".

    Can you help me?

  • Hi,

    does your application start? Can you step-debug? At which line does the application fail?

    Does it work when you lock the interrupts before calling updateMemoryInFlash()?

    #include <ti/sysbios/knl/hal/Hwi.h>
    
    uint32_t previousState = Hwi_lock();
    updateMemoryInFlash((void *)pageInFlash, pageInRam, sizeof(pageInRam));
    Hwi_restore(previousState);
  • Richard W. said:

    Hi,

    does your application start? Can you step-debug? At which line does the application fail?

    Does it work when you lock the interrupts before calling updateMemoryInFlash()?

    #include <ti/sysbios/knl/hal/Hwi.h>
    
    uint32_t previousState = Hwi_lock();
    updateMemoryInFlash((void *)pageInFlash, pageInRam, sizeof(pageInRam));
    Hwi_restore(previousState);

    It wasn't even starting.

    Anyway, I changed from:

    #pragma DATA_SECTION(pageInFlash, ".flashdata");
    const uint8_t pageInFlash[FLASH_PAGE_SIZE];

    to:

    #pragma DATA_SECTION(pageInFlash, ".flashdata");
    const uint8_t pageInFlash[FLASH_PAGE_SIZE] = { 0 };

    I am not sure why, but now it is working.

  • Hi Richard,

    Everything is working great here.

    I modified the example to write and read all pages from the 6th to the 31th.

    I only have one more doubt.

    In your example you use memcpy() to read from the flash.

    I noted that the writing function have a "protection":

        /* Disable flash cache */
        VIMSModeSet(VIMS_BASE, VIMS_MODE_DISABLED);
        while (VIMSModeGet(VIMS_BASE) != VIMS_MODE_DISABLED);



    // CODE HERE

    /* Re-enable flash cache */ VIMSModeSet(VIMS_BASE, VIMS_MODE_ENABLED);

    Is it not necessary for the reading?
    Something like that:

        /* Disable flash cache */
        VIMSModeSet(VIMS_BASE, VIMS_MODE_DISABLED);
        while (VIMSModeGet(VIMS_BASE) != VIMS_MODE_DISABLED);
        
        memcpy(pageInRam, &pageInFlash[addr], sizeof(pageInRam));
        
        /* Re-enable flash cache */
        VIMSModeSet(VIMS_BASE, VIMS_MODE_ENABLED);

    In addition, I found another example which have even more "protections":

        /* Disable the cache */
        VIMSModeSet(VIMS_BASE, VIMS_MODE_DISABLED);
        while(VIMSModeGet(VIMS_BASE) != VIMS_MODE_DISABLED);
                  
        /* Make sure that sector isn't write protected. */
        result = FlashProtectionGet(SECTOR_TO_ERASE_START_ADDR);
        if(result == FLASH_WRITE_PROTECT)
        {
            while (1);
        }
                    
        /* Disable all interrupts when accessing the flash */
        CPUcpsid();
    
    
        // CODE HERE
    
    
        CPUcpsie();   
    
        /* Re-enable the cache */
        VIMSModeSet(VIMS_BASE, VIMS_MODE_ENABLED);
    
    

    Is it also necessary?

    Thank you in advance!

  • Hi,

    it is good behavior to disable interrupts. An ISR during erase/write operations would result in bus fault. If write protection must be checked depends on the application. A generic flash function should of course do that. For this simple example, it is not necessary because we can guarantee that all pages are writable.

    I have updated the above example with interrupt locking and line buffer protection.

  • Richard W. said:

    Hi,

    it is good behavior to disable interrupts. An ISR during erase/write operations would result in bus fault. If write protection must be checked depends on the application. A generic flash function should of course do that. For this simple example, it is not necessary because we can guarantee that all pages are writable.

    I have updated the above example with interrupt locking and line buffer protection.

    Hi Richard,

    Thank you for the support.

    I have yet another question.

    In the examples that come with CC1310, the SECTIONS is defined in the .cmd file as:

    SECTIONS
    {
        .text           :   > FLASH
        .const          :   > FLASH
        .constdata      :   > FLASH
        .rodata         :   > FLASH
        .cinit          :   > FLASH
        .pinit          :   > FLASH
        .init_array     :   > FLASH
        .emb_text       :   > FLASH
        .ccfg           :   > FLASH (HIGH)
    
    #ifdef __TI_COMPILER_VERSION__
    #if __TI_COMPILER_VERSION__ >= 15009000
        .TI.ramfunc     : {} load=FLASH, run=SRAM, table(BINIT)
    #endif
    #endif
        .data           :   > SRAM
        .bss            :   > SRAM
        .sysmem         :   > SRAM
        .stack          :   > SRAM (HIGH)
        .nonretenvar    :   > SRAM
    }

    In the flash example I am using it is defined as:

    SECTIONS
    {
        .text           :   > FLASH_APPL
        .const          :   > FLASH_APPL
        .constdata      :   > FLASH_APPL
        .rodata         :   > FLASH_APPL
        .cinit          :   > FLASH_APPL
        .pinit          :   > FLASH_APPL
        .init_array     :   > FLASH_APPL
        .emb_text       :   > FLASH_APPL
        .flashdata      :   > FLASH_DATA
        .ccfg           :   > FLASH_CCFG (HIGH)
    
        .data           :   > SRAM
        .bss            :   > SRAM
        .sysmem         :   > SRAM
        .stack          :   > SRAM (HIGH)
        .nonretenvar    :   > SRAM
    }

    Where are FLASH, FLASH_APPL or FLASH_DATA defined?

    What are the consequences of not having the code below in the SECTIONS?

    #ifdef __TI_COMPILER_VERSION__
    #if __TI_COMPILER_VERSION__ >= 15009000
        .TI.ramfunc     : {} load=FLASH, run=SRAM, table(BINIT)
    #endif
    #endif

  • Hi,

    Mad River said:
    Where are FLASH, FLASH_APPL or FLASH_DATA defined?

    They are defined by the MEMORY directive:

    MEMORY
    {
        /* Application stored in and executes from internal flash */
        FLASH_APPL (RX) : origin = FLASH_APPL_ADDR, length = FLASH_APPL_SIZE
        /* User-defined data section in flash */
        FLASH_DATA (RX) : origin = FLASH_DATA_ADDR, length = FLASH_DATA_SIZE
        /* CCFG data */
        FLASH_CCFG (RX) : origin = FLASH_CCFG_ADDR, length = FLASH_CCFG_SIZE
        /* Application uses internal RAM for data */
        SRAM (RWX) : origin = RAM_ADDR, length = RAM_SIZE
    }

    If you have questions regarding linker command files in the TI toolchain, have a look into the ARM Assembly Language Tools User's Guide.

    Mad River said:

    What are the consequences of not having the code below in the SECTIONS?

    #ifdef __TI_COMPILER_VERSION__
    #if __TI_COMPILER_VERSION__ >= 15009000
        .TI.ramfunc     : {} load=FLASH, run=SRAM, table(BINIT)
    #endif
    #endif

    There might be some functions in the SDK that must be placed in the RAM. Not having this section would then result in a linker error. I cannot tell you whether there actually exist such functions or not. But if you want to be sure, please ask in the TI-RTOS forum. Please note that in newer board files these ifdefs are omitted and the section .Ti.ramfunc is always included.