Implement LP and us tickers to CM3DS

This commit represents the first stage of the low power implementations
that are required from Mbed 5.10 onwards. The LP ticker has been
implemented using a CMSDK Dual Timer's both timers (HW prescaler needed
to operate in the specified frequency domain), whereas the us ticker
uses one CMSDK Timer. Besides the default hal implementations (lp_ticker.c
and us_ticker.c), the CMSDK Dual Timer's native driver needed to be added.

Change-Id: I0b16b93dfac7753bebf430a2ce77761cb9c43ee5
Signed-off-by: Bence Kaposzta <bence.kaposzta@arm.com>
pull/8737/head
Bence Kaposzta 2018-09-05 15:16:43 +02:00
parent aab3ade2b7
commit 1b792317e4
8 changed files with 1712 additions and 198 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,50 @@
*/
/* 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)
/* ARM GPIO */
#define ARM_GPIO0
@ -51,7 +93,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

@ -37,6 +37,16 @@ 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
/* ARM GPIO driver structures */
#ifdef ARM_GPIO0
static const struct arm_gpio_dev_cfg_t ARM_GPIO0_DEV_CFG = {

View File

@ -20,84 +20,101 @@
/* ======= 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
/* 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

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

@ -2934,7 +2934,7 @@
"extra_labels": ["ARM_SSG", "CM3DS_MPS2"],
"OUTPUT_EXT": "elf",
"macros": ["CMSDK_CM3DS"],
"device_has": ["ANALOGIN", "EMAC", "FLASH", "I2C", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "SERIAL", "SPI", "TRNG"],
"device_has": ["ANALOGIN", "EMAC", "FLASH", "I2C", "INTERRUPTIN", "LPTICKER", "PORTIN", "PORTINOUT", "PORTOUT", "SERIAL", "SPI", "TRNG", "USTICKER"],
"release_versions": ["2", "5"],
"copy_method": "mps2",
"reset_method": "reboot.txt",