i2c_lpc2.c
Go to the documentation of this file.00001
00038 #include "cfg/cfg_i2c.h"
00039
00040 #define LOG_LEVEL I2C_LOG_LEVEL
00041 #define LOG_FORMAT I2C_LOG_FORMAT
00042
00043 #include <cfg/log.h>
00044
00045 #include <cfg/debug.h>
00046 #include <cfg/macros.h>
00047
00048 #include <cpu/detect.h>
00049 #include <cpu/irq.h>
00050 #include <cpu/power.h>
00051
00052 #include <drv/timer.h>
00053 #include <drv/i2c.h>
00054
00055 #include <io/lpc23xx.h>
00056
00057 struct I2cHardware
00058 {
00059 uint32_t base;
00060 uint32_t pconp;
00061 uint32_t pinsel_port;
00062 uint32_t pinsel;
00063 uint32_t pinsel_mask;
00064 uint32_t pclksel;
00065 uint32_t pclk_mask;
00066 uint32_t pclk_div;
00067 };
00068
00069
00070
00071
00072
00073
00074
00075
00076 #define WAIT_SI(i2c) \
00077 do { \
00078 ticks_t start = timer_clock(); \
00079 while( !(HWREG(i2c->hw->base + I2C_CONSET_OFF) & BV(I2CON_SI)) ) \
00080 { \
00081 if (timer_clock() - start > ms_to_ticks(CONFIG_I2C_START_TIMEOUT)) \
00082 { \
00083 LOG_ERR("Timeout SI assert\n"); \
00084 LOG_ERR("[%08lx]\n", HWREG(i2c->hw->base + I2C_STAT_OFF)); \
00085 break; \
00086 } \
00087 cpu_relax(); \
00088 } \
00089 } while (0)
00090
00091 static void i2c_hw_restart(I2c *i2c)
00092 {
00093
00094 HWREG(i2c->hw->base + I2C_CONCLR_OFF) = BV(I2CON_STAC) | BV(I2CON_SIC) | BV(I2CON_AAC);
00095
00096
00097 HWREG(i2c->hw->base + I2C_CONSET_OFF) = BV(I2CON_STA);
00098
00099 WAIT_SI(i2c);
00100 }
00101
00102
00103 static void i2c_hw_stop(I2c *i2c)
00104 {
00105
00106 HWREG(i2c->hw->base + I2C_CONSET_OFF) = BV(I2CON_STO);
00107
00108 HWREG(i2c->hw->base + I2C_CONCLR_OFF) = BV(I2CON_STAC) | BV(I2CON_SIC) | BV(I2CON_AAC);
00109 }
00110
00111 static void i2c_lpc2_putc(I2c *i2c, uint8_t data)
00112 {
00113 HWREG(i2c->hw->base + I2C_DAT_OFF) = data;
00114 HWREG(i2c->hw->base + I2C_CONCLR_OFF) = BV(I2CON_SIC);
00115
00116 WAIT_SI(i2c);
00117
00118 uint32_t status = HWREG(i2c->hw->base + I2C_STAT_OFF);
00119
00120
00121
00122 if (i2c->xfer_size == 1)
00123 {
00124 if (I2C_TEST_STOP(i2c->flags) == I2C_STOP)
00125 i2c_hw_stop(i2c);
00126 }
00127
00128 if (status == I2C_STAT_DATA_NACK)
00129 {
00130 LOG_ERR("Data NACK\n");
00131 i2c->errors |= I2C_NO_ACK;
00132 i2c_hw_stop(i2c);
00133 }
00134 else if ((status == I2C_STAT_ERROR) || (status == I2C_STAT_UNKNOW))
00135 {
00136 LOG_ERR("I2C error.\n");
00137 i2c->errors |= I2C_ERR;
00138 i2c_hw_stop(i2c);
00139 }
00140 }
00141
00142 static uint8_t i2c_lpc2_getc(I2c *i2c)
00143 {
00144
00145
00146
00147
00148 if (i2c->xfer_size > 1)
00149 HWREG(i2c->hw->base + I2C_CONSET_OFF) = BV(I2CON_AA);
00150 else
00151 HWREG(i2c->hw->base + I2C_CONCLR_OFF) = BV(I2CON_AAC);
00152
00153 HWREG(i2c->hw->base + I2C_CONCLR_OFF) = BV(I2CON_SIC);
00154
00155 WAIT_SI(i2c);
00156
00157 uint32_t status = HWREG(i2c->hw->base + I2C_STAT_OFF);
00158 uint8_t data = (uint8_t)HWREG(i2c->hw->base + I2C_DAT_OFF);
00159
00160 if (status == I2C_STAT_RDATA_ACK)
00161 {
00162 return data;
00163 }
00164 else if (status == I2C_STAT_RDATA_NACK)
00165 {
00166
00167
00168
00169
00170 if (I2C_TEST_STOP(i2c->flags) == I2C_STOP)
00171 i2c_hw_stop(i2c);
00172
00173 return data;
00174 }
00175 else if ((status == I2C_STAT_ERROR) || (status == I2C_STAT_UNKNOW))
00176 {
00177 LOG_ERR("I2C error.\n");
00178 i2c->errors |= I2C_ERR;
00179 i2c_hw_stop(i2c);
00180 }
00181
00182 return 0xFF;
00183 }
00184
00185 static void i2c_lpc2_start(struct I2c *i2c, uint16_t slave_addr)
00186 {
00187 if (I2C_TEST_START(i2c->flags) == I2C_START_W)
00188 {
00189 ticks_t start = timer_clock();
00190 while (true)
00191 {
00192 i2c_hw_restart(i2c);
00193
00194 uint8_t status = HWREG(i2c->hw->base + I2C_STAT_OFF);
00195
00196
00197 if ((status == I2C_STAT_SEND) || (status == I2C_STAT_RESEND))
00198 HWREG(i2c->hw->base + I2C_DAT_OFF) = slave_addr & ~I2C_READBIT;
00199
00200
00201 HWREG(i2c->hw->base + I2C_CONCLR_OFF) = BV(I2CON_SIC) | BV(I2CON_STAC);
00202
00203 if (status == I2C_STAT_SLAW_ACK)
00204 break;
00205
00206 if (status == I2C_STAT_ARB_LOST)
00207 {
00208 LOG_ERR("Arbitration lost\n");
00209 i2c->errors |= I2C_ARB_LOST;
00210 i2c_hw_stop(i2c);
00211 }
00212
00213 if (timer_clock() - start > ms_to_ticks(CONFIG_I2C_START_TIMEOUT))
00214 {
00215 LOG_ERR("Timeout on I2C START\n");
00216 i2c->errors |= I2C_NO_ACK;
00217 i2c_hw_stop(i2c);
00218 break;
00219 }
00220 }
00221 }
00222 else if (I2C_TEST_START(i2c->flags) == I2C_START_R)
00223 {
00224 i2c_hw_restart(i2c);
00225
00226 uint8_t status = HWREG(i2c->hw->base + I2C_STAT_OFF);
00227
00228
00229 if ((status == I2C_STAT_SEND) || (status == I2C_STAT_RESEND))
00230 HWREG(i2c->hw->base + I2C_DAT_OFF) = slave_addr | I2C_READBIT;
00231
00232
00233 HWREG(i2c->hw->base + I2C_CONCLR_OFF) = BV(I2CON_SIC) | BV(I2CON_STAC);
00234
00235 WAIT_SI(i2c);
00236
00237 status = HWREG(i2c->hw->base + I2C_STAT_OFF);
00238
00239 if (status == I2C_STAT_SLAR_NACK)
00240 {
00241 LOG_ERR("SLAR NACK:%02x\n", status);
00242 i2c->errors |= I2C_NO_ACK;
00243 i2c_hw_stop(i2c);
00244 }
00245
00246 if (status == I2C_STAT_ARB_LOST)
00247 {
00248 LOG_ERR("Arbitration lost\n");
00249 i2c->errors |= I2C_ARB_LOST;
00250 i2c_hw_stop(i2c);
00251 }
00252 }
00253 else
00254 {
00255 ASSERT(0);
00256 }
00257 }
00258
00259 static const I2cVT i2c_lpc_vt =
00260 {
00261 .start = i2c_lpc2_start,
00262 .getc = i2c_lpc2_getc,
00263 .putc = i2c_lpc2_putc,
00264 .write = i2c_genericWrite,
00265 .read = i2c_genericRead,
00266 };
00267
00268 static struct I2cHardware i2c_lpc2_hw[] =
00269 {
00270 {
00271 .base = I2C0_BASE_ADDR,
00272 .pconp = BV(PCONP_PCI2C0),
00273 .pinsel_port = PINSEL1_OFF,
00274 .pinsel = I2C0_PINSEL,
00275 .pinsel_mask = I2C0_PINSEL_MASK,
00276 .pclksel = PCLKSEL0_OFF,
00277 .pclk_mask = I2C0_PCLK_MASK,
00278 .pclk_div = I2C0_PCLK_DIV8,
00279 },
00280 {
00281 .base = I2C1_BASE_ADDR,
00282 .pconp = BV(PCONP_PCI2C1),
00283 .pinsel_port = PINSEL0_OFF,
00284 .pinsel = I2C1_PINSEL,
00285 .pinsel_mask = I2C1_PINSEL_MASK,
00286 .pclksel = PCLKSEL1_OFF,
00287 .pclk_mask = I2C1_PCLK_MASK,
00288 .pclk_div = I2C1_PCLK_DIV8,
00289 },
00290 {
00291 .base = I2C2_BASE_ADDR,
00292 .pconp = BV(PCONP_PCI2C2),
00293 .pinsel_port = PINSEL0_OFF,
00294 .pinsel = I2C2_PINSEL,
00295 .pinsel_mask = I2C2_PINSEL_MASK,
00296 .pclksel = PCLKSEL1_OFF,
00297 .pclk_mask = I2C2_PCLK_MASK,
00298 .pclk_div = I2C2_PCLK_DIV8,
00299 },
00300 };
00301
00305 void i2c_hw_init(I2c *i2c, int dev, uint32_t clock)
00306 {
00307 i2c->hw = &i2c_lpc2_hw[dev];
00308 i2c->vt = &i2c_lpc_vt;
00309
00310
00311 PCONP |= i2c->hw->pconp;
00312
00313 ASSERT(clock <= 400000);
00314
00315 HWREG(i2c->hw->base + I2C_CONCLR_OFF) = BV(I2CON_I2ENC) | BV(I2CON_STAC) | BV(I2CON_SIC) | BV(I2CON_AAC);
00316
00317
00318
00319
00320
00321 HWREG(SCB_BASE_ADDR + i2c->hw->pclksel) &= ~i2c->hw->pclk_mask;
00322 HWREG(SCB_BASE_ADDR + i2c->hw->pclksel) |= i2c->hw->pclk_div;
00323
00324 HWREG(i2c->hw->base + I2C_SCLH_OFF) = (((CPU_FREQ / 8) / clock) / 2) + 1;
00325 HWREG(i2c->hw->base + I2C_SCLL_OFF) = (((CPU_FREQ / 8) / clock) / 2);
00326
00327 ASSERT(HWREG(i2c->hw->base + I2C_SCLH_OFF) > 4);
00328 ASSERT(HWREG(i2c->hw->base + I2C_SCLL_OFF) > 4);
00329
00330
00331 HWREG(PINSEL_BASE_ADDR + i2c->hw->pinsel_port) &= ~i2c->hw->pinsel_mask;
00332 HWREG(PINSEL_BASE_ADDR + i2c->hw->pinsel_port) |= i2c->hw->pinsel;
00333
00334
00335 HWREG(i2c->hw->base + I2C_CONSET_OFF) = BV(I2CON_I2EN);
00336 }