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.

CC2540 flash read write max bytes

Other Parts Discussed in Thread: CC2540

Hi

I am using cc2540, and i want to write nearly 1024 bytes. using HAL API osal_snv_write and custom ID 0x80, but I am not sure how can I write or how much data I can write in ID 0x80

is it correct

#define DATA_LEN 2014

{

char data[1024];

.....

.....

VOID osal_snv_write(BLE_NVID_CUST_START, DATA_LEN,
&data);

or should I divide into segments if so then how much data can be write in one single NV ID (Customer NV Items - Range  0x80 - 0x8F )

Regards

Harshit

  • Hi Harshit,

    If you look at the signature for osal_snv_write (BLE SDK 1.4.1) you will notice:

    #if defined(OSAL_SNV_UINT16_ID)
      typedef uint16 osalSnvId_t;
      typedef uint16 osalSnvLen_t;
    #else
      typedef uint8 osalSnvId_t;
      typedef uint8 osalSnvLen_t;
    #endif
    
    uint8 osal_snv_write( osalSnvId_t id, osalSnvLen_t len, void *pBuf);

    But that aside, the SNV pages are only 2kB in size, so it really is not recommended to store big arrays there, as the SNV will be filled up, and very often the SNV driver would have to switch pages and erase the previous page which takes a lot of power and also can disrupt the BLE connection.

    If you want to log data and it's not more than ~20kB, you can make arrays

    #include "hal_flash.h"
    
    // Convert apparent address of XDATA-mapped flash to a flash page.
    // 0x800 bytes per page, mapping starts at 0x8000, Bank 1 starts at page 16.
    // From linker file:
    // // Then the segment with addresses as put in the hex file (flash bank 1)
    // -P(CODE)XDATA_ROM_C_FLASH=0x18000-0x1FFFF
    #define XDATA_CONST_PAGE(addr)  ((((unsigned int)addr >> 11) & 0xF) + 16)
    // Find offset into a page
    #define XDATA_CONST_OFFSET(addr) ((unsigned int)addr & 0x7FF)
    // Generate Flash Write address for flash controller
    #define XDATA_CONST_WRITE_ADDR(addr)  ((XDATA_CONST_PAGE(myArrayOne) << 9) + (XDATA_CONST_OFFSET(myArrayOne) >>2))
    
    
    #pragma data_alignment=2048
    const __root uint8 myArrayOne[2048] = {0xBA, 0xAB};
    
    #pragma data_alignment=2048
    const __root uint8 myArrayTwo[2048] = {0xBA, 0xAB};
    
    void someFunc()
    {
      uint8 myTestArray[] = "This is a joke, right?";
      
      if ( *(uint16 *)myArrayOne == 0xABBA ) // Erase and write on first run-through after re-programming.
      {
        HalFlashErase(XDATA_CONST_PAGE(myArrayOne));
        // Can only write 4 bytes at a time, so add extra word if array to be written % 4 != 0.
        HalFlashWrite(XDATA_CONST_WRITE_ADDR(myArrayOne),
                      myTestArray,
                      (sizeof(myTestArray) >> 2) + (sizeof(myTestArray)&0x3?1:0));
      }
    }

    These arrays will be placed in Bank 1, because that's where CONST data is placed. This is then mapped to RAM starting at address 0x8000.

    Each of the arrays is aligned at 2048 because that's the page size on this chip, and you can only ever erase entire pages in one go. This is also why each array is 2kB - because otherwise the linker might place other vital CONST in the same page that you just erased.

    You can look at the memory via the watch window, adding the array, or LogicalCode in the memory view, starting at 0x18000.

    Best regards,
    Aslak

  • Hi Aslak,

    Thanks for your quick reply, it actually clear my concept on FLASH read write :)!!

    But I have some doubts,

    1. in IAR const will always be stored in BANK1 ?  and if I use this code

    Aslak N. said:
    #pragma data_alignment=2048 const __root uint8 myArrayOne[2048] = {0xBA, 0xAB}; #pragma data_alignment=2048 const __root uint8 myArrayTwo[2048] = {0xBA, 0xAB};

    there some possibility that in next reboot memory address will be change and that I will not be able to retrieve last log that I stored, so to solve this I have to  use logical address like 0x18000 (BANK1) ?

    HalFlashErase(XDATA_CONST_PAGE(0x18000));  // To Erase data on BANK1 (PAGEID 16)
    
    HalFlashWrite(XDATA_CONST_WRITE_ADDR(0x18000),
    
                     myTestArray,
    
                     (sizeof(myTestArray) >> 2) + (sizeof(myTestArray)&0x3?1:0));

    is this correct ?

    2. Again, To store data on BANK 2 ... 7 should I use Logical address ? like in case on BANK1 you said CONST data store here.

    HalFlashErase(XDATA_CONST_PAGE(0x28000));   // To Erase data on BANK2 (PAGEID 32)
    
    HalFlashWrite(XDATA_CONST_WRITE_ADDR(0x28000),
    
                     myTestArray,
    
                     (sizeof(myTestArray) >> 2) + (sizeof(myTestArray)&0x3?1:0));

    is this correct ?

    3.  To Store data more then 2KB do I need to switch PAGE ID like first 2Kb i will call HalFlashErase() and HalFlashWrite() then again for next 2KB buffer i'll call HalFlashErase() HalFlashWrite again and so on..  ,

    or HalFlashErase() and HalFlashWrite() will calculate internally I just need to call one time ?

    BR

    Harshit

  • Hi,

    1. Yes, there is some chance that when you re-compile your firmware, this will be moved around. However, that is not a problem as long as you refer to the arrays by symbol name.

    It will be stored in Bank 1 as long as the linker file is configured this way.

    2. To use other banks, you must 1) reserve some space in the linker file, and 2) use HalFlashRead to read the data, as it will not any more be mapped always to XDATA.

    The defines I made only work for bank 1 + XDATA-address for the arrays and do not accept logical address. Please see the documentation for HalFlashRead/Write/Erase for how to do this. You can also look at osal_snv.c which uses these.

    You can do like the SNV driver does:

    /** Linker file addition **/
    // Internal flash used for My Logging address space.
    // ---------------------------
    //
    // Address range for HAL_FLASH_PAGE_SIZE == 2048
    -D_MY_ADDRESS_SPACE_START=0x68000
    -D_MY_ADDRESS_SPACE_END=0x6FFFF
    //
    
    -Z(CODE)MY_ADDRESS_SPACE=_MY_ADDRESS_SPACE_START-_MY_ADDRESS_SPACE_END
    
    /** Declaration in some .c file **/
    #pragma location="MY_ADDRESS_SPACE"
    __no_init uint8 _myFlashBuf[16 * 2048UL];
    #pragma required=_myFlashBuf
    
    /** Result in map file **/
    MY_ADDRESS_SPACE
      Relative segment, address: CODE 00030000 - 00037FFF (0x8000 bytes), align: 0
      Segment part 38.            Intra module refs:   SimpleBLEPeripheral_Init
               ENTRY                   ADDRESS         REF BY
               =====                   =======         ======
               _myFlashBuf             00030000 
    

    I now see that I have a mistake in the #define for XDATA_CONST_WRITE_ADDR. It should of course refer to "addr".

    Anyway, as as continuation of the above, you can write to this location via:

      myBufAddr = (uint32)_myFlashBuf;
      
    #define GET_FLASH_PAGE(bank, addr) ((((unsigned int)addr >> 11) & 0xF) + 16 * bank)
    #define GET_FLASH_PAGE_OFFSET(addr) ((unsigned int)addr & 0x7FF)  
    #define GET_FLASH_WRITE_ADDR(bank, addr)  ((GET_FLASH_PAGE(bank, addr) << 9) + (GET_FLASH_PAGE_OFFSET(addr) >>2))
    
      HalFlashWrite(GET_FLASH_WRITE_ADDR(6, myBufAddr),
                  myTestArray,
                  (sizeof(myTestArray) >> 2) + (sizeof(myTestArray)&0x3?1:0));

    3. There is 32 kb available in Bank 1, so you can make more than one 2kB array for data, and erase each 2kB block in isolation.

    Best regards,
    Aslak

  • Hi Aslak,

    Thanks again, my problem is solved :) !

    and just last Question. If I use or define Address range in linker file, how can I check that that range is not used by other BLE lib code or some other code .?

    like I found BANKED_CODE used in .map file and in linker.

    -P(CODE)BANKED_CODE=_CODE_START-_CODE_END,[(_CODEBANK_START+_FIRST_BANK_ADDR)-(_CODEBANK_END+_FIRST_BANK_ADDR)]*_NR_OF_BANKS+10000 // Setup bank-switched segments.

    BR

    Harshit

  • Hi Harshit


    I just wanted to know how to assign PAGE to HalFlashErase/Write how to do that can you give me some information or if there is any document which describes regarding all the required parameters for HalFlash that will be very helpful.

    I am using Bank5, and I have changed in the linker files and addresses also reserved,I am not getting how to assign Page numbers to it.


    With Thanks and regards

    Jayaraj
  • Hi Jayaraj,

    I also couldn't found any document related to HalFlash memory, so I check datasheet and API ref in code.

    and conversion for page id, memory add and offset (pls check above post)

    #define GET_FLASH_PAGE(bank, addr) ((((unsigned int)addr >> 11) & 0xF) + 16 * bank)
    #define GET_FLASH_PAGE_OFFSET(addr) ((unsigned int)addr & 0x7FF)  
    #define GET_FLASH_WRITE_ADDR(bank, addr)  ((GET_FLASH_PAGE(bank, addr) << 9) + (GET_FLASH_PAGE_OFFSET(addr) >>2))
    

    and in hal_flash.h you can find API Ref and parameter to pass in HalFlash api.