CC2651R3: Assignment of multirole task stack to GPRAM section for CC2651R3 leads to boot problems

Part Number: CC2651R3
Other Parts Discussed in Thread: SYSCONFIG

Hi, 

 

Our application is tailored around the multirole application from TI simplelink BLE SDK v7.10.2.23.

I want to reconfigure the cache as GPRAM for the CC2651R3 in order to free some SRAM.

I have followed the necessary and can see the configured GPRAM section in the memory allocation window. However, I can not assign the multirole task stack buffer to the GPRAM block.

static __attribute__((section( ".TaskStacks"))) uint8_t mrTaskStack[MR_TASK_STACK_SIZE];

In case I do this, the application boots up successfully after cold reset (mass erase and boot up for first) and advertises as expected. For all subsequent warm resets, the application does not boot up, essentially I see no advertisement.

 

I attach the linker command file for your reference and the .map file.

 

/*******************************************************************************
 * CCS Linker configuration
 */

/* Retain interrupt vector table variable                                    */
--retain=g_pfnVectors
/* Override default entry point.                                             */
--entry_point ResetISR
/* Suppress warnings and errors:                                             */
/* - 10063: Warning about entry point not being _c_int00                     */
/* - 16011, 16012: 8-byte alignment errors. Observed when linking in object  */
/*   files compiled using Keil (ARM compiler)                                */
--diag_suppress=10063,16011,16012

/* The following command line options are set as part of the CCS project.    */
/* If you are building using the command line, or for some reason want to    */
/* define them here, you can uncomment and modify these lines as needed.     */
/* If you are using CCS for building, it is probably better to make any such */
/* modifications in your CCS project and leave this file alone.              */
/*                                                                           */
/* --heap_size=0                                                             */
--stack_size=1024
/* --library=rtsv7M3_T_le_eabi.lib                                           */

/* The starting address of the application.  Normally the interrupt vectors  */
/* must be located at the beginning of the application. Flash is 128KB, with */
/* sector length of 4KB                                                      */
/*******************************************************************************
 * Memory Sizes
 */
#define FLASH_BASE   0x00000000
#define GPRAM_BASE   0x11000000
#define RAM_BASE     0x20000000

#define FLASH_SIZE   0x00058000
#define GPRAM_SIZE   0x00002000
#define RAM_SIZE     0x00008000

#define RTOS_RAM_SIZE           0x0000012C

/*******************************************************************************
 * Memory Definitions
 ******************************************************************************/

/*******************************************************************************
 * RAM
 */

#define RAM_START      RAM_BASE

#ifdef ICALL_RAM0_START
  #define RAM_END      (ICALL_RAM0_START - 1)
#else
  #define RAM_END      (RAM_BASE + RAM_SIZE - 1)
#endif /* ICALL_RAM0_START */

/* For ROM 2 devices, the following section needs to be allocated and reserved */
#define RTOS_RAM_START RAM_BASE
#define RTOS_RAM_END   (RAM_BASE + RTOS_RAM_SIZE - 1)

/*******************************************************************************
 * Flash
 */

#define FLASH_START                FLASH_BASE
#define WORD_SIZE                  4

#define PAGE_SIZE                  0x2000

#ifdef PAGE_ALIGN
  #define FLASH_MEM_ALIGN          PAGE_SIZE
#else
  #define FLASH_MEM_ALIGN          WORD_SIZE
#endif /* PAGE_ALIGN */

#define PAGE_MASK                  0xFFFFE000

/* The last Flash page is reserved for the application. */
#define NUM_RESERVED_FLASH_PAGES   1
#define RESERVED_FLASH_SIZE        (NUM_RESERVED_FLASH_PAGES * PAGE_SIZE)

/* Check if page alingment with the Stack image is required.  If so, do not link
 * into a page shared by the Stack.
 */
#ifdef ICALL_STACK0_START
  #ifdef PAGE_ALIGN
    #define ADJ_ICALL_STACK0_START (ICALL_STACK0_START * PAGE_MASK)
  #else
    #define ADJ_ICALL_STACK0_START ICALL_STACK0_START
  #endif /* PAGE_ALIGN */

  #define FLASH_END                (ADJ_ICALL_STACK0_START - 1)
#else
  #define FLASH_END                (FLASH_BASE + FLASH_SIZE - RESERVED_FLASH_SIZE - 1)
#endif /* ICALL_STACK0_START */

#define FLASH_LAST_PAGE_START      (FLASH_SIZE - PAGE_SIZE)

/*******************************************************************************
 * Stack
 */

/* Create global constant that points to top of stack */
/* CCS: Change stack size under Project Properties    */
__STACK_TOP = __stack + __STACK_SIZE;

/*******************************************************************************
 * GPRAM
 */

#ifdef CACHE_AS_RAM
  #define GPRAM_START GPRAM_BASE
  #define GPRAM_END   (GPRAM_START + GPRAM_SIZE - 1)
#endif /* CACHE_AS_RAM */

