dev_spi.h 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577
  1. /* ------------------------------------------
  2. * Copyright (c) 2017, Synopsys, Inc. All rights reserved.
  3. * Redistribution and use in source and binary forms, with or without modification,
  4. * are permitted provided that the following conditions are met:
  5. * 1) Redistributions of source code must retain the above copyright notice, this
  6. * list of conditions and the following disclaimer.
  7. * 2) Redistributions in binary form must reproduce the above copyright notice,
  8. * this list of conditions and the following disclaimer in the documentation and/or
  9. * other materials provided with the distribution.
  10. * 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
  11. * be used to endorse or promote products derived from this software without
  12. * specific prior written permission.
  13. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  14. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  15. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  16. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
  17. * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  18. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  19. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
  20. * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  21. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  22. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  23. *
  24. * \version 2017.03
  25. * \date 2014-06-16
  26. * \author Huaqi Fang(Huaqi.Fang@synopsys.com)
  27. --------------------------------------------- */
  28. /**
  29. * \defgroup DEVICE_HAL_SPI SPI Device HAL Interface
  30. * \ingroup DEVICE_HAL_DEF
  31. * \brief definitions for spi device hardware layer (\ref dev_spi.h)
  32. * \details provide interfaces for spi driver to implement
  33. * Here is a diagram for the spi interface.
  34. *
  35. * \htmlonly
  36. * <div class="imagebox">
  37. * <div style="width: 600px">
  38. * <img src="pic/dev_spi_hal.jpg" alt="SPI Device HAL Interface Diagram"/>
  39. * <p>SPI Device HAL Interface Diagram</p>
  40. * </div>
  41. * </div>
  42. * \endhtmlonly
  43. *
  44. * @{
  45. *
  46. * \file
  47. * \brief spi device hardware layer definitions
  48. * \details provide common definitions for spi device,
  49. * then software developer can develop spi driver
  50. * following this definitions, and the applications
  51. * can directly call this definition to realize functions
  52. */
  53. #ifndef _DEVICE_HAL_SPI_H_
  54. #define _DEVICE_HAL_SPI_H_
  55. #include "device/device_hal/inc/dev_common.h"
  56. /**
  57. * \defgroup DEVICE_HAL_SPI_CTRLCMD SPI Device Control Commands
  58. * \ingroup DEVICE_HAL_SPI
  59. * \brief Definitions for spi control command, used in \ref dev_spi::spi_control "SPI IO Control"
  60. * \details These commands defined here can be used in user code directly.
  61. * - Parameters Usage
  62. * - For passing parameters like integer, just use uint32_t/int32_t to directly pass values
  63. * - For passing parameters for a structure, please use pointer to pass values
  64. * - For getting some data, please use pointer to store the return data
  65. * - Common Return Values
  66. * - \ref E_OK, Control device successfully
  67. * - \ref E_CLSED, Device is not opened
  68. * - \ref E_OBJ, Device object is not valid or not exists
  69. * - \ref E_PAR, Parameter is not valid for current control command
  70. * - \ref E_SYS, Control device failed, due to hardware issues such as device is disabled
  71. * - \ref E_CTX, Control device failed, due to different reasons like in transfer state
  72. * - \ref E_NOSPT, Control command is not supported or not valid
  73. * - Usage Comment
  74. * - For SPI poll or interrupt read/write/transfer operations, only 1 operation can be triggered.
  75. * If there is a operation is running, any other operation will return \ref E_CTX
  76. * - If SPI is in transfer, then the following operations may return \ref E_CTX. Like
  77. * \ref SPI_CMD_SET_CLK_MODE, \ref SPI_CMD_SET_TXINT_BUF, \ref SPI_CMD_SET_RXINT_BUF,
  78. * \ref SPI_CMD_SET_TXINT, \ref SPI_CMD_SET_RXINT, \ref SPI_CMD_ABORT_TX, \ref SPI_CMD_ABORT_RX,
  79. * \ref SPI_CMD_FLUSH_TX, \ref SPI_CMD_FLUSH_RX, \ref SPI_CMD_SET_DFS, \ref SPI_CMD_TRANSFER_POLLING,
  80. * \ref SPI_CMD_TRANSFER_INT, \ref SPI_CMD_ABORT_XFER, \ref SPI_CMD_MST_SEL_DEV, \ref SPI_CMD_MST_DSEL_DEV,
  81. * \ref SPI_CMD_MST_SET_FREQ and \ref dev_spi::spi_write "SPI Poll Write" or \ref dev_spi::spi_read "SPI Poll Read".
  82. * @{
  83. */
  84. /** Define SPI control commands for common usage */
  85. #define DEV_SET_SPI_SYSCMD(cmd) DEV_SET_SYSCMD((cmd))
  86. /** Define SPI control commands for master usage */
  87. #define DEV_SET_SPI_MST_SYSCMD(cmd) DEV_SET_SYSCMD(0x00001000|(cmd))
  88. /** Define SPI control commands for slave usage */
  89. #define DEV_SET_SPI_SLV_SYSCMD(cmd) DEV_SET_SYSCMD(0x00002000|(cmd))
  90. /* ++++ Common commands for SPI Device ++++ */
  91. /**
  92. * Get \ref dev_spi_info::status "current device status"
  93. * - Param type : uint32_t *
  94. * - Param usage : store result of current status
  95. * - Return value explanation :
  96. */
  97. #define SPI_CMD_GET_STATUS DEV_SET_SPI_SYSCMD(0)
  98. /**
  99. * set the \ref dev_spi_info::clk_mode "clock mode" of spi transfer
  100. * - Param type : uint32_t
  101. * - Param usage : spi clock mode to choose clock phase and clock polarity
  102. * - Return value explanation :
  103. */
  104. #define SPI_CMD_SET_CLK_MODE DEV_SET_SPI_SYSCMD(1)
  105. /**
  106. * set spi \ref dev_spi_info::dfs "data frame size"
  107. * - Param type : uint32_t
  108. * - Param usage : should > 0
  109. * - Return value explanation : If dfs is not supported, then return \ref E_SYS
  110. */
  111. #define SPI_CMD_SET_DFS DEV_SET_SPI_SYSCMD(2)
  112. /**
  113. * set the \ref dev_spi_info::dummy "dummy data" during spi transfer
  114. * - Param type : uint32_t
  115. * - Param usage : dummy data to transfer
  116. * - Return value explanation :
  117. */
  118. #define SPI_CMD_SET_DUMMY_DATA DEV_SET_SPI_SYSCMD(3)
  119. /**
  120. * Set \ref dev_spi_cbs::tx_cb "spi transmit success callback" function
  121. * when all required bytes are transmitted for interrupt method
  122. * - Param type : \ref DEV_CALLBACK * or NULL
  123. * - Param usage : transmit success callback function for spi
  124. * - Return value explanation :
  125. */
  126. #define SPI_CMD_SET_TXCB DEV_SET_SPI_SYSCMD(4)
  127. /**
  128. * Set \ref dev_spi_cbs::rx_cb "spi receive success callback" function
  129. * when all required bytes are received for interrupt method
  130. * - Param type : \ref DEV_CALLBACK * or NULL
  131. * - Param usage : receive success callback function for spi
  132. * - Return value explanation :
  133. */
  134. #define SPI_CMD_SET_RXCB DEV_SET_SPI_SYSCMD(5)
  135. /**
  136. * Set \ref dev_spi_cbs::xfer_cb "spi transfer success callback" function
  137. * when all required transfer are done for interrupt method
  138. * - Param type : \ref DEV_CALLBACK * or NULL
  139. * - Param usage : transfer success callback function for spi
  140. * - Return value explanation :
  141. */
  142. #define SPI_CMD_SET_XFERCB DEV_SET_SPI_SYSCMD(6)
  143. /**
  144. * Set \ref dev_spi_cbs::err_cb "spi transfer error callback" function
  145. * when something error happened for interrupt method
  146. * - Param type : \ref DEV_CALLBACK * or NULL
  147. * - Param usage : transfer error callback function for spi
  148. * - Return value explanation :
  149. */
  150. #define SPI_CMD_SET_ERRCB DEV_SET_SPI_SYSCMD(7)
  151. /**
  152. * Set buffer in interrupt transmit, and it will set \ref dev_spi_info::xfer "spi tranfer".
  153. * - SPI master and slave mode use case \n
  154. * For both master and slave mode, if you set tx buffer to NULL, when tx interrupt is enabled and entered into tx interrupt,
  155. * it will automatically disable the tx interrupt, so when you want to transfer something, you need to set the
  156. * tx buffer to Non-NULL and enable tx interrupt, when the tx buffer is sent, it will disable the tx interrupt
  157. * and call tx callback function if available.
  158. * - Param type : DEV_BUFFER * or NULL
  159. * - Param usage : buffer structure pointer, if param is NULL, then it will set xfer to empty
  160. * - Return value explanation :
  161. */
  162. #define SPI_CMD_SET_TXINT_BUF DEV_SET_SPI_SYSCMD(8)
  163. /**
  164. * Set buffer in interrupt receive, and it will set \ref dev_spi_info::xfer "spi tranfer".
  165. * - SPI master mode use case \n
  166. * Similar to \ref SPI_CMD_SET_TXINT_BUF
  167. * - SPI slave mode use case \n
  168. * Similiar to \ref SPI_CMD_SET_TXINT_BUF
  169. * - Param type : DEV_BUFFER * or NULL
  170. * - Param usage : buffer structure pointer, if param is NULL, then it will set xfer to empty
  171. * - Return value explanation :
  172. */
  173. #define SPI_CMD_SET_RXINT_BUF DEV_SET_SPI_SYSCMD(9)
  174. /**
  175. * Enable or disable transmit interrupt,
  176. * for master mode, only one of tx and rx interrupt can be enabled,
  177. * if tx interrupt is enabled, then rx interrupt can't be enabled.
  178. * - Param type : uint32_t
  179. * - Param usage : enable(none-zero) or disable(zero) flag
  180. * - Return value explanation :
  181. */
  182. #define SPI_CMD_SET_TXINT DEV_SET_SPI_SYSCMD(10)
  183. /**
  184. * Enable or disable receive interrupt,
  185. * for master mode, only one of tx and rx interrupt can be enabled,
  186. * if rx interrupt is enabled, then tx interrupt can't be enabled.
  187. * - Param type : uint32_t
  188. * - Param usage : enable(none-zero) or disable(zero) flag
  189. * - Return value explanation :
  190. */
  191. #define SPI_CMD_SET_RXINT DEV_SET_SPI_SYSCMD(11)
  192. /**
  193. * start the transfer by polling
  194. * - Param type : \ref DEV_SPI_TRANSFER *
  195. * - Param usage :
  196. * - Return value explanation :
  197. */
  198. #define SPI_CMD_TRANSFER_POLLING DEV_SET_SPI_SYSCMD(12)
  199. /**
  200. * start the transfer by interrupt
  201. * - Param type : \ref DEV_SPI_TRANSFER * or NULL
  202. * - Param usage : If NULL, it will disable transfer interrupt, if not NULL, it will enable transfer interrupt
  203. * - Return value explanation :
  204. */
  205. #define SPI_CMD_TRANSFER_INT DEV_SET_SPI_SYSCMD(13)
  206. /**
  207. * Abort current interrupt transmit operation if tx interrupt enabled,
  208. * it will disable transmit interrupt, and set \ref DEV_IN_TX_ABRT
  209. * in \ref dev_spi_info::status "status" variable,
  210. * and call the transmit callback function, when tx callback is finished,
  211. * it will clear \ref DEV_IN_TX_ABRT and return
  212. * - Param type : NULL
  213. * - Param usage :
  214. * - Return value explanation :
  215. */
  216. #define SPI_CMD_ABORT_TX DEV_SET_SPI_SYSCMD(14)
  217. /**
  218. * Abort current interrupt receive operation if rx interrupt enabled,
  219. * it will disable receive interrupt, and set \ref DEV_IN_TX_ABRT
  220. * in \ref dev_spi_info::status "status" variable,
  221. * and call the receive callback function, when rx callback is finished,
  222. * it will clear \ref DEV_IN_TX_ABRT and return
  223. * - Param type : NULL
  224. * - Param usage :
  225. * - Return value explanation :
  226. */
  227. #define SPI_CMD_ABORT_RX DEV_SET_SPI_SYSCMD(15)
  228. /**
  229. * Abort current interrupt transfer operation if transfer is issued,
  230. * it will disable transfer interrupt, and set \ref DEV_IN_XFER_ABRT
  231. * in \ref dev_spi_info::status "status" variable,
  232. * and call the transfer callback function, when xfer callback is finished,
  233. * it will clear \ref DEV_IN_XFER_ABRT and return
  234. * - Param type : NULL
  235. * - Param usage :
  236. * - Return value explanation :
  237. */
  238. #define SPI_CMD_ABORT_XFER DEV_SET_SPI_SYSCMD(16)
  239. /**
  240. * Do a software reset for SPI device, it will stop current transfer,
  241. * and clear error state and bring device to normal state, set next condition to STOP
  242. * - Param type : NULL
  243. * - Param usage :
  244. * - Return value explanation :
  245. */
  246. #define SPI_CMD_RESET DEV_SET_SPI_SYSCMD(17)
  247. /**
  248. * Flush spi tx fifo, this will clear the data in tx fifo
  249. * - Param type : NULL
  250. * - Param usage :
  251. * - Return value explanation :
  252. */
  253. #define SPI_CMD_FLUSH_TX DEV_SET_SPI_SYSCMD(18)
  254. /**
  255. * Flush spi rx fifo, this will clear the data in rx fifo
  256. * - Param type : NULL
  257. * - Param usage :
  258. * - Return value explanation :
  259. */
  260. #define SPI_CMD_FLUSH_RX DEV_SET_SPI_SYSCMD(19)
  261. /**
  262. * Enable spi device
  263. * - Param type : NULL
  264. * - Param usage : param is not required
  265. * - Return value explanation :
  266. */
  267. #define SPI_CMD_ENA_DEV DEV_SET_SPI_SYSCMD(20)
  268. /**
  269. * Disable spi device, when device is disabled,
  270. * only \ref SPI_CMD_ENA_DEV, \ref SPI_CMD_DIS_DEV,
  271. * \ref SPI_CMD_GET_STATUS and \ref SPI_CMD_RESET
  272. * commands can be executed, other commands will return \ref E_SYS
  273. * - Param type : NULL
  274. * - Param usage : param is not required
  275. * - Return value explanation :
  276. */
  277. #define SPI_CMD_DIS_DEV DEV_SET_SPI_SYSCMD(21)
  278. /**
  279. * Get how many bytes space in spi are available to transmit,
  280. * this can be used in interrupt callback functions,
  281. * cooperate with \ref dev_spi::spi_write "spi_write" API to realize non-blocked write
  282. * - Param type : int32_t *
  283. * - Param usage : store the write available bytes, > 0 for available bytes, 0 for not available
  284. * - Return value explanation :
  285. */
  286. #define SPI_CMD_GET_TXAVAIL DEV_SET_SPI_SYSCMD(22)
  287. /**
  288. * Get how many bytes in spi are available to receive,
  289. * this can be used in interrupt callback functions,
  290. * cooperate with \ref dev_spi::spi_read "spi_read" API to realize non-blocked read
  291. * - Param type : int32_t *
  292. * - Param usage : store the read available bytes, > 0 for available bytes, 0 for not available
  293. * - Return value explanation :
  294. */
  295. #define SPI_CMD_GET_RXAVAIL DEV_SET_SPI_SYSCMD(23)
  296. /* ++++ Master only commands for SPI Device ++++ */
  297. /**
  298. * select spi slave device
  299. * - Param type : uint32_t
  300. * - Param usage : the number of spi slave device to select
  301. * - Return value explanation : return \ref E_SYS when selection can't be done, return \ref E_CTX during transfer
  302. */
  303. #define SPI_CMD_MST_SEL_DEV DEV_SET_SPI_MST_SYSCMD(0)
  304. /**
  305. * de-select spi slave device
  306. * - Param type : uint32_t
  307. * - Param usage : the number of spi slave device to de-select
  308. * - Return value explanation : return \ref E_SYS when selection can't be done, return \ref E_CTX during transfer
  309. */
  310. #define SPI_CMD_MST_DSEL_DEV DEV_SET_SPI_MST_SYSCMD(1)
  311. /**
  312. * Set \ref dev_spi_info::freq "spi frequency".
  313. * - Param type : uint32_t
  314. * - Param usage : spi freq
  315. * - Return value explanation : no return
  316. */
  317. #define SPI_CMD_MST_SET_FREQ DEV_SET_SPI_MST_SYSCMD(2)
  318. /* ++++ Slave only commands for SPI Device ++++ */
  319. /* \todo add spi slave related CMDs */
  320. /** @} */
  321. /**
  322. * \defgroup DEVICE_HAL_SPI_CALLBACK SPI Interrupt callback functions
  323. * \ingroup DEVICE_HAL_SPI
  324. * \brief callback function structure for SPI device
  325. * @{
  326. */
  327. typedef struct dev_spi_cbs {
  328. DEV_CALLBACK tx_cb; /*!< spi data transmit success required bytes callback */
  329. DEV_CALLBACK rx_cb; /*!< spi data receive success required bytes callback */
  330. DEV_CALLBACK err_cb; /*!< spi error callback */
  331. DEV_CALLBACK xfer_cb; /*!< transfer callback */
  332. } DEV_SPI_CBS, *DEV_SPI_CBS_PTR;
  333. /** @} */
  334. /** SPI Clock Mode */
  335. typedef enum spi_clk_mode {
  336. SPI_CPOL_0_CPHA_0 = 0, /*!< Inactive state of serial clock is low, serial clock toggles in middle of first data bit */
  337. SPI_CPOL_0_CPHA_1 = 1, /*!< Inactive state of serial clock is low, serial clock toggles at start of first data bit */
  338. SPI_CPOL_1_CPHA_0 = 2, /*!< Inactive state of serial clock is high, serial clock toggles in middle of first data bit */
  339. SPI_CPOL_1_CPHA_1 = 3, /*!< Inactive state of serial clock is high, serial clock toggles at start of first data bit */
  340. SPI_CLK_MODE_0 = SPI_CPOL_0_CPHA_0, /*!< Equal to \ref SPI_CPOL_0_CPHA_0 */
  341. SPI_CLK_MODE_1 = SPI_CPOL_0_CPHA_1, /*!< Equal to \ref SPI_CPOL_0_CPHA_1 */
  342. SPI_CLK_MODE_2 = SPI_CPOL_1_CPHA_0, /*!< Equal to \ref SPI_CPOL_1_CPHA_0 */
  343. SPI_CLK_MODE_3 = SPI_CPOL_1_CPHA_1 /*!< Equal to \ref SPI_CPOL_1_CPHA_1 */
  344. } SPI_CLK_MODE;
  345. #define SPI_CLK_MODE_DEFAULT SPI_CPOL_0_CPHA_0 /*!< Default SPI device clock mode */
  346. /**
  347. * \defgroup DEVICE_HAL_SPI_DEVSTRUCT SPI Device Structure
  348. * \ingroup DEVICE_HAL_SPI
  349. * \brief contains definitions of spi device structure.
  350. * \details this structure will be used in user implemented code, which was called
  351. * Device Driver Implement Layer for spi to realize in user code.
  352. * @{
  353. */
  354. typedef struct dev_spi_transfer DEV_SPI_TRANSFER, *DEV_SPI_TRANSFER_PTR;
  355. /**
  356. * \brief spi read and write data structure used by \ref SPI_CMD_TRANSFER
  357. * spi write then read data
  358. *
  359. */
  360. struct dev_spi_transfer {
  361. DEV_SPI_TRANSFER *next;
  362. /* Calc by software */
  363. /** tot_len = (tx_totlen>rx_totlen)?tx_totlen:rx_totlen */
  364. uint32_t tot_len;
  365. /* Set by user */
  366. uint8_t *tx_buf;
  367. uint32_t tx_ofs;
  368. uint32_t tx_len;
  369. uint8_t *rx_buf;
  370. uint32_t rx_ofs;
  371. uint32_t rx_len;
  372. /* Should auto set to proper value during set buffer value */
  373. uint32_t tx_idx;
  374. uint32_t tx_totlen; /** tx_totlen = tx_len + tx_ofs */
  375. uint32_t rx_idx;
  376. uint32_t rx_totlen; /** rx_totlen = rx_len + rx_ofs */
  377. };
  378. /** Set tx buffer of device spi transfer */
  379. #define DEV_SPI_XFER_SET_TXBUF(xfer, buf, ofs, len) { \
  380. (xfer)->tx_buf = (uint8_t *)(buf); \
  381. (xfer)->tx_len = (uint32_t)(len); \
  382. (xfer)->tx_ofs = (uint32_t)(ofs); \
  383. (xfer)->tx_idx = 0; \
  384. (xfer)->tx_totlen = ( (uint32_t)(len) \
  385. + (uint32_t)(ofs) ) ; \
  386. }
  387. /** Set rx buffer of device spi transfer */
  388. #define DEV_SPI_XFER_SET_RXBUF(xfer, buf, ofs, len) { \
  389. (xfer)->rx_buf = (uint8_t *)(buf); \
  390. (xfer)->rx_len = (uint32_t)(len); \
  391. (xfer)->rx_ofs = (uint32_t)(ofs); \
  392. (xfer)->rx_idx = 0; \
  393. (xfer)->rx_totlen = ( (uint32_t)(len) \
  394. + (uint32_t)(ofs) ) ; \
  395. }
  396. /** Calculate total length of current transfer without next transfer */
  397. #define DEV_SPI_XFER_CALC_TOTLEN(xfer) (xfer)->tot_len = \
  398. ((xfer)->tx_totlen > (xfer)->rx_totlen) ? (xfer)->tx_totlen : (xfer)->rx_totlen ;
  399. /** Set next SPI transfer */
  400. #define DEV_SPI_XFER_SET_NEXT(xfer, next_xfer) (xfer)->next = (next_xfer);
  401. /** Init spi transfer */
  402. #define DEV_SPI_XFER_INIT(xfer) { \
  403. (xfer)->tx_idx = 0; \
  404. (xfer)->rx_idx = 0; \
  405. (xfer)->tx_totlen = ((xfer)->tx_len \
  406. + (xfer)->tx_ofs) ; \
  407. (xfer)->rx_totlen = ((xfer)->rx_len \
  408. + (xfer)->rx_ofs) ; \
  409. DEV_SPI_XFER_CALC_TOTLEN(xfer); \
  410. }
  411. /**
  412. * \brief spi information struct definition
  413. * \details informations about spi open state, working state,
  414. * frequency, spi registers, working method, interrupt number
  415. */
  416. typedef struct dev_spi_info {
  417. void *spi_ctrl; /*!< spi control related */
  418. uint32_t status; /*!< current working status, refer to \ref DEVICE_HAL_COMMON_DEVSTATUS, this should be \ref DEV_ENABLED for first open */
  419. uint32_t freq; /*!< spi working baudrate */
  420. uint8_t mode; /*!< spi working mode (master/slave) */
  421. uint8_t clk_mode; /*!< spi clock phase and polarity, this should be \ref SPI_CLK_MODE_DEFAULT for first open */
  422. uint8_t opn_cnt; /*!< spi open count, open it will increase 1, close it will decrease 1, 0 for close, >0 for open */
  423. uint8_t slave; /*!< current selected slave device no, start from 0, this should be \ref SPI_SLAVE_NOT_SELECTED for first open */
  424. uint8_t dfs; /*!< data frame size, this should be \ref SPI_DFS_DEFAULT for first open */
  425. DEV_SPI_TRANSFER xfer; /*!< spi transfer, this should be set to all zero for first open */
  426. DEV_SPI_CBS spi_cbs; /*!< spi callbacks, for both master and slave mode, this should be all NULL for first open */
  427. void *extra; /*!< a extra pointer to get hook to applications which should not used by bsp developer,
  428. this should be NULL for first open and you can \ref DEV_SPI_INFO_SET_EXTRA_OBJECT "set"
  429. or \ref DEV_SPI_INFO_GET_EXTRA_OBJECT "get" the extra information pointer */
  430. uint32_t dummy; /*!< dummy write data when send and receive, this should be \ref SPI_DUMMY_DEFAULT for first open */
  431. } DEV_SPI_INFO, * DEV_SPI_INFO_PTR;
  432. /** Set extra information pointer of spi info */
  433. #define DEV_SPI_INFO_SET_EXTRA_OBJECT(spi_info_ptr, extra_info) (spi_info_ptr)->extra = (void *)(extra_info)
  434. /** Get extra information pointer of spi info */
  435. #define DEV_SPI_INFO_GET_EXTRA_OBJECT(spi_info_ptr) ((spi_info_ptr)->extra)
  436. #define SPI_DFS_DEFAULT 8 /*!< Default spi data frame size */
  437. #define SPI_SLAVE_NOT_SELECTED (0xFF) /*!< Slave is not selected */
  438. #define SPI_DUMMY_DEFAULT (0xFF) /*!< default dummy value for first open */
  439. /**
  440. * \brief spi device interface definition
  441. * \details define spi device interface, like spi information structure,
  442. * fuctions to get spi info, open/close/control spi, send/receive data by spi
  443. * \note all this details are implemented by user in user porting code
  444. */
  445. typedef struct dev_spi {
  446. DEV_SPI_INFO spi_info; /*!< spi device information */
  447. int32_t (*spi_open) (uint32_t mode, uint32_t param); /*!< open spi device in master/slave mode, \
  448. when in master mode, param stands for frequency, \
  449. when in slave mode, param stands for clock mode */
  450. int32_t (*spi_close) (void); /*!< close spi device */
  451. int32_t (*spi_control) (uint32_t ctrl_cmd, void *param); /*!< control spi device */
  452. int32_t (*spi_write) (const void *data, uint32_t len); /*!< send data to spi device (blocking method) */
  453. int32_t (*spi_read) (void *data, uint32_t len); /*!< read data from spi device (blocking method) */
  454. } DEV_SPI, * DEV_SPI_PTR;
  455. /**
  456. * \fn int32_t (* dev_spi::spi_open) (uint32_t mode, uint32_t param)
  457. * \details open an spi device with selected mode (master or slave) with defined \ref param
  458. * \param[in] mode working mode (\ref DEV_MASTER_MODE "master" or \ref DEV_SLAVE_MODE "slave")
  459. * \param[in] param When mode is \ref DEV_MASTER_MODE, param stands for \ref dev_spi_info::freq "frequency",
  460. * when mode is \ref DEV_SLAVE_MODE, param stands for \ref dev_spi_info::clk_mode "slave clock mode"
  461. * \retval E_OK Open successfully without any issues
  462. * \retval E_OPNED If device was opened before with different parameters,
  463. * then just increase the \ref dev_spi_info::opn_cnt "opn_cnt" and return \ref E_OPNED
  464. * \retval E_OBJ Device object is not valid
  465. * \retval E_SYS Device is opened for different mode before, if you want to open it with different mode, you need to fully close it first.
  466. * \retval E_PAR Parameter is not valid
  467. * \retval E_NOSPT Open settings are not supported
  468. */
  469. /**
  470. * \fn int32_t (* dev_spi::spi_close) (void)
  471. * \details close an spi device, just decrease the \ref dev_spi_info::opn_cnt "opn_cnt",
  472. * if \ref dev_spi_info::opn_cnt "opn_cnt" equals 0, then close the device
  473. * \retval E_OK Close successfully without any issues(including scenario that device is already closed)
  474. * \retval E_OPNED Device is still opened, the device \ref dev_spi_info::opn_cnt "opn_cnt" decreased by 1
  475. * \retval E_OBJ Device object is not valid
  476. */
  477. /**
  478. * \fn int32_t (* dev_spi::spi_control) (uint32_t ctrl_cmd, void *param)
  479. * \details control an spi device by \ref ctrl_cmd, with passed \ref param.
  480. * you can control spi device using predefined spi control commands defined using \ref DEV_SET_SYSCMD
  481. * (which must be implemented by bsp developer), such as \ref SPI_CMD_MST_SET_FREQ "set spi master frequency",
  482. * \ref SPI_CMD_FLUSH_TX "flush tx" and \ref DEVICE_HAL_SPI_CTRLCMD "more".
  483. * And you can also control spi device using your own specified commands defined using \ref DEV_SET_USRCMD,
  484. * but these specified commands should be defined in your own spi device driver implementation.
  485. * \param[in] ctrl_cmd \ref DEVICE_HAL_SPI_CTRLCMD "control command", to change or get some thing related to spi
  486. * \param[in,out] param parameters that maybe argument of the command,
  487. * or return values of the command, must not be NULL
  488. * \retval E_OK Control device successfully
  489. * \retval E_CLSED Device is not opened
  490. * \retval E_OBJ Device object is not valid or not exists
  491. * \retval E_PAR Parameter is not valid for current control command
  492. * \retval E_SYS Control device failed, due to hardware issues, such as device is disabled
  493. * \retval E_CTX Control device failed, due to different reasons like in transfer state
  494. * \retval E_NOSPT Control command is not supported or not valid
  495. */
  496. /**
  497. * \fn int32_t (* dev_spi::spi_write) (const void *data, uint32_t len)
  498. * \details send \ref data through spi with defined \ref len to slave device .
  499. * \param[in] data pointer to data need to send by spi
  500. * \param[in] len length of data to be sent
  501. * \retval >0 Byte count that was successfully sent for poll method
  502. * \retval E_OBJ Device object is not valid or not exists
  503. * \retval E_PAR Parameter is not valid
  504. * \retval E_CTX Device is still in transfer state
  505. * \retval E_SYS Can't write data to hardware due to hardware issues, such as device is disabled
  506. */
  507. /**
  508. * \fn int32_t (* dev_spi::spi_read) (void *data, uint32_t len)
  509. * \details receive \ref data of defined \ref len through spi from slave device .
  510. * \param[out] data pointer to data need to received by spi
  511. * \param[in] len length of data to be received
  512. * \retval >0 Byte count that was successfully received for poll method
  513. * \retval E_OBJ Device object is not valid or not exists
  514. * \retval E_CTX Device is still in transfer state
  515. * \retval E_PAR Parameter is not valid
  516. * \retval E_SYS Can't receive data from hardware due to hardware issues, such as device is disabled
  517. */
  518. /** @} */
  519. #ifdef __cplusplus
  520. extern "C" {
  521. #endif
  522. /**
  523. * \brief get an \ref dev_spi "spi device" by spi device id.
  524. * For how to use spi device hal refer to \ref dev_spi "Functions in spi device structure"
  525. * \param[in] spi_id id of spi, defined by user
  526. * \retval !NULL pointer to an \ref dev_spi "spi device structure"
  527. * \retval NULL failed to find the spi device by \ref spi_id
  528. * \note need to implemented by user in user code
  529. */
  530. extern DEV_SPI_PTR spi_get_dev(int32_t spi_id);
  531. #ifdef __cplusplus
  532. }
  533. #endif
  534. /** @} */
  535. #endif /* _DEVICE_HAL_SPI_H_ */