twif.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980
  1. /*
  2. * Copyright (C) 2001-2005 by egnite Software GmbH. All rights reserved.
  3. * Copyright (C) 2012, Ole Reinhardt <ole.reinhardt@embedded-it.de>
  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 arch/avr/dev/twif.c
  36. * \brief AVR TWI support.
  37. *
  38. * \verbatim
  39. * $Id: twif.c 4937 2013-01-22 11:38:42Z haraldkipp $
  40. * \endverbatim
  41. */
  42. #include <string.h>
  43. #include <dev/irqreg.h>
  44. #include <sys/event.h>
  45. #include <sys/atom.h>
  46. #include <sys/timer.h>
  47. #include <sys/thread.h>
  48. #include <sys/heap.h>
  49. #include <dev/twif.h>
  50. #ifdef __AVR_ENHANCED__
  51. /*
  52. TWINT TWEA TWSTA TWSTO TWWC TWEN 0 TWIE
  53. C R R
  54. */
  55. #define TWGO (_BV(TWINT) | _BV(TWEN) | _BV(TWIE))
  56. /*
  57. * TWI interrupt handler.
  58. */
  59. static void TwInterrupt(void *arg)
  60. {
  61. NUTTWIBUS *bus = arg;
  62. NUTTWIICB *icb = bus->bus_icb;
  63. uint8_t twsr;
  64. register uint8_t twcr = inb(TWCR);
  65. /*
  66. * Read the status and interpret its contents.
  67. */
  68. twsr = inb(TWSR) & 0xF8;
  69. switch (twsr) {
  70. /*
  71. * 0x08: Start condition has been transmitted.
  72. * 0x10: Repeated start condition has been transmitted.
  73. */
  74. case TW_START:
  75. case TW_REP_START:
  76. /* We are entering the master mode. Mark the interface busy. */
  77. icb->tw_if_busy = 1;
  78. icb->tw_mm_txidx = 0;
  79. icb->tw_mm_rxidx = 0;
  80. /*
  81. * If outgoing data is available, transmit SLA+W. Logic is in
  82. * master transmit mode.
  83. */
  84. if (icb->tw_mm_txlen) {
  85. outb(TWDR, icb->tw_mm_sla);
  86. }
  87. /*
  88. * If outgoing data not available, transmit SLA+R. Logic will
  89. * switch to master receiver mode.
  90. */
  91. else {
  92. outb(TWDR, icb->tw_mm_sla | 1);
  93. }
  94. outb(TWCR, TWGO | (twcr & _BV(TWEA)));
  95. break;
  96. /*
  97. * 0x18: SLA+W has been transmitted and ACK has been received.
  98. * 0x28: Data byte has been transmitted and ACK has been received.
  99. */
  100. case TW_MT_SLA_ACK:
  101. case TW_MT_DATA_ACK:
  102. /*
  103. * If outgoing data left to send, put the next byte in the data
  104. * register.
  105. */
  106. if (icb->tw_mm_txidx < icb->tw_mm_txlen) {
  107. outb(TWDR, icb->tw_mm_txbuf[icb->tw_mm_txidx]);
  108. /* Late increment fixes ICCAVR bug. Thanks to Andreas Siebert and Michael Fischer. */
  109. icb->tw_mm_txidx++;
  110. outb(TWCR, TWGO | (twcr & _BV(TWEA)));
  111. break;
  112. }
  113. /*
  114. * All outgoing data has been sent. If a response is expected,
  115. * transmit a repeated start condition.
  116. */
  117. icb->tw_mm_txlen = 0;
  118. if (icb->tw_mm_rxlen) {
  119. outb(TWCR, TWGO | (twcr & _BV(TWEA)) | _BV(TWSTA));
  120. break;
  121. }
  122. /*
  123. * 0x20: SLA+W has been transmitted, but not acknowledged.
  124. * 0x30: Data byte has been transmitted, but not acknowledged.
  125. * 0x48: SLA+R has been transmitted, but not acknowledged.
  126. */
  127. case TW_MT_SLA_NACK:
  128. case TW_MT_DATA_NACK:
  129. case TW_MR_SLA_NACK:
  130. /* Set unique error code. */
  131. if (twsr == TW_MT_SLA_NACK || twsr == TW_MR_SLA_NACK) {
  132. icb->tw_mm_err = TWERR_SLA_NACK;
  133. icb->tw_mm_txlen = 0;
  134. icb->tw_mm_rxlen = 0;
  135. }
  136. /* Wake up the application. */
  137. NutEventPostFromIrq(&icb->tw_mm_mtx);
  138. /*
  139. * Send a stop condition. If we have a listener, generate
  140. * an acknowlegde on an incoming address byte.
  141. */
  142. if(icb->tw_sm_rxlen) {
  143. outb(TWCR, TWGO | _BV(TWEA) | _BV(TWSTO));
  144. }
  145. else {
  146. outb(TWCR, TWGO | _BV(TWSTO));
  147. }
  148. /* The interface is idle. */
  149. icb->tw_if_busy = 0;
  150. break;
  151. /*
  152. * 0x38: Arbitration lost while in master mode.
  153. */
  154. case TW_MT_ARB_LOST:
  155. /*
  156. * The start condition will be automatically resend after
  157. * the bus becomes available.
  158. */
  159. sbi(TWCR, TWSTA);
  160. /* The interface is idle. */
  161. icb->tw_if_busy = 0;
  162. break;
  163. /*
  164. * 0x50: Data byte has been received and acknowledged.
  165. */
  166. case TW_MR_DATA_ACK:
  167. /*
  168. * Store the data byte in the master receive buffer.
  169. */
  170. icb->tw_mm_rxbuf[icb->tw_mm_rxidx] = inb(TWDR);
  171. /* Late increment fixes ICCAVR bug. Thanks to Andreas Siebert and Michael Fischer. */
  172. icb->tw_mm_rxidx++;
  173. /*
  174. * 0x40: SLA+R has been transmitted and ACK has been received.
  175. */
  176. case TW_MR_SLA_ACK:
  177. /*
  178. * Acknowledge next data bytes except the last one.
  179. */
  180. if (icb->tw_mm_rxidx + 1 < icb->tw_mm_rxlen) {
  181. outb(TWCR, TWGO | _BV(TWEA));
  182. }
  183. else {
  184. outb(TWCR, TWGO);
  185. }
  186. break;
  187. /*
  188. * 0x58: Data byte has been received, but not acknowledged.
  189. */
  190. case TW_MR_DATA_NACK:
  191. /*
  192. * Store the last data byte.
  193. */
  194. icb->tw_mm_rxbuf[icb->tw_mm_rxidx] = inb(TWDR);
  195. /* Late increment fixes ICCAVR bug. Thanks to Andreas Siebert and Michael Fischer. */
  196. icb->tw_mm_rxidx++;
  197. icb->tw_mm_rxlen = 0;
  198. /* Wake up the application. */
  199. NutEventPostFromIrq(&icb->tw_mm_mtx);
  200. /*
  201. * Send a stop condition. If we have a listener, generate
  202. * an acknowlegde on an incoming address byte.
  203. */
  204. if(icb->tw_sm_rxlen) {
  205. outb(TWCR, TWGO | _BV(TWEA) | _BV(TWSTO));
  206. }
  207. else {
  208. outb(TWCR, TWGO | _BV(TWSTO));
  209. }
  210. /* The interface is idle. */
  211. icb->tw_if_busy = 0;
  212. break;
  213. /*
  214. * 0x60: Own SLA+W has been received and acknowledged.
  215. * 0x68: Arbitration lost as master. Own SLA+W has been received
  216. * and acknowledged.
  217. * 0x70: General call address has been received and acknowledged.
  218. * 0x78: Arbitration lost as master. General call address has been
  219. * received and acknowledged.
  220. */
  221. case TW_SR_SLA_ACK:
  222. case TW_SR_ARB_LOST_SLA_ACK:
  223. case TW_SR_GCALL_ACK:
  224. case TW_SR_ARB_LOST_GCALL_ACK:
  225. /*
  226. * Do only acknowledge incoming data bytes, if we got receive
  227. * buffer space. Fetch the slave address from the data register
  228. * and reset the receive index.
  229. */
  230. if (icb->tw_sm_rxlen) {
  231. /* We are entering the slave receive mode. Mark the interface busy. */
  232. icb->tw_if_busy = 1;
  233. icb->tw_sm_sla = inb(TWDR);
  234. outb(TWCR, TWGO | _BV(TWEA));
  235. icb->tw_sm_rxidx = 0;
  236. }
  237. /*
  238. * Do not acknowledge incoming data.
  239. */
  240. else {
  241. outb(TWCR, TWGO);
  242. }
  243. break;
  244. /*
  245. * 0x80: Data byte for own SLA has been received and acknowledged.
  246. * 0x90: Data byte for general call address has been received and
  247. * acknowledged.
  248. */
  249. case TW_SR_DATA_ACK:
  250. case TW_SR_GCALL_DATA_ACK:
  251. /*
  252. * If the receive buffer isn't filled up, store data byte.
  253. */
  254. if (icb->tw_sm_rxidx < icb->tw_sm_rxlen) {
  255. icb->tw_sm_rxbuf[icb->tw_sm_rxidx] = inb(TWDR);
  256. /* Late increment fixes ICCAVR bug. Thanks to Andreas Siebert and Michael Fischer. */
  257. icb->tw_sm_rxidx++;
  258. }
  259. else {
  260. icb->tw_sm_rxlen = 0;
  261. }
  262. /*
  263. * If more space is available for incoming data, then continue
  264. * receiving. Otherwise do not acknowledge new data bytes.
  265. */
  266. if (icb->tw_sm_rxlen) {
  267. outb(TWCR, TWGO | _BV(TWEA));
  268. break;
  269. }
  270. /*
  271. * 0x88: Data byte received, but not acknowledged.
  272. * 0x98: Data byte for general call address received, but not
  273. * acknowledged.
  274. */
  275. case TW_SR_DATA_NACK:
  276. case TW_SR_GCALL_DATA_NACK:
  277. /*
  278. * Continue not accepting more data.
  279. */
  280. if (icb->tw_mm_txlen || icb->tw_mm_rxlen) {
  281. outb(TWCR, inb(TWCR) | _BV(TWEA) | _BV(TWSTA));
  282. }
  283. else {
  284. outb(TWCR, inb(TWCR) | _BV(TWEA));
  285. }
  286. break;
  287. /*
  288. * 0xA0: Stop condition or repeated start condition received.
  289. */
  290. case TW_SR_STOP:
  291. /*
  292. * Wake up the application. If successful, do nothing. This
  293. * will keep SCL low and thus block the bus. The application
  294. * must now setup the transmit buffer and re-enable the
  295. * interface.
  296. */
  297. if (icb->tw_sm_rxmtx == 0 || icb->tw_sm_err) {
  298. /*
  299. * If no one has been waiting on the queue, the application
  300. * probably gave up waiting. So we continue on our own, either
  301. * in idle mode or switching to master mode if a master
  302. * request is waiting.
  303. */
  304. if (icb->tw_mm_txlen || icb->tw_mm_rxlen) {
  305. outb(TWCR, TWGO | _BV(TWSTA));
  306. }
  307. else {
  308. outb(TWCR, TWGO);
  309. }
  310. icb->tw_if_busy = 0;
  311. }
  312. else {
  313. NutEventPostFromIrq(&icb->tw_sm_rxmtx);
  314. icb->tw_sm_rxlen = 0;
  315. outb(TWCR, twcr & ~(_BV(TWINT) | _BV(TWIE)));
  316. }
  317. break;
  318. /*
  319. * 0xA8: Own SLA+R has been received and acknowledged.
  320. * 0xB0: Arbitration lost in master mode. Own SLA has been received
  321. * and acknowledged.
  322. */
  323. case TW_ST_SLA_ACK:
  324. case TW_ST_ARB_LOST_SLA_ACK:
  325. /* Not idle. */
  326. icb->tw_if_busy = 1;
  327. /* Reset transmit index and fall through for outgoing data. */
  328. icb->tw_sm_txidx = 0;
  329. /*
  330. * 0xB8: Data bytes has been transmitted and acknowledged.
  331. */
  332. case TW_ST_DATA_ACK:
  333. /*
  334. * If outgoing data left to send, put the next byte in the
  335. * data register. Otherwise transmit a dummy byte.
  336. */
  337. if (icb->tw_sm_txidx < icb->tw_sm_txlen) {
  338. outb(TWDR, icb->tw_sm_txbuf[icb->tw_sm_txidx]);
  339. /* Do not set acknowledge on the last data byte. */
  340. /* Early increment fixes ICCAVR bug. Thanks to Andreas Siebert and Michael Fischer. */
  341. ++icb->tw_sm_txidx;
  342. if (icb->tw_sm_txidx < icb->tw_sm_txlen) {
  343. outb(TWCR, TWGO | _BV(TWEA));
  344. }
  345. else {
  346. icb->tw_sm_txlen = 0;
  347. outb(TWCR, TWGO);
  348. }
  349. break;
  350. }
  351. /* No more data. Continue sending dummies. */
  352. outb(TWDR, 0);
  353. outb(TWCR, TWGO);
  354. break;
  355. /*
  356. * 0xC0: Data byte has been transmitted, but not acknowledged.
  357. * 0xC8: Last data byte has been transmitted and acknowledged.
  358. */
  359. case TW_ST_DATA_NACK:
  360. case TW_ST_LAST_DATA:
  361. NutEventPostFromIrq(&icb->tw_sm_txmtx);
  362. /* Transmit start condition, if a master transfer is waiting. */
  363. if (icb->tw_mm_txlen || icb->tw_mm_rxlen) {
  364. outb(TWCR, TWGO | _BV(TWSTA) | /**/ _BV(TWEA));
  365. }
  366. /* Otherwise enter idle state. */
  367. else {
  368. outb(TWCR, TWGO | _BV(TWEA));
  369. }
  370. icb->tw_if_busy = 0;
  371. break;
  372. /*
  373. * 0x00: Bus error.
  374. */
  375. case TW_BUS_ERROR:
  376. outb(TWCR, inb(TWCR) | _BV(TWSTO));
  377. #if 1
  378. icb->tw_if_busy = 0;
  379. icb->tw_mm_err = TWERR_BUS;
  380. icb->tw_sm_err = TWERR_BUS;
  381. NutEventPostFromIrq(&icb->tw_sm_rxmtx);
  382. NutEventPostFromIrq(&icb->tw_sm_txmtx);
  383. NutEventPostFromIrq(&icb->tw_mm_mtx);
  384. #endif
  385. break;
  386. }
  387. }
  388. #endif /* __AVR_ENHANCED__ */
  389. /*!
  390. * \brief Transmit and/or receive data as a master.
  391. *
  392. * The two-wire serial interface must have been initialized by calling
  393. * TwInit() before this function can be used.
  394. *
  395. * \note This function is only available on ATmega128 systems.
  396. *
  397. * \param sla Slave address of the destination. This slave address
  398. * must be specified as a 7-bit address. For example, the
  399. * PCF8574A may be configured to slave addresses from 0x38
  400. * to 0x3F.
  401. * \param txdata Points to the data to transmit. Ignored, if the number
  402. * of data bytes to transmit is zero.
  403. * \param txlen Number of data bytes to transmit. If zero, then the
  404. * interface will not send any data to the slave device
  405. * and will directly enter the master receive mode.
  406. * \param rxdata Points to a buffer, where the received data will be
  407. * stored. Ignored, if the maximum number of bytes to
  408. * receive is zero.
  409. * \param rxsiz Maximum number of bytes to receive. Set to zero, if
  410. * no bytes are expected from the slave device.
  411. * \param tmo Timeout in milliseconds. To disable timeout, set this
  412. * parameter to NUT_WAIT_INFINITE.
  413. *
  414. * \return The number of bytes received, -1 in case of an error or timeout.
  415. */
  416. int NutTwiMasterTranceive(NUTTWIBUS *bus, uint8_t sla, const void *txdata, uint16_t txlen, void *rxdata, uint16_t rxsiz, uint32_t tmo)
  417. {
  418. #ifndef __AVR_ENHANCED__
  419. return -1;
  420. #else
  421. NUTTWIICB *icb = bus->bus_icb;
  422. int rc = -1;
  423. /* This routine is marked reentrant, so lock the interface. */
  424. if(NutEventWait(&bus->bus_mutex, tmo)) {
  425. icb->tw_mm_err = TWERR_IF_LOCKED;
  426. NutEventPost(&bus->bus_mutex);
  427. return -1;
  428. }
  429. if (icb->tw_if_busy)
  430. NutSleep(1);
  431. while(icb->tw_if_busy) {
  432. if (tmo == 1)
  433. return -1;
  434. NutSleep(1);
  435. tmo --;
  436. }
  437. NutEnterCritical();
  438. /*
  439. * Set all parameters for master mode.
  440. */
  441. icb->tw_mm_sla = sla << 1;
  442. icb->tw_mm_err = 0;
  443. icb->tw_mm_txlen = txlen;
  444. icb->tw_mm_txbuf = txdata;
  445. icb->tw_mm_rxlen = rxsiz;
  446. icb->tw_mm_rxbuf = rxdata;
  447. /*
  448. * Send a start condition if the interface is idle. If busy, then
  449. * the interrupt routine will automatically initiate the transfer
  450. * as soon as the interface becomes ready again.
  451. */
  452. if(icb->tw_if_busy == 0) {
  453. uint8_t twcr = inb(TWCR);
  454. uint8_t twsr = inb(TWSR);
  455. if((twsr & 0xF8) == TW_NO_INFO) {
  456. if(icb->tw_sm_rxlen) {
  457. outb(TWCR, _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWSTA) | (twcr & _BV(TWSTO)));
  458. }
  459. else {
  460. outb(TWCR, _BV(TWEN) | _BV(TWIE) | _BV(TWSTA) | (twcr & _BV(TWSTO)));
  461. }
  462. }
  463. }
  464. /* Clear the queue. */
  465. //*broken?! NutEventBroadcastAsync(&tw_mm_mtx);
  466. if (icb->tw_mm_mtx == SIGNALED) {
  467. icb->tw_mm_mtx = 0;
  468. }
  469. NutExitCritical();
  470. /*
  471. * Wait for master transmission done.
  472. */
  473. rc = -1;
  474. if (NutEventWait(&icb->tw_mm_mtx, tmo)) {
  475. icb->tw_mm_error = TWERR_TIMEOUT;
  476. } else {
  477. NutEnterCritical();
  478. if (icb->tw_mm_err) {
  479. icb->tw_mm_error = icb->tw_mm_err;
  480. } else {
  481. rc = icb->tw_mm_rxidx;
  482. }
  483. NutExitCritical();
  484. }
  485. /*
  486. * Release the interface.
  487. */
  488. NutEventPost(&bus->bus_mutex);
  489. return rc;
  490. #endif /* __AVR_ENHANCED__ */
  491. }
  492. /*!
  493. * \brief Get last master mode error.
  494. *
  495. * You may call this function to determine the specific cause
  496. * of an error after TwMasterTransact() failed.
  497. *
  498. * \note This function is only available on ATmega128 systems.
  499. *
  500. */
  501. int NutTwiMasterError(NUTTWIBUS *bus)
  502. {
  503. #ifndef __AVR_ENHANCED__
  504. return -1;
  505. #else
  506. int rc = bus->bus_icb->tw_mm_error;
  507. bus->bus_icb->tw_mm_error = 0;
  508. return rc;
  509. #endif
  510. }
  511. /*!
  512. * \brief Listen for incoming data from a master.
  513. *
  514. * If this function returns without error, the bus is blocked. The caller
  515. * must immediately process the request and return a response by calling
  516. * TwSlaveRespond().
  517. *
  518. * \note This function is only available on ATmega128 systems. The
  519. * function is not reentrant.
  520. *
  521. * \param sla Points to a byte variable, which receives the slave
  522. * address sent by the master. This can be used by the
  523. * caller to determine whether the the interface has been
  524. * addressed by a general call or its individual address.
  525. * \param rxdata Points to a data buffer where the received data bytes
  526. * are stored.
  527. * \param rxsiz Specifies the maximum number of data bytes to receive.
  528. * \param tmo Timeout in milliseconds. To disable timeout,
  529. * set this parameter to NUT_WAIT_INFINITE.
  530. *
  531. * \return The number of bytes received, -1 in case of an error or timeout.
  532. */
  533. int NutTwiSlaveListen(NUTTWIBUS *bus, uint8_t *sla, void *rxdata, uint16_t rxsiz, uint32_t tmo)
  534. {
  535. #ifndef __AVR_ENHANCED__
  536. return -1;
  537. #else
  538. int rc = -1;
  539. NUTTWIICB *icb = bus->bus_icb;
  540. NutEnterCritical();
  541. /* Initialize parameters for slave receive. */
  542. icb->tw_sm_err = 0;
  543. icb->tw_sm_rxlen = rxsiz;
  544. icb->tw_sm_rxbuf = rxdata;
  545. /*
  546. * If the interface is currently not busy then enable it for
  547. * address recognition.
  548. */
  549. if(icb->tw_if_busy == 0) {
  550. uint8_t twsr = inb(TWSR);
  551. if((twsr & 0xF8) == TW_NO_INFO) {
  552. if(icb->tw_mm_txlen || icb->tw_mm_rxlen)
  553. outb(TWCR, _BV(TWEA) | _BV(TWEN) | _BV(TWIE) | _BV(TWSTA));
  554. else
  555. outb(TWCR, _BV(TWEA) | _BV(TWEN) | _BV(TWIE));
  556. }
  557. }
  558. /* Clear the queue. */
  559. //*broken?! NutEventBroadcastAsync(&tw_sm_rxmtx);
  560. if (icb->tw_sm_rxmtx == SIGNALED) {
  561. icb->tw_sm_rxmtx = 0;
  562. }
  563. NutExitCritical();
  564. /* Wait for a frame on the slave mode queue. */
  565. if (NutEventWait(&icb->tw_sm_rxmtx, tmo)) {
  566. NutEnterCritical();
  567. icb->tw_sm_err = TWERR_TIMEOUT;
  568. icb->tw_sm_rxlen = 0;
  569. NutExitCritical();
  570. }
  571. /*
  572. * Return the number of bytes received and the destination slave
  573. * address, if no slave error occured. In this case the bus is
  574. * blocked.
  575. */
  576. if(icb->tw_sm_err == 0) {
  577. rc = icb->tw_sm_rxidx;
  578. *sla = icb->tw_sm_sla;
  579. }
  580. return rc;
  581. #endif /* __AVR_ENHANCED__ */
  582. }
  583. /*!
  584. * \brief Send response to a master.
  585. *
  586. * This function must be called as soon as possible after TwSlaveListen()
  587. * returned successfully, even if no data needs to be returned. Not doing
  588. * so will completely block the bus.
  589. *
  590. * \note This function is only available on ATmega128 systems.
  591. *
  592. * \param txdata Points to the data to transmit. Ignored, if the
  593. * number of bytes to transmit is zero.
  594. * \param txlen Number of data bytes to transmit.
  595. * \param tmo Timeout in milliseconds. To disable timeout,
  596. * set this parameter to NUT_WAIT_INFINITE.
  597. *
  598. * \return The number of bytes transmitted, -1 in case of an error or timeout.
  599. */
  600. int NutTwiSlaveRespond(NUTTWIBUS *bus, void *txdata, uint16_t txlen, uint32_t tmo)
  601. {
  602. #ifndef __AVR_ENHANCED__
  603. return -1;
  604. #else
  605. int rc = -1;
  606. NUTTWIICB *icb = bus->bus_icb;
  607. /* The bus is blocked. No critical section required. */
  608. icb->tw_sm_txbuf = txdata;
  609. icb->tw_sm_txlen = txlen;
  610. /*
  611. * If there is anything to transmit, start the interface.
  612. */
  613. if (txlen) {
  614. NutEnterCritical();
  615. /* Clear the queue. */
  616. //*broken?! NutEventBroadcastAsync(&tw_sm_txmtx);
  617. if (icb->tw_sm_txmtx == SIGNALED) {
  618. icb->tw_sm_txmtx = 0;
  619. }
  620. /* Release the bus, accepting SLA+R. */
  621. outb(TWCR, TWGO | _BV(TWEA));
  622. NutExitCritical();
  623. if (NutEventWait(&icb->tw_sm_txmtx, tmo)) {
  624. icb->tw_sm_err = TWERR_TIMEOUT;
  625. }
  626. NutEnterCritical();
  627. icb->tw_sm_txlen = 0;
  628. if (icb->tw_sm_err) {
  629. icb->tw_sm_error = icb->tw_sm_err;
  630. } else {
  631. rc = icb->tw_sm_txidx;
  632. }
  633. NutExitCritical();
  634. }
  635. /*
  636. * Nothing to transmit.
  637. */
  638. else {
  639. rc = 0;
  640. /* Release the bus, not accepting SLA+R. */
  641. NutEnterCritical();
  642. inb(TWCR);
  643. inb(TWSR);
  644. /* Transmit start condition, if a master transfer is waiting. */
  645. if (icb->tw_mm_txlen || icb->tw_mm_rxlen) {
  646. outb(TWCR, TWGO | _BV(TWSTA));
  647. }
  648. /* Otherwise enter idle state. */
  649. else {
  650. icb->tw_if_busy = 0;
  651. outb(TWCR, TWGO);
  652. }
  653. NutExitCritical();
  654. }
  655. return rc;
  656. #endif /* __AVR_ENHANCED__ */
  657. }
  658. /*!
  659. * \brief Get last slave mode error.
  660. *
  661. * You may call this function to determine the specific cause
  662. * of an error after TwSlaveListen() or TwSlaveRespond() failed.
  663. *
  664. * \note This function is only available on ATmega128 systems.
  665. *
  666. */
  667. int NutTwiSlaveError(NUTTWIBUS *bus)
  668. {
  669. #ifndef __AVR_ENHANCED__
  670. return -1;
  671. #else
  672. int rc = bus->bus_icb->tw_sm_error;
  673. bus->bus_icb->tw_sm_error = 0;
  674. return rc;
  675. #endif
  676. }
  677. int NutTwiSetSpeed( NUTTWIBUS *bus, uint32_t speed)
  678. {
  679. #ifndef __AVR_ENHANCED__
  680. return -1;
  681. #else
  682. int rc = -1;
  683. uint32_t lval;
  684. if (speed > 400000) {
  685. /* Speed out of range */
  686. return rc;
  687. }
  688. if (bus==NULL) {
  689. /* No bus selected */
  690. return rc;
  691. }
  692. lval = ((2UL * NutGetCpuClock() / speed + 1UL) / 2UL - 16UL) / 2UL;
  693. if (lval > 1020UL) {
  694. lval /= 16UL;
  695. sbi(TWSR, TWPS1);
  696. } else {
  697. cbi(TWSR, TWPS1);
  698. }
  699. if (lval > 255UL) {
  700. lval /= 4UL;
  701. sbi(TWSR, TWPS0);
  702. } else {
  703. cbi(TWSR, TWPS0);
  704. }
  705. if (lval > 9UL && lval < 256UL) {
  706. outb(TWBR, (uint8_t) lval);
  707. rc = 0;
  708. } else {
  709. rc = -1;
  710. }
  711. return rc;
  712. #endif
  713. }
  714. /*!
  715. * \brief Request Current Speed of I2C Interface.
  716. *
  717. * \return 0..400000 for speed, -1 in case of error.
  718. */
  719. int NutTwiGetSpeed( NUTTWIBUS *bus, uint32_t *speed)
  720. {
  721. #ifndef __AVR_ENHANCED__
  722. return -1;
  723. #else
  724. uint32_t lval;
  725. if (bus) {
  726. lval = 2UL;
  727. if (bit_is_set(TWSR, TWPS0)) {
  728. lval *= 4UL;
  729. }
  730. if (bit_is_set(TWSR, TWPS1)) {
  731. lval *= 16UL;
  732. }
  733. *speed = NutGetCpuClock() / (16UL + lval * (uint32_t) inb(TWBR));
  734. }
  735. return 0;
  736. #endif
  737. }
  738. /*!
  739. * \brief Perform TWI control functions.
  740. *
  741. * This function is only available on ATmega128 systems.
  742. *
  743. * \param req Requested control function. May be set to one of the
  744. * following constants:
  745. * - TWI_SETSPEED, if conf points to an uint32_t value containing the bitrate.
  746. * - TWI_GETSPEED, if conf points to an uint32_t value receiving the current bitrate.
  747. * \param conf Points to a buffer that contains any data required for
  748. * the given control function or receives data from that
  749. * function.
  750. * \return 0 on success, -1 otherwise.
  751. *
  752. * \note Timeout is limited to the granularity of the system timer.
  753. *
  754. */
  755. int NutTwiIOCtl( NUTTWIBUS *bus, int req, void *conf )
  756. {
  757. #ifndef __AVR_ENHANCED__
  758. return -1;
  759. #else
  760. int rc = 0;
  761. NUTTWIICB *icb = bus->bus_icb;
  762. switch (req) {
  763. case TWI_SETSPEED:
  764. rc = NutTwiSetSpeed(bus, *((uint32_t *)conf));
  765. break;
  766. case TWI_GETSPEED:
  767. rc = NutTwiGetSpeed(bus, ((uint32_t *)conf));
  768. break;
  769. case TWI_GETSTATUS:
  770. rc = 0;
  771. break;
  772. case TWI_SETSTATUS:
  773. rc = 0;
  774. break;
  775. case TWI_GETSLAVEADDRESS:
  776. // TODO: Slave handling
  777. *((uint8_t *)conf) = TWAR;
  778. break;
  779. case TWI_SETSLAVEADDRESS:
  780. // TODO: Slave handling
  781. TWAR = (*((uint8_t *) conf) << 1) | 1;
  782. icb->tw_mm_sla = *((uint16_t*)conf);
  783. break;
  784. default:
  785. rc = -1;
  786. break;
  787. }
  788. return rc;
  789. #endif /* __AVR_ENHANCED__ */
  790. }
  791. /*!
  792. * \brief Initialize TWI interface bus.
  793. *
  794. * The specified slave address is used only, if the local system
  795. * is running as a slave. Anyway, care must be taken that it doesn't
  796. * conflict with another connected device.
  797. *
  798. * \note This function is only available on ATmega128 systems.
  799. *
  800. * \param sla Slave address, must be specified as a 7-bit address,
  801. * always lower than 128.
  802. */
  803. int NutRegisterTwiBus( NUTTWIBUS *bus, uint8_t sla )
  804. {
  805. #ifndef __AVR_ENHANCED__
  806. return -1;
  807. #else
  808. int rc = 0;
  809. uint32_t speed = 2400;
  810. NUTTWIICB *icb = NULL;
  811. /* Check if bus was already registered */
  812. if( bus->bus_icb) {
  813. return 0;
  814. }
  815. /* Allocate ICB for this bus */
  816. icb = NutHeapAlloc(sizeof(NUTTWIICB));
  817. if( icb == NULL) {
  818. return rc;
  819. }
  820. memset( icb, 0, sizeof(NUTTWIICB));
  821. /* Link bus and ICB */
  822. bus->bus_icb = icb;
  823. /* Initialize interface hardware */
  824. if (bus->bus_initbus) {
  825. rc = bus->bus_initbus();
  826. }
  827. /*
  828. * Set address register, enable general call address, set transfer
  829. * speed and enable interface.
  830. */
  831. outb(TWAR, (sla << 1) | 1);
  832. #ifdef I2C_DEFAULT_SPEED
  833. speed = I2C_DEFAULT_SPEED*1000UL;
  834. #endif
  835. /* Set initial rate. */
  836. if( (rc = NutTwiSetSpeed( bus, speed))) {
  837. return rc;
  838. }
  839. /* Register IRQ Handler */
  840. if( (rc = NutRegisterIrqHandler( bus->bus_sig_ev, TwInterrupt, bus))) {
  841. return rc;
  842. }
  843. /* Enable level triggered interrupts. */
  844. NutIrqEnable(bus->bus_sig_ev);
  845. outb(TWCR, _BV(TWINT));
  846. outb(TWCR, _BV(TWEN) | _BV(TWIE));
  847. /* Initialize mutex semaphores. */
  848. NutEventPost(&bus->bus_mutex);
  849. return rc;
  850. #endif
  851. }
  852. int NutDestroyTwiBus( NUTTWIBUS *bus)
  853. {
  854. #ifndef __AVR_ENHANCED__
  855. return -1;
  856. #else
  857. if (bus->bus_icb) {
  858. NutIrqDisable(bus->bus_sig_ev);
  859. NutHeapFree( bus->bus_icb);
  860. }
  861. return 0;
  862. #endif
  863. }
  864. /*!
  865. * \brief TWI/I2C bus structure.
  866. */
  867. NUTTWIBUS AVRTwiBus = {
  868. /*.bus_base = */ 0, /* Bus base address. */
  869. #ifndef __AVR_ENHANCED__
  870. /*.bus_sig_ev = */ NULL, /* Bus data and event interrupt handler. */
  871. #else
  872. /*.bus_sig_ev = */ &sig_2WIRE_SERIAL, /* Bus data and event interrupt handler. */
  873. #endif
  874. /*.bus_sig_er = */ NULL, /* Bus error interrupt handler. */
  875. /*.bus_mutex = */ NULL, /* Bus lock queue. */
  876. /*.bus_icb = */ NULL, /* Bus Runtime Data Pointer */
  877. /*.bus_dma_tx = */ 0, /* DMA channel for TX direction. */
  878. /*.bus_dma_rx = */ 0, /* DMA channel for RX direction. */
  879. /*.bus_initbus =*/ NULL, /* Initialize bus controller. */
  880. /*.bus_recover =*/ NULL, /* Recover bus controller */
  881. };