×
嵌入式 > 技术百科 > 详情

【飞思卡尔 MC9S12】BootLoader 下位机

发布时间:2024-05-20 发布时间:
|

本篇讲述BootLoader下位机的开发。


刚到新公司第三天就接了一个项目,搞到现在才局部完成,更新比较慢了。


先上传源码比较实际,再介绍基本功能。


源码地址:/zixunimg/eeworldimg/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

{

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

for(j=0;j<1000;j++) ;

}

//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)

[1] [2]
飞思卡尔MC9S12BootLoader下位机


『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
FPGA及CPLD应用领域不断拓展