void I2C_Master_init(void) { //- Enable TWI1 Clock (TWI1 clock ID = TWI1 vector ID = 20) PMC->PMC_PCDR0 |= PMC_PCDR0_PID20 ; //- Reset TWI TWI1->TWI_CR |= TWI_CR_SWRST; //- Set TWI timings TWI1->TWI_CWGR = (TWI_CWGR_CHDIV(0)|TWI_CWGR_CHDIV(0)|TWI_CWGR_CLDIV(0)); //- Set TWI as Master TWI1->TWI_CR |= (TWI_CR_SVDIS|TWI_CR_MSEN); }
static int i2c_clk_set(Twi *const twi, u32_t speed) { u32_t ck_div = 0; u32_t cl_div; bool div_completed = false; /* From the datasheet "TWI Clock Waveform Generator Register" * T_low = ( ( CLDIV × 2^CKDIV ) + 4 ) × T_MCK */ while (!div_completed) { cl_div = ((SOC_ATMEL_SAM_MCK_FREQ_HZ / (2 * speed)) - 4) / (1 << ck_div); if (cl_div <= 255) { div_completed = true; } else { ck_div++; } } if (ck_div > CKDIV_MAX) { LOG_ERR("Failed to configure I2C clock"); return -EIO; } /* Set TWI clock duty cycle to 50% */ twi->TWI_CWGR = TWI_CWGR_CLDIV(cl_div) | TWI_CWGR_CHDIV(cl_div) | TWI_CWGR_CKDIV(ck_div); return 0; }
/** * \brief Set the I2C bus speed in conjunction with the clock frequency. * * \param p_twi Pointer to a TWI instance. * \param ul_speed The desired I2C bus speed (in Hz). * \param ul_mck Main clock of the device (in Hz). * * \retval PASS New speed setting is accepted. * \retval FAIL New speed setting is rejected. */ uint32_t twi_set_speed(Twi *p_twi, uint32_t ul_speed, uint32_t ul_mck) { uint32_t ckdiv = 0; uint32_t c_lh_div; if (ul_speed > I2C_FAST_MODE_SPEED) { return FAIL; } c_lh_div = ul_mck / (ul_speed * TWI_CLK_DIVIDER) - TWI_CLK_CALC_ARGU; /* cldiv must fit in 8 bits, ckdiv must fit in 3 bits */ while ((c_lh_div > TWI_CLK_DIV_MAX) && (ckdiv < TWI_CLK_DIV_MIN)) { /* Increase clock divider */ ckdiv++; /* Divide cldiv value */ c_lh_div /= TWI_CLK_DIVIDER; } /* set clock waveform generator register */ p_twi->TWI_CWGR = TWI_CWGR_CLDIV(c_lh_div) | TWI_CWGR_CHDIV(c_lh_div) | TWI_CWGR_CKDIV(ckdiv); return PASS; }
void config_twi(void) { //enable peripheral clock for TWI0 PMC->PMC_PCER0 = PMC_PCER0_PID17; //Set clock divider (slow for now, probably never necessary to increase) uint32_t t_high = (uint32_t)(60*TWI_CLK_HIGH_T - 2); uint32_t t_low = (uint32_t)(60*TWI_CLK_LOW_T - 2); TWI0->TWI_CWGR = TWI_CWGR_CHDIV(t_high) | TWI_CWGR_CKDIV(1) | TWI_CWGR_CLDIV(t_low); //enable master mode; disable slave mode TWI0->TWI_CR = TWI_CR_MSEN | TWI_CR_SVDIS; return; }
static int at91_twi_attach(device_t dev) { struct at91_twi_softc *sc = device_get_softc(dev); int err; sc->dev = dev; err = at91_twi_activate(dev); if (err) goto out; AT91_TWI_LOCK_INIT(sc); #ifdef FDT /* * Disable devices need to hold their resources, so return now and not attach * the iicbus, setup interrupt handlers, etc. */ if (!ofw_bus_status_okay(dev)) return 0; #endif /* * Activate the interrupt */ err = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC | INTR_MPSAFE, NULL, at91_twi_intr, sc, &sc->intrhand); if (err) { AT91_TWI_LOCK_DESTROY(sc); goto out; } sc->cwgr = TWI_CWGR_CKDIV(8 * at91_master_clock / TWI_FASTEST_CLOCK) | TWI_CWGR_CHDIV(TWI_CWGR_DIV(TWI_DEF_CLK)) | TWI_CWGR_CLDIV(TWI_CWGR_DIV(TWI_DEF_CLK)); WR4(sc, TWI_CR, TWI_CR_SWRST); WR4(sc, TWI_CR, TWI_CR_MSEN | TWI_CR_SVDIS); WR4(sc, TWI_CWGR, sc->cwgr); if ((sc->iicbus = device_add_child(dev, "iicbus", -1)) == NULL) device_printf(dev, "could not allocate iicbus instance\n"); /* probe and attach the iicbus */ bus_generic_attach(dev); out: if (err) at91_twi_deactivate(dev); return (err); }
static int at91_twi_rst_card(device_t dev, u_char speed, u_char addr, u_char *oldaddr) { struct at91_twi_softc *sc; int clk; sc = device_get_softc(dev); AT91_TWI_LOCK(sc); if (oldaddr) *oldaddr = sc->twi_addr; sc->twi_addr = addr; /* * speeds are for 1.5kb/s, 45kb/s and 90kb/s. */ switch (speed) { case IIC_SLOW: clk = TWI_SLOW_CLOCK; break; case IIC_FAST: clk = TWI_FAST_CLOCK; break; case IIC_UNKNOWN: case IIC_FASTEST: default: clk = TWI_FASTEST_CLOCK; break; } sc->cwgr = TWI_CWGR_CKDIV(1) | TWI_CWGR_CHDIV(TWI_CWGR_DIV(clk)) | TWI_CWGR_CLDIV(TWI_CWGR_DIV(clk)); WR4(sc, TWI_CR, TWI_CR_SWRST); WR4(sc, TWI_CR, TWI_CR_MSEN | TWI_CR_SVDIS); WR4(sc, TWI_CWGR, sc->cwgr); printf("setting cwgr to %#x\n", sc->cwgr); AT91_TWI_UNLOCK(sc); return 0; }
void i2c_master_init(I2CDriver *i2cp) { i2cdef_t i2c = i2cp->i2c; uint32_t ckdiv = 0; uint32_t c_lh_div; /* Disable TWI interrupts */ i2c->TWI_IDR = ~0UL; /* Dummy read in status register */ i2c->TWI_SR; /* Reset TWI peripheral */ i2c->TWI_CR = TWI_CR_SWRST; i2c->TWI_RHR; /* enable master mode */ i2c->TWI_CR = TWI_CR_MSDIS; i2c->TWI_CR = TWI_CR_SVDIS; i2c->TWI_CR = TWI_CR_MSEN; /* Select the speed */ c_lh_div = SystemCoreClock / (i2cp->config->bitrate * TWI_CLK_DIVIDER) - TWI_CLK_CALC_ARGU; /* cldiv must fit in 8 bits, ckdiv must fit in 3 bits */ while ((c_lh_div > TWI_CLK_DIV_MAX) && (ckdiv < TWI_CLK_DIV_MIN)) { /* Increase clock divider */ ckdiv++; /* Divide cldiv value */ c_lh_div /= TWI_CLK_DIVIDER; } /* set clock waveform generator register */ i2c->TWI_CWGR = TWI_CWGR_CLDIV(c_lh_div) | TWI_CWGR_CHDIV(c_lh_div) | TWI_CWGR_CKDIV(ckdiv); }
void i2c_setup() { for ( uint8_t ch = ISSI_I2C_FirstBus_define; ch < ISSI_I2C_Buses_define + ISSI_I2C_FirstBus_define; ch++ ) { #if defined(_kinetis_) volatile uint8_t *I2C_F = (uint8_t*)(&I2C0_F) + i2c_offset[ch]; volatile uint8_t *I2C_FLT = (uint8_t*)(&I2C0_FLT) + i2c_offset[ch]; volatile uint8_t *I2C_C1 = (uint8_t*)(&I2C0_C1) + i2c_offset[ch]; volatile uint8_t *I2C_C2 = (uint8_t*)(&I2C0_C2) + i2c_offset[ch]; switch ( ch ) { case 0: // Enable I2C internal clock SIM_SCGC4 |= SIM_SCGC4_I2C0; // Bus 0 // External pull-up resistor PORTB_PCR0 = PORT_PCR_ODE | PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(2); PORTB_PCR1 = PORT_PCR_ODE | PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(2); break; #if defined(_kii_v2_) case 1: // Enable I2C internal clock SIM_SCGC4 |= SIM_SCGC4_I2C1; // Bus 1 // External pull-up resistor PORTC_PCR10 = PORT_PCR_ODE | PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(2); PORTC_PCR11 = PORT_PCR_ODE | PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(2); break; #endif } // SCL Frequency Divider #if ISSI_Chip_31FL3731_define == 1 && defined(_kii_v1_) // 0x53 -> 48 MHz / (2 * 72) = 333.333 kBaud // 0x40 => mul(2) // 0x13 => ICR(30) *I2C_F = 0x53; *I2C_FLT = 0x05; #elif ISSI_Chip_31FL3731_define == 1 && defined(_kii_v2_) // 0x4E -> 36 MHz / (2 * 56) = 321.428 kBaud // 0x40 => mul(2) // 0x0E => ICR(56) *I2C_F = 0x4E; *I2C_FLT = 0x04; #elif ISSI_Chip_31FL3732_define == 1 || ISSI_Chip_31FL3733_define == 1 || ISSI_Chip_31FL3736_define == 1 /* // Works // 0x84 -> 36 MHz / (4 * 28) = 321.428 kBaud // 0x80 => mul(4) // 0x04 => ICR(28) *I2C_F = 0x84; *I2C_FLT = 0x02; // Also works, 80 fps, no errors (flicker?) // 0x0C -> 36 MHz / (1 * 44) = 818.181 kBaud // 0x00 => mul(1) // 0x0C => ICR(44) *I2C_F = 0x0C; *I2C_FLT = 0x02; // Glitch protection, reduce if you see bus errors */ // Also works, 86 fps, no errors, using frame delay of 50 us // 0x40 -> 36 MHz / (2 * 20) = 900 kBaud // 0x40 => mul(2) // 0x00 => ICR(20) *I2C_F = 0x40; *I2C_FLT = 0x02; #endif *I2C_C1 = I2C_C1_IICEN; *I2C_C2 = I2C_C2_HDRS; // High drive select switch ( ch ) { case 0: // Enable I2C Interrupt NVIC_ENABLE_IRQ( IRQ_I2C0 ); // Set priority below USB, but not too low to maintain performance NVIC_SET_PRIORITY( IRQ_PIT_CH0, I2C_Priority_define ); break; #if defined(_kii_v2_) case 1: // Enable I2C Interrupt NVIC_ENABLE_IRQ( IRQ_I2C1 ); // Set priority below USB, but not too low to maintain performance NVIC_SET_PRIORITY( IRQ_PIT_CH1, I2C_Priority_define ); break; #endif } #elif defined(_sam_) #if ISSI_Chip_31FL3731_define == 1 #define BAUD 400000 #define CK 1 #elif ISSI_Chip_31FL3732_define == 1 || ISSI_Chip_31FL3733_define == 1 || ISSI_Chip_31FL3736_define == 1 #define BAUD 800000 #define CK 0 #endif switch ( ch ) { case 0: // Enable Peripheral / Disable PIO PIOA->PIO_PDR = (1 << 3) | (1 << 4); // Enable i2c clock PMC->PMC_PCER0 = (1 << ID_TWI0); break; case 1: MATRIX->CCFG_SYSIO |= CCFG_SYSIO_SYSIO4 | CCFG_SYSIO_SYSIO5; // Switch PB4 from TDI to GPIO PIOB->PIO_PDR = (1 << 4) | (1 << 5); PMC->PMC_PCER0 = (1 << ID_TWI1); break; } Twi *twi_dev = twi_devs[ch]; uint16_t div = (F_CPU/BAUD - 4) / (2<<CK); // Set clock twi_dev->TWI_CWGR = TWI_CWGR_CLDIV(div) + TWI_CWGR_CHDIV(div) + TWI_CWGR_CKDIV(CK); // Enable master mode twi_dev->TWI_CR = TWI_CR_MSDIS | TWI_CR_SVDIS; twi_dev->TWI_CR = TWI_CR_MSEN; switch ( ch ) { case 0: NVIC_SetPriority(TWI0_IRQn, I2C_Priority_define); NVIC_EnableIRQ(TWI0_IRQn); break; case 1: NVIC_SetPriority(TWI1_IRQn, I2C_Priority_define); NVIC_EnableIRQ(TWI1_IRQn); break; } #endif } }