Tricore学习-芯片启动流程

2023-05-16

第一次接触Tricore, 学习下从芯片上电到运行到main函数的过程,本文以TC36X为例,具体可参考英飞凌官方的Infineon-AURIX_TC3xx_Part1-UserManual-v02_00-EN
首先Tricore类似三星的MPU,有一段自带的BROM,这段FLASH中存储了一段固化的启动代码,称为Startup Sofrware(SSW), 这个意味着这段代码是英飞凌出厂就烧进去的,且无法覆盖。
在这里插入图片描述
然后SSW什么时候执行呢?当然是RESET的时候,英飞凌把RESET分为三种:

  • Cold (initial) power-on reset 上电复位,一切都处于初始状态
  • System reset 触发源为内部看门狗,软件主动请求,PORST输入脉冲复位等,复位后一切都处于初始状态
  • Application reset 触发源和System reset相同,只是可以通过复位前软件配置,使得复位后时钟,RAM不会跟着复位
    复位后如果一切正常就会自动执行SSW
    先放张图
    在这里插入图片描述
    SSW会去读取DFLASH UCB区的BMHD(Boot Mode Header)内容。
    在这里插入图片描述
    一共四个配置项,从BMHD0开始检测是否有效,如果BMHD0有效则使用它,否则依次检测出第一个有效的BMHD,如果都无效则需要进入BootStrap Loader刷程序,芯片无法正常启动,跳转到用户写的代码去执行
    在这里插入图片描述
    这就是一个UCB-BMHD内容,需要用户自己填写(不确定出厂是否会有默认的内容),编译链接到.section .bmhd_0_orig 并下载到DFLASH.UCB.BMHD对应的地址上去,这样下次芯片上电执行SSW才能读到正确的内容。
    找了一个例程,大家看下配置
