Blog:
NXP iMX7 M4 核心 PWM 驱动开发

Friday, January 11, 2019

简介

在早先的一篇文章已经介绍过基于 NXP iMX7 异构多核架构进行开发调试,本文就延续这一篇文章的介绍,以 PWM 功能为示例着重介绍在 iMX7 多核架构里面的 M4 核心上面开发驱动的方式。

而本文所演示的 Arm 平台同样来自于 Toradex  基于 NXP iMX7 Arm 处理器的 Colibri iMX7 Arm 嵌入式平台。

准备

a). Colibri iMX7S Arm 核心版配合Colibri Evaluation Board,分别连接 A 7核心默认调试串口 UART1(载板X27)和 M4 核心默认调试串口 UART2(载板 X25 上)到开发主机方便调试,另外由于 iMX7S 只支持一个 USB 接口,需要通过载板 X30 连接一个 USB Hub 后来扩展键盘鼠标外设。更多关于 Colibri iMX7 的说明请参考 DatasheetLinux 开发上手指南

b). Colibri iMX7 A7 核心系统使用 Toradex 官方发布的 Embedded Linux,更新方法请参考这里

c). 另外,由于本文演示示例使用到了载板上面 PWM 驱动 LED 和按键资源,需要连接如下:

X10 SODIMM-28 -> X21 LED1

X10 SODIMM-133 -> X21 SW6

d). SEGGER J-Link 仿真器,USB 一端连接开发主机,JTAG 一端连接载板 X13。

Colibri iMX7 M4核心FreeRTOS基本资料

a). Colibri iMX7 架构基本说明请参考如下:

https://developer.toradex.cn/knowledge-base/freertos-on-the-cortex-m4-of-a-colibri-imx7

b). 本示例中 M4 核心运行 FreeRTOS v8 系统,相关的源代码和 sample 程序请从下面git下载:

http://git.toradex.cn/cgit/freertos-toradex.git/

c). 基本的 SDK 配置和编译请参考如下:

https://developer.toradex.cn/knowledge-base/freertos-on-the-cortex-m4-of-a-colibri-imx7#Linux_support

d). 编译好的 M4 firmwar e如何在 Colibri iMX7上面加载运行请参考如下:

https://developer.toradex.cn/knowledge-base/freertos-on-the-cortex-m4-of-a-colibri-imx7#Running_a_Firmware_on_CortexM4

e). 几个自带的 sample 代码简单说明请参考如下:

https://developer.toradex.com/knowledge-base/freertos-on-the-cortex-m4-of-a-colibri-imx7#Examples

Colibri iMX7 M4 核心 FreeRTOS PWM 驱动开发

a). 在上一章节中提到的 iMX7 M4 FreeRTOS 源代码中,已经包含了一些接口的驱动示例,比如 GPIO,UART,I2C,Flexcan 等,但并没有包含 PWM 部分,因此我们需要手动添加 PWM 驱动。

b). 首先我们要找到提供 iMX7 芯片核心寄存器定义的 macro code 文件,获取 PWM 相关寄存器定义以及做细微调整。

platform/devices/MCIMX7D/include/MCIMX7D_M4.h

这个文件是整个 iMX7 M4 FreeRTOS 代码最核心的文件之一,里面定义了所有芯片寄存器 macro code,具体的寄存器功能说明需要参照 NXP iMX7 Reference Manual 文档。

在这个文件里面,如下 ”PWM Peripheral Access Layer”开始的部分定义了PWM相关的寄存器,是最关键的部分。

-- PWM Peripheral Access Layer

/** PWM - Register Layout Typedef */
typedef struct {
__IO uint32_t PWMCR; /**< PWM Control Register, offset: 0x0 */
__IO uint32_t PWMSR; /**< PWM Status Register, offset: 0x4 */
__IO uint32_t PWMIR; /**< PWM Interrupt Register, offset: 0x8 */
__IO uint32_t PWMSAR; /**< PWM Sample Register, offset: 0xC */
__IO uint32_t PWMPR; /**< PWM Period Register, offset: 0x10 */
__I uint32_t PWMCNR; /**< PWM Counter Register, offset: 0x14 */
} PWM_Type, *PWM_MemMapPtr;

在这里,为了后面PWM驱动配置方便,我们做了如下patch

https://github.com/simonqin09/iMX7_M4_PWM_Driver/blob/master/MCIMX7D_M4.patch

c). 然后是关于 CCM(Clock Control Module)驱动配置头文件,添加PWM所需要的clock源

platform/drivers/inc/ccm_imx7d.h

如下patch,增加 PWM 所需 clock gate

https://github.com/simonqin09/iMX7_M4_PWM_Driver/blob/master/ccm_imx7d.patch

