ChibiOS  0.0.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 /**
151  * @brief Type of a PAL event record.
152  */
153 typedef struct {
154 #if (PAL_USE_WAIT == TRUE) || defined(__DOXYGEN__)
155  /**
156  * @brief Threads queued for an event.
157  */
159 #endif
160 #if (PAL_USE_CALLBACKS == TRUE) || defined(__DOXYGEN__)
161  /**
162  * @brief Event callback.
163  */
165  /**
166  * @brief Event callback argument.
167  */
168  void *arg;
169 #endif
170 } palevent_t;
171 
172 #include "hal_pal_lld.h"
173 
174 /**
175  * @brief I/O bus descriptor.
176  * @details This structure describes a group of contiguous digital I/O lines
177  * that have to be handled as bus.
178  * @note I/O operations on a bus do not affect I/O lines on the same port but
179  * not belonging to the bus.
180  */
181 typedef struct {
182  /**
183  * @brief Port identifier.
184  */
186  /**
187  * @brief Bus mask aligned to port bit 0.
188  * @note The bus mask implicitly define the bus width. A logic AND is
189  * performed on the bus data.
190  */
192  /**
193  * @brief Offset, within the port, of the least significant bit of the bus.
194  */
195  uint_fast8_t offset;
196 } IOBus;
197 
198 /*===========================================================================*/
199 /* Driver macros. */
200 /*===========================================================================*/
201 
202 /**
203  * @brief Port bit helper macro.
204  * @details This macro calculates the mask of a bit within a port.
205  *
206  * @param[in] n bit position within the port
207  * @return The bit mask.
208  */
209 #if !defined(PAL_PORT_BIT) || defined(__DOXYGEN__)
210 #define PAL_PORT_BIT(n) ((ioportmask_t)(1U << (n)))
211 #endif
212 
213 /**
214  * @brief Bits group mask helper.
215  * @details This macro calculates the mask of a bits group.
216  *
217  * @param[in] width group width
218  * @return The group mask.
219  */
220 #if !defined(PAL_GROUP_MASK) || defined(__DOXYGEN__)
221 #define PAL_GROUP_MASK(width) ((ioportmask_t)(1U << (width)) - 1U)
222 #endif
223 
224 /**
225  * @brief Data part of a static I/O bus initializer.
226  * @details This macro should be used when statically initializing an I/O bus
227  * that is part of a bigger structure.
228  *
229  * @param[in] name name of the IOBus variable
230  * @param[in] port I/O port descriptor
231  * @param[in] width bus width in bits
232  * @param[in] offset bus bit offset within the port
233  */
234 #define _IOBUS_DATA(name, port, width, offset) \
235  {port, PAL_GROUP_MASK(width), offset}
236 
237 /**
238  * @brief Static I/O bus initializer.
239  *
240  * @param[in] name name of the IOBus variable
241  * @param[in] port I/O port descriptor
242  * @param[in] width bus width in bits
243  * @param[in] offset bus bit offset within the port
244  */
245 #define IOBUS_DECL(name, port, width, offset) \
246  IOBus name = _IOBUS_DATA(name, port, width, offset)
247 
248 #if (PAL_USE_CALLBACKS == TRUE) || (PAL_USE_WAIT == TRUE) || \
249  defined(__DOXYGEN__)
250 /**
251  * @name Low level driver helper macros
252  * @{
253  */
254 #if ((PAL_USE_CALLBACKS == TRUE) && (PAL_USE_WAIT == TRUE)) || \
255  defined(__DOXYGEN__)
256 /**
257  * @brief Initializes a PAL event object.
258  *
259  * @param[in] e event index
260  *
261  * @notapi
262  */
263 #define _pal_init_event(e) \
264  do { \
265  osalThreadQueueObjectInit(&_pal_events[e].threads); \
266  _pal_events[e].cb = NULL; \
267  _pal_events[e].arg = NULL; \
268  } while (false)
269 #endif /* (PAL_USE_CALLBACKS == TRUE) && (PAL_USE_WAIT == TRUE) */
270 
271 #if (PAL_USE_CALLBACKS == TRUE) && (PAL_USE_WAIT == FALSE)
272 #define _pal_init_event(e) \
273  do { \
274  _pal_events[e].cb = NULL; \
275  _pal_events[e].arg = NULL; \
276  } while (false)
277 #endif /* (PAL_USE_CALLBACKS == TRUE) && (PAL_USE_WAIT == FALSE) */
278 
279 #if (PAL_USE_CALLBACKS == FALSE) && (PAL_USE_WAIT == TRUE)
280 #define _pal_init_event(e) \
281  do { \
282  osalThreadQueueObjectInit(&_pal_events[e].threads); \
283  } while (false)
284 #endif /* (PAL_USE_CALLBACKS == FALSE) && (PAL_USE_WAIT == TRUE) */
285 
286 #if ((PAL_USE_CALLBACKS == TRUE) && (PAL_USE_WAIT == TRUE)) || defined(__DOXYGEN__)
287 /**
288  * @brief Clears a PAL event object.
289  *
290  * @param[in] e event index
291  *
292  * @notapi
293  */
294 #define _pal_clear_event(e) \
295  do { \
296  osalThreadDequeueAllI(&_pal_events[pad].threads, MSG_RESET); \
297  _pal_events[e].cb = NULL; \
298  _pal_events[e].arg = NULL; \
299  } while (false)
300 #endif /* (PAL_USE_CALLBACKS == TRUE) && (PAL_USE_WAIT == TRUE) */
301 
302 #if (PAL_USE_CALLBACKS == TRUE) && (PAL_USE_WAIT == FALSE)
303 #define _pal_clear_event(e) \
304  do { \
305  _pal_events[e].cb = NULL; \
306  _pal_events[e].arg = NULL; \
307  } while (false)
308 #endif /* (PAL_USE_CALLBACKS == TRUE) && (PAL_USE_WAIT == FALSE) */
309 
310 #if (PAL_USE_CALLBACKS == FALSE) && (PAL_USE_WAIT == TRUE)
311 #define _pal_clear_event(e) \
312  do { \
313  osalThreadDequeueAllI(&_pal_events[pad].threads, MSG_RESET); \
314  } while (false)
315 #endif /* (PAL_USE_CALLBACKS == FALSE) && (PAL_USE_WAIT == TRUE) */
316 
317 /**
318  * @brief Common ISR code.
319  * @note This macro is meant to be used in the low level drivers
320  * implementation only.
321  *
322  * @param[in] e event index
323  *
324  * @notapi
325  */
326 #if ((PAL_USE_CALLBACKS == TRUE) && (PAL_USE_WAIT == TRUE)) || \
327  defined(__DOXYGEN__)
328 #define _pal_isr_code(e) do { \
329  if (_pal_events[e].cb != NULL) { \
330  _pal_events[e].cb(_pal_events[e].arg); \
331  } \
332  osalSysLockFromISR(); \
333  osalThreadDequeueAllI(&_pal_events[e].threads, MSG_OK); \
334  osalSysUnlockFromISR(); \
335 } while (false)
336 #endif /* (PAL_USE_CALLBACKS == TRUE) && (PAL_USE_WAIT == TRUE) */
337 
338 #if (PAL_USE_CALLBACKS == TRUE) && (PAL_USE_WAIT == FALSE)
339 #define _pal_isr_code(e) do { \
340  if (_pal_events[e].cb != NULL) { \
341  _pal_events[e].cb(_pal_events[e].arg); \
342  } \
343 } while (false)
344 #endif /* (PAL_USE_CALLBACKS == TRUE) && (PAL_USE_WAIT == FALSE) */
345 
346 #if ((PAL_USE_CALLBACKS == FALSE) && (PAL_USE_WAIT == TRUE)) || \
347  defined(__DOXYGEN__)
348 #define _pal_isr_code(e) do { \
349  osalSysLockFromISR(); \
350  osalThreadDequeueAllI(&_pal_events[e].threads, MSG_OK); \
351  osalSysUnlockFromISR(); \
352 } while (false)
353 #endif /* (PAL_USE_CALLBACKS == FALSE) && (PAL_USE_WAIT == TRUE) */
354 
355 /** @} */
356 #endif /* (PAL_USE_CALLBACKS == TRUE) || (PAL_USE_WAIT == TRUE) */
357 
358 /**
359  * @name Macro Functions
360  * @{
361  */
362 /**
363  * @brief PAL subsystem initialization.
364  * @note This function is implicitly invoked by @p halInit(), there is
365  * no need to explicitly initialize the driver.
366  *
367  * @init
368  */
369 #if defined(PAL_NEW_INIT) || defined(__DOXYGEN__)
370 #define palInit() pal_lld_init()
371 #else
372 #define palInit(config) pal_lld_init(config)
373 #endif
374 
375 /**
376  * @brief Reads the physical I/O port states.
377  * @note The function can be called from any context.
378  *
379  * @param[in] port port identifier
380  * @return The port logic states.
381  *
382  * @special
383  */
384 #if !defined(pal_lld_readport) || defined(__DOXYGEN__)
385 #define palReadPort(port) ((void)(port), 0U)
386 #else
387 #define palReadPort(port) pal_lld_readport(port)
388 #endif
389 
390 /**
391  * @brief Reads the output latch.
392  * @details The purpose of this function is to read back the latched output
393  * value.
394  * @note The function can be called from any context.
395  *
396  * @param[in] port port identifier
397  * @return The latched logic states.
398  *
399  * @special
400  */
401 #if !defined(pal_lld_readlatch) || defined(__DOXYGEN__)
402 #define palReadLatch(port) ((void)(port), 0U)
403 #else
404 #define palReadLatch(port) pal_lld_readlatch(port)
405 #endif
406 
407 /**
408  * @brief Writes a bits mask on a I/O port.
409  * @note The function can be called from any context.
410  *
411  * @param[in] port port identifier
412  * @param[in] bits bits to be written on the specified port
413  *
414  * @special
415  */
416 #if !defined(pal_lld_writeport) || defined(__DOXYGEN__)
417 #define palWritePort(port, bits) ((void)(port), (void)(bits))
418 #else
419 #define palWritePort(port, bits) pal_lld_writeport(port, bits)
420 #endif
421 
422 /**
423  * @brief Sets a bits mask on a I/O port.
424  * @note The operation is not guaranteed to be atomic on all the
425  * architectures, for atomicity and/or portability reasons you may
426  * need to enclose port I/O operations between @p osalSysLock() and
427  * @p osalSysUnlock().
428  * @note The function can be called from any context.
429  *
430  * @param[in] port port identifier
431  * @param[in] bits bits to be ORed on the specified port
432  *
433  * @special
434  */
435 #if !defined(pal_lld_setport) || defined(__DOXYGEN__)
436 #define palSetPort(port, bits) \
437  palWritePort(port, palReadLatch(port) | (bits))
438 #else
439 #define palSetPort(port, bits) pal_lld_setport(port, bits)
440 #endif
441 
442 /**
443  * @brief Clears a bits mask on a I/O port.
444  * @note The operation is not guaranteed to be atomic on all the
445  * architectures, for atomicity and/or portability reasons you may
446  * need to enclose port I/O operations between @p osalSysLock() and
447  * @p osalSysUnlock().
448  * @note The function can be called from any context.
449  *
450  * @param[in] port port identifier
451  * @param[in] bits bits to be cleared on the specified port
452  *
453  * @special
454  */
455 #if !defined(pal_lld_clearport) || defined(__DOXYGEN__)
456 #define palClearPort(port, bits) \
457  palWritePort(port, palReadLatch(port) & ~(bits))
458 #else
459 #define palClearPort(port, bits) pal_lld_clearport(port, bits)
460 #endif
461 
462 /**
463  * @brief Toggles a bits mask on a I/O port.
464  * @note The operation is not guaranteed to be atomic on all the
465  * architectures, for atomicity and/or portability reasons you may
466  * need to enclose port I/O operations between @p osalSysLock() and
467  * @p osalSysUnlock().
468  * @note The function can be called from any context.
469  *
470  * @param[in] port port identifier
471  * @param[in] bits bits to be XORed on the specified port
472  *
473  * @special
474  */
475 #if !defined(pal_lld_toggleport) || defined(__DOXYGEN__)
476 #define palTogglePort(port, bits) \
477  palWritePort(port, palReadLatch(port) ^ (bits))
478 #else
479 #define palTogglePort(port, bits) pal_lld_toggleport(port, bits)
480 #endif
481 
482 /**
483  * @brief Reads a group of bits.
484  * @note The function can be called from any context.
485  *
486  * @param[in] port port identifier
487  * @param[in] mask group mask, a logic AND is performed on the input
488  * data
489  * @param[in] offset group bit offset within the port
490  * @return The group logic states.
491  *
492  * @special
493  */
494 #if !defined(pal_lld_readgroup) || defined(__DOXYGEN__)
495 #define palReadGroup(port, mask, offset) \
496  ((palReadPort(port) >> (offset)) & (mask))
497 #else
498 #define palReadGroup(port, mask, offset) pal_lld_readgroup(port, mask, offset)
499 #endif
500 
501 /**
502  * @brief Writes a group of bits.
503  * @note The operation is not guaranteed to be atomic on all the
504  * architectures, for atomicity and/or portability reasons you may
505  * need to enclose port I/O operations between @p osalSysLock() and
506  * @p osalSysUnlock().
507  * @note The function can be called from any context.
508  *
509  * @param[in] port port identifier
510  * @param[in] mask group mask, a logic AND is performed on the
511  * output data
512  * @param[in] offset group bit offset within the port
513  * @param[in] bits bits to be written. Values exceeding the group
514  * width are masked.
515  *
516  * @special
517  */
518 #if !defined(pal_lld_writegroup) || defined(__DOXYGEN__)
519 #define palWriteGroup(port, mask, offset, bits) \
520  palWritePort(port, (palReadLatch(port) & ~((mask) << (offset))) | \
521  (((bits) & (mask)) << (offset)))
522 #else
523 #define palWriteGroup(port, mask, offset, bits) \
524  pal_lld_writegroup(port, mask, offset, bits)
525 #endif
526 
527 /**
528  * @brief Pads group mode setup.
529  * @details This function programs a pads group belonging to the same port
530  * with the specified mode.
531  * @note The operation is not guaranteed to be atomic on all the
532  * architectures, for atomicity and/or portability reasons you may
533  * need to enclose port I/O operations between @p osalSysLock() and
534  * @p osalSysUnlock().
535  * @note Programming an unknown or unsupported mode is silently ignored.
536  * @note The function can be called from any context.
537  *
538  * @param[in] port port identifier
539  * @param[in] mask group mask
540  * @param[in] offset group bit offset within the port
541  * @param[in] mode group mode
542  *
543  * @special
544  */
545 #if !defined(pal_lld_setgroupmode) || defined(__DOXYGEN__)
546 #define palSetGroupMode(port, mask, offset, mode)
547 #else
548 #define palSetGroupMode(port, mask, offset, mode) \
549  pal_lld_setgroupmode(port, mask, offset, mode)
550 #endif
551 
552 /**
553  * @brief Reads an input pad logic state.
554  * @note The function can be called from any context.
555  *
556  * @param[in] port port identifier
557  * @param[in] pad pad number within the port
558  * @return The logic state.
559  * @retval PAL_LOW low logic state.
560  * @retval PAL_HIGH high logic state.
561  *
562  * @special
563  */
564 #if !defined(pal_lld_readpad) || defined(__DOXYGEN__)
565 #define palReadPad(port, pad) ((palReadPort(port) >> (pad)) & 1U)
566 #else
567 #define palReadPad(port, pad) pal_lld_readpad(port, pad)
568 #endif
569 
570 /**
571  * @brief Writes a logic state on an output pad.
572  * @note The operation is not guaranteed to be atomic on all the
573  * architectures, for atomicity and/or portability reasons you may
574  * need to enclose port I/O operations between @p osalSysLock() and
575  * @p osalSysUnlock().
576  * @note The function can be called from any context.
577  *
578  * @param[in] port port identifier
579  * @param[in] pad pad number within the port
580  * @param[in] bit logic value, the value must be @p PAL_LOW or
581  * @p PAL_HIGH
582  *
583  * @special
584  */
585 #if !defined(pal_lld_writepad) || defined(__DOXYGEN__)
586 #define palWritePad(port, pad, bit) \
587  palWritePort(port, (palReadLatch(port) & ~PAL_PORT_BIT(pad)) | \
588  (((bit) & 1U) << pad))
589 #else
590 #define palWritePad(port, pad, bit) pal_lld_writepad(port, pad, bit)
591 #endif
592 
593 /**
594  * @brief Sets a pad logic state to @p PAL_HIGH.
595  * @note The operation is not guaranteed to be atomic on all the
596  * architectures, for atomicity and/or portability reasons you may
597  * need to enclose port I/O operations between @p osalSysLock() and
598  * @p osalSysUnlock().
599  * @note The function can be called from any context.
600  *
601  * @param[in] port port identifier
602  * @param[in] pad pad number within the port
603  *
604  * @special
605  */
606 #if !defined(pal_lld_setpad) || defined(__DOXYGEN__)
607 #define palSetPad(port, pad) palSetPort(port, PAL_PORT_BIT(pad))
608 #else
609 #define palSetPad(port, pad) pal_lld_setpad(port, pad)
610 #endif
611 
612 /**
613  * @brief Clears a pad logic state to @p PAL_LOW.
614  * @note The operation is not guaranteed to be atomic on all the
615  * architectures, for atomicity and/or portability reasons you may
616  * need to enclose port I/O operations between @p osalSysLock() and
617  * @p osalSysUnlock().
618  * @note The function can be called from any context.
619  *
620  * @param[in] port port identifier
621  * @param[in] pad pad number within the port
622  *
623  * @special
624  */
625 #if !defined(pal_lld_clearpad) || defined(__DOXYGEN__)
626 #define palClearPad(port, pad) palClearPort(port, PAL_PORT_BIT(pad))
627 #else
628 #define palClearPad(port, pad) pal_lld_clearpad(port, pad)
629 #endif
630 
631 /**
632  * @brief Toggles a pad logic state.
633  * @note The operation is not guaranteed to be atomic on all the
634  * architectures, for atomicity and/or portability reasons you may
635  * need to enclose port I/O operations between @p osalSysLock() and
636  * @p osalSysUnlock().
637  * @note The function can be called from any context.
638  *
639  * @param[in] port port identifier
640  * @param[in] pad pad number within the port
641  *
642  * @special
643  */
644 #if !defined(pal_lld_togglepad) || defined(__DOXYGEN__)
645 #define palTogglePad(port, pad) palTogglePort(port, PAL_PORT_BIT(pad))
646 #else
647 #define palTogglePad(port, pad) pal_lld_togglepad(port, pad)
648 #endif
649 
650 /**
651  * @brief Pad mode setup.
652  * @details This function programs a pad with the specified mode.
653  * @note The operation is not guaranteed to be atomic on all the
654  * architectures, for atomicity and/or portability reasons you may
655  * need to enclose port I/O operations between @p osalSysLock() and
656  * @p osalSysUnlock().
657  * @note Programming an unknown or unsupported mode is silently ignored.
658  * @note The function can be called from any context.
659  *
660  * @param[in] port port identifier
661  * @param[in] pad pad number within the port
662  * @param[in] mode pad mode
663  *
664  * @special
665  */
666 #if !defined(pal_lld_setpadmode) || defined(__DOXYGEN__)
667 #define palSetPadMode(port, pad, mode) \
668  palSetGroupMode(port, PAL_PORT_BIT(pad), 0U, mode)
669 #else
670 #define palSetPadMode(port, pad, mode) pal_lld_setpadmode(port, pad, mode)
671 #endif
672 
673 /**
674  * @brief Reads an input line logic state.
675  * @note The function can be called from any context.
676  *
677  * @param[in] line line identifier
678  * @return The logic state.
679  * @retval PAL_LOW low logic state.
680  * @retval PAL_HIGH high logic state.
681  *
682  * @special
683  */
684 #if !defined(pal_lld_readline) || defined(__DOXYGEN__)
685 #define palReadLine(line) palReadPad(PAL_PORT(line), PAL_PAD(line))
686 #else
687 #define palReadLine(line) pal_lld_readline(line)
688 #endif
689 
690 /**
691  * @brief Writes a logic state on an output line.
692  * @note The operation is not guaranteed to be atomic on all the
693  * architectures, for atomicity and/or portability reasons you may
694  * need to enclose port I/O operations between @p osalSysLock() and
695  * @p osalSysUnlock().
696  * @note The function can be called from any context.
697  *
698  * @param[in] line line identifier
699  * @param[in] bit logic value, the value must be @p PAL_LOW or
700  * @p PAL_HIGH
701  *
702  * @special
703  */
704 #if !defined(pal_lld_writeline) || defined(__DOXYGEN__)
705 #define palWriteLine(line, bit) palWritePad(PAL_PORT(line), PAL_PAD(line), bit)
706 #else
707 #define palWriteLine(line, bit) pal_lld_writeline(line, bit)
708 #endif
709 
710 /**
711  * @brief Sets a line logic state to @p PAL_HIGH.
712  * @note The operation is not guaranteed to be atomic on all the
713  * architectures, for atomicity and/or portability reasons you may
714  * need to enclose port I/O operations between @p osalSysLock() and
715  * @p osalSysUnlock().
716  * @note The function can be called from any context.
717  *
718  * @param[in] line line identifier
719  *
720  * @special
721  */
722 #if !defined(pal_lld_setline) || defined(__DOXYGEN__)
723 #define palSetLine(line) palSetPad(PAL_PORT(line), PAL_PAD(line))
724 #else
725 #define palSetLine(line) pal_lld_setline(line)
726 #endif
727 
728 /**
729  * @brief Clears a line logic state to @p PAL_LOW.
730  * @note The operation is not guaranteed to be atomic on all the
731  * architectures, for atomicity and/or portability reasons you may
732  * need to enclose port I/O operations between @p osalSysLock() and
733  * @p osalSysUnlock().
734  * @note The function can be called from any context.
735  *
736  * @param[in] line line identifier
737  *
738  * @special
739  */
740 #if !defined(pal_lld_clearline) || defined(__DOXYGEN__)
741 #define palClearLine(line) palClearPad(PAL_PORT(line), PAL_PAD(line))
742 #else
743 #define palClearLine(line) pal_lld_clearline(line)
744 #endif
745 
746 /**
747  * @brief Toggles a line logic state.
748  * @note The operation is not guaranteed to be atomic on all the
749  * architectures, for atomicity and/or portability reasons you may
750  * need to enclose port I/O operations between @p osalSysLock() and
751  * @p osalSysUnlock().
752  * @note The function can be called from any context.
753  *
754  * @param[in] line line identifier
755  *
756  * @special
757  */
758 #if !defined(pal_lld_toggleline) || defined(__DOXYGEN__)
759 #define palToggleLine(line) palTogglePad(PAL_PORT(line), PAL_PAD(line))
760 #else
761 #define palToggleLine(line) pal_lld_toggleline(line)
762 #endif
763 
764 /**
765  * @brief Line mode setup.
766  * @note The operation is not guaranteed to be atomic on all the
767  * architectures, for atomicity and/or portability reasons you may
768  * need to enclose port I/O operations between @p osalSysLock() and
769  * @p osalSysUnlock().
770  * @note The function can be called from any context.
771  *
772  * @param[in] line line identifier
773  * @param[in] mode pad mode
774  *
775  * @special
776  */
777 #if !defined(pal_lld_setlinemode) || defined(__DOXYGEN__)
778 #define palSetLineMode(line, mode) \
779  palSetPadMode(PAL_PORT(line), PAL_PAD(line), mode)
780 #else
781 #define palSetLineMode(line, mode) pal_lld_setlinemode(line, mode)
782 #endif
783 
784 #if (PAL_USE_CALLBACKS == TRUE) || (PAL_USE_WAIT == TRUE) || \
785  defined(__DOXYGEN__)
786 /**
787  * @brief Pad event enable.
788  * @note Programming an unknown or unsupported mode is silently ignored.
789  *
790  * @param[in] port port identifier
791  * @param[in] pad pad number within the port
792  * @param[in] mode pad event mode
793  *
794  * @iclass
795  */
796 #if !defined(pal_lld_enablepadevent) || defined(__DOXYGEN__)
797 #define palEnablePadEventI(port, pad, mode)
798 #else
799 #define palEnablePadEventI(port, pad, mode) \
800  pal_lld_enablepadevent(port, pad, mode)
801 #endif
802 
803 /**
804  * @brief Pad event disable.
805  * @details This function also disables previously programmed event callbacks.
806  *
807  * @param[in] port port identifier
808  * @param[in] pad pad number within the port
809  *
810  * @iclass
811  */
812 #if !defined(pal_lld_disablepadevent) || defined(__DOXYGEN__)
813 #define palDisablePadEventI(port, pad)
814 #else
815 #define palDisablePadEventI(port, pad) \
816  pal_lld_disablepadevent(port, pad)
817 #endif
818 
819 /**
820  * @brief Pad event enable.
821  * @note Programming an unknown or unsupported mode is silently ignored.
822  *
823  * @param[in] port port identifier
824  * @param[in] pad pad number within the port
825  * @param[in] mode pad event mode
826  *
827  * @api
828  */
829 #define palEnablePadEvent(port, pad, mode) \
830  do { \
831  osalSysLock(); \
832  palEnablePadEventI(port, pad, mode); \
833  osalSysUnlock(); \
834  } while (false)
835 
836 /**
837  * @brief Pad event disable.
838  * @details This function also disables previously programmed event callbacks.
839  *
840  * @param[in] port port identifier
841  * @param[in] pad pad number within the port
842  *
843  * @api
844  */
845 #define palDisablePadEvent(port, pad) \
846  do { \
847  osalSysLock(); \
848  palDisablePadEventI(port, pad); \
849  osalSysUnlock(); \
850  } while (false)
851 
852 /**
853  * @brief Line event enable.
854  * @note Programming an unknown or unsupported mode is silently ignored.
855  *
856  * @param[in] line line identifier
857  * @param[in] mode line event mode
858  *
859  * @iclass
860  */
861 #if !defined(pal_lld_enablelineevent) || defined(__DOXYGEN__)
862 #define palEnableLineEventI(line, mode) \
863  palEnablePadEventI(PAL_PORT(line), PAL_PAD(line), mode)
864 #else
865 #define palEnableLineEventI(line, mode) \
866  pal_lld_enablelineevent(line, mode)
867 #endif
868 
869 /**
870  * @brief Line event disable.
871  * @details This function also disables previously programmed event callbacks.
872  *
873  * @param[in] line line identifier
874  *
875  * @iclass
876  */
877 #if !defined(pal_lld_disablelineevent) || defined(__DOXYGEN__)
878 #define palDisableLineEventI(line) \
879  palDisablePadEventI(PAL_PORT(line), PAL_PAD(line))
880 #else
881 #define palDisableLineEventI(line) pal_lld_disablelineevent(line)
882 #endif
883 
884 /**
885  * @brief Line event enable.
886  * @note Programming an unknown or unsupported mode is silently ignored.
887  *
888  * @param[in] line line identifier
889  * @param[in] mode line event mode
890  *
891  * @api
892  */
893 #define palEnableLineEvent(line, mode) \
894  do { \
895  osalSysLock(); \
896  palEnableLineEventI(line, mode); \
897  osalSysUnlock(); \
898  } while (false)
899 
900 /**
901  * @brief Line event disable.
902  * @details This function also disables previously programmed event callbacks.
903  *
904  * @param[in] line line identifier
905  *
906  * @api
907  */
908 #define palDisableLineEvent(line) \
909  do { \
910  osalSysLock(); \
911  palDisableLineEventI(line); \
912  osalSysUnlock(); \
913  } while (false)
914 
915 #endif /* PAL_USE_CALLBACKS || PAL_USE_WAIT */
916 
917 #if (PAL_USE_CALLBACKS == TRUE) || defined(__DOXYGEN__)
918 /**
919  * @brief Associates a callback to a pad.
920  *
921  * @param[in] port port identifier
922  * @param[in] pad pad number within the port
923  * @param[in] cb event callback function
924  * @param[in] arg callback argument
925  *
926  * @api
927  */
928 #define palSetPadCallback(port, pad, cb, arg) \
929  do { \
930  osalSysLock(); \
931  palSetPadCallbackI(port, pad, cb, arg); \
932  osalSysUnlock(); \
933  } while (false)
934 
935 /**
936  * @brief Associates a callback to a line.
937  *
938  * @param[in] line line identifier
939  * @param[in] cb event callback function
940  * @param[in] arg callback argument
941  *
942  * @iclass
943  */
944 #define palSetLineCallback(line, cb, arg) \
945  do { \
946  osalSysLock(); \
947  palSetLineCallbackI(line, cb, arg); \
948  osalSysUnlock(); \
949  } while (false)
950 #endif /* PAL_USE_CALLBACKS == TRUE */
951 
952 /** @} */
953 
954 /*===========================================================================*/
955 /* External declarations. */
956 /*===========================================================================*/
957 
958 #ifdef __cplusplus
959 extern "C" {
960 #endif
961  ioportmask_t palReadBus(const IOBus *bus);
962  void palWriteBus(const IOBus *bus, ioportmask_t bits);
963  void palSetBusMode(const IOBus *bus, iomode_t mode);
964 #if (PAL_USE_CALLBACKS == TRUE) || defined(__DOXYGEN__)
965  void palSetPadCallbackI(ioportid_t port, iopadid_t pad,
966  palcallback_t cb, void *arg);
967  void palSetLineCallbackI(ioline_t line, palcallback_t cb, void *arg);
968 #endif /* PAL_USE_CALLBACKS == TRUE */
969 #if (PAL_USE_WAIT == TRUE) || defined(__DOXYGEN__)
971  sysinterval_t timeout);
973  sysinterval_t timeout);
976 #endif /* PAL_USE_WAIT == TRUE */
977 #ifdef __cplusplus
978 }
979 #endif
980 
981 #endif /* HAL_PAL_H */
982 
983 #endif /* HAL_USE_PAL == TRUE */
984 
985 /** @} */
ioportmask_t mask
Bus mask aligned to port bit 0.
Definition: hal_pal.h:191
Type of a PAL event record.
Definition: hal_pal.h:153
uint32_t ioportmask_t
Digital I/O port sized unsigned type.
Definition: hal_pal_lld.h:100
uint64_t sysinterval_t
Type of time interval.
Definition: chtime.h:119
uint32_t iopadid_t
Type of an pad identifier.
Definition: hal_pal_lld.h:123
palcallback_t cb
Event callback.
Definition: hal_pal.h:164
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:185
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
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:195
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:168
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:181
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:158
int32_t msg_t
Definition: chtypes.h:51
void(* palcallback_t)(void *arg)
Type of a PAL event callback.
Definition: hal_pal.h:148