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