ChibiOS/HAL  7.0.3
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  *
217  * @api
218  */
219 void wspiCommand(WSPIDriver *wspip, const wspi_command_t *cmdp) {
220 
221  osalDbgCheck((wspip != NULL) && (cmdp != NULL));
222  osalDbgCheck((cmdp->cfg & WSPI_CFG_DATA_MODE_MASK) == WSPI_CFG_DATA_MODE_NONE);
223 
224  osalSysLock();
225 
226  osalDbgAssert(wspip->state == WSPI_READY, "not ready");
227  osalDbgAssert(wspip->config->end_cb == NULL, "has callback");
228 
229  wspiStartCommandI(wspip, cmdp);
230  (void) osalThreadSuspendS(&wspip->thread);
231 
232  osalSysUnlock();
233 }
234 
235 /**
236  * @brief Sends a command with data over the WSPI bus.
237  * @pre In order to use this function the option @p WSPI_USE_WAIT must be
238  * enabled.
239  * @pre In order to use this function the driver must have been configured
240  * without callbacks (@p end_cb = @p NULL).
241  *
242  * @param[in] wspip pointer to the @p WSPIDriver object
243  * @param[in] cmdp pointer to the command descriptor
244  * @param[in] n number of bytes to send
245  * @param[in] txbuf the pointer to the transmit buffer
246  *
247  * @api
248  */
249 void wspiSend(WSPIDriver *wspip, const wspi_command_t *cmdp,
250  size_t n, const uint8_t *txbuf) {
251 
252  osalDbgCheck((wspip != NULL) && (cmdp != NULL));
253  osalDbgCheck((n > 0U) && (txbuf != NULL));
254  osalDbgCheck((cmdp->cfg & WSPI_CFG_DATA_MODE_MASK) != WSPI_CFG_DATA_MODE_NONE);
255 
256  osalSysLock();
257 
258  osalDbgAssert(wspip->state == WSPI_READY, "not ready");
259  osalDbgAssert(wspip->config->end_cb == NULL, "has callback");
260 
261  wspiStartSendI(wspip, cmdp, n, txbuf);
262  (void) osalThreadSuspendS(&wspip->thread);
263 
264  osalSysUnlock();
265 }
266 
267 /**
268  * @brief Sends a command then receives data over the WSPI bus.
269  * @pre In order to use this function the option @p WSPI_USE_WAIT must be
270  * enabled.
271  * @pre In order to use this function the driver must have been configured
272  * without callbacks (@p end_cb = @p NULL).
273  *
274  * @param[in] wspip pointer to the @p WSPIDriver object
275  * @param[in] cmdp pointer to the command descriptor
276  * @param[in] n number of bytes to send
277  * @param[out] rxbuf the pointer to the receive buffer
278  *
279  * @api
280  */
281 void wspiReceive(WSPIDriver *wspip, const wspi_command_t *cmdp,
282  size_t n, uint8_t *rxbuf) {
283 
284  osalDbgCheck((wspip != NULL) && (cmdp != NULL));
285  osalDbgCheck((n > 0U) && (rxbuf != NULL));
286  osalDbgCheck((cmdp->cfg & WSPI_CFG_DATA_MODE_MASK) != WSPI_CFG_DATA_MODE_NONE);
287 
288  osalSysLock();
289 
290  osalDbgAssert(wspip->state == WSPI_READY, "not ready");
291  osalDbgAssert(wspip->config->end_cb == NULL, "has callback");
292 
293  wspiStartReceiveI(wspip, cmdp, n, rxbuf);
294  (void) osalThreadSuspendS(&wspip->thread);
295 
296  osalSysUnlock();
297 }
298 #endif /* WSPI_USE_WAIT == TRUE */
299 
300 #if (WSPI_SUPPORTS_MEMMAP == TRUE) || defined(__DOXYGEN__)
301 /**
302  * @brief Maps in memory space a WSPI flash device.
303  * @pre The memory flash device must be initialized appropriately
304  * before mapping it in memory space.
305  *
306  * @param[in] wspip pointer to the @p WSPIDriver object
307  * @param[in] cmdp pointer to the command descriptor
308  * @param[out] addrp pointer to the memory start address of the mapped
309  * flash or @p NULL
310  *
311  * @api
312  */
314  const wspi_command_t *cmdp,
315  uint8_t **addrp) {
316 
317  osalDbgCheck((wspip != NULL) && (cmdp != NULL));
318  osalDbgCheck((cmdp->cfg & WSPI_CFG_DATA_MODE_MASK) != WSPI_CFG_DATA_MODE_NONE);
319 
320  osalSysLock();
321 
322  osalDbgAssert(wspip->state == WSPI_READY, "not ready");
323 
324  wspiMapFlashI(wspip, cmdp, addrp);
325  wspip->state = WSPI_MEMMAP;
326 
327  osalSysUnlock();
328 }
329 
330 /**
331  * @brief Unmaps from memory space a WSPI flash device.
332  * @post The memory flash device must be re-initialized for normal
333  * commands exchange.
334  *
335  * @param[in] wspip pointer to the @p WSPIDriver object
336  *
337  * @api
338  */
340 
341  osalDbgCheck(wspip != NULL);
342 
343  osalSysLock();
344 
345  osalDbgAssert(wspip->state == WSPI_MEMMAP, "not ready");
346 
347  wspiUnmapFlashI(wspip);
348  wspip->state = WSPI_READY;
349 
350  osalSysUnlock();
351 }
352 #endif /* WSPI_SUPPORTS_MEMMAP == TRUE */
353 
354 #if (WSPI_USE_MUTUAL_EXCLUSION == TRUE) || defined(__DOXYGEN__)
355 /**
356  * @brief Gains exclusive access to the WSPI bus.
357  * @details This function tries to gain ownership to the WSPI bus, if the bus
358  * is already being used then the invoking thread is queued.
359  * @pre In order to use this function the option @p WSPI_USE_MUTUAL_EXCLUSION
360  * must be enabled.
361  *
362  * @param[in] wspip pointer to the @p WSPIDriver object
363  *
364  * @api
365  */
367 
368  osalDbgCheck(wspip != NULL);
369 
370  osalMutexLock(&wspip->mutex);
371 }
372 
373 /**
374  * @brief Releases exclusive access to the WSPI bus.
375  * @pre In order to use this function the option @p WSPI_USE_MUTUAL_EXCLUSION
376  * must be enabled.
377  *
378  * @param[in] wspip pointer to the @p WSPIDriver object
379  *
380  * @api
381  */
383 
384  osalDbgCheck(wspip != NULL);
385 
386  osalMutexUnlock(&wspip->mutex);
387 }
388 #endif /* WSPI_USE_MUTUAL_EXCLUSION == TRUE */
389 
390 #endif /* HAL_USE_WSPI == TRUE */
391 
392 /** @} */
static void osalMutexObjectInit(mutex_t *mp)
Initializes s mutex_t object.
Definition: osal.h:681
void wspiMapFlash(WSPIDriver *wspip, const wspi_command_t *cmdp, uint8_t **addrp)
Maps in memory space a WSPI flash device.
Definition: hal_wspi.c:313
wspicallback_t end_cb
Operation complete callback or NULL.
Definition: hal_wspi.h:142
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
msg_t osalThreadSuspendS(thread_reference_t *trp)
Sends the current thread sleeping and sets a reference variable.
Definition: osal.c:185
void wspiAcquireBus(WSPIDriver *wspip)
Gains exclusive access to the WSPI bus.
Definition: hal_wspi.c:366
void wspi_lld_start(WSPIDriver *wspip)
Configures and activates the WSPI peripheral.
Definition: hal_wspi_lld.c:77
Structure representing an WSPI driver.
Definition: hal_wspi.h:150
HAL subsystem header.
void wspiStart(WSPIDriver *wspip, const WSPIConfig *config)
Configures and activates the WSPI peripheral.
Definition: hal_wspi.c:91
void 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:249
void wspiStop(WSPIDriver *wspip)
Deactivates the WSPI peripheral.
Definition: hal_wspi.c:116
void osalMutexLock(mutex_t *mp)
Locks the specified mutex.
Definition: osal.c:384
Driver configuration structure.
Definition: hal_wspi.h:138
static void osalSysUnlock(void)
Leaves a critical zone from thread context.
Definition: osal.h:540
void wspiInit(void)
WSPI Driver initialization.
Definition: hal_wspi.c:56
void wspiReleaseBus(WSPIDriver *wspip)
Releases exclusive access to the WSPI bus.
Definition: hal_wspi.c:382
void wspiUnmapFlash(WSPIDriver *wspip)
Unmaps from memory space a WSPI flash device.
Definition: hal_wspi.c:339
#define wspiStartCommandI(wspip, cmdp)
Sends a command without data phase.
Definition: hal_wspi.h:269
void wspi_lld_init(void)
Low level WSPI driver initialization.
Definition: hal_wspi_lld.c:63
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
const WSPIConfig * config
Current configuration data.
Definition: hal_wspi.h:158
void wspiObjectInit(WSPIDriver *wspip)
Initializes the standard part of a WSPIDriver structure.
Definition: hal_wspi.c:68
wspistate_t state
Driver state.
Definition: hal_wspi.h:154
thread_reference_t thread
Waiting thread.
Definition: hal_wspi.h:163
#define osalDbgCheck(c)
Function parameters check.
Definition: osal.h:278
#define wspiUnmapFlashI(wspip)
Maps in memory space a WSPI flash device.
Definition: hal_wspi.h:342
mutex_t mutex
Mutex protecting the peripheral.
Definition: hal_wspi.h:169
#define wspiMapFlashI(wspip, cmdp, addrp)
Maps in memory space a WSPI flash device.
Definition: hal_wspi.h:330
void 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:281
#define wspiStartReceiveI(wspip, cmdp, n, rxbuf)
Receives data from the WSPI bus.
Definition: hal_wspi.h:309
void wspi_lld_stop(WSPIDriver *wspip)
Deactivates the WSPI peripheral.
Definition: hal_wspi_lld.c:99
Type of a WSPI command descriptor.
Definition: hal_wspi.h:100
static void osalSysLock(void)
Enters a critical zone from thread context.
Definition: osal.h:530
#define wspiStartSendI(wspip, cmdp, n, txbuf)
Sends data over the WSPI bus.
Definition: hal_wspi.h:289
void wspiCommand(WSPIDriver *wspip, const wspi_command_t *cmdp)
Sends a command without data phase.
Definition: hal_wspi.c:219
#define osalDbgAssert(c, remark)
Condition assertion.
Definition: osal.h:258
void osalMutexUnlock(mutex_t *mp)
Unlocks the specified mutex.
Definition: osal.c:404
void wspiStartCommand(WSPIDriver *wspip, const wspi_command_t *cmdp)
Sends a command without data phase.
Definition: hal_wspi.c:141
uint32_t cfg
Transfer configuration field.
Definition: hal_wspi.h:104