最近想研究下rt的BootLoader,就看到了ymodem的应用。
组件开启得很少,就只有ota_downloader和fal抽象层,用于将文件通过串口写入W25Q的download分区。
直接按照官方的wiki走,输入ymodem_ota
指令后就可以通过XShell的Ymodem协议传输文件了,但是提示Update firmware fail.
错误。网上有各种说比如传输时不能有日志输出,我把ymodem换到了UART3,和控制台的UART1区分开,并且把波特率也降低到了9600,数据传输成功,以下是起始帧传输完对buffer的监视。
上图可以看到,SOH后需要跟随128字节的数据块,依次是:
0x01,SOH头,代表后面128字节的起始帧;
0x00FF,帧序号,表示第一个数据帧;
后面接128字节的正文,包含rtthread.rbl(’\0’结尾),文件大小53520字节(‘ ’结尾);后面的两个ASCII字串内容不清楚(‘ ’结尾);剩下空间补零;
最后两个字节的校验位0x8064。
含SOH共133字节数据。现在分析错误原因,把波特率调回115200,连续测试两次:
两次都是超时退出的,期间共收到129字节,都收到了头和尾,但中间有明显的缺失,第一次100644字串编程了10064,第二次文件大小53520变成了3520,两次都有丢包出现,丢包的位置是随机的,丢包的尺寸是一样的,初步推断是周期性的其他调度和优先级问题导致的。
此时仅有4个线程在运行。
传输过程中MSH无操作,则仅有用于系统调度的滴答时钟中断和接受数据的串口中断在运行,在适当的位置修改优先级让串口优先:
HAL_NVIC_SetPriority(SysTick_IRQn, 4, 0);
HAL_NVIC_SetPriority(uart->config->irq_type, 1, 0);
再次Debug:
共收到132字节数据,有一定的改善,看来系统调度有一定的干扰。
虽然main线程没有任何操作,干脆直接提前结束。
再次测试:
起始帧接收完毕。
把中断优先级再改回去:
HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
//HAL_NVIC_SetPriority(uart->config->irq_type, 1, 0);
再次调试,收到130字节数据。
按理说,ymodem在运行时直接接管了串口中断函数,期间也没有别的操作,不至于那么大的开销,考虑到工程直接使用的内部时钟,外设和主频都比较低:
修改为外部时钟:
接收正常。
出现问题是ymodem传输过快,单片机处理过慢的问题导致的,降低波特率和提升主频都是一种处理方式。
但值得深思的是,此时几乎没有任务调度,没有其他线程参与,串口参数为115200/8/1/N,字符传输速度差不多11.52K字节/每秒,使用内部时钟时,外设频率和系统时钟都为16Mhz,这接近1000倍的时间差。
如果是中断现场保护恢复、信号量通知和系统调度等操作占用时间过长,超过了2字节的传输间隔差不多100us,也就是说这些操作要使用1388个时钟周期,那RT-Thread在STM32上的开销就真的太大了。