s3c2440 省电模式开发详解

发布者:闪耀之星最新更新时间:2020-06-14 来源: eefocus关键字:s3c2440  省电模式  休眠部分 手机看文章 扫描二维码
随时随地手机看文章

1、源码包
Kernel:linux-2.6.18.2
Uboot:u-boot-1.1.4
Gcc:arm-linux-gcc-3.4.1.tar.bz2

 

开发流程及详细步骤
1、休眠部分

1.电源管理守护进程
省略

 

2.内核接口文件(arch/arm/kernel/apm.c)
电源守护进程通过apm.c的ioctl函数来使内核开始进入sleep模式。
case APM_IOC_SUSPEND:
        as->suspend_result = -EINTR;
        if (as->suspend_state == SUSPEND_READ) {
               as->suspend_state = SUSPEND_ACKED;
               suspends_pending--;
        } else {
               queue_event(APM_USER_SUSPEND, as);
        }
        if (suspends_pending == 0)
               apm_suspend(); //由此进入sleep
       调用的顺序如下:


3.进sleep前的准备工作
A.关闭系统进程(kernel/power/ console.c)
int pm_prepare_console(void) //该函数使所有系统进程休眠或关闭。
B.关闭外设驱动电源(drivers/base/power/suspend.c)
int device_power_down(pm_message_t state) //该函数使所有设备驱动sleep

4.进入sleep前的设置(arch/arm/mach-s3c2410/pm.c)
static int s3c2410_pm_enter(suspend_state_t state) //该函数引导进sleep前的设置

static int s3c2410_pm_enter(suspend_state_t state)
{
unsigned long regs_save[16];
unsigned long tmp;

s3c2410_pm_debug_init(); //sleep中uart不能再用,此函数实现uart重新初始化用来调试

DBG("s3c2410_pm_enter(%d)n", state); //打印信息

if (state != PM_SUSPEND_MEM) {
        printk(KERN_ERR PFX "error: only PM_SUSPEND_MEM supportedn");
        return -EINVAL;
} //判断是否是休眠只用ram实现,应为该项目不支持硬盘休眠功能。

if (!any_allowed(s3c_irqwake_intmask, s3c_irqwake_intallow) &&
    !any_allowed(s3c_irqwake_eintmask, s3c_irqwake_eintallow)) {
        printk(KERN_ERR PFX "No sources enabled for wake-up!n");
        printk(KERN_ERR PFX "Aborting sleepn");
        return -EINVAL;
} //判断中断唤醒是否允许,不允许则不能进入休眠。


s3c2410_pm_check_prepare(); //如果需要在sleep前检查ram则此函数会运行,否则此函数为空,即如果CONFIG_S3C2410_PM_CHECK被定义。


s3c2410_sleep_save_phys = virt_to_phys(regs_save);
//将用来保存系统寄存器的数组地址转为物理地址,以供后面调用。
DBG("s3c2410_sleep_save_phys=0x%08lxn", s3c2410_sleep_save_phys); //打印信息
__raw_writel(virt_to_phys(s3c2410_cpu_resume), S3C2410_GSTATUS3);
                             //将系统唤醒时需要调用的函数地址写入GSTATUS3寄存器。
DBG("GSTATUS3 0x%08xn", __raw_readl(S3C2410_GSTATUS3)); //打印信息
DBG("GSTATUS4 0x%08xn", __raw_readl(S3C2410_GSTATUS4)); //打印信息

s3c2410_pm_do_save(gpio_save, ARRAY_SIZE(gpio_save));  //保存io口配置状态
s3c2410_pm_do_save(irq_save, ARRAY_SIZE(irq_save));      //保存中断配置状态
s3c2410_pm_do_save(core_save, ARRAY_SIZE(core_save));  //保存核心配置状态
s3c2410_pm_do_save(uart_save, ARRAY_SIZE(uart_save));    //保存串口配置状态

s3c2410_pm_configure_extint(); //配置外部中断唤醒,使系统休眠中可以按键唤醒

DBG("sleep: irq wakeup masks: %08lx,%08lxn",
    s3c_irqwake_intmask, s3c_irqwake_eintmask); //打印信息

__raw_writel(s3c_irqwake_intmask, S3C2410_INTMSK);        //屏蔽系统定义中断
__raw_writel(s3c_irqwake_eintmask, S3C2410_EINTMASK); //打开外部唤醒中断

__raw_writel(__raw_readl(S3C2410_EINTPEND), S3C2410_EINTPEND);
//通过写已经被申请的位,将中断请求寄存器清空

arm920_flush_kern_cache_all(); //清缓冲区

s3c2410_pm_check_store();//如果需要在sleep前检查ram则此函数会运行,否则此函数为空,即如果CONFIG_S3C2410_PM_CHECK被定义。

__raw_writel(0x00, S3C2410_CLKCON);  //关闭所有外设时钟

s3c2410_cpu_suspend(regs_save); //调用汇编函数s3c2410_cpu_suspend 进入sleep。
/************************************************************************/
上为进入休眠部分,下为唤醒部分。
/************************************************************************/
cpu_init(); //CPU初始化

tmp = __raw_readl(S3C2410_GSTATUS2);
tmp &= S3C2410_GSTATUS2_OFFRESET;
__raw_writel(tmp, S3C2410_GSTATUS2); //清除唤醒复位标记

s3c2410_pm_do_restore_core(core_save, ARRAY_SIZE(core_save)); //恢复核心配置
s3c2410_pm_do_restore(gpio_save, ARRAY_SIZE(gpio_save));       //恢复io口配置
s3c2410_pm_do_restore(irq_save, ARRAY_SIZE(irq_save));            //恢复中断配置
s3c2410_pm_do_restore(uart_save, ARRAY_SIZE(uart_save));         //恢复串口配置

s3c2410_pm_debug_init(); //串口调试函数初始化

DBG("post sleep: IRQs 0x%08x, 0x%08xn",
    __raw_readl(S3C2410_SRCPND),
    __raw_readl(S3C2410_EINTPEND)); //打印信息

s3c2410_pm_show_resume_irqs(IRQ_EINT0, __raw_readl(S3C2410_SRCPND),
                          s3c_irqwake_intmask); //查看中断唤醒源信息
s3c2410_pm_show_resume_irqs(IRQ_EINT4-4, __raw_readl(S3C2410_EINTPEND),
                          s3c_irqwake_eintmask); //查看中断唤醒源信息

DBG("post sleep, preparing to returnn");

s3c2410_pm_check_restore();//如果需要在sleep前检查ram则此函数会运行,否则此函数为空,即如果CONFIG_S3C2410_PM_CHECK被定义。

DBG("S3C2410 PM Resume (post-restore)n");
return 0;
}


