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
 |