freescale R10 ipu lib 分析 - ipu_device.c

IPU设备驱动解析
本文详细解析了IPU设备驱动的实现原理,介绍了如何通过不同的ioctl命令来初始化、配置及管理IPU通道,包括缓冲区管理、IRQ设置等功能。

ipu_device.c

原文:http://blog.youkuaiyun.com/kickxxx/archive/2011/06/22/6561804.aspx

 

这个函数很长,很简单,都是对ipu common函数的封装,先去分析ipu_common.c

 

这个文件创建了一个mxc_ipu字符设备节点,目的是为了ipu lib服务的,主要函数就是mxc_ipu_ioctl,  app可以利用ipu lib实现如下功能:

  1. Resize
  2. Rotation
  3. Color space/format convert
  4. Overlay combination with the same size which supports color ker and alpha blending
  5. Output display to frame buffer directly after IPU process
  6. Two outputs processed form one input
  7. Windows crop
  8. Local alpha blending

474 int register_ipu_device()
475 {
476     int ret = 0;
477     struct device *temp;
478     mxc_ipu_major = register_chrdev(0, "mxc_ipu", &mxc_ipu_fops);
.................
510 }

478注册一个字符设备,应用通过/dev/mxc_ipu这个设备节点,操作IPU的channel,实现上述功能

 87 static int mxc_ipu_ioctl(struct inode *inode, struct file *file,
 88         unsigned int cmd, unsigned long arg)
 89 {
 90     int ret = 0;
 91 
 92     switch (cmd) {
 93     case IPU_INIT_CHANNEL:
 94         {
 95             ipu_channel_parm parm;
 96 
 97             if (copy_from_user
 98                     (&parm, (ipu_channel_parm *) arg,
 99                      sizeof(ipu_channel_parm)))
100                 return -EFAULT;
101 
102             if (!parm.flag) {
103                 ret =
104                     ipu_init_channel(parm.channel,
105                             &parm.params);
106             } else {
107                 ret = ipu_init_channel(parm.channel, NULL);
108             }
109         }
110         break;
111     case IPU_UNINIT_CHANNEL:
112         {
113         ipu_channel_t ch;
114         int __user *argp = (void __user *)arg;
115         if (get_user(ch, argp))
116                 return -EFAULT;
117             ipu_uninit_channel(ch);
118         }
119         break;
120     case IPU_INIT_CHANNEL_BUFFER:
121         {
122             ipu_channel_buf_parm parm;
123             if (copy_from_user
124                 (&parm, (ipu_channel_buf_parm *) arg,
125                 sizeof(ipu_channel_buf_parm)))
126                 return -EFAULT;
127 
128             ret =
129                 ipu_init_channel_buffer(
130                         parm.channel, parm.type,
131                         parm.pixel_fmt,
132                         parm.width, parm.height,
133                         parm.stride,
134                         parm.rot_mode,
135                         parm.phyaddr_0,
136                         parm.phyaddr_1,
137                         parm.u_offset,
138                         parm.v_offset);
139 
140         }
141         break;
142     case IPU_UPDATE_CHANNEL_BUFFER:
143         {
144             ipu_channel_buf_parm parm;
145             if (copy_from_user
146                 (&parm, (ipu_channel_buf_parm *) arg,
147                 sizeof(ipu_channel_buf_parm)))
148                 return -EFAULT;
149 
150             if ((parm.phyaddr_0 != (dma_addr_t) NULL)
151                 && (parm.phyaddr_1 == (dma_addr_t) NULL)) {
152                 ret =
153                     ipu_update_channel_buffer(
154                             parm.channel,
155                             parm.type,
156                             parm.bufNum,
157                             parm.phyaddr_0);
158             } else if ((parm.phyaddr_0 == (dma_addr_t) NULL)
159                 && (parm.phyaddr_1 != (dma_addr_t) NULL)) {
160                 ret =
161                     ipu_update_channel_buffer(
162                             parm.channel,
163                             parm.type,
164                             parm.bufNum,
165                             parm.phyaddr_1);
166             } else {
167                 ret = -1;
168             }
169 
170         }
171         break;
172     case IPU_SELECT_CHANNEL_BUFFER:
173         {
174             ipu_channel_buf_parm parm;
175             if (copy_from_user
176                 (&parm, (ipu_channel_buf_parm *) arg,
177                 sizeof(ipu_channel_buf_parm)))
178                 return -EFAULT;
179 
180             ret =
181                 ipu_select_buffer(parm.channel,
182                     parm.type, parm.bufNum);
183 
184         }
185         break;
186     case IPU_SELECT_MULTI_VDI_BUFFER:
187         {
188             uint32_t parm;
189             if (copy_from_user
190                 (&parm, (uint32_t *) arg,
191                 sizeof(uint32_t)))
192                 return -EFAULT;
193 
194             ret = ipu_select_multi_vdi_buffer(parm);
195         }
196         break;
197     case IPU_LINK_CHANNELS:
198         {
199             ipu_channel_link link;
200             if (copy_from_user
201                 (&link, (ipu_channel_link *) arg,
202                 sizeof(ipu_channel_link)))
203                 return -EFAULT;
204 
205             ret = ipu_link_channels(link.src_ch,
206                 link.dest_ch);
207 
208         }
209         break;
210     case IPU_UNLINK_CHANNELS:
211         {
212             ipu_channel_link link;
213             if (copy_from_user
214                 (&link, (ipu_channel_link *) arg,
215                 sizeof(ipu_channel_link)))
216                 return -EFAULT;
217 
218             ret = ipu_unlink_channels(link.src_ch,
219                 link.dest_ch);
220 
221         }
222         break;
223     case IPU_ENABLE_CHANNEL:
224         {
225             ipu_channel_t ch;
226             int __user *argp = (void __user *)arg;
227             if (get_user(ch, argp))
228                 return -EFAULT;
229             ipu_enable_channel(ch);
230         }
231         break;
232     case IPU_DISABLE_CHANNEL:
233         {
234             ipu_channel_info info;
235             if (copy_from_user
236                 (&info, (ipu_channel_info *) arg,
237                  sizeof(ipu_channel_info)))
238                 return -EFAULT;
239 
240             ret = ipu_disable_channel(info.channel,
241                 info.stop);
242         }
243         break;
244     case IPU_ENABLE_IRQ:
245         {
246             uint32_t irq;
247             int __user *argp = (void __user *)arg;
248             if (get_user(irq, argp))
249                 return -EFAULT;
250             ipu_enable_irq(irq);
251         }
252         break;
253     case IPU_DISABLE_IRQ:
254         {
255             uint32_t irq;
256             int __user *argp = (void __user *)arg;
257             if (get_user(irq, argp))
258                 return -EFAULT;
259             ipu_disable_irq(irq);
260         }
261         break;
262     case IPU_CLEAR_IRQ:
263         {
264             uint32_t irq;
265             int __user *argp = (void __user *)arg;
266             if (get_user(irq, argp))
267                 return -EFAULT;
268             ipu_clear_irq(irq);
269         }
270         break;
271     case IPU_FREE_IRQ:
272         {
273             ipu_irq_info info;
274 
275             if (copy_from_user
276                     (&info, (ipu_irq_info *) arg,
277                      sizeof(ipu_irq_info)))
278                 return -EFAULT;
279 
280             ipu_free_irq(info.irq, info.dev_id);
281             irq_info[info.irq].irq_pending = 0;
282         }
283         break;
284     case IPU_REQUEST_IRQ_STATUS:
285         {
286             uint32_t irq;
287             int __user *argp = (void __user *)arg;
288             if (get_user(irq, argp))
289                 return -EFAULT;
290             ret = ipu_get_irq_status(irq);
291         }
292         break;
293     case IPU_REGISTER_GENERIC_ISR:
294         {
295             ipu_event_info info;
296             if (copy_from_user
297                     (&info, (ipu_event_info *) arg,
298                      sizeof(ipu_event_info)))
299                 return -EFAULT;
300 
301             ret =
302                 ipu_request_irq(info.irq,
303                     mxc_ipu_generic_handler,
304                     0, "video_sink", info.dev);
305             if (ret == 0)
306                 init_waitqueue_head(&(irq_info[info.irq].waitq));
307         }
308         break;
309     case IPU_GET_EVENT:
310         /* User will have to allocate event_type
311         structure and pass the pointer in arg */
312         {
313             ipu_event_info info;
314             int r = -1;
315 
316             if (copy_from_user
317                     (&info, (ipu_event_info *) arg,
318                      sizeof(ipu_event_info)))
319                 return -EFAULT;
320 
321             r = get_events(&info);
322             if (r == -1) {
323                 if ((file->f_flags & O_NONBLOCK) &&
324                     (irq_info[info.irq].irq_pending == 0))
325                     return -EAGAIN;
326                 wait_event_interruptible_timeout(irq_info[info.irq].waitq,
327                         (irq_info[info.irq].irq_pending != 0), 2 * HZ);
328                 r = get_events(&info);
329             }
330             ret = -1;
331             if (r == 0) {
332                 if (!copy_to_user((ipu_event_info *) arg,
333                     &info, sizeof(ipu_event_info)))
334                     ret = 0;
335             }
336         }
337         break;
338     case IPU_ALOC_MEM:
339         {
340             ipu_mem_info info;
341             if (copy_from_user
342                     (&info, (ipu_mem_info *) arg,
343                      sizeof(ipu_mem_info)))
344                 return -EFAULT;
345 
346             info.vaddr = dma_alloc_coherent(0,
347                     PAGE_ALIGN(info.size),
348                     &info.paddr,
349                     GFP_DMA | GFP_KERNEL);
350             if (info.vaddr == 0) {
351                 printk(KERN_ERR "dma alloc failed!/n");
352                 return -ENOBUFS;
353             }
354             if (copy_to_user((ipu_mem_info *) arg, &info,
355                     sizeof(ipu_mem_info)) > 0)
356                 return -EFAULT;
357         }
358         break;
359     case IPU_FREE_MEM:
360         {
361             ipu_mem_info info;
362             if (copy_from_user
363                     (&info, (ipu_mem_info *) arg,
364                      sizeof(ipu_mem_info)))
365                 return -EFAULT;
366 
367             if (info.vaddr)
368                 dma_free_coherent(0, PAGE_ALIGN(info.size),
369                     info.vaddr, info.paddr);
370             else
371                 return -EFAULT;
372         }
373         break;
374     case IPU_IS_CHAN_BUSY:
375         {
376             ipu_channel_t chan;
377             if (copy_from_user
378                     (&chan, (ipu_channel_t *)arg,
379                      sizeof(ipu_channel_t)))
380                 return -EFAULT;
381 
382             if (ipu_is_channel_busy(chan))
383                 ret = 1;
384             else
385                 ret = 0;
386         }
387         break;
388     case IPU_CALC_STRIPES_SIZE:
389         {
390             ipu_stripe_parm stripe_parm;
391 
392             if (copy_from_user (&stripe_parm, (ipu_stripe_parm *)arg,
393                      sizeof(ipu_stripe_parm)))
394                 return -EFAULT;
395             ipu_calc_stripes_sizes(stripe_parm.input_width,
396                         stripe_parm.output_width,
397                         stripe_parm.maximal_stripe_width,
398                         stripe_parm.cirr,
399                         stripe_parm.equal_stripes,
400                         stripe_parm.input_pixelformat,
401                         stripe_parm.output_pixelformat,
402                         &stripe_parm.left,
403                         &stripe_parm.right);
404             if (copy_to_user((ipu_stripe_parm *) arg, &stripe_parm,
405                     sizeof(ipu_stripe_parm)) > 0)
406                 return -EFAULT;
407         }
408         break;
409     case IPU_UPDATE_BUF_OFFSET:
410         {
411             ipu_buf_offset_parm offset_parm;
412 
413             if (copy_from_user (&offset_parm, (ipu_buf_offset_parm *)arg,
414                      sizeof(ipu_buf_offset_parm)))
415                 return -EFAULT;
416             ret = ipu_update_channel_offset(offset_parm.channel,
417                             offset_parm.type,
418                             offset_parm.pixel_fmt,
419                             offset_parm.width,
420                             offset_parm.height,
421                             offset_parm.stride,
422                             offset_parm.u_offset,
423                             offset_parm.v_offset,
424                             offset_parm.vertical_offset,
425                             offset_parm.horizontal_offset);
426         }
427         break;
428     case IPU_CSC_UPDATE:
429         {
430             int param[5][3];
431             ipu_csc_update csc;
432             if (copy_from_user(&csc, (void *) arg,
433                        sizeof(ipu_csc_update)))
434                 return -EFAULT;
435             if (copy_from_user(&param[0][0], (void *) csc.param,
436                        sizeof(param)))
437                 return -EFAULT;
438             ipu_set_csc_coefficients(csc.channel, param);
439         }
440         break;
441     default:
442         break;
443     }
444     return ret;
445 }

 

