ChibiOS  21.6.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) \
331  do { \
332  if (_pal_events[e].cb != NULL) { \
333  _pal_events[e].cb(_pal_events[e].arg); \
334  } \
335  osalSysLockFromISR(); \
336  osalThreadDequeueAllI(&_pal_events[e].threads, MSG_OK); \
337  osalSysUnlockFromISR(); \
338  } while (false)
339 #endif /* (PAL_USE_CALLBACKS == TRUE) && (PAL_USE_WAIT == TRUE) */
340 
341 #if (PAL_USE_CALLBACKS == TRUE) && (PAL_USE_WAIT == FALSE)
342 #define _pal_isr_code(e) \
343  do { \
344  if (_pal_events[e].cb != NULL) { \
345  _pal_events[e].cb(_pal_events[e].arg); \
346  } \
347  } while (false)
348 #endif /* (PAL_USE_CALLBACKS == TRUE) && (PAL_USE_WAIT == FALSE) */
349 
350 #if ((PAL_USE_CALLBACKS == FALSE) && (PAL_USE_WAIT == TRUE)) || \
351  defined(__DOXYGEN__)
352 #define _pal_isr_code(e) \
353  do { \
354  osalSysLockFromISR(); \
355  osalThreadDequeueAllI(&_pal_events[e].threads, MSG_OK); \
356  osalSysUnlockFromISR(); \
357  } while (false)
358 #endif /* (PAL_USE_CALLBACKS == FALSE) && (PAL_USE_WAIT == TRUE) */
359 
360 /** @} */
361 #endif /* (PAL_USE_CALLBACKS == TRUE) || (PAL_USE_WAIT == TRUE) */
362 
363 /**
364  * @name Macro Functions
365  * @{
366  */
367 /**
368  * @brief PAL subsystem initialization.
369  * @note This function is implicitly invoked by @p halInit(), there is
370  * no need to explicitly initialize the driver.
371  *
372  * @init
373  */
374 #if defined(PAL_NEW_INIT) || defined(__DOXYGEN__)
375 #define palInit() pal_lld_init()
376 #else
377 #define palInit(config) pal_lld_init(config)
378 #endif
379 
380 /**
381  * @brief Reads the physical I/O port states.
382  * @note The function can be called from any context.
383  *
384  * @param[in] port port identifier
385  * @return The port logic states.
386  *
387  * @special
388  */
389 #if !defined(pal_lld_readport) || defined(__DOXYGEN__)
390 #define palReadPort(port) ((void)(port), 0U)
391 #else
392 #define palReadPort(port) pal_lld_readport(port)
393 #endif
394 
395 /**
396  * @brief Reads the output latch.
397  * @details The purpose of this function is to read back the latched output
398  * value.
399  * @note The function can be called from any context.
400  *
401  * @param[in] port port identifier
402  * @return The latched logic states.
403  *
404  * @special
405  */
406 #if !defined(pal_lld_readlatch) || defined(__DOXYGEN__)
407 #define palReadLatch(port) ((void)(port), 0U)
408 #else
409 #define palReadLatch(port) pal_lld_readlatch(port)
410 #endif
411 
412 /**
413  * @brief Writes a bits mask on a I/O port.
414  * @note The function can be called from any context.
415  *
416  * @param[in] port port identifier
417  * @param[in] bits bits to be written on the specified port
418  *
419  * @special
420  */
421 #if !defined(pal_lld_writeport) || defined(__DOXYGEN__)
422 #define palWritePort(port, bits) ((void)(port), (void)(bits))
423 #else
424 #define palWritePort(port, bits) pal_lld_writeport(port, bits)
425 #endif
426 
427 /**
428  * @brief Sets a bits mask on a I/O port.
429  * @note The operation is not guaranteed to be atomic on all the
430  * architectures, for atomicity and/or portability reasons you may
431  * need to enclose port I/O operations between @p osalSysLock() and
432  * @p osalSysUnlock().
433  * @note The function can be called from any context.
434  *
435  * @param[in] port port identifier
436  * @param[in] bits bits to be ORed on the specified port
437  *
438  * @special
439  */
440 #if !defined(pal_lld_setport) || defined(__DOXYGEN__)
441 #define palSetPort(port, bits) \
442  palWritePort(port, palReadLatch(port) | (bits))
443 #else
444 #define palSetPort(port, bits) pal_lld_setport(port, bits)
445 #endif
446 
447 /**
448  * @brief Clears a bits mask on a I/O port.
449  * @note The operation is not guaranteed to be atomic on all the
450  * architectures, for atomicity and/or portability reasons you may
451  * need to enclose port I/O operations between @p osalSysLock() and
452  * @p osalSysUnlock().
453  * @note The function can be called from any context.
454  *
455  * @param[in] port port identifier
456  * @param[in] bits bits to be cleared on the specified port
457  *
458  * @special
459  */
460 #if !defined(pal_lld_clearport) || defined(__DOXYGEN__)
461 #define palClearPort(port, bits) \
462  palWritePort(port, palReadLatch(port) & ~(bits))
463 #else
464 #define palClearPort(port, bits) pal_lld_clearport(port, bits)
465 #endif
466 
467 /**
468  * @brief Toggles a bits mask on a I/O port.
469  * @note The operation is not guaranteed to be atomic on all the
470  * architectures, for atomicity and/or portability reasons you may
471  * need to enclose port I/O operations between @p osalSysLock() and
472  * @p osalSysUnlock().
473  * @note The function can be called from any context.
474  *
475  * @param[in] port port identifier
476  * @param[in] bits bits to be XORed on the specified port
477  *
478  * @special
479  */
480 #if !defined(pal_lld_toggleport) || defined(__DOXYGEN__)
481 #define palTogglePort(port, bits) \
482  palWritePort(port, palReadLatch(port) ^ (bits))
483 #else
484 #define palTogglePort(port, bits) pal_lld_toggleport(port, bits)
485 #endif
486 
487 /**
488  * @brief Reads a group of bits.
489  * @note The function can be called from any context.
490  *
491  * @param[in] port port identifier
492  * @param[in] mask group mask, a logic AND is performed on the input
493  * data
494  * @param[in] offset group bit offset within the port
495  * @return The group logic states.
496  *
497  * @special
498  */
499 #if !defined(pal_lld_readgroup) || defined(__DOXYGEN__)
500 #define palReadGroup(port, mask, offset) \
501  ((palReadPort(port) >> (offset)) & (mask))
502 #else
503 #define palReadGroup(port, mask, offset) pal_lld_readgroup(port, mask, offset)
504 #endif
505 
506 /**
507  * @brief Writes a group of bits.
508  * @note The operation is not guaranteed to be atomic on all the
509  * architectures, for atomicity and/or portability reasons you may
510  * need to enclose port I/O operations between @p osalSysLock() and
511  * @p osalSysUnlock().
512  * @note The function can be called from any context.
513  *
514  * @param[in] port port identifier
515  * @param[in] mask group mask, a logic AND is performed on the
516  * output data
517  * @param[in] offset group bit offset within the port
518  * @param[in] bits bits to be written. Values exceeding the group
519  * width are masked.
520  *
521  * @special
522  */
523 #if !defined(pal_lld_writegroup) || defined(__DOXYGEN__)
524 #define palWriteGroup(port, mask, offset, bits) \
525  palWritePort(port, (palReadLatch(port) & ~((mask) << (offset))) | \
526  (((bits) & (mask)) << (offset)))
527 #else
528 #define palWriteGroup(port, mask, offset, bits) \
529  pal_lld_writegroup(port, mask, offset, bits)
530 #endif
531 
532 /**
533  * @brief Pads group mode setup.
534  * @details This function programs a pads group belonging to the same port
535  * with the specified mode.
536  * @note The operation is not guaranteed to be atomic on all the
537  * architectures, for atomicity and/or portability reasons you may
538  * need to enclose port I/O operations between @p osalSysLock() and
539  * @p osalSysUnlock().
540  * @note Programming an unknown or unsupported mode is silently ignored.
541  * @note The function can be called from any context.
542  *
543  * @param[in] port port identifier
544  * @param[in] mask group mask
545  * @param[in] offset group bit offset within the port
546  * @param[in] mode group mode
547  *
548  * @special
549  */
550 #if !defined(pal_lld_setgroupmode) || defined(__DOXYGEN__)
551 #define palSetGroupMode(port, mask, offset, mode) \
552  do { \
553  (void)(port); \
554  (void)(mask); \
555  (void)(offset); \
556  (void)(port); \
557  } while (mode)
558 #else
559 #define palSetGroupMode(port, mask, offset, mode) \
560  pal_lld_setgroupmode(port, mask, offset, mode)
561 #endif
562 
563 /**
564  * @brief Reads an input pad logic state.
565  * @note The function can be called from any context.
566  *
567  * @param[in] port port identifier
568  * @param[in] pad pad number within the port
569  * @return The logic state.
570  * @retval PAL_LOW low logic state.
571  * @retval PAL_HIGH high logic state.
572  *
573  * @special
574  */
575 #if !defined(pal_lld_readpad) || defined(__DOXYGEN__)
576 #define palReadPad(port, pad) ((palReadPort(port) >> (pad)) & 1U)
577 #else
578 #define palReadPad(port, pad) pal_lld_readpad(port, pad)
579 #endif
580 
581 /**
582  * @brief Writes a logic state on an output pad.
583  * @note The operation is not guaranteed to be atomic on all the
584  * architectures, for atomicity and/or portability reasons you may
585  * need to enclose port I/O operations between @p osalSysLock() and
586  * @p osalSysUnlock().
587  * @note The function can be called from any context.
588  *
589  * @param[in] port port identifier
590  * @param[in] pad pad number within the port
591  * @param[in] bit logic value, the value must be @p PAL_LOW or
592  * @p PAL_HIGH
593  *
594  * @special
595  */
596 #if !defined(pal_lld_writepad) || defined(__DOXYGEN__)
597 #define palWritePad(port, pad, bit) \
598  palWritePort(port, (palReadLatch(port) & ~PAL_PORT_BIT(pad)) | \
599  (((bit) & 1U) << pad))
600 #else
601 #define palWritePad(port, pad, bit) pal_lld_writepad(port, pad, bit)
602 #endif
603 
604 /**
605  * @brief Sets a pad logic state to @p PAL_HIGH.
606  * @note The operation is not guaranteed to be atomic on all the
607  * architectures, for atomicity and/or portability reasons you may
608  * need to enclose port I/O operations between @p osalSysLock() and
609  * @p osalSysUnlock().
610  * @note The function can be called from any context.
611  *
612  * @param[in] port port identifier
613  * @param[in] pad pad number within the port
614  *
615  * @special
616  */
617 #if !defined(pal_lld_setpad) || defined(__DOXYGEN__)
618 #define palSetPad(port, pad) palSetPort(port, PAL_PORT_BIT(pad))
619 #else
620 #define palSetPad(port, pad) pal_lld_setpad(port, pad)
621 #endif
622 
623 /**
624  * @brief Clears a pad logic state to @p PAL_LOW.
625  * @note The operation is not guaranteed to be atomic on all the
626  * architectures, for atomicity and/or portability reasons you may
627  * need to enclose port I/O operations between @p osalSysLock() and
628  * @p osalSysUnlock().
629  * @note The function can be called from any context.
630  *
631  * @param[in] port port identifier
632  * @param[in] pad pad number within the port
633  *
634  * @special
635  */
636 #if !defined(pal_lld_clearpad) || defined(__DOXYGEN__)
637 #define palClearPad(port, pad) palClearPort(port, PAL_PORT_BIT(pad))
638 #else
639 #define palClearPad(port, pad) pal_lld_clearpad(port, pad)
640 #endif
641 
642 /**
643  * @brief Toggles a pad logic state.
644  * @note The operation is not guaranteed to be atomic on all the
645  * architectures, for atomicity and/or portability reasons you may
646  * need to enclose port I/O operations between @p osalSysLock() and
647  * @p osalSysUnlock().
648  * @note The function can be called from any context.
649  *
650  * @param[in] port port identifier
651  * @param[in] pad pad number within the port
652  *
653  * @special
654  */
655 #if !defined(pal_lld_togglepad) || defined(__DOXYGEN__)
656 #define palTogglePad(port, pad) palTogglePort(port, PAL_PORT_BIT(pad))
657 #else
658 #define palTogglePad(port, pad) pal_lld_togglepad(port, pad)
659 #endif
660 
661 /**
662  * @brief Pad mode setup.
663  * @details This function programs a pad with the specified mode.
664  * @note The operation is not guaranteed to be atomic on all the
665  * architectures, for atomicity and/or portability reasons you may
666  * need to enclose port I/O operations between @p osalSysLock() and
667  * @p osalSysUnlock().
668  * @note Programming an unknown or unsupported mode is silently ignored.
669  * @note The function can be called from any context.
670  *
671  * @param[in] port port identifier
672  * @param[in] pad pad number within the port
673  * @param[in] mode pad mode
674  *
675  * @special
676  */
677 #if !defined(pal_lld_setpadmode) || defined(__DOXYGEN__)
678 #define palSetPadMode(port, pad, mode) \
679  palSetGroupMode(port, PAL_PORT_BIT(pad), 0U, mode)
680 #else
681 #define palSetPadMode(port, pad, mode) pal_lld_setpadmode(port, pad, mode)
682 #endif
683 
684 /**
685  * @brief Reads an input line logic state.
686  * @note The function can be called from any context.
687  *
688  * @param[in] line line identifier
689  * @return The logic state.
690  * @retval PAL_LOW low logic state.
691  * @retval PAL_HIGH high logic state.
692  *
693  * @special
694  */
695 #if !defined(pal_lld_readline) || defined(__DOXYGEN__)
696 #define palReadLine(line) palReadPad(PAL_PORT(line), PAL_PAD(line))
697 #else
698 #define palReadLine(line) pal_lld_readline(line)
699 #endif
700 
701 /**
702  * @brief Writes a logic state on an output line.
703  * @note The operation is not guaranteed to be atomic on all the
704  * architectures, for atomicity and/or portability reasons you may
705  * need to enclose port I/O operations between @p osalSysLock() and
706  * @p osalSysUnlock().
707  * @note The function can be called from any context.
708  *
709  * @param[in] line line identifier
710  * @param[in] bit logic value, the value must be @p PAL_LOW or
711  * @p PAL_HIGH
712  *
713  * @special
714  */
715 #if !defined(pal_lld_writeline) || defined(__DOXYGEN__)
716 #define palWriteLine(line, bit) palWritePad(PAL_PORT(line), PAL_PAD(line), bit)
717 #else
718 #define palWriteLine(line, bit) pal_lld_writeline(line, bit)
719 #endif
720 
721 /**
722  * @brief Sets a line logic state to @p PAL_HIGH.
723  * @note The operation is not guaranteed to be atomic on all the
724  * architectures, for atomicity and/or portability reasons you may
725  * need to enclose port I/O operations between @p osalSysLock() and
726  * @p osalSysUnlock().
727  * @note The function can be called from any context.
728  *
729  * @param[in] line line identifier
730  *
731  * @special
732  */
733 #if !defined(pal_lld_setline) || defined(__DOXYGEN__)
734 #define palSetLine(line) palSetPad(PAL_PORT(line), PAL_PAD(line))
735 #else
736 #define palSetLine(line) pal_lld_setline(line)
737 #endif
738 
739 /**
740  * @brief Clears a line logic state to @p PAL_LOW.
741  * @note The operation is not guaranteed to be atomic on all the
742  * architectures, for atomicity and/or portability reasons you may
743  * need to enclose port I/O operations between @p osalSysLock() and
744  * @p osalSysUnlock().
745  * @note The function can be called from any context.
746  *
747  * @param[in] line line identifier
748  *
749  * @special
750  */
751 #if !defined(pal_lld_clearline) || defined(__DOXYGEN__)
752 #define palClearLine(line) palClearPad(PAL_PORT(line), PAL_PAD(line))
753 #else
754 #define palClearLine(line) pal_lld_clearline(line)
755 #endif
756 
757 /**
758  * @brief Toggles a line logic state.
759  * @note The operation is not guaranteed to be atomic on all the
760  * architectures, for atomicity and/or portability reasons you may
761  * need to enclose port I/O operations between @p osalSysLock() and
762  * @p osalSysUnlock().
763  * @note The function can be called from any context.
764  *
765  * @param[in] line line identifier
766  *
767  * @special
768  */
769 #if !defined(pal_lld_toggleline) || defined(__DOXYGEN__)
770 #define palToggleLine(line) palTogglePad(PAL_PORT(line), PAL_PAD(line))
771 #else
772 #define palToggleLine(line) pal_lld_toggleline(line)
773 #endif
774 
775 /**
776  * @brief Line mode setup.
777  * @note The operation is not guaranteed to be atomic on all the
778  * architectures, for atomicity and/or portability reasons you may
779  * need to enclose port I/O operations between @p osalSysLock() and
780  * @p osalSysUnlock().
781  * @note The function can be called from any context.
782  *
783  * @param[in] line line identifier
784  * @param[in] mode pad mode
785  *
786  * @special
787  */
788 #if !defined(pal_lld_setlinemode) || defined(__DOXYGEN__)
789 #define palSetLineMode(line, mode) \
790  palSetPadMode(PAL_PORT(line), PAL_PAD(line), mode)
791 #else
792 #define palSetLineMode(line, mode) pal_lld_setlinemode(line, mode)
793 #endif
794 
795 #if (PAL_USE_CALLBACKS == TRUE) || (PAL_USE_WAIT == TRUE) || \
796  defined(__DOXYGEN__)
797 /**
798  * @brief Pad event enable.
799  * @note Programming an unknown or unsupported mode is silently ignored.
800  *
801  * @param[in] port port identifier
802  * @param[in] pad pad number within the port
803  * @param[in] mode pad event mode
804  *
805  * @iclass
806  */
807 #if !defined(pal_lld_enablepadevent) || defined(__DOXYGEN__)
808 #define palEnablePadEventI(port, pad, mode)
809 #else
810 #define palEnablePadEventI(port, pad, mode) \
811  pal_lld_enablepadevent(port, pad, mode)
812 #endif
813 
814 /**
815  * @brief Pad event disable.
816  * @details This function also disables previously programmed event callbacks.
817  *
818  * @param[in] port port identifier
819  * @param[in] pad pad number within the port
820  *
821  * @iclass
822  */
823 #if !defined(pal_lld_disablepadevent) || defined(__DOXYGEN__)
824 #define palDisablePadEventI(port, pad)
825 #else
826 #define palDisablePadEventI(port, pad) \
827  pal_lld_disablepadevent(port, pad)
828 #endif
829 
830 /**
831  * @brief Pad event enable.
832  * @note Programming an unknown or unsupported mode is silently ignored.
833  *
834  * @param[in] port port identifier
835  * @param[in] pad pad number within the port
836  * @param[in] mode pad event mode
837  *
838  * @api
839  */
840 #define palEnablePadEvent(port, pad, mode) \
841  do { \
842  osalSysLock(); \
843  palEnablePadEventI(port, pad, mode); \
844  osalSysUnlock(); \
845  } while (false)
846 
847 /**
848  * @brief Pad event disable.
849  * @details This function also disables previously programmed event callbacks.
850  *
851  * @param[in] port port identifier
852  * @param[in] pad pad number within the port
853  *
854  * @api
855  */
856 #define palDisablePadEvent(port, pad) \
857  do { \
858  osalSysLock(); \
859  palDisablePadEventI(port, pad); \
860  osalSysUnlock(); \
861  } while (false)
862 
863 /**
864  * @brief Line event enable.
865  * @note Programming an unknown or unsupported mode is silently ignored.
866  *
867  * @param[in] line line identifier
868  * @param[in] mode line event mode
869  *
870  * @iclass
871  */
872 #if !defined(pal_lld_enablelineevent) || defined(__DOXYGEN__)
873 #define palEnableLineEventI(line, mode) \
874  palEnablePadEventI(PAL_PORT(line), PAL_PAD(line), mode)
875 #else
876 #define palEnableLineEventI(line, mode) \
877  pal_lld_enablelineevent(line, mode)
878 #endif
879 
880 /**
881  * @brief Line event disable.
882  * @details This function also disables previously programmed event callbacks.
883  *
884  * @param[in] line line identifier
885  *
886  * @iclass
887  */
888 #if !defined(pal_lld_disablelineevent) || defined(__DOXYGEN__)
889 #define palDisableLineEventI(line) \
890  palDisablePadEventI(PAL_PORT(line), PAL_PAD(line))
891 #else
892 #define palDisableLineEventI(line) pal_lld_disablelineevent(line)
893 #endif
894 
895 /**
896  * @brief Line event enable.
897  * @note Programming an unknown or unsupported mode is silently ignored.
898  *
899  * @param[in] line line identifier
900  * @param[in] mode line event mode
901  *
902  * @api
903  */
904 #define palEnableLineEvent(line, mode) \
905  do { \
906  osalSysLock(); \
907  palEnableLineEventI(line, mode); \
908  osalSysUnlock(); \
909  } while (false)
910 
911 /**
912  * @brief Line event disable.
913  * @details This function also disables previously programmed event callbacks.
914  *
915  * @param[in] line line identifier
916  *
917  * @api
918  */
919 #define palDisableLineEvent(line) \
920  do { \
921  osalSysLock(); \
922  palDisableLineEventI(line); \
923  osalSysUnlock(); \
924  } while (false)
925 
926 /**
927  * @brief Pad event enable check.
928  *
929  * @param[in] port port identifier
930  * @param[in] pad pad number within the port
931  * @return Pad event status.
932  * @retval false if the pad event is disabled.
933  * @retval true if the pad event is enabled.
934  *
935  * @xclass
936  */
937 #if !defined(pal_lld_ispadeventenabled) || defined(__DOXYGEN__)
938 #define palIsPadEventEnabledX(port, pad) false
939 #else
940 #define palIsPadEventEnabledX(port, pad) \
941  pal_lld_ispadeventenabled(port, pad)
942 #endif
943 
944 /**
945  * @brief Line event enable check.
946  *
947  * @param[in] line line identifier
948  * @return Line event status.
949  * @retval false if the line event is disabled.
950  * @retval true if the line event is enabled.
951  *
952  * @xclass
953  */
954 #if !defined(pal_lld_islineeventenabled) || defined(__DOXYGEN__)
955 #define palIsLineEventEnabledX(line) \
956  pal_lld_ispadeventenabled(PAL_PORT(line), PAL_PAD(line))
957 #else
958 #define palIsLineEventEnabledX(line) \
959  pal_lld_islineeventenabled(line)
960 #endif
961 
962 #endif /* PAL_USE_CALLBACKS || PAL_USE_WAIT */
963 
964 #if (PAL_USE_CALLBACKS == TRUE) || defined(__DOXYGEN__)
965 /**
966  * @brief Associates a callback to a pad.
967  *
968  * @param[in] port port identifier
969  * @param[in] pad pad number within the port
970  * @param[in] cb event callback function
971  * @param[in] arg callback argument
972  *
973  * @api
974  */
975 #define palSetPadCallback(port, pad, cb, arg) \
976  do { \
977  osalSysLock(); \
978  palSetPadCallbackI(port, pad, cb, arg); \
979  osalSysUnlock(); \
980  } while (false)
981 
982 /**
983  * @brief Associates a callback to a line.
984  *
985  * @param[in] line line identifier
986  * @param[in] cb event callback function
987  * @param[in] arg callback argument
988  *
989  * @api
990  */
991 #define palSetLineCallback(line, cb, arg) \
992  do { \
993  osalSysLock(); \
994  palSetLineCallbackI(line, cb, arg); \
995  osalSysUnlock(); \
996  } while (false)
997 #endif /* PAL_USE_CALLBACKS == TRUE */
998 
999 /** @} */
1000 
1001 /*===========================================================================*/
1002 /* External declarations. */
1003 /*===========================================================================*/
1004 
1005 #ifdef __cplusplus
1006 extern "C" {
1007 #endif
1008  ioportmask_t palReadBus(const IOBus *bus);
1009  void palWriteBus(const IOBus *bus, ioportmask_t bits);
1010  void palSetBusMode(const IOBus *bus, iomode_t mode);
1011 #if (PAL_USE_CALLBACKS == TRUE) || defined(__DOXYGEN__)
1012  void palSetPadCallbackI(ioportid_t port, iopadid_t pad,
1013  palcallback_t cb, void *arg);
1014  void palSetLineCallbackI(ioline_t line, palcallback_t cb, void *arg);
1015 #endif /* PAL_USE_CALLBACKS == TRUE */
1016 #if (PAL_USE_WAIT == TRUE) || defined(__DOXYGEN__)
1018  sysinterval_t timeout);
1020  sysinterval_t timeout);
1023 #endif /* PAL_USE_WAIT == TRUE */
1024 #ifdef __cplusplus
1025 }
1026 #endif
1027 
1028 #endif /* HAL_PAL_H */
1029 
1030 #endif /* HAL_USE_PAL == TRUE */
1031 
1032 /** @} */
ioportid_t
uint32_t ioportid_t
Port Identifier.
Definition: hal_pal_lld.h:122
IOBus::portid
ioportid_t portid
Port identifier.
Definition: hal_pal.h:187
iopadid_t
uint32_t iopadid_t
Type of an pad identifier.
Definition: hal_pal_lld.h:127
iomode_t
uint32_t iomode_t
Digital I/O modes.
Definition: hal_pal_lld.h:109
palWaitPadTimeout
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
palSetPadCallbackI
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
msg_t
int32_t msg_t
Definition: chearly.h:88
ioportmask_t
uint32_t ioportmask_t
Digital I/O port sized unsigned type.
Definition: hal_pal_lld.h:104
palSetBusMode
void palSetBusMode(const IOBus *bus, iomode_t mode)
Programs a bus with the specified mode.
Definition: hal_pal.c:113
palevent_t::arg
void * arg
Event callback argument.
Definition: hal_pal.h:169
palevent_t::cb
palcallback_t cb
Event callback.
Definition: hal_pal.h:165
palWaitLineTimeoutS
msg_t palWaitLineTimeoutS(ioline_t line, sysinterval_t timeout)
Waits for an edge on the specified line.
Definition: hal_pal.c:225
palReadBus
ioportmask_t palReadBus(const IOBus *bus)
Read from an I/O bus.
Definition: hal_pal.c:65
threads_queue_t
Type of a thread queue.
Definition: osal.h:238
palWriteBus
void palWriteBus(const IOBus *bus, ioportmask_t bits)
Write to an I/O bus.
Definition: hal_pal.c:90
ioline_t
uint32_t ioline_t
Type of an I/O line.
Definition: hal_pal_lld.h:114
palWaitPadTimeoutS
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
sysinterval_t
uint64_t sysinterval_t
Type of time interval.
Definition: chtime.h:119
palevent_t::threads
threads_queue_t threads
Threads queued for an event.
Definition: hal_pal.h:159
IOBus
I/O bus descriptor.
Definition: hal_pal.h:183
hal_pal_lld.h
PLATFORM PAL subsystem low level driver header.
palevent_t
Type of a PAL event record.
Definition: hal_pal.h:154
palcallback_t
void(* palcallback_t)(void *arg)
Type of a PAL event callback.
Definition: hal_pal.h:148
palSetLineCallbackI
void palSetLineCallbackI(ioline_t line, palcallback_t cb, void *arg)
Associates a callback to a line.
Definition: hal_pal.c:148
IOBus::mask
ioportmask_t mask
Bus mask aligned to port bit 0.
Definition: hal_pal.h:193
IOBus::offset
uint_fast8_t offset
Offset, within the port, of the least significant bit of the bus.
Definition: hal_pal.h:197
palWaitLineTimeout
msg_t palWaitLineTimeout(ioline_t line, sysinterval_t timeout)
Waits for an edge on the specified line.
Definition: hal_pal.c:245