日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

Linux下LCD 10分钟自动关屏的问题总结

發布時間:2024/9/5 linux 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux下LCD 10分钟自动关屏的问题总结 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

記錄一下,防止博客丟失。來自:http://blog.csdn.net/mao0514/article/details/46562057

Linux下的LCD驅動默認10分鐘后會自動關閉屏幕,我們可以修改一下代碼讓其不自動關屏

在有一個 drivers/char/vt.c 文件其中有一個變量(blankinterval)可以設置它來修改自動關屏的時間,也可以在函數(blank_screen_t)開頭直接返回,這樣就永遠不會關屏了


? 在用LCD顯示的時候,發現10分鐘LCD就不再工作了。確實,Linux下有一個參數blankinterval的值就是10*60*Hz。

它決定了LCD只顯示10分鐘,然后LCD控制器就被關掉了。

具體細節請參考http://blog.csdn.net/dongliqiang2006/article/details/4262950

但是這篇文章最后給出的程序是不能用的,有一處錯誤,在write那行應該是\0,原文是/0。

#include <fcntl.h>
#include <stdio.h>
#include <sys/ioctl.h>
int main(int argc ,char *argv[])
{
?int f0;
?f0 = open("/dev/tty0", O_RDWR);
?write(f0, "\033[9;0]", 8);
?close(f0);
?return 0;
}

1.程序存為display_time.c 2 交叉編譯 arm-linux-gcc -o?display_time ?display_time.c 3.display_time復制到根目錄下 4 運行 ?./display_time 如果要開機自動啟動,復制到根目錄后,在/etc/init.d/rcS里加上一句 ?/display_time 。 原理請看下一篇博文Linux驅動和應用程序的開機自啟動。


