STM32F103X hal RTThread rtc驱动支持日期保存

发布时间:2024-01-20 08:03:35

之前那篇移植的驱动(地址https://blog.csdn.net/Mooney_yuan/article/details/83377428)似乎有点问题,验证的时候发现RTC实际上没有起作用。实际上开始时测试过可以工作的,但现在在我板子上测试不行,所以重新改写了一下,并且解决了STM32 HAL驱动RTC掉电后日期无法保存的问题。

环境

1. 开发板,正点原子ALIENTEK MiniSTM32 V3.4

2. rtthread 3.1.0

1. 增加drv_rtc.c驱动文件

添加drv_rtc.c文件到 bsp/stm32f10x-HAL/drivers 目录下,修改该目录下的SConscript文件,增加drv_rtc.c编译选择
?


if GetDepend(['RT_USING_RTC']):

    src += ['drv_rtc.c']

2. 配置rtthread

通过env的menuconfig命令,打开 RT-Thread Components -> Device Drivers?

[*] Using RTC device drivers      
 [ ]   Using software simulation RTC device    
 [ ]   Using NTP auto sync RTC time

3.?drv_rtc.c源码

/*
 * Copyright (c) 2006-2018, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2017-10-25     ZYH      first implementation
 */
#include "drv_rtc.h"
#include <board.h>
#include <rtdevice.h>
#include <string.h>
#include <time.h>
#ifndef RT_USING_SOFT_RTC
RTC_HandleTypeDef hrtc;
uint8_t time_synced;
#define BKUP_REG_DATA 0xA5A5
/* RTC init function */
void MX_RTC_Init(void)
{
    __HAL_RCC_PWR_CLK_ENABLE();
    __HAL_RCC_BKP_CLK_ENABLE();
    RCC_OscInitTypeDef RCC_OscInitStruct = {0};
#ifdef BSP_RTC_USING_LSI
    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;
#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);   

    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_TimeTypeDef sTime;
    // RTC_DateTypeDef sDate;

    /**Initialize RTC Only
    */
    hrtc.Instance = RTC;

    if (HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR1) != BKUP_REG_DATA)
    {
        hrtc.Init.OutPut = RTC_OUTPUTSOURCE_NONE;
        hrtc.Init.AsynchPrediv = 32767;

        RT_ASSERT(HAL_RTC_Init(&hrtc) == HAL_OK);

        // sTime.Hours = 11;
        // sTime.Minutes = 34;
        // sTime.Seconds = 0;
        // RT_ASSERT(HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BIN) == HAL_OK);
        // sDate.WeekDay = 5;
        // sDate.Month = 03;
        // sDate.Date = 13;
        // sDate.Year = 20;
        // RT_ASSERT(HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BIN) == HAL_OK);
        HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR1, BKUP_REG_DATA);
    }
    else {
        time_synced = 1;
    }

    // // hrtc.Init.AsynchPrediv = RTC_AUTO_1_SECOND;
    // hrtc.Init.AsynchPrediv = 32767;
    // hrtc.Init.OutPut = RTC_OUTPUTSOURCE_NONE;
    // RT_ASSERT(HAL_RTC_Init(&hrtc) == HAL_OK);
    /**Initialize RTC and set the Time and Date
    */
    // if (HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR1) != 0x5050)
    // {
    //     sTime.Hours = 9;
    //     sTime.Minutes = 46;
    //     sTime.Seconds = 0;
    //     RT_ASSERT(HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BIN) == HAL_OK);
    //     sDate.WeekDay = 4;
    //     sDate.Month = 10;
    //     sDate.Date = 25;
    //     sDate.Year = 18;
    //     RT_ASSERT(HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BIN) == HAL_OK);
    //     HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR1, 0x5050);
    // }
}
#if 0
void HAL_RTC_MspInit(RTC_HandleTypeDef *rtcHandle)
{
    RCC_OscInitTypeDef RCC_OscInitStruct;
    RCC_PeriphCLKInitTypeDef PeriphClkInitStruct;
    RTC_TimeTypeDef sTime;
    RTC_DateTypeDef sDate;

    __HAL_RCC_PWR_CLK_ENABLE();
    __HAL_RCC_BKP_CLK_ENABLE();
	HAL_PWR_EnableBkUpAccess();
    if (HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR1) != 0x5050)
    {
        sTime.Hours = 9;
        sTime.Minutes = 46;
        sTime.Seconds = 0;
        RT_ASSERT(HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BIN) == HAL_OK);
        sDate.WeekDay = 4;
        sDate.Month = 10;
        sDate.Date = 25;
        sDate.Year = 18;
        RT_ASSERT(HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BIN) == HAL_OK);
        HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR1, 0x5050);

    #if 1
        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;
        HAL_RCC_OscConfig(&RCC_OscInitStruct);

        PeriphClkInitStruct.PeriphClockSelection=RCC_PERIPHCLK_RTC;
        PeriphClkInitStruct.RTCClockSelection=RCC_RTCCLKSOURCE_LSE;
        HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);
    #else
        RCC_OscInitStruct.OscillatorType=RCC_OSCILLATORTYPE_LSI;
        RCC_OscInitStruct.PLL.PLLState=RCC_PLL_ON;
        RCC_OscInitStruct.LSIState=RCC_LSI_ON;              
        HAL_RCC_OscConfig(&RCC_OscInitStruct);

        PeriphClkInitStruct.PeriphClockSelection=RCC_PERIPHCLK_RTC;
        PeriphClkInitStruct.RTCClockSelection=RCC_RTCCLKSOURCE_LSI;
        HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);          
    #endif
        __HAL_RCC_RTC_ENABLE();  
    }          
}
#endif

