微控制器的功耗调试:找出能量泄漏,降低嵌入式系统功耗
功耗调试技术使软件工程师得以了解嵌入式系统的软件对系统功耗的影响。通过建立源代码和功耗之间的联系,使得测试和调整系统功耗成为可能,即所谓功耗调试。传统上,降低功耗仅是硬件工程师的设计目标;然而在实际运行的系统中,功耗不仅取决于硬件的设计,而且还与硬件如何被使用有关,而后者则是由系统软件来控制的。
图1:IAR Systems的C-SPY调试器能够在不同的视图中显示静态和动态的功耗数据。 功耗调试技术基于对功耗进行采样,并建立每个采样数据与程序的指令序列(以及源代码)之间的关联。其中的难点之一在于实现高精度的采样。理想情况下,对功耗的采样频率应该与系统时钟相同,但系统中的电容性元件会降低此类测量的可靠性。从软件工程师的角度来看,更感兴趣的是功耗与源代码以及程序运行期间的各种事件之间的联系,而非个别的指令,因此所需的采样分辨率将大大低于对每个指令进行采样的频率。 对功耗的测量由调试工具完成。例如,IAR Embedded Workbench所支持的调试工具是IAR J-Link Ultra。它能够测量芯片的供电电源经过一个串联小电阻之后的压降,见图2。该压降是使用差分放大器进行测量,并通过模数转换器进行采样的。
图2:IAR J-Link Ultra能够测量芯片的供电电源经过一个串联小电阻之后的压降。 要提高功耗调试的精确性,关键在于建立指令跟踪与功耗采样之间的良好关联。最佳的关联仅当能够进行完全的指令跟踪时才能实现,但其缺点在于并非所有芯片都能支持这一功能;即便支持,也通常需要特殊的调试工具。 要在较低的精确性下达到较好的关联度,可以使用一些现代片上调试架构所支持的PC采样功能。该功能周期性地对PC进行采样,并给出每个采样的时间戳。与此同时,调试工具使用模数转换器对芯片的功耗进行采样。通过比对功耗采样值和PC采样值的时间戳,调试器就能够在同一根时间轴上显示功耗数据以及中断纪录、变量监控等图形,并且将功耗数据与源代码关联起来,见图3。
图3:PC和功耗采样校正。 一般来说,功耗优化与速度优化是非常相似的。一个任务运行得越快,低功耗模式持续的时间就能越长。因此,将处理器的空闲时间最大化可以降低系统的功耗。 想要找出系统中不必要的能耗以及在何处能够降低这些能耗是有难度的。通常它们并非源代码中显而易见地暴露出来的缺陷,而更多地存在于对硬件使用方式的调整之中。
等待设备的状态 一个导致不必要能耗的常见错误是使用轮询来等待某个外设状态的改变。下面的例子中,代码一直不中断地运行,直到状态变量变为预期的值。 while (USBD_GetState() < USBD_STATE_CONFIGURED); while ((BASE_PMC->PMC_SR & MC_MCKRDY) != PMC_MCKRDY); 另一种类似的代码是在for或while循环中实现软件延时,例如: i = 10000; // SW Delay do i--; while (i != 0); 这段代码使得CPU一直忙于执行除了计时之外没有任何作用的指令。 在上述这些情况中,可以通过改写代码来降低功耗。延时最好是通过硬件定时器来实现。CPU在设置好定时器中断之后就可以进入低功耗模式直到被中断唤醒。同样,对外设状态的轮询若有可能也应该通过中断来解决,或者使用定时器中断从而使得CPU在两次轮询之间可以进入休眠。 DMA vs polled I/O 传统上,DMA被用于提高传输速度。在某些架构中,CPU即使在DMA传输过程中也可以进入休眠模式。功耗调试使得开发者能够试验并通过调试器看到与传统由CPU驱动的传输方式相比,DMA技术所带来的效果。 低功耗模式 很多嵌入式应用都把大多数时间花费在等待某些事件发生。如果处理器在空闲时仍然全速运行,电池的寿命将在几乎未作任何事情的情况下被消耗。所以在很多应用中,处理器仅在总计很少的时间里才被激活。通过将处理器在空闲时间里置于低功耗模式,电池的寿命将得到数量级的延长。 一个好的方式是使用RTOS和面向任务的设计。可以定义一个最低优先级,仅当没有任何其他任务需要运行时才会被运行的任务。这个空闲任务将是实现功耗管理的理想场所。在实践中,当空闲任务每次被激活时,都将处理器(或其部份)置于(可能的)多种低功耗模式之一。 CPU频率 理论上,CMOS MCU的功耗可由以下公式得出: P = f x U^2 x k 上式中的f是时钟频率,U是供电电压,k是常数。 功耗调试使得开发者能够验证功耗与时钟频率之间的关系。运行在50MHz且几乎不休眠的系统,当运行在100MHz时将在休眠模式下消耗约50%的时间。调试器中的功耗数据使得开发者能够检验所期望的行为,以及当如果存在与时钟频率的非线性关系时,选择功耗最低的工作频率。 中断处理 图4显示了一个事件驱动系统的功耗示意图,其在t0时处于非激活模式,消耗的电流为I0。在t1时系统被激活且电流上升为I1,对应于系统在激活模式下且有一个外设被使用时的功耗。在t2时,程序的运行被一个更高优先级的中断所挂起。已经被激活的外设没有被关闭,虽然高优先级的线程中并未用到它们。更多的外设被新的线程所激活,导致电流在t2和t3之间升高为I2。在t3时,控制权重又回到低优先级的线程。
图4:显示了一个事件驱动系统的功耗示意图。 该系统的功能可以非常出色,并且能够在运行速度和代码尺寸两方面进行优化。然而在功耗方面,还有更多的优化可以实现。图中黄 色的区域表示如果在t2和t3之间关闭不需要的外设,或者对调这两个线程的优先级,所能够节省的能量。 使用功耗调试,能够更容易地发现当中断发生时功耗的额外上升,并将其标识为异常。
查找有冲突的硬件初始化 为了避免输入端浮动,在通常的设计中会将未使用的MCU I/O管脚接地。如果软件错误地将某个接地管脚配置为输出逻辑“1”,高达25mA的电流会流向该管脚。这种非期望的高电流在功耗采样图形上很容易观测到;同时还可以通过观察系统启动过程中的图形来查找相关的初始化错误代码。 模拟干扰也可能对功耗调试产生影响。模数混合电路板有其自身的特性。板级的布局和走线对于抑制模拟噪声、保证对低电平模拟信号的精确采样十分重要。良好的混合信号电路需要对硬件进行仔细的考量和认真的设计。 总结 功耗调试使得嵌入式系统的开发者能够深入了解他们的应用,并发现程序的代码对功耗有何影响。基于这些信息,可以通过调整和优化源代码以最大限度地降低功耗。使用这种方法,工程师们能够确保他们的设计已经尽可能地节省能量,而又不会对系统性能产生不利的影响。
|