board/freescale/mx6ull_alientek_emmc/mx6ull_alientek_emmc.c:138:34: error: expected ‘)’ before numeric constant gpio_direction_output(IOX_STCP, 1); ^ board/freescale/mx6ull_alientek_emmc/mx6ull_alientek_emmc.c:140:2: error: expected identifier or ‘(’ before ‘for’ for (i = 7; i >= 0; i--) { ^ board/freescale/mx6ull_alientek_emmc/mx6ull_alientek_emmc.c:140:16: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘>=’ token for (i = 7; i >= 0; i--) { ^ board/freescale/mx6ull_alientek_emmc/mx6ull_alientek_emmc.c:140:23: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘--’ token for (i = 7; i >= 0; i--) { ^ board/freescale/mx6ull_alientek_emmc/mx6ull_alientek_emmc.c:147:34: error: expected ‘)’ before numeric constant gpio_direction_output(IOX_STCP, 0); ^ board/freescale/mx6ull_alientek_emmc/mx6ull_alientek_emmc.c:148:9: error: expected declaration specifiers or ‘...’ before numeric constant udelay(500); ^ board/freescale/mx6ull_alientek_emmc/mx6ull_alientek_emmc.c:152:34: error: expected ‘)’ before numeric constant gpio_direction_output(IOX_STCP, 1); ^ board/freescale/mx6ull_alientek_emmc/mx6ull_alientek_emmc.c:153:1: error: expected identifier or ‘(’ before ‘}’ token }; ^ board/freescale/mx6ull_alientek_emmc/mx6ull_alientek_emmc.c: In function ‘iox74lv_set’: board/freescale/mx6ull_alientek_emmc/mx6ull_alientek_emmc.c:160:25: error: ‘IOX_SHCP’ undeclared (first use in this function) gpio_direction_output(IOX_SHCP, 0); ^ board/freescale/mx6ull_alientek_emmc/mx6ull_alientek_emmc.c:160:25: note: each undeclared identifier is reported only once for each function it appears in board/freescale/mx6ull_alientek_emmc/mx6ull_alientek_emmc.c:163:26: error: ‘IOX_SDI’ undeclared (first use in this function) gpio_direction_output(IOX_SDI, seq[qn_output[i]][0]); ^ board/freescale/mx6ull_alientek_emmc/mx6ull_alientek_emmc.c:171:24: error: ‘IOX_STCP’ undeclared (first use in this function) gpio_direction_output(IOX_STCP, 0); ^ arm-linux-gnueabihf-gcc -Wp,-MD,drivers/mmc/.fsl_esdhc.o.d -nostdinc -isystem /usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/4.9.4/include -Iinclude -I./arch/arm/include -include ./include/linux/kconfig.h -D__KERNEL__ -D__UBOOT__ -Wall -Wstrict-prototypes -Wno-format-security -fno-builtin -ffreestanding -Os -fno-stack-protector -fno-delete-null-pointer-checks -g -fstack-usage -Wno-format-nonliteral -Werror=date-time -D__ARM__ -marm -mno-thumb-interwork -mabi=aapcs-linux -mword-relocations -fno-pic -mno-unaligned-access -ffunction-sections -fdata-sections -fno-common -ffixed-r9 -msoft-float -pipe -march=armv7-a -D"KBUILD_STR(s)=#s" -D"KBUILD_BASENAME=KBUILD_STR(fsl_esdhc)" -D"KBUILD_MODNAME=KBUILD_STR(fsl_esdhc)" -c -o drivers/mmc/fsl_esdhc.o drivers/mmc/fsl_esdhc.c arm-linux-gnueabihf-gcc -Wp,-MD,drivers/mmc/.mmc_write.o.d -nostdinc -isystem /usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/4.9.4/include -Iinclude -I./arch/arm/include -include ./include/linux/kconfig.h -D__KERNEL__ -D__UBOOT__ -Wall -Wstrict-prototypes -Wno-format-security -fno-builtin -ffreestanding -Os -fno-stack-protector -fno-delete-null-pointer-checks -g -fstack-usage -Wno-format-nonliteral -Werror=date-time -D__ARM__ -marm -mno-thumb-interwork -mabi=aapcs-linux -mword-relocations -fno-pic -mno-unaligned-access -ffunction-sections -fdata-sections -fno-common -ffixed-r9 -msoft-float -pipe -march=armv7-a -D"KBUILD_STR(s)=#s" -D"KBUILD_BASENAME=KBUILD_STR(mmc_write)" -D"KBUILD_MODNAME=KBUILD_STR(mmc_write)" -c -o drivers/mmc/mmc_write.o drivers/mmc/mmc_write.c scripts/Makefile.build:280: recipe for target 'board/freescale/mx6ull_alientek_emmc/mx6ull_alientek_emmc.o' failed make[1]: *** [board/freescale/mx6ull_alientek_emmc/mx6ull_alientek_emmc.o] Error 1 make -f ./scripts/Makefile.build obj=drivers/mtd/spi arm-linux-gnueabihf-gcc -Wp,-MD,drivers/mmc/.mmc.o.d -nostdinc -isystem /usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/4.9.4/include -Iinclude -I./arch/arm/include -include ./include/linux/kconfig.h -D__KERNEL__ -D__UBOOT__ -Wall -Wstrict-prototypes -Wno-format-security -fno-builtin -ffreestanding -Os -fno-stack-protector -fno-delete-null-pointer-checks -g -fstack-usage -Wno-format-nonliteral -Werror=date-time -D__ARM__ -marm -mno-thumb-interwork -mabi=aapcs-linux -mword-relocations -fno-pic -mno-unaligned-access -ffunction-sections -fdata-sections -fno-common -ffixed-r9 -msoft-float -pipe -march=armv7-a -D"KBUILD_STR(s)=#s" -D"KBUILD_BASENAME=KBUILD_STR(mmc)" -D"KBUILD_MODNAME=KBUILD_STR(mmc)" -c -o drivers/mmc/mmc.o drivers/mmc/mmc.c rm -f drivers/mtd/onenand/built-in.o; arm-linux-gnueabihf-ar rcs drivers/mtd/onenand/built-in.o Makefile:1196: recipe for target 'board/freescale/mx6ull_alientek_emmc' failed make: *** [board/freescale/mx6ull_alientek_emmc] Error 2 make: *** 正在等待未完成的任务....
最新发布
08-19
<think>我们遇到了一个编译错误,错误集中在文件 `board/freescale/mx6ull_alientek_emmc/mx6ull_alientek_emmc.c` 中。错误信息包括: 1. `error: expected ‘)’ before numeric constant`:在调用函数时,参数传递可能有问题,可能是宏定义错误或者参数类型不匹配。 2. `error: expected identifier or ‘(’ before ‘for’`:在for循环之前可能有语法错误,可能是前面的语句没有正确结束。 3. `error: ‘IOX_SHCP’ undeclared`:表明这些宏没有被定义,可能是头文件包含问题或者宏定义缺失。 ### 错误分析 从错误信息来看,主要问题在于: - 在调用`gpio_direction_output`函数时,第二个参数是数字常量(如1或0),但编译器在数字常量之前期望有一个右括号,这通常是因为第一个参数(即GPIO引脚号)的宏定义有问题,可能是宏定义不正确或者被错误地重定义了。 - 在for循环之前有语法错误,可能是前面的语句缺少分号或者括号不匹配。 - 宏`IOX_SHCP`、`IOX_SDI`、`IOX_STCP`未声明,说明这些宏可能没有被定义。这可能是由于头文件未包含或宏定义条件不满足。 ### 解决方案 #### 步骤1:检查宏定义 首先,我们需要确认这些宏(`IOX_SHCP`, `IOX_SDI`, `IOX_STCP`)是否在头文件中正确定义。通常,这些宏应该在开发板的头文件中定义,例如在`include/configs/mx6ull_alientek_emmc.h`中。 如果没有定义,我们需要添加类似以下的定义(具体的GPIO号需要根据硬件原理图确定): ```c /* 例如: */ #define IOX_SHCP IMX_GPIO_NR(1, 20) #define IOX_SDI IMX_GPIO_NR(1, 21) #define IOX_STCP IMX_GPIO_NR(1, 18) ``` #### 步骤2:检查函数调用 在代码中,调用`gpio_direction_output`时,第二个参数是数字常量(0或1),这是正确的。但是错误提示在数字常量之前缺少右括号,这通常是因为第一个参数(宏)被展开后可能包含一些意外的字符,或者宏展开后导致参数个数不对。 例如,如果宏`IOX_STCP`没有被正确定义,它可能会被展开为空或者其他不正确的内容,导致函数调用的参数列表错误。 #### 步骤3:检查语法错误 在for循环之前,我们注意到有错误提示,可能是前面的函数调用语句缺少分号,或者括号不匹配。检查错误行之前的代码,确保每行语句以分号结束,括号匹配。 #### 步骤4:检查头文件包含 确保在`mx6ull_alientek_emmc.c`文件中包含了必要的头文件,特别是定义了`IMX_GPIO_NR`的头文件。通常,应该包含: ```c #include <asm/gpio.h> #include <asm/mach-imx/gpio.h> ``` ### 修改示例 假设我们发现宏没有定义,我们在开发板的配置头文件中添加宏定义(注意:具体引脚号需要根据原理图修改): 1. 打开 `include/configs/mx6ull_alientek_emmc.h`,在文件末尾的`#endif`之前添加: ```c /* GPIO for IOX */ #define IOX_SHCP IMX_GPIO_NR(1, 20) #define IOX_SDI IMX_GPIO_NR(1, 21) #define IOX_STCP IMX_GPIO_NR(1, 18) ``` 2. 在`mx6ull_alientek_emmc.c`文件中,确保包含头文件: ```c #include <asm/gpio.h> #include <asm/mach-imx/gpio.h> ``` 3. 检查错误行(138行、140行等)附近的代码,确保语法正确。例如,在for循环之前,确保前一行语句有分号结束。 ### 错误代码片段及修正 原错误代码片段(可能): ```c gpio_direction_output(IOX_STCP, 1); // 第138行 for (i = 7; i >= 0; i--) { // 第140行 ... } ``` 如果138行后面没有分号,但实际代码中是有分号的,那么可能是宏展开问题。如果宏未定义,则预处理器会将`IOX_STCP`视为0(如果没有警告的话),但这里报错是语法错误,所以更可能是宏被错误定义或者展开后产生异常。 ### 重新编译 修改后,重新编译: ```bash make clean make mx6ull_alientek_emmc_defconfig make -j4 ``` ### 其他可能的问题 如果上述方法不能解决,可能是代码中其他地方有语法错误,导致编译器解析到for循环时出现混乱。可以尝试注释掉出错的部分,逐步排查。 §§相关问题§§: 1. 在嵌入式开发中,如何根据原理图确定GPIO引脚号? 2. U-Boot中添加自定义板级支持包(BSP)的步骤是什么? 3. 如何调试U-Boot编译过程中的头文件和宏定义问题? 4. 在C语言中,宏定义的使用有哪些注意事项以避免展开错误?</think>### 问题分析 您遇到的编译错误主要集中在 `board/freescale/mx6ull_alientek_emmc/mx6ull_alientek_emmc.c` 文件中,主要问题包括: 1. **宏定义缺失**: - `IOX_SHCP`, `IOX_SDI`, `IOX_STCP` 等 GPIO 宏未声明 - 这些宏通常应在板级配置文件中定义 2. **语法错误**: - `expected ')' before numeric constant`:函数调用参数传递问题 - `expected identifier before 'for'`:循环结构前的语法错误 3. **头文件包含问题**: - 可能缺少必要的 GPIO 操作头文件 - 宏定义未正确包含到源文件中 --- ### 解决方案 #### 步骤 1:添加 GPIO 宏定义 在板级配置头文件中添加 GPIO 定义(例如 `include/configs/mx6ull_alientek_emmc.h`): ```c /* GPIO 引脚定义 */ #define IOX_SHCP IMX_GPIO_NR(1, 20) // GPIO1_IO20 #define IOX_SDI IMX_GPIO_NR(1, 21) // GPIO1_IO21 #define IOX_STCP IMX_GPIO_NR(1, 22) // GPIO1_IO22 ``` #### 步骤 2:修复语法错误 修改 `mx6ull_alientek_emmc.c` 文件中的问题代码: ```c // 修复前 gpio_direction_output(IOX_STCP, 1); // 修复后 gpio_direction_output(IOX_STCP, 1); // 确保分号结束 ``` #### 步骤 3:添加必要的头文件 在源文件开头添加 GPIO 操作所需的头文件: ```c #include <asm/gpio.h> #include <asm/mach-imx/gpio.h> #include <linux/delay.h> ``` #### 步骤 4:完整修复示例 ```c // 添加头文件 #include <asm/gpio.h> #include <asm/mach-imx/gpio.h> #include <linux/delay.h> // 确保宏定义可见 #ifndef IOX_SHCP #define IOX_SHCP IMX_GPIO_NR(1, 20) #endif void iox74lv_init(void) { // 初始化代码 gpio_direction_output(IOX_SHCP, 0); gpio_direction_output(IOX_SDI, 0); gpio_direction_output(IOX_STCP, 0); // 修复循环结构 int i; for (i = 7; i >= 0; i--) { // 循环体 } // 确保参数传递正确 gpio_direction_output(IOX_STCP, 1); udelay(500); // 使用正确的延时函数 } ``` --- ### 错误原因详解 1. **宏定义缺失**: - U-Boot 使用 `IMX_GPIO_NR(bank, pin)` 宏定义 GPIO - 需要包含 `<asm/mach-imx/gpio.h>` 头文件 2. **语法错误分析**: ```c // 错误:数字常量前缺少右括号 gpio_direction_output(IOX_STCP, 1); // 实际应为:gpio_direction_output(IOX_STCP, 1); // 错误:for 循环前有未结束的语句 function_call(); for(...) { ... } ``` 3. **延时函数使用**: - 正确使用 `udelay()` 需要包含 `<linux/delay.h>` - 参数应为整数:`udelay(500);` 而不是 `udelay(500)` --- ### 完整修复流程 1. 打开板级配置文件: ```bash vi include/configs/mx6ull_alientek_emmc.h ``` 2. 添加 GPIO 宏定义: ```c /* IO扩展器引脚 */ #define IOX_SHCP IMX_GPIO_NR(1, 20) #define IOX_SDI IMX_GPIO_NR(1, 21) #define IOX_STCP IMX_GPIO_NR(1, 22) ``` 3. 修改源文件: ```bash vi board/freescale/mx6ull_alientek_emmc/mx6ull_alientek_emmc.c ``` - 添加头文件包含 - 修复语法错误 - 确保所有函数调用正确结束 4. 重新编译: ```bash make clean make mx6ull_alientek_emmc_defconfig make -j4 ``` --- ### 关键注意事项 1. **GPIO 编号规则**: - i.MX6ULL 使用 `IMX_GPIO_NR(bank, pin)` 格式 - Bank 范围 1-5,Pin 范围 0-31 2. **延时函数选择**: - `udelay()`:微秒级延时(< 1000μs) - `mdelay()`:毫秒级延时 - 包含 `<linux/delay.h>` 后使用 3. **错误排查技巧**: ```bash # 查看预处理后的代码 arm-linux-gnueabihf-gcc -E board/freescale/.../file.c # 检查宏定义是否生效 grep -r "IOX_SHCP" include/configs/ ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值