blob: 19f77ac287ce25101ff70bd7311def6318d312b1 [file] [log] [blame]
/*****************************************************************************
* © 2014 Microchip Technology Inc. and its subsidiaries.
* You may use this software and any derivatives exclusively with
* Microchip products.
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS".
* NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
* INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
* AND FITNESS FOR A PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP
* PRODUCTS, COMBINATION WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION.
* IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE,
* INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND
* WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS
* BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE.
* TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL
* CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF
* FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
* MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE
* OF THESE TERMS.
*****************************************************************************/
/** @file mec14xx_timers.c
*MEC14xx Timers
*/
/** @defgroup MEC14xx Peripherals Timers
* @{
*/
#include "appcfg.h"
#include "platform.h"
#include "MEC14xx/mec14xx.h"
#include "MEC14xx/mec14xx_pcr.h"
#include "MEC14xx/mec14xx_timers.h"
// pairs of bytes (sleep reg, bit position)
// sleep reg = 0 for EC_SLEEP_EN or 1 for EC_SLEEP_EN2
//
struct btmr_sleep_info_s {
uint8_t slp_reg;
uint8_t bit_pos;
};
static const struct btmr_sleep_info_s btmr_slp_info[BTMR_MAX_INSTANCE] = {
{ 0, PCR_EC_TIMER0_SLP_BITPOS },
{ 0, PCR_EC_TIMER1_SLP_BITPOS },
{ 1, PCR_EC2_TIMER2_SLP_BITPOS },
{ 1, PCR_EC2_TIMER3_SLP_BITPOS }
};
#ifdef MEC14XX_BTIMER_CHECK_ID
/**
* tmr_valid - Local helper that checks if logical Timer ID is
* valid.
*
* @author sworley
*
* @param tmr_id 0-based Timer ID
*
* @return uint8_t Non-zero(VALID), 0(Invalid)
*/
static uint8_t btmr_valid(uint8_t tmr_id)
{
if ( tmr_id < (BTMR_ID_MAX ) ) {
return true;
}
return false;
}
#else
/**
* @brief - This version of tmr_valid skips checking always
* returning TRUE. Compiler may optimize it out.
*
*/
static uint8_t btmr_valid(uint8_t tmr_id)
{
(void) tmr_id;
return true;
}
#endif
uint32_t btmr_get_hw_addr(uint8_t btmr_id)
{
return (uint32_t)(BTMR0_BASE) +
((uint32_t)(btmr_id) << (BTMR_INSTANCE_BITPOS));
}
/**
* btmr_sleep_en - Enable/Disable clock gating on idle of a
* timer
*
* @author sworley (8/16/2013)
*
* @param tmr_id zero based timer ID.
* @param pwr_on boolean true=ON, false=OFF
*/
void btmr_sleep_en(uint8_t tmr_id, uint8_t sleep_en)
{
uint32_t sleep_mask;
uint32_t volatile * p;
sleep_mask = 0ul;
if ( btmr_valid(tmr_id) ) {
if (btmr_slp_info[tmr_id].slp_reg) {
p = (uint32_t volatile *)&(PCR->EC_SLEEP_EN2);
} else {
p = (uint32_t volatile *)&(PCR->EC_SLEEP_EN);
}
sleep_mask = (1ul << btmr_slp_info[tmr_id].bit_pos);
if (sleep_en) {
*p |= (sleep_mask);
} else {
*p &= ~(sleep_mask);
}
}
}
/**
* btmr_reset - Peform soft reset of specified timer.
*
* @author sworley
*
* @param tmr_id 0-based Timer ID
* @note Soft reset set all registers to POR values.
* Spins 256 times waiting on hardware to clear reset bit.
*/
void btmr_reset(uint8_t tmr_id)
{
BTMR_TypeDef * p;
uint32_t wait_cnt;
if (btmr_valid(tmr_id)) {
p = (BTMR_TypeDef *)btmr_get_hw_addr(tmr_id);
p->CONTROL = (BTMR_CNTL_SOFT_RESET);
wait_cnt = 256ul;
do {
if ( 0ul == (p->CONTROL & BTMR_CNTL_SOFT_RESET) ) {
break;
}
}
while ( wait_cnt-- );
}
}
/**
* btmr_init - Initialize specified timer
* @param zero based timer ID
* @param tmr_cntl b[15:0] = timer configuration flags.
* @param initial_count
* @param preload_count
* @note performs a soft reset of the timer before
* configuration.
*/
void btmr_init(uint8_t tmr_id,
uint16_t tmr_cntl,
uint16_t prescaler,
uint32_t initial_count,
uint32_t preload_count)
{
BTMR_TypeDef * pTMR;
pTMR = NULL;
if (btmr_valid(tmr_id)) {
btmr_reset(tmr_id);
pTMR = (BTMR_TypeDef *)btmr_get_hw_addr(tmr_id);
// Ungate timer clocks and program prescale
pTMR->CONTROL = ((uint32_t)prescaler << 16) + (BTMR_CNTL_ENABLE);
// Program Preload & initial counter value
pTMR->PRELOAD = preload_count;
pTMR->COUNT = initial_count;
// Program control register, interrupt enable, and clear status
if (tmr_cntl & BTMR_COUNT_UP) {
pTMR->CONTROL |= BTMR_CNTL_COUNT_UP;
}
if (tmr_cntl & BTMR_AUTO_RESTART) {
pTMR->CONTROL |= BTMR_CNTL_AUTO_RESTART;
}
if (tmr_cntl & BTMR_INT_EN) {
pTMR->INTEN = 0x01u; // enable first
pTMR->STATUS = 0x01u; // clear status
}
}
}
/**
* btmr_ien - Enable specified timer's interrupt.
*
* @author sworley
*
* @param tmr_id zero based timer ID.
* @param ien Non-zero enable interrupt in timer block, 0
* disable.
* @note Write 0 or 1 to timer's INTEN register.
*/
void btmr_ien(uint8_t tmr_id, uint8_t ien)
{
BTMR_TypeDef * p;
if (btmr_valid(tmr_id)) {
p = (BTMR_TypeDef *)btmr_get_hw_addr(tmr_id);
if (ien) {
p->INTEN = (BTMR_INTEN);
} else {
p->INTEN = (BTMR_INTDIS);
}
}
}
/**
* tmr_get_clr_ists - Read Timer interrupt status and clear if
* set.
*
* @author sworley
*
* @param tmr_id zero based timer ID.
*
* @return uint8_t true (Timer interrupt status set) else false.
* @note If timer interrupt status is set then clear it before
* returning.
*/
uint8_t btmr_get_clr_ists(uint8_t tmr_id)
{
BTMR_TypeDef * p;
uint8_t rc;
rc = (MEC14XX_FALSE);
if (btmr_valid(tmr_id)) {
p = (BTMR_TypeDef *)btmr_get_hw_addr(tmr_id);
if ( p->STATUS ) {
p->STATUS = (BTMR_STATUS_ACTIVE);
rc = true;
}
}
return rc;
}
/**
* btmr_reload - Force timer to reload counter from preload
* register.
*
* @param tmr_id zero based timer ID.
* @note Hardware will only reload counter if timer is running.
*/
void btmr_reload(uint8_t tmr_id)
{
BTMR_TypeDef * p;
if ( btmr_valid(tmr_id) ) {
p = (BTMR_TypeDef *)btmr_get_hw_addr(tmr_id);
if (p->CONTROL & BTMR_CNTL_START) {
p->CONTROL |= BTMR_CNTL_RELOAD;
}
}
}
/**
* btmr_set_count - Program timer's counter register.
*
* @author sworley
*
* @param tmr_id zero based timer ID
* @param count new counter value
* @note Timer hardware may implement a 16-bit or 32-bit
* hardware counter. If the timer is 16-bit only the lower
* 16-bits of the count paramter are used.
*/
void btmr_set_count(uint8_t tmr_id, uint32_t count)
{
BTMR_TypeDef * p;
if (btmr_valid(tmr_id)) {
p = (BTMR_TypeDef *)btmr_get_hw_addr(tmr_id);
p->COUNT = count;
}
}
/**
* btmr_count - Return current value of timer's count register.
*
* @author sworley
*
* @param tmr_id zero based timer ID.
*
* @return uint32_t timer count may be 32 or 16 bits depending
* upon the hardware. On MEC1322 Timers 0-3 are 16-bit
* and Timers 4-5 are 32-bit.
*/
uint32_t btmr_count(uint8_t tmr_id)
{
BTMR_TypeDef * p;
uint32_t cnt;
cnt = 0ul;
if ( btmr_valid(tmr_id) ) {
p = (BTMR_TypeDef *)btmr_get_hw_addr(tmr_id);
cnt = (uint32_t)(p->COUNT);
}
return cnt;
}
/**
* btmr_start - Start timer counting.
*
* @author sworley
*
* @param tmr_id zero based timer ID.
*/
void btmr_start(uint8_t btmr_id)
{
BTMR_TypeDef * p;
if ( btmr_valid(btmr_id) ) {
p = (BTMR_TypeDef *)btmr_get_hw_addr(btmr_id);
p->CONTROL |= BTMR_CNTL_START;
}
}
/**
* btmr_stop - Stop timer.
*
* @author sworley
*
* @param tmr_id zero based timer ID.
* @note When a stopped timer is started again it will reload
* the count register from preload value.
*/
void btmr_stop(uint8_t tmr_id)
{
BTMR_TypeDef * p;
if (btmr_valid(tmr_id)) {
p = (BTMR_TypeDef *)btmr_get_hw_addr(tmr_id);
p->CONTROL &= ~(BTMR_CNTL_START);
}
}
/**
* btmr_is_stopped - Return state of timer's START bit.
*
* @author sworley
*
* @param tmr_id zero based timer ID.
*
* @return uint8_t false(timer not started), true(timer started)
*/
uint8_t btmr_is_stopped(uint8_t tmr_id)
{
BTMR_TypeDef * p;
uint8_t rc;
rc = (MEC14XX_TRUE);
if (btmr_valid(tmr_id)) {
rc = (MEC14XX_FALSE);
p = (BTMR_TypeDef *)btmr_get_hw_addr(tmr_id);
if ((p->CONTROL & BTMR_CNTL_START) == 0) {
rc = (MEC14XX_TRUE);
}
}
return rc;
}
/**
* btmr_halt - Halt timer counting with no reload on unhalt.
*
* @author sworley
*
* @param tmr_id zero based timer ID.
* @note A halted timer will not reload the count register when
* unhalted, it will continue counting from the current
* count value.
*/
void btmr_halt(uint8_t tmr_id)
{
BTMR_TypeDef * p;
if ( btmr_valid(tmr_id) ) {
p = (BTMR_TypeDef *)btmr_get_hw_addr(tmr_id);
p->CONTROL |= (BTMR_CNTL_HALT);
}
}
/**
* btmr_unhalt - Unhalt timer counting.
*
* @author sworley
*
* @param tmr_id zero based timer ID.
*/
void btmr_unhalt(uint8_t tmr_id)
{
BTMR_TypeDef * p;
if ( btmr_valid(tmr_id) ) {
p = (BTMR_TypeDef *)btmr_get_hw_addr(tmr_id);
p->CONTROL &= ~(BTMR_CNTL_HALT);
}
}
/* end mec14xx_timers.c */
/** @}
*/