hal_wspi.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  1. /*
  2. ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. /**
  14. * @file hal_wspi.c
  15. * @brief WSPI Driver code.
  16. *
  17. * @addtogroup WSPI
  18. * @{
  19. */
  20. #include "hal.h"
  21. #if (HAL_USE_WSPI == TRUE) || defined(__DOXYGEN__)
  22. /*===========================================================================*/
  23. /* Driver local definitions. */
  24. /*===========================================================================*/
  25. /*===========================================================================*/
  26. /* Driver exported variables. */
  27. /*===========================================================================*/
  28. /*===========================================================================*/
  29. /* Driver local variables and types. */
  30. /*===========================================================================*/
  31. /*===========================================================================*/
  32. /* Driver local functions. */
  33. /*===========================================================================*/
  34. /*===========================================================================*/
  35. /* Driver exported functions. */
  36. /*===========================================================================*/
  37. /**
  38. * @brief WSPI Driver initialization.
  39. * @note This function is implicitly invoked by @p halInit(), there is
  40. * no need to explicitly initialize the driver.
  41. *
  42. * @init
  43. */
  44. void wspiInit(void) {
  45. wspi_lld_init();
  46. }
  47. /**
  48. * @brief Initializes the standard part of a @p WSPIDriver structure.
  49. *
  50. * @param[out] wspip pointer to the @p WSPIDriver object
  51. *
  52. * @init
  53. */
  54. void wspiObjectInit(WSPIDriver *wspip) {
  55. wspip->state = WSPI_STOP;
  56. wspip->config = NULL;
  57. #if WSPI_USE_WAIT == TRUE
  58. wspip->thread = NULL;
  59. #endif
  60. #if WSPI_USE_MUTUAL_EXCLUSION == TRUE
  61. osalMutexObjectInit(&wspip->mutex);
  62. #endif
  63. #if defined(WSPI_DRIVER_EXT_INIT_HOOK)
  64. WSPI_DRIVER_EXT_INIT_HOOK(wspip);
  65. #endif
  66. }
  67. /**
  68. * @brief Configures and activates the WSPI peripheral.
  69. *
  70. * @param[in] wspip pointer to the @p WSPIDriver object
  71. * @param[in] config pointer to the @p WSPIConfig object
  72. *
  73. * @api
  74. */
  75. void wspiStart(WSPIDriver *wspip, const WSPIConfig *config) {
  76. osalDbgCheck((wspip != NULL) && (config != NULL));
  77. osalSysLock();
  78. osalDbgAssert((wspip->state == WSPI_STOP) || (wspip->state == WSPI_READY),
  79. "invalid state");
  80. wspip->config = config;
  81. wspi_lld_start(wspip);
  82. wspip->state = WSPI_READY;
  83. osalSysUnlock();
  84. }
  85. /**
  86. * @brief Deactivates the WSPI peripheral.
  87. * @note Deactivating the peripheral also enforces a release of the slave
  88. * select line.
  89. *
  90. * @param[in] wspip pointer to the @p WSPIDriver object
  91. *
  92. * @api
  93. */
  94. void wspiStop(WSPIDriver *wspip) {
  95. osalDbgCheck(wspip != NULL);
  96. osalSysLock();
  97. osalDbgAssert((wspip->state == WSPI_STOP) || (wspip->state == WSPI_READY),
  98. "invalid state");
  99. wspi_lld_stop(wspip);
  100. wspip->config = NULL;
  101. wspip->state = WSPI_STOP;
  102. osalSysUnlock();
  103. }
  104. /**
  105. * @brief Sends a command without data phase.
  106. * @post At the end of the operation the configured callback is invoked.
  107. *
  108. * @param[in] wspip pointer to the @p WSPIDriver object
  109. * @param[in] cmdp pointer to the command descriptor
  110. *
  111. * @api
  112. */
  113. void wspiStartCommand(WSPIDriver *wspip, const wspi_command_t *cmdp) {
  114. osalDbgCheck((wspip != NULL) && (cmdp != NULL));
  115. osalSysLock();
  116. osalDbgAssert(wspip->state == WSPI_READY, "not ready");
  117. wspiStartCommandI(wspip, cmdp);
  118. osalSysUnlock();
  119. }
  120. /**
  121. * @brief Sends a command with data over the WSPI bus.
  122. * @post At the end of the operation the configured callback is invoked.
  123. *
  124. * @param[in] wspip pointer to the @p WSPIDriver object
  125. * @param[in] cmdp pointer to the command descriptor
  126. * @param[in] n number of bytes to send
  127. * @param[in] txbuf the pointer to the transmit buffer
  128. *
  129. * @api
  130. */
  131. void wspiStartSend(WSPIDriver *wspip, const wspi_command_t *cmdp,
  132. size_t n, const uint8_t *txbuf) {
  133. osalDbgCheck((wspip != NULL) && (cmdp != NULL));
  134. osalDbgCheck((n > 0U) && (txbuf != NULL));
  135. osalSysLock();
  136. osalDbgAssert(wspip->state == WSPI_READY, "not ready");
  137. wspiStartSendI(wspip, cmdp, n, txbuf);
  138. osalSysUnlock();
  139. }
  140. /**
  141. * @brief Sends a command then receives data over the WSPI bus.
  142. * @post At the end of the operation the configured callback is invoked.
  143. *
  144. * @param[in] wspip pointer to the @p WSPIDriver object
  145. * @param[in] cmdp pointer to the command descriptor
  146. * @param[in] n number of bytes to send
  147. * @param[out] rxbuf the pointer to the receive buffer
  148. *
  149. * @api
  150. */
  151. void wspiStartReceive(WSPIDriver *wspip, const wspi_command_t *cmdp,
  152. size_t n, uint8_t *rxbuf) {
  153. osalDbgCheck((wspip != NULL) && (cmdp != NULL));
  154. osalDbgCheck((n > 0U) && (rxbuf != NULL));
  155. osalSysLock();
  156. osalDbgAssert(wspip->state == WSPI_READY, "not ready");
  157. wspiStartReceiveI(wspip, cmdp, n, rxbuf);
  158. osalSysUnlock();
  159. }
  160. #if (WSPI_USE_WAIT == TRUE) || defined(__DOXYGEN__)
  161. /**
  162. * @brief Sends a command without data phase.
  163. * @pre In order to use this function the option @p WSPI_USE_WAIT must be
  164. * enabled.
  165. * @pre In order to use this function the driver must have been configured
  166. * without callbacks (@p end_cb = @p NULL).
  167. *
  168. * @param[in] wspip pointer to the @p WSPIDriver object
  169. * @param[in] cmdp pointer to the command descriptor
  170. *
  171. * @api
  172. */
  173. void wspiCommand(WSPIDriver *wspip, const wspi_command_t *cmdp) {
  174. osalDbgCheck((wspip != NULL) && (cmdp != NULL));
  175. osalDbgCheck((cmdp->cfg & WSPI_CFG_DATA_MODE_MASK) == WSPI_CFG_DATA_MODE_NONE);
  176. osalSysLock();
  177. osalDbgAssert(wspip->state == WSPI_READY, "not ready");
  178. osalDbgAssert(wspip->config->end_cb == NULL, "has callback");
  179. wspiStartCommandI(wspip, cmdp);
  180. (void) osalThreadSuspendS(&wspip->thread);
  181. osalSysUnlock();
  182. }
  183. /**
  184. * @brief Sends a command with data over the WSPI bus.
  185. * @pre In order to use this function the option @p WSPI_USE_WAIT must be
  186. * enabled.
  187. * @pre In order to use this function the driver must have been configured
  188. * without callbacks (@p end_cb = @p NULL).
  189. *
  190. * @param[in] wspip pointer to the @p WSPIDriver object
  191. * @param[in] cmdp pointer to the command descriptor
  192. * @param[in] n number of bytes to send
  193. * @param[in] txbuf the pointer to the transmit buffer
  194. *
  195. * @api
  196. */
  197. void wspiSend(WSPIDriver *wspip, const wspi_command_t *cmdp,
  198. size_t n, const uint8_t *txbuf) {
  199. osalDbgCheck((wspip != NULL) && (cmdp != NULL));
  200. osalDbgCheck((n > 0U) && (txbuf != NULL));
  201. osalDbgCheck((cmdp->cfg & WSPI_CFG_DATA_MODE_MASK) != WSPI_CFG_DATA_MODE_NONE);
  202. osalSysLock();
  203. osalDbgAssert(wspip->state == WSPI_READY, "not ready");
  204. osalDbgAssert(wspip->config->end_cb == NULL, "has callback");
  205. wspiStartSendI(wspip, cmdp, n, txbuf);
  206. (void) osalThreadSuspendS(&wspip->thread);
  207. osalSysUnlock();
  208. }
  209. /**
  210. * @brief Sends a command then receives data over the WSPI bus.
  211. * @pre In order to use this function the option @p WSPI_USE_WAIT must be
  212. * enabled.
  213. * @pre In order to use this function the driver must have been configured
  214. * without callbacks (@p end_cb = @p NULL).
  215. *
  216. * @param[in] wspip pointer to the @p WSPIDriver object
  217. * @param[in] cmdp pointer to the command descriptor
  218. * @param[in] n number of bytes to send
  219. * @param[out] rxbuf the pointer to the receive buffer
  220. *
  221. * @api
  222. */
  223. void wspiReceive(WSPIDriver *wspip, const wspi_command_t *cmdp,
  224. size_t n, uint8_t *rxbuf) {
  225. osalDbgCheck((wspip != NULL) && (cmdp != NULL));
  226. osalDbgCheck((n > 0U) && (rxbuf != NULL));
  227. osalDbgCheck((cmdp->cfg & WSPI_CFG_DATA_MODE_MASK) != WSPI_CFG_DATA_MODE_NONE);
  228. osalSysLock();
  229. osalDbgAssert(wspip->state == WSPI_READY, "not ready");
  230. osalDbgAssert(wspip->config->end_cb == NULL, "has callback");
  231. wspiStartReceiveI(wspip, cmdp, n, rxbuf);
  232. (void) osalThreadSuspendS(&wspip->thread);
  233. osalSysUnlock();
  234. }
  235. #endif /* WSPI_USE_WAIT == TRUE */
  236. #if (WSPI_SUPPORTS_MEMMAP == TRUE) || defined(__DOXYGEN__)
  237. /**
  238. * @brief Maps in memory space a WSPI flash device.
  239. * @pre The memory flash device must be initialized appropriately
  240. * before mapping it in memory space.
  241. *
  242. * @param[in] wspip pointer to the @p WSPIDriver object
  243. * @param[in] cmdp pointer to the command descriptor
  244. * @param[out] addrp pointer to the memory start address of the mapped
  245. * flash or @p NULL
  246. *
  247. * @api
  248. */
  249. void wspiMapFlash(WSPIDriver *wspip,
  250. const wspi_command_t *cmdp,
  251. uint8_t **addrp) {
  252. osalDbgCheck((wspip != NULL) && (cmdp != NULL));
  253. osalDbgCheck((cmdp->cfg & WSPI_CFG_DATA_MODE_MASK) != WSPI_CFG_DATA_MODE_NONE);
  254. osalSysLock();
  255. osalDbgAssert(wspip->state == WSPI_READY, "not ready");
  256. wspiMapFlashI(wspip, cmdp, addrp);
  257. wspip->state = WSPI_MEMMAP;
  258. osalSysUnlock();
  259. }
  260. /**
  261. * @brief Unmaps from memory space a WSPI flash device.
  262. * @post The memory flash device must be re-initialized for normal
  263. * commands exchange.
  264. *
  265. * @param[in] wspip pointer to the @p WSPIDriver object
  266. *
  267. * @api
  268. */
  269. void wspiUnmapFlash(WSPIDriver *wspip) {
  270. osalDbgCheck(wspip != NULL);
  271. osalSysLock();
  272. osalDbgAssert(wspip->state == WSPI_MEMMAP, "not ready");
  273. wspiUnmapFlashI(wspip);
  274. wspip->state = WSPI_READY;
  275. osalSysUnlock();
  276. }
  277. #endif /* WSPI_SUPPORTS_MEMMAP == TRUE */
  278. #if (WSPI_USE_MUTUAL_EXCLUSION == TRUE) || defined(__DOXYGEN__)
  279. /**
  280. * @brief Gains exclusive access to the WSPI bus.
  281. * @details This function tries to gain ownership to the WSPI bus, if the bus
  282. * is already being used then the invoking thread is queued.
  283. * @pre In order to use this function the option @p WSPI_USE_MUTUAL_EXCLUSION
  284. * must be enabled.
  285. *
  286. * @param[in] wspip pointer to the @p WSPIDriver object
  287. *
  288. * @api
  289. */
  290. void wspiAcquireBus(WSPIDriver *wspip) {
  291. osalDbgCheck(wspip != NULL);
  292. osalMutexLock(&wspip->mutex);
  293. }
  294. /**
  295. * @brief Releases exclusive access to the WSPI bus.
  296. * @pre In order to use this function the option @p WSPI_USE_MUTUAL_EXCLUSION
  297. * must be enabled.
  298. *
  299. * @param[in] wspip pointer to the @p WSPIDriver object
  300. *
  301. * @api
  302. */
  303. void wspiReleaseBus(WSPIDriver *wspip) {
  304. osalDbgCheck(wspip != NULL);
  305. osalMutexUnlock(&wspip->mutex);
  306. }
  307. #endif /* WSPI_USE_MUTUAL_EXCLUSION == TRUE */
  308. #endif /* HAL_USE_WSPI == TRUE */
  309. /** @} */