twi_at91.c
Go to the documentation of this file.00001
00040 #include "twi_at91.h"
00041
00042 #include "cfg/cfg_i2c.h"
00043 #include <cfg/compiler.h>
00044 #include <cfg/debug.h>
00045 #include <cfg/macros.h>
00046 #include <cfg/module.h>
00047
00048 #include <drv/timer.h>
00049
00050 #include <io/arm.h>
00051
00055 #define TWI_TIMEOUT ms_to_ticks(50)
00056
00067 bool twi_write(uint8_t id, twi_iaddr_t byte1, twi_iaddr_t byte2, twi_iaddr_t byte3, const void *_buf, size_t size)
00068 {
00069 uint8_t addr_size = 0;
00070 const uint8_t *buf = (const uint8_t *)_buf;
00071 ticks_t start;
00072
00073
00074 ASSERT(size >= 1);
00075
00076
00077 if (byte1 != TWI_NO_IADDR)
00078 addr_size++;
00079
00080 if (byte2 != TWI_NO_IADDR)
00081 {
00082 ASSERT(addr_size == 1);
00083 addr_size++;
00084 }
00085
00086 if (byte3 != TWI_NO_IADDR)
00087 {
00088 ASSERT(addr_size == 2);
00089 addr_size++;
00090 }
00091
00092 start = timer_clock();
00093
00094 while (!(TWI_SR & BV(TWI_TXRDY)))
00095 {
00096 if (timer_clock() - start > TWI_TIMEOUT)
00097 return false;
00098 }
00099
00100
00101 TWI_MMR = (uint32_t)id << TWI_DADR_SHIFT | (uint32_t)addr_size << TWI_IADRSZ_SHIFT;
00102
00103 TWI_IADR = ((uint32_t)(byte3 & 0xff) << 16) | ((uint32_t)(byte2 & 0xff) << 8) | ((uint32_t)(byte1 & 0xff));
00104
00105 while (size--)
00106 {
00107
00108 TWI_THR = *buf++;
00109
00110 start = timer_clock();
00111
00112 while (!(TWI_SR & BV(TWI_TXRDY)))
00113 {
00114 if (timer_clock() - start > TWI_TIMEOUT)
00115 return false;
00116 }
00117 }
00118
00119
00120 start = timer_clock();
00121 while (!(TWI_SR & BV(TWI_TXCOMP)))
00122 {
00123 if (timer_clock() - start > TWI_TIMEOUT)
00124 return false;
00125 }
00126
00127 return true;
00128 }
00129
00130
00141 bool twi_read(uint8_t id, twi_iaddr_t byte1, twi_iaddr_t byte2, twi_iaddr_t byte3, void *_buf, size_t size)
00142 {
00143 uint8_t addr_size = 0;
00144 uint8_t *buf = (uint8_t *)_buf;
00145 bool stopped = false;
00146 ticks_t start;
00147
00148
00149 ASSERT(size >= 1);
00150
00151
00152 if (byte1 != TWI_NO_IADDR)
00153 addr_size++;
00154
00155 if (byte2 != TWI_NO_IADDR)
00156 {
00157 ASSERT(addr_size == 1);
00158 addr_size++;
00159 }
00160
00161 if (byte3 != TWI_NO_IADDR)
00162 {
00163 ASSERT(addr_size == 2);
00164 addr_size++;
00165 }
00166
00167
00168 start = timer_clock();
00169 while (!(TWI_SR & BV(TWI_TXRDY)))
00170 {
00171 if (timer_clock() - start > TWI_TIMEOUT)
00172 return false;
00173 }
00174
00175
00176
00177 TWI_MMR = ((uint32_t)id << TWI_DADR_SHIFT) | BV(TWI_MREAD) | ((uint32_t)addr_size << TWI_IADRSZ_SHIFT);
00178
00179 TWI_IADR = ((uint32_t)(byte3 & 0xff) << 16) | ((uint32_t)(byte2 & 0xff) << 8) | ((uint32_t)(byte1 & 0xff));
00180
00181
00182
00183
00184
00185
00186 if (size == 1)
00187 {
00188 TWI_CR = BV(TWI_START) | BV(TWI_STOP);
00189 stopped = true;
00190 }
00191 else
00192 TWI_CR = BV(TWI_START);
00193
00194 while (size--)
00195 {
00196
00197
00198 if (!size && !stopped)
00199 TWI_CR = BV(TWI_STOP);
00200
00201
00202 start = timer_clock();
00203 while (!(TWI_SR & BV(TWI_RXRDY)))
00204 {
00205 if (timer_clock() - start > TWI_TIMEOUT)
00206 {
00207 TWI_CR = BV(TWI_STOP);
00208 return false;
00209 }
00210 }
00211
00212
00213 *buf++ = TWI_RHR;
00214 }
00215
00216
00217 start = timer_clock();
00218 while (!(TWI_SR & BV(TWI_TXCOMP)))
00219 {
00220 if (timer_clock() - start > TWI_TIMEOUT)
00221 return false;
00222 }
00223
00224 return true;
00225 }
00226
00227 MOD_DEFINE(twi);
00228
00232 void twi_init(void)
00233 {
00234
00235 PIOA_PDR = BV(TWD) | BV(TWCK);
00236
00237
00238 PIOA_MDER = BV(TWD);
00239
00240
00241 TWI_IDR = 0xFFFFFFFF;
00242
00243 TWI_CR = BV(TWI_SWRST);
00244
00245
00246 TWI_CR = BV(TWI_MSEN);
00247
00248 PMC_PCER = BV(TWI_ID);
00249
00250
00251
00252
00253
00254
00255
00256 uint16_t cldiv, ckdiv = 0;
00257 while ((cldiv = ((CPU_FREQ / (2 * CONFIG_I2C_FREQ)) - 3) / (1 << ckdiv)) > 255)
00258 ckdiv++;
00259
00260
00261 ASSERT(ckdiv < 5);
00262
00263 TWI_CWGR = ((uint32_t)ckdiv << TWI_CKDIV_SHIFT) | (cldiv << TWI_CLDIV_SHIFT) | (cldiv << TWI_CHDIV_SHIFT);
00264 TRACEMSG("TWI_CWGR [%08lx]", TWI_CWGR);
00265
00266 MOD_INIT(twi);
00267 }
00268