ChibiOS 21.11.5
hal_buffered_sio.c
Go to the documentation of this file.
1/*
2 ChibiOS - Copyright (C) 2006-2026 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_buffered_sio.c
19 * @brief Buffered SIO Driver code.
20 *
21 * @addtogroup HAL_BUFFERED_SIO
22 * @{
23 */
24
25#include "hal.h"
26
27#if (HAL_USE_SIO == TRUE) || defined(__DOXYGEN__)
28
29#include "hal_buffered_sio.h"
30
31/*===========================================================================*/
32/* Driver local definitions. */
33/*===========================================================================*/
34
35/*===========================================================================*/
36/* Driver exported variables. */
37/*===========================================================================*/
38
39/*===========================================================================*/
40/* Driver local variables and types. */
41/*===========================================================================*/
42
43/*===========================================================================*/
44/* Driver local functions. */
45/*===========================================================================*/
46
48
49 while (!sioIsTXFullX(bsiop->siop)) {
50 msg_t msg;
51
52 msg = oqGetI(&bsiop->oqueue);
53 if (msg < MSG_OK) {
55 return;
56 }
57 sioPutX(bsiop->siop, (uint_fast16_t)msg);
58 }
59}
60
62
63 /* RX FIFO needs to be fully emptied or SIO will not generate more RX FIFO
64 events.*/
65 while (!sioIsRXEmptyX(bsiop->siop)) {
66 bsIncomingDataI((BufferedSerial *)bsiop, sioGetX(bsiop->siop));
67 }
68}
69
70static void __bsio_default_cb(SIODriver *siop) {
71 BufferedSIODriver *bsiop = (BufferedSIODriver *)siop->arg;
72 sioevents_t events;
73
74 if (bsiop == NULL) {
75 return;
76 }
77
79
80 /* Drain/fill FIFOs before re-enabling data interrupts in the LLD.
81 NOTE: this assumes status/error flags are not cleared by data reads,
82 otherwise non-data events could be lost before sioGetAndClearEventsX(). */
83 if (!sioIsRXEmptyX(siop)) {
84 __bsio_pop_data(bsiop);
85 }
86 if (!sioIsTXFullX(siop)) {
87 __bsio_push_data(bsiop);
88 }
89
90 /* Posting the non-data SIO events as channel event flags, the masks are
91 made to match.*/
92 events = sioGetAndClearEventsX(siop);
93 chnAddFlagsI(bsiop, (eventflags_t)(events & ~SIO_EV_ALL_DATA));
94
96}
97
98static void __bsio_onotify(io_queue_t *qp) {
99
101}
102
103/*
104 * Interface implementation.
105 */
106static size_t __bsio_write(void *ip, const uint8_t *bp, size_t n) {
107
108 return __buffered_serial_write_impl(ip, bp, n);
109}
110
111static size_t __bsio_read(void *ip, uint8_t *bp, size_t n) {
112
113 return __buffered_serial_read_impl(ip, bp, n);
114}
115
116static msg_t __bsio_put(void *ip, uint8_t b) {
117
118 return __buffered_serial_put_impl(ip, b);
119}
120
121static msg_t __bsio_get(void *ip) {
122
124}
125
126static msg_t __bsio_putt(void *ip, uint8_t b, sysinterval_t timeout) {
127
128 return __buffered_serial_put_timeout_impl(ip, b, timeout);
129}
130
131static msg_t __bsio_gett(void *ip, sysinterval_t timeout) {
132
133 return __buffered_serial_get_timeout_impl(ip, timeout);
134}
135
136static size_t __bsio_writet(void *ip, const uint8_t *bp, size_t n,
137 sysinterval_t timeout) {
138
139 return __buffered_serial_write_timeout_impl(ip, bp, n, timeout);
140}
141
142static size_t __bsio_readt(void *ip, uint8_t *bp, size_t n,
143 sysinterval_t timeout) {
144
145 return __buffered_serial_read_timeout_impl(ip, bp, n, timeout);
146}
147
148static msg_t __bsio_ctl(void *ip, unsigned int operation, void *arg) {
149
150 return sioControlX(((BufferedSIODriver *)ip)->siop, operation, arg);
151}
152
159
160/*===========================================================================*/
161/* Driver exported functions. */
162/*===========================================================================*/
163
164/**
165 * @brief Initializes a generic serial driver object.
166 * @details The HW dependent part of the initialization has to be performed
167 * outside, usually in the hardware initialization code.
168 *
169 * @param[out] bsiop pointer to a @p BufferedSIODriver structure
170 * @param[in] siop pointer to the @p SIODriver object
171 * @param[in] ib pointer to the input buffer
172 * @param[in] ibsize size of the input buffer
173 * @param[in] ob pointer to the output buffer
174 * @param[in] obsize size of the output buffer
175 *
176 * @init
177 */
179 uint8_t *ib, size_t ibsize,
180 uint8_t *ob, size_t obsize) {
181
182 __buffered_serial_objinit_impl((void *)bsiop, (const void *)&vmt,
183 ib, ibsize, NULL, NULL,
184 ob, obsize, __bsio_onotify, (void *)bsiop);
185 bsiop->siop = siop;
186 siop->arg = (void *)bsiop;
187}
188
189/**
190 * @brief Configures and starts the driver.
191 *
192 * @param[out] bsiop pointer to a @p BufferedSIODriver structure
193 * @param[in] config the architecture-dependent serial driver configuration.
194 * If this parameter is set to @p NULL then a default
195 * configuration is used.
196 * @return The operation status.
197 *
198 * @api
199 */
201 msg_t msg;
202
203 osalDbgCheck(bsiop != NULL);
204
205 osalDbgAssert((bsiop->state == BS_STOP) || (bsiop->state == BS_READY),
206 "invalid state");
207
208 msg = sioStart(bsiop->siop, config);
209 if (msg == HAL_RET_SUCCESS) {
210 osalSysLock();
211 bsiop->siop->arg = (void *)bsiop;
212 sioSetCallbackX(bsiop->siop, &__bsio_default_cb);
214 bsiop->state = BS_READY;
216 }
217 else {
218 bsiop->state = BS_STOP;
219 }
220
221 return msg;
222}
223
224/**
225 * @brief Stops the driver.
226 * @details Any thread waiting on the driver's queues will be awakened with
227 * the message @p MSG_RESET.
228 *
229 * @param[out] bsiop pointer to a @p BufferedSIODriver structure
230 *
231 * @api
232 */
234
235 osalDbgCheck(bsiop != NULL);
236
237 osalDbgAssert((bsiop->state == BS_STOP) || (bsiop->state == BS_READY),
238 "invalid state");
239
240 /* Stopping undelying SIO driver.*/
241 sioStop(bsiop->siop);
242
243 bsiop->state = BS_STOP;
244
245 osalSysLock();
246 oqResetI(&bsiop->oqueue); /* TODO should go in the upper class.*/
247 iqResetI(&bsiop->iqueue);
250}
251
252#endif /* HAL_USE_SIO == TRUE */
253
254/** @} */
static CC_FORCE_INLINE size_t __buffered_serial_read_timeout_impl(void *ip, uint8_t *bp, size_t n, sysinterval_t timeout)
static CC_FORCE_INLINE msg_t __buffered_serial_put_impl(void *ip, uint8_t b)
static CC_FORCE_INLINE size_t __buffered_serial_write_impl(void *ip, const uint8_t *bp, size_t n)
static CC_FORCE_INLINE msg_t __buffered_serial_get_timeout_impl(void *ip, sysinterval_t timeout)
static CC_FORCE_INLINE msg_t __buffered_serial_get_impl(void *ip)
static CC_FORCE_INLINE size_t __buffered_serial_read_impl(void *ip, uint8_t *bp, size_t n)
struct hal_buffered_serial BufferedSerial
Structure representing a buffered serial class.
static CC_FORCE_INLINE size_t __buffered_serial_write_timeout_impl(void *ip, const uint8_t *bp, size_t n, sysinterval_t timeout)
static CC_FORCE_INLINE msg_t __buffered_serial_put_timeout_impl(void *ip, uint8_t b, sysinterval_t timeout)
void bsIncomingDataI(BufferedSerial *bsp, uint8_t b)
Handles incoming data.
static CC_FORCE_INLINE void __buffered_serial_objinit_impl(void *ip, const void *vmt, uint8_t *ib, size_t ibsize, qnotify_t inotify, void *iarg, uint8_t *ob, size_t obsize, qnotify_t onotify, void *oarg)
Object initialization implementation.
static msg_t __bsio_putt(void *ip, uint8_t b, sysinterval_t timeout)
static void __bsio_onotify(io_queue_t *qp)
static void __bsio_push_data(BufferedSIODriver *bsiop)
static msg_t __bsio_gett(void *ip, sysinterval_t timeout)
struct hal_buffered_siol_driver BufferedSIODriver
Buffered SIO driver class.
static size_t __bsio_writet(void *ip, const uint8_t *bp, size_t n, sysinterval_t timeout)
SIOConfig BufferedSIOConfig
Type of a buffered SIO configuration.
static msg_t __bsio_get(void *ip)
static void __bsio_default_cb(SIODriver *siop)
static size_t __bsio_read(void *ip, uint8_t *bp, size_t n)
static size_t __bsio_readt(void *ip, uint8_t *bp, size_t n, sysinterval_t timeout)
void bsioObjectInit(BufferedSIODriver *bsiop, SIODriver *siop, uint8_t *ib, size_t ibsize, uint8_t *ob, size_t obsize)
Initializes a generic serial driver object.
static void __bsio_pop_data(BufferedSIODriver *bsiop)
void bsioStop(BufferedSIODriver *bsiop)
Stops the driver.
static size_t __bsio_write(void *ip, const uint8_t *bp, size_t n)
msg_t bsioStart(BufferedSIODriver *bsiop, const BufferedSIOConfig *config)
Configures and starts the driver.
static msg_t __bsio_put(void *ip, uint8_t b)
static msg_t __bsio_ctl(void *ip, unsigned int operation, void *arg)
static const struct EFlashDriverVMT vmt
Definition hal_efl.c:71
void iqResetI(input_queue_t *iqp)
Resets an input queue.
Definition hal_queues.c:201
void oqResetI(output_queue_t *oqp)
Resets an output queue.
Definition hal_queues.c:467
msg_t oqGetI(output_queue_t *oqp)
Output queue read.
Definition hal_queues.c:576
struct io_queue io_queue_t
Type of a generic I/O queue structure.
Definition hal_queues.h:58
#define HAL_RET_SUCCESS
Definition hal.h:93
#define CHN_OUTPUT_EMPTY
Output queue empty.
#define chnAddFlagsI(ip, flags)
Adds status flags to the listeners's flags mask.
static void osalSysLock(void)
Enters a critical zone from thread context.
Definition osal.h:601
static void osalSysUnlock(void)
Leaves a critical zone from thread context.
Definition osal.h:611
static void osalSysLockFromISR(void)
Enters a critical zone from ISR context.
Definition osal.h:621
void osalOsRescheduleS(void)
Checks if a reschedule is required and performs it.
Definition osal.c:119
static void osalSysUnlockFromISR(void)
Leaves a critical zone from ISR context.
Definition osal.h:631
#define osalDbgAssert(c, remark)
Condition assertion.
Definition osal.h:264
#define osalDbgCheck(c)
Function parameters check.
Definition osal.h:284
#define sioPutX(siop, data)
Pushes one frame into the TX FIFO.
Definition hal_sio.h:421
#define SIO_EV_ALL_DATA
Definition hal_sio.h:59
#define sioGetX(siop)
Returns one frame from the RX FIFO.
Definition hal_sio.h:410
struct hal_sio_driver SIODriver
Type of structure representing a SIO driver.
Definition hal_sio.h:138
#define sioSetCallbackX(siop, f)
Associates a callback to the SIO instance.
Definition hal_sio.h:260
#define sioWriteEnableFlagsX(siop, mask)
Writes the enabled events mask.
Definition hal_sio.h:331
#define sioIsTXFullX(siop)
Determines the state of the TX FIFO.
Definition hal_sio.h:309
msg_t sioStart(SIODriver *siop, const SIOConfig *config)
Configures and activates the SIO peripheral.
Definition hal_sio.c:264
#define sioGetAndClearEventsX(siop)
Get and clears SIO event flags.
Definition hal_sio.h:389
#define sioControlX(siop, operation, arg)
Control operation on a serial port.
Definition hal_sio.h:469
eventflags_t sioevents_t
Type of event flags.
Definition hal_sio.h:133
void sioStop(SIODriver *siop)
Deactivates the SIO peripheral.
Definition hal_sio.c:307
#define sioIsRXEmptyX(siop)
Determines the state of the RX FIFO.
Definition hal_sio.h:272
#define SIO_EV_ALL_EVENTS
Definition hal_sio.h:72
uint32_t eventflags_t
Definition chearly.h:90
int32_t msg_t
Definition chearly.h:87
#define MSG_OK
Normal wakeup message.
Definition chschd.h:38
uint64_t sysinterval_t
Type of time interval.
Definition chtime.h:118
HAL subsystem header.
Buffered SIO Driver macros and structures.
BufferedSIODriver virtual methods table.
void * arg
User argument.
Definition hal_sio.h:224
void * q_link
Application defined field.
Definition hal_queues.h:84