//! //! @brief This function sends nb_data bytes pointed to by ptr_buf on the specified pipe. //! //! @param pipe //! @param nb_data //! @param ptr_buf //! @param handler Call-back function pointer //! //! @return bool: Status //! bool host_send_data_interrupt(uint8_t pipe, uint16_t nb_data, const void *ptr_buf, Pipe_handler *handler) { bool sav_glob_int_en; if (it_pipe_str[pipe].enable) return false; if (!is_any_interrupt_pipe_active()) { g_sav_int_sof_enable = Is_host_sof_interrupt_enabled(); Host_enable_sof_interrupt(); } it_pipe_str[pipe].enable = true; it_pipe_str[pipe].nb_byte_to_process = nb_data; it_pipe_str[pipe].nb_byte_processed = 0; it_pipe_str[pipe].ptr_buf = (void *)ptr_buf; it_pipe_str[pipe].handler = handler; it_pipe_str[pipe].timeout = 0; it_pipe_str[pipe].nak_timeout = NAK_SEND_TIMEOUT; if ((sav_glob_int_en = cpu_irq_is_enabled())) cpu_irq_disable(); Host_reset_pipe(pipe); (void)Is_host_resetting_pipe(pipe); if (sav_glob_int_en) cpu_irq_enable(); Host_configure_pipe_token(pipe, TOKEN_OUT); Host_ack_out_ready(pipe); Host_unfreeze_pipe(pipe); // Prepare data to be sent Host_reset_pipe_fifo_access(pipe); it_pipe_str[pipe].nb_byte_on_going = nb_data - host_write_p_txpacket(pipe, ptr_buf, nb_data, NULL); private_sof_counter = 0; // Reset the counter in SOF detection subroutine it_pipe_str[pipe].timeout = 0; // Refresh time-out counter if ((sav_glob_int_en = cpu_irq_is_enabled())) cpu_irq_disable(); Host_ack_out_ready(pipe); Host_ack_stall(pipe); Host_ack_nak_received(pipe); (void)Is_host_nak_received(pipe); if (sav_glob_int_en) cpu_irq_enable(); Host_enable_stall_interrupt(pipe); Host_enable_pipe_error_interrupt(pipe); #if NAK_TIMEOUT_ENABLE == ENABLE Host_enable_nak_received_interrupt(pipe); #endif Host_enable_out_ready_interrupt(pipe); Host_enable_pipe_interrupt(pipe); Host_send_out(pipe); // Send the USB frame return true; }
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; }
void pm_bod_disable_irq(volatile avr32_pm_t *pm) { bool global_interrupt_enabled = cpu_irq_is_enabled(); if (global_interrupt_enabled) cpu_irq_disable(); pm->idr = AVR32_PM_IDR_BODDET_MASK; pm->isr; if (global_interrupt_enabled) cpu_irq_enable(); }
void rtc_clear_interrupt(volatile avr32_rtc_t *rtc) { bool global_interrupt_enabled = cpu_irq_is_enabled(); if (global_interrupt_enabled) cpu_irq_disable(); rtc->icr = AVR32_RTC_ICR_TOPI_MASK; rtc->isr; if (global_interrupt_enabled) cpu_irq_enable(); }
/** * \brief Disable the TWI interrupts and clear its status register * * \param twim Base address of the TWIM (i.e. &AVR32_TWI). */ void twim_disable_interrupt (volatile avr32_twim_t *twim) { bool global_interrupt_enabled = cpu_irq_is_enabled (); if (global_interrupt_enabled) { cpu_irq_disable (); } // Clear the interrupt flags twim->idr = ~0UL; // Clear the status flags twim->scr = ~0UL; }
void cpu_irq_enter_critical(void) { if (cpu_irq_critical_section_counter == 0) { if (cpu_irq_is_enabled()) { cpu_irq_disable(); cpu_irq_prev_interrupt_state = true; } else { /* Make sure the to save the prev state as false */ cpu_irq_prev_interrupt_state = false; } } cpu_irq_critical_section_counter++; }
/** * \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; }
//! //! @brief This function receives nb_data bytes pointed to by ptr_buf on the specified pipe. //! //! *nb_data is updated with the final number of data bytes received. //! //! @param pipe //! @param nb_data //! @param ptr_buf //! @param handler Call-back function pointer //! //! @return bool: Status //! bool host_get_data_interrupt(uint8_t pipe, uint16_t nb_data, void *ptr_buf, Pipe_handler *handler) { bool sav_glob_int_en; if (it_pipe_str[pipe].enable) return false; if (!is_any_interrupt_pipe_active()) { g_sav_int_sof_enable = Is_host_sof_interrupt_enabled(); Host_enable_sof_interrupt(); } it_pipe_str[pipe].enable = true; it_pipe_str[pipe].nb_byte_to_process = nb_data; it_pipe_str[pipe].nb_byte_processed = 0; it_pipe_str[pipe].ptr_buf = ptr_buf; it_pipe_str[pipe].handler = handler; it_pipe_str[pipe].timeout = 0; it_pipe_str[pipe].nak_timeout = NAK_RECEIVE_TIMEOUT; private_sof_counter = 0; // Reset the counter in SOF detection subroutine if ((sav_glob_int_en = cpu_irq_is_enabled())) cpu_irq_disable(); Host_reset_pipe(pipe); Host_ack_stall(pipe); Host_ack_nak_received(pipe); (void)Is_host_nak_received(pipe); if (sav_glob_int_en) cpu_irq_enable(); Host_enable_stall_interrupt(pipe); #if NAK_TIMEOUT_ENABLE == ENABLE Host_enable_nak_received_interrupt(pipe); #endif Host_enable_pipe_error_interrupt(pipe); Host_enable_in_received_interrupt(pipe); Host_enable_pipe_interrupt(pipe); Host_enable_continuous_in_mode(pipe); Host_configure_pipe_token(pipe, TOKEN_IN); Host_ack_in_received(pipe); Host_unfreeze_pipe(pipe); return true; }
//! host_disable_all_pipes //! //! This function disables all pipes for the host controller. //! Useful to execute upon disconnection. //! //! @return Void //! void host_disable_all_pipes(void) { #if USB_HOST_PIPE_INTERRUPT_TRANSFER == ENABLE bool sav_glob_int_en; #endif U8 p; #if USB_HOST_PIPE_INTERRUPT_TRANSFER == ENABLE // Disable global interrupts if ((sav_glob_int_en = cpu_irq_is_enabled())) cpu_irq_disable(); #endif for (p = 0; p < MAX_PEP_NB; p++) { // Disable the pipe <p> (disable interrupt, free memory, reset pipe, ...) Host_disable_pipe_interrupt(p); Host_reset_pipe(p); Host_unallocate_memory(p); Host_disable_pipe(p); } #if USB_HOST_PIPE_INTERRUPT_TRANSFER == ENABLE (void)Is_host_pipe_enabled(MAX_PEP_NB - 1); // Restore the global interrupts to the initial state if (sav_glob_int_en) cpu_irq_enable(); #endif }
//! This function is the generic control pipe management function. //! This function is used to send and receive control requests over control pipe. //! //! @todo Fix all time-out errors and disconnections in active wait loop. //! //! @param data_pointer void *: Pointer to data to transfer //! //! @return Status_t: Status //! //! @note This function uses the usb_request global structure. Hence, this //! structure should be filled before calling this function. //! Status_t host_transfer_control(void *data_pointer) { int status = CONTROL_GOOD; bool sav_int_sof_enable; bool sav_glob_int_en; uint16_t data_length; uint8_t c; Usb_ack_event(EVT_HOST_SOF); sav_int_sof_enable = Is_host_sof_interrupt_enabled(); Host_enable_sof_interrupt(); // SOF software detection is in interrupt subroutine while (!Is_usb_event(EVT_HOST_SOF)) // Wait 1 SOF { #if defined(Host_wait_action) Host_wait_action(); #endif if (Is_host_emergency_exit()) { Host_freeze_pipe(P_CONTROL); Host_reset_pipe(P_CONTROL); status = CONTROL_TIMEOUT; goto host_transfer_control_end; } } Host_configure_pipe_token(P_CONTROL, TOKEN_SETUP); Host_ack_setup_ready(); Host_unfreeze_pipe(P_CONTROL); // Build and send the setup request fields Host_reset_pipe_fifo_access(P_CONTROL); Host_write_pipe_data(P_CONTROL, 8, usb_request.bmRequestType); Host_write_pipe_data(P_CONTROL, 8, usb_request.bRequest); Host_write_pipe_data(P_CONTROL, 16, usb_format_mcu_to_usb_data(16, usb_request.wValue)); Host_write_pipe_data(P_CONTROL, 16, usb_format_mcu_to_usb_data(16, usb_request.wIndex)); Host_write_pipe_data(P_CONTROL, 16, usb_format_mcu_to_usb_data(16, usb_request.wLength)); Host_send_setup(); while (!Is_host_setup_ready()) // Wait for SETUP ack { #if defined(Host_wait_action) Host_wait_action(); #endif if (Is_host_emergency_exit()) { Host_freeze_pipe(P_CONTROL); Host_reset_pipe(P_CONTROL); status = CONTROL_TIMEOUT; goto host_transfer_control_end; } if (Is_host_pipe_error(P_CONTROL)) // Any error? { c = Host_error_status(P_CONTROL); Host_ack_all_errors(P_CONTROL); status = c; // Send error status goto host_transfer_control_end; } } // Setup token sent; now send IN or OUT token // Before just wait 1 SOF Usb_ack_event(EVT_HOST_SOF); Host_freeze_pipe(P_CONTROL); data_length = usb_request.wLength; while (!Is_usb_event(EVT_HOST_SOF)) // Wait 1 SOF { #if defined(Host_wait_action) Host_wait_action(); #endif if (Is_host_emergency_exit()) { Host_freeze_pipe(P_CONTROL); Host_reset_pipe(P_CONTROL); status = CONTROL_TIMEOUT; goto host_transfer_control_end; } } // IN request management --------------------------------------------- if (usb_request.bmRequestType & 0x80) // Data stage IN (bmRequestType.D7 == 1) { Host_disable_continuous_in_mode(P_CONTROL); Host_configure_pipe_token(P_CONTROL, TOKEN_IN); Host_ack_control_in_received_free(); while (data_length) { Host_unfreeze_pipe(P_CONTROL); private_sof_counter = 0; // Reset the counter in SOF detection subroutine while (!Is_host_control_in_received()) { #if defined(Host_wait_action) Host_wait_action(); #endif if (Is_host_emergency_exit()) { Host_freeze_pipe(P_CONTROL); Host_reset_pipe(P_CONTROL); status = CONTROL_TIMEOUT; goto host_transfer_control_end; } if (Is_host_pipe_error(P_CONTROL)) // Any error? { c = Host_error_status(P_CONTROL); Host_ack_all_errors(P_CONTROL); status = c; // Send error status goto host_transfer_control_end; } if (Is_host_stall(P_CONTROL)) { Host_ack_stall(P_CONTROL); status = CONTROL_STALL; goto host_transfer_control_end; } #if TIMEOUT_DELAY_ENABLE == ENABLE if (1000 < host_get_timeout()) // Count 1s { Host_freeze_pipe(P_CONTROL); Host_reset_pipe(P_CONTROL); status = CONTROL_TIMEOUT; goto host_transfer_control_end; } #endif } Host_reset_pipe_fifo_access(P_CONTROL); c = Host_get_pipe_size(P_CONTROL) - Host_byte_count(P_CONTROL); data_length = host_read_p_rxpacket(P_CONTROL, data_pointer, data_length, &data_pointer); if (usb_request.incomplete_read || c) data_length = 0; Host_freeze_pipe(P_CONTROL); Host_ack_control_in_received_free(); // In low-speed mode, the USB IP may have not yet sent the ACK at this // point. The USB IP does not support a new start of transaction request // from the firmware if the ACK has not been sent. The only means of // making sure the ACK has been sent is to wait for the next Keep-Alive // before starting a new transaction. if (Is_usb_low_speed_mode()) { Usb_ack_event(EVT_HOST_SOF); if ((sav_glob_int_en = cpu_irq_is_enabled())) cpu_irq_disable(); Host_ack_sof(); (void)Is_host_sof_interrupt_enabled(); if (sav_glob_int_en) cpu_irq_enable(); while (!Is_usb_event(EVT_HOST_SOF)) // Wait for next Keep-Alive { if (Is_host_emergency_exit()) { Host_freeze_pipe(P_CONTROL); Host_reset_pipe(P_CONTROL); status = CONTROL_TIMEOUT; goto host_transfer_control_end; } } } } // End of IN data stage Host_configure_pipe_token(P_CONTROL, TOKEN_OUT); Host_ack_control_out_ready_send(); Host_unfreeze_pipe(P_CONTROL); #if TIMEOUT_DELAY_ENABLE == ENABLE private_sof_counter = 0; // Reset the counter in SOF detection subroutine #endif while (!Is_host_control_out_ready()) { #if defined(Host_wait_action) Host_wait_action(); #endif if (Is_host_emergency_exit()) { Host_freeze_pipe(P_CONTROL); Host_reset_pipe(P_CONTROL); status = CONTROL_TIMEOUT; goto host_transfer_control_end; } if (Is_host_pipe_error(P_CONTROL)) // Any error? { c = Host_error_status(P_CONTROL); Host_ack_all_errors(P_CONTROL); status = c; // Send error status goto host_transfer_control_end; } if (Is_host_stall(P_CONTROL)) { Host_ack_stall(P_CONTROL); status = CONTROL_STALL; goto host_transfer_control_end; } #if TIMEOUT_DELAY_ENABLE == ENABLE if (2000 < host_get_timeout()) // Count 2s { Host_freeze_pipe(P_CONTROL); Host_reset_pipe(P_CONTROL); status = CONTROL_TIMEOUT; goto host_transfer_control_end; } #endif } Host_ack_control_out_ready(); } // OUT request management -------------------------------------------- else // Data stage OUT (bmRequestType.D7 == 0) { Host_configure_pipe_token(P_CONTROL, TOKEN_OUT); Host_ack_control_out_ready(); while (data_length) { Host_unfreeze_pipe(P_CONTROL); Host_reset_pipe_fifo_access(P_CONTROL); data_length = host_write_p_txpacket(P_CONTROL, data_pointer, data_length, (const void **)&data_pointer); Host_send_control_out(); while (!Is_host_control_out_ready()) { #if defined(Host_wait_action) Host_wait_action(); #endif if (Is_host_emergency_exit()) { Host_freeze_pipe(P_CONTROL); Host_reset_pipe(P_CONTROL); status = CONTROL_TIMEOUT; goto host_transfer_control_end; } if (Is_host_pipe_error(P_CONTROL)) // Any error? { c = Host_error_status(P_CONTROL); Host_ack_all_errors(P_CONTROL); status = c; // Send error status goto host_transfer_control_end; } if (Is_host_stall(P_CONTROL)) { Host_ack_stall(P_CONTROL); status = CONTROL_STALL; goto host_transfer_control_end; } } Host_ack_control_out_ready(); } // End of OUT data stage Host_freeze_pipe(P_CONTROL); Host_configure_pipe_token(P_CONTROL, TOKEN_IN); Host_ack_control_in_received_free(); Host_unfreeze_pipe(P_CONTROL); #if TIMEOUT_DELAY_ENABLE == ENABLE private_sof_counter = 0; // Reset the counter in SOF detection subroutine #endif while (!Is_host_control_in_received()) { #if defined(Host_wait_action) Host_wait_action(); #endif if (Is_host_emergency_exit()) { Host_freeze_pipe(P_CONTROL); Host_reset_pipe(P_CONTROL); status = CONTROL_TIMEOUT; goto host_transfer_control_end; } if (Is_host_pipe_error(P_CONTROL)) // Any error? { c = Host_error_status(P_CONTROL); Host_ack_all_errors(P_CONTROL); status = c; // Send error status goto host_transfer_control_end; } if (Is_host_stall(P_CONTROL)) { Host_ack_stall(P_CONTROL); status = CONTROL_STALL; goto host_transfer_control_end; } #if TIMEOUT_DELAY_ENABLE == ENABLE if (2000 < host_get_timeout()) // Count 2s { Host_freeze_pipe(P_CONTROL); Host_reset_pipe(P_CONTROL); status = CONTROL_TIMEOUT; goto host_transfer_control_end; } #endif } Host_ack_control_in_received(); Host_freeze_pipe(P_CONTROL); Host_free_control_in(); } host_transfer_control_end: if (!sav_int_sof_enable) // Restore SOF interrupt enable { if ((sav_glob_int_en = cpu_irq_is_enabled())) cpu_irq_disable(); Host_disable_sof_interrupt(); (void)Is_host_sof_interrupt_enabled(); if (sav_glob_int_en) cpu_irq_enable(); } return status; }
//! //! @brief This function receives nb_data bytes pointed to by ptr_buf on the specified pipe. //! //! *nb_data is updated with the final number of data bytes received. //! //! @note This function activates the host SOF interrupt to detect time-outs. //! The initial enable state of this interrupt will be restored. //! //! @param pipe //! @param nb_data //! @param ptr_buf //! //! @return Status_t: Pipe status //! Status_t host_get_data(uint8_t pipe, uint16_t *nb_data, void *ptr_buf) { Status_t status = PIPE_GOOD; // Frame correctly received by default bool sav_int_sof_enable; bool sav_glob_int_en; uint8_t nak_timeout; uint16_t n, i; #if NAK_TIMEOUT_ENABLE == ENABLE uint16_t cpt_nak; #endif n = *nb_data; sav_int_sof_enable = Is_host_sof_interrupt_enabled(); Host_enable_sof_interrupt(); Host_enable_continuous_in_mode(pipe); Host_configure_pipe_token(pipe, TOKEN_IN); Host_ack_in_received(pipe); while (n) // While missing data... { Host_free_in(pipe); Host_unfreeze_pipe(pipe); private_sof_counter = 0; // Reset the counter in SOF detection subroutine nak_timeout = 0; #if NAK_TIMEOUT_ENABLE == ENABLE cpt_nak = 0; #endif while (!Is_host_in_received(pipe)) { if (Is_host_emergency_exit()) // Asynchronous disconnection or role exchange detected under interrupt { status = PIPE_DELAY_TIMEOUT; Host_reset_pipe(pipe); goto host_get_data_end; } #if TIMEOUT_DELAY_ENABLE == ENABLE if (private_sof_counter >= 250) // Time-out management { private_sof_counter = 0; // Done in host SOF interrupt if (nak_timeout++ >= TIMEOUT_DELAY) // Check for local time-out { status = PIPE_DELAY_TIMEOUT; Host_reset_pipe(pipe); goto host_get_data_end; } } #endif if (Is_host_pipe_error(pipe)) // Error management { status = Host_error_status(pipe); Host_ack_all_errors(pipe); goto host_get_data_end; } if (Is_host_stall(pipe)) // STALL management { status = PIPE_STALL; Host_reset_pipe(pipe); Host_ack_stall(pipe); goto host_get_data_end; } #if NAK_TIMEOUT_ENABLE == ENABLE if (Is_host_nak_received(pipe)) // NAK received { Host_ack_nak_received(pipe); if (cpt_nak++ > NAK_RECEIVE_TIMEOUT) { status = PIPE_NAK_TIMEOUT; Host_reset_pipe(pipe); goto host_get_data_end; } } #endif } Host_freeze_pipe(pipe); Host_reset_pipe_fifo_access(pipe); i = Host_get_pipe_size(pipe) - Host_byte_count(pipe); if (!ptr_buf) { if (Host_byte_count(pipe) > n) // More bytes received than expected { n = 0; //! @todo Error code management } else // Nb bytes received <= expected { n -= Host_byte_count(pipe); if (i) // Short packet { *nb_data -= n; n = 0; } } } else { n = host_read_p_rxpacket(pipe, ptr_buf, n, &ptr_buf); if (Host_byte_count(pipe)) // More bytes received than expected { //! @todo Error code management } else if (i) // Short packet with nb bytes received <= expected { *nb_data -= n; n = 0; } } Host_ack_in_received(pipe); // In low-speed mode, the USB IP may have not yet sent the ACK at this // point. The USB IP does not support a new start of transaction request // from the firmware if the ACK has not been sent. The only means of making // sure the ACK has been sent is to wait for the next Keep-Alive before // starting a new transaction. if (Is_usb_low_speed_mode()) { Usb_ack_event(EVT_HOST_SOF); sav_int_sof_enable = Is_host_sof_interrupt_enabled(); if ((sav_glob_int_en = cpu_irq_is_enabled())) cpu_irq_disable(); Host_ack_sof(); (void)Is_host_sof_interrupt_enabled(); if (sav_glob_int_en) cpu_irq_enable(); Host_enable_sof_interrupt(); while (!Is_usb_event(EVT_HOST_SOF)) // Wait for next Keep-Alive { if (Is_host_emergency_exit()) { status = PIPE_DELAY_TIMEOUT; Host_reset_pipe(pipe); goto host_get_data_end; } } if (!sav_int_sof_enable) // Restore SOF interrupt enable { if ((sav_glob_int_en = cpu_irq_is_enabled())) cpu_irq_disable(); Host_disable_sof_interrupt(); (void)Is_host_sof_interrupt_enabled(); if (sav_glob_int_en) cpu_irq_enable(); } } } host_get_data_end: Host_freeze_pipe(pipe); // Restore SOF interrupt enable state if (!sav_int_sof_enable) { if ((sav_glob_int_en = cpu_irq_is_enabled())) cpu_irq_disable(); Host_disable_sof_interrupt(); (void)Is_host_sof_interrupt_enabled(); if (sav_glob_int_en) cpu_irq_enable(); } // And return... return status; }
//! //! @brief This function sends nb_data bytes pointed to by ptr_buf on the specified pipe. //! //! @note This function activates the host SOF interrupt to detect time-outs. //! The initial enable state of this interrupt will be restored. //! //! @param pipe //! @param nb_data //! @param ptr_buf //! //! @return Status_t: Pipe status //! Status_t host_send_data(uint8_t pipe, uint16_t nb_data, const void *ptr_buf) { Status_t status = PIPE_GOOD; // Frame correctly sent by default bool sav_int_sof_enable; bool sav_glob_int_en; uint8_t nak_timeout; #if NAK_TIMEOUT_ENABLE == ENABLE uint16_t cpt_nak; #endif sav_int_sof_enable = Is_host_sof_interrupt_enabled(); // Save state of enable SOF interrupt Host_enable_sof_interrupt(); Host_configure_pipe_token(pipe, TOKEN_OUT); Host_ack_out_ready(pipe); Host_unfreeze_pipe(pipe); while (nb_data) // While there is something to send... { // Prepare data to be sent Host_reset_pipe_fifo_access(pipe); nb_data = host_write_p_txpacket(pipe, ptr_buf, nb_data, &ptr_buf); private_sof_counter = 0; // Reset the counter in SOF detection subroutine #if NAK_TIMEOUT_ENABLE == ENABLE cpt_nak = 0; #endif nak_timeout = 0; Host_ack_out_ready_send(pipe); while (!Is_host_out_ready(pipe)) { if (Is_host_emergency_exit()) // Async disconnection or role change detected under interrupt { status = PIPE_DELAY_TIMEOUT; Host_reset_pipe(pipe); goto host_send_data_end; } #if TIMEOUT_DELAY_ENABLE == ENABLE if (private_sof_counter >= 250) // Count 250 ms (250 SOF) { private_sof_counter = 0; if (nak_timeout++ >= TIMEOUT_DELAY) // Increment time-out and check for overflow { status = PIPE_DELAY_TIMEOUT; Host_reset_pipe(pipe); goto host_send_data_end; } } #endif if (Is_host_pipe_error(pipe)) // Error management { status = Host_error_status(pipe); Host_ack_all_errors(pipe); goto host_send_data_end; } if (Is_host_stall(pipe)) // STALL management { status = PIPE_STALL; Host_ack_stall(pipe); goto host_send_data_end; } #if NAK_TIMEOUT_ENABLE == ENABLE if (Is_host_nak_received(pipe)) // NAK received { Host_ack_nak_received(pipe); if (cpt_nak++ > NAK_SEND_TIMEOUT) { status = PIPE_NAK_TIMEOUT; Host_reset_pipe(pipe); goto host_send_data_end; } } #endif } // Here OUT sent Host_ack_out_ready(pipe); } while (Host_nb_busy_bank(pipe)); host_send_data_end: Host_freeze_pipe(pipe); // Restore SOF interrupt enable state if (!sav_int_sof_enable) { if ((sav_glob_int_en = cpu_irq_is_enabled())) cpu_irq_disable(); Host_disable_sof_interrupt(); (void)Is_host_sof_interrupt_enabled(); if (sav_glob_int_en) cpu_irq_enable(); } // And return... return status; }
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; }