ChibiOS 21.11.4
hal_wspi.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_wspi.c
19 * @brief WSPI Driver code.
20 *
21 * @addtogroup WSPI
22 * @{
23 */
24
25#include "hal.h"
26
27#if (HAL_USE_WSPI == 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 WSPI 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 */
56void wspiInit(void) {
57
59}
60
61/**
62 * @brief Initializes the standard part of a @p WSPIDriver structure.
63 *
64 * @param[out] wspip pointer to the @p WSPIDriver object
65 *
66 * @init
67 */
69
70 wspip->state = WSPI_STOP;
71 wspip->config = NULL;
72#if WSPI_USE_WAIT == TRUE
73 wspip->thread = NULL;
74#endif
75#if WSPI_USE_MUTUAL_EXCLUSION == TRUE
77#endif
78#if defined(WSPI_DRIVER_EXT_INIT_HOOK)
79 WSPI_DRIVER_EXT_INIT_HOOK(wspip);
80#endif
81}
82
83/**
84 * @brief Configures and activates the WSPI peripheral.
85 *
86 * @param[in] wspip pointer to the @p WSPIDriver object
87 * @param[in] config pointer to the @p WSPIConfig object
88 * @return The operation status.
89 *
90 * @api
91 */
92msg_t wspiStart(WSPIDriver *wspip, const WSPIConfig *config) {
93 msg_t msg;
94
95 osalDbgCheck((wspip != NULL) && (config != NULL));
96
98 osalDbgAssert((wspip->state == WSPI_STOP) || (wspip->state == WSPI_READY),
99 "invalid state");
100
101 wspip->config = config;
102
103#if defined(WSPI_LLD_ENHANCED_API)
104 msg = wspi_lld_start(wspip);
105 if (msg == HAL_RET_SUCCESS) {
106 wspip->state = WSPI_READY;
107 }
108 else {
109 wspip->state = WSPI_STOP;
110 }
111#else
112 wspi_lld_start(wspip);
113 wspip->state = WSPI_READY;
114 msg = HAL_RET_SUCCESS;
115#endif
116
118
119 return msg;
120}
121
122/**
123 * @brief Deactivates the WSPI peripheral.
124 * @note Deactivating the peripheral also enforces a release of the slave
125 * select line.
126 *
127 * @param[in] wspip pointer to the @p WSPIDriver object
128 *
129 * @api
130 */
131void wspiStop(WSPIDriver *wspip) {
132
133 osalDbgCheck(wspip != NULL);
134
135 osalSysLock();
136
137 osalDbgAssert((wspip->state == WSPI_STOP) || (wspip->state == WSPI_READY),
138 "invalid state");
139
140 wspi_lld_stop(wspip);
141 wspip->config = NULL;
142 wspip->state = WSPI_STOP;
143
145}
146
147/**
148 * @brief Sends a command without data phase.
149 * @post At the end of the operation the configured callback is invoked.
150 *
151 * @param[in] wspip pointer to the @p WSPIDriver object
152 * @param[in] cmdp pointer to the command descriptor
153 *
154 * @api
155 */
156void wspiStartCommand(WSPIDriver *wspip, const wspi_command_t *cmdp) {
157
158 osalDbgCheck((wspip != NULL) && (cmdp != NULL));
159
160 osalSysLock();
161
162 osalDbgAssert(wspip->state == WSPI_READY, "not ready");
163
164 wspiStartCommandI(wspip, cmdp);
165
167}
168
169/**
170 * @brief Sends a command with data over the WSPI bus.
171 * @post At the end of the operation the configured callback is invoked.
172 *
173 * @param[in] wspip pointer to the @p WSPIDriver object
174 * @param[in] cmdp pointer to the command descriptor
175 * @param[in] n number of bytes to send
176 * @param[in] txbuf the pointer to the transmit buffer
177 *
178 * @api
179 */
180void wspiStartSend(WSPIDriver *wspip, const wspi_command_t *cmdp,
181 size_t n, const uint8_t *txbuf) {
182
183 osalDbgCheck((wspip != NULL) && (cmdp != NULL));
184 osalDbgCheck((n > 0U) && (txbuf != NULL));
185
186 osalSysLock();
187
188 osalDbgAssert(wspip->state == WSPI_READY, "not ready");
189
190 wspiStartSendI(wspip, cmdp, n, txbuf);
191
193}
194
195/**
196 * @brief Sends a command then receives data over the WSPI bus.
197 * @post At the end of the operation the configured callback is invoked.
198 *
199 * @param[in] wspip pointer to the @p WSPIDriver object
200 * @param[in] cmdp pointer to the command descriptor
201 * @param[in] n number of bytes to send
202 * @param[out] rxbuf the pointer to the receive buffer
203 *
204 * @api
205 */
207 size_t n, uint8_t *rxbuf) {
208
209 osalDbgCheck((wspip != NULL) && (cmdp != NULL));
210 osalDbgCheck((n > 0U) && (rxbuf != NULL));
211
212 osalSysLock();
213
214 osalDbgAssert(wspip->state == WSPI_READY, "not ready");
215
216 wspiStartReceiveI(wspip, cmdp, n, rxbuf);
217
219}
220
221#if (WSPI_USE_WAIT == TRUE) || defined(__DOXYGEN__)
222/**
223 * @brief Sends a command without data phase.
224 * @pre In order to use this function the option @p WSPI_USE_WAIT must be
225 * enabled.
226 * @pre In order to use this function the driver must have been configured
227 * without callbacks (@p end_cb = @p NULL).
228 *
229 * @param[in] wspip pointer to the @p WSPIDriver object
230 * @param[in] cmdp pointer to the command descriptor
231 * @return The operation status.
232 * @retval false if the operation succeeded.
233 * @retval true if the operation failed because HW issues.
234 *
235 * @api
236 */
237bool wspiCommand(WSPIDriver *wspip, const wspi_command_t *cmdp) {
238 msg_t msg;
239
240 osalDbgCheck((wspip != NULL) && (cmdp != NULL));
242
243 osalSysLock();
244
245 osalDbgAssert(wspip->state == WSPI_READY, "not ready");
246 osalDbgAssert(wspip->config->end_cb == NULL, "has callback");
247
248 wspiStartCommandI(wspip, cmdp);
249 msg = osalThreadSuspendS(&wspip->thread);
250
252
253 return (bool)(msg != MSG_OK);
254}
255
256/**
257 * @brief Sends a command with data over the WSPI bus.
258 * @pre In order to use this function the option @p WSPI_USE_WAIT must be
259 * enabled.
260 * @pre In order to use this function the driver must have been configured
261 * without callbacks (@p end_cb = @p NULL).
262 *
263 * @param[in] wspip pointer to the @p WSPIDriver object
264 * @param[in] cmdp pointer to the command descriptor
265 * @param[in] n number of bytes to send
266 * @param[in] txbuf the pointer to the transmit buffer
267 * @return The operation status.
268 * @retval false if the operation succeeded.
269 * @retval true if the operation failed because HW issues.
270 *
271 * @api
272 */
273bool wspiSend(WSPIDriver *wspip, const wspi_command_t *cmdp,
274 size_t n, const uint8_t *txbuf) {
275 msg_t msg;
276
277 osalDbgCheck((wspip != NULL) && (cmdp != NULL));
278 osalDbgCheck((n > 0U) && (txbuf != NULL));
280
281 osalSysLock();
282
283 osalDbgAssert(wspip->state == WSPI_READY, "not ready");
284 osalDbgAssert(wspip->config->end_cb == NULL, "has callback");
285
286 wspiStartSendI(wspip, cmdp, n, txbuf);
287 msg = osalThreadSuspendS(&wspip->thread);
288
290
291 return (bool)(msg != MSG_OK);
292}
293
294/**
295 * @brief Sends a command then receives data over the WSPI bus.
296 * @pre In order to use this function the option @p WSPI_USE_WAIT must be
297 * enabled.
298 * @pre In order to use this function the driver must have been configured
299 * without callbacks (@p end_cb = @p NULL).
300 *
301 * @param[in] wspip pointer to the @p WSPIDriver object
302 * @param[in] cmdp pointer to the command descriptor
303 * @param[in] n number of bytes to send
304 * @param[out] rxbuf the pointer to the receive buffer
305 * @return The operation status.
306 * @retval false if the operation succeeded.
307 * @retval true if the operation failed because HW issues.
308 *
309 * @api
310 */
311bool wspiReceive(WSPIDriver *wspip, const wspi_command_t *cmdp,
312 size_t n, uint8_t *rxbuf) {
313 msg_t msg;
314
315 osalDbgCheck((wspip != NULL) && (cmdp != NULL));
316 osalDbgCheck((n > 0U) && (rxbuf != NULL));
318
319 osalSysLock();
320
321 osalDbgAssert(wspip->state == WSPI_READY, "not ready");
322 osalDbgAssert(wspip->config->end_cb == NULL, "has callback");
323
324 wspiStartReceiveI(wspip, cmdp, n, rxbuf);
325 msg = osalThreadSuspendS(&wspip->thread);
326
328
329 return (bool)(msg != MSG_OK);
330}
331#endif /* WSPI_USE_WAIT == TRUE */
332
333#if (WSPI_SUPPORTS_MEMMAP == TRUE) || defined(__DOXYGEN__)
334/**
335 * @brief Maps in memory space a WSPI flash device.
336 * @pre The memory flash device must be initialized appropriately
337 * before mapping it in memory space.
338 *
339 * @param[in] wspip pointer to the @p WSPIDriver object
340 * @param[in] cmdp pointer to the command descriptor
341 * @param[out] addrp pointer to the memory start address of the mapped
342 * flash or @p NULL
343 *
344 * @api
345 */
347 const wspi_command_t *cmdp,
348 uint8_t **addrp) {
349
350 osalDbgCheck((wspip != NULL) && (cmdp != NULL));
352
353 osalSysLock();
354
355 osalDbgAssert(wspip->state == WSPI_READY, "not ready");
356
357 wspiMapFlashI(wspip, cmdp, addrp);
358 wspip->state = WSPI_MEMMAP;
359
361}
362
363/**
364 * @brief Unmaps from memory space a WSPI flash device.
365 * @post The memory flash device must be re-initialized for normal
366 * commands exchange.
367 *
368 * @param[in] wspip pointer to the @p WSPIDriver object
369 *
370 * @api
371 */
373
374 osalDbgCheck(wspip != NULL);
375
376 osalSysLock();
377
378 osalDbgAssert(wspip->state == WSPI_MEMMAP, "not ready");
379
380 wspiUnmapFlashI(wspip);
381 wspip->state = WSPI_READY;
382
384}
385#endif /* WSPI_SUPPORTS_MEMMAP == TRUE */
386
387#if (WSPI_USE_MUTUAL_EXCLUSION == TRUE) || defined(__DOXYGEN__)
388/**
389 * @brief Gains exclusive access to the WSPI bus.
390 * @details This function tries to gain ownership to the WSPI bus, if the bus
391 * is already being used then the invoking thread is queued.
392 * @pre In order to use this function the option @p WSPI_USE_MUTUAL_EXCLUSION
393 * must be enabled.
394 *
395 * @param[in] wspip pointer to the @p WSPIDriver object
396 *
397 * @api
398 */
400
401 osalDbgCheck(wspip != NULL);
402
403 osalMutexLock(&wspip->mutex);
404}
405
406/**
407 * @brief Releases exclusive access to the WSPI bus.
408 * @pre In order to use this function the option @p WSPI_USE_MUTUAL_EXCLUSION
409 * must be enabled.
410 *
411 * @param[in] wspip pointer to the @p WSPIDriver object
412 *
413 * @api
414 */
416
417 osalDbgCheck(wspip != NULL);
418
419 osalMutexUnlock(&wspip->mutex);
420}
421#endif /* WSPI_USE_MUTUAL_EXCLUSION == TRUE */
422
423#endif /* HAL_USE_WSPI == TRUE */
424
425/** @} */
#define HAL_RET_SUCCESS
Definition hal.h:93
static void osalSysLock(void)
Enters a critical zone from thread context.
Definition osal.h:601
static void osalMutexObjectInit(mutex_t *mp)
Initializes a mutex_t object.
Definition osal.h:753
static void osalSysUnlock(void)
Leaves a critical zone from thread context.
Definition osal.h:611
msg_t osalThreadSuspendS(thread_reference_t *trp)
Sends the current thread sleeping and sets a reference variable.
Definition osal.c:183
void osalMutexLock(mutex_t *mp)
Locks the specified mutex.
Definition osal.c:380
#define osalDbgAssert(c, remark)
Condition assertion.
Definition osal.h:264
void osalMutexUnlock(mutex_t *mp)
Unlocks the specified mutex.
Definition osal.c:400
#define osalDbgCheck(c)
Function parameters check.
Definition osal.h:284
void wspiObjectInit(WSPIDriver *wspip)
Initializes the standard part of a WSPIDriver structure.
Definition hal_wspi.c:68
void wspi_lld_init(void)
Low level WSPI driver initialization.
void wspiMapFlash(WSPIDriver *wspip, const wspi_command_t *cmdp, uint8_t **addrp)
Maps in memory space a WSPI flash device.
Definition hal_wspi.c:346
#define wspiStartReceiveI(wspip, cmdp, n, rxbuf)
Receives data from the WSPI bus.
Definition hal_wspi.h:314
struct hal_wspi_driver WSPIDriver
Type of a structure representing an WSPI driver.
Definition hal_wspi.h:83
#define wspiStartSendI(wspip, cmdp, n, txbuf)
Sends data over the WSPI bus.
Definition hal_wspi.h:294
void wspiAcquireBus(WSPIDriver *wspip)
Gains exclusive access to the WSPI bus.
Definition hal_wspi.c:399
void wspiStartSend(WSPIDriver *wspip, const wspi_command_t *cmdp, size_t n, const uint8_t *txbuf)
Sends a command with data over the WSPI bus.
Definition hal_wspi.c:180
#define wspiMapFlashI(wspip, cmdp, addrp)
Maps in memory space a WSPI flash device.
Definition hal_wspi.h:335
void wspiInit(void)
WSPI Driver initialization.
Definition hal_wspi.c:56
void wspiStartCommand(WSPIDriver *wspip, const wspi_command_t *cmdp)
Sends a command without data phase.
Definition hal_wspi.c:156
msg_t wspiStart(WSPIDriver *wspip, const WSPIConfig *config)
Configures and activates the WSPI peripheral.
Definition hal_wspi.c:92
bool wspiReceive(WSPIDriver *wspip, const wspi_command_t *cmdp, size_t n, uint8_t *rxbuf)
Sends a command then receives data over the WSPI bus.
Definition hal_wspi.c:311
#define wspiStartCommandI(wspip, cmdp)
Sends a command without data phase.
Definition hal_wspi.h:274
void wspi_lld_stop(WSPIDriver *wspip)
Deactivates the WSPI peripheral.
#define wspiUnmapFlashI(wspip)
Maps in memory space a WSPI flash device.
Definition hal_wspi.h:347
void wspiReleaseBus(WSPIDriver *wspip)
Releases exclusive access to the WSPI bus.
Definition hal_wspi.c:415
bool wspiCommand(WSPIDriver *wspip, const wspi_command_t *cmdp)
Sends a command without data phase.
Definition hal_wspi.c:237
bool wspiSend(WSPIDriver *wspip, const wspi_command_t *cmdp, size_t n, const uint8_t *txbuf)
Sends a command with data over the WSPI bus.
Definition hal_wspi.c:273
void wspiUnmapFlash(WSPIDriver *wspip)
Unmaps from memory space a WSPI flash device.
Definition hal_wspi.c:372
#define WSPI_CFG_DATA_MODE_MASK
Definition hal_wspi.h:241
void wspi_lld_start(WSPIDriver *wspip)
Configures and activates the WSPI peripheral.
struct hal_wspi_config WSPIConfig
Type of a structure representing an WSPI driver configuration.
Definition hal_wspi.h:88
void wspiStartReceive(WSPIDriver *wspip, const wspi_command_t *cmdp, size_t n, uint8_t *rxbuf)
Sends a command then receives data over the WSPI bus.
Definition hal_wspi.c:206
void wspiStop(WSPIDriver *wspip)
Deactivates the WSPI peripheral.
Definition hal_wspi.c:131
#define WSPI_CFG_DATA_MODE_NONE
Definition hal_wspi.h:242
@ WSPI_STOP
Definition hal_wspi.h:72
@ WSPI_MEMMAP
Definition hal_wspi.h:77
@ WSPI_READY
Definition hal_wspi.h:73
int32_t msg_t
Definition chearly.h:88
#define MSG_OK
Normal wakeup message.
Definition chschd.h:39
HAL subsystem header.
wspicallback_t end_cb
Operation complete callback or NULL.
Definition hal_wspi.h:143
const WSPIConfig * config
Current configuration data.
Definition hal_wspi.h:163
thread_reference_t thread
Waiting thread.
Definition hal_wspi.h:168
wspistate_t state
Driver state.
Definition hal_wspi.h:159
mutex_t mutex
Mutex protecting the peripheral.
Definition hal_wspi.h:174
Type of a WSPI command descriptor.
Definition hal_wspi.h:101
uint32_t cfg
Transfer configuration field.
Definition hal_wspi.h:105