app_twi.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. /* Copyright (c) 2015 Nordic Semiconductor. All Rights Reserved.
  2. *
  3. * The information contained herein is property of Nordic Semiconductor ASA.
  4. * Terms and conditions of usage are described in detail in NORDIC
  5. * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
  6. *
  7. * Licensees are granted free, non-transferable use of the information. NO
  8. * WARRANTY of ANY KIND is provided. This heading must NOT be removed from
  9. * the file.
  10. *
  11. */
  12. #ifndef APP_TWI_H__
  13. #define APP_TWI_H__
  14. #include <stdint.h>
  15. #include "nrf_drv_twi.h"
  16. #include "sdk_errors.h"
  17. /**
  18. * @defgroup app_twi TWI transaction manager
  19. * @{
  20. * @ingroup app_common
  21. *
  22. * @brief Module for scheduling TWI transactions.
  23. */
  24. /**
  25. * @brief Flag indicating that a given transfer should not be ended
  26. * with a stop condition.
  27. *
  28. * Use this flag when a stop condition is undesirable between two transfers,
  29. * for example, when the first transfer is a write that sets an address in the slave
  30. * device and the second one is a read that fetches certain data using this
  31. * address. In this case, the second transfer should follow directly after the
  32. * first transfer, with a repeated start condition instead of a stop and then
  33. * a new start condition.
  34. */
  35. #define APP_TWI_NO_STOP 0x01
  36. /**
  37. * @brief Macro for creating a write transfer.
  38. *
  39. * @param address Slave address.
  40. * @param[in] p_data Pointer to the data to be sent.
  41. * @param length Number of bytes to transfer.
  42. * @param flags Transfer flags (see @ref APP_TWI_NO_STOP).
  43. */
  44. #define APP_TWI_WRITE(address, p_data, length, flags) \
  45. APP_TWI_TRANSFER(APP_TWI_WRITE_OP(address), p_data, length, flags)
  46. /**
  47. * @brief Macro for creating a read transfer.
  48. *
  49. * @param address Slave address.
  50. * @param[in] p_data Pointer to the buffer where received data should be placed.
  51. * @param length Number of bytes to transfer.
  52. * @param flags Transfer flags (see @ref APP_TWI_NO_STOP).
  53. */
  54. #define APP_TWI_READ(address, p_data, length, flags) \
  55. APP_TWI_TRANSFER(APP_TWI_READ_OP(address), p_data, length, flags)
  56. /**
  57. * @brief Helper macro, should not be used directly.
  58. */
  59. #define APP_TWI_TRANSFER(_operation, _p_data, _length, _flags) \
  60. { \
  61. .p_data = (uint8_t *)(_p_data), \
  62. .length = _length, \
  63. .operation = _operation, \
  64. .flags = _flags \
  65. }
  66. /**
  67. * @brief Helper macro, should not be used directly.
  68. */
  69. #define APP_TWI_WRITE_OP(address) (((address) << 1) | 0)
  70. /**
  71. * @brief Helper macro, should not be used directly.
  72. */
  73. #define APP_TWI_READ_OP(address) (((address) << 1) | 1)
  74. /**
  75. * @brief Helper macro, should not be used directly.
  76. */
  77. #define APP_TWI_IS_READ_OP(operation) ((operation) & 1)
  78. /**
  79. * @brief Helper macro, should not be used directly.
  80. */
  81. #define APP_TWI_OP_ADDRESS(operation) ((operation) >> 1)
  82. /**
  83. * @brief TWI transaction callback prototype.
  84. *
  85. * @param result Result of operation (NRF_SUCCESS on success,
  86. * otherwise a relevant error code).
  87. * @param[in] p_user_data Pointer to user data defined in transaction
  88. * descriptor.
  89. */
  90. typedef void (* app_twi_callback_t)(ret_code_t result, void * p_user_data);
  91. /**
  92. * @brief TWI transfer descriptor.
  93. */
  94. typedef struct {
  95. uint8_t * p_data; ///< Pointer to the buffer holding the data.
  96. uint8_t length; ///< Number of bytes to transfer.
  97. uint8_t operation; ///< Device address combined with transfer direction.
  98. uint8_t flags; ///< Transfer flags (see @ref APP_TWI_NO_STOP).
  99. } app_twi_transfer_t;
  100. /**
  101. * @brief TWI transaction descriptor.
  102. */
  103. typedef struct {
  104. app_twi_callback_t callback;
  105. ///< User-specified function to be called after the transaction is finished.
  106. void * p_user_data;
  107. ///< Pointer to user data to be passed to the callback.
  108. app_twi_transfer_t const * p_transfers;
  109. ///< Pointer to the array of transfers that make up the transaction.
  110. uint8_t number_of_transfers;
  111. ///< Number of transfers that make up the transaction.
  112. } app_twi_transaction_t;
  113. /**
  114. * @brief TWI transaction queue.
  115. */
  116. typedef struct {
  117. app_twi_transaction_t const * volatile * p_buffer;
  118. uint8_t size;
  119. uint8_t volatile read_idx;
  120. uint8_t volatile write_idx;
  121. } app_twi_queue_t;
  122. /**
  123. * @brief TWI transaction manager instance.
  124. */
  125. typedef struct {
  126. app_twi_queue_t queue;
  127. ///< Transaction queue.
  128. uint8_t volatile current_transfer_idx;
  129. ///< Index of currently performed transfer (within current transaction).
  130. bool volatile internal_transaction_in_progress;
  131. ///< Informs that an internal transaction is being performed (by app_twi_perform()).
  132. uint8_t volatile internal_transaction_result;
  133. ///< Used to pass the result of the internal transaction realized by app_twi_perform().
  134. app_twi_transaction_t const * volatile p_current_transaction;
  135. ///< Currently realized transaction.
  136. nrf_drv_twi_t const twi;
  137. ///< TWI master driver instance.
  138. } app_twi_t;
  139. /**
  140. * @brief Macro for creating an instance of the TWI transaction manager.
  141. *
  142. * @param[in] twi_idx Index of the TWI master driver instance to be utilized
  143. * by this manager instance.
  144. */
  145. #define APP_TWI_INSTANCE(twi_idx) \
  146. { \
  147. .twi = NRF_DRV_TWI_INSTANCE(twi_idx) \
  148. }
  149. /**
  150. * @brief Macro that simplifies the initialization of a TWI transaction manager
  151. * instance.
  152. *
  153. * This macro allocates a static buffer for the transaction queue.
  154. * Therefore, it should be used in only one place in the code for a given
  155. * instance.
  156. *
  157. * @param[in] p_app_twi Pointer to the instance to be initialized.
  158. * @param[in] p_twi_config Pointer to the TWI master driver configuration.
  159. * @param queue_size Size of the transaction queue (maximum number
  160. * of pending transactions).
  161. * See @ref app_twi_init_note "this note".
  162. * @param[out] err_code The result of the app_twi_init() function call
  163. * is written to this parameter.
  164. */
  165. #define APP_TWI_INIT(p_app_twi, p_twi_config, queue_size, err_code) \
  166. do { \
  167. static app_twi_transaction_t const * queue_buffer[queue_size + 1]; \
  168. err_code = app_twi_init(p_app_twi, p_twi_config, \
  169. queue_size, queue_buffer); \
  170. } while (0)
  171. /**
  172. * @brief Function for initializing a TWI transaction manager instance.
  173. *
  174. * This function initializes the utilized TWI master driver instance and
  175. * prepares the transaction queue.
  176. *
  177. * @anchor app_twi_init_note
  178. * @note The queue size is the maximum number of pending transactions
  179. * not counting the one that is currently realized. This means that
  180. * for an empty queue with size of, for example, 4 elements, it is
  181. * possible to schedule up to 5 transactions.
  182. *
  183. * @param[in] p_app_twi Pointer to the instance to be initialized.
  184. * @param[in] p_twi_config Pointer to the TWI master driver configuration.
  185. * @param queue_size Size of the transaction queue (maximum number
  186. * of pending transactions).
  187. * @param[in] p_queue_buffer Pointer to a buffer for queued transactions
  188. * storage. Due to the queue implementation, the buffer must
  189. * be big enough to hold queue_size + 1 entries
  190. * (pointers to transaction descriptors).
  191. *
  192. * @retval NRF_SUCCESS If initialization was successful. Otherwise, the error code
  193. * returned by the nrf_drv_twi_init() function is returned.
  194. */
  195. ret_code_t app_twi_init(app_twi_t * p_app_twi,
  196. nrf_drv_twi_config_t const * p_twi_config,
  197. uint8_t queue_size,
  198. app_twi_transaction_t const * * p_queue_buffer);
  199. /**
  200. * @brief Function for uninitializing a TWI transaction manager instance.
  201. *
  202. * @param[in] p_app_twi Pointer to the instance to be uninitialized.
  203. */
  204. void app_twi_uninit(app_twi_t * p_app_twi);
  205. /**
  206. * @brief Function for scheduling a TWI transaction.
  207. *
  208. * The transaction is enqueued and started as soon as the TWI bus is
  209. * available, thus when all previously scheduled transactions have been
  210. * finished (possibly immediately).
  211. *
  212. * @param[in] p_app_twi Pointer to the TWI transaction manager instance.
  213. * @param[in] p_transaction Pointer to the descriptor of the transaction to be
  214. * scheduled.
  215. *
  216. * @retval NRF_SUCCESS If the transaction has been successfully scheduled.
  217. * @retval NRF_ERROR_BUSY If the limit of pending transactions has been reached
  218. * (the transaction queue is full).
  219. */
  220. ret_code_t app_twi_schedule(app_twi_t * p_app_twi,
  221. app_twi_transaction_t const * p_transaction);
  222. /**
  223. * @brief Function for scheduling a transaction and waiting until it is finished.
  224. *
  225. * This function schedules a transaction that consists of one or more transfers
  226. * and waits until it is finished.
  227. *
  228. * @param[in] p_app_twi Pointer to the TWI transaction manager instance.
  229. * @param[in] p_transfers Pointer to an array of transfers to be performed.
  230. * @param number_of_transfers Number of transfers to be performed.
  231. * @param user_function User-specified function to be called while
  232. * waiting. NULL if such functionality
  233. * is not needed.
  234. *
  235. * @retval NRF_SUCCESS If the transfers have been successfully realized.
  236. * @retval NRF_ERROR_BUSY If some transfers are already performed (if this function
  237. * was called from another context).
  238. * @retval - Other error codes mean that the transaction has ended
  239. * with the error that is specified in the error code.
  240. */
  241. ret_code_t app_twi_perform(app_twi_t * p_app_twi,
  242. app_twi_transfer_t const * p_transfers,
  243. uint8_t number_of_transfers,
  244. void (* user_function)(void));
  245. /**
  246. * @brief Function for getting the current state of a TWI transaction manager
  247. * instance.
  248. *
  249. * @param[in] p_app_twi Pointer to the TWI transaction manager instance.
  250. *
  251. * @retval true If all scheduled transactions have been finished.
  252. * @retval false Otherwise.
  253. */
  254. __STATIC_INLINE bool app_twi_is_idle(app_twi_t * p_app_twi)
  255. {
  256. return (p_app_twi->p_current_transaction == NULL);
  257. }
  258. /**
  259. *@}
  260. **/
  261. #endif // APP_TWI_H__