Merge pull request #8737 from kapi90/cm3ds_lp_requirements

Add low power implementations for CM3DS
pull/8863/head
Martin Kojtal 2018-11-24 19:49:57 +01:00 committed by GitHub
commit d7f2e3056c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 2208 additions and 206 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018 ARM Limited
* Copyright (c) 2018 Arm Limited
*
* Licensed under the Apache License Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -27,8 +27,54 @@
*/
/* CMSDK Timers */
#define ARM_CMSDK_TIMER0
#define ARM_CMSDK_TIMER1
#define ARM_CMSDK_DUALTIMER
/* Timer Peripherals are driven by APB System Core Clocks,
* defined in system_CMSDK_CM3DS.c
*/
#define TIMERS_INPUT_CLOCK_FREQ_HZ 25000000U
/* mbed usec high-resolution ticker configuration */
#define USEC_TIMER_DEV CMSDK_TIMER1_DEV
#define usec_interval_irq_handler TIMER1_IRQHandler
#define USEC_INTERVAL_IRQ TIMER1_IRQn
/* The us ticker uses CMSDK Timer1, that does not have HW prescaler.
* The reported shift define is necessary for the software emulated
* prescaler behavior, so the ticker works as if it was ticking on a
* virtually slower frequency. The value 5 sets up the ticker to work
* properly in the specified frequency interval.
*/
#define USEC_TIMER_BIT_WIDTH 32U
#define USEC_REPORTED_SHIFT 5U
#define USEC_REPORTED_FREQ_HZ (TIMERS_INPUT_CLOCK_FREQ_HZ >> \
USEC_REPORTED_SHIFT)
#define USEC_REPORTED_BITS (USEC_TIMER_BIT_WIDTH - USEC_REPORTED_SHIFT)
/* mbed low power ticker configuration */
#define LP_TIMER_DEV CMSDK_DUALTIMER_DEV
#define lp_interval_irq_handler DUALTIMER_IRQHandler
#define LP_INTERVAL_IRQ DUALTIMER_IRQn
/* The lp ticker a CMSDK Dual Timer that is capable of prescaling
* its input clock frequency by 256 at most. Having 25MHz as input
* frequency requires an additional slowing factor in order for the ticker
* to operate in the specified frequency interval, thus the effective
* prescaler value is going to be the sum of the HW and the virtual
* prescaler values.
*/
#define LP_TIMER_BIT_WIDTH 32U
#define LP_TIMER_HW_PRESCALER 8U
#define LP_REPORTED_SHIFT 1U
#define LP_REPORTED_FREQ_HZ (TIMERS_INPUT_CLOCK_FREQ_HZ >> \
(LP_TIMER_HW_PRESCALER+LP_REPORTED_SHIFT))
#define LP_REPORTED_BITS (LP_TIMER_BIT_WIDTH - LP_REPORTED_SHIFT)
/* RTC PL031 */
#define RTC_PL031
/* ARM GPIO */
#define ARM_GPIO0
@ -51,7 +97,7 @@
#define ARM_SPI4
/* ARM UART */
#define DEFAULT_UART_BAUDRATE 9600
#define DEFAULT_UART_BAUDRATE 9600U
#define ARM_UART0
#define ARM_UART1
#define ARM_UART2

View File

