F29H85x-SDK  1.03.00.00
 
RAM-based JTAG Flash Kernel

F29x RAM-based JTAG Flash Kernel example for secure device programming.

Located in F29H85X-SDK /examples/driverlib/single_core/flash/ram_based_jtag_kernel

Introduction

This example serves as a RAM-based bootloader that leverages JTAG to perform secure programming operations including key provisioning (KP) and code provisioning (CP).

The JTAG Flash Programmer or CCS Scripting Console is required to interface with the device via JTAG. More details are provided in the following sections.

Getting Started

To fully understand this example, it is highly recommended to first review the foundational concepts outlined in the \ref UART_FLASH_PROGRAMMER_PAGE document.

The document covers essential topics such as device lifecycle, firmware update methodologies (DFU,FOTA,LFU) and flash bank modes, which are prerequisites for a complete understanding of this kernel.

Software Overview

The RAM-based JTAG Flash Kernel, in a nutshell, is an intermediate piece of code that runs in RAM. It is downloaded to the device via JTAG. Once loaded, it receives commands from the JTAG debugger and performs the corresponding programming operations.

The primary purposes of the RAM-based JTAG Flash Kernel are:

  1. Device bring-up
    • Convert the device into HS-SE which enforces HSM & SSU security.
    • Programs any CPU/HSM flash applications.
  2. Device Firmware Update
    • Supports secure (CP) programming operations.

For instructions on how to use the RAM-based JTAG kernel, refer to the "Example Demonstration" section.

Build Configurations

The example provides a single build configuration that supports both key provisioning and code provisioning operations:

RAM-based JTAG Kernel build configuration
RAM • KP and CP operations
• HS-FS, HS-KP and HS-SE
• Requires RAM-based HSM runtime

The RAM configuration consolidates the key and code provisioning code to support the full device conversion from HS-FS to HS-KP and then to HS-SE. See the "Available Commands" section for the supported operations.

Build Options

Two build options are provided in the \\ccs folder: importing a CCS project or using a Makefile.

  • CCS project:
    • In CCS, click on "Import CCS Projects..." and select "secure_ram_based_jtag_kernel"
    • Select the project and choose the RAM build configuration.
    • Build the project "secure_ram_based_jtag_kernel", and it will produce secure_ram_based_jtag_kernel.out.
  • Makefile:
    • First, make sure all required Makefile dependency paths are properly set up (see \ref MAKEFILE_BUILD_PAGE)
    • To build the makefile, within \\ccs folder, do:
      • Use make -f makefile all
    • It will produce secure_ram_based_jtag_kernel.out

Image Signing Requirements

The JTAG kernel itself (.out file) does not require certificate signing or authentication when loaded via JTAG debugger. The kernel runs with full debug access and bypasses boot authentication.

However, the images programmed by the kernel must be properly signed:

  • For Key Provisioning (HS-FS → HS-KP): HSM Runtime and HSM Keys must be signed with Factory Encryption Key (FEK)
  • For Code Provisioning (HS-KP → HS-SE): HSM Runtime, HSM Flash Image, CPU1/CPU3 Images, and Sec Cfg must be signed with the customer keys programmed during Key Provisioning

By default, SDK examples use mcu_custMek.pem as the signing key. It is recommended to first conduct the device conversion exercise to HS-SE using this default key.

JTAG Access Limitations

\attention The JTAG kernel may not be usable for code provisioning in HS-SE devices if debug access has been closed via the Sec Cfg security configuration. In HS-SE state, the device enforces security policies that may disable JTAG debug access, making the device inaccessible via JTAG debugger. For field programming of HS-SE devices with closed debug access, use alternative bootloaders such as the RAM-based UART SBL or Flash-based SBL instead.

Memory Partition

In JTAG boot mode, the RAM bootloader utilizes the following memory regions:

  • LDAx RAM (RWX)
    • Accessible by CPU1 & HSM
    • LDA7 - LDA2 reserved by RAM-based HSM runtime
    • LDA1 used as scratchpad for passing data between CPU and HSM
    • LDA0 contains security library, stack, and HSM-accessible global variables
  • LPAx RAM (RWIX)
    • 128KB executable RAM starting at 0x20100000
    • Contains main kernel code and data
  • CDAx RAM (RW)
    • Non-executable data RAM

Below is the F29H85x memory layout in JTAG boot mode:

(R-read, W-write, I-initialize, X-execute)

  • LDAx RAM: Shared between CPU1 and HSM for secure operations
  • LPAx RAM: Main kernel executable code
  • CDAx RAM: Additional data storage

The kernel's LDA1 RAM is solely reserved as a scratchpad to pass programming/authentication data to the HSM, while LDA0 RAM contains the security library, stack, and any HSM-accessible global variables.

Device Setup

The kernel is loaded via JTAG interface using:

  • CCS Scripting Console for automated device programming
  • CCS Debug Session for manual loading and control
  • JTAG Flash Programmer tools for production programming

On both the F29H85x SOM and F29H85x Launchpad, JTAG is connected via the XDS110 debug probe.

Available commands

The list below shows the commands supported by the JTAG Flash Kernel:

Key Provisioning (KP):

  • Load HSM RAM Image (OTP Keywriter)
  • Load HSM Keys

Code Provisioning (CP):

  • Load HSM RAM Image (CP services)
  • Program Sec Cfg
  • Load HSM Flash Image
  • Load C29 CPU1 Image
  • Load C29 CPU3 Image

Utility commands:

  • Sync Device Status
  • Get Device State
  • Get Bank Mode

Example demonstration

This section provides a walkthrough for a complete device bring-up using the JTAG Flash Kernel.

It is recommended to perform these exercises first with the default signing key (mcu_custMek.pem), used by all the related examples to sign the required images.

\attention For more information on HSM security software, please request access to the TIFS-SDK for F29H85x , available on the same TI download page as F29H85X-SDK for F29H85x .

Device Bringup

A complete device bring-up encompasses all operations needed for a production program, including device conversion from its initial HS-FS to a fully secure HS-SE type, bank mode changes, programming Sec Cfg and CPU, HSM flash.

To perform a complete device bring-up in fewest steps, follow the steps in chronological order:

Device in HS-FS:

  1. Load RAM-based JTAG Kernel via JTAG
  2. Load HSM RAM image at 0x200E0000 (OTP keywriter)
  3. Load Keys Certificate at 0x200F8000 and run kernel
  4. Device automatically performs XRSN (system reset) after conversion

Device in HS-KP:

  1. Load RAM-based JTAG Kernel via JTAG
  2. Load HSM RAM image 0x200E0000 (CP services)
  3. Program Sec Cfg by sending in chunks
  4. Program CPU1,3 & HSM flash
    • In no particular order
    • by sending in chunks
  5. Device reset (manual or via debugger)

See the following subsections on step-by-step instructions in converting the device to HS-KP and HS-SE.

Device Conversion from HS-FS to HS-KP

Device conversion from HS-FS to HS-KP is done through Key Provision (KP).

A. Preparation:

First, prepare the following:

  1. RAM-based JTAG Kernel
    • RAM configuration (.out file)
    • Loaded via JTAG debugger
  2. RAM-based HSM image w/ OTP Keywriter service
    • Prepended w/ X.509 cert signed with FEK (Factory Encryption Key)
    • Required for HS-FS device authentication
  3. HSM Key certificate
    • SMPK/SMEK & BMPK/BMEK
    • Prepended w/ X.509 cert signed with FEK
    • Contains customer keys to be programmed into OTP

B. Dry Run vs Key Writer Mode:

By default, the RAM-based JTAG kernel operates in DRYRUN_MODE. This mode simulates the key writing process and produces verification logs without permanently programming the OTP eFuse. It's strongly recommended to perform a successful dry run first to validate your setups, tools and the provided keys before making irreversible changes.

Once you have verified the process with a dry run, modify the source code to reflect certHeader.reserved = KEYWRITER_MODE in ex3_key_provisioning_cpu1.c:132. Rebuild the kernel and reload via JTAG.

