FSL_TICS_ZP 发表于 2014-7-21 10:05:43

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例程包:

FSL_TICS_ZP 发表于 2014-7-21 10:06:21


不足之处,欢迎指正,未完待续!!

黑夜之狼 发表于 2014-7-21 10:16:01

mark         

lyzhangxiang 发表于 2014-7-21 10:34:50

不错终于看到带程序的讲解了
很直观,流程图

powerlabor001 发表于 2014-7-21 11:46:04

很不错,mark以下。

FSL_TICS_ZP 发表于 2014-7-21 13:48:57

lyzhangxiang 发表于 2014-7-21 10:34
不错终于看到带程序的讲解了
很直观,流程图

欢迎浏览,如有什么疑问请在此帖下留言!

FSL_TICS_ZP 发表于 2014-7-21 13:50:36

欢迎网友们浏览,如有什么疑问请在此帖下留言!

qwert1213131 发表于 2014-8-22 11:17:10

还要下载第三个,呵呵,收集全了

hongyancl 发表于 2014-8-22 11:32:39

能不能合在一个文档里啊

mo_fish 发表于 2014-8-22 12:23:40

这个非常好,有图有程序有解析,这样更容易理解了

abszy 发表于 2014-8-22 15:18:21

很有指导性的文档希望我申请的KE02快点到   赶快试试

jiang887786 发表于 2014-9-2 13:54:42

收藏继续学习,这些都是要必须掌握的本领。谢谢楼主。

lidreamer 发表于 2014-9-2 18:05:11

谁能告诉我 解析(一)的链接在哪里

lidreamer 发表于 2014-9-2 18:08:45

另外,你们和飞思卡尔中文论坛的那些FAE是一伙人么

tyqhaha 发表于 2014-9-4 23:29:28

楼主的例程包里没发现boot loader工程哦。。。

fbestwish 发表于 2014-9-5 06:22:47

流程图很清晰啊,辛苦了

FSL_TICS_ZP 发表于 2014-9-5 09:01:17

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

RainKing 发表于 2014-9-5 09:14:51

必须支持啊....辛苦了

FSL_TICS_ZP 发表于 2014-9-5 09:25:24

lidreamer 发表于 2014-9-2 18:08
另外,你们和飞思卡尔中文论坛的那些FAE是一伙人么

一伙人,感觉像不法组织一样。
是的,我们都会在论坛上提供支持。

lidreamer 发表于 2014-9-5 14:02:07

FSL_TICS_ZP 发表于 2014-9-5 09:25
一伙人,感觉像不法组织一样。
是的,我们都会在论坛上提供支持。

呵呵,不拘小节.....据说,你们以后会着重整那个KBOOT,AN2295就停止维护了是么?

lidreamer 发表于 2014-9-5 14:04:25

tyqhaha 发表于 2014-9-4 23:29
楼主的例程包里没发现boot loader工程哦。。。

自己去官网下载吧{:sweat:}

FSL_TICS_ZP 发表于 2014-9-5 14:06:00

lidreamer 发表于 2014-9-5 14:02
呵呵,不拘小节.....据说,你们以后会着重整那个KBOOT,AN2295就停止维护了是么? ...

KBOOT肯定替代AN229等一些Bootloader方案,KBOOT是个全新Bootloader方案,
让客户使用起来更加方便。

lidreamer 发表于 2014-9-5 14:07:22

FSL_TICS_ZP 发表于 2014-9-5 14:06
KBOOT肯定替代AN229等一些Bootloader方案,KBOOT是个全新Bootloader方案,
让客户使用起来更加方便。 ...

正在研究你们的KBOOT,好像目前只支持K64

FSL_TICS_ZP 发表于 2014-9-9 09:26:45

本帖最后由 FSL_TICS_ZP 于 2014-9-9 09:33 编辑

lidreamer 发表于 2014-9-5 14:07
正在研究你们的KBOOT,好像目前只支持K64

是的,好像这一版只推出针对K64的bootloader例程,保守起见,我再确认一下。

successliufei 发表于 2014-9-9 09:34:17

谢谢分享。。

qqliyunpeng 发表于 2014-9-9 13:36:53

楼主本论坛里发表的格式很good呀!

renjun_EMbest 发表于 2014-11-26 20:29:01

不错,赞一个。貌似没有错误处理机制

FSL_TICS_ZP 发表于 2014-11-27 09:27:43

renjun_EMbest 发表于 2014-11-26 20:29
不错,赞一个。貌似没有错误处理机制

你说的挺正确,错误辨别和处理机制几乎是没有的,这只是一个类似最小系统板的东西,真正应用还需要客户自己添加对应的应用。

一品电子 发表于 2014-11-30 13:00:06

一直想研究一下这个东西

lininglive 发表于 2014-11-30 15:57:29

牛逼 谢谢

子鱼 发表于 2014-11-30 16:06:47

只是大概介绍了流程 最终用到产品的时候比这个考虑的肯定会更加全面

FSL_TICS_ZP 发表于 2014-12-1 09:29:16

子鱼 发表于 2014-11-30 16:06
只是大概介绍了流程 最终用到产品的时候比这个考虑的肯定会更加全面

你好,
你说的很对,本贴介绍的就是实现bootloader的基本内容,真正在产品里肯定不能这么干了,
还可能加上加密,解密等。

lzs21802180 发表于 2014-12-1 09:40:09

不错终于看到带程序的讲解了

role_2099 发表于 2014-12-2 12:49:54

看了一下,是不是和STM32的差不多,也是必须建立两个工程分别烧录IAP和APP吗

kinsno 发表于 2014-12-2 12:54:14

哎哟喂,才看到这个BOOTLOADER的分析,这绝对要收藏的啊,好东西;

superrf 发表于 2014-12-18 16:37:51

有这个应该可以做烧写器了

a515509429 发表于 2019-6-10 17:20:45

下载学习 多谢分享

jordonwu 发表于 2019-6-10 22:09:06

下载学习
页: [1]
查看完整版本: AN2295 bootloader文档解析(二)