RW61x Shadow Registers#

Introduction#

The NXP tool, shadowregs (see User Guide), control your OTP fuses during development or testing. It enables the creation of “copies” of OTP fuses in the form of shadow registers. After each power-on reset, these shadow registers are cleared, and the default OTP fuses are loaded. It’s important to note two small limitations: the device must be in a lifecycle that supports shadow registers, and certain registers are not included in shadow registers.

Supported Commands#

  • fuses-script - Generate BLHOST script to burn up fuses in device by configuration.

  • get-template - Generate the template of Shadow registers YAML configuration file.

  • getreg - Print the current value of one shadow register.

  • loadconfig - Load new state of shadow registers from YAML file into micro controller.

  • printregs - Print all Shadow registers including theirs current values.

  • reset - Reset connected device.

  • saveconfig - Save current state of shadow registers to YAML file.

  • setreg - The command sets a value of one shadow register defined by parameter.

Let’s prepare the environment#

%run ../init_notebook.ipynb

import os
import pprint
import yaml

pp = pprint.PrettyPrinter(indent=4)

WORKSPACE = "workspace/" # change this to path to your workspace
INPUTS = "inputs/"

# choose debug interface
INTERFACE = "-i jlink"
# family
FAMILY = "-f rw61x"
env: JUPYTER_SPSDK=1
Created `%!` as an alias for `%execute`.

Device preparation#

  • Have the device in debug mode.

RW61X-EVK

# check availability of debug probe 
%! nxpdebugmbox $INTERFACE test-connection
nxpdebugmbox -i jlink test-connection 
  #   Interface   Id           Description             
-------------------------------------------------------
  0   Jlink       1061995210   Segger J-Link MCU-Link  
The device is accessible for debugging.

Compare the current state of shadowregs with defaults#

  • Verify that your shadow registers are in the default state.

# save differences comparing to defaults
SR_DIFF_PATH = os.path.join(WORKSPACE, "sr_diff_rw61x.yml")

%! shadowregs $INTERFACE $FAMILY saveconfig -o $SR_DIFF_PATH -d
shadowregs -i jlink -f rw61x saveconfig -o workspace/sr_diff_rw61x.yml -d 
  #   Interface   Id           Description             
-------------------------------------------------------
  0   Jlink       1061995210   Segger J-Link MCU-Link  
The Shadow registers has been saved into spsdk\examples\rw61x_shadowregs\workspace\sr_diff_rw61x.yml YAML file
# optional but recommended: reset connected device
%! shadowregs $INTERFACE $FAMILY reset
shadowregs -i jlink -f rw61x reset 
  #   Interface   Id           Description             
-------------------------------------------------------
  0   Jlink       1061995210   Segger J-Link MCU-Link  
The target has been reset.

Generate shadowregs template#

# generate the template of shadow registers
SR_TEMPLATE_PATH = os.path.join(WORKSPACE, "sr_template_rw61x.yml")

%! shadowregs $FAMILY get-template -o $SR_TEMPLATE_PATH --force
shadowregs -f rw61x get-template -o workspace/sr_template_rw61x.yml --force 
The Shadow registers template for rw61x has been saved into spsdk\examples\rw61x_shadowregs\workspace\sr_template_rw61x.yml YAML file

Prepare shadowregs for dual boot#

In this section, one of the possible use cases of shadow registers will be presented.

  • Dual boot is normally not possible on RW61x devices without configuring the registers.

  • Dual boot represents the possibility to write two images and always boot the image that has the higher image version.

NOTICE: Switch the device to ISP mode (U38: OFF OFF OFF ON)!

# modification of shadowregs for dual boot
with open(SR_TEMPLATE_PATH) as sr_rw61x:
    # load yaml configuration to dictionary
    sr = yaml.safe_load(sr_rw61x)
    # change paths
    sr["registers"]["BOOT_CFG0"]["DICE_SKIP"] = "DISABLED"
    sr["registers"]["BOOT_CFG0"]["PRIMARY_BOOT_SOURCE"] = "FLEXSPI_BOOT"
    sr["registers"]["BOOT_CFG2"]["FLEXSPI_IMAGE_OFFSET"] = "0x1"
    sr["registers"]["LIFE_CYCLE_STATE"]["LCS[7:0]"] = "Develop2"
    sr["registers"]["LIFE_CYCLE_STATE"]["LCS_REDUNDANT[7:0]"] = "Develop2"

