BeRTOS
|
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> // BV() 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 * The start is not performed when we call the start function 00081 * because the hardware should know the first data byte to send. 00082 * Generally to perform a byte send we should write the slave address 00083 * in slave address register and the first byte to send in data registry. 00084 * After then we can perform the start write procedure, and send really 00085 * the our data. To use common bertos i2c api the really start will be 00086 * performed when the user "put" or "send" its data. These tricks are hide 00087 * from the driver implementation. 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 /* (I2C_TEST_START(i2c->flags) == I2C_START_R) */ 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 { /* I2C0 */ 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 { /* I2C1 */ 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 /* Enable the peripheral clock */ 00235 SYSCTL_RCGC1_R |= i2c->hw->sys_cntl; 00236 SYSCTL_RCGC2_R |= i2c->hw->sys_gpio; 00237 00238 /* Configure GPIO pins to work as I2C pins */ 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 * Note: to set correctly the i2c speed we shold before enable the i2c 00243 * device and then set in master time period the correct value 00244 */ 00245 00246 /* Enable i2c device */ 00247 HWREG(i2c->hw->base + I2C_O_MCR) |= I2C_MCR_MFE; 00248 00249 /* 00250 * Compute the clock divider that achieves the fastest speed less than or 00251 * equal to the desired speed. The numerator is biased to favor a larger 00252 * clock divider so that the resulting clock is always less than or equal 00253 * to the desired clock, never greater. 00254 */ 00255 HWREG(i2c->hw->base + I2C_O_MTPR) = ((CPU_FREQ + (2 * 10 * clock) - 1) / (2 * 10 * clock)) - 1; 00256 }