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. */ /* 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. */ /* Derived constants and error checks. */
/*===========================================================================*/ /*===========================================================================*/
@ -130,7 +143,19 @@ typedef void (*palcallback_t)(void *arg);
* @brief Type of a PAL event record. * @brief Type of a PAL event record.
*/ */
typedef struct { 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; palcallback_t cb;
/**
* @brief Event callback argument.
*/
void *arg; void *arg;
} palevent_t; } palevent_t;
@ -223,7 +248,22 @@ typedef struct {
* *
* @notapi * @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. * @brief PAL event setup.
@ -236,10 +276,18 @@ typedef struct {
* *
* @notapi * @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) { \ #define _pal_set_event(e, c, a) { \
_pal_events[e].cb = c; \ _pal_events[e].cb = c; \
_pal_events[e].arg = a; \ _pal_events[e].arg = a; \
} }
#endif
/** /**
* @brief PAL event clear. * @brief PAL event clear.
@ -250,10 +298,18 @@ typedef struct {
* *
* @notapi * @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) { \ #define _pal_clear_event(e) { \
_pal_events[e].cb = NULL; \ _pal_events[e].cb = NULL; \
_pal_events[e].arg = NULL; \ _pal_events[e].arg = NULL; \
} }
#endif
/** @} */ /** @} */
/** /**
@ -585,9 +641,9 @@ typedef struct {
* @iclass * @iclass
*/ */
#if !defined(pal_lld_enablepadevent) || defined(__DOXYGEN__) #if !defined(pal_lld_enablepadevent) || defined(__DOXYGEN__)
#define palPadEnableEventI(port, pad, mode, callback, arg) #define palEnablePadEventI(port, pad, mode, callback, arg)
#else #else
#define palPadEnableEventI(port, pad, mode, callback, arg) \ #define palEnablePadEventI(port, pad, mode, callback, arg) \
pal_lld_enablepadevent(port, pad, mode, callback, arg) pal_lld_enablepadevent(port, pad, mode, callback, arg)
#endif #endif
@ -601,9 +657,9 @@ typedef struct {
* @iclass * @iclass
*/ */
#if !defined(pal_lld_disablepadevent) || defined(__DOXYGEN__) #if !defined(pal_lld_disablepadevent) || defined(__DOXYGEN__)
#define palPadDisableEventI(port, pad) #define palDisablePadEventI(port, pad)
#else #else
#define palPadDisableEventI(port, pad) \ #define PadDisablepalEventI(port, pad) \
pal_lld_disablepadevent(port, pad) pal_lld_disablepadevent(port, pad)
#endif #endif
@ -620,10 +676,10 @@ typedef struct {
* *
* @api * @api
*/ */
#define palPadEnableEvent(port, pad, mode, callback, arg) \ #define palEnablePadEvent(port, pad, mode, callback, arg) \
do { \ do { \
osalSysLock(); \ osalSysLock(); \
palPadEnableEventI(port, pad, mode, callback, arg); \ palEnablePadEventI(port, pad, mode, callback, arg); \
osalSysUnlock(); \ osalSysUnlock(); \
} while (false) } while (false)
@ -636,10 +692,10 @@ typedef struct {
* *
* @api * @api
*/ */
#define palPadDisableEvent(port, pad) \ #define palDisablePadEvent(port, pad) \
do { \ do { \
osalSysLock(); \ osalSysLock(); \
palPadDisableEventI(port, pad); \ palisablePadDEventI(port, pad); \
osalSysUnlock(); \ osalSysUnlock(); \
} while (false) } while (false)
@ -764,12 +820,12 @@ typedef struct {
* *
* @iclass * @iclass
*/ */
#if !defined(pal_lld_lineenableevent) || defined(__DOXYGEN__) #if !defined(pal_lld_enablelineevent) || defined(__DOXYGEN__)
#define palLineEnableEventI(line, mode, callback, arg) \ #define palEnableLineEventI(line, mode, callback, arg) \
palPadEnableEventI(PAL_PORT(line), PAL_PAD(line), mode, callback, arg) palEnablePadEventI(PAL_PORT(line), PAL_PAD(line), mode, callback, arg)
#else #else
#define palLineEnableEventI(line, mode, callback, arg) \ #define palEnableLineEventI(line, mode, callback, arg) \
pal_lld_lineenableevent(line, mode, callback, arg) pal_lld_enablelineevent(line, mode, callback, arg)
#endif #endif
/** /**
@ -779,11 +835,11 @@ typedef struct {
* *
* @iclass * @iclass
*/ */
#if !defined(pal_lld_linedisableevent) || defined(__DOXYGEN__) #if !defined(pal_lld_disablelineevent) || defined(__DOXYGEN__)
#define palLineDisableEventI(line) \ #define palDisableLineEventI(line) \
palPadDisableEventI(PAL_PORT(line), PAL_PAD(line)) palDisablePadEventI(PAL_PORT(line), PAL_PAD(line))
#else #else
#define palLineDisableEventI(line) pal_lld_linedisableevent(line) #define palDisableLineEventI(line) pal_lld_disablelineevent(line)
#endif #endif
/** /**
@ -796,10 +852,10 @@ typedef struct {
* *
* @api * @api
*/ */
#define palLineEnableEvent(line, mode, callback, arg) \ #define palEnableLineEvent(line, mode, callback, arg) \
do { \ do { \
osalSysLock(); \ osalSysLock(); \
palLineEnableEventI(line, mode, callback, arg); \ palEnableLineEventI(line, mode, callback, arg); \
osalSysUnlock(); \ osalSysUnlock(); \
} while (false) } while (false)
@ -810,12 +866,57 @@ typedef struct {
* *
* @api * @api
*/ */
#define palLineDisableEvent(line) \ #define paDisableLineEvent(line) \
do { \ do { \
osalSysLock(); \ osalSysLock(); \
palLineDisableEventI(line); \ palDisableLineEventI(line); \
osalSysUnlock(); \ osalSysUnlock(); \
} while (false) } 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); ioportmask_t palReadBus(IOBus *bus);
void palWriteBus(IOBus *bus, ioportmask_t bits); void palWriteBus(IOBus *bus, ioportmask_t bits);
void palSetBusMode(IOBus *bus, iomode_t mode); 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 #ifdef __cplusplus
} }
#endif #endif

View File

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

View File

@ -394,6 +394,27 @@ typedef uint32_t iopadid_t;
#define pal_lld_disablepadevent(port, pad) \ #define pal_lld_disablepadevent(port, pad) \
_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__) #if !defined(__DOXYGEN__)
extern const PALConfig pal_default_config; extern const PALConfig pal_default_config;
extern palevent_t _pal_events[16]; extern palevent_t _pal_events[16];

View File

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

View File

@ -577,6 +577,27 @@ typedef uint32_t iopadid_t;
#define pal_lld_disablepadevent(port, pad) \ #define pal_lld_disablepadevent(port, pad) \
_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__) #if !defined(__DOXYGEN__)
extern const PALConfig pal_default_config; extern const PALConfig pal_default_config;
extern palevent_t _pal_events[16]; extern palevent_t _pal_events[16];

