程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> S3C2416睡眠後喚醒的具體細節

S3C2416睡眠後喚醒的具體細節

編輯:C++入門知識

S3C2416睡眠後喚醒的具體細節


〇、引子

書接上回,即:S3C2416睡眠的底層實現。

話說,春夢了無痕,秋鴻有信終需醒。睡醒後的恢復操作以及恢復哪些東西,在s3c_pm_enter(suspend_state_t state)函數的後半部分有具體實現:

arch/arm/plat-samsung/pm.c

static int s3c_pm_enter(suspend_state_t state)
{
	......

	/* restore the system state */

	s3c_pm_restore_core();
	s3c_pm_restore_uarts();
	samsung_pm_restore_gpios();
	s3c_pm_restored_gpios();

	s3c_pm_debug_init();

	/* check what irq (if any) restored the system */

	s3c_pm_arch_show_resume_irqs();

	S3C_PMDBG("%s: post sleep, preparing to return\n", __func__);

	/* LEDs should now be 1110 */
	s3c_pm_debug_smdkled(1 << 1, 0);

	s3c_pm_check_restore();

	/* ok, let's return from sleep */

	S3C_PMDBG("S3C PM Resume (post-restore)\n");
	return 0;
}
這裡一筆帶過。接下來從喚醒源入手,看怎麼把指定的外部中斷或RTC設置為喚醒源,以及,喚醒源是怎麼被內核識別的。


一、插曲:

開始,是從以下兩個全局變了入手的,但最後進入了死胡同,出口渺然無蹤:

unsigned long s3c_irqwake_intmask	= 0xffffffffL;
unsigned long s3c_irqwake_eintmask	= 0xffffffffL;
茫茫然時突然想到,為何不從喚醒源處入手?


二、正文:

以IRQ_EINT0作為喚醒源,添加在smdk_machine_init()函數中:

arch/arm/mach-s3c24xx/common-smdk.c

void __init smdk_machine_init(void)
{
request_irq(IRQ_EINT0, button_irq, IRQ_TYPE_EDGE_FALLING, "BUTTON_IRQ_EINT0", NULL);
enable_irq_wake(IRQ_EINT0);
s3c_pm_init();
}

enable_irq_wake()函數的入參作為喚醒源標號:

include/linux/interrupt.h

static inline intenable_irq_wake(unsigned int irq)
{
return irq_set_irq_wake(irq, 1);
}


irq_set_irq_wake()函數的第二個參數非零,就使能喚醒源IRQ_EINT0:

kernel/irq/manage.c

intirq_set_irq_wake(unsigned int irq, unsigned int on)
{
/* Wakeup mode lets this IRQ wake the system from sleep
* states like "suspend to RAM".
*/
if (on) {
if (desc->wake_depth++ == 0) {
ret = set_irq_wake_real(irq, on);
if (ret)
desc->wake_depth = 0;
else
irqd_set(&desc->irq_data, IRQD_WAKEUP_STATE);
}
}
}

static intset_irq_wake_real(unsigned int irq, unsigned int on)
{
struct irq_desc *desc = irq_to_desc(irq);
int ret = -ENXIO;

if (irq_desc_get_chip(desc)->flags & IRQCHIP_SKIP_SET_WAKE)
return 0;

if (desc->irq_data.chip->irq_set_wake)
ret = desc->irq_data.chip->irq_set_wake(&desc->irq_data, on);

return ret;
}

irq_set_wake是函數指針,原型定義:

int (*irq_set_wake)(struct irq_data *data, unsigned int on);

到了這裡,死胡同由出現了;它指向哪裡?也即功能的實現實在哪裡呢?

這時,先前提到的兩個全局變量s3c_irqwake_intmask、s3c_irqwake_eintmask就“粉墨登場”了,irq_set_wake指向函數s3c_irq_wake()就在這兩個變量的下面:

arch/arm/mach-s3c24xx/irq-pm.c

Linux的源代碼,一定記得使用如下網站:

http://lxr.free-electrons.com/ident?i=


至此,Linux內核對睡眠/喚醒的支持流程分析完畢。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved