diff options
Diffstat (limited to 'os/hal')
| -rw-r--r-- | os/hal/platforms/AT91SAM7/gpt_lld.c | 456 | ||||
| -rw-r--r-- | os/hal/platforms/AT91SAM7/gpt_lld.h | 230 | ||||
| -rw-r--r-- | os/hal/platforms/AT91SAM7/platform.mk | 1 | 
3 files changed, 687 insertions, 0 deletions
| diff --git a/os/hal/platforms/AT91SAM7/gpt_lld.c b/os/hal/platforms/AT91SAM7/gpt_lld.c new file mode 100644 index 000000000..3d584fee3 --- /dev/null +++ b/os/hal/platforms/AT91SAM7/gpt_lld.c @@ -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 */
 +
 +/** @} */
 diff --git a/os/hal/platforms/AT91SAM7/gpt_lld.h b/os/hal/platforms/AT91SAM7/gpt_lld.h new file mode 100644 index 000000000..dc6338210 --- /dev/null +++ b/os/hal/platforms/AT91SAM7/gpt_lld.h @@ -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_ */
 +
 +/** @} */
 diff --git a/os/hal/platforms/AT91SAM7/platform.mk b/os/hal/platforms/AT91SAM7/platform.mk index 6b8438c6d..1f173f9d5 100644 --- a/os/hal/platforms/AT91SAM7/platform.mk +++ b/os/hal/platforms/AT91SAM7/platform.mk @@ -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
 | 
