【ART-PI】RT-Thread 开启RTC 与 Alarm组件

发布于 2021-01-20 09:25:53

【ART-PI】STM32H750XBH6 - 入手篇

【ART-PI】STM32H750XBH6 - RT-Thread 最小系统移植

【ART-PI】RT-Thread Freemodbus RS485 RTU 从机

【ART-PI】RT-Thread 开启RTC 与 Alarm组件

【ART-PI】STM32H750XBH6 RT-Thread 点亮LCD

背景

  • 【ART-PI】默认没有开启Alarm组件,尝试适配并开启
  • 有部分工程师想使用RT-Thread 基于STM32H7系列的RTC 与 Alarm(闹钟功能)

验证平台

  • Keil MDK5(使用RT-Thread Studio 可以作为参考)
  • 【ART-PI】STM32H750XBH6,使用Pandoro STM32L4系列MCU,同样验证通过

移植方法

  • 只前做过一次基于Apollo3平台的Alarm组件的移植,适配部分与STM32有些不同,直接Copy过去编译,发现编译不过,很正常!!
  • 这次基于STM32H7、STM32L4平台,如果也编译不过去,只需要微调!

2021-01-20_084804.png

2021-01-20_085113.png

2021-01-20_085442.png

2021-01-20_085529.png

2021-01-20_085724.png

2021-01-20_085814.png

功能验证

2021-01-20_090458.png

2021-01-20_090528.png

2021-01-20_090900.png

drv_rtc.c 代码,供参考

#include "board.h"
#include <rtdevice.h>
#include <sys/time.h>

#ifdef BSP_USING_ONCHIP_RTC

struct rt_rtc_device
{
    struct rt_device        device;
#ifdef RT_USING_ALARM
    struct rt_rtc_wkalarm   wkalarm;
#endif
};

#define DBG_ENABLE
#define DBG_SECTION_NAME    "drv_rtc"
#define DBG_LEVEL           DBG_INFO
#include <rtdbg.h>

static struct rt_rtc_device rtc_device;

#ifdef RT_USING_ALARM
static rt_err_t rtc_alarm_time_set(struct rt_rtc_device* p_dev);
static int rt_rtc_alarm_init(void);
static RTC_AlarmTypeDef salarmstructure;
#endif

#ifndef RTC_BKP_DR1
#define RTC_BKP_DR1 RT_NULL
#endif

#define BKUP_REG_DATA 0xA5A5

static RTC_HandleTypeDef RTC_Handler;

RT_WEAK uint32_t HAL_RTCEx_BKUPRead(RTC_HandleTypeDef *hrtc, uint32_t BackupRegister)
{
    return (~BKUP_REG_DATA);
}

RT_WEAK void HAL_RTCEx_BKUPWrite(RTC_HandleTypeDef *hrtc, uint32_t BackupRegister, uint32_t Data)
{
    return;
}

static time_t get_rtc_timestamp(void)
{
    RTC_TimeTypeDef RTC_TimeStruct = {0};
    RTC_DateTypeDef RTC_DateStruct = {0};
    struct tm tm_new = {0};

    HAL_RTC_GetTime(&RTC_Handler, &RTC_TimeStruct, RTC_FORMAT_BIN);
    HAL_RTC_GetDate(&RTC_Handler, &RTC_DateStruct, RTC_FORMAT_BIN);

    tm_new.tm_sec  = RTC_TimeStruct.Seconds;
    tm_new.tm_min  = RTC_TimeStruct.Minutes;
    tm_new.tm_hour = RTC_TimeStruct.Hours;
    tm_new.tm_mday = RTC_DateStruct.Date;
    tm_new.tm_mon  = RTC_DateStruct.Month - 1;
    tm_new.tm_year = RTC_DateStruct.Year + 100;

    return mktime(&tm_new);
}

