英飞凌AURIX™系列单片机,凭借强大的实时性能、功能安全以及信息安全的优异设计,受到了客户的普遍欢迎。英飞凌也一直致力于打造强大的生态圈,助力我们的客户更方便、快速地完成设计。本文将进一步为大家介绍更多AURIX™干货,以及完善的生态体系新动态:
- AURIX™ TC3xx启动文件解析;
- AURIX™生态体系进一步完善:近期,国产RT-Thread操作系统加入AURIX™生态体系,宣布商业支持英飞凌科技车规级32位AURIX™ TriCore™多核微控制器。
启动文件流程图
TC3xx系列MCU复位后会从Ifx_Ssw_Tc0.c文件的_START()函数开始启动,启动的时候都会从CPU0开始运行,直到在_StartUpSoftware_Phase6()函数中才会根据用户配置依次启动其他核。
_START()
_START()的地址由link文件中RESET决定,以TASKING为例,在Link文件中:
#define RESET 0xA0000000
这个地址也必须和BMHD中的应用程序起始地址定义一致。
_START()代码解析
void _START(void)
{
Ifx_Ssw_jumpToFunction(__StartUpSoftware); // 直接跳转到__StartUpSoftware()
}
_StartUpSoftware()
_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()代码解析:
static void __StartUpSoftware(void)
{
Ifx_Ssw_setAddressReg(a1, __SDATA2(0)); // A1指向small data区域
Ifx_Ssw_MTCR(CPU_PSW, IFX_CFG_SSW_PSW_DEFAULT); // 设置CPU0的PSW寄存器
if (Ifx_Ssw_isApplicationReset() != 1)
{
Ifx_Ssw_jumpToFunction(__StartUpSoftware_Phase2);
}
else
{
Ifx_Ssw_jumpToFunction(__StartUpSoftware_Phase3ApplicationResetPath);
}
}
_StartUpSoftware_Phase2()
在这个API里面,会根据用户的配置,执行EVRC的初始化配置,LBIST测试,MONBIST测试。
_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);
}
_StartUpSoftware_Phase3PowerOnResetPath()
在这个API里面, 会初始化上下文,所谓的上下文就是SP指针和CSA。
在TriCore™中,SP是A10寄存器,在这里会把栈顶地址赋给A10。
CSA是存放上下文的区域,在TriCore™中,每当调用子函数或者进中断时,都会把一些通用寄存器自动存放在CSA区域 (Push),然后等到子函数返回或中断返回时,再把这些寄存器恢复(Pop)。
_StartUpSoftware_Phase3ApplicationResetPath代码解析:
_StartUpSoftware_Phase4
在这个API里面,会首先进行对CPU0 watchdog和safety watchdog进行一次喂狗(注意:复位后CPU0 watchdog和safety watchdog是使能的),然后根据用户配置,完成时钟初始化以及MBIST测试。
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*/
unsignedshort cpuWdtPassword = Ifx_Ssw_getCpuWatchdogPasswordInline(&MODULE_SCU.WDTCPU[0]);
unsignedshort 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);
}
IFX_CFG_SSW_CALLOUT_PLL_INIT() | 是否执行,取决于Ifx_Cfg_Ssw.h中的IFX_CFG_SSW_ENABLE_PLL_INIT的配置,这个函数用来初始化PLL配置。这个API所调用函数在IfxScuCcu.c中,所以要进行PLL初始化,需要在工程中添加这个LLD文件 |
IFX_CFG_SSW_CALLOUT_MBIST() | 是否执行,取决于Ifx_Cfg_Ssw.h中的IFX_CFG_SSW_ENABLE_MBIST的配置。这个函数用来执行MBIST测试,MBIST用于对RAM区域进行硬件自检。这个API所调用函数在IfxMtu.c,所以要进行这个测试,需要在工程中添加这个LLD文件 |
_StartUpSoftware_Phase5
在这个API里面, 只有SMU配置的一个API,但是这个API只是个空函数,所以其实在这里什么都没有做。
_StartUpSoftware_Phase3ApplicationResetPath
和_StartUpSoftware_Phase3PowerOnResetPath()一样。
_StartUpSoftware_Phase6
根据用户配置启动不同的内核。
IFX_CFG_SSW_ENABLE_TRICORE1 | 1: 启动Core1, 0: 不启动Core1 |
IFX_CFG_SSW_ENABLE_TRICORE2 | 1: 启动Core2, 0: 不启动Core2 |
IFX_CFG_SSW_ENABLE_TRICORE3 | 1: 启动Core3, 0: 不启动Core3 |
SYSCON寄存器的BHALT位用来设置Core是否启动,PC用来设置程序指针,Ifx_Ssw_startCore()中设置这两个寄存器,来启动其他内核。
_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)&__Core1_start); // 启动core 1
#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)&__Core2_start); // 启动core 2
#endif
#if (IFX_CFG_SSW_ENABLE_TRICORE2 == 0)
#if (IFX_CFG_SSW_ENABLE_TRICORE3 != 0)
Ifx_Ssw_startCore(&MODULE_CPU3, (unsigned int)&__Core3_start); // 启动core 3
#endif
#endif/* #if (IFX_CFG_SSW_ENABLE_TRICORE2 == 0) */
#endif/* #if (IFX_CFG_SSW_ENABLE_TRICORE1 == 0) */
Ifx_Ssw_jumpToFunction(__Core0_start);
}