5.进休眠前的最后汇编段程序(arch/arm/mach-s3c2410/sleep.s)
ENTRY(s3c2410_cpu_suspend)
stmfd      sp!, { r4 - r12, lr }

@@ store co-processor registers

mrc p15, 0, r4, c15, c1, 0     @ CP access register
mrc p15, 0, r5, c13, c0, 0     @ PID
mrc p15, 0, r6, c3, c0, 0       @ Domain ID
mrc p15, 0, r7, c2, c0, 0       @ translation table base address
mrc p15, 0, r8, c1, c0, 0       @ control register

stmia       r0, { r4 - r13 }

@@ flush the caches to ensure everything is back out to
@@ SDRAM before the core powers down

#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
bl    arm920_flush_kern_cache_all
#endif

@@ prepare cpu to sleep

ldr   r4, =S3C2410_REFRESH
ldr   r5, =S3C24XX_MISCCR
ldr   r6, =S3C2410_CLKCON
ldr   r7, [ r4 ]         @ get REFRESH (and ensure in TLB)
ldr   r8, [ r5 ]         @ get MISCCR (and ensure in TLB)
ldr   r9, [ r6 ]         @ get CLKCON (and ensure in TLB)

orr   r7, r7, #S3C2410_REFRESH_SELF    @ SDRAM sleep command
orr   r8, r8, #(S3C2410_MISCCR_USBSUSPND0 | S3C2410_MISCCR_USBSUSPND1) @suspend usb
orr   r8, r8, #(S3C2400_MISCCR_SPUCR_LDIS | S3C2400_MISCCR_SPUCR_HDIS) @suspend d(0-31)
orr   r8, r8, #S3C2410_MISCCR_SDSLEEP @ SDRAM power-down signals
orr   r9, r9, #S3C2410_CLKCON_POWER    @ power down command

teq   pc, #0                   @ first as a trial-run to load cache
bl    s3c2410_do_sleep
teq   r0, r0                    @ now do it for real
b     s3c2410_do_sleep   @

@@ align next bit of code to cache line
.align      8
s3c2410_do_sleep:
streq       r7, [ r4 ]                @ SDRAM sleep command
    mov r0, #0x1000

1: subs r0, r0, #1          @wait until the SelfRefresh is released
    bne 1b
streq       r8, [ r5 ]                @ SDRAM power-down config
streq       r9, [ r6 ]                @ CPU sleep
1:     beq 1b
mov pc, r14


2、唤醒部分
1、Uboot部分(u-boot-1.1.4/cpu/arm920t/start.s)
reset:
#if 0
mrs r0, cpsr      /* Set the cpu to SVC32 mode */
bic   r0, r0, #0x1f
orr   r0, r0, #0xd3
msr cpsr, r0
#endif

