NXP iMX8MM Cortex-M4 核心 GPT Capture 测试

2024-03-07 14:20

本文主要是介绍NXP iMX8MM Cortex-M4 核心 GPT Capture 测试,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

By Toradex秦海

1). 简介

NXP i.MX8 系列处理器均为异构多核架构 SoC,除了可以运行 Linux 等复杂操作系统的 Cortax-A 核心,还包含了可以运行实时操作系统比如 FreeRTOS 的 Cortex-M 核心,本文就演示通过 NXP i.MX8MM 处理器集成的 Cortex-M4 核心来运行 GPT (General Purpose Timer) 输入采集功能模块的测试。

I.MX8M Mini 处理器 GPT 模块硬件比较简单,如下框图,可以实现 Capture 捕获输入功能和 Compare 定时输出功能。

NXP iMX8MM Cortex-M4 核心 GPT Capture 测试_web333.png

本文所演示的ARM平台来自于Toradex 基于NXP i.MX8M Mini ARM处理器的Verdin iMX8MM ARM嵌入式平台。

2. 准备

a). Verdin i.MX8MM ARM核心版配合Verdin Development Board,连接调试串口(载板X66)到开发主机方便调试,X66 连接了4个串口,其中第三个是 Cortex-M4 核心的默认调试串口,第四个是 Cortex-A53 核心的默认调试串口。

b). 为了测试 GPT 输入捕获, 相应的需要一个PWM 波发生设备,这里使用Toradex 基于NXP i.MX8M Plus ARM处理器的Verdin i.MX8MP 核心板配合 Dahlia Board 作为PWM output使用。同样连接调试串口(载板X18)到开发主机方便调试。

c). Verdin i.MX8MP Cortex-A53 核心系统使用Toradex Yocto Linux BSP6, 更多说明请参考这里。

d). 参考如下将 Verdin i.MX8MP PWM1 连接到 Verdin i.MX8MM GPT1 Capture 管脚,同时为了阻断载板其他电路干扰,将 Verdin Development Board X6 Pin_24 的跳线帽去掉。

Dahlia Board X20 Pin_9 -> Verdin Development Board X5Pin_24 SODIMM_252

3). Verdin i.MX8MM M4核心FreeRTOS基本资料

a). Verdin i.MX8MM HMP(Heterogeneous Multi-core Processing) 架构基本说明请参考如下:

Cortex-M and Memory Areas on Toradex SoMs | Toradex Developer Center

b). 参考如下说明下载配置 NXP 用于开发 Cortex-M 核心的 MCUXpresso SDK

Setting Up MCUXpresso SDK and Toolchain for Cortex-M development | Toradex Developer Center

c). Verdin i.MX8MM 编译运行 M4 firmware 操作流程请参考如下文章

Running FreeRTOS on the Cortex-M4 of a Verdin iMX8M Mini | Toradex Developer Center

d). MCUXpresso SDK 包含的 sample 示例应用可以参考如下 SDK 源位置

-----------------------------

$cd <SDK_root>/boards/evkmimx8mm/

$ tree -L 2

.

├── cmsis_driver_examples

│   ├── ecspi

│   ├── enet

│   ├── i2c

│   └── uart

├── demo_apps

│   ├── hello_world

│   └── sai_low_power_audio

├── driver_examples

│   ├── ecspi

│   ├── enet

│   ├── gpio

│   ├── gpt

│   ├── i2c

│   ├── pdm

│   ├── pwm

│   ├── rdc

│   ├── sai

│   ├── sdma

│   ├── sema4

│   ├── tmu

│   ├── uart

│   └── wdog

├── evkmimx8mm.png

├── freertos_examples

│   ├── freertos_event

│   ├── freertos_generic

│   ├── freertos_hello

│   ├── freertos_mutex

│   ├── freertos_queue

│   ├── freertos_sem

│   ├── freertos_swtimer

│   └── freertos_tickless

├── multicore_examples

│   ├── rpmsg_lite_pingpong_rtos

│   └── rpmsg_lite_str_echo_rtos

└── project_template

    ├── board.c

    ├── board.h

    ├── BOARD_Project_Template_evkmimx8mm.cmake

    ├── clock_config.c

    ├── clock_config.h

    ├── peripherals.c

    ├── peripherals.h

    ├── pin_mux.c

    └── pin_mux.h

-----------------------------

4). Verdin i.MX8MM Cortex-M4核心FreeRTOS GPT Capture示例驱动开发

a). Verdin i.MX8MM MCUXpresso SDK 已经包含一个简单的 GPT Capture sample驱动,本文基于此 sample 进行修改测试。

-----------------------------

$cd <SDK_root>/boards/evkmimx8mm/driver_examples/gpt/capture

$ tree -L 1

.

├── armgcc

├── board.c

├── board.h

├── clock_config.c

├── clock_config.h

├── empty_rsc_table.c

├── fsl_iomuxc.h

├── gpt_capture.c

├── gpt_capture_v3_14.xml

├── pin_mux.c

├── pin_mux.h

└── readme.md

-----------------------------

b). 首先先确认 pin_mux 定义以及其他 i.MX8MM 初始化基本配置,如果需要可以进行修改

./ pin_mux.h/pin_mux.c 用于确定项目中使用的管脚定义,本文中使用的正好就是示例默认的 GPT1 Capture1 管脚,因此无需修改。如果用到其他管脚,就需要进行修改,支持的所有管脚定义可以参考 fsl_iomuxc.h 文件。

-----------------------------

/* FUNCTION ************************************************************************************************************

 *

 * Function Name : BOARD_InitPins

 * Description   : Configures pin routing and optionally pin electrical features.

 *

 * END ****************************************************************************************************************/

void BOARD_InitPins(void) {                                /*!< Function assigned for the core: Cortex-M4[m4] */

    IOMUXC_SetPinMux(IOMUXC_SAI3_RXFS_GPT1_CAPTURE1, 0U);

    IOMUXC_SetPinMux(IOMUXC_UART4_RXD_UART4_RX, 0U);

...

-----------------------------

./ board.h/board.c 用于 i.MX8MM M4 核心基本初始化配置,本文不做修改。

./ clock_config.h/clock_config.c 用于 i.MX8MM M4 核心基本时钟配置,本文不做修改。

c). GPT Capture 功能实现

./ 本文 GPT Capture 功能定义

GPT1 capture1 管脚输入一个给定频率(如 1k Hz )和占空比(如  50% ) 的PWM 信号,通过捕获输入上升/下降沿中断,分别获得相邻两次中断的 GPT Counter 计数器的计数,并以此来计算输入 PWM 信号的半波周期。

./ GPT Capture 功能基本都是通过 gpt_capture.c 文件代码来实现,默认 sample 是捕获上升沿中断后,打印中断当时的 GPT Counter 计数数值。

./ 为了实现本文定义的捕获功能,首先增加如下全局变量定义

-----------------------------

/*******************************************************************************

 * Variables

 ******************************************************************************/

volatile bool gptIsrFlag_Start = false;

volatile bool gptIsrFlag_Finish = false;

volatile bool gptIsrFlag_Overflow = false;

volatile uint32_t captureVal = 0;

volatile uint32_t captureVal_Last = 0;

-----------------------------

// gptIsrFlag_Start 定义为第一次捕获中断开始标志

// gptIsrFlag_Finish 定义为第二次捕获中断结束标志

// gptIsrFlag_Overflow 定义为 GPT Counter 溢出标志

// captureVal 定义为第二次中断 GPT Counter 数值

// captureVal_Last 定义为第一次中断 GPT Counter 数值

./ GPT Interrupt 函数修改如下:

首先处理计数器溢出情况,如果中断发生时候已经发生溢出,则声明 gptIsrFlag_Overflow 溢出标志位;然后通过 gptIsrFlag_Start / gptIsrFlag_Finish 标志位来分别处理第一次和第二次中断,获取第一次和第二次中断时候的 GPT Counter 数值,同时分别翻转 GPT Capture Interrupt 模式。另外,当溢出发生在第一次中断计数和第二次中断计数之间的时候,需要将第二次中断计数数值增加溢出值 0xffffffff。

-----------------------------

void EXAMPLE_GPT_CAPTURE_IRQHandler(void)

