Kernel changes:
+ Made xTaskNotifyGiveFromISR() its own function, rather than a macro that calls xTaskNotifyFromISR() (minor performance improvement). + GCC and Keil Cortex-M4F ports now use vPortRaiseBASEPRI() in place of ulPortRaiseBASEPRI() where the return value is not required (minor performance improvement). Demo changes: Change the [very basic] FreeRTOS+UDP SAM4E driver to use task notifications rather than a semaphore (execution time now 55% what it was in FreeRTOS V8.1.2!). Robustness improvements to IntQueue.c standard demo task.h. Added the latest standard demo tasks, reg test tasks and int q tasks to the SAM4E demo.pull/1/head
parent
2de32c0141
commit
fd02010886
Binary file not shown.
@ -0,0 +1,596 @@
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* \brief Timer Counter (TC) driver for SAM.
|
||||
*
|
||||
* Copyright (c) 2011-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 <assert.h>
|
||||
#include "tc.h"
|
||||
|
||||
/// @cond 0
|
||||
/**INDENT-OFF**/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/**INDENT-ON**/
|
||||
/// @endcond
|
||||
|
||||
#define TC_WPMR_WPKEY_VALUE TC_WPMR_WPKEY((uint32_t)0x54494D)
|
||||
|
||||
/**
|
||||
* \defgroup sam_drivers_tc_group Timer Counter (TC)
|
||||
*
|
||||
* The Timer Counter (TC) includes three identical 32-bit Timer Counter
|
||||
* channels. Each channel can be independently programmed to perform a wide
|
||||
* range of functions including frequency measurement, event counting,
|
||||
* interval measurement, pulse generation, delay timing and pulse width
|
||||
* modulation.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief Configure TC for timer, waveform generation or capture.
|
||||
*
|
||||
* \param p_tc Pointer to a TC instance.
|
||||
* \param ul_channel Channel to configure.
|
||||
* \param ul_mode Control mode register value to set.
|
||||
*
|
||||
* \attention If the TC is configured for waveform generation, the external
|
||||
* event selection (EEVT) should only be set to \c TC_CMR_EEVT_TIOB or the
|
||||
* equivalent value \c 0 if it really is the intention to use TIOB as an
|
||||
* external event trigger.\n
|
||||
* This is because the setting forces TIOB to be an input even if the
|
||||
* external event trigger has not been enabled with \c TC_CMR_ENETRG, and
|
||||
* thus prevents normal operation of TIOB.
|
||||
*/
|
||||
void tc_init(Tc *p_tc, uint32_t ul_channel, uint32_t ul_mode)
|
||||
{
|
||||
TcChannel *tc_channel;
|
||||
|
||||
Assert(ul_channel <
|
||||
(sizeof(p_tc->TC_CHANNEL) / sizeof(p_tc->TC_CHANNEL[0])));
|
||||
tc_channel = p_tc->TC_CHANNEL + ul_channel;
|
||||
|
||||
/* Disable TC clock. */
|
||||
tc_channel->TC_CCR = TC_CCR_CLKDIS;
|
||||
|
||||
/* Disable interrupts. */
|
||||
tc_channel->TC_IDR = 0xFFFFFFFF;
|
||||
|
||||
/* Clear status register. */
|
||||
tc_channel->TC_SR;
|
||||
|
||||
/* Set mode. */
|
||||
tc_channel->TC_CMR = ul_mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Asserts a SYNC signal to generate a software trigger to
|
||||
* all channels.
|
||||
*
|
||||
* \param p_tc Pointer to a TC instance.
|
||||
*
|
||||
*/
|
||||
void tc_sync_trigger(Tc *p_tc)
|
||||
{
|
||||
p_tc->TC_BCR = TC_BCR_SYNC;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Configure TC Block mode.
|
||||
* \note tc_init() must be called first.
|
||||
*
|
||||
* \param p_tc Pointer to a TC instance.
|
||||
* \param ul_blockmode Block mode register value to set.
|
||||
*
|
||||
*/
|
||||
void tc_set_block_mode(Tc *p_tc, uint32_t ul_blockmode)
|
||||
{
|
||||
p_tc->TC_BMR = ul_blockmode;
|
||||
}
|
||||
|
||||
#if (!SAM3U)
|
||||
|
||||
/**
|
||||
* \brief Configure TC for 2-bit Gray Counter for Stepper Motor.
|
||||
* \note tc_init() must be called first.
|
||||
*
|
||||
* \param p_tc Pointer to a TC instance.
|
||||
* \param ul_channel Channel to configure.
|
||||
* \param ul_steppermode Stepper motor mode register value to set.
|
||||
*
|
||||
* \return 0 for OK.
|
||||
*/
|
||||
uint32_t tc_init_2bit_gray(Tc *p_tc, uint32_t ul_channel,
|
||||
uint32_t ul_steppermode)
|
||||
{
|
||||
Assert(ul_channel <
|
||||
(sizeof(p_tc->TC_CHANNEL) / sizeof(p_tc->TC_CHANNEL[0])));
|
||||
|
||||
p_tc->TC_CHANNEL[ul_channel].TC_SMMR = ul_steppermode;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Start TC clock counter on the selected channel.
|
||||
*
|
||||
* \param p_tc Pointer to a TC instance.
|
||||
* \param ul_channel Channel to configure.
|
||||
*/
|
||||
void tc_start(Tc *p_tc, uint32_t ul_channel)
|
||||
{
|
||||
Assert(ul_channel <
|
||||
(sizeof(p_tc->TC_CHANNEL) / sizeof(p_tc->TC_CHANNEL[0])));
|
||||
|
||||
p_tc->TC_CHANNEL[ul_channel].TC_CCR = TC_CCR_CLKEN | TC_CCR_SWTRG;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Stop TC clock counter on the selected channel.
|
||||
*
|
||||
* \param p_tc Pointer to a TC instance.
|
||||
* \param ul_channel Channel to configure.
|
||||
*/
|
||||
void tc_stop(Tc *p_tc, uint32_t ul_channel)
|
||||
{
|
||||
Assert(ul_channel <
|
||||
(sizeof(p_tc->TC_CHANNEL) / sizeof(p_tc->TC_CHANNEL[0])));
|
||||
|
||||
p_tc->TC_CHANNEL[ul_channel].TC_CCR = TC_CCR_CLKDIS;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Read counter value on the selected channel.
|
||||
*
|
||||
* \param p_tc Pointer to a TC instance.
|
||||
* \param ul_channel Channel to configure.
|
||||
*
|
||||
* \return Counter value.
|
||||
*/
|
||||
uint32_t tc_read_cv(Tc *p_tc, uint32_t ul_channel)
|
||||
{
|
||||
Assert(ul_channel <
|
||||
(sizeof(p_tc->TC_CHANNEL) / sizeof(p_tc->TC_CHANNEL[0])));
|
||||
|
||||
return p_tc->TC_CHANNEL[ul_channel].TC_CV;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Read RA TC counter on the selected channel.
|
||||
*
|
||||
* \param p_tc Pointer to a TC instance.
|
||||
* \param ul_channel Channel to configure.
|
||||
*
|
||||
* \return RA value.
|
||||
*/
|
||||
uint32_t tc_read_ra(Tc *p_tc, uint32_t ul_channel)
|
||||
{
|
||||
Assert(ul_channel <
|
||||
(sizeof(p_tc->TC_CHANNEL) / sizeof(p_tc->TC_CHANNEL[0])));
|
||||
|
||||
return p_tc->TC_CHANNEL[ul_channel].TC_RA;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Read RB TC counter on the selected channel.
|
||||
*
|
||||
* \param p_tc Pointer to a TC instance.
|
||||
* \param ul_channel Channel to configure.
|
||||
*
|
||||
* \return RB value.
|
||||
*/
|
||||
uint32_t tc_read_rb(Tc *p_tc, uint32_t ul_channel)
|
||||
{
|
||||
Assert(ul_channel <
|
||||
(sizeof(p_tc->TC_CHANNEL) / sizeof(p_tc->TC_CHANNEL[0])));
|
||||
|
||||
return p_tc->TC_CHANNEL[ul_channel].TC_RB;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Read RC TC counter on the selected channel.
|
||||
*
|
||||
* \param p_tc Pointer to a TC instance.
|
||||
* \param ul_channel Channel to configure.
|
||||
*
|
||||
* \return RC value.
|
||||
*/
|
||||
uint32_t tc_read_rc(Tc *p_tc, uint32_t ul_channel)
|
||||
{
|
||||
Assert(ul_channel <
|
||||
(sizeof(p_tc->TC_CHANNEL) / sizeof(p_tc->TC_CHANNEL[0])));
|
||||
|
||||
return p_tc->TC_CHANNEL[ul_channel].TC_RC;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Write RA TC counter on the selected channel.
|
||||
*
|
||||
* \param p_tc Pointer to a TC instance.
|
||||
* \param ul_channel Channel to configure.
|
||||
* \param ul_value Value to set in register.
|
||||
*/
|
||||
void tc_write_ra(Tc *p_tc, uint32_t ul_channel,
|
||||
uint32_t ul_value)
|
||||
{
|
||||
Assert(ul_channel <
|
||||
(sizeof(p_tc->TC_CHANNEL) / sizeof(p_tc->TC_CHANNEL[0])));
|
||||
|
||||
p_tc->TC_CHANNEL[ul_channel].TC_RA = ul_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Write RB TC counter on the selected channel.
|
||||
*
|
||||
* \param p_tc Pointer to a TC instance.
|
||||
* \param ul_channel Channel to configure.
|
||||
* \param ul_value Value to set in register.
|
||||
*/
|
||||
void tc_write_rb(Tc *p_tc, uint32_t ul_channel,
|
||||
uint32_t ul_value)
|
||||
{
|
||||
Assert(ul_channel <
|
||||
(sizeof(p_tc->TC_CHANNEL) / sizeof(p_tc->TC_CHANNEL[0])));
|
||||
|
||||
p_tc->TC_CHANNEL[ul_channel].TC_RB = ul_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Write RC TC counter on the selected channel.
|
||||
*
|
||||
* \param p_tc Pointer to a TC instance.
|
||||
* \param ul_channel Channel to configure.
|
||||
* \param ul_value Value to set in register.
|
||||
*/
|
||||
void tc_write_rc(Tc *p_tc, uint32_t ul_channel,
|
||||
uint32_t ul_value)
|
||||
{
|
||||
Assert(ul_channel <
|
||||
(sizeof(p_tc->TC_CHANNEL) / sizeof(p_tc->TC_CHANNEL[0])));
|
||||
|
||||
p_tc->TC_CHANNEL[ul_channel].TC_RC = ul_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Enable TC interrupts on the selected channel.
|
||||
*
|
||||
* \param p_tc Pointer to a TC instance.
|
||||
* \param ul_channel Channel to configure.
|
||||
* \param ul_sources Interrupt sources bit map.
|
||||
*/
|
||||
void tc_enable_interrupt(Tc *p_tc, uint32_t ul_channel,
|
||||
uint32_t ul_sources)
|
||||
{
|
||||
TcChannel *tc_channel;
|
||||
|
||||
Assert(ul_channel <
|
||||
(sizeof(p_tc->TC_CHANNEL) / sizeof(p_tc->TC_CHANNEL[0])));
|
||||
tc_channel = p_tc->TC_CHANNEL + ul_channel;
|
||||
tc_channel->TC_IER = ul_sources;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Disable TC interrupts on the selected channel.
|
||||
*
|
||||
* \param p_tc Pointer to a TC instance.
|
||||
* \param ul_channel Channel to configure.
|
||||
* \param ul_sources Interrupt sources bit map.
|
||||
*/
|
||||
void tc_disable_interrupt(Tc *p_tc, uint32_t ul_channel,
|
||||
uint32_t ul_sources)
|
||||
{
|
||||
TcChannel *tc_channel;
|
||||
|
||||
Assert(ul_channel <
|
||||
(sizeof(p_tc->TC_CHANNEL) / sizeof(p_tc->TC_CHANNEL[0])));
|
||||
tc_channel = p_tc->TC_CHANNEL + ul_channel;
|
||||
tc_channel->TC_IDR = ul_sources;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Read TC interrupt mask on the selected channel.
|
||||
*
|
||||
* \param p_tc Pointer to a TC instance.
|
||||
* \param ul_channel Channel to configure.
|
||||
*
|
||||
* \return The interrupt mask value.
|
||||
*/
|
||||
uint32_t tc_get_interrupt_mask(Tc *p_tc, uint32_t ul_channel)
|
||||
{
|
||||
TcChannel *tc_channel;
|
||||
|
||||
Assert(ul_channel <
|
||||
(sizeof(p_tc->TC_CHANNEL) / sizeof(p_tc->TC_CHANNEL[0])));
|
||||
tc_channel = p_tc->TC_CHANNEL + ul_channel;
|
||||
return tc_channel->TC_IMR;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Get current status on the selected channel.
|
||||
*
|
||||
* \param p_tc Pointer to a TC instance.
|
||||
* \param ul_channel Channel to configure.
|
||||
*
|
||||
* \return The current TC status.
|
||||
*/
|
||||
uint32_t tc_get_status(Tc *p_tc, uint32_t ul_channel)
|
||||
{
|
||||
TcChannel *tc_channel;
|
||||
|
||||
Assert(ul_channel <
|
||||
(sizeof(p_tc->TC_CHANNEL) / sizeof(p_tc->TC_CHANNEL[0])));
|
||||
tc_channel = p_tc->TC_CHANNEL + ul_channel;
|
||||
return tc_channel->TC_SR;
|
||||
}
|
||||
|
||||
/* TC divisor used to find the lowest acceptable timer frequency */
|
||||
#define TC_DIV_FACTOR 65536
|
||||
|
||||
#if (!SAM4L)
|
||||
|
||||
#ifndef FREQ_SLOW_CLOCK_EXT
|
||||
#define FREQ_SLOW_CLOCK_EXT 32768 /* External slow clock frequency (hz) */
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Find the best MCK divisor.
|
||||
*
|
||||
* Finds the best MCK divisor given the timer frequency and MCK. The result
|
||||
* is guaranteed to satisfy the following equation:
|
||||
* \code
|
||||
* (MCK / (DIV * 65536)) <= freq <= (MCK / DIV)
|
||||
* \endcode
|
||||
* with DIV being the lowest possible value,
|
||||
* to maximize timing adjust resolution.
|
||||
*
|
||||
* \param ul_freq Desired timer frequency.
|
||||
* \param ul_mck Master clock frequency.
|
||||
* \param p_uldiv Divisor value.
|
||||
* \param p_ultcclks TCCLKS field value for divisor.
|
||||
* \param ul_boardmck Board clock frequency.
|
||||
*
|
||||
* \return 1 if a proper divisor has been found, otherwise 0.
|
||||
*/
|
||||
uint32_t tc_find_mck_divisor(uint32_t ul_freq, uint32_t ul_mck,
|
||||
uint32_t *p_uldiv, uint32_t *p_ultcclks, uint32_t ul_boardmck)
|
||||
{
|
||||
const uint32_t divisors[5] = { 2, 8, 32, 128,
|
||||
ul_boardmck / FREQ_SLOW_CLOCK_EXT };
|
||||
uint32_t ul_index;
|
||||
uint32_t ul_high, ul_low;
|
||||
|
||||
/* Satisfy frequency bound. */
|
||||
for (ul_index = 0;
|
||||
ul_index < (sizeof(divisors) / sizeof(divisors[0]));
|
||||
ul_index++) {
|
||||
ul_high = ul_mck / divisors[ul_index];
|
||||
ul_low = ul_high / TC_DIV_FACTOR;
|
||||
if (ul_freq > ul_high) {
|
||||
return 0;
|
||||
} else if (ul_freq >= ul_low) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ul_index >= (sizeof(divisors) / sizeof(divisors[0]))) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Store results. */
|
||||
if (p_uldiv) {
|
||||
*p_uldiv = divisors[ul_index];
|
||||
}
|
||||
|
||||
if (p_ultcclks) {
|
||||
*p_ultcclks = ul_index;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if (SAM4L)
|
||||
/**
|
||||
* \brief Find the best PBA clock divisor.
|
||||
*
|
||||
* Finds the best divisor given the timer frequency and PBA clock. The result
|
||||
* is guaranteed to satisfy the following equation:
|
||||
* \code
|
||||
* (ul_pbaclk / (2* DIV * 65536)) <= freq <= (ul_pbaclk / (2* DIV))
|
||||
* \endcode
|
||||
* with DIV being the lowest possible value,
|
||||
* to maximize timing adjust resolution.
|
||||
*
|
||||
* \param ul_freq Desired timer frequency.
|
||||
* \param ul_mck PBA clock frequency.
|
||||
* \param p_uldiv Divisor value.
|
||||
* \param p_ultcclks TCCLKS field value for divisor.
|
||||
* \param ul_boardmck useless here.
|
||||
*
|
||||
* \return 1 if a proper divisor has been found, otherwise 0.
|
||||
*/
|
||||
uint32_t tc_find_mck_divisor(uint32_t ul_freq, uint32_t ul_mck,
|
||||
uint32_t *p_uldiv, uint32_t *p_ultcclks, uint32_t ul_boardmck)
|
||||
{
|
||||
const uint32_t divisors[5] = { 0, 2, 8, 32, 128};
|
||||
uint32_t ul_index;
|
||||
uint32_t ul_high, ul_low;
|
||||
|
||||
UNUSED(ul_boardmck);
|
||||
|
||||
/* Satisfy frequency bound. */
|
||||
for (ul_index = 1;
|
||||
ul_index < (sizeof(divisors) / sizeof(divisors[0]));
|
||||
ul_index++) {
|
||||
ul_high = ul_mck / divisors[ul_index];
|
||||
ul_low = ul_high / TC_DIV_FACTOR;
|
||||
if (ul_freq > ul_high) {
|
||||
return 0;
|
||||
} else if (ul_freq >= ul_low) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ul_index >= (sizeof(divisors) / sizeof(divisors[0]))) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Store results. */
|
||||
if (p_uldiv) {
|
||||
*p_uldiv = divisors[ul_index];
|
||||
}
|
||||
|
||||
if (p_ultcclks) {
|
||||
*p_ultcclks = ul_index;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if (!SAM4L)
|
||||
|
||||
/**
|
||||
* \brief Enable TC QDEC interrupts.
|
||||
*
|
||||
* \param p_tc Pointer to a TC instance.
|
||||
* \param ul_sources Interrupts to be enabled.
|
||||
*/
|
||||
void tc_enable_qdec_interrupt(Tc *p_tc, uint32_t ul_sources)
|
||||
{
|
||||
p_tc->TC_QIER = ul_sources;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Disable TC QDEC interrupts.
|
||||
*
|
||||
* \param p_tc Pointer to a TC instance.
|
||||
* \param ul_sources Interrupts to be disabled.
|
||||
*/
|
||||
void tc_disable_qdec_interrupt(Tc *p_tc, uint32_t ul_sources)
|
||||
{
|
||||
p_tc->TC_QIDR = ul_sources;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Read TC QDEC interrupt mask.
|
||||
*
|
||||
* \param p_tc Pointer to a TC instance.
|
||||
*
|
||||
* \return The interrupt mask value.
|
||||
*/
|
||||
uint32_t tc_get_qdec_interrupt_mask(Tc *p_tc)
|
||||
{
|
||||
return p_tc->TC_QIMR;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Get current QDEC status.
|
||||
*
|
||||
* \param p_tc Pointer to a TC instance.
|
||||
*
|
||||
* \return The current TC status.
|
||||
*/
|
||||
uint32_t tc_get_qdec_interrupt_status(Tc *p_tc)
|
||||
{
|
||||
return p_tc->TC_QISR;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if (!SAM3U)
|
||||
|
||||
/**
|
||||
* \brief Enable or disable write protection of TC registers.
|
||||
*
|
||||
* \param p_tc Pointer to a TC instance.
|
||||
* \param ul_enable 1 to enable, 0 to disable.
|
||||
*/
|
||||
void tc_set_writeprotect(Tc *p_tc, uint32_t ul_enable)
|
||||
{
|
||||
if (ul_enable) {
|
||||
p_tc->TC_WPMR = TC_WPMR_WPKEY_VALUE | TC_WPMR_WPEN;
|
||||
} else {
|
||||
p_tc->TC_WPMR = TC_WPMR_WPKEY_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if SAM4L
|
||||
|
||||
/**
|
||||
* \brief Indicate features.
|
||||
*
|
||||
* \param p_tc Pointer to a TC instance.
|
||||
*
|
||||
* \return TC_FEATURES value.
|
||||
*/
|
||||
uint32_t tc_get_feature(Tc *p_tc)
|
||||
{
|
||||
return p_tc->TC_FEATURES;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Indicate version.
|
||||
*
|
||||
* \param p_tc Pointer to a TC instance.
|
||||
*
|
||||
* \return TC_VERSION value.
|
||||
*/
|
||||
uint32_t tc_get_version(Tc *p_tc)
|
||||
{
|
||||
return p_tc->TC_VERSION;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//@}
|
||||
|
||||
/// @cond 0
|
||||
/**INDENT-OFF**/
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
/**INDENT-ON**/
|
||||
/// @endcond
|
@ -0,0 +1,114 @@
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* \brief Timer Counter (TC) driver for SAM.
|
||||
*
|
||||
* Copyright (c) 2011-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
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TC_H_INCLUDED
|
||||
#define TC_H_INCLUDED
|
||||
|
||||
#include "compiler.h"
|
||||
|
||||
/// @cond 0
|
||||
/**INDENT-OFF**/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/**INDENT-ON**/
|
||||
/// @endcond
|
||||
|
||||
void tc_init(Tc *p_tc, uint32_t ul_Channel, uint32_t ul_Mode);
|
||||
void tc_sync_trigger(Tc *p_tc);
|
||||
void tc_set_block_mode(Tc *p_tc, uint32_t ul_blockmode);
|
||||
|
||||
#if (!SAM3U)
|
||||
uint32_t tc_init_2bit_gray(Tc *p_tc, uint32_t ul_channel,
|
||||
uint32_t ul_steppermode);
|
||||
#endif
|
||||
|
||||
void tc_start(Tc *p_tc, uint32_t ul_channel);
|
||||
void tc_stop(Tc *p_tc, uint32_t ul_channel);
|
||||
|
||||
uint32_t tc_read_cv(Tc *p_tc, uint32_t ul_channel);
|
||||
uint32_t tc_read_ra(Tc *p_tc, uint32_t ul_channel);
|
||||
uint32_t tc_read_rb(Tc *p_tc, uint32_t ul_channel);
|
||||
uint32_t tc_read_rc(Tc *p_tc, uint32_t ul_channel);
|
||||
|
||||
void tc_write_ra(Tc *p_tc, uint32_t ul_channel,
|
||||
uint32_t ul_value);
|
||||
void tc_write_rb(Tc *p_tc, uint32_t ul_channel,
|
||||
uint32_t ul_value);
|
||||
void tc_write_rc(Tc *p_tc, uint32_t ul_channel,
|
||||
uint32_t ul_value);
|
||||
|
||||
uint32_t tc_find_mck_divisor(uint32_t ul_freq, uint32_t ul_mck,
|
||||
uint32_t *p_uldiv, uint32_t *ul_tcclks, uint32_t ul_boardmck);
|
||||
void tc_enable_interrupt(Tc *p_tc, uint32_t ul_channel,
|
||||
uint32_t ul_sources);
|
||||
void tc_disable_interrupt(Tc *p_tc, uint32_t ul_channel,
|
||||
uint32_t ul_sources);
|
||||
uint32_t tc_get_interrupt_mask(Tc *p_tc, uint32_t ul_channel);
|
||||
uint32_t tc_get_status(Tc *p_tc, uint32_t ul_channel);
|
||||
#if (!SAM4L)
|
||||
void tc_enable_qdec_interrupt(Tc *p_tc, uint32_t ul_sources);
|
||||
void tc_disable_qdec_interrupt(Tc *p_tc, uint32_t ul_sources);
|
||||
uint32_t tc_get_qdec_interrupt_mask(Tc *p_tc);
|
||||
uint32_t tc_get_qdec_interrupt_status(Tc *p_tc);
|
||||
#endif
|
||||
|
||||
#if (!SAM3U)
|
||||
void tc_set_writeprotect(Tc *p_tc, uint32_t ul_enable);
|
||||
#endif
|
||||
|
||||
#if SAM4L
|
||||
uint32_t tc_get_feature(Tc *p_tc);
|
||||
uint32_t tc_get_version(Tc *p_tc);
|
||||
|
||||
#endif
|
||||
|
||||
/// @cond 0
|
||||
/**INDENT-OFF**/
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
/**INDENT-ON**/
|
||||
/// @endcond
|
||||
|
||||
#endif /* TC_H_INCLUDED */
|
@ -0,0 +1,198 @@
|
||||
/*
|
||||
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||
All rights reserved
|
||||
|
||||
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* FreeRTOS provides completely free yet professionally developed, *
|
||||
* robust, strictly quality controlled, supported, and cross *
|
||||
* platform software that has become a de facto standard. *
|
||||
* *
|
||||
* Help yourself get started quickly and support the FreeRTOS *
|
||||
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||
* *
|
||||
* Thank you! *
|
||||
* *
|
||||
***************************************************************************
|
||||
|
||||
This file is part of the FreeRTOS distribution.
|
||||
|
||||
FreeRTOS is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License (version 2) as published by the
|
||||
Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
|
||||
|
||||
>>! NOTE: The modification to the GPL is included to allow you to !<<
|
||||
>>! distribute a combined work that includes FreeRTOS without being !<<
|
||||
>>! obliged to provide the source code for proprietary components !<<
|
||||
>>! outside of the FreeRTOS kernel. !<<
|
||||
|
||||
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. Full license text is available from the following
|
||||
link: http://www.freertos.org/a00114.html
|
||||
|
||||
1 tab == 4 spaces!
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* Having a problem? Start by reading the FAQ "My application does *
|
||||
* not run, what could be wrong?" *
|
||||
* *
|
||||
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||
* *
|
||||
***************************************************************************
|
||||
|
||||
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||
license and Real Time Engineers Ltd. contact details.
|
||||
|
||||
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
|
||||
including FreeRTOS+Trace - an indispensable productivity tool, a DOS
|
||||
compatible FAT file system, and our tiny thread aware UDP/IP stack.
|
||||
|
||||
http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||
licenses offer ticketed support, indemnification and middleware.
|
||||
|
||||
http://www.SafeRTOS.com - High Integrity Systems also provide a safety
|
||||
engineered and independently SIL3 certified version for use in safety and
|
||||
mission critical applications that require provable dependability.
|
||||
|
||||
1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
/*
|
||||
* Provides the two timers sources for the standard demo IntQueue test. Also
|
||||
* includes a high frequency timer to maximise the interrupt nesting achieved.
|
||||
*/
|
||||
|
||||
/* Standard includes. */
|
||||
#include <limits.h>
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
/* Demo includes. */
|
||||
#include "IntQueueTimer.h"
|
||||
#include "IntQueue.h"
|
||||
|
||||
/* System includes. */
|
||||
#include "board.h"
|
||||
#include "asf.h"
|
||||
|
||||
/* The frequencies at which the first two timers expire are slightly offset to
|
||||
ensure they don't remain synchronised. The frequency of the highest priority
|
||||
interrupt is 20 times faster so really hammers the interrupt entry and exit
|
||||
code. */
|
||||
#define tmrTIMER_0_FREQUENCY ( 2000UL )
|
||||
#define tmrTIMER_1_FREQUENCY ( 1003UL )
|
||||
#define tmrTIMER_2_FREQUENCY ( 20000UL )
|
||||
|
||||
/* Priorities used by the timer interrupts - these are set differently to make
|
||||
nesting likely/common. The high frequency timer operates above the max
|
||||
system call interrupt priority, but does not use the RTOS API. */
|
||||
#define tmrTIMER_0_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY )
|
||||
#define tmrTIMER_1_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY + 1 )
|
||||
#define tmrTIMER_2_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY - 1 )
|
||||
|
||||
/* The channels used within the TC0 timer. */
|
||||
#define tmrTIMER_0_CHANNEL ( 0 )
|
||||
#define tmrTIMER_1_CHANNEL ( 1 )
|
||||
#define tmrTIMER_2_CHANNEL ( 2 )
|
||||
|
||||
/* TC register bit specifics. */
|
||||
#define tmrTRIGGER_ON_RC ( 1UL << 4UL )
|
||||
#define trmDIVIDER ( 128 )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Handers for the timer interrupts. */
|
||||
void TC0_Handler( void );
|
||||
void TC1_Handler( void );
|
||||
void TC2_Handler( void );
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Incremented by the high frequency timer, which operates above the max
|
||||
syscall interrupt priority. This is just for inspection. */
|
||||
volatile uint32_t ulHighFrequencyTimerInterrupts = 0;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vInitialiseTimerForIntQueueTest( void )
|
||||
{
|
||||
uint32_t ulInputFrequency;
|
||||
|
||||
/* Calculate the frequency of the clock that feeds the TC. */
|
||||
ulInputFrequency = configCPU_CLOCK_HZ;
|
||||
ulInputFrequency /= trmDIVIDER;
|
||||
|
||||
/* Three channels are used - two that run at or under
|
||||
configMAX_SYSCALL_INTERRUPT_PRIORITY, and one that runs over
|
||||
configMAX_SYSCALL_INTERRUPT_PRIORITY. */
|
||||
sysclk_enable_peripheral_clock( ID_TC0 );
|
||||
sysclk_enable_peripheral_clock( ID_TC1 );
|
||||
sysclk_enable_peripheral_clock( ID_TC2 );
|
||||
|
||||
/* Init TC channels to waveform mode - up mode clean on RC match. */
|
||||
tc_init( TC0, tmrTIMER_0_CHANNEL, TC_CMR_TCCLKS_TIMER_CLOCK4 | TC_CMR_WAVE | TC_CMR_ACPC_CLEAR | TC_CMR_CPCTRG );
|
||||
tc_init( TC0, tmrTIMER_1_CHANNEL, TC_CMR_TCCLKS_TIMER_CLOCK4 | TC_CMR_WAVE | TC_CMR_ACPC_CLEAR | TC_CMR_CPCTRG );
|
||||
tc_init( TC0, tmrTIMER_2_CHANNEL, TC_CMR_TCCLKS_TIMER_CLOCK4 | TC_CMR_WAVE | TC_CMR_ACPC_CLEAR | TC_CMR_CPCTRG );
|
||||
|
||||
tc_enable_interrupt( TC0, tmrTIMER_0_CHANNEL, tmrTRIGGER_ON_RC );
|
||||
tc_enable_interrupt( TC0, tmrTIMER_1_CHANNEL, tmrTRIGGER_ON_RC );
|
||||
tc_enable_interrupt( TC0, tmrTIMER_2_CHANNEL, tmrTRIGGER_ON_RC );
|
||||
|
||||
tc_write_rc( TC0, tmrTIMER_0_CHANNEL, ( ulInputFrequency / tmrTIMER_0_FREQUENCY ) );
|
||||
tc_write_rc( TC0, tmrTIMER_1_CHANNEL, ( ulInputFrequency / tmrTIMER_1_FREQUENCY ) );
|
||||
tc_write_rc( TC0, tmrTIMER_2_CHANNEL, ( ulInputFrequency / tmrTIMER_2_FREQUENCY ) );
|
||||
|
||||
NVIC_SetPriority( TC0_IRQn, tmrTIMER_0_PRIORITY );
|
||||
NVIC_SetPriority( TC1_IRQn, tmrTIMER_1_PRIORITY );
|
||||
NVIC_SetPriority( TC2_IRQn, tmrTIMER_2_PRIORITY );
|
||||
|
||||
NVIC_EnableIRQ( TC0_IRQn );
|
||||
NVIC_EnableIRQ( TC1_IRQn );
|
||||
NVIC_EnableIRQ( TC2_IRQn );
|
||||
|
||||
tc_start( TC0, tmrTIMER_0_CHANNEL );
|
||||
tc_start( TC0, tmrTIMER_1_CHANNEL );
|
||||
tc_start( TC0, tmrTIMER_2_CHANNEL );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void TC0_Handler( void )
|
||||
{
|
||||
/* Handler for the first timer in the IntQueue test. Was the interrupt
|
||||
caused by a compare on RC? */
|
||||
if( ( tc_get_status( TC0, tmrTIMER_0_CHANNEL ) & ~TC_SR_CPCS ) != 0 )
|
||||
{
|
||||
portYIELD_FROM_ISR( xFirstTimerHandler() );
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void TC1_Handler( void )
|
||||
{
|
||||
/* Handler for the second timer in the IntQueue test. Was the interrupt
|
||||
caused by a compare on RC? */
|
||||
if( ( tc_get_status( TC0, tmrTIMER_1_CHANNEL ) & ~TC_SR_CPCS ) != 0 )
|
||||
{
|
||||
portYIELD_FROM_ISR( xSecondTimerHandler() );
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void TC2_Handler( void )
|
||||
{
|
||||
/* Handler for the high frequency timer that does nothing but increment a
|
||||
variable to give an indication that it is running. Was the interrupt caused
|
||||
by a compare on RC? */
|
||||
if( ( tc_get_status( TC0, tmrTIMER_2_CHANNEL ) & ~TC_SR_CPCS ) != 0 )
|
||||
{
|
||||
ulHighFrequencyTimerInterrupts++;
|
||||
}
|
||||
}
|
@ -0,0 +1,74 @@
|
||||
/*
|
||||
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||
All rights reserved
|
||||
|
||||
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* FreeRTOS provides completely free yet professionally developed, *
|
||||
* robust, strictly quality controlled, supported, and cross *
|
||||
* platform software that has become a de facto standard. *
|
||||
* *
|
||||
* Help yourself get started quickly and support the FreeRTOS *
|
||||
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||
* *
|
||||
* Thank you! *
|
||||
* *
|
||||
***************************************************************************
|
||||
|
||||
This file is part of the FreeRTOS distribution.
|
||||
|
||||
FreeRTOS is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License (version 2) as published by the
|
||||
Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
|
||||
|
||||
>>! NOTE: The modification to the GPL is included to allow you to !<<
|
||||
>>! distribute a combined work that includes FreeRTOS without being !<<
|
||||
>>! obliged to provide the source code for proprietary components !<<
|
||||
>>! outside of the FreeRTOS kernel. !<<
|
||||
|
||||
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. Full license text is available from the following
|
||||
link: http://www.freertos.org/a00114.html
|
||||
|
||||
1 tab == 4 spaces!
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* Having a problem? Start by reading the FAQ "My application does *
|
||||
* not run, what could be wrong?" *
|
||||
* *
|
||||
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||
* *
|
||||
***************************************************************************
|
||||
|
||||
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||
license and Real Time Engineers Ltd. contact details.
|
||||
|
||||
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
|
||||
including FreeRTOS+Trace - an indispensable productivity tool, a DOS
|
||||
compatible FAT file system, and our tiny thread aware UDP/IP stack.
|
||||
|
||||
http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||
licenses offer ticketed support, indemnification and middleware.
|
||||
|
||||
http://www.SafeRTOS.com - High Integrity Systems also provide a safety
|
||||
engineered and independently SIL3 certified version for use in safety and
|
||||
mission critical applications that require provable dependability.
|
||||
|
||||
1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
#ifndef INT_QUEUE_TIMER_H
|
||||
#define INT_QUEUE_TIMER_H
|
||||
|
||||
void vInitialiseTimerForIntQueueTest( void );
|
||||
BaseType_t xTimer0Handler( void );
|
||||
BaseType_t xTimer1Handler( void );
|
||||
|
||||
#endif
|
||||
|
Binary file not shown.
Loading…
Reference in New Issue