异常处理一例 - Bootloader开机自动升级

71 篇文章 0 订阅
41 篇文章 2 订阅

1.Misfunctional behavior

Bootloader开机后,会尝试与远端的自动程序升级终端握手。目前这个过程是这样的:接收到首帧后,首帧反馈信息不符合YModem协议:

Out之后的In不对,检查一下此时SecureCrt是否在等待回应:

yes, It still waiting...

2.分析

2.1 检查代码的可能位置

1.1.64已经可以看到收到发出了"C" 。这个"C",导致上位机发出 YModem首帧。相关代码:

void TryToLoadApp(void)
{
//等待時間
#define WAIT_TIME 1000
#define WAIT_SPAN 200
    int16_t RetryCnt = WAIT_TIME/WAIT_SPAN;
    if((EE_Key_1 == MAGIC_BYTE1) && (EE_Key_2 == MAGIC_BYTE2))
    {
        RetryCnt = 30000/WAIT_SPAN;
        //不清除,因爲這種狀態會被自然清理掉。
    }
    while(EUSART1_is_rx_ready()) getch(); //讀完緩衝區裏的所有遺留字符。
    
    do
    {
        while(!EUSART1_is_rx_ready())
        {
            putch('C');
            HAL_Delay(WAIT_SPAN);
            if((RetryCnt--)<=0) break;
        }
        
        if(!EUSART1_is_rx_ready())
        {
            if(IsAppExisted()) JumpToRealApp(); //default jump
        }
    }while(!EUSART1_is_rx_ready());
}

这个函数已经退出。明白了,在putch('c')之后,那个WAIT_SPAN的长延时不妥。115200的波特率,10/115200的延时,对方的数据就会来。这是86us。所以,这里的等待检测时间需要达到50us级。

修改=》内存空间超限。。。

2.2 为什么0x600以内的地址空间,编译工具无法使用?

post quesiton at Microchip's forum...

Microchip Forum Question about XC8-CC'shttps://forum.microchip.com/s/topic/a5C3l000000Bpr8EAC/t391265

 此问题已经有答案。我现在又多出来1.5KBytes左右的ROM空间可用。

2.3 将等待时间缩短至50us

现在15帧似乎回送成功了。但是还是多追加了几个"C"、"C"

2.4 根本机制发现,是代码速度跟不上485

最终开机代码改为如下模式:

void TryToLoadApp(void)
{
//等待時間
#define WAIT_TIME 1000 /*單位ms*/
#define WAIT_SPAN 50   /*單位us, DO NOT CHANGE!!! =115200BPS*/
#define OUTPUT_SPAN   (200*1000/WAIT_SPAN) /*單位WAIT_SPAN = 50us*/
    uint32_t RetryCnt = WAIT_TIME/WAIT_SPAN*1000;
    if((EE_Key_1 == MAGIC_BYTE1) && (EE_Key_2 == MAGIC_BYTE2))
    {
        RetryCnt <<=5; 
        //不清除,因爲這種狀態會被自然清理掉。
    }
    while(EUSART1_is_rx_ready()) getch(); //讀完緩衝區裏的所有遺留字符。
    
    do
    {
        while(!EUSART1_is_rx_ready())
        {
            if((RetryCnt--)<=0) break;
            if((RetryCnt&0x7ff)==0) putch('C'); //about 200ms delay。。。
            HAL_usDelay(WAIT_SPAN);
        }
        
        if(!EUSART1_is_rx_ready())
        {
            if(IsAppExisted()) JumpToRealApp(); //default jump
        }
    }while(!EUSART1_is_rx_ready());
    
    uint8_t ymodemHeader[7] = {0x01, 0x00, 0xff, 'g', 'p', 'b', 't'};
    uint8_t idx=0;
    uint8_t dumb;
    uint16_t cnts=0;
    //嘗試讀取ymodem協議字符串
    if(EUSART1_is_rx_ready())
    {
        uint8_t nullLoop=0;
        while(1)
        {
            if(EUSART1_is_rx_ready()) 
            {
                dumb = getch();
                if(idx<7)
                {
                    if(ymodemHeader[idx++]!=dumb) idx|=0xf0;
                }
                cnts++;
            }
            else
            {
                HAL_usDelay(50);
                if(++nullLoop>100) break;
            }
        }
    }
    if(idx==0x07) EE_DUMB = ACK;
    else if(cnts>=128) EE_DUMB = NAK;
    else EE_DUMB = 0;
    xlog("idx=%d, cnts=%d, DUMB=%c", idx, cnts, EE_DUMB);
}

3.结论

为了解析人手工输入的命令并能够在开机时;并能够自动进入YModem接收模式,之前对这些特征字符串是这样解析的:流式命令析取工具https://mp.csdn.net/mp_blog/creation/editor/131644811

在嵌入式环境中,你始终要对时间要警醒——单片机可能无法在指定时间内完成你所设定的动作。那个命令析取工具,应付人手输入,应该可以,但是应付115200bps的485数字流,来不及。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

子正

thanks, bro...

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值