d). 接下来就是在 ”plaftform/drivers/inc” 和 ”platform/drivers/src” 下分别增加 PWM 驱动头文件 ”pwm_imx.h” 和源文件 ”pwm_imx.c”,完成PWM相关基本寄存器的读写操作等基本功能函数的实现。

pwm_imx.h 文件代码如下

https://github.com/simonqin09/iMX7_M4_PWM_Driver/blob/master/pwm_imx.h

pwm_imx.c 文件代码如下

https://github.com/simonqin09/iMX7_M4_PWM_Driver/blob/master/pwm_imx.c

Colibri iMX7 M4 核心 FreeRTOS PWM 驱动应用示例

a). 在上面章节基本驱动配置好之后,我们就可以调用驱动进行示例开发了。本文就简单演示通过一个 GPIO 按键来动态调整 PWM 输出占空比的示例。本示例所使用的 GPIO Key 为 examples里面已经配置的 ” BOARD_GPIO_KEY_CONFIG”,PWM 使用为 PWM2。

b). 首先进入 “examples/imx7_colibri_m4” 目录,对几个基本文件进行修改适配

board.h – 这个文件定义了当前 examples 下所有示例所涉及到的接口,中断,clock 等定义,因此需要将 PWM2 相关定义添加进来,如下面 patch。

https://github.com/simonqin09/iMX7_M4_PWM_Driver/blob/master/board.patch

pin_mux.h 和 pin_mux.c – 定义了除了GPIO之外的所有示例所涉及的接口功能的对应管脚的 Pin Mux 配置,这里我们将 PWM2 的管脚配置添加进来,如下面 patch。GPIO 管脚的 Pin Mux 配置在 gpio_pins.h/gpio_pins.c 中定义。

https://github.com/simonqin09/iMX7_M4_PWM_Driver/blob/master/pin_mux.patch

c). 然后再创建 ”pwm_imx” 目录,为了方便,可以复制同一目录下的 gpio_imx 目录后进行修改。

hardware_init.c – 硬件初始化,board,GPIO/PWM RDC/Clock 等,代码如下

https://github.com/simonqin09/iMX7_M4_PWM_Driver/blob/master/pwm_imx/hardware_init.c

main.c – 主程序文件,包含三个子程序和 main 主程序,三个子程序分别负责 GPIO 初始化,GPIO Ke y按键响应处理以及 PWM 中断 Handler,main 主程序完成了对 GPIO 和 PWM 初始化配置后,在每次按键的时候将 PWM 输出占空比从 25%-50%-75% 之间循环,具体代码如下:

https://github.com/simonqin09/iMX7_M4_PWM_Driver/blob/master/pwm_imx/main.c

最后修改 “armgcc/CMakeLists.txt” 文件,将所有新创建的文件包含进去,然后进行编译,具体内容如下:

https://github.com/simonqin09/iMX7_M4_PWM_Driver/blob/master/pwm_imx/armgcc/CMakeLists.txt

对 iMX7 M4 FreeRTOS 代码进行 debug 的方法请参考这里,本文就不再赘述。

Colibri iMX7 M4 PWM驱动示例部署

a). 在部署之前,首先需要确保将本文所使用的 PWM2 从 iMX7 A7 核心 Linux device tree 中 disable,以免发生资源冲突。有两种方法如下:

参考这里下载 A7 Linux kernel 源代码,再参考这里修改 device tree 后重新编译部署。

可以直接在uboot中通过 ”fdt_fixup” 环境变量来临时禁止某个外设

/* read device tree file and print details */
# ubi part ubi
# ubi read ${fdt_addr_r} dtb
# fdt addr ${fdt_addr_r}
# fdt list
/* find PWM2 related setting */
# fdt list /soc/aips-bus@30400000/pwm@30670000
/* set fdt_fixup variable with UARTB and PWM2 disable */
# setenv fdt_fixup ‘fdt addr ${fdt_addr_r} && fdt rm /soc/aips-bus@30800000/spba-bus@30800000/serial@30890000 &&
fdt rm /soc/aips-bus@30400000/pwm@30670000’

b). 然后就可以参考上面的相关文档或者之前的文章进行加载 M4 firmware 运行了

程序开始运行,如下示波器测量数据所示,PWM2 输出周期为 500ms(周期来自 main 主函数文件里面的配置),占空比为 25%,从 LED 等可以看到亮的时间比灭的时间较短。

然后按动载板按键 SW6一次,PWM2 输出周期不变,占空比会变成50%。

再次按动载板按键 SW6一次,PWM2 输出周期不变,占空比会变成75%。

以后每次按键都会循环上述过程。

总结

如上述示例,iMX7 M4 核心可以非常方便的开发外设驱动并进行调用,尤其是基于 FreeRTOS,相对于直接配置寄存器就更直观写,代码也更具备灵活性和重用性。

Author: 秦海,技术销售工程师,韬睿(上海)

Leave a comment

Please login to leave a comment!
Have a Question?