186 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			186 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 * Copyright (c) 2006-2018, RT-Thread Development Team
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * SPDX-License-Identifier: Apache-2.0
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Change Logs:
							 | 
						||
| 
								 | 
							
								 * Date           Author       Notes
							 | 
						||
| 
								 | 
							
								 * 2009-04-26     yi.qiu       	first version
							 | 
						||
| 
								 | 
							
								 * 2010-03-18     Gary Lee	add functions such as GregorianDay
							 | 
						||
| 
								 | 
							
								 *                             		and rtc_time_to_tm
							 | 
						||
| 
								 | 
							
								 * 2009-03-20     yi.qiu       	clean up
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <rtthread.h>
							 | 
						||
| 
								 | 
							
								#include <time.h>
							 | 
						||
| 
								 | 
							
								#include <s3c24x0.h>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// #define RTC_DEBUG
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define RTC_ENABLE		RTCCON |=  0x01;	/*RTC read and write enable */
							 | 
						||
| 
								 | 
							
								#define RTC_DISABLE		RTCCON &= ~0x01;	/* RTC read and write disable */
							 | 
						||
| 
								 | 
							
								#define BCD2BIN(n)		(((((n) >> 4) & 0x0F) * 10) + ((n) & 0x0F))
							 | 
						||
| 
								 | 
							
								#define BIN2BCD(n)		((((n) / 10) << 4) | ((n) % 10))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * This function get rtc time
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								void rt_hw_rtc_get(struct tm *ti)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									rt_uint8_t sec, min, hour, mday, wday, mon, year;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* enable access to RTC registers */
							 | 
						||
| 
								 | 
							
									RTCCON |= RTC_ENABLE;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* read RTC registers */
							 | 
						||
| 
								 | 
							
									do
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										sec 	= BCDSEC;
							 | 
						||
| 
								 | 
							
										min 	= BCDMIN;
							 | 
						||
| 
								 | 
							
										hour 	= BCDHOUR;
							 | 
						||
| 
								 | 
							
										mday	= BCDDATE;
							 | 
						||
| 
								 | 
							
										wday 	= BCDDAY;
							 | 
						||
| 
								 | 
							
										mon 	= BCDMON;
							 | 
						||
| 
								 | 
							
										year 	= BCDYEAR;
							 | 
						||
| 
								 | 
							
								    } while (sec != BCDSEC);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef RTC_DEBUG
							 | 
						||
| 
								 | 
							
									rt_kprintf("sec:%x min:%x hour:%x mday:%x wday:%x mon:%x year:%x\n",
							 | 
						||
| 
								 | 
							
										sec, min, hour, mday, wday, mon, year);
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* disable access to RTC registers */
							 | 
						||
| 
								 | 
							
									RTC_DISABLE
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									ti->tm_sec  	= BCD2BIN(sec  & 0x7F);
							 | 
						||
| 
								 | 
							
									ti->tm_min  	= BCD2BIN(min  & 0x7F);
							 | 
						||
| 
								 | 
							
									ti->tm_hour 	= BCD2BIN(hour & 0x3F);
							 | 
						||
| 
								 | 
							
									ti->tm_mday 	= BCD2BIN(mday & 0x3F);
							 | 
						||
| 
								 | 
							
									ti->tm_mon  	= BCD2BIN(mon & 0x1F);
							 | 
						||
| 
								 | 
							
									ti->tm_year 	= BCD2BIN(year);
							 | 
						||
| 
								 | 
							
									ti->tm_wday 	= BCD2BIN(wday & 0x07);
							 | 
						||
| 
								 | 
							
									ti->tm_yday 	= 0;
							 | 
						||
| 
								 | 
							
									ti->tm_isdst 	= 0;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * This function set rtc time
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								void rt_hw_rtc_set(struct tm *ti)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									rt_uint8_t sec, min, hour, mday, wday, mon, year;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									year	= BIN2BCD(ti->tm_year);
							 | 
						||
| 
								 | 
							
									mon 	= BIN2BCD(ti->tm_mon);
							 | 
						||
| 
								 | 
							
									wday 	= BIN2BCD(ti->tm_wday);
							 | 
						||
| 
								 | 
							
									mday 	= BIN2BCD(ti->tm_mday);
							 | 
						||
| 
								 | 
							
									hour 	= BIN2BCD(ti->tm_hour);
							 | 
						||
| 
								 | 
							
									min 	= BIN2BCD(ti->tm_min);
							 | 
						||
