在好多實(shí)時(shí)操作系統(tǒng)中,并沒(méi)有dpm這個(gè)框架,所以我們可以仿照linux的dpm框架,來(lái)實(shí)現(xiàn)我們自己的dpm,可以運(yùn)用到需要dpm的系統(tǒng)中。
為便于描述,本文使用偽代碼,僅個(gè)別地方具體實(shí)現(xiàn);
1、首先,我們需要定義兩個(gè)結(jié)構(gòu)體類(lèi)型,一個(gè)用于控制,一個(gè)用于各個(gè)模塊注冊(cè);
(1)控制結(jié)構(gòu)體
struct my_dpm{
list_head??? dpm_list;
list_head??? prepare_list;
list_head???early_list;
list_head??? suspend_list;
list_head??? late_list;
spinlock_t????? lock_mutx;
}dpm_ctrl;
(2)各模塊注冊(cè)dpm使用的結(jié)構(gòu)體
struct dpm_device{
char *device_name;
list_head???? entry;
void *data;
int ?(*prepare)(struct dpm_device *dev);
int ?(*suspend_early)(struct dpm_device *dev);
int (*suspend)(struct dpm_device *dev);
int (*suspend_late)(struct dpm_device *dev);
int ?(*resume_early)(struct dpm_device *dev);
int ?(*resume)(struct dpm_device *dev);
int? (*resume_late)(struct dpm_device *dev);
int ?(*complete)(struct dpm_device *dev);
};
2、OK,結(jié)構(gòu)體我們已經(jīng)定義完了,那么我們接下來(lái)需要初始化一下控制結(jié)構(gòu)體的變量
int? my_dpm_init(void){
初始化五個(gè)鏈表;
初始化spin_lock鎖;
return OK;
}
3、到此,我們自己的dpm已初始化完成,各個(gè)模塊想要注冊(cè)dpm,就差一個(gè)注冊(cè)接口了,下面我們來(lái)實(shí)現(xiàn)注冊(cè)接口
int dpm_register(struct dpm_device *device
獲取互斥鎖;
初始化設(shè)備結(jié)構(gòu)體中的entry;
加入到dpm_list鏈表中;
釋放互斥鎖;
return OK;
}
4、這樣,用戶(hù)就可以調(diào)用dpm_register來(lái)注冊(cè)dpm了;但是注冊(cè)完后,得需要提供接口來(lái)供低功耗流程來(lái)調(diào)用啊,莫急,我們這就來(lái)實(shí)現(xiàn)供低功耗調(diào)用的接口,??? dpm_suspend和dpm_resume
(1)dpm_suspend:主要回調(diào)各個(gè)模塊注冊(cè)的保存信息的回調(diào)函數(shù),包括prepare、suspend_early、suspend、suspend_late
int dpm_suspend(void){
if(prepare())
return -1;
if(suspend_early())
return -1;
if(suspend())
return -1;
if(suspend_late())
return -1;
return 0;
}
(2)dpm_resume:主要用在喚醒階段,按照優(yōu)先級(jí)回調(diào)各個(gè)模塊注冊(cè)的恢復(fù)信息的回調(diào)函數(shù),包括resume_early、resume、resume_late、complete
int dpm_resume(void)
{
if(resume_early())
return -1;
if(resume())
return -1;
if(resume_late())
return -1;
if(complete())
return -1;
return 0;
}
5、大家可以看到,上面兩個(gè)接口中分別調(diào)用了4個(gè)函數(shù),供8個(gè)函數(shù),分別用在suspend階段和resume階段,接下來(lái)我們簡(jiǎn)單實(shí)現(xiàn)一下其中一個(gè)函數(shù)prepare
int prepare(void)
{
獲取互斥鎖;
遍歷dpm_list鏈表,檢查每個(gè)結(jié)點(diǎn)是否注冊(cè)prepare回調(diào)函數(shù),如果注冊(cè),則執(zhí)行回調(diào)函數(shù):ret=dev->prepare(dev),如果成功,則移入prepare_list,否則,執(zhí)行恢復(fù)操作;
釋放互斥鎖;
}
其他的suspend_early()、suspend()、suspend_late()、resume()、resume_early()、resume_late()、complete()等具體函數(shù)實(shí)現(xiàn)基本大致相同,只不過(guò)所操作的鏈表不同罷了。
好了,我們的dpm框架實(shí)現(xiàn)完成了,簡(jiǎn)單吧,我們嘗試注冊(cè)一個(gè)吧:
int my_prepare(struct dpm_device *dev){}
int my_suspend dpm_device *dev){}
int my_resumet dpm_device *dev){}
int my_completedpm_device *dev){}
struct dpm_device test_device={
.device_name = "my_test_device";
.prepare = my_prepare;
.suspend = mysuspend;
.resume = my_resume;
.omplete = my_complete;
};
在合適的地方調(diào)用dpm_register(&test_device)即可,需要注意的是,dpm回調(diào)函數(shù)注冊(cè)一定要配對(duì):prepare--complete?????? suspend--resume??????? suspend_late--resume_early??????????????? suspend_late--resume_early
?
評(píng)論
查看更多