#if defined(__HIGHTEC__)
#pragma section
#pragma section ".bmhd_0_orig" a
#endif
#if defined(__TASKING__)
#pragma section farrom "bmhd_0_orig"
#endif
#if defined(__DCC__)
#pragma section CONST ".bmhd_0_orig" far-absolute R
#endif
#if defined(__ghs__)
#pragma ghs section rodata= ".bmhd_0_orig"
#endif
const Ifx_Ssw_Bmhd bmhd_0_orig =
{
    0x003E,         /* 0x000: .bmi: Boot Mode Index (BMI)     PINDIS                                         */
    0xB359,         /* 0x002: .bmhdid: Boot Mode Header ID (CODE) = B359H                               */
    0xA0000000,     /* 0x004: .stad: User Code start address                                            */
    0xD86CBDAB,     /* 0x008: .crc: Check Result for the BMI Header (offset 000H - 007H)                */
    0x27934254,     /* 0x00C: .crcInv: Inverted Check Result for the BMI Header (offset 000H - 007H)    */
    {
        0x00000000, 0x00000000, 0x00000000, 0x00000000,        /* 0x010: Reserved (0x010 - 0x01F)       */
        0x00000000, 0x00000000, 0x00000000, 0x00000000,        /* 0x020: Reserved (0x020 - 0x02F)       */
        0x00000000, 0x00000000, 0x00000000, 0x00000000,        /* 0x030: Reserved (0x030 - 0x03F)       */
        0x00000000, 0x00000000, 0x00000000, 0x00000000,        /* 0x040: Reserved (0x040 - 0x04F)       */
        0x00000000, 0x00000000, 0x00000000, 0x00000000,        /* 0x050: Reserved (0x050 - 0x05F)       */
        0x00000000, 0x00000000, 0x00000000, 0x00000000,        /* 0x060: Reserved (0x060 - 0x06F)       */
        0x00000000, 0x00000000, 0x00000000, 0x00000000,        /* 0x070: Reserved (0x070 - 0x07F)       */
        0x00000000, 0x00000000, 0x00000000, 0x00000000,        /* 0x080: Reserved (0x080 - 0x08F)       */
        0x00000000, 0x00000000, 0x00000000, 0x00000000,        /* 0x090: Reserved (0x090 - 0x09F)       */
        0x00000000, 0x00000000, 0x00000000, 0x00000000,        /* 0x0A0: Reserved (0x0A0 - 0x0AF)       */
        0x00000000, 0x00000000, 0x00000000, 0x00000000,        /* 0x0B0: Reserved (0x0B0 - 0x0BF)       */
        0x00000000, 0x00000000, 0x00000000, 0x00000000,        /* 0x0C0: Reserved (0x0C0 - 0x0CF)       */
        0x00000000, 0x00000000, 0x00000000, 0x00000000,        /* 0x0D0: Reserved (0x0D0 - 0x0DF)       */
        0x00000000, 0x00000000, 0x00000000, 0x00000000,        /* 0x0E0: Reserved (0x0E0 - 0x0EF)       */
        0x00000000, 0x00000000, 0x00000000, 0x00000000         /* 0x0F0: Reserved (0x0F0 - 0x0FF)       */
    },
    {
        0x00000000, /* 0x100: .pw0: Password protection word 0 (lsw)                                    */
        0x00000000, /* 0x104: .pw1: Password protection word 1                                          */
        0x00000000, /* 0x108: .pw2: Password protection word 2                                          */
        0x00000000, /* 0x10C: .pw3: Password protection word 3                                          */
        0x00000000, /* 0x110: .pw4: Password protection word 4                                          */
        0x00000000, /* 0x114: .pw5: Password protection word 5                                          */
        0x00000000, /* 0x118: .pw6: Password protection word 6                                          */
        0x00000000, /* 0x11C: .pw7: Password protection word 7 (msw)                                    */
    },
    {
        0x00000000, 0x00000000, 0x00000000, 0x00000000,        /* 0x120: Reserved (0x120 - 0x12F)       */
        0x00000000, 0x00000000, 0x00000000, 0x00000000,        /* 0x130: Reserved (0x130 - 0x13F)       */
        0x00000000, 0x00000000, 0x00000000, 0x00000000,        /* 0x140: Reserved (0x140 - 0x14F)       */
        0x00000000, 0x00000000, 0x00000000, 0x00000000,        /* 0x150: Reserved (0x150 - 0x15F)       */
        0x00000000, 0x00000000, 0x00000000, 0x00000000,        /* 0x160: Reserved (0x160 - 0x16F)       */
        0x00000000, 0x00000000, 0x00000000, 0x00000000,        /* 0x170: Reserved (0x170 - 0x17F)       */
        0x00000000, 0x00000000, 0x00000000, 0x00000000,        /* 0x180: Reserved (0x180 - 0x18F)       */
        0x00000000, 0x00000000, 0x00000000, 0x00000000,        /* 0x190: Reserved (0x190 - 0x19F)       */
        0x00000000, 0x00000000, 0x00000000, 0x00000000,        /* 0x1A0: Reserved (0x1A0 - 0x1AF)       */
        0x00000000, 0x00000000, 0x00000000, 0x00000000,        /* 0x1B0: Reserved (0x1B0 - 0x1BF)       */
        0x00000000, 0x00000000, 0x00000000, 0x00000000,        /* 0x1C0: Reserved (0x1C0 - 0x1CF)       */
        0x00000000, 0x00000000, 0x00000000, 0x00000000,        /* 0x1D0: Reserved (0x1D0 - 0x1DF)       */
        0x00000000, 0x00000000, 0x00000000, 0x00000000         /* 0x1E0: Reserved (0x1E0 - 0x1EF)       */
    },
    0x43211234      /* 0x1F0: .confirmation: 32-bit CODE, (always same)                                 */
};

这里的BMI =0x3E =0b111110 ,大家可以具体看看这种配置是社么意思
在这里插入图片描述
比如PINDIS=0且 HWCFGbits [3:1] = 0b111 代表上电无需检测外部Pin14.2等引脚电平,直接start from Flash,那么从Flash哪个地址开始执行呢?
BMHD.STAD: User Code start address 是可以配置的
这里配置为了0xA0000000
在这里插入图片描述
这是NON-CACHE CPU0的Program Flash起始地址

