Multi Source Translation Content

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Multi Source Translation Content

Discussions

Sort by:
[MCX A153] LPSPI 入门指南(日语博客) 本文 旨在为 NXP 产品新手工程师介绍 MCX A153 上的 LPSPI( 低 功耗 串行 外设 接口 ) 基本概念 以及 如何使用 MCUXpresso SDK 实现该接口。 首先,我们将概述硬件,然后以 FRDM-MCXA153 开发板为基础,通过代码示例讲解如何使用MCUXpresso SDK。 (阅读时间:20分钟) 1. LPSPI模块概述   1.1 什么是LPSPI ?   LPSPI 是一种用于与外部设备进行同步串行通信的外围模块。 这里, “LP(低功耗)”是指“设计用于低功耗运行”。   与标准SPI的区别(从低功耗角度来看) 以下是LPSPI与典型SPI模块相比的特点: 即使在低功耗模式(停止/睡眠)下,它也能继续运行。 通过与 DMA(eDMA)协同工作并减少 CPU 干预,可以降低系统整体功耗。 可以使用硬件触发器(例如 HREQ)来启动通信,而无需唤醒 CPU。 LPSPI 不仅仅是一个实现 SPI 通信的模块;它被设计成一个低功耗的通信模块,用于运行整个系统。   1.2 MCX A153 的配置 MCX A153具有多个LPSPI实例,并使用以下信号: CS(P1_3) SCK (P1_1) SDI(P1_2) SDO(P1_0) 2. LPSPI的基本操作   2.1信号的作用 SPI 通信主要使用以下四根线进行通信。 SPI 通信根据极性和相位有四种模式,但例如在模式 0 中,每个信号都遵循以下时序图。   2.2 先进先出原则的作用 LPSPI具有内部FIFO (先进先出),可以临时保存已发送和已接收的数据。 这使得CPU能够在一定程度上分批处理数据,而无需立即逐字节执行寄存器操作。此外,通过将其与eDMA结合使用,可以实现FIFO的数据供取和检索自动化,而无需由CPU处理。 3. DMA( eDMA )传输的基本概念   3.1为什么要使用DMA ? 对于只需要通过SPI发送几个字节的应用来说,简单的轮询就足够了,但在实际的嵌入式开发中,经常会遇到以下要求: 我希望能够持续传输传感器数据、显示数据等等。 我不希望CPU在等待通信时停止运行。 我希望它能与其他控制进程和RTOS任务并行运行。 我想减轻通信处理的负担。   这里的关键概念是“非阻塞”。 非阻塞函数是指不等待处理完成就立即返回的函数。 例如,对于SPI通信,通常有两种工作模式,如下所示: 阻塞 当调用发送函数时,CPU 会等待通信完成。 通信进行期间,其他操作无法执行。 非阻塞式 该函数仅启动传输并立即返回。 实际通信在后台进行(例如,DMA)。 CPU 在此期间可以执行其他任务。 使用 LPSPI + eDMA 可以让硬件处理大部分数据传输,从而实现无阻塞通信。   3.2 DMA传输的概念 在DMA传输中, CPU首先设置“从哪里发送”、“从哪里接收”和“要发送多少字节”,然后指示系统开始传输。 之后, eDMA会根据LPSPI的FIFO请求自动进行数据传输。CPU 无需等待,可以继续执行其他进程。   3.3操作图像 DMA传输的一般流程如下: CPU初始化LPSPI和eDMA 。 设置发送缓冲区/接收缓冲区/大小 CPU指示开始DMA传输。 eDMA根据FIFO请求传输数据。 转账完成后,我们会回拨电话通知您。 4. SDK驱动程序的基本流程 要使用 LPSPI,需要通过软件进行以下设置: 设置时钟引脚 LPSPI模块初始化 eDMA句柄定义 LPSPI句柄生成 传输缓冲区设置 转账执行 通过回拨确认完成。 本节演示如何使用驱动程序,并以 MCUXpresso SDK 中的示例项目为例进行说明。 我将以以下项目为例进行解释。 参考网址: 硬件要求 — MCUXpresso SDK 文档 mcuxsdk-examples/driver_examples/lpspi/edma_transfer/lpspi_edma_transfer.cc 在 main · nxp-mcuxpresso/mcuxsdk-examples   4.1 时钟设置和引脚设置 首先,初始化时钟并将端口连接到 LPSPI0。 如果忘记启用时钟,设备将无法正常工作。端口分配设置 (MuxAlt) 必须与 LPSPI0 匹配,这一点非常重要。 /* クロック有効化 */ void BOARD_InitHardware(void) { /* Attach peripheral clock */ CLOCK_SetClockDiv(kCLOCK_DivLPSPI0, 1u); CLOCK_AttachClk(kFRO12M_to_LPSPI0); } /* PORT設定 */ /* PORT1: Peripheral clock is enabled */ CLOCK_EnableClock(kCLOCK_GatePORT1); /* PORT3: Peripheral clock is enabled */ CLOCK_EnableClock(kCLOCK_GatePORT3); /* LPSPI0 peripheral is released from reset */ RESET_ReleasePeripheralReset(kLPSPI0_RST_SHIFT_RSTn); /* PORT1 peripheral is released from reset */ RESET_ReleasePeripheralReset(kPORT1_RST_SHIFT_RSTn); /* LPSPI1 peripheral is released from reset */ RESET_ReleasePeripheralReset(kLPSPI1_RST_SHIFT_RSTn); /* PORT3 peripheral is released from reset */ RESET_ReleasePeripheralReset(kPORT3_RST_SHIFT_RSTn); const port_pin_config_t port1_0_pin135_config = {/* Internal pull-up/down resistor is disabled */ .pullSelect = kPORT_PullDisable, /* Low internal pull resistor value is selected. */ .pullValueSelect = kPORT_LowPullResistor, /* Fast slew rate is configured */ .slewRate = kPORT_FastSlewRate, /* Passive input filter is disabled */ .passiveFilterEnable = kPORT_PassiveFilterDisable, /* Open drain output is disabled */ .openDrainEnable = kPORT_OpenDrainDisable, /* Low drive strength is configured */ .driveStrength = kPORT_LowDriveStrength, /* Normal drive strength is configured */ .driveStrength1 = kPORT_NormalDriveStrength, /* Pin is configured as LPSPI0_SDO */ .mux = kPORT_MuxAlt2, /* Digital input enabled */ .inputBuffer = kPORT_InputBufferEnable, /* Digital input is not inverted */ .invertInput = kPORT_InputNormal, /* Pin Control Register fields [15:0] are not locked */ .lockRegister = kPORT_UnlockRegister}; /* PORT1_0 (pin 135) is configured as LPSPI0_SDO */ PORT_SetPinConfig(PORT1, 0U, &port1_0_pin135_config); const port_pin_config_t port1_1_pin136_config = {/* Internal pull-up/down resistor is disabled */ .pullSelect = kPORT_PullDisable, /* Low internal pull resistor value is selected. */ .pullValueSelect = kPORT_LowPullResistor, /* Fast slew rate is configured */ .slewRate = kPORT_FastSlewRate, /* Passive input filter is disabled */ .passiveFilterEnable = kPORT_PassiveFilterDisable, /* Open drain output is disabled */ .openDrainEnable = kPORT_OpenDrainDisable, /* Low drive strength is configured */ .driveStrength = kPORT_LowDriveStrength, /* Normal drive strength is configured */ .driveStrength1 = kPORT_NormalDriveStrength, /* Pin is configured as LPSPI0_SCK */ .mux = kPORT_MuxAlt2, /* Digital input enabled */ .inputBuffer = kPORT_InputBufferEnable, /* Digital input is not inverted */ .invertInput = kPORT_InputNormal, /* Pin Control Register fields [15:0] are not locked */ .lockRegister = kPORT_UnlockRegister}; /* PORT1_1 (pin 136) is configured as LPSPI0_SCK */ PORT_SetPinConfig(PORT1, 1U, &port1_1_pin136_config); const port_pin_config_t port1_2_pin137_config = {/* Internal pull-up/down resistor is disabled */ .pullSelect = kPORT_PullDisable, /* Low internal pull resistor value is selected. */ .pullValueSelect = kPORT_LowPullResistor, /* Fast slew rate is configured */ .slewRate = kPORT_FastSlewRate, /* Passive input filter is disabled */ .passiveFilterEnable = kPORT_PassiveFilterDisable, /* Open drain output is disabled */ .openDrainEnable = kPORT_OpenDrainDisable, /* Low drive strength is configured */ .driveStrength = kPORT_LowDriveStrength, /* Normal drive strength is configured */ .driveStrength1 = kPORT_NormalDriveStrength, /* Pin is configured as LPSPI0_SDI */ .mux = kPORT_MuxAlt2, /* Digital input enabled */ .inputBuffer = kPORT_InputBufferEnable, /* Digital input is not inverted */ .invertInput = kPORT_InputNormal, /* Pin Control Register fields [15:0] are not locked */ .lockRegister = kPORT_UnlockRegister}; /* PORT1_2 (pin 137) is configured as LPSPI0_SDI */ PORT_SetPinConfig(PORT1, 2U, &port1_2_pin137_config); const port_pin_config_t port1_3_pin138_config = {/* Internal pull-up/down resistor is disabled */ .pullSelect = kPORT_PullDisable, /* Low internal pull resistor value is selected. */ .pullValueSelect = kPORT_LowPullResistor, /* Fast slew rate is configured */ .slewRate = kPORT_FastSlewRate, /* Passive input filter is disabled */ .passiveFilterEnable = kPORT_PassiveFilterDisable, /* Open drain output is disabled */ .openDrainEnable = kPORT_OpenDrainDisable, /* Low drive strength is configured */ .driveStrength = kPORT_LowDriveStrength, /* Normal drive strength is configured */ .driveStrength1 = kPORT_NormalDriveStrength, /* Pin is configured as LPSPI0_PCS0 */ .mux = kPORT_MuxAlt2, /* Digital input enabled */ .inputBuffer = kPORT_InputBufferEnable, /* Digital input is not inverted */ .invertInput = kPORT_InputNormal, /* Pin Control Register fields [15:0] are not locked */ .lockRegister = kPORT_UnlockRegister}; /* PORT1_3 (pin 138) is configured as LPSPI0_PCS0 */ PORT_SetPinConfig(PORT1, 3U, &port1_3_pin138_config); const port_pin_config_t port3_10_pin96_config = {/* Internal pull-up/down resistor is disabled */ .pullSelect = kPORT_PullDisable, /* Low internal pull resistor value is selected. */ .pullValueSelect = kPORT_LowPullResistor, /* Fast slew rate is configured */ .slewRate = kPORT_FastSlewRate, /* Passive input filter is disabled */ .passiveFilterEnable = kPORT_PassiveFilterDisable, /* Open drain output is disabled */ .openDrainEnable = kPORT_OpenDrainDisable, /* Low drive strength is configured */ .driveStrength = kPORT_LowDriveStrength, /* Normal drive strength is configured */ .driveStrength1 = kPORT_NormalDriveStrength, /* Pin is configured as LPSPI1_SCK */ .mux = kPORT_MuxAlt2, /* Digital input enabled */ .inputBuffer = kPORT_InputBufferEnable, /* Digital input is not inverted */ .invertInput = kPORT_InputNormal, /* Pin Control Register fields [15:0] are not locked */ .lockRegister = kPORT_UnlockRegister}; /* PORT3_10 (pin 96) is configured as LPSPI1_SCK */ PORT_SetPinConfig(PORT3, 10U, &port3_10_pin96_config); const port_pin_config_t port3_11_pin95_config = {/* Internal pull-up/down resistor is disabled */ .pullSelect = kPORT_PullDisable, /* Low internal pull resistor value is selected. */ .pullValueSelect = kPORT_LowPullResistor, /* Fast slew rate is configured */ .slewRate = kPORT_FastSlewRate, /* Passive input filter is disabled */ .passiveFilterEnable = kPORT_PassiveFilterDisable, /* Open drain output is disabled */ .openDrainEnable = kPORT_OpenDrainDisable, /* Low drive strength is configured */ .driveStrength = kPORT_LowDriveStrength, /* Normal drive strength is configured */ .driveStrength1 = kPORT_NormalDriveStrength, /* Pin is configured as LPSPI1_PCS0 */ .mux = kPORT_MuxAlt2, /* Digital input enabled */ .inputBuffer = kPORT_InputBufferEnable, /* Digital input is not inverted */ .invertInput = kPORT_InputNormal, /* Pin Control Register fields [15:0] are not locked */ .lockRegister = kPORT_UnlockRegister}; /* PORT3_11 (pin 95) is configured as LPSPI1_PCS0 */ PORT_SetPinConfig(PORT3, 11U, &port3_11_pin95_config); const port_pin_config_t port3_8_pin98_config = {/* Internal pull-up/down resistor is disabled */ .pullSelect = kPORT_PullDisable, /* Low internal pull resistor value is selected. */ .pullValueSelect = kPORT_LowPullResistor, /* Fast slew rate is configured */ .slewRate = kPORT_FastSlewRate, /* Passive input filter is disabled */ .passiveFilterEnable = kPORT_PassiveFilterDisable, /* Open drain output is disabled */ .openDrainEnable = kPORT_OpenDrainDisable, /* Low drive strength is configured */ .driveStrength = kPORT_LowDriveStrength, /* Normal drive strength is configured */ .driveStrength1 = kPORT_NormalDriveStrength, /* Pin is configured as LPSPI1_SDO */ .mux = kPORT_MuxAlt2, /* Digital input enabled */ .inputBuffer = kPORT_InputBufferEnable, /* Digital input is not inverted */ .invertInput = kPORT_InputNormal, /* Pin Control Register fields [15:0] are not locked */ .lockRegister = kPORT_UnlockRegister}; /* PORT3_8 (pin 98) is configured as LPSPI1_SDO */ PORT_SetPinConfig(PORT3, 8U, &port3_8_pin98_config); const port_pin_config_t port3_9_pin97_config = {/* Internal pull-up/down resistor is disabled */ .pullSelect = kPORT_PullDisable, /* Low internal pull resistor value is selected. */ .pullValueSelect = kPORT_LowPullResistor, /* Fast slew rate is configured */ .slewRate = kPORT_FastSlewRate, /* Passive input filter is disabled */ .passiveFilterEnable = kPORT_PassiveFilterDisable, /* Open drain output is disabled */ .openDrainEnable = kPORT_OpenDrainDisable, /* Low drive strength is configured */ .driveStrength = kPORT_LowDriveStrength, /* Normal drive strength is configured */ .driveStrength1 = kPORT_NormalDriveStrength, /* Pin is configured as LPSPI1_SDI */ .mux = kPORT_MuxAlt2, /* Digital input enabled */ .inputBuffer = kPORT_InputBufferEnable, /* Digital input is not inverted */ .invertInput = kPORT_InputNormal, /* Pin Control Register fields [15:0] are not locked */ .lockRegister = kPORT_UnlockRegister}; /* PORT3_9 (pin 97) is configured as LPSPI1_SDI */ PORT_SetPinConfig(PORT3, 9U, &port3_9_pin97_config); }   4.2 LPSPI初始化 初始化 LPSPI 模块。使用 LPSPI_MasterGetDefaultConfig() 获取初始值,并根据需要进行修改。 lpspi_master_config_t masterConfig; LPSPI_MasterGetDefaultConfig(&masterConfig); masterConfig.baudRate = 500000U; LPSPI_MasterInit(LPSPI0, &masterConfig, CLOCK_GetFreq(kCLOCK_CoreSysClk));   4.3句柄定义 在 MCUXpresso SDK 驱动程序中,“句柄”是一个常用术语,指的是用于间接引用和操作资源的标识符。使用 eDMA 时,还需要为每个通道创建一个句柄,并将其传递给 LPSPI 驱动程序。此外,还可以通过传递函数指针来设置回调函数(SPI 传输完成后调用的函数)。 edma_handle_t txHandle; edma_handle_t rxHandle; lpspi_master_edma_handle_t lpspiEdmaHandle; EDMA_CreateHandle(&txHandle, DMA0, 0); EDMA_CreateHandle(&rxHandle, DMA0, 1); LPSPI_MasterTransferCreateHandleEDMA( LPSPI0, &lpspiEdmaHandle, lpspi_master_callback, NULL, &txHandle, &rxHandle );   4.4传输缓冲区和传输设置 指定具体的传输细节(缓冲区地址、传输大小)。 /*Start master transfer*/ masterXfer.txData = masterTxData; masterXfer.rxData = NULL; masterXfer.dataSize = TRANSFER_SIZE; isTransferCompleted = false;   4.5 开始 SPI传输 SPI 数据传输即将开始。此API以非阻塞方式运行。函数调用结束后, CPU将立即恢复并能够继续执行其他进程。 LPSPI_MasterTransferEDMALite(EXAMPLE_LPSPI_MASTER_BASEADDR, &g_m_edma_handle,&masterXfer);   4.6回调的概念 DMA传输设计为通过回调接收完成通知,而不是等待处理完成。这使得可以在主循环或任务端执行完成确认。在RTOS环境中,这可以用信号量或事件通知来替代。 volatile bool g_transferComplete = false; void lpspi_master_callback(LPSPI_Type *base, lpspi_master_edma_handle_t *handle, status_t status, void *userData) { if (status == kStatus_Success) { g_transferComplete = true; } }   5.常见的绊脚石 以下是每个项目常见障碍的总结。 (1)未返回数据 MOSI/MISO接线错误 引脚分配设置错误 与其他设备时序不匹配(如果从设备未先准备就绪,则传输和接收将无法正常工作)。 (2)无时钟信号 LPSPI模块时钟已禁用 PCS 的管控未达到预期效果。 (3)DMA传输未完成 DMA通道配置错误 回调注册失败 传输尺寸不匹配 (4)CS无法控制 PCS配置标志(configFlags)不正确。 另一台设备的极性设置不兼容。 (5)接收到的数据已损坏 时钟设置太快了。 FIFO/DMA/缓冲区大小不一致。 线路质量或信号波形存在问题。   6.总结   LPSPI 是 MCX A153 中实现 SPI 通信的主要串行通信模块,其设计注重低功耗和 DMA 集成。实际使用时,不仅需要正确配置 LPSPI 设置,还需要正确配置引脚设置和时钟设置。 此外,借助 MCUXpresso SDK,可以轻松实现基于 eDMA 的非阻塞通信。这使得 CPU 可以执行其他任务而无需受通信处理的限制,从而提高系统整体效率。 ========================= 即使您在本文的“评论”栏留言,我们目前也无法回复。 给您带来不便,我们深感抱歉。请在询问时参阅“NXP技术问题-联系方式(日本博客)”。 (如果您已经是NXP的代理商或与其有合作关系,可以直接向负责人咨询。) 本文 旨在为 NXP 产品新手工程师介绍 MCX A153 上的 LPSPI( 低 功耗 串行 外设 接口 ) 基本概念 以及 如何使用 MCUXpresso SDK 实现该接口。 首先,我们将概述硬件,然后以 FRDM-MCXA153 开发板为基础,通过代码示例讲解如何使用MCUXpresso SDK。 (阅读时间:20分钟) MCX 日本博客
View full article
[MCX A153] GPIO入門ガイド(日本語ブログ) 本記事では、MCX A153 に搭載されている GPIO (General Purpose Input/Output) の基本概念を解説します。またFRDM-MCXA153ボードをベースに、MCUXpresso SDK を用いたソフトウェアの実装方法を、初めてNXP製品を扱うエンジニア向けに解説します。まずハードウェアの概要を説明し、その後MCUXpresso SDKの使い方をコードスニペットとともに説明します。 (読了時間:20分) 1. GPIOモジュールの概要   1.1 GPIOの役割 GPIOは、マイコンのピンを「入力」または「出力」として制御するための最も基本的なインターフェースです。 例えば、FRDM-MCXA153においては、3色RGB LEDが以下のGPIOにそれぞれ配線されているため、GPIOを制御することで、LEDのON/OFFを切り替えることが可能です。   赤 : P3_12 緑 : P3_13 青 : P3_0 1.2 MCX A153におけるピンの制御機能 MCX A153では、ピンの制御機能は以下の2つのモジュールに分かれて管理されます。 (1) PORTモジュール 主に以下の役割を持ちます。1つのピンは複数の機能を持つため、GPIOとして使うにはPORT設定が必要です。 ピンの機能選択(GPIO / UART / SPI / I2C / PWM など) プルアップ/プルダウン設定 ドライブ能力設定   (2) GPIOモジュール 主に以下の役割を持ちます。 入出力データの制御 ピンのHigh/Low出力 入力状態の読み取り 「PORT = ピン設定」「GPIO = 実際の入出力操作」といった具合です。   2. GPIOの基本動作 GPIOモジュールには、出力モードと入力モードがあり、それぞれ以下の動作が可能です。 (1) 出力モード 以下の処理が可能 High出力 Low出力 トグル(現在の出力を反転) (2) 入力モード 以下の処理が可能 ピン電圧状態の読み取り(High or Low) 割り込み検知(立ち上がり/立ち下がり)   3. SDKドライバの基本フロー   GPIOを使用するためには、ソフトウェアによって以下の設定が必要となります。 - クロック設定 - ピン設定(PORTの設定) - 入力、または出力設定(GPIOの設定) - 割り込み設定(必要に応じて) MCUXpresso SDKのサンプルプロジェクトを例に、ドライバの使用方法を紹介します。    3.1 出力モード 以下のプロジェクトを参考に、説明します。 参考URL: Hardware requirements — MCUXpresso SDK Documentation mcuxsdk-examples/driver_examples/gpio/led_output/gpio_led_output.c at main · nxp-mcuxpresso...   3.1.1 初期化 まず、クロック、PORT、GPIOを赤色LED向けに初期化します。 #include "fsl_gpio.h" #include "fsl_port.h" // 赤色LEDに配線されたピンのパラメータ #define BOARD_INITPINS_LED_RED_PORT PORT3 #define BOARD_INITPINS_LED_RED_GPIO GPIO3 #define BOARD_INITPINS_LED_RED_PIN 12 void init_gpio(void) { // クロック有効化 CLOCK_EnableClock(kCLOCK_GateGPIO3); // PORT設定 const port_pin_config_t LED_RED = {/* Internal pull-up/down resistor is disabled */ kPORT_PullDisable, /* Low internal pull resistor value is selected. */ kPORT_LowPullResistor, /* Fast slew rate is configured */ kPORT_FastSlewRate, /* Passive input filter is disabled */ kPORT_PassiveFilterDisable, /* Open drain output is disabled */ kPORT_OpenDrainDisable, /* Low drive strength is configured */ kPORT_LowDriveStrength, /* Normal drive strength is configured */ kPORT_NormalDriveStrength, /* Pin is configured as P3_12 */ kPORT_MuxAlt0, /* Digital input enabled */ kPORT_InputBufferEnable, /* Digital input is not inverted */ kPORT_InputNormal, /* Pin Control Register fields [15:0] are not locked */ kPORT_UnlockRegister}; PORT_SetPinConfig(BOARD_INITPINS_LED_RED_PORT, BOARD_INITPINS_LED_RED_PIN, &LED_RED); // GPIO設定 gpio_pin_config_t LED_RED_config = { .pinDirection = kGPIO_DigitalOutput, .outputLogic = 0U }; GPIO_PinInit(BOARD_INITPINS_LED_RED_GPIO, BOARD_INITPINS_LED_RED_PIN, &LED_RED_config); }   3.1.2 出力操作(LED点灯/消灯/トグル) 出力値は以下のAPIによって、変更可能です。 GPIO_PinWrite(BOARD_INITPINS_LED_RED_PORT, BOARD_INITPINS_LED_RED_PIN, 1); // High GPIO_PinWrite(BOARD_INITPINS_LED_RED_PORT, BOARD_INITPINS_LED_RED_PIN, 0); // Low GPIO_PortToggle(BOARD_INITPINS_LED_RED_PORT, 1U << BOARD_INITPINS_LED_RED_PIN); // Toggle   3.2 入力モード 以下のプロジェクトを参考に、説明します。 参考URL: Hardware requirements — MCUXpresso SDK Documentation mcuxsdk-examples/driver_examples/gpio/input_interrupt/gpio_input_interrupt.c at main · nxp-mcuxpresso...   3.2.1 初期化 出力モードと引数以外同じなので、省略します。    3.2.2 入力読み取り 入力値は以下のAPIによって、読み取り可能です。 uint32_t value = GPIO_PinRead(BOARD_SW_GPIO, BOARD_SW_GPIO_PIN); if (value == 0) { // スイッチ押下(プルアップの場合) }   3.2.3 割り込み設定 立ち下り信号を、GPIO割り込みとして設定する場合は、以下のAPIを使用します。EnableIRQは、Cortex-M側の割り込み許可設定です。 GPIO_SetPinInterruptConfig(BOARD_SW_GPIO, BOARD_SW_GPIO_PIN, kGPIO_InterruptFallingEdge); EnableIRQ(BOARD_SW_IRQ); 割り込み発生時の処理は、割り込みハンドラとして、関数定義が必要です。 割り込みフラグをクリアしないと、割り込みが永久に入り続けるので、注意が必要です。 void BOARD_SW_IRQ_HANDLER(void) { /* 割り込みフラグをクリア */ GPIO_GpioClearInterruptFlags(BOARD_SW_GPIO, 1U << BOARD_SW_GPIO_PIN); // 処理 SDK_ISR_EXIT_BARRIER; } 割り込みが発生するまでの流れを以下に示します。 以上が、MCUXpresso SDKを用いた、GPIOドライバの使用方法となります。   4. よくあるつまづき もしソースコードを変更して、GPIOが期待通りに動作しない場合は、以下の項目を確認してみてください。 ピンが他の役割として設定されている → ピンがGPIOに割り当てられているかPORT設定確認 クロック未有効 → CLOCK_EnableClockを呼び出しているか確認 ピン番号の間違い → ハードウェアのピン番号と一致しているか確認 GPIO割り込みが入らない → EnableIRQでCortex-M側でも、割り込みを許可している確認 GPIO割り込みがループする → 割り込みフラグがクリアされているか確認   5. まとめ   MCX A153のGPIOは、PORTモジュールによるピン設定とGPIOモジュールによる入出力制御の2段構成で動作します。 そのため、GPIOとしてピンを使用する場合は、まずPORTモジュールでピンの割り当て設定を行い、GPIO機能を選択する必要があります。その後、GPIOモジュールを用いて入力または出力として初期化し、LEDの点灯・消灯やスイッチの状態読み取りといった操作を行います。 MCUXpresso SDKを利用すると、これらの設定や制御をライブラリAPI経由で簡潔に実装できます。 また、GPIO割り込み機能を利用することで、スイッチ押下などのイベントを効率よく検出することも可能です。GPIOが期待どおりに動作しない場合は、PORT設定の有無、対象PORTのクロック有効化、そしてピン番号の設定が正しいかを確認して下さい。   ========================= 本投稿の「Comment」欄にコメントをいただいても、現在返信に対応しておりません。 お手数をおかけしますが、お問い合わせの際には「NXPへの技術質問 - 問い合わせ方法 (日本語ブログ)」をご参照ください。 (既に弊社NXP代理店、もしくはNXPとお付き合いのある方は、直接担当者へご質問いただいてもかまいません。) 本記事では、MCX A153 に搭載されている GPIO (General Purpose Input/Output) の基本概念を解説します。またFRDM-MCXA153ボードをベースに、MCUXpresso SDK を用いたソフトウェアの実装方法を、初めてNXP製品を扱うエンジニア向けに解説します。まずハードウェアの概要を説明し、その後MCUXpresso SDKの使い方をコードスニペットとともに説明します。 (読了時間:20分) MCX 日本語ブログ
View full article
[MCX A153] LPUART入門ガイド(日本語ブログ) 本記事では、MCX A153 に搭載されている LPUART(Low Power Universal Asynchronous Receiver/Transmitter) の基本概念と、MCUXpresso SDK を用いた使用方法を、初めて NXP 製品を扱うエンジニア向けに解説します。まずハードウェアの概要を説明し、その後FRDM-MCXA153ボードをベースに、MCUXpresso SDK API の使い方をコードスニペットとともに説明します。 (読了:20分) 1. LPUART モジュール概要 LPUART は、非同期シリアル通信を実現するためのモジュールです。ここでは代表的な特徴を順に見ていきます。   非同期通信(スタートビット/ストップビット) LPUART はクロック線を使わず、データに含まれるスタートビットとストップビットでタイミングを判断します。配線が TX と RX の 2 本だけで済むため、PC との通信、センサーとの接続、デバッグログの出力など、異なる機器同士を簡単につなぐ用途に広く使われています。 割り込み/DMA対応 LPUART は、CPU が 1 バイトずつデータを処理するのではなく、ハードウェアが自動でデータ転送を補助する仕組みを備えています。割り込みを使えばイベント発生時にのみ CPU が処理を行い、DMA を使えば CPU を介さずにメモリとの間でデータを転送できます。DMA 連携を前提とした設計になっているため、高速な通信でも CPU 負荷を最小限に抑えることができます。 FIFO(バッファ)内蔵 LPUART は内部に送受信用のバッファ、いわゆる FIFO を持っています。データを一時的に蓄積できるため、通信速度と CPU や DMA の処理速度との差を吸収することができます。DMA と組み合わせることで、途切れのない連続通信が実現しやすくなります。 低消費電力動作 通常の UART よりも低消費電力で動作するよう設計されており、スリープ中でも動作を継続できるケースがあります。クロック制御と密接に連携しているため、バッテリー駆動の機器や IoT 用途で特に有用です。 複数インスタンス対応 MCU 内に LPUART を複数搭載しており、同時に複数の通信を行うことができます。デバッグ用途とセンサー通信用途を分けるなど、インスタンスごとに役割を切り分けて利用できます。 2. ソフトウェア構成(MCUXpresso SDK) MCUXpresso SDK では、LPUART を扱うドライバとしてポーリング、割り込み、eDMA の 3 種類が提供されています。 実務では、小規模な通信であれば割り込み方式で十分ですが、高速かつ連続的な通信を扱う場合は eDMA を利用します。CPU に負荷を与えたくないアプリケーションでは、最初から eDMA を使う前提で設計しておくと後々の変更が少なくて済みます。したがって、本記事では、DMAを使用する前提で話を進めます。 3. FIFO の役割と DMA DMA を正しく使うためには、まず FIFO の動作を理解することが重要です。LPUART は内部に FIFO(First-In First-Out バッファ)を持っており、送信データの一時保持、受信データの一時蓄積、そして LPUART と DMA の間に生じる速度差の吸収という役割を担っています。 DMA との連携では、受信側では LPUART が受け取ったデータが RX FIFO に蓄積され、しきい値に達したタイミングで DMA が RX FIFO からメモリへデータを転送します。送信側では、DMA がメモリから TX FIFO へデータを書き込み、LPUART が TX FIFO から順次取り出して送信します。こうした仕組みによって、DMA 転送の完了を待たずにハードウェア側で連続的にデータを受け渡すことができ、スループットを止めずに通信を継続できます。 DMA の動きを図解すると、以下のようになります。 LPUART を DMA で使う際には、LPUART の TX/RX 要求を eDMA のどのチャネルに流し込むかを決めるために、チャネル MUX の設定が必要になります。 MCX A153 では、他ファミリーで見られるような独立した DMAMUX ペリフェラルは存在せず、eDMA コントローラの各チャネルが内蔵するチャネル MUX(CHn_MUX レジスタ)で、どの周辺機能の DMA 要求ソースを受け付けるかを選択します。SDK からは EDMA_SetChannelMux() API を使ってチャネルごとに要求ソースを割り当てます(具体的な呼び出し方は 4 章で紹介します)。チャネル番号は固定ではなく、アプリケーションの用途に応じて自由に切り替えられます。 下図は、周辺機能側の多数の DMA 要求ソースが、eDMA 各チャネルに内蔵されたチャネル MUX セレクタを介してチャネル本体に接続される様子を示したものです。 上図では、 EDMA_SetChannelMux によって LPUART0 TX を Channel 0、LPUART0 RX を Channel 1 に割り当てた例を実線で示しています。点線は選択肢として存在する接続候補で、API 呼び出し時の引数を書き換えることで、たとえば LPUART0 TX を Channel 2 に割り当てるといった変更も可能です。 4. SDK ドライバの基本フロー 次に、MCUXpresso SDK のサンプルプロジェクト “lpuart_edma_transfer” を例に、ドライバの使用方法を紹介します。 参考URL: Hardware requirements — MCUXpresso SDK Documentation mcuxsdk-examples/driver_examples/lpuart/edma_transfer/lpuart_edma_transfer.c LPUART と DMA を組み合わせて使う際の基本ステップは、次の 7 つです。 クロックを有効化する ピン MUX を設定する LPUART を初期化する eDMA のチャネル MUX を設定する DMA ハンドルを生成する 送信/受信を開始する コールバックで次の処理を制御する 以降では、コードスニペットを交えながら、各ステップを具体的に説明していきます。 4.1 クロック・ポート設定 まず LPUART モジュールのクロックを有効化します。 CLOCK_EnableClock(kCLOCK_Lpuart0); 続いて、TX と RX に使用するピンの MUX を設定します。 PORT_SetPinMux(PORTA, 1U, kPORT_MuxAlt2); // TX PORT_SetPinMux(PORTA, 2U, kPORT_MuxAlt2); // RX GND を除くと、UART の配線は送信と受信の 2 本だけです。FRDM-MCXA153 の回路図では、LPUART0 の TXD と RXD が MCU-LINK の Virtual COM に接続されており、MCU-Link を PC と USB で接続することで、UART 通信を経由したデバッグが可能になります。 flowchart LR PC[PC] <-->|USB| MCULINK[MCU-LINK Virtual COM] MCULINK <-->|UART| LPUART0[MCXA153 LPUART0]   4.2 LPUART 初期化 LPUART の初期化は、まずデフォルト設定を取得してから必要な項目を変更する流れになります。 lpuart_config_t config; LPUART_GetDefaultConfig(&config); config.baudRate_Bps = 115200; config.enableTx = true; config.enableRx = true; LPUART_Init(LPUART0, &config, CLOCK_GetFreq(kCLOCK_CoreSysClk)); ボーレートは LPUART に供給されるクロック周波数に依存して決まるため、 CLOCK_GetFreq() で正しいクロックソースの周波数を渡す必要があります。TX と RX の有効化は、用途に応じて変更してください。 4.3 eDMA チャネル MUX 設定 ハンドルを生成する前に、LPUART の TX/RX 要求を eDMA のどのチャネルに流し込むかを EDMA_SetChannelMux で指定しておきます。3 章で説明したとおり、MCX A153 では独立 DMAMUX は存在せず、この API で各チャネルの CHn_MUX レジスタに要求ソースを設定します。 /* LPUART0 TX を eDMA の任意チャネル(例: CH0)に割り当てる */ EDMA_SetChannelMux(DMA0, LPUART_TX_DMA_CHANNEL, kDma0RequestMuxLPUART0Tx); /* LPUART0 RX を eDMA の任意チャネル(例: CH1)に割り当てる */ EDMA_SetChannelMux(DMA0, LPUART_RX_DMA_CHANNEL, kDma0RequestMuxLPUART0Rx); ここで指定するチャネル番号は、後続の DMA ハンドル生成時に txEdmaHandle / rxEdmaHandle に渡すチャネル番号と一致している必要があります。 4.4 DMA ハンドル生成 LPUART と DMA を結びつけるハンドルを生成し、通信完了時に呼び出されるコールバック関数をここで登録します。 lpuart_edma_handle_t g_lpuartEdmaHandle; LPUART_TransferCreateHandleEDMA(LPUART0, &g_lpuartEdmaHandle, lpuart_callback, userData, &txEdmaHandle, &rxEdmaHandle); このハンドルによって LPUART と DMA の TX/RX チャネルが関連付けられ、以降の送受信 API で利用されます。 4.5 送信(DMA) 送信は、送信バッファとサイズを lpuart_transfer_t に設定して API を呼び出すだけです。 lpuart_transfer_t xfer; xfer.data = txBuffer; xfer.dataSize = txSize; LPUART_TransferSendEDMA(LPUART0, &g_lpuartEdmaHandle, &xfer);   4.6 受信(DMA) 受信も同様に、受信バッファとサイズを指定して呼び出します。 lpuart_transfer_t xfer; xfer.data = rxBuffer; xfer.dataSize = rxSize; LPUART_TransferReceiveEDMA(LPUART0, &g_lpuartEdmaHandle, &xfer);   4.7 コールバック実装 コールバック関数を介して、通信の完了がアプリケーションに通知されます。 void lpuart_callback(LPUART_Type *base, lpuart_edma_handle_t *handle, status_t status, void *userData) { if (status == kStatus_LPUART_TxIdle) { // 送信完了処理 } else if (status == kStatus_LPUART_RxIdle) { // 受信完了処理 } } kStatus_LPUART_TxIdle は DMA による送信の完了、 kStatus_LPUART_RxIdle は DMA による受信の完了を示します。連続して受信を続けたい場合は、このコールバック内で再度 LPUART_TransferReceiveEDMA() を呼び出すことで、受信を途切れさせずに継続できます。   4.8 重要な設計ポイント 実際に LPUART と DMA を組み合わせて使う際には、いくつか押さえておきたい設計上の観点があります。 まず転送サイズです。1 回の転送サイズが小さすぎると割り込み回数が増えて CPU 効率が低下し、大きすぎると転送完了までのレイテンシが大きくなります。FIFO のサイズを意識しながら、アプリケーションの要求に合わせて適切な値を選ぶ必要があります。 次に受信バッファの設計です。受信長があらかじめ決まっている場合は固定長バッファで十分ですが、不定長のデータを受け続ける場合はリングバッファを用いるのが一般的です。 最後にコールバック処理です。コールバックは転送完了をアプリケーションに通知するだけでなく、次の DMA 転送を再設定するトリガーにもなります。連続通信を安定して回すうえで、ここの実装が最も重要な部分になります。 5. よくあるトラブル   5.1 DMA が動かない DMA クロックが有効化されていない、 EDMA_SetChannelMux で指定した要求ソースが LPUART の TX/RX と合っていない、あるいは LPUART ドライバに渡したチャネル番号と EDMA_SetChannelMux で設定したチャネル番号が一致していない、といった原因が考えられます。まずクロックの有効化と、チャネル MUX の割り当ての一致を確認するのが近道です。 5.2 データ欠落 FIFO のオーバーランや、転送サイズの設定が実際のデータ量に合っていないケースが典型的です。FIFO しきい値と DMA の転送単位の関係を見直してください。 5.3 高速通信で破綻 ボーレートを上げていくと、FIFO のアンダーラン、バッファ設計の不足、波形品質の低下、クロック誤差といった要因が顕在化してきます。ハードウェア側の信号品質と、ソフトウェア側のバッファ供給能力の両面から原因を切り分ける必要があります。 6. まとめ LPUART を実務で使いこなすうえで最も重要なのは、FIFO の役割を正しく理解し、DMA との連携を踏まえてデータバッファを設計することです。これらを押さえておけば、低消費電力かつ CPU 負荷の小さい、安定した UART 通信を実現することができます。 ========================= 本投稿の「Comment」欄にコメントをいただいても、現在返信に対応しておりません。 お手数をおかけしますが、お問い合わせの際には「NXPへの技術質問 - 問い合わせ方法 (日本語ブログ)」をご参照ください。 (既に弊社 NXP 代理店、もしくは NXP とお付き合いのある方は、直接担当者へご質問いただいてもかまいません。) 本記事では、MCX A153 に搭載されている LPUART(Low Power Universal Asynchronous Receiver/Transmitter) の基本概念と、MCUXpresso SDK を用いた使用方法を、初めて NXP 製品を扱うエンジニア向けに解説します。まずハードウェアの概要を説明し、その後FRDM-MCXA153ボードをベースに、MCUXpresso SDK API の使い方をコードスニペットとともに説明します。 (読了:20分) MCUXpresso SDK MCX 日本語ブログ
View full article
[MCX A153] eDMA Introduction Guide (Japanese Blog) This article explains the basic concepts of eDMA( Enhanced Direct Memory Access ) on the MCX A153 and how to use it with the MCUXpresso SDK , aimed at engineers who are new to NXP products. First, we will explain the hardware overview, and then, using the FRDM-MCXA153 board as a base, we will explain how to use the MCUXpresso SDK with code snippets. (Reading time: 20 minutes)   1. What is eDMA?   eDMA is hardware that transfers data between memory and peripherals, or between memory devices, without involving the CPU. When data transfer is performed by the CPU, the CPU itself needs to repeatedly read the data from the source and write it to the destination. Therefore, the CPU load increases as the amount of data transferred increases. On the other hand, when using eDMA, the CPU only needs to set the transfer conditions (source address, destination address, transfer size, etc.) and start eDMA. Since the actual data transfer is performed by the eDMA hardware, the CPU can perform other tasks in parallel, such as communication processing and application processing. This has a significant effect on reducing CPU load and improving real-time performance, especially in applications that involve continuous data transfer such as UART and SPI. Typical uses of eDMA include the following: ADC conversion results are automatically stored in RAM. LPUART received data is stored in RAM. Transfer LPSPI transmission data to FIFO Copying from external Flash to TCM (Tightly Coupled Memory) Periodic transfer combined with PWM or timer 2. eDMA configuration of MCX A153   The MCXA153 features four eDMA channels , each operating independently. Forwarding requests to each channel can be issued, for example, from the following: LPUART LPSPI LPI2C ADC CTIMER FlexPWM Software Requirements 3. Basic Concepts of eDMA   3.1 TCD   Understanding the TCD (Transfer Control Descriptor) is crucial when considering eDMA settings . A TCD is a transfer descriptor that defines "where to transfer from, where to transfer from, how many bytes to transfer, and how many times to transfer." eDMA operates according to the TCD. Typical TCD parameters are shown below.   item meaning SADDR Source address DADDR Destination Address SOFF Source address increment per transfer DOFF Destination increment per transfer NBYTES Minor Loop Size CITER Remaining Major Loops BITER Initial Major Loop Count SLAST Source correction value after transfer is complete DLASTSGA Destination correction value after transfer is complete 3.2.Minor Loop and Major Loop   This is the part that causes the most confusion for people using eDMA for the first time.   Minor Loop   This refers to the amount of data transferred in a single DMA request. For example, if NBYTES is set to 4, 4 bytes of data will be transferred each time a DMA request occurs. In other words, Minor Loop is a parameter that represents the "amount of data transferred per DMA request".   Major Loop   This refers to the number of times the Minor Loop is repeated. For example, if NBYTES is set to 4 and BITER to 100, the DMA will repeat the transfer of 4 bytes 100 times. As a result, a total of 400 bytes of data will be transferred. In short, Major Loop is a parameter that represents "how many times the Minor Loop is repeated".   3.3.Understanding eDMA through pseudocode The operation of eDMA can be easier to understand if you think of it as follows: Please keep the following points in mind. NBYTES/SIZE is the number of Minor Loops BITER is the number of Major Loops SOFF/DOFF updates the address for each transfer. SLAST/DLAST allows data to be restored after transfer is complete ( this mechanism enables the implementation of a ring buffer). size_t *src,*dst; src=saddr; dst = daddr; for(citer = biter; citer>0; citer--) // major loop { for(i = 0; i 4. Basic Flow of SDK Drivers   To use eDMA, the following settings are required by the software: eDMA module initialization eDMA handle definition TCD settings Transfer execution This guide will demonstrate how to use the driver , using a sample project from the MCUXpresso SDK as an example . Reference URL: Hardware requirements — MCUXpresso SDK Documentation mcuxsdk-examples/driver_examples/edma4/memory_to_memory/edma_memory_to_memory.c at main · nxp-mcuxpresso/mcuxsdk-examples   4.1 eDMA initialization This initializes the eDMA module. Obtain the initial values using EDMA_GetDefaultConfig() and modify them as needed. edma_config_t config; EDMA_GetDefaultConfig(&config); EDMA_Init(DMA0, &config); 4.2 Transfer Settings   This is the most important API in the SDK sample. edma_transfer_config_t transferConfig; EDMA_PrepareTransfer(&transferConfig, srcAddr, sizeof(srcAddr[0]), destAddr, sizeof(destAddr[0]), sizeof(destAddr), sizeof(destAddr), kEDMA_MemoryToMemory); EDMA_SetTransferConfig(EXAMPLE_DMA_BASEADDR, DEMO_DMA_CHANNEL_0, &transferConfig, NULL); EnableIRQ(DMA_CH0_IRQn); Meaning of arguments:   argument meaning srcBuffer Source srcWidth Transfer unit dstBuffer Forwarding destination dstWidth Transfer unit minorBytes Minor Loop Size totalBytes Total transfer volume Type Transfer type 4.3 Transfer Start EDMA_TriggerChannelStart(EXAMPLE_DMA_BASEADDR, DEMO_DMA_CHANNEL_0); This will start the DMA operation.   4.4 Callback DMA transfers are designed to receive completion notifications via callbacks instead of waiting for processing to finish. This allows completion confirmation to be performed on the main loop or task side. In an RTOS environment, this can be replaced with semaphores or event notifications. /* EDMA transfer channel 0 IRQ handler */ void DMA_CH0_IRQHandler(void) { if ((EDMA_GetChannelStatusFlags(EXAMPLE_DMA_BASEADDR, DEMO_DMA_CHANNEL_0) & kEDMA_InterruptFlag) != 0U) { EDMA_ClearChannelStatusFlags(EXAMPLE_DMA_BASEADDR, DEMO_DMA_CHANNEL_0, kEDMA_InterruptFlag); g_Transfer_Done = true; } }     5. Common stumbling blocks Below is a summary of common stumbling blocks for each item. Transfer not starting Is the DMA initialized? Is the channel number correct? Stopped during transfer NBYTES settings BITER settings Alignment violation   Data corruption Transfer size (8/16/32bit) SOFF/DOFF setting Buffer size 6. Summary   The MCXA153's eDMA is a high-performance 4-channel DMA. Understanding the meaning of the TCD parameters is crucial. Many other introductory guides also introduce projects using eDMA , so please be sure to read them.     ========================= We are currently unable to respond to comments left in the "Comment" section of this post. We apologize for the inconvenience, but when making an inquiry, please use the subject line " Technical Questions to NXP". - How to contact us Please refer to the "( Japanese blog) " section. (If you are already an NXP distributor or have a relationship with NXP, you may ask your representative directly.) This article explains the basic concepts of eDMA( Enhanced Direct Memory Access ) on the MCX A153 and how to use it with the MCUXpresso SDK , aimed at engineers who are new to NXP products. First, we will explain the hardware overview, and then, using the FRDM-MCXA153 board as a base, we will explain how to use the MCUXpresso SDK with code snippets. MCX Japanese Blog
View full article
[MCX A153] LPSPI入門ガイド(日本語ブログ) 本記事では、MCX A153 に搭載されている LPSPI(Low Power Serial Peripheral Interface)の基本概念と、MCUXpresso SDK を用いた実装方法を、初めてNXP製品を扱うエンジニア向けに解説します。まずハードウェアの概要を説明し、その後FRDM-MCXA153ボードをベースに、MCUXpresso SDKの使い方をコードスニペットとともに説明します。 (読了:20分) 1. LPSPIモジュール概要   1.1 LPSPIとは   LPSPI は、外部デバイスとの同期シリアル通信を行うための周辺モジュールです。 ここでの "LP(Low Power)" とは「低消費電力で動作できる設計」 を意味します。   通常のSPIとの違い(Low Powerの視点) 一般的なSPIモジュールと比較したときの LPSPI の特徴は以下です。 低消費電力モード(Stop / Sleep)でも動作継続可能 DMA(eDMA)と連携し、CPU介在を減らすことでシステム全体の電力削減 ハードウェアトリガ(HREQなど)でCPUを起こさず通信開始が可能 LPSPI は「単にSPI通信ができる」だけではなく、 「システム全体を低消費電力で運用するための通信モジュール」として設計されています。   1.2 MCX A153における構成 MCX A153 には複数の LPSPI インスタンスがあり、例えば、以下のような信号が使用されます: CS (P1_3) SCK (P1_1) SDI (P1_2) SDO (P1_0) 2. LPSPIの基本動作   2.1 信号の役割 SPI通信では、基本的に以下の4線を使用して、通信します。 SPI通信には極性と位相によって、4つのモードがありますが、例えばモード0の場合、それぞれの信号は、以下のタイミングチャートに従います。   2.2 FIFOの役割 LPSPI は内部に FIFO を持っており、送信データ・受信データを一時的に保持できます。 これにより、CPU が 1 バイトずつ即時にレジスタ操作しなくても、ある程度まとめてデータを処理できます。さらに eDMA を組み合わせることで、FIFO へのデータ供給/取り出しを CPU の代わりに自動化できます。 3. DMA(eDMA)転送の基本概念   3.1 なぜ DMA を使うのか SPI で数バイトだけ送る用途なら単純なポーリングでも動作しますが、実際の組み込み開発では以下の要求が多くあります。 センサデータや表示データなどを連続転送したい CPU を通信待ちで止めたくない 他の制御処理や RTOS タスクと並行動作したい 通信処理の負荷を下げたい   ここで重要になる考え方が「ノンブロッキング(Non-blocking)」です。 ノンブロッキングとは、「処理の完了を待たずにすぐに関数が戻る動作」のことです。 例えば SPI 通信の場合、通常は以下のような2つの動作モデルがあります。 ブロッキング(Blocking) 送信関数を呼ぶと、通信が終わるまでCPUが待ち続ける 通信中は他の処理ができない ノンブロッキング(Non-blocking) 送信開始だけ行い、すぐに関数が戻る 実際の通信はバックグラウンド(DMAなど)で進む CPUはその間に他の処理を実行できる LPSPI + eDMA を使うと、データ転送の大部分をハードウェア側に任せることができるため、ノンブロッキング通信を実現する事が可能となります。   3.2 DMA転送の考え方 DMA 転送では、CPU は最初に「どこから送るか」「どこへ受けるか」「何バイト送るか」を設定し、転送開始を指示します。 その後は、LPSPI の FIFO 要求に応じて eDMA が自動的にデータ転送を進めます。CPU は待機せず、他の処理を続けることができます。   3.3 動作イメージ DMA転送時の流れは概ね以下の通りです。 CPU が LPSPI と eDMA を初期化 送信バッファ / 受信バッファ / サイズを設定 CPU が DMA転送開始を指示 eDMA が FIFO 要求に応じてデータを搬送 転送完了時にコールバックで通知  4. SDKドライバの基本フロー LPSPIを使用するためには、ソフトウェアによって以下の設定が必要となります。 クロック・ピンを設定 LPSPIモジュール初期化 eDMAハンドル定義 LPSPIハンドル生成 転送バッファ設定 転送実行 コールバックで完了確認 MCUXpresso SDKのサンプルプロジェクトを例に、ドライバの使用方法を紹介します。  以下のプロジェクトを参考に、説明します。 参考URL: Hardware requirements — MCUXpresso SDK Documentation mcuxsdk-examples/driver_examples/lpspi/edma_transfer/lpspi_edma_transfer.cc at main · nxp-mcuxpresso/mcuxsdk-examples   4.1 クロック設定・ピン設定 まず、クロック、PORTをLPSPI0に初期化します。 クロック有効化を忘れると物理的に動きません。PORTの割り当て設定(MuxAlt)がLPSPI0に一致している事が重要です。 /* クロック有効化 */ void BOARD_InitHardware(void) { /* Attach peripheral clock */ CLOCK_SetClockDiv(kCLOCK_DivLPSPI0, 1u); CLOCK_AttachClk(kFRO12M_to_LPSPI0); } /* PORT設定 */ /* PORT1: Peripheral clock is enabled */ CLOCK_EnableClock(kCLOCK_GatePORT1); /* PORT3: Peripheral clock is enabled */ CLOCK_EnableClock(kCLOCK_GatePORT3); /* LPSPI0 peripheral is released from reset */ RESET_ReleasePeripheralReset(kLPSPI0_RST_SHIFT_RSTn); /* PORT1 peripheral is released from reset */ RESET_ReleasePeripheralReset(kPORT1_RST_SHIFT_RSTn); /* LPSPI1 peripheral is released from reset */ RESET_ReleasePeripheralReset(kLPSPI1_RST_SHIFT_RSTn); /* PORT3 peripheral is released from reset */ RESET_ReleasePeripheralReset(kPORT3_RST_SHIFT_RSTn); const port_pin_config_t port1_0_pin135_config = {/* Internal pull-up/down resistor is disabled */ .pullSelect = kPORT_PullDisable, /* Low internal pull resistor value is selected. */ .pullValueSelect = kPORT_LowPullResistor, /* Fast slew rate is configured */ .slewRate = kPORT_FastSlewRate, /* Passive input filter is disabled */ .passiveFilterEnable = kPORT_PassiveFilterDisable, /* Open drain output is disabled */ .openDrainEnable = kPORT_OpenDrainDisable, /* Low drive strength is configured */ .driveStrength = kPORT_LowDriveStrength, /* Normal drive strength is configured */ .driveStrength1 = kPORT_NormalDriveStrength, /* Pin is configured as LPSPI0_SDO */ .mux = kPORT_MuxAlt2, /* Digital input enabled */ .inputBuffer = kPORT_InputBufferEnable, /* Digital input is not inverted */ .invertInput = kPORT_InputNormal, /* Pin Control Register fields [15:0] are not locked */ .lockRegister = kPORT_UnlockRegister}; /* PORT1_0 (pin 135) is configured as LPSPI0_SDO */ PORT_SetPinConfig(PORT1, 0U, &port1_0_pin135_config); const port_pin_config_t port1_1_pin136_config = {/* Internal pull-up/down resistor is disabled */ .pullSelect = kPORT_PullDisable, /* Low internal pull resistor value is selected. */ .pullValueSelect = kPORT_LowPullResistor, /* Fast slew rate is configured */ .slewRate = kPORT_FastSlewRate, /* Passive input filter is disabled */ .passiveFilterEnable = kPORT_PassiveFilterDisable, /* Open drain output is disabled */ .openDrainEnable = kPORT_OpenDrainDisable, /* Low drive strength is configured */ .driveStrength = kPORT_LowDriveStrength, /* Normal drive strength is configured */ .driveStrength1 = kPORT_NormalDriveStrength, /* Pin is configured as LPSPI0_SCK */ .mux = kPORT_MuxAlt2, /* Digital input enabled */ .inputBuffer = kPORT_InputBufferEnable, /* Digital input is not inverted */ .invertInput = kPORT_InputNormal, /* Pin Control Register fields [15:0] are not locked */ .lockRegister = kPORT_UnlockRegister}; /* PORT1_1 (pin 136) is configured as LPSPI0_SCK */ PORT_SetPinConfig(PORT1, 1U, &port1_1_pin136_config); const port_pin_config_t port1_2_pin137_config = {/* Internal pull-up/down resistor is disabled */ .pullSelect = kPORT_PullDisable, /* Low internal pull resistor value is selected. */ .pullValueSelect = kPORT_LowPullResistor, /* Fast slew rate is configured */ .slewRate = kPORT_FastSlewRate, /* Passive input filter is disabled */ .passiveFilterEnable = kPORT_PassiveFilterDisable, /* Open drain output is disabled */ .openDrainEnable = kPORT_OpenDrainDisable, /* Low drive strength is configured */ .driveStrength = kPORT_LowDriveStrength, /* Normal drive strength is configured */ .driveStrength1 = kPORT_NormalDriveStrength, /* Pin is configured as LPSPI0_SDI */ .mux = kPORT_MuxAlt2, /* Digital input enabled */ .inputBuffer = kPORT_InputBufferEnable, /* Digital input is not inverted */ .invertInput = kPORT_InputNormal, /* Pin Control Register fields [15:0] are not locked */ .lockRegister = kPORT_UnlockRegister}; /* PORT1_2 (pin 137) is configured as LPSPI0_SDI */ PORT_SetPinConfig(PORT1, 2U, &port1_2_pin137_config); const port_pin_config_t port1_3_pin138_config = {/* Internal pull-up/down resistor is disabled */ .pullSelect = kPORT_PullDisable, /* Low internal pull resistor value is selected. */ .pullValueSelect = kPORT_LowPullResistor, /* Fast slew rate is configured */ .slewRate = kPORT_FastSlewRate, /* Passive input filter is disabled */ .passiveFilterEnable = kPORT_PassiveFilterDisable, /* Open drain output is disabled */ .openDrainEnable = kPORT_OpenDrainDisable, /* Low drive strength is configured */ .driveStrength = kPORT_LowDriveStrength, /* Normal drive strength is configured */ .driveStrength1 = kPORT_NormalDriveStrength, /* Pin is configured as LPSPI0_PCS0 */ .mux = kPORT_MuxAlt2, /* Digital input enabled */ .inputBuffer = kPORT_InputBufferEnable, /* Digital input is not inverted */ .invertInput = kPORT_InputNormal, /* Pin Control Register fields [15:0] are not locked */ .lockRegister = kPORT_UnlockRegister}; /* PORT1_3 (pin 138) is configured as LPSPI0_PCS0 */ PORT_SetPinConfig(PORT1, 3U, &port1_3_pin138_config); const port_pin_config_t port3_10_pin96_config = {/* Internal pull-up/down resistor is disabled */ .pullSelect = kPORT_PullDisable, /* Low internal pull resistor value is selected. */ .pullValueSelect = kPORT_LowPullResistor, /* Fast slew rate is configured */ .slewRate = kPORT_FastSlewRate, /* Passive input filter is disabled */ .passiveFilterEnable = kPORT_PassiveFilterDisable, /* Open drain output is disabled */ .openDrainEnable = kPORT_OpenDrainDisable, /* Low drive strength is configured */ .driveStrength = kPORT_LowDriveStrength, /* Normal drive strength is configured */ .driveStrength1 = kPORT_NormalDriveStrength, /* Pin is configured as LPSPI1_SCK */ .mux = kPORT_MuxAlt2, /* Digital input enabled */ .inputBuffer = kPORT_InputBufferEnable, /* Digital input is not inverted */ .invertInput = kPORT_InputNormal, /* Pin Control Register fields [15:0] are not locked */ .lockRegister = kPORT_UnlockRegister}; /* PORT3_10 (pin 96) is configured as LPSPI1_SCK */ PORT_SetPinConfig(PORT3, 10U, &port3_10_pin96_config); const port_pin_config_t port3_11_pin95_config = {/* Internal pull-up/down resistor is disabled */ .pullSelect = kPORT_PullDisable, /* Low internal pull resistor value is selected. */ .pullValueSelect = kPORT_LowPullResistor, /* Fast slew rate is configured */ .slewRate = kPORT_FastSlewRate, /* Passive input filter is disabled */ .passiveFilterEnable = kPORT_PassiveFilterDisable, /* Open drain output is disabled */ .openDrainEnable = kPORT_OpenDrainDisable, /* Low drive strength is configured */ .driveStrength = kPORT_LowDriveStrength, /* Normal drive strength is configured */ .driveStrength1 = kPORT_NormalDriveStrength, /* Pin is configured as LPSPI1_PCS0 */ .mux = kPORT_MuxAlt2, /* Digital input enabled */ .inputBuffer = kPORT_InputBufferEnable, /* Digital input is not inverted */ .invertInput = kPORT_InputNormal, /* Pin Control Register fields [15:0] are not locked */ .lockRegister = kPORT_UnlockRegister}; /* PORT3_11 (pin 95) is configured as LPSPI1_PCS0 */ PORT_SetPinConfig(PORT3, 11U, &port3_11_pin95_config); const port_pin_config_t port3_8_pin98_config = {/* Internal pull-up/down resistor is disabled */ .pullSelect = kPORT_PullDisable, /* Low internal pull resistor value is selected. */ .pullValueSelect = kPORT_LowPullResistor, /* Fast slew rate is configured */ .slewRate = kPORT_FastSlewRate, /* Passive input filter is disabled */ .passiveFilterEnable = kPORT_PassiveFilterDisable, /* Open drain output is disabled */ .openDrainEnable = kPORT_OpenDrainDisable, /* Low drive strength is configured */ .driveStrength = kPORT_LowDriveStrength, /* Normal drive strength is configured */ .driveStrength1 = kPORT_NormalDriveStrength, /* Pin is configured as LPSPI1_SDO */ .mux = kPORT_MuxAlt2, /* Digital input enabled */ .inputBuffer = kPORT_InputBufferEnable, /* Digital input is not inverted */ .invertInput = kPORT_InputNormal, /* Pin Control Register fields [15:0] are not locked */ .lockRegister = kPORT_UnlockRegister}; /* PORT3_8 (pin 98) is configured as LPSPI1_SDO */ PORT_SetPinConfig(PORT3, 8U, &port3_8_pin98_config); const port_pin_config_t port3_9_pin97_config = {/* Internal pull-up/down resistor is disabled */ .pullSelect = kPORT_PullDisable, /* Low internal pull resistor value is selected. */ .pullValueSelect = kPORT_LowPullResistor, /* Fast slew rate is configured */ .slewRate = kPORT_FastSlewRate, /* Passive input filter is disabled */ .passiveFilterEnable = kPORT_PassiveFilterDisable, /* Open drain output is disabled */ .openDrainEnable = kPORT_OpenDrainDisable, /* Low drive strength is configured */ .driveStrength = kPORT_LowDriveStrength, /* Normal drive strength is configured */ .driveStrength1 = kPORT_NormalDriveStrength, /* Pin is configured as LPSPI1_SDI */ .mux = kPORT_MuxAlt2, /* Digital input enabled */ .inputBuffer = kPORT_InputBufferEnable, /* Digital input is not inverted */ .invertInput = kPORT_InputNormal, /* Pin Control Register fields [15:0] are not locked */ .lockRegister = kPORT_UnlockRegister}; /* PORT3_9 (pin 97) is configured as LPSPI1_SDI */ PORT_SetPinConfig(PORT3, 9U, &port3_9_pin97_config); }   4.2 LPSPI 初期化 LPSPIモジュールの初期化を行います。LPSPI_MasterGetDefaultConfig() で初期値を取得して、用途に応じて変更してください。 lpspi_master_config_t masterConfig; LPSPI_MasterGetDefaultConfig(&masterConfig); masterConfig.baudRate = 500000U; LPSPI_MasterInit(LPSPI0, &masterConfig, CLOCK_GetFreq(kCLOCK_CoreSysClk));   4.3 ハンドル定義 ハンドルは、MCUXpresso SDKのドライバではよく使われる単語であり、あるリソースを間接的に参照・操作するための識別子のことです。eDMAを使用する場合もチャンネルごとにハンドルを作り、それをLPSPIのドライバに渡す必要があります。関数ポインタを渡すことで、コールバック(SPI転送終了時に呼び出される関数)を設定することも出来ます。 edma_handle_t txHandle; edma_handle_t rxHandle; lpspi_master_edma_handle_t lpspiEdmaHandle; EDMA_CreateHandle(&txHandle, DMA0, 0); EDMA_CreateHandle(&rxHandle, DMA0, 1); LPSPI_MasterTransferCreateHandleEDMA( LPSPI0, &lpspiEdmaHandle, lpspi_master_callback, NULL, &txHandle, &rxHandle );   4.4 転送バッファと転送設定 具体的な転送内容(バッファのアドレス、転送サイズ)を指定します。 /*Start master transfer*/ masterXfer.txData = masterTxData; masterXfer.rxData = NULL; masterXfer.dataSize = TRANSFER_SIZE; isTransferCompleted = false;   4.5 SPI転送開始 SPI転送を開始します。この API はノンブロッキングで動作します。関数呼び出し後、CPU はすぐに復帰し、他の処理を継続できます。 LPSPI_MasterTransferEDMALite(EXAMPLE_LPSPI_MASTER_BASEADDR, &g_m_edma_handle,&masterXfer);   4.6 コールバックの考え方 DMA 転送では、処理完了を待つ代わりにコールバックで完了を受け取る設計にします。これにより、メインループ側やタスク側で完了確認が可能です。RTOS 環境ならセマフォやイベント通知に置き換え可能です。 volatile bool g_transferComplete = false; void lpspi_master_callback(LPSPI_Type *base, lpspi_master_edma_handle_t *handle, status_t status, void *userData) { if (status == kStatus_Success) { g_transferComplete = true; } }   5. よくあるつまずき 以下に各項目ごとに、つまずきがちなポイントをまとめました。 (1) データが返らない MOSI / MISO の配線ミス ピン割り当て設定ミス 相手デバイスとのタイミングミスマッチ(スレーブが先に待機しないと、正常に送受信できません) (2) クロックが出ない LPSPI モジュールクロック未有効 PCS が期待どおり制御されていない (3) DMA転送が完了しない DMA チャネル設定ミス コールバック登録漏れ 転送サイズ不一致 (4) CS が制御できない PCS 設定フラグ(configFlags)不備 相手デバイス側の極性設定と不一致 (5) 受信データが崩れる クロック設定が速すぎる FIFO / DMA / バッファサイズの整合が取れていない 配線品質や信号波形に問題がある   6. まとめ   LPSPI は、MCX A153 における SPI 通信を実現するための主要なシリアル通信モジュールであり、低消費電力動作や DMA 連携を考慮して設計されています。実際に使用する際には、LPSPI の設定だけでなく、ピン設定、やクロック設定を正しく行うことが重要です。 また、MCUXpresso SDKを利用することで、eDMA を用いたノンブロッキング通信を容易に実装できます。これにより、CPU は通信処理に拘束されることなく他の処理を実行でき、システム全体の効率向上につながります。 ========================= 本投稿の「Comment」欄にコメントをいただいても、現在返信に対応しておりません。 お手数をおかけしますが、お問い合わせの際には「NXPへの技術質問 - 問い合わせ方法 (日本語ブログ)」をご参照ください。 (既に弊社NXP代理店、もしくはNXPとお付き合いのある方は、直接担当者へご質問いただいてもかまいません。) 本記事では、MCX A153 に搭載されている LPSPI(Low Power Serial Peripheral Interface)の基本概念と、MCUXpresso SDK を用いた実装方法を、初めてNXP製品を扱うエンジニア向けに解説します。まずハードウェアの概要を説明し、その後FRDM-MCXA153ボードをベースに、MCUXpresso SDKの使い方をコードスニペットとともに説明します。 (読了:20分) MCX 日本語ブログ
View full article
[MCX A153] LPUART Introduction Guide (Japanese Blog) This article explains the basic concepts of LPUART ( Low Power Universal Asynchronous Receiver / Transmitter ) on the MCX A153 and how to use it with the MCUXpresso SDK, aimed at engineers who are new to NXP products. First, we will explain the hardware overview, and then, using the FRDM-MCXA153 board as a base, we will explain how to use the MCUXpresso SDK API with code snippets. (Reading time: 20 minutes) 1. LPUART Module Overview LPUART is a module for implementing asynchronous serial communication. Here, we will look at its key features in order.   Asynchronous communication (start bit/stop bit) LPUART does not use a clock line; instead, it determines timing using start and stop bits included in the data. Because it only requires two wires, TX and RX, it is widely used for easily connecting different devices, such as communicating with a PC, connecting to sensors, and outputting debug logs. Interrupt/DMA compatible LPUART features a mechanism where hardware automatically assists with data transfer, rather than the CPU processing data byte by byte. Using interrupts, the CPU only processes data when an event occurs, and using DMA, data can be transferred to and from memory without CPU intervention. Because it's designed with DMA integration in mind, CPU load can be minimized even during high-speed communication. Built-in FIFO (buffer) LPUART has an internal buffer for sending and receiving data, also known as a FIFO. Because it can temporarily store data, it can absorb the difference between the communication speed and the processing speed of the CPU or DMA. When combined with DMA, it makes it easier to achieve uninterrupted, continuous communication. Low power operation Designed to operate with lower power consumption than a standard UART, it can sometimes continue operating even while in sleep mode. Because it works closely with clock control, it is particularly useful for battery-powered devices and IoT applications. Supports multiple instances The MCU has multiple LPUARTs, allowing for simultaneous communication of multiple devices. This enables you to separate roles for each instance, such as separating debugging and sensor communication. 2. Software Configuration (MCUXpresso SDK) The MCUXpresso SDK provides three types of drivers for handling LPUART: polling, interrupt, and eDMA. In practical applications, interrupt-based communication is sufficient for small-scale communications, but eDMA is used for high-speed, continuous communications. For applications where you don't want to burden the CPU, designing with eDMA in mind from the start will minimize future changes. Therefore, this article will proceed on the assumption that DMA is being used. 3. The role of FIFO and DMA To use DMA correctly, it's essential to first understand how FIFOs work. LPUART has an internal FIFO (First-In First-Out buffer) that plays the role of temporarily holding transmitted data, temporarily storing received data, and absorbing the speed difference that occurs between LPUART and DMA. In DMA integration, on the receiving side, data received by the LPUART is stored in the RX FIFO, and when a threshold is reached, the DMA transfers the data from the RX FIFO to memory. On the transmitting side, the DMA writes data from memory to the TX FIFO, and the LPUART sequentially retrieves and transmits the data from the TX FIFO. This mechanism allows for continuous data transfer on the hardware side without waiting for the DMA transfer to complete, enabling continuous communication without interrupting throughput. The operation of DMA can be illustrated as follows: When using LPUART with DMA, you need to configure the channel MUX to determine which eDMA channel the LPUART's TX/RX requests should be routed through. In the MCX A153, there is no separate DMAMUX peripheral as seen in other families. Instead, each channel of the eDMA controller has a built-in channel MUX (CHn_MUX register) that selects which peripheral function's DMA request source it will accept. The SDK assigns request sources to each channel using the EDMA_SetChannelMux() API (the specific calling method is described in Chapter 4). The channel number is not fixed and can be freely switched depending on the application's use. The diagram below illustrates how multiple DMA request sources on the peripheral function side are connected to the channel body via a channel MUX selector built into each eDMA channel. In the diagram above, the solid lines show an example where LPUART0 TX is assigned to Channel 0 and LPUART0 RX to Channel 1 using EDMA_SetChannelMux . The dotted lines represent available connection options, and by rewriting the arguments when calling the API, it is possible to change other assignments, such as assigning LPUART0 TX to Channel 2. 4. Basic Flow of SDK Drivers Next, we will demonstrate how to use the driver using the MCUXpresso SDK sample project "lpuart_edma_transfer" as an example. Reference URL: Hardware requirements — MCUXpresso SDK Documentation mcuxsdk-examples/driver_examples/lpuart/edma_transfer/lpuart_edma_transfer.c The following seven steps are the basic steps when using LPUART and DMA together: Enable the clock. Configure pin MUX Initialize the LPUART. Configure the eDMA channel MUX. Generate a DMA handle Start sending/receiving The next process is controlled by the callback. In the following sections, we will explain each step in detail, including code snippets. 4.1 Clock Port Settings First, enable the clock on the LPUART module. CLOCK_EnableClock(kCLOCK_Lpuart0); Next, we configure the MUX pins used for TX and RX. PORT_SetPinMux(PORTA, 1U, kPORT_MuxAlt2); // TX PORT_SetPinMux(PORTA, 2U, kPORT_MuxAlt2); // RX Aside from GND, the UART wiring consists of only two wires: transmit and receive. In the FRDM-MCXA153 circuit diagram, the TXD and RXD of LPUART0 are connected to the MCU-LINK's Virtual COM, and by connecting the MCU-Link to a PC via USB, debugging via UART communication becomes possible. flowchart LR PC[PC] <-->|USB| MCULINK[MCU-LINK Virtual COM] MCULINK <-->|UART| LPUART0[MCXA153 LPUART0]   4.2 LPUART initialization Initializing the LPUART involves first obtaining the default settings and then modifying the necessary items. lpuart_config_t config; LPUART_GetDefaultConfig(&config); config.baudRate_Bps = 115200; config.enableTx = true; config.enableRx = true; LPUART_Init(LPUART0, &config, CLOCK_GetFreq(kCLOCK_CoreSysClk)); The baud rate depends on the clock frequency supplied to the LPUART, so you need to pass the correct clock source frequency in CLOCK_GetFreq() . Enable TX and RX as needed. 4.3 eDMA Channel MUX Settings Before generating the handle, you specify with EDMA_SetChannelMux which eDMA channel to route the LPUART TX/RX requests to. As explained in Chapter 3, the MCX A153 does not have an independent DMAMUX, and this API sets the request source in the CHn_MUX register for each channel. /* LPUART0 TX を eDMA の任意チャネル(例: CH0)に割り当てる */ EDMA_SetChannelMux(DMA0, LPUART_TX_DMA_CHANNEL, kDma0RequestMuxLPUART0Tx); /* LPUART0 RX を eDMA の任意チャネル(例: CH1)に割り当てる */ EDMA_SetChannelMux(DMA0, LPUART_RX_DMA_CHANNEL, kDma0RequestMuxLPUART0Rx); The channel number specified here must match the channel number passed to txEdmaHandle / rxEdmaHandle when generating the subsequent DMA handle. 4.4 DMA Handle Generation A handle is created to link LPUART and DMA, and a callback function is registered here to be called when communication is complete. lpuart_edma_handle_t g_lpuartEdmaHandle; LPUART_TransferCreateHandleEDMA(LPUART0, &g_lpuartEdmaHandle, lpuart_callback, userData, &txEdmaHandle, &rxEdmaHandle); This handle associates the LPUART and DMA TX/RX channels, which are then used by subsequent transmit and receive APIs. 4.5 Transmission (DMA) Sending is as simple as calling the API with the send buffer and size set to lpuart_transfer_t . lpuart_transfer_t xfer; xfer.data = txBuffer; xfer.dataSize = txSize; LPUART_TransferSendEDMA(LPUART0, &g_lpuartEdmaHandle, &xfer);   4.6 Receiving (DMA) Similarly, receiving is also done by specifying the receive buffer and size when calling the function. lpuart_transfer_t xfer; xfer.data = rxBuffer; xfer.dataSize = rxSize; LPUART_TransferReceiveEDMA(LPUART0, &g_lpuartEdmaHandle, &xfer);   4.7 Callback Implementation The application is notified of the completion of the communication via a callback function. void lpuart_callback(LPUART_Type *base, lpuart_edma_handle_t *handle, status_t status, void *userData) { if (status == kStatus_LPUART_TxIdle) { // 送信完了処理 } else if (status == kStatus_LPUART_RxIdle) { // 受信完了処理 } } kStatus_LPUART_TxIdle kStatus_LPUART_RxIdle indicates completion of transmission via DMA, and indicates completion of reception via DMA. If you want to continue receiving continuously, you can call LPUART_TransferReceiveEDMA() again within this callback to continue receiving without interruption.   4.8 Key Design Points When actually using LPUART and DMA in combination, there are several design considerations that you should keep in mind. First, let's consider the transfer size . If the transfer size is too small, the number of interrupts will increase, reducing CPU efficiency. If it's too large, the latency until the transfer is complete will be high. You need to choose an appropriate value that matches the application's requirements while keeping the FIFO size in mind. Next is the design of the receive buffer . If the receive length is predetermined, a fixed-length buffer is sufficient, but if you are continuously receiving data of an unspecified length, it is common to use a ring buffer. Finally, there's the callback process . Callbacks not only notify the application that the transfer is complete, but they also trigger the reconfiguration of the next DMA transfer. Implementing this part is the most crucial for ensuring stable continuous communication. 5. Common problems   5.1 DMA is not working Possible causes include the DMA clock not being enabled, the request source specified in EDMA_SetChannelMux not matching the LPUART's TX/RX, or the channel number passed to the LPUART driver not matching the channel number set in EDMA_SetChannelMux . The quickest solution is to first enable the clock and check that the channel MUX assignments match. 5.2 Data Loss Typical issues include FIFO overruns and transfer size settings that don't match the actual data volume. Review the relationship between the FIFO threshold and the DMA transfer unit. 5.3 Failure due to high-speed communication As the baud rate increases, factors such as FIFO underrun, insufficient buffer design, degraded waveform quality, and clock errors become apparent. It is necessary to isolate the cause from both the hardware-side signal quality and the software-side buffer supply capability. 6. Summary The most important thing for effectively using LPUART in practice is to correctly understand the role of FIFO and design the data buffer in consideration of its interaction with DMA. By keeping these points in mind, you can achieve stable UART communication with low power consumption and low CPU load. ========================= We are currently unable to respond to comments left in the "Comment" section of this post. We apologize for the inconvenience, but please refer to " Technical Questions to NXP - How to Contact Us (Japanese Blog) " when making inquiries. (If you are already an NXP distributor or have a relationship with NXP, you may contact your representative directly.) This article explains the basic concepts of LPUART (Low Power Universal Asynchronous Receiver/Transmitter) on the MCX A153 and how to use it with the MCUXpresso SDK, aimed at engineers who are new to NXP products. First, we will explain the hardware overview, and then, using the FRDM-MCXA153 board as a base, we will explain how to use the MCUXpresso SDK API with code snippets. (Reading time: 20 minutes) MCUXpresso SDK MCX Japanese Blog
View full article
[MCX A153] GPIO Beginner's Guide (Japanese Blog) This article explains the basic concepts of GPIO ( General Purpose Input / Output ) on the MCX A153 . It also explains how to implement software using the MCUXpresso SDK , based on the FRDM-MCXA153 board, for engineers new to NXP products. First, an overview of the hardware is provided, followed by an explanation of how to use the MCUXpresso SDK, along with code snippets. (Reading time: 20 minutes) 1. Overview of the GPIO module   1.1 Role of GPIO GPIO is the most basic interface for controlling microcontroller pins as either "inputs" or "outputs". For example, in the FRDM-MCXA153 , the three RGB LEDs are wired to the following GPIOs , so it is possible to switch the LEDs ON/OFF by controlling the GPIOs. Red : P3_12 Green : P3_13 Blue : P3_0 1.2 Pin control function in MCX A153 In the MCX A153 , pin control functions are managed by the following two modules: (1) PORT module It primarily serves the following roles. Since one pin has multiple functions, PORT configuration is required to use it as a GPIO. Pin function selection ( GPIO / UART / SPI / I2C / PWM , etc. ) Pull-up / Pull-down settings Drive capability settings   (2) GPIO module It primarily serves the following roles: Input/Output Data Control High/Low output of the pin Reading the input state " PORT = pin configuration" and " GPIO = actual input/output operation," and so on.   2. Basic operation of GPIO GPIO modules have output and input modes, and the following operations are possible with each mode: (1) Output mode The following processes are possible: High output Low output Toggle (inverts the current output) (2) Input mode The following processes are possible: Read the pin voltage status (High or Low) Interrupt detection (rising / falling edge)   3. Basic Flow of SDK Drivers   To use GPIO, the following settings are required by the software. - Clock settings - Pin settings (PORT settings) - Input or output settings ( GPIO settings) - Interrupt settings (if necessary) This guide will demonstrate how to use the driver, using a sample project from the MCUXpresso SDK as an example.    3.1 Output Modes I will explain using the following project as an example. Reference URL: Hardware requirements — MCUXpresso SDK Documentation mcuxsdk-examples/driver_examples/gpio/led_output/gpio_led_output.c at main · nxp-mcuxpresso...   3.1.1Initialization First, initialize the clock, port, and GPIO for the red LED. #include "fsl_gpio.h" #include "fsl_port.h" // 赤色LEDに配線されたピンのパラメータ #define BOARD_INITPINS_LED_RED_PORT PORT3 #define BOARD_INITPINS_LED_RED_GPIO GPIO3 #define BOARD_INITPINS_LED_RED_PIN 12 void init_gpio(void) { // クロック有効化 CLOCK_EnableClock(kCLOCK_GateGPIO3); // PORT設定 const port_pin_config_t LED_RED = {/* Internal pull-up/down resistor is disabled */ kPORT_PullDisable, /* Low internal pull resistor value is selected. */ kPORT_LowPullResistor, /* Fast slew rate is configured */ kPORT_FastSlewRate, /* Passive input filter is disabled */ kPORT_PassiveFilterDisable, /* Open drain output is disabled */ kPORT_OpenDrainDisable, /* Low drive strength is configured */ kPORT_LowDriveStrength, /* Normal drive strength is configured */ kPORT_NormalDriveStrength, /* Pin is configured as P3_12 */ kPORT_MuxAlt0, /* Digital input enabled */ kPORT_InputBufferEnable, /* Digital input is not inverted */ kPORT_InputNormal, /* Pin Control Register fields [15:0] are not locked */ kPORT_UnlockRegister}; PORT_SetPinConfig(BOARD_INITPINS_LED_RED_PORT, BOARD_INITPINS_LED_RED_PIN, &LED_RED); // GPIO設定 gpio_pin_config_t LED_RED_config = { .pinDirection = kGPIO_DigitalOutput, .outputLogic = 0U }; GPIO_PinInit(BOARD_INITPINS_LED_RED_GPIO, BOARD_INITPINS_LED_RED_PIN, &LED_RED_config); }   3.1.2Output control ( LED on / off / toggle) The output values can be modified using the following API. GPIO_PinWrite(BOARD_INITPINS_LED_RED_PORT, BOARD_INITPINS_LED_RED_PIN, 1); // High GPIO_PinWrite(BOARD_INITPINS_LED_RED_PORT, BOARD_INITPINS_LED_RED_PIN, 0); // Low GPIO_PortToggle(BOARD_INITPINS_LED_RED_PORT, 1U << BOARD_INITPINS_LED_RED_PIN); // Toggle   3.2 Input Mode I will explain using the following project as an example. Reference URL: Hardware requirements — MCUXpresso SDK Documentation mcuxsdk-examples/driver_examples/gpio/input_interrupt/gpio_input_interrupt.c at main · nxp-mcuxpresso...   3.2.1 Initialization Since it's the same except for the output mode and arguments, I'll omit the details.   3.2.2Input reading The input values can be read using the following API. uint32_t value = GPIO_PinRead(BOARD_SW_GPIO, BOARD_SW_GPIO_PIN); if (value == 0) { // スイッチ押下(プルアップの場合) }   3.2.3Interrupt settings To set the falling edge signal as a GPIO interrupt, use the following API. EnableIRQ is the interrupt enable setting on the Cortex-M side. GPIO_SetPinInterruptConfig(BOARD_SW_GPIO, BOARD_SW_GPIO_PIN, kGPIO_InterruptFallingEdge); EnableIRQ(BOARD_SW_IRQ); Handling interrupts requires a function definition as an interrupt handler. If you don't clear the interrupt flag, the interrupt will continue to occur indefinitely, so be careful. void BOARD_SW_IRQ_HANDLER(void) { /* 割り込みフラグをクリア */ GPIO_GpioClearInterruptFlags(BOARD_SW_GPIO, 1U << BOARD_SW_GPIO_PIN); // 処理 SDK_ISR_EXIT_BARRIER; } The process leading up to an interrupt is shown below. The above explains how to use the GPIO driver with the MCUXpresso SDK.   4. Common pitfalls If you modify the source code and the GPIO doesn't work as expected, please check the following items. The pin is set to a different function → Check the PORT settings to see if the pin is assigned to GPIO. Clock not enabled → Check if CLOCK_EnableClock is being called. Incorrect pin number → Check if it matches the hardware pin number. GPIO interrupts are not being received → Check that interrupts are enabled on the Cortex-M side using EnableIRQ. GPIO interrupts are looping → Check if the interrupt flag has been cleared.   5. Summary   The GPIO pins on the MCX A153 operate in a two-stage configuration: pin configuration via the PORT module and input/output control via the GPIO module. Therefore, when using a pin as a GPIO, you must first configure the pin assignment settings in the PORT module and select the GPIO function. After that, you use the GPIO module to initialize it as an input or output and perform operations such as turning LEDs on and off or reading the state of switches. Using the MCUXpresso SDK, these settings and controls can be implemented concisely via the library API. Furthermore, by utilizing the GPIO interrupt function, it is possible to efficiently detect events such as switch presses. If the GPIO does not work as expected, check whether the PORT setting is enabled, whether the clock is enabled for the target PORT, and whether the pin number setting is correct.   ========================= We are currently unable to respond to comments left in the "Comment" section of this post. We apologize for the inconvenience, but please refer to " Technical Questions to NXP - How to Contact Us( Japanese Blog) " when making an inquiry. (If you are already an NXP distributor or have a relationship with NXP, you may ask your representative directly.) This article explains the basic concepts of GPIO ( General Purpose Input / Output ) on the MCX A153 . It also explains how to implement software using the MCUXpresso SDK , based on the FRDM-MCXA153 board, for engineers new to NXP products. First, an overview of the hardware is provided, followed by an explanation of how to use the MCUXpresso SDK, along with code snippets. (Reading time: 20 minutes) MCX Japanese Blog
View full article
OpenWrt upgrade for i.MX platforms is ready Processor and Board Support i.MX 8M Mini EVK i.MX 8M Nano EVK i.MX 8M Plus EVK i.MX 8M Quad EVK i.MX 91 EVK i.MX 93 EVK i.MX 93W EVK i.MX 95 15x15 EVK i.MX 95 19x19 EVK FRDM-IMX8MPLUS FRDM-IMX91 FRDM-IMX91S FRDM-IMX93 FRDM-IMX93W FRDM-IMX95 FRDM-IMX95-PRO OpenWrt and Toolchain OpenWrt from mainline (date: 29 Jun 2026, commit: f0a60eee2fe tag: v25.12.5) Toolchain:  ARMV8: GCC 14.3.0, GNU Binutils 2.44 U-Boot Bootloader i.MX SDK release, tag: lf-6.12.49-2.2.0 v2025.04 Linux Kernel OpenWrt kernel 6.12.94 based on IMX SDK release kernel lf-6.12.49-2.2.0 Firmware firmware-imx-8.30 Features Squashfs rootfs support on SD card. Support CLI and web configuration. U-Boot Boot Loader - U-Boot: lf-6.12.49-2.2.0. - Arm Trusted firmware (TF-A) integration. - Boot from SDHC Linux Kernel Core - Linux kernel 6.12.49 - Cortex-A53 (AARCH64), little endian for imx8m platforms - Cortex-A55 (AARCH64), little endian for imx9 platforms - 64-bit effective kernel addressing Linux Kernel Drivers - SDIO 3.0 / eMMC5.1 - USB 3.0/2.0 Dual-Role with PHY type C - 32-bit LPDDR4/LPDDR5 - 2x Gigabit Ethernet with AVB, IEEE 1588, EEE   and 1x w/ TSN - PCIe Gen 3 + WIFI - CAN FD - Dual-ch. QuadSPI (XIP) or 1x OctalSPI(XIP) - RTC - IW610/IW612 WiFi module - Bluetooth Licensing The majority of the software included in the OpenWrt release is licensed under a form of open source license (e.g. GPL, BSD). Some software is licensed under the NXP EULA license.  How to obtain this release The source code of the OpenWrt release can be got from the following link: https://github.com/nxp-imx/imx_openwrt   branch: imx-openwrt-25.12 tag: imx_v25.12_v6.12.49 The user guide can be found in the below link for build and deployment on IMX targets: https://github.com/nxp-imx/imx_openwrt/blob/imx-openwrt-25.12/target/linux/imx/README
View full article
Debugging_Bare_Metal_Code_in_NOR_Flash Scope This practical guide records the complete workflow used to build a ROM-target bare-metal image, program it into NOR flash, boot independently from NOR, and attach CodeWarrior with symbols for source-level debugging. Create the bare-metal project and confirm it works with the RAM/JTAG configuration. Create a ROM build configuration and link .intvec at 0xEFF00000 and .reset at 0xEFFFFFFC. Build the ELF. Generate the raw BIN from the same build. Create the Flash Programmer task using T1013RDB_NOR_FLASH.xml. Confirm the S29GL01GP flash range is 0xE8000000 to 0xEFFFFFFF. Configure the BIN destination as 0xEFF00000. Erase the selected sectors, program the image, and enable verification. Select NOR boot and power-cycle or reset the board. Confirm the program starts without JTAG downloading the image. Attach CodeWarrior to the running target. Load the exact matching ELF as symbols only. Confirm the Program Counter, set breakpoints, and begin source-level debugging.
View full article
GUI Guider 2.0.1 imageConfig 同时设 RGB565A8 和 RLE,保存后重开工程即卡死 GUI Guider 2.0.1 imageConfig 同时设 RGB565A8 和 RLE,生成代码即卡住,然后退出重开工程即卡死,一直Loading无法进入 Re: GUI Guider 2.0.1 imageConfig 同时设 RGB565A8 和 RLE,保存后重开工程即卡死 Hi @Mike22 , 感谢您关注恩智浦,感谢您反馈此问题。 我们已经知悉 GUI Guider 2.0.1 中的这个问题。当启用 RLE 压缩,并且图片的宽度和高度同时为奇数时,可能会导致代码生成过程卡住,并且重新打开工程后一直停留在 Loading 状态。 作为临时解决方案,如果工程已经无法正常打开,请手动编辑本地的 .guiguider 工程文件,将 ImageConfig 中的 compress 配置从: "compress": "RLE" 修改为: "compress": "" 修改后,工程应该可以正常打开。 此外,在使用 RLE 压缩时,请确保图片的宽度和高度不要同时为奇数,即可避免触发该问题。 此问题将在下一个版本中修复。 对此给您带来的不便,我们深表歉意,也感谢您的理解与配合。 Best Regards May Liu
View full article
i.MX95:在定制硬件上 OP-TEE xtest 测试失败 你好, 我最近将基于 i.MX95 (B0 rev) 的自定义硬件的 BSP 从 Linux 6.12.49_2.2.0 移植到了 Linux 6.18.37_2.1.0。突然,OP-TEE 的 xtest 开始出现测试失败的情况(xtest 输出已附上)。 经过一番调查,我发现故障源于 OP-TEE 核心无法验证从文件系统加载的 TA 上的 RSA 签名;这是由于 ELE 总是对 RSA 验证请求响应 ELE_INVALID_MESSAGE 造成的。 以下是 CFG_TEE_CORE_LOG_LEVEL=2 和 CFG_TEE_TA_LOG_LEVEL=2 时 OP-TEE 输出的摘录: E/TC:? 0 imx_ele_signature_verification:391 签名验证失败 res = ffff0006 ETC:?0 do_verify:514 RSA 签名验证失败 E/LD: init_elf:494 sys_open_ta_bin(cb3e5ba0-adf1-11e0-998b-0002a5d5c51b) ETC:?0 ldelf_init_with_ldelf:152 ldelf 失败,返回值为:0xffff000f 有什么建议可以帮助我调查吗? 先感谢您 Linux 安全 Re: i.MX95: OP-TEE xtest failing on custom hardware 我找到了罪魁祸首:新的 电路板支持包。 启用了 ELE 支持的 ECC 和 RSA,但它们依赖于已加载的 ELE 运行时固件。可以通过以下方式触发负载: echo 1 > /sys/kernel/se/se_load_fw 预期的 dmesg 输出为:   fsl-se secure-enclave-0:正在加载固件 imx/ele/mx95b0runtime-ahab-container.img fsl-se secure-enclave-0:固件已成功加载   Re: i.MX95: OP-TEE xtest failing on custom hardware 你好@fvalla-MTA 是的你是对的。 版本 6.18.37 需要加载 ELE 运行时固件。 B.R
View full article
i.MX95: OP-TEE xtest failing on custom hardware Hello, I recently ported the BSP for my custom hardware, based on i.MX95 (B0 rev), from Linux 6.12.49_2.2.0 to Linux 6.18.37_2.1.0 and suddenly OP-TEE's xtest started failing tests (xtest output attached). Some digging led me to determine that failures come from the OP-TEE core not being able to validate RSA signatures on TAs loaded from filesystem; that is caused by the ELE always responding ELE_INVALID_MESSAGE to RSA validation requests. Here is an extract of the OP-TEE output with CFG_TEE_CORE_LOG_LEVEL=2 and CFG_TEE_TA_LOG_LEVEL=2: E/TC:? 0 imx_ele_signature_verification:391 Failure in signature verificaction res = ffff0006 E/TC:? 0 do_verify:514 RSA signature verification failed E/LD: init_elf:494 sys_open_ta_bin(cb3e5ba0-adf1-11e0-998b-0002a5d5c51b) E/TC:? 0 ldelf_init_with_ldelf:152 ldelf failed with res: 0xffff000f Any idea on what should I investigate? Thank you in advance Linux Security Re: i.MX95: OP-TEE xtest failing on custom hardware I found the culprit: the new BSP enables ELE-backed ECC and RSA, but they depend on the ELE runtime firmware being loaded. The load can be triggered with: echo 1 > /sys/kernel/se/se_load_fw The expected dmesg output is:   fsl-se secure-enclave-0: loading firmware imx/ele/mx95b0runtime-ahab-container.img fsl-se secure-enclave-0: Firmware loaded successfully   Re: i.MX95: OP-TEE xtest failing on custom hardware Hi @fvalla-MTA  yes, you are right. Version 6.18.37 requires loading the ELE runtime fw. B.R
View full article
mcxa145 编程异常 早上好, 我已将微控制器从 MCXA144VLH 更换为 MCXA145VLL,但使用该微控制器的板遇到了一些问题。 我尝试对一块带有 MCXA145 的板进行编程,当我尝试通过 IDE(使用 Cyclone LC)开始调试时,固件不会在主函数中的断点处停止(如下面的屏幕截图所示)。该板之前从未被编程过。 在我进行的第二次测试中,我直接通过 Cyclone 对微控制器进行编程(没有通过 IDE),编程成功了。 如果在此编程完成后,我立即通过 IDE 再次尝试,调试器会在主函数中的断点处正确停止。 但是,一旦我重新启动固件,IDE 就完全失去了对它的跟踪,调试器也挂起了(如第一张图片所示)。 但是,一旦我重新启动固件,IDE 就完全失去了对主函数的跟踪,调试器崩溃了(如第一张图片所示)。 然而,我发现的问题是,固件实际上并没有被编程——无论是第一种方式还是第二种方式。每次我关闭控制单元再重新启动时,固件就会丢失。 我使用运行相同软件的 MCXA144 时从未遇到过这类问题。 但是,在这种情况下,ISP 模式下的 P0_6 引脚固定为 GND。这会不会是原因? 先行致谢。 顺祝商祺! Re: mcxa145 programming anomalies 你好@Transidico , 请您在MCX 微控制器 - NXP 社区下创建一个新帖子来提出您的新问题吗?它能帮助我们追踪不同的主题。 先行致谢。 BR 塞莱斯特 Re: mcxa145 programming anomalies 非常感谢你,Celeste——你解释得非常清楚。 关于 WWDT0,我还有另一个问题。我的设置如下: 我用它来在固件死机后 250 毫秒内 RESET 固件。 在我的固件的某些部分,我特意加入了一个 `while(1)` 循环,以便进行这种 RESET。 使用窗口式看门狗是正确的选择吗? 我注意到看门狗在一个硬件上工作正常,但在另一个硬件上却不行——是不是有什么东西阻止了 WWDT,或者我有什么需要注意的吗? 再次感谢你,塞莱斯特 Re: mcxa145 programming anomalies 你好@Transidico , MCXA144VLH 和 MCXA145VLL 的情况有所不同。 对于 MCXA145VLL,仅使用 P0_6 作为 ISP 输入引脚。引脚 50 (P3_29) 可用作普通 GPIO。 对于 MCXA144VLH(LQFP64 封装),该设备受勘误 ERR053147 影响: 因此,P0_6 和 P3_29 都需要谨慎处理。为避免意外进入 ISP 模式,请确保在 POR 期间 P0_6 为高电平,在热 RESET 期间 P3_29 为高电平。 希望对您有所帮助。 BR 塞莱斯特 Re: mcxa145 programming anomalies 谢谢 Celeste, 我试过了,现在可以正常进入调试模式了。 我还想知道引脚 50 是否应该保持高电平,或者它是否可以用作普通的 GPIO。 也感谢您提前提供的答案。 顺祝商祺! Re: mcxa145 programming anomalies 你好@Transidico , 感谢你的帖子。 是的,这种现象看起来更像是RESET后启动/ISP入口的问题,而不是闪存中已编程的镜像文件丢失。 对于从内部 Flash 正常启动的情况,RESET期间 P0_6 不应保持低电平。由于您的板上的 P0_6 引脚已连接到 GND,请释放此引脚并重复编程、RESET 和上电循环测试。 作为快速检查,您还可以使用MCUXpresso 安全配置工具,并在 RESET 或断电重启后单击“测试连接”。如果通过 ISP 接口连接成功,则表明 MCU 已进入 ISP 模式,而不是从内部 Flash 启动应用程序。 希望对您有所帮助。 BR 塞莱斯特
View full article
mcxa145 プログラミング異常 おはようございます。 MCXA144VLHマイクロコントローラからMCXA145VLLに切り替えたのですが、このマイクロコントローラを搭載したボードでいくつか問題が発生しています。 MCXA145を載せたボードをプログラムしてみたところ、IDE(Cyclone LC)でデバッグを始めようとすると、メイン機能のブレークポイントでファームウェアが停止しません(下のスクリーンショットでわかります)。このボードはこれまで一度もプログラムされたことがない。 2回目のテストでは、IDEを経ずにCycloneで直接マイクロコントローラをプログラムし、プログラムは成功しました。 このプログラミング直後にIDEで再度試みると、デバッガはメイン関数のブレークポイントで正しく停止します。 しかし、ファームウェアを再起動すると、IDEsは完全にその追跡を失い、デバッガがフリーズしてしまいます(最初の画像に示されています)。 しかし、ファームウェアを再起動すると、IDEはメイン機能を完全に認識しなくなり、デバッガが潰れてしまいます(最初の画像に示されています)。 しかし、私が気づいた問題は、ファームウェアが実際にはプログラムされていないということです。最初の方法でも、2番目の方法でもです。コントロールユニットをオフにして再度オンにすると、ファームウェアが失われてしまいます。 同じソフトで動くMCXA144ではこんな問題は一度もありません。 しかしこの場合、ISPモードのP0_6ピンはGNDに固定されています。これが原因でしょうか? よろしくお願いいたします。 よろしくお願いいたします。 Re: mcxa145 programming anomalies こんにちは、 @Transidico さん、 新しい質問のために「MCX マイクロコントローラ - NXPコミュニティ」の新しい投稿を作成してもらえますか?これにより、異なるトピックを追跡するのに役立ちます。 よろしくお願いいたします。 BR セレステ Re: mcxa145 programming anomalies セレステ、本当にありがとうございます。とても分かりやすく説明してくれました。 WWDT0についてもう一つ質問があります。これが私の設定です。 フリーズが起きた場合に備えて、250ms後にファームウェアをリセットするために使っています。 ファームウェアの一部では、このリセットを可能にするために、意図的に`while(1)`ループを含めています。 ウィンドウ型ウォッチドッグを使用するのは正しい選択でしょうか? ウォッチドッグタイマーが、あるハードウェアでは正しく動作するのに、別のハードウェアでは動作しないことに気づきました。WWDTの動作を妨げている可能性のある要因があるのでしょうか、それとも私が注意すべき点があるのでしょうか? セレストさん、改めてありがとうございました。 Re: mcxa145 programming anomalies こんにちは、 @Transidico さん、 MCXA144VLHとMCXA145VLLの場合は状況が異なります。 MCXA145VLLの場合、ISPエントリピンとして使用されるのはP0_6のみです。ピン50(P3_29)は通常のGPIOとして使用できます。 MCXA144VLH(LQFP64パッケージ)では、装置は訂正ERR053147の影響を受けます: したがって、P0_6とP3_29はどちらも慎重に取り扱う必要がある。意図せずISPモードに入ってしまうことを避けるため、POR中はP0_6がハイレベル、ウォームリセット中はP3_29がハイレベルであることを確認してください。 お役に立てば幸いです。 BR セレステ Re: mcxa145 programming anomalies セレストさん、ありがとう。 試してみたところ、正しくデバッグモードに入るようになりました。 ピン50を高く保つべきか、それとも通常のGPIOとして使えるかも気になっています。 この回答についても、事前に感謝申し上げます。 よろしくお願いいたします。 Re: mcxa145 programming anomalies こんにちは、 @Transidico さん、 投稿ありがとうございます。 はい、その動作は、フラッシュメモリからプログラムされたイメージが実際に失われたというよりも、リセット後のブート/ISPエントリの問題のように見えます。 内部フラッシュからの通常の起動では、リセット中にP0_6を低く保つべきではありません。お使いの基板ではP0_6がGNDに接続されているため、このピンを解放してから、プログラミング、リセット、電源投入のテストを再度実行してください。 簡単な確認として、 MCUXpressoのSecure Provisioning Tool を使ってリセットや電源を入れ直した後に「接続テスト」をクリックすることもできます。ISPインターフェース経由で接続が成功した場合、これはMCUが内部フラッシュからアプリケーションを起動するのではなくISPモードに入ったことを示します。 お役に立てば幸いです。 BR セレステ
View full article
i.MX95: カスタムハードウェアでOP-TEEのテストが失敗する こんにちは、 最近、カスタムハードウェア用にi.MX95(B0バージョン)用にBSPをLinux 6.12.49_2.2.0からLinux 6.18.37_2.1.0に移植しましたそして突然、OP-TEEのxtestがテストに失敗し始めました(xtestの出力を添付します)。 調査の結果、OP-TEEコアがファイルシステムからロードされたTA上のRSA署名を検証できないことが障害の原因であることが判明しました。これは、ELEがRSA検証要求に対して常にELE_INVALID_MESSAGEという応答を返すことが原因です。 以下は、CFG_TEE_CORE_LOG_LEVEL=2 および CFG_TEE_TA_LOG_LEVEL=2 の場合の OP-TEE 出力の抜粋です。 E/TC:? 0 imx_ele_signature_verification:391 署名検証に失敗しました res = ffff0006 等:?0 do_verify:514 RSA署名検証に失敗しました E/LD: init_elf:494 sys_open_ta_bin(cb3e5ba0-adf1-11e0-998b-0002a5d5c51b) 等:?0 ldelf_init_with_ldelf:152 ldelf が res: 0xffff000f で失敗しました 何を調べればいいか、何かアイデアはありますか? よろしくお願いします Linux Security Re: i.MX95: OP-TEE xtest failing on custom hardware 原因が判明しました。新しいBSPはELEを基盤としたECCとRSAを有効にしますが、それらはELEランタイムファームウェアがロードされていることを前提としています。負荷は以下の方法でトリガーできます: echo 1 > /sys/kernel/se/se_load_fw 期待されるdmesgの出力は以下のとおりです。   FSL-se セキュア・エンクレーブ-0: loading firmware IMX/ele/MX95B0runtime-ahab-container.img FSL-SE セキュア・エンクレーブ-0:ファームウェアの正常なロード   Re: i.MX95: OP-TEE xtest failing on custom hardware こんにちは、 @fvalla-MTAさん はい、おっしゃる通りです。バージョン6.18.37では、ELEランタイムファームウェアのロードが必要です。 B.R
View full article
GUI Guider 2.0.1では、imageConfigでRGB565A8とRLEの両方を設定し、保存してプロジェクトを再起動すると、フリーズします。 GUI Guider 2.0.1を使用してimageConfigでRGB565A8とRLEの両方を同時に設定すると、コード生成プロセスがフリーズします。プロジェクトを終了して再起動すると、再びフリーズし、読み込み状態のまま先に進めなくなります。 Re: GUI Guider 2.0.1 imageConfig 同时设 RGB565A8 和 RLE,保存后重开工程即卡死 こんにちは、 @Mike22 さん。 NXPにご関心をお寄せいただき、またこの件についてご意見をお寄せいただき、ありがとうございます。 GUI Guider 2.0.1 において、この問題が発生することを認識しています。RLE 圧縮が有効になっており、画像の幅と高さが両方とも奇数の場合、コード生成プロセスがフリーズし、プロジェクトを再度開いた後も読み込み状態のままになることがあります。 一時的な解決策として、プロジェクトが正常に開けない場合は、ローカルの.guiguiderファイルを手動で編集してください。プロジェクトファイル内のImageConfigの圧縮設定を以下のように変更します。 「圧縮」: 「RLE」 改訂版: 「圧縮」: 「」 変更後、プロジェクトは正常に起動するはずです。 さらに、RLE圧縮を使用する場合は、この問題を回避するために、画像の幅と高さが両方とも奇数にならないようにしてください。 この問題は次期バージョンで修正されます。ご迷惑をおかけして誠に申し訳ございません。ご理解とご協力をお願いいたします。 よろしくお願いします メイ・リウ
View full article
mcxa145 programming anomalies Good morning, I’ve switched from using the MCXA144VLH microcontroller to the MCXA145VLL and am experiencing some issues with boards featuring this microcontroller. I tried programming a board with the MCXA145 on it, and when I try to start debugging via the IDE (using Cyclone LC), the firmware does not halt at the breakpoint in the main function (as you can see from the screenshot below). The board has never been programmed before. In a second test I carried out, I programmed the microcontroller directly via Cyclone (without going through the IDE), and the programming was successful. If, immediately after this programming, I try again via the IDE, the debugger stops correctly at the breakpoint in the main function. However, as soon as I restart the firmware, the IDE completely loses track of it and the debugger hangs (as shown in the first image). However, as soon as I restart the firmware, the IDE completely loses track of the main function and the debugger crushes(as shown in the first image). The problem I’ve noticed, however, is that the firmware isn’t actually being programmed – neither in the first way nor in the second. Whenever I switch the control unit off and on again, the firmware is lost.  I’ve never had this sort of problem with the MCXA144, which runs on the same software. In this case, however, the P0_6 pin in ISP mode is fixed to GND. Could this be the cause? Thanks in advance. Best regards. Re: mcxa145 programming anomalies Hello @Transidico , Could you please create a new post under MCX Microcontrollers - NXP Community for the new question? It helps us track different topic. Thanks in advance. BR Celeste Re: mcxa145 programming anomalies Thank you so much, Celeste – you’ve explained it very clearly. I have another question about the WWDT0. These are my settings: I use it to reset the firmware after 250 ms in case it freezes. In certain parts of my firmware, I deliberately include a `while(1)` loop to allow for this reset. Is it the right choice to use the windowed watchdog? I’ve noticed that the watchdog works correctly with one piece of hardware but not with another – is there anything that might be blocking the WWDT, or is there anything I need to be aware of? Thanks again, Celeste Re: mcxa145 programming anomalies Hello @Transidico , The situation is different for MCXA144VLH and MCXA145VLL. For MCXA145VLL, only P0_6 is used as the ISP entry pin. Pin 50 (P3_29) can be used as a normal GPIO. For MCXA144VLH(LQFP64 package), the device is affected by erratum ERR053147: Therefore, both P0_6 and P3_29 need to be handled carefully. To avoid unintentionally entering ISP mode, please ensure that P0_6 is high during POR and P3_29 is high during a warm reset. Hope it can help you. BR Celeste Re: mcxa145 programming anomalies Thanks Celeste, I tried it, and now it enters debug mode correctly. I was also wondering if pin 50 should be kept high, or if it can be used as a normal GPIO. Thanks in advance for this answer as well. Best Regards. Re: mcxa145 programming anomalies Hello @Transidico , Thanks for your post. Yes, the behavior looks more like a boot/ISP-entry issue after reset rather than the programmed image actually being lost from Flash.  For normal boot from internal Flash, P0_6 should not be held low during reset. Since P0_6 is tied to GND on your board, please release this pin and repeat the programming, reset, and power-cycle tests. As a quick check, you can also use MCUXpresso Secure Provisioning Tool and click "Test connection" after a reset or power cycle. If the connection succeeds through the ISP interface, this would indicate that the MCU has entered ISP mode rather than booting the application from internal Flash. Hope it can help you. BR Celeste
View full article
In GUI Guider 2.0.1, setting both RGB565A8 and RLE in imageConfig, saving and restarting the project causes it to freeze. When using GUI Guider 2.0.1 to simultaneously set both RGB565A8 and RLE in imageConfig, the code generation process freezes. Exiting and restarting the project then causes another freeze, stuck in a loading state and unable to proceed. Re: GUI Guider 2.0.1 imageConfig 同时设 RGB565A8 和 RLE,保存后重开工程即卡死 Hi @Mike22 , Thank you for your interest in NXP and for providing feedback on this issue. We are aware of this issue in GUI Guider 2.0.1. When RLE compression is enabled and the width and height of the image are both odd numbers, the code generation process may freeze, and the project may remain in the Loading state after being reopened. As a temporary solution, if the project cannot be opened normally, please manually edit your local .guiguider file.In the project files, change the compress configuration in ImageConfig from: "compress": "RLE" Revised to: "compress": "" After the modifications, the project should open normally. In addition, when using RLE compression, ensure that the width and height of the image are not both odd numbers to avoid triggering this problem. This issue will be fixed in the next version. We sincerely apologize for any inconvenience this may cause and thank you for your understanding and cooperation. Best Regards May Liu
View full article
LS1043A 安全启动 4x 4096 密钥导致启动挂起 使用 1 个 1024 位密钥(包含 1 个元素的密钥表)可以正常实现安全启动。 尝试更改为 4 个 4096 位密钥(包含 4 个元素的密钥表) 常规输出卡在: 注意:高效密码学标准\(SEC\) 已初始化并配置完成。 调试输出卡在: 详细信息:表键 3 哈希 然后是 8 行哈希值 不确定是否为巧合,但最后一行的值为:VERBOSE: 642dead0 谷歌/Gemini 似乎认为放置 4 个 4096 位密钥导致了越界或错位。 上面表键 0、1 和 2 的其他几行似乎都没问题。 QorIQ LS1设备 Re: LS1043A Secure Boot 4x 4096 keys hangs boot 我觉得我已经找到问题所在了。当更换为更大的密钥和 HSM 时,我不得不修改一些构建脚本,导致它无法正确生成带有标头/签名等的二进制有效负载。我希望稍后能够确认,并将此问题标记为已解决,因为我没有看到删除帖子/移除帖子的选项。 Re: LS1043A Secure Boot 4x 4096 keys hangs boot 尝试将密钥数量减少到 2 个 4096 键,但仍然卡在了第一个键上,情况和之前一样。把它降到 1 个 4096 键,然后也挂起来了。 使用由 CST 2.x 生成和签名的 1x 1024 密钥时。我尝试使用的 4096 个密钥是通过 NitroKey HSM2 生成的,然后我使用 cst 为 srk 表/公钥生成映像哈希,然后使用 openssl 和 pkcs11 对文件进行签名,最后调用 cst sign_embed 实用程序来附加签名。
View full article
RT798S HiFi4 TRAX TraceRAM 在 AP 3 和 DSP ERI 上读取零值 我正在研究使用 RT798S HiFi4 在 MIMXRT700-EVK 上捕获 TRAX 指令。RI-2023.11 核心配置报告 XCHAL_HAVE_TRAX=1 和 XCHAL_TRAX_MEM_SIZE=8192。XOCD 14.11 通过 DAP AP 3 到达 HiFi4;观察到的 TRAXID 为 0x0d43eff2。 在跟踪不活动 (TRAXSTAT.TRACT=0) 和内存启用 (TRAXCTRL.TMEN=1) 的情况下,我使用 AP 3 xdmreg-wr/xdmreg-rd 命令将四个模式写入 TRAXDATA 并将它们读出来。TRAXADDR 按预期推进,但所有四个读取操作均返回零。DSP 端 libtrax ERI 写入/读取测试也返回零。XOCD 写入输出会回显所提供的值,因此我不将其视为 TraceRAM 已接受写入的确认。 CM33 端只读快照显示 DSP 功率域已开启,SRAM 分区 14-17 已通电,HiFi4 仲裁器-1 时钟已启用,HiFi4 仲裁器-0 访问掩码为 0x3fffffff。我没有任何文档将这些共享 SRAM 仲裁寄存器与 TRAX TraceRAM 联系起来。 请问您能否澄清一下: HiFi4 TRAX 及其 8 KiB TraceRAM 是否已在此 RT798S 芯片版本上完全实现和支持?是否存在相关的勘误或已知局限性? 通过调试 AP 验证 TRAXDATA 写入/读取的推荐步骤是什么?除了 TRAXADDR 递增之外,我是否还应该检查 APB/JTAG 事务接受或错误状态? TraceRAM 接口是否有 RT798S 特有的电源、时钟、RESET、网络安全或集成控制,而这些控制并未在标准 PMC SRAM 分区控制或 HiFi4 RAM 仲裁器中记录? NXP 是否有示例或已知可靠的调试器/工具版本可以捕获和读取此板上的 HiFi4 TRAX TraceRAM? 除了 Cadence libtrax API 之外,DSP 端 ERI 访问是否需要任何 RT798S 特有的排序或访问条件? 我可以提供 POC 源代码和日志:trax_poc.c,AP 3 测试日志和 DSP ERI 测试日志。 评估板
View full article