• R/O
  • SSH
  • HTTPS

chibios: Commit


Commit MetaInfo

Révision14911 (tree)
l'heure2021-10-14 23:29:34
Auteurgdisirio

Message de Log

(empty log message)

Change Summary

Modification

--- trunk/os/hal/include/hal_spi_v2.h (nonexistent)
+++ trunk/os/hal/include/hal_spi_v2.h (revision 14911)
@@ -0,0 +1,482 @@
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_spi.h
19+ * @brief SPI (v2) Driver macros and structures.
20+ *
21+ * @addtogroup SPI_V2
22+ * @{
23+ */
24+
25+#ifndef HAL_SPI_V2_H
26+#define HAL_SPI_V2_H
27+
28+#if (HAL_USE_SPI == TRUE) || defined(__DOXYGEN__)
29+
30+/*===========================================================================*/
31+/* Driver constants. */
32+/*===========================================================================*/
33+
34+/**
35+ * @name Chip Select modes
36+ * @{
37+ */
38+#define SPI_SELECT_MODE_NONE 0 /** @brief @p spiSelect() and
39+ @p spiUnselect() do
40+ nothing. */
41+#define SPI_SELECT_MODE_PAD 1 /** @brief Legacy mode. */
42+#define SPI_SELECT_MODE_PORT 2 /** @brief Fastest mode. */
43+#define SPI_SELECT_MODE_LINE 3 /** @brief Packed mode. */
44+#define SPI_SELECT_MODE_LLD 4 /** @brief LLD-defined mode.*/
45+/** @} */
46+
47+/*===========================================================================*/
48+/* Driver pre-compile time settings. */
49+/*===========================================================================*/
50+
51+/**
52+ * @name SPI configuration options
53+ * @{
54+ */
55+/**
56+ * @brief Support for thread synchronization API.
57+ */
58+#if !defined(SPI_USE_SYNCHRONIZATION) || defined(__DOXYGEN__)
59+#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__)
60+#define SPI_USE_SYNCHRONIZATION FALSE
61+#else
62+#define SPI_USE_SYNCHRONIZATION SPI_USE_WAIT
63+#endif
64+#endif
65+
66+/**
67+ * @brief Enables circular transfers APIs.
68+ * @note Disabling this option saves both code and data space.
69+ */
70+#if !defined(SPI_USE_CIRCULAR) || defined(__DOXYGEN__)
71+#define SPI_USE_CIRCULAR FALSE
72+#endif
73+
74+/**
75+ * @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs.
76+ * @note Disabling this option saves both code and data space.
77+ */
78+#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
79+#define SPI_USE_MUTUAL_EXCLUSION TRUE
80+#endif
81+
82+/**
83+ * @brief Handling method for SPI CS line.
84+ * @note Disabling this option saves both code and data space.
85+ */
86+#if !defined(SPI_SELECT_MODE) || defined(__DOXYGEN__)
87+#define SPI_SELECT_MODE SPI_SELECT_MODE_LINE
88+#endif
89+/** @} */
90+
91+/*===========================================================================*/
92+/* Derived constants and error checks. */
93+/*===========================================================================*/
94+
95+#if (SPI_SELECT_MODE != SPI_SELECT_MODE_NONE) && \
96+ (SPI_SELECT_MODE != SPI_SELECT_MODE_PAD) && \
97+ (SPI_SELECT_MODE != SPI_SELECT_MODE_PORT) && \
98+ (SPI_SELECT_MODE != SPI_SELECT_MODE_LINE) && \
99+ (SPI_SELECT_MODE != SPI_SELECT_MODE_LLD)
100+#error "invalid SPI_SELECT_MODE setting"
101+#endif
102+
103+/* Some modes have a dependency on the PAL driver, making the required
104+ checks here.*/
105+#if ((SPI_SELECT_MODE != SPI_SELECT_MODE_PAD) || \
106+ (SPI_SELECT_MODE != SPI_SELECT_MODE_PORT) || \
107+ (SPI_SELECT_MODE != SPI_SELECT_MODE_LINE)) && \
108+ (HAL_USE_PAL != TRUE)
109+#error "current SPI_SELECT_MODE requires HAL_USE_PAL"
110+#endif
111+
112+/*===========================================================================*/
113+/* Driver data structures and types. */
114+/*===========================================================================*/
115+
116+/**
117+ * @brief Driver state machine possible states.
118+ */
119+typedef enum {
120+ SPI_UNINIT = 0, /**< Not initialized. */
121+ SPI_STOP = 1, /**< Stopped. */
122+ SPI_READY = 2, /**< Ready. */
123+ SPI_ACTIVE = 3, /**< Exchanging data. */
124+ SPI_COMPLETE = 4 /**< Asynchronous operation complete. */
125+} spistate_t;
126+
127+/**
128+ * @brief Type of a structure representing an SPI driver.
129+ */
130+typedef struct hal_spi_driver SPIDriver;
131+
132+/**
133+ * @brief Type of a SPI driver configuration structure.
134+ */
135+typedef struct hal_spi_config SPIConfig;
136+
137+/**
138+ * @brief SPI notification callback type.
139+ *
140+ * @param[in] spip pointer to the @p SPIDriver object triggering the
141+ * callback
142+ */
143+typedef void (*spicb_t)(SPIDriver *spip);
144+
145+/* Including the low level driver header, it exports information required
146+ for completing types.*/
147+#include "hal_spi_v2_lld.h"
148+
149+#if !defined(SPI_SUPPORTS_CIRCULAR)
150+#error "SPI_SUPPORTS_CIRCULAR not defined in LLD"
151+#endif
152+
153+#if !defined(SPI_SUPPORTS_SLAVE_MODE)
154+#error "SPI_SUPPORTS_SLAVE_MODE not defined in LLD"
155+#endif
156+
157+/**
158+ * @brief Driver configuration structure.
159+ */
160+struct hal_spi_config {
161+#if (SPI_SUPPORTS_CIRCULAR == TRUE) || defined(__DOXYGEN__)
162+ /**
163+ * @brief Enables the circular buffer mode.
164+ */
165+ bool circular;
166+#endif
167+#if (SPI_SUPPORTS_SLAVE_MODE == TRUE) || defined(__DOXYGEN__)
168+ /**
169+ * @brief Enables the circular buffer mode.
170+ */
171+ bool slave;
172+#endif
173+ /**
174+ * @brief Operation complete callback or @p NULL.
175+ */
176+ spicallback_t end_cb;
177+ /**
178+ * @brief Operation error callback or @p NULL.
179+ */
180+ spicallback_t error_cb;
181+#if (SPI_SELECT_MODE == SPI_SELECT_MODE_LINE) || defined(__DOXYGEN__)
182+ /**
183+ * @brief The chip select line.
184+ * @note Only used in master mode.
185+ */
186+ ioline_t ssline;
187+#elif SPI_SELECT_MODE == SPI_SELECT_MODE_PORT
188+ /**
189+ * @brief The chip select port.
190+ * @note Only used in master mode.
191+ */
192+ ioportid_t ssport;
193+ /**
194+ * @brief The chip select port mask.
195+ * @note Only used in master mode.
196+ */
197+ ioportmask_t ssmask;
198+#elif SPI_SELECT_MODE == SPI_SELECT_MODE_PAD
199+ /**
200+ * @brief The chip select port.
201+ * @note Only used in master mode.
202+ */
203+ ioportid_t ssport;
204+ /**
205+ * @brief The chip select pad number.
206+ * @note Only used in master mode.
207+ */
208+ uint_fast8_t sspad;
209+#endif
210+ /* End of the mandatory fields.*/
211+ spi_lld_config_fields;
212+};
213+
214+/**
215+ * @brief Structure representing an SPI driver.
216+ */
217+struct hal_spi_driver {
218+ /**
219+ * @brief Driver state.
220+ */
221+ spistate_t state;
222+ /**
223+ * @brief Current configuration data.
224+ */
225+ const SPIConfig *config;
226+#if (SPI_USE_SYNCHRONIZATION == TRUE) || defined(__DOXYGEN__)
227+ /**
228+ * @brief Synchronization point for transfer.
229+ */
230+ thread_reference_t sync_transfer;
231+#endif /* SPI_USE_SYNCHRONIZATION == TRUE */
232+#if (SPI_USE_MUTUAL_EXCLUSION == TRUE) || defined(__DOXYGEN__)
233+ /**
234+ * @brief Mutex protecting the peripheral.
235+ */
236+ mutex_t mutex;
237+#endif /* SPI_USE_MUTUAL_EXCLUSION == TRUE */
238+#if defined(SPI_DRIVER_EXT_FIELDS)
239+ SPI_DRIVER_EXT_FIELDS
240+#endif
241+ /* End of the mandatory fields.*/
242+ spi_lld_driver_fields;
243+};
244+
245+/*===========================================================================*/
246+/* Driver macros. */
247+/*===========================================================================*/
248+
249+/**
250+ * @name Macro Functions
251+ * @{
252+ */
253+/**
254+ * @brief Buffer state.
255+ * @note This function is meant to be called from the SPI callback only.
256+ *
257+ * @param[in] spip pointer to the @p SPIDriver object
258+ * @return The buffer state.
259+ * @retval false if the driver filled/sent the first half of the
260+ * buffer.
261+ * @retval true if the driver filled/sent the second half of the
262+ * buffer.
263+ *
264+ * @special
265+ */
266+#define spiIsBufferComplete(spip) ((bool)((spip)->state == SPI_COMPLETE))
267+
268+#if (SPI_SELECT_MODE == SPI_SELECT_MODE_LLD) || defined(__DOXYGEN__)
269+/**
270+ * @brief Asserts the slave select signal and prepares for transfers.
271+ *
272+ * @param[in] spip pointer to the @p SPIDriver object
273+ *
274+ * @iclass
275+ */
276+#define spiSelectI(spip) \
277+do { \
278+ spi_lld_select(spip); \
279+} while (false)
280+
281+/**
282+ * @brief Deasserts the slave select signal.
283+ * @details The previously selected peripheral is unselected.
284+ *
285+ * @param[in] spip pointer to the @p SPIDriver object
286+ *
287+ * @iclass
288+ */
289+#define spiUnselectI(spip) \
290+do { \
291+ spi_lld_unselect(spip); \
292+} while (false)
293+
294+#elif SPI_SELECT_MODE == SPI_SELECT_MODE_LINE
295+#define spiSelectI(spip) \
296+do { \
297+ palClearLine((spip)->config->ssline); \
298+} while (false)
299+
300+#define spiUnselectI(spip) \
301+do { \
302+ palSetLine((spip)->config->ssline); \
303+} while (false)
304+
305+#elif SPI_SELECT_MODE == SPI_SELECT_MODE_PORT
306+#define spiSelectI(spip) \
307+do { \
308+ palClearPort((spip)->config->ssport, (spip)->config->ssmask); \
309+} while (false)
310+
311+#define spiUnselectI(spip) \
312+do { \
313+ palSetPort((spip)->config->ssport, (spip)->config->ssmask); \
314+} while (false)
315+
316+#elif SPI_SELECT_MODE == SPI_SELECT_MODE_PAD
317+#define spiSelectI(spip) \
318+do { \
319+ palClearPad((spip)->config->ssport, (spip)->config->sspad); \
320+} while (false)
321+
322+#define spiUnselectI(spip) \
323+do { \
324+ palSetPad((spip)->config->ssport, (spip)->config->sspad); \
325+} while (false)
326+
327+#elif SPI_SELECT_MODE == SPI_SELECT_MODE_NONE
328+#define spiSelectI(spip)
329+
330+#define spiUnselectI(spip)
331+#endif
332+
333+/**
334+ * @brief Exchanges one frame using a polled wait.
335+ * @details This synchronous function exchanges one frame using a polled
336+ * synchronization method. This function is useful when exchanging
337+ * small amount of data on high speed channels, usually in this
338+ * situation is much more efficient just wait for completion using
339+ * polling than suspending the thread waiting for an interrupt.
340+ * @note This API is implemented as a macro in order to minimize latency.
341+ *
342+ * @param[in] spip pointer to the @p SPIDriver object
343+ * @param[in] frame the data frame to send over the SPI bus
344+ * @return The received data frame from the SPI bus.
345+ */
346+#define spiPolledExchange(spip, frame) spi_lld_polled_exchange(spip, frame)
347+/** @} */
348+
349+/**
350+ * @name Low level driver helper macros
351+ * @{
352+ */
353+#if (SPI_USE_SYNCHRONIZATION == TRUE) || defined(__DOXYGEN__)
354+/**
355+ * @brief Wakes up the waiting thread.
356+ *
357+ * @param[in] spip pointer to the @p SPIDriver object
358+ *
359+ * @notapi
360+ */
361+#define _spi_wakeup_isr(spip) { \
362+ osalSysLockFromISR(); \
363+ osalThreadResumeI(&(spip)->thread, MSG_OK); \
364+ osalSysUnlockFromISR(); \
365+}
366+#else /* !SPI_USE_SYNCHRONIZATION */
367+#define _spi_wakeup_isr(spip)
368+#endif /* !SPI_USE_SYNCHRONIZATION */
369+
370+/**
371+ * @brief Common ISR code when circular mode is not supported.
372+ * @details This code handles the portable part of the ISR code:
373+ * - Callback invocation.
374+ * - Waiting thread wakeup, if any.
375+ * - Driver state transitions.
376+ * .
377+ * @note This macro is meant to be used in the low level drivers
378+ * implementation only.
379+ *
380+ * @param[in] spip pointer to the @p SPIDriver object
381+ *
382+ * @notapi
383+ */
384+#define _spi_isr_code(spip) { \
385+ if ((spip)->config->end_cb) { \
386+ (spip)->state = SPI_COMPLETE; \
387+ (spip)->config->end_cb(spip); \
388+ if ((spip)->state == SPI_COMPLETE) \
389+ (spip)->state = SPI_READY; \
390+ } \
391+ else \
392+ (spip)->state = SPI_READY; \
393+ _spi_wakeup_isr(spip); \
394+}
395+
396+/**
397+ * @brief Half buffer filled ISR code in circular mode.
398+ * @details This code handles the portable part of the ISR code:
399+ * - Callback invocation.
400+ * .
401+ * @note This macro is meant to be used in the low level drivers
402+ * implementation only.
403+ *
404+ * @param[in] spip pointer to the @p SPIDriver object
405+ *
406+ * @notapi
407+ */
408+#define _spi_isr_half_code(spip) { \
409+ if ((spip)->config->end_cb) { \
410+ (spip)->config->end_cb(spip); \
411+ } \
412+}
413+
414+/**
415+ * @brief Full buffer filled ISR code in circular mode.
416+ * @details This code handles the portable part of the ISR code:
417+ * - Callback invocation.
418+ * - Driver state transitions.
419+ * .
420+ * @note This macro is meant to be used in the low level drivers
421+ * implementation only.
422+ *
423+ * @param[in] spip pointer to the @p SPIDriver object
424+ *
425+ * @notapi
426+ */
427+#define _spi_isr_full_code(spip) { \
428+ if ((spip)->config->end_cb) { \
429+ (spip)->state = SPI_COMPLETE; \
430+ (spip)->config->end_cb(spip); \
431+ if ((spip)->state == SPI_COMPLETE) \
432+ (spip)->state = SPI_ACTIVE; \
433+ } \
434+}
435+/** @} */
436+
437+/*===========================================================================*/
438+/* External declarations. */
439+/*===========================================================================*/
440+
441+#ifdef __cplusplus
442+extern "C" {
443+#endif
444+ void spiInit(void);
445+ void spiObjectInit(SPIDriver *spip);
446+ msg_t spiStart(SPIDriver *spip, const SPIConfig *config);
447+ void spiStop(SPIDriver *spip);
448+ void spiSelect(SPIDriver *spip);
449+ void spiUnselect(SPIDriver *spip);
450+ bool spiStartIgnoreI(SPIDriver *spip, size_t n);
451+ bool spiStartIgnore(SPIDriver *spip, size_t n);
452+ bool spiStartExchangeI(SPIDriver *spip, size_t n,
453+ const void *txbuf, void *rxbuf);
454+ bool spiStartExchange(SPIDriver *spip, size_t n,
455+ const void *txbuf, void *rxbuf);
456+ bool spiStartSendI(SPIDriver *spip, size_t n, const void *txbuf);
457+ bool spiStartSend(SPIDriver *spip, size_t n, const void *txbuf);
458+ bool spiStartReceiveI(SPIDriver *spip, size_t n, void *rxbuf);
459+ bool spiStartReceive(SPIDriver *spip, size_t n, void *rxbuf);
460+ size_t spiStopTransferI(SPIDriver *spip);
461+ size_t spiStopTransfer(SPIDriver *spip);
462+#if SPI_USE_SYNCHRONIZATION == TRUE
463+ msg_t spiSynchronizeS(SPIDriver *spip, sysinterval_t timeout);
464+ msg_t spiSynchronize(SPIDriver *spip, sysinterval_t timeout);
465+ void spiIgnore(SPIDriver *spip, size_t n);
466+ void spiExchange(SPIDriver *spip, size_t n, const void *txbuf, void *rxbuf);
467+ void spiSend(SPIDriver *spip, size_t n, const void *txbuf);
468+ void spiReceive(SPIDriver *spip, size_t n, void *rxbuf);
469+#endif
470+#if SPI_USE_MUTUAL_EXCLUSION == TRUE
471+ void spiAcquireBus(SPIDriver *spip);
472+ void spiReleaseBus(SPIDriver *spip);
473+#endif
474+#ifdef __cplusplus
475+}
476+#endif
477+
478+#endif /* HAL_USE_SPI == TRUE */
479+
480+#endif /* HAL_SPI_V2_H */
481+
482+/** @} */
--- trunk/os/hal/src/hal_sio.c (revision 14910)
+++ trunk/os/hal/src/hal_sio.c (revision 14911)
@@ -447,6 +447,8 @@
447447 * @retval MSG_RESET operation has been stopped while waiting.
448448 * @retval SIO_MSG_IDLE if RX line went idle.
449449 * @retval SIO_MSG_ERRORS if RX errors occurred during wait.
450+ *
451+ * @api
450452 */
451453 msg_t sioSynchronizeRX(SIODriver *siop, sysinterval_t timeout) {
452454 msg_t msg = MSG_OK;
@@ -482,6 +484,8 @@
482484 * @retval MSG_OK if there is space in the TX FIFO.
483485 * @retval MSG_TIMEOUT if synchronization timed out.
484486 * @retval MSG_RESET operation has been stopped while waiting.
487+ *
488+ * @api
485489 */
486490 msg_t sioSynchronizeTX(SIODriver *siop, sysinterval_t timeout) {
487491 msg_t msg = MSG_OK;
@@ -514,6 +518,8 @@
514518 * @return The synchronization result.
515519 * @retval MSG_OK if TX operation finished.
516520 * @retval MSG_TIMEOUT if synchronization timed out.
521+ *
522+ * @api
517523 */
518524 msg_t sioSynchronizeTXEnd(SIODriver *siop, sysinterval_t timeout) {
519525 msg_t msg;
--- trunk/os/hal/src/hal_spi_v2.c (nonexistent)
+++ trunk/os/hal/src/hal_spi_v2.c (revision 14911)
@@ -0,0 +1,598 @@
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_spi_v2.c
19+ * @brief SPI (v2) Driver code.
20+ *
21+ * @addtogroup SPI_V2
22+ * @{
23+ */
24+
25+#include "hal.h"
26+
27+#if (HAL_USE_SPI == 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 SPI Driver initialization.
51+ * @note This function is implicitly invoked by @p halInit(), there is
52+ * no need to explicitly initialize the driver.
53+ *
54+ * @init
55+ */
56+void spiInit(void) {
57+
58+ spi_lld_init();
59+}
60+
61+/**
62+ * @brief Initializes the standard part of a @p SPIDriver structure.
63+ *
64+ * @param[out] spip pointer to the @p SPIDriver object
65+ *
66+ * @init
67+ */
68+void spiObjectInit(SPIDriver *spip) {
69+
70+ spip->state = SPI_STOP;
71+ spip->config = NULL;
72+#if SPI_USE_SYNCHRONIZATION == TRUE
73+ spip->synch_transfer = NULL;
74+#endif
75+#if SPI_USE_MUTUAL_EXCLUSION == TRUE
76+ osalMutexObjectInit(&spip->mutex);
77+#endif
78+#if defined(SPI_DRIVER_EXT_INIT_HOOK)
79+ SPI_DRIVER_EXT_INIT_HOOK(spip);
80+#endif
81+}
82+
83+/**
84+ * @brief Configures and activates the SPI peripheral.
85+ *
86+ * @param[in] spip pointer to the @p SPIDriver object
87+ * @param[in] config pointer to the @p SPIConfig object
88+ * @return The operation status.
89+ *
90+ * @api
91+ */
92+msg_t spiStart(SPIDriver *spip, const SPIConfig *config) {
93+ msg_t msg;
94+
95+ osalDbgCheck((spip != NULL) && (config != NULL));
96+
97+ osalSysLock();
98+ osalDbgAssert((spip->state == SPI_STOP) || (spip->state == SPI_READY),
99+ "invalid state");
100+
101+ spip->config = config;
102+
103+#if defined(SPI_LLD_ENHANCED_API)
104+ msg = spi_lld_start(spip);
105+#else
106+ spi_lld_start(spip);
107+ msg = HAL_START_SUCCESS;
108+#endif
109+ if (msg == HAL_START_SUCCESS) {
110+ spip->state = SPI_READY;
111+ }
112+ else {
113+ spip->state = SPI_STOP;
114+ }
115+
116+ osalSysUnlock();
117+
118+ return msg;
119+}
120+
121+/**
122+ * @brief Deactivates the SPI peripheral.
123+ *
124+ * @param[in] spip pointer to the @p SPIDriver object
125+ *
126+ * @api
127+ */
128+void spiStop(SPIDriver *spip) {
129+
130+ osalDbgCheck(spip != NULL);
131+
132+ osalSysLock();
133+
134+ osalDbgAssert((spip->state == SPI_STOP) || (spip->state == SPI_READY),
135+ "invalid state");
136+
137+ spi_lld_stop(spip);
138+ spip->config = NULL;
139+ spip->state = SPI_STOP;
140+
141+ osalSysUnlock();
142+}
143+
144+/**
145+ * @brief Asserts the slave select signal and prepares for transfers.
146+ *
147+ * @param[in] spip pointer to the @p SPIDriver object
148+ *
149+ * @api
150+ */
151+void spiSelect(SPIDriver *spip) {
152+
153+ osalDbgCheck(spip != NULL);
154+
155+ osalSysLock();
156+ osalDbgAssert(spip->state == SPI_READY, "not ready");
157+ spiSelectI(spip);
158+ osalSysUnlock();
159+}
160+
161+/**
162+ * @brief Deasserts the slave select signal.
163+ * @details The previously selected peripheral is unselected.
164+ *
165+ * @param[in] spip pointer to the @p SPIDriver object
166+ *
167+ * @api
168+ */
169+void spiUnselect(SPIDriver *spip) {
170+
171+ osalDbgCheck(spip != NULL);
172+
173+ osalSysLock();
174+ osalDbgAssert(spip->state == SPI_READY, "not ready");
175+ spiUnselectI(spip);
176+ osalSysUnlock();
177+}
178+
179+/**
180+ * @brief Ignores data on the SPI bus.
181+ * @details This asynchronous function starts the transmission of a series of
182+ * idle words on the SPI bus and ignores the received data.
183+ * @pre A slave must have been selected using @p spiSelect() or
184+ * @p spiSelectI().
185+ * @post At the end of the operation the configured callback is invoked.
186+ *
187+ * @param[in] spip pointer to the @p SPIDriver object
188+ * @param[in] n number of words to be ignored
189+ * @return The operation status.
190+ * @retval false if the operation started correctly.
191+ * @retval true if the operation did not start.
192+ *
193+ * @iclass
194+ */
195+bool spiStartIgnoreI(SPIDriver *spip, size_t n) {
196+
197+ osalDbgCheck((spip != NULL) && (n > 0U));
198+#if SPI_SUPPORTS_CIRCULAR
199+ osalDbgCheck((spip->config->circular == false) || ((n & 1U) == 0U));
200+#endif
201+
202+ osalDbgAssert(spip->state == SPI_READY, "not ready");
203+
204+ spip->state = SPI_ACTIVE;
205+ return spi_lld_ignore(spip, n);
206+}
207+
208+/**
209+ * @brief Ignores data on the SPI bus.
210+ * @details This asynchronous function starts the transmission of a series of
211+ * idle words on the SPI bus and ignores the received data.
212+ * @pre A slave must have been selected using @p spiSelect() or
213+ * @p spiSelectI().
214+ * @post At the end of the operation the configured callback is invoked.
215+ *
216+ * @param[in] spip pointer to the @p SPIDriver object
217+ * @param[in] n number of words to be ignored
218+ * @return The operation status.
219+ * @retval false if the operation started correctly.
220+ * @retval true if the operation did not start.
221+ *
222+ * @api
223+ */
224+bool spiStartIgnore(SPIDriver *spip, size_t n) {
225+ bool ret;
226+
227+ osalSysLock();
228+ ret = spiStartIgnoreI(spip, n);
229+ osalSysUnlock();
230+
231+ return ret;
232+}
233+
234+/**
235+ * @brief Exchanges data on the SPI bus.
236+ * @details This asynchronous function starts a simultaneous transmit/receive
237+ * operation.
238+ * @pre A slave must have been selected using @p spiSelect() or
239+ * @p spiSelectI().
240+ * @post At the end of the operation the configured callback is invoked.
241+ * @note The buffers are organized as uint8_t arrays for data sizes below
242+ * or equal to 8 bits else it is organized as uint16_t arrays.
243+ *
244+ * @param[in] spip pointer to the @p SPIDriver object
245+ * @param[in] n number of words to be exchanged
246+ * @param[in] txbuf the pointer to the transmit buffer
247+ * @param[out] rxbuf the pointer to the receive buffer
248+ * @return The operation status.
249+ * @retval false if the operation started correctly.
250+ * @retval true if the operation did not start.
251+ *
252+ * @iclass
253+ */
254+bool spiStartExchangeI(SPIDriver *spip, size_t n,
255+ const void *txbuf, void *rxbuf) {
256+
257+ osalDbgCheck((spip != NULL) && (n > 0U) &&
258+ (rxbuf != NULL) && (txbuf != NULL));
259+#if SPI_SUPPORTS_CIRCULAR
260+ osalDbgCheck((spip->config->circular == false) || ((n & 1U) == 0U));
261+#endif
262+
263+ osalDbgAssert(spip->state == SPI_READY, "not ready");
264+
265+ spip->state = SPI_ACTIVE;
266+ return spi_lld_exchange(spip, n, txbuf, rxbuf);
267+}
268+
269+/**
270+ * @brief Exchanges data on the SPI bus.
271+ * @details This asynchronous function starts a simultaneous transmit/receive
272+ * operation.
273+ * @pre A slave must have been selected using @p spiSelect() or
274+ * @p spiSelectI().
275+ * @post At the end of the operation the configured callback is invoked.
276+ * @note The buffers are organized as uint8_t arrays for data sizes below
277+ * or equal to 8 bits else it is organized as uint16_t arrays.
278+ *
279+ * @param[in] spip pointer to the @p SPIDriver object
280+ * @param[in] n number of words to be exchanged
281+ * @param[in] txbuf the pointer to the transmit buffer
282+ * @param[out] rxbuf the pointer to the receive buffer
283+ * @return The operation status.
284+ * @retval false if the operation started correctly.
285+ * @retval true if the operation did not start.
286+ *
287+ * @api
288+ */
289+bool spiStartExchange(SPIDriver *spip, size_t n,
290+ const void *txbuf, void *rxbuf) {
291+ bool ret;
292+
293+ osalSysLock();
294+ ret = spiStartExchangeI(spip, n, txbuf, rxbuf);
295+ osalSysUnlock();
296+
297+ return ret;
298+}
299+
300+/**
301+ * @brief Sends data over the SPI bus.
302+ * @details This asynchronous function starts a transmit operation.
303+ * @pre A slave must have been selected using @p spiSelect() or
304+ * @p spiSelectI().
305+ * @post At the end of the operation the configured callback is invoked.
306+ * @note The buffers are organized as uint8_t arrays for data sizes below
307+ * or equal to 8 bits else it is organized as uint16_t arrays.
308+ *
309+ * @param[in] spip pointer to the @p SPIDriver object
310+ * @param[in] n number of words to send
311+ * @param[in] txbuf the pointer to the transmit buffer
312+ * @return The operation status.
313+ * @retval false if the operation started correctly.
314+ * @retval true if the operation did not start.
315+ *
316+ * @iclass
317+ */
318+bool spiStartSendI(spip, n, txbuf) {
319+
320+ osalDbgCheck((spip != NULL) && (n > 0U) && (txbuf != NULL));
321+#if SPI_SUPPORTS_CIRCULAR
322+ osalDbgCheck((spip->config->circular == false) || ((n & 1U) == 0U));
323+#endif
324+
325+ osalDbgAssert(spip->state == SPI_READY, "not ready");
326+
327+ spip->state = SPI_ACTIVE;
328+ return spi_lld_send(spip, n, txbuf);
329+}
330+
331+/**
332+ * @brief Sends data over the SPI bus.
333+ * @details This asynchronous function starts a transmit operation.
334+ * @pre A slave must have been selected using @p spiSelect() or
335+ * @p spiSelectI().
336+ * @post At the end of the operation the configured callback is invoked.
337+ * @note The buffers are organized as uint8_t arrays for data sizes below
338+ * or equal to 8 bits else it is organized as uint16_t arrays.
339+ *
340+ * @param[in] spip pointer to the @p SPIDriver object
341+ * @param[in] n number of words to send
342+ * @param[in] txbuf the pointer to the transmit buffer
343+ * @return The operation status.
344+ * @retval false if the operation started correctly.
345+ * @retval true if the operation did not start.
346+ *
347+ * @api
348+ */
349+bool spiStartSend(SPIDriver *spip, size_t n, const void *txbuf) {
350+ bool ret;
351+
352+ osalSysLock();
353+ ret = spiStartSendI(spip, n, txbuf);
354+ osalSysUnlock();
355+
356+ return ret;
357+}
358+
359+/**
360+ * @brief Receives data from the SPI bus.
361+ * @details This asynchronous function starts a receive operation.
362+ * @pre A slave must have been selected using @p spiSelect() or
363+ * @p spiSelectI().
364+ * @post At the end of the operation the configured callback is invoked.
365+ * @note The buffers are organized as uint8_t arrays for data sizes below
366+ * or equal to 8 bits else it is organized as uint16_t arrays.
367+ *
368+ * @param[in] spip pointer to the @p SPIDriver object
369+ * @param[in] n number of words to receive
370+ * @param[out] rxbuf the pointer to the receive buffer
371+ * @return The operation status.
372+ * @retval false if the operation started correctly.
373+ * @retval true if the operation did not start.
374+ *
375+ * @iclass
376+ */
377+bool spiStartReceiveI(SPIDriver *spip, size_t n, void *rxbuf) {
378+
379+ osalDbgCheck((spip != NULL) && (n > 0U) && (rxbuf != NULL));
380+#if SPI_SUPPORTS_CIRCULAR
381+ osalDbgCheck((spip->config->circular == false) || ((n & 1U) == 0U));
382+#endif
383+
384+ osalDbgAssert(spip->state == SPI_READY, "not ready");
385+
386+ spip->state = SPI_ACTIVE;
387+ return spi_lld_receive(spip, n, rxbuf);
388+}
389+
390+/**
391+ * @brief Receives data from the SPI bus.
392+ * @details This asynchronous function starts a receive operation.
393+ * @pre A slave must have been selected using @p spiSelect() or
394+ * @p spiSelectI().
395+ * @post At the end of the operation the configured callback is invoked.
396+ * @note The buffers are organized as uint8_t arrays for data sizes below
397+ * or equal to 8 bits else it is organized as uint16_t arrays.
398+ *
399+ * @param[in] spip pointer to the @p SPIDriver object
400+ * @param[in] n number of words to receive
401+ * @param[out] rxbuf the pointer to the receive buffer
402+ * @return The operation status.
403+ * @retval false if the operation started correctly.
404+ * @retval true if the operation did not start.
405+ *
406+ * @api
407+ */
408+bool spiStartReceive(SPIDriver *spip, size_t n, void *rxbuf) {
409+ bool ret;
410+
411+ osalSysLock();
412+ ret = spiStartReceiveI(spip, n, rxbuf);
413+ osalSysUnlock();
414+
415+ return ret;
416+}
417+
418+#if (SPI_USE_SYNCHRONIZATION == TRUE) || defined(__DOXYGEN__)
419+/**
420+ * @brief Synchronizes with current transfer completion.
421+ * @note This function can only be called by a single thread at time.
422+ *
423+ * @param[in] spip pointer to the @p SPIDriver object
424+ * @param[in] timeout synchronization timeout
425+ * @return The synchronization result.
426+ * @retval MSG_OK if TX operation finished.
427+ * @retval MSG_TIMEOUT if synchronization timed out.
428+ *
429+ * @sclass
430+ */
431+msg_t spiSynchronizeS(SPIDriver *spip, sysinterval_t timeout) {
432+ msg_t msg;
433+
434+ osalDbgCheck((spip != NULL) && (n > 0U));
435+ osalDbgAssert((spip->state == SPI_ACTIVE) || (spip->state == SPI_READY),
436+ "invalid state");
437+
438+ if (spip->state == SPI_ACTIVE) {
439+ msg = osalThreadSuspendTimeoutS(&spip->sync_transfer, timeout);
440+ }
441+ else {
442+ msg = MSG_OK;
443+ }
444+
445+ return msg;
446+}
447+
448+/**
449+ * @brief Synchronizes with current transfer completion.
450+ * @note This function can only be called by a single thread at time.
451+ *
452+ * @param[in] spip pointer to the @p SPIDriver object
453+ * @param[in] timeout synchronization timeout
454+ * @return The synchronization result.
455+ * @retval MSG_OK if TX operation finished.
456+ * @retval MSG_TIMEOUT if synchronization timed out.
457+ *
458+ * @api
459+ */
460+msg_t spiSynchronize(SPIDriver *spip, sysinterval_t timeout) {
461+ msg_t msg;
462+
463+ osalSysLock();
464+ msg = spiSynchronizeS(spip, timeout);
465+ osalSysUnlock();
466+
467+ return msg;
468+}
469+
470+/**
471+ * @brief Ignores data on the SPI bus.
472+ * @details This synchronous function performs the transmission of a series of
473+ * idle words on the SPI bus and ignores the received data.
474+ * @pre In order to use this function the option @p SPI_USE_SYNCHRONIZATION
475+ * must be enabled.
476+ *
477+ * @param[in] spip pointer to the @p SPIDriver object
478+ * @param[in] n number of words to be ignored
479+ *
480+ * @api
481+ */
482+void spiIgnore(SPIDriver *spip, size_t n) {
483+
484+ osalSysLock();
485+ spiStartIgnoreI(spip, n);
486+ (void) spiSynchronizeS(spip, TIME_INFINITE);
487+ osalSysUnlock();
488+}
489+
490+/**
491+ * @brief Exchanges data on the SPI bus.
492+ * @details This synchronous function performs a simultaneous transmit/receive
493+ * operation.
494+ * @pre In order to use this function the option @p SPI_USE_SYNCHRONIZATION
495+ * must be enabled.
496+ * @note The buffers are organized as uint8_t arrays for data sizes below
497+ * or equal to 8 bits else it is organized as uint16_t arrays.
498+ *
499+ * @param[in] spip pointer to the @p SPIDriver object
500+ * @param[in] n number of words to be exchanged
501+ * @param[in] txbuf the pointer to the transmit buffer
502+ * @param[out] rxbuf the pointer to the receive buffer
503+ *
504+ * @api
505+ */
506+void spiExchange(SPIDriver *spip, size_t n,
507+ const void *txbuf, void *rxbuf) {
508+
509+ osalSysLock();
510+ spiStartExchangeI(spip, n, txbuf, rxbuf);
511+ (void) spiSynchronizeS(spip, TIME_INFINITE);
512+ osalSysUnlock();
513+}
514+
515+/**
516+ * @brief Sends data over the SPI bus.
517+ * @details This synchronous function performs a transmit operation.
518+ * @pre In order to use this function the option @p SPI_USE_SYNCHRONIZATION
519+ * must be enabled.
520+ * @note The buffers are organized as uint8_t arrays for data sizes below
521+ * or equal to 8 bits else it is organized as uint16_t arrays.
522+ *
523+ * @param[in] spip pointer to the @p SPIDriver object
524+ * @param[in] n number of words to send
525+ * @param[in] txbuf the pointer to the transmit buffer
526+ *
527+ * @api
528+ */
529+void spiSend(SPIDriver *spip, size_t n, const void *txbuf) {
530+
531+ osalSysLock();
532+ spiStartSendI(spip, n, txbuf);
533+ (void) spiSynchronizeS(spip, TIME_INFINITE);
534+ osalSysUnlock();
535+}
536+
537+/**
538+ * @brief Receives data from the SPI bus.
539+ * @details This synchronous function performs a receive operation.
540+ * @pre In order to use this function the option @p SPI_USE_SYNCHRONIZATION
541+ * must be enabled.
542+ * @note The buffers are organized as uint8_t arrays for data sizes below
543+ * or equal to 8 bits else it is organized as uint16_t arrays.
544+ *
545+ * @param[in] spip pointer to the @p SPIDriver object
546+ * @param[in] n number of words to receive
547+ * @param[out] rxbuf the pointer to the receive buffer
548+ *
549+ * @api
550+ */
551+void spiReceive(SPIDriver *spip, size_t n, void *rxbuf) {
552+
553+ osalSysLock();
554+ spiStartReceiveI(spip, n, rxbuf);
555+ (void) spiSynchronizeS(spip, TIME_INFINITE);
556+ osalSysUnlock();
557+}
558+#endif /* SPI_USE_SYNCHRONIZATION == TRUE */
559+
560+#if (SPI_USE_MUTUAL_EXCLUSION == TRUE) || defined(__DOXYGEN__)
561+/**
562+ * @brief Gains exclusive access to the SPI bus.
563+ * @details This function tries to gain ownership to the SPI bus, if the bus
564+ * is already being used then the invoking thread is queued.
565+ * @pre In order to use this function the option @p SPI_USE_MUTUAL_EXCLUSION
566+ * must be enabled.
567+ *
568+ * @param[in] spip pointer to the @p SPIDriver object
569+ *
570+ * @api
571+ */
572+void spiAcquireBus(SPIDriver *spip) {
573+
574+ osalDbgCheck(spip != NULL);
575+
576+ osalMutexLock(&spip->mutex);
577+}
578+
579+/**
580+ * @brief Releases exclusive access to the SPI bus.
581+ * @pre In order to use this function the option @p SPI_USE_MUTUAL_EXCLUSION
582+ * must be enabled.
583+ *
584+ * @param[in] spip pointer to the @p SPIDriver object
585+ *
586+ * @api
587+ */
588+void spiReleaseBus(SPIDriver *spip) {
589+
590+ osalDbgCheck(spip != NULL);
591+
592+ osalMutexUnlock(&spip->mutex);
593+}
594+#endif /* SPI_USE_MUTUAL_EXCLUSION == TRUE */
595+
596+#endif /* HAL_USE_SPI == TRUE */
597+
598+/** @} */
Afficher sur ancien navigateur de dépôt.