void HAL_RTC_MspDeInit(RTC_HandleTypeDef *rtcHandle)
{
    __HAL_RCC_PWR_CLK_DISABLE();
    __HAL_RCC_RTC_DISABLE();
}

extern uint32_t           RTC_ReadTimeCounter(RTC_HandleTypeDef* hrtc);
extern HAL_StatusTypeDef  RTC_WriteTimeCounter(RTC_HandleTypeDef* hrtc, uint32_t TimeCounter);
static rt_err_t stm32_rtc_control(struct rt_device *dev,
                                  int              cmd,
                                  void             *args)
{
    struct tm *tm_now;
    struct tm now;
    RTC_TimeTypeDef sTime;
    RTC_DateTypeDef sDate;

    switch (cmd)
    {
    case RT_DEVICE_CTRL_RTC_GET_TIME:
        // HAL_RTC_GetTime(&hrtc, &sTime, RTC_FORMAT_BIN);
        // HAL_RTC_GetDate(&hrtc, &sDate, RTC_FORMAT_BIN);
        // printf("get rtc time:%02d:%02d:%02d\r\n",sTime.Hours,sTime.Minutes,sTime.Seconds);
        // now.tm_hour = sTime.Hours;
        // now.tm_min = sTime.Minutes;
        // now.tm_sec = sTime.Seconds;
        // now.tm_year = sDate.Year + 100;
        // now.tm_mon = sDate.Month - 1;
        // now.tm_mday = sDate.Date;
        // *((time_t *)args) = mktime(&now);
        *((uint32_t *)args) = RTC_ReadTimeCounter(&hrtc);
        break;
    case RT_DEVICE_CTRL_RTC_SET_TIME:
        // rt_enter_critical();
        // /* converts calendar time time into local time. */
        // tm_now = localtime((const time_t *) args);
        // /* copy the statically located variable */
        // memcpy(&now, tm_now, sizeof(struct tm));
        // /* unlock scheduler. */
        // rt_exit_critical();

        // sTime.Hours = now.tm_hour;
        // sTime.Minutes = now.tm_min;
        // sTime.Seconds = now.tm_sec;
        // sDate.Year = now.tm_year - 100;
        // sDate.Month = now.tm_mon + 1;
        // sDate.Date = now.tm_mday;
        // HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BIN);
        // HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BIN);
        RTC_WriteTimeCounter(&hrtc, *((uint32_t *)args));
        break;
    }
    return RT_EOK;
}

static rt_err_t stm32_rtc_init(struct rt_device *dev)
{
    return RT_EOK;
}

static rt_err_t stm32_rtc_open(struct rt_device *dev, rt_uint16_t oflag)
{
    return RT_EOK;
}

static rt_err_t stm32_rtc_close(struct rt_device *dev)
{
    return RT_EOK;
}

static rt_size_t stm32_rtc_read(struct rt_device *dev,
                                rt_off_t          pos,
                                void             *buffer,
                                rt_size_t         size)
{
    stm32_rtc_control(dev, RT_DEVICE_CTRL_RTC_GET_TIME, buffer);
    return size;
}