| 
								 | 
							
									sec 	= BIN2BCD(ti->tm_sec);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* enable access to RTC registers */
							 | 
						||
| 
								 | 
							
									RTC_ENABLE
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									do{
							 | 
						||
| 
								 | 
							
										/* write RTC registers */
							 | 
						||
| 
								 | 
							
										BCDSEC 		= sec;
							 | 
						||
| 
								 | 
							
										BCDMIN 		= min;
							 | 
						||
| 
								 | 
							
										BCDHOUR 	= hour;
							 | 
						||
| 
								 | 
							
										BCDDATE 	= mday;
							 | 
						||
| 
								 | 
							
										BCDDAY 		= wday;
							 | 
						||
| 
								 | 
							
										BCDMON 	= mon;
							 | 
						||
| 
								 | 
							
										BCDYEAR 	= year;
							 | 
						||
| 
								 | 
							
									}while (sec != BCDSEC);
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									/* disable access to RTC registers */
							 | 
						||
| 
								 | 
							
									RTC_DISABLE
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * This function reset rtc
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								void rt_hw_rtc_reset (void)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									RTCCON = (RTCCON & ~0x06) | 0x08;
							 | 
						||
| 
								 | 
							
									RTCCON &= ~(0x08|0x01);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static struct rt_device rtc;
							 | 
						||
| 
								 | 
							
								static rt_err_t rtc_open(rt_device_t dev, rt_uint16_t oflag)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									RTC_ENABLE
							 | 
						||
| 
								 | 
							
									return RT_EOK;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static rt_err_t rtc_close(rt_device_t dev)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									RTC_DISABLE
							 | 
						||
| 
								 | 
							
									return RT_EOK;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static rt_size_t rtc_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									return RT_EOK;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static rt_err_t rtc_control(rt_device_t dev, int cmd, void *args)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									struct tm tm, *tm_ptr;
							 | 
						||
| 
								 | 
							
								    time_t *time;
							 | 
						||
| 
								 | 
							
									RT_ASSERT(dev != RT_NULL);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									time = (time_t *)args;
							 | 
						||
| 
								 | 
							
									switch (cmd)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
									case RT_DEVICE_CTRL_RTC_GET_TIME:
							 | 
						||
| 
								 | 
							
										/* read device */
							 | 
						||
| 
								 | 
							
										rt_hw_rtc_get(&tm);
							 | 
						||
| 
								 | 
							
										*((rt_time_t *)args) = mktime(&tm);
							 | 
						||
| 
								 | 
							
										break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									case RT_DEVICE_CTRL_RTC_SET_TIME:
							 | 
						||
| 
								 | 
							
										tm_ptr = localtime(time);
							 | 
						||
| 
								 | 
							
										/* write device */
							 | 
						||
| 
								 | 
							
										rt_hw_rtc_set(tm_ptr);
							 | 
						||
| 
								 | 
							
										break;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return RT_EOK;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void rt_hw_rtc_init(void)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									rtc.type	= RT_Device_Class_RTC;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* register rtc device */
							 | 
						||
| 
								 | 
							
									rtc.init 	= RT_NULL;
							 | 
						||
| 
								 | 
							
									rtc.open 	= rtc_open;
							 | 
						||
| 
								 | 
							
									rtc.close	= rtc_close;
							 | 
						||
| 
								 | 
							
									rtc.read 	= rtc_read;
							 | 
						||
| 
								 | 
							
									rtc.write	= RT_NULL;
							 | 
						||
| 
								 | 
							
									rtc.control = rtc_control;
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									/* no private */
							 | 
						||
| 
								 | 
							
									rtc.user_data = RT_NULL;
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									rt_device_register(&rtc, "rtc", RT_DEVICE_FLAG_RDWR);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef RT_USING_FINSH
							 | 
						||
| 
								 | 
							
								#include <finsh.h>
							 | 
						||
| 
								 | 
							
								void list_date()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									time_t time;
							 | 
						||
| 
								 | 
							
									rt_device_t device;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									device = rt_device_find("rtc");
							 | 
						||
| 
								 | 
							
									if (device != RT_NULL)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										rt_device_control(device, RT_DEVICE_CTRL_RTC_GET_TIME, &time);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										rt_kprintf("%d, %s\n", time, ctime(&time));
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								FINSH_FUNCTION_EXPORT(list_date, list date);
							 | 
						||
| 
								 | 
							
								#endif
							 |