PSoC4 Uart Bootloader


PSoC4 Bootloader and Bootloadable

参考文档:Infineon-AN68272 - PSoC_4…_UART_Bootloader-ApplicationNotes-v16_00-EN.pdf

参考这篇文档很容易就可以实现PSoC uart的bootloader和bootloadable,So…这不是今天的主角,今天的主角是简单的、能看的懂的自实现的uart bootloader,并且可以引导运行bootloadable APP。

一、先简单过一遍官方的Bootloader和Bootloadable:

  1. 实现: 实现过程很简单,只要分别在各自的工程中加入Bootloader和Bootloadable控件即可。
  2. 共享:Bootloader和Bootloadable共享变量:cyBtldrRunType
  3. 从Btl跳转至App … 这有点复杂,所有相关操作均在Bootloader.c中,2900+行,兼容各种PSoC 3、4、5,读起来晦涩难懂,这就是为什么要自己实现个BTL,稍后再记录它吧。
  4. 从App跳转至Bootloader的实现:调用 Bootloadable_Load() 即可。
void Bootloadable_Load(void) 
{
    /* Schedule Bootloader to start after reset */
    Bootloadable_SET_RUN_TYPE(Bootloadable_SCHEDULE_BTLDR);    //Set cyBtldrRunType

    CySoftwareReset();    //软复位
}

#define Bootloadable_SET_RUN_TYPE(x)        (cyBtldrRunType = (x))

#define Bootloadable_SCHEDULE_BTLDB             (0x80u)
#define Bootloadable_SCHEDULE_BTLDR             (0x40u)
#define Bootloadable_SCHEDULE_MASK              (0xC0u)

// Set cyBtldrRunType = Bootloadable_SCHEDULE_BTLDR;
  1. Bootloadable生成的文件格式说明:参考AN68272 Append B,

    • .elf : 包含各种调试信息的文件。

    • .hex :合并了bootloader、meta区的整个文件,可用于生产。

    • .cyacd:包含一个header line和诸多flash line,

    Header line: [4 Bytes Silicon ID] + [1Byte Silicon rev] + [1Byte checksum type]

    Flash line: [1 Byte Array ID] + [2 Bytes row number] + [2Bytes data length] + [N Bytes data] + [1 Byte checksum]

    checksum type: 0 - 和校验,1 - CRC-16

  2. Metadata: 位于flash最后一行的最后64字节,PSoC4的格式如下:

//metadata struct
#pragma pack(1)                    //按字节对齐
typedef struct
{
    uint8_t     appCheckSum;    //B0
    uint32_t    appAddress;     //B1~B4
    uint32_t    lastBtlRow;     //B5~B8
    uint32_t    appLength;      //B9~B0C
    uint8_t     NA1;            //B0D
    uint8_t     NA2;            //B0E
    uint8_t     NA3;            //B0F
    uint8_t     appActive;      //B10
    uint8_t     appVerified;    //B11
    uint8_t     btlVersion;     //B12
    uint16_t    appID;          //B13~B14
    uint16_t    appVersion;     //B15~B16
    uint16_t    appCustomID;    //B17~B18
}strMetadata;       //__attribute__((aligned(1))) 
#pragma pack ()     
  1. Bootloadable生成的.cyacd格式中,最后一行的flash data数据,就是如上的mata数据。其中:appLength、appCheckSum、appAddress等是bootloader用于校验app及跳转app的地址。
  2. PSoC工程有如下几种类型,通过CYDEV_PROJ_TYPE定义工程类型。
#define CYDEV_PROJ_TYPE_STANDARD 0
#define CYDEV_PROJ_TYPE_BOOTLOADER 1
#define CYDEV_PROJ_TYPE_LOADABLE 2
#define CYDEV_PROJ_TYPE_MULTIAPPBOOTLOADER 3
#define CYDEV_PROJ_TYPE_LOADABLEANDBOOTLOADER 4
#define CYDEV_PROJ_TYPE_LAUNCHER 5

#define CYDEV_PROJ_TYPE 2

二、手写一个 Uart Bootloader:

