2014-08-27 18:47:31 +02:00
|
|
|
/*
|
|
|
|
* Copyright 2010, Freie Universitaet Berlin (FUB).
|
|
|
|
* Copyright 2013, 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.
|
|
|
|
*/
|
2010-12-13 01:29:46 +01:00
|
|
|
|
2013-03-13 21:56:56 +01:00
|
|
|
/**
|
2017-06-22 15:43:17 +02:00
|
|
|
* @ingroup cc430
|
|
|
|
* @ingroup drivers_periph_rtc
|
|
|
|
* @{
|
|
|
|
*
|
2014-11-25 15:03:54 +01:00
|
|
|
* @file
|
2014-07-31 20:46:28 +02:00
|
|
|
* @brief CC430 real time clock implementation
|
|
|
|
* @author Oliver Hahm <oliver.hahm@inria.fr>
|
2017-06-22 15:43:17 +02:00
|
|
|
*
|
|
|
|
* @}
|
2013-03-13 21:56:56 +01:00
|
|
|
*/
|
|
|
|
|
2010-12-13 01:29:46 +01:00
|
|
|
#include <string.h>
|
2013-03-30 21:44:16 +01:00
|
|
|
#include <legacymsp430.h>
|
2013-12-16 17:54:58 +01:00
|
|
|
#include "irq.h"
|
|
|
|
#include "cpu.h"
|
|
|
|
#include "cc430-rtc.h"
|
2010-12-13 01:29:46 +01:00
|
|
|
|
2014-11-20 17:55:28 +01:00
|
|
|
/* Alarm callback */
|
|
|
|
static rtc_alarm_cb_t _cb;
|
|
|
|
|
|
|
|
/* Argument to alarm callback */
|
|
|
|
static void *_cb_arg;
|
|
|
|
|
2010-12-13 01:29:46 +01:00
|
|
|
static struct tm time_to_set;
|
2010-12-16 18:21:24 +01:00
|
|
|
static int set_time = 0;
|
2014-08-06 09:44:31 +02:00
|
|
|
kernel_pid_t rtc_second_pid = KERNEL_PID_UNDEF;
|
2010-12-13 01:29:46 +01:00
|
|
|
|
2013-06-21 03:52:57 +02:00
|
|
|
void rtc_init(void)
|
|
|
|
{
|
2010-12-13 01:29:46 +01:00
|
|
|
/* Set to calendar mode */
|
|
|
|
RTCCTL1 |= RTCMODE_H;
|
|
|
|
}
|
|
|
|
|
2014-11-20 17:55:28 +01:00
|
|
|
void rtc_poweron(void)
|
2013-06-21 03:52:57 +02:00
|
|
|
{
|
2010-12-13 01:29:46 +01:00
|
|
|
/* Set RTC operational */
|
|
|
|
RTCCTL1 &= ~RTCHOLD_H;
|
|
|
|
}
|
2015-03-21 16:24:47 +01:00
|
|
|
|
2014-11-20 17:55:28 +01:00
|
|
|
void rtc_poweroff(void)
|
2013-06-21 03:52:57 +02:00
|
|
|
{
|
2010-12-13 01:29:46 +01:00
|
|
|
/* Stop RTC */
|
|
|
|
RTCCTL1 |= RTCHOLD_H;
|
|
|
|
}
|
2014-11-20 17:55:28 +01:00
|
|
|
|
|
|
|
int rtc_set_time(struct tm *localt)
|
2013-06-21 03:52:57 +02:00
|
|
|
{
|
2013-06-24 22:37:35 +02:00
|
|
|
if (localt == NULL) {
|
2014-11-20 17:55:28 +01:00
|
|
|
return -1;
|
2010-12-13 01:29:46 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* copy time to be set */
|
|
|
|
memcpy(&time_to_set, localt, sizeof(struct tm));
|
2010-12-16 18:21:24 +01:00
|
|
|
set_time = 1;
|
2014-11-20 17:55:28 +01:00
|
|
|
return 0;
|
2010-12-13 01:29:46 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*---------------------------------------------------------------------------
|
|
|
|
time_t rtc_time(void) {
|
|
|
|
time_t sec;
|
|
|
|
struct tm t;
|
|
|
|
rtc_get_localtime(&t);
|
|
|
|
sec = mktime(&t);
|
2014-07-31 20:46:28 +02:00
|
|
|
return sec;
|
2010-12-13 01:29:46 +01:00
|
|
|
}
|
|
|
|
*/
|
2014-11-20 17:55:28 +01:00
|
|
|
|
|
|
|
int rtc_get_time(struct tm *localt)
|
2013-06-21 03:52:57 +02:00
|
|
|
{
|
2010-12-13 01:29:46 +01:00
|
|
|
uint8_t success = 0;
|
|
|
|
uint8_t i;
|
|
|
|
uint16_t tmpyear;
|
|
|
|
|
2013-06-24 22:37:35 +02:00
|
|
|
if (localt == NULL) {
|
2014-11-20 17:55:28 +01:00
|
|
|
return -1;
|
2010-12-13 01:29:46 +01:00
|
|
|
}
|
|
|
|
|
2013-06-24 22:37:35 +02:00
|
|
|
while (!success) {
|
|
|
|
for (i = 0; i < 8; i++) {
|
2010-12-13 01:29:46 +01:00
|
|
|
/* try again when RTC is in transition */
|
2013-06-24 22:37:35 +02:00
|
|
|
if (!(RTCCTL1 & RTCRDY_H)) {
|
2010-12-13 01:29:46 +01:00
|
|
|
break;
|
|
|
|
}
|
2013-06-21 03:52:57 +02:00
|
|
|
|
|
|
|
switch(i) {
|
2010-12-13 01:29:46 +01:00
|
|
|
case 0:
|
|
|
|
localt->tm_sec = RTCSEC;
|
|
|
|
break;
|
2013-06-21 03:52:57 +02:00
|
|
|
|
2010-12-13 01:29:46 +01:00
|
|
|
case 1:
|
|
|
|
localt->tm_min = RTCMIN;
|
|
|
|
break;
|
2013-06-21 03:52:57 +02:00
|
|
|
|
2010-12-13 01:29:46 +01:00
|
|
|
case 2:
|
|
|
|
localt->tm_hour = RTCHOUR;
|
|
|
|
break;
|
2013-06-21 03:52:57 +02:00
|
|
|
|
2010-12-13 01:29:46 +01:00
|
|
|
case 3:
|
|
|
|
localt->tm_mday = RTCDAY;
|
|
|
|
break;
|
2013-06-21 03:52:57 +02:00
|
|
|
|
2010-12-13 01:29:46 +01:00
|
|
|
case 4:
|
|
|
|
localt->tm_wday = RTCDOW;
|
|
|
|
break;
|
2013-06-21 03:52:57 +02:00
|
|
|
|
2010-12-13 01:29:46 +01:00
|
|
|
case 5:
|
|
|
|
localt->tm_mon = RTCMON - 1;
|
|
|
|
break;
|
2013-06-21 03:52:57 +02:00
|
|
|
|
2010-12-13 01:29:46 +01:00
|
|
|
case 6:
|
|
|
|
tmpyear = RTCYEARL;
|
|
|
|
tmpyear |= (RTCYEARH << 0x08);
|
|
|
|
localt->tm_year = tmpyear - 1900;
|
|
|
|
break;
|
2013-06-21 03:52:57 +02:00
|
|
|
|
2010-12-13 01:29:46 +01:00
|
|
|
default:
|
|
|
|
success = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-11-20 17:55:28 +01:00
|
|
|
|
|
|
|
return 0;
|
2010-12-13 01:29:46 +01:00
|
|
|
}
|
|
|
|
|
2014-11-20 17:55:28 +01:00
|
|
|
int rtc_set_alarm(struct tm *localt, rtc_alarm_cb_t cb, void *arg)
|
2013-06-21 03:52:57 +02:00
|
|
|
{
|
build: fix unused parameter errors
cpu, sam0_common: fix unused parameter in periph/spi
cpu, kinetis_common: fix unused parameter in periph/spi
cpu, cc2538: fix unused param in periph/i2c
cpu, cc2538: fix unused param in periph/spi
cpu, sam3: fix unused param in periph/spi
cpu, stm32_common: fix unused param in periph/pm
cpu, stm32f3: fix unused params in periph/i2c
cpu, nrf5x_common: fix unused param in periph/gpio
cpu, nrf5x_common: fix unused param in periph/spi
cpu, lpc2387: fix unused params in periph/spi
cpu, cc2538: fix unused params in radio/netdev
cpu, cc2650: fix unused params in periph/uart
cpu, lm4f120: fix unused param in periph/spi
cpu, lm4f120: fix unused params in periph/timer
cpu, lm4f120: fix unused params in periph/uart
cpu, stm32_common: fix unused params in periph/dac
cpu, stm32l0: fix unused params in periph/i2c
cpu, msp430fxyz: fix unused params in periph/uart
cpu, mips: fix unused params
cpu, cc430: fix unused-params in periph/timer
cpu, msp430fxyz: fix unused params in periph/spi
drivers, cc2420: fix unused param
cpu, mips32r2_common: fix unused params in periph/timer
cpu, cc2538: fix unused-param in periph/i2c
cpu, mips32r2_common: fix unused-param in periph/timer
cpu, msp430fxyz: fix unused params in periph/timer
cpu, atmega_common: fix unused params in periph/spi
driver, nrfmin: fix unused params
cpu, cc2538_rf: fix unused params
driver, netdev_ieee802514: fix unused param
cpu, mip_pic32m: fix unused params
cpu, lpc2387: fix unused params in periph/pwm
tests/driver_sdcard_spi: fix unused params
cpu, sam3: fix unused param in periph/pwm
tests/driver_dynamixel: fix unused params, and style issues
cpu, cc430: fix unused param in periph/rtc
cpu, atmega_common: fix unused params in periph/i2c
2017-10-31 12:09:11 +01:00
|
|
|
(void)arg;
|
|
|
|
|
2014-11-20 17:55:28 +01:00
|
|
|
if (localt != NULL) {
|
2010-12-13 01:29:46 +01:00
|
|
|
RTCAMIN = localt->tm_min;
|
|
|
|
RTCAMIN |= BIT7;
|
|
|
|
RTCAHOUR = localt->tm_hour;
|
|
|
|
RTCAHOUR |= BIT7;
|
|
|
|
RTCADOW = localt->tm_wday;
|
|
|
|
RTCADOW |= BIT7;
|
|
|
|
RTCADAY = localt->tm_mday;
|
|
|
|
RTCADAY |= BIT7;
|
2014-11-20 17:55:28 +01:00
|
|
|
|
|
|
|
RTCCTL0 |= RTCAIE;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (cb == NULL) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return -2;
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
2010-12-13 01:29:46 +01:00
|
|
|
}
|
2013-06-21 03:52:57 +02:00
|
|
|
|
2014-11-20 17:55:28 +01:00
|
|
|
return -1;
|
2010-12-13 01:29:46 +01:00
|
|
|
}
|
|
|
|
|
2014-11-20 17:55:28 +01:00
|
|
|
void rtc_clear_alarm(void)
|
2013-06-21 03:52:57 +02:00
|
|
|
{
|
2010-12-13 01:29:46 +01:00
|
|
|
/* reset all AE bits */
|
|
|
|
RTCAHOUR &= ~BIT7;
|
|
|
|
RTCAMIN &= ~BIT7;
|
|
|
|
RTCADAY &= ~BIT7;
|
|
|
|
RTCADOW &= ~BIT7;
|
|
|
|
|
|
|
|
/* reset alarm interrupt enable */
|
|
|
|
RTCCTL0 &= ~RTCAIE;
|
|
|
|
}
|
2014-11-20 17:55:28 +01:00
|
|
|
|
2013-06-21 03:52:57 +02:00
|
|
|
interrupt(RTC_VECTOR) __attribute__((naked)) rtc_isr(void)
|
|
|
|
{
|
2010-12-13 01:29:46 +01:00
|
|
|
__enter_isr();
|
2013-06-21 03:52:57 +02:00
|
|
|
|
2010-12-13 01:29:46 +01:00
|
|
|
/* RTC is save to write for up to one second now */
|
2013-06-24 22:37:35 +02:00
|
|
|
if (RTCIV == RTC_RTCRDYIFG) {
|
2010-12-13 01:29:46 +01:00
|
|
|
/* disable interrupt */
|
2010-12-16 18:21:24 +01:00
|
|
|
//RTCCTL0 &= ~RTCRDYIE;
|
|
|
|
|
2013-06-24 22:37:35 +02:00
|
|
|
if (set_time) {
|
2010-12-16 18:21:24 +01:00
|
|
|
set_time = 0;
|
2013-06-21 03:52:57 +02:00
|
|
|
/* set previous set time and reset it */
|
2010-12-16 18:21:24 +01:00
|
|
|
RTCSEC = time_to_set.tm_sec;
|
|
|
|
RTCMIN = time_to_set.tm_min;
|
|
|
|
RTCHOUR = time_to_set.tm_hour;
|
|
|
|
RTCDAY = time_to_set.tm_mday;
|
|
|
|
RTCDOW = time_to_set.tm_wday;
|
|
|
|
RTCMON = time_to_set.tm_mon + 1;
|
|
|
|
RTCYEARL = (time_to_set.tm_year + 1900) & 0xFF;
|
|
|
|
RTCYEARH = (time_to_set.tm_year + 1900) >> 0x08;
|
|
|
|
}
|
2013-06-21 03:52:57 +02:00
|
|
|
|
2014-08-06 09:44:31 +02:00
|
|
|
if (rtc_second_pid != KERNEL_PID_UNDEF) {
|
2014-04-11 17:20:23 +02:00
|
|
|
static msg_t m;
|
2014-11-20 17:55:28 +01:00
|
|
|
m.type = RTCSEC;
|
2010-12-16 18:21:24 +01:00
|
|
|
msg_send_int(&m, rtc_second_pid);
|
|
|
|
}
|
2010-12-13 01:29:46 +01:00
|
|
|
}
|
|
|
|
/* RTC alarm */
|
2013-06-24 22:37:35 +02:00
|
|
|
else if (RTCIV == RTC_RTCAIFG) {
|
2014-11-20 17:55:28 +01:00
|
|
|
if (_cb) {
|
|
|
|
_cb(_cb_arg);
|
|
|
|
}
|
2010-12-13 01:29:46 +01:00
|
|
|
}
|
2013-06-21 03:52:57 +02:00
|
|
|
|
2010-12-13 01:29:46 +01:00
|
|
|
__exit_isr();
|
|
|
|
}
|