Squashed commit of the following:
arch/z80/src/ez80: Clean-up RTC driver; get a clean compilation. Still untested. arch/z80/src/ez80: This brings the RTC to code complete, but does not yet compile. arch/z80/src/ez80/ez80_rtc.c: Bring in badly ported RTC driver from STM32F4. Little more than naming changing at this point not even ready to attempt comilation arch/z80/src/ez80: Add RTC driver. Initial commit is just the STMF4 RTC driver with name changes.
This commit is contained in:
parent
1f3958116a
commit
f5b890d098
@ -12,7 +12,7 @@
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* the documentation and/or otherr materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
@ -99,6 +99,12 @@ void up_initialize(void)
|
||||
|
||||
up_irqinitialize();
|
||||
|
||||
#ifdef CONFIG_RTC_ALARM
|
||||
/* Enable RTC alarm interrupts */
|
||||
|
||||
ez80_rtc_irqinitialize();
|
||||
#endif
|
||||
|
||||
#if !defined(CONFIG_SUPPRESS_INTERRUPTS) && !defined(CONFIG_SUPPRESS_TIMER_INTS)
|
||||
/* Initialize the system timer interrupt */
|
||||
|
||||
|
@ -116,6 +116,10 @@ extern "C"
|
||||
|
||||
void up_irqinitialize(void);
|
||||
|
||||
#ifdef CONFIG_RTC_ALARM
|
||||
void ez80_rtc_irqinitialize(void);
|
||||
#endif
|
||||
|
||||
#ifdef USE_LOWSERIALINIT
|
||||
void up_lowserialinit(void);
|
||||
#endif
|
||||
|
@ -30,6 +30,13 @@ config EZ80_SPI
|
||||
bool "SPI"
|
||||
default n
|
||||
|
||||
config EZ80_RTC
|
||||
bool "RTC"
|
||||
default n
|
||||
select RTC
|
||||
select RTC_DATETIME
|
||||
select TIME_EXTENDED
|
||||
|
||||
config EZ80_EMAC
|
||||
bool "Ethernet MAC"
|
||||
default n
|
||||
@ -38,7 +45,23 @@ config EZ80_EMAC
|
||||
---help---
|
||||
Enables support for ez80 EMAC driver.
|
||||
|
||||
endmenu
|
||||
endmenu # ez80 Peripheral Support
|
||||
|
||||
config EZ80_RTC_32KHZ
|
||||
bool "32KHz crystal present"
|
||||
default y
|
||||
depends on EZ80_RTC
|
||||
---help---
|
||||
If there is no 32Hz crystal, the RTC will fall back to use the line
|
||||
frequency.
|
||||
|
||||
config EZ80_RTC_LINEFREQ50
|
||||
bool "50Hz line frequency"
|
||||
default n
|
||||
depends on EZ80_RTC && !EZ80_RTC_32KHZ
|
||||
---help---
|
||||
If there is no 32Hz crystal, the RTC will fall back to use the line
|
||||
frequency, either 50 or 60Hz.
|
||||
|
||||
# The ZiLOG ZDS-II Windows toolchain is the only toolchain available for
|
||||
# the ez80.
|
||||
|
@ -63,6 +63,10 @@ ifeq ($(CONFIG_EZ80_SPI),y)
|
||||
CHIP_CSRCS += ez80_spi.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_EZ80_RTC),y)
|
||||
CHIP_CSRCS += ez80_rtc.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_ARCH_CHIP_EZ80F91),y)
|
||||
ifeq ($(CONFIG_EZ80_EMAC),y)
|
||||
CHIP_CSRCS += ez80_emac.c
|
||||
|
801
arch/z80/src/ez80/ez80_rtc.c
Normal file
801
arch/z80/src/ez80/ez80_rtc.c
Normal file
@ -0,0 +1,801 @@
|
||||
/****************************************************************************
|
||||
* arch/z80/src/ez80/ez80_rtc.c
|
||||
*
|
||||
* Copyright (C) 2019 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <sched.h>
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/irq.h>
|
||||
|
||||
#include <arch/io.h>
|
||||
|
||||
#include "chip.h"
|
||||
#include "up_arch.h"
|
||||
#include "ez80_rtc.h"
|
||||
|
||||
#include <arch/board/board.h>
|
||||
|
||||
#ifdef CONFIG_EZ80_RTC
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* Configuration ************************************************************/
|
||||
|
||||
#ifndef CONFIG_RTC_DATETIME
|
||||
# error "CONFIG_RTC_DATETIME must be set to use this driver"
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_RTC_HIRES
|
||||
# error "CONFIG_RTC_HIRES must NOT be set with this driver"
|
||||
#endif
|
||||
|
||||
/* Constants ****************************************************************/
|
||||
|
||||
#define SYNCHRO_TIMEOUT (0x00020000)
|
||||
#define INITMODE_TIMEOUT (0x00010000)
|
||||
|
||||
/* Proxy definitions to make the same code work for all the EZ80 series ****/
|
||||
|
||||
# define EZ80_RCC_XXX EZ80_RCC_BDCR
|
||||
# define RCC_XXX_YYYRST RCC_BDCR_BDRST
|
||||
# define RCC_XXX_RTCEN RCC_BDCR_RTCEN
|
||||
# define RCC_XXX_RTCSEL_MASK RCC_BDCR_RTCSEL_MASK
|
||||
# define RCC_XXX_RTCSEL_LSE RCC_BDCR_RTCSEL_LSE
|
||||
# define RCC_XXX_RTCSEL_LSI RCC_BDCR_RTCSEL_LSI
|
||||
# define RCC_XXX_RTCSEL_HSE RCC_BDCR_RTCSEL_HSE
|
||||
|
||||
/* Time conversions */
|
||||
|
||||
#define MINUTES_IN_HOUR 60
|
||||
#define HOURS_IN_DAY 24
|
||||
|
||||
#define hours_add(parm_hrs) \
|
||||
time->tm_hour += parm_hrs;\
|
||||
if ((HOURS_IN_DAY-1) < (time->tm_hour))\
|
||||
{\
|
||||
time->tm_hour = (parm_hrs - HOURS_IN_DAY);\
|
||||
}
|
||||
|
||||
#define RTC_ALRMR_DIS_MASK (RTC_ALRMR_MSK4 | RTC_ALRMR_MSK3 | \
|
||||
RTC_ALRMR_MSK2 | RTC_ALRMR_MSK1)
|
||||
#define RTC_ALRMR_DIS_DATE_MASK (RTC_ALRMR_MSK4)
|
||||
#define RTC_ALRMR_ENABLE (0)
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
*****************************************************************************/
|
||||
|
||||
/* Raw time from the RTC. All are binary. */
|
||||
|
||||
struct rtc_timeregs_s
|
||||
{
|
||||
uint8_t sec; /* Seconds Range 0-59 */
|
||||
uint8_t min; /* Minutes Range 0-59 */
|
||||
uint8_t hrs; /* Hours Range 0-23 */
|
||||
uint8_t dow; /* Day of week Range 1-7 */
|
||||
uint8_t dom; /* Day of month Range 1-31 */
|
||||
uint8_t mon; /* Month Range 1-12 */
|
||||
uint8_t yr; /* Year Range 0-99 */
|
||||
uint8_t cen; /* Century Range 0-99 */
|
||||
};
|
||||
|
||||
/* Alarm time from the RTC. All are BCD encoded. */
|
||||
|
||||
struct rtc_almregs_s
|
||||
{
|
||||
uint8_t sec; /* Seconds */
|
||||
uint8_t min; /* Minutes */
|
||||
uint8_t hrs; /* Hours */
|
||||
uint8_t dow; /* Day of week */
|
||||
};
|
||||
|
||||
#ifdef CONFIG_RTC_ALARM
|
||||
struct alm_cbinfo_s
|
||||
{
|
||||
volatile alm_callback_t ac_cb; /* Client callback function */
|
||||
volatile FAR void *ac_arg; /* Argument to pass with the callback function */
|
||||
};
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/* Interrupt handlers attached to the ALARM EXTI */
|
||||
|
||||
static xcpt_t g_alarm_callback;
|
||||
static void *g_callback_arg;
|
||||
|
||||
#ifdef CONFIG_RTC_ALARM
|
||||
/* Callback to use when an EXTI is activated */
|
||||
|
||||
static struct alm_cbinfo_s g_alarmcb;
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
/* g_rtc_enabled is set true after the RTC has successfully initialized */
|
||||
|
||||
volatile bool g_rtc_enabled = false;
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/* Debug */
|
||||
|
||||
static void rtc_dumpregs(FAR const char *msg);
|
||||
static void rtc_dumptime(FAR const struct tm *tp, FAR const char *msg);
|
||||
|
||||
/* Register access */
|
||||
|
||||
static void rtc_unlock(void);
|
||||
static void rtc_lock(void);
|
||||
|
||||
static void get_raw_time(struct rtc_timeregs_s *rtcregs);
|
||||
static void set_raw_time(const struct rtc_timeregs_s *rtcregs);
|
||||
|
||||
#ifdef CONFIG_RTC_ALARM
|
||||
static void get_raw_alarm(struct rtc_timeregs_s *almregs);
|
||||
static void set_raw_alarm(const struct rtc_timeregs_s *almregs);
|
||||
static int ez80_alarm_interrupt(int irq, void *context, void *arg);
|
||||
static int ez80_rtc_getalarmdatetime(const struct rtc_almregs_s almregs
|
||||
FAR struct tm *tp);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: rtc_dumpregs
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_DEBUG_RTC_INFO
|
||||
static void rtc_dumpregs(FAR const char *msg)
|
||||
{
|
||||
int rtc_state;
|
||||
|
||||
rtcinfo("%s:\n", msg);
|
||||
rtcinfo(" SEC: %02x\n", inp(EZ80_RTC_SEC));
|
||||
rtcinfo(" MIN: %02x\n", inp(EZ80_RTC_MIN));
|
||||
rtcinfo(" HRS: %02x\n", inp(EZ80_RTC_HRS));
|
||||
rtcinfo(" DOW: %02x\n", inp(EZ80_RTC_DOW));
|
||||
rtcinfo(" DOM: %02x\n", inp(EZ80_RTC_DOM));
|
||||
rtcinfo(" MON: %02x\n", inp(EZ80_RTC_MON));
|
||||
rtcinfo(" YR: %02x\n", inp(EZ80_RTC_YR));
|
||||
rtcinfo(" CEN: %02x\n", inp(EZ80_RTC_CEN));
|
||||
rtcinfo(" ASEC: %02x\n", inp(EZ80_RTC_ASEC));
|
||||
rtcinfo(" AMIN: %02x\n", inp(EZ80_RTC_AMIN));
|
||||
rtcinfo(" AHRS: %02x\n", inp(EZ80_RTC_AHRS));
|
||||
rtcinfo(" ADOW: %02x\n", inp(EZ80_RTC_ADOW));
|
||||
rtcinfo(" ACTRL: %02x\n", inp(EZ80_RTC_ACTRL));
|
||||
rtcinfo(" CTRL: %02x\n", inp(EZ80_RTC_CTRL));
|
||||
}
|
||||
#else
|
||||
# define rtc_dumpregs(msg)
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: rtc_dumptime
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_DEBUG_RTC_INFO
|
||||
static void rtc_dumptime(FAR const struct tm *tp, FAR const char *msg)
|
||||
{
|
||||
rtcinfo("%s:\n", msg);
|
||||
rtcinfo(" tm_sec: %08x\n", tp->tm_sec);
|
||||
rtcinfo(" tm_min: %08x\n", tp->tm_min);
|
||||
rtcinfo(" tm_hour: %08x\n", tp->tm_hour);
|
||||
rtcinfo(" tm_mday: %08x\n", tp->tm_mday);
|
||||
rtcinfo(" tm_mon: %08x\n", tp->tm_mon);
|
||||
rtcinfo(" tm_year: %08x\n", tp->tm_year);
|
||||
}
|
||||
#else
|
||||
# define rtc_dumptime(tp, msg)
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: rtc_unlock
|
||||
*
|
||||
* Description:
|
||||
* Disable RTC write protection
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void rtc_unlock(void)
|
||||
{
|
||||
uint8_t regval;
|
||||
|
||||
regval = inp(EZ80_RTC_CTRL);
|
||||
regval |= EZ80_RTC_UNLOCK;
|
||||
outp(EZ80_RTC_CTRL,regval);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: rtc_lock
|
||||
*
|
||||
* Description:
|
||||
* Enable RTC write protection
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void rtc_lock(void)
|
||||
{
|
||||
uint8_t regval;
|
||||
|
||||
regval = inp(EZ80_RTC_CTRL);
|
||||
regval &= ~EZ80_RTC_UNLOCK;
|
||||
outp(EZ80_RTC_CTRL,regval);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: get_raw_time
|
||||
*
|
||||
* Description:
|
||||
* Read all of the RTC time registers
|
||||
*
|
||||
* Input Parameters:
|
||||
* rtcregs - Location to return the raw RTC time registers
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void get_raw_time(struct rtc_timeregs_s *rtcregs)
|
||||
{
|
||||
rtcregs->sec = inp(EZ80_RTC_SEC);
|
||||
rtcregs->min = inp(EZ80_RTC_MIN);
|
||||
rtcregs->hrs = inp(EZ80_RTC_HRS);
|
||||
rtcregs->dow = inp(EZ80_RTC_DOW);
|
||||
rtcregs->dom = inp(EZ80_RTC_DOM);
|
||||
rtcregs->mon = inp(EZ80_RTC_MON);
|
||||
rtcregs->yr = inp(EZ80_RTC_YR);
|
||||
rtcregs->cen = inp(EZ80_RTC_CEN);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: set_raw_time
|
||||
*
|
||||
* Description:
|
||||
* Write all of the RTC time registers
|
||||
*
|
||||
* Input Parameters:
|
||||
* almregs - New RTC register values
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void set_raw_time(const struct rtc_timeregs_s *rtcregs)
|
||||
{
|
||||
rtc_unlock();
|
||||
outp(EZ80_RTC_SEC, rtcregs->sec);
|
||||
outp(EZ80_RTC_MIN, rtcregs->min);
|
||||
outp(EZ80_RTC_HRS, rtcregs->hrs);
|
||||
outp(EZ80_RTC_DOW, rtcregs->dow);
|
||||
outp(EZ80_RTC_DOM, rtcregs->dom);
|
||||
outp(EZ80_RTC_MON, rtcregs->mon);
|
||||
outp(EZ80_RTC_YR, rtcregs->yr);
|
||||
outp(EZ80_RTC_CEN, rtcregs->cen);
|
||||
rtc_unlock();
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: get_raw_alarm
|
||||
*
|
||||
* Description:
|
||||
* Read all of the RTC alarm registers
|
||||
*
|
||||
* Input Parameters:
|
||||
* almregs - Location to return the raw RTC alarm registers
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void get_raw_alarm(struct rtc_timeregs_s *almregs)
|
||||
{
|
||||
almregs->sec = inp(EZ80_RTC_ASEC);
|
||||
almregs->min = inp(EZ80_RTC_AMIN);
|
||||
almregs->hrs = inp(EZ80_RTC_AHRS);
|
||||
almregs->dow = inp(EZ80_RTC_ADOW);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: set_raw_alarm
|
||||
*
|
||||
* Description:
|
||||
* Write all of the RTC alarm registers
|
||||
*
|
||||
* Input Parameters:
|
||||
* almregs - New RTC register values
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void set_raw_alarm(const struct rtc_timeregs_s *almregs)
|
||||
{
|
||||
rtc_unlock();
|
||||
outp(EZ80_RTC_ASEC, almregs->sec);
|
||||
outp(EZ80_RTC_AMIN, almregs->min);
|
||||
outp(EZ80_RTC_AHRS, almregs->hrs);
|
||||
outp(EZ80_RTC_ADOW, almregs->dow);
|
||||
rtc_unlock();
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ez80_alarm_interrupt
|
||||
*
|
||||
* Description:
|
||||
* RTC ALARM interrupt service routine through the EXTI line
|
||||
*
|
||||
* Input Parameters:
|
||||
* irq - The IRQ number that generated the interrupt
|
||||
* context - Architecture specific register save information.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) on success; A negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_RTC_ALARM
|
||||
static int ez80_alarm_interrupt(int irq, void *context, void *arg)
|
||||
{
|
||||
uint_t regval;
|
||||
|
||||
/* Verify that the alarm iinterrupt is pending */
|
||||
|
||||
regval = inp(EZ80_RTC_CTRL);
|
||||
if ((regval & EZ80_RTC_ALARM) != 0)
|
||||
{
|
||||
/* Disable the alarm and disable the alarm interrupt */
|
||||
|
||||
rtc_unlock();
|
||||
outp(EZ80_RTC_ACTRL, 0);
|
||||
|
||||
regval = inp(EZ80_RTC_CTRL);
|
||||
regval &= ~EZ80_RTC_INTEN;
|
||||
outp(EZ80_RTC_CTRL, regval);
|
||||
rtc_lock();
|
||||
|
||||
up_irq_disble(EZ80_RTC_IRQ);
|
||||
|
||||
/* Perform the alarm callback */
|
||||
|
||||
cb = g_alarmcb.ac_cb;
|
||||
cb_arg = (FAR void *)g_alarmcb.ac_arg;
|
||||
|
||||
g_alarmcb.ac_cb = NULL;
|
||||
g_alarmcb.ac_arg = NULL;
|
||||
|
||||
cb(cb_arg);
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ez80_rtc_getalarmdatetime
|
||||
*
|
||||
* Description:
|
||||
* Get the current date and time for a RTC alarm.
|
||||
*
|
||||
* Input Parameters:
|
||||
* reg - RTC alarm register
|
||||
* tp - The location to return the high resolution time value.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) on success; a negated errno on failure
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_RTC_ALARM
|
||||
static int ez80_rtc_getalarmdatetime(const struct rtc_almregs_s almregs
|
||||
FAR struct tm *tp)
|
||||
{
|
||||
uint32_t data, tmp;
|
||||
|
||||
DEBUGASSERT(tp != NULL);
|
||||
|
||||
/* Sample the data time register. */
|
||||
|
||||
data = inp(reg);
|
||||
|
||||
/* Convert the RTC time to fields in struct tm format. All of the EZ80
|
||||
* ranges of values correspond between struct tm and the time register.
|
||||
*/
|
||||
|
||||
tp->tm_sec = xxx(tmp);
|
||||
tp->tm_min = xxx(tmp);
|
||||
tp->tm_hour = xxx(tmp);
|
||||
tp->tm_mday = xxx(tmp);
|
||||
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_rtc_initialize
|
||||
*
|
||||
* Description:
|
||||
* Initialize the hardware RTC per the selected configuration. This
|
||||
* function is called once during the OS initialization sequence
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) on success; a negated errno on failure
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int up_rtc_initialize(void)
|
||||
{
|
||||
uint8_t regval;
|
||||
|
||||
/* Some boards do not have the external 32khz oscillator installed,
|
||||
* for those boards we must fallback to the crummy line frequency
|
||||
* clock source.
|
||||
*/
|
||||
|
||||
regval = 0;
|
||||
|
||||
#ifndef CONFIG_EZ80_RTC_32KHZ
|
||||
#ifdef EZ80_RTC_LINEFREQ50
|
||||
/* Use the internal 50/60 Hz clock as the input to the RTC block */
|
||||
|
||||
regval |= (EZ80_RTC_FREQSEL | EZ80_RTC_CLKSEL);
|
||||
#else
|
||||
regval |= EZ80_RTC_CLKSEL;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
outp(EZ80_RTC_CTRL, regval);
|
||||
|
||||
rtc_dumpregs("After Initialization");
|
||||
g_rtc_enabled = true;
|
||||
return OK;
|
||||
}
|
||||
|
||||
/************************************************************************************
|
||||
* Name: ez80_rtc_irqinitialize
|
||||
*
|
||||
* Description:
|
||||
* Initialize IRQs for RTC, not possible during up_rtc_initialize because
|
||||
* up_irqinitialize is called later.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) on success; a negated errno on failure
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
#ifdef CONFIG_RTC_ALARM
|
||||
int ez80_rtc_irqinitialize(void)
|
||||
{
|
||||
DEBUGVERIFY(irq_attach(EZ80_RTC_IRQ, ez80_alarm_interrupt, NULL));
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_rtc_getdatetime
|
||||
*
|
||||
* Description:
|
||||
* Get the current date and time from the date/time RTC. This is used to
|
||||
* replace the system timer. It is only used by the RTOS during
|
||||
* initialization to set up the system time when CONFIG_RTC and
|
||||
* CONFIG_RTC_DATETIME are selected (and CONFIG_RTC_HIRES is not).
|
||||
*
|
||||
* Input Parameters:
|
||||
* tp - The location to return the high resolution time value.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) on success; a negated errno on failure
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int up_rtc_getdatetime(FAR struct tm *tp)
|
||||
{
|
||||
struct rtc_timeregs_s timeregs;
|
||||
struct rtc_timeregs_s tmpregs;
|
||||
|
||||
/* Sample the data time registers. There is a race condition here... ,
|
||||
* for example, we sample the time just before midnight on December 31,
|
||||
* the date couldbe wrong because the day rolled over while were
|
||||
* sampling. Thus loop for checking wrap here is needed.
|
||||
*/
|
||||
|
||||
do
|
||||
{
|
||||
get_raw_time(&tmpregs);
|
||||
get_raw_time(&timeregs);
|
||||
}
|
||||
while (tmpregs.min != timeregs.min &&
|
||||
tmpregs.hrs != timeregs.hrs &&
|
||||
tmpregs.dom != timeregs.dom &&
|
||||
tmpregs.mon != timeregs.mon &&
|
||||
tmpregs.yr != timeregs.yr &&
|
||||
tmpregs.cen != timeregs.cen);
|
||||
|
||||
rtc_dumpregs("Reading Time");
|
||||
|
||||
/* Convert the RTC time to fields in struct tm format. All of the EZ80
|
||||
* ranges of values correspond between struct tm and the time register.
|
||||
*/
|
||||
|
||||
tp->tm_sec = timeregs.sec;
|
||||
tp->tm_min = timeregs.min;
|
||||
tp->tm_hour = timeregs.min;
|
||||
tp->tm_mday = timeregs.dom;
|
||||
tp->tm_mon = timeregs.dom - 1; /* Range is 0-11 */
|
||||
|
||||
/* Years since 1900 */
|
||||
|
||||
tp->tm_year = (uint16_t)timeregs.cen * 100 + (uint16_t)timeregs.yr - 1900;
|
||||
|
||||
rtc_dumptime((FAR const struct tm *)tp, "Returning");
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ez80_rtc_setdatetime
|
||||
*
|
||||
* Description:
|
||||
* Set the RTC to the provided time. RTC implementations which provide
|
||||
* up_rtc_getdatetime() (CONFIG_RTC_DATETIME is selected) should provide
|
||||
* this function.
|
||||
*
|
||||
* Input Parameters:
|
||||
* tp - the time to use
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) on success; a negated errno on failure
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int ez80_rtc_setdatetime(FAR const struct tm *tp)
|
||||
{
|
||||
struct rtc_timeregs_s timeregs;
|
||||
uint16_t year;
|
||||
uint16_t cen;
|
||||
|
||||
timeregs.sec = tp->tm_sec;
|
||||
timeregs.min = tp->tm_min;
|
||||
timeregs.min = tp->tm_hour;
|
||||
timeregs.dom = tp->tm_mday;
|
||||
timeregs.dom = tp->tm_mon + 1; /* Range is 1-12 */
|
||||
|
||||
/* Years AD */
|
||||
|
||||
year = tp->tm_year + 1900;
|
||||
cen = year * 100;
|
||||
|
||||
timeregs.cen = cen;
|
||||
timeregs.yr = year - 100 * cen;
|
||||
|
||||
set_raw_time(&timeregs);
|
||||
|
||||
rtc_dumpregs("New time setting");
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_rtc_settime
|
||||
*
|
||||
* Description:
|
||||
* Set the RTC to the provided time. All RTC implementations must be able
|
||||
* to set their time based on a standard timespec.
|
||||
*
|
||||
* Input Parameters:
|
||||
* tp - the time to use
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) on success; a negated errno on failure
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int up_rtc_settime(FAR const struct timespec *tp)
|
||||
{
|
||||
FAR struct tm newtime;
|
||||
|
||||
/* Break out the time values (not that the time is set only to units of
|
||||
* seconds)
|
||||
*/
|
||||
|
||||
(void)gmtime_r(&tp->tv_sec, &newtime);
|
||||
return ez80_rtc_setdatetime(&newtime);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ez80_rtc_setalarm
|
||||
*
|
||||
* Description:
|
||||
* Set an alarm to an absolute time using associated hardware.
|
||||
*
|
||||
* Input Parameters:
|
||||
* alminfo - Information about the alarm configuration.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) on success; a negated errno on failure
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_RTC_ALARM
|
||||
int ez80_rtc_setalarm(FAR struct alm_setalarm_s *alminfo)
|
||||
{
|
||||
struct rtc_almregs_s almregs;
|
||||
int ret = -EINVAL;
|
||||
|
||||
DEBUGASSERT(alminfo != NULL);
|
||||
|
||||
rtc_dumptime(&alminfo->as_time, "New alarm time");
|
||||
|
||||
/* Save the callback info */
|
||||
|
||||
g_alarmcb.ac_cb = alminfo->as_cb;
|
||||
g_alarmcb.ac_arg = alminfo->as_arg;
|
||||
|
||||
/* Set the alarm time */
|
||||
|
||||
almregs.sec = alminfo->as_time.sec;
|
||||
almregs.min = alminfo->as_time.min;
|
||||
almregs.hrs = alminfo->as_time.hrs;
|
||||
almregs.dow = alminfo->as_time.dow;
|
||||
|
||||
set_raw_alarm(&alarmregs);
|
||||
|
||||
/* Enable the alarm */
|
||||
|
||||
rtc_unlock();
|
||||
outp(EZ80_RTC_ACTRL, EZ80_RTX_AALL);
|
||||
|
||||
regval = inp(EZ80_RTC_CTRL);
|
||||
regval |= ~EZ80_RTC_INTEN;
|
||||
outp(EZ80_RTC_CTRL, regval);
|
||||
rtc_lock();
|
||||
|
||||
rtc_dumpregs("Set Alarm");
|
||||
|
||||
/* Enable the alarm interrupt at the interrupt controller */
|
||||
|
||||
up_irq_enable(EZ80_RTC_IRQ);
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ez80_rtc_cancelalarm
|
||||
*
|
||||
* Description:
|
||||
* Cancel an alarm.
|
||||
*
|
||||
* Input Parameters:
|
||||
* alarmid - Identifies the alarm to be cancelled
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) on success; a negated errno on failure
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_RTC_ALARM
|
||||
int ez80_rtc_cancelalarm(void)
|
||||
{
|
||||
/* Cancel the global callback function */
|
||||
|
||||
g_alarmcb[alarmid].ac_cb = NULL;
|
||||
g_alarmcb[alarmid].ac_arg = NULL;
|
||||
|
||||
/* Disable RTC alarm and and the alarm interrupt */
|
||||
|
||||
rtc_unlock();
|
||||
outp(EZ80_RTC_ACTRL, 0);
|
||||
|
||||
regval = inp(EZ80_RTC_CTRL);
|
||||
regval &= ~EZ80_RTC_INTEN;
|
||||
outp(EZ80_RTC_CTRL, regval);
|
||||
rtc_lock();
|
||||
|
||||
up_irq_disable(EZ80_RTC_IRQ);
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ez80_rtc_rdalarm
|
||||
*
|
||||
* Description:
|
||||
* Return the current alarm setting.
|
||||
*
|
||||
* Input Parameters:
|
||||
* almtime - Location to retun the current alarm ime.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) on success; a negated errno on failure
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_RTC_ALARM
|
||||
int ez80_rtc_rdalarm(FAR struct rtc_time *almtime)
|
||||
struct rtc_almregs_s almregs;
|
||||
int ret = -EINVAL;
|
||||
|
||||
DEBUGASSERT(almtime != NULL);
|
||||
|
||||
/* Read the alarm time from the RTC */
|
||||
|
||||
get_raw_alarm(&almregs);
|
||||
|
||||
/* A return that as struct tm */
|
||||
|
||||
return ez80_rtc_getalarmdatetime(&almregs, almtime);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* CONFIG_EZ80_RTC */
|
208
arch/z80/src/ez80/ez80_rtc.h
Normal file
208
arch/z80/src/ez80/ez80_rtc.h
Normal file
@ -0,0 +1,208 @@
|
||||
/****************************************************************************
|
||||
* arch/z80/src/ez80/ez80_rtc.h
|
||||
*
|
||||
* Copyright (C) 2019 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __ARCH_EZ80_SRC_EZ80_EZ80_RTC_H
|
||||
#define __ARCH_EZ80_SRC_EZ80_EZ80_RTC_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#include "chip.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* RTC registers ************************************************************/
|
||||
|
||||
/* Provided in z80F91.h */
|
||||
|
||||
/* RTC register bit definitions *********************************************/
|
||||
|
||||
/* ACTRL register */
|
||||
|
||||
#define EZ80_RTC_ASECEN (1 << 0) /* Bit 0: Enable seconds alarm */
|
||||
#define EZ80_RTC_AMINEN (1 << 1) /* Bit 1: Enable minutes alarm */
|
||||
#define EZ80_RTC_AHRSEN (1 << 2) /* Bit 4: Enable hours alarm */
|
||||
#define EZ80_RTC_ADOWEN (1 << 3) /* Bit 3: Enable day-of-week alarm */
|
||||
#define EZ80_RTX_AALL 0x0f /* All times */
|
||||
|
||||
/* CTRL register */
|
||||
|
||||
#define EZ80_RTC_UNLOCK (1 << 0) /* Bit 0: RTC registers unlocked */
|
||||
#define EZ80_RTC_SLPWAKE (1 << 1) /* Bit 1: Alarm sleep recovery */
|
||||
#define EZ80_RTC_FREQSEL (1 << 3) /* Bit 3: Power line is 50Hz */
|
||||
#define EZ80_RTC_CLKSEL (1 << 4) /* Bit 4: Clock source is power line */
|
||||
#define EZ80_RTC_BCDEN (1 << 5) /* Bit 5: BCD encoded time */
|
||||
#define EZ80_RTC_INTEN (1 << 6) /* Bit 6: Alarm interrupt enabled */
|
||||
#define EZ80_RTC_ALARM (1 << 7) /* Bit 7: Alarm interrupt active */
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
typedef CODE void (*alm_callback_t)(FAR void *arg);
|
||||
|
||||
/* Structure used to pass parameters to set an alarm */
|
||||
|
||||
struct alm_setalarm_s
|
||||
{
|
||||
struct tm as_time; /* Alarm expiration time */
|
||||
alm_callback_t as_cb; /* Callback (if non-NULL) */
|
||||
FAR void *as_arg; /* Argument for callback */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
#define EXTERN extern "C"
|
||||
extern "C"
|
||||
{
|
||||
#else
|
||||
#define EXTERN extern
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ez80_rtc_setdatetime
|
||||
*
|
||||
* Description:
|
||||
* Set the RTC to the provided time. RTC implementations which provide
|
||||
* up_rtc_getdatetime() (CONFIG_RTC_DATETIME is selected) should provide
|
||||
* this function.
|
||||
*
|
||||
* Input Parameters:
|
||||
* tp - the time to use
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) on success; a negated errno on failure
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
struct tm;
|
||||
int ez80_rtc_setdatetime(FAR const struct tm *tp);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ez80_rtc_lowerhalf
|
||||
*
|
||||
* Description:
|
||||
* Instantiate the RTC lower half driver for the EZ80. General usage:
|
||||
*
|
||||
* #include <nuttx/timers/rtc.h>
|
||||
* #include "ez80_rtc.h"
|
||||
*
|
||||
* struct rtc_lowerhalf_s *lower;
|
||||
* lower = ez80_rtc_lowerhalf();
|
||||
* rtc_initialize(0, lower);
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* On success, a non-NULL RTC lower interface is returned. NULL is
|
||||
* returned on any failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_RTC_DRIVER
|
||||
struct rtc_lowerhalf_s;
|
||||
FAR struct rtc_lowerhalf_s *ez80_rtc_lowerhalf(void);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_RTC_ALARM
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ez80_rtc_setalarm
|
||||
*
|
||||
* Description:
|
||||
* Set an alarm to an absolute time using associated hardware.
|
||||
*
|
||||
* Input Parameters:
|
||||
* alminfo - Information about the alarm configuration.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) on success; a negated errno on failure
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int ez80_rtc_setalarm(FAR struct alm_setalarm_s *alminfo);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ez80_rtc_rdalarm
|
||||
*
|
||||
* Description:
|
||||
* Return the current alarm setting.
|
||||
*
|
||||
* Input Parameters:
|
||||
* almtime - Location to retun the current alarm ime.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) on success; a negated errno on failure
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int ez80_rtc_rdalarm(FAR struct rtc_time *almtime);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ez80_rtc_cancelalarm
|
||||
*
|
||||
* Description:
|
||||
* Cancel an alarm.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) on success; a negated errno on failure
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int ez80_rtc_cancelalarm(void);
|
||||
|
||||
#endif /* CONFIG_RTC_ALARM */
|
||||
#endif /* __ARCH_EZ80_SRC_EZ80_RTC_H */
|
Loading…
Reference in New Issue
Block a user