上一篇主要介绍了TC397 SOTA相关配置寄存器,此篇主要讲解TC397 SOTA的实现过程,在开始之前先做如下的约定:
a : 在标准地址映射中活动的Bank称为A Bank
b : 在备用地址映射中活动的Bank称为B Bank
1、TC397 SOTA的初始化过程
一个全新的TC397芯片,SOTA的功能是未开启的且此种状态下使用的标准地址映射,因此可以按照一下的操作步骤启动TC397 的SOTA功能,下面的x取值范围0~15。
a : 用调试器把APP镜像烧写到A Bank和B Bank地址处
b : 向MARKERLx寄存器中写入0x00000055
c : 向MARKERHx寄存器中写入MARKERL0寄存器的地址
d : 向CONFERMATIONLx寄存器中写入0x57B5327F
f : 向CONFERMATIONHx寄存器中写入CONFERMATIONx寄存器的地址
g : 向UCB_OPT0中的SWAPEN(bit16和bit17)中写入1,来使能SOTA
h : 下电重启TC397
经过上面的配置过程,TC397在重启后便会进入SOTA模式,如果是新片子,经过一次操作,便会在重启后执行B Bank区域的代码。
在英飞凌的手册中也给出了如下的操作流程图供我们参考,如下所示:
2、TC397 SOTA RunTime Configuration
上面1中提到是初始状态进行一次SOTA操作,接下来我们看看SOTA启用后,是怎么进行APP更新的,首先先看手册中的流程图,后面再对此流程图进行解释。
根据上图以及个人调试SOTA的经验,进行如下的总结:
a : 此时TC397已经处于SOTA激活的状态了
b : 通过活动的Bank(B Bank)将新的APP程序写入到未激活的B Bank(比如A Bank)中,同时根据写入后的Bank 选择标准地址映射还是备用地址映射。
c : 先配置Bank 交换,根据当前激活的Bank来选择下一次复位后使用标准地址映射还是备用地址映射,即根据当前的Bank状态来更新UCB_SWAP_ORIG_MARKERLx+1寄存器的值是写0x00000055还是写0x000000AA。
d : 然后向UCB_SWAP_ORIG_CONFIRMATIONLx+1寄存器中写入0x57B5327F。
e : 接着往UCB_SWAP_ORIG_CONFIRMATIONHx+1寄存器中写入UCB_SWAP_ORIG_CONFIRMATIONLx+1寄存器的地址。
f : 然后向UCB_SWAP_ORIG_CONFIRMATIONLx寄存中写入0xFFFFFFFF,使当前UCB_SWAP_ORIG内容失效。
g : 最后向UCB的配置写入到UCB SWAP FLASH中。
3、TC397 SOTA 功能代码
在讲解代码之前,先做几点说明:
a : UCB FLASH Bank的特性是需要先进行擦除操作,然后才能进行写操作
3.1 UCB_SWAP_Enable的代码实现
void UCB_SWAP_Enable(void)
{
unsigned short safetyWdtPassword;
safetyWdtPassword = Ifx_Ssw_getSafetyWatchdogPassword();
Ifx_DMU_HF_PROCONTP *pHF_PROCONTP = (Ifx_DMU_HF_PROCONTP *)0xAF4041E8;
if(pHF_PROCONTP->B.SWAPEN != UCB_SWAP_EN)
{
Ifx_DMU_HF_PROCONTP HF_PROCONTP;
HF_PROCONTP.B.SWAPEN = UCB_SWAP_EN;
HF_PROCONTP.B.CPU0DDIS = CPUX_DIS;
HF_PROCONTP.B.CPU1DDIS = CPUX_DIS;
HF_PROCONTP.B.CPU2DDIS = CPUX_DIS;
HF_PROCONTP.B.CPU3DDIS = CPUX_DIS;
HF_PROCONTP.B.CPU4DDIS = CPUX_DIS;
HF_PROCONTP.B.CPU5DDIS = CPUX_DIS;
FlashUcb_waitUnbusy();
Ifx_Ssw_clearSafetyEndinit(safetyWdtPassword);
FlashUcb_eraseSector(UCB_DMU_OTP_ADDRESS);
Ifx_Ssw_setSafetyEndinit(safetyWdtPassword);
FlashUcb_waitUnbusy();
FlashUcb_enterPageMode();
FlashUcb_waitUnbusy();
FlashUcb_loadPage2X32(HF_PROCONTP.U, 0x00000000);
Ifx_Ssw_clearSafetyEndinit(safetyWdtPassword);
FlashUcb_writePage(UCB_DMU_HF_PROCONTP);
Ifx_Ssw_setSafetyEndinit(safetyWdtPassword);
FlashUcb_waitUnbusy();
FlashUcb_enterPageMode();
FlashUcb_waitUnbusy();
FlashUcb_loadPage2X32(UCB_SWAP_UNLOCKED, 0x00000000);
Ifx_Ssw_clearSafetyEndinit(safetyWdtPassword);
FlashUcb_writePage(UCB_OTP0_ORIG_CODE);
Ifx_Ssw_setSafetyEndinit(safetyWdtPassword);
FlashUcb_waitUnbusy();
}
}
3.2 UCB_SWAP_Disable代码实现
void UCB_SWAP_Disable(void)
{
unsigned short safetyWdtPassword;
safetyWdtPassword = Ifx_Ssw_getSafetyWatchdogPassword();
Ifx_DMU_HF_PROCONTP *pHF_PROCONTP = (Ifx_DMU_HF_PROCONTP *)0xAF4041E8;
if(pHF_PROCONTP->B.SWAPEN != UCB_SWAP_EN)
{
Ifx_DMU_HF_PROCONTP HF_PROCONTP;
HF_PROCONTP.B.SWAPEN = UCB_SWAP_DIS;
HF_PROCONTP.B.CPU0DDIS = CPUX_DEN;
HF_PROCONTP.B.CPU1DDIS = CPUX_DEN;
HF_PROCONTP.B.CPU2DDIS = CPUX_DEN;
HF_PROCONTP.B.CPU3DDIS = CPUX_DEN;
HF_PROCONTP.B.CPU4DDIS = CPUX_DEN;
HF_PROCONTP.B.CPU5DDIS = CPUX_DEN;
FlashUcb_waitUnbusy();
Ifx_Ssw_clearSafetyEndinit(safetyWdtPassword);
FlashUcb_eraseSector(UCB_DMU_OTP_ADDRESS);
Ifx_Ssw_setSafetyEndinit(safetyWdtPassword);
FlashUcb_waitUnbusy();
FlashUcb_enterPageMode();
FlashUcb_waitUnbusy();
FlashUcb_loadPage2X32(HF_PROCONTP.U, 0x00000000);
Ifx_Ssw_clearSafetyEndinit(safetyWdtPassword);
FlashUcb_writePage(UCB_DMU_HF_PROCONTP);
Ifx_Ssw_setSafetyEndinit(safetyWdtPassword);
FlashUcb_waitUnbusy();
FlashUcb_enterPageMode();
FlashUcb_waitUnbusy();
FlashUcb_loadPage2X32(UCB_SWAP_UNLOCKED, 0x00000000);
Ifx_Ssw_clearSafetyEndinit(safetyWdtPassword);
FlashUcb_writePage(UCB_OTP0_ORIG_CODE);
Ifx_Ssw_setSafetyEndinit(safetyWdtPassword);
FlashUcb_waitUnbusy();
}
}
在这里插入代码片
3.3 Swap_Init 代码实现
void Swap_Init(void)
{
uint8 i = 0;
Swap_Flag = FALSE;
Swap.ActiveMarkerNumber = 0;
if(A_BANK == SCU_SWAPCTRL.B.ADDRCFG)
{
Swap.ActiveBank = SWAP_A_BANK_ACTIVE;
}
else if(B_BANK == SCU_SWAPCTRL.B.ADDRCFG)
{
Swap.ActiveBank = SWAP_B_BANK_ACTIVE;
}
else
{
Swap.ActiveBank = SWAP_ACTIVE_ILLEGAL;
}
Confirm_Value = (*(uint32 *)UCB_SWAP_ORIG_CONFIRMATION_ADDRESS);
if((Confirm_Value == UCB_SWAP_UNLOCKED) || (Confirm_Value == UCB_SWAP_CONFIRMED))
{
Swap.ActiveUCB = UCB_SWAP_ORIG_ACTIVE;
Swap.ActiveAddress = UCB_SWAP_ORIG_ADDRESS;
}
else
{
Swap.ActiveUCB = UCB_SWAP_COPY_ACTIVE;
Swap.ActiveAddress = UCB_SWAP_COPY_ADDRESS;
}
for(i = 0; i < UCB_SWAP_SIZE; i++)
{
Swap.UCB.US.CONFIRMATIONLx = (*(uint32 *)(Swap.ActiveAddress + 0x00000008));
if(Swap.UCB.US.CONFIRMATIONLx != UCB_SWAP_CONFIRMED)
{
Swap.ActiveAddress = Swap.ActiveAddress + 0x00000010;
}
else
{
Swap.ActiveMarkerNumber = i;
break;
}
}
if(i >= (UCB_SWAP_SIZE -1))
{
Swap.ActiveMarkerNumber = 0;
Swap.EraseAtNextSwap = TRUE;
if(Swap.ActiveUCB == UCB_SWAP_ORIG_ACTIVE)
{
Swap.ActiveAddress = UCB_SWAP_ORIG_ADDRESS + 0xF0;
}
else
{
Swap.ActiveAddress = UCB_SWAP_COPY_ADDRESS + 0xF0;
}
}
}
在这里插入代码片
3.4 SOTA Runtim Configuration 代码实现
void Swap_Swich(void)
{
unsigned short safetyWdtPassword;
unsigned short swapOrigCopy = 0;
if(Swap_Flag == TRUE)
{
Swap_Flag = FALSE;
safetyWdtPassword = Ifx_Ssw_getSafetyWatchdogPassword();
IfxCpu_disableInterrupts();
if(Swap.EraseAtNextSwap == TRUE)
{
Swap.EraseAtNextSwap = FALSE;
swapOrigCopy = 1;
FlashUcb_waitUnbusy();
Ifx_Ssw_clearSafetyEndinit(safetyWdtPassword);
if(Swap.ActiveBank == UCB_SWAP_ORIG_ACTIVE)
{
FlashUcb_eraseSector(UCB_SWAP_COPY_ADDRESS);
}
else
{
FlashUcb_eraseSector(UCB_SWAP_ORIG_ADDRESS);
}
Ifx_Ssw_setSafetyEndinit(safetyWdtPassword);
FlashUcb_waitUnbusy();
FlashUcb_enterPageMode();
FlashUcb_waitUnbusy();
FlashUcb_loadPage2X32(UCB_SWAP_UNLOCKED, 0x00000000);
Ifx_Ssw_clearSafetyEndinit(safetyWdtPassword);
if(Swap.ActiveUCB == UCB_SWAP_ORIG_ACTIVE)
{
FlashUcb_writePage(UCB_SWAP_COPY_CONFIRMATION_ADDRESS);
Swap.ActiveAddress = UCB_SWAP_COPY_ADDRESS;
}
else if(Swap.ActiveUCB == UCB_SWAP_COPY_ACTIVE)
{
FlashUcb_writePage(UCB_SWAP_ORIG_CONFIRMATION_ADDRESS);
Swap.ActiveAddress = UCB_SWAP_ORIG_ADDRESS;
}
Ifx_Ssw_setSafetyEndinit(safetyWdtPassword);
FlashUcb_waitUnbusy();
}
else
{
FlashUcb_waitUnbusy();
FlashUcb_enterPageMode();
FlashUcb_waitUnbusy();
FlashUcb_loadPage2X32(UCB_SWAP_INVALIDATION, UCB_SWAP_INVALIDATION);
Ifx_Ssw_clearSafetyEndinit(safetyWdtPassword);
FlashUcb_writePage(Swap.ActiveAddress + 0x00000008);
Ifx_Ssw_setSafetyEndinit(safetyWdtPassword);
FlashUcb_waitUnbusy();
Swap.ActiveAddress = Swap.ActiveAddress + 0x00000010;
}
if(Swap.ActiveBank == SWAP_A_BANK_ACTIVE)
{
Swap.ActiveBank = SWAP_B_BANK_ACTIVE;
Swap.UCB.US.MARKERLx = UCB_SWAP_B_BANK_ACTIVE;
}
else
{
Swap.ActiveBank = SWAP_A_BANK_ACTIVE;
Swap.UCB.US.MARKERLx = UCB_SWAP_A_BANK_ACTIVE;
}
Swap.UCB.US.MARKERHx = Swap.ActiveAddress;
Swap.UCB.US.CONFIRMATIONLx = UCB_SWAP_CONFIRMED;
Swap.UCB.US.CONFIRMATIONHx = Swap.ActiveAddress + 0x00000008;
FlashUcb_waitUnbusy();
FlashUcb_enterPageMode();
FlashUcb_waitUnbusy();
FlashUcb_loadPage2X32(Swap.UCB.US.MARKERLx, Swap.UCB.US.MARKERHx);
Ifx_Ssw_clearSafetyEndinit(safetyWdtPassword);
FlashUcb_writePage(Swap.ActiveAddress);
Ifx_Ssw_setSafetyEndinit(safetyWdtPassword);
FlashUcb_waitUnbusy();
FlashUcb_enterPageMode();
FlashUcb_waitUnbusy();
FlashUcb_loadPage2X32(Swap.UCB.US.CONFIRMATIONLx, Swap.UCB.US.CONFIRMATIONHx);
Ifx_Ssw_clearSafetyEndinit(safetyWdtPassword);
FlashUcb_writePage(Swap.ActiveAddress + 0x00000008);
Ifx_Ssw_setSafetyEndinit(safetyWdtPassword);
FlashUcb_waitUnbusy();
if(swapOrigCopy)
{
swapOrigCopy = 0;
FlashUcb_enterPageMode();
FlashUcb_waitUnbusy();
FlashUcb_loadPage2X32(UCB_SWAP_INVALIDATION, 0x00000000);
if(Swap.ActiveUCB == UCB_SWAP_ORIG_ACTIVE)
{
FlashUcb_writePage(UCB_SWAP_ORIG_CONFIRMATION_ADDRESS);
}
else if(Swap.ActiveUCB == UCB_SWAP_COPY_ACTIVE)
{
FlashUcb_writePage(UCB_SWAP_COPY_CONFIRMATION_ADDRESS);
}
}
}
}在这里插入代码片
4、总结
以上就是TC397 SOTA功能的代码实现。