with open(SR_TEMPLATE_PATH, "w+") as sr_rw61x:
    print("Shadowregs config:")
    pp.pprint(sr)
    # dump the dictionary back to YAML
    yaml.dump(sr, sr_rw61x)
Shadowregs config:
{   'family': 'rt5xx',
    'registers': {   'BOOT_CFG0': {   'BOOT_CLK_SPEED': 0,
                                      'BOOT_FAIL_PIN': 0,
                                      'BOOT_FAIL_PORT': 0,
                                      'DEFAULT_ISP_MODE': 'AUTO_ISP',
                                      'DICE_INC_OTP': 'NOT_INCLUDED',
                                      'DICE_SKIP': 'DISABLED',
                                      'PRIMARY_BOOT_SOURCE': 'FLEXSPI_BOOT',
                                      'REDUNDANT_SPI_PORT': 'FC0',
                                      'SECURE_BOOT_EN': 'DISABLED',
                                      'STOP_ON_FAILURE': 0,
                                      'TZM_IMAGE_TYPE': 'IGNORED'},
                     'BOOT_CFG1': {   'FLEXSPI_AUTO_PROBE_EN': 'FLASH_AUTO_PROBE',
                                      'FLEXSPI_DUMMY_CYCLES': 'AUTO_PROB',
                                      'FLEXSPI_FLASH_TYPE': 'FLEXSPI_SDR_3B',
                                      'FLEXSPI_FREQUENCY': 'FLEXSPI_100MHZ',
                                      'FLEXSPI_HOLD_TIME': 'NO_DELAY',
                                      'FLEXSPI_PROBE_TYPE': 'QSPI_NOR',
                                      'FLEXSPI_PWR_HOLD_TIME': 'NO_DELAY',
                                      'FLEXSPI_RST_HOLD_TIME': 'NO_DELAY',
                                      'FLEXSPI_RST_SEQ': 'NO_RESET_PERFORMED',
                                      'FLEXSPI_WUP_HOLD_TIME': 'NO_DELAY',
                                      'FLEXSPI_WUP_SEQ': 'NO_RESET_PERFORMED'},
                     'BOOT_CFG2': {   'FLEXSPI_DELAY_CELL_NUM': 0,
                                      'FLEXSPI_IMAGE_OFFSET': '0x1',
                                      'FLEXSPI_IMAGE_SIZE': 'SIZE_OFFSET'},
                     'BOOT_CFG3': {   'ENABLE_CRC_CHECK': 0,
                                      'ENF_CNSA': 'P-256_KEY',
                                      'FIPS_AES_STEN': 'SKIP_SELF_TEEST_RUN',
                                      'FIPS_CMAC_STEN': 'SKIP_SELF_TEEST_RUN',
                                      'FIPS_DRBG_STEN': 'SKIP_SELF_TEEST_RUN',
                                      'FIPS_ECDSA_STEN': 'SKIP_SELF_TEEST_RUN',
                                      'FIPS_KDF_STEN': 'SKIP_SELF_TEEST_RUN',
                                      'FIPS_SHA_STEN': 'SKIP_SELF_TEEST_RUN',
                                      'ROTK0_USAGE': 'DebugCA_ImageCA_FwCA_ImageKey_FwKey',
                                      'ROTK1_USAGE': 'DebugCA_ImageCA_FwCA_ImageKey_FwKey',
                                      'ROTK2_USAGE': 'DebugCA_ImageCA_FwCA_ImageKey_FwKey',
                                      'ROTK3_USAGE': 'DebugCA_ImageCA_FwCA_ImageKey_FwKey',
                                      'SKIP_PM_SIGN_VERIFCATION': 0},
                     'BOOT_CFG5': {'USB_PID': 0, 'USB_VID': 0},
                     'BOOT_CFG6': {'SDIO_PID': 0, 'SDIO_VID': 0},
                     'DCFG_CC_SOCU': {   'DFLT_CPU1DBGEN': 'DISABLED',
                                         'DFLT_CPU1NIDEN': 'DISABLED',
                                         'DFLT_CPU2DBGEN': 'DISABLED',
                                         'DFLT_CPU2NIDEN': 'DISABLED',
                                         'DFLT_DBGEN': 'DISABLED',
                                         'DFLT_FACMDEN': 'DISABLED',
                                         'DFLT_ISPCMDEN': 'DISABLED',
                                         'DFLT_NIDEN': 'DISABLED',
                                         'DFLT_SPIDEN': 'DISABLED',
                                         'DFLT_SPNIDEN': 'DISABLED',
                                         'DFLT_TAPEN': 'DISABLED',
                                         'FORCE_UUID_MATCH': 0,
                                         'PINNED_CPU1DBGEN': 'DAR_CC',
                                         'PINNED_CPU1NIDEN': 'DAR_CC',
                                         'PINNED_CPU2DBGEN': 'DAR_CC',
                                         'PINNED_CPU2NIDEN': 'DAR_CC',
                                         'PINNED_DBGEN': 'DAR_CC',
                                         'PINNED_FACMDEN': 'DAR_CC',
                                         'PINNED_ISPCMDEN': 'DAR_CC',
                                         'PINNED_NIDEN': 'DAR_CC',
                                         'PINNED_SPIDEN': 'DAR_CC',
                                         'PINNED_SPNIDEN': 'DAR_CC',
                                         'PINNED_TAPEN': 'DAR_CC'},
                     'DCFG_CC_SOCU_AP': '0x00000000',
                     'DCFG_CC_SOCU_NS': {   'DFLT_CPU1DBGEN_NS': 'DISABLED',
                                            'DFLT_CPU1NIDEN_NS': 'DISABLED',
                                            'DFLT_CPU2DBGEN_NS': 'DISABLED',
                                            'DFLT_CPU2NIDEN_NS': 'DISABLED',
                                            'DFLT_DBGEN_NS': 'DISABLED',
                                            'DFLT_FACMDEN_NS': 'DISABLED',
                                            'DFLT_ISPCMDEN_NS': 'DISABLED',
                                            'DFLT_NIDEN_NS': 'DISABLED',
                                            'DFLT_SPIDEN_NS': 'DISABLED',
                                            'DFLT_SPNIDEN_NS': 'DISABLED',
                                            'DFLT_TAPEN_NS': 'DISABLED',
                                            'FORCE_UUID_MATCH_NS': 0,
                                            'PINNED_CPU1DBGEN_NS': 'DAR_CC',
                                            'PINNED_CPU1NIDEN_NS': 'DAR_CC',
                                            'PINNED_CPU2DBGEN_NS': 'DAR_CC',
                                            'PINNED_CPU2NIDEN_NS': 'DAR_CC',
                                            'PINNED_DBGEN_NS': 'DAR_CC',
                                            'PINNED_FACMDEN_NS': 'DAR_CC',
                                            'PINNED_ISPCMDEN_NS': 'DAR_CC',
                                            'PINNED_NIDEN_NS': 'DAR_CC',
                                            'PINNED_SPIDEN_NS': 'DAR_CC',
                                            'PINNED_SPNIDEN_NS': 'DAR_CC',
                                            'PINNED_TAPEN_NS': 'DAR_CC'},
                     'LIFE_CYCLE_STATE': {   'LCS[7:0]': 'Develop2',
                                             'LCS_REDUNDANT[7:0]': 'Develop2',
                                             'Redundancy': 0},
                     'RKTH': '0000000000000000000000000000000000000000000000000000000000000000',
                     'SEC_BOOT_CFG0': {   'FA_MODE_EN': 0,
                                          'REVOKE_ROOTKEY0': 'ENABLED',
                                          'REVOKE_ROOTKEY1': 'ENABLED',
                                          'REVOKE_ROOTKEY2': 'ENABLED',
                                          'REVOKE_ROOTKEY3': 'ENABLED',
                                          'Redundancy': 0},
                     'SEC_BOOT_CFG1': {'DAP_VENDOR_USAGE': 0, 'Redundancy': 0},
                     'SEC_BOOT_CFG2': {   'REVOKE_IMG_KEY[15:0]': 0,
                                          'Redundancy': 0},
                     'SEC_BOOT_CFG3': {   'REVOKE_IMG_KEY[31:16]': 0,
                                          'Redundancy': 0}},
    'revision': 'latest'}
