TI-RTOS

Build process

  • xdc packet structure
  • sysbios generation
  • build folder structure

TI-RTOS configuration - The .cfg file

Important modules

  • explain whether the module affects code size or debugging experience
  • intoduce modules briefly, provide links to the online documentation:
    • heap: XXX_construct() vs. XXX_create()
    • ROM module
    • SysCallback vs. SysMin
    • assertions: how to use them
    • clock module: why better not to change the tickPeriod

Using code generation to avoid boilerplate code

  • explain why this is useful: faster development, less error-prone, more readable code
  • link to the existing documentation

On-chip resources needed by TI-RTOS

  • TI-RTOS uses the RTC, it can not be used by the application
  • more resources to mention?

Estimating stack sizes

Debugging TI-RTOS applications

  • do not repeat too much TI-RTOS documentation here
  • provide links to videos and tutorials about how to use the ROV
  • maybe write about two things:
    • locate stack overflows
    • read exceptions

Accessing flash memory

  • constant values can be always put into flash
  • placing is either doen implicitly, for instance by const keyword or by adding a .section directive.
  • page size is 4 KiB, this is the minimum erase size

Placing variables at a certain location

  • linker script modification

Example linker script that defines a FLASH_DATA section at the 31st page in flash (second last):

/* Override default entry point.                                             */
--entry_point ResetISR
/* Allow main() to take args                                                 */
--args 0x8
/* 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 starting address of the application.  Normally the interrupt vectors  */
/* must be located at the beginning of the application.                      */
#define FLASH_PAGE_SIZE         0x1000
#define FLASH_ADDR              0x0
#define FLASH_SIZE              0x20000
#define FLASH_APPL_ADDR         FLASH_ADDR
#define FLASH_APPL_SIZE         (30 * FLASH_PAGE_SIZE)              // 30 pages for the application
#define FLASH_DATA_ADDR         (FLASH_APPL_ADDR + FLASH_APPL_SIZE)
#define FLASH_DATA_SIZE         (1 * FLASH_PAGE_SIZE)               // 1 page for the config data
#define FLASH_CCFG_ADDR         (FLASH_DATA_ADDR + FLASH_DATA_SIZE)
#define FLASH_CCFG_SIZE         (1 * FLASH_PAGE_SIZE)               // 1 page for the ccfg
#define RAM_ADDR                0x20000000
#define RAM_SIZE                0x5000

__FLASH_ADDR      = FLASH_ADDR;
__FLASH_SIZE      = FLASH_SIZE;
__FLASH_DATA_ADDR = FLASH_DATA_ADDR;
__FLASH_DATA_SIZE = FLASH_DATA_SIZE;

/* System memory map */

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
}

/* Section allocation in memory */

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
}

Updating data in flash

Example snippet:

#include <stdint.h>
#include <driverlib/flash.h>
#include <driverlib/vims.h>
#include <xdc/runtime/Assert.h>
#include <xdc/std.h>


/*
Erase a flash page at a certain 'address'.
The parameter 'address' is expected to be aligned to the section size.
The section size is 4KiB for all sections.

Returns true if erase was successful, otherwise false.
*/
Bool flash_eraseSection(void* address)
{
    setFlashCacheEnabled(FALSE);
    uint32_t result = FlashSectorErase(0);
    setFlashCacheEnabled(TRUE);

    return (result == FAPI_STATUS_SUCCESS);
}

/*
Writes 'size' bytes from 'sourceAddr' to 'destAddr'.

This function does not perform an erase nor does it check
whether destAddr already contains data.

Returns true if successful, otherwise false.
*/
Bool flash_write(void* destAddr, const void* sourceAddr, uint16_t size)
{
    setFlashCacheEnabled(FALSE);
    uint32_t result = FlashProgram((uint8_t*)sourceAddr, (uint32_t)destAddr, size);
    setFlashCacheEnabled(TRUE);

    return (result == FAPI_STATUS_SUCCESS);
}

/*
Enables/disables the flash cache. This is necesary on the CC1310
in order to prevent from reading old content.
*/
void setFlashCacheEnabled(Bool enabled)
{
    if (enabled == TRUE)
    {
        VIMSModeSet(VIMS_BASE, VIMS_MODE_ENABLED);
    }
    else
    {
        VIMSModeSet(VIMS_BASE, VIMS_MODE_DISABLED);
        while (VIMSModeGet(VIMS_BASE) != VIMS_MODE_DISABLED);
    }
}

Implementing a custom bootloader

The following steps are necessary in order to implement a custom bootloader and do over-the-air updates:

  1. Understand the memory layout of the CC1310
  2. Implement a bootloader application
  3. Enable bootloader support in TI-RTOS

The memory layout on the CC1310

The internal flash memory is split into 32 pages with a page size of 4 KiB. Like all NAND flash devices, erase is only possible on whole pages with 0xFF representing an empty byte. Write operations (changing 1 into 0) can be performed byte-wise. The following table shows a memory map of the

