aboutsummaryrefslogtreecommitdiffstats
path: root/os
diff options
context:
space:
mode:
authorgdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4>2012-04-23 17:43:42 +0000
committergdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4>2012-04-23 17:43:42 +0000
commite817b7032d9610508e39921c65cda6ba108db357 (patch)
treefc4f7dfd20f8655e87b6165a4da1f27ba134c3a4 /os
parentcdabdb46317e967dc0fa79e8c23cde3c2ffd0b10 (diff)
downloadChibiOS-e817b7032d9610508e39921c65cda6ba108db357.tar.gz
ChibiOS-e817b7032d9610508e39921c65cda6ba108db357.tar.bz2
ChibiOS-e817b7032d9610508e39921c65cda6ba108db357.zip
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@4128 35acf78f-673a-0410-8e92-d51de3d6d3f4
Diffstat (limited to 'os')
-rw-r--r--os/hal/include/ext.h26
-rw-r--r--os/hal/platforms/STM32/ext_lld.c76
-rw-r--r--os/hal/platforms/STM32/ext_lld.h39
-rw-r--r--os/hal/src/ext.c59
4 files changed, 125 insertions, 75 deletions
diff --git a/os/hal/include/ext.h b/os/hal/include/ext.h
index 56e683019..37a7dcd15 100644
--- a/os/hal/include/ext.h
+++ b/os/hal/include/ext.h
@@ -36,7 +36,7 @@
/*===========================================================================*/
/**
- * @name EXT channels modes
+ * @name EXT channel modes
* @{
*/
#define EXT_CH_MODE_EDGES_MASK 3 /**< @brief Mask of edges field. */
@@ -104,6 +104,27 @@ typedef struct EXTDriver EXTDriver;
* @iclass
*/
#define extChannelDisableI(extp, channel) ext_lld_channel_disable(extp, channel)
+
+/**
+ * @brief Changes the operation mode of a channel.
+ * @note This function attempts to write over the current configuration
+ * structure that must have been not declared constant. This
+ * violates the @p const qualifier in @p extStart() but it is
+ * intentional. This function cannot be used if the configuration
+ * structure is declared @p const.
+ *
+ * @param[in] extp pointer to the @p EXTDriver object
+ * @param[in] channel channel to be changed
+ * @param[in] extcp new configuration for the channel
+ *
+ * @api
+ */
+#define extSetChannelMode(extp, channel, extcp) { \
+ chSysLock(); \
+ extSetChannelModeI(extp, channel, extcp); \
+ chSysUnlock(); \
+}
+
/** @} */
/*===========================================================================*/
@@ -119,6 +140,9 @@ extern "C" {
void extStop(EXTDriver *extp);
void extChannelEnable(EXTDriver *extp, expchannel_t channel);
void extChannelDisable(EXTDriver *extp, expchannel_t channel);
+ void extSetChannelModeI(EXTDriver *extp,
+ expchannel_t channel,
+ const EXTChannelConfig *extcp);
#ifdef __cplusplus
}
#endif
diff --git a/os/hal/platforms/STM32/ext_lld.c b/os/hal/platforms/STM32/ext_lld.c
index 569262e75..4a3cd3c2e 100644
--- a/os/hal/platforms/STM32/ext_lld.c
+++ b/os/hal/platforms/STM32/ext_lld.c
@@ -430,7 +430,6 @@ void ext_lld_init(void) {
*/
void ext_lld_start(EXTDriver *extp) {
unsigned i;
- uint32_t imr, emr, rtsr, ftsr;
if (extp->state == EXT_STOP) {
/* Clock activation.*/
@@ -489,37 +488,12 @@ void ext_lld_start(EXTDriver *extp) {
CORTEX_PRIORITY_MASK(STM32_EXT_EXTI18_IRQ_PRIORITY));
#endif
}
- /* Configuration.*/
- imr = emr = rtsr = ftsr = 0;
- for (i = 0; i < EXT_MAX_CHANNELS; i++) {
- if (extp->config->channels[i].mode & EXT_CH_MODE_AUTOSTART) {
- if (extp->config->channels[i].cb != NULL)
- imr |= (1 << i);
- else
- emr |= (1 << i);
- if (extp->config->channels[i].mode & EXT_CH_MODE_RISING_EDGE)
- rtsr |= (1 << i);
- if (extp->config->channels[i].mode & EXT_CH_MODE_FALLING_EDGE)
- ftsr |= (1 << i);
- }
- }
-#if defined(STM32L1XX_MD) || defined(STM32F2XX) || defined(STM32F4XX)
- SYSCFG->EXTICR[0] = extp->config->exti[0];
- SYSCFG->EXTICR[1] = extp->config->exti[1];
- SYSCFG->EXTICR[2] = extp->config->exti[2];
- SYSCFG->EXTICR[3] = extp->config->exti[3];
-#else /* STM32F1XX */
- AFIO->EXTICR[0] = extp->config->exti[0];
- AFIO->EXTICR[1] = extp->config->exti[1];
- AFIO->EXTICR[2] = extp->config->exti[2];
- AFIO->EXTICR[3] = extp->config->exti[3];
-#endif /* STM32F1XX */
- EXTI->SWIER = 0;
- EXTI->RTSR = rtsr;
- EXTI->FTSR = ftsr;
- EXTI->PR = EXT_CHANNELS_MASK;
- EXTI->EMR = emr;
- EXTI->IMR = imr;
+ /* Configuration of automatic channels.*/
+ for (i = 0; i < EXT_MAX_CHANNELS; i++)
+ if (extp->config->channels[i].mode & EXT_CH_MODE_AUTOSTART)
+ ext_lld_channel_enable(extp, i);
+ else
+ ext_lld_channel_disable(extp, i);
}
/**
@@ -581,14 +555,40 @@ void ext_lld_stop(EXTDriver *extp) {
*/
void ext_lld_channel_enable(EXTDriver *extp, expchannel_t channel) {
- if (extp->config->channels[channel].cb != NULL)
- EXTI->IMR |= (1 << channel);
- else
- EXTI->EMR |= (1 << channel);
+ /* Programming edge registers.*/
if (extp->config->channels[channel].mode & EXT_CH_MODE_RISING_EDGE)
EXTI->RTSR |= (1 << channel);
+ else
+ EXTI->RTSR &= ~(1 << channel);
if (extp->config->channels[channel].mode & EXT_CH_MODE_FALLING_EDGE)
EXTI->FTSR |= (1 << channel);
+ else
+ EXTI->FTSR &= ~(1 << channel);
+
+ /* Programming interrupt and event registers.*/
+ if (extp->config->channels[channel].cb != NULL) {
+ EXTI->IMR |= (1 << channel);
+ EXTI->EMR &= ~(1 << channel);
+ }
+ else {
+ EXTI->EMR |= (1 << channel);
+ EXTI->IMR &= ~(1 << channel);
+ }
+
+ /* Setting the associated GPIO for external channels.*/
+ if (channel < 16) {
+ uint32_t n = channel & 3;
+ uint32_t mask = 0xF << (channel >> 2);
+ uint32_t port = ((extp->config->channels[channel].mode &
+ EXT_MODE_GPIO_MASK) >>
+ EXT_MODE_GPIO_OFF) << (channel >> 2);
+
+#if defined(STM32L1XX_MD) || defined(STM32F2XX) || defined(STM32F4XX)
+ SYSCFG->EXTICR[n] = (SYSCFG->EXTICR[n] & mask) | port;
+#else /* STM32F1XX */
+ AFIO->EXTICR[n] = (AFIO->EXTICR[n] & mask) | port;
+#endif /* STM32F1XX */
+ }
}
/**
@@ -605,9 +605,7 @@ void ext_lld_channel_disable(EXTDriver *extp, expchannel_t channel) {
EXTI->IMR &= ~(1 << channel);
EXTI->EMR &= ~(1 << channel);
- EXTI->RTSR &= ~(1 << channel);
- EXTI->FTSR &= ~(1 << channel);
- EXTI->PR = (1 << channel);
+ EXTI->PR = (1 << channel);
}
#endif /* HAL_USE_EXT */
diff --git a/os/hal/platforms/STM32/ext_lld.h b/os/hal/platforms/STM32/ext_lld.h
index 6ef14427b..60a77fc41 100644
--- a/os/hal/platforms/STM32/ext_lld.h
+++ b/os/hal/platforms/STM32/ext_lld.h
@@ -46,31 +46,20 @@
#define EXT_CHANNELS_MASK ((1 << EXT_MAX_CHANNELS) - 1)
/**
- * @name EXTI configuration helpers
+ * @name STM32-specific EXT channel modes
* @{
*/
-/**
- * @brief EXTI-GPIO association macro.
- * @details Helper macro to associate a GPIO to each of the Mx EXTI inputs.
- */
-#define EXT_MODE_EXTI(m0, m1, m2, m3, m4, m5, m6, m7, \
- m8, m9, m10, m11, m12, m13, m14, m15) \
- { \
- ((m0) << 0) | ((m1) << 4) | ((m2) << 8) | ((m3) << 12), \
- ((m4) << 0) | ((m5) << 4) | ((m6) << 8) | ((m7) << 12), \
- ((m8) << 0) | ((m9) << 4) | ((m10) << 8) | ((m11) << 12), \
- ((m12) << 0) | ((m13) << 4) | ((m14) << 8) | ((m15) << 12) \
- }
-
-#define EXT_MODE_GPIOA 0 /**< @brief GPIOA identifier. */
-#define EXT_MODE_GPIOB 1 /**< @brief GPIOB identifier. */
-#define EXT_MODE_GPIOC 2 /**< @brief GPIOC identifier. */
-#define EXT_MODE_GPIOD 3 /**< @brief GPIOD identifier. */
-#define EXT_MODE_GPIOE 4 /**< @brief GPIOE identifier. */
-#define EXT_MODE_GPIOF 5 /**< @brief GPIOF identifier. */
-#define EXT_MODE_GPIOG 6 /**< @brief GPIOG identifier. */
-#define EXT_MODE_GPIOH 7 /**< @brief GPIOH identifier. */
-#define EXT_MODE_GPIOI 8 /**< @brief GPIOI identifier. */
+#define EXT_MODE_GPIO_MASK 0xF0 /**< @bried Port field mask. */
+#define EXT_MODE_GPIO_OFF 4 /**< @bried Port field offset. */
+#define EXT_MODE_GPIOA 0x00 /**< @brief GPIOA identifier. */
+#define EXT_MODE_GPIOB 0x10 /**< @brief GPIOB identifier. */
+#define EXT_MODE_GPIOC 0x20 /**< @brief GPIOC identifier. */
+#define EXT_MODE_GPIOD 0x30 /**< @brief GPIOD identifier. */
+#define EXT_MODE_GPIOE 0x40 /**< @brief GPIOE identifier. */
+#define EXT_MODE_GPIOF 0x50 /**< @brief GPIOF identifier. */
+#define EXT_MODE_GPIOG 0x60 /**< @brief GPIOG identifier. */
+#define EXT_MODE_GPIOH 0x70 /**< @brief GPIOH identifier. */
+#define EXT_MODE_GPIOI 0x80 /**< @brief GPIOI identifier. */
/** @} */
/*===========================================================================*/
@@ -228,10 +217,6 @@ typedef struct {
*/
EXTChannelConfig channels[EXT_MAX_CHANNELS];
/* End of the mandatory fields.*/
- /**
- * @brief Initialization values for EXTICRx registers.
- */
- uint16_t exti[4];
} EXTConfig;
/**
diff --git a/os/hal/src/ext.c b/os/hal/src/ext.c
index e89962dea..bd175d483 100644
--- a/os/hal/src/ext.c
+++ b/os/hal/src/ext.c
@@ -120,6 +120,7 @@ void extStop(EXTDriver *extp) {
/**
* @brief Enables an EXT channel.
+ * @pre The channel must not be in @p EXT_CH_MODE_DISABLED mode.
*
* @param[in] extp pointer to the @p EXTDriver object
* @param[in] channel channel to be enabled
@@ -128,13 +129,13 @@ void extStop(EXTDriver *extp) {
*/
void extChannelEnable(EXTDriver *extp, expchannel_t channel) {
- chDbgCheck((extp != NULL) &&
- (channel < EXT_MAX_CHANNELS) &&
- (extp->config->channels[channel].mode != EXT_CH_MODE_DISABLED),
+ chDbgCheck((extp != NULL) && (channel < EXT_MAX_CHANNELS),
"extChannelEnable");
chSysLock();
- chDbgAssert(extp->state == EXT_ACTIVE,
+ chDbgAssert((extp->state == EXT_ACTIVE) &&
+ ((extp->config->channels[channel].mode &
+ EXT_CH_MODE_EDGES_MASK) != EXT_CH_MODE_DISABLED),
"extChannelEnable(), #1", "invalid state");
extChannelEnableI(extp, channel);
chSysUnlock();
@@ -142,6 +143,7 @@ void extChannelEnable(EXTDriver *extp, expchannel_t channel) {
/**
* @brief Disables an EXT channel.
+ * @pre The channel must not be in @p EXT_CH_MODE_DISABLED mode.
*
* @param[in] extp pointer to the @p EXTDriver object
* @param[in] channel channel to be disabled
@@ -150,18 +152,59 @@ void extChannelEnable(EXTDriver *extp, expchannel_t channel) {
*/
void extChannelDisable(EXTDriver *extp, expchannel_t channel) {
- chDbgCheck((extp != NULL) &&
- (channel < EXT_MAX_CHANNELS) &&
- (extp->config->channels[channel].mode != EXT_CH_MODE_DISABLED),
+ chDbgCheck((extp != NULL) && (channel < EXT_MAX_CHANNELS),
"extChannelDisable");
chSysLock();
- chDbgAssert(extp->state == EXT_ACTIVE,
+ chDbgAssert((extp->state == EXT_ACTIVE) &&
+ ((extp->config->channels[channel].mode &
+ EXT_CH_MODE_EDGES_MASK) != EXT_CH_MODE_DISABLED),
"extChannelDisable(), #1", "invalid state");
extChannelDisableI(extp, channel);
chSysUnlock();
}
+/**
+ * @brief Changes the operation mode of a channel.
+ * @note This function attempts to write over the current configuration
+ * structure that must have been not declared constant. This
+ * violates the @p const qualifier in @p extStart() but it is
+ * intentional.
+ * @note This function cannot be used if the configuration structure is
+ * declared @p const.
+ * @note The effect of this function on constant configuration structures
+ * is not defined.
+ *
+ * @param[in] extp pointer to the @p EXTDriver object
+ * @param[in] channel channel to be changed
+ * @param[in] extcp new configuration for the channel
+ *
+ * @iclass
+ */
+void extSetChannelModeI(EXTDriver *extp,
+ expchannel_t channel,
+ const EXTChannelConfig *extcp) {
+ EXTChannelConfig *oldcp;
+
+ chDbgCheck((extp != NULL) && (channel < EXT_MAX_CHANNELS) &&
+ (extcp != NULL), "extSetChannelModeI");
+
+ /* Note that here the access is enforced as non-const, known access
+ violation.*/
+ oldcp = (EXTChannelConfig *)&extp->config->channels[channel];
+
+ chSysLock();
+
+ chDbgAssert(extp->state == EXT_ACTIVE,
+ "extSetChannelModeI(), #1", "invalid state");
+
+ /* Overwiting the old channels configuration then the channel is reconfigured
+ by the low level driver.*/
+ *oldcp = *extcp;
+ ext_lld_channel_enable(extp, channel);
+ chSysUnlock();
+}
+
#endif /* HAL_USE_EXT */
/** @} */