static rt_err_t set_rtc_time_stamp(time_t time_stamp)
{
    RTC_TimeTypeDef RTC_TimeStruct = {0};
    RTC_DateTypeDef RTC_DateStruct = {0};
    struct tm *p_tm;

    p_tm = localtime(&time_stamp);
    if (p_tm->tm_year < 100)
    {
        return -RT_ERROR;
    }

    RTC_TimeStruct.Seconds = p_tm->tm_sec ;
    RTC_TimeStruct.Minutes = p_tm->tm_min ;
    RTC_TimeStruct.Hours   = p_tm->tm_hour;
    RTC_DateStruct.Date    = p_tm->tm_mday;
    RTC_DateStruct.Month   = p_tm->tm_mon + 1 ;
    RTC_DateStruct.Year    = p_tm->tm_year - 100;
    RTC_DateStruct.WeekDay = p_tm->tm_wday + 1;

    if (HAL_RTC_SetTime(&RTC_Handler, &RTC_TimeStruct, RTC_FORMAT_BIN) != HAL_OK)
    {
        return -RT_ERROR;
    }
    if (HAL_RTC_SetDate(&RTC_Handler, &RTC_DateStruct, RTC_FORMAT_BIN) != HAL_OK)
    {
        return -RT_ERROR;
    }

    LOG_D("set rtc time.");
    HAL_RTCEx_BKUPWrite(&RTC_Handler, RTC_BKP_DR1, BKUP_REG_DATA);

#ifdef SOC_SERIES_STM32F1
    /* F1 series does't save year/month/date datas. so keep those datas to bkp reg */
    HAL_RTCEx_BKUPWrite(&RTC_Handler, RTC_BKP_DR2, RTC_DateStruct.Year);
    HAL_RTCEx_BKUPWrite(&RTC_Handler, RTC_BKP_DR3, RTC_DateStruct.Month);
    HAL_RTCEx_BKUPWrite(&RTC_Handler, RTC_BKP_DR4, RTC_DateStruct.Date);
    HAL_RTCEx_BKUPWrite(&RTC_Handler, RTC_BKP_DR5, RTC_DateStruct.WeekDay);
#endif

    return RT_EOK;
}

static void rt_rtc_init(void)
{
#if !defined(SOC_SERIES_STM32H7) && !defined(SOC_SERIES_STM32WB)
    __HAL_RCC_PWR_CLK_ENABLE();
#endif

    RCC_OscInitTypeDef RCC_OscInitStruct = {0};
#ifdef BSP_RTC_USING_LSI
#ifdef SOC_SERIES_STM32WB
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI1;
    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
    RCC_OscInitStruct.LSEState = RCC_LSE_OFF;
    RCC_OscInitStruct.LSIState = RCC_LSI_ON;
#else
    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI;
    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
    RCC_OscInitStruct.LSEState = RCC_LSE_OFF;
    RCC_OscInitStruct.LSIState = RCC_LSI_ON;
#endif
#else
    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE;
    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
    RCC_OscInitStruct.LSEState = RCC_LSE_ON;
    RCC_OscInitStruct.LSIState = RCC_LSI_OFF;
#endif
    HAL_RCC_OscConfig(&RCC_OscInitStruct);
}

#ifdef SOC_SERIES_STM32F1
/* update RTC_BKP_DRx*/
static void rt_rtc_f1_bkp_update(void)
{
    RTC_DateTypeDef RTC_DateStruct = {0};

    HAL_PWR_EnableBkUpAccess();
    __HAL_RCC_BKP_CLK_ENABLE();

    RTC_DateStruct.Year    = HAL_RTCEx_BKUPRead(&RTC_Handler, RTC_BKP_DR2);
    RTC_DateStruct.Month   = HAL_RTCEx_BKUPRead(&RTC_Handler, RTC_BKP_DR3);
    RTC_DateStruct.Date    = HAL_RTCEx_BKUPRead(&RTC_Handler, RTC_BKP_DR4);
    RTC_DateStruct.WeekDay = HAL_RTCEx_BKUPRead(&RTC_Handler, RTC_BKP_DR5);
    if (HAL_RTC_SetDate(&RTC_Handler, &RTC_DateStruct, RTC_FORMAT_BIN) != HAL_OK)
    {
        Error_Handler();
    }

    HAL_RTC_GetDate(&RTC_Handler, &RTC_DateStruct, RTC_FORMAT_BIN);
    if (HAL_RTCEx_BKUPRead(&RTC_Handler, RTC_BKP_DR4) != RTC_DateStruct.Date)
    {
        HAL_RTCEx_BKUPWrite(&RTC_Handler, RTC_BKP_DR1, BKUP_REG_DATA);
        HAL_RTCEx_BKUPWrite(&RTC_Handler, RTC_BKP_DR2, RTC_DateStruct.Year);
        HAL_RTCEx_BKUPWrite(&RTC_Handler, RTC_BKP_DR3, RTC_DateStruct.Month);
        HAL_RTCEx_BKUPWrite(&RTC_Handler, RTC_BKP_DR4, RTC_DateStruct.Date);
        HAL_RTCEx_BKUPWrite(&RTC_Handler, RTC_BKP_DR5, RTC_DateStruct.WeekDay);
    }
}
#endif

