AN2295 bootloader文档解析(二)
本帖最后由 FSL_TICS_ZP 于 2014-7-21 10:08 编辑AN2295 bootloader文档解析
AN2295提供了基于8-bit MCU、Coldfire、Kinetis版本的boot loader代码,开发者可根据自己所选MCU的型号,选择对应的版本。由于在同一版本的boot loader代码中,为了适用于同一类型但不同系列的MCU,所以就定义了很多变量以作不同系列MCU的选择之用,但这样会导致boot loader代码的复杂程度递增,从而增加分析的难度。
所以出于上述的原因,特地选择FRDM-KE02的boot loader例程,其可为作为AN2295 boot loader代码的“简装版”,来介绍boot loader例程的工作原理及流程。
主程序代码说明
int main(void)
{
uint32_t uiNullCounter = 0;
uint32_t uiRepeatCount = 0;
FC_Init();
for(;;) {
if( !FC_Communication() )
{
if( g_ucFC_State == FC_STATE_NULL )
{
uiNullCounter ++;
if( uiNullCounter > 0xffff )
{
uiNullCounter = 0;
uiRepeatCount ++;
UART_putchar(TERM_PORT,0xfc);
}
if( uiRepeatCount > CONNECT_OVER_TIME )
{
#ifdef FLASH_LOCATION
SCB_VTOR = RELOCATION_VERTOR_ADDR;
JumpToUserApplication(RELOCATION_VERTOR_ADDR);
#endif
}
}
}
}
return 0;
}
FC_Init函数
void FC_Init( void )
{
Flash_Init(); //初始化Flash时钟
m_pRecFrame = (uint8_t *)&m_RecFrame;
g_ucFC_State = FC_STATE_NULL;
m_uiRecCount = 0; //初始化各变量值
}
FC_ Communication函数
unsigned char FC_Communication( void )
{
uint8_t uiReadData,i;
uint8_t *pAddress;
ADDRESS_TYPE * pTempAddress;
// 判断UART有无收到数据
if(UART_S1_RDRF_MASK != UART_getchar_present(TERM_PORT))
{
return 0;
}
// 读取UART收到的数据
uiReadData = UART_getchar(TERM_PORT);
switch( g_ucFC_State )
{
case FC_STATE_NULL:
{
if( uiReadData == FC_CMD_ACK ) // FC_CMD_ADK即为0xFC
{
//由于KE02波特率设置精准,所以例程中无MCU与PC波特率同步校准函数
UART_putchar( TERM_PORT,0xfc );
g_ucFC_State = FC_STATE_WORKING;// 进入接受命令操作状态
}
else
{
return 0;
}
}
break;
case FC_STATE_WORKING:
{
switch( uiReadData )
{
// Ident指令(0x49),发送boot loader的相关属性信息
case FC_CMD_IDENT:
{
UART_putchar( TERM_PORT,m_MCU_Info.Version);
UART_putchar( TERM_PORT,m_MCU_Info.Sdid>>8);
UART_putchar( TERM_PORT,m_MCU_Info.Sdid);
pTempAddress=(ADDRESS_TYPE *)&m_MCU_Info.BlocksCnt;
for(i=0;i<7;i++)
{
UART_putchar( TERM_PORT,pTempAddress.Bytes.hh);
UART_putchar( TERM_PORT,pTempAddress.Bytes.hl);
UART_putchar( TERM_PORT,pTempAddress.Bytes.lh);
UART_putchar( TERM_PORT,pTempAddress.Bytes.ll);
}
i = 0;
do
{
UART_putchar( TERM_PORT,m_MCU_Info.IdString);
}while(m_MCU_Info.IdString);
}
break;
// Erase指令(0x45),进入Erase Flash 操作
case FC_CMD_ERASE:
{
g_ucFC_State = FC_STATE_EREASE;
}
break;
// Write指令(0x57),进入Write Flash操作
case FC_CMD_WRITE:
{
g_ucFC_State = FC_STATE_WRITE_ADDRESS;
}
break;
//Read指令(0x52),进入Read Flash 操作
case FC_CMD_READ:
{
g_ucFC_State = FC_STATE_READ;
}
break;
//Quit指令(0x51),进入Quit 操作
case FC_CMD_QUIT:
{
//中断向量重定位
SCB_VTOR = RELOCATION_VERTOR_ADDR;
//跳转到User application
JumpToUserApplication(RELOCATION_VERTOR_ADDR);
}
break;
default:
break;
}
m_uiRecCount = 0;
}
break;
// Erase flash操作中
case FC_STATE_EREASE:
{
m_pRecFrame = uiReadData;
if( m_uiRecCount >= sizeof(uint32_t) )
{
//地址字节校正
LONG_Convert(&m_RecFrame.uiAddress);
//判断Erase flash操作是否成功
if(!Flash_EraseSector(m_RecFrame.uiAddress))
{
UART_putchar( TERM_PORT,FC_CMD_ACK );
}
else
{
UART_putchar( TERM_PORT,FC_CMD_NACK );
}
g_ucFC_State = FC_STATE_WORKING;
}
}
break;
// 接受Write Flash操作的起始地址
case FC_STATE_WRITE_ADDRESS:
{
m_pRecFrame = uiReadData;
if( m_uiRecCount >= sizeof(uint32_t) )
{
g_ucFC_State = FC_STATE_WRITE_LEN;
}
}
break;
// 接受Write Flash操作的字节个数
case FC_STATE_WRITE_LEN:
{
m_pRecFrame = uiReadData;
g_ucFC_State = FC_STATE_WRITE_DATA;
}
break;
// 接受Write Flash操作的数据
case FC_STATE_WRITE_DATA:
{
m_pRecFrame = uiReadData;
if( m_uiRecCount > (m_RecFrame.Length + sizeof(uint32_t) ))
{
LONG_Convert(&m_RecFrame.uiAddress);
Memcpy_Byte((uint8_t*)&m_ucDataBuff,(uint8_t*)&m_RecFrame.DataBuff,
m_RecFrame.Length);
uiNumberCount ++;
if( !Flash_Program(m_RecFrame.uiAddress,
(uint8_t *)&m_ucDataBuff,m_RecFrame.Length) )
{
UART_putchar( TERM_PORT,FC_CMD_ACK );
}
else
{
UART_putchar( TERM_PORT,FC_CMD_NACK );
}
g_ucFC_State = FC_STATE_WORKING;
}
}
break;
//Read Flash操作
case FC_STATE_READ:
{
m_pRecFrame = uiReadData;
if( m_uiRecCount > sizeof(uint32_t) )
{
LONG_Convert(&m_RecFrame.uiAddress);
pAddress = (uint8_t *)m_RecFrame.uiAddress;
for( i=0;i<m_RecFrame.Length;i++)
{
UART_putchar( TERM_PORT,pAddress );
}
g_ucFC_State = FC_STATE_WORKING;
}
}
break;
default:
break;
}
return 1;
}
Boot loader程序流程图
boot loader例程程序流程图如下图所示。
文档下载:
FRDM-KE02例程包:
不足之处,欢迎指正,未完待续!! mark 不错终于看到带程序的讲解了
很直观,流程图 很不错,mark以下。 lyzhangxiang 发表于 2014-7-21 10:34
不错终于看到带程序的讲解了
很直观,流程图
欢迎浏览,如有什么疑问请在此帖下留言! 欢迎网友们浏览,如有什么疑问请在此帖下留言! 还要下载第三个,呵呵,收集全了 能不能合在一个文档里啊 这个非常好,有图有程序有解析,这样更容易理解了 很有指导性的文档希望我申请的KE02快点到 赶快试试 收藏继续学习,这些都是要必须掌握的本领。谢谢楼主。 谁能告诉我 解析(一)的链接在哪里 另外,你们和飞思卡尔中文论坛的那些FAE是一伙人么 楼主的例程包里没发现boot loader工程哦。。。 流程图很清晰啊,辛苦了 lidreamer 发表于 2014-9-2 18:05
谁能告诉我 解析(一)的链接在哪里
AN2295 bootloader文档解析(一)
http://www.amobbs.com/thread-5587485-1-1.html
AN2295 bootloader文档解析(三)
http://www.amobbs.com/thread-5589466-1-1.html 必须支持啊....辛苦了 lidreamer 发表于 2014-9-2 18:08
另外,你们和飞思卡尔中文论坛的那些FAE是一伙人么
一伙人,感觉像不法组织一样。
是的,我们都会在论坛上提供支持。 FSL_TICS_ZP 发表于 2014-9-5 09:25
一伙人,感觉像不法组织一样。
是的,我们都会在论坛上提供支持。
呵呵,不拘小节.....据说,你们以后会着重整那个KBOOT,AN2295就停止维护了是么? tyqhaha 发表于 2014-9-4 23:29
楼主的例程包里没发现boot loader工程哦。。。
自己去官网下载吧{:sweat:} lidreamer 发表于 2014-9-5 14:02
呵呵,不拘小节.....据说,你们以后会着重整那个KBOOT,AN2295就停止维护了是么? ...
KBOOT肯定替代AN229等一些Bootloader方案,KBOOT是个全新Bootloader方案,
让客户使用起来更加方便。 FSL_TICS_ZP 发表于 2014-9-5 14:06
KBOOT肯定替代AN229等一些Bootloader方案,KBOOT是个全新Bootloader方案,
让客户使用起来更加方便。 ...
正在研究你们的KBOOT,好像目前只支持K64 本帖最后由 FSL_TICS_ZP 于 2014-9-9 09:33 编辑
lidreamer 发表于 2014-9-5 14:07
正在研究你们的KBOOT,好像目前只支持K64
是的,好像这一版只推出针对K64的bootloader例程,保守起见,我再确认一下。 谢谢分享。。 楼主本论坛里发表的格式很good呀! 不错,赞一个。貌似没有错误处理机制 renjun_EMbest 发表于 2014-11-26 20:29
不错,赞一个。貌似没有错误处理机制
你说的挺正确,错误辨别和处理机制几乎是没有的,这只是一个类似最小系统板的东西,真正应用还需要客户自己添加对应的应用。 一直想研究一下这个东西 牛逼 谢谢 只是大概介绍了流程 最终用到产品的时候比这个考虑的肯定会更加全面 子鱼 发表于 2014-11-30 16:06
只是大概介绍了流程 最终用到产品的时候比这个考虑的肯定会更加全面
你好,
你说的很对,本贴介绍的就是实现bootloader的基本内容,真正在产品里肯定不能这么干了,
还可能加上加密,解密等。 不错终于看到带程序的讲解了 看了一下,是不是和STM32的差不多,也是必须建立两个工程分别烧录IAP和APP吗 哎哟喂,才看到这个BOOTLOADER的分析,这绝对要收藏的啊,好东西; 有这个应该可以做烧写器了 下载学习 多谢分享 下载学习
页:
[1]