【飞思卡尔 MC9S12】BootLoader 上位机

 

本篇讲述BootLoader上位机开发。

Bootloader上位机、下位机以及用户App 范例源码:https://gitee.com/beatfan/freescale_mc9s12xep100_-bootloader.git

此上位机采用WPF框架,C#语言开发,支持周立功的CAN设备和ValueCAN。

由于手头上暂时没有硬件,无法实际演示,大家先凑合看示例图。

注意,有很多人操作误区在于,将S19文件选择成了Bootloader,这里应该选择app,就是你自己的应用程序。

Bootloader与App分别占用2个非分页区。

Bootloader: 0xC000-0xFFFF(实际到0xF7FF,保留一个sector给vector table)

Application: 0x4000-0x7FFF,加上其它分页区(转换成全局地址为0x7F4000-0x7FFFF)

若是不知道怎么写App,可参考范例

 

 

 

 

BootloaderPage.xaml        --        Bootloader刷写界面

S19ParseWithText             --        为S19文件解析查看界面,仅用于查看数据,与刷写无关

ClassBootloaderForCAN   --        协议封包解包在

CANCommon                    --        通用的CAN连接断开、发送接收的类(实际收发在CANDevices类库,大家也可以添加自己手上以后的CAN设备的API,以便于支持)

VAlueCAN和ZlgCAN.xaml --        CAN配置控件,用于设置各个不同的CAN配置参数,方便转换成通用的例如波特率的参数。

 