static rt_size_t stm32_rtc_write(struct rt_device *dev,
                                 rt_off_t          pos,
                                 const void       *buffer,
                                 rt_size_t         size)
{
    stm32_rtc_control(dev, RT_DEVICE_CTRL_RTC_SET_TIME, (void *)buffer);
    return size;
}

struct rt_device rtc_device;
int rt_hw_rtc_init(void)
{
    MX_RTC_Init();
    rtc_device.type        = RT_Device_Class_RTC;
    rtc_device.rx_indicate = RT_NULL;
    rtc_device.tx_complete = RT_NULL;
    rtc_device.init        = stm32_rtc_init;
    rtc_device.open        = stm32_rtc_open;
    rtc_device.close       = stm32_rtc_close;
    rtc_device.read        = stm32_rtc_read;
    rtc_device.write       = stm32_rtc_write;
    rtc_device.control     = stm32_rtc_control;
    rtc_device.user_data   = RT_NULL;
    /* register a character device */
    return rt_device_register(&rtc_device, "rtc", RT_DEVICE_FLAG_DEACTIVATE);
}
INIT_BOARD_EXPORT(rt_hw_rtc_init);
#endif

4. 修改HAL库文件 Libraies/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rtc.c

因为上面的驱动引用了这个文件中的两个static函数,所以把这两个static函数的声明改成全局的

 .../Libraries/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rtc.c   | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/bsp/stm32f10x-HAL/Libraries/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rtc.c b/bsp/stm32f10x-HAL/Libraries/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rtc.c
index f25541d..cc22b7c 100644
--- a/bsp/stm32f10x-HAL/Libraries/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rtc.c
+++ b/bsp/stm32f10x-HAL/Libraries/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rtc.c
@@ -190,8 +190,10 @@
 /** @defgroup RTC_Private_Functions RTC Private Functions
   * @{
   */
-static uint32_t           RTC_ReadTimeCounter(RTC_HandleTypeDef* hrtc);
-static HAL_StatusTypeDef  RTC_WriteTimeCounter(RTC_HandleTypeDef* hrtc, uint32_t TimeCounter);
+// static uint32_t           RTC_ReadTimeCounter(RTC_HandleTypeDef* hrtc);
+// static HAL_StatusTypeDef  RTC_WriteTimeCounter(RTC_HandleTypeDef* hrtc, uint32_t TimeCounter);
+ uint32_t           RTC_ReadTimeCounter(RTC_HandleTypeDef* hrtc);
+ HAL_StatusTypeDef  RTC_WriteTimeCounter(RTC_HandleTypeDef* hrtc, uint32_t TimeCounter);
 static uint32_t           RTC_ReadAlarmCounter(RTC_HandleTypeDef* hrtc);
 static HAL_StatusTypeDef  RTC_WriteAlarmCounter(RTC_HandleTypeDef* hrtc, uint32_t AlarmCounter);
 static HAL_StatusTypeDef  RTC_EnterInitMode(RTC_HandleTypeDef* hrtc);
@@ -1357,7 +1359,8 @@ HAL_StatusTypeDef HAL_RTC_WaitForSynchro(RTC_HandleTypeDef* hrtc)
   *                the configuration information for RTC.
   * @retval Time counter
   */
-static uint32_t RTC_ReadTimeCounter(RTC_HandleTypeDef* hrtc)
+// static uint32_t RTC_ReadTimeCounter(RTC_HandleTypeDef* hrtc)
+uint32_t RTC_ReadTimeCounter(RTC_HandleTypeDef* hrtc)
 {
   uint16_t high1 = 0U, high2 = 0U, low = 0U;
   uint32_t timecounter = 0U;
@@ -1387,7 +1390,8 @@ static uint32_t RTC_ReadTimeCounter(RTC_HandleTypeDef* hrtc)
   * @param  TimeCounter: Counter to write in RTC_CNT registers
   * @retval HAL status
   */
-static HAL_StatusTypeDef RTC_WriteTimeCounter(RTC_HandleTypeDef* hrtc, uint32_t TimeCounter)
+// static HAL_StatusTypeDef RTC_WriteTimeCounter(RTC_HandleTypeDef* hrtc, uint32_t TimeCounter)
+HAL_StatusTypeDef RTC_WriteTimeCounter(RTC_HandleTypeDef* hrtc, uint32_t TimeCounter)
 {
   HAL_StatusTypeDef status = HAL_OK;
   

?

文章来源:https://blog.csdn.net/Mooney_yuan/article/details/104973755
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。