本文是关于我的第一个开源项目“ repl”(链接到下面的存储库)。这个项目的想法是允许微控制器程序员通过其任何接口调试微控制器中的程序,而调试与通过jtag接口进行调试没有太大区别。通过程序的指导性调试,可以停止程序,设置断点,查看寄存器,内存。
首先想到的是创建一个2x应用程序,其中一个线程负责调试接口,另一个线程负责用户程序,这是我所做的。线程之间的切换是在计时器上执行的,每个线程都有自己的堆栈。我决定不使用一堆工具来编写调试接口。必须使用2种不同的线程,否则在处理堆时,必须不断切换到一个线程。
实现指令调试的第一个想法是减少定时器中断之间的时间,以使之只能执行一条指令。该选项显示了其在Atmega328p微控制器上的理想工作,事实是,Atmega中断之间的最短时间为1个处理器周期,任何指令(无论其执行所需的周期数如何)都将在执行开始后始终结束。
不幸的是,当我切换到stm32时,此选项不起作用,因为Cortex-M内核可以在中间中断一条指令的执行,然后在从中断返回时再次开始执行它。然后我决定好了,没问题,我只会增加中断之间的时钟周期数,直到执行该指令为止,然后我偶然发现了另一个问题,有些指令只能由它们后面的指令执行,或者根本不执行,不幸的是这个问题无法解决,所以我决定从根本上改变方法。
我决定效仿这些指令。乍一看,编写一个Cortex M内核仿真器甚至是适合微控制器内存的仿真器的想法看起来都很棒。但是我意识到我并不需要模拟所有指令,而只需要模拟与程序计数器相关联的指令,就没有那么多了。我剩下的所有内容都可以简单地移到另一个存储位置并在那里执行,以便仅执行一条指令,然后在其后添加跳转指令“ b”。
然后转折点了,为了实现它们,我决定使用一条实现while(1);逻辑的指令。我们替换位于我们要设置断点的地址处的指令,并等待定时器中断。我知道类似一条指令会引发异常会更好,但是我想创建一个通用版本。执行后,我们将其替换回原处。一个好的选择是在微控制器的RAM中运行程序,否则微控制器的闪存不会持续很长时间。但是到此为止,我已经完成了为stm32编写一个指令模拟器,并决定了为什么不为Atmega328编写相同的指令模拟器并编写了它。现在,您无需将指令替换回来,它们可以被模拟。
为了使运行时成为所有这些朋友,我首先想编写自己的gdb客户端。不幸的是,它支持两个用于ide的接口。由她决定使用哪种方法。实现这两者(在我看来第一个很简单,第二个不太简单),再加上我必须将源代码与固件结合起来,在我看来这不是一个好主意。因此,我决定编写自己的gdbserver,幸运的是只有一个协议,而且非常简单。
我决定实现的第一个接口是GSM。作为收发器,我决定使用SIM800作为服务器,该服务器具有php支持。主要思想是,在来自微控制器的发布请求到达后,保持30秒与微控制器的连接,并每100毫秒与数据库联系一次(如果数据似乎将其发送为对请求的响应,并等待来自微控制器的下一个请求)。
gdb客户端到服务器的第一个连接表明,使用pause或step命令从gdb客户端到服务器的请求太多。因此,决定将所有这些请求组合成一个大的微控制器请求,因为我了解了这些请求的逻辑并学会了如何预测它们。现在这些命令没有那么快地执行,我希望更快,但是可以忍受。
下一个接口是usb,对于Atmega328微控制器,我决定使用V-usb库。为了使用usb,我重写了run命令逻辑。现在,此命令之后的微控制器没有启动等待暂停命令的程序,而是将其启动了1秒钟,然后向其发送了新的运行命令,依此类推。此逻辑是必要的,因为我在程序运行时禁用了界面。为了避免编写驱动程序的麻烦,我决定使用标准的hid驱动程序。当通信功能隐藏获取功能报告时,隐藏设置功能报告。
至于微控制器的闪存,我认为这对于usb接口是多余的,因此对于第一个固件,您仍然需要编程器。但是对于GSM接口来说,它是最多的。通常,为此目的编写一个单独的程序,但是我决定以不同的方式进行操作,为了编写一个单独的程序,我决定将程序完全加载到微控制器的闪存中,然后在下载完成后,将该程序复制到内存的开头。然后我想为什么要发送整个程序,只能发送当前固件和以前的二进制文件之间的差异。
为了最大程度地减少这种差异,我决定为用户程序的一部分重命名.text,.data,.bss,.contructors数组节(对于不同的微控制器,通用名称是不同的),并将它们放在主程序之后的内存中。
我还必须编写自己的函数来初始化这些部分。现在,在大多数情况下,程序的小的更改等于二进制的小的更改,即等于正在传输的少量数据。结果,微控制器的闪烁速度通常比RUN,STEP,PAUSE命令的运行速度快。
最后是一段工作视频:
通过USB接口进行Stm32调试。
通过gsm接口进行STM32调试。
通过USB接口进行Atmega328调试。
通过gsm接口进行Atmega328调试。
Git仓库