/** | |
* \file | |
* | |
* \brief AST driver for SAM. | |
* | |
* Copyright (C) 2012-2013 Atmel Corporation. All rights reserved. | |
* | |
* \asf_license_start | |
* | |
* \page License | |
* | |
* Redistribution and use in source and binary forms, with or without | |
* modification, are permitted provided that the following conditions are met: | |
* | |
* 1. Redistributions of source code must retain the above copyright notice, | |
* this list of conditions and the following disclaimer. | |
* | |
* 2. Redistributions in binary form must reproduce the above copyright notice, | |
* this list of conditions and the following disclaimer in the documentation | |
* and/or other materials provided with the distribution. | |
* | |
* 3. The name of Atmel may not be used to endorse or promote products derived | |
* from this software without specific prior written permission. | |
* | |
* 4. This software may only be redistributed and used in connection with an | |
* Atmel microcontroller product. | |
* | |
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED | |
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | |
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE | |
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR | |
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | |
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN | |
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
* POSSIBILITY OF SUCH DAMAGE. | |
* | |
* \asf_license_stop | |
* | |
*/ | |
#include "ast.h" | |
#include "sysclk.h" | |
#include "sleepmgr.h" | |
#include "conf_ast.h" | |
/** | |
* \internal | |
* \brief AST callback function pointer array | |
*/ | |
ast_callback_t ast_callback_pointer[AST_INTERRUPT_SOURCE_NUM]; | |
/** | |
* \brief Check the status of AST. | |
* | |
* \param ast Base address of the AST. | |
* | |
* \return true If AST is enabled, else it will return false. | |
*/ | |
bool ast_is_enabled(Ast *ast) | |
{ | |
while (ast_is_busy(ast)) { | |
} | |
return ((ast->AST_CR & AST_CR_EN) != 0); | |
} | |
/** | |
* \brief Enable the AST. | |
* | |
* \param ast Base address of the AST. | |
*/ | |
void ast_enable(Ast *ast) | |
{ | |
sysclk_enable_peripheral_clock(ast); | |
sleepmgr_lock_mode(SLEEPMGR_BACKUP); | |
} | |
/** | |
* \brief Disable the AST. It also disables the AST module. | |
* | |
* \param ast Base address of the AST. | |
*/ | |
void ast_disable(Ast *ast) | |
{ | |
/* Wait until the ast CTRL register is up-to-date */ | |
while (ast_is_busy(ast)) { | |
} | |
/* Disable the AST */ | |
ast->AST_CR &= ~(AST_CR_EN); | |
/* Wait until write is done */ | |
while (ast_is_busy(ast)) { | |
} | |
sysclk_disable_peripheral_clock(ast); | |
sleepmgr_unlock_mode(SLEEPMGR_BACKUP); | |
} | |
/** | |
* \brief This function enables the option to clear the counter on AST alarm. | |
* | |
* \param ast Base address of the AST. | |
* \param alarm_channel AST Alarm Channel. | |
*/ | |
void ast_enable_counter_clear_on_alarm(Ast *ast, | |
uint8_t alarm_channel) | |
{ | |
/* Wait until the ast CTRL register is up-to-date */ | |
while (ast_is_busy(ast)) { | |
} | |
/* Enable Clear Counter on Alarm */ | |
ast->AST_CR | |
|= (alarm_channel ? 0 : AST_CR_CA0); | |
/* Wait until write is done */ | |
while (ast_is_busy(ast)) { | |
} | |
} | |
/** | |
* \brief This function clears the AST periodic prescalar counter to zero. | |
* | |
* \param ast Base address of the AST. | |
*/ | |
void ast_clear_prescalar(Ast *ast) | |
{ | |
/* Wait until the ast CTRL register is up-to-date */ | |
while (ast_is_busy(ast)) { | |
} | |
/* Clear Counter on Alarm */ | |
ast->AST_CR |= AST_CR_PCLR; | |
/* Wait until write is done */ | |
while (ast_is_busy(ast)) { | |
} | |
} | |
/** | |
* \brief This function will initialize the AST module in | |
* calendar or counter Mode. It then enables the AST module. | |
* | |
* \note If you use the 32 KHz oscillator, it will enable this module. | |
* | |
* \param ast Base address of the AST. | |
* \param ast_conf The AST configuration | |
* | |
* \return 1 if the initialization succeeds otherwise it will return 0. | |
*/ | |
uint32_t ast_set_config(Ast *ast, struct ast_config *ast_conf) | |
{ | |
uint32_t time_out = AST_POLL_TIMEOUT; | |
while (ast_is_clkbusy(ast)) { | |
if (--time_out == 0) { | |
return 0; | |
} | |
} | |
ast->AST_CLOCK = ast_conf->osc_type << AST_CLOCK_CSSEL_Pos; | |
time_out = AST_POLL_TIMEOUT; | |
while (ast_is_clkbusy(ast)) { | |
if (--time_out == 0) { | |
return 0; | |
} | |
} | |
ast->AST_CLOCK |= AST_CLOCK_CEN; | |
time_out = AST_POLL_TIMEOUT; | |
while (ast_is_clkbusy(ast)) { | |
if (--time_out == 0) { | |
return 0; | |
} | |
} | |
/* Set the new AST configuration */ | |
if (ast_conf->mode == AST_CALENDAR_MODE) { | |
ast->AST_CR = AST_CR_CAL | ast_conf->psel << AST_CR_PSEL_Pos; | |
} | |
if (ast_conf->mode == AST_COUNTER_MODE) { | |
ast->AST_CR = ast_conf->psel << AST_CR_PSEL_Pos; | |
} | |
/* Wait until the ast CTRL register is up-to-date */ | |
while (ast_is_busy(ast)) { | |
} | |
/* Set the calendar */ | |
if (ast_conf->mode == AST_CALENDAR_MODE) { | |
ast_write_calendar_value(ast, ast_conf->calendar); | |
} | |
if (ast_conf->mode == AST_COUNTER_MODE) { | |
ast_write_counter_value(ast, ast_conf->counter); | |
} | |
/* Wait until the ast CTRL register is up-to-date */ | |
while (ast_is_busy(ast)) { | |
} | |
/* Enable the AST */ | |
ast->AST_CR |= AST_CR_EN; | |
/* Wait until write is done */ | |
while (ast_is_busy(ast)) { | |
} | |
return 1; | |
} | |
/** | |
* \brief Function to tune the AST prescalar frequency to the desired frequency | |
* | |
* \param ast Base address of the AST. | |
* \param input_freq Prescaled AST Clock Frequency | |
* \param tuned_freq Desired AST frequency | |
* | |
* \retval 0 If invalid frequency is passed | |
* \retval 1 If configuration succeeds | |
* | |
* \note Parameter Calculation: | |
* Formula: \n | |
* ADD=0 -> ft= fi(1 - (1/((div_ceil(256/value) * (2^exp)) + 1))) \n | |
* ADD=1 -> ft= fi(1 + (1/((div_ceil(256/value) * (2^exp)) - 1))) \n | |
* Specifications: \n | |
* exp > 0, value > 1 \n | |
* Let X = (2 ^ exp), Y = div_ceil(256 / value) \n | |
* Tuned Frequency -> ft \n | |
* Input Frequency -> fi \n | |
* | |
* IF ft < fi \n | |
* ADD = 0 \n | |
* Z = (ft / (fi - ft)) \n | |
* ELSE IF ft > fi \n | |
* ADD = 1 \n | |
* Z = (ft / (ft - fi)) \n | |
* ELSE \n | |
* exit function -> Tuned Frequency = Input Frequency \n | |
* | |
* The equation can be reduced to (X * Y) = Z | |
* | |
* Frequency Limits \n | |
* (1/((div_ceil(256/value) * (2^exp)) + 1)) should be min to get the lowest | |
* possible output from Digital Tuner.\n | |
* (1/((div_ceil(256/value) * (2^exp)) - 1)) should be min to get the highest | |
* possible output from Digital Tuner.\n | |
* For that, div_ceil(256/value) & (2^exp) should be minimum \n | |
* min (EXP) = 1 (Note: EXP > 0) \n | |
* min (div_ceil(256/value)) = 2 \n | |
* max (Ft) = (4*fi)/3 \n | |
* min (Ft) = (4*fi)/5 \n | |
* | |
* Using the above details, X & Y that will closely satisfy the equation is | |
* found in this function. | |
*/ | |
uint32_t ast_configure_digital_tuner(Ast *ast, | |
uint32_t input_freq, uint32_t tuned_freq) | |
{ | |
bool add; | |
uint8_t value; | |
uint8_t exp; | |
uint32_t x, y, z; | |
uint32_t diff; | |
if (tuned_freq < input_freq) { | |
/* Check for Frequency Limit */ | |
if (tuned_freq < ((4 * input_freq) / 5)) { | |
return 0; | |
} | |
/* Set the ADD to 0 when freq less than input freq */ | |
add = false; | |
/* Calculate the frequency difference */ | |
diff = input_freq - tuned_freq; | |
} else if (tuned_freq > input_freq) { | |
/* Check for Frequency Limit */ | |
if (tuned_freq > ((4 * input_freq) / 3)) { | |
return 0; | |
} | |
/* Set the ADD to 1 when freq greater than input freq */ | |
add = true; | |
/* Calculate the frequency difference */ | |
diff = tuned_freq - input_freq; | |
} else { | |
/* required & input freq are equal */ | |
return 1; | |
} | |
z = (tuned_freq) / (diff); | |
if ((tuned_freq % diff) > (diff / 2)) { | |
z++; | |
} | |
/* | |
* Initialize with minimum possible values. | |
* exp value should be greater than zero, min(exp) = 1 -> min(x)= (2^1) | |
* = 2 | |
* y should be greater than one -> div_ceil(256/value) where value- 0 to | |
* 255 | |
* min(y) = div_ceil(256/255) = 2 | |
*/ | |
y = 2; | |
x = 2; | |
exp = 1; | |
/* | |
* Keep exp constant and increase y value until it reaches its limit. | |
* Increment exp and follow the same steps until we found the closest | |
* possible match for the required frequency. | |
*/ | |
do { | |
if (y < 255) { | |
y++; | |
} else { | |
x = x << 1; | |
y = 2; | |
exp++; | |
} | |
} while (z > (x * y)); | |
/* Decrement y value after exit from loop */ | |
y = y - 1; | |
/* Find VALUE from y */ | |
value = div_ceil(256, y); | |
/* Initialize the Digital Tuner using the required parameters */ | |
ast_init_digital_tuner(ast, add, value, exp); | |
return 1; | |
} | |
/** | |
* \brief This function will initialize the digital tuner of AST module. | |
* | |
* \param ast Base address of the AST. | |
* \param add set to true if frequency has to be increased, false if it | |
* has to be decreased. | |
* \param value Parameter used in the formula | |
* \param exp Parameter used in the formula | |
* | |
* \return 1 if the initialization succeeds otherwise it will return 0. | |
*/ | |
void ast_init_digital_tuner(Ast *ast, bool add, | |
uint8_t value, uint8_t exp) | |
{ | |
/* Wait until the ast CTRL register is up-to-date */ | |
while (ast_is_busy(ast)) { | |
} | |
if (add) { | |
ast->AST_DTR = AST_DTR_ADD | AST_DTR_VALUE(value) | AST_DTR_EXP( | |
exp); | |
} else { | |
ast->AST_DTR = AST_DTR_VALUE(value) | AST_DTR_EXP(exp); | |
} | |
/* Wait until the ast CTRL register is up-to-date */ | |
while (ast_is_busy(ast)) { | |
} | |
} | |
/** | |
* \brief This function will disable the digital tuner of AST module. | |
* | |
* \param ast Base address of the AST. | |
*/ | |
void ast_disable_digital_tuner(Ast *ast) | |
{ | |
/* Wait until the ast CTRL register is up-to-date */ | |
while (ast_is_busy(ast)) { | |
} | |
ast->AST_DTR &= ~(AST_DTR_VALUE_Msk); | |
/* Wait until the ast CTRL register is up-to-date */ | |
while (ast_is_busy(ast)) { | |
} | |
} | |
/** | |
* \brief This function sets the AST current calendar value. | |
* | |
* \param ast Base address of the AST. | |
* \param ast_calendar Startup date | |
*/ | |
void ast_write_calendar_value(Ast *ast, | |
struct ast_calendar calendar) | |
{ | |
/* Wait until we can write into the VAL register */ | |
while (ast_is_busy(ast)) { | |
} | |
/* Set the new val value */ | |
ast->AST_CALV = calendar.field; | |
/* Wait until write is done */ | |
while (ast_is_busy(ast)) { | |
} | |
} | |
/** | |
* \brief This function sets the AST current counter value. | |
* | |
* \param ast Base address of the AST. | |
* \param ast_counter Startup counter value | |
*/ | |
void ast_write_counter_value(Ast *ast, | |
uint32_t ast_counter) | |
{ | |
/* Wait until we can write into the VAL register */ | |
while (ast_is_busy(ast)) { | |
} | |
/* Set the new val value */ | |
ast->AST_CV = ast_counter; | |
/* Wait until write is done */ | |
while (ast_is_busy(ast)) { | |
} | |
} | |
/** | |
* \brief This function returns the AST current calendar value. | |
* | |
* \param ast Base address of the AST. | |
* | |
* \return The AST current calendar value. | |
*/ | |
struct ast_calendar ast_read_calendar_value(Ast *ast) | |
{ | |
struct ast_calendar calendar; | |
calendar.field = ast->AST_CALV; | |
return calendar; | |
} | |
/** | |
* \brief This function set the AST alarm0 value. | |
* | |
* \param ast Base address of the AST. | |
* \param alarm_value AST alarm0 value. | |
*/ | |
void ast_write_alarm0_value(Ast *ast, uint32_t alarm_value) | |
{ | |
/* Wait until the ast CTRL register is up-to-date */ | |
while (ast_is_busy(ast)) { | |
} | |
/* Set the new alarm0 compare value */ | |
ast->AST_AR0 = alarm_value; | |
/* Wait until write is done */ | |
while (ast_is_busy(ast)) { | |
} | |
} | |
/** | |
* \brief This function set the AST periodic0 value. | |
* | |
* \param ast Base address of the AST. | |
* \param pir AST periodic0. | |
*/ | |
void ast_write_periodic0_value(Ast *ast, uint32_t pir) | |
{ | |
/* Wait until the ast CTRL register is up-to-date */ | |
while (ast_is_busy(ast)) { | |
} | |
/* Set the periodic prescaler value */ | |
ast->AST_PIR0 = pir; | |
/* Wait until write is done */ | |
while (ast_is_busy(ast)) { | |
} | |
} | |
/** | |
* \brief This function enables the AST interrupts | |
* | |
* \param ast Base address of the AST. | |
* \param source AST Interrupts to be enabled | |
*/ | |
void ast_enable_interrupt(Ast *ast, ast_interrupt_source_t source) | |
{ | |
/* Wait until the ast CTRL register is up-to-date */ | |
while (ast_is_busy(ast)) { | |
} | |
switch (source) { | |
case AST_INTERRUPT_ALARM: | |
ast->AST_IER = AST_IER_ALARM0_1; | |
break; | |
case AST_INTERRUPT_PER: | |
ast->AST_IER = AST_IER_PER0_1; | |
break; | |
case AST_INTERRUPT_OVF: | |
ast->AST_IER = AST_IER_OVF_1; | |
break; | |
case AST_INTERRUPT_READY: | |
ast->AST_IER = AST_IER_READY_1; | |
break; | |
case AST_INTERRUPT_CLKREADY: | |
ast->AST_IER = AST_IER_CLKRDY_1; | |
break; | |
default: | |
break; | |
} | |
/* Wait until write is done */ | |
while (ast_is_busy(ast)) { | |
} | |
} | |
/** | |
* \brief This function disables the AST interrupts. | |
* | |
* \param ast Base address of the AST. | |
* \param source AST Interrupts to be disabled | |
*/ | |
void ast_disable_interrupt(Ast *ast, ast_interrupt_source_t source) | |
{ | |
/* Wait until the ast CTRL register is up-to-date */ | |
while (ast_is_busy(ast)) { | |
} | |
switch (source) { | |
case AST_INTERRUPT_ALARM: | |
ast->AST_IDR = AST_IDR_ALARM0_1; | |
break; | |
case AST_INTERRUPT_PER: | |
ast->AST_IDR = AST_IDR_PER0_1; | |
break; | |
case AST_INTERRUPT_OVF: | |
ast->AST_IDR = AST_IDR_OVF_1; | |
break; | |
case AST_INTERRUPT_READY: | |
ast->AST_IDR = AST_IDR_READY_1; | |
break; | |
case AST_INTERRUPT_CLKREADY: | |
ast->AST_IDR = AST_IDR_CLKRDY_1; | |
break; | |
default: | |
break; | |
} | |
/* Wait until write is done */ | |
while (ast_is_busy(ast)) { | |
} | |
} | |
/** | |
* \brief This function clears the AST status flags. | |
* | |
* \param ast Base address of the AST. | |
* \param source AST status flag to be cleared | |
*/ | |
void ast_clear_interrupt_flag(Ast *ast, ast_interrupt_source_t source) | |
{ | |
/* Wait until the ast CTRL register is up-to-date */ | |
while (ast_is_busy(ast)) { | |
} | |
switch (source) { | |
case AST_INTERRUPT_ALARM: | |
ast->AST_SCR = AST_SCR_ALARM0; | |
break; | |
case AST_INTERRUPT_PER: | |
ast->AST_SCR = AST_SCR_PER0; | |
break; | |
case AST_INTERRUPT_OVF: | |
ast->AST_SCR = AST_SCR_OVF; | |
break; | |
case AST_INTERRUPT_READY: | |
ast->AST_SCR = AST_SCR_READY; | |
break; | |
case AST_INTERRUPT_CLKREADY: | |
ast->AST_SCR = AST_SCR_CLKRDY; | |
break; | |
default: | |
break; | |
} | |
/* Wait until write is done */ | |
while (ast_is_busy(ast)) { | |
} | |
} | |
/** | |
* \brief Set callback for AST | |
* | |
* \param ast Base address of the AST. | |
* \param source AST interrupt source. | |
* \param callback callback function pointer. | |
* \param irq_line interrupt line. | |
* \param irq_level interrupt level. | |
*/ | |
void ast_set_callback(Ast *ast, ast_interrupt_source_t source, | |
ast_callback_t callback, uint8_t irq_line, uint8_t irq_level) | |
{ | |
ast_callback_pointer[source] = callback; | |
NVIC_ClearPendingIRQ((IRQn_Type)irq_line); | |
NVIC_SetPriority((IRQn_Type)irq_line, irq_level); | |
NVIC_EnableIRQ((IRQn_Type)irq_line); | |
ast_enable_interrupt(ast, source); | |
} | |
/** | |
* \brief Interrupt handler for AST. | |
*/ | |
void ast_interrupt_handler(void) | |
{ | |
uint32_t status, mask; | |
status = ast_read_status(AST); | |
mask = ast_read_interrupt_mask(AST); | |
if ((status & AST_SR_ALARM0) && (mask & AST_IMR_ALARM0)) { | |
ast_callback_pointer[AST_INTERRUPT_ALARM](); | |
} | |
if ((status & AST_SR_PER0) && (mask & AST_IMR_PER0)) { | |
ast_callback_pointer[AST_INTERRUPT_PER](); | |
} | |
if ((status & AST_SR_OVF) && (mask & AST_IMR_OVF_1)) { | |
ast_callback_pointer[AST_INTERRUPT_OVF](); | |
} | |
if ((status & AST_SR_READY) && (mask & AST_IMR_READY_1)) { | |
ast_callback_pointer[AST_INTERRUPT_READY](); | |
} | |
if ((status & AST_SR_CLKRDY) && (mask & AST_IMR_CLKRDY_1)) { | |
ast_callback_pointer[AST_INTERRUPT_CLKREADY](); | |
} | |
} | |
/** | |
* \brief Interrupt handler for AST periodic. | |
*/ | |
#ifdef AST_PER_ENABLE | |
void AST_PER_Handler(void) | |
{ | |
ast_interrupt_handler(); | |
} | |
#endif | |
/** | |
* \brief Interrupt handler for AST alarm. | |
*/ | |
#ifdef AST_ALARM_ENABLE | |
void AST_ALARM_Handler(void) | |
{ | |
ast_interrupt_handler(); | |
} | |
#endif | |
/** | |
* \brief Interrupt handler for AST periodic. | |
*/ | |
#ifdef AST_OVF_ENABLE | |
void AST_OVF_Handler(void) | |
{ | |
ast_interrupt_handler(); | |
} | |
#endif | |
/** | |
* \brief Interrupt handler for AST alarm. | |
*/ | |
#ifdef AST_READY_ENABLE | |
void AST_READY_Handler(void) | |
{ | |
ast_interrupt_handler(); | |
} | |
#endif | |
/** | |
* \brief Interrupt handler for AST periodic. | |
*/ | |
#ifdef AST_CLKREADY_ENABLE | |
void AST_CLKREADY_Handler(void) | |
{ | |
ast_interrupt_handler(); | |
} | |
#endif | |
/** | |
* \brief This function enables the AST Asynchronous wake-up. | |
* | |
* \param ast Base address of the AST. | |
* \param source AST wake-up flag to be enabled. | |
*/ | |
void ast_enable_wakeup(Ast *ast, ast_wakeup_source_t source) | |
{ | |
/* Wait until the ast CTRL register is up-to-date */ | |
while (ast_is_busy(ast)) { | |
} | |
switch (source) { | |
case AST_WAKEUP_ALARM: | |
ast->AST_WER |= AST_WER_ALARM0_1; | |
break; | |
case AST_WAKEUP_PER: | |
ast->AST_WER |= AST_WER_PER0_1; | |
break; | |
case AST_WAKEUP_OVF: | |
ast->AST_WER |= AST_WER_OVF_1; | |
break; | |
default: | |
break; | |
} | |
/* Wait until write is done */ | |
while (ast_is_busy(ast)) { | |
} | |
} | |
/** | |
* \brief This function disables the AST Asynchronous wake-up. | |
* 8 | |
* \param ast Base address of the AST. | |
* \param source AST wake-up flag to be disabled. | |
*/ | |
void ast_disable_wakeup(Ast *ast, ast_wakeup_source_t source) | |
{ | |
/* Wait until the ast CTRL register is up-to-date */ | |
while (ast_is_busy(ast)) { | |
} | |
switch (source) { | |
case AST_WAKEUP_ALARM: | |
ast->AST_WER &= ~AST_WER_ALARM0_1; | |
break; | |
case AST_WAKEUP_PER: | |
ast->AST_WER &= ~AST_WER_PER0_1; | |
break; | |
case AST_WAKEUP_OVF: | |
ast->AST_WER &= ~AST_WER_OVF_1; | |
break; | |
default: | |
break; | |
} | |
/* Wait until write is done */ | |
while (ast_is_busy(ast)) { | |
} | |
} | |
/** | |
* \brief This function enables the AST event. | |
* | |
* \param ast Base address of the AST. | |
* \param source AST event flag to be enabled. | |
*/ | |
void ast_enable_event(Ast *ast, ast_event_source_t source) | |
{ | |
/* Wait until the ast CTRL register is up-to-date */ | |
while (ast_is_busy(ast)) { | |
} | |
switch (source) { | |
case AST_EVENT_ALARM: | |
ast->AST_EVE = AST_EVE_ALARM0; | |
break; | |
case AST_EVENT_PER: | |
ast->AST_EVE = AST_EVE_PER0; | |
break; | |
case AST_EVENT_OVF: | |
ast->AST_EVE = AST_EVE_OVF; | |
break; | |
default: | |
break; | |
} | |
/* Wait until write is done */ | |
while (ast_is_busy(ast)) { | |
} | |
} | |
/** | |
* \brief This function disables the AST event. | |
* | |
* \param ast Base address of the AST. | |
* \param source AST event flag to be disabled. | |
*/ | |
void ast_disable_event(Ast *ast, ast_event_source_t source) | |
{ | |
/* Wait until the ast CTRL register is up-to-date */ | |
while (ast_is_busy(ast)) { | |
} | |
switch (source) { | |
case AST_EVENT_ALARM: | |
ast->AST_EVD = AST_EVD_ALARM0; | |
break; | |
case AST_EVENT_PER: | |
ast->AST_EVD = AST_EVD_PER0; | |
break; | |
case AST_EVENT_OVF: | |
ast->AST_EVD = AST_EVD_OVF; | |
break; | |
default: | |
break; | |
} | |
/* Wait until write is done */ | |
while (ast_is_busy(ast)) { | |
} | |
} |