arm linux debug notes (error note)
来源:互联网 发布:网络运维服务承诺书 编辑:程序博客网 时间:2024/05/21 04:43
1. forgot __func__ and pointer is judged too earlily.
ret = sprdfb_panel_constructor(pan_node, fb_dev);if (ret) {pr_err("%s: failed to construct panel device\n"); // lose __func__return -EFAULT;}
%s, __func__, forgot __func__
if (!fb_dev || fb_dev->panel)return -ENODEV; // Actually, panel pointer is NULL...pan_node = sprdfb_panel_search(fb_dev);if (!pan_node) {pr_warn("can't find panel specified by cmdline, try reading id\n");}ret = sprdfb_panel_constructor(pan_node, fb_dev);if (ret) {pr_err("%s: failed to construct panel device\n", __func__);return -EFAULT;}panel = fb_dev->panel;
The error log is as following:
7sprdfb_panel: ---- enter: sprdfb_panel_device_register ----1Unable to handle kernel paging request at virtual address 600001131pgd = c00040001[60000113] *pgd=000000000Internal error: Oops: 5 [#1] PREEMPT SMP ARMdModules linked in:dCPU: 1 PID: 1 Comm: swapper/0 Tainted: G W 3.10.17-00026-g6d61c92-dirty #29dtask: d7098000 ti: d70a0000 task.ti: d70a0000PC is at strnlen+0x1c/0x30LR is at string.isra.3+0x34/0xc8pc : [<c01e5e20>] lr : [<c01e6e34>] psr: 20000193 // stopped at printk, actually is pr_err.sp : d70a1c78 ip : 00000020 fp : d70a1d58r10: c055827b r9 : c084b0e0 r8 : 00000000r7 : 60000113 r6 : ffffffff r5 : c084b0e0 r4 : c084ad0ar3 : 60000113 r2 : 60000113 r1 : 60000112 r0 : 60000113 // 6000113 is a abnormal address!!!Flags: nzCv IRQs off FIQs on Mode SVC_32 ISA ARM Segment kernelControl: 10c53c7d Table: 8000406a DAC: 00000015
2. pointer should not NULL
porch = kzalloc(sizeof(struct timing_rgb), GFP_KERNEL);panel = kzalloc(sizeof(struct panel_spec), GFP_KERNEL);if (!panel || porch) // judge porch not right, should !porchgoto alloc_panel_mem_error;
3. The field name doesn't not match
name = (char *)of_get_property(pan_node,"sprdfb,dispc-dsi-panel-name", NULL);if (!name) {strlcpy(panel->panel_name, "unspecified", PANEL_NAME_LEN);ret = -ENXIO;pr_err("%s:%d, Panel name not specified\n",__func__, __LINE__);goto parse_dt_error;} else {strlcpy(panel->panel_name, name, PANEL_NAME_LEN);pr_info("%s: Panel: %s is specified\n",__func__, panel->panel_name);}
The name in dtsi is "dispc-panel-name", but in source code, the name is "dispc-dsi-panel-name".
4. NULL Pointer
static int sprdfb_panel_parse_dcs_cmds(const struct device_node *np,struct dsi_cmds_list *pcmds, char *cmd_key){const char *data;int dt_len = 0, len;char *buf, *bp;struct dsi_cmd_desc *d;int cnt = 0;pr_debug("---- enter: %s ----\n", __func__);data = of_get_property(np, cmd_key, &dt_len);if (!data) {pr_err("%s: failed, key=%s\n", __func__, cmd_key);return -ENOMEM;}buf = kzalloc(sizeof(char) * dt_len, GFP_KERNEL);if (!buf)return -ENOMEM;memcpy(buf, data, dt_len);/* scan dcs commands */bp = buf;len = dt_len;d = (struct dsi_cmd_desc *)bp;d->c_len = ntohs(d->c_len); // If d is NULL, now dereference it, kernel will be dumped. while (len > (sizeof(*d) + d->c_len)) {if (d->c_len > len) {pr_err("%s: dtsi cmd=%x error, len=%d",__func__, d->data_type, d->c_len);goto exit_free;}pr_debug("data type is %d, cmd len is %d\n",d->data_type, d->c_len);bp += sizeof(*d) + d->c_len;len -= sizeof(*d) + d->c_len;d = (struct dsi_cmd_desc *)bp;d->c_len = ntohs(d->c_len);cnt++;}pcmds->cmds_cnt = cnt;pcmds->cmds = (struct dsi_cmd_desc *)buf;return 0;exit_free:kfree(buf);return -EFAULT;}
5. Init sequence for using dts
1) platform_bus_init
2) iomap
3) register all platform_driver to platform_driver bus
4) hwspinlock init
4.1 find the hwspinlock node in DTS
4.2 register the hwspinlock device to platform_device bus
4.3 hwspinlock probe() and init the hwspinlock data struct
4.4 early_init_hwspinlock
5) ADI_init and ADC_init
6) populate the DT, register all devices to platform_device bus
6. name is defined wrongly
data = (char *)of_get_property(node,"sprdfb,dispc-dsi-color-mode-polarity", NULL);if (data) {if (!strcmp(data, "negative"))panel->info.mipi->color_mode_pol = SPRDFB_POLARITY_NEG;elsepanel->info.mipi->color_mode_pol = SPRDFB_POLARITY_POS;} elsepanel->info.mipi->color_mode_pol = SPRDFB_POLARITY_POS;
The field "sprdfb,dispc-dsi-color-mode-polarity" is right, but previously, it is wrong, "-polarity" is missed.
In dtsi, the field is as following:
sprdfb,dispc-dsi-h-sync-polarity = "positive";sprdfb,dispc-dsi-v-sync-polarity = "positive";sprdfb,dispc-dsi-de-polarity = "positive";sprdfb,dispc-dsi-te-polarity = "positive";sprdfb,dispc-dsi-color-mode-polarity = "negative";sprdfb,dispc-dsi-shut-down-polarity = "negative";
7. pointer to pointers and dsi commands
static int sprdfb_dsi_tx_cmds(struct panel_spec *panel,struct dsi_cmd_desc **cmds, u32 cmds_len, bool force_lp){int i, time, len;struct ops_mipi *ops = panel->info.mipi->ops;u8 *data;u16 work_mode = panel->info.mipi->work_mode;pr_info("%s, len: %d\n", __func__, cmds_len);if (!ops->mipi_set_cmd_mode ||!ops->mipi_dcs_write ||!ops->mipi_set_hs_mode ||!ops->mipi_set_lp_mode ||!ops->mipi_force_write) {pr_err("%s: Expected functions are NULL.\n", __func__);return -EFAULT;}if (force_lp) {if (work_mode == SPRDFB_MIPI_MODE_CMD)ops->mipi_set_lp_mode();elseops->mipi_set_data_lp_mode();}ops->mipi_set_cmd_mode();for (i = 0; i < cmds_len; i++) {if (cmds[i]->data_type != DCS_SHORT_WRITE_0 &&cmds[i]->data_type != DCS_SHORT_WRITE_1) {len = cmds[i]->c_len + sizeof(cmds[i]->c_len);data = cmds[i]->payload - sizeof(cmds[i]->c_len);} else {len = cmds[i]->c_len;data = cmds[i]->payload;}pr_debug("dsi write cmd type: %d, len: %d\n",cmds[i]->data_type, len);if (cmds[i]->data_type == GENERIC_LONG_WRITE)ops->mipi_force_write(GENERIC_LONG_WRITE, data, len);elseops->mipi_dcs_write(data, len);if (cmds[i]->wait_time) {time = cmds[i]->wait_time * 1000;usleep_range(time, time);}}if (force_lp) {if (work_mode == SPRDFB_MIPI_MODE_CMD)ops->mipi_set_hs_mode();elseops->mipi_set_data_hs_mode();}return 0;}
struct dsi_cmds_list {struct dsi_cmd_desc *cmds[PANEL_MAX_CMDS_LEN];u32 cmds_cnt;};
struct dsi_cmd_desc {u8 data_type; /* BYTE[0] */u8 reserved; /* BYTE[1]: reserved */u8 wait_time; /* BYTE[2] */u16 c_len; /* BYTE[3...4]: cmd lenght */u8 payload[0]; /* BYTE[5] */} __packed;
/* 05: DCS short Wr; 39: DCS long Wr; 06: DCS read; 15: DCS short Wr */#define GENERIC_SHORT_WRITE_00x03#define GENERIC_SHORT_WRITE_10x13#define GENERIC_SHORT_WRITE_20x23#define GENERIC_LONG_WRITE0x29#define DCS_SHORT_WRITE_00x05#define DCS_SHORT_WRITE_10x15#define DCS_LONG_WRITE0x39#define GENERIC_SHORT_READ_00x04#define GENERIC_SHORT_READ_10x14#define GENERIC_SHORT_READ_20x24#define DCS_READ_00x06#define SET_MAX_RET_PKT_SIZE0x37
Parsing and handling commands of dsi are not easy. They should be paid a lot of attention to.
static int sprdfb_panel_parse_dcs_cmds(const struct device_node *np,struct dsi_cmds_list *pcmds, char *cmd_key){const char *data;int dt_len = 0, len, header;char *buf, *bp;int cnt = 0;pr_debug("---- enter: %s ----\n", __func__);data = of_get_property(np, cmd_key, &dt_len);if (!data) {pr_err("%s: failed, key=%s\n", __func__, cmd_key);return -ENOMEM;}buf = kzalloc(sizeof(char) * dt_len, GFP_KERNEL);if (!buf)return -ENOMEM;memcpy(buf, data, dt_len);/* scan dcs commands */bp = buf;len = dt_len;header = sizeof(struct dsi_cmd_desc);while (len > header) {pcmds->cmds[cnt] = (struct dsi_cmd_desc *)bp;pcmds->cmds[cnt]->c_len = ntohs(pcmds->cmds[cnt]->c_len);if (pcmds->cmds[cnt]->c_len > len) {pr_err("%s: data type is 0x%x error, len=%d\n",__func__, pcmds->cmds[cnt]->data_type,pcmds->cmds[cnt]->c_len);goto exit_free;}pr_debug("data type is 0x%x, cmd len is %d, remaining(%d), ""cnt(%d)\n", pcmds->cmds[cnt]->data_type,pcmds->cmds[cnt]->c_len, len, cnt + 1);bp += header;len -= header;bp += pcmds->cmds[cnt]->c_len;len -= pcmds->cmds[cnt]->c_len;cnt++;}pcmds->cmds_cnt = cnt;return 0;exit_free:kfree(buf);return -EFAULT;}
6. virtual address and physical address switch
trace32 -> CPU -> peripheral -> System Control and Config -> SCTLR_EL1 -> M -> enable (enable virtual address) / disable (physical address)
7 linux flags
__attribute__
函数f()将被放到只读new_section段中,而不是.text中。
asmlinkage
__init
是一个宏定义,定义在arch/um/include/init.h文件中,具体如:
__weak
是一个宏定义,定义在include/asm-mips/linkage.h文件中,具体如:
__va(x)
是个宏,定义在include/asm-alpha/page.h文件中,具体如下:
__pa(x)
也是个宏,定义在include/asm-alpha/page.h文件中,具体如下:
其中的PAGE_OFFSET定义为0xffff800000000000UL或0xfffffc0000000000UL
register
可以用来修饰变量,表示寄存器变量,只能用于整型和字符变量,表示变量被存储在CPU的寄存器中, 而不像普通变量被存储在内存中,这样可以提高运算速度,它常用于在同一变量名频繁出现的地方,且 它只适用于局部变量和函数的形式参数,它属于auto型变量,不能作为全局变量
EXPORT_SYMBOL
0 0
- arm linux debug notes (error note)
- linux kernel / android debug notes
- linux error note
- KGDB for ARM-Linux Usage Notes
- Android debug :arm-linux-androideabi-addr2line
- display debug notes
- FPGA debug notes
- armv8 AArch64 debug notes
- ARM learning notes
- ARM--------ADS1.2 debug出错 error starting external process process error code 87(0x57)
- error debug
- Debug Error
- Linux Notes
- linux notes
- Linux Notes
- linux notes
- linux notes
- ubuntu14.04 install arm-linux-gcc error
- NC常用控件
- html加载顺序
- 微软2014年4月 实习生招聘机试题 1.String reorder
- 树形控件Tree Control以及CTreeCtrl类
- c# 托管堆,堆栈【图文非常详细】
- arm linux debug notes (error note)
- oracle 主键自增
- 黑马程序员--Java面向对象——多线程——下
- C# Func<>委托
- JavaScript动态时钟
- Raw-OS源码分析之软件定时器
- jquery_warp
- no zuo no die 歌
- 黑马程序员--Java面向对象——String StringBuffer