View File

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

View File

@ -589,6 +589,27 @@ typedef uint32_t iopadid_t;
#define pal_lld_disablepadevent(port, pad) \ #define pal_lld_disablepadevent(port, pad) \
_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__) #if !defined(__DOXYGEN__)
extern const PALConfig pal_default_config; extern const PALConfig pal_default_config;
extern palevent_t _pal_events[16]; 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); 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 */ #endif /* HAL_USE_PAL == TRUE */
/** @} */ /** @} */

View File

@ -89,6 +89,9 @@
***************************************************************************** *****************************************************************************
*** Next *** *** 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" - NEW: Added to the serial driver and channels interface a new "control"
function that allows to implement extensions in the LLD without function that allows to implement extensions in the LLD without
touching the high level interface. Conceptually it is similar touching the high level interface. Conceptually it is similar

View File

@ -38,6 +38,53 @@ static THD_FUNCTION(Thread1, arg) {
} }
#endif #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_pressed_event;
static event_source_t button_released_event; static event_source_t button_released_event;
@ -85,7 +132,7 @@ int main(void) {
#endif #endif
/* Enabling callback on both edges of the button line.*/ /* 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); button_cb, NULL);
/* /*
@ -103,3 +150,6 @@ int main(void) {
} }
} }
} }
#endif /* !defined(PAL_USE_WAIT) */