i2c_lm3s.c
Go to the documentation of this file.00001
00039 #include "cfg/cfg_i2c.h"
00040
00041 #define LOG_LEVEL I2C_LOG_LEVEL
00042 #define LOG_FORMAT I2C_LOG_FORMAT
00043
00044 #include <cfg/log.h>
00045
00046 #include <cfg/debug.h>
00047 #include <cfg/macros.h>
00048
00049 #include <cpu/detect.h>
00050 #include <cpu/irq.h>
00051 #include <cpu/types.h>
00052 #include <cpu/power.h>
00053
00054 #include <io/lm3s.h>
00055
00056 #include <drv/timer.h>
00057 #include <drv/i2c.h>
00058 #include <drv/gpio_lm3s.h>
00059 #include <drv/clock_lm3s.h>
00060
00061
00062 struct I2cHardware
00063 {
00064 uint32_t base;
00065 uint32_t sys_cntl;
00066 uint32_t sys_gpio;
00067 uint32_t pin_mask;
00068 uint32_t gpio_base;
00069 bool first_xtranf;
00070 };
00071
00072 #define WAIT_BUSY(base) \
00073 do { \
00074 while (HWREG(base + I2C_O_MCS) & I2C_MCS_BUSY ) \
00075 cpu_relax(); \
00076 } while (0);
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089 static void i2c_lm3s_start(struct I2c *i2c, uint16_t slave_addr)
00090 {
00091 i2c->hw->first_xtranf = true;
00092
00093 if (I2C_TEST_START(i2c->flags) == I2C_START_W)
00094 HWREG(i2c->hw->base + I2C_O_MSA) = slave_addr & ~BV(0);
00095 else
00096 HWREG(i2c->hw->base + I2C_O_MSA) = slave_addr | BV(0);
00097 }
00098
00099 INLINE bool wait_addrAck(I2c *i2c, uint32_t mode_mask)
00100 {
00101 ticks_t start = timer_clock();
00102 while (1)
00103 {
00104 uint32_t status = HWREG(i2c->hw->base + I2C_O_MCS);
00105
00106 if (timer_clock() - start > ms_to_ticks(CONFIG_I2C_START_TIMEOUT))
00107 return false;
00108
00109 if(status & I2C_MCS_ADRACK)
00110 {
00111 HWREG(i2c->hw->base + I2C_O_MCS) = mode_mask;
00112 WAIT_BUSY(i2c->hw->base);
00113 }
00114 else
00115 break;
00116
00117 cpu_relax();
00118 }
00119 return true;
00120 }
00121
00122 static void i2c_lm3s_putc(I2c *i2c, const uint8_t data)
00123 {
00124 HWREG(i2c->hw->base + I2C_O_MDR) = data;
00125
00126 if (i2c->hw->first_xtranf)
00127 {
00128 HWREG(i2c->hw->base + I2C_O_MCS) = I2C_MCS_RUN | I2C_MCS_START;
00129 while( HWREG(i2c->hw->base + I2C_O_MCS) & I2C_MCS_BUSY );
00130
00131 if (!wait_addrAck(i2c, I2C_MCS_RUN | I2C_MCS_START))
00132 {
00133 LOG_ERR("Start timeout\n");
00134 i2c->errors |= I2C_START_TIMEOUT;
00135 HWREG(i2c->hw->base + I2C_O_MCS) = I2C_MCS_STOP;
00136 WAIT_BUSY(i2c->hw->base);
00137 return;
00138 }
00139
00140 i2c->hw->first_xtranf = false;
00141 }
00142 else
00143 {
00144 HWREG(i2c->hw->base + I2C_O_MCS) = I2C_MCS_RUN;
00145 WAIT_BUSY(i2c->hw->base);
00146 }
00147
00148 if ((i2c->xfer_size == 1) && (I2C_TEST_STOP(i2c->flags) == I2C_STOP))
00149 {
00150 HWREG(i2c->hw->base + I2C_O_MCS) = I2C_MCS_STOP;
00151 WAIT_BUSY(i2c->hw->base);
00152 }
00153 }
00154
00155 static uint8_t i2c_lm3s_getc(I2c *i2c)
00156 {
00157 uint8_t data;
00158 if (i2c->hw->first_xtranf)
00159 {
00160 uint32_t start_mode;
00161 if (i2c->xfer_size == 1)
00162 start_mode = I2C_MCS_RUN | I2C_MCS_START;
00163 else
00164 start_mode = I2C_MCS_ACK | I2C_MCS_RUN | I2C_MCS_START;
00165
00166 HWREG(i2c->hw->base + I2C_O_MCS) = start_mode;
00167 WAIT_BUSY(i2c->hw->base);
00168 if (!wait_addrAck(i2c, start_mode))
00169 {
00170 LOG_ERR("Start timeout\n");
00171 i2c->errors |= I2C_START_TIMEOUT;
00172 HWREG(i2c->hw->base + I2C_O_MCS) = I2C_MCS_STOP;
00173 WAIT_BUSY(i2c->hw->base);
00174 return 0xFF;
00175 }
00176
00177 data = HWREG(i2c->hw->base + I2C_O_MDR);
00178 i2c->hw->first_xtranf = false;
00179 }
00180 else
00181 {
00182 if (i2c->xfer_size > 1)
00183 HWREG(i2c->hw->base + I2C_O_MCS) = I2C_MCS_ACK | I2C_MCS_RUN;
00184 else
00185 HWREG(i2c->hw->base + I2C_O_MCS) = I2C_MCS_RUN;
00186
00187 WAIT_BUSY(i2c->hw->base);
00188 data = HWREG(i2c->hw->base + I2C_O_MDR);
00189 }
00190
00191 if ((i2c->xfer_size == 1) && (I2C_TEST_STOP(i2c->flags) == I2C_STOP))
00192 {
00193 HWREG(i2c->hw->base + I2C_O_MCS) = I2C_MCS_STOP;
00194 WAIT_BUSY(i2c->hw->base);
00195 }
00196 return data;
00197 }
00198
00199 static const I2cVT i2c_lm3s_vt =
00200 {
00201 .start = i2c_lm3s_start,
00202 .getc = i2c_lm3s_getc,
00203 .putc = i2c_lm3s_putc,
00204 .write = i2c_genericWrite,
00205 .read = i2c_genericRead,
00206 };
00207
00208 static struct I2cHardware i2c_lm3s_hw[] =
00209 {
00210 {
00211 .base = I2C0_MASTER_BASE,
00212 .sys_cntl = SYSCTL_RCGC1_I2C0,
00213 .sys_gpio = SYSCTL_RCGC2_GPIOB,
00214 .pin_mask = (GPIO_I2C0_SCL_PIN | GPIO_I2C0_SDA_PIN),
00215 .gpio_base = GPIO_PORTB_BASE,
00216 },
00217 {
00218 .base = I2C1_MASTER_BASE,
00219 .sys_cntl = SYSCTL_RCGC1_I2C1,
00220 .sys_gpio = SYSCTL_RCGC2_GPIOA,
00221 .pin_mask = (GPIO_I2C1_SCL_PIN | GPIO_I2C1_SDA_PIN),
00222 .gpio_base = GPIO_PORTA_BASE,
00223 },
00224 };
00225
00229 void i2c_hw_init(I2c *i2c, int dev, uint32_t clock)
00230 {
00231 i2c->hw = &i2c_lm3s_hw[dev];
00232 i2c->vt = &i2c_lm3s_vt;
00233
00234
00235 SYSCTL_RCGC1_R |= i2c->hw->sys_cntl;
00236 SYSCTL_RCGC2_R |= i2c->hw->sys_gpio;
00237
00238
00239 lm3s_gpioPinConfig(i2c->hw->gpio_base, i2c->hw->pin_mask,
00240 GPIO_DIR_MODE_HW, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_OD_WPU);
00241
00242
00243
00244
00245
00246
00247 HWREG(i2c->hw->base + I2C_O_MCR) |= I2C_MCR_MFE;
00248
00249
00250
00251
00252
00253
00254
00255 HWREG(i2c->hw->base + I2C_O_MTPR) = ((CPU_FREQ + (2 * 10 * clock) - 1) / (2 * 10 * clock)) - 1;
00256 }