# list available connected devices
%! nxpdevscan
nxpdevscan 
-------- Connected NXP SDIO Devices --------

-------- Connected NXP USB Devices --------

-------- Connected NXP UART Devices --------

Port: COM5
Type: mboot device

-------- Connected NXP SIO Devices --------
# choose com port for rw61x
UART_CONNECTION = "-p com5"
# memory configuration
FCB_PATH = os.path.join(INPUTS, "converted_fcb.bin")

%! blhost $UART_CONNECTION write-memory 0x2000F000 $FCB_PATH
%! blhost $UART_CONNECTION configure-memory 9 0x2000F000
%! blhost $UART_CONNECTION flash-erase-region 0x08000000 25000
%! blhost $UART_CONNECTION flash-erase-region 0x08040000 25000
%! blhost $UART_CONNECTION fill-memory 0x2000F000 4 0xF000000F 
%! blhost $UART_CONNECTION configure-memory 9 0x2000F000
%! blhost $UART_CONNECTION write-memory 0x08040400 $FCB_PATH
blhost -p com5 write-memory 0x2000F000 inputs/converted_fcb.bin 
Writing memory
Response status = 0 (0x0) Success.
Response word 1 = 512 (0x200)
blhost -p com5 configure-memory 9 0x2000F000 
Response status = 0 (0x0) Success.
blhost -p com5 flash-erase-region 0x08000000 25000 
Response status = 0 (0x0) Success.
blhost -p com5 flash-erase-region 0x08040000 25000 
Response status = 0 (0x0) Success.
blhost -p com5 fill-memory 0x2000F000 4 0xF000000F 
Response status = 0 (0x0) Success.
blhost -p com5 configure-memory 9 0x2000F000 
Response status = 0 (0x0) Success.
blhost -p com5 write-memory 0x08040400 inputs/converted_fcb.bin 
Writing memory
Response status = 0 (0x0) Success.
Response word 1 = 512 (0x200)
# write images and versions
LED_BLINKY_PATH = os.path.join(INPUTS, "mbi_crc_led_blinky.bin")
HELLO_WORLD_PATH = os.path.join(INPUTS, "mbi_crc_hello_world.bin")
IMG_V0_PATH = os.path.join(INPUTS, "img_v0.bin")
IMG_V1_PATH = os.path.join(INPUTS, "img_v1.bin")

