From 92fe1a35249b1723419405dc2939d19ea940d9db Mon Sep 17 00:00:00 2001 From: Giovanni Di Sirio Date: Wed, 30 Aug 2017 13:34:37 +0000 Subject: PAL callbacks implementation for STM32, not complete yet. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@10507 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/ports/STM32/LLD/GPIOv3/hal_pal_lld.c | 125 ++++++++++++++++++++++++++++ os/hal/ports/STM32/LLD/GPIOv3/hal_pal_lld.h | 49 ++++++++++- 2 files changed, 173 insertions(+), 1 deletion(-) (limited to 'os/hal/ports/STM32') 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 -- cgit v1.2.3