hal_i2cslave.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423
  1. /*
  2. ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
  3. 2011,2012,2013 Giovanni Di Sirio.
  4. This file is part of ChibiOS/RT.
  5. ChibiOS/RT is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 3 of the License, or
  8. (at your option) any later version.
  9. ChibiOS/RT is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. ---
  16. A special exception to the GPL can be applied should you wish to distribute
  17. a combined work that includes ChibiOS/RT, without being obliged to provide
  18. the source code for any proprietary components. See the file exception.txt
  19. for full details of how and when the exception can be applied.
  20. */
  21. /*
  22. Slave I2C support contributed by Brent Roman of the
  23. Monterey Bay Aquarium Research Institute
  24. */
  25. /**
  26. * @file i2cslave.h
  27. * @brief Slave Mode for the I2C Driver.
  28. *
  29. * @addtogroup I2C
  30. * @{
  31. */
  32. #ifndef _I2CSLAVE_H_
  33. #define _I2CSLAVE_H_
  34. #if HAL_USE_I2C_SLAVE || defined(__DOXYGEN__)
  35. #include <hal_i2c.h>
  36. #ifdef __cplusplus
  37. extern "C" {
  38. #endif
  39. /**
  40. * @brief Configure to respond to messages directed to the given i2cadr
  41. *
  42. * @param[in] i2cp pointer to the @p I2CDriver object
  43. * @param[in] i2cadr I2C bus address
  44. * - @a 0 matches "all call"
  45. * .
  46. * @return Length of message OR the type of event received
  47. * @retval I2C_OK Success
  48. * @retval I2C_ERROR Cannot match address in addition of those already
  49. *
  50. * @details MatchAddress calls are cumulative.
  51. * Specify address zero to match I2C "all call"
  52. * Most hardware supports matching only a signle nonzero address.
  53. *
  54. * @api
  55. */
  56. int i2cMatchAddress(I2CDriver *i2cp, i2caddr_t i2cadr);
  57. /**
  58. * @brief Configure to ignore messages directed to the given i2cadr
  59. *
  60. * @param[in] i2cp pointer to the @p I2CDriver object
  61. * @param[in] i2cadr I2C bus address
  62. * - @a 0 matches "all call"
  63. * .
  64. * @details A message being transferred that has already matched the
  65. * specified address will continue being processed.
  66. * Requests to unmatch an address that is not currently being matched
  67. * are ignored.
  68. *
  69. * @api
  70. */
  71. void i2cUnmatchAddress(I2CDriver *i2cp, i2caddr_t i2cadr);
  72. /**
  73. * @brief Configure to ignore all messages
  74. *
  75. * @param[in] i2cp pointer to the @p I2CDriver object
  76. *
  77. * @details A message being transferred that has already matched the
  78. * specified address will continue being processed.
  79. *
  80. * @api
  81. */
  82. void i2cUnmatchAll(I2CDriver *i2cp);
  83. /**
  84. * @brief Configure to respond to messages directed to the given i2cadr
  85. *
  86. * @param[in] i2cp pointer to the @p I2CDriver object
  87. * @param[in] i2cadr I2C bus address
  88. * - @a 0 matches "all call"
  89. * .
  90. * @return non-zero implies failure.
  91. *
  92. * @details Identical to i2cMatchAddress(), but called from interrupt context
  93. *
  94. * @api
  95. */
  96. static inline msg_t
  97. i2cMatchAddressI(I2CDriver *i2cp, i2caddr_t i2cadr)
  98. {
  99. osalDbgCheck(i2cp != NULL);
  100. return i2c_lld_matchAddress(i2cp, i2cadr);
  101. }
  102. /**
  103. * @brief Configure to ignore messages directed to the given i2cadr
  104. *
  105. * @param[in] i2cp pointer to the @p I2CDriver object
  106. * @param[in] i2cadr I2C bus address
  107. * - @a 0 matches "all call"
  108. * .
  109. * @details Identical to i2cUnmatchAddress(), but called from interrupt context
  110. *
  111. * @api
  112. */
  113. static inline void
  114. i2cUnmatchAddressI(I2CDriver *i2cp, i2caddr_t i2cadr)
  115. {
  116. osalDbgCheck(i2cp != NULL);
  117. i2c_lld_unmatchAddress(i2cp, i2cadr);
  118. }
  119. /**
  120. * @brief Configure to ignore all messages
  121. *
  122. * @param[in] i2cp pointer to the @p I2CDriver object
  123. *
  124. * @details Identical to i2cUnmatchAll(), but called from interrupt context
  125. *
  126. * @api
  127. */
  128. static inline void
  129. i2cUnmatchAllI(I2CDriver *i2cp)
  130. /*
  131. Notes:
  132. Must be called from interrupt context
  133. Does not affect the processing of any message currently being received
  134. */
  135. {
  136. osalDbgCheck(i2cp != NULL);
  137. i2c_lld_unmatchAll(i2cp);
  138. }
  139. /* I2C Bus activity timeout configuration */
  140. /**
  141. * @brief return maximum number of ticks a slave bus transaction may last
  142. *
  143. * @param[in] i2cp pointer to the @p I2CDriver object
  144. *
  145. * @return maximum number of ticks a slave bus transaction my last
  146. *
  147. * @details initialized to TIME_INFINITE (disabling slave mode bus timeouts)
  148. *
  149. * @api
  150. */
  151. static inline
  152. systime_t i2cSlaveTimeout(I2CDriver *i2cp)
  153. {
  154. osalDbgCheck(i2cp != NULL);
  155. return i2c_lld_get_slaveTimeout(i2cp);
  156. }
  157. /**
  158. * @brief set the maximum number of ticks a slave bus transaction may last
  159. *
  160. * @param[in] i2cp pointer to the @p I2CDriver object
  161. * @param[in] ticks maximum number of ticks a slave bus transaction my last
  162. * - @a TIME_INFINITE disables slave mode bus timeouts
  163. * - @a TIME_IMMEDIATE is invalid
  164. * .
  165. *
  166. * @api
  167. */
  168. static inline
  169. void i2cSlaveSetTimeout(I2CDriver *i2cp, systime_t ticks)
  170. {
  171. osalDbgCheck(i2cp != NULL && ticks != TIME_IMMEDIATE);
  172. i2c_lld_set_slaveTimeout(i2cp, ticks);
  173. }
  174. /* bus transaction attributes */
  175. /**
  176. * @brief return bit mask of errors associated with this slave transaction
  177. *
  178. * @param[in] i2cp pointer to the @p I2CDriver object
  179. *
  180. * @return I2C bus error conditions described in i2c.h
  181. *
  182. * @api
  183. */
  184. static inline
  185. i2cflags_t i2cSlaveErrors(I2CDriver *i2cp)
  186. {
  187. osalDbgCheck(i2cp != NULL);
  188. return i2c_lld_get_slaveErrors(i2cp);
  189. }
  190. /**
  191. * @brief return number of bytes transferred during this slave transaction
  192. *
  193. * @param[in] i2cp pointer to the @p I2CDriver object
  194. *
  195. * @return number of bytes actually transferred on the bus
  196. *
  197. * @api
  198. */
  199. static inline
  200. size_t i2cSlaveBytes(I2CDriver *i2cp)
  201. {
  202. osalDbgCheck(i2cp != NULL);
  203. return i2c_lld_get_slaveBytes(i2cp);
  204. }
  205. /**
  206. * @brief return i2c address to which this message was targetted
  207. *
  208. * @param[in] i2cp pointer to the @p I2CDriver object
  209. *
  210. * @return i2c address to which this message was targetted
  211. *
  212. * @details The address returns will be one of those
  213. * specified earlier as an argument to i2cMatchAddress()
  214. *
  215. * @api
  216. */
  217. static inline
  218. i2caddr_t i2cSlaveTargetAdr(I2CDriver *i2cp)
  219. {
  220. osalDbgCheck(i2cp != NULL);
  221. return i2c_lld_get_slaveTargetAdr(i2cp);
  222. }
  223. /*
  224. An event service thread based API library called i2cevent supports processing
  225. slave messages on a dedicated thread. This facility is built upon the
  226. low-level driver's asynchronous callback functions described below:
  227. Each callback function may alter the processing of subsequent I2C
  228. messages and read requests by calling i2cSlaveReceive() and
  229. i2cSlaveReply(), respectively. Further, callbacks may alter their
  230. i2cSlaveMsg structs in RAM, but only those for their own channel.
  231. Such changes take immediate affect. This facility can be used to
  232. avoid copying message buffers.
  233. If receive buffers become full or a reply to a read request cannot be
  234. generated immediately, the relevant I2CSlaveMsg struct may be substituted
  235. for another whose body pointer is NULL or whose body size is zero.
  236. Note that, I2CSlaveMsg structs may be modified
  237. in place within a channel's callbacks to the same effect.
  238. A NULL body pointer or zero size causes the slave to signal the master node
  239. to wait by holding the I2C clock signal low, "stretching it", during the next
  240. transaction to which that I2CSlaveMsg applies.
  241. The I2C clock resumes only after a i2cSlaveSetReceive() or SetReply() is
  242. called with an I2CSlaveMsg containing a non-NULL body,
  243. or after the transaction timeout expires.
  244. Therefore, if a NULL body pointer is replaced with a non-NULL one or
  245. a zero length is replaced with a non-zero one, i2cSlaveReceive() or
  246. i2cSlaveReply() MUST be called -- even if with the same pointer values --
  247. to inform the i2c driver that the transaction may resume.
  248. Note that Receive and Reply processing is initially "locked".
  249. */
  250. /**
  251. * @brief Configure callbacks & buffers for message reception & query reply
  252. *
  253. * @param[in] i2cp pointer to the @p I2CDriver object
  254. * @param[in] rxMsg @p I2CSlaveMsg struct for processing subsequent messages
  255. * @param[in] replyMsg @p I2CSlaveMsg struct for processing subsequent queries
  256. *
  257. * @details Must be called from a thread
  258. * Call i2cMatchAddress() after this to start processing
  259. * Enabling match addresses before installing handler callbacks can
  260. * result in locking the I2C bus when a master accesses those
  261. * unconfigured slave addresses
  262. *
  263. * @api
  264. */
  265. void i2cSlaveConfigure(I2CDriver *i2cp,
  266. const I2CSlaveMsg *rxMsg, const I2CSlaveMsg *replyMsg);
  267. /**
  268. * @brief Configure callbacks & buffers for message reception
  269. *
  270. * @param[in] i2cp pointer to the @p I2CDriver object
  271. * @param[in] rxMsg @p I2CSlaveMsg struct for processing subsequent messages
  272. * @param[in] replyMsg @p I2CSlaveMsg struct for processing subsequent queries
  273. *
  274. * @details Must be called from a thread
  275. * Call i2cMatchAddress() after this to start processing
  276. * Enabling match addresses before installing handler callbacks can
  277. * result in locking the I2C bus when a master accesses those
  278. * unconfigured slave addresses
  279. *
  280. * @api
  281. */
  282. void i2cSlaveReceive(I2CDriver *i2cp, const I2CSlaveMsg *rxMsg);
  283. /**
  284. * @brief return @p I2CSlaveMsg for processing received messages
  285. *
  286. * @param[in] i2cp pointer to the @p I2CDriver object
  287. * @returns @p I2CSlaveMsg struct for processing subsequent messages
  288. *
  289. * @api
  290. */
  291. static inline
  292. const I2CSlaveMsg *i2cSlaveReceiveMsg(I2CDriver *i2cp)
  293. {
  294. osalDbgCheck(i2cp != NULL);
  295. return i2c_lld_get_slaveReceive(i2cp);
  296. }
  297. /**
  298. * @brief Configure callbacks & buffers for query reply
  299. *
  300. * @param[in] i2cp pointer to the @p I2CDriver object
  301. * @param[in] replyMsg @p I2CSlaveMsg struct for processing subsequent queries
  302. *
  303. * @details Must be called from a thread
  304. * Call i2cMatchAddress() after this to start processing
  305. * Enabling match addresses before installing handler callbacks can
  306. * result in locking the I2C bus when a master accesses those
  307. * unconfigured slave addresses
  308. *
  309. * @api
  310. */
  311. void i2cSlaveReply(I2CDriver *i2cp, const I2CSlaveMsg *replyMsg);
  312. /**
  313. * @brief return @p I2CSlaveMsg for processing received messages
  314. *
  315. * @param[in] i2cp pointer to the @p I2CDriver object
  316. * @returns @p I2CSlaveMsg struct for processing subsequent messages
  317. *
  318. * @api
  319. */
  320. static inline
  321. const I2CSlaveMsg *i2cSlaveReplyMsg(I2CDriver *i2cp)
  322. /*
  323. processing descriptor for the next reply message
  324. */
  325. {
  326. osalDbgCheck(i2cp != NULL);
  327. return i2c_lld_get_slaveReply(i2cp);
  328. }
  329. /**
  330. * @brief Configure callbacks & buffers for message reception
  331. *
  332. * @param[in] i2cp pointer to the @p I2CDriver object
  333. * @param[in] rxMsg @p I2CSlaveMsg struct for processing subsequent messages
  334. *
  335. * @details Must be called from an interrupt context
  336. *
  337. * @api
  338. */
  339. static inline void
  340. i2cSlaveReceiveI(I2CDriver *i2cp, const I2CSlaveMsg *rxMsg)
  341. {
  342. osalDbgCheck(i2cp != NULL && rxMsg != NULL);
  343. i2c_lld_slaveReceive(i2cp, rxMsg);
  344. }
  345. /**
  346. * @brief Configure callbacks & buffers for query reply
  347. *
  348. * @param[in] i2cp pointer to the @p I2CDriver object
  349. * @param[in] replyMsg @p I2CSlaveMsg struct for processing subsequent messages
  350. *
  351. * @details Must be called from an interrupt context
  352. *
  353. * @api
  354. */
  355. static inline void
  356. i2cSlaveReplyI(I2CDriver *i2cp, const I2CSlaveMsg *replyMsg)
  357. /*
  358. Prepare to reply to I2C read requests from bus masters
  359. according to the replyMsg configuration.
  360. Notes:
  361. Must be called from interrupt context
  362. Does not affect the processing of any message reply being sent
  363. */
  364. {
  365. osalDbgCheck(i2cp != NULL && replyMsg != NULL);
  366. i2c_lld_slaveReply(i2cp, replyMsg);
  367. }
  368. #ifdef __cplusplus
  369. }
  370. #endif
  371. #endif /* HAL_USE_I2C_SLAVE */
  372. #endif /* _I2CSLAVE_H_ */