twibus_gpio.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544
  1. /*
  2. * Copyright (C) 2005-2007 by egnite Software GmbH. All rights reserved.
  3. * Copyright (C) 2012 Uwe Bonnes
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. *
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. * 3. Neither the name of the copyright holders nor the names of
  15. * contributors may be used to endorse or promote products derived
  16. * from this software without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  19. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  20. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  21. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  22. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  23. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  24. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  25. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  26. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  27. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  28. * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  29. * SUCH DAMAGE.
  30. *
  31. * For additional information see http://www.ethernut.de/
  32. *
  33. */
  34. /*!
  35. * \file dev/twibus_gpio.c
  36. * \brief Bit banging base on the GPIO API.
  37. *
  38. *
  39. */
  40. #include <cfg/os.h>
  41. #include <cfg/twi.h>
  42. #include <cfg/arch/gpio.h>
  43. #include <sys/heap.h>
  44. #include <sys/event.h>
  45. #include <sys/timer.h>
  46. #include <string.h>
  47. #include <dev/twif.h>
  48. #include <dev/gpio.h>
  49. #if defined(SDA_PORT) && defined(SDA_PIN) \
  50. && defined(SCL_PORT) && defined(SCL_PIN)
  51. #define SDA_INIT GpioPinConfigSet \
  52. (SDA_PORT, SDA_PIN, GPIO_CFG_OUTPUT | GPIO_CFG_MULTIDRIVE | GPIO_CFG_PULLUP)
  53. #define SCL_INIT GpioPinConfigSet \
  54. (SCL_PORT, SCL_PIN, GPIO_CFG_OUTPUT | GPIO_CFG_MULTIDRIVE | GPIO_CFG_PULLUP)
  55. #define SCL_HIGH GpioPinSetHigh(SCL_PORT, SCL_PIN)
  56. #define SCL_LOW GpioPinSetLow(SCL_PORT, SCL_PIN)
  57. #define SDA_HIGH GpioPinSetHigh(SDA_PORT, SDA_PIN)
  58. #define SDA_LOW GpioPinSetLow(SDA_PORT, SDA_PIN)
  59. #define SDA_STAT GpioPinGet(SDA_PORT, SDA_PIN)
  60. #define SCL_RELEASE GpioPinRelease(SCL_PORT, SCL_PIN)
  61. #define SCL_DRIVE GpioPinDrive(SCL_PORT, SCL_PIN)
  62. #define SDA_RELEASE GpioPinRelease(SDA_PORT, SDA_PIN)
  63. #define SDA_DRIVE GpioPinDrive(SDA_PORT, SDA_PIN)
  64. #else
  65. #define SDA_INIT
  66. #define SCL_INIT
  67. #define SCL_HIGH
  68. #define SCL_LOW
  69. #define SDA_HIGH
  70. #define SDA_LOW
  71. #define SDA_STAT 0
  72. #define SCL_RELEASE
  73. #define SCL_DRIVE
  74. #define SDA_RELEASE
  75. #define SDA_DRIVE
  76. #define TWI_GPIO_UNDEFINED
  77. #endif
  78. static int_fast8_t twibb_initialized;
  79. static uint_fast16_t delay_unit;
  80. static volatile int_fast8_t tw_mm_error;
  81. /*
  82. * Short delay.
  83. *
  84. * Our bit banging code relies on pull-up resistors. The I/O ports mimic
  85. * open collector outputs by switching to input mode for high level and
  86. * switching to output mode for low level. This is much slower than
  87. * switching an output between low to high. Thus we need some delay.
  88. */
  89. static void TwDelay(int nops)
  90. {
  91. NutMicroDelay(nops * delay_unit);
  92. }
  93. /*
  94. * Falling edge on the data line while the clock line is high indicates
  95. * a start condition.
  96. *
  97. * Entry: SCL any, SDA any
  98. * Exit: SCL low, SDA low
  99. */
  100. static void TwStart(void)
  101. {
  102. SDA_RELEASE; SDA_HIGH;
  103. TwDelay(1);
  104. SCL_RELEASE; SCL_HIGH;
  105. TwDelay(1);
  106. SDA_LOW; SDA_DRIVE;
  107. TwDelay(1);
  108. SCL_LOW; SCL_DRIVE;
  109. TwDelay(1);
  110. }
  111. /*
  112. * Rising edge on the data line while the clock line is high indicates
  113. * a stop condition.
  114. *
  115. * Entry: SCL low, SDA any
  116. * Exit: SCL high, SDA high
  117. */
  118. static void TwStop(void)
  119. {
  120. SDA_LOW; SDA_DRIVE;
  121. TwDelay(1);
  122. SCL_RELEASE; SCL_HIGH;
  123. TwDelay(2);
  124. SDA_RELEASE; SDA_HIGH;
  125. TwDelay(8);
  126. }
  127. /*
  128. * Toggles out a single byte in master mode.
  129. *
  130. * Entry: SCL low, SDA any
  131. * Exit: SCL low, SDA high
  132. */
  133. static int TwPut(uint8_t octet)
  134. {
  135. int i;
  136. for (i = 0x80; i; i >>= 1) {
  137. /* Set the data bit. */
  138. if (octet & i) {
  139. SDA_RELEASE; SDA_HIGH;
  140. } else {
  141. SDA_LOW; SDA_DRIVE;
  142. }
  143. /* Wait for data to stabelize. */
  144. TwDelay(1);
  145. /* Toggle the clock. */
  146. SCL_RELEASE; SCL_HIGH;
  147. TwDelay(2);
  148. SCL_LOW; SCL_DRIVE;
  149. TwDelay(1);
  150. }
  151. /* Set data line high to receive the ACK bit. */
  152. SDA_RELEASE; SDA_HIGH;
  153. /* ACK should appear shortly after the clock's rising edge. */
  154. SCL_RELEASE; SCL_HIGH;
  155. TwDelay(2);
  156. if (SDA_STAT) {
  157. i = -1;
  158. } else {
  159. i = 0;
  160. }
  161. SCL_LOW; SCL_DRIVE;
  162. return i;
  163. }
  164. /*
  165. * Toggles in a single byte in master mode.
  166. *
  167. * Entry: SCL low, SDA any
  168. * Exit: SCL low, SDA high
  169. */
  170. static uint8_t TwGet(void)
  171. {
  172. uint8_t rc = 0;
  173. int i;
  174. /* SDA is input. */
  175. SDA_RELEASE; SDA_HIGH;
  176. TwDelay(1);
  177. for (i = 0x80; i; i >>= 1) {
  178. TwDelay(1);
  179. /* Data should appear shortly after the clock's rising edge. */
  180. SCL_RELEASE; SCL_HIGH;
  181. TwDelay(2);
  182. /* SDA read. */
  183. if (SDA_STAT) {
  184. rc |= i;
  185. }
  186. SCL_LOW; SCL_DRIVE;
  187. }
  188. return rc;
  189. }
  190. /*
  191. * Toggles out an acknowledge bit in master mode.
  192. *
  193. * Entry: SCL low, SDA any
  194. * Exit: SCL low, SDA high
  195. */
  196. static void TwAck(void)
  197. {
  198. SDA_LOW; SDA_DRIVE;
  199. TwDelay(1);
  200. SCL_RELEASE; SCL_HIGH;
  201. TwDelay(2);
  202. SCL_LOW; SCL_DRIVE;
  203. TwDelay(1);
  204. SDA_RELEASE; SDA_HIGH;
  205. }
  206. /*!
  207. * \brief Initialize TWI interface.
  208. *
  209. * The specified slave address is used only, if the local system
  210. * is running as a slave. Anyway, care must be taken that it doesn't
  211. * conflict with another connected device.
  212. *
  213. * \param sla Slave address, must be specified as a 7-bit address,
  214. * always lower than 128.
  215. *
  216. * \return Always 0.
  217. *
  218. */
  219. static int TwGpioInit(void)
  220. {
  221. SDA_RELEASE; SDA_HIGH;
  222. SCL_RELEASE; SCL_HIGH;
  223. SDA_INIT;
  224. SCL_INIT;
  225. twibb_initialized = 1;
  226. return 0;
  227. }
  228. /*!
  229. * \brief Transmit and/or receive data as a master.
  230. *
  231. * The two-wire serial interface must have been initialized by calling
  232. * TwInit() before this function can be used.
  233. *
  234. * \param sla Slave address of the destination. This slave address
  235. * must be specified as a 7-bit address. For example, the
  236. * PCF8574A may be configured to slave addresses from 0x38
  237. * to 0x3F.
  238. * \param txdata Points to the data to transmit. Ignored, if the number
  239. * of data bytes to transmit is zero.
  240. * \param txlen Number of data bytes to transmit. If zero, then the
  241. * interface will not send any data to the slave device
  242. * and will directly enter the master receive mode.
  243. * \param rxdata Points to a buffer, where the received data will be
  244. * stored. Ignored, if the maximum number of bytes to
  245. * receive is zero.
  246. * \param rxsiz Maximum number of bytes to receive. Set to zero, if
  247. * no bytes are expected from the slave device.
  248. * \param tmo Timeout in milliseconds. To disable timeout, set this
  249. * parameter to NUT_WAIT_INFINITE.
  250. *
  251. * \return The number of bytes received, -1 in case of an error or timeout.
  252. *
  253. * \note Timeout is not used in the bit banging version.
  254. */
  255. int NutTwiMasterTranceive(NUTTWIBUS *bus, uint8_t sla, const void *txdata, uint16_t txlen, void *rxdata, uint16_t rxsiz, uint32_t tmo)
  256. {
  257. int rc = 0;
  258. uint8_t *cp;
  259. if (!twibb_initialized) {
  260. TwGpioInit();
  261. }
  262. /* This routine is marked reentrant, so lock the interface. */
  263. if (NutEventWait(&bus->bus_mutex, tmo)) {
  264. tw_mm_error = TWERR_IF_LOCKED;
  265. return -1;
  266. }
  267. TwStart();
  268. /* Send SLA+W and check for ACK. */
  269. if ((rc = TwPut(sla << 1)) == 0) {
  270. for (cp = (uint8_t *)txdata; txlen--; cp++) {
  271. if ((rc = TwPut(*cp)) != 0) {
  272. break;
  273. }
  274. }
  275. }
  276. if (rc == 0 && rxsiz) {
  277. TwStart();
  278. /* Send SLA+R and check for ACK. */
  279. if ((rc = TwPut((sla << 1) | 1)) == 0) {
  280. for (cp = rxdata;; cp++) {
  281. *cp = TwGet();
  282. if (++rc >= rxsiz) {
  283. break;
  284. }
  285. TwAck();
  286. }
  287. }
  288. }
  289. TwStop();
  290. if (rc == -1) {
  291. tw_mm_error = TWERR_SLA_NACK;
  292. }
  293. /* Release the interface. */
  294. NutEventPost(&bus->bus_mutex);
  295. return rc;
  296. }
  297. /*!
  298. * \brief Get last master mode error.
  299. *
  300. * You may call this function to determine the specific cause
  301. * of an error after twi transaction failed.
  302. *
  303. */
  304. int NutTwiMasterError(NUTTWIBUS *bus)
  305. {
  306. int rc = tw_mm_error;
  307. tw_mm_error = 0;
  308. return rc;
  309. }
  310. /*!
  311. * \brief Listen for incoming data from a master.
  312. *
  313. * If this function returns without error, the bus is blocked. The caller
  314. * must immediately process the request and return a response by calling
  315. * TwSlaveRespond().
  316. *
  317. * \note Slave mode is not implemented in the bitbanging driver.
  318. * Thus the function always returns -1.
  319. *
  320. * \param sla Points to a byte variable, which receives the slave
  321. * address sent by the master. This can be used by the
  322. * caller to determine whether the the interface has been
  323. * addressed by a general call or its individual address.
  324. * \param rxdata Points to a data buffer where the received data bytes
  325. * are stored.
  326. * \param rxsiz Specifies the maximum number of data bytes to receive.
  327. * \param tmo Timeout in milliseconds. To disable timeout,
  328. * set this parameter to NUT_WAIT_INFINITE.
  329. *
  330. * \return The number of bytes received, -1 in case of an error or timeout.
  331. *
  332. */
  333. int NutTwiSlaveListen(NUTTWIBUS *bus, uint8_t *sla, void *rxdata, uint16_t rxsiz, uint32_t tmo)
  334. {
  335. return -1;
  336. }
  337. /*!
  338. * \brief Send response to a master.
  339. *
  340. * This function must be called as soon as possible after TwSlaveListen()
  341. * returned successfully, even if no data needs to be returned. Not doing
  342. * so will completely block the bus.
  343. *
  344. * \note Slave mode is not implemented in the bitbanging driver.
  345. * Thus the function always returns -1.
  346. *
  347. * \param txdata Points to the data to transmit. Ignored, if the
  348. * number of bytes to transmit is zero.
  349. * \param txlen Number of data bytes to transmit.
  350. * \param tmo Timeout in milliseconds. To disable timeout,
  351. * set this parameter to NUT_WAIT_INFINITE.
  352. *
  353. * \return The number of bytes transmitted, -1 in case of an error or timeout.
  354. */
  355. extern int NutTwiSlaveRespond(NUTTWIBUS *bus, void *txdata, uint16_t txlen, uint32_t tmo)
  356. {
  357. return -1;
  358. }
  359. /*!
  360. * \brief Get last slave mode error.
  361. *
  362. * You may call this function to determine the specific cause
  363. * of an error after TwSlaveListen() or TwSlaveRespond() failed.
  364. *
  365. * \return Error code or 0 if no error occurred.
  366. *
  367. * \note Slave mode is not implemented in the bitbanging driver.
  368. * Thus the function always returns TWERR_BUS.
  369. */
  370. extern int NutTwiSlaveError(NUTTWIBUS *bus)
  371. {
  372. return TWERR_BUS;
  373. }
  374. /*!
  375. * \brief Set Speed of I2C Interface.
  376. *
  377. * Setup Interface Speed
  378. */
  379. static int NutTwiSetSpeed( NUTTWIBUS *bus, uint32_t *speed)
  380. {
  381. int rc = -1;
  382. if (bus==NULL) {
  383. /* No bus selected */
  384. return rc;
  385. }
  386. if (*speed > 400000) {
  387. /* Speed out of range */
  388. return rc;
  389. }
  390. if (*speed < 4)
  391. delay_unit = 0xffff;
  392. else
  393. delay_unit = 250000/(*speed);
  394. if (delay_unit == 0)
  395. delay_unit = 1;
  396. return 0;
  397. }
  398. /*!
  399. * \brief Request Current Speed of I2C Interface.
  400. *
  401. * \return the caculated TWI Speed
  402. */
  403. static uint32_t NutTwiGetSpeed(void)
  404. {
  405. return 250000L/(uint32_t)delay_unit;
  406. }
  407. /*!
  408. * \brief Perform TWI control functions.
  409. *
  410. * Not implemented in the bit banging version.
  411. *
  412. * \param req Requested control function.
  413. * \param conf Points to a buffer that contains any data required for
  414. * the given control function or receives data from that
  415. * function.
  416. *
  417. * \return Always 0.
  418. */
  419. int NutTwiIOCtl( NUTTWIBUS *bus, int req, void *conf )
  420. {
  421. int rc = 0;
  422. switch (req) {
  423. case TWI_SETSPEED:
  424. rc = NutTwiSetSpeed(bus, (uint32_t *)conf);
  425. break;
  426. case TWI_GETSPEED:
  427. *((uint32_t *)conf) = NutTwiGetSpeed();
  428. break;
  429. case TWI_GETSTATUS:
  430. rc = 0;
  431. break;
  432. case TWI_SETSTATUS:
  433. rc = 0;
  434. break;
  435. default:
  436. rc = -1;
  437. break;
  438. }
  439. return rc;
  440. }
  441. /*!
  442. * \brief Initialize TWI interface bus.
  443. *
  444. * The specified slave address is not used here as we don't support twi-slave
  445. * on the bitbanging interface
  446. *
  447. * \param sla Slave address, must be specified as a 7-bit address,
  448. * always lower than 128.
  449. */
  450. int NutRegisterTwiBus( NUTTWIBUS *bus, uint8_t sla )
  451. {
  452. int rc = 0;
  453. #if defined(TWI_GPIO_UNDEFINED)
  454. return -1;
  455. #endif
  456. /* Check if bus was already registered */
  457. if( bus->bus_icb) {
  458. return 0;
  459. }
  460. bus->bus_icb = (void*)1;
  461. /* Initialize interface hardware */
  462. if (bus->bus_initbus) {
  463. rc = bus->bus_initbus();
  464. }
  465. /* Initialize mutex semaphores. */
  466. NutEventPost(&bus->bus_mutex);
  467. return rc;
  468. }
  469. int NutDestroyTwiBus( NUTTWIBUS *bus)
  470. {
  471. return 0;
  472. }
  473. /*!
  474. * \brief TWI/I2C bus structure.
  475. */
  476. NUTTWIBUS TwGpioBus = {
  477. /*.bus_base = */ 0, /* Bus base address. */
  478. /*.bus_sig_ev = */ NULL, /* Bus data and event interrupt handler. */
  479. /*.bus_sig_er = */ NULL, /* Bus error interrupt handler. */
  480. /*.bus_mutex = */ NULL, /* Bus lock queue. */
  481. /*.bus_icb = */ NULL, /* Bus Runtime Data Pointer */
  482. /*.bus_dma_tx = */ 0, /* DMA channel for TX direction. */
  483. /*.bus_dma_rx = */ 0, /* DMA channel for RX direction. */
  484. /*.bus_initbus =*/ TwGpioInit, /* Initialize bus controller. */
  485. /*.bus_recover =*/ NULL, /* Recover bus controller */
  486. };