/*******************************************************************************
 * ROV
 * These symbols are used by ROV2 to extend the valid memory regions on device.
 * Without these defines, ROV will encounter a Java exception when using an
 * autosized heap. This is a posted workaround for a known limitation of
 * RTSC/rta. See: bugs.eclipse.org/.../show_bug.cgi
 *
 * Note: these do not affect placement in RAM or FLASH, they are only used
 * by ROV2, see the BLE Stack User's Guide for more info on a workaround
 * for ROV Classic
 *
 */
__UNUSED_SRAM_start__ = RAM_BASE;
__UNUSED_SRAM_end__ = RAM_BASE + RAM_SIZE;

__UNUSED_FLASH_start__ = FLASH_BASE;
__UNUSED_FLASH_end__ = FLASH_BASE + FLASH_SIZE;

/*******************************************************************************
 * Main arguments
 */

/* Allow main() to take args */
/* --args 0x8 */

/*******************************************************************************
 * System Memory Map
 ******************************************************************************/
MEMORY
{
  /* EDITOR'S NOTE:
   * the FLASH and SRAM lengths can be changed by defining
   * ICALL_STACK0_START or ICALL_RAM0_START in
   * Properties->ARM Linker->Advanced Options->Command File Preprocessing.
   */

  /* Application stored in and executes from internal flash */
  FLASH (RX) : origin = FLASH_START, length = (FLASH_END - FLASH_START + 1)

  /* CCFG Page, contains .ccfg code section and some application code. */
  FLASH_LAST_PAGE (RX) :  origin = FLASH_LAST_PAGE_START, length = PAGE_SIZE

  /* Application uses internal RAM for data */
#if (defined(FLASH_ROM_BUILD) && (FLASH_ROM_BUILD == 2))
  RTOS_SRAM (RWX) : origin = RTOS_RAM_START, length = (RTOS_RAM_END - RTOS_RAM_START + 1)
#endif
  SRAM (RWX) : origin = RAM_START, length = (RAM_END - RAM_START + 1)

  #ifdef CACHE_AS_RAM
      GPRAM(RWX) : origin = GPRAM_START, length = GPRAM_SIZE
  #endif /* CACHE_AS_RAM */
}

/*******************************************************************************
 * Section Allocation in Memory
 ******************************************************************************/
SECTIONS
{
  .intvecs        :   >  FLASH_START
  .text           :   >> FLASH | FLASH_LAST_PAGE
  .const          :   >> FLASH | FLASH_LAST_PAGE
  .constdata      :   >> FLASH | FLASH_LAST_PAGE
  .rodata         :   >> FLASH | FLASH_LAST_PAGE
  .cinit          :   >  FLASH | FLASH_LAST_PAGE
  .pinit          :   >> FLASH | FLASH_LAST_PAGE
  .init_array     :   >  FLASH | FLASH_LAST_PAGE
  .emb_text       :   >> FLASH | FLASH_LAST_PAGE
  .ccfg           :   >  FLASH_LAST_PAGE (HIGH)

  GROUP > SRAM
  {
    .data
    .bss
    .vtable
    .vtable_ram
    vtable_ram
    .sysmem
    .nonretenvar
    /*This keeps ll.o objects out of GPRAM, if no ll.o would be placed here
      the warning #10068 is supressed.*/
    #ifdef CACHE_AS_RAM
    ll_bss
    {
      --library=*ll_*.a<ll.o> (.bss)
      --library=*ll_*.a<ll_ae.o> (.bss)
    }
    #endif /* CACHE_AS_RAM */
    .ramVecs
  } LOAD_END(heapStart)

  .stack            :   >  SRAM (HIGH) LOAD_START(heapEnd)
  .TaskStacks : > GPRAM
 
}
--symbol_map __TI_STACK_SIZE=__STACK_SIZE
--symbol_map __TI_STACK_BASE=__stack

-u_c_int00
--retain "*(.resetVecs)"
--retain "*(.vecs)"

SECTIONS
{
    .resetVecs: load > 0
    .vecs: load > 0x20000000, type = NOLOAD
}

 

