接上文,继续学习TC277的启动过程。分析启动函数
有关用的寄存器说明,参考文章
目录
TC27x寄存器学习
start函数分析
isync汇编指令(同步指令)
dsync汇编指令(同步数据),
1清除endinit
2设置中断堆栈
3启用对系统全局寄存器的写访问
4初始化SDA基指针
5关闭对系统全局寄存器的写访问
6关闭看门狗,恢复Endinit位
7初始化CSA
8初始化ram,拷贝rom数据到ram
9跳转主函数
__asm ("_START: movh.a %a10,hi:0xD000F000");
__asm (" lea %a10,[%a10]lo:0xD000F000");
__asm (" movh.a %a15,hi:_start");
__asm (" lea %a15,[%a15]lo:_start");
__asm (" ji %a15");
movh.a是(Move High to Address),将0xD000F000的高16bit写入address resgster A[10]地址寄存器中
A[10]是堆栈指针寄存器(SP)
lea指令(Load Effective Address)将0xD000F000的低16bit 写入address resgster A[10]的低16bit
0xD000F000应该表示SP地址值
A[15]是隐式地址寄存器, movh.a %a15,hi:_start 将 _start函数的地址高16位写入A[15]
ji指令(Jump Indirect)将A[15]的地址写入PC指针,并跳转到相应地址,即跳转到_start函数中执行
这个汇编的跳转没太懂,为什么要这么写?
void _start(void)
{
unsigned int coreID = _mfcr(CPU_CORE_ID) & IFX_CPU_CORE_ID_CORE_ID_MSK;
const CoreInit_t *core; /* the core initialisation structure */
core = &CPUInit[coreID];//初始化core0
cstart(core);//启动core0
}
_mfcr是汇编语言中的获取寄存器中的值
MTCR是写操作_mtcr(regaddr, val) 对寄存器写值
CPU_CORE_ID是Core Identification Register CSFR_Base + FE1CH
头文件中定义为 #define CPU_CORE_ID (0xFE1C)
CPU必须使用MTCR和MFCR指令访问自己的CSFR寄存器。其他CPU的CSFR寄存器可以通过XBAR_SRI使用加载和存储指令进行访问。任何CPU的SFR寄存器只能通过XBAR_SRI使用加载和存储指令进行访问。目前,CPUx的覆盖控制和访问保护寄存器映射到CPUx SFR地址范围。
CSFR-Core Special Function Registers.
void cstart(constCoreInit_t *)__attribute__ ((interrupt,noinline)); 声明为非内联函数。
interrupt此属性指示编译器以适合用作异常处理程序的方式生成函数
,强制完成之前的所有指令,然后刷新CPU管道,并在继续执行下一条指令之前使任何缓存的管道状态无效。ISYNC指令应该跟在MTCR指令之后。
强制所有数据访问在与指令关联的任何数据访问之前完成,为确保内存一致性,必须在访问活动CSA内存位置之前执行DSYNC指令。
/*
* the initial startup routine 初始化启动程序
* - initialise the global RAM 初始化全局ram
* - start the other CPUs 启动其他CPU
* - disable/enable System Watchdog 关闭/开启 系统开门狗
* - call the main function 调用主函数
*/
void cstart(const CoreInit_t *core)
{
/* reset endinit and disable watchdog */复位endinit 关闭看门狗
/* clear endinit bit in CPU0 WDT */
/* clear endinit bit in safety WDT */
WDT_ClearEndinit(volatileunsignedint *wdtbase)
{
unsigned int passwd;
passwd = *wdtbase;//读取寄存器中的值,获取原始密码
passwd &= 0xffffff00;//低8位清0
*wdtbase = passwd | 0xf1;//lck位置0,endinit位置1 应该是Password Access过程,[7:2]置111100
*wdtbase = passwd | 0xf2;//【2】lck位置1,endinit位置0,获取访问许可,应该是Modify Access过程
/* read back new value ==> synchronise LFI */
(void)*wdtbase;//读取更新返回值
}
/* setup interrupt stack */
_mtcr(CPU_ISP, (unsigned int)core->istack);//_mtcr(regaddr, val) 对寄存器写值
//加载中断向量指针寄存器
/* install trap handlers */
//加载陷阱向量表指针寄存器
_mtcr(CPU_PCON0, (unsigned int)0);//操作PMI0,程序允许缓存
_isync();//同步指令
/* initialise call depth counter */
psw = _mfcr(CPU_PSW);//读寄存器值
psw |= IFX_CPU_PSW_CDC_MSK;//禁用call depth counter
//关闭call depth counter,其实上面设置就够了
_mtcr(CPU_PSW, psw);//写入PSW
_isync();//同步指令
/* enable write access to system global registers */
psw = _mfcr(CPU_PSW);//读寄存器值
//启用A[0], A[1], A[8], A[9] 写入权限
_mtcr(CPU_PSW, psw);//写入PSW
_isync();
/* initialise SDA base pointers */
目的是啥?
/* disable write access to system global registers */
psw = _mfcr(CPU_PSW);
//关闭A[0], A[1], A[8], A[9] 写入权限
_mtcr(CPU_PSW, psw);
_isync();
/* disable Watchdogs */
if (core == &CPUInit[0])
{
/* safety WDT handled by CPU0 */
SCU_WDTSCON1.B.DR = 1;
WDT_SetEndinit(&SCU_WDTSCON0.U);
}
core->wdtCon1->B.DR = 1;
WDT_SetEndinit(&core->wdtCon0->U);
init_csa(core->csaBase, core->csaSize);
/* handle global clear and copy tables */
if (core == &CPUInit[0])
{
clear_table_func(&__clear_table);
copy_table_func(&__copy_table);
}
/* handle core specific clear and copy tables */
clear_table_func(core->cleartable);
copy_table_func(core->copytable);
....
(*core->main)(1, (char **)&core->ustack[0]);//调用core0的main函数
}
WDTCPU0定义的联合
/** \brief CPU WDT Control Register 0 */
typedef union
{
unsigned int U; /**< \brief Unsigned access */
signed int I; /**< \brief Signed access */
Ifx_SCU_WDTCPU_CON0_Bits B; /**< \brief Bitfield access */
} Ifx_SCU_WDTCPU_CON0;
/** \brief CPU WDT Control Register 0 */
typedef struct _Ifx_SCU_WDTCPU_CON0_Bits
{
Ifx_Strict_32Bit ENDINIT:1; /**< \brief [0:0] End-of-Initialization Control Bit (rwh) */
Ifx_Strict_32Bit LCK:1; /**< \brief [1:1] Lock Bit to Control Access to WDTxCON0 (rwh) */
Ifx_Strict_32Bit PW:14; /**< \brief [15:2] User-Definable Password Field for Access to WDTxCON0 (rwh) */
Ifx_Strict_32Bit REL:16; /**< \brief [31:16] Reload Value for the WDT (also Time Check Value) (rw) */
} Ifx_SCU_WDTCPU_CON0_Bits;
该main函数在Bswinit.c中
int main(void)
{
BswInit_PreInitPowerOn();
BswInit_InitializeOne();
BswInit_InitializeTwo();
EcuM_Init(); /* never returns */
return 0;
}
BswInit_PreInitPowerOn在BswInit_callout_Stubs.c中
可用于ASR模块未涵盖的任何与硬件相关的初始化
以上还没看到其他CPU启动的过程。需要继续分析后面的代码