热度 19
2015-2-22 21:22
3158 次阅读|
0 个评论
闲来无事,总结一下前段时间做过的U盘升级项目。一个新手的成长之路在于善于总结,生活也是一样扯远了,我准备了两个软件环境,一个带操作系统(UCOS)的,另一个裸机版的。随后我会附上两个程序代码。U盘升级可以分为两部分代码:U盘读取 bin文件和IAP功能两部分。大概说一下实现过程,具体IAP网上都玩坏了。 硬件环境:NXP 1788 软件环境:KEIL 运行升级程序。其实可以更具体,比如说设置升级标志或者按键。 拿到一个程序先从main开始,直接贴代码,说一大堆废话有什么用。 int main() { int32_t rc; uint32_t numBlks, blkSize; uint8_t inquiryResult ; 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; PCONP |= 0x80000000; OTGClkCtrl = 0x00000019; /* Enable USB host clock */ OTGClkSt & 0x00000019) != 0x19); StCtrl = 0x1;/* 01: U1 = host (OTG), U2 = host */ P0_29 &= ~(0x07UL << 0); P0_30 &= ~(0x07UL << 0); P1_28 &= ~(0x07UL << 0); P1_29 &= ~(0x07UL << 0); P0_29 |= 0x01UL << 0; /* P0.29 -- USB1 D+ */ P0_30 |= 0x01UL << 0; /* P0.30 -- USB1 D- */ P1_28 |= 0x01UL << 0; /* P1.28 -- USB_SCL1 */ 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 */ Control = 0; /* HARDWARE RESET */ ControlHeadED = 0; /* Initialize Control list head to Zero */ BulkHeadED = 0; /* Initialize Bulk list head to Zero */ /* SOFTWARE RESET */ CommandStatus = OR_CMD_STATUS_HCR; FmInterval = DEFAULT_FMINTERVAL; /* Write Fm Interval and Largest Data Packet Counter */ /* Put HC in operational state */ Control & (~OR_CONTROL_HCFS)) | OR_CONTROL_HC_OPER; RhStatus = OR_RH_STATUS_LPSC; /* Set Global Power */ HCCA = (uint32_t)Hcca; InterruptStatus; /* Clear Interrrupt Status */ 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); 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"); 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); 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"); VTOR = APP_START_ADDR; /* ÖØÐÂÓ³ÉäÏòÁ¿±í */ ExceuteApplication(); FILE_Close(fdr); } else { 上面的代码可以分为两部分:1.从U盘读取bin文件2.IAP功能。先说IAP部分,IAP实现方法有UART,GPRS,USB等方式。要进行IAP设计,先划分FLASH扇区。LPC1788的FLASH划分如下: 将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_ADDR0x00A000 //用户程序起始地址 #define APP_END_ADDR 0x78000 //LPC1788 512K Flash //#define APP_SIZE 0x10000 /* * Define the flash sectors used by the application */ #define APP_START_SECTOR10 #define APP_END_SECTOR 29 // LPC1788 512K Flash扇区 接下面 现场升级方案:采用U盘方式进行IAP功能的实现(二) Blog: 更多技术文章请关注: 百家号: https://author.baidu.com/home?context=%7B%22app_id%22%3A%221646108714303504%22%7D&wfr=bjh 头条号: https://www.toutiao.com/c/user/8115738721/#mid=1646025109246987 CSDN : https://blog.csdn.net/u012246376