@ -0,0 +1,590 @@
/*
* Copyright (c) 2016-2018 Arm Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* \file dualtimer_cmsdk_drv.c
* \brief Generic driver for CMSDK Dualtimers.
*/
#include "dualtimer_cmsdk_drv.h"
/** Dualtimer state definition */
#define DUALTIMER_CMSDK_INITIALIZED (1u)
/** Dual timer control register bit indexes */
#define CTRL_REG_ONE_SHOT_INDEX (0u)
#define CTRL_REG_SIZE_INDEX (1u)
#define CTRL_REG_PRESCALE_INDEX (3u)
#define CTRL_REG_IRQ_EN_INDEX (5u)
#define CTRL_REG_MODE_INDEX (6u)
#define CTRL_REG_TIMER_EN_INDEX (7u)
/** Dual timer interrupt registers bit indexes */
#define XRIS_REG_RAW_IRQ_INDEX (0u)
#define XMIS_REG_MASKED_IRQ_INDEX (0u)
#define XINTCLR_REG_CLEAR_IRQ_INDEX (0u)
/** Misc definition */
#define TWO_BITS_WIDTH (2u)
/** Bit handling macros */
#define ATOMIC_SET_BIT(WORD, BIT_INDEX) (WORD = (1u << BIT_INDEX))
#define ATOMIC_CLR_BIT(WORD, BIT_INDEX) (WORD = ~(1u << BIT_INDEX))
#define SET_BIT(WORD, BIT_INDEX) (WORD |= (1u << BIT_INDEX))
#define CLR_BIT(WORD, BIT_INDEX) (WORD &= ~(1u << BIT_INDEX))
#define GET_BIT(WORD, BIT_INDEX) (bool)((WORD & (1u << BIT_INDEX)))
/** Generate a flexible width left shifted bit-mask */
#define BIT_MASK(BIT_INDEX, WIDTH)\
(((1u << (WIDTH)) - 1u) << (BIT_INDEX - WIDTH + 1u))
/** Set N number of bits defined by width at index position in a register */
#define SET_NBITS(WORD, BIT_INDEX, WIDTH, DATA)\
(WORD |= (DATA << (BIT_INDEX - WIDTH + 1u))\
& BIT_MASK(BIT_INDEX, WIDTH))
/** Get N number of bits defined by width at index position in a register */
#define GET_NBITS(WORD, BIT_INDEX, WIDTH)\
((WORD & BIT_MASK(BIT_INDEX, WIDTH))\
>> (BIT_INDEX - WIDTH + 1u))
/** Map the registers for dualtimer device */
#define DUALTIMER_REG_MAP(DEVICE)\
((struct dualtimer_cmsdk_reg_map_t*)((DEVICE)->cfg->base))
/** DualTimer register map structure */
struct dualtimer_cmsdk_reg_map_t {
volatile uint32_t timer1load; /** Offset: 0x000 (R/W) Timer 1 Load */
volatile uint32_t timer1value; /** Offset: 0x004 (R/ ) Timer 1 Counter
* Current Value */
volatile uint32_t timer1ctrl; /** Offset: 0x008 (R/W) Timer 1 Control */
volatile uint32_t timer1intclr; /** Offset: 0x00C ( /W) Timer 1 Interrupt
* Clear */
volatile uint32_t timer1ris; /** Offset: 0x010 (R/ ) Timer 1 Raw
* Interrupt Status */
volatile uint32_t timer1mis; /** Offset: 0x014 (R/ ) Timer 1 Masked
* Interrupt Status */
volatile uint32_t timer1bgload; /** Offset: 0x018 (R/W) Background Load
* Register */
volatile uint32_t reserved0;
volatile uint32_t timer2load; /** Offset: 0x020 (R/W) Timer 2 Load */
volatile uint32_t timer2value; /** Offset: 0x024 (R/ ) Timer 2 Counter
* Current Value */
volatile uint32_t timer2ctrl; /** Offset: 0x028 (R/W) Timer 2 Control */
volatile uint32_t timer2intclr; /** Offset: 0x02C ( /W) Timer 2 Interrupt
* Clear */
volatile uint32_t timer2ris; /** Offset: 0x030 (R/ ) Timer 2 Raw
* Interrupt Status */
volatile uint32_t timer2mis; /** Offset: 0x034 (R/ ) Timer 2 Masked
* Interrupt Status */
volatile uint32_t timer2bgload; /** Offset: 0x038 (R/W) Background Load
* Register */
volatile uint32_t reserved1[945];
volatile uint32_t itcr; /** Offset: 0xF00 (R/W) Integration Test
* Control Register */
volatile uint32_t itop; /** Offset: 0xF04 ( /W) Integration Test
* Output Set
* Register */
};
static void dualtimer_cmsdk_defaults(const struct dualtimer_cmsdk_dev_t* dev)
{
dualtimer_cmsdk_disable_both_timers(dev);
dualtimer_cmsdk_clear_interrupt_timer1(dev);
dualtimer_cmsdk_clear_interrupt_timer2(dev);
dualtimer_cmsdk_set_oneshot_count_both_timers(dev,
DUALTIMER_CMSDK_WRAPPING);
dualtimer_cmsdk_set_size_both_timers(dev, DUALTIMER_CMSDK_SIZE_16BIT);
dualtimer_cmsdk_set_prescale_both_timers(dev,
DUALTIMER_CMSDK_CLOCK_DIV1);
dualtimer_cmsdk_enable_interrupt_both_timers(dev);
dualtimer_cmsdk_set_mode_both_timers(dev, DUALTIMER_CMSDK_FREE_RUNNING);
dualtimer_cmsdk_set_reload_both_timers(dev,
DUALTIMER_CMSDK_DEF_16BIT_RELOAD);
}
/** Init */
void dualtimer_cmsdk_init(const struct dualtimer_cmsdk_dev_t* dev)
{
if (DUALTIMER_CMSDK_INITIALIZED != dev->data->is_initialized) {
dualtimer_cmsdk_defaults(dev);
dev->data->is_initialized = 1;
}
}
bool dualtimer_cmsdk_is_initialized(const struct dualtimer_cmsdk_dev_t* dev)
{
return(bool)dev->data->is_initialized;
}
void dualtimer_cmsdk_free(const struct dualtimer_cmsdk_dev_t* dev)
{
dualtimer_cmsdk_disable_both_timers(dev);
dev->data->is_initialized = 0;
}
/** Enable - Disable */
void dualtimer_cmsdk_enable_timer1(const struct dualtimer_cmsdk_dev_t* dev)
{
SET_BIT(DUALTIMER_REG_MAP(dev)->timer1ctrl, CTRL_REG_TIMER_EN_INDEX);
}
void dualtimer_cmsdk_enable_timer2(const struct dualtimer_cmsdk_dev_t* dev)
{
SET_BIT(DUALTIMER_REG_MAP(dev)->timer2ctrl, CTRL_REG_TIMER_EN_INDEX);
}
void dualtimer_cmsdk_enable_both_timers(const struct dualtimer_cmsdk_dev_t* dev)
{
dualtimer_cmsdk_enable_timer1(dev);
dualtimer_cmsdk_enable_timer2(dev);
}
void dualtimer_cmsdk_disable_timer1(const struct dualtimer_cmsdk_dev_t* dev)
{
CLR_BIT(DUALTIMER_REG_MAP(dev)->timer1ctrl, CTRL_REG_TIMER_EN_INDEX);
}
void dualtimer_cmsdk_disable_timer2(const struct dualtimer_cmsdk_dev_t* dev)
{
CLR_BIT(DUALTIMER_REG_MAP(dev)->timer2ctrl, CTRL_REG_TIMER_EN_INDEX);
}
void dualtimer_cmsdk_disable_both_timers(
const struct dualtimer_cmsdk_dev_t* dev)
{
dualtimer_cmsdk_disable_timer1(dev);
dualtimer_cmsdk_disable_timer2(dev);
}
/** Interrupts */
void dualtimer_cmsdk_enable_interrupt_timer1(
const struct dualtimer_cmsdk_dev_t* dev)
{
SET_BIT(DUALTIMER_REG_MAP(dev)->timer1ctrl, CTRL_REG_IRQ_EN_INDEX);
}
void dualtimer_cmsdk_enable_interrupt_timer2(
const struct dualtimer_cmsdk_dev_t* dev)
{
SET_BIT(DUALTIMER_REG_MAP(dev)->timer2ctrl, CTRL_REG_IRQ_EN_INDEX);
}
void dualtimer_cmsdk_enable_interrupt_both_timers(
const struct dualtimer_cmsdk_dev_t* dev)
{
dualtimer_cmsdk_enable_interrupt_timer1(dev);
dualtimer_cmsdk_enable_interrupt_timer2(dev);
}
void dualtimer_cmsdk_disable_interrupt_timer1(
const struct dualtimer_cmsdk_dev_t* dev)
{
CLR_BIT(DUALTIMER_REG_MAP(dev)->timer1ctrl, CTRL_REG_IRQ_EN_INDEX);
}
void dualtimer_cmsdk_disable_interrupt_timer2(
const struct dualtimer_cmsdk_dev_t* dev)
{
CLR_BIT(DUALTIMER_REG_MAP(dev)->timer2ctrl, CTRL_REG_IRQ_EN_INDEX);
}
void dualtimer_cmsdk_disable_interrupt_both_timers(
const struct dualtimer_cmsdk_dev_t* dev)
{
dualtimer_cmsdk_disable_interrupt_timer1(dev);
dualtimer_cmsdk_disable_interrupt_timer2(dev);
}
void dualtimer_cmsdk_clear_interrupt_timer1(
const struct dualtimer_cmsdk_dev_t* dev)
{
ATOMIC_SET_BIT(DUALTIMER_REG_MAP(dev)->timer1intclr,
XINTCLR_REG_CLEAR_IRQ_INDEX);
}
void dualtimer_cmsdk_clear_interrupt_timer2(
const struct dualtimer_cmsdk_dev_t* dev)
{
ATOMIC_SET_BIT(DUALTIMER_REG_MAP(dev)->timer2intclr,
XINTCLR_REG_CLEAR_IRQ_INDEX);
}
/** One Shot */
void dualtimer_cmsdk_set_oneshot_count_timer1(
const struct dualtimer_cmsdk_dev_t* dev,
enum dualtimer_cmsdk_oneshot_t mode)
{
if (DUALTIMER_CMSDK_ONE_SHOT == mode) {
SET_BIT(DUALTIMER_REG_MAP(dev)->timer1ctrl, CTRL_REG_ONE_SHOT_INDEX);
} else {
CLR_BIT(DUALTIMER_REG_MAP(dev)->timer1ctrl, CTRL_REG_ONE_SHOT_INDEX);
}
}
void dualtimer_cmsdk_set_oneshot_count_timer2(
const struct dualtimer_cmsdk_dev_t* dev,
enum dualtimer_cmsdk_oneshot_t mode)
{
if (DUALTIMER_CMSDK_ONE_SHOT == mode) {
SET_BIT(DUALTIMER_REG_MAP(dev)->timer2ctrl, CTRL_REG_ONE_SHOT_INDEX);
} else {
CLR_BIT(DUALTIMER_REG_MAP(dev)->timer2ctrl, CTRL_REG_ONE_SHOT_INDEX);
}
}
void dualtimer_cmsdk_set_oneshot_count_both_timers(
const struct dualtimer_cmsdk_dev_t* dev,
enum dualtimer_cmsdk_oneshot_t mode)
{
dualtimer_cmsdk_set_oneshot_count_timer1(dev, mode);
dualtimer_cmsdk_set_oneshot_count_timer2(dev, mode);
}
/** Timer Size */
void dualtimer_cmsdk_set_size_timer1(const struct dualtimer_cmsdk_dev_t* dev,
enum dualtimer_cmsdk_size_t bit_size)
{
if (DUALTIMER_CMSDK_SIZE_32BIT == bit_size) {
SET_BIT(DUALTIMER_REG_MAP(dev)->timer1ctrl, CTRL_REG_SIZE_INDEX);
} else {
CLR_BIT(DUALTIMER_REG_MAP(dev)->timer1ctrl, CTRL_REG_SIZE_INDEX);
}
}
void dualtimer_cmsdk_set_size_timer2(const struct dualtimer_cmsdk_dev_t* dev,
enum dualtimer_cmsdk_size_t bit_size)
{
if (DUALTIMER_CMSDK_SIZE_32BIT == bit_size) {
SET_BIT(DUALTIMER_REG_MAP(dev)->timer2ctrl, CTRL_REG_SIZE_INDEX);
} else {
CLR_BIT(DUALTIMER_REG_MAP(dev)->timer2ctrl, CTRL_REG_SIZE_INDEX);
}
}
void dualtimer_cmsdk_set_size_both_timers(
const struct dualtimer_cmsdk_dev_t* dev,
enum dualtimer_cmsdk_size_t bit_size)
{
dualtimer_cmsdk_set_size_timer1(dev, bit_size);
dualtimer_cmsdk_set_size_timer2(dev, bit_size);
}
enum dualtimer_cmsdk_size_t dualtimer_cmsdk_get_size_timer1(
const struct dualtimer_cmsdk_dev_t* dev)
{
if(GET_BIT(DUALTIMER_REG_MAP(dev)->timer1ctrl, CTRL_REG_SIZE_INDEX)) {
return DUALTIMER_CMSDK_SIZE_32BIT;
}
return DUALTIMER_CMSDK_SIZE_16BIT;
}
enum dualtimer_cmsdk_size_t dualtimer_cmsdk_get_size_timer2(
const struct dualtimer_cmsdk_dev_t* dev)
{
if(GET_BIT(DUALTIMER_REG_MAP(dev)->timer2ctrl, CTRL_REG_SIZE_INDEX)) {
return DUALTIMER_CMSDK_SIZE_32BIT;
}
return DUALTIMER_CMSDK_SIZE_16BIT;
}
/** Timer Prescale */
void dualtimer_cmsdk_set_prescale_timer1(
const struct dualtimer_cmsdk_dev_t* dev,
enum dualtimer_cmsdk_prescale_t prescale)
{
SET_NBITS(DUALTIMER_REG_MAP(dev)->timer1ctrl, CTRL_REG_PRESCALE_INDEX,
TWO_BITS_WIDTH, prescale);
}
void dualtimer_cmsdk_set_prescale_timer2(
const struct dualtimer_cmsdk_dev_t* dev,
enum dualtimer_cmsdk_prescale_t prescale)
{
SET_NBITS(DUALTIMER_REG_MAP(dev)->timer2ctrl, CTRL_REG_PRESCALE_INDEX,
TWO_BITS_WIDTH, prescale);
}
void dualtimer_cmsdk_set_prescale_both_timers(
const struct dualtimer_cmsdk_dev_t* dev,
enum dualtimer_cmsdk_prescale_t prescale)
{
dualtimer_cmsdk_set_prescale_timer1(dev, prescale);
dualtimer_cmsdk_set_prescale_timer2(dev, prescale);
}
enum dualtimer_cmsdk_prescale_t dualtimer_cmsdk_get_prescale_timer1(
const struct dualtimer_cmsdk_dev_t* dev)
{
return (enum dualtimer_cmsdk_prescale_t)\
GET_NBITS(DUALTIMER_REG_MAP(dev)->timer1ctrl, CTRL_REG_PRESCALE_INDEX,
TWO_BITS_WIDTH);
}
enum dualtimer_cmsdk_prescale_t dualtimer_cmsdk_get_prescale_timer2(
const struct dualtimer_cmsdk_dev_t* dev)
{
return (enum dualtimer_cmsdk_prescale_t)\
GET_NBITS(DUALTIMER_REG_MAP(dev)->timer2ctrl, CTRL_REG_PRESCALE_INDEX,
TWO_BITS_WIDTH);
}
/** Timer Mode */
void dualtimer_cmsdk_set_mode_timer1(const struct dualtimer_cmsdk_dev_t* dev,
enum dualtimer_cmsdk_mode_t mode)
{
if (DUALTIMER_CMSDK_PERIODIC == mode) {
SET_BIT(DUALTIMER_REG_MAP(dev)->timer1ctrl, CTRL_REG_MODE_INDEX);
} else {
CLR_BIT(DUALTIMER_REG_MAP(dev)->timer1ctrl, CTRL_REG_MODE_INDEX);
}
}
void dualtimer_cmsdk_set_mode_timer2(const struct dualtimer_cmsdk_dev_t* dev,
enum dualtimer_cmsdk_mode_t mode)
{
if (DUALTIMER_CMSDK_PERIODIC == mode) {
SET_BIT(DUALTIMER_REG_MAP(dev)->timer2ctrl, CTRL_REG_MODE_INDEX);
} else {
CLR_BIT(DUALTIMER_REG_MAP(dev)->timer2ctrl, CTRL_REG_MODE_INDEX);
}
}
void dualtimer_cmsdk_set_mode_both_timers(
const struct dualtimer_cmsdk_dev_t* dev,
enum dualtimer_cmsdk_mode_t mode)
{
dualtimer_cmsdk_set_mode_timer1(dev, mode);
dualtimer_cmsdk_set_mode_timer2(dev, mode);
}
enum dualtimer_cmsdk_mode_t dualtimer_cmsdk_get_mode_timer1(
const struct dualtimer_cmsdk_dev_t* dev)
{
return (enum dualtimer_cmsdk_mode_t)\
GET_BIT(DUALTIMER_REG_MAP(dev)->timer1ctrl, CTRL_REG_MODE_INDEX);
}
enum dualtimer_cmsdk_mode_t dualtimer_cmsdk_get_mode_timer2(
const struct dualtimer_cmsdk_dev_t* dev)
{
return (enum dualtimer_cmsdk_mode_t)\
GET_BIT(DUALTIMER_REG_MAP(dev)->timer2ctrl, CTRL_REG_MODE_INDEX);
}
/** Reload-Background reload */
enum dualtimer_cmsdk_error_t dualtimer_cmsdk_set_reload_timer1(
const struct dualtimer_cmsdk_dev_t* dev,
uint32_t reload)
{
const uint32_t rel_size = dualtimer_cmsdk_get_size_timer1(dev);
if (DUALTIMER_CMSDK_SIZE_16BIT == rel_size && UINT16_MAX <= reload) {
return DUALTIMER_CMSDK_ERR_OVERFLOW;
}
DUALTIMER_REG_MAP(dev)->timer1load = reload;
return DUALTIMER_CMSDK_ERR_NONE;
}
enum dualtimer_cmsdk_error_t dualtimer_cmsdk_set_reload_timer2(
const struct dualtimer_cmsdk_dev_t* dev,
uint32_t reload)
{
const uint32_t rel_size = dualtimer_cmsdk_get_size_timer2(dev);
if (DUALTIMER_CMSDK_SIZE_16BIT == rel_size && UINT16_MAX <= reload) {
return DUALTIMER_CMSDK_ERR_OVERFLOW;
}
DUALTIMER_REG_MAP(dev)->timer2load = reload;
return DUALTIMER_CMSDK_ERR_NONE;
}
enum dualtimer_cmsdk_error_t dualtimer_cmsdk_set_reload_both_timers(
const struct dualtimer_cmsdk_dev_t* dev,
uint32_t reload)
{
uint32_t ret = 0;
ret +=(uint32_t)dualtimer_cmsdk_set_reload_timer2(dev, reload);
ret +=(uint32_t)dualtimer_cmsdk_set_reload_timer2(dev, reload);
if (ret) {
return DUALTIMER_CMSDK_ERR_OVERFLOW;
}
return DUALTIMER_CMSDK_ERR_NONE;
}
uint32_t dualtimer_cmsdk_get_reload_timer1(
const struct dualtimer_cmsdk_dev_t* dev)
{
return DUALTIMER_REG_MAP(dev)->timer1load;
}
uint32_t dualtimer_cmsdk_get_reload_timer2(
const struct dualtimer_cmsdk_dev_t* dev)
{
return DUALTIMER_REG_MAP(dev)->timer2load;
}
enum dualtimer_cmsdk_error_t dualtimer_cmsdk_set_bgreload_timer1(
const struct dualtimer_cmsdk_dev_t* dev,
uint32_t reload)
{
const uint32_t rel_size = dualtimer_cmsdk_get_size_timer1(dev);
if (DUALTIMER_CMSDK_SIZE_16BIT == rel_size && UINT16_MAX <= reload) {
return DUALTIMER_CMSDK_ERR_OVERFLOW;
}
DUALTIMER_REG_MAP(dev)->timer1bgload = reload;
return DUALTIMER_CMSDK_ERR_NONE;
}
enum dualtimer_cmsdk_error_t dualtimer_cmsdk_set_bgreload_timer2(
const struct dualtimer_cmsdk_dev_t* dev,
uint32_t reload)
{
const uint32_t rel_size = dualtimer_cmsdk_get_size_timer2(dev);
if (DUALTIMER_CMSDK_SIZE_16BIT == rel_size && UINT16_MAX <= reload) {
return DUALTIMER_CMSDK_ERR_OVERFLOW;
}
DUALTIMER_REG_MAP(dev)->timer2bgload = reload;
return DUALTIMER_CMSDK_ERR_NONE;
}
enum dualtimer_cmsdk_error_t dualtimer_cmsdk_set_bgreload_both_timers(
const struct dualtimer_cmsdk_dev_t* dev,
uint32_t reload)
{
uint32_t ret = 0;
ret +=(uint32_t)dualtimer_cmsdk_set_bgreload_timer1(dev, reload);
ret +=(uint32_t)dualtimer_cmsdk_set_bgreload_timer2(dev, reload);
if (ret) {
return DUALTIMER_CMSDK_ERR_OVERFLOW;
}
return DUALTIMER_CMSDK_ERR_NONE;
}
uint32_t dualtimer_cmsdk_get_bgreload_timer1(
const struct dualtimer_cmsdk_dev_t* dev)
{
return DUALTIMER_REG_MAP(dev)->timer1bgload;
}
uint32_t dualtimer_cmsdk_get_bgreload_timer2(
const struct dualtimer_cmsdk_dev_t* dev)
{
return DUALTIMER_REG_MAP(dev)->timer2bgload;
}
/** Current timer value */
uint32_t dualtimer_cmsdk_get_current_timer1(
const struct dualtimer_cmsdk_dev_t* dev)
{
return DUALTIMER_REG_MAP(dev)->timer1value;
}
uint32_t dualtimer_cmsdk_get_current_timer2(
const struct dualtimer_cmsdk_dev_t* dev)
{
return DUALTIMER_REG_MAP(dev)->timer2value;
}
/** Status check methods */
bool dualtimer_cmsdk_is_enabled_timer1(
const struct dualtimer_cmsdk_dev_t* dev)
{
return (bool)GET_BIT(DUALTIMER_REG_MAP(dev)->timer1ctrl,
CTRL_REG_TIMER_EN_INDEX);
}
bool dualtimer_cmsdk_is_enabled_timer2(
const struct dualtimer_cmsdk_dev_t* dev)
{
return (bool)GET_BIT(DUALTIMER_REG_MAP(dev)->timer2ctrl,
CTRL_REG_TIMER_EN_INDEX);
}
bool dualtimer_cmsdk_is_interrupt_enabled_timer1(
const struct dualtimer_cmsdk_dev_t* dev)
{
return (bool)GET_BIT(DUALTIMER_REG_MAP(dev)->timer1ctrl,
CTRL_REG_IRQ_EN_INDEX);
}
bool dualtimer_cmsdk_is_interrupt_enabled_timer2(
const struct dualtimer_cmsdk_dev_t* dev)
{
return (bool)GET_BIT(DUALTIMER_REG_MAP(dev)->timer2ctrl,
CTRL_REG_IRQ_EN_INDEX);
}
bool dualtimer_cmsdk_is_interrupt_active_timer1(
const struct dualtimer_cmsdk_dev_t* dev)
{
return (bool)GET_BIT(DUALTIMER_REG_MAP(dev)->timer1mis,
XMIS_REG_MASKED_IRQ_INDEX);
}
bool dualtimer_cmsdk_is_interrupt_active_timer2(
const struct dualtimer_cmsdk_dev_t* dev)
{
return (bool)GET_BIT(DUALTIMER_REG_MAP(dev)->timer2mis,
XMIS_REG_MASKED_IRQ_INDEX);
}
bool dualtimer_cmsdk_is_raw_interrupt_active_timer1(
const struct dualtimer_cmsdk_dev_t* dev)
{
return (bool)GET_BIT(DUALTIMER_REG_MAP(dev)->timer1ris,
XRIS_REG_RAW_IRQ_INDEX);
}
bool dualtimer_cmsdk_is_raw_interrupt_active_timer2(
const struct dualtimer_cmsdk_dev_t* dev)
{
return (bool)GET_BIT(DUALTIMER_REG_MAP(dev)->timer2ris,
XRIS_REG_RAW_IRQ_INDEX);
}
uint32_t dualtimer_cmsdk_get_elapsed_value_timer1(
const struct dualtimer_cmsdk_dev_t* dev)
{
struct dualtimer_cmsdk_reg_map_t* register_map =
(struct dualtimer_cmsdk_reg_map_t*)dev->cfg->base;
return register_map->timer1load - register_map->timer1value;
}
uint32_t dualtimer_cmsdk_get_elapsed_value_timer2(
const struct dualtimer_cmsdk_dev_t* dev)
{
struct dualtimer_cmsdk_reg_map_t* register_map =
(struct dualtimer_cmsdk_reg_map_t*)dev->cfg->base;
return register_map->timer2load - register_map->timer2value;
}
void dualtimer_cmsdk_reset_timer1(const struct dualtimer_cmsdk_dev_t* dev)
{
struct dualtimer_cmsdk_reg_map_t* register_map =
(struct dualtimer_cmsdk_reg_map_t*)dev->cfg->base;
register_map->timer1value = register_map->timer1load;
}
void dualtimer_cmsdk_reset_timer2(const struct dualtimer_cmsdk_dev_t* dev)
{
struct dualtimer_cmsdk_reg_map_t* register_map =
(struct dualtimer_cmsdk_reg_map_t*)dev->cfg->base;
register_map->timer2value = register_map->timer2load;
}
void dualtimer_cmsdk_reset_both_timers(const struct dualtimer_cmsdk_dev_t* dev)
{
struct dualtimer_cmsdk_reg_map_t* register_map =
(struct dualtimer_cmsdk_reg_map_t*)dev->cfg->base;
register_map->timer1value = register_map->timer1load;
register_map->timer2value = register_map->timer2load;
}