static rt_err_t rt_rtc_config(struct rt_device *dev)
{
    RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};

    HAL_PWR_EnableBkUpAccess();
    PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_RTC;
#ifdef BSP_RTC_USING_LSI
    PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSI;
#else
    PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
#endif
    HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);

    /* Enable RTC Clock */
    __HAL_RCC_RTC_ENABLE();

    RTC_Handler.Instance = RTC;
    if (HAL_RTCEx_BKUPRead(&RTC_Handler, RTC_BKP_DR1) != BKUP_REG_DATA)
    {
        LOG_I("RTC hasn't been configured, please use <date> command to config.");

#if defined(SOC_SERIES_STM32F1)
        RTC_Handler.Init.OutPut = RTC_OUTPUTSOURCE_NONE;
        RTC_Handler.Init.AsynchPrediv = RTC_AUTO_1_SECOND;
#elif defined(SOC_SERIES_STM32F0)

        /* set the frequency division */
#ifdef BSP_RTC_USING_LSI
        RTC_Handler.Init.AsynchPrediv = 0XA0;
        RTC_Handler.Init.SynchPrediv = 0xFA;
#else
        RTC_Handler.Init.AsynchPrediv = 0X7F;
        RTC_Handler.Init.SynchPrediv = 0x0130;
#endif /* BSP_RTC_USING_LSI */

        RTC_Handler.Init.HourFormat = RTC_HOURFORMAT_24;
        RTC_Handler.Init.OutPut = RTC_OUTPUT_DISABLE;
        RTC_Handler.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
        RTC_Handler.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
#elif defined(SOC_SERIES_STM32F2) || defined(SOC_SERIES_STM32F4) || defined(SOC_SERIES_STM32F7) || defined(SOC_SERIES_STM32L4) || defined(SOC_SERIES_STM32H7) || defined (SOC_SERIES_STM32WB)

        /* set the frequency division */
#ifdef BSP_RTC_USING_LSI
        RTC_Handler.Init.AsynchPrediv = 0X7D;
#else
        RTC_Handler.Init.AsynchPrediv = 0X7F;
#endif /* BSP_RTC_USING_LSI */
        RTC_Handler.Init.SynchPrediv = 0XFF;

        RTC_Handler.Init.HourFormat = RTC_HOURFORMAT_24;
        RTC_Handler.Init.OutPut = RTC_OUTPUT_DISABLE;
        RTC_Handler.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
        RTC_Handler.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
#endif
        if (HAL_RTC_Init(&RTC_Handler) != HAL_OK)
        {
            return -RT_ERROR;
        }
    }
#ifdef SOC_SERIES_STM32F1
    else
    {
        /* F1 series need update by bkp reg datas */
        rt_rtc_f1_bkp_update();
    }
#endif

    return RT_EOK;
}

