PAL synchronous API.

git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@10528 35acf78f-673a-0410-8e92-d51de3d6d3f4
This commit is contained in:
Giovanni Di Sirio 2017-09-02 12:40:56 +00:00
parent dec89f7333
commit 6b9d134110
10 changed files with 290 additions and 47 deletions

View File

@ -113,6 +113,19 @@
/* Driver pre-compile time settings. */
/*===========================================================================*/
/**
* @name PAL configuration options
* @{
*/
/**
* @brief Enables synchronous APIs.
* @note Disabling this option saves both code and data space.
*/
#if !defined(PAL_USE_WAIT) || defined(__DOXYGEN__)
#define PAL_USE_WAIT TRUE
#endif
/** @} */
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
@ -130,7 +143,19 @@ typedef void (*palcallback_t)(void *arg);
* @brief Type of a PAL event record.
*/
typedef struct {
#if defined(PAL_USE_WAIT) || defined(__DOXYGEN__)
/**
* @brief Threads queued for an event.
*/
threads_queue_t threads;
#endif
/**
* @brief Event callback.
*/
palcallback_t cb;
/**
* @brief Event callback argument.
*/
void *arg;
} palevent_t;
@ -223,7 +248,22 @@ typedef struct {
*
* @notapi
*/
#define _pal_isr_code(e) _pal_events[e].cb(_pal_events[e].arg)
#if defined(PAL_USE_WAIT) || defined(__DOXYGEN__)
#define _pal_isr_code(e) do { \
if (_pal_events[e].cb != NULL) { \
_pal_events[e].cb(_pal_events[e].arg); \
} \
osalSysLockFromISR(); \
osalThreadDequeueAllI(&_pal_events[e].threads, MSG_OK); \
osalSysUnlockFromISR(); \
} while (false)
#else
#define _pal_isr_code(e) do { \
if (_pal_events[e].cb != NULL) { \
_pal_events[e].cb(_pal_events[e].arg); \
} \
} while (false)
#endif
/**
* @brief PAL event setup.
@ -236,10 +276,18 @@ typedef struct {
*
* @notapi
*/
#if defined(PAL_USE_WAIT) || defined(__DOXYGEN__)
#define _pal_set_event(e, c, a) { \
osalThreadQueueObjectInit(&_pal_events[e].threads); \
_pal_events[e].cb = c; \
_pal_events[e].arg = a; \
}
#else
#define _pal_set_event(e, c, a) { \
_pal_events[e].cb = c; \
_pal_events[e].arg = a; \
}
#endif
/**
* @brief PAL event clear.
@ -250,10 +298,18 @@ typedef struct {
*
* @notapi
*/
#if defined(PAL_USE_WAIT) || defined(__DOXYGEN__)
#define _pal_clear_event(e) { \
osalThreadDequeueAllI(&_pal_events[e].threads, MSG_RESET); \
_pal_events[e].cb = NULL; \
_pal_events[e].arg = NULL; \
}
#else
#define _pal_clear_event(e) { \
_pal_events[e].cb = NULL; \
_pal_events[e].arg = NULL; \
}
#endif
/** @} */
/**
@ -585,9 +641,9 @@ typedef struct {
* @iclass
*/
#if !defined(pal_lld_enablepadevent) || defined(__DOXYGEN__)
#define palPadEnableEventI(port, pad, mode, callback, arg)
#define palEnablePadEventI(port, pad, mode, callback, arg)
#else
#define palPadEnableEventI(port, pad, mode, callback, arg) \
#define palEnablePadEventI(port, pad, mode, callback, arg) \
pal_lld_enablepadevent(port, pad, mode, callback, arg)
#endif
@ -601,9 +657,9 @@ typedef struct {
* @iclass
*/
#if !defined(pal_lld_disablepadevent) || defined(__DOXYGEN__)
#define palPadDisableEventI(port, pad)
#define palDisablePadEventI(port, pad)
#else
#define palPadDisableEventI(port, pad) \
#define PadDisablepalEventI(port, pad) \
pal_lld_disablepadevent(port, pad)
#endif
@ -620,10 +676,10 @@ typedef struct {
*
* @api
*/
#define palPadEnableEvent(port, pad, mode, callback, arg) \
#define palEnablePadEvent(port, pad, mode, callback, arg) \
do { \
osalSysLock(); \
palPadEnableEventI(port, pad, mode, callback, arg); \
palEnablePadEventI(port, pad, mode, callback, arg); \
osalSysUnlock(); \
} while (false)
@ -636,10 +692,10 @@ typedef struct {
*
* @api
*/
#define palPadDisableEvent(port, pad) \
#define palDisablePadEvent(port, pad) \
do { \
osalSysLock(); \
palPadDisableEventI(port, pad); \
palisablePadDEventI(port, pad); \
osalSysUnlock(); \
} while (false)
@ -764,12 +820,12 @@ typedef struct {
*
* @iclass
*/
#if !defined(pal_lld_lineenableevent) || defined(__DOXYGEN__)
#define palLineEnableEventI(line, mode, callback, arg) \
palPadEnableEventI(PAL_PORT(line), PAL_PAD(line), mode, callback, arg)
#if !defined(pal_lld_enablelineevent) || defined(__DOXYGEN__)
#define palEnableLineEventI(line, mode, callback, arg) \
palEnablePadEventI(PAL_PORT(line), PAL_PAD(line), mode, callback, arg)
#else
#define palLineEnableEventI(line, mode, callback, arg) \
pal_lld_lineenableevent(line, mode, callback, arg)
#define palEnableLineEventI(line, mode, callback, arg) \
pal_lld_enablelineevent(line, mode, callback, arg)
#endif
/**
@ -779,11 +835,11 @@ typedef struct {
*
* @iclass
*/
#if !defined(pal_lld_linedisableevent) || defined(__DOXYGEN__)
#define palLineDisableEventI(line) \
palPadDisableEventI(PAL_PORT(line), PAL_PAD(line))
#if !defined(pal_lld_disablelineevent) || defined(__DOXYGEN__)
#define palDisableLineEventI(line) \
palDisablePadEventI(PAL_PORT(line), PAL_PAD(line))
#else
#define palLineDisableEventI(line) pal_lld_linedisableevent(line)
#define palDisableLineEventI(line) pal_lld_disablelineevent(line)
#endif
/**
@ -796,10 +852,10 @@ typedef struct {
*
* @api
*/
#define palLineEnableEvent(line, mode, callback, arg) \
#define palEnableLineEvent(line, mode, callback, arg) \
do { \
osalSysLock(); \
palLineEnableEventI(line, mode, callback, arg); \
palEnableLineEventI(line, mode, callback, arg); \
osalSysUnlock(); \
} while (false)
@ -810,12 +866,57 @@ typedef struct {
*
* @api
*/
#define palLineDisableEvent(line) \
#define paDisableLineEvent(line) \
do { \
osalSysLock(); \
palLineDisableEventI(line); \
palDisableLineEventI(line); \
osalSysUnlock(); \
} while (false)
#if defined(PAL_USE_WAIT) || defined(__DOXYGEN__)
/**
* @brief Waits for an edge on the specified port/pad.
*
* @param[in] port port identifier
* @param[in] pad pad number within the port
* @returns The operation state.
* @retval MSG_OK if an edge has been detected.
* @retval MSG_TIMEOUT if a timeout occurred before an edge cound be detected.
* @retval MSG_RESET if the event has been disabled while the thread was
* waiting for an edge.
*
* @api
*/
#define palWaitPadTimeout(port, pad, timeout) \
do { \
osalSysLock(); \
palWaitPadTimeoutS(port, pad, timeout); \
osalSysUnlock(); \
} while (false)
/**
* @brief Waits for an edge on the specified line.
*
* @param[in] line line identifier
* @param[in] timeout operation timeout
* @returns The operation state.
* @retval MSG_OK if an edge has been detected.
* @retval MSG_TIMEOUT if a timeout occurred before an edge cound be detected.
* @retval MSG_RESET if the event has been disabled while the thread was
* waiting for an edge.
*
* @api
*/
#define palWaitLineTimeout(line, timeout) \
do { \
osalSysLock(); \
palWaitLineTimeoutS(line, timeout); \
osalSysUnlock(); \
} while (false)
#endif /* defined(PAL_USE_WAIT) */
/** @} */
/*===========================================================================*/
@ -828,6 +929,10 @@ extern "C" {
ioportmask_t palReadBus(IOBus *bus);
void palWriteBus(IOBus *bus, ioportmask_t bits);
void palSetBusMode(IOBus *bus, iomode_t mode);
#if defined(PAL_USE_WAIT) || defined(__DOXYGEN__)
msg_t palWaitPadTimeoutS(ioportid_t port, iopadid_t pad, systime_t timeout);
msg_t palWaitLineTimeoutS(ioline_t line, systime_t timeout);
#endif /* defined(PAL_USE_WAIT) */
#ifdef __cplusplus
}
#endif

View File

@ -235,14 +235,8 @@ void _pal_lld_enablepadevent(ioportid_t port,
EXTI->FTSR &= ~padmask;
/* Programming interrupt and event registers.*/
if (callback != NULL) {
EXTI->IMR |= padmask;
EXTI->EMR &= ~padmask;
}
else {
EXTI->EMR |= padmask;
EXTI->IMR &= ~padmask;
}
EXTI->IMR |= padmask;
EXTI->EMR &= ~padmask;
/* Setting up callback and argument for this event.*/
_pal_set_event(pad, callback, arg);

View File

@ -394,6 +394,27 @@ typedef uint32_t iopadid_t;
#define pal_lld_disablepadevent(port, pad) \
_pal_lld_disablepadevent(port, pad)
/**
* @brief Returns a PAL event structure associated to a pad.
*
* @param[in] port port identifier
* @param[in] pad pad number within the port
*
* @notapi
*/
#define pal_lld_get_pad_event(port, pad) \
&_pal_events[pad]; (void)(port)
/**
* @brief Returns a PAL event structure associated to a line.
*
* @param[in] line line identifier
*
* @notapi
*/
#define pal_lld_get_line_event(line) \
&_pal_events[PAL_PAD(line)]
#if !defined(__DOXYGEN__)
extern const PALConfig pal_default_config;
extern palevent_t _pal_events[16];

View File

@ -264,14 +264,8 @@ void _pal_lld_enablepadevent(ioportid_t port,
EXTI->FTSR &= ~padmask;
/* Programming interrupt and event registers.*/
if (callback != NULL) {
EXTI->IMR |= padmask;
EXTI->EMR &= ~padmask;
}
else {
EXTI->EMR |= padmask;
EXTI->IMR &= ~padmask;
}
EXTI->IMR |= padmask;
EXTI->EMR &= ~padmask;
/* Setting up callback and argument for this event.*/
_pal_set_event(pad, callback, arg);

View File

@ -577,6 +577,27 @@ typedef uint32_t iopadid_t;
#define pal_lld_disablepadevent(port, pad) \
_pal_lld_disablepadevent(port, pad)
/**
* @brief Returns a PAL event structure associated to a pad.
*
* @param[in] port port identifier
* @param[in] pad pad number within the port
*
* @notapi
*/
#define pal_lld_get_pad_event(port, pad) \
&_pal_events[pad]; (void)(port)
/**
* @brief Returns a PAL event structure associated to a line.
*
* @param[in] line line identifier
*
* @notapi
*/
#define pal_lld_get_line_event(line) \
&_pal_events[PAL_PAD(line)]
#if !defined(__DOXYGEN__)
extern const PALConfig pal_default_config;
extern palevent_t _pal_events[16];

View File

@ -260,14 +260,8 @@ void _pal_lld_enablepadevent(ioportid_t port,
EXTI->FTSR &= ~padmask;
/* Programming interrupt and event registers.*/
if (callback != NULL) {
EXTI->IMR |= padmask;
EXTI->EMR &= ~padmask;
}
else {
EXTI->EMR |= padmask;
EXTI->IMR &= ~padmask;
}
EXTI->IMR |= padmask;
EXTI->EMR &= ~padmask;
/* Setting up callback and argument for this event.*/
_pal_set_event(pad, callback, arg);

View File

@ -589,6 +589,27 @@ typedef uint32_t iopadid_t;
#define pal_lld_disablepadevent(port, pad) \
_pal_lld_disablepadevent(port, pad)
/**
* @brief Returns a PAL event structure associated to a pad.
*
* @param[in] port port identifier
* @param[in] pad pad number within the port
*
* @notapi
*/
#define pal_lld_get_pad_event(port, pad) \
&_pal_events[pad]; (void)(port)
/**
* @brief Returns a PAL event structure associated to a line.
*
* @param[in] line line identifier
*
* @notapi
*/
#define pal_lld_get_line_event(line) \
&_pal_events[PAL_PAD(line)]
#if !defined(__DOXYGEN__)
extern const PALConfig pal_default_config;
extern palevent_t _pal_events[16];

View File

@ -117,6 +117,46 @@ void palSetBusMode(IOBus *bus, iomode_t mode) {
palSetGroupMode(bus->portid, bus->mask, bus->offset, mode);
}
#if defined(PAL_USE_WAIT) || defined(__DOXYGEN__)
/**
* @brief Waits for an edge on the specified port/pad.
*
* @param[in] port port identifier
* @param[in] pad pad number within the port
* @returns The operation state.
* @retval MSG_OK if an edge has been detected.
* @retval MSG_TIMEOUT if a timeout occurred before an edge cound be detected.
* @retval MSG_RESET if the event has been disabled while the thread was
* waiting for an edge.
*
* @sclass
*/
msg_t palWaitPadTimeoutS(ioportid_t port, iopadid_t pad, systime_t timeout) {
palevent_t *pep = pal_lld_get_pad_event(port, pad);
return osalThreadEnqueueTimeoutS(&pep->threads, timeout);
}
/**
* @brief Waits for an edge on the specified line.
*
* @param[in] line line identifier
* @param[in] timeout operation timeout
* @returns The operation state.
* @retval MSG_OK if an edge has been detected.
* @retval MSG_TIMEOUT if a timeout occurred before an edge cound be detected.
* @retval MSG_RESET if the event has been disabled while the thread was
* waiting for an edge.
*
* @sclass
*/
msg_t palWaitLineTimeoutS(ioline_t line, systime_t timeout) {
palevent_t *pep = pal_lld_get_line_event(line);
return osalThreadEnqueueTimeoutS(&pep->threads, timeout);
}
#endif /* defined(PAL_USE_WAIT) */
#endif /* HAL_USE_PAL == TRUE */
/** @} */

View File

@ -89,6 +89,9 @@
*****************************************************************************
*** Next ***
- NEW: Implemented PAL enhancements on all existing STM32 ports.
- NEW: PAL driver enhanced with improved callbacks capability and new
synchronous API for edge synchronization.
- NEW: Added to the serial driver and channels interface a new "control"
function that allows to implement extensions in the LLD without
touching the high level interface. Conceptually it is similar

View File

@ -38,6 +38,53 @@ static THD_FUNCTION(Thread1, arg) {
}
#endif
#if defined(PAL_USE_WAIT) || defined(__DOXYGEN__)
/*
* Application entry point.
*/
int main(void) {
/*
* System initializations.
* - HAL initialization, this also initializes the configured device drivers
* and performs the board-specific initializations.
* - Kernel initialization, the main() function becomes a thread and the
* RTOS is active.
*/
halInit();
chSysInit();
#if defined(PORTAB_LINE_LED2)
/*
* Creates the blinker thread.
*/
chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO, Thread1, NULL);
#endif
/* Enabling callback on both edges of the button line.*/
palEnableLineEvent(PORTAB_LINE_BUTTON, PAL_EVENT_MODE_BOTH_EDGES,
NULL, NULL);
/*
* Normal main() thread activity.
*/
while (true) {
/* Waiting for an edge on the button.*/
palWaitLineTimeout(PORTAB_LINE_BUTTON, TIME_INFINITE);
/* Action depending on button state.*/
if (palReadLine(PORTAB_LINE_BUTTON) == PORTAB_BUTTON_PRESSED) {
palWriteLine(PORTAB_LINE_LED1, PORTAB_LEN_ON);
}
else {
palWriteLine(PORTAB_LINE_LED1, PORTAB_LEN_OFF);
}
}
}
#else /* !defined(PAL_USE_WAIT) */
static event_source_t button_pressed_event;
static event_source_t button_released_event;
@ -85,7 +132,7 @@ int main(void) {
#endif
/* Enabling callback on both edges of the button line.*/
palLineEnableEvent(PORTAB_LINE_BUTTON, PAL_EVENT_MODE_BOTH_EDGES,
palEnableLineEvent(PORTAB_LINE_BUTTON, PAL_EVENT_MODE_BOTH_EDGES,
button_cb, NULL);
/*
@ -103,3 +150,6 @@ int main(void) {
}
}
}
#endif /* !defined(PAL_USE_WAIT) */