Pārlūkot izejas kodu

[BSP][STM32] RTC Alarm驱动适配

张世争 2 gadi atpakaļ
vecāks
revīzija
c8a73411f6
1 mainītis faili ar 121 papildinājumiem un 6 dzēšanām
  1. 121 6
      bsp/stm32/libraries/HAL_Drivers/drv_rtc.c

+ 121 - 6
bsp/stm32/libraries/HAL_Drivers/drv_rtc.c

@@ -26,6 +26,21 @@
 
 #define BKUP_REG_DATA 0xA5A5
 
+struct rtc_device_object
+{
+    rt_rtc_dev_t  rtc_dev;
+#ifdef RT_USING_ALARM
+    struct rt_rtc_wkalarm   wkalarm;
+#endif
+};
+
+#ifdef RT_USING_ALARM
+static rt_err_t rtc_alarm_time_set(struct rtc_device_object* p_dev);
+static int rt_rtc_alarm_init(void);
+static RTC_AlarmTypeDef Alarm_InitStruct = { 0 };
+#endif
+
+static struct rtc_device_object rtc_device;
 static RTC_HandleTypeDef RTC_Handler;
 
 RT_WEAK uint32_t HAL_RTCEx_BKUPRead(RTC_HandleTypeDef *hrtc, uint32_t BackupRegister)
@@ -269,29 +284,125 @@ static rt_err_t stm32_rtc_set_secs(time_t *sec)
         result = -RT_ERROR;
     }
     LOG_D("RTC: set rtc_time %d", *sec);
-
+#ifdef RT_USING_ALARM
+    rt_alarm_update(&rtc_device.rtc_dev.parent, 1);
+#endif
     return result;
 }
 
+static rt_err_t stm32_rtc_get_alarm(struct rt_rtc_wkalarm *alarm)
+{
+#ifdef RT_USING_ALARM
+    *alarm = rtc_device.wkalarm;
+    LOG_D("GET_ALARM %d:%d:%d",rtc_device.wkalarm.tm_hour,
+        rtc_device.wkalarm.tm_min,rtc_device.wkalarm.tm_sec);
+    return RT_EOK;
+#else
+    return -RT_ERROR;
+#endif
+}
+
+static rt_err_t stm32_rtc_set_alarm(struct rt_rtc_wkalarm *alarm)
+{
+#ifdef RT_USING_ALARM
+    LOG_D("RT_DEVICE_CTRL_RTC_SET_ALARM");
+    if (alarm != RT_NULL)
+    {
+        rtc_device.wkalarm.enable = alarm->enable;
+        rtc_device.wkalarm.tm_hour = alarm->tm_hour;
+        rtc_device.wkalarm.tm_min = alarm->tm_min;
+        rtc_device.wkalarm.tm_sec = alarm->tm_sec;
+        rtc_alarm_time_set(&rtc_device);
+    }
+    else
+    {
+        LOG_E("RT_DEVICE_CTRL_RTC_SET_ALARM error!!");
+        return -RT_ERROR;
+    }
+    LOG_D("SET_ALARM %d:%d:%d",alarm->tm_hour,
+        alarm->tm_min, alarm->tm_sec);
+    return RT_EOK;
+#else
+    return -RT_ERROR;
+#endif
+}
+
 static const struct rt_rtc_ops stm32_rtc_ops =
 {
     stm32_rtc_init,
     stm32_rtc_get_secs,
     stm32_rtc_set_secs,
-    RT_NULL,
-    RT_NULL,
+    stm32_rtc_get_alarm,
+    stm32_rtc_set_alarm,
     stm32_rtc_get_timeval,
     RT_NULL,
 };
 
