【简介】
S32K3XX 系列的芯片启动首先会运行SBAF 代码在固定的几个位置查找是否有合法的IVT(Image vector table) 信息,IVT 的定义输入内部含有镜像的地址信息,配置项目的信息。对应的IVT 定义如下
对应的C结构体可以按照如下的格式来定义。
typedef struct { /*00h*/ uint32_t IVT_header; /**< @brief IVT header marker */ /*04h*/ uint32_t bootCfgWord; /**< @brief Boot Configuration Word */ /*08h*/ uint32_t reserved1; /**< @brief 4 bytes reserved */ /*0Ch*/ uint32_t pAppImg_addr_0; /**< @brief Application address for Boot Target 0 */ /*10h*/ uint32_t reserved2; /**< @brief 4 bytes reserved */ /*14h*/ uint32_t pAppImg_addr_1; /**< @brief Application address for Boot Target 1 */ /*18h*/ uint32_t reserved3[3]; /**< @brief 4 bytes reserved */ /*24h*/ uint32_t LCCfgWord; /**< @brief Life-Cycle configuration word */ /*28h*/ uint32_t reserved4; /*2Ch*/ uint32_t pHSE; /**< @brief pointer to HSE image */ /*30h*/ uint32_t AppBL; /**< @brief 192 bytes reserved */ /*34h*/ uint32_t reserved5[3]; /**< @brief 192 bytes reserved */ /*40h*/ uint32_t appRecoveryAddr; /**< @brief Pointer to start address of application core for secure recovery mode */ /*44h*/ uint32_t appRecoverySize; /**< @brief Length of Recovery Application */ /*48h*/ uint32_t reserved6[39]; /**< @brief 156 bytes reserved */ /*E4h*/ uint32_t randomVector[3]; /**< @brief Initialization vector value to be used in calculation of GMAC */ /*F0h*/ uint32_t GMAC[4]; /**< @brief GMAC TAG over the IVT image */ } HseMid_IVT_t;
以下是SBAF 的查找IVT 启动APP 程序的流程图
IVT 的地址需要在固定的几个位置存放,以下是IVT可以存放的位置说明。
我们在上一篇的串口测试程序中使用的地址为0x400000,我们在此基础上修改程序IVT 配置让程序运行在0X800000,我们更新IVT中core 的运行地址为0x800000
同时修改程序的链接地址为0x800000
将程序下载到板子中运行,IVT 已经按照预期的配置从0x800000地址启动程序了。
程序按照预期打印hello world
上述的IVT 不仅可以指定每个core 的代打的运行地址,还可以指定HSE 安装时的加密镜像的地址,用于HSE firmware 的安装,HSE 的安装之前此贴有介绍(【S32K3XX】HSE固件安装配置说明)
上述代码就是更新IVT 中的HSE 镜像的地址来通知HSE core 从对应的地址来安装HSE firmware
IVT 中还定义个一个Word BCW(boot config word)用于配置boot选项,安全启动的配置开关就是在此配置,SBAF 代码会根据配置来执行boot 流程,BCW 配置定义如下
其中BIT3 为secure boot 的配置开关,一旦配置好了安全启动的key,就可以通过该bit 通知SBAF 运行secure boot 流程,本地开启安全启动后读取IVT的信息,发现bit3也是配置为1.
以下代码是开启secure boot 代码,代码中会更新IVT 的 BCW 的bit3 BOOT_SEQ 位
hseSrvResponse_t HseMid_SecureBoot_EnableSeq( uint32_t UpdateAddress , uint32_t SourceAddress , boolean isEnableSecureBoot ) { hseSrvResponse_t hseSrvResponse = 0xFFFFFFFF; Fls_CheckStatusType flsStatus = 0; HseMid_IVT_t TempIvt ; /* save origin ivt */ MEMCPY((void *)&TempIvt, (void *)( SourceAddress ), sizeof(HseMid_IVT_t) ); _TRY_START; if ( FALSE == isEnableSecureBoot) { TempIvt.bootCfgWord &= ~IVT_BOOT_CFG_WORD_BOOT_SEQ; } else { hseMid_Attr_t getAttrVal; hseSrvResponse = HseMid_Admin_GetAttr(HSE_ENABLE_BOOT_AUTH_ATTR_ID, sizeof(getAttrVal.ivtAuthConfig_OTP), &getAttrVal, NULL); _THROW_DIFF( HSE_SRV_RSP_OK , hseSrvResponse ); if( HSE_IVT_NO_AUTH == getAttrVal.ivtAuthConfig_OTP ) { TempIvt.bootCfgWord |= IVT_BOOT_CFG_WORD_BOOT_SEQ; /* 1. FXOSC enablement flag must be enabled * 2. PLL is configured only when BOOT_SEQ==1 */ /* uint64_t* FxoscValAddr = (uint64_t*)(UTEST_BASE_ADDRESS+0x50u) ; if( FXOSC_ENABLE_MAGIC_NUMBER == (uint32_t)( ((uint64_t)(*FxoscValAddr)) >> 32u ) ) */ if( 0u != (uint32_t)((IP_DCM_GPR->DCMROF21) >> DCM_GPR_DCMROF21_HSE_CLK_MODE_OPTION_SHIFT) ) { TempIvt.bootCfgWord |= IVT_BOOT_CFG_WORD_PLL_ENABLE; } } else { /* generate GMAC of IVT, write to block 0 ivt address */ } } /* erase IVT location */ flsStatus = gHsePort_FlsIf.eraseApi( UpdateAddress , 1U ); hseSrvResponse = ( FLS_JOB_OK == flsStatus ) ? HSE_SRV_RSP_OK : 0xFFFFFFFF ; _THROW_DIFF( HSE_SRV_RSP_OK , hseSrvResponse ); flsStatus = gHsePort_FlsIf.writeApi( UpdateAddress, (uint8_t* )&TempIvt,(uint32_t)sizeof(HseMid_IVT_t) ) ; hseSrvResponse = ( FLS_JOB_OK == flsStatus ) ? HSE_SRV_RSP_OK : 0xFFFFFFFF ; _THROW_DIFF( HSE_SRV_RSP_OK , hseSrvResponse ); _TRY_END; return hseSrvResponse; }
从该芯片的boot 流程图也可以看出,在设置了上述的BOOT_SEQ 后会执行HSE_FW_boot 的流程进行校验,校验通过后运行app 程序。