S32K144 bootloader 方案设计

最近在做一款车载产品的bootloader 设计,考虑可靠性,所以采用了Swap A/B方案

1、memmory 分配方案。
在这里插入图片描述
考虑安全性,同时充分利用MCU的片内资源,故将bootloader 放到了flexNVM,也就是另外一块的flash中。
(1 ) flexNVM 应是64KB,其中32KB 给bootloader,另外的当做EEPROM,用来存储一些需要长久保存的信息,比如车辆VIN,以及一些security KEY,OTA用到的秘钥,蓝牙车钥匙的 私钥等。
(2)考虑到对于固件信息做检验,所以拿出4KB ,用于存放固件信息,以及固件是否有效标志等。

2、固件A的链接文件配置
在这里插入图片描述
3、固件B的链接文件 配置
在这里插入图片描述
链接文件的配置,是对照memory分配表来的。

这里面很关键的就是中断向量表的位置。

4、分析下如何 这套机制如何工作的。
(1)startup.c 中的 一个初始化函数
startup.c 文件中的 section 定义

void init_data_bss(void)
{
    uint32_t n;
    uint8_t coreId;

    volatile uint32_t * vectors[NUMBER_OF_CORES] = FEATURE_INTERRUPT_INT_VECTORS;

/* ARM Compiler 4/5 or ARM Compiler 6 (armclang) */
#if !((defined (__CC_ARM )                                      ) ||  \
      (defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050))   )
    /* Declare pointers for various data sections. These pointers
     * are initialized using values pulled in from the linker file */
    uint8_t * data_ram;
    uint8_t * code_ram;
    uint8_t * bss_start;
    const uint8_t * data_rom, * data_rom_end;
    const uint8_t * code_rom, * code_rom_end;
    const uint8_t * bss_end;
#endif

    /* Addresses for VECTOR_TABLE and VECTOR_RAM come from the linker file */
    extern uint32_t __RAM_VECTOR_TABLE_SIZE[];
    extern uint32_t __VECTOR_TABLE[];
    extern uint32_t __VECTOR_RAM[];

    /* Get section information from linker files */
#if defined(__ICCARM__)
    /* Data */
    data_ram        = __section_begin(".data");
    data_rom        = __section_begin(".data_init");
    data_rom_end    = __section_end(".data_init");

    /* CODE RAM */
    #pragma section = "__CODE_ROM"
    #pragma section = "__CODE_RAM"
    code_ram        = __section_begin("__CODE_RAM");
    code_rom        = __section_begin("__CODE_ROM");
    code_rom_end    = __section_end("__CODE_ROM");

    /* BSS */
    bss_start       = __section_begin(".bss");
    bss_end         = __section_end(".bss");

/* ARM Compiler 4/5 or ARM Compiler 6 (armclang) */
#elif ((defined (__CC_ARM )                                      ) ||  \
       (defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050))   )
    extern uint32_t Image$$VECTOR_ROM$$Base[];
    extern uint32_t Image$$VECTOR_RAM$$Base[];
    extern uint32_t Image$$RW_m_data$$Base[];

    // #define __VECTOR_TABLE Image$$VECTOR_ROM$$Base
    #define __VECTOR_RAM Image$$VECTOR_RAM$$Base
    #define __RAM_VECTOR_TABLE_SIZE (((uint32_t)Image$$RW_m_data$$Base - (uint32_t)Image$$VECTOR_RAM$$Base))

#else
    extern uint32_t __DATA_ROM[];
    extern uint32_t __DATA_RAM[];
    extern uint32_t __DATA_END[];

    extern uint32_t __CODE_RAM[];
    extern uint32_t __CODE_ROM[];
    extern uint32_t __CODE_END[];

    extern uint32_t __BSS_START[];
    extern uint32_t __BSS_END[];
    data_ram        = (uint8_t *)__DATA_RAM;
    data_rom        = (uint8_t *)__DATA_ROM;
    data_rom_end    = (uint8_t *)__DATA_END;
    /* CODE RAM */
    code_ram        = (uint8_t *)__CODE_RAM;
    code_rom        = (uint8_t *)__CODE_ROM;
    code_rom_end    = (uint8_t *)__CODE_END;
    /* BSS */
    bss_start       = (uint8_t *)__BSS_START;
    bss_end         = (uint8_t *)__BSS_END;
#endif

    coreId = (uint8_t)GET_CORE_ID();

    /* Check if VECTOR_TABLE copy is needed */
    if (__VECTOR_RAM != __VECTOR_TABLE)
    {
        /* Copy the vector table from ROM to RAM */
        for (n = 0; n < (((uint32_t)__RAM_VECTOR_TABLE_SIZE)/sizeof(uint32_t)); n++)
        {
            __VECTOR_RAM[n] = __VECTOR_TABLE[n];
        }
        /* Point the VTOR to the position of vector table */
        *vectors[coreId] = (uint32_t)__VECTOR_RAM;
    }
    else
    {
        /* Point the VTOR to the position of vector table */
        *vectors[coreId] = (uint32_t)__VECTOR_TABLE;
    }

