Skip to content
Snippets Groups Projects
Commit 8a13af10 authored by Jérôme SEMETTE's avatar Jérôme SEMETTE
Browse files

Merge branch 'zero' of github.com:arduino/ArduinoZero into zero

Conflicts:
	hardware/arduino/samd/cores/arduino/validation/build_as6/test.atsuo
	hardware/arduino/samd/cores/validation/validation_core/build_as6/test.cppproj
	hardware/arduino/samd/cores/validation/validation_core/test.cpp
parents d9a6408a b6658c1b
No related branches found
No related tags found
No related merge requests found
Showing
with 3194 additions and 376 deletions
...@@ -40,3 +40,45 @@ arduino_zero.build.variant=arduino_zero ...@@ -40,3 +40,45 @@ arduino_zero.build.variant=arduino_zero
arduino_zero.build.variant_system_lib= arduino_zero.build.variant_system_lib=
arduino_zero.build.vid=0x2341 arduino_zero.build.vid=0x2341
arduino_zero.build.pid=0x004d arduino_zero.build.pid=0x004d
arduino_zero_bl_dbg.name=Arduino Zero with Bootloader (Programming Port)
arduino_zero_bl_dbg.vid.0=0x03eb
arduino_zero_bl_dbg.pid.0=0x2111
arduino_zero_bl_dbg.upload.tool=bossac
arduino_zero_bl_dbg.upload.protocol=sam-ba
arduino_zero_bl_dbg.upload.maximum_size=262144
arduino_zero_bl_dbg.upload.use_1200bps_touch=false
arduino_zero_bl_dbg.upload.wait_for_upload_port=false
arduino_zero_bl_dbg.upload.native_usb=false
arduino_zero_bl_dbg.build.mcu=cortex-m0plus
arduino_zero_bl_dbg.build.f_cpu=48000000L
arduino_zero_bl_dbg.build.usb_product="Arduino Zero"
arduino_zero_bl_dbg.build.board=SAM_ZERO
arduino_zero_bl_dbg.build.core=arduino
arduino_zero_bl_dbg.build.extra_flags=-D__SAMD21G18A__ -mthumb {build.usb_flags}
arduino_zero_bl_dbg.build.ldscript=linker_scripts/gcc/flash_with_bootloader.ld
arduino_zero_bl_dbg.build.variant=arduino_zero
arduino_zero_bl_dbg.build.variant_system_lib=
arduino_zero_bl_dbg.build.vid=0x03eb
arduino_zero_bl_dbg.build.pid=0x2111
arduino_zero_bl.name=Arduino Zero with Bootloader (Native USB Port)
arduino_zero_bl.vid.0=0x2341
arduino_zero_bl.pid.0=0x004d
arduino_zero_bl.upload.tool=bossac
arduino_zero_bl.upload.protocol=sam-ba
arduino_zero_bl.upload.maximum_size=262144
arduino_zero_bl.upload.use_1200bps_touch=false
arduino_zero_bl.upload.wait_for_upload_port=false
arduino_zero_bl.upload.native_usb=true
arduino_zero_bl.build.mcu=cortex-m0plus
arduino_zero_bl.build.f_cpu=48000000L
arduino_zero_bl.build.usb_product="Arduino Zero"
arduino_zero_bl.build.board=SAM_ZERO
arduino_zero_bl.build.core=arduino
arduino_zero_bl.build.extra_flags=-D__SAMD21G18A__ -mthumb {build.usb_flags}
arduino_zero_bl.build.ldscript=linker_scripts/gcc/flash_with_bootloader.ld
arduino_zero_bl.build.variant=arduino_zero_bl
arduino_zero_bl.build.variant_system_lib=
arduino_zero_bl.build.vid=0x2341
arduino_zero_bl.build.pid=0x004d
...@@ -50,8 +50,8 @@ extern "C"{ ...@@ -50,8 +50,8 @@ extern "C"{
void yield( void ) ; void yield( void ) ;
/* sketch */ /* sketch */
extern void setup( void ) ; void setup( void ) ;
extern void loop( void ) ; void loop( void ) ;
#define NOT_AN_INTERRUPT -1 #define NOT_AN_INTERRUPT -1
...@@ -74,15 +74,18 @@ typedef void (*voidFuncPtr)( void ) ; ...@@ -74,15 +74,18 @@ typedef void (*voidFuncPtr)( void ) ;
#ifdef __cplusplus #ifdef __cplusplus
} // extern "C" } // extern "C"
#endif // __cplusplus
#include "WCharacter.h" // The following headers are for C++ only compilation
#include "WString.h" #ifdef __cplusplus
#include "Tone.h" #include "WCharacter.h"
#include "WMath.h" #include "WString.h"
#include "HardwareSerial.h" #include "Tone.h"
#include "wiring_pulse.h" #include "WMath.h"
#include "delay.h" #include "HardwareSerial.h"
#include "wiring_pulse.h"
#include "delay.h"
#include "Uart.h"
#endif // __cplusplus #endif // __cplusplus
// Include board variant // Include board variant
......
...@@ -29,7 +29,7 @@ static void banzai() { ...@@ -29,7 +29,7 @@ static void banzai() {
__disable_irq(); __disable_irq();
// Reset the device // Reset the device
// todo NVIC_SystemReset() ;
while (true); while (true);
} }
......
#include "SERCOM.h" #include "SERCOM.h"
// Constants for Clock multiplexers
#define GENERIC_CLOCK_SERCOM0 (0x14ul)
#define GENERIC_CLOCK_SERCOM1 (0x15ul)
#define GENERIC_CLOCK_SERCOM2 (0x16ul)
#define GENERIC_CLOCK_SERCOM3 (0x17ul)
#define GENERIC_CLOCK_SERCOM4 (0x18ul)
#define GENERIC_CLOCK_SERCOM5 (0x19ul)
SERCOM::SERCOM(Sercom* sercom) SERCOM::SERCOM(Sercom* s)
{ {
this->sercom = sercom; sercom = s;
} }
/* ========================= /* =========================
...@@ -11,21 +18,23 @@ SERCOM::SERCOM(Sercom* sercom) ...@@ -11,21 +18,23 @@ SERCOM::SERCOM(Sercom* sercom)
* ========================= * =========================
*/ */
void SERCOM::initUART(SercomUartMode mode, SercomUartSampleRate sampleRate, uint32_t baudrate) void SERCOM::initUART(SercomUartMode mode, SercomUartSampleRate sampleRate, uint32_t baudrate)
{ {
resetUART(); resetUART();
initClock();
initNVIC();
//Setting the CTRLA register //Setting the CTRLA register
sercom->USART.CTRLA.reg = SERCOM_USART_CTRLA_MODE(mode) | sercom->USART.CTRLA.reg = SERCOM_USART_CTRLA_MODE(mode) |
SERCOM_USART_CTRLA_SAMPR(sampleRate); SERCOM_USART_CTRLA_SAMPR(sampleRate);
//Setting the Interrupt register //Setting the Interrupt register
sercom->USART.INTENSET.reg = SERCOM_USART_INTENSET_DRE | //Data Register Empty sercom->USART.INTENSET.reg = SERCOM_USART_INTENSET_RXC | //Received complete
SERCOM_USART_INTENSET_RXC | //Received complete
SERCOM_USART_INTENSET_ERROR; //All others errors SERCOM_USART_INTENSET_ERROR; //All others errors
if(mode == UART_INT_CLOCK) if(mode == UART_INT_CLOCK)
{ {
uint32_t sampleRateValue; uint16_t sampleRateValue;
if(sampleRate == SAMPLE_RATE_x16) if(sampleRate == SAMPLE_RATE_x16)
sampleRateValue = 16; sampleRateValue = 16;
...@@ -35,7 +44,9 @@ void SERCOM::initUART(SercomUartMode mode, SercomUartSampleRate sampleRate, uint ...@@ -35,7 +44,9 @@ void SERCOM::initUART(SercomUartMode mode, SercomUartSampleRate sampleRate, uint
sampleRateValue = 3; sampleRateValue = 3;
//Asynchronous arithmetic mode //Asynchronous arithmetic mode
sercom->USART.BAUD.reg = 65535 * ( 1 - sampleRateValue * division(baudrate,SERCOM_FREQ_REF)); //65535 * ( 1 - sampleRateValue * baudrate / SERCOM_FREQ_REF);
sercom->USART.BAUD.reg = 65535.0 * ( 1.0 - (float)(sampleRateValue) * (float)(baudrate) / (float)(SERCOM_FREQ_REF));
} }
} }
void SERCOM::initFrame(SercomUartCharSize charSize, SercomDataOrder dataOrder, SercomParityMode parityMode, SercomNumberStopBit nbStopBits) void SERCOM::initFrame(SercomUartCharSize charSize, SercomDataOrder dataOrder, SercomParityMode parityMode, SercomNumberStopBit nbStopBits)
...@@ -132,7 +143,7 @@ int SERCOM::writeDataUART(uint8_t data) ...@@ -132,7 +143,7 @@ int SERCOM::writeDataUART(uint8_t data)
flushUART(); flushUART();
//Put data into DATA register //Put data into DATA register
sercom->USART.DATA.bit.DATA = data; sercom->USART.DATA.reg = (uint16_t)data;
return 1; return 1;
} }
...@@ -155,7 +166,7 @@ void SERCOM::initSPI(SercomSpiTXPad mosi, SercomRXPad miso, SercomSpiCharSize ch ...@@ -155,7 +166,7 @@ void SERCOM::initSPI(SercomSpiTXPad mosi, SercomRXPad miso, SercomSpiCharSize ch
(0x1ul) << SERCOM_SPI_CTRLB_RXEN_Pos; //Active the SPI receiver. (0x1ul) << SERCOM_SPI_CTRLB_RXEN_Pos; //Active the SPI receiver.
} }
void SERCOM::initClock(SercomSpiClockMode clockMode, uint32_t baudrate) void SERCOM::initSPIClock(SercomSpiClockMode clockMode, uint32_t baudrate)
{ {
//Extract data from clockMode //Extract data from clockMode
int cpha, cpol; int cpha, cpol;
...@@ -285,42 +296,7 @@ bool SERCOM::isReceiveCompleteSPI() ...@@ -285,42 +296,7 @@ bool SERCOM::isReceiveCompleteSPI()
uint8_t SERCOM::calculateBaudrateSynchronous(uint32_t baudrate) uint8_t SERCOM::calculateBaudrateSynchronous(uint32_t baudrate)
{ {
return division(SERCOM_FREQ_REF, (2 * baudrate)) - 1; return SERCOM_FREQ_REF / (2 * baudrate) - 1;
}
uint32_t SERCOM::division(uint32_t dividend, uint32_t divisor)
{
// division WITHOUT division operator
uint32_t denom = divisor;
uint32_t current = 1;
uint32_t answer = 0;
if ( denom > dividend)
return 0;
if ( denom == dividend)
return 1;
while (denom <= dividend) {
denom <<= 1;
current <<= 1;
}
denom >>= 1;
current >>= 1;
while (current!=0) {
if ( dividend >= denom) {
dividend -= denom;
answer |= current;
}
current >>= 1;
denom >>= 1;
}
return answer;
} }
...@@ -515,3 +491,89 @@ uint8_t SERCOM::readDataWIRE() ...@@ -515,3 +491,89 @@ uint8_t SERCOM::readDataWIRE()
else else
return sercom->I2CS.DATA.reg; return sercom->I2CS.DATA.reg;
} }
void SERCOM::initClock()
{
uint8_t clockId = 0;
if(sercom == SERCOM0)
{
clockId = GENERIC_CLOCK_SERCOM0;
}
else if(sercom == SERCOM1)
{
clockId = GENERIC_CLOCK_SERCOM1;
}
else if(sercom == SERCOM2)
{
clockId = GENERIC_CLOCK_SERCOM2;
}
else if(sercom == SERCOM3)
{
clockId = GENERIC_CLOCK_SERCOM3;
}
else if(sercom == SERCOM4)
{
clockId = GENERIC_CLOCK_SERCOM4;
}
else if(sercom == SERCOM5)
{
clockId = GENERIC_CLOCK_SERCOM5;
}
//Setting clock
GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID( clockId ) | // Generic Clock 0 (SERCOMx)
GCLK_CLKCTRL_GEN_GCLK0 | // Generic Clock Generator 0 is source
GCLK_CLKCTRL_CLKEN ;
while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY )
{
/* Wait for synchronization */
}
}
void SERCOM::initNVIC()
{
IRQn_Type Id;
if(sercom == SERCOM0)
{
Id = SERCOM0_IRQn;
}
else if(sercom == SERCOM1)
{
Id = SERCOM1_IRQn;
}
else if(sercom == SERCOM2)
{
Id = SERCOM2_IRQn;
}
else if(sercom == SERCOM3)
{
Id = SERCOM3_IRQn;
}
else if(sercom == SERCOM4)
{
Id = SERCOM4_IRQn;
}
else if(sercom == SERCOM5)
{
Id = SERCOM5_IRQn;
}
NVIC_EnableIRQ(Id);
NVIC_SetPriority (Id, (1<<__NVIC_PRIO_BITS) - 1); /* set Priority */
}
/* =========================
* ===== SERCOM DEFINITION
* =========================
*/
SERCOM * SERCOM::sercom0 = new SERCOM(SERCOM0);
SERCOM * SERCOM::sercom1 = new SERCOM(SERCOM1);
SERCOM * SERCOM::sercom2 = new SERCOM(SERCOM2);
SERCOM * SERCOM::sercom3 = new SERCOM(SERCOM3);
SERCOM * SERCOM::sercom4 = new SERCOM(SERCOM4);
SERCOM * SERCOM::sercom5 = new SERCOM(SERCOM5);
...@@ -61,10 +61,10 @@ typedef enum ...@@ -61,10 +61,10 @@ typedef enum
typedef enum typedef enum
{ {
UART_TX_PAD_0 = 0, //Only for Intern Clock UART_TX_PAD_0 = 0x0ul, //Only for UART
UART_TX_PAD_1 = 0, //Only for Extern Clock UART_TX_PAD_2 = 0x1ul, //Only for UART
UART_TX_PAD_2 = 1, //Only for Intern Clock //UART_TX_PAD_1 = 0x0ul, //DON'T USE
UART_TX_PAD_3 = 1 //Only for Extern Clock //UART_TX_PAD_3 = 0x1ul //DON'T USE
} SercomUartTXPad; } SercomUartTXPad;
typedef enum typedef enum
...@@ -76,10 +76,10 @@ typedef enum ...@@ -76,10 +76,10 @@ typedef enum
typedef enum typedef enum
{ {
SPI_MODE_0 = 0, // CPOL : 0 | CPHA : 0 SERCOM_SPI_MODE_0 = 0, // CPOL : 0 | CPHA : 0
SPI_MODE_1, // CPOL : 0 | CPHA : 1 SERCOM_SPI_MODE_1, // CPOL : 0 | CPHA : 1
SPI_MODE_2, // CPOL : 1 | CPHA : 0 SERCOM_SPI_MODE_2, // CPOL : 1 | CPHA : 0
SPI_MODE_3 // CPOL : 1 | CPHA : 1 SERCOM_SPI_MODE_3 // CPOL : 1 | CPHA : 1
} SercomSpiClockMode; } SercomSpiClockMode;
typedef enum typedef enum
...@@ -127,7 +127,15 @@ typedef enum ...@@ -127,7 +127,15 @@ typedef enum
class SERCOM class SERCOM
{ {
public: public:
SERCOM(Sercom* sercom); SERCOM(Sercom* s);
/* ========== SERCOM OBJECT ========== */
static SERCOM * sercom0;
static SERCOM * sercom1;
static SERCOM * sercom2;
static SERCOM * sercom3;
static SERCOM * sercom4;
static SERCOM * sercom5;
/* ========== UART ========== */ /* ========== UART ========== */
void initUART(SercomUartMode mode, SercomUartSampleRate sampleRate, uint32_t baudrate=0); void initUART(SercomUartMode mode, SercomUartSampleRate sampleRate, uint32_t baudrate=0);
...@@ -148,7 +156,7 @@ class SERCOM ...@@ -148,7 +156,7 @@ class SERCOM
/* ========== SPI ========== */ /* ========== SPI ========== */
void initSPI(SercomSpiTXPad mosi, SercomRXPad miso, SercomSpiCharSize charSize, SercomDataOrder dataOrder); void initSPI(SercomSpiTXPad mosi, SercomRXPad miso, SercomSpiCharSize charSize, SercomDataOrder dataOrder);
void initClock(SercomSpiClockMode clockMode, uint32_t baudrate); void initSPIClock(SercomSpiClockMode clockMode, uint32_t baudrate);
void resetSPI(); void resetSPI();
void enableSPI(); void enableSPI();
...@@ -190,6 +198,8 @@ class SERCOM ...@@ -190,6 +198,8 @@ class SERCOM
Sercom* sercom; Sercom* sercom;
uint8_t calculateBaudrateSynchronous(uint32_t baudrate); uint8_t calculateBaudrateSynchronous(uint32_t baudrate);
uint32_t division(uint32_t dividend, uint32_t divisor); uint32_t division(uint32_t dividend, uint32_t divisor);
void initClock();
void initNVIC();
}; };
#endif #endif
...@@ -14,10 +14,22 @@ ...@@ -14,10 +14,22 @@
** SOFTWARE. ** SOFTWARE.
*/ */
#include "Arduino.h" #include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
// Include Atmel headers
#include "sam.h"
#include "wiring_constants.h"
#include "USBCore.h"
#include "USB_device.h"
#include "USBDesc.h"
#include "USBAPI.h" #include "USBAPI.h"
//#include "samd21_device.h"
#include "Reset.h" #include "Reset.h"
#ifdef CDC_ENABLED #ifdef CDC_ENABLED
#define CDC_SERIAL_BUFFER_SIZE 512 #define CDC_SERIAL_BUFFER_SIZE 512
...@@ -159,15 +171,15 @@ void Serial_::end(void) ...@@ -159,15 +171,15 @@ void Serial_::end(void)
void Serial_::accept(void) void Serial_::accept(void)
{ {
static uint32_t guard = 0; // static uint32_t guard = 0;
// synchronized access to guard // synchronized access to guard
do { //JCB do {
if (__LDREXW(&guard) != 0) { // if (__LDREXW(&guard) != 0) {
__CLREX(); // __CLREX();
return; // busy // return; // busy
} // }
} while (__STREXW(1, &guard) != 0); // retry until write succeed // } while (__STREXW(1, &guard) != 0); // retry until write succeed
ring_buffer *buffer = &cdc_rx_buffer; ring_buffer *buffer = &cdc_rx_buffer;
uint32_t i = (uint32_t)(buffer->head+1) % CDC_SERIAL_BUFFER_SIZE; uint32_t i = (uint32_t)(buffer->head+1) % CDC_SERIAL_BUFFER_SIZE;
...@@ -179,7 +191,8 @@ void Serial_::accept(void) ...@@ -179,7 +191,8 @@ void Serial_::accept(void)
while (i != buffer->tail) { while (i != buffer->tail) {
uint32_t c; uint32_t c;
if (!USBD_Available(CDC_RX)) { if (!USBD_Available(CDC_RX)) {
udd_ack_fifocon(CDC_RX); UDD_ReleaseRX(CDC_RX);
//JCB udd_ack_fifocon(CDC_RX);
break; break;
} }
c = USBD_Recv(CDC_RX); c = USBD_Recv(CDC_RX);
...@@ -191,7 +204,7 @@ void Serial_::accept(void) ...@@ -191,7 +204,7 @@ void Serial_::accept(void)
} }
// release the guard // release the guard
guard = 0; // guard = 0;
} }
int Serial_::available(void) int Serial_::available(void)
...@@ -280,8 +293,8 @@ size_t Serial_::write(uint8_t c) { ...@@ -280,8 +293,8 @@ size_t Serial_::write(uint8_t c) {
Serial_::operator bool() Serial_::operator bool()
{ {
// this is here to avoid spurious opening after upload // this is here to avoid spurious opening after upload
if (millis() < 500) // if (millis() < 500)
return false; // return false;
bool result = false; bool result = false;
...@@ -290,7 +303,7 @@ Serial_::operator bool() ...@@ -290,7 +303,7 @@ Serial_::operator bool()
result = true; result = true;
} }
delay(10); // delay(10);
return result; return result;
} }
......
...@@ -14,11 +14,19 @@ ...@@ -14,11 +14,19 @@
** SOFTWARE. ** SOFTWARE.
*/ */
#include "Arduino.h"
#ifdef HID_ENABLED #ifdef HID_ENABLED
#include "USBAPI.h"
#include "Reset.h"
#include "USBCore.h"
#include "USBDesc.h"
#include "sam.h"
#include "USB_device.h"
//#define RAWHID_ENABLED //#define RAWHID_ENABLED
#ifdef __cplusplus
extern "C"{
#endif // __cplusplus
// Singletons for mouse and keyboard // Singletons for mouse and keyboard
...@@ -196,6 +204,9 @@ bool WEAK HID_Setup(Setup& setup) ...@@ -196,6 +204,9 @@ bool WEAK HID_Setup(Setup& setup)
} }
return false; return false;
} }
#ifdef __cplusplus
}
#endif
//================================================================================ //================================================================================
//================================================================================ //================================================================================
......
...@@ -19,8 +19,20 @@ ...@@ -19,8 +19,20 @@
#ifndef __USBAPI__ #ifndef __USBAPI__
#define __USBAPI__ #define __USBAPI__
/* Define attribute */
#if defined ( __CC_ARM ) /* Keil uVision 4 */
#define WEAK (__attribute__ ((weak)))
#elif defined ( __ICCARM__ ) /* IAR Ewarm 5.41+ */
#define WEAK __weak
#elif defined ( __GNUC__ ) /* GCC CS */
#define WEAK __attribute__ ((weak))
#endif
#if defined __cplusplus #if defined __cplusplus
#include "Stream.h"
#include "RingBuffer.h" #include "RingBuffer.h"
//================================================================================ //================================================================================
...@@ -49,7 +61,7 @@ private: ...@@ -49,7 +61,7 @@ private:
RingBuffer *_cdc_rx_buffer; RingBuffer *_cdc_rx_buffer;
public: public:
void begin(uint32_t baud_count); void begin(uint32_t baud_count);
void begin(uint32_t baud_count, uint8_t config); void begin(unsigned long, uint8_t);
void end(void); void end(void);
virtual int available(void); virtual int available(void);
...@@ -189,7 +201,7 @@ bool MSC_Data(uint8_t rx,uint8_t tx); ...@@ -189,7 +201,7 @@ bool MSC_Data(uint8_t rx,uint8_t tx);
//================================================================================ //================================================================================
//================================================================================ //================================================================================
// CSC 'Driver' // CDC 'Driver'
int CDC_GetInterface(uint8_t* interfaceNum); int CDC_GetInterface(uint8_t* interfaceNum);
int CDC_GetOtherInterface(uint8_t* interfaceNum); int CDC_GetOtherInterface(uint8_t* interfaceNum);
...@@ -217,5 +229,5 @@ uint32_t USBD_Recv(uint32_t ep); // non-blocking ...@@ -217,5 +229,5 @@ uint32_t USBD_Recv(uint32_t ep); // non-blocking
void USBD_Flush(uint32_t ep); void USBD_Flush(uint32_t ep);
uint32_t USBD_Connected(void); uint32_t USBD_Connected(void);
#endif #endif // __cplusplus
#endif #endif // __USBAPI__
...@@ -13,16 +13,40 @@ ...@@ -13,16 +13,40 @@
** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS ** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
** SOFTWARE. ** SOFTWARE.
*/ */
#include <stdlib.h>
#include "Arduino.h"
#include "USBAPI.h"
#include "Reset.h"
#include <stdio.h> #include <stdio.h>
#include <stdint.h>
// Include Atmel headers
#include "sam.h"
#include "wiring_constants.h"
#include "USBCore.h"
#include "USB_device.h" // needed for USB PID define
#include "USBDesc.h"
#include "USBAPI.h"
#define TRACE_CORE(x) x
//#define TRACE_CORE(x)
// USB Device
#define USB_VID 0x2341 // arduino LLC vid
#define USB_PID_LEONARDO 0x0034
#define USB_PID_MICRO 0x0035
#define USB_PID_DUE 0x003E
#define USB_PID_ZERO 0x004D
#define EP_TYPE_CONTROL 0
#ifdef CDC_ENABLED
#define EP_TYPE_INTERRUPT_IN 1 // CDC_ENDPOINT_ACM
#define EP_TYPE_BULK_OUT 2 // CDC_ENDPOINT_OUT
#define EP_TYPE_BULK_IN 3 // CDC_ENDPOINT_IN
#endif
#ifdef HID_ENABLED
#define EP_TYPE_INTERRUPT_IN_HID 4 // HID_ENDPOINT_INT
#endif
//#define TRACE_CORE(x) x
#define TRACE_CORE(x)
static const uint32_t EndPoints[] = static const uint8_t EndPoints[] =
{ {
EP_TYPE_CONTROL, EP_TYPE_CONTROL,
...@@ -90,18 +114,18 @@ const DeviceDescriptor USB_DeviceDescriptor = ...@@ -90,18 +114,18 @@ const DeviceDescriptor USB_DeviceDescriptor =
const DeviceDescriptor USB_DeviceDescriptorA = const DeviceDescriptor USB_DeviceDescriptorA =
D_DEVICE(DEVICE_CLASS,0x00,0x00,64,USB_VID,USB_PID,0x100,IMANUFACTURER,IPRODUCT,0,1); D_DEVICE(DEVICE_CLASS,0x00,0x00,64,USB_VID,USB_PID,0x100,IMANUFACTURER,IPRODUCT,0,1);
const DeviceDescriptor USB_DeviceQualifier = //const DeviceDescriptor USB_DeviceQualifier =
D_QUALIFIER(0x00,0x00,0x00,64,1); // D_QUALIFIER(0x00,0x00,0x00,64,1);
//
//! 7.1.20 Test Mode Support ////! 7.1.20 Test Mode Support
static const unsigned char test_packet_buffer[] = { //static const unsigned char test_packet_buffer[] = {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // JKJKJKJK * 9 // 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // JKJKJKJK * 9
0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA, // JJKKJJKK * 8 // 0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA, // JJKKJJKK * 8
0xEE,0xEE,0xEE,0xEE,0xEE,0xEE,0xEE,0xEE, // JJJJKKKK * 8 // 0xEE,0xEE,0xEE,0xEE,0xEE,0xEE,0xEE,0xEE, // JJJJKKKK * 8
0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, // JJJJJJJKKKKKKK * 8 // 0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, // JJJJJJJKKKKKKK * 8
0x7F,0xBF,0xDF,0xEF,0xF7,0xFB,0xFD, // JJJJJJJK * 8 // 0x7F,0xBF,0xDF,0xEF,0xF7,0xFB,0xFD, // JJJJJJJK * 8
0xFC,0x7E,0xBF,0xDF,0xEF,0xF7,0xFB,0xFD,0x7E // {JKKKKKKK * 10}, JK // 0xFC,0x7E,0xBF,0xDF,0xEF,0xF7,0xFB,0xFD,0x7E // {JKKKKKKK * 10}, JK
}; //};
//================================================================== //==================================================================
//================================================================== //==================================================================
...@@ -115,23 +139,23 @@ uint32_t _cdcComposite = 0; ...@@ -115,23 +139,23 @@ uint32_t _cdcComposite = 0;
//================================================================== //==================================================================
#define USB_RECV_TIMEOUT #define USB_RECV_TIMEOUT
class LockEP //class LockEP
{ //{
irqflags_t flags; // irqflags_t flags;
public: //public:
LockEP(uint32_t ep) : flags(cpu_irq_save()) // LockEP(uint32_t ep) : flags(cpu_irq_save())
{ // {
} // }
~LockEP() // ~LockEP()
{ // {
cpu_irq_restore(flags); // cpu_irq_restore(flags);
} // }
}; //};
// Number of bytes, assumes a rx endpoint // Number of bytes, assumes a rx endpoint
uint32_t USBD_Available(uint32_t ep) uint32_t USBD_Available(uint32_t ep)
{ {
LockEP lock(ep); // LockEP lock(ep);
return UDD_FifoByteCount(ep & 0xF); return UDD_FifoByteCount(ep & 0xF);
} }
...@@ -142,7 +166,7 @@ uint32_t USBD_Recv(uint32_t ep, void* d, uint32_t len) ...@@ -142,7 +166,7 @@ uint32_t USBD_Recv(uint32_t ep, void* d, uint32_t len)
if (!_usbConfiguration || len < 0) if (!_usbConfiguration || len < 0)
return -1; return -1;
LockEP lock(ep); // LockEP lock(ep);
uint32_t n = UDD_FifoByteCount(ep & 0xF); uint32_t n = UDD_FifoByteCount(ep & 0xF);
len = min(n,len); len = min(n,len);
n = len; n = len;
...@@ -263,7 +287,7 @@ static bool USB_SendStringDescriptor(const uint8_t *string, int wLength) { ...@@ -263,7 +287,7 @@ static bool USB_SendStringDescriptor(const uint8_t *string, int wLength) {
// TODO // TODO
int USBD_RecvControl(void* d, uint32_t len) int USBD_RecvControl(void* d, uint32_t len)
{ {
UDD_WaitOUT(); // UDD_WaitOUT();
UDD_Recv(EP0, (uint8_t*)d, len); UDD_Recv(EP0, (uint8_t*)d, len);
UDD_ClearOUT(); UDD_ClearOUT();
...@@ -312,23 +336,23 @@ int USBD_SendInterfaces(void) ...@@ -312,23 +336,23 @@ int USBD_SendInterfaces(void)
return interfaces; return interfaces;
} }
int USBD_SendOtherInterfaces(void) //int USBD_SendOtherInterfaces(void)
{ //{
int total = 0; // int total = 0;
uint8_t interfaces = 0; // uint8_t interfaces = 0;
//
#ifdef CDC_ENABLED //#ifdef CDC_ENABLED
total = CDC_GetOtherInterface(&interfaces); // total = CDC_GetOtherInterface(&interfaces);
#endif //#endif
//
#ifdef HID_ENABLED //#ifdef HID_ENABLED
total += HID_GetInterface(&interfaces); // total += HID_GetInterface(&interfaces);
#endif //#endif
//
total = total; // Get rid of compiler warning // total = total; // Get rid of compiler warning
TRACE_CORE(printf("=> USBD_SendInterfaces, total=%d interfaces=%d\r\n", total, interfaces);) // TRACE_CORE(printf("=> USBD_SendInterfaces, total=%d interfaces=%d\r\n", total, interfaces);)
return interfaces; // return interfaces;
} //}
// Construct a dynamic configuration descriptor // Construct a dynamic configuration descriptor
// This really needs dynamic endpoint allocation etc // This really needs dynamic endpoint allocation etc
...@@ -342,9 +366,9 @@ static bool USBD_SendConfiguration(int maxlen) ...@@ -342,9 +366,9 @@ static bool USBD_SendConfiguration(int maxlen)
//TRACE_CORE(printf("=> USBD_SendConfiguration _cmark2=%d\r\n", _cmark);) //TRACE_CORE(printf("=> USBD_SendConfiguration _cmark2=%d\r\n", _cmark);)
//TRACE_CORE(printf("=> USBD_SendConfiguration sizeof=%d\r\n", sizeof(ConfigDescriptor));) //TRACE_CORE(printf("=> USBD_SendConfiguration sizeof=%d\r\n", sizeof(ConfigDescriptor));)
_Pragma("pack(1)") //JCB _Pragma("pack(1)")
ConfigDescriptor config = D_CONFIG(_cmark + sizeof(ConfigDescriptor),interfaces); ConfigDescriptor config = D_CONFIG((uint16_t)(_cmark + sizeof(ConfigDescriptor)),(uint8_t)interfaces);
_Pragma("pack()") //JCB _Pragma("pack()")
//TRACE_CORE(printf("=> USBD_SendConfiguration clen=%d\r\n", config.clen);) //TRACE_CORE(printf("=> USBD_SendConfiguration clen=%d\r\n", config.clen);)
//TRACE_CORE(printf("=> USBD_SendConfiguration maxlen=%d\r\n", maxlen);) //TRACE_CORE(printf("=> USBD_SendConfiguration maxlen=%d\r\n", maxlen);)
...@@ -356,28 +380,28 @@ _Pragma("pack()") ...@@ -356,28 +380,28 @@ _Pragma("pack()")
return true; return true;
} }
static bool USBD_SendOtherConfiguration(int maxlen) //static bool USBD_SendOtherConfiguration(int maxlen)
{ //{
// Count and measure interfaces // // Count and measure interfaces
USBD_InitControl(0); // USBD_InitControl(0);
//TRACE_CORE(printf("=> USBD_SendConfiguration _cmark1=%d\r\n", _cmark);) // //TRACE_CORE(printf("=> USBD_SendConfiguration _cmark1=%d\r\n", _cmark);)
int interfaces = USBD_SendOtherInterfaces(); // int interfaces = USBD_SendOtherInterfaces();
//TRACE_CORE(printf("=> USBD_SendConfiguration _cmark2=%d\r\n", _cmark);) // //TRACE_CORE(printf("=> USBD_SendConfiguration _cmark2=%d\r\n", _cmark);)
//TRACE_CORE(printf("=> USBD_SendConfiguration sizeof=%d\r\n", sizeof(ConfigDescriptor));) // //TRACE_CORE(printf("=> USBD_SendConfiguration sizeof=%d\r\n", sizeof(ConfigDescriptor));)
//
_Pragma("pack(1)") //_Pragma("pack(1)")
ConfigDescriptor config = D_OTHERCONFIG(_cmark + sizeof(ConfigDescriptor),interfaces); // ConfigDescriptor config = D_OTHERCONFIG(_cmark + sizeof(ConfigDescriptor),interfaces);
_Pragma("pack()") //_Pragma("pack()")
//TRACE_CORE(printf("=> USBD_SendConfiguration clen=%d\r\n", config.clen);) // //TRACE_CORE(printf("=> USBD_SendConfiguration clen=%d\r\n", config.clen);)
//
//TRACE_CORE(printf("=> USBD_SendConfiguration maxlen=%d\r\n", maxlen);) // //TRACE_CORE(printf("=> USBD_SendConfiguration maxlen=%d\r\n", maxlen);)
//
// Now send them // // Now send them
USBD_InitControl(maxlen); // USBD_InitControl(maxlen);
USBD_SendControl(0,&config,sizeof(ConfigDescriptor)); // USBD_SendControl(0,&config,sizeof(ConfigDescriptor));
USBD_SendOtherInterfaces(); // USBD_SendOtherInterfaces();
return true; // return true;
} //}
static bool USBD_SendDescriptor(Setup& setup) static bool USBD_SendDescriptor(Setup& setup)
{ {
...@@ -431,22 +455,22 @@ static bool USBD_SendDescriptor(Setup& setup) ...@@ -431,22 +455,22 @@ static bool USBD_SendDescriptor(Setup& setup)
desc_length = setup.wLength; desc_length = setup.wLength;
} }
} }
else if (USB_DEVICE_QUALIFIER == t) // else if (USB_DEVICE_QUALIFIER == t)
{ // {
// Device qualifier descriptor requested // // Device qualifier descriptor requested
desc_addr = (const uint8_t*)&USB_DeviceQualifier; // desc_addr = (const uint8_t*)&USB_DeviceQualifier;
if( *desc_addr > setup.wLength ) { // if( *desc_addr > setup.wLength ) {
desc_length = setup.wLength; // desc_length = setup.wLength;
} // }
} // }
else if (USB_OTHER_SPEED_CONFIGURATION == t) // else if (USB_OTHER_SPEED_CONFIGURATION == t)
{ // {
// Other configuration descriptor requested // // Other configuration descriptor requested
return USBD_SendOtherConfiguration(setup.wLength); // return USBD_SendOtherConfiguration(setup.wLength);
} // }
else else
{ {
//printf("Device ERROR"); TRACE_CORE(printf("Device ERROR");)
} }
if (desc_addr == 0) if (desc_addr == 0)
...@@ -466,131 +490,26 @@ static bool USBD_SendDescriptor(Setup& setup) ...@@ -466,131 +490,26 @@ static bool USBD_SendDescriptor(Setup& setup)
} }
static void USB_SendZlp( void ) //static void USB_SendZlp( void )
{ //{
while( UOTGHS_DEVEPTISR_TXINI != (UOTGHS->UOTGHS_DEVEPTISR[0] & UOTGHS_DEVEPTISR_TXINI ) ) // //while( UOTGHS_DEVEPTISR_TXINI != (UOTGHS->UOTGHS_DEVEPTISR[0] & UOTGHS_DEVEPTISR_TXINI ) )
{ // while (!(USB->DEVICE.DeviceEndpoint[EP0].EPSTATUS.reg & USB_DEVICE_EPSTATUSCLR_BK1RDY))
if((UOTGHS->UOTGHS_DEVISR & UOTGHS_DEVISR_SUSP) == UOTGHS_DEVISR_SUSP) // {
{ // //if((UOTGHS->UOTGHS_DEVISR & UOTGHS_DEVISR_SUSP) == UOTGHS_DEVISR_SUSP)
return; // if((USB->DEVICE.INTFLAG.reg & USB_DEVICE_INTFLAG_SUSPEND) == USB_DEVICE_INTFLAG_SUSPEND)
} // {
} // return;
UOTGHS->UOTGHS_DEVEPTICR[0] = UOTGHS_DEVEPTICR_TXINIC; // }
} // }
// //UOTGHS->UOTGHS_DEVEPTICR[0] = UOTGHS_DEVEPTICR_TXINIC;
// USB->DEVICE.DeviceEndpoint[EP0].EPSTATUSSET.reg = USB_DEVICE_EPSTATUSSET_BK1RDY;
static void Test_Mode_Support( uint8_t wIndex ) //}
{ //
uint8_t i;
uint8_t *ptr_dest = (uint8_t *) &udd_get_endpoint_fifo_access8(2);
switch( wIndex )
{
case 4:
//Test mode Test_Packet:
//Upon command, a port must repetitively transmit the following test packet until
//the exit action is taken. This enables the testing of rise and fall times, eye
//patterns, jitter, and any other dynamic waveform specifications.
//The test packet is made up by concatenating the following strings.
//(Note: For J/K NRZI data, and for NRZ data, the bit on the left is the first one
//transmitted. "S" indicates that a bit stuff occurs, which inserts an "extra" NRZI data bit.
//"* N" is used to indicate N occurrences of a string of bits or symbols.)
//A port in Test_Packet mode must send this packet repetitively. The inter-packet timing
//must be no less than the minimum allowable inter-packet gap as defined in Section 7.1.18 and
//no greater than 125 us.
// Send ZLP
USB_SendZlp();
UOTGHS->UOTGHS_DEVDMA[0].UOTGHS_DEVDMACONTROL = 0; // raz
UOTGHS->UOTGHS_DEVDMA[1].UOTGHS_DEVDMACONTROL = 0; // raz
// Configure endpoint 2, 64 bytes, direction IN, type BULK, 1 bank
UOTGHS->UOTGHS_DEVEPTCFG[2] = UOTGHS_DEVEPTCFG_EPSIZE_64_BYTE
| UOTGHS_DEVEPTCFG_EPDIR_IN
| UOTGHS_DEVEPTCFG_EPTYPE_BLK
| UOTGHS_DEVEPTCFG_EPBK_1_BANK;
// Check if the configuration is ok
UOTGHS->UOTGHS_DEVEPTCFG[2] |= UOTGHS_DEVEPTCFG_ALLOC;
while((UOTGHS->UOTGHS_DEVEPTISR[2]&UOTGHS_DEVEPTISR_CFGOK)==0) {}
UOTGHS->UOTGHS_DEVEPT |= UOTGHS_DEVEPT_EPEN2;
// Write FIFO
for( i=0; i<sizeof(test_packet_buffer); i++)
{
ptr_dest[i] = test_packet_buffer[i];;
}
// Tst PACKET
UOTGHS->UOTGHS_DEVCTRL |= UOTGHS_DEVCTRL_TSTPCKT;
// Send packet
UOTGHS->UOTGHS_DEVEPTICR[2] = UOTGHS_DEVEPTICR_TXINIC;
UOTGHS->UOTGHS_DEVEPTIDR[2] = UOTGHS_DEVEPTIDR_FIFOCONC;
for(;;);
// break;
case 1:
//Test mode Test_J:
//Upon command, a port's transceiver must enter the high-speed J state and remain in that
//state until the exit action is taken. This enables the testing of the high output drive
//level on the D+ line.
// Send a ZLP
USB_SendZlp();
UOTGHS->UOTGHS_DEVCTRL |= UOTGHS_DEVCTRL_TSTJ;
for(;;);
// break;
case 2:
//Test mode Test_K:
//Upon command, a port's transceiver must enter the high-speed K state and remain in
//that state until the exit action is taken. This enables the testing of the high output drive
//level on the D- line.
// Send a ZLP
USB_SendZlp();
UOTGHS->UOTGHS_DEVCTRL |= UOTGHS_DEVCTRL_TSTK;
for(;;);
// break;
case 3:
//Test mode Test_SE0_NAK:
//Upon command, a port's transceiver must enter the high-speed receive mode
//and remain in that mode until the exit action is taken. This enables the testing
//of output impedance, low level output voltage, and loading characteristics.
//In addition, while in this mode, upstream facing ports (and only upstream facing ports)
//must respond to any IN token packet with a NAK handshake (only if the packet CRC is
//determined to be correct) within the normal allowed device response time. This enables testing of
//the device squelch level circuitry and, additionally, provides a general purpose stimulus/response
//test for basic functional testing.
// Send a ZLP
USB_SendZlp();
UOTGHS->UOTGHS_DEVIDR = UOTGHS_DEVIDR_SUSPEC
| UOTGHS_DEVIDR_MSOFEC
| UOTGHS_DEVIDR_SOFEC
| UOTGHS_DEVIDR_EORSTEC
| UOTGHS_DEVIDR_WAKEUPEC
| UOTGHS_DEVIDR_EORSMEC
| UOTGHS_DEVIDR_UPRSMEC
| UOTGHS_DEVIDR_PEP_0
| UOTGHS_DEVIDR_PEP_1
| UOTGHS_DEVIDR_PEP_2
| UOTGHS_DEVIDR_PEP_3
| UOTGHS_DEVIDR_PEP_4
| UOTGHS_DEVIDR_PEP_5
| UOTGHS_DEVIDR_PEP_6
| UOTGHS_DEVIDR_DMA_1
| UOTGHS_DEVIDR_DMA_2
| UOTGHS_DEVIDR_DMA_3
| UOTGHS_DEVIDR_DMA_4
| UOTGHS_DEVIDR_DMA_5
| UOTGHS_DEVIDR_DMA_6;
for(;;);
// break;
}
}
//unsigned int iii=0; //unsigned int iii=0;
// Endpoint 0 interrupt // Endpoint 0 interrupt
static void USB_ISR(void) void USB_Handler(void)
{ {
// printf("ISR=0x%X\n\r", UOTGHS->UOTGHS_DEVISR); // jcb // printf("ISR=0x%X\n\r", UOTGHS->UOTGHS_DEVISR); // jcb
// if( iii++ > 1500 ) while(1); // jcb // if( iii++ > 1500 ) while(1); // jcb
...@@ -601,12 +520,12 @@ static void USB_ISR(void) ...@@ -601,12 +520,12 @@ static void USB_ISR(void)
// Reset USB address to 0 // Reset USB address to 0
udd_configure_address(0); udd_configure_address(0);
udd_enable_address(); //udd_enable_address();
// Configure EP 0 // Configure EP 0
UDD_InitEP(0, EP_TYPE_CONTROL); UDD_InitEP(0, EP_TYPE_CONTROL);
udd_enable_setup_received_interrupt(0); udd_enable_setup_received_interrupt(0);
udd_enable_endpoint_interrupt(0); // udd_enable_endpoint_interrupt(0);
_usbConfiguration = 0; _usbConfiguration = 0;
udd_ack_reset(); udd_ack_reset();
...@@ -645,7 +564,7 @@ static void USB_ISR(void) ...@@ -645,7 +564,7 @@ static void USB_ISR(void)
if (requestType & REQUEST_DEVICETOHOST) if (requestType & REQUEST_DEVICETOHOST)
{ {
TRACE_CORE(puts(">>> EP0 Int: IN Request\r\n");) TRACE_CORE(puts(">>> EP0 Int: IN Request\r\n");)
UDD_WaitIN(); //JCB UDD_WaitIN();
} }
else else
{ {
...@@ -719,26 +638,26 @@ static void USB_ISR(void) ...@@ -719,26 +638,26 @@ static void USB_ISR(void)
//USBD_Halt(USBGenericRequest_GetEndpointNumber(pRequest)); //USBD_Halt(USBGenericRequest_GetEndpointNumber(pRequest));
UDD_Send8(EP0, 0); UDD_Send8(EP0, 0);
} }
if( setup.wValueL == 2) // TEST_MODE // if( setup.wValueL == 2) // TEST_MODE
{ // {
// 7.1.20 Test Mode Support, 9.4.9 SetFeature // // 7.1.20 Test Mode Support, 9.4.9 SetFeature
if( (setup.bmRequestType == 0 /*USBGenericRequest_DEVICE*/) && // if( (setup.bmRequestType == 0 /*USBGenericRequest_DEVICE*/) &&
((setup.wIndex & 0x000F) == 0) ) // ((setup.wIndex & 0x000F) == 0) )
{ // {
// the lower byte of wIndex must be zero // // the lower byte of wIndex must be zero
// the most significant byte of wIndex is used to specify the specific test mode // // the most significant byte of wIndex is used to specify the specific test mode
//
UOTGHS->UOTGHS_DEVIDR &= ~UOTGHS_DEVIDR_SUSPEC; // UOTGHS->UOTGHS_DEVIDR &= ~UOTGHS_DEVIDR_SUSPEC;
UOTGHS->UOTGHS_DEVCTRL |= UOTGHS_DEVCTRL_SPDCONF_HIGH_SPEED; // remove suspend ? // UOTGHS->UOTGHS_DEVCTRL |= UOTGHS_DEVCTRL_SPDCONF_HIGH_SPEED; // remove suspend ?
//
Test_Mode_Support( (setup.wIndex & 0xFF00)>>8 ); // Test_Mode_Support( (setup.wIndex & 0xFF00)>>8 );
} // }
} // }
} }
else if (SET_ADDRESS == r) else if (SET_ADDRESS == r)
{ {
TRACE_CORE(puts(">>> EP0 Int: SET_ADDRESS\r\n");) TRACE_CORE(puts(">>> EP0 Int: SET_ADDRESS\r\n");)
UDD_WaitIN(); //JCB UDD_WaitIN();
UDD_SetAddress(setup.wValueL); UDD_SetAddress(setup.wValueL);
} }
else if (GET_DESCRIPTOR == r) else if (GET_DESCRIPTOR == r)
...@@ -768,7 +687,7 @@ static void USB_ISR(void) ...@@ -768,7 +687,7 @@ static void USB_ISR(void)
#ifdef CDC_ENABLED #ifdef CDC_ENABLED
// Enable interrupt for CDC reception from host (OUT packet) // Enable interrupt for CDC reception from host (OUT packet)
udd_enable_out_received_interrupt(CDC_RX); udd_enable_out_received_interrupt(CDC_RX);
udd_enable_endpoint_interrupt(CDC_RX); // udd_enable_endpoint_interrupt(CDC_RX);
#endif #endif
} }
else else
...@@ -792,7 +711,7 @@ static void USB_ISR(void) ...@@ -792,7 +711,7 @@ static void USB_ISR(void)
{ {
TRACE_CORE(puts(">>> EP0 Int: ClassInterfaceRequest\r\n");) TRACE_CORE(puts(">>> EP0 Int: ClassInterfaceRequest\r\n");)
UDD_WaitIN(); // Workaround: need tempo here, else CDC serial won't open correctly //JCB UDD_WaitIN(); // Workaround: need tempo here, else CDC serial won't open correctly
USBD_InitControl(setup.wLength); // Max length of transfer USBD_InitControl(setup.wLength); // Max length of transfer
ok = USBD_ClassInterfaceRequest(setup); ok = USBD_ClassInterfaceRequest(setup);
...@@ -806,7 +725,7 @@ static void USB_ISR(void) ...@@ -806,7 +725,7 @@ static void USB_ISR(void)
else else
{ {
TRACE_CORE(puts(">>> EP0 Int: Stall\r\n");) TRACE_CORE(puts(">>> EP0 Int: Stall\r\n");)
UDD_Stall(); UDD_Stall(0);
} }
} }
} }
...@@ -823,7 +742,7 @@ uint32_t USBD_Connected(void) ...@@ -823,7 +742,7 @@ uint32_t USBD_Connected(void)
{ {
uint8_t f = UDD_GetFrameNumber(); uint8_t f = UDD_GetFrameNumber();
delay(3); //delay(3); //JCB
return f != UDD_GetFrameNumber(); return f != UDD_GetFrameNumber();
} }
...@@ -836,12 +755,14 @@ USBDevice_ USBDevice; ...@@ -836,12 +755,14 @@ USBDevice_ USBDevice;
USBDevice_::USBDevice_() USBDevice_::USBDevice_()
{ {
UDD_SetStack(&USB_ISR); //UDD_SetStack(&USB_ISR);
if (UDD_Init() == 0UL) // if (UDD_Init() == 0UL)
{ // {
_usbInitialized=1UL; // _usbInitialized=1UL;
} // }
UDD_Init();
_usbInitialized=1UL;
} }
bool USBDevice_::attach(void) bool USBDevice_::attach(void)
...@@ -858,7 +779,7 @@ bool USBDevice_::attach(void) ...@@ -858,7 +779,7 @@ bool USBDevice_::attach(void)
} }
} }
bool USBDevice_::detach(void) bool USBDevice_::detach()
{ {
if (_usbInitialized != 0UL) if (_usbInitialized != 0UL)
{ {
......
...@@ -287,8 +287,8 @@ _Pragma("pack()") ...@@ -287,8 +287,8 @@ _Pragma("pack()")
#define D_CONFIG(_totalLength,_interfaces) \ #define D_CONFIG(_totalLength,_interfaces) \
{ 9, 2, _totalLength,_interfaces, 1, 0, USB_CONFIG_SELF_POWERED, USB_CONFIG_POWER_MA(500) } { 9, 2, _totalLength,_interfaces, 1, 0, USB_CONFIG_SELF_POWERED, USB_CONFIG_POWER_MA(500) }
#define D_OTHERCONFIG(_totalLength,_interfaces) \ //#define D_OTHERCONFIG(_totalLength,_interfaces)
{ 9, 7, _totalLength,_interfaces, 1, 0, USB_CONFIG_SELF_POWERED, USB_CONFIG_POWER_MA(500) } // { 9, 7, _totalLength,_interfaces, 1, 0, USB_CONFIG_SELF_POWERED, USB_CONFIG_POWER_MA(500) }
#define D_INTERFACE(_n,_numEndpoints,_class,_subClass,_protocol) \ #define D_INTERFACE(_n,_numEndpoints,_class,_subClass,_protocol) \
{ 9, 4, _n, 0, _numEndpoints, _class,_subClass, _protocol, 0 } { 9, 4, _n, 0, _numEndpoints, _class,_subClass, _protocol, 0 }
...@@ -296,8 +296,8 @@ _Pragma("pack()") ...@@ -296,8 +296,8 @@ _Pragma("pack()")
#define D_ENDPOINT(_addr,_attr,_packetSize, _interval) \ #define D_ENDPOINT(_addr,_attr,_packetSize, _interval) \
{ 7, 5, _addr,_attr,_packetSize, _interval } { 7, 5, _addr,_attr,_packetSize, _interval }
#define D_QUALIFIER(_class,_subClass,_proto,_packetSize0,_configs) \ //#define D_QUALIFIER(_class,_subClass,_proto,_packetSize0,_configs)
{ 10, 6, 0x200, _class,_subClass,_proto,_packetSize0,_configs } // { 10, 6, 0x200, _class,_subClass,_proto,_packetSize0,_configs }
#define D_IAD(_firstInterface, _count, _class, _subClass, _protocol) \ #define D_IAD(_firstInterface, _count, _class, _subClass, _protocol) \
{ 8, 11, _firstInterface, _count, _class, _subClass, _protocol, 0 } { 8, 11, _firstInterface, _count, _class, _subClass, _protocol, 0 }
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
#define __USBDESC_H__ #define __USBDESC_H__
#define CDC_ENABLED #define CDC_ENABLED
#define HID_ENABLED //#define HID_ENABLED
#ifdef CDC_ENABLED #ifdef CDC_ENABLED
#define CDC_INTERFACE_COUNT 2 #define CDC_INTERFACE_COUNT 2
......
/* ----------------------------------------------------------------------------
* SAM Software Package License
* ----------------------------------------------------------------------------
* Copyright (c) 2011-2012, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following condition is met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
#ifndef USB_DEVICE_H_INCLUDED
#define USB_DEVICE_H_INCLUDED
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include "samd21_device.h"
extern void UDD_WaitIN(void);
//extern void UDD_WaitOUT(void);
extern void UDD_ClearIN(void);
extern void UDD_ClearOUT(void);
extern uint32_t UDD_WaitForINOrOUT(void);
extern void UDD_ClearRxFlag(unsigned char bEndpoint);
extern uint32_t UDD_ReceivedSetupInt(void);
extern void UDD_ClearSetupInt(void);
//extern uint32_t UDD_ReadWriteAllowed(uint32_t ep);
extern uint32_t UDD_FifoByteCount(uint32_t ep);
extern uint8_t UDD_FifoFree(void);
extern void UDD_ReleaseRX(uint32_t ep);
extern void UDD_ReleaseTX(uint32_t ep);
extern uint8_t UDD_FrameNumber(void);
extern uint8_t UDD_GetConfiguration(void);
extern uint32_t UDD_Send(uint32_t ep, const void* data, uint32_t len);
extern void UDD_Send8(uint32_t ep, uint8_t data );
extern uint8_t UDD_Recv8(uint32_t ep);
extern void UDD_Recv(uint32_t ep, uint8_t* data, uint32_t len);
extern void UDD_InitEndpoints(const uint8_t* eps_table, const uint8_t ul_eps_table_size);
extern void UDD_InitControl(int end);
extern uint32_t UDD_Init(void);
extern void UDD_InitEP( uint32_t ul_ep, uint32_t ul_ep_cfg );
extern void UDD_Attach(void);
extern void UDD_Detach(void);
//extern void UDD_SetStack(void (*pf_isr)(void));
extern void UDD_SetAddress(uint32_t addr);
extern void UDD_Stall(uint32_t ep);
extern uint32_t UDD_GetFrameNumber(void);
/*! \name Usual Types
*/
//! @{
typedef unsigned char Bool; //!< Boolean.
#ifndef __cplusplus
#if !defined(__bool_true_false_are_defined)
typedef unsigned char bool; //!< Boolean.
#endif
#endif
typedef int8_t S8; //!< 8-bit signed integer.
typedef uint8_t U8; //!< 8-bit unsigned integer.
typedef int16_t S16; //!< 16-bit signed integer.
typedef uint16_t U16; //!< 16-bit unsigned integer.
typedef uint16_t le16_t;
typedef uint16_t be16_t;
typedef int32_t S32; //!< 32-bit signed integer.
typedef uint32_t U32; //!< 32-bit unsigned integer.
typedef uint32_t le32_t;
typedef uint32_t be32_t;
typedef int64_t S64; //!< 64-bit signed integer.
typedef uint64_t U64; //!< 64-bit unsigned integer.
typedef float F32; //!< 32-bit floating-point number.
typedef double F64; //!< 64-bit floating-point number.
typedef uint32_t iram_size_t;
//! @}
/*! \name Bit-Field Handling
*/
//! @{
/*! \brief Reads the bits of a value specified by a given bit-mask.
*
* \param value Value to read bits from.
* \param mask Bit-mask indicating bits to read.
*
* \return Read bits.
*/
#define Rd_bits( value, mask) ((value) & (mask))
/*! \brief Writes the bits of a C lvalue specified by a given bit-mask.
*
* \param lvalue C lvalue to write bits to.
* \param mask Bit-mask indicating bits to write.
* \param bits Bits to write.
*
* \return Resulting value with written bits.
*/
#define Wr_bits(lvalue, mask, bits) ((lvalue) = ((lvalue) & ~(mask)) |\
((bits ) & (mask)))
/*! \brief Tests the bits of a value specified by a given bit-mask.
*
* \param value Value of which to test bits.
* \param mask Bit-mask indicating bits to test.
*
* \return \c 1 if at least one of the tested bits is set, else \c 0.
*/
#define Tst_bits( value, mask) (Rd_bits(value, mask) != 0)
/*! \brief Clears the bits of a C lvalue specified by a given bit-mask.
*
* \param lvalue C lvalue of which to clear bits.
* \param mask Bit-mask indicating bits to clear.
*
* \return Resulting value with cleared bits.
*/
#define Clr_bits(lvalue, mask) ((lvalue) &= ~(mask))
/*! \brief Sets the bits of a C lvalue specified by a given bit-mask.
*
* \param lvalue C lvalue of which to set bits.
* \param mask Bit-mask indicating bits to set.
*
* \return Resulting value with set bits.
*/
#define Set_bits(lvalue, mask) ((lvalue) |= (mask))
/*! \brief Toggles the bits of a C lvalue specified by a given bit-mask.
*
* \param lvalue C lvalue of which to toggle bits.
* \param mask Bit-mask indicating bits to toggle.
*
* \return Resulting value with toggled bits.
*/
#define Tgl_bits(lvalue, mask) ((lvalue) ^= (mask))
/*! \brief Reads the bit-field of a value specified by a given bit-mask.
*
* \param value Value to read a bit-field from.
* \param mask Bit-mask indicating the bit-field to read.
*
* \return Read bit-field.
*/
#define Rd_bitfield( value, mask) (Rd_bits( value, mask) >> ctz(mask))
/*! \brief Writes the bit-field of a C lvalue specified by a given bit-mask.
*
* \param lvalue C lvalue to write a bit-field to.
* \param mask Bit-mask indicating the bit-field to write.
* \param bitfield Bit-field to write.
*
* \return Resulting value with written bit-field.
*/
#define Wr_bitfield(lvalue, mask, bitfield) (Wr_bits(lvalue, mask, (U32)(bitfield) << ctz(mask)))
//! @}
/*! \name Token Paste
*
* Paste N preprocessing tokens together, these tokens being allowed to be \#defined.
*
* May be used only within macros with the tokens passed as arguments if the tokens are \#defined.
*
* For example, writing TPASTE2(U, WIDTH) within a macro \#defined by
* UTYPE(WIDTH) and invoked as UTYPE(UL_WIDTH) with UL_WIDTH \#defined as 32 is
* equivalent to writing U32.
*/
//! @{
#define TPASTE2( a, b) a##b
#define TPASTE3( a, b, c) a##b##c
#define TPASTE4( a, b, c, d) a##b##c##d
#define TPASTE5( a, b, c, d, e) a##b##c##d##e
#define TPASTE6( a, b, c, d, e, f) a##b##c##d##e##f
#define TPASTE7( a, b, c, d, e, f, g) a##b##c##d##e##f##g
#define TPASTE8( a, b, c, d, e, f, g, h) a##b##c##d##e##f##g##h
#define TPASTE9( a, b, c, d, e, f, g, h, i) a##b##c##d##e##f##g##h##i
#define TPASTE10(a, b, c, d, e, f, g, h, i, j) a##b##c##d##e##f##g##h##i##j
//! @}
/*! \name Absolute Token Paste
*
* Paste N preprocessing tokens together, these tokens being allowed to be \#defined.
*
* No restriction of use if the tokens are \#defined.
*
* For example, writing ATPASTE2(U, UL_WIDTH) anywhere with UL_WIDTH \#defined
* as 32 is equivalent to writing U32.
*/
//! @{
#define ATPASTE2( a, b) TPASTE2( a, b)
#define ATPASTE3( a, b, c) TPASTE3( a, b, c)
#define ATPASTE4( a, b, c, d) TPASTE4( a, b, c, d)
#define ATPASTE5( a, b, c, d, e) TPASTE5( a, b, c, d, e)
#define ATPASTE6( a, b, c, d, e, f) TPASTE6( a, b, c, d, e, f)
#define ATPASTE7( a, b, c, d, e, f, g) TPASTE7( a, b, c, d, e, f, g)
#define ATPASTE8( a, b, c, d, e, f, g, h) TPASTE8( a, b, c, d, e, f, g, h)
#define ATPASTE9( a, b, c, d, e, f, g, h, i) TPASTE9( a, b, c, d, e, f, g, h, i)
#define ATPASTE10(a, b, c, d, e, f, g, h, i, j) TPASTE10(a, b, c, d, e, f, g, h, i, j)
//! @}
/*! \brief Counts the trailing zero bits of the given value considered as a 32-bit integer.
*
* \param u Value of which to count the trailing zero bits.
*
* \return The count of trailing zero bits in \a u.
*/
#if (defined __GNUC__) || (defined __CC_ARM)
# define ctz(u) __builtin_ctz(u)
#else
# define ctz(u) ((u) & (1ul << 0) ? 0 : \
(u) & (1ul << 1) ? 1 : \
(u) & (1ul << 2) ? 2 : \
(u) & (1ul << 3) ? 3 : \
(u) & (1ul << 4) ? 4 : \
(u) & (1ul << 5) ? 5 : \
(u) & (1ul << 6) ? 6 : \
(u) & (1ul << 7) ? 7 : \
(u) & (1ul << 8) ? 8 : \
(u) & (1ul << 9) ? 9 : \
(u) & (1ul << 10) ? 10 : \
(u) & (1ul << 11) ? 11 : \
(u) & (1ul << 12) ? 12 : \
(u) & (1ul << 13) ? 13 : \
(u) & (1ul << 14) ? 14 : \
(u) & (1ul << 15) ? 15 : \
(u) & (1ul << 16) ? 16 : \
(u) & (1ul << 17) ? 17 : \
(u) & (1ul << 18) ? 18 : \
(u) & (1ul << 19) ? 19 : \
(u) & (1ul << 20) ? 20 : \
(u) & (1ul << 21) ? 21 : \
(u) & (1ul << 22) ? 22 : \
(u) & (1ul << 23) ? 23 : \
(u) & (1ul << 24) ? 24 : \
(u) & (1ul << 25) ? 25 : \
(u) & (1ul << 26) ? 26 : \
(u) & (1ul << 27) ? 27 : \
(u) & (1ul << 28) ? 28 : \
(u) & (1ul << 29) ? 29 : \
(u) & (1ul << 30) ? 30 : \
(u) & (1ul << 31) ? 31 : \
32)
#endif
/*! \name Zero-Bit Counting
*
* Under GCC, __builtin_clz and __builtin_ctz behave like macros when
* applied to constant expressions (values known at compile time), so they are
* more optimized than the use of the corresponding assembly instructions and
* they can be used as constant expressions e.g. to initialize objects having
* static storage duration, and like the corresponding assembly instructions
* when applied to non-constant expressions (values unknown at compile time), so
* they are more optimized than an assembly periphrasis. Hence, clz and ctz
* ensure a possible and optimized behavior for both constant and non-constant
* expressions.
*/
//! @{
/*! \brief Counts the leading zero bits of the given value considered as a 32-bit integer.
*
* \param u Value of which to count the leading zero bits.
*
* \return The count of leading zero bits in \a u.
*/
#if (defined __GNUC__) || (defined __CC_ARM)
# define clz(u) __builtin_clz(u)
#elif (defined __ICCARM__)
# define clz(u) __CLZ(u)
#else
# define clz(u) (((u) == 0) ? 32 : \
((u) & (1ul << 31)) ? 0 : \
((u) & (1ul << 30)) ? 1 : \
((u) & (1ul << 29)) ? 2 : \
((u) & (1ul << 28)) ? 3 : \
((u) & (1ul << 27)) ? 4 : \
((u) & (1ul << 26)) ? 5 : \
((u) & (1ul << 25)) ? 6 : \
((u) & (1ul << 24)) ? 7 : \
((u) & (1ul << 23)) ? 8 : \
((u) & (1ul << 22)) ? 9 : \
((u) & (1ul << 21)) ? 10 : \
((u) & (1ul << 20)) ? 11 : \
((u) & (1ul << 19)) ? 12 : \
((u) & (1ul << 18)) ? 13 : \
((u) & (1ul << 17)) ? 14 : \
((u) & (1ul << 16)) ? 15 : \
((u) & (1ul << 15)) ? 16 : \
((u) & (1ul << 14)) ? 17 : \
((u) & (1ul << 13)) ? 18 : \
((u) & (1ul << 12)) ? 19 : \
((u) & (1ul << 11)) ? 20 : \
((u) & (1ul << 10)) ? 21 : \
((u) & (1ul << 9)) ? 22 : \
((u) & (1ul << 8)) ? 23 : \
((u) & (1ul << 7)) ? 24 : \
((u) & (1ul << 6)) ? 25 : \
((u) & (1ul << 5)) ? 26 : \
((u) & (1ul << 4)) ? 27 : \
((u) & (1ul << 3)) ? 28 : \
((u) & (1ul << 2)) ? 29 : \
((u) & (1ul << 1)) ? 30 : \
31)
#endif
/*! \name Mathematics
*
* The same considerations as for clz and ctz apply here but GCC does not
* provide built-in functions to access the assembly instructions abs, min and
* max and it does not produce them by itself in most cases, so two sets of
* macros are defined here:
* - Abs, Min and Max to apply to constant expressions (values known at
* compile time);
* - abs, min and max to apply to non-constant expressions (values unknown at
* compile time), abs is found in stdlib.h.
*/
//! @{
///*! \brief Takes the absolute value of \a a.
// *
// * \param a Input value.
// *
// * \return Absolute value of \a a.
// *
// * \note More optimized if only used with values known at compile time.
// */
//#define Abs(a) (((a) < 0 ) ? -(a) : (a))
//
///*! \brief Takes the minimal value of \a a and \a b.
// *
// * \param a Input value.
// * \param b Input value.
// *
// * \return Minimal value of \a a and \a b.
// *
// * \note More optimized if only used with values known at compile time.
// */
//#define Min(a, b) (((a) < (b)) ? (a) : (b))
//
///*! \brief Takes the maximal value of \a a and \a b.
// *
// * \param a Input value.
// * \param b Input value.
// *
// * \return Maximal value of \a a and \a b.
// *
// * \note More optimized if only used with values known at compile time.
// */
//#define Max(a, b) (((a) > (b)) ? (a) : (b))
//
//// abs() is already defined by stdlib.h
//
///*! \brief Takes the minimal value of \a a and \a b.
// *
// * \param a Input value.
// * \param b Input value.
// *
// * \return Minimal value of \a a and \a b.
// *
// * \note More optimized if only used with values unknown at compile time.
// */
//#define min(a, b) Min(a, b)
//
///*! \brief Takes the maximal value of \a a and \a b.
// *
// * \param a Input value.
// * \param b Input value.
// *
// * \return Maximal value of \a a and \a b.
// *
// * \note More optimized if only used with values unknown at compile time.
// */
//#define max(a, b) Max(a, b)
//
////! @}
#ifdef __cplusplus
}
#endif
#endif /* USB_DEVICE_H_INCLUDED */
/* ----------------------------------------------------------------------------
* SAM Software Package License
* ----------------------------------------------------------------------------
* Copyright (c) 2011-2012, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following condition is met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
#ifndef USB_HOST_H_INCLUDED
#define USB_HOST_H_INCLUDED
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#define tokSETUP UOTGHS_HSTPIPCFG_PTOKEN_SETUP
#define tokIN UOTGHS_HSTPIPCFG_PTOKEN_IN
#define tokOUT UOTGHS_HSTPIPCFG_PTOKEN_OUT
#define tokINHS UOTGHS_HSTPIPCFG_PTOKEN_IN
#define tokOUTHS UOTGHS_HSTPIPCFG_PTOKEN_OUT
//! \brief Device speed
/*typedef enum {
UHD_SPEED_LOW = 0,
UHD_SPEED_FULL = 1,
UHD_SPEED_HIGH = 2,
} uhd_speed_t;*/
//! States of USBB interface
typedef enum {
UHD_STATE_NO_VBUS = 0,
UHD_STATE_DISCONNECTED = 1,
UHD_STATE_CONNECTED = 2,
UHD_STATE_ERROR = 3,
} uhd_vbus_state_t;
//extern uhd_speed_t uhd_get_speed(void);
extern void UHD_SetStack(void (*pf_isr)(void));
extern void UHD_Init(void);
extern void UHD_BusReset(void);
extern uhd_vbus_state_t UHD_GetVBUSState(void);
extern uint32_t UHD_Pipe0_Alloc(uint32_t ul_add, uint32_t ul_ep_size);
extern 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);
extern void UHD_Pipe_Free(uint32_t ul_pipe);
extern uint32_t UHD_Pipe_Read(uint32_t ul_pipe, uint32_t ul_size, uint8_t* data);
extern void UHD_Pipe_Write(uint32_t ul_pipe, uint32_t ul_size, uint8_t* data);
extern void UHD_Pipe_Send(uint32_t ul_pipe, uint32_t ul_token_type);
extern uint32_t UHD_Pipe_Is_Transfer_Complete(uint32_t ul_pipe, uint32_t ul_token_type);
#ifdef __cplusplus
}
#endif
#endif /* USB_HOST_H_INCLUDED */
This diff is collapsed.
This diff is collapsed.
/* ----------------------------------------------------------------------------
* SAM Software Package License
* ----------------------------------------------------------------------------
* Copyright (c) 2011-2012, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following condition is met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
#include <stdio.h>
#if SAM3XA_SERIES
//#define TRACE_UOTGHS_HOST(x) x
#define TRACE_UOTGHS_HOST(x)
extern void (*gpf_isr)(void);
// Handle UOTGHS Host driver state
static uhd_vbus_state_t uhd_state = UHD_STATE_NO_VBUS;
/**
* \brief Interrupt sub routine for USB Host state machine management.
*/
static void UHD_ISR(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;
}
// 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;
}
// Check USB clock ready after asynchronous interrupt
while (!Is_otg_clock_usable())
;
otg_unfreeze_clock();
// 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;
}
// Other errors
if (Is_uhd_errors_interrupt())
{
TRACE_UOTGHS_HOST(printf(">>> UHD_ISR : Other error INT\r\n");)
uhd_ack_errors_interrupt();
return;
}
}
/**
* \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;
// 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();
otg_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);
}
/**
* \brief Trigger a USB bus reset.
*/
void UHD_BusReset(void)
{
uhd_start_reset();
}
/**
* \brief Get VBUS state.
*
* \return VBUS status.
*/
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.
*
* \param ul_add Address of remote device for pipe 0.
* \param ul_ep_size Actual size of the FIFO in bytes.
*
* \retval 0 success.
* \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;
}
/**
* \brief Allocate a new pipe.
*
* \note UOTGHS maximum pipe number is limited to 10, meaning that only a limited
* amount of devices can be connected. Unfortunately, using only one pipe shared accross
* various endpoints and devices is not possible because the UOTGHS IP does not allow to
* change the data toggle value through register interface.
*
* \param ul_dev_addr Address of remote device.
* \param ul_dev_ep Targeted endpoint of remote device.
* \param ul_type Pipe type.
* \param ul_dir Pipe direction.
* \param ul_maxsize Pipe size.
* \param ul_interval Polling interval (if applicable to pipe type).
* \param ul_nb_bank Number of banks associated with this pipe.
*
* \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 is configured and allocated successfully
return ul_pipe;
}
return 0;
}
/**
* \brief Free a pipe.
*
* \param ul_pipe Pipe number to free.
*/
void UHD_Pipe_Free(uint32_t ul_pipe)
{
// Unalloc pipe
uhd_disable_pipe(ul_pipe);
uhd_unallocate_memory(ul_pipe);
uhd_reset_pipe(ul_pipe);
}
/**
* \brief Read from a pipe.
*
* \param ul_pipe Pipe number.
* \param ul_size Maximum number of data to read.
* \param data Buffer to store the data.
*
* \return number of data read.
*/
uint32_t UHD_Pipe_Read(uint32_t ul_pipe, uint32_t ul_size, uint8_t* data)
{
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;
}
/**
* \brief Write into a pipe.
*
* \param ul_pipe Pipe number.
* \param ul_size Maximum number of data to read.
* \param data Buffer containing data to write.
*/
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++;
}
/**
* \brief Send a pipe content.
*
* \param ul_pipe Pipe number.
* \param ul_token_type Token type.
*/
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);
}
/**
* \brief Check for pipe transfer completion.
*
* \param ul_pipe Pipe number.
* \param ul_token_type Token type.
*
* \retval 0 transfer is not complete.
* \retval 1 transfer is complete.
*/
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;
}
}
return 0;
}
#endif /* SAM3XA_SERIES */
This diff is collapsed.
#include "SERCOMUart.h" #include "Uart.h"
#include "WVariant.h"
#include "wiring_digital.h"
Uart::Uart(SERCOM *s, uint8_t pinRX, uint8_t pinTX)
SERCOMUart::SERCOMUart(SERCOM *sercom)
{ {
this->sercom = sercom; sercom = s;
if(sercom == SERCOM::sercom0)
{
pinPeripheral(pinRX, g_APinDescription[pinRX].ulPinType);
pinPeripheral(pinTX, g_APinDescription[pinTX].ulPinType);
}
else if(sercom == SERCOM::sercom5)
{
pinPeripheral(pinRX, g_APinDescription[pinRX].ulPinType);
pinPeripheral(pinTX, g_APinDescription[pinTX].ulPinType);
}
} }
void SERCOMUart::begin(uint16_t baudrate) void Uart::begin(unsigned long baudrate)
{ {
begin(baudrate, SERIAL_8N1); begin(baudrate, (uint8_t)SERIAL_8N1);
} }
void SERCOMUart::begin(uint16_t baudrate, uint8_t config) void Uart::begin(unsigned long baudrate, uint8_t config)
{ {
sercom->initUART(UART_INT_CLOCK, SAMPLE_RATE_x16, baudrate); sercom->initUART(UART_INT_CLOCK, SAMPLE_RATE_x16, baudrate);
sercom->initFrame(extractCharSize(config), LSB_FIRST, extractParity(config), extractNbStopBit(config)); sercom->initFrame(extractCharSize(config), LSB_FIRST, extractParity(config), extractNbStopBit(config));
sercom->initPads(UART_TX_PAD_0, SERCOM_RX_PAD_2); sercom->initPads(UART_TX_PAD_2, SERCOM_RX_PAD_3);
sercom->enableUART(); sercom->enableUART();
} }
void SERCOMUart::end() void Uart::end()
{ {
sercom->resetUART(); sercom->resetUART();
rxBuffer.clear(); rxBuffer.clear();
} }
void SERCOMUart::flush() void Uart::flush()
{ {
sercom->flushUART(); sercom->flushUART();
} }
void SERCOMUart::IrqHandler() void Uart::IrqHandler()
{ {
if(sercom->availableDataUART()) if(sercom->availableDataUART())
{ {
rxBuffer.store_char(sercom->readDataUART()); rxBuffer.store_char(sercom->readDataUART());
} }
if(sercom->isDataRegisterEmptyUART())
{
sercom->writeDataUART(txBuffer.read_char());
}
if( sercom->isBufferOverflowErrorUART() || if( sercom->isBufferOverflowErrorUART() ||
sercom->isFrameErrorUART() || sercom->isFrameErrorUART() ||
sercom->isParityErrorUART()) sercom->isParityErrorUART())
...@@ -51,31 +58,41 @@ void SERCOMUart::IrqHandler() ...@@ -51,31 +58,41 @@ void SERCOMUart::IrqHandler()
} }
} }
int SERCOMUart::available() int Uart::available()
{ {
return rxBuffer.available(); return rxBuffer.available();
} }
int SERCOMUart::peek() int Uart::peek()
{ {
return rxBuffer.peek(); return rxBuffer.peek();
} }
int SERCOMUart::read() int Uart::read()
{ {
return rxBuffer.read_char(); return rxBuffer.read_char();
} }
size_t SERCOMUart::write(uint8_t data) size_t Uart::write(const uint8_t data)
{ {
if(txBuffer.isFull()) sercom->writeDataUART(data);
return 0;
txBuffer.store_char(data);
return 1; return 1;
} }
SercomNumberStopBit SERCOMUart::extractNbStopBit(uint8_t config) size_t Uart::write(const char * data)
{
size_t writed = 0;
while(*data != '\0')
{
writed += write(*data);
++data;
}
return writed;
}
SercomNumberStopBit Uart::extractNbStopBit(uint8_t config)
{ {
switch(config & HARDSER_STOP_BIT_MASK) switch(config & HARDSER_STOP_BIT_MASK)
{ {
...@@ -88,7 +105,7 @@ SercomNumberStopBit SERCOMUart::extractNbStopBit(uint8_t config) ...@@ -88,7 +105,7 @@ SercomNumberStopBit SERCOMUart::extractNbStopBit(uint8_t config)
} }
} }
SercomUartCharSize SERCOMUart::extractCharSize(uint8_t config) SercomUartCharSize Uart::extractCharSize(uint8_t config)
{ {
switch(config & HARDSER_DATA_MASK) switch(config & HARDSER_DATA_MASK)
{ {
...@@ -108,7 +125,7 @@ SercomUartCharSize SERCOMUart::extractCharSize(uint8_t config) ...@@ -108,7 +125,7 @@ SercomUartCharSize SERCOMUart::extractCharSize(uint8_t config)
} }
} }
SercomParityMode SERCOMUart::extractParity(uint8_t config) SercomParityMode Uart::extractParity(uint8_t config)
{ {
switch(config & HARDSER_PARITY_MASK) switch(config & HARDSER_PARITY_MASK)
{ {
...@@ -124,3 +141,14 @@ SercomParityMode SERCOMUart::extractParity(uint8_t config) ...@@ -124,3 +141,14 @@ SercomParityMode SERCOMUart::extractParity(uint8_t config)
} }
} }
Uart Serial = Uart(SERCOM::sercom0, 0, 1);
Uart Serial5 = Uart(SERCOM::sercom5, 36, 35);
void SERCOM0_Handler()
{
Serial.IrqHandler();
}
void SERCOM5_Handler()
{
Serial5.IrqHandler();
}
...@@ -8,18 +8,19 @@ ...@@ -8,18 +8,19 @@
#include <cstddef> #include <cstddef>
class SERCOMUart : public HardwareSerial class Uart : public HardwareSerial
{ {
public: public:
SERCOMUart(SERCOM *sercom); Uart(SERCOM *s, uint8_t pinRX, uint8_t pinTX);
void begin(uint16_t baudRate); void begin(unsigned long baudRate);
void begin(uint16_t baudrate, uint8_t config); void begin(unsigned long baudrate, uint8_t config);
void end(); void end();
int available(); int available();
int peek(); int peek();
int read(); int read();
void flush(); void flush();
size_t write(const uint8_t c); size_t write(const uint8_t data);
size_t write(const char * data);
void IrqHandler(); void IrqHandler();
...@@ -28,12 +29,14 @@ class SERCOMUart : public HardwareSerial ...@@ -28,12 +29,14 @@ class SERCOMUart : public HardwareSerial
private: private:
SERCOM *sercom; SERCOM *sercom;
RingBuffer rxBuffer; RingBuffer rxBuffer;
RingBuffer txBuffer;
SercomNumberStopBit extractNbStopBit(uint8_t config); SercomNumberStopBit extractNbStopBit(uint8_t config);
SercomUartCharSize extractCharSize(uint8_t config); SercomUartCharSize extractCharSize(uint8_t config);
SercomParityMode extractParity(uint8_t config); SercomParityMode extractParity(uint8_t config);
}; };
extern Uart Serial;
extern Uart Serial5;
#endif #endif
...@@ -25,21 +25,21 @@ ...@@ -25,21 +25,21 @@
*/ */
int main( void ) int main( void )
{ {
init(); init();
delay(1); delay(1);
//#if defined(USBCON) #if defined(USBCON)
// USBDevice.attach(); // USBDevice.attach();
//#endif #endif
setup(); setup();
for (;;) for (;;)
{ {
loop(); loop();
if (serialEventRun) serialEventRun(); if (serialEventRun) serialEventRun();
} }
return 0; return 0;
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment