ChibiOS 21.11.4
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 */
148typedef 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 */
154typedef 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 */
183typedef 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 Reads the group latch.
508 * @note The function can be called from any context.
509 *
510 * @param[in] port port identifier
511 * @param[in] mask group mask, a logic AND is performed on the input
512 * data
513 * @param[in] offset group bit offset within the port
514 * @return The group logic states.
515 *
516 * @special
517 */
518#if !defined(pal_lld_readgrouplatch) || defined(__DOXYGEN__)
519#define palReadGroupLatch(port, mask, offset) \
520 ((palReadLatch(port) >> (offset)) & (mask))
521#else
522#define palReadGroupLatch(port, mask, offset) pal_lld_readgrouplatch(port, mask, offset)
523#endif
524
525/**
526 * @brief Writes a group of bits.
527 * @note The operation is not guaranteed to be atomic on all the
528 * architectures, for atomicity and/or portability reasons you may
529 * need to enclose port I/O operations between @p osalSysLock() and
530 * @p osalSysUnlock().
531 * @note The function can be called from any context.
532 *
533 * @param[in] port port identifier
534 * @param[in] mask group mask, a logic AND is performed on the
535 * output data
536 * @param[in] offset group bit offset within the port
537 * @param[in] bits bits to be written. Values exceeding the group
538 * width are masked.
539 *
540 * @special
541 */
542#if !defined(pal_lld_writegroup) || defined(__DOXYGEN__)
543#define palWriteGroup(port, mask, offset, bits) \
544 palWritePort(port, (palReadLatch(port) & ~((mask) << (offset))) | \
545 (((bits) & (mask)) << (offset)))
546#else
547#define palWriteGroup(port, mask, offset, bits) \
548 pal_lld_writegroup(port, mask, offset, bits)
549#endif
550
551/**
552 * @brief Pads group mode setup.
553 * @details This function programs a pads group belonging to the same port
554 * with the specified mode.
555 * @note The operation is not guaranteed to be atomic on all the
556 * architectures, for atomicity and/or portability reasons you may
557 * need to enclose port I/O operations between @p osalSysLock() and
558 * @p osalSysUnlock().
559 * @note Programming an unknown or unsupported mode is silently ignored.
560 * @note The function can be called from any context.
561 *
562 * @param[in] port port identifier
563 * @param[in] mask group mask
564 * @param[in] offset group bit offset within the port
565 * @param[in] mode group mode
566 *
567 * @special
568 */
569#if !defined(pal_lld_setgroupmode) || defined(__DOXYGEN__)
570#define palSetGroupMode(port, mask, offset, mode) \
571 do { \
572 (void)(port); \
573 (void)(mask); \
574 (void)(offset); \
575 (void)(port); \
576 } while (mode)
577#else
578#define palSetGroupMode(port, mask, offset, mode) \
579 pal_lld_setgroupmode(port, mask, offset, mode)
580#endif
581
582/**
583 * @brief Reads an input pad logic state.
584 * @note The function can be called from any context.
585 *
586 * @param[in] port port identifier
587 * @param[in] pad pad number within the port
588 * @return The logic state.
589 * @retval PAL_LOW low logic state.
590 * @retval PAL_HIGH high logic state.
591 *
592 * @special
593 */
594#if !defined(pal_lld_readpad) || defined(__DOXYGEN__)
595#define palReadPad(port, pad) ((palReadPort(port) >> (pad)) & 1U)
596#else
597#define palReadPad(port, pad) pal_lld_readpad(port, pad)
598#endif
599
600/**
601 * @brief Writes a logic state on an output pad.
602 * @note The operation is not guaranteed to be atomic on all the
603 * architectures, for atomicity and/or portability reasons you may
604 * need to enclose port I/O operations between @p osalSysLock() and
605 * @p osalSysUnlock().
606 * @note The function can be called from any context.
607 *
608 * @param[in] port port identifier
609 * @param[in] pad pad number within the port
610 * @param[in] bit logic value, the value must be @p PAL_LOW or
611 * @p PAL_HIGH
612 *
613 * @special
614 */
615#if !defined(pal_lld_writepad) || defined(__DOXYGEN__)
616#define palWritePad(port, pad, bit) \
617 palWritePort(port, (palReadLatch(port) & ~PAL_PORT_BIT(pad)) | \
618 (((bit) & 1U) << pad))
619#else
620#define palWritePad(port, pad, bit) pal_lld_writepad(port, pad, bit)
621#endif
622
623/**
624 * @brief Sets a pad logic state to @p PAL_HIGH.
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_setpad) || defined(__DOXYGEN__)
637#define palSetPad(port, pad) palSetPort(port, PAL_PORT_BIT(pad))
638#else
639#define palSetPad(port, pad) pal_lld_setpad(port, pad)
640#endif
641
642/**
643 * @brief Clears a pad logic state to @p PAL_LOW.
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_clearpad) || defined(__DOXYGEN__)
656#define palClearPad(port, pad) palClearPort(port, PAL_PORT_BIT(pad))
657#else
658#define palClearPad(port, pad) pal_lld_clearpad(port, pad)
659#endif
660
661/**
662 * @brief Toggles a pad logic state.
663 * @note The operation is not guaranteed to be atomic on all the
664 * architectures, for atomicity and/or portability reasons you may
665 * need to enclose port I/O operations between @p osalSysLock() and
666 * @p osalSysUnlock().
667 * @note The function can be called from any context.
668 *
669 * @param[in] port port identifier
670 * @param[in] pad pad number within the port
671 *
672 * @special
673 */
674#if !defined(pal_lld_togglepad) || defined(__DOXYGEN__)
675#define palTogglePad(port, pad) palTogglePort(port, PAL_PORT_BIT(pad))
676#else
677#define palTogglePad(port, pad) pal_lld_togglepad(port, pad)
678#endif
679
680/**
681 * @brief Pad mode setup.
682 * @details This function programs a pad with the specified mode.
683 * @note The operation is not guaranteed to be atomic on all the
684 * architectures, for atomicity and/or portability reasons you may
685 * need to enclose port I/O operations between @p osalSysLock() and
686 * @p osalSysUnlock().
687 * @note Programming an unknown or unsupported mode is silently ignored.
688 * @note The function can be called from any context.
689 *
690 * @param[in] port port identifier
691 * @param[in] pad pad number within the port
692 * @param[in] mode pad mode
693 *
694 * @special
695 */
696#if !defined(pal_lld_setpadmode) || defined(__DOXYGEN__)
697#define palSetPadMode(port, pad, mode) \
698 palSetGroupMode(port, PAL_PORT_BIT(pad), 0U, mode)
699#else
700#define palSetPadMode(port, pad, mode) pal_lld_setpadmode(port, pad, mode)
701#endif
702
703/**
704 * @brief Reads an input line logic state.
705 * @note The function can be called from any context.
706 *
707 * @param[in] line line identifier
708 * @return The logic state.
709 * @retval PAL_LOW low logic state.
710 * @retval PAL_HIGH high logic state.
711 *
712 * @special
713 */
714#if !defined(pal_lld_readline) || defined(__DOXYGEN__)
715#define palReadLine(line) palReadPad(PAL_PORT(line), PAL_PAD(line))
716#else
717#define palReadLine(line) pal_lld_readline(line)
718#endif
719
720/**
721 * @brief Writes a logic state on an output line.
722 * @note The operation is not guaranteed to be atomic on all the
723 * architectures, for atomicity and/or portability reasons you may
724 * need to enclose port I/O operations between @p osalSysLock() and
725 * @p osalSysUnlock().
726 * @note The function can be called from any context.
727 *
728 * @param[in] line line identifier
729 * @param[in] bit logic value, the value must be @p PAL_LOW or
730 * @p PAL_HIGH
731 *
732 * @special
733 */
734#if !defined(pal_lld_writeline) || defined(__DOXYGEN__)
735#define palWriteLine(line, bit) palWritePad(PAL_PORT(line), PAL_PAD(line), bit)
736#else
737#define palWriteLine(line, bit) pal_lld_writeline(line, bit)
738#endif
739
740/**
741 * @brief Sets a line logic state to @p PAL_HIGH.
742 * @note The operation is not guaranteed to be atomic on all the
743 * architectures, for atomicity and/or portability reasons you may
744 * need to enclose port I/O operations between @p osalSysLock() and
745 * @p osalSysUnlock().
746 * @note The function can be called from any context.
747 *
748 * @param[in] line line identifier
749 *
750 * @special
751 */
752#if !defined(pal_lld_setline) || defined(__DOXYGEN__)
753#define palSetLine(line) palSetPad(PAL_PORT(line), PAL_PAD(line))
754#else
755#define palSetLine(line) pal_lld_setline(line)
756#endif
757
758/**
759 * @brief Clears a line logic state to @p PAL_LOW.
760 * @note The operation is not guaranteed to be atomic on all the
761 * architectures, for atomicity and/or portability reasons you may
762 * need to enclose port I/O operations between @p osalSysLock() and
763 * @p osalSysUnlock().
764 * @note The function can be called from any context.
765 *
766 * @param[in] line line identifier
767 *
768 * @special
769 */
770#if !defined(pal_lld_clearline) || defined(__DOXYGEN__)
771#define palClearLine(line) palClearPad(PAL_PORT(line), PAL_PAD(line))
772#else
773#define palClearLine(line) pal_lld_clearline(line)
774#endif
775
776/**
777 * @brief Toggles a line logic state.
778 * @note The operation is not guaranteed to be atomic on all the
779 * architectures, for atomicity and/or portability reasons you may
780 * need to enclose port I/O operations between @p osalSysLock() and
781 * @p osalSysUnlock().
782 * @note The function can be called from any context.
783 *
784 * @param[in] line line identifier
785 *
786 * @special
787 */
788#if !defined(pal_lld_toggleline) || defined(__DOXYGEN__)
789#define palToggleLine(line) palTogglePad(PAL_PORT(line), PAL_PAD(line))
790#else
791#define palToggleLine(line) pal_lld_toggleline(line)
792#endif
793
794/**
795 * @brief Line mode setup.
796 * @note The operation is not guaranteed to be atomic on all the
797 * architectures, for atomicity and/or portability reasons you may
798 * need to enclose port I/O operations between @p osalSysLock() and
799 * @p osalSysUnlock().
800 * @note The function can be called from any context.
801 *
802 * @param[in] line line identifier
803 * @param[in] mode pad mode
804 *
805 * @special
806 */
807#if !defined(pal_lld_setlinemode) || defined(__DOXYGEN__)
808#define palSetLineMode(line, mode) \
809 palSetPadMode(PAL_PORT(line), PAL_PAD(line), mode)
810#else
811#define palSetLineMode(line, mode) pal_lld_setlinemode(line, mode)
812#endif
813
814#if (PAL_USE_CALLBACKS == TRUE) || (PAL_USE_WAIT == TRUE) || \
815 defined(__DOXYGEN__)
816/**
817 * @brief Pad event enable.
818 * @note Programming an unknown or unsupported mode is silently ignored.
819 *
820 * @param[in] port port identifier
821 * @param[in] pad pad number within the port
822 * @param[in] mode pad event mode
823 *
824 * @iclass
825 */
826#if !defined(pal_lld_enablepadevent) || defined(__DOXYGEN__)
827#define palEnablePadEventI(port, pad, mode)
828#else
829#define palEnablePadEventI(port, pad, mode) \
830 pal_lld_enablepadevent(port, pad, mode)
831#endif
832
833/**
834 * @brief Pad event disable.
835 * @details This function also disables previously programmed event callbacks.
836 *
837 * @param[in] port port identifier
838 * @param[in] pad pad number within the port
839 *
840 * @iclass
841 */
842#if !defined(pal_lld_disablepadevent) || defined(__DOXYGEN__)
843#define palDisablePadEventI(port, pad)
844#else
845#define palDisablePadEventI(port, pad) \
846 pal_lld_disablepadevent(port, pad)
847#endif
848
849/**
850 * @brief Pad event enable.
851 * @note Programming an unknown or unsupported mode is silently ignored.
852 *
853 * @param[in] port port identifier
854 * @param[in] pad pad number within the port
855 * @param[in] mode pad event mode
856 *
857 * @api
858 */
859#define palEnablePadEvent(port, pad, mode) \
860 do { \
861 osalSysLock(); \
862 palEnablePadEventI(port, pad, mode); \
863 osalSysUnlock(); \
864 } while (false)
865
866/**
867 * @brief Pad event disable.
868 * @details This function also disables previously programmed event callbacks.
869 *
870 * @param[in] port port identifier
871 * @param[in] pad pad number within the port
872 *
873 * @api
874 */
875#define palDisablePadEvent(port, pad) \
876 do { \
877 osalSysLock(); \
878 palDisablePadEventI(port, pad); \
879 osalSysUnlock(); \
880 } while (false)
881
882/**
883 * @brief Line event enable.
884 * @note Programming an unknown or unsupported mode is silently ignored.
885 *
886 * @param[in] line line identifier
887 * @param[in] mode line event mode
888 *
889 * @iclass
890 */
891#if !defined(pal_lld_enablelineevent) || defined(__DOXYGEN__)
892#define palEnableLineEventI(line, mode) \
893 palEnablePadEventI(PAL_PORT(line), PAL_PAD(line), mode)
894#else
895#define palEnableLineEventI(line, mode) \
896 pal_lld_enablelineevent(line, mode)
897#endif
898
899/**
900 * @brief Line event disable.
901 * @details This function also disables previously programmed event callbacks.
902 *
903 * @param[in] line line identifier
904 *
905 * @iclass
906 */
907#if !defined(pal_lld_disablelineevent) || defined(__DOXYGEN__)
908#define palDisableLineEventI(line) \
909 palDisablePadEventI(PAL_PORT(line), PAL_PAD(line))
910#else
911#define palDisableLineEventI(line) pal_lld_disablelineevent(line)
912#endif
913
914/**
915 * @brief Line event enable.
916 * @note Programming an unknown or unsupported mode is silently ignored.
917 *
918 * @param[in] line line identifier
919 * @param[in] mode line event mode
920 *
921 * @api
922 */
923#define palEnableLineEvent(line, mode) \
924 do { \
925 osalSysLock(); \
926 palEnableLineEventI(line, mode); \
927 osalSysUnlock(); \
928 } while (false)
929
930/**
931 * @brief Line event disable.
932 * @details This function also disables previously programmed event callbacks.
933 *
934 * @param[in] line line identifier
935 *
936 * @api
937 */
938#define palDisableLineEvent(line) \
939 do { \
940 osalSysLock(); \
941 palDisableLineEventI(line); \
942 osalSysUnlock(); \
943 } while (false)
944
945/**
946 * @brief Pad event enable check.
947 *
948 * @param[in] port port identifier
949 * @param[in] pad pad number within the port
950 * @return Pad event status.
951 * @retval false if the pad event is disabled.
952 * @retval true if the pad event is enabled.
953 *
954 * @xclass
955 */
956#if !defined(pal_lld_ispadeventenabled) || defined(__DOXYGEN__)
957#define palIsPadEventEnabledX(port, pad) false
958#else
959#define palIsPadEventEnabledX(port, pad) \
960 pal_lld_ispadeventenabled(port, pad)
961#endif
962
963/**
964 * @brief Line event enable check.
965 *
966 * @param[in] line line identifier
967 * @return Line event status.
968 * @retval false if the line event is disabled.
969 * @retval true if the line event is enabled.
970 *
971 * @xclass
972 */
973#if !defined(pal_lld_islineeventenabled) || defined(__DOXYGEN__)
974#define palIsLineEventEnabledX(line) \
975 pal_lld_ispadeventenabled(PAL_PORT(line), PAL_PAD(line))
976#else
977#define palIsLineEventEnabledX(line) \
978 pal_lld_islineeventenabled(line)
979#endif
980
981#endif /* PAL_USE_CALLBACKS || PAL_USE_WAIT */
982
983#if (PAL_USE_CALLBACKS == TRUE) || defined(__DOXYGEN__)
984/**
985 * @brief Associates a callback to a pad.
986 *
987 * @param[in] port port identifier
988 * @param[in] pad pad number within the port
989 * @param[in] cb event callback function
990 * @param[in] arg callback argument
991 *
992 * @api
993 */
994#define palSetPadCallback(port, pad, cb, arg) \
995 do { \
996 osalSysLock(); \
997 palSetPadCallbackI(port, pad, cb, arg); \
998 osalSysUnlock(); \
999 } while (false)
1000
1001/**
1002 * @brief Associates a callback to a line.
1003 *
1004 * @param[in] line line identifier
1005 * @param[in] cb event callback function
1006 * @param[in] arg callback argument
1007 *
1008 * @api
1009 */
1010#define palSetLineCallback(line, cb, arg) \
1011 do { \
1012 osalSysLock(); \
1013 palSetLineCallbackI(line, cb, arg); \
1014 osalSysUnlock(); \
1015 } while (false)
1016#endif /* PAL_USE_CALLBACKS == TRUE */
1017
1018/** @} */
1019
1020/*===========================================================================*/
1021/* External declarations. */
1022/*===========================================================================*/
1023
1024#ifdef __cplusplus
1025extern "C" {
1026#endif
1027 ioportmask_t palReadBus(const IOBus *bus);
1028 void palWriteBus(const IOBus *bus, ioportmask_t bits);
1029 void palSetBusMode(const IOBus *bus, iomode_t mode);
1030#if (PAL_USE_CALLBACKS == TRUE) || defined(__DOXYGEN__)
1032 palcallback_t cb, void *arg);
1033 void palSetLineCallbackI(ioline_t line, palcallback_t cb, void *arg);
1034#endif /* PAL_USE_CALLBACKS == TRUE */
1035#if (PAL_USE_WAIT == TRUE) || defined(__DOXYGEN__)
1037 sysinterval_t timeout);
1039 sysinterval_t timeout);
1042#endif /* PAL_USE_WAIT == TRUE */
1043#ifdef __cplusplus
1044}
1045#endif
1046
1047#endif /* HAL_PAL_H */
1048
1049#endif /* HAL_USE_PAL == TRUE */
1050
1051/** @} */
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
void palSetLineCallbackI(ioline_t line, palcallback_t cb, void *arg)
Associates a callback to a line.
Definition hal_pal.c:148
msg_t palWaitLineTimeout(ioline_t line, sysinterval_t timeout)
Waits for an edge on the specified line.
Definition hal_pal.c:243
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:199
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:174
uint32_t ioportid_t
Port Identifier.
ioportmask_t palReadBus(const IOBus *bus)
Read from an I/O bus.
Definition hal_pal.c:65
uint32_t ioportmask_t
Digital I/O port sized unsigned type.
msg_t palWaitLineTimeoutS(ioline_t line, sysinterval_t timeout)
Waits for an edge on the specified line.
Definition hal_pal.c:223
void(* palcallback_t)(void *arg)
Type of a PAL event callback.
Definition hal_pal.h:148
uint32_t iomode_t
Digital I/O modes.
void palSetBusMode(const IOBus *bus, iomode_t mode)
Programs a bus with the specified mode.
Definition hal_pal.c:113
uint32_t iopadid_t
Type of an pad identifier.
uint32_t ioline_t
Type of an I/O line.
int32_t msg_t
Definition chearly.h:88
uint64_t sysinterval_t
Type of time interval.
Definition chtime.h:119
PLATFORM PAL subsystem low level driver header.
I/O bus descriptor.
Definition hal_pal.h:183
uint_fast8_t offset
Offset, within the port, of the least significant bit of the bus.
Definition hal_pal.h:197
ioportid_t portid
Port identifier.
Definition hal_pal.h:187
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
void * arg
Event callback argument.
Definition hal_pal.h:169
palcallback_t cb
Event callback.
Definition hal_pal.h:165
threads_queue_t threads
Threads queued for an event.
Definition hal_pal.h:159
Type of a thread queue.
Definition osal.h:238