Multi Source Translation Content

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

Multi Source Translation Content

Discussions

Sort by:
MCUXpresso 配置工具:引脚工具的使用方法(日语博客) 目录 介绍 在哪些情况下可以使用图钉工具? 安装配置工具 引脚工具屏幕配置 引脚工具基础知识——信号从哪里流向哪里? 演示:更改引脚设置并更改 LED 的闪烁颜色。 额外福利 - 在文档(Excel 文件)中查看密码列表   介绍 本文介绍 MCUXpresso 配置工具中包含的“引脚工具” ,该工具用于配置引脚。有关“时钟工具”的使用说明,请参阅以下文章。 MCUXpresso 配置工具:如何使用时钟工具(日语博客) 近年来,微控制器(MCU)集成了许多外围功能,导致一些MCU拥有超过200个引脚。MCU的引脚配置设计灵活,允许将多个功能(信号)分配给单个引脚。此外,同一功能还可以有多个引脚选项。虽然这种高度灵活性也使得配置变得相当复杂。 因此,决定将哪个功能分配给哪个引脚(引脚复用配置)是设计早期阶段一项重要且具有挑战性的任务。这时,MCUXpresso 配置工具中的“引脚工具”就派上了用场。 Pins Tool 允许您通过 GUI 直观地执行引脚分配和电气设置,并自动将结果生成为代码,从而避免手动配置错误和冲突。 我们将首先解释如何在 VS Code 环境中的配置工具中使用引脚工具。然后,我们将演示如何更改引脚设置和更改 LED 闪烁颜色。   在哪些情况下可以使用图钉工具? 当您想要检查现有引脚设置时 当你想在设计中避免引脚冲突时 (*如果您不小心进行了冲突的设置,错误信息将以清晰易懂的方式显示。) 当您想使用 GUI 调整上拉/下拉和驱动强度等电气设置时。 当您需要自动生成引脚配置代码时   安装配置工具 本指南解释了如何在 VS Code 环境中安装 Config Tools。 *如果您尚未为 VS Code 安装 MCUXpresso,请参阅此博客文章。 安装适用于 VSC 和 SDK 的 MCUXpresso(日文博客) 启动 VS Code 后,从左侧面板中选择 MCUXpresso,然后从快速启动面板中单击“打开 MCUXpresso 安装程序”。 安装程序将启动。选择 MCUXpresso 配置工具,然后单击右上角的“安装”。 (这篇博文介绍了 MCUXpresso 配置工具 v26.03 的安装过程。) 安装开始后,系统会提示您登录 MyNXP。 登录后,将显示许可协议。请阅读并同意其内容。 *安装完成后请重启VS Code。 问:如果安装失败怎么办? A. 请从以下网站下载适合您电脑操作系统环境的安装程序并进行尝试。 MCUXpresso 配置工具 | NXP 微控制器 (MCU) 软件开发 | NXP 半导体 安装过程中,初始屏幕上会出现以下界面。如果您没有看到任何相关信息,可以将其关闭。 要从 VS Code 访问配置工具,请安装 SDK,导入示例,然后右键单击您的项目。“使用 MCUXpresso 配置工具打开”将出现;单击它。 *整个过程将在最终演示中详细解释,因此我们在此省略。 配置工具将在短时间内启动。 如果您使用的是 MCUXpresso IDE,则配置工具默认已集成,可以直接从顶部选项卡启动。   引脚工具屏幕配置 启动配置工具后,您可以使用屏幕右侧的面板在工具之间切换。 这次,我们将选择“别针”。 本节介绍图钉工具中的主要视图。 引脚:逐个引脚分配外设。 外设信号:按外设分配引脚。 封装:显示芯片的引脚配置。 路由详情:配置每个引脚与外设之间的连接,以及输入/输出设置。 问题:显示与设置相关的错误或警告。 接下来,我们将仔细研究路由细节,这是设置中最重要的方面。 #:表示MCU封装上的实际引脚编号(位置)。 外设:指示分配给该引脚的外设。 信号:指示外设信号。对于 UART,将显示 TX/RX;对于 SPI,将显示 SCK 或 MOSI。 箭头:指示连接方向。<->:双向连接 <- :ペリフェラルへの入力 ->:输出到外围设备 布线引脚/信号:指示连接外围信号或内部信号的引脚。 标签:可以任意设置的标签。 标识符:代码生成过程中使用的标识符。此标识符会自动生成为 #define 宏,并在应用程序代码中引用。 方向:指定引脚用作 GPIO 时的输入/输出方向。对于 UART 和 SPI 等信号,输入/输出方向是预先确定的,因此“方向”仅供参考。 如果由于引脚设置错误而导致故障,问题视图将显示错误的位置和原因。其他区域也会以红色突出显示,方便您直观地识别问题区域。 在下图所示的电路中,多个外设配置在引脚 B12 上,这意味着发生了冲突。   引脚工具基础知识——信号从哪里流向哪里? 在实际使用该工具之前,让我们先明确一下 Pins Tool 是用来配置什么的。 在 PinsTool 中 “交通信号灯从哪里来,又到哪里去?” 我们将从这个角度配置引脚设置。 这种“流程”主要有三种模式。 ① 将外部信号输入到MCU(引脚⇀外设) 首先,我们来看一下输入。这涉及到通过引脚将来自外部传感器、开关或其他集成电路的信号输入到微控制器内部的外围设备中。 在“路线详情”中点击“+”按钮将添加一行,允许您直接输入数据。 下图中的示例显示,“复位按钮 SW1 的信号输入通过 F3 引脚 (RESET_B) 进入 MCU”。 ② 将MCU内部信号输出到外部(外设⇀引脚) 接下来是输出。在这种情况下,信号会通过引脚从MCU内部的外设发送到外部。 下图中的示例展示了如何“将来自内部外设 (FlexSPI) 的信号 (FLEXSPI_B_DATA0) 分配给 K3 引脚,并将该信号向外输出”。 ③ 内部自包含连接(外围设备⇀外围设备) 最后,还有一种情况,即一个内部外设的输出连接到另一个内部外设的输入。 在下图所示的示例中,PWM 触发信号 (PWM0_A0_TRIG0) 通过内部路由连接到 ADC0 触发输入 (TRG)。 这表明它将被用作 CH0。 在这种情况下,由于它不通过外部引脚,因此表示最左侧引脚分配的“#”为 n/a。 在大多数实际设计中,涉及与外部系统进行输入和输出的情况①和②占绝大多数。内部连接(③)则用于更高级的控制和优化。   演示:更改引脚设置并更改 LED 的闪烁颜色。 接下来,我们将实际更改引脚工具中的引脚设置,看看评估板上的 LED 闪烁颜色是否会发生变化。 硬件准备 本文使用的评估板是 FRDM-MCXN947 安装 SDK 在VS Code 的左侧面板中选择MCUXpresso ,然后单击“导入存储库”。 接下来,点击左侧第二个选项“远程存档”,然后在“软件包”部分搜索“ FRDM-MCXN947 ”。输入“ 947 ”后,它应该会立即出现。 您可以根据需要设置名称、位置和“创建 Git”复选框。 *对于名称和位置名称,最好只使用小写字母数字字符和下划线(_)或连字符(-) ,并避免使用符号( \、/、:、*、?、"、、| )和空格(这可能会导致程序故障)。 最后,勾选“我同意”复选框,然后点击“导入”开始安装SDK 。请稍候片刻。当屏幕右下角显示“存储库导入成功”时,安装即完成。 导入示例代码 SDK安装完成后,即可导入示例代码。 点击左侧面板中的“从存储库导入示例”。 在右侧显示的每个选项卡中,“存储库”下,选择您刚刚导入的SDK 。 请为“主板”选择FRDM-MCXN947 。 在本“模板”演示中,我们将展示如何更改LED的闪烁颜色。 尝试输入“ led ”,然后选择出现的“ driver_examples/gpio/gpio_led_output_cm33_core0 ”。 接下来,选择工具链并点击“导入” 。 打开配置工具 右键单击导入的示例,然后选择“使用 MCUXpresso 配置工具打开”。稍等片刻,配置工具将启动。 配置工具打开后,首先查看右侧面板中的概览。在本例中, “时钟”和“引脚”均显示为绿色(开启) ,表示这两个工具均已启用。 选择引脚以查看当前引脚设置。 查看“布线详情”,可以看到三个引脚(A1、B1、B12)已启用。 但是,当我们查看LED的B12 引脚组的方向时,它显示“未指定”,这意味着LED未在引脚工具中设置为输出。 那么,为什么即使没有进行配置, LED也会闪烁呢?让我们回到 VS Code,查看C源文件 (gpio_led_output.c)。 查看C源文件,引脚功能由BOARD_InitHardware()反映出来,但正如我们之前确认的那样,此时引脚 B12 并未在Pins Tool中设置为 GPIO 输出。 因此,在该示例的初始状态下, GPIO输入/输出方向取决于源代码,而不是引脚工具。 具体来说, GPIO_PinInit() 函数将引脚 B12 初始化为“GPIO 输出”,使其可以控制 LED 。 此处的目的是使用引脚工具更改引脚设置,并将这些更改反映到代码中。因此,我们将删除与GPIO初始化和控制相关的源代码部分(如下红色部分所示) 。 删除它将从任何地方移除 GPIO 输出设置,因此在构建和调试时LED将不再闪烁。 接下来,使用引脚工具配置引脚。在引脚工具中,将引脚 # B12 的GPIO0_10方向更改为输出。 这是上面 ② 的情况,其中内部MCU信号被发送到外部(外设 ⇀ 引脚)。 这样就改变了配置,使得“引脚B12 ( PIO0_10 ) 被设置为GPIO输出,并且由MCU的内部 GPIO 控制(软件控制)控制的信号通过该引脚输出到外部 ( LED_RED )。 您可以在右侧的代码预览面板中看到代码更改。 将“未指定”更改为“输出”会在pin_mux.c的底部添加GPIO初始化代码。 现在,我们将重写示例代码。首先,点击“配置工具”屏幕左上角的“更新代码” 。 此时会弹出一个窗口。在这里,您可以像在代码预览中一样看到代码更改。 返回VS Code后,您会在屏幕顶部看到三个复选框。请确保选中它们,然后单击“确定” 。稍等片刻,时钟工具中所做的更改将应用到VS Code中的示例代码。 *如果您使用的是其他 SDK 版本,则可能不会显示此内容。 完成后,在组装之前将电路板(FRDM-MCXN947)连接到您的电脑。 连接建立后,调试导入的示例(构建、编写和运行应用程序) 。 调试过程完成后,程序将在断点处停止,因此请点击屏幕顶部的“|▶”图标。 如图所示,红色LED灯将开始闪烁。 (function() { var wrapper = document.getElementById('lia-vid-6397512171112w304h540r886'); var videoEl = wrapper ? wrapper.querySelector('video-js') : null; if (videoEl) { if (window.videojs) { window.videojs(videoEl).ready(function() { this.on('loadedmetadata', function() { this.el().querySelectorAll('.vjs-load-progress div[data-start]').forEach(function(bar) { bar.setAttribute('role', 'presentation'); bar.setAttribute('aria-hidden', 'true'); }); }); }); } }})(); (显示我的视频) 要退出程序,请点击方形图标(只要连接到电脑, LED 指示灯就会继续闪烁,但请暂时忽略这一点) 。 为什么红色LED灯会闪烁? 以下是关于红色LED 指示灯闪烁原因的一些补充信息。 在这种情况下,红色LED的闪烁由两个主要设置决定: app.h:定义要控制的LED(引脚) 。 pin_mux.c:定义如何使用该引脚。 这两个元件使LED能够闪烁。 哪个LED正在被控制?(app.h) 在C源文件“ gpio_led_output.c ”的底部,有一个名为GPIO_PortToggle的函数:它可以反转指定GPIO引脚的输出。 在这个函数中, BOARD_LED_GPIO(GPIO 端口) BOARD_LED_GPIO_PIN(引脚编号) 这将反转指定 GPIO 引脚的输出,使 LED 闪烁。 但是,目前还不清楚哪个颜色的LED对应于这个GPIO端口和引脚。 然后,右键单击BOARD_LED_GPIO ,选择“转到定义”(或“fn + F12” )打开“ app.h ”。 如果您查看app.h中的Definitions部分,您会发现这些定义被分配给了红色LED的GPIO 引脚。这证实了操作的目标是红色LED 。然而,即使在app.h中已为红色LED指定了引脚,除非将该引脚配置为GPIO输出,否则LED 也不会亮起。 如何使用引脚(pin_mux.c) 接下来,我们将查看pin_mux.c的内容以检查引脚设置。在gpio_led_output.c文件中,您会找到 Pin、Clock 和 Debug 参数。每个控制台都有一个 BOARD_InitHardware()函数用于初始化,因此请在此处右键单击并选择“转到定义”(或“fn + F12” )以查看更多详细信息。 下一个位置是BOARD_InitPins();,其中描述了引脚设置。再次右键单击BOARD_InitPins();并选择“转到定义(或“fn + F12” )”以打开“ pin_mux.c ”。 pin_mux.c文件反映了Pins Tool中的配置,与您之前在代码预览中将红色LED设置为输出时看到的内容相同。文件底部有如下描述,表示连接到红色LED 的引脚B12被初始化为GPIO输出,初始值为0 。 这样, app.h确定“要控制哪个LED (红色LED )”,而pin_mux.c使“该引脚可用作GPIO输出”,以便可以通过GPIO_PortToggle()控制红色LED 。 更改引脚设置,将 LED 的闪烁颜色更改为蓝色。 接下来,我们将通过改变引脚设置,把LED的闪烁颜色从红色改为蓝色。 返回配置工具,如果您在引脚中搜索“ LED ”,您会发现引脚C4对应于蓝色LED (LED_BLUE) 。 检查C4引脚时,会出现如下所示的窗口。选中GPIO1:GPIO,2 (PIO1_2)并单击“完成” 。 完成这些步骤后,您添加的C4引脚将出现在“布线详情”中。 C4引脚配置为GPIO功能( PIO1_2 ),并被赋予标签“LED_BLUE ” 。这使得软件能够将此引脚视为蓝色LED 。 接下来,我们将配置引脚的输入/输出设置。在“方向”面板中,将红色LED 的设置从“输出”更改为“未指定”,将蓝色 LED 的设置从“未指定”更改为“输出”。这样,蓝色 LED 就被配置为 GPIO 输出。 您可以在代码预览中看到pin_mux.c的变化。 现在,重写示例代码。和之前一样,在配置工具中运行“更新代码” ,并在VS Code中确认更改。更改后的引脚设置将会生效。 目前, pin_mux.c已更新。 最后,更新app.h。 按照前面描述的步骤打开app.h ,并将LED_RED更改为LED_BLUE 。 通过更改此定义,您可以将GPIO控制目标从红色LED切换到蓝色LED 。 完成这些步骤后,再次进行调试(构建、刷写并运行应用程序) 。 调试过程完成后,点击屏幕顶部的“|▶”图标。 如图所示,蓝色LED灯将开始闪烁。 (function() { var wrapper = document.getElementById('lia-vid-6397512593112w304h540r703'); var videoEl = wrapper ? wrapper.querySelector('video-js') : null; if (videoEl) { if (window.videojs) { window.videojs(videoEl).ready(function() { this.on('loadedmetadata', function() { this.el().querySelectorAll('.vjs-load-progress div[data-start]').forEach(function(bar) { bar.setAttribute('role', 'presentation'); bar.setAttribute('aria-hidden', 'true'); }); }); }); } }})(); (显示我的视频) 顺便一提,之所以一个LED可以闪烁不同的颜色,是因为本项目中使用的FRDM-MCXN947开发板配备了RGB LED。查看FRDM-MCXN947的电路图,可以看到每个引脚都分别对应了R/G/B三种颜色。 因此,通过在引脚工具中同时设置两个彩色引脚的输出并适当格式化源代码,可以表示各种颜色(例如,红色+蓝色=紫色)。   额外福利 - 在文档(Excel 文件)中查看密码列表 打开MCX N 参考手册后,你会发现一个名为MCXNP184M150F70_Pinout.xlsx的附件。该文件包含引脚列表以及每个引脚对应的外设功能列表。 如今,随着引脚工具的不断发展,参考此类列表手动配置引脚设置的需求可能会减少。 另一方面,它仍然可以作为系统设计早期阶段的有用参考文档,例如用于器件选择、封装比较和检查可用外围设备。 要下载 MCX N 参考手册,您需要注册一个 MyNXP 帐户。 *使用 Acrobat Reader 打开 这个解释使用了一个简单的例子,但实际设计中的引脚配置要复杂得多。这时Pins Tool就派上用场了;它可以帮助避免错误,并实现高效的配置。请试用一下! =========================​ 我们目前无法 回复 此帖子“ 评论”部分留下的评论。 对于由此造成的不便,我们深表歉意,但 在进行咨询时, 请 参考“ NXP 技术问题 - 如何联系我们 ( 日语博客 ) ” 。 (如果您已经是 恩智浦的 分销商或 与 恩智浦 有合作关系 ,您可以直接咨询您的代表。) 本指南重点介绍 MCUXpresso 配置工具中的“引脚工具”,解释设置引脚的基本原理和方法。 本指南将涵盖从在 VS Code 环境中安装到通过更改引脚设置来演示 LED 闪烁的所有内容。 (预计耗时:10 分钟 *假设已安装 MCUXpresso for VSC(Visual Studio Code)SDK) MCUXpresso MCX SW | 下载 日本博客
View full article
MCUXpresso Config Tools : Pins Toolの使い方 (日本語ブログ) 目次 はじめに Pins Toolはどのような場面で活用するのか Config Toolsのインストール Pins Toolの画面構成 Pins Toolの基本 ~信号はどこからどこへ流れるのか?~ デモンストレーション:ピン設定を変更し、LEDの点滅色を変更する おまけ - ピン一覧をドキュメント(Excelファイル)で確認する   はじめに  本記事では、MCUXpresso Config Toolsに含まれ、ピンの設定をおこなう「Pins Tool」について解説します。「Clocks Tool」の使い方については、以下の記事をご参考ください。 MCUXpresso Config Tools : Clocks Toolの使い方 (日本語ブログ) 最近のMCUには多くのペリフェラル機能が集約・統合されており、それに伴いピンの数も200ピンを超えるようなMCUも出ています。MCUのピン設定は柔軟に使えるように設計されており、1つのピンで複数の機能(信号)を切り替えて使うことができます。また、同じ機能でも複数のピン候補から選べるようになっています。柔軟性が高い分、設定は非常に複雑です。 そのため、どの機能をどのピンに割り当てるか(ピン・マルチプレックス設定)は、設計初期の重要かつ大変な作業の一つです。そこで活躍するのが、MCUXpresso Config Toolsの「Pins Tool」です。 Pins Toolを使うことで、ピン割り当てや電気的設定をGUI上で直感的に行い、その結果をコードとして自動生成することができ、手作業による設定ミスや競合(コンフリクト)を避けることができます。 VS Code環境からConfig Tools内のPins Toolを開き、はじめにツールの使い方を解説します。その後、ピン設定を変更し、LED点滅色を変更するデモンストレーションを紹介いたします。   Pins Toolはどのような場面で活用するのか? 既存のピン設定を確認したいとき ピンの競合(コンフリクト)を避けて設計したいとき (*誤って競合した設定をすると視覚的に分かりやすくエラー箇所が表示されます) プルアップ/プルダウンやドライブ強度などの電気的設定をGUIで調整したいとき ピン設定コードを自動生成したいとき   Config Toolsのインストール VS Code環境におけるConfig Toolsのインストール方法について解説します。 ※MCUXpresso for VS Codeのインストールがお済みでない方はこちらのブログをご参照ください。 MCUXpresso for VSCとSDKのインストール (日本語ブログ) VS Codeを起動後、左側のパネルからMCUXpressoを選択し、Quick Start PanelよりOpen MCUXpresso Installerをクリックしてください。 Installerが立ち上がりますので、MCUXpresso Configuration Toolsを選択し、右上のInstallをクリックしてください。 (今回のブログではMCUXpresso Config Tools v26.03 をInstallしています) インストールの開始と同時にMyNXPへのログインを求められます。 ログインの後、License Agreementが表示されますので内容をご確認のうえ同意してください。 ※インストール後は、VS Codeを再起動してください。 Q. もしインストールに失敗した場合は? A. 以下ウェブサイトからのご自身のPC OS環境に応じたインストーラーをダウンロードして、お試しください。 MCUXpresso Config Tools | NXPマイクロコントローラ (MCU) 向けソフトウェア開発 | NXP Semiconductors) インストールを進めると初期画面で以下のような画面が表示されますが、該当がなければ閉じて問題ありません。 VS CodeからConfig Toolsを呼び出すにはSDKをインストールし、サンプルをインポート後、プロジェクトを右クリックすると Open with MCUXpresso Config Toolsが現れますので、こちらをクリックしてください。 ※この一連のプロセスは最後のデモンストレーションで詳細に説明するので、ここでは割愛します。  しばらくするとConfig Toolsが起動します。 なおMCUXpresso IDEを使用している場合、Config Toolsは標準で統合されており、上部タブから直接起動できます。   Pins Toolの画面構成 Config Tools起動後、画面右側のパネルでツールの切り替えが可能です。 今回は「Pins」を選択します。 Pin Tool内の主要なビューについて説明します。 Pins : ピン単位でペリフェラルの割り当てを行う Peripheral Signals:ペリフェラル単位でピンの割り当てを行う Package:チップのピン配置を可視化 Routing Details:各ピンとペリフェラルの接続関係や入力/出力設定を行う Problems:設定内容に関するエラーや警告が表示される 続いて、設定において最も重要となるRouting Detailsについて深堀りして見ていきます。 # : MCUパッケージ上の実際のピン番号(位置)を示す。 Peripheral : ピンに割り当てられているペリフェラルを示す。 Signal : ペリフェラルの信号を示す。UARTであればTX/RX、SPIであればSCKやMOSIが表示される。 Arrow: 接続方向を示す。 <->:双方向 <- :ペリフェラルへの入力 -> :ペリフェラルからの出力 Routed pin/signal:ペリフェラルの信号が接続されるピンもしくは内部信号を示す。 Label : 任意に設定可能なラベル。 Identifier:コード生成時に使用される識別名。この識別名が #define マクロとして自動生成され、アプリケーションコードから参照される。 Direction:ピンをGPIOとして使用する場合の入出力方向(Input or Output)を指定。UARTやSPIなどの信号は、あらかじめ入出力方向が決まっているため、Directionは参考表示となる場合がある。 ピン設定に誤りがあり、エラーが発生するとProblemsビューにはエラーの発生箇所と原因が表示されます。またその他の箇所にも赤色でハイライト表示されるため、問題箇所を視覚的に特定できます。 下記図では、B12ピンに対して複数のペリフェラルが設定された状態、つまり競合(コンフリクト)が起きています。   Pins Toolの基本 ~信号はどこからどこへ流れるのか?~ 実際にツールを操作する前に、Pins Toolが何を設定しているツールなのかを整理しておきましょう。 Pins Toolでは 「信号がどこから来て、どこへ流れるか」 という観点でピン設定を行います。 この“流れ”には、大きく3つのパターンがあります。 ① 外部の信号をMCUに取り込む(ピン⇀ペリフェラル) まずは入力です。外部のセンサやスイッチ、他のICからの信号をピン経由でMCU内のペリフェラルに取り込むケースです。  Routing Details上の”+”をクリックすると行を追加し、直接入力できます。  下記図の例では、「リセットボタンSW1からの入力された信号をF3ピン(RESET_B)経由でMCUに取り込むこと」を示しています。 ② MCU内部の信号を外部に出す(ペリフェラル⇀ピン) 続いて出力です。MCU内部のペリフェラルからピンを介して外部に信号を出すケースです。 下記図の例では、「内部ペリフェラル(FlexSPI)の信号(FLEXSPI_B_DATA0)をK3ピンに割り当て、その信号を外部へ出力すること」を示しています。 ③ 内部で完結する接続 (ペリフェラル⇀ペリフェラル) 最後に内部ペリフェラルの出力を別の内部ペリフェラルの入力に接続するケースです。 下記図の例では、「PWMのトリガ信号(PWM0_A0_TRIG0)を、内部ルーディングによりADC0のトリガ入力(TRG CH0)として使う」ことを示しています。 この場合は外部ピンを経由しないため、左端のピン割り当てを示す”# “はn/aとなっています。 実際の多くの設計では、外部との入出力となる①・②のケースが大半を占めます。 ③の内部接続は、より高度な制御や最適化を行う際に使用されます。   デモンストレーション:ピン設定を変更し、LEDの点滅色を変更する ここからは実際にPins Tool上でピン設定を変更し、評価ボード上のLEDの点滅色が変更されるかを見ていきます。 ハードウェアの準備 本稿で使用する評価ボード ・FRDM-MCXN947 SDKのインストール VS Code内の左側のパネルからMCUXpressoを選択した状態で「Import Repository」をクリックしてください。 その後、左から2番目の「REMOTE ARCHIVE」をクリックし、Packageにて「FRDM-MCXN947」を検索してください。「947」と打ち込むとすぐに出てきます。 Name名、Location名、Create Gitへのチェックは任意に設定して下さい。 ※NameおよびLocation名については、「小文字の英数字」「アンダースコア(_)またはハイフン(-)」のみを使用し、(\, /, :, *, ?, ", <, >, |)などの記号やスペース(プログラムの動作不良の原因になりうる)を避けるのが無難です。 最後に「I agree」にチェックを入れた後、「Import」をクリックするとSDKのインストールが開始しますので、しばらくお待ちください。画面右下に"Repository successfully imported"が表示されたら完了です。 サンプルコードのインポート SDKのインストールが完了したら、サンプルコードのインポートへと進みます。 左側のパネルから「Import Example From Repository」をクリックしてください。 右側に表示された各タブ内で、「Repository」では先ほどインポートしたSDKを選択、 「Board」はFRDM-MCXN947を選択してください。 「Template」では、今回はLEDの点滅色を変えるデモンストレーションですので、 「led」と打ち込んで表示される「driver_examples/gpio/gpio_led_output_cm33_core0」で試してみます。 その後、Toolchainを選択して「Import」をクリックしてください。 ConfigToolsを開く インポートしたサンプル上で右クリックして、「Open with MCUXpresso Config Tools」を選択してください。少し待つとConfig Toolsが立ち上がります。 Config Toolsが開いたらまずは右側のパネルにあるOverviewを確認します。このサンプルにおいては、ClocksとPinsの2つが緑色(ONの状態)になっており、2つのツールが有効であることを示しています。 Pinsを選択し、現在のピン設定の状況を見てみます。 「Routing Details」を見ると3つのピン(A1,B1,B12)が有効になっています。 しかしながら、LEDに対して設定されているB12ピンのDirectionを見ると“Not Specified”となっており、つまりPins Tool上ではLEDに対してOutput(出力)設定がされていない状態となっています。 では、なぜ設定がされていないのにLEDが点滅するのかというと、VS Codeに戻りCソースファイル(gpio_led_output.c)を見てみます。 Cソースファイルを見ると、BOARD_InitHardware()によってピンの機能は反映されますが、先ほど確認したように、この時点ではPins Tool上でB12ピンはGPIO出力として設定はされていません。 したがって、このサンプルの初期状態では、GPIOの入出力方向はPins Toolではなく、ソースコード側に依存しています。 具体的には、GPIO_PinInit()関数によってB12ピンが「GPIO出力」として初期化され、LEDを制御できる状態になっています。 今回の目的はPins Tool上でピン設定を変更し、その結果をコードとして反映させることですので、ソースコード側からGPIOの初期化および制御に関する部分(下記赤枠)を削除します。 削除するとGPIOの出力設定がどこにも存在しなくなるため、ビルド・デバッグを行うとLEDは点滅しなくなります。 続いて、Pins Toolsでピン設定を行います。Pins Toolより#B12ピンのGPIO0_10のDirectionをOutputに変更します。 これは先ほどの②MCU内部の信号を外部に出す(ペリフェラル⇀ピン)のケースです。 これにより「B12ピン(PIO0_10)をGPIO出力として設定し、MCU内部のGPIO制御(ソフトウェア制御)による信号をピン経由で外部(LED_RED)へ出力する状態」へと変わりました。 コードの変更点は右側のパネルのCode Previewより確認できます。 Not SpecifiedからOutputに変更することでpin_mux.cの最下部にGPIOの初期化コードが追加されます。 この状態でサンプルコードを書き換えます。まずはConfig Toolsの画面左上にあるUpdate Codeをクリックしてください。 その後Windowが表示されます。ここでもCode Previewと同様にコードの変更を確認することができます。 VS Codeに戻ると、画面上部にチェックボックスが3つ並んで表示されますので、チェックが入った状態でOKをクリックしてください。少し時間が経つと、Clocks Toolでの変更がVS Code上のサンプルコードに適応されます。 ※SDKのバージョンが異なる場合は表示されない場合もあります。 完了したら、ビルドの前にボード(FRDM-MCXN947)とPCを接続します。 接続が完了したらインポートしたサンプルをデバッグ(ビルド&書き込み&アプリケーションの実行)します。 デバッグのプロセスが完了したら、プログラムがブレイクポイントで止まっているので、画面上部のアイコン内の"|▶"をクリックします。 動画のように赤色のLEDが点滅を開始します。 (function() { var wrapper = document.getElementById('lia-vid-6397512171112w304h540r886'); var videoEl = wrapper ? wrapper.querySelector('video-js') : null; if (videoEl) { if (window.videojs) { window.videojs(videoEl).ready(function() { this.on('loadedmetadata', function() { this.el().querySelectorAll('.vjs-load-progress div[data-start]').forEach(function(bar) { bar.setAttribute('role', 'presentation'); bar.setAttribute('aria-hidden', 'true'); }); }); }); } }})(); (マイビデオを表示) プログラムの終了は、アイコンの□をクリックします(PCと接続している限りLEDは点滅を続けますが一旦無視してください)。 なぜ赤色LEDが点滅したのか? ここで、なぜ赤色LEDが点滅したのかについて補足します。 今回の赤色LEDの点滅は、大きく次の2つの設定によって決まっています。 app.h:どのLED(ピン)を操作するかを定義 pin_mux.c:そのピンをどのように使うかを定義 この2つによりLEDの点滅が実現されています どのLEDを操作しているか?(app.h) Cソースファイル「gpio_led_output.c」の最下部には、GPIO_PortToggle :指定したGPIOピンの出力を反転するための関数が存在します。 この関数では、 BOARD_LED_GPIO (GPIOポート) BOARD_LED_GPIO_PIN(ピン番号) で指定されたGPIOの出力を反転し、LEDを点滅させています。 ただしこの時点では、このGPIOポートとピンがどの色のLEDに対応しているかはわかりません。 そこで、BOARD_LED_GPIO で右クリックし「Go to Definition(もしくは"fn + F12")」を選択すると、「app.h」が開きます app.hでDefinitionsの部分を確認すると、これらの定義は赤色LED用のGPIOに割り当てられていることがわかります。つまり、この時点で操作対象が赤色LEDであることが確定します。しかし、app.hで赤色LEDが割り当てられていてもピン設定がGPIO出力になっていなければ、LEDは光りません。 ピンをどのように使うか(pin_mux.c) 続いて、ピン設定を確認するためにpin_mux.cの中身を見ていきます。「gpio_led_output.c」内にPin、Clock、Debug consolのそれぞれ初期化を実行するためのBOARD_InitHardware(); があるので、ここで右クリックし「Go to Definition(もしくは"fn + F12")」を選択し、さらに詳細を見てみます。 遷移先にBOARD_InitPins();があり、ここにピン設定が記述されています。BOARD_InitPins(); 上でもう一度右クリックし、「Go to Definition(もしくは"fn + F12")」を選択すると「pin_mux.c」が開きます。 pin_mux.c はPins Tool上で設定した内容が反映されたファイルで、先ほど赤色LEDをOutputへ変更した際にCode Previewで確認したものと同じです。最下部に以下の記述があり、赤色LEDに接続されたB12ピンを、初期値0のGPIO出力として初期化することを意味しています。 このように、app.hで「どのLEDを操作するか(赤色LED)」が決まり、pin_mux.cで「そのピンをGPIO出力として使えるようにする」ことで、GPIO_PortToggle()によって赤色LEDを制御できる状態になっています。 ピン設定を変更し、LEDの点滅を青色に変更する 次にピン設定を変更することでLEDの点滅色を赤色から青色に変更します。 Config Toolに戻り、Pinsから「LED」検索するとC4ピンが青色LED(LED_BLUE)に対応していることがわかります。 C4ピンにチェックを入れると下図のようなウィンドウが表示されるので、GPIO1:GPIO,2(PIO1_2)にチェックを入れてDoneをクリックします。 ここまで完了すると、Routing Detailsに追加したC4ピンが表示されます。 C4ピンをGPIO機能(PIO1_2)として設定し、このピンに青色LED(LED_BLUE)というラベルを割り当てています。これにより、ソフトウェアからこのピンを青色LEDとして扱うことができます。 続いて、ピンの入出力設定を行います。Directionの赤色LEDをOutput⇀Not Specifiedに、青色LEDをNot Specified ⇀Outputに変更します。この設定により青色LEDをGPIO出力として設定できました。 Code Previewで、pin_mux.cの変更点は確認できます。 この状態でサンプルコードを書き換えます。先ほど実施したようにConfig Tools上でUpdate Codeを実行し、VS Code上でも変更を承認してください。変更したピン設定が反映されます。 ここまでで、まずはpin_mux.cが更新されました。 最後に、app.hを更新します。 先ほどの手順でapp.hを開き、LED_REDからLED_BLUEに変更します。 この定義を変更することで、GPIOの制御対象を赤色LEDから青色LEDへ切り替えることができます。 ここまで完了したら再度デバッグ(ビルド&書き込み&アプリケーションの実行)します。 デバッグのプロセスが完了したら、画面上部のアイコン内の"|▶"をクリックします。 動画のように青色のLEDが点滅を開始します。 (function() { var wrapper = document.getElementById('lia-vid-6397512593112w304h540r703'); var videoEl = wrapper ? wrapper.querySelector('video-js') : null; if (videoEl) { if (window.videojs) { window.videojs(videoEl).ready(function() { this.on('loadedmetadata', function() { this.el().querySelectorAll('.vjs-load-progress div[data-start]').forEach(function(bar) { bar.setAttribute('role', 'presentation'); bar.setAttribute('aria-hidden', 'true'); }); }); }); } }})(); (マイビデオを表示) ちなみに、なぜ1つのLEDで異なる色の点滅ができたかについて、今回使用したボードFRDM-MCXN947にはRGB LEDが搭載されています。FRDM-MCXN947の回路図を見るとピンごとにR/G/Bが割り当てられていることがわかります。 このため、2色のピンを同時にPins Tool内で出力設定し、ソースコードを適切な形に整えれば様々な色を表現することも可能です (例 : 赤 + 青 = 紫)。   おまけ - ピン一覧をドキュメント(Excelファイル)で確認する MCX Nのリファレンス・マニュアルを開くと、添付ファイルにMCXNP184M150F70_Pinout.xlsx というファイルがあります。ここにはピンの一覧と各ピンに対するペリフェラル機能の一覧が載っています。 最近では、Pins Toolの進化により、このような一覧表を参照しながら手作業でピン設定を行う機会は少なくなってきているかもしれません。 一方で、デバイス選定やパッケージ比較、利用可能なペリフェラルの確認など、システム設計の初期段階では今でも有用なリファレンス資料として活用できます。 MCX Nのリファレンス・マニュアルをダウンロードするには、MyNXPアカウントの登録が必要です。 ※Acrobat Readerで開いています 今回はシンプルな例で説明しましたが、実際の設計ではピン設定はさらに複雑になります。そんなときこそPins Toolを活用することで、ミスを防ぎながら効率的に設定を進めることができます。是非ご活用ください。 =========================​ 本投稿の「Comment」欄にコメントをいただいても、現在返信に対応しておりません。​ お手数をおかけしますが、お問い合わせの際には「NXPへの技術質問 - 問い合わせ方法 (日本語ブログ)」をご参照ください。​ (既に弊社NXP代理店、もしくはNXPとお付き合いのある方は、直接担当者へご質問いただいてもかまいません。) MCUXpresso Config Toolsの中から「Pins Tool」にフォーカスし、ピン設定の基本および設定方法を解説します。 VS Code環境での導入方法から、ピン設定の変更によるLED点滅デモまで紹介します。 (作業時間:10分 *MCUXpresso for VSC (Visual Studio Code), SDKをインストールしている前提) MCUXpresso MCX SW | Downloads 日本語ブログ
View full article
Function of solid plane in the NFC antenna Hello, We have integrated our NFC antenna onto a controller board. Our antenna measures approximately 90 mm x 40 mm and has 3 turns. It is already surrounded by ground planes on two sides. The distance between the ground planes and the antenna is approximately 5 mm. Our PCB manufacturer (of a multi-layer PCB) wants us to fill the antenna area of the inner layers with copper. Since I found NFC demo boards from NXP where this is implemented in a similar way, I think it should work and would like to implement it similarly. Are there any reasons why it was implemented this way on these evaluation boards? To what extent does the copper area affect the range? Does the copper area affect EMC? Is it better or worse? What should be the minimum distance between the copper area and the antenna? Is it better to use a single large area or several small areas? Thank you very much, and best regards, Michael Re: Function of solid plane in the NFC antenna Hello Michael,  The main reason why we use this inner metallization is mainly for a demonstration purpose to simulate a realistic environment around the NFC antenna e.g. in the POS terminal.  Also this metal filling may help to reduce the detuning effect by a different object because the antenna is already tuned with the "metal loading" inside.   However for the real product, I would go for a conventional NFC antenna without any filling inside. BR Tomas  Re: Function of solid plane in the NFC antenna Hi Tomas, Thank you very much for the information. We have since conducted tests by gluing copper tiles (8 mm x 8 mm, spaced 2 mm apart, 2 layers each) to the antenna surface on both the top and bottom. We then measured the antenna and rematched it. We can’t detect any differences in terms of functionality (range, current measurement, and EMI). You wrote that you would recommend a conventional design. Are there reasons for this, and if so, what are they? Maybe several smaller areas with more spacing between them would be better than the 8x8 mm with 2 mm spacing? Thank you very much, Michael Re: Function of solid plane in the NFC antenna Hello @michael_d_1983 , As mentioned, we use the copper tiles to demonstrates a a bit more realistic environment. This means that you may observe a slightly lower reading range, which is more reflecting the reality than an ideal antenna in free space. This because of some energy is absorbed the the metal tiles.  But there is no change in the TX current and EMI, if the tuning stays the same.  Therefore there is no need to implement such design into the "real" product.  BR Tomas  Re: Function of solid plane in the NFC antenna Hi Tomas, Thanks for your feedback! We actually don’t want to include the copper areas at all. The PCB manufacturer wants us to do that. (The reason is that if the copper distribution on the PCB is uneven, problems arise during the lamination process in PCB production—such as air pockets and delamination—because the resin in the prepregs isn’t sufficient to compensate for the missing copper.) We just want to clarify whether there’s any fundamental reason against this that we haven’t considered yet. We’ve tested it (reader functionality). Everything seems to be working as usual. Best regards, Michael
View full article
使用 NXP DDR Tool 在 IMX8M Plus 中无法完成 DDR 测试 您好, 我下载了RPA工具并更新了信息。附件是截图。   通过脚本,我能够在调试模式下获取 PMIC 信息。 这里是调试日志和 .ds 文件。文件供参考。 我在调试日志中发现内存容量显示为: 每个芯片选区的密度:4096MB 每个控制器的容量为:4096MB 但我使用了 1GB 容量的 LPDDR4 RAM(W66DP2RQQAGJ:双芯片封装 (DDP) 32Mb x 16DQ x 8 组 x 2 通道,密度为 8 Gb (8,589,934,592 位)。 它还卡在了“步骤 1:DDRPHY 训练”这一步。 Re: Unable to complete DDR test via NXP DDR Tool in IMX8M Plus 您好,我的配置工具也出现了同样的问题。以下是日志,供您参考。 此致 Re: Unable to complete DDR test via NXP DDR Tool in IMX8M Plus 你好, 我看不出你的内存配置有什么问题。 如果使用配置工具中的 DDR 工具,是否也会出现同样的问题? 顺祝商祺! Re: Unable to complete DDR test via NXP DDR Tool in IMX8M Plus 你好, 您在配置工具中遇到的问题是串口连接存在问题,请确认串口已连接到 Cortex-A 控制台,并且开发板处于串口下载模式。 请问您能分享一下您的原理图吗? 顺祝商祺! Re: Unable to complete DDR test via NXP DDR Tool in IMX8M Plus 您好, 使用 MSCALE_DDR_TOOL 可以解决此问题。 这是IMX8MP的页面链接 https://community.nxp.com/t5/i-MX-Processors-Knowledge-Base/i-MX-8M-Family-DDR-Tool-Release/ta-p/1104467 以及 LPDDR 的 RPA 表格链接 https://community.nxp.com/t5/i-MX-Processors-Knowledge-Base/i-MX-8MPlus-m865S-DDR-Register-Programming-Aids-RPA/ta-p/1235352 谢谢!
View full article
chromium-ozone-waylandのコンパイル中にビルドが失敗しました こんにちは、 YoctoでIMX8MPボード用にchromium-ozone-waylandをコンパイルしようとしていますが、以下のエラーでコンパイルが失敗します: | デバッグ: Python 関数 extend_recipe_sysroot が完了しました | デバッグ: シェル関数 do_configure を実行中 | エラー //.gn:150:5: 代入が無効でした。 | build_dotfile_settings.exec_script_allowlist + | ^--------------------------------------------- ここで変数「exec_script_allowlist」を設定しましたが、以前は使用されていませんでした。 対象外です。 警告: シェルコマンドからの終了コードが 1 です。 エラー:タスク(/home/admin/Dharmik/IMX8M-Plus/sources/meta-browser/meta-chromium/recipes-browser/chromium/chromium-ozone-wayland_138.0.7204.157.bb:do_configure)終了コード「1」で失敗しました 注:タスクの概要:2814個のタスクが試行され、そのうち2800個は再実行の必要がなく、1個が失敗しました。 conf/local.conf に CORE_IMAGE_EXTRA_INSTALL += "chromium-ozone-wayland" を追加しました。 以下は私のヨクト設定です。 ビルド構成: BB_VERSION = "2.16.0" BUILD_SYS = 「x86_64-linux」 NATIVELSBSTRING = 「ユニバーサル」 TARGET_SYS = "aarch64-poky-linux" MACHINE = "imx8mp-lpddr4-evk" ディストリビューション = "fsl-imx-wayland" DISTRO_VERSION = 「6.18-whinlatter」 TUNE_FEATURES = "aarch64 armv8a crc crypto" ありがとうございます ダルミック Re: Build failed while compiling chromium-ozone-wayland 過去のChromiumバージョンでもこのエラーを見たことがあり、そのビルド状況で私の場合うまくいったのはこのファイルの変更でした。 \tmp\work\armv8a-mx8-poky-linux\chromium-ozone-wayland\117.0.5938.132\chromium-117.0.5938.132\media\gpu\sandbox\BUILD.gn if (current_cpu != "s390x" && current_cpu != "ppc64" && is_linux && ozone_platform_x11 && !is_castos) { # For DRI_DRIVER_DIR. configs += [ "//build/config/linux/dri" ] } このファイルの下部のプラットフォームリストに「&& ozone_platform_x11 」を追加したことで問題は解決しました。 Chromium v138がすでに追加されているか確認してもらえますかozone_platform_x11? よろしくお願いいたします。 ダイアナ Re: Build failed while compiling chromium-ozone-wayland PREFERRED_VERSION_gn-native = "0+git" の変更を追加した後、以下のエラーが発生します。 |DEBUG: Python関数extend_recipe_sysroot完了しました |DEBUG:シェル関数の実行do_configure |//build/config/linux/dri/BUILD.gn:11:20でのエラー:スクリプトがゼロでない終了コードを返しました。 |dri_driver_dir = exec_script(pkg_config_script, |^---------- |現在の編集名: /home/admin/Dharmik/IMX8M-Plus/build-imx8mp/tmp/work/armv8a-mx8mp-poky-linux/chromium-ozone-wayland/138.0.7204.157/sources/chromium-138.0.7204.157/out/Release/ |コマンド: python3 /home/admin/Dharmik/IMX8M-Plus/build-imx8mp/tmp/work/armv8a-mx8mp-poky-linux/chromium-ozone-wayland/138.0.7204.157/sources/chromium-138.0.7204.157/build/config/linux/pkg-config.py --dridriverdir dri |1枚返品して印刷しました: | |pkg-configからのエラーです。 | |スタール: | |pkg-configの検索パスにはdriパッケージが見つかりませんでした。 |おそらく「dri.pc」を含むディレクトリを追加したほうがいいかもしれません |PKG_CONFIG_PATH環境変数に |パッケージの「ドリ」は見つかりませんでした | |//media/gpu/sandbox/BUILD.gn:31:18:を参照し、これがファイルが含まれた原因となりました。 |configs += [ "//build/config/linux/dri" ] |^------------------------- |警告:シェルコマンドからコード1を終了してください。 ありがとうございます ダルミック Re: Build failed while compiling chromium-ozone-wayland こんにちは、ダルミックさん。 local.confにchromiumパッケージ以外にもう一つ追加してみてはどうでしょうか? PREFERRED_VERSION_gn-native = "0+git" 問題が解決しない場合はお知らせください。 よろしくお願いいたします。 ダイアナ
View full article
Build failed while compiling chromium-ozone-wayland Hello, I am trying to compile chromium-ozone-wayland on Yocto for IMX8MP board, but the compilation fails with the error: | DEBUG: Python function extend_recipe_sysroot finished | DEBUG: Executing shell function do_configure | ERROR at //.gn:150:5: Assignment had no effect. | build_dotfile_settings.exec_script_allowlist + | ^--------------------------------------------- | You set the variable "exec_script_allowlist" here and it was unused before it went | out of scope. | WARNING: exit code 1 from a shell command. ERROR: Task (/home/admin/Dharmik/IMX8M-Plus/sources/meta-browser/meta-chromium/recipes-browser/chromium/chromium-ozone-wayland_138.0.7204.157.bb:do_configure) failed with exit code '1' NOTE: Tasks Summary: Attempted 2814 tasks of which 2800 didn't need to be rerun and 1 failed. I have added CORE_IMAGE_EXTRA_INSTALL += "chromium-ozone-wayland" in conf/local.conf Below is my yocto configuration, Build Configuration: BB_VERSION = "2.16.0" BUILD_SYS = "x86_64-linux" NATIVELSBSTRING = "universal" TARGET_SYS = "aarch64-poky-linux" MACHINE = "imx8mp-lpddr4-evk" DISTRO = "fsl-imx-wayland" DISTRO_VERSION = "6.18-whinlatter" TUNE_FEATURES = "aarch64 armv8a crc crypto"  Thanks, Dharmik Re: Build failed while compiling chromium-ozone-wayland I've seen this error in the past Chromium versions, and what worked for me in that build situation was a change in this file: \tmp\work\armv8a-mx8-poky-linux\chromium-ozone-wayland\117.0.5938.132\chromium-117.0.5938.132\media\gpu\sandbox\BUILD.gn if (current_cpu != "s390x" && current_cpu != "ppc64" && is_linux && ozone_platform_x11 && !is_castos) { # For DRI_DRIVER_DIR. configs += [ "//build/config/linux/dri" ] } Adding "&& ozone_platform_x11 " to the platform list at the bottom of this files fixed the issue. Could you check whether Chromium v138 has already ozone_platform_x11 added? Best regards, Diana Re: Build failed while compiling chromium-ozone-wayland After adding PREFERRED_VERSION_gn-native = "0+git" changes I am getting below error, | DEBUG: Python function extend_recipe_sysroot finished | DEBUG: Executing shell function do_configure | ERROR at //build/config/linux/dri/BUILD.gn:11:20: Script returned non-zero exit code. | dri_driver_dir = exec_script(pkg_config_script, | ^---------- | Current dir: /home/admin/Dharmik/IMX8M-Plus/build-imx8mp/tmp/work/armv8a-mx8mp-poky-linux/chromium-ozone-wayland/138.0.7204.157/sources/chromium-138.0.7204.157/out/Release/ | Command: python3 /home/admin/Dharmik/IMX8M-Plus/build-imx8mp/tmp/work/armv8a-mx8mp-poky-linux/chromium-ozone-wayland/138.0.7204.157/sources/chromium-138.0.7204.157/build/config/linux/pkg-config.py --dridriverdir dri | Returned 1 and printed out: | | Error from pkg-config. | | stderr: | | Package dri was not found in the pkg-config search path. | Perhaps you should add the directory containing `dri.pc' | to the PKG_CONFIG_PATH environment variable | No package 'dri' found | | See //media/gpu/sandbox/BUILD.gn:31:18: which caused the file to be included. | configs += [ "//build/config/linux/dri" ] | ^------------------------- | WARNING: exit code 1 from a shell command. Thanks, Dharmik Re: Build failed while compiling chromium-ozone-wayland Hi Dharmik, Can you try adding to local.conf one more thing besides chromium package?  PREFERRED_VERSION_gn-native = "0+git" Let me know if the issue still persists. Best regards, Diana
View full article
IMX8M PlusでNXP DDRツールによるDDRテストを完了できません こんにちは、 RPAツールをダウンロードして情報を更新しました。添付のスクリーンショットをご覧ください。   そのスクリプトのおかげで、デバッグモードでPMICの情報を取得することができました。 デバッグログと.dsファイルはこちらです参考資料として保管してください。 デバッグログでメモリ容量が次のように表示されていることがわかりました。 チップセレクトあたりの密度:4096MB コントローラーあたりの密度は4096MBです しかし、私はLPDDR4 RAMを1GB容量(W66DP2RQQAGJ:デュアルダイパッケージ(DDP)32Mb x 16DQ x 8バンク×2チャネル、8 Gb(8,589,934,592ビット)の密度で使ったことがあります。 また、「ステップ1:DDRPHYトレーニング」で止まってしまいました。 Re: Unable to complete DDR test via NXP DDR Tool in IMX8M Plus こんにちは、私もConfigツールで同じ問題が発生しています。参考までにログを以下に示します。 よろしくお願いします Re: Unable to complete DDR test via NXP DDR Tool in IMX8M Plus こんにちは、 そのメモリの設定に問題は見当たりません。 DDRツールやConfig Toolsを使って試した場合も、同じ問題が発生しますか? よろしくお願いいたします。 Re: Unable to complete DDR test via NXP DDR Tool in IMX8M Plus こんにちは、 設定ツールで起きている問題はシリアルポート接続に問題があることを示しています。Cortex-Aコンソールに接続されているか、そしてボードがシリアルダウンロードモードで接続されているか確認してください。 回路図を教えていただけますか? よろしくお願いいたします。 Re: Unable to complete DDR test via NXP DDR Tool in IMX8M Plus こんにちは、 MSCALE_DDR_TOOLを使用することで、この問題は解決します。 IMX8MPのページへのリンクはこちらです https://community.nxp.com/t5/i-MX-Processors-Knowledge-Base/i-MX-8M-Family-DDR-Tool-Release/ta-p/1104467 LPDDR用のRPAシートリンク https://community.nxp.com/t5/i-MX-Processors-Knowledge-Base/i-MX-8MPlus-m865S-DDR-Register-Programming-Aids-RPA/ta-p/1235352 よろしくお願いします。
View full article
NFC天线中固体平面的作用 你好, 我们已将NFC天线集成到控制器板上。 我们的天线尺寸约为 90 毫米 x 40 毫米,有 3 圈。 它两侧已被地面包围。地平面与天线之间的距离约为 5 毫米。 我们的PCB制造商(生产多层PCB)要求我们在内层天线区域填充铜。 由于我找到了 NXP 的 NFC 演示板,其中以类似的方式实现了此功能,我认为它应该可行,并且我想以类似的方式实现它。 这些评估委员会采用这种方式实施的原因是什么? 铜矿区对射程的影响程度如何? 铜箔面积会影响电磁兼容性吗?是更好还是更糟? 铜区域与天线之间的最小距离应该是多少? 使用一个大区域好,还是使用几个小区域好? 非常感谢,并致以最诚挚的问候。 迈克尔 Re: Function of solid plane in the NFC antenna 你好,迈克尔, 我们使用这种内部金属化的主要原因是为了演示目的,模拟 NFC 天线周围的真实环境,例如在 POS 终端中。 此外,这种金属填充物可能有助于减少其他物体造成的失谐效应,因为天线内部的“金属负载”已经使其调谐。 但是对于实际产品而言,我会选择内部没有任何填充物的传统 NFC 天线。 BR 托马斯 Re: Function of solid plane in the NFC antenna 嗨,托马斯, 非常感谢您提供的信息。 此后,我们进行了测试,将铜片(8 毫米 x 8 毫米,间隔 2 毫米,每片 2 层)粘到天线表面的顶部和底部。 然后我们测量了天线并重新匹配。 我们在功能方面(范围、电流测量和电磁干扰)检测不出任何差异。 您曾写道,您会推荐传统的设计方案。 造成这种情况的原因是什么?如果有,原因是什么? 或许几个间距更大的小区域会比间距为 2 毫米的 8x8 毫米区域更好? 非常感谢, 迈克尔 Re: Function of solid plane in the NFC antenna 你好@michael_d_1983 , 如前所述,我们使用铜瓦来展示更真实的场景。 这意味着您可能会观察到读数范围略低,这比自由空间中的理想天线更能反映实际情况。这是因为部分能量被金属瓦片吸收了。 但如果调谐保持不变,则发射电流和电磁干扰不会发生变化。 因此,没有必要将这种设计应用到“实际”产品中。 BR 托马斯 Re: Function of solid plane in the NFC antenna 嗨,托马斯, 感谢您的反馈! 我们其实根本不想把铜矿区包括在内。PCB制造商希望我们这样做。 (原因是,如果PCB上的铜分布不均匀,在PCB生产的层压过程中就会出现问题,例如气泡和分层,因为预浸料中的树脂不足以弥补铜的缺失。) 我们只是想澄清一下,是否存在我们尚未考虑到的反对这一做法的根本原因。 我们已经测试过了(阅读器功能)。一切似乎都正常运转。 此致, 迈克尔
View full article
Unable to complete DDR test via NXP DDR Tool in IMX8M Plus Hi, I downloaded RPA Tool and updated the information. Here is the snapshot attached.   With the script I was able to get the PMIC information in debug. here are the debug log and .ds file for reference. I found out in the debug log the memory capacity was shown as : Density per chip select:  4096MB  Density per controller is: 4096MB  but I have used LPDDR4 RAM with 1GB capacity (W66DP2RQQAGJ: Dual-Die-Package (DDP) 32Mb x 16DQ x 8-banks x 2 channels with 8 Gb (8,589,934,592 bits) density. Also it got stuck in "Step 1: DDRPHY Training" Re: Unable to complete DDR test via NXP DDR Tool in IMX8M Plus hi, I am getting the same issue with Config tool. Here are the log for reference. Best regards Re: Unable to complete DDR test via NXP DDR Tool in IMX8M Plus Hello, I do not see issues in your configuration for that memory. Do you get the same issue if you try with DDR Tool of Config Tools? Best regards. Re: Unable to complete DDR test via NXP DDR Tool in IMX8M Plus Hello, The issue you are getting in Config Tools shows that there is an issue with serial port connection, please confirm that is connected to the Cortex-A console and the board in serial download mode. Could you please share you schematic? Best regards. Re: Unable to complete DDR test via NXP DDR Tool in IMX8M Plus Hi, The issue is resolved using MSCALE_DDR_TOOL. Here is the link of the page for IMX8MP https://community.nxp.com/t5/i-MX-Processors-Knowledge-Base/i-MX-8M-Family-DDR-Tool-Release/ta-p/1104467 And RPA Sheet Link for LPDDR https://community.nxp.com/t5/i-MX-Processors-Knowledge-Base/i-MX-8MPlus-m865S-DDR-Register-Programming-Aids-RPA/ta-p/1235352 Thanks
View full article
编译 chromium-ozone-wayland 时构建失败 你好, 我尝试在 Yocto 上为 IMX8MP 开发板编译 chromium-ozone-wayland,但编译失败并出现以下错误: | 调试:Python 函数 extend_recipe_sysroot 已完成 | 调试:正在执行 shell 函数 do_configure | 错误位于 //.gn:150:5: 赋值无效。 | build_dotfile_settings.exec_script_allowlist + | ^--------------------------------------------- 您在此处设置了变量“exec_script_allowlist”,但在它离开之前未使用过。 | 超出范围。 | 警告:shell 命令的退出代码为 1。 错误:任务 (/home/admin/Dharmik/IMX8M-Plus/sources/meta-browser/meta-chromium/recipes-browser/chromium/chromium-ozone-wayland_138.0.7204.157.bb:do_configure)失败,退出代码为“1” 注意:任务摘要:尝试了 2814 个任务,其中 2800 个不需要重新运行,1 个失败。 我已在 conf/local.conf 中添加了 CORE_IMAGE_EXTRA_INSTALL += "chromium-ozone-wayland" 以下是我的 Yocto 配置: 构建配置: BB_VERSION = "2.16.0" BUILD_SYS = "x86_64-linux" NATIVELSBSTRING = "universal" TARGET_SYS =“aarch64-poky-linux” 机器 = "imx8mp-lpddr4-evk" DISTRO = "fsl-imx-wayland" DISTRO_VERSION = "6.18-whinlatter" TUNE_FEATURES = "aarch64 armv8a crc crypto" 谢谢! 达摩克 Re: Build failed while compiling chromium-ozone-wayland 我在之前的 Chromium 版本中遇到过这个错误,当时我的解决方法是修改以下文件: \tmp\work\armv8a-mx8-poky-linux\chromium-ozone-wayland\117.0.5938.132\chromium-117.0.5938.132\media\gpu\sandbox\BUILD.gn if (current_cpu != "s390x" && current_cpu != "ppc64" && is_linux && ozone_platform_x11 && !is_castos) { # For DRI_DRIVER_DIR. configs += [ "//build/config/linux/dri" ] } 添加“ && ozone_platform_x11 将“添加到此文件底部的平台列表”解决了这个问题。 请问 Chromium v138 是否已经添加了 ozone_platform_x11 模块? 顺祝商祺! 戴安娜 Re: Build failed while compiling chromium-ozone-wayland 添加PREFERRED_VERSION_gn-native = "0+git" 更改后,出现以下错误: | 调试:Python 函数 extend_recipe_sysroot 已完成 | 调试:正在执行 shell 函数 do_configure | 错误位于 //build/config/linux/dri/BUILD.gn:11:20: 脚本返回非零退出代码。 | dri_driver_dir = exec_script(pkg_config_script, | ^---------- | 当前目录:/home/admin/Dharmik/IMX8M-Plus/build-imx8mp/tmp/work/armv8a-mx8mp-poky-linux/chromium-ozone-wayland/138.0.7204.157/sources/chromium-138.0.7204.157/out/Release/ | 命令:python3 /home/admin/Dharmik/IMX8M-Plus/build-imx8mp/tmp/work/armv8a-mx8mp-poky-linux/chromium-ozone-wayland/138.0.7204.157/sources/chromium-138.0.7204.157/build/config/linux/pkg-config.py --dridriverdir dri 返回值为 1,并打印出来: | | pkg-config 出错。 | | 标准错误输出: | | 在 pkg-config 搜索路径中未找到软件包 dri。 或许您应该添加包含 `dri.pc` 的目录。 | 添加到 PKG_CONFIG_PATH 环境变量 未找到软件包“dri”。 | | 请参阅 //media/gpu/sandbox/BUILD.gn:31:18:导致该文件被包含。 | configs += [ "//build/config/linux/dri" ] | ^------------------------- | 警告:shell 命令的退出代码为 1。 谢谢! 达摩克 Re: Build failed while compiling chromium-ozone-wayland 你好, Dharmik, 除了 chromium 软件包之外,您能否尝试在local.conf中添加其他内容? PREFERRED_VERSION_gn-native = "0+git" 如果问题仍然存在,请告知我。 顺祝商祺! 戴安娜
View full article
NFCアンテナにおける固体平面の機能 こんにちは、 私たちはNFCアンテナをコントローラボードに統合しています。 当社のアンテナは、約90mm×40mmのサイズで、3ターン巻かれています。 既に両側を地上の飛行機に囲まれている。グランドプレーンとアンテナ間の距離は約5mmです。 多層基板の製造業者から、内層のアンテナ領域を銅で埋めるように指示されています。 NXPのNFCデモボードで同様の実装例を見つけたので、うまくいくはずだと考え、同様の方法で実装したいと思っています。 なぜこれらの評価ボードでこのように実装されたのでしょうか? 銅の面積は、どの程度範囲に影響しますか? 銅箔面積はEMCに影響を与えますか?良くなったのか、悪くなったのか? 銅部分とアンテナ間の最小距離はどれくらいにすべきですか? 広い面積を1つ使うのと、小さな面積を複数使うのとでは、どちらが良いでしょうか? どうもありがとうございました。よろしくお願いいたします。 マイケル Re: Function of solid plane in the NFC antenna こんにちは、マイケルさん。 この内部金属配線を使用する主な理由は、主にデモンストレーション目的で、例えばPOS端末内におけるNFCアンテナ周辺の現実的な環境をシミュレートするためです。 また、この金属充填は、アンテナが内部の「金属負荷」によって既に同調されているため、他の物体による同調ずれの影響を軽減するのに役立つ可能性がある。 しかし製品なら、内部に充填のない従来のNFCアンテナを選びます。 BR トマス Re: Function of solid plane in the NFC antenna こんにちは、トーマスさん。 情報提供ありがとうございました。 その後、アンテナ表面の上下両面に銅製のタイル(8mm×8mm、2mm間隔、各2層)を接着して試験を実施しました。 次にアンテナを測定し、再調整しました。 機能面(航続距離、電流測定、EMI)で違いは検出できません。 あなたは従来型の設計を推奨すると書いていましたね。 その理由はあるのでしょうか?もしあれば、それは何でしょうか? 8×8mmで間隔が2mmの領域よりも、間隔の広い小さな領域をいくつか設けた方が良いかもしれません。 どうもありがとうございます、 マイケル Re: Function of solid plane in the NFC antenna こんにちは、 @michael_d_1983 さん、 前述の通り、よりリアルな環境を表現するために銅製のタイルを使用しています。 これは、受信範囲が若干狭くなる可能性があることを意味します。これは、自由空間にある理想的なアンテナよりも、より現実的な状況を反映しています。これは、金属タイルがエネルギーの一部を吸収するためです。 しかし、チューニングが同じままであれば、送信電流とEMIに変化はありません。 したがって、そのような設計を「実際の」製品に実装する必要はありません。 BR トマス Re: Function of solid plane in the NFC antenna こんにちは、トーマスさん。 ご意見ありがとうございます! 実際には、銅の領域は一切含めたくないのです。基板メーカーは私たちにそうしてほしいと望んでいます。 (その理由は、プリント基板上の銅の分布が不均一だと、プリプレグに含まれる樹脂が不足している銅を補うのに十分ではないため、プリント基板製造における積層工程で気泡や剥離などの問題が発生するからである。) 私たちがまだ考慮していない、これに対する根本的な反対理由があるかどうかを明確にしたいだけです。 (リーダー機能について)テスト済みです。すべて通常通りに機能しているようです。 よろしくお願いします、 マイケル
View full article
RW610/RW612はTLS 1.2以降をサポートしていますか? RW610/RW612はTLS 1.2以降をサポートしていますか? Re: RW610/RW612 支持TLS 1.2及以上版本么 こんにちは、 @Cherlyn はい、RW610/RW612はTLS 1.2をサポートしています。 TLS 3.0については、frdmrw612_mbedtls3x_selftestやfrdmrw612_mbedtls3x_psatestなどの関連サンプルを用意しています。これらを参照して、要件を満たしているかどうかをご確認ください。 他に何か具体的なご要望がございましたら、遠慮なくお申し付けください。一緒に話し合いましょう。 よろしくお願いします、 クリスティン。
View full article
[S32K324 / 定制板] HSE 固件已安装 (0x4039C028=1) 但初始化失败 (0x4038C107=0) 大家好, 我正在寻求有关 S32K324 定制板上 HSE 固件初始化无法完成的问题的建议。 1. 开发环境 MCU:S32K324(定制板) HSE固件:s32k3x4_hse_fw_1.5.0_2.55.0_pb250130.bin.pink 调试器:S32DS + T32 (Trace32) 2. 进度和状态登记册 已成功在 UTEST 区域 (0x1B000000) 中编程 HSE FW 使用标志。 已将粉色图像二进制文件下载到闪存中。 执行上电复位(POR)后,状态寄存器如下: 0x4039C028 (HSE GPR): 0x01 (安装已确认) 0x4038C107 (HSE_STATUS_INIT_OK): 0x00 (启动过程中停止) 3. 问题 我想请教各位专家以下问题: 我首先应该检查什么? 由于安装成功但初始化失败,是否有任何特定的寄存器(例如,故障状态)或硬件信号需要检查以找出确切的原因? 自定义板环境是否会影响初始化失败? 由于我使用的是定制板,我怀疑硬件差异(例如,初始晶振频率)或主核心(M7)的早期时钟(PLL)配置代码可能会干扰 HSE 启动序列。如果这是一个已知问题,能否指导我推荐的启动顺序(例如,在进行任何时钟设置之前轮询 INIT_OK 标志)或可能的解决方案? 任何线索都将对我们大有帮助。感谢您的支持! Re: [S32K324 / Custom Board] HSE FW Installed (0x4039C028=1) but Init Failed (0x4038C107=0) 您好, 非常感谢您提供的清晰指导。 首先,我使用演示应用程序进行固件安装,然后在系统启动状态下转储 MU 和 HSE GPR 寄存器值。如果这些注册地址有任何错误,请告知我。 结果如下: 1. MU0 寄存器(基地址:0x4038C000)     2. HSE GPR 寄存器(基地址:0x4039C000)   请您审核一下这些数值好吗?我非常希望您能提供专业意见,帮我判断这些是否表明存在具体的错误原因,例如时钟配置冲突或固件认证失败。 再次感谢您的时间和支持! Re: [S32K324 / Custom Board] HSE FW Installed (0x4039C028=1) but Init Failed (0x4038C107=0) 请问您能否提供以下信息? MU寄存器、FSR、GSR等: HSE GPR3: Re: [S32K324 / Custom Board] HSE FW Installed (0x4039C028=1) but Init Failed (0x4038C107=0) 谢谢。但我需要看到 HSE 核心处于 WFI 状态时的屏幕截图,而不是 RESET 后立即显示的屏幕截图。
View full article
RT1176 PWMの起動に失敗しました 私はPWM + Fault + QTimerを使ってモーターパルス制御を実装していますが、PWM3サブモジュール0のPWM_Aチャネルが時々起動できず、最初のハイレベル以降は一定のままで、その後のパルスは現れません。検査の結果、PWMの「ラン」部分が正しく設定されていないことが判明しました。後からプログラムに起動時の処理を繰り返し追加したにもかかわらず、この異常は依然として発生した。 Re: RT1176 PWM startup failed こんにちは、 @liu626 さん。 カスタムボードを使用していますか、それともEVKを使用していますか?EVKを使用している場合、何か改造を加えましたか? PWM3で使っている構成を教えてもらえますか? 何か例を参考にしていますか?もしそうなら、どの学校ですか? PWM3のみを含むプロジェクトを使用して問題を再現しようとした場合、問題は解消されますか? これはPWM3サブモジュール0のPWM_Aチャネルだけに起こるのでしょうか?他のPWMモジュールやサブモジュールでも同様の現象が発生しましたか? PWM3レジスタを操作し、ランビットに影響を与えたり上書きしたりする他のタスクや割り込みはありますか? よろしくお願いします、 パブロ Re: RT1176 PWM startup failed こんにちは、カスタム回路基板を使用しました。私は具体的な例を挙げませんでした。これは、プロジェクトの正式な開発過程で発見された問題だった。パルス制御用に6つのPWMチャネルを設定しました。このチャネルだけが問題を起こし、他のサブモジュールでは同様の問題はありませんでした。調べたところ、このチャネルだけがPWM3モジュールを使っていることがわかりました。他に干渉因子は検出されなかった。以下は私の設定です。 static axis_ctrl_t g_axes[AXIS_NUM] = ヤージュ ヤージュ .id= AXIS_X1、.name= "X1", .pwmBase= PWM1、.pwmModule= kPWM_Module_0、.pwmChannel= kPWM_PwmA、 .tmrBase= TMR3、.lowCh= kQTMR_Channel_2、.highCh= kQTMR_Channel_3、 .tmrInputsrc=kQTMR_ClockCounter2InputPin、.cascadePcs= 6U、 .faultNum= 0U、.hwExactSupported= true、.outTrigMask= kPWM_ValueRegisterMask_3、 }、 ヤージュ .id= AXIS_X2、.name= "X2", .pwmBase= PWM2、.pwmModule= kPWM_Module_0、.pwmChannel= kPWM_PwmA、 .tmrBase= TMR2、.lowCh= kQTMR_Channel_0、.highCh= kQTMR_Channel_1、 .tmrInputsrc=kQTMR_ClockCounter0InputPin、.cascadePcs= 4U、 .faultNum= 0U、.hwExactSupported= true、.outTrigMask= kPWM_ValueRegisterMask_3、 }、 ヤージュ .id= AXIS_Y、.name= "Y"、 .pwmBase= PWM3、.pwmModule= kPWM_Module_0、.pwmChannel= kPWM_PwmA、 .tmrBase= TMR3、.lowCh= kQTMR_Channel_0、.highCh= kQTMR_Channel_1、 .tmrInputsrc=kQTMR_ClockCounter0InputPin、.cascadePcs= 4U、 .faultNum= 0U、.hwExactSupported= true、.outTrigMask= kPWM_ValueRegisterMask_3、 }、 ヤージュ .id= AXIS_Z、.name= "Z"、 .pwmBase= PWM4、.pwmModule= kPWM_Module_0、.pwmChannel= kPWM_PwmA、 .tmrBase= TMR1、.lowCh= kQTMR_Channel_0、.highCh= kQTMR_Channel_1、 .tmrInputsrc=kQTMR_ClockCounter0InputPin、.cascadePcs= 4U、 .faultNum= 0U、.hwExactSupported= true、.outTrigMask= kPWM_ValueRegisterMask_3、 }、 ヤージュ .id= AXIS_EX1、.name= "EX1", .pwmBase= PWM1、.pwmModule= kPWM_Module_1、.pwmChannel= kPWM_PwmA、 .tmrBase= TMR1、.lowCh= kQTMR_Channel_2、.highCh= kQTMR_Channel_3、 .tmrInputsrc=kQTMR_ClockCounter2InputPin、.cascadePcs= 6U、 .faultNum= 1U、.hwExactSupported= true、.outTrigMask= kPWM_ValueRegisterMask_3、 }、 ヤージュ .id= AXIS_EX2、.name= "EX2", .pwmBase= PWM2、.pwmModule= kPWM_Module_1、.pwmChannel= kPWM_PwmA、 .tmrBase= TMR2、.lowCh= kQTMR_Channel_2、.highCh= kQTMR_Channel_3、 .tmrInputsrc=kQTMR_ClockCounter2InputPin、.cascadePcs= 6U、 .faultNum= 1U、.hwExactSupported= true、.outTrigMask= kPWM_ValueRegisterMask_3、 }、 };static void APP_Init_PWM_QTMR(void) ヤージュ pwm_config_t pwmConfig; pwm_fault_param_t faultConfig; qtmr_config_t qtmrConfig; PWM_GetDefaultConfig(&pwmConfig); pwmConfig.pairOperation= kPWM_Independent; pwmConfig.reloadLogic = kPWM_ReloadImmediate; PWM_FaultDefaultConfig(&faultConfig); faultConfig.faultLevel = true; faultConfig.enableCombinationalPath= 偽; faultConfig.faultClearingMode= kPWM_ManualSafety; faultConfig.recoverMode = kPWM_NoRecovery; QTMR_GetDefaultConfig(&qtmrConfig); CLOCK_EnableClock(kCLOCK_Qtimer1); CLOCK_EnableClock(kCLOCK_Qtimer2); CLOCK_EnableClock(kCLOCK_Qtimer3); PWM_StopTimer(PWM1, 0x0FU); PWM_StopTimer(PWM2, 0x0FU); PWM_StopTimer(PWM3, 0x0FU); PWM_StopTimer(PWM4, 0x0FU); pwm_fault_input_filter_param_t faultFilter; faultFilter.faultFilterPeriod= 255U; faultFilter.aultFilterCount= 7U; faultFilter.faultGlitchStretch= 偽; /* 记录每个 PWM 实例上已配置的 faultチャネル,避免重复设置 */ uint16_t pwm1FaultDone = 0U, pwm2FaultDone = 0U, pwm3FaultDone = 0U, pwm4FaultDone = 0U; for (uint8_t i = 0U; i < AXIS_NUM; i++) { axis_ctrl_t *ax = &g_axes[i]; PWM_Init(ax->pwmBase, ax->pwmModule, &pwmConfig); PWM_SetupFaults(ax->pwmBase, (pwm_fault_input_t)ax->faultNum, &faultConfig); /* 故障濾波(每個 PWM 实例的每个 faultチャネル 只设一次) */ { uint16_t *faultDone; if (ax->pwmBase == PWM1) faultDone = &pwm1FaultDone; else if (ax->pwmBase == PWM2) faultDone = &pwm2FaultDone; else if (ax->pwmBase == PWM3) faultDone = &pwm3FaultDone; else faultDone = &pwm4FaultDone; uint16_t faultBit = (uint16_t)(1U << ax->faultNum); if((*faultDone & faultBit) == 0U) { PWM_SetupFaultInputFilterExt(ax->pwmBase, (pwm_fault_channels_t)ax->faultNum, &faultFilter); *faultDone |= faultBit; } } /* 故障時輸出低電平 */ ax->pwmBase->SM[ax->pwmModule].OCTRL &= ~(PWM_OCTRL_PWMAFS_MASK |PWM_OCTRL_PWMBFS_MASK); APP_PWM_Unmap_Selected_Fault(ax); APP_PWM_ClearFault_Safe(ax); ax->pwmBase->SM[ax->pwmModule].INIT = 0U; ax->pwmBase->SM[ax->pwmModule].VAL0 = 0U; ax->pwmBase->SM[ax->pwmModule].VAL1 = 1U; ax->pwmBase->SM[ax->pwmModule].VAL2 = 0U; ax->pwmBase->SM[ax->pwmModule].VAL3 = 0U; ax->pwmBase->SM[ax->pwmModule].VAL4 = 0U; ax->pwmBase->SM[ax->pwmModule].VAL5 = 0U; ax->pwmBase->SM[ax->pwmModule].TCTRL = PWM_TCTRL_OUT_TRIG_EN(ax->outTrigMask); APP_PWM_Disable_Output(ax); if (ax->hwExactSupported) { qtmrConfig.primarySource= ax->tmrInputSrc; QTMR_Init(ax->tmrBase, ax->lowCh, &qtmrConfig); QTMR_Init(ax->tmrBase, ax->highCh, &qtmrConfig); ax->tmrBase->CHANNEL[ax->lowCh]。CTRL = TMR_CTRL_CM(kQTMR_PriSrcRiseEdge) |TMR_CTRL_PCS(ax->tmrInputSrc); ax->tmrBase->CHANNEL[ax->highCh]。CTRL = TMR_CTRL_CM(kQTMR_CascadeCount) |TMR_CTRL_PCS(ax->カスケードPcs); APP_QTMR_Disable_Low_OFLAG_Output(ax); QTMR_DisableInterrupts(ax->tmrBase, ax->lowCh, 0xFFU); QTMR_DisableInterrupts(ax->tmrBase, ax->highCh, 0xFFU); QTMR_ClearStatusFlags(ax->tmrBase, ax->lowCh, 0xFFU); QTMR_ClearStatusFlags(ax->tmrBase, ax->highCh, 0xFFU); } ax->位相 = kAxisIdle; ax->armed = false; ax->running=false; ax->done = 真; #if HARD_PWM_STATE_GUARD_ENABLE APP_StateGuard_Reset(斧); #endif } /* 使能 QTMR 中断 */ NVIC_SetPriority(TMR1_IRQn、2U); NVIC_SetPriority(TMR2_IRQn、2U); NVIC_SetPriority(TMR3_IRQn、2U); EnableIRQ(TMR1_IRQn); EnableIRQ(TMR2_IRQn); EnableIRQ(TMR3_IRQn); }静的ブールAPP_PWM_Config_Pulse(axis_ctrl_t *軸、 uint32_t highCnt400M、 uint32_t 低Cnt400M) { pwm_clock_prescale_tプリスケール; uint16_t期間ダックス; uint32_t totalCnt400M = highCnt400M + lowCnt400M; もし((軸 == NULL) ||(totalCnt400M == 0U))Return false; もし(!APP_PWM_SelectPrescaler_FromPeriodCnt400M(totalCnt400M、およびprescale、&periodTicks)) Return false; uint32_t highTicks32 = (uint32_t)((((uint64_t)periodTicks * (uint64_t)highCnt400M + ((uint64_t)totalCnt400M / 2ULL))/ (uint64_t)totalCnt400M); もし(highTicks32 == 0U) highTicks32 = 1U; もし(highTicks32 >= periodTicks) highTicks32 = (uint32_t)periodTicks - 1U; uint32_t riseTicks32 = 0U; uint32_t fallTicks32 = highTicks32; #if HARD_PWM_LOW_START_PHASE_ENABLE uint32_t lowTicks32 = (uint32_t)periodTicks - highTicks32; もし (lowTicks32 >= (2U * HARD_PWM_LOW_START_PHASE_MIN_TICKS)) { uint32_t LeadCnt400M = highCnt400M; uint32_t minLeadCnt400M = (uint32_t)HARD_PWM_LOW_START_PHASE_MIN_US * 400U; もし(desiredLeadCnt400M < minLeadCnt400M) desiredLeadCnt400M = minLeadCnt400M; uint32_t desiredLeadTicks32 = (uint32_t)(((uint64_t)periodTicks * (uint64_t)desiredLeadCnt400M + ((uint64_t)totalCnt400M / 2ULL))/ (uint64_t)totalCnt400M); if (desiredLeadTicks32 < HARD_PWM_LOW_START_PHASE_MIN_TICKS) desiredLeadTicks32 = HARD_PWM_LOW_START_PHASE_MIN_TICKS; uint32_t maxRiseByHalfTicks32 = lowTicks32 / 2U; uint32_t postGuardTicks32 = (uint32_t)(((uint64_t)periodTicks * (uint64_t)(HARD_PWM_VAL3_POST_LOW_GUARD_US * 400U) + ((uint64_t)totalCnt400M / 2ULL))/ (uint64_t)totalCnt400M); if(postGuardTicks32 < HARD_PWM_VAL3_POST_LOW_GUARD_MIN_TICKS) postGuardTicks32 = HARD_PWM_VAL3_POST_LOW_GUARD_MIN_TICKS; uint32_t maxRiseByPostGuardTicks32 = (lowTicks32 > postGuardTicks32) ? (lowTicks32 - postGuardTicks32) : 0U; uint32_t RiseTicks32; もし (maxRiseByHalfTicks32 >= desiredLeadTicks32) { selectedRiseTicks32 = desiredLeadTicks32; if(selectedRiseTicks32 > maxRiseByHalfTicks32) selectedRiseTicks32 = maxRiseByHalfTicks32; } そうでなければ(maxRiseByPostGuardTicks32 >= desiredLeadTicks32) { selectedRiseTicks32 = desiredLeadTicks32; if (selectedRiseTicks32 > maxRiseByPostGuardTicks32) selectedRiseTicks32 = maxRiseByPostGuardTicks32; } そうでなければ { selectedRiseTicks32 = maxRiseByPostGuardTicks32; } if (selectedRiseTicks32 >= HARD_PWM_LOW_START_PHASE_MIN_TICKS) { riseTicks32 = selectedRiseTicks32; fallTicks32 = riseTicks32 + highTicks32; } } #endif もし(fallTicks32 >= (uint32_t)periodTicks) fallTicks32 = (uint32_t)periodTicks - 1U; uint16_t riseTicks = (uint16_t)riseTicks32; uint16_t fallTicks = (uint16_t)fallTicks32; PWM_SetPwmLdok(axis->pwmBase, APP_PwmModuleMask(axis), false); uint16_t ctrl = axis->pwmBase->SM[axis->pwmModule]。CTRL; ctrl &=(uint16_t)(~PWM_CTRL_PRSC_MASK); ctrl |= PWM_CTRL_PRSC(プリスケール); axis->pwmBase->SM[axis->pwmModule]。CTRL = ctrl; axis->pwmBase->SM[axis->pwmModule]。INIT = 0U; axis->pwmBase->SM[axis->pwmModule]。VAL0 = 0U; axis->pwmBase->SM[axis->pwmModule]。VAL1 = ((uint16_t)(periodTicks - 1U); もし(軸>pwmチャンネル== kPWM_PwmA) { axis->pwmBase->SM[axis->pwmModule]。VAL2 = riseTicks; axis->pwmBase->SM[axis->pwmModule]。VAL3 = fallTicks; } そうでなければ (axis->pwmChannel == kPWM_PwmB) { axis->pwmBase->SM[axis->pwmModule]。VAL4 = riseTicks; axis->pwmBase->SM[axis->pwmModule]。VAL5 = fallTicks; } axis->pwmBase->SM[axis->pwmModule]。TCTRL = PWM_TCTRL_OUT_TRIG_EN(axis->outTrigMask); PWM_SetPwmLdok(軸>pwmBase、APP_PwmModuleMask(軸)、真); PWM_SetPwmLdok(軸>pwmBase、APP_PwmModuleMask(軸)、真); axis->pwmConfigValid = true; 軸>キャッシュドHighCnt400M = highCnt400M; axis->cachedLowCnt400M = lowCnt400M; 真を返す; } Re: RT1176 PWM startup failed こんにちは、 @liu626 さん。 設定を分離して、PWM3だけを初期化しても問題が続くかテストするのを手伝ってもらえますか? ご提供いただいた設定を確認し、その動作を再現するために、以下の質問があります。 axis_ctrl_t の定義は何ですか? アプリケーションでHARD_PWM_LOW_START_PHASE_ENABLEとHARD_PWM_STATE_GUARD_ENABLEは有効になっていますか? 以下のアプリ機能はどのような働きをしますか? APP_PWM_Unmap_Selected_Fault APP_PWM_ClearFault_Safe APP_PWM_出力無効化 APP_QTMR_Disable_Low_OFLAG_Output APP_StateGuard_Reset APP_PWM_SelectPrescaler_FromPeriodCnt400M APP_PwmModuleMask よろしくお願いします、 パブロ Re: RT1176 PWM startup failed お返事ありがとうございます。私が使用しているGPIOピンはrt1176のGPIO_EMC_B1_29です。「axis_ctrl_t」はモーターシャフトに関連する定義です。 * PWM出力パルス -> XBAR信号をトリガー -> パルスの立ち下がりエッジがQTMRの外部クロック入力を駆動 -> * QTMR 32ビットカスケードカウンタが1ずつ減少する -> 0に達すると、QTMR比較割り込みがトリガーされる -> 割り込みにより内部的にPWMがオフになる * 同時に、QTMR はハードウェア障害をトリガーし、PWM の物理出力ピンを直接プルダウンします。.id= AXIS_Y、 。名前= "Y", /* シリアルポートのログ記録またはブレークポイントデバッグでY軸を識別するために使用されます */ /* ================= PWM出力リソース割り当て ================= */ .pwmBase= PWM3、/* Y軸はFlexPWM3モジュールを使用します */ .pwmモジュール= kPWM_Module_0, /* PWM3 のサブモジュール 0 を使用します (各 PWM には 0 から 3 までの 4 つのサブモジュールがあります) */ .pwmChannel= kPWM_PwmA, /* サブモジュール0のフェーズAの出力ピンを使用します。これは物理ピンGPIO_EMC_B1_29に対応します。 */ /* ================= 32 ビット QTMR カスケード カウント リソース割り当て ================= */ .tmrBase= TMR3, /* Y軸はQTMR3ペリフェラル(IRQ割り込み番号TMR3_IRQnに対応します)を使用します */ .lowCh= kQTMR_Channel_0, /* 16ビットローカウンタ:TMR3のチャンネル0を使用します */ .highCh= kQTMR_Channel_1,/* 16ビットハイカウンタ:TMR3のチャンネル1を使用 */ /* 👉 .lowCh と .highChこれらはペアになっており、ハードウェアレベルでは自動的に32ビットカウンタに結合されます。 /* ================= ハードウェアカスケードクロックソースの構成 (コアクリティカル) ================= */ .tmrInputsrc=kQTMR_ClockCounter0InputPin, /* チャンネル0のクロックソース:「外部ピン入力0」に設定。 XBAR構成では、PWM3からのパルスの落ち降り縁がXBARを介してTMR3のチャネル0の入力ピンに接続されます。 したがって、PWMでパルスが出力されるたびに、チャンネル0(16ビット)は一度だけ減衰操作を行います。*/ .cascadePcs = 4U, /* 高16ビットチャネル(チャネル1)のクロックソース(PCS)の設定。 i.MX RTのQTMRレジスタにおけるPCS値は以下の通りに対応します。 0-3 = 外部ピン入力; 4 = チャネル0のオーバーフロー/終了イベント; 5 = チャネル1のオーバーフロー/終了イベント; 6 = チャネル2のオーバーフロー/終了イベント; 7 = チャネル3のオーバーフロー/終了イベント。 ここでは4Uとして構成されており、つまり「TMR3のチャネル1」が「TMR3のチャネル0のオーバーフローイベント」を監視することを意味します。 HARD_PWM_LOW_START_PHASE_ENABLE と HARD_PWM_STATE_GUARD_ENABLE が有効になっています。APP_PWM_Unmap_Selected_Fault 機能:現在の軸に対応する故障ピンマッピングを削除します。障害を無効にするには、基となる PWM_SetupFaultDisableMap 関数を呼び出します。その目的は、ハードウェア障害が不要な場合に、偶発的な外部干渉によってPWMがオフになるのを防ぎ、根本的なデバッグプロセスを容易にすることです。 APP_PWM_ClearFault(元のコード関数) 機能:PWMモジュールの障害状態フラグ(axis->pwmBase->FSTS)をクリアします。ハードウェア故障が発生した後は、PWMの再起動を許可する前にまずこのフラグをクリアしなければなりません。 APP_PWM_出力無効化 機能: PWMタイマーを即座に停止し、ピンの出力を強制的に低レベル(PWM_SetPwmForceOutputToZero)にし、出力を有効にします。この目的は、ピンがモーター起動前に浮かんだりデフォルト状態に置かれたりして高レベルを出力し、モーターが不規則に動くのを防ぐことです。 APP_QTMR_Disable_Low_OFLAG_Output 機能:QTMRのOFLAG(ステータスフラグ)出力を無効にし、OFLAGを低レベルに強制的に設定します。XBARハードウェアと連携して、その役割はQTMR出力からPWMフォルトピンへの経路を遮断し、起動前にフォルトが誤ってトリガーされるのを防ぐことです。 APP_StateGuard_Reset 機能:国家警備隊(番犬)のカウンターと旗をクリアします。この関数は、HARD_PWM_STATE_GUARD_ENABLEが有効になっている場合に、長時間パルス変化がない状態やデッドロックが発生した場合に、システムを停止または再起動する前にこれらの保護変数をリセットするために使用されます。 APP_PWM_SelectPrescaler_FromPeriodCnt400M 機能:これは周波数計算の非常に重要な基本機能です。これは、High + Lowの合計400MHzカウント値を受け取り、16ビットPWMレジスタに収まるように設定すべきプリスケーラ(PRSC)とPWM周期(PERIOD)の数を計算します。ご注意ください:計算された周期が65535を超え、かつ除算係数が範囲外の場合、この関数はfalseを返し、モーターの起動に失敗します。 APP_PwmModuleMask 機能:PWMサブモジュールのインデックス番号(例えば、値が0のkPWM_Module_0)を、Nビット左シフトしたビットマスクに変換します。NXPのPWMレジスタの多く(OUTEN、MCTRLなど)はビット単位で制御されます。この関数は、正しいバイナリマスクを生成する役割を担っています。
View full article
如何使用 PeMicro 调试器在 S32K3x4EVB-T172 (S32K344) 上安装 S32K344 A/B 交换 HSE 固件。 您好, 我想在 S32K344 上测试 OTA A/B 替换演示。 为此,我需要在我的 S32K344 芯片上安装 HSE (A/B) 固件,该芯片上没有任何 HSE 固件。 我携带了以下硬件: 1. S32K3x4EVB-T172 (S32K344) 2. PeMicro 调试器。 (注:我没有 Lauterbach TRACE32 工具) 因此,我请求您提供一个正确的步骤,以便借助 S32 设计工作室,使用 PE 微调试器在 s32k344 上安装 HSE (A/B) 固件。 请尽量提供一个完整的操作流程,其中应包含所有必要信息,例如要使用的 DS 版本、RTD、HSE 粉色文件等。 谢谢。 Re: How to install S32K344 A/B swap HSE FW using PeMicro debugger on S32K3x4EVB-T172 (S32K344). HSE DEMO 代码(可随 HSE FW 下载)使用 Lauterbach TRACE32。虽然没有使用不同调试器的专门示例,但有 HSE 示例包: https://www.nxp.com/webapp/Download?colCode=S32K3_HSE_DemoExamples 它基本上是将 HSE DEMO 的功能移植到与调试器无关的代码中。例如,如果您使用 S32K344_HSE_FW_INSTALL,则可以使用任何调试器安装 HSE 固件。
View full article
RT1176 PWM startup failed I am using PWM + fault + QTimer to implement motor pulse control, but the PWM3 submodule 0 PWM_A channel occasionally fails to start, where after the first high level it remains constant and subsequent pulses do not appear.After the inspection, it was found that the "run" bit of the pwm was not correctly set. Even though repeated startup operations were added in the program later, this anomaly still occurred. Re: RT1176 PWM startup failed Hi @liu626, Are you using a custom board or an EVK? If you are using the EVK, did you make any rework to it? Could you share the configuration you are using for PWM3? Are you using an example as a reference? If so, which one? If you try to replicate the issue using a project with only PWM3, does the problem persist? Does this only happen with PWM3 submodule 0 PWM_A channel? Has this occurred on other PWM modules or submodules? Is there any other task or interrupt that manipulates PWM3 registers and could affect or overwrite the run bit? Best Regards, Pablo Re: RT1176 PWM startup failed hi,I used a custom circuit board. I didn't refer to any examples. This was a problem that was discovered during the official development of the project. I configured six PWM channels for pulse control. Only this channel had problems, while no such issue occurred on the other sub-modules. I checked and found that only this channel was using the PWM3 module. No other interfering factors were detected. Below is my configuration. static axis_ctrl_t g_axes[AXIS_NUM] = { { .id = AXIS_X1, .name = "X1", .pwmBase = PWM1, .pwmModule = kPWM_Module_0, .pwmChannel = kPWM_PwmA, .tmrBase = TMR3, .lowCh = kQTMR_Channel_2, .highCh = kQTMR_Channel_3, .tmrInputsrc=kQTMR_ClockCounter2InputPin, .cascadePcs = 6U, .faultNum = 0U, .hwExactSupported = true, .outTrigMask = kPWM_ValueRegisterMask_3, }, { .id = AXIS_X2, .name = "X2", .pwmBase = PWM2, .pwmModule = kPWM_Module_0, .pwmChannel = kPWM_PwmA, .tmrBase = TMR2, .lowCh = kQTMR_Channel_0, .highCh = kQTMR_Channel_1, .tmrInputsrc=kQTMR_ClockCounter0InputPin, .cascadePcs = 4U, .faultNum = 0U, .hwExactSupported = true, .outTrigMask = kPWM_ValueRegisterMask_3, }, { .id = AXIS_Y, .name = "Y", .pwmBase = PWM3, .pwmModule = kPWM_Module_0, .pwmChannel = kPWM_PwmA, .tmrBase = TMR3, .lowCh = kQTMR_Channel_0, .highCh = kQTMR_Channel_1, .tmrInputsrc=kQTMR_ClockCounter0InputPin, .cascadePcs = 4U, .faultNum = 0U, .hwExactSupported = true, .outTrigMask = kPWM_ValueRegisterMask_3, }, { .id = AXIS_Z, .name = "Z", .pwmBase = PWM4, .pwmModule = kPWM_Module_0, .pwmChannel = kPWM_PwmA, .tmrBase = TMR1, .lowCh = kQTMR_Channel_0, .highCh = kQTMR_Channel_1, .tmrInputsrc=kQTMR_ClockCounter0InputPin, .cascadePcs = 4U, .faultNum = 0U, .hwExactSupported = true, .outTrigMask = kPWM_ValueRegisterMask_3, }, { .id = AXIS_EX1, .name = "EX1", .pwmBase = PWM1, .pwmModule = kPWM_Module_1, .pwmChannel = kPWM_PwmA, .tmrBase = TMR1, .lowCh = kQTMR_Channel_2, .highCh = kQTMR_Channel_3, .tmrInputsrc=kQTMR_ClockCounter2InputPin, .cascadePcs = 6U, .faultNum = 1U, .hwExactSupported = true, .outTrigMask = kPWM_ValueRegisterMask_3, }, { .id = AXIS_EX2, .name = "EX2", .pwmBase = PWM2, .pwmModule = kPWM_Module_1, .pwmChannel = kPWM_PwmA, .tmrBase = TMR2, .lowCh = kQTMR_Channel_2, .highCh = kQTMR_Channel_3, .tmrInputsrc=kQTMR_ClockCounter2InputPin, .cascadePcs = 6U, .faultNum = 1U, .hwExactSupported = true, .outTrigMask = kPWM_ValueRegisterMask_3, }, };static void APP_Init_PWM_QTMR(void) { pwm_config_t pwmConfig; pwm_fault_param_t faultConfig; qtmr_config_t qtmrConfig; PWM_GetDefaultConfig(&pwmConfig); pwmConfig.pairOperation = kPWM_Independent; pwmConfig.reloadLogic = kPWM_ReloadImmediate; PWM_FaultDefaultConfig(&faultConfig); faultConfig.faultLevel = true; faultConfig.enableCombinationalPath = false; faultConfig.faultClearingMode = kPWM_ManualSafety; faultConfig.recoverMode = kPWM_NoRecovery; QTMR_GetDefaultConfig(&qtmrConfig); CLOCK_EnableClock(kCLOCK_Qtimer1); CLOCK_EnableClock(kCLOCK_Qtimer2); CLOCK_EnableClock(kCLOCK_Qtimer3); PWM_StopTimer(PWM1, 0x0FU); PWM_StopTimer(PWM2, 0x0FU); PWM_StopTimer(PWM3, 0x0FU); PWM_StopTimer(PWM4, 0x0FU); pwm_fault_input_filter_param_t faultFilter; faultFilter.faultFilterPeriod = 255U; faultFilter.faultFilterCount = 7U; faultFilter.faultGlitchStretch = false; /* 记录每个 PWM 实例上已配置的 fault channel,避免重复设置 */ uint16_t pwm1FaultDone = 0U, pwm2FaultDone = 0U, pwm3FaultDone = 0U, pwm4FaultDone = 0U; for (uint8_t i = 0U; i < AXIS_NUM; i++) { axis_ctrl_t *ax = &g_axes[i]; PWM_Init(ax->pwmBase, ax->pwmModule, &pwmConfig); PWM_SetupFaults(ax->pwmBase, (pwm_fault_input_t)ax->faultNum, &faultConfig); /* 故障滤波(每个 PWM 实例的每个 fault channel 只设一次) */ { uint16_t *faultDone; if (ax->pwmBase == PWM1) faultDone = &pwm1FaultDone; else if (ax->pwmBase == PWM2) faultDone = &pwm2FaultDone; else if (ax->pwmBase == PWM3) faultDone = &pwm3FaultDone; else faultDone = &pwm4FaultDone; uint16_t faultBit = (uint16_t)(1U << ax->faultNum); if ((*faultDone & faultBit) == 0U) { PWM_SetupFaultInputFilterExt(ax->pwmBase, (pwm_fault_channels_t)ax->faultNum, &faultFilter); *faultDone |= faultBit; } } /* Fault 时输出低电平 */ ax->pwmBase->SM[ax->pwmModule].OCTRL &= ~(PWM_OCTRL_PWMAFS_MASK | PWM_OCTRL_PWMBFS_MASK); APP_PWM_Unmap_Selected_Fault(ax); APP_PWM_ClearFault_Safe(ax); ax->pwmBase->SM[ax->pwmModule].INIT = 0U; ax->pwmBase->SM[ax->pwmModule].VAL0 = 0U; ax->pwmBase->SM[ax->pwmModule].VAL1 = 1U; ax->pwmBase->SM[ax->pwmModule].VAL2 = 0U; ax->pwmBase->SM[ax->pwmModule].VAL3 = 0U; ax->pwmBase->SM[ax->pwmModule].VAL4 = 0U; ax->pwmBase->SM[ax->pwmModule].VAL5 = 0U; ax->pwmBase->SM[ax->pwmModule].TCTRL = PWM_TCTRL_OUT_TRIG_EN(ax->outTrigMask); APP_PWM_Disable_Output(ax); if (ax->hwExactSupported) { qtmrConfig.primarySource = ax->tmrInputSrc; QTMR_Init(ax->tmrBase, ax->lowCh, &qtmrConfig); QTMR_Init(ax->tmrBase, ax->highCh, &qtmrConfig); ax->tmrBase->CHANNEL[ax->lowCh].CTRL = TMR_CTRL_CM(kQTMR_PriSrcRiseEdge) | TMR_CTRL_PCS(ax->tmrInputSrc); ax->tmrBase->CHANNEL[ax->highCh].CTRL = TMR_CTRL_CM(kQTMR_CascadeCount) | TMR_CTRL_PCS(ax->cascadePcs); APP_QTMR_Disable_Low_OFLAG_Output(ax); QTMR_DisableInterrupts(ax->tmrBase, ax->lowCh, 0xFFU); QTMR_DisableInterrupts(ax->tmrBase, ax->highCh, 0xFFU); QTMR_ClearStatusFlags(ax->tmrBase, ax->lowCh, 0xFFU); QTMR_ClearStatusFlags(ax->tmrBase, ax->highCh, 0xFFU); } ax->phase = kAxisIdle; ax->armed = false; ax->running = false; ax->done = true; #if HARD_PWM_STATE_GUARD_ENABLE APP_StateGuard_Reset(ax); #endif } /* 使能 QTMR 中断 */ NVIC_SetPriority(TMR1_IRQn, 2U); NVIC_SetPriority(TMR2_IRQn, 2U); NVIC_SetPriority(TMR3_IRQn, 2U); EnableIRQ(TMR1_IRQn); EnableIRQ(TMR2_IRQn); EnableIRQ(TMR3_IRQn); }static bool APP_PWM_Config_Pulse(axis_ctrl_t *axis, uint32_t highCnt400M, uint32_t lowCnt400M) { pwm_clock_prescale_t prescale; uint16_t periodTicks; uint32_t totalCnt400M = highCnt400M + lowCnt400M; if ((axis == NULL) || (totalCnt400M == 0U)) return false; if (!APP_PWM_SelectPrescaler_FromPeriodCnt400M(totalCnt400M, &prescale, &periodTicks)) return false; uint32_t highTicks32 = (uint32_t)(((uint64_t)periodTicks * (uint64_t)highCnt400M + ((uint64_t)totalCnt400M / 2ULL)) / (uint64_t)totalCnt400M); if (highTicks32 == 0U) highTicks32 = 1U; if (highTicks32 >= periodTicks) highTicks32 = (uint32_t)periodTicks - 1U; uint32_t riseTicks32 = 0U; uint32_t fallTicks32 = highTicks32; #if HARD_PWM_LOW_START_PHASE_ENABLE uint32_t lowTicks32 = (uint32_t)periodTicks - highTicks32; if (lowTicks32 >= (2U * HARD_PWM_LOW_START_PHASE_MIN_TICKS)) { uint32_t desiredLeadCnt400M = highCnt400M; uint32_t minLeadCnt400M = (uint32_t)HARD_PWM_LOW_START_PHASE_MIN_US * 400U; if (desiredLeadCnt400M < minLeadCnt400M) desiredLeadCnt400M = minLeadCnt400M; uint32_t desiredLeadTicks32 = (uint32_t)(((uint64_t)periodTicks * (uint64_t)desiredLeadCnt400M + ((uint64_t)totalCnt400M / 2ULL)) / (uint64_t)totalCnt400M); if (desiredLeadTicks32 < HARD_PWM_LOW_START_PHASE_MIN_TICKS) desiredLeadTicks32 = HARD_PWM_LOW_START_PHASE_MIN_TICKS; uint32_t maxRiseByHalfTicks32 = lowTicks32 / 2U; uint32_t postGuardTicks32 = (uint32_t)(((uint64_t)periodTicks * (uint64_t)(HARD_PWM_VAL3_POST_LOW_GUARD_US * 400U) + ((uint64_t)totalCnt400M / 2ULL)) / (uint64_t)totalCnt400M); if (postGuardTicks32 < HARD_PWM_VAL3_POST_LOW_GUARD_MIN_TICKS) postGuardTicks32 = HARD_PWM_VAL3_POST_LOW_GUARD_MIN_TICKS; uint32_t maxRiseByPostGuardTicks32 = (lowTicks32 > postGuardTicks32) ? (lowTicks32 - postGuardTicks32) : 0U; uint32_t selectedRiseTicks32; if (maxRiseByHalfTicks32 >= desiredLeadTicks32) { selectedRiseTicks32 = desiredLeadTicks32; if (selectedRiseTicks32 > maxRiseByHalfTicks32) selectedRiseTicks32 = maxRiseByHalfTicks32; } else if (maxRiseByPostGuardTicks32 >= desiredLeadTicks32) { selectedRiseTicks32 = desiredLeadTicks32; if (selectedRiseTicks32 > maxRiseByPostGuardTicks32) selectedRiseTicks32 = maxRiseByPostGuardTicks32; } else { selectedRiseTicks32 = maxRiseByPostGuardTicks32; } if (selectedRiseTicks32 >= HARD_PWM_LOW_START_PHASE_MIN_TICKS) { riseTicks32 = selectedRiseTicks32; fallTicks32 = riseTicks32 + highTicks32; } } #endif if (fallTicks32 >= (uint32_t)periodTicks) fallTicks32 = (uint32_t)periodTicks - 1U; uint16_t riseTicks = (uint16_t)riseTicks32; uint16_t fallTicks = (uint16_t)fallTicks32; PWM_SetPwmLdok(axis->pwmBase, APP_PwmModuleMask(axis), false); uint16_t ctrl = axis->pwmBase->SM[axis->pwmModule].CTRL; ctrl &= (uint16_t)(~PWM_CTRL_PRSC_MASK); ctrl |= PWM_CTRL_PRSC(prescale); axis->pwmBase->SM[axis->pwmModule].CTRL = ctrl; axis->pwmBase->SM[axis->pwmModule].INIT = 0U; axis->pwmBase->SM[axis->pwmModule].VAL0 = 0U; axis->pwmBase->SM[axis->pwmModule].VAL1 = (uint16_t)(periodTicks - 1U); if (axis->pwmChannel == kPWM_PwmA) { axis->pwmBase->SM[axis->pwmModule].VAL2 = riseTicks; axis->pwmBase->SM[axis->pwmModule].VAL3 = fallTicks; } else if (axis->pwmChannel == kPWM_PwmB) { axis->pwmBase->SM[axis->pwmModule].VAL4 = riseTicks; axis->pwmBase->SM[axis->pwmModule].VAL5 = fallTicks; } axis->pwmBase->SM[axis->pwmModule].TCTRL = PWM_TCTRL_OUT_TRIG_EN(axis->outTrigMask); PWM_SetPwmLdok(axis->pwmBase, APP_PwmModuleMask(axis), true); PWM_SetPwmLdok(axis->pwmBase, APP_PwmModuleMask(axis), true); axis->pwmConfigValid = true; axis->cachedHighCnt400M = highCnt400M; axis->cachedLowCnt400M = lowCnt400M; return true; } Re: RT1176 PWM startup failed Hi @liu626, Could you help me isolate the configuration and test whether the issue persists when only PWM3 is initialized? After reviewing the configuration, you shared and in order to try to replicate the behavior, I have the following questions: What is the definition of axis_ctrl_t? Are HARD_PWM_LOW_START_PHASE_ENABLE and HARD_PWM_STATE_GUARD_ENABLE enabled in your application? What do the following APP functions do? APP_PWM_Unmap_Selected_Fault APP_PWM_ClearFault_Safe APP_PWM_Disable_Output APP_QTMR_Disable_Low_OFLAG_Output APP_StateGuard_Reset APP_PWM_SelectPrescaler_FromPeriodCnt400M APP_PwmModuleMask Best Regards, Pablo Re: RT1176 PWM startup failed Thank you for your reply. The GPIO pin I'm using is GPIO_EMC_B1_29 of the rt1176."axis_ctrl_t" is the definition related to the motor shaft. * PWM output pulse -> Trigger XBAR signal -> Falling edge of pulse drives the external clock input of QTMR -> * QTMR 32-bit cascaded counter decrements by 1 -> When it reaches 0, triggers QTMR comparison interrupt -> Interrupt internally turns off PWM * At the same time, QTMR triggers the hardware Fault, directly pulling down the physical output pin of PWM. .id = AXIS_Y, .name = "Y", /* Used for serial port logging or breakpoint debugging to identify the Y-axis */ /* ================= PWM Output Resource Allocation ================= */ .pwmBase = PWM3, /* The Y-axis uses the FlexPWM3 module */ .pwmModule = kPWM_Module_0, /* Uses the sub-module 0 of PWM3 (each PWM has 4 sub-modules from 0 to 3) */ .pwmChannel = kPWM_PwmA, /* Uses the output pin of phase A of sub-module 0, corresponding to the physical pin GPIO_EMC_B1_29 */ /* ================= 32-bit QTMR cascaded count resource allocation ================= */ .tmrBase = TMR3, /* The Y-axis uses the QTMR3 peripheral (corresponding to IRQ interrupt number TMR3_IRQn) */ .lowCh = kQTMR_Channel_0, /* 16-bit low counter: uses channel 0 of TMR3 */ .highCh = kQTMR_Channel_1,/* 16-bit high counter: uses channel 1 of TMR3 */ /* 👉 .lowCh and .highCh are paired, and in the hardware level, they are automatically combined into a 32-bit counter */ /* ================= Configuration of Hardware Cascaded Clock Sources (Core Critical) ================= */ .tmrInputsrc=kQTMR_ClockCounter0InputPin, /* The clock source for Channel 0: Set to "External Pin Input 0". In the XBAR configuration, the falling edge of the pulse from PWM3 is connected to the input pin of Channel 0 of TMR3 through the XBAR. Therefore, every time a pulse is output by PWM, Channel 0 (16-bit) will perform a decrement operation once. */ .cascadePcs = 4U, /* Configuration of the clock source (PCS) for the high 16-bit channel (Channel 1). In the QTMR register of i.MX RT, the PCS value corresponds as follows: 0-3 = External pin input; 4 = Overflow/Termination event of Channel 0; 5 = Overflow/Termination event of Channel 1; 6 = Overflow/Termination event of Channel 2; 7 = Overflow/Termination event of Channel 3. Here, it is configured as 4U, meaning: Let "Channel 1 of TMR3" monitor the "Overflow event of Channel 0 of TMR3". HARD_PWM_LOW_START_PHASE_ENABLE and HARD_PWM_STATE_GUARD_ENABLE have been enabled. APP_PWM_Unmap_Selected_Fault Function: Remove the Fault pin mapping corresponding to the current axis. Call the underlying PWM_SetupFaultDisableMap function to disable the Fault. The purpose is: When the hardware Fault is not needed, prevent accidental external interference from causing the PWM to be turned off, facilitating the underlying debugging process. APP_PWM_ClearFault (original code function) Function: Clear the Fault status flag (axis->pwmBase->FSTS) of the PWM module. After triggering a hardware Fault, you must first clear this flag before the PWM can be allowed to restart. APP_PWM_Disable_Output Function: Immediately stop the PWM timer, force the pin to output a low level (PWM_SetPwmForceOutputToZero), and enable the output. Its purpose is to ensure that the pin does not output a high level due to being left floating or in the default state before the motor starts, which could cause the motor to move erratically. APP_QTMR_Disable_Low_OFLAG_Output Function: Disable the OFLAG (status flag) output of QTMR and force the OFLAG to be at a low level. In conjunction with the XBAR hardware, its role is to cut off the path from the QTMR output to the PWM Fault pin, preventing accidental triggering of Fault before startup. APP_StateGuard_Reset Function: Clears the counters and flags of the state guard (watchdog). This function is used to reset these protection variables before stopping or restarting the system if it encounters a long period of no pulse change or a deadlock when HARD_PWM_STATE_GUARD_ENABLE is enabled. APP_PWM_SelectPrescaler_FromPeriodCnt400M Function: This is a very core underlying frequency calculation function. It receives the total 400MHz count value of High + Low, and calculates how many prescalers (PRSC) and PWM periods (PERIOD) should be set in order to fit into the 16-bit PWM register. Please note: If the calculated period exceeds 65535 and the division coefficient is out of range, this function will return false, causing the motor to fail to start. APP_PwmModuleMask Function: Convert the index number of the PWM sub-module (for example, kPWM_Module_0 with the value 0) into a bit mask shifted left by N bits. Many of NXP's PWM registers (such as OUTEN, MCTRL) are controlled bit by bit. This function is responsible for generating the correct binary mask.
View full article
RT1176 PWM启动失败 我使用PWM+故障+QTimer来实现电机脉冲控制,但PWM3子模块0的PWM_A通道偶尔无法启动,在第一个高电平之后就一直保持高电平,后续脉冲不再出现。检查后发现,PWM的“运行”位没有正确设置。即使后来在程序中添加了重复启动操作,这种异常情况仍然发生。 Re: RT1176 PWM startup failed 你好@liu626 , 你用的是定制板还是EVK板?如果你使用的是 EVK,你对它进行过任何修改吗? 能否分享一下您使用的PWM3配置? 您是使用示例作为参考吗?如果是,是哪一个? 如果尝试使用仅包含 PWM3 的项目来重现该问题,问题是否仍然存在? 这种情况是否只发生在 PWM3 子模块 0 PWM_A 通道上?其他PWM模块或子模块是否也出现过这种情况? 是否还有其他任务或中断会操作 PWM3 寄存器,从而影响或覆盖运行位? 此致, 巴勃罗 Re: RT1176 PWM startup failed 您好,我使用的是定制电路板。我没有举任何例子。这是在项目正式开发过程中发现的问题。我配置了六个PWM通道用于脉冲控制。只有这个通道出现了问题,其他子模块都没有出现此类问题。我检查后发现,只有这个通道使用了 PWM3 模块。未检测到其他干扰因素。以下是我的配置。 静态 axis_ctrl_t g_axes[AXIS_NUM] = { { 。ID= AXIS_X1,.name= "X1", .pwmBase= PWM1,.pwmModule= kPWM_Module_0,.pwmChannel= kPWM_PwmA, .tmrBase= TMR3,.lowCh= kQTMR_Channel_2,.highCh= kQTMR_Channel_3, .tmrInputsrc=kQTMR_ClockCounter2InputPin,.cascadePcs= 6U, 故障编号= 0U,.hwExactSupported= true,.outTrigMask= kPWM_ValueRegisterMask_3, }, { 。ID= AXIS_X2,.name= "X2", .pwmBase= PWM2,.pwmModule= kPWM_Module_0,.pwmChannel= kPWM_PwmA, .tmrBase= TMR2,.lowCh= kQTMR_Channel_0, .highCh= kQTMR_Channel_1, .tmrInputsrc=kQTMR_ClockCounter0InputPin,.cascadePcs= 4U, 故障编号= 0U,.hwExactSupported= true,.outTrigMask= kPWM_ValueRegisterMask_3, }, { 。ID= AXIS_Y,.name= "Y", .pwmBase= PWM3,.pwmModule= kPWM_Module_0,.pwmChannel= kPWM_PwmA, .tmrBase= TMR3,.lowCh= kQTMR_Channel_0, .highCh= kQTMR_Channel_1, .tmrInputsrc=kQTMR_ClockCounter0InputPin,.cascadePcs= 4U, 故障编号= 0U,.hwExactSupported= true,.outTrigMask= kPWM_ValueRegisterMask_3, }, { 。ID= AXIS_Z,.name= "Z", .pwmBase= PWM4,.pwmModule= kPWM_Module_0,.pwmChannel= kPWM_PwmA, .tmrBase= TMR1,.lowCh= kQTMR_Channel_0, .highCh= kQTMR_Channel_1, .tmrInputsrc=kQTMR_ClockCounter0InputPin,.cascadePcs= 4U, 故障编号= 0U,.hwExactSupported= true,.outTrigMask= kPWM_ValueRegisterMask_3, }, { 。ID= AXIS_EX1,.name= "EX1", .pwmBase= PWM1,.pwmModule= kPWM_Module_1,.pwmChannel= kPWM_PwmA, .tmrBase= TMR1,.lowCh= kQTMR_Channel_2,.highCh= kQTMR_Channel_3, .tmrInputsrc=kQTMR_ClockCounter2InputPin,.cascadePcs= 6U, 故障编号= 1U,.hwExactSupported= true,.outTrigMask= kPWM_ValueRegisterMask_3, }, { 。ID= AXIS_EX2,.name= "EX2", .pwmBase= PWM2,.pwmModule= kPWM_Module_1,.pwmChannel= kPWM_PwmA, .tmrBase= TMR2,.lowCh= kQTMR_Channel_2,.highCh= kQTMR_Channel_3, .tmrInputsrc=kQTMR_ClockCounter2InputPin,.cascadePcs= 6U, 故障编号= 1U,.hwExactSupported= true,.outTrigMask= kPWM_ValueRegisterMask_3, }, };static void APP_Init_PWM_QTMR(void) { pwm_config_t pwmConfig; pwm_fault_param_t faultConfig; qtmr_config_t qtmrConfig; PWM_GetDefaultConfig(&pwmConfig); pwmConfig.pairOperation= kPWM_Independent; pwmConfig.reloadLogic = kPWM_ReloadImmediate; PWM_FaultDefaultConfig(&faultConfig); faultConfig.faultLevel = true; faultConfig.enableCombinationPath= false; faultConfig.faultClearingMode= kPWM_手动安全; faultConfig.recoverMode = kPWM_NoRecovery; QTMR_GetDefaultConfig(&qtmrConfig); CLOCK_EnableClock(kCLOCK_Qtimer1); CLOCK_EnableClock(kCLOCK_Qtimer2); CLOCK_EnableClock(kCLOCK_Qtimer3); PWM_StopTimer(PWM1, 0x0FU); PWM_StopTimer(PWM2, 0x0FU); PWM_StopTimer(PWM3, 0x0FU); PWM_StopTimer(PWM4, 0x0FU); pwm_fault_input_filter_param_t faultFilter; 故障过滤器.故障过滤器周期= 255U; faultFilter.faultFilterCount= 7U; faultFilter.faultGlitchStretch= false; /* 记录每个PWM实例上已配置的故障通道,避免重复设置 */ uint16_t pwm1FaultDone = 0U, pwm2FaultDone = 0U, pwm3FaultDone = 0U, pwm4FaultDone = 0U; for (uint8_t i = 0U; i < AXIS_NUM; i++) { axis_ctrl_t *ax = &g_axes[i]; PWM_Init(ax->pwmBase, ax->pwmModule, &pwmConfig); PWM_SetupFaults(ax->pwmBase, (pwm_fault_input_t)ax->faultNum, &faultConfig); /* 故障提示(每个 PWM 实例的每个故障通道只设置一次) */ { uint16_t *faultDone; 如果 (ax->pwmBase == PWM1) faultDone = &pwm1FaultDone; 否则如果 (ax->pwmBase == PWM2) faultDone = &pwm2FaultDone; 否则如果 (ax->pwmBase == PWM3) faultDone = &pwm3FaultDone; 否则 faultDone = &pwm4FaultDone; uint16_t faultBit = (uint16_t)(1U << ax->faultNum); 如果 ((*faultDone & faultBit) == 0U) { PWM_SetupFaultInputFilterExt(ax->pwmBase, (pwm_fault_channels_t)ax->faultNum, &faultFilter); *faultDone |= faultBit; } } /* 故障时输出低电平 */ ax->pwmBase->SM[ax->pwmModule].OCTRL &= ~(PWM_OCTRL_PWMAFS_MASK | PWM_OCTRL_PWMBFS_MASK); APP_PWM_Unmap_Selected_Fault(ax); APP_PWM_ClearFault_Safe(ax); ax->pwmBase->SM[ax->pwmModule].INIT = 0U; ax->pwmBase->SM[ax->pwmModule].VAL0 = 0U; ax->pwmBase->SM[ax->pwmModule].VAL1 = 1U; ax->pwmBase->SM[ax->pwmModule].VAL2 = 0U; ax->pwmBase->SM[ax->pwmModule].VAL3 = 0U; ax->pwmBase->SM[ax->pwmModule].VAL4 = 0U; ax->pwmBase->SM[ax->pwmModule].VAL5 = 0U; ax->pwmBase->SM[ax->pwmModule].TCTRL = PWM_TCTRL_OUT_TRIG_EN(ax->outTrigMask); APP_PWM_Disable_Output(ax); 如果 (ax->hwExactSupported) { qtmrConfig.primarySource= ax->tmrInputSrc; QTMR_Init(ax->tmrBase, ax->lowCh, &qtmrConfig); QTMR_Init(ax->tmrBase, ax->highCh, &qtmrConfig); ax->tmrBase->CHANNEL[ax->lowCh].CTRL = TMR_CTRL_CM(kQTMR_PriSrcRiseEdge) | TMR_CTRL_PCS(ax->tmrInputSrc); ax->tmrBase->CHANNEL[ax->highCh].CTRL = TMR_CTRL_CM(kQTMR_CascadeCount) | TMR_CTRL_PCS(ax->cascadePcs); APP_QTMR_Disable_Low_OFLAG_Output(ax); QTMR_DisableInterrupts(ax->tmrBase, ax->lowCh, 0xFFU); QTMR_DisableInterrupts(ax->tmrBase, ax->highCh, 0xFFU); QTMR_ClearStatusFlags(ax->tmrBase, ax->lowCh, 0xFFU); QTMR_ClearStatusFlags(ax->tmrBase, ax->highCh, 0xFFU); } ax->phase = kAxisIdle; ax->armed = false; ax->running = false; ax->done = true; #if HARD_PWM_STATE_GUARD_ENABLE APP_StateGuard_Reset(ax); #endif } /* 使能 QTMR 中断 */ NVIC_SetPriority(TMR1_IRQn, 2U); NVIC_SetPriority(TMR2_IRQn, 2U); NVIC_SetPriority(TMR3_IRQn, 2U); 启用IRQ(TMR1_IRQn); 启用IRQ(TMR2_IRQn); 启用IRQ(TMR3_IRQn); }static bool APP_PWM_Config_Pulse(axis_ctrl_t *axis, uint32_t highCnt400M, uint32_t lowCnt400M) { pwm_clock_prescale_t 预分频; uint16_t periodTicks; uint32_t totalCnt400M = highCnt400M + lowCnt400M; 如果 ((axis == NULL) || (totalCnt400M == 0U)) 返回 false; 如果 (!APP_PWM_SelectPrescaler_FromPeriodCnt400M(totalCnt400M, &prescale, &periodTicks)) 返回 false; uint32_t highTicks32 = (uint32_t)(((uint64_t)periodTicks * (uint64_t)highCnt400M + ((uint64_t)totalCnt400M / 2ULL)) / (uint64_t)totalCnt400M); 如果 (highTicks32 == 0U) highTicks32 = 1U; 如果 (highTicks32 >= periodTicks) highTicks32 = (uint32_t)periodTicks - 1U; uint32_t riseTicks32 = 0U; uint32_t fallTicks32 = highTicks32; #if HARD_PWM_LOW_START_PHASE_ENABLE uint32_t lowTicks32 = (uint32_t)periodTicks - highTicks32; 如果 (lowTicks32 >= (2U * HARD_PWM_LOW_START_PHASE_MIN_TICKS)) { uint32_t desiredLeadCnt400M = highCnt400M; uint32_t minLeadCnt400M = (uint32_t)HARD_PWM_LOW_START_PHASE_MIN_US * 400U; 如果 (desiredLeadCnt400M < minLeadCnt400M) desiredLeadCnt400M = minLeadCnt400M; uint32_t desiredLeadTicks32 = (uint32_t)(((uint64_t)periodTicks * (uint64_t)desiredLeadCnt400M + ((uint64_t)totalCnt400M / 2ULL)) / (uint64_t)totalCnt400M); 如果 (desiredLeadTicks32 < HARD_PWM_LOW_START_PHASE_MIN_TICKS) desiredLeadTicks32 = HARD_PWM_LOW_START_PHASE_MIN_TICKS; uint32_t maxRiseByHalfTicks32 = lowTicks32 / 2U; uint32_t postGuardTicks32 = (uint32_t)(((uint64_t)periodTicks * (uint64_t)(HARD_PWM_VAL3_POST_LOW_GUARD_US * 400U) + ((uint64_t)totalCnt400M / 2ULL)) / (uint64_t)totalCnt400M); 如果 (postGuardTicks32 < HARD_PWM_VAL3_POST_LOW_GUARD_MIN_TICKS) postGuardTicks32 = HARD_PWM_VAL3_POST_LOW_GUARD_MIN_TICKS; uint32_t maxRiseByPostGuardTicks32 = (lowTicks32 > postGuardTicks32) ? (lowTicks32 - postGuardTicks32):0U; uint32_t selectedRiseTicks32; 如果 (maxRiseByHalfTicks32 >= desiredLeadTicks32) { selectedRiseTicks32 = desiredLeadTicks32; 如果 (selectedRiseTicks32 > maxRiseByHalfTicks32) selectedRiseTicks32 = maxRiseByHalfTicks32; } 否则如果(maxRiseByPostGuardTicks32 >= desiredLeadTicks32) { selectedRiseTicks32 = desiredLeadTicks32; 如果 (selectedRiseTicks32 > maxRiseByPostGuardTicks32) selectedRiseTicks32 = maxRiseByPostGuardTicks32; } 别的 { selectedRiseTicks32 = maxRiseByPostGuardTicks32; } 如果 (selectedRiseTicks32 >= HARD_PWM_LOW_START_PHASE_MIN_TICKS) { riseTicks32 = selectedRiseTicks32; fallTicks32 = riseTicks32 + highTicks32; } } #endif 如果 (fallTicks32 >= (uint32_t)periodTicks) fallTicks32 = (uint32_t)periodTicks - 1U; uint16_t riseTicks = (uint16_t)riseTicks32; uint16_t fallTicks = (uint16_t)fallTicks32; PWM_SetPwmLdok(axis->pwmBase, APP_PwmModuleMask(axis), false); uint16_t ctrl = axis->pwmBase->SM[axis->pwmModule].CTRL; ctrl &= (uint16_t)(~PWM_CTRL_PRSC_MASK); ctrl |= PWM_CTRL_PRSC(预分频); axis->pwmBase->SM[axis->pwmModule].CTRL = ctrl; axis->pwmBase->SM[axis->pwmModule].INIT = 0U; axis->pwmBase->SM[axis->pwmModule].VAL0 = 0U; axis->pwmBase->SM[axis->pwmModule].VAL1 = (uint16_t)(periodTicks - 1U); 如果 (axis->pwmChannel == kPWM_PwmA) { axis->pwmBase->SM[axis->pwmModule].VAL2 = riseTicks; axis->pwmBase->SM[axis->pwmModule].VAL3 = fallTicks; } 否则如果 (axis->pwmChannel == kPWM_PwmB) { axis->pwmBase->SM[axis->pwmModule]。VAL4 = riseTicks; axis->pwmBase->SM[axis->pwmModule].VAL5 = fallTicks; } axis->pwmBase->SM[axis->pwmModule].TCTRL = PWM_TCTRL_OUT_TRIG_EN(axis->outTrigMask); PWM_SetPwmLdok(axis->pwmBase, APP_PwmModuleMask(axis), true); PWM_SetPwmLdok(axis->pwmBase, APP_PwmModuleMask(axis), true); axis->pwmConfigValid = true; axis->cachedHighCnt400M = highCnt400M; axis->cachedLowCnt400M = lowCnt400M; 返回 true; } Re: RT1176 PWM startup failed 你好@liu626 , 您能否帮我找出配置问题,并测试一下仅初始化 PWM3 时问题是否仍然存在? 在查看了您分享的配置后,为了尝试重现该行为,我有以下问题: axis_ctrl_t 的定义是什么? 您的应用程序中是否启用了 HARD_PWM_LOW_START_PHASE_ENABLE 和 HARD_PWM_STATE_GUARD_ENABLE? 以下APP功能是做什么用的? APP_PWM_Unmap_Selected_Fault APP_PWM_ClearFault_Safe APP_PWM_禁用输出 APP_QTMR_Disable_Low_OFLAG_Output APP_StateGuard_Reset APP_PWM_SelectPrescaler_FromPeriodCnt400M APP_PwmModuleMask 此致, 巴勃罗 Re: RT1176 PWM startup failed 感谢你的回复。我使用的 GPIO 引脚是 rt1176 的 GPIO_EMC_B1_29。“axis_ctrl_t”是与电机轴相关的定义。 * PWM 输出脉冲 -> 触发 XBAR 信号 -> 脉冲下降沿驱动 QTMR 的外部时钟输入 -> * QTMR 32 位级联计数器递减 1 -> 当计数器达到 0 时,触发 QTMR 比较中断 -> 中断内部关闭 PWM * 同时,QTMR 触发硬件故障,直接拉低 PWM 的物理输出引脚。。ID= AXIS_Y, 。姓名= "Y", /* 用于串口日志记录或断点调试,以识别 Y 轴 */ /* ================= PWM 输出资源分配 ================= */ .pwmBase= PWM3, /* Y轴使用FlexPWM3模块 */ .pwm模块= kPWM_Module_0, /* 使用 PWM3 的子模块 0(每个 PWM 有 4 个子模块,编号从 0 到 3) */ .pwm通道= kPWM_PwmA, /* 使用子模块 0 的 A 相输出引脚,对应于物理引脚 GPIO_EMC_B1_29 */ /* ================= 32 位 QTMR 级联计数资源分配 ================= */ .tmrBase= TMR3, /* Y轴使用QTMR3外设(对应于IRQ中断号TMR3_IRQn) */ 低= kQTMR_Channel_0, /* 16 位低计数器:使用 TMR3 的通道 0 */ .highCh= kQTMR_Channel_1,/* 16 位高位计数器:使用 TMR3 的通道 1 */ /* 👉 .lowCh 和 .highCh它们成对出现,在硬件层面上,它们会自动组合成一个 32 位计数器。 /* ================= 硬件级联时钟源配置(核心关键) ================= */ .tmrInputsrc=kQTMR_ClockCounter0InputPin, /* 通道 0 的时钟源:设置为“外部引脚输入 0”。 在 XBAR 配置中,PWM3 脉冲的下降沿通过 XBAR 连接到 TMR3 通道 0 的输入引脚。 因此,每次 PWM 输出脉冲时,通道 0(16 位)将执行一次减量操作。*/ .cascadePcs = 4U, /* 高 16 位通道(通道 1)的时钟源 (PCS) 配置。 在 i.MX RT 的 QTMR 寄存器中,PCS 值对应如下: 0-3 = 外部引脚输入; 4 = 通道 0 的溢出/终止事件; 5 = 通道 1 的溢出/终止事件; 6 = 通道 2 的溢出/终止事件; 7 = 通道 3 的溢出/终止事件。 这里配置为 4U,意思是:让“TMR3 的通道 1”监测“TMR3 的通道 0 的溢出事件”。 已启用 HARD_PWM_LOW_START_PHASE_ENABLE 和 HARD_PWM_STATE_GUARD_ENABLE。APP_PWM_Unmap_Selected_Fault 功能:移除与当前轴对应的故障引脚映射。调用底层 PWM_SetupFaultDisableMap 函数来禁用故障。目的是为了:在不需要硬件故障的情况下,防止意外的外部干扰导致 PWM 关闭,从而方便底层调试过程。 APP_PWM_ClearFault(原始代码函数) 功能:清除 PWM 模块的故障状态标志(axis->pwmBase->FSTS)。触发硬件故障后,必须先清除此标志,然后才能允许 PWM 重新启动。 APP_PWM_禁用输出 功能:立即停止 PWM 定时器,强制引脚输出低电平(PWM_SetPwmForceOutputToZero),并启用输出。它的目的是确保在电机启动之前,引脚不会因为浮空或处于默认状态而输出高电平,这可能会导致电机运动不规则。 APP_QTMR_Disable_Low_OFLAG_Output 功能:禁用 QTMR 的 OFLAG(状态标志)输出,并强制 OFLAG 处于低电平。它与 XBAR 硬件配合使用,其作用是切断 QTMR 输出到 PWM 故障引脚的路径,防止在启动前意外触发故障。 APP_StateGuard_Reset 功能:清除国家卫队(看门狗)的计数器和旗帜。如果启用 HARD_PWM_STATE_GUARD_ENABLE 时系统遇到长时间无脉冲变化或死锁,则此功能用于在停止或重新启动系统之前重置这些保护变量。 APP_PWM_SelectPrescaler_FromPeriodCnt400M 功能:这是一个非常核心的底层频率计算函数。它接收高电平 + 低电平的总 400MHz 计数值,并计算应设置多少个预分频器 (PRSC) 和 PWM 周期 (PERIOD) 才能放入 16 位 PWM 寄存器中。请注意:如果计算出的周期超过 65535 且除法系数超出范围,则此函数将返回 false,导致电机无法启动。 APP_PwmModuleMask 功能:将 PWM 子模块的索引号(例如,值为 0 的 kPWM_Module_0)转换为左移 N 位的位掩码。NXP 的许多 PWM 寄存器(例如 OUTEN、MCTRL)都是逐位控制的。该函数负责生成正确的二进制掩码。
View full article
[S32K324 / Custom Board] HSE FW Installed (0x4039C028=1) but Init Failed (0x4038C107=0) Hi everyone, I am seeking advice regarding an issue where the HSE Firmware initialization fails to complete on an S32K324 custom board. 1. Development Environment MCU: S32K324 (Custom Board) HSE FW: s32k3x4_hse_fw_1.5.0_2.55.0_pb250130.bin.pink Debugger: S32DS + T32 (Trace32) 2. Progress and Status Registers Successfully programmed the HSE FW Usage Flag in the UTEST region (0x1B000000). Downloaded the Pink Image binary into flash memory. After performing a Power-On Reset (POR), the status registers are as follows: 0x4039C028 (HSE GPR): 0x01 (Installation confirmed) 0x4038C107 (HSE_STATUS_INIT_OK): 0x00 (Halted during boot) 3. Questions I would like to ask the experts the following: What is the very first thing I should check? Since the installation succeeded but initialization failed, are there any specific registers (e.g., Fault status) I should dump or hardware signals to inspect to pinpoint the exact cause? Can the Custom Board environment affect the initialization failure? Since I am using a custom board, I suspect hardware differences (e.g., initial XTAL frequency) or the early clock (PLL) configuration code of the main core (M7) might be interfering with the HSE boot sequence. If this is a known issue, could you guide me on the recommended boot sequence (e.g., polling the INIT_OK flag before any clock setup) or potential solutions? Any clues would be a great help. Thank you in advance for your support! Re: [S32K324 / Custom Board] HSE FW Installed (0x4039C028=1) but Init Failed (0x4038C107=0) Hi there, Thank you so much for the clear guidance. First, I proceeded with the firmware installation using the demo app, and then dumped the MU and HSE GPR register values while in the system.up state. Please let me know if any of these register addresses are incorrect. The results are as follows: 1. MU0 Registers (Base Address: 0x4038C000)     2. HSE GPR Registers (Base Address: 0x4039C000)   Could you please review these values? I would highly appreciate your expert opinion on whether these indicate a specific error cause, such as a clock configuration conflict or a firmware authentication failure. Thank you again for your time and support! Re: [S32K324 / Custom Board] HSE FW Installed (0x4039C028=1) but Init Failed (0x4038C107=0) Could you provide following information? MU registers, FSR, GSR, etc: HSE GPR3: Re: [S32K324 / Custom Board] HSE FW Installed (0x4039C028=1) but Init Failed (0x4038C107=0) Thanks. But I would need to see this screenshot when HSE core is in WFI state, not directly after reset.
View full article
RW610/RW612 支持TLS 1.2及以上版本么 RW610/RW612 支持TLS 1.2及以上版本么 Re: RW610/RW612 支持TLS 1.2及以上版本么 Hi, @Cherlyn  Yes, RW610/RW612 支持TLS 1.2. For TLS 3.0, 我们有提供相关的example:frdmrw612_mbedtls3x_selftest 以及frdmrw612_mbedtls3x_psatest 等,您可以参考看一下是否可以满足您的要求。 如果还有其他具体的诉求,也可以提出来,我们一起讨论。 Best regards, Christine.
View full article
Do RW610/RW612 support TLS 1.2 and above? Do RW610/RW612 support TLS 1.2 and above? Re: RW610/RW612 支持TLS 1.2及以上版本么 Hi, @Cherlyn Yes, RW610/RW612 supports TLS 1.2. For TLS 3.0, we have provided relevant examples: frdmrw612_mbedtls3x_selftest and frdmrw612_mbedtls3x_psatest, etc. You can refer to them to see if they meet your requirements. If you have any other specific requests, please feel free to bring them up, and we can discuss them together. Best regards, Christine.
View full article