在之前的UART的工程上,增加协议、flash操作、跳转app前的校验及跳转函数即可。具体的请参考工程源码。下面是几点注意的地方:

  1. 由于是普通工程(未包含Bootloader组件),所以CYDEV_PROJ_TYPE被定义为 CYDEV_PROJ_TYPE_STANDARD = 0。这个影响了cyBtldrRunType:普通工程中未定义该变量。如果CYDEV_PROJ_TYPE不为0,则会在Cm0plusStart.c中定义该变量。

  2. App-Bootloadable的cm0plusgcc.ld连接文件中,将cyBtldrRunType链接至bootloaderruntype段:

    // Bootloadable - cm0plusgcc.ld
    __attribute__ ((section(".bootloaderruntype")))
        volatile uint32 cyBtldrRunType;
    
        .ramvectors (NOLOAD) : ALIGN(8)
        {
          __cy_region_start_ram = .;
          KEEP(*(.ramvectors))
        }
        .btldr_run (NOLOAD) : ALIGN(8)
        {
            KEEP(*(.bootloaderruntype))
        }
        .noinit (NOLOAD) : ALIGN(8)
        {
          KEEP(*(.noinit))
        }

    而普通工程中并没有 .btldr_run 段,ramvectors下接着就是noinit段。

    // CYDEV_PROJ_TYPE = CYDEV_PROJ_TYPE_STANDARD  - cm0plusgcc.ld   
        .ramvectors (NOLOAD) : ALIGN(8)
        {
          __cy_region_start_ram = .;
          KEEP(*(.ramvectors))
        }
        .noinit (NOLOAD) : ALIGN(8)
        {
          KEEP(*(.noinit))
        }

    尝试过在cm0plusgcc.ld中手动插入btldr_run段,clean & rebuild后又被清掉,此路不通。

    但是:可以定义一个变量cyBtldrRunTypeB放在noinit段中,查看并对比生成的map文件:

    // CYDEV_PROJ_TYPE = CYDEV_PROJ_TYPE_STANDARD  - cm0plusgcc.ld   
    CY_NOINIT volatile uint32_t cyBtldrRunTypeB; //CY_NOINIT 段是和Bootloadable段地址一样
    
    .noinit         0x200000b0        0x4
     *(.noinit)
     .noinit        0x200000b0        0x4 .\CortexM0p\ARM_GCC_541\Debug\btl.o
                    0x200000b0                cyBtldrRunTypeB
    
    //Bootloadable    
    .btldr_run      0x200000b0        0x4
     *(.bootloaderruntype)
     .bootloaderruntype
                    0x200000b0        0x4 .\CortexM0p\ARM_GCC_541\Debug\Cm0plusStart.o
                    0x200000b0                cyBtldrRunType    

    cyBtldrRunType 和 cyBtldrRunTypeB都位于0x200000b0地址。

    这样在APP中调用Bootloadable_Load() 函数,会设置cyBtldrRunType = Bootloadable_SCHEDULE_BTLDR,软复位后进入自定义的Bootloader,通过访问相同地址的cyBtldrRunTypeB并判断是否为Bootloadable_SCHEDULE_BTLDR即可。

  1. 跳转:跳转参考官方Bootloader中实现:

    /* Moves argument appAddr (RO) into PC, moving execution to appAddr */
    #if defined (__ARMCC_VERSION)
        __asm static void CustomBootloader_LaunchBootloadable(uint32 appAddr)
        {
            BX  R0
            ALIGN
        }
    #elif defined(__GNUC__)
        __attribute__((noinline)) /* Workaround for GCC toolchain bug with inlining */
        __attribute__((naked))
        static void CustomBootloader_LaunchBootloadable(uint32 appAddr)
        {
            __asm volatile("    BX  R0\n");
        }
    #elif defined (__ICCARM__)
        static void CustomBootloader_LaunchBootloadable(uint32 appAddr)
        {
            __asm volatile("    BX  R0\n");
        }
    #endif  /* (__ARMCC_VERSION) */
    
    CustomBootloader_LaunchBootloadable(meta->appAddress);     //校验通过 直接跳到APP区

    跳转地址需要注意:

    CustomBootloader_LaunchBootloadable(meta->appAddress); //校验通过 直接跳到APP区

    跳转的地址不是设置的APP起始地址,而是meta区中存储的appAddress,比如在Bootloadable组件中,选择Manual application image placement: 0x00004000 , App从Flash 16KB地址开始,但是存储在meta->appAddress中的值并不是0x00004000 ,而是偏移了0x11个字节 - 0x4011,所以跳转必须要使用meta中存储的该地址。

  2. 跳转时需要使用meta->appAddress的值,但是校验APP的checksum时,需要从Manual application image placement地址开始,比如0x4000,长度为meta->appLength

    uint8_t sum = 0;    
    uint8_t * p = (uint8_t *)STARTAPP_ADDR;    
    for(uint32_t i=0;i < meta->appLength; i++)
    {
        sum += p[i];
    }
    sum = ( uint8_t )1u + ( uint8_t )(~sum);
    
    if(sum != meta->appCheckSum)    return 6;

三、 PC APP

  1. 官方提供了Bootloader Host软件,位于D:\Cypress\PSoC Creator\4.4\PSoC Creator\bin目录下,测试使用官方的Bootloader和Bootloadable组件,可以使用该软件测试bootloader.
  2. 同时也提供了相关的参考代码,位于: D:\Cypress\PSoC Creator\4.4\PSoC Creator\cybootloaderutils目录下。参考cybtldr_parse.c实现cyacd格式的解析。
  3. UART协议未使用官方协议,改成我之前用过的简单协议,上位机在之前的串口程序中修改了一个,用于读取并解析.cyacd格式的app文件,并支持将app存储为纯BIN文件,方便使用其他工具升级。
  4. 注:PC APP暂不支持中文路径。

PSoC4 Uart BTL PC APP

可以看到如下信息:

Silicon ID:0x257C1175,校验和为普通SUM校验。

Flash Line信息:ROW Num64 ~ ROW Num72,为Flash Data。

ROW Num 511 : MetaData。

串口调试信息:

PSoC4 Uart BTL DebugInfor

  1. 首次烧录Boot时,运行Bootloader程序。
  2. 通过PC更新过APP后,通过Reboot命令让Bootloader复位重启,运行APP程序。
  3. 可以看出appAddress: 0x4011
  4. 手动按下按键,从App中再跳到bootloader中,此时由于cyBtldrRunTypeB = 0x40,又留在了bootloader中。

欢迎留言交流,稍后更新源码下载地址。


文章作者: xArm
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 xArm !
评论