1
前言
在开发STM32的过程中,我们经常会用Debug来调试程序查看程序运行中的某些变量或者查看自己的程序运行顺序是否和自己预期的保持一致。
在以前的认知中,Debug时整个CPU是处在一个被暂停的状态,随着我们的程序步进才往前移动。这也当然认为所有内容都被暂停了。
当程序停在某一步的时候,在监控窗口查看定时器的计数值,发现CNT寄存器并没有增加,这时候本能的认为定时器也受Debug影响被“暂停”了,但是,事实真是如此嘛?
2
DMA缓存区
我们在前几期中介绍如何使用ADC的DMA传输以及DAC的DMA传输。它们都有对应的缓存区,其中ADC的缓存区存放了ADC在每个定时器溢出之后采集的一个值。但是当我Debug的发现,当我刚运行完开启ADC的DMA传输时,ADC的缓存区就会装满。这只有两种解释:采集的太快了或者
Debug暂停的仅是CPU并没有暂停定时器的工作 .
为什么这么说呢?因为无论是硬件定时器还是DMA它们都是板载硬件资源,不依赖于CPU的(受CPU调度)虽然我们Debug暂停了CPU的程序运行,但是影响不到定时器以及其他的不依靠CPU运行的外设。
这也能解释另一个现象:Debug中, ** DAC输出的正弦波不受任何影响 ** 。
在上期文章中,我们利用DAC+DMA+TIM实现正弦波的输出。
而就在我Debug的时候发现,正弦波信号也不受Debug影响。程序虽然停在了某处,但是正弦波信号依旧是完整的。如果定时器不工作,DAC的值就不会依靠DMA更新,应该保持在某个值不变。
3
调试冻结寄存器
在仔细阅读参考手册的时候,会发现STM32有一个特殊的寄存器:调试冻结寄存器。STM32中这个寄存器专门用来管理调试过程中各个外设和内核之间的关系。
它主要涉及了在调试状态下各个外设的时钟是否停止,这个功能也是我第一次见到。
例如当我们设置某一位之后,可以当内核停止的时候停止相关定时器。
我们按照手册的方法,可以设置相关寄存器。
DBGMCU->APB1FZR1 |= DBGMCU_APB1FZR1_DBG_TIM7_STOP;DBGMCU->APB1FZR1 |= DBGMCU_APB1FZR1_DBG_TIM3_STOP;
这样子我们就可以实现在Debug内核运行的时候,定时器正常工作,内核停在某处的时候,定时器也会暂停计数。
这样子我们运行完ADC启动时,由于内核是停止的,所以定时器并不会处在工作状态,ADC的缓存区也不会立刻工作。
并且,当我们的内核停下时,DAC也如我们所预料那边保持为直流信号直到内核继续运行。
这也会防止我们Debug的时候出现一些意外的情况。例如:
ADC的缓存区溢出,导致系统进入Hard_Error中断,在Debug中表现的现象就是:开启DMA传输之后,系统走了一两步 ** 停在某个地方停了一下
**
,这时候定时器还在工作,缓存区已经溢出了。然后继续运行就进入了Error中断(数组溢出),从而让开发者一头雾水,不知道为什么停在那个地方之后就会异常了。
而当我们使用了调试冻结寄存器之后,定时器以及其他外设,才能够真正的停下。