Multi Source Translation Content

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

Multi Source Translation Content

Discussions

Sort by:
S32 设计工作室许可证已过期 尊敬的恩智浦: S32 Design Studio 3.5 许可证即将到期。 请问您能否帮忙延长许可证期限? 谢谢。 激活ID:29E6-6248-FCB2-DBB6 Re: S32 Design Studio License Expired 你好, 您的S32DS许可证已延期。请使用您之前的激活码重新激活S32DS。
View full article
ZephyrでのFRDM-IMX93(A55)でのSAI/eDMAサポートに関する質問 NXPサポートの皆様、 私はZephyrを使ってFRDM-IMX93ボードのオーディオ入出力機能を評価しています。 環境: ボード:FRDM-IMX93 コア:Cortex-A55 OS:Zephyr(NXP Zephyrツリー) オーディオインターフェース:SAI3 DMA:eDMA4 オーディオコーデック:CS42448(MX93AUD-HAT) ZephyrでSAI3とeDMA4を有効にしているときにいくつかの問題に直面し、これらが既知の制限か欠陥かを確認したいと思います。 1. I2S PLL構成 ファイル: ドライバ/i2s/i2s_mcux_sai.c ビルドが以下のエラーで失敗します。 #エラー SOCシリーズ固有のclock_audio_pll_config_tを初期化します 実装は以下のみをサポートするようです: CONFIG_SOC_SERIES_IMXRT10XX CONFIG_SOC_SERIES_IMXRT11XX CONFIG_SOC_SERIES_IMXRT118X IMX93特有のハンドリングは見つかりませんでした。 これは既知の問題ですか? 2. bclkSrcSwap コンパイルエラー 以下の文はコンパイルエラーを引き起こします。 config.bitClock.bclkSrcSwap = false; メンバーは、以下の条件を満たす場合にのみ存在します。 FSL_FEATURE_SAI_HAS_BIT_CLOCK_SWAP 有効になっています。 IMX93ではこの機能は利用できないようですが、コードは依然としてメンバーにアクセスできます。 これは既知のバグですか? 3. DMAディスクリプタキャッシュ構成 ビルドが以下のエラーで失敗します。 #エラー DMA記述子の予期しない、または許可されていないキャッシュ状況 Cortex-A55はデータキャッシュを有効にするため、追加しなければなりませんでした: CONFIG_NOCACHE_MEMORY=y 進むために。 IMX93 A55にはこの設定が必要ですか? 4. eDMA4割り込み設定 デフォルトのDTS定義を使用する: edma4_2 { 割り込み = <0x0 0x80 0x2 0xa0>、 <0x0 0x80 0x2 0xa0>、 <0x0 0x81 0x2 0xa0>、 <0x0 0x81 0x2 0xa0>; }; 結果として: table_index 161 に複数の登録があります IRQ 161 (0xa1) 用 ビルドは、以下の内容で上書きした後で続行されます。 &edma4_2 { 割り込み = <0x0 0x80 0x2 0xa0>、 <0x0 0x81 0x2 0xa0>; チャネル-shared-irq-mask = <0x3 0xc>; }; これはIMX93デバイスツリー定義における既知の問題ですか? 質問 SAI + eDMAはZephyrのFRDM-IMX93 Cortex-A55で公式にサポートされていますか? SAI3とeDMA4を組み合わせた動作例は知られていますか? 上記の4つの問題は既に判明しているのでしょうか? パッチ、更新されたブランチ、または推奨される修正プログラムはありますか? 再開まで今しばらくお待ちください。 よろしくお願いいたします。 #i.MX93 Zephyr Re: Question regarding SAI/eDMA support on FRDM-IMX93 (A55) with Zephyr こんにちは@Zhiming_Liu ご回答ありがとうございます。 現状は理解しています。 現在、バージョン4.4.1でこれを検証中です。 MX93AUD-HAT(TDM 8ch)をサポートするFUTUREパッチアップデートの予定があれば教えていただけますか? あるいは、自分でサポートを実装すべきでしょうか? ご協力ありがとうございました。 よろしくお願いいたします。 サダチ Re: Question regarding SAI/eDMA support on FRDM-IMX93 (A55) with Zephyr こんにちは、 @sadachi さん。 パッチを提出したエンジニアに確認したところ、sai+edmaの Zephyrパッチ はv4.1 でしか テストされていません。 検証済みのv4.1バージョンの使用方法については、下記のドキュメントを参照してください。 https://community.nxp.com/t5/i-MX-Processors-Knowledge-Base/Run-Zephyr-on-A55-with-FRDM-IMX93-and-FRDM-IMX91/ta-p/2143151 バージョン4.1以降を使用している場合、これらの問題は想定内のものです。 よろしくお願いします、 志明 Re: Question regarding SAI/eDMA support on FRDM-IMX93 (A55) with Zephyr こんにちは@sadachi  現時点でソフトウェアチームはこの問題を調査する十分なリソースも時間もありません。今のところ、もしお急ぎでしたら、ご自身で修理を試みていただくのも良いかもしれません。 よろしくお願いします、 志明 Re: Question regarding SAI/eDMA support on FRDM-IMX93 (A55) with Zephyr こんにちは@Zhiming_Liu チームの状況は理解しました。お知らせいただきありがとうございます。 まずはこちらで試してみます。もし不明な点があれば、アドバイスをいただけるとありがたいです。 よろしくお願いします、 サダチ
View full article
S32G399 Bare Metal DDR initialization Greetings! We are trying to reproduce this core sequence in booting process: but encountered some problems during DDR initialization by M7 core. 1. We created a new project from example in Design Studio; (Linflexd_Uart_Ip_Example_S32G399A_M7: Debug_RAM); 2. Configured and verified DDR, generated source files related to ddr_*.c; 3. copied and adjusted some code related to DDR initialization from GoldVIP example and arm-trusted-firmware; 4. we've got such code sequence in the main.c:   Clock_Ip_Init(&Mcu_aClockConfigPB[0]); IntCtrl_Ip_Init(&IntCtrlConfig_0); Siul2_Port_Ip_Init(NUM_OF_CONFIGURED_PINS0, g_pin_mux_InitConfigArr0); Mpu_M7_Ip_Init(&MPU_M7_ModuleConfig_0); EnableRdInterconnect(2); // RD2 EnableRdInterconnect(3); // RD3 /* 2. NoC QoS */ FlexNOC_InitNoc(4); // 4 - CORE_ID_M7_0 enable_partition(); ddr_status = ddr_init();   we noticed, that after DDR is initialized it is in sleeping mode, so we wake it up:   *(volatile uint32_t*)0x403C0000 = 0x83080023; *(volatile uint32_t*)0x403C0020 &= ~0x1; *(volatile uint32_t*)0x403C0030 = 0x0; *(volatile uint32_t*)0x403C0320 = 0x0; *(volatile uint32_t*)0x403C0320 = 0x1;   The DDR memory starts from address 0x60000000, so during the Debugging with Debug Probe we can see in Assembly that memory is allocated, no errors, no hard fault, but still if we call in GDB:   set {uint32_t}0x60000000 = 0xDEADBEEF or x/1xw 0x60000000   it returns "Cannot access memory at address 0x60000000"   ddr_status returns 0.   Could you please guide us what we are doing wrong? and is that diagram actually applicable as recommended by NXP way to boot S32G399 board?   Thank you! Re: S32G399 Bare Metal DDR initialization Hello, @Interrogator  Thanks for your post. Actually the flow you mentioned is not a typical booting flow while using the S32G platform. Typical booting flow is as described in AN13750 and GoldVIP, a bootloader is running on the M7_0(also init clock, pin, etc.), which is responsible for loading images for different partition(like M7_1/2, A53_0), while Linux BSP is loaded to A53_0, and DDR would be initialized by the TFA running on the A53_0. May I know if you are currently working the design? if so, using the booting flow described above is relatively recommended. BR Chenyin Re: S32G399 Bare Metal DDR initialization @chenyin_h thank you for your reply! I really appreciate that. Could you also help me with understanding one thing: we currently have the board on hands, and possibly M7 doesn't have bootloader. We flashed Linux Image built by Yocto BSP 46 on the SD card (.sdcard file)), inserted card in the board, switched pins on the board to load from SD card and expected the same behavior as on S32G274, but UART output is completely empty. Although pressing buttons while in the COM session (MobaXterm) making Rx indicator on the board flashing. To see Linux output we need to have M7 bootloader, right? Could you pls suggest the best approach in our situation? Thank you! Re: S32G399 Bare Metal DDR initialization @chenyin_h greetings! 1. We use custom board that only have SW3, SW6.1-2, SW10.1-2 and SW12.1-2 pins. 2. We run bitbake and build an image from the source codes (kernel, bootloaders, rootfs) on our machine. Re: S32G399 Bare Metal DDR initialization Hello, @Interrogator  Thanks for your confirmation 1. Typically, with default BSP code/settings, the images built are targeted booting the S32G3 reference board like RDB3/EVB3. 2. Since you are working with the custom board, it is possible that the images built that could not boot the board correctly, which is actually a custom board bring up issue. Not sure if you had made any modification on the original BSP46 BSP and any debug logs for locating the issue? BR Chenyin Re: S32G399 Bare Metal DDR initialization Hello, @Interrogator  Thanks for your reply. If you do not need use the M7 side, solely booting the board with BSP is applicable.(M7 bootloader is not mandatory in such setup) Regarding to the issue you met 1. What kind of board is used? custom one or reference design from NXP? 2. How the BSP46 images that flash to SD card are generated? pre-built images or custom built images are used? BR Chenyin  Re: S32G399 Bare Metal DDR initialization Good day, @chenyin_h  Thank you for your active participation! 1. We tried out the pre-built BSP 46 for S32G3 RDB3 right now, and unfortunately experienced the same problem. 2. We started Debugging on A core with s32g3xx_attach.py script and found this log in the Debugger Console: 394,149 =cmd-param-changed,param="remote hardware-breakpoint-limit",value="6" 394,149 =cmd-param-changed,param="remote hardware-watchpoint-limit",value="4" 394,150 =cmd-param-changed,param="mem inaccessible-by-default",value="off" 394,151 =cmd-param-changed,param="mem inaccessible-by-default",value="on" 394,164 ~"Core can't be stopped. State: CoreMode.Disabled\r\n" 394,165 ~"Type of the error: [CoreError]\r\n" 394,165 ~"Error code: [200]\r\n" 394,165 ~"\r\n" 394,165 ~"\r\n" 394,165 ~" --- STACK TRACE OF THE INIT SCRIPTS ---\r\n" Does this give you any clues? s32g3xx_attach.py on M core returns the same result. However, s32g3xx_generic_bareboard.py works fine, but our idea was to attach debugger to the core that is already launched and check its status via Registers in Assembly. Re: S32G399 Bare Metal DDR initialization Hello, @Interrogator  Thanks for your reply. The BSP46 pre-built images should work on RDB3(unless it is very old version board) 1. Would you mind confirming if you have both RDB3 and custom board?(since different board are mentioned in your different replies) 2. The final target is to run the BSP or GoldVIP style design(M bootloader -> A(BSP) + M(App))? based on your custom board or RDB3 is enough? We could discuss further for the details(If some of the contents are not convenient to share, we may also discuss it in private messages/support case), and to divide the target into several phases to help you to use the S32G efficiently in your system designed. BR Chenyin Re: S32G399 Bare Metal DDR initialization Hello, @Interrogator  Thanks for your reply. Sorry that I feel a little confused about your testing setup, would you mind clarifying it accordingly: 1. From hardware view, may I know if you hold a custom board(the board that designed by your company or 3rd party)  or a reference board(designed by NXP, you may bought it from NXP or any certified distributer, the reference board of S32G3 may be called RDB3/EVB3/GoldBox3)? 2. BSP is software released by NXP which is mainly targeted running on A53 side of S32G3, would you please help to confirm if your final target is to run BSP on RDB3? or run BSP on your custom board? BR Chenyin Re: S32G399 Bare Metal DDR initialization Hello, @chenyin_h Sorry for the confusing answer in the previous post. Let me clarify it a bit for you: 1. I'm holding a custom board 2. my final target is to run BSP on our custom board Thank you! Re: S32G399 Bare Metal DDR initialization Hello, @Interrogator  Thanks for your confirmation. For such bring up issue, I may need to check your hardware design firstly, in order for conveniently share the information like schematic, I will help you create a private case later, for better further discussion. BR Chenyin Re: S32G399 Bare Metal DDR initialization Greetings, @chenyin_h 1. I have only custom board, I just tried different approaches to launch it (RDB3 and GoldVIP) 2. The final target is to run the RDB3/BSP approach. Thank you for your engagement, I wouldn't mind further help. Which additional information would be helpful for you?
View full article
漏洞:dw-mipi-dsi:在非突发DSI桥接器上720p60分辨率输出异常 你好, 我们发现 NXP 下游内核 (lf-6.18.y) 存在问题,我们认为问题是由以下原因造成的: ▎ LF-14666-2:drm/bridge:synopsys:dw-mipi-dsi:实现 720p60 的修复 在 i.MX95 上使用 TI SN65DSI86(DSI 转 DisplayPort)时,720p60 会出现图像闪烁。 在非突发模式下,DSI_VID_HLINE_TIME 为 htotal * bpp / (lanes * 😎 通道字节时钟周期,如果不是整数则向上取整。对于 4 通道 RGB888 的 720p60,数值为 1237.5,四舍五入为 1238。这样一来,DSI 线就比 DPI 线长,误差会在帧内累积。只有在 HFP 期间返回 LP 才会将每行的行计时器与 DPI 重新同步。 Mainline 始终在 HFP 中启用 LP。LF-14666-2 将其设为可选的,仅当 DSI 设备设置 MIPI_DSI_MODE_VIDEO_NO_HFP 时才可设置。这对于 LT8912B 来说是有效的,因为 LF-14666-1 向该驱动程序添加了标志。但是舍入操作来自主机控制器,而不是设备,因此,只要线路时间为小数,所有其他未设置标志的桥接器或面板(例如 SN65DSI86)现在都会中断。 我已在邮件中附上一个补丁,可以解决我们遇到的问题,如果有人能帮忙看一下,我将不胜感激。 谢谢, 安托万·古比 Linux
View full article
BUG: dw-mipi-dsi: 720p60 broken on non-burst DSI bridges Hello, We have an issue with the NXP downstream kernel (lf-6.18.y) that we think is caused by: ▎ LF-14666-2: drm/bridge: synopsys: dw-mipi-dsi: Implement fixup for 720p60 On i.MX95 with a TI SN65DSI86 (DSI to DisplayPort), 720p60 gives a flickering image. In non-burst mode, DSI_VID_HLINE_TIME is htotal * bpp / (lanes * 😎 lane byte clock cycles, rounded up when that isn't an integer. For 720p60 on 4 lanes with RGB888 that's 1237.5, rounded to 1238. The DSI line is then longer than the DPI line, and the error builds up over the frame. Only returning to LP during HFP resyncs the line timer to DPI on every line. Mainline always enables LP in HFP. LF-14666-2 made it optional, only when the DSI device sets MIPI_DSI_MODE_VIDEO_NO_HFP. That works for LT8912B, because LF-14666-1 adds the flag to that driver. But the rounding comes from the host controller, not from the device, so every other bridge or panel that doesn't set the flag (SN65DSI86 for example) is now broken whenever the line time is fractional. I attached to this message a patch the corrects the issue for us, I would appreciate if anyone can take a look at this. Thanks, Antoine Gouby Linux
View full article
i.MX93 FRDM:使用 ISI 进行 RAW10 捕获时,IMX219 和 IMX708 每帧仅写入一行。 你好, 我们正在FRDM-IMX93上安装MIPI CSI-2 RAW相机,希望得到NXP的帮助。IMX219 和 IMX708 都能启动并传输数据帧,但每种传感器只能捕获一行数据。 帧包含数据。其他所有行均为零。在 IMX219 上,我们测试的每个分辨率都会出现这种情况。我们不清楚原因,恳请您指点。 这里曾报道过内核 6.12.20 上出现过类似的症状,但没有找到解决方案: https://community.nxp.com/t5/i-MX-Graphics/i-MX93-RAW10-capture-issue-only-first-line-valid-IMX219-ISI/mp/2321729 环境 - 板:FRDM-IMX93(机器型号 = imx93-11x11-lpddr4x-frdm),摄像头位于 P6 MIPI CSI 连接器上 - 电路板支持包。:imx-6.18.37-2.1.0来自 nxp-imx/imx-清单 (meta-imx rel_imx_6.18.37_2.1.0)Yocto 6.0.2 wrynose,发行版 = fsl-imx-wayland - 内核:6.18.37-2.1.0-gddef48f9b907 - Pipeline: sensor --csidev-4ae00000.csi (dwc-mipi-csi2) --crossbar --mxc_isi.0-> mxc_isi.0.捕获 (/dev/video0) - 格式:SRGGB10_1X10 / RG10,2 条数据通道 传感器 1. Raspberry Pi 相机模块 v2 NoIR (IMX219) - 内置 imx219 驱动程序以及未修改的 电路板支持包。 CSI 和 ISI 驱动程序 - 链路频率:456 MHz 2. 树莓派摄像头模块 3 NoIR (IMX708) - 驱动程序移植自 Raspberry Pi 内核 (rpi-6.12.y) - 链路频率:450 MHz - 如果不做进一步的更改,该传感器会产生 IPI FIFO 溢出,并且没有帧。当传感器寄存器 0x3095 设置为 0 时,帧速率为 56 fps,分辨率为 2304x1296。 结果 传感器分辨率图像源结果 IMX219 640x480 实时图像,彩色条形帧已输出,但只有第 0 行有数据。 已交付 IMX219 1640x1232 彩色条形帧,但只有第 0 行包含数据。 IMX219 1920x1080 实时图像,彩色条形帧已输出,但只有第 0 行有数据。 IMX219 3280x2464 彩色条形帧已输出(14.5 fps),但只有第 0 行有数据。 IMX708 2304x1296 彩色条形帧已输出(56 fps),但只有第 0 行有数据。 在每种情况下,缓冲区的大小都符合预期(宽度 x 高度 x 2 字节)。第 0 行包含预期数据,例如颜色条。其余所有行均为零。IMX219 测试结果显示未检测到 CSI 或 ISI。 dmesg 中出现错误。 命令(IMX219,640x480) media-ctl -V "'imx219 2-0010':0[fmt:SRGGB10_1X10/640x480]" media-ctl -V "'csidev-4ae00000.csi':0[fmt:SRGGB10_1X10/640x480 field:none]" media-ctl -V "'crossbar':0[fmt:SRGGB10_1X10/640x480 field:none]" media-ctl -V "'mxc_isi.0':0[fmt:SRGGB10_1X10/640x480字段:无]" media-ctl -V "'mxc_isi.0':1[fmt:SRGGB10_1X10/640x480字段:无]" v4l2-ctl -d /dev/video0 --set-fmt-video=width=640,height=480,pixelformat=RG10 \ --stream-mmap --stream-count=10 --stream-to=/tmp/cap.bin 流式传输期间读取的寄存器值(IMX219,640x480,调试 CSI 版本,症状相同) ISI 0x4ae40000: CHNL_CTRL (0x00) = 0xe0000000 CHNL_IMG_CTRL (0x04) = 0x0f008001 CHNL_IMG_CFG (0x0c) = 0x01e00280 媒体混合 0x4ac10000: 0x30 = 0x00010158 0x3c = 0x00000e07 0x40 = 0x00000001 0x44 = 0x00019140(帧间值) 0x48 = 0x0002291c 问题 1.i.MX93 是否验证了通过 ISI 从 CSI-2 传感器捕获 RAW 数据的功能?如果是,请问使用了哪种传感器、电路板支持包。版本和配置? 2. 是否有适用于此用例的已知问题、勘误或必需设置? 3. 接下来我们应该检查什么?请与我们联系,告知我们需要哪些注册表、日志或捕获文件,我们将提供这些文件。 4. FRDM-IMX93 上是否有适用于 IMX219 或其他 RAW 传感器的参考设备树或补丁? 我们可以根据要求分享完整日志、设备树叠加图和原始捕获数据。 感谢您的支持。 Linux Yocto Project Re: i.MX93 FRDM: RAW10 capture through ISI writes only one line per frame with IMX219 and IMX708 我已经把imx219的补丁发给你了,请参考这个。
View full article
imx93:SRK撤销 你好, 我正在尝试对我的已关闭的imx93板执行密钥撤销操作。 我的脑脊液文件内容如下: [标题] 目标 = AHAB 版本 = 1.0 [安装SRK] 文件 = "../cst-3.4.0/crts/SRKtable.bin" 来源 = "../cst-3.4.0/crts/SRK2_sha384_secp384r1_v3_usr_crt.pem" 来源索引 = 1 源集 = OEM 撤销次数 = 0x1 [验证数据] 文件 = "spl.bin" 偏移量 = 0x400 0x490 其思路是使用 SRK2 进行签名,并撤销 SRK1(0x1 位掩码)。从该镜像启动可以正常工作,但我仍然可以从使用 SRK1 签名的镜像启动。 撤销 SRK1 还需要做其他什么吗? 谢谢! 马蒂厄 Re: imx93: SRK revocation 您好,我也在研究 i.MX93 上的 SRK 撤销,谢谢您的提示。ahab_commit 0x10 的确是使撤销生效的原因,但我对其输出以及如何在现场设备上使用它有一个疑问。 在一台封闭的 i.MX93 上,我启动了第一个镜像,该镜像包含一个容器,该容器使用 SRK 表的第一个密钥 (SRK0) 和第四个密钥(掩码 0x8,SRK3)的撤销位进行签名,但撤销尚未应用,然后从 u-boot 控制台运行了 ahab_commit 0x10: - 第一次提交回答“Ahab 提交成功”。信息类型为 0x10”,然后第 4 个密钥似乎被撤销了:用该密钥签名的镜像(在提交之前启动)之后被拒绝; - 之后,连续三次运行完全相同的命令(相同的参数,相同的 u-boot),总是回答“Ahab commit 成功”。信息类型为 0x0,ahab_status 中没有事件。 “信息类型”值是什么意思?这是实际已执行操作的掩码吗?所以 0x0 表示没有什么需要执行的?据我所知,没有其他方法可以知道撤销是否仍在进行中(撤销前后可读的熔丝组和 ele_info 完全相同)。 这对于现场设备来说很重要,因为没有人可以在 u-boot 控制台中输入命令:提交必须由 u-boot 自动运行(启动命令)。该命令应该只运行一次(需要添加一个标志来跟踪它),还是可以每次启动时都将其保留在启动命令中?我更倾向于第二种方案,这样即使跳过了某些更新版本,任何新版本都可以包含撤销信息。 谢谢您! Re: imx93: SRK revocation 成功了,谢谢。不过,我必须添加对 ahab_commit 主线版本的支持: https://lists.denx.de/pipermail/u-boot/2024-March/548873.html Re: imx93: SRK revocation 检查是否缺少步骤 ahab_commit 0x10 此致 哈维
View full article
Question regarding SAI/eDMA support on FRDM-IMX93 (A55) with Zephyr Dear NXP Support, I am evaluating audio input/output functionality on the FRDM-IMX93 board using Zephyr. Environment: Board: FRDM-IMX93 Core: Cortex-A55 OS: Zephyr (NXP Zephyr tree) Audio Interface: SAI3 DMA: eDMA4 Audio Codec: CS42448 (MX93AUD-HAT) While enabling SAI3 and eDMA4 in Zephyr, I encountered several issues and would like to confirm whether these are known limitations or defects. 1. I2S PLL configuration File: drivers/i2s/i2s_mcux_sai.c Build fails with: #error Initialize SOC Series-specific clock_audio_pll_config_t The implementation appears to support only: CONFIG_SOC_SERIES_IMXRT10XX CONFIG_SOC_SERIES_IMXRT11XX CONFIG_SOC_SERIES_IMXRT118X and I could not find IMX93-specific handling. Is this a known issue? 2. bclkSrcSwap compilation error The following statement causes a compilation error: config.bitClock.bclkSrcSwap = false; The member exists only when: FSL_FEATURE_SAI_HAS_BIT_CLOCK_SWAP is enabled. For IMX93 this feature appears to be unavailable, yet the code still accesses the member. Is this a known bug? 3. DMA descriptor cache configuration Build fails with: #error Unexpected or disallowed cache situation for dma descriptors Since Cortex-A55 enables data cache, I had to add: CONFIG_NOCACHE_MEMORY=y to proceed. Is this configuration required for IMX93 A55? 4. eDMA4 interrupt configuration Using the default DTS definition: edma4_2 { interrupts = <0x0 0x80 0x2 0xa0>, <0x0 0x80 0x2 0xa0>, <0x0 0x81 0x2 0xa0>, <0x0 0x81 0x2 0xa0>; }; results in: multiple registrations at table_index 161 for irq 161 (0xa1) The build proceeds after overriding it with: &edma4_2 { interrupts = <0x0 0x80 0x2 0xa0>, <0x0 0x81 0x2 0xa0>; channels-shared-irq-mask = <0x3 0xc>; }; Is this a known issue in the IMX93 device tree definition? Questions Is SAI + eDMA officially supported on FRDM-IMX93 Cortex-A55 under Zephyr? Is there a known working example using SAI3 + eDMA4? Are the above four issues already known? Are there any patches, updated branches, or recommended fixes available? Thank you for your support. Best regards, #i.MX93 #ZEPHYR Re: Question regarding SAI/eDMA support on FRDM-IMX93 (A55) with Zephyr Hi @Zhiming_Liu  Thank you for your response. I understand the current situation. I am currently verifying this with v4.4.1. Could you please let me know if there are any plans for a future patch update to support the MX93AUD-HAT (TDM 8ch)? Alternatively, should I implement the support on my own? Thank you for your assistance. Best Regards, sadachi Re: Question regarding SAI/eDMA support on FRDM-IMX93 (A55) with Zephyr Hi @sadachi  I checked with the engineer who submitted the patch, and the Zephyr patch for sai+edma has only been tested in v4.1. Please refer to the document below for instructions on using the verified v4.1 version. https://community.nxp.com/t5/i-MX-Processors-Knowledge-Base/Run-Zephyr-on-A55-with-FRDM-IMX93-and-FRDM-IMX91/ta-p/2143151 If you are using version 4.1 or later, these issues are to be expected. Best Regards, Zhiming Re: Question regarding SAI/eDMA support on FRDM-IMX93 (A55) with Zephyr Hi @sadachi  At the moment, the software team doesn't have enough resources or time to look into this issue. For now, if you're in a hurry, you might want to try fixing it yourself. Best Regards, Zhiming Re: Question regarding SAI/eDMA support on FRDM-IMX93 (A55) with Zephyr Hi @Zhiming_Liu  I understand the team's situation, thank you for letting me know. I'll give it a try on my end first, and I'd appreciate any advice if I run into something unclear. Best Regards, sadachi
View full article
关于 Zephyr 对 FRDM-IMX93 (A55) 的 SAI/eDMA 支持的问题 尊敬的NXP技术支持: 我正在使用 Zephyr 评估 FRDM-IMX93 板上的音频输入/输出功能。 环境: 电路板:FRDM-IMX93 核心:Cortex-A55 操作系统:Zephyr(NXP Zephyr 内核树) 音频接口:SAI3 DMA:eDMA4 音频编解码器:CS42448 (MX93AUD-HAT) 在 Zephyr 中启用 SAI3 和 eDMA4 时,我遇到了一些问题,想确认这些是已知的限制还是缺陷。 1. I2S PLL 配置 文件: drivers/i2s/i2s_mcux_sai.c 版本失败,并显示以下错误信息: #错误 初始化 SOC 系列特定 clock_audio_pll_config_t 该实现似乎仅支持: CONFIG_SOC_SERIES_IMXRT10XX CONFIG_SOC_SERIES_IMXRT11XX CONFIG_SOC_SERIES_IMXRT118X 我找不到针对 IMX93 的特定处理方法。 这是已知问题吗? 2. bclkSrcSwap 编译错误 以下语句会导致编译错误: config.bitClock.bclkSrcSwap = false; 该成员仅在以下情况下存在: FSL_FEATURE_SAI_HAS_BIT_CLOCK_SWAP 已启用。 对于 IMX93,此功能似乎不可用,但代码仍然可以访问成员。 这是已知漏洞吗? 3. DMA描述符缓存配置 版本失败,并显示以下错误信息: #错误 DMA描述符的缓存情况意外或被禁止 由于 Cortex-A55 支持数据缓存,所以我必须添加: CONFIG_NOCACHE_MEMORY=y 继续。 IMX93 A55 是否需要这种配置? 4. eDMA4 中断配置 使用默认的 DTS 定义: edma4_2 { 中断 = <0x0 0x80 0x2 0xa0>, <0x0 0x80 0x2 0xa0>, <0x0 0x81 0x2 0xa0>, <0x0 0x81 0x2 0xa0>; }; 结果如下: 在表索引 161 处存在多个注册 中断 161 (0xa1) 覆盖此设置后,版本将继续进行: &edma4_2 { 中断 = <0x0 0x80 0x2 0xa0>, <0x0 0x81 0x2 0xa0>; channels-shared-irq-mask = <0x3 0xc>; }; 这是 IMX93 设备树定义中已知的问题吗? 问题 Zephyr 系统下,FRDM-IMX93 Cortex-A55 是否正式支持 SAI + eDMA? 是否有使用 SAI3 + eDMA4 的已知可行示例? 以上四个问题是否已被知晓? 是否有任何补丁、更新分支或推荐的修复方案? 感谢您的支持。 顺祝商祺! #i.MX93 #和风 Re: Question regarding SAI/eDMA support on FRDM-IMX93 (A55) with Zephyr 嗨@Zhiming_Liu 感谢您的回复。 我了解目前的情况。 我目前正在使用 v4.4.1 版本进行验证。 请问未来是否有计划发布补丁更新以支持 MX93AUD-HAT(TDM 8通道)? 或者,我应该自己实现这个支持功能吗? 谢谢你的帮助。 顺祝商祺! 佐田 Re: Question regarding SAI/eDMA support on FRDM-IMX93 (A55) with Zephyr 嗨@sadachi 我向提交补丁的工程师确认过,Sai+EDMA 的Zephyr 补丁只在 v4.1 版本中测试过。 请参考以下文档,了解如何使用已验证的 v4.1 版本。 https://community.nxp.com/t5/i-MX-Processors-Knowledge-Base/Run-Zephyr-on-A55-with-FRDM-IMX93-and-FRDM-IMX91/ta-p/2143151 如果您使用的是 4.1 或更高版本,则出现这些问题是正常的。 此致, 志明 Re: Question regarding SAI/eDMA support on FRDM-IMX93 (A55) with Zephyr 嗨@sadachi 目前,软件团队没有足够的资源或时间来调查这个问题。如果你时间紧迫,不妨现在就尝试自己修理。 此致, 志明 Re: Question regarding SAI/eDMA support on FRDM-IMX93 (A55) with Zephyr 嗨@Zhiming_Liu 我了解球队的情况,谢谢你告诉我。 我先自己试一下,如果遇到任何不清楚的地方,请不吝指点。 此致, 佐田
View full article
imx93: SRK revocation Hello, I am trying to perform key revocation on my closed imx93 board. My CSF file looks like: [Header] Target = AHAB Version = 1.0 [Install SRK] File = "../cst-3.4.0/crts/SRKtable.bin" Source = "../cst-3.4.0/crts/SRK2_sha384_secp384r1_v3_usr_crt.pem" Source index = 1 Source set = OEM Revocations = 0x1 [Authenticate Data] File = "spl.bin" Offsets = 0x400 0x490 The idea is to sign with SRK2 and revoke SRK1 (0x1 bitmask). Booting from that image works fine, but I can still also boot from an image signed with SRK1. Is there anything else that needs to be done in order to revoke SRK1? Thanks, Mathieu Re: imx93: SRK revocation Hello, I am working on SRK revocation on i.MX93 too, and thanks for the hint. ahab_commit 0x10 is indeed what makes the revocation effective, but I have a question about its output and about how to use it on devices in the field. On a closed i.MX93, I booted the first image carrying a container signed with the first key of the SRK table (SRK0) and with the revoke bit of the 4th key (mask 0x8, SRK3), with the revocation not yet applied, and ran ahab_commit 0x10 from the u-boot console: - this first commit answered "Ahab commit succeeded. Information type is 0x10", and the 4th key then seems to be revoked: an image signed with it, which booted before the commit, is refused afterwards; - after that, running exactly the same command again (same argument, same u-boot), three times in a row, always answers "Ahab commit succeeded. Information type is 0x0", with no events in ahab_status. What does the "Information type" value mean? Is it the mask of what has actually been committed, so 0x0 means nothing was left to commit? As far as I can see there is no other way to know whether a revocation is still pending (the readable fuse banks and ele_info are identical before and after). This matters for devices in the field, where nobody can type the command in the u-boot console: the commit has to be run automatically by u-boot (boot command). Should it be run only once, which would need a flag to track it, or is it fine to leave it in the boot command at every boot? I would prefer the second option, so that any new build can carry the revocation even if some update version was skipped. Thanks! Re: imx93: SRK revocation That worked thanks. I had to add support for ahab_commit mainline though: https://lists.denx.de/pipermail/u-boot/2024-March/548873.html Re: imx93: SRK revocation check if missing the step ahab_commit 0x10 Regards Harvey
View full article
バグ:dw-mipi-dsi:非バーストDSIブリッジで720p60が壊れています こんにちは、 NXPのダウンストリームカーネル(lf-6.18.y)に問題が発生しており、その原因は以下の通りだと考えています。 ▎ LF-14666-2: drm/bridge: synopsys: dw-mipi-dsi: 720p60 の修正を実装 TI SN65DSI86(DSI-DisplayPort変換アダプタ)を搭載したi.MX95では、720p60で画像がちらつく。 非バーストモードでは、DSI_VID_HLINE_TIME は htotal * bpp / (lanes * 😎 レーンバイトクロックサイクル。整数でない場合は切り上げ。720p60で4レーン、RGB888の場合、1237.5となり、四捨五入すると1238になります。DSIラインはDPIラインよりも長くなり、フレーム全体にわたって誤差が蓄積されていく。HFP中にLPに戻った場合のみ、すべてのラインでラインタイマーがDPIに再同期されます。 メインラインでは常にHFPでLPが有効になります。LF-14666-2では、DSIデバイスがMIPI_DSI_MODE_VIDEO_NO_HFPを設定した場合のみ、これをオプションにしました。これはLT8912Bに合っています。なぜならLF-14666-1はそのドライバにフラグを追加するからです。しかし、丸めはデバイスではなくホストコントローラから来ているため、フラグを設定しない他のブリッジやパネル(例えばSN65DSI86)は、ライン時間が分数になると壊れてしまいます。 このメッセージに問題を修正するパッチを添付しました。どなたか見ていただけるとありがたいです。 ありがとう、 アントワーヌ・グビー Linux
View full article
imx93: SRKの取り消し こんにちは、 私は、閉鎖済みのimx93ボード上で鍵の失効処理を実行しようとしています。 私のCSFファイルは次のようになっています。 [ヘッダ] ターゲット=アハブ バージョン = 1.0 [SRKをインストール] ファイル = "../cst-3.4.0/crts/SRKtable.bin" ソース = "../cst-3.4.0/crts/SRK2_sha384_secp384r1_v3_usr_crt.pem" ソースインデックス = 1 ソースセット = OEM 取り消し = 0x1 [データの認証] ファイル = "spl.bin" オフセット = 0x400 0x490 このアイデアはSRK2に署名し、SRK1(0x1ビットマスク)を取り消すことです。そのイメージから起動しても問題ありませんが、SRK1で署名されたイメージからも起動できます。 SRK1の資格を取り消すために、他に何か必要な手続きはありますか? ありがとうございます マチュー Re: imx93: SRK revocation こんにちは。私もi.MX93でSRKの失効処理に取り組んでおり、ヒントをありがとうございます。ahab_commit 0x10 は確かに失効を有効にするものですが、その出力と、現場のデバイスでどのように使用するかについて質問があります。 閉じた状態の i.MX93 上で、SRK テーブルの最初のキー (SRK0) と 4 番目のキーの失効ビット (マスク 0x8、SRK3) で署名されたコンテナを含む最初のイメージを起動し、失効処理はまだ適用されていません。そして、u-boot コンソールから ahab_commit 0x10 を実行しました。 - この最初のコミットは「Ahab コミットが成功しました」と回答しました。情報タイプは「0x10」であり、4番目のキーが失効したようです。コミット前に起動した、そのキーで署名されたイメージは、その後拒否されます。 その後、まったく同じコマンド(同じ引数、同じ u-boot)を 3 回連続で実行すると、常に「Ahab コミットが成功しました」という応答が返されます。情報タイプは0x0」であり、ahab_statusにイベント情報はありません。 「情報タイプ」の値は何を意味しますか?それは実際に犯されたことの仮面で、犯すことが何も残っていない0x0なのでしょうか?私の知る限り、取り消しがまだ保留中かどうかを知る他の方法はない(ヒューズバンクとele_infoは前後で同一です)。 これは現場のデバイスで重要で、u-bootコンソールでコマンドを入力できないため、コミットはu-boot(起動コマンド)によって自動的に実行されなければなりません。一度だけ実行するようにすれば、それを追跡するためのフラグが必要になりますが、それとも毎回起動時のブートコマンドに含めておいても問題ありませんか?私は後者の方が好みです。そうすれば、新しいビルドはアップデートバージョンがスキップされていても取り消しを継続できるからです。 よろしくお願いします! Re: imx93: SRK revocation うまくいきました、ありがとうございます。ただ、メインラインのサポートahab_commit追加しなければなりませんでした: https://lists.denx.de/pipermail/u-boot/2024-March/548873.html Re: imx93: SRK revocation ahab_commit 0x10 のステップが欠落していないか確認します よろしくお願いします。 Harvey
View full article
S32G399 裸机 DDR 初始化 问候! 我们正在尝试在启动过程中重现这一核心序列: 但在 M7 内核初始化 DDR 时遇到了一些问题。 1. 我们在 Design Studio 中根据示例创建了一个新项目;(Linflexd_Uart_Ip_Example_S32G399A_M7: Debug_RAM); 2.配置并验证了DDR,生成了与ddr_*.c相关的源文件; 3. 从 GoldVIP 示例和 arm-trusted-firmware 中复制并修改了一些与 DDR 初始化相关的代码; 4. 我们在 main.c 中有这样的代码序列:   Clock_Ip_Init(&Mcu_aClockConfigPB[0]); IntCtrl_Ip_Init(&IntCtrlConfig_0); Siul2_Port_Ip_Init(NUM_OF_CONFIGURED_PINS0, g_pin_mux_InitConfigArr0); Mpu_M7_Ip_Init(&MPU_M7_ModuleConfig_0); EnableRdInterconnect(2); // RD2 EnableRdInterconnect(3); // RD3 /* 2. NoC QoS */ FlexNOC_InitNoc(4); // 4 - CORE_ID_M7_0 enable_partition(); ddr_status = ddr_init();   我们注意到,DDR初始化后处于睡眠模式,所以我们将其唤醒:   *(volatile uint32_t*)0x403C0000 = 0x83080023; *(volatile uint32_t*)0x403C0020 &= ~0x1; *(volatile uint32_t*)0x403C0030 = 0x0; *(volatile uint32_t*)0x403C0320 = 0x0; *(volatile uint32_t*)0x403C0320 = 0x1;   DDR 内存从地址 0x60000000 开始,因此在使用调试探针进行调试时,我们可以在汇编代码中看到内存已分配,没有错误,也没有硬故障,但是如果我们在 GDB 中调用:   set {uint32_t}0x60000000 = 0xDEADBEEF 或 x/1xw 0x60000000   它返回“无法访问地址 0x60000000 处的内存”。   ddr_status返回0 。   请问我们哪里做错了?该图是否真的适用于NXP推荐的S32G399板启动方式?   谢谢! Re: S32G399 Bare Metal DDR initialization 你好, @Interrogator 感谢你的帖子。 实际上,您提到的流程并不是使用 S32G 平台时的典型启动流程。 典型的启动流程如 AN13750 和 GoldVIP 中所述,启动加载程序在 M7_0 上运行(也是初始化时钟、引脚等),负责加载不同分区(如 M7_1/2、A53_0)的映像,而 Linux 电路板支持包。加载到 A53_0,DDR 将由在 A53_0 上运行的 TFA 初始化。 请问您目前正在进行设计工作吗?如果是这样,相对推荐使用上述启动流程。 BR 陈银 Re: S32G399 Bare Metal DDR initialization @chenyin_h谢谢你的回复!我非常感谢。您能否也帮我理解一件事:我们目前手头有这块板,但 M7 可能没有引导加载程序。我们将 Yocto 电路板支持包。 46 构建的 Linux 镜像烧录到 SD 卡(.sdcard 文件)上,将卡插入板子,切换板上的引脚以从 SD 卡加载,并期望与 S32G274 上的行为相同,但 UART 输出完全为空。虽然在 COM 会话 (MobaXterm) 中按下按钮会导致板上的 Rx 指示灯闪烁。要查看 Linux 输出,我们需要 M7 引导加载程序,对吗?请问针对我们目前的情况,您能提出最佳解决方案吗? 谢谢你! Re: S32G399 Bare Metal DDR initialization @chenyin_h你好! 1.我们使用定制板,该电路板只有 SW3、SW6.1-2、SW10.1-2 和 SW12.1-2 引脚。 2. 我们在我们的机器上运行 bitbake,并从源代码(内核、引导加载程序、根文件系统)构建镜像。 Re: S32G399 Bare Metal DDR initialization 你好, @Interrogator 感谢您的回复。 如果您不需要使用 M7 端,则仅使用电路板支持包。启动主板即可。(M7 在这种设置下,引导加载程序并非必需。) 关于您遇到的问题 1. 使用的是哪种类型的板?定制方案还是恩智浦的参考设计? 2. 如何生成写入 SD 卡的 BSP46 镜像?使用的是预构建镜像还是自定义镜像? BR 陈银  Re: S32G399 Bare Metal DDR initialization 你好, @Interrogator 谢谢你的确认 1. 通常情况下,使用默认的 电路板支持包。 代码/设置,构建的镜像旨在启动 S32G3 参考板,如 RDB3/EVB3。 2. 由于您使用的是定制板,因此构建的映像可能无法正确启动该板,这实际上是定制板启动问题。 不确定您是否对原始的 BSP46 电路板支持包。进行过任何修改,以及是否有任何调试日志可以帮助定位问题? BR 陈银 Re: S32G399 Bare Metal DDR initialization 您好, @chenyin_h 感谢您的积极参与! 1. 我们刚刚试用了预构建的电路板支持包。 46,但很遗憾地遇到了同样的问题。 2. 我们使用 s32g3xx_attach.py 脚本对 A 核心进行调试,并在调试器控制台中发现了以下日志: 394,149 =cmd-param-changed,param="remote hardware-breakpoint-limit",value="6" 394,149 =cmd-param-changed,param="remote hardware-watchpoint-limit",value="4" 394,150 =cmd-param-changed,param="默认无法访问的内存",value="关闭" 394,151 =cmd-param-changed,param="默认无法访问的内存",value="开启" 394,164 ~“核心无法停止。状态:CoreMode.Disabled\r\n” 394,165 ~“错误类型:[CoreError]\r\n” 394,165 ~"错误代码:[200]\r\n" 394,165 ~"\r\n" 394,165 ~"\r\n" 394,165 ~" --- 初始化脚本的堆栈跟踪 ---\r\n" 这能给你提供什么线索吗? 在 M 核心上运行 s32g3xx_attach.py 返回相同的结果。 然而,s32g3xx_generic_bareboard.py 运行良好,但我们的想法是将调试器附加到已启动的核心,并通过汇编中的寄存器检查其状态。 Re: S32G399 Bare Metal DDR initialization 你好, @Interrogator 感谢您的回复。 BSP46预编译镜像应该可以在RDB3上运行(除非是非常老的版本板)。 1. 请问您是否同时拥有RDB3和定制板?(因为您在不同的回复中提到了不同的板) 2. 最终目标是运行基于自定义板的 电路板支持包。 或 GoldVIP 风格设计(M 引导加载程序 -> A(电路板支持包。) + M(App))吗?RDB3 就足够了吗? 我们可以进一步讨论细节(如果某些内容不方便分享,我们也可以在私信/支持案例中讨论),并将目标分成几个阶段,以帮助您在设计的系统中高效地使用 S32G。 BR 陈银 Re: S32G399 Bare Metal DDR initialization 你好, @Interrogator 感谢您的回复。 抱歉,我对您的测试设置有些困惑,您能否详细说明一下? 1. 从硬件角度来看,请问您使用的是定制板(由贵公司或第三方设计的板)还是参考板(由恩智浦设计,您可以从恩智浦或任何授权分销商处购买,S32G3 的参考板可能被称为 RDB3/EVB3/GoldBox3)? 2. 电路板支持包。 是 NXP 版本的软件,主要面向 S32G3 的 A53 端运行。请问您的最终目标是在 RDB3 上运行电路板支持包。,还是在您的定制板上运行电路板支持包。? BR 陈银 Re: S32G399 Bare Metal DDR initialization 你好, @chenyin_h 很抱歉之前的帖子回答得不够清楚。让我再解释一下: 1.我手里拿着一块定制板。 2. 我的最终目标是在我们定制的电路板上运行电路板支持包。。 谢谢你! Re: S32G399 Bare Metal DDR initialization 你好, @chenyin_h 1.我只有一块定制的开发板,我尝试了用上市,不用发布它的不同方法(RDB3 和 GoldVIP)。 2. 最终目标是运行 RDB3/电路板支持包。方法。 感谢您的参与,我很乐意接受进一步的帮助。您需要哪些额外信息? Re: S32G399 Bare Metal DDR initialization 你好, @Interrogator 谢谢您的确认。 对于此类问题,我可能需要先查看您的硬件设计,以便方便地分享原理图等信息。稍后我会帮您创建一个私人案例,以便更好地进行进一步讨论。 BR 陈银
View full article
S32G399 ベアメタル DDR 初期化 こんにちは! 私たちは、起動プロセスにおいてこのコアシーケンスを再現しようとしています。 しかし、M7コアによるDDR初期化中にいくつかの問題が発生しました。 1. Design Studioの例から新しいプロジェクトを作成しました;(Linflexd_Uart_Ip_Example_S32G399A_M7: Debug_RAM); 2. DDRの設定と検証を行い、ddr_*.cに関連するソースファイルを生成しました。 3. GoldVIP例およびarm-trusted-firmwareからDDR初期化に関するコードをコピー・調整; 4. main.c には次のようなコードシーケンスがあります。   Clock_Ip_Init(&Mcu_aClockConfigPB[0]); IntCtrl_Ip_Init(&IntCtrlConfig_0); Siul2_Port_Ip_Init(NUM_OF_CONFIGURED_PINS0, g_pin_mux_InitConfigArr0); Mpu_M7_Ip_Init(&MPU_M7_ModuleConfig_0); EnableRdInterconnect(2); // RD2 EnableRdInterconnect(3); // RD3 /* 2. NoC QoS */ FlexNOC_InitNoc(4); // 4 - CORE_ID_M7_0 enable_partition(); ddr_status = ddr_init();   DDRが初期化された後はスリープモードになることに気づいたので、私たちはそれを起動します:   *(volatile uint32_t*)0x403C0000 = 0x83080023; *(volatile uint32_t*)0x403C0020 &= ~0x1; *(volatile uint32_t*)0x403C0030 = 0x0; *(volatile uint32_t*)0x403C0320 = 0x0; *(volatile uint32_t*)0x403C0320 = 0x1;   DDRメモリはアドレス0x60000000から始まるため、Debug Probeでのデバッグ中にアセンブリでメモリが割り当てられていることが確認できます。エラーもハードフォルトもありませんが、GDBで呼び出すと:   set {uint32_t}0x60000000 = 0xDEADBEEF または x/1xw 0x60000000   「アドレス0x60000000のメモリにアクセスできません」と返されます   ddr_status は0を返します。   私たちが何を間違っているのか教えていただけますか?そして、その図はNXPが推奨するS32G399ボードの起動方法として実際に適用できるものなのでしょうか?   ご回答をお待ちしています。 Re: S32G399 Bare Metal DDR initialization こんにちは、 @Interrogator 投稿ありがとうございます。 実は、あなたが言及したフローはS32Gプラットフォームを使う際の典型的なブートフローではありません。 典型的なブートフローは、AN13750やGoldVIPで説明されている通りで、ブートローダーがM7_0(イニットクロックやピンなど)上で動作し、異なるパーティション(M7_1/2、A53_0など)のイメージを読み込みます。一方、Linux BSPはA53_0に読み込まれ、DDRはA53_0上で動作するTFAによって初期化されます。 現在、デザインに取り組んでいるか教えていただけますか?もしそうなら、上記のブートフローを使うことが比較的推奨されます。 BR チェイン Re: S32G399 Bare Metal DDR initialization @chenyin_hこんにちは! 1.当社では、SW3、SW6.1-2、SW10.1-2、SW12.1-2のピンのみを備えたカスタム基板を使用しています。 2. マシン上でbitbakeを実行し、ソースコード(カーネル、ブートローダー、ルートファイルシステム)からイメージを構築します。 Re: S32G399 Bare Metal DDR initialization @chenyin_h返信ありがとうございます!本当に感謝しています。もう一つ教えてもらえますか?現在ボードは手元にあり、M7にはブートローダーがない可能性があります。Yocto BSP 46で構築されたLinuxイメージをSDカード(.sdcardファイル)に書き込み、ボードにカードを差し込み、ボードのピンをSDカードから読み込むように切り替えましたが、S32G274と同じ動作を期待していましたが、UARTの出力は完全に空でした。COMセッション(MobaXterm)中にボタンを押すと、ボード上のRxインジケーターが点滅します。Linux出力を見るにはM7ブートローダーが必要ですよね?私たちの状況で最善の方法を教えていただけませんか? ありがとう! Re: S32G399 Bare Metal DDR initialization こんにちは、 @Interrogator 確認ありがとうございます 1. 通常、デフォルトのBSPコード/設定では、構築されるイメージはRDB3/EVB3のようなS32G3リファレンスボードの起動をターゲットとしています。 2. カスタムボードを扱っている場合、正しく起動できなかったイメージが作られ、これはカスタムボードの表示問題である可能性があります。 オリジナルのBSP46 BSPに何らかの変更を加えたかどうか、また問題箇所を特定するためのデバッグログがあるかどうかは分かりません。 BR チェイン Re: S32G399 Bare Metal DDR initialization こんにちは、 @Interrogator ご返信ありがとうございます。 M7側を使用する必要がない場合は、BSPのみを使用してボードを起動すれば十分です。(M7ブートローダーはこのような設定では必須ではありません。 あなたが遭遇した問題に関して 1. どのような種類のボードが使用されていますか?カスタムのものか、NXPのリファレンスデザインか? 2. SDカードに書き込まれるBSP46イメージはどのように生成されるのですか?既製のイメージとカスタムイメージのどちらが使用されますか? BR チェイン  Re: S32G399 Bare Metal DDR initialization こんにちは、 @chenyin_h 積極的なご参加ありがとうございました! 1. 現在、S32G3 RDB3 用のプリビルド済み BSP 46 を試してみましたが、残念ながら同じ問題が発生しました。 2. s32g3xx_attach.pyスクリプトを使用してAコアのデバッグを開始したところ、デバッガーコンソールに次のログが表示されました。 394,149 =cmd-param-changed, param="remote hardware-breakpoint-limit", value="6" 394,149 =cmd-param-changed, param="remote hardware-watchpoint-limit", value="4" 394,150 =cmd-param-changed,param="mem inaccessible-by-default",value="off" 394,151 =cmd-param-changed,param="mem inaccessible-by-default",value="on" 394,164 ~「コアは止められない。状態: CoreMode.Disabled\r\n" 394,165 ~"エラーの種類: [CoreError]\r\n" 394,165 ~"エラーコード: [200]\r\n" 394,165 ~"\r\n" 394,165 ~"\r\n" 394,165 ~" --- 初期化スクリプトのスタックトレース ---\r\n" 何か手がかりになりますか? Mコア上でs32g3xx_attach.pyを実行しても同じ結果が返されます。 しかし、s32g3xx_generic_bareboard.py問題なく動作しますが、私たちのアイデアは、すでに起動しているコアにデバッガーを接続し、アセンブリのレジスタでその状態を確認することでした。 Re: S32G399 Bare Metal DDR initialization こんにちは、 @Interrogator ご返信ありがとうございます。 BSP46のプリビルドイメージは、RDB3で動作するはずです(ただし、非常に古いバージョンのボードの場合は除きます)。 1. RDB3とカスタムボードの両方をお持ちかどうか確認していただけますか?(ご回答ごとに異なるボードについて言及されているため) 2. 最終的な目標はBSPスタイルかGoldVIPスタイルのデザイン(Mブートローダー-> A(BSP)+M(App))で動かすことですか?カスタムボードベースかRDB3で十分ですか? 詳細についてはさらに話し合うこともできます(内容の一部が共有に不便な場合は、個別メッセージやサポートCASEでお話しするかもしれません)、ターゲットをいくつかのフェーズに分けて、S32Gをあなたのシステムで効率的に活用できるようにしたいと思います。 BR チェイン Re: S32G399 Bare Metal DDR initialization こんにちは、 @chenyin_h 前回の投稿で分かりにくい回答をしてしまい、申し訳ありませんでした。もう少し詳しく説明させてください。 1.私はカスタムボードを持っています 2. 私の最終目標は、カスタムボード上でBSPを実行することです。 ありがとう! Re: S32G399 Bare Metal DDR initialization こんにちは、 @Interrogator ご返信ありがとうございます。 テスト設定について少し混乱している点があり申し訳ありません。よろしければ、もう少し詳しく説明していただけますでしょうか? 1. ハードウェアの観点から、あなたが持っているのはカスタムボード(御社または第三者が設計したボード)か、NXPが設計したリファレンスボード(NXPや認定ディストリビューターから購入可能で、S32G3のリファレンスボードはRDB3/EVB3/GoldBox3と呼ばれることがある)ですか? 2. BSPはNXPがリリースしたソフトウェアで、主にS32G3のA53側で動作することをターゲットにしています。最終的な目標がBSPをRDB3上で動かすことなのか、ご確認いただけますか?それともカスタム基板上でBSPを動かすのですか? BR チェイン Re: S32G399 Bare Metal DDR initialization こんにちは、 @Interrogator ご確認いただきありがとうございます。 このような問題がある場合は、まずハードウェア設計を確認する必要があるかもしれません。回路図のような情報を便利に共有するために、後でプライベートCASEの作成をお手伝いしますので、より詳しい議論ができるようにします。 BR チェイン Re: S32G399 Bare Metal DDR initialization こんにちは、 @chenyin_h さん 1.私はカスタムボードしか持っていません。起動するために様々な方法(RDB3とGoldVIP)を試してみました。 2. 最終目標は、RDB3/BSP方式を実行することです。 ご尽力いただきありがとうございます。今後も何かお手伝いできることがあれば、ぜひお願いしたいです。他にどのような情報があれば役立ちますか?
View full article
i.MX93 FRDM: RAW10 capture through ISI writes only one line per frame with IMX219 and IMX708 Hello, We are bringing up MIPI CSI-2 RAW cameras on the FRDM-IMX93 and would appreciate NXP's help. With both an IMX219 and an IMX708, streaming starts and frames are delivered, but only one line of each captured frame contains data. All other lines are zero. On the IMX219 this happens at every resolution we tested. We do not know the cause and would be grateful for your guidance. A similar symptom was reported here on kernel 6.12.20, without a resolution: https://community.nxp.com/t5/i-MX-Graphics/i-MX93-RAW10-capture-issue-only-first-line-valid-IMX219-ISI/m-p/2321729 Environment - Board: FRDM-IMX93 (MACHINE = imx93-11x11-lpddr4x-frdm), camera on the P6 MIPI CSI connector - BSP: imx-6.18.37-2.1.0 from nxp-imx/imx-manifest (meta-imx rel_imx_6.18.37_2.1.0), Yocto 6.0.2 wrynose, DISTRO = fsl-imx-wayland - Kernel: 6.18.37-2.1.0-gddef48f9b907 - Pipeline: sensor -> csidev-4ae00000.csi (dwc-mipi-csi2) -> crossbar -> mxc_isi.0 -> mxc_isi.0.capture (/dev/video0) - Format: SRGGB10_1X10 / RG10, 2 data lanes Sensors 1. Raspberry Pi Camera Module v2 NoIR (IMX219) - In-tree imx219 driver and the unmodified BSP CSI and ISI drivers - Link frequency: 456 MHz 2. Raspberry Pi Camera Module 3 NoIR (IMX708) - Driver ported from the Raspberry Pi kernel (rpi-6.12.y) - Link frequency: 450 MHz - Without further changes, this sensor produces an IPI FIFO overflow and no frames. With sensor register 0x3095 set to 0, frames are delivered at 56 fps at 2304x1296. Results Sensor Resolution Image source Result IMX219 640x480 live image, colour bars frames delivered, only line 0 has data IMX219 1640x1232 colour bars frames delivered, only line 0 has data IMX219 1920x1080 live image, colour bars frames delivered, only line 0 has data IMX219 3280x2464 colour bars frames delivered (14.5 fps), only line 0 has data IMX708 2304x1296 colour bars frames delivered (56 fps), only line 0 has data In each case the buffer has the expected size (width x height x 2 bytes). Line 0 contains the expected data, for example the colour bars. All remaining lines are zero. The IMX219 tests reported no CSI or ISI errors in dmesg. Commands (IMX219, 640x480) media-ctl -V "'imx219 2-0010':0[fmt:SRGGB10_1X10/640x480]" media-ctl -V "'csidev-4ae00000.csi':0[fmt:SRGGB10_1X10/640x480 field:none]" media-ctl -V "'crossbar':0[fmt:SRGGB10_1X10/640x480 field:none]" media-ctl -V "'mxc_isi.0':0[fmt:SRGGB10_1X10/640x480 field:none]" media-ctl -V "'mxc_isi.0':1[fmt:SRGGB10_1X10/640x480 field:none]" v4l2-ctl -d /dev/video0 --set-fmt-video=width=640,height=480,pixelformat=RG10 \ --stream-mmap --stream-count=10 --stream-to=/tmp/cap.bin Register values read during streaming (IMX219, 640x480, debug CSI build, same symptom) ISI 0x4ae40000: CHNL_CTRL (0x00) = 0xe0000000 CHNL_IMG_CTRL (0x04) = 0x0f008001 CHNL_IMG_CFG (0x0c) = 0x01e00280 Media mix 0x4ac10000: 0x30 = 0x00010158 0x3c = 0x00000e07 0x40 = 0x00000001 0x44 = 0x00019140 (value between frames) 0x48 = 0x0002291c Questions 1. Is RAW capture from a CSI-2 sensor through the ISI validated on i.MX93? If so, which sensor, BSP version and configuration were used? 2. Are there known issues, errata or required settings that apply to this use case? 3. What should we check next? Please let us know which registers, logs or captures would be useful, and we will provide them. 4. Is a reference device tree or patch available for IMX219 or another RAW sensor on FRDM-IMX93? We can share full logs, the device tree overlay and raw captures on request. Thank you for your support. Linux Yocto Project Re: i.MX93 FRDM: RAW10 capture through ISI writes only one line per frame with IMX219 and IMX708 I sent to you the patch for imx219 already, pls refer to this 
View full article
S32 Design Studioのライセンスが切れました 親愛なるNXPへ: S32 Design Studio 3.5のライセンスがまもなく期限切れになります。      ライセンス延長を手伝ってもらえますか?      ありがとう。 アクティベーションID: 29E6-6248-FCB2-DBB6 Re: S32 Design Studio License Expired こんにちは、 お客様のS32DSライセンスが延長されました。以前のコードを使用して、S32DSを再度有効化してください。
View full article
i.MX93 FRDM: ISI を介した RAW10 キャプチャでは、IMX219 および IMX708 ではフレームごとに 1 行しか書き込まれません こんにちは、 FRDM-IMX93上でMIPI CSI-2 RAWカメラを起動させようとしており、NXPのご協力をいただければ幸いです。IMX219とIMX708の両方で、ストリーミングの開始とフレームが配信されますが、キャプチャされるのはそれぞれ1ラインのみです。 フレームにはデータが含まれています。その他の行はすべてゼロです。IMX219では、テストしたすべての解像度でこの現象が発生します。原因が不明なため、ご助言いただければ幸いです。 同様の症状がカーネル6.12.20でも報告されていますが、解決策は見つかっていません。 https://community.nxp.com/t5/i-MX-Graphics/i-MX93-RAW10-capture-issue-only-first-line-valid-IMX219-ISI/mp/2321729 環境 - ボード: FRDM-IMX93 (マシン = imx93-11x11-lpddr4x-frdm)、カメラはP6 MIPI CSIコネクタに接続 - BSP: imx-6.18.37-2.1.0nxp-imx/imx-manifest (meta-imx rel_imx_6.18.37_2.1.0) から、Yocto 6.0.2 wrynose, DISTRO = fsl-imx-wayland - カーネル:6.18.37-2.1.0-gddef48f9b907 - パイプライン:センサ -> csidev-4ae00000.csi (dwc-mipi-csi2) -> クロスバー -> mxc_isi.0-> mxc_isi.0.capture (/dev/video0) - フォーマット: SRGGB10_1X10 / RG10、2データレーン センサ 1. ラズベリーパイカメラモジュールv2 NoIR(IMX219) - インツリーのimx219ドライバおよび修正されていないBSP CSIおよびISIドライバ - リンク周波数:456 MHz 2. ラズベリーパイカメラモジュール3 NoIR(IMX708) - Raspberry Piカーネル(rpi-6.12.y)から移植されたドライバ - リンク周波数:450 MHz - 追加変更なしでは、このセンサはIPI FIFOオーバーフローを生成し、フレームは発生しません。センサーレジスタ0x3095を0に設定すると、フレームは2304x1296で56fpsで配信されます。 結果 センサ解像度画像ソースの結果 IMX219 640x480のライブ画像、カラーバーフレームが配信中、データがあるのはライン0のみです IMX219 1640x1232カラーバーフレームが届きましたが、データがあるのはライン0のみです IMX219 1920x1080 ライブ画像、カラーバーフレームを配信、データがあるのはライン0のみ IMX219 3280x2464カラーバーのフレームは14.5fpsで配信され、データがあるのはライン0のみです IMX708 2304x1296カラーバーのフレームが配信されました(56fps)、データがあるのはライン0のみです 各CASEで、バッファは期待されるサイズ(幅×高さ×2バイト)を持ちます。0行目には、例えばカラーバーなど、期待されるデータが含まれています。残りの行はすべてゼロです。IMX219のテストでは、CSIまたはISIは報告されませんでした。 dmesg にエラーが表示されます。 コマンド(IMX219、640x480) media-ctl -V "'imx219 2-0010':0[fmt:SRGGB10_1X10/640x480]" media-ctl -V "'csidev-4ae00000.csi':0[fmt:SRGGB10_1X10/640x480 field:none]" media-ctl -V "'crossbar':0[fmt:SRGGB10_1X10/640x480 field:none]" media-ctl -V "'mxc_isi.0':0[fmt:SRGGB10_1X10/640x480field:noe]" media-ctl -V "'mxc_isi.0':1[fmt:SRGGB10_1X10/640x480フィールド:なし]" v4l2-ctl -d /dev/video0 --set-fmt-video=width=640,height=480,pixelformat=RG10 \ --stream-mmap --stream-count=10 --stream-to=/tmp/cap.bin ストリーミング中のレジスタ値の読み取り(IMX219、640x480、デバッグCSIビルド、同じ症状) ISI 0x4ae40000: CHNL_CTRL (0x00) = 0xe0000000 CHNL_IMG_CTRL (0x04) = 0x0f008001 CHNL_IMG_CFG (0x0c) = 0x01e00280 メディアミックス0x4ac10000: 0x30 = 0x00010158 0x3c = 0x00000e07 0x40 = 0x00000001 0x44 = 0x00019140(フレーム間の値) 0x48 = 0x0002291c 質問 1.ISIを経由したCSI-2センサからのRAWキャプチャはi.MX93で検証されますか?もしCASEなら、どのセンサ、BSPバージョン、構成が使われましたか? 2. このユースCASEに適用される既知の問題、訂正表、または必須設定はありますか? 3. 次に何を調べるべきか?どのレジスタ、ログ、キャプチャが役立つかをお知らせいただければ、ご提供いたします。 4. FRDM-IMX93上のIMX219や他のRAWセンサの参照デバイスツリーやパッチはありますか? リクエストに応じて、完全なログ、デバイスツリーのオーバーレイ、生のキャプチャも共有可能です。 再開まで今しばらくお待ちください。 Linux Yocto Project Re: i.MX93 FRDM: RAW10 capture through ISI writes only one line per frame with IMX219 and IMX708 imx219用のパッチは既にお送りしましたので、こちらをご参照ください。
View full article
S32 Design Studio License Expired Dear NXP:      The S32 Design Studio 3.5 license is about to expire.      Could you please help extend the license?      Thank you.      ActivationId: 29E6-6248-FCB2-DBB6 Re: S32 Design Studio License Expired Hi,  your S32DS license has been extended. Please activate S32DS again with your old code. 
View full article
FRDM-MCXN947でMicroPythonを動かす (日本語ブログ) MicroPython, FRDM-MCXN947, ZephyrMicroPython, FRDM-MCXN947, ZephyrMicroPython, FRDM-MCXN947, ZephyrMicroPython, FRDM-MCXN947, Zephyr MicroPythonの本家リポジトリ,そのZephyrポートに,FRDM-MCXN947向けの設定がマージされました. Zephyrポートというのは,MicroPythonをZephyr RTOSの上で動かす移植版です.MicroPythonは通常,マイコンの種類ごとに専用の「ポート」(移植版)を持ちますが,MCXシリーズに専用ポートはありません.その代わり,Zephyrが対応しているボードなら動かせるこの仕組みを使います(詳しくは1.3節). ビルド自体は,これまでもできました.ただしボード固有の設定が無かったため,出来上がるのは最小限のMicroPythonで,スクリプトを保存するファイルシステムも無く,I²CもSPIも使えませんでした.今回のマージで,これらが最初から使えるようになります. これでNXPのマイコンでMicroPythonを使う選択肢が広がりました.これまでは事実上,上位のクロスオーバーMCUであるi.MX RTシリーズに限られていましたが,そこにMCX Nシリーズという,より小規模で手を出しやすい選択肢が加わったことになります. このボードに有線のEthernetが載っている点も見逃せません.MicroPythonが動く安価なボードの多くは,Wi-FiやBluetoothでネットワークにつなぎます.用途によっては,電波を使わない有線のほうが扱いやすい場面もあります.この記事の後半では,ボードをWebサーバにしてブラウザからLEDを操作するところまで動かします. 一方で,制約もあります.Zephyrポートは,チップ専用のポートに比べると機能が絞られます.たとえば同じNXPのマイコンでも,i.MX RT向けの ports/mimxrt には network.LAN() があってIPアドレスを実行時に設定できますが,Zephyrポートには network モジュール自体がありません.使えるのは socket だけで,IPアドレスはビルド時にしか決められません.この記事では,そうした制約と,実際にぶつかった問題の回避策も含めて書いています(8.2節に整理しました). 以降では,MicroPythonとは何かという話から始めて,実際にFRDM-MCXN947にMicroPythonを書き込み,LEDを光らせ,スイッチを読み,I²CやSPIのデバイスを動かし,最後にEthernetを使うところまでを一通り解説します.「MicroPythonを触るのは初めて」という方を想定して,途中の手順はできるだけ省略せずに書きました. この記事の読み方 長めの記事なので,必要なところから読んでください. Zephyrの開発環境がまだの方 → 2.1節から すでにビルドと書き込みが済んでいる方 → 3章から 何ができるのか先に見たい方 → 8.6節(ブラウザからLEDを操作する例) 章ごとに必要なものは次のとおりです. 1〜5章:FRDM-MCXN947本体とUSBケーブルだけで進められます [作業時間:60分] 6章(I²C):ジャンパ線2本 [作業時間:20分] 7章(SPI):ジャンパ線1本 [作業時間:20分] 8章(Ethernet):LANケーブル1本 [作業時間:20分] 0. 目次 目次 MicroPythonとはなんなのか? 1.1 どういうところで使われているのか 1.2 MicroPythonのいいところ,悪いところ 1.3 MCXマイコンへの対応:「Zephyrポート」という形 1.4 今回の対応でできるようになったこと 1.5 Zephyrポートの弱点:ピンの指定がタプルになる MicroPython Zephyrポートのビルド 2.1 Zephyr開発環境のインストール 2.2 MicroPythonのソースを取得する 2.3 ビルドする 2.4 ボードに書き込む MicroPythonを使ってみる — 基本編 3.1 Thonnyを用意する 3.2 どのUSBコネクタに繋ぐのか 3.3 接続してプロンプトを確認する 3.4 「REPL」とは 3.5 スクリプトを書いてみる:Lチカ 3.6 このボードで使えるピンを調べる 3.7 Lチカの色を変えてみる 応用編:ピン名を工夫する 4.1 まずはスクリプトの中にPINS辞書を書く 4.2 config.pyに切り出す 4.3 ストレージに保存して共有する 4.4 config.pyを使った3色Lチカ 応用編:スイッチを読む 5.1 スイッチの状態を読む 5.2 押されたことを割り込みで知る 応用編:I²Cを使ってみる 6.1 このボードのI²C事情 6.2 ジャンパを2本つなぐ 6.3 バスをスキャンする 6.4 温度を読む 応用編:SPIを使ってみる 7.1 ループバックで試す 7.2 CSは自動制御されない 応用編:Ethernetを使ってみる 8.1 有線LANという強み 8.2 このポートのネットワークAPI 8.3 PCと直結して試す 8.4 自分のIPアドレスを調べる 8.5 ボードをWebサーバにする 8.6 LEDをブラウザから操作する 8.7 電源を入れるだけで動くようにする 8.8 ハマりやすい点 まとめ 参考資料 付録:LED操作サーバのコード解説 11.1 ここまでの内容が1つにまとまっている 11.2 コードの3つの仕掛け 11.3 例外処理が必要な理由 11.4 Connection: close について 11.5 そのほか気をつける点 11.6 この挙動は将来変わるかもしれません 1. MicroPythonとはなんなのか? MicroPythonは,マイコンの上で直接動くPython 3のインタプリタです.2013年にDamien George氏がKickstarterで資金を集めて開発を始めたもので,現在はオープンソース(MITライセンス)のプロジェクトとして開発が続いています. 「Python 3の処理系」といっても,PCで動くCPythonをそのまま持ってきたわけではありません.数百KB程度のROMと数十KBのRAMに収まるように,言語仕様とライブラリを絞り込んで再実装したものです.そのため文法はPython 3とほぼ同じですが,標準ライブラリは必要なものだけが用意されています. その代わりに,マイコンならではのモジュールが用意されています.GPIO,I²C,SPI,UART,PWM,ADCといった周辺機能を扱う machine モジュールがその代表です.このブログでも machine モジュールを使っていきます. なお,この章は背景の説明です. すぐに手を動かしたい方は2章へ進んでください. 1.1 どういうところで使われているのか MicroPythonがよく使われるのは,次のような場面です. 教育用途:BBC micro:bitがMicroPythonを採用したことで,一気に知られるようになりました.Raspberry Pi PicoもMicroPythonを公式にサポートしています. プロトタイピング:センサをとりあえず動かしてデータを見てみたい,という段階では,ビルドとフラッシュ書き込みを繰り返すCの開発サイクルより圧倒的に速く進みます. 治具・測定器:製造ラインの検査治具や,実験用の簡易測定装置のように,「少量でいいので早く作りたい」ものに向いています. ホビー:電子工作の分野では定番の選択肢のひとつです. いずれも「動くものを早く作る」ことが重視される場面です.ここがMicroPythonの一番の得意分野といえます. 1.2 MicroPythonのいいところ,悪いところ この節の内容は,特定のマイコンやポートに限らない,MicroPython全般の性質です.使うかどうかを判断できるように,両面を挙げておきます. いいところ コードが簡単に書ける:Python 3の文法がそのまま使えます.文字列処理やリスト操作といった,Cだと面倒な処理が数行で書けます. 対話的に試せる:ボードに接続して,1行ずつコマンドを打ち込みながら動作を確かめられます.「このピンをHIGHにしたらLEDは点くのか,消えるのか」といった確認が,その場で1行打つだけで済みます.ハードウェアの挙動を手探りで確かめるとき,これは非常に強力です.(この対話環境をREPLと呼びます.3.4節で詳しく説明します) ビルドが要らない:スクリプトを書いて実行するだけです.コンパイル・リンク・書き込みのサイクルが不要なので,試行錯誤が速く回ります. 学習コストが低い:Pythonを知っていれば,マイコン側の知識だけ足せば始められます. 悪いところ 実行速度が遅い:インタプリタなので,Cで書いたコードに比べると数十倍から百倍程度遅くなります.厳密なタイミング制御が必要な処理や,高速な信号処理には向きません.ただし対策はあって,関数に @micropython.native や @micropython.viper のデコレータを付けると,その関数だけをネイティブコードにコンパイルできます.それでも足りない場合は,その部分だけCで書いてモジュールとして組み込むこともできます. メモリを食う:インタプリタ本体と標準ライブラリをマイコンに載せる必要があります.数百KBのフラッシュと数十KBのRAMが,アプリケーションを書く前の時点で消費されます.小さなマイコンでは現実的ではありません. リアルタイム性の保証がない:ガベージコレクションが動くタイミングをこちらから完全には制御できません. MCXN947は2MBのフラッシュと512KBのSRAMをチップ上に持っているので,メモリの点では余裕をもってMicroPythonを載せられます. 1.3 MCXマイコンへの対応:「Zephyrポート」という形 MicroPythonは,マイコンの種類ごとに「ポート」と呼ばれる移植版を持っています. ports/rp2 (Raspberry Pi Pico), ports/mimxrt (i.MX RT), ports/esp32 といった具合です.これらは各マイコンのレジスタやSDKを直接叩く,そのチップ専用の実装です. MCXシリーズについては,このような専用ポートは存在しません.その代わりに使えるのが ports/zephyr ,つまりZephyr RTOSの上で動かすポートです. これは「Zephyrがサポートしているボードなら,原理的にはどれでもMicroPythonが動く」という作りになっています.ペリフェラルへのアクセスはZephyrのデバイスドライバ経由で行われるため,MicroPython側にチップ固有のコードを書く必要がありません. FRDM-MCXN947はZephyrが正式にサポートしているボードなので,この仕組みに乗ることができます. NXPのマイコンでMicroPythonを使う選択肢 ここで少し整理しておきます. NXPのマイコンでMicroPythonを動かそうとしたとき,これまで実質的な選択肢はi.MX RTシリーズでした.専用ポートの ports/mimxrt がRT1010からRT1170までのEVKやTeensy 4.xに対応しており,周辺機能もひととおり使えます. Zephyrポートにも以前からいくつかNXPボードの設定が入っていましたが, mimxrt1020_evk や mimxrt685_evk_cm33 といったクロスオーバーMCU向けか, frdm_k64f / frdm_kw41z のようにかなり以前のKinetis向けで,しかも後者はファイルシステムやI²C/SPIまで整えられたものではありませんでした. i.MX RTは高い性能を持つ反面,MCUとしては上位の製品群です.「MicroPythonでちょっと試したい」という用途には,やや大きな構えになります. 今回FRDM-MCXN947の設定が入ったことで,汎用MCUであるMCX Nシリーズという,より手を出しやすい選択肢が加わりました.これも今回の対応の意味のひとつだと思います. 図1:MicroPython Zephyrポートの階層   この方式には,長所と短所の両方があります.長所は,Zephyrが対応しているボードに幅広く展開できること.短所は,Zephyrの抽象化を通すぶん,チップ専用ポートに比べて「そのボードらしい書き味」が薄くなることです.具体的には後述する「ピン指定の問題」として表れます. 1.4 今回の対応でできるようになったこと Zephyrポート自体は以前からありましたが,FRDM-MCXN947用の設定は入っていませんでした.そのままビルドすると,対話的にコマンドを打ち込むことはできても,ストレージもI²CもSPIも使えない,という状態でした. 今回,以下の2つのファイルが本家 micropython/micropython のmasterにマージされました. ports/zephyr/boards/frdm_mcxn947_mcxn947_cpu0.conf ports/zephyr/boards/frdm_mcxn947_mcxn947_cpu0.overlay これによって,次のことができるようになっています. (1) オンボードのフラッシュをファイルシステムとして使える FRDM-MCXN947に載っている8 MiBのQSPIフラッシュ(Winbond W25Q64JV)の storage_partition を,LittleFSとして /flash にマウントします.書いたスクリプトをボード上に保存しておけるようになる,という意味で,これが一番大きい変更です. 実際にマウントした状態で容量を確認すると,次のようになります. >>> import os >>> os.statvfs('/flash') (4096, 4096, 2048, 2043, 2043, 0, 0, 0, 0, 255) ブロックサイズ4096バイト × 2048ブロック = 8 MiB のうち,LittleFSの管理領域を除いた約7.98 MiBが使えます. (2) MikroBusのSPIが使えるようになった MikroBusコネクタのSPI( flexcomm6_lpspi6 )を有効にしています.このSPIは,ボード共通のdevicetreeではピン定義まで用意されているものの, status = "disabled" のままになっていました.MOSI/SCKに使うP3_20/P3_21が,SAI1と共用のピンだからです. SAIは Serial Audio Interface の略で,I²SやTDMといったデジタルオーディオのデータをやり取りするためのシリアル・インターフェースです.オーディオコーデックやマイクを繋ぐときに使うもので,同じピンをSPIとSAIの両方に同時に割り当てることはできません.そのためボード共通の定義では,どちらとも決めずに無効にしてありました. では,どちらに使うのか.今回のoverlayではSPIとして有効にするという判断がされました.根拠は単純で,MicroPythonのZephyrポートにはI²S/SAIを扱うドライバも machine.I2S のようなクラスも存在しないからです.つまりSAI1のピンとして残しておいても,MicroPythonからは使いようがありません.それならSPIとして使えるようにしたほうが有用だろう,というわけです. (3) I²CとSPIのドライバが組み込まれるようになった CONFIG_I2C=y と CONFIG_SPI=y を指定しています.これがないと machine.I2C や machine.SPI を作ろうとしても失敗します. 1.5 Zephyrポートの弱点:ピンの指定がタプルになる さて,ここでZephyrポートの「使いにくいところ」を先に紹介しておきます.あとで対策を示すので,まずは問題を知っておいてください. 一般的なMicroPythonのポートでは,ピンは名前や番号で指定します. # i.MX RTの専用ポート(ports/mimxrt)の場合 led = Pin('D9', Pin.OUT) # Raspberry Pi Pico の場合 led = Pin(25, Pin.OUT) # ESP32 の場合 led = Pin(2, Pin.OUT) 同じNXPのマイコンでも,i.MX RT用の専用ポートでは 'D9' というボード上の表記そのままの名前が使えます. ところがZephyrポートでは,GPIOポート名とビット位置のタプルで指定します. # FRDM-MCXN947(Zephyrポート)の場合 led = Pin(("gpio0", 10), Pin.OUT) ("gpio0", 10) は「GPIO0ポートの10ビット目」,つまりデータシート上のP0_10を指します.間違った形式を渡すと,次のようなエラーが出ます. >>> Pin(25, Pin.OUT) Traceback (most recent call last): File " ", line 1, in ValueError: Pin id must be tuple of ("GPIO_x", pin#) なぜこうなっているかというと,ZephyrのdevicetreeではGPIOが gpio0 , gpio1 ,… というポート単位のデバイスとして定義されていて,その中のビット位置でピンを指すからです.MicroPython側はそれをそのまま受け渡す作りになっています. 問題は,この数字が回路図やボードのシルク印刷と対応していないことです.たとえば「ArduinoヘッダーのD9に接続されている赤色LEDを光らせたい」と思っても,そのD9が ("gpio0", 10) であることは,devicetreeを読まないとわかりません.Arduinoヘッダーの D9 や,RGB LEDの 赤 といった名前は,MicroPythonからは一切見えないのです. これはかなり不便です.4章で,この対策を段階を追って紹介します. コラム:Zephyrは「SDKの下回り」としても使われている Zephyrというと「組み込みアプリケーションを書くためのRTOS」というイメージが強いと思います.実際そのとおりなのですが,最近はもうひとつの使われ方が目立ってきました.別のSDKやフレームワークの土台として,裏側で使われるという使い方です. 今回のMicroPython Zephyrポートがまさにそれです.ユーザーが書くのはPythonのコードで,Zephyrの存在を意識することはほとんどありません.しかしその下ではZephyrのカーネルとデバイスドライバが動いていて,MicroPythonのインタプリタ自身も,Zephyrのスレッドのひとつとして実行されています. 同じ構造の例としてArduinoCore-zephyrがあります.これはArduinoのAPI( pinMode() , digitalWrite() , Wire , SPI …)をZephyrの上に実装したもので,Arduino IDEから使う限りはZephyrは見えません.けれども下回りはZephyrなので,Zephyrが対応しているボードにArduino環境を持ち込めることになります. このように「Zephyrを直接使う」以外に「Zephyrの上に載ったものを使う」という選択肢が増えてきています.Zephyrのボードサポートを整備することが,そのままMicroPythonやArduinoの対応にもつながる,という関係です. ▲ 目次に戻る 2. MicroPython Zephyrポートのビルド ここからは実際に手を動かしていきます.まずはファームウェアをビルドしてボードに書き込みます. 2.1 Zephyr開発環境のインストール この記事のコマンド例は,macOSやLinuxのシェル(bashやzsh)を前提にしています.Windowsをお使いの方は,環境を作り始める前に次のコラムをお読みください. コラム:Windowsで進める場合 先に結論を書くと,Windowsのコマンドプロンプト(cmd.exe)やPowerShellでは,このビルドは通りません.コマンドを書き換えても駄目です. MicroPythonのビルド処理そのものが,UNIXのコマンドに依存しているためです.ビルド規則を定めている py/mkrules.cmake の中で, cat ・ sed ・ touch が直接呼ばれています.たとえばqstr(文字列テーブル)を生成する箇所は,次のようなシェルのパイプライン1本で書かれています. cat … | sed … | (Cプリプロセッサ) | sed … > 出力ファイル これらのコマンドはWindowsに存在しません.パイプやリダイレクトはcmd.exeでも解釈できますが,肝心の cat や sed が無いので,結局そこで止まります.シェルを変えても解決しないのはこのためです. 実際,MicroPython本家のCIでも,Zephyrポートのビルドは ubuntu-latest でのみ実行されています.Windowsでのビルドは想定されていません. 紛らわしいのですが,Zephyr自体はネイティブのWindowsでビルドできます.この節で紹介するZephyrのGetting Started Guideにも,wingetでツールを入れるWindows向けの手順があります.そちらの手順どおりに環境を作れてしまうため,MicroPythonをビルドする段階になって初めて行き詰まる,ということが起こります. Windowsで進めるなら,次のいずれかのUNIX環境を使ってください.どちらでも,この記事のコマンドはそのまま使えます. WSL2(Windows Subsystem for Linux).ZephyrのGetting Started Guideでも,Ubuntu向けの手順をそのまま使う選択肢として触れられています.導入手順はMicrosoftのドキュメントを参照してください Git for Windows(Git Bash) や MSYS2 のbash環境 なお,ビルドと書き込みだけをUNIX環境で行い,ThonnyでのMicroPython操作はWindows側から,という分け方もできます.ThonnyもmpremoteもWindowsでそのまま動くので,3章以降はWindowsだけで進められます. MicroPython ZephyrポートのビルドにはZephyrの開発環境(west,Zephyr SDK,Pythonの仮想環境など)が必要です. Zephyr環境の構築手順は,NXPコミュニティの日本語ブログで詳しく解説されています.まだ環境を作っていない方は,まずそちらを参照してください. Zephyr シリーズ 第2回 はじめてのビルドと実機動作 (日本語ブログ) この記事で参照していただきたいのは,開発環境をインストールする部分です.記事の後半ではZephyrのサンプルプログラム( blinky など)をビルドして動かしますが,このブログでビルドするのはZephyrのサンプルではなくMicroPythonです.ビルドの対象を指定する部分だけが違うと考えてください. west build が通る状態まで作れていれば,準備は完了です. Zephyrの公式ドキュメントは以下です. Zephyr Getting Started Guide 環境ができていれば, ~/zephyrproject のようなディレクトリにwest workspaceが用意されているはずです.以降はこれを ~/zephyrproject として説明します. 2.2 MicroPythonのソースを取得する MicroPythonのソースは,Zephyrのworkspaceとは別の場所に置いて構いません.Zephyrのworkspaceを汚さずに済むので,むしろ別の場所を推奨します. git clone https://github.com/micropython/micropython.git cloneしたら,作られたディレクトリに移ってサブモジュールを取得します. cd micropython git submodule update --init lib/micropython-lib micropython-lib はMicroPython用の標準ライブラリ群で,サブモジュールとして分離されています.これを取得しておかないとビルド時にエラーになるので,忘れずに実行してください. 冒頭で書いたとおり,FRDM-MCXN947用の設定は本家のmasterに入っています.パッチをあてる必要はありません. 念のため,ボード用のファイルがあることを確認しておきましょう. micropython ディレクトリにいる状態のまま実行します. ls ports/zephyr/boards/ | grep mcxn947 frdm_mcxn947_mcxn947_cpu0.conf と frdm_mcxn947_mcxn947_cpu0.overlay の2つが表示されればOKです. なぜファイル名が長いのか Zephyrでは,同じボードでもコアや動作モードによって複数の構成を持つことがあります.FRDM-MCXN947はCortex-M33をデュアルで搭載しているため, frdm_mcxn947/mcxn947/cpu0 のように「ボード名/SoC名/コア名」で指定します.これをボード修飾子(board qualifier) と呼びます. MicroPythonのZephyrポートは,この修飾子を含めた名前でconf/overlayを探します.つまり frdm_mcxn947.conf という名前では読み込まれません. frdm_mcxn947_mcxn947_cpu0.conf としてはじめて認識されます.自分でボード設定を追加するときは,ここでつまずきやすいので注意してください. 2.3 ビルドする まずZephyrの仮想環境を有効にします. source ~/zephyrproject/.venv/bin/activate 次に,Zephyrのバージョンを合わせます. cd ~/zephyrproject/zephyr git checkout v4.4.0 west update MicroPythonのZephyrポートが対応を明言しているのは,v3.7(LTS)とv4.4,そして開発版です.本家のCIはv4.4でビルドを検証しています.workspaceがそれ以外のバージョンになっていると,ビルドが通らなかったり,通っても動作が違ったりすることがあるので,ここでv4.4.0に揃えておきます. west update は,切り替えたZephyrのバージョンに合わせて,HALやライブラリなどの関連モジュールを取り直すためのものです. git checkout だけでは不整合が残るので,必ずセットで実行してください. 準備ができたら west build を実行します. cd ~/zephyrproject west build -b frdm_mcxn947/mcxn947/cpu0 ~/micropython/ports/zephyr -b がボード指定,最後の引数がビルド対象のアプリケーション(MicroPythonのZephyrポート)です. ~/micropython の部分は,実際にcloneした場所に読み替えてください. ビルドが通ると build/zephyr/ の下に zephyr.bin , zephyr.hex , zephyr.elf が生成されます. 2回目以降,設定を変えてビルドし直すときは, --pristine (または -p )を付けて前回の結果を消してからビルドすると確実です. cd ~/zephyrproject west build -p -b frdm_mcxn947/mcxn947/cpu0 ~/micropython/ports/zephyr 2.4 ボードに書き込む FRDM-MCXN947にはMCU-Linkデバッガがオンボードで載っているので,書き込みに別途デバッガを用意する必要はありません. USBケーブルはJ17(MCU-Link側のUSBコネクタ)に接続します. 図2:USBケーブルはJ17(MCU-Link側)に接続する 接続したら, west flash を実行するだけです. cd ~/zephyrproject west flash 書き込みが終わると,ボードは自動的にリセットされてMicroPythonが起動します. このJ17は書き込みだけでなく,MicroPythonと対話するためのシリアル通信にも使います.つまりケーブル1本で書き込みと操作の両方ができます.詳しくは3.2節で説明します. ▲ 目次に戻る 3. MicroPythonを使ってみる — 基本編 ファームウェアが書き込めたら,いよいよMicroPythonを触っていきます. 3.1 Thonnyを用意する MicroPythonを使うには,ボードのシリアルポートに繋いでコマンドを打ち込む環境が必要です.ターミナルソフトでも構いませんが,ここでは Thonny を使います. ThonnyはMicroPython向けの機能を最初から持っているエディタ兼IDEです.無償で,Windows / macOS / Linuxで動きます. Thonny 公式サイト Thonnyのインストールと基本操作については,以下の動画の該当部分がわかりやすいです. MicroPythonをi.MX RTクロスオーバーMCUで動かしてみた (YouTube) — Thonnyの導入部分から再生されます Thonnyを使う利点は,シリアル通信ができることに加えて, 上部のエディタでスクリプトを書いて,そのままボード上で実行できる ボードのファイルシステム( /flash )の中身をGUIで見られる PCとボードの間でファイルをドラッグ&ドロップでコピーできる という点です.4章でファイルをボードに置くときに効いてきます. 3.2 どのUSBコネクタに繋ぐのか FRDM-MCXN947にはUSB Type-Cのコネクタが複数あります.MicroPythonのコンソールに繋ぐのは J17,MCU-Link側のコネクタです(2.4節の図2と同じ場所です). MicroPythonのコンソールは,Zephyrのコンソール( zephyr,console )に出力されます.FRDM-MCXN947のcpu0では,これが flexcomm4_lpuart4 (P1_8 / P1_9)に割り当てられていて,その先がMCU-LinkのVCOM(仮想COMポート)に繋がっています. つまり J17の1本で,ファームウェアの書き込みとコンソールの両方ができます.もう一方のUSBコネクタはMCXN947本体のUSBに繋がっていますが,今回の構成では使いません. 3.3 接続してプロンプトを確認する ケーブルを繋いだらThonnyを起動します. Thonnyの右下(またはメニューの「実行」→「インタプリタの選択」)から,インタプリタとして 「MicroPython (generic)」 を選び,ポートにボードのVCOMを指定します. Windows: COM3 のような名前 macOS: /dev/cu.usbmodem… Linux: /dev/ttyACM0 など 図3:インタプリタに「MicroPython (generic)」を選ぶ   うまく繋がると,下部のシェル(Shell)ペインにプロンプトが出ます.出ないときは,シェルペインをクリックしてから Ctrl-D(ソフトリセット)を押してみてください. MicroPython v1.30.0-preview.17.g47e9329e51 on 2026-08-30; zephyr-frdm_mcxn947 with mcxn947 Type "help()" for more information. >>>   図4:接続に成功すると,シェルペイン(ウィンドウ下部)にバナーとプロンプトが表示される 最後の zephyr-frdm_mcxn947 with mcxn947 の部分に注目してください. zephyr-frdm_mcxn947 はZephyrの CONFIG_BOARD , mcxn947 は CONFIG_SOC から作られる名前です.ここが期待どおりになっていれば,狙ったボード用のバイナリが動いていると確認できます. >>> がプロンプトです.ここにPythonの式を打ち込めます.まず「Hello, world!」の表示から試してみましょう. >>> print("Hello, world!") Hello, world! MicroPythonはPythonなので,式を打つだけでも結果が返ります. >>> 1 + 2 3 >>> "MCX" * 3 'MCXMCXMCX' ファイルシステムも確認しておきます. >>> import os >>> os.getcwd() '/flash' >>> os.listdir('/flash') [] 起動直後のカレントディレクトリが /flash になっています.これは今回マージされた設定でLittleFSがマウントされているからです.まだ何も置いていないので中身は空です. 3.4 「REPL」とは いま打ち込んでいるこの対話環境を REPL と呼びます.Read(読む),Eval(評価する),Print(表示する),Loop(繰り返す)の頭文字です. 1行入力するたびに,MicroPythonはそれを読み,実行し,結果を表示し,また次の入力を待ちます.これがREPLです. コンパイルして書き込んで実行して,という手順を踏まないと結果がわからないCの開発と比べると,試行錯誤の回しかたそのものが変わってきます.たとえば「このピンをHIGHにしたらLEDは点くのか,消えるのか」といった確認が,その場で1行打つだけで済みます.ハードウェアの挙動を手探りで確かめるとき,REPLは非常に強力な道具になります. REPLで覚えておくと便利なキー操作をまとめておきます. キー 動作 Ctrl-C 実行中のプログラムを中断する Ctrl-D ソフトリセット(MicroPythonを再起動する) Ctrl-E ペーストモードに入る Ctrl-A rawREPLモードに入る Ctrl-B 通常のREPLモードに戻る 表1:REPLの制御キー Ctrl-C は,無限ループに入ってしまったプログラムを止めるときに使います.Ctrl-D は,変数などをすべて忘れて最初からやり直したいときに使います. Ctrl-E のペーストモードは,複数行のコードをまとめて貼り付けるときに使います.通常のREPLは1行ごとにインデントを解釈しようとするので, for 文のような複数行のコードをそのまま貼るとうまくいかないことがあります.Ctrl-Eを押してからコードを貼り付け,Ctrl-Dで実行すると,まとめて処理されます. 3.5 スクリプトを書いてみる:Lチカ ここまではREPLに1行ずつ打ち込んできました.ちょっとした確認にはこれが一番早いのですが,繰り返しや条件分岐が入ってくるとさすがに窮屈になります.そういうまとまった処理は,スクリプトとして書いたほうが楽です. ではスクリプトを書いてみましょう.定番のLチカ(LEDチカチカ)です. FRDM-MCXN947にはRGBのLEDが載っています.まずは赤を点滅させてみます.赤のLEDはP0_10,つまり ("gpio0", 10) に繋がっています. Thonnyの上部のエディタペインに,次のコードを書いてください. import time from machine import Pin led = Pin(("gpio0", 10), Pin.OUT) # 赤LED (P0_10) while True: led.value(0) # 点灯 time.sleep(0.5) led.value(1) # 消灯 time.sleep(0.5) 図5:上側のエディタペインにコードを書く.下側がシェルペイン   書けたら,ツールバーの「実行」ボタン(緑の三角のアイコン.ショートカットはF5)を押します.Thonnyが「保存しますか」と聞いてきたら,保存先として「このコンピュータ」か「MicroPythonデバイス」かを選べます.今は試すだけなので,どちらでも構いません. 赤いLEDが0.5秒ごとに点滅すれば成功です. 止めるときは,ツールバーの「停止」ボタン(赤い丸のアイコン)を押します.シェルペインで Ctrl-C を押しても同じように止まります. ここで「あれ?」と思った方へ コードをよく見てください. value(0) が点灯で, value(1) が消灯です.直感と逆に見えますが,これで合っています. FRDM-MCXN947のRGB LEDは,アノードコモンで接続されています.LEDのプラス側が電源に繋がっていて,マイコンのピンがマイナス側を引っ張る形です.つまりピンをLOW(0)にしたときに電流が流れて点灯します.このような接続をアクティブ・ローといいます. 図6:FRDM-MCXN947回路図のRGB LED部分の抜粋.LEDのアノード側が電源に繋がっている   Zephyrのdevicetreeには,このLEDが GPIO_ACTIVE_LOW であるという情報がちゃんと書かれています.しかしMicroPythonの machine.Pin は,devicetreeのこのフラグを見ずにGPIOを生の値のまま読み書きします(内部で gpio_pin_set_raw() を呼んでいます).そのため,論理を反転してくれることはありません. 0 を書けばピンはLOWになり,LEDは点きます. ちなみに, led.value(0) は led.off() とも書けます.つまり led.off() を呼ぶとLEDは点灯します.名前と実際の動作が逆になるので,混乱しそうなときは value(0) / value(1) で書くほうが安全かもしれません. もうひとつ注意点: toggle() はありません 他のポートのMicroPythonに慣れていると led.toggle() と書きたくなりますが,Zephyrポートの Pin にはこのメソッドがありません.使えるのは次のものだけです. メソッド / 定数 説明 value([x]) 引数なしで読み出し,引数ありで書き込み on() HIGH(1)を出力 off() LOW(0)を出力 init(...) ピンの設定を変更 irq(...) 割り込みハンドラを設定 Pin.IN / Pin.OUT / Pin.OPEN_DRAIN 入出力モード Pin.PULL_UP / Pin.PULL_DOWN プルアップ / プルダウン Pin.IRQ_RISING / Pin.IRQ_FALLING 割り込みエッジ 表2:Zephyrポートの machine.Pin で使えるもの トグルしたいときは,読んで反転して書けば済みます. led.value(not led.value()) 3.6 このボードで使えるピンを調べる さて,赤のLEDが ("gpio0", 10) であることは,どこから来た値なのかを説明しないまま使ってきました.では自分で調べるにはどうすればいいのでしょうか. この節では,答えを探しにZephyrの設定ファイルまで降りていきます.少し込み入った話になるので,先を急ぐ方は読み飛ばして4章に進んで構いません.4章では,ここで調べた対応表を一度作ってしまえば以降は名前でピンを指定できる,という話をします. 残念ながら,MicroPythonのZephyrポートには「使えるピンの一覧を表示する」機能がありません. machine モジュールの中身を見ても,ピンの名前は出てきません. >>> import machine >>> dir(machine) Pin , I2C , SPI , UART , PWM , ADC , Timer , WDT といったクラス名が並びます(実際に何が入っているかはビルド時の設定で変わるので,手元で実行して確かめてください). Pin というクラスがあることはわかりますが,どのピンが使えるかはわかりません. では,どこを見ればいいのか 答えは Zephyrのdevicetree です. devicetreeとは (Zephyrを使ったことがある方には既知の内容です.下の「FRDM-MCXN947のdevicetreeを読む」まで飛ばしてください) devicetree(デバイスツリー)は,ボードにどんなハードウェアが載っていて,どう繋がっているかを記述したテキストファイルです.もともとはLinuxカーネルで使われていた仕組みで,Zephyrもこれを採用しています. 「このSoCにはI²Cコントローラが何個あって,それぞれどのアドレスにあって,どのピンに出ていて,有効なのか無効なのか」といった情報が, .dts / .dtsi という拡張子のファイルに階層構造で書かれています.Zephyrはビルド時にこれを読み取り,必要なドライバの初期化コードやピンの設定を自動的に生成します. ソースコードにピン番号を直接書く代わりに,ハードウェアの構成情報をコードから分離しておく,という考え方です.おかげで,同じアプリケーションのソースを別のボード向けにビルドし直すことができます. MicroPythonのZephyrポートが ("gpio0", 10) というタプルを要求するのも,このdevicetreeの構造をそのまま反映しているからです. gpio0 はdevicetree上のデバイス名で, 10 はそのポート内のビット位置です. FRDM-MCXN947のdevicetreeを読む FRDM-MCXN947のピン配置は,Zephyrのリポジトリの以下のファイルに書かれています. zephyr/boards/nxp/frdm_mcxn947/frdm_mcxn947.dtsi この中の arduino_header というノードに,Arduinoヘッダーの各ピンがどのGPIOに繋がるかが書かれています. arduino_header: arduino-connector { compatible = "arduino-header-r3"; gpio-map = , , , , , /* RX */ , /* TX */ , ... , /* SCK */ , /* SDA */ ; /* SCL */ }; は「ヘッダーのD13は gpio0 の25ビット目」という意味です.これをMicroPythonのタプルに直すと ("gpio0", 25) になります. 同じファイルの中に,LEDとスイッチの定義もあります. leds { compatible = "gpio-leds"; green_led: led_1 { gpios = <&gpio0 27 GPIO_ACTIVE_LOW>; ... }; blue_led: led_2 { gpios = <&gpio1 2 GPIO_ACTIVE_LOW>; ... }; red_led: led_3 { gpios = <&gpio0 10 GPIO_ACTIVE_LOW>; ... }; }; gpio_keys { compatible = "gpio-keys"; user_button_2: button_0 { gpios = <&gpio0 23 ...>; }; /* SW2 */ user_button_3: button_1 { gpios = <&gpio0 6 ...>; }; /* SW3 */ }; 赤のLEDが &gpio0 10 ,つまり ("gpio0", 10) であることがここで確認できます. GPIO_ACTIVE_LOW と書かれているのも見えますね.先ほど説明したアクティブ・ローの根拠がこれです. 毎回devicetreeを読むのか? もちろん,毎回これを調べるのは現実的ではありません.「LEDを光らせたいだけなのにdevicetreeを読む」というのは,MicroPythonの手軽さを台無しにしています. そこで4章では,この対応表を一度だけ作って,以降は名前で書けるようにする方法を紹介します. 3.7 Lチカの色を変えてみる 対策の前に,タプル指定の不便さをもう少し体感しておきましょう.3色のLEDを順番に光らせてみます. devicetreeから読み取った値は次のとおりでした. 色 ピン タプル 赤 P0_10 ("gpio0", 10) 緑 P0_27 ("gpio0", 27) 青 P1_2 ("gpio1", 2) 表3:RGB LEDのピン割り当て import time from machine import Pin red = Pin(("gpio0", 10), Pin.OUT, value=1) green = Pin(("gpio0", 27), Pin.OUT, value=1) blue = Pin(("gpio1", 2), Pin.OUT, value=1) while True: for led in (red, green, blue): led.value(0) # 点灯 time.sleep(0.5) led.value(1) # 消灯 Pin() の value=1 は,ピンを出力に設定すると同時に初期値をHIGH(消灯)にする指定です.これを付けないと,設定した瞬間に一瞬光ることがあります. 赤→緑→青と順番に光れば成功です. さて,このコードを見てどう思うでしょうか. red = Pin(("gpio0", 10), Pin.OUT, value=1) ("gpio0", 10) という部分に,意味が読み取れません. red という変数名を付けたから読めるだけで,この数字だけを見て「赤のLED」だとわかる人はいないはずです. しかも,この数字を間違えてもエラーにはなりません. ("gpio0", 11) と書いてしまったら,存在するピンなので Pin は正常に作られ,ただLEDが光らないだけです.「どこが悪いのか」を探すのに時間を取られることになります. この問題を,次の章で片付けます. ▲ 目次に戻る 4. 応用編:ピン名を工夫する Zephyrポートがピン名を提供してくれないなら,自分で用意すればいい.それがこの章の方針です. 段階を追って,3つの段階で進めます. スクリプトの中に辞書を書く config.py という別ファイルに切り出す ボードのストレージに置いて,すべてのスクリプトから共有する 4.1 まずはスクリプトの中にPINS辞書を書く 一番簡単なのは,スクリプトの先頭にPythonの辞書を書いてしまう方法です. import time from machine import Pin PINS = { "LED_RED": ("gpio0", 10), "LED_GREEN": ("gpio0", 27), "LED_BLUE": ("gpio1", 2), } red = Pin(PINS["LED_RED"], Pin.OUT, value=1) while True: red.value(0) time.sleep(0.5) red.value(1) time.sleep(0.5) Pin(PINS["LED_RED"], ...) と書けるようになりました.これなら何をしているか一目でわかります. さらに良いのは,タイプミスがエラーになることです. >>> Pin(PINS["LED_RD"], Pin.OUT) Traceback (most recent call last): File " ", line 1, in KeyError: LED_RD 先ほどの「数字を間違えても黙って動く」状態と比べてください.辞書のキーを間違えれば KeyError で止まってくれます.これだけでもデバッグの手間がかなり減ります. 4.2 config.pyに切り出す しかし,スクリプトを書くたびにこの辞書をコピーするのは面倒です.実際,LEDだけでなくArduinoヘッダーやMikroBusのピンも定義したくなるので,辞書はどんどん長くなります.そのたびに全部のスクリプトの先頭に貼り付けるのは現実的ではありません. Pythonらしく,別ファイルに切り出してimportしましょう. config.py というファイルを作ります. PINS = { # --- Arduinoヘッダー --- "D0": ("gpio4", 3), # P4_3 (RX) "D1": ("gpio4", 2), # P4_2 (TX) "D2": ("gpio0", 29), # P0_29 "D3": ("gpio1", 23), # P1_23 "D4": ("gpio0", 30), # P0_30 "D5": ("gpio1", 21), # P1_21 "D6": ("gpio1", 2), # P1_2 "D7": ("gpio0", 31), # P0_31 "D8": ("gpio0", 28), # P0_28 "D9": ("gpio0", 10), # P0_10 "D10": ("gpio0", 27), # P0_27 (CS) "D11": ("gpio0", 24), # P0_24 (MOSI) "D12": ("gpio0", 26), # P0_26 (MISO) "D13": ("gpio0", 25), # P0_25 (SCK) "D14": ("gpio4", 0), # P4_0 (SDA) "D15": ("gpio4", 1), # P4_1 (SCL) "A2": ("gpio0", 14), # P0_14 "A3": ("gpio0", 22), # P0_22 "A4": ("gpio0", 15), # P0_15 "A5": ("gpio0", 23), # P0_23 # --- バス(Zephyrのデバイスノード名) --- "I2C": "lpi2c@94800", # flexcomm2_lpi2c2 (arduino_i2c) "SPI": "spi@93000", # flexcomm1_lpspi1 (D10〜D13) "MIKROBUS_I2C": "lpi2c@95800", # flexcomm3_lpi2c3 "MIKROBUS_SPI": "spi@b6000", # flexcomm6_lpspi6 # --- MikroBusのGPIO --- "MIKROBUS_RST": ("gpio1", 3), "MIKROBUS_CS": ("gpio3", 23), "MIKROBUS_SCK": ("gpio3", 21), "MIKROBUS_MISO": ("gpio3", 22), "MIKROBUS_MOSI": ("gpio3", 20), "MIKROBUS_PWM": ("gpio3", 19), "MIKROBUS_INT": ("gpio5", 7), "MIKROBUS_RX": ("gpio1", 16), # GPIOとして使える.UARTのRXではない "MIKROBUS_TX": ("gpio1", 17), # GPIOとして使える.UARTのTXではない "MIKROBUS_SCL": ("gpio1", 1), "MIKROBUS_SDA": ("gpio1", 0), # --- エイリアス --- "LED_RED": ("gpio0", 10), # = D9 "LED_GREEN": ("gpio0", 27), # = D10 "LED_BLUE": ("gpio1", 2), # = D6 "SW2": ("gpio0", 23), # = A5 "SW3": ("gpio0", 6), # P0_6 } すべてdevicetreeから転記した値です. いくつか補足します. RGB LEDはArduinoヘッダーと共用です. 赤のLED(P0_10)はArduinoヘッダーのD9と同じピンです.同様に緑がD10,青がD6です.Arduinoシールドを挿すときは,これらのピンを使うとLEDも一緒に光ります.逆に言えば,シールドがD6やD9を使っていると,LEDのつもりで操作するとシールド側に影響が出ます. SDA/SCLはA4/A5ではありません. Arduino UNO R3のボードでは,I²CのSDA/SCLがA4/A5と同じ配線になっていることが多く,「A4=SDA,A5=SCL」と覚えている方も多いと思います.しかしFRDM-MCXN947では違います.I²CはAREFの隣にある専用のSDA/SCLピン(Zephyrのdevicetree上ではD14/D15)に出ていて,これはP4_0/P4_1です.A4(P0_15)とA5(P0_23)は,I²Cバスには繋がっていない独立したGPIOです.5章でジャンパを繋ぐときに重要になるので,覚えておいてください. SW2はA5と同じピンです. ユーザースイッチのSW2(P0_23)は,ArduinoヘッダーのA5と同じピンに繋がっています.A5を出力として使うとスイッチの回路に影響するので注意してください. バスは文字列で指定します. machine.I2C と machine.SPI のid引数は,タプルではなくZephyrのデバイスノード名の文字列です. "lpi2c@94800" の 94800 は,MCXN947のメモリマップ上のペリフェラルのアドレス(0x94800)です.ここもdevicetree由来の値です. 4.3 ストレージに保存して共有する config.py ができました. スクリプトは「モジュール」として読み込める 先に進む前に, import について補足しておきます. config.py は特別な形式のファイルではありません. PINS = { ... } と書いただけの,ごく普通のPythonのスクリプトです.Lチカのスクリプトと同じ,ただのテキストファイルです. Pythonでは,こうしたスクリプトを他のスクリプトから読み込んで使えます.読み込まれる側をモジュールと呼び,読み込む命令が import です. from config import PINS これは「 config.py を読み込んで実行し,その中で作られた PINS をこちらに持ってくる」という意味になります.ファイル名から .py を取った config が,そのままモジュール名になります. config.py の中身が実行されるので PINS という辞書ができあがり,それをこちらで使える,というわけです. よく使う定義や関数を別ファイルにまとめておいて,必要なスクリプトから読み込む.これはPythonでごく一般的なやり方で,MicroPythonでも同じように使えます. どこに置けばよいか では config.py をボードのどこに置けば,すべてのスクリプトから import できるでしょうか. MicroPythonは,モジュールを sys.path に並んだディレクトリから探します.確認してみましょう. >>> import sys >>> sys.path ['', '.frozen', '/flash/lib'] /flash/lib が入っています.これは今回マージされた設定でLittleFSがマウントされたときに,起動処理( _boot.py )が自動的に追加してくれるものです. つまり /flash/lib/config.py として保存すれば,どのスクリプトからも from config import PINS で読めるということです. Thonnyで置く Thonnyのメニューから「表示」→「ファイル」を選ぶと,画面左側にファイルペインが表示されます.上半分がPC側,下半分がボード(MicroPythonデバイス)側です.   図7:Thonnyのファイルペインウィンドウ左側 ( config.py を /flash/lib へアップロードした)   手順は次のとおりです. 下半分(ボード側)が /flash を表示していることを確認する ボード側のペインで右クリック →「新しいディレクトリ」を選び, lib を作る 作られた lib をダブルクリックして中に入る 上半分(PC側)で config.py を右クリック →「/flash/lib へアップロード」を選ぶ 置けたか確認しましょう. >>> import os >>> os.listdir('/flash/lib') ['config.py'] コマンドラインから操作する場合(mpremote) Thonnyを使わず,コマンドラインから操作したい方には mpremote が便利です. pip install mpremote でインストールできます. まず lib ディレクトリを作ります. mpremote mkdir :/flash/lib その中に config.py をコピーします. mpremote cp config.py :/flash/lib/config.py スクリプトを実行するだけなら,ボードに保存せずに実行することもできます. mpremote run blink.py 4.4 config.pyを使った3色Lチカ 準備ができました.3.7節のコードを書き直してみましょう. import time from machine import Pin from config import PINS red = Pin(PINS["LED_RED"], Pin.OUT, value=1) green = Pin(PINS["LED_GREEN"], Pin.OUT, value=1) blue = Pin(PINS["LED_BLUE"], Pin.OUT, value=1) while True: for led in (red, green, blue): led.value(0) # 点灯 time.sleep(0.5) led.value(1) # 消灯 3.7節と見比べてください.違いは, Pin() に渡しているものだけです. red = Pin(("gpio0", 10), Pin.OUT, value=1) # 3.7節 red = Pin(PINS["LED_RED"], Pin.OUT, value=1) # こちら ("gpio0", 10) のような数字はどこにも出てきません.「赤・緑・青のLEDを順番に光らせる」という意図が,そのままコードになりました. これで,1.5節で挙げたZephyrポートの弱点は,実用上ほぼ解消できました. config.py は一度作ってボードに置いてしまえば,以降ずっと使えます. なお,ここで使っている config.py の全文は4.2節に載せてあります.そのままコピーして使ってください. トラブルシューティング:うまくimportできないときは config.py を置いたのに ImportError が出る場合は,次を確認してください. ソフトリセットを試す.シェルペインで Ctrl-D を押します.MicroPythonは一度importしたモジュールをキャッシュするので,ファイルを置き換えても古いものが使われることがあります.これが一番よくある原因です. 置き場所を確認する. os.listdir('/flash/lib') で config.py が見えるか確かめます. lib ディレクトリを作る前にアップロードして, /flash/ の直下に置かれてしまっているケースがよくあります. sys.path を確認する. import sys; print(sys.path) に /flash/lib が入っているか見ます.入っていなければ, /flash のマウントに失敗している可能性があります. ファイル名を確認する. from config import PINS で読めるのは config.py という名前のファイルだけです.別の名前で保存していないか確かめてください. ▲ 目次に戻る 5. 応用編:スイッチを読む 3章ではLEDを光らせました.GPIOの出力です.今度は反対に,入力を扱ってみます. FRDM-MCXN947には,ユーザーが自由に使えるスイッチが2つ載っています.SW2とSW3です.ここではSW2を使います. 図8:ユーザースイッチSW2とSW3の位置   この章に追加の部品は要りません.ボードとUSBケーブルだけで進められます. 5.1 スイッチの状態を読む SW2はP0_23に繋がっていて, config.py に SW2 として入れてあります. from machine import Pin from config import PINS sw = Pin(PINS["SW2"], Pin.IN, Pin.PULL_UP) print(sw.value()) Pin.IN で入力に設定し, Pin.PULL_UP で内部のプルアップ抵抗を有効にしています. なぜプルアップが必要なのか このスイッチは,押すとピンがGNDに繋がる回路になっています.逆に言えば,押していないときはピンがどこにも繋がっていません.この状態では電圧が定まらず,読み出す値が安定しません. プルアップ抵抗を有効にすると,押していないときはピンが電源側に引き上げられてHIGHになります.押したときだけGNDに引かれてLOWになります.これで両方の状態がはっきりします. つまり読み出される値は次のようになります. 押していない → 1 押している → 0 ここでも 0 が「押されている」です. LEDのときと同じアクティブ・ローの考え方で(3.5節),このボードではよく出てくる形です. 実行して確かめてみましょう. >>> print(sw.value()) 1 押していないので 1 が返りました.押しながら実行すれば 0 になります. 繰り返し読む場合 状態を監視し続けるなら,こうなります. import time from machine import Pin from config import PINS sw = Pin(PINS["SW2"], Pin.IN, Pin.PULL_UP) last = sw.value() while True: now = sw.value() if now != last: print("押された" if now == 0 else "離された") last = now time.sleep_ms(20) 前回の値と比べて,変化したときだけ表示しています.毎回表示すると,押している間ずっと出力され続けてしまうためです. この方法をポーリングと呼びます.仕組みは単純ですが,欠点もあります. sleep_ms(20) の間にスイッチが押されて離されると,見逃してしまいます.かといって間隔を短くすると,その分だけCPUがこの確認に費やされます. 5.2 押されたことを割り込みで知る そこで使えるのが割り込みです. 「ピンの状態が変化したら,この関数を呼んでほしい」と登録しておく方式で,ふだんは他の処理をしていられます.見逃しもありません. machine.Pin では irq() メソッドで登録します. import time from machine import Pin from config import PINS sw = Pin(PINS["SW2"], Pin.IN, Pin.PULL_UP) n = 0 def pressed(pin): global n n += 1 print(" 割り込み %d 回目 value=%d" % (n, pin.value())) sw.irq(handler=pressed, trigger=Pin.IRQ_FALLING) print("SW2を数回押してください(30秒間)") for i in range(30): time.sleep(1) sw.irq(handler=None) print("合計 %d 回検出しました" % n) 実行してSW2を10回押した結果です. SW2を数回押してください(30秒間) 割り込み 1 回目 value=0 割り込み 2 回目 value=0 割り込み 3 回目 value=0 (中略) 割り込み 10 回目 value=0 合計 10 回検出しました 押した回数だけ,きちんと呼ばれました. コードの読みかた trigger には,どの変化で呼んでほしいかを指定します. 指定 意味 Pin.IRQ_FALLING HIGH→LOW の変化(このボードでは「押した」) Pin.IRQ_RISING LOW→HIGH の変化(「離した」) `Pin.IRQ_FALLING \ Pin.IRQ_RISING` 両方 表4: irq() の trigger に指定できるもの ここでは押した瞬間だけ知りたいので Pin.IRQ_FALLING を指定しています. handler に渡す関数は,引数を1つ受け取るように書きます.呼ばれるときに,割り込みの起きた Pin オブジェクトが渡されるためです.上の例では pin.value() として,そのピンの値を読んでいます. global n が必要なのは,関数の外にある変数を書き換えるためです.これはPythonの一般的な決まりで,MicroPythonでも同じです. 最後の sw.irq(handler=None) で割り込みを解除しています.解除しないと,そのあともスイッチを押すたびにハンドラが呼ばれ続けます. ハンドラの中で print() してよいのか 割り込みハンドラの中では,時間のかかる処理やメモリを確保する処理を避けるのが原則です. print() はどちらにも当てはまるので,本来は避けたいところです. ただしMicroPythonの irq() には hard という引数があり,既定値は hard=False です.このとき,ハンドラは割り込みが起きた瞬間ではなく,少し後の安全なタイミングにまわして実行されます.そのため print() を書いても問題ありません. hard=True を指定すると,割り込みが起きた瞬間に実行されます.応答は速くなりますが, print() やメモリ確保はできなくなります.まずは既定のままで構いません. チャタリングについて 機械式のスイッチは,接点が触れる瞬間に細かくON/OFFを繰り返すことがあります.これをチャタリングと呼び,1回押しただけで割り込みが何度も入る原因になります. FRDM-MCXN947のSW2で試したかぎりでは,10回の押下に対して割り込みは10回で,チャタリングは観測されませんでした.ただしスイッチの個体や押しかたによっては起こりうるので,数が合わないときは,前回からの経過時間を見て短すぎるものを無視する,といった対策を入れてください. ▲ 目次に戻る 6. 応用編:I²Cを使ってみる GPIOの次はI²Cです.温度センサを読んでみましょう. 6.1 このボードのI²C事情 FRDM-MCXN947には P3T1755 という温度センサが載っています.I²CとI3Cの両方に対応した,分解能12ビット,±0.5℃精度のセンサです. ところが,これをMicroPythonからそのまま読むことはできません.理由は,このセンサがI3Cバスに接続されているからです. MCXN947のI3C1は,devicetree上で次のピンに割り当てられています. pinmux_i3c1: pinmux_i3c1 { group0 { pinmux = , ; ... }; }; つまり SDAがP1_16,SCLがP1_17 です. 一方で,MicroPythonのZephyrポートには I3Cのドライバがありません. machine モジュールにあるのは I2C だけで, I3C というクラスは存在しないのです.つまりMicroPythonからは,このセンサに手が届きません. しかしI3Cのターゲットデバイスは,I²CのコントローラからもI²Cデバイスとしてアクセスできる仕様になっています(レガシーI²Cモード).P3T1755もそうです.ということは,I3Cバスの信号線をI²Cコントローラに繋ぎ替えれば読めるはずです. ここで,先ほど config.py に書いたMikroBusのピン定義を思い出してください. "MIKROBUS_RX": ("gpio1", 16), # GPIOとして使える.UARTのRXではない "MIKROBUS_TX": ("gpio1", 17), # GPIOとして使える.UARTのTXではない P1_16とP1_17です.I3C1のSDA/SCLと,同じピンです. FRDM-MCXN947では,このI3Cの信号線がMikroBusコネクタのRX/TXピンにも引き出されています(devicetreeでは「GPIO, Not a RX」というコメント付きで,GPIOとして扱えることが示されています).つまり,MikroBusコネクタのRX/TXピンに,P3T1755がぶら下がっているわけです. コネクタに出ているのなら,ジャンパ線で他のバスに繋げます. 6.2 ジャンパを2本つなぐ 繋ぎ先は,ArduinoヘッダーのI²C( flexcomm2_lpi2c2 )にします.4.2節で強調したとおり,このバスが出ているのはAREFの隣にある専用のSDA/SCLピンです.A4/A5ではありません. 配線は次のようになります. 接続元(MikroBusコネクタ) 信号 接続先(Arduinoヘッダー) 信号 RX (P1_16) I3C1_SDA SDA (P4_0) LPI2C2 SDA TX (P1_17) I3C1_SCL SCL (P4_1) LPI2C2 SCL 表5:ジャンパ配線 図9:ジャンパ線の接続 注意点 SDAとSCLを取り違えないでください. 逆に繋ぐと,当然ながら通信できません.MikroBus側はRXがSDA,TXがSCLです.名前から想像すると間違えやすいので気をつけてください. プルアップ抵抗:I²Cはオープンドレインなので,本来はプルアップ抵抗が必要です.ただし筆者の環境では,外付けの抵抗なしで通信できました.I3C1側のピンにはdevicetreeで bias-pull-up が指定されていて,内部プルアップが有効になるためです.もし通信できない場合は,4.7kΩ程度の抵抗をSDA/SCLそれぞれと3.3Vの間に入れてみてください. A4/A5に繋がないでください. このボードのA4/A5はI²Cバスではありません. 6.3 バスをスキャンする 配線ができたら,まずバス上に何が見えるかを確認します. I2C.scan() は,7ビットアドレスの範囲(0x08〜0x77)に順番に問い合わせを出して,応答(ACK)を返したアドレスの一覧を返します. REPLで直接試してみましょう. >>> from machine import I2C >>> from config import PINS >>> i2c = I2C(PINS["I2C"]) >>> [hex(a) for a in i2c.scan()] ['0x48'] 0x48 が見つかりました.これがP3T1755です. freq= は指定できません 他のポートのMicroPythonでは I2C(id, freq=400_000) のようにクロック周波数を指定できますが,Zephyrポートでは例外になります. >>> i2c = I2C(PINS["I2C"], freq=100_000) Traceback (most recent call last): File " ", line 1, in NotImplementedError: explicit choice of freq is not implemented scl / sda / timeout も同様に指定できません.これらはすべてdevicetreeで決まる値だからです.FRDM-MCXN947のI²Cは,devicetreeで clock-frequency = ,つまり100kHzに設定されています.速度を変えたい場合はdevicetree(またはoverlay)を書き換えて,ファームウェアをビルドし直すことになります. 何も見つからないときは 空のリスト [] が返る場合は,次を確認してください. ジャンパ線がきちんと刺さっているか(半挿しになっていないか) SDAとSCLが逆になっていないか ボードの電源が入っているか(当たり前ですが,USBが抜けかけていることがあります) プルアップ抵抗が効いているか ロジックアナライザやオシロスコープがあれば,SCLにクロックが出ているかを見るのが一番確実です. scan() は相手がいなくても波形自体は出るので,「クロックが出ていない」のか「クロックは出ているが応答がない」のかを切り分けられます. I²Cの信号の見かたやトラブルシューティングについては,10章に挙げたI²C関連のブログを参照してください. 6.4 温度を読む P3T1755のレジスタ構成は,古くからあるLM75というセンサと互換です.温度を読む手順は次のようになります. ポインタレジスタに 0x00 (温度レジスタ)を書く 2バイト読む 読んだ2バイトは16ビットの値ですが,有効なのは上位12ビットです.下位4ビットは常に0です.上位12ビットは2の補数の符号付き整数で,1LSBが 0.0625℃ に対応します. コードにするとこうなります. import time from machine import I2C from config import PINS ADDR = 0x48 # P3T1755のI2Cアドレス REG_TEMP = 0x00 # 温度レジスタ def read_temperature(i2c, addr=ADDR): """P3T1755から温度を読んで摂氏で返す.""" i2c.writeto(addr, bytes([REG_TEMP])) # ポインタレジスタを指定 data = i2c.readfrom(addr, 2) # 2バイト読む raw = (data[0] << 8) | data[1] # 16ビットに合成 raw >>= 4 # 有効なのは上位12ビット if raw & 0x800: # 12ビットの符号を展開 raw -= 0x1000 return raw * 0.0625 # 1LSB = 0.0625℃ i2c = I2C(PINS["I2C"]) print("found:", [hex(a) for a in i2c.scan()]) while True: print("{:.4f} degC".format(read_temperature(i2c))) time.sleep(1) 実行すると,1秒ごとに温度が表示されます. found: ['0x48'] 25.5000 degC 25.5625 degC 25.5000 degC ... センサに指で触れると,値が上がっていくのがわかります.0.0625℃刻みなので,指を近づけただけでも動きが見えるはずです. コードの補足 raw >>= 4 の部分がわかりにくいかもしれません.P3T1755が返す2バイトは,次のようなビット配置になっています. 図10:温度レジスタのビット配置   12ビットのデータが左詰め(MSB側に寄せて)格納されているので,4ビット右にシフトして右詰めに直しています. 符号の展開( if raw & 0x800 )は,氷点下を正しく扱うために必要です.12ビットの2の補数では,最上位のビット11が1なら負の数です.Pythonの整数は桁数の制限がないので,「12ビットの負数」を「Pythonの負数」に直すために 0x1000 を引いています.0℃以上しか測らないなら省略しても動きますが,入れておくのが安全です. MikroBus側のI²Cを使う場合 同じセンサをMikroBusのI²C( flexcomm3_lpi2c3 )から読むこともできます.その場合はジャンパの接続先をMikroBusコネクタのSDA(P1_0)/SCL(P1_1)にして,コードの PINS["I2C"] を PINS["MIKROBUS_I2C"] に変えるだけです. i2c = I2C(PINS["MIKROBUS_I2C"]) 同じMikroBusコネクタの中で,RX/TXからSCL/SDAへジャンパを渡す形になるので,配線は短くて済みます. ▲ 目次に戻る 7. 応用編:SPIを使ってみる 最後にSPIです. 7.1 ループバックで試す I²Cと違って,FRDM-MCXN947にはSPIで繋がったデバイスが載っていません.そこで ループバックで試します. ループバックというのは,MOSI(送信)とMISO(受信)を直結してしまう方法です.自分が送ったデータがそのまま自分に返ってくるので,外部にデバイスがなくてもSPIが正しく動いているかを確認できます. ArduinoヘッダーのSPI( flexcomm1_lpspi1 )は,次のピンに出ています. 信号 Arduinoヘッダー ピン タプル CS D10 P0_27 ("gpio0", 27) MOSI D11 P0_24 ("gpio0", 24) MISO D12 P0_26 ("gpio0", 26) SCK D13 P0_25 ("gpio0", 25) 表6:Arduino SPIのピン割り当て D11(MOSI)とD12(MISO)をジャンパ線で繋いでください. 図11:MOSIとMISOを直結してループバックにする   from machine import Pin, SPI from config import PINS spi = SPI(PINS["SPI"], baudrate=1_000_000, polarity=0, phase=0) tx = bytes([0x00, 0xFF, 0xAA, 0x55, 0x01, 0x02, 0x04, 0x08]) rx = bytearray(len(tx)) spi.write_readinto(tx, rx) print("送信:", [hex(b) for b in tx]) print("受信:", [hex(b) for b in rx]) print("一致:", tx == bytes(rx)) 実行結果はこうなります. 送信: ['0x0', '0xff', '0xaa', '0x55', '0x1', '0x2', '0x4', '0x8'] 受信: ['0x0', '0xff', '0xaa', '0x55', '0x1', '0x2', '0x4', '0x8'] 一致: True 送ったデータがそのまま返ってきました.SPIが正しく動作しています. ジャンパ線を外して実行すると,受信データは変わります.MISOがどこにも繋がっていない状態(ハイインピーダンス)になるので, 0x00 ばかりになったり,不定の値が返ったりします.これも「繋がっていないこと」が確認できたということなので,試してみてください. 送るデータの選び方 0x00 , 0xFF , 0xAA , 0x55 ,そして 0x01 〜 0x08 という並びには理由があります. 0x00 / 0xFF :全ビット0と全ビット1.線が固定されていないかを見る 0xAA / 0x55 : 10101010 と 01010101 .ビットごとに切り替わるので,タイミングの余裕を見るのに向く 0x01 , 0x02 , 0x04 , 0x08 …:1のビットを1つずつずらしていく.ビット順(MSBファーストかLSBファーストか)の確認ができる ロジックアナライザで波形を見るときにも,この並びは判別しやすくて便利です. SPIのモード polarity と phase はSPIのモードを決めるパラメータです. モード polarity (CPOL) phase (CPHA) 0 0 0 1 0 1 2 1 0 3 1 1 表7:SPIのモード ループバックでは自分が送ったものを自分で受けるだけなので,どのモードでも一致します.実際のデバイスに繋ぐときは,そのデバイスのデータシートに合わせてください. なお,I²Cと違ってSPIでは baudrate が指定できます. 7.2 CSは自動制御されない ループバックでは使いませんでしたが,実際のSPIデバイスを繋ぐときにはCS(チップセレクト) が必要になります. ここで,このポート特有の注意点があります. MicroPython ZephyrポートのSPIドライバは,CSを自動制御しません. 多くのMicroPythonのポートでは, SPI オブジェクトにCSピンを渡しておくと,転送のたびに自動でCSをLOWにして,終わったらHIGHに戻してくれます.しかしZephyrポートの実装では,内部でZephyrに渡すSPI設定のCS指定が空になっています. したがって,CSは machine.Pin で自分で制御する必要があります. import time from machine import Pin, SPI from config import PINS cs = Pin(PINS["D10"], Pin.OUT, value=1) # アイドル時はHIGH spi = SPI(PINS["SPI"], baudrate=1_000_000, polarity=0, phase=0) data = bytes([0x9F]) # 例:何かのコマンド rx = bytearray(3) cs.value(0) # CSをアサート(LOW) spi.write(data) spi.readinto(rx) cs.value(1) # CSをデアサート(HIGH) print([hex(b) for b in rx]) CSはアクティブ・ローなのが一般的です. value(0) で選択, value(1) で非選択になります.LEDのときと同じで, 0 が「有効」です. CSを戻し忘れないよう注意してください. LOWのままにすると,次の転送でデバイスが混乱します.転送のたびに cs.value(0) と cs.value(1) を対で書く,と覚えておくのが確実です. MikroBusのSPIを使う場合 MikroBusコネクタのSPI( flexcomm6_lpspi6 )も同じように使えます.これが今回のマージで新しく使えるようになったものです. cs = Pin(PINS["MIKROBUS_CS"], Pin.OUT, value=1) spi = SPI(PINS["MIKROBUS_SPI"], baudrate=1_000_000, polarity=0, phase=0) MikroBusには豊富な種類のClick boardが用意されているので,そちらを繋いで試すのも面白いと思います. ▲ 目次に戻る 8. 応用編:Ethernetを使ってみる 最後にEthernetです. 8.1 有線LANという強み 冒頭でも少し触れましたが,有線のEthernetを持っていることはこのボードの明確な強みです.ここで,その理由を具体的に見ておきます. 電波を使わないので,無線が禁止・制限される場所でも使えます 遅延が安定しているため,決まった周期で応答してほしい用途に向きます 配線した相手としか通信しないので,どこと通信しているかがはっきりします 工場やビル設備など,すでに有線のネットワークが敷かれている環境にそのまま入れます MCXN947のEthernetコントローラ(ENET QoS)はZephyrのドライバでサポートされていて,MicroPythonからは socket モジュールを通して使えます. 8.2 このポートのネットワークAPI 先に,できることとできないことをはっきりさせておきます.ここを知らずに始めると確実に戸惑います. 使えるのは socket モジュールだけです. >>> import socket >>> import network Traceback (most recent call last): File " ", line 1, in ImportError: no module named 'network' ここは,同じNXPのマイコン向けであるi.MX RTの専用ポート( ports/mimxrt )と比べるとわかりやすいと思います.あちらではEthernetを次のように扱えます. import network lan = network.LAN(0) lan.active(True) DHCPサーバがあればアドレスはそこから配られ,無ければ lan.ipconfig(addr4="...") で実行時に設定できます.インターフェースを有効にするのも無効にするのも lan.active() ひとつです. Zephyrポートには,この network モジュールがありません. network.LAN() も ifconfig() も存在せず,IPアドレスの設定や確認をするための専用APIが無い,ということです.アドレスはビルド時のKconfigで決まります(後述). socket オブジェクトが持つメソッドも,一般的なMicroPythonより少なめです. 使えるもの 使えないもの bind / listen / accept / connect getsockname() send / recv / recvfrom / sendto getpeername() read / write / readline / makefile settimeout() setsockopt / close   表8:Zephyrポートの socket で使えるもの・使えないもの 特に効いてくるのが次の3点です. getsockname() が無いので,自分のIPアドレスを直接は表示できません(8.4節で回避策を示します) settimeout() が無いので,通信待ちのブロックから抜ける手段がありません(8.8節で詳しく述べます) accept() が返す接続元アドレスは常に None です.ポートのソースにコメントで // TODO と書かれている,未実装の部分です IPアドレスはビルド時に決まります もうひとつ大きな制約があります.このポートには,実行時にIPアドレスを設定する手段がありません.アドレスはZephyrのKconfigで,ファームウェアをビルドするときに決まります. ports/zephyr/prj.conf の既定値は次のようになっています. CONFIG_NET_CONFIG_MY_IPV4_ADDR="192.0.2.1" CONFIG_NET_CONFIG_MY_IPV4_NETMASK="255.255.255.0" CONFIG_NET_CONFIG_MY_IPV4_GW="192.0.2.2" CONFIG_NET_DHCPV4=y DHCPも有効になっているので,DHCPサーバのあるネットワークに繋げばそちらからアドレスが割り当てられます.DHCPサーバがいない環境では,上の静的アドレス 192.0.2.1 が使われます. なお 192.0.2.x は,RFC 5737で文書の例示用に予約されたアドレスです.Zephyrのサンプル設定がそのまま入っているだけなので,実際の運用では自分のネットワークに合わせた値に変更することになります.変更する場合はボードの .conf に上書きの設定を書いて,ビルドし直してください. 8.3 PCと直結して試す DHCPサーバのあるLANに繋いでもいいのですが,その場合ボードがどのアドレスをもらったのかを知るのが面倒です( getsockname() が無いため). そこでここでは,ボードとPCをLANケーブルで直結して試します.この構成ならボードのアドレスは静的設定の 192.0.2.1 に決まるので確実です. (下の写真では「直結」と言ってもコンピュータにEthernetポートが無いのでUSB Type-CとEthernetの変換アダプタを介して接続しています.この接続でもEthernet接続は1対1の直結接続となります)   図12:ボードとPCを直結する(※ このコンピュータの場合,EthernetポートがないのでUSB Type-Cとの変換器を使って接続した) PC側の設定 PCのEthernetインターフェースを,ボードと同じサブネットにします. 項目 値 IPアドレス 192.0.2.2 サブネットマスク 255.255.255.0 デフォルトゲートウェイ 空欄でよい 表9:PC側のネットワーク設定 192.0.2.2 はボードがゲートウェイとして設定しているアドレスなので,これに合わせておくと都合がいいです. 最近のPCとボードはAuto MDI/MDI-Xに対応しているので,クロスケーブルでなくストレートケーブルで構いません. まずpingで確かめる MicroPythonを触る前に,PCからpingを打つのが確実です.ZephyrのIPスタックはMicroPythonとは別のスレッドで動いているので,REPLに何も入力しなくてもpingには応答します. ping 192.0.2.1 PING 192.0.2.1 (192.0.2.1): 56 data bytes 64 bytes from 192.0.2.1: icmp_seq=0 ttl=64 time=1.088 ms 64 bytes from 192.0.2.1: icmp_seq=1 ttl=64 time=0.657 ms 64 bytes from 192.0.2.1: icmp_seq=2 ttl=64 time=1.938 ms --- 192.0.2.1 ping statistics --- 3 packets transmitted, 3 packets received, 0.0% packet loss これが通れば,PHYのリンク・Ethernetドライバ・IPスタックまで動いていることになります.ここが通らないうちにMicroPythonのコードを書いても意味がないので,先に確認してください. 通らない場合は,ケーブル,PC側のIP設定,ボードの電源を順に確認します. 8.4 自分のIPアドレスを調べる getsockname() が無いので,ボードに「あなたのIPアドレスは?」と直接は聞けません. 代わりに使えるのが bind() の成否です.自分が持っていないアドレスに bind() しようとすると失敗するので,候補を順に試せば,どれを持っているかがわかります. import socket for ip in ("0.0.0.0", "192.0.2.1", "192.168.1.1"): s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) try: s.bind((ip, 9999)) print(" bind OK ->", ip) except Exception as e: print(" bind NG ->", ip, type(e).__name__, e) s.close() 実行するとこうなります. bind OK -> 0.0.0.0 bind OK -> 192.0.2.1 bind NG -> 192.168.1.1 OSError [Errno 2] ENOENT 0.0.0.0 はどの環境でも通る特別なアドレスなので判定には使えません.ここでは 192.0.2.1 だけが成功したので,ボードは静的設定のアドレスを使っているとわかります.DHCPでアドレスをもらっていれば,ここは別の値になります. DHCPを使う場合は,そもそも候補を挙げること自体が難しくなります.その場合は,ルータのDHCPリース一覧を見るのが確実です.「どの機器にどのアドレスを貸したか」の一覧が見られるので,そこからボードのアドレスを拾ってください. 8.5 ボードをWebサーバにする ここまでで疎通は確認できました.最後に,ボードをWebサーバにしてみます.PC側に用意するものはブラウザだけです. import socket srv = socket.socket(socket.AF_INET, socket.SOCK_STREAM) srv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) srv.bind(("0.0.0.0", 8080)) srv.listen(1) print("listen 0.0.0.0:8080 接続待ち...") cl, addr = srv.accept() # addr は常に None print("接続あり:", addr) req = cl.recv(256) print("リクエスト先頭:", req.split(b"\r\n")[0]) body = " FRDM-MCXN947 MicroPython on Zephyr " cl.send("HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n" + body) cl.close() srv.close() bind() に "0.0.0.0" を渡しているのは,「このボードが持っているすべてのアドレスで待ち受ける」という意味です.アドレスを決め打ちしなくて済むので,DHCPでも直結でもそのまま動きます. 実行するとボード側はこう表示して,接続を待ちます. listen 0.0.0.0:8080 接続待ち... この状態でPCのブラウザから http://192.0.2.1:8080/ を開いてください. 図13:ブラウザからボードにアクセスする   ボード側にはリクエストが表示されます. 接続あり: None リクエスト先頭: b'GET / HTTP/1.1' 接続あり: None となっているのが,7.2節で触れた accept() の未実装部分です.接続自体はできていて,通信にも支障はありません. 数十行のPythonで,マイコンがWebサーバになりました.ここから,センサの値をHTMLに埋め込んで返すようにすれば,6章の温度センサをブラウザから読める温度計になります. 8.6 LEDをブラウザから操作する 前節のサーバは,決まったページを1回返して終わりでした.今度はブラウザからボードのLEDを操作できるようにしてみます. 3章で光らせた赤色LEDを, /on と /off というURLで切り替えます. import socket from machine import Pin from config import PINS led = Pin(PINS["LED_RED"], Pin.OUT, value=1) # 1 = 消灯 srv = socket.socket(socket.AF_INET, socket.SOCK_STREAM) srv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) srv.bind(("0.0.0.0", 8080)) srv.listen(1) print("http://192.0.2.1:8080/ を開いてください") running = True while running: cl, _ = srv.accept() try: req = cl.recv(256) path = req.split(b" ")[1] if b" " in req else b"/" if path == b"/on": led.value(0) # アクティブ・ロー: 0で点灯 elif path == b"/off": led.value(1) elif path == b"/quit": running = False state = "ON" if led.value() == 0 else "OFF" cl.send("HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n" "Connection: close\r\n\r\n" " FRDM-MCXN947 " " RED LED: %s " " ON / OFF " "" % state) except OSError as e: print("接続エラー(無視):", e) # 後述.握りつぶして継続する try: cl.close() except OSError: pass srv.close() print("サーバを終了しました") 前節が14行,こちらが38行です. ブラウザで http://192.0.2.1:8080/ を開くと,「ON」「OFF」のリンクが並んだページが出ます.クリックするたびに,ボードの赤色LEDが実際に点いたり消えたりします. 図14:ブラウザからボードのLEDを操作する http://192.0.2.1:8080/quit を開けばサーバが終わり,REPLに戻ります. ここまで動けば成功です.コードの中身と, try / except を入れてある理由については付録にまとめました. 8.7 電源を入れるだけで動くようにする ここまでは,PCからスクリプトを実行していました.最後に,PCを繋がずに電源だけで動くようにしてみます. MicroPythonは起動時に, /flash にある次のファイルを順に探して,あれば自動的に実行します. _boot.py … ファイルシステムのマウントなど(ファームウェアに内蔵,変更不可) boot.py … あれば実行される(起動時の設定用) main.py … あれば実行される(アプリケーション用) つまり /flash/main.py として保存したスクリプトは,電源を入れるだけで動きます. 7.6節のLED操作サーバを main.py として保存してみてください.Thonnyなら,エディタで開いた状態で「ファイル」→「名前を付けて保存」を選び,保存先に「MicroPythonデバイス」を選んで main.py という名前にします. mpremote なら次のとおりです. mpremote cp led_server.py :/flash/main.py 保存したらUSBケーブルを抜き,ACアダプタやモバイルバッテリーなど,電源だけを繋いでください.LANケーブルは繋いだままにします. しばらく待ってからPCのブラウザで http://192.0.2.1:8080/ を開くと,PCと繋がっていないボードのLEDが,ブラウザから操作できます. 数十行のPythonを書いて main.py という名前で置いただけで,ネットワーク越しに操作できる機器になりました. 必ず「抜け道」を用意してから保存してください ここで重要な注意があります. main.py は起動のたびに実行されます.もしその中身が accept() で待ち続けるサーバだと,REPLは永久に戻ってきません.8.8節で述べるとおり,このポートには settimeout() が無く,Ctrl-Cでも抜けられないからです. しかもREPLに入れないということは,その main.py を消すこともできないという状態になります. 7.6節のコードに /quit を入れてあるのは,このためです.ブラウザで http://192.0.2.1:8080/quit を開けばスクリプトが終了し,REPLが戻ってきます.ネットワーク経由の非常口というわけです. main.py を作るときは,次の順序を守ってください. まず普通のスクリプトとして実行し,期待どおり動くことを確認する 終了する手段があることを確認する( /quit など) それから main.py として保存する いきなり main.py に書いて試すのは避けてください. 8.8 ハマりやすい点 settimeout() が無いので,ブロックすると戻ってきません これが一番の注意点です. accept() や recv() は,相手が来るまで待ち続けます.通常のMicroPythonなら settimeout() で待ち時間の上限を決められますが,このポートには実装されていません. さらに,これらはC言語のレベルで待ちに入るため Ctrl-Cが効きません.一度この状態になると,REPLは入力を受け付けなくなります. 筆者はこの状態から復帰するのに,ボードの電源を入れ直す必要がありました.リセットボタンでも戻らないことがあります. 対策としては, accept() を実行したら,すぐに接続しに行く(ブラウザのアドレス欄にURLを入れておき,実行後すぐ開けるようにしておく) 繰り返し受け付けるサーバには,8.6節の /quit のような抜け道を必ず用意しておく 動作を確認するまでは main.py に置かない(8.7節.起動のたびに固まり,REPLに入れないので消すこともできなくなります) エラーで止まったあとは EADDRINUSE になります サーバのプログラムが途中でエラー終了すると,待ち受けに使っていたソケットが閉じられないまま残ります.その状態でもう一度実行すると,こうなります. Traceback (most recent call last): File " ", line 10, in __main__ OSError: [Errno 112] EADDRINUSE 「そのアドレスとポートはもう使われている」という意味です. SO_REUSEADDR を指定していても,前のソケットが本当に開いたままなら効きません. Ctrl-D でソフトリセットすれば,MicroPythonが再起動してソケットがすべて解放されます.サーバを書いて試しているときは,エラーが出たらまずCtrl-Dを押す,と覚えておくと楽です. ネットワークはREPLが止まっていても動いています これは知っておくと切り分けが楽になります.ZephyrのIPスタックはMicroPythonとは別のスレッドで動いているので,MicroPythonが固まっていてもpingには応答します. つまり「pingは通るのにREPLが無反応」という状況は,Ethernetの故障ではなくMicroPythonがブロックしていることを示しています.逆に「pingも通らない」ならケーブルや設定を疑う,という切り分けができます. DNSは環境次第です socket.getaddrinfo() で名前解決もできますが,DNSサーバのアドレスは CONFIG_DNS_SERVER1 の既定値が 192.0.2.2 になっています.DHCP環境ならDHCPから配られたDNSサーバが使われます.直結の構成では名前解決はできないので,IPアドレスを直接指定してください. ▲ 目次に戻る 9. まとめ FRDM-MCXN947でMicroPythonを動かすまでの一通りを見てきました.最後に要点を整理します. 今回のマージで得られたもの 本家 micropython/micropython のmasterにFRDM-MCXN947の設定が入ったことで,パッチをあてずに本家のソースからそのままビルドできるようになりました.オンボードのQSPIフラッシュが /flash として使え,I²C・SPI(ArduinoヘッダーとMikroBusの両方)が動きます. 有線Ethernetが使えること MicroPythonが動く安価なボードの多くは無線でネットワークに繋ぎますが,このボードは有線のEthernetを持っています.電波を使えない場所や,遅延を安定させたい用途では代えがききません.本記事ではpingでの疎通確認から,ボードをWebサーバにしてブラウザから見るところまでを実機で確認しました. Zephyrポートの弱点と,その対策 ピンを ("gpio0", 10) のようなタプルで指定しなければならない点が,このポートの一番の使いにくさです.これは config.py に PINS 辞書を用意して /flash/lib/ に置くことで,実用上ほぼ解消できます.名前で書けるようになるだけでなく,タイプミスが KeyError で検出できるようになるという副次的な効果もあります. 引っかかりやすいポイント ボード設定ファイルの名前は,ボード修飾子込みの frdm_mcxn947_mcxn947_cpu0.conf でないと読まれない cloneしたあとに git submodule update --init lib/micropython-lib が必要 RGB LEDはアクティブ・ロー. value(0) で点灯する( off() を呼ぶと光る) Pin に toggle() はない スイッチ入力は Pin.IN, Pin.PULL_UP で構成する.押すと 0 (LEDと同じアクティブ・ロー) Pin.irq() が使える.既定は hard=False なのでハンドラ内で print() してよい このボードのArduinoヘッダーのI²Cは,A4/A5ではなく専用のSDA/SCLピン(P4_0/P4_1) machine.I2C に freq= / scl= / sda= / timeout= は指定できない(devicetreeで決まる) SPIのCSは自動制御されないので, machine.Pin で手動制御する オンボードのP3T1755はI3Cバスに繋がっていて,MicroPythonにはI3Cドライバがないため,ジャンパでI²Cバスに引き込む必要がある os.uname() はこのポートでは組み込まれていない ネットワークは socket のみ. network モジュールは無い socket に getsockname() が無いので,自分のIPは bind() の成否で調べる socket に settimeout() が無い. accept() や recv() でブロックするとCtrl-Cでも抜けられず,電源の入れ直しが必要になることがある accept() が返す接続元アドレスは常に None accept() は失敗しても例外を投げない.無効なソケットが返り,次の recv() が EBADF になるので, try / except OSError で囲む サーバがエラー終了するとポートが掴まれたままになる.Ctrl-Dで解放する IPアドレスは実行時に変更できない.Kconfigで決まるのでビルドし直す このビルドでは input() が使えない(機能レベルが BASIC_FEATURES のため.対話待ちが必要なときは time.sleep() によるカウントダウンで代用します) MicroPythonは「動くものを早く作る」ことにかけては非常に強力です.FRDM-MCXN947のような高性能なマイコンでも,まずはMicroPythonで動かして感触をつかんでから本番の実装をCで書く,という進め方は十分に現実的だと思います. ぜひ試してみてください. ▲ 目次に戻る 10. 参考資料 MicroPython MicroPython 公式サイト MicroPython ドキュメント MicroPython GitHub リポジトリ MicroPython Zephyrポートのreadme 今回マージされたPull Request (#19573) Zephyr Zephyr Project 公式サイト Zephyr Getting Started Guide Zephyr FRDM-MCXN947 ボードドキュメント Zephyr シリーズ 第2回 はじめてのビルドと実機動作 (日本語ブログ) ツール Thonny 公式サイト Thonnyのインストールと基本操作 (YouTube) mpremote ドキュメント ハードウェア FRDM-MCXN947 製品ページ MCX Nシリーズ 製品ページ P3T1755 製品ページ バス NXPコミュニティ・ブログ:I²Cバスの概要 (日本語ブログ) NXPコミュニティ・ブログ:SPIバスの概要 (日本語ブログ) NXPコミュニティ・ブログ:I3Cバスの概要 次のシリアルバス (日本語ブログ) NXPコミュニティ・ブログ:I²Cハードウェア・デバッグ (日本語ブログ) ▲ 目次に戻る 11. 付録:LED操作サーバのコード解説 8.6節のコードについて,中身の説明をここにまとめました.本文の流れを止めたくないので分けてあります.動かすだけなら読まなくても構いません. 11.1 ここまでの内容が1つにまとまっている このコードは短いわりに,この記事で扱ってきたことをほとんど使っています. from config import PINS — 4章で作ってボードに置いたピン定義 Pin(PINS["LED_RED"], ...) — 3章のLED. value(0) で点灯するのは3.5節で説明したアクティブ・ローだからです socket — 7章のネットワーク 11.2 コードの3つの仕掛け (1) while True で繰り返し受け付ける 8.5節のサーバは1回で終わりでしたが,操作を続けるには繰り返しが要ります.ただしこれには代償があります. accept() で待ち続けるループになるので,8.8節で述べたブロックの問題がずっと続く状態になります. そこで /quit を用意しました. elif path == b"/quit": running = False ブラウザで http://192.0.2.1:8080/quit を開くと,最後の応答を返してからループを抜け,REPLが戻ってきます.たった2行ですが,これが無いとプログラムを止める手段が電源の入れ直ししかなくなります.繰り返し受け付けるサーバを書くときは,必ず抜け道を用意しておくことをおすすめします. (2) リクエストからパスを取り出す ブラウザは,接続すると次のような文字列を送ってきます. GET /on HTTP/1.1 Host: 192.0.2.1:8080 ... このうち必要なのは真ん中の /on の部分だけです.空白で区切って2つ目を取れば済みます. path = cl.recv(256).split(b" ")[1] b" " のように b が付いているのは,通信で受け取るのが文字列ではなくバイト列だからです.比較する側も b"/on" と書く必要があります. (3) 現在の状態をページに反映する led.value() を引数なしで呼ぶと,いまの出力値が読めます.アクティブ・ローなので 0 が点灯です. state = "ON" if led.value() == 0 else "OFF" これで,ページを開き直すたびに現在の状態が表示されます. 11.3 例外処理が必要な理由 素直に書くと, try / except を省いて次のようにしたくなります. cl, _ = srv.accept() path = cl.recv(256).split(b" ")[1] # ← ここで落ちることがある ところがこう書くと,ブラウザで操作を繰り返すうちに必ず次のエラーで止まります. Traceback (most recent call last): File " ", line 16, in OSError: [Errno 9] EBADF EBADF は「無効なファイル記述子」という意味です. accept() が返してきたソケットが,そもそも使える状態になっていません. 原因はこのポートの実装にあります. ports/zephyr/modsocket.c の accept は,こうなっています. int ctx = zsock_accept(socket->ctx, &sockaddr, &addrlen); socket_obj_t *socket2 = socket_new(); socket2->ctx = ctx; /* エラーチェックが無い */ 同じファイルの他の関数は RAISE_SOCK_ERRNO(res) で戻り値を検査しているのに, accept だけが検査をしていません. zsock_accept() が失敗して -1 を返しても,それをそのままソケットの中身として持ち帰ってしまいます.その結果,次の recv() が EBADF になる,という流れです. ではなぜ accept() が失敗するのか.Zephyrが同時に扱えるネットワーク接続の数に上限があるためです. CONFIG_NET_MAX_CONTEXTS=6 CONFIG_NET_TCP_TIME_WAIT_DELAY=1500 同時に使える通信の枠が6個しかなく,しかも閉じた接続も1.5秒間は枠を占有し続けます(TCPの TIME_WAIT という状態です).ブラウザはページ本体のほかに /favicon.ico なども取りに来るので,続けてクリックしていると,あっという間に6個を使い切ります. そこで,例外が出ても握りつぶして次の接続を待つようにしてあります.これで,たまに応答が返らないことがあっても,サーバは動き続けます. except OSError as e: print("接続エラー(無視):", e) cl.close() も try で囲んであるのは,壊れたソケットを閉じようとして,そこでまた例外が出るのを防ぐためです. 実際にどのくらい失敗するのか 筆者の環境で測ってみました. 操作のペース 成功 / 試行 間隔をあけずに連打 32 / 40 1秒間隔 15 / 15 2秒間隔 10 / 10 表10:クリックの速さと応答の取りこぼし 人がブラウザをクリックする程度の速さであれば,取りこぼしは起きません.連打すると一部が応答しなくなりますが,例外処理を入れてあるのでサーバが止まることはありません.再度クリックすれば普通に反応します. 11.4 Connection: close について これは「この応答を返したら接続を切ってください」とブラウザに伝えるものです.ブラウザは既定では接続を使い回そうとしますが,そうすると上で述べた6個の枠を長く占有してしまいます.明示的に切ってもらうことで,枠の解放を早めています. 11.5 そのほか気をつける点 ページの文字はASCIIにしてあります.日本語を入れる場合は Content-Type: text/html; charset=utf-8 としてください req.split(b" ")[1] if b" " in req else b"/" としているのは, recv() が空を返したときに IndexError で落ちないようにするためです Connection: close を返している理由も付録で説明します 11.6 この挙動は将来変わるかもしれません accept() のエラーチェックが無い点は,本家に報告すれば修正されうる部分です.修正されれば accept() が正しく例外を投げるようになるので, try / except の書き方も素直になります.ここに書いた内容は,2026年8月時点のものとしてお読みください. ここまで来れば,あとは応用です. led を3色それぞれに増やせばRGBの操作盤になりますし,6章の温度センサの値をページに埋め込めば,ブラウザから読める温度計になります. ▲ 目次に戻る 変更履歴:2026-09-02:初版 ========================= 本投稿の「Comment」欄にコメントをいただいても、現在返信に対応しておりません。お手数をおかけしますが、お問い合わせの際には「NXPへの技術質問 - 問い合わせ方法 (日本語ブログ)」をご参照ください。(既に弊社NXP代理店、もしくはNXPとお付き合いのある方は、直接担当者へご質問いただいてもかまいません。) MicroPythonの本家リポジトリ,そのZephyrポートに,FRDM-MCXN947向けの設定がマージされました.これまでNXPのマイコンでMicroPythonを使う選択肢は事実上 i.MX RT シリーズに限られていましたが,そこに,より小規模で手を出しやすい MCX N シリーズが加わったことになります. この記事では,ファームウェアのビルドと書き込みから始めて,REPLでの対話操作,Lチカ,スイッチ入力と割り込み,I²Cでの温度センサ読み出し,SPI,そして有線EthernetでボードをWebサーバにしてブラウザから LED を操作するところまでを,順を追って解説します.掲載したコードはすべて実機で動作を確認したものです. 「MicroPythonを触るのは初めて」という方を想定し,途中でつまずきやすい点や,このポート固有の制約とその回避策も含めて書きました. MicroPython and FRDM-MCXN947MicroPython and FRDM-MCXN947MicroPython and FRDM-MCXN947MicroPython and FRDM-MCXN947 Ethernet Interface introduction MCX 日本語ブログ Re: FRDM-MCXN947でMicroPythonを動かす (日本語ブログ) 这篇文章值得付费阅读,非常有趣。 Re: FRDM-MCXN947でMicroPythonを動かす (日本語ブログ) 谢谢
View full article
FRDM-MCXN947でMicroPythonを动かす (日本语ブログ) MicroPython, FRDM-MCXN947, ZephyrMicroPython, FRDM-MCXN947, ZephyrMicroPython, FRDM-MCXN947, ZephyrMicroPython, FRDM-MCXN947, Zephyr MicroPython 's main family R&D , Zephyr's Zephyr , FRDM-MCXN947's FRDM-MCXN947 setting. Zephyr ポートというのは, MicroPython をZephyr RTOSの上でかす transplanted version です. MicroPython is usually used in microPython. "(Ported version) を志ちますが, MCX シリーズに専用ポートはありません.その代わり, Zephyr が対応しているボードなら动かせるこの士组みを使います (Detailed しくはSection 1.3 ). ビルド自体は, これまでもできました.ただしボード inherent setting が无かったため, come out on がるのはminimum limitのMicroPythonで,スクリプトをSaveするファイルシステムも无く,I²CもSPIも使えませんでした. This time, the first step is to make the first step. これでNXPのマイコンでMicroPythonをmake the selection択limbが広がりました.これまでは事実上,上上のクロスオーバーMCUであるi.MX RTシリーズにlimited られていましたが,そこにMCX Nシリーズという,より小scaleで手を出しやすい选択limbがplusわったことになります. このボードにWired のEthernetが load っている点も见狠せません. MicroPython が安価なボードの多くは, Wi-Fi やBluetooth でネットワークにつなぎます. The purpose is the same as the radio wave, the wired one is the wired one, the scene is the same.この记事の后halfでは,ボードをWebサーバにしてブラウザからLEDをoperationするところまで动かします. On one side, the restriction is on one side. Zephyr ポートは, チップ専用のポートに比べると Function がtwisting られます.たとえば同じNXPのマイコンでも, i.MX RTけの ports/mimxrt には network.LAN() があってIPアドレスを実行时にSETできますが, Zephyrポートには network モジュール自体がありません. Make the えるのは socket だけで, IP アドレスはビルド时にしかdetermine められません.この记事では, そうした restricts と, 実记にぶつかったproblem のevasion strategy も有めて书いています( section 8.2にorganizing しました). Since then, MicroPython has begun, and MicroPython has begun ,LED を光らせ,スイッチを読み,I²CやSPIのデバイスを动かし, the last にEthernet をmake うところまでを一通り Explain します. 「MicroPythonをtouchるのは初めて」という方を思定して, on the way, the hand is smooth and the way is omitted.せずに书きました. この记事の読み方 It’s a long story, it’s a long story, it’s a must. Zephyr's open environment environment → Section 2.1から すでにビルドと书き込みが済んでいる方→ Chapter 3から How to do it first? → Section 8.6 (Example of how to operate an LED) Chapter ごとにNecessaryなものは时のとおりです. Chapters 1~5 : FRDM-MCXN947 main body and USB cable [Assignment time: 60 minutes] Chapter 6 (I²C) : ジャンパ线 2 books [Assignment time: 20 minutes] Chapter 7 (SPI) : ジャンパ线 1 [Assignment time: 20 minutes] Chapter 8 (Ethernet) : LAN Controller 1 [Assignment time: 20 minutes] 0. Catalog Table of contents MicroPythonとはなんなのか? 1.1 どういうところで使われているのか 1.2 MicroPythonのいいところ,悪いところ 1.3 MCX Maintenance: 「Zephyrポート」form 1.4 This time's の対応でできるようになったこと 1.5 Zephyr's Weakness: Designated by Zephyr MicroPython Zephyrポートのビルド 2.1 Zephyr open environment environment 2.2 MicroPython のソースをGet する 2.3 ビルドする 2.4 ボードに书き込む MicroPython ってみる — Basic Editor 3.1 Thonny する 3.2 USB USB 3.3 Accept the confirmation 3.4 「REPL」とは 3.5 スクリプトを书いてみる:Lチカ 3.6 このボードで使えるピンを动べる 3.7 Lチカの色を変えてみる Edited by: ピン名を公夫する 4.1 まずはスクリプトの中にPINS Dictionary を书く 4.2 config.pyにcutり出す 4.3 ストレージにSaved by してShared by する 4.4 config.pyった3色Lチカ Editor: スイッチを読む 5.1 スイッチのSTATEを読む 5.2 杀されたことを Cut り込みで知る User editor: I²C ってみる 6.1 このボードのI²C matter 6.2 ジャンパを2本つなぐ 6.3 バスをスキャンする 6.4 Temperature control Editor: SPI ってみる 7.1 ループバックでtrial 7.2 CS automatic control system Editor: Ethernet ってみる 8.1 Wired LAN connection 8.2 このポートのネットワークAPI 8.3 PC direct connection test 8.4 Self-divided IP address 8.5 ボードをWebサーバにする 8.6 LED display operation method 8.7 The power supply is connected to the power supply. 8.8 ハマりやすいPoint まとめ References Additional Notes: LED Operation System Explanation 11.1 ここまでのcontentが1つにまとまっている 11.2 コードの3つのShi hangけ 11.3 Reasons why exceptions are necessary 11.4 Connection: close について 11.5 そのほか気をつける点 11.6 The future of the future 1. MicroPython とはなんなのか? MicroPythonは,マイコンの上でdirect actionくPython 3のインタプリタです. Damien in 2013 George's Kickstarter fund collection is open now.はオープンソース(MITライセンス)のプロジェクトとして开発が続いています. "Python 3 processing system" といっても, PC で动くCPython をそのままhold ってきたわけではありません. There are hundreds of KB of ROM and dozens of KB of RAM, and the language can be used in a variety of ways.そのためgrammarはPython 3とほぼ Same as じですが, standard ライブラリはnecessary なものだけがpurpose されています. その代わりに,マイコンならではのモジュールが意されています. GPIO, I²C, SPI, UART, PWM, ADC and other machine functions.このブログでも machine モジュールを使っていきます. なお,この章はBackground descriptionです. すぐに手を动かしたい方はChapter 2へ入んでください. 1.1 どういうところで使われているのか MicroPython is used to perform tasks, and times are used to perform scenes. Educational use : BBC micro:bitがMicroPythonをadoptsしたことで,一気に知られるようになりました. Raspberry Pi Pico も MicroPython を formula に サ ポ ー ト し て い ま す. プロトタイピング:センサをとりあえず动かしてデータを见てみたい,というstageでは. Jig and measuring device : Manufacturer of ラインの検CHECK Jig や, のように of simple measuring device for 実験 use, 『A small amount of でいいのでEarly work りたい』ものに向いています. ホビー:Electronic work is divided into different areas. いずれも                                            sincecessous by early く作る」ここがMicroPython's one-stop proud division といえます. 1.2 MicroPythonのいいところ,悪いところ このsectionのcontentは, specific のマイコンやポートにlimit らない, MicroPython’s general properties です. Make the judgment of うかどうかをできるように, 両面を挙げておきます. いいところ コードが简単に书ける:Python 3のgrammarがそのまま使えます. The character string processing is the same as the operation, and the C processing is the number of lines and the writing is the same. The answer to the question is: ボードに与続して, 1 line of ずつコマンドを打ち込みながらactionを正かめられます. 「このピンをHIGHにしたらLEDはPointくのか, eliminateえるのか」といったconfirmationが,その fieldで1 row hitつだけで済みます.ハードウェアの挙猙动を Manual detection りで真かめるとき, これは very strong です. (この対情码ENVIREPLとHUびます.Section 3.4 detailed explanationします) ビルドが要らない:スクリプトを书いて実行するだけです.コンパイル・リンク・书き込みのサイクルが不要なので, trial and error がspeed く ります. Learn コストがlowい: Python を知っていれば, マイコンのknowledge だけ Foot せば开 められます. 悪いところ The speed of running is : インタプリタなので, Cで书いたコードに is dozens of times higher than べると, and it is a hundred times higher than ぅくなります. It is necessary to control the necessary processing and high-speed signal processing.ただし対泽はあって,Guan Shuに @micropython.native や @micropython.viper のデコレータをpayけると, その关数だけをネイティブコードにコンパイルできます.それでも足りないoccasionは,そのpartだけCで书いてモジュールとして组み込むこともできます. メモリを食う: インタプリタ main body and standard ライブラリをマイコンにせる Required があります. Hundreds of KB of RAM, tens of KB of RAM, consumption of books in front of the time. The small さなマイコンでは is now the ではありません. ガベージコレクションがThe action of the movement is complete and the control is complete. MCXN947は2MBのフラッシュと512KBのSRAMをチップ上にholdっているので,メモリの点では yuyu をもってMicroPythonを开せられます. 1.3 MCX Maintenance: 「Zephyrポート」form MicroPythonは,マイコンのkindごとに「ポート」とcallingばれるported versionをholdっています. ports/rp2 (Raspberry Pi Pico), ports/mimxrt (i.MX RT), ports/esp32 といったtool合です. The これらはeach マイコンのレジスタやSDKを is directly 叩く, and the そのチップ専用の実装です. MCX シリーズについては, このような専用ポートはexistent しません.その代わりに使えるのが ports/zephyr , つまりZephyr RTOSの上で动かすポートです. Zephyrがサポートしているボードなら, principle of the same "MicroPython" Zephyr Zephyrめ, MicroPython side has a unique and necessary function. FRDM-MCXN947 は Zephyr が に サ ポ ー ト し て る ボ ー ド な の で, こ の士组 み に ride る こ と が で き ま す. NXPのマイコンでMicroPython is used ここで小しorganize しておきます. NXPのマイコンでMicroPythonを动かそうとしたとき,これまで実性的な选択limbはi.MX RTシリーズでした。 Exclusive use of ポートの ports/mimxrt がRT1010からRT1170までのEVKやTeensy 4 . Zephyrポートにも前からいくつかNXPボードのSETが入っていましたが, mimxrt1020_evk や mimxrt685_evk_cm33 といったクロスオーバーMCU to けか, frdm_k64f / frdm_kw41z のようにかなり前のKinetis to けで, しかもlater はファイルシステムやI²C/SPIまで全えられたものではありませんでした. i.MX RT has high performance and high performance, while MCU has a high-end product group. "MicroPython's use of microPython" and its purpose are as follows: This time, the settings of FRDM-MCXN947 are set up, and the general-purpose MCU is MCX Nシリーズという, より手を出しやすい选択limbs plus わりました.これもThis time's の対応のmeaningのひとつだと思います. 図1: MicroPython Zephyr class   この道には, 强的do と无码 の両方があります. Changsuo, Zephyr, Zephyr, が対応しているボードに纃く unfolds できること. Short place, Zephyr's abstraction, すぶん, チップ専用ポートに比べて「そのボードらしい书きFlavour」が thin くなることです. The specific details will be discussed later. 1.4 This time's の対応でできるようになったこと Zephyr's own body has been used before, and the settings used for FRDM-MCXN947 have been set up.そのままビルドすると,対语的にコマンドを打ち込むことはできても,ストレージもI²CもSPIも使えない,というSTATEでした. This time, the following の2つのファイルが本家 micropython/micropython のmasterにマージされました. ports/zephyr/boards/frdm_mcxn947_mcxn947_cpu0.conf ports/zephyr/boards/frdm_mcxn947_mcxn947_cpu0.overlay これによって,时のことができるようになっています. (1) オンボードのフラッシュをファイルシステムとして使える FRDM-MCXN947にっている8 MiBのQSPIフラッシュ(Winbond W25Q64JV)の storage_partition を,LittleFSとして /flash にマウントします. The book is saved by the book いたスクリプトをボード上にしておけるようになる, the というmeans で, and the これが一大きい変changes です. 実界にマウントしたstatusでCapacityをconfirmationすると,时のようになります. >>> import os >>> os.statvfs('/flash') (4096, 4096, 2048, 2043, 2043, 0, 0, 0, 0, 255) ブロックサイズ4096バイト × 2048ブロック = 8 MiB のうち, LittleFS management area をexcept いたabout 7.98 MiB が えます. (2) MikroBusのSPIが使えるようになった MikroBusコネクタのSPI( flexcomm6_lpspi6 )をeffectiveにしています.このSPIは, ボード通のdevicetree ではピンDefinition まで意されているものの, status = "disabled" のままになっていました. MOSI/SCK is used for P3_20/P3_21, SAI1 is shared with others. SAIは Serial Audio Interfaceの slightly, I²SやTDMといったデジタルオーディオのデータをやり出りするためのシリアル・インターフェースです.オーディオコーデックやマイクを行ぐときに使うもので, Same as じピンをSPIとSAIの両squareにsimultaneouslyに Cutり为てることはできません.そのためボード common definition では, どちらともdetermine めずに invalid にしてありました. では, どちらに使うのか. This time the overlay is valid and the SPI is valid and the judgment is valid. Gen拠は単正で,MicroPythonのZephyrポートにはI²S /SAIをうドライバも machine.I2S のようなクラスもexistent しないからです.つまりSAI1のピンとして半しておいても, MicroPython からは making いようがありません.それならSPIとしてmakes えるようにしたほうが useful だろう, というわけです. (3) I²CとSPIのドライバが组み込まれるようになった CONFIG_I2C=y と CONFIG_SPI=y しています.これがないと machine.I2C や machine.SPI を作ろうとしてもFAILURE します. 1.5 Zephyr's Weakness: Designated by Zephyr さて, ここでZephyrポートの「使いにくいところ」を前に说しておきます.あとで対 Ceをshowすので,まずはquestionを知っておいてください. Normally MicroPython is used, and the name of MicroPython is specified by name. # i.MX RTの専用ポート(ports/mimxrt)の場合 led = Pin('D9', Pin.OUT) # Raspberry Pi Pico の場合 led = Pin(25, Pin.OUT) # ESP32 の場合 led = Pin(2, Pin.OUT) Same as NXP's のマイコンでも, i.MX RT's の専用ポートでは 'D9' というボード上の表记そのままの名前が使えます. ところがZephyr ポートでは, GPIO ポートname とビットposition のタプルでspecified します. # FRDM-MCXN947(Zephyrポート)の場合 led = Pin(("gpio0", 10), Pin.OUT) ("gpio0", 10) は「GPIO0ポートの10ビット目」,つまりデータシート上のP0_10を Refers to します. The form of the violation is the crossing, and the time is the crossing. >>> Pin(25, Pin.OUT) Traceback (most recent call last): File " ", line 1, in ValueError: Pin id must be tuple of ("GPIO_x", pin#) なぜこうなっているかというと, ZephyrのdevicetreeではGPIOが gpio0 , gpio1 ,…というポート単position のデバイスとしてDefinition されていて, その中のビットposition でピンをrefers to すからです. MicroPython side is open and closed. The problem is that the digital circuit is printed and printed .たとえば    っても,そのD9が ("gpio0", 10) であることは,devicetreeを読まないとわかりません. Arduino ヘッダーの D9 や, RGB LED の 赤 といった名前は, MicroPython everything seen えないのです. これはかなりIt’s inconvenient. Chapter 4 : この対 CeをStep by StepをChasingってIntroductionします. コラム:Zephyrは「SDKの下注り」としても使われている Zephyr み込みアプリケーションを书くためのRTOS" というイメージが强いと思います.実记そのとおりなのですが, recently the はもうひとつの使われ方が目立ってきました. Don't use the SDK to install the platform on the ground . This time's MicroPython Zephyrポートがまさにそれです.ユーザーが书くのはPythonのコードで, Zephyr's existence をconsciousness することはほとんどありません. MicroPy thonのインタプリタ自も, Zephyrのスレッドのひとつとして実行されています. Example of the same structure: ArduinoCore-zephyrがあります.これはArduinoのAPI( pinMode() , digitalWrite() , Wire , SPI ...)をZephyrの上に実装したもので, Arduino IDEから使うlimitりはZephyrは见えません.けれども下注りはZephyrなので, Zephyrが対応しているボードにArduino environment をhold ち込めることになります. このように「Zephyrをdirect use」に「Zephyrの上にったものを使う」という选択 Limb が壗えてきています. Zephyr's のボードサポートを preparation することが, そのままMicroPython やArduino's 対応にもつながる, というrelations です. ▲ Catalog に戻る 2. MicroPython Zephyrポートのビルド ここからは実记に手を动かしていきます.まずはファームウェアをビルドしてボードに书き込みます. 2.1 Zephyr open environment environment この记事のコマンド Exampleは, macOSやLinuxのシェル(bashやzsh)をpremiseにしています. Windows is easy to use, and the environment is easy to use. コラム:Windows does not enter the situation The first conclusion is the book, the Windows PowerShell (cmd.exe), the Windows PowerShell, and the PowerShell .コマンドを书きchangeえても駄目です. MicroPython's processing is done, and UNIX's dependency is maintained.ビルドを定めている py/mkrules.cmake の中で, cat ・ sed ・ touch が directly call ばれています.たとえばqstr (character sequence テーブル) する箇所は, 时のようなシェルのパイプライン1 で书かれています. cat … | sed … | (Cプリプロセッサ) | sed … > 出力ファイル これらのコマンドはWindowsにexistingしません. cmd.exe There cat is sed no ending, and the ending is ending.シェルを変えてもsolvedしないのはこのためです. 実记,MicroPython's main familyのCIでも, Zephyrポートのビルドは ubuntu-latest でのみ実行されています. Windows でのビルドは Thought されていません. 风らわしいのですが, Zephyr's own はネイティブのWindows でビルドできます.この节で IntroductionするZephyrのGetting Started Guideにも、wingetでツールを入れるWindows 到けの手顺があります. MicroPythonをビルドするdan step になって初めて行き诘まる, ということが出こります. Windows has entered the environment, and the environment of the UNIX environment has improved.どちらでも、この记事のコマンドはそのまま使えます. WSL2 (Windows Subsystem for Linux). Zephyr's Getting Started Guideでも, Ubuntu's application to the user's hand is easy to use. Import instructions for Microsoft Git for Windows (Git Bash) やMSYS2のbash environment なお,ビルドと书き込みだけをUNIX environment で行い, Thonny でのMicroPython operation は Windows side から, という分け方 もできます. ThonnyもmpremoteもWindowsでそのまま动くので, from chapter 3 onwardsはWindowsだけで入められます. MicroPython Zephyr's environment (west, Zephyr SDK, Python's environment) is not necessary Zephyr environment construction guide, NXP Japanese language explanation and explanation The まだenvironment is made by the っていない方は, and the まずそちらを refers to the してください. Zephyr シリーズ Chapter 2 はじめてのビルドと実机动(日本语ブログ) この记事で Reference していただきたいのは, Kailu environment をインストールする partです. The second half of the story, Zephyr, Zephyr blinky など)をビルドして动かしますが,このブログでビルドするのはZephyrのサンプルではなくMicroPythonです.ビルドの対相をSpecificationするPartだけがviolationうとtestえてください. west build The status of the pass is the same as the work, and the preparation is completed. Zephyr's formula is the following. Zephyr Getting Started Guide Environment ができていれば, ~/zephyrproject のようなディレクトリにwest workspace がpurpose されているはずです. Hereafter はこれを ~/zephyrproject として说します. 2.2 MicroPython のソースをGet する MicroPython のソースは, Zephyr のworkspace とはdifferent place に Location い て struct い ま せ ん. Zephyr's workspace is dirty, and it's a different place. git clone https://github.com/micropython/micropython.git cloneしたら,为られたディレクトリに动ってサブモジュールをGetします. cd micropython git submodule update --init lib/micropython-lib micropython-lib MicroPython uses the standard ライブラリgroup and サブモジュールとしてseparationされています.これをGet the しておかないとビルド时にエラーになるので, forget the れずに実行してください. The book that appears is the book, the setting for FRDM-MCXN947 is the master of the main house.パッチをあてるNecessaryはありません. Read the のため, and use the のファイルがあることを to confirm the しておきましょう. micropython ディレクトリにいるSTATUSのまま実行します. ls ports/zephyr/boards/ | grep mcxn947 frdm_mcxn947_mcxn947_cpu0.conf と frdm_mcxn947_mcxn947_cpu0.overlay の2つが means されればOKです. なぜファイル名が长いのか Zephyr では, the same as じボードでもコアやaction モードによってplural の constitute をhold つことがあります. FRDM-MCXN947 Cortex-M33 Cortex-M33 をデュアルで is equipped with しているため, frdm_mcxn947/mcxn947/cpu0 のように「ボードName/SoC name/コアname」specified します. Board qualifier (board qualifier) and board qualifier. MicroPython's Zephyr ポートは, このmodifier をincluding めた名前でconf/overlay をExploration します.つまり frdm_mcxn947.conf という名前では読み込まれません. frdm_mcxn947_mcxn947_cpu0.conf としてはじめて见されます. The self-divided settings are added to the setting, and the settings are added to the settings. 2.3 ビルドする まずZephyrの仮 Thinking about the environment をeffectiveにします. source ~/zephyrproject/.venv/bin/activate Zephyrのバージョンを合わせます. cd ~/zephyrproject/zephyr git checkout v4.4.0 west update MicroPython's Zephyr ポートが対応を明言しているのは, v3.7 (LTS) and v4.4, そして开発版です. Honke's CIはv4.4でビルドを検证しています.のバージョンになっていると, outside workspace , 通ってもactionがviolationったりすることがあるので,ここでv4.4.0に揃えておきます. west update HALやライブラリなどのrelated モジュールをtake り正すためのものです. git checkout だけでは不integrationが residualるので,必ずセットで実行してください. Preparationができたら west build を実行します. cd ~/zephyrproject west build -b frdm_mcxn947/mcxn947/cpu0 ~/micropython/ports/zephyr -b がボード specifies, the last argument is がビルド対相のアプリケーション(MicroPythonのZephyrポート)です. ~/micropython のpartは,実记にcloneしたplaceに読み为えてください. ビルドが通ると build/zephyr/ の下に zephyr.bin , zephyr.hex , zephyr.elf がGenerationされます. After 2 episodes, the settings are straight and straight, --pristine (または -p ) The result of the previous return is the result of the previous return. cd ~/zephyrproject west build -p -b frdm_mcxn947/mcxn947/cpu0 ~/micropython/ports/zephyr 2.4 ボードに书き込む FRDM-MCXN947にはMCU-LinkデバッガがオンボードでThe book is written in a different way, the purpose is necessary, and the book is written in a different way. USB ケーブルはJ17 (MCU-Link side USB コネクタ) connector 図2: USB connector J17 (MCU-Link side) connector Receive 続したら, west flash を実行するだけです. cd ~/zephyrproject west flash Book き込みがEnd わると, ボードはAutomatic にリセットされてMicroPython がStart します. このJ17は书き込みだけでなく, MicroPython と対语するためのシリアルcommunication にも使います.つまりケーブル1で书き込みとoperationの両方ができます. Detailed description in Section 3.2 . ▲ Catalog に戻る 3. MicroPython ってみる—Basic editor ファームウェアが书き込めたら, いよいよMicroPython をtouch っていきます. 3.1 Thonny する MicroPython is easy to use, and the environment of MicroPython is not necessary.ターミナルソフトでもstructuring いませんが, ここではThonnyをmaking います. Thonny is MicroPython's first functional function and is also an IDE. Free of charge, Windows / macOS / Linux can be used. Thonny formula サイト The basic operation of Thonny's のインストールと is the basic operation, and the following animation is the corresponding part. MicroPythonをi.MX RTクロスオーバーMCUで动かしてみた(YouTube) — Thonnyの Import PartからRegenerationされます Thonny is the advantage of the point, and the communication is the same. The upper part of the book, the upper part of the book, the upper part of the book, the upper part of the book ボードのファイルシステム( /flash )の中体をGUIで见られる PCとボードの间でファイルをドラッグ&ドロップでコピーできる という点です. Chapter 4. 3.2 USB USB FRDM-MCXN947にはUSB Type-Cのコネクタがpluralあります. MicroPython のコンソールにsystem ぐのはJ17 , MCU-Link side のコネクタです ( Section 2.4の図2と同じ地です). MicroPython のコンソールは, Zephyr のコンソール( zephyr,console )に出力されます. FRDM-MCXN947のcpu0では,これが flexcomm4_lpuart4 (P1_8 / P1_9) The original MCU-Link MCU-Link VCOM (仮愿COMポート) がっています. つまりJ17の1书で,ファームウェアの书き込みとコンソールの両方ができます. The main body of MCXN947 is the USB system of the main body, and the composition of this chapter is the USB system. 3.3 Accept the confirmation ケーブルを行いだらThonnyをStartします. Thonny's lower right (またはメニューの「実行」→「インタプリタの选択」)から,インタプリタとして「MicroPython (generic) "を Select び, ポートにボードのVCOM をSpecify します. Windows: COM3 のような名前 macOS: /dev/cu.usbmodem… Linux: /dev/ttyACM0 など 図3:インタプリタに「MicroPython (generic)」を选ぶ   The うまく system is a がると, the lower のシェル(Shell) ペインにプロンプトが出ます. Ctrl-D (ソフトリセット)を気てみてください. MicroPython v1.30.0-preview.17.g47e9329e51 on 2026-08-30; zephyr-frdm_mcxn947 with mcxn947 Type "help()" for more information. >>>   図4: The success of the 続にすると, シェルペイン(ウィンドウ下)にバナーとプロンプトが means される The last part of zephyr-frdm_mcxn947 with mcxn947 is the focus of attention. zephyr-frdm_mcxn947 はZephyrの CONFIG_BOARD , mcxn947 は CONFIG_SOC から作られる名前です.ここがLook forward to どおりになっていれば, snipe ったボード Use のバイナリが move いているとconfirm できます. >>> がプロンプトです.ここにPythonのstyleを打ち込めます.まず「Hello, world!」のexpressionから出してみましょう. >>> print("Hello, world!") Hello, world! MicroPython はPython なので, formula をhit つだけでも results が return ります. >>> 1 + 2 3 >>> "MCX" * 3 'MCXMCXMCX' ファイルシステムもconfirmationしておきます. >>> import os >>> os.getcwd() '/flash' >>> os.listdir('/flash') [] Start the straight back のカレントディレクトリが /flash になっています.これはThis time the マージされたsetでLittleFSがマウントされているからです.まだ何も志いていないので中体は空です. 3.4 「REPL」とは いま打ち込んでいるこの対情码ENVIRONMENT をREPLとHUびます. R ead (読む), E val (evaluation価する), P rint (expression す る), L oop (粲 り return す) no initial character で す. 1 line of input force, MicroPython はそれを読み, 実行し, the result を represents し, また时の enter force をWaiting ちます.これがREPLです. コンパイルして书き込んで実行して, という手顺をStep on the result of がわからないCの开発と比べると, trial and error の回しかたそのものが変わってきます.たとえば「このピンをHIGHにしたらLEDは点くのか, eliminateえるのか」といったconfirmationが, そのfieldで1 line hit つだけで済みます.ハードウェアの挙猙动を Manual detection りで真かめるとき, REPL はvery powerful な props になります. REPL is easy to use and easy to operate. キー Action Ctrl-C 実行中のプログラムをinterruptionする Ctrl-D MicroPython ソを restart する Ctrl-E ペーストモードに入る Ctrl-A rawREPLモードに入る Ctrl-B Normal REPLモードに戻る Table 1: REPL control system Ctrl-Cは, unlimited ループに入ってしまったプログラムをstop めるときに使います. Ctrl-D Ctrl-Eのペーストモードは, plural line のコードをまとめてsticker けるときに使います. Normally REPLは1行ごとにインデントを解釈しようとするので, for 文のようなplural lineのコードをそのままるとうまくいかないことがあります. Ctrl-E して ら コ ー ド を paste り け, Ctrl-D で実行 す る と, ま と め て さ れ ま す. 3.5 スクリプトを书いてみる:Lチカ ここまではREPLに1行ずつ打ち込んできました.ちょっとしたconfirm にはこれが一半hayいのですが,缲り回しやconditions divergence が into ってくるとさすがに俫なります.そういうまとまったprocessingは, スクリプトとして书いたほうが楽です. ではスクリプトを书いてみましょう. LED のLチカ(LEDチカチカ)です. FRDM-MCXN947にはRGBのLEDがっています.まずは红を点杀させてみます.红のLEDはP0_10,つまり ("gpio0", 10) に式がっています. Thonny's upper part is the upper part of the book, and the second part is the book. import time from machine import Pin led = Pin(("gpio0", 10), Pin.OUT) # 赤LED (P0_10) while True: led.value(0) # 点灯 time.sleep(0.5) led.value(1) # 消灯 time.sleep(0.5) 図5: The upper side of the book. Lower side がシェルペイン   书けたら, ツールバーの「実行」ボタン(Green Triangleのアイコン.ショートカットはF5)を気ます. Thonnyが           ,                           ious Generation                   ched in in in on in MicroPython Today's test is the same as the test, and the test is the same as the test. The red LED lights up successfully in 0.5 seconds. Stop it, stop it, stop it, stop it.シェルペインでCtrl-Cを気ても同じように出まります. ここで「あれ?」と思った方へ コードをよく见てください. value(0) means turning on the lights, value(1) means turning off the lights. Intuition is the opposite of seeing the truth, and the harmony is the truth. FRDM-MCXN947のRGB LEDは,アノードコモンでConnect続されています. LED side power supply system, マイコンのピンがマイナス side を lead っ Zhang る-shaped です.つまりピンをLOW(0)にしたときにcurrent が流れてlighting します.このような涚をアクティブ・ローといいます. 図6: The RGB LED part of the FRDM-MCXN947 circuit . LED power supply system   Zephyrのdevicetreeには,このLEDが GPIO_ACTIVE_LOW であるというInformationがちゃんと书かれています.しかしMicroPythonの machine.Pin は,devicetreeのこのフラグを见ずにGPIOを生の値のまま読み书きします(内で gpio_pin_set_raw() をHUんでいます).そのため, 论理をanti転してくれることはありません. 0 を书けばピンはLOWになり,LEDは点きます. ちなみに, led.value(0) は led.off() とも书けます.つまり led.off() をHUぶとLEDはLight upします. Mingmao と実记のaction が inverse になるので, chaos しそうなときは value(0) / value(1) で书くほうが安全 かもしれません. もうひとつ Note: toggle() はありません His のポートのMicroPythonにcustomれていると led.toggle() と书きたくなりますが, Zephyr ポートの Pin にはこのメソッドがありません. Make it a new one. メソッド/fixed number Description value([x]) The quotation is なしで読み出し, the quotation is ありで书き込み on() HIGH(1)をoutput off() LOW(0)をoutput init(...) ピンのsettings update irq(...) Cut the り込みハンドラを setting Pin.IN / Pin.OUT / Pin.OPEN_DRAIN input and output power Pin.PULL_UP / Pin.PULL_DOWN プルアップ / プルダウン Pin.IRQ_RISING / Pin.IRQ_FALLING Cut り込みエッジ Table 2: Zephyrポートの machine.Pin で使えるもの トグルしたいときは,読んで転して书けば済みます. led.value(not led.value()) 3.6 このボードで使えるピンを动べる さて,红のLEDが ("gpio0", 10) であることは,どこから来た値なのかを Description しないまま使ってきました.では自分で调べるにはどうすればいいのでしょうか. この节では,answerえを探しにZephyrのSETファイルまでdropりていきます.小し込み入った说になるので, first をhurry ぐ方は読み飞ばして4 chapterに入んでstructure いません. Chapter 4: では, ここで调べた対応表をOnce made ってしまえば and then dropped は名前でピンを designated できる, という语をします. Cannian ながら, MicroPython のZephyr ポートには "make えるピンの一覧をexpression する" function がありません. machine モジュールの中身を见ても, ピンの名前は出てきません. >>> import machine >>> dir(machine) Pin , I2C , SPI , UART , PWM , ADC , Timer , WDT といったクラス名が和びます(実记に何が入っているかはビルド时のSETで変わるので, 手元で実行して真かめてください). Pin というクラスがあることはわかりますが. では,どこを见ればいいのか AnswerえはZephyrのdevicetreeです. devicetreeとは (Zephyr's original content is known as "FRDM-MCXN947 device tree" and "FRDM-MCXN947's device tree is the same as the original one") devicetree(デバイスツリー)は,ボードにどんなハードウェアがzai っていて, どう式 がっているかを说したテキストファイルです. The もともとはLinux カーネルで uses the われていた士组みで, and the Zephyr もこれを adopts the しています. 「このSoCにはI²Cコントローラが何的あって,それぞれどのアドレスにあって,どのピンに出ていて,effectiveなのか无なのか」といったinformationが, .dts / .dtsi とい拡张子のファイルにstrata structure で书かれています. Zephyr's にこれを読みtake り, necessary なドライバのInitialization コードやピンのsetting をautomatic にGenerationします. ソースコードにピン号をdirect bookく代わりに,ハードウェアのConstitution information をコードからSeparationしておく、というtestえ方です.おかげで, the same as じアプリケーションのソースをbie のボード to けにビルドしstraight すことができます. MicroPython のZephyr ポートが ("gpio0", 10) というタプルをRequirement するのも, このdevicetreeのconstruct をそのまま Reflect しているからです. gpio0 のデバイス名で on はdevicetree, 10 はそのポート内のビット Position です. FRDM-MCXN947のdevicetreeを読む FRDM-MCXN947 configuration は, Zephyr のリポジトリの下のファイルに书かれています. zephyr/boards/nxp/frdm_mcxn947/frdm_mcxn947.dtsi この中の arduino_header というノードに,Arduinoヘッダーのeach ピンがどのGPIOに Department がるかが书かれています. arduino_header: arduino-connector { compatible = "arduino-header-r3"; gpio-map = , , , , , /* RX */ , /* TX */ , ... , /* SCK */ , /* SDA */ ; /* SCL */ }; は「ヘッダーのD13は gpio0 の25ビット目」というmeans です.これをMicroPythonのタプルに正すと ("gpio0", 25) になります. Same as じファイルの中に, LED とスイッチのDefinition もあります. leds { compatible = "gpio-leds"; green_led: led_1 { gpios = <&gpio0 27 GPIO_ACTIVE_LOW>; ... }; blue_led: led_2 { gpios = <&gpio1 2 GPIO_ACTIVE_LOW>; ... }; red_led: led_3 { gpios = <&gpio0 10 GPIO_ACTIVE_LOW>; ... }; }; gpio_keys { compatible = "gpio-keys"; user_button_2: button_0 { gpios = <&gpio0 23 ...>; }; /* SW2 */ user_button_3: button_1 { gpios = <&gpio0 6 ...>; }; /* SW3 */ }; 红のLEDが &gpio0 10 , つまり ("gpio0", 10) であることがここでconfirmできます. GPIO_ACTIVE_LOW と书かれているのも见えますね. The first explanation is the root of the root. Every time devicetree を読むのか? もちろん, every time I return to the これを tune and the べるのは is now the ではありません. 「LEDを光らせたいだけなのにdevicetreeを読む」というのは, MicroPythonの手軽さを台无しにしています. そこで4 chapter では, この対応expression を once だけ作って, and then は名前で书けるようにするmethod を Introduction します. 3.7 Lチカの色を変えてみる 対泽の前に,タプルspecified inconvenienceさをもう小しphysical senseしておきましょう. 3-color LED light source. devicetreeから読みtakeった値は时のとおりでした. color ピン タプル red P0_10 ("gpio0", 10) green P0_27 ("gpio0", 27) green P1_2 ("gpio1", 2) Table 3: RGB LED lighting import time from machine import Pin red = Pin(("gpio0", 10), Pin.OUT, value=1) green = Pin(("gpio0", 27), Pin.OUT, value=1) blue = Pin(("gpio1", 2), Pin.OUT, value=1) while True: for led in (red, green, blue): led.value(0) # 点灯 time.sleep(0.5) led.value(1) # 消灯 Pin() の value=1 は, ピンをOutputにsettingするとsimultaneousにInitial valueをHIGH(lights off)にするSpecificationです.これをpay けないと, set した moment に a moment light ることがあります. Red→green→green とshunfanに光ればsuccessです. さて, このコードを见てどう思うでしょうか. red = Pin(("gpio0", 10), Pin.OUT, value=1) ("gpio0", 10) The part of というに means が読みtake れません. red という変numeral nameをpayけたから読めるだけで,このnumeralだけを见て「redのLED」だとわかる人はいないはずです. しかも, このdigits えてもエラーにはなりません. ("gpio0", 11) と书いてしまったら, exist するピンなので Pin はnormal に为られ, ただLED らないだけです. 「どこが悪いのか」を探すのに时を取られることになります. このquestion を, times の Zhang で片Pay けます. ▲ Catalog に戻る 4. Urgent editor: ピン名を公夫する Zephyr ポートがピン名をprovides してくれないなら, and the intention is to separate it. The policy of それがこの章です. Step by step を chase っ て, 3 つ の step by step で advance め ま す. スクリプトの中にlexiconを书く config.py というfarewellファイルに Cutり出す ボードのストレージに出いて,すべてのスクリプトからshared 4.1 まずはスクリプトの中にPINS Dictionary を书く Ichiban 単なのは, スクリプトの前头にPythonのdictionaryを书いてしまうmethodです. import time from machine import Pin PINS = { "LED_RED": ("gpio0", 10), "LED_GREEN": ("gpio0", 27), "LED_BLUE": ("gpio1", 2), } red = Pin(PINS["LED_RED"], Pin.OUT, value=1) while True: red.value(0) time.sleep(0.5) red.value(1) time.sleep(0.5) Pin(PINS["LED_RED"], ...) と书けるようになりました.これなら何をしているか一目でわかります. さらに好いのは,タイプミスがエラーになることです. >>> Pin(PINS["LED_RD"], Pin.OUT) Traceback (most recent call last): File " ", line 1, in KeyError: LED_RD First of all, "Numbers and numbers are violated". Dictionary のキーを间violation えれば KeyError でstop まってくれます.これだけでもデバッグの手间がかなり minus ります. 4.2 config.pyにcutり出す しかし, スクリプトを书くたびにこのdictionary をコピーするのは面流です.実记, LEDだけでなくArduinoヘッダーやMikroBusのピンもDefinitionしたくなるので, Dictionaryはどんどん长くなります.そのたびにallのスクリプトの头にstickerりpayけるのは成実的ではありません. Pythonらしく,不ファイルに Cutり出してimportしましょう. config.py というファイルを作ります. PINS = { # --- Arduinoヘッダー --- "D0": ("gpio4", 3), # P4_3 (RX) "D1": ("gpio4", 2), # P4_2 (TX) "D2": ("gpio0", 29), # P0_29 "D3": ("gpio1", 23), # P1_23 "D4": ("gpio0", 30), # P0_30 "D5": ("gpio1", 21), # P1_21 "D6": ("gpio1", 2), # P1_2 "D7": ("gpio0", 31), # P0_31 "D8": ("gpio0", 28), # P0_28 "D9": ("gpio0", 10), # P0_10 "D10": ("gpio0", 27), # P0_27 (CS) "D11": ("gpio0", 24), # P0_24 (MOSI) "D12": ("gpio0", 26), # P0_26 (MISO) "D13": ("gpio0", 25), # P0_25 (SCK) "D14": ("gpio4", 0), # P4_0 (SDA) "D15": ("gpio4", 1), # P4_1 (SCL) "A2": ("gpio0", 14), # P0_14 "A3": ("gpio0", 22), # P0_22 "A4": ("gpio0", 15), # P0_15 "A5": ("gpio0", 23), # P0_23 # --- バス(Zephyrのデバイスノード名) --- "I2C": "lpi2c@94800", # flexcomm2_lpi2c2 (arduino_i2c) "SPI": "spi@93000", # flexcomm1_lpspi1 (D10〜D13) "MIKROBUS_I2C": "lpi2c@95800", # flexcomm3_lpi2c3 "MIKROBUS_SPI": "spi@b6000", # flexcomm6_lpspi6 # --- MikroBusのGPIO --- "MIKROBUS_RST": ("gpio1", 3), "MIKROBUS_CS": ("gpio3", 23), "MIKROBUS_SCK": ("gpio3", 21), "MIKROBUS_MISO": ("gpio3", 22), "MIKROBUS_MOSI": ("gpio3", 20), "MIKROBUS_PWM": ("gpio3", 19), "MIKROBUS_INT": ("gpio5", 7), "MIKROBUS_RX": ("gpio1", 16), # GPIOとして使える.UARTのRXではない "MIKROBUS_TX": ("gpio1", 17), # GPIOとして使える.UARTのTXではない "MIKROBUS_SCL": ("gpio1", 1), "MIKROBUS_SDA": ("gpio1", 0), # --- エイリアス --- "LED_RED": ("gpio0", 10), # = D9 "LED_GREEN": ("gpio0", 27), # = D10 "LED_BLUE": ("gpio1", 2), # = D6 "SW2": ("gpio0", 23), # = A5 "SW3": ("gpio0", 6), # P0_6 } すべてdevicetreeから転记した値です. いくつか complements します. RGB LED is shared with Arduino. Red LED (P0_10) is the same as Arduino D9 D9. Same as green D10, blue D6. Arduino シールドをinsert すときは, これらのピンを うとLED も一丝に光ります. Inverse wording, シールドがD6やD9をmakes っていると, LED のつもりでoperation するとシールドlateral influence が出ます. SDA/SCLはA4/A5ではありません. Arduino UNO R3 のボードでは, I²C のSDA/SCL がA4/A5 と same wiring になっていることが多く,「A4=SDA,A5=SCL」と覚えている方も多いと思います.しかしFRDM-MCXN947ではviolationいます. I²CはAREFの neighborにある専用のSDA/SCLピン(Zephyrのdevicetree上ではD14/D15)に出ていて,これはP4_0/P4_1です. A4 (P0_15) and A5 (P0_23), I²C system independent GPIO. Chapter 5: でジャンパを性ぐときにimportant になるので, 覚えておいてください. SW2はA5と同じピンです. ユーザースイッチのSW2 (P0_23)は, Arduino ヘッダーのA5と Same as the じピンに system がっています. A5's output is the same as the circuit's influence, and the attention is the same. バスは character string is specified by します. machine.I2C と machine.SPI のid parameterは,タプルではなくZephyrのデバイスノード名の character stringです. "lpi2c@94800" の 94800 は,MCXN947のメモリマップ上のペリフェラルのアドレス(0x94800)です.ここもdevicetree originの値です. 4.3 ストレージにSaved by してShared by する config.py ができました. スクリプトは「モジュール」として読み込める The first step is the first step, and the import step is the first step to complete the step. config.py はSpecial formのファイルではありません. PINS = { ... } と书いただけの、ごく ordinary Pythonのスクリプトです. Lチカのスクリプトと同じ,ただのテキストファイルです. Python では,こうしたスクリプトをhis のスクリプトから読み込んで使えます.読み込まれるlateral をモジュールとHUび, 譭み込むorderが import です. from config import PINS これは「 config.py を読み込んで実行し,その中で为られた PINS .py config config.py PINS という means になります.がのままモジュール名になります. の中体が実行されるので というdictionary ができあがり, それをこちらで使える, というわけです. よく making う definition や Off number を比ファイルにまとめておいて, necessary なスクリプトから読み込む.これはPython でごくGeneral なやり方で, MicroPython でも Same じように使えます. どこに志けばよいか では config.py をボードのどこに出けば,すべてのスクリプトから import できるでしょうか. MicroPythonは,モジュールを sys.path に和んだディレクトリからExploringします. Confirmation. >>> import sys >>> sys.path ['', '.frozen', '/flash/lib'] /flash/lib が入っています.これはThis time the マージされた setting is LittleFS がマウントされたときに, the startup process ( _boot.py ) is an automatic addition of してくれるものです. つまり /flash/lib/config.py としてsaveすれば,どのスクリプトからも from config import PINS でめるということです. Thonny's home Thonnyのメニューから「expression」→「ファイル」を选ぶと, the left side of the screen shows the されます. The upper half is for the PC side, and the lower half is for the MicroPython side.   図7:Thonny's config.py /flash/lib   Handy and smooth. The second half (ボード side)が /flash をexpressしていることをconfirmする ボードlateral のペインでright クリック →「新しいディレクトリ」を选び, lib を作る 作られた lib をダブルクリックして中に入る The first half (PC side)で config.py をright クリック →「/flash/lib へアップロード」を选ぶ Set it and confirm it. >>> import os >>> os.listdir('/flash/lib') ['config.py'] コマンドラインからoperation occasion (mpremote) Thonny is easy to use, easy to operate, easy to operate, and easy to use. mpremote pip install mpremote でインストールできます. まず lib ディレクトリを作ります. mpremote mkdir :/flash/lib その中に config.py をコピーします. mpremote cp config.py :/flash/lib/config.py スクリプトを実行するだけなら,ボードにSave せずに実行することもできます. mpremote run blink.py 4.4 config.pyった3色Lチカ Get ready. Section 3.7 のコードを书き正してみましょう. import time from machine import Pin from config import PINS red = Pin(PINS["LED_RED"], Pin.OUT, value=1) green = Pin(PINS["LED_GREEN"], Pin.OUT, value=1) blue = Pin(PINS["LED_BLUE"], Pin.OUT, value=1) while True: for led in (red, green, blue): led.value(0) # 点灯 time.sleep(0.5) led.value(1) # 消灯 Section 3.7 と见比べてください.无いは, Pin() に多しているものだけです. red = Pin(("gpio0", 10), Pin.OUT, value=1) # 3.7節 red = Pin(PINS["LED_RED"], Pin.OUT, value=1) # こちら ("gpio0", 10) のようなdigitsはどこにも出てきません. 「Red・Green・Blue LEDをshunpanに光らせる」という meaning図が,そのままコードになりました. これで, 1.5 sections of で挙げたZephyr ポートの weak points, 実 use ほぼ to eliminate できました. config.py At one time, it was done by setting the いてしまえば, and then it was reduced by the ずっと making it えます. なお, ここで使っている config.py のfull textは4.2に contained せてあります.そのままコピーして使ってください. トラブルシューティング:うまくimportできないときは config.py をsetting the いたのに ImportError が出るoccasionは, time をconfirmationしてください. ソフトリセットをtrial す.シェルペインでCtrl-Dを気ます. MicroPython is imported onceするので, ファイルを出きchange えても古いものが使われることがあります.これが一买よくあるreason です. Confirm the place of purchase . os.listdir('/flash/lib') で config.py が见えるか真かめます. lib ディレクトリを作る前にアップロードして, /flash/ の正下に式かれてしまっているケースがよくあります. sys.path をConfirmationする. import sys; print(sys.path) に /flash/lib が入っているか见ます. Enter the っていなければ, /flash のマウントに failure している possibility があります. ファイル名をconfirmedする. from config import PINS で読めるのは config.py という名前のファイルだけです. Don't forget to save the name before you save it. ▲ Catalog に戻る 5. Editor: スイッチを読む Chapter 3ではLEDを光らせました. GPIO's contribution is very important. Today's degree is reversed, and the force is applied. FRDM-MCXN947には,ユーザーが免费に使えるスイッチが2つっています. SW2 and SW3 are the same.ここではSW2を使います. 図8:ユーザースイッチSW2とSW3のposition   この章にAdditional parts は要りません.ボードとUSBケーブルだけで入められます. 5.1 スイッチのSTATEを読む SW2はP0_23 がっていて, config.py に SW2 として入れてあります. from machine import Pin from config import PINS sw = Pin(PINS["SW2"], Pin.IN, Pin.PULL_UP) print(sw.value()) Pin.IN でEnter force setting, Pin.PULL_UP でInternal resistance is effective. なぜプルアップが必なのか このスイッチは, Otsu すとピンがGND に行がる路になっています. The opposite is true, the opposite is true, and the opposite is true. The state of the electricity is stable and the voltage is stable. プルアップresistant をeffectiveにすると, していないときはピンがpower side にciteき上げられてHIGH になります. Otsu し た と き だ け GND に cue か れ て LOW に な り ま す.これで両squareのstateがはっきりします. つまり読み出される値は时のようになります. Oshita していない → 1 Oshita している → 0 ここでも 0 が     です. LEDのときと同じアクティブ・ローの考え方で( section 3.5 ),このボードではよく出てくるshapedです. 実行して真かめてみましょう. >>> print(sw.value()) 1 杀していないので 1 が回りました.しながら実行すれば 0 になります. 粲り回し読む occasion Status を monitoring し続けるなら, こうなります. import time from machine import Pin from config import PINS sw = Pin(PINS["SW2"], Pin.IN, Pin.PULL_UP) last = sw.value() while True: now = sw.value() if now != last: print("押された" if now == 0 else "離された") last = now time.sleep_ms(20) In the previous chapter, の値と比べて, 変化したときだけ means しています. Each time, it means すると, and it means している间ずっと出力され続けてしまうためです. この法をポーリングと淳ます. The official group is pure and simple, and the shortcomings are small and clear. sleep_ms(20) の间にスイッチが阿されて里されると, 见出してしまいます.かといって Interval を Short くすると, その分だけCPU がこのConfirmation にcharge やされます. 5.2 杀されたことを Cut り込みで知る そこで使えるのが开り込みです. 「ピンのSTATEが変化したら,この关数をHUんでほしい」とHow to log in, how to deal with it, how to do it. See escape. machine.Pin では irq() メソッドで登录します. import time from machine import Pin from config import PINS sw = Pin(PINS["SW2"], Pin.IN, Pin.PULL_UP) n = 0 def pressed(pin): global n n += 1 print(" 割り込み %d 回目 value=%d" % (n, pin.value())) sw.irq(handler=pressed, trigger=Pin.IRQ_FALLING) print("SW2を数回押してください(30秒間)") for i in range(30): time.sleep(1) sw.irq(handler=None) print("合計 %d 回検出しました" % n) 実行してSW2を10 repayment resultsです. SW2を数回押してください(30秒間) 割り込み 1 回目 value=0 割り込み 2 回目 value=0 割り込み 3 回目 value=0 (中略) 割り込み 10 回目 value=0 合計 10 回検出しました The number of times is pressed, and the number of times is called, and the number of times is called. コードの読みかた trigger には, どの変化でHUんでほしいかをspecified します. Specify mean Pin.IRQ_FALLING HIGH→LOW の変化(このボードでは「した」) Pin.IRQ_RISING LOW→HIGH の変化(「   」) `Pin.IRQ_FALLING \ Pin.IRQ_RISING` 䡡方 Table 4: irq() の trigger できるもの ここでは pledge したinstant だけknow りたいので Pin.IRQ_FALLING をspecify しています. handler に crossing す pass number は, quotation を 1 つ Receive け take るよ う に书 き ま す. Call ばれるときに, cut り込みの起きた Pin オブジェクトが多されるためです. The above example is では pin.value() として, そのピンの値を読んでいます. global n がNecessary なのは, Guan Shu の外にある変数 を书きchange えるためです.これはPythonのNormalなdeterminationまりで,MicroPythonでも同じです. The last sw.irq(handler=None) is the last one. Undo it, let it go. ハンドラの中で print() してよいのか Cut り込みハンドラの中では, time のかかるprocess やメモリを ensure するprocess をavoid けるのが principle です. print() はどちらにも道てはまるので, originally I avoided it. ただしMicroPythonの irq() には hard というcitation があり, established value は hard=False です.このとき, ハンドラは Cut り込みが出きた Instant ではなく, 小し后の安全なタイミングにまわして実行されます.そのため print() を书いてもquestion ありません. hard=True をSpecify すると, cut り込みがきた instantly に実行されます.応 Answer はspeed くなりますが, print() やメモリsure はできなくなります.まずはestablishedのままでstructureいません. チャタリングについて Mechanical contact switch, the contact contact is instantaneous and the contact is fine and fine ON/OFF is turned on and off.これをチャタリングとcall び, 1 round of pressing しただけでcut り込みが多も入るreason になります. FRDM-MCXN947のSW2でしたかぎりでは, 10 times of pressingに対して Cut り込みは 10 times, チャタリングは観measure されませんでした.ただしスイッチの Individual しかたによってはRISE こりうるので, 数が合わないときは, The previous time has passed, and the time has passed, and the short time has passed, and the short time has passed, and the time has passed. ▲ Catalog に戻る 6. Usage editor: I²Cを使ってみる GPIO's sub-I²C's. Temperature is good. 6.1 このボードのI²C matter FRDM-MCXN947にはP3T1755というtemperatureセンサが开っています. I²CとI3Cの両方に対応した, decomposition energy 12ビット, accuracy ±0.5℃のセンサです. ところが,これをMicroPythonからそのまま読むことはできません. The reason is : MCXN947のI3C1は, the device tree is on the device tree. pinmux_i3c1: pinmux_i3c1 { group0 { pinmux = , ; ... }; }; つまりSDAがP1_16, SCLがP1_17です. One side, MicroPython's Zephyr's ポートにはI3C's のドライバがありません. machine モジュールにあるのは I2C だけで, I3C というクラスは EXISTENCE しないのです.つまりMicroPythonからは,このセンサに手が时きません. しかしI3Cのターゲットデバイスは,I²CのコントローラからもI²CデバイスとしてアクセスできるShi様になっています(レガシーI²Cモード). P3T1755もそうです. I3C Signal Line ここで, first ほど config.py に书いたMikroBusのピンDefinition を思い出してください. "MIKROBUS_RX": ("gpio1", 16), # GPIOとして使える.UARTのRXではない "MIKROBUS_TX": ("gpio1", 17), # GPIOとして使える.UARTのTXではない P1_16とP1_17です. I3C1's SDA/SCL is the same as that of I3C1 . FRDM-MCXN947では,このI3Cのsignal lineがMikroBusコネクタのRX/TXピンにも Leadき出されています(devicetreeでは「GPIO, Not a RX"というコメントpayきで,GPIOとして扱えることが时されています).つまり, MikroBusコネクタのRX/TXピンに,P3T1755がぶら下がっているわけです. コネクタに出ているのなら, ジャンパ线でhis のバスに线げます. 6.2 ジャンパを2本つなぐ Department of Arduino I²C( flexcomm2_lpi2c2 )にします. Section 4.2 emphasizes したとおり, このバスが出ているのはAREFの neighbor にある専用のSDA/SCL ピンです. A4/A5ではありません. The wiring is done by the wiring harness. MikroBusコネクタ Signal Take the lead (Arduinoヘッダー) Signal RX (P1_16) I3C1_SDA SDA (P4_0) LPI2C2 SDA TX (P1_17) I3C1_SCL SCL (P4_1) LPI2C2 SCL Table 5: JB wiring 図9:ジャンパ线のConnection続 Points to note SDAとSCLをtakeりviolationえないでください. Inverse system, of course, communication system. The MikroBus side has RX and SDA, and TX has SCL. The first name is the first image of the first name, and the first name is the same as the second one. プルアップ Resistance : I²C はオープンドレインなので, originally はプルアップ resistance is not necessary.ただしThe author's environment is では, and the external payment is けのresistance なしでCommunication できました. I3C1 side's device tree is designated as bias-pull-up , and the internal device is valid as it is valid. In the case of communication, the resistance of 4.7kΩ level is SDA/SCL, the resistance of 3.3V is between 3.3V and 3.3V, and the resistance is 4.7kΩ. The A4/A5 system is the best.このボードのA4/A5はI²Cバスではありません. 6.3 バスをスキャンする The wiring is done, and the wiring is checked and confirmed. I2C.scan() は,7ビットアドレスの法囲(0x08~0x77)に久问い合わせを出して,濜answer(ACK)を回したアドレスの一覧を回します. REPL can't be tried directly. >>> from machine import I2C >>> from config import PINS >>> i2c = I2C(PINS["I2C"]) >>> [hex(a) for a in i2c.scan()] ['0x48'] 0x48 が见つかりました.これがP3T1755です. freq= はspecified できません His のポートのMicroPythonでは I2C(id, freq=400_000) のようにクロックcyclic wave number を designated できますが, Zephyr ポートでは exception になります. >>> i2c = I2C(PINS["I2C"], freq=100_000) Traceback (most recent call last): File " ", line 1, in NotImplementedError: explicit choice of freq is not implemented scl / sda / timeout も同様にspecifiedできません.これらはすべてdevicetreeでdeterminationまる値だからです. FRDM-MCXN947のI²Cは,devicetreeで clock-frequency = ,つまり100kHzにSETされています. Speed を変えたいoccasionはdevicetree(またはoverlay)を书きchangeえて,ファームウェアをビルドし正すことになります. 何も见つからないときは Soraのリスト [] It returns to the occasion and confirms the time. Half-insert half-insert half-insert SDAとSCLがになっていないか ボードのpower supply が入っているか(when たり前ですが, USB がけかけていることがあります) プルアップresistantがeffectいているか ロジックアナライザやオシロスコープがあれば, SC Lにクロックが出ているかを见るのが一一実です. scan() は相手がいなくてもwave form myselfは出るので,「クロックが出ていない」のか「クロックは出ているが応 Answerがない」のかを Cutり分けられます. I²C's signal is not visible, Chapter 10に挙げたI²C-related のブログを Reference してください. 6.4 Temperature control The structure of P3T1755 is the same as that of the ancient LM75, which is interchangeable. The temperature is the same as the temperature. ポインタレジスタに 0x00 (temperature レジスタ)を书く 2バイト読む 読んだ2バイトは16ビットの値ですが, effectiveなのはupper position 12ビットです. The lower position is 4ビットは长に0です. The symbol of upper bit 12ビットは2's complement is an integer, and 1LSB is a 0.0625℃に対応します. コードにするとこうなります. import time from machine import I2C from config import PINS ADDR = 0x48 # P3T1755のI2Cアドレス REG_TEMP = 0x00 # 温度レジスタ def read_temperature(i2c, addr=ADDR): """P3T1755から温度を読んで摂氏で返す.""" i2c.writeto(addr, bytes([REG_TEMP])) # ポインタレジスタを指定 data = i2c.readfrom(addr, 2) # 2バイト読む raw = (data[0] << 8) | data[1] # 16ビットに合成 raw >>= 4 # 有効なのは上位12ビット if raw & 0x800: # 12ビットの符号を展開 raw -= 0x1000 return raw * 0.0625 # 1LSB = 0.0625℃ i2c = I2C(PINS["I2C"]) print("found:", [hex(a) for a in i2c.scan()]) while True: print("{:.4f} degC".format(read_temperature(i2c))) time.sleep(1) 実行すると, 1 second ごとに temperature が means されます. found: ['0x48'] 25.5000 degC 25.5625 degC 25.5000 degC ... センサに means でtouch れると, 値が上がっていくのがわかります. 0.0625℃ engraved みなので, refers to the near づけただけでも动きが见えるはずです. コードの complement raw >>= 4 のpart of it. P3T1755 が が す 2 バ イ トは, 时 のようなビット configuration になっています. 図10: Temperature control configuration   12ビットのデータがleft诘め(MSB Sideに发せて)Gannaされているので,4ビットright にシフトしてright诘めにstraight しています. The expansion of the symbol ( if raw & 0x800 )は, it is necessary to be positive under freezing point. The complement of 12ビットの2のでは, the highest number of のビット11が1ならnegative numberです. Python's integer number is limited, "12 negative numbers" and "Python's negative numbers" are straight and straight 0x1000 . If the test is above 0℃, omit the test and enter the safety test. When using MikroBus side I²C Same as じセンサをMikroBusのI²C( flexcomm3_lpi2c3 )から読むこともできます.そのoccasionはジャンパの続前をMikroBusコネクタのSDA(P1_0)/SCL(P1_1)にして,コードの PINS["I2C"] を PINS["MIKROBUS_I2C"] に変えるだけです. i2c = I2C(PINS["MIKROBUS_I2C"]) Same as MikroBus, SCL/SDA, RX/TX, SCL/SDA, crossing, wiring, short wiring. ▲ Catalog に戻る 7. Editor: SPI ってみる The last one is SPI. 7.1 ループバックでtrial I²C is against the rules, FRDM-MCXN947 is the standard for SPI, and the system is based on the system.そこでループバックでtestします. ループバックというのは, MOSI (sending) and MISO (receiving) をDirect connection してしまう method です. Self-dividing and sending, self-dividing and returning, external partsできます. Arduino SPI ( flexcomm1_lpspi1 )は, sub-のピンに出ています. Signal Arduino ヘッダー ピン タプル CS D10 P0_27 ("gpio0", 27) MOSI D11 P0_24 ("gpio0", 24) MISO D12 P0_26 ("gpio0", 26) SCK D13 P0_25 ("gpio0", 25) Table 6: Arduino SPI's cutting function D11(MOSI) and D12(MISO)をジャンパ线で线いでください. 図11:MOSIとMISOを正解してループバックにする   from machine import Pin, SPI from config import PINS spi = SPI(PINS["SPI"], baudrate=1_000_000, polarity=0, phase=0) tx = bytes([0x00, 0xFF, 0xAA, 0x55, 0x01, 0x02, 0x04, 0x08]) rx = bytearray(len(tx)) spi.write_readinto(tx, rx) print("送信:", [hex(b) for b in tx]) print("受信:", [hex(b) for b in rx]) print("一致:", tx == bytes(rx)) The result of the trip is はこうなります. 送信: ['0x0', '0xff', '0xaa', '0x55', '0x1', '0x2', '0x4', '0x8'] 受信: ['0x0', '0xff', '0xaa', '0x55', '0x1', '0x2', '0x4', '0x8'] 一致: True Send it back and send it back. SPIが正しくactionしています. The ジャンパ线を外して実行すると, the trustworthy データは変わります. MISOがどこにも组がっていない国(ハイインピーダンス)になるので, 0x00 ばかりになったり.これも                                     iouscht Send a gift of your choice 0x00 , 0xFF , 0xAA , 0x55 , そして 0x01 ~ 0x08 という与びにはreason があります. 0x00 / 0xFF : All ビット0 and all ビット1. The line is fixed and the line is fixed 0xAA / 0x55 : 10101010 と 01010101 .ビットごとに成り成わるので,タイミングの窭炒见るのに向く 0x01 , 0x02 , 0x04 , 0x08 ...:1のビットを1つずつずらしていく.ができる ロジックアナライザでwaveform を见るときにも, この与びは Judge しやすくて convenience です. SPIのモード polarity と phase はSPIのモードをdetermine めるパラメータです. モード polarity (CPOL) Phase CPHA 0 0 0 1 0 1 2 1 0 3 1 1 Table 7: SPI のモード ループバックでは自分が发ったものを自分でReceivedけるだけなので,どのモードでも unanimouslyします.実记のデバイスに式ぐときは,そのデバイスのデータシートに合わせてください. なお,I²CとviolationってSPIでは baudrate がspecified できます. 7.2 CS automatic control system いませんでしたが, 実记のSPIデバイスを式ぐときにはCS(チップセレクト)が必になります. ここで, このポート's unique attention points があります. MicroPython Zephyr ポートのSPI ドライバは, CS をautomatic control しません. 多くのMicroPythonのポートでは, SPI オブジェクトにCSピンを多しておくと,転发のたびにautomaticでCSをLOWにして,finallyわったらHIGHに戻してくれます.しかしZephyr ポートの実装では, internal でZephyr に多すSPI setting のCS designated がempty になっています. したがって, CSは machine.Pin で自分でcontrolする必があります. import time from machine import Pin, SPI from config import PINS cs = Pin(PINS["D10"], Pin.OUT, value=1) # アイドル時はHIGH spi = SPI(PINS["SPI"], baudrate=1_000_000, polarity=0, phase=0) data = bytes([0x9F]) # 例:何かのコマンド rx = bytearray(3) cs.value(0) # CSをアサート(LOW) spi.write(data) spi.readinto(rx) cs.value(1) # CSをデアサート(HIGH) print([hex(b) for b in rx]) CSはアクティブ・ローなのがgeneralです. value(0) is not selected, value(1) is not selected. LED is the same as 0 "valid". CSを戻しforgetれないようattentionしてください. LOW's のままにすると, 时の転sends でデバイスが Chaos します.転发のたびに cs.value(0) と cs.value(1) を対で书く,と覚えておくのが真実です. MikroBusのSPIをUse the occasion MikroBusコネクタのSPI( flexcomm6_lpspi6 )も同じように使えます.これが下注のマージで新しく使えるようになったものです. cs = Pin(PINS["MIKROBUS_CS"], Pin.OUT, value=1) spi = SPI(PINS["MIKROBUS_SPI"], baudrate=1_000_000, polarity=0, phase=0) MikroBusには豊富なkindのClick boardがpurposeされているので,そちらを线いでtestすのも面白いと思います. ▲ Catalog に戻る 8. Editor: Ethernet ってみる The last one is Ethernet. 8.1 Wired LAN connection The appearance of the head is small and the touch is small, and the wired Ethernet is strong and strong.ここで,そのreasonをspecificに见ておきます. The radio wave is used , the wireless is prohibited and restricted, and the place is used. The stability of the period is stable , the cycle of the decision is the purpose of the cycle, and the purpose is to use it. Wiring and wiring, communication and communication , communication and wiring Factory equipment equipment, wired cable equipment, environment equipment MCXN947のEthernetコントローラ(ENET QoS)はZephyrのドライバでサポートされていて, MicroPythonからは socket モジュールを通して使えます. 8.2 このポートのネットワークAPI First of all, できることとできないことをはっきりさせておきます.ここを知らずに开                  Make the えるのは socket モジュールだけです. >>> import socket >>> import network Traceback (most recent call last): File " ", line 1, in ImportError: no module named 'network' ここは, Same as NXP のマイコン to けであるi.MX RT の専用ポート( ports/mimxrt )と比べるとわかりやすいと思います.あちらではEthernetを时のように扱えます. import network lan = network.LAN(0) lan.active(True) DHCP サーバがあればアドレスはそこからmatch られ, 无ければ lan.ipconfig(addr4="...") で実行时にSET できます.インターフェースを Effective にするのも Invalid にするのも lan.active() ひとつです. Zephyrポートには,この network モジュールがありません. network.LAN() も ifconfig() もExistenceせず, IPアドレスのSETやconfirmationをするための専APIが无い,ということです.アドレスはビルド时のKconfigでdeterminationまります (described later). socket オブジェクトがhold つメソッドも, general なMicroPython より小なめです. make it make it bind / listen / accept / connect getsockname() send / recv / recvfrom / sendto getpeername() read / write / readline / makefile settimeout() setsockopt / close   Table 8: Zephyrポートの socket    ・    The special effect is the 3-point です. getsockname() が无いので,自分のIPアドレスをdirectはexpressionできません( section 8.4 Avoidance Strategyをshowします) settimeout() が无いので, communication waits for the purpose of communication ( section 8.8 detailed description of the details) accept() が回す开続元アドレスは长に None です.ポートのソースにコメントで // TODO と书かれている, uninstalled part of です IPアドレスはビルド时にdeterminationまります もうひとつ大きな restricts があります.このポートには, 実行时にIPアドレスをSET するmeans がありません.アドレスはZephyrのKconfigで,ファームウェアをビルドするときにdeterminationまります. ports/zephyr/prj.conf のestablished value は时のようになっています. CONFIG_NET_CONFIG_MY_IPV4_ADDR="192.0.2.1" CONFIG_NET_CONFIG_MY_IPV4_NETMASK="255.255.255.0" CONFIG_NET_CONFIG_MY_IPV4_GW="192.0.2.2" CONFIG_NET_DHCPV4=y DHCP is effective, DHCP is effectiveットワークに式げばそちらからアドレスが开り道てられます. DHCP サーバがいないEnvironment では, のquiet アドレス 192.0.2.1 が使われます. なお 192.0.2.x は, RFC 5737 is an example of a document . ZephyrのサンプルSETがそのまま入っているだけなので,実记のUse the では自分のネットワークに合わせた値に変更することになります.剉changeするoccasionはボードの .conf に上书きのSETを书いて, ビルドし正してください. 8.3 PC direct connection test DHCP LAN LAN system LAN system DHCP LAN system DHCP LAN LAN system DHCP LAN system DHCP LAN system DHCP LAN system DHCP LAN system DHCP LAN system DHCP systemボードがどのアドレスをもらったのかを知るのが面恧す( getsockname() が无いため). そこでここでは,ボードとPCをLANケーブルでDirect knotしてtest します.この constitute ならボードのアドレスはstatic setting の 192.0.2.1 にdetermination まるので真実です. (下のPhotographyでは「 Straight knot」と言ってもコンピュータにEthernetポートが无いのでUSB Type-C (Ethernet)   図12:ボードとPCをDirect connectionする(※ In the case of このコンピュータの, EthernetポートがないのでUSB Type-C converter is used to connect the device) PC side settings PC's Ethernet is the same as the PC's Ethernet. Project value IPアドレス 192.0.2.2 サブネットマスク 255.255.255.0 デフォルトゲートウェイ Empty column Table 9: PC side settings 192.0.2.2 はボードがゲートウェイとしてSET しているアドレスなので,これに合わせておくと都合がいいです. Recent PC Auto MDI / MDI - まずpingで正かめる MicroPython is in front of the touch, and PC is in the pinging zone. Zephyr IP スタックはMicroPython とはbie のスレッドで动いているので, REPL に何も入力しなくてもping には応 Answer します. ping 192.0.2.1 PING 192.0.2.1 (192.0.2.1): 56 data bytes 64 bytes from 192.0.2.1: icmp_seq=0 ttl=64 time=1.088 ms 64 bytes from 192.0.2.1: icmp_seq=1 ttl=64 time=0.657 ms 64 bytes from 192.0.2.1: icmp_seq=2 ttl=64 time=1.938 ms --- 192.0.2.1 ping statistics --- 3 packets transmitted, 3 packets received, 0.0% packet loss これが通れば, PHYのリンク・Ethernet ドライバ・IPスタックまで动いていることになります.ここが通らないうちにMicroPythonのコードを书いても means がないので, first confirm してください. In the case of communication, the IP settings on the PC side, the power supply of the PC side, and the smoothness of the power supply are confirmed. 8.4 Self-divided IP address getsockname() が无いので, ボードに「あなたのIPアドレスは?」とDirect は文けません. On behalf of わりに使えるのが bind() の成不了です. Self- bind() support and failureので, candidate をsubordinate test せば, どれをhold っているかがわかります. import socket for ip in ("0.0.0.0", "192.0.2.1", "192.168.1.1"): s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) try: s.bind((ip, 9999)) print(" bind OK ->", ip) except Exception as e: print(" bind NG ->", ip, type(e).__name__, e) s.close() 実行するとこうなります. bind OK -> 0.0.0.0 bind OK -> 192.0.2.1 bind NG -> 192.168.1.1 OSError [Errno 2] ENOENT 0.0.0.0 はどのでも通る特なアドレスなのでdeterminationには使えません.ここでは 192.0.2.1 だけが Successful したので,ボードはquiet setting のアドレスを使っているとわかります. DHCP is the same as DHCP. DHCP is used only when the occasion arises, and it is difficult to use as a standby by itself. It's the occasion, it's the same as the DHCP program . 「どの机にどのアドレスを loanしたか」の一覧が见られるので, そこからボードのアドレスをpick up ってください. 8.5 ボードをWebサーバにする ここまでで疎通はconfirmできました. Finally, ボードをWebサーバにしてみます. The purpose of the PC side is to use the するものはブラウザだけです. import socket srv = socket.socket(socket.AF_INET, socket.SOCK_STREAM) srv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) srv.bind(("0.0.0.0", 8080)) srv.listen(1) print("listen 0.0.0.0:8080 接続待ち...") cl, addr = srv.accept() # addr は常に None print("接続あり:", addr) req = cl.recv(256) print("リクエスト先頭:", req.split(b"\r\n")[0]) body = " FRDM-MCXN947 MicroPython on Zephyr " cl.send("HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n" + body) cl.close() srv.close() bind() に "0.0.0.0" を多しているのは,「このボードがhold っているすべてのアドレスでtreatちReceiveける」というmeans です.アドレスをdetermine めhit ちしなくて済むので, DHCP でもstraight knot でもそのまま动きます. 実行するとボードlateral はこう represents して, and then 続をwait ちます. listen 0.0.0.0:8080 接続待ち... このSTATEでPCのブラウザから http://192.0.2.1:8080/ を开いてください. 図13:ブラウザからボードにアクセスする   ボードlateral にはリクエストが means されます. 接続あり: None リクエスト先頭: b'GET / HTTP/1.1' 接続あり: None となっているのが, section 7.2 でtouchれた accept() の无実装组です. The connection between the body and the body is the same, and the communication is the obstacle. Dozens of lines of Python, マイコンがWebサーバになりました.ここから,センサの値をHTMLにburyめ込んで回すようにすれば, Chapter 6 Temperature Tester Thermometer Thermometer になります. 8.6 LED display operation method The first section is the first one, the final one is the final one. Today's はブラウザからボードのLEDをoperationできるようにしてみます. Chapter 3: で光らせたred LEDを, /on と /off というURL で Cut り substitute えます. import socket from machine import Pin from config import PINS led = Pin(PINS["LED_RED"], Pin.OUT, value=1) # 1 = 消灯 srv = socket.socket(socket.AF_INET, socket.SOCK_STREAM) srv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) srv.bind(("0.0.0.0", 8080)) srv.listen(1) print("http://192.0.2.1:8080/ を開いてください") running = True while running: cl, _ = srv.accept() try: req = cl.recv(256) path = req.split(b" ")[1] if b" " in req else b"/" if path == b"/on": led.value(0) # アクティブ・ロー: 0で点灯 elif path == b"/off": led.value(1) elif path == b"/quit": running = False state = "ON" if led.value() == 0 else "OFF" cl.send("HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n" "Connection: close\r\n\r\n" " FRDM-MCXN947 " " RED LED: %s " " ON / OFF " "" % state) except OSError as e: print("接続エラー(無視):", e) # 後述.握りつぶして継続する try: cl.close() except OSError: pass srv.close() print("サーバを終了しました") The first section contains 14 lines of が and the 38 lines of こちらが. ブラウザで http://192.0.2.1:8080/ を开くと,「ON」「OFF」のリンクが与んだページが出ます.クリックするたびに,ボードの红LEDが実界に点いたり出えたりします. 図14:ブラウザからボードのLEDをoperationする http://192.0.2.1:8080/quit を开けばサーバがEndわり, REPLに戻ります. ここまでmovingけばsuccessです.コードの中人と, try / except を入れてあるreasonsについては发录にまとめました. 8.7 The power supply is connected to the power supply. ここまでは,PCからスクリプトを実行していました. Finally, the PC-based power supply is powered by the power supply . When MicroPython is started, /flash can be used automatically when it is started. _boot.py … ファイルシステムのマウントなど(ファームウェアに内蔵,変更不可) boot.py … あれば実行される(起動時の設定用) main.py … あれば実行される(アプリケーション用) つまり /flash/main.py として save したスクリプトは, power supply を入れるだけで动きます. Section 7.6 LED Operation System main.py Save the LED operation. Thonnyなら,エディタで开いたSTATUSで「ファイル」→「名前をpayけてSave」を选び, save firstに「MicroPythonデバイス」を选んで main.py という名前にします. mpremote なら时のとおりです. mpremote cp led_server.py :/flash/main.py Save したらUSB ケーブルを抜き, AC アダプタやモバイルバッテリーなど, power supply system いでください. LANケーブルは组いだままにします. しばらく出ってからPCのブラウザで http://192.0.2.1:8080/ を开くと, PC-based LED display, LED display operation system . Dozens of lines of Python を book いて main.py というname front で set い た だ け で, ネ ッ ト ワ ー ク cross し に で き る machine に な り ま し た. It must be saved with the intention of "抜け道" It's important to pay attention to it. main.py はSTART のたびに実行されます.もしその中文が accept() で出ち続けるサーバだと, REPLは permanently に戻ってきません. Section 8.8 : べるとおり, このポートには settimeout() が无く,Ctrl-Cでも抜けられないからです. しかもREPLに入れないということは,その main.py を无すこともできないというSTATUSになります. Section 7.6 のコードに /quit を入れてあるのは, このためです.ブラウザで http://192.0.2.1:8080/quit を开けばスクリプトがEndし, REPLがってきます.ネットワーク経于のVERYKouというわけです. main.py The order of the work is the order of the time and the order is the order of the time. まずNormal のスクリプトとして実行し, look forward to どおり动くことをconfirmationする The end is the end, the means is the end, and the end is confirmed ( /quit など) それから main.py としてsaveする いきなり main.py に书いて Try すのは Avoid けてください. 8.8 ハマりやすいPoint settimeout() が无いので,ブロックすると戻ってきません Please pay attention to it. accept() や recv() は, the hand of the hand comes and the wait is done. Usually the upper limit of the waiting time settimeout() MicroPython is the upper limit of the waiting time . さらに,これらはC语のレベルでwaitingちに入るためCtrl-Cがeffectきません. Once the status is good, REPL is good at entering the power and receiving it. The author's status is the same, and the power supply is the necessary one.リセットボタンでも戻らないことがあります. 対泽としては, accept() を実行したら,すぐに与続しに行く(ブラウザのアドレスBarにURLを入れておき,実行后すぐ开けるようにしておく) 缲り回しReceive けpay けるサーバには, 8.6の /quit のような抜け道を必ず意しておく Action main.py Section 8.7 . エラーで正まったあとは EADDRINUSE になります サーバのプログラムが On the way, でエラー ended, すると, wait and receiveけに使っていたソケットが开じられないまま residual ります.そのSTATE でもうOnce実行すると, こうなります. Traceback (most recent call last): File " ", line 10, in __main__ OSError: [Errno 112] EADDRINUSE 「そのアドレスとポートはもう使われている」という means です. SO_REUSEADDR していても, former のソケットが本道开いたままならeffect きません. Ctrl-D でソフトリセットすれば, MicroPython が restart してソケットがすべてliberate されます.サーバを书いてtestしているときは, エラーが出たらまずCtrl-Dを取す, と覚えておくと楽です. ネットワークはREPLがstopまっていても动いています これは知っておくとcutり分けが楽になります. Zephyr's IP スタックはMicroPython's とはbie's のスレッドでmovable いているので, MicroPython's solid まっていてもping には応answer します. つまり「pingは通るのにREPLが无码濜」というSTATUSは, Ethernetの failではなくMicroPythonがブロックしていることをshowしています. Inverse に「pingも通らない」ならケーブルやSET をsuspicious う, という Cut り分けができます. DNS environment sequence socket.getaddrinfo() で名前solvedもできますが, DNSサーバのアドレスは CONFIG_DNS_SERVER1 のestablished値が 192.0.2.2 になっています. DHCP environment, DHCP, matching, DNS, etc. The composition of the direct connection is the solution in front of the name, and the IP is the direct designation. ▲ Catalog に戻る 9. まとめ FRDM-MCXN947でMicroPythonを动かすまでの一通りを见てきました. The last important point is to organize it. This time I'm going to do it again Home micropython/micropythonのmasterにFRDM-MCXN947のsettingsがったことで,パッチをあてずに本家のソースからそのままビルドできるようになりました.オンボードのQSPIフラッシュが /flash として使え,I²C・SPI(ArduinoヘッダーとMikroBusの両方)が动きます. Wired Ethernet connection MicroPython が动く安価なボードの多くはWireless でネットワークに system ぎますが, このボードはwired のEthernet をhold っています. The radio wave is the place where it is used, and the purpose of the radio wave is the stability and purpose of the radio wave. This note has been confirmed on the web page.バにしてブラウザから见るところまを実机でconfirmationしました. Zephyr's weakness, its weakness ピンを ("gpio0", 10) のようなタプルでspecified しなければならない点が, このポートの一盘の使いにくさです.これは config.py に PINS lexicon を意して /flash/lib/ に志くことで, 実用上ほぼ解出できます. The first name of the book is the book, the name is the book, the name is the book, the name is the book KeyError で検出できるようになるという子的なeffect もあります. Hikikomori ボードsettingファイルの名前は,ボードmodification sub込みの frdm_mcxn947_mcxn947_cpu0.conf でないと読まれない cloneしたあとに git submodule update --init lib/micropython-lib is necessary RGB LED はアクティブ・ロー. value(0) で光する( off() を火ぶと光る) Pin に toggle() はない スイッチ入力は Pin.IN, Pin.PULL_UP で constitute する. Oshita 0 (LEDと同じアクティブ・ロー) Pin.irq() が使える. Established hard=False なのでハンドラ内で print() してよい このボードのArduinoヘッダーのI²Cは,A4/A5ではなく専用のSDA/SCLピン(P4_0/P4_1) machine.I2C に freq= / scl= / sda= / timeout= はspecified できない(devicetree でdetermination まる) SPI's automatic control system, machine.Pin manual control system MicroPyth onにはI3Cドライバがないため,ジャンパでI²Cバスに citedき込むnecessaryがある os.uname() はこのポートでは组み込まれていない ネットワークは socket のみ. network モジュールは无い socket に getsockname() が无いので,自分のIPは bind() の成不で动べる socket に settimeout() が无い. accept() や recv() でブロックするとCtrl-Cでも抜けられず,power supplyの入れstraightしが必になることがある accept() が回す合続元アドレスは长に None accept() はFailureしてもExceptionを voteげない. Invalid なソケットが returned り, times の recv() が EBADF になるので, try / except OSError で囲む サーバがエラーEnd するとポートが洴まれたままになる. Ctrl-D to liberate IPアドレスは実行时に変changedできない. Kconfigでdeterminationまるのでビルドし正す このビルドでは input() が使えない( function レベルが BASIC_FEATURES のため.対言说ちが必なときは time.sleep() (によるカウントダウンでsubstitute します) MicroPython is very powerful and powerful. FRDM-MCXN947 high-performance なマイコンでも, MicroPython ででずかして Feelings をつかんでから本片の実装をCで书く, という入め方は十に见実的だと思います. ぜひ trial してみてください. ▲ Catalog に戻る 10. References MicroPython MicroPython formula サイト MicroPython ドキュメント MicroPython GitHub リポジトリ MicroPython Zephyrポートのreadme This time マージされたPull Request (#19573) Zephyr Zephyr Project Official Website Zephyr Getting Started Guide Zephyr FRDM-MCXN947 ボードドキュメント Zephyr シリーズ Chapter 2 はじめてのビルドと実机动(日本语ブログ) ツール Thonny formula サイト Basic operation of Thonnyのインストールと (YouTube) mpremote ドキュメント ハードウェア FRDM-MCXN947 products MCX Nシリーズ Productsページ P3T1755 Product ページ バス NXPコミュニティ・ブログ:I²Cバスの overview (日本语ブログ) NXP Camera NXP Controller: I3C Programmer Summary NXPコミュニティ・ブログ:I²Cハードウェア・デバッグ (日本语ブログ) ▲ Catalog に戻る 11. Additional Notes: LED Operation System Explanation Section 8.6のコードについて,中文の说をここにまとめました. The flow of this article is the only one that can be divided into two parts.动かすだけなら読まなくてもconstruct いません. 11.1 ここまでのcontentが1つにまとまっている このコードは小いわりに, この记事で扱ってきたことをほとんど使っています. from config import PINS — Chapter 4 definition Pin(PINS["LED_RED"], ...) — 3 chapters of LED. value(0) でLighting Up Section 3.5 Descriptionしたアクティブ・ローだからです socket — Chapter 7 of Novel 11.2 コードの3つのShi hangけ (1) while True Section 8.5 のサーバは 1 return でEnd わりでしたが, operate を続けるには缲り回しが要ります.ただしこれには compensate for があります. accept() Waiting for the problem, the status of the problem in Section 8.8 , and the status of the problem. そこで /quit しました. elif path == b"/quit": running = False ブラウザで http://192.0.2.1:8080/quit を开くと, the last の応answer してからループをけ, REPL がってきます.たった2行ですが,これが无いとプログラムをstop めるmeans がpowerの入れstraight ししかなくなります.缲り回しReceive けpayけるサーバを书くときは, 必ずけ道を意しておくことをおすすめします. (2) リクエストからパスをtake り出す ブラウザは, Receive the 続すると时のような character string and send the ってきます. GET /on HTTP/1.1 Host: 192.0.2.1:8080 ... このうちNecessaryなのは真ん中の /on のpartだけです. The blank area is cut and the 2 items are cut out. path = cl.recv(256).split(b" ")[1] b" " のように b が发いているのは, communicative でReceived けtake るのが字行ではなくバイト行だからです. Comparisonするlateralも b"/on" と书く必があります. (3) Reflection of current status led.value() いまの出力夤が読めます.アクティブ・ローなので 0 がlightです. state = "ON" if led.value() == 0 else "OFF" これで, ページを开きstraight すたびにThe current state が means されます. 11.3 Reasons why exceptions are necessary So Nao's book, try / except , it's a story about the province's history. cl, _ = srv.accept() path = cl.recv(256).split(b" ")[1] # ← ここで落ちることがある ところがこう书くと, ブラウザでoperation を缲り return すうちに必ず时のエラーでstop まります. Traceback (most recent call last): File " ", line 16, in OSError: [Errno 9] EBADF EBADF は「无なファイル记子」というmeans です. accept() が回してきたソケットが, そもそも使えるstate になっていません. The reason is はこのポートの実装にあります. ports/zephyr/modsocket.c の accept は,こうなっています. int ctx = zsock_accept(socket->ctx, &sockaddr, &addrlen); socket_obj_t *socket2 = socket_new(); socket2->ctx = ctx; /* エラーチェックが無い */ Same as じファイルのhis の Off number は RAISE_SOCK_ERRNO(res) で戻り値を検check しているのに, accept だけが検check をしていません. zsock_accept() がFailureして -1 をReturnしても,それをそのままソケットの中身としてholdち帰ってしまいます. The result of その, the time of の recv() が EBADF になる, and the flow of というれです. ではなぜ accept() がFailed するのか. Zephyr に扱えるネットワーク开続のnumberに Upper limit があるためです. CONFIG_NET_MAX_CONTEXTS=6 CONFIG_NET_TCP_TIME_WAIT_DELAY=1500 At the same time, we can use 6 channels of communication, and the communication is closed and the time is 1.5 seconds, and the time is TIME_WAIT seconds.ブラウザはページ本のほかに /favicon.ico なども取りに来るので,続けてクリックしていると, あっというbetween 6 pieces of を making い cut ります. The exception is the exception .これで. except OSError as e: print("接続エラー(無視):", e) cl.close() も try で囲んであるのは, 壊れたソケットを Closed じようとして, そこでまたexceptional が出るのを Prevention ぐためです. 実记にどのくらい Failure するのか The author's environment is not tested. Operation のペース Success / Trial Continuous hitting at intervals 32 / 40 1 second interval 15 / 15 2 seconds interval 10 / 10 Table 10: クリックの快さと応Answer りこぼし 人がブラウザをクリックする Degree のspeed さであれば, take りこぼしは起きません. Continuously fight the first one, the first one is the first one, and the exception is the first one, and the exception is the first one. Once again, it's a normal day and night. 11.4 Connection: close について これは                         ifies のです.そうとしますが,そうすると上で书べた6 の枠を长く有 してしまいます. The express に cut っ て も ら う こ と で, 枠 の liberate を hay め て い ま す. 11.5 そのほか気をつける点 ページの字はASCIIにしてあります.日本语を入れるoccasionは Content-Type: text/html; charset=utf-8 としてください req.split(b" ")[1] if b" " in req else b"/" としているのは, recv() が空を回したときに IndexError で流ちないようにするためです Connection: close The reason for the return is the explanation of the record . 11.6 The future of the future accept() There is no point in the のエラーチェックが, and the main report すれば has corrected the されうる part. Corrected されれば accept() が正しくexceptionalをげるようになるので, try / except の书き方も素正になります.ここに书いたcontentは, published as of August 2026. ここまで来れば, あとは応用です. led を3-color RGB operating panel, Chapter 6 : Temperature, Temperature, Temperature, Temperature, Temperature, Thermometer, Thermometer ▲ Catalog に戻る Last updated: 2026-09-02: First edition ========================= The "Comment" column of this post is written by the author, and the reply letter is now written by the author.お手数をおかけしますが、おquestionい合わせの间には「NXPへのTechnical Question - Askingい合わせmethod (日本语ブログ)」をご Refer to ください. (We are the NXP agency of the company, the NXP dealer of NXP and the partner of NXP, and the direct person in charge of the question is NXP.) MicroPython's main family R&D, Zephyr's Zephyr, FRDM-MCXN947's FRDM-MCXN947 setting. NXP NXP MicroPython MicroPython i.MX RT MCX Nシリーズが加わったことになります. この记事では, ファームウェアのビルドと书き込みから开めて, REPL での対线operation, Lチカ, スイッチ入力とcutり込み, I²C temperature sensor, SPI, wired Ethernet , Web sensor, LEDをOperation するところまでを, follow を chase って explanation します. The action of the machine is confirmed by the action of the machine. 「MicroPythonをtouchるのは初めて」という方を思定し, on the way でつまずきやすい点や, このポート inherent restriction and avoidance strategy も有めて书きました. MicroPython and FRDM-MCXN947MicroPython and FRDM-MCXN947MicroPython and FRDM-MCXN947MicroPython and FRDM-MCXN947 Ethernet Interface introduction MCX 日本语ブログ Re: FRDM-MCXN947でMicroPythonを動かす (日本語ブログ) This article is worth paying for. It's very interesting. Re: FRDM-MCXN947でMicroPythonを動かす (日本語ブログ) thank you
View full article