Linux啟動之后,只要一段時間不動鍵盤(開發板上用IO擴展出來的鍵盤),LCD就會自動關閉(黑屏、顯示慢慢消失之類),只要按下鍵盤就能恢復。 這個問題讓我花了一天多的時間。其實如果是手持設備,這樣也沒有什么。但是我們公司的產品是要一直顯示東西的,必須解決這個問題。我看了很多論 壇,有不少人也遇到了這個問題,但是我剛才是搜索的時候,關鍵詞不對,總找不到正確的答案。如果你遇到了同樣的問題,而且不想看我的三腳貓分析,那么就在 百度上搜索“blankinterval”、“setterm -blank 0”之類的,馬上你就能找到簡單的解決方案。 這個問題很容易讓人想到屏幕保護和電源管理。的確,這是一種電源管理。但是,你卻無法從Linux內核選項的電源管理中解決這個問題。我們一步步來。 首先,我測量到LCD的PCLK時鐘消失了,這意味著內核把LCD控制器關掉了。于是,從LCD驅動程序著手。我用的是S3C2440,這是 2410的升級版,但是LCD控制器是一樣的,在我拿到的開發板廠商給我做好驅動的內核里,驅動的位置在/drivers/video /s3c2410fb.c。為什么后面有個fb呢?這是Framebuffer的縮寫,百度下你能找到很多關于它的解釋。Framebuffer是所有 Linux下GUI程序對硬件操作的設備接口,位于/dev中,一般為fb0。在s3c2410fb.c中可以找到一個類似 s3c2410_disable_controller()這樣名稱的函數,我的驅動里叫pxafb_disable_controller(),可以看 出這個驅動是從pxa處理器改的,當然廠家不一樣名字也叫得不一樣。里面有一句類似這樣寫的 __raw_writel(fbi->reg.lcdcon1 & ~S3C2410_LCDCON1_ENVID, S3C2410_LCDCON1);,把這句話刪掉LCD就不會關掉了。這是第一個層次,我也看到有人是這樣做的。但是,這有問題,按鍵盤恢復后,原本顯 示在屏幕上的東西如果你不重畫會消失,就算你重畫了,也會看到屏幕的某些部分先黑了下,然后恢復了。當然如果你可以接受,那么就這樣吧。 然后,可以很自然的想到是誰調用了這個函數,從源頭把這個問題消除掉。但是情況卻不是這樣的。我搜索這個函數名,找到了一個 set_ctrlr_state()的函數調用了pxafb_disable_controller(),搜索set_ctrlr_state(),發現 有個pxafb_task()調用了set_ctrlr_state(),但是到了pxafb_task()就沒有辦法再往上找了,因為這是提供給內核的 一個任務,以指針傳遞函數入口。我對內核了解太不夠了,花了很多時間看了很多論壇上的文章,機緣巧合之下,我找到了/drivers/char/vt.c 這個文件。vt.c我感覺應該是2.4內核的console.c和vt.c的結合體,應為它集成了console基本上所有功能函數,就ioctl在 vt_ioctl.c這個文件里。這個文件的主要作用是負責管理控制臺,如控制臺的模式(圖形、字符)、向控制臺輸出等等。其中能找到一些如 do_blank_screen(),blank_screen_t()這樣的函數,就是這些函數關閉了LCD控制器,修改任意一個都可以起作用。網上的 一個解決方案是把blank_screen_t()變成空函數,但是我沒有這樣試過,我覺得已經來到了問題的根源附近,應該能從根本上解決。 我們先看下屏幕關閉問題的真正起因,看這個控制臺初始化函數 static int __init con_init(void)
{
?const char *display_desc = NULL;
?struct vc_data *vc;
?unsigned int currcons = 0; acquire_console_sem(); if (conswitchp)
??display_desc = conswitchp->con_startup();
?if (!display_desc) {
??fg_console = 0;
??release_console_sem();
??return 0;
?} ?init_timer(&console_timer);
?console_timer.function = blank_screen_t;
?
?if (blankinterval) {
??blank_state = blank_normal_wait;
??mod_timer(&console_timer, jiffies + blankinterval);
?}
// 這是對控制臺定時器的初始化,定時器事件函數被連接到了blank_screen_t() /*
? * kmalloc is not running yet - we use the bootmem allocator.
? */
?for (currcons = 0; currcons < MIN_NR_CONSOLES; currcons++) {
??vc_cons[currcons].d = vc = alloc_bootmem(sizeof(struct vc_data));
??visual_init(vc, currcons, 1);
??vc->vc_screenbuf = (unsigned short *)alloc_bootmem(vc->vc_screenbuf_size);
??vc->vc_kmalloced = 0;
??vc_init(vc, vc->vc_rows, vc->vc_cols,
???currcons || !vc->vc_sw->con_save_screen);
?}
?currcons = fg_console = 0;
?master_display_fg = vc = vc_cons[currcons].d;
?set_origin(vc);
?save_screen(vc);
?gotoxy(vc, vc->vc_x, vc->vc_y);
?csi_J(vc, 0);
?update_screen(vc);
?printk("Console: %s %s %dx%d",
??vc->vc_can_do_color ? "colour" : "mono",
??display_desc, vc->vc_cols, vc->vc_rows);
?printable = 1;
?printk("/n"); release_console_sem(); #ifdef CONFIG_VT_CONSOLE
?register_console(&vt_console_driver);
#endif
?return 0;
}
其中引用了一個叫blankinterval的全局變量和一個console_time,我不知道內核的定時器是具體是怎么工作,但是 這樣的代碼已經很明顯了。這個定時器和電源管理宏PM_CONFIG沒有任何關系,它是控制臺的一部分。再看下blank_screen_t(): static void blank_screen_t(unsigned long dummy)
{
?blank_timer_expired = 1;
?schedule_work(&console_work);
} 可以發現vt.c開頭的宏,static DECLARE_WORK(console_work, console_callback, NULL);,找到了console_callback()這個函數: static void console_callback(void *ignored)
{
?acquire_console_sem(); if (want_console >= 0) {
??if (want_console != fg_console &&
????? vc_cons_allocated(want_console)) {
???hide_cursor(vc_cons[fg_console].d);
???change_console(vc_cons[want_console].d);
???/* we only changed when the console had already
????? been allocated - a new console is not created
????? in an interrupt routine */
??}
??want_console = -1;
?}
?if (do_poke_blanked_console) { /* do not unblank for a LED change */
??do_poke_blanked_console = 0;
??poke_blanked_console();
?}
?if (scrollback_delta) {
??struct vc_data *vc = vc_cons[fg_console].d;
??clear_selection();
??if (vc->vc_mode == KD_TEXT)
???vc->vc_sw->con_scrolldelta(vc, scrollback_delta);
??scrollback_delta = 0;
?}
?if (blank_timer_expired) {
??do_blank_screen(0);
??blank_timer_expired = 0;
?}
release_console_sem();
} 再看do_blank_screen(),隨著struct vc_data中的與fops類似指針跟蹤下去,就可以找到驅動里面的相應代碼了。寫出來太麻煩,讓我偷懶把。 小總結下,其實在控制臺內部就有一個定時器,它負責在一定時間之后將顯示關閉,而無視是否打開了電源管理功能。那這和Framebuffer有什么關系呢?我從一個很弱智的角度解釋,內核剛啟動的時候有這樣一句輸出: Console: colour dummy device 80x30 在初始化LCD控制器(Framebuffer)之后,有這樣一句輸出: Console: switching to colour frame buffer device 80x30 我就理解:這時候,內核把控制臺(也不知道是console還是tty)切換到了Framebuffer上,大蝦們趕快跳出來批判我吧,呵呵。 回到正題,從代碼可以發現,根本的解決之道是讓blankinterval = 0,blank_state就不會是blank_off之外的值,也就不會關閉屏幕了。 但是問題到這里還是沒有完全解決,如果用戶程序希望改變blankinterval來實現屏保(當然在我的系統上用不著);另外,一些程序改變 了blankinterval,程序退出之后,屏幕在一段時間之后還是會關閉的。怎么才能在用戶程序那頭解決這個問題呢,這又耗費了我很多時間。 我在追查代碼的過程中走了個彎路,認為修改控制臺的模式可以不讓黑屏現象出現,但是后來發現,這樣可能會使控制臺沒有辦法畫圖,不知道對不對。 忽略彎路,直接正解。vt.c中不是有很多操作控制臺的函數么?看看是誰修改了blankinterval。于是搜索 blankinterval,發現setterm_command()修改了它,然后搜索setterm_command,找到了 do_con_trol()函數,搜索do_con_trol,找到了do_con_write()函數,搜索do_con_write,終于最終 BOSS現身了:con_write()函數。為什么說它是最終BOSS呢?看看這段: static struct tty_operations con_ops = {
?.open = con_open,
?.close = con_close,
?.write = con_write,
?.write_room = con_write_room,
?.put_char = con_put_char,
?.flush_chars = con_flush_chars,
?.chars_in_buffer = con_chars_in_buffer,
?.ioctl = vt_ioctl,
?.stop = con_stop,
?.start = con_start,
?.throttle = con_throttle,
?.unthrottle = con_unthrottle,
}; 熟悉fops的話你就能看出來了,這是對tty設備的文件操作函數的表。也就是說,在用戶程序里,通過open函數打開/dev/tty,然后 再用write函數就可以修改blankinterval了。原理是找到了,實踐上有很大困難,那么多重函數調用,再看看do_con_trol()里面 的switch語句,正常人都要發暈。好在偉大的百度為我們提供了很多信息:在命令行下,可以使用setterm -blank 0指令來設置blankinterval。哈哈,救星來了,趕快看看setterm的源代碼。setterm屬于util-linux包,搜索一下很容易 找到。其中的perform_sequence()函數里有這樣一段: /* -blank [0-60]. */
?if (opt_blank && vcterm)?
??printf("/033[9;%d]", opt_bl_min); 真得很神奇啊,用個printf就可以在用戶程序里解決這個問題,本來我是打算只說用printf解決的,看到原理我想會更舒服一些;況且,在我的系統上用printf是不行的。 但是!問題還沒有完,往往在我們的系統中,LCD的虛擬控制臺和控制臺TTY不是同一個設備,也就是說,如果在程序里單純的printf是不行的!這樣只能修改你正在使用的TTY的blankinterval,而你用的卻是文本方式的設備,不存在黑屏問題。 于是,就需要仔細比較/dev/console、/dev/tty、/dev/ttyn的設備號,在我的系統里,用戶程序里/dev /console和/dev/tty都是5,說明他們是一個東西,/dev/ttyn是4,這才是FB上的虛擬控制臺。但是/dev/ttyn不是正在使 用的TTY,那么怎么printf呢?只好用write函數來解決了。 寫這樣一段代碼: #include <fcntl.h> #include <stdio.h> #include <sys/ioctl.h> void some_function() { int f; f = open("/dev/tty0", O_RDWR); write(f, "/033[9;0]", 8); close(f); } 問題終于解決了。 總結下,第二個問題有很多種解決方法: 1.修改LCD驅動,把關閉LCD控制器的函數變為空(不推薦) 2.修改vt.c中的blank_screen_t()函數,讓其為空(在系統不需要使用關閉顯示功能時推薦) 3.修改vt.c中的blankinterval,讓其為0(系統可能需要使用關閉顯示功能,而且希望系統上電后正常狀態下不會關閉顯示時推薦) 4.修改用戶程序,加入設置blankinterval的代碼(推薦)

還可以這樣:echo 0 > /sys/class/graphics/fb0/blank,可以修改為不息屏。非0情況就可以息屏,或者不刷新屏幕了。




與50位技術專家面對面20年技術見證,附贈技術全景圖

總結

以上是生活随笔為你收集整理的Linux下LCD 10分钟自动关屏的问题总结的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。