From 5b0e38c8282e92e4a6b88dd8e2af41ef67b56f15 Mon Sep 17 00:00:00 2001 From: Fabio Utzig Date: Sun, 23 Oct 2016 10:53:37 +0000 Subject: Added EXT driver git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@9871 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/include/hal_ext.h | 1 + os/hal/ports/AVR/hal_ext_lld.c | 374 +++++++++++++++++++++++++++++++++++++++++ os/hal/ports/AVR/hal_ext_lld.h | 136 +++++++++++++++ os/hal/ports/AVR/platform.mk | 1 + 4 files changed, 512 insertions(+) create mode 100644 os/hal/ports/AVR/hal_ext_lld.c create mode 100644 os/hal/ports/AVR/hal_ext_lld.h (limited to 'os/hal') diff --git a/os/hal/include/hal_ext.h b/os/hal/include/hal_ext.h index c93a4ce97..2d92a4d68 100644 --- a/os/hal/include/hal_ext.h +++ b/os/hal/include/hal_ext.h @@ -40,6 +40,7 @@ #define EXT_CH_MODE_RISING_EDGE 1U /**< @brief Rising edge callback. */ #define EXT_CH_MODE_FALLING_EDGE 2U /**< @brief Falling edge callback. */ #define EXT_CH_MODE_BOTH_EDGES 3U /**< @brief Both edges callback. */ +#define EXT_CH_MODE_LOW_LEVEL 5U /**< @brief low level callback. */ #define EXT_CH_MODE_AUTOSTART 4U /**< @brief Channel started automatically on driver start. */ diff --git a/os/hal/ports/AVR/hal_ext_lld.c b/os/hal/ports/AVR/hal_ext_lld.c new file mode 100644 index 000000000..61582d38b --- /dev/null +++ b/os/hal/ports/AVR/hal_ext_lld.c @@ -0,0 +1,374 @@ +/* + ChibiOS - Copyright (C) 2016 Theodore Ateba + + 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 AVR/hal_ext_lld.c + * @brief AVR EXT subsystem low level driver source. + * + * @addtogroup EXT + * @{ + */ + +#include "hal.h" + +#if HAL_USE_EXT || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** + * @brief EXTD1 driver identifier. + */ +EXTDriver EXTD1; + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Set the INTx interrupt trigger front or state. + * + * @param[in] channel the channel to configure + * @param[in] edge the front or state to configure + */ +void ext_lld_set_intx_edges(expchannel_t channel, uint8_t edge) { +#if AVR_EXT_USE_INT0 || defined(__DOXYGEN__) + if (channel == INT0) { + if (edge == EXT_CH_MODE_RISING_EDGE) { + EICRA |= (1 << 0); + EICRA |= (1 << 1); + } else if (edge == EXT_CH_MODE_FALLING_EDGE) { + EICRA &= ~(1 << 0); + EICRA |= (1 << 1); + } else if (edge == EXT_CH_MODE_BOTH_EDGES) { + EICRA |= (1 << 0); + EICRA &= ~(1 << 1); + } else { + EICRA &= ~(1 << 0); + EICRA &= ~(1 << 1); + } + } +#endif +#if AVR_EXT_USE_INT1 || defined(__DOXYGEN__) + if (channel == INT1) { + if (edge == EXT_CH_MODE_RISING_EDGE) { + EICRA |= (1 << 2); + EICRA |= (1 << 3); + } else if (edge == EXT_CH_MODE_FALLING_EDGE) { + EICRA &= ~(1 << 2); + EICRA |= (1 << 3); + } else if (edge == EXT_CH_MODE_BOTH_EDGES) { + EICRA |= (1 << 2); + EICRA &= ~(1 << 3); + } else { + EICRA &= ~(1 << 2); + EICRA &= ~(1 << 3); + } + } +#endif +#if AVR_EXT_USE_INT2 || defined(__DOXYGEN__) + if (channel == INT2) { + if (edge == EXT_CH_MODE_RISING_EDGE) { + EICRA |= (1 << 4); + EICRA |= (1 << 5); + } else if (edge == EXT_CH_MODE_FALLING_EDGE) { + EICRA &= ~(1 << 4); + EICRA |= (1 << 5); + } else if (edge == EXT_CH_MODE_BOTH_EDGES) { + EICRA |= (1 << 4); + EICRA &= ~(1 << 5); + } else { + EICRA &= ~(1 << 4); + EICRA &= ~(1 << 5); + } + } +#endif +#if AVR_EXT_USE_INT3 || defined(__DOXYGEN__) + if (channel == INT3) { + if (edge == EXT_CH_MODE_RISING_EDGE) { + EICRA |= (1 << 6); + EICRA |= (1 << 7); + } else if (edge == EXT_CH_MODE_FALLING_EDGE) { + EICRA &= ~(1 << 6); + EICRA |= (1 << 7); + } else if (edge == EXT_CH_MODE_BOTH_EDGES) { + EICRA |= (1 << 6); + EICRA &= ~(1 << 7); + } else { + EICRA &= ~(1 << 6); + EICRA &= ~(1 << 7); + } + } +#endif +#if AVR_EXT_USE_INT4 || defined(__DOXYGEN__) + if (channel == INT4) { + if (edge == EXT_CH_MODE_RISING_EDGE) { + EICRB |= (1 << 0); + EICRB |= (1 << 1); + } else if (edge == EXT_CH_MODE_FALLING_EDGE) { + EICRB &= ~(1 << 0); + EICRB |= (1 << 1); + } else if (edge == EXT_CH_MODE_BOTH_EDGES) { + EICRB |= (1 << 0); + EICRB &= ~(1 << 1); + } else { + EICRB &= ~(1 << 0); + EICRB &= ~(1 << 1); + } + } +#endif +#if AVR_EXT_USE_INT5 || defined(__DOXYGEN__) + if (channel == INT5) { + if (edge == EXT_CH_MODE_RISING_EDGE) { + EICRB |= (1 << 2); + EICRB |= (1 << 3); + } else if (edge == EXT_CH_MODE_FALLING_EDGE) { + EICRB &= ~(1 << 2); + EICRB |= (1 << 3); + } else if (edge == EXT_CH_MODE_BOTH_EDGES) { + EICRB |= (1 << 2); + EICRB &= ~(1 << 3); + } else { + EICRB &= ~(1 << 2); + EICRB &= ~(1 << 3); + } + } +#endif +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if AVR_EXT_USE_INT0 || defined(__DOXYGEN__) +/** + * @brief EXTI[INT0] interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(INT0_vect) { + OSAL_IRQ_PROLOGUE(); + EXTD1.config->channels[INT0].cb(&EXTD1, INT0); + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if AVR_EXT_USE_INT1 || defined(__DOXYGEN__) +/** + * @brief EXTI[INT1] interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(INT1_vect) { + OSAL_IRQ_PROLOGUE(); + EXTD1.config->channels[INT1].cb(&EXTD1, INT1); + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if AVR_EXT_USE_INT2 || defined(__DOXYGEN__) +/** + * @brief EXTI[INT2] interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(INT2_vect) { + OSAL_IRQ_PROLOGUE(); + EXTD1.config->channels[INT2].cb(&EXTD1, INT2); + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if AVR_EXT_USE_INT3 || defined(__DOXYGEN__) +/** + * @brief EXTI[INT3] interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(INT3_vect) { + OSAL_IRQ_PROLOGUE(); + EXTD1.config->channels[INT3].cb(&EXTD1, INT3); + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if AVR_EXT_USE_INT4 || defined(__DOXYGEN__) +/** + * @brief EXTI[INT4] interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(INT4_vect) { + OSAL_IRQ_PROLOGUE(); + EXTD1.config->channels[INT4].cb(&EXTD1, INT4); + OSAL_IRQ_EPILOGUE(); +} +#endif +#if AVR_EXT_USE_INT5 || defined(__DOXYGEN__) +/** + * @brief EXTI[INT5] interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(INT5_vect) { + OSAL_IRQ_PROLOGUE(); + EXTD1.config->channels[INT5].cb(&EXTD1, INT5); + OSAL_IRQ_EPILOGUE(); +} +#endif + +/*===========================================================================*/ +/* Driver functions. */ +/*===========================================================================*/ + +/** + * @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) { +#if AVR_EXT_USE_INT0 || defined(__DOXYGEN__) + if (channel == INT0) { + EIMSK |= 1 << INT0; + ext_lld_set_intx_edges(channel, extp->config->channels[channel].mode); + } +#endif +#if AVR_EXT_USE_INT1 || defined(__DOXYGEN__) + if (channel == INT1) { + EIMSK |= 1 << INT1; + ext_lld_set_intx_edges(channel, extp->config->channels[channel].mode); + } +#endif +#if AVR_EXT_USE_INT2 || defined(__DOXYGEN__) + if (channel == INT2) { + EIMSK |= 1 << INT2; + ext_lld_set_intx_edges(channel, extp->config->channels[channel].mode); + } +#endif +#if AVR_EXT_USE_INT3 || defined(__DOXYGEN__) + if (channel == INT3) { + EIMSK |= 1 << INT3; + ext_lld_set_intx_edges(channel, extp->config->channels[channel].mode); + } +#endif +#if AVR_EXT_USE_INT4 || defined(__DOXYGEN__) + if (channel == INT4) { + EIMSK |= 1 << INT4; + ext_lld_set_intx_edges(channel, extp->config->channels[channel].mode); + } +#endif +#if AVR_EXT_USE_INT5 || defined(__DOXYGEN__) + if (channel == INT5) { + EIMSK |= 1 << INT5; + ext_lld_set_intx_edges(channel, extp->config->channels[channel].mode); + } +#endif +} + +/** + * @brief Disables an EXT channel. + * + * @param[in] extp pinter to the @p EXTDriver object + * @param[in] channel channel to be disabled + * + * @notapi + */ +void ext_lld_channel_disable(EXTDriver *extp, expchannel_t channel) { +#if AVR_EXT_USE_INT0 || defined(__DOXYGEN__) + if (channel == INT0) + EIMSK &= ~(1 << INT0); +#endif +#if AVR_EXT_USE_INT1 || defined(__DOXYGEN__) + if (channel == INT1) + EIMSK &= ~(1 << INT1); +#endif +#if AVR_EXT_USE_INT2 || defined(__DOXYGEN__) + if (channel == INT2) + EIMSK &= ~(1 << INT2); +#endif +#if AVR_EXT_USE_INT3 || defined(__DOXYGEN__) + if (channel == INT3) + EIMSK &= ~(1 << INT3); +#endif +#if AVR_EXT_USE_INT4 || defined(__DOXYGEN__) + if (channel == INT4) + EIMSK &= ~(1 << INT4); +#endif +#if AVR_EXT_USE_INT5 || defined(__DOXYGEN__) + if (channel == INT5) + EIMSK &= ~(1 << INT5); +#endif +} + +/** + * @brief Low level EXT driver initialization. + * + * @notapi + */ +void ext_lld_init(void) { + /* Driver initialization.*/ + extObjectInit(&EXTD1); +} + +/** + * @brief Configures and activates the EXT peripheral. + * + * @param[in] extp pointer to the @p EXTDriver object + * + * @notapi + */ +void ext_lld_start(EXTDriver *extp) { + expchannel_t line; + + if (extp->state == EXT_STOP) + osalSysUnlock(); + + /* Configuration of automatic channels. */ + for (line = 0; line < EXT_MAX_CHANNELS; line++) { + if (extp->config->channels[line].mode & EXT_CH_MODE_AUTOSTART) + ext_lld_channel_enable(extp, line); + else + ext_lld_channel_disable(extp, line); + } +} + +/** + * @brief Deactivates the EXT peripheral. + * + * @param[in] extp pointer to the @p EXTDriver object + * + * @notapi + */ +void ext_lld_stop(EXTDriver *extp) { + if (extp->state == EXT_ACTIVE) + osalSysLock(); +} + +#endif /* HAL_USE_EXT */ + +/** @} */ diff --git a/os/hal/ports/AVR/hal_ext_lld.h b/os/hal/ports/AVR/hal_ext_lld.h new file mode 100644 index 000000000..1a93c2803 --- /dev/null +++ b/os/hal/ports/AVR/hal_ext_lld.h @@ -0,0 +1,136 @@ +/* + ChibiOS - Copyright (C) 2016 Theodore Ateba + + 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 AVR/hal_ext_lld.h + * @brief EXT Driver subsystem low level driver source. + * + * @addtogroup EXT + * @{ + */ + +#ifndef _HAL_EXT_LLD_H_ +#define _HAL_EXT_LLD_H_ + +#if HAL_USE_EXT || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @brief Maximum number of EXT channels. + */ +#define AVR_INT_NUM_LINES 6 /**< INT0 to INT5 */ + +/** + * @brief Available number of EXT channels. + */ +#define EXT_MAX_CHANNELS AVR_INT_NUM_LINES + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief EXT channel identifier. + */ +typedef uint16_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. + */ + 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.*/ +} 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.*/ +}; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ +extern EXTDriver EXTD1; + +#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 /* _HAL_EXT_LLD_H_ */ + +/** @} */ diff --git a/os/hal/ports/AVR/platform.mk b/os/hal/ports/AVR/platform.mk index 2b20b8a80..8c9389fdc 100644 --- a/os/hal/ports/AVR/platform.mk +++ b/os/hal/ports/AVR/platform.mk @@ -3,6 +3,7 @@ PLATFORMSRC = ${CHIBIOS}/os/hal/ports/AVR/hal_lld.c \ ${CHIBIOS}/os/hal/ports/AVR/hal_pal_lld.c \ ${CHIBIOS}/os/hal/ports/AVR/hal_serial_lld.c \ ${CHIBIOS}/os/hal/ports/AVR/hal_adc_lld.c \ + ${CHIBIOS}/os/hal/ports/AVR/hal_ext_lld.c \ ${CHIBIOS}/os/hal/ports/AVR/hal_i2c_lld.c \ ${CHIBIOS}/os/hal/ports/AVR/hal_spi_lld.c \ ${CHIBIOS}/os/hal/ports/AVR/hal_gpt_lld.c \ -- cgit v1.2.3