static void twim_init(void) { uint8_t status; const gpio_map_t TWIM_GPIO_MAP = { (AVR32_TWIMS0_TWCK_0_0_PIN, AVR32_TWIMS0_TWCK_0_0_FUNCTION,AVR32_TWIMS0_TWD_0_0_PIN, AVR32_TWIMS0_TWD_0_0_FUNCTION) }; gpio_enable_module(TWIM_GPIO_MAP, sizeof(TWIM_GPIO_MAP)/sizeof(TWIM_GPIO_MAP[0])); status = twim_master_init(TWIM, &twi_opt_GYRO); twim_set_speed (TWIM, TWI_STD_MODE_SPEED, FPBA_HZ); }
/** * \brief Initialize the TWIM module * * \param twim Base address of the TWIM * \param config Options for initializing the TWIM module * * \retval STATUS_OK Transaction is successful * \retval ERR_INVALID_ARG Invalid arg resulting in wrong CWGR Exponential */ status_code_t twim_set_config(Twim *twim, struct twim_config *config) { sysclk_enable_peripheral_clock(twim); /* Enable master transfer */ twim->TWIM_CR = TWIM_CR_MEN; /* Reset TWI */ twim->TWIM_CR = TWIM_CR_SWRST; /* Clear SR */ twim->TWIM_SCR = ~0UL; if (config->smbus) { /* Enable SMBUS Transfer */ twim->TWIM_CR = TWIM_CR_SMEN; twim->TWIM_SMBTR = (uint32_t) -1; } /* Select the speed */ if (config->speed) { if (twim_set_speed(twim, config->speed, config->twim_clk, config->data_setup_cycles) != STATUS_OK) { return ERR_INVALID_ARG; } } if (config->hsmode_speed) { if (twim_set_hsmode_speed(twim, config->hsmode_speed, config->twim_clk, config->hsmode_data_setup_cycles) != STATUS_OK) { return ERR_INVALID_ARG; } } /* Set clock and data slew rate */ twim->TWIM_SRR = ((config->speed < TWI_FAST_MODE_PLUS_SPEED) ? TWIM_SRR_FILTER(2) : TWIM_SRR_FILTER(3)) | TWIM_SRR_CLSLEW(config->clock_slew_limit) | TWIM_SRR_CLDRIVEL(config->clock_drive_strength_low) | TWIM_SRR_DASLEW(config->data_slew_limit) | TWIM_SRR_DADRIVEL(config->data_drive_strength_low); twim->TWIM_HSSRR = TWIM_HSSRR_FILTER(1) | TWIM_HSSRR_CLSLEW(config->hs_clock_slew_limit) | TWIM_HSSRR_CLDRIVEL(config->hs_clock_drive_strength_low) | TWIM_HSSRR_CLDRIVEH(config->hs_clock_drive_strength_high) | TWIM_HSSRR_DASLEW(config->hs_data_slew_limit) | TWIM_HSSRR_DADRIVEL(config->hs_data_drive_strength_low); #if TWIM_LOW_POWER_ENABLE sleepmgr_init(); #endif return STATUS_OK; }
/** * \brief Initialize the twi master module * * \param twim Base address of the TWIM (i.e. &AVR32_TWIM) * \param *opt Options for initializing the twim module * (see \ref twim_options_t) * \retval STATUS_OK Transaction is successful * \retval ERR_INVALID_ARG Invalid arg resulting in wrong CWGR Exponential * \retval ERR_IO_ERROR NACK is received or Bus Arbitration lost */ status_code_t twim_master_init (volatile avr32_twim_t *twim, const twim_options_t *opt) { bool global_interrupt_enabled = cpu_irq_is_enabled (); // Initialize bus transfer status transfer_status = TWI_SUCCESS; // Disable TWI interrupts if (global_interrupt_enabled) { cpu_irq_disable (); } twim->idr = ~0UL; // Enable master transfer twim->cr = AVR32_TWIM_CR_MEN_MASK; // Reset TWI twim->cr = AVR32_TWIM_CR_SWRST_MASK; if (global_interrupt_enabled) { cpu_irq_enable (); } // Clear SR twim->scr = ~0UL; // register Register twim_master_interrupt_handler interrupt on level CONF_TWIM_IRQ_LEVEL irqflags_t flags = cpu_irq_save(); irq_register_handler(twim_master_interrupt_handler, CONF_TWIM_IRQ_LINE, CONF_TWIM_IRQ_LEVEL); cpu_irq_restore(flags); /* if (opt->smbus) { // Enable SMBUS Transfer twim->cr = AVR32_TWIM_CR_SMEN_MASK; twim->smbtr = (uint32_t) -1; } */ // Select the speed if (twim_set_speed (twim, opt->speed, opt->pba_hz) == ERR_INVALID_ARG) { return ERR_INVALID_ARG; } // Probe the component twim_probe (twim, opt->chip); //Check for nack and abitration if (transfer_status == TWI_RECEIVE_NACK || transfer_status == TWI_ARBITRATION_LOST) { return ERR_IO_ERROR; } return STATUS_OK; }
void i2c_driver_init(uint8_t i2c_device) { volatile avr32_twim_t *twim; switch (i2c_device) { case I2C0: twim = &AVR32_TWIM0; ///< Register PDCA IRQ interrupt. INTC_register_interrupt( (__int_handler) &i2c_int_handler_i2c0, AVR32_TWIM0_IRQ, AVR32_INTC_INT1); gpio_enable_module_pin(AVR32_TWIMS0_TWCK_0_0_PIN, AVR32_TWIMS0_TWCK_0_0_FUNCTION); gpio_enable_module_pin(AVR32_TWIMS0_TWD_0_0_PIN, AVR32_TWIMS0_TWD_0_0_FUNCTION); break; case I2C1: twim = &AVR32_TWIM1;///< Register PDCA IRQ interrupt. //INTC_register_interrupt( (__int_handler) &i2c_int_handler_i2c1, AVR32_TWIM1_IRQ, AVR32_INTC_INT1); gpio_enable_module_pin(AVR32_TWIMS1_TWCK_0_0_PIN, AVR32_TWIMS1_TWCK_0_0_FUNCTION); gpio_enable_module_pin(AVR32_TWIMS1_TWD_0_0_PIN, AVR32_TWIMS1_TWD_0_0_FUNCTION); break; default: ///< invalid device ID return; } static twim_options_t twi_opt= { .pba_hz = 64000000, .speed = 400000, .chip = 0xff, .smbus = false }; twi_opt.pba_hz = sysclk_get_pba_hz(); status_code_t ret_twim_init = twim_master_init(twim, &twi_opt); print_util_dbg_print("\r\n"); switch(ret_twim_init) { case ERR_IO_ERROR : print_util_dbg_print("NO Twim probe here \r\n"); case STATUS_OK : print_util_dbg_print("I2C initialised \r\n"); break; default : print_util_dbg_print("Error initialising I2C \r\n"); break; } } int8_t i2c_driver_reset(uint8_t i2c_device) { volatile avr32_twim_t *twim; switch (i2c_device) { case 0: twim = &AVR32_TWIM0; break; case 1: twim = &AVR32_TWIM1; break; default: ///< invalid device ID return -1; } bool global_interrupt_enabled = cpu_irq_is_enabled (); ///< Disable TWI interrupts if (global_interrupt_enabled) { cpu_irq_disable (); } twim->idr = ~0UL; ///< Enable master transfer twim->cr = AVR32_TWIM_CR_MEN_MASK; ///< Reset TWI twim->cr = AVR32_TWIM_CR_SWRST_MASK; if (global_interrupt_enabled) { cpu_irq_enable (); } ///< Clear SR twim->scr = ~0UL; return STATUS_OK; //No error } int8_t i2c_driver_trigger_request(uint8_t i2c_device, i2c_packet_t *transfer) { ///< initiate transfer of given request ///< set up DMA channel volatile avr32_twim_t *twim; bool global_interrupt_enabled = cpu_irq_is_enabled (); if (global_interrupt_enabled) { cpu_irq_disable (); } switch (i2c_device) { case 0: twim = &AVR32_TWIM0; twim->cr = AVR32_TWIM_CR_MEN_MASK; twim->cr = AVR32_TWIM_CR_SWRST_MASK; twim->cr = AVR32_TWIM_CR_MDIS_MASK; twim->scr = ~0UL; // Clear the interrupt flags twim->idr = ~0UL; if (twim_set_speed(twim, transfer->i2c_speed, sysclk_get_pba_hz()) == ERR_INVALID_ARG) { return ERR_INVALID_ARG; } //pdca_load_channel(TWI0_DMA_CH, (void *)schedule[i2c_device][schedule_slot].config.write_data, schedule[i2c_device][schedule_slot].config.write_count); ///< Enable pdca interrupt each time the reload counter reaches zero, i.e. each time ///< the whole block was received //pdca_enable_interrupt_transfer_error(TWI0_DMA_CH); break; case 1: twim = &AVR32_TWIM1; twim->cr = AVR32_TWIM_CR_MEN_MASK; twim->cr = AVR32_TWIM_CR_SWRST_MASK; twim->cr = AVR32_TWIM_CR_MDIS_MASK; twim->scr = ~0UL; ///< Clear the interrupt flags twim->idr = ~0UL; if (twim_set_speed(twim, transfer->i2c_speed, sysclk_get_pba_hz()) == ERR_INVALID_ARG) { return ERR_INVALID_ARG; } break; default: ///< invalid device ID return -1; } ///< set up I2C speed and mode //twim_set_speed(twim, 100000, sysclk_get_pba_hz()); switch (1/*conf->direction*/) { case I2C_READ: twim->cmdr = (transfer->slave_address << AVR32_TWIM_CMDR_SADR_OFFSET) | (transfer->data_size << AVR32_TWIM_CMDR_NBYTES_OFFSET) | (AVR32_TWIM_CMDR_VALID_MASK) | (AVR32_TWIM_CMDR_START_MASK) | (AVR32_TWIM_CMDR_STOP_MASK) | (AVR32_TWIM_CMDR_READ_MASK); twim->ncmdr = 0; twim->ier = AVR32_TWIM_IER_STD_MASK | AVR32_TWIM_IER_RXRDY_MASK; break; case I2C_WRITE1_THEN_READ: ///< set up next command register for the burst read transfer ///< set up command register to initiate the write transfer. The DMA will take care of the reading once this is done. twim->cmdr = (transfer->slave_address << AVR32_TWIM_CMDR_SADR_OFFSET) | ((1)<< AVR32_TWIM_CMDR_NBYTES_OFFSET) | (AVR32_TWIM_CMDR_VALID_MASK) | (AVR32_TWIM_CMDR_START_MASK) //| (AVR32_TWIM_CMDR_STOP_MASK) | (0 << AVR32_TWIM_CMDR_READ_OFFSET); ; twim->ncmdr = (transfer->slave_address << AVR32_TWIM_CMDR_SADR_OFFSET) | ((transfer->data_size) << AVR32_TWIM_CMDR_NBYTES_OFFSET) | (AVR32_TWIM_CMDR_VALID_MASK) | (AVR32_TWIM_CMDR_START_MASK) | (AVR32_TWIM_CMDR_STOP_MASK) | (AVR32_TWIM_CMDR_READ_MASK); twim->ier = AVR32_TWIM_IER_STD_MASK | AVR32_TWIM_IER_RXRDY_MASK | AVR32_TWIM_IER_TXRDY_MASK; ///< set up writing of one byte (usually a slave register index) twim->cr = AVR32_TWIM_CR_MEN_MASK; twim->thr = transfer->write_then_read_preamble; twim->cr = AVR32_TWIM_CR_MEN_MASK; break; case I2C_WRITE: twim->cmdr = (transfer->slave_address << AVR32_TWIM_CMDR_SADR_OFFSET) | ((transfer->data_size) << AVR32_TWIM_CMDR_NBYTES_OFFSET) | (AVR32_TWIM_CMDR_VALID_MASK) | (AVR32_TWIM_CMDR_START_MASK) | (AVR32_TWIM_CMDR_STOP_MASK); twim->ncmdr = 0; ; twim->ier = AVR32_TWIM_IER_NAK_MASK | AVR32_TWIM_IER_TXRDY_MASK; break; } ///< start transfer current_transfer = transfer; current_transfer->transfer_in_progress = 1; current_transfer->data_index = 0; if (global_interrupt_enabled) { cpu_irq_enable (); } twim->cr = AVR32_TWIM_CR_MEN_MASK; return STATUS_OK; }
int32_t i2c_driver_init(uint8_t i2c_device) { int32_t i; volatile avr32_twim_t *twim; switch (i2c_device) { case 0: twim = &AVR32_TWIM0; // Register PDCA IRQ interrupt. INTC_register_interrupt( (__int_handler) &pdca_int_handler_i2c0, TWI0_DMA_IRQ, AVR32_INTC_INT0); gpio_enable_module_pin(AVR32_TWIMS0_TWCK_0_0_PIN, AVR32_TWIMS0_TWCK_0_0_FUNCTION); gpio_enable_module_pin(AVR32_TWIMS0_TWD_0_0_PIN, AVR32_TWIMS0_TWD_0_0_FUNCTION); break; case 1: twim = &AVR32_TWIM1;// Register PDCA IRQ interrupt. INTC_register_interrupt( (__int_handler) &pdca_int_handler_i2c0, TWI1_DMA_IRQ, AVR32_INTC_INT0); gpio_enable_module_pin(AVR32_TWIMS1_TWCK_0_0_PIN, AVR32_TWIMS1_TWCK_0_0_FUNCTION); gpio_enable_module_pin(AVR32_TWIMS1_TWD_0_0_PIN, AVR32_TWIMS1_TWD_0_0_FUNCTION); gpio_enable_pin_pull_up(AVR32_TWIMS1_TWCK_0_0_PIN); gpio_enable_pin_pull_up(AVR32_TWIMS1_TWD_0_0_PIN); break; default: // invalid device ID return -1; } for (i = 0; i < I2C_SCHEDULE_SLOTS; i++) { schedule[i2c_device][i].active = -1; } bool global_interrupt_enabled = cpu_irq_is_enabled (); // Disable TWI interrupts if (global_interrupt_enabled) { cpu_irq_disable (); } twim->idr = ~0UL; // Enable master transfer twim->cr = AVR32_TWIM_CR_MEN_MASK; // Reset TWI twim->cr = AVR32_TWIM_CR_SWRST_MASK; if (global_interrupt_enabled) { cpu_irq_enable (); } // Clear SR twim->scr = ~0UL; // register Register twim_master_interrupt_handler interrupt on level CONF_TWIM_IRQ_LEVEL // irqflags_t flags = cpu_irq_save(); // irq_register_handler(twim_master_interrupt_handler, // CONF_TWIM_IRQ_LINE, CONF_TWIM_IRQ_LEVEL); // cpu_irq_restore(flags); // Select the speed if (twim_set_speed(twim, 100000, sysclk_get_pba_hz()) == ERR_INVALID_ARG) { return ERR_INVALID_ARG; } return STATUS_OK; }