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:
- Understand the memory layout of the CC1310
- Implement a bootloader application
- 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 codeFLASH_TIRTOS1
(4 KiB) : The second flash page, half occupied by TI-RTOSFLASH_BOOT2
(12 KiB) : The bootloaderFLASH_TIRTOS2
(104 KiB) : The TI-RTOS applicationFLASH_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.