mbed library sources
Fork of mbed-src by
Diff: targets/hal/TARGET_Atmel/TARGET_SAM21/us_ticker.c
- Revision:
- 579:53297373a894
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/targets/hal/TARGET_Atmel/TARGET_SAM21/us_ticker.c Wed Jul 01 09:45:11 2015 +0100 @@ -0,0 +1,165 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include <stddef.h> +#include "us_ticker_api.h" +#include "cmsis.h" +#include "mbed_assert.h" +#include "ins_gclk.h" +#include "compiler.h" +#include "system.h" +#include "tc.h" +#include "tc_interrupt.h" + +#define TICKER_COUNTER_uS TC4 +#define TICKER_COUNTER_IRQn TC4_IRQn +#define TICKER_COUNTER_Handlr TC4_Handler + +static int us_ticker_inited = 0; +extern uint8_t g_sys_init; + +struct tc_module us_ticker_module; + + +static inline void tc_clear_interrupt( + struct tc_module *const module, + const enum tc_callback callback_type) +{ + /* Sanity check arguments */ + MBED_ASSERT(module); + + /* Clear interrupt flags */ + if (callback_type == TC_CALLBACK_CC_CHANNEL0) { + module->hw->COUNT8.INTENCLR.reg = TC_INTFLAG_MC(1); + } else if (callback_type == TC_CALLBACK_CC_CHANNEL1) { + module->hw->COUNT8.INTENCLR.reg = TC_INTFLAG_MC(2); + } else { + module->hw->COUNT8.INTENCLR.reg = (1 << callback_type); + } +} + +void us_ticker_irq_handler_internal(struct tc_module* us_tc_module) +{ + uint32_t status_flags; + + /* Clear TC capture overflow and TC count overflow */ + status_flags = TC_STATUS_CAPTURE_OVERFLOW | TC_STATUS_COUNT_OVERFLOW; + tc_clear_status(&us_ticker_module, status_flags); + + us_ticker_irq_handler(); +} + +void us_ticker_init(void) +{ + uint32_t cycles_per_us; + uint32_t prescaler = 0; + struct tc_config config_tc; + enum status_code ret_status; + + if (us_ticker_inited) return; + us_ticker_inited = 1; + + if (g_sys_init == 0) { + system_init(); + g_sys_init = 1; + } + + tc_get_config_defaults(&config_tc); + + cycles_per_us = system_gclk_gen_get_hz(config_tc.clock_source) / 1000000; + MBED_ASSERT(cycles_per_us > 0); + /*while((cycles_per_us & 1) == 0 && prescaler <= 10) { + cycles_per_us = cycles_per_us >> 1; + prescaler++; + }*/ + while((cycles_per_us > 1) && (prescaler <= 10)) { + cycles_per_us = cycles_per_us >> 1; + prescaler++; + } + if (prescaler >= 9) { + prescaler = 7; + } else if (prescaler >= 7) { + prescaler = 6; + } else if (prescaler >= 5) { + prescaler = 5; + } + + config_tc.clock_prescaler = TC_CTRLA_PRESCALER(prescaler); + config_tc.counter_size = TC_COUNTER_SIZE_32BIT; + config_tc.run_in_standby = true; + config_tc.counter_32_bit.value = 0; + config_tc.counter_32_bit.compare_capture_channel[TC_COMPARE_CAPTURE_CHANNEL_0] = 0xFFFFFFFF; + + /* Initialize the timer */ + ret_status = tc_init(&us_ticker_module, TICKER_COUNTER_uS, &config_tc); + MBED_ASSERT(ret_status == STATUS_OK); + + /* Register callback function */ + tc_register_callback(&us_ticker_module, (tc_callback_t)us_ticker_irq_handler_internal, TC_CALLBACK_CC_CHANNEL0); + + /* Enable the timer module */ + tc_enable(&us_ticker_module); +} + +uint32_t us_ticker_read() +{ + if (!us_ticker_inited) + us_ticker_init(); + + return tc_get_count_value(&us_ticker_module); +} + +void us_ticker_set_interrupt(timestamp_t timestamp) +{ + uint32_t cur_time; + int32_t delta; + + cur_time = us_ticker_read(); + delta = (int32_t)((uint32_t)timestamp - cur_time); + if (delta < 0) { + /* Event already occurred in past */ + us_ticker_irq_handler(); + return; + } + + NVIC_DisableIRQ(TICKER_COUNTER_IRQn); + NVIC_SetVector(TICKER_COUNTER_IRQn, (uint32_t)TICKER_COUNTER_Handlr); + + /* Enable the callback */ + tc_enable_callback(&us_ticker_module, TC_CALLBACK_CC_CHANNEL0); + tc_set_compare_value(&us_ticker_module, TC_COMPARE_CAPTURE_CHANNEL_0, (uint32_t)timestamp); + + NVIC_EnableIRQ(TICKER_COUNTER_IRQn); +} + +void us_ticker_disable_interrupt(void) +{ + /* Disable the callback */ + tc_disable_callback(&us_ticker_module, TC_CALLBACK_CC_CHANNEL0); + NVIC_DisableIRQ(TICKER_COUNTER_IRQn); +} + +void us_ticker_clear_interrupt(void) +{ + uint32_t status_flags; + + /* Clear TC channel 0 match */ + status_flags = TC_STATUS_CHANNEL_0_MATCH; + tc_clear_status(&us_ticker_module, status_flags); + + /* Clear the interrupt */ + tc_clear_interrupt(&us_ticker_module, TC_CALLBACK_CC_CHANNEL0); + NVIC_ClearPendingIRQ(TICKER_COUNTER_IRQn); +} \ No newline at end of file