迅为iMX6UL开发板驱动-PWM测试方法

本文详细介绍了在迅为iMX6UL开发板上配置和测试PWM的方法,包括硬件连接、设备树文件分析与修改、时钟配置、管脚配置及设备注册等步骤,并通过实际测试验证PWM输出。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

平台:迅为iMX6UL开发板 
说明:PWM 配置和测试方法
测试中不需要添加额外驱动,是基于系统用户态的 sysfs,可以使用命令来直接操作底层。








1 iMX6UL的PWM简介
打开 iMX6UL 的 datasheet,搜索 PWM 关键词,如下图所示。
PWM5-PWM8 的地址如下。










PWM1-PWM4 的地址如下。






可以知道 iMX6UL 最多可以支持 8 路 PWM 输出,也查出了物理地址。




2 iMX6UL的PWM0测试
所有的 ARM 板,默认情况下背光都是采用的 PWM 来调整的,那么它的 PWM 时钟地址
等参数肯定是配置好的,我们可以先使用背光对应 PWM 来做初步的测试。






2.1 硬件简介
打开 iMX6UL 的底板原理图,如下图所示,可以看到背光使用的 PWM 网络标号是
“BLT_PWM”。








如下图所示,“BLT_PWM”和“GPIO_8”接到了一起。














在核心板原理图中搜索“GPIO_8”,可以查到对应的这个网络标号对应的 PAD 为
“GPIO1_IO08”,如下图所示。






2.2 设备树文件分析和修改
在内核源码目录下,打开“arch/arm/boot/dts/imx6ul-14x14-evk.dts ”设备树文件,
在其中搜索“GPIO1_IO08”,如下图所示,管脚已经配置了。






接着搜索“pinctrl_pwm1”,查看在哪里注册了,如下图所示,可以看到“pwm1”中
调用了。


接着搜索“pwm1”,可以看到 pwm1 在背光驱动中调用了,这里仿照下图,将其注释
掉。






请注意:如果这里注释掉,屏幕将无法使用,如果需要使用屏幕,务必在测试完成之后恢
复原样。
然后重新编译设备树文件,烧写到开发板中。




2.3 pwm0测试
烧写新的镜像之后,在串口控制台中依次输入以下命令:
echo 0 > sys/class/pwm/pwmchip0/export
echo 1 > /sys/class/pwm/pwmchip0/pwm0/enable
echo 1000000 > /sys/class/pwm/pwmchip0/pwm0/period
echo 500000 > /sys/class/pwm/pwmchip0/pwm0/duty_cycle
第一个命令为设置 pwm 输出,跳出 pwm0 目录下的节点;
第二个命令为使能 pwm0;
第三个命令为设置周期;
第三个命令为设置占空比。
最后使用示波器测试下面 R129 电阻,可以看到 pwm 输出。














3 PWM2分析和测试
PWM1 测试因为内核中肯定将时钟和 IO 配置好了,我们只需要将背光设备注释掉就可以
完成测试。本小节介绍 PWM2,更进一步介绍时钟和 IO 配置以及 PWM2 注册。
3.1 datasheet和原理图分析
在 datasheet中,搜索 PWM2,如下图所示,可以看到“GPIO1_IO09”这个 pad 可以
被配置为 PWM2。










在核心板原理图上,搜索“GPIO1_IO09”,如下图所示,可知网络标号为
“GPIO_9”。






在底板原理图中搜索“GPIO_9”,如下图所示,可以看出它通过 J38 的管脚 5 引出。








通过在原理图中搜索可以发现这个管脚没有接到其它设备上。


3.3 时钟配置
回到内核源码,很明显在“arch/arm/boot/dts/imx6ul-14x14-evk.dts”设备树文件中
没有对 PWM1 进行时钟配置,但是我们在前面测试 PWM1 的时候是能成功的,这表明它一
定在其它地方配置了。
打开设备树文件,查看其包含的头文件,如下图所示,应该是和设备树同一目录目录下的
“imx6ul.dtsi”。








