[bsp][nxp] Add FRDM-MCXC162 BSP support

This commit is contained in:
yandld
2026-09-08 16:15:20 +08:00
committed by Rbb666
parent 7fa651bd29
commit a9ce0ccbb2
47 changed files with 11597 additions and 1 deletions
+1
View File
@@ -258,6 +258,7 @@
"nxp/imx/imxrt/imxrt1180-nxp-evk/cm7",
"nxp/mcx/mcxn/frdm-mcxn947",
"nxp/mcx/mcxn/frdm-mcxn236",
"nxp/mcx/mcxc/frdm-mcxc162",
"nxp/mcx/mcxc/frdm-mcxc444",
"nxp/mcx/mcxa/frdm-mcxa153",
"nxp/mcx/mcxa/frdm-mcxa156",
+1
View File
@@ -197,6 +197,7 @@ This document is based on the RT-Thread mainline repository and categorizes the
| [frdm-mcxa153](nxp/mcx/mcxa/frdm-mcxa153) | ✅ | ✅ | ✅ | - | - | - | ✅ | ✅ | ✅ | - | - | ✅ | - | - | - | - | - | - | ✅ | - | - | - | ✅ |
| [frdm-mcxa156](nxp/mcx/mcxa/frdm-mcxa156) | ✅ | ✅ | ✅ | - | - | - | - | ✅ | ✅ | - | - | ✅ | ✅ | - | ✅ | - | - | - | ✅ | - | - | - | ✅ |
| [frdm-mcxa346](nxp/mcx/mcxa/frdm-mcxa346) | ✅ | ✅ | ✅ | - | - | - | - | ✅ | ✅ | - | - | ✅ | ✅ | - | - | - | - | - | ✅ | - | - | - | ✅ |
| [frdm-mcxc162](nxp/mcx/mcxc/frdm-mcxc162) | ✅ | ✅ | - | - | - | - | - | ✅ | ✅ | - | - | ✅ | ✅ | - | - | - | - | - | ✅ | - | - | - | ✅ |
| [frdm-mcxc444](nxp/mcx/mcxc/frdm-mcxc444) | ✅ | ✅ | - | - | - | - | - | ✅ | ✅ | - | - | ✅ | ✅ | - | - | - | - | - | ✅ | - | - | - | ✅ |
| [frdm-mcxe247](nxp/mcx/mcxe/frdm-mcxe247) | ✅ | ✅ | ✅ | - | - | - | - | ✅ | ✅ | - | - | ✅ | ✅ | - | - | - | - | - | ✅ | - | - | - | ✅ |
| [frdm-mcxn236](nxp/mcx/mcxn/frdm-mcxn236) | ✅ | ✅ | ✅ | ✅ | ✅ | - | - | ✅ | ✅ | - | - | ✅ | ✅ | - | - | - | - | - | ✅ | - | - | - | ✅ |
+1
View File
@@ -13,6 +13,7 @@ NXP 系列 BSP 目前支持情况如下表所示:
| [frdm-mcxa346](mcx/mcxa/frdm-mcxa346) | NXP 官方 FRDM-MCXA346 开发板 |
| [frdm-mcxa344](mcx/mcxa/frdm-mcxa344) | NXP 官方 FRDM-MCXA344 开发板 |
| **MCXC 系列** | |
| [frdm-mcxc162](mcx/mcxc/frdm-mcxc162) | NXP 官方 FRDM-MCXC162 开发板 |
| [frdm-mcxc444](mcx/mcxc/frdm-mcxc444) | NXP 官方 FRDM-MCXC444 开发板 |
| **LPC 系列** | |
| [lpc43xx](lpc/lpc43xx) | NXP LPC43xx 系列开发板 |
@@ -0,0 +1,23 @@
peripheral.communication:
scons_arg: &scons
- '--strict'
kconfig:
- CONFIG_BSP_USING_UART1=y
- CONFIG_BSP_USING_UART2=y
- CONFIG_BSP_USING_I2C=y
- CONFIG_BSP_USING_I2C0=y
- CONFIG_BSP_USING_SPI=y
- CONFIG_BSP_USING_SPI0=y
peripheral.timing_control:
scons_arg: *scons
kconfig:
- CONFIG_RT_USING_EVENT=y
- CONFIG_RT_USING_ALARM=y
- CONFIG_BSP_USING_RTC=y
- CONFIG_BSP_USING_WDT=y
- CONFIG_BSP_USING_CLOCK_TIMER=y
- CONFIG_BSP_USING_CTIMER0=y
- CONFIG_BSP_USING_CTIMER1=y
- CONFIG_BSP_USING_PWM=y
- CONFIG_BSP_USING_PWM0=y
File diff suppressed because it is too large Load Diff
+4
View File
@@ -0,0 +1,4 @@
JLinkLog.txt
JLinkSettings.ini
project.uvoptx
RTE/
+15
View File
@@ -0,0 +1,15 @@
mainmenu "RT-Thread Configuration"
BSP_DIR := .
RTT_DIR := ../../../../..
PKGS_DIR := packages
config SOC_MCX
bool
select ARCH_ARM_CORTEX_M23
default y
source "$(RTT_DIR)/Kconfig"
osource "$PKGS_DIR/Kconfig"
rsource "../libraries/Kconfig"
rsource "board/Kconfig"
+188
View File
@@ -0,0 +1,188 @@
# FRDM-MCXC162 BSP
## Overview
This BSP targets the production FRDM-MCXC162 board fitted with an
`MCXC162VFT` Cortex-M23 MCU. The core runs from the 72 MHz FRO with no FPU,
TrustZone, or MPU enabled.
The linker uses only the 64 KiB Program Flash at `0x00000000` and 12 KiB SRAM
at `0x20000000`. The non-contiguous Data Flash at `0x0001C000` is not part of
the program image.
## Supported interfaces
| RT-Thread device | Peripheral | Board pins | Default |
| --- | --- | --- | --- |
| `pin` | GPIO0-GPIO3 | `GET_PINS(port, pin)` | Enabled |
| `uart0` | LPUART0 | P0_2 RX, P0_3 TX | Enabled, console |
| `uart1` | LPUART1 | P2_12 RX, P2_13 TX | Disabled |
| `uart2` | LPUART2 | P3_13 RX, P3_12 TX | Disabled |
| `i2c0` | LPI2C0 | P3_27 SCL, P3_28 SDA | Disabled |
| `spi0` | LPSPI0 | P3_10 SCK, P3_8 SDO, P3_9 SDI, P3_11 software CS | Disabled |
| `rtc` | RTC0 | Internal | Disabled |
| `wdt` | WWDT0 | Internal | Disabled |
| `timer0`, `timer1` | CTIMER0, CTIMER1 | Internal | Disabled |
| `pwm0` channel 0/1 | FLEXPWM0 SM0 A/B | P3_0, P3_1 | Disabled |
The two PWM channels share one period. Changing the period while the other
channel is enabled returns `-RT_EINVAL`.
UART3, LPADC0, DMA, Data Flash, TRDC, low-power modes, and tickless operation
are outside this BSP version.
## Build
Install or update the NXP MCX CMSIS and series packages first:
```console
pkgs --update
```
Set `RTT_EXEC_PATH` to the compiler binary directory, then build:
```console
set RTT_CC=gcc
set RTT_EXEC_PATH=C:\path\to\arm-none-eabi\bin
scons -j8
```
The primary GCC baseline is Arm GNU Toolchain 14.2 from MCUXpresso IDE 25.06.
GCC 10.3.1 is retained as a compatibility build. Keil MDK 5.43a with
`MCXC162_DFP 26.06.00` and IAR EWARM 9.70.4 are the SDK 26.06 reference
versions.
The final generated projects are verified with Keil MDK 5.42 and Arm Compiler
6.23, and with IAR EWARM 9.60.3.422. The SDK reference Keil 5.43a and IAR
9.70.4 versions have not been repeated locally.
Project files can be regenerated with:
```console
set RTT_CC=keil
scons --target=mdk5
set RTT_CC=iar
scons --target=iar
```
Build the generated `project.uvprojx` with `uVision.com` and `project.ewp` with
`IarBuild.exe`; the `template.*` files are generator inputs, not build targets.
```console
uVision.com -b project.uvprojx -j0
IarBuild.exe project.ewp -build Debug
```
## Default behavior
The default configuration provides a 1 kHz system tick and a 115200-8-N-1
`uart0` console with MSH. The active-low red LED on P2_3 toggles every 500 ms.
No periodic application log is emitted.
Run `button_irq_test`, then press both SW2 and SW3 during its 10-second window.
It must report non-zero falling-edge interrupt counts for both buttons. The wait
also provides a simple observable check of the 1 kHz RT-Thread tick.
Run `reboot` and confirm that the banner and MSH prompt return after a software
reset; use the RESET button for the matching hardware-reset check.
The validation commands below are compiled only when their corresponding
optional BSP driver is enabled. They add no code to the default PIN + UART0
image.
Build the two CI validation configurations with:
```console
scons --attach=peripheral.communication
scons -j8
scons --attach=default
scons --attach=peripheral.timing_control
scons -j8
scons --attach=default
```
## Peripheral validation commands
Use `uart0` for the MSH console while testing the other UARTs.
| Test | Wiring | Command | Pass criterion |
| --- | --- | --- | --- |
| UART1 | Jumper Arduino D1/P2_13 TX to D0/P2_12 RX | `uart_loop uart1` | `PASS` after an 8-byte 115200-8-N-1 loopback |
| UART2 | Jumper mikroBUS TX/P3_12 to RX/P3_13 | `uart_loop uart2` | `PASS` after an 8-byte 115200-8-N-1 loopback |
| P3T1755 | None; the sensor is already connected to P3_27 SCL and P3_28 SDA | `p3t1755` | Address `0x48` acknowledges and one temperature is printed |
| SPI0 | Jumper Arduino D11/P3_8 SDO to D12/P3_9 SDI; probe D13/P3_10 SCK and D10/P3_11 CS | `spi_loop` | `PASS`; the analyzer also shows mode 0, 1 MHz SCK, and active-low CS |
| CTIMER0 | None | `ctimer0_test` | The RT-Thread clock-time backend reports one 100 ms one-shot completion |
| CTIMER1 | None | `ctimer_test timer1 oneshot`, then `ctimer_test timer1 periodic` | One interrupt, then 4-6 interrupts in 550 ms |
`timer0` is opened exclusively by the RT-Thread clock-time subsystem and must
not be opened or controlled as a regular timer device. Use `timer1` for direct
one-shot and periodic device tests.
P3_11 is driven as the RT-Thread software chip select. LPSPI uses an unrouted
internal PCS, so P3_11 remains asserted across compound SPI messages. This BSP
supports active-low software chip select only.
`p3t1755` sends the temperature-register pointer and the two-byte read as one
two-message transaction. The bus therefore emits a repeated START, as required
by ERR053261.
The v1 I2C adapter requires each `rt_i2c_transfer()` call to begin with START
and end with STOP. A first-message `RT_I2C_NO_START` or final-message
`RT_I2C_NO_STOP` request is rejected. `RT_I2C_NO_START` is accepted only when
joining consecutive writes to the same addressed slave.
WWDT tests must be run separately after each reset. `wwdt refresh` starts a
3-second watchdog and refreshes it once per second without periodic output; let
it run for at least 10 seconds and press RESET to end the test. `wwdt timeout`
does not refresh the watchdog: the MCU must reset in about 3 seconds, and the
next boot must report `last reset was caused by WWDT0`.
RTC set/get and PWM control reuse the standard MSH commands:
```console
date 2026 9 3 12 0 0
date
rtc_alarm_test
pwm probe pwm0
pwm set 0 1000000 250000
pwm enable 0
pwm set 1 1000000 500000
pwm enable 1
pwm get 0
pwm get 1
pwm disable 0
pwm disable 1
```
`rtc_alarm_test` requires `RT_USING_ALARM` and must report `PASS` after about
3 seconds. For PWM, probe Arduino D5/P3_0 (channel 0) and D6/P3_1 (channel 1)
against GND; expect 1 kHz at 25% and 50% duty respectively. While channel 0 is
enabled, `pwm set 1 2000000 1000000` must return `-RT_EINVAL` and must not
change the shared 1 ms period.
## Hardware validation
The following checks have been completed on a production FRDM-MCXC162 Rev 1:
- banner, MSH, red LED, SW2 P3_14 and SW3 P3_29 interrupts, reset behavior,
1 kHz tick, and a 10-minute run;
- UART1/UART2 loopback;
- the onboard P3T1755 at address `0x48` and temperature reads on `i2c0`;
- SPI0 SDO-to-SDI loopback, including SCK and CS;
- RTC time/alarm, WWDT refresh and timeout reset, CTIMER one-shot/periodic,
and PWM frequency, duty, start/stop, and shared-period rejection;
- download, startup, tick, console, and GPIO with both Keil and IAR.
For MCXC162 erratum ERR053261, do not issue consecutive LPI2C read commands
without a STOP/START or repeated START between them.
Board programming and the MCUXpresso IDE debug configuration are performed by
the board owner.
## References
- [FRDM-MCXC162 board](https://www.nxp.com/design/design-center/development-boards-and-designs/FRDM-MCXC162)
- [MCXC162 data sheet](https://www.nxp.com/docs/en/data-sheet/MCXCP048M072F20.pdf)
- [MCXC162 errata](https://www.nxp.com/docs/en/errata/MCXC162VFT_0P18R.pdf)
- [NXP MCXC162 device files](https://github.com/nxp-mcuxpresso/mcux-devices-mcx/tree/main/MCXC/MCXC162)
- [MCUX SDK 26.06 release notes](https://docs.mcuxpresso.nxp.com/mcuxsdk/26.06.00/html/boards/MCX/frdmmcxc162/releaseNotes/rnindex.html)
+172
View File
@@ -0,0 +1,172 @@
# FRDM-MCXC162 BSP 说明
## 简介
本 BSP 面向量产版 FRDM-MCXC162,固定使用 `MCXC162VFT` Cortex-M23,内核运行
在 72 MHz FRO;不启用 FPU、TrustZone 和 MPU。
链接器只使用 `0x00000000` 起始的 64 KiB Program Flash,以及
`0x20000000` 起始的 12 KiB SRAM。位于 `0x0001C000` 的非连续 Data Flash 不会
拼入程序区。
## 支持接口
| RT-Thread 设备 | 芯片外设 | 板级引脚 | 默认状态 |
| --- | --- | --- | --- |
| `pin` | GPIO0-GPIO3 | `GET_PINS(port, pin)` | 开启 |
| `uart0` | LPUART0 | P0_2 RX、P0_3 TX | 开启,作为控制台 |
| `uart1` | LPUART1 | P2_12 RX、P2_13 TX | 关闭 |
| `uart2` | LPUART2 | P3_13 RX、P3_12 TX | 关闭 |
| `i2c0` | LPI2C0 | P3_27 SCL、P3_28 SDA | 关闭 |
| `spi0` | LPSPI0 | P3_10 SCK、P3_8 SDO、P3_9 SDI、P3_11 软件 CS | 关闭 |
| `rtc` | RTC0 | 内部 | 关闭 |
| `wdt` | WWDT0 | 内部 | 关闭 |
| `timer0`、`timer1` | CTIMER0、CTIMER1 | 内部 | 关闭 |
| `pwm0` 通道 0/1 | FLEXPWM0 SM0 A/B | P3_0、P3_1 | 关闭 |
PWM 两个通道共用周期。另一通道已经启用时,如果提交不同周期,驱动返回
`-RT_EINVAL`。
本版不支持 UART3、LPADC0、DMA、Data Flash、TRDC、低功耗和 tickless。
## 编译
先安装或更新 NXP MCX CMSIS 与 series package:
```console
pkgs --update
```
将 `RTT_EXEC_PATH` 指向编译器的可执行文件目录后编译:
```console
set RTT_CC=gcc
set RTT_EXEC_PATH=C:\path\to\arm-none-eabi\bin
scons -j8
```
主 GCC 基线为 MCUXpresso IDE 25.06 内置 Arm GNU Toolchain 14.2;另用 GCC
10.3.1 做兼容回归。SDK 26.06 的参考版本是 Keil MDK 5.43a(配合
`MCXC162_DFP 26.06.00`)和 IAR EWARM 9.70.4。工程可重新生成:
最终生成工程已使用 Keil MDK 5.42 + Arm Compiler 6.23 和 IAR EWARM
9.60.3.422 完成验证。本地未重复 SDK 参考版本 Keil 5.43a 与 IAR 9.70.4 的验证。
```console
set RTT_CC=keil
scons --target=mdk5
set RTT_CC=iar
scons --target=iar
```
Keil 应构建生成的 `project.uvprojx`,IAR 应构建生成的 `project.ewp`;
`template.*` 仅是工程生成器输入,不是构建目标。
```console
uVision.com -b project.uvprojx -j0
IarBuild.exe project.ewp -build Debug
```
## 默认运行现象
默认配置提供 1 kHz 系统 tick、115200-8-N-1 的 `uart0` 控制台和 MSH。低有效
红灯 P2_3 每 500 ms 翻转一次,应用不输出周期日志。
执行 `button_irq_test`,并在 10 秒窗口内分别按下 SW2 和 SW3;命令必须报告两键
都有非零下降沿中断计数。该等待窗口也可直观检查 RT-Thread 的 1 kHz tick。
执行 `reboot` 后,banner 和 MSH 提示符必须在软件复位后重新出现;硬复位则使用
板载 RESET 键做同样检查。
以下验收命令只在对应的可选 BSP 驱动开启后参与编译;默认 PIN + UART0 固件
不会带入额外测试代码。
两组 CI 验收配置可按下列命令构建:
```console
scons --attach=peripheral.communication
scons -j8
scons --attach=default
scons --attach=peripheral.timing_control
scons -j8
scons --attach=default
```
## 外设验收命令
测试其他 UART 时,继续用 `uart0` 作为 MSH 控制台。
| 项目 | 接线 | 命令 | 通过判据 |
| --- | --- | --- | --- |
| UART1 | Arduino D1/P2_13 TX 短接 D0/P2_12 RX | `uart_loop uart1` | 115200-8-N-1 回环 8 字节并输出 `PASS` |
| UART2 | mikroBUS TX/P3_12 短接 RX/P3_13 | `uart_loop uart2` | 115200-8-N-1 回环 8 字节并输出 `PASS` |
| P3T1755 | 无需接线;板载器件已连接 P3_27 SCL、P3_28 SDA | `p3t1755` | `0x48` 应答并打印一次温度 |
| SPI0 | Arduino D11/P3_8 SDO 短接 D12/P3_9 SDI;在 D13/P3_10 SCK、D10/P3_11 CS 测量 | `spi_loop` | 输出 `PASS`,且波形为 mode 0、1 MHz SCK、低有效 CS |
| CTIMER0 | 无需接线 | `ctimer0_test` | RT-Thread clock-time 后端完成一次 100 ms 单次定时 |
| CTIMER1 | 无需接线 | `ctimer_test timer1 oneshot`,再运行 `ctimer_test timer1 periodic` | 单次模式 1 次中断;周期模式 550 ms 内 4-6 次中断 |
`timer0` 由 RT-Thread clock-time 子系统独占打开,不能作为普通定时器设备再次
打开或控制。直接验证单次/周期设备接口时使用 `timer1`。
P3_11 由 RT-Thread 软件控制片选;LPSPI 内部改用未路由的 PCS,因此复合 SPI
消息之间 P3_11 会保持有效。本 BSP 只支持低有效软件片选。
`p3t1755` 把温度寄存器指针写入和两字节读取放在同一个双消息事务中,线上会
产生 repeated START,满足 ERR053261 的要求。
v1 I2C 适配要求每次 `rt_i2c_transfer()` 以 START 开始、以 STOP 结束;若首条
消息设置 `RT_I2C_NO_START`,或末条消息设置 `RT_I2C_NO_STOP`,请求会被拒绝。
仅发往同一地址的连续写消息允许使用 `RT_I2C_NO_START` 拼接。
WWDT 两种测试应分别在复位后执行。`wwdt refresh` 启动 3 秒看门狗并每秒喂狗,
期间没有周期输出;至少稳定运行 10 秒后按 RESET 结束。`wwdt timeout` 不喂狗,
MCU 应在约 3 秒后复位,下一次启动应打印
`last reset was caused by WWDT0`。
RTC set/get 和 PWM 控制直接复用 RT-Thread 标准 MSH 命令:
```console
date 2026 9 3 12 0 0
date
rtc_alarm_test
pwm probe pwm0
pwm set 0 1000000 250000
pwm enable 0
pwm set 1 1000000 500000
pwm enable 1
pwm get 0
pwm get 1
pwm disable 0
pwm disable 1
```
`rtc_alarm_test` 还需开启 `RT_USING_ALARM`,约 3 秒后应输出 `PASS`。PWM 测量点
为 Arduino D5/P3_0(通道 0)和 D6/P3_1(通道 1),相对 GND 应分别得到 1 kHz、
25% 和 50% 占空比。通道 0 已启用时执行
`pwm set 1 2000000 1000000`,必须返回 `-RT_EINVAL`,共享的 1 ms 周期不得改变。
## 实板验收
以下验证已在量产版 FRDM-MCXC162 Rev 1 实板上完成:
- banner、MSH、红灯、SW2 P3_14/SW3 P3_29 中断、软硬复位、1 kHz tick 和
10 分钟稳定运行;
- UART1/UART2 跳线回环;
- `i2c0` 上板载 P3T1755 地址 `0x48` 应答及温度读取;
- SPI0 SDO→SDI 回环,并检查 SCK/CS;
- RTC 走时/alarm、WWDT refresh/故意超时复位、CTIMER 单次/周期模式,以及
PWM 频率、占空比、启停和共享周期拒绝;
- Keil 与 IAR 分别完成下载、启动、tick、console 和 GPIO 验证。
针对 MCXC162 勘误 ERR053261,连续 LPI2C 读命令之间必须插入 STOP/START 或
repeated START。
实板烧写及 MCUXpresso IDE 下载配置由板卡使用者完成。
## 参考资料
- [FRDM-MCXC162 官方页](https://www.nxp.com/design/design-center/development-boards-and-designs/FRDM-MCXC162)
- [MCXC162 数据手册](https://www.nxp.com/docs/en/data-sheet/MCXCP048M072F20.pdf)
- [MCXC162 芯片勘误](https://www.nxp.com/docs/en/errata/MCXC162VFT_0P18R.pdf)
- [NXP MCXC162 device 文件](https://github.com/nxp-mcuxpresso/mcux-devices-mcx/tree/main/MCXC/MCXC162)
- [MCUX SDK 26.06 release notes](https://docs.mcuxpresso.nxp.com/mcuxsdk/26.06.00/html/boards/MCX/frdmmcxc162/releaseNotes/rnindex.html)
+12
View File
@@ -0,0 +1,12 @@
import os
from building import *
cwd = GetCurrentDir()
objs = []
for name in os.listdir(cwd):
path = os.path.join(cwd, name)
if os.path.isfile(os.path.join(path, 'SConscript')):
objs += SConscript(os.path.join(name, 'SConscript'))
Return('objs')
+67
View File
@@ -0,0 +1,67 @@
import os
import sys
import rtconfig
if os.getenv('RTT_ROOT'):
RTT_ROOT = os.getenv('RTT_ROOT')
else:
RTT_ROOT = os.path.normpath(os.getcwd() + '/../../../../..')
sys.path.append(os.path.join(RTT_ROOT, 'tools'))
try:
from building import *
except ImportError:
print('Cannot find the RT-Thread root directory:')
print(RTT_ROOT)
exit(-1)
def bsp_pkg_check():
package_files = [
os.path.join(rtconfig.NXP_MCX_CMSIS_ROOT, 'Core', 'Include', 'core_cm23.h'),
os.path.join(rtconfig.NXP_MCX_SERIES_ROOT, 'MCXC162', 'gcc', 'MCXC162_flash.ld'),
]
if not all(os.path.isfile(path) for path in package_files):
print('Required NXP packages are missing. Run pkgs --update first.')
exit(1)
RegisterPreBuildingAction(bsp_pkg_check)
TARGET = 'rtthread.' + rtconfig.TARGET_EXT
env = Environment(
tools=['mingw'],
AS=rtconfig.AS,
ASFLAGS=rtconfig.AFLAGS,
CC=rtconfig.CC,
CFLAGS=rtconfig.CFLAGS,
CXX=rtconfig.CXX,
CXXFLAGS=rtconfig.CXXFLAGS,
AR=rtconfig.AR,
ARFLAGS='-rc',
LINK=rtconfig.LINK,
LINKFLAGS=rtconfig.LFLAGS,
CXXCOM='$CXX -o $TARGET -c $CXXFLAGS $_CCCOMCOM $SOURCES',
)
env.PrependENVPath('PATH', rtconfig.EXEC_PATH)
if rtconfig.PLATFORM == 'iccarm':
env.Replace(CCCOM=['$CC $CFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS -o $TARGET $SOURCES'])
env.Replace(ARFLAGS=[])
env.Replace(LINKCOM=env['LINKCOM'] + ' --map rtthread.map')
Export('RTT_ROOT')
Export('rtconfig')
SDK_ROOT = os.path.abspath('.')
libraries_path = SDK_ROOT + '/libraries' if os.path.exists(SDK_ROOT + '/libraries') else os.path.dirname(SDK_ROOT) + '/libraries'
SDK_LIB = libraries_path
Export('SDK_LIB')
objs = PrepareBuilding(env, RTT_ROOT, has_libcpu=False)
if rtconfig.PLATFORM == 'iccarm':
env.Replace(ASCOM='$AS $ASFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS -o $TARGET $SOURCES')
objs.extend(SConscript(os.path.join(libraries_path, 'drivers', 'SConscript'),
variant_dir='build/libraries/drivers', duplicate=0))
DoBuilding(TARGET, objs)
@@ -0,0 +1,14 @@
from building import *
cwd = GetCurrentDir()
src = ['main.c']
if (GetDepend('BSP_USING_UART1') or GetDepend('BSP_USING_UART2') or
GetDepend('BSP_USING_I2C0') or GetDepend('BSP_USING_SPI0') or
GetDepend('BSP_USING_RTC') or GetDepend('BSP_USING_WDT') or
GetDepend('BSP_USING_CLOCK_TIMER')):
src += ['peripheral_test.c']
group = DefineGroup('Applications', src, depend=[''], CPPPATH=[cwd])
Return('group')
@@ -0,0 +1,83 @@
/*
* Copyright (c) 2006-2026, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <rtdevice.h>
#include "board.h"
#ifdef RT_USING_FINSH
#include <finsh.h>
static volatile rt_uint32_t sw2_irq_count;
static volatile rt_uint32_t sw3_irq_count;
static void button_irq(void *args)
{
(*(volatile rt_uint32_t *)args)++;
}
static int button_irq_test(void)
{
rt_err_t result;
rt_uint32_t sw2_count;
rt_uint32_t sw3_count;
sw2_irq_count = 0;
sw3_irq_count = 0;
rt_pin_mode(SW2_PIN, PIN_MODE_INPUT_PULLUP);
rt_pin_mode(SW3_PIN, PIN_MODE_INPUT_PULLUP);
result = rt_pin_attach_irq(SW2_PIN, PIN_IRQ_MODE_FALLING,
button_irq, (void *)&sw2_irq_count);
if (result != RT_EOK)
{
return result;
}
result = rt_pin_attach_irq(SW3_PIN, PIN_IRQ_MODE_FALLING,
button_irq, (void *)&sw3_irq_count);
if (result != RT_EOK)
{
rt_pin_detach_irq(SW2_PIN);
return result;
}
rt_pin_irq_enable(SW2_PIN, PIN_IRQ_ENABLE);
rt_pin_irq_enable(SW3_PIN, PIN_IRQ_ENABLE);
rt_kprintf("Press SW2 and SW3 within 10 seconds\n");
rt_thread_mdelay(10000);
rt_pin_irq_enable(SW2_PIN, PIN_IRQ_DISABLE);
rt_pin_irq_enable(SW3_PIN, PIN_IRQ_DISABLE);
rt_pin_detach_irq(SW2_PIN);
rt_pin_detach_irq(SW3_PIN);
sw2_count = sw2_irq_count;
sw3_count = sw3_irq_count;
rt_kprintf("%s: SW2=%u, SW3=%u interrupt(s)\n",
sw2_count != 0U && sw3_count != 0U ? "PASS" : "FAIL",
(unsigned int)sw2_count, (unsigned int)sw3_count);
return sw2_count != 0U && sw3_count != 0U ? RT_EOK : -RT_ERROR;
}
MSH_CMD_EXPORT(button_irq_test, count SW2 and SW3 falling-edge interrupts for 10 seconds);
static void reboot(void)
{
rt_hw_cpu_reset();
}
MSH_CMD_EXPORT(reboot, reset the MCU);
#endif
int main(void)
{
rt_pin_write(LED_RED_PIN, PIN_HIGH);
rt_pin_mode(LED_RED_PIN, PIN_MODE_OUTPUT);
while (1)
{
rt_pin_write(LED_RED_PIN, !rt_pin_read(LED_RED_PIN));
rt_thread_mdelay(500);
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,96 @@
menu "Hardware Drivers Config"
config SOC_MCXC162
bool
select RT_USING_COMPONENTS_INIT
select RT_USING_USER_MAIN
default y
menu "On-chip Peripheral Drivers"
config BSP_USING_PIN
bool "Enable GPIO"
select RT_USING_PIN
default y
menuconfig BSP_USING_UART
bool "Enable LPUART"
select RT_USING_SERIAL
default y
if BSP_USING_UART
config BSP_USING_UART0
bool "Enable LPUART0 as uart0"
default y
config BSP_USING_UART1
bool "Enable LPUART1 as uart1"
default n
config BSP_USING_UART2
bool "Enable LPUART2 as uart2"
default n
endif
menuconfig BSP_USING_I2C
bool "Enable LPI2C"
select RT_USING_I2C
default n
if BSP_USING_I2C
config BSP_USING_I2C0
bool "Enable LPI2C0 as i2c0"
default y
endif
menuconfig BSP_USING_SPI
bool "Enable LPSPI"
select BSP_USING_PIN
select RT_USING_SPI
default n
if BSP_USING_SPI
config BSP_USING_SPI0
bool "Enable LPSPI0 as spi0"
default y
endif
config BSP_USING_RTC
bool "Enable RTC0 as rtc"
select RT_USING_RTC
default n
config BSP_USING_WDT
bool "Enable WWDT0 as wdt"
select RT_USING_WDT
default n
menuconfig BSP_USING_CLOCK_TIMER
bool "Enable CTIMER hardware timers"
select RT_USING_CLOCK_TIME
default n
if BSP_USING_CLOCK_TIMER
config BSP_USING_CTIMER0
bool "Enable CTIMER0 as timer0"
default y
config BSP_USING_CTIMER1
bool "Enable CTIMER1 as timer1"
depends on BSP_USING_CTIMER0
default n
endif
menuconfig BSP_USING_PWM
bool "Enable FLEXPWM"
select RT_USING_PWM
default n
if BSP_USING_PWM
config BSP_USING_PWM0
bool "Enable FLEXPWM0 SM0 as pwm0"
default y
endif
endmenu
endmenu
@@ -0,0 +1,29 @@
/*
* Copyright 2026 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "clock_config.h"
#include "fsl_clock.h"
void BOARD_InitBootClocks(void)
{
BOARD_BootClockFROHF72M();
}
void BOARD_BootClockFROHF72M(void)
{
/* One wait state is required before raising the core clock to 72 MHz. */
FMU0->FCTRL = (FMU0->FCTRL & ~FMU_FCTRL_RWSC_MASK) | FMU_FCTRL_RWSC(1U);
CLOCK_SetClockDiv(kCLOCK_DivFRO_LF, 1U);
CLOCK_SetupFRO12MClocking();
CLOCK_SetClockDiv(kCLOCK_DivFRO_HF, 1U);
CLOCK_SetupFROHFClocking(BOARD_BOOTCLOCKFROHF72M_CORE_CLOCK);
CLOCK_SetClockDiv(kCLOCK_DivAHBCLK, 1U);
CLOCK_AttachClk(kFRO_HF_to_MAIN_CLK);
SystemCoreClock = BOARD_BOOTCLOCKFROHF72M_CORE_CLOCK;
}
@@ -0,0 +1,17 @@
/*
* Copyright 2026 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _CLOCK_CONFIG_H_
#define _CLOCK_CONFIG_H_
#include "fsl_common.h"
#define BOARD_BOOTCLOCKFROHF72M_CORE_CLOCK 72000000U
void BOARD_InitBootClocks(void);
void BOARD_BootClockFROHF72M(void);
#endif
@@ -0,0 +1,135 @@
/*
* Copyright 2026 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "pin_mux.h"
#include "fsl_clock.h"
#include "fsl_gpio.h"
#include "fsl_port.h"
#include "fsl_reset.h"
#include "rtconfig.h"
static void configure_pin(PORT_Type *port, uint32_t pin, port_mux_t mux,
uint16_t pull, uint16_t drive)
{
const port_pin_config_t config = {
.pullSelect = pull,
.pullValueSelect = kPORT_LowPullResistor,
.slewRate = kPORT_FastSlewRate,
.passiveFilterEnable = kPORT_PassiveFilterDisable,
.openDrainEnable = kPORT_OpenDrainDisable,
.driveStrength = drive,
.driveStrength1 = kPORT_NormalDriveStrength,
.mux = mux,
.inputBuffer = kPORT_InputBufferEnable,
.invertInput = kPORT_InputNormal,
.lockRegister = kPORT_UnlockRegister,
};
PORT_SetPinConfig(port, pin, &config);
}
#ifdef BSP_USING_UART0
static void init_uart0_pins(void)
{
CLOCK_EnableClock(kCLOCK_GatePORT0);
RESET_ReleasePeripheralReset(kPORT0_RST_SHIFT_RSTn);
RESET_ReleasePeripheralReset(kLPUART0_RST_SHIFT_RSTn);
configure_pin(PORT0, 2U, kPORT_MuxAlt2, kPORT_PullDisable, kPORT_HighDriveStrength);
configure_pin(PORT0, 3U, kPORT_MuxAlt2, kPORT_PullUp, kPORT_LowDriveStrength);
}
#endif
#ifdef BSP_USING_UART1
static void init_uart1_pins(void)
{
CLOCK_EnableClock(kCLOCK_GatePORT2);
RESET_ReleasePeripheralReset(kPORT2_RST_SHIFT_RSTn);
RESET_ReleasePeripheralReset(kLPUART1_RST_SHIFT_RSTn);
configure_pin(PORT2, 12U, kPORT_MuxAlt3, kPORT_PullDisable, kPORT_LowDriveStrength);
configure_pin(PORT2, 13U, kPORT_MuxAlt3, kPORT_PullDisable, kPORT_LowDriveStrength);
}
#endif
#ifdef BSP_USING_UART2
static void init_uart2_pins(void)
{
CLOCK_EnableClock(kCLOCK_GatePORT3);
RESET_ReleasePeripheralReset(kPORT3_RST_SHIFT_RSTn);
RESET_ReleasePeripheralReset(kLPUART2_RST_SHIFT_RSTn);
configure_pin(PORT3, 12U, kPORT_MuxAlt3, kPORT_PullDisable, kPORT_LowDriveStrength);
configure_pin(PORT3, 13U, kPORT_MuxAlt3, kPORT_PullDisable, kPORT_LowDriveStrength);
}
#endif
#ifdef BSP_USING_I2C0
static void init_i2c0_pins(void)
{
CLOCK_EnableClock(kCLOCK_GatePORT3);
RESET_ReleasePeripheralReset(kPORT3_RST_SHIFT_RSTn);
RESET_ReleasePeripheralReset(kLPI2C0_RST_SHIFT_RSTn);
configure_pin(PORT3, 27U, kPORT_MuxAlt2, kPORT_PullDisable, kPORT_LowDriveStrength);
configure_pin(PORT3, 28U, kPORT_MuxAlt2, kPORT_PullDisable, kPORT_LowDriveStrength);
}
#endif
#ifdef BSP_USING_SPI0
static void init_spi0_pins(void)
{
const gpio_pin_config_t cs_config = {
.pinDirection = kGPIO_DigitalOutput,
.outputLogic = 1U,
};
CLOCK_EnableClock(kCLOCK_GatePORT3);
RESET_ReleasePeripheralReset(kPORT3_RST_SHIFT_RSTn);
RESET_ReleasePeripheralReset(kLPSPI0_RST_SHIFT_RSTn);
configure_pin(PORT3, 8U, kPORT_MuxAlt2, kPORT_PullDisable, kPORT_LowDriveStrength);
configure_pin(PORT3, 9U, kPORT_MuxAlt2, kPORT_PullDisable, kPORT_LowDriveStrength);
configure_pin(PORT3, 10U, kPORT_MuxAlt2, kPORT_PullDisable, kPORT_LowDriveStrength);
configure_pin(PORT3, 11U, kPORT_MuxAsGpio, kPORT_PullDisable, kPORT_LowDriveStrength);
GPIO_PinInit(GPIO3, 11U, &cs_config);
}
#endif
#ifdef BSP_USING_PWM0
static void init_pwm0_pins(void)
{
CLOCK_EnableClock(kCLOCK_GatePORT3);
RESET_ReleasePeripheralReset(kPORT3_RST_SHIFT_RSTn);
RESET_ReleasePeripheralReset(kFLEXPWM0_RST_SHIFT_RSTn);
configure_pin(PORT3, 0U, kPORT_MuxAlt5, kPORT_PullDisable, kPORT_LowDriveStrength);
configure_pin(PORT3, 1U, kPORT_MuxAlt5, kPORT_PullDisable, kPORT_LowDriveStrength);
}
#endif
void BOARD_InitBootPins(void)
{
#ifdef BSP_USING_UART0
init_uart0_pins();
#endif
#ifdef BSP_USING_UART1
init_uart1_pins();
#endif
#ifdef BSP_USING_UART2
init_uart2_pins();
#endif
#ifdef BSP_USING_I2C0
init_i2c0_pins();
#endif
#ifdef BSP_USING_SPI0
init_spi0_pins();
#endif
#ifdef BSP_USING_PWM0
init_pwm0_pins();
#endif
}
@@ -0,0 +1,12 @@
/*
* Copyright 2026 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _PIN_MUX_H_
#define _PIN_MUX_H_
void BOARD_InitBootPins(void);
#endif
@@ -0,0 +1,25 @@
Import('rtconfig')
from building import *
cwd = GetCurrentDir()
src = Split('''
board.c
MCUX_Config/board/clock_config.c
MCUX_Config/board/pin_mux.c
''')
linkflags = ''
if rtconfig.PLATFORM == 'armclang':
linkflags = ' --keep *.o(.rti_fn.*) --keep *.o(FSymTab) --keep *.o(VSymTab)'
group = DefineGroup(
'Drivers',
src,
depend=[''],
CPPPATH=[cwd, cwd + '/MCUX_Config/board'],
CPPDEFINES=['CPU_MCXC162VFT'],
LINKFLAGS=linkflags,
)
Return('group')
@@ -0,0 +1,59 @@
/*
* Copyright (c) 2006-2026, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <rthw.h>
#include <rtthread.h>
#include "board.h"
#include "pin_mux.h"
void SysTick_Handler(void)
{
rt_interrupt_enter();
rt_tick_increase();
rt_interrupt_leave();
}
void rt_hw_board_init(void)
{
BOARD_InitBootPins();
BOARD_InitBootClocks();
SysTick_Config(SystemCoreClock / RT_TICK_PER_SECOND);
NVIC_SetPriority(PendSV_IRQn, (1U << __NVIC_PRIO_BITS) - 1U);
#ifdef RT_USING_HEAP
rt_system_heap_init(HEAP_BEGIN, HEAP_END);
#endif
#ifdef RT_USING_COMPONENTS_INIT
rt_components_board_init();
#endif
#if defined(RT_USING_CONSOLE) && defined(RT_USING_DEVICE)
rt_console_set_device(RT_CONSOLE_DEVICE_NAME);
#endif
}
void rt_hw_us_delay(rt_uint32_t us)
{
uint32_t cycles = SystemCoreClock / 1000000U * us;
uint32_t start = SysTick->VAL;
uint32_t elapsed = 0;
uint32_t reload = SysTick->LOAD + 1U;
while (elapsed < cycles)
{
uint32_t now = SysTick->VAL;
elapsed += (start >= now) ? (start - now) : (start + reload - now);
start = now;
}
}
void rt_hw_cpu_reset(void)
{
NVIC_SystemReset();
}
@@ -0,0 +1,44 @@
/*
* Copyright (c) 2006-2026, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef __BOARD_H__
#define __BOARD_H__
#include <rtthread.h>
#include "clock_config.h"
#include "fsl_common.h"
#define GET_PINS(port, pin) ((port) * 32 + (pin))
#define LED_RED_PIN GET_PINS(2, 3)
#define LED_GREEN_PIN GET_PINS(2, 7)
#define LED_BLUE_PIN GET_PINS(1, 10)
#define SW2_PIN GET_PINS(3, 14)
#define SW3_PIN GET_PINS(3, 29)
#if defined(__ARMCC_VERSION)
extern int Image$$ARM_LIB_HEAP$$ZI$$Base;
extern int Image$$ARM_LIB_STACK$$ZI$$Base;
#define HEAP_BEGIN ((void *)&Image$$ARM_LIB_HEAP$$ZI$$Base)
#define HEAP_END ((void *)&Image$$ARM_LIB_STACK$$ZI$$Base)
#elif defined(__ICCARM__)
#pragma section = "HEAP"
#define HEAP_BEGIN (__segment_end("HEAP"))
extern void __RTT_HEAP_END;
#define HEAP_END (&__RTT_HEAP_END)
#elif defined(__GNUC__)
extern int __HeapBase;
extern int __HeapLimit;
#define HEAP_BEGIN ((void *)&__HeapBase)
#define HEAP_END ((void *)&__HeapLimit)
#endif
void rt_hw_board_init(void);
void rt_hw_us_delay(rt_uint32_t us);
void rt_hw_cpu_reset(void);
#endif
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<workspace>
<project>
<path>$WS_DIR$\project.ewp</path>
</project>
<batchBuild/>
</workspace>
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+134
View File
@@ -0,0 +1,134 @@
import os
ARCH = 'arm'
CPU = 'cortex-m23'
CROSS_TOOL = os.getenv('RTT_CC', 'gcc')
BOARD_NAME = 'frdm-mcxc162'
BSP_LIBRARY_TYPE = 'MCXC162'
EXEC_PATH = os.getenv('RTT_EXEC_PATH', '')
BUILD = 'debug'
def _resolve_package_path(package_name, marker):
bsp_root = os.path.dirname(os.path.abspath(__file__))
search_roots = ['libraries', os.path.join('..', 'libraries'), 'packages']
for search_root in search_roots:
package_path = os.path.join(search_root, package_name)
if os.path.isfile(os.path.join(bsp_root, package_path, marker)):
return package_path.replace('\\', '/')
return os.path.join('packages', package_name).replace('\\', '/')
NXP_MCX_CMSIS_ROOT = _resolve_package_path('nxp-mcx-cmsis-latest', 'Core/Include/core_cm23.h')
NXP_MCX_SERIES_ROOT = _resolve_package_path('nxp-mcx-series-latest', 'MCXC162/gcc/MCXC162_flash.ld')
if CROSS_TOOL == 'gcc':
PLATFORM = 'gcc'
elif CROSS_TOOL == 'keil':
PLATFORM = 'armclang'
elif CROSS_TOOL == 'iar':
PLATFORM = 'iccarm'
else:
raise RuntimeError('Unsupported toolchain: ' + CROSS_TOOL)
if PLATFORM == 'gcc':
PREFIX = 'arm-none-eabi-'
CC = PREFIX + 'gcc'
CXX = PREFIX + 'g++'
AS = PREFIX + 'gcc'
AR = PREFIX + 'ar'
LINK = PREFIX + 'gcc'
TARGET_EXT = 'elf'
SIZE = PREFIX + 'size'
OBJDUMP = PREFIX + 'objdump'
OBJCPY = PREFIX + 'objcopy'
STRIP = PREFIX + 'strip'
DEVICE = ' -mcpu=cortex-m23 -mthumb -mfloat-abi=soft -ffunction-sections -fdata-sections'
CFLAGS = DEVICE + ' -Wall -std=c99'
CXXFLAGS = DEVICE + ' -Wall -fno-exceptions -fno-rtti'
AFLAGS = ' -c' + DEVICE + ' -x assembler-with-cpp'
LFLAGS = DEVICE
LFLAGS += ' -specs=nano.specs -specs=nosys.specs'
LFLAGS += ' -Wl,--gc-sections,-Map=rtthread.map,--print-memory-usage'
LFLAGS += ' -T"' + NXP_MCX_SERIES_ROOT + '/MCXC162/gcc/MCXC162_flash.ld"'
if BUILD == 'debug':
CFLAGS += ' -Os -gdwarf-2'
CXXFLAGS += ' -Os -gdwarf-2'
AFLAGS += ' -gdwarf-2'
else:
CFLAGS += ' -Os'
CXXFLAGS += ' -Os'
POST_ACTION = OBJCPY + ' -O binary $TARGET rtthread.bin\n' + SIZE + ' $TARGET\n'
CPATH = ''
LPATH = ''
M_CFLAGS = CFLAGS + ' -mlong-calls -fPIC'
M_CXXFLAGS = CXXFLAGS + ' -mlong-calls -fPIC'
M_LFLAGS = DEVICE + ' -shared -fPIC -nostartfiles -static-libgcc -Wl,--gc-sections,-z,max-page-size=0x4'
M_POST_ACTION = STRIP + ' -R .hash $TARGET\n' + SIZE + ' $TARGET\n'
elif PLATFORM == 'armclang':
CC = 'armclang'
CXX = 'armclang'
AS = 'armasm'
AR = 'armar'
LINK = 'armlink'
TARGET_EXT = 'axf'
DEVICE = ' --cpu Cortex-M23'
CFLAGS = ' --target=arm-arm-none-eabi -mcpu=cortex-m23 -mfloat-abi=soft'
CFLAGS += ' -funsigned-char -fshort-enums -fshort-wchar -ffunction-sections -std=c99'
CXXFLAGS = ' --target=arm-arm-none-eabi -mcpu=cortex-m23 -mfloat-abi=soft'
CXXFLAGS += ' -funsigned-char -fshort-enums -fshort-wchar -ffunction-sections -fno-exceptions -fno-rtti'
AFLAGS = DEVICE + ' --apcs=interwork'
LFLAGS = DEVICE + ' --strict --info sizes --info totals --info unused --info veneers'
LFLAGS += ' --list rtthread.map'
LFLAGS += ' --scatter "' + NXP_MCX_SERIES_ROOT + '/MCXC162/arm/MCXC162_flash.scf"'
if BUILD == 'debug':
CFLAGS += ' -O1 -g -gdwarf-3'
CXXFLAGS += ' -O1 -g -gdwarf-3'
AFLAGS += ' -g'
else:
CFLAGS += ' -O2'
CXXFLAGS += ' -O2'
POST_ACTION = 'fromelf --bin $TARGET --output rtthread.bin\nfromelf -z $TARGET'
elif PLATFORM == 'iccarm':
CC = 'iccarm'
CXX = 'iccarm'
AS = 'iasmarm'
AR = 'iarchive'
LINK = 'ilinkarm'
TARGET_EXT = 'out'
dlib_config = os.path.normpath(os.path.join(EXEC_PATH, '..', 'inc', 'c', 'DLib_Config_Normal.h'))
CFLAGS = ' --cpu=Cortex-M23 --fpu=None --endian=little -e'
CFLAGS += ' --dlib_config "' + dlib_config + '" --diag_suppress Pa050'
CXXFLAGS = CFLAGS
AFLAGS = ' -s+ -r --cpu Cortex-M23 --fpu None'
LFLAGS = ' --config "' + NXP_MCX_SERIES_ROOT + '/MCXC162/iar/MCXC162_flash.icf"'
LFLAGS += ' --redirect _Printf=_PrintfTiny --redirect _Scanf=_ScanfSmall'
LFLAGS += ' --entry __iar_program_start'
if BUILD == 'debug':
CFLAGS += ' --debug -On'
CXXFLAGS += ' --debug -On'
else:
CFLAGS += ' -Oh'
CXXFLAGS += ' -Oh'
POST_ACTION = 'ielftool --bin $TARGET rtthread.bin'
def dist_handle(BSP_ROOT, dist_dir):
import sys
sys.path.append(os.path.join(os.path.dirname(BSP_ROOT), '..', 'tools'))
from sdk_dist import dist_do_building
dist_do_building(BSP_ROOT, dist_dir)
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
-1
View File
@@ -1,5 +1,4 @@
config SOC_MCX
bool
select ARCH_ARM_CORTEX_M0
select PKG_USING_NXP_MCX_CMSIS_DRIVER
select PKG_USING_NXP_MCX_SERIES_DRIVER
@@ -2,6 +2,10 @@ from building import *
cwd = GetCurrentDir()
if GetDepend('SOC_MCXC162'):
group = SConscript('mcxc162/SConscript')
Return('group')
src = []
if GetDepend('BSP_USING_PIN'):
@@ -0,0 +1,32 @@
from building import *
cwd = GetCurrentDir()
src = []
if GetDepend('BSP_USING_PIN'):
src += ['drv_pin.c']
if GetDepend('BSP_USING_UART'):
src += ['drv_uart.c']
if GetDepend('BSP_USING_I2C'):
src += ['drv_i2c.c']
if GetDepend('BSP_USING_SPI'):
src += ['drv_spi.c']
if GetDepend('BSP_USING_RTC'):
src += ['drv_rtc.c']
if GetDepend('BSP_USING_WDT'):
src += ['drv_wdt.c']
if GetDepend('BSP_USING_CLOCK_TIMER'):
src += ['drv_hwtimer.c']
if GetDepend('BSP_USING_PWM'):
src += ['drv_pwm.c']
group = DefineGroup('Drivers', src, depend=[''], CPPPATH=[cwd])
Return('group')
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,12 @@
/*
* Copyright (c) 2006-2026, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef __DRV_MCXC162_HWTIMER_H__
#define __DRV_MCXC162_HWTIMER_H__
int rt_hw_hwtimer_init(void);
#endif /* __DRV_MCXC162_HWTIMER_H__ */
@@ -0,0 +1,185 @@
/*
* Copyright (c) 2006-2026, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <rtdevice.h>
#include "fsl_clock.h"
#include "fsl_lpi2c.h"
#if defined(RT_USING_I2C) && defined(BSP_USING_I2C0)
#define MCXC162_LPI2C_READ_CHUNK 256U
#define MCXC162_LPI2C_START_CMD LPI2C_MTDR_CMD(4U)
#define MCXC162_I2C_UNSUPPORTED (RT_I2C_ADDR_10BIT | RT_I2C_IGNORE_NACK | RT_I2C_NO_READ_ACK)
static struct rt_i2c_bus_device i2c0_bus;
static status_t mcxc162_i2c_wait_tx_ready(void)
{
uint32_t flags;
status_t status;
do
{
flags = LPI2C_MasterGetStatusFlags(LPI2C0);
status = LPI2C_MasterCheckAndClearError(LPI2C0, flags);
if (status != kStatus_Success)
{
return status;
}
} while ((flags & (uint32_t)kLPI2C_MasterTxReadyFlag) == 0U);
return kStatus_Success;
}
static status_t mcxc162_i2c_restart(const struct rt_i2c_msg *msg)
{
lpi2c_direction_t direction;
status_t status;
status = mcxc162_i2c_wait_tx_ready();
if (status != kStatus_Success)
{
return status;
}
direction = (msg->flags & RT_I2C_RD) != 0U ? kLPI2C_Read : kLPI2C_Write;
LPI2C0->MTDR = MCXC162_LPI2C_START_CMD |
((uint32_t)msg->addr << 1U) | (uint32_t)direction;
return kStatus_Success;
}
static status_t mcxc162_i2c_transfer_message(const struct rt_i2c_msg *msg)
{
rt_size_t offset = 0U;
rt_size_t remaining = msg->len;
rt_size_t chunk;
status_t status;
if ((msg->flags & RT_I2C_RD) == 0U)
{
if (remaining == 0U)
{
return kStatus_Success;
}
return LPI2C_MasterSend(LPI2C0, msg->buf, remaining);
}
while (remaining != 0U)
{
chunk = remaining > MCXC162_LPI2C_READ_CHUNK ? MCXC162_LPI2C_READ_CHUNK : remaining;
if (offset != 0U)
{
status = mcxc162_i2c_restart(msg);
if (status != kStatus_Success)
{
return status;
}
}
status = LPI2C_MasterReceive(LPI2C0, &msg->buf[offset], chunk);
if (status != kStatus_Success)
{
return status;
}
offset += chunk;
remaining -= chunk;
}
return kStatus_Success;
}
static rt_ssize_t mcxc162_i2c_xfer(struct rt_i2c_bus_device *bus,
struct rt_i2c_msg msgs[], rt_uint32_t num)
{
rt_uint32_t i;
status_t status;
if (num == 0U || (msgs[0].flags & RT_I2C_NO_START) != 0U ||
(msgs[num - 1U].flags & RT_I2C_NO_STOP) != 0U)
{
return 0;
}
for (i = 0U; i < num; i++)
{
if ((msgs[i].flags & MCXC162_I2C_UNSUPPORTED) != 0U)
{
return 0;
}
if (i != 0U && (msgs[i].flags & RT_I2C_NO_START) != 0U &&
(((msgs[i - 1U].flags | msgs[i].flags) & RT_I2C_RD) != 0U ||
msgs[i - 1U].addr != msgs[i].addr))
{
return 0;
}
}
if (bus->config.usage_freq != bus->config.max_hz)
{
LPI2C_MasterSetBaudRate(LPI2C0, CLOCK_GetLpi2cClkFreq(0U), bus->config.max_hz);
bus->config.usage_freq = bus->config.max_hz;
}
LPI2C_MasterEnable(LPI2C0, true);
LPI2C_SlaveEnable(LPI2C0, false);
status = LPI2C_MasterStart(LPI2C0, msgs[0].addr,
(msgs[0].flags & RT_I2C_RD) != 0U ? kLPI2C_Read : kLPI2C_Write);
if (status != kStatus_Success)
{
return 0;
}
for (i = 0U; i < num; i++)
{
if (i != 0U && (msgs[i].flags & RT_I2C_NO_START) == 0U)
{
/* ERR053261 requires a START between consecutive receive commands. */
status = mcxc162_i2c_restart(&msgs[i]);
}
if (status == kStatus_Success)
{
status = mcxc162_i2c_transfer_message(&msgs[i]);
}
if (status != kStatus_Success)
{
break;
}
}
if (LPI2C_MasterStop(LPI2C0) != kStatus_Success)
{
return 0;
}
return status == kStatus_Success ? num : i;
}
static const struct rt_i2c_bus_device_ops mcxc162_i2c_ops = {
.master_xfer = mcxc162_i2c_xfer,
};
int rt_hw_i2c_init(void)
{
lpi2c_master_config_t config;
CLOCK_SetClockDiv(kCLOCK_DivLPI2C0, 1U);
CLOCK_AttachClk(kFRO_LF_DIV_to_LPI2C0);
LPI2C_MasterGetDefaultConfig(&config);
config.baudRate_Hz = 100000U;
LPI2C_MasterInit(LPI2C0, &config, CLOCK_GetLpi2cClkFreq(0U));
i2c0_bus.config.max_hz = config.baudRate_Hz;
i2c0_bus.config.usage_freq = config.baudRate_Hz;
i2c0_bus.ops = &mcxc162_i2c_ops;
return rt_i2c_bus_device_register(&i2c0_bus, "i2c0");
}
INIT_DEVICE_EXPORT(rt_hw_i2c_init);
#endif /* RT_USING_I2C && BSP_USING_I2C0 */
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,16 @@
/*
* Copyright (c) 2006-2026, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef __DRV_PIN_MCXC162_H__
#define __DRV_PIN_MCXC162_H__
#include <rtdevice.h>
#define GET_PINS(port, pin) ((port) * 32 + (pin))
int rt_hw_pin_init(void);
#endif /* __DRV_PIN_MCXC162_H__ */
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,12 @@
/*
* Copyright (c) 2006-2026, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef __DRV_MCXC162_PWM_H__
#define __DRV_MCXC162_PWM_H__
int rt_hw_pwm_init(void);
#endif /* __DRV_MCXC162_PWM_H__ */
@@ -0,0 +1,176 @@
/*
* Copyright (c) 2006-2026, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2026-09-03 Alex Yang Add MCXC162 RTC0 support
*/
#include <rtthread.h>
#include <rtdevice.h>
#include <sys/time.h>
#include "fsl_clock.h"
#include "fsl_rtc.h"
#ifdef BSP_USING_RTC
static rt_rtc_dev_t mcxc162_rtc;
static rt_err_t mcxc162_rtc_init(void)
{
rtc_config_t config;
CLOCK_SetupFRO16KClocking(kCLOCK_Clk16kToSysAndCore);
RTC_GetDefaultConfig(&config);
RTC_Init(RTC0, &config);
RTC_StartTimer(RTC0);
return RT_EOK;
}
static rt_err_t mcxc162_rtc_get_secs(time_t *seconds)
{
*seconds = (time_t)RTC0->TSR;
return RT_EOK;
}
static rt_err_t mcxc162_rtc_set_secs(time_t *seconds)
{
if ((rt_uint64_t)*seconds > 0xFFFFFFFFULL)
{
return -RT_EINVAL;
}
RTC_StopTimer(RTC0);
RTC0->TSR = (uint32_t)*seconds;
RTC_StartTimer(RTC0);
#ifdef RT_USING_ALARM
rt_alarm_update(&mcxc162_rtc.parent, 1U);
#endif
return RT_EOK;
}
static rt_err_t mcxc162_rtc_get_alarm(struct rt_rtc_wkalarm *alarm)
{
time_t timestamp = (time_t)RTC0->TAR;
struct tm date;
#ifdef RT_ALARM_USING_LOCAL_TIME
localtime_r(&timestamp, &date);
#else
gmtime_r(&timestamp, &date);
#endif
alarm->enable = (RTC_GetEnabledInterrupts(RTC0) & kRTC_AlarmInterruptEnable) != 0U;
alarm->tm_sec = date.tm_sec;
alarm->tm_min = date.tm_min;
alarm->tm_hour = date.tm_hour;
alarm->tm_mday = date.tm_mday;
alarm->tm_mon = date.tm_mon;
alarm->tm_year = date.tm_year;
return RT_EOK;
}
static rt_err_t mcxc162_rtc_set_alarm(struct rt_rtc_wkalarm *alarm)
{
rtc_datetime_t date;
struct tm calendar = {
.tm_sec = alarm->tm_sec,
.tm_min = alarm->tm_min,
.tm_hour = alarm->tm_hour,
.tm_mday = alarm->tm_mday,
.tm_mon = alarm->tm_mon,
.tm_year = alarm->tm_year,
};
#ifdef RT_ALARM_USING_LOCAL_TIME
time_t timestamp;
#endif
if (!alarm->enable)
{
RTC_DisableInterrupts(RTC0, kRTC_AlarmInterruptEnable);
DisableIRQ(RTC_IRQn);
RTC_ClearStatusFlags(RTC0, kRTC_AlarmFlag);
return RT_EOK;
}
#ifdef RT_ALARM_USING_LOCAL_TIME
calendar.tm_isdst = -1;
timestamp = mktime(&calendar);
if (timestamp == (time_t)-1)
{
return -RT_EINVAL;
}
gmtime_r(&timestamp, &calendar);
#endif
date.second = (uint8_t)calendar.tm_sec;
date.minute = (uint8_t)calendar.tm_min;
date.hour = (uint8_t)calendar.tm_hour;
date.day = (uint8_t)calendar.tm_mday;
date.month = (uint8_t)(calendar.tm_mon + 1);
date.year = (uint16_t)(calendar.tm_year + 1900);
if (RTC_SetAlarm(RTC0, &date) != kStatus_Success || RTC0->TAR <= RTC0->TSR)
{
RTC_DisableInterrupts(RTC0, kRTC_AlarmInterruptEnable);
DisableIRQ(RTC_IRQn);
RTC_ClearStatusFlags(RTC0, kRTC_AlarmFlag);
return -RT_EINVAL;
}
RTC_ClearStatusFlags(RTC0, kRTC_AlarmFlag);
RTC_EnableInterrupts(RTC0, kRTC_AlarmInterruptEnable);
NVIC_ClearPendingIRQ(RTC_IRQn);
EnableIRQ(RTC_IRQn);
return RT_EOK;
}
static const struct rt_rtc_ops mcxc162_rtc_ops = {
.init = mcxc162_rtc_init,
.get_secs = mcxc162_rtc_get_secs,
.set_secs = mcxc162_rtc_set_secs,
.get_alarm = mcxc162_rtc_get_alarm,
.set_alarm = mcxc162_rtc_set_alarm,
.get_timeval = RT_NULL,
.set_timeval = RT_NULL,
};
void RTC_IRQHandler(void)
{
rt_interrupt_enter();
if ((RTC_GetStatusFlags(RTC0) & kRTC_AlarmFlag) != 0U)
{
RTC_ClearStatusFlags(RTC0, kRTC_AlarmFlag);
#ifdef RT_USING_ALARM
rt_alarm_update(&mcxc162_rtc.parent, 1U);
#endif
}
rt_interrupt_leave();
SDK_ISR_EXIT_BARRIER;
}
int rt_hw_rtc_init(void)
{
rt_err_t result;
mcxc162_rtc.ops = &mcxc162_rtc_ops;
result = rt_hw_rtc_register(&mcxc162_rtc, "rtc", RT_DEVICE_FLAG_RDWR, RT_NULL);
if (result != RT_EOK)
{
return result;
}
return rt_device_init(&mcxc162_rtc.parent);
}
INIT_DEVICE_EXPORT(rt_hw_rtc_init);
#endif /* BSP_USING_RTC */
@@ -0,0 +1,12 @@
/*
* Copyright (c) 2006-2026, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef __DRV_MCXC162_RTC_H__
#define __DRV_MCXC162_RTC_H__
int rt_hw_rtc_init(void);
#endif /* __DRV_MCXC162_RTC_H__ */
@@ -0,0 +1,145 @@
/*
* Copyright (c) 2006-2026, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <rtdevice.h>
#include "drv_spi.h"
#include "fsl_clock.h"
#include "fsl_lpspi.h"
#if defined(RT_USING_SPI) && defined(BSP_USING_SPI0)
#define MCXC162_LPSPI_INTERNAL_PCS kLPSPI_Pcs3
#define MCXC162_LPSPI_INTERNAL_PCS_FLAG kLPSPI_MasterPcs3
static struct rt_spi_bus spi0_bus;
rt_err_t rt_hw_spi_device_attach(const char *bus_name, const char *device_name,
rt_base_t cs_pin)
{
struct rt_spi_device *device = rt_calloc(1U, sizeof(*device));
rt_err_t result;
if (device == RT_NULL)
{
return -RT_ENOMEM;
}
if (cs_pin != PIN_NONE)
{
rt_pin_write(cs_pin, PIN_HIGH);
}
result = rt_spi_bus_attach_device_cspin(device, device_name, bus_name,
cs_pin, RT_NULL);
if (result != RT_EOK)
{
rt_free(device);
}
return result;
}
static rt_err_t mcxc162_spi_configure(struct rt_spi_device *device,
struct rt_spi_configuration *cfg)
{
lpspi_master_config_t config;
uint32_t period_ns;
(void)device;
if ((cfg->mode & (RT_SPI_SLAVE | RT_SPI_3WIRE | RT_SPI_READY |
RT_SPI_CS_HIGH)) != 0U ||
(cfg->data_width != 8U && cfg->data_width != 16U) || cfg->max_hz == 0U)
{
return -RT_EINVAL;
}
LPSPI_MasterGetDefaultConfig(&config);
config.baudRate = cfg->max_hz;
config.bitsPerFrame = cfg->data_width;
config.cpol = (cfg->mode & RT_SPI_CPOL) != 0U ? kLPSPI_ClockPolarityActiveLow : kLPSPI_ClockPolarityActiveHigh;
config.cpha = (cfg->mode & RT_SPI_CPHA) != 0U ? kLPSPI_ClockPhaseSecondEdge : kLPSPI_ClockPhaseFirstEdge;
config.direction = (cfg->mode & RT_SPI_MSB) != 0U ? kLPSPI_MsbFirst : kLPSPI_LsbFirst;
config.whichPcs = MCXC162_LPSPI_INTERNAL_PCS;
config.pcsActiveHighOrLow = kLPSPI_PcsActiveLow;
period_ns = 1000000000U / cfg->max_hz;
config.pcsToSckDelayInNanoSec = period_ns / 2U;
config.lastSckToPcsDelayInNanoSec = period_ns / 2U;
config.betweenTransferDelayInNanoSec = period_ns / 2U;
LPSPI_MasterInit(LPSPI0, &config, CLOCK_GetLpspiClkFreq(0U));
return RT_EOK;
}
static void mcxc162_spi_set_cs(struct rt_spi_device *device, rt_bool_t active)
{
rt_uint8_t level;
if (device->cs_pin == PIN_NONE || (device->config.mode & RT_SPI_NO_CS) != 0U)
{
return;
}
level = (device->config.mode & RT_SPI_CS_HIGH) != 0U ? PIN_HIGH : PIN_LOW;
rt_pin_write(device->cs_pin, active ? level : !level);
}
static rt_ssize_t mcxc162_spi_xfer(struct rt_spi_device *device,
struct rt_spi_message *message)
{
lpspi_transfer_t transfer = {
.txData = message->send_buf,
.rxData = message->recv_buf,
.dataSize = message->length,
.configFlags = MCXC162_LPSPI_INTERNAL_PCS_FLAG | kLPSPI_MasterPcsContinuous,
};
status_t status = kStatus_Success;
if (message->cs_take != 0U)
{
mcxc162_spi_set_cs(device, true);
}
if (message->length != 0U)
{
status = LPSPI_MasterTransferBlocking(LPSPI0, &transfer);
}
if (status != kStatus_Success)
{
mcxc162_spi_set_cs(device, false);
return -RT_EIO;
}
if (message->cs_release != 0U)
{
mcxc162_spi_set_cs(device, false);
}
return (rt_ssize_t)message->length;
}
static const struct rt_spi_ops mcxc162_spi_ops = {
.configure = mcxc162_spi_configure,
.xfer = mcxc162_spi_xfer,
};
int rt_hw_spi_init(void)
{
lpspi_master_config_t config;
CLOCK_SetClockDiv(kCLOCK_DivLPSPI0, 1U);
CLOCK_AttachClk(kFRO_LF_DIV_to_LPSPI0);
LPSPI_MasterGetDefaultConfig(&config);
LPSPI_MasterInit(LPSPI0, &config, CLOCK_GetLpspiClkFreq(0U));
return rt_spi_bus_register(&spi0_bus, "spi0", &mcxc162_spi_ops);
}
INIT_DEVICE_EXPORT(rt_hw_spi_init);
#endif /* RT_USING_SPI && BSP_USING_SPI0 */
@@ -0,0 +1,16 @@
/*
* Copyright (c) 2006-2026, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef __DRV_SPI_MCXC162_H__
#define __DRV_SPI_MCXC162_H__
#include <rtdevice.h>
rt_err_t rt_hw_spi_device_attach(const char *bus_name, const char *device_name,
rt_base_t cs_pin);
int rt_hw_spi_init(void);
#endif /* __DRV_SPI_MCXC162_H__ */
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,12 @@
/*
* Copyright (c) 2006-2026, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef __DRV_UART_MCXC162_H__
#define __DRV_UART_MCXC162_H__
int rt_hw_uart_init(void);
#endif /* __DRV_UART_MCXC162_H__ */
@@ -0,0 +1,138 @@
/*
* Copyright (c) 2006-2026, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2026-09-03 Alex Yang Add MCXC162 WWDT0 support
*/
#include <rtthread.h>
#include <rtdevice.h>
#include "fsl_clock.h"
#include "fsl_wwdt.h"
#ifdef BSP_USING_WDT
#define DBG_TAG "drv.wwdt"
#define DBG_LVL DBG_INFO
#include <rtdbg.h>
#define MCXC162_WWDT_DEFAULT_TIMEOUT 5U
struct mcxc162_wwdt
{
rt_watchdog_t watchdog;
rt_uint32_t timeout;
rt_bool_t started;
};
static struct mcxc162_wwdt mcxc162_wwdt = {
.timeout = MCXC162_WWDT_DEFAULT_TIMEOUT,
};
static uint32_t mcxc162_wwdt_ticks_per_second(void)
{
return CLOCK_GetWwdtClkFreq() / 4U;
}
static rt_err_t mcxc162_wwdt_set_timeout(rt_uint32_t timeout)
{
uint64_t count = (uint64_t)mcxc162_wwdt_ticks_per_second() * timeout;
if ((timeout == 0U) || (count > WWDT_TC_COUNT_MASK))
{
return -RT_EINVAL;
}
mcxc162_wwdt.timeout = timeout;
if (mcxc162_wwdt.started)
{
WWDT_SetTimeoutValue(WWDT0, (uint32_t)count);
WWDT_Refresh(WWDT0);
}
return RT_EOK;
}
static rt_err_t mcxc162_wwdt_init(rt_watchdog_t *watchdog)
{
RT_UNUSED(watchdog);
CLOCK_SetClockDiv(kCLOCK_DivWWDT0, 1U);
return RT_EOK;
}
static rt_err_t mcxc162_wwdt_control(rt_watchdog_t *watchdog, int command, void *argument)
{
rt_uint32_t *value = (rt_uint32_t *)argument;
RT_UNUSED(watchdog);
switch (command)
{
case RT_DEVICE_CTRL_WDT_GET_TIMEOUT:
*value = mcxc162_wwdt.timeout;
return RT_EOK;
case RT_DEVICE_CTRL_WDT_SET_TIMEOUT:
return mcxc162_wwdt_set_timeout(*value);
case RT_DEVICE_CTRL_WDT_GET_TIMELEFT:
*value = (WWDT0->TV + mcxc162_wwdt_ticks_per_second() - 1U) /
mcxc162_wwdt_ticks_per_second();
return RT_EOK;
case RT_DEVICE_CTRL_WDT_KEEPALIVE:
WWDT_Refresh(WWDT0);
return RT_EOK;
case RT_DEVICE_CTRL_WDT_START:
if (!mcxc162_wwdt.started)
{
wwdt_config_t config;
WWDT_GetDefaultConfig(&config);
config.enableWatchdogReset = true;
config.timeoutValue = mcxc162_wwdt_ticks_per_second() * mcxc162_wwdt.timeout;
config.clockFreq_Hz = CLOCK_GetWwdtClkFreq();
WWDT_Init(WWDT0, &config);
mcxc162_wwdt.started = RT_TRUE;
}
else
{
WWDT_Refresh(WWDT0);
}
return RT_EOK;
case RT_DEVICE_CTRL_WDT_STOP:
return -RT_ENOSYS;
default:
return -RT_EINVAL;
}
}
static const struct rt_watchdog_ops mcxc162_wwdt_ops = {
.init = mcxc162_wwdt_init,
.control = mcxc162_wwdt_control,
};
int rt_hw_wdt_init(void)
{
mcxc162_wwdt.watchdog.ops = &mcxc162_wwdt_ops;
if ((CMC->SRS & CMC_SRS_WWDT0_MASK) != 0U)
{
LOG_I("last reset was caused by WWDT0");
}
return rt_hw_watchdog_register(&mcxc162_wwdt.watchdog, "wdt",
RT_DEVICE_FLAG_DEACTIVATE, RT_NULL);
}
INIT_DEVICE_EXPORT(rt_hw_wdt_init);
#endif /* BSP_USING_WDT */
@@ -0,0 +1,12 @@
/*
* Copyright (c) 2006-2026, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef __DRV_MCXC162_WDT_H__
#define __DRV_MCXC162_WDT_H__
int rt_hw_wdt_init(void);
#endif /* __DRV_MCXC162_WDT_H__ */