From 5ed2d0ea3bf0fd5cfb83b22548d55db6754453be Mon Sep 17 00:00:00 2001 From: FlyM Date: Tue, 29 Sep 2015 06:53:44 +0800 Subject: [PATCH] [bsp]add stm32f4xx bsp rtc driver --- bsp/stm32f40x/drivers/stm32f4_rtc.c | 247 ++++++++++++++++++++++++++++ bsp/stm32f40x/drivers/stm32f4_rtc.h | 23 +++ 2 files changed, 270 insertions(+) create mode 100644 bsp/stm32f40x/drivers/stm32f4_rtc.c create mode 100644 bsp/stm32f40x/drivers/stm32f4_rtc.h diff --git a/bsp/stm32f40x/drivers/stm32f4_rtc.c b/bsp/stm32f40x/drivers/stm32f4_rtc.c new file mode 100644 index 0000000000..b949f4510b --- /dev/null +++ b/bsp/stm32f40x/drivers/stm32f4_rtc.c @@ -0,0 +1,247 @@ +/* + * File : stm32f4_rtc.c + * This file is stm32f4 rtc driver part of RT-Thread RTOS + * COPYRIGHT (C) 2009, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2015-09-29 FlyM the first version. + */ +#include +#include +#include +#include "stm32f4_rtc.h" + +static int get_week(int year, int month, int day) +{ + if (month==1||month==2) + { + year -=1; + month +=12; + } + return (day+1+2*month+3*(month+1)/5+year+(year/4)-year/100+year/400)%7; +} + +static struct rt_device rtc; +static rt_err_t rt_rtc_open(rt_device_t dev, rt_uint16_t oflag) +{ + if (dev->rx_indicate != RT_NULL) + { + /* Open Interrupt */ + } + + return RT_EOK; +} + +static rt_size_t rt_rtc_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size) +{ + return 0; +} + +static rt_err_t rt_rtc_control(rt_device_t dev, rt_uint8_t cmd, void *args) +{ + rt_time_t *time; + RT_ASSERT(dev != RT_NULL); + + switch (cmd) + { + case RT_DEVICE_CTRL_RTC_GET_TIME: + { + struct tm ct; + RTC_TimeTypeDef t; + RTC_DateTypeDef d; + + rt_memset(&ct,0,sizeof(struct tm)); + time = (rt_time_t *)args; + /* read device */ + RTC_GetDate(RTC_Format_BIN,&d); + RTC_GetTime(RTC_Format_BIN,&t); + + ct.tm_year = d.RTC_Year + 100; + ct.tm_mon = d.RTC_Month - 1; + ct.tm_mday = d.RTC_Date; + ct.tm_wday = d.RTC_WeekDay; + + ct.tm_hour = t.RTC_Hours; + ct.tm_min = t.RTC_Minutes; + ct.tm_sec = t.RTC_Seconds; + + *time = mktime(&ct); + } + break; + + case RT_DEVICE_CTRL_RTC_SET_TIME: + { + struct tm *ct; + struct tm tm_new; + time_t *time; + RTC_TimeTypeDef RTC_TimeStructure; + RTC_InitTypeDef RTC_InitStructure; + RTC_DateTypeDef RTC_DateStructure; + + time = (time_t *)args; + /* lock scheduler. */ + rt_enter_critical(); + /* converts calendar time time into local time. */ + ct = localtime(time); + /* copy the statically located variable */ + rt_memcpy(&tm_new, ct, sizeof(struct tm)); + /* unlock scheduler. */ + rt_exit_critical(); + /* Enable the PWR clock */ + RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE); + /* Allow access to RTC */ + PWR_BackupAccessCmd(ENABLE); + /* ck_spre(1Hz) = RTCCLK(LSI) /(uwAsynchPrediv + 1)*(uwSynchPrediv + 1)*/ + //uwSynchPrediv = 0xFF; + //uwAsynchPrediv = 0x7F; + /* Configure the RTC data register and RTC prescaler */ + RTC_InitStructure.RTC_AsynchPrediv = 0x7F; + RTC_InitStructure.RTC_SynchPrediv = 0xFF; + RTC_InitStructure.RTC_HourFormat = RTC_HourFormat_24; + RTC_Init(&RTC_InitStructure); + /* Set the date */ + RTC_DateStructure.RTC_Year = tm_new.tm_year - 100; + RTC_DateStructure.RTC_Month = tm_new.tm_mon + 1; + RTC_DateStructure.RTC_Date = tm_new.tm_mday; + RTC_DateStructure.RTC_WeekDay = get_week(tm_new.tm_year+1900,tm_new.tm_mon+1,tm_new.tm_mday); + RTC_SetDate(RTC_Format_BIN, &RTC_DateStructure); + /* Set the time*/ + if (tm_new.tm_hour > 11) + { + RTC_TimeStructure.RTC_H12 = RTC_H12_PM; + } + else + { + RTC_TimeStructure.RTC_H12 = RTC_H12_AM; + } + RTC_TimeStructure.RTC_Hours = tm_new.tm_hour; + RTC_TimeStructure.RTC_Minutes = tm_new.tm_min; + RTC_TimeStructure.RTC_Seconds = tm_new.tm_sec; + + RTC_SetTime(RTC_Format_BIN, &RTC_TimeStructure); + + /* Indicator for the RTC configuration */ + RTC_WriteBackupRegister(RTC_BKP_DR0, 0x32F2); + } + break; + } + + return RT_EOK; +} + +/******************************************************************************* +* Function Name : RTC_Configuration +* Description : Configures the RTC. +* Input : None +* Output : None +* Return : 0 reday,-1 error. +*******************************************************************************/ +int RTC_Configuration(void) +{ + /* Enable the PWR clock */ + RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE); + + /* Allow access to RTC */ + PWR_BackupAccessCmd(ENABLE); + +#if defined (RTC_CLOCK_SOURCE_LSI) /* LSI used as RTC source clock*/ + /* The RTC Clock may varies due to LSI frequency dispersion */ + /* Enable the LSI OSC */ + RCC_LSICmd(ENABLE); + + /* Wait till LSI is ready */ + while(RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET) + { + } + + /* Select the RTC Clock Source */ + RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI); + + /* ck_spre(1Hz) = RTCCLK(LSI) /(uwAsynchPrediv + 1)*(uwSynchPrediv + 1)*/ + //uwSynchPrediv = 0xFF; + //uwAsynchPrediv = 0x7F; + +#elif defined (RTC_CLOCK_SOURCE_LSE) /* LSE used as RTC source clock */ + /* Enable the LSE OSC */ + RCC_LSEConfig(RCC_LSE_ON); + + /* Wait till LSE is ready */ + while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET) + { + } + /* Select the RTC Clock Source */ + RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); + +#else +#error Please select the RTC Clock source inside the main.c file +#endif /* RTC_CLOCK_SOURCE_LSI */ + + /* Enable the RTC Clock */ + RCC_RTCCLKCmd(ENABLE); + + /* Wait for RTC APB registers synchronisation */ + RTC_WaitForSynchro(); + + return 0; +} + +void rt_hw_rtc_init(void) +{ + rtc.type = RT_Device_Class_RTC; + + if (RTC_ReadBackupRegister(RTC_BKP_DR0) != 0x32F2) + { + rt_kprintf("rtc is not configured\n"); + rt_kprintf("please configure with set_date and set_time\n"); + if ( RTC_Configuration() != 0) + { + rt_kprintf("rtc configure fail...\r\n"); + return ; + } + } + else + { + /* Wait for RTC registers synchronization */ + RTC_WaitForSynchro(); + } + + /* register rtc device */ + rtc.init = RT_NULL; + rtc.open = rt_rtc_open; + rtc.close = RT_NULL; + rtc.read = rt_rtc_read; + rtc.write = RT_NULL; + rtc.control = rt_rtc_control; + + /* no private */ + rtc.user_data = RT_NULL; + + rt_device_register(&rtc, "rtc", RT_DEVICE_FLAG_RDWR); + + return; +} + +#ifdef RT_USING_FINSH +#include "finsh.h" +void show_time(void) +{ + RTC_TimeTypeDef t; + RTC_DateTypeDef d; + /* Get the current Date */ + RTC_GetDate(RTC_Format_BIN,&d); + /* Get the current Time */ + RTC_GetTime(RTC_Format_BIN, &t); + /* Display time Format : hh:mm:ss */ + rt_kprintf("Now Time = 20%02d %02d %02d[%02d]-%0.2d:%0.2d:%0.2d \r\n", \ + d.RTC_Year,d.RTC_Month,d.RTC_Date,d.RTC_WeekDay,t.RTC_Hours, t.RTC_Minutes, t.RTC_Seconds); +} + +FINSH_FUNCTION_EXPORT(show_time, show current time.) +#endif + + diff --git a/bsp/stm32f40x/drivers/stm32f4_rtc.h b/bsp/stm32f40x/drivers/stm32f4_rtc.h new file mode 100644 index 0000000000..42fa4ebed7 --- /dev/null +++ b/bsp/stm32f40x/drivers/stm32f4_rtc.h @@ -0,0 +1,23 @@ +/* + * File : stm32f4_rtc.h + * This file is stm32f4 rtc driver part of RT-Thread RTOS + * COPYRIGHT (C) 2009, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2015-09-29 FlyM the first version + */ + +#ifndef __STM32F4_RTC_H__ +#define __STM32F4_RTC_H__ + +#define RTC_CLOCK_SOURCE_LSE + +void rt_hw_rtc_init(void); + +#endif +