1.0 Introduction
This document describes the One SDK design, including the development environment.
2.0 Setup development environment
2.1 Install prerequisites
- Install e2studio/FSP for RA
- Install Python needed to support MCUBoot
- Install Segger J-Link Software and Documentation
2.2 Introduction to Trust Zone
- Secure after POR
- Bootloader Set up S, NS and NSC memories
- Describe S+NS side-by-side development model
- Describe Secure Bundle distribution model
- How to place "secret sauce" in secure memory
- How to call S code from NS code
- How to call NS code from S code
2.3 Create your first "Blinky" project
- S and NS co-reside in the same workspace
- Create Secure Project (S) - add Bootloader to set up S, NS and NSC memory map
- Show where S calls into NS code
- Create Non-secure Project (NS) - add FreeRTOS
- Build and Run
- Show the S to NS code flow to end up blinking LEDs
- Show where to find the *.sbd file
3.0 SDK Architecture
3.1 Overview
One SDK model consists of four layers plus a RTOS:
Hardware layer: the physical hardware where the application built with the SDK runs. The hardware can be MCU registers, peripheral registers, memory, etc.
Driver layer (HAL): a collection of device drivers callable by the upper layer code to interact with the hardware. Usually, each module in the driver layer is associated with a specific hardware component, e.g., UART, I2C, SPI, Flash, etc. The driver layer is usually hardware specific. For example, different MCU may require a different driver layer. However, since different MCU often share the same peripheral blocks, the driver modules may be common between the MCUs.
Middleware layer: a collection of processing modules that serve as the building blocks for constructing applications. Each middleware module can be associated with a specific driver module, as in the case of protocol stacks, or associated with specific data-in, data-out functions or algorithms, such as FFT, or state-of-charge computation. One can think of the middleware layer as a collection of building blocks to be sequenced by the application layer to create the application executables.
Application layer: a collection of loops/threads/interrupt handlers that form the top-level application logic. If threads are used, then RTOS would be required to facilitate scheduling, thread synchronization and inter-process communication.
Figure 1 - One SDK high-level architecture.
Application stack: a collection of application threads and middleware modules that implements a specific application. In One SDK each application stack is standalone and can be included or excluded at build time. For instance, if the above example as only the TCPM application stack, then the MCU running the application would become a TCPM controller. If only the FG application stack is included, then the MCU becomes a battery fuel gauge. If both application stacks are included, then the MCU becomes a multi-function ASSP capable of functioning both as TCPM and battery fuel gauge, subject to MCU bandwidth limitation, available peripherals and memory capacity.
3.2 Supported MCU targets
- RL78
- CM0+
- CM23
- CM33
3.3 File structure
- Closely following e2studio/FSP
- Project/make files
- S project
- src
- include
- test
- NS project
- src
- include
- test
- Scripts
- Tools
- Docs
3.4 Privilege states
One SDK supports MCU with Trust Zone support or without. For MCU with TZ, three privilege states are supported: Factory (Renesas), Unsealed (OEM/ODM), Sealed (User). For MCU without TZ support, only Unsealed and Sealed states are supported. The meaning of each is defined below:
- Factory (STATE_FACTORY) – Factory state is intended to be accessed by Renesas only. In this state, MCU runs the factory bootloader in secure (S) mode. Both secure and non-secure code/data can be read and written. Factory state can only be entered from unsealed state with factory command and factory password known only to Renesas. Factory state always exits to Sealed state with a self-reset.
- Sealed (STATE_SEALED) – Sealed state is where the application runs. After reset the factory bootloader runs, and it quickly checks if it should enter the factory state; if not it will immediately transition to sealed state and jumps to the application.
- Unsealed (STATE_UNSEALED) – Unsealed state is only entered from the Sealed state with CMD_UNSEAL command and the correct customer password. Unsealed state runs in NS mode and supports additional commands.
Figure 2. Privilege states of MCU with TZ support.
The benefit of having a TZ is to enable OEM/ODM to customize the device with Renesas "secret sauce" pre-programmed into the device. For MCU without TZ support, such as CM0+ and RL78, there will be no Factory state, and therefore the Factory State will be bypassed resulting in the below state transition diagram:
Figure 3. Privilege states of MCU without TZ support.
Note that, in this case, there is no TZ support, therefore "secret sauce" code/data hiding is not possible. Renesas must be the one doing the firmware customization and deliver only the executable binary.
3.4.1 Top-level pseudo code
Below shows the factory bootloader pseudo code which would run right after reset:
void factory_bootloader() { uint8_t cmd; uint8_t param[MAX_PARAM_SZ] = {0}; gs_dev_state = gsf_dev_state; if (gs_dev_state == STATE_FACTORY) { flash_write(&gsf_dev_state, STATE_SEALED); while (true) { bool rc = read_cmd(&cmd, param); if (rc == OK) { if (cmd == CMD_RESET) { sys_reset(); } else { rc = process_factory_cmd(cmd, param); } } print error(rc); } } NS_entry(); }
Note that even if TZ is not supported factor_bootloader() can still be included, as the state upon reset would not be STATE_FACTORY and the execution will immediately jump to NS_entry() and run the application.
The NS_entry() is the non-secure entry function. Customer may optionally to implement customer bootloader() in NS_entry() or before the application code is called:
void NS_entry() { application(); } void application() { // Initialize, setup ISR or threads application_setup(); // Comm loop while (true) { uint8_t rc = read_cmd(&cmd, ¶m); if (rc == OK) { if (state == STATE_UNSEALED) { rc = process_unsealed_cmds(cmd, param); } else { if ((cmd == CMD_UNSEAL) && (0 == strcmp(param, customer_password)) { state = STATE_UNSEALED; } else { rc = process_sealed_cmds(cmd, param); } } } print_error(rc); } }
3.4.2 Updating firmware
Firmware update involves a host writing new code/data into secure and non-secure flash memories using the CMD_FLASH_WR command by parsing the Intel HEX file or Motorola S-Record file generated from the firmware build process. Then the host can setup the Trust Zone memory boundaries by writing to the the IDAU registers.
3.4.3 Generalized packet protocol
The bootloader communication shall be adaptable to any packet-based serial communication such as, UART, SMBus, SPI, TCP/IP socket, etc. The device driver shall convert selected serial communication into packets, and a generalized packet parser shall process the packets and execute valid commands.
5.0 Application stacks
5.1 Application stack interface
- Thread
- Stack
- Trigger events
- Priority
5.2 Fuel gauge (FG) application stack
- Introduction
- Pseudo code of FG application thread
- Security
- Communication
- SBS Data v1.1 support
- Additional data support
- Algorithm API
- AFE API
5.3 TCPM application stack
- Introduction
- Pseudo code of TCPM application stack
- Security
- Communication
- Algorithm API
- AFE API
5.4 Motherboard application stack
- Introduction
- Pseudo code of motherboard application stack
- Security
- Communication - RTT requires RA4E1 board modification
- Algorithm API - include daughter card detection
- AFE API - multi-daughter cards
6.0 References
- RA Flexible Software Package Users Manual
- Security Design with ARM Trust Zone using Cortex M33
- Renesas Device Life Cycle Management Key Injection
- RA4E1 device data sheet