Example #1
0
//!
//! @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;
}
Example #2
0
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;
}
Example #3
0
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();
}
Example #4
0
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();
}
Example #5
0
/**
 * \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++;
}
Example #7
0
/**
 * \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;
}
Example #8
0
//!
//! @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;
}
Example #9
0
//! 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;
}
Example #11
0
//!
//! @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;
}
Example #12
0
//!
//! @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;
}
Example #13
0
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;
}
Example #14
0
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;
}