NXP

【MPC5744P】Bootloader下位机开发(CAN通讯)

2019-07-12 12:26发布

Bootloader下位机及用户APP范例直接下载:https://download.csdn.net/download/u010875635/10882172 此下位机开发通讯采用CAN,所有Hex文件解析工作在上位机,下位机尽可能避免复杂操作,以加快烧录速度。 使用的为NXP DEVKIT-MPC5744P开发板。 为保证烧录过程不出现错误,上下位机采用一问一答模式,上位机发送一帧数据后,下位机接收处理完毕再回馈给上位机,上位机再决定下一步动作。 核心代码逻辑部分,将命令分成EntryBootloader, Reset, Data, DataEnd, CheckBootloader, Erase, ERR几个部分。 烧录时会先检查是否处于Bootloader,然后执行擦写操作(擦写地址范围由上位机发送),再发送数据(地址+数据为一帧),最后发送结束命令。由于Flash编程最小单位为64bits,所以为防止出现奇数个数据,最后结束检查必不可少。 void CAN_Tasks() { // uint32_t iflag = CAN_0.IFLAG1.R; if(CAN_0.IFLAG1.B.BUF6I==1) /*is new CAN data received*/ { CAN_RxMsg = CAN0_ReceiveMsg(MB6); //CAN_0.IFLAG1.B.BUF6I=0; AfterBootloader_CmdType result = Bootloader_DataParse_g(CAN_RxMsg.Frame_Data,CAN_RxMsg.Frame_Length); switch (result) { case EntryBootloader: break; case Reset: bootloader_entry(); /*jump to app and should not back */ break; case Data: UserFlash_DataParseAddrData(CAN_RxMsg.Frame_Data,CAN_RxMsg.Frame_Length); SIUL2.GPDO[LED_R].B.PDO ^= 1; //red led blink Load_ReponseToUpMachine(g_Bootloader_DataReponse,8); // g_ReceiveCount++; break; case DataEnd: UserFlash_LastIsFull64Bits_g(); SIUL2.GPDO[LED_R].B.PDO = 1; //red off SIUL2.GPDO[LED_G].B.PDO = 0; //green on SIUL2.GPDO[LED_B].B.PDO = 1; // blue off Load_ReponseToUpMachine(g_Bootloader_DataProgramEndReponse,8); app_entry(); /*jump to app and should not back */ break; case CheckBootloader: Load_ReponseToUpMachine(g_Bootloader_CheckBootloaderReponse,8); break; case Erase: countTimer=(1000*g_GOTOAPP_TIMEOUT)+1; UserFlash_EraseIvtAndUserAppBlock_g(CAN_RxMsg.Frame_Data,CAN_RxMsg.Frame_Length); SIUL2.GPDO[LED_R].B.PDO = 1; //red off SIUL2.GPDO[LED_G].B.PDO = 1; //green off SIUL2.GPDO[LED_B].B.PDO = 1; // blue off Load_ReponseToUpMachine(g_Bootloader_EraseFlashReponse,8); break; default: break; }/*end if switch*/ } } //每帧CAN数据类型解析 AfterBootloader_CmdType Bootloader_DataParse_g(uint8_t *data, uint8_t dataLength) { uint8_t result=0; if(dataLength!=8) return 0xff; //第一个字节为数据类型 switch(data[0]) { case EntryBootloader: result = EntryBootloader; break; case Reset: result = Reset; break; case Data: result = Data; break; case DataEnd: result = DataEnd; break; case CheckBootloader: result = CheckBootloader; break; case Erase: result = Erase; break; default:return 0xff; } return result; } Flash焼写逻辑(注意,由于CAN长度为8字节,而32位地址已经占用4字节,Flash地址从0x800000开始,所以所有地址减去0x800000,3字节即可,首字节作为数据类型): /*************************************** * Flash Block Range 锛� // LOW--not program, partition 0 and 1 0x00800000-0x00803FFF -- 16KB,EEPROM-low block0, RWW_P:0 0x00804000-0x00807FFF -- 16KB,EEPROM-low block1, RWW_P:0 0x00F98000-0x00F9BFFF -- 16KB,low flash memory block2, RWW_P:1 //bootloader 0x00F9C000-0x00F9FFFF -- 16KB,low flash memory block3, RWW_P:1 //bootloader // MID , partition 2 and 3 0x00808000-0x0080FFFF -- 32KB,EEPROM-mid block0, RWW_P:2 0x00810000-0x00817FFF -- 32KB,EEPROM-mid block1, RWW_P:3 //HIGH, , partition 4 and 5 0x00FA0000-0x00FAFFFF -- 64KB,high flash memory block0, RWW_P:4 //User App 0x00FB0000-0x00FBFFFF -- 64KB,high flash memory block1, RWW_P:4 0x00FC0000-0x00FCFFFF -- 64KB,high flash memory block2, RWW_P:4 0x00FD0000-0x00FDFFFF -- 64KB,high flash memory block3, RWW_P:5 0x00FE0000-0x00FEFFFF -- 64KB,high flash memory block4, RWW_P:5 0x00FF0000-0x00FFFFFF -- 64KB,high flash memory block5, RWW_P:5 //256K--all used 0x01000000-0x0103FFFF -- 256KB,256k flash memory block0, RWW_P:6 0x01040000-0x0107FFFF -- 256KB,256k flash memory block1, RWW_P:6 0x01080000-0x010BFFFF -- 256KB,256k flash memory block2, RWW_P:6 0x010C0000-0x010FFFFF -- 256KB,256k flash memory block3, RWW_P:6 0x01100000-0x0113FFFF -- 256KB,256k flash memory block4, RWW_P:7 0x01140000-0x0117FFFF -- 256KB,256k flash memory block5, RWW_P:7 0x01180000-0x011BFFFF -- 256KB,256k flash memory block6, RWW_P:7 0x011C0000-0x011FFFFF -- 256KB,256k flash memory block7, RWW_P:7 **************************************/ uint32_t USERAPPFLASH_STARTADDR=0x00FA0000; uint32_t USERAPPFLASH_ENDADDR=0x011FFFFF; //erase //0xFD0000-0x010032E4, 0x05,0x7d,0x00,0x00,0x80,0x32,0xe4,0x00 void UserFlash_EraseIvtAndUserAppBlock_g(uint8_t *data, uint8_t length) { uint32_t count=0; USERAPPFLASH_STARTADDR = data[1]*256*256 + data[2]*256 + data[3] + 0x800000; USERAPPFLASH_ENDADDR = data[4]*256*256 + data[5]*256 + data[6] + 0x800000; Flash_Unlock_g(USERAPPFLASH_STARTADDR,USERAPPFLASH_ENDADDR); Flash_Erase_g(USERAPPFLASH_STARTADDR,USERAPPFLASH_ENDADDR); //Flash_Check_g(USERAPPFLASH_STARTADDR,USERAPPFLASH_ENDADDR); while(count<100000) count++; // erase_flash_except_bootloader(); } //length%2==0,length must be even number void UserFlash_WriteData(uint32_t addr, uint32_t *data, uint32_t length) { uint32_t startAddr; uint32_t endAddr; startAddr = addr; endAddr = startAddr+length-1; // Flash_Unlock_g(startAddr,endAddr); // ret = Flash_Erase_g(startAddr,endAddr); //ret = Flash_Check_g(startAddr,endAddr); Flash_Program_g(startAddr,endAddr, data,length); // Flash_Lock_g(startAddr,endAddr); } uint32_t m_LastAddr=0x000004+0x800000; //program every 8 address uint32_t dataForWrite[2]; //最小写入单位64bits //program addr must add 0x800000 void UserFlash_DataParseAddrData(uint8_t *data, uint8_t length) { uint32_t addr; uint32_t dataTmp; addr = data[1]*256*256 + data[2]*256 + data[3] + 0x800000; //large-endian dataTmp = data[4]*256*256*256 +data[5]*256*256+ data[6]*256 + data[7]; if(addr%8==0) //本次第一个地址 { if(m_LastAddr%8==0) //上一次也为第一个 { dataForWrite[1] = 0xFFFFFFFF; //上一次第二个填充FFFFFFFF UserFlash_WriteData(m_LastAddr,dataForWrite,2); } //无论上次是否为第一个,本次都是开始 dataForWrite[0] = dataTmp; //鏈涓虹涓�涓寚浠ゅ瓧 } else //本次为第二个地址 { if(m_LastAddr%8==0) //上次为第一个 { if((addr-m_LastAddr)==4) //与上次连续 { dataForWrite[1] = dataTmp; //本地为上次同一组第二个 UserFlash_WriteData(m_LastAddr,dataForWrite,2); } else //与上一次不连续 { dataForWrite[1] = 0xFFFFFFFF; //上次第二个填充FFFFFFFF UserFlash_WriteData(m_LastAddr,dataForWrite,2); dataForWrite[0] = 0xFFFFFFFF; //本次第一个填充FFFFFFFF dataForWrite[1] = dataTmp; / UserFlash_WriteData(addr-4,dataForWrite,2); } } else //上次为第二个,仅填充本次组即可 { dataForWrite[0] = 0xFFFFFFFF; dataForWrite[1] = dataTmp; UserFlash_WriteData(addr-4,dataForWrite,2); } } m_LastAddr = addr; } void UserFlash_LastIsFull64Bits_g() { if(m_LastAddr%8==0) //最后是否为单个数据 { dataForWrite[1] = 0xFFFFFFFF; UserFlash_WriteData(m_LastAddr,dataForWrite,2); } Flash_Lock_g(USERAPPFLASH_STARTADDR,USERAPPFLASH_ENDADDR); }   另外提醒大家一下,在没有Bootloader时,首次通过JTAG烧录程序时,可以将Bootloader和App合并烧录,一般是将Bootloader的Hex文件最后一行删除,将App的所有行复制到Bootloader后面。     下面贴几个文件:   Bootloader.h #ifndef _AFTER_PROTOCOL_BOOTLOADER_H_ #define _AFTER_PROTOCOL_BOOTLOADER_H_ #include //bootloader wait time (seconds) #define g_GOTOAPP_TIMEOUT 4 /// /// Command type /// typedef enum { EntryBootloader=0,Reset=1,Data=2,DataEnd=3,CheckBootloader=4,Erase=5,ERR=0xff }AfterBootloader_CmdType; /// /// Bootloader Entry /// uint8_t m_Bootloader_EntryBootloaderCmd[8]; /// /// reset in bootloader /// uint8_t m_Bootloader_ResetCmd_g[8]; /// /// Check Mcu is whether in bootloader /// uint8_t m_Bootloader_CheckBootloaderCmd[8]; /// /// reponse to up machine with "I am in bootloader" for once enter bootloader /// uint8_t g_Bootloader_EntryBootloaderReponse[8]; /// /// reponse for check bootloader command, if mcu is in bootloader and up machine ask for reply /// uint8_t g_Bootloader_CheckBootloaderReponse[8]; /// /// reponse for erasing completed /// uint8_t g_Bootloader_EraseFlashReponse[8]; /// /// reponse for filling one data completed /// 02 00 00 00 00 00 00 00 /// uint8_t g_Bootloader_DataReponse[8]; /// /// reponse for the last data writing completed /// extern uint8_t g_Bootloader_DataProgramEndReponse[8]; //check received can data, and parse command type AfterBootloader_CmdType Bootloader_DataParse_g(uint8_t *data, uint8_t dataLength); #endif     Bootloader.c #include "Bootloader.h" /// /// Bootloader Entry /// uint8_t m_Bootloader_EntryBootloaderCmd[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /// /// reset in bootloader /// uint8_t m_Bootloader_ResetCmd_g[8] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /// /// Check Mcu is whether in bootloader /// uint8_t m_Bootloader_CheckBootloaderCmd[8] = { 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /// /// reponse to up machine with "I am in bootloader" for once enter bootloader /// uint8_t g_Bootloader_EntryBootloaderReponse[8] = { 0x00, g_GOTOAPP_TIMEOUT, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /// /// reponse for check bootloader command, if mcu is in bootloader and up machine ask for reply /// uint8_t g_Bootloader_CheckBootloaderReponse[8] = { 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /// /// reponse for erasing completed /// uint8_t g_Bootloader_EraseFlashReponse[8] = {0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; /// /// reponse for filling one data completed /// 02 00 00 00 00 00 00 00 /// uint8_t g_Bootloader_DataReponse[8] ={ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; /// /// reponse for the last data writing completed /// uint8_t g_Bootloader_DataProgramEndReponse[8] = { 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; //compare array uint8_t ArrayCheck(uint8_t *data1,uint8_t *data2,uint8_t length) { uint8_t i,result=0; for(i=0;i   UserAppFlash.h #ifndef _AFTER_PROTOCOL_USERAPPFLASH_H_ #define _AFTER_PROTOCOL_USERAPPFLASH_H_ #include //erase, 8 bits data is can receive data void UserFlash_EraseIvtAndUserAppBlock_g(uint8_t *data, uint8_t length); //fill data, 8 bits data is can receive data void UserFlash_DataParseAddrData(uint8_t *data, uint8_t length); //receive data end, check data is whether writed completed void UserFlash_LastIsFull64Bits_g(); #endif   UserAppFlash.c #include "Bootloader.h" #include "Drivers/Flash/flash.h" /*************************************** * Flash Block Range 锛� // LOW--not program, partition 0 and 1 0x00800000-0x00803FFF -- 16KB,EEPROM-low block0, RWW_P:0 0x00804000-0x00807FFF -- 16KB,EEPROM-low block1, RWW_P:0 0x00F98000-0x00F9BFFF -- 16KB,low flash memory block2, RWW_P:1 //bootloader 0x00F9C000-0x00F9FFFF -- 16KB,low flash memory block3, RWW_P:1 //bootloader // MID , partition 2 and 3 0x00808000-0x0080FFFF -- 32KB,EEPROM-mid block0, RWW_P:2 0x00810000-0x00817FFF -- 32KB,EEPROM-mid block1, RWW_P:3 //HIGH, , partition 4 and 5 0x00FA0000-0x00FAFFFF -- 64KB,high flash memory block0, RWW_P:4 //User App 0x00FB0000-0x00FBFFFF -- 64KB,high flash memory block1, RWW_P:4 0x00FC0000-0x00FCFFFF -- 64KB,high flash memory block2, RWW_P:4 0x00FD0000-0x00FDFFFF -- 64KB,high flash memory block3, RWW_P:5 0x00FE0000-0x00FEFFFF -- 64KB,high flash memory block4, RWW_P:5 0x00FF0000-0x00FFFFFF -- 64KB,high flash memory block5, RWW_P:5 //256K--all used 0x01000000-0x0103FFFF -- 256KB,256k flash memory block0, RWW_P:6 0x01040000-0x0107FFFF -- 256KB,256k flash memory block1, RWW_P:6 0x01080000-0x010BFFFF -- 256KB,256k flash memory block2, RWW_P:6 0x010C0000-0x010FFFFF -- 256KB,256k flash memory block3, RWW_P:6 0x01100000-0x0113FFFF -- 256KB,256k flash memory block4, RWW_P:7 0x01140000-0x0117FFFF -- 256KB,256k flash memory block5, RWW_P:7 0x01180000-0x011BFFFF -- 256KB,256k flash memory block6, RWW_P:7 0x011C0000-0x011FFFFF -- 256KB,256k flash memory block7, RWW_P:7 **************************************/ uint32_t USERAPPFLASH_STARTADDR=0x00FA0000; uint32_t USERAPPFLASH_ENDADDR=0x011FFFFF; //erase //0xFD0000-0x010032E4, 0x05,0x7d,0x00,0x00,0x80,0x32,0xe4,0x00 void UserFlash_EraseIvtAndUserAppBlock_g(uint8_t *data, uint8_t length) { uint32_t count=0; USERAPPFLASH_STARTADDR = data[1]*256*256 + data[2]*256 + data[3] + 0x800000; USERAPPFLASH_ENDADDR = data[4]*256*256 + data[5]*256 + data[6] + 0x800000; Flash_Unlock_g(USERAPPFLASH_STARTADDR,USERAPPFLASH_ENDADDR); Flash_Erase_g(USERAPPFLASH_STARTADDR,USERAPPFLASH_ENDADDR); //Flash_Check_g(USERAPPFLASH_STARTADDR,USERAPPFLASH_ENDADDR); while(count<100000) count++; // erase_flash_except_bootloader(); } //write one group (64bits) data //length%2==0,length must be even number void UserFlash_WriteData(uint32_t addr, uint32_t *data, uint32_t length) { uint32_t startAddr; uint32_t endAddr; startAddr = addr; endAddr = startAddr+length-1; // Flash_Unlock_g(startAddr,endAddr); // ret = Flash_Erase_g(startAddr,endAddr); //ret = Flash_Check_g(startAddr,endAddr); Flash_Program_g(startAddr,endAddr, data,length); // Flash_Lock_g(startAddr,endAddr); } uint32_t m_LastAddr=0x000004+0x800000; //program every 8 address锛�64bits uint32_t dataForWrite[2]; //every 64bits for programming //program addr must add 0x800000 //every 64bits for programming (one group with two data) void UserFlash_DataParseAddrData(uint8_t *data, uint8_t length) { uint32_t addr; uint32_t dataTmp; addr = data[1]*256*256 + data[2]*256 + data[3] + 0x800000; //large-endian dataTmp = data[4]*256*256*256 +data[5]*256*256+ data[6]*256 + data[7]; if(addr%8==0) //is the first 32bits data of 64bits , every 32bits occupy 4 address uints { if(m_LastAddr%8==0) // last address is first of a group { dataForWrite[1] = 0xFFFFFFFF; //fill second data of last group with 0xffffffff UserFlash_WriteData(m_LastAddr,dataForWrite,2); //write last group data to flash } //Hower last group is really filled, the new group start dataForWrite[0] = dataTmp; //new group first data } else //is the second data of group { if(m_LastAddr%8==0) // last address is first of a group { if((addr-m_LastAddr)==4) //this is the next of last data within one group { dataForWrite[1] = dataTmp; //fill the second data of group UserFlash_WriteData(m_LastAddr,dataForWrite,2); //write this group to flash } else //last address is first data of a group, and this address is second, but they are not in one group { dataForWrite[1] = 0xFFFFFFFF; //fill second data of last group with 0xffffffff UserFlash_WriteData(m_LastAddr,dataForWrite,2); //write last group data to flash dataForWrite[0] = 0xFFFFFFFF; //fill first data of this group with 0xffffffff dataForWrite[1] = dataTmp; //fill second data of this group UserFlash_WriteData(addr-4,dataForWrite,2); //write this group data to flash } } else// last address is second of a group, and this address is second { dataForWrite[0] = 0xFFFFFFFF; //fill first data of this group with 0xffffffff dataForWrite[1] = dataTmp; //fill second data of this group UserFlash_WriteData(addr-4,dataForWrite,2); //write this group data to flash } } m_LastAddr = addr; } //receive data end, check data is whether writed completed void UserFlash_LastIsFull64Bits_g() { if(m_LastAddr%8==0) // last address is first of a group { dataForWrite[1] = 0xFFFFFFFF; //fill second data of last group with 0xffffffff UserFlash_WriteData(m_LastAddr,dataForWrite,2); //write last group data to flash } Flash_Lock_g(USERAPPFLASH_STARTADDR,USERAPPFLASH_ENDADDR); }