原创 现场升级方案:采用U盘方式进行IAP功能的实现(一)

2015-2-22 21:22 3158 19 19 分类: MCU/ 嵌入式

闲来无事,总结一下前段时间做过的U盘升级项目。一个新手的成长之路在于善于总结,生活也是一样扯远了,我准备了两个软件环境,一个带操作系统(UCOS)的,另一个裸机版的。随后我会附上两个程序代码。U盘升级可以分为两部分代码:U盘读取bin文件和IAP功能两部分。大概说一下实现过程,具体IAP网上都玩坏了。硬件环境:NXP 1788

软件环境:KEIL实现过程:上面说了我准备了两个程序,就用裸机版的代码说一下实现流程。带操作系统的原理都是一样的。只是多创建几个任务而已。USB_HOST实现IAP升级,总的思路就是:复制bin文件到U盘->目标板断电,插上U盘->目标板上电,进入升级->运行升级程序。其实可以更具体,比如说设置升级标志或者按键。拿到一个程序先从main开始,直接贴代码,说一大堆废话有什么用。

 int main()
{
  int32_t  rc;
 uint32_t  numBlks, blkSize;
 uint8_t  inquiryResult[INQUIRY_LENGTH];

 SystemInit();                /*目标板初始化                  */

    UART_Init(57600);          /* 串口调试初始化          */
    Host_Init();                     /* USB初始化*/
    rc = Host_EnumDev();       /* USB设备枚举          */
    if (rc == OK) {
  /* Initialize the mass storage and scsi interfaces */
        rc = MS_Init( &blkSize, &numBlks, inquiryResult );
        if (rc == OK) {
            rc = FAT_Init();   /*文件系统初始化*/
            if (rc == OK) {
                Bin_Read();    /*读取bin文件调用IAP     */
            } else {
                return (0);
            }
        } else {
            return (0);
        }
    } else {       
        return (0);
    }
    while(1);
}

下面分模块说一下, 前面的硬件初始化函数很简单,USB设备枚举和FAT文件系统NXP官网上都有,只需改硬件接口,Host_Init函数如下:

void  Host_Init (void)
{
 uint32_t HostBaseAddr;

    LPC_SC->PCONP   |= 0x80000000;
    LPC_USB->OTGClkCtrl   = 0x00000019;  /* Enable USB host clock                      */
    while ((LPC_USB->OTGClkSt & 0x00000019) != 0x19);
 
 LPC_USB->StCtrl = 0x1; /* 01: U1 = host (OTG), U2 = host */

   LPC_IOCON->P0_29 &= ~(0x07UL << 0);
    LPC_IOCON->P0_30 &= ~(0x07UL << 0);
    LPC_IOCON->P1_28 &= ~(0x07UL << 0);
    LPC_IOCON->P1_29 &= ~(0x07UL << 0);

    LPC_IOCON->P0_29 |= 0x01UL << 0;                                    /*  P0.29 -- USB1 D+            */
    LPC_IOCON->P0_30 |= 0x01UL << 0;                                    /*  P0.30 -- USB1 D-            */
    LPC_IOCON->P1_28 |= 0x01UL << 0;                                    /*  P1.28 -- USB_SCL1           */
    LPC_IOCON->P1_29 |= 0x01UL << 0;                                    //  P1.29 -- USB_SDA1     
   PRINT_Log("Initializing Host Stack\n");

 /* Set up host base address and TD and ED descriptors */
 HostBaseAddr = HOST_BASE_ADDR;

    Hcca       = (volatile  HCCA       *)(HostBaseAddr+0x000);
    TDHead     = (volatile  HCTD       *)(HostBaseAddr+0x100);
    TDTail     = (volatile  HCTD       *)(HostBaseAddr+0x110);
    EDCtrl     = (volatile  HCED       *)(HostBaseAddr+0x120);
    EDBulkIn   = (volatile  HCED       *)(HostBaseAddr+0x130);
    EDBulkOut  = (volatile  HCED       *)(HostBaseAddr+0x140);
    TDBuffer   = (volatile  uint8_t *)(HostBaseAddr+0x150);
    FATBuffer  = (volatile  uint8_t *)(HostBaseAddr+0x1D0);
    UserBuffer = (volatile  uint8_t *)(HostBaseAddr+0x1000);

    /* Initialize all the TDs, EDs and HCCA to 0  */
    Host_EDInit(EDCtrl);
    Host_EDInit(EDBulkIn);
    Host_EDInit(EDBulkOut);
    Host_TDInit(TDHead);
    Host_TDInit(TDTail);
    Host_HCCAInit(Hcca);

    Host_DelayMS(50);                /* Wait 50 ms before apply reset              */
    LPC_USB->Control       = 0;    /* HARDWARE RESET                             */
    LPC_USB->ControlHeadED = 0;    /* Initialize Control list head to Zero       */
    LPC_USB->BulkHeadED    = 0;    /* Initialize Bulk list head to Zero          */
   
    /* SOFTWARE RESET                             */
    LPC_USB->CommandStatus = OR_CMD_STATUS_HCR;
    LPC_USB->FmInterval    = DEFAULT_FMINTERVAL;  /* Write Fm Interval and Largest Data Packet Counter */

                                                    /* Put HC in operational state                */
    LPC_USB->Control  = (LPC_USB->Control & (~OR_CONTROL_HCFS)) | OR_CONTROL_HC_OPER;
    LPC_USB->RhStatus = OR_RH_STATUS_LPSC;        /* Set Global Power                           */
   
    LPC_USB->HCCA = (uint32_t)Hcca;
    LPC_USB->InterruptStatus |= LPC_USB->InterruptStatus;                   /* Clear Interrrupt Status                    */

    LPC_USB->InterruptEnable  = OR_INTR_ENABLE_MIE |
                         OR_INTR_ENABLE_WDH |
                         OR_INTR_ENABLE_RHSC |
                         OR_INTR_ENABLE_UE;

  /* Enable the USB Interrupt */
 NVIC_EnableIRQ(USB_IRQn);               /* enable USB interrupt */
 NVIC_SetPriority (USB_IRQn, 0);   /* highest priority */

    PRINT_Log("Host Initialized\n");
}

 这段主要是USB引脚配置和USB主机初始化。Bin_Read()函数如下:

