ChibiOS/HAL  6.1.0
hal_pal.c
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.c
19  * @brief I/O Ports Abstraction Layer code.
20  *
21  * @addtogroup PAL
22  * @{
23  */
24 
25 #include "hal.h"
26 
27 #if (HAL_USE_PAL == TRUE) || defined(__DOXYGEN__)
28 
29 /*===========================================================================*/
30 /* Driver local definitions. */
31 /*===========================================================================*/
32 
33 /*===========================================================================*/
34 /* Driver exported variables. */
35 /*===========================================================================*/
36 
37 /*===========================================================================*/
38 /* Driver local variables and types. */
39 /*===========================================================================*/
40 
41 /*===========================================================================*/
42 /* Driver local functions. */
43 /*===========================================================================*/
44 
45 /*===========================================================================*/
46 /* Driver exported functions. */
47 /*===========================================================================*/
48 
49 /**
50  * @brief Read from an I/O bus.
51  * @note The operation is not guaranteed to be atomic on all the
52  * architectures, for atomicity and/or portability reasons you may
53  * need to enclose port I/O operations between @p osalSysLock() and
54  * @p osalSysUnlock().
55  * @note The function internally uses the @p palReadGroup() macro. The use
56  * of this function is preferred when you value code size, readability
57  * and error checking over speed.
58  * @note The function can be called from any context.
59  *
60  * @param[in] bus the I/O bus, pointer to a @p IOBus structure
61  * @return The bus logical states.
62  *
63  * @special
64  */
66 
67  osalDbgCheck((bus != NULL) && (bus->offset < PAL_IOPORTS_WIDTH));
68 
69  return palReadGroup(bus->portid, bus->mask, bus->offset);
70 }
71 
72 /**
73  * @brief Write to an I/O bus.
74  * @note The operation is not guaranteed to be atomic on all the
75  * architectures, for atomicity and/or portability reasons you may
76  * need to enclose port I/O operations between @p osalSysLock() and
77  * @p osalSysUnlock().
78  * @note The default implementation is non atomic and not necessarily
79  * optimal. Low level drivers may optimize the function by using
80  * specific hardware or coding.
81  * @note The function can be called from any context.
82  *
83  * @param[in] bus the I/O bus, pointer to a @p IOBus structure
84  * @param[in] bits the bits to be written on the I/O bus. Values exceeding
85  * the bus width are masked so most significant bits are
86  * lost.
87  *
88  * @special
89  */
90 void palWriteBus(const IOBus *bus, ioportmask_t bits) {
91 
92  osalDbgCheck((bus != NULL) && (bus->offset < PAL_IOPORTS_WIDTH));
93 
94  palWriteGroup(bus->portid, bus->mask, bus->offset, bits);
95 }
96 
97 /**
98  * @brief Programs a bus with the specified mode.
99  * @note The operation is not guaranteed to be atomic on all the
100  * architectures, for atomicity and/or portability reasons you may
101  * need to enclose port I/O operations between @p osalSysLock() and
102  * @p osalSysUnlock().
103  * @note The default implementation is non atomic and not necessarily
104  * optimal. Low level drivers may optimize the function by using
105  * specific hardware or coding.
106  * @note The function can be called from any context.
107  *
108  * @param[in] bus the I/O bus, pointer to a @p IOBus structure
109  * @param[in] mode the mode
110  *
111  * @special
112  */
113 void palSetBusMode(const IOBus *bus, iomode_t mode) {
114 
115  osalDbgCheck((bus != NULL) && (bus->offset < PAL_IOPORTS_WIDTH));
116 
117  palSetGroupMode(bus->portid, bus->mask, bus->offset, mode);
118 }
119 
120 #if (PAL_USE_CALLBACKS == TRUE) || defined(__DOXYGEN__)
121 /**
122  * @brief Associates a callback to a port/pad.
123  *
124  * @param[in] port port identifier
125  * @param[in] pad pad number within the port
126  * @param[in] cb event callback function
127  * @param[in] arg callback argument
128  *
129  * @iclass
130  */
132  palcallback_t cb, void *arg) {
133 
134  palevent_t *pep = pal_lld_get_pad_event(port, pad);
135  pep->cb = cb;
136  pep->arg = arg;
137 }
138 
139 /**
140  * @brief Associates a callback to a line.
141  *
142  * @param[in] line line identifier
143  * @param[in] cb event callback function
144  * @param[in] arg callback argument
145  *
146  * @iclass
147  */
148 void palSetLineCallbackI(ioline_t line, palcallback_t cb, void *arg) {
149 
150  palevent_t *pep = pal_lld_get_line_event(line);
151  pep->cb = cb;
152  pep->arg = arg;
153 }
154 #endif /* PAL_USE_CALLBACKS == TRUE */
155 
156 #if (PAL_USE_WAIT == TRUE) || defined(__DOXYGEN__)
157 /**
158  * @brief Waits for an edge on the specified port/pad.
159  *
160  * @param[in] port port identifier
161  * @param[in] pad pad number within the port
162  * @param[in] timeout the number of ticks before the operation timeouts,
163  * the following special values are allowed:
164  * - @a TIME_IMMEDIATE immediate timeout.
165  * - @a TIME_INFINITE no timeout.
166  * .
167  * @returns The operation state.
168  * @retval MSG_OK if an edge has been detected.
169  * @retval MSG_TIMEOUT if a timeout occurred before an edge could be detected.
170  * @retval MSG_RESET if the event has been disabled while the thread was
171  * waiting for an edge.
172  *
173  * @sclass
174  */
176  iopadid_t pad,
177  sysinterval_t timeout) {
178 
179  palevent_t *pep = pal_lld_get_pad_event(port, pad);
180  return osalThreadEnqueueTimeoutS(&pep->threads, timeout);
181 }
182 
183 /**
184  * @brief Waits for an edge on the specified port/pad.
185  *
186  * @param[in] port port identifier
187  * @param[in] pad pad number within the port
188  * @param[in] timeout the number of ticks before the operation timeouts,
189  * the following special values are allowed:
190  * - @a TIME_IMMEDIATE immediate timeout.
191  * - @a TIME_INFINITE no timeout.
192  * .
193  * @returns The operation state.
194  * @retval MSG_OK if an edge has been detected.
195  * @retval MSG_TIMEOUT if a timeout occurred before an edge cound be detected.
196  * @retval MSG_RESET if the event has been disabled while the thread was
197  * waiting for an edge.
198  *
199  * @api
200  */
202  iopadid_t pad,
203  sysinterval_t timeout) {
204  msg_t msg;
205 
206  osalSysLock();
207  msg = palWaitPadTimeoutS(port, pad, timeout);
208  osalSysUnlock();
209  return msg;
210 }
211 
212 /**
213  * @brief Waits for an edge on the specified line.
214  *
215  * @param[in] line line identifier
216  * @param[in] timeout operation timeout
217  * @returns The operation state.
218  * @retval MSG_OK if an edge has been detected.
219  * @retval MSG_TIMEOUT if a timeout occurred before an edge could be detected.
220  * @retval MSG_RESET if the event has been disabled while the thread was
221  * waiting for an edge.
222  *
223  * @sclass
224  */
226  sysinterval_t timeout) {
227 
228  palevent_t *pep = pal_lld_get_line_event(line);
229  return osalThreadEnqueueTimeoutS(&pep->threads, timeout);
230 }
231 
232 /**
233  * @brief Waits for an edge on the specified line.
234  *
235  * @param[in] line line identifier
236  * @param[in] timeout operation timeout
237  * @returns The operation state.
238  * @retval MSG_OK if an edge has been detected.
239  * @retval MSG_TIMEOUT if a timeout occurred before an edge cound be detected.
240  * @retval MSG_RESET if the event has been disabled while the thread was
241  * waiting for an edge.
242  *
243  * @api
244  */
246  msg_t msg;
247 
248  osalSysLock();
249  msg= palWaitLineTimeoutS(line, timeout);
250  osalSysUnlock();
251  return msg;
252 }
253 #endif /* PAL_USE_WAIT == TRUE */
254 
255 #endif /* HAL_USE_PAL == TRUE */
256 
257 /** @} */
ioportmask_t mask
Bus mask aligned to port bit 0.
Definition: hal_pal.h:193
Type of a PAL event record.
Definition: hal_pal.h:154
uint32_t ioportmask_t
Digital I/O port sized unsigned type.
Definition: hal_pal_lld.h:100
uint32_t iopadid_t
Type of an pad identifier.
Definition: hal_pal_lld.h:123
palcallback_t cb
Event callback.
Definition: hal_pal.h:165
uint32_t ioline_t
Type of an I/O line.
Definition: hal_pal_lld.h:110
#define PAL_IOPORTS_WIDTH
Width, in bits, of an I/O port.
Definition: hal_pal_lld.h:45
ioportid_t portid
Port identifier.
Definition: hal_pal.h:187
HAL subsystem header.
#define palReadGroup(port, mask, offset)
Reads a group of bits.
Definition: hal_pal.h:497
static void osalSysUnlock(void)
Leaves a critical zone from thread context.
Definition: osal.h:540
msg_t palWaitLineTimeout(ioline_t line, sysinterval_t timeout)
Waits for an edge on the specified line.
Definition: hal_pal.c:245
msg_t palWaitPadTimeout(ioportid_t port, iopadid_t pad, sysinterval_t timeout)
Waits for an edge on the specified port/pad.
Definition: hal_pal.c:201
int32_t msg_t
Type of a message.
Definition: osal.h:160
ioportmask_t palReadBus(const IOBus *bus)
Read from an I/O bus.
Definition: hal_pal.c:65
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
#define pal_lld_get_pad_event(port, pad)
Returns a PAL event structure associated to a pad.
Definition: hal_pal_lld.h:415
uint_fast8_t offset
Offset, within the port, of the least significant bit of the bus.
Definition: hal_pal.h:197
msg_t palWaitPadTimeoutS(ioportid_t port, iopadid_t pad, sysinterval_t timeout)
Waits for an edge on the specified port/pad.
Definition: hal_pal.c:175
#define osalDbgCheck(c)
Function parameters check.
Definition: osal.h:278
void * arg
Event callback argument.
Definition: hal_pal.h:169
uint32_t sysinterval_t
Type of system time interval.
Definition: osal.h:170
msg_t osalThreadEnqueueTimeoutS(threads_queue_t *tqp, sysinterval_t timeout)
Enqueues the caller thread.
Definition: osal.c:277
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
static void osalSysLock(void)
Enters a critical zone from thread context.
Definition: osal.h:530
I/O bus descriptor.
Definition: hal_pal.h:183
void palSetBusMode(const IOBus *bus, iomode_t mode)
Programs a bus with the specified mode.
Definition: hal_pal.c:113
uint32_t iomode_t
Digital I/O modes.
Definition: hal_pal_lld.h:105
#define palWriteGroup(port, mask, offset, bits)
Writes a group of bits.
Definition: hal_pal.h:521
threads_queue_t threads
Threads queued for an event.
Definition: hal_pal.h:159
#define pal_lld_get_line_event(line)
Returns a PAL event structure associated to a line.
Definition: hal_pal_lld.h:425
#define palSetGroupMode(port, mask, offset, mode)
Pads group mode setup.
Definition: hal_pal.h:548
void(* palcallback_t)(void *arg)
Type of a PAL event callback.
Definition: hal_pal.h:148