自研调试器烧写固件程序(下载bin文件工具)
时间:2021年07月18日 人气:...

通常嵌入式开发中,调试用的都是基于搭载了xx芯片的模组搞得开发板(后续简称MCU),给它烧录固件一般都是在电脑上(后续简称PC)使用串口进行下载烧写。所以通常的开发调试步骤都是,先打开一个串口工具看看调试信息,当需要下载固件时,就关闭这个串口工具,然后使用下载工具打开这个串口进行固件下载烧写,当固件烧写完成之后,再关闭固件下载工具,再次打开串口工具查看调试信息。   --->  这样我们不难看出,研发人员需要不停的切换串口工具,虽然操作不难,但是步骤重复繁琐。

有次我在对接客户程序时,发现客户提供了一个使用调试器烧写固件的工具,用它下载固件就不用进行串口工具切换,感觉十分的方便。后来发现RT-Thread提供的studio集成环境也是提供了类似的工具(如给stm32下载固件时点一下下载就烧写进去了),感觉这好傻瓜化啊,真特么好用。

于是我就对这种烧写的技术原理产生了探究的冲动。我以前也接触过keil、Iar等工具,我知道像这种用调试进行烧写时需要先编写flash烧写驱动,所以各家拿调试器下载固件的套路应该基本上都是一样的。起先我在linux时使用gdb调试程序,后来切换到嵌入式后发现使用调试器(jtag)也可以使用gdb调试,于是我瞬间就明白了这种烧写套路的原理。

先讲讲这种烧写模型:

这里面pc1和pc2可能是同一台电脑,也有可能是两台不同的电脑(常见的pc1是自己电脑,pc2是编译服i务器);

mcu和pc的连接通常就是使用调试器进行连接的(常见的如jlink、stlink、dap、cklink、icemini等);

debug server各家实现都不一样甚至名字都不一样(如openocd),有些甚至就是开源项目openocd的包装改名(如csky debug server、iceman等);

再讲讲这种烧写步骤:

为了通俗好懂,我以gdb操作为例说明怎么完成这种烧写。

  • 1.  先编写一个加载在mcu上ram上运行的elf程序,这个程序里通常定义了几个固定名称的变量和函数,流程都是根据某个变量的取值进行下一步操作的;

  • 2.  使用gdb加载elf程序到mcu上(load指令);

  • 3.  对elf程序某个固定函数设置断点(b fun指令),也有可能是elf程序固定产生一个软件断点(软中断汇编指令);

  • 4.  让elf程序run起来(c指令);

  • 5.  等待预定的断点产生,查询elf那几个固定的变量名称以便检查某个流程执行结果是否成功(p var指令);

  • 6.  改变某些固定变量的值(set var=xx指令),这一步是为了控制流程或传输数据(如将真正的固件bin文件逐渐填入这些变量地址中);

  • 7.  重复步骤5和6;

  • 8.  当真正的固件bin传输完成之后,继续用步骤6中的步骤设置流程变量触发elf程序结束烧写流程(如复位mcu或直接从rom启动);

如何实现这种操作?

根据我的模型图,先在电脑上连接一个mcu,然后起个debug serve让它连接到mcu上,然后就写一段在pc上执行的程序,这个pc程序使用tcp连接debug server,然后使用rsp协议(GDB Remote Serial Protocol)控制debug server:加载mcu的elf程序--->传输真正的固件bin数据到mcu并控制elf程序完成烧写。

更多功能

进一步给他增加了把bin带入默认参数、自动拉起debug server、可以选择使用带界面的程序等等等。

可以命令行使用--->

可以带界面使用--->

windows下

ubuntu下

结束

写到最后,我提供编译好的程序供喜欢的朋友研究。

flash_program_v3.5 for windows.zip   <---   在windows10下测试可用

flash_program_v3.5 for linux.zip          <---   在ubuntu20.04下测试可用


所有这套程序是我用c语言实现的,也提供源码给感兴趣的朋友研究。

除了pC侧程序,针对具体的mcu核,还需要使用者根据例子实现mcu 侧的汇编启动代码和的flash操作接口。

em_flash_program_v1.0.7z        <---   包含了mcu测的代码示例

flash_program_v3.5 source.7z   <---   仅包含了PC侧代码


分享看到两篇好文章:

原来gdb的底层调试原理这么简单

gdb调试解决找不到源代码的问题

热门评论