From cf562270006e9fc71d270c81648859745142db6c Mon Sep 17 00:00:00 2001 From: yandld <1453363089@qq.com> Date: Tue, 3 Sep 2024 17:25:23 +0800 Subject: [PATCH] [bsp][mcxc] add rtc/wdog/uart driver --- bsp/nxp/mcx/mcxc/Libraries/drivers/drv_rtc.c | 116 ++++++++++++++++++ bsp/nxp/mcx/mcxc/Libraries/drivers/drv_rtc.h | 19 +++ bsp/nxp/mcx/mcxc/Libraries/drivers/drv_uart.c | 85 +++++++++---- bsp/nxp/mcx/mcxc/Libraries/drivers/drv_wdt.c | 92 ++++++++++++++ bsp/nxp/mcx/mcxc/Libraries/drivers/drv_wdt.h | 19 +++ bsp/nxp/mcx/mcxc/frdm-mcxc444/board/Kconfig | 4 +- .../board/MCUX_Config/board/pin_mux.c | 27 ++-- 7 files changed, 319 insertions(+), 43 deletions(-) create mode 100644 bsp/nxp/mcx/mcxc/Libraries/drivers/drv_rtc.c create mode 100644 bsp/nxp/mcx/mcxc/Libraries/drivers/drv_rtc.h create mode 100644 bsp/nxp/mcx/mcxc/Libraries/drivers/drv_wdt.c create mode 100644 bsp/nxp/mcx/mcxc/Libraries/drivers/drv_wdt.h diff --git a/bsp/nxp/mcx/mcxc/Libraries/drivers/drv_rtc.c b/bsp/nxp/mcx/mcxc/Libraries/drivers/drv_rtc.c new file mode 100644 index 0000000000..ebf087b182 --- /dev/null +++ b/bsp/nxp/mcx/mcxc/Libraries/drivers/drv_rtc.c @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2024, Your Company Name + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2024-09-04 Alex First version for MCXC444 + */ + +#include +#include +#include + +#include "drv_rtc.h" + +#include "fsl_rtc.h" +#include "fsl_clock.h" + +#define DBG_TAG "drv.rtc" +#define DBG_LVL DBG_INFO +#include + +static rt_err_t mcxc444_rtc_init(rt_device_t dev) +{ + rtc_config_t rtcConfig; + + CLOCK_EnableClock(kCLOCK_Rtc0); + + RTC_GetDefaultConfig(&rtcConfig); + + RTC_Init(RTC, &rtcConfig); + + RTC_SetClockSource(RTC); + + rt_thread_mdelay(10); + + RTC_StartTimer(RTC); + + return RT_EOK; +} + +static rt_err_t mcxc444_rtc_get_time(time_t *ts) +{ + if (ts == RT_NULL) + { + return -RT_EINVAL; + } + + *ts = RTC->TSR; + + return RT_EOK; +} + +static rt_err_t mcxc444_rtc_set_time(time_t *ts) +{ + if (ts == RT_NULL) + { + return -RT_EINVAL; + } + + RTC_StopTimer(RTC); + RTC->TSR = *ts; + RTC_StartTimer(RTC); + + return RT_EOK; +} + +static rt_err_t mcxc444_rtc_control(rt_device_t dev, int cmd, void *args) +{ + rt_err_t result = RT_EOK; + + switch (cmd) + { + case RT_DEVICE_CTRL_RTC_GET_TIME: + result = mcxc444_rtc_get_time((time_t *)args); + break; + + case RT_DEVICE_CTRL_RTC_SET_TIME: + result = mcxc444_rtc_set_time((time_t *)args); + break; + + default: + return -RT_EINVAL; + } + + return result; +} + +static struct rt_device rtc_device; + +int rt_hw_rtc_init(void) +{ + rt_err_t ret; + + rtc_device.type = RT_Device_Class_RTC; + rtc_device.init = mcxc444_rtc_init; + rtc_device.open = RT_NULL; + rtc_device.close = RT_NULL; + rtc_device.read = RT_NULL; + rtc_device.write = RT_NULL; + rtc_device.control = mcxc444_rtc_control; + + ret = rt_device_register(&rtc_device, "rtc", RT_DEVICE_FLAG_RDWR); + if (ret != RT_EOK) + { + LOG_E("rtc register err code: %d\n", ret); + return ret; + } + + return RT_EOK; +} + +INIT_DEVICE_EXPORT(rt_hw_rtc_init); + + diff --git a/bsp/nxp/mcx/mcxc/Libraries/drivers/drv_rtc.h b/bsp/nxp/mcx/mcxc/Libraries/drivers/drv_rtc.h new file mode 100644 index 0000000000..85af003745 --- /dev/null +++ b/bsp/nxp/mcx/mcxc/Libraries/drivers/drv_rtc.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2006-2024, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2024-09-04 Alex First version for MCXC444 + */ + +#ifndef __DRV_RTC_H__ +#define __DRV_RTC_H__ + +#include +#include + +int rt_hw_rtc_init(void); + +#endif diff --git a/bsp/nxp/mcx/mcxc/Libraries/drivers/drv_uart.c b/bsp/nxp/mcx/mcxc/Libraries/drivers/drv_uart.c index 733e4b8faa..9d7a37a068 100644 --- a/bsp/nxp/mcx/mcxc/Libraries/drivers/drv_uart.c +++ b/bsp/nxp/mcx/mcxc/Libraries/drivers/drv_uart.c @@ -6,6 +6,7 @@ * Change Logs: * Date Author Notes * 2024-08-25 RT-Thread First version for MCXC444 + * 2024-09-03 yandld Updated to support multiple UARTs */ #include @@ -18,7 +19,6 @@ #ifdef RT_USING_SERIAL -/* MCXC444 UART driver */ struct mcxc444_uart { LPUART_Type *uart_base; @@ -29,22 +29,27 @@ struct mcxc444_uart static void uart_isr(struct rt_serial_device *serial); -#if defined(BSP_USING_UART0) -struct rt_serial_device serial0; +#define UART_DEVICE(uart_base, irq_name, device_name) \ + { \ + uart_base, \ + irq_name, \ + RT_NULL, \ + device_name, \ + } -void LPUART0_IRQHandler(void) -{ - uart_isr(&serial0); -} - -static const struct mcxc444_uart uart0 = -{ - LPUART0, - LPUART0_IRQn, - &serial0, - "uart0", -}; +static const struct mcxc444_uart uarts[] = { +#ifdef BSP_USING_UART0 + UART_DEVICE(LPUART0, LPUART0_IRQn, "uart0"), #endif +#ifdef BSP_USING_UART1 + UART_DEVICE(LPUART1, LPUART1_IRQn, "uart1"), +#endif + +}; + +#define UART_COUNT (sizeof(uarts) / sizeof(uarts[0])) + +static struct rt_serial_device serial_devices[UART_COUNT]; static rt_err_t mcxc444_configure(struct rt_serial_device *serial, struct serial_configure *cfg) { @@ -92,7 +97,15 @@ static rt_err_t mcxc444_configure(struct rt_serial_device *serial, struct serial return RT_ERROR; } - CLOCK_SetLpuart0Clock(0x1U); + if (uart->uart_base == LPUART0) + { + CLOCK_SetLpuart0Clock(0x1U); + } + else if (uart->uart_base == LPUART1) + { + CLOCK_SetLpuart1Clock(0x1U); + } + LPUART_Init(uart->uart_base, &config, CLOCK_GetFreq(kCLOCK_McgIrc48MClk)); return RT_EOK; @@ -145,16 +158,21 @@ static int mcxc444_getc(struct rt_serial_device *serial) static void uart_isr(struct rt_serial_device *serial) { + uint32_t status; + struct mcxc444_uart *uart = (struct mcxc444_uart *)serial->parent.user_data; - rt_interrupt_enter(); + status = LPUART_GetStatusFlags(uart->uart_base); - if (LPUART_GetStatusFlags(uart->uart_base) & kLPUART_RxDataRegFullFlag) + if (status & kLPUART_RxDataRegFullFlag) { rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND); } - rt_interrupt_leave(); + if (status & kLPUART_RxOverrunFlag) + { + LPUART_ClearStatusFlags(uart->uart_base, kLPUART_RxOverrunFlag); + } } static const struct rt_uart_ops mcxc444_uart_ops = @@ -165,18 +183,33 @@ static const struct rt_uart_ops mcxc444_uart_ops = mcxc444_getc, }; +#ifdef BSP_USING_UART0 +void LPUART0_IRQHandler(void) +{ + uart_isr(&serial_devices[0]); +} +#endif + +#ifdef BSP_USING_UART1 +void LPUART1_IRQHandler(void) +{ + uart_isr(&serial_devices[1]); +} +#endif + int rt_hw_uart_init(void) { struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; -#ifdef BSP_USING_UART0 - serial0.ops = &mcxc444_uart_ops; - serial0.config = config; + for (rt_size_t i = 0; i < UART_COUNT; i++) + { + serial_devices[i].ops = &mcxc444_uart_ops; + serial_devices[i].config = config; - rt_hw_serial_register(&serial0, uart0.device_name, - RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, - (void *)&uart0); -#endif + rt_hw_serial_register(&serial_devices[i], uarts[i].device_name, + RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, + (void *)&uarts[i]); + } return 0; } diff --git a/bsp/nxp/mcx/mcxc/Libraries/drivers/drv_wdt.c b/bsp/nxp/mcx/mcxc/Libraries/drivers/drv_wdt.c new file mode 100644 index 0000000000..4897d7de0e --- /dev/null +++ b/bsp/nxp/mcx/mcxc/Libraries/drivers/drv_wdt.c @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2006-2024, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2024-09-04 Alex First version for MCXC444 + */ + +#include +#include "drv_wdt.h" + +#include "fsl_cop.h" +#include "fsl_clock.h" + + +struct mcx_cop +{ + rt_watchdog_t watchdog; + SIM_Type *cop_base; +}; + +static struct mcx_cop cop_dev; + +static rt_err_t cop_init(rt_watchdog_t *wdt) +{ + cop_config_t config; + + COP_GetDefaultConfig(&config); + + config.timeoutMode = kCOP_ShortTimeoutMode; + config.clockSource = kCOP_LpoClock; + config.timeoutCycles = kCOP_2Power10CyclesOr2Power18Cycles; + config.enableStop = true; + config.enableDebug = true; + + + COP_Init(cop_dev.cop_base, &config); + + return RT_EOK; +} + +static rt_err_t cop_control(rt_watchdog_t *wdt, int cmd, void *arg) +{ + switch (cmd) + { + case RT_DEVICE_CTRL_WDT_START: + { + return RT_EOK; + } + case RT_DEVICE_CTRL_WDT_STOP: + { + COP_Disable(cop_dev.cop_base); + return RT_EOK; + } + case RT_DEVICE_CTRL_WDT_KEEPALIVE: + { + COP_Refresh(cop_dev.cop_base); + return RT_EOK; + } + case RT_DEVICE_CTRL_WDT_SET_TIMEOUT: + return -RT_ERROR; + + default: + return -RT_ERROR; + } +} + +static struct rt_watchdog_ops cop_ops = +{ + cop_init, + cop_control, +}; + +int rt_hw_cop_init(void) +{ + cop_dev.cop_base = SIM; + + cop_dev.watchdog.ops = &cop_ops; + + if (rt_hw_watchdog_register(&cop_dev.watchdog, "cop", RT_DEVICE_FLAG_DEACTIVATE, RT_NULL) != RT_EOK) + { + rt_kprintf("cop register failed\n"); + return -RT_ERROR; + } + + return RT_EOK; +} + +INIT_BOARD_EXPORT(rt_hw_cop_init); + diff --git a/bsp/nxp/mcx/mcxc/Libraries/drivers/drv_wdt.h b/bsp/nxp/mcx/mcxc/Libraries/drivers/drv_wdt.h new file mode 100644 index 0000000000..d685dd1fe5 --- /dev/null +++ b/bsp/nxp/mcx/mcxc/Libraries/drivers/drv_wdt.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2006-2024, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2024-09-04 Alex First version for MCXC444 + */ + +#ifndef __DRV_WDT_H__ +#define __DRV_WDT_H__ + +#include +#include + +int rt_hw_wdt_init(void); + +#endif /* __DRV_WDT_H__ */ diff --git a/bsp/nxp/mcx/mcxc/frdm-mcxc444/board/Kconfig b/bsp/nxp/mcx/mcxc/frdm-mcxc444/board/Kconfig index f0ea626331..6aa77dbb84 100644 --- a/bsp/nxp/mcx/mcxc/frdm-mcxc444/board/Kconfig +++ b/bsp/nxp/mcx/mcxc/frdm-mcxc444/board/Kconfig @@ -26,7 +26,9 @@ menu "On-chip Peripheral Drivers" config BSP_USING_UART0 bool "Enable UART0" default y - + config BSP_USING_UART1 + bool "Enable UART1" + default y endif menuconfig BSP_USING_I2C diff --git a/bsp/nxp/mcx/mcxc/frdm-mcxc444/board/MCUX_Config/board/pin_mux.c b/bsp/nxp/mcx/mcxc/frdm-mcxc444/board/MCUX_Config/board/pin_mux.c index 277fba2303..aca870dc13 100644 --- a/bsp/nxp/mcx/mcxc/frdm-mcxc444/board/MCUX_Config/board/pin_mux.c +++ b/bsp/nxp/mcx/mcxc/frdm-mcxc444/board/MCUX_Config/board/pin_mux.c @@ -22,22 +22,17 @@ void BOARD_InitBootPins(void) void BOARD_InitPins(void) { - /* Port A Clock Gate Control: Clock enabled */ CLOCK_EnableClock(kCLOCK_PortA); + CLOCK_EnableClock(kCLOCK_PortB); + CLOCK_EnableClock(kCLOCK_PortC); + CLOCK_EnableClock(kCLOCK_PortD); + CLOCK_EnableClock(kCLOCK_PortE); + + PORT_SetPinMux(PORTA, 1U, kPORT_MuxAlt2); /* LPUART0_RX */ + PORT_SetPinMux(PORTA, 2U, kPORT_MuxAlt2); /* LPUART0_TX */ + + PORT_SetPinMux(PORTE, 0U, kPORT_MuxAlt3); /* LPUART1_TX */ + PORT_SetPinMux(PORTE, 1U, kPORT_MuxAlt3); /* LPUART1_RX */ - /* PORTA1 (pin 23) is configured as LPUART0_RX */ - PORT_SetPinMux(PORTA, 1U, kPORT_MuxAlt2); - - /* PORTA2 (pin 24) is configured as LPUART0_TX */ - PORT_SetPinMux(PORTA, 2U, kPORT_MuxAlt2); - - SIM->SOPT5 = ((SIM->SOPT5 & - /* Mask bits to zero which are setting */ - (~(SIM_SOPT5_LPUART0TXSRC_MASK | SIM_SOPT5_LPUART0RXSRC_MASK))) - - /* LPUART0 Transmit Data Source Select: LPUART0_TX pin. */ - | SIM_SOPT5_LPUART0TXSRC(SOPT5_LPUART0TXSRC_LPUART_TX) - - /* LPUART0 Receive Data Source Select: LPUART_RX pin. */ - | SIM_SOPT5_LPUART0RXSRC(SOPT5_LPUART0RXSRC_LPUART_RX)); + SIM->SOPT5 = 0; }