diff --git a/boards/avsextrem/Makefile.features b/boards/avsextrem/Makefile.features index af23a974c8..a62395a350 100644 --- a/boards/avsextrem/Makefile.features +++ b/boards/avsextrem/Makefile.features @@ -1 +1 @@ -FEATURES_PROVIDED += transceiver +FEATURES_PROVIDED += transceiver periph_rtc diff --git a/boards/avsextrem/include/periph_conf.h b/boards/avsextrem/include/periph_conf.h index b2dabf6c26..5a721fd413 100644 --- a/boards/avsextrem/include/periph_conf.h +++ b/boards/avsextrem/include/periph_conf.h @@ -45,6 +45,11 @@ extern "C" { #define PWM_0_CH2_PIN (4) #define PWM_0_FUNC (1) +/** + * @brief Real Time Clock configuration + */ +#define RTC_NUMOF (1) + #ifdef __cplusplus } #endif diff --git a/boards/chronos/Makefile.features b/boards/chronos/Makefile.features index 762734b956..5f9d34a50e 100644 --- a/boards/chronos/Makefile.features +++ b/boards/chronos/Makefile.features @@ -1 +1 @@ -FEATURES_PROVIDED = transceiver +FEATURES_PROVIDED = transceiver periph_rtc diff --git a/boards/chronos/include/periph_conf.h b/boards/chronos/include/periph_conf.h new file mode 100644 index 0000000000..7f825ab6fc --- /dev/null +++ b/boards/chronos/include/periph_conf.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2014 INRIA + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License v2.1. See the file LICENSE in the top level directory for more + * details. + */ + +/** + * @ingroup boards_chronos + * @{ + * + * @file + * @brief Chronos peripheral configuration + * + * @author Oliver Hahm + */ + +#ifndef PERIPH_CONF_H +#define PERIPH_CONF_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Real Time Clock configuration + */ +#define RTC_NUMOF (1) + +#ifdef __cplusplus +} +#endif + +#endif /* PERIPH_CONF_H */ diff --git a/boards/msb-430/include/periph_conf.h b/boards/msb-430/include/periph_conf.h new file mode 100644 index 0000000000..cf7bb61559 --- /dev/null +++ b/boards/msb-430/include/periph_conf.h @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2014 INRIA + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License v2.1. See the file LICENSE in the top level directory for more + * details. + */ + +/** + * @ingroup boards_msb430 + * @{ + * + * @file + * @brief MSB-430 peripheral configuration + * + * @author Oliver Hahm + */ + +#ifndef PERIPH_CONF_H +#define PERIPH_CONF_H + +/* make Travis happy: #ifdef __cplusplus extern "C" { #endif */ + +#endif /* PERIPH_CONF_H */ diff --git a/boards/msb-430h/include/periph_conf.h b/boards/msb-430h/include/periph_conf.h new file mode 100644 index 0000000000..c01b19e602 --- /dev/null +++ b/boards/msb-430h/include/periph_conf.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2014 INRIA + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License v2.1. See the file LICENSE in the top level directory for more + * details. + */ + +/** + * @ingroup boards_msb430h + * @{ + * + * @file + * @brief MSB-430h peripheral configuration + * + * @author Oliver Hahm + */ + +#ifndef PERIPH_CONF_H +#define PERIPH_CONF_H + +/* make Travis happy: #ifdef __cplusplus extern "C" { #endif */ + +#endif /* PERIPH_CONF_H */ + diff --git a/boards/msba2/Makefile.features b/boards/msba2/Makefile.features index ab02d7f760..66243c0812 100644 --- a/boards/msba2/Makefile.features +++ b/boards/msba2/Makefile.features @@ -1 +1 @@ -FEATURES_PROVIDED += transceiver periph_pwm cpp +FEATURES_PROVIDED += transceiver periph_pwm periph_rtc cpp diff --git a/boards/msba2/include/periph_conf.h b/boards/msba2/include/periph_conf.h index 3766bda25e..a9a7bdf3be 100644 --- a/boards/msba2/include/periph_conf.h +++ b/boards/msba2/include/periph_conf.h @@ -46,6 +46,11 @@ extern "C" { #define PWM_0_CH2_PIN (4) #define PWM_0_FUNC (1) +/** + * @brief Real Time Clock configuration + */ +#define RTC_NUMOF (1) + #ifdef __cplusplus } #endif diff --git a/boards/native/Makefile.features b/boards/native/Makefile.features index 2c1e593763..251d81bea6 100644 --- a/boards/native/Makefile.features +++ b/boards/native/Makefile.features @@ -1,2 +1,3 @@ FEATURES_PROVIDED += transceiver periph_cpuid cpp FEATURES_PROVIDED += periph_random +FEATURES_PROVIDED += periph_rtc diff --git a/boards/pttu/Makefile.features b/boards/pttu/Makefile.features index 9efa2cc57f..54bc2978ab 100644 --- a/boards/pttu/Makefile.features +++ b/boards/pttu/Makefile.features @@ -1,2 +1,3 @@ # Enable this after fixing https://github.com/RIOT-OS/RIOT/issues/659 #FEATURES_PROVIDED += transceiver +FEATURES_PROVIDED += periph_rtc diff --git a/boards/pttu/include/periph_conf.h b/boards/pttu/include/periph_conf.h index 9ad4d8e28b..ed13a5c78e 100644 --- a/boards/pttu/include/periph_conf.h +++ b/boards/pttu/include/periph_conf.h @@ -45,6 +45,11 @@ extern "C" { #define PWM_0_CH2_PIN (4) #define PWM_0_FUNC (1) +/** + * @brief Real Time Clock configuration + */ +#define RTC_NUMOF (1) + #ifdef __cplusplus } #endif diff --git a/boards/redbee-econotag/include/periph_conf.h b/boards/redbee-econotag/include/periph_conf.h new file mode 100644 index 0000000000..1fa2059b55 --- /dev/null +++ b/boards/redbee-econotag/include/periph_conf.h @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2014 INRIA + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License v2.1. See the file LICENSE in the top level directory for more + * details. + */ + +/** + * @ingroup boards_redbee-econotag + * @{ + * + * @file + * @brief Redbee Econotag peripheral configuration + * + * @author Oliver Hahm + */ + +#ifndef PERIPH_CONF_H +#define PERIPH_CONF_H + +/* make Travis happy: #ifdef __cplusplus extern "C" { #endif */ + +#endif /* PERIPH_CONF_H */ diff --git a/boards/telosb/include/periph_conf.h b/boards/telosb/include/periph_conf.h new file mode 100644 index 0000000000..ff1db5a34f --- /dev/null +++ b/boards/telosb/include/periph_conf.h @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2014 INRIA + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License v2.1. See the file LICENSE in the top level directory for more + * details. + */ + +/** + * @ingroup boards_telosb + * @{ + * + * @file + * @brief TelosB peripheral configuration + * + * @author Oliver Hahm + */ + +#ifndef PERIPH_CONF_H +#define PERIPH_CONF_H + +/* make Travis happy: #ifdef __cplusplus extern "C" { #endif */ + +#endif /* PERIPH_CONF_H */ diff --git a/boards/wsn430-common/include/periph_conf.h b/boards/wsn430-common/include/periph_conf.h new file mode 100644 index 0000000000..16a2f385f2 --- /dev/null +++ b/boards/wsn430-common/include/periph_conf.h @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2014 INRIA + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License v2.1. See the file LICENSE in the top level directory for more + * details. + */ + +/** + * @ingroup boards_wsn430-common + * @{ + * + * @file + * @brief WSN30 peripheral configuration + * + * @author Oliver Hahm + */ + +#ifndef PERIPH_CONF_H +#define PERIPH_CONF_H + +/* make Travis happy: #ifdef __cplusplus extern "C" { #endif */ + +#endif /* PERIPH_CONF_H */ diff --git a/boards/z1/include/periph_conf.h b/boards/z1/include/periph_conf.h new file mode 100644 index 0000000000..3f77da85c1 --- /dev/null +++ b/boards/z1/include/periph_conf.h @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2014 INRIA + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License v2.1. See the file LICENSE in the top level directory for more + * details. + */ + +/** + * @ingroup boards_z1 + * @{ + * + * @file + * @brief Zolertia Z1 peripheral configuration + * + * @author Oliver Hahm + */ + +#ifndef PERIPH_CONF_H +#define PERIPH_CONF_H + +/* make Travis happy: #ifdef __cplusplus extern "C" { #endif */ + +#endif /* PERIPH_CONF_H */ diff --git a/cpu/arm7_common/gettimeofday.c b/cpu/arm7_common/gettimeofday.c deleted file mode 100644 index a0ab89df05..0000000000 --- a/cpu/arm7_common/gettimeofday.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2013 Oliver Hahm - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - */ - -/** - * @file - * @ingroup arm7_common - * @brief LPC2387 Newlib gettimeofday() system call glue - * - * @author Michael Baar - * @author René Kijewski - */ - -#include -#include "kernel_types.h" - -#if defined MODULE_RTC -# include "rtc.h" -#elif defined MODULE_VTIMER -# include "vtimer.h" -#endif - -/* Declared as external, without a definition. */ -/* This will cause a linktime error, if _gettimeofday() is referenced, */ -/* and neither rtc nor vtimer were linked in. */ -extern void __gettimeofday_syscall_is_not_implemented_without_vtimer_or_rtc_module(void); - -int _gettimeofday(struct timeval *tp, void *restrict tzp) -{ - (void) tzp; - -#if defined MODULE_RTC - rtc_time(tp); -#elif defined MODULE_VTIMER - vtimer_gettimeofday(tp); -#else - (void) tp; - __gettimeofday_syscall_is_not_implemented_without_vtimer_or_rtc_module(); -#endif - - return 0; -} diff --git a/cpu/arm7_common/syscalls.c b/cpu/arm7_common/syscalls.c index 6d5ca835cd..383975754a 100644 --- a/cpu/arm7_common/syscalls.c +++ b/cpu/arm7_common/syscalls.c @@ -31,7 +31,7 @@ #include "kernel.h" #include "irq.h" #if defined MODULE_RTC -#include "rtc.h" +#include "periph/rtc.h" #elif defined MODULE_VTIMER #include "vtimer.h" #endif diff --git a/cpu/cc430/Makefile b/cpu/cc430/Makefile index 9ea7e86c47..bea70e4d1d 100644 --- a/cpu/cc430/Makefile +++ b/cpu/cc430/Makefile @@ -1,5 +1,5 @@ MODULE = cpu -DIRS = $(RIOTCPU)/msp430-common +DIRS = $(RIOTCPU)/msp430-common periph include $(RIOTBASE)/Makefile.base diff --git a/cpu/cc430/Makefile.include b/cpu/cc430/Makefile.include index cbad776158..4cf199e20f 100644 --- a/cpu/cc430/Makefile.include +++ b/cpu/cc430/Makefile.include @@ -1,3 +1,5 @@ INCLUDES += -I$(RIOTBASE)/cpu/cc430/include/ include $(RIOTCPU)/msp430-common/Makefile.include + +export USEMODULE += periph diff --git a/cpu/cc430/include/cc430-rtc.h b/cpu/cc430/include/cc430-rtc.h index ead80ecefb..2d95dfca6f 100644 --- a/cpu/cc430/include/cc430-rtc.h +++ b/cpu/cc430/include/cc430-rtc.h @@ -8,7 +8,7 @@ #ifndef CC430_RTC_H #define CC430_RTC_H -#include "rtc.h" +#include "periph/rtc.h" #include "time.h" #ifdef __cplusplus @@ -39,18 +39,6 @@ typedef enum { RTC_ALARM_DOM = 0x08 ///< Alarm mask for Day of Month } rtc_alarm_mask_t; -/** - * @brief Sets the alarm - * @internal - * @param[in] localt Alarm time - * @param[in] mask Sets the registers to poll for the alarm - * - * To disable the alarm set mask to RTC_ALARM_DISABLED. - * - * @see ::rtc_alarm_mask - */ -void rtc_set_alarm(struct tm *localti, rtc_alarm_mask_t mask); - /** * @brief Resets any set alarm */ diff --git a/cpu/lpc2387/rtc/Makefile b/cpu/cc430/periph/Makefile similarity index 100% rename from cpu/lpc2387/rtc/Makefile rename to cpu/cc430/periph/Makefile diff --git a/cpu/cc430/cc430-rtc.c b/cpu/cc430/periph/rtc.c similarity index 71% rename from cpu/cc430/cc430-rtc.c rename to cpu/cc430/periph/rtc.c index ec98840603..3b7572e503 100644 --- a/cpu/cc430/cc430-rtc.c +++ b/cpu/cc430/periph/rtc.c @@ -8,8 +8,8 @@ */ /** - * @ingroup rtc - * @file cc430-rtc.c + * @ingroup driver_periph_rtc + * @file * @brief CC430 real time clock implementation * @author Oliver Hahm */ @@ -20,51 +20,45 @@ #include "cpu.h" #include "cc430-rtc.h" -//static volatile time_t epoch; +/* Alarm callback */ +static rtc_alarm_cb_t _cb; + +/* Argument to alarm callback */ +static void *_cb_arg; + static struct tm time_to_set; static int set_time = 0; kernel_pid_t rtc_second_pid = KERNEL_PID_UNDEF; -/*---------------------------------------------------------------------------*/ void rtc_init(void) { /* Set to calendar mode */ RTCCTL1 |= RTCMODE_H; } -/*---------------------------------------------------------------------------*/ -void rtc_enable(void) +void rtc_poweron(void) { /* Set RTC operational */ RTCCTL1 &= ~RTCHOLD_H; } -/*---------------------------------------------------------------------------*/ -void rtc_disable(void) +void rtc_poweroff(void) { /* Stop RTC */ RTCCTL1 |= RTCHOLD_H; } -/*---------------------------------------------------------------------------*/ -void rtc_set_localtime(struct tm *localt) + +int rtc_set_time(struct tm *localt) { if (localt == NULL) { - return; + return -1; } /* copy time to be set */ memcpy(&time_to_set, localt, sizeof(struct tm)); set_time = 1; + return 0; } -/*--------------------------------------------------------------------------- -void rtc_set(time_t time) { - struct tm* localt; - localt = localtime(&time); // convert seconds to broken-down time - rtc_set_localtime(localt); - epoch = time - localt->tm_sec - localt->tm_min * 60; -} -*/ - /*--------------------------------------------------------------------------- time_t rtc_time(void) { time_t sec; @@ -74,15 +68,15 @@ time_t rtc_time(void) { return sec; } */ -/*---------------------------------------------------------------------------*/ -void rtc_get_localtime(struct tm *localt) + +int rtc_get_time(struct tm *localt) { uint8_t success = 0; uint8_t i; uint16_t tmpyear; if (localt == NULL) { - return; + return -1; } while (!success) { @@ -129,36 +123,53 @@ void rtc_get_localtime(struct tm *localt) } } } + + return 0; } -/*---------------------------------------------------------------------------*/ -void rtc_set_alarm(struct tm *localt, rtc_alarm_mask_t mask) +int rtc_set_alarm(struct tm *localt, rtc_alarm_cb_t cb, void *arg) { - if (mask & RTC_ALARM_MIN) { + if (localt != NULL) { RTCAMIN = localt->tm_min; RTCAMIN |= BIT7; - } - - if (mask & RTC_ALARM_HOUR) { RTCAHOUR = localt->tm_hour; RTCAHOUR |= BIT7; - } - - if (mask & RTC_ALARM_DOW) { RTCADOW = localt->tm_wday; RTCADOW |= BIT7; - } - - if (mask & RTC_ALARM_DOM) { RTCADAY = localt->tm_mday; RTCADAY |= BIT7; + + RTCCTL0 |= RTCAIE; + return 0; } - RTCCTL0 |= RTCAIE; + else if (cb == NULL) { + return -1; + } + + return -2; } -/*---------------------------------------------------------------------------*/ -void rtc_remove_alarm(void) +int rtc_get_alarm(struct tm *localt) +{ + if (localt != NULL) { + localt->tm_sec = -1; + localt->tm_min = RTCAMIN; + localt->tm_hour = RTCAHOUR; + localt->tm_mday = -1; + localt->tm_wday = RTCADOW; + localt->tm_yday = -1; + localt->tm_mon = - 1; + localt->tm_year = -1; + localt->tm_isdst = -1; /* not available */ + + return 0; + } + + return -1; +} + +void rtc_clear_alarm(void) { /* reset all AE bits */ RTCAHOUR &= ~BIT7; @@ -169,7 +180,7 @@ void rtc_remove_alarm(void) /* reset alarm interrupt enable */ RTCCTL0 &= ~RTCAIE; } -/*---------------------------------------------------------------------------*/ + interrupt(RTC_VECTOR) __attribute__((naked)) rtc_isr(void) { __enter_isr(); @@ -194,12 +205,15 @@ interrupt(RTC_VECTOR) __attribute__((naked)) rtc_isr(void) if (rtc_second_pid != KERNEL_PID_UNDEF) { static msg_t m; - m.type = RTC_SECOND; + m.type = RTCSEC; msg_send_int(&m, rtc_second_pid); } } /* RTC alarm */ else if (RTCIV == RTC_RTCAIFG) { + if (_cb) { + _cb(_cb_arg); + } } __exit_isr(); diff --git a/cpu/lpc2387/Makefile b/cpu/lpc2387/Makefile index bbe0498ed1..0425bcfc65 100644 --- a/cpu/lpc2387/Makefile +++ b/cpu/lpc2387/Makefile @@ -10,9 +10,6 @@ endif ifneq (,$(filter mci,$(USEMODULE))) DIRS += mci endif -ifneq (,$(filter rtc,$(USEMODULE))) - DIRS += rtc -endif ifneq (,$(filter i2c,$(USEMODULE))) DIRS += i2c endif diff --git a/cpu/lpc2387/include/lpc2387-rtc.h b/cpu/lpc2387/include/lpc2387-rtc.h deleted file mode 100644 index d0ca6f8d51..0000000000 --- a/cpu/lpc2387/include/lpc2387-rtc.h +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright 2008, Freie Universitaet Berlin (FUB). All rights reserved. - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - */ - -#ifndef LPC2387_RTC_H -#define LPC2387_RTC_H - -/** - * @defgroup lpc2387_rtc LPC2387 Real-Time-Clock - * @ingroup lpc2387 - * - * \section lpc2387_rtc_newlib Standard library support - * Currently reading and setting time and date through standard C functions is implemented. - * Standard C timers are not available. - * - * @{ - */ - -/** - * @file - * @brief LPC2387 Real-Time-Clock - * - * @author Freie Universität Berlin, Computer Systems & Telematics - * @version $Revision: 1998 $ - * - * @note $Id: lpc2387-rtc.h 1998 2010-03-16 13:05:41Z baar $ - */ - -#include -#include -#include "rtc.h" -#include "lpc2387.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* ------------------------------------------------------------------------- */ -/** - * @name LPC2387 RTC Compile-Time Configuration - * @{ - */ - -/** @} */ - -/** - * @brief Mask for RTC alarms - * @see ::rtc_set_alarm, ::rtc_get_alarm - */ -enum rtc_alarm_mask { - RTC_AMR_DISABLED = 0, ///< Alarm disables - RTC_AMR_SEC = AMRSEC, ///< Alarm mask for Seconds - RTC_AMR_MIN = AMRMIN, ///< Alarm mask for Minutes - RTC_AMR_HOUR = AMRHOUR, ///< Alarm mask for Hours - RTC_AMR_DOM = AMRDOM, ///< Alarm mask for Day of Month - RTC_AMR_DOW = AMRDOW, ///< Alarm mask for Day of Week - RTC_AMR_DOY = AMRDOY, ///< Alarm mask for Day of Year - RTC_AMR_MON = AMRMON, ///< Alarm mask for Month - RTC_AMR_YEAR = AMRYEAR, ///< Alarm mask for Year -}; - -void rtc_reset(void); - -/** - * @brief Returns the time of compilation in seconds - * @internal - */ -time_t rtc_get_compile_time(void) __attribute__((noinline)); - -/** - * @brief Returns the current clock time - * @param[out] time optional return value - * @return clock time in seconds - */ -time_t rtc_time(struct timeval *time); - -/** - * @brief Sets the current clock time - * @param[in] time new time in seconds - * @note Any set alarm is shifted - */ -void rtc_set(time_t time); - -/** - * @brief Sets the alarm - * @internal - * @param[in] localt Alarm time - * @param[in] mask Sets the registers to poll for the alarm - * - * To disable the alarm set mask to RTC_AMR_DISABLED. - * - * @see ::rtc_alarm_mask - */ -void rtc_set_alarm(struct tm *localt, enum rtc_alarm_mask mask); - -/** - * @brief Gets the current alarm setting - * @internal - * @param[out] localt Pointer to structure to receive alarm time - * @return Alarm mask - * - * @see rtc_set_alarm - * @see ::rtc_alarm_mask - */ -enum rtc_alarm_mask _rtc_get_alarm(struct tm *localt); - -#ifdef __cplusplus -} -#endif - -/** @} */ -#endif /* end __RTC_H */ diff --git a/cpu/lpc2387/rtc/lpc2387-rtc.c b/cpu/lpc2387/periph/rtc.c similarity index 52% rename from cpu/lpc2387/rtc/lpc2387-rtc.c rename to cpu/lpc2387/periph/rtc.c index f5dbb463ad..7eca711b31 100644 --- a/cpu/lpc2387/rtc/lpc2387-rtc.c +++ b/cpu/lpc2387/periph/rtc.c @@ -1,22 +1,12 @@ /* * Copyright 2008-2010, Freie Universitaet Berlin (FUB). All rights reserved. + * Copyright 2014 INRIA * * This file is subject to the terms and conditions of the GNU Lesser * General Public License v2.1. See the file LICENSE in the top level * directory for more details. */ -/** - * @file - * @ingroup lpc2387_rtc - * @brief LPC2387 Real-Time-Clock - * - * @author Michael Baar - * @version $Revision: 2005 $ - * - * @note $Id: lpc2387-rtc.c 2005 2010-03-17 10:52:03Z baar $ - */ - #include #include #include @@ -24,32 +14,54 @@ #include "kernel_types.h" /* cpu */ +#include "periph/rtc.h" #include "VIC.h" #include "lpc2387.h" -#include "lpc2387-rtc.h" #include "lpm.h" -#define PREINT_RTC 0x000001C8 /* Prescaler value, integer portion, PCLK = 15Mhz */ -#define PREFRAC_RTC 0x000061C0 /* Prescaler value, fraction portion, PCLK = 15Mhz */ - #define ENABLE_DEBUG (0) #include "debug.h" -/** - * @brief epoch time in hour granularity - */ -static volatile time_t epoch; +/* Alarm callback */ +static rtc_alarm_cb_t _cb; + +/* Argument to alarm callback */ +static void *_cb_arg; + +/* internal function to set time based on time_t */ +static void _rtc_set(time_t time); + +void RTC_IRQHandler(void) __attribute__((interrupt("IRQ"))); + +void rtc_init(void) +{ + PCONP |= BIT9; + RTC_AMR = 0xff; /* disable alarm irq */ + RTC_CIIR = 0; /* disable increase irq */ + RTC_CISS = 0; /* disable subsecond irq */ + + INTWAKE |= BIT15; /* rtc irq wakes up mcu from power down */ + + RTC_CCR = CCR_CLKSRC; /* Clock from external 32 kHz Osc. */ + + /* initialize clock with valid unix compatible values + * If RTC_YEAR contains an value larger unix time_t we must reset. */ + if (RTC_YEAR > 2037) { + _rtc_set(0); + } + + DEBUG("%2lu.%2lu.%4lu %2lu:%2lu:%2lu\n", + RTC_DOM, RTC_MONTH, RTC_YEAR, RTC_HOUR, RTC_MIN, RTC_SEC); +} -/*---------------------------------------------------------------------------*/ /** * @brief Sets the current time in broken down format directly from to RTC * @param[in] localt Pointer to structure with time to set */ -void -rtc_set_localtime(struct tm *localt) +int rtc_set_time(struct tm *localt) { if (localt == NULL) { - return; + return -1; } /* set clock */ @@ -61,158 +73,11 @@ rtc_set_localtime(struct tm *localt) RTC_DOY = localt->tm_yday; RTC_MONTH = localt->tm_mon + 1; RTC_YEAR = localt->tm_year; -} -/*---------------------------------------------------------------------------*/ -void rtc_set(time_t time) -{ - struct tm *localt; - localt = localtime(&time); /* convert seconds to broken-down time */ - rtc_set_localtime(localt); - epoch = time - localt->tm_sec - localt->tm_min * 60; -} -/*---------------------------------------------------------------------------*/ -//* set clock to start of unix epoch */ -void rtc_reset(void) -{ - rtc_set(0); - epoch = 0; -} -/*---------------------------------------------------------------------------*/ -void -rtc_set_alarm(struct tm *localt, enum rtc_alarm_mask mask) -{ - if (localt != NULL) { - RTC_ALSEC = localt->tm_sec; - RTC_ALMIN = localt->tm_min; - RTC_ALHOUR = localt->tm_hour; - RTC_ALDOM = localt->tm_mday; - RTC_ALDOW = localt->tm_wday; - RTC_ALDOY = localt->tm_yday; - RTC_ALMON = localt->tm_mon + 1; - RTC_ALYEAR = localt->tm_year; - RTC_AMR = ~mask; /* set wich alarm fields to check */ - DEBUG("alarm set %2lu.%2lu.%4lu %2lu:%2lu:%2lu\n", - RTC_ALDOM, RTC_ALMON, RTC_ALYEAR, RTC_ALHOUR, RTC_ALMIN, RTC_ALSEC); - } - else { - RTC_AMR = 0xff; - } -} -/*---------------------------------------------------------------------------*/ -enum rtc_alarm_mask -rtc_get_alarm(struct tm *localt) -{ - if (localt != NULL) { - localt->tm_sec = RTC_ALSEC; - localt->tm_min = RTC_ALMIN; - localt->tm_hour = RTC_ALHOUR; - localt->tm_mday = RTC_ALDOM; - localt->tm_wday = RTC_ALDOW; - localt->tm_yday = RTC_ALDOY; - localt->tm_mon = RTC_ALMON - 1; - localt->tm_year = RTC_ALYEAR; - localt->tm_isdst = -1; /* not available */ - } - return (~RTC_AMR) & 0xff; /* return which alarm fields are checked */ -} -/*---------------------------------------------------------------------------*/ -void RTC_IRQHandler(void) __attribute__((interrupt("IRQ"))); -void RTC_IRQHandler(void) -{ - lpm_begin_awake(); - - if (RTC_ILR & ILR_RTSSF) { - /* sub second interrupt (does not need flag-clearing) */ - - } - else if (RTC_ILR & ILR_RTCCIF) { - /* counter increase interrupt */ - RTC_ILR |= ILR_RTCCIF; - epoch += 60 * 60; /* add 1 hour */ - - } - else if (RTC_ILR & ILR_RTCALF) { - RTC_ILR |= ILR_RTCALF; - RTC_AMR = 0xff; /* disable alarm irq */ - DEBUG("Ring\n"); - lpm_end_awake(); - } - - VICVectAddr = 0; /* Acknowledge Interrupt */ + return 0; } -/*---------------------------------------------------------------------------*/ -void rtc_enable(void) -{ - RTC_ILR = (ILR_RTSSF | ILR_RTCCIF | ILR_RTCALF); /* clear interrupt flags */ - RTC_CCR |= CCR_CLKEN; /* enable clock */ - install_irq(RTC_INT, &RTC_IRQHandler, IRQP_RTC); /* install interrupt handler */ - - time_t now = rtc_time(NULL); - epoch = now - (now % 3600); -} -/*---------------------------------------------------------------------------*/ -void rtc_init(void) -{ - PCONP |= BIT9; - RTC_AMR = 0xff; /* disable alarm irq */ - RTC_CIIR = IMHOUR; /* enable increase irq */ - RTC_CISS = 0; /* disable subsecond irq */ - - INTWAKE |= BIT15; /* rtc irq wakes up mcu from power down */ - - RTC_CCR = CCR_CLKSRC; /* Clock from external 32 kHz Osc. */ - - /* initialize clock with valid unix compatible values - * If RTC_YEAR contains an value larger unix time_t we must reset. */ - if (RTC_YEAR > 2037) { - rtc_reset(); - } - - DEBUG("%2lu.%2lu.%4lu %2lu:%2lu:%2lu epoch %lu\n", - RTC_DOM, RTC_MONTH, RTC_YEAR, RTC_HOUR, RTC_MIN, RTC_SEC, - epoch); -} -/*---------------------------------------------------------------------------*/ -time_t rtc_time(struct timeval *time) -{ - uint32_t sec; - uint32_t usec; - uint32_t min; - - usec = (RTC_CTC >> 1); - sec = RTC_SEC; - min = RTC_MIN; - - while (usec != (RTC_CTC >> 1)) { - usec = (RTC_CTC >> 1); - sec = RTC_SEC; - min = RTC_MIN; - } - - sec += min * 60; /* add number of minutes */ - sec += epoch; /* add precalculated epoch in hour granularity */ - - if (time != NULL) { - usec = usec * 15625; - usec >>= 9; - time->tv_sec = sec; - time->tv_usec = usec; - } - - return sec; -} -/*---------------------------------------------------------------------------*/ -void rtc_disable(void) -{ - RTC_CCR &= ~CCR_CLKEN; /* disable clock */ - install_irq(RTC_INT, NULL, 0); - RTC_ILR = 0; -} -/*---------------------------------------------------------------------------*/ -void -rtc_get_localtime(struct tm *localt) +int rtc_get_time(struct tm *localt) { if (localt != NULL) { localt->tm_sec = RTC_SEC; @@ -224,16 +89,104 @@ rtc_get_localtime(struct tm *localt) localt->tm_mon = RTC_MONTH - 1; localt->tm_year = RTC_YEAR; localt->tm_isdst = -1; /* not available */ + return 0; } + return -1; } -/*---------------------------------------------------------------------------*/ -void gettimeofday_r(struct _reent *r, struct timeval *ptimeval, struct timezone *ptimezone) + + +int rtc_set_alarm(struct tm *localt, rtc_alarm_cb_t cb, void *arg) { - (void) ptimezone; /* unused */ + if (localt != NULL) { + RTC_ALSEC = localt->tm_sec; + RTC_ALMIN = localt->tm_min; + RTC_ALHOUR = localt->tm_hour; + RTC_ALDOM = localt->tm_mday; + RTC_ALDOW = localt->tm_wday; + RTC_ALDOY = localt->tm_yday; + RTC_ALMON = localt->tm_mon + 1; + RTC_ALYEAR = localt->tm_year; + RTC_AMR = 0; /* set wich alarm fields to check */ + DEBUG("alarm set %2lu.%2lu.%4lu %2lu:%2lu:%2lu\n", + RTC_ALDOM, RTC_ALMON, RTC_ALYEAR, RTC_ALHOUR, RTC_ALMIN, RTC_ALSEC); - r->_errno = 0; - - if (ptimeval != NULL) { - rtc_time(ptimeval); + _cb = cb; + return 0; } + else if (cb == NULL) { + return -1; + } + + RTC_AMR = 0xff; + return -2; +} + +int rtc_get_alarm(struct tm *localt) +{ + if (localt != NULL) { + localt->tm_sec = RTC_ALSEC; + localt->tm_min = RTC_ALMIN; + localt->tm_hour = RTC_ALHOUR; + localt->tm_mday = RTC_ALDOM; + localt->tm_wday = RTC_ALDOW; + localt->tm_yday = RTC_ALDOY; + localt->tm_mon = RTC_ALMON - 1; + localt->tm_year = RTC_ALYEAR; + localt->tm_isdst = -1; /* not available */ + + return 0; + } + + return -1; +} + +void rtc_clear_alarm(void) +{ + RTC_AMR = 0xff; +} + +void rtc_poweron(void) +{ + PCONP |= BIT9; + RTC_ILR = (ILR_RTSSF | ILR_RTCCIF | ILR_RTCALF); /* clear interrupt flags */ + RTC_CCR |= CCR_CLKEN; /* enable clock */ + install_irq(RTC_INT, &RTC_IRQHandler, IRQP_RTC); /* install interrupt handler */ +} + +void rtc_poweroff(void) +{ + RTC_CCR &= ~CCR_CLKEN; /* disable clock */ + install_irq(RTC_INT, NULL, 0); + RTC_ILR = 0; + PCONP &= ~BIT9; +} + +void RTC_IRQHandler(void) +{ + lpm_begin_awake(); + + if (RTC_ILR & ILR_RTSSF) { + /* sub second interrupt (does not need flag-clearing) */ + } + else if (RTC_ILR & ILR_RTCCIF) { + /* counter increase interrupt */ + } + else if (RTC_ILR & ILR_RTCALF) { + RTC_ILR |= ILR_RTCALF; + RTC_AMR = 0xff; /* disable alarm irq */ + if (_cb) { + _cb(_cb_arg); + } + DEBUG("Ring\n"); + lpm_end_awake(); + } + + VICVectAddr = 0; /* Acknowledge Interrupt */ +} + +static void _rtc_set(time_t time) +{ + struct tm *localt; + localt = localtime(&time); /* convert seconds to broken-down time */ + rtc_set_time(localt); } diff --git a/cpu/native/Makefile b/cpu/native/Makefile index 628d7eb5a3..7447a2006c 100644 --- a/cpu/native/Makefile +++ b/cpu/native/Makefile @@ -1,7 +1,6 @@ MODULE = cpu DIRS += periph -DIRS += drivers ifneq (,$(filter nativenet,$(USEMODULE))) DIRS += net endif diff --git a/cpu/native/drivers/Makefile b/cpu/native/drivers/Makefile deleted file mode 100644 index 439af37cdc..0000000000 --- a/cpu/native/drivers/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -ifneq (,$(filter rtc,$(USEMODULE))) - DIRS += rtc -endif - -include $(RIOTBASE)/Makefile.base diff --git a/cpu/native/drivers/rtc/Makefile b/cpu/native/drivers/rtc/Makefile deleted file mode 100644 index 7d178b6174..0000000000 --- a/cpu/native/drivers/rtc/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -include $(RIOTBASE)/Makefile.base - -INCLUDES = $(NATIVEINCLUDES) diff --git a/cpu/native/drivers/rtc/posix-rtc.c b/cpu/native/drivers/rtc/posix-rtc.c deleted file mode 100644 index 95aa424064..0000000000 --- a/cpu/native/drivers/rtc/posix-rtc.c +++ /dev/null @@ -1,93 +0,0 @@ -/** - * Native CPU rtc.h implementation - * - * The native rtc implementation uses POSIX system calls to simulate a - * real-time clock. - * - * Setting the clock will be implemented using a delta variable. - * - * Copyright (C) 2013 Ludwig Ortmann - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - * - * @author Ludwig Ortmann - * - * @ingroup native_cpu - * @ingroup rtc - * @file - */ - -#include -#include -#include - -#include "debug.h" - -#include "rtc.h" -#include "cpu.h" - -#include "native_internal.h" - -static int native_rtc_enabled; -static int native_rtc_initialized; - -void rtc_init(void) -{ - native_rtc_enabled = 0; - native_rtc_initialized = 1; - printf("native rtc initialized\n"); -} - -void rtc_enable(void) -{ - DEBUG("rtc_enable\n"); - if (native_rtc_initialized == 1) { - native_rtc_enabled = 1; - } - else { - DEBUG("rtc not initialized, not enabling\n"); - } -} - -void rtc_disable(void) -{ - DEBUG("rtc_disable()\n"); - native_rtc_enabled = 0; -} - -void rtc_set_localtime(struct tm *localt) -{ - DEBUG("rtc_set_localtime()\n"); - - (void)localt; /* not implemented atm */ - printf("setting time not supported."); -} - -void rtc_get_localtime(struct tm *localt) -{ - time_t t; - - if (native_rtc_enabled == 1) { - _native_syscall_enter(); - t = time(NULL); - - if (localtime_r(&t, localt) == NULL) { - err(EXIT_FAILURE, "rtc_get_localtime: localtime_r"); - } - _native_syscall_leave(); - } -} - -time_t rtc_time(struct timeval *time) -{ - if (native_rtc_enabled == 1) { - _native_syscall_enter(); - if (gettimeofday(time, NULL) == -1) { - err(EXIT_FAILURE, "rtc_time: gettimeofday"); - } - _native_syscall_leave(); - } - return time->tv_sec; -} diff --git a/cpu/native/include/periph_conf.h b/cpu/native/include/periph_conf.h index 0774418052..a4655e110b 100644 --- a/cpu/native/include/periph_conf.h +++ b/cpu/native/include/periph_conf.h @@ -27,6 +27,13 @@ #define RANDOM_NUMOF (1U) /** @} */ +/** + * @name RealTime Clock configuration + * @{ + */ +#define RTC_NUMOF (1) +/** @} */ + #ifdef __cplusplus } #endif diff --git a/cpu/native/periph/rtc.c b/cpu/native/periph/rtc.c new file mode 100644 index 0000000000..23b066c39b --- /dev/null +++ b/cpu/native/periph/rtc.c @@ -0,0 +1,181 @@ +/* + * Copyright (C) 2013, 2014 Ludwig Ortmann + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * Native CPU periph/rtc.h implementation + * + * The implementation uses POSIX system calls to emulate a real-time + * clock based on the system clock. + * + * @author Ludwig Ortmann + * + * @ingroup _native_cpu + * @defgroup _native_rtc + * @file + */ + +#include +#include +#include +#include + +#include "periph/rtc.h" +#include "cpu.h" + +#include "native_internal.h" + +#define ENABLE_DEBUG (0) +#include "debug.h" + +static int _native_rtc_initialized = 0; +static int _native_rtc_powered = 0; +static struct tm _native_rtc_alarm; +static rtc_alarm_cb_t _native_rtc_alarm_callback; +static void *_native_rtc_alarm_argument; + +void rtc_init(void) +{ + DEBUG("rtc_init\n"); + + memset(&_native_rtc_alarm, 0, sizeof(_native_rtc_alarm)); + _native_rtc_alarm_callback = NULL; + _native_rtc_alarm_argument = NULL; + + _native_rtc_initialized = 1; + printf("Native RTC initialized.\n"); + + rtc_poweron(); +} + +void rtc_poweron(void) +{ + DEBUG("rtc_poweron\n"); + + if (!_native_rtc_initialized) { + warnx("rtc_poweron: not initialized"); + return; + } + + _native_rtc_powered = 1; +} + +void rtc_poweroff(void) +{ + DEBUG("rtc_poweroff()\n"); + + if (!_native_rtc_initialized) { + warnx("rtc_poweroff: not initialized"); + } + if (!_native_rtc_powered) { + warnx("rtc_poweroff: not powered on"); + } + + _native_rtc_powered = 0; +} + +/* TODO: implement time setting using a delta */ +int rtc_set_time(struct tm *ttime) +{ + (void) ttime; + + DEBUG("rtc_set_time()\n"); + + if (!_native_rtc_initialized) { + warnx("rtc_set_time: not initialized"); + return -1; + } + if (!_native_rtc_powered) { + warnx("rtc_set_time: not powered on"); + return -1; + } + + warnx("rtc_set_time: not implemented"); + + return -1; +} + +int rtc_get_time(struct tm *ttime) +{ + time_t t; + + if (!_native_rtc_initialized) { + warnx("rtc_get_time: not initialized"); + return -1; + } + if (!_native_rtc_powered) { + warnx("rtc_get_time: not powered on"); + return -1; + } + + _native_syscall_enter(); + t = time(NULL); + + if (localtime_r(&t, ttime) == NULL) { + err(EXIT_FAILURE, "rtc_get_time: localtime_r"); + } + _native_syscall_leave(); + + return 0; +} + +/* TODO: implement alarm scheduling */ +int rtc_set_alarm(struct tm *time, rtc_alarm_cb_t cb, void *arg) +{ + (void) time; + (void) cb; + (void) arg; + + if (!_native_rtc_initialized) { + warnx("rtc_set_alarm: not initialized"); + return -1; + } + if (!_native_rtc_powered) { + warnx("rtc_set_alarm: not powered on"); + return -1; + } + + memcpy(&_native_rtc_alarm, time, sizeof(_native_rtc_alarm)); + + warnx("rtc_set_alarm: not implemented"); + + return -1; +} + +int rtc_get_alarm(struct tm *time) +{ + (void) time; + + if (!_native_rtc_initialized) { + warnx("rtc_get_alarm: not initialized"); + return -1; + } + if (!_native_rtc_powered) { + warnx("rtc_get_alarm: not powered on"); + return -1; + } + + memcpy(time, &_native_rtc_alarm, sizeof(_native_rtc_alarm)); + + return 0; +} + +/* TODO: implement alarm unscheduling once rtc_set_alarm is + * implemented */ +void rtc_clear_alarm(void) +{ + DEBUG("rtc_clear_alarm()\n"); + + if (!_native_rtc_initialized) { + warnx("rtc_clear_alarm: not initialized"); + } + if (!_native_rtc_powered) { + warnx("rtc_clear_alarm: not powered on"); + } + + memset(&_native_rtc_alarm, 0, sizeof(_native_rtc_alarm)); +} diff --git a/drivers/include/rtc.h b/drivers/include/rtc.h deleted file mode 100644 index 81bd6bd96d..0000000000 --- a/drivers/include/rtc.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2010, Freie Universitaet Berlin (FUB). All rights reserved. - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - */ - -/** - * @defgroup rtc Realtime Clock - * @ingroup drivers - * @brief Generic real time clock driver interface - * @{ - */ - -#ifndef RTC_H -#define RTC_H - -#define RTC_SECOND 10001U - -#include -#include -#include "kernel_types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Initializes the RTC for calendar mode - */ -void rtc_init(void); - -/** - * @brief Starts the RTC - */ -void rtc_enable(void); - -/** - * @brief Stops the RTC - */ -void rtc_disable(void); - -/** - * @brief Sets the current time in broken down format directly from to RTC - * @param[in] localt Pointer to structure with time to set - */ -void rtc_set_localtime(struct tm *localt); - -/** - * @brief Returns the current time in broken down format directly from the RTC - * @param[out] localt Pointer to structure to receive time - */ -void rtc_get_localtime(struct tm *localt); - -/** - * @brief Get the current time as a struct timeval - * @param[out] time Pointer to structure to receive time - */ -time_t rtc_time(struct timeval *time); - -extern kernel_pid_t rtc_second_pid; - -#ifdef __cplusplus -} -#endif - -/** @} */ -#endif diff --git a/examples/ccn-lite-relay/main.c b/examples/ccn-lite-relay/main.c index 4d12a9c121..6684116026 100644 --- a/examples/ccn-lite-relay/main.c +++ b/examples/ccn-lite-relay/main.c @@ -26,7 +26,7 @@ // riot #include "thread.h" -#include "rtc.h" +#include "periph/rtc.h" // ccn #include "ccn_lite/ccnl-riot.h" diff --git a/examples/default/Makefile b/examples/default/Makefile index cfb50016c1..6c96ecea35 100644 --- a/examples/default/Makefile +++ b/examples/default/Makefile @@ -37,6 +37,7 @@ USEMODULE += vtimer USEMODULE += defaulttransceiver FEATURES_OPTIONAL += transceiver +FEATURES_OPTIONAL += periph_rtc ifneq (,$(filter msb-430,$(BOARD))) USEMODULE += sht11 @@ -44,14 +45,12 @@ endif ifneq (,$(filter msba2,$(BOARD))) USEMODULE += sht11 USEMODULE += ltc4150 - USEMODULE += rtc USEMODULE += mci USEMODULE += config USEMODULE += random endif ifneq (,$(filter native,$(BOARD))) USEMODULE += ltc4150 - USEMODULE += rtc USEMODULE += config USEMODULE += random endif diff --git a/examples/default/main.c b/examples/default/main.c index 311a57605b..437d4c5bd4 100644 --- a/examples/default/main.c +++ b/examples/default/main.c @@ -31,6 +31,10 @@ #include "shell_commands.h" #include "board_uart0.h" +#if FEATURE_PERIPH_RTC +#include "periph/rtc.h" +#endif + #ifdef MODULE_LTC4150 #include "ltc4150.h" #endif @@ -156,6 +160,10 @@ int main(void) init_transceiver(); #endif +#ifdef FEATURE_PERIPH_RTC + rtc_init(); +#endif + (void) puts("Welcome to RIOT!"); shell_init(&shell, NULL, UART0_BUFSIZE, shell_readc, shell_putchar); diff --git a/sys/auto_init/auto_init.c b/sys/auto_init/auto_init.c index a570959551..86cbaf7acd 100644 --- a/sys/auto_init/auto_init.c +++ b/sys/auto_init/auto_init.c @@ -52,7 +52,7 @@ #endif #ifdef MODULE_RTC -#include "rtc.h" +#include "periph/rtc.h" #endif #ifdef MODULE_SIXLOWPAN @@ -214,7 +214,6 @@ void auto_init(void) #ifdef MODULE_RTC DEBUG("Auto init rtc module.\n"); rtc_init(); - rtc_enable(); #endif #ifdef MODULE_SHT11 DEBUG("Auto init SHT11 module.\n"); diff --git a/sys/shell/commands/Makefile b/sys/shell/commands/Makefile index bf71eb0dba..6dd26cc09f 100644 --- a/sys/shell/commands/Makefile +++ b/sys/shell/commands/Makefile @@ -31,9 +31,6 @@ endif ifneq (,$(filter rpl,$(USEMODULE))) SRC += sc_rpl.c endif -ifneq (,$(filter rtc,$(USEMODULE))) - SRC += sc_rtc.c -endif ifneq (,$(filter sht11,$(USEMODULE))) SRC += sc_sht11.c endif @@ -59,4 +56,11 @@ ifneq (,$(filter lsm303dlhc,$(USEMODULE))) SRC += sc_lsm303dlhc.c endif +# TODO +# Conditional building not possible at the moment due to +# https://github.com/RIOT-OS/RIOT/issues/2058 +# The implementation is guarded in the source file instead, this +# should be changed once the issue has been resolved +SRC += sc_rtc.c + include $(RIOTBASE)/Makefile.base diff --git a/sys/shell/commands/sc_rtc.c b/sys/shell/commands/sc_rtc.c index 456066e49e..b7bcdabf2e 100644 --- a/sys/shell/commands/sc_rtc.c +++ b/sys/shell/commands/sc_rtc.c @@ -1,76 +1,187 @@ -/** - * Shell commands for real time clock - * - * Copyright (C) 2013 INRIA. +/* + * Copyright 2013 INRIA. + * Copyright 2014 Ludwig Ortmann * * This file is subject to the terms and conditions of the GNU Lesser * General Public License v2.1. See the file LICENSE in the top level * directory for more details. - * + */ + +/** * @ingroup shell_commands * @{ - * @file sc_rtc.c - * @brief provides shell commands to access the rtc + * @file + * @brief Shell command implementation for the peripheral RTC interface + * * @author Oliver Hahm + * @author Ludwig Ortmann * @} */ +#ifdef FEATURE_PERIPH_RTC + #include #include #include +#include -#ifdef MODULE_RTC -#include "rtc.h" +#include "periph/rtc.h" -static void _gettime_handler(void) +void _alarm_handler(void *arg) { - struct tm now; - rtc_get_localtime(&now); + (void) arg; - /* cppcheck: see man 3 asctime: obsoleted by POSIX.1-2008 */ - /* cppcheck-suppress obsoleteFunctionsasctime */ - printf("%s", asctime(&now)); + puts("The alarm rang"); } -static void _settime_handler(char **argv) +static int dow(int year, int month, int day) { - do { - short i1, i2, i3; - - int res = sscanf(argv[1], "%6hd-%6hd-%6hd", &i1, &i2, &i3); - if (res != 3) { - break; - } - - struct tm now; - now.tm_year = i1 - 1900; - now.tm_mon = i2 - 1; - now.tm_mday = i3; - - res = sscanf(argv[2], "%6hd:%6hd:%6hd", &i1, &i2, &i3); - if (res != 3) { - break; - } - now.tm_hour = i1; - now.tm_min = i2; - now.tm_sec = i3; - - rtc_set_localtime(&now); - puts("OK"); - return; - } while (0); - - printf("Usage: %s YYYY-MM-DD hh:mm:ss\n", argv[0]); + /* calculate the day of week using Tøndering's algorithm */ + static int t[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4}; + year -= month < 3; + return (year + year/4 - year/100 + year/400 + t[month-1] + day) % 7; } -void _date_handler(int argc, char **argv) + +static int _parse_time(char **argv, struct tm *time) { - if (argc != 3) { - _gettime_handler(); + short i; + char *end; + + i = strtol(argv[0], &end, 10); + time->tm_year = i - 1900; + + i = strtol(end + 1, &end, 10); + time->tm_mon = i - 1; + + i = strtol(end + 1, &end, 10); + time->tm_mday = i; + + i = strtol(argv[1], &end, 10); + time->tm_hour = i; + + i = strtol(end + 1, &end, 10); + time->tm_min = i; + + i = strtol(end + 1, &end, 10); + time->tm_sec = i; + + time->tm_wday = dow(time->tm_year + 1900, time->tm_mon + 1, time->tm_mday); + time->tm_isdst = -1; /* undefined */ + + return 0; +} + +static void _print_time(struct tm *time) +{ + printf("%04i-%02i-%02i %02i:%02i:%02i\n", + time->tm_year + 1900, time->tm_mon + 1, time->tm_mday, + time->tm_hour, time->tm_min, time->tm_sec + ); +} + +static void _rtc_getalarm(void) +{ + struct tm t; + if (rtc_get_alarm(&t) == 0) { + _print_time(&t); } else { - _settime_handler(argv); + puts("rtc: error getting alarm"); } } -#endif +static void _rtc_setalarm(char **argv) +{ + struct tm now; + + if (_parse_time(argv, &now) == 0) { + if (rtc_set_alarm(&now, _alarm_handler, NULL) == -1) { + puts("rtc: error setting alarm"); + } + } +} + +static void _rtc_gettime(void) +{ + struct tm t; + if (rtc_get_time(&t) == 0) { + _print_time(&t); + } + else { + puts("rtc: error getting time"); + } +} + +static void _rtc_settime(char **argv) +{ + struct tm now; + + if (_parse_time(argv, &now) == 0) { + if (rtc_set_time(&now) == -1) { + puts("rtc: error setting time"); + } + } +} + +static void _rtc_usage(void) +{ + puts("usage: rtc [arguments]"); + puts("commands:"); + puts("\tinit\t\tinitialize the interface"); + puts("\tpoweron\t\tpower the interface on"); + puts("\tpoweroff\tpower the interface off"); + puts("\tclearalarm\tdeactivate the current alarm"); + puts("\tgetalarm\tprint the currently alarm time"); + puts("\tsetalarm YYYY-MM-DD HH:MM:SS\n\t\t\tset an alarm for the specified time"); + puts("\tgettime\t\tprint the current time"); + puts("\tsettime YYYY-MM-DD HH:MM:SS\n\t\t\tset the current time"); +} + +void _rtc_handler(int argc, char **argv) +{ + if (argc < 2) { + _rtc_usage(); + } + else if (strncmp(argv[1], "init", 4) == 0) { + rtc_init(); + } + else if (strncmp(argv[1], "poweron", 7) == 0) { + rtc_poweron(); + } + else if (strncmp(argv[1], "poweroff", 8) == 0) { + rtc_poweroff(); + } + else if (strncmp(argv[1], "clearalarm", 8) == 0) { + rtc_clear_alarm(); + } + else if (strncmp(argv[1], "getalarm", 8) == 0) { + _rtc_getalarm(); + } + else if (strncmp(argv[1], "setalarm", 8) == 0) { + _rtc_setalarm(argv + 2); + } + else if (strncmp(argv[1], "gettime", 7) == 0) { + _rtc_gettime(); + } + else if (strncmp(argv[1], "settime", 7) == 0) { + _rtc_settime(argv + 2); + } + else { + printf("unknown command: %s\n", argv[1]); + } +} + +#else + +#include + +void _rtc_handler(int argc, char **argv) +{ + (void) argc; + (void) argv; + + puts("not implemented"); +} + +#endif /* FEATURE_RTC */ diff --git a/sys/shell/commands/shell_commands.c b/sys/shell/commands/shell_commands.c index 90f381aa87..d9d8b1b92c 100644 --- a/sys/shell/commands/shell_commands.c +++ b/sys/shell/commands/shell_commands.c @@ -38,10 +38,6 @@ extern void _heap_handler(int argc, char **argv); extern void _ps_handler(int argc, char **argv); #endif -#ifdef MODULE_RTC -extern void _date_handler(int argc, char **argv); -#endif - #ifdef MODULE_SHT11 extern void _get_temperature_handler(int argc, char **argv); extern void _get_humidity_handler(int argc, char **argv); @@ -74,6 +70,10 @@ extern void _get_current_handler(int argc, char **argv); extern void _reset_current_handler(int argc, char **argv); #endif +#if FEATURE_PERIPH_RTC +extern void _rtc_handler(int argc, char **argv); +#endif + #ifdef CPU_X86 extern void _x86_lspci(int argc, char **argv); #endif @@ -162,9 +162,6 @@ const shell_command_t _shell_command_list[] = { #ifdef MODULE_PS {"ps", "Prints information about running threads.", _ps_handler}, #endif -#ifdef MODULE_RTC - {"date", "Gets or sets current date and time.", _date_handler}, -#endif #ifdef MODULE_SHT11 {"temp", "Prints measured temperature.", _get_temperature_handler}, {"hum", "Prints measured humidity.", _get_humidity_handler}, @@ -241,6 +238,9 @@ const shell_command_t _shell_command_list[] = { { "mersenne_init", "initializes the PRNG", _mersenne_init }, { "mersenne_get", "returns 32 bit of pseudo randomness", _mersenne_get }, #endif +#if FEATURE_PERIPH_RTC + {"rtc", "control RTC peripheral interface", _rtc_handler}, +#endif #ifdef CPU_X86 {"lspci", "Lists PCI devices", _x86_lspci}, #endif