Multi Source Translation Content

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

Multi Source Translation Content

Discussions

Sort by:
iMX8Mp_FALCON_MODE_RDC_FAILED Hi Environment details: Board: i.MX8M Plus EVK (i.MX8MP EVK) Kernel Version: 6.12.49 Yocto Environment: Yocto-based NXP BSP Boot Mode: Falcon Mode As i have enabled the Falcon mode in i.MX8MP, getting a error:  Failed to find node!, err: -11!  => I Found this issue came from RDC node not structured. We need RDC node? else we can go with this. Here i am pasting my boot logs: U-Boot SPL 2025.04-g4ddbad60eff3-dirty (Nov 19 2025 - 07:56:58 +0000)         DDRINFO: start DRAM init                                                     DDRINFO: DRAM rate 4000MTS                                                   DDRINFO:ddrphy calibration done                                               DDRINFO: ddrmix config done                                                   SEC0:  RNG instantiated                                                       Normal Boot                                                                   Trying to boot from MMC2                                                     Failed to find node!, err: -11!                                               Failed to find node!, err: -11!                                               NOTICE:  Do not release JR0 to NS as it can be used by HAB                   NOTICE:  BL31: v2.12.0(release):lf-6.12.49-2.2.0-dirty                       NOTICE:  BL31: Built : 10:13:07, Oct 17 2025 p104p104p104 NXP i.MX Release Distro 6.12-walnascar imx8mpevk ttymxc1   imx8mpevk login: root root@imx8mpevk:~# i.MX 8M | i.MX 8M Mini | i.MX 8M Nano Re: iMX8Mp_FALCON_MODE_RDC_FAILED Hi @Sanjiv_Mns  “imx8m,mcu_rdc” is used to generate an RDC configuration for allocating resources exclusively owned by the M7. If you do not need this, you can remove the reference to board_handle_rdc_config. If you do need it, you can add mcu_rdc to the dts. Best Regards, Zhiming
View full article
Secure DFU on RT600 Board: RT685 EVK Zephyr toolchain: zephyr-sdk-1.0.1, zsdk nxp-v4.4.1.1 Hi Team! I am working on a Zephyr-based RT600 application, which should include three images in total ( MCUBoot, ARM core image, and DSP core image). Since the RT600 is a flash-less MCU, those images have to live in the external flash, and I am looking for a proper way to protect them against read-back and other potential risks that could leak the image. On top of that, I would like to have the DFU feature to update both the ARM core and the DSP core images via SMP protocol (RT600 running as SMP server, or through MCUBoot serial recovery, or both) in an encrypted manner. I failed to find an example shipped with nxp-zsdk, could you please help me find a practical path to follow? Best regards, Yue Re: Secure DFU on RT600 Hi @YueZ , For the RT685 EVK, I recommend treating this as two related design tasks : securing what is stored in external flash, and securely updating the Arm and DSP firmware. An encrypted update alone does not establish that the active image is protected against external-flash read-back. A practical starting point is to package the DSP firmware with the Arm application and update them as one signed image . That lets you bring up a single MCUboot primary/secondary-slot update path before taking on independent DSP image management. Zephyr’s SMP image-management flow uploads an update to a secondary slot for MCUboot to process at boot.(zephyr/doc/services/device_mgmt/smp_groups/smp_group_1.rst at main · zephyrproject-rtos/zephyr · GitHub) On RT600, the boot images reside outside internal flash, either for loading into SRAM or for execution from external memory, so the flash layout and boot chain need to be designed together. - https://www.nxp.com/docs/en/application-note/AN12985.pdf  I would proceed in this order: Establish a trusted boot chain : authenticate the bootloader at startup, then have it verify signed application updates. Include production key provisioning and debug-access policy in the design. Demonstrate a signed Arm-plus-DSP update through an application-side SMP server, with a defined primary and secondary flash slot. Confirm that the newly built DSP firmware is actually included in the image being uploaded. Address confidentiality of the installed image separately . NXP’s RT600 secure-provisioning workflow describes writing an encrypted application and OTFAD key blobs,(mcuxpresso.nxp.com/secure/latest/_sources/06_processor_specific_workflow.md) and its RT600 FOTA note describes a signed-and-encrypted OTA approach. Those are useful RT600 references, but their procedures are not a ready-made Zephyr SMP integration. - https://www.nxp.com/docs/en/application-note/AN13478.pdf  If independent Arm and DSP updates are required, design separate image storage and verification, plus a way to prevent incompatible Arm/DSP versions from being activated together. I would treat that as a second integration milestone, not as a capability already demonstrated by the combined-image example. Application-side SMP and bootloader-side serial recovery can both be considered, but they are distinct update paths; you do not need to implement both to validate the first DFU milestone.  Could you confirm whether the DSP must be updated independently, or whether updating Arm and DSP together is acceptable? That decision determines whether the simpler combined-image path meets your requirements or whether a multi-image boot and rollback design is necessary.   Have a great day, Kan ------------------------------------------------------------------------------- Note: - If this post answers your question, please click the "Mark Correct" button. Thank you! - We are following threads for 7 weeks after the last post, later replies are ignored Please open a new thread and refer to the closed one, if you have a related question at a later point in time. ------------------------------------------------------------------------------- Re: Secure DFU on RT600 Hi Kan, Thank you very much for the information, it is really clear and helpful! To answer your question, I am fine with packing the two images into one; they don't need to be separate. Additionally, I am eager to know your suggestions on a few more questions, and please correct me if I am wrong since I am new to the NXP secure-provisioning workflow: The two milestones are, if I understood it correctly: 1) verify FOTA image signing and boot chain; 2) verify OTFAD on the off-chip flash. It looks like the west build process only signs the image without encryption; the output hex(bin) image file remains in plaintext, which is supposed to be encrypted in the second step for OTFAD. On an OTA update, a signed image is received and then written into flash as OTFAD-encrypted. Does that mean the image in transit is exposed to attack? XIP or loading in RAM, which would you recommend for less workload in Zephyr if combined with signing and encryption?  Is there an example available in Zephyr demonstrating the OTFAD feature on RT600 (and whether OTFAD is supported by MCUBoot serial recovery)? I found modules/hal/nxp/mcux/mcux-sdk-ng/drivers/otfad/fsl_otfad.h, but nothing has referred to it yet. A starting point would be very much appreciated! Best regards, Yue Re: Secure DFU on RT600 Hi @YueZ , Thank you for confirming that the Arm and DSP firmware can be packaged together. That is the path I would start with: one signed application update containing both firmwares , rather than two independently managed application images. Your proposed milestones are sensible, but I would separate them slightly differently: Prove the boot and update chain: boot the combined image through MCUboot, upload a signed replacement through application-side SMP, and verify the upgrade and recovery behavior. Prove encrypted boot on the RT685 EVK: use Secure Provisioning Tool (SPT) to build and boot an OTFAD-encrypted image from external flash, initially using the documented shadow-register development workflow. - Processor-specific workflows — Secure Provisioning Tool 26.09  Integrate the two: determine how a field update will be staged and installed in the encrypted flash layout without breaking image verification or recovery. This last step is not provided automatically by enabling OTFAD. - Generic workflows — Secure Provisioning Tool 26.09  On the plaintext build output and transmission: your understanding is substantially correct. The documented Zephyr/MCUboot workflow produces a signed application file, zephyr.signed.bin ; signing does not conceal its contents. If that file is distributed and uploaded as-is, someone able to obtain the file or observe an unprotected transfer can read the firmware. You can protect the transfer with an appropriately authenticated, encrypted transport, or distribute an encrypted update artifact. These are separate from protecting the installed image in external flash. - Generic workflows — Secure Provisioning Tool 26.09 Encrypted XIP and MCUboot — MCUXpresso SDK Documentation I would make one correction to the proposed OTA diagram: do not assume that receiving a signed plaintext image and writing it with Zephyr’s flash driver automatically produces OTFAD-encrypted flash contents. SPT’s RT5xx/6xx workflow explicitly writes an encrypted application and OTFAD key blobs . A field updater must reproduce a compatible result—or use another validated installation scheme—while accounting for the protected address ranges and keys. The RT600 OTFAD reference describes decryption of encrypted flash during reads; the SPT provisioning procedure should not be taken as an implementation of Zephyr’s runtime update writer. -https://www.nxp.com/docs/en/training-reference-material/RT600_Security_Architecture_sb.pdf  XIP versus load-to-RAM: since your goal is specifically to protect an application stored in external flash with OTFAD, I would use encrypted XIP as the first security proof of concept . SPT documents that boot workflow for RT5xx/6xx. This is a recommendation for the boot experiment , not a claim that encrypted XIP makes the Zephyr DFU integration easy. Load-to-RAM is also a documented RT5xx/6xx image arrangement, but it does not remove the need to protect the stored image and design a secure update path. I cannot substantiate that either option is a turnkey, lower-workload Zephyr solution for your SDK version. Regarding examples and serial recovery: I have not found a validated RT685 Zephyr example combining OTFAD, MCUboot and SMP/serial-recovery encrypted updates for nxp-v4.4.1.1 . The fsl_otfad.h header establishes that a driver interface exists; it does not establish that the RT685 MCUboot recovery or flash-installation path integrates it. NXP’s Encrypted XIP and MCUboot documentation describes an encrypted-XIP extension, but its listed OTFAD example boards are RT1152/RT1160/RT1170, not RT685 . I would not assume that its serial-recovery or installation behavior carries over to this board. That is something I still need to check with the team. For a concrete starting reference, use SPT 26.09, “RT5xx/6xx device workflow → Booting OTFAD encrypted image using shadow registers” to establish the encrypted-boot baseline. In parallel, use AN13478, Implementing FOTA on i.MX RT600 to study NXP’s RT600 signed-and-encrypted update approach. That application note is not a Zephyr SMP example, so the remaining work is to reconcile its encrypted-image installation approach with your Zephyr/M​​CUboot slot layout and chosen update path.    For this board, I would validate signed combined-image DFU and SPT-generated OTFAD XIP separately, then treat encrypted field installation—including any serial-recovery support—as an integration task requiring its own test.   Have a great day, Kan ------------------------------------------------------------------------------- Note: - If this post answers your question, please click the "Mark Correct" button. Thank you! - We are following threads for 7 weeks after the last post, later replies are ignored Please open a new thread and refer to the closed one, if you have a related question at a later point in time. ------------------------------------------------------------------------------- Re: Secure DFU on RT600 Hi Kan, This is enough information for me to digest at this point, I will mark it as a solution. Please notify me if the team has any updates on the capability of RT685 MCUboot recovery with OTFAD. Thank you very much for the details! You have a great day too! Yue
View full article
关于 S32G3 电路板支持包。 48.0.0 的 RESET 序列和 A53 锁步启动流程的说明 尊敬的恩智浦技术支持团队: 我正在使用 S32G378A EVB3 和 Linux 电路板支持包。 48.0.0。我的目标是先启动 Cortex-M7,然后从 M7 软件启用 Cortex-A53 锁步模式,最后在 Cortex-A53 上启动 Linux。 我了解到,电路板支持包。通过在 conf/local.conf 文件中添加以下内容来支持 m7boot 功能: DISTRO_FEATURES:append = " m7boot" 然后使用以下命令重建镜像: bitbake fsl-image-auto 之后,我会写入生成的 .sdcard 文件。将镜像文件写入SD卡,并从SD卡启动板。 但是,我需要了解实际的RESET和启动顺序。 问题 1:上电后的 RESET 状态是什么? 假设 Linux 已经安装并运行在 Cortex-A53 上。然后我关闭或断开板的电源,使用 m7boot 重建 电路板支持包。,将新镜像写入 SD 卡,然后再次打开板的电源。 完全断电重启后,哪些 Cortex-M7 和 Cortex-A53 内核或功能域会被硬件和 BootROM 保持在复位状态? BootROM 是否会根据 IVT 启动目标自动启动 M7_0,同时保持 A53 处于 RESET 状态? 是否需要任何额外的 RESET 配置来确保 A53 在 M7 软件启用 Lockstep 之前保持 RESET 状态? 问题 2:m7boot 会自动执行哪些操作? 启用 m7boot、重新构建电路板支持包并写入生成的 SD 卡映像后: 电路板支持包是否会自动提供并执行启用 A53 锁步功能的 M7 固件? 该固件是否会将 A53 保持在 RESET 状态,配置 A53_GPR06[CA53_LOCKSTEP_EN],然后释放 A53 以启动 Linux? 或者我必须单独修改、构建或部署 M7 固件来实现这些步骤? 请说明电路板支持包。中哪些部分是自动执行的,哪些部分需要用户实现。 问题 3:启用 Lockstep 并启动 A53 所需的运行时顺序是什么? 我希望能够提供从冷启动开始的完整操作步骤: 板上电并执行 BootROM。 IVT 选择 M7_0 作为启动目标。 M7固件启动。 配置锁步时保持 A53 处于 RESET 状态。 配置 Lockstep 后释放或启动 A53。 在 A53 上以锁步模式启动 Linux。 具体来说,启用 Lockstep 后,M7 如何释放或启动 A53?哪个已记录的寄存器、API 或固件函数执行此步骤? 这个过程是在一次正常启动过程中完成的,还是在启用 Lockstep 后需要 RESET 电路板或进行第二次启动? 问题 4:后续启动会发生什么? 当 Linux 在 A53 上以锁步模式运行时,如果我关闭或断开电路板的电源,然后再重新开机: 每次启动时,是否都会自动运行相同的 M7 优先、Lockstep 配置和 A53 启动顺序? 锁步配置在热RESET后是否会保留,还是必须通过 M7 重新配置? 冷启动、热RESET和软件重启之间有什么区别是我需要注意的吗? 我的目标是在每次启动时自动完成此操作,而无需手动进入启动加载程序或再次 RESET 板。 请提供 S32G378A EVB3 的相关 电路板支持包。 48.0.0 源代码参考、配置文件和已记录的重置/启动顺序? 顺祝商祺! Re: Clarification on Reset Sequence and A53 Lockstep Boot Flow with S32G3 BSP 48.0.0 你好,Toan 感谢你的回复。希望这些内容对您有所帮助。 问题 1:上电后的 RESET 状态是什么? >>> BootROM 根据 IVT 启动配置字中的 BOOT_TARGET 选择应用程序核心。对于“m7boot”,BootROM 使用映像中的 IVT 启动 M7。然后,M7 应用程序配置 A53 Lockstep,并负责启动 A53 core0。 问题 2:m7boot 会自动执行哪些操作? >>>在 Yocto 中使用 DISTRO_FEATURES:append = " m7boot", m7-sample 项目将自动下载,这是 M7 固件。 此应用程序包含几个功能,例如启用分区、启用 A53 核心、设置 a53_entry_point 地址以及在启用分区之前进行锁步设置,如下图所示。 https://github.com/nxp-auto-linux/m7-sample/blob/release/bsp48.0/src/main.c   问题 3:启用 Lockstep 并启动 A53 所需的运行时顺序是什么? 我希望能够提供从冷启动开始的完整操作步骤: 板上电并执行 BootROM。 IVT 选择 M7_0 作为启动目标。 M7固件启动。 配置锁步时保持 A53 处于 RESET 状态。 配置 Lockstep 后释放或启动 A53。 在 A53 上以锁步模式启动 Linux。 具体来说,启用 Lockstep 后,M7 如何释放或启动 A53?哪个已记录的寄存器、API 或固件函数执行此步骤? 这个过程是在一次正常启动过程中完成的,还是在启用 Lockstep 后需要 RESET 电路板或进行第二次启动? >>>你上面的理解对于 Yocto 中的 DISTRO_FEATURES:append = " m7boot" 基本正确。理论上讲,m7 样本有助于完成这些任务。 关于第 32 章模式输入模块 (MC_ME) 的 S32G2RM.pdf 文件,对于“启用锁步后 M7 如何释放或启动 A53”这个问题很有用。 问题 4:后续启动会发生什么? >>>您可以参考此链接查看 M7boot 源代码。 https://github.com/nxp-auto-linux/m7-sample/tree/release/bsp46.0 根据 m7-sample,M7boot 将在每次启动时设置 Lockstep 模式。 BR 乔伊 Re: Clarification on Reset Sequence and A53 Lockstep Boot Flow with S32G3 BSP 48.0.0 嗨,乔伊, 感谢您的反馈, 我们的计划是按照 S32G3 Linux 电路板支持包。 48.0.0 文档,使用 Yocto 为 S32G399A EVB3 构建 Linux 镜像,然后将其部署到 SD 卡。 我们打算先启动 Cortex-M7,并使用 M7 软件启用 Cortex-A53 Lockstep 模式,同时保持 A53 RESET 功能域处于 RESET 状态。配置好 Lockstep 后,Cortex-A53 将可以启动 Linux。 我们不打算使用 Cortex-M7 来运行我们的应用程序。M7 的唯一目的是在 Linux 启动之前执行必要的初始化以启用 A53 锁步模式。 此致, 托安 Re: Clarification on Reset Sequence and A53 Lockstep Boot Flow with S32G3 BSP 48.0.0 你好,Toan 感谢您与我们联系。 我已经收到您的案件,我会帮您核查。 在 Yocto 中,“DISTRO_FEATURES:append = 'm7boot'” 行提供了一个示例,方便地演示了 Cortex-M7 的启动过程,并启用了锁定步进操作模式。 请问您能否告知一下您项目中 S32G378 的启动过程?您是否考虑使用M7核心?您的项目是否考虑过使用引导加载程序来启动 M7 核心和 A53 核心? BR 乔伊 Re: Clarification on Reset Sequence and A53 Lockstep Boot Flow with S32G3 BSP 48.0.0 嗨,乔伊, 谢谢你的支持,我很感激。我还有一个问题想问。 由于我的唯一目标是启用 A53 Lockstep,请问默认的 m7-sample是否已经能够启用 Lockstep 并重启 A53 core0,从而使 Linux 能够在 Lockstep 模式下运行而无需任何额外的固件修改? 感谢您的确认。 此致, 托安 Re: Clarification on Reset Sequence and A53 Lockstep Boot Flow with S32G3 BSP 48.0.0 你好, Toan 感谢您与我们联系。 由于我的唯一目标是启用 A53 Lockstep,请问默认的 m7-sample 是否已经能够启用 Lockstep 并重启 A53 core0,从而使 Linux 能够在 Lockstep 模式下运行而无需任何额外的固件修改? >>>是的,m7-sample 启动应用程序确实可以实现您所说的功能,其主要功能包括启用锁步/分区/A53 核心,这与 RM 手册中的描述相符,如下图所示。 m7-sample/src/main.c 位于 版本/bsp48.0 · nxp-auto-linux/m7-sample · GitHub 1.启用锁步/分区 2.启用核心 此外,您还可以尝试检查Linux应用程序中的锁步功能。 希望这些信息对您有所帮助;如果您还有其他问题,可以随时联系我们。 BR 乔伊 Re: Clarification on Reset Sequence and A53 Lockstep Boot Flow with S32G3 BSP 48.0.0 嗨,乔伊, 非常感谢您的帮助和解答我的问题。我非常感谢您的支持。 如果以后我还有其他问题,希望还能再次得到您的帮助。 再次感谢! Re: Clarification on Reset Sequence and A53 Lockstep Boot Flow with S32G3 BSP 48.0.0 你好,Toan 我很乐意帮助你! 如果您还有其他问题,欢迎随时联系我们! BR 乔伊
View full article
RT600でのセキュアDFU 基板: RT685 EVK Zephyr toolchain: zephyr-sdk-1.0.1, zsdk nxp-v4.4.1.1 チームの皆さん、こんにちは! 私はZephyrベースのRT600アプリケーションを開発しており、合計3つの画像(MCUBoot、ARMコアイメージ、DSPコアイメージ)を含める予定です。 RT600はフラッシュレスMCUなので、それらの映像は外部フラッシュに収まらなければならず、読み書きや画像のリークリスクから適切に保護する方法を探しています。さらに、DFU機能を使って、ARMコアとDSPコアのイメージをSMPプロトコル(RT600をSMPサーバーとして動作させるか、MCUBoot シリアルリカバリー、またはその両方で動作する)で暗号化して更新したいと考えています。 nxp-zsdkに付属している例を見つけられませんでした。実践的な方法を教えていただけませんか? よろしくお願いいたします。 ユエ Re: Secure DFU on RT600 こんにちは、 @YueZ さん。 RT685 EVKについては、これを 2つの関連する設計タスク として扱うことをおすすめします。外部フラッシュに保存されるものの安全と、ArmおよびDSPファームウェアの安全な更新です。暗号化されたアップデートだけでは、アクティブイメージが外部フラッシュからの読み出し攻撃から保護されていることを保証するものではありません。 実用的な出発点としては 、DSPファームウェアをArmアプリケーションにパッケージ化し、それらを1つの署名済みイメージとして更新 することです。これにより、独立したDSPイメージマネジメントを行う前に、単一のMCUbootプライマリ/セカンダリスロット更新パスを起動できます。ZephyrのSMPイメージマネジメントフローは、MCUbootが起動時に処理するための二次スロットに更新をアップロードします。(zephyr/doc/services/device_mgmt/smp_groups/smp_group_1.rst at main · zephyrproject-rtos/zephyr ·GitHub)RT600では、起動イメージは内部フラッシュの外部に存在し、SRAMへの読み込みや外部メモリからの実行に使うため、フラッシュのレイアウトとブートチェーンは一緒に設計する必要があります。- https://www.nxp.com/docs/en/application-note/AN12985.pdf 私は以下の順序で進めます。 信頼できるブートチェーンを確立します:起動時にブートローダーを認証し、その後、署名済みのアプリケーション更新を検証させます。設計に本番キーのプロビジョニングとデバッグアクセスポリシーを含めてください。 プライマリおよびセカンダリフラッシュスロットを定義したアプリケーション側のSMPサーバーを通じて 、署名済みのArm plus-DSPアップデート を実証します。新たに構築されたDSPファームウェアが実際にアップロードされるイメージに含まれているか確認してください。 インストールされたイメージの機密性については、別途対処してください。NXPのRT600セキュアプロビジョニングワークフローは暗号化アプリケーションとOTFADキーブロブ(mcuxpresso.nxp.com/secure/latest/_sources/06_processor_specific_workflow.md)の作成を説明し、RT600 FOTAノートは署名付き暗号化されたOTAアプローチを説明しています。それらはRT600の有用な参考資料ですが、手順は既製のZephyr SMP統合ではありません。- https://www.nxp.com/docs/en/application-note/AN13478.pdf 独立したArmおよびDSPの更新が必要な場合は、別々の画像保存と検証を設計し、互換性のないArm/DSPバージョンが同時に起動されるのを防ぐ方法も用意してください。私はそれを、結合イメージの例ですでに実証された機能ではなく、2番目の統合マイルストーンとして捉えるべきでしょう。 アプリケーション側のSMPとブートローダー側のシリアルリカバリーはどちらも考慮できますが、それぞれ異なる更新経路です。最初のDFUマイルストーンを検証するために両方を実装する必要はありません。 DSPは独立して更新する必要があるのか、それともArmとDSPを同時に更新しても問題ないのか確認していただけますか?その判断が、よりシンプルな結合イメージパスが要件を満たすか、それとも複数イメージのブート&ロールバックデザインが必要かを決定します。   すてきな一日を、 カン ------------------------------------------------------------------------------- 注記: この投稿があなたの質問への回答になっている場合は、「正解としてマーク」ボタンをクリックしてください。ありがとうございます! - 前回の投稿から7週間Threadをフォローしており、その後の返信は無視しています もし後で関連する質問があれば、新しいThreadを開き、閉じたThreadを参照してください。 ------------------------------------------------------------------------------- Re: Secure DFU on RT600 こんにちは、カンさん。 情報提供ありがとうございました。とても分かりやすく、大変参考になりました!ご質問にお答えすると、2つの画像を1つにまとめることに問題はありません。別々にする必要はありません。 さらに、いくつか質問があるので、ご意見をお聞かせいただければ幸いです。また、NXPのセキュアプロビジョニングワークフローは初めてなので、もし私の理解が間違っていたらご指摘ください。 私が正しく理解していれば、2つのマイルストーンは次のとおりである。1) FOTAイメージの署名とブートチェーンの検証、2) オフチップフラッシュ上のOTFADの検証。どうやら、西側のビルドプロセスではイメージに署名するだけで暗号化は行われていないようです。出力されるhex(bin)イメージファイルは平文のままですが、これはOTFADの2番目のステップで暗号化されるはずです。OTAアップデート時には、署名付きイメージが受信され、OTFAD暗号化された状態でフラッシュメモリに書き込まれる。それは、転送中の画像が攻撃にさらされる可能性があるという意味ですか? XIPとRAMでの読み込み、署名や暗号化と組み合わせた場合、Zephyrで作業負荷を減らすためにどちらがおすすめでしょうか? ZephyrでRT600のOTFAD機能(およびOTFADがMCUBootシリアルリカバリーでサポートされているかどうか)を示す例はありますか?modules/hal/nxp/mcux/mcux-sdk-ng/ドライバ/otfad/fsl_otfad.hは見つけましたが、まだ何も言及されていません。出発点となる情報があれば大変ありがたいです! よろしくお願いいたします。 ユエ Re: Secure DFU on RT600 こんにちは、 @YueZ さん。 ArmとDSPのファームウェアが一緒にパッケージ化できることを確認してくれてありがとうございます。私ならまず最初に考えるのは、2つの独立管理アプリケーションイメージではなく、 両方のファームウェアを含む署名付きアプリケーションアップデートを 1つにすることです。 あなたが提案したマイルストーンは理にかなっていますが、私なら少し違った形で分類します。 起動と更新の連鎖を証明する: 結合イメージをMCUboot経由で起動し、アプリケーション側のSMPで署名入り代替画像をアップロードし、アップグレードと回復の動作を確認します。 RT685 EVK 上で暗号化ブートを検証する: Secure Provisioning Tool (SPT) を使用して、外部フラッシュから OTFAD で暗号化されたイメージを構築してブートします。最初は、ドキュメントに記載されているシャドウレジスタ開発ワークフローを使用します。- プロセッサ固有のワークフロー — Secure Provisioning Tool 26.09  この2つを統合する:イメージの検証や復旧を損なうことなく、暗号化されたフラッシュレイアウト内でフィールドアップデートをどのように段階的に実行し、インストールするかを決定する。この最後のステップは、OTFADを有効にしても自動的には提供されません。-汎用ワークフロー — セキュアプロビジョニングツール 26.09 平文の構築出力と送信に関して:あなたの理解は概ね正しいです。文書化されたZephyr/MCUbootのワークフローは署名済みアプリケーションファイル zephyr.signed.bin 生成します;署名はその内容を隠しません。そのファイルがそのまま配布・アップロードされた場合、ファイルを入手したり保護されていない転送を観察できる人がファームウェアを読み取ることができます。適切に認証された暗号化されたトランスポートで転送を保護するか、暗号化された更新アーティファクトを配布することもできます。これらは、外部フラッシュメモリにインストールされたイメージを保護することとは別個のものです。- 汎用ワークフロー — Secure Provisioning Tool 26.09 暗号化XIPおよびMCUboot — MCUXpresso SDKドキュメント 提案されたOTA図に一つ訂正したいのは、 署名済みのプレーンテキスト画像を受け取り、Zephyrのフラッシュドライバーで書き込みをすると自動的にOTFAD暗号化されたフラッシュ内容を生成すると仮定しないことです。SPTのRT5xx/6xxワークフローは、 暗号化されたアプリケーション と OTFADキーの塊 を明示的に書き込みます。フィールドアップデーターは、保護されたアドレス範囲とキーを考慮しながら、互換性のある結果を再現するか、または別の検証済みのインストール方式を使用する必要があります。RT600 OTFADのリファレンスは、読み込み中の暗号化フラッシュの復号化を記述しています。SPTのプロビジョニング手順は、Zephyrのランタイム更新ライターの実装として受け取るべきではありません。- https://www.nxp.com/docs/en/training-reference-material/RT600_Security_Architecture_sb.pdf XIPとRAMへのロード: あなたの目的はOTFADで外部フラッシュに保存されたアプリケーションを保護することなので、 最初のセキュリティ証明として暗号化されたXIP を使うのが良いでしょう。SPTドキュメントには、RT5xx/6xxのブートワークフローが記載されています。これは ブート実験 のための推奨であり、暗号化されたXIPがZephyr DFU統合を簡単にするという主張ではありません。RAMへのロードも文書化されたRT5xx/6xxイメージ配置ですが、保存されたイメージを保護し安全な更新経路を設計する必要性を取り除くわけではありません。どちらの選択肢もあなたのSDKバージョンに対して、Zephyrのターンキーで作業負荷の少ないソリューションだとは証明できません。 例とシリアルリカバリーについて:OTFAD、MCUboot、SMP/シリアルリカバリーの暗号化アップデートを組み合わせたRT685 Zephyrの検証済み例は nxp-v4.4.1.1 見つかっていません。 fsl_otfad.h ヘッダーはドライバーインターフェースの存在を示します。RT685のMCUbootリカバリーやフラッシュインストールパスがそれを統合しているとは証明しません。NXPの Encrypted XIPおよびMCUboot のドキュメント では暗号化されたXIP拡張が説明されていますが、掲載されている OTFADの例基板はRT1152/RT1160/RT1170であり、RT685ではありません 。そのシリアルリカバリやインストール時の動作が、このボードにもそのまま引き継がれるとは考えない方が良いでしょう。それはまだチームに確認する必要がある事項です。 具体的な出発点として、 SPT 26.09「RT5xx/6xx デバイスワークフロー → シャドウレジスタを使用した OTFAD 暗号化イメージのブート」を使用して、暗号化ブートのベースラインを確立してください。並行して、 AN13478 「i.MX RT600でのFOTAの実装」を参照して、NXPのRT600における署名付き暗号化アップデート方式について調べてください。このアプリケーションノートはZephyr SMPの例 ではないため 、残る作業は暗号化イメージインストール方式とZephyr/MCUbootのスロットレイアウトおよび選択した更新経路を照合することです。   このボードでは、署名済みの結合イメージDFUとSPT生成のOTFAD XIPを別々に検証し、暗号化フィールドインストール(シリアルリカバリーサポートを含む)を統合タスクとして独自のテストが必要と扱います。   すてきな一日を、 カン ------------------------------------------------------------------------------- 注記: この投稿があなたの質問への回答になっている場合は、「正解としてマーク」ボタンをクリックしてください。ありがとうございます! - 前回の投稿から7週間Threadをフォローしており、その後の返信は無視しています もし後で関連する質問があれば、新しいThreadを開き、閉じたThreadを参照してください。 ------------------------------------------------------------------------------- Re: Secure DFU on RT600 こんにちは、カンさん。 現時点では、これだけの情報で十分理解できましたので、解決済みとしてマークします。チームからOTFADを使用したR T685 MCUbootリカバリ機能に関する最新情報があれば、私に知らせてください。 詳しい情報をありがとうございました!あなたも素敵な一日をお過ごしください! ユエ
View full article
FS2400 INIT_CRC_NOK_I 在频繁的电源循环(开/关)条件下,检测到了 FS2400 的 INIT_CRC_NOK_I 标志。在这种情况下,我读取了 FS_I_XXX 寄存器,其内容与我在 INIT 阶段写入的数据一致。此外,故障错误计数没有增加,仍然为0。请问这是否是误报,这种情况是否可以不予处理? Re: FS2400 INIT_CRC_NOK_I 您好, 当 FS2400 的循环 CRC 校验机制检测到每 5 毫秒对 INIT 寄存器重新计算的 CRC 与存储在 FS_CRC 寄存器中的值不匹配时,将设置 INIT_CRC_NOK_I 标志。这是一项真正的功能安全监控功能,在不了解其根本原因的情况下不应忽视。 即使您可以读取 FS_I_XXX 寄存器并发现其值与您写入的值一致,也不能排除 CRC 校验不匹配的可能性——这种情况最常见的原因是 MCU 正确写入了 INIT 寄存器,但在 INIT 阶段结束之前没有计算并将正确的 CRC 值存储在 FS_CRC 中(即,未执行任何操作)。在第一次正确的监视程序刷新之前)。请核实以下内容: 1. CRC 计算:必须对以下寄存器位域的连接进行 8 位 CRC 计算(按此顺序): FS_I_OVUV_CFG1[15:0] FS_I_OVUV_CFG2[15:0] FS_I_ERRMON_LIMP0_CFG[15:0] FS_I_FSSM_CFG[15:4] FS_I_WD_CFG[15:7] 要应用的多项式是:x⁸ + x⁴ + x³ + x² + 1(与 SPI CRC 相同)。 2. CRC 注册:MCU 必须在 INIT 阶段结束之前将计算出的 CRC 写入 FS_CRC(即,在 INIT 阶段结束之前)。在第一次正确的监视程序刷新之前)。如果在写入 CRC 之后修改了任何 INIT 寄存器,则必须重新计算并重新写入 CRC。 3. 故障错误计数器说明:我们注意到您提到故障错误计数仍为 0。请注意,根据设备数据手册,上电复位 (POR) 后故障错误计数器从 1 开始,而不是从 0 开始。每次 INIT_CRC_NOK 触发信号被触发时,该计数器都会加 1。请问您能否确认一下您正在读取哪个寄存器和字段中的值?如果计数器在多次上电循环中保持为 1(POR-RESET 值),则表明该标志在上电序列的早期就被观察到,可能在计数器有时间累积之前。我们希望您能具体说明一下,您观察到该标志出现的时间与 INIT 阶段完成时间之间的确切关系。 4. 电源循环考虑:INIT 阶段总是从 POR(完全断电和上电)重新进入。循环 CRC 校验仅在 INIT 阶段结束后的正常模式下激活。如果在 INIT 关闭后不久观察到 INIT_CRC_NOK_I 标志,则强烈表明在第一次 5 毫秒检查时,FS_CRC 寄存器值与当前的 INIT 寄存器内容不匹配。 BRs,托马斯
View full article
RT600 上的安全 DFU 电路板:RT685 EVK Zephyr 工具链:zephyr-sdk-1.0.1,zsdk nxp-v4.4.1.1 大家好! 我正在开发一个基于 Zephyr 的 RT600 应用程序,该应用程序总共应该包含三个镜像(MCUBoot、ARM 内核镜像和 DSP 内核镜像)。 由于 RT600 是一个无闪存的 MCU,这些图像必须存储在外部闪存中,我正在寻找一种合适的方法来保护它们免受回读和其他可能泄露图像的潜在风险。除此之外,我还希望 DFU 功能能够以加密的方式通过 SMP 协议(RT600 作为 SMP 服务器运行,或通过 MCUBoot 串行恢复,或两者兼而有之)更新 ARM 内核和 DSP 内核映像。 我没有找到 nxp-zsdk 自带的示例,您能帮我找到一个可行的学习路径吗? 顺祝商祺! 岳 Re: Secure DFU on RT600 你好@YueZ , 对于 RT685 EVK,我建议将其视为两个相关的设计任务:保护存储在外部闪存中的内容,以及安全地更新 Arm 和 DSP 固件。单凭加密更新并不能证明活动映像受到保护,免受外部闪存读取。 一个切实可行的起点是将DSP 固件与 Arm 应用程序打包在一起,并将它们作为一个签名映像进行更新。这样,您就可以在进行独立的 DSP 映像管理之前,启动单个 MCUboot 主/辅助插槽更新路径。Zephyr 的 SMP 镜像管理流程会将更新上传到辅助插槽,供 MCUboot 在启动时处理。( zephyr/doc/services/device_mgmt/smp_groups/smp_group_1.rst at main · zephyrproject-rtos/zephyr · GitHub )在 RT600 上,启动映像位于内部闪存之外,可以加载到 SRAM 中,也可以从外部存储器执行,因此闪存布局和启动链需要一起设计。- https://www.nxp.com/docs/en/application-note/AN12985.pdf 我会按以下顺序进行: 建立可信的启动链:在启动时验证引导加载程序,然后让它验证已签名的应用程序更新。在设计中纳入生产密钥配置和调试访问策略。 通过应用端 SMP 服务器演示已签名的 Arm+DSP 更新,并定义主闪存槽和辅助闪存槽。确认新构建的 DSP 固件确实包含在上传的镜像中。 单独处理已安装镜像的保密性问题。NXP 的 RT600 安全配置工作流程描述了如何编写加密的应用程序和 OTFAD 密钥块( mcuxpresso.nxp.com/secure/latest/_sources/06_processor_specific_workflow.md ),其 RT600 FOTA 说明描述了一种签名和加密的 OTA 方法。这些是有用的 RT600 参考资料,但它们的程序并不是现成的 Zephyr SMP 集成。- https://www.nxp.com/docs/en/application-note/AN13478.pdf 如果需要独立的 Arm 和 DSP 更新,则设计单独的映像存储和验证,以及防止不兼容的 Arm/DSP 版本同时激活的方法。我会将其视为第二个集成里程碑,而不是组合图像示例已经证明的功能。 应用层SMP和引导加载程序层串行恢复都可以考虑,但它们是不同的更新路径;您无需同时实现两者即可验证第一个DFU里程碑。 请问DSP是否必须单独更新,还是Arm和DSP可以同时更新?该决定将决定更简单的组合映像路径是否满足您的要求,或者是否需要多映像启动和回滚设计。   祝你有美好的一天, 坎 ------------------------------------------------------------------------------- 笔记: - 如果此回复解答了您的问题,请点击“标记为正确答案”按钮。谢谢你! - 我们会持续关注帖子,从最后一条回复发出后持续7周,之后的回复将被忽略。 如果您之后有相关问题,请另开新帖并引用已关闭的帖子。 ------------------------------------------------------------------------------- Re: Secure DFU on RT600 嗨,Kan, 非常感谢您提供的信息,它非常清晰且很有帮助!回答你的问题,我觉得把两张图片合并成一张没问题;它们不需要分开。 此外,我还想听听您对以下几个问题的建议,如果我说错了,请您指正,因为我对NXP安全配置工作流程还不熟悉: 如果我理解正确的话,这两个里程碑是:1)验证 FOTA 镜像签名和启动链;2)验证片外闪存上的 OTFAD。看起来西部的版本过程只是对图像进行签名而没有加密;输出的 hex(bin)图像文件仍然是明文,应该在第二步中对 OTFAD 进行加密。在 OTA 更新过程中,会收到一个签名镜像,然后将其以 OTFAD 加密的形式写入闪存。这是否意味着传输中的图像容易受到攻击? 如果将签名和加密功能结合使用,您会推荐使用 XIP 还是 RAM 加载来降低 Zephyr 的工作负载? Zephyr 中是否有示例演示 RT600 上的 OTFAD 功能(以及 MCUBoot 串行恢复是否支持 OTFAD)?我找到了 modules/hal/nxp/mcux/mcux-sdk-ng/drivers/otfad/fsl_otfad.h,但目前还没有任何东西引用它。非常感谢您能提供一个起点! 顺祝商祺! 岳 Re: Secure DFU on RT600 你好@YueZ , 感谢您确认 Arm 和 DSP 固件可以打包在一起。我会从以下方案入手:使用一个包含两个固件的签名应用程序更新,而不是两个独立管理的应用程序映像。 你提出的里程碑计划很合理,但我会稍微调整一下它们的划分方式: 验证启动和更新链:通过 MCUboot 启动组合镜像,通过应用端 SMP 上传签名替换,并验证升级和恢复行为。 在 RT685 EVK 上验证加密启动:使用安全配置工具 (SPT) 从外部闪存构建和启动 OTFAD 加密映像,最初使用已记录的影子寄存器开发工作流程。-处理器特定工作流程 — 安全配置工具 26.09 将两者结合起来:确定如何在加密闪存布局中分阶段和安装现场更新,而不会破坏映像验证或恢复。启用 OTFAD 并不会自动执行最后一步。-通用工作流程 — 安全配置工具 26.09 关于纯文本版本输出和传输:你的理解基本正确。文档中记录的 Zephyr/MCUboot 工作流程会生成一个已签名的应用程序文件 zephyr.signed.bin ;签名并不会隐藏其内容。如果该文件按原样分发和上传,那么任何能够获取该文件或观察到未受保护传输的人都可以读取固件。您可以使用经过适当身份验证的加密传输来保护传输,或者分发加密的更新工件。这些与保护安装在外部闪存中的映像是分开的。-通用工作流程 — 安全配置工具 26.09加密 XIP 和 MCUboot — MCUXpresso SDK 文档 我对提议的 OTA 图有一点更正:不要假设接收到签名的明文图像并使用 Zephyr 的闪存驱动程序写入它会自动生成 OTFAD 加密的闪存内容。SPT 的 RT5xx/6xx 工作流程明确地写入加密的应用程序和OTFAD 密钥块。现场更新程序必须重现兼容的结果,或者使用其他经过验证的安装方案,同时还要考虑受保护的地址范围和密钥。RT600 OTFAD 参考文档描述了读取期间加密闪存的解密;SPT 配置过程不应被视为 Zephyr 运行时更新写入器的实现。- https://www.nxp.com/docs/en/training-reference-material/RT600_Security_Architecture_sb.pdf XIP 与加载到 RAM:由于您的目标具体是使用 OTFAD 保护存储在外部闪存中的应用程序,我将使用加密的 XIP 作为第一个网络安全概念验证。SPT 文档用于启动 RT5xx/6xx 的工作流程。这是对启动实验的建议,而不是声称加密的 XIP 使 Zephyr DFU 集成变得容易。Load-to-RAM 也是 RT5xx/6xx 镜像的一种有据可查的配置方式,但这并不能消除保护存储镜像和设计安全更新路径的必要性。我无法证实这两种方案都是适用于您的 SDK 版本的交钥匙、工作负载较低的 Zephyr 解决方案。 关于示例和串行恢复:我还没有找到经过验证的RT685 Zephyr 示例,该示例结合了 OTFAD、MCUboot 和 SMP/串行恢复加密更新,适用于 nxp-v4.4.1.1 。 fsl_otfad.h 标头表明存在驱动程序接口;但它并未表明 RT685 MCUboot 恢复或闪存安装路径集成了该接口。NXP 的加密 XIP 和 MCUboot文档描述了加密 XIP 扩展,但其列出的OTFAD 示例板是 RT1152/RT1160/RT1170,而不是 RT685 。我不认为它的串行恢复或安装行为会延续到这个板上。这方面我还需要和团队确认一下。 如需具体的参考资料,请使用SPT 26.09,“RT5xx/6xx 设备工作流程 → 使用影子寄存器启动 OTFAD 加密映像”来建立加密启动基线。同时,利用AN13478,在 i.MX RT600 上实现 FOTA ,研究 NXP 的 RT600 签名加密更新方法。该应用笔记并非Zephyr SMP 示例,因此剩余的工作是将其加密映像安装方法与您的 Zephyr/M​​CUboot 插槽布局和选择的更新路径相协调。   对于此板,我会分别验证签名组合映像 DFU 和 SPT 生成的 OTFAD XIP,然后将加密现场安装(包括任何串行恢复支持)视为一项集成任务,需要进行单独的测试。   祝你有美好的一天, 坎 ------------------------------------------------------------------------------- 笔记: - 如果此回复解答了您的问题,请点击“标记为正确答案”按钮。谢谢你! - 我们会持续关注帖子,从最后一条回复发出后持续7周,之后的回复将被忽略。 如果您之后有相关问题,请另开新帖并引用已关闭的帖子。 ------------------------------------------------------------------------------- Re: Secure DFU on RT600 嗨,Kan, 目前这些信息足够我消化了,我会把它标记为解决方案。如果团队对 R T685 MCUboot 恢复与 OTFAD的功能有任何更新,请通知我。 非常感谢您提供的详细信息!祝你今天也过得愉快! 岳
View full article
S32G3 BSP 48.0.0におけるリセットシーケンスとA53ロックステップブートフローに関する説明 NXP技術サポートチームへ、 私はS32G378A EVB3とLinux BSP 48.0.0を使っています。まずCortex-M7を起動し、M7ソフトウェアでCortex-A53ロックステップモードを有効にし、その後Cortex-A53でLinuxを起動するのが目標です。 BSPはconf/local.confに以下の機能を追加することでm7boot機能をサポートしています。 DISTRO_FEATURES:append = " m7boot" 次に、以下のコマンドでイメージを再構築します。 Bitbake FSL-image-車載 その後、生成された.sdcardを書きますイメージをSDカードに保存し、そこからボードを起動します。 しかし、実際のリセットと起動の手順について、より詳しい説明が必要です。 質問1:電源投入後のリセット状態は何ですか? LinuxがすでにCortex-A53上でインストールされ、動作しているとします。その後、ボードをシャットダウンまたは電源オフにし、m7bootを使用してBSPを再構築し、新しいイメージをSDカードに書き込み、ボードの電源を再びオンにします。 フル電源サイクル後、ハードウェアとBootROMによってリセットされたCortex-M7およびCortex-A53コアまたはリセットドメインはどれですか? BootROMは、IVTブートターゲットに基づいてM7_0を自動的に起動し、A53をリセット状態に維持しますか? M7ソフトウェアがLockstepを有効にするまでA53がリセット状態のままになるようにするために、追加のリセット設定が必要ですか? 質問2:m7bootは具体的にどのようなことを自動的に行うのですか? m7bootを有効にし、BSPを再構築し、生成されたSDカードイメージを書き込んだ後: BSPは、A53ロックステップを有効にするM7ファームウェアを自動的に提供および実行しますか? このファームウェアはA53をリセットしたままにし、A53_GPR06[CA53_LOCKSTEP_EN]を設定してからA53をリリースしてLinuxを起動するのでしょうか? それとも、これらの手順を実行するために、M7ファームウェアを別途変更、構築、または展開する必要があるのでしょうか? どの部分がBSPによって自動的に実行され、どの部分がユーザーの実装を必要とするのかを明確にしてください。 質問3:Lockstepを有効にしてA53を起動するために必要な実行時シーケンスは何ですか? 電源投入直後から始まる、想定される正確な手順を教えていただけると幸いです。 基板の電源投入とBootROMの実行。 IVTによるブートターゲットとしてM7_0の選択。 M7ファームウェアの起動。 ロックステップの設定中は、A53をリセット状態に保ってください。 Lockstepの設定が完了した後に、A53を解放または起動する。 A53でLinuxをロックステップモードで起動します。 特に、M7はロックステップを有効にした後、どのようにA53を解放または起動するのでしょうか?この手順を実行するのは、どのドキュメント化されたレジスタ、API、またはファームウェア機能ですか? この一連の動作は通常の起動時に一度で完了するのでしょうか、それともLockstepを有効にした後にボードのリセットまたは2回目の起動が必要になるのでしょうか? 質問4:2回目以降の起動時に何が起こりますか? LinuxがA53でロックステップモードで動いたら、ボードをシャットダウンまたは電源オフして再度電源を入れると: 毎回の起動時に、M7ファースト、ロックステップ構成、A53起動のシーケンスが自動的に実行されますか? ロックステップの設定は、ウォームリセット後も保持されますか、それともM7で再度設定する必要がありますか? コールドオン、ウォームリセット、ソフトウェア再起動の違いを考慮に入れる必要がありますか? 私の目標は、ブートローダーを手動で起動したり、ボードを二度リセットしたりすることなく、毎回の起動時にこれを自動的に実現することです。 S32G378A EVB3の関連するBSP 48.0.0のソースコード参照、設定ファイル、そして文書化されたリセット/起動手順を教えていただけますか? よろしくお願いいたします。 Re: Clarification on Reset Sequence and A53 Lockstep Boot Flow with S32G3 BSP 48.0.0 こんにちは、トアン お返事ありがとうございます。これらの内容があなたの役に立てば幸いです。 質問1:電源投入後のリセット状態は何ですか? >>>BootROMはIVTブート構成ワードのBOOT_TARGETに基づいてアプリケーションコアを選択します。「m7boot」の場合、BootROMはイメージ内のIVTを使用してM7を起動します。M7アプリケーションはその後、A53 Lockstepを構成し、A53 core0の起動を担当します。 質問2:m7bootは具体的にどのようなことを自動的に行うのですか? >>>YoctoのDISTRO_FEATURES:append = "m7boot"を使うと、 m7-sampleプロジェクトは自動的にダウンロードされます。これはM7ファームウェアです。 このアプリケーションには、パーティションの有効化、A53コアの有効化、a53_entry_pointアドレスの設定、そしてパーティションを有効にする前のロックステップ設定など、いくつかの機能が含まれています。以下の図のようにパーティションを有効にします。 https://github.com/nxp-auto-linux/m7-sample/blob/release/bsp48.0/src/main.c   質問3:Lockstepを有効にしてA53を起動するために必要な実行時シーケンスは何ですか? 電源投入直後から始まる、想定される正確な手順を教えていただけると幸いです。 基板の電源投入とBootROMの実行。 IVTによるブートターゲットとしてM7_0の選択。 M7ファームウェアの起動。 ロックステップの設定中は、A53をリセット状態に保ってください。 Lockstepの設定が完了した後に、A53を解放または起動する。 A53でLinuxをロックステップモードで起動します。 特に、M7はロックステップを有効にした後、どのようにA53を解放または起動するのでしょうか?この手順を実行するのは、どのドキュメント化されたレジスタ、API、またはファームウェア機能ですか? この一連の動作は通常の起動時に一度で完了するのでしょうか、それともLockstepを有効にした後にボードのリセットまたは2回目の起動が必要になるのでしょうか? >>>上記の理解は、YoctoのDISTRO_FEATURES:append = "m7boot"に関して基本的に正しいです。理論的には、m7サンプルはこれらのタスクを完了するのに役立ってきた。 S32G2RM.pdfの第32章「モードエントリモジュール(MC_ME)」は、「ロックステップを有効にした後、M7でA53を解放または開始する方法」に役立ちます。 質問4:2回目以降の起動時に何が起こりますか? >>>このリンクを参照してM7bootのソースコードを確認できます。 https://github.com/nxp-auto-linux/m7-sample/tree/release/bsp46.0 m7-sampleによると、M7bootは起動のたびにLockstepモードを設定します。 BR ジョーイ Re: Clarification on Reset Sequence and A53 Lockstep Boot Flow with S32G3 BSP 48.0.0 こんにちは、ジョーイ。 ご返信ありがとうございます。 私たちの計画は、S32G3のLinux BSP 48.0.0のドキュメントに従い、Yoctoを使ってS32G399A EVB3用のLinuxイメージを構築し、それをSDカードにデプロイすることです。 まずCortex-M7を起動し、A53リセットドメインがリセットされている間にM7ソフトウェアを使ってCortex-A53ロックステップモードを有効にする予定です。Lockstepの設定が完了すると、Cortex-A53がLinuxの起動用にリリースされます。 Cortex-M7を使ってアプリケーションを実行するつもりはありません。M7の唯一の目的は、Linuxが始まる前にA53ロックステップモードを有効にするための初期化を行うことです。 よろしくお願いします、 トアン Re: Clarification on Reset Sequence and A53 Lockstep Boot Flow with S32G3 BSP 48.0.0 こんにちは、トアン お問い合わせいただきありがとうございます。 あなたのCASEは受け取りましたので、確認を手伝います。 Yoctoでは、「DISTRO_FEATURES:append = 'm7boot'」の行が、Cortex-M7の起動プロセスを便利に示し、ロックステップ操作モードを有効にする例を提供しています。 あなたのプロジェクトのS32G378のブートプロセスについて教えていただけますか?M7コアの使用を検討されていますか?また、プロジェクトにおいて、ブートローダーを使用してM7コアとA53コアを起動することを検討してみてはいかがでしょうか? BR ジョーイ Re: Clarification on Reset Sequence and A53 Lockstep Boot Flow with S32G3 BSP 48.0.0 こんにちは、ジョーイ。 サポートありがとうございます。感謝しています。最後にもう一つだけ質問させてください 私の唯一の目的はA53 Lockstepを有効にすることなので、デフォルトのm7-sampleがすでにLockstepの有効化とA53 core0の再起動に対応しているか確認していただけますか?これにより、Linuxは追加のファームウェア変更なしでLockstepモードで動作します。 ご確認いただきありがとうございます。 よろしくお願いします、 トアン Re: Clarification on Reset Sequence and A53 Lockstep Boot Flow with S32G3 BSP 48.0.0 こんにちは、トアン お問い合わせいただきありがとうございます。 私の唯一の目的はA53 Lockstepを有効にすることなので、デフォルトのm7-sampleがすでにLockstepの有効化とA53 core0の再起動に対応しているか確認していただけますか?これにより、Linuxは追加のファームウェア変更なしでLockstepモードで動作します。 >>>はい、m7-sampleの起動アプリケーションはあなたの言う通りに動作します。主な機能はロックステップ/パーティション/A53コアを有効にすることで、RMマニュアルの説明に従って以下の図に対応しています。 M7-sample/src/main.c at release/bsp48.0 ·nxp-車載-Linux/m7-sample ·GitHub 1. ロックステップ/パーティションを有効にする 2.コアを有効にする また、Linuxアプリケーションでロックステップ機能を確認することもできます。 この情報がお役に立てば幸いです。他に質問があればいつでもお問い合わせください。 BR ジョーイ Re: Clarification on Reset Sequence and A53 Lockstep Boot Flow with S32G3 BSP 48.0.0 こんにちは、ジョーイ。 ご協力とご質問へのご回答、誠にありがとうございました。皆さんのサポートに本当に感謝しています。 FUTUREも質問があれば、また助けをCAN求めることを願っています。 改めてありがとうございました! Re: Clarification on Reset Sequence and A53 Lockstep Boot Flow with S32G3 BSP 48.0.0 こんにちは、トアン お役に立てて嬉しいです! 他に質問があればいつでもお問い合わせください! BR ジョーイ
View full article
FS2400 INIT_CRC_NOK_I Under frequent power cycling(power on/off) conditions, the INIT_CRC_NOK_I flag of the FS2400 was detected. In this situation, I read the FS_I_XXX registers, and the contents are consistent with the data I wrote during the INIT phase. In addition, the fault error count did not increase and remained at 0. Could you help me confirm whether this is a false alarm and whether this situation can be left untreated? Re: FS2400 INIT_CRC_NOK_I Hi, The INIT_CRC_NOK_I flag is set when the FS2400's cyclic CRC check mechanism detects a mismatch between the CRC it recalculates over the INIT registers every 5 ms and the value stored in the FS_CRC register. This is a genuine safety monitoring function and should not be dismissed without understanding its root cause. The fact that you can read the FS_I_XXX registers back and find the values consistent with what you wrote does not rule out a CRC mismatch — the most common cause in this scenario is that the MCU writes the INIT registers correctly but does not compute and store the correct CRC in FS_CRC before closing the INIT phase (i.e. before the first correct watchdog refresh). Please verify the following: 1. CRC computation: The 8-bit CRC must be computed over the concatenation of the following register bit-fields (in this order): FS_I_OVUV_CFG1[15:0] FS_I_OVUV_CFG2[15:0] FS_I_ERRMON_LIMP0_CFG[15:0] FS_I_FSSM_CFG[15:4] FS_I_WD_CFG[15:7] The polynomial to apply is: x⁸ + x⁴ + x³ + x² + 1 (same as the SPI CRC). 2. CRC registration: The MCU must write the computed CRC into FS_CRC before the INIT phase is closed (i.e. before the first correct watchdog refresh). If any INIT register is modified after the CRC has been written, the CRC must be recomputed and rewritten. 3. Fault error counter clarification: We note that you mention the fault error count remained at 0. Please be aware that, per the device datasheet, the fault error counter starts at 1 after a power-on reset (POR), not 0. INIT_CRC_NOK increments this counter by +1 each time it is triggered. Could you confirm which register and field you are reading for this value? If the counter remains at 1 (the POR-reset value) across power cycles, this would suggest the flag is being observed very early in the power-on sequence, possibly before the counter has had time to accumulate. We would appreciate clarification on the exact timing of when you observe the flag relative to the INIT phase completion. 4. Power cycling consideration: The INIT phase is always re-entered from POR (full power-down and power-up). The cyclic CRC check only activates in Normal mode after the INIT phase is closed. If the INIT_CRC_NOK_I flag is being observed very shortly after INIT closes, this strongly points to the FS_CRC register value not matching the current INIT register content at the time of the first 5 ms check. BRs, Tomas
View full article
RCCU, FCCU, and Lockstep Diagnostic Data Flow on S32G3 Dear NXP, Based on my understanding, RCCU detects Lockstep mismatches and reports errors to FCCU, which handles fault management and may provide diagnostic information through the Linux kernel log (dmesg). However, the BSP documentation describes this process only at a high level. Could you please provide more specific implementation guidance for the S32G378A with Linux BSP 48.0.0? Available diagnostic data: What types of data can be collected from RCCU and FCCU, such as error status, fault source, error type, or fault context? What information is actually available in hardware, and what can be reported through Linux dmesg? End-to-end data flow: What is the exact flow from a Lockstep mismatch being detected by RCCU, through FCCU fault handling, to Linux kernel reporting? Which registers, interrupts, drivers, or software components are involved? Source code and implementation: Which source files, device drivers, device-tree entries, or configuration files need to be modified or enabled in BSP 48.0.0 to collect and report this information? Does NXP provide an existing GitHub repository, reference implementation, or sample code demonstrating the complete flow? Lockstep input and output: What does the Lockstep mechanism actually compare as its input? Is the input generated internally by the redundant A53 execution paths, or must software configure or load any input data? Where is the relevant configuration performed, and what diagnostic output can software retrieve when a mismatch occurs? Please provide the relevant Reference Manual sections, source-code references, and a concrete implementation workflow, as the current BSP documentation does not explain these details sufficiently. Re: RCCU, FCCU, and Lockstep Diagnostic Data Flow on S32G3 Thank you for your reply. I would like to ask one more question. The Linux BSP 48.0.0 User Manual describes FCCU configuration using Device Tree properties such as `nxp,ncf_fault_list` and `nxp,ncf_actions`. Could you please clarify which source file we should modify to apply this configuration? After saving the changes, will they take effect through the Device Tree, or do we also need to modify the FCCU driver? If possible, please provide a simple example for S32G378A-EVB3. Best regards, Toan Re: RCCU, FCCU, and Lockstep Diagnostic Data Flow on S32G3 Hello, @Toan  Thanks for the post 1. The FCCU provides a hardware interface to collect faults when a failure is detected in the device, it is hardware behavior, different fault number would reflect different failure, you may refer the fault map file attached in S32G3 RM. The Linux FCCU driver in BSP48 allows updating the selected list of Non-Critical Faults handled in FCCU and selecting one of the supported NCF actions using device tree, if the reaction set is an alarm, then the alarm information is printed in the kernel’s log if the corresponding failure occurred. 2. When RCCU detected the issue, the FCCU will record it and then execute the actions set by the user, for example, if alarm is set as the action, then the information could be found in the kernel log, the Linux FCCU driver, DTS, FCCU alarm interrupt handler would be involved. 3. The corresponding information could be obtained from the Chapter 6 of BSP48 UM. 4.  In the lockstep mode, one cluster is considered the main cluster and the second cluster is considered the checker cluster. From a software perspective, the two clusters operate as a single cluster in the lockstep mode. Cortex-A53 Cluster0 is the main execution cluster, where Cortex-A53 Cluster1 follows execution of Cortex-A53 Cluster0. Equivalent operation of replicated resources is supervised by comparators (RCCU) on all functional signals leaving the cluster for the rest of the MCU. Any operational deviations between the supervised signals causes the FCCU to be notified of the discrepancy. In S32G3 A53 Lockstep mode, software does not need to provide or load input data for the Lockstep comparison. The comparison is performed internally by the hardware during normal A53 execution and is transparent to application software. Software mainly configures the Lockstep operating mode, rather than the comparison data. Software can set the corresponding action for the fault. If a mismatch is detected, it is reported through the RCCU/FCCU safety fault mechanism and the relevant actions would be executed. BR Chenyin
View full article
Clarification on Reset Sequence and A53 Lockstep Boot Flow with S32G3 BSP 48.0.0 Dear NXP Technical Support Team, I am working with the S32G378A EVB3 and Linux BSP 48.0.0. My goal is to boot Cortex-M7 first, enable Cortex-A53 Lockstep mode from M7 software, and then start Linux on Cortex-A53. I understand that the BSP supports the m7boot feature by adding the following to conf/local.conf: DISTRO_FEATURES:append = " m7boot" Then rebuilding the image with: bitbake fsl-image-auto After that, I would write the generated .sdcard image to the SD card and boot the board from it. However, I need clarification on the actual reset and startup sequence. Question 1: What is the reset state after power-up? Suppose Linux is already installed and running on Cortex-A53. I then shut down or power off the board, rebuild the BSP with m7boot, write the new image to the SD card, and power on the board again. After a full power cycle, which Cortex-M7 and Cortex-A53 cores or reset domains are held in reset by the hardware and BootROM? Does the BootROM automatically start M7_0 based on the IVT boot target, while keeping A53 in reset? Is any additional reset configuration required to ensure that A53 remains in reset until M7 software has enabled Lockstep? Question 2: What exactly does m7boot do automatically? After enabling m7boot, rebuilding the BSP, and writing the generated SD-card image: Does the BSP automatically provide and execute the M7 firmware that enables A53 Lockstep? Does this firmware keep A53 in reset, configure A53_GPR06[CA53_LOCKSTEP_EN], and then release A53 to boot Linux? Or must I separately modify, build, or deploy M7 firmware to implement these steps? Please clarify which parts are performed automatically by the BSP and which parts require user implementation. Question 3: What is the required runtime sequence to enable Lockstep and start A53? I would appreciate the exact expected sequence, starting from a cold power-on: Board power-up and BootROM execution. IVT selection of M7_0 as the boot target. M7 firmware startup. Keeping A53 in reset while configuring Lockstep. Releasing or starting A53 after Lockstep has been configured. Booting Linux on A53 in Lockstep mode. In particular, how does M7 release or start A53 after enabling Lockstep? Which documented register, API, or firmware function performs this step? Does this sequence happen during one normal boot, or is a board reset or second boot required after enabling Lockstep? Question 4: What happens on subsequent boots? Once Linux is running on A53 in Lockstep mode, if I shut down or power off the board and power it on again: Does the same M7-first, Lockstep-configuration, and A53-startup sequence run automatically on every boot? Is Lockstep configuration retained across a warm reset, or must M7 configure it again? Are there any differences between a cold power-on, a warm reset, and a software reboot that I need to account for? My goal is to achieve this automatically on every boot, without manually entering a bootloader or resetting the board a second time. Could you please provide the relevant BSP 48.0.0 source-code references, configuration files, and documented reset/startup sequence for the S32G378A EVB3? Best regards, Re: Clarification on Reset Sequence and A53 Lockstep Boot Flow with S32G3 BSP 48.0.0 Hi, Toan Thank you for your reply. Hope these contents can help you.  Question 1: What is the reset state after power-up? >>>The BootROM selects the application core based on the BOOT_TARGET in the IVT Boot Configuration Word. For "m7boot", the BootROM initiates the M7 using the IVT in the image. The M7 application then configures the A53 Lockstep and is responsible for starting the A53 core0. Question 2: What exactly does m7boot do automatically? >>>Using the DISTRO_FEATURES:append = " m7boot" in Yocto,   m7-sample project will be downloaded automatically, this is the M7 firmware. This application includes several functions, such as enabling partition, enabling A53 core, setting the a53_entry_point address, and lockstep setting before enabling the partition as the following picture. https://github.com/nxp-auto-linux/m7-sample/blob/release/bsp48.0/src/main.c   Question 3: What is the required runtime sequence to enable Lockstep and start A53? I would appreciate the exact expected sequence, starting from a cold power-on: Board power-up and BootROM execution. IVT selection of M7_0 as the boot target. M7 firmware startup. Keeping A53 in reset while configuring Lockstep. Releasing or starting A53 after Lockstep has been configured. Booting Linux on A53 in Lockstep mode. In particular, how does M7 release or start A53 after enabling Lockstep? Which documented register, API, or firmware function performs this step? Does this sequence happen during one normal boot, or is a board reset or second boot required after enabling Lockstep? >>>Your above understanding is basically correct for the DISTRO_FEATURES:append = " m7boot" in Yocto. Theoretically speaking, the m7-sample has helped to complete these tasks. Regarding the S32G2RM.pdf of Chapter 32 Mode Entry Module (MC_ME) is useful for "how does M7 release or start A53 after enabling Lockstep" Question 4: What happens on subsequent boots? >>>You can refer to this link to check the M7boot source code. https://github.com/nxp-auto-linux/m7-sample/tree/release/bsp46.0 According to the m7-sample, M7boot will set the Lockstep mode at each booting. BR Joey Re: Clarification on Reset Sequence and A53 Lockstep Boot Flow with S32G3 BSP 48.0.0 Hi Joey, Thank you for your response. Our plan is to follow the S32G3 Linux BSP 48.0.0 documentation and use Yocto to build the Linux image for the S32G399A EVB3, then deploy it to an SD card. We intend to boot Cortex-M7 first and use M7 software to enable Cortex-A53 Lockstep mode while the A53 reset domain is held in reset. After Lockstep is configured, Cortex-A53 will be released to boot Linux. We do not intend to use Cortex-M7 to run our application. Our only purpose for M7 is to perform the necessary initialization to enable A53 Lockstep mode before Linux starts. Best regards, Toan Re: Clarification on Reset Sequence and A53 Lockstep Boot Flow with S32G3 BSP 48.0.0 Hi,Toan Thank you for contacting us. I have received your case and will help you to check it. In Yocto, the "DISTRO_FEATURES:append = 'm7boot'" line provides an example that conveniently demonstrates the booting process for the Cortex-M7, and enables the lockstep operation mode. Could you tell me what the boot process for the S32G378 in your project? Do you consider using the M7 core? And have your project consider using the Bootloader to start the M7 core and the A53 core?  BR Joey Re: Clarification on Reset Sequence and A53 Lockstep Boot Flow with S32G3 BSP 48.0.0 Hi Joey, Thank you for your support, im appreciate , i wanna ask 1 more last question Since my only objective is to enable A53 Lockstep, could you please confirm that the default m7-sample already handles enabling Lockstep and restarting A53 core0, allowing Linux to run in Lockstep mode without any additional firmware modifications? Thank you for your confirmation. Best regards, Toan Re: Clarification on Reset Sequence and A53 Lockstep Boot Flow with S32G3 BSP 48.0.0 Hi,Toan Thank you for contacting us. Since my only objective is to enable A53 Lockstep, could you please confirm that the default m7-sample already handles enabling Lockstep and restarting A53 core0, allowing Linux to run in Lockstep mode without any additional firmware modifications? >>>Yes, the m7-sample boot application does this work what you said, the mainly function includes to enable lockstep/Partition/A53 Core, it is corresponded with the description in the RM manual as the following picture. m7-sample/src/main.c at release/bsp48.0 · nxp-auto-linux/m7-sample · GitHub 1.Enable Lockstep/Partition 2.Enable Core Also, you can try to check your lockstep function in your Linux application.  Hope this information can help you; you can contact us at any time if you have other question. BR Joey Re: Clarification on Reset Sequence and A53 Lockstep Boot Flow with S32G3 BSP 48.0.0 Hi Joey, Thank you very much for your help and for answering my questions. I really appreciate your support. If I have any further questions in the future, I hope I can ask for your help again. Thank you again! Re: Clarification on Reset Sequence and A53 Lockstep Boot Flow with S32G3 BSP 48.0.0 Hi,Toan I am glad to help you! You can contact us at any time if you have other question! BR Joey
View full article
FS2400 INIT_CRC_NOK_I 頻繁な電源サイクル(電源オン/オフ)条件下で、FS2400のINIT_CRC_NOK_Iフラグが検出されました。この状況では、FS_I_XXXレジスタを読み取ったところ、その内容はINITフェーズ中に書き込んだデータと一致していました。さらに、故障エラー数は増加せず、0のままでした。これが誤報かどうか、またこの状況を放置してもよいのか、確認を手伝ってもらえますか? Re: FS2400 INIT_CRC_NOK_I こんにちは、 INIT_CRC_NOK_Iフラグは、FS2400の周期的CRCチェック機構が、5msごとにINITレジスタで再計算したCRCとFS_CRCレジスタに格納されている値との間に不一致を検出した場合に設定されます。これは真のセーフティ監視機能であり、その根本原因を理解しずに軽視すべきではありません。 FS_I_XXXレジスタを読み返して、あなたが書いた値と一致する結果が得られるという事実は、CRCの不一致を排除するものではありません。このシナリオで最も一般的な原因は、MCUがINITレジスタを正しく書き込むが、INITフェーズを閉じる前に正しいCRCをFS_CRCに計算・保存しないことです(すなわち、最初の正しいウォッチドッグ更新の前に)。以下の点をご確認ください。 1. CRC計算:8ビットCRCは、以下のレジスタビットフィールドの連結(この順序で)に対して計算する必要があります。 FS_I_OVUV_CFG1[15:0] FS_I_OVUV_CFG2[15:0] FS_I_ERRMON_LIMP0_CFG[15:0] FS_I_FSSM_CFG[15:4] FS_I_WD_CFG[15:7] 適用する多項式は、x⁸ + x⁴ + x³ + x² + 1 です(SPI CRC と同じです)。 2. CRC登録:MCUはINITフェーズが終了する前に計算されたCRCをFS_CRCに書き込みなければなりません(すなわち最初の正しいウォッチドッグ更新の前に)。CRCが書き込まれた後にINITレジスタが変更された場合、CRCを再計算して書き直す必要があります。 3. 障害エラーカウンタに関する補足説明:障害エラーカウントが0のままだったとのことですが、デバイスのデータシートによると、障害エラーカウンタは電源投入リセット(POR)後に0ではなく1から開始します。INIT_CRC_NOKはトリガーされるたびにこのカウンタを+1ずつ増加させます。この値をどのレジスタとフィールドで読み取っているのか確認してもらえますか?電源投入サイクルを経てもカウンタが1(PORリセット値)のままである場合、これは電源投入シーケンスの非常に早い段階でフラグが観測されていることを示唆しており、おそらくカウンタが蓄積される前に観測されていると考えられます。INITフェーズの完了からどのタイミングでフラグが観測されたのか、正確なタイミングについてご説明いただけると幸いです。 4. 電源サイクルに関する考慮事項: INIT フェーズは常に POR (完全な電源オフと電源オン) から再開されます。周期的なCRCチェックは、INITフェーズが終了した後の通常モードでのみ有効になります。INIT_CRC_NOK_IフラグがINIT終了直後に観測される場合、これは最初の5msチェック時点でFS_CRCレジスタの値が現在のINITレジスタの内容と一致していないことを強く示唆しています。 BRs、トーマス
View full article
S32G3におけるRCCU、FCCU、およびLockstep診断データフロー 親愛なるNXPへ、 私の理解では、RCCUはLockstepのミスマッチを検出し、FCCUにエラーを報告します。FCCUは故障マネジメントを担当し、Linuxカーネルログ(dmesg)を通じて診断情報を提供することがあります。しかし、BSPのドキュメントではこのプロセスが大まかに説明されているに過ぎません。 Linux BSP 48.0.0のS32G378Aに関するより具体的な実装ガイダンスを教えていただけますか? 利用可能な診断データ:RCCUおよびFCCUから収集可能なデータの種類には、エラーの状態、故障の発生源、エラータイプ、故障のコンテキストなどがありますか?ハードウェアで実際に利用可能な情報と、Linux dmesgを通じて報告できる情報は何でしょうか? エンドツーエンドのデータフロー:RCCUによるロックステップ不一致の検出から、FCCUの故障処理、Linuxカーネル報告までの正確な流れはどのようなものなのでしょうか?どのレジスタ、割り込み、ドライバ、またはソフトウェアコンポーネントが関与しているのでしょうか? ソースコードと実装:BSP 48.0.0でこれらの情報を収集・報告するために、どのソースファイル、デバイスドライバ、デバイスツリーエントリ、または設定ファイルを変更する必要があるのか?NXPは、完全なフローを示す既存のGitHubリポジトリ、リファレンス実装、またはサンプルコードを提供していますか? ロックステップの入出力:ロックステップ機構は、入力として実際に何を比較するのでしょうか?入力は冗長なA53実行パスによって内部的に生成されるのか、それとも入力データをソフトウェアで設定または読み込む必要があるのか?関連する構成はどこで行われ、不一致が発生した場合にソフトウェアが取得できる診断出力は何でしょうか? 関連するリファレンスマニュアルのセクション、ソースコード参照、具体的な実装ワークフローをご提供ください。現在のBSPドキュメントではこれらの詳細が十分に説明されていません。 Re: RCCU, FCCU, and Lockstep Diagnostic Data Flow on S32G3 お返事ありがとうございます。もう一つ質問させてください。 Linux BSP 48.0.0ユーザーマニュアルでは、デバイスツリーのプロパティ(例えば「nxp,ncf_fault_list」や「nxp,ncf_actions)」を用いてFCCUの設定を説明しています。 この設定を適用するためにどのソースファイルを修正すべきか、教えていただけますか?変更を保存した後、デバイスツリーを通じて有効になりますか?それともFCCUドライバも修正する必要がありますか? 可能であれば、S32G378A-EVB3の簡単な例を示してください。 よろしくお願いします、 トアン Re: RCCU, FCCU, and Lockstep Diagnostic Data Flow on S32G3 こんにちは、 @Toan 投稿ありがとうございます 1.FCCUは、デバイスで故障が検出された際に故障を収集するためのハードウェアインターフェースを提供しています。これはハードウェアの挙動であり、異なる故障番号は異なる故障を反映します。S32G3 RMに添付された故障マップファイルを参照してください。BSP48のLinux FCCUドライバは、FCCUで処理された非重大障害の選択リストを更新し、デバイスツリーを使ってサポートされるNCFアクションのいずれかを選択できます。反応セットがアラームの場合、アラーム情報は 対応する障害が発生した場合、カーネルのログに印刷されました。 2. RCCUが問題を検出すると、FCCUはそれを記録し、ユーザーが設定したアクションを実行します。例えば、アラームがアクションに設定されている場合、その情報はカーネルログに記載されており、Linux FCCUドライバ、DTS、FCCUアラーム割り込みハンドラが関与します。 3. 対応する情報はBSP48 UM第6章から入手可能。 4. ロックステップモードでは、1つのクラスタがメインクラスタ、2つ目のクラスタがチェッカークラスタとみなされます。ソフトウェアの観点からは、2つのクラスタはロックステップモードで単一のクラスタとして動作します。Cortex-A53 Cluster0はメインの実行クラスタであり、Cortex-A53 Cluster1はCortex-A53 Cluster0の実行後に続きます。複製されたリソースの同等な動作は、クラスタから出るすべての機能信号に対してコンパレータ(RCCU)によって監督され、残りのMCUに送られます。監督信号間の運用上の逸脱があれば、FCCUに不一致が通知されます。 S32G3 A53ロックステップモードでは、ソフトウェアはロックステップ比較のために入力データを提供または読み込む必要がありません。比較は通常のA53実行中にハードウェア内部で行われ、アプリケーションソフトウェアには透過的です。 ソフトウェアは主に比較データではなく、ロックステップの動作モードを設定します。ソフトウェアは故障に対応するアクションを設定できます。不一致が検出された場合、それはRCCU/FCCUのセーフティ故障メカニズムを通じて報告され、関連する対応が実行されます。 BR チェイン
View full article
S32G3上的RCCU、FCCU和锁步诊断数据流 尊敬的恩智浦: 据我了解,RCCU 会检测锁步不匹配并将错误报告给 FCCU,FCCU 会处理故障管理,并可能通过 Linux 内核日志 (dmesg) 提供诊断信息。然而,电路板支持包文档仅从宏观层面描述了这一过程。 能否提供针对 Linux 电路板支持包。 48.0.0 的 S32G378A 的更具体的实施指导? 可用的诊断数据:可以从 RCCU 和 FCCU 收集哪些类型的数据,例如错误状态、故障源、错误类型或故障上下文?硬件中实际有哪些信息可用,Linux dmesg 可以报告哪些信息? 端到端数据流:从 RCCU 检测到锁步不匹配,到 FCCU 故障处理,再到 Linux 内核报告,整个流程是怎样的?涉及哪些寄存器、中断、驱动程序或软件组件? 源代码和实现:在电路板支持包 48.0.0 中需要修改或启用哪些源文件、设备驱动程序、设备树条目或配置文件才能收集和报告此信息?NXP 是否提供现有的 GitHub 代码库、参考实现或示例代码来演示完整的流程? 锁步输入和输出:锁步机制的输入实际上比较的是什么?输入是由冗余的 A53 执行路径内部生成的,还是必须由软件配置或加载任何输入数据?相关配置在哪里执行?当出现不匹配情况时,软件可以检索到哪些诊断输出? 请提供相关的参考手册章节、源代码参考以及具体的实现流程,因为当前的电路板支持包文档对这些细节的解释不够充分。 Re: RCCU, FCCU, and Lockstep Diagnostic Data Flow on S32G3 感谢你的回复。我还想问最后一个问题。 Linux 电路板支持包。 48.0.0 用户手册描述了使用设备树属性(例如 `nxp,ncf_fault_list` 和 `nxp,ncf_actions`)配置 FCCU。 请问我们需要修改哪个源文件才能应用此配置?保存更改后,更改会通过设备树生效吗?还是我们还需要修改 FCCU 驱动程序? 如果可以,请提供 S32G378A-EVB3 的简单示例。 此致, 托安 Re: RCCU, FCCU, and Lockstep Diagnostic Data Flow on S32G3 你好, @Toan 谢谢你的帖子 1.FCCU 提供硬件接口来收集设备中检测到的故障信息,这是硬件行为,不同的故障编号反映不同的故障,您可以参考 S32G3 RM 中附加的故障映射文件。BSP48 中的 Linux FCCU 驱动程序允许更新 FCCU 中处理的非关键故障的选定列表,并使用设备树选择支持的 NCF 操作之一。如果响应集是警报,则警报信息为: 如果发生相应的故障,则将其打印在内核日志中。 2. 当 RCCU 检测到问题时,FCCU 将记录该问题,然后执行用户设置的操作,例如,如果将报警设置为操作,则可以在内核日志中找到相关信息,Linux FCCU 驱动程序、DTS、FCCU 报警中断处理程序将参与其中。 3. 相关信息可从 BSP48 UM 第 6 章中获得。 4.在锁步模式下,一个集群被视为主集群,另一个集群被视为校验集群。从软件角度来看,这两个集群在锁步模式下作为一个集群运行。Cortex-A53 Cluster0 是主执行集群,Cortex-A53 Cluster1 紧随其后执行。所有离开集群并发送到 MCU 其他部分的功能信号都由比较器 (RCCU) 进行监控,以确保复制资源的等效操作。任何被监控信号之间的操作偏差都会触发 FCCU 收到差异通知。 在 S32G3 A53 锁步模式下,软件不需要提供或加载锁步比较的输入数据。该比较由硬件在 A53 正常执行期间内部执行,对应用程序软件是透明的。 软件主要配置 Lockstep 操作模式,而不是对比数据。软件可以针对故障设置相应的操作。如果检测到不匹配,则会通过 RCCU/FCCU 功能安全故障机制报告,并执行相关操作。 BR 陈银
View full article
[MCX A153] ADC模块基础知识及使用方法(日语博客) 本文介绍了MCX A153中安装的ADC(模数转换器)模块的基本用法。首先通过ADC的应用示例,总结了其主要功能、模块结构和使用注意事项,然后介绍了如何使用SDK示例代码进行设备初始化,以及如何使用DMA传输ADC转换结果。 本文旨在帮助您了解在应用中使用 MCX A153 ADC 所需的基本原理,使您能够实现从 ADC 转换的初始设置到利用 DMA 进行高效数据传输的一切操作。   目录 1. 应用中的常见用例 1.1 主要用途 1.2 使用示例 2. MCX A153 ADC模块的主要功能和框图 2.1 概述 2.2 主要特点 2.3 方框图 3. 注意事项和限制 4. ADC 示例代码(设备初始化) 4.1 示例代码概述 4.2 打开 SDK 示例项目 4.3 宏观定义 4.4 设备初始化 5. 使用MCX A153 DMA传输AD转换值 5.1 与ADC相关的代码 5.2 DMA相关代码 总结 1. 应用中的常见用例 ADC 将来自传感器、电位器等的模拟信号(连续变化的电压)转换为微控制器可用于计算的数字值(数值)。 1.1 主要用途 将电位器输入的模拟电压值转换为数字值。 电位器安装在伺服电机(例如无线电遥控车辆中使用的伺服电机)的轴上,通过输出的变化来检测电机的旋转角度。 将来自各种传感器的模拟信号转换为数字值。 它通过转换来自加速度计的模拟信号来检测物体的倾斜度。例如,这可以用于检测智能手机的方向。 环境温度是通过转换温度传感器的模拟信号来测量的。   1.2 使用示例(以下示例旨在说明一般概念,因此省略了细节。) 电位器应用示例:         2. 主要功能和框图   2.1 概述 MCX A153 配备了一个 16 位模数转换器 (ADC)。ADC 是一种将模拟电压转换为数字值的电路。   2.2 主要特点 配备一个逐次逼近型AD转换器单元。 支持 16 位或 12 位分辨率和单端输入(更高的分辨率可以更精细地表示输入电压)。 已安装频道数量(因套餐而异): 64 引脚 LQFP 封装:24 通道,48 引脚 LQFP 封装:16 通道,48 引脚 HVQFN 封装:18 通道,32 引脚 HVQFN 封装:9 通道 采样率(每秒数据转换次数) 16 位模式:最高 3.2 Msps,12 位模式:最高 4 Msps 可以设置采样时间。 可在微控制器的低功耗模式下运行。 支持四种触发源(软件或硬件触发)。 七个命令缓冲区可以扫描连续通道。 支持比较功能(自动比较较小、较大、在范围内、超出范围,保存为匹配项等) 配备八个用于存储转换结果数据的FIFO,具有水印和溢出检测功能。 支持中断、DMA 和轮询。 校准功能 内置温度传感器,带专用输入通道   2.3 方框图 MCX A153 参考手册(MCXAP64M96FS3RM) 图 165。ADC框图摘录   SDK示例代码使用示例(连接电位器)     3. MCX A153 ADC 模块 本节解释了在使用 MCX A153 的 ADC 之前需要考虑的重要事项和限制。 16 位模式下的速度降低 MCX A153 的 ADC 支持两种模式:16 位(ENOB16:16 位有效分辨率)和 12 位(ENOB12:12 位有效分辨率)。但是,16 位模式的采样率低于 12 位模式。 (摘自MCX A153 数据手册表 34) 校准执行时间 校准请求和执行必须在复位或上电期间进行。此外,必须先配置时钟源和频率才能执行校准。 转化率结果的平均值 ADC模块可以在保存转换结果之前,对同一通道的多个结果进行平均。当CMDHa[AVGS]位域设置为非零值时,硬件平均功能启用。该功能可用于任何转换模式,并减轻软件计算平均值的负担。 4. AD转换示例代码 4.1 示例代码概述 主序列执行时,将进行设备初始化。设备初始化首先设置时钟、配置外部接口,并选择要连接到接口的外设。之后,初始化外设(ADC、UART)并启用中断。初始化过程完成后,循环内会设置一个软件触发信号以启动ADC转换,并在控制台上显示ADC转换值和转换次数。 硬件方面,我们将使用MCX A153开发板“FRDM-MCXA153”。   4.2 在 VS Code 中打开 ADC 示例项目的步骤 4.2.1 准备 VS Code 和扩展程序 安装 VS Code。 在扩展视图(Ctrl+Shift+X)中搜索“MCUXpresso for VS Code”并安装。 MCUXpresso 图标将出现在左侧的活动栏中。点击该图标即可打开快速入门面板。   4.2.2 安装依赖工具 在快速启动面板中运行“打开 MCUXpresso 安装程序”。 请选择并安装以下工具。 Arm GNU 工具链 CMake / Ninja Python / 西方 Git LinkServer(MCU-Link 的调试探针) SDK相关工具 完成后,重启 VS Code。   4.2.3整合 SDK 存储库 在快速入门面板中单击“导入存储库”。 选择“远程”作为数据导入源。   指定目标文件夹。路径应简短,且不得包含日文字符或空格。 您可以通过勾选“我同意”并按下“导入”按钮来导入存储库。   4.2.4 导入样品 在“快速入门面板”中,单击“从存储库导入示例”。 设置方法如下:   您可以点击“导入”按钮导入项目。 项目 设置值 存储库 步骤 3 中导入的 SDK (frdm_mcxa153) 工具链 Arm GNU 工具链 木板 frdmmcxa153 (FRDM-MCXA153) 模板 driver_examples → lpadc → interrupt(lpadc_interrupt) 地点 项目保存位置 姓名 可选(默认值为 lpadc_interrupt) 4.3 宏观定义 这是 ADC 功能的宏定义代码(摘自 lpadc\interrupt\app.h)。 请调整输入通道、分辨率设置和参考电压源,以匹配您的实际电路设计和预期用途。 定义 //(lpadc\interrupt\app.hから抜粋) /******************************************************************************/ #define DEMO_LPADC_BASE ADC0 //ADCのinstance、ベースアドレス、MCX A153は1個 ADCしかない #define DEMO_LPADC_IRQn ADC0_IRQn #define DEMO_LPADC_IRQ_HANDLER_FUNC ADC0_IRQHandler #define DEMO_LPADC_USER_CHANNEL 0U //チャンネル番号 #define DEMO_LPADC_USER_CMDID 1U //コマンドID #define DEMO_LPADC_VREF_SOURCE kLPADC_ReferenceVoltageAlt3 //参考電圧ソース #define DEMO_LPADC_DO_OFFSET_CALIBRATION true //オフセットキャリブレーションの利用可否 #define DEMO_LPADC_USE_HIGH_RESOLUTION true //高分解能の利用可否 与ADC相关的变量 变量 //(lpadc\interrupt\lpadc_interrupt.cから抜粋) volatile bool g_LpadcConversionCompletedFlag = false; volatile uint32_t g_LpadcInterruptCounter = 0U; lpadc_conv_result_t g_LpadcResultConfigStruct; #if (defined(DEMO_LPADC_USE_HIGH_RESOLUTION) && DEMO_LPADC_USE_HIGH_RESOLUTION) //高分解能 const uint32_t g_LpadcFullRange = 65536U; const uint32_t g_LpadcResultShift = 0U; #else //低分解能 const uint32_t g_LpadcFullRange = 4096U; const uint32_t g_LpadcResultShift = 3U; #endif /* DEMO_LPADC_USE_HIGH_RESOLUTION */ ADC 配置结构的默认值(详情请参见 fsl_lpadc.c),转换结果的平均值。 //(lpadc\interrupt\lpadc_interrupt.cから抜粋) LPADC_GetDefaultConfig(&mLpadcConfigStruct); mLpadcConfigStruct.enableAnalogPreliminary = true; //ADCアナログ回路は事前に有効化され、起動遅延なしで変換を実行する準備 #if defined(DEMO_LPADC_VREF_SOURCE) mLpadcConfigStruct.referenceVoltageSource = DEMO_LPADC_VREF_SOURCE; //参考電圧ソース #endif /* DEMO_LPADC_VREF_SOURCE */ #if defined(FSL_FEATURE_LPADC_HAS_CTRL_CAL_AVGS) && FSL_FEATURE_LPADC_HAS_CTRL_CAL_AVGS mLpadcConfigStruct.conversionAverageMode = kLPADC_ConversionAverage; //変換結果平均化設定、平均しない/2回の平均/4回の平均/8回の平均/16回の平均....1024回の平均化選択可能 #endif     4.4 设备初始化     时钟分频比初始化 CLOCK_SetClockDiv 函数处理 ADC 外设使用的时钟分频设置。 //(lpadc\interrupt\hardware_init.cから抜粋) /* Attach peripheral clock */ CLOCK_SetClockDiv(kCLOCK_DivADC0, 1u); div_name:选择枚举定义的分频器。 值:除法比率 *以下代码是从 fsl_clock.c 开始的驱动程序部分,不建议用户修改。 //(fsl_clock.cから抜粋) void CLOCK_SetClockDiv(clock_div_name_t div_name, uint32_t value) { volatile uint32_t *pDivCtrl = (volatile uint32_t *)(MRCC0_BASE + (uint32_t)div_name); assert(div_name <= kCLOCK_DivMax); /* Unlock clock configuration */ SYSCON->CLKUNLOCK &= ~SYSCON_CLKUNLOCK_UNLOCK_MASK; /* halt and reset clock dividers */ *pDivCtrl = 0x3UL << 29U; if (value == 0U) /*!< halt */ { *pDivCtrl |= (1UL << 30U); } else { *pDivCtrl = (value - 1U); } /* Freeze clock configuration */ SYSCON->CLKUNLOCK |= SYSCON_CLKUNLOCK_UNLOCK_MASK; }   时钟选择 CLOCK_AttachClk 选择 ADC 外设要使用的四个时钟源之一。 驱动程序通过将 `clock_attach_id_t` 结构中定义的值作为参数传递给 `void CLOCK_AttachClk(clock_attach_id_t connection)` 函数来配置连接。 //(fsl_clock.hから抜粋) kFRO12M_to_ADC0 = CLK_ATTACH_MUX(kCLOCK_SelADC0, 0U), /* Attach FRO12M to ADC0. */ kFRO_HF_to_ADC0 = CLK_ATTACH_MUX(kCLOCK_SelADC0, 1U), /* Attach FRO_HF to ADC0. */ kCLK_IN_to_ADC0 = CLK_ATTACH_MUX(kCLOCK_SelADC0, 3U), /* Attach CLK_IN to ADC0. */ kCLK_1M_to_ADC0 = CLK_ATTACH_MUX(kCLOCK_SelADC0, 5U), /* Attach CLK_1M to ADC0. */ kNONE_to_ADC0 = CLK_ATTACH_MUX(kCLOCK_SelADC0, 7U), /* Attach NONE to ADC0. */ //(lpadc\interrupt\hardware_init.cから抜粋) CLOCK_AttachClk(kFRO12M_to_ADC0); 以下函数是 SDK 提供的驱动程序部分的一部分,从 fsl_clock.c 开始,不建议用户修改它们。 //(fsl_clock.hから抜粋) void CLOCK_AttachClk(clock_attach_id_t connection) { const uint32_t reg_offset = CLK_ATTACH_REG_OFFSET(connection); const uint32_t clk_sel = CLK_ATTACH_CLK_SEL(connection); if (kNONE_to_NONE != connection) { CLOCK_SetClockSelect((clock_select_name_t)reg_offset, clk_sel); } } //(fsl_clock.hから抜粋) void CLOCK_SetClockSelect(clock_select_name_t sel_name, uint32_t value) { volatile uint32_t *pClkCtrl = (volatile uint32_t *)(MRCC0_BASE + (uint32_t)sel_name); assert(sel_name <= kCLOCK_SelMax); if (sel_name == kCLOCK_SelSCGSCS) { SCG0->RCCR = (SCG0->RCCR & ~(SCG_RCCR_SCS_MASK)) | SCG_RCCR_SCS(value); while ((SCG0->CSR & SCG_CSR_SCS_MASK) != SCG_CSR_SCS(value)) { } } else { /* Unlock clock configuration */ SYSCON->CLKUNLOCK &= ~SYSCON_CLKUNLOCK_UNLOCK_MASK; *pClkCtrl = value; /* Freeze clock configuration */ SYSCON->CLKUNLOCK |= SYSCON_CLKUNLOCK_UNLOCK_MASK; } } 关于电路板初始化功能 时钟将被初始化。   引脚初始化 调用 InitPins() 函数,并处理 pin_mux.c 文件。pin_mux.c 文件由 NXP 的 MCUXPresso 使用。可以使用集成到 IDE 中的引脚配置工具来覆盖此设置。 //(lpadc\interrupt\hardware_init.cから抜粋) BOARD_InitPins(); BOARD_InitPins() 函数执行四个操作。 启用外围时钟 禁用外围设备复位 外部引脚对引脚和外设连接(MUX 配置)-> 结构体参数设置 在登记簿中写入 3   初始化启动时钟 MCX A153 支持中等驱动模式和标准驱动模式。这两种模式分别对应 1.0 V 和 1.1 V 的 VDD_CORE 电压,以及 48 MHz 或 96 MHz 的 rfo_hf 时钟频率。切换模式需要外部电源,并且需要配置与电压相关的寄存器,例如 LDO。 //(lpadc\interrupt\hardware_init.cから抜粋) BOARD_InitBootClocks(); 时钟是通过与工作频率相对应的寄存器设置功能来设置的。 //(fsl_clock.cから抜粋) void BOARD_InitBootClocks(void) { BOARD_BootClockFRO96M(); }     初始化调试端口 //(lpadc\interrupt\hardware_init.cから抜粋) BOARD_InitDebugConsole();   //(board.cから抜粋) void BOARD_InitDebugConsole(void) { /* attach 12 MHz clock to LPUART0 (debug console) */ CLOCK_SetClockDiv(kCLOCK_DivLPUART0, 1u); CLOCK_AttachClk(BOARD_DEBUG_UART_CLK_ATTACH); RESET_PeripheralReset(BOARD_DEBUG_UART_RST); DbgConsole_Init(BOARD_DEBUG_UART_INSTANCE, BOARD_DEBUG_UART_BAUDRATE, BOARD_DEBUG_UART_TYPE, BOARD_DEBUG_UART_CLK_FREQ); }   应用程序初始化 ADC 初始化在 LPADC_Init(DEMO_LPADC_BASE, &mLpadcConfigStruct) 函数中处理。LPADC_Init() 函数位于 fsl_lpadc.c 的驱动程序部分。 DEMO_LPADC_BASE:0x400A_F000 -> ADC 的起始地址 定义结构表并配置ADC。 typedef struct {} lpadc_config_t 姓名 属性 说明 lpadc_config_t 类型 LPADC配置参数信息 启用休眠模式 布尔值 ADC转换期间的操作设置基于模式 转换平均模式 lpadc_conversion_average_mode_t 与自动校准相关的设置 启用模拟初步 布尔值 ADC启动前设置 上电延迟 uint32_t ADC电路的稳定时间 参考电压源 lpadc_reference_voltage_source_t 参考电压源 功率级别模式 lpadc_power_level_mode_t 电源配置选择 触发优先级策略 lpadc_trigger_priority_policy_t 如何处理高利润触发因素 启用会话暂停 布尔值 设置 AD 转换执行间隔。 对话暂停延迟 uint32_t 命令序列期间的暂停时间 先进先出水印 uint32_t FIFO 中数据点数量的阈值设置。 //(lpadc\interrupt\lpadc_interrupt.cから抜粋) LPADC_Init(DEMO_LPADC_BASE, &mLpadcConfigStruct); //(fsl_lpadc.cから抜粋) void LPADC_Init(ADC_Type *base, const lpadc_config_t *config) { /* 省略 */ base->CTRL |= ADC_CTRL_CAL_AVGS(config->conversionAverageMode); /* 省略 */ }   关于ADC校准   在使用模数转换器 (ADC) 之前,需要进行校准以校正转换结果中包含的偏移误差和其他因素,从而提高模数转换的精度。 校准过程大致可分为以下两个阶段: 设置校准模式和条件。 执行校准并将校正值应用于ADC。   在默认示例中,ADC 校准在执行完 LPADC_Init() 之后、AD 转换开始之前进行。首先,使用 LPADC_SetOffsetCalibrationMode() 在相应的器件上设置偏移校准模式。然后,如果启用了 DEMO_LPADC_DO_OFFSET_CALIBRATION,则执行 LPADC_DoOffsetCalibration();否则,使用预先通过 LPADC_SetOffsetValue() 设置的偏移值。 此外,如果启用了相应的函数宏,则在延迟 1 µs 或更长时间后执行 LPADC_DoAutoCalibration() 函数。该函数用于校准增益误差和线性误差。仅当器件支持的功能宏启用时,才会编译相应的进程。 以下是LPADC校准模式的设置。 //(lpadc\interrupt\lpadc_interrupt.cから抜粋) /* Request LPADC calibration. */ #if defined(FSL_FEATURE_LPADC_HAS_CTRL_CALOFSMODE) && FSL_FEATURE_LPADC_HAS_CTRL_CALOFSMODE LPADC_SetOffsetCalibrationMode(DEMO_LPADC_BASE, DEMO_LPADC_OFFSET_CALIBRATION_MODE); #endif /* FSL_FEATURE_LPADC_HAS_CTRL_CALOFSMODE */     执行偏移校准 //(lpadc\interrupt\lpadc_interrupt.cから抜粋) #if defined(FSL_FEATURE_LPADC_HAS_CTRL_CALOFS) && \ FSL_FEATURE_LPADC_HAS_CTRL_CALOFS #if defined(DEMO_LPADC_DO_OFFSET_CALIBRATION) && \ DEMO_LPADC_DO_OFFSET_CALIBRATION L PADC_DoOffsetCalibration(DEMO_LPADC_BASE); //キャリブレーションを実行しない場合 #else /* Update OFSTRIM register manually. */   5. MCX A153 DMA 为什么ADC转换要使用DMA传输? 当仅通过软件处理ADC采集的数据时,CPU需要监控ADC转换的完成情况,读取转换结果并将其写入内存。对于单次ADC转换而言,这并非主要问题;但当以固定间隔连续采样或处理多个输入通道时,此过程会反复发生。因此,CPU的处理负载会增加,从而可能减少可用于其他应用程序处理的时间。 解决此问题的一种方法是使用 DMA(直接内存访问)传输 ADC 转换结果。使用 DMA,ADC 转换完成后,转换结果可以自动传输到内存。换句话说,由于从获取 ADC 转换结果到将其存储到内存的过程可以由硬件处理,因此可以减少 CPU 执行的数据传输处理量,从而降低软件的处理负载。 鉴于以上原因,ADC和DMA的组合配置常用于需要连续模数转换和高速数据采集的应用中。本文将首先介绍ADC的基本初始化方法,然后介绍如何使用MCX A153通过DMA将ADC转换结果传输到存储器。 使用DMA进行AD转换值传输概述 AD转换后的数据存储在ADC外设的缓冲区中。ADC无需每次都手动读取数据,而是可以通过DMA传输数据。例如,程序可以修改为连续执行五次AD转换,然后通过DMA将数据保存到RAM缓冲区,并在控制台上显示平均值、最小值和最大值。 使用DMA传输AD转换值的步骤 我们将修改ADC示例代码,添加DMA处理功能。 DMA 激活是通过来自 ADC 的 DMA 请求信号执行的。 使用 DMA,将 ADC FIFO 值(5 次转换)复制到 RAM,并向 CPU 发出中断通知。 CPU 在 DMA 传输完成后,在主循环中取平均值,并将最小值、最大值和平均值显示在控制台上。     防范措施 要添加 DMA 代码,您需要将 DMA 驱动程序头文件和源代码添加到您的项目中。最简单的方法是从 MCUXpresso IDE 创建一个示例 DMA 代码 (frdmmcxa153_edma3_memory_to_memory_transfer) 并复制它。只需从 drivers 目录复制以下文件即可。 fsl_edma_core.h fsl_edma_soc.c fsl_edma_soc.h fsl_edma.c fsl_edma.h   5.1 与ADC相关的代码修改和新增   代码修改步骤 ADC转换完成后发生的中断已被禁用。 添加了ADC配置。 设置为连续执行 5 次 AD 转换。 启用DMA请求 将先进先出 (FIFO) 水印设置为 4。 增加了处理功能,以获取 DMA 传输值的平均值、最小值和最大值,并将它们输出到控制台。     1. 当ADC转换完成后,禁用中断。 由于中断使能寄存器 (IE) 是通过 LPADC_EnableInterrupts() 函数和 kLPADC_FIFOWatermarkInterruptEnable 启用的,因此我们将注释掉这一行。 // LPADC_EnableInterrupts(DEMO_LPADC_BASE, kLPADC_FIFOWatermarkInterruptEnable);   2. 添加ADC配置 ADC 配置为循环 5 次(= 5 次 AD 转换)。 mLpadcCommandConfigStruct.loopCount = 4 //loopCount +1回の変換 启用DMA请求 //178行目 LPADC_EnableFIFOWatermarkDMA(DEMO_LPADC_BASE, 1); // 1でDMA Requestがイネーブル     3. 将先进先出 (FIFO) 中的水印级别数设置为 4。 // 33行目 /* ++ ADCのマクロ */ #define FIFO0WatermarkLEVEL (4) //108行目 mLpadcConfigStruct.FIFOWatermark = FIFO0WatermarkLEVEL;   4. 增加了处理,以获取 DMA 传输的值和控制台输出的平均值、最小值和最大值。 uint32_t adc_values[5] = {0}; PRINTF("Please press any key to get user channel's ADC value.\r\n"); while(1) { GETCHAR(); EXAMPLE_DMA_BASEADDR->CH[0].CH_CSR = DMA_CH_CSR_ERQ(1); EXAMPLE_DMA_BASEADDR->CH[0].TCD_DLAST_SGA = -0x14; LPADC_DoSoftwareTrigger(DEMO_LPADC_BASE, 1U); /* 1U is trigger0 mask. */ while (!g_Transfer_Done) { /* DMA転送終了割り込み待ち */ } g_Transfer_Done = false; uint16_t min=adc_values[0]; uint16_t max=adc_values[0]; uint32_t sum=0; for(uint32_t i=0; i<5; i++) { if(max < (0x0000FFFF & adc_values[i])) max = adc_values[i]; if(min > (0x0000FFFF & adc_values[i])) min = adc_values[i]; sum += 0x0000FFFF & adc_values[i]; } PRINTF("ADC Min: %d, Max: %d, ave: %d\r\n", min, max, sum/5); for(size_t i=0; i<5; i++) { adc_values[i] = 0; } sum = 0; }   5.2 添加DMA相关代码   代码添加政策 包含头文件 添加了与DMA相关的宏。 DMA配置和初始化 DMA传输配置 DMA传输完成中断处理   1. 包含标题 // 10行目 #include "fsl_debug_console.h" #include "pin_mux.h" #include "clock_config.h" #include "board.h" #include "fsl_lpadc.h" /* ++ */ #include "fsl_edma.h" // DMAドライバヘッダファイルの追加 #include "fsl_clock.h" #include "fsl_reset.h"   2. 添加与 DMA 相关的宏。 // 32行目 #define EXAMPLE_DMA_BASEADDR DMA0 #define DEMO_DMA_CHANNEL_0 0U #define APP_DMA_IRQ DMA_CH0_IRQn #define APP_DMA_IRQ_HANDLER DMA_CH0_IRQHandler     3. DMA配置 // 197行目 edma_transfer_config_t transferConfig; edma_config_t userConfig; // 203行目 RESET_PeripheralReset(kDMA_RST_SHIFT_RSTn); /* Configure EDMA channel for one shot transfer */ EDMA_GetDefaultConfig(&userConfig); EDMA_Init(EXAMPLE_DMA_BASEADDR, &userConfig);     4. DMA传输配置 // 209行目 EDMA_PrepareTransfer(&transferConfig, (void *)0x400AF300, // eDMA transfer source address. sizeof(uint32_t), // eDMA transfer source address width(bytes) (void *)adc_values, // eDMA transfer destination address sizeof(&adc_values), // eDMA transfer destination address width(bytes) sizeof(adc_values), // eDMA transfer bytes per channel request sizeof(adc_values), // eDMA transfer bytes to be transferred kEDMA_PeripheralToMemory // eDMA transfer type ); EDMA_SetTransferConfig(EXAMPLE_DMA_BASEADDR, DEMO_DMA_CHANNEL_0, &transferConfig, NULL); EDMA_SetChannelMux(EXAMPLE_DMA_BASEADDR, DEMO_DMA_CHANNEL_0, kDma0RequestMuxAdc0FifoRequest); EnableIRQ(APP_DMA_IRQ); EDMA_EnableChannelInterrupts(EXAMPLE_DMA_BASEADDR, DEMO_DMA_CHANNEL_0, kEDMA_MajorInterruptEnable); 在用软件触发启动软件 ADC 之前,添加 EDMA_TriggerChannelStart() 以在 DMA 通道 0 上触发中断。当 DMA 中断标志被清除时,DMA 触发的中断将被禁用,因此该处理是在 ADC 的软件触发之前添加的。 // 242行目 while(1) { GETCHAR(); EDMA_TriggerChannelStart(EXAMPLE_DMA_BASEADDR, DEMO_DMA_CHANNEL_0); EXAMPLE_DMA_BASEADDR->CH[0].TCD_DLAST_SGA = -0x14; LPADC_DoSoftwareTrigger(DEMO_LPADC_BASE, 1U); /* 1U is trigger0 mask. */ while (!g_Transfer_Done) { /* DMA転送終了割り込み待ち */ } g_Transfer_Done = false;   5. DMA传输完成中断处理 void APP_DMA_IRQ_HANDLER(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; } } 概括: 本文介绍了MCX A153 ADC的基本功能和注意事项,以及如何使用VS Code SDK的ADC示例项目进行初始化和转换。阅读本文后半部分,您将看到一些配置示例和代码流程,这些内容在实际开发中非常有用,涵盖了从使用ADC示例进行初始化和转换,到使用DMA自动传输转换结果等各个环节。(建议您先运行ADC示例并确认其运行正常,然后再添加DMA,这样更容易排查问题。) =========================​ 我们目前无法 回复 此帖子“ 评论”部分留下的评论。 对于由此造成的不便,我们深表歉意,但在进行咨询时,请参考“ NXP技术问题-如何联系我们(日语博客) ”。 (如果您已经是 恩智浦的 分销商或 与 恩智浦 有合作关系 ,您可以直接咨询您的代表。 ) 本文全面讲解了MCX A153中ADC(模数转换器)的基础知识,包括如何使用MCUXpresso SDK进行初始化,以及如何使用DMA自动传输转换结果。如果您是第一次使用ADC或DMA,建议您先阅读第1章和第2章,了解整体概念,然后再阅读第4章的示例代码和第5章的DMA设置,以便更好地理解。 ADC:一种将模拟信号(例如来自传感器的信号)转换为微控制器可以处理的数字值的功能。 DMA:一种无需经过 CPU 即可在外围设备和内存之间传输数据的功能。 SDK:包含软件开发所需的驱动程序和示例代码的开发工具包。 (阅读时间:30分钟) 通用微控制器 介绍 MCUXpresso IDE MCUXpresso SDK 日本博客
View full article
[MCX A153] Basics and Usage of the ADC Module (Japanese Blog) This article explains the basic usage of the ADC (Analog-to-Digital Converter) module installed in the MCX A153 . Starting with application examples using the ADC, it summarizes the main functions, block structure, and points to note when using it, and then introduces device initialization using SDK sample code and how to transfer ADC conversion results using DMA. This article aims to help you understand the fundamentals required when using the MCX A153 ADC in your applications, enabling you to implement everything from initial setup for ADC conversion to efficient data transfer utilizing DMA.   table of contents 1. Common use cases in applications 1.1 Main Uses 1.2 Usage example 2. Main functions and block diagram of the MCX A153 ADC module 2.1 Overview 2.2 Main Features 2.3 Block Diagram 3. Points to note and restrictions 4. ADC Sample Code (Device Initialization) 4.1 Overview of Sample Code 4.2 Opening the SDK Sample Project 4.3 Macro Definitions 4.4 Device Initialization 5. Transfer of AD conversion values using MCX A153 DMA 5.1 Code related to ADC 5.2 DMA-related code summary 1. Common use cases in applications An ADC converts analog signals (continuously changing voltages) input from sensors, potentiometers, etc., into digital values (numerical values) that a microcontroller can use for calculations. 1.1 Main Uses Converts the analog voltage value input from the potentiometer to a digital value. A potentiometer is attached to the shaft of a servo motor, such as those used in radio-controlled vehicles, to detect the angle of rotation of the motor from the change in output. Convert analog signals from various sensors into digital values. It detects the tilt of an object by converting analog signals from an accelerometer. This can be applied to detecting the orientation of a smartphone, for example. The ambient temperature is measured by converting the analog signal from the temperature sensor.   1.2 Usage Examples (These are examples illustrating the general concept, so details are omitted.) Examples of potentiometer usage:         2. Main Functions and Block Diagram   2.1 Overview The MCX A153 is equipped with a 16-bit analog-to-digital converter (ADC). An ADC is a circuit that converts analog voltages into digital values.   2.2 Main Features Equipped with one successive approximation AD converter unit. Supports 16-bit or 12-bit resolution and single-ended input (higher resolution allows for finer representation of input voltage). Number of channels installed (varies depending on the package): 64-pin LQFP: 24 channels, 48-pin LQFP: 16 channels, 48-pin HVQFN: 18 channels, 32-pin HVQFN: 9 channels Sampling rate (how many times per second the data can be converted) 16-bit mode: up to 3.2 Msps, 12-bit mode: up to 4 Msps Sample time can be set. Can operate in low-power mode of the microcontroller. Supports four trigger sources (software or hardware triggers). Seven command buffers enable scanning of consecutive channels. Supports compare function (automatically compares smaller, larger, within range, outside range, save as match, etc.) Equipped with eight FIFOs for conversion result data, featuring watermark and overflow detection functions. Supports interrupts, DMA, and polling. Calibration function Built-in temperature sensor with dedicated input channel   2.3 Block Diagram MCX A153 Reference Manual (MCXAP64M96FS3RM) Figure 165. Excerpt from ADC block diagram   Example of using SDK sample code (connecting a potentiometer)     3. MCX A153 ADC Module This section explains important points and limitations to consider before using the MCX A153's ADC. Speed reduction in 16-bit mode The MCX A153's ADC supports two modes: 16-bit (ENOB16: 16-bit effective resolution) and 12-bit (ENOB12: 12-bit effective resolution). However, the 16-bit mode has a lower sampling rate than the 12-bit mode. (Excerpt from MCX A153 DataSheet Table.34) Timing of calibration execution Calibration requests and execution must be performed during reset or power-on. Furthermore, the clock source and frequency must be configured before calibration can be performed. Averaging of conversion results The ADC module can average multiple results for the same channel before saving the conversion result. The hardware averaging function is enabled when the CMDHa[AVGS] bit field is set to a non-zero value. It can be used in any conversion mode and reduces the burden of calculating the average in software. 4. Sample code for AD conversion 4.1 Overview of Sample Code When the main sequence is executed, device initialization is performed. Device initialization begins with setting the clock, configuring the external terminals, and selecting the peripherals to connect to the terminals. After that, the peripherals (ADC, UART) are initialized and interrupts are enabled. After the initialization process, a software trigger is set within the loop to start ADC conversion, and the AD conversion value and the number of conversions are displayed on the console. For hardware, we will use the MCX A153 development board "FRDM-MCXA153".   4.2 Steps to open the ADC sample project in VS Code 4.2.1 Preparing VS Code and Extensions Install VS Code. Search for "MCUXpresso for VS Code" in the Extensions view (Ctrl+Shift+X) and install it. The MCUXpresso icon will appear in the activity bar on the left. Click it to open the QUICKSTART PANEL.   4.2.2 Installing Dependent Tools Run "Open MCUXpresso Installer" in the QUICKSTART PANEL. Select and install the following tool. Arm GNU Toolchain CMake / Ninja Python / West Git LinkServer (Debug probe for MCU-Link) SDK-related tools After completion, restart VS Code.   4.2.3Incorporating the SDK repository Click "Import Repository" in the QUICKSTART PANEL. Select "Remote" as the source for importing data.   Specify the destination folder. The path should be short and should not contain Japanese characters or spaces. You can import the repository by checking "I agree" and pressing the Import button.   4.2.4 Importing Samples In the QUICKSTART PANEL, click "Import Example from Repository". Set it as follows:   You can import the project by clicking the Import button. item Set value Repository The SDK (frdm_mcxa153) imported in step 3 Toolchain Arm GNU Toolchain Board frdmmcxa153 (FRDM-MCXA153) Template driver_examples → lpadc → interrupt(lpadc_interrupt) Location Project save location Name Optional (default is lpadc_interrupt) 4.3 Macro Definitions This is the macro definition code for the ADC's functions (excerpted from lpadc\interrupt\app.h). Please adjust the input channels, resolution settings, and reference voltage sources to match your actual circuit design and intended use. Definitions //(lpadc\interrupt\app.hから抜粋) /******************************************************************************/ #define DEMO_LPADC_BASE ADC0 //ADCのinstance、ベースアドレス、MCX A153は1個 ADCしかない #define DEMO_LPADC_IRQn ADC0_IRQn #define DEMO_LPADC_IRQ_HANDLER_FUNC ADC0_IRQHandler #define DEMO_LPADC_USER_CHANNEL 0U //チャンネル番号 #define DEMO_LPADC_USER_CMDID 1U //コマンドID #define DEMO_LPADC_VREF_SOURCE kLPADC_ReferenceVoltageAlt3 //参考電圧ソース #define DEMO_LPADC_DO_OFFSET_CALIBRATION true //オフセットキャリブレーションの利用可否 #define DEMO_LPADC_USE_HIGH_RESOLUTION true //高分解能の利用可否 Variables related to ADC Variables //(lpadc\interrupt\lpadc_interrupt.cから抜粋) volatile bool g_LpadcConversionCompletedFlag = false; volatile uint32_t g_LpadcInterruptCounter = 0U; lpadc_conv_result_t g_LpadcResultConfigStruct; #if (defined(DEMO_LPADC_USE_HIGH_RESOLUTION) && DEMO_LPADC_USE_HIGH_RESOLUTION) //高分解能 const uint32_t g_LpadcFullRange = 65536U; const uint32_t g_LpadcResultShift = 0U; #else //低分解能 const uint32_t g_LpadcFullRange = 4096U; const uint32_t g_LpadcResultShift = 3U; #endif /* DEMO_LPADC_USE_HIGH_RESOLUTION */ Defaulting of the ADC configuration structure (details can be found in fsl_lpadc.c), averaging of conversion results. //(lpadc\interrupt\lpadc_interrupt.cから抜粋) LPADC_GetDefaultConfig(&mLpadcConfigStruct); mLpadcConfigStruct.enableAnalogPreliminary = true; //ADCアナログ回路は事前に有効化され、起動遅延なしで変換を実行する準備 #if defined(DEMO_LPADC_VREF_SOURCE) mLpadcConfigStruct.referenceVoltageSource = DEMO_LPADC_VREF_SOURCE; //参考電圧ソース #endif /* DEMO_LPADC_VREF_SOURCE */ #if defined(FSL_FEATURE_LPADC_HAS_CTRL_CAL_AVGS) && FSL_FEATURE_LPADC_HAS_CTRL_CAL_AVGS mLpadcConfigStruct.conversionAverageMode = kLPADC_ConversionAverage; //変換結果平均化設定、平均しない/2回の平均/4回の平均/8回の平均/16回の平均....1024回の平均化選択可能 #endif     4.4 Device Initialization     Initialization of clock division ratio The CLOCK_SetClockDiv function handles the clock division settings used by the ADC peripheral. //(lpadc\interrupt\hardware_init.cから抜粋) /* Attach peripheral clock */ CLOCK_SetClockDiv(kCLOCK_DivADC0, 1u); div_name: Select a frequency divider defined by the enumeration. value: division ratio *The following code is the driver section starting with fsl_clock.c, and user modification is not recommended. //(fsl_clock.cから抜粋) void CLOCK_SetClockDiv(clock_div_name_t div_name, uint32_t value) { volatile uint32_t *pDivCtrl = (volatile uint32_t *)(MRCC0_BASE + (uint32_t)div_name); assert(div_name <= kCLOCK_DivMax); /* Unlock clock configuration */ SYSCON->CLKUNLOCK &= ~SYSCON_CLKUNLOCK_UNLOCK_MASK; /* halt and reset clock dividers */ *pDivCtrl = 0x3UL << 29U; if (value == 0U) /*!< halt */ { *pDivCtrl |= (1UL << 30U); } else { *pDivCtrl = (value - 1U); } /* Freeze clock configuration */ SYSCON->CLKUNLOCK |= SYSCON_CLKUNLOCK_UNLOCK_MASK; }   Clock selection CLOCK_AttachClk selects one of four clock sources to be used by the ADC peripheral. The driver configures the connection by passing a value defined in the `clock_attach_id_t` structure as an argument to the `void CLOCK_AttachClk(clock_attach_id_t connection)` function. //(fsl_clock.hから抜粋) kFRO12M_to_ADC0 = CLK_ATTACH_MUX(kCLOCK_SelADC0, 0U), /* Attach FRO12M to ADC0. */ kFRO_HF_to_ADC0 = CLK_ATTACH_MUX(kCLOCK_SelADC0, 1U), /* Attach FRO_HF to ADC0. */ kCLK_IN_to_ADC0 = CLK_ATTACH_MUX(kCLOCK_SelADC0, 3U), /* Attach CLK_IN to ADC0. */ kCLK_1M_to_ADC0 = CLK_ATTACH_MUX(kCLOCK_SelADC0, 5U), /* Attach CLK_1M to ADC0. */ kNONE_to_ADC0 = CLK_ATTACH_MUX(kCLOCK_SelADC0, 7U), /* Attach NONE to ADC0. */ //(lpadc\interrupt\hardware_init.cから抜粋) CLOCK_AttachClk(kFRO12M_to_ADC0); The following functions are part of the driver section provided by the SDK, starting with fsl_clock.c, and it is not recommended that users modify them. //(fsl_clock.hから抜粋) void CLOCK_AttachClk(clock_attach_id_t connection) { const uint32_t reg_offset = CLK_ATTACH_REG_OFFSET(connection); const uint32_t clk_sel = CLK_ATTACH_CLK_SEL(connection); if (kNONE_to_NONE != connection) { CLOCK_SetClockSelect((clock_select_name_t)reg_offset, clk_sel); } } //(fsl_clock.hから抜粋) void CLOCK_SetClockSelect(clock_select_name_t sel_name, uint32_t value) { volatile uint32_t *pClkCtrl = (volatile uint32_t *)(MRCC0_BASE + (uint32_t)sel_name); assert(sel_name <= kCLOCK_SelMax); if (sel_name == kCLOCK_SelSCGSCS) { SCG0->RCCR = (SCG0->RCCR & ~(SCG_RCCR_SCS_MASK)) | SCG_RCCR_SCS(value); while ((SCG0->CSR & SCG_CSR_SCS_MASK) != SCG_CSR_SCS(value)) { } } else { /* Unlock clock configuration */ SYSCON->CLKUNLOCK &= ~SYSCON_CLKUNLOCK_UNLOCK_MASK; *pClkCtrl = value; /* Freeze clock configuration */ SYSCON->CLKUNLOCK |= SYSCON_CLKUNLOCK_UNLOCK_MASK; } } Regarding the board initialization function The clock will be initialized.   Pin initialization The InitPins() function is called, and the pin_mux.c file is processed. The pin_mux.c file is used by NXP's MCUXPressoThis can be overridden using the Pin Config tool integrated into the IDE. //(lpadc\interrupt\hardware_init.cから抜粋) BOARD_InitPins(); The BOARD_InitPins() function performs four operations. Enable peripheral clock Disable peripheral reset External pin-to-pin and peripheral connection (MUX configuration) -> Parameter setting for the structure Write 3 to the register   Initializing the boot clock The MCX A153 supports Mid Drive Mode and Standard Drive Mode. These modes operate with VDD_CORE voltage levels of 1.0 V and 1.1 V, respectively, and with an rfo_hf clock of 48 MHz or 96 MHz. Switching modes requires external power supply and configuration of voltage-related registers such as the LDO. //(lpadc\interrupt\hardware_init.cから抜粋) BOARD_InitBootClocks(); The clock is set using a register setting function that corresponds to the operating frequency. //(fsl_clock.cから抜粋) void BOARD_InitBootClocks(void) { BOARD_BootClockFRO96M(); }     Initializing the debug port //(lpadc\interrupt\hardware_init.cから抜粋) BOARD_InitDebugConsole();   //(board.cから抜粋) void BOARD_InitDebugConsole(void) { /* attach 12 MHz clock to LPUART0 (debug console) */ CLOCK_SetClockDiv(kCLOCK_DivLPUART0, 1u); CLOCK_AttachClk(BOARD_DEBUG_UART_CLK_ATTACH); RESET_PeripheralReset(BOARD_DEBUG_UART_RST); DbgConsole_Init(BOARD_DEBUG_UART_INSTANCE, BOARD_DEBUG_UART_BAUDRATE, BOARD_DEBUG_UART_TYPE, BOARD_DEBUG_UART_CLK_FREQ); }   Application initialization ADC initialization is handled within the LPADC_Init(DEMO_LPADC_BASE, &mLpadcConfigStruct); function. The LPADC_Init() function is a function in the driver section of fsl_lpadc.c. DEMO_LPADC_BASE: 0x400A_F000 -> Starting address of the ADC Define the structure table and configure the ADC. typedef struct {} lpadc_config_t name attribute explanation lpadc_config_t type LPADC Configuration Parameter Information enableInDozeMode bool Operation settings based on mode during ADC conversion conversionAverageMode lpadc_conversion_average_mode_t Settings related to Auto Calibration enableAnalogPreliminary bool ADC pre-startup settings PowerUpDelay uint32_t Stabilization time of ADC circuit referenceVoltageSource lpadc_reference_voltage_source_t Source of reference voltage powerLevelMode lpadc_power_level_mode_t Power supply configuration selection triggerPriorityPolicy lpadc_trigger_priority_policy_t How to process high-profitability triggers EnableConvPause bool Setting the AD conversion execution interval. convPauseDelay uint32_t Pause time during command sequence FIFOWatermark uint32_t Threshold setting for the number of data points in FIFO //(lpadc\interrupt\lpadc_interrupt.cから抜粋) LPADC_Init(DEMO_LPADC_BASE, &mLpadcConfigStruct); //(fsl_lpadc.cから抜粋) void LPADC_Init(ADC_Type *base, const lpadc_config_t *config) { /* 省略 */ base->CTRL |= ADC_CTRL_CAL_AVGS(config->conversionAverageMode); /* 省略 */ }   About ADC calibration   Before using an ADC, calibration is performed to correct for offset errors and other factors included in the conversion result, thereby improving the accuracy of the AD conversion. The calibration process can be broadly divided into the following two stages: Set the calibration mode and conditions. Perform calibration and apply the correction values to the ADC.   In the default sample, ADC calibration is performed after LPADC_Init() is executed and before AD conversion begins. First, the offset calibration mode is set with LPADC_SetOffsetCalibrationMode() on the corresponding device. Then, if DEMO_LPADC_DO_OFFSET_CALIBRATION is enabled, LPADC_DoOffsetCalibration() is executed; otherwise, the offset value set in advance with LPADC_SetOffsetValue() is used. Furthermore, if the corresponding function macro is enabled, LPADC_DoAutoCalibration() is executed after a delay of 1 µs or more. This performs calibration of gain errors and linearity errors. Each process is compiled only if the function macro supported by the device is enabled. The following are the settings for the LPADC calibration mode. //(lpadc\interrupt\lpadc_interrupt.cから抜粋) /* Request LPADC calibration. */ #if defined(FSL_FEATURE_LPADC_HAS_CTRL_CALOFSMODE) && FSL_FEATURE_LPADC_HAS_CTRL_CALOFSMODE LPADC_SetOffsetCalibrationMode(DEMO_LPADC_BASE, DEMO_LPADC_OFFSET_CALIBRATION_MODE); #endif /* FSL_FEATURE_LPADC_HAS_CTRL_CALOFSMODE */     Performing offset calibration //(lpadc\interrupt\lpadc_interrupt.cから抜粋) #if defined(FSL_FEATURE_LPADC_HAS_CTRL_CALOFS) && \ FSL_FEATURE_LPADC_HAS_CTRL_CALOFS #if defined(DEMO_LPADC_DO_OFFSET_CALIBRATION) && \ DEMO_LPADC_DO_OFFSET_CALIBRATION L PADC_DoOffsetCalibration(DEMO_LPADC_BASE); //キャリブレーションを実行しない場合 #else /* Update OFSTRIM register manually. */   5. MCX A153 DMA Why use DMA transfer for ADC conversion? When processing data acquired by an ADC solely in software, the CPU needs to monitor the completion of the ADC conversion, read the conversion results, and write them to memory. This is not a major problem for a single AD conversion, but when sampling continuously at regular intervals or when handling multiple input channels, this process occurs repeatedly. As a result, the CPU processing load increases, potentially reducing the time available for other application processing. One way to solve this problem is to transfer the ADC conversion results using DMA (Direct Memory Access). Using DMA, the ADC conversion results can be automatically transferred to memory as soon as the ADC conversion is complete. In other words, since the process from acquiring the ADC conversion results to storing them in memory can be handled by hardware, the amount of data transfer processing performed by the CPU can be reduced, and the processing load on the software can be lowered. For these reasons, configurations combining ADC and DMA are often used in applications requiring continuous AD conversion and high-speed data acquisition. This article will first explain the basic initialization method of the ADC, and then introduce how to transfer the ADC conversion result to memory using DMA with the MCX A153. Overview of AD conversion value transfer using DMA The data after AD conversion is stored in a buffer within the ADC peripheral. Instead of reading the data manually each time, the ADC may trigger DMA to transfer the data. For example, the program will be modified to perform AD conversion five times consecutively, then save the data to a RAM buffer via DMA, and display the average, minimum, and maximum values on the console. Procedure for transferring AD conversion values using DMA We will modify the ADC sample code to add DMA processing. DMA activation is performed using a DMA Request signal from the ADC. Using DMA, the ADC FIFO values (for 5 conversions) are copied to RAM, and an interrupt is notified to the CPU. The CPU takes the average value within the main loop after the DMA transfer is complete and displays the min, max, and ave values to the console.     Precautions To add DMA code, you need to add the DMA driver header file and source code to your project. The easiest way to do this is to create a sample DMA code (frdmmcxa153_edma3_memory_to_memory_transfer) from the MCUXpresso IDE and copy it. Simply copy the following files from the drivers directory. fsl_edma_core.h fsl_edma_soc.c fsl_edma_soc.h fsl_edma.c fsl_edma.h   5.1 Code modifications and additions related to ADC   Code modification steps The interrupt that occurs when ADC conversion is complete has been disabled. Added ADC configuration. Setting to perform AD conversion 5 times consecutively. Enable DMA requests Set the FIFO watermark to 4. Added processing to obtain the average, minimum, and maximum values of the values transferred by DMA, and to output them to the console.     1. Disable interrupts when ADC conversion is complete. Since the Interrupt Enable Register (IE) is enabled using the LPADC_EnableInterrupts() function and kLPADC_FIFOWatermarkInterruptEnable, we will comment out this line. // LPADC_EnableInterrupts(DEMO_LPADC_BASE, kLPADC_FIFOWatermarkInterruptEnable);   2. Add ADC configuration The ADC is configured to loop 5 times (= 5 AD conversions). mLpadcCommandConfigStruct.loopCount = 4 //loopCount +1回の変換 Enable DMA requests //178行目 LPADC_EnableFIFOWatermarkDMA(DEMO_LPADC_BASE, 1); // 1でDMA Requestがイネーブル     3. Set the number of Watermark levels in the FIFO to 4. // 33行目 /* ++ ADCのマクロ */ #define FIFO0WatermarkLEVEL (4) //108行目 mLpadcConfigStruct.FIFOWatermark = FIFO0WatermarkLEVEL;   4. Added processing to obtain the average, minimum, and maximum values of the values transferred by DMA, and console output. uint32_t adc_values[5] = {0}; PRINTF("Please press any key to get user channel's ADC value.\r\n"); while(1) { GETCHAR(); EXAMPLE_DMA_BASEADDR->CH[0].CH_CSR = DMA_CH_CSR_ERQ(1); EXAMPLE_DMA_BASEADDR->CH[0].TCD_DLAST_SGA = -0x14; LPADC_DoSoftwareTrigger(DEMO_LPADC_BASE, 1U); /* 1U is trigger0 mask. */ while (!g_Transfer_Done) { /* DMA転送終了割り込み待ち */ } g_Transfer_Done = false; uint16_t min=adc_values[0]; uint16_t max=adc_values[0]; uint32_t sum=0; for(uint32_t i=0; i<5; i++) { if(max < (0x0000FFFF & adc_values[i])) max = adc_values[i]; if(min > (0x0000FFFF & adc_values[i])) min = adc_values[i]; sum += 0x0000FFFF & adc_values[i]; } PRINTF("ADC Min: %d, Max: %d, ave: %d\r\n", min, max, sum/5); for(size_t i=0; i<5; i++) { adc_values[i] = 0; } sum = 0; }   5.2 Adding DMA-related code   Code Addition Policy Include header files Added DMA-related macros. DMA configuration and initialization DMA transfer configuration DMA transfer completion interrupt handling   1. Include headers // 10行目 #include "fsl_debug_console.h" #include "pin_mux.h" #include "clock_config.h" #include "board.h" #include "fsl_lpadc.h" /* ++ */ #include "fsl_edma.h" // DMAドライバヘッダファイルの追加 #include "fsl_clock.h" #include "fsl_reset.h"   2. Add DMA-related macros. // 32行目 #define EXAMPLE_DMA_BASEADDR DMA0 #define DEMO_DMA_CHANNEL_0 0U #define APP_DMA_IRQ DMA_CH0_IRQn #define APP_DMA_IRQ_HANDLER DMA_CH0_IRQHandler     3. DMA Configuration // 197行目 edma_transfer_config_t transferConfig; edma_config_t userConfig; // 203行目 RESET_PeripheralReset(kDMA_RST_SHIFT_RSTn); /* Configure EDMA channel for one shot transfer */ EDMA_GetDefaultConfig(&userConfig); EDMA_Init(EXAMPLE_DMA_BASEADDR, &userConfig);     4. DMA transfer configuration // 209行目 EDMA_PrepareTransfer(&transferConfig, (void *)0x400AF300, // eDMA transfer source address. sizeof(uint32_t), // eDMA transfer source address width(bytes) (void *)adc_values, // eDMA transfer destination address sizeof(&adc_values), // eDMA transfer destination address width(bytes) sizeof(adc_values), // eDMA transfer bytes per channel request sizeof(adc_values), // eDMA transfer bytes to be transferred kEDMA_PeripheralToMemory // eDMA transfer type ); EDMA_SetTransferConfig(EXAMPLE_DMA_BASEADDR, DEMO_DMA_CHANNEL_0, &transferConfig, NULL); EDMA_SetChannelMux(EXAMPLE_DMA_BASEADDR, DEMO_DMA_CHANNEL_0, kDma0RequestMuxAdc0FifoRequest); EnableIRQ(APP_DMA_IRQ); EDMA_EnableChannelInterrupts(EXAMPLE_DMA_BASEADDR, DEMO_DMA_CHANNEL_0, kEDMA_MajorInterruptEnable); Before starting the software ADC with a software trigger, add EDMA_TriggerChannelStart() to trigger an interrupt on DMA channel 0. When the DMA interrupt flag is cleared, DMA-triggered interrupts are disabled, so this processing is added before the ADC's software trigger. // 242行目 while(1) { GETCHAR(); EDMA_TriggerChannelStart(EXAMPLE_DMA_BASEADDR, DEMO_DMA_CHANNEL_0); EXAMPLE_DMA_BASEADDR->CH[0].TCD_DLAST_SGA = -0x14; LPADC_DoSoftwareTrigger(DEMO_LPADC_BASE, 1U); /* 1U is trigger0 mask. */ while (!g_Transfer_Done) { /* DMA転送終了割り込み待ち */ } g_Transfer_Done = false;   5. DMA transfer completion interrupt handling void APP_DMA_IRQ_HANDLER(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; } } summary: This article explained the basic functions and points to note about the MCX A153 ADC, as well as the initialization and conversion process using the VS Code SDK's ADC sample project . Following the latter part of this article, you should be able to see configuration examples and code flows that will be useful in actual development, from initialization and conversion using the ADC sample to automatic transfer of conversion results using DMA. (It's easier to isolate problems if you first run the ADC sample and confirm its operation before adding DMA.) =========================​ 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 ask your representative directly.) This article explains everything from the basics of the ADC (analog-to-digital converter) in the MCX A153 , to initialization using the MCUXpresso SDK, and even automatic transfer of conversion results using DMA. If you are using ADC or DMA for the first time, it is recommended to first review the overall picture in Chapters 1 and 2, and then proceed to the sample code in Chapter 4 and the DMA settings in Chapter 5 for easier understanding. ADC: A function that converts analog signals, such as those from sensors, into digital values that can be handled by a microcontroller. DMA: A function that transfers data between peripherals and memory without going through the CPU. SDK: A development kit containing drivers and sample code necessary for software development. (Reading time: 30 minutes) General Purpose Microcontrollers Introduction MCUXpresso IDE MCUXpresso SDK Japanese Blog
View full article
[MCX A153] ADCモジュールの基本と使い方 (日本語ブログ)    この記事はMCX A153に搭載されたADC(Analog-to-Digital Converter)モジュールの基本的な使い方を説明します。ADCを利用したアプリケーション例から始め、主な機能、ブロック構成、使用時の注意点を整理したうえで、SDKサンプルコードを使ったデバイス初期化と、DMAによるADC変換結果の転送方法を紹介します。 この記事を読むことで、MCX A153のADCをアプリケーションで使用する際に必要となる基本事項を理解し、ADC変換を行うための初期設定から、DMAを活用した効率的なデータ転送までを実装できるようになることを目指します。   目次 1. アプリケーション上のよくある使用例        1.1 主な用途        1.2 使用例 2. MCX A153 ADCモジュールの主な機能とブロック図               2.1 概要               2.2 主な機能               2.3 ブロック図 3. 注意点、制限事項 4. ADCサンプルコード(デバイスの初期化)             4.1 サンプルコードの概要             4.2 SDKサンプルプロジェクトを開くまで             4.3 マクロ定義             4.4 デバイスの初期化 5. MCX A153 DMAを用いたAD変換値の転送           5.1 ADCに関するコード           5.2 DMAに関するコード まとめ 1. アプリケーション上のよくある使用例 ADCは、センサやポテンショメータなどから入力されたアナログ信号(連続的に変化する電圧)を、マイコンが計算に使えるデジタル値(数値)へ変換します。 1.1 主な用途 ポテンショメータから入力されたアナログの電圧値をデジタル値に変換 ポテンショメータをラジコンなどのサーボモータの軸に取り付けて、出力の変化からモータが回転した角度を検出する。 各種センサからのアナログ信号をデジタル値に変換 加速度センサからのアナログ信号を変換して物体の傾きを検出する。スマホの縦横の向きの検知などに応用できる。 温度センサからのアナログ信号を変換して周囲温度を測定する。   1.2 使用例 (概要を説明している例なので詳細は割愛しています) ポテンショメータの使用例:         2. 主な機能とブロック図   2.1 概要   MCX A153には、16ビットのADコンバータ(ADC)が搭載されています。ADコンバータは、アナログ電圧をデジタル値に変換する回路です。   2.2 主な機能 逐次比較型ADコンバータを1ユニット搭載 16ビットまたは12ビットの分解能で、シングルエンド入力に対応(分解能が高いほど、入力電圧を細かく表現できます) 搭載チャネル数 (パッケージにより異なる): 64ピンLQFP:24ch、48ピンLQFP:16ch、48ピンHVQFN:18ch、32ピンHVQFN:9ch サンプリング速度 (1秒間に何回変換できるか) 16ビットモード:最大3.2Msps、12ビットモード:最大4Msps サンプル時間が設定可能 マイコンの低電力モードで動作可能 4つのトリガーソースに対応 (ソフトウェアまたはハードウェアトリガーに対応) 7つのコマンドバッファにより連続したチャネルのスキャンが可能 コンペア機能をサポート (より小さい、より大きい、範囲内、範囲外、一致で保存、などを自動比較) ウォーターマークとオーバーフロー検出機能を持つ8つ変換結果データFIFOを搭載 割り込み、DMA、ポーリングに対応 キャリブレーション機能 専用入力チャネルを持つ温度センサを内蔵   2.3 ブロック図 MCX A153リファレンスマニュアル(MCXAP64M96FS3RM) Figure 165. ADC block diagramから抜粋   SDKサンプルコードの使用例 (ポテンショメータを接続)     3. MCX A153 ADCモジュール <注意点、制限事項> ここでは、MCX A153のADCを使う前に確認しておきたい注意点と制限事項を説明します。 16bitモードの速度低下 MCX A153のADCは、16ビット(ENOB16:実効分解能16ビット)と12ビット(ENOB12:実効分解能12ビット)の2つのモードに対応しています。ただし、16ビットモードは12ビットモードよりも、サンプリング速度が低下します。 (MCX A153 DataSheet Table.34から抜粋) キャリブレーションの実行タイミング キャリブレーションへのリクエスト&実行は、リセットまたは電源投入時に行わなければなりません。そして、キャリブレーション実行する前に、クロックソースと周波数をコンフィグする必要があります。 変換結果の平均化 ADCモジュールは、変換結果を保存する前に、同じチャネルの複数の結果を平均化できます。ハードウェア平均機能は、CMDHa[AVGS]ビットフィールドを0以外に設定すると有効になります。どの変換モードでも使用でき、ソフトウェアで平均値を計算する負担を減らせます。 4. AD変換のサンプルコード 4.1 サンプルコードの概要 mainシーケンスが実行されると、デバイスの初期化が実行されます。 デバイスの初期化は、クロックの設定に始まり、外部端子の構成と端子に接続するペリフェ ラルの選択をします。その後、ペリフェラル(ADC、UART)の初期化と、割り込みを有効に します。 初期化処理後、ループ処理内でADC変換開始のソフトウェアトリガをかけて、コンソールに AD変換の値と変換回数を表示します。 ハードウェアとしては、MCX A153の開発ボード「FRDM-MCXA153」を使用します。   4.2 VS codeでADCのサンプルプロジェクトを開くまでの手順 4.2.1 VS Codeと拡張機能の準備 VS Codeをインストールします。 拡張機能ビュー(Ctrl+Shift+X)で 「MCUXpresso for VS Code」 を検索してインストールします。 左のアクティビティバーにMCUXpressoアイコンが出ます。それをクリックして QUICKSTART PANEL を開きます。   4.2.2 依存ツールのインストール QUICKSTART PANELで 「Open MCUXpresso Installer」 を実行します。 次のツールを選んでインストールします。 Arm GNU Toolchain CMake / Ninja Python / West Git LinkServer(MCU-Link用デバッグプローブ) SDK 関連ツール 完了後、VS Codeを再起動します。   4.2.3 SDKリポジトリの取り込み QUICKSTART PANELで 「Import Repository」 をクリックします。 取り込み元として、リモートを選びます   保存先フォルダを指定します。パスは短く、日本語やスペースを含まないものにします  "I agree"をチェックして、Importボタンを押すことでレポジトリをインポートできます。   4.2.4 サンプルのインポート QUICKSTART PANELで 「Import Example from Repository」 をクリックします。 次のように設定します。   Importボタンを押すことで、プロジェクトをimportできます。 項目 設定値 Repository 手順3で取り込んだSDK(frdm_mcxa153) Toolchain Arm GNU Toolchain Board frdmmcxa153(FRDM-MCXA153) Template driver_examples → lpadc → interrupt(lpadc_interrupt) Location プロジェクト保存先 Name 任意(既定はlpadc_interrupt) 4.3 マクロ定義 ADCの機能に関するマクロ定義のコードです(lpadc\interrupt\app.hから抜粋)。 実際の回路設計と使用目的に合わせて、入力チャンネル、分解能設定、参考電圧ソースを修正してください。 Definitions //(lpadc\interrupt\app.hから抜粋) /******************************************************************************/ #define DEMO_LPADC_BASE ADC0 //ADCのinstance、ベースアドレス、MCX A153は1個 ADCしかない #define DEMO_LPADC_IRQn ADC0_IRQn #define DEMO_LPADC_IRQ_HANDLER_FUNC ADC0_IRQHandler #define DEMO_LPADC_USER_CHANNEL 0U //チャンネル番号 #define DEMO_LPADC_USER_CMDID 1U //コマンドID #define DEMO_LPADC_VREF_SOURCE kLPADC_ReferenceVoltageAlt3 //参考電圧ソース #define DEMO_LPADC_DO_OFFSET_CALIBRATION true //オフセットキャリブレーションの利用可否 #define DEMO_LPADC_USE_HIGH_RESOLUTION true //高分解能の利用可否 ADCに関する変数 Variables //(lpadc\interrupt\lpadc_interrupt.cから抜粋) volatile bool g_LpadcConversionCompletedFlag = false; volatile uint32_t g_LpadcInterruptCounter = 0U; lpadc_conv_result_t g_LpadcResultConfigStruct; #if (defined(DEMO_LPADC_USE_HIGH_RESOLUTION) && DEMO_LPADC_USE_HIGH_RESOLUTION) //高分解能 const uint32_t g_LpadcFullRange = 65536U; const uint32_t g_LpadcResultShift = 0U; #else //低分解能 const uint32_t g_LpadcFullRange = 4096U; const uint32_t g_LpadcResultShift = 3U; #endif /* DEMO_LPADC_USE_HIGH_RESOLUTION */ ADCに関する設定の構造体のデフォルト化(詳細はfsl_lpadc.cにある)、変換結果の平均化設定 //(lpadc\interrupt\lpadc_interrupt.cから抜粋) LPADC_GetDefaultConfig(&mLpadcConfigStruct); mLpadcConfigStruct.enableAnalogPreliminary = true; //ADCアナログ回路は事前に有効化され、起動遅延なしで変換を実行する準備 #if defined(DEMO_LPADC_VREF_SOURCE) mLpadcConfigStruct.referenceVoltageSource = DEMO_LPADC_VREF_SOURCE; //参考電圧ソース #endif /* DEMO_LPADC_VREF_SOURCE */ #if defined(FSL_FEATURE_LPADC_HAS_CTRL_CAL_AVGS) && FSL_FEATURE_LPADC_HAS_CTRL_CAL_AVGS mLpadcConfigStruct.conversionAverageMode = kLPADC_ConversionAverage; //変換結果平均化設定、平均しない/2回の平均/4回の平均/8回の平均/16回の平均....1024回の平均化選択可能 #endif     4.4 デバイスの初期化     クロック分周比の初期化 CLOCK_SetClockDiv関数では、ADCペリフェラルで使用するクロック分周設定を処理します。 //(lpadc\interrupt\hardware_init.cから抜粋) /* Attach peripheral clock */ CLOCK_SetClockDiv(kCLOCK_DivADC0, 1u); div_name: 列挙体で定義された分周器を選択 value: 分周比 ※以下のコードは、fsl_clock.cで始まるドライバ部となり、ユーザによる変更はオススメしません。 //(fsl_clock.cから抜粋) void CLOCK_SetClockDiv(clock_div_name_t div_name, uint32_t value) { volatile uint32_t *pDivCtrl = (volatile uint32_t *)(MRCC0_BASE + (uint32_t)div_name); assert(div_name <= kCLOCK_DivMax); /* Unlock clock configuration */ SYSCON->CLKUNLOCK &= ~SYSCON_CLKUNLOCK_UNLOCK_MASK; /* halt and reset clock dividers */ *pDivCtrl = 0x3UL << 29U; if (value == 0U) /*!< halt */ { *pDivCtrl |= (1UL << 30U); } else { *pDivCtrl = (value - 1U); } /* Freeze clock configuration */ SYSCON->CLKUNLOCK |= SYSCON_CLKUNLOCK_UNLOCK_MASK; }   クロック選択 CLOCK_AttachClkでは、ADCペリフェラルで用いるクロックソースを4つから選択します。 void CLOCK_AttachClk(clock_attach_id_t connection)関数の引数に 構造体clock_attach_id_tで定義された値を入れることで、ドライバにより設定が行われます。 //(fsl_clock.hから抜粋) kFRO12M_to_ADC0 = CLK_ATTACH_MUX(kCLOCK_SelADC0, 0U), /* Attach FRO12M to ADC0. */ kFRO_HF_to_ADC0 = CLK_ATTACH_MUX(kCLOCK_SelADC0, 1U), /* Attach FRO_HF to ADC0. */ kCLK_IN_to_ADC0 = CLK_ATTACH_MUX(kCLOCK_SelADC0, 3U), /* Attach CLK_IN to ADC0. */ kCLK_1M_to_ADC0 = CLK_ATTACH_MUX(kCLOCK_SelADC0, 5U), /* Attach CLK_1M to ADC0. */ kNONE_to_ADC0 = CLK_ATTACH_MUX(kCLOCK_SelADC0, 7U), /* Attach NONE to ADC0. */ //(lpadc\interrupt\hardware_init.cから抜粋) CLOCK_AttachClk(kFRO12M_to_ADC0); 以下の関数は、fsl_clock.cで始まるSDKで提供されているドライバ部の関数になり、ユーザーにより変更することはオススメしません。 //(fsl_clock.hから抜粋) void CLOCK_AttachClk(clock_attach_id_t connection) { const uint32_t reg_offset = CLK_ATTACH_REG_OFFSET(connection); const uint32_t clk_sel = CLK_ATTACH_CLK_SEL(connection); if (kNONE_to_NONE != connection) { CLOCK_SetClockSelect((clock_select_name_t)reg_offset, clk_sel); } } //(fsl_clock.hから抜粋) void CLOCK_SetClockSelect(clock_select_name_t sel_name, uint32_t value) { volatile uint32_t *pClkCtrl = (volatile uint32_t *)(MRCC0_BASE + (uint32_t)sel_name); assert(sel_name <= kCLOCK_SelMax); if (sel_name == kCLOCK_SelSCGSCS) { SCG0->RCCR = (SCG0->RCCR & ~(SCG_RCCR_SCS_MASK)) | SCG_RCCR_SCS(value); while ((SCG0->CSR & SCG_CSR_SCS_MASK) != SCG_CSR_SCS(value)) { } } else { /* Unlock clock configuration */ SYSCON->CLKUNLOCK &= ~SYSCON_CLKUNLOCK_UNLOCK_MASK; *pClkCtrl = value; /* Freeze clock configuration */ SYSCON->CLKUNLOCK |= SYSCON_CLKUNLOCK_UNLOCK_MASK; } } ボードの初期化関数について クロックの初期化を行います。   ピンの初期化 InitPins()を読み出し、pin_mux.cファイルの処理を行います。 pin_mux.cファイルは、NXPのMCUXPresso IDEに統合されているPin Configツールを用いて上書き可能です。 //(lpadc\interrupt\hardware_init.cから抜粋) BOARD_InitPins(); BOARD_InitPins()関数では、4つの処理を行います。 ペリフェラルのクロックの有効化 ペリフェラルのリセット解除 外部ピンとピンとペリフェラルの接続(MUXの設定)構成 -> 構造体へのパラメータ設定 3をレジスタへ書き込み   ブートクロックの初期化 MCX A153では、Mid Drive ModeとStandard Drive Modeをサポートしています。 それぞれ、VDD_COREの電圧レベルが、1.0 Vと1.1 Vで、rfo_hfクロックが48MHzもしくは96MHzで動作します。 モードを切り換えるには、外部からの電源供給に加えて、LDO等の電圧関連のレジスタ設定が必要です。 //(lpadc\interrupt\hardware_init.cから抜粋) BOARD_InitBootClocks(); 動作周波数に応じたレジスタ設定用の関数を用いて、クロックを設定します。 //(fsl_clock.cから抜粋) void BOARD_InitBootClocks(void) { BOARD_BootClockFRO96M(); }     デバッグポートの初期化 //(lpadc\interrupt\hardware_init.cから抜粋) BOARD_InitDebugConsole();   //(board.cから抜粋) void BOARD_InitDebugConsole(void) { /* attach 12 MHz clock to LPUART0 (debug console) */ CLOCK_SetClockDiv(kCLOCK_DivLPUART0, 1u); CLOCK_AttachClk(BOARD_DEBUG_UART_CLK_ATTACH); RESET_PeripheralReset(BOARD_DEBUG_UART_RST); DbgConsole_Init(BOARD_DEBUG_UART_INSTANCE, BOARD_DEBUG_UART_BAUDRATE, BOARD_DEBUG_UART_TYPE, BOARD_DEBUG_UART_CLK_FREQ); }   アプリケーションの初期化 ADCの初期化は、LPADC_Init(DEMO_LPADC_BASE, &mLpadcConfigStruct);関数内で処理されます。 LPADC_Init()の関数は、fsl_lpadc.cのドライバ部分の関数になります。 DEMO_LPADC_BASE: 0x400A_F000 -> ADCの先頭アドレス 構造体テーブルを定義して、ADCのコンフィギュレーションを行います。 typedef struct {} lpadc_config_t 名称 属性 説明 lpadc_config_t 型 LPADCコンフィグパラメータ情報 enableInDozeMode bool ADC変換中のモードによる動作設定 conversionAverageMode lpadc_conversion_average_mode_t Auto Calibrationに関する設定 enableAnalogPreliminary bool ADC事前起動設定 powerUpDelay uint32_t ADC回路の安定時間 referenceVoltageSource lpadc_reference_voltage_source_t 基準電圧のソース powerLevelMode lpadc_power_level_mode_t 電源構成の選択 triggerPriorityPolicy lpadc_trigger_priority_policy_t 高プロイオリティトリガの処理方法 enableConvPause bool AD変換実行間隔の設定 convPauseDelay uint32_t コマンドシーケンス中のポーズ時間 FIFOWatermark uint32_t FIFO内データ数の閾値設定 //(lpadc\interrupt\lpadc_interrupt.cから抜粋) LPADC_Init(DEMO_LPADC_BASE, &mLpadcConfigStruct); //(fsl_lpadc.cから抜粋) void LPADC_Init(ADC_Type *base, const lpadc_config_t *config) { /* 省略 */ base->CTRL |= ADC_CTRL_CAL_AVGS(config->conversionAverageMode); /* 省略 */ }   ADCのキャリブレーションについて   ADCでは、変換結果に含まれるオフセット誤差などを補正し、AD変換の精度を向上させるために、ADCの使用開始前にキャリブレーションを実行します。 キャリブレーション処理は、主に次の2段階に分けて考えることができます。 キャリブレーションのモードや条件を設定する キャリブレーションを実行し、補正値をADCへ反映する   デフォルトサンプルでは、LPADC_Init()の実行後、AD変換を開始する前にADCキャリブレーションを実行します。まず、対応するデバイスではLPADC_SetOffsetCalibrationMode()でオフセットキャリブレーションのモードを設定します。その後、DEMO_LPADC_DO_OFFSET_CALIBRATIONが有効な場合はLPADC_DoOffsetCalibration()を実行し、無効な場合はLPADC_SetOffsetValue()であらかじめ設定したオフセット値を使用します。 さらに、対応する機能マクロが有効な場合は、1 µs以上の待ち時間を置いてLPADC_DoAutoCalibration()を実行します。これにより、ゲイン誤差や直線性誤差のキャリブレーションを行います。各処理は、デバイスがサポートする機能マクロが有効な場合にのみコンパイルされます。   下記はLPADCのキャリブレーションモードの設定です。 //(lpadc\interrupt\lpadc_interrupt.cから抜粋) /* Request LPADC calibration. */ #if defined(FSL_FEATURE_LPADC_HAS_CTRL_CALOFSMODE) && FSL_FEATURE_LPADC_HAS_CTRL_CALOFSMODE LPADC_SetOffsetCalibrationMode(DEMO_LPADC_BASE, DEMO_LPADC_OFFSET_CALIBRATION_MODE); #endif /* FSL_FEATURE_LPADC_HAS_CTRL_CALOFSMODE */     オフセットキャリブレーションの実行 //(lpadc\interrupt\lpadc_interrupt.cから抜粋) #if defined(FSL_FEATURE_LPADC_HAS_CTRL_CALOFS) && \ FSL_FEATURE_LPADC_HAS_CTRL_CALOFS #if defined(DEMO_LPADC_DO_OFFSET_CALIBRATION) && \ DEMO_LPADC_DO_OFFSET_CALIBRATION L PADC_DoOffsetCalibration(DEMO_LPADC_BASE); //キャリブレーションを実行しない場合 #else /* Update OFSTRIM register manually. */   5. MCX A153 DMA ADC変換にDMA転送を用いる理由 ADCで取得したデータをソフトウェアだけで処理する場合、ADC変換の完了をCPUが監視し、変換結果を読み出してメモリへ書き込む処理が必要になります。単発のAD変換であれば大きな問題にはなりませんが、一定周期で連続的にサンプリングする場合や、複数の入力チャネルを扱う場合には、この処理が繰り返し発生します。その結果、CPUの処理負荷が増加し、他のアプリケーション処理に割り当てられる時間が少なくなる可能性があります。 この課題を解決する方法の一つが、DMA(Direct Memory Access)を用いたADC変換結果の転送です。DMAを使用すると、ADC変換の完了をきっかけに、ADCの変換結果をメモリへ自動的に転送できます。つまり、AD変換結果の取得からメモリへの格納までをハードウェアで処理できるため、CPUによるデータ転送処理を減らし、ソフトウェアの処理負荷を低減できます。 このような理由から、連続的なAD変換や高速なデータ取得が必要なアプリケーションでは、ADCとDMAを組み合わせた構成がよく利用されます。本記事では、まずADCの基本的な初期化方法を説明した後、MCX A153でDMAを使用してADC変換結果をメモリへ転送する方法を紹介します。 DMAを用いたAD変換値の転送 概要 AD変換後のデータはADCペリフェラル内のバッファに格納されます。都度、ソフトウェアで読み出さずに、ADCのトリガによりDMA を起動し、データを転送することがあります。1例として、AD変換を連続で5回おこなった後、DMAにてRAM上のバッファに保存し、コンソールに平均値と最小、最大を表示するプログラムに変更します。 DMAを用いたAD変換値の転送手順 ADCのサンプルコードを変更し、DMAの処理を追加していきます。 DMA起動は、ADCからのDMA Request信号を用います。 DMAを用いて、ADC FIFOの値(5回変換分)をRAMへコピーし、CPUへ割り込みを通知します。 CPUは、DMA転送完了後にmainループ内で平均値をとり、min, max, aveをコンソールに表示させます。     注意事項 DMAのコードを追加するにあたり、DMAドライバのヘッダファイルとソースコードをプロジェクトに追加してください。 一番簡単と思われる方法は、MCUXpresso IDEからDMAのサンプルコード(frdmmcxa153_edma3_memory_to_memory_transfer)を作成し、コピーする方法です。 driversディレクトリから、以下のファイルをコピーすればOKです。 fsl_edma_core.h fsl_edma_soc.c fsl_edma_soc.h fsl_edma.c fsl_edma.h   5.1  ADCに関するコードの修正と追加   コードの修正手順 ADC変換完了時の割り込みをディスエーブルに修正 ADCのコンフィグレーションを追加 AD変換を連続5回実行する設定 DMAリクエストをイネーブル設定 FIFOのWatermarkを4に設定 DMAが転送した値の平均、最小、最大値取得処理とコンソール出力を追加     1. ADC変換完了時の割り込みを無効 LPADC_EnableInterrupts()関数とkLPADC_FIFOWatermarkInterruptEnableを用いて、Interrupt Enable Register (IE)を有効にしているため、この行をコメントアウトします。 // LPADC_EnableInterrupts(DEMO_LPADC_BASE, kLPADC_FIFOWatermarkInterruptEnable);   2. ADCのコンフィグレーションを追加 ADCを5回ループ設定(=5回のAD変換) mLpadcCommandConfigStruct.loopCount = 4 //loopCount +1回の変換 DMAリクエストをイネーブルに設定 //178行目 LPADC_EnableFIFOWatermarkDMA(DEMO_LPADC_BASE, 1); // 1でDMA Requestがイネーブル     3. FIFOのWaterMarkの段数を4に設定 // 33行目 /* ++ ADCのマクロ */ #define FIFO0WatermarkLEVEL (4) //108行目 mLpadcConfigStruct.FIFOWatermark = FIFO0WatermarkLEVEL;   4. DMAが転送した値の平均、最小、最大値取得処理とコンソール出力を追加 uint32_t adc_values[5] = {0}; PRINTF("Please press any key to get user channel's ADC value.\r\n"); while(1) { GETCHAR(); EXAMPLE_DMA_BASEADDR->CH[0].CH_CSR = DMA_CH_CSR_ERQ(1); EXAMPLE_DMA_BASEADDR->CH[0].TCD_DLAST_SGA = -0x14; LPADC_DoSoftwareTrigger(DEMO_LPADC_BASE, 1U); /* 1U is trigger0 mask. */ while (!g_Transfer_Done) { /* DMA転送終了割り込み待ち */ } g_Transfer_Done = false; uint16_t min=adc_values[0]; uint16_t max=adc_values[0]; uint32_t sum=0; for(uint32_t i=0; i<5; i++) { if(max < (0x0000FFFF & adc_values[i])) max = adc_values[i]; if(min > (0x0000FFFF & adc_values[i])) min = adc_values[i]; sum += 0x0000FFFF & adc_values[i]; } PRINTF("ADC Min: %d, Max: %d, ave: %d\r\n", min, max, sum/5); for(size_t i=0; i<5; i++) { adc_values[i] = 0; } sum = 0; }   5.2 DMAに関するコードの追加   コードの追加方針 ヘッダファイルのインクルード DMA関連のマクロを追加 DMAのコンフィグレションと初期化 DMA転送のコンフィグレーション DMA転送完了割り込み処理   1. ヘッダのインクルード // 10行目 #include "fsl_debug_console.h" #include "pin_mux.h" #include "clock_config.h" #include "board.h" #include "fsl_lpadc.h" /* ++ */ #include "fsl_edma.h" // DMAドライバヘッダファイルの追加 #include "fsl_clock.h" #include "fsl_reset.h"   2. DMA関連のマクロを追加 // 32行目 #define EXAMPLE_DMA_BASEADDR DMA0 #define DEMO_DMA_CHANNEL_0 0U #define APP_DMA_IRQ DMA_CH0_IRQn #define APP_DMA_IRQ_HANDLER DMA_CH0_IRQHandler     3. DMAのコンフィグレーション // 197行目 edma_transfer_config_t transferConfig; edma_config_t userConfig; // 203行目 RESET_PeripheralReset(kDMA_RST_SHIFT_RSTn); /* Configure EDMA channel for one shot transfer */ EDMA_GetDefaultConfig(&userConfig); EDMA_Init(EXAMPLE_DMA_BASEADDR, &userConfig);     4. DMA転送のコンフィグレーション // 209行目 EDMA_PrepareTransfer(&transferConfig, (void *)0x400AF300, // eDMA transfer source address. sizeof(uint32_t), // eDMA transfer source address width(bytes) (void *)adc_values, // eDMA transfer destination address sizeof(&adc_values), // eDMA transfer destination address width(bytes) sizeof(adc_values), // eDMA transfer bytes per channel request sizeof(adc_values), // eDMA transfer bytes to be transferred kEDMA_PeripheralToMemory // eDMA transfer type ); EDMA_SetTransferConfig(EXAMPLE_DMA_BASEADDR, DEMO_DMA_CHANNEL_0, &transferConfig, NULL); EDMA_SetChannelMux(EXAMPLE_DMA_BASEADDR, DEMO_DMA_CHANNEL_0, kDma0RequestMuxAdc0FifoRequest); EnableIRQ(APP_DMA_IRQ); EDMA_EnableChannelInterrupts(EXAMPLE_DMA_BASEADDR, DEMO_DMA_CHANNEL_0, kEDMA_MajorInterruptEnable); ソフトウェアADCをソフトウェアトリガで起動する前に、DMAのチャネル0に割込みのトリガが掛るようにEDMA_TriggerChannelStart()を追加します。 DMAの割込みフラグをクリアした際、DMAトリガによる割込みがディスエーブルになるため、ADCのソフトウェアトリガの前に処理をついかします。 // 242行目 while(1) { GETCHAR(); EDMA_TriggerChannelStart(EXAMPLE_DMA_BASEADDR, DEMO_DMA_CHANNEL_0); EXAMPLE_DMA_BASEADDR->CH[0].TCD_DLAST_SGA = -0x14; LPADC_DoSoftwareTrigger(DEMO_LPADC_BASE, 1U); /* 1U is trigger0 mask. */ while (!g_Transfer_Done) { /* DMA転送終了割り込み待ち */ } g_Transfer_Done = false;   5. DMA転送完了割り込み処理 void APP_DMA_IRQ_HANDLER(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; } } まとめ: 本記事では、MCX A153 ADCの基本機能、注意点、vscode sdkのADCサンプルプロジェクトを使った初期化と変換処理を説明しました。そして、後半の記事従い、ADCサンプルを使った初期化・変換処理から、DMAによる変換結果の自動転送まで、実際の開発に役立つ設定例とコードの流れを確認できると思います。(まずはADC単体のサンプルを動かし、動作を確認してからDMAを追加すると、問題を切り分けやすくなります。) =========================​ 本投稿の「Comment」欄にコメントをいただいても、現在返信に対応しておりません。​ お手数をおかけしますが、お問い合わせの際には「NXPへの技術質問 - 問い合わせ方法 (日本語ブログ)」をご参照ください。​ (既に弊社NXP代理店、もしくはNXPとお付き合いのある方は、直接担当者へご質問いただいてもかまいません。)​ この記事では、MCX A153に搭載されているADC(アナログ信号をデジタル値に変換する回路)の基本から、MCUXpresso SDKを使った初期化、さらにDMAを使った変換結果の自動転送までを説明します。ADCやDMAを初めて使う場合は、まず1章と2章で全体像を確認し、その後に4章のサンプルコード、5章のDMA設定へ進むと理解しやすくなります。 ADC:センサなどのアナログ信号を、マイコンで扱えるデジタル値に変換する機能 DMA:CPUを介さずに、ペリフェラルとメモリの間でデータを転送する機能 SDK:ソフトウェア開発に必要なドライバやサンプルコードをまとめた開発キット (読了:30分) General Purpose Microcontrollers introduction MCUXpresso IDE MCUXpresso SDK 日本語ブログ
View full article
S32K312 BCTU – FIFO Watermark Callback Working, but Last Conversion Callback Not Triggered Hello NXP Community, I am working with the S32K312 MCU using S32 Design Studio and S32K3 RTD 7.0.1. I have configured the BCTU to trigger a list of ADC conversions using a software trigger. I am testing both the BCTU FIFO1 watermark callback and the BCTU last-conversion callback. Current Configuration: MCU: S32K312 Driver: S32K3 RTD 7.0.1 ADC instance: ADC0 BCTU conversion list: 4 ADC channels (0, 2, 4, 3) Trigger source: BCTU software trigger Interrupt: BCTU_IRQn enabled Notifications: FIFO1 watermark and last-conversion callbacks Observed Behavior: When I enable the FIFO1 watermark notification, the watermark callback is triggered successfully, and I can read the ADC conversion results from FIFO1. However, when I enable the BCTU last-conversion notification, the corresponding callback is not triggered. During debugging, I observed: Execution enters Bctu_0_Isr(). The driver checks the enabled BCTU interrupt sources. The condition if((*Reg & Mask) != 0U) evaluates to false for the last-conversion notification. The LIST0_Last bit in the BCTU MSR register remains 0 when inspected during interrupt handling. As a result, the last-conversion callback is not executed. Questions: Why does the FIFO1 watermark callback work correctly while the BCTU last-conversion callback is not triggered? What exact hardware condition causes MSR.LIST0_Last to become 1? Does the last-conversion interrupt require additional configuration in the BCTU conversion list, trigger configuration, or interrupt enable settings? Can both the FIFO1 watermark callback and the BCTU last-conversion callback be used for the same conversion list? Is the LIST0_Last status flag automatically cleared by hardware or by the RTD interrupt handler? If so, at what point? Which BCTU registers should I monitor to verify that the last-conversion event is generated correctly? Could you please help me understand why the FIFO watermark interrupt is functioning correctly while the BCTU last-conversion interrupt is not being generated or handled as expected? I can provide screenshots of my BCTU configuration, register values, and ISR debugging observations if required. Thank you for your support. #s32k312 #adcbctu #bctuswconv #listlastconv Re: S32K312 BCTU – FIFO Watermark Callback Working, but Last Conversion Callback Not Triggered Hi, if remember well, Last Conversion Notification can be generated only when the ADC conversion result destination is set to ADCnDR. The Reference Manual also states it in the LIST_IEN description.   BR, Petr  
View full article
Multicore Project setup of an additional MPU region I've been working on making a project that is essentially a combination of 2 SDK examples. I've been using the RT1170-EVKB SDK, version 26.09.00. The idea of the project is to take a multicore example and an LVGL example to have the M7 core run the graphics then communicate with the M4 core running the program. To do this I have taken the SDK examples: freertos_message_buffers (both primary and secondary) as my base project. I then slowly add in the graphics by copying and pasting the code and driver files from the lvgl_guider_cm7 project. I keep lvgl_guider_cm7 mcux_config.h file the same so that it does use PXP and VGLite. In order to do this, framebuffers need to placed in non-cache. The shared memory used in the SDK example also needs to be placed in non-cache. When this happens, I get artifacts on the display (little lines through objects that shouldn't be there). I can fix this by removing the __USE_SHMEM preprocessor, obviously this causes the multicore communication to fail. I believe it is because of the BOARD_EarlyConfigMPU function. Inside the function there is a section that goes like: #elif defined(__MCUXPRESSO) #if defined(__USE_SHMEM) extern uint32_t __base_rpmsg_sh_mem; extern uint32_t __top_rpmsg_sh_mem; uint32_t nonCacheStart = (uint32_t)(&__base_rpmsg_sh_mem); uint32_t size = (uint32_t)(&__top_rpmsg_sh_mem) - nonCacheStart; #else extern uint32_t __base_NCACHE_REGION; extern uint32_t __top_NCACHE_REGION; uint32_t nonCacheStart = (uint32_t)(&__base_NCACHE_REGION); uint32_t size = (uint32_t)(&__top_NCACHE_REGION) - nonCacheStart; #endif In this section it defines non-cache for either the shared memory or regular non-cache based on the __USE_SHMEM preprocessor. Further down in the function it declares the MPU region like so: volatile uint32_t i = 0; ... while ((size >> i) > 0x1U) { i++; } if (i != 0) { /* The MPU region size should be 2^N, 5<=N<=32, region base should be multiples of size. */ BOARD_EARLY_ASSERT(!(nonCacheStart % size)); BOARD_EARLY_ASSERT(size == (uint32_t)(1 << i)); BOARD_EARLY_ASSERT(i >= 5); /* Region 10 setting: Memory with Normal type, not shareable, non-cacheable */ MPU->RBAR = ARM_MPU_RBAR(BOARD_MPU_REGION_NONCACHE, nonCacheStart); MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 1, 0, 0, 0, 0, i - 1); } Now I want to be able to define both regions in the MPU to have both LVGL working without artifacts and the rpmsg message buffers be able to communicate. My memory regions can be found below: What I tried to do was modify the code above to perform both MPU region definitions, like so: #elif defined(__MCUXPRESSO) extern uint32_t __base_NCACHE_REGION; extern uint32_t __top_NCACHE_REGION; uint32_t nonCacheStart = (uint32_t)(&__base_NCACHE_REGION); uint32_t nonCacheSize = (uint32_t)(&__top_NCACHE_REGION) - nonCacheStart; #if defined(__USE_SHMEM) extern uint32_t __base_rpmsg_sh_mem; extern uint32_t __top_rpmsg_sh_mem; uint32_t rpmsgShmemStart = (uint32_t)(&__base_rpmsg_sh_mem); uint32_t rpmsgShmemSize = (uint32_t)(&__top_rpmsg_sh_mem) - rpmsgShmemStart; #endif This way the regular non-cache region is always defined and the shared memory region is only defined if used. I modified the MPU region definition like so: volatile uint32_t i = 0; ... while ((nonCacheSize >> i) > 0x1U) { i++; } if (i != 0) { /* The MPU region size should be 2^N, 5<=N<=32, region base should be multiples of size. */ BOARD_EARLY_ASSERT(!(nonCacheStart % nonCacheSize)); BOARD_EARLY_ASSERT(nonCacheSize == (uint32_t)(1 << i)); BOARD_EARLY_ASSERT(i >= 5); /* Region 10 setting: Memory with Normal type, not shareable, non-cacheable */ MPU->RBAR = ARM_MPU_RBAR(BOARD_MPU_REGION_NONCACHE, nonCacheStart); MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 1, 0, 0, 0, 0, i - 1); } #if (__USE_SHMEM) i = 0; while ((rpmsgShmemSize >> i) > 0x1U) { i++; } if (i != 0) { /* The MPU region size should be 2^N, 5<=N<=32, region base should be multiples of size. */ BOARD_EARLY_ASSERT(!(rpmsgShmemStart % rpmsgShmemSize)); BOARD_EARLY_ASSERT(rpmsgShmemSize == (uint32_t)(1 << i)); BOARD_EARLY_ASSERT(i >= 5); /* Region 16 setting: Memory with Normal type, not shareable, non-cacheable */ MPU->RBAR = ARM_MPU_RBAR(BOARD_MPU_REGION_SHMEM, rpmsgShmemStart); MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 1, 0, 0, 0, 0, i - 1); } #endif In doing this I created a macro for the additional MPU region inside board.h like so: #define BOARD_MPU_REGION_SHMEM (16) /* rpmsg shared memory */ Performing the modifications allowed LVGL to draw without artifacts but the multicore communication still fails. I put a breakpoint in the M4 thread running the multicore communication. Sometimes it'll trigger at the start, notifying that it received a message, but the message data is incorrect so it will not execute the code associated with the message's data. After a couple triggers of the breakpoint it will never trigger again. Is there anything I'm missing to be able to get this project running, the MPU region defines, etc...? Re: Multicore Project setup of an additional MPU region The changes were only applied to the primary core, as the primary core runs BOARD_EarlyConfigMPU and the secondary core runs BOARD_ConfigMPU, in the secondary core's function it already has the behaviour that I changed the primary core to have. Below are snippets from the what the secondary core runs on hardware init. #elif __CORTEX_M == 4 void BOARD_ConfigMPU(void) { #if defined(__CC_ARM) || defined(__ARMCC_VERSION) ... #elif defined(__MCUXPRESSO) extern uint32_t __base_NCACHE_REGION; extern uint32_t __top_NCACHE_REGION; uint32_t nonCacheStart = (uint32_t)(&__base_NCACHE_REGION); uint32_t nonCacheSize = (uint32_t)(&__top_NCACHE_REGION) - nonCacheStart; #elif defined(__ICCARM__) || defined(__GNUC__) ... #endif #if defined(__USE_SHMEM) #if defined(__CC_ARM) || defined(__ARMCC_VERSION) ... #elif defined(__MCUXPRESSO) extern uint32_t __base_rpmsg_sh_mem; extern uint32_t __top_rpmsg_sh_mem; uint32_t rpmsgShmemStart = (uint32_t)(&__base_rpmsg_sh_mem); uint32_t rpmsgShmemSize = (uint32_t)(&__top_rpmsg_sh_mem) - rpmsgShmemStart; #elif defined(__ICCARM__) || defined(__GNUC__) ... #endif #endif And then later in the function: uint32_t i = 0; /* Only config non-cacheable region on system bus */ assert(nonCacheStart >= 0x20000000); ... while ((nonCacheSize >> i) > 0x1U) { i++; } if (i != 0) { /* The MPU region size should be 2^N, 5<=N<=32, region base should be multiples of size. */ assert(!(nonCacheStart % nonCacheSize)); assert(nonCacheSize == (uint32_t)(1 << i)); assert(i >= 5); /* Region 0 setting: Memory with device type, not shareable, non-cacheable */ MPU->RBAR = ARM_MPU_RBAR(BOARD_MPU_REGION_NONCACHE, nonCacheStart); MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 2, 0, 0, 0, 0, i - 1); } #if defined(__USE_SHMEM) i = 0; while ((rpmsgShmemSize >> i) > 0x1U) { i++; } if (i != 0) { /* The MPU region size should be 2^N, 5<=N<=32, region base should be multiples of size. */ assert(!(rpmsgShmemStart % rpmsgShmemSize)); assert(rpmsgShmemSize == (uint32_t)(1 << i)); assert(i >= 5); /* Region 1 setting: Memory with device type, not shareable, non-cacheable */ MPU->RBAR = ARM_MPU_RBAR(BOARD_MPU_REGION_RPMSG_SHMEM, rpmsgShmemStart); MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 2, 0, 0, 0, 0, i - 1); } #endif Both projects have __USE_SHMEM defined in the preprocessor. Below is the memory config for the secondary core: Am I missing something else, or perhaps are my modifications wrong? Do I need to add something extra to the "Manage Linker Script" section of the primary project's settings? When I get the chance I'll upload a .zip of the projects that run on the EVK-B board so that you may see/replicate the issue. Re: Multicore Project setup of an additional MPU region Hi @CMoran, Your understanding makes sense, but it wasn't clear if that changed you mention were applied to both CM7 and CM4 cores. Each core has a definition of board.h, where they use their respective configuration of the MPU to setup during the initial hardware initialization. If the changes you mention were only made for the primary core, it's likely that the cores don't treat the memory regions equally, resulting in these unexpected behaviors. Please verify that the changes are applied to both cores to ensure they coincide on MPU setup, as well as ensuring that __USE_SHMEM was setup for both project's preprocessor definitions. Re: Multicore Project setup of an additional MPU region Here's the .zip with the m7 and m4 projects within. I've left it to be before my modifications, as the modifications didn't work anyway. In this example if you open a terminal and push the button in the center, both the m7 and m4 cores will print a message. The settings icon moving around the screen has a bunch of artifacts in it as described. Removing the __USE_SHMEM preprocessor from the m7 project will fix the artifacts in the settings icon, but the multicore communication will fail. Adding the modifications I've applied above will also fix the settings icon, but the multicore communication will fail. Screen used in this demo is the RK055HDMIPI4MA0. Re: Multicore Project setup of an additional MPU region Hi @CMoran, Got it. Going back on your first reply though: You mentioned that you created a new definition for a memory region: #define BOARD_MPU_REGION_SHMEM (16) /* rpmsg shared memory */ But the definition of ARM_MPU_RBAR() uses MPU_RBAR_REGION_Msk, which is defined as 15: #define MPU_RBAR_REGION_Msk (0xFUL /*<< MPU_RBAR_REGION_Pos*/)  The CM7 defines the number of regions as 16, numbered 0-15. Therefore, you are actually setting region 0 by doing so. Re: Multicore Project setup of an additional MPU region Unfortunately before creating the new memory region definition: #define BOARD_MPU_REGION_SHMEM (16) /* rpmsg shared memory */ I was just reusing the predefined memory region for non-cache: #define BOARD_MPU_REGION_NONCACHE (10) /* Noncacheable space in application */ And I had the same result. I've changed my new memory region definition to be 10 now to match the non-cache. With no luck on the cores being able to communicate. I've checked the start location and the size of the rpmsg shared memory on both cores with breakpoints, both have the correct start (0x20340000) and size (0x10000). I've changed the 4th parameter of the ARM_MPU_RASR() function on both cores to 1 to indicate that the region is "shareable". No luck there still. When you or a member of the team gets a chance, I posted my project's code in another reply. I'm running out of ideas of what to try. Re: Multicore Project setup of an additional MPU region Hi again @CMoran, After building your project and analyzing the memory regions on the resulting .ld files, I see that the regions where the LVGL framebuffers and the multicore message buffers are located at separate memory regions in a way that can't be merged as they are non-contiguous physical memories: NCACHE_REGION at 0x81000000 (16 MB, in SDRAM) for the LVGL framebuffers rpmsg_sh_mem at 0x20340000 (64 KB, in OCRAM) for the multicore message buffers That said, MPU region 7 currently covers 0x20300000–0x2037FFFF (512 KB) as cacheable Normal memory, a range that includes the rpmsg_sh_mem region, which could mean that the shared memory ends up being cacheable, resulting in the inter-core communication errors that you are seeing. Reducing the size of Region 7 to ensure rpmsg_sh_mem falls through to region 3, which is already non-cacheable might be a straightforward fix to ensure the proper functionality of the message buffers, without MPU driver level changes on the existing drivers. Re: Multicore Project setup of an additional MPU region Hi @EdwinHz  I've taken a second to test your suggestion. I changed the MPU Region 7 (OCRAM2) to be 256 KB instead of 512 KB like so: /* Region 7 setting: Memory with Normal type, not shareable, outer/inner write back */ MPU->RBAR = ARM_MPU_RBAR(BOARD_MPU_REGION_OCRAM_B, 0x20300000U); MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 1, 0, ARM_MPU_REGION_SIZE_256KB); After I removed the __USE_SHMEM preprocessor as the rpmsg_sh_mem will fall through to MPU Region 3, which is already defined as non-cacheable. The demo I created is now working as intended.
View full article
RW612: 同時デュアルPHY(1M + コード化)スキャン中にLEコード化PHYが深刻な飢餓状態に陥る こんにちは、NXPコミュニティの皆さん、 私たちは RW612上で、#SDKs 26.09のもとでコントローラファームウェア18.99.8.p141のASTM F3411リモートIDレシーバを開発しています。デュアルPHYスキャンが有効な場合、LEコードPHYに深刻なコントローラ側の飢餓問題が発生していることを特定しました。 同時に1Mと符号スキャンをコントローラに委任(60ms間隔で15%1M、85%符号化作業)すると、符号化PHY受信率は7%に崩壊し、Wi-Fi TX/RXが同時接続しているフルシステム負荷時には5%に低下します。 アイソレーションテストの結果、この問題はコントローラのスキャンパラメータに両方のPHYを組み合わせたことで厳密に引き起こされることが示されました。 ソロコード化スキャン(85%デューティ、ウィンドウ処理):受信率98% (47/48パケット) 。 デュアルPHYスキャン(1M 15% + コード化85%):受信率7% (29/391パケット) 。 ホストの逐次タイムスライシング(符号化2000ms/1Mあたり300ms): 単独で符号受信を 98% まで回復し、完全な並行性(2パック/秒の生Wi-Fi注入、Wi-Fiモニター、ローカルBT4/BT5広告)では 54% を維持し、基準値の5%から増加します。 ホストのバッファとキューは完全に正常な状態を維持しており、データ損失や破損は一切発生していません。この問題は、マルチPHYスキャンパラメータを処理する際のCPU2無線ファームウェアスケジューラに限定されています。 これはCPU2コントローラのファームウェア(rw61x_sb_ble_a2.bin)の既知のスケジューリングバグでしょうか? ホスト管理型のシーケンシャルシングルPHYタイムスライシングは、RW612上で1M PHYとCoded PHYの両方を監視するための公式に推奨されている回避策ですか? 製品: WiFi RW6XX プロトコル:Bluetooth Re: RW612: Severe LE Coded PHY Starvation During Concurrent Dual-PHY (1M + Coded) Scanning こんにちは@ecg3 Dual-PHYスキャンの設定やテストステップを教えていただけますか?また、レビューのためにhciログとOTAログを共有してください。 よろしくお願いいたします。 ショーン Re: RW612: Severe LE Coded PHY Starvation During Concurrent Dual-PHY (1M + Coded) Scanning こんにちは、 @shaun_wu さん。 ご連絡ありがとうございます。私はRW612(MCUXpresso SDKs 26.09、EdgeFastオープンホスト、FW 18。99.8。p141、アイドルWi-Fi)を、1メートル離れた広告主に対してLEコードの拡張広告(ASTM F3411リモートID、500ms間隔、8ビットペイロードカウンターで追跡)とnRF52840のOTAスニッファーを同時にテストしました。 私はデュアルPHYスキャン(Scanning_PHYs 0x05、60ms間隔、8。75ms、1Mのウィンドウ、50ms。6msの符号付きウィンドウ)と、符号のみの参照スキャン(Scanning_PHYs 0x04、同一の50ms。6ms符号化ウィンドウ)を比較しました。 符号化のみのスキャンはオンエアパケットの94%(112パケット中105パケット)を正常に受信しましたが、デュアルPHYを有効にすると符号受信は急激に13%に低下しました(報告されたパケットは94パケット中12パケットのみ)。RW612コントローラは通常通りレガシー1Mパケットを報告し続け、配布された数少ない符号化パケットは完全に無傷(データステータス0)で、欠損パケットはコントローラによって単純にドロップまたはスキップされたことを示しています。 両方の実行の完全なログ(生のUART、パケット損失のないHCI_Resetからの完全なHCI btsnoop 、および同期されたOTA pcapngキャプチャ)を添付しました。RW612とPCのクロックにはわずかなオフセット(約0.4~0.9秒)があるため、タイムスタンプではなくペイロードカウンタを使用してHCIとスニファのトレースを相関させてください(たとえば、デュアルPHYキャプチャでは、 btsnoopフレーム531がカウンタ157のスニファフレーム2998と一致します。BDアドレス58:ce:2a:6b:d5:8bでフィルタリングすると、両方のストリームが分離されます)。 よろしくお願いいたします。
View full article
PN7642EV/C100とPN7642EV/C102の比較 最初の質問です。新しいデザインでPN7642EV/C102を使う予定です。PN7642EV/C100は主流の代理店に在庫があるので代替部品として追加したいと考えており、長期的なサプライチェーンの問題を軽減したいと考えています。これらのPNの違いは出荷時のFWバージョンだけのように見えます。もしそうなら、PN7642EV/C100を入力して最新のFWに更新することは、PN7642EV/C102で同じことをするのと同じことになります。この推測は正しいでしょうか? 2つ目の質問ですが、このアプリケーションでは基本的なNFCタグ、Google Wallet、Apple Walletを読みます。GoogleウォレットやAppleウォレットを読み取るには多くの認証や許可が必要なことは理解していますが、ハードウェアの観点から見て、C100およびC102のバリアントはこれに対応できるのでしょうか? Re: PN7642EV/C100 vs PN7642EV/C102 こんにちは、 @adamdoyle15 あなたの調子が良いといいのですが。 PN7642はECPに対応しているはずです。また、ご指摘のとおり、これらのバリアントの主な違いは、C102は出荷時にファームウェアv3.00が搭載されている点です。 よろしくお願いいたします。 エドゥアルド。 Re: PN7642EV/C100 vs PN7642EV/C102 こんにちは、 ECPサポートは主にソフトウェアで行われており、ハードウェアのバリアント間で区別はないはずです。 よろしくお願いいたします。 エドゥアルド。 Re: PN7642EV/C100 vs PN7642EV/C102 迅速なご対応ありがとうございます。 ECP機能については、データシートを見る限りPN7642はECP対応であることがわかりますが、ハードウェアの観点からこれでApple Walletとの互換性が十分かどうかが疑問です。
View full article