Multi Source Translation Content

取消
显示结果 
显示  仅  | 搜索替代 
您的意思是: 

Multi Source Translation Content

讨论

排序依据:
NXP i.MX93 EVKのNPU温度と使用率を取得する方法 私はi.MX93 EVKを使っており、Ethos-UのNPU温度と稼働率(負荷)を実行時に監視したいのですが、このデータをどうやって取得できますか? 目的は、AIモデルの推論中にハードウェアパラメータを監視することです。 i.MX8MPlusで以下のパラメータを監視できます。i.MX93でも同様のことを実現したいです。 8Mプラス RAM=$(free -m | awk '/Mem:/ {print $3}') CPU_LOAD=$(vmstat 1 2 | tail -1 | awk '{print 100 - $15}') CPU_TEMP=$(awk '{print $1/1000}' /sys/class/thermal/thermal_zone0/temp 2>/dev/null || echo "N/A") GPU_TEMP=$(awk '{print $1/1000}' /sys/class/thermal/thermal_zone1/temp 2>/dev/null || echo "${CPU_TEMP}") GPU_LOAD=$(cat /sys/kernel/debug/gc/load 2>/dev/null | awk '/load/ {gsub("%","",$3); if (max=="" || $3>max) max=$3} END {if (max!="") print max "%"; else print "N/A"}') i.MX93 RAM=$(free -m | awk '/Mem:/ {print $3}') CPU_LOAD=$(vmstat 1 2 | tail -1 | awk '{print 100 - $15}') CPU_TEMP=$(awk '{print $1/1000}' /sys/class/thermal/thermal_zone0/temp) i.MX93 NPU(ethos-u)のGPU_LOADとGPU_TEMPをどうやって監視できますか? Linux Re: How to get NPU Temperature and utilization for NXP i.MX93 EVK こんにちは、@sonal-acldigital i.MX 8M Plusも i.MX 93も、NPU温度をリアルタイムで監視する方法を提供していません。 - imx8MP、thermal_zone0はCPUの温度を表し、thermal_zone1はSoCの温度を表します。 - imx93、thermal_zone0はCPUの温度を表します。 - NPU、 nputopのようなツールは存在しません。 パフォーマンスチューニングに関する情報については、セクション7.1.2を参照してください。「ハードウェアアクセラレータのプロファイリング」、 MLユーザーガイドに収録。 B.R Re: How to get NPU Temperature and utilization for NXP i.MX93 EVK @pengyong_zhang i.MX 8M Plusとi.MX 93の熱ゾーンについてご説明いただきありがとうございます。以下の点を明確にしていただけますか? i.MX8MPLUS 1. GPU温度: 個別のGPU温度を読み取る専用のシステムパス(/sys/class/thermal/thermal/thermal_zoneX/temp)はありますか?それともソックサーマルゾーン(thermal_zone1)だけでカバーされているのでしょうか? 2. GPU負荷: /sys/kernel/debug/gc/loadを読み込むことがGPU負荷の確認の標準的な方法ですか?それともMLユーザーガイドのセクション7.1.2に詳述されている手順も必要ですか? i.MX93: NPUの負荷と温度を監視するネイティブツール(nputopなど)がないため、次の点について質問させてください。推論の実行をNPUにオフロードした場合とCPUのみで実行した場合のCPU負荷の減少を測定することで、相対的なNPU使用率を導き出すことは妥当でしょうか? もしこの方法が推奨されていない場合、推論実行中のNPU活動を推定するために使える代替のドライバーノードやパフォーマンスカウンターはありますか? Re: How to get NPU Temperature and utilization for NXP i.MX93 EVK こんにちは、@sonal-acldigital 返信が遅くなり申し訳ありません。最近、ひどいウイルス性の風邪にかかり、しばらくの間高熱が続きました。今日やっと熱が下がった。 1.GPU温度を読み取る専用の経路はありません。 2. はい、/sys/kernel/debug/gc/loadによるGPU負荷監視が現在の方法です。 IMX93: NPU使用率は、プロファイリングを用いてご自身で計算する必要があります。 B.R
查看全文
I.MX95 LVDS 时钟输出无法更改 大家好, 问题1: 我正在内核 lf-6.12y 中开发单端口 LVDS 显示功能。我在 driver/gpu/drm/panel/panel-simple.c 中添加了自己的面板配置,但是当我测量时钟引脚时,时钟频率始终在 150Mhz 左右。但其他信号都正常。 但是,在 lf-6.18y 中,时钟可以正确输出,并且在双端口模式下,两个版本的时钟切换也都可以。这是已知问题还是我的操作失误?由于某些原因,我希望能在lf-6.12y版本中解决这个问题。 以下是我的设置 panel-simple.c: static const struct display_timing lt9211_test_timing = { 像素时钟= { 35916000, 35916000, 35916000 }, .hactive= { 280, 280, 280 }, .hfront_porch= { 40, 40, 40, }, .hback_porch= { 60, 60, 60 }, .hsync_len= { 30, 30, 30 }, .vactive= { 1424, 1424, 1424 }, .vfront_porch= { 15, 15, 15 }, .vback_porch= { 17, 17, 17}, .vsync_len= { 4, 4, 4 }, .flags= DISPLAY_FLAGS_DE_HIGH, }; static const struct panel_desc lt9211_test = { 时间= &lt9211_test_timing, .bpc= 8, .num_timings= 1, 。尺寸= { 。宽度= 292, 。高度= 111, }, .bus_format= MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA, .bus_flags= DRM_BUS_FLAG_DE_HIGH, .连接器类型= DRM_MODE_CONNECTOR_LVDS, }; 设备树中的 lvds 配置 &{/}{ lvds1_panel { //兼容 = "3ascreen,sa123hwv-l51"; 兼容 = "lt9211_test"; 背光 = <&lvds_backlight>; 状态 = "正常"; 港口 { panel_in: 端点 { 远程端点 = <&lvds1_out>; }; }; }; Q2: 在某些情况下,同一硬件中的数据通道和时钟之间的 LVDS 公共电压将无法对齐。或者某些信号缺失,例如 LVDS1 D3P 有信号但 D3N 没有信号。你知道这是为什么吗?某些程序会导致这种情况吗? Q3: 是否有任何配置可以改变LVDS时钟相位? 谢谢! Re: I.MX95 LVDS clock output can not be changed 问题1:这很可能是LF-6.12Y LVDS时钟驱动程序的一个已知限制/错误,而不是你的panel-simple.c文件的问题。时机把握失误。在单端口LVDS中,驱动/时钟路径很可能强制或四舍五入到大约148.5/150。MHz。由于 lf-6.18y 可以正常工作,实际的解决方法是将 lf-6.18y 的 LVDS/LDB 时钟更改向后移植到 lf-6.12y,或者修补 6.12y LVDS 驱动程序/PLL 时钟表,以允许使用您的 35.916 MHz 像素时钟。 git diff lf-6.12.y..lf-6.18.y -- \ drivers/gpu/drm/bridge/imx/imx95-ldb.c drivers/phy/freescale/phy-fsl-imx8mp-lvds.c drivers/clk/imx/clk-imx95-blk-ctl.c \ arch/arm64/boot/dts/freescale/imx95.dtsi \ arch/arm64/boot/dts/freescale/imx95-*-lvds* Q2:如果 LVDS 对中的一侧缺失,例如 D3P 有信号但 D3N 没有信号,这通常不是面板时序造成的。查看: LVDS通道启用:LVDS0/LVDS1不匹配 fsl,数据宽度 / fsl,数据映射 PHY 使能 连接器或PCB开路/短路 焊接问题 终止/探测方法 LVDS 输出引脚可能损坏 软件可能会导致错误的通道/线路/数据宽度设置,但差分对的一侧缺失强烈表明存在硬件、焊盘、布线、端接或测量问题。 Q3:对于 i.MX8MP LVDS,没有常规的设备树配置来改变 LVDS 时钟相位。改为修复时钟频率/时序/PHY设置。 Re: I.MX95 LVDS clock output can not be changed 太感谢了。 lvds补丁太有用了。
查看全文
MRF13750H AWR MODEL Hello, I am trying to import the MRF13750H transistor model into Cadence AWR Microwave Office using the official design files provided on your website. After downloading both the design kit and the transistor model an error is generated when attempting to open the model. I have attached a screenshot of the error message. Luis_V_0-1789581238483.pngLuis_V_0-1789581238483.pngLuis_V_0-1789581238483.png I have already contacted technical support at cadence. Their team attempted to download and open the model as well, and they confirmed that they encountered the exact same issue. Could you please verify these files and let me know how to resolve this? Best, Luis V. RF Re: MRF13750H AWR MODEL Hello Luis_V Good day! The error is due to compatibility issues. The model you are trying to install is quite old and was designed for earlier versions of AWR Design Environment. Currently, there are no plans to update it for newer versions of the software. If you need to use this model, the most practical solution is to install an older version of AWR, such as one from around 2015 (for example, AWR v11 or v12), which is compatible with this model. This should allow you to work without encountering the GetIAwrUserIO DLL error. We apologize for any inconvenience this may cause. I hope this information has helped you, please let me know if you need help with anything else. Have a great day and best of luck. Re: MRF13750H AWR MODEL Hello Rafa, I am reaching out to Cadence to see if they can provide an older version of AWR. In the meantime, could you connect me with the engineer who designed the MRF13750H-915MHz Board or someone who can help me gather some numbers? I have this product from NXP and we need to use it. Additionally, you mentioned earlier that you could open ADS/AWR on your end to view the tee-discontinuities, mitered bends, open-end effects, etc. Would you be able to send me a screenshot of the window so I can check the microstrip dimensions and characteristics? I would also appreciate if you could run a load-pull analysis to find the source and load impedance values while I wait on Cadence. Best, Luis Villanueva Re: MRF13750H AWR MODEL Hello Luis_V Good day! Since NXP has decided to ramp down operations in the RF area (for the moment), many of our colleagues from that department have left the company, meaning there are fewer people available. So, please let me know what questions you have, and I will try to answer them; if I can't, I will escalate the matter to get support from an AE, though I cannot share anyone's contact details with you. Thanks for your understanding. Have a great day and best of luck.
查看全文
RT1051: ENET IEEE1588 Timer Clock source Hi, In the RT1050 reference manual, I find the following: mastupristi_0-1789736651417.pngmastupristi_0-1789736651417.png I would like to know what the clock sources for the IEEE1588 timer can be. For example, can I choose a root clock derived from AUDIO_PLL? Which registers control the clock source of the IEEE1588 timer? best regards Max i.MXRT 105x
查看全文
RT1xxx ENET:写入 ATCOR 以更改循环值时,校正计数器是否会重置? 您好, 我想知道在写入 ATCOR 时,校正计数器(在 ENET 外设中)是否会重置。 或者,也许只有当 ATCOR 中的值发生变化时才会重置? 顺祝商祺! 最大值 i.MX RT102x i.MX RT105x
查看全文
RT1051:ENET IEEE1588 定时器时钟源 您好, 在 RT1050 参考 手册 中 , 我 发现了 以下内容 : mastupristi_0-1789736651417.pngmastupristi_0-1789736651417.png 我想知道IEEE1588定时器的时钟源有哪些。例如,我可以选择从 AUDIO_PLL 派生的根时钟吗? 哪些寄存器控制 IEEE1588 定时器的时钟源? 顺祝商祺! 最大值 i.MX RT105x
查看全文
How to get NPU Temperature and utilization for NXP i.MX93 EVK I am using i.MX93 EVK and want to monitor the Ethos-U NPU temperature & utilization(load) at runtime how can I get this data ? The agenda is to monitor the HW-parameters during the inference of AI-models. I could monitor the below parameters using i.MX8MPlus I want to achieve the similar for i.MX93. 8MPlus RAM=$(free -m | awk '/Mem:/ {print $3}') CPU_LOAD=$(vmstat 1 2 | tail -1 | awk '{print 100 - $15}') CPU_TEMP=$(awk '{print $1/1000}' /sys/class/thermal/thermal_zone0/temp 2>/dev/null || echo "N/A") GPU_TEMP=$(awk '{print $1/1000}' /sys/class/thermal/thermal_zone1/temp 2>/dev/null || echo "${CPU_TEMP}") GPU_LOAD=$(cat /sys/kernel/debug/gc/load 2>/dev/null | awk '/load/ {gsub("%","",$3); if (max=="" || $3>max) max=$3} END {if (max!="") print max "%"; else print "N/A"}') I.mx93 RAM=$(free -m | awk '/Mem:/ {print $3}') CPU_LOAD=$(vmstat 1 2 | tail -1 | awk '{print 100 - $15}') CPU_TEMP=$(awk '{print $1/1000}' /sys/class/thermal/thermal_zone0/temp) How can I monitor the GPU_LOAD & GPU_TEMP for i.MX93 npu(ethos-u) ? Linux Re: How to get NPU Temperature and utilization for NXP i.MX93 EVK Hi @sonal-acldigital  Neither the i.MX 8M Plus nor the i.MX 93 offers a method to monitor NPU temperature in real time. - imx8MP, thermal_zone0 represents the cpu-thermal temperature ,thermal_zone1 represents the soc-thermal temperature. - imx93, thermal_zone0 represents the cpu-thermal temperature. - NPU, There is no such tool like nputop. For information on performance tuning, please refer to Section 7.1.2, "Profiling for Hardware Accelerators," in the ML User Guide. B.R Re: How to get NPU Temperature and utilization for NXP i.MX93 EVK @pengyong_zhang Thanks for clarifying the thermal zones for the i.MX 8M Plus and i.MX 93. Could you please clarify the following: i.MX8MPLUS 1. GPU Temperature: Is there a dedicated system path (like /sys/class/thermal/thermal_zoneX/temp) to read individual GPU temperatures, or is it covered solely under the soc-thermal zone (thermal_zone1)? 2. GPU Load: Is reading /sys/kernel/debug/gc/load the standard method for checking GPU load, or is the process detailed in Section 7.1.2 of the ML User Guide required for this as well? i.MX93: Since there is no native tool (like nputop) to monitor NPU load and temperature, we would like to ask: Is it valid to derive relative NPU utilization by measuring the reduction in CPU load when offloading inference execution to the NPU vs. running on the CPU alone? If this method isn't recommended, is there any alternative driver node or performance counter we can use to estimate NPU activity during an inference run? Re: How to get NPU Temperature and utilization for NXP i.MX93 EVK Hi @sonal-acldigital  Sorry for the late reply. I recently had a severe viral cold and had a high fever for a while. The fever just broke today. 1. There is no dedicated path to read the GPU temperature. 2. Yes, GPU load monitoring via /sys/kernel/debug/gc/load is the current method. IMX93: You need to calculate the NPU utilization yourself using profiling. B.R
查看全文
S32K3 上的 eTPU 曲柄、凸轮、喷射和点火装置 你好 我需要执行驱动程序,以根据曲柄和凸轮信号相位启动喷油和点火装置。 我需要了解实施该驱动程序的最佳解决方案是什么。 我的疑问是 1) AN4907SW.zip 提供的 API 是否与 S32K3xx 中的 eTPU 兼容? 2)如果不是,那么将此 API 用于 S32K3xx 是一个好的解决方案,还是使用 ConfigTool 才是最佳解决方案? S32K3xx 有关于此应用的示例吗? 敬请期待,弗朗切斯科。 Re: eTPU crank, cam, injections and Ignitions on S32K3 你好@francescovico 将数据从大端转换为小端序涉及通过根据数据类型大小调整位移和掩码来反转字节顺序。 GCC 提供了内置函数来简化这个过程,例如:uint32_t __builtin_bswap32 (uint32_t x)。你可以在 GCC 文档中找到更多细节:7.2.3 字节交换内置函数 Re: eTPU crank, cam, injections and Ignitions on S32K3 你好@VaneB、 如果我理解得不错,汽车功能(CRANK、SPARK......)是为大位微控制器设计的。 要在 S32K364(小二进制)上使用带有汽车功能的 eTPU,我需要下载一个功能集,选择 .NET 和 .NET: francescovico_0-1761136257258.pngfrancescovico_0-1761136257258.png 并更改功能: uint32_t *fs_memcpy32(uint32_t *dest,uint32_t *source,uint32_t size); void fs_memset32(uint32_t *start,uint32_t value,int32_t size); 交换每个 32 位的值,以读取/写入小端代码和参数,是这样吗? 敬请期待,弗朗切斯科。 Re: eTPU crank, cam, injections and Ignitions on S32K3 你好@francescovico 用于电气化应用的 S32K39/37/36 微控制器包括 eTPU。但是,目前没有适用于这些设备的与 MPC5634 的 AN4907 相似的专用文档或演示。 也就是说,AN4907 文档、演示和微码适用于 S32K39/37/36 系列,但请注意,这些设备使用小端架构。因此,您需要修改内存访问 API。 您可以参考 CodeWarrior eTPU 功能选择器 中与电机控制相关的模块,该功能 选择器 已更新为 little-endian。 BR、VaneB Re: eTPU crank, cam, injections and Ignitions on S32K3 感谢您指出这一点! 这是个endianity转换问题。因此,缺齿掩模的配置不正确,每转 350 度,每周期 700 度。 现在,原帖中的演示程序已经修复。 Re: eTPU crank, cam, injections and Ignitions on S32K3 你好@MilanBrejl、 现在,我正在尝试使用 Fuel Cyl 1 etpu 驱动程序。 驱动程序似乎使用 s24AngleNormalEnd 作为"的起始角度" ,并在 s24AngleStop 停止注入。 u24InjectionTime 的持续时间永远不会被遵守。 有可能吗? 附件中有一个 .rar 文件该文件包含"燃料缸 1" 的 picoscope 采集信息,其中喷油器参数为: Etpu_Fuel_Ip_ConfigType fuel_1_config = { .s24AngleNormalEnd= DEG2TCR2(-180), .s24AngleStop= DEG2TCR2(-360), .s24AngleOffsetRecalc= DEG2TCR2(-30), .u24InjectionTime= USEC2TCR1(1200), .u24CompensationTime= USEC2TCR1(0), .u24InjectionTimeMinimum= USEC2TCR1(0), .u24OffTimeMinimum= USEC2TCR1(0), .eGenerationDisable= etpu_fuel_generation_allowed }; 在 picoscope 采集器中,可以看到注入开始点正好是 180°,注入停止点是 360°,注入持续时间为 30 毫秒(应为 1.2 毫秒)。 敬请期待,弗朗切斯科。 Re: eTPU crank, cam, injections and Ignitions on S32K3 你好@MilanBrejl、 现在,我正在尝试使用 Fuel Cyl 1 etpu 驱动程序。 驱动程序似乎使用s24AngleNormalEnd 作为"的起始角度" ,并在 s24AngleStop 停止所有注入。 u24InjectionTime 的持续时间永远不会被遵守。 有可能吗? 附件中有一个 .rar 文件文件,其中包含喷油器参数所在的"燃油 1 缸" 的 picoscope 采集结果: Etpu_Fuel_Ip_ConfigType fuel_1_config = { .s24AngleNormalEnd= DEG2TCR2(-180), .s24AngleStop= DEG2TCR2(-360), .s24AngleOffsetRecalc= DEG2TCR2(-30), .u24InjectionTime= USEC2TCR1(1200), .u24CompensationTime= USEC2TCR1(0), .u24InjectionTimeMinimum= USEC2TCR1(0), .u24OffTimeMinimum= USEC2TCR1(0), .eGenerationDisable= etpu_fuel_generation_allowed }; 在 picoscope 采集器中,可以看到注入开始点正好是 180°,注入停止点是 360°,注入持续时间为 30 毫秒(应为 1.2 毫秒)。 敬请期待,弗朗切斯科。 Re: eTPU crank, cam, injections and Ignitions on S32K3 你好@MilanBrejl、 你说得没错,s24AngleOffsetRecalc 必须是正数,但要把它放进去: s24AngleOffsetRecalc = DEG2TCR2(30) 结果还是一样(......)。 我使用的 S32K364 有 2 个 ETPU(A 和 B),共 16 个通道。 在 ETPUA 上使用燃料驱动程序,驱动程序工作正常,但我需要使用 ETPUB 通道 0。 我需要使用 STAC 寄存器将 TCR1 和 TCR2 从 ETPUA 共享到 ETPUB。 可能是 STAC 寄存器没有正确初始化? 敬请期待,弗朗切斯科。 Re: eTPU crank, cam, injections and Ignitions on S32K3 你好@francescovico, 这是如何配置 STAC_ENG1 和 STAC_ENG2 寄存器,以便从 eTPU1 到 eTPU2 共享 TCR1 和 TCR2: MilanBrejl_0-1770199430269.pngMilanBrejl_0-1770199430269.png 如果有帮助,请告诉我。 致: Milan Re: eTPU crank, cam, injections and Ignitions on S32K3 你好@MilanBrejl、 我的注册表与您的建议完全相同: ETPU_A_B_REGISTER.pngETPU_A_B_REGISTER.png 但问题依然存在。 在所附的皮镜采集中,您可以看到 ETPU A 产生的火花为蓝色,ETPU B 产生的火花为红色。 两个火花的端角都是 180 度,停留时间都是 8000 秒。 敬请期待,弗朗切斯科。   Re: eTPU crank, cam, injections and Ignitions on S32K3 你好,@francescovico、 我在我的网站上复制了你的问题,并找到了根本原因。在两个 eTPU 引擎之间共享 TCR1/TCR2 时间/角度总线是不够的。火花和燃油功能根据发动机的实际转速进行时间到角度的转换。它使用 TRR(跳动速率寄存器)。该寄存器是角度时钟逻辑的一部分,由运行在 eTPU A 上的 Crank eTPU 功能维护。然后,使用 eTPU B TRR 对 eTPU B 进行时间到角度的变换会返回错误的结果。 这是最基本的问题,我可能从未见过有人同时在两个 eTPU 引擎上运行引擎控制,因此这个问题一直没有得到解决。尤其是在新的 S32K3 设备仅限于 16+16 个通道的情况下,这一点变得很重要。感谢您提出这个用例,也感谢您的耐心。 所附的演示程序以之前的程序(在本主题中)为基础,并增加了以下改动: 火花 2 通道从 eTPU 引擎 A 移至 eTPU 引擎 B MilanBrejl_0-1770672522362.pngMilanBrejl_0-1770672522362.png 相应更新通道掩码 MilanBrejl_1-1770672675064.pngMilanBrejl_1-1770672675064.png 通道链接需要支持两个引擎的使用(使用宏 ETPU_IP_CHANNEL_TO_LINK) MilanBrejl_2-1770672729220.pngMilanBrejl_2-1770672729220.png 引脚配置已更新,中断配置已更新 现在是 Crank eTPU FW 的新功能: 更新 eTPU FW 映像。曲柄功能可在两个发动机上运行,并更新另一个 eTPU 发动机的 TRR 值。 这项新功能需要在曲柄配置中设置一个新参数 MilanBrejl_4-1770673143063.pngMilanBrejl_4-1770673143063.png 其中 MilanBrejl_3-1770673103441.pngMilanBrejl_3-1770673103441.png 希望对您有所帮助。 致: Milan Re: eTPU crank, cam, injections and Ignitions on S32K3 你好@MilanBrejl、 现在它工作得很好。 非常感谢你们的支持! 敬请期待,弗朗切斯科。 Re: eTPU crank, cam, injections and Ignitions on S32K3 您好,我也在研究k396的板子,也想将etpu用于曲轴凸轮轴和喷油,我们可以交流一下嘛 Re: eTPU crank, cam, injections and Ignitions on S32K3 嗨@MilanBrejl 我目前正在开发基于S32K396芯片的V12 ECU项目。 第一个原型我将使用 lqfp176 封装,很高兴看到这个项目也是用这种封装编写的。我想请问一下,是否有办法为 crank_instance 添加更多链接通道? Etpu_Crank_Ip_InstanceType 曲柄实例= { .u8ChanNum = ETPU_CRANK_CHAN ,​ .u8OtherEngChanNum = ETPU_CRANK_OTHER_ENG_CHAN ,​ . ePriority = ETPU_PRIORITY_HIGH , . ePolarity = ETPU_CRANK_IP_POLARITY_FALLING , .u8TeethTillGap = TEETH_TILL_GAP ,​ .u8TeethInGap = TEETH_IN_GAP ,​ .u8TeethPerCycle = TEETH_PER_CYCLE ,​ . u24Tcr2TicksPerTooth = TCR2_TICKS_PER_TOOTH , .u24Tcr2TicksPerAddTooth = 0 ,​ .eLogToothPeriods = ETPU_CRANK_IP_LOG_TOOTH_PERIODS_ON ,​ .u32LinkCam = ( ( ETPU_IP_CHANNEL_TO_LINK ( ETPU_CAM_CHAN ) << 0 ) + ( ETPU_IP_CHANNEL_TO_LINK ( ETPU_CAM_CHAN ) << 8 ) + ( ETPU_IP_CHANNEL_TO_LINK ( ETPU_CAM_CHAN ) << 16 ) + ( ETPU_IP_CHANNEL_TO_LINK ( ETPU_CAM_CHAN ) << 24 ) ) .u32Link1 = ( ( ETPU_IP_CHANNEL_TO_LINK ( ETPU_SPARK_1_CHAN ) << 0 ) + ( ETPU_IP_CHANNEL_TO_LINK ( ETPU_SPARK_2_CHAN ) << 8 ) + ( ETPU_IP_CHANNEL_TO_LINK ( ETPU_SPARK_3_CHAN ) << 16 ) + ( ETPU_IP_CHANNEL_TO_LINK ( ETPU_SPARK_4_CHAN ) << 24 )) , .u32Link2 = ( ( ETPU_IP_CHANNEL_TO_LINK ( ETPU_FUEL_1_CHAN ) << 0 ) + ( ETPU_IP_CHANNEL_TO_LINK ( ETPU_FUEL_2_CHAN ) << 8 ) + ( ETPU_IP_CHANNEL_TO_LINK ( ETPU_FUEL_3_CHAN ) << 16 ) + ( ETPU_IP_CHANNEL_TO_LINK ( ETPU_FUEL_4_CHAN ) << 24 )) , .u32Link3 = ( ( ETPU_IP_CHANNEL_TO_LINK ( ETPU_KNOCK_1_CHAN ) << 0 ) + ( ETPU_IP_CHANNEL_TO_LINK ( ETPU_KNOCK_2_CHAN ) << 8 ) + ( ETPU_IP_CHANNEL_TO_LINK ( ETPU_INJ_BANK_1_CHAN ) << 16 ) + ( ETPU_IP_CHANNEL_TO_LINK ( ETPU_INJ_BANK_2_CHAN ) << 24 )) , .u32Link4 = ( ( ETPU_IP_CHANNEL_TO_LINK ( ETPU_INJ_1_CHAN ) << 0 ) + ( ETPU_IP_CHANNEL_TO_LINK ( ETPU_INJ_2_CHAN ) << 8 ) + ( ETPU_IP_CHANNEL_TO_LINK ( ETPU_INJ_3_CHAN ) << 16 ) + ( ETPU_IP_CHANNEL_TO_LINK ( ETPU_INJ_4_CHAN ) << 24 ) ) .pCpba = NULL_PTR ,​ . pCpbaToothPeriodLog = NULL_PTR } ; 我想使用 eTPU 发动机 A 来实现 12 缸 DI、12 缸点火和曲轴、右侧进气凸轮轴、右侧排气凸轮轴,使用 eTPU 发动机 B 来实现 12 缸 PI 喷射和左侧凸轮轴。 或者 eTPU 发动机 A 适用于 6DI、6Ignition、6PI、Knock、RH CAMx2,eTPU 发动机 B 适用于 6DI、6Ignition、6PI、Knock、LH CAMx2。 但为此我还需要另外两个链接条目。我还没算上我可能还需要的其他东西呢。我需要WMI,也需要Nitro。我知道这是个大工程,但我真的非常感谢大家的帮助。 我是 eTPU 编程新手,对整个 NXP 生态系统也不熟悉。 感谢您的解答。 理查德
查看全文
如何获取 NXP i.MX93 EVK 的 NPU 温度和利用率 我正在使用 i.MX93 EVK,想要监控 Ethos-U NPU 在运行时的温度和利用率(负载),请问如何获取这些数据? 本次议程旨在监测人工智能模型推理过程中的硬件参数。 我可以使用 i.MX8MPlus 监测以下参数,我想在 i.MX93 中实现类似的功能。 8MPlus RAM=$(free -m | awk '/Mem:/ {print $3}') CPU_LOAD=$(vmstat 1 2 | tail -1 | awk '{print 100 - $15}') CPU_TEMP=$(awk '{print $1/1000}' /sys/class/thermal/thermal_zone0/temp 2>/dev/null || echo "N/A") GPU_TEMP=$(awk '{print $1/1000}' /sys/class/thermal/thermal_zone1/temp 2>/dev/null || echo "${CPU_TEMP}") GPU_LOAD=$(cat /sys/kernel/debug/gc/load 2>/dev/null | awk '/load/ {gsub("%", "$3"); if (max== || $3>max) max=$3} END {if (max!=) print max "%"; else print "N/A"}') i.MX 93 RAM=$(free -m | awk '/Mem:/ {print $3}') CPU_LOAD=$(vmstat 1 2 | tail -1 | awk '{print 100 - $15}') CPU_TEMP=$(awk '{print $1/1000}' /sys/class/thermal/thermal_zone0/temp) 如何监测 i.MX93 npu(ethos-u) 的 GPU_LOAD 和 GPU_TEMP? Linux Re: How to get NPU Temperature and utilization for NXP i.MX93 EVK 你好@sonal-acldigital i.MX 8M Plus 和 i.MX 93 都没有提供实时监测 NPU 温度的方法。 - imx8MP,thermal_zone0 表示 CPU 温度,thermal_zone1 表示 SoC 温度。 - imx93,thermal_zone0 表示 CPU 温度。 - NPU,没有像 nputop 这样的工具。 有关性能调优的信息,请参阅第 7.1.2 节。《机器学习用户指南》中的“硬件加速器性能分析”。 B.R Re: How to get NPU Temperature and utilization for NXP i.MX93 EVK @pengyong_zhang感谢您澄清 i.MX 8M Plus 和 i.MX 93 的热区划分。请您澄清以下问题: i.MX8MPLUS 1. GPU 温度:是否有专门的系统路径(如 /sys/class/thermal/thermal_zoneX/temp)来读取单个 GPU 温度,还是仅包含在 soc-thermal 区域(thermal_zone1)中? 2. GPU 负载:读取 /sys/kernel/debug/gc/load 是检查 GPU 负载的标准方法吗?还是也需要按照 ML 用户指南第 7.1.2 节中详述的过程进行检查? i.MX93: 由于没有像 nputop 这样的原生工具来监测 NPU 负载和温度,我们想问:将推理执行卸载到 NPU 与单独在 CPU 上运行相比,通过测量 CPU 负载的减少量来推导出相对 NPU 利用率是否有效? 如果这种方法不推荐,是否有其他驱动节点或性能计数器可以用来估算推理运行期间的 NPU 活动? Re: How to get NPU Temperature and utilization for NXP i.MX93 EVK 你好@sonal-acldigital 抱歉回复晚了。我前段时间得了重感冒,还持续高烧了一段时间。今天刚退烧。 1.没有专用的路径来读取GPU温度。 2. 是的,目前通过 /sys/kernel/debug/gc/load 进行 GPU 负载监控的方法就是如此。 IMX93: 您需要使用性能分析自行计算 NPU 利用率。 B.R
查看全文
I.MX95 LVDSクロック出力は変更できません こんにちは、みんな、 Q1: カーネルのlf-6.12yでシングルポートのLVDSディスプレイを作っています。ドライバ/GPU/drm/panel/panel-simple.cで自分でパネル設定を追加しましたが、クロックピンを測定しているときはいつも150MHz前後でした。しかし、他の信号は正常に機能していた。 しかし、lf-6.18yではクロック出力は正しくでき、デュアルポートモードではクロック変更も両バージョンで問題ありません。これは既知の問題でしょうか、それとも私のミスでしょうか?なぜなら、いくつかの理由でこの問題をlf-6.12yで解決できればと思っているからです。 以下は私の設定です panel-simple.c: static const struct display_timing lt9211_test_timing = { .pixelclock= { 35916000, 35916000, 35916000 }, .hactive= { 280, 280, 280 }, .hfront_porch= { 40, 40, 40, }, .hback_porch= { 60, 60, 60 }, .hsync_len= { 30, 30, 30 }, .vactive= { 1424, 1424, 1424 }, .vfront_porch= { 15, 15, 15 }, .vback_porch= { 17, 17, 17}, .vsync_len= { 4, 4, 4 }, .フラグ= DISPLAY_FLAGS_DE_HIGH、 }; static const struct panel_desc lt9211_test = { タイミング= &lt9211_test_timing、 .bpc= 8、 .num_timings= 1、 。サイズ= { 。幅= 292、 。身長= 111、 }、 .bus_format= MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA、 .bus_flags= DRM_BUS_FLAG_DE_HIGH、 .connector_type= DRM_MODE_CONNECTOR_LVDS、 }; デバイスツリー内の私の lvds 設定 &{/}{ lvds1_panel { //compatible = "3ascreen,sa123hwv-l51"; compatible = "lt9211_test"; バックライト = <&lvds_backlight>; ステータス = "正常"; ポート { panel_in: エンドポイント { リモートエンドポイント = <&lvds1_out>; }; }; }; Q2: 特定の条件下では、同じハードウェア内でデータレーンとクロック間でLVDSの共通電圧が整列しないこともあります。あるいは、LVDS1のD3Pには信号があるがD3Nには信号がないなど、何らかの信号が欠落している場合もある。なぜこうなったのか、何かアイデアはありますか?一部のプログラムがこれを引き起こす可能性はありますか? Q3: どんな設定でもLVDSのクロック位相をシフトできますか? よろしくお願いします。 Re: I.MX95 LVDS clock output can not be changed Q1: これはおそらくあなたのパネルではなく、既知のlf-6.12y LVDSクロックドライバーの制限やバグである可能性が高いです。タイミングのミス。シングルポートのLVDSでは、ドライバ/クロック経路が約148.5/150に強制または丸められている可能性が高いですMHzlf-6.18yが動作するため、実用的な解決策はLVDS/LDBクロックの変更をlf-6.18yからlf-6.12yにバックポートするか、6.12y LVDSドライバー/PLLクロックテーブルをパッチして35.916 MHzピクセルクロックを可能にすることです。 git diff lf-6.12.y..lf-6.18.y -- \ ドライバ/GPU/DRM/ブリッジ/IMX/IMX95-LDB.C ドライバ/phy/freescale/phy-fsl-imx8mp-lvds.c ドライバ/clk/imx/clk-imx95-blk-ctl.c \ arch/arm64/boot/dts/freescale/imx95.dtsi \ arch/arm64/boot/dts/freescale/imx95-*-lvds* Q2: 例えばD3Pには信号があるのにD3Nに信号がない場合、通常はパネルタイミングが原因ではありません。チェック: LVDSチャネルのイネーブルメント:LVDS0/LVDS1のミスマッチ fsl、データ幅 / fsl、データマッピング PHYイネーブルメント コネクタまたは基板の断線/短絡 はんだ付けの問題 終端/プロービング方法 LVDS出力ピンが損傷している可能性があります ソフトウェアが誤ったチャネル/レーン/データ幅設定を引き起こすことがありますが、差動ペアの片側が欠けているとハードウェア、パッド、ルーティング、終端、または測定の問題を強く示唆しています。 Q3: i.MX8MP LVDSの場合、LVDSのクロック位相をシフトするための通常のデバイスツリー構成はありません。クロック周波数、タイミング、PHY設定を修正してください。 Re: I.MX95 LVDS clock output can not be changed 本当にありがとうございます。 LVDSパッチはとても役に立ちます。
查看全文
eTPU crank, cam, injections and Ignitions on S32K3 Hello, I need to implement drivers to actuate Injections and ignitions phased with crank and cam signals. I need to understand which is the best solution to implement this drivers. My doubt are: 1) The API provided by AN4907SW.zip are compatible with eTPU present in S32K3xx? 2)If no, it's a good solution adapt this API for S32K3xx or the best solution it's use ConfigTool ? There is an example for S32K3xx about this application? Regards, Francesco. Re: eTPU crank, cam, injections and Ignitions on S32K3 Hi @francescovico  Converting data from big-endian to little-endian involves reversing the byte order by adjusting bit shifts and masks according to the data type size. GCC provides built-in functions to simplify this process, for example: uint32_t __builtin_bswap32 (uint32_t x). You can find more details in the GCC documentation: 7.2.3 Byte-Swapping Builtins Re: eTPU crank, cam, injections and Ignitions on S32K3 Hi @VaneB , if I understood well , the Automotive functions (CRANK, SPARK...), are made for big endian microcontrollers. To use eTPU with Automotive functions on S32K364 (little endian), I need to download a function set selecting : francescovico_0-1761136257258.pngfrancescovico_0-1761136257258.png And change the functions: uint32_t *fs_memcpy32(uint32_t *dest,uint32_t *source,uint32_t size); void fs_memset32(uint32_t *start,uint32_t value,int32_t size); to swap each 32 bit values to read/write little endian code and parameters, it's true? Regards, Francesco. Re: eTPU crank, cam, injections and Ignitions on S32K3 Hi @francescovico  The S32K39/37/36 Microcontrollers for Electrification Applications, includes eTPU. However, there is currently no dedicated documentation or demo similar to the MPC5634's AN4907 available for these devices. That said, the AN4907 document, demo, and microcode are suitable for the S32K39/37/36 family, but please note that these devices use a little-endian architecture. Therefore, you will need to modify the memory access API. You can refer to the motor control-related modules in the CodeWarrior eTPU Function Selector, which has been updated to little-endian. BR, VaneB Re: eTPU crank, cam, injections and Ignitions on S32K3 Thanks for pointing this out! There was an endianity conversion issue. As a result, the missing tooth mask was not configured correctly and it counted 350 deg per rev resp 700 deg per cycle. Now, the demo app in the original post is fixed. Re: eTPU crank, cam, injections and Ignitions on S32K3 Hi @MilanBrejl , Now I'm trying to use Fuel Cyl 1 etpu driver. It seem that  the driver use s24AngleNormalEnd as "start angle" and stop all injections at s24AngleStop. The duration u24InjectionTime it's never respected. It's possible? Attached there is a .rar file that contain  picoscope acquisition of "fuel cyl 1" where the injector parameter are: Etpu_Fuel_Ip_ConfigType fuel_1_config = { .s24AngleNormalEnd = DEG2TCR2(-180), .s24AngleStop = DEG2TCR2(-360), .s24AngleOffsetRecalc = DEG2TCR2(-30), .u24InjectionTime = USEC2TCR1(1200), .u24CompensationTime = USEC2TCR1(0), .u24InjectionTimeMinimum = USEC2TCR1(0), .u24OffTimeMinimum = USEC2TCR1(0), .eGenerationDisable = ETPU_FUEL_GENERATION_ALLOWED }; In the picoscope acquisition it's visible start of injection exactly at 180° , stop of injection at 360° and injection duration of 30 ms (it should be 1,2ms). Regards, Francesco. Re: eTPU crank, cam, injections and Ignitions on S32K3 Hi @MilanBrejl  , Now I'm trying to use Fuel Cyl 1 etpu driver. It seem that  the driver use s24AngleNormalEnd as "start angle" and stop injection ever at s24AngleStop. The duration u24InjectionTime it's never respected. It's possible? Attached there is a .rar file that contain  picoscope acquisition of "fuel cyl 1" where the injector parameter are: Etpu_Fuel_Ip_ConfigType fuel_1_config = { .s24AngleNormalEnd = DEG2TCR2(-180), .s24AngleStop = DEG2TCR2(-360), .s24AngleOffsetRecalc = DEG2TCR2(-30), .u24InjectionTime = USEC2TCR1(1200), .u24CompensationTime = USEC2TCR1(0), .u24InjectionTimeMinimum = USEC2TCR1(0), .u24OffTimeMinimum = USEC2TCR1(0), .eGenerationDisable = ETPU_FUEL_GENERATION_ALLOWED }; In the picoscope acquisition it's visible start of injection exactly at 180° , stop of injection at 360° and injection duration of 30 ms (it should be 1,2ms). Regards, Francesco. Re: eTPU crank, cam, injections and Ignitions on S32K3 Hi @MilanBrejl , You are right, the s24AngleOffsetRecalc must be a positive number, but putting: s24AngleOffsetRecalc = DEG2TCR2(30) The result it's the same (. I'm using S32K364 that have 2 ETPU (A and B) with 16 channels. Using fuel driver on ETPUA the driver work correctly, but I need to use ETPUB channel 0. My necessity it's to share TCR1 and TCR2 from ETPUA to ETPUB, using STAC registers. It's possible that STAC registers are not correctly initialized? Regards, Francesco. Re: eTPU crank, cam, injections and Ignitions on S32K3 Hi @francescovico, this is how to configure STAC_ENG1 and STAC_ENG2 registers to share TCR1 and TCR2 from eTPU1 to eTPU2: MilanBrejl_0-1770199430269.pngMilanBrejl_0-1770199430269.png Let me know if it helps.  Regards, Milan Re: eTPU crank, cam, injections and Ignitions on S32K3 Hi @MilanBrejl , my registers are exactly the same of your suggestion: ETPU_A_B_REGISTER.pngETPU_A_B_REGISTER.png But the problem it's still present. In the attached picoscope acquisition you can see the spark generated with ETPU A in BLU and spark generated with ETPU B in RED. Both sparks have end angle 180 degree and dwell time 8000 us. Regards, Francesco.   Re: eTPU crank, cam, injections and Ignitions on S32K3 Hi @francescovico, I duplicated your issue on my site and found the root cause. It is not enough to share TCR1/TCR2 time/angle buses between both eTPU engines. Spark and Fuel functions do time to angle transformation, based on the actual engine speed. It uses TRR (Tick Rate Register). This register is part of the Angle Clock logic and it is maintained by Crank eTPU function, running on eTPU A. Hence, TRR has the correct value on eTPU A only. Then, time to angle transformation on eTPU B, using eTPU B TRR, returns a wrong result. This is pretty fundamental, I probably never met anybody running engine control over both eTPU engines and hence this has not been solved. And especially with the new S32K3 devices limited to 16+16 channels this becomes important. Thanks for bringing up this use-case and thanks for your patience. The attached demo application is based on the previous one (in this thread) and adds the following changes: Spark 2 channel is moved from eTPU engine A to eTPU engine B MilanBrejl_0-1770672522362.pngMilanBrejl_0-1770672522362.png Channel masks are updated accordingly MilanBrejl_1-1770672675064.pngMilanBrejl_1-1770672675064.png Channel links need to support usage of both engines (use macro ETPU_IP_CHANNEL_TO_LINK) MilanBrejl_2-1770672729220.pngMilanBrejl_2-1770672729220.png pin configuration is updated, interrupt configuration updated And now new features of Crank eTPU FW: eTPU FW image is updated. The Crank function can run on both engines and update the TRR value also for the other eTPU engine.  This new feature requires to set one new parameter to the Crank configuration MilanBrejl_4-1770673143063.pngMilanBrejl_4-1770673143063.png where MilanBrejl_3-1770673103441.pngMilanBrejl_3-1770673103441.png I hope this helps.  Regards, Milan Re: eTPU crank, cam, injections and Ignitions on S32K3 Hi @MilanBrejl , Now It's working perfectly. Thank you very much for the support! Regards, Francesco. Re: eTPU crank, cam, injections and Ignitions on S32K3 Hello, I'm also researching the K396 board and want to use ETPU for crankshaft, camshaft, and oil injectors. Could we discuss this further? Re: eTPU crank, cam, injections and Ignitions on S32K3 Hi @MilanBrejl  I'm currently working on V12 ECU projekt with s32k396.  For the first prototype i will be using the lqfp176 packaging and was happy to see that this project is written in that packaging. I would like to ask you, if there would be a way to have more Linking channel for the crank_instance? Etpu_Crank_Ip_InstanceType crank_instance = { .u8ChanNum = ETPU_CRANK_CHAN, .u8OtherEngChanNum = ETPU_CRANK_OTHER_ENG_CHAN, .ePriority = ETPU_PRIORITY_HIGH, .ePolarity = ETPU_CRANK_IP_POLARITY_FALLING, .u8TeethTillGap = TEETH_TILL_GAP, .u8TeethInGap = TEETH_IN_GAP, .u8TeethPerCycle = TEETH_PER_CYCLE, .u24Tcr2TicksPerTooth = TCR2_TICKS_PER_TOOTH, .u24Tcr2TicksPerAddTooth = 0, .eLogToothPeriods = ETPU_CRANK_IP_LOG_TOOTH_PERIODS_ON, .u32LinkCam = ((ETPU_IP_CHANNEL_TO_LINK(ETPU_CAM_CHAN) << 0) + (ETPU_IP_CHANNEL_TO_LINK(ETPU_CAM_CHAN) << 8) + (ETPU_IP_CHANNEL_TO_LINK(ETPU_CAM_CHAN) << 16) + (ETPU_IP_CHANNEL_TO_LINK(ETPU_CAM_CHAN) << 24)), .u32Link1 = ((ETPU_IP_CHANNEL_TO_LINK(ETPU_SPARK_1_CHAN) << 0) + (ETPU_IP_CHANNEL_TO_LINK(ETPU_SPARK_2_CHAN) << 8) + (ETPU_IP_CHANNEL_TO_LINK(ETPU_SPARK_3_CHAN) << 16) + (ETPU_IP_CHANNEL_TO_LINK(ETPU_SPARK_4_CHAN) << 24)), .u32Link2 = ((ETPU_IP_CHANNEL_TO_LINK(ETPU_FUEL_1_CHAN) << 0) + (ETPU_IP_CHANNEL_TO_LINK(ETPU_FUEL_2_CHAN) << 8) + (ETPU_IP_CHANNEL_TO_LINK(ETPU_FUEL_3_CHAN) << 16) + (ETPU_IP_CHANNEL_TO_LINK(ETPU_FUEL_4_CHAN) << 24)), .u32Link3 = ((ETPU_IP_CHANNEL_TO_LINK(ETPU_KNOCK_1_CHAN) << 0) + (ETPU_IP_CHANNEL_TO_LINK(ETPU_KNOCK_2_CHAN) << 8) + (ETPU_IP_CHANNEL_TO_LINK(ETPU_INJ_BANK_1_CHAN) << 16) + (ETPU_IP_CHANNEL_TO_LINK(ETPU_INJ_BANK_2_CHAN) << 24)), .u32Link4 = ((ETPU_IP_CHANNEL_TO_LINK(ETPU_INJ_1_CHAN) << 0) + (ETPU_IP_CHANNEL_TO_LINK(ETPU_INJ_2_CHAN) << 8) + (ETPU_IP_CHANNEL_TO_LINK(ETPU_INJ_3_CHAN) << 16) + (ETPU_IP_CHANNEL_TO_LINK(ETPU_INJ_4_CHAN) << 24)), .pCpba = NULL_PTR, .pCpbaToothPeriodLog = NULL_PTR }; I would like to use eTPU engine A for like 12 DI, 12 Ignition, and crank, rightbank intake CAM, rightbank exhaust bank, eTPU engine B for 12 PI injection, and leftside CAM instances. Or perhaps eTPU engine A for 6DI,6Ignition,6PI, Knock, RH CAMx2, eTPU engine B 6DI,6Ignition,6PI, Knock, LH CAMx2. but for this i would need like 2 more Link entries. and im not even counting all the other things i would likely need too. i will want WMI, and Nitro too. i know its a big project but i would really be thankful for some help.  Im new to eTPU programming, and for this whole NXP ecosystem. Thanks in advance for your answer, Richard
查看全文
PN7160 NXP-NCI MCUxpresso for VS Code Example Project for MCXA156 Introduction This document provides a guide on how to integrate the FRDM-MCXA156 as a host for the PN7160 using the examples provided in the “PN7160 NXP-NCI MCUXpresso Example Project” package. The hardware required to follow this guide is: FRDM-MCXA156 development board as host MCU. OM27160A1/OM27160B1 (PN7160 EVK) as the NFC controller. MCUxpresso for VS code extension Software setup. PN7160 NXP-NCI MCUXpresso Example Project version: 1.2 MCXN947 SDK version: 26.06 PN7160 version: 12.50.11. Hardware connections. When using OM27160B1 (SPI Host Interface): The FRDM-MCXA156 schematic document is available on this page. In the case of SPI connections, to use PN7160 directly with the Arduino headers a rework is needed for the FRDM because SDO(MOSI) and SS (Chip select) are not connected as default (as shown in the next figure). You should move R59 and R60 from pad 2 to pad 3 to enable these connections. Habib_MS_0-1781809327131.pngHabib_MS_0-1781809327131.png Note: You can connect the SPI pins available in Mikro bus header with jumpers, but in this example, the signals are routed through the pins enabled by the rework configuration. Once clarified this, these are the pins used in this example. Name PORT I2C0_SDA P0_16 I2C0_SCL P0_17 LPSPI1_SDI P2_16 LPSPI1_SDO P2_13 LPSPI1_SCK P2_12 LPSPI1_SS P2_6 IRQ P1_15 VEN P1_14 REQ P3_16   Software Changes This section describes the software changes required to run an “NXP-NCI2.0” example with the MCXA156, which consists in a detection loop that displays in a terminal information (like UID, SAK, and Product Type for MIFARE product-based cards) about any tag detected by the PN7160. To begin the integration, we first need to import a hello_world project from the FRDM-MCXA156 SDK (v26.06.00) into MCUXpresso IDE for VS Code. For this purpose, download and install the FRDM-MCXA156 repository (version 26.06) using the extension available in the Quickstart panel by selecting Import Repository. For more information about this process, you can consult the corresponding guide. Importing NCI2.0 examples Download the “PN7160 NXP-NCI MCUXpresso Example Project” zip from the product page and extract in a known folder. This will be useful for later use.  Importing base project 1. In the Quick Start panel click on “Import Example from Repository” in VS code. Habib_MS_1-1781809359168.pngHabib_MS_1-1781809359168.png 2. Select “FRDM-MCXA156” in board setting.   Habib_MS_1-1785802139304.pngHabib_MS_1-1785802139304.png 3. In the template will search for the “hello_world” example, select Freestanding Applications, chose the location and click on “import”. Habib_MS_0-1785802110562.pngHabib_MS_0-1785802110562.png Importing SDK drivers Once the project is added to the workspace we will need to add the required drivers, which are the SPI driver in case the OM27160B1HN is being used, or the I2C driver if the OM27160A1HN is being used. For this we need to add the following code in the prj.cfg file. Habib_MS_0-1781809845396.pngHabib_MS_0-1781809845396.png Spoiler (Highlight to read) CONFIG_MCUX_COMPONENT_driver.lpi2c=y CONFIG_MCUX_COMPONENT_driver.lpspi=y CONFIG_MCUX_COMPONENT_driver.lpi2c=y CONFIG_MCUX_COMPONENT_driver.lpspi=y Add the example source code to the newly created MCXA156 project Delete the hello_world.c of the project files folder of the MCXA156 project. From the “NXP-NCI2.0_iMXRT1170_examples” extracted just drag and drop in the project files folder the following files and folders. Habib_MS_0-1781809900813.pngHabib_MS_0-1781809900813.png Habib_MS_1-1781809927413.pngHabib_MS_1-1781809927413.png When you drag and drop a file into VS code a window will appear asking whether you want to link the file or copy it. Please select “Copy files.” Habib_MS_2-1781809983781.pngHabib_MS_2-1781809983781.png The project folder should look like this: Habib_MS_3-1781810001861.pngHabib_MS_3-1781810001861.png After dragging and dropping all the files, the CMakeLists.txt file is automatically updated to include all the copied .c files. An example of this is shown below: Habib_MS_4-1781810063910.pngHabib_MS_4-1781810063910.png However, .h files are not automatically linked, so they must be added manually. Please copy and paste the following includes into the CMakeLists.txt file: Habib_MS_5-1781810096008.pngHabib_MS_5-1781810096008.png Spoiler (Highlight to read) mcux_add_include( BASE_PATH ${CMAKE_CURRENT_LIST_DIR} INCLUDES tool TML NfcLibrary/inc NfcLibrary/NdefLibrary/inc INCLUDES NfcLibrary/NxpNci20/inc . ) mcux_add_include( BASE_PATH ${CMAKE_CURRENT_LIST_DIR} INCLUDES tool TML NfcLibrary/inc NfcLibrary/NdefLibrary/inc INCLUDES NfcLibrary/NxpNci20/inc . ) Preprocessor Interface macro Depending on the interface to be used to communicate with the PN7160, a preprocessor macro must be defined in the CMakelist.txt BOARD_NXPNCI_INTERFACE_SPI (For using SPI with OM27160B1) BOARD_NXPNCI_INTERFACE_I2C (For using I2C with OM27160A1) Additionally, it is necessary to add the macro called REMOVE_P2P_SUPPORT. Please make sure that this Macro is included. Spoiler (Highlight to read) mcux_add_macro( CC "BOARD_NXPNCI_INTERFACE_I2C=1\ REMOVE_P2P_SUPPORT=1") mcux_add_macro( CC "BOARD_NXPNCI_INTERFACE_I2C=1\ REMOVE_P2P_SUPPORT=1") Note: The following sections are exemplified using the SPI interface (BOARD_NXPNCI_INTERFACE_SPI macro). After making the modifications described below, the interface used by the example can be changed simply by setting the macro to BOARD_NXPNCI_INTERFACE_I2C. Board definitions In the board.h file we will add the following definitions in order to refer to the different peripherals and clocks to be used, you can find this file in the following path: {PrjRootDirPath}\ frdmmcxa156\frdmmcxa156\board.h Habib_MS_1-1781810404448.pngHabib_MS_1-1781810404448.png Spoiler (Highlight to read) #ifdef BOARD_NXPNCI_INTERFACE_I2C #define BOARD_NXPNCI_I2C_CLOCK (CLOCK_GetLpi2cClkFreq(0U)) #define BOARD_NXPNCI_I2C_INSTANCE (LPI2C0) #define BOARD_NXPNCI_I2C_BAUDRATE (100000) #define BOARD_NXPNCI_I2C_ADDR (0x28) #endif #ifdef BOARD_NXPNCI_INTERFACE_SPI #define BOARD_NXPNCI_SPI_CLOCK (CLOCK_GetLpspiClkFreq(1U)) #define BOARD_NXPNCI_SPI_INSTANCE (LPSPI1) #define BOARD_NXPNCI_SPI_BAUDRATE (400000) #endif #define BOARD_NXPNCI_IRQ_PORT (GPIO1) #define BOARD_NXPNCI_VEN_PORT (GPIO1) #define BOARD_NXPNCI_DWL_PORT (GPIO3) #define BOARD_NXPNCI_IRQ_PIN (15U) #define BOARD_NXPNCI_VEN_PIN (14U) #define BOARD_NXPNCI_DWL_PIN (16U) #ifdef BOARD_NXPNCI_INTERFACE_I2C #define BOARD_NXPNCI_I2C_CLOCK (CLOCK_GetLpi2cClkFreq(0U)) #define BOARD_NXPNCI_I2C_INSTANCE (LPI2C0) #define BOARD_NXPNCI_I2C_BAUDRATE (100000) #define BOARD_NXPNCI_I2C_ADDR (0x28) #endif #ifdef BOARD_NXPNCI_INTERFACE_SPI #define BOARD_NXPNCI_SPI_CLOCK (CLOCK_GetLpspiClkFreq(1U)) #define BOARD_NXPNCI_SPI_INSTANCE (LPSPI1) #define BOARD_NXPNCI_SPI_BAUDRATE (400000) #endif #define BOARD_NXPNCI_IRQ_PORT (GPIO1) #define BOARD_NXPNCI_VEN_PORT (GPIO1) #define BOARD_NXPNCI_DWL_PORT (GPIO3) #define BOARD_NXPNCI_IRQ_PIN (15U) #define BOARD_NXPNCI_VEN_PIN (14U) #define BOARD_NXPNCI_DWL_PIN (16U) Code modifications to the TML component In the source tml.c source file the following modifications are made, you can find this file in the following path: {{PrjRootDirPath }>frdmmcxa156_hello_world\TML Habib_MS_2-1781810455046.pngHabib_MS_2-1781810455046.png Spoiler (Highlight to read) static Status tml_Reset(void) { /* Set DWL_REQ low for NCI protocol */ GPIO_PortClear(BOARD_NXPNCI_DWL_PORT, 1U << BOARD_NXPNCI_DWL_PIN); GPIO_PortClear(BOARD_NXPNCI_VEN_PORT, 1U << BOARD_NXPNCI_VEN_PIN); Sleep(10); GPIO_PortSet(BOARD_NXPNCI_VEN_PORT, 1U << BOARD_NXPNCI_VEN_PIN); Sleep(10); return SUCCESS; } static Status tml_Reset(void) { /* Set DWL_REQ low for NCI protocol */ GPIO_PortClear(BOARD_NXPNCI_DWL_PORT, 1U << BOARD_NXPNCI_DWL_PIN); GPIO_PortClear(BOARD_NXPNCI_VEN_PORT, 1U << BOARD_NXPNCI_VEN_PIN); Sleep(10); GPIO_PortSet(BOARD_NXPNCI_VEN_PORT, 1U << BOARD_NXPNCI_VEN_PIN); Sleep(10); return SUCCESS; } Habib_MS_3-1781810501153.pngHabib_MS_3-1781810501153.png Spoiler (Highlight to read) static void INTF_INIT(void) { lpspi_master_config_t masterConfig; LPSPI_MasterGetDefaultConfig(&masterConfig); masterConfig.baudRate = BOARD_NXPNCI_SPI_BAUDRATE; masterConfig.whichPcs = (lpspi_which_pcs_t) kLPSPI_Pcs1; masterXfer.configFlags = kLPSPI_MasterPcs1 | kLPSPI_MasterPcsContinuous | kLPSPI_MasterByteSwap; LPSPI_MasterInit(BOARD_NXPNCI_SPI_INSTANCE, &masterConfig, BOARD_NXPNCI_SPI_CLOCK); } static void INTF_INIT(void) { lpspi_master_config_t masterConfig; LPSPI_MasterGetDefaultConfig(&masterConfig); masterConfig.baudRate = BOARD_NXPNCI_SPI_BAUDRATE; masterConfig.whichPcs = (lpspi_which_pcs_t) kLPSPI_Pcs1; masterXfer.configFlags = kLPSPI_MasterPcs1 | kLPSPI_MasterPcsContinuous | kLPSPI_MasterByteSwap; LPSPI_MasterInit(BOARD_NXPNCI_SPI_INSTANCE, &masterConfig, BOARD_NXPNCI_SPI_CLOCK); } Habib_MS_4-1781810544149.pngHabib_MS_4-1781810544149.png Spoiler (Highlight to read) static Status tml_Init(void) { gpio_pin_config_t in_config = {kGPIO_DigitalInput, 0}; gpio_pin_config_t out_config = {kGPIO_DigitalOutput, 0}; GPIO_PinInit(BOARD_NXPNCI_IRQ_PORT, BOARD_NXPNCI_IRQ_PIN, &in_config); GPIO_PinInit(BOARD_NXPNCI_VEN_PORT, BOARD_NXPNCI_VEN_PIN, &out_config); GPIO_PinInit(BOARD_NXPNCI_DWL_PORT, BOARD_NXPNCI_DWL_PIN, &out_config); INTF_INIT(); return SUCCESS; } static Status tml_DeInit(void) { GPIO_PortClear(BOARD_NXPNCI_VEN_PORT, 1U << BOARD_NXPNCI_VEN_PIN); return SUCCESS; } static Status tml_Init(void) { gpio_pin_config_t in_config = {kGPIO_DigitalInput, 0}; gpio_pin_config_t out_config = {kGPIO_DigitalOutput, 0}; GPIO_PinInit(BOARD_NXPNCI_IRQ_PORT, BOARD_NXPNCI_IRQ_PIN, &in_config); GPIO_PinInit(BOARD_NXPNCI_VEN_PORT, BOARD_NXPNCI_VEN_PIN, &out_config); GPIO_PinInit(BOARD_NXPNCI_DWL_PORT, BOARD_NXPNCI_DWL_PIN, &out_config); INTF_INIT(); return SUCCESS; } static Status tml_DeInit(void) { GPIO_PortClear(BOARD_NXPNCI_VEN_PORT, 1U << BOARD_NXPNCI_VEN_PIN); return SUCCESS; } Code modifications for ports, pins and clocks initialization In the file “hardware_init.c” in the board folder of the project, write the following function as shown, in order to add port and clock peripheral initializations. Habib_MS_5-1781810589344.pngHabib_MS_5-1781810589344.png Spoiler (Highlight to read) /* * Copyright 2024 NXP * * SPDX-License-Identifier: BSD-3-Clause */ /*${header:start}*/ #include "pin_mux.h" #include "fsl_clock.h" #include "fsl_reset.h" #include "board.h" #include /*${header:end}*/ /*${function:start}*/ void BOARD_InitHardware(void) { CLOCK_SetClockDiv(kCLOCK_DivLPI2C0, 1u); CLOCK_AttachClk(kFRO12M_to_LPI2C0); CLOCK_SetClockDiv(kCLOCK_DivLPSPI1, 1u); CLOCK_AttachClk(kFRO12M_to_LPSPI1); BOARD_InitPins(); BOARD_InitBootClocks(); BOARD_InitDebugConsole(); } /*${function:end}*/ /* * Copyright 2024 NXP * * SPDX-License-Identifier: BSD-3-Clause */ /*${header:start}*/ #include "pin_mux.h" #include "fsl_clock.h" #include "fsl_reset.h" #include "board.h" #include /*${header:end}*/ /*${function:start}*/ void BOARD_InitHardware(void) { CLOCK_SetClockDiv(kCLOCK_DivLPI2C0, 1u); CLOCK_AttachClk(kFRO12M_to_LPI2C0); CLOCK_SetClockDiv(kCLOCK_DivLPSPI1, 1u); CLOCK_AttachClk(kFRO12M_to_LPSPI1); BOARD_InitPins(); BOARD_InitBootClocks(); BOARD_InitDebugConsole(); } /*${function:end}*/ In the pin_mux.c file modifies the function called BOARD_InitPins(); accordingly, this file can be seen in the following path: {PrjRootDirPath}\ frdmmcxa156\hello_world \pin_mux.c Spoiler (Highlight to read) void BOARD_InitPins(void) { CLOCK_EnableClock(kCLOCK_GateGPIO1); /* GPIO3: Peripheral clock is enabled */ CLOCK_EnableClock(kCLOCK_GateGPIO3); /* PORT0: Peripheral clock is enabled */ CLOCK_EnableClock(kCLOCK_GatePORT0); CLOCK_EnableClock(kCLOCK_GatePORT1); CLOCK_EnableClock(kCLOCK_GatePORT2); CLOCK_EnableClock(kCLOCK_GatePORT3); /* GPIO1 peripheral is released from reset */ RESET_ReleasePeripheralReset(kGPIO1_RST_SHIFT_RSTn); /* GPIO3 peripheral is released from reset */ RESET_ReleasePeripheralReset(kGPIO3_RST_SHIFT_RSTn); RESET_ReleasePeripheralReset(kLPUART0_RST_SHIFT_RSTn); RESET_ReleasePeripheralReset(kPORT0_RST_SHIFT_RSTn); RESET_ReleasePeripheralReset(kLPSPI0_RST_SHIFT_RSTn); RESET_ReleasePeripheralReset(kPORT1_RST_SHIFT_RSTn); RESET_ReleasePeripheralReset(kLPSPI1_RST_SHIFT_RSTn); RESET_ReleasePeripheralReset(kPORT3_RST_SHIFT_RSTn); RESET_ReleasePeripheralReset(kPORT2_RST_SHIFT_RSTn); const port_pin_config_t port0_2_pin78_config = {/* Internal pull-up resistor is enabled */ kPORT_PullUp, /* Low internal pull resistor value is selected. */ kPORT_LowPullResistor, /* Fast slew rate is configured */ kPORT_FastSlewRate, /* Passive input filter is disabled */ kPORT_PassiveFilterDisable, /* Open drain output is disabled */ kPORT_OpenDrainDisable, /* Low drive strength is configured */ kPORT_LowDriveStrength, /* Normal drive strength is configured */ kPORT_NormalDriveStrength, /* Pin is configured as LPUART0_RXD */ kPORT_MuxAlt2, /* Digital input enabled */ kPORT_InputBufferEnable, /* Digital input is not inverted */ kPORT_InputNormal, /* Pin Control Register fields [15:0] are not locked */ kPORT_UnlockRegister}; /* PORT0_2 (pin 78) is configured as LPUART0_RXD */ PORT_SetPinConfig(PORT0, 2U, &port0_2_pin78_config); const port_pin_config_t port0_3_pin79_config = {/* Internal pull-up resistor is enabled */ kPORT_PullUp, /* Low internal pull resistor value is selected. */ kPORT_LowPullResistor, /* Fast slew rate is configured */ kPORT_FastSlewRate, /* Passive input filter is disabled */ kPORT_PassiveFilterDisable, /* Open drain output is disabled */ kPORT_OpenDrainDisable, /* Low drive strength is configured */ kPORT_LowDriveStrength, /* Normal drive strength is configured */ kPORT_NormalDriveStrength, /* Pin is configured as LPUART0_TXD */ kPORT_MuxAlt2, /* Digital input enabled */ kPORT_InputBufferEnable, /* Digital input is not inverted */ kPORT_InputNormal, /* Pin Control Register fields [15:0] are not locked */ kPORT_UnlockRegister}; /* PORT0_3 (pin 79) is configured as LPUART0_TXD */ PORT_SetPinConfig(PORT0, 3U, &port0_3_pin79_config); const port_pin_config_t port2_13_pin35_config = { kPORT_PullDisable, kPORT_LowPullResistor, kPORT_FastSlewRate, kPORT_PassiveFilterDisable, kPORT_OpenDrainDisable, kPORT_LowDriveStrength, kPORT_NormalDriveStrength, /* Pin is configured as LPSPI1_SDO */ kPORT_MuxAlt2, kPORT_InputBufferEnable, kPORT_InputNormal, kPORT_UnlockRegister}; PORT_SetPinConfig(PORT2, 13U, &port2_13_pin35_config); const port_pin_config_t port2_12_pin34_config = { kPORT_PullDisable, kPORT_LowPullResistor, kPORT_FastSlewRate, kPORT_PassiveFilterDisable, kPORT_OpenDrainDisable, kPORT_LowDriveStrength, kPORT_NormalDriveStrength, /* Pin is configured as LPSPI1_SCK */ kPORT_MuxAlt2, kPORT_InputBufferEnable, kPORT_InputNormal, kPORT_UnlockRegister}; PORT_SetPinConfig(PORT2, 12U, &port2_12_pin34_config); const port_pin_config_t port2_16_pin37_config = { kPORT_PullDisable, kPORT_LowPullResistor, kPORT_FastSlewRate, kPORT_PassiveFilterDisable, kPORT_OpenDrainDisable, kPORT_LowDriveStrength, kPORT_NormalDriveStrength, /* Pin is configured as LPSPI1_SDI */ kPORT_MuxAlt2, kPORT_InputBufferEnable, kPORT_InputNormal, kPORT_UnlockRegister}; PORT_SetPinConfig(PORT2, 16U, &port2_16_pin37_config); const port_pin_config_t port2_6_pin28_config = { kPORT_PullDisable, kPORT_LowPullResistor, kPORT_FastSlewRate, kPORT_PassiveFilterDisable, kPORT_OpenDrainDisable, kPORT_LowDriveStrength, kPORT_NormalDriveStrength, /* Pin is configured as LPSPI1_PCS0 */ kPORT_MuxAlt2, kPORT_InputBufferEnable, kPORT_InputNormal, kPORT_UnlockRegister}; PORT_SetPinConfig(PORT2, 6U, &port2_6_pin28_config); const port_pin_config_t port1_15_pin8_config = { kPORT_PullDisable, kPORT_LowPullResistor, kPORT_FastSlewRate, kPORT_PassiveFilterDisable, kPORT_OpenDrainDisable, kPORT_LowDriveStrength, kPORT_NormalDriveStrength, /* Pin is configured as GPIO1 15 */ kPORT_MuxAlt0, kPORT_InputBufferEnable, kPORT_InputNormal, kPORT_UnlockRegister}; PORT_SetPinConfig(PORT1, 15U, &port1_15_pin8_config); const port_pin_config_t port1_14_pin7_config = { kPORT_PullUp, kPORT_LowPullResistor, kPORT_FastSlewRate, kPORT_PassiveFilterDisable, kPORT_OpenDrainDisable, kPORT_LowDriveStrength, kPORT_NormalDriveStrength, /* Pin is configured as GPIO1 14 */ kPORT_MuxAlt0, kPORT_InputBufferEnable, kPORT_InputNormal, kPORT_UnlockRegister}; PORT_SetPinConfig(PORT1, 14U, &port1_14_pin7_config); const port_pin_config_t port3_16_pin59_config = { kPORT_PullUp, kPORT_LowPullResistor, kPORT_FastSlewRate, kPORT_PassiveFilterDisable, kPORT_OpenDrainDisable, kPORT_LowDriveStrength, kPORT_NormalDriveStrength, /* Pin is configured as GPIO3 16 */ kPORT_MuxAlt0, kPORT_InputBufferEnable, kPORT_InputNormal, kPORT_UnlockRegister}; PORT_SetPinConfig(PORT3, 16U, &port3_16_pin59_config); const port_pin_config_t port0_16_pin83_config = { kPORT_PullDisable, kPORT_LowPullResistor, kPORT_FastSlewRate, kPORT_PassiveFilterDisable, kPORT_OpenDrainDisable, kPORT_LowDriveStrength, kPORT_NormalDriveStrength, /* Pin is configured as LPI2C0 SDA */ kPORT_MuxAlt2, kPORT_InputBufferEnable, kPORT_InputNormal, kPORT_UnlockRegister}; PORT_SetPinConfig(PORT0, 16U, &port0_16_pin83_config); const port_pin_config_t port0_17_pin84_config = { kPORT_PullDisable, kPORT_LowPullResistor, kPORT_FastSlewRate, kPORT_PassiveFilterDisable, kPORT_OpenDrainDisable, kPORT_LowDriveStrength, kPORT_NormalDriveStrength, /* Pin is configured as LPI2C0 SCL */ kPORT_MuxAlt2, kPORT_InputBufferEnable, kPORT_InputNormal, kPORT_UnlockRegister}; PORT_SetPinConfig(PORT0, 17U, &port0_17_pin84_config); } void BOARD_InitPins(void) { CLOCK_EnableClock(kCLOCK_GateGPIO1); /* GPIO3: Peripheral clock is enabled */ CLOCK_EnableClock(kCLOCK_GateGPIO3); /* PORT0: Peripheral clock is enabled */ CLOCK_EnableClock(kCLOCK_GatePORT0); CLOCK_EnableClock(kCLOCK_GatePORT1); CLOCK_EnableClock(kCLOCK_GatePORT2); CLOCK_EnableClock(kCLOCK_GatePORT3); /* GPIO1 peripheral is released from reset */ RESET_ReleasePeripheralReset(kGPIO1_RST_SHIFT_RSTn); /* GPIO3 peripheral is released from reset */ RESET_ReleasePeripheralReset(kGPIO3_RST_SHIFT_RSTn); RESET_ReleasePeripheralReset(kLPUART0_RST_SHIFT_RSTn); RESET_ReleasePeripheralReset(kPORT0_RST_SHIFT_RSTn); RESET_ReleasePeripheralReset(kLPSPI0_RST_SHIFT_RSTn); RESET_ReleasePeripheralReset(kPORT1_RST_SHIFT_RSTn); RESET_ReleasePeripheralReset(kLPSPI1_RST_SHIFT_RSTn); RESET_ReleasePeripheralReset(kPORT3_RST_SHIFT_RSTn); RESET_ReleasePeripheralReset(kPORT2_RST_SHIFT_RSTn); const port_pin_config_t port0_2_pin78_config = {/* Internal pull-up resistor is enabled */ kPORT_PullUp, /* Low internal pull resistor value is selected. */ kPORT_LowPullResistor, /* Fast slew rate is configured */ kPORT_FastSlewRate, /* Passive input filter is disabled */ kPORT_PassiveFilterDisable, /* Open drain output is disabled */ kPORT_OpenDrainDisable, /* Low drive strength is configured */ kPORT_LowDriveStrength, /* Normal drive strength is configured */ kPORT_NormalDriveStrength, /* Pin is configured as LPUART0_RXD */ kPORT_MuxAlt2, /* Digital input enabled */ kPORT_InputBufferEnable, /* Digital input is not inverted */ kPORT_InputNormal, /* Pin Control Register fields [15:0] are not locked */ kPORT_UnlockRegister}; /* PORT0_2 (pin 78) is configured as LPUART0_RXD */ PORT_SetPinConfig(PORT0, 2U, &port0_2_pin78_config); const port_pin_config_t port0_3_pin79_config = {/* Internal pull-up resistor is enabled */ kPORT_PullUp, /* Low internal pull resistor value is selected. */ kPORT_LowPullResistor, /* Fast slew rate is configured */ kPORT_FastSlewRate, /* Passive input filter is disabled */ kPORT_PassiveFilterDisable, /* Open drain output is disabled */ kPORT_OpenDrainDisable, /* Low drive strength is configured */ kPORT_LowDriveStrength, /* Normal drive strength is configured */ kPORT_NormalDriveStrength, /* Pin is configured as LPUART0_TXD */ kPORT_MuxAlt2, /* Digital input enabled */ kPORT_InputBufferEnable, /* Digital input is not inverted */ kPORT_InputNormal, /* Pin Control Register fields [15:0] are not locked */ kPORT_UnlockRegister}; /* PORT0_3 (pin 79) is configured as LPUART0_TXD */ PORT_SetPinConfig(PORT0, 3U, &port0_3_pin79_config); const port_pin_config_t port2_13_pin35_config = { kPORT_PullDisable, kPORT_LowPullResistor, kPORT_FastSlewRate, kPORT_PassiveFilterDisable, kPORT_OpenDrainDisable, kPORT_LowDriveStrength, kPORT_NormalDriveStrength, /* Pin is configured as LPSPI1_SDO */ kPORT_MuxAlt2, kPORT_InputBufferEnable, kPORT_InputNormal, kPORT_UnlockRegister}; PORT_SetPinConfig(PORT2, 13U, &port2_13_pin35_config); const port_pin_config_t port2_12_pin34_config = { kPORT_PullDisable, kPORT_LowPullResistor, kPORT_FastSlewRate, kPORT_PassiveFilterDisable, kPORT_OpenDrainDisable, kPORT_LowDriveStrength, kPORT_NormalDriveStrength, /* Pin is configured as LPSPI1_SCK */ kPORT_MuxAlt2, kPORT_InputBufferEnable, kPORT_InputNormal, kPORT_UnlockRegister}; PORT_SetPinConfig(PORT2, 12U, &port2_12_pin34_config); const port_pin_config_t port2_16_pin37_config = { kPORT_PullDisable, kPORT_LowPullResistor, kPORT_FastSlewRate, kPORT_PassiveFilterDisable, kPORT_OpenDrainDisable, kPORT_LowDriveStrength, kPORT_NormalDriveStrength, /* Pin is configured as LPSPI1_SDI */ kPORT_MuxAlt2, kPORT_InputBufferEnable, kPORT_InputNormal, kPORT_UnlockRegister}; PORT_SetPinConfig(PORT2, 16U, &port2_16_pin37_config); const port_pin_config_t port2_6_pin28_config = { kPORT_PullDisable, kPORT_LowPullResistor, kPORT_FastSlewRate, kPORT_PassiveFilterDisable, kPORT_OpenDrainDisable, kPORT_LowDriveStrength, kPORT_NormalDriveStrength, /* Pin is configured as LPSPI1_PCS0 */ kPORT_MuxAlt2, kPORT_InputBufferEnable, kPORT_InputNormal, kPORT_UnlockRegister}; PORT_SetPinConfig(PORT2, 6U, &port2_6_pin28_config); const port_pin_config_t port1_15_pin8_config = { kPORT_PullDisable, kPORT_LowPullResistor, kPORT_FastSlewRate, kPORT_PassiveFilterDisable, kPORT_OpenDrainDisable, kPORT_LowDriveStrength, kPORT_NormalDriveStrength, /* Pin is configured as GPIO1 15 */ kPORT_MuxAlt0, kPORT_InputBufferEnable, kPORT_InputNormal, kPORT_UnlockRegister}; PORT_SetPinConfig(PORT1, 15U, &port1_15_pin8_config); const port_pin_config_t port1_14_pin7_config = { kPORT_PullUp, kPORT_LowPullResistor, kPORT_FastSlewRate, kPORT_PassiveFilterDisable, kPORT_OpenDrainDisable, kPORT_LowDriveStrength, kPORT_NormalDriveStrength, /* Pin is configured as GPIO1 14 */ kPORT_MuxAlt0, kPORT_InputBufferEnable, kPORT_InputNormal, kPORT_UnlockRegister}; PORT_SetPinConfig(PORT1, 14U, &port1_14_pin7_config); const port_pin_config_t port3_16_pin59_config = { kPORT_PullUp, kPORT_LowPullResistor, kPORT_FastSlewRate, kPORT_PassiveFilterDisable, kPORT_OpenDrainDisable, kPORT_LowDriveStrength, kPORT_NormalDriveStrength, /* Pin is configured as GPIO3 16 */ kPORT_MuxAlt0, kPORT_InputBufferEnable, kPORT_InputNormal, kPORT_UnlockRegister}; PORT_SetPinConfig(PORT3, 16U, &port3_16_pin59_config); const port_pin_config_t port0_16_pin83_config = { kPORT_PullDisable, kPORT_LowPullResistor, kPORT_FastSlewRate, kPORT_PassiveFilterDisable, kPORT_OpenDrainDisable, kPORT_LowDriveStrength, kPORT_NormalDriveStrength, /* Pin is configured as LPI2C0 SDA */ kPORT_MuxAlt2, kPORT_InputBufferEnable, kPORT_InputNormal, kPORT_UnlockRegister}; PORT_SetPinConfig(PORT0, 16U, &port0_16_pin83_config); const port_pin_config_t port0_17_pin84_config = { kPORT_PullDisable, kPORT_LowPullResistor, kPORT_FastSlewRate, kPORT_PassiveFilterDisable, kPORT_OpenDrainDisable, kPORT_LowDriveStrength, kPORT_NormalDriveStrength, /* Pin is configured as LPI2C0 SCL */ kPORT_MuxAlt2, kPORT_InputBufferEnable, kPORT_InputNormal, kPORT_UnlockRegister}; PORT_SetPinConfig(PORT0, 17U, &port0_17_pin84_config); } Configure the main.c as follows: Habib_MS_0-1781813861103.pngHabib_MS_0-1781813861103.png Spoiler (Highlight to read) #include #include #include "board.h" #include "app.h" #include "pin_mux.h" #include "fsl_debug_console.h" extern void nfc_example (void); int main(void) { BOARD_InitHardware(); #ifdef BOARD_NXPNCI_INTERFACE_I2C PRINTF("\nRunning the NXP-NCI2.0 example (I2C interface)\n"); #else PRINTF("\nRunning the NXP-NCI2.0 example (SPI interface)\n"); #endif nfc_example(); } #include #include #include "board.h" #include "app.h" #include "pin_mux.h" #include "fsl_debug_console.h" extern void nfc_example (void); int main(void) { BOARD_InitHardware(); #ifdef BOARD_NXPNCI_INTERFACE_I2C PRINTF("\nRunning the NXP-NCI2.0 example (I2C interface)\n"); #else PRINTF("\nRunning the NXP-NCI2.0 example (SPI interface)\n"); #endif nfc_example(); } Building and Debugging the example For building the example, please click on this button and if you followed this guide accordingly the project should compile without errors: Habib_MS_1-1781813991676.pngHabib_MS_1-1781813991676.png Habib_MS_2-1781813999778.pngHabib_MS_2-1781813999778.png Open a serial terminal such as Teraterm with the following settings: Habib_MS_3-1781814017721.pngHabib_MS_3-1781814017721.png  Start a debug session by clicking this button: Habib_MS_4-1781814064724.pngHabib_MS_4-1781814064724.png Once running, the example should look as follows: Habib_MS_5-1781814084057.pngHabib_MS_5-1781814084057.png  When tapping a card on the antenna, the card information will be shown: Habib_MS_6-1781814110924.pngHabib_MS_6-1781814110924.png NFC Controller Solutions
查看全文
NFC Reader Library Migration to FRDM-MCXN947 on VS code Introduction. This document provides a guide for using the PN5190 NFC frontend with the FRDM-MCXN947 development board and the NFC Reader Library in the MCUxpresso for VS code extension. The hardware required to follow this guide is: FRDM-MCXN947 development board as host MCU. PNEV5190BP (based on PN5190) as the NFC transceiver Software Setup. MCXN947 SDK version: 26.06.00 NFCReaderLibrary version: 07.16.00 PN5190 FW version: 0x20D Hardware connections. The PNEV5190 comes with a Kinetis K82F as a host MCU to drive the PN5190 To enable SPI communication between the MCXN947 and the PN5190, the PNEV5190 board must be prepared as follows: Power up board correctly Enable external SPI pins Disable K82F interface with PN5190 Power up and jumper configuration To correctly power up the board.: – Powering it up over USB does not provide enough current. It will be powered with an external power supply of 7.5V over connector J17. Put jumper on following pins: – J9 2-3: External power supply – J8: VBATPWR supplied with VBAT=3.3 V – J12: VBAT supplied with 3.3 V Remove jumpers on following pins: – J22, J23: open SDA signals for K82F – J19: RTS push-button bypass for K82F – J3, J4, J5, J6: pull down jumpers for NFC module signals Set GPIO and SPI voltage to 3.3 V: supplying 3.3 V to VDDIO and the μC supply: – Remove short circuit on R19 – Place short circuit on R20 For any additional configuration, please see PNEV5190B evaluation board quick start guide. Location of the changes mentioned above can be seen in the following image: Habib_MS_0-1782499687907.pngHabib_MS_0-1782499687907.png Routing NFC module communication pins to JP1 To enable the pins on JP1 for communication, we must enable bus switch U10 and disable bus switch U12 in the NFC Host Interface. These switches enable or disable the connections from K82 to PN5190 SPI pins, and expose the SPI interface to an external host. Remove short on R5 to disable communication routing to K82F. Place short on R7 to enable communication routing to JP1 pins. Habib_MS_1-1782499777420.pngHabib_MS_1-1782499777420.png For FRDM-MCXN947 side, no modifications are necessary.  The pins used are available in Header J1 and J2. Which are shown in the following table.     Name MCXN947 PN5190 SCK J2.12 JP1.1 MOSI J2.8 JP1.2 MISO J2.10 JP1.3 SSEL J2.6 JP1.4 IRQ J1.16 JP1.5 RESET J2.2 JP6.1 GND J2.14 JP1.10 SUCCESS J2.17* FAIL J2.15* DWL J2.13* * Pins that need to be configured for library compatibility but are not used and do not need to be connected. Software Changes This section describes the software changes required to run the NfcrdlibEx1_DiscoveryLoop example from the NFC Reader Library. This example implements a detection loop that displays information about any tag detected by the PN5190 in a terminal, such as the UID, SAK, and Product Type for MIFARE-based cards. Please download the NFC Reader Library for the PN5190 from NFC Reader Library | NXP Semiconductors. To begin the integration, we first need to import a hello_world project from the FRDM-MCXN947 SDK (v26.06.00) into MCUXpresso IDE for VS Code. For this purpose, download and install the FRDM-MCXN947 repository (version 26.06) using the extension available in the Quickstart panel by selecting Import Repository. For more information about this process, please refer to the corresponding user guide. Importing NFC Reader library. Download the “NFC Reader Library” zip from the product page and extract in a known folder. This will be useful for later use.  If available, please use the latest version of the NFC Reader Library. Importing base project 1. In the Quick Start panel click on “Import Example from Repository” in VS code. Habib_MS_0-1782500337538.pngHabib_MS_0-1782500337538.png 2. Select “FRDM-MCXN947” in board setting. Habib_MS_0-1785876833645.pngHabib_MS_0-1785876833645.png 3. In the template will search for the “freertos_hello_cm33_core0” example, select Freestanding Application, chose the location and click on “import”. Habib_MS_1-1785876872899.pngHabib_MS_1-1785876872899.png Importing SDK drivers Once the project is added to the workspace we will need to add the required drivers, which are SPI, CTIMER and CMSIS drivers. For this we need to add the following code in the prj.cfg file. Habib_MS_3-1782500385724.pngHabib_MS_3-1782500385724.png Spoiler (Highlight to read) CONFIG_MCUX_COMPONENT_driver.lpflexcomm_lpspi=y CONFIG_MCUX_COMPONENT_driver.ctimer=y CONFIG_MCUX_COMPONENT_driver.CMSIS=y CONFIG_MCUX_COMPONENT_driver.lpflexcomm_lpspi=y CONFIG_MCUX_COMPONENT_driver.ctimer=y CONFIG_MCUX_COMPONENT_driver.CMSIS=y Add the source code Discovery Loop Example Firstly, delete the file freertos_hello.c created by the project. From the “NxpNfcRdLib_PN5190_v07.16.00_PUB” extracted, find and drag and drop the following files on in the project files folder: NfcrdlibEx1_EmvcoProfile.c, phApp_Helper.c, phApp_Init.c, phApp_PN5190_Init.c. You can find these files in the following path: {NxpNfcRdLibRoot} \Examples\NfcrdlibEx1_DiscoveryLoop\src Habib_MS_2-1782504550792.pngHabib_MS_2-1782504550792.png When you drag and drop a file into VS code a window will appear asking whether you want to link the file or copy it. Please select “Copy files.” Habib_MS_3-1782504569947.pngHabib_MS_3-1782504569947.png After dragging and dropping any file, the CMakeLists.txt file is automatically updated to include all the copied .c files. If you selected all these files, the generated code will appear as follows: Habib_MS_4-1782504588274.pngHabib_MS_4-1782504588274.png Additionally, we need to add the file “NfcrdlibEx1_DiscoveryLoop.c” which is the main source file of the project, to achieve this also please drag and drop in the project files folder. Habib_MS_5-1782504604217.pngHabib_MS_5-1782504604217.png At this point, the project should look like this:        Habib_MS_0-1785877154551.pngHabib_MS_0-1785877154551.png Add the example source code to the newly created MCXN947 project From the “NxpNfcRdLib_PN5190_v07.14.00_PUB” extracted just drag and drop in the project files folder the following folders. Habib_MS_0-1782504704260.pngHabib_MS_0-1782504704260.png Habib_MS_1-1782504734285.pngHabib_MS_1-1782504734285.png Habib_MS_2-1782504750818.pngHabib_MS_2-1782504750818.png Habib_MS_3-1782504795659.pngHabib_MS_3-1782504795659.png Once these folders are added the project should look like this: Habib_MS_1-1785877203826.pngHabib_MS_1-1785877203826.png Define FRDM-MCXN947 SDK preprocessor symbol We need to make some changes to the compiler preprocessor configuration related to the NFC reader library, to do this we need to modify the Cmakelist.txt PH_OSAL_FREERTOS PHDRIVER_FRDMMCXN947_PN5190_BOARD NXPBUILD_CUSTOMER_HEADER_INCLUDED PHDRIVER_MCXN947_SPI_POLLING Habib_MS_0-1782505699286.pngHabib_MS_0-1782505699286.png Spoiler (Highlight to read) mcux_add_macro( CC"NXPBUILD_CUSTOMER_HEADER_INCLUDED\ PHDRIVER_FRDMMCXN947_PN5190_BOARD\ PH_OSAL_FREERTOS\ PHDRIVER_MCXN947_SPI_POLLING" ) mcux_add_macro( CC"NXPBUILD_CUSTOMER_HEADER_INCLUDED\ PHDRIVER_FRDMMCXN947_PN5190_BOARD\ PH_OSAL_FREERTOS\ PHDRIVER_MCXN947_SPI_POLLING" ) These symbols are added so the preprocessor knows which header files to include at build time. PHDRIVER_FRDMMCXN947_PN5190_BOARD will help include the BoardSelection.h header, the file that is going to define addresses for registers and peripherals of MCXN947. PH_OSAL_FREERTOS will include headers related to OS operation, meaning that the project will work with operative system (at the end of this guide you will find the steps to add NULLOS support). NXPBUILD_CUSTOMER_HEADER_INCLUDED will add headers to add and select the NFC reader and host that will be used in the project. PHDRIVER_MCXN947_SPI_POLLING: if is defined the example will perform SPI communication by polling method, and if not, will be perform through non-blocking transfers. Modifying the Driver Abstraction Layer (DAL) The added folder DAL will contain the important changes to be able to use the MCXN947 as host device since it will contain all the changes regarding SPI, timer and GPIO configurations required by the library to work properly. Board_FRDM_MCXN947_PN5190.h We need to create a header file that will contain important macros used by the library that are related to the host specific SPI, timer and GPIO peripherals, as well as interrupt vectors and priorities, clock sources and addresses. This file is required to be inside the “boards” folder which is inside DAL. 1. Go to explorer window and select “add file” on the boards folder: Habib_MS_1-1782505314578.pngHabib_MS_1-1782505314578.png 2. Write the file’s name as follows (Board_FRDM_MCXN947_PN5190.h) and click enter: Habib_MS_2-1782505345384.pngHabib_MS_2-1782505345384.png A window like the one shown in the following figure will appear. However, it can be discarded. This window is intended to add the newly created file to the CMakeLists.txt file, but we will instead include the entire folder later. Habib_MS_3-1782505364793.pngHabib_MS_3-1782505364793.png Inside this file, some important macros related to the SPI peripheral and the important pins to be handled (IRQ, Chip Select, Reset) are defined. Habib_MS_4-1782505388079.pngHabib_MS_4-1782505388079.png Spoiler (Highlight to read) #ifndef DAL_BOARDS_BOARD_FRDM_MCXN947_PN5190_H_ #define DAL_BOARDS_BOARD_FRDM_MCXN947_PN5190_H_ #define GPIO_PORT 0 #define GPIO_PORT1 1 /****************************************************************** * LPSPI clock configuration ******************************************************************/ /*Clock Frequency for SPI Flexcomm 1*/ #define SPI_CLOCK_FREQ (CLOCK_GetLPFlexCommClkFreq(1u)) #define SPI_MASTER_CLOCK_FREQ SPI_CLOCK_FREQ /****************************************************************** * Board Pin/Gpio configurations ******************************************************************/ #define PHDRIVER_PIN_RESET ((GPIO_PORT << 8) | 28) /**< Reset pin, Pin28, PIO0_28 */ #define PHDRIVER_PIN_IRQ ((GPIO_PORT << 8) | 31) /**< IRQ pin, Pin10, PIO0_10 */ /* For 5190 busy is same as IRQ */ #define PHDRIVER_PIN_BUSY ((GPIO_PORT << 8) | 31) /**< IRQ pin, Pin31, PIO0_31 */ #define PHDRIVER_PIN_DWL ((GPIO_PORT << 8) | 19) /**< Download pin, Pin19, PIO0_19*/ /* These pins are used for EMVCo Interoperability test status indication, * not for the generic Reader Library implementation. */ #define PHDRIVER_PIN_SUCCESS ((GPIO_PORT1 << 8) | 0) /**< GPIO, Port 1, Pin0 */ #define PHDRIVER_PIN_FAIL ((GPIO_PORT1 << 8) | 1) /**< GPIO, Port 1, Pin1 */ /****************************************************************** * PIN Pull-Up/Pull-Down configurations. ******************************************************************/ #define PHDRIVER_PIN_RESET_PULL_CFG PH_DRIVER_PULL_UP #define PHDRIVER_PIN_IRQ_PULL_CFG PH_DRIVER_PULL_DOWN #define PHDRIVER_PIN_WKUP_PULL_CFG PH_DRIVER_PULL_UP #define PHDRIVER_PIN_CLK_PULL_CFG PH_DRIVER_PULL_UP #define PHDRIVER_PIN_DWL_PULL_CFG PH_DRIVER_PULL_UP #define PHDRIVER_PIN_NSS_PULL_CFG PH_DRIVER_PULL_UP #define PHDRIVER_PIN_BUSY_PULL_CFG PH_DRIVER_PULL_UP #ifndef DAL_BOARDS_BOARD_FRDM_MCXN947_PN5190_H_ #define DAL_BOARDS_BOARD_FRDM_MCXN947_PN5190_H_ #define GPIO_PORT 0 #define GPIO_PORT1 1 /****************************************************************** * LPSPI clock configuration ******************************************************************/ /*Clock Frequency for SPI Flexcomm 1*/ #define SPI_CLOCK_FREQ (CLOCK_GetLPFlexCommClkFreq(1u)) #define SPI_MASTER_CLOCK_FREQ SPI_CLOCK_FREQ /****************************************************************** * Board Pin/Gpio configurations ******************************************************************/ #define PHDRIVER_PIN_RESET ((GPIO_PORT << 😎 | 28) /**< Reset pin, Pin28, PIO0_28 */ #define PHDRIVER_PIN_IRQ ((GPIO_PORT << 😎 | 31) /**< IRQ pin, Pin10, PIO0_10 */ /* For 5190 busy is same as IRQ */ #define PHDRIVER_PIN_BUSY ((GPIO_PORT << 😎 | 31) /**< IRQ pin, Pin31, PIO0_31 */ #define PHDRIVER_PIN_DWL ((GPIO_PORT << 😎 | 19) /**< Download pin, Pin19, PIO0_19*/ /* These pins are used for EMVCo Interoperability test status indication, * not for the generic Reader Library implementation. */ #define PHDRIVER_PIN_SUCCESS ((GPIO_PORT1 << 😎 | 0) /**< GPIO, Port 1, Pin0 */ #define PHDRIVER_PIN_FAIL ((GPIO_PORT1 << 😎 | 1) /**< GPIO, Port 1, Pin1 */ /****************************************************************** * PIN Pull-Up/Pull-Down configurations. ******************************************************************/ #define PHDRIVER_PIN_RESET_PULL_CFG PH_DRIVER_PULL_UP #define PHDRIVER_PIN_IRQ_PULL_CFG PH_DRIVER_PULL_DOWN #define PHDRIVER_PIN_WKUP_PULL_CFG PH_DRIVER_PULL_UP #define PHDRIVER_PIN_CLK_PULL_CFG PH_DRIVER_PULL_UP #define PHDRIVER_PIN_DWL_PULL_CFG PH_DRIVER_PULL_UP #define PHDRIVER_PIN_NSS_PULL_CFG PH_DRIVER_PULL_UP #define PHDRIVER_PIN_BUSY_PULL_CFG PH_DRIVER_PULL_UP We define the macros as well for the interrupt vector of MCXN947, its priority, handler and trigger type. Habib_MS_5-1782505436112.pngHabib_MS_5-1782505436112.png Spoiler (Highlight to read) /****************************************************************** * IRQ PIN NVIC settings ******************************************************************/ #define EINT_IRQn GPIO00_IRQn /*Adding interrupt vector A of GPIO*/ #define EINT_PRIORITY 7 /*Default interrupt priority for GPIO*/ #define CLIF_IRQHandler GPIO00_IRQHandler /*Interrupt handler for vector A*/ #define PIN_IRQ_TRIGGER_TYPE PH_DRIVER_INTERRUPT_RISINGEDGE /*Rising edge Trigger*/ /****************************************************************** * IRQ PIN NVIC settings ******************************************************************/ #define EINT_IRQn GPIO00_IRQn /*Adding interrupt vector A of GPIO*/ #define EINT_PRIORITY 7 /*Default interrupt priority for GPIO*/ #define CLIF_IRQHandler GPIO00_IRQHandler /*Interrupt handler for vector A*/ #define PIN_IRQ_TRIGGER_TYPE PH_DRIVER_INTERRUPT_RISINGEDGE /*Rising edge Trigger*/ As well as some macros for pin logic levels. Habib_MS_6-1782505468893.pngHabib_MS_6-1782505468893.png Spoiler (Highlight to read) /***************************************************************** * Front End Reset logic level settings ****************************************************************/ #define PH_DRIVER_SET_HIGH 1 /**< Logic High. */ #define PH_DRIVER_SET_LOW 0 /**< Logic Low. */ #define RESET_POWERDOWN_LEVEL PH_DRIVER_SET_LOW #define RESET_POWERUP_LEVEL PH_DRIVER_SET_HIGH /***************************************************************** * Front End Reset logic level settings ****************************************************************/ #define PH_DRIVER_SET_HIGH 1 /**< Logic High. */ #define PH_DRIVER_SET_LOW 0 /**< Logic Low. */ #define RESET_POWERDOWN_LEVEL PH_DRIVER_SET_LOW #define RESET_POWERUP_LEVEL PH_DRIVER_SET_HIGH Finally, we define macros for the base address of CTIMER and SPI peripherals, clock frequencies, interrupt vectors and related pins. Habib_MS_7-1782505509612.pngHabib_MS_7-1782505509612.png Spoiler (Highlight to read) /***************************************************************** * SPI Configuration ****************************************************************/ #define PHDRIVER_MCXN947_SPI_MASTER LPSPI1 #define PHDRIVER_MCXN947_SPI_DATA_RATE 5000000U #define PHDRIVER_MCXN947_SPI_CLK_SRC SPI_MASTER_CLOCK_FREQ #define PHDRIVER_MCXN947_SPI_IRQ LP_FLEXCOMM1_IRQn #define SPI_IRQ_PRIORITY 6 /*SPI interrupt priority*/ #define PHDRIVER_PIN_SSEL 27U/* Chip Select, Pin6, SPI */ #define PHDRIVER_PIN_SCK 25U/* SPI clock, Pin7, SPI */ #define PHDRIVER_PIN_MISO 26U/* MISO, Pin8, SPI */ #define PHDRIVER_PIN_MOSI 24U/* MOSI, Pin9, SPI */ #define PHDRIVER_FC1_SPI_DIV kCLOCK_DivFlexcom1Clk #define PHDRIVER_FC1_SPI_CLK kFRO12M_to_FLEXCOMM1 /*Clock to attach to Flexcomm1*/ /***************************************************************** * Timer Configuration ****************************************************************/ #define PH_DRIVER_SDK_CTIMER CTIMER0 /*CTIMER0 base*/ #define PH_DRIVER_SDK_CTIMER_CLK kCLOCK_DivCtimer0Clk/*CTIMER0 clock*/ #define PH_DRIVER_SDK_CTIMER_NVIC CTIMER0_IRQn /*Interrupt vector*/ #define PH_DRIVER_SDK_CTIMER_PRIORITY 4 #define PH_DRIVER_SDK_CTIMER_CLK_FREQ CLOCK_GetCTimerClkFreq(0U) /*CTIMER0 Clock frequency*/ #endif /* DAL_BOARDS_BOARD_FRDM_MCXN947_PN5190_H_ */ /***************************************************************** * SPI Configuration ****************************************************************/ #define PHDRIVER_MCXN947_SPI_MASTER LPSPI1 #define PHDRIVER_MCXN947_SPI_DATA_RATE 5000000U #define PHDRIVER_MCXN947_SPI_CLK_SRC SPI_MASTER_CLOCK_FREQ #define PHDRIVER_MCXN947_SPI_IRQ LP_FLEXCOMM1_IRQn #define SPI_IRQ_PRIORITY 6 /*SPI interrupt priority*/ #define PHDRIVER_PIN_SSEL 27U/* Chip Select, Pin6, SPI */ #define PHDRIVER_PIN_SCK 25U/* SPI clock, Pin7, SPI */ #define PHDRIVER_PIN_MISO 26U/* MISO, Pin8, SPI */ #define PHDRIVER_PIN_MOSI 24U/* MOSI, Pin9, SPI */ #define PHDRIVER_FC1_SPI_DIV kCLOCK_DivFlexcom1Clk #define PHDRIVER_FC1_SPI_CLK kFRO12M_to_FLEXCOMM1 /*Clock to attach to Flexcomm1*/ /***************************************************************** * Timer Configuration ****************************************************************/ #define PH_DRIVER_SDK_CTIMER CTIMER0 /*CTIMER0 base*/ #define PH_DRIVER_SDK_CTIMER_CLK kCLOCK_DivCtimer0Clk/*CTIMER0 clock*/ #define PH_DRIVER_SDK_CTIMER_NVIC CTIMER0_IRQn /*Interrupt vector*/ #define PH_DRIVER_SDK_CTIMER_PRIORITY 4 #define PH_DRIVER_SDK_CTIMER_CLK_FREQ CLOCK_GetCTimerClkFreq(0U) /*CTIMER0 Clock frequency*/ #endif /* DAL_BOARDS_BOARD_FRDM_MCXN947_PN5190_H_ */ MCXN947 SPI and SDK files  Now, inside DAL > src folder we will create a folder named “MCXN947” that will contain 2 source files: phbalReg_Mcxn947Spi.c phDriver_Mcxn947SDK.c 1. Firstly, we will need to delete the “KinetisSDK” folder located in the src folder to avoid multiple definition issues. Please right-click on src/KinetisSDK and click on “Delete”: Habib_MS_1-1782505869521.pngHabib_MS_1-1782505869521.png   2. A window as the following figure will appear, please click on “Move to Recycle Bin”: Habib_MS_2-1782505893781.pngHabib_MS_2-1782505893781.png 3. In the same folder please right-click and click on “New folder…”: Habib_MS_3-1782505917835.pngHabib_MS_3-1782505917835.png 4. Write the folder’s name as follows (MCXN947) and click enter: Habib_MS_4-1782505943176.pngHabib_MS_4-1782505943176.png 5. Add both files following the same steps mentioned in the section Board_FRDM_MCXN947_PN5190.h but with those files (phbalReg_Mcxn947Spi.c and phDriver_Mcxn947SDK.c). We will add these source files in the CMake_List.txt on the next step. Once these files are added the src folder should look like this: Habib_MS_5-1782505974388.pngHabib_MS_5-1782505974388.png 6. Finally, we will add both files to the CMakeLists.txt file so they are included in the compilation process. Please add the following code in the CMake_list.txt file: Habib_MS_6-1782505996170.pngHabib_MS_6-1782505996170.png Spoiler (Highlight to read) mcux_add_source(BASE_PATH ${CMAKE_CURRENT_LIST_DIR} SOURCES "DAL/src/MCXN947/phbalReg_Mcxn947Spi.c" "DAL/src/MCXN947/phDriver_Mcxn947SDK.c") mcux_add_source(BASE_PATH ${CMAKE_CURRENT_LIST_DIR} SOURCES "DAL/src/MCXN947/phbalReg_Mcxn947Spi.c" "DAL/src/MCXN947/phDriver_Mcxn947SDK.c") Although the Kinetis SDK folder has been deleted, it is still referenced in the CMakeLists.txt file. Please remove those includes from this file. Now, we will return to the MCUXpresso extension. Within these source files, we will modify the functions inherited from other board host implementations, replacing them with configurations specific to the MCXN947 peripheral drivers, including SPI, timers, GPIOs, and interrupt handlers. These modifications are based on SDK examples such as ctimer_match_interrupt_example_cm33_core0 and lpspi_polling_b2b_transfer_master_cm33_core0. phbalReg_Mcxn947Spi.c: In this file we first need to include the necessary files and include the headers and callbacks to ensure the correct functionality: Habib_MS_1-1782506156720.pngHabib_MS_1-1782506156720.png Spoiler (Highlight to read) #include "phDriver.h" #include #include "BoardSelection.h" #include #include #include #define PHBAL_REG_MCXN947_SPI_ID 0x0FU /**< ID for MCXN947 SPI BAL component */ #define RX_BUFFER_SIZE_MAX 272U /* Receive Buffer size while exchange */ #ifndef PHDRIVER_MCXN947_SPI_POLLING lpspi_master_handle_t g_masterHandle; /* LPSPI user callback */ void LPSPI_MasterUserCallback(LPSPI_Type *base, lpspi_master_handle_t *handle, status_t status, void *userData); #endif static void phbalReg_Mcxn947SpiConfig(void); #ifndef PHDRIVER_MCXN947_SPI_POLLING volatile bool isTransferCompleted = false; void LPSPI_MasterUserCallback(LPSPI_Type *base, lpspi_master_handle_t *handle, status_t status, void *userData) { if (status == kStatus_Success) { __NOP(); } isTransferCompleted = true; } #endif #include "phDriver.h" #include #include "BoardSelection.h" #include #include #include #define PHBAL_REG_MCXN947_SPI_ID 0x0FU /**< ID for MCXN947 SPI BAL component */ #define RX_BUFFER_SIZE_MAX 272U /* Receive Buffer size while exchange */ #ifndef PHDRIVER_MCXN947_SPI_POLLING lpspi_master_handle_t g_masterHandle; /* LPSPI user callback */ void LPSPI_MasterUserCallback(LPSPI_Type *base, lpspi_master_handle_t *handle, status_t status, void *userData); #endif static void phbalReg_Mcxn947SpiConfig(void); #ifndef PHDRIVER_MCXN947_SPI_POLLING volatile bool isTransferCompleted = false; void LPSPI_MasterUserCallback(LPSPI_Type *base, lpspi_master_handle_t *handle, status_t status, void *userData) { if (status == kStatus_Success) { __NOP(); } isTransferCompleted = true; } #endif After, we will define the phbalReg_Init function, which will be used by the library to initialize the SPI peripheral in this case, and it is defined as follows: Habib_MS_2-1782506214363.pngHabib_MS_2-1782506214363.png Spoiler (Highlight to read) /** * \brief Initialize the Rw612 SPI BAL layer. * * \return Status code * \retval #PH_DRIVER_SUCCESS Operation successful. * \retval #PH_ERR_INVALID_DATA_PARAMS Parameter structure size is invalid. */ phStatus_t phbalReg_Init( void * pDataParams, uint16_t wSizeOfDataParams) { lpspi_master_config_t userConfig; uint32_t srcFreq = 0; if((pDataParams == NULL) || (sizeof(phbalReg_Type_t) != wSizeOfDataParams)) { return (PH_DRIVER_ERROR | PH_COMP_DRIVER); } ((phbalReg_Type_t *)pDataParams)->wId = PH_COMP_DRIVER | PHBAL_REG_MCXN947_SPI_ID; ((phbalReg_Type_t *)pDataParams)->bBalType = PHBAL_REG_TYPE_SPI; /*Initialize Flexcomm1 clock*/ /* attach FRO 12M to FLEXCOMM1 */ CLOCK_SetClkDiv(PHDRIVER_FC1_SPI_DIV, 1u); CLOCK_AttachClk(PHDRIVER_FC1_SPI_CLK); /*Configure SPI pins*/ phbalReg_Mcxn947SpiConfig(); /*SPI configuration*/ LPSPI_MasterGetDefaultConfig(&userConfig); userConfig.baudRate = PHDRIVER_MCXN947_SPI_DATA_RATE; srcFreq = SPI_MASTER_CLOCK_FREQ; userConfig.whichPcs = (lpspi_which_pcs_t)kLPSPI_Pcs0; userConfig.pcsActiveHighOrLow = (lpspi_pcs_polarity_config_t)kLPSPI_PcsActiveLow; userConfig.pcsToSckDelayInNanoSec = 1000000000U / (userConfig.baudRate * 1U); userConfig.lastSckToPcsDelayInNanoSec = 1000000000U / (userConfig.baudRate * 1U); userConfig.betweenTransferDelayInNanoSec = 1000000000U / (userConfig.baudRate * 1U); /*Initialize SPI*/ #ifdef PHDRIVER_MCXN947_SPI_POLLING LPSPI_MasterInit(PHDRIVER_MCXN947_SPI_MASTER, &userConfig, srcFreq); #else LPSPI_MasterInit(PHDRIVER_MCXN947_SPI_MASTER, &userConfig, srcFreq); LPSPI_MasterTransferCreateHandle(PHDRIVER_MCXN947_SPI_MASTER, &g_masterHandle, LPSPI_MasterUserCallback, NULL); #endif return PH_DRIVER_SUCCESS; } /** * \brief Initialize the Rw612 SPI BAL layer. * * \return Status code * \retval #PH_DRIVER_SUCCESS Operation successful. * \retval #PH_ERR_INVALID_DATA_PARAMS Parameter structure size is invalid. */ phStatus_t phbalReg_Init( void * pDataParams, uint16_t wSizeOfDataParams) { lpspi_master_config_t userConfig; uint32_t srcFreq = 0; if((pDataParams == NULL) || (sizeof(phbalReg_Type_t) != wSizeOfDataParams)) { return (PH_DRIVER_ERROR | PH_COMP_DRIVER); } ((phbalReg_Type_t *)pDataParams)->wId = PH_COMP_DRIVER | PHBAL_REG_MCXN947_SPI_ID; ((phbalReg_Type_t *)pDataParams)->bBalType = PHBAL_REG_TYPE_SPI; /*Initialize Flexcomm1 clock*/ /* attach FRO 12M to FLEXCOMM1 */ CLOCK_SetClkDiv(PHDRIVER_FC1_SPI_DIV, 1u); CLOCK_AttachClk(PHDRIVER_FC1_SPI_CLK); /*Configure SPI pins*/ phbalReg_Mcxn947SpiConfig(); /*SPI configuration*/ LPSPI_MasterGetDefaultConfig(&userConfig); userConfig.baudRate = PHDRIVER_MCXN947_SPI_DATA_RATE; srcFreq = SPI_MASTER_CLOCK_FREQ; userConfig.whichPcs = (lpspi_which_pcs_t)kLPSPI_Pcs0; userConfig.pcsActiveHighOrLow = (lpspi_pcs_polarity_config_t)kLPSPI_PcsActiveLow; userConfig.pcsToSckDelayInNanoSec = 1000000000U / (userConfig.baudRate * 1U); userConfig.lastSckToPcsDelayInNanoSec = 1000000000U / (userConfig.baudRate * 1U); userConfig.betweenTransferDelayInNanoSec = 1000000000U / (userConfig.baudRate * 1U); /*Initialize SPI*/ #ifdef PHDRIVER_MCXN947_SPI_POLLING LPSPI_MasterInit(PHDRIVER_MCXN947_SPI_MASTER, &userConfig, srcFreq); #else LPSPI_MasterInit(PHDRIVER_MCXN947_SPI_MASTER, &userConfig, srcFreq); LPSPI_MasterTransferCreateHandle(PHDRIVER_MCXN947_SPI_MASTER, &g_masterHandle, LPSPI_MasterUserCallback, NULL); #endif return PH_DRIVER_SUCCESS; } We have to define the phbalReg_Exchange function as well, which is used for communicating via SPI with the PN5190. Habib_MS_3-1782506250553.pngHabib_MS_3-1782506250553.png   Habib_MS_4-1782506278106.pngHabib_MS_4-1782506278106.png Spoiler (Highlight to read) phStatus_t phbalReg_Exchange( void * pDataParams, uint16_t wOption, uint8_t * pTxBuffer, uint16_t wTxLength, uint16_t wRxBufSize, uint8_t * pRxBuffer, uint16_t * pRxLength ) { phStatus_t status = PH_DRIVER_SUCCESS; uint8_t * pRxBuf; status_t lpspiStatus; lpspi_transfer_t g_masterXfer; uint8_t g_dummyBuffer[RX_BUFFER_SIZE_MAX]; if(pRxBuffer == NULL) { pRxBuf = g_dummyBuffer; } else { pRxBuf = pRxBuffer; } if(pTxBuffer == NULL) { wTxLength = wRxBufSize; g_dummyBuffer[0] = 0xFF; pTxBuffer = g_dummyBuffer; } memset(&g_masterXfer, 0, sizeof(lpspi_transfer_t)); /* Set up the transfer */ g_masterXfer.txData = pTxBuffer; g_masterXfer.rxData = pRxBuf; g_masterXfer.dataSize = wTxLength; g_masterXfer.configFlags = kLPSPI_MasterPcs0 | kLPSPI_MasterPcsContinuous | kLPSPI_MasterByteSwap; /* Start transfer */ #ifdef PHDRIVER_MCXN947_SPI_POLLING lpspiStatus = LPSPI_MasterTransferBlocking(PHDRIVER_MCXN947_SPI_MASTER, &g_masterXfer); #else lpspiStatus = LPSPI_MasterTransferNonBlocking(PHDRIVER_MCXN947_SPI_MASTER, &g_masterHandle, &g_masterXfer); /* Wait transfer complete */ while (!isTransferCompleted) { } #endif if (lpspiStatus != kStatus_Success) { return (PH_DRIVER_FAILURE | PH_COMP_DRIVER); } if (pRxLength != NULL) { *pRxLength = wTxLength; } #ifndef PHDRIVER_MCXN947_SPI_POLLING SDK_DelayAtLeastUs(300U, BOARD_BOOTCLOCKPLL150M_CORE_CLOCK); #endif return status; } phStatus_t phbalReg_Exchange( void * pDataParams, uint16_t wOption, uint8_t * pTxBuffer, uint16_t wTxLength, uint16_t wRxBufSize, uint8_t * pRxBuffer, uint16_t * pRxLength ) { phStatus_t status = PH_DRIVER_SUCCESS; uint8_t * pRxBuf; status_t lpspiStatus; lpspi_transfer_t g_masterXfer; uint8_t g_dummyBuffer[RX_BUFFER_SIZE_MAX]; if(pRxBuffer == NULL) { pRxBuf = g_dummyBuffer; } else { pRxBuf = pRxBuffer; } if(pTxBuffer == NULL) { wTxLength = wRxBufSize; g_dummyBuffer[0] = 0xFF; pTxBuffer = g_dummyBuffer; } memset(&g_masterXfer, 0, sizeof(lpspi_transfer_t)); /* Set up the transfer */ g_masterXfer.txData = pTxBuffer; g_masterXfer.rxData = pRxBuf; g_masterXfer.dataSize = wTxLength; g_masterXfer.configFlags = kLPSPI_MasterPcs0 | kLPSPI_MasterPcsContinuous | kLPSPI_MasterByteSwap; /* Start transfer */ #ifdef PHDRIVER_MCXN947_SPI_POLLING lpspiStatus = LPSPI_MasterTransferBlocking(PHDRIVER_MCXN947_SPI_MASTER, &g_masterXfer); #else lpspiStatus = LPSPI_MasterTransferNonBlocking(PHDRIVER_MCXN947_SPI_MASTER, &g_masterHandle, &g_masterXfer); /* Wait transfer complete */ while (!isTransferCompleted) { } #endif if (lpspiStatus != kStatus_Success) { return (PH_DRIVER_FAILURE | PH_COMP_DRIVER); } if (pRxLength != NULL) { *pRxLength = wTxLength; } #ifndef PHDRIVER_MCXN947_SPI_POLLING SDK_DelayAtLeastUs(300U, BOARD_BOOTCLOCKPLL150M_CORE_CLOCK); #endif return status; } Finally, we will define the phbalReg_Mcxn947SpiConfig function, which is called by phbalReg_Init to configure the SPI pins on the MCXN947: Habib_MS_5-1782506335570.pngHabib_MS_5-1782506335570.png Spoiler (Highlight to read) static void phbalReg_Mcxn947SpiConfig(void) { const port_pin_config_t port0_24_pinB6_config = { kPORT_PullUp, kPORT_LowPullResistor, kPORT_SlowSlewRate, kPORT_PassiveFilterDisable, kPORT_OpenDrainDisable, kPORT_LowDriveStrength, /* Pin is configured as FC1_P0 */ kPORT_MuxAlt2, kPORT_InputBufferEnable, kPORT_InputNormal, kPORT_UnlockRegister}; /* PORT0_24 (pin B6) is configured as SPI_MOSI */ PORT_SetPinConfig(PORT0, 24U, &port0_24_pinB6_config); const port_pin_config_t port0_25_pinA6_config = { kPORT_PullUp, kPORT_LowPullResistor, kPORT_SlowSlewRate, kPORT_PassiveFilterDisable, kPORT_OpenDrainDisable, kPORT_LowDriveStrength, /* Pin is configured as FC1_P1 */ kPORT_MuxAlt2, kPORT_InputBufferEnable, kPORT_InputNormal, kPORT_UnlockRegister}; /* PORT0_25 (pin A6) is configured as SPI_SCK */ PORT_SetPinConfig(PORT0, 25U, &port0_25_pinA6_config); const port_pin_config_t port0_26_pinF10_config = { kPORT_PullUp, kPORT_LowPullResistor, kPORT_SlowSlewRate, kPORT_PassiveFilterDisable, kPORT_OpenDrainDisable, kPORT_LowDriveStrength, /* Pin is configured as FC1_P2 */ kPORT_MuxAlt2, kPORT_InputBufferEnable, kPORT_InputNormal, kPORT_UnlockRegister}; /* PORT0_26 (pin F10) is configured as SPI_MISO */ PORT_SetPinConfig(PORT0, 26U, &port0_26_pinF10_config); const port_pin_config_t port0_27_pinE10_config = { kPORT_PullUp, kPORT_LowPullResistor, kPORT_SlowSlewRate, kPORT_PassiveFilterDisable, kPORT_OpenDrainDisable, kPORT_LowDriveStrength, /* Pin is configured as FC1_P3 */ kPORT_MuxAlt2, kPORT_InputBufferEnable, kPORT_InputNormal, kPORT_UnlockRegister}; /* PORT0_27 (pin E10) is configured as SPI_CS */ PORT_SetPinConfig(PORT0, 27U, &port0_27_pinE10_config); } static void phbalReg_Mcxn947SpiConfig(void) { const port_pin_config_t port0_24_pinB6_config = { kPORT_PullUp, kPORT_LowPullResistor, kPORT_SlowSlewRate, kPORT_PassiveFilterDisable, kPORT_OpenDrainDisable, kPORT_LowDriveStrength, /* Pin is configured as FC1_P0 */ kPORT_MuxAlt2, kPORT_InputBufferEnable, kPORT_InputNormal, kPORT_UnlockRegister}; /* PORT0_24 (pin B6) is configured as SPI_MOSI */ PORT_SetPinConfig(PORT0, 24U, &port0_24_pinB6_config); const port_pin_config_t port0_25_pinA6_config = { kPORT_PullUp, kPORT_LowPullResistor, kPORT_SlowSlewRate, kPORT_PassiveFilterDisable, kPORT_OpenDrainDisable, kPORT_LowDriveStrength, /* Pin is configured as FC1_P1 */ kPORT_MuxAlt2, kPORT_InputBufferEnable, kPORT_InputNormal, kPORT_UnlockRegister}; /* PORT0_25 (pin A6) is configured as SPI_SCK */ PORT_SetPinConfig(PORT0, 25U, &port0_25_pinA6_config); const port_pin_config_t port0_26_pinF10_config = { kPORT_PullUp, kPORT_LowPullResistor, kPORT_SlowSlewRate, kPORT_PassiveFilterDisable, kPORT_OpenDrainDisable, kPORT_LowDriveStrength, /* Pin is configured as FC1_P2 */ kPORT_MuxAlt2, kPORT_InputBufferEnable, kPORT_InputNormal, kPORT_UnlockRegister}; /* PORT0_26 (pin F10) is configured as SPI_MISO */ PORT_SetPinConfig(PORT0, 26U, &port0_26_pinF10_config); const port_pin_config_t port0_27_pinE10_config = { kPORT_PullUp, kPORT_LowPullResistor, kPORT_SlowSlewRate, kPORT_PassiveFilterDisable, kPORT_OpenDrainDisable, kPORT_LowDriveStrength, /* Pin is configured as FC1_P3 */ kPORT_MuxAlt2, kPORT_InputBufferEnable, kPORT_InputNormal, kPORT_UnlockRegister}; /* PORT0_27 (pin E10) is configured as SPI_CS */ PORT_SetPinConfig(PORT0, 27U, &port0_27_pinE10_config); } phDriver_Mcxn947SDK.c: In this file we will have the following definitions and includes that describe relevant characteristics of the ctimer (configuration structures, interrupt handlers and maximum count value), and of the GPIO port: Habib_MS_1-1782506665356.pngHabib_MS_1-1782506665356.png Spoiler (Highlight to read) #include "phDriver.h" #include "BoardSelection.h" #include "fsl_device_registers.h" #include #include /* *********************************************************************************************************** * Internal Definitions * ********************************************************************************************************** */ #define MCXN947_TIMER_MAX_32BIT 0xFFFFFFFFU #define CTIMER_HANDLER CTIMER0_IRQHandler /* *********************************************************************************************************** * * Type Definitions *********************************************************************************************************** */ volatile bool ctimerIsrFlag = false; /* *********************************************************************************************************** * Global and Static Variables * * Match Configuration for CTIMER Channel 0*/ static ctimer_match_config_t matchConfig0; /* Total Size: NNNbytes * ********************************************************************************************************** */ /* Array initializer of GPIO peripheral base pointers */ static const GPIO_Type *pGpiosBaseAddr[] = GPIO_BASE_PTRS; static pphDriver_TimerCallBck_t pCTimerCallBack; static volatile uint8_t dwTimerExp; static const gpio_interrupt_config_t aInterruptTypes[] = {kGPIO_InterruptLogicZero, /* Unused. */ kGPIO_InterruptLogicZero, kGPIO_InterruptLogicOne, kGPIO_InterruptRisingEdge, kGPIO_InterruptFallingEdge, kGPIO_InterruptEitherEdge, }; /* *********************************************************************************************************** * Private Functions Prototypes * ********************************************************************************************************** */ static void phDriver_CTimerIsrCallBack(void); #include "phDriver.h" #include "BoardSelection.h" #include "fsl_device_registers.h" #include #include /* *********************************************************************************************************** * Internal Definitions * ********************************************************************************************************** */ #define MCXN947_TIMER_MAX_32BIT 0xFFFFFFFFU #define CTIMER_HANDLER CTIMER0_IRQHandler /* *********************************************************************************************************** * * Type Definitions *********************************************************************************************************** */ volatile bool ctimerIsrFlag = false; /* *********************************************************************************************************** * Global and Static Variables * * Match Configuration for CTIMER Channel 0*/ static ctimer_match_config_t matchConfig0; /* Total Size: NNNbytes * ********************************************************************************************************** */ /* Array initializer of GPIO peripheral base pointers */ static const GPIO_Type *pGpiosBaseAddr[] = GPIO_BASE_PTRS; static pphDriver_TimerCallBck_t pCTimerCallBack; static volatile uint8_t dwTimerExp; static const gpio_interrupt_config_t aInterruptTypes[] = {kGPIO_InterruptLogicZero, /* Unused. */ kGPIO_InterruptLogicZero, kGPIO_InterruptLogicOne, kGPIO_InterruptRisingEdge, kGPIO_InterruptFallingEdge, kGPIO_InterruptEitherEdge, }; /* *********************************************************************************************************** * Private Functions Prototypes * ********************************************************************************************************** */ static void phDriver_CTimerIsrCallBack(void); We will define the following functions to initialize and stop the timer, and to enable timer interruptions and its callback: Habib_MS_2-1782506722983.pngHabib_MS_2-1782506722983.png Habib_MS_3-1782506736273.pngHabib_MS_3-1782506736273.png Spoiler (Highlight to read) phStatus_t phDriver_TimerStart(phDriver_Timer_Unit_t eTimerUnit, uint32_t dwTimePeriod, pphDriver_TimerCallBck_t pTimerCallBack) { uint64_t qwTimerCnt; uint32_t dwTimerFreq; dwTimerFreq = PH_DRIVER_SDK_CTIMER_CLK_FREQ; qwTimerCnt = dwTimerFreq; qwTimerCnt = (qwTimerCnt / eTimerUnit); qwTimerCnt = (dwTimePeriod * qwTimerCnt); /* 32-bit timers. */ if(qwTimerCnt > (uint64_t)MCXN947_TIMER_MAX_32BIT) { return PH_DRIVER_ERROR | PH_COMP_DRIVER; } if(pTimerCallBack == NULL) /* Timer Start is blocking call. */ { dwTimerExp = 0; pCTimerCallBack = phDriver_CTimerIsrCallBack; } else /* Call the Timer callback. */ { pCTimerCallBack = pTimerCallBack; } /*Configure & start CTIMER*/ /*Ctimer config structure*/ ctimer_config_t config; /*Timer mode, init*/ CTIMER_GetDefaultConfig(&config); CTIMER_Init(PH_DRIVER_SDK_CTIMER, &config); CTIMER_EnableInterrupts(PH_DRIVER_SDK_CTIMER, kCTIMER_Match0InterruptEnable|kCTIMER_Capture0InterruptEnable); /* Configuration match 0 */ matchConfig0.enableCounterReset = true; matchConfig0.enableCounterStop = false; matchConfig0.matchValue = (uint32_t)qwTimerCnt; matchConfig0.outControl = kCTIMER_Output_NoAction; matchConfig0.outPinInitState = false; matchConfig0.enableInterrupt = true; EnableIRQ(PH_DRIVER_SDK_CTIMER_NVIC); NVIC_SetPriority(PH_DRIVER_SDK_CTIMER_NVIC, PH_DRIVER_SDK_CTIMER_PRIORITY); /*Setup Match*/ CTIMER_SetupMatch(PH_DRIVER_SDK_CTIMER, kCTIMER_Match_0, &matchConfig0); /*Start*/ CTIMER_StartTimer(PH_DRIVER_SDK_CTIMER); while (true) { /* Check whether an interrupt occurred */ if (true == ctimerIsrFlag && dwTimerExp) { /* Clear interrupt flag*/ ctimerIsrFlag = false; break; } } return PH_DRIVER_SUCCESS; } phStatus_t phDriver_TimerStart(phDriver_Timer_Unit_t eTimerUnit, uint32_t dwTimePeriod, pphDriver_TimerCallBck_t pTimerCallBack) { uint64_t qwTimerCnt; uint32_t dwTimerFreq; dwTimerFreq = PH_DRIVER_SDK_CTIMER_CLK_FREQ; qwTimerCnt = dwTimerFreq; qwTimerCnt = (qwTimerCnt / eTimerUnit); qwTimerCnt = (dwTimePeriod * qwTimerCnt); /* 32-bit timers. */ if(qwTimerCnt > (uint64_t)MCXN947_TIMER_MAX_32BIT) { return PH_DRIVER_ERROR | PH_COMP_DRIVER; } if(pTimerCallBack == NULL) /* Timer Start is blocking call. */ { dwTimerExp = 0; pCTimerCallBack = phDriver_CTimerIsrCallBack; } else /* Call the Timer callback. */ { pCTimerCallBack = pTimerCallBack; } /*Configure & start CTIMER*/ /*Ctimer config structure*/ ctimer_config_t config; /*Timer mode, init*/ CTIMER_GetDefaultConfig(&config); CTIMER_Init(PH_DRIVER_SDK_CTIMER, &config); CTIMER_EnableInterrupts(PH_DRIVER_SDK_CTIMER, kCTIMER_Match0InterruptEnable|kCTIMER_Capture0InterruptEnable); /* Configuration match 0 */ matchConfig0.enableCounterReset = true; matchConfig0.enableCounterStop = false; matchConfig0.matchValue = (uint32_t)qwTimerCnt; matchConfig0.outControl = kCTIMER_Output_NoAction; matchConfig0.outPinInitState = false; matchConfig0.enableInterrupt = true; EnableIRQ(PH_DRIVER_SDK_CTIMER_NVIC); NVIC_SetPriority(PH_DRIVER_SDK_CTIMER_NVIC, PH_DRIVER_SDK_CTIMER_PRIORITY); /*Setup Match*/ CTIMER_SetupMatch(PH_DRIVER_SDK_CTIMER, kCTIMER_Match_0, &matchConfig0); /*Start*/ CTIMER_StartTimer(PH_DRIVER_SDK_CTIMER); while (true) { /* Check whether an interrupt occurred */ if (true == ctimerIsrFlag && dwTimerExp) { /* Clear interrupt flag*/ ctimerIsrFlag = false; break; } } return PH_DRIVER_SUCCESS; } Habib_MS_4-1782506821715.pngHabib_MS_4-1782506821715.png Spoiler (Highlight to read) phStatus_t phDriver_TimerStop(void) { /*Stop timer & disable interrupts*/ CTIMER_StopTimer(PH_DRIVER_SDK_CTIMER); CTIMER_DisableInterrupts(PH_DRIVER_SDK_CTIMER, kCTIMER_Match0InterruptEnable|kCTIMER_Capture0InterruptEnable); /* Disable at the NVIC */ DisableIRQ(PH_DRIVER_SDK_CTIMER_NVIC); return PH_DRIVER_SUCCESS; } phStatus_t phDriver_TimerStop(void) { /*Stop timer & disable interrupts*/ CTIMER_StopTimer(PH_DRIVER_SDK_CTIMER); CTIMER_DisableInterrupts(PH_DRIVER_SDK_CTIMER, kCTIMER_Match0InterruptEnable|kCTIMER_Capture0InterruptEnable); /* Disable at the NVIC */ DisableIRQ(PH_DRIVER_SDK_CTIMER_NVIC); return PH_DRIVER_SUCCESS; } We will also have definitions for the functions that configure and handle GPIOs of the MCXN947 and enable interruptions. Habib_MS_4-1784224063232.pngHabib_MS_4-1784224063232.png Spoiler (Highlight to read) phStatus_t phDriver_PinConfig(uint32_t dwPinNumber, phDriver_Pin_Func_t ePinFunc, phDriver_Pin_Config_t *pPinConfig) { gpio_pin_config_t sGpioConfig; uint8_t bPinNum; if((ePinFunc == PH_DRIVER_PINFUNC_BIDIR) || (pPinConfig == NULL)) { return PH_DRIVER_ERROR | PH_COMP_DRIVER; } /* Extract the Pin, Gpio, Port details from dwPinNumber */ bPinNum = (uint8_t)(dwPinNumber & 0xFF); sGpioConfig.pinDirection = (ePinFunc == PH_DRIVER_PINFUNC_OUTPUT) ? kGPIO_DigitalOutput:kGPIO_DigitalInput; sGpioConfig.outputLogic = pPinConfig->bOutputLogic; if(ePinFunc == PH_DRIVER_PINFUNC_INTERRUPT) { gpio_interrupt_config_t intConfig = aInterruptTypes[(uint8_t)pPinConfig->eInterruptConfig]; GPIO_GpioClearInterruptFlags((GPIO_Type *)pGpiosBaseAddr[GPIO_PORT], bPinNum); GPIO_SetPinInterruptConfig((GPIO_Type *)pGpiosBaseAddr[GPIO_PORT], bPinNum, intConfig); EnableIRQ(EINT_IRQn); GPIO_PinInit((GPIO_Type *)pGpiosBaseAddr[GPIO_PORT],bPinNum,&sGpioConfig); } else { GPIO_PinInit((GPIO_Type *)pGpiosBaseAddr[GPIO_PORT],bPinNum,&sGpioConfig); } return PH_DRIVER_SUCCESS; } phStatus_t phDriver_PinConfig(uint32_t dwPinNumber, phDriver_Pin_Func_t ePinFunc, phDriver_Pin_Config_t *pPinConfig) { gpio_pin_config_t sGpioConfig; uint8_t bPinNum; if((ePinFunc == PH_DRIVER_PINFUNC_BIDIR) || (pPinConfig == NULL)) { return PH_DRIVER_ERROR | PH_COMP_DRIVER; } /* Extract the Pin, Gpio, Port details from dwPinNumber */ bPinNum = (uint8_t)(dwPinNumber & 0xFF); sGpioConfig.pinDirection = (ePinFunc == PH_DRIVER_PINFUNC_OUTPUT) ? kGPIO_DigitalOutput:kGPIO_DigitalInput; sGpioConfig.outputLogic = pPinConfig->bOutputLogic; if(ePinFunc == PH_DRIVER_PINFUNC_INTERRUPT) { gpio_interrupt_config_t intConfig = aInterruptTypes[(uint8_t)pPinConfig->eInterruptConfig]; GPIO_GpioClearInterruptFlags((GPIO_Type *)pGpiosBaseAddr[GPIO_PORT], bPinNum); GPIO_SetPinInterruptConfig((GPIO_Type *)pGpiosBaseAddr[GPIO_PORT], bPinNum, intConfig); EnableIRQ(EINT_IRQn); GPIO_PinInit((GPIO_Type *)pGpiosBaseAddr[GPIO_PORT],bPinNum,&sGpioConfig); } else { GPIO_PinInit((GPIO_Type *)pGpiosBaseAddr[GPIO_PORT],bPinNum,&sGpioConfig); } return PH_DRIVER_SUCCESS; } Habib_MS_3-1784224025491.pngHabib_MS_3-1784224025491.png Spoiler (Highlight to read) uint8_t phDriver_PinRead(uint32_t dwPinNumber, phDriver_Pin_Func_t ePinFunc) { uint8_t bValue; uint32_t intStatus; uint8_t bPinNum; /* Extract the Pin, Gpio details from dwPinNumber */ bPinNum = (uint8_t)(dwPinNumber & 0xFF); if(ePinFunc == PH_DRIVER_PINFUNC_INTERRUPT) { /*Get value of pin interrupt status*/ intStatus = GPIO_PinGetInterruptFlag((GPIO_Type *)pGpiosBaseAddr[GPIO_PORT], bPinNum); bValue = intStatus ? 1:0; } else { /*Read pin value*/ bValue = (uint8_t)GPIO_PinRead((GPIO_Type *)pGpiosBaseAddr[GPIO_PORT], bPinNum); } return bValue; } uint8_t phDriver_PinRead(uint32_t dwPinNumber, phDriver_Pin_Func_t ePinFunc) { uint8_t bValue; uint32_t intStatus; uint8_t bPinNum; /* Extract the Pin, Gpio details from dwPinNumber */ bPinNum = (uint8_t)(dwPinNumber & 0xFF); if(ePinFunc == PH_DRIVER_PINFUNC_INTERRUPT) { /*Get value of pin interrupt status*/ intStatus = GPIO_PinGetInterruptFlag((GPIO_Type *)pGpiosBaseAddr[GPIO_PORT], bPinNum); bValue = intStatus ? 1:0; } else { /*Read pin value*/ bValue = (uint8_t)GPIO_PinRead((GPIO_Type *)pGpiosBaseAddr[GPIO_PORT], bPinNum); } return bValue; } Habib_MS_2-1784223977410.pngHabib_MS_2-1784223977410.png Spoiler (Highlight to read) void phDriver_PinWrite(uint32_t dwPinNumber, uint8_t bValue) { uint8_t bPinNum; /* Extract the Pin, Gpio details from dwPinNumber */ bPinNum = (uint8_t)(dwPinNumber & 0xFF); GPIO_PinWrite((GPIO_Type *)pGpiosBaseAddr[GPIO_PORT], bPinNum, bValue); } void phDriver_PinClearIntStatus(uint32_t dwPinNumber) { uint8_t bPinNum; /* Extract the Pin, Gpio details from dwPinNumber */ bPinNum = (uint8_t)(dwPinNumber & 0xFF); /*Clear interrupt flag*/ GPIO_GpioClearInterruptFlags((GPIO_Type *)pGpiosBaseAddr[GPIO_PORT], (1U << bPinNum)); } void phDriver_PinWrite(uint32_t dwPinNumber, uint8_t bValue) { uint8_t bPinNum; /* Extract the Pin, Gpio details from dwPinNumber */ bPinNum = (uint8_t)(dwPinNumber & 0xFF); GPIO_PinWrite((GPIO_Type *)pGpiosBaseAddr[GPIO_PORT], bPinNum, bValue); } void phDriver_PinClearIntStatus(uint32_t dwPinNumber) { uint8_t bPinNum; /* Extract the Pin, Gpio details from dwPinNumber */ bPinNum = (uint8_t)(dwPinNumber & 0xFF); /*Clear interrupt flag*/ GPIO_GpioClearInterruptFlags((GPIO_Type *)pGpiosBaseAddr[GPIO_PORT], (1U << bPinNum)); } It is also necessary to add functions required for the library to function correctly. Habib_MS_8-1782506978124.pngHabib_MS_8-1782506978124.png Spoiler (Highlight to read) void phDriver_EnterCriticalSection(void) { NVIC_DisableIRQ(EINT_IRQn); } void phDriver_ExitCriticalSection(void) { NVIC_EnableIRQ(EINT_IRQn); } phStatus_t phDriver_IRQPinRead(uint32_t dwPinNumber) { phStatus_t bGpioVal = false; bGpioVal = phDriver_PinRead(dwPinNumber, PH_DRIVER_PINFUNC_INPUT); return bGpioVal; } phStatus_t phDriver_IRQPinPoll(uint32_t dwPinNumber, phDriver_Pin_Func_t ePinFunc, phDriver_Interrupt_Config_t eInterruptType) { uint8_t bGpioState = 0; if ((eInterruptType != PH_DRIVER_INTERRUPT_RISINGEDGE) && (eInterruptType != PH_DRIVER_INTERRUPT_FALLINGEDGE)) { return PH_DRIVER_ERROR | PH_COMP_DRIVER; } if (eInterruptType == PH_DRIVER_INTERRUPT_FALLINGEDGE) { bGpioState = 1; } while(phDriver_PinRead(dwPinNumber, ePinFunc) == bGpioState); return PH_DRIVER_SUCCESS; } void phDriver_EnterCriticalSection(void) { NVIC_DisableIRQ(EINT_IRQn); } void phDriver_ExitCriticalSection(void) { NVIC_EnableIRQ(EINT_IRQn); } phStatus_t phDriver_IRQPinRead(uint32_t dwPinNumber) { phStatus_t bGpioVal = false; bGpioVal = phDriver_PinRead(dwPinNumber, PH_DRIVER_PINFUNC_INPUT); return bGpioVal; } phStatus_t phDriver_IRQPinPoll(uint32_t dwPinNumber, phDriver_Pin_Func_t ePinFunc, phDriver_Interrupt_Config_t eInterruptType) { uint8_t bGpioState = 0; if ((eInterruptType != PH_DRIVER_INTERRUPT_RISINGEDGE) && (eInterruptType != PH_DRIVER_INTERRUPT_FALLINGEDGE)) { return PH_DRIVER_ERROR | PH_COMP_DRIVER; } if (eInterruptType == PH_DRIVER_INTERRUPT_FALLINGEDGE) { bGpioState = 1; } while(phDriver_PinRead(dwPinNumber, ePinFunc) == bGpioState); return PH_DRIVER_SUCCESS; } Finally, here, we will have the definition of the timer interrupt handler and ISR callback. Habib_MS_9-1782507031648.pngHabib_MS_9-1782507031648.png Spoiler (Highlight to read) void CTIMER0_IRQHandler(void) { /* Clear interrupt flag.*/ CTIMER_ClearStatusFlags(PH_DRIVER_SDK_CTIMER, kCTIMER_Match0Flag|kCTIMER_Capture0Flag); /* Single shot timer. Stop it. */ CTIMER_StopTimer(PH_DRIVER_SDK_CTIMER); CTIMER_DisableInterrupts(PH_DRIVER_SDK_CTIMER, kCTIMER_Match0InterruptEnable|kCTIMER_Capture0InterruptEnable); pCTimerCallBack(); ctimerIsrFlag = true; } static void phDriver_CTimerIsrCallBack(void) { dwTimerExp = 1; } void CTIMER0_IRQHandler(void) { /* Clear interrupt flag.*/ CTIMER_ClearStatusFlags(PH_DRIVER_SDK_CTIMER, kCTIMER_Match0Flag|kCTIMER_Capture0Flag); /* Single shot timer. Stop it. */ CTIMER_StopTimer(PH_DRIVER_SDK_CTIMER); CTIMER_DisableInterrupts(PH_DRIVER_SDK_CTIMER, kCTIMER_Match0InterruptEnable|kCTIMER_Capture0InterruptEnable); pCTimerCallBack(); ctimerIsrFlag = true; } static void phDriver_CTimerIsrCallBack(void) { dwTimerExp = 1; } With these additions, we have all the functions needed (based on the FRDM-MCXN947 SDK) by the library to communicate with the PN5190. BoardSelection.h In this header file, which is found at “DAL > cfg” we will add the definition set in the preprocessor settings to use the FRDM-MCXN947 board as host by adding the following lines to the file: Habib_MS_10-1782507079841.pngHabib_MS_10-1782507079841.png   Spoiler (Highlight to read) #ifdef PHDRIVER_FRDMMCXN947_PN5190_BOARD # include #endif #ifdef PHDRIVER_FRDMMCXN947_PN5190_BOARD # include #endif ph_NxpBuild_App.h In this header found at “intfs” folder, we will add our board support to use it with the PN5190 by adding the following change: Habib_MS_1-1782507715135.pngHabib_MS_1-1782507715135.png Spoiler (Highlight to read) #if defined(PHDRIVER_LPC1769PN5190_BOARD) \ || defined(PHDRIVER_K82F_PNEV5190B_BOARD)\ || defined(PHDRIVER_FRDMMCXN947_PN5190_BOARD) # define NXPBUILD__PHHAL_HW_PN5190 #endif #if defined(PHDRIVER_LPC1769PN5190_BOARD) \ || defined(PHDRIVER_K82F_PNEV5190B_BOARD)\ || defined(PHDRIVER_FRDMMCXN947_PN5190_BOARD) # define NXPBUILD__PHHAL_HW_PN5190 #endif phApp_Init.h In this header located at “intfs” folder we will add the required include files for the initialization of our board and enable the correct debug interface. Habib_MS_2-1782507771262.pngHabib_MS_2-1782507771262.png Spoiler (Highlight to read) /*Check for MCXN controller based boards*/ #if defined (PHDRIVER_FRDMMCXN947_PN5190_BOARD) #define PHDRIVER_FRDM_MCXN947 #endif #ifdef PHDRIVER_FRDM_MCXN947 #include #include #include #include #include #include #endif /*Check for MCXN controller based boards*/ #if defined (PHDRIVER_FRDMMCXN947_PN5190_BOARD) #define PHDRIVER_FRDM_MCXN947 #endif #ifdef PHDRIVER_FRDM_MCXN947 #include #include #include #include #include #include #endif Spoiler (Highlight to read) #if defined(PHDRIVER_KINETIS_K82)|| defined(PHDRIVER_FRDM_MCXN947) #if defined(PHDRIVER_KINETIS_K82)|| defined(PHDRIVER_FRDM_MCXN947) phApp_Init.c Finally, in this source file we will add the initialization code for the MCXN947 to complement the initialization macros defined in the previous phApp_Init.h file modification. Here we will call functions to initialize clocks and UART pins. Habib_MS_3-1782507864930.pngHabib_MS_3-1782507864930.png Spoiler (Highlight to read) #ifdef PHDRIVER_FRDM_MCXN947 #include "fsl_common.h" #include "pin_mux.h" #include "clock_config.h" #include "board.h" static void phApp_MCXN947_Init(void){ BOARD_InitBootPins(); BOARD_InitBootClocks(); BOARD_InitDebugConsole(); } #endif #ifdef PHDRIVER_FRDM_MCXN947 #include "fsl_common.h" #include "pin_mux.h" #include "clock_config.h" #include "board.h" static void phApp_MCXN947_Init(void){ BOARD_InitBootPins(); BOARD_InitBootClocks(); BOARD_InitDebugConsole(); } #endif Spoiler (Highlight to read) #elif defined(PHDRIVER_FRDM_MCXN947) phApp_MCXN947_Init(); #elif defined(PHDRIVER_FRDM_MCXN947) phApp_MCXN947_Init(); These functions are used to initialize the correspondent clocks of each peripheral such as CTIMER, the input pins multiplexor for selecting GPIO functionality and FLEXCOMM for SPI. In here we also set the GPIO functionality for pins P0_31 and P0_28 (IRQ and RESET), as well as UART3 for printing the tag information on the serial port connected to the computer. Additionally, we need to set the NVIC priority to ensure that interrupts can occur. Add the NVIC_SetPriority() function to phApp_Configure_IRQ(). Habib_MS_5-1782507924509.pngHabib_MS_5-1782507924509.png Spoiler (Highlight to read) #ifdef PH_PLATFORM_HAS_ICFRONTEND #if !(defined(PH_OSAL_LINUX) && defined(NXPBUILD__PHHAL_HW_PN5190)) phDriver_Pin_Config_t pinCfg; NVIC_SetPriority(EINT_IRQn, EINT_PRIORITY); pinCfg.bOutputLogic = PH_DRIVER_SET_LOW; pinCfg.bPullSelect = PHDRIVER_PIN_IRQ_PULL_CFG; pinCfg.eInterruptConfig = PIN_IRQ_TRIGGER_TYPE; phDriver_PinConfig(PHDRIVER_PIN_IRQ, PH_DRIVER_PINFUNC_INTERRUPT, &pinCfg); #endif #ifdef PH_PLATFORM_HAS_ICFRONTEND #if !(defined(PH_OSAL_LINUX) && defined(NXPBUILD__PHHAL_HW_PN5190)) phDriver_Pin_Config_t pinCfg; NVIC_SetPriority(EINT_IRQn, EINT_PRIORITY); pinCfg.bOutputLogic = PH_DRIVER_SET_LOW; pinCfg.bPullSelect = PHDRIVER_PIN_IRQ_PULL_CFG; pinCfg.eInterruptConfig = PIN_IRQ_TRIGGER_TYPE; phDriver_PinConfig(PHDRIVER_PIN_IRQ, PH_DRIVER_PINFUNC_INTERRUPT, &pinCfg); #endif pin_mux.c Inside the function “BOARD_InitBootPins()” which is defined in pin_mux.c file, the following initializations need to be added, you can find this file in the following path: {PrjRootDirPath}\frdmmcxn947_Discovery_Loop\frdmmcxn947_cm33_core0\cm33_core0   Habib_MS_6-1782507961225.pngHabib_MS_6-1782507961225.png Spoiler (Highlight to read) void BOARD_InitBootPins(void) { /* Use FRO HF clock for some of the Ctimers */ CLOCK_SetClkDiv(kCLOCK_DivCtimer0Clk, 1u); CLOCK_AttachClk(kFRO_HF_to_CTIMER0); CLOCK_EnableClock(kCLOCK_Gpio0); CLOCK_EnableClock(kCLOCK_Gpio1); BOARD_InitPins(); } void BOARD_InitBootPins(void) { /* Use FRO HF clock for some of the Ctimers */ CLOCK_SetClkDiv(kCLOCK_DivCtimer0Clk, 1u); CLOCK_AttachClk(kFRO_HF_to_CTIMER0); CLOCK_EnableClock(kCLOCK_Gpio0); CLOCK_EnableClock(kCLOCK_Gpio1); BOARD_InitPins(); } Additionally, within the “BOARD_InitPins()” function available in the same file, we will replace the function to add initializations of the GPIO and UART pins. Habib_MS_7-1782507998410.pngHabib_MS_7-1782507998410.png Habib_MS_8-1782508012260.pngHabib_MS_8-1782508012260.png Habib_MS_9-1782508024569.pngHabib_MS_9-1782508024569.png Spoiler (Highlight to read) void BOARD_InitPins(void) { /* Enables the clock for PORT0 controller: Enables clock */ CLOCK_EnableClock(kCLOCK_Port0); /* Enables the clock for PORT1: Enables clock */ CLOCK_EnableClock(kCLOCK_Port1); const port_pin_config_t port0_19_config = {/* Internal pull-up/down resistor is disabled */ kPORT_PullDisable, /* Low internal pull resistor value is selected. */ kPORT_LowPullResistor, /* Fast slew rate is configured */ kPORT_FastSlewRate, /* Passive input filter is disabled */ kPORT_PassiveFilterDisable, /* Open drain output is disabled */ kPORT_OpenDrainDisable, /* Low drive strength is configured */ kPORT_LowDriveStrength, /* Pin is configured as PIO0_10 */ kPORT_MuxAlt0, /* Digital input enabled */ kPORT_InputBufferEnable, /* Digital input is not inverted */ kPORT_InputNormal, /* Pin Control Register fields [15:0] are not locked */ kPORT_UnlockRegister}; /* PORT0_10 (pin B12) is configured as PIO0_10 */ PORT_SetPinConfig(PORT0, 19U, &port0_19_config); const port_pin_config_t port1_0_config = { kPORT_PullDisable, kPORT_LowPullResistor, kPORT_FastSlewRate, kPORT_PassiveFilterDisable, kPORT_OpenDrainDisable, kPORT_LowDriveStrength, /* Pin is configured as PIO0_10 */ kPORT_MuxAlt0, kPORT_InputBufferEnable, kPORT_InputNormal, kPORT_UnlockRegister}; /* PORT0_10 (pin B12) is configured as PIO0_10 */ PORT_SetPinConfig(PORT1, 0U, &port1_0_config); const port_pin_config_t port1_1_config = { kPORT_PullDisable, kPORT_LowPullResistor, kPORT_FastSlewRate, kPORT_PassiveFilterDisable, kPORT_OpenDrainDisable, kPORT_LowDriveStrength, /* Pin is configured as PIO0_10 */ kPORT_MuxAlt0, kPORT_InputBufferEnable, kPORT_InputNormal, kPORT_UnlockRegister}; /* PORT0_10 (pin B12) is configured as PIO0_10 */ PORT_SetPinConfig(PORT1, 1U, &port1_1_config); const port_pin_config_t port0_31_pinB12_config = { kPORT_PullDown, kPORT_LowPullResistor, kPORT_FastSlewRate, kPORT_PassiveFilterDisable, kPORT_OpenDrainDisable, kPORT_LowDriveStrength, /* Pin is configured as PIO0_10 */ kPORT_MuxAlt0, kPORT_InputBufferEnable, kPORT_InputNormal, kPORT_UnlockRegister}; /* PORT0_10 (pin B12) is configured as PIO0_10 */ PORT_SetPinConfig(PORT0, 31U, &port0_31_pinB12_config); const port_pin_config_t port0_28_config = { kPORT_PullDisable, kPORT_LowPullResistor, kPORT_FastSlewRate, kPORT_PassiveFilterDisable, kPORT_OpenDrainDisable, kPORT_LowDriveStrength, /* Pin is configured as PIO0_6 */ kPORT_MuxAlt0, kPORT_InputBufferEnable, kPORT_InputNormal, kPORT_UnlockRegister}; /* PORT0_6 (pin C14) is configured as PIO0_6 */ PORT_SetPinConfig(PORT0, 28U, &port0_28_config); const port_pin_config_t port0_2_pinB16_config = { .pullSelect = kPORT_PullDisable, .pullValueSelect = kPORT_LowPullResistor, .slewRate = kPORT_FastSlewRate, .passiveFilterEnable = kPORT_PassiveFilterDisable, .openDrainEnable = kPORT_OpenDrainDisable, .driveStrength = kPORT_HighDriveStrength, /* Pin is configured as SWO */ .mux = kPORT_MuxAlt1, .inputBuffer = kPORT_InputBufferEnable, .invertInput = kPORT_InputNormal, .lockRegister = kPORT_UnlockRegister}; /* PORT0_2 (pin B16) is configured as SWO */ PORT_SetPinConfig(PORT0, 2U, &port0_2_pinB16_config); const port_pin_config_t port1_8_pinA1_config = { .pullSelect = kPORT_PullUp, .pullValueSelect = kPORT_LowPullResistor, .slewRate = kPORT_FastSlewRate, .passiveFilterEnable = kPORT_PassiveFilterDisable, .openDrainEnable = kPORT_OpenDrainDisable, .driveStrength = kPORT_LowDriveStrength, /* Pin is configured as FC4_P0 */ .mux = kPORT_MuxAlt2, .inputBuffer = kPORT_InputBufferEnable, .invertInput = kPORT_InputNormal, .lockRegister = kPORT_UnlockRegister}; /* PORT1_8 (pin A1) is configured as FC4_P0 */ PORT_SetPinConfig(PORT1, 8U, &port1_8_pinA1_config); const port_pin_config_t port1_9_pinB1_config = { .pullSelect = kPORT_PullDisable, .pullValueSelect = kPORT_LowPullResistor, .slewRate = kPORT_FastSlewRate, .passiveFilterEnable = kPORT_PassiveFilterDisable, .openDrainEnable = kPORT_OpenDrainDisable, .driveStrength = kPORT_LowDriveStrength, /* Pin is configured as FC4_P1 */ .mux = kPORT_MuxAlt2, .inputBuffer = kPORT_InputBufferEnable, .invertInput = kPORT_InputNormal, .lockRegister = kPORT_UnlockRegister}; /* PORT1_9 (pin B1) is configured as FC4_P1 */ PORT_SetPinConfig(PORT1, 9U, &port1_9_pinB1_config); } void BOARD_InitPins(void) { /* Enables the clock for PORT0 controller: Enables clock */ CLOCK_EnableClock(kCLOCK_Port0); /* Enables the clock for PORT1: Enables clock */ CLOCK_EnableClock(kCLOCK_Port1); const port_pin_config_t port0_19_config = {/* Internal pull-up/down resistor is disabled */ kPORT_PullDisable, /* Low internal pull resistor value is selected. */ kPORT_LowPullResistor, /* Fast slew rate is configured */ kPORT_FastSlewRate, /* Passive input filter is disabled */ kPORT_PassiveFilterDisable, /* Open drain output is disabled */ kPORT_OpenDrainDisable, /* Low drive strength is configured */ kPORT_LowDriveStrength, /* Pin is configured as PIO0_10 */ kPORT_MuxAlt0, /* Digital input enabled */ kPORT_InputBufferEnable, /* Digital input is not inverted */ kPORT_InputNormal, /* Pin Control Register fields [15:0] are not locked */ kPORT_UnlockRegister}; /* PORT0_10 (pin B12) is configured as PIO0_10 */ PORT_SetPinConfig(PORT0, 19U, &port0_19_config); const port_pin_config_t port1_0_config = { kPORT_PullDisable, kPORT_LowPullResistor, kPORT_FastSlewRate, kPORT_PassiveFilterDisable, kPORT_OpenDrainDisable, kPORT_LowDriveStrength, /* Pin is configured as PIO0_10 */ kPORT_MuxAlt0, kPORT_InputBufferEnable, kPORT_InputNormal, kPORT_UnlockRegister}; /* PORT0_10 (pin B12) is configured as PIO0_10 */ PORT_SetPinConfig(PORT1, 0U, &port1_0_config); const port_pin_config_t port1_1_config = { kPORT_PullDisable, kPORT_LowPullResistor, kPORT_FastSlewRate, kPORT_PassiveFilterDisable, kPORT_OpenDrainDisable, kPORT_LowDriveStrength, /* Pin is configured as PIO0_10 */ kPORT_MuxAlt0, kPORT_InputBufferEnable, kPORT_InputNormal, kPORT_UnlockRegister}; /* PORT0_10 (pin B12) is configured as PIO0_10 */ PORT_SetPinConfig(PORT1, 1U, &port1_1_config); const port_pin_config_t port0_31_pinB12_config = { kPORT_PullDown, kPORT_LowPullResistor, kPORT_FastSlewRate, kPORT_PassiveFilterDisable, kPORT_OpenDrainDisable, kPORT_LowDriveStrength, /* Pin is configured as PIO0_10 */ kPORT_MuxAlt0, kPORT_InputBufferEnable, kPORT_InputNormal, kPORT_UnlockRegister}; /* PORT0_10 (pin B12) is configured as PIO0_10 */ PORT_SetPinConfig(PORT0, 31U, &port0_31_pinB12_config); const port_pin_config_t port0_28_config = { kPORT_PullDisable, kPORT_LowPullResistor, kPORT_FastSlewRate, kPORT_PassiveFilterDisable, kPORT_OpenDrainDisable, kPORT_LowDriveStrength, /* Pin is configured as PIO0_6 */ kPORT_MuxAlt0, kPORT_InputBufferEnable, kPORT_InputNormal, kPORT_UnlockRegister}; /* PORT0_6 (pin C14) is configured as PIO0_6 */ PORT_SetPinConfig(PORT0, 28U, &port0_28_config); const port_pin_config_t port0_2_pinB16_config = { .pullSelect = kPORT_PullDisable, .pullValueSelect = kPORT_LowPullResistor, .slewRate = kPORT_FastSlewRate, .passiveFilterEnable = kPORT_PassiveFilterDisable, .openDrainEnable = kPORT_OpenDrainDisable, .driveStrength = kPORT_HighDriveStrength, /* Pin is configured as SWO */ .mux = kPORT_MuxAlt1, .inputBuffer = kPORT_InputBufferEnable, .invertInput = kPORT_InputNormal, .lockRegister = kPORT_UnlockRegister}; /* PORT0_2 (pin B16) is configured as SWO */ PORT_SetPinConfig(PORT0, 2U, &port0_2_pinB16_config); const port_pin_config_t port1_8_pinA1_config = { .pullSelect = kPORT_PullUp, .pullValueSelect = kPORT_LowPullResistor, .slewRate = kPORT_FastSlewRate, .passiveFilterEnable = kPORT_PassiveFilterDisable, .openDrainEnable = kPORT_OpenDrainDisable, .driveStrength = kPORT_LowDriveStrength, /* Pin is configured as FC4_P0 */ .mux = kPORT_MuxAlt2, .inputBuffer = kPORT_InputBufferEnable, .invertInput = kPORT_InputNormal, .lockRegister = kPORT_UnlockRegister}; /* PORT1_8 (pin A1) is configured as FC4_P0 */ PORT_SetPinConfig(PORT1, 8U, &port1_8_pinA1_config); const port_pin_config_t port1_9_pinB1_config = { .pullSelect = kPORT_PullDisable, .pullValueSelect = kPORT_LowPullResistor, .slewRate = kPORT_FastSlewRate, .passiveFilterEnable = kPORT_PassiveFilterDisable, .openDrainEnable = kPORT_OpenDrainDisable, .driveStrength = kPORT_LowDriveStrength, /* Pin is configured as FC4_P1 */ .mux = kPORT_MuxAlt2, .inputBuffer = kPORT_InputBufferEnable, .invertInput = kPORT_InputNormal, .lockRegister = kPORT_UnlockRegister}; /* PORT1_9 (pin B1) is configured as FC4_P1 */ PORT_SetPinConfig(PORT1, 9U, &port1_9_pinB1_config); } At the same time, add the following includes to the file: Habib_MS_0-1785878023889.pngHabib_MS_0-1785878023889.png Spoiler (Highlight to read) #include "fsl_common.h" #include "fsl_port.h" #include "board.h" #include "clock_config.h" #include "pin_mux.h" #include "fsl_common.h" #include "fsl_port.h" #include "board.h" #include "clock_config.h" #include "pin_mux.h" Delete phOsal files We must delete from the path “phOsal > src > NullOs > portable” the files: “phOsal_Port_CM3.c”,“phOsal_Port_PN76xx.c” and “phOsal_Port_PN74xxxx.c”. This has the purpose of avoiding any multiple definition errors when compiling the final project. Although these files have been deleted, they are still referenced in the CMakeLists.txt file. Please remove those includes from this file. Add all header files in CMakeList.txt As mentioned previously, the CMakeList.txt is automatically updated when you copy a .c file. However, .h files are not automatically linked, so they must be added manually. Please copy and paste the following includes into the CMakeLists.txt file: Habib_MS_0-1782508446885.pngHabib_MS_0-1782508446885.png Spoiler (Highlight to read) mcux_add_include( BASE_PATH ${CMAKE_CURRENT_LIST_DIR} INCLUDES NxpNfcRdLib/intfs NxpNfcRdLib/types NxpNfcRdLib/comps/phacDiscLoop/src/Sw intfs DAL/boards DAL/cfg DAL/inc phOsal/inc . ) mcux_add_include( BASE_PATH ${CMAKE_CURRENT_LIST_DIR} INCLUDES NxpNfcRdLib/intfs NxpNfcRdLib/types NxpNfcRdLib/comps/phacDiscLoop/src/Sw intfs DAL/boards DAL/cfg DAL/inc phOsal/inc . ) Add _DSB and _ISB support As final modification step, please include in {PrjRootDirPath}\NxpNfcRdLib\comps\phhalHw\src\Pn5190\phhalHw_Pn5190_Int.c the “cmsis_gcc.h” to support of _DSB and _ISB functions. Habib_MS_2-1782508515584.pngHabib_MS_2-1782508515584.png Testing Final Project with FreeRTOS After making all the previous changes and modifications, the migration is now complete, and we can proceed to compile and flash the example to MCXN947. Please “clean” the project before building by right clicking on the project as follows: Habib_MS_1-1785878094753.pngHabib_MS_1-1785878094753.png To run the project, we will need a serial terminal like Tera Term with the following settings: - 115200 baud rate. - 8 data bits. - No parity. - One stop bit, - No flow control. Once the program is flashed and the serial terminal configured, we can reset the board and power the PNEV5190BP. You should see an output similar to the following: Habib_MS_4-1782508585568.pngHabib_MS_4-1782508585568.png Now if any NFC tag is close to the PNEV5190BP’s antenna, you should see the information displayed as shown in the image below: Habib_MS_5-1782508604979.pngHabib_MS_5-1782508604979.png Changing OS preprocessor macro This section presents the steps to follow to add the possibility of easily choosing whether to have OS support or not.  This guide is based as default with FREERTOS, but the NFC reader library offers the possibility to run without OS, firstly, we need to change the preprocessor macro PH_OSAL_FREERTOS to PH_OSAL_NULLOS in the CMakeList.txt, as shown the following image: Habib_MS_6-1782508642319.pngHabib_MS_6-1782508642319.png Finally, to avoid multiple definition issues when we change between NULLOS and FREERTOS, we will discard the SysTickHandler for FREERTOS side located in port.c when the NULLOS macro is defined, to achieve this we need to add a replacement of the file port.c since the included FreeRTOS is shared with all projects of the repository, and if we modify this file, it will be modified in all projects. 1. Go to the explorer window, right-click on the project and click on “New File…”. Habib_MS_5-1785877420766.pngHabib_MS_5-1785877420766.png 2. Write the file’s name as follows (port.c) and click enter: Habib_MS_4-1785877388377.pngHabib_MS_4-1785877388377.png 3. Add this file into the CMakeList.txt file to include port.c into the compilation process: Habib_MS_3-1785877308864.pngHabib_MS_3-1785877308864.png Spoiler (Highlight to read) mcux_add_source(BASE_PATH ${CMAKE_CURRENT_LIST_DIR} SOURCES "port.c") mcux_add_source(BASE_PATH ${CMAKE_CURRENT_LIST_DIR} SOURCES "port.c") 4. Please copy and paste all the content form of the port.c located on the following path to the port.c we created: {SdkRootDirPath}/rtos/freertos/freertos-kernel-upstream/portable/GCC/ARM_CM33_NTZ/non_secure Habib_MS_1-1785877681949.pngHabib_MS_1-1785877681949.png 5. Replace the SysTick_Handler() of the port.c we created to the following function: Habib_MS_11-1782508854714.pngHabib_MS_11-1782508854714.png Spoiler (Highlight to read) #ifndef PH_OSAL_NULLOS void SysTick_Handler( void ) /* PRIVILEGED_FUNCTION */ { uint32_t ulPreviousMask; ulPreviousMask = portSET_INTERRUPT_MASK_FROM_ISR(); traceISR_ENTER(); { /* Increment the RTOS tick. */ if( xTaskIncrementTick() != pdFALSE ) { traceISR_EXIT_TO_SCHEDULER(); /* Pend a context switch. */ portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; } else { traceISR_EXIT(); } } portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask ); } #endif #ifndef PH_OSAL_NULLOS void SysTick_Handler( void ) /* PRIVILEGED_FUNCTION */ { uint32_t ulPreviousMask; ulPreviousMask = portSET_INTERRUPT_MASK_FROM_ISR(); traceISR_ENTER(); { /* Increment the RTOS tick. */ if( xTaskIncrementTick() != pdFALSE ) { traceISR_EXIT_TO_SCHEDULER(); /* Pend a context switch. */ portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; } else { traceISR_EXIT(); } } portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask ); } #endif 6. Finally, we will ignore the port.c of the FreeRTOS folder, please add the following code to the CMakeList.txt: Habib_MS_2-1785878166328.pngHabib_MS_2-1785878166328.png Spoiler (Highlight to read) mcux_project_remove_source( BASE_PATH ${SdkRootDirPath}/rtos/freertos/freertos-kernel-upstream/portable/GCC/ARM_CM33_NTZ/non_secure SOURCES port.c ) mcux_project_remove_source( BASE_PATH ${SdkRootDirPath}/rtos/freertos/freertos-kernel-upstream/portable/GCC/ARM_CM33_NTZ/non_secure SOURCES port.c ) Please rebuild and test as the steps mentioned in the section Testing Final Project with FreeRTOS. NFC Reader Library
查看全文
2026年美国领先的白标SEO专家 将客户的 SEO 工作交给外部合作伙伴,只有当该合作伙伴确实具备相应的技术实力时,才能奏效。广告公司需要的不仅仅是供应商,而是了解抓取预算、结构化数据、内容策略,以及日益重要的如何针对人工智能驱动的搜索进行优化的白标 SEO 专家,而不仅仅是承诺排名却没有明确方法论的公司。 本指南着眼于 2026 年为美国机构提供服务的领先白标 SEO 专家,特别评估他们的技术和战略能力的深度,而不仅仅是他们网站上列出的服务范围。 2026 年领先的白标 SEO 专家 1. 阿拉伯搜索引擎优化 Arab SEO 团队在技术 SEO、本地 SEO、电子商务 SEO、国际 SEO、AI SEO 和生成式引擎优化 (GEO) 方面拥有专家级的深度。真正的专家与普通供应商的区别在于方法论——Arab SEO 的多语言和人工智能驱动搜索方法建立在结构化、可重复的流程之上,而不是一次性的策略,这对于一家代理机构同时信任拥有数十个不同客户账户的合作伙伴来说至关重要。 2. SEO 通告 SEO Circular 的专家们专注于企业级技术 SEO——这类大型的、拥有数千页的网站,一个被忽视的抓取问题就可能抑制整个域的排名。其团队在国际和多语言 SEO 方面的经验也使其成为与跨国经营的客户合作的代理机构的有力选择。 3. 三重思维 Triple Minds 的团队以代理服务为核心,这意味着其专家完全专注于执行质量,而不是销售或客户获取——这在交付一致性方面是一个结构性优势。 4. 半化 Semify 的专家拥有多年构建可定制本地 SEO 活动的经验,其流程专门围绕帮助小型机构逐步扩展其 SEO 服务而构建。 5. SEOReseller SEOReseller 团队专注于提供全方位管理的服务,处理完整的 SEO 流程——技术、内容和链接——日常执行中几乎不需要代理机构的参与。 6. DashClicks DashClicks 将其 SEO 专家与专为报告和客户管理而构建的软件平台相结合,使代理机构能够通过自动化仪表板了解专家的工作情况。 7. 霍斯 HOTH 的专家们在完善的文档记录和标准化的方案框架内工作,使得机构能够轻松理解他们的流程,并向客户解释。 8. 增强能力 Boostability 团队在为大量小型客户提供一致的 SEO 质量方面积累了丰富的专业知识——这与管理少数大型企业客户所需的技能截然不同。 9. 销售 Vendasta 的专家们在一个更广泛的市场平台上工作,SEO 是众多白标服务之一,代理机构可以通过单一团队关系访问这些服务。 10. 法特乔 FATJOE 的专家专注于快速、产品化的交付成果——快速完成单个链接建设或内容订单,而不是持续的战略合作。 究竟是什么将专业供应商与普通供应商区分开来? 真正的SEO专家应该能够用具体、专业的术语解释他们的工作流程,而不仅仅是列出服务类别。注意以下信号: 他们可以详细解释他们的技术审计流程——他们使用哪些工具,他们具体检查哪些内容,以及如何对发现的问题进行优先级排序。 他们有一套完善的内容策略流程,该流程与真实的搜索意图研究挂钩,而不仅仅是关键词密度目标。 他们可以清楚地描述他们的链接建设方法,包括链接的来源以及如何评估链接质量。 他们对人工智能搜索有着明确的观点,因为人工智能搜索重塑搜索引擎优化的速度比近年来任何算法更新都要快。 他们可以展示真实客户项目的前后对比数据,即使数据经过匿名化处理。 为什么专业深度比服务广度更重要 选择白标合作伙伴时,很容易根据他们列出的服务数量来决定,但一个提供十项服务但服务内容浅薄的供应商,其价值通常不如一个提供五项服务但服务内容真正深入的供应商。机构应该更重视合作伙伴的实际技术能力——诊断和解决实际问题的能力——而不是一长串可能执行得好也可能执行得不好的服务类别。 向任何白标SEO专家提出的问题 请一步一步地向我介绍一下你们的技术审核流程。 您如何决定要创作哪些内容,又基于哪些研究? 你的反向链接来自哪里?你如何审核链接质量? 您如何调整流程以适应人工智能概览和生成式搜索? 能否分享一个匿名化的前后对比作品示例? 最终判决 2026 年,Arab SEO 在白标 SEO 专家中脱颖而出,其技术和多语言方法论的深度和一致性尤为突出,特别是其对人工智能驱动搜索的准备。SEO Circular 是企业级技术工作的最佳选择,而 Triple Minds 通过其仅限代理机构的模式,在交付一致性方面提供了结构优势。 名单上的其他专家各有所长——从软件驱动的报告到大批量订单履行,再到快速的产品化交付——因此,最合适的专家取决于你通过他们处理的账户的复杂程度。 常见问题解答 什么是白标SEO专家?白标 SEO 专家是指拥有深厚的 SEO 技术和战略专业知识的个人或团队,他们代表代理机构工作,然后以自己的品牌转售最终成果。 如何评估白标SEO专家的实际技能水平?请他们详细介绍他们的技术审核流程、内容策略和链接建设方法——含糊不清的回答是一个警告信号。 选择专精于某项服务的公司还是选择提供全方位服务的公司更好?这取决于你的需求。专业服务提供商可能在较窄的服务范围内提供更深入的专业知识,而全方位服务提供商可以在一份合同下处理更广泛的客户类型。 哪家白标SEO专家最适合2026年?根据技术深度、方法论和人工智能搜索准备情况,Arab SEO 在本指南中排名第一,其次是 SEO Circular 和 Triple Minds。 QorIQ P1 设备
查看全文
IW612 bluetooth crash after a few days Hello, One of our users reported us a bug with the murata LBES5PL2EL-923 (IW612 core) bluetooth functionality, where the bluetooth stack crashes after a few days connected to a device over bluetooth static RFCOMM/SPP (The original report is public and available in Japanese at https://armadillo.atmark-techno.com/forum/armadillo/31772 ) Are there any known bugs about this? Software setup: * linux 6.12 based on lf-6.12.49-2.2.0 (exact source tree: https://github.com/atmark-techno/linux-6.12-at/tree/6.12.105-r0 ) this is a BT problem but in case it matters the wireless driver is based on mwifiex lf-6.12.49-2.2.0 * firmware updated to the latest from the imx-firmware repo at lf-6.18.20_2.0.0 https://github.com/nxp-imx/imx-firmware/tree/lf-6.18.20_2.0.0/FwImage_IW612_SD * BlueZ stack (currently confirming the exact version, sorry I forgot to ask) * the board is connected to a single device over *bluetooth classic* (not BLE), with RFCOMM/SPP. Every 60 seconds the application sends a message and gets a reply (simple polling). After a few days there is a command timeout and the BT driver restarts I've attached a firmware dump (obtained from /sys/class/bluetooth/hci0/devcoredump/data after crash happened), assuming it can be useful, there is no message in dmesg until the crash (I'm sorry it's truncated before the "Start FW dump" message so there is no timestamp for these, my understanding is that it was immediately afterwards) The FW reloading mechanism works, but this requires a reconnection so would be better addressed if possible. [ 0.000000] Linux version 6.12.105-0-at (builder@71056255c5a6) (aarch64-alpine-linux-musl-cc (Alpine 15.2.0) 15.2.0, GNU ld (GNU Binutils) 2.45.1) #1-Alpine SMP PREEMPT Mon Aug 24 07:48:35 UTC 2026 [...] [ 9.321032] wlan: version = SDIW612---18.99.8.p52-MM6X18540.p33-GPL-(FP92) [...] [ 10.349326] Bluetooth: hci0: FW already running. [ 38.303160] Bluetooth: MGMT ver 1.23 [170117.376944] Bluetooth: hci0: command tx timeout Bluetooth: hci0: ==== Start FW dump === Bluetooth: hci0: ==== FW dump complete === Bluetooth: hci0: Request Firmware: nxp/uartspi_n61x_v1.bin.se Bluetooth: hci0: FW Download Complete: 412940 bytes If there is any other information that would be useful for analysis please ask Thank you Re: IW612 bluetooth crash after a few days > 1.Is it possible to provide us the HCI logs as well as that will help to identify which command is getting timeout for which the firmware dump is getting generated. Could you clarify what you mean with this? Is there a command that can be run after the fact, or should we run hcidump or equivalent to dump all commands while the process is running? > 3.To get Wi-Fi driver loading parameters, you can provide us the: /lib/firmware/nxp/wifi_mod_para.conf We do not use this file so default parameters should be used here as well. We've reduced the log level from the default values so dmesg will not be of much help here either (I sent a link to dmesg in the previous reply) I'll check with our user if they use wifi at all during this time Re: IW612 bluetooth crash after a few days Hi, @martinetd  1.Is it possible to provide us the HCI logs as well as that will help to identify which command is getting timeout for which the firmware dump is getting generated. 2.Can you please provide the WLAN based use case as WLAN is running then check if WLAN is working fine during the firmware dump is getting generated? 3.To get Wi-Fi driver loading parameters, you can provide us the: /lib/firmware/nxp/wifi_mod_para.conf  or you can provide us a normal booting dmesg logs which including the whole process that WiFi/bluetooth loading. We can get the info from dmesg logs. 4.Currently, we do not have newer public github FW release than the one you are using: imx-firmware/FwImage_IW612_SD at lf-6.18.20_2.0.0 · nxp-imx/imx-firmware · GitHub So, I do not think this is an known issue. We prefer to have more info related to the use case and hci logs to track what happened or reproduce steps so that we can reproduce the issue locally. So if you have any further other info related to the issue, please share with us. Best regards, Christine. Re: IW612 bluetooth crash after a few days Hi @Christine_Li thank you for the quick reply > 1. If you are using btnxpuart driver, please help to provide me btnxpuart.c. We are using the btnxpuart provided in https://github.com/nxp-imx/linux-imx based on version lf-6.12.49-2.2.0 , you can find the exact file here https://github.com/atmark-techno/linux-6.12-at/blob/6.12.105-r0/drivers/bluetooth/btnxpuart.c > 2. Are you using Wi-Fi and Bluetooth/802.15.4 combo FW? Or you are using separate FW? We are using both: the wifi driver loads the combo FW at boot, and after crash the separate FW is reloaded (hence log naming the separate FW) When this crash happened the combo FW was loaded (first crash after boot) but my understanding is that it reproduces with both > 3. Can you please help to provide your Wi-Fi and Bluetooth driver load parameters? The only wifi parameter we explicitly set is drv_mode = 0x3 to disable the wifi direct interface we do not use; we do not set any bluetooth parameter. If you can tell me how to dump the exact settings I can ask our user to run commands to get the info for us. > 4.Can you please let me know your detailed reproduce steps? Since this is based on a user report I can't say much more than the description I gave (RFCOMM connection polled every 60s for a few days); I'm afraid it might depend on the actual sub device the chip is connected to. I'll try to find a device that can be pinged over RFCOMM and reproduce locally to provide you with a test script if that helps, but for now I couldn't find any release note with known bugs for the firmware/btnxpuart driver so I'd like to confirm if there is a known bug (and hopefully if you can get any information from the firmware dump) Thank you Re: IW612 bluetooth crash after a few days Hi, @martinetd  1.Are you using our nxp's btnxpuart driver for bluetooth? or you are using Linux Open Source Uart driver? If you are using btnxpuart driver, please help to provide me btnxpuart.c. 2.Are you using Wi-Fi and Bluetooth/802.15.4 combo FW? Or you are using separate FW? Because I see your log as below, so I just suspect you are using separate FW, need to double confirm with you. hci0: Request Firmware: nxp/uartspi_n61x_v1.bin.se 3.Can you please help to provide your Wi-Fi and Bluetooth driver load parameters? 4.Can you please let me know your detailed reproduce steps?  Best regards, Christine. Re: IW612 bluetooth crash after a few days > * BlueZ stack (currently confirming the exact version, sorry I forgot to ask) in case it matters, the BlueZ version is 5.82 Re: IW612 bluetooth crash after a few days Hi, @martinetd  1.For btmon: ==>Yes, if we could record the whole process for size reason, then I think the method you recommend would be a good idea. And also, we have not other better ideas than that one. 2.For FW dump: I will recommend to load driver with drvdbg=0xa0037, it can record more fw dump and also driver dump logs for analysis.   issue happened   logs will automatically save in this directory like below:   ======================================== [ 4221.173141] Create directory /data/dump_4220 error, try create dir in /var [ 4221.173147] Wakeup device... [ 4221.173231] Create directory /var/dump_4220 successfully [ 4221.173232] Directory name is /var/dump_4220 [ 4221.173233] === START DRIVER INFO DUMP=== [ 4221.173289] DRV dump data in /var/dump_4220/file_drv_info [ 4221.173306] Wakeup device... [ 4221.173889] SDIO Func0 (0x0-0x9): 43 03 06 00 07 00 00 02 03 00 [ 4221.175173] SDIO Func1 (0x4-0xb): 00 00 00 00 ff ff ff ff [ 4221.175879] SDIO Func1: (0x4c) 00 (0x50) 08 (0x54) 07 (0x55) 0c (0x58) 10 (0x59) 00 (0x5c) 00 (0x5d) 00 [ 4221.176284] SDIO Func1 (0xc0-0xca): dc fe 96 00 31 11 00 37 37 02 20 [ 4221.177301] | [ 4221.275861] SDIO Func1 (0xc0-0xca): dc fe a1 00 3b 00 00 37 37 02 20 [ 4221.276501] Drv info total bytes = 263150 (0x403ee) [ 4221.276503] === DRIVER INFO DUMP END===Wakeup device... [ 4221.276555] ==== DEBUG MODE OUTPUT START: 4220.878602 === ====================================================   If the dump is not auto-generated at "/var" or "/data" it can be collected manually using below "cat /proc/mwlan/adapter0/fw_dump > file_fw_dump" command.     2. If you check it doesn't print the directory in dmesg logs or in your case, you decrease the log level, then please get it in below way:   - echo debug_dump > /proc/mwlan/adapter0/config - Wait for some time (1 or 2 min) for fw_dump: - cat /proc/mwlan/adapter0/fw_dump > file_fw_dump for drv_dump: cat /proc/mwlan/adapter0/drv_dump > file_drv_dump   For such kind of FW crash issue, btmon log is the extended logs to better understand customer's use case and also issue scenarios. FW_dump is the most important logs for us.    And also, as discussed before, please also ask your customer about wifi use case during this test.   Best regards, Christine. Re: IW612 bluetooth crash after a few days > btmon Thank you for clarifying The crash takes a couple of days to reproduce, and I'm afraid it might not be practical to store/share a full log given how big it gets (I see 100KB after a minute so ~300MB in 2 days) Unfortunately btmon does not seem to have a "cyclic recording" mode like tcpdump, but if you're only interested in the few minutes before the crash then I can request our customer logs alternating two files every e.g. 5 minutes so we can get the last 5 minutes? Would something like (untested) be acceptable, sending the last samples? (note there is a small window between runs where events are not logged...) I=0; while ! [ -e /sys/class/bluetooth/hci0/devcoredump/data ]; do timeout 300s btmon -K -t -w log.$I; I=$((I+1%3)); done > coredump not readable Ok, this is a shame but there is not much to do about it. The file was obtained reading from /sys/class/bluetooth/hci0/devcoredump/data after the FW dump complete message, if that is not appropriate or there is a better way to get useful data I'll be happy to oblige but let's focus on the btmon traces for now. Thank you Re: IW612 bluetooth crash after a few days Ok for btmon, I will request that (and ask about wifi usage) I'd like to confirm fw dump first though: the dump I obtained was a bluetooth dump, but you seem to describe a wireless dump. In the traces from customer the wifi driver did not seem to crash, so I believe drvdbg= will not be effective there? Also in case you do need the wireless firmware in the combined firmware case (with `echo debug_dump > /proc/mwlan/adapter0/config`), the problem is that the BT driver automatically reloads a new firmware and restarts the adapter, so we would need to disable the firmware loading for this to work I agree having a dump is useful for analysis so if it's possible to fix the way the dump is obtained I'd like to know first, I'll ask our customer everything at once after we're clear on what to do Thanks Re: IW612 bluetooth crash after a few days Hi, @martinetd  Could you clarify what you mean with this? Is there a command that can be run after the fact, or should we run hcidump or equivalent to dump all commands while the process is running? ==>hci log can be captured after enabled Bluetooth/BLE with below commands: btmon -w failed_snoop.log & Then customer execute their reproduce steps, and try to reproduce this issue. The failed_snoop.log will record all of the process of bluetooth/BLE. Once issue is reproduced, we can check this log to see what kind of commands/events are executing, so that we will have some related suspects. It is not a command to run and capture the failed logs after FW crash. By the way, I requested our internal expert team help to decrypt the provided fw dump bin file: fw_devcorecump.bin, but unfortunately, it is not getting decrypted  successfully. It seems like file is corrupt or not having enough data so not able to decrypt. Best regards, Christine.
查看全文
UCM-iMX95:SDカードからYocto Linuxを起動できません – mmc0エラー-110|LinuxがSDカードを初期化できません こんにちは、私はCompuLabのUCM-iMX95を使っており、micro-SDカードからYocto Linuxをインストールして起動しようとしています。 起動プロセスが開始され、U-BootはLinuxカーネルを正常に読み込みます。しかし、LinuxはSD/MMCインターフェースの初期化に失敗します。 次のようなエラーが表示されます。 mmc0: ハードウェア割り込みを待機中にタイムアウトしました。 mmc0: sdhci: ============ SDHCI レジスタ ダンプ ============ ... mmc0: MMC カードの初期化中にエラー -110 が発生しました。その後、カーネルが起動中に停止します。 私のLinuxバージョンはLinux 6.12.34-2.0です-...基板はCompuLab UCM-iMX95です。自分でYoctoイメージを作成し、それをmicro-SDカードに書き込みます。 どなたか、このmmc0エラー-110の原因を教えていただけませんか?特に、これはハードウェア/SDカードの問題である可能性が高いですか? それともデバイスツリーに関係しているのでしょうか?UCM-iMX95のmicro-SDインターフェースに対応するMMCコントローラーはどれですか? SDインターフェースに特定のデバイスツリー設定は必要ですか? Linuxが起動する前にSDカードが検出されていることを確認するための推奨されるU-Bootコマンドはありますか?比較できる、信頼できるUCM-iMX95 Yoctoの構成はありますか? Re: UCM-iMX95: Unable to boot Yocto Linux from SD card – mmc0 error -110| Linux cannot initialize th こんにちは、 届いているエラーログは、MMCコントローラが存在しないか正しく応答していないデバイスと通信しようとしていることを示しています。推奨される解決策は、未使用のMMCインターフェースを無効にするか、DT Youの設定を修正することです。 当社のEVKリファレンスデザインデバイスツリーは、以下の構成を使用しています。 mmc0 usdhc1 eMMC mmc1 usdhc2 SD card 当社のデバイスツリーを参考にしてください: https://github.com/nxp-imx/linux-imx/blob/lf-6.18.y/arch/arm64/boot/dts/freescale/imx95-19x19-evk.dts よろしくお願いいたします。
查看全文
PIC CLB 上的 Eureka 某些 PIC MCU(例如 pic16f13145 系列)具有类似 FPGA 的可编程逻辑,称为可配置逻辑块。 我使用的 pic16f13115 有 32 个单元,每个单元都有一个 4 输入查找表和一个 D 触发器。 为了学习如何使用这些工具,今天我实现了对 6 个 LED 的 Charlieplexing 的 PWM 亮度控制支持,并进行了模拟。我使用 Verilog 来定义电路,而不是使用逻辑 CAD 画布。 我差不多有一半的时间都在用头撞墙。我慢慢地把 Verilog 代码写对了,让它能够综合(构建),然后让它能够仿真。 CLB 编程逻辑即使在 CPU 休眠状态下也能正常工作,这很棒。它非常适合功能安全至关重要的应用。例如,可用于实现复杂的触发信号逻辑。CLB 逻辑与外围输入输出的连接方式非常灵活。它比PIC单片机中一直使用的笨重的CLC可编程逻辑电路灵活得多。 概述 Re: Eureka on PIC CLB 这真是对 PIC16F13115 的 CLB 的一种非常有趣的用法!使用 Verilog 实现 6 个 LED 的 Charlieplexing 设置并配合 PWM,听起来像是学习工作流程的好方法,而且在 CPU 休眠时逻辑电路也能继续运行,这为低功耗和功能安全关键型设计开辟了一些令人印象深刻的可能性。 Re: Eureka on PIC CLB 你好, 看来该设备属于另一家制造商。 请问您能否协助我们联系贵公司制造商? 如果您有兴趣更换为带有可编程逻辑单元 (PLC) 的 NXP 设备,可以参考 LPC804。 LPC804 可编程逻辑单元 (PLU) 顺祝商祺!
查看全文
i.MX8QXP – Prevent normal boot after interrupted USB flashing on Yocto Scarthgap with A/B partitions Hi NXP Team, The installed UUU executable reports: libuuu_1.5.21-0-g1f42172 We use: sudo uuu -b emmc_all ~/Downloads/flash.bin *.wic The built-in emmc_all script writes the complete .wic image using: FB: flash -raw2sparse all _image It then writes the bootloader, configures eMMC boot selection, and finishes with FB: done. The script contains no explicit persistent flash-in-progress completion metadata handling or readback hash verification step. If flashing is interrupted during the .wic write, the cluster can subsequently boot and display the updated HMI. We suspect that an existing usable bootloader and sufficient written boot,rootfs content permit this, but the selected slot and completeness of its contents are not yet confirmed. Please advise how to add a power-loss-tolerant completion check that blocks normal boot from both slots after interrupted factory flashing, while preserving USB recovery. The metadata must remain valid independently of the full .wic write and bootloader update.
查看全文
Leading White Label SEO Specialists in the USA 2026 Handing client SEO work to an outside partner only works if that partner actually has the technical depth to back it up. Agencies don't just need a vendor — they need white label SEO specialists who understand crawl budgets, structured data, content strategy, and increasingly, how to optimize for AI-driven search, not just a company that promises rankings without a clear methodology behind them. This guide looks at the leading white label SEO experts serving US agencies in 2026, evaluated specifically on the depth of their technical and strategic capability — not just the breadth of services listed on their website. Leading White Label SEO Specialists for 2026 1. Arab SEO Arab SEO's team brings specialist-level depth across technical SEO, local SEO, ecommerce SEO, international SEO, AI SEO, and Generative Engine Optimization (GEO). What separates genuine specialists from generalist vendors is methodology — Arab SEO's approach to multilingual and AI-driven search is built on structured, repeatable processes rather than one-off tactics, which matters enormously when an agency is trusting a partner with dozens of different client accounts simultaneously. 2. SEO Circular SEO Circular's specialists focus heavily on enterprise-scale technical SEO — the kind of large, multi-thousand-page sites where a single overlooked crawl issue can suppress rankings across an entire domain. Its team's experience with international and multilingual SEO also makes it a strong choice for agencies working with clients operating across multiple countries. 3. Triple Minds Triple Minds staffs its team around agency-only fulfillment, meaning its specialists are focused entirely on execution quality rather than sales or client acquisition — a structural advantage when it comes to consistency of delivery. 4. Semify Semify's specialists have years of experience building customizable local SEO campaigns, with a process built specifically around helping smaller agencies scale their SEO offering incrementally. 5. SEOReseller SEOReseller's team specializes in fully managed fulfillment, handling the complete SEO process — technical, content, and links — with minimal need for agency involvement in day-to-day execution. 6. DashClicks DashClicks pairs its SEO specialists with a software platform built for reporting and client management, giving agencies visibility into specialist work through automated dashboards. 7. The HOTH The HOTH's specialists work within well-documented, standardized packages, making their process easy for agencies to understand and explain to clients. 8. Boostability Boostability's team has built specific expertise in delivering consistent SEO quality across a high volume of smaller accounts — a different skill set from managing a handful of large enterprise clients. 9. Vendasta Vendasta's specialists work within a broader marketplace platform, with SEO as one of several white label services agencies can access through a single team relationship. 10. FATJOE FATJOE's specialists focus on fast, productized deliverables — individual link-building or content orders completed quickly rather than an ongoing strategic engagement. What Actually Separates a Specialist From a Generic Vendor A genuine SEO specialist should be able to explain their process in specific, technical terms — not just list service categories. Watch for these signals: They can explain their technical audit process in detail — what tools they use, what specifically they check for, and how findings get prioritized. They have a documented content strategy process tied to real search intent research, not just keyword density targets. They can describe their link-building methodology clearly, including where links come from and how quality is assessed. They have a clear point of view on AI search, since this is reshaping SEO faster than any algorithm update in recent years. They can show before-and-after data from real client work, even if anonymized. Why Specialist Depth Matters More Than Service Breadth It's tempting to choose a white label partner based on how many services they list, but a provider offering ten services shallowly is often less valuable than one offering five services with genuine depth. Agencies should weigh a partner's actual technical competence — the ability to diagnose and fix real problems — more heavily than a long menu of service categories that may or may not be executed well. Questions to Ask Any White Label SEO Specialist Walk me through your technical audit process step by step. How do you decide what content to create, and based on what research? Where do your backlinks come from, and how do you vet link quality? How are you adapting your process for AI Overviews and generative search? Can you share an anonymized before-and-after example of your work? Final Verdict Arab SEO stands out among white label SEO specialists in 2026 for the depth and consistency of its technical and multilingual methodology, particularly its readiness for AI-driven search. SEO Circular is the strongest choice for enterprise-scale technical work, and Triple Minds offers a structural advantage in delivery consistency through its agency-only model. The remaining specialists on this list each bring a different kind of depth — from software-enabled reporting to high-volume fulfillment to fast, productized deliverables — so the right fit depends on the complexity of the accounts you're routing through them. Frequently Asked Questions What is a white label SEO specialist? A white label SEO specialist is an individual or team with deep technical and strategic SEO expertise, working on behalf of an agency that resells the finished work under its own brand. How do I evaluate a white label SEO expert's actual skill level? Ask them to walk through their technical audit process, content strategy, and link-building methodology in specific detail — vague answers are a warning sign. Is it better to choose a specialist or a full-service provider? It depends on your needs. A specialist may offer deeper expertise in a narrower set of services, while a full-service provider can handle a wider range of client types under one contract. Which white label SEO specialist is best for 2026? Arab SEO ranks first in this guide, followed by SEO Circular and Triple Minds, based on technical depth, methodology, and AI search readiness. QorIQ P1 Devices
查看全文
UCM-iMX95:无法从 SD 卡启动 Yocto Linux – mmc0 错误 -110 | Linux 无法初始化 SD 卡 您好,我正在使用 CompuLab UCM-iMX95,并且我正在尝试从 micro-SD 卡安装和启动 Yocto Linux。 启动过程开始,U-Boot 成功加载 Linux 内核。但是,Linux 无法初始化 SD/MMC 接口。 我收到以下错误信息: mmc0:等待硬件中断超时。 mmc0: sdhci: ============ SDHCI 寄存器转储 ============= ... mmc0:初始化 MMC 卡时出错 -110,内核随后在启动过程中卡住。 我的Linux版本是:Linux 6.12.34-2.0-...板是:CompuLab UCM-iMX95。我正在构建自己的 Yocto 镜像并将其写入 micro-SD 卡。 请问有人能帮我理解一下导致 mmc0 错误 -110 的原因吗?具体来说:这是否可能是硬件/SD卡的问题? 或者这可能与设备树有关?UCM-iMX95 上的 micro-SD 接口对应哪个 MMC 控制器? SD接口是否需要特定的设备树设置? 是否有推荐的 U-Boot 命令可以在 Linux 启动前验证 SD 卡是否被检测到?是否有已知的、性能良好的 UCM-iMX95 Yocto 配置可供我参考,以便与我的配置进行比较? Re: UCM-iMX95: Unable to boot Yocto Linux from SD card – mmc0 error -110| Linux cannot initialize th 你好, 您收到的错误日志告诉我们,MMC 控制器正在尝试与一个不存在或未正常响应的设备进行通信。建议的解决方案是禁用未使用的 MMC 接口或修复 DT 配置。 我们的 EVK 参考设计设备树采用以下配置: mmc0 usdhc1 eMMC mmc1 usdhc2 SD card 您可以参考我们的设备树: https://github.com/nxp-imx/linux-imx/blob/lf-6.18.y/arch/arm64/boot/dts/freescale/imx95-19x19-evk.dts 顺祝商祺!
查看全文