TC27x启动过程(2)-TC277
接上文,继续学习TC277的启动过程。分析启动函数
有关用的寄存器说明,参考文章
TC27x寄存器学习
目录
TC27x寄存器学习
start函数分析
isync汇编指令(同步指令)
dsync汇编指令(同步数据),
1清除endinit
2设置中断堆栈
3启用对系统全局寄存器的写访问
4初始化SDA基指针
5关闭对系统全局寄存器的写访问
6关闭看门狗,恢复Endinit位
7初始化CSA
8初始化ram,拷贝rom数据到ram
9跳转主函数
start函数分析
__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此属性指示编译器以适合用作异常处理程序的方式生成函数
isync汇编指令(同步指令)
,强制完成之前的所有指令,然后刷新CPU管道,并在继续执行下一条指令之前使任何缓存的管道状态无效。ISYNC指令应该跟在MTCR指令之后。
dsync汇编指令(同步数据),
强制所有数据访问在与指令关联的任何数据访问之前完成,为确保内存一致性,必须在访问活动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)
{
1清除endinit
/* 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;//读取更新返回值
}
2设置中断堆栈
/* 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();//同步指令
3启用对系统全局寄存器的写访问
/* 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();
4初始化SDA基指针
/* initialise SDA base pointers */
目的是啥?
5关闭对系统全局寄存器的写访问
/* disable write access to system global registers */
psw = _mfcr(CPU_PSW);
//关闭A[0], A[1], A[8], A[9] 写入权限
_mtcr(CPU_PSW, psw);
_isync();
6关闭看门狗,恢复Endinit位
/* 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);
7初始化CSA
init_csa(core->csaBase, core->csaSize);
8初始化ram,拷贝rom数据到ram
/* 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);
....
9跳转主函数
(*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启动的过程。需要继续分析后面的代码
TC27x启动过程(2)-TC277相关推荐
- TC27x启动过程(3)-TC277
接上文,继续分析TC277多核启动过程 目录 main函数分析 Os_InitMemory->Step1 Os_Init->Os_Api_Init:执行step2 BswInit_Init ...
- Android系统的启动过程
Android系统的启动过程可以简单地总结为以下几个流程: 加载BootLoader -> 初始化内核 -> 启动init进程 -> init进程fork出Zygote(孵化器)进程 ...
- Android系统默认Home应用程序(Launcher)的启动过程源代码分析
在前面一篇文章中,我们分析了Android系统在启动时安装应用程序的过程,这些应用程序安装好之后,还需要有一个Home应用程序来负责把它们在桌面上展示出来,在Android系统中,这个默认的Home应 ...
- Linux0.11内核引导启动过程概述
Linux0.11仅支持x86架构.它的内核引导启动程序在文件夹boot内,共有三个汇编代码文件.按照启动流程依次是: (1)bootsect.s.boot是启动引导的意思,sect即sector,是 ...
- linux启动sql server数据库,SQL Server数据库启动过程详解及启动不起来的问题分析及解决方法...
第五步.启动系统数据库model model系统数据库同样也是SQL Server启动过程中用到的一个非常关键的数据库,如果这个库损坏,SQL Server启动也会失败,关于model数据不能启动的原 ...
- Linux必知必会的目录与启动过程
第1章 /etc/目录 1.1 /etc/sysconfig/network-scripts/ifcfg-eth0 linux第一块网卡的配置文件 [root@znix ~]# cat /etc/sy ...
- Spring Boot启动过程(二)
书接上篇 该说refreshContext(context)了,首先是判断context是否是AbstractApplicationContext派生类的实例,之后调用了强转为AbstractAppl ...
- Linux X Window System运行原理和启动过程
本文主要说明X Window System的基本运行原理,其启动过程,及常见的跨网络运行X Window System. 一) 基本运行原理 X Window System采用C/S结构,但和我们常见 ...
- Spring 容器的启动过程
点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 本文来源:http://r6f.cn/b47K 一. 前言 ...
- golang源码分析-启动过程概述
golang源码分析-启动过程概述 golang语言作为根据CSP模型实现的一种强类型的语言,本文主要就是通过简单的实例来分析一下golang语言的启动流程,为深入了解与学习做铺垫. golang代码 ...
最新文章
- java11 是长期支持_这里有你不得不了解的Java 11版本特性说明
- 清华Thinker团队提出AI计算芯片存储优化新方法 | ISCA 2018中国唯一一作论文
- 虚拟化基础架构Windows 2008篇之8-添加启动映像
- 批处理文件中判断是否64位系统
- java.lang包含_原因:java.lang.IllegalArgumentException:包含(1)...
- 39道高级java面试题及答案(最新)
- java jax-rs_在Java EE 7和WildFly中使用Bean验证来验证JAX-RS资源数据
- 动态css语言less,less让css具有动态语言的特性
- HTML5 classList使用
- 网红手工耿造了辆电动汽车 罗永浩点赞 网友喊话雷军投资
- Redis 6.0 源码阅读笔记(10) -- 主从复制 Master 节点流程分析
- Php真太阳时计算公式,第七章:如何计算真太阳时?
- FastStone Capture注册破解码
- The Elements of Style 4ed ---英文写作指南(一)
- Axure RP 8--模板的使用
- linux把m4s格式转换mp4,批量将哔哩哔哩缓存M4S格式视频改成MP4格式
- MIT开创减少双量子比特门误差的新方法,提高鲁棒性迈向纠错量子计算机
- 怎么实现在FireFox IE Opera Safari 都可以正常播放WMV和MOV的网页播放器代码
- oracle对成绩开根号运算,Oracle SQL 之 数学计算-开方根(咋个办呢 zgbn)
- iphone与android共享位置,苹果手机,相互始终共享位置了以后,查看不了对方的位置...