首页 > 代码库 > 通过SPI方式实现LPC17xx的远程升级设计

通过SPI方式实现LPC17xx的远程升级设计

本方案基于NXP的LPC1768微处理器为平台,使用KEIL MDK4.70A为开发工具,通过SPI的方式实现程序的自动更新。本方案参考NXP官方的应用手册AN11257为蓝本。

 

程序设计:

程序由三部分组成bootloader、低区用户程序,高区用户程序。Bootloader实现程序的跳转及IAP程序的烧写。低区程序位于LPC1768的0x1000~0x2FFFF处,高区程序位于LPC1768的0x30000~0x67FFFF处。


 

待更新的程序放置于外部存储芯片N25Q256的0x00100000处,并占据48个扇区。LPC1768的bootloader通过SPI的方式读取N25Q256的数据并更新程序至高区用户程序,更新成功后,程序复位,运行更新后的程序。


 

一、Bootloader程序流程简介

Bootloader主要完成两个功能,跳转和IAP程序烧写。本程序占用FLASH的最低4K字节。

1.程序跳转。

在高区程序的最后四个字节(0x67FFC)存储着程序的版本信息,程序通过判断高区程序的版本信息实现跳转,如果版本信息为0xFFFFFFFF,则认为高区程序无效,程序执行低区用户程序,否则,执行高区程序。

#define SBL_SLV_FIRMWARE_ID_ADDR    (0x67FFC)
Bool upgrade = FALSE;
         uint32_t*versions;
         /*Get Version ID */
         versions= (uint32_t*)SBL_SLV_FIRMWARE_ID_ADDR;
         if(*versions== 0xFFFFFFFF)
                   upgrade= TRUE;
 
         if(!upgrade)
         {
                   //Run user code
                   SBL_SlaveRunUserCode();
         }
         else
                   SBL_SlaveRunOldUserCode();

 

程序流程图如下:

 

 

跳转至用户程序时,使用函数指针的形式直接跳转至用户程序的入口地址。

定义函数指针:

typedef void (*USER_ENTRY_PFN)();

定义程序入口地址:

#define SBL_SLV_FIRMWARE_START                 (0x38000)
user_entry = (USER_ENTRY_PFN) *((uint32_t*)(SBL_SLV_FIRMWARE_START + 4));

实现跳转:

(user_entry)();

 

2升级

升序程序使用分散加载机制,将升级程序的函数指针存入至程序的低16字节,即0x00000FF0~0x00000FFF处。用户程序接收到升级指令后,使用函数指针跳转到入口地址。

在分散加载sct文件中,指定存储函数指针入口地址的FLASH空间:

LR_SBL_CODE 0x00000FF0 0x00000010{ ;SBL-API
         ER_SBL0x00000FF0  0x00000010 { ;
     sbl_slave.o("sbl_call", +First)
         }
}

指定函数指针的入口地址

void SBL_APICall(uint32_t API, uint8_t*pData) __attribute__((section("sbl_call")));

这样用户程序通过调用SBL_APICall就可以实现跳转至bootloader中。

 

3 使用IAP更新程序

IAP的相关函数及操作流程都可以参考NXP的例程文件,不作修改。

 

二、用户程序

用户程序需要进行中断向量的重映射。

LPC1768通过VTOR写入偏移量来进行中断向量的重映射。

         #defineVTOR_OFFSET         (0x00038000)
         __disable_irq();
         SCB->VTOR  = VTOR_OFFSET;
         __enable_irq();

高区的程序版本号位于0x67FFC地址处,烧录代码的同时也会更新程序的版本号。通过分散加载的机制实现。