1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2025-01-18 12:52:44 +01:00

Merge pull request #2060 from OlegHahm/periph_rtc

drivers: Adapt old platforms to periph rtc
This commit is contained in:
Ludwig Ortmann 2014-12-16 18:56:59 +01:00
commit e7f6f640f6
39 changed files with 763 additions and 636 deletions

View File

@ -1 +1 @@
FEATURES_PROVIDED += transceiver
FEATURES_PROVIDED += transceiver periph_rtc

View File

@ -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

View File

@ -1 +1 @@
FEATURES_PROVIDED = transceiver
FEATURES_PROVIDED = transceiver periph_rtc

View File

@ -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 <oliver.hahm@inria.fr>
*/
#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 */

View File

@ -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 <oliver.hahm@inria.fr>
*/
#ifndef PERIPH_CONF_H
#define PERIPH_CONF_H
/* make Travis happy: #ifdef __cplusplus extern "C" { #endif */
#endif /* PERIPH_CONF_H */

View File

@ -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 <oliver.hahm@inria.fr>
*/
#ifndef PERIPH_CONF_H
#define PERIPH_CONF_H
/* make Travis happy: #ifdef __cplusplus extern "C" { #endif */
#endif /* PERIPH_CONF_H */

View File

@ -1 +1 @@
FEATURES_PROVIDED += transceiver periph_pwm cpp
FEATURES_PROVIDED += transceiver periph_pwm periph_rtc cpp

View File

@ -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

View File

@ -1,2 +1,3 @@
FEATURES_PROVIDED += transceiver periph_cpuid cpp
FEATURES_PROVIDED += periph_random
FEATURES_PROVIDED += periph_rtc

View File

@ -1,2 +1,3 @@
# Enable this after fixing https://github.com/RIOT-OS/RIOT/issues/659
#FEATURES_PROVIDED += transceiver
FEATURES_PROVIDED += periph_rtc

View File

@ -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

View File

@ -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 <oliver.hahm@inria.fr>
*/
#ifndef PERIPH_CONF_H
#define PERIPH_CONF_H
/* make Travis happy: #ifdef __cplusplus extern "C" { #endif */
#endif /* PERIPH_CONF_H */

View File

@ -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 <oliver.hahm@inria.fr>
*/
#ifndef PERIPH_CONF_H
#define PERIPH_CONF_H
/* make Travis happy: #ifdef __cplusplus extern "C" { #endif */
#endif /* PERIPH_CONF_H */

View File

@ -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 <oliver.hahm@inria.fr>
*/
#ifndef PERIPH_CONF_H
#define PERIPH_CONF_H
/* make Travis happy: #ifdef __cplusplus extern "C" { #endif */
#endif /* PERIPH_CONF_H */

View File

@ -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 <oliver.hahm@inria.fr>
*/
#ifndef PERIPH_CONF_H
#define PERIPH_CONF_H
/* make Travis happy: #ifdef __cplusplus extern "C" { #endif */
#endif /* PERIPH_CONF_H */

View File

@ -1,46 +0,0 @@
/*
* Copyright (C) 2013 Oliver Hahm <oliver.hahm@inria.fr>
*
* 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 <michael.baar@fu-berlin.de>
* @author René Kijewski <rene.kijewski@fu-berlin.de>
*/
#include <sys/time.h>
#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;
}

View File

@ -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

View File

@ -1,5 +1,5 @@
MODULE = cpu
DIRS = $(RIOTCPU)/msp430-common
DIRS = $(RIOTCPU)/msp430-common periph
include $(RIOTBASE)/Makefile.base

View File

@ -1,3 +1,5 @@
INCLUDES += -I$(RIOTBASE)/cpu/cc430/include/
include $(RIOTCPU)/msp430-common/Makefile.include
export USEMODULE += periph

View File

@ -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
*/

View File

@ -8,8 +8,8 @@
*/
/**
* @ingroup rtc
* @file cc430-rtc.c
* @ingroup driver_periph_rtc
* @file
* @brief CC430 real time clock implementation
* @author Oliver Hahm <oliver.hahm@inria.fr>
*/
@ -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;
}
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();

View File

@ -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

View File

@ -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 <time.h>
#include <sys/time.h>
#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 */

View File

@ -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 <michael.baar@fu-berlin.de>
* @version $Revision: 2005 $
*
* @note $Id: lpc2387-rtc.c 2005 2010-03-17 10:52:03Z baar $
*/
#include <sys/time.h>
#include <stdint.h>
#include <string.h>
@ -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);
}

View File

@ -1,7 +1,6 @@
MODULE = cpu
DIRS += periph
DIRS += drivers
ifneq (,$(filter nativenet,$(USEMODULE)))
DIRS += net
endif

View File

@ -1,5 +0,0 @@
ifneq (,$(filter rtc,$(USEMODULE)))
DIRS += rtc
endif
include $(RIOTBASE)/Makefile.base

View File

@ -1,3 +0,0 @@
include $(RIOTBASE)/Makefile.base
INCLUDES = $(NATIVEINCLUDES)

View File

@ -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 <ludwig.ortmann@fu-berlin.de>
*
* 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 <ludwig.ortmann@fu-berlin.de>
*
* @ingroup native_cpu
* @ingroup rtc
* @file
*/
#include <time.h>
#include <stdlib.h>
#include <err.h>
#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;
}

View File

@ -27,6 +27,13 @@
#define RANDOM_NUMOF (1U)
/** @} */
/**
* @name RealTime Clock configuration
* @{
*/
#define RTC_NUMOF (1)
/** @} */
#ifdef __cplusplus
}
#endif

181
cpu/native/periph/rtc.c Normal file
View File

@ -0,0 +1,181 @@
/*
* Copyright (C) 2013, 2014 Ludwig Ortmann <ludwig.ortmann@fu-berlin.de>
*
* 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 <ludwig.ortmann@fu-berlin.de>
*
* @ingroup _native_cpu
* @defgroup _native_rtc
* @file
*/
#include <time.h>
#include <stdlib.h>
#include <string.h>
#include <err.h>
#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));
}

View File

@ -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 <time.h>
#include <sys/time.h>
#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

View File

@ -26,7 +26,7 @@
// riot
#include "thread.h"
#include "rtc.h"
#include "periph/rtc.h"
// ccn
#include "ccn_lite/ccnl-riot.h"

View File

@ -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

View File

@ -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);

View File

@ -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");

View File

@ -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

View File

@ -1,76 +1,187 @@
/**
* Shell commands for real time clock
*
* Copyright (C) 2013 INRIA.
/*
* Copyright 2013 INRIA.
* Copyright 2014 Ludwig Ortmann <ludwig.ortmann@fu-berlin.de>
*
* 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 <oliver.hahm@inria.fr>
* @author Ludwig Ortmann <ludwig.ortmann@fu-berlin.de>
* @}
*/
#ifdef FEATURE_PERIPH_RTC
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#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 <command> [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 <stdio.h>
void _rtc_handler(int argc, char **argv)
{
(void) argc;
(void) argv;
puts("not implemented");
}
#endif /* FEATURE_RTC */

View File

@ -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