diff options
Diffstat (limited to 'os/hal/ports/STM32/LLD')
-rw-r--r-- | os/hal/ports/STM32/LLD/GPIOv3/hal_pal_lld.c | 125 | ||||
-rw-r--r-- | os/hal/ports/STM32/LLD/GPIOv3/hal_pal_lld.h | 49 |
2 files changed, 173 insertions, 1 deletions
diff --git a/os/hal/ports/STM32/LLD/GPIOv3/hal_pal_lld.c b/os/hal/ports/STM32/LLD/GPIOv3/hal_pal_lld.c index e55c0c697..a20e39c9a 100644 --- a/os/hal/ports/STM32/LLD/GPIOv3/hal_pal_lld.c +++ b/os/hal/ports/STM32/LLD/GPIOv3/hal_pal_lld.c @@ -38,10 +38,24 @@ #error "missing or unsupported platform for GPIOv3 PAL driver"
#endif
+/* Handling a difference in ST headers.*/
+#if defined(STM32L4XX)
+#define EMR EMR1
+#define IMR IMR1
+#define PR PR1
+#define RTSR RTSR1
+#define FTSR FTSR1
+#endif
+
/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/
+/**
+ * @brief Event records for the 16 GPIO EXTI channels.
+ */
+palevent_t _pal_events[16];
+
/*===========================================================================*/
/* Driver local variables and types. */
/*===========================================================================*/
@@ -194,6 +208,117 @@ void _pal_lld_setgroupmode(ioportid_t port, }
}
+/**
+ * @brief Pad event enable.
+ * @details This function programs an event callback in the specified mode.
+ * @note Programming an unknown or unsupported mode is silently ignored.
+ *
+ * @param[in] port port identifier
+ * @param[in] pad pad number within the port
+ * @param[in] mode pad event mode
+ * @param[in] callback event callback function
+ * @param[in] arg callback argument
+ *
+ * @notapi
+ */
+void _pal_lld_enablepadevent(ioportid_t port,
+ iopadid_t pad,
+ ioeventmode_t mode,
+ palcallback_t callback,
+ void *arg) {
+
+ uint32_t padmask, cridx, crmask, portidx;
+
+ /* Mask of the pad.*/
+ padmask = 1U << (uint32_t)pad;
+
+ /* Multiple channel setting of the same channel not allowed, first disable
+ it. This is done because on STM32 the same channel cannot be mapped on
+ multiple ports.*/
+ osalDbgAssert(((EXTI->RTSR & padmask) == 0U) &&
+ ((EXTI->FTSR & padmask) == 0U), "channel already in use");
+
+ /* Index and mask of the SYSCFG CR register to be used.*/
+ cridx = (uint32_t)pad >> 2U;
+ crmask = ~(0xFU << (((uint32_t)pad & 3U) * 4U));
+
+ /* Port index is obtained assuming that GPIO ports are placed at regular
+ 0x400 intervalis in memory space. So far this is true for all devices.*/
+ portidx = (uint32_t)port >> 10U;
+
+ /* Port selection in SYSCFG.*/
+ SYSCFG->EXTICR[cridx] = (SYSCFG->EXTICR[cridx] & crmask) | portidx;
+
+ /* Programming edge registers.*/
+ if (mode & PAL_EVENT_MODE_RISING_EDGE)
+ EXTI->RTSR |= padmask;
+ else
+ EXTI->RTSR &= ~padmask;
+ if (mode & PAL_EVENT_MODE_FALLING_EDGE)
+ EXTI->FTSR |= padmask;
+ else
+ EXTI->FTSR &= ~padmask;
+
+ /* Programming interrupt and event registers.*/
+ if (callback != NULL) {
+ EXTI->IMR |= padmask;
+ EXTI->EMR &= ~padmask;
+ }
+ else {
+ EXTI->EMR |= padmask;
+ EXTI->IMR &= ~padmask;
+ }
+
+ /* Setting up callback and argument for this event.*/
+ _pal_set_event(pad, callback, arg);
+}
+
+/**
+ * @brief Pad event disable.
+ * @details This function disables previously programmed event callbacks.
+ *
+ * @param[in] port port identifier
+ * @param[in] pad pad number within the port
+ *
+ * @notapi
+ */
+void _pal_lld_disablepadevent(ioportid_t port, iopadid_t pad) {
+ uint32_t padmask, rtsr1, ftsr1;
+
+ rtsr1 = EXTI->RTSR1;
+ ftsr1 = EXTI->FTSR1;
+
+ /* Mask of the pad.*/
+ padmask = 1U << (uint32_t)pad;
+
+ /* If either RTRS1 or FTSR1 is enabled then the channel is in use.*/
+ if (((rtsr1 | ftsr1) & padmask) != 0U) {
+ uint32_t cridx, croff, crport, portidx;
+
+ /* Index and mask of the SYSCFG CR register to be used.*/
+ cridx = (uint32_t)pad >> 2U;
+ croff = ((uint32_t)pad & 3U) * 4U;
+
+ /* Port index is obtained assuming that GPIO ports are placed at regular
+ 0x400 intervalis in memory space. So far this is true for all devices.*/
+ portidx = (uint32_t)port >> 10U;
+
+ crport = (SYSCFG->EXTICR[cridx] >> croff) & 0xFU;
+
+ osalDbgAssert(crport == portidx, "channel mapped on different port");
+
+ /* Disabling channel.*/
+ EXTI->IMR &= ~padmask;
+ EXTI->EMR &= ~padmask;
+ EXTI->RTSR = rtsr1 & ~padmask;
+ EXTI->FTSR = ftsr1 & ~padmask;
+ EXTI->PR = padmask;
+
+ /* Clearing callback and argument for this event.*/
+ _pal_clear_event(pad);
+ }
+}
+
#endif /* HAL_USE_PAL */
/** @} */
diff --git a/os/hal/ports/STM32/LLD/GPIOv3/hal_pal_lld.h b/os/hal/ports/STM32/LLD/GPIOv3/hal_pal_lld.h index ac3c085bf..b1f5694b6 100644 --- a/os/hal/ports/STM32/LLD/GPIOv3/hal_pal_lld.h +++ b/os/hal/ports/STM32/LLD/GPIOv3/hal_pal_lld.h @@ -341,13 +341,23 @@ typedef uint32_t iomode_t; typedef uint32_t ioline_t;
/**
- * @brief Port Identifier.
+ * @brief Type of an event mode.
+ */
+typedef uint32_t ioeventmode_t;
+
+/**
+ * @brief Type of a port Identifier.
* @details This type can be a scalar or some kind of pointer, do not make
* any assumption about it, use the provided macros when populating
* variables of this type.
*/
typedef stm32_gpio_t * ioportid_t;
+/**
+ * @brief Type of an pad identifier.
+ */
+typedef uint32_t iopadid_t;
+
/*===========================================================================*/
/* I/O Ports Identifiers. */
/* The low level driver wraps the definitions already present in the STM32 */
@@ -551,7 +561,38 @@ typedef stm32_gpio_t * ioportid_t; */
#define pal_lld_writepad(port, pad, bit) pal_lld_writegroup(port, 1, pad, bit)
+/**
+ * @brief Pad event enable.
+ * @details This function programs an event callback in the specified mode.
+ * @note Programming an unknown or unsupported mode is silently ignored.
+ *
+ * @param[in] port port identifier
+ * @param[in] pad pad number within the port
+ * @param[in] mode pad event mode
+ * @param[in] callback event callback function
+ * @param[in] arg callback argument
+ *
+ * @notapi
+ */
+#define pal_lld_enablepadevent(port, pad, mode, callback, arg) \
+ _pal_lld_enablepadevent(port, pad, mode, callback, arg)
+
+/**
+ * @brief Pad event disable.
+ * @details This function disables previously programmed event callbacks.
+ *
+ * @param[in] port port identifier
+ * @param[in] pad pad number within the port
+ *
+ * @notapi
+ */
+#define pal_lld_disablepadevent(port, pad) \
+ _pal_lld_disablepadevent(port, pad)
+
+#if !defined(__DOXYGEN__)
extern const PALConfig pal_default_config;
+extern palevent_t _pal_events[16];
+#endif
#ifdef __cplusplus
extern "C" {
@@ -560,6 +601,12 @@ extern "C" { void _pal_lld_setgroupmode(ioportid_t port,
ioportmask_t mask,
iomode_t mode);
+ void _pal_lld_enablepadevent(ioportid_t port,
+ iopadid_t pad,
+ ioeventmode_t mode,
+ palcallback_t callback,
+ void *arg);
+ void _pal_lld_disablepadevent(ioportid_t port, iopadid_t pad);
#ifdef __cplusplus
}
#endif
|