This section provides an overview about the memory layout of the CC1310 for application developers. More details can also be found in the CPU Domain Memory Map documentation.

Segment Begin End Size Description
Flash (32/128 KiB) 0x0000 0000 0x0000 0FFF 4 KiB Free for application. 0x0000 is used as default reset vector.
0x0000 1000 0x0000 14FF 1280 B When using TI-RTOS in ROM, this section contains kernel data structures at fixed addresses.
0x0001 FFA8 0x0001 FFFF 88 B Customer configuration (CCFG) area. It contains configuration parameters for the ROM bootcode, device hardware, and device firmware. Please refer to the Device Configuration chapter in the Technical Reference Manual
ROM (128 KiB) 0x1000 0000 0x1001 FFFF 128 KiB Pre-built functions from TI-RTOS kernel and DriverLib. This reduces the size of applications. See Rom Functions and also Important modules.
GPRAM 0x1100 0000 0x1100 1FFF 8 KiB Used as internal instruction cache by default. Can be used for application purpose. Please refer to the VIMS chapter in the Technical Reference Manual.
SRAM 0x2000 0000 0x2004 FFFF 20 KiB Free for application data.
RFC_RAM 0x2100 0000 0x2100 FFFF 4 KiB Internal RF Core RAM. Not accessible from the application.
Peripheral and internal registers 0x4000 0000 0xFFFF FFFF   Internal registers of peripheral units. Not accessible from the application. Please refer to CPU Domain Memory Map for details.

When using TI-RTOS in ROM, the fixed content between 0x1000 and 0x14FF reserves the whole 4 KiB flash page for the application. This means that the second flash page can not be used by the bootloader. The space between 0x1500 and 0x1FFF is not necessarily lost, though. Small sections of the application may be mapped into this segment by adjusting the application linker script.

The ROM section contains elected functions of CC13xxWare and the TI-RTOS kernel. They have been pre-built and pre-programmed as a golden image to the chip. ROM functions reduce the flash memory footprint of applications and also the power consumption, because the internal ROM needs less power. More information can be found in Rom Functions and also in Important modules. The symbols for the internal ROM functions and the build files for the golden ROM image are defined in the following folder:

${TIRTOS_INSTALL_DIR}/products/${BIOS_DIR}/packages/ti/sysbios/rom/cortexm/cc13xx/golden/CC13xx/

Implementing a bootloader application

This example provides all necessary building blocks for a fully functional bootloader. This includes: - UART access (main.c) - flash access (flash.h/c) - decryption (crypto.h/c) - starting the TI-RTOS application (main.c) - bootloader linker script (cc13x0f128_bootloader.cmd)

However, the actual application logic is not implemented, because it is highly product-specific.

Linker script

The linker script tells the linker where to put the application in memory. Two linker scripts are needed: one for the bootloader and one for the TI-RTOS application. For more details about linker scripts in the TI toolchain, please refer to the [ARM Assembly Language Tools User’s Guide]. The following excerpt shows the memory segments specification and the system memory map for the TI linker. These two parts are similar for the bootloader and the application linker script:

// Memory segment specification
// ----------------------------
// 0x0000 .. 0xfff  is available for bootloader
#define FLASH_BOOT1_BASE        0x0
#define FLASH_BOOT1_SIZE        0x1000

// The next page is reserved for TI-RTOS hard-coded symbols
// 0x1000 .. 0x14ff
#define FLASH_TIRTOS1_BASE      0x1000
#define FLASH_TIRTOS1_SIZE      0x1000

// Next pages are available for more bootloader code
// 0x2000 .. 0x4fff
#define FLASH_BOOT2_BASE        0x2000
#define FLASH_BOOT2_SIZE        0x3000

// There are 104 KiB left for application
// 0x5000 .. 0x10FFF
#define FLASH_TIRTOS2_BASE      0x5000
#define FLASH_TIRTOS2_SIZE      0x1A000

// The last flash page is reserved for custom configuration
// 0x1F000 .. 0x1FFFF
#define FLASH_CCFG_BASE         0x1F000
#define FLASH_CCFG_SIZE         0x1000

#define RAM_BASE                0x20000000
#define RAM_SIZE                0x5000
#define GPRAM_BASE              0x11000000
#define GPRAM_SIZE              0x2000

// System memory map
// -----------------
MEMORY
{
    FLASH_BOOT1   (RX)  : origin = FLASH_BOOT1_BASE,   length = FLASH_BOOT1_SIZE
    FLASH_TIRTOS1 (RX)  : origin = FLASH_TIRTOS1_BASE, length = FLASH_TIRTOS1_SIZE
    FLASH_BOOT2   (RX)  : origin = FLASH_BOOT2_BASE,   length = FLASH_BOOT2_SIZE
    FLASH_TIRTOS2 (RX)  : origin = FLASH_TIRTOS2_BASE, length = FLASH_TIRTOS2_SIZE
    FLASH_CCFG    (RX)  : origin = FLASH_CCFG_BASE,    length = FLASH_CCFG_SIZE

    SRAM          (RWX) : origin = RAM_BASE,           length = RAM_SIZE
    GPRAM         (RWX) : origin = GPRAM_BASE,         length = GPRAM_SIZE
}

