最近在调试使用RGB接口的LCD显示屏的时候,发现有花屏的现象。
想到两个方案:
1、延迟背光的使能。
2、还是尽快打开背光,但是在LCD显示屏驱动里面做处理:即ret = fb_register_client(&nb)。
我们先不讨论第二个方案。
第一个方案客户是可以接受的。
原本背光在是在:
static int __init mxc_init_fb(void)
{
if (!machine_is_mx53_smd())
return 0;
// primary_di=0;
if (primary_di) {
printk(KERN_INFO "DI1 is primary\n");
/* DI1 -> DP-BG channel: */
mxc_fb_devices[1].num_resources = ARRAY_SIZE(mxcfb_resources);
mxc_fb_devices[1].resource = mxcfb_resources;
mxc_register_device(&mxc_fb_devices[1], &fb_data[1]);
/* DI0 -> DC channel: */
mxc_register_device(&mxc_fb_devices[0], &fb_data[0]);
} else {
printk(KERN_INFO "DI0 is primary\n");
/* DI0 -> DP-BG channel: */
mxc_fb_devices[0].num_resources = ARRAY_SIZE(mxcfb_resources);
mxc_fb_devices[0].resource = mxcfb_resources;
mxc_register_device(&mxc_fb_devices[0], &fb_data[0]);
/* DI1 -> DC channel: */
mxc_register_device(&mxc_fb_devices[1], &fb_data[1]);
}
/*
* DI0/1 DP-FG channel:
*/
mxc_register_device(&mxc_fb_devices[2], NULL);
printk(KERN_INFO "\n\nmxc_register_device&mxc_fb_devices[2]\n");
enable backlight & lcd power*/
/*gpio_request(MX53_ADV_LCD_PWR_EN,"lcd power");
gpio_direction_output(MX53_ADV_LCD_PWR_EN,1);
//msleep(300);
printk(KERN_INFO "\n\n gpio_direction_outputMX53_ADV_LCD_PWR_EN,1;\n");
gpio_request(MX53_ADV_BLK_PWR_EN,"blacklight power");
gpio_direction_output(MX53_ADV_BLK_PWR_EN,1);
printk(KERN_INFO "\n\n gpio_requestMX53_ADV_BLK_PWR_EN,blacklight power\n");
return 0;
}
device_initcall(mxc_init_fb);
我将背光放在ldbdriver的ldb_enable,里面打开。此ldb_enable()会在ldb probe时候通过fb_register_client()时候注册notifier_block nb进去。
最终ldb_enable会被内核调度。注意
static void ldb_enable(int ipu_di)
{
uint32_t reg;
spin_lock(&ldb_lock);
printk("\n####################\n$$$$$$$$$$$$$$$ldb_enable\n\n");
//+++++++++++++++++++
/*enable backlight & lcd power*/
gpio_request(MX53_ADV_LCD_PWR_EN,"lcd power");
gpio_direction_output(MX53_ADV_LCD_PWR_EN,1);
msleep(1300);
printk(KERN_INFO "\n\n gpio_direction_outputMX53_ADV_LCD_PWR_EN,1;\n");
gpio_request(MX53_ADV_BLK_PWR_EN,"blacklight power");
gpio_direction_output(MX53_ADV_BLK_PWR_EN,1);
printk(KERN_INFO "\n\n gpio_requestMX53_ADV_BLK_PWR_EN,blacklight power\n");
//+++++++++++++++++++++++
。。。
}
但发现功能OK,但出现内核的BUG: scheduling while atomic: swapper/1/0x00000002。
百度之,参考http://blog.csdn.net/cfy_phonex/article/details/12090943则解决问题。
即在内核在中断处理时候调用了可以休眠的函数。这是linux内核不允许的。却掉上面的sleep即可。
结论整理
linux内核打印"BUG: scheduling while atomic"和"bad: scheduling from the idle thread"错误的时候,
通常是在中断处理函数中调用了可以休眠的函数,如semaphore,mutex,sleep之类的可休眠的函数,
而linux内核要求在中断处理的时候,不允许系统调度,不允许抢占,要等到中断处理完成才能做其他事情。
因此,要充分考虑中断处理的时间,一定不能太久。
另外一个能产生此问题的是在idle进程里面,做了不该做的事情。现在Linux用于很多手持式设备,为了降低功耗,
通常的作法是在idle进程里面降低CPU或RAM的频率、关闭一些设备等等。要保证这些动作的原子性才能确保
不发生"bad: scheduling from the idle thread"这样的错误!
禁止内核抢占是指内核不会主动的抢占你的process,但是现在是你在自己的程序中主动call schedule(),
kernel并不能阻止你这么作。
Scheduling while atomic" means that a thread has called schedule() during an operation which is supposed to be atomic (ie uninterrupted).