/// <summary>
        /// 更新进度
        /// </summary>
        void UpdateProgress()
        {
            double percentNoDiv100 = m_CmdCount.SendFrameCount * 100.00 / m_CANSendFrameCount;// e.ProgressPercentage;// m_CmdCount.SendFrameCount * 1.0 / m_CANdataList.Count;
            double usedTime = DateTime.Now.Subtract(m_SendDataSartTime).TotalSeconds;
            double leftTime = usedTime / percentNoDiv100 * (100 - percentNoDiv100);
            //TextBlockChangeMsg("发送进度", "已发送帧数:" + m_CmdCount.SendFrameCount.ToString(), System.Windows.Media.Brushes.Gray);
            TextBlockChangeMsg("刷写进度", "已刷写帧数: " + m_CmdCount.ReceiveFrameCount.ToString() + " ,已用时间:" + usedTime.ToString("0.00") + " s  ,剩余时间:" + leftTime.ToString("0.00") + " s", System.Windows.Media.Brushes.Gray);
            ProcessUpdate(percentNoDiv100);

        }

        /// <summary>
        /// 开始烧录
        /// </summary>
        void TryBurnS19()
        {
            //SendData();
            //return;

            DateTime startTime;
            
            ProcessUpdate(0); //进度清零



            TextBlockAddMsg("检查是否已擦除Flash", System.Windows.Media.Brushes.Black);

            

            m_Mtcl1DevelopCmd.SendNormalBytes(m_UpdateAppSendCmdCANID, GetCurrentCANIndex(),m_CanDataParse.CanErasePackage(m_ValidMinGlobalAddr, m_ValidMaxGlobalAddr));

            startTime = DateTime.Now; //开始计时
            while (m_McuState != McuState.McuFlashErased)
            {
                uint count = 0;
                while (count < 100000)
                    count++;
                if (DateTime.Now.Subtract(startTime).TotalSeconds > 10) //是否超过10s没有接收到
                    break;
            }
            if (m_McuState != McuState.McuFlashErased)
            {
                TextBlockAddMsg("擦除超时", System.Windows.Media.Brushes.Red, 1);
                BurnHex();
                return;
            }
            string ts = DateTime.Now.Subtract(startTime).TotalSeconds.ToString();
            TextBlockAddMsg("擦除完毕!,总耗时:" + ts + "s", System.Windows.Media.Brushes.Blue);

            TextBlockAddMsg("开始发送数据,CAN帧数;" + m_CANSendFrameCount.ToString(), System.Windows.Media.Brushes.Black);


            //m_UpdateProgressTimer.Start(); //定时更新UI
            SendData(); //发送数据
            //m_UpdateProgressTimer.Stop(); //关闭定时更新UI
            
            UpdateProgress();
            
            TextBlockAddMsg("发送数据结束,耗时: " + DateTime.Now.Subtract(m_SendDataSartTime).TotalSeconds.ToString("0.00") + "s", System.Windows.Media.Brushes.Black);

            m_Mtcl1DevelopCmd.SendNormalBytes(m_UpdateAppSendCmdCANID, GetCurrentCANIndex(), m_CanDataParse.g_DataEndCmd); //数据结束命令

            BurnHex();
            
        }

        /// <summary>
        /// 发送后检查是否超时或错误
        /// </summary>
        /// <returns></returns>
        bool CheckAfterSend()
        {
            if (!SendDataCheck_Wait(ref m_CmdCount.SendFrameCount, ref m_CmdCount.ReceiveFrameCount, 2000)) //发送中断
            {
                TextBlockAddMsg("发送超时 ", System.Windows.Media.Brushes.Red);
                return false;
            }

            if (m_ReponseState != ClassBootloaderForCAN.ReponseState.CmdRunOK)
                return false;

            return true;
        }

        /// <summary>
        /// 发送数据
        /// </summary>
        private void SendData()
        {

            m_CmdCount.SendLineCount = 0;
            m_CmdCount.SendFrameCount = m_CmdCount.ReceiveFrameCount = 0;
            m_SendDataSartTime = DateTime.Now; //开始计时

            bool isNotBreak = true;
            
            //发送数据
            for (int i = 0; i < m_CANAddrList.Count && isNotBreak; i++)
            {
                m_Mtcl1DevelopCmd.SendNormalBytes(m_UpdateAppSendCmdCANID, GetCurrentCANIndex(), m_CANAddrList[i]); //发送地址命令
                m_CmdCount.SendLineCount++;
                m_CmdCount.SendFrameCount++;
                if (!CheckAfterSend() ) //发送中断
                {
                    isNotBreak = false;
                    break;
                }

                for (int j=0;j<m_CANdataListList[i].Count && isNotBreak; j++)
                {
                    m_Mtcl1DevelopCmd.SendNormalBytes(m_UpdateAppSendDataCANID, GetCurrentCANIndex(),  m_CANdataListList[i][j]); //发送数据
                    m_CmdCount.SendFrameCount++;
                    if (!CheckAfterSend()) //发送中断
                    {
                        isNotBreak = false;
                        break;
                    }

                }
                if(m_CmdCount.SendLineCount%10==0)
                    UpdateProgress();

            }

            

        }

        /// <summary>
        /// 检查接收情况
        /// </summary>
        /// <returns></returns>
        bool CheckReceive(ref byte[] datas)
        {
            m_ReponseState = ProcessReponseState(ref datas); //获取返回状态
            switch (m_ReponseState)
            {
                case ClassBootloaderForCAN.ReponseState.AddressChecksumError:
                case ClassBootloaderForCAN.ReponseState.AddressOverRange:
                case ClassBootloaderForCAN.ReponseState.DataChecksumError:
                case ClassBootloaderForCAN.ReponseState.EraseFailed:
                case ClassBootloaderForCAN.ReponseState.FlashProgramFailed:
                    TextBlockAddMsg("错误: " + Enum.GetName(typeof(ClassBootloaderForCAN.ReponseState), m_ReponseState), System.Windows.Media.Brushes.Red);
                    return false;

                default: break;
            }
            return true;
        }

        /// <summary>
        /// 获取返回数据的状态
        /// </summary>
        /// <param name="datas"></param>
        /// <returns></returns>
        private ClassBootloaderForCAN.ReponseState ProcessReponseState(ref byte[] datas)
        {
            return (ClassBootloaderForCAN.ReponseState)(datas[1]);
        }

        /// <summary>
        /// 接收数据,回调函数
        /// </summary>
        private void ReceiveData(uint canId, string canIndex,byte[] datas)
        {
            if (canId==m_UpdateAppReceiveCmdCANID) //命令id
            {

                if (!CheckReceive(ref datas)) //收到错误报告
                    return;

                //判断回馈类型
                ClassBootloaderForCAN.CmdType cmdType = m_CanDataParse.ReceiveDataParse(ref datas);
                //TextBlockAddMsg("ReceiveData:"+BitConverter.ToString(datas), System.Windows.Media.Brushes.DarkOrange);
                switch (cmdType)
                {
                    case ClassBootloaderForCAN.CmdType.EntryBootloader: //已经入Bootloader
                        if (m_McuState == McuState.WaitForBootloader)
                            m_McuState = McuState.InBootloader;
                        BootloaderIndicator(true);
                        TextBlockAddMsg("成功进入Bootloader," + datas[2].ToString() + "s内无操作进入用户程序!", System.Windows.Media.Brushes.Blue);
                        break;
                    case ClassBootloaderForCAN.CmdType.CheckBootloader: //检查是否处于Bootloader
                        if (m_McuState == McuState.WaitForBootloader)
                            m_McuState = McuState.InBootloader;
                        BootloaderIndicator(true);
                        //TextBlockAddMsg("成功进入Bootloader," + datas[2].ToString() + "s内无操作进入用户程序!", System.Windows.Media.Brushes.Blue);
                        break;
                    case ClassBootloaderForCAN.CmdType.LeaveBootloader: //离开Bootloader
                        //m_McuState = McuState.BurnEnd;
                        BootloaderIndicator(false);
                        TextBlockAddMsg("Bootloader已断开", System.Windows.Media.Brushes.Blue);
                        break;


                    case ClassBootloaderForCAN.CmdType.Reset:
                        //m_McuState = McuState.BurnEnd;
                        BootloaderIndicator(false);
                        TextBlockAddMsg("重启!", System.Windows.Media.Brushes.Blue);
                        break;

                    case ClassBootloaderForCAN.CmdType.Erase:
                        if (m_McuState == McuState.InBootloader)
                            m_McuState = McuState.McuFlashErased;
                        break;
                    case ClassBootloaderForCAN.CmdType.SendAddress:
                        m_CmdCount.ReceiveFrameCount++;
                        break;

                    case ClassBootloaderForCAN.CmdType.DataEnd:
                        if (m_McuState == McuState.Burnning)
                            m_McuState = McuState.BurnEnd;
                        //m_CmdCount.ReceiveFrameCount++;
                        TextBlockAddMsg("用户程序刷新完毕!", System.Windows.Media.Brushes.Blue);
                        break;
                        
                    case ClassBootloaderForCAN.CmdType.Other:
                        TextBlockAddMsg("Receive Other: " + BitConverter.ToString(datas), System.Windows.Media.Brushes.DarkOrange);
                        break;
                    default: break;
                }
            }
            else //返回数据回应
            {
                //判断回馈类型
                if(m_CanDataParse.ReceiveDataParse(ref datas)==ClassBootloaderForCAN.CmdType.SendData)
                {
                    if (m_McuState == McuState.McuFlashErased)
                        m_McuState = McuState.Burnning;
                    m_CmdCount.ReceiveFrameCount++;
                }
                    
                
            }
            
            
        }

 

 

posted on 2019-07-04 08:29  Beatfan  阅读(773)  评论(0)    收藏  举报

导航