/* disable watchdog timer */
mov r0, #WTCON_BASE
ldr r1, =0x0
str r1, [r0, #oWTCON]
/*
* mask all IRQs by setting all bits in the INTMR - default
*/
mov r0, #INT_BASE
ldr   r1, =0xffffffff
str    r1, [r0, #oINTMSK]

ldr   r1, =0x7ff
str    r1, [r0, #oINTSUBMSK]

mov r0, #CLK_BASE
ldr r1, =0xffffffff
str r1, [r0, #oLOCKTIME]

/* FCLK:HCLK:PCLK */
ldr r1, =0x0
str r1, [r0, #oCAMDIVN]

ldr r1, =_clkdivn
str r1, [r0, #oCLKDIVN]

mrc p15, 0, r1, c1, c0, 0           /* read ctrl register */
orr r1, r1, #0xc0000000           /* Asynchronous */
mcr p15, 0, r1, c1, c0, 0           /* write ctrl register */

/* UPLL setup */
ldr r1, =_upllcon
str r1, [r0, #oUPLLCON]

nop
nop
nop         /* wait until upll has the effect */
nop
nop

/* PLL setup */
ldr r1, =_mpllcon
str r1, [r0, #oMPLLCON]
/* configure memory */
bl    memset
/* Power Manage  Check if this is a wake-up from sleep */
ldr r1, PMST_ADDR
ldr r0, [r1]
@bic r0,r0,#0xfffffffd
tst r0, #(0x02)
bne WakeupStart
WakeupStart:
    /* Clear sleep reset bit */   
    ldr r0, PMST_ADDR
    mov r1, #0x0       @PMST_SMR
    str r1, [r0]
  
    ldr r0, PMCTL1_ADDR  /* Release the SDRAM signal protections */
    ldr r1, =0x00010330
   str r1, [r0]
   
    ldr r0, =0x48000024
    ldr r1, [r0]
    bic r1, r1, #0x400000
    str r1, [r0]
     
   mov r1, #0x1000
1: subs r1, r1, #1 /* wait until the SelfRefresh is released. */
    bne 1b
   
    /* Go... */  
    ldr r0, =0x560000B8 /* read a return address  go to s3c2410_cpu_resume*/
    ldr r1, [r0]
      
    mov pc, r1
    nop
    nop
1: b   1b      /* infinite loop */

[1] [2]
关键字:s3c2440  省电模式  休眠部分 引用地址:s3c2440 省电模式开发详解

上一篇:基于S3C2440的UART传输小结
下一篇:s3c2440串口接收中断(OK2440III)

推荐阅读最新更新时间:2024-11-09 13:27

s3c2440代码重定位和段的引入——学以致用,综合Makefile的锻炼
对于2440而言,nand启动,nand的前4k内容由硬件复制到sram。 nor flash,可以像内存一样读,但是不能像内存一样写,执行写操作需要特殊的操作。 程序中包含有需要写的全局或者静态变量,它们在bin文件中,写在nor flash上,直接修改这样的变量是无效的。 到底什么意思呢?还是看例子比较有说服力。 在学习C语言的过程中,我们或多或少知道一些东西,c/c++可执行文件需要预处理,编译,汇编,连接。 程序有text段,data段,bss段,rodata段等等,今天,就和它们来个亲密接触吧。 还是先说上面的问题吧,看例子: 在之前的程序代码基础上,启动代码增加自动识别是nand还是nor启
[单片机]
<font color='red'>s3c2440</font>代码重定位和段的引入——学以致用,综合Makefile的锻炼
s3c2440中PWM应用
s3c2440芯片中一共有5个16位的定时器,其中有4个定时器(定时器0~定时器3)具有脉宽调制功能,因此用s3c2440可以很容易地实现PWM功能。下面就具体介绍如何实现PWM功能。 1、PWM是通过引脚TOUT0~TOUT3输出的,而这4个引脚是与GPB0~GPB3复用的,因此要实现PWM功能首先要把相应的引脚配置成TOUT输出。 2、再设置定时器的输出时钟频率,它是以PCLK为基准,再除以用寄存器TCFG0配置的prescaler参数,和用寄存器TCFG1配置的divider参数。 3、然后设置脉冲的具体宽度,它的基本原理是通过寄存器TCNTBn来对寄存器TCNTn(内部寄存器)进行配置计数,TCNTn是递减的,如果减到零,
[单片机]
S3C2440C语言点灯
S3C2440芯片手册导读 对于GPFCON,只用到了16位 对于GPFDAT,只用到了8位 我们仍然可以以32位,就是4字节的形式来访问这些寄存器 对于GPFCON,我们只关心低16位 对于GPFDAT,我们只关心低8位 其他不需要用到的位,我们不写入值,或者写入0值 用指针表示 我们用4字节去访问这两个寄存器 可以用int变量去表示 注意: 对int变量,最高位是表示符号位 对寄存器,最高位仍然是控制硬件 所以,我们用unsigned int来表示 unsigned int *pGPFCON = 0x56000050; unsigned int *pGPFDAT = 0x56000054; 在内存中的存
[单片机]
S3C2440C语言点灯
s3c2440】第四课:外部中断
外部中断初始化流程 外部中断的流程图如下: 此处不考虑中断优先级,涉及的寄存器如下: 外部中断配置 一、初始化中断 将系统的模式(MODE)从SVC(supervise)模式设置位USER模式。将M4~M0设置为b10000即可。 CPSR寄存器详细描述: 各种模式下M4~M0的值: 打开中断总开关。CPSR中的第6位表示中断总开关。当I等于0时,irq中断使能。 初始化外部中断,中断控制器中的INTMSK寄存器可以屏蔽各种中断,需要解除外部中断的屏蔽。INTMSK的默认值为0xFFFFFFFF。0表示使能中断,1表示屏蔽中断。 INTMSK寄存器详细信息: INTMOD设置中断模式:0: IRQ MOD
[单片机]
【<font color='red'>s3c2440</font>】第四课:外部中断
2440串口linux编程,S3C2440串口通讯的相关配置
UART配置的相关寄存器如下(按s3c2440手册中的顺序列出): 1.ULCONn寄存器:线性控制寄存器 功能:设置奇偶校验,停止位, 数据位(5-8位) 注意:一般设置为无校验,一个停止位,数据位为8位,也就是常说的“8N1”,此时寄存器值为0x3。(bit =0为正常模式,否则为红外模式); 2.UCONn寄存器:通道n控制器 功能:选择UART时钟源、设置UART中断方式 注意:可选择PCLK、UEXTCLK或FCLK/n。bit =1为回送模式,用于测试;bit 和bit 分别控制传输和接收模式,初学者常设置为中断请求或查询模式,bit =bit =01。 3.UFCONn寄存器:FIFO控制寄存器 功能:用于设
[单片机]
基于S3C2440的DM9000网卡驱动的移植
0 引言   以太网(Ethernet)是一种计算机局域网组网技术。在局域网中,多个节点是共享传输介质的,这就必须由某种机制来决定某个时刻哪个设备占用传输介质来传输数据,因此,局域网的链路层要有介质访问控制的功能,即数据链路层分为逻辑链路控制LLC子层和介质访问控制MAC子层 。   本文主要研究基于S3C2440的DM9000网卡驱动的移植。网络对于嵌入式系统来说是必不可少的,但是S3C2440没有集成以太网接口,所以要想使S3C2440具备以太网的功能,就必须扩展网卡接口。本文选择外接DM9000,使其可以与以太网相连接,并完成DM9000网卡驱动的移植。 1 Linux网络驱动层次   Linux网络驱动可以划分为4层,
[单片机]
U-boot在S3C2440上的移植详解(五)
一、移植环境 主 机:VMWare--Fedora 9 开发板:Mini2440--64MB Nand,Kernel:2.6.30.4 编译器:arm-linux-gcc-4.3.2.tgz u-boot:u-boot-2009.08.tar.bz2 二、移植步骤 9)实现u-boot对yaffs/yaffs2文件系统下载的支持。 注意:此篇对Nand的操作是基于MTD架构方式,在“u-boot-2009.08在2440上的移植详解(三)”中讲到过。 通常一个Nnad Flash存储设备由若干块组成,1个块由若干页组成。一般128MB以下容量的Nand Flash芯片,一页大小为528B,被依次分为2
[单片机]
U-boot在<font color='red'>S3C2440</font>上的移植详解(五)
S3C2440 音频解码芯片WM8976声卡驱动移植、madplay测试
1. WM9876接口和工作原理 本节使用了JZ2440开发板移植WM9876驱动,其结构如下图所示,最后利用madplay工具测试音频文件。 IIS和控制接口; WM9876声卡是负责录音、播音、调节音量和声音合成等的一种多媒体板卡。包括两种接口:IIS接口(提供音频接收和发送)、控制接口(控制音量大小,使能各个输出通道等) 1)当我们播放声音时,将数字信号传入I2SDO脚,声卡便通过解码,产生模拟信号到喇叭/耳机; 2)当我们录音时,声卡便获取麦克风的模拟信号,编码出数字信号到I2SDI引脚上。 ----------- 接口说明 ---------------- ----------- 接口说明
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
随便看看

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved