新闻| 论坛| 博客| 在线研讨会
NXP iMX8MM Cortex-M4 核心 GPT Capture 测试
toradex| 2024-03-11 17:21:50 阅读:48 发布文章

By Toradex秦海

1).简介

NXP i.MX8系列处理器均为异构多核架构SoC,除了可以运行Linux等复杂操作系统的Cortax-A核心,还包含了可以运行实时操作系统比如FreeRTOSCortex-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.MX8MMARM核心版配合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).Verdini.MX8MMM4核心FreeRTOS基本资料

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

https://developer.toradex.cn/software/cortex-m/hmp-memory-areas-on-toradex-soms/

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

https://developer.toradex.cn/software/cortex-m/setting-up-sdk-toolchain/

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

https://developer.toradex.cn/software/real-time/freertos/freertos-on-the-cortex-m4-of-a-verdin-imx8mm

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

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

$cd /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.MX8MMCortex-M4核心FreeRTOSGPT Capture示例驱动开发

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

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

$cd /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 uint8_t gptIsrFlag_Overflow = 0;

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模式。

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

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 ++;

}

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 */

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)

{

uint64_t int_Peroid = 0;

uint32_t time_Ms = 0;

uint32_t time_Us = 0;

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)

{

/* GPT counter diff value between 2 IRQs */

int_Peroid = gptIsrFlag_Overflow * (uint64_t) 0xffffffff;

int_Peroid = int_Peroid + captureVal;

int_Peroid = int_Peroid - captureVal_Last;

/* transfer counter value to peroid */

time_Us = (uint32_t) ((int_Peroid / 24) % 1000);

time_Ms = (uint32_t) ((int_Peroid / 24) / 1000);

PRINTF("\r\n interval between 2 rising edge =%u ms and %u us\r\n", time_Ms, time_Us);

gptIsrFlag_Overflow = 0;

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波的半波周期。如果有溢出发生,则需要考虑增加相应的0xffffffff溢出计数次数。这里需要说明下,由于NXP iMX8MM SoC也受到如下Errata影响,因此GPT Clock Source只能使用内部24M Hz时钟源,所以这里直接使用24M来算出半波周期是多少msus

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

5).Verdin i.MX8MMCortex-M4核心FreeRTOSGPT 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

echo500000 > 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 = 0ms and 500us

Input Capture Half Period Value = 0ms and 500us

Input Capture Half Period Value = 0ms and 500us

Input Capture Half Period Value = 0ms and 500us

...

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

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

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

...

echo 100000 > pwm0/period

echo80000 > pwm0/duty_cycle

...

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

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

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

Input Capture Half Period Value = 0ms and 80us

Input Capture Half Period Value = 0ms and 80us

Input Capture Half Period Value = 0ms and 80us

Input Capture Half Period Value = 0ms and 80us

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

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管脚资源。

https://git.toradex.cn/cgit/linux-toradex.git/tree/arch/arm64/boot/dts/freescale/imx8mm-verdin.dtsi?h=toradex_5.15-2.2.x-imx#n40

6).总结

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


*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。

参与讨论
登录后参与讨论
推荐文章
最近访客