twi_sw_master.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519
  1. /**
  2. * Copyright (c) 2009 - 2020, Nordic Semiconductor ASA
  3. *
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without modification,
  7. * are permitted provided that the following conditions are met:
  8. *
  9. * 1. Redistributions of source code must retain the above copyright notice, this
  10. * list of conditions and the following disclaimer.
  11. *
  12. * 2. Redistributions in binary form, except as embedded into a Nordic
  13. * Semiconductor ASA integrated circuit in a product or a software update for
  14. * such product, must reproduce the above copyright notice, this list of
  15. * conditions and the following disclaimer in the documentation and/or other
  16. * materials provided with the distribution.
  17. *
  18. * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
  19. * contributors may be used to endorse or promote products derived from this
  20. * software without specific prior written permission.
  21. *
  22. * 4. This software, with or without modification, must only be used with a
  23. * Nordic Semiconductor ASA integrated circuit.
  24. *
  25. * 5. Any software provided in binary form under this license must not be reverse
  26. * engineered, decompiled, modified and/or disassembled.
  27. *
  28. * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
  29. * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  30. * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
  31. * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
  32. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  33. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
  34. * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  35. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  36. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  37. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  38. *
  39. */
  40. #include <stdbool.h>
  41. #include <stdint.h>
  42. #include "twi_master.h"
  43. #include "nrf_delay.h"
  44. #include "twi_master_config.h"
  45. /*lint -e415 -e845 -save "Out of bounds access" */
  46. #define TWI_SDA_STANDARD0_NODRIVE1() do { \
  47. NRF_GPIO->PIN_CNF[TWI_MASTER_CONFIG_DATA_PIN_NUMBER] = (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos) \
  48. |(GPIO_PIN_CNF_DRIVE_S0D1 << GPIO_PIN_CNF_DRIVE_Pos) \
  49. |(GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos) \
  50. |(GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) \
  51. |(GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos); \
  52. } while (0) /*!< Configures SDA pin to Standard-0, No-drive 1 */
  53. #define TWI_SCL_STANDARD0_NODRIVE1() do { \
  54. NRF_GPIO->PIN_CNF[TWI_MASTER_CONFIG_CLOCK_PIN_NUMBER] = (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos) \
  55. |(GPIO_PIN_CNF_DRIVE_S0D1 << GPIO_PIN_CNF_DRIVE_Pos) \
  56. |(GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos) \
  57. |(GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) \
  58. |(GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos); \
  59. } while (0) /*!< Configures SCL pin to Standard-0, No-drive 1 */
  60. /*lint -restore */
  61. #ifndef TWI_MASTER_TIMEOUT_COUNTER_LOAD_VALUE
  62. #define TWI_MASTER_TIMEOUT_COUNTER_LOAD_VALUE (0UL) //!< Unit is number of empty loops. Timeout for SMBus devices is 35 ms. Set to zero to disable slave timeout altogether.
  63. #endif
  64. static bool twi_master_clear_bus(void);
  65. static bool twi_master_issue_startcondition(void);
  66. static bool twi_master_issue_stopcondition(void);
  67. static bool twi_master_clock_byte(uint_fast8_t databyte);
  68. static bool twi_master_clock_byte_in(uint8_t * databyte, bool ack);
  69. static bool twi_master_wait_while_scl_low(void);
  70. bool twi_master_init(void)
  71. {
  72. // Configure both pins to output Standard 0, No-drive (open-drain) 1
  73. TWI_SDA_STANDARD0_NODRIVE1(); /*lint !e416 "Creation of out of bounds pointer" */
  74. TWI_SCL_STANDARD0_NODRIVE1(); /*lint !e416 "Creation of out of bounds pointer" */
  75. // Configure SCL as output
  76. TWI_SCL_HIGH();
  77. TWI_SCL_OUTPUT();
  78. // Configure SDA as output
  79. TWI_SDA_HIGH();
  80. TWI_SDA_OUTPUT();
  81. return twi_master_clear_bus();
  82. }
  83. bool twi_master_transfer(uint8_t address, uint8_t * data, uint8_t data_length, bool issue_stop_condition)
  84. {
  85. bool transfer_succeeded = true;
  86. transfer_succeeded &= twi_master_issue_startcondition();
  87. transfer_succeeded &= twi_master_clock_byte(address);
  88. if (address & TWI_READ_BIT)
  89. {
  90. /* Transfer direction is from Slave to Master */
  91. while (data_length-- && transfer_succeeded)
  92. {
  93. // To indicate to slave that we've finished transferring last data byte
  94. // we need to NACK the last transfer.
  95. if (data_length == 0)
  96. {
  97. transfer_succeeded &= twi_master_clock_byte_in(data, (bool)false);
  98. }
  99. else
  100. {
  101. transfer_succeeded &= twi_master_clock_byte_in(data, (bool)true);
  102. }
  103. data++;
  104. }
  105. }
  106. else
  107. {
  108. /* Transfer direction is from Master to Slave */
  109. while (data_length-- && transfer_succeeded)
  110. {
  111. transfer_succeeded &= twi_master_clock_byte(*data);
  112. data++;
  113. }
  114. }
  115. if (issue_stop_condition || !transfer_succeeded)
  116. {
  117. transfer_succeeded &= twi_master_issue_stopcondition();
  118. }
  119. return transfer_succeeded;
  120. }
  121. /**
  122. * @brief Function for detecting stuck slaves and tries to clear the bus.
  123. *
  124. * @return
  125. * @retval false Bus is stuck.
  126. * @retval true Bus is clear.
  127. */
  128. static bool twi_master_clear_bus(void)
  129. {
  130. bool bus_clear;
  131. TWI_SDA_HIGH();
  132. TWI_SCL_HIGH();
  133. TWI_DELAY();
  134. if (TWI_SDA_READ() == 1 && TWI_SCL_READ() == 1)
  135. {
  136. bus_clear = true;
  137. }
  138. else if (TWI_SCL_READ() == 1)
  139. {
  140. bus_clear = false;
  141. // Clock max 18 pulses worst case scenario(9 for master to send the rest of command and 9 for slave to respond) to SCL line and wait for SDA come high
  142. for (uint_fast8_t i = 18; i--;)
  143. {
  144. TWI_SCL_LOW();
  145. TWI_DELAY();
  146. TWI_SCL_HIGH();
  147. TWI_DELAY();
  148. if (TWI_SDA_READ() == 1)
  149. {
  150. bus_clear = true;
  151. break;
  152. }
  153. }
  154. }
  155. else
  156. {
  157. bus_clear = false;
  158. }
  159. return bus_clear;
  160. }
  161. /**
  162. * @brief Function for issuing TWI START condition to the bus.
  163. *
  164. * START condition is signaled by pulling SDA low while SCL is high. After this function SCL and SDA will be low.
  165. *
  166. * @return
  167. * @retval false Timeout detected
  168. * @retval true Clocking succeeded
  169. */
  170. static bool twi_master_issue_startcondition(void)
  171. {
  172. #if 0
  173. if (TWI_SCL_READ() == 1 && TWI_SDA_READ() == 1)
  174. {
  175. // Pull SDA low
  176. TWI_SDA_LOW();
  177. }
  178. else if (TWI_SCL_READ() == 1 && TWI_SDA_READ() == 0)
  179. {
  180. // Issue Stop by pulling SDA high
  181. TWI_SDA_HIGH();
  182. TWI_DELAY();
  183. // Then Start by pulling SDA low
  184. TWI_SDA_LOW();
  185. }
  186. else if (TWI_SCL_READ() == 0 && TWI_SDA_READ() == 0)
  187. {
  188. // First pull SDA high
  189. TWI_SDA_HIGH();
  190. // Then SCL high
  191. if (!twi_master_wait_while_scl_low())
  192. {
  193. return false;
  194. }
  195. // Then SDA low
  196. TWI_SDA_LOW();
  197. }
  198. else if (TWI_SCL_READ() == 0 && TWI_SDA_READ() == 1)
  199. {
  200. // SCL high
  201. if (!twi_master_wait_while_scl_low())
  202. {
  203. return false;
  204. }
  205. // Then SDA low
  206. TWI_SDA_LOW();
  207. }
  208. TWI_DELAY();
  209. TWI_SCL_LOW();
  210. #endif
  211. // Make sure both SDA and SCL are high before pulling SDA low.
  212. TWI_SDA_HIGH();
  213. TWI_DELAY();
  214. if (!twi_master_wait_while_scl_low())
  215. {
  216. return false;
  217. }
  218. TWI_SDA_LOW();
  219. TWI_DELAY();
  220. // Other module function expect SCL to be low
  221. TWI_SCL_LOW();
  222. TWI_DELAY();
  223. return true;
  224. }
  225. /**
  226. * @brief Function for issuing TWI STOP condition to the bus.
  227. *
  228. * STOP condition is signaled by pulling SDA high while SCL is high. After this function SDA and SCL will be high.
  229. *
  230. * @return
  231. * @retval false Timeout detected
  232. * @retval true Clocking succeeded
  233. */
  234. static bool twi_master_issue_stopcondition(void)
  235. {
  236. #if 0
  237. if (TWI_SCL_READ() == 1 && TWI_SDA_READ() == 1)
  238. {
  239. // Issue start, then issue stop
  240. // Pull SDA low to issue START
  241. TWI_SDA_LOW();
  242. TWI_DELAY();
  243. // Pull SDA high while SCL is high to issue STOP
  244. TWI_SDA_HIGH();
  245. }
  246. else if (TWI_SCL_READ() == 1 && TWI_SDA_READ() == 0)
  247. {
  248. // Pull SDA high while SCL is high to issue STOP
  249. TWI_SDA_HIGH();
  250. }
  251. else if (TWI_SCL_READ() == 0 && TWI_SDA_READ() == 0)
  252. {
  253. if (!twi_master_wait_while_scl_low())
  254. {
  255. return false;
  256. }
  257. // Pull SDA high while SCL is high to issue STOP
  258. TWI_SDA_HIGH();
  259. }
  260. else if (TWI_SCL_READ() == 0 && TWI_SDA_READ() == 1)
  261. {
  262. TWI_SDA_LOW();
  263. TWI_DELAY();
  264. // SCL high
  265. if (!twi_master_wait_while_scl_low())
  266. {
  267. return false;
  268. }
  269. // Pull SDA high while SCL is high to issue STOP
  270. TWI_SDA_HIGH();
  271. }
  272. TWI_DELAY();
  273. #endif
  274. TWI_SDA_LOW();
  275. TWI_DELAY();
  276. if (!twi_master_wait_while_scl_low())
  277. {
  278. return false;
  279. }
  280. TWI_SDA_HIGH();
  281. TWI_DELAY();
  282. return true;
  283. }
  284. /**
  285. * @brief Function for clocking one data byte out and reads slave acknowledgment.
  286. *
  287. * Can handle clock stretching.
  288. * After calling this function SCL is low and SDA low/high depending on the
  289. * value of LSB of the data byte.
  290. * SCL is expected to be output and low when entering this function.
  291. *
  292. * @param databyte Data byte to clock out.
  293. * @return
  294. * @retval true Slave acknowledged byte.
  295. * @retval false Timeout or slave didn't acknowledge byte.
  296. */
  297. static bool twi_master_clock_byte(uint_fast8_t databyte)
  298. {
  299. bool transfer_succeeded = true;
  300. /** @snippet [TWI SW master write] */
  301. // Make sure SDA is an output
  302. TWI_SDA_OUTPUT();
  303. // MSB first
  304. for (uint_fast8_t i = 0x80; i != 0; i >>= 1)
  305. {
  306. TWI_SCL_LOW();
  307. TWI_DELAY();
  308. if (databyte & i)
  309. {
  310. TWI_SDA_HIGH();
  311. }
  312. else
  313. {
  314. TWI_SDA_LOW();
  315. }
  316. if (!twi_master_wait_while_scl_low())
  317. {
  318. transfer_succeeded = false; // Timeout
  319. break;
  320. }
  321. }
  322. // Finish last data bit by pulling SCL low
  323. TWI_SCL_LOW();
  324. TWI_DELAY();
  325. /** @snippet [TWI SW master write] */
  326. // Configure TWI_SDA pin as input for receiving the ACK bit
  327. TWI_SDA_INPUT();
  328. // Give some time for the slave to load the ACK bit on the line
  329. TWI_DELAY();
  330. // Pull SCL high and wait a moment for SDA line to settle
  331. // Make sure slave is not stretching the clock
  332. transfer_succeeded &= twi_master_wait_while_scl_low();
  333. // Read ACK/NACK. NACK == 1, ACK == 0
  334. transfer_succeeded &= !(TWI_SDA_READ());
  335. // Finish ACK/NACK bit clock cycle and give slave a moment to release control
  336. // of the SDA line
  337. TWI_SCL_LOW();
  338. TWI_DELAY();
  339. // Configure TWI_SDA pin as output as other module functions expect that
  340. TWI_SDA_OUTPUT();
  341. return transfer_succeeded;
  342. }
  343. /**
  344. * @brief Function for clocking one data byte in and sends ACK/NACK bit.
  345. *
  346. * Can handle clock stretching.
  347. * SCL is expected to be output and low when entering this function.
  348. * After calling this function, SCL is high and SDA low/high depending if ACK/NACK was sent.
  349. *
  350. * @param databyte Data byte to clock out.
  351. * @param ack If true, send ACK. Otherwise send NACK.
  352. * @return
  353. * @retval true Byte read succesfully
  354. * @retval false Timeout detected
  355. */
  356. static bool twi_master_clock_byte_in(uint8_t *databyte, bool ack)
  357. {
  358. uint_fast8_t byte_read = 0;
  359. bool transfer_succeeded = true;
  360. /** @snippet [TWI SW master read] */
  361. // Make sure SDA is an input
  362. TWI_SDA_INPUT();
  363. // SCL state is guaranteed to be high here
  364. // MSB first
  365. for (uint_fast8_t i = 0x80; i != 0; i >>= 1)
  366. {
  367. if (!twi_master_wait_while_scl_low())
  368. {
  369. transfer_succeeded = false;
  370. break;
  371. }
  372. if (TWI_SDA_READ())
  373. {
  374. byte_read |= i;
  375. }
  376. else
  377. {
  378. // No need to do anything
  379. }
  380. TWI_SCL_LOW();
  381. TWI_DELAY();
  382. }
  383. // Make sure SDA is an output before we exit the function
  384. TWI_SDA_OUTPUT();
  385. /** @snippet [TWI SW master read] */
  386. *databyte = (uint8_t)byte_read;
  387. // Send ACK bit
  388. // SDA high == NACK, SDA low == ACK
  389. if (ack)
  390. {
  391. TWI_SDA_LOW();
  392. }
  393. else
  394. {
  395. TWI_SDA_HIGH();
  396. }
  397. // Let SDA line settle for a moment
  398. TWI_DELAY();
  399. // Drive SCL high to start ACK/NACK bit transfer
  400. // Wait until SCL is high, or timeout occurs
  401. if (!twi_master_wait_while_scl_low())
  402. {
  403. transfer_succeeded = false; // Timeout
  404. }
  405. // Finish ACK/NACK bit clock cycle and give slave a moment to react
  406. TWI_SCL_LOW();
  407. TWI_DELAY();
  408. return transfer_succeeded;
  409. }
  410. /**
  411. * @brief Function for pulling SCL high and waits until it is high or timeout occurs.
  412. *
  413. * SCL is expected to be output before entering this function.
  414. * @note If TWI_MASTER_TIMEOUT_COUNTER_LOAD_VALUE is set to zero, timeout functionality is not compiled in.
  415. * @return
  416. * @retval true SCL is now high.
  417. * @retval false Timeout occurred and SCL is still low.
  418. */
  419. static bool twi_master_wait_while_scl_low(void)
  420. {
  421. #if TWI_MASTER_TIMEOUT_COUNTER_LOAD_VALUE != 0
  422. uint32_t volatile timeout_counter = TWI_MASTER_TIMEOUT_COUNTER_LOAD_VALUE;
  423. #endif
  424. // Pull SCL high just in case if something left it low
  425. TWI_SCL_HIGH();
  426. TWI_DELAY();
  427. while (TWI_SCL_READ() == 0)
  428. {
  429. // If SCL is low, one of the slaves is busy and we must wait
  430. #if TWI_MASTER_TIMEOUT_COUNTER_LOAD_VALUE != 0
  431. if (timeout_counter-- == 0)
  432. {
  433. // If timeout_detected, return false
  434. return false;
  435. }
  436. #endif
  437. }
  438. return true;
  439. }
  440. /*lint --flb "Leave library region" */