本帖最后由 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[i].Bytes.hh);
- UART_putchar( TERM_PORT,pTempAddress[i].Bytes.hl);
- UART_putchar( TERM_PORT,pTempAddress[i].Bytes.lh);
- UART_putchar( TERM_PORT,pTempAddress[i].Bytes.ll);
- }
- i = 0;
- do
- {
- UART_putchar( TERM_PORT,m_MCU_Info.IdString[i]);
- }while(m_MCU_Info.IdString[i++]);
- }
- 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[m_uiRecCount++] = 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[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;
- for( i=0;i<m_RecFrame.Length;i++)
- {
- UART_putchar( TERM_PORT,pAddress[i] );
- }
- g_ucFC_State = FC_STATE_WORKING;
- }
- }
- break;
- default:
- break;
- }
- return 1;
- }
复制代码
Boot loader程序流程图
boot loader例程程序流程图如下图所示。
11.jpg (109.18 KB, 下载次数: 0)
下载附件
2014-7-21 10:03 上传
文档下载:
AN2295—Developer’s Serial Bootloader 解析(二).pdf
(457.14 KB, 下载次数: 162)
2014-7-21 10:04 上传
点击文件名下载附件
FRDM-KE02例程包:
你好,
你说的很对,本贴介绍的就是实现bootloader的基本内容,真正在产品里肯定不能这么干了,
还可能加上加密,解密等。
一周热门 更多>