Addition of GPT driver for AT91SAM7 (working but not all features tested yet)
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@6818 35acf78f-673a-0410-8e92-d51de3d6d3f4master
parent
f20d6ff60c
commit
30e4b1df65
|
@ -0,0 +1,456 @@
|
|||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
|
||||
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 AT91SAM7/gpt_lld.c
|
||||
* @brief AT91SAM7 GPT subsystem low level driver source.
|
||||
*
|
||||
* @addtogroup GPT
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "ch.h"
|
||||
#include "hal.h"
|
||||
|
||||
#if HAL_USE_GPT || defined(__DOXYGEN__)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local definitions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported variables. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief GPTD1 driver identifier.
|
||||
* @note The driver GPTD1 allocates the complex timer TC0 when enabled.
|
||||
*/
|
||||
#if AT91_GPT_USE_TC0 || defined(__DOXYGEN__)
|
||||
GPTDriver GPTD1;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief GPTD2 driver identifier.
|
||||
* @note The driver GPTD2 allocates the timer TC1 when enabled.
|
||||
*/
|
||||
#if AT91_GPT_USE_TC1 || defined(__DOXYGEN__)
|
||||
GPTDriver GPTD2;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief GPTD3 driver identifier.
|
||||
* @note The driver GPTD3 allocates the timer TC2 when enabled.
|
||||
*/
|
||||
#if AT91_GPT_USE_TC2 || defined(__DOXYGEN__)
|
||||
GPTDriver GPTD3;
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local variables and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Shared IRQ handler.
|
||||
*
|
||||
* @param[in] gptp pointer to a @p GPTDriver object
|
||||
*/
|
||||
static void gpt_lld_serve_interrupt(GPTDriver *gptp) {
|
||||
// Read the status to clear the interrupts
|
||||
{
|
||||
uint32_t isr = gptp->tc->TC_SR;
|
||||
(void) isr;
|
||||
}
|
||||
|
||||
// Clear one-shot
|
||||
if (gptp->state == GPT_ONESHOT) {
|
||||
gptp->state = GPT_READY; // Back in GPT_READY state.
|
||||
gptp->tc->TC_IDR = 0xFFFFFFFF; // Disable interrupts (not really needed but safer)
|
||||
}
|
||||
|
||||
// Do the callback
|
||||
gptp->config->callback(gptp);
|
||||
}
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver interrupt handlers. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if AT91_GPT_USE_TC0
|
||||
/**
|
||||
* @brief TC1 interrupt handler.
|
||||
*
|
||||
* @isr
|
||||
*/
|
||||
CH_IRQ_HANDLER(TC0_IRQHandler) {
|
||||
CH_IRQ_PROLOGUE();
|
||||
gpt_lld_serve_interrupt(&GPTD1);
|
||||
AT91C_BASE_AIC->AIC_EOICR = 0;
|
||||
CH_IRQ_EPILOGUE();
|
||||
}
|
||||
#endif /* AT91_GPT_USE_TC0 */
|
||||
|
||||
#if AT91_GPT_USE_TC1
|
||||
/**
|
||||
* @brief TC1 interrupt handler.
|
||||
*
|
||||
* @isr
|
||||
*/
|
||||
CH_IRQ_HANDLER(TC1_IRQHandler) {
|
||||
CH_IRQ_PROLOGUE();
|
||||
gpt_lld_serve_interrupt(&GPTD2);
|
||||
AT91C_BASE_AIC->AIC_EOICR = 0;
|
||||
CH_IRQ_EPILOGUE();
|
||||
}
|
||||
#endif /* AT91_GPT_USE_TC1 */
|
||||
|
||||
#if AT91_GPT_USE_TC2
|
||||
/**
|
||||
* @brief TC1 interrupt handler.
|
||||
*
|
||||
* @isr
|
||||
*/
|
||||
CH_IRQ_HANDLER(TC2_IRQHandler) {
|
||||
CH_IRQ_PROLOGUE();
|
||||
gpt_lld_serve_interrupt(&GPTD2);
|
||||
AT91C_BASE_AIC->AIC_EOICR = 0;
|
||||
CH_IRQ_EPILOGUE();
|
||||
}
|
||||
}
|
||||
#endif /* AT91_GPT_USE_TC2 */
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Low level GPT driver initialization.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void gpt_lld_init(void) {
|
||||
|
||||
#if AT91_GPT_USE_TC0
|
||||
AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC0); // Turn on the power
|
||||
GPTD1.tc = AT91C_BASE_TC0;
|
||||
gptObjectInit(&GPTD1);
|
||||
gpt_lld_stop(&GPTD1); // Make sure it is disabled
|
||||
AIC_ConfigureIT(AT91C_ID_TC0, AT91C_AIC_SRCTYPE_HIGH_LEVEL | AT91_GPT_TC0_IRQ_PRIORITY, TC0_IRQHandler);
|
||||
AIC_EnableIT(AT91C_ID_TC0);
|
||||
#endif
|
||||
|
||||
#if AT91_GPT_USE_TC1
|
||||
AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1); // Turn on the power
|
||||
GPTD2.tc = AT91C_BASE_TC1;
|
||||
gptObjectInit(&GPTD2);
|
||||
gpt_lld_stop(&GPTD2); // Make sure it is disabled
|
||||
AIC_ConfigureIT(AT91C_ID_TC1, AT91C_AIC_SRCTYPE_HIGH_LEVEL | AT91_GPT_TC1_IRQ_PRIORITY, TC1_IRQHandler);
|
||||
AIC_EnableIT(AT91C_ID_TC1);
|
||||
#endif
|
||||
|
||||
#if AT91_GPT_USE_TC2
|
||||
AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC2); // Turn on the power
|
||||
GPTD3.tc = AT91C_BASE_TC2;
|
||||
gptObjectInit(&GPTD3);
|
||||
gpt_lld_stop(&GPTD3); // Make sure it is disabled
|
||||
AIC_ConfigureIT(AT91C_ID_TC2, AT91C_AIC_SRCTYPE_HIGH_LEVEL | AT91_GPT_TC2_IRQ_PRIORITY, TC2_IRQHandler);
|
||||
AIC_EnableIT(AT91C_ID_TC2);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configures and activates the GPT peripheral.
|
||||
*
|
||||
* @param[in] gptp pointer to the @p GPTDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void gpt_lld_start(GPTDriver *gptp) {
|
||||
uint32_t cmr, rc, bmr;
|
||||
|
||||
bmr = *AT91C_TCB_BMR;
|
||||
rc = 65535;
|
||||
cmr = (AT91C_TC_ASWTRG_CLEAR | AT91C_TC_ACPC_CLEAR | AT91C_TC_ACPA_SET |
|
||||
AT91C_TC_WAVE | AT91C_TC_WAVESEL_UP_AUTO);
|
||||
|
||||
// Calculate clock
|
||||
switch(gptp->config->clocksource) {
|
||||
case GPT_CLOCK_MCLK:
|
||||
switch(gptp->config->frequency) {
|
||||
case MCK/2: cmr |= AT91C_TC_CLKS_TIMER_DIV1_CLOCK; break;
|
||||
case MCK/8: cmr |= AT91C_TC_CLKS_TIMER_DIV2_CLOCK; break;
|
||||
case MCK/32: cmr |= AT91C_TC_CLKS_TIMER_DIV3_CLOCK; break;
|
||||
case MCK/128: cmr |= AT91C_TC_CLKS_TIMER_DIV4_CLOCK; break;
|
||||
case MCK/1024: cmr |= AT91C_TC_CLKS_TIMER_DIV5_CLOCK; break;
|
||||
default:
|
||||
chDbgAssert(TRUE, "gpt_lld_start(), #1", "invalid frequency");
|
||||
cmr |= AT91C_TC_CLKS_TIMER_DIV5_CLOCK;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case GPT_CLOCK_FREQUENCY:
|
||||
/* Set the Mode of the Timer Counter and calculate the period */
|
||||
rc = (MCK/2)/gptp->config->frequency;
|
||||
if (rc < (0x10000<<0)) {
|
||||
cmr |= AT91C_TC_CLKS_TIMER_DIV1_CLOCK;
|
||||
} else if (rc < (0x10000<<2)) {
|
||||
rc >>= 2;
|
||||
cmr |= AT91C_TC_CLKS_TIMER_DIV2_CLOCK;
|
||||
} else if (rc < (0x10000<<4)) {
|
||||
rc >>= 4;
|
||||
cmr |= AT91C_TC_CLKS_TIMER_DIV3_CLOCK;
|
||||
} else if (rc < (0x10000<<6)) {
|
||||
rc >>= 6;
|
||||
cmr |= AT91C_TC_CLKS_TIMER_DIV4_CLOCK;
|
||||
} else {
|
||||
rc >>= 9;
|
||||
cmr |= AT91C_TC_CLKS_TIMER_DIV5_CLOCK;
|
||||
}
|
||||
break;
|
||||
case GPT_CLOCK_RE_TCLK0:
|
||||
case GPT_CLOCK_FE_TCLK0:
|
||||
if ((gptp->config->clocksource & 1)) cmr |= AT91C_TC_CLKI;
|
||||
cmr |= AT91C_TC_CLKS_XC0;
|
||||
#if AT91_GPT_USE_TC0
|
||||
if (gptp == &GPTD1) bmr = (bmr & ~AT91C_TCB_TC0XC0S) | AT91C_TCB_TC0XC0S_TCLK0;
|
||||
#endif
|
||||
break;
|
||||
case GPT_CLOCK_RE_TCLK1:
|
||||
case GPT_CLOCK_FE_TCLK1:
|
||||
if ((gptp->config->clocksource & 1)) cmr |= AT91C_TC_CLKI;
|
||||
cmr |= AT91C_TC_CLKS_XC1;
|
||||
#if AT91_GPT_USE_TC1
|
||||
if (gptp == &GPTD2) bmr = (bmr & ~AT91C_TCB_TC1XC1S) | AT91C_TCB_TC1XC1S_TCLK1;
|
||||
#endif
|
||||
break;
|
||||
case GPT_CLOCK_RE_TCLK2:
|
||||
case GPT_CLOCK_FE_TCLK2:
|
||||
if ((gptp->config->clocksource & 1)) cmr |= AT91C_TC_CLKI;
|
||||
cmr |= AT91C_TC_CLKS_XC2;
|
||||
#if AT91_GPT_USE_TC2
|
||||
if (gptp == &GPTD3) bmr = (bmr & ~AT91C_TCB_TC2XC2S) | AT91C_TCB_TC2XC2S_TCLK2;
|
||||
#endif
|
||||
break;
|
||||
case GPT_CLOCK_RE_TC0:
|
||||
case GPT_CLOCK_FE_TC0:
|
||||
if ((gptp->config->clocksource & 1)) cmr |= AT91C_TC_CLKI;
|
||||
#if AT91_GPT_USE_TC0
|
||||
if (gptp == &GPTD1) {
|
||||
chDbgAssert(TRUE, "gpt_lld_start(), #2", "invalid clock");
|
||||
cmr |= AT91C_TC_CLKS_XC0;
|
||||
bmr = (bmr & ~AT91C_TCB_TC0XC0S) | AT91C_TCB_TC0XC0S_NONE;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#if AT91_GPT_USE_TC1
|
||||
if (gptp == &GPTD2) {
|
||||
cmr |= AT91C_TC_CLKS_XC1;
|
||||
bmr = (bmr & ~AT91C_TCB_TC1XC1S) | AT91C_TCB_TC1XC1S_TIOA0;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#if AT91_GPT_USE_TC2
|
||||
if (gptp == &GPTD3) {
|
||||
cmr |= AT91C_TC_CLKS_XC2;
|
||||
bmr = (bmr & ~AT91C_TCB_TC2XC2S) | AT91C_TCB_TC2XC2S_TIOA0;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
chDbgAssert(TRUE, "gpt_lld_start(), #3", "invalid GPT device");
|
||||
cmr |= AT91C_TC_CLKS_TIMER_DIV5_CLOCK;
|
||||
break;
|
||||
case GPT_CLOCK_RE_TC1:
|
||||
case GPT_CLOCK_FE_TC1:
|
||||
if ((gptp->config->clocksource & 1)) cmr |= AT91C_TC_CLKI;
|
||||
#if AT91_GPT_USE_TC0
|
||||
if (gptp == &GPTD1) {
|
||||
cmr |= AT91C_TC_CLKS_XC0;
|
||||
bmr = (bmr & ~AT91C_TCB_TC0XC0S) | AT91C_TCB_TC0XC0S_TIOA1;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#if AT91_GPT_USE_TC1
|
||||
if (gptp == &GPTD2) {
|
||||
chDbgAssert(TRUE, "gpt_lld_start(), #4", "invalid clock");
|
||||
cmr |= AT91C_TC_CLKS_XC1;
|
||||
bmr = (bmr & ~AT91C_TCB_TC1XC1S) | AT91C_TCB_TC1XC1S_NONE;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#if AT91_GPT_USE_TC2
|
||||
if (gptp == &GPTD3) {
|
||||
cmr |= AT91C_TC_CLKS_XC2;
|
||||
bmr = (bmr & ~AT91C_TCB_TC2XC2S) | AT91C_TCB_TC2XC2S_TIOA1;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
chDbgAssert(TRUE, "gpt_lld_start(), #5", "invalid GPT device");
|
||||
cmr |= AT91C_TC_CLKS_TIMER_DIV5_CLOCK;
|
||||
break;
|
||||
case GPT_CLOCK_RE_TC2:
|
||||
case GPT_CLOCK_FE_TC2:
|
||||
if ((gptp->config->clocksource & 1)) cmr |= AT91C_TC_CLKI;
|
||||
#if AT91_GPT_USE_TC0
|
||||
if (gptp == &GPTD1) {
|
||||
cmr |= AT91C_TC_CLKS_XC0;
|
||||
bmr = (bmr & ~AT91C_TCB_TC0XC0S) | AT91C_TCB_TC0XC0S_TIOA2;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#if AT91_GPT_USE_TC1
|
||||
if (gptp == &GPTD2) {
|
||||
cmr |= AT91C_TC_CLKS_XC1;
|
||||
bmr = (bmr & ~AT91C_TCB_TC1XC1S) | AT91C_TCB_TC1XC1S_TIOA2;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#if AT91_GPT_USE_TC2
|
||||
if (gptp == &GPTD3) {
|
||||
chDbgAssert(TRUE, "gpt_lld_start(), #6", "invalid clock");
|
||||
cmr |= AT91C_TC_CLKS_XC2;
|
||||
bmr = (bmr & ~AT91C_TCB_TC2XC2S) | AT91C_TCB_TC2XC2S_NONE;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
chDbgAssert(TRUE, "gpt_lld_start(), #7", "invalid GPT device");
|
||||
cmr |= AT91C_TC_CLKS_TIMER_DIV5_CLOCK;
|
||||
break;
|
||||
default:
|
||||
chDbgAssert(TRUE, "gpt_lld_start(), #8", "invalid clock");
|
||||
cmr |= AT91C_TC_CLKS_TIMER_DIV5_CLOCK;
|
||||
break;
|
||||
}
|
||||
|
||||
// Calculate clock gating
|
||||
chDbgAssert(gptp->config->clockgate == GPT_GATE_NONE || gptp->config->clockgate == GPT_GATE_TCLK0
|
||||
|| gptp->config->clockgate == GPT_GATE_TCLK1 || gptp->config->clockgate == GPT_GATE_TCLK2
|
||||
, "gpt_lld_start(), #9", "invalid clockgate");
|
||||
cmr |= ((uint32_t)(gptp->config->clockgate & 0x03)) << 4; // special magic numbers here
|
||||
|
||||
// Calculate triggers
|
||||
chDbgAssert(gptp->config->trigger == GPT_TRIGGER_NONE
|
||||
|| gptp->config->trigger == GPT_TRIGGER_RE_TIOB || gptp->config->trigger == GPT_TRIGGER_FE_TIOB || gptp->config->trigger == GPT_TRIGGER_BE_TIOB
|
||||
|| gptp->config->trigger == GPT_TRIGGER_RE_TCLK0 || gptp->config->trigger == GPT_TRIGGER_FE_TCLK0 || gptp->config->trigger == GPT_TRIGGER_BE_TCLK0
|
||||
|| gptp->config->trigger == GPT_TRIGGER_RE_TCLK1 || gptp->config->trigger == GPT_TRIGGER_FE_TCLK1 || gptp->config->trigger == GPT_TRIGGER_BE_TCLK1
|
||||
|| gptp->config->trigger == GPT_TRIGGER_RE_TCLK2 || gptp->config->trigger == GPT_TRIGGER_FE_TCLK2 || gptp->config->trigger == GPT_TRIGGER_BE_TCLK2
|
||||
, "gpt_lld_start(), #10", "invalid trigger");
|
||||
cmr |= ((uint32_t)(gptp->config->trigger & 0x03)) << 10; // special magic numbers here
|
||||
cmr |= ((uint32_t)(gptp->config->trigger & 0x30)) << (8-4); // special magic numbers here
|
||||
|
||||
/* Set everything up but disabled */
|
||||
gptp->tc->TC_CCR = AT91C_TC_CLKDIS;
|
||||
gptp->tc->TC_IDR = 0xFFFFFFFF;
|
||||
gptp->tc->TC_CMR = cmr;
|
||||
gptp->tc->TC_RC = rc;
|
||||
gptp->tc->TC_RA = rc/2;
|
||||
*AT91C_TCB_BMR = bmr;
|
||||
cmr = gptp->tc->TC_SR; // Clear any pending interrupts
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Deactivates the GPT peripheral.
|
||||
*
|
||||
* @param[in] gptp pointer to the @p GPTDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void gpt_lld_stop(GPTDriver *gptp) {
|
||||
gptp->tc->TC_CCR = AT91C_TC_CLKDIS;
|
||||
gptp->tc->TC_IDR = 0xFFFFFFFF;
|
||||
{ uint32_t isr = gptp->tc->TC_SR; (void)isr; }
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Starts the timer in continuous mode.
|
||||
*
|
||||
* @param[in] gptp pointer to the @p GPTDriver object
|
||||
* @param[in] interval period in ticks
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void gpt_lld_start_timer(GPTDriver *gptp, gptcnt_t interval) {
|
||||
|
||||
if (gptp->config->clocksource != GPT_CLOCK_FREQUENCY) {
|
||||
gptp->tc->TC_RC = interval;
|
||||
gptp->tc->TC_RA = interval/2;
|
||||
}
|
||||
gptp->tc->TC_CMR &= ~AT91C_TC_CPCDIS;
|
||||
gptp->tc->TC_CCR = AT91C_TC_CLKEN|AT91C_TC_SWTRG;
|
||||
gptp->tc->TC_IER = AT91C_TC_CPCS|AT91C_TC_COVFS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stops the timer.
|
||||
*
|
||||
* @param[in] gptp pointer to the @p GPTDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void gpt_lld_stop_timer(GPTDriver *gptp) {
|
||||
gptp->tc->TC_CCR = AT91C_TC_CLKDIS;
|
||||
gptp->tc->TC_IDR = 0xFFFFFFFF;
|
||||
{ uint32_t isr = gptp->tc->TC_SR; (void)isr; }
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Changes the interval of GPT peripheral.
|
||||
* @details This function changes the interval of a running GPT unit.
|
||||
* @pre The GPT unit must have been activated using @p gptStart().
|
||||
* @pre The GPT unit must have been running in continuous mode using
|
||||
* @p gptStartContinuous().
|
||||
* @post The GPT unit interval is changed to the new value.
|
||||
* @note The function has effect at the next cycle start.
|
||||
*
|
||||
* @param[in] gptp pointer to a @p GPTDriver object
|
||||
* @param[in] interval new cycle time in timer ticks
|
||||
* @notapi
|
||||
*/
|
||||
void gpt_lld_change_interval(GPTDriver *gptp, gptcnt_t interval) {
|
||||
if (gptp->config->clocksource != GPT_CLOCK_FREQUENCY) {
|
||||
gptp->tc->TC_RC = interval;
|
||||
gptp->tc->TC_RA = interval/2;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Starts the timer in one shot mode and waits for completion.
|
||||
* @details This function specifically polls the timer waiting for completion
|
||||
* in order to not have extra delays caused by interrupt servicing,
|
||||
* this function is only recommended for short delays.
|
||||
*
|
||||
* @param[in] gptp pointer to the @p GPTDriver object
|
||||
* @param[in] interval time interval in ticks
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void gpt_lld_polled_delay(GPTDriver *gptp, gptcnt_t interval) {
|
||||
|
||||
if (gptp->config->clocksource != GPT_CLOCK_FREQUENCY) {
|
||||
gptp->tc->TC_RC = interval;
|
||||
gptp->tc->TC_RA = interval/2;
|
||||
}
|
||||
gptp->tc->TC_CMR |= AT91C_TC_CPCDIS;
|
||||
gptp->tc->TC_CCR = AT91C_TC_CLKEN|AT91C_TC_SWTRG;
|
||||
while (!(gptp->tc->TC_SR & (AT91C_TC_CPCS|AT91C_TC_COVFS)));
|
||||
}
|
||||
|
||||
#endif /* HAL_USE_GPT */
|
||||
|
||||
/** @} */
|
|
@ -0,0 +1,230 @@
|
|||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
|
||||
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 AT91SAM7/gpt_lld.h
|
||||
* @brief AT91SAM7 GPT subsystem low level driver header.
|
||||
*
|
||||
* @addtogroup GPT
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _GPT_LLD_H_
|
||||
#define _GPT_LLD_H_
|
||||
|
||||
#if HAL_USE_GPT || defined(__DOXYGEN__)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver constants. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver pre-compile time settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @name Configuration options
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @brief GPTD1 driver enable switch.
|
||||
* @details If set to @p TRUE the support for GPTD1 is included.
|
||||
* @note The default is @p TRUE.
|
||||
*/
|
||||
#if !defined(AT91_GPT_USE_TC0) || defined(__DOXYGEN__)
|
||||
#define AT91_GPT_USE_TC0 FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief GPTD2 driver enable switch.
|
||||
* @details If set to @p TRUE the support for GPTD2 is included.
|
||||
* @note The default is @p TRUE.
|
||||
*/
|
||||
#if !defined(AT91_GPT_USE_TC1) || defined(__DOXYGEN__)
|
||||
#define AT91_GPT_USE_TC1 FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief GPTD3 driver enable switch.
|
||||
* @details If set to @p TRUE the support for GPTD3 is included.
|
||||
* @note The default is @p TRUE.
|
||||
*/
|
||||
#if !defined(AT91_GPT_USE_TC2) || defined(__DOXYGEN__)
|
||||
#define AT91_GPT_USE_TC3 FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief GPTD1 interrupt priority level setting.
|
||||
*/
|
||||
#if !defined(AT91_GPT_TC0_IRQ_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define AT91_GPT_TC0_IRQ_PRIORITY (AT91C_AIC_PRIOR_HIGHEST - 2)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief GPTD2 interrupt priority level setting.
|
||||
*/
|
||||
#if !defined(AT91_GPT_TC1_IRQ_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define AT91_GPT_TC1_IRQ_PRIORITY (AT91C_AIC_PRIOR_HIGHEST - 2)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief GPTD3 interrupt priority level setting.
|
||||
*/
|
||||
#if !defined(AT91_GPT_TC2_IRQ_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define AT91_GPT_TC2_IRQ_PRIORITY (AT91C_AIC_PRIOR_HIGHEST - 2)
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Derived constants and error checks. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if !AT91_GPT_USE_TC0 && !AT91_GPT_USE_TC1 && !AT91_GPT_USE_TC2
|
||||
#error "GPT driver activated but no TC peripheral assigned"
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver data structures and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief GPT frequency type.
|
||||
*/
|
||||
typedef uint32_t gptfreq_t;
|
||||
|
||||
/**
|
||||
* @brief GPT counter type.
|
||||
*/
|
||||
typedef uint16_t gptcnt_t;
|
||||
|
||||
/**
|
||||
* @brief Driver configuration structure.
|
||||
* @note It could be empty on some architectures.
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* @brief Timer clock in Hz.
|
||||
* @note The low level can use assertions in order to catch invalid
|
||||
* frequency specifications.
|
||||
*/
|
||||
gptfreq_t frequency;
|
||||
/**
|
||||
* @brief Timer callback pointer.
|
||||
* @note This callback is invoked on GPT counter events.
|
||||
*/
|
||||
gptcallback_t callback;
|
||||
/* End of the mandatory fields.*/
|
||||
/**
|
||||
* @brief Timer Clock Source.
|
||||
*/
|
||||
uint8_t clocksource;
|
||||
#define GPT_CLOCK_MCLK 0 // @< Internal clock. frequency must = MCLK/2, MCLK/8, MCLK/32, MCLK/128 or MCLK/1024
|
||||
#define GPT_CLOCK_FREQUENCY 1 // @< Internal clock. interval is ignored. frequency determines rate
|
||||
#define GPT_CLOCK_RE_TCLK0 2 // @< External TCLK0. Rising Edge
|
||||
#define GPT_CLOCK_FE_TCLK0 3 // @< External TCLK0. Falling Edge
|
||||
#define GPT_CLOCK_RE_TCLK1 4 // @< External TCLK1. Rising Edge
|
||||
#define GPT_CLOCK_FE_TCLK1 5 // @< External TCLK1. Falling Edge
|
||||
#define GPT_CLOCK_RE_TCLK2 6 // @< External TCLK2. Rising Edge
|
||||
#define GPT_CLOCK_FE_TCLK2 7 // @< External TCLK2. Falling Edge
|
||||
#define GPT_CLOCK_RE_TC0 8 // @< TC0 output. Rising Edge. Do not use on TC0
|
||||
#define GPT_CLOCK_FE_TC0 9 // @< TC0 output. Falling Edge. Do not use on TC0
|
||||
#define GPT_CLOCK_RE_TC1 10 // @< TC1 output. Rising Edge. Do not use on TC1
|
||||
#define GPT_CLOCK_FE_TC1 11 // @< TC1 output. Falling Edge. Do not use on TC1
|
||||
#define GPT_CLOCK_RE_TC2 12 // @< TC2 output. Rising Edge. Do not use on TC2
|
||||
#define GPT_CLOCK_FE_TC2 13 // @< TC2 output. Falling Edge. Do not use on TC2
|
||||
uint8_t clockgate;
|
||||
#define GPT_GATE_NONE 0 // @< Clock gating off
|
||||
#define GPT_GATE_TCLK0 1 // @< Clock on TCLK0 active high signal. If using this on TC0 with GPT_CLOCK_xx_TIMx, the TIMx output will be used instead.
|
||||
#define GPT_GATE_TCLK1 2 // @< Clock on TCLK1 active high signal. If using this on TC1 with GPT_CLOCK_xx_TIMx, the TIMx output will be used instead.
|
||||
#define GPT_GATE_TCLK2 3 // @< Clock on TCLK2 active high signal. If using this on TC2 with GPT_CLOCK_xx_TIMx, the TIMx output will be used instead.
|
||||
uint8_t trigger;
|
||||
#define GPT_TRIGGER_NONE 0x00 // @< Start immediately
|
||||
#define GPT_TRIGGER_RE_TIOB 0x10 // @< Start on TIOB signal. Rising Edge.
|
||||
#define GPT_TRIGGER_FE_TIOB 0x20 // @< Start on TIOB signal. Falling Edge.
|
||||
#define GPT_TRIGGER_BE_TIOB 0x30 // @< Start on TIOB signal. Both Edges.
|
||||
#define GPT_TRIGGER_RE_TCLK0 0x11 // @< Start on TCLK0 signal. Rising Edge. If using this on TC0 with GPT_CLOCK_xx_TIMx, the TIMx output will be used instead.
|
||||
#define GPT_TRIGGER_FE_TCLK0 0x21 // @< Start on TCLK0 signal. Falling Edge. If using this on TC0 with GPT_CLOCK_xx_TIMx, the TIMx output will be used instead.
|
||||
#define GPT_TRIGGER_BE_TCLK0 0x31 // @< Start on TCLK0 signal. Both Edges. If using this on TC0 with GPT_CLOCK_xx_TIMx, the TIMx output will be used instead.
|
||||
#define GPT_TRIGGER_RE_TCLK1 0x12 // @< Start on TCLK1 signal. Rising Edge. If using this on TC1 with GPT_CLOCK_xx_TIMx, the TIMx output will be used instead.
|
||||
#define GPT_TRIGGER_FE_TCLK1 0x22 // @< Start on TCLK1 signal. Falling Edge. If using this on TC1 with GPT_CLOCK_xx_TIMx, the TIMx output will be used instead.
|
||||
#define GPT_TRIGGER_BE_TCLK1 0x32 // @< Start on TCLK1 signal. Both Edges. If using this on TC1 with GPT_CLOCK_xx_TIMx, the TIMx output will be used instead.
|
||||
#define GPT_TRIGGER_RE_TCLK2 0x13 // @< Start on TCLK2 signal. Rising Edge. If using this on TC2 with GPT_CLOCK_xx_TIMx, the TIMx output will be used instead.
|
||||
#define GPT_TRIGGER_FE_TCLK2 0x23 // @< Start on TCLK2 signal. Falling Edge. If using this on TC2 with GPT_CLOCK_xx_TIMx, the TIMx output will be used instead.
|
||||
#define GPT_TRIGGER_BE_TCLK2 0x33 // @< Start on TCLK2 signal. Both Edges. If using this on TC2 with GPT_CLOCK_xx_TIMx, the TIMx output will be used instead.
|
||||
} GPTConfig;
|
||||
|
||||
/**
|
||||
* @brief Structure representing a GPT driver.
|
||||
*/
|
||||
struct GPTDriver {
|
||||
/**
|
||||
* @brief Driver state.
|
||||
*/
|
||||
gptstate_t state;
|
||||
/**
|
||||
* @brief Current configuration data.
|
||||
*/
|
||||
const GPTConfig *config;
|
||||
#if defined(GPT_DRIVER_EXT_FIELDS)
|
||||
GPT_DRIVER_EXT_FIELDS
|
||||
#endif
|
||||
/* End of the mandatory fields.*/
|
||||
/**
|
||||
* @brief Pointer to the TCx registers block.
|
||||
*/
|
||||
AT91S_TC *tc;
|
||||
};
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver macros. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* External declarations. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if AT91_GPT_USE_TC0 && !defined(__DOXYGEN__)
|
||||
extern GPTDriver GPTD1;
|
||||
#endif
|
||||
|
||||
#if AT91_GPT_USE_TC1 && !defined(__DOXYGEN__)
|
||||
extern GPTDriver GPTD2;
|
||||
#endif
|
||||
|
||||
#if AT91_GPT_USE_TC2 && !defined(__DOXYGEN__)
|
||||
extern GPTDriver GPTD3;
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void gpt_lld_init(void);
|
||||
void gpt_lld_start(GPTDriver *gptp);
|
||||
void gpt_lld_stop(GPTDriver *gptp);
|
||||
void gpt_lld_start_timer(GPTDriver *gptp, gptcnt_t period);
|
||||
void gpt_lld_stop_timer(GPTDriver *gptp);
|
||||
void gpt_lld_change_interval(GPTDriver *gptp, gptcnt_t interval);
|
||||
void gpt_lld_polled_delay(GPTDriver *gptp, gptcnt_t interval);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* HAL_USE_GPT */
|
||||
|
||||
#endif /* _GPT_LLD_H_ */
|
||||
|
||||
/** @} */
|
|
@ -9,6 +9,7 @@ PLATFORMSRC = ${CHIBIOS}/os/hal/platforms/AT91SAM7/hal_lld.c \
|
|||
${CHIBIOS}/os/hal/platforms/AT91SAM7/mac_lld.c \
|
||||
${CHIBIOS}/os/hal/platforms/AT91SAM7/pwm_lld.c \
|
||||
${CHIBIOS}/os/hal/platforms/AT91SAM7/can_lld.c \
|
||||
${CHIBIOS}/os/hal/platforms/AT91SAM7/gpt_lld.c \
|
||||
${CHIBIOS}/os/hal/platforms/AT91SAM7/at91sam7_mii.c \
|
||||
${CHIBIOS}/os/hal/platforms/AT91SAM7/at91lib/aic.c
|
||||
|
||||
|
|
Loading…
Reference in New Issue