将其打开,搜索“pwm1”,如下图所示。










如上图所示,可以看到 pwm1 中引用了物理地址“0208_0000”,引用时钟 PWM 时钟
配置“IMX6UL_CLK_PWM1”。在最前面介绍 PWM 的时候,其实有提到物理地址,如下图
所示,这里和 datasheet上是一致(肯定一致,不然前面测试一定不行)。










接着看 pwm2,默认定义了,但是没有将 PWM 时钟打开,如下图所示,将两个
“IMX6UL_CLK_DUMMY”修改为“IMX6UL_CLK_PWM2”。








至此 PWM2 的时钟配置完成,其它 PWM 时钟也可以依照这样的方式,在这个文件中打
开时钟或者新增,新增的话,要注意其中的中断号,PWM1 为 83,PWM2 为 84,依次类
推,仿照着来就成。


3.4 管脚配置和设备注册
前一小节介绍了时钟配置,回到“arch/arm/boot/dts/imx6ul-14x14-evk.dts”设备树
文件,先搜索“PWM2”和“pwm2”,这里搜索 PWM2 是因为有其它 pad 是可能被配置
为 pwm2,如果有配置配置,则宏定义中一定有 PWM2。搜索发现“PWM2”和“pwm2”
都没有。
然后搜索“GPIO1_IO09”,发现被定义为 SD1 的 reset,直接注释掉,如下图所示。








如下图所示,在 pinctrl_pwm1 后面添加 pinctrl_pwm2,将“GPIO1_IO09”配置为
PWM2 模式。




上图添加的代码如下:
pinctrl_pwm2: pwm2grp {
fsl,pins = <
MX6UL_PAD_GPIO1_IO09__PWM2_OUT 0x110b0
>;
};
接着添加 PWM2 设备注册的代码,如下图所示。








上图添加的代码如下:
&pwm2 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_pwm2>;
status = "okay";
};
至此,时钟,管脚配置,设备注册全部完成。
重新编译烧写到开发板。




3.5 测试
新的镜像烧写之后,依次使用以下命令:
echo 0 > sys/class/pwm/pwmchip1/export
echo 1 > /sys/class/pwm/pwmchip1/pwm0/enable
echo 1000000 > /sys/class/pwm/pwmchip1/pwm0/period
echo 500000 > /sys/class/pwm/pwmchip1/pwm0/duty_cycle
然后使用示波器测试 J38 的管脚 5,可以观察到有脉冲波信号。
剩余的 6 路 PWM 可以按照本文档介绍的思路实现,用户如果有需要,可以自行实现。