The 128 KiB flash memory is splitted into five sections:

  • FLASH_BOOT1 (4 KiB) : The first flash page, contains the interrupt vector table and other bootloader code
  • FLASH_TIRTOS1 (4 KiB) : The second flash page, half occupied by TI-RTOS
  • FLASH_BOOT2 (12 KiB) : The bootloader
  • FLASH_TIRTOS2 (104 KiB) : The TI-RTOS application
  • FLASH_CCFG (4 KiB) : The configuration section. The last 88 B are used by .ccfg data

This is only one example mapping, but there are other possibilities as well.

As a third step, the linker script must define a section allocation map. For the bootloader, this would look as follows:

// Section allocation in memory for the bootloader
SECTIONS
{
    .intvecs        :   >  FLASH_BOOT1_BASE
    .const          :   >> FLASH_BOOT1 | FLASH_BOOT2
    .constdata      :   >> FLASH_BOOT1 | FLASH_BOOT2
    .rodata         :   >> FLASH_BOOT1 | FLASH_BOOT2
    .binit          :   >> FLASH_BOOT1 | FLASH_BOOT2
    .cinit          :   >  FLASH_BOOT2
    .pinit          :   >> FLASH_BOOT1 | FLASH_BOOT2
    .init_array     :   >> FLASH_BOOT1 | FLASH_BOOT2
    .emb_text       :   >> FLASH_BOOT1 | FLASH_BOOT2
    .text           :   >> FLASH_BOOT1 | FLASH_BOOT2
    .ccfg           :   >  FLASH_CCFG (HIGH)

    .vtable         :   > SRAM
    .vtable_ram     :   > SRAM
     vtable_ram     :   > SRAM
    .data           :   > SRAM
    .bss            :   > SRAM
    .sysmem         :   > SRAM
    .stack          :   > SRAM (HIGH)
    .nonretenvar    :   > SRAM
    .gpram          :   > GPRAM
}

Most input sections are mapped to either FLASH_BOOT1 or FLASH_BOOT2 by using the split directive >> XX | XX. Only the interrupt vectors need to be placed at a fixed address and .cinit has to reside in one section. For more details about linker scripts in the TI toolchain, please refer to the ARM Assembly Language Tools User’s Guide.

The complete bootloader linker script for the TI toolchain is available in the file cc13x0f128_bootloader.cmd. Other linkers like GNU-ld are treated very similar.

Enable bootloader support in TI-RTOS

In order to activate bootloader support in a regular TI-RTOS project, the following changes are necessary:

  • Relocate the reset vector
  • Modify the linker script

The reset vector in TI-RTOS is placed to the address 0x000000 by default and can be changed in the ti.sysbios.family.arm.m3.Hwi module via the .cfg file:

In the linker script, the begin of the application must be shifted to this address. Using the memory specifications from the above, we can define the section allocation as follows:

// Section allocation in memory for the TIRTOS application
SECTIONS
{
    .text           :   >> FLASH_TIRTOS1 | FLASH_TIRTOS2
    .const          :   >> FLASH_TIRTOS1 | FLASH_TIRTOS2
    .constdata      :   >> FLASH_TIRTOS1 | FLASH_TIRTOS2
    .rodata         :   >> FLASH_TIRTOS1 | FLASH_TIRTOS2
    .cinit          :   >  FLASH_TIRTOS2
    .pinit          :   >> FLASH_TIRTOS1 | FLASH_TIRTOS2
    .init_array     :   >> FLASH_TIRTOS1 | FLASH_TIRTOS2
    .emb_text       :   >> FLASH_TIRTOS1 | FLASH_TIRTOS2
    .ccfg           :   >  FLASH_CCFG (HIGH)

    .data           :   > SRAM
    .bss            :   > SRAM
    .sysmem         :   > SRAM
    .stack          :   > SRAM (HIGH)
    .nonretenvar    :   > SRAM
}

Similar to the bootloader linker script, the application is distributed among both sections, FLASH_TIRTOS1 and FLASH_TIRTOS2. The complete TI-RTOS application linker script for the TI toolchain is available in the file cc13x0f128_tirtos.cmd. Other linkers like GNU-ld are treated very similar.

Dealing with the CCFG section

The custom configuration resides in the last flash page. It is normally compiled along with a TI-RTOS application, but with the bootloader, there are two applications running on the same chip. Whether the bootloader or the application shall manage the ccfg section, depends on the product. For security reasons, the bootloader should not allow overwriting the ccfg section or only some of the fields. For instance, it should not allow to unlock flash pages that have been protected before.