闲来无事,总结一下前段时间做过的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划分如下:
作者: 阳光守望者, 来源:面包板社区
链接: https://mbb.eet-china.com/blog/uid-me-1758179.html
版权声明:本文为博主原创,未经本人允许,禁止转载!
文章评论(0条评论)
登录后参与讨论