-static rt_rtc_dev_t stm32_rtc_dev;
+#ifdef RT_USING_ALARM
+void rt_rtc_alarm_enable(void)
+{
+    HAL_RTC_SetAlarm_IT(&RTC_Handler,&Alarm_InitStruct,RTC_FORMAT_BIN);
+    HAL_RTC_GetAlarm(&RTC_Handler,&Alarm_InitStruct,RTC_ALARM_A,RTC_FORMAT_BIN);
+    LOG_D("alarm read:%d:%d:%d", Alarm_InitStruct.AlarmTime.Hours,
+        Alarm_InitStruct.AlarmTime.Minutes,
+        Alarm_InitStruct.AlarmTime.Seconds);
+    HAL_NVIC_SetPriority(RTC_Alarm_IRQn, 0x02, 0);
+    HAL_NVIC_EnableIRQ(RTC_Alarm_IRQn);
+}
+
+void rt_rtc_alarm_disable(void)
+{
+    HAL_RTC_DeactivateAlarm(&RTC_Handler, RTC_ALARM_A);
+    HAL_NVIC_DisableIRQ(RTC_Alarm_IRQn);
+}
+
+static int rt_rtc_alarm_init(void)
+{
+    return RT_EOK;
+}
+
+static rt_err_t rtc_alarm_time_set(struct rtc_device_object* p_dev)
+{
+    if (p_dev->wkalarm.enable)
+    {
+        Alarm_InitStruct.Alarm = RTC_ALARM_A;
+        Alarm_InitStruct.AlarmDateWeekDay = RTC_WEEKDAY_MONDAY;
+        Alarm_InitStruct.AlarmDateWeekDaySel = RTC_ALARMDATEWEEKDAYSEL_WEEKDAY;
+        Alarm_InitStruct.AlarmMask = RTC_ALARMMASK_DATEWEEKDAY;
+        Alarm_InitStruct.AlarmSubSecondMask = RTC_ALARMSUBSECONDMASK_NONE;
+        Alarm_InitStruct.AlarmTime.TimeFormat = RTC_HOURFORMAT12_AM;
+        Alarm_InitStruct.AlarmTime.Hours = p_dev->wkalarm.tm_hour;
+        Alarm_InitStruct.AlarmTime.Minutes = p_dev->wkalarm.tm_min;
+        Alarm_InitStruct.AlarmTime.Seconds = p_dev->wkalarm.tm_sec;
+        LOG_D("alarm set:%d:%d:%d", Alarm_InitStruct.AlarmTime.Hours,
+            Alarm_InitStruct.AlarmTime.Minutes,
+            Alarm_InitStruct.AlarmTime.Seconds);
+        rt_rtc_alarm_enable();
+    }
+
+    return RT_EOK;
+}
+
+void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc)
+{
+    //LOG_D("rtc alarm isr.\n");
+    rt_alarm_update(&rtc_device.rtc_dev.parent, 1);
+}
+
+void RTC_Alarm_IRQHandler(void)
+{
+    rt_interrupt_enter();
+    HAL_RTC_AlarmIRQHandler(&RTC_Handler);
+    rt_interrupt_leave();
+}
+#endif
 
 static int rt_hw_rtc_init(void)
 {
     rt_err_t result;
 
-    stm32_rtc_dev.ops = &stm32_rtc_ops;
-    result = rt_hw_rtc_register(&stm32_rtc_dev, "rtc", RT_DEVICE_FLAG_RDWR, RT_NULL);
+    rtc_device.rtc_dev.ops = &stm32_rtc_ops;
+    result = rt_hw_rtc_register(&rtc_device.rtc_dev, "rtc", RT_DEVICE_FLAG_RDWR, RT_NULL);
     if (result != RT_EOK)
     {
         LOG_E("rtc register err code: %d", result);
@@ -299,6 +410,10 @@ static int rt_hw_rtc_init(void)
     }
     LOG_D("rtc init success");
 
+#ifdef RT_USING_ALARM
+    rt_rtc_alarm_init();
+#endif
+
     return RT_EOK;
 }
 INIT_DEVICE_EXPORT(rt_hw_rtc_init);