Skip to content

Commit c53c578

Browse files
committed
bsp:nxp/mcx/mcxe: Add RTC driver.
Signed-off-by: Yilin Sun <[email protected]>
1 parent cab0504 commit c53c578

File tree

1 file changed

+278
-0
lines changed

1 file changed

+278
-0
lines changed
Lines changed: 278 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,278 @@
1+
/*
2+
* Copyright (c) 2006-2025, RT-Thread Development Team
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*
6+
* Change Logs:
7+
* Date Author Notes
8+
* 2025-08-19 Alex Yang Add MCXA346 RTC driver for RT-Thread
9+
*/
10+
11+
#include <rtthread.h>
12+
#include <rtdevice.h>
13+
#include <sys/time.h>
14+
15+
#ifdef BSP_USING_RTC
16+
17+
#define DBG_TAG "drv.rtc"
18+
#define DBG_LVL DBG_INFO
19+
#include <rtdbg.h>
20+
21+
#include "fsl_rtc.h"
22+
#include "fsl_clock.h"
23+
24+
25+
/* Get RTC timestamp */
26+
static time_t get_rtc_timestamp(void)
27+
{
28+
rtc_datetime_t datetime;
29+
struct tm tm_new;
30+
31+
/* Get current time from RTC */
32+
RTC_GetDatetime(RTC, &datetime);
33+
34+
tm_new.tm_sec = datetime.second;
35+
tm_new.tm_min = datetime.minute;
36+
tm_new.tm_hour = datetime.hour;
37+
tm_new.tm_mday = datetime.day;
38+
tm_new.tm_mon = datetime.month - 1;
39+
tm_new.tm_year = datetime.year - 1900;
40+
tm_new.tm_isdst = 0;
41+
42+
LOG_D("get rtc time: %04d-%02d-%02d %02d:%02d:%02d",
43+
datetime.year, datetime.month, datetime.day,
44+
datetime.hour, datetime.minute, datetime.second);
45+
46+
return mktime(&tm_new);
47+
}
48+
49+
/* Set RTC timestamp */
50+
static rt_err_t set_rtc_time_stamp(time_t time_stamp)
51+
{
52+
rtc_datetime_t datetime;
53+
struct tm *time_tm;
54+
55+
time_tm = gmtime(&time_stamp);
56+
if (time_tm->tm_year < 70) /* Year should be >= 1970 */
57+
{
58+
LOG_E("Invalid year: %d", time_tm->tm_year + 1900);
59+
return -RT_ERROR;
60+
}
61+
62+
/* Convert to RTC datetime format */
63+
datetime.year = time_tm->tm_year + 1900;
64+
datetime.month = time_tm->tm_mon + 1;
65+
datetime.day = time_tm->tm_mday;
66+
datetime.hour = time_tm->tm_hour;
67+
datetime.minute = time_tm->tm_min;
68+
datetime.second = time_tm->tm_sec;
69+
70+
/* Set RTC time */
71+
RTC_StopTimer(RTC);
72+
73+
RTC_SetDatetime(RTC, &datetime);
74+
75+
RTC_StartTimer(RTC);
76+
77+
LOG_D("set rtc time: %04d-%02d-%02d %02d:%02d:%02d",
78+
datetime.year, datetime.month, datetime.day,
79+
datetime.hour, datetime.minute, datetime.second);
80+
81+
return RT_EOK;
82+
}
83+
84+
/* RTC configuration */
85+
static rt_err_t rt_rtc_config(void)
86+
{
87+
rtc_config_t rtc_config;
88+
89+
/* Get default RTC configuration */
90+
RTC_GetDefaultConfig(&rtc_config);
91+
92+
/* Initialize RTC - Note: RTC_Init returns void, not status */
93+
RTC_Init(RTC, &rtc_config);
94+
95+
/* Start RTC timer */
96+
RTC_StartTimer(RTC);
97+
98+
return RT_EOK;
99+
}
100+
101+
/* RTC initialization */
102+
static rt_err_t rtc_init(void)
103+
{
104+
105+
/* Configure RTC */
106+
if (rt_rtc_config() != RT_EOK)
107+
{
108+
LOG_E("RTC config failed.");
109+
return -RT_ERROR;
110+
}
111+
112+
LOG_D("RTC initialized successfully");
113+
return RT_EOK;
114+
}
115+
116+
/* Get RTC seconds */
117+
static rt_err_t rtc_get_secs(time_t *args)
118+
{
119+
RT_ASSERT(args != RT_NULL);
120+
121+
*args = get_rtc_timestamp();
122+
LOG_D("RTC: get rtc_time %x", *args);
123+
124+
return RT_EOK;
125+
}
126+
127+
/* Set RTC seconds */
128+
static rt_err_t rtc_set_secs(time_t *args)
129+
{
130+
rt_err_t result = RT_EOK;
131+
132+
RT_ASSERT(args != RT_NULL);
133+
134+
if (set_rtc_time_stamp(*args) != RT_EOK)
135+
{
136+
result = -RT_ERROR;
137+
}
138+
LOG_D("RTC: set rtc_time %x", *args);
139+
140+
return result;
141+
}
142+
143+
/* Get RTC alarm */
144+
static rt_err_t rtc_get_alarm(struct rt_rtc_wkalarm *wkalarm)
145+
{
146+
rtc_datetime_t datetime;
147+
148+
RT_ASSERT(wkalarm != RT_NULL);
149+
150+
/* Get alarm time from RTC */
151+
RTC_GetAlarm(RTC, &datetime);
152+
153+
/* Convert to wkalarm format */
154+
wkalarm->tm_sec = datetime.second;
155+
wkalarm->tm_min = datetime.minute;
156+
wkalarm->tm_hour = datetime.hour;
157+
wkalarm->tm_mday = datetime.day;
158+
wkalarm->tm_mon = datetime.month - 1;
159+
wkalarm->tm_year = datetime.year - 1900;
160+
161+
/* Check if alarm is enabled */
162+
wkalarm->enable = (RTC_GetEnabledInterrupts(RTC) & kRTC_AlarmInterruptEnable) ? 1 : 0;
163+
164+
LOG_D("RTC: get alarm %04d-%02d-%02d %02d:%02d:%02d (%s)",
165+
datetime.year, datetime.month, datetime.day,
166+
datetime.hour, datetime.minute, datetime.second,
167+
wkalarm->enable ? "ENABLED" : "DISABLED");
168+
169+
return RT_EOK;
170+
}
171+
172+
/* Set RTC alarm */
173+
static rt_err_t rtc_set_alarm(struct rt_rtc_wkalarm *wkalarm)
174+
{
175+
rtc_datetime_t datetime;
176+
177+
RT_ASSERT(wkalarm != RT_NULL);
178+
179+
/* Convert from wkalarm format */
180+
datetime.year = wkalarm->tm_year + 1900;
181+
datetime.month = wkalarm->tm_mon + 1;
182+
datetime.day = wkalarm->tm_mday;
183+
datetime.hour = wkalarm->tm_hour;
184+
datetime.minute = wkalarm->tm_min;
185+
datetime.second = wkalarm->tm_sec;
186+
187+
/* Set alarm time */
188+
RTC_SetAlarm(RTC, &datetime);
189+
190+
/* Enable/disable alarm interrupt */
191+
if (wkalarm->enable)
192+
{
193+
RTC_EnableInterrupts(RTC, kRTC_AlarmInterruptEnable);
194+
EnableIRQ(RTC_IRQn); /* Use RTC_IRQn instead of RTC0_IRQn */
195+
LOG_D("RTC alarm enabled");
196+
}
197+
else
198+
{
199+
RTC_DisableInterrupts(RTC, kRTC_AlarmInterruptEnable);
200+
LOG_D("RTC alarm disabled");
201+
}
202+
203+
LOG_D("RTC: set alarm %04d-%02d-%02d %02d:%02d:%02d",
204+
datetime.year, datetime.month, datetime.day,
205+
datetime.hour, datetime.minute, datetime.second);
206+
207+
return RT_EOK;
208+
}
209+
210+
/* RTC operations structure */
211+
static const struct rt_rtc_ops rtc_ops =
212+
{
213+
rtc_init,
214+
rtc_get_secs,
215+
rtc_set_secs,
216+
rtc_get_alarm,
217+
rtc_set_alarm,
218+
RT_NULL, /* get_timeval */
219+
RT_NULL, /* set_timeval */
220+
};
221+
222+
static rt_rtc_dev_t mcxa_rtc_dev;
223+
224+
/* RTC interrupt handler */
225+
void RTC_IRQHandler(void)
226+
{
227+
rt_interrupt_enter();
228+
229+
/* Get interrupt status */
230+
uint32_t status = RTC_GetStatusFlags(RTC);
231+
232+
/* Handle alarm interrupt */
233+
if (status & kRTC_AlarmFlag)
234+
{
235+
/* Clear alarm flag */
236+
RTC_ClearStatusFlags(RTC, kRTC_AlarmFlag);
237+
238+
LOG_D("RTC alarm triggered");
239+
240+
/* If alarm framework is available, notify it */
241+
#ifdef RT_USING_ALARM
242+
/* Send alarm event to alarm thread */
243+
rt_event_send(&_container.event, 1);
244+
#endif
245+
}
246+
247+
/* Handle seconds interrupt if needed */
248+
if (status & kRTC_SecondsInterruptEnable)
249+
{
250+
LOG_D("RTC seconds interrupt");
251+
}
252+
253+
rt_interrupt_leave();
254+
}
255+
256+
/* Hardware RTC initialization */
257+
int rt_hw_rtc_init(void)
258+
{
259+
rt_err_t result;
260+
261+
/* Set RTC operations */
262+
mcxa_rtc_dev.ops = &rtc_ops;
263+
264+
/* Register RTC device */
265+
result = rt_hw_rtc_register(&mcxa_rtc_dev, "rtc", RT_DEVICE_FLAG_RDWR, RT_NULL);
266+
if (result != RT_EOK)
267+
{
268+
LOG_E("RTC register failed, err code: %d", result);
269+
return result;
270+
}
271+
272+
LOG_D("RTC init success");
273+
return RT_EOK;
274+
}
275+
276+
INIT_DEVICE_EXPORT(rt_hw_rtc_init);
277+
278+
#endif /* BSP_USING_RTC */

0 commit comments

Comments
 (0)