问题描述:
在调试mipi接口的显示屏的时候出现如下两种情况,
(1)在设备树arch\arm\boot\dts\rk3128-box-rk88.dts中配置在uboot阶段显示logo,会出现程序跑飞。
(2) 在在设备树arch\arm\boot\dts\rk3128-box-rk88.dts中配置在uboot阶段显示logo后,出现显示异常,颜色过度不自然,颜色不纯有色块等,并且通过PQ调试也无法解决。
阶段uboot阶段显示logo设备树配置如下:
&fb {
rockchip,disp-mode = <NO_DUAL>;
rockchip,uboot-logo-on = <1>;
};
问题1解决方案:
针对程序跑飞,最后发现从Log无法提供有用信息,但是通过开关uboot-logo-on发现只有开启uboot-logo-on才会出现该问题。最后通过网上资料查询得知,如果mipi发送的cmds参数太长会导致局部数组溢出导致程序跑飞。最后修改如下:
index 7679e52..368aa1f 100755
--- a/u-boot/drivers/video/screen/lcd_mipi.c
+++ b/u-boot/drivers/video/screen/lcd_mipi.c
[url=home.php?mod=space&uid=1999721]@@[/url] -27,6 +27,10 @@
#include "../transmitter/mipi_dsi.h"
#endif
+/ added by liangzhentao /
+#define CMD_LEN 256
+/ end of adding /
#ifdef CONFIG_RK32_DSI
#define MIPI_SCREEN_DBG(x...) //printf(x)
#elif defined CONFIG_LCD_MIPI
@@ -354,7 +358,7 @@ static int rk_mipi_screen_init_dt(struct mipi_screen *screen)
struct list_head *pos;
struct property *prop;
enum of_gpio_flags flags;
u32 value, i, debug, gpio, ret, cmds[25], length;
u32 value, i, debug, gpio, ret, cmds[CMD_LEN], length;
memset(screen, 0, sizeof(*screen));
@@ -612,7 +616,7 @@ EXPORT_SYMBOL(rk_mipi_get_dsi_clk);
static int rk_mipi_screen_init_dt(struct mipi_screen *screen)
{
struct mipi_dcs_cmd_ctr_list *dcs_cmd;
u32 i,cmds[20];
u32 i,cmds[CMD_LEN];
int length;
int err;
int node;
如上修改成256过后程序正常跑起来。
问题2解决方法:
问题当时困扰了很久,lcd能正常显示,并且供电电压等都正常,但是显示就是不自然,颜色过度不自然,调试pq的时候色轮明显色块不纯。UI设计同事调试PQ无法调试,认为硬件出现了问题,排查许久,最终在一次偶然的机会关闭uboot-logo的调试发现颜色几乎正常(还没调试PQ)。最终排查从uboot-logo思路方面排查调试。
通过不断打印发送cmds参数发现,在发送一次参数比较长数据的时候会出现参数跟设备树匹配的参数值不匹配的情况。最明显例如发送长度为60个cmds参数的时候,每次都会在第33,42,43这三个cmds数据出现异常。后来定位的出错的地方如下(打印出来的cmds参数跟设备树配置的不一样):
static void rk_mipi_screen_cmd_init(struct mipi_screen *screen)
{
u8 len, i;
u8 *cmds;
struct list_head *screen_pos;
struct mipi_dcs_cmd_ctr_list *dcs_cmd;
#ifdef CONFIG_RK32_DSI
cmds = calloc(1,0x400);
if(!cmds) {
printf("request cmds fail!\n");
return;
}
#endif
#ifdef CONFIG_LCD_MIPI
cmds = kmalloc(0x400, GFP_KERNEL);
if(!cmds) {
printk("request cmds fail!\n");
return ;
}
#endif
list_for_each(screen_pos, &screen->cmdlist_head){
dcs_cmd = list_entry(screen_pos, struct mipi_dcs_cmd_ctr_list, list);
len = dcs_cmd->dcs_cmd.cmd_len + 1;
for( i = 1; i < len ; i++){
cmds[i] = dcs_cmd->dcs_cmd.cmds[i-1];
//printf("cmds[%d]=0x%x ",i,cmds[i]);//打印一次发送命令参数
}
//printf("\n"); //发送一行后分割
MIPI_SCREEN_DBG("dcs_cmd.name:%s\n",dcs_cmd->dcs_cmd.name);
if(dcs_cmd->dcs_cmd.type == LPDT){
cmds[0] = LPDT;
if(dcs_cmd->dcs_cmd.dsi_id == 0){
MIPI_SCREEN_DBG("dcs_cmd.dsi_id == 0 line=%d\n",__LINE__);
dsi_send_packet(0, cmds, len);//发送参数
}
......
}
}
最后想到应该也是一些数组溢出访问的问题,果然发现结构体mipi_dcs_cmd_ctr_list中的成员变量申请的数组个数是32个,这样说明为何每次都是第33个开始出错了。最后修改如下:
index f4d77a0..089a672 100755
--- a/u-boot/drivers/video/transmitter/mipi_dsi.h
+++ b/u-boot/drivers/video/transmitter/mipi_dsi.h
@@ -255,12 +255,17 @@ struct mipi_dsi_screen {
#define INVALID_GPIO -1
+/ added by liangzhentao /
+#define CMD_LEN 256
+/ end of adding /
struct dcs_cmd {
u8 type;
u8 dtype;
u8 dsi_id;
u8 cmd_len;
int cmds[32];
+// int cmds[32]; //原来这里只有32 int类型的储存单位,当设备树配置的cmds超过32个的时候出现异常
int cmds[CMD_LEN]; //sometimes len will very long
int delay;
char name[32];
};
原作者:Ian22l
更多回帖