/* ARM Compiler 4/5 or ARM Compiler 6 (armclang) */
#if !((defined (__CC_ARM )                                      ) ||  \
      (defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050))   )
    /* Copy initialized data from ROM to RAM */
    while (data_rom_end != data_rom)
    {
        *data_ram = *data_rom;
        data_ram++;
        data_rom++;
    }

    /* Copy functions from ROM to RAM */
    while (code_rom_end != code_rom)
    {
        *code_ram = *code_rom;
        code_ram++;
        code_rom++;
    }

    /* Clear the zero-initialized data section */
    while(bss_end != bss_start)
    {
        *bss_start = 0;
        bss_start++;
    }
#endif
}

编译工程,查看map信息,看看生产的文件和配置的是否一致。

![](https://img-blog.csdnimg.cn/20200711235346408.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzEzOTc5NA==,size_16,color_FFFFFF,t_70)
5、跳转验证,

(1) 从bootloader --》固件A [测试OK]
(2) 从bootloader -》固件B [目前测试失败,固件B的APP不能启动]
(3)从固件A---->boot ,明天测试
(4)从固件B—》boot 明天测试
(5) 从固件A—固件B 测试。当然这个貌似没有这个场景的需求。

bootloader 方案的健壮可靠和合理,对于车载的OTA 来说,十分重要。
可以通过远程留解决很多软件bug。
防止变砖 是最基本,也是最核心的最求。

马上12点了,赶紧睡,写的很匆忙,条理性也不好,过几天有时间再完善吧!
2020-7-11
23:58
//========================================================//
**

2020年7月12更新

**

今天是周末,昨晚的跳转问题没有找到原因,今天心里堵的慌,下午刚好有时间,就赶紧坐下来 研究这个问题,终于在天黑的时候,搞定了。
目前:
在这里插入图片描述

要点如下:
1、从boot调准至APP的入口地址,必须是中断向量:m_interrupt_start 的地址,而不是固件存放的地址。

比如APP-A的配置如下:
在这里插入图片描述
因为是采用的IDE刷写,所以在下载程序到MCU时,这个地方的配置也很重要。(需要多验证,貌似这个地方也不影响,应为在hex文件中,都定义了数据对应到flash中的位置)
在这里插入图片描述
boot 工程中,main的代码如下:

 while(1)
{
	   //  LPUART0_send_char('>');
		 PTD->PTOR |= (1<<13);
		  sys_delay(500);
		  cnt++;
      	  Uart_Printf("waiting for jump...%d\r\n",cnt);
	
		  if(cnt == 20)
		  { 
			  Uart_Printf("P_flash progamme test!\r\n");
			//  P_Flash_test();
			  Uart_Printf("I will be jump to the app-A=%d\r\n",cnt);
			  sys_delay(1000);
			  INT_SYS_DisableIRQGlobal();
			  boot_jump_to_app(APP_BLOCK_B);
		  }		
  }
}

跳转 的函数如下,其实就直接跳转至地址;

void boot_jump_to_app( uint8_t app_block )
{

	 if(app_block  ==  APP_BLOCK_A)
	 { 
		   (*(void (*)(void))(APP_StartAddr_A))();/*run the function via function pointer convert 				    with a certain address*/		
	       while(1);
	 }
	 else if(app_block  ==  APP_BLOCK_B)
	 {
		
			(*(void (*)(void))(APP_StartAddr_B))();/*run the function via function pointer convert with a certain address*/		
	         while(1);		 
	 }
   
}

其中 APP_StartAddr_B,这里要注意,要在其实地址后加+4,也就是一个PC寄存器的长度。
MCU上电后,要从PC寄存器抓起 数据,然后才是进入应用。
在这里插入图片描述
接下来的工作:

就是要搞定从APP应用程序向bootloader跳转,这也是我们的OTA 的流程,
所以这个必须要解决。

明天继续更新吧。

  • 8
    点赞
  • 78
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
s32k144是一款微控制器,bootloader是在该微控制器上运行的一段特殊程序,用于加载和启动应用程序。s32k144bootloader跳转指的是当bootloader执行完其任务后,将控制权交给应用程序的过程。 s32k144bootloader跳转的实现方法有多种,具体取决于设计者的要求和需求。以下是其中一种常见的实现方法: 1. 在bootloader中,定义一个函数,该函数的功能是跳转到应用程序的入口点。这个入口点地址需要在编译应用程序时预先确定并保存在某个特定位置,供bootloader跳转使用。 2. 应用程序在编译时,将入口点地址写入一个特定的内存位置,例如特殊的区域或一个预留的变量中。 3. 在bootloader中,通过读取这个特定的内存位置,获取应用程序的入口点地址。 4. 当bootloader的任务完成时,即完成了一些必要的操作,例如固件更新或配置加载等,bootloader将调用这个特定的函数,跳转到应用程序的入口点。 5. 跳转到应用程序后,控制权交给应用程序,应用程序将开始执行。 这种方法的好处是灵活性和可靠性。通过将入口点地址保存在特定的内存位置,bootloader可以在不同的应用程序之间跳转,从而实现多个应用程序共存的功能。另外,此方法也确保了bootloader和应用程序之间的隔离,增强了系统的安全性和可靠性。 总之,s32k144bootloader跳转是将控制权从bootloader转移到应用程序的过程,它可以通过在编译应用程序时预先确定和保存入口点地址的方法来实现。这种方法在实现多个应用程序共存并增加系统的安全性和可靠性方面具有优势。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值