void  Bin_Read (void)
{
      int32_t  fdr;
      uint32_t  bytes_read,writelen;
     uint32_t dstaddr;
      SelSector(APP_START_SECTOR,APP_END_SECTOR);        //选择扇区
      EraseSector(APP_START_SECTOR,APP_END_SECTOR);                          /* 擦除扇区                     */
      BlankCHK(APP_START_SECTOR,APP_END_SECTOR);                             /* 查空扇区                    */
      SelSector(APP_START_SECTOR,APP_END_SECTOR);     
      PRINT_Log("\r\nstart file operations...\r\n");

    fdr = FILE_Open(FILENAME_R, RDONLY);
    if (fdr > 0) {
        PRINT_Log("Reading from %s...\n", FILENAME_R);
  for(writelen=0;writelen<(APP_END_ADDR-APP_START_ADDR)/1024;writelen++)
   {
    bytes_read = FILE_Read(fdr, UserBuffer, MAX_BUFFER_SIZE);            /* 读出文件                */
    dstaddr =  (uint32_t)(APP_START_ADDR + (writelen)*1024);//dst address.  
    SelSector(APP_START_SECTOR,APP_END_SECTOR);     
    RamToFlash(dstaddr,(uint32_t)UserBuffer, 1024);
    Compare(dstaddr, (uint32_t)UserBuffer, 1024);
    }  
  // printf("%x",writelen);
  PRINT_Log("\r\n write file successful\r\n");
    SCB->VTOR  = APP_START_ADDR;                                    /* 重新映射向量表          */
    ExceuteApplication();                                                     /*执行用户程序*/ 
  FILE_Close(fdr);                                                                /*关闭文件系统*/
    } else {
        PRINT_Log("\r\n write file failed\r\n");
    }
}void  Bin_Read (void)
{
      int32_t  fdr;
      uint32_t  bytes_read,writelen;
     uint32_t dstaddr;
      SelSector(APP_START_SECTOR,APP_END_SECTOR);  
      EraseSector(APP_START_SECTOR,APP_END_SECTOR);                          /* ²Á³ýÉÈÇø                     */
      BlankCHK(APP_START_SECTOR,APP_END_SECTOR);                             /* ²é¿ÕÉÈÇø                     */
      SelSector(APP_START_SECTOR,APP_END_SECTOR);     
      PRINT_Log("\r\nstart file operations...\r\n");

    fdr = FILE_Open(FILENAME_R, RDONLY);
    if (fdr > 0) {
        PRINT_Log("Reading from %s...\n", FILENAME_R);
  for(writelen=0;writelen<(APP_END_ADDR-APP_START_ADDR)/1024;writelen++)
   {
    bytes_read = FILE_Read(fdr, UserBuffer, MAX_BUFFER_SIZE);            /* ¶Á³öÎļþ                 */
    dstaddr =  (uint32_t)(APP_START_ADDR + (writelen)*1024);//dst address.  
    SelSector(APP_START_SECTOR,APP_END_SECTOR);     
    RamToFlash(dstaddr,(uint32_t)UserBuffer, 1024);
    Compare(dstaddr, (uint32_t)UserBuffer, 1024);
    }  
  // printf("%x",writelen);
  PRINT_Log("\r\n write file successful\r\n");
    SCB->VTOR  = APP_START_ADDR;                                    /* ÖØÐÂÓ³ÉäÏòÁ¿±í               */
    ExceuteApplication(); 
  FILE_Close(fdr);
    } else {
   
上面的代码可以分为两部分:1.从U盘读取bin文件2.IAP功能。先说IAP部分,IAP实现方法有UART,GPRS,USB等方式。要进行IAP设计,先划分FLASH扇区。LPC1788的FLASH划分如下:

flash-iap.jpg
将flash划分为两个区,bootloader和APP区,bootloader存放升级引导程序,即我们的USB_HOST_IAP代码,根据具体的Code大小确定bootloader的扇区,APP就是用户程序即需要升级的程序代码。APP需要配置后面再说。这是我的扇区划分:
#define     IAP_START_ADDR  0x00000000                                  // IAP开始地址
#define     IAP_LOCATION     0x1FFF1FF1                                   /* IAP升级的入口地址          */
/* The area will be erase and program */
#define APP_START_ADDR      0x00A000              // 用户程序起始地址
#define APP_END_ADDR        0x78000                //LPC1788 512K Flash         
//#define APP_SIZE       0x10000 
/*
 * Define the flash sectors used by the application
 */
#define APP_START_SECTOR     10
#define APP_END_SECTOR         29                   // LPC1788  512K Flash扇区
接下面
现场升级方案:采用U盘方式进行IAP功能的实现(二)

作者: 阳光守望者, 来源:面包板社区

链接: https://mbb.eet-china.com/blog/uid-me-1758179.html

版权声明:本文为博主原创,未经本人允许,禁止转载!

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
19
关闭 站长推荐上一条 /3 下一条