{

    /* GPT Counter Overflow processing */

    if (GPT_GetStatusFlags(DEMO_GPT_BASE, kGPT_RollOverFlag) != false)

    {

        if (gptIsrFlag_Start != true)

        {

           gptIsrFlag_Overflow = true;

        }

        GPT_ClearStatusFlags(DEMO_GPT_BASE, kGPT_RollOverFlag);

    }

    if (GPT_GetStatusFlags(DEMO_GPT_BASE, kGPT_InputCapture1Flag) != false)

    {

        if(gptIsrFlag_Finish != true)

        {

           /* First time IRQ */

           if (gptIsrFlag_Start == false)

           {

               captureVal_Last = GPT_GetInputCaptureValue(DEMO_GPT_BASE, BOARD_GPT_INPUT_CAPTURE_CHANNEL);

               /* Switch Interrupt mode to falling edge */

               GPT_SetInputOperationMode(DEMO_GPT_BASE, BOARD_GPT_INPUT_CAPTURE_CHANNEL, kGPT_InputOperation_FallEdge);

               gptIsrFlag_Start = true;

           }

           /* Second time IRQ */

   /* GPT counter overflow */

           else if (gptIsrFlag_Overflow == true)

           {

               captureVal = GPT_GetInputCaptureValue(DEMO_GPT_BASE, BOARD_GPT_INPUT_CAPTURE_CHANNEL) + 0xffffffff;

               /* Switch Interrupt mode to rising edge */

               GPT_SetInputOperationMode(DEMO_GPT_BASE, BOARD_GPT_INPUT_CAPTURE_CHANNEL, kGPT_InputOperation_RiseEdge);

               gptIsrFlag_Start = false;

               gptIsrFlag_Finish = true;

           }

   else

   {

               captureVal = GPT_GetInputCaptureValue(DEMO_GPT_BASE, BOARD_GPT_INPUT_CAPTURE_CHANNEL);

               /* Switch Interrupt mode to rising edge */

               GPT_SetInputOperationMode(DEMO_GPT_BASE, BOARD_GPT_INPUT_CAPTURE_CHANNEL, kGPT_InputOperation_RiseEdge);

               gptIsrFlag_Start = false;

               gptIsrFlag_Finish = true;

   }

      }

      GPT_ClearStatusFlags(DEMO_GPT_BASE, BOARD_GPT_CHANNEL_FLAG);

   }

   SDK_ISR_EXIT_BARRIER;

}

-----------------------------

./ Main 主函数修改如下:

-----------------------------

int main(void)

{

    gpt_config_t gptConfig;

...

GPT_GetDefaultConfig(&gptConfig);

    /* Initialize GPT module */

    GPT_Init(DEMO_GPT_BASE, &gptConfig);

...

/* Setup input capture on a gpt channel */

    GPT_SetInputOperationMode(DEMO_GPT_BASE, BOARD_GPT_INPUT_CAPTURE_CHANNEL, kGPT_InputOperation_RiseEdge);

...

    /* Enable GPT Overflow interrupt */

    GPT_EnableInterrupts(DEMO_GPT_BASE, kGPT_RollOverFlagInterruptEnable);

...

while (true)

    {

        /* Check whether occur 2nd interupt */

        if (true == gptIsrFlag_Finish)

        {

            PRINTF("\r\n Input Capture Half Period Value =%u us\r\n", (captureVal - captureVal_Last)/24);

            gptIsrFlag_Finish = false;

        }

        else

        {

            __WFI();

        }

    }

}

-----------------------------

// 通过 GPT_GetDefaultConfig 函数获取默认的 GPT Capture 配置,参考 docs 目录下的 MCUXpresso SDK API Reference Manual_MIMX8MM6.pdf 文档,可以查到默认配置如下,如果需要也可以修改这个配置

-----------------------------

config->clockSource = kGPT_ClockSource_Periph;

config->divider = 1U;

config->enableRunInStop = true;

config->enableRunInWait = true;

config->enableRunInDoze = false;

config->enableRunInDbg = false;

config->enableFreeRun = false;

config->enableMode = true;

-----------------------------

// 通过 GPT_SetInputOperationMode 函数将 GPT Capture 模式初始配置为上升沿触发

// 为了处理 GPT Counter Overflow,使能对应中断

// while 函数循环执行当  gptIsrFlag_Finish 第二次中断采集结束标志位声明后,打印捕获的输入 PWM 波的半波周期。这里需要说明下,由于 NXP iMX8MM SoC 也受到如下 Errata 影响,因此 GPT Clock Source 只能使用内部 24M Hz 时钟源,所以这里 printf 函数直接使用 24M 来算出半波周期是多少 us 。

https://www.nxp.com.cn/docs/en/errata/IMX8X_C0_0N99Z_ER.pdf

5). Verdin i.MX8MM Cortex-M4核心FreeRTOS GPT Capture示例部署测试

a). 将上述修改后的项目参考章节 3 的相关资料编译后,复制 gpt_capture.bin 可执行文件到 Verdin i.MX8MM 核心板 Linux /home/root 目录下保存。

b). 对Verdin i.MX8MM 模块进入 U-boot 命令行,通过如下命令配置 Cortex-M4 核心 Firmware 下载和运行

-----------------------------

# setenv load_cmd "ext4load mmc 0:2"

# setenv m4image "/home/root/gpt_capture.bin"

> setenv m4image_size 17000

> setenv loadm4image "${load_cmd} ${loadaddr} ${m4image}"

> setenv m4boot "${loadm4image}; cp.b ${loadaddr} 0x7e0000 ${m4image_size}; dcache flush; bootaux 0x7e0000"

> saveenv

> run m4boot

-----------------------------

c). Verdin i.MX8MM Cortex-M4 核心运行后其调试串口打印信息

-----------------------------

GPT input capture example

Once the input signal is received the input capture half peroid is printed

-----------------------------

d). 此时在 Verdin i.MX8MP 平台通过如下脚本使能 1kHz 50% 占空比 PWM 输出 10s 时间

-----------------------------

#!/bin/sh

cd /sys/class/pwm/pwmchip0/

echo 0 > export

echo 1000000 > pwm0/period

echo 500000 > pwm0/duty_cycle

echo "normal" > pwm0/polarity

echo 1 > pwm0/enable

sleep 10

echo 0 > pwm0/enable

-----------------------------

e). 这时 Verdin i.MX8MM Cortex-M4 调试串口就会打印出对应的半波周期

-----------------------------

...

 Input Capture Half Period Value =500 us

 Input Capture Half Period Value =499 us

 Input Capture Half Period Value =499 us

 Input Capture Half Period Value =499 us

...

-----------------------------

f). 尝试将 Verdin i.MX8MP PWM 修改为 10kHz 80%/20% 占空比

-----------------------------

...

echo 100000 > pwm0/period

echo 80000 > pwm0/duty_cycle

...

-----------------------------

g). Verdin i.MX8MM Cortex-M4 输出周期会对应变化

-----------------------------

 Input Capture Half Period Value =80 us

 Input Capture Half Period Value =80 us

 Input Capture Half Period Value =80 us

 Input Capture Half Period Value =80 us

-----------------------------

h). 最后,由于 Verdin i.MX8MM GPT1 CAPTURE1 管脚在 Cortex-A53 核心 Linux 下默认是用于 WAKEUP GPIO 使用,如果需要同时运行 Verdin i.MX8MM Cortex-A53 核心和 Cortex-M4 核心,就需要在 Linux device-tree 文件中将 WAKEUP gpio-key 功能替换为其他 GPIO 管脚资源。

imx8mm-verdin.dtsi « freescale « dts « boot « arm64 « arch - linux-toradex.git - Linux kernel for Apalis and Colibri modules

6). 总结

本文简单示例了基于i.MX8MM Cortex-M4 核心 GPT Capture 功能供参考。

这篇关于NXP iMX8MM Cortex-M4 核心 GPT Capture 测试的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/783803

相关文章

如何测试计算机的内存是否存在问题? 判断电脑内存故障的多种方法

《如何测试计算机的内存是否存在问题?判断电脑内存故障的多种方法》内存是电脑中非常重要的组件之一,如果内存出现故障,可能会导致电脑出现各种问题,如蓝屏、死机、程序崩溃等,如何判断内存是否出现故障呢?下... 如果你的电脑是崩溃、冻结还是不稳定,那么它的内存可能有问题。要进行检查,你可以使用Windows 11

性能测试介绍

性能测试是一种测试方法,旨在评估系统、应用程序或组件在现实场景中的性能表现和可靠性。它通常用于衡量系统在不同负载条件下的响应时间、吞吐量、资源利用率、稳定性和可扩展性等关键指标。 为什么要进行性能测试 通过性能测试,可以确定系统是否能够满足预期的性能要求,找出性能瓶颈和潜在的问题,并进行优化和调整。 发现性能瓶颈:性能测试可以帮助发现系统的性能瓶颈,即系统在高负载或高并发情况下可能出现的问题

字节面试 | 如何测试RocketMQ、RocketMQ?

字节面试:RocketMQ是怎么测试的呢? 答: 首先保证消息的消费正确、设计逆向用例,在验证消息内容为空等情况时的消费正确性; 推送大批量MQ,通过Admin控制台查看MQ消费的情况,是否出现消费假死、TPS是否正常等等问题。(上述都是临场发挥,但是RocketMQ真正的测试点,还真的需要探讨) 01 先了解RocketMQ 作为测试也是要简单了解RocketMQ。简单来说,就是一个分

Andrej Karpathy最新采访:认知核心模型10亿参数就够了,AI会打破教育不公的僵局

夕小瑶科技说 原创  作者 | 海野 AI圈子的红人,AI大神Andrej Karpathy,曾是OpenAI联合创始人之一,特斯拉AI总监。上一次的动态是官宣创办一家名为 Eureka Labs 的人工智能+教育公司 ,宣布将长期致力于AI原生教育。 近日,Andrej Karpathy接受了No Priors(投资博客)的采访,与硅谷知名投资人 Sara Guo 和 Elad G

【测试】输入正确用户名和密码,点击登录没有响应的可能性原因

目录 一、前端问题 1. 界面交互问题 2. 输入数据校验问题 二、网络问题 1. 网络连接中断 2. 代理设置问题 三、后端问题 1. 服务器故障 2. 数据库问题 3. 权限问题: 四、其他问题 1. 缓存问题 2. 第三方服务问题 3. 配置问题 一、前端问题 1. 界面交互问题 登录按钮的点击事件未正确绑定,导致点击后无法触发登录操作。 页面可能存在

4B参数秒杀GPT-3.5:MiniCPM 3.0惊艳登场!

​ 面壁智能 在 AI 的世界里,总有那么几个时刻让人惊叹不已。面壁智能推出的 MiniCPM 3.0,这个仅有4B参数的"小钢炮",正在以惊人的实力挑战着 GPT-3.5 这个曾经的AI巨人。 MiniCPM 3.0 MiniCPM 3.0 MiniCPM 3.0 目前的主要功能有: 长上下文功能:原生支持 32k 上下文长度,性能完美。我们引入了

业务中14个需要进行A/B测试的时刻[信息图]

在本指南中,我们将全面了解有关 A/B测试 的所有内容。 我们将介绍不同类型的A/B测试,如何有效地规划和启动测试,如何评估测试是否成功,您应该关注哪些指标,多年来我们发现的常见错误等等。 什么是A/B测试? A/B测试(有时称为“分割测试”)是一种实验类型,其中您创建两种或多种内容变体——如登录页面、电子邮件或广告——并将它们显示给不同的受众群体,以查看哪一种效果最好。 本质上,A/B测

GPT系列之:GPT-1,GPT-2,GPT-3详细解读

一、GPT1 论文:Improving Language Understanding by Generative Pre-Training 链接:https://cdn.openai.com/research-covers/languageunsupervised/language_understanding_paper.pdf 启发点:生成loss和微调loss同时作用,让下游任务来适应预训

PostgreSQL核心功能特性与使用领域及场景分析

PostgreSQL有什么优点? 开源和免费 PostgreSQL是一个开源的数据库管理系统,可以免费使用和修改。这降低了企业的成本,并为开发者提供了一个活跃的社区和丰富的资源。 高度兼容 PostgreSQL支持多种操作系统(如Linux、Windows、macOS等)和编程语言(如C、C++、Java、Python、Ruby等),并提供了多种接口(如JDBC、ODBC、ADO.NET等

深入解析秒杀业务中的核心问题 —— 从并发控制到事务管理

深入解析秒杀业务中的核心问题 —— 从并发控制到事务管理 秒杀系统是应对高并发、高压力下的典型业务场景,涉及到并发控制、库存管理、事务管理等多个关键技术点。本文将深入剖析秒杀商品业务中常见的几个核心问题,包括 AOP 事务管理、同步锁机制、乐观锁、CAS 操作,以及用户限购策略。通过这些技术的结合,确保秒杀系统在高并发场景下的稳定性和一致性。 1. AOP 代理对象与事务管理 在秒杀商品