ChibiOS/HAL  6.1.0
hal_pal.h
Go to the documentation of this file.
1 /*
2  ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
3 
4  Licensed under the Apache License, Version 2.0 (the "License");
5  you may not use this file except in compliance with the License.
6  You may obtain a copy of the License at
7 
8  http://www.apache.org/licenses/LICENSE-2.0
9 
10  Unless required by applicable law or agreed to in writing, software
11  distributed under the License is distributed on an "AS IS" BASIS,
12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  See the License for the specific language governing permissions and
14  limitations under the License.
15 */
16 
17 /**
18  * @file hal_pal.h
19  * @brief I/O Ports Abstraction Layer macros, types and structures.
20  *
21  * @addtogroup PAL
22  * @{
23  */
24 
25 #ifndef HAL_PAL_H
26 #define HAL_PAL_H
27 
28 #if (HAL_USE_PAL == TRUE) || defined(__DOXYGEN__)
29 
30 /*===========================================================================*/
31 /* Driver constants. */
32 /*===========================================================================*/
33 
34 /**
35  * @name Pads mode constants
36  * @{
37  */
38 /**
39  * @brief After reset state.
40  * @details The state itself is not specified and is architecture dependent,
41  * it is guaranteed to be equal to the after-reset state. It is
42  * usually an input state.
43  */
44 #define PAL_MODE_RESET 0U
45 
46 /**
47  * @brief Safe state for <b>unconnected</b> pads.
48  * @details The state itself is not specified and is architecture dependent,
49  * it may be mapped on @p PAL_MODE_INPUT_PULLUP,
50  * @p PAL_MODE_INPUT_PULLDOWN or @p PAL_MODE_OUTPUT_PUSHPULL for
51  * example.
52  */
53 #define PAL_MODE_UNCONNECTED 1U
54 
55 /**
56  * @brief Regular input high-Z pad.
57  */
58 #define PAL_MODE_INPUT 2U
59 
60 /**
61  * @brief Input pad with weak pull up resistor.
62  */
63 #define PAL_MODE_INPUT_PULLUP 3U
64 
65 /**
66  * @brief Input pad with weak pull down resistor.
67  */
68 #define PAL_MODE_INPUT_PULLDOWN 4U
69 
70 /**
71  * @brief Analog input mode.
72  */
73 #define PAL_MODE_INPUT_ANALOG 5U
74 
75 /**
76  * @brief Push-pull output pad.
77  */
78 #define PAL_MODE_OUTPUT_PUSHPULL 6U
79 
80 /**
81  * @brief Open-drain output pad.
82  */
83 #define PAL_MODE_OUTPUT_OPENDRAIN 7U
84 /** @} */
85 
86 /**
87  * @name Logic level constants
88  * @{
89  */
90 /**
91  * @brief Logical low state.
92  */
93 #define PAL_LOW 0U
94 
95 /**
96  * @brief Logical high state.
97  */
98 #define PAL_HIGH 1U
99 /** @} */
100 
101 /**
102  * @name PAL event modes
103  * @{
104  */
105 #define PAL_EVENT_MODE_EDGES_MASK 3U /**< @brief Mask of edges field. */
106 #define PAL_EVENT_MODE_DISABLED 0U /**< @brief Channel disabled. */
107 #define PAL_EVENT_MODE_RISING_EDGE 1U /**< @brief Rising edge callback. */
108 #define PAL_EVENT_MODE_FALLING_EDGE 2U /**< @brief Falling edge callback. */
109 #define PAL_EVENT_MODE_BOTH_EDGES 3U /**< @brief Both edges callback. */
110 /** @} */
111 
112 /*===========================================================================*/
113 /* Driver pre-compile time settings. */
114 /*===========================================================================*/
115 
116 /**
117  * @name PAL configuration options
118  * @{
119  */
120 /**
121  * @brief Enables synchronous APIs.
122  * @note Disabling this option saves both code and data space.
123  */
124 #if !defined(PAL_USE_CALLBACKS) || defined(__DOXYGEN__)
125 #define PAL_USE_CALLBACKS TRUE
126 #endif
127 
128 /**
129  * @brief Enables synchronous APIs.
130  * @note Disabling this option saves both code and data space.
131  */
132 #if !defined(PAL_USE_WAIT) || defined(__DOXYGEN__)
133 #define PAL_USE_WAIT TRUE
134 #endif
135 /** @} */
136 
137 /*===========================================================================*/
138 /* Derived constants and error checks. */
139 /*===========================================================================*/
140 
141 /*===========================================================================*/
142 /* Driver data structures and types. */
143 /*===========================================================================*/
144 
145 /**
146  * @brief Type of a PAL event callback.
147  */
148 typedef void (*palcallback_t)(void *arg);
149 
150 #if (PAL_USE_WAIT == TRUE) || (PAL_USE_CALLBACKS == TRUE) || defined(__DOXYGEN__)
151 /**
152  * @brief Type of a PAL event record.
153  */
154 typedef struct {
155 #if (PAL_USE_WAIT == TRUE) || defined(__DOXYGEN__)
156  /**
157  * @brief Threads queued for an event.
158  */
160 #endif
161 #if (PAL_USE_CALLBACKS == TRUE) || defined(__DOXYGEN__)
162  /**
163  * @brief Event callback.
164  */
166  /**
167  * @brief Event callback argument.
168  */
169  void *arg;
170 #endif
171 } palevent_t;
172 #endif
173 
174 #include "hal_pal_lld.h"
175 
176 /**
177  * @brief I/O bus descriptor.
178  * @details This structure describes a group of contiguous digital I/O lines
179  * that have to be handled as bus.
180  * @note I/O operations on a bus do not affect I/O lines on the same port but
181  * not belonging to the bus.
182  */
183 typedef struct {
184  /**
185  * @brief Port identifier.
186  */
188  /**
189  * @brief Bus mask aligned to port bit 0.
190  * @note The bus mask implicitly define the bus width. A logic AND is
191  * performed on the bus data.
192  */
194  /**
195  * @brief Offset, within the port, of the least significant bit of the bus.
196  */
197  uint_fast8_t offset;
198 } IOBus;
199 
200 /*===========================================================================*/
201 /* Driver macros. */
202 /*===========================================================================*/
203 
204 /**
205  * @brief Port bit helper macro.
206  * @details This macro calculates the mask of a bit within a port.
207  *
208  * @param[in] n bit position within the port
209  * @return The bit mask.
210  */
211 #if !defined(PAL_PORT_BIT) || defined(__DOXYGEN__)
212 #define PAL_PORT_BIT(n) ((ioportmask_t)(1U << (n)))
213 #endif
214 
215 /**
216  * @brief Bits group mask helper.
217  * @details This macro calculates the mask of a bits group.
218  *
219  * @param[in] width group width
220  * @return The group mask.
221  */
222 #if !defined(PAL_GROUP_MASK) || defined(__DOXYGEN__)
223 #define PAL_GROUP_MASK(width) ((ioportmask_t)(1U << (width)) - 1U)
224 #endif
225 
226 /**
227  * @brief Data part of a static I/O bus initializer.
228  * @details This macro should be used when statically initializing an I/O bus
229  * that is part of a bigger structure.
230  *
231  * @param[in] name name of the IOBus variable
232  * @param[in] port I/O port descriptor
233  * @param[in] width bus width in bits
234  * @param[in] offset bus bit offset within the port
235  */
236 #define _IOBUS_DATA(name, port, width, offset) \
237  {port, PAL_GROUP_MASK(width), offset}
238 
239 /**
240  * @brief Static I/O bus initializer.
241  *
242  * @param[in] name name of the IOBus variable
243  * @param[in] port I/O port descriptor
244  * @param[in] width bus width in bits
245  * @param[in] offset bus bit offset within the port
246  */
247 #define IOBUS_DECL(name, port, width, offset) \
248  IOBus name = _IOBUS_DATA(name, port, width, offset)
249 
250 #if (PAL_USE_CALLBACKS == TRUE) || (PAL_USE_WAIT == TRUE) || \
251  defined(__DOXYGEN__)
252 /**
253  * @name Low level driver helper macros
254  * @{
255  */
256 #if ((PAL_USE_CALLBACKS == TRUE) && (PAL_USE_WAIT == TRUE)) || \
257  defined(__DOXYGEN__)
258 /**
259  * @brief Initializes a PAL event object.
260  *
261  * @param[in] e event index
262  *
263  * @notapi
264  */
265 #define _pal_init_event(e) \
266  do { \
267  osalThreadQueueObjectInit(&_pal_events[e].threads); \
268  _pal_events[e].cb = NULL; \
269  _pal_events[e].arg = NULL; \
270  } while (false)
271 #endif /* (PAL_USE_CALLBACKS == TRUE) && (PAL_USE_WAIT == TRUE) */
272 
273 #if (PAL_USE_CALLBACKS == TRUE) && (PAL_USE_WAIT == FALSE)
274 #define _pal_init_event(e) \
275  do { \
276  _pal_events[e].cb = NULL; \
277  _pal_events[e].arg = NULL; \
278  } while (false)
279 #endif /* (PAL_USE_CALLBACKS == TRUE) && (PAL_USE_WAIT == FALSE) */
280 
281 #if (PAL_USE_CALLBACKS == FALSE) && (PAL_USE_WAIT == TRUE)
282 #define _pal_init_event(e) \
283  do { \
284  osalThreadQueueObjectInit(&_pal_events[e].threads); \
285  } while (false)
286 #endif /* (PAL_USE_CALLBACKS == FALSE) && (PAL_USE_WAIT == TRUE) */
287 
288 #if ((PAL_USE_CALLBACKS == TRUE) && (PAL_USE_WAIT == TRUE)) || defined(__DOXYGEN__)
289 /**
290  * @brief Clears a PAL event object.
291  *
292  * @param[in] e event index
293  *
294  * @notapi
295  */
296 #define _pal_clear_event(e) \
297  do { \
298  osalThreadDequeueAllI(&_pal_events[pad].threads, MSG_RESET); \
299  _pal_events[e].cb = NULL; \
300  _pal_events[e].arg = NULL; \
301  } while (false)
302 #endif /* (PAL_USE_CALLBACKS == TRUE) && (PAL_USE_WAIT == TRUE) */
303 
304 #if (PAL_USE_CALLBACKS == TRUE) && (PAL_USE_WAIT == FALSE)
305 #define _pal_clear_event(e) \
306  do { \
307  _pal_events[e].cb = NULL; \
308  _pal_events[e].arg = NULL; \
309  } while (false)
310 #endif /* (PAL_USE_CALLBACKS == TRUE) && (PAL_USE_WAIT == FALSE) */
311 
312 #if (PAL_USE_CALLBACKS == FALSE) && (PAL_USE_WAIT == TRUE)
313 #define _pal_clear_event(e) \
314  do { \
315  osalThreadDequeueAllI(&_pal_events[pad].threads, MSG_RESET); \
316  } while (false)
317 #endif /* (PAL_USE_CALLBACKS == FALSE) && (PAL_USE_WAIT == TRUE) */
318 
319 /**
320  * @brief Common ISR code.
321  * @note This macro is meant to be used in the low level drivers
322  * implementation only.
323  *
324  * @param[in] e event index
325  *
326  * @notapi
327  */
328 #if ((PAL_USE_CALLBACKS == TRUE) && (PAL_USE_WAIT == TRUE)) || \
329  defined(__DOXYGEN__)
330 #define _pal_isr_code(e) do { \
331  if (_pal_events[e].cb != NULL) { \
332  _pal_events[e].cb(_pal_events[e].arg); \
333  } \
334  osalSysLockFromISR(); \
335  osalThreadDequeueAllI(&_pal_events[e].threads, MSG_OK); \
336  osalSysUnlockFromISR(); \
337 } while (false)
338 #endif /* (PAL_USE_CALLBACKS == TRUE) && (PAL_USE_WAIT == TRUE) */
339 
340 #if (PAL_USE_CALLBACKS == TRUE) && (PAL_USE_WAIT == FALSE)
341 #define _pal_isr_code(e) do { \
342  if (_pal_events[e].cb != NULL) { \
343  _pal_events[e].cb(_pal_events[e].arg); \
344  } \
345 } while (false)
346 #endif /* (PAL_USE_CALLBACKS == TRUE) && (PAL_USE_WAIT == FALSE) */
347 
348 #if ((PAL_USE_CALLBACKS == FALSE) && (PAL_USE_WAIT == TRUE)) || \
349  defined(__DOXYGEN__)
350 #define _pal_isr_code(e) do { \
351  osalSysLockFromISR(); \
352  osalThreadDequeueAllI(&_pal_events[e].threads, MSG_OK); \
353  osalSysUnlockFromISR(); \
354 } while (false)
355 #endif /* (PAL_USE_CALLBACKS == FALSE) && (PAL_USE_WAIT == TRUE) */
356 
357 /** @} */
358 #endif /* (PAL_USE_CALLBACKS == TRUE) || (PAL_USE_WAIT == TRUE) */
359 
360 /**
361  * @name Macro Functions
362  * @{
363  */
364 /**
365  * @brief PAL subsystem initialization.
366  * @note This function is implicitly invoked by @p halInit(), there is
367  * no need to explicitly initialize the driver.
368  *
369  * @init
370  */
371 #if defined(PAL_NEW_INIT) || defined(__DOXYGEN__)
372 #define palInit() pal_lld_init()
373 #else
374 #define palInit(config) pal_lld_init(config)
375 #endif
376 
377 /**
378  * @brief Reads the physical I/O port states.
379  * @note The function can be called from any context.
380  *
381  * @param[in] port port identifier
382  * @return The port logic states.
383  *
384  * @special
385  */
386 #if !defined(pal_lld_readport) || defined(__DOXYGEN__)
387 #define palReadPort(port) ((void)(port), 0U)
388 #else
389 #define palReadPort(port) pal_lld_readport(port)
390 #endif
391 
392 /**
393  * @brief Reads the output latch.
394  * @details The purpose of this function is to read back the latched output
395  * value.
396  * @note The function can be called from any context.
397  *
398  * @param[in] port port identifier
399  * @return The latched logic states.
400  *
401  * @special
402  */
403 #if !defined(pal_lld_readlatch) || defined(__DOXYGEN__)
404 #define palReadLatch(port) ((void)(port), 0U)
405 #else
406 #define palReadLatch(port) pal_lld_readlatch(port)
407 #endif
408 
409 /**
410  * @brief Writes a bits mask on a I/O port.
411  * @note The function can be called from any context.
412  *
413  * @param[in] port port identifier
414  * @param[in] bits bits to be written on the specified port
415  *
416  * @special
417  */
418 #if !defined(pal_lld_writeport) || defined(__DOXYGEN__)
419 #define palWritePort(port, bits) ((void)(port), (void)(bits))
420 #else
421 #define palWritePort(port, bits) pal_lld_writeport(port, bits)
422 #endif
423 
424 /**
425  * @brief Sets a bits mask on a I/O port.
426  * @note The operation is not guaranteed to be atomic on all the
427  * architectures, for atomicity and/or portability reasons you may
428  * need to enclose port I/O operations between @p osalSysLock() and
429  * @p osalSysUnlock().
430  * @note The function can be called from any context.
431  *
432  * @param[in] port port identifier
433  * @param[in] bits bits to be ORed on the specified port
434  *
435  * @special
436  */
437 #if !defined(pal_lld_setport) || defined(__DOXYGEN__)
438 #define palSetPort(port, bits) \
439  palWritePort(port, palReadLatch(port) | (bits))
440 #else
441 #define palSetPort(port, bits) pal_lld_setport(port, bits)
442 #endif
443 
444 /**
445  * @brief Clears a bits mask on a I/O port.
446  * @note The operation is not guaranteed to be atomic on all the
447  * architectures, for atomicity and/or portability reasons you may
448  * need to enclose port I/O operations between @p osalSysLock() and
449  * @p osalSysUnlock().
450  * @note The function can be called from any context.
451  *
452  * @param[in] port port identifier
453  * @param[in] bits bits to be cleared on the specified port
454  *
455  * @special
456  */
457 #if !defined(pal_lld_clearport) || defined(__DOXYGEN__)
458 #define palClearPort(port, bits) \
459  palWritePort(port, palReadLatch(port) & ~(bits))
460 #else
461 #define palClearPort(port, bits) pal_lld_clearport(port, bits)
462 #endif
463 
464 /**
465  * @brief Toggles a bits mask on a I/O port.
466  * @note The operation is not guaranteed to be atomic on all the
467  * architectures, for atomicity and/or portability reasons you may
468  * need to enclose port I/O operations between @p osalSysLock() and
469  * @p osalSysUnlock().
470  * @note The function can be called from any context.
471  *
472  * @param[in] port port identifier
473  * @param[in] bits bits to be XORed on the specified port
474  *
475  * @special
476  */
477 #if !defined(pal_lld_toggleport) || defined(__DOXYGEN__)
478 #define palTogglePort(port, bits) \
479  palWritePort(port, palReadLatch(port) ^ (bits))
480 #else
481 #define palTogglePort(port, bits) pal_lld_toggleport(port, bits)
482 #endif
483 
484 /**
485  * @brief Reads a group of bits.
486  * @note The function can be called from any context.
487  *
488  * @param[in] port port identifier
489  * @param[in] mask group mask, a logic AND is performed on the input
490  * data
491  * @param[in] offset group bit offset within the port
492  * @return The group logic states.
493  *
494  * @special
495  */
496 #if !defined(pal_lld_readgroup) || defined(__DOXYGEN__)
497 #define palReadGroup(port, mask, offset) \
498  ((palReadPort(port) >> (offset)) & (mask))
499 #else
500 #define palReadGroup(port, mask, offset) pal_lld_readgroup(port, mask, offset)
501 #endif
502 
503 /**
504  * @brief Writes a group of bits.
505  * @note The operation is not guaranteed to be atomic on all the
506  * architectures, for atomicity and/or portability reasons you may
507  * need to enclose port I/O operations between @p osalSysLock() and
508  * @p osalSysUnlock().
509  * @note The function can be called from any context.
510  *
511  * @param[in] port port identifier
512  * @param[in] mask group mask, a logic AND is performed on the
513  * output data
514  * @param[in] offset group bit offset within the port
515  * @param[in] bits bits to be written. Values exceeding the group
516  * width are masked.
517  *
518  * @special
519  */
520 #if !defined(pal_lld_writegroup) || defined(__DOXYGEN__)
521 #define palWriteGroup(port, mask, offset, bits) \
522  palWritePort(port, (palReadLatch(port) & ~((mask) << (offset))) | \
523  (((bits) & (mask)) << (offset)))
524 #else
525 #define palWriteGroup(port, mask, offset, bits) \
526  pal_lld_writegroup(port, mask, offset, bits)
527 #endif
528 
529 /**
530  * @brief Pads group mode setup.
531  * @details This function programs a pads group belonging to the same port
532  * with the specified mode.
533  * @note The operation is not guaranteed to be atomic on all the
534  * architectures, for atomicity and/or portability reasons you may
535  * need to enclose port I/O operations between @p osalSysLock() and
536  * @p osalSysUnlock().
537  * @note Programming an unknown or unsupported mode is silently ignored.
538  * @note The function can be called from any context.
539  *
540  * @param[in] port port identifier
541  * @param[in] mask group mask
542  * @param[in] offset group bit offset within the port
543  * @param[in] mode group mode
544  *
545  * @special
546  */
547 #if !defined(pal_lld_setgroupmode) || defined(__DOXYGEN__)
548 #define palSetGroupMode(port, mask, offset, mode)
549 #else
550 #define palSetGroupMode(port, mask, offset, mode) \
551  pal_lld_setgroupmode(port, mask, offset, mode)
552 #endif
553 
554 /**
555  * @brief Reads an input pad logic state.
556  * @note The function can be called from any context.
557  *
558  * @param[in] port port identifier
559  * @param[in] pad pad number within the port
560  * @return The logic state.
561  * @retval PAL_LOW low logic state.
562  * @retval PAL_HIGH high logic state.
563  *
564  * @special
565  */
566 #if !defined(pal_lld_readpad) || defined(__DOXYGEN__)
567 #define palReadPad(port, pad) ((palReadPort(port) >> (pad)) & 1U)
568 #else
569 #define palReadPad(port, pad) pal_lld_readpad(port, pad)
570 #endif
571 
572 /**
573  * @brief Writes a logic state on an output pad.
574  * @note The operation is not guaranteed to be atomic on all the
575  * architectures, for atomicity and/or portability reasons you may
576  * need to enclose port I/O operations between @p osalSysLock() and
577  * @p osalSysUnlock().
578  * @note The function can be called from any context.
579  *
580  * @param[in] port port identifier
581  * @param[in] pad pad number within the port
582  * @param[in] bit logic value, the value must be @p PAL_LOW or
583  * @p PAL_HIGH
584  *
585  * @special
586  */
587 #if !defined(pal_lld_writepad) || defined(__DOXYGEN__)
588 #define palWritePad(port, pad, bit) \
589  palWritePort(port, (palReadLatch(port) & ~PAL_PORT_BIT(pad)) | \
590  (((bit) & 1U) << pad))
591 #else
592 #define palWritePad(port, pad, bit) pal_lld_writepad(port, pad, bit)
593 #endif
594 
595 /**
596  * @brief Sets a pad logic state to @p PAL_HIGH.
597  * @note The operation is not guaranteed to be atomic on all the
598  * architectures, for atomicity and/or portability reasons you may
599  * need to enclose port I/O operations between @p osalSysLock() and
600  * @p osalSysUnlock().
601  * @note The function can be called from any context.
602  *
603  * @param[in] port port identifier
604  * @param[in] pad pad number within the port
605  *
606  * @special
607  */
608 #if !defined(pal_lld_setpad) || defined(__DOXYGEN__)
609 #define palSetPad(port, pad) palSetPort(port, PAL_PORT_BIT(pad))
610 #else
611 #define palSetPad(port, pad) pal_lld_setpad(port, pad)
612 #endif
613 
614 /**
615  * @brief Clears a pad logic state to @p PAL_LOW.
616  * @note The operation is not guaranteed to be atomic on all the
617  * architectures, for atomicity and/or portability reasons you may
618  * need to enclose port I/O operations between @p osalSysLock() and
619  * @p osalSysUnlock().
620  * @note The function can be called from any context.
621  *
622  * @param[in] port port identifier
623  * @param[in] pad pad number within the port
624  *
625  * @special
626  */
627 #if !defined(pal_lld_clearpad) || defined(__DOXYGEN__)
628 #define palClearPad(port, pad) palClearPort(port, PAL_PORT_BIT(pad))
629 #else
630 #define palClearPad(port, pad) pal_lld_clearpad(port, pad)
631 #endif
632 
633 /**
634  * @brief Toggles a pad logic state.
635  * @note The operation is not guaranteed to be atomic on all the
636  * architectures, for atomicity and/or portability reasons you may
637  * need to enclose port I/O operations between @p osalSysLock() and
638  * @p osalSysUnlock().
639  * @note The function can be called from any context.
640  *
641  * @param[in] port port identifier
642  * @param[in] pad pad number within the port
643  *
644  * @special
645  */
646 #if !defined(pal_lld_togglepad) || defined(__DOXYGEN__)
647 #define palTogglePad(port, pad) palTogglePort(port, PAL_PORT_BIT(pad))
648 #else
649 #define palTogglePad(port, pad) pal_lld_togglepad(port, pad)
650 #endif
651 
652 /**
653  * @brief Pad mode setup.
654  * @details This function programs a pad with the specified mode.
655  * @note The operation is not guaranteed to be atomic on all the
656  * architectures, for atomicity and/or portability reasons you may
657  * need to enclose port I/O operations between @p osalSysLock() and
658  * @p osalSysUnlock().
659  * @note Programming an unknown or unsupported mode is silently ignored.
660  * @note The function can be called from any context.
661  *
662  * @param[in] port port identifier
663  * @param[in] pad pad number within the port
664  * @param[in] mode pad mode
665  *
666  * @special
667  */
668 #if !defined(pal_lld_setpadmode) || defined(__DOXYGEN__)
669 #define palSetPadMode(port, pad, mode) \
670  palSetGroupMode(port, PAL_PORT_BIT(pad), 0U, mode)
671 #else
672 #define palSetPadMode(port, pad, mode) pal_lld_setpadmode(port, pad, mode)
673 #endif
674 
675 /**
676  * @brief Reads an input line logic state.
677  * @note The function can be called from any context.
678  *
679  * @param[in] line line identifier
680  * @return The logic state.
681  * @retval PAL_LOW low logic state.
682  * @retval PAL_HIGH high logic state.
683  *
684  * @special
685  */
686 #if !defined(pal_lld_readline) || defined(__DOXYGEN__)
687 #define palReadLine(line) palReadPad(PAL_PORT(line), PAL_PAD(line))
688 #else
689 #define palReadLine(line) pal_lld_readline(line)
690 #endif
691 
692 /**
693  * @brief Writes a logic state on an output line.
694  * @note The operation is not guaranteed to be atomic on all the
695  * architectures, for atomicity and/or portability reasons you may
696  * need to enclose port I/O operations between @p osalSysLock() and
697  * @p osalSysUnlock().
698  * @note The function can be called from any context.
699  *
700  * @param[in] line line identifier
701  * @param[in] bit logic value, the value must be @p PAL_LOW or
702  * @p PAL_HIGH
703  *
704  * @special
705  */
706 #if !defined(pal_lld_writeline) || defined(__DOXYGEN__)
707 #define palWriteLine(line, bit) palWritePad(PAL_PORT(line), PAL_PAD(line), bit)
708 #else
709 #define palWriteLine(line, bit) pal_lld_writeline(line, bit)
710 #endif
711 
712 /**
713  * @brief Sets a line logic state to @p PAL_HIGH.
714  * @note The operation is not guaranteed to be atomic on all the
715  * architectures, for atomicity and/or portability reasons you may
716  * need to enclose port I/O operations between @p osalSysLock() and
717  * @p osalSysUnlock().
718  * @note The function can be called from any context.
719  *
720  * @param[in] line line identifier
721  *
722  * @special
723  */
724 #if !defined(pal_lld_setline) || defined(__DOXYGEN__)
725 #define palSetLine(line) palSetPad(PAL_PORT(line), PAL_PAD(line))
726 #else
727 #define palSetLine(line) pal_lld_setline(line)
728 #endif
729 
730 /**
731  * @brief Clears a line logic state to @p PAL_LOW.
732  * @note The operation is not guaranteed to be atomic on all the
733  * architectures, for atomicity and/or portability reasons you may
734  * need to enclose port I/O operations between @p osalSysLock() and
735  * @p osalSysUnlock().
736  * @note The function can be called from any context.
737  *
738  * @param[in] line line identifier
739  *
740  * @special
741  */
742 #if !defined(pal_lld_clearline) || defined(__DOXYGEN__)
743 #define palClearLine(line) palClearPad(PAL_PORT(line), PAL_PAD(line))
744 #else
745 #define palClearLine(line) pal_lld_clearline(line)
746 #endif
747 
748 /**
749  * @brief Toggles a line logic state.
750  * @note The operation is not guaranteed to be atomic on all the
751  * architectures, for atomicity and/or portability reasons you may
752  * need to enclose port I/O operations between @p osalSysLock() and
753  * @p osalSysUnlock().
754  * @note The function can be called from any context.
755  *
756  * @param[in] line line identifier
757  *
758  * @special
759  */
760 #if !defined(pal_lld_toggleline) || defined(__DOXYGEN__)
761 #define palToggleLine(line) palTogglePad(PAL_PORT(line), PAL_PAD(line))
762 #else
763 #define palToggleLine(line) pal_lld_toggleline(line)
764 #endif
765 
766 /**
767  * @brief Line mode setup.
768  * @note The operation is not guaranteed to be atomic on all the
769  * architectures, for atomicity and/or portability reasons you may
770  * need to enclose port I/O operations between @p osalSysLock() and
771  * @p osalSysUnlock().
772  * @note The function can be called from any context.
773  *
774  * @param[in] line line identifier
775  * @param[in] mode pad mode
776  *
777  * @special
778  */
779 #if !defined(pal_lld_setlinemode) || defined(__DOXYGEN__)
780 #define palSetLineMode(line, mode) \
781  palSetPadMode(PAL_PORT(line), PAL_PAD(line), mode)
782 #else
783 #define palSetLineMode(line, mode) pal_lld_setlinemode(line, mode)
784 #endif
785 
786 #if (PAL_USE_CALLBACKS == TRUE) || (PAL_USE_WAIT == TRUE) || \
787  defined(__DOXYGEN__)
788 /**
789  * @brief Pad event enable.
790  * @note Programming an unknown or unsupported mode is silently ignored.
791  *
792  * @param[in] port port identifier
793  * @param[in] pad pad number within the port
794  * @param[in] mode pad event mode
795  *
796  * @iclass
797  */
798 #if !defined(pal_lld_enablepadevent) || defined(__DOXYGEN__)
799 #define palEnablePadEventI(port, pad, mode)
800 #else
801 #define palEnablePadEventI(port, pad, mode) \
802  pal_lld_enablepadevent(port, pad, mode)
803 #endif
804 
805 /**
806  * @brief Pad event disable.
807  * @details This function also disables previously programmed event callbacks.
808  *
809  * @param[in] port port identifier
810  * @param[in] pad pad number within the port
811  *
812  * @iclass
813  */
814 #if !defined(pal_lld_disablepadevent) || defined(__DOXYGEN__)
815 #define palDisablePadEventI(port, pad)
816 #else
817 #define palDisablePadEventI(port, pad) \
818  pal_lld_disablepadevent(port, pad)
819 #endif
820 
821 /**
822  * @brief Pad event enable.
823  * @note Programming an unknown or unsupported mode is silently ignored.
824  *
825  * @param[in] port port identifier
826  * @param[in] pad pad number within the port
827  * @param[in] mode pad event mode
828  *
829  * @api
830  */
831 #define palEnablePadEvent(port, pad, mode) \
832  do { \
833  osalSysLock(); \
834  palEnablePadEventI(port, pad, mode); \
835  osalSysUnlock(); \
836  } while (false)
837 
838 /**
839  * @brief Pad event disable.
840  * @details This function also disables previously programmed event callbacks.
841  *
842  * @param[in] port port identifier
843  * @param[in] pad pad number within the port
844  *
845  * @api
846  */
847 #define palDisablePadEvent(port, pad) \
848  do { \
849  osalSysLock(); \
850  palDisablePadEventI(port, pad); \
851  osalSysUnlock(); \
852  } while (false)
853 
854 /**
855  * @brief Line event enable.
856  * @note Programming an unknown or unsupported mode is silently ignored.
857  *
858  * @param[in] line line identifier
859  * @param[in] mode line event mode
860  *
861  * @iclass
862  */
863 #if !defined(pal_lld_enablelineevent) || defined(__DOXYGEN__)
864 #define palEnableLineEventI(line, mode) \
865  palEnablePadEventI(PAL_PORT(line), PAL_PAD(line), mode)
866 #else
867 #define palEnableLineEventI(line, mode) \
868  pal_lld_enablelineevent(line, mode)
869 #endif
870 
871 /**
872  * @brief Line event disable.
873  * @details This function also disables previously programmed event callbacks.
874  *
875  * @param[in] line line identifier
876  *
877  * @iclass
878  */
879 #if !defined(pal_lld_disablelineevent) || defined(__DOXYGEN__)
880 #define palDisableLineEventI(line) \
881  palDisablePadEventI(PAL_PORT(line), PAL_PAD(line))
882 #else
883 #define palDisableLineEventI(line) pal_lld_disablelineevent(line)
884 #endif
885 
886 /**
887  * @brief Line event enable.
888  * @note Programming an unknown or unsupported mode is silently ignored.
889  *
890  * @param[in] line line identifier
891  * @param[in] mode line event mode
892  *
893  * @api
894  */
895 #define palEnableLineEvent(line, mode) \
896  do { \
897  osalSysLock(); \
898  palEnableLineEventI(line, mode); \
899  osalSysUnlock(); \
900  } while (false)
901 
902 /**
903  * @brief Line event disable.
904  * @details This function also disables previously programmed event callbacks.
905  *
906  * @param[in] line line identifier
907  *
908  * @api
909  */
910 #define palDisableLineEvent(line) \
911  do { \
912  osalSysLock(); \
913  palDisableLineEventI(line); \
914  osalSysUnlock(); \
915  } while (false)
916 
917 #endif /* PAL_USE_CALLBACKS || PAL_USE_WAIT */
918 
919 #if (PAL_USE_CALLBACKS == TRUE) || defined(__DOXYGEN__)
920 /**
921  * @brief Associates a callback to a pad.
922  *
923  * @param[in] port port identifier
924  * @param[in] pad pad number within the port
925  * @param[in] cb event callback function
926  * @param[in] arg callback argument
927  *
928  * @api
929  */
930 #define palSetPadCallback(port, pad, cb, arg) \
931  do { \
932  osalSysLock(); \
933  palSetPadCallbackI(port, pad, cb, arg); \
934  osalSysUnlock(); \
935  } while (false)
936 
937 /**
938  * @brief Associates a callback to a line.
939  *
940  * @param[in] line line identifier
941  * @param[in] cb event callback function
942  * @param[in] arg callback argument
943  *
944  * @api
945  */
946 #define palSetLineCallback(line, cb, arg) \
947  do { \
948  osalSysLock(); \
949  palSetLineCallbackI(line, cb, arg); \
950  osalSysUnlock(); \
951  } while (false)
952 #endif /* PAL_USE_CALLBACKS == TRUE */
953 
954 /** @} */
955 
956 /*===========================================================================*/
957 /* External declarations. */
958 /*===========================================================================*/
959 
960 #ifdef __cplusplus
961 extern "C" {
962 #endif
963  ioportmask_t palReadBus(const IOBus *bus);
964  void palWriteBus(const IOBus *bus, ioportmask_t bits);
965  void palSetBusMode(const IOBus *bus, iomode_t mode);
966 #if (PAL_USE_CALLBACKS == TRUE) || defined(__DOXYGEN__)
967  void palSetPadCallbackI(ioportid_t port, iopadid_t pad,
968  palcallback_t cb, void *arg);
969  void palSetLineCallbackI(ioline_t line, palcallback_t cb, void *arg);
970 #endif /* PAL_USE_CALLBACKS == TRUE */
971 #if (PAL_USE_WAIT == TRUE) || defined(__DOXYGEN__)
973  sysinterval_t timeout);
975  sysinterval_t timeout);
978 #endif /* PAL_USE_WAIT == TRUE */
979 #ifdef __cplusplus
980 }
981 #endif
982 
983 #endif /* HAL_PAL_H */
984 
985 #endif /* HAL_USE_PAL == TRUE */
986 
987 /** @} */
ioportmask_t mask
Bus mask aligned to port bit 0.
Definition: hal_pal.h:193
Type of a PAL event record.
Definition: hal_pal.h:154
uint32_t ioportmask_t
Digital I/O port sized unsigned type.
Definition: hal_pal_lld.h:100
uint32_t iopadid_t
Type of an pad identifier.
Definition: hal_pal_lld.h:123
palcallback_t cb
Event callback.
Definition: hal_pal.h:165
uint32_t ioline_t
Type of an I/O line.
Definition: hal_pal_lld.h:110
ioportid_t portid
Port identifier.
Definition: hal_pal.h:187
msg_t palWaitLineTimeout(ioline_t line, sysinterval_t timeout)
Waits for an edge on the specified line.
Definition: hal_pal.c:245
msg_t palWaitPadTimeout(ioportid_t port, iopadid_t pad, sysinterval_t timeout)
Waits for an edge on the specified port/pad.
Definition: hal_pal.c:201
int32_t msg_t
Type of a message.
Definition: osal.h:160
ioportmask_t palReadBus(const IOBus *bus)
Read from an I/O bus.
Definition: hal_pal.c:65
Type of a thread queue.
Definition: osal.h:232
uint32_t ioportid_t
Port Identifier.
Definition: hal_pal_lld.h:118
void palSetLineCallbackI(ioline_t line, palcallback_t cb, void *arg)
Associates a callback to a line.
Definition: hal_pal.c:148
uint_fast8_t offset
Offset, within the port, of the least significant bit of the bus.
Definition: hal_pal.h:197
msg_t palWaitPadTimeoutS(ioportid_t port, iopadid_t pad, sysinterval_t timeout)
Waits for an edge on the specified port/pad.
Definition: hal_pal.c:175
void * arg
Event callback argument.
Definition: hal_pal.h:169
uint32_t sysinterval_t
Type of system time interval.
Definition: osal.h:170
void palSetPadCallbackI(ioportid_t port, iopadid_t pad, palcallback_t cb, void *arg)
Associates a callback to a port/pad.
Definition: hal_pal.c:131
void palWriteBus(const IOBus *bus, ioportmask_t bits)
Write to an I/O bus.
Definition: hal_pal.c:90
msg_t palWaitLineTimeoutS(ioline_t line, sysinterval_t timeout)
Waits for an edge on the specified line.
Definition: hal_pal.c:225
I/O bus descriptor.
Definition: hal_pal.h:183
void palSetBusMode(const IOBus *bus, iomode_t mode)
Programs a bus with the specified mode.
Definition: hal_pal.c:113
uint32_t iomode_t
Digital I/O modes.
Definition: hal_pal_lld.h:105
PLATFORM PAL subsystem low level driver header.
threads_queue_t threads
Threads queued for an event.
Definition: hal_pal.h:159
void(* palcallback_t)(void *arg)
Type of a PAL event callback.
Definition: hal_pal.h:148