static rt_err_t rt_rtc_control(rt_device_t dev, int cmd, void *args)
{
    rt_err_t result = RT_EOK;
#ifdef RT_USING_ALARM
    struct rt_rtc_wkalarm *p_wkalarm = RT_NULL;
#endif
    RT_ASSERT(dev != RT_NULL);

    switch (cmd)
    {
    case RT_DEVICE_CTRL_RTC_GET_TIME:
        *(rt_uint32_t *)args = get_rtc_timestamp();
        LOG_D("RTC: get rtc_time %x\n", *(rt_uint32_t *)args);
        break;

    case RT_DEVICE_CTRL_RTC_SET_TIME:
        if (set_rtc_time_stamp(*(rt_uint32_t *)args))
        {
            result = -RT_ERROR;
        }
#ifdef RT_USING_ALARM
        rt_alarm_update(&rtc_device.device, 1);
#endif
        LOG_D("RTC: set rtc_time %x\n", *(rt_uint32_t *)args);
        break;

#ifdef RT_USING_ALARM
    case RT_DEVICE_CTRL_RTC_GET_ALARM:
        args = &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);
        break;

    case RT_DEVICE_CTRL_RTC_SET_ALARM:
        LOG_D("RT_DEVICE_CTRL_RTC_SET_ALARM");
        p_wkalarm = (struct rt_rtc_wkalarm *)args;
        if (p_wkalarm != RT_NULL)
        {
            rtc_device.wkalarm.enable = p_wkalarm->enable;
            rtc_device.wkalarm.tm_hour = p_wkalarm->tm_hour;
            rtc_device.wkalarm.tm_min = p_wkalarm->tm_min;
            rtc_device.wkalarm.tm_sec = p_wkalarm->tm_sec;
            rtc_alarm_time_set(&rtc_device);
        }
        else
        {
            result = -RT_ERROR;
            LOG_E("RT_DEVICE_CTRL_RTC_SET_ALARM error!!");
        }
        LOG_D("SET_ALARM %d:%d:%d",p_wkalarm->tm_hour,
            p_wkalarm->tm_min,p_wkalarm->tm_sec);
        break;
#endif
    }

    return result;
}

#ifdef RT_USING_DEVICE_OPS
const static struct rt_device_ops rtc_ops =
{
    RT_NULL,
    RT_NULL,
    RT_NULL,
    RT_NULL,
    RT_NULL,
    rt_rtc_control
};
#endif

static rt_err_t rt_hw_rtc_register(rt_device_t device, const char *name, rt_uint32_t flag)
{
    RT_ASSERT(device != RT_NULL);

    rt_rtc_init();
    if (rt_rtc_config(device) != RT_EOK)
    {
        return -RT_ERROR;
    }
#ifdef RT_USING_DEVICE_OPS
    device->ops         = &rtc_ops;
#else
    device->init        = RT_NULL;
    device->open        = RT_NULL;
    device->close       = RT_NULL;
    device->read        = RT_NULL;
    device->write       = RT_NULL;
    device->control     = rt_rtc_control;
#endif
    device->type        = RT_Device_Class_RTC;
    device->rx_indicate = RT_NULL;
    device->tx_complete = RT_NULL;
    device->user_data   = RT_NULL;

    /* register a character device */
    return rt_device_register(device, name, flag);
}

int rt_hw_rtc_init(void)
{
    rt_err_t result;

    result = rt_hw_rtc_register(&rtc_device.device, "rtc", RT_DEVICE_FLAG_RDWR);
    if (result != RT_EOK)
    {
        LOG_E("rtc register err code: %d\n", result);
        return result;
    }
#ifdef RT_USING_ALARM
    rt_rtc_alarm_init();
#endif
    LOG_D("rtc init success\n");
    return RT_EOK;
}

