基于SEP0611的电源管理驱动设计方案

基于SEP0611的电源管理驱动设计方案,第1张

  摘要:休眠模式是减少嵌入式系统功率消耗的一种运行模式。一般来说,系统处于休眠模式时,不执行任何功能,在一定时期内没有用户请求产生,因此它可以最大限度地减少其不必要的功耗。在文章中,硬件平台采用东南大学自主研发的SEP0611嵌入式微处理器,软件平台采用Linux2.6.32内核,设计并实现了电源管理驱动。在SEP0611电源管理驱动中,使系统进入休眠模式的代码负责保存芯片状态、自刷新DDR;使系统退出休眠模式的代码负责使得DDR退出自刷新状态、恢复芯片状态,以使系统返回正常模式。通过在测试板上让系统进入休眠并唤醒系统、同时测试系统休眠前后各路电路电流值,从而验证了该驱动的准确性。

  0 引言

  系统休眠是嵌入式系统除关机外最省电的一种状态。休眠(Suspend, STR (Suspend To RAM )) ,又称为挂起或者挂起到内存,会将目前的运行状态数据存放在内存,并关闭硬盘、外设等设备,进入等待状态,此时除了内存仍然需要电力维持其数据,整机其余部分耗电很少。

  恢复时处理器从内存读出数据,回到挂起前的状态,恢复速度较快。一般在电池无故障且充满电的情况下可以维持这种状态数天之久。

  1 SEP0611和电源管理单元硬件设计

  SEP0611是东南大学自主研发的一款基于UniCore32内核的32位高性能、低功耗RISC微处理器,是定位于手持播放设备、卫星导航产品的高性能处理器。主要分为五个部分:系统与时钟控制、外设接口、多媒体系统、GPS系统和存储系统。系统与时钟控制部分包含了电源管理单元(Power Management Unit, PMU)的设计。

  PMU包括时钟控制和功耗控制两部分。功耗控制主要负责在各个工作模式下的切换,进入低功耗模式后的唤醒,以及系统的复位控制。系统工作模式主要分为三种:正常工作模式、挂起模式、休眠模式。

  2 Linux APM技术

  基于SEP0611的电源管理驱动设计方案,图1 Linux APM技术架构图,第2张

  图1 Linux APM技术架构图

  图1是APM技术在Linux中的架构图。用户通过用户态的APM接口或策略向BIOS申请休眠请求,BIOS设备接收到用户层的休眠请求后会调用内核低功耗层的接口函数,从而实现系统进入休眠的一系列 *** 作;在接收到唤醒信号后内核低功耗层会执行唤醒 *** 作,与此同时低功耗层也会调用外设驱动的电源管理接口让设备跟随系统实现唤醒。SEP0611无BIOS,系统唤醒后会回到bootloader执行。

  3 系统休眠的内核层分析与驱动设计

  Linux系统休眠内核层是整个休眠部分的核心。它将接受上层休眠命令,并通过驱动层使外围设备进入相应的suspend状态等,在得到唤醒信号后将恢复状态继续运行。它包括了体系结构无关的部分:当前进程的冻结/释放,管理外围驱动;也包括了体系结构相关的部分:让处理器进入/退出休眠,DDR进入自刷新指令序列,系统状态保存/恢复等。本小节由休眠准备,休眠进入和休眠退出,完成唤醒三部分组成。

  3.1 休眠准备

  在本文中,将suspend_prepare函数、suspend_devices_and_enter函数中的大部分内容划分为休眠准备部分。

  suspend_prepare函数的主要作用如下:

  (1) 用一个全局变量保存好控制台。

  (2) 执行pm_noTIfier_call_chain函数,该函数调用noTIfier_call_chain函数来通知事件(将休眠)的到达。

  (3) 冻结进程,这通过freeze_processses函数实现。

  在suspend_devices_and_enter函数中执行剩余的休眠准备工作:

  (1) 调用suspend_ops-》begin.

  (2) 调用suspend_cONsole函数获取控制台信号量以休眠控制台。

  (3) 调用dpm_suspend_start函数,该函数分为两步。

  首先调用device_prepare,该设备准备函数通常无 *** 作;然后调用device_suspend函数,使设备驱动进入休眠模式。

  在该函数中,系统会遍历dpm_acTIve链表,为该链表上的每个驱动调用suspend函数(该函数负责挂起设备驱动),正常返回后会将其移至dpm_off链表队列。至此,已完成休眠准备部分的工作。下面以音频驱动为例展示设备驱动suspend函数的填写(函数头略):

  int i;

  volaTIle unsigned long *p_regs = i2s_info.base;

  i2s_regs = kmalloc((I2S_PM_REGS_NUM 《 2),

  GFP_KERNEL);

  if(i2s_regs == NULL)

  return -ENOMEM;

  for(i=0; i《I2S_PM_REGS_NUM; i++)

  i2s_regs[i] = *p_regs++;

  clk_disable(i2s_info.clk);

  return 0;

  这段代码主要实现:保存音频设备硬件寄存器;禁止音频设备时钟。

  3.2 休眠进入和休眠退出

  完成了进入休眠的准备工作,接下来就是进入休眠。

  suspend_enter是休眠进入函数,该函数将调用suspend_ops-》enter(state),调用该函数即是调用SEP0611驱动接口函数sep_pm_enter;该接口函数在sep_pm.c中实现。该文件将保存在CPU寄存器,将休眠代码搬运到sram中,然后系统在sram中执行休眠代码,先让DDR进入自刷新状态,而后处理器进入sleep模式。当系统处于休眠模式时,一旦接收到唤醒事件的中断,如内部的RTC ALARM中断或者外部的Wakeup按键信号才能够让系统退出休眠,即唤醒系统。综上,进入/退出休眠的代码流程图如图2所示。

  基于SEP0611的电源管理驱动设计方案,图2 进入/退出sleep模式的代码流图,第3张

  图2 进入/退出sleep模式的代码流图

  在图2中的休眠进入部分,保存CPU各模式状态之后,跳转到sram执行DDR2的自刷新和休眠的进入,而这段代码(DDR2的自刷新和休眠的进入)此前已由copy_func_to_sram函数搬运至sram中;而跳转通过将sram的物理地址静态映射到linux内核(在对应架构的mm.c中)实现。

  此后,系统处于休眠(sleep)模式,直至唤醒信号的到来。

  SEP0611中可用的唤醒信号有:电源键、RTC的ALARM中断、外部GPIO(AO)口。一旦唤醒信号到来,即是该执行休眠退出部分了。PMU硬件部分将让系统重新上电,而软件则回到bootloader部分执行,在bootloader中有一段分支代码,该部分代码判断是一次正常启动还是一次从休眠的唤醒,若是后者,则恢复CPU各模式状态,此后回到linux *** 作系统。需要说明的是,在进入休眠部分的保存CPU各模式状态之前,PC值(用于返回的地址,实际保存的是PC值加上0x10(合4条指令))已经被保存到一个硬件寄存器中;因此,在退出休眠部分的恢复CPU各模式状态之后,将PC值从硬件寄存器取出,通过其使程序回到linux *** 作系统执行。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/dianzi/2687860.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-08-15
下一篇 2022-08-15

发表评论

登录后才能评论

评论列表(0条)

保存