[sam] first USB with Init/Attach/Detach

This commit is contained in:
Thibaut VIARD 2012-04-28 15:16:13 +02:00
parent 08b614048d
commit 86533a5e8f
7 changed files with 221 additions and 24 deletions

View File

@ -15,8 +15,8 @@ public:
USB_();
bool configured();
void attach();
void detach(); // Serial port goes down too...
bool attach();
bool detach(); // Serial port goes down too...
void poll();
};
extern USB_ USB;

View File

@ -94,8 +94,9 @@ const DeviceDescriptor USB_DeviceDescriptorA =
//==================================================================
//==================================================================
volatile uint8_t _usbConfiguration = 0;
uint8_t _cdcComposite = 0;
volatile uint32_t _usbConfiguration = 0;
volatile uint32_t _usbInitialized = 0;
uint32_t _cdcComposite = 0;
//==================================================================
@ -129,7 +130,7 @@ int USBD_Recv(uint8_t ep, void* d, int len)
}
n = FifoByteCount(ep);
len = min(n,len);
n = len;
dst = (uint8_t*)d;
@ -151,16 +152,16 @@ static bool USBD_SendControl(uint8_t d)
{
return false;
}
Send8( d ) ;
if ( !((_cmark + 1) & 0x3F) )
{
ClearIN(); // Fifo is full, release this packet
}
}
_cmark++;
return true ;
}
@ -173,7 +174,7 @@ int USBD_SendControl(uint8_t flags, const void* d, int len)
while ( len-- )
{
uint8_t c = *data++ ;
if ( !SendControl( c ) )
{
return -1;
@ -293,7 +294,7 @@ static bool USBD_SendDescriptor(Setup& setup)
{
return false ;
}
if ( desc_length == 0 )
{
desc_length = *desc_addr;
@ -308,7 +309,7 @@ static bool USBD_SendDescriptor(Setup& setup)
void USB_ISR()
{
SetEP(0) ;
if ( !ReceivedSetupInt() )
{
return;
@ -367,7 +368,7 @@ void USB_ISR()
{
InitEndpoints();
_usbConfiguration = setup.wValueL;
}
}
else
{
ok = false;
@ -458,17 +459,38 @@ USB_ USB;
USB_::USB_()
{
if ( USBD_Init() == 0UL )
{
_usbInitialized=1UL ;
}
}
void USB_::attach(void)
bool USB_::attach(void)
{
USBD_Attach() ;
if ( _usbInitialized != 0UL )
{
USBD_Attach() ;
return true ;
}
else
{
return false ;
}
}
void USB_::detach(void)
bool USB_::detach(void)
{
UDPHS->UDPHS_CTRL |= UDPHS_CTRL_DETACH; // detach
UDPHS->UDPHS_CTRL &= ~UDPHS_CTRL_PULLD_DIS; // Enable Pull Down
if ( _usbInitialized != 0UL )
{
USBD_Detach() ;
return true ;
}
else
{
return false ;
}
}
// Check for interrupts

View File

@ -148,8 +148,6 @@ create_output:
# @echo *$(A_SRC)
# @echo -------------------------
# -@mkdir $(subst /,$(SEP),$(OUTPUT_BIN)) 1>NUL 2>&1
-mkdir $(subst /,$(SEP),$(OUTPUT_BIN))
-@mkdir $(OUTPUT_PATH) 1>NUL 2>&1
$(addprefix $(OUTPUT_PATH)/,$(C_OBJ)): $(OUTPUT_PATH)/%.o: %.c

View File

@ -148,8 +148,6 @@ create_output:
# @echo *$(A_SRC)
# @echo -------------------------
# -@mkdir $(subst /,$(SEP),$(OUTPUT_BIN)) 1>NUL 2>&1
-mkdir $(subst /,$(SEP),$(OUTPUT_BIN))
-@mkdir $(OUTPUT_PATH) 1>NUL 2>&1
$(addprefix $(OUTPUT_PATH)/,$(C_OBJ)): $(OUTPUT_PATH)/%.o: %.c

View File

@ -8,7 +8,7 @@
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
@ -64,6 +64,8 @@ extern void USBD_InitEndpoints(void) ;
extern void USBD_InitControl(int end) ;
extern uint32_t USBD_Init(void) ;
extern void USBD_Attach(void) ;
extern void USBD_Detach(void) ;

View File

@ -8,7 +8,7 @@
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
@ -19,4 +19,29 @@
#ifndef UOTGHS_H_INCLUDED
#define UOTGHS_H_INCLUDED
#define EP_SINGLE_64 (0x32UL) // EP0
#define EP_DOUBLE_64 (0x36UL) // Other endpoints
// Control Endpoint
#define EP_TYPE_CONTROL (UOTGHS_DEVEPTCFG_EPSIZE_64_BYTE | UOTGHS_DEVEPTCFG_EPTYPE_CTRL | UOTGHS_DEVEPTCFG_EPBK_1_BANK)
// CDC Endpoints
#ifdef CDC_ENABLED
#define EP_TYPE_BULK_IN (UOTGHS_DEVEPTCFG_EPSIZE_512_BYTE | UOTGHS_DEVEPTCFG_EPDIR_IN | UOTGHS_DEVEPTCFG_EPTYPE_BLK | UOTGHS_DEVEPTCFG_EPBK_2_BANK)
#define EP_TYPE_BULK_OUT (UOTGHS_DEVEPTCFG_EPSIZE_512_BYTE | UOTGHS_DEVEPTCFG_EPTYPE_BLK | UOTGHS_DEVEPTCFG_EPBK_2_BANK)
#define EP_TYPE_INTERRUPT_IN (UOTGHS_DEVEPTCFG_EPSIZE_64_BYTE | UOTGHS_DEVEPTCFG_EPDIR_IN | UOTGHS_DEVEPTCFG_EPTYPE_INTRPT | UOTGHS_DEVEPTCFG_EPBK_2_BANK)
#endif
// HID Endpoints
#ifdef HID_ENABLED
#define EP_TYPE_INTERRUPT_IN_HID (UOTGHS_DEVEPTCFG_EPSIZE_64_BYTE | UOTGHS_DEVEPTCFG_EPDIR_IN | UOTGHS_DEVEPTCFG_EPTYPE_INTRPT | UOTGHS_DEVEPTCFG_EPBK_2_BANK)
#endif
// Various definitions
#define EP_TYPE_INTERRUPT_OUT (UOTGHS_DEVEPTCFG_EPSIZE_64_BYTE | UOTGHS_DEVEPTCFG_EPTYPE_INTRPT | UOTGHS_DEVEPTCFG_EPTYPE_INTRPT | UOTGHS_DEVEPTCFG_EPBK_1_BANK)
#define EP_TYPE_ISOCHRONOUS_IN (UOTGHS_DEVEPTCFG_EPSIZE_1024_BYTE | UOTGHS_DEVEPTCFG_EPDIR_IN | UOTGHS_DEVEPTCFG_EPTYPE_ISO | UOTGHS_DEVEPTCFG_EPBK_3_BANK)
#define EP_TYPE_ISOCHRONOUS_OUT (UOTGHS_DEVEPTCFG_EPSIZE_1024_BYTE | UOTGHS_DEVEPTCFG_EPTYPE_ISO | UOTGHS_DEVEPTCFG_EPBK_3_BANK)
#endif /* UOTGHS_H_INCLUDED */

View File

@ -8,7 +8,7 @@
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
@ -20,5 +20,157 @@
#if SAM3XA_SERIES
void USBD_InitEndpoints(void)
{
}
uint32_t USBD_Init(void)
{
uint32_t ul ;
// Enables the USB Clock
pmc_enable_periph_clk(ID_UOTGHS);
pmc_enable_upll_clock();
pmc_switch_udpck_to_upllck(0); // div=0+1
pmc_enable_udpck();
// Configure interrupts
NVIC_SetPriority((IRQn_Type) ID_UOTGHS, 0UL);
NVIC_EnableIRQ((IRQn_Type) ID_UOTGHS);
// Always authorize asynchrone USB interrupts to exit from sleep mode
// for SAM3 USB wake up device except BACKUP mode
pmc_set_fast_startup_input(PMC_FSMR_USBAL);
// Enable USB macro
UOTGHS->UOTGHS_CTRL |= UOTGHS_CTRL_USBE;
// Automatic mode speed for device
UOTGHS->UOTGHS_DEVCTRL &= ~UOTGHS_DEVCTRL_SPDCONF_Msk; // Normal mode
UOTGHS->UOTGHS_DEVCTRL &= ~( UOTGHS_DEVCTRL_LS | UOTGHS_DEVCTRL_TSTJ | UOTGHS_DEVCTRL_TSTK |
UOTGHS_DEVCTRL_TSTPCKT | UOTGHS_DEVCTRL_OPMODE2 ); // Normal mode
UOTGHS->UOTGHS_DEVCTRL = 0;
UOTGHS->UOTGHS_HSTCTRL = 0;
// Enable OTG pad
UOTGHS->UOTGHS_CTRL |= UOTGHS_CTRL_OTGPADE;
// Enable clock OTG pad
UOTGHS->UOTGHS_CTRL &= ~UOTGHS_CTRL_FRZCLK;
// Usb disable
UOTGHS->UOTGHS_CTRL &= ~UOTGHS_CTRL_USBE;
UOTGHS->UOTGHS_CTRL &= ~UOTGHS_CTRL_OTGPADE;
UOTGHS->UOTGHS_CTRL |= UOTGHS_CTRL_FRZCLK;
// Usb enable
UOTGHS->UOTGHS_CTRL |= UOTGHS_CTRL_USBE;
UOTGHS->UOTGHS_CTRL |= UOTGHS_CTRL_OTGPADE;
UOTGHS->UOTGHS_CTRL &= ~UOTGHS_CTRL_FRZCLK;
// Usb select_device
UOTGHS->UOTGHS_CTRL &= ~UOTGHS_CTRL_UIDE;
UOTGHS->UOTGHS_CTRL |= UOTGHS_CTRL_UIMOD_Device;
// Device is in the Attached state
// deviceState = USBD_STATE_SUSPENDED;
// previousDeviceState = USBD_STATE_POWERED;
// Enable USB macro and clear all other bits
UOTGHS->UOTGHS_DEVCTRL |= UOTGHS_CTRL_USBE;
UOTGHS->UOTGHS_DEVCTRL = UOTGHS_CTRL_USBE;
// Configure the pull-up on D+ and disconnect it
USBD_Detach();
// Clear General IT
UOTGHS->UOTGHS_SCR = (UOTGHS_SCR_IDTIC|UOTGHS_SCR_VBUSTIC|UOTGHS_SCR_SRPIC|UOTGHS_SCR_VBERRIC|UOTGHS_SCR_BCERRIC|UOTGHS_SCR_ROLEEXIC|UOTGHS_SCR_HNPERRIC|UOTGHS_SCR_STOIC|UOTGHS_SCR_VBUSRQC);
// Clear OTG Device IT
UOTGHS->UOTGHS_DEVICR = (UOTGHS_DEVICR_SUSPC|UOTGHS_DEVICR_MSOFC|UOTGHS_DEVICR_SOFC|UOTGHS_DEVICR_EORSTC|UOTGHS_DEVICR_WAKEUPC|UOTGHS_DEVICR_EORSMC|UOTGHS_DEVICR_UPRSMC);
// Clear OTG Host IT
UOTGHS->UOTGHS_HSTICR = (UOTGHS_HSTICR_DCONNIC|UOTGHS_HSTICR_DDISCIC|UOTGHS_HSTICR_RSTIC|UOTGHS_HSTICR_RSMEDIC|UOTGHS_HSTICR_RXRSMIC|UOTGHS_HSTICR_HSOFIC|UOTGHS_HSTICR_HWUPIC);
// Reset all Endpoints Fifos
UOTGHS->UOTGHS_DEVEPT |= (UOTGHS_DEVEPT_EPRST0|UOTGHS_DEVEPT_EPRST1|UOTGHS_DEVEPT_EPRST2|UOTGHS_DEVEPT_EPRST3|UOTGHS_DEVEPT_EPRST4|
UOTGHS_DEVEPT_EPRST5|UOTGHS_DEVEPT_EPRST6|UOTGHS_DEVEPT_EPRST7|UOTGHS_DEVEPT_EPRST8);
UOTGHS->UOTGHS_DEVEPT &= ~(UOTGHS_DEVEPT_EPRST0|UOTGHS_DEVEPT_EPRST1|UOTGHS_DEVEPT_EPRST2|UOTGHS_DEVEPT_EPRST3|UOTGHS_DEVEPT_EPRST4|
UOTGHS_DEVEPT_EPRST5|UOTGHS_DEVEPT_EPRST6|UOTGHS_DEVEPT_EPRST7|UOTGHS_DEVEPT_EPRST8);
// Disable all endpoints
UOTGHS->UOTGHS_DEVEPT &= ~(UOTGHS_DEVEPT_EPEN0|UOTGHS_DEVEPT_EPEN1|UOTGHS_DEVEPT_EPEN2|UOTGHS_DEVEPT_EPEN3|UOTGHS_DEVEPT_EPEN4|
UOTGHS_DEVEPT_EPEN5|UOTGHS_DEVEPT_EPEN6|UOTGHS_DEVEPT_EPEN7|UOTGHS_DEVEPT_EPEN8);
// Device is in the Attached state
// deviceState = USBD_STATE_SUSPENDED;
// previousDeviceState = USBD_STATE_POWERED;
// Automatic mode speed for device
UOTGHS->UOTGHS_DEVCTRL &= ~UOTGHS_DEVCTRL_SPDCONF_Msk;
// Force Full Speed mode for device
//UOTGHS->UOTGHS_DEVCTRL = UOTGHS_DEVCTRL_SPDCONF_FORCED_FS;
// Force High Speed mode for device
//UOTGHS->UOTGHS_DEVCTRL = UOTGHS_DEVCTRL_SPDCONF_HIGH_SPEED;
UOTGHS->UOTGHS_DEVCTRL &= ~(UOTGHS_DEVCTRL_LS|UOTGHS_DEVCTRL_TSTJ| UOTGHS_DEVCTRL_TSTK|UOTGHS_DEVCTRL_TSTPCKT|UOTGHS_DEVCTRL_OPMODE2) ;
// Enable USB macro
UOTGHS->UOTGHS_DEVCTRL |= UOTGHS_CTRL_USBE;
// Enable the UID pin select
UOTGHS->UOTGHS_DEVCTRL |= UOTGHS_CTRL_UIDE;
// Enable OTG pad
UOTGHS->UOTGHS_DEVCTRL |= UOTGHS_CTRL_OTGPADE;
// Enable clock OTG pad
UOTGHS->UOTGHS_DEVCTRL &= ~UOTGHS_CTRL_FRZCLK;
// With OR without DMA !!!
// Initialization of DMA
for( ul=1; ul<= UOTGHSDEVDMA_NUMBER ; ul++ )
{
// RESET endpoint canal DMA:
// DMA stop channel command
UOTGHS->UOTGHS_DEVDMA[ul].UOTGHS_DEVDMACONTROL = 0; // STOP command
// Disable endpoint
UOTGHS->UOTGHS_DEVEPTIDR[ul] = (UOTGHS_DEVEPTIDR_TXINEC|UOTGHS_DEVEPTIDR_RXOUTEC|UOTGHS_DEVEPTIDR_RXSTPEC|UOTGHS_DEVEPTIDR_UNDERFEC|UOTGHS_DEVEPTIDR_NAKOUTEC|
UOTGHS_DEVEPTIDR_HBISOINERREC|UOTGHS_DEVEPTIDR_NAKINEC|UOTGHS_DEVEPTIDR_HBISOFLUSHEC|UOTGHS_DEVEPTIDR_OVERFEC|UOTGHS_DEVEPTIDR_STALLEDEC|
UOTGHS_DEVEPTIDR_CRCERREC|UOTGHS_DEVEPTIDR_SHORTPACKETEC|UOTGHS_DEVEPTIDR_MDATEC|UOTGHS_DEVEPTIDR_DATAXEC|UOTGHS_DEVEPTIDR_ERRORTRANSEC|
UOTGHS_DEVEPTIDR_NBUSYBKEC|UOTGHS_DEVEPTIDR_FIFOCONC|UOTGHS_DEVEPTIDR_EPDISHDMAC|UOTGHS_DEVEPTIDR_NYETDISC|UOTGHS_DEVEPTIDR_STALLRQC);
// Reset endpoint config
UOTGHS->UOTGHS_DEVEPTCFG[ul] = 0UL;
// Reset DMA channel (Buff count and Control field)
UOTGHS->UOTGHS_DEVDMA[ul].UOTGHS_DEVDMACONTROL = 0x02UL; // NON STOP command
// Reset DMA channel 0 (STOP)
UOTGHS->UOTGHS_DEVDMA[ul].UOTGHS_DEVDMACONTROL = 0UL; // STOP command
// Clear DMA channel status (read the register to clear it)
UOTGHS->UOTGHS_DEVDMA[ul].UOTGHS_DEVDMASTATUS = UOTGHS->UOTGHS_DEVDMA[ul].UOTGHS_DEVDMASTATUS;
}
UOTGHS->UOTGHS_DEVCTRL |= UOTGHS_CTRL_VBUSTE;
UOTGHS->UOTGHS_DEVIER = UOTGHS_DEVIER_WAKEUPES;
return 0UL ;
}
void USBD_Attach(void)
{
UOTGHS->UOTGHS_DEVCTRL &= ~(unsigned int)UOTGHS_DEVCTRL_DETACH;
}
void USBD_Detach(void)
{
UOTGHS->UOTGHS_DEVCTRL |= UOTGHS_DEVCTRL_DETACH;
}
#endif /* SAM3XA_SERIES */