stm32_twi.c 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071
  1. /*
  2. * Copyright (C) 2010 by Ulrich Prinz (uprinz2@netscape.net)
  3. * Copyright (C) 2010 by Rittal GmbH & Co. KG. All rights reserved.
  4. *
  5. * All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. *
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. * 2. Redistributions in binary form must reproduce the above copyright
  14. * notice, this list of conditions and the following disclaimer in the
  15. * documentation and/or other materials provided with the distribution.
  16. * 3. Neither the name of the copyright holders nor the names of
  17. * contributors may be used to endorse or promote products derived
  18. * from this software without specific prior written permission.
  19. *
  20. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  21. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  22. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  23. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  24. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  25. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  26. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  27. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  28. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  29. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  30. * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31. * SUCH DAMAGE.
  32. *
  33. * For additional information see http://www.ethernut.de/
  34. *
  35. */
  36. /*
  37. * \verbatim
  38. * $Id: stm32_twi.c 5620 2014-04-02 13:19:09Z u_bonnes $
  39. * \endverbatim
  40. */
  41. #include <arch/cm3.h>
  42. #include <dev/irqreg.h>
  43. #include <sys/event.h>
  44. #include <sys/atom.h>
  45. #include <sys/timer.h>
  46. #include <sys/thread.h>
  47. #include <sys/heap.h>
  48. #include <cfg/twi.h>
  49. #include <dev/twif.h>
  50. #include <stdlib.h>
  51. #include <string.h>
  52. #include <arch/cm3/stm/stm32xxxx.h>
  53. #if defined(I2CBUS1_USE_DMA) || defined(I2CBUS2_USE_DMA)
  54. #if defined(MCU_STM32F1)
  55. #include <arch/cm3/stm/stm32f1_dma.h>
  56. #else
  57. #warning "Unhandled STM32 family"
  58. #endif
  59. #endif
  60. //#define TWI_DEBUG
  61. #ifdef TWI_DEBUG
  62. #include <stdio.h>
  63. #include <dev/gpio.h>
  64. #define TPRINTF(...) printf(__VA_ARGS__); fflush(stdout)
  65. #define DBGP1_INIT() GpioPinConfigSet(NUTGPIO_PORTB, 1, GPIO_CFG_OUTPUT)
  66. #define DBGP1(v) GpioPinSet(NUTGPIO_PORTB, 1, v)
  67. #define DBGP2_INIT() GpioPinConfigSet(NUTGPIO_PORTB, 9, GPIO_CFG_OUTPUT)
  68. #define DBGP2(v) GpioPinSet(NUTGPIO_PORTB, 9, v)
  69. #else
  70. #define TPRINTF(...)
  71. #define DBGP1_INIT()
  72. #define DBGP1(v)
  73. #define DBGP2_INIT()
  74. #define DBGP2(v)
  75. #endif
  76. #define MODE_FLAG_Mask ((uint32_t)0x00FFFFFF)
  77. #define CR1_CLEAR_Mask ((uint16_t)0xFBF5) /* I2C registers Masks */
  78. #define CCR_CCR_Set ((uint16_t)0x0FFF) /* I2C CCR mask */
  79. #define CCR_FS_Set ((uint16_t)0x8000) /* I2C F/S mask */
  80. #define MODE_READ 1 /* Work as Receiver */
  81. #define MODE_WRITE 0 /* Work as Transmitter */
  82. #define ENABLE 1
  83. #define DISABLE 0
  84. #define ERROR 0
  85. #define SUCCESS 1
  86. /* Enable DMA trensfer mode at given bus */
  87. inline void I2C_DMA_Enable(I2C_TypeDef* I2Cx){
  88. I2Cx->CR2 |= I2C_CR2_DMAEN;
  89. };
  90. /* Disable DMA trensfer mode at given bus */
  91. inline void I2C_DMA_Disable(I2C_TypeDef* I2Cx){
  92. I2Cx->CR2 &= (uint16_t)~I2C_CR2_DMAEN;
  93. };
  94. /* Check if interface is busy */
  95. inline uint8_t I2C_Is_Busy(I2C_TypeDef* I2Cx)
  96. {
  97. return (uint8_t)(I2Cx->SR2&I2C_SR2_BUSY);
  98. }
  99. /* Answer with NACK to next received byte and set STOP */
  100. #define I2C_NACK_STOP(x) { \
  101. x->CR1 &= (uint16_t)~I2C_CR1_ACK; \
  102. x->CR1 |= I2C_CR1_STOP; \
  103. }
  104. #define I2C_ENA_ACK(x) x->CR1 |= I2C_CR1_ACK
  105. /* Send (RE-)START condition */
  106. #define I2C_RESTART(x) x->CR1 |= I2C_CR1_START
  107. /* Send STOP after current transmission finished */
  108. #define I2C_STOP(x) x->CR1 |= I2C_CR1_STOP
  109. /* Disable Event Interrupt */
  110. #define I2C_DIS_EVT(x) x->CR2 &= (uint16_t)~I2C_CR2_ITEVTEN
  111. /* Control Buffer Interrupt */
  112. #define I2C_DIS_BUF(x) x->CR2 &= (uint16_t)~I2C_CR2_ITBUFEN
  113. #define I2C_ENA_BUF(x) x->CR2 |= I2C_CR2_ITBUFEN
  114. /*
  115. * TWI Event & Data Interrupt Handler
  116. */
  117. void TwEventIrq( void *arg)
  118. {
  119. NUTTWIBUS *bus = arg;
  120. NUTTWIICB *icb = bus->bus_icb;
  121. I2C_TypeDef* I2Cx = (I2C_TypeDef*)bus->bus_base;
  122. uint32_t twsr1 = I2Cx->SR1;
  123. uint32_t twsr2 = I2Cx->SR2;
  124. // int i;
  125. #if 0
  126. i=16;
  127. do {
  128. i--;
  129. DBGP1(1);
  130. DBGP2(twsr1&(1<<i));
  131. DBGP1(0);
  132. } while(i);
  133. #endif
  134. if( twsr1 & I2C_SR1_SB) {
  135. /* Send Slave Address and direction bit */
  136. // TODO: 10-Bit Addressing
  137. I2Cx->DR = (icb->tw_mm_sla | icb->tw_mm_dir);
  138. }
  139. if( twsr2 & I2C_SR2_MSL)
  140. {
  141. DBGP1(1);
  142. /* Interface is in master mode */
  143. if( twsr1 & I2C_SR1_ADDR) {
  144. /*
  145. * This Section is called only after
  146. * Slave Address has been sent
  147. */
  148. if( icb->tw_mm_dir == MODE_WRITE) {
  149. /*
  150. * Master Transmitter 1st Byte
  151. */
  152. if( icb->tw_mm_iadrlen) {
  153. /* we have to send a register address to the slave */
  154. /* little-endian machine! */
  155. I2Cx->DR = *icb->tw_mm_iadr--;
  156. icb->tw_mm_iadrlen--;
  157. }
  158. else if( icb->tw_mm_txlen) {
  159. /* we have to send data */
  160. I2Cx->DR = *icb->tw_mm_txbuf++;
  161. icb->tw_mm_txlen--;
  162. }
  163. /* If there was only one byte to send */
  164. if( (icb->tw_mm_txlen==0) && (icb->tw_mm_iadrlen==0)) {
  165. /* Disable TXE Interrupt */
  166. I2C_DIS_BUF(I2Cx);
  167. }
  168. }
  169. else {
  170. /*
  171. * Master Receiver if only one byte awaited
  172. */
  173. /* Check if only one byte to read */
  174. if( icb->tw_mm_rxlen == 1) {
  175. /* Last byte awaited: send NACK and STOP */
  176. I2C_NACK_STOP(I2Cx);
  177. }
  178. }
  179. goto TwEvExit;
  180. }
  181. /*
  182. * Master in transmission 2nd to last byte
  183. */
  184. if( (twsr1 & (I2C_SR1_TXE|I2C_SR1_BTF)) == I2C_SR1_TXE) {
  185. if( icb->tw_mm_iadrlen) {
  186. /* send next register address byte */
  187. /* little-endian machine! */
  188. I2Cx->DR = *icb->tw_mm_iadr--;
  189. icb->tw_mm_iadrlen--;
  190. }
  191. else if( icb->tw_mm_txlen) {
  192. /* send next data byte */
  193. I2Cx->DR = *icb->tw_mm_txbuf++;
  194. icb->tw_mm_txlen--;
  195. }
  196. /* Check if end of tx */
  197. if( (icb->tw_mm_txlen==0) && (icb->tw_mm_iadrlen==0)) {
  198. /* Nothing left to send */
  199. I2C_DIS_BUF(I2Cx);
  200. }
  201. goto TwEvExit;
  202. }
  203. /*
  204. * Master transmitted last byte
  205. */
  206. if( (twsr1 & (I2C_SR1_TXE|I2C_SR1_BTF)) == (I2C_SR1_TXE|I2C_SR1_BTF)) {
  207. /* Check if Write->Read transition */
  208. if( icb->tw_mm_rxlen) {
  209. /* Switch to read direction */
  210. icb->tw_mm_dir = MODE_READ;
  211. /* Issue a RESTART */
  212. I2C_RESTART(I2Cx);
  213. /* Enable Buffer Interrupt again */
  214. I2C_ENA_BUF(I2Cx);
  215. }
  216. else {
  217. /* We are complete: Clear ACK, send STOP */
  218. I2C_NACK_STOP(I2Cx);
  219. /* Disable EV_IT */
  220. I2C_DIS_EVT(I2Cx);
  221. }
  222. goto TwEvExit;
  223. }
  224. /*
  225. * Master is receiving
  226. */
  227. if( twsr1 & I2C_SR1_RXNE) {
  228. /* Read data */
  229. *icb->tw_mm_rxbuf++ = (uint8_t)I2Cx->DR;
  230. icb->tw_mm_rxlen--;
  231. if( icb->tw_mm_rxlen == 1) {
  232. /* Only one byte left to receive: Clear ACK, set STOP */
  233. I2C_NACK_STOP(I2Cx);
  234. }
  235. if( icb->tw_mm_rxlen == 0) {
  236. /* Only one byte left to receive: Clear ACK, set STOP */
  237. I2C_DIS_BUF(I2Cx);
  238. goto TwEvExit;
  239. }
  240. goto TwEvExit;
  241. }
  242. }
  243. else {
  244. /* Slave mode */
  245. I2C_DIS_BUF(I2Cx);
  246. I2C_DIS_EVT(I2Cx);
  247. DBGP2(1);
  248. }
  249. TwEvExit:
  250. DBGP2(0);
  251. DBGP1(0);
  252. }
  253. void TwErrorIrq( void *arg)
  254. {
  255. NUTTWIBUS *bus = arg;
  256. NUTTWIICB *icb = bus->bus_icb;
  257. I2C_TypeDef* I2Cx = (I2C_TypeDef*)bus->bus_base;
  258. register uint32_t twsr1 = (I2Cx->SR1);
  259. /*
  260. *** ERROR HANDLING ***
  261. */
  262. if( twsr1 & I2C_SR1_AF) {
  263. /* Acknowledge failed */
  264. I2Cx->SR1 &= (uint16_t)~I2C_SR1_AF;
  265. icb->tw_mm_err = TWERR_SLA_NACK;
  266. I2C_STOP(I2Cx);
  267. }
  268. if( twsr1 & I2C_SR1_ARLO) {
  269. /* Arbitration lost */
  270. I2Cx->SR1 &= (uint16_t)~I2C_SR1_ARLO;
  271. icb->tw_mm_err = TWERR_ARBLOST;
  272. }
  273. if( twsr1 & I2C_SR1_BERR) {
  274. /* Misplaced Start/STOP condition detected */
  275. I2Cx->SR1 &= (uint16_t)~I2C_SR1_BERR;
  276. icb->tw_mm_err = TWERR_BUS;
  277. }
  278. if( twsr1 & I2C_SR1_TIMEOUT) {
  279. /* Timeout occured */
  280. I2Cx->SR1 &= (uint16_t)~I2C_SR1_TIMEOUT;
  281. icb->tw_mm_err = TWERR_TIMEOUT;
  282. }
  283. if( twsr1 & I2C_SR1_OVR) {
  284. /* Overrun/Underrun detected */
  285. I2Cx->SR1 &= (uint16_t)~I2C_SR1_OVR;
  286. icb->tw_mm_err = TWERR_OVRE;
  287. }
  288. }
  289. /*!
  290. * \brief Reset the I2C peripheral by issueing soft-reset.
  291. */
  292. void NutTwiSoftReset( NUTTWIBUS *bus)
  293. {
  294. I2C_TypeDef* I2Cx = (I2C_TypeDef*)bus->bus_base;
  295. I2Cx->CR1 |= I2C_CR1_SWRST;
  296. I2Cx->CR1 &= ~I2C_CR1_SWRST;
  297. }
  298. #if defined(MCU_STM32F4) || defined(MCU_STM32F2)
  299. int TwWaitForFlag( volatile uint32_t *reg, uint32_t mask, uint16_t flag)
  300. #else
  301. int TwWaitForFlag( volatile uint16_t *reg, uint16_t mask, uint16_t flag)
  302. #endif
  303. {
  304. int ret = 0;
  305. uint32_t sptout = 0xFFFF;
  306. while( (*(volatile uint16_t*)reg & mask) != flag) {
  307. if (sptout-- == 0) {
  308. ret = TWERR_SPCTOUT;
  309. break;
  310. }
  311. }
  312. return ret;
  313. }
  314. #if 0
  315. int TwWaitBusFree( NUTTWIBUS *bus)
  316. {
  317. int ret = -1;
  318. uint32_t tout = 100;
  319. NUTTWIICB *icb = bus->bus_icb;
  320. I2C_TypeDef* I2Cx = (I2C_TypeDef*)bus->bus_base;
  321. /* Wait till last transfer finished */
  322. tout = 100;
  323. while (I2C_Is_Busy(I2Cx) && tout) {
  324. TPRINTF("B");
  325. NutSleep(1);
  326. tout--;
  327. }
  328. if (tout) {
  329. /* Interface released in time */
  330. ret = 0;
  331. }
  332. else {
  333. TPRINTF("R");
  334. I2Cx->CR1 &= ~I2C_CR1_PE;
  335. I2Cx->CR1 |= I2C_CR1_SWRST;
  336. bus->bus_recover();
  337. I2Cx->CR1 &= ~I2C_CR1_SWRST;
  338. I2Cx->CR1 &= ~I2C_CR1_PE;
  339. NutSleep(1);
  340. if (I2C_Is_Busy(I2Cx)) {
  341. /* Bus still blocked */
  342. icb->tw_mm_error = TWERR_BUS;
  343. /* Release the interface. */
  344. NutEventPost( &bus->bus_mutex );
  345. }
  346. else {
  347. /* We made it! */
  348. ret = 0;
  349. }
  350. }
  351. return ret;
  352. }
  353. #endif
  354. /*!
  355. * \brief Set START condition and wait for its appearance on the bus.
  356. */
  357. void NutTwiStartRolling( NUTTWIBUS *bus, uint32_t tmo)
  358. {
  359. int ret = 0;
  360. uint32_t tout = tmo;
  361. NUTTWIICB *icb = bus->bus_icb;
  362. I2C_TypeDef* I2Cx = (I2C_TypeDef*)bus->bus_base;
  363. /* Enable Interrupts */
  364. I2Cx->CR2 |= (I2C_CR2_ITEVTEN|I2C_CR2_ITBUFEN|I2C_CR2_ITERREN);
  365. /* Generate Start gets Irq System rolling */
  366. I2Cx->CR1 = (I2C_CR1_ACK|I2C_CR1_START|I2C_CR1_PE);
  367. /* Wait till the START has been sent */
  368. ret = TwWaitForFlag(&I2Cx->CR1, I2C_CR1_START, I2C_CR1_START);
  369. /* Continue only if START has been sent */
  370. if (ret == 0) {
  371. /* Go to background till we are through */
  372. while( I2C_Is_Busy(I2Cx)) {
  373. // while( icb->tw_mm_rxlen+icb->tw_mm_txlen) {
  374. NutSleep(1);
  375. if( tout-- == 0) {
  376. ret = TWERR_TIMEOUT;
  377. break;
  378. }
  379. }
  380. // TODO: Go back into Slave Mode
  381. I2Cx->CR1 |= I2C_CR1_ACK;
  382. }
  383. else
  384. icb->tw_mm_err |= ret;
  385. return;
  386. }
  387. /*!
  388. * \brief Transmit and/or receive data as a master.
  389. *
  390. * The two-wire serial interface must have been initialized by calling
  391. * TwInit() before this function can be used.
  392. *
  393. * \param sla Slave address of the destination. This slave address
  394. * must be specified as a 7-bit address. For example, the
  395. * PCF8574A may be configured to slave addresses from 0x38
  396. * to 0x3F.
  397. * \param txdata Points to the data to transmit. Ignored, if the number
  398. * of data bytes to transmit is zero.
  399. * \param txlen Number of data bytes to transmit. If zero, then the
  400. * interface will not send any data to the slave device
  401. * and will directly enter the master receive mode.
  402. * \param rxdata Points to a buffer, where the received data will be
  403. * stored. Ignored, if the maximum number of bytes to
  404. * receive is zero.
  405. * \param rxsiz Maximum number of bytes to receive. Set to zero, if
  406. * no bytes are expected from the slave device.
  407. * \param tmo Timeout in milliseconds. To disable timeout, set this
  408. * parameter to NUT_WAIT_INFINITE.
  409. *
  410. * \return The number of bytes received, -1 in case of an error or timeout.
  411. */
  412. int NutTwiMasterTranceive( NUTTWIBUS *bus,
  413. uint8_t sla,
  414. const void *txdata, uint16_t txlen,
  415. void *rxdata, uint16_t rxsiz,
  416. uint32_t tmo )
  417. {
  418. int rc = -1;
  419. NUTTWIICB *icb = bus->bus_icb;
  420. // TPRINTF( "TMT ");
  421. /* This routine is marked reentrant, so lock the interface. */
  422. if( NutEventWait( &bus->bus_mutex, tmo ) ) {
  423. icb->tw_mm_error = TWERR_IF_LOCKED;
  424. TPRINTF("! mtx=LOCKED... OUT\n");
  425. return rc;
  426. }
  427. #if 0
  428. /* Check if bus is blocked for any reason */
  429. if (TwWaitBusFree( bus))
  430. {
  431. return rc;
  432. }
  433. #endif
  434. /* Clear errors. */
  435. icb->tw_mm_err = 0;
  436. /* fetch transfer parameters for current transaction */
  437. icb->tw_mm_sla = sla<<1;
  438. icb->tw_mm_iadr = NULL;
  439. icb->tw_mm_iadrlen = 0;
  440. icb->tw_mm_txbuf = (uint8_t*)txdata;
  441. icb->tw_mm_txlen = txlen;
  442. icb->tw_mm_rxbuf = rxdata;
  443. icb->tw_mm_rxlen = rxsiz;
  444. icb->tw_mm_err = 0;
  445. if (icb->tw_mm_rxlen)
  446. icb->tw_mm_dir = MODE_READ;
  447. else
  448. icb->tw_mm_dir = MODE_WRITE;
  449. /* Issue start and wait till transmission completed */
  450. NutTwiStartRolling( bus, tmo);
  451. /* Check for errors that may have been detected
  452. * by the interrupt routine.
  453. */
  454. if( icb->tw_mm_err ) {
  455. icb->tw_mm_error = icb->tw_mm_err;
  456. rc = -1;
  457. /* Soft-Reset this Bus */
  458. // NutTwiSoftReset( bus);
  459. } else {
  460. if( rxsiz)
  461. rc = (int)(rxsiz - icb->tw_mm_rxlen);
  462. else
  463. rc = (int)(txlen - icb->tw_mm_txlen);
  464. }
  465. /* Release the interface. */
  466. NutEventPost( &bus->bus_mutex );
  467. TPRINTF( "* Bye rc=%d\n", rc);
  468. return rc;
  469. }
  470. /*!
  471. * \brief Receive data as a master from a device having internal addressable registers
  472. *
  473. * The two-wire serial interface must have been initialized by calling
  474. * TwInit() before this function can be used.
  475. *
  476. * \param sla Slave address of the destination. This slave address
  477. * must be specified as a 7-bit address. For example, the
  478. * PCF8574A may be configured to slave addresses from 0x38
  479. * to 0x3F.
  480. * \param iadr Address send to the device to access certain registers
  481. * or memory addresses of it.
  482. * \param iadrlen Number of bytes to send as address, maximum 3 bytes are
  483. * supported from AT91SAM7
  484. * \param rxdata Points to a buffer, where the received data will be
  485. * stored.
  486. * \param rxsiz Maximum number of bytes to receive.
  487. * \param tmo Timeout in milliseconds. To disable timeout, set this
  488. * parameter to NUT_WAIT_INFINITE.
  489. *
  490. * \return The number of bytes received, -1 in case of an error or timeout.
  491. */
  492. int NutTwiMasterRegRead( NUTTWIBUS *bus,
  493. uint8_t sla,
  494. uint32_t iadr, uint8_t iadrlen,
  495. void *rxdata, uint16_t rxsiz,
  496. uint32_t tmo )
  497. {
  498. int rc = -1;
  499. NUTTWIICB *icb = bus->bus_icb;
  500. // TPRINTF( "TMRR ");
  501. /* Quit if nothing to do */
  502. if( rxsiz == 0 ) {
  503. TPRINTF("! rxs=0... OUT\n");
  504. return rc;
  505. }
  506. /* This routine is marked reentrant, so lock the interface. */
  507. if( NutEventWait( &bus->bus_mutex, tmo ) ) {
  508. icb->tw_mm_error = TWERR_IF_LOCKED;
  509. TPRINTF("! LOCKED... OUT\n");
  510. return rc;
  511. }
  512. #if 0
  513. /* Check if bus is blocked for any reason */
  514. if (TwWaitBusFree( bus))
  515. {
  516. return rc;
  517. }
  518. #endif
  519. /* Clear errors. */
  520. icb->tw_mm_err = 0;
  521. /* fetch transfer parameters for current transaction */
  522. icb->tw_mm_sla = sla<<1;
  523. icb->tw_mm_iadrlen = iadrlen;
  524. if( iadrlen) {
  525. /* little-endian machine! */
  526. icb->tw_mm_iadr = ((uint8_t*)&iadr)+iadrlen-1;
  527. }
  528. icb->tw_mm_txbuf = NULL;
  529. icb->tw_mm_txlen = 0;
  530. icb->tw_mm_rxbuf = rxdata;
  531. icb->tw_mm_rxlen = rxsiz;
  532. icb->tw_mm_dir = MODE_WRITE;
  533. icb->tw_mm_err = 0;
  534. /* Issue start and wait till transmission completed */
  535. NutTwiStartRolling( bus, tmo);
  536. /* Check for errors that may have been detected
  537. * by the interrupt routine.
  538. */
  539. if( icb->tw_mm_err ) {
  540. icb->tw_mm_error = icb->tw_mm_err;
  541. rc = -1;
  542. TPRINTF( "! Error 0x%d\n", icb->tw_mm_err);
  543. /* Soft-Reset this Bus */
  544. // NutTwiSoftReset( bus);
  545. }
  546. else {
  547. rc = (int)(rxsiz - icb->tw_mm_rxlen);
  548. }
  549. /* Release the interface. */
  550. NutEventPost( &bus->bus_mutex );
  551. // TPRINTF( "* Bye rc=%d\n", rc);
  552. return rc;
  553. }
  554. /*!
  555. * \brief Transmit data as a master to a device having internal addressable registers
  556. *
  557. * The two-wire serial interface must have been initialized by calling
  558. * TwInit() before this function can be used.
  559. *
  560. * \param sla Slave address of the destination. This slave address
  561. * must be specified as a 7-bit address. For example, the
  562. * PCF8574A may be configured to slave addresses from 0x38
  563. * to 0x3F.
  564. * \param iadr Address send to the device to access certain registers
  565. * or memory addresses of it.
  566. * \param iadrlen Number of bytes to send as address, maximum 3 bytes are
  567. * supported from AT91SAM7
  568. * \param txdata Points to a buffer, where the data to transmit will be
  569. * stored.
  570. * \param txsiz Maximum number of bytes to transmit.
  571. * \param tmo Timeout in milliseconds. To disable timeout, set this
  572. * parameter to NUT_WAIT_INFINITE.
  573. *
  574. * \return The number of bytes transmitted, -1 in case of an error
  575. * or timeout. Number could be less if slave end transmission
  576. * with NAK.
  577. */
  578. int NutTwiMasterRegWrite( NUTTWIBUS *bus,
  579. uint8_t sla,
  580. uint32_t iadr, uint8_t iadrlen,
  581. const void *txdata, uint16_t txsiz,
  582. uint32_t tmo )
  583. {
  584. int rc = -1;
  585. NUTTWIICB *icb = bus->bus_icb;
  586. // TPRINTF( "TMRW ");
  587. /* Quit if nothing to do */
  588. if( txsiz==0) {
  589. TPRINTF("! txs=0... OUT\n");
  590. return rc;
  591. }
  592. /* This routine is marked reentrant, so lock the interface. */
  593. if( NutEventWait( &bus->bus_mutex, tmo ) ) {
  594. icb->tw_mm_error = TWERR_IF_LOCKED;
  595. TPRINTF("! mtx=LOCKED... OUT\n");
  596. return rc;
  597. }
  598. #if 0
  599. /* Check if bus is blocked for any reason */
  600. if (TwWaitBusFree( bus))
  601. {
  602. return rc;
  603. }
  604. #endif
  605. /* Clear errors. */
  606. icb->tw_mm_err = 0;
  607. /* fetch transfer parameters for current transaction */
  608. icb->tw_mm_sla = sla<<1;
  609. icb->tw_mm_iadrlen = iadrlen;
  610. if( iadrlen) {
  611. /* little-endian machine! */
  612. icb->tw_mm_iadr = ((uint8_t*)&iadr)+iadrlen-1;
  613. }
  614. icb->tw_mm_txbuf = (uint8_t*)txdata;
  615. icb->tw_mm_txlen = txsiz;
  616. icb->tw_mm_rxbuf = 0;
  617. icb->tw_mm_rxlen = 0;
  618. icb->tw_mm_dir = MODE_WRITE;
  619. icb->tw_mm_err = 0;
  620. /* Issue start and wait till transmission completed */
  621. NutTwiStartRolling( bus, tmo);
  622. /* Check for errors that may have been detected
  623. * by the interrupt routine.
  624. */
  625. if( icb->tw_mm_err ) {
  626. icb->tw_mm_error = icb->tw_mm_err;
  627. rc = -1;
  628. TPRINTF( "! Error 0x%d\n", icb->tw_mm_err);
  629. /* Soft-Reset this Bus */
  630. // NutTwiSoftReset( bus);
  631. }
  632. else {
  633. rc = (int)(txsiz - icb->tw_mm_txlen);
  634. }
  635. /* Release the interface. */
  636. NutEventPost( &bus->bus_mutex );
  637. // TPRINTF( "* Bye rc=%d\n", rc);
  638. return rc;
  639. }
  640. /*!
  641. * \brief Get last master mode error.
  642. *
  643. * You may call this function to determine the specific cause
  644. * of an error after twi transaction failed.
  645. *
  646. */
  647. int NutTwiMasterError(NUTTWIBUS *bus)
  648. {
  649. int rc = bus->bus_icb->tw_mm_error;
  650. bus->bus_icb->tw_mm_error = 0;
  651. return rc;
  652. }
  653. /*!
  654. * \brief Listen for incoming data from a master.
  655. *
  656. * If this function returns without error, the bus is blocked. The caller
  657. * must immediately process the request and return a response by calling
  658. * TwSlaveRespond().
  659. *
  660. * \note Slave mode is not implemented in the STM32 driver.
  661. * Thus the function always returns -1.
  662. *
  663. * \param sla Points to a byte variable, which receives the slave
  664. * address sent by the master. This can be used by the
  665. * caller to determine whether the the interface has been
  666. * addressed by a general call or its individual address.
  667. * \param rxdata Points to a data buffer where the received data bytes
  668. * are stored.
  669. * \param rxsiz Specifies the maximum number of data bytes to receive.
  670. * \param tmo Timeout in milliseconds. To disable timeout,
  671. * set this parameter to NUT_WAIT_INFINITE.
  672. *
  673. * \return The number of bytes received, -1 in case of an error or timeout.
  674. *
  675. */
  676. int NutTwiSlaveListen(NUTTWIBUS *bus, uint8_t *sla, void *rxdata, uint16_t rxsiz, uint32_t tmo)
  677. {
  678. return -1;
  679. }
  680. /*!
  681. * \brief Send response to a master.
  682. *
  683. * This function must be called as soon as possible after TwSlaveListen()
  684. * returned successfully, even if no data needs to be returned. Not doing
  685. * so will completely block the bus.
  686. *
  687. * \note Slave mode is not implemented in the STM32 driver.
  688. * Thus the function always returns -1.
  689. *
  690. * \param txdata Points to the data to transmit. Ignored, if the
  691. * number of bytes to transmit is zero.
  692. * \param txlen Number of data bytes to transmit.
  693. * \param tmo Timeout in milliseconds. To disable timeout,
  694. * set this parameter to NUT_WAIT_INFINITE.
  695. *
  696. * \return The number of bytes transmitted, -1 in case of an error or timeout.
  697. */
  698. extern int NutTwiSlaveRespond(NUTTWIBUS *bus, void *txdata, uint16_t txlen, uint32_t tmo)
  699. {
  700. return -1;
  701. }
  702. /*!
  703. * \brief Get last slave mode error.
  704. *
  705. * You may call this function to determine the specific cause
  706. * of an error after TwSlaveListen() or TwSlaveRespond() failed.
  707. *
  708. * \return Error code or 0 if no error occurred.
  709. *
  710. * \note Slave mode is not implemented in the STM32 driver.
  711. * Thus the function always returns TWERR_BUS.
  712. */
  713. extern int NutTwiSlaveError(NUTTWIBUS *bus)
  714. {
  715. return TWERR_BUS;
  716. }
  717. /*!
  718. * \brief Get last transfer results.
  719. *
  720. * \todo Do we really need this. It may not work with competing threads.
  721. * Answer: We really need this! It is bus dependand and is used by
  722. * EEPROM driver to determine the number of bytes transferred and
  723. * detection of EEPROM busy event (ACK-Polling).
  724. *
  725. * You may call this function to determine how many bytes where
  726. * transferred before the twi transaction failed.
  727. *
  728. */
  729. uint16_t NutTwiIndexes( NUTTWIBUS *bus, uint8_t idx )
  730. {
  731. NUTTWIICB *icb = bus->bus_icb;
  732. switch ( idx ) {
  733. case 0:
  734. return (uint16_t) icb->tw_mm_error;
  735. case 1:
  736. return (uint16_t) icb->tw_mm_rxlen;
  737. case 2:
  738. return (uint16_t) icb->tw_mm_txlen;
  739. default:
  740. return 0;
  741. }
  742. }
  743. /*!
  744. * \brief Set Speed of I2C Interface.
  745. *
  746. * Setup Interface Speed
  747. */
  748. int NutTwiSetSpeed( NUTTWIBUS *bus, uint32_t speed)
  749. {
  750. int rc = 0;
  751. register uint16_t ccr;
  752. I2C_TypeDef* I2Cx = (I2C_TypeDef*)bus->bus_base;
  753. uint32_t apbclk = NutClockGet(NUT_HWCLK_PCLK1);
  754. uint16_t frqrange = (uint16_t)(apbclk/1000000);
  755. uint16_t cr1 = I2Cx->CR1;
  756. /* Disable I2C peripheral */
  757. I2Cx->CR1 &= ~I2C_CR1_PE;
  758. /* sanity check */
  759. if( speed > 400000 ) {
  760. speed = 400000;
  761. rc = -1;
  762. }
  763. /* Configure speed in fast mode */
  764. if( speed > 100000 ) {
  765. /* calculate CCR value */
  766. ccr = (uint16_t)(apbclk/(speed*25));
  767. if( ccr == 0 ) {
  768. /* keep minimum allowed value */
  769. ccr = 0x0001;
  770. }
  771. /* Set DUTY bit and set F/S bit for fast mode */
  772. ccr |= (I2C_CCR_DUTY|I2C_CCR_FS);
  773. /* Set Maximum Rise Time for fast mode */
  774. I2Cx->TRISE = (uint16_t)(((frqrange*300)/1000)+1);
  775. }
  776. else {
  777. /* Standard mode speed calculate */
  778. ccr = (uint16_t)(apbclk/(speed<<1));
  779. /* Test if CCR value is under 0x4 */
  780. if( ccr < 4 ) {
  781. /* Set minimum allowed value */
  782. ccr = 4;
  783. }
  784. else if ( ccr > I2C_CCR_CCR ) {
  785. ccr = I2C_CCR_CCR;
  786. }
  787. /* Set Maximum Rise Time for standard mode */
  788. I2Cx->TRISE = frqrange+1;
  789. }
  790. /* Write CCR register */
  791. I2Cx->CCR = ccr;
  792. /* Restore the CR1 register */
  793. I2Cx->CR1 = cr1;
  794. return rc;
  795. }
  796. /*!
  797. * \brief Request Current Speed of I2C Interface.
  798. *
  799. */
  800. uint32_t NutTwiGetSpeed( NUTTWIBUS *bus)
  801. {
  802. uint32_t speed = 0;
  803. uint32_t ccr = 0;
  804. uint32_t apbclk = NutClockGet(NUT_HWCLK_PCLK1);
  805. I2C_TypeDef* I2Cx = (I2C_TypeDef*)bus->bus_base;
  806. ccr=I2Cx->CCR;
  807. if(ccr & I2C_CCR_FS) {
  808. /* High speed */
  809. speed=(int)(apbclk/(25UL*(ccr&I2C_CCR_CCR)));
  810. }
  811. else {
  812. /* Low speed */
  813. speed=(int)(apbclk/(2UL*(ccr&I2C_CCR_CCR)));
  814. }
  815. return speed;
  816. }
  817. /*!
  818. * \brief Perform TWI control functions.
  819. *
  820. * \param req Requested control function. May be set to one of the
  821. * following constants:
  822. * - TWI_SETSPEED, if conf points to an uint32_t value containing the bitrate.
  823. * - TWI_GETSPEED, if conf points to an uint32_t value receiving the current bitrate.
  824. * \param conf Points to a buffer that contains any data required for
  825. * the given control function or receives data from that
  826. * function.
  827. * \return 0 on success, -1 otherwise.
  828. *
  829. * \note Timeout is limited to the granularity of the system timer.
  830. *
  831. */
  832. int NutTwiIOCtl( NUTTWIBUS *bus, int req, void *conf )
  833. {
  834. int rc = 0;
  835. NUTTWIICB *icb = bus->bus_icb;
  836. switch (req)
  837. {
  838. case TWI_SETSPEED:
  839. NutTwiSetSpeed( bus, *(uint32_t*)conf);
  840. break;
  841. case TWI_GETSPEED:
  842. *(uint32_t*)conf = NutTwiGetSpeed( bus);
  843. break;
  844. case TWI_GETSTATUS:
  845. break;
  846. case TWI_SETSTATUS:
  847. break;
  848. case TWI_GETSLAVEADDRESS:
  849. // TODO: Slave handling
  850. icb->tw_mm_sla = *((uint16_t*)conf);
  851. break;
  852. case TWI_SETSLAVEADDRESS:
  853. // TODO: Slave handling
  854. *(uint32_t*)conf = (uint32_t)icb->tw_mm_sla;
  855. break;
  856. default:
  857. rc = -1;
  858. break;
  859. }
  860. return rc;
  861. }
  862. /*!
  863. * \brief Initialize TWI interface.
  864. *
  865. * The specified slave address is not used here as we don't support twi-slave
  866. * on this architecture for now.
  867. *
  868. * \note This function is only available on AT91SAM7xxxx systems.
  869. *
  870. * \param sla Slave address, must be specified as a 7-bit address,
  871. * always lower than 128.
  872. */
  873. int NutRegisterTwiBus( NUTTWIBUS *bus, uint8_t sla )
  874. {
  875. int rc = -1;
  876. uint32_t speed = 80000; /* Errata Doc 14574 Rev. 9 Chapter 2.11: Avoid 88kHz to 100kHz */
  877. // uint16_t tmpreg = 0;
  878. I2C_TypeDef* I2Cx = (I2C_TypeDef*)bus->bus_base;
  879. NUTTWIICB *icb = NULL;
  880. DBGP1_INIT();
  881. DBGP2_INIT();
  882. /* Check if bus was already registered */
  883. if( bus->bus_icb) {
  884. return 0;
  885. }
  886. /* Allocate ICB for this bus */
  887. icb = NutHeapAlloc(sizeof(NUTTWIICB));
  888. if( icb == NULL) {
  889. return rc;
  890. }
  891. memset( icb, 0, sizeof(NUTTWIICB));
  892. /* Link bus and ICB */
  893. bus->bus_icb = icb;
  894. if( NutRegisterIrqHandler( bus->bus_sig_ev, TwEventIrq, bus ) ) {
  895. free( icb);
  896. return rc;
  897. }
  898. if( NutRegisterIrqHandler( bus->bus_sig_er, TwErrorIrq, bus ) ) {
  899. free( icb);
  900. return rc;
  901. }
  902. /* Initialize GPIO Hardware */
  903. if( bus->bus_initbus != NULL) {
  904. rc = bus->bus_initbus();
  905. }
  906. if( rc) {
  907. return rc;
  908. }
  909. /* Disable and reset this bus */
  910. I2Cx->CR1 &= ~I2C_CR1_PE;
  911. I2Cx->CR1 |= I2C_CR1_SWRST;
  912. I2Cx->CR1 &= ~I2C_CR1_SWRST;
  913. #ifdef I2C_DEFAULT_SPEED
  914. if( bus->bus_base == I2C1_BASE)
  915. speed = I2CBUS1_DEFAULT_SPEED*1000UL;
  916. #endif
  917. #ifdef I2CBUS2_DEFAULT_SPEED
  918. if( bus->bus_base == I2C2_BASE)
  919. speed = I2CBUS2_DEFAULT_SPEED*1000UL;
  920. #endif
  921. /* Set initial rate. */
  922. if( (rc = NutTwiSetSpeed( bus, speed))) {
  923. return rc;
  924. }
  925. /* Setup 7-Bit Addressing Mode not acknowledged */
  926. I2Cx->OAR1 = 0x4000; /* FIXME: OAR1 Bit 14 is reserved */
  927. #if 0
  928. /* Setup CR1 */
  929. tmpreg = I2Cx->CR1;
  930. tmpreg &= ~(I2C_CR1_SMBUS|I2C_CR1_SMBTYPE|I2C_CR1_PEC);
  931. tmpreg |= I2C_CR1_ACK;
  932. // TODO: Set SMBTYPE and SMBUS bits
  933. I2Cx->CR1 = tmpreg;
  934. /* Setup Interrupts */
  935. tmpreg = I2Cx->CR2;
  936. tmpreg |= (I2C_CR2_ITBUFEN|I2C_CR2_ITEVTEN|I2C_CR2_ITERREN);
  937. I2Cx->CR2 = tmpreg;
  938. #endif
  939. I2Cx->CR2 = 0x0000;
  940. I2Cx->CR2 &= I2C_CR2_FREQ;
  941. I2Cx->CR2 |= (NutClockGet(NUT_HWCLK_PCLK1)/1000000);
  942. I2Cx->CR1 = I2C_CR1_PE;
  943. // TODO: Slave Address Setup
  944. NutIrqSetPriority(bus->bus_sig_ev, 0);
  945. rc = NutIrqEnable(bus->bus_sig_ev);
  946. if( rc) {
  947. return rc;
  948. }
  949. NutIrqSetPriority(bus->bus_sig_er, 1);
  950. rc = NutIrqEnable(bus->bus_sig_er);
  951. if( rc) {
  952. return rc;
  953. }
  954. /* Initialize mutex semaphores. */
  955. NutEventPost(&bus->bus_mutex);
  956. return rc;
  957. }
  958. /*@}*/