AURIX™ BootROM
Tricore有一段自带的BROM:固化的启动代码,这段代码是英飞凌出厂就烧进去的,且无法覆盖,包括:
• 启动软件(SSW)。
• 实现附加功能的软件模块(Bootstrap loader)。
• 测试固件
Startup Software(SSW)
TC3xx系列MCU复位后会从Ifx_Ssw_Tc0.c文件的_START()函数开始启动,启动的时候都会从CPU0开始运行,直到在__StartUpSoftware_Phase6()函数中才会根据用户配置依次启动其他核。
_START()
代码解析
void _START(void)
{
Ifx_Ssw_jumpToFunction(__StartUpSoftware);
}
//直接跳转到__StartUpSoftware()
_START()的地址由link文件中RESET决定,以Tasking为例. 在Link文件中:
这个地址也必须和BMHD中的应用程序起始地址定义一致。
__StartUpSoftware()
代码解析:
static void __StartUpSoftware(void)
{
/* A1指向small data区域 */
Ifx_Ssw_setAddressReg(a1, __SDATA2(0));
/* 设置CPU0的PSW寄存器 */
Ifx_Ssw_MTCR(CPU_PSW, IFX_CFG_SSW_PSW_DEFAULT);
if (Ifx_Ssw_isApplicationReset() != 1)
{
Ifx_Ssw_jumpToFunction(__StartUpSoftware_Phase2);
}
else
{
Ifx_Ssw_jumpToFunction(__StartUpSoftware_Phase3ApplicationResetPath);
}
}
__StartUpSoftware()主要用来设置A1寄存器,设置PSW寄存器,以及判断是否是Application Reset, 从而进行不同的跳转。
在Tricore中A0,A1,A8,A9是全局地址寄存器,此处的A1所指向区域用来存放small RODATA, 所谓small data区域就是可以直接寻址。
PSW的默认值设的是0x980, 即Supervise mode, Global Address Register Write Permission Enable, Call Depth Count Enable, User Stack
__StartUpSoftware_Phase2()
代码解析:
static void __StartUpSoftware_Phase2(void)
{
/* Power and EVRC configurations */
IFX_CFG_SSW_CALLOUT_PMS_INIT(); //执行EVC初始化流程
/* LBIST Tests and evaluation */
IFX_CFG_SSW_CALLOUT_LBIST(); //执行LBIST测试
/* MONBIST Tests and evaluation */
IFX_CFG_SSW_CALLOUT_MONBIST(); //执行MONBIST测试
Ifx_Ssw_jumpToFunction(__StartUpSoftware_Phase3PowerOnResetPath);
}
在这个API里面,会根据用户的配置,执行EVRC的初始化配置,LBIST测试,MONBIST测试。
__StartUpSoftware_Phase3PowerOnResetPath()/ __StartUpSoftware_Phase3ApplicationResetPath
代码解析:
static void __StartUpSoftware_Phase3ApplicationResetPath(void)
{
IFX_SSW_INIT_CONTEXT(); //初始化上下文
Ifx_Ssw_jumpToFunction(__StartUpSoftware_Phase5);
}
static void __StartUpSoftware_Phase3ApplicationResetPath(void)
{
IFX_SSW_INIT_CONTEXT();
Ifx_Ssw_jumpToFunction(__StartUpSoftware_Phase5);
}
#define IFX_SSW_INIT_CONTEXT() \
{ \
/* Load user stack pointer */ \
Ifx_Ssw_setAddressReg(a10, __USTACK(0)); \
Ifx_Ssw_DSYNC(); \
\
/*Initialize the context save area for CPU0. Function Calls Possible */ \
/* Setup the context save area linked list */ \
Ifx_Ssw_initCSA((unsigned int *)__CSA(0), (unsigned int *)__CSA_END(0)); \
/* Clears any instruction buffer */ \
Ifx_Ssw_ISYNC(); \
}
在这个API里面, 会初始化上下文,所谓的上下文就是SP指针和CSA。
在Tricore中,SP是A10寄存器,在这里会把栈顶地址赋给A10.
CSA是存放上下文的区域,在Tricore中,每当调用子函数或者进中断时,都会把一些通用寄存器自动存放在CSA区域 (Push),然后等到子函数返回或中断返回时,再把这些寄存器恢复(Pop)
__StartUpSoftware_Phase3ApplicationResetPath 和__StartUpSoftware_Phase3PowerOnResetPath()一样。
__StartUpSoftware_Phase4
代码解析:
static void __StartUpSoftware_Phase4(void)
{
/* This is for ADAS chip, where clock is provided by MMIC chip. This has to be
* implemented according the board.
*/
IFX_CFG_SSW_CALLOUT_MMIC_CHECK();
{
/* Update safety and cpu watchdog reload value*/
unsigned short cpuWdtPassword = Ifx_Ssw_getCpuWatchdogPasswordInline(&MODULE_SCU.WDTCPU[0]);
unsigned short safetyWdtPassword = Ifx_Ssw_getSafetyWatchdogPasswordInline();
/* servicing watchdog timers */
Ifx_Ssw_serviceCpuWatchdog(&MODULE_SCU.WDTCPU[0], cpuWdtPassword);
Ifx_Ssw_serviceSafetyWatchdog(safetyWdtPassword);
}
/* Initialize the clock system */
IFX_CFG_SSW_CALLOUT_PLL_INIT();
/* MBIST Tests and evaluation */
IFX_CFG_SSW_CALLOUT_MBIST();
Ifx_Ssw_jumpToFunction(__StartUpSoftware_Phase5);
}
在这个API里面,会首先进行对CPU0 watchdog和safety watchdog进行一次喂狗(注意:复位后CPU0 watchdog和safety watchdog是使能的),然后根据用户配置,完成时钟初始化以及MBIST测试。
__StartUpSoftware_Phase5
在这个API里面, 只有SMU配置的一个API,但是这个API只是个空函数,所以其实在这里什么都没有做。
__StartUpSoftware_Phase6
代码解析:
static void __StartUpSoftware_Phase6(void)
{
/* Start remaining cores as a daisy-chain */
#if (IFX_CFG_SSW_ENABLE_TRICORE1 != 0)
Ifx_Ssw_startCore(&MODULE_CPU1, (unsigned int)__START(1)); //启动core1
#endif /* #if (IFX_CFG_CPU_CSTART_ENABLE_TRICORE1 != 0)*/
#if (IFX_CFG_SSW_ENABLE_TRICORE1 == 0)
#if (IFX_CFG_SSW_ENABLE_TRICORE2 != 0)
Ifx_Ssw_startCore(&MODULE_CPU2, (unsigned int)__START(2)); //启动core2
#endif
#if (IFX_CFG_SSW_ENABLE_TRICORE2 == 0)
#if (IFX_CFG_SSW_ENABLE_TRICORE3 != 0)
Ifx_Ssw_startCore(&MODULE_CPU3, (unsigned int)__START(3)); //启动core3
#endif
#if (IFX_CFG_SSW_ENABLE_TRICORE3 == 0)
#if (IFX_CFG_SSW_ENABLE_TRICORE4 != 0)
Ifx_Ssw_startCore(&MODULE_CPU4, (unsigned int)__START(4)); //启动core4
#endif
#if (IFX_CFG_SSW_ENABLE_TRICORE4 == 0)
#if (IFX_CFG_SSW_ENABLE_TRICORE5 != 0)
Ifx_Ssw_startCore(&MODULE_CPU5, (unsigned int)__START(5)); //启动core5
#endif
#endif /* #if (IFX_CFG_SSW_ENABLE_TRICORE4 == 0) */
#endif /* #if (IFX_CFG_SSW_ENABLE_TRICORE3 == 0) */
#endif /* #if (IFX_CFG_SSW_ENABLE_TRICORE2 == 0) */
#endif /* #if (IFX_CFG_SSW_ENABLE_TRICORE1 == 0) */
Ifx_Ssw_jumpToFunction(__Core0_start);
}
根据用户配置启动不同的内核。
SYSCON寄存器的BHALT位用来设置Core是否启动,PC用来设置程序指针,Ifx_Ssw_startCore()中设置这两个寄存器,来启动其他内核
Ifx_Ssw_startCore()
void Ifx_Ssw_startCore(Ifx_CPU *cpu, unsigned int programCounter)
{
/* 设置 PC */
cpu->PC.B.PC = (unsigned int)programCounter >> 1U;
/* release boot halt mode if required */
Ifx_CPU_SYSCON syscon;
syscon = cpu->SYSCON;
if (syscon.B.BHALT)
{
syscon.B.BHALT = 0U; //启动内核
cpu->SYSCON = syscon;
}
}
以TC38x为例,如果所有4个内核都启动,那么__StartUpSoftware_Phase6()中会启动CORE1。这个时候,__Core0_Start()和__Core1_Start()是同时运行的,在__Core1_Start()的最后会启动Core2,然后跳转到__Core2_Start(),在_Core2_Start() 最后会启动Core3, 然后跳转到__Core3_Start().
__Corex_start
以__Core0_Start()为例,在__Core0_Start()中,会根据配置使能PCACHE和DCACHE,设置A0, A8, A9地址,配置Trap和中断向量表起始地址,配置中断栈指针,初始化全局变量。
CACHE配置:
/*是否使能CACHE*/
{
Ifx_CPU_PCON0 pcon0;
pcon0.U = 0;
pcon0.B.PCBYP = IFX_CFG_SSW_ENABLE_TRICORE0_PCACHE ? 0 : 1; /* depending on the enable bypass bit is reset/set */
Ifx_Ssw_MTCR(CPU_PCON0, pcon0.U);
Ifx_Ssw_ISYNC();
}
{
Ifx_CPU_DCON0 dcon0;
dcon0.U = 0;
dcon0.B.DCBYP = IFX_CFG_SSW_ENABLE_TRICORE0_DCACHE ? 0 : 1; /* depending on the enable bypass bit is reset/set */
Ifx_Ssw_MTCR(CPU_DCON0, dcon0.U);
Ifx_Ssw_ISYNC();
}
是否使能CACHE,通过配置下面两个宏:
通过配置PCON0的PCBYP位来使能PCACHE:
通过配置DCON0的PCBYP来使能DCACHE:
Trap和中断向量配置:
BTV寄存器用来设置Trap向量表的首地址,在工程中Trap向量表的首地址在link文件中设置,通过下面语句会把link文件中Trap向量表地址赋给BTV.
Ifx_Ssw_MTCR(CPU_BTV, (unsigned int)__TRAPTAB(0));
BIV寄存器用来设置中断向量表的首地址,在工程中中断向量表的首地址在link文件中设置,通过下面语句会把link文件的中断向量表地址赋给BIV. 注意在Tricore中,默认状态下,中断向量是32字节对齐的,中断向量的位置不是固定的,而是由中断优先级决定的。
Ifx_Ssw_MTCR(CPU_BIV, (unsigned int)__INTTAB(0));
配置ISTACK:
在Tricore中,栈分为USTACK和ISTACK, 他们的使用由PSW.IS位来决定,默认配置PSW.IS=0,即在线程中的函数调用时,会用USTACK(A11)部分作为CPU的栈,而在中断函数中会用ISTACK(ISP)作为CPU的栈。USTACK和ISTACK大小和位置是在Link文件中配置的。下面语句设置ISP:
Ifx_Ssw_MTCR(CPU_ISP, (unsigned int)__ISTACK(0));
对于CPU0,在__StartUpSoftware_Phase3ApplicationResetPath()已经把USTACK的栈顶指针赋给了A10. 对于其他CPU,在各自的__Corex_Start()把USTACK的栈顶指针赋给了各自CPU的A10。
初始化全局变量:
下面函数用来初始化全局变量 (这个函数是编译器来实现的),全局变量分为两部分:Data和BSS。
Data: 存放有初始化全局变量,有初始化的全局变量的初始值最初是放在Flash中,在这个函数里面,会把初始值从Flash赋给全局变量。
BSS: BSS段用于存放没有初始化值的全局变量,在这个函数里面会把没有初始化值的全局变量清零。
/* Initialization of C runtime variables */
Ifx_Ssw_C_Init();
对于其它__Corex_Start()而言,和__Core0_Start()的流程基本一样,另外增加了把USTACK栈顶指针赋给A10的操作和PSW初始化操作。
在各个CPU的__Corex_Start()最后会跳转到各自的corex_main()中运行。
补充知识
TriCore架构寄存器
TriCore架构寄存器包括:16个通用的地址寄存器A[0]~A[15],16个通用的数据寄存器D[0]~D[15],1个PC(Program Counter)寄存器,1个程序状态字寄存器PSW(Program Status Word),1个上下文信息寄存器PCXI( Previous Context Information register)。除了这些,还有Core Special Function Registers (CSFRs),这里不一一展开。上述寄存器均是32 Bit寄存器,TriCore架构寄存器如下所示:
通用寄存器中,编号0~7对应的[地址寄存器|数据寄存器]称为低位寄存器(Lower Registers),编号8~15对应的[地址寄存器|数据寄存器]称为高位寄存器(Upper Registers)。
PSW、PCXI不仅记录着程序运行的状态信息,而且与PC寄存器一样,是程序切换过程中,存储(Save)和恢复(Restore)上下文的重要组成部分。
A[10]、A[11]、A[15]、D[15]这4个通用寄存器还有特殊功能:
A[10]:栈指针寄存器Stack Pointer (SP) register
A[11]:返回地址寄存器Return Address (RA) register
A[15]:隐式基地址寄存器Implicit Address register
D[15]:隐式数据寄存器Implicit Data register
A[0]、A[1]、A[8]、A[9]是系统全局寄存器,也就是说在函数调用、中断发生过程中,上下文的Save和Restore不会存储这4个寄存器中的信息。
这里需要着重关注一下A[11]和D[15]寄存器。这两个寄存器对于Bug问题的排查非常有用。
当程序异常时,
D[15]寄存器存储记录TIN(Trap Identification Number),
A[11]记录Trap的入口地址。
如果能获取这两个信息,很多问题可被快速定位。注意,如果Bug问题是异步的(Asynchronous),A[11]寄存器最近捕获的地址并不一定是问题发生点的入口地址。
D[15]寄存器很有用,在Tricore架构中,Trap分为8个等级:MMU (Memory Management Unit)、 Internal Protection、 Instruction Error、Context Management、System Bus and Peripherals、Assertion Trap、System Call、Non-Maskable Interrupt (NMI)。通过D[15]记录的TIN号即可确认Trap的Class,因此,可以在Trap程序中,将D[15]和A[11]寄存器的信息存储到NVM中,以便于Bug问题的排查。
文章知识点与官方知识档案匹配,可进一步学习相关知识
————————————————
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/2301_76563067/article/details/131324733
|