转自:http://www.topeetboard.com
<think>好的,用户现在问的是如何入门使用i.MX6ULL学习BSP驱动开发。首先,我需要回顾之前的对话历史,看看用户之前的问题是什么。之前用户问过应该更注重系统理解还是裸机理解,我当时的回答是建议先打好裸机基础,再过渡到系统层面。现在用户可能已经决定开始学习,选择了i.MX6ULL这个具体的平台,所以需要具体的入门指导。 i.MX6ULL是恩智浦的一款应用处理器,常用于嵌入式Linux开发,因此用户可能是在转向嵌入式Linux驱动开发。我需要考虑用户的基础,可能已经具备一定的裸机开发经验,但不确定。不过根据之前的建议,用户可能已经有一定的裸机基础,现在想进入BSP和驱动开发。 首先,用户需要了解i.MX6ULL的基本架构,包括处理器核心、内存管理、外设等。然后,需要搭建开发环境,包括交叉编译工具链、uboot、内核源码,以及根文件系统。接着,学习如何编译和烧写系统镜像,这可能涉及uboot的配置、内核的编译和设备树的编写。 驱动开发部分,用户需要从简单的字符设备驱动开始,逐步掌握GPIO、中断、PWM、ADC等外设的驱动开发。此外,设备树(Device Tree)的使用在i.MX6ULL开发中非常重要,用户需要理解如何通过设备树配置硬件资源,以及如何在内核驱动中解析设备树节点。 调试和优化也是关键部分,用户需要掌握内核日志、使用调试工具如gdb、以及性能分析工具。此外,参考官方文档和社区资源能够帮助用户更快解决问题,比如恩智浦的官方SDK、Linux内核文档和社区论坛。 用户可能遇到的问题包括环境搭建的困难、设备树配置错误、驱动与硬件不兼容等,因此需要提供一些常见问题的解决方法,比如检查设备树节点的兼容性、确保时钟配置正确等。 最后,实践项目是巩固知识的重要部分,建议用户从LED控制、按键中断等简单项目开始,逐步过渡到更复杂的传感器驱动和多媒体应用,最终完成综合性项目,如物联网网关,整合多种外设和通信协议。 需要确保回答结构清晰,分步骤指导,涵盖硬件准备、环境搭建、基础知识、驱动开发步骤、调试方法、资源推荐和项目实践。同时,注意使用用户之前提到的格式要求,比如行内数学公式用$...$,独立公式用$$...$$,但在这个问题中可能涉及较少数学内容,重点放在代码示例和步骤说明上。</think>--- ### **i.MX6ULL BSP驱动开发入门指南** **核心路径**:**硬件认知→环境搭建→驱动开发三部曲(裸机→设备树→内核驱动)→调试与优化**。以下是详细步骤: --- ### 一、**硬件基础准备** #### 1. **关键硬件特性梳理** - **处理器核心**: - ARM Cortex-A7 @ 792MHz - 支持NEON/VFPv4浮点运算 - **内存接口**: - 支持LPDDR2/DDR3/DDR3L(最高512MB) - 注意地址映射关系:`0x8000_0000~0xFFFF_FFFF`为DDR内存空间 - **外设资源**: | 接口类型 | 实例 | |----------------|-------------------------------| | GPIO | 5组GPIO(GPIO1~5)共124引脚 | | PWM | 8路PWM输出(e.g. PWM1~8) | | ADC | 12位精度,8通道(最大1MHz采样)| #### 2. **推荐开发板** - **正点原子Alpha/Mini**: - 配套教程完善,支持Linux+裸机双模式 - 集成LCD、摄像头、以太网等常用外设 - **官方EVK开发板**: - 适合深入研究电源管理、DDR布线等高级课题 --- ### 二、**开发环境搭建** #### 1. **工具链配置** - **交叉编译器**: ```bash # 安装ARM Linux官方工具链 sudo apt install gcc-arm-linux-gnueabihf # 验证版本 arm-linux-gnueabihf-gcc -v # 要求 ≥ 4.9.3 ``` - **源码获取**: - **U-Boot**:`git clone git://git.denx.de/u-boot.git`(分支:`imx_v2016.03_4.1.15_2.0.0_ga`) - **Linux内核**:`git clone https://github.com/Freescale/linux-fslc.git`(分支:`5.10-2.1.x-imx`) #### 2. **构建系统镜像** - **编译U-Boot**: ```bash make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- mx6ull_14x14_evk_defconfig make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j8 ``` - **内核配置**: ```bash make ARCH=arm imx_v7_defconfig # 使用默认配置 make ARCH=arm menuconfig # 自定义驱动选项 ``` --- ### 三、**驱动开发三步走** #### 阶段1:裸机驱动实践(2-4周) - **目标**:理解硬件寄存器级操作 - **实验案例**:GPIO中断控制LED ```c // 寄存器地址定义 #define GPIO1_BASE 0x0209C000 #define GPIO1_GDIR *(volatile uint32_t *)(GPIO1_BASE + 0x04) #define GPIO1_ISR *(volatile uint32_t *)(GPIO1_BASE + 0x14) void gpio1_irq_handler() { if(GPIO1_ISR & (1<<3)) { // 检测GPIO1_IO03中断 GPIO1_ISR |= (1<<3); // 清除中断标志 LED_TOGGLE(); // 翻转LED状态 } } ``` - **调试技巧**: - 使用J-Link调试器单步执行,观察`GPIOx_GDIR`寄存器位变化 - 逻辑分析仪抓取GPIO电平变化(验证中断响应时间是否≤5μs) #### 阶段2:设备树(DTS)精通(1-2周) - **核心语法**: ```dts // 示例:配置UART4引脚(设备树片段) &iomuxc { pinctrl_uart4: uart4grp { fsl,pins = < MX6UL_PAD_UART4_TX_DATA__UART4_DCE_TX 0x1b0b1 MX6UL_PAD_UART4_RX_DATA__UART4_DCE_RX 0x1b0b1 >; }; }; &uart4 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_uart4>; status = "okay"; }; ``` - **关键验证**: - 编译后检查`dtc -I dtb -O dts -o test.dts test.dtb`反编译结果 - 内核启动日志中搜索`OF: [device tree]`确认解析正确性 #### 阶段3:Linux内核驱动开发(4-8周) - **字符设备驱动框架**: ```c static int mydrv_open(struct inode *inode, struct file *filp) { // 1. 映射寄存器地址 regs = ioremap(0x0209C000, 4096); // GPIO1物理地址 // 2. 配置GPIO方向 writel(0x00000008, regs + 0x04); // 设置GPIO1_IO03为输出 return 0; } static struct file_operations mydrv_fops = { .owner = THIS_MODULE, .open = mydrv_open, .write = mydrv_write, }; ``` - **进阶内容**: - 实现`ioctl`接口进行PWM占空比调节 - 使用`regmap`框架操作I2C/SPI外设寄存器 --- ### 四、**调试与性能优化** #### 1. **内核级调试手段** - **动态打印**: ```c pr_debug("GPIO state: 0x%x\n", readl(regs)); // 需开启CONFIG_DYNAMIC_DEBUG echo -n 'file mydrv.c +p' > /sys/kernel/debug/dynamic_debug/control ``` - **Oops分析**: - 使用`arm-linux-gnueabihf-objdump -d vmlinux > disasm.txt`反汇编 - 通过`PC`值定位崩溃代码位置(误差±2条指令) #### 2. **性能优化案例** - **DMA传输优化**: - 原始方案:CPU拷贝数据耗时`120μs/MB` - 优化后:配置DMA通道,耗时降至`8μs/MB` ```c dma_cap_zero(mask); dma_cap_set(DMA_SLAVE, mask); chan = dma_request_channel(mask, filter, NULL); // 申请DMA通道 ``` --- ### 五、**学习资源推荐** #### 官方文档: - **《i.MX6ULL Reference Manual》**(重点章节:Chapter 28 GPIO, Chapter 35 IOMUXC) - **《Linux Device Drivers, 3rd Edition》**(配套代码适配4.x内核) #### 实战项目: 1. **综合实验**: - 通过GPIO中断采集按键事件,通过PWM控制电机转速 - 在用户态通过`sysfs`接口调节参数(需实现驱动中的`sysfs_ops`) 2. **高级挑战**: - 移植LVGL图形库到i.MX6ULL的LCD接口 - 实现基于`V4L2`框架的摄像头驱动 --- ### 六、**常见问题排查** #### 1. **驱动加载失败** - **现象**:`insmod`时报`Unknown symbol in module` - **解决方案**: - 检查内核配置是否导出符号(`EXPORT_SYMBOL()`) - 使用`modinfo`确认模块依赖关系 #### 2. **设备树配置错误** - **现象**:内核启动时提示`[drm:imx_drm_bind] *ERROR* failed to find bridge node` - **调试步骤**: 1. 在U-Boot中输入`fdt list /soc/aips-bus@02000000`查看设备树片段 2. 确认`compatible`属性与驱动代码中的匹配字符串一致 --- **学习路线图**: **第1个月**:裸机GPIO/UART驱动 → **第2个月**:设备树配置 → **第3个月**:字符设备驱动 → **第4个月**:参与真实项目开发。坚持**“代码→烧写→测试→调试”循环**,每个实验务必用示波器/逻辑分析仪验证硬件行为。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值