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
This commit is contained in:
Giovanni Di Sirio 2017-08-30 13:34:37 +00:00
parent ab5f8476e1
commit 92fe1a3524
3 changed files with 227 additions and 1 deletions

View File

@ -126,6 +126,14 @@
*/
typedef void (*palcallback_t)(void *arg);
/**
* @brief Type of a PAL event record.
*/
typedef struct {
palcallback_t cb;
void *arg;
} palevent_t;
#include "hal_pal_lld.h"
/**
@ -202,6 +210,52 @@ typedef struct {
#define IOBUS_DECL(name, port, width, offset) \
IOBus name = _IOBUS_DATA(name, port, width, offset)
/**
* @name Low level driver helper macros
* @{
*/
/**
* @brief Common ISR code.
* @note This macro is meant to be used in the low level drivers
* implementation only.
*
* @param[in] e event index
*
* @notapi
*/
#define _pal_isr_code(e) _pal_events[e].cb(_pal_events[e].arg)
/**
* @brief PAL event setup.
* @note This macro is meant to be used in the low level drivers
* implementation only.
*
* @param[in] e event index
* @param[in] c callback pointer
* @param[in] a callback argument
*
* @notapi
*/
#define _pal_set_event(e, c, a) { \
_pal_events[e].cb = c; \
_pal_events[e].arg = a; \
}
/**
* @brief PAL event clear.
* @note This macro is meant to be used in the low level drivers
* implementation only.
*
* @param[in] e event index
*
* @notapi
*/
#define _pal_clear_event(e) { \
_pal_events[e].cb = NULL; \
_pal_events[e].arg = NULL; \
}
/** @} */
/**
* @name Macro Functions
* @{

View File

@ -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 */
/** @} */

View File

@ -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