From 8912d9fea23f516281c150fb5f3a101f4338a37d Mon Sep 17 00:00:00 2001 From: gdisirio Date: Sun, 30 Oct 2011 10:09:16 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@3457 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/platforms/AT91SAM7/ext_lld.c | 238 ++++++++++++++++++++++++++++++++ os/hal/platforms/AT91SAM7/ext_lld.h | 249 ++++++++++++++++++++++++++++++++++ os/hal/platforms/AT91SAM7/platform.mk | 1 + 3 files changed, 488 insertions(+) create mode 100644 os/hal/platforms/AT91SAM7/ext_lld.c create mode 100644 os/hal/platforms/AT91SAM7/ext_lld.h (limited to 'os/hal/platforms/AT91SAM7') diff --git a/os/hal/platforms/AT91SAM7/ext_lld.c b/os/hal/platforms/AT91SAM7/ext_lld.c new file mode 100644 index 000000000..2dbfc1562 --- /dev/null +++ b/os/hal/platforms/AT91SAM7/ext_lld.c @@ -0,0 +1,238 @@ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, + 2011 Giovanni Di Sirio, + 2011 Florian Goebe, Chair for Computer Science 11, + RWTH Aachen University + + This file is part of ChibiOS/RT. + + ChibiOS/RT is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/RT 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. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ + +/** + * @file STM32/ext_lld.c + * @brief STM32 EXT subsystem low level driver source. + * + * @addtogroup EXT + * @{ + */ + +#include "ch.h" +#include "hal.h" + +#if HAL_USE_EXT || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** + * @brief EXTDA driver identifier. + */ +EXTDriver EXTDA; + +#if (SAM7_PLATFORM == SAM7X128) || (SAM7_PLATFORM == SAM7X256) || \ + (SAM7_PLATFORM == SAM7X512) +/** + * @brief EXTDB driver identifier. + */ +EXTDriver EXTDB; +#endif + +/*===========================================================================*/ +/* Driver local variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Handles external interrupts. + * + * @param[in] extp pointer to the driver that received the interrupt + */ +static void ext_lld_serveInterrupt(EXTDriver *extp) { + uint32_t irqFlags; + uint32_t ch; + + chSysLockFromIsr(); + + /* Read flags of pending PIO interrupts.*/ + irqFlags = extp->pio->PIO_ISR; + + /* Call callback function for any pending interrupt.*/ + for(ch = 0; ch < 32; ch++) { + + /* Check if the channel is activated and if its IRQ flag is set.*/ + if((extp->config->channels[ch].mode & + EXT_CH_MODE_ENABLED & EXT_CH_MODE_EDGES_MASK) + && ((1 << ch) & irqFlags)) { + (extp->config->channels[ch].cb)(extp, ch); + } + } + + chSysUnlockFromIsr(); + + AT91C_BASE_AIC->AIC_EOICR = 0; +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/** + * @brief EXTI[0] interrupt handler. + * + * @isr + */ +CH_IRQ_HANDLER(EXTIA_IRQHandler) { + + CH_IRQ_PROLOGUE(); + + ext_lld_serveInterrupt(&EXTDA); + + CH_IRQ_EPILOGUE(); +} + +#if (SAM7_PLATFORM == SAM7X128) || (SAM7_PLATFORM == SAM7X256) || \ + (SAM7_PLATFORM == SAM7X512) +/** + * @brief EXTI[1] interrupt handler. + * + * @isr + */ +CH_IRQ_HANDLER(EXTIB_IRQHandler) { + CH_IRQ_PROLOGUE(); + + ext_lld_serveInterrupt(&EXTDB); + + CH_IRQ_EPILOGUE(); +} +#endif + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level EXT driver initialization. + * + * @notapi + */ +void ext_lld_init(void) { + + /* Driver initialization.*/ + extObjectInit(&EXTDA); + + /* Set PIO base addresses.*/ + EXTDA.pio = AT91C_BASE_PIOA; + + /* Set peripheral IDs.*/ + EXTDA.pid = AT91C_ID_PIOA; + +#if (SAM7_PLATFORM == SAM7X128) || (SAM7_PLATFORM == SAM7X256) || \ + (SAM7_PLATFORM == SAM7X512) + /* Aame for PIOB.*/ + extObjectInit(&EXTDB); + EXTDB.pio = AT91C_BASE_PIOB; + EXTDB.pid = AT91C_ID_PIOB; +#endif +} + +/** + * @brief Configures and activates the EXT peripheral. + * + * @param[in] extp pointer to the @p EXTDriver object + * + * @notapi + */ +void ext_lld_start(EXTDriver *extp) { + uint16_t ch; + uint32_t ier = 0; + const EXTConfig *config = extp->config; + + switch(extp->pid) { + case AT91C_ID_PIOA: + AIC_ConfigureIT(AT91C_ID_PIOA, SAM7_computeSMR(config->mode, + config->priority), + EXTIA_IRQHandler); + break; +#if (SAM7_PLATFORM == SAM7X128) || (SAM7_PLATFORM == SAM7X256) || \ + (SAM7_PLATFORM == SAM7X512) + case AT91C_ID_PIOB: + AIC_ConfigureIT(AT91C_ID_PIOB, SAM7_computeSMR(config->mode, + config->priority), + EXTIB_IRQHandler); + break; +#endif + } + + /* Enable and Disable channels with respect to config.*/ + for(ch = 0; ch < EXT_MAX_CHANNELS; ch++) { + ier |= (config->channels[ch].mode & EXT_CH_MODE_EDGES_MASK & EXT_CH_MODE_ENABLED ? 1 : 0) << ch; + } + extp->pio->PIO_IER = ier; + extp->pio->PIO_IDR = ~ier; + + /* Enable interrupt on corresponding PIO port in AIC.*/ + AIC_EnableIT(extp->pid); +} + +/** + * @brief Deactivates the EXT peripheral. + * + * @param[in] extp pointer to the @p EXTDriver object + * + * @notapi + */ +void ext_lld_stop(EXTDriver *extp) { + + /* Disable interrupt on corresponding PIO port in AIC.*/ + AIC_DisableIT(extp->pid); +} + +/** + * @brief Enables an EXT channel. + * + * @param[in] extp pointer to the @p EXTDriver object + * @param[in] channel channel to be enabled + * + * @notapi + */ +void ext_lld_channel_enable(EXTDriver *extp, expchannel_t channel) { + + extp->pio->PIO_IER = (1 << channel); +} + +/** + * @brief Disables an EXT channel. + * + * @param[in] extp pointer to the @p EXTDriver object + * @param[in] channel channel to be disabled + * + * @notapi + */ +void ext_lld_channel_disable(EXTDriver *extp, expchannel_t channel) { + + extp->pio->PIO_IDR = (1 << channel); +} + +#endif /* HAL_USE_EXT */ + +/** @} */ diff --git a/os/hal/platforms/AT91SAM7/ext_lld.h b/os/hal/platforms/AT91SAM7/ext_lld.h new file mode 100644 index 000000000..4c8442481 --- /dev/null +++ b/os/hal/platforms/AT91SAM7/ext_lld.h @@ -0,0 +1,249 @@ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, + 2011 Giovanni Di Sirio, + 2011 Florian Goebe, Chair for Computer Science 11, + RWTH Aachen University + + This file is part of ChibiOS/RT. + + ChibiOS/RT is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/RT 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. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file AT91SAM7/ext_lld.h + * @brief AT91SAM7 EXT subsystem low level driver header. + * + * @addtogroup EXT + * @{ + */ + +#ifndef _EXT_LLD_H_ +#define _EXT_LLD_H_ + +#if HAL_USE_EXT || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @brief Pointer to the SAM7 AIC register block. + */ +#define SAM7_EXT_AIC ((AT91PS_AIC *)AT91C_BASE_AIC) + +/** + * @brief Number of channels within one ext driver. + */ +#define EXT_MAX_CHANNELS 32 + +/** + * @brief Mask of priority bits in interrupt mode register. + */ +#define SAM7_EXT_PRIORITY_MASK 0x00000007 + +/** + * @brief Shifter for priority bits in interrupt mode register. + */ +#define SAM7_EXT_PRIORITY_SHIFTER 0 + +/** + * @brief Shifter for mode bits in interrupt mode register. + */ +#define SAM7_EXT_MODE_SHIFTER 5 + +/* + * On the SAM7 architecture, a single channel can only be enables or disabled + * Hence, undefine the other channel mode constants + */ +#ifdef EXT_CH_MODE_RISING_EDGE +#undef EXT_CH_MODE_RISING_EDGE +#endif + +#ifdef EXT_CH_MODE_FALLING_EDGE +#undef EXT_CH_MODE_FALLING_EDGE +#endif + +#ifdef EXT_CH_MODE_BOTH_EDGES +#undef EXT_CH_MODE_BOTH_EDGES +#endif + +/** + * @name EXT channels mode + * @{ + */ +#define EXT_CH_MODE_ENABLED 1 /**< @brief Channel is enabled. */ +/** @} */ + +/** + * @name EXT drivers mode + * @{ + */ +/** + * @brief Mask for modes. + */ +#define SAM7_EXT_MODE_MASK AT91C_AIC_SRCTYPE +/** + * @brief Falling edge callback. + */ +#define SAM7_EXT_MODE_FALLING_EDGE AT91C_AIC_SRCTYPE_EXT_NEGATIVE_EDGE +/** + * @brief Rising edge callback. + */ +#define SAM7_EXT_MODE_RISING_EDGE AT91C_AIC_SRCTYPE_POSITIVE_EDGE +/** + * @brief High-level callback. + */ +#define SAM7_EXT_MODE_HIGH_LEVEL AT91C_AIC_SRCTYPE_HIGH_LEVEL +/** + * @brief Low-level callback. + */ +#define SAM7_EXT_MODE_LOW_LEVEL AT91C_AIC_SRCTYPE_EXT_LOW_LEVEL +/** @} */ + +/** + * @name EXT drivers priorities + * @{ + */ +#define SAM7_EXT_PRIOR_HIGHEST AT91C_AIC_PRIOR_HIGHEST +#define SAM7_EXT_PRIOR_LOWEST AT91C_AIC_PRIOR_LOWEST +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief EXT channel identifier. + */ +typedef uint32_t expchannel_t; + +/** + * @brief Type of an EXT generic notification callback. + * + * @param[in] extp pointer to the @p EXPDriver object triggering the + * callback + */ +typedef void (*extcallback_t)(EXTDriver *extp, expchannel_t channel); + +/** + * @brief Channel configuration structure. + */ +typedef struct { + /** + * @brief Channel mode. + */ + uint32_t mode; + /** + * @brief Channel callback. + * @details In the STM32 implementation a @p NULL callback pointer is + * valid and configures the channel as an event sources instead + * of an interrupt source. + */ + extcallback_t cb; +} EXTChannelConfig; + +/** + * @brief Driver configuration structure. + * @note It could be empty on some architectures. + */ +typedef struct { + /** + * @brief Channel configurations. + */ + EXTChannelConfig channels[EXT_MAX_CHANNELS]; + /* End of the mandatory fields.*/ + + /** + * @brief interrupt mode. + */ + uint32_t mode; + + /** + * @brief interrupt priority. + */ + uint32_t priority; +} EXTConfig; + +/** + * @brief Structure representing an EXT driver. + */ +struct EXTDriver { + /** + * @brief Driver state. + */ + extstate_t state; + /** + * @brief Current configuration data. + */ + const EXTConfig *config; + /* End of the mandatory fields.*/ + /** + * @brief Pointer to the corresponding PIO registers block. + */ + AT91PS_PIO pio; + /** + * @brief peripheral ID of the corresponding PIO block. + */ + uint32_t pid; +}; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @brief Computes the content for the interrupt source mode register. + */ +#define SAM7_computeSMR(mode, prio) ( \ + ((mode & SAM7_EXT_MODE_MASK) << SAM7_EXT_MODE_SHIFTER) | \ + ((prio & SAM7_EXT_PRIORITY_MASK) << SAM7_EXT_PRIORITY_SHIFTER) \ +) + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if !defined(__DOXYGEN__) +extern EXTDriver EXTDA; +#if (SAM7_PLATFORM == SAM7X128) || (SAM7_PLATFORM == SAM7X256) || \ + (SAM7_PLATFORM == SAM7X512) +extern EXTDriver EXTDB; +#endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void ext_lld_init(void); + void ext_lld_start(EXTDriver *extp); + void ext_lld_stop(EXTDriver *extp); + void ext_lld_channel_enable(EXTDriver *extp, expchannel_t channel); + void ext_lld_channel_disable(EXTDriver *extp, expchannel_t channel); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_EXT */ + +#endif /* _EXT_LLD_H_ */ + +/** @} */ diff --git a/os/hal/platforms/AT91SAM7/platform.mk b/os/hal/platforms/AT91SAM7/platform.mk index 9a5bba436..83b53491a 100644 --- a/os/hal/platforms/AT91SAM7/platform.mk +++ b/os/hal/platforms/AT91SAM7/platform.mk @@ -1,6 +1,7 @@ # List of all the AT91SAM7 platform files. PLATFORMSRC = ${CHIBIOS}/os/hal/platforms/AT91SAM7/hal_lld.c \ ${CHIBIOS}/os/hal/platforms/AT91SAM7/pal_lld.c \ + ${CHIBIOS}/os/hal/platforms/AT91SAM7/ext_lld.c \ ${CHIBIOS}/os/hal/platforms/AT91SAM7/serial_lld.c \ ${CHIBIOS}/os/hal/platforms/AT91SAM7/spi_lld.c \ ${CHIBIOS}/os/hal/platforms/AT91SAM7/mac_lld.c \ -- cgit v1.2.3