ex3_key_provisioning_cpu1.c : copyKeysToRAM()
/*
The default mode is DRYRUN_MODE . No conversion occurs in this mode.
To convert a device change the certHeader.reserved field below to KEYWRITER_MODE .
*/
certHeader.reserved = DRYRUN_MODE;

C. Load via JTAG:

  1. Connect the device via JTAG debugger (XDS110)
  2. Create a target configuration and connect to CPU1 core
  3. Load the secure_ram_based_jtag_kernel.out file via CCS debugger
  4. Run the program
  5. The kernel will automatically execute the following sequence:
    • Initialize and enter "Wait Boot Mode"
    • Check device state (HS-FS, HS-KP, or HS-SE)
    • Load HSM RAM Image (OTP Keywriter or HSM Code Provisioning Images)
    • The kernel waits for key data via JTAG communication
  6. Provide the user keys via JTAG data transfer to the designated memory region (LDA1_RAM_BASE)
  7. After successful key write, the device will automatically issue XRSN and transition to HS-KP state.

\note The kernel provides debug output via the DebugP_log interface which can be viewed in the CCS console. The OTP Keywriter logs include detailed error information with phase, module, stage, and customer key extension error codes.

Device Conversion from HS-KP to HS-SE

Device conversion from HS-KP to HS-SE is done through Code Provision (CP).

A. Preparation:

First, prepare the following:

  1. RAM-based JTAG Kernel
    • RAM configuration (.out file)
    • Loaded via JTAG debugger
  2. RAM-based HSM image w/ CP services
    • Prepended w/ X.509 cert signed with customer keys (programmed in HS-KP)
    • SMPK/SMEK used for authentication
  3. Sec Cfg image
    • SSU security configuration
    • Prepended w/ X.509 cert signed with customer keys
    • See \ref #EXAMPLES_SSU_MODE2 post-build step on generating the Sec Cfg image
    • A pre-generated image with default settings and default mcu_custMek.pem is provided for checkout in F29H85X-SDK /source/defseccfgbin/
  4. CPU1/CPU3 Flash Images (if programming applications)
    • Prepended w/ X.509 cert signed with customer keys
  5. HSM Flash Image (if programming HSM application)
    • Prepended w/ X.509 cert signed with customer keys

B. Load via JTAG:

  1. After a power-on reset, connect to the device via JTAG
  2. Load the secure_ram_based_jtag_kernel.out file via CCS debugger
  3. Run the program
  4. The kernel will automatically execute the following sequence:
    • Check device state (HS-KP)
    • Enable flash erase and write protection registers for HS-KP state
    • Load HSM RAM Image (CP services)
    • Wait for SecCfg data
  5. Transfer the Sec Cfg image to the designated memory region via JTAG
  6. The kernel processes Sec Cfg in three phases:
    • Certificate Processing
    • Code Programming
    • Code Verification
  7. After Sec Cfg, program CPU1, CPU3, and HSM flash applications as needed
  8. Perform a final device reset. The device is now in HS-SE.
    • All CP commands support reprogramming once in HS-SE, follow the same steps for additional updates.

C. Verification:

One can verify the device status by checking:

  • Device State: Read from DEVCFG_BASE.DEVLIFECYCLE register shows HS_SE
  • Bank Mode: Read from SSU registers shows configured bank mode
  • SSU Security: Sec Cfg is active and enforcing security policies

HS-KP Flash Access Handling

In HS-KP device state, the C29 CPU does not have flash read/write access by default. The SSU registers are held in reset values during this lifecycle as the C29 ROM is unable to configure these registers.

The kernel automatically handles this by calling enableFlashEraseAndWrite() which configures the following SSU WEPROT registers:

  • WEPROT_FLC1_B0_A/B: Flash controller 1, Bank 0
  • WEPROT_FLC1_B2_A/B: Flash controller 1, Bank 2
  • WEPROT_FLC2_B0_A/B: Flash controller 2, Bank 0
  • WEPROT_FLC2_B2_A/B: Flash controller 2, Bank 2

