From ecfe0c3e3de00102ed6a20d86c1c643e248fcf21 Mon Sep 17 00:00:00 2001 From: Jean-Christophe BUDA <jean-christophe.buda@atmel.com> Date: Wed, 25 Jun 2014 18:21:46 +0200 Subject: [PATCH] correct include missing in -I --- cores/arduino/USB/CDC.cpp | 2 +- cores/arduino/USB/HID.cpp | 2 +- cores/arduino/USB/USBCore.cpp | 2 +- cores/arduino/USB/USB_device.h | 2 +- cores/arduino/USB/samd21_device.c | 7 +- cores/arduino/USB/samd21_host.c | 773 ++++++++++++++++++------------ 6 files changed, 479 insertions(+), 309 deletions(-) diff --git a/cores/arduino/USB/CDC.cpp b/cores/arduino/USB/CDC.cpp index d53a0f45..770c035d 100644 --- a/cores/arduino/USB/CDC.cpp +++ b/cores/arduino/USB/CDC.cpp @@ -23,7 +23,7 @@ #include "sam.h" #include "wiring_constants.h" #include "USBCore.h" -#include "USB_device.h" +#include "USB/USB_device.h" #include "USBDesc.h" #include "USBAPI.h" diff --git a/cores/arduino/USB/HID.cpp b/cores/arduino/USB/HID.cpp index 56d632a7..63856a4a 100644 --- a/cores/arduino/USB/HID.cpp +++ b/cores/arduino/USB/HID.cpp @@ -20,7 +20,7 @@ #include "USBCore.h" #include "USBDesc.h" #include "sam.h" -#include "USB_device.h" +#include "USB/USB_device.h" #ifdef HID_ENABLED diff --git a/cores/arduino/USB/USBCore.cpp b/cores/arduino/USB/USBCore.cpp index 857d8dcd..80543bbe 100644 --- a/cores/arduino/USB/USBCore.cpp +++ b/cores/arduino/USB/USBCore.cpp @@ -21,7 +21,7 @@ #include "sam.h" #include "wiring_constants.h" #include "USBCore.h" -#include "USB_device.h" // needed for USB PID define +#include "USB/USB_device.h" // needed for USB PID define #include "USBDesc.h" #include "USBAPI.h" diff --git a/cores/arduino/USB/USB_device.h b/cores/arduino/USB/USB_device.h index dae619e4..d33aa20a 100644 --- a/cores/arduino/USB/USB_device.h +++ b/cores/arduino/USB/USB_device.h @@ -35,7 +35,7 @@ extern "C" { #endif #include <stdint.h> -#include "samd21_device.h" +#include "USB/samd21_device.h" // bEndpointAddress in Endpoint Descriptor diff --git a/cores/arduino/USB/samd21_device.c b/cores/arduino/USB/samd21_device.c index 010181df..a31e2bec 100644 --- a/cores/arduino/USB/samd21_device.c +++ b/cores/arduino/USB/samd21_device.c @@ -32,8 +32,8 @@ #include <string.h> #include "variant.h" -#include "USB_device.h" -#include "samd21_device.h" +#include "USB/USB_device.h" +#include "USB/samd21_device.h" #include "sam.h" #ifdef __cplusplus @@ -75,6 +75,7 @@ void UDD_Init(void) uint32_t pad_transn; uint32_t pad_transp; uint32_t pad_trim; + uint32_t i; /* Enable USB clock */ PM->APBBMASK.reg |= PM_APBBMASK_USB; @@ -148,7 +149,7 @@ void UDD_Init(void) USB->DEVICE.DESCADD.reg = (uint32_t)(&usb_endpoint_table[0]); // For USB_SPEED_FULL udd_force_full_speed(); - for (uint32_t i = 0; i < sizeof(usb_endpoint_table); i++) { + for (i = 0; i < sizeof(usb_endpoint_table); i++) { (*(uint32_t *)(&usb_endpoint_table[0]+i)) = 0; } diff --git a/cores/arduino/USB/samd21_host.c b/cores/arduino/USB/samd21_host.c index fc432e1e..3d8395f8 100644 --- a/cores/arduino/USB/samd21_host.c +++ b/cores/arduino/USB/samd21_host.c @@ -28,185 +28,330 @@ */ #include <stdio.h> +// #include <stdint.h> +// #include <string.h> +// +// #include "variant.h" +// #include "USB_host.h" +// #include "USB/samd21_host.h" +// #include "sam.h" -#if SAM3XA_SERIES +//#if SAM3XA_SERIES + +#ifdef HOST_DEFINED //#define TRACE_UOTGHS_HOST(x) x #define TRACE_UOTGHS_HOST(x) -extern void (*gpf_isr)(void); +//extern void (*gpf_isr)(void); // Handle UOTGHS Host driver state static uhd_vbus_state_t uhd_state = UHD_STATE_NO_VBUS; + __attribute__((__aligned__(4))) UsbHostDescriptor usb_pipe_table[USB_EPT_NUM]; + + +// NVM Software Calibration Area Mapping +// USB TRANSN calibration value. Should be written to the USB PADCAL register. +#define NVM_USB_PAD_TRANSN_POS 45 +#define NVM_USB_PAD_TRANSN_SIZE 5 +// USB TRANSP calibration value. Should be written to the USB PADCAL register. +#define NVM_USB_PAD_TRANSP_POS 50 +#define NVM_USB_PAD_TRANSP_SIZE 5 +// USB TRIM calibration value. Should be written to the USB PADCAL register. +#define NVM_USB_PAD_TRIM_POS 55 +#define NVM_USB_PAD_TRIM_SIZE 3 + /** - * \brief Interrupt sub routine for USB Host state machine management. + * \brief Initialize the SAMD21 host driver. */ -static void UHD_ISR(void) +void UHD_Init(void) { - // Manage dis/connection event - if (Is_uhd_disconnection() && Is_uhd_disconnection_int_enabled()) { - TRACE_UOTGHS_HOST(printf(">>> UHD_ISR : Disconnection INT\r\n");) - uhd_ack_disconnection(); - uhd_disable_disconnection_int(); - // Stop reset signal, in case of disconnection during reset - uhd_stop_reset(); - // Disable wakeup/resumes interrupts, - // in case of disconnection during suspend mode - //UOTGHS->UOTGHS_HSTIDR = UOTGHS_HSTIDR_HWUPIEC - // | UOTGHS_HSTIDR_RSMEDIEC - // | UOTGHS_HSTIDR_RXRSMIEC; - uhd_ack_connection(); - uhd_enable_connection_int(); - uhd_state = UHD_STATE_DISCONNECTED; - return; - } - if (Is_uhd_connection() && Is_uhd_connection_int_enabled()) { - TRACE_UOTGHS_HOST(printf(">>> UHD_ISR : Connection INT\r\n");) - uhd_ack_connection(); - uhd_disable_connection_int(); - uhd_ack_disconnection(); - uhd_enable_disconnection_int(); - //uhd_enable_sof(); - uhd_state = UHD_STATE_CONNECTED; - return; + uint32_t pad_transn; + uint32_t pad_transp; + uint32_t pad_trim; + + /* Enable USB clock */ + PM->APBBMASK.reg |= PM_APBBMASK_USB; + + /* Set up the USB DP/DN pins */ + PORT->Group[0].PINCFG[PIN_PA24G_USB_DM].bit.PMUXEN = 1; + PORT->Group[0].PMUX[PIN_PA24G_USB_DM/2].reg &= ~(0xF << (4 * (PIN_PA24G_USB_DM & 0x01u))); + PORT->Group[0].PMUX[PIN_PA24G_USB_DM/2].reg |= MUX_PA24G_USB_DM << (4 * (PIN_PA24G_USB_DM & 0x01u)); + PORT->Group[0].PINCFG[PIN_PA25G_USB_DP].bit.PMUXEN = 1; + PORT->Group[0].PMUX[PIN_PA25G_USB_DP/2].reg &= ~(0xF << (4 * (PIN_PA25G_USB_DP & 0x01u))); + PORT->Group[0].PMUX[PIN_PA25G_USB_DP/2].reg |= MUX_PA25G_USB_DP << (4 * (PIN_PA25G_USB_DP & 0x01u)); + + /* ---------------------------------------------------------------------------------------------- + * Put Generic Clock Generator 0 as source for Generic Clock Multiplexer 6 (USB reference) + */ + GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID( 6 ) | // Generic Clock Multiplexer 6 + GCLK_CLKCTRL_GEN_GCLK0 | // Generic Clock Generator 0 is source + GCLK_CLKCTRL_CLKEN ; + + while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY ) + { + /* Wait for synchronization */ } - // Manage Vbus error - if (Is_uhd_vbus_error_interrupt()) - { - TRACE_UOTGHS_HOST(printf(">>> UHD_ISR : VBUS error INT\r\n");) - uhd_ack_vbus_error_interrupt(); - uhd_state = UHD_STATE_DISCONNECTED; //UHD_STATE_ERROR; - return; + /* Reset */ + USB->HOST.CTRLA.bit.SWRST = 1; + while (USB->HOST.SYNCBUSY.bit.SWRST) { + /* Sync wait */ } - // Check USB clock ready after asynchronous interrupt - while (!Is_otg_clock_usable()) - ; - otg_unfreeze_clock(); + udd_enable(); - // Manage Vbus state change - if (Is_otg_vbus_transition()) - { - otg_ack_vbus_transition(); - if (Is_otg_vbus_high()) - { - TRACE_UOTGHS_HOST(printf(">>> UHD_ISR : VBUS transition INT : UHD_STATE_DISCONNECT\r\n");) - uhd_state = UHD_STATE_DISCONNECTED; - } - else - { - TRACE_UOTGHS_HOST(printf(">>> UHD_ISR : VBUS transition INT : UHD_STATE_NO_VBUS\r\n");) - otg_freeze_clock(); - uhd_state = UHD_STATE_NO_VBUS; - } - TRACE_UOTGHS_HOST(printf(">>> UHD_ISR : VBUS transition INT : done.\r\n");) - return; - } + /* Load Pad Calibration */ + pad_transn =( *((uint32_t *)(NVMCTRL_OTP4) // Non-Volatile Memory Controller + + (NVM_USB_PAD_TRANSN_POS / 32)) + >> (NVM_USB_PAD_TRANSN_POS % 32)) + & ((1 << NVM_USB_PAD_TRANSN_SIZE) - 1); - // Other errors - if (Is_uhd_errors_interrupt()) - { - TRACE_UOTGHS_HOST(printf(">>> UHD_ISR : Other error INT\r\n");) - uhd_ack_errors_interrupt(); - return; + if (pad_transn == 0x1F) { // maximum value (31) + pad_transn = 5; } -} - -/** - * \brief Set the interrupt sub routines callback for USB interrupts. - * - * \param pf_isr the ISR address. - */ -void UHD_SetStack(void (*pf_isr)(void)) -{ - gpf_isr = pf_isr; -} -/** - * \brief Initialize the UOTGHS host driver. - */ -void UHD_Init(void) -{ - irqflags_t flags; + USB->HOST.PADCAL.bit.TRANSN = pad_transn; - // To avoid USB interrupt before end of initialization - flags = cpu_irq_save(); + pad_transp =( *((uint32_t *)(NVMCTRL_OTP4) + + (NVM_USB_PAD_TRANSP_POS / 32)) + >> (NVM_USB_PAD_TRANSP_POS % 32)) + & ((1 << NVM_USB_PAD_TRANSP_SIZE) - 1); - // Setup USB Host interrupt callback - UHD_SetStack(&UHD_ISR); + if (pad_transp == 0x1F) { // maximum value (31) + pad_transp = 29; + } - // Enables the USB Clock - pmc_enable_upll_clock(); - pmc_switch_udpck_to_upllck(0); // div=0+1 - pmc_enable_udpck(); - pmc_enable_periph_clk(ID_UOTGHS); + USB->HOST.PADCAL.bit.TRANSP = pad_transp; - // Always authorize asynchronous USB interrupts to exit of sleep mode - // For SAM3 USB wake up device except BACKUP mode - NVIC_SetPriority((IRQn_Type) ID_UOTGHS, 0); - NVIC_EnableIRQ((IRQn_Type) ID_UOTGHS); + pad_trim =( *((uint32_t *)(NVMCTRL_OTP4) + + (NVM_USB_PAD_TRIM_POS / 32)) + >> (NVM_USB_PAD_TRIM_POS % 32)) + & ((1 << NVM_USB_PAD_TRIM_SIZE) - 1); - // ID pin not used then force host mode - otg_disable_id_pin(); - udd_force_host_mode(); + if (pad_trim == 0x7) { // maximum value (7) + pad_trim = 3; + } - // Signal is active low (because all SAM3X Pins are high after startup) - // Hence VBOF must be low after connection request to power up the remote device - // uhd_set_vbof_active_low(); + USB->HOST.PADCAL.bit.TRIM = pad_trim; - // According to the Arduino Due circuit the VBOF must be active high to power up the remote device - uhd_set_vbof_active_high(); + /* Set the configuration */ + udd_force_host_mode(); + udd_device_run_in_standby(); + // Set address of USB SRAM + USB->HOST.DESCADD.reg = (uint32_t)(&usb_endpoint_table[0]); + // For USB_SPEED_FULL + udd_force_full_speed(); + for (uint32_t i = 0; i < sizeof(usb_endpoint_table); i++) { + (*(uint32_t *)(&usb_endpoint_table[0]+i)) = 0; + } - otg_enable_pad(); - otg_enable(); + uhd_state = UHD_STATE_NO_VBUS; - otg_unfreeze_clock(); + USB->HOST.CTRLB.bit.VBUSOK = 1; - // Check USB clock - while (!Is_otg_clock_usable()) - ; + // Configure interrupts + NVIC_SetPriority((IRQn_Type) USB_IRQn, 0UL); + NVIC_EnableIRQ((IRQn_Type) USB_IRQn); +} - // Clear all interrupts that may have been set by a previous host mode - UOTGHS->UOTGHS_HSTICR = UOTGHS_HSTICR_DCONNIC | UOTGHS_HSTICR_DDISCIC - | UOTGHS_HSTICR_HSOFIC | UOTGHS_HSTICR_HWUPIC - | UOTGHS_HSTICR_RSMEDIC | UOTGHS_HSTICR_RSTIC - | UOTGHS_HSTICR_RXRSMIC; +// /** +// * \brief Initialize the UOTGHS host driver. +// */ +// void UHD_Init(void) +// { +// // irqflags_t flags; +// +// // To avoid USB interrupt before end of initialization +// // flags = cpu_irq_save(); +// +// // Setup USB Host interrupt callback +// // UHD_SetStack(&UHD_ISR); +// +// // Enables the USB Clock +// pmc_enable_upll_clock(); +// pmc_switch_udpck_to_upllck(0); // div=0+1 +// pmc_enable_udpck(); +// pmc_enable_periph_clk(ID_UOTGHS); +// +// // Always authorize asynchronous USB interrupts to exit of sleep mode +// // For SAM3 USB wake up device except BACKUP mode +// NVIC_SetPriority((IRQn_Type) ID_UOTGHS, 0); +// NVIC_EnableIRQ((IRQn_Type) ID_UOTGHS); +// +// // ID pin not used then force host mode +// otg_disable_id_pin(); +// udd_force_host_mode(); +// +// // Signal is active low (because all SAM3X Pins are high after startup) +// // Hence VBOF must be low after connection request to power up the remote device +// // uhd_set_vbof_active_low(); +// +// // According to the Arduino Due circuit the VBOF must be active high to power up the remote device +// uhd_set_vbof_active_high(); +// +// otg_enable_pad(); +// otg_enable(); +// +// otg_unfreeze_clock(); +// +// // Check USB clock +// while (!Is_otg_clock_usable()) +// ; +// +// // Clear all interrupts that may have been set by a previous host mode +// UOTGHS->UOTGHS_HSTICR = UOTGHS_HSTICR_DCONNIC | UOTGHS_HSTICR_DDISCIC +// | UOTGHS_HSTICR_HSOFIC | UOTGHS_HSTICR_HWUPIC +// | UOTGHS_HSTICR_RSMEDIC | UOTGHS_HSTICR_RSTIC +// | UOTGHS_HSTICR_RXRSMIC; +// +// otg_ack_vbus_transition(); +// +// // Enable Vbus change and error interrupts +// // Disable automatic Vbus control after Vbus error +// Set_bits(UOTGHS->UOTGHS_CTRL, +// UOTGHS_CTRL_VBUSHWC | UOTGHS_CTRL_VBUSTE | UOTGHS_CTRL_VBERRE); +// +// uhd_enable_vbus(); +// +// // Force Vbus interrupt when Vbus is always high +// // This is possible due to a short timing between a Host mode stop/start. +// if (Is_otg_vbus_high()) +// { +// otg_raise_vbus_transition(); +// } +// +// // Enable main control interrupt +// // Connection, SOF and reset +// UOTGHS->UOTGHS_HSTIER = UOTGHS_HSTICR_DCONNIC; +// +// otg_freeze_clock(); +// +// uhd_state = UHD_STATE_NO_VBUS; +// +// // cpu_irq_restore(flags); +// } - otg_ack_vbus_transition(); - // Enable Vbus change and error interrupts - // Disable automatic Vbus control after Vbus error - Set_bits(UOTGHS->UOTGHS_CTRL, - UOTGHS_CTRL_VBUSHWC | UOTGHS_CTRL_VBUSTE | UOTGHS_CTRL_VBERRE); +/** + * \brief Interrupt sub routine for USB Host state machine management. + */ +//static void UHD_ISR(void) +void USB_Handler(void) +{ + uint16_t flags; + uint8_t i; + uint8_t ept_int; + + ept_int = udd_endpoint_interrupt(); + + /* Not endpoint interrupt */ + if (0 == ept_int) + { - uhd_enable_vbus(); - // Force Vbus interrupt when Vbus is always high - // This is possible due to a short timing between a Host mode stop/start. - if (Is_otg_vbus_high()) - { - otg_raise_vbus_transition(); } + else + { + /* host interrupts */ + + /* get interrupt flags */ + flags = USB->HOST.INTFLAG.reg; + + /* host SOF interrupt */ + if (flags & USB_HOST_INTFLAG_HSOF) { + /* clear the flag */ + USB->HOST.INTFLAG.reg = USB_HOST_INTFLAG_HSOF; + uhd_state = UHD_STATE_CONNECTED; + return; + } + + /* host reset interrupt */ + if (flags & USB_HOST_INTFLAG_RST) { + /* clear the flag */ + USB->HOST.INTFLAG.reg = USB_HOST_INTFLAG_RST; + uhd_state = UHD_STATE_DISCONNECTED; //UHD_STATE_ERROR; + return; + } + + /* host upstream resume interrupts */ + if (flags & USB_HOST_INTFLAG_UPRSM) { + /* clear the flags */ + USB->HOST.INTFLAG.reg = USB_HOST_INTFLAG_UPRSM; + uhd_state = UHD_STATE_DISCONNECTED; //UHD_STATE_ERROR; + return; + } + + /* host downstream resume interrupts */ + if (flags & USB_HOST_INTFLAG_DNRSM) { + /* clear the flags */ + USB->HOST.INTFLAG.reg = USB_HOST_INTFLAG_DNRSM; + uhd_state = UHD_STATE_DISCONNECTED; //UHD_STATE_ERROR; + return; + } + + /* host wakeup interrupts */ + if (flags & USB_HOST_INTFLAG_WAKEUP) { + /* clear the flags */ + USB->HOST.INTFLAG.reg = USB_HOST_INTFLAG_WAKEUP; + uhd_state = UHD_STATE_CONNECTED; //UHD_STATE_ERROR; + return; + } + + /* host ram access interrupt */ + if (flags & USB_HOST_INTFLAG_RAMACER) { + /* clear the flag */ + USB->HOST.INTFLAG.reg = USB_HOST_INTFLAG_RAMACER; + uhd_state = UHD_STATE_DISCONNECTED; //UHD_STATE_ERROR; + return; + } + + /* host connect interrupt */ + if (flags & USB_HOST_INTFLAG_DCONN) { + TRACE_UOTGHS_HOST(printf(">>> UHD_ISR : Connection INT\r\n");) + /* clear the flag */ + uhd_ack_connection(); + uhd_disable_connection_int(); + uhd_ack_disconnection(); + uhd_enable_disconnection_int(); + //uhd_enable_sof(); + uhd_state = UHD_STATE_CONNECTED; + return; + } + + /* host disconnect interrupt */ + if (flags & USB_HOST_INTFLAG_DDISC) { + TRACE_UOTGHS_HOST(printf(">>> UHD_ISR : Disconnection INT\r\n");) + /* clear the flag */ + uhd_ack_disconnection(); + uhd_disable_disconnection_int(); + // Stop reset signal, in case of disconnection during reset + uhd_stop_reset(); + // Disable wakeup/resumes interrupts, + // in case of disconnection during suspend mode + //UOTGHS->UOTGHS_HSTIDR = UOTGHS_HSTIDR_HWUPIEC + // | UOTGHS_HSTIDR_RSMEDIEC + // | UOTGHS_HSTIDR_RXRSMIEC; + uhd_ack_connection(); + uhd_enable_connection_int(); + uhd_state = UHD_STATE_DISCONNECTED; + return; + } + + } - // Enable main control interrupt - // Connection, SOF and reset - UOTGHS->UOTGHS_HSTIER = UOTGHS_HSTICR_DCONNIC; +} - otg_freeze_clock(); - uhd_state = UHD_STATE_NO_VBUS; - cpu_irq_restore(flags); -} /** * \brief Trigger a USB bus reset. */ void UHD_BusReset(void) { - uhd_start_reset(); + USB->HOST.CTRLB.bit.BUSRESET = 1;; } /** @@ -219,23 +364,7 @@ uhd_vbus_state_t UHD_GetVBUSState(void) return uhd_state; } -/*uhd_speed_t uhd_get_speed(void) -{ - switch (uhd_get_speed_mode()) - { - case UOTGHS_SR_SPEED_HIGH_SPEED: - return UHD_SPEED_HIGH; - - case UOTGHS_SR_SPEED_FULL_SPEED: - return UHD_SPEED_FULL; - case UOTGHS_SR_SPEED_LOW_SPEED: - return UHD_SPEED_LOW; - - default: - return UHD_SPEED_LOW; - } -}*/ /** * \brief Allocate FIFO for pipe 0. @@ -247,40 +376,31 @@ uhd_vbus_state_t UHD_GetVBUSState(void) * \retval 1 error. */ uint32_t UHD_Pipe0_Alloc(uint32_t ul_add, uint32_t ul_ep_size) -{ - if (ul_ep_size < 8) - { - TRACE_UOTGHS_HOST(printf("/!\\ UHD_EP0_Alloc : incorrect pipe size!\r\n");) - return 1; - } - - if (Is_uhd_pipe_enabled(0)) - { - // Pipe is already allocated - return 0; - } - - uhd_enable_pipe(0); - uhd_configure_pipe(0, // Pipe 0 - 0, // No frequency - 0, // Enpoint 0 - UOTGHS_HSTPIPCFG_PTYPE_CTRL, - UOTGHS_HSTPIPCFG_PTOKEN_SETUP, - ul_ep_size, - UOTGHS_HSTPIPCFG_PBK_1_BANK, 0); - - uhd_allocate_memory(0); - - if (!Is_uhd_pipe_configured(0)) - { - TRACE_UOTGHS_HOST(printf("/!\\ UHD_EP0_Alloc : incorrect pipe settings!\r\n");) - uhd_disable_pipe(0); - return 1; - } - - uhd_configure_address(0, ul_add); - - return 0; +{ + struct usb_host_pipe_config cfg; + + if (ep_size < 8) + { + return 0; + } + + /* set pipe config */ + USB->HOST.HostPipe[0].PCFG.bit.BK = 0; + USB->HOST.HostPipe[0].PCFG.bit.PTYPE = USB_HOST_PIPE_TYPE_CONTROL; + USB->HOST.HostPipe[0].BINTERVAL.reg = 0; + USB->HOST.HostPipe[0].PCFG.bit.PTOKEN = USB_HOST_PIPE_TOKEN_SETUP; + + memset((uint8_t *)&usb_pipe_table[pipe_num], 0, sizeof(usb_pipe_table[0])); + usb_pipe_table[pipe_num].HostDescBank[0].CTRL_PIPE.bit.PDADDR = 0; + usb_pipe_table[pipe_num].HostDescBank[0].CTRL_PIPE.bit.PEPNUM = 0; + usb_pipe_table[pipe_num].HostDescBank[0].PCKSIZE.bit.SIZE = 0x03; // 64 bytes + + USB->HOST.HostPipe[pipe_num].PINTENSET.reg = USB_HOST_PINTENSET_TRCPT_Msk; + USB->HOST.HostPipe[pipe_num].PINTENSET.reg = USB_HOST_PINTENSET_TRFAIL | USB_HOST_PINTENSET_PERR; + USB->HOST.HostPipe[pipe_num].PINTENSET.reg = USB_HOST_PINTENSET_TXSTP; + USB->HOST.HostPipe[pipe_num].PINTENSET.reg = USB_HOST_PINTENSET_STALL; + + return 1; } /** @@ -301,38 +421,42 @@ uint32_t UHD_Pipe0_Alloc(uint32_t ul_add, uint32_t ul_ep_size) * * \return the newly allocated pipe number on success, 0 otherwise. */ -uint32_t UHD_Pipe_Alloc(uint32_t ul_dev_addr, uint32_t ul_dev_ep, uint32_t ul_type, uint32_t ul_dir, uint32_t ul_maxsize, uint32_t ul_interval, uint32_t ul_nb_bank) -{ - uint32_t ul_pipe = 1; - - for (ul_pipe = 1; ul_pipe < UOTGHS_EPT_NUM; ++ul_pipe) - { - if (Is_uhd_pipe_enabled(ul_pipe)) - { - continue; - } - - uhd_enable_pipe(ul_pipe); - - uhd_configure_pipe(ul_pipe, ul_interval, ul_dev_ep, ul_type, ul_dir, - ul_maxsize, ul_nb_bank, UOTGHS_HSTPIPCFG_AUTOSW); - - uhd_allocate_memory(ul_pipe); - if (!Is_uhd_pipe_configured(ul_pipe)) - { - uhd_disable_pipe(ul_pipe); - return 0; - } - - uhd_configure_address(ul_pipe, ul_dev_addr); +// pipe = UHD_Pipe_Alloc(bAddress, epInfo[index].deviceEpNum, UOTGHS_HSTPIPCFG_PTYPE_BLK, UOTGHS_HSTPIPCFG_PTOKEN_IN, epInfo[index].maxPktSize, 0, UOTGHS_HSTPIPCFG_PBK_1_BANK); - // Pipe is configured and allocated successfully - return ul_pipe; - } +uint32_t UHD_Pipe_Alloc(uint32_t ul_dev_addr, uint32_t ul_dev_ep, uint32_t ul_type, uint32_t ul_dir, uint32_t ul_maxsize, uint32_t ul_interval, uint32_t ul_nb_bank) +//bool uhd_ep_alloc(usb_add_t add, usb_ep_desc_t *ep_desc) +{ + /* set pipe config */ + USB->HOST.HostPipe[ul_dev_ep].PCFG.bit.BK = ul_nb_bank; + USB->HOST.HostPipe[ul_dev_ep].PCFG.bit.PTYPE = ul_type; + USB->HOST.HostPipe[ul_dev_ep].BINTERVAL.reg = ul_interval; + + if (ul_dir & USB_EP_DIR_IN) + { + USB->HOST.HostPipe[ul_dev_ep].PCFG.bit.PTOKEN = USB_HOST_PIPE_TOKEN_IN; + USB->HOST.HostPipe[ul_dev_ep].PSTATUSSET.reg = USB_HOST_PSTATUSSET_BK0RDY; + } + else + { + USB->HOST.HostPipe[ul_dev_ep].PCFG.bit.PTOKEN = USB_HOST_PIPE_TOKEN_OUT; + USB->HOST.HostPipe[ul_dev_ep].PSTATUSCLR.reg = USB_HOST_PSTATUSCLR_BK0RDY; + } + + memset((uint8_t *)&usb_descriptor_table.usb_pipe_table[ul_dev_ep], 0, sizeof(usb_pipe_table[ul_dev_ep])); + + usb_descriptor_table.usb_pipe_table[ul_dev_ep].HostDescBank[0].CTRL_PIPE.bit.PDADDR = ul_dev_addr; + usb_descriptor_table.usb_pipe_table[ul_dev_ep].HostDescBank[0].CTRL_PIPE.bit.PEPNUM = ul_dev_ep; + usb_descriptor_table.usb_pipe_table[ul_dev_ep].HostDescBank[0].PCKSIZE.bit.SIZE = 0x03; // 64 bytes + + USB->HOST.HostPipe[pipe_num].PINTENSET.reg = USB_HOST_PINTENSET_TRCPT_Msk; + USB->HOST.HostPipe[pipe_num].PINTENSET.reg = USB_HOST_PINTENSET_TRFAIL | USB_HOST_PINTENSET_PERR; +// USB->HOST.HostPipe[pipe_num].PINTENSET.reg = USB_HOST_PINTENSET_TXSTP; + USB->HOST.HostPipe[pipe_num].PINTENSET.reg = USB_HOST_PINTENSET_STALL; + + return 1; +} - return 0; -} /** * \brief Free a pipe. @@ -345,6 +469,9 @@ void UHD_Pipe_Free(uint32_t ul_pipe) uhd_disable_pipe(ul_pipe); uhd_unallocate_memory(ul_pipe); uhd_reset_pipe(ul_pipe); + + // The Pipe is frozen and no additional requests will be sent to the device on this pipe address. + USB->HOST.HostPipe[pipe_num].PSTATUSSET.reg = USB_HOST_PSTATUSSET_PFREEZE; } /** @@ -356,26 +483,26 @@ void UHD_Pipe_Free(uint32_t ul_pipe) * * \return number of data read. */ -uint32_t UHD_Pipe_Read(uint32_t ul_pipe, uint32_t ul_size, uint8_t* data) +uint32_t UHD_Pipe_Read(uint32_t pipe_num, uint32_t buf_size, uint8_t* buf) { - uint8_t *ptr_ep_data = 0; - uint8_t nb_byte_received = 0; - uint32_t ul_nb_trans = 0; - - // Get information to read data - nb_byte_received = uhd_byte_count(ul_pipe); - - ptr_ep_data = (uint8_t *) & uhd_get_pipe_fifo_access(ul_pipe, 8); - - // Copy data from pipe to payload buffer - while (ul_size && nb_byte_received) { - *data++ = *ptr_ep_data++; - ul_nb_trans++; - ul_size--; - nb_byte_received--; - } - - return ul_nb_trans; + if (USB->HOST.HostPipe[pipe_num].PCFG.bit.PTYPE == USB_HOST_PIPE_TYPE_DISABLE) + { + return 0; + } + + /* get pipe config from setting register */ + usb_descriptor_table.usb_pipe_table[pipe_num].HostDescBank[0].ADDR.reg = (uint32_t)buf; + usb_descriptor_table.usb_pipe_table[pipe_num].HostDescBank[0].PCKSIZE.bit.BYTE_COUNT = 0; + usb_descriptor_table.usb_pipe_table[pipe_num].HostDescBank[0].PCKSIZE.bit.MULTI_PACKET_SIZE = buf_size; + USB->HOST.HostPipe[pipe_num].PCFG.bit.PTOKEN = USB_HOST_PIPE_TOKEN_IN; + + /* Start transfer */ + USB->HOST.HostPipe[pipe_num].PSTATUSCLR.reg = USB_HOST_PSTATUSCLR_BK0RDY; + + // Unfreeze pipe + USB->HOST.HostPipe[pipe_num].PSTATUSCLR.reg = USB_HOST_PSTATUSCLR_PFREEZE; + + return buf_size; } /** @@ -387,20 +514,36 @@ uint32_t UHD_Pipe_Read(uint32_t ul_pipe, uint32_t ul_size, uint8_t* data) */ void UHD_Pipe_Write(uint32_t ul_pipe, uint32_t ul_size, uint8_t* data) { - volatile uint8_t *ptr_ep_data = 0; - uint32_t i = 0; - // Check pipe - if (!Is_uhd_pipe_enabled(ul_pipe)) - { - // Endpoint not valid - TRACE_UOTGHS_HOST(printf("/!\\ UHD_EP_Send : pipe is not enabled!\r\n");) - return; - } - - ptr_ep_data = (volatile uint8_t *)&uhd_get_pipe_fifo_access(ul_pipe, 8); - for (i = 0; i < ul_size; ++i) - *ptr_ep_data++ = *data++; + if (USB->HOST.HostPipe[pipe_num].PCFG.bit.PTYPE == USB_HOST_PIPE_TYPE_DISABLE) + { + return 0; + } + + /* get pipe config from setting register */ + usb_descriptor_table.usb_pipe_table[pipe_num].HostDescBank[0].ADDR.reg = (uint32_t)buf; + usb_descriptor_table.usb_pipe_table[pipe_num].HostDescBank[0].PCKSIZE.bit.BYTE_COUNT = buf_size; + usb_descriptor_table.usb_pipe_table[pipe_num].HostDescBank[0].PCKSIZE.bit.MULTI_PACKET_SIZE = 0; + USB->HOST.HostPipe[pipe_num].PCFG.bit.PTOKEN = USB_HOST_PIPE_TOKEN_OUT; + + + return 1; + + +// volatile uint8_t *ptr_ep_data = 0; +// uint32_t i = 0; +// +// // Check pipe +// if (!Is_uhd_pipe_enabled(ul_pipe)) +// { +// // Endpoint not valid +// TRACE_UOTGHS_HOST(printf("/!\\ UHD_EP_Send : pipe is not enabled!\r\n");) +// return; +// } +// +// ptr_ep_data = (volatile uint8_t *)&uhd_get_pipe_fifo_access(ul_pipe, 8); +// for (i = 0; i < ul_size; ++i) +// *ptr_ep_data++ = *data++; } /** @@ -411,28 +554,34 @@ void UHD_Pipe_Write(uint32_t ul_pipe, uint32_t ul_size, uint8_t* data) */ void UHD_Pipe_Send(uint32_t ul_pipe, uint32_t ul_token_type) { - // Check pipe - if (!Is_uhd_pipe_enabled(ul_pipe)) - { - // Endpoint not valid - TRACE_UOTGHS_HOST(printf("/!\\ UHD_EP_Send : pipe %lu is not enabled!\r\n", ul_pipe);) - return; - } - - // Set token type for zero length packet - // When actually using the FIFO, pipe token MUST be configured first - uhd_configure_pipe_token(ul_pipe, ul_token_type); - - // Clear interrupt flags - uhd_ack_setup_ready(ul_pipe); - uhd_ack_in_received(ul_pipe); - uhd_ack_out_ready(ul_pipe); - uhd_ack_short_packet(ul_pipe); - uhd_ack_nak_received(ul_pipe); - - // Send actual packet - uhd_ack_fifocon(ul_pipe); - uhd_unfreeze_pipe(ul_pipe); + /* Start transfer */ + USB->HOST.HostPipe[pipe_num].PSTATUSSET.reg = USB_HOST_PSTATUSSET_BK0RDY; + + // Unfreeze pipe + USB->HOST.HostPipe[pipe_num].PSTATUSCLR.reg = USB_HOST_PSTATUSCLR_PFREEZE; + +// // Check pipe +// if (!Is_uhd_pipe_enabled(ul_pipe)) +// { +// // Endpoint not valid +// TRACE_UOTGHS_HOST(printf("/!\\ UHD_EP_Send : pipe %lu is not enabled!\r\n", ul_pipe);) +// return; +// } +// +// // Set token type for zero length packet +// // When actually using the FIFO, pipe token MUST be configured first +// uhd_configure_pipe_token(ul_pipe, ul_token_type); +// +// // Clear interrupt flags +// uhd_ack_setup_ready(ul_pipe); +// uhd_ack_in_received(ul_pipe); +// uhd_ack_out_ready(ul_pipe); +// uhd_ack_short_packet(ul_pipe); +// uhd_ack_nak_received(ul_pipe); +// +// // Send actual packet +// uhd_ack_fifocon(ul_pipe); +// uhd_unfreeze_pipe(ul_pipe); } /** @@ -446,44 +595,64 @@ void UHD_Pipe_Send(uint32_t ul_pipe, uint32_t ul_token_type) */ uint32_t UHD_Pipe_Is_Transfer_Complete(uint32_t ul_pipe, uint32_t ul_token_type) { - // Check for transfer completion depending on token type - switch (ul_token_type) - { - case UOTGHS_HSTPIPCFG_PTOKEN_SETUP: - if (Is_uhd_setup_ready(ul_pipe)) - { - uhd_freeze_pipe(ul_pipe); - uhd_ack_setup_ready(ul_pipe); - return 1; - } - - case UOTGHS_HSTPIPCFG_PTOKEN_IN: - if (Is_uhd_in_received(ul_pipe)) - { - // In case of low USB speed and with a high CPU frequency, - // a ACK from host can be always running on USB line - // then wait end of ACK on IN pipe. - while(!Is_uhd_pipe_frozen(ul_pipe)) - ; - - // IN packet received - uhd_ack_in_received(ul_pipe); - - return 1; - } - - case UOTGHS_HSTPIPCFG_PTOKEN_OUT: - if (Is_uhd_out_ready(ul_pipe)) - { - // OUT packet sent - uhd_freeze_pipe(ul_pipe); - uhd_ack_out_ready(ul_pipe); - - return 1; - } + + // Freeze pipe + USB->HOST.HostPipe[pipe_num].PSTATUSSET.reg = USB_HOST_PSTATUSSET_PFREEZE; + switch(uhd_ctrl_request_phase) { + case UHD_CTRL_REQ_PHASE_DATA_IN: + _uhd_ctrl_phase_data_in(p_callback_para->transfered_size); + break; + case UHD_CTRL_REQ_PHASE_ZLP_IN: + _uhd_ctrl_request_end(UHD_TRANS_NOERROR); + break; + case UHD_CTRL_REQ_PHASE_DATA_OUT: + _uhd_ctrl_phase_data_out(); + break; + case UHD_CTRL_REQ_PHASE_ZLP_OUT: + _uhd_ctrl_request_end(UHD_TRANS_NOERROR); + break; } + +// // Check for transfer completion depending on token type +// switch (ul_token_type) +// { +// case UOTGHS_HSTPIPCFG_PTOKEN_SETUP: +// if (Is_uhd_setup_ready(ul_pipe)) +// { +// uhd_freeze_pipe(ul_pipe); +// uhd_ack_setup_ready(ul_pipe); +// return 1; +// } +// +// case UOTGHS_HSTPIPCFG_PTOKEN_IN: +// if (Is_uhd_in_received(ul_pipe)) +// { +// // In case of low USB speed and with a high CPU frequency, +// // a ACK from host can be always running on USB line +// // then wait end of ACK on IN pipe. +// while(!Is_uhd_pipe_frozen(ul_pipe)) +// ; +// +// // IN packet received +// uhd_ack_in_received(ul_pipe); +// +// return 1; +// } +// +// case UOTGHS_HSTPIPCFG_PTOKEN_OUT: +// if (Is_uhd_out_ready(ul_pipe)) +// { +// // OUT packet sent +// uhd_freeze_pipe(ul_pipe); +// uhd_ack_out_ready(ul_pipe); +// +// return 1; +// } +// } +// return 0; } -#endif /* SAM3XA_SERIES */ +#endif /* SAM3XA_SERIES HOST_DEFINED */ + -- GitLab