%! blhost $UART_CONNECTION write-memory 0x08000600 $IMG_V0_PATH
%! blhost $UART_CONNECTION write-memory 0x08001000 $LED_BLINKY_PATH

%! blhost $UART_CONNECTION write-memory 0x08040600 $IMG_V1_PATH
%! blhost $UART_CONNECTION write-memory 0x08041000 $HELLO_WORLD_PATH
blhost -p com5 write-memory 0x08000600 inputs/img_v0.bin 
Writing memory
Response status = 0 (0x0) Success.
Response word 1 = 4 (0x4)
blhost -p com5 write-memory 0x08001000 inputs/mbi_crc_led_blinky.bin 
Writing memory
Response status = 0 (0x0) Success.
Response word 1 = 14008 (0x36b8)
blhost -p com5 write-memory 0x08040600 inputs/img_v1.bin 
Writing memory
Response status = 0 (0x0) Success.
Response word 1 = 4 (0x4)
blhost -p com5 write-memory 0x08041000 inputs/mbi_crc_hello_world.bin 
Writing memory
Response status = 0 (0x0) Success.
Response word 1 = 22044 (0x561c)
# load modified shadowregs
%! shadowregs $INTERFACE $FAMILY loadconfig -c $SR_TEMPLATE_PATH
shadowregs -i jlink -f rw61x loadconfig -c workspace/sr_template_rw61x.yml 
  #   Interface   Id           Description             
-------------------------------------------------------
  0   Jlink       1061995210   Segger J-Link MCU-Link  
The Shadow registers has been loaded by configuration in spsdk\examples\rw61x_shadowregs\workspace\sr_template_rw61x.yml YAML file
# reset the device and run image
%! shadowregs $INTERFACE $FAMILY reset
shadowregs -i jlink -f rw61x reset 
  #   Interface   Id           Description             
-------------------------------------------------------
  0   Jlink       1061995210   Segger J-Link MCU-Link  
The target has been reset.