This enables code provisioning operations in HS-KP state (ex3_jtag_boot_cpu1.c:63-72).

Command Flow

The kernel operates with a state machine that processes commands in sequence:

  1. SYNC_STATUS: Initial handshake confirming kernel is active
  2. HSM_RT_IMAGE: Load HSM runtime image to LDA7 RAM base
    • Waits for HSM boot notification
    • Parses and displays HSM version
    • Transitions to next state based on device lifecycle
  3. HSM_KEYS (HS-FS only): Key provisioning flow
    • Copies keys to LDA1 RAM
    • Invokes HSM keywriter service
    • Issues XRSN on completion
  4. HSM_CP_FLASH_IMAGE (HS-KP/HS-SE): HSM flash programming
  5. CPU1_CP_FLASH_IMAGE: CPU1 application programming
  6. CPU3_CP_FLASH_IMAGE: CPU3 application programming
  7. SEC_CFG_IMAGE: Security configuration programming

Each command uses:

  • sendACK(): EMUSTOP0 to pause and signal acknowledgment
  • sendNAK(): EMUSTOP0 + XRSN for error conditions
  • ackWithXRSN(): EMUSTOP0 + XRSN for completion with reset

Image Authentication and Programming

All images undergo a three-phase authentication and programming process via HSM services:

  1. Certificate Processing (HsmClient_firmwareUpdate_CertProcess)
    • Validates X.509 certificate (MAX_CERT_SIZE = 4 KB)
    • Extracts image metadata
    • Verifies signature against provisioned keys
  2. Code Programming (HsmClient_firmwareUpdate_CodeProgram)
    • Programs flash in chunks rather than the full image at once
    • Chunk Size: 16 KB (CHUNK_SIZE = 16 * 1024 bytes)
    • The image is divided into chunks, with each chunk programmed sequentially
    • Handles both full chunks and any remaining data smaller than chunk size
    • Displays progress bar in console showing programming completion percentage
    • After each chunk is programmed, sends ACK to synchronize with debugger
  3. Code Verification (HsmClient_firmwareUpdate_CodeVerify)
    • Verifies programmed data integrity
    • Confirms successful flash operation

Chunked Programming Flow

The code provisioning flow processes large images (HSM Flash, CPU1/CPU3 applications, Sec Cfg) in chunks to manage memory constraints efficiently. The chunking logic (see ex3_code_provisioning_cpu1.c:233-359) operates as follows:

// Calculate number of chunks
numBytesRemaining = ImageSize;
if (0 == (numBytesRemaining % CHUNK_SIZE)) {
numChunks = numBytesRemaining / CHUNK_SIZE;
} else {
numChunks = (numBytesRemaining / CHUNK_SIZE);
lastDataStreamSize = numBytesRemaining - (numChunks * CHUNK_SIZE);
}
// Program each chunk
while ((0 != numChunks) || (0 != lastDataStreamSize)) {
if (numChunks > 0) {
// Program 16 KB chunk
HsmClient_firmwareUpdate_CodeProgram(&gHSMClient, &firmwareUpdate);
bytesWritten += CHUNK_SIZE;
numChunks--;
} else if (lastDataStreamSize != 0) {
// Program remaining data (< 16 KB)
HsmClient_firmwareUpdate_CodeProgram(&gHSMClient, &firmwareUpdate);
}
}
int32_t HsmClient_firmwareUpdate_CodeProgram(HsmClient_t *HsmClient, FirmwareUpdateReq_t *pFirmwareUpdateObject)
service request issued to HSM server to program the incoming firmware to device dormant banks This se...
Definition hsmclient.c:1889

This chunked approach allows programming of large flash images without requiring the entire image to be held in RAM simultaneously, making efficient use of the limited RAM resources available in the bootloader environment.

Additional resource

  • Refer to Serial Flash Programming for F29x Device
  • TI provides tool support via the TI Cybershield toolkit to support the secure provisioning flow via Secure Ram Based JTAG Kernel. Please reach out to your TI customer representative for more details.

Help and Support

For additional help and support, please visit E2E™ design support forum