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);  
	
}
Exemplo n.º 2
0
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;
}
Exemplo n.º 3
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;
}
Exemplo n.º 4
0
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;
}
Exemplo n.º 5
0
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);
}
Exemplo n.º 6
0
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;
}
Exemplo n.º 7
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);

}
Exemplo n.º 8
0
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
	}
}