#if defined(__HIGHTEC__)
#pragma section
#pragma section ".start" x
#endif
void _START(void)
{
    Ifx_Ssw_jumpToFunction(__StartUpSoftware);
}
#if defined(__HIGHTEC__)
#pragma section
#endif
通过宏将void _START(void)代码放到了section .start
链接脚本
#define LCF_STARTPTR_NC_CPU0 0xA0000000
 group (ordered)
        {
            group  reset (run_addr=RESET)
            {
                section "reset" ( size = 0x20, fill = 0x0800, attributes = r )
                {
                    select ".text.start";
                }
            }
            group  interface_const (run_addr=mem:pfls0[0x0020])
            {
                select "*.interface_const";
            }
            "__IF_CONST" := addressof(group:interface_const);
            "__START0" := LCF_STARTPTR_NC_CPU0;
            "__START1" := LCF_STARTPTR_NC_CPU1;
        }
 

总之就是将_START放到了CPU0的PFLASH0的起始地址,也就是BMHD中指定的STAD,而CPU1的_START1同样也放到了PFLASH1的起始地址,顺便提一下,上电的时候CPU0是默认开启的,且SSW也是由这个核执行的,其他所有CPU都处于HALT状态。
到这里SSW就结束了,后面就是执行用户写的代码,第一个指令就是_START(相当于CPU0的启动代码)位于Ifx_Ssw_Tc0.c

void _START(void)
{
    Ifx_Ssw_jumpToFunction(__StartUpSoftware);
}/*汇编直接跳转到__StartUpSoftware*/
static void __StartUpSoftware(void)
{
    /* Initialize A1 pointer to use the global constants with small data addressing */
    Ifx_Ssw_setAddressReg(a1, __SDATA2(0));

    /* Set the PSW to its reset value in case of a warm start,clear PSW.IS */
    Ifx_Ssw_MTCR(CPU_PSW, IFX_CFG_SSW_PSW_DEFAULT);

    /* This phase is executed only if last reset is not of type application reset */
    if (Ifx_Ssw_isApplicationReset() != 1)
    {
        Ifx_Ssw_jumpToFunction(__StartUpSoftware_Phase2);
    }
    else
    {
        Ifx_Ssw_jumpToFunction(__StartUpSoftware_Phase3ApplicationResetPath);
    }
}
/*System Reset*/
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();                                                         \
    }/*初始化CPU0 的RAM, 其他核也有自己的专用RAM,参考手册MemoryMap 
    包括CSA 将utack 栈顶赋值给寄存器A10(相当于ARM 的LDR SP ,= StackTopAddr) CPU的RAM
    怎么分配的可以参考链接脚本*/
 按道理说只有初始化的Stack才能执行C语言写的函数,
 那么在这之前的那些步骤难道不算C语言函数?
 static void __StartUpSoftware_Phase5(void)
{
    /* SMU alarm handling */
    IFX_CFG_SSW_CALLOUT_SMU();

    Ifx_Ssw_jumpToFunction(__StartUpSoftware_Phase6);
}/*其实是直接跳转到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));           /*The status returned by function call is ignored */
#endif /* #if (IFX_CFG_CPU_CSTART_ENABLE_TRICORE1 != 0)*/

    Ifx_Ssw_jumpToFunction(__Core0_start);
}/*可以看到CPU1其实是由CPU0启动的,当然你要配置使用CPU1*/
Ifx_Ssw_startCore(&MODULE_CPU1, (unsigned int)__START(1));  
void Ifx_Ssw_startCore(Ifx_CPU *cpu, unsigned int programCounter)
{
    /* Set the 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;
    }

}
可以看到是直接将cpu1->PC寄存器指向_START1()函数,
并且通过设置某个特殊寄存器,解除CPU1的HALT状态,使其进入RUN,
那么CPU1就可以执行_START1()了
CPU0开启CPU1后,继续自己的初始化
Ifx_Ssw_jumpToFunction(__Core0_start);
static void __Core0_start(void)
{
  	... 很多代码大家可以自己去看, 这里就不分析了,
  	值得注意的是初始化看门狗, 初始化RAM,
  	建立异常和中断Vector,
  	中断栈, 使能或不使能Cache等等
    /*Call main function of Cpu0 */
    Ifx_Ssw_jumpToFunction(core0_main);
}