View File

@ -0,0 +1,888 @@
/*
* Copyright (c) 2016-2018 Arm Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* \file dualtimer_cmsdk_drv.h
* \brief Generic driver for ARM CMSDK Dualtimers.
*/
#ifndef __DUALTIMER_CMSDK_DRV_H__
#define __DUALTIMER_CMSDK_DRV_H__
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/* Dualtimer default reload value */
#define DUALTIMER_CMSDK_DEF_32BIT_RELOAD UINT32_MAX
#define DUALTIMER_CMSDK_DEF_16BIT_RELOAD UINT16_MAX
/* Dualtimer device configuration structure */
struct dualtimer_cmsdk_dev_cfg_t {
const uint32_t base; /*!< Dualtimer base address */
};
/* Dualtimer device data structure */
struct dualtimer_cmsdk_dev_data_t {
uint32_t is_initialized; /*!< Indicates if the timer is initialized */
};
/* Dualtimer device structure */
struct dualtimer_cmsdk_dev_t {
const struct dualtimer_cmsdk_dev_cfg_t* const cfg; /*!< Dualtimer
configuration */
struct dualtimer_cmsdk_dev_data_t* const data; /*!< Dualtimer data */
};
/* Dualtimer enumeration types */
enum dualtimer_cmsdk_error_t {
DUALTIMER_CMSDK_ERR_NONE = 0u, /*!< No error */
DUALTIMER_CMSDK_ERR_NOT_INIT, /*!< Error dualtimer is not initialized */
DUALTIMER_CMSDK_ERR_NOT_ENABLE, /*!< Error timer is not enabled */
DUALTIMER_CMSDK_ERR_OVERFLOW
};
enum dualtimer_cmsdk_size_t {
DUALTIMER_CMSDK_SIZE_16BIT = 0u, /*!< Timer is set as 16 Bit */
DUALTIMER_CMSDK_SIZE_32BIT = 1u /*!< Timer is set as 32 Bit */
};
enum dualtimer_cmsdk_prescale_t {
DUALTIMER_CMSDK_CLOCK_DIV1 = 0u, /*!< Timer pre-scale is clock/1 */
DUALTIMER_CMSDK_CLOCK_DIV16 = 1u, /*!< Timer pre-scale is clock/16 */
DUALTIMER_CMSDK_CLOCK_DIV256 = 2u, /*!< Timer pre-scale is clock/256 */
};
enum dualtimer_cmsdk_oneshot_t {
DUALTIMER_CMSDK_WRAPPING = 0u, /*!< Timer wraps around */
DUALTIMER_CMSDK_ONE_SHOT = 1u /*!< Timer will halt when reaching 0 */
};
enum dualtimer_cmsdk_mode_t {
DUALTIMER_CMSDK_FREE_RUNNING = 0u, /*!< Timer counts from UINT32_MAX */
DUALTIMER_CMSDK_PERIODIC = 1u /*!< Timer counts from load value */
};
/**
* \brief Initializes a dualtimer hardware.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \note This function doesn't check if dev is NULL.
* \note Init should be called prior to any other process.
*/
void dualtimer_cmsdk_init(const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Frees up a dualtimer hardware, so it could be reinitalized.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \note This function doesn't check if dev is NULL.
* \note Init should be called prior to any other process.
*/
void dualtimer_cmsdk_free(const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Enables single timer 1 included in dualtimer hardware.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
void dualtimer_cmsdk_enable_timer1(const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Enables single timer 2 included in dualtimer hardware.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
void dualtimer_cmsdk_enable_timer2(const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Enables both timer 1&2 included in dualtimer hardware.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
void dualtimer_cmsdk_enable_both_timers(
const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Disables timer 1 included in dualtimer hardware.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
void dualtimer_cmsdk_disable_timer1(
const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Disables timer 2 included in dualtimer hardware.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
void dualtimer_cmsdk_disable_timer2(const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Disables both timers 1&2 included in dualtimer hardware.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
void dualtimer_cmsdk_disable_both_timers(
const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Sets one shot count for timer 1 included in dualtimer hardware.
*
* When timer reaches zero if one-shot is set it will wait there until user
* does one of the following:
* - Write a new value to load register.
* - Clear one shot setting the timers to WRAPPING mode.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
* \param[in] mode enum dualtimer_cmsdk_oneshot_t WRAPPING/ONE_SHOT
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
void dualtimer_cmsdk_set_oneshot_count_timer1(
const struct dualtimer_cmsdk_dev_t* dev,
enum dualtimer_cmsdk_oneshot_t mode);
/**
* \brief Sets one shot count for timer 2 included in dualtimer hardware.
*
* When timer reaches zero if one-shot is set it will wait there until user
* does one of the following:
* - Write a new value to load register.
* - Clear one shot setting the timers to WRAPPING mode.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
* \param[in] mode enum dualtimer_cmsdk_oneshot_t WRAPING/ONE_SHOT
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
void dualtimer_cmsdk_set_oneshot_count_timer2(
const struct dualtimer_cmsdk_dev_t* dev,
enum dualtimer_cmsdk_oneshot_t mode);
/**
* \brief Sets one shot count for timers 1&2 included in dualtimer hardware.
*
* When timer reaches zero if one-shot is set it will wait there until user
* does one of the following:
* - Write a new value to load register.
* - Clear one shot setting the timers to WRAPPING mode.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
* \param[in] mode enum dualtimer_cmsdk_oneshot_t WRAPING/ONE_SHOT
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
void dualtimer_cmsdk_set_oneshot_count_both_timers(
const struct dualtimer_cmsdk_dev_t* dev,
enum dualtimer_cmsdk_oneshot_t mode);
/**
* \brief Sets the size of timer 1 included in dualtimer hardware.
*
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
* \param[in] bit_size enum dualtimer_cmsdk_oneshot_t SIZE_16BIT/SIZE_32BIT
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
void dualtimer_cmsdk_set_size_timer1(
const struct dualtimer_cmsdk_dev_t* dev,
enum dualtimer_cmsdk_size_t bit_size);
/**
* \brief Sets the size of timer 2 included in dualtimer hardware.
*
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
* \param[in] bit_size enum dualtimer_cmsdk_oneshot_t SIZE_16BIT/SIZE_32BIT
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
void dualtimer_cmsdk_set_size_timer2(
const struct dualtimer_cmsdk_dev_t* dev,
enum dualtimer_cmsdk_size_t bit_size);
/**
* \brief Sets the size of timers 1&2 included in dualtimer hardware.
*
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
* \param[in] bit_size enum dualtimer_cmsdk_oneshot_t SIZE_16BIT/SIZE_32BIT
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
void dualtimer_cmsdk_set_size_both_timers(
const struct dualtimer_cmsdk_dev_t* dev,
enum dualtimer_cmsdk_size_t bit_size);
/**
* \brief Gets the size of timer 1 included in dualtimer hardware.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \return enum dualtimer_cmsdk_oneshot_t SIZE_16BIT/SIZE_32BIT
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
enum dualtimer_cmsdk_size_t dualtimer_cmsdk_get_size_timer1(
const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Gets the size of timer 2 included in dualtimer hardware.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \return enum dualtimer_cmsdk_oneshot_t SIZE_16BIT/SIZE_32BIT
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
enum dualtimer_cmsdk_size_t dualtimer_cmsdk_get_size_timer2(
const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Sets the clock divider for timer 1 included in dualtimer hardware.
*
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
* \param[in] enum dualtimer_cmsdk_prescale_t prescale CLOCK_DIV1/16/256
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
void dualtimer_cmsdk_set_prescale_timer1(
const struct dualtimer_cmsdk_dev_t* dev,
enum dualtimer_cmsdk_prescale_t prescale);
/**
* \brief Sets the clock divider for timer 2 included in dualtimer hardware.
*
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
* \param[in] enum dualtimer_cmsdk_prescale_t prescale CLOCK_DIV1/16/256
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
void dualtimer_cmsdk_set_prescale_timer2(
const struct dualtimer_cmsdk_dev_t* dev,
enum dualtimer_cmsdk_prescale_t prescale);
/**
* \brief Sets the clock divider for timers 1&2 included in dualtimer hardware.
*
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
* \param[in] enum dualtimer_cmsdk_prescale_t prescale CLOCK_DIV1/16/256
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
void dualtimer_cmsdk_set_prescale_both_timers(
const struct dualtimer_cmsdk_dev_t* dev,
enum dualtimer_cmsdk_prescale_t prescale);
/**
* \brief Gets the current set prescale value for timer 1.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \return enum dualtimer_cmsdk_prescale_t prescale CLOCK_DIV1/16/256
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
enum dualtimer_cmsdk_prescale_t dualtimer_cmsdk_get_prescale_timer1(
const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Gets the current set prescale value for timer 2.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \return enum dualtimer_cmsdk_prescale_t prescale CLOCK_DIV1/16/256
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
enum dualtimer_cmsdk_prescale_t dualtimer_cmsdk_get_prescale_timer2(
const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Sets the run mode for timer1 1 included in dualtimer hardware.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
* \param[in] enum dualtimer_cmsdk_mode_t mode FREE_RUNNING/PERIODIC
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
void dualtimer_cmsdk_set_mode_timer1(const struct dualtimer_cmsdk_dev_t* dev,
enum dualtimer_cmsdk_mode_t mode);
/**
* \brief Sets the run mode for timer 2 included in dualtimer hardware.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
* \param[in] enum dualtimer_cmsdk_mode_t mode FREE_RUNNING/PERIODIC
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
void dualtimer_cmsdk_set_mode_timer2(const struct dualtimer_cmsdk_dev_t* dev,
enum dualtimer_cmsdk_mode_t mode);
/**
* \brief Sets the run mode for timers 1&2 included in dualtimer hardware.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
* \param[in] enum dualtimer_cmsdk_mode_t mode FREE_RUNNING/PERIODIC
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
void dualtimer_cmsdk_set_mode_both_timers(
const struct dualtimer_cmsdk_dev_t* dev,
enum dualtimer_cmsdk_mode_t mode);
/**
* \brief Gets the run mode for timer 1 included in dualtimer hardware.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \return enum dualtimer_cmsdk_mode_t mode FREE_RUNNING/PERIODIC
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
enum dualtimer_cmsdk_mode_t dualtimer_cmsdk_get_mode_timer1(
const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Gets the run mode for timer 2 included in dualtimer hardware.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \return enum dualtimer_cmsdk_mode_t mode FREE_RUNNING/PERIODIC
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
enum dualtimer_cmsdk_mode_t dualtimer_cmsdk_get_mode_timer2(
const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Enables the interrupt for timer 1 included in dualtimer hardware.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
* \note This function only enables the hardware irq, use NVIC for handler setup.
*/
void dualtimer_cmsdk_enable_interrupt_timer1(
const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Enables the interrupt for timer 2 included in dualtimer hardware.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
* \note This function only enables the hardware irq, use NVIC for handler setup.
*/
void dualtimer_cmsdk_enable_interrupt_timer2(
const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Enables the interrupt for timer 1&2 included in dualtimer hardware.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
* \note This function only enables the hardware irq, use NVIC for handler setup.
*/
void dualtimer_cmsdk_enable_interrupt_both_timers(
const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Disables the interrupt for timer 1 included in dualtimer hardware.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
void dualtimer_cmsdk_disable_interrupt_timer1(
const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Disables the interrupt for timer 2 included in dualtimer hardware.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
void dualtimer_cmsdk_disable_interrupt_timer2(
const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Disables the interrupt for timers 1&2 included in dualtimer hardware.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
void dualtimer_cmsdk_disable_interrupt_both_timers(
const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Clears the interrupt for timer 1 included in dualtimer hardware.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
void dualtimer_cmsdk_clear_interrupt_timer1(
const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Clears the interrupt for timer 2 included in dualtimer hardware.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
void dualtimer_cmsdk_clear_interrupt_timer2(
const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Set the reload value for timer 1 included in dualtimer hardware.
*
* Writing to the reload register while timer is active will reset the
* current value register to the reload value
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
* \param[in] reload uint32_t value that the timer counts down from
*
* \return dualtimer_cmsdk_error_t NONE/ERR_OVERFLOW
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
* \note This function will detect if users sets a uint32_t value to 16Bit timer
*/
enum dualtimer_cmsdk_error_t dualtimer_cmsdk_set_reload_timer1(
const struct dualtimer_cmsdk_dev_t* dev,
uint32_t reload);
/**
* \brief Set the reload value for timer 2 included in dualtimer hardware.
*
* Writing to the reload register while timer is active will reset the
* current value register to the reload value
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
* \param[in] reload uint32_t value that the timer counts down from
*
* \return dualtimer_cmsdk_error_t NONE/ERR_OVERFLOW
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
* \note This function will detect if users sets a uint32_t value to 16Bit timer
*/
enum dualtimer_cmsdk_error_t dualtimer_cmsdk_set_reload_timer2(
const struct dualtimer_cmsdk_dev_t* dev,
uint32_t reload);
/**
* \brief Set the reload value for timers 1&2 included in dualtimer hardware.
*
* Writing to the reload register while timer is active will reset the
* current value register to the reload value
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
* \param[in] reload uint32_t value that the timer counts down from
*
* \return dualtimer_cmsdk_error_t NONE/ERR_OVERFLOW
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
* \note This function will detect if users sets a uint32_t value to 16Bit timer
*/
enum dualtimer_cmsdk_error_t dualtimer_cmsdk_set_reload_both_timers(
const struct dualtimer_cmsdk_dev_t* dev,
uint32_t reload);
/**
* \brief Gets the reload value for timer 1 included in dualtimer hardware.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \return uint32_t Reload value of timer 1
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
uint32_t dualtimer_cmsdk_get_reload_timer1(
const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Gets the reload value for timer 2 included in dualtimer hardware.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \return uint32_t Reload value of timer 2
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
uint32_t dualtimer_cmsdk_get_reload_timer2(
const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Set the background-reload value for timer 1 of dualtimer hw.
*
* Unlike normal reload, writing to this register will not affect current
* value of timer, and the change become effective after the timer counts to zero
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
* \param[in] reload uint32_t value that the timer counts down from
*
* \return dualtimer_cmsdk_error_t NONE/ERR_OVERFLOW
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
* \note This function will detect if users sets a uint32_t value to 16Bit timer
*/
enum dualtimer_cmsdk_error_t dualtimer_cmsdk_set_bgreload_timer1(
const struct dualtimer_cmsdk_dev_t* dev,
uint32_t reload);
/**
* \brief Set the background-reload value for timers 2 of dualtimer hw.
*
* Unlike normal reload, writing to this register will not affect current
* value of timer, and the change become effective after the timer counts to zero
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
* \param[in] reload uint32_t value that the timer counts down from
*
* \return dualtimer_cmsdk_error_t NONE/ERR_OVERFLOW
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
* \note This function will detect if users sets a uint32_t value to 16Bit timer
*/
enum dualtimer_cmsdk_error_t dualtimer_cmsdk_set_bgreload_timer2(
const struct dualtimer_cmsdk_dev_t* dev,
uint32_t reload);
/**
* \brief Set the background-reload value for timers 1&2 of dualtimer hw.
*
* Unlike normal reload, writing to this register will not affect current
* value of timer, and the change become effective after the timer counts to zero
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
* \param[in] reload uint32_t value that the timer counts down from
*
* \return dualtimer_cmsdk_error_t NONE/ERR_OVERFLOW
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
* \note This function will detect if users sets a uint32_t value to 16Bit timer
*/
enum dualtimer_cmsdk_error_t dualtimer_cmsdk_set_bgreload_both_timers(
const struct dualtimer_cmsdk_dev_t* dev,
uint32_t reload);
/**
* \brief Gets the background-reload value for timer 1 of dualtimer hw.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \return uint32_t Reload value of timer 1
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
uint32_t dualtimer_cmsdk_get_bgreload_timer1(
const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Gets the background-reload value for timer 2 of dualtimer hw.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \return uint32_t Reload value of timer 2
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
uint32_t dualtimer_cmsdk_get_bgreload_timer2(
const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Gets the current value for timer 1 included in dualtimer hardware.
*
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \return uint32_t Copy of current value of timer.
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
uint32_t dualtimer_cmsdk_get_current_timer1(
const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Gets the current value for timer 2 included in dualtimer hardware.
*
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \return uint32_t Copy of current value of timer.
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
uint32_t dualtimer_cmsdk_get_current_timer2(
const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Checks if timer 1 included in dualtimer hardware, is enabled.
*
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \return bool true if timer 1 is enabled.
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
bool dualtimer_cmsdk_is_enabled_timer1(const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Checks if timer 2 included in dualtimer hardware, is enabled.
*
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \return bool true if timer 2 is enabled.
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
bool dualtimer_cmsdk_is_enabled_timer2(const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Checks if timer 1 included in dualtimer hardware, has the irq enabled.
*
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \return bool true if timer 1 irq is enabled.
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
bool dualtimer_cmsdk_is_interrupt_enabled_timer1(
const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Checks if timer 2 included in dualtimer hardware, has the irq enabled.
*
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \return bool true if timer 2 irq is enabled.
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
bool dualtimer_cmsdk_is_interrupt_enabled_timer2(
const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Checks the masked interrupt status of timer 1 included in dualtimer hw.
*
* This function is checking against the masked interrupt register which is the
* output of timerx enabled AND timerX raw interrupt.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \return bool true if timer 1's masked irq is active
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
bool dualtimer_cmsdk_is_interrupt_active_timer1(
const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Checks the masked interrupt status of timer 1 included in dualtimer hw.
*
* This function is checking against the masked interrupt register which is the
* output of timerx enabled AND timerX raw interrupt.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \return bool true if timer 2's masked irq is active
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
bool dualtimer_cmsdk_is_interrupt_active_timer2(
const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Checks the raw interrupt status of timer 1 included in dualtimer hw.
*
* This function is checking for the raw interrupt produced when timer reaches 0
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \return bool true if timer 1's masked irq is active
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
bool dualtimer_cmsdk_is_raw_interrupt_active_timer1(
const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Checks the raw interrupt status of timer 1 included in dualtimer hw.
*
* This function is checking for the raw interrupt produced when timer reaches 0
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \return bool true if timer 2's masked irq is active
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
bool dualtimer_cmsdk_is_raw_interrupt_active_timer2(
const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Checks if dualtimer hardware has been initialized.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \return bool true if dualtimer has been initialized.
*
* \note This function doesn't check if dev is NULL.
*/
bool dualtimer_cmsdk_is_initialized(const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Reads the number of ticks elapsed in the current cycle of timer 1.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \return Get elapsed number of ticks since last reload was set.
* Elapsed = (Reload value - Current value)
*/
uint32_t dualtimer_cmsdk_get_elapsed_value_timer1(
const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Reads the number of ticks elapsed in the current cycle of timer 2.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \return Get elapsed number of ticks since last reload was set.
* Elapsed = (Reload value - Current value)
*/
uint32_t dualtimer_cmsdk_get_elapsed_value_timer2(
const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Resets the timer 1 count value to the reload value.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
void dualtimer_cmsdk_reset_timer1(const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Resets the timer 2 count value to the reload value.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
void dualtimer_cmsdk_reset_timer2(const struct dualtimer_cmsdk_dev_t* dev);
/**
* \brief Resets both timers' count values to their reload values.
*
* \param[in] dev Dualtimer device structure \ref dualtimer_cmsdk_dev_t
*
* \note This function doesn't check if dev is NULL.
* \note This function doesn't check if dualtimer has been initialized.
*/
void dualtimer_cmsdk_reset_both_timers(const struct dualtimer_cmsdk_dev_t* dev);
#ifdef __cplusplus
}
#endif
#endif /* __DUALTIMER_CMSDK_DRV_H__ */

View File

@ -0,0 +1,226 @@
/*
* Copyright (c) 2018 Arm Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* \file rtc_pl031_drv.c
* \brief Implementation of the PL031 Real Time Clock (RTC) native driver.
*
* \note PL031 device specific definitions based on
* real_time_clock_pl031_r1p3_technical_reference_manual.pdf
* which is available from http://infocenter.arm.com.
*/
#include <stddef.h>
#include "rtc_pl031_drv.h"
/**
* \brief Structure to access the memory mapped registers of the PL031.
*/
struct rtc_pl031_dev_reg_map_t {
volatile uint32_t rtcdr; /*!< Data Register */
volatile uint32_t rtcmr; /*!< Match Register */
volatile uint32_t rtclr; /*!< Load Register */
volatile uint32_t rtccr; /*!< Control Register */
volatile uint32_t rtcimsc;
/*!< Interrupt Mask Set or Clear Register */
volatile uint32_t rtcris; /*!< Raw Interrupt Status Register */
volatile uint32_t rtcmis; /*!< Masked Interrupt Status Register */
volatile uint32_t rtcicr; /*!< Interrupt Clear Register */
volatile uint32_t reserved[1008]; /*!< Reserved from Offset 0x20-0xFDC */
volatile uint32_t rtcperiphid0; /*!< Peripheral ID0 Register */
volatile uint32_t rtcperiphid1; /*!< Peripheral ID1 Register */
volatile uint32_t rtcperiphid2; /*!< Peripheral ID2 Register */
volatile uint32_t rtcperiphid3; /*!< Peripheral ID3 Register */
volatile uint32_t rtcpcellid0; /*!< Primary Cell ID0 Register */
volatile uint32_t rtcpcellid1; /*!< Primary Cell ID1 Register */
volatile uint32_t rtcpcellid2; /*!< Primary Cell ID2 Register */
volatile uint32_t rtcpcellid3; /*!< Primary Cell ID3 Register */
};
/* RTC Control Register */
#define RTC_PL031_RTCCR_ENABLE_POS 0x0U
#define RTC_PL031_RTCCR_ENABLE_MSK (0x1U << RTC_PL031_RTCCR_ENABLE_POS)
/* RTC Interrupt Mask Set or Clear Register */
#define RTC_PL031_RTCIMSC_SET_CLEAR_POS 0x0U
#define RTC_PL031_RTCIMSC_SET_CLEAR_MSK (0x1U << \
RTC_PL031_RTCIMSC_SET_CLEAR_POS)
/* RTC RAW Interrupt Status Register */
#define RTC_PL031_RTCRIS_STATUS_POS 0x0U
#define RTC_PL031_RTCRIS_STATUS_MSK (0x1U << RTC_PL031_RTCRIS_STATUS_POS)
/* RTC Masked Interrupt Status Register */
#define RTC_PL031_RTCMIS_STATUS_POS 0x0U
#define RTC_PL031_RTCMIS_STATUS_MSK (0x1U << RTC_PL031_RTCMIS_STATUS_POS)
/* RTC Interrupt Clear Register */
#define RTC_PL031_RTCICR_CLEAR_POS 0x0U
#define RTC_PL031_RTCICR_CLEAR_MSK (0x1U << RTC_PL031_RTCICR_CLEAR_POS)
bool rtc_pl031_init(struct rtc_pl031_dev_t* dev)
{
struct rtc_pl031_dev_reg_map_t* p_rtc;
if (dev == NULL) {
return false;
}
p_rtc = (struct rtc_pl031_dev_reg_map_t*) dev->cfg->base;
p_rtc->rtcmr = 0U;
p_rtc->rtcicr = RTC_PL031_RTCICR_CLEAR_MSK;
return true;
}
bool rtc_pl031_dev_enable(struct rtc_pl031_dev_t* dev)
{
struct rtc_pl031_dev_reg_map_t* p_rtc;
if (dev == NULL) {
return false;
}
p_rtc = (struct rtc_pl031_dev_reg_map_t*) dev->cfg->base;
p_rtc->rtccr = RTC_PL031_RTCCR_ENABLE_MSK;
return true;
}
bool rtc_pl031_dev_disable(struct rtc_pl031_dev_t* dev)
{
struct rtc_pl031_dev_reg_map_t* p_rtc;
if (dev == NULL) {
return false;
}
p_rtc = (struct rtc_pl031_dev_reg_map_t*) dev->cfg->base;
p_rtc->rtccr = 0U;
return true;
}
bool rtc_pl031_read_current_time(struct rtc_pl031_dev_t* dev, uint32_t *seconds)
{
struct rtc_pl031_dev_reg_map_t* p_rtc;
if (dev == NULL || seconds == NULL) {
return false;
}
p_rtc = (struct rtc_pl031_dev_reg_map_t*) dev->cfg->base;
*seconds = (uint32_t)p_rtc->rtcdr;
return true;
}
bool rtc_pl031_write_current_time(struct rtc_pl031_dev_t* dev, uint32_t seconds)
{
struct rtc_pl031_dev_reg_map_t* p_rtc;
if (dev == NULL) {
return false;
}
p_rtc = (struct rtc_pl031_dev_reg_map_t*) dev->cfg->base;
p_rtc->rtclr = (uint32_t)seconds;
return true;
}
bool rtc_pl031_enable_interrupt(struct rtc_pl031_dev_t* dev)
{
struct rtc_pl031_dev_reg_map_t* p_rtc;
if (dev == NULL) {
return false;
}
p_rtc = (struct rtc_pl031_dev_reg_map_t*) dev->cfg->base;
p_rtc->rtcimsc = 0U;
return true;
}
bool rtc_pl031_disable_interrupt(struct rtc_pl031_dev_t* dev)
{
struct rtc_pl031_dev_reg_map_t* p_rtc;
if (dev == NULL) {
return false;
}
p_rtc = (struct rtc_pl031_dev_reg_map_t*) dev->cfg->base;
p_rtc->rtcimsc = RTC_PL031_RTCIMSC_SET_CLEAR_MSK;
return true;
}
bool rtc_pl031_is_interrupt_masked(struct rtc_pl031_dev_t* dev)
{
struct rtc_pl031_dev_reg_map_t* p_rtc =
(struct rtc_pl031_dev_reg_map_t*) dev->cfg->base;
if (p_rtc->rtcimsc & RTC_PL031_RTCIMSC_SET_CLEAR_MSK){
return true;
} else {
return false;
}
}
bool rtc_pl031_is_raw_interrupt_pending(struct rtc_pl031_dev_t* dev)
{
struct rtc_pl031_dev_reg_map_t* p_rtc =
(struct rtc_pl031_dev_reg_map_t*) dev->cfg->base;
if (p_rtc->rtcris & RTC_PL031_RTCRIS_STATUS_MSK) {
return true;
} else {
return false;
}
}
bool rtc_pl031_is_masked_interrupt_pending(struct rtc_pl031_dev_t* dev)
{
struct rtc_pl031_dev_reg_map_t* p_rtc =
(struct rtc_pl031_dev_reg_map_t*) dev->cfg->base;
if (p_rtc->rtcmis & RTC_PL031_RTCMIS_STATUS_MSK) {
return true;
} else {
return false;
}
}
bool rtc_pl031_write_match_value(struct rtc_pl031_dev_t* dev, uint32_t seconds)
{
struct rtc_pl031_dev_reg_map_t* p_rtc;
if (dev == NULL) {
return false;
}
p_rtc = (struct rtc_pl031_dev_reg_map_t*) dev->cfg->base;
p_rtc->rtcmr = (uint32_t)seconds;
return true;
}
bool rtc_pl031_clear_interrupt(struct rtc_pl031_dev_t* dev)
{
struct rtc_pl031_dev_reg_map_t* p_rtc;
if (dev == NULL) {
return false;
}
p_rtc = (struct rtc_pl031_dev_reg_map_t*) dev->cfg->base;
p_rtc->rtcicr = RTC_PL031_RTCICR_CLEAR_MSK;
return true;
}

View File

@ -0,0 +1,180 @@
/*
* Copyright (c) 2018 Arm Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* \file rtc_pl031_drv.h
* \brief Declarations for the PL031 Real Time Clock (RTC) native driver.
*/
#ifndef __RTC_PL031_DRV_H__
#define __RTC_PL031_DRV_H__
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief RTC PL031 device configuration structure.
*/
struct rtc_pl031_dev_cfg_t {
const uintptr_t base; /*!< RTC PL031 base address */
};
/**
* \brief RTC PL031 device structure.
*/
struct rtc_pl031_dev_t {
const struct rtc_pl031_dev_cfg_t* const cfg;
/*!< RTC driver configuration */
};
/**
* \brief Initializes the RTC PL031 device.
*
* \param[in] dev RTC device structure \ref rtc_pl031_dev_t.
*
* \return Return true indicates that the function executed successfully,
* otherwise an error occurred.
*/
bool rtc_pl031_init(struct rtc_pl031_dev_t* dev);
/**
* \brief Enables RTC PL031 device.
*
* \param[in] dev RTC device structure \ref rtc_pl031_dev_t.
*
* \return Return true indicates that the function executed successfully,
* otherwise an error occurred.
*/
bool rtc_pl031_dev_enable(struct rtc_pl031_dev_t* dev);
/**
* \brief Disables RTC PL031 device.
*
* \param[in] dev RTC device structure \ref rtc_pl031_dev_t.
*
* \return Return true indicates that the function executed successfully,
* otherwise an error occurred.
*/
bool rtc_pl031_dev_disable(struct rtc_pl031_dev_t* dev);
/**
* \brief Reads current time from RTC PL031 device.
*
* \param[in] dev RTC device structure \ref rtc_pl031_dev_t.
* \param[out] seconds Current time in seconds.
*
* \return Return true indicates that the function executed successfully,
* otherwise an error occurred.
*/
bool rtc_pl031_read_current_time(struct rtc_pl031_dev_t* dev,
uint32_t *seconds);
/**
* \brief Writes current time to RTC PL031 device.
*
* \param[in] dev RTC device structure \ref rtc_pl031_dev_t.
* \param[in] seconds Current time to be set in seconds.
*
* \return Return true indicates that the function executed successfully,
* otherwise an error occurred.
*/
bool rtc_pl031_write_current_time(struct rtc_pl031_dev_t* dev,
uint32_t seconds);
/**
* \brief Clears interrupt mask of RTC PL031.
*
* \param[in] dev RTC device structure \ref rtc_pl031_dev_t.
*
* \return Return true indicates that the function executed successfully,
* otherwise an error occurred.
*/
bool rtc_pl031_enable_interrupt(struct rtc_pl031_dev_t* dev);
/**
* \brief Sets interrupt mask of RTC PL031.
*
* \param[in] dev RTC device structure \ref rtc_pl031_dev_t.
*
* \return Return true indicates that the function executed successfully,
* otherwise an error occurred.
*/
bool rtc_pl031_disable_interrupt(struct rtc_pl031_dev_t* dev);
/**
* \brief Check if RTC PL031 interrupt is masked.
*
* \param[in] dev RTC device structure \ref rtc_pl031_dev_t.
*
* \return Return true indicates that RTC PL031 interrupt is masked.
*
* \note This function does not check if dev is NULL.
*/
bool rtc_pl031_is_interrupt_masked(struct rtc_pl031_dev_t* dev);
/**
* \brief Gets raw interrupt pending status of RTC PL031.
*
* \param[in] dev RTC device structure \ref rtc_pl031_dev_t.
*
* \return Return true indicates that RTC PL031 raw interrupt
* status is pending.
*
* \note This function does not check if dev is NULL.
*/
bool rtc_pl031_is_raw_interrupt_pending(struct rtc_pl031_dev_t* dev);
/**
* \brief Gets masked interrupt pending status of RTC PL031.
*
* \param[in] dev RTC device structure \ref rtc_pl031_dev_t.
*
* \return Return true indicates that RTC PL031 masked interrupt
* status is pending.
*
* \note This function does not check if dev is NULL.
*/
bool rtc_pl031_is_masked_interrupt_pending(struct rtc_pl031_dev_t* dev);
/**
* \brief Writes match value to RTC PL031 device.
*
* \param[in] dev RTC device structure \ref rtc_pl031_dev_t.
* \param[in] seconds Match value to be set in seconds.
*
* \return Return true indicates that the function executed successfully,
* otherwise an error occurred.
*/
bool rtc_pl031_write_match_value(struct rtc_pl031_dev_t* dev, uint32_t seconds);
/**
* \brief Clear interrupt status bit of RTC PL031.
*
* \param[in] dev RTC device structure \ref rtc_pl031_dev_t.
*
* \return Return true indicates that the function executed successfully,
* otherwise an error occurred.
*/
bool rtc_pl031_clear_interrupt(struct rtc_pl031_dev_t* dev);
#ifdef __cplusplus
}
#endif
#endif /* __RTC_PL031_DRV_H__ */

View File

@ -37,6 +37,23 @@ struct timer_cmsdk_dev_t CMSDK_TIMER1_DEV = {&(CMSDK_TIMER1_DEV_CFG),
&(CMSDK_TIMER1_DEV_DATA)};
#endif
/* ARM CMSDK Dual Timer driver structure */
#ifdef ARM_CMSDK_DUALTIMER
static const struct dualtimer_cmsdk_dev_cfg_t CMSDK_DUALTIMER_DEV_CFG = {
.base = CMSDK_DUALTIMER_BASE};
static struct dualtimer_cmsdk_dev_data_t CMSDK_DUALTIMER_DEV_DATA = {
.is_initialized = 0};
struct dualtimer_cmsdk_dev_t CMSDK_DUALTIMER_DEV = {&(CMSDK_DUALTIMER_DEV_CFG),
&(CMSDK_DUALTIMER_DEV_DATA)};
#endif
/* PL031 Real-Time Clock structure */
#ifdef RTC_PL031
static const struct rtc_pl031_dev_cfg_t RTC_PL031_DEV_CFG = {
.base = CMSDK_RTC_BASE};
struct rtc_pl031_dev_t RTC_PL031_DEV = {&(RTC_PL031_DEV_CFG)};
#endif
/* ARM GPIO driver structures */
#ifdef ARM_GPIO0
static const struct arm_gpio_dev_cfg_t ARM_GPIO0_DEV_CFG = {

View File

@ -20,84 +20,107 @@
/* ======= Configures the peripheral set ======= */
#include "device_cfg.h"
/* ======= Includes generic driver headers ======= */
#include "timer_cmsdk_drv.h"
#include "arm_gpio_drv.h"
#include "arm_mps2_io_drv.h"
#include "spi_pl022_drv.h"
#include "arm_uart_drv.h"
#include "smsc9220_eth_drv.h"
/* ======= Defines peripheral configuration structures ======= */
/* ARM CMSDK Timer driver structures */
#ifdef ARM_CMSDK_TIMER0
#include "timer_cmsdk_drv.h"
extern struct timer_cmsdk_dev_t CMSDK_TIMER0_DEV;
#endif
#ifdef ARM_CMSDK_TIMER1
#include "timer_cmsdk_drv.h"
extern struct timer_cmsdk_dev_t CMSDK_TIMER1_DEV;
#endif
/* ARM CMSDK Dual Timer driver structure */
#ifdef ARM_CMSDK_DUALTIMER
#include "dualtimer_cmsdk_drv.h"
extern struct dualtimer_cmsdk_dev_t CMSDK_DUALTIMER_DEV;
#endif
/* RTC PL031 */
#ifdef RTC_PL031
#include "rtc_pl031_drv.h"
extern struct rtc_pl031_dev_t RTC_PL031_DEV;
#endif
/* ARM GPIO driver structures */
#ifdef ARM_GPIO0
#include "arm_gpio_drv.h"
extern struct arm_gpio_dev_t ARM_GPIO0_DEV;
#endif
#ifdef ARM_GPIO1
#include "arm_gpio_drv.h"
extern struct arm_gpio_dev_t ARM_GPIO1_DEV;
#endif
#ifdef ARM_GPIO2
#include "arm_gpio_drv.h"
extern struct arm_gpio_dev_t ARM_GPIO2_DEV;
#endif
#ifdef ARM_GPIO3
#include "arm_gpio_drv.h"
extern struct arm_gpio_dev_t ARM_GPIO3_DEV;
#endif
/* ARM MPS2 IO FPGAIO driver structures */
#ifdef ARM_MPS2_IO_FPGAIO
#include "arm_mps2_io_drv.h"
extern struct arm_mps2_io_dev_t ARM_MPS2_IO_FPGAIO_DEV;
#endif
/* ARM MPS2 IO SCC driver structures */
#ifdef ARM_MPS2_IO_SCC
#include "arm_mps2_io_drv.h"
extern struct arm_mps2_io_dev_t ARM_MPS2_IO_SCC_DEV;
#endif
/* ARM SPI driver structures */
#ifdef ARM_SPI0
#include "spi_pl022_drv.h"
extern struct spi_pl022_dev_t SPI0_PL022_DEV;
#endif
#ifdef ARM_SPI1
#include "spi_pl022_drv.h"
extern struct spi_pl022_dev_t SPI1_PL022_DEV;
#endif
#ifdef ARM_SPI2
#include "spi_pl022_drv.h"
extern struct spi_pl022_dev_t SPI2_PL022_DEV;
#endif
#ifdef ARM_SPI3
#include "spi_pl022_drv.h"
extern struct spi_pl022_dev_t SPI3_PL022_DEV;
#endif
#ifdef ARM_SPI4
#include "spi_pl022_drv.h"
extern struct spi_pl022_dev_t SPI4_PL022_DEV;
#endif
/* ARM UART driver structures */
#ifdef ARM_UART0
#include "arm_uart_drv.h"
extern struct arm_uart_dev_t ARM_UART0_DEV;
#endif
#ifdef ARM_UART1
#include "arm_uart_drv.h"
extern struct arm_uart_dev_t ARM_UART1_DEV;
#endif
#ifdef ARM_UART2
#include "arm_uart_drv.h"
extern struct arm_uart_dev_t ARM_UART2_DEV;
#endif
#ifdef ARM_UART3
#include "arm_uart_drv.h"
extern struct arm_uart_dev_t ARM_UART3_DEV;
#endif
#ifdef ARM_UART4
#include "arm_uart_drv.h"
extern struct arm_uart_dev_t ARM_UART4_DEV;
#endif
#ifdef SMSC9220_ETH
#include "smsc9220_eth_drv.h"
extern struct smsc9220_eth_dev_t SMSC9220_ETH_DEV;
#endif

View File

@ -1,5 +1,5 @@
/* mbed Microcontroller Library
* Copyright (c) 2018 ARM Limited
* Copyright (c) 2017-2018 Arm Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -14,108 +14,95 @@
* limitations under the License.
*/
/**
* Low-power elapsed time measure and interval timer in micro-secundum,
* servicing \ref lp_ticker_api.h, using CMSDK Timer1 \ref CMSDK_TIMER1_DEV.
*/
/**
* Supports the Low Power Ticker for mbed by implementing \ref lp_ticker_api.h,
* using both timers in a CMSDK Dual Timer \ref dualtimer_cmsdk_dev_t.
*/
#include <limits.h>
#include "cmsdk_ticker.h"
#include "dualtimer_cmsdk_drv.h"
#include "lp_ticker_api.h"
#include "platform_devices.h"
#if DEVICE_LPTICKER
/**
* \brief Calculate clocks to us
*
* \param[in] tick Number of clock ticks
*
* \return Number of usec, relative to the timer frequency,
* that a given ammount of ticks equates to.
static uint32_t last_read = 0;
/* Initializes both timers in the Dualtimer:
* -Timer1 as the free running timer
* -Timer2 as the interval timer
* Both timers are set:
* -32 bit size
* -256 Clk divisor
* -Maximum reload value
*/
static uint32_t convert_tick_to_us(uint32_t tick)
{
return (tick / (SystemCoreClock / SEC_TO_USEC_MULTIPLIER));
}
/**
* \brief Calculate us to clock ticks
*
* \param[in] us Time to convert to clock ticks
*
* \return Number of clock ticks relative to the timer frequency,
* that a given period of usec equates to.
*/
static uint32_t convert_us_to_tick(uint32_t us)
{
return (us * (SystemCoreClock / SEC_TO_USEC_MULTIPLIER));
}
static const struct tick_cfg_t cfg =
{
.timer_driver = &CMSDK_TIMER1_DEV,
.irq_n = TIMER1_IRQn,
.interval_callback = &lp_ticker_irq_handler,
.convert_tick_to_time = &convert_tick_to_us,
.convert_time_to_tick = &convert_us_to_tick
};
static struct tick_data_t data =
{
.is_initialized = false,
.cumulated_time = 0,
.max_interval_time = 0,
.reload_time = 0,
.interval_callback_enabled = false,
.previous_cumulated_time = 0,
.previous_elapsed = 0
};
static struct tick_drv_data_t timer_data =
{
.cfg = &cfg,
.data = &data
};
void lp_ticker_init(void)
{
cmsdk_ticker_init(&timer_data);
}
uint32_t lp_ticker_read()
{
return cmsdk_ticker_read(&timer_data);
}
void lp_ticker_set_interrupt(timestamp_t timestamp)
{
cmsdk_ticker_set_interrupt(&timer_data, timestamp);
}
void lp_ticker_disable_interrupt(void)
{
cmsdk_ticker_disable_interrupt(&timer_data);
}
void lp_ticker_clear_interrupt(void)
{
cmsdk_ticker_clear_interrupt(&timer_data);
}
void lp_ticker_fire_interrupt(void)
{
cmsdk_ticker_fire_interrupt(&timer_data);
dualtimer_cmsdk_init(&LP_TIMER_DEV);
dualtimer_cmsdk_set_size_both_timers(&LP_TIMER_DEV,
DUALTIMER_CMSDK_SIZE_32BIT);
dualtimer_cmsdk_set_prescale_both_timers(&LP_TIMER_DEV,
DUALTIMER_CMSDK_CLOCK_DIV256);
dualtimer_cmsdk_disable_both_timers(&LP_TIMER_DEV);
dualtimer_cmsdk_set_reload_both_timers(&LP_TIMER_DEV,
TIMER_CMSDK_MAX_RELOAD);
dualtimer_cmsdk_reset_both_timers(&LP_TIMER_DEV);
NVIC_EnableIRQ(LP_INTERVAL_IRQ);
dualtimer_cmsdk_enable_both_timers(&LP_TIMER_DEV);
}
void lp_ticker_free(void)
{
dualtimer_cmsdk_free(&LP_TIMER_DEV);
}
void TIMER1_IRQHandler(void)
uint32_t lp_ticker_read()
{
cmsdk_ticker_irq_handler(&timer_data);
uint32_t tick = dualtimer_cmsdk_get_elapsed_value_timer1(&LP_TIMER_DEV);
last_read = tick >> LP_REPORTED_SHIFT;
return last_read;
}
void lp_ticker_set_interrupt(timestamp_t timestamp)
{
uint32_t reload = (timestamp - last_read) << LP_REPORTED_SHIFT;
dualtimer_cmsdk_disable_timer2(&LP_TIMER_DEV);
dualtimer_cmsdk_set_reload_timer2(&LP_TIMER_DEV, reload);
dualtimer_cmsdk_reset_timer2(&LP_TIMER_DEV);
dualtimer_cmsdk_enable_interrupt_timer2(&LP_TIMER_DEV);
dualtimer_cmsdk_enable_timer2(&LP_TIMER_DEV);
}
void lp_ticker_disable_interrupt(void)
{
dualtimer_cmsdk_disable_interrupt_timer2(&LP_TIMER_DEV);
}
void lp_ticker_clear_interrupt(void)
{
dualtimer_cmsdk_clear_interrupt_timer2(&LP_TIMER_DEV);
}
void lp_ticker_fire_interrupt(void)
{
NVIC_SetPendingIRQ(LP_INTERVAL_IRQ);
}
const ticker_info_t* lp_ticker_get_info()
{
static const ticker_info_t info = {
LP_REPORTED_FREQ_HZ,
LP_REPORTED_BITS
};
return &info;
}
#ifndef lp_interval_irq_handler
#error "lp_interval_irq_handler should be defined, check device_cfg.h!"
#endif
/* According to mbed's specification, the free running timer shouldn't fire
* interrupt, since the upper layer polls that and handles the overflow,
* by cumulating the read values.
*/
void lp_interval_irq_handler(void)
{
lp_ticker_disable_interrupt();
lp_ticker_irq_handler();
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017 ARM Limited
* Copyright (c) 2018 Arm Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -15,8 +15,10 @@
*/
#include "rtc_api.h"
#include "device.h"
#include "cmsis.h"
#include "platform_devices.h"
#include "rtc_pl031_drv.h"
static uint32_t is_enabled = 0;
/**
* \defgroup hal_rtc RTC hal functions
@ -31,7 +33,9 @@
*/
void rtc_init(void)
{
CMSDK_RTC->RTCCR |= (1 << CMSDK_RTC_ENABLE_Pos);
rtc_pl031_init(&RTC_PL031_DEV);
rtc_pl031_dev_enable(&RTC_PL031_DEV);
is_enabled = 1;
}
/**
@ -41,7 +45,7 @@ void rtc_init(void)
*/
void rtc_free(void)
{
/* Not supported */
is_enabled = 0;
}
/**
@ -51,17 +55,24 @@ void rtc_free(void)
*/
int rtc_isenabled(void)
{
return (CMSDK_RTC->RTCCR & CMSDK_RTC_ENABLE_Msk);
return is_enabled;
}
/**
* \brief Get the current time from the RTC peripheral
*
* Sysclock and RTC clock may not be in sync which can cause reading
* out metastable values. It's usually prevented by adding a loop,
* however PL031 has a syncronisation block to prevent this, therefore
* no additional loop needed.
*
* \return The current time in seconds
*/
time_t rtc_read(void)
{
return (time_t)CMSDK_RTC->RTCDR;
uint32_t val;
rtc_pl031_read_current_time(&RTC_PL031_DEV, &val);
return (time_t)val;
}
/**
@ -72,7 +83,7 @@ time_t rtc_read(void)
void rtc_write(time_t t)
{
CMSDK_RTC->RTCLR = (uint32_t)t;
rtc_pl031_write_current_time(&RTC_PL031_DEV, (uint32_t)t);
}
/**@}*/

View File

@ -0,0 +1,50 @@
/** \addtogroup hal */
/** @{*/
/* mbed Microcontroller Library
* Copyright (c) 2018 Arm Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "platform_devices.h"
#include "sleep_api.h"
#include "timer_cmsdk_drv.h"
#if DEVICE_SLEEP
void hal_sleep(void)
{
__WFI();
}
/* Since there is no power management implemented in CM3DS, Deep Sleep could be
* supported only by additional software components, registering and managing
* the currently configured IPs. This would also mean a huge implementation
* overhead, that is not intended to be added. Therefore, Deep Sleep is almost
* identical to Sleep, representing a "Waiting For Interrupt" state, and
* disabling the Microsec ticker in addition */
void hal_deepsleep(void)
{
#if DEVICE_USTICKER
timer_cmsdk_disable(&USEC_TIMER_DEV);
#endif
__WFI();
#if DEVICE_USTICKER
timer_cmsdk_enable(&USEC_TIMER_DEV);
#endif
}
#endif
/**@}*/

View File

@ -15,124 +15,104 @@
*/
/**
* Elapsed time measure and interval timer in micro-secundum,
* servicing \ref us_ticker_api.h, using CMSDK Timer0 \ref CMSDK_TIMER0_DEV.
* Supports the High-resolution Ticker for mbed by implementing
* \ref us_ticker_api.h, using a CMSDK Timer \ref timer_cmsdk_dev_t.
*/
#include "cmsdk_ticker.h"
#include "us_ticker_api.h"
#include "platform_devices.h"
#include "timer_cmsdk_drv.h"
/*
* The CMSDK Ticker counts on 32 bits.
static uint64_t total_ticks = 0;
/* Stores the last reload value, or the last tick value read when a read API
* call occurs from the upper layer, needed to keep total_ticks
* accumulated properly.
*/
#define CMSDK_TICKER_COUNTER_BITS 32U
static uint32_t previous_ticks = 0;
static uint32_t last_read = 0;
/**
* \brief Pass-through function to make the US ticker HAL only work in the tick
* domain. This function is needed by the CMSDK Ticker layer.
*
* \param[in] tick Number of clock ticks
*
* \return The number of ticks given.
*/
static uint32_t convert_tick_to_us(uint32_t tick)
static void restart_timer(uint32_t new_reload)
{
/* Work only in the tick domain. */
return tick;
timer_cmsdk_disable(&USEC_TIMER_DEV);
timer_cmsdk_set_reload_value(&USEC_TIMER_DEV,
new_reload);
timer_cmsdk_reset(&USEC_TIMER_DEV);
timer_cmsdk_clear_interrupt(&USEC_TIMER_DEV);
timer_cmsdk_enable_interrupt(&USEC_TIMER_DEV);
timer_cmsdk_enable(&USEC_TIMER_DEV);
}
/**
* \brief Pass-through function to make the US ticker HAL only work in the tick
* domain. This function is needed by the CMSDK Ticker layer.
*
* \param[in] us Number of us
*
* \return The number of us given.
*/
static uint32_t convert_us_to_tick(uint32_t us)
{
/* Work only in the tick domain. */
return us;
}
static const struct tick_cfg_t cfg =
{
.timer_driver = &CMSDK_TIMER0_DEV,
.irq_n = TIMER0_IRQn,
.interval_callback = &us_ticker_irq_handler,
.convert_tick_to_time = &convert_tick_to_us,
.convert_time_to_tick = &convert_us_to_tick
};
static struct tick_data_t data =
{
.is_initialized = false,
.cumulated_time = 0,
.max_interval_time = 0,
.reload_time = 0,
.interval_callback_enabled = false,
.previous_cumulated_time = 0,
.previous_elapsed = 0
};
static struct tick_drv_data_t timer_data =
{
.cfg = &cfg,
.data = &data
};
void us_ticker_init(void)
{
cmsdk_ticker_init(&timer_data);
}
uint32_t us_ticker_read()
{
return cmsdk_ticker_read(&timer_data);
}
void us_ticker_set_interrupt(timestamp_t timestamp)
{
cmsdk_ticker_set_interrupt(&timer_data, timestamp);
}
void us_ticker_disable_interrupt(void)
{
cmsdk_ticker_disable_interrupt(&timer_data);
}
void us_ticker_clear_interrupt(void)
{
cmsdk_ticker_clear_interrupt(&timer_data);
}
void us_ticker_fire_interrupt(void)
{
cmsdk_ticker_fire_interrupt(&timer_data);
timer_cmsdk_init(&USEC_TIMER_DEV);
previous_ticks = TIMER_CMSDK_MAX_RELOAD;
NVIC_EnableIRQ(USEC_INTERVAL_IRQ);
restart_timer(previous_ticks);
}
void us_ticker_free(void)
{
timer_cmsdk_disable(&USEC_TIMER_DEV);
}
void TIMER0_IRQHandler(void)
uint32_t us_ticker_read(void)
{
cmsdk_ticker_irq_handler(&timer_data);
if (timer_cmsdk_is_interrupt_active(&USEC_TIMER_DEV)) {
total_ticks += previous_ticks;
previous_ticks = TIMER_CMSDK_MAX_RELOAD;
restart_timer(previous_ticks);
} else {
uint32_t tick = timer_cmsdk_get_current_value(&USEC_TIMER_DEV);
if (tick < previous_ticks) {
uint32_t delta = previous_ticks - tick;
total_ticks += delta;
previous_ticks = tick;
}
}
last_read = (uint32_t)(total_ticks >> USEC_REPORTED_SHIFT);
return last_read;
}
const ticker_info_t* us_ticker_get_info(void)
/* To ensure that timestamp is always bigger than the current time, it should
* be calculated by using the us_ticker_read() method.
*/
void us_ticker_set_interrupt(timestamp_t timestamp)
{
static ticker_info_t us_ticker_info = {
.bits = CMSDK_TICKER_COUNTER_BITS
uint32_t reload = (timestamp - last_read) << USEC_REPORTED_SHIFT;
previous_ticks = reload;
restart_timer(previous_ticks);
}
void us_ticker_disable_interrupt(void)
{
timer_cmsdk_disable_interrupt(&USEC_TIMER_DEV);
}
void us_ticker_clear_interrupt(void)
{
timer_cmsdk_clear_interrupt(&USEC_TIMER_DEV);
}
void us_ticker_fire_interrupt(void)
{
NVIC_SetPendingIRQ(USEC_INTERVAL_IRQ);
}
const ticker_info_t* us_ticker_get_info()
{
static const ticker_info_t info = {
USEC_REPORTED_FREQ_HZ,
USEC_REPORTED_BITS
};
/*
* SystemCoreClock is not a constant so it cannot be used to initialize the
* ticker_info_t structure.
*/
us_ticker_info.frequency = SystemCoreClock;
return &us_ticker_info;
return &info;
}
#ifndef usec_interval_irq_handler
#error "usec_interval_irq_handler should be defined, check device_cfg.h!"vector!
#endif
void usec_interval_irq_handler(void)
{
us_ticker_read();
us_ticker_irq_handler();
}

View File

@ -4648,12 +4648,16 @@
"FLASH",
"I2C",
"INTERRUPTIN",
"LPTICKER",
"PORTIN",
"PORTINOUT",
"PORTOUT",
"RTC",
"SERIAL",
"SLEEP",
"SPI",
"TRNG"
"TRNG",
"USTICKER"
],
"release_versions": ["2", "5"],
"copy_method": "mps2",