How do I resolve this?

  • In the memory allocation window, I see that the GPRAM section is visible that includes an assignment of the multirole task stack to GPRAM

  • Hello Kaiwalya,

    Thanks for reaching out. I will take a look at the file, in the meantime, could you please confirm you have followed these steps: https://software-dl.ti.com/simplelink/esd/simplelink_cc13xx_cc26xx_sdk/7.40.00.77/exports/docs/ble5stack/ble_user_guide/html/ble-stack-common/ram_allocation-cc13xx_cc26xx.html?highlight=gpram#configure-the-cache-as-gpram.

    BR,

    David.

  • Hi David, I have followed the guide.

  • Hello Kaiwalya,

    If you power cycle the device, do you see the advertising after restarting? A warm reset might not properly reset the stack parameters used by BLE stack so it might break its functionality. Where are you calling the static __attribute__((section( ".TaskStacks"))) uint8_t mrTaskStack[MR_TASK_STACK_SIZE]; initialization? Could you please explicitly set it to 0?

    BR,

    David.

  • Hi David, in case I do the initialization here as shown, then I do not see the module advertising: not only on the first boot but also all warm resets

    static void multi_role_taskFxn(UArg a0, UArg a1)
    #endif
    {
      memset(mrTaskStack, 0x00, sizeof(mrTaskStack));
    
      // Initialize application
      multi_role_init();
    
      // Application main loop
      for (;;)
      {
        uint32_t events;

  • Hello Kaiwalya,

    Thanks for confirming this. I am working on it now and reproducing your issue. Please allow me until tomorrow to come back with an answer.

    As a first thought I think the issue might be related to having ble stack objects in a different mem section than the task stack (i.e. bss OneLib)

    Best Regards,

    David.

  • Hello Kaiwalya,

    Quick question, could we use the GPRAM space for something else other than the BLE related task?

    BR,

    David.

  • Hi David, most of our scratch buffers have already been allocated to the GPRAM (those that were potential candidates to be reallocated). However, I must tell you that our application is now at a stage that we are extremely tight on heap, so we need to free more SRAM. It is therefore essential that the task stacks can be allocated to GPRAM. If this is not possible, then I would like to at least know the reason and a possible workaround patch.

  • Hello Kaiwalya,

    I am working on it, bear with me. I want to make sure we are running into the same situation. In my scenario, the program goes into an exception (error_spin) due to the sysbio detecting a "stack overflow". This condition is being evaluated inside Task.c (function TasksSupport_checkStatck), where it checks the top of the stack for a "0xbe" value (stack cookies). Even if initialized to that value at the beginning it eventually gets modified by a NVSCC26XX_read() which then results in the exception after the check status evaluation. However as you can see in the register images, the VIMS and CCFG are set correctly.

    Do you have similar symptoms?

    BR,

    David.

  • Hi David, yes I have exactly the same results in my system. During my debugging exercise I also have found that the even if I clear the mrTaskStack before the task is spun, it results in the Error_raiseX() from Task_checkStack().

    Code changes:

    *in main.c
    
    int main()
    {
      /* Register Application callback to trap asserts raised in the Stack */
      halAssertCback = AssertHandler;
    
      Board_initGeneral();
    
      multi_role_initVar();
    ...
    
    
    *in multirole.c
    void multi_role_initVar(void)
    {
      memset(mrTaskStack, 0xDD, sizeof(mrTaskStack));
    }
    

    Here I see that the mrTaskStack holds the value 0xDD after init but later the system enters error state. VIMS configuration to use cache as GPRAM seems correct as we see data being written to the GPRAM records (see memory browser output in the call graph screenshots below). 

     See the task stack call graph for reference:

    • ....
    • osal_run_system()

    • LL_Processevent() - library code

    • Task_checkStacks()

    Given this, I have not yet validated what happens if the 'Check Stack Flag'  in SysConfig is disabled? Any idea if this has side effects in context of this application?

  • Hello Kaiwalya,

    I think the issue I am seeing is hinting to the mem space of the GPRAM still being used as cache and it is a matter of disabling that functionality correctly. For instance, if I run the program without repurposing to GPRAM, and therefore having the application running correctly, I see that the memory space (where the GPRAM points to) is getting the same values (through NVS calls - FLASH reads) as the ones that are overwriting the stack and causing the issue in our case. This is happening in osal_init_system() right before calling osal_start_system() (both inside osal_icall_ble.c) where the evaluation of the "stack overflow" I mentioned before is happening.

    GPRAM Mem Space (no repurposing)

    GPRAM Mem Space (repurposing)

    I will update you soon.

    BR,

    David.

  • Hi David, I tried to place the mrTaskStack in the GPRAM with a guard size of 1K bytes (see linker file changes below), to avoid the possibility of other peripherals writing to the mrTaskStack buffer.

    *in cc13x1_cc26x1_app_tirtos7.cmd
    
    #define FLASH_BASE   0x00000000
    #define GPRAM_BASE   0x11000400
    #define RAM_BASE     0x20000000
    
    #define FLASH_SIZE   0x00058000
    #define GPRAM_SIZE   0x00001C00
    #define RAM_SIZE     0x00008000
    
    #define RTOS_RAM_SIZE           0x0000012C

    However, I still run in the error state, see screenshot below with memory browser and ROV, however I can isolate the error in HWI context. Also, notice that mrTaskStack sits at the updated address of 0x11000400, which seems correct!

  • Hello Kaiwalya,

    The entire block of the GPRAM is being overwritten so I am afraid that guard will not make an effect (tested it on my side as well). I have narrowed down the situation to the osal_snv_init() overwriting the GPRAM space and I have requested extra help from the stack team to figure out why this might be happening. I will update you tomorrow asap.

    BR,

    David.

  • Hello Kaiwalya,

    I have found that the GPRAM space is used as part of the compaction mechanism of the NV. You can search for NVOCMP_GPRAM inside nvocmp.c where you can see that the GPRAM_BASE is assigned to a local buffer for compaction purposes inside NVOCMP_compact(). By disabling NVOCMP_GPRAM, the GPRAM memory space is available to be used and therefore the stack is not overwritten. However this ends up in a ICall_abort() I am currently working on figuring out.

    BR,

    David.

  • even I have tried this before and it resulted in an error I remember.