aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--os/hal/include/hal_pal.h149
-rw-r--r--os/hal/ports/STM32/LLD/GPIOv1/hal_pal_lld.c10
-rw-r--r--os/hal/ports/STM32/LLD/GPIOv1/hal_pal_lld.h21
-rw-r--r--os/hal/ports/STM32/LLD/GPIOv2/hal_pal_lld.c10
-rw-r--r--os/hal/ports/STM32/LLD/GPIOv2/hal_pal_lld.h21
-rw-r--r--os/hal/ports/STM32/LLD/GPIOv3/hal_pal_lld.c10
-rw-r--r--os/hal/ports/STM32/LLD/GPIOv3/hal_pal_lld.h21
-rw-r--r--os/hal/src/hal_pal.c40
-rw-r--r--readme.txt3
-rw-r--r--testhal/STM32/multi/PAL/main.c52
10 files changed, 290 insertions, 47 deletions
diff --git a/os/hal/include/hal_pal.h b/os/hal/include/hal_pal.h
index ede48c470..f19c8396f 100644
--- a/os/hal/include/hal_pal.h
+++ b/os/hal/include/hal_pal.h
@@ -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(); \
+ 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(); \
- palLineDisableEventI(line); \
+ 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
diff --git a/os/hal/ports/STM32/LLD/GPIOv1/hal_pal_lld.c b/os/hal/ports/STM32/LLD/GPIOv1/hal_pal_lld.c
index b432fa6ee..be8f7e829 100644
--- a/os/hal/ports/STM32/LLD/GPIOv1/hal_pal_lld.c
+++ b/os/hal/ports/STM32/LLD/GPIOv1/hal_pal_lld.c
@@ -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);
diff --git a/os/hal/ports/STM32/LLD/GPIOv1/hal_pal_lld.h b/os/hal/ports/STM32/LLD/GPIOv1/hal_pal_lld.h
index a80597d64..a20cea930 100644
--- a/os/hal/ports/STM32/LLD/GPIOv1/hal_pal_lld.h
+++ b/os/hal/ports/STM32/LLD/GPIOv1/hal_pal_lld.h
@@ -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];
diff --git a/os/hal/ports/STM32/LLD/GPIOv2/hal_pal_lld.c b/os/hal/ports/STM32/LLD/GPIOv2/hal_pal_lld.c
index 6a23eff29..70f769f02 100644
--- a/os/hal/ports/STM32/LLD/GPIOv2/hal_pal_lld.c
+++ b/os/hal/ports/STM32/LLD/GPIOv2/hal_pal_lld.c
@@ -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);
diff --git a/os/hal/ports/STM32/LLD/GPIOv2/hal_pal_lld.h b/os/hal/ports/STM32/LLD/GPIOv2/hal_pal_lld.h
index ba90ccafd..4a30a61a5 100644
--- a/os/hal/ports/STM32/LLD/GPIOv2/hal_pal_lld.h
+++ b/os/hal/ports/STM32/LLD/GPIOv2/hal_pal_lld.h
@@ -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];
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 a20e39c9a..6c8a1ec2e 100644
--- a/os/hal/ports/STM32/LLD/GPIOv3/hal_pal_lld.c
+++ b/os/hal/ports/STM32/LLD/GPIOv3/hal_pal_lld.c
@@ -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);
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 b1f5694b6..7b423807e 100644
--- a/os/hal/ports/STM32/LLD/GPIOv3/hal_pal_lld.h
+++ b/os/hal/ports/STM32/LLD/GPIOv3/hal_pal_lld.h
@@ -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];
diff --git a/os/hal/src/hal_pal.c b/os/hal/src/hal_pal.c
index 0be77ad70..850c3506b 100644
--- a/os/hal/src/hal_pal.c
+++ b/os/hal/src/hal_pal.c
@@ -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 */
/** @} */
diff --git a/readme.txt b/readme.txt
index 665927b6e..da36610a1 100644
--- a/readme.txt
+++ b/readme.txt
@@ -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
diff --git a/testhal/STM32/multi/PAL/main.c b/testhal/STM32/multi/PAL/main.c
index 46a714dd2..5d53b97b2 100644
--- a/testhal/STM32/multi/PAL/main.c
+++ b/testhal/STM32/multi/PAL/main.c
@@ -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) */
+
+