tag 标签: iMX8

相关博文
  • 热度 1
    2024-11-29 15:29
    147 次阅读|
    0 个评论
    By Toradex胡珊逢 简介 嵌入式领域的部分应用对安全、可靠、实时性有切实的需求,在诸多实现该需求的方案中,QNX 是经行业验证的选择。在 QNX SDP 8.0 上 BlackBerry 推出了 QNX Everywhere 项目,个人用户可以出于非商业目的免费使用 QNX 操作系统。得益于 Toradex 和 QNX 的良好合作伙伴关系,用户能够在 Apalis iMX8QM 和 Verdin iMX8MP 模块上轻松测试和评估 QNX 8 系统。下面将基于 Apalis iMX8QM 介绍如何运行 QNX。 下载 QNX 首先,在QNX 网站上注册帐号,待审核通过后,根据提示在License Manager页面将授权部署到自己的帐号上。接下来下载QNX Software Center,这里建议使用 Linux Host 本版。 安装完 QNX Software Center 后,启动 QNX Software Center 点击 Add Installation。 分别选择 QNX Momentics IDE 和 QNX Software Development Platform 8.0。 在 QNX Software Center 中点击 Install New Packages。 并在 Availables 标签页中选择本次演示使用 Apalis iMX8QM 设备。 编译 QNX BSP Import,在 QNX 文件夹中选择 QNX Source Package and BSP。 然后点击下面的 Browse for ZIP Archive。具体的路径取决于之前选择的安装目录,例如 /home/ben/qnx800/bsp 下的 BSP_apalis-imx8qm_br-hw-rel_be-800_SVN989187_JBN69.zip 是适用于 Apalis iMX8QM 的 BSP 文件。 导入 BSP 后,在 IDE 的项目浏览窗口中就可以编译该 BSP 所需的所有文件。这些文件和目录的具体说明可以参考QNX 的网页。 在 IDE 中右击该项目文件夹,然后点击 Build Project。期间在下方的 Console 标签页面会显示完整的编译过程。 当编译结束后,在项目的 image 文件下即会出现一个 zip 压缩包。 在安装前还需要进行简单的修改。解压 zip 压缩包后,在 image.json 文件中 filelist 添加 IMX-DTB 。 "name" : "mmcblk0" , "partitions" : , 下载Apalis-iMX8_Reference-Multimedia-Image-Tezi_5.7.6+build.29.tar,解压 Reference-Multimedia-Image-apalis-imx8.bootfs.tar.xz。根据实际使用 Apalis iMX8QM 和 Ixora 硬件版本,找到对应的 dtb 文件将其重命名为 IMX-DTB,并放到上面 image.json 所在的目录。最后在 Apalis iMX8QM 上使用 Toradex Easy Installer 进行安装。 QNX BSP 安装完成后,启动时在调试串口中按 E ,就可以继续加载 QNX 系统。 Welcome to QNX Initial Program Loader for Toradex Apalis i .MX8QM (Rev B ) SoM (ARM Cortex-A53/A72) SCFW build version: 4612 , SCFW commit: 732e719a SECO version: 3.6 .2 , commit: 732e719a ATF commit: 2fa8c63 Command: Press 'D' for serial download, using the 'sendnto' utility Press 'M' for eSDC download, IFS filename MUST be 'QNX-IFS' Press 'E' for eMMC download, IFS filename MUST be 'QNX-IFS' eMMC download... load image done . Found image @ 0 x88000000 Loading FDT @ 0x80400000 Jumping to startup @ 0 x80800800 ARM trusted firmware is enabled Hypervisor support disabled board_smp_num_cpu: 6 cores MMU: 16 -bit ASID 40 -bit PA TCR_EL1= 00000012 b 5183519 ARM GIC-500 r1p1, arch v3.0 detected board_smp_num_cpu: 6 cores board_smp_num_cpu: 6 cores 调试 QNX 应用程序 QNX Project,选择 C/C++ 类型中的 QNX Executable 项目模板。 Apalis iMX8QM 采用的是 64bit SoC,所以在 CPU Variant 中选择 aarch64le 构架。 在该项目文件夹上右击 Build Project 即可编译。完成后在 build/aarch64le-debug 目录下生成编译好的可执行二进制文件。 开始调试之前,需要知道运行 QNX 8 的 Apalis iMX8QM 的 IP 地址。在调试终端输入 ifconfig 命令后可以在 ffec0 接口中看到自动获取的 IP。默认的 QNX 8 采用随机 MAC 地址,所以每次重启后自动获取的 IP 将会发生变化。 # ifconfig ffec0: flags=8843 metric 0 mtu 1500 options = 80008 ether 62:73:64:54 : 6 c: 85 inet6 fe80::cf96: 1 b48:a747:aff1%ffec0 prefixlen 64 scopeid 0x5 inet6 fdcf: 4 b94: 78 d4: 0 :fdbd :f8e7 :dce3 : 81ed prefixlen 64 autoconf inet6 fdcf: 4 b94: 78 d4:: 274 prefixlen 128 inet 192.168.3.196 netmask 0xffffff00 broadcast 192.168.3.255 media: Ethernet autoselect (1000baseT ) status : active nd6 options= 1 IDE 和设备上运行的 qconn 代理建立 IP 连接,从而实现应用程序的调试、监控和分析。qconn 在 QNX 的 buildfile 中默认已经添加,并开机自动运行。在调试终端里运行下面命令可以查看运行情况,默认监听 8000 端口。 # pidin | grep qconn114714 1 usr/sbin/qconn 10r SIGWAITINFO 114714 2 usr/sbin/qconn 10r RECEIVE C/C++ QNX Application。 在弹出的对话框中点击下方的 New QNX Target 添加需要调试的设备。 输入 Apalis iMX8QM 的 IP 地址。然后选中添加的设备,并点击 OK。 然后 IDE 会进入调试界面,在这里可以进行调试操作如单步运行。 总结 文章介绍了如何借助 QNX Everywhere 项目在 Apalis iMX8QM 使用 QNX 系统。这里主要涉及 QNX 开发环境安装、配置和应用开发说明,关于 QNX OS 定制、应用集成等请参考 QNX 官方资料,为您的项目选择最合适方法。
  • 热度 11
    2023-4-19 17:50
    1360 次阅读|
    0 个评论
    B y Toradex 胡珊逢 Apalis iMX8 计算机模块的数字音频接口 SAI ( Synchronous Audio Interface )可以配置为 AC97 、 I2S 格式,用于连接外部音频编解码器。文章接下来将介绍在 Linux BSP v6 上如何扩展第二路 SGTL5000 。 iMX8 处理器具有多路 SAI 通道, SAI1 已经被模块片上的 SGTL5000 使用, SAI0 通道引出到模块金手指上,并且是兼容 Apalis 标准数字音频接口, 该 通道在基于其他 CPU 的 Apalis 模块也可以直接使用。因此,我们选择 SAI0 扩展外部 SGTL5000 。 SGTL5000 面向 iMX8 处理器的接口主要是 I2S 和时钟信号。 Apalis iMX8 的 SAI0 通道可以直接连接 SGTL5000 的 I2S 接口。但是 MXM3_194 引脚上没有时钟信号。对于外部音频编解码器如果需要时钟输入,如 SGTL5000 的 SYS_MCLK ,可以选择 MXM3_215 引脚,或者采用外部时钟源,如晶振。 SGTL5000 在 master mode 时可以向 Apalis iMX8 输出 I2S_LRCLK 和 I2S_SCLK 信号。 当 SYS_MCLK = SupportedRates * Fs , I2S_LRCLK 可以和 SYS_MCLK 同步。如果无法满足, SGTL5000 则会使用内部的 PLL 产生符合音源的 I2S_LRCLK 频率。 PLL 的使用会增加 额外的功耗。 PLL 的时钟输入也来自 SYS_MCLK ,可以支持 8.0 到 27MHz 频率。 外部 SGTL5000 原理图如下,其中使用一个 12.28MHz 的外部有源晶振。 接下来修改 device tree 添加 SGTL5000 的相关配置。 imx8-apalis-v1.1.dtsi 的 I2C3 节点添加 SGTL5000 的 I2C 配置。 --------------------------------------- /* Apalis I2C3 (CAM) */ &i2c3 { #address-cells = ; #size-cells = ; clock-frequency = ; pinctrl-names = "default"; pinctrl-0 = ; status = "okay"; external_sgtl5000: audio-codec@a { #sound-dai-cells = ; compatible = "fsl,sgtl5000"; reg = ; //micbias-resistor-k-ohms = ; micbias-voltage-m-volts = ; VDDA-supply = ; VDDIO-supply = ; VDDD-supply = ; clocks = ; }; }; --------------------------------------- SGTL5000 使用外部的电源供电,所以也需要添加 VDDA-supply , VDDIO-supply 和 VDDD-supply 。 --------------------------------------- reg_ex_auido_3v: regulator-ex-audio-3v { compatible = "regulator-fixed"; regulator-name = "ex-audio-3V"; regulator-min-microvolt = ; regulator-max-microvolt = ; regulator-always-on; }; reg_ex_auido_1v8: regulatorex-audio-1v8 { compatible = "regulator-fixed"; regulator-name = "+V1.8"; regulator-min-microvolt = ; regulator-max-microvolt = ; }; --------------------------------------- 以及外部时钟定义。 --------------------------------------- ex_audio_clk: sgtl5000_12M { compatible = "fixed-clock"; #clock-cells = ; clock-frequency = ; }; --------------------------------------- 在原有的 sound 节点后再增加一个 外部 SGTL5000 的 sound_external 。 --------------------------------------- sound_external { compatible = "simple-audio-card"; simple-audio-card,bitclock-master = ; simple-audio-card,format = "i2s"; simple-audio-card,frame-master = ; simple-audio-card,name = "external-sgtl5000"; simple-audio-card,cpu { sound-dai = ; }; dailink_master_external: simple-audio-card,codec { sound-dai = ; system-clock-frequency = ; }; }; --------------------------------------- 配置 sai0 节点。 --------------------------------------- &sai0 { assigned-clocks = , , , ; assigned-clock-rates = , , , ; pinctrl-names = "default"; pinctrl-0 = ; #sound-dai-cells = ; //fsl,txm-rxs; }; --------------------------------------- 最后在 imx8-apalis-ixora-v1.2.dtsi 里启用 SAI0 。 --------------------------------------- &sai0 { status = "okay"; }; --------------------------------------- 参考 这里 重新编译和部署 device tree 。上面提到的 patch 文件下载 。重新启动后检查外部 SGTL5000 挂载情况。在 I2C-5 通道上已经发现地址为 0x0a 的设备。 --------------------------------------- root@apalis-imx8-06852111:/tmp# i2cdetect -y -r 5 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- UU -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --------------------------------------- 相应的驱动也加载。 --------------------------------------- root@apalis-imx8-06852111:/tmp# dmesg|grep sgtl sgtl5000 3-000a: sgtl5000 revision 0x11 sgtl5000 5-000a: sgtl5000 revision 0x11 --------------------------------------- 检查声卡设备,发现 sysdefault:CARD=externalsgtl500 。 --------------------------------------- root@apalis-imx8-06852111:/tmp# aplay -L null Discard all samples (playback) or generate zero samples (capture) sysdefault:CARD=externalsgtl500 external-sgtl5000, 59040000.sai-sgtl5000 sgtl5000-0 Default Audio Device sysdefault:CARD=apalisimx8qmsgt apalis-imx8qm-sgtl5000, 59050000.sai-sgtl5000 sgtl5000-0 Default Audio Device sysdefault:CARD=imxspdif imx-spdif, S/PDIF PCM snd-soc-dummy-dai-0 Default Audio Device --------------------------------------- 使用 BSP 默认的音频文件播放。 --------------------------------------- root@apalis-imx8-06852111:/tmp# aplay -D sysdefault:CARD=externalsgtl500 ~/sound/Gong.wav --------------------------------------- 如果音量小的话,使用 alsamixer 调整。按 F6 选择外部 SGTL5000 。 Gong.wav 是一个采样率 44.1KHz , 16bit 双声道文件,比特率 =16*2*44.1K=1.4MHz 。如下面示波器 测量 显示, CH1 是 LRCLK , CH2 是 SCLK 。 SGTL5000 在播放时会根据音源文件调整工作参数,例如时钟, PLL 工作状态。可以通过 cat /sys/kernel/debug/regmap/5-000a/registers 命令查看寄存器配置。由于 SGTL5000 的已经被其驱动占用,所以无法使用 i2cget 读取寄存器。 例如寄存器 CHIP_CLK_CTRL 0x0004 的值为 0007 。 bit3:2=0x01 ,表示采样频率为 44.1KHz 。 Bit 1:0 = 0x3 ,表示使用 PLL 。这是由于 44.1KHz 信号无法通过 12.28MHz 的 256 、 384 或 512 倍分频得到,所以只能使用 PLL 产生。 外部 SGTL5000 的录音功能可以使用下面命令。 --------------------------------------- root@apalis-imx8-06852111:/tmp# arecord -D hw:0,0 -V mono -c 2 -f S16_LE -r 44100 -t wav mic.wav --------------------------------------- 其中 hw:0,0 可以 aplay -l 命令查看对应声卡的 card, subdevice 序号。 --------------------------------------- root@apalis-imx8-06852111:/tmp# aplay -l **** List of PLAYBACK Hardware Devices **** card 0: externalsgtl500 , device 0: 59040000.sai-sgtl5000 sgtl5000-0 Subdevices: 1/1 Subdevice #0: subdevice #0 --------------------------------------- 总结 Apalis iMX8 的数字音频接口可以非常方便地扩展音频编解码器,具体的引脚分配、 device tree 配置等需要结合所使用的音频编解码器,有些可能会十分简单,如 MAX98357A ,其甚至不需要 I2C 和 SYS_MCLK 就可以直接工作。 Apalis iMX8 所使用的 Linux kernel 源码中有非常多的示例可供用户参考。
  • 热度 8
    2023-4-7 16:02
    609 次阅读|
    0 个评论
    为了能够让更多工程师朋友了解多核异构处理器,飞凌嵌入式特别推出了【玩转多核异构】专题,帮助大家解决在多核异构处理器的开发过程中遇到的问题。专题持续更新中,欢迎您的订阅关注。 SPI(串行外围设备接口)是一种低成本、易使用的接口协议,具备全双工、高速、通讯简单的特点,被广泛应用于微控制器和外围设备芯片之间的通讯。当SPI接口作为主模式时可以连接Flash存储器、AD采样芯片、实时时钟RTC、LCD显示屏、音频芯片以及各种传感器。 随着产品功能的愈加丰富,多处理器使用SPI接口进行通讯的场景开始出现,而多个SPI设备之间通信必须由主设备(Master)来控制从设备(Slave)。小编手上的OKMX8MP-C开发板基于NXP i.MX8M Plus多核异构处理器设计,它的M核有1路SPI,因而为实现SPI的相互通讯,我们就需要两块OKMX8MP-C开发板的SPI互作主从设备进行通信。本文小编就将从应用角度为大家讲解M核SPI间通讯的实现方式。 01 SPI主模式 SPI初始化 SPI初始化主要包括总线时钟、管脚和相应寄存器的初始化。具体如下: (1)SPI总线时钟:现将SPI总线倍频到800MHz,再10分频到80MHz。 CLOCK_SetRootMux(kCLOCK_RootEcspi2, kCLOCK_EcspiRootmuxSysPll1); //SPI2总线时钟使用PLL1-800MHz CLOCK_SetRootDivider(kCLOCK_RootEcspi2, 2U, 5U); //分频因子为2*5=10,设置SPI2总线时钟为80MHz (2)管脚配置:选择SPI2的四个管脚。 IOMUXC_SetPinMux(IOMUXC_ECSPI2_MISO_ECSPI2_MISO, 0U); // SPI2-MISO IOMUXC_SetPinMux(IOMUXC_ECSPI2_MOSI_ECSPI2_MOSI, 0U); // SPI2-MOSI IOMUXC_SetPinMux(IOMUXC_ECSPI2_SCLK_ECSPI2_SCLK, 0U); // SPI2-SCLK IOMUXC_SetPinMux(IOMUXC_ECSPI2_SS0_ECSPI2_SS0, 0U); // SPI2-SSO (3)SPI速率:设置速率为500K。 define TRANSFER_BAUDRATE 500000U // 速率 500K (4)数据长度选择:8bit。 burstLength = 8; // 数据长度 8bit (5)四种模式选择:CPOL和CPHA的四种组合即为SPI的四种模式。 clockInactiveState = kECSPI_ClockInactiveStateLow; // 时钟SCL: 活动时低电平,空闲时高电平 dataLineInactiveState = kECSPI_DataLineInactiveStateLow;// 数据MOSI&MISO: 活动时低电平,空闲时高电平 chipSlectActiveState = kECSPI_ChipSelectActiveStateLow;// 片选SS: 低电平选中,高电平无效 polarity = kECSPI_PolarityActiveHigh; // 时钟信号极性,即CPOL为0的话 SCLK高电平有效(空闲的时候为低电平),为1的话SCLK低电平有效(空闲的时候为高电平)。 phase = kECSPI_ClockPhaseFirstEdge; // 时钟相位,即CPHA为0的话串行时钟的第一个跳变沿(上升沿或下降沿)采集数据,为1的话串行时钟的第二个跳变沿(上升沿或下降沿)采集数据。 (6)主模式选择:设置SPI为主模式。 channelConfig.channelMode = kECSPI_Master; // 主模式 (7)通道选择:一个 SPI 有四个硬件片选信号,每个片选信号是一个硬件通道,本程序选择通道0。 channel = kECSPI_Channel0; // 通道0 (8)关闭自回环:如果开启了自回环,那么SPI数据会在芯片内回环,不会到外部管脚,在程序调试时可以排除外部端子的干扰,但真实应用时,需要关闭自回环,从外部管脚收发数据。 enableLoopBack = false; // 不回环,使用外部管脚 SPI收发流程 我们分别将两块OKMX8MP-C开发板命名为开发板1和开发板2,并且将开发板1的SPI接口采用主模式,使能收发中断;将开发板2的SPI接口采用从模式,使能收发中断。 SPI主发送64字节数据,SPI从接收后,将数据回传。SPI主接收回传信息后,比对接收和发送的数据是否一致,输出比对结果。如一致,本次传输结束,等待输入任何按键启动下一次传输。 (1)SPI发送数据:EXAMPLE_ECSPI_MASTER_BASEADDR 表示为SPI2,g_m_handle为SPI实例,包含了发送接收中断及其回调函数,masterXfer为要发送的64字节数据。 ECSPI_MasterTransferNonBlocking(EXAMPLE_ECSPI_MASTER_BASEADDR, &g_m_handle, &masterXfer); //主模式中断方式发送数据 (2)SPI接收数据:SPI总线的发送和接收都是主模式控制的,因此接收函数的过程和发送是一致的。 (3)接收和发送数据对比: for (i = 0U; i < TRANSFER_SIZE; i++) { if (masterTxData != masterRxData ) { errorCount++; } } 02 SPI从模式 SPI初始化 SPI从模式初始化与主模式要保持一致,除了将工作模式设为从模式,其他设置均一样。主从模式选择:设置SPI为从模式。 channelConfig.channelMode = kECSPI_Slave; //从模式 SPI收发流程 开发板2的SPI接口采用从模式,使能收发中断。 SPI从进入等待接收状态,在片选有效后,通过接收中断获取数据,并回传信息,再次进入接收状态。 (1)SPI接收数据:EXAMPLE_ECSPI_SLAVE_BASEADDR表示为SPI2,g_m_handle为SPI实例,包含了发送接收中断及其回调函数,slaveXfer存储接收的数据。 ECSPI_SlaveTransferNonBlocking(EXAMPLE_ECSPI_SLAVE_BASEADDR, &g_s_handle, &slaveXfer); //从模式中断方式接收数据 (2)SPI发送数据:SPI总线的发送和接收都是主模式控制的,因此接收函数的过程和发送是一致的。 03 A核修改 A核设备树中若保留SPI2,内核解析设备树,在/dev下生成设备文件spidev1.0。这样待M核运行后,A核将重新对SPI2初始化,造成M核SPI功能异常,因此需要去除A核对SPI的控制。 修改设备树 (1)在设备树OK8MP-C.dts中,删除SPI2设备节点相关信息。 &ecspi2 { #address-cells = ; #size-cells = ; fsl,spi-num-chipselects = ; pinctrl-names = "default"; pinctrl-0 = ; cs-gpios = ; status = "okay"; spidev1: spi@0 { reg = ; compatible = "rohm,dh2228fv"; spi-max-frequency = ; }; }; pinctrl_ecspi2: ecspi2grp { fsl,pins = ; }; pinctrl_ecspi2_cs: ecspi2cs { fsl,pins = ; }; (2)编译生成新的内核镜像Image及设备树OK8MP-C.dtb。 (3)将生成的OK8MP-C.dtb和Image拷贝至开发板/run/media/mmcblk2p1/目录下,输入sync命令,重启开发板。 (4)输ls /dev查看发现没有SPI2设备文件spidev1.0。 04 程序验证 硬件连接 使用杜邦线将两块OKMX8MP-C开发板的SPI一一对应连接,线序如下: M核程序 修改uboot环境变量设置M核自启动,同时将M核程序forlinx_m7_tcm_firmware.bin 【玩转多核异构】M核程序的启动、编写和仿真。 实际测试 (1)开发板2先上电,M核程序启动,完成SPI初始化后,进入接收等待状态; (2)开发板1后上电,M核程序启动,完成SPI初始化后,主动发送64字节数据; (3)开发板2的SPI接收数据,通过串口打印接收的数据,并将接收的数据再次发送; (4)开发板1的SPI接收到回传信息,通过串口打印接收的数据。和发送数据比对,输出结果。 (5)此时在开发板1调试串口输入任意键,即可开启新一轮的SPI发送和接收流程。 以上就是小编为小伙伴带来的OKMX8MP-C开发板M核控制SPI主从模式的使用方法了,是不是感觉性能很强大呢?
  • 热度 2
    2023-3-1 14:46
    1516 次阅读|
    0 个评论
    B y Toradex 秦海 1). 简介 为了提高处理器的设计灵活性和可用性, NXP 的所有 i.MX 系列处理器都配备了基于 IOMUX Controller (IOMUXC) 和 IOMUX 来使能 Pin Mux 功能,使得一个特定的 IO 管脚可以选择不同的可能多达 8 种的功能定义模块 (ALT0, ALT1, ALT2, ALT3 ... ) ,同时为了适配不同的功能模块, IOMUXC 可以对应配置管脚的配置参数(比如上拉 / 下拉,驱动能力等等)。本文就基于 NXP 最新的 i.MX8 系列平台说明 Pin Mux 的定义和配置方式。 本文所演示的平台来自于 Toradex Apalis iMX 8 嵌入式平台,这个平台是基于 近年发布的 NXP iMX 8 系列 ARM 处理器,核心为 Cortex-A 72/A53 。 2. 准备 a). Apalis iMX8 ARM 核心版配 合 Apalis Eva Board 载板, 并连接调试串口用于测试 。 b). 参考 这里 下载 Toradex Ycoto Linux BSP5 Linux Kernel (toradex_5.4-2.3.x-imx 分支 ) 用于后续 Device Tree 修改和编译。 3). 规划管脚功能定义 a). 参考 Apalis iMX8 datasheet 文档 4.4 SoC Functions List 章节来找到所需要的 iMX8 管脚的功能定义和默认状态,比如这里我们就用 X1 Pin 6 作为示例,其基本信息如下图,有 4 个功能模块定义,目前在 Toradex Ycoto Linux Device Tree 中默认配置功能是黄色高亮显示的 ALT1 PWM 功能, Reset Sate 参考 datasheet 4.3 Pin Reset Status 章节定义是 Pull-Down (Input) 状态。 b). Device Tree 中一个管脚的 IOMUX 定义由两部分组成,如下是上述管脚 X1 Pin 6 在 Devcie tree 中作为 PWM 功能的管脚 Pin mux 定义作为参考 -------------------------------- /* Apalis PWM3 */ pinctrl_pwm0: pwm0grp { fsl,pins = < IMX8QM_UART0_RTS_B_LSIO_PWM0_OUT 0x00000020 ; }; -------------------------------- ./ fsl,pins 里面的定义就是具体的 Pin mux 定义,包含两部分。第一部分是 PIN_FUNC_ID ,其由 _ 组成,示例中 ” IMX8QM_UART0_RTS_B ” 就是 ,而 ” LSIO_PWM0_OUT ” 就是 ,也就是具体的功能模块定义( ALT1 )。 PIN_FUNC_ID 在 Kernel Device Tree 源代码中通过相应 pinctrl 头文件定义,下面是 NXP iMX8/iMX8x/iMX8MM/iMX8MP 系列处理器对应的头文件位置列表供参考 -------------------------------- Apalis iMX8 - /include/dt-bindings/pinctrl/pads-imx8qm.h Colibri iMX8X - /include/dt-bindings/pinctrl/pads-imx8qxp.h Verdin iMX8M Plus - /arch/arm64/boot/dts/freescale/imx8mp-pinfunc.h Verdin iMX8M Mini - /arch/arm64/boot/dts/freescale/imx8mm-pinfunc.h -------------------------------- ./ 第二部分是管脚的配置参数 (BIT_CONFIG) ,详细的定义需要从对应 SoC 处理器的 Reference Manual 文档 IOMUXD 章节的对应管脚 Pad Control 寄存器说明找到,比如上述示例引脚的相关定义可以从 NXP iMX8QM Reference Manual 9.2.5.1.26 UART0_RTS_B (UART0_RTS_B) 章节找到,如下。 需要注意的是默认情况下 Pin Ctrl 寄存器 29-27bit mux mode 的配置保持 000 即可,因为这部分已经在前面 PIN_FUNC_ID 那里定义了。另外配置参数还有下面两个软件设置状态: -------------------------------- NO_PAD_CTL(1 << 31) - 声明当前管脚无需配置参数 SION(1 << 30) - Software Input On Field ,强制当前管脚 Input Path 而忽略 mux mode 设定的状态 -------------------------------- ./ Kernel Documentation 关于 NXP i.MX 系列处理器的 Pin Mux 的说明可以参考如下 -------------------------------- / Documentation/devicetree/bindings/pinctrl/fsl, * -pinctrl.txt -------------------------------- c ). 基于上述描述,这里要将上述管脚功能定义从 PWM 修改为标准 GPIO ,并将 GPIO 管脚的初始状态设置为下拉( pull down )和高驱动能力( high drive strength ) ./ 查找 pads-imx8qm.h 文件确定所需 PIN_FUNC_ID 为 “IMX8QM_UART0_RTS_B_LSIO_GPIO0_IO22” -------------------------------- #define IMX8QM_UART0_RTS_B_DMA_UART0_RTS_B IMX8QM_UART0_RTS_B 0 #define IMX8QM_UART0_RTS_B_LSIO_PWM0_OUT IMX8QM_UART0_RTS_B 1 #define IMX8QM_UART0_RTS_B_DMA_UART2_RX IMX8QM_UART0_RTS_B 2 #define IMX8QM_UART0_RTS_B_LSIO_GPIO0_IO22 IMX8QM_UART0_RTS_B 3 -------------------------------- ./ 从 iMX8QM Reference Manual UART0_RTS_B Pin Ctrl 寄存器确认所需的 BIT_CONFIG 参数是 0x00000040 4). 修改配置 Device Tree 文件 a). 修改方式由两种,一种是直接在 Kernel 源代码中修改设备对应的 Device Tree 文件源码然后重新编译 Device Tree binary 文件( .dtb) 后部署,另外一种是通过生成 Device Tree Overlay 文件的方式直接部署,无需编译源代码。本文就简单示例通过源代码编译方式,如果需要了解 Device Tree Overlay 方式可以参考如下两个文档 ./ https://developer.toradex.cn/knowledge-base/pin-multiplexing-in-device-tree ./ https://www.toradex.cn/blog/device-tree-overlay-shi-yong ./ https://developer.toradex.cn/knowledge-base/device-tree-overlays-linux b). Device Tree 源代码修改 Patch 如下,分别关闭默认占用 X1 Pin 6 的 PWM 功能,以及重新将 X1 Pin6 配置为 GPIO 通过 iomuxc 输出。另外,具体的 Device Tree 编译和部署可以参考如下文档 ./ https://developer.toradex.cn/knowledge-base/build-u-boot-and-linux-kernel-from-source-code ./ https://developer.toradex.cn/device-tree-customization ./ https://developer.toradex.cn/knowledge-base/device-tree-customization-examples -------------------------------- diff --git a/arch/arm64/boot/dts/freescale/imx8-apalis-eval.dtsi b/arch/arm64/boot/dts/freescale/imx8-apalis-eval.dtsi index 0a4fe3898993..b75c649e706c 100644 --- a/arch/arm64/boot/dts/freescale/imx8-apalis-eval.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8-apalis-eval.dtsi @@ -271,7 +271,7 @@ /* Apalis PWM3, MXM3 pin 6 */ &pwm0 { - status = "okay"; + status = "disabled"; }; /* Apalis PWM4, MXM3 pin 8 */ diff --git a/arch/arm64/boot/dts/freescale/imx8-apalis-v1.1.dtsi b/arch/arm64/boot/dts/freescale/imx8-apalis-v1.1.dtsi index 0ece42889af8..8dfe04714ec7 100644 --- a/arch/arm64/boot/dts/freescale/imx8-apalis-v1.1.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8-apalis-v1.1.dtsi @@ -426,7 +426,7 @@ , , , , , , - ; + , ; apalis-imx8qm { /* Apalis AN1_ADC */ @@ -600,6 +600,13 @@ IMX8QM_MLB_DATA_LSIO_GPIO3_IO28 0x00000021 ; }; + + /* Apalis Pin Mux Demo GPIO9 */ + pinctrl_gpio9: gpio9grp { + fsl,pins = < + IMX8QM_UART0_RTS_B_LSIO_GPIO0_IO22 0x00000040 ; + }; /* Apalis I2C1 */ pinctrl_lpi2c2: lpi2c2grp { -------------------------------- b). 测试部署 Device Tree 文件 ./ 在修改部署之前 X1 Pin 6 管脚的状态可以参考如下文章,通过连接 LED 硬件配合 libgpiod 库进行测试,由于被 PWM 驱动占用因此无论通过 gpioset 如何设置这个管脚,外部 LED 始终是不亮状态没有变化 https://www.toradex.cn/blog/nxp-imx8-qian-ru-shilinux-xialibgpiod-ying-yong-shi-li -------------------------------- ### 系统启动后查看 PWM 驱动状态,管脚对应的 PWM 设备 (5d000000.pwm) 状态正常 ### root@apalis-imx8-07308034:~# cat /sys/kernel/debug/pwm platform/57244000.pwm, 1 PWM device pwm-0 (backlight ): requested enabled period: 6666667 ns duty: 3111111 ns polaritye platform/5d030000.pwm, 1 PWM device pwm-0 ((null) ): period: 2730667 ns duty: 0 ns polarity: normal platform/5d020000.pwm, 1 PWM device pwm-0 ((null) ): period: 2730667 ns duty: 0 ns polarity: normal platform/5d010000.pwm, 1 PWM device pwm-0 ((null) ): period: 2730667 ns duty: 0 ns polarity: normal platform/5d000000.pwm, 1 PWM device pwm-0 ((null) ): period: 2730667 ns duty: 0 ns polarity: normal ### 由于管脚被 PWM 驱动占用,因此启动后 LED 为灭状态,而且无论通过 gpioset 如何设置, LED 始终为灭状态,无法控制 ### root@apalis-imx8-07308034:~# gpioset 0 22=1 root@apalis-imx8-07308034:~# gpioset 0 22=0 -------------------------------- c). 修改部署新的 Device Tree binary “imx8qm-apalis-v1.1-eval.dtb” 后,通过 LED 发现可以正常控制 X1 Pin 6 管脚作为输出的电平状态了 -------------------------------- ### 系统启动后,基于管脚初始状态为 Pull Down ,连接的 LED 灯为灭状态 ### root@apalis-imx8-07308034:~# gpioinfo 0 |grep -e "MXM3_6" line 22: "MXM3_6" unused input active-high ### 查看 PWM 驱动状态,管脚对应的 PWM 设备 (5d000000.pwm) 已经没有了 ### root@apalis-imx8-07308034:~# cat /sys/kernel/debug/pwm platform/57244000.pwm, 1 PWM device pwm-0 (backlight ): requested enabled period: 6666667 ns duty: 3111111 ns polarity: inverse platform/5d030000.pwm, 1 PWM device pwm-0 ((null) ): period: 2730667 ns duty: 0 ns polarity: normal platform/5d020000.pwm, 1 PWM device pwm-0 ((null) ): period: 2730667 ns duty: 0 ns polarity: normal platform/5d010000.pwm, 1 PWM device pwm-0 ((null) ): period: 2730667 ns duty: 0 ns polarity: normal ### 通过如下命令将管脚配置为输出高电平,连接的 LED 灯为亮状态 ### root@apalis-imx8-07308034:~# gpioset 0 22=1 ### 翻转输出为低电平,,连接的 LED 灯为灭状态 ### root@apalis-imx8-07308034:~# gpioset 0 22=0 -------------------------------- ./ 如果将 X1 Pin 6 管脚的 Pin Mux 配置 BIT_CONFIG 参数改为 0x000000 2 0 , 也就是由 Pull Down 改为 Pull Up ,那么实际测试上电启动系统后,连接的 LED 灯为亮状态。 5 ). 总结 本文 基于 NXP iMX8 处理器演示了 Pin Multiplexing 的定义和配置方法,其他 i.MX 处理器也都是类似的思路。
  • 热度 9
    2023-2-23 09:29
    711 次阅读|
    0 个评论
    *为了能够让更多的工程师朋友了解多核异构处理器,飞凌嵌入式特别推出了【玩转多核异构】专题,帮助大家解决在多核异构处理器的开发过程中遇到的问题。【玩转多核异构】专题持续更新中,欢迎您的订阅关注。 引言 凭借实时性、抗干扰性和安全性等优点,CAN2.0在工业及汽车行业得到了广泛应用,但其最高速率仅为1Mbit/s,每帧最多只能传输8字节的有效数据,报文中只有约50%的带宽用于有效数据传输。然而随着产业的发展,各种传感器和控制器数量的增多,总线上的数据量也激增,这使得CAN2.0总线在传输速率和带宽方面的缺点暴露的更加明显,于是就诞生了CAN-FD。 CAN-FD在传输速率和带宽方面有了明显的提升,波特率可高达8Mbit/s,每帧可多达64字节有效数据,传输效率可提高至约80%,能够进一步提高总线的实时性,拓宽总线的数据带宽,提升总线的传输效率。 在飞凌嵌入式OKMX8MP-C开发板上有两路CAN-FD,小编今天就基于这款开发板以处理器的M核与A核各控制一路CAN-FD互相通信为例,从应用角度讲述M核和A核如何控制CAN-FD高速通信。 飞凌嵌入式OKMX8MP-C开发板所搭载的NXP i.MX8M Plus处理器具备强悍的性能,集成4个主频最高可达1.8GHz (工业级主频为1.6GHz)的Arm Cortex-A53多任务核和1个Cortex-M7实时核,不管是对数据的高速吞吐、处理,还是复杂的人机交互界面处理,都能从容应对。 ! (/img/bVbMDQ 01 M核CAN-FD CAN-FD初始化 CAN-FD初始化主要包括总线时钟,管脚和相应寄存器的初始化。具体如下: (1)CAN总线时钟: 现将CAN总线倍频到800MHz,再10分频到80MHz。 CLOCKSetRootMux(kCLOCKRootFlexCan1, kCLOCKFlexCanRootmuxSysPll1); // 设置CAN1总线时钟为800MHz CLOCKSetRootDivider(kCLOCKRootFlexCan1, 2U, 5U); // 分频因子为25=10,设置CAN1总线时钟为80MHz (2)管脚配置: 选择CAN1的发送管脚为32脚,接收管脚为34脚。 IOMUXCSetPinMux(IOMUXCSAI2TXCCAN1RX, 0U); // CAN1 RX IOMUXCSetPinMux(IOMUXCSAI2RXCCAN1TX, 0U); // CAN1 TX (3)CAN波特率: CAN-FD支持可变速率,即控制区和数据区的波特率可以不一致,控制区最大为1Mbit/s;数据区最大为8Mbit/s。后续程序根据总线时钟和设置的波特率,分配时段设置的seg1,seg2等数值。 bitRate = 1000000U; // CAN-FD控制区波特率为1Mbit/s bitRateFD = 8000000U; // CAN-FD数据区波特率为8Mbit/ (4)CAN-FD使能: 除了使能CAN-FD,可变波特率也需要使能,否则数据区的最大速率和控制区的速率一样,最大为1Mbit/s。 MCR |= CANMCRFDENMASK; // CAN-FD使能 fdctrl |= CANFDCTRLFDRATEMASK; // 可变波特率使能 (5)关闭自回环: 如果开启了自回环,那么CAN1数据会在芯片内回环,不会到外部管脚,在程序调试时可以排除外部端子的干扰,但真实应用时,需要关闭自回环,从外部管脚收发数据。 enableLoopBack = false; // 不回环,使用外部管脚 (6)帧格式: 本次我们使用11位标准数据帧,小伙伴也在后续试试扩展帧。需要设置自己的ID,便于总线上其他设备识别。 mbConfig.format = kFLEXCANFrameFormatStandard; // 11位标准帧,非扩展帧 mbConfig.type = kFLEXCANFrameTypeData; // 数据帧 非远程帧 mbConfig.id = FLEXCANIDSTD(rxIdentifier); // 帧ID 用于区别总线中不同的设备 (7)接收过滤: 用户可设置接收过滤规则,这样就可以只接收特定帧ID的数据,减少应用处理的数据量。 rxIdentifier = 0; FLEXCANSetRxMbGlobalMask(EXAMPLECAN, FLEXCANRXMBSTDMASK(rxIdentifier, 0, 0));//接收所有ID数据 CAN-FD收发流程 本次测试M核做主站,CAN1先发送一帧包含64字节数据,A核CAN2收到,将64字节数据再次发送,M核CAN1接收。对比发送和接收的64字节数据是否一致。重复100次。 (1)CAN-FD发送数据: EXAMPLECAN表示为CAN1,flexcanHandle为CAN实例,包含了发送接收回调函数,txXfer为要发送的64字节数据。 FLEXCANTransferFDSendNonBlocking(EXAMPLECAN, &flexcanHandle, &txXfer); // CAN-FD发送数据 (2)CAN-FD接收数据: EXAMPLECAN表示为CAN1,flexcanHandle为CAN实例,包含了发送接收回调函数,rxXfer为接收的64字节数据。 FLEXCANTransferFDReceiveNonBlocking(EXAMPLECAN, &flexcanHandle, &rxXfer); // CAN-FD接收函数 (3)接收和发送数据对比: for (j = 0U; j <= DLC; j++) // 对比收发数据,不一致打印 { dataWord ) { LOGINFO("Data mismatch !!! j=%d \r\n",j); } } 02A核CAN-FD A核设备树中保留CAN2,内核解析设备树在 /dev下生成can0。设置波特率后使能can0节点,应用程序中open函数打开接口,write函数发送数据,read函数接收数据。我们把CAN接口的示例已经作为一个跨平台的综合演示程序,小伙伴们可以直接加参数调用即可。 分配节点 (1)M核独享CAN1,A核独享CAN2,修改设备树,在设备树OK8MP-C.dts中,删除CAN1设备节点,保留CAN2设备节点。编译新的设备树; (2)将生成的OK8MP-C.dtb和Image拷贝至开发板的 /run/media/mmcblk2p1/ 目录下,输入sync命令同步后重启开发板; (3)通过A核串口输入命令uname -r ,显示内核版本,将 /lib/modbule目录下文件夹名称改为内核版本,这样才能自动加载模块生成can0节点,重启开发板。 演示Demo 进程名:candemo 使用方法:./candemo设备名 … … 本次测试接口为can0(对应开发板CAN2),控制区波特率为1Mbit/s,数据区最大为8Mbit/s,11位标准帧,不过滤帧ID,不主动发数据,不回环。因此命令为: ./candemo can0-b 1000 -fd 8000。 03 程序验证 硬件连接 使用杜邦线将CAN1和CAN2的can-H短接,同时将can-L短接,注意不要接反。 M核程序 修改uboot环境变量设置M核自启动,同时将M核程序forlinxm7tcmfirmware.bin; 放到/run/media/mmcblk2p1/目录下。详细操作可看上篇文章《【玩转多核异构】M核程序的启动、编写和仿真》。 A核程序 (1)使用串口Xmodem,网络FTP,SCP,U盘,TF卡等多种方式,将candemo从电脑拷贝至核心板默认目录下,输入以下命令修改权限; chmod 777 candemo (2)输入以下命令,A核应用程序candemo将设置波特率后打开can0节点,等待M核发送的数据,再将接收的数据通过CAN2发送给M核。 ./candemo can0 -b 1000 -fd 8000 实际测试 (1)OKMX8MP-C开发板重新上电后,M核程序启动,完成CAN1初始化后,在M核调试串口输出信息,等待按键; (2)在A核调试串口输入以下命令,CAN2将处于接收的状态: ./candemo can0 -b 1000 -fd 8000 (3)在M核串口按下键A或a,M核CAN1发送64字节数据,A核CAN2接收数据,并将接收的数据再次发送,M核CAN1接收后和发送数据对比,输出结果。循环100次; (4)通过测试可以看到,依托i.MX8M Plus强大的性能,双核都以8Mbit/s的高速率发送大量数据,均没有出现异常。 以上就是小编为小伙伴带来的基于飞凌嵌入式OKMX8MP-C开发板双核控制CAN-FD的使用方法了,是不是感觉性能很强大呢?
相关资源