[size=34.54545211791992px]AN2295 bootloader[size=34.54545211791992px]文档解析
AN2295提供了基于8-bit MCU、Coldfire、[url=https://www.freescale.co
m/zh-Hans/webapp/sps/site/homepage.jsp?code=KINETIS]Kinetis[/url]版本的boot loader代码,开发者可根据自己所选MCU的型号,选择对应的版本。由于在同一版本的boot loader代码中,为了适用于同一类型但不同系列的MCU,所以就定义了很多变量以作不同系列MCU的选择之用,但这样会导致boot loader代码的复杂程度递增,从而增加分析的难度。
所以出于上述的原因,特地选择[url=https://www.freescale.co
m/zh-Hans/webapp/sps/site/prod_summary.jsp?code=FRDM-KE02Z]FRDM-KE02[/url]的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函数
[table=400] [tr] [td] 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;
<span style="mso-bidi-font-size:10.5pt;font-family:"微软雅黑","sans-serif""> for(i=0;i= 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[m_uiRecCount++] = uiReadData;
if( m_uiRecCount >= sizeof(uint32_t) )
{
g_ucFC_State = FC_STATE_WRITE_LEN;
}
}
break;
// 接受Write Flash操作的字节个数
case FC_STATE_WRITE_LEN:
{
m_pRecFrame[m_uiRecCount++] = uiReadData;
g_ucFC_State = FC_STATE_WRITE_DATA;
}
break;
// 接受Write Flash操作的数据
case FC_STATE_WRITE_DATA:
{
m_pRecFrame[m_uiRecCount++] = uiReadData;
if( m_uiRecCount > (m_RecFrame.Length + sizeof(uint32_t) ))
{
LONG_Convert(&m_RecFrame.uiAddress);
Memcpy_Byte((uint8_t*)&m_ucDataBuff[0],(uint8_t*)&m_RecFrame.DataBuff[0],
m_RecFrame.Length);
uiNumberCount ++;
if( !Flash_Program(m_RecFrame.uiAddress,
(uint8_t *)&m_ucDataBuff[0],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[m_uiRecCount++] = uiReadData;
if( m_uiRecCount > sizeof(uint32_t) )
{
LONG_Convert(&m_RecFrame.uiAddress);
pAddress = (uint8_t *)m_RecFrame.uiAddress;
<span style="mso-bidi-font-size:10.5pt;font-family:"微软雅黑","sans-serif""> for( i=0;i
|