#ifdef RT_USING_ALARM
void rt_rtc_alarm_enable(void)
{
    HAL_RTC_SetAlarm_IT(&RTC_Handler,&salarmstructure,RTC_FORMAT_BIN);
    HAL_RTC_GetAlarm(&RTC_Handler,&salarmstructure,RTC_ALARM_A,RTC_FORMAT_BIN);
    LOG_D("alarm read:%d:%d:%d", salarmstructure.AlarmTime.Hours,
        salarmstructure.AlarmTime.Minutes,
        salarmstructure.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 rt_rtc_device* p_dev)
{
    if (p_dev->wkalarm.enable)
    {
        salarmstructure.Alarm = RTC_ALARM_A;
        salarmstructure.AlarmDateWeekDay = RTC_WEEKDAY_MONDAY;
        salarmstructure.AlarmDateWeekDaySel = RTC_ALARMDATEWEEKDAYSEL_WEEKDAY;
        salarmstructure.AlarmMask = RTC_ALARMMASK_DATEWEEKDAY;
        salarmstructure.AlarmSubSecondMask = RTC_ALARMSUBSECONDMASK_NONE;
        salarmstructure.AlarmTime.TimeFormat = RTC_HOURFORMAT12_AM;
        salarmstructure.AlarmTime.Hours = p_dev->wkalarm.tm_hour;
        salarmstructure.AlarmTime.Minutes = p_dev->wkalarm.tm_min;
        salarmstructure.AlarmTime.Seconds = p_dev->wkalarm.tm_sec;
        LOG_D("alarm set:%d:%d:%d", salarmstructure.AlarmTime.Hours,
            salarmstructure.AlarmTime.Minutes,
            salarmstructure.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.device, 1);
}

void RTC_Alarm_IRQHandler(void)
{
    HAL_RTC_AlarmIRQHandler(&RTC_Handler);
}

#endif

INIT_DEVICE_EXPORT(rt_hw_rtc_init);

#endif /* BSP_USING_ONCHIP_RTC */

RTC_Alarm 测试代码,供参考

#include <rtthread.h>
#include "board.h"
#include <rtdevice.h>
#include <time.h>

#define RTC_DEBUG

#define DBG_ENABLE
#define DBG_SECTION_NAME    "rtc.test"
#define DBG_LEVEL           DBG_LOG
#include <rtdbg.h>

#ifdef RTC_DEBUG

static struct rt_alarm * p_alarm_sec = RT_NULL;
static struct rt_alarm * p_alarm_min = RT_NULL;
static struct rt_alarm * p_alarm_hour = RT_NULL;
static struct rt_alarm * p_alarm_time = RT_NULL;

static rt_err_t rtc_set_time(time_t timestamp)
{
    /* converts the local time in time to calendar time. */
    rt_device_t rtc_device;
    rt_err_t ret = -RT_ERROR;

    rtc_device = rt_device_find("rtc");

    if (rtc_device == RT_NULL)
    {
        return -RT_ERROR;
    }

    /* update to RTC device. */
    ret = rt_device_control(rtc_device, RT_DEVICE_CTRL_RTC_SET_TIME, &timestamp);

    return ret;
}

static time_t rtc_gettime(void)
{
    static time_t now;
    static struct tm tm;

    now = time(NULL);
#ifdef _WIN32
    _gmtime32_s(&tm, &now);
#else
    gmtime_r(&now, &tm);
#endif

    LOG_D("BJ time:%04d-%02d-%02d %02d:%02d:%02d.%03d\n",
                tm.tm_year + 1900, tm.tm_mon + 1,
                tm.tm_mday, tm.tm_hour + 8, tm.tm_min,
                tm.tm_sec, rt_tick_get() % 1000);

    return now;
}

static void alarm_time_cb(rt_alarm_t alarm, time_t timestamp)
{
    LOG_D("alarm_time_cb ok!\n");
}

static void alarm_hour_cb(rt_alarm_t alarm, time_t timestamp)
{
    LOG_D("alarm_hour_cb ok!\n");
}

static void alarm_minute_cb(rt_alarm_t alarm, time_t timestamp)
{
    LOG_D("alarm_minute_cb ok!\n");
}

static void alarm_second_cb(rt_alarm_t alarm, time_t timestamp)
{
    LOG_D("alarm_second_cb ok!\n");
}

static struct rt_alarm * rtc_alarm_test_create(rt_alarm_callback_t callback, rt_uint32_t flag, struct tm *p_tm)
{
    struct rt_alarm_setup alarm_setup_test;

    alarm_setup_test.flag = flag;
    alarm_setup_test.wktime.tm_year = p_tm->tm_year;
    alarm_setup_test.wktime.tm_mon = p_tm->tm_mon;
    alarm_setup_test.wktime.tm_mday = p_tm->tm_mday;
    alarm_setup_test.wktime.tm_wday = p_tm->tm_wday;
    alarm_setup_test.wktime.tm_hour = p_tm->tm_hour;
    alarm_setup_test.wktime.tm_min = p_tm->tm_min;
    alarm_setup_test.wktime.tm_sec = p_tm->tm_sec;

    return rt_alarm_create(callback, &alarm_setup_test);
}

static void rtc_alarm_time_create(void)
{
    static time_t now;
    static struct tm tm;

    if (p_alarm_time != RT_NULL)
        return;

    now = time(NULL) + 65;
#ifdef _WIN32
    _gmtime32_s(&tm, &now);
#else
    gmtime_r(&now, &tm);
#endif

    p_alarm_time = rtc_alarm_test_create(alarm_time_cb, RT_ALARM_DAILY, &tm);
}

static void rtc_alarm_time_start(void)
{
    if (p_alarm_time != RT_NULL)
        rt_alarm_start(p_alarm_time);
}

static void rtc_alarm_time_stop(void)
{
    if (p_alarm_time != RT_NULL)
        rt_alarm_stop(p_alarm_time);
}

static void rtc_alarm_time_delete(void)
{
    if (p_alarm_time != RT_NULL)
    {
        if (rt_alarm_delete(p_alarm_time) == RT_EOK)
            p_alarm_time = RT_NULL;
    }
}

static void rtc_alarm_second_create(void)
{
    static time_t now;
    static struct tm tm;

    if (p_alarm_sec != RT_NULL)
        return;

    now = time(NULL) + 1;
#ifdef _WIN32
    _gmtime32_s(&tm, &now);
#else
    gmtime_r(&now, &tm);
#endif

    p_alarm_sec = rtc_alarm_test_create(alarm_second_cb, RT_ALARM_SECOND, &tm);
}

static void rtc_alarm_second_start(void)
{
    if (p_alarm_sec != RT_NULL)
        rt_alarm_start(p_alarm_sec);
}

static void rtc_alarm_second_stop(void)
{
    if (p_alarm_sec != RT_NULL)
        rt_alarm_stop(p_alarm_sec);
}

static void rtc_alarm_second_delete(void)
{
    if (p_alarm_sec != RT_NULL)
    {
        if (rt_alarm_delete(p_alarm_sec) == RT_EOK)
            p_alarm_sec = RT_NULL;
    }
}

static void rtc_alarm_minute_create(void)
{
    static time_t now;
    static struct tm tm;

    if (p_alarm_min != RT_NULL)
        return;

    now = time(NULL) + 60;
#ifdef _WIN32
    _gmtime32_s(&tm, &now);
#else
    gmtime_r(&now, &tm);
#endif

    p_alarm_min = rtc_alarm_test_create(alarm_minute_cb, RT_ALARM_MINUTE, &tm);
}

static void rtc_alarm_minute_start(void)
{
    if (p_alarm_min != RT_NULL)
        rt_alarm_start(p_alarm_min);
}

static void rtc_alarm_minute_stop(void)
{
    if (p_alarm_min != RT_NULL)
        rt_alarm_stop(p_alarm_min);
}

static void rtc_alarm_minute_delete(void)
{
    if (p_alarm_min != RT_NULL)
    {
        if (rt_alarm_delete(p_alarm_min) == RT_EOK)
            p_alarm_min = RT_NULL;
    }
}

static void rtc_alarm_hour_create(void)
{
    static time_t now;
    static struct tm tm;

    if (p_alarm_hour != RT_NULL)
        return;

    now = time(NULL) + 3600;
#ifdef _WIN32
    _gmtime32_s(&tm, &now);
#else
    gmtime_r(&now, &tm);
#endif

    p_alarm_hour = rtc_alarm_test_create(alarm_hour_cb, RT_ALARM_HOUR, &tm);
}

static void rtc_alarm_hour_start(void)
{
    if (p_alarm_hour != RT_NULL)
        rt_alarm_start(p_alarm_hour);
}

static void rtc_alarm_hour_stop(void)
{
    if (p_alarm_hour != RT_NULL)
        rt_alarm_stop(p_alarm_hour);
}

static void rtc_alarm_hour_delete(void)
{
    if (p_alarm_hour != RT_NULL)
    {
        if (rt_alarm_delete(p_alarm_hour) == RT_EOK)
            p_alarm_hour = RT_NULL;
    }
}

void rtc_alarm_start(int argc, char **argv)
{
    int index = 0;

    if (argc >= 2)
    {
        index = atoi(argv[1]);
    }

    switch(index)
    {
        case 0:
            rtc_alarm_hour_start();
            break;
        case 1:
            rtc_alarm_minute_start();
            break;
        case 2:
            rtc_alarm_second_start();
            break;
        case 3:
            rtc_alarm_time_start();
            break;
        default:
            break;
    }
}

void rtc_alarm_stop(int argc, char **argv)
{
    int index = 0;

    if (argc >= 2)
    {
        index = atoi(argv[1]);
    }

    switch(index)
    {
        case 0:
            rtc_alarm_hour_stop();
            break;
        case 1:
            rtc_alarm_minute_stop();
            break;
        case 2:
            rtc_alarm_second_stop();
            break;
        case 3:
            rtc_alarm_time_stop();
            break;
        default:
            break;
    }
}

void rtc_alarm_create(int argc, char **argv)
{
    int index = 0;

    if (argc >= 2)
    {
        index = atoi(argv[1]);
    }

    switch(index)
    {
        case 0:
            rtc_alarm_hour_create();
            break;
        case 1:
            rtc_alarm_minute_create();
            break;
        case 2:
            rtc_alarm_second_create();
            break;
        case 3:
            rtc_alarm_time_create();
            break;
        default:
            break;
    }
}

void rtc_alarm_delete(int argc, char **argv)
{
    int index = 0;

    if (argc >= 2)
    {
        index = atoi(argv[1]);
    }

    switch(index)
    {
        case 0:
            rtc_alarm_hour_delete();
            break;
        case 1:
            rtc_alarm_minute_delete();
            break;
        case 2:
            rtc_alarm_second_delete();
            break;
        case 3:
            rtc_alarm_time_delete();
            break;
        default:
            break;
    }
}

MSH_CMD_EXPORT(rtc_gettime, rtc get time);
MSH_CMD_EXPORT(rtc_alarm_create, rtc alarm_create);
MSH_CMD_EXPORT(rtc_alarm_delete, rtc alarm_delete);
MSH_CMD_EXPORT(rtc_alarm_start, rtc alarm_start);
MSH_CMD_EXPORT(rtc_alarm_stop, rtc alarm_stop);

#endif

总结

  • RT-Thread RTC alarm组件,配置起来,稍微有点麻烦。
  • Alarm闹钟功能,使能组件后,还是需要创建闹钟、开启闹钟、停止闹钟、删除闹钟业务代码的配合。
  • 多使用,多总结。

调试记录

msh />rtc
rtc_gettime
rtc_alarm_create
rtc_alarm_delete
rtc_alarm_start
rtc_alarm_stop
msh />rtc_al
rtc_alarm_create
rtc_alarm_delete
rtc_alarm_start
rtc_alarm_stop
msh />rtc_alarm_c
rtc_alarm_create
msh />rtc_alarm_create 0
msh />rtc
rtc_gettime
rtc_alarm_create
rtc_alarm_delete
rtc_alarm_start
rtc_alarm_stop
msh />rtc_al
rtc_alarm_create
rtc_alarm_delete
rtc_alarm_start
rtc_alarm_stop
msh />rtc_alarm_c
rtc_alarm_create
msh />rtc_alarm_create 1
msh />al
alarm_dump
msh />alarm_dump
| id | YYYY-MM-DD hh:mm:ss | week | flag | en |
+----+---------------------+------+------+----+
|  0 | 2000-01-01 08:13:12 |   6  |   M  |  0 |
|  1 | 2000-01-01 09:12:07 |   6  |   H  |  0 |
|  2 | 2000-01-01 08:12:13 |   6  |   S  |  1 |
+----+---------------------+------+------+----+
msh />rt
rtc_gettime
rtc_alarm_create
rtc_alarm_delete
rtc_alarm_start
rtc_alarm_stop
msh />rtc_al
rtc_alarm_create
rtc_alarm_delete
rtc_alarm_start
rtc_alarm_stop
msh />rtc_alarm_st
rtc_alarm_start
rtc_alarm_stop
msh />rtc_alarm_sta
rtc_alarm_start
msh />rtc_alarm_start 0
msh />rtc
rtc_gettime
rtc_alarm_create
rtc_alarm_delete
rtc_alarm_start
rtc_alarm_stop
msh />rtc_al
rtc_alarm_create
rtc_alarm_delete
rtc_alarm_start
rtc_alarm_stop
msh />rtc_alarm_st
rtc_alarm_start
rtc_alarm_stop
msh />rtc_alarm_sta
rtc_alarm_start
msh />rtc_alarm_start 1
msh />al
alarm_dump
msh />alarm_dump
| id | YYYY-MM-DD hh:mm:ss | week | flag | en |
+----+---------------------+------+------+----+
|  0 | 2000-01-01 08:13:12 |   6  |   M  |  1 |
|  1 | 2000-01-01 09:12:07 |   6  |   H  |  1 |
|  2 | 2000-01-01 08:12:29 |   6  |   S  |  1 |
+----+---------------------+------+------+----+
msh />
msh />rtc_al
rtc_alarm_create
rtc_alarm_delete
rtc_alarm_start
rtc_alarm_stop
msh />rtc_alarm_crw 
msh />rtc_alarm_cr 
rtc_alarm_create
msh />rtc_alarm_create 2
msh />rtc
rtc_gettime
rtc_alarm_create
rtc_alarm_delete
rtc_alarm_start
rtc_alarm_stop
msh />rtc_al
rtc_alarm_create
rtc_alarm_delete
rtc_alarm_start
rtc_alarm_stop
msh />rtc_alarm_star
rtc_alarm_start
msh />rtc_alarm_start 2
msh />[D/rtc.test] alarm_second_cb ok!

[D/rtc.test] alarm_second_cb ok!

[D/rtc.test] alarm_second_cb ok!

[D/rtc.test] alarm_second_cb ok!

rtc
rtc_gettime
rtc_alarm_create
rtc_alarm_delete
rtc_alarm_start
rtc_alarm_stop
msh />rtc_[D/rtc.test] alarm_second_cb ok!

a-[D/rtc.test] alarm_second_cb ok!

msh />rtc_a-[D/rtc.test] alarm_second_cb ok!
                                                                                                                                                           
rtc_alarm_create
rtc_alarm_delete
rtc_alarm_start
rtc_alarm_stop
msh />rtc_alarm_[D/rtc.test] alarm_second_cb ok!

s[D/rtc.test] alarm_second_cb ok!

rtc_alarm_start
rtc_alarm_stop
msh />rtc_alarm_st
rtc_alarm_start
rtc_alarm_stop
msh />rtc_alarm_sto
rtc_alarm_stop
msh />rtc_alarm_stop[D/rtc.test] alarm_second_cb ok!

rtc_alarm_stop
msh />rtc_alarm_stop
rtc_alarm_stop
msh />rtc_alarm_stop 2
msh />al
alarm_dump
msh />alarm_dump
| id | YYYY-MM-DD hh:mm:ss | week | flag | en |
+----+---------------------+------+------+----+
|  0 | 2000-01-01 08:13:05 |   6  |   S  |  0 |
|  1 | 2000-01-01 08:13:12 |   6  |   M  |  1 |
|  2 | 2000-01-01 09:12:07 |   6  |   H  |  1 |
|  3 | 2000-01-01 08:13:11 |   6  |   S  |  1 |
+----+---------------------+------+------+----+
msh />[D/rtc.test] alarm_minute_cb ok!
20 条评论

发布
问题