最重要的是Ifx_Ssw_jumpToFunction(core0_main) 这样芯片从上电CPU0 RUN CPUX HALT ->读取UFLASH-UCB-BMHD->_START0->core_start(cpu1)->go to MAIN函数就完成了, 同样的CPU1执行_START1() 后也会继续执行自己的core1_main
现在多核CPU就可以各自执行自己的MAIN函数(它们在不同的flash地址), 各玩各的,但这样是显然不行的,涉及到共享资源访问,核间通信等问题以后再研究。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Tricore学习-芯片启动流程 的相关文章

随机推荐

  • freeRTOS系统静态与动态建立任务

    一 xff0c 静态建立任务 1 xff0c 定义任务函数 xff08 一个无限循环且不带返回值的函数 xff09 任务必须是死循环 xff0c 否则任务将经过 LR 返回 xff0c 如果 LR 指向了非法内存就会产生HardFault
  • Ubuntu18.04安装Ceres1.14

    Ubuntu18 04安装Ceres1 14 1 下载Ceres2 安装依赖项3 编译4 安装 1 下载Ceres 链接Github下载地址 2 安装依赖项 sudo apt get install liblapack dev libsui
  • SSH登录出现REMOTE HOST IDENTIFICATION HAS CHANGED故障的解决办法

    今天登录一台交换机 xff0c 出现如图错误 xff1a 原因 该IP分配给过另一台交换机 xff0c 在knows hosts文件中保留了当时的rsa信息 xff0c 将这个IP有分配给新设备 xff0c SSH登录时会提示RSA key
  • 外贸函电常用词汇

    外贸函电常用词汇 xff1a xff08 1 xff09 贵函 Your letter Your favour your esteemed letter Your esteemed favour Your valued letter You
  • 匿名拓空者Pro开源飞控使用介绍-1-飞控特点

    匿名团队 是一个爱好技术 xff0c 爱好创新的团队 做自己 xff0c 发现兴趣 xff0c 追随兴趣 xff0c 分享兴趣 非常欢迎大家关注我们匿名 xff0c 交流群 xff1a 190169595 匿名拓空者Pro 飞控 xff0c
  • 匿名拓空者Pro开源飞控使用介绍-2-硬件配置及拓展接口

    硬件配置 主控 STM32F407 xff1a 1M FLASH xff0c 192K RAM xff0c 运行频率168MHz xff1b 惯性传感器 icm20602 xff1a 3轴陀螺 43 3轴加速度 43 恒温设计 xff08
  • 匿名拓空者Pro开源飞控使用介绍-3-连接上位机及基本测试

    飞控连接上位机方法 飞控可以通过底板上的USB端口连接上位机 xff0c 使用USB线连接飞控和电脑 xff0c 飞控买家版程序会将USB端口初始化成HID设备 xff0c 免安装驱动程序 xff0c 只要打开匿名上位机 xff0c 打开程
  • 匿名拓空者Pro开源飞控使用介绍-4-飞控安装及坐标系定义

    飞控安装 将机架组装好 xff0c 电机安装于机架上 xff0c 飞控安装于机架重心位置 xff08 一般为机架中心板中心位置 xff0c 也就是两条电机对角线交点 注意 xff0c 飞控尽量水平安装于机架上 xff0c 飞行效果最好 xf
  • 匿名拓空者Pro开源飞控使用介绍-5-接收机连接

    确定使用何种接收机连接方式 匿名拓空者PRO飞控支持SBUS PPM PWM型接收机 xff0c 根据推荐程度依次为SBUS gt PPM gt PWM SBUS PPM均可以实现1根信号线传输多通道遥控数据的功能 xff0c SBUS为串
  • 匿名科创--匿名拓空者PRO—TI版全开源飞控使用入门—TM4C123

    1 飞控介绍 匿名团队针对TI芯片的强烈学习需求 xff0c 推出了匿名拓空者PRO飞控的TI版 使用TI公司的 TM4C123G 主控芯片 xff0c 打造了一款完全开源的飞控产品 xff0c 提供完全开源的飞控整体工程文件 xff0c
  • 匿名科创--ANO_OPENMV视觉开发板介绍

    1 ANO OPENMV介绍 官方OPENMV体积大 xff1f 在飞行器上不方便安装 xff1f 串口通过杜邦线容易接触不良 xff1f 不可否认 xff0c OPENMV为大家提供了一个非常方便 易用的视觉开发环境 xff0c 但是在实
  • 匿名科创--匿名拓空者PRO--开源光流融合算法使用教程

    1 总体介绍 为了更好的支持匿名TI飞控买家 xff0c 匿名团队开源了基于优象光流模块的飞控算法 xff0c 光流传感器直接连接至匿名拓空者PRO TI版飞控 xff0c 由飞控读取原始光流传感器的光流数据 xff0c 结合高度传感器以及
  • Linux 设备驱动开发实例

    编译和运行 驱动编译要用到kernel的Makefile文件 也就是源码树的编译系统 因此 xff0c 源码需要被配置和编译 xff0c 以ubuntu自带的源码为例 xff1a 编译外部模块 ko 的编译命令是 xff1a make C
  • 匿名科创-匿名光流V3版对天安装介绍

    安装介绍 光流模块对天安装时 xff0c 方向参考上图 注意 xff0c 只有光流模块对上安装 xff0c 激光或超声波测距模块仍然对地安装 配置介绍 如需使用对天模式 xff0c 硬件安装好后 xff0c USB线连接光流模块至上位机 x
  • 从 C51+uCos-II 近距离了解操作系统任务切换原理

    前言 从 C51 43 uCos II 简单介绍下任务切换的原理 方便大家更形象的理解多任务怎么切换 为后续写 x86 43 Linux 任务切换做铺垫练手吧 参考资料如下 xff1a uCos II 源码 单片机原理与应用及 C51 编程
  • Keil+Simulink生成Xcp标定协议A2L文件

    Keil 43 Simulink生成Xcp标定协议A2L文件 由于最近要为ECU移植XCP协议 xff0c 所以记录一下 xff0c 我使用的MCU为NXP S32K144 IDE选用MDK 官方IDE S32DS无代码联想功能 xff0c
  • 记录一下关于MPC5744P CAN总线学习

    记录一下关于MPC5744P CAN总线学习 主要是针对开发出BUSOFF管理 xff0c NXP感觉都是一个套路 xff0c 无论powerpc xff0c 还是arm m status t span class token functi
  • 通过.map文件填写XCP标定需要的A2L文件

    首先你得有一个模板 xff0c 通过python脚本打开编译后的 map文件自动填写到A2L文件对应位置 xff0c 目前只实现了填写Mesurement 区域 xff0c 但是这个填写主要是更新变量名和对应的ECU ADRRESS 因为
  • Autosar Xcp移植

    前言 xff1a 可能有兄弟胸中有点疑问 Vector ETAS等软件包都有XCP xff0c 你移植个吊 xff0c 但是我的MICORSAR BSW中没发现XCP静态代码 xff0c 倒是在CFG中发现了XCP配置选项 xff0c 难道
  • Tricore学习-芯片启动流程

    第一次接触Tricore 学习下从芯片上电到运行到main函数的过程 xff0c 本文以TC36X为例 xff0c 具体可参考英飞凌官方的Infineon AURIX TC3xx Part1 UserManual v02 00 EN 首先T