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
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.
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.
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.