历史上的今天
今天是:2025年05月17日(星期六)
2020年05月17日 | 【飞思卡尔 MC9S12】BootLoader 下位机
2020-05-17 来源:eefocus
本篇讲述BootLoader下位机的开发。
刚到新公司第三天就接了一个项目,搞到现在才局部完成,更新比较慢了。
先上传源码比较实际,再介绍基本功能。
源码地址:https://download.csdn.net/download/u010875635/11692136
实际上搞定CAN通信和Flash读写,Bootloader下位机就没什么问题了。
注意一下Bootloader与App的分区划分。
Bootloader与App分别占用2个非分页区。
Bootloader: 0xC000-0xFFFF(实际到0xF7FF,保留一个sector给vector table)
Application: 0x4000-0x7FFF,加上其它分页区(转换成全局地址为0x7F4000-0x7FFFF)

Bootloader实际上核心逻辑没有什么东西,无非就是传输协议,数据重新组合,然后写进去,只不过数据组合的方式决定了刷写的速度。
MCU上电后,首先会进入Bootloader中,1s内没有收到刷写命令(如果App可以接收跳转,则时间不需要这么久,可直接从App跳到Bootloader进行刷写),就会跳到App。数据的CAN ID和命令的CAN ID分开。
本Bootloader采用按行传送数据,减少地址传送次数,以及数据和命令分开传送的方式,提高单位时间数据传送量,以加快刷写速度,在刷写结束后,做个简单校验(例如CRC校验,此处没有做,大家可以自行补充),然后在某个地方写Flag标识,开机启动时Bootloader会读取这个标识,然后判断App是否完好,若是完好,则会在超时后跳到App。
需要注意的是,跳转前要将使用的设备DeInit,例如CAN,否则App使用时可能会有问题。

