mirror of
https://github.com/RT-Thread/rt-thread.git
synced 2026-10-01 08:27:30 +08:00
[bsp][nxp] Add FRDM-MCXC162 BSP support
This commit is contained in:
@@ -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",
|
||||
|
||||
@@ -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) | ✅ | ✅ | ✅ | ✅ | ✅ | - | - | ✅ | ✅ | - | - | ✅ | ✅ | - | - | - | - | - | ✅ | - | - | - | ✅ |
|
||||
|
||||
@@ -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
@@ -0,0 +1,4 @@
|
||||
JLinkLog.txt
|
||||
JLinkSettings.ini
|
||||
project.uvoptx
|
||||
RTE/
|
||||
@@ -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"
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
@@ -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')
|
||||
@@ -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
@@ -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,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(×tamp, &date);
|
||||
#else
|
||||
gmtime_r(×tamp, &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(×tamp, &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__ */
|
||||
Reference in New Issue
Block a user