4 * This file is part of BeRTOS.
6 * Bertos is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 * As a special exception, you may use this file as part of a free software
21 * library without restriction. Specifically, if other files instantiate
22 * templates or use macros or inline functions from this file, or you compile
23 * this file and link it with other files to produce an executable, this
24 * file does not by itself cause the resulting executable to be covered by
25 * the GNU General Public License. This exception does not however
26 * invalidate any other reasons why the executable file might be covered by
27 * the GNU General Public License.
29 * Copyright 2008 Develer S.r.l. (http://www.develer.com/)
33 * \brief Driver for the AT91 ARM TWI (implementation)
36 * \author Francesco Sacchi <batt@develer.com>
41 #include "cfg/cfg_i2c.h"
42 #include <cfg/compiler.h>
43 #include <cfg/debug.h>
44 #include <cfg/macros.h>
45 #include <cfg/module.h>
47 #include <drv/timer.h>
52 * Timeout for ACK slave waiting.
54 #define TWI_TIMEOUT ms_to_ticks(50)
57 * Send \a size bytes over the twi line to slave \a id.
58 * If the device requires internal addressing before writing, \a byte1 \a byte2 and \a byte3 can
59 * be specified. Internal addressign bytes not used *must* be set to TWI_NO_IADDR. If 1 or 2 bytes
60 * are required for internal addressing you *must* first use \a byte1 and than \a byte2.
61 * \note Atmel TWI implementation is broken so it was not possible to supply a better
62 * interface. Additionally NACK handling is also broken, so if the i2c device reply nack
63 * this function will return after TWI_TIMEOUT.
64 * \return true if ok, false on slave timeout.
66 bool twi_write(uint8_t id, twi_iaddr_t byte1, twi_iaddr_t byte2, twi_iaddr_t byte3, const void *_buf, size_t size)
68 uint8_t addr_size = 0;
69 const uint8_t *buf = (const uint8_t *)_buf;
72 /* At least 1 byte *must* be transmitted, thanks to crappy hw implementation */
75 /* Check internal byte address presence */
76 if (byte1 != TWI_NO_IADDR)
79 if (byte2 != TWI_NO_IADDR)
81 ASSERT(addr_size == 1);
85 if (byte3 != TWI_NO_IADDR)
87 ASSERT(addr_size == 2);
91 start = timer_clock();
92 /* Wait tx buffer empty */
93 while (!(TWI_SR & BV(TWI_TXRDY)))
95 if (timer_clock() - start > TWI_TIMEOUT)
99 /* Set slave address and (optional) internal slave addresses */
100 TWI_MMR = (uint32_t)id << TWI_DADR_SHIFT | (uint32_t)addr_size << TWI_IADRSZ_SHIFT;
102 TWI_IADR = ((uint32_t)(byte3 & 0xff) << 16) | ((uint32_t)(byte2 & 0xff) << 8) | ((uint32_t)(byte1 & 0xff));
109 start = timer_clock();
110 /* Wait tx buffer empty */
111 while (!(TWI_SR & BV(TWI_TXRDY)))
113 if (timer_clock() - start > TWI_TIMEOUT)
118 /* Wait transmit complete bit */
119 start = timer_clock();
120 while (!(TWI_SR & BV(TWI_TXCOMP)))
122 if (timer_clock() - start > TWI_TIMEOUT)
131 * Read \a size bytes from the twi line from slave \a id.
132 * If the device requires internal addressing before reading, \a byte1 \a byte2 and \a byte3 must
133 * be specified. Internal addressign bytes not used *must* be set to TWI_NO_IADDR. If 1 or 2 bytes
134 * are required for internal addressing you *must* first use \a byte1 and than \a byte2.
135 * \note Atmel TWI implementation is broken so it was not possible to supply a better
136 * interface. Additionally NACK handling is also broken, so if the i2c device reply nack
137 * this function will return after TWI_TIMEOUT.
138 * \return true if ok, false on slave timeout.
140 bool twi_read(uint8_t id, twi_iaddr_t byte1, twi_iaddr_t byte2, twi_iaddr_t byte3, void *_buf, size_t size)
142 uint8_t addr_size = 0;
143 uint8_t *buf = (uint8_t *)_buf;
144 bool stopped = false;
147 /* At least 1 byte *must* be transmitted, thanks to crappy twi implementation */
150 /* Check internal byte address presence */
151 if (byte1 != TWI_NO_IADDR)
154 if (byte2 != TWI_NO_IADDR)
156 ASSERT(addr_size == 1);
160 if (byte3 != TWI_NO_IADDR)
162 ASSERT(addr_size == 2);
166 /* Wait tx buffer empty */
167 start = timer_clock();
168 while (!(TWI_SR & BV(TWI_TXRDY)))
170 if (timer_clock() - start > TWI_TIMEOUT)
175 /* Set slave address and (optional) internal slave addresses */
176 TWI_MMR = ((uint32_t)id << TWI_DADR_SHIFT) | BV(TWI_MREAD) | ((uint32_t)addr_size << TWI_IADRSZ_SHIFT);
178 TWI_IADR = ((uint32_t)(byte3 & 0xff) << 16) | ((uint32_t)(byte2 & 0xff) << 8) | ((uint32_t)(byte1 & 0xff));
182 * Kludge: if we want to receive only 1 byte, the stop but *must* be set here
183 * (thanks to crappy twi implementation again).
187 TWI_CR = BV(TWI_START) | BV(TWI_STOP);
191 TWI_CR = BV(TWI_START);
195 /* If we are at the last byte, inform the crappy hw that we
196 want to stop the reception. */
197 if (!size && !stopped)
198 TWI_CR = BV(TWI_STOP);
200 /* Wait until a byte is received */
201 start = timer_clock();
202 while (!(TWI_SR & BV(TWI_RXRDY)))
204 if (timer_clock() - start > TWI_TIMEOUT)
206 TWI_CR = BV(TWI_STOP);
215 /* Wait transmit complete bit */
216 start = timer_clock();
217 while (!(TWI_SR & BV(TWI_TXCOMP)))
219 if (timer_clock() - start > TWI_TIMEOUT)
229 * Init the (broken) sam7 twi driver.
233 /* Disable PIO on TWI pins */
234 PIOA_PDR = BV(TWD) | BV(TWCK);
236 /* Enable oper drain on TWI pins */
239 /* Disable all irqs */
240 TWI_IDR = 0xFFFFFFFF;
242 TWI_CR = BV(TWI_SWRST);
244 /* Enable master mode */
245 TWI_CR = BV(TWI_MSEN);
247 PMC_PCER = BV(TWI_ID);
251 * CLDIV = ((Tlow * 2^CKDIV) -3) * Tmck
252 * CHDIV = ((THigh * 2^CKDIV) -3) * Tmck
253 * Only CLDIV is computed since CLDIV = CHDIV (50% duty cycle)
255 uint16_t cldiv, ckdiv = 0;
256 while ((cldiv = ((CPU_FREQ / (2 * CONFIG_I2C_FREQ)) - 3) / (1 << ckdiv)) > 255)
259 /* Atmel errata states that ckdiv *must* be less than 5 for unknown reason */
262 TWI_CWGR = ((uint32_t)ckdiv << TWI_CKDIV_SHIFT) | (cldiv << TWI_CLDIV_SHIFT) | (cldiv << TWI_CHDIV_SHIFT);
263 TRACEMSG("TWI_CWGR [%08lx]", TWI_CWGR);