核心逻辑代码如下(详细请参考源码):
void main(void)
{
McuDrivers_System_Init();
McuDrivers_GPIO_Init();
McuDrivers_CAN2_Init();
EnableInterrupts;
CAN_Send(1,g_Bootloader_EntryBootloaderReponse,8);
for(;;)
{
CAN_Tasks(); //can
Tick_Tasks();
//_FEED_COP(); /* feeds the dog */
} /* loop forever */
/* please make sure that you never leave main */
}
UINT32 countTick = 0;
UINT8 Tick_Tasks()
{
countTick++;
//每隔1000大约1ms
if(countTick==1000)
{
countTick=0;
return Time_Tasks();
}
return 1;
}
UINT32 countTimer=0;
UINT8 Time_Tasks()
{
countTimer++;
if(countTimer<(1000*g_GOTOAPP_TIMEOUT))
{
if(countTimer%500==0)
McuDriver_GPIO_PB0_Toggle(); //blue led blink
}
else if(countTimer==(1000*g_GOTOAPP_TIMEOUT))
{
app_entry();
return 0;
}
if(countTimer>(1000*g_GOTOAPP_TIMEOUT*10))
countTimer=(1000*g_GOTOAPP_TIMEOUT)+1;
return 1;
}
Scm_CanStandData m_CAN_RxMsg; /* for CAN RX */
#pragma MESSAGE DISABLE C1420 //result of function call is ignore
//send can data
void CAN_Send(UINT8 isCmdType,UINT8 *datas,UINT8 length)
{
m_CAN_RxMsg.U32ID = isCmdType==1?SendCmdCANID:SendDataCANID;
m_CAN_RxMsg.DataType = 0; //data type
m_CAN_RxMsg.DataFormat = 1; //ext
m_CAN_RxMsg.DataLength = length;
memcpy(m_CAN_RxMsg.Datas,datas,length);
McuDrivers_CAN2_SendData(&m_CAN_RxMsg);
}
void Software_Wait(UINT16 milliSeconds)
{
UINT16 i,j;
for(i=0;i } //UINT32 g_ReceiveCount=0; UINT8 m_State = 0; #pragma MESSAGE DISABLE C2705//result of function call is ignore //Receive Can Data void CAN_Tasks() { Protocol_Bootloader_CmdType result; int reponse = 0; if(McuDrivers_CAN2_GetStateRX()) { if(McuDrivers_CAN2_ReadData(&m_CAN_RxMsg)==ERR_OK) { if(m_CAN_RxMsg.U32ID==ReceiveCmdCANID) //cmd id { result = Bootloader_DataParse_g(m_CAN_RxMsg.Datas,m_CAN_RxMsg.DataLength); switch (result) { case Reset: app_entry(); /*jump to app and should not back */ break; case FlashErase: if(m_State==0) { countTimer=(1000*g_GOTOAPP_TIMEOUT)+1; reponse = UserFlash_EraseIvtAndUserAppBlock_g(m_CAN_RxMsg.Datas,m_CAN_RxMsg.DataLength); switch(reponse) { case -1: g_Bootloader_EraseFlashReponse[1]=AddressChecksumError; break; case -2: g_Bootloader_EraseFlashReponse[1]= AddressOverRange; break; case -3: g_Bootloader_EraseFlashReponse[1]= EraseFailed; break; default: g_Bootloader_EraseFlashReponse[1]= CmdRunOK; UserFlash_ClearAppIndicate_g(APP_UPDATE_OK_GLOBAL_ADDR); //clear app flag McuDriver_GPIO_PB0_Set(); // led 0 off m_State = 1; break; } CAN_Send(1,g_Bootloader_EraseFlashReponse,8); } break; case SendAddress: if(m_State==1) { // g_ReceiveCount++; //if(g_ReceiveCount>=20063) // _asm(nop); reponse = UserFlash_AddrParse_g(m_CAN_RxMsg.Datas,m_CAN_RxMsg.DataLength); switch(reponse) { case -1: g_Bootloader_SendAddressReponse[1]=AddressChecksumError; break; case -2: g_Bootloader_SendAddressReponse[1]= DataChecksumError; break; default: g_Bootloader_SendAddressReponse[1]= CmdRunOK; break; } CAN_Send(1,g_Bootloader_SendAddressReponse,8); } break; case DataEnd: reponse = UserFlash_CheckLastLineChecksumAndWritten_g(); //write last line to flash switch(reponse) { case -1: g_Bootloader_DataProgramEndReponse[1]=DataChecksumError; break; case -2: g_Bootloader_DataProgramEndReponse[1]= FlashProgramFailed; break; default:
史海拾趣
|
矢量网络分析仪 对于频谱分析和电磁干扰测量来说,频谱分析仪是通信测量仪器中常用的设备,由于具有大于1∞dB的动态范围、低于-110dBc/Hz的噪声、1Hz-100Hz的带宽、50GHz以上的频率范围,能够接收到极微弱的信号和分辨出两个幅度相差很大的信号。频 ...… 查看全部问答> |
|
DM642外部两个中断不同时发生,怎么得到两个中断之间的时间呢? 我现在使用的是DM642,ext_int5,ext_int6分别用作两个外部中断信号 相信大家也遇到过这样的问题,比如一个车轮压在前后两个磁钢上,这两个磁钢分别产生中断信号送给CPU,请问这两次中断之间的时间应该怎么计算呢? 我现在想的是:第一个中断发生 ...… 查看全部问答> |
|
来源:我的博客:http://blog.163.com/yuan_xihua/blog/static/3074054420087135650488/ 一,编程语言部分1,C语言 《C语言大全(第四版)》 市场价 :¥48.00 【原 书 名】 The Complete Referene,Fourth Edition 【 ...… 查看全部问答> |
|
在看2.4.18内核的关于三星的nand flash 驱动时遇到一个地方没有看明白,请指教 使用的nand flash 为 k9f1208 其中有个函数:作用是向flash发送一个地址 static void s3c2410_command (struct mtd_info *mtd, unsigned command, int column, int ...… 查看全部问答> |
|
招聘嵌入式Linux讲师,工作地点上海,要求如下: 1、具有3年或以上相关领域工作经验 2、熟悉嵌入式Bootloadr 3、熟悉Linux 内核及实时系统 4、熟悉Linux驱动 5、熟悉Linux设备驱动 6、熟悉嵌入式文件系统 工作时间可在周末,一经录用 ...… 查看全部问答> |
|
与时俱进的LabVIEW 2010 Friday, September 17, 2010 2:00 PM - 4:00 PM CST Webinar Registration 作为图形化系统设计的平台, NI LabVIEW帮助世界上的工程师与科学家们实现了一个又 ...… 查看全部问答> |
|
作者:Ralf Bendlin,德州仪器系统工程师Tony Ekpenyong,德州仪器系统工程师Debbie Greenstreet,德州仪器战略市场营销 摘要 智能手机与其它手持设备的发展以及其上数据消费应用的大量繁衍生息,不 ...… 查看全部问答> |
|
INOUT引脚: 1.FPGA IO在做输入时,可以用作高阻态,这就是所说的高阻输入; 2.FPGA IO在做输出时,则可以直接用来输入输出。 芯片外部引脚很多都使用inout类型的,为的是节省管腿。就是一个端口同时做输入和输出。 inout在具体实现上一般用 ...… 查看全部问答> |




