diff --git a/.gitignore b/.gitignore index e5f5ed02..27e86337 100644 --- a/.gitignore +++ b/.gitignore @@ -17,6 +17,8 @@ _build/ *.pyc *.expect *.so +**/bin/** +**/tests/result/* **/logs*/** test_results.csv .DS_Store @@ -30,9 +32,14 @@ Installs/ tests/bin.txt tests/log tests/test_**/**test_xs2.xn -tests/test_**/**test_xs3_500.xn -tests/test_**/**test_xs3_540.xn -tests/test_**/**test_xs3_600.xn -tests/test_**/**test_xs3_800.xn +tests/test_**/**test_xs3_*.xn **/venv/** *.gtkw +**/tests/build/** +**/tests/doc/** +**/build/html/** +**/tests/assets/** +**/build/docstrees/** +tests/report.html +tests/testplan.rst +build/doctrees/environment.pickle diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 12d65f97..8e40e0b2 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,14 @@ lib_xud Change Log ================== +2.1.0 +----- + + * CHANGE: Various optimisations to aid corner-case timings on XS3 based + devices + * CHANGE: Some API functions re-authored in C (from Assembly) + * CHANGE: Testbench now more accurately models XS3 based devices + 2.0.2 ----- diff --git a/README.rst b/README.rst index b815cd4a..bc9c04f3 100644 --- a/README.rst +++ b/README.rst @@ -13,6 +13,8 @@ The library provides functionality to act as a USB *device* only. This library is for use with xCORE-200 Series or xCORE-AI series devices only, previous generations of xCORE devices are no longer supported. +Note, at points lib_xud will run in "fast mode" this is a requirement to meet timing. + Features ........ diff --git a/lib_xud/api/xud.h b/lib_xud/api/xud.h index aac91c30..1e50e0ad 100644 --- a/lib_xud/api/xud.h +++ b/lib_xud/api/xud.h @@ -271,7 +271,7 @@ XUD_Result_t XUD_SetDevAddr(/*tileref usbtile*/ unsigned addr); * \param one IN or OUT endpoint identifier to perform the reset on. * \param two Optional second IN or OUT endpoint structure to perform a reset on. * \return Either ``XUD_SPEED_HS`` - the host has accepted that this device can execute - * at high speed, ``XUD_SPEED_FS`` - the device is runnig at full speed, + * at high speed, ``XUD_SPEED_FS`` - the device is running at full speed, * or ``XUD_SPEED_KILL`` to indicate that the USB stack has been shut down * by another part of the user code (using XUD_Kill). If the last value is * returned, the endpoint code should call XUD_CloseEndpoint and then @@ -552,6 +552,27 @@ void XUD_SetData_Select(chanend c, XUD_ep ep, REFERENCE_PARAM(XUD_Result_t, resu #define XUD_OSC_MHZ (24) #endif -#endif //__ASSEMBLER__ + +/* TODO pack this to save mem + * TODO size of this hardcoded in ResetRpStateByAddr_ + */ +typedef struct XUD_ep_info +{ + unsigned int array_ptr; // 0 + unsigned int xud_chanend; // 1 + unsigned int client_chanend; // 2 + unsigned int buffer; // 3 Pointer to buffer + unsigned int pid; // 4 Expected out PID + unsigned int epType; // 5 Data + unsigned int actualPid; // 6 Actual OUT PID received for OUT, Length (words) for IN. + unsigned int tailLength; // 7 "tail" length for IN (bytes) + unsigned int epAddress; // 8 EP address assigned by XUD (Used for marking stall etc) + unsigned int resetting; // 9 Flag to indicate to EP a bus-reset occured. + unsigned int halted; // 10 NAK or STALL + unsigned int saved_array_ptr; // 11 +} XUD_ep_info; + + +#endif //__ASSEMBLER__ #endif // _XUD_H_ diff --git a/lib_xud/module_build_info b/lib_xud/module_build_info index 6df049f6..7d4de900 100644 --- a/lib_xud/module_build_info +++ b/lib_xud/module_build_info @@ -1,13 +1,14 @@ -VERSION = 2.0.2 +VERSION = 2.1.0 MODULE_XCC_FLAGS = $(XCC_FLAGS) \ -O3 \ -DREF_CLK_FREQ=100 \ -fasm-linenum \ -fcomment-asm \ - -DXUD_FULL_PIDTABLE=1 + -DXUD_FULL_PIDTABLE=1 \ + -g -XCC_FLAGS_XUD_IoLoop.S = $(MODULE_XCC_FLAGS) -fschedule -g +XCC_FLAGS_XUD_IoLoop.S = $(MODULE_XCC_FLAGS) -fschedule XCC_FLAGS_endpoint0.xc = $(MODULE_XCC_FLAGS) -Os XCC_FLAGS_dfu.xc = $(MODULE_XCC_FLAGS) -Os @@ -44,6 +45,7 @@ SOURCE_DIRS = src/core \ EXCLUDE_FILES += XUD_CrcAddrCheck.S \ XUD_G_Crc.S \ XUD_PidJumpTable.S \ + XUD_PidJumpTable_RxData.S \ XUD_RxData.S \ XUD_Token_In_DI.S \ XUD_Token_Out_DI.S \ diff --git a/lib_xud/src/core/XUD_CrcAddrCheck.S b/lib_xud/src/core/XUD_CrcAddrCheck.S index 6baf4459..0f378c78 100644 --- a/lib_xud/src/core/XUD_CrcAddrCheck.S +++ b/lib_xud/src/core/XUD_CrcAddrCheck.S @@ -10,17 +10,18 @@ // r10: Extracted EP number #ifdef __XS3A__ - {in r10, res[RXD]; sub r1, r8, 5} // ldc r1 11 - {shr r10, r10, 16; mkmsk r11, r1} - {and r11, r10, r11; shr r4, r10, r1} // r4: Received CRC + {in r10, res[RXD]; sub r1, r8, 5} // ldc r1 11 + {shr r10, r10, 16; mkmsk r11, r1} + {and r11, r10, r11; ldw r8, sp[STACK_CRC5TABLE_ADDR]} - ldaw r8, dp[crc5Table_Addr] - ld8u r8, r8[r11] // Correct CRC + {shr r4, r10, r1 // r4: Received CRC + ld8u r8, r8[r11]} // r8: Expected CRC - xor r4, r4, r8 // R4 set to 0 in L code with in from valid tok port - {BRFF_ru6 r4, 5; shr r10, r11, 7} // Extract EP number + //xor r4, r4, r8 // R4 set to 0 in L code with in from valid tok port + {eq r4, r4, r8; shr r10, r11, 7} // Extract EP number + BRFT_ru6 r4, 5 - ldw r11, sp[STACK_RXA_PORT] // Wait for RXA to gow low (i.e. end of packet) + ldw r11, sp[STACK_RXA_PORT] // Wait for RXA to gow low (i.e. end of packet) in r10, res[r11] bt r10, waitforRXALow0 setc res[RXD], XS1_SETC_RUN_CLRBUF diff --git a/lib_xud/src/core/XUD_IoLoop.S b/lib_xud/src/core/XUD_IoLoop.S index 2e0ca65d..2317a9a0 100755 --- a/lib_xud/src/core/XUD_IoLoop.S +++ b/lib_xud/src/core/XUD_IoLoop.S @@ -52,7 +52,8 @@ suspend_t_wtwrsths: #define STACK_TXCRC_INIT (20) #define STACK_RXCRC_INIT (21) #define STACK_PIDJUMPTABLE (22) -#define STACK_HANDSHAKETABLEIN (23) +#define STACK_PIDJUMPTABLE_RXDATA (23) +#define STACK_CRC5TABLE_ADDR (24) // Params #define STACK_VTOK_PORT (STACK_EXTEND + 1) @@ -263,8 +264,13 @@ ConfigSofJump: #endif ConfigSofJump_Done: stw r10, sp[STACK_PIDJUMPTABLE] - ldaw r10, dp[handshakeTable_IN] // Load handshake table - stw r10, sp[STACK_HANDSHAKETABLEIN] + + ldaw r10, dp[PidJumpTable_RxData] + stw r10, sp[STACK_PIDJUMPTABLE_RXDATA] + + ldaw r10, dp[crc5Table_Addr] + stw r10, sp[STACK_CRC5TABLE_ADDR] + ConfigRxErrEventVector: setc res[r3], XS1_SETC_COND_EQ @@ -374,4 +380,5 @@ Return: // Tables of tables... #include "./included/XUD_PidJumpTable.S" +#include "./included/XUD_PidJumpTable_RxData.S" diff --git a/lib_xud/src/core/XUD_Main.xc b/lib_xud/src/core/XUD_Main.xc index 00cfffb3..2ce8b84c 100755 --- a/lib_xud/src/core/XUD_Main.xc +++ b/lib_xud/src/core/XUD_Main.xc @@ -62,22 +62,7 @@ on USB_TILE: clock rx_usb_clk = XS1_CLKBLK_5; XUD_chan epChans[USB_MAX_NUM_EP]; XUD_chan epChans0[USB_MAX_NUM_EP]; -/* TODO pack this to save mem - * TODO size of this hardcoded in ResetRpStateByAddr_ - */ -typedef struct XUD_ep_info -{ - unsigned int chan_array_ptr; // 0 - unsigned int ep_xud_chanend; // 1 - unsigned int ep_client_chanend; // 2 - unsigned int scratch; // 3 used for datalength in - unsigned int pid; // 4 Expected out PID - unsigned int epType; // 5 Data - unsigned int actualPid; // 6 Actual OUT PID received for OUT, Length (words) for IN. - unsigned int tailLength; // 7 "tail" length for IN (bytes) - unsigned int epAddress; // 8 EP address assigned by XUD (Used for marking stall etc) - unsigned int resetting; // 9 Flag to indicate to EP a bus-reset occured. -} XUD_ep_info; + XUD_ep_info ep_info[USB_MAX_NUM_EP]; @@ -93,8 +78,8 @@ extern unsigned XUD_LLD_IoLoop( XUD_EpType epTypeTableOut[], XUD_EpType epTypeTableIn[], XUD_chan epChans[], int epCount, chanend? c_sof) ; -unsigned handshakeTable_IN[USB_MAX_NUM_EP_IN] = {0}; // 0 or STALL -unsigned handshakeTable_OUT[USB_MAX_NUM_EP_OUT]; // NAK or STALL +unsigned ep_addr[USB_MAX_NUM_EP]; + unsigned sentReset=0; unsigned crcmask = 0b11111111111; @@ -181,21 +166,18 @@ static int XUD_Manager_loop(XUD_chan epChans0[], XUD_chan epChans[], chanend ?c #endif #ifdef XUD_SIM_XSIM - #if (XUD_CORE_CLOCK > 500) - #define RX_RISE_DELAY 2 - #define RX_FALL_DELAY 5 - #define TX_RISE_DELAY 2 - #define TX_FALL_DELAY 3 - #elif (XUD_CORE_CLOCK > 400) - #define RX_RISE_DELAY 5 - #define RX_FALL_DELAY 5 - #define TX_RISE_DELAY 2 - #define TX_FALL_DELAY 3 - #else /* 400 */ - #define RX_RISE_DELAY 3 - #define RX_FALL_DELAY 5 - #define TX_RISE_DELAY 3 - #define TX_FALL_DELAY 3 + #if (XUD_CORE_CLOCK >= 700) + #define RX_RISE_DELAY 0 + #define RX_FALL_DELAY 0 + #define TX_RISE_DELAY 0 + #define TX_FALL_DELAY 7 + #elif (XUD_CORE_CLOCK >= 600) + #define RX_RISE_DELAY 0 + #define RX_FALL_DELAY 0 + #define TX_RISE_DELAY 0 + #define TX_FALL_DELAY 5 + #else + #error XUD_CORE_CLOCK must be >= 600 #endif #else #if (XUD_CORE_CLOCK >= 600) @@ -203,7 +185,6 @@ static int XUD_Manager_loop(XUD_chan epChans0[], XUD_chan epChans[], chanend ?c #define RX_FALL_DELAY 1 #define TX_RISE_DELAY 1 #define TX_FALL_DELAY 1 - #elif (XUD_CORE_CLOCK >= 500) #define RX_RISE_DELAY 1 #define RX_FALL_DELAY 0 @@ -230,20 +211,18 @@ static int XUD_Manager_loop(XUD_chan epChans0[], XUD_chan epChans[], chanend ?c set_port_inv(p_usb_clk); set_port_sample_delay(p_usb_clk); -#if !defined(XUD_SIM_XSIM) - //This delay controls the capture of rdy + // This delay controls the capture of rdy set_clock_rise_delay(tx_usb_clk, TX_RISE_DELAY); - //this delay controls the launch of data. + // This delay controls the launch of data. set_clock_fall_delay(tx_usb_clk, TX_FALL_DELAY); - //this delay th capture of the rdyIn and data. + // This delay the capture of the rdyIn and data. set_clock_rise_delay(rx_usb_clk, RX_RISE_DELAY); set_clock_fall_delay(rx_usb_clk, RX_FALL_DELAY); -#endif #ifdef __XS3A__ - set_pad_delay(flag1_port, 3); + set_pad_delay(flag1_port, 2); #else set_pad_delay(flag1_port, 2); #endif @@ -312,7 +291,7 @@ static int XUD_Manager_loop(XUD_chan epChans0[], XUD_chan epChans[], chanend ?c /* Sample line state and check for reset (or suspend) */ XUD_LineState_t ls = XUD_HAL_GetLineState(); if(ls == XUD_LINESTATE_SE0) - reset == 1; + reset = 1; else reset = 0; } @@ -337,7 +316,6 @@ static int XUD_Manager_loop(XUD_chan epChans0[], XUD_chan epChans[], chanend ?c /* Test if coming back from reset or suspend */ if(reset == 1) { - if(!sentReset) { SendResetToEps(epChans0, epChans, epTypeTableOut, epTypeTableIn, noEpOut, noEpIn, USB_RESET_TOKEN); @@ -484,16 +462,16 @@ int XUD_Main(chanend c_ep_out[], int noEpOut, for(int i = 0; i < USB_MAX_NUM_EP_OUT; i++) { - handshakeTable_OUT[i] = USB_PIDn_NAK; ep_info[i].epAddress = i; ep_info[i].resetting = 0; + ep_info[i].halted = USB_PIDn_NAK; } for(int i = 0; i < USB_MAX_NUM_EP_IN; i++) { - handshakeTable_IN[i] = 0; ep_info[USB_MAX_NUM_EP_OUT+i].epAddress = (i | 0x80); ep_info[USB_MAX_NUM_EP_OUT+i].resetting = 0; + ep_info[USB_MAX_NUM_EP_OUT+i].halted = 0; } /* Populate arrays of channels and status flag tabes */ @@ -505,16 +483,18 @@ int XUD_Main(chanend c_ep_out[], int noEpOut, epChans0[i] = XUD_Sup_GetResourceId(c_ep_out[i]); asm("ldaw %0, %1[%2]":"=r"(x):"r"(epChans),"r"(i)); - ep_info[i].chan_array_ptr = x; + ep_info[i].array_ptr = x; + ep_info[i].saved_array_ptr = 0; asm("mov %0, %1":"=r"(x):"r"(c_ep_out[i])); - ep_info[i].ep_xud_chanend = x; + ep_info[i].xud_chanend = x; asm("getd %0, res[%1]":"=r"(x):"r"(c_ep_out[i])); - ep_info[i].ep_client_chanend = x; + ep_info[i].client_chanend = x; asm("ldaw %0, %1[%2]":"=r"(x):"r"(ep_info),"r"(i*sizeof(XUD_ep_info)/sizeof(unsigned))); outuint(c_ep_out[i], x); + ep_addr[i] = x; epStatFlagTableOut[i] = epTypeTableOut[i] & XUD_STATUS_ENABLE; epTypeTableOut[i] = epTypeTableOut[i] & 0x7FFFFFFF; @@ -537,17 +517,19 @@ int XUD_Main(chanend c_ep_out[], int noEpOut, epChans0[i+USB_MAX_NUM_EP_OUT] = XUD_Sup_GetResourceId(c_ep_in[i]); asm("ldaw %0, %1[%2]":"=r"(x):"r"(epChans),"r"(USB_MAX_NUM_EP_OUT+i)); - ep_info[USB_MAX_NUM_EP_OUT+i].chan_array_ptr = x; + ep_info[USB_MAX_NUM_EP_OUT+i].array_ptr = x; + ep_info[USB_MAX_NUM_EP_OUT+i].saved_array_ptr = 0; asm("mov %0, %1":"=r"(x):"r"(c_ep_in[i])); - ep_info[USB_MAX_NUM_EP_OUT+i].ep_xud_chanend = x; + ep_info[USB_MAX_NUM_EP_OUT+i].xud_chanend = x; asm("getd %0, res[%1]":"=r"(x):"r"(c_ep_in[i])); - ep_info[USB_MAX_NUM_EP_OUT+i].ep_client_chanend = x; + ep_info[USB_MAX_NUM_EP_OUT+i].client_chanend = x; asm("ldaw %0, %1[%2]":"=r"(x):"r"(ep_info),"r"((USB_MAX_NUM_EP_OUT+i)*sizeof(XUD_ep_info)/sizeof(unsigned))); outuint(c_ep_in[i], x); + ep_addr[USB_MAX_NUM_EP_OUT+i] = x; ep_info[USB_MAX_NUM_EP_OUT+i].pid = USB_PIDn_DATA0; diff --git a/lib_xud/src/core/included/XUD_PidJumpTable_RxData.S b/lib_xud/src/core/included/XUD_PidJumpTable_RxData.S new file mode 100755 index 00000000..bad18a86 --- /dev/null +++ b/lib_xud/src/core/included/XUD_PidJumpTable_RxData.S @@ -0,0 +1,556 @@ +// Copyright 2011-2021 XMOS LIMITED. +// This Software is subject to the terms of the XMOS Public Licence: Version 1. +#if defined (__XS2A__) + +// PID jump table +.section .dp.data, "adw", @progbits + +.globl PidJumpTable_RxData +.type PidJumpTable_RxData, @object + +.cc_top PidJumpTable_RxData.func, PidJumpTable_RxData +.align 4 +PidJumpTable_RxData: +.word Pid_Reserved // 0 0x00 +.word Pid_Out // 1 0x01 +.word Pid_Ack // 2 0x02 +.word Pid_Data0_RxData // 3 0x03 +.word Pid_Ping // 4 0x04 +.word Pid_Sof // 5 0x05 +.word Pid_Nyet // 6 0x06 +.word Pid_Data2_RxData // 7 0x07 +.word Pid_Split // 8 0x08 +.word Pid_In // 9 0x09 +.word Pid_Nak // 10 0x0a +.word Pid_Data1_RxData // 11 0x0b +.word Pid_Pre // 12 0x0c +.word Pid_Setup // 13 0x0d +.word Pid_Stall // 14 0x0e +.word Pid_Datam_RxData // 15 0x0f +#if defined(XUD_DEBUG_VERSION) || defined(XUD_FULL_PIDTABLE) +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData +.word Pid_Bad_RxData + +#endif + +.size PidJumpTable_RxData, .-PidJumpTable_RxData +.cc_bottom PidJumpTable_RxData.func + +#endif + +#if defined(__XS3A__) +// Generated using genpidtable.c +.section .dp.data, "adw", @progbits +.globl PidJumpTable_RxData +.type PidJumpTable_RxData, @function + +.cc_top PidJumpTable_RxData.func, PidJumpTable_RxData +.align 4 + +PidJumpTable_RxData: +.word Pid_Bad_RxData // 0 0x00 +.word Pid_Bad_RxData // 1 0x01 +.word Pid_Bad_RxData // 2 0x02 +.word Pid_Bad_RxData // 3 0x03 +.word Pid_Bad_RxData // 4 0x04 +.word Pid_Bad_RxData // 5 0x05 +.word Pid_Bad_RxData // 6 0x06 +.word Pid_Bad_RxData // 7 0x07 +.word Pid_Bad_RxData // 8 0x08 +.word Pid_Bad_RxData // 9 0x09 +.word Pid_Bad_RxData // 10 0x0a +.word Pid_Bad_RxData // 11 0x0b +.word Pid_Bad_RxData // 12 0x0c +.word Pid_Bad_RxData // 13 0x0d +.word Pid_Bad_RxData // 14 0x0e +.word Pid_MData // 15 0x0f +.word Pid_Bad_RxData // 16 0x10 +.word Pid_Bad_RxData // 17 0x11 +.word Pid_Bad_RxData // 18 0x12 +.word Pid_Bad_RxData // 19 0x13 +.word Pid_Bad_RxData // 20 0x14 +.word Pid_Bad_RxData // 21 0x15 +.word Pid_Bad_RxData // 22 0x16 +.word Pid_Bad_RxData // 23 0x17 +.word Pid_Bad_RxData // 24 0x1 +.word Pid_Bad_RxData // 25 0x19 +.word Pid_Bad_RxData // 26 0x1a +.word Pid_Bad_RxData // 27 0x1b +.word Pid_Bad_RxData // 28 0x1c +.word Pid_Bad_RxData // 29 0x1d +.word Pid_Bad_RxData // 30 0x1e +.word Pid_Bad_RxData // 31 0x1f +.word Pid_Bad_RxData // 32 0x20 +.word Pid_Bad_RxData // 33 0x21 +.word Pid_Bad_RxData // 34 0x22 +.word Pid_Bad_RxData // 35 0x23 +.word Pid_Bad_RxData // 36 0x24 +.word Pid_Bad_RxData // 37 0x25 +.word Pid_Bad_RxData // 38 0x26 +.word Pid_Bad_RxData // 39 0x27 +.word Pid_Bad_RxData // 40 0x28 +.word Pid_Bad_RxData // 41 0x29 +.word Pid_Bad_RxData // 42 0x2a +.word Pid_Bad_RxData // 43 0x2b +.word Pid_Bad_RxData // 44 0x2c +.word Pid_Bad_RxData // 45 0x2d +.word Pid_Bad_RxData // 46 0x2e +.word Pid_Bad_RxData // 47 0x2f +.word Pid_Bad_RxData // 48 0x30 +.word Pid_Bad_RxData // 49 0x31 +.word Pid_Bad_RxData // 50 0x32 +.word Pid_Bad_RxData // 51 0x33 +.word Pid_Bad_RxData // 52 0x34 +.word Pid_Bad_RxData // 53 0x35 +.word Pid_Bad_RxData // 54 0x36 +.word Pid_Bad_RxData // 55 0x37 +.word Pid_Bad_RxData // 56 0x38 +.word Pid_Bad_RxData // 57 0x39 +.word Pid_Bad_RxData // 58 0x3a +.word Pid_Bad_RxData // 59 0x3b +.word Pid_Bad_RxData // 60 0x3c +.word Pid_Bad_RxData // 61 0x3d +.word Pid_Bad_RxData // 62 0x3e +.word Pid_Bad_RxData // 63 0x3f +.word Pid_Bad_RxData // 64 0x40 +.word Pid_Bad_RxData // 65 0x41 +.word Pid_Bad_RxData // 66 0x42 +.word Pid_Bad_RxData // 67 0x43 +.word Pid_Bad_RxData // 68 0x44 +.word Pid_Bad_RxData // 69 0x45 +.word Pid_Bad_RxData // 70 0x46 +.word Pid_Bad_RxData // 71 0x47 +.word Pid_Bad_RxData // 72 0x48 +.word Pid_Bad_RxData // 73 0x49 +.word Pid_Bad_RxData // 74 0x4a +.word Pid_Data1_RxData // 75 0x4b +.word Pid_Bad_RxData // 76 0x4c +.word Pid_Bad_RxData // 77 0x4d +.word Pid_Bad_RxData // 78 0x4e +.word Pid_Bad_RxData // 79 0x4f +.word Pid_Bad_RxData // 80 0x50 +.word Pid_Bad_RxData // 81 0x51 +.word Pid_Bad_RxData // 82 0x52 +.word Pid_Bad_RxData // 83 0x53 +.word Pid_Bad_RxData // 84 0x54 +.word Pid_Bad_RxData // 85 0x55 +.word Pid_Bad_RxData // 86 0x56 +.word Pid_Bad_RxData // 87 0x57 +.word Pid_Bad_RxData // 88 0x58 +.word Pid_Bad_RxData // 89 0x59 +.word Pid_Bad_RxData // 90 0x5a +.word Pid_Bad_RxData // 91 0x5b +.word Pid_Bad_RxData // 92 0x5c +.word Pid_Bad_RxData // 93 0x5d +.word Pid_Bad_RxData // 94 0x5e +.word Pid_Bad_RxData // 95 0x5f +.word Pid_Bad_RxData // 96 0x60 +.word Pid_Bad_RxData // 97 0x61 +.word Pid_Bad_RxData // 98 0x62 +.word Pid_Bad_RxData // 99 0x63 +.word Pid_Bad_RxData // 100 0x64 +.word Pid_Bad_RxData // 101 0x65 +.word Pid_Bad_RxData // 102 0x66 +.word Pid_Bad_RxData // 103 0x67 +.word Pid_Bad_RxData // 104 0x68 +.word Pid_Bad_RxData // 105 0x69 +.word Pid_Bad_RxData // 106 0x6a +.word Pid_Bad_RxData // 107 0x6b +.word Pid_Bad_RxData // 108 0x6c +.word Pid_Bad_RxData // 109 0x6d +.word Pid_Bad_RxData // 110 0x6e +.word Pid_Bad_RxData // 111 0x6f +.word Pid_Bad_RxData // 112 0x70 +.word Pid_Bad_RxData // 113 0x71 +.word Pid_Bad_RxData // 114 0x72 +.word Pid_Bad_RxData // 115 0x73 +.word Pid_Bad_RxData // 116 0x74 +.word Pid_Bad_RxData // 117 0x75 +.word Pid_Bad_RxData // 118 0x76 +.word Pid_Bad_RxData // 119 0x77 +.word Pid_Bad_RxData // 120 0x78 +.word Pid_Bad_RxData // 121 0x79 +.word Pid_Bad_RxData // 122 0x7a +.word Pid_Bad_RxData // 123 0x7b +.word Pid_Bad_RxData // 124 0x7c +.word Pid_Bad_RxData // 125 0x7d +.word Pid_Bad_RxData // 126 0x7e +.word Pid_Bad_RxData // 127 0x7f +.word Pid_Bad_RxData // 128 0x80 +.word Pid_Bad_RxData // 129 0x81 +.word Pid_Bad_RxData // 130 0x82 +.word Pid_Bad_RxData // 131 0x83 +.word Pid_Bad_RxData // 132 0x84 +.word Pid_Bad_RxData // 133 0x85 +.word Pid_Bad_RxData // 134 0x86 +.word Pid_Data2 // 135 0x87 +.word Pid_Bad_RxData // 136 0x88 +.word Pid_Bad_RxData // 137 0x89 +.word Pid_Bad_RxData // 138 0x8a +.word Pid_Bad_RxData // 139 0x8b +.word Pid_Bad_RxData // 140 0x8c +.word Pid_Bad_RxData // 141 0x8d +.word Pid_Bad_RxData // 142 0x8e +.word Pid_Bad_RxData // 143 0x8f +.word Pid_Bad_RxData // 144 0x90 +.word Pid_Bad_RxData // 145 0x91 +.word Pid_Bad_RxData // 146 0x92 +.word Pid_Bad_RxData // 147 0x93 +.word Pid_Bad_RxData // 148 0x94 +.word Pid_Bad_RxData // 149 0x95 +.word Pid_Bad_RxData // 150 0x96 +.word Pid_Bad_RxData // 151 0x97 +.word Pid_Bad_RxData // 152 0x98 +.word Pid_Bad_RxData // 153 0x99 +.word Pid_Bad_RxData // 154 0x9a +.word Pid_Bad_RxData // 155 0x9b +.word Pid_Bad_RxData // 156 0x9c +.word Pid_Bad_RxData // 157 0x9d +.word Pid_Bad_RxData // 158 0x9e +.word Pid_Bad_RxData // 159 0x9f +.word Pid_Bad_RxData // 160 0xa0 +.word Pid_Bad_RxData // 161 0xa1 +.word Pid_Bad_RxData // 162 0xa2 +.word Pid_Bad_RxData // 163 0xa3 +.word Pid_Bad_RxData // 164 0xa4 +.word Pid_Bad_RxData // 165 0xa5 +.word Pid_Bad_RxData // 166 0xa6 +.word Pid_Bad_RxData // 167 0xa7 +.word Pid_Bad_RxData // 168 0xa8 +.word Pid_Bad_RxData // 169 0xa9 +.word Pid_Bad_RxData // 170 0xaa +.word Pid_Bad_RxData // 171 0xab +.word Pid_Bad_RxData // 172 0xac +.word Pid_Bad_RxData // 173 0xad +.word Pid_Bad_RxData // 174 0xae +.word Pid_Bad_RxData // 175 0xaf +.word Pid_Bad_RxData // 176 0xb0 +.word Pid_Bad_RxData // 177 0xb1 +.word Pid_Bad_RxData // 178 0xb2 +.word Pid_Bad_RxData // 179 0xb3 +.word Pid_Bad_RxData // 180 0xb4 +.word Pid_Bad_RxData // 181 0xb5 +.word Pid_Bad_RxData // 182 0xb6 +.word Pid_Bad_RxData // 183 0xb7 +.word Pid_Bad_RxData // 184 0xb8 +.word Pid_Bad_RxData // 185 0xb9 +.word Pid_Bad_RxData // 186 0xba +.word Pid_Bad_RxData // 187 0xbb +.word Pid_Bad_RxData // 188 0xbc +.word Pid_Bad_RxData // 189 0xbd +.word Pid_Bad_RxData // 190 0xbe +.word Pid_Bad_RxData // 191 0xbf +.word Pid_Bad_RxData // 192 0xc0 +.word Pid_Bad_RxData // 193 0xc1 +.word Pid_Bad_RxData // 194 0xc2 +.word Pid_Data0_RxData // 195 0xc3 +.word Pid_Bad_RxData // 196 0xc4 +.word Pid_Bad_RxData // 197 0xc5 +.word Pid_Bad_RxData // 198 0xc6 +.word Pid_Bad_RxData // 199 0xc7 +.word Pid_Bad_RxData // 200 0xc8 +.word Pid_Bad_RxData // 201 0xc9 +.word Pid_Bad_RxData // 202 0xca +.word Pid_Bad_RxData // 203 0xcb +.word Pid_Bad_RxData // 204 0xcc +.word Pid_Bad_RxData // 205 0xcd +.word Pid_Bad_RxData // 206 0xce +.word Pid_Bad_RxData // 207 0xcf +.word Pid_Bad_RxData // 208 0xd0 +.word Pid_Bad_RxData // 209 0xd1 +.word Pid_Bad_RxData // 210 0xd2 +.word Pid_Bad_RxData // 211 0xd3 +.word Pid_Bad_RxData // 212 0xd4 +.word Pid_Bad_RxData // 213 0xd5 +.word Pid_Bad_RxData // 214 0xd6 +.word Pid_Bad_RxData // 215 0xd7 +.word Pid_Bad_RxData // 216 0xd8 +.word Pid_Bad_RxData // 217 0xd9 +.word Pid_Bad_RxData // 218 0xda +.word Pid_Bad_RxData // 219 0xdb +.word Pid_Bad_RxData // 220 0xdc +.word Pid_Bad_RxData // 221 0xdd +.word Pid_Bad_RxData // 222 0xde +.word Pid_Bad_RxData // 223 0xdf +.word Pid_Bad_RxData // 224 0xe0 +.word Pid_Bad_RxData // 225 0xe1 +.word Pid_Bad_RxData // 226 0xe2 +.word Pid_Bad_RxData // 227 0xe3 +.word Pid_Bad_RxData // 228 0xe4 +.word Pid_Bad_RxData // 229 0xe5 +.word Pid_Bad_RxData // 230 0xe6 +.word Pid_Bad_RxData // 231 0xe7 +.word Pid_Bad_RxData // 232 0xe8 +.word Pid_Bad_RxData // 233 0xe9 +.word Pid_Bad_RxData // 234 0xea +.word Pid_Bad_RxData // 235 0xeb +.word Pid_Bad_RxData // 236 0xec +.word Pid_Bad_RxData // 237 0xed +.word Pid_Bad_RxData // 238 0xee +.word Pid_Bad_RxData // 239 0xef +.word Pid_Bad_RxData // 240 0xf0 +.word Pid_Bad_RxData // 241 0xf1 +.word Pid_Bad_RxData // 242 0xf2 +.word Pid_Bad_RxData // 243 0xf3 +.word Pid_Bad_RxData // 244 0xf4 +.word Pid_Bad_RxData // 245 0xf5 +.word Pid_Bad_RxData // 246 0xf6 +.word Pid_Bad_RxData // 247 0xf7 +.word Pid_Bad_RxData // 248 0xf8 +.word Pid_Bad_RxData // 249 0xf9 +.word Pid_Bad_RxData // 250 0xfa +.word Pid_Bad_RxData // 251 0xfb +.word Pid_Bad_RxData // 252 0xfc +.word Pid_Bad_RxData // 253 0xfd +.word Pid_Bad_RxData // 254 0xfe +.word Pid_Bad_RxData // 255 0xff + +.size PidJumpTable_RxData, .-PidJumpTable_RxData +.cc_bottom PidJumpTable_RxData.func + +#endif diff --git a/lib_xud/src/core/included/XUD_RxData.S b/lib_xud/src/core/included/XUD_RxData.S index dde77ddf..fdc9a64d 100644 --- a/lib_xud/src/core/included/XUD_RxData.S +++ b/lib_xud/src/core/included/XUD_RxData.S @@ -1,68 +1,97 @@ // Copyright 2019-2021 XMOS LIMITED. // This Software is subject to the terms of the XMOS Public Licence: Version 1. - #define PASTER(x,y) x ## _ ## y #define EVALUATOR(x,y) PASTER(x,y) -//#define LABEL(fun) EVALUATOR(fun, LABELNO) #define LABEL(fun) fun // r0: RXD: Rx Data port // r1: Buffer // r2: Tx Port // r3: Ep structure -// r4: zero -// r5: buffer address -// r5: ep structures array -// r6: crc rx init -// r7: crc tx init -// r9: crc poly -// r8: -// r10: ep number -// r11: scratch +// r4: Zero (set in XUD_CrcAddCheck.S) then buffer index +// r5: EP structures array +// r6: CRC Rx init +// r7: CRC Tx init +// r9: CRC poly +// r8: Scratch +// r10: EP number +// r11: Scratch -doRXData_badPid: - ldc r8, 16 // Note, this is a cut-down version of XUD_TokenJump.S - ldaw r10, dp[PidJumpTable] - ldw r11, r10[r7] - {bau r11; setpsc res[RXD], r8} +// On exit require: +// r4: Datalength (words) +// r8: Taillength (bits) +// r11: Expected CRC -LABEL(doRXData): +Pid_Bad_RxData: + ldaw r10, dp[PidJumpTable] + {ldw r11, r10[r4]; ldc r8, 16} + {bau r11; setpsc res[RXD], r8} // XUD_CrcAddrCheck.S requires 16 in r8 - inpw r8, res[r0], 8 // Input PID +doRXData: + inpw r4, res[r0], 8 // Input PID + ldw r8, sp[STACK_RXA_PORT] +#ifdef __XS2A__ // If pid != DATAx then jump and handle as a token. DATA0, DATA1, DATA2 & MDATA all of the form 0bxx11. // This is a fast alternative to a "timeout" - {shr r7, r8, 24; mkmsk r11, 2} - and r11, r11, r7 - eq r11, r11, 3 - bf r11, doRXData_badPid - {setsr 1; ldw r7, sp[STACK_RXA_PORT]} // Load RxA Port ID + // Note, this doesn't check that PID[0:3] = ~PID[4:7] - which is an issue for XS3 + {mkmsk r11, 2; shr r4, r4, 24} + and r11, r11, r4 // Store PID into EP structure, + eq r11, r11, 3 + bf r11, Pid_Bad_RxData +#else + {shr r4, r4, 24; ldw r11, sp[STACK_PIDJUMPTABLE_RXDATA]} + ldw r11, r11[r4] + bau r11 +#endif + +Pid_Datam_RxData: +Pid_Data0_RxData: +Pid_Data1_RxData: +Pid_Data2_RxData: + {stw r4, r3[6]; setsr 1} // Store PID into EP structure -LABEL(GotRxPid): - eeu res[r7] // Enable events on RxA +GotRxPid: + {eeu res[r8]; mkmsk r4, 32} // Enable events on RxA + // Init buffer index to -1 -LABEL(NextRxWord): +NextRxWord: // Partially un-rolled to assist with timing + in r11, res[r0] + crc32_inc r6, r11, r9, r4, 1 + stw r11, r1[r4] in r11, res[r0] + crc32_inc r6, r11, r9, r4, 1 stw r11, r1[r4] + in r11, res[r0] crc32_inc r6, r11, r9, r4, 1 + stw r11, r1[r4] in r11, res[r0] + crc32_inc r6, r11, r9, r4, 1 stw r11, r1[r4] + in r11, res[r0] crc32_inc r6, r11, r9, r4, 1 + stw r11, r1[r4] in r11, res[r0] + crc32_inc r6, r11, r9, r4, 1 stw r11, r1[r4] + in r11, res[r0] crc32_inc r6, r11, r9, r4, 1 + stw r11, r1[r4] in r11, res[r0] + crc32_inc r6, r11, r9, r4, 1 stw r11, r1[r4] + in r11, res[r0] crc32_inc r6, r11, r9, r4, 1 - bu LABEL(NextRxWord) + stw r11, r1[r4] + bu NextRxWord ///////////////////////////////////////////////////////////////////////////// .align 32 -.skip 20 +.skip 16 RxALow: - {stw r8, r3[6]; in r7, res[r7]} // Store (NON-SHIFTED) PID into EP structure, - // Clear event data on RXA + stw r11, r1[r4] // Extra stw, if not enough MIPS STW in loop above may not have chance to run + {in r8, res[r8]; add r4, r4, 1} // Clear event data on RXA endin r8, res[r0] LABEL(RxTail): {in r11, res[r0]; bru r8} diff --git a/lib_xud/src/core/included/XUD_Token_In_DI.S b/lib_xud/src/core/included/XUD_Token_In_DI.S index 965515f4..a9ce35ea 100755 --- a/lib_xud/src/core/included/XUD_Token_In_DI.S +++ b/lib_xud/src/core/included/XUD_Token_In_DI.S @@ -13,13 +13,13 @@ // R10: EP number (used here) // R9 : CRC16 Poly (used here) // R8 : -// R7 : +// R7 : Tx CRC init // R6 : ep_pid_sequence_table_IN_A -// R5 : Channel Array +// R5 : EP structures array // R4 : // R3 : 0 // R2 : TXD -// R1 : Valid Token Port (XS2 only) +// R1 : XS2: Valid Token Port, XS3: Spare! // R0 : RXD .align FUNCTION_ALIGNMENT XUD_IN_NotReady: @@ -31,8 +31,10 @@ XUD_IN_NotReady: #include "XUD_TokenJmp.S" XUD_IN_TxHandshake: // Non-Iso - ldaw r11, dp[handshakeTable_IN] // Load handshake table - ldw r11, r11[r10] // Load handshake PID (or 0) + ldaw r11, dp[ep_addr] + ldw r11, r11[r3] + ldw r11, r11[10] + bf r11, XUD_IN_TxNak outpw res[TXD], r11, 8 // Output STALL #include "XUD_TokenJmp.S" @@ -52,12 +54,7 @@ Pid_In: ldaw r3, r10[4] // R3 = R10 + 16 ldw r4, r5[r3] // Load EP structure address bf r4, XUD_IN_NotReady - - ldaw r11, dp[handshakeTable_IN] // Load handshake table - ldw r11, r11[r10] - bt r11, XUD_IN_TxStall // Note, user could potentially stall an ISO EP. - - ldw r11, r4[4] // Load PID from structure + ldw r1, r4[4] // Load PID from structure XUD_IN_Ready: ldw r8, r4[3] // Load buffer @@ -66,13 +63,12 @@ XUD_IN_Ready: bf r4, XUD_IN_SmallTxPacket // Check for Short packet XUD_IN_Tx: - outpw res[TXD], r11, 8 // Out PID ldw r11, r8[r4] // Load first data word + crc32_inc r7, r11, r9, r4, 1 + outpw res[TXD], r1, 8 // Out PID -XUD_IN_TxPid: - out res[TXD], r11 - crc32_inc r7, r11, r9, r4, 1 - bf r4, XUD_IN_TxLoopEnd +XUD_IN_Loop0: + {out res[TXD], r11; bf r4, XUD_IN_TxLoopEnd} XUD_IN_TxLoop: ldw r11, r8[r4] // Load first data word @@ -102,7 +98,6 @@ DoneTail: SetupReceiveHandShake: ldc r11, 8 setpsc res[RXD], r11 // Set port shift count (expect 8 bit handshake) - eeu res[RXD] // Events on RXD always enabled - Can;t be any more due to using events on channels SetupTimeout: // Timeout done using another port we dont happen to already be using events on. Cunning. #ifdef __XS2A__ @@ -110,6 +105,8 @@ SetupTimeout: // Timeout done using another #else ldw r1, dp[rx_rdy] // TODO load from stack #endif + eeu res[RXD] // Events on RXD always enabled - Can;t be any more due to using events on channels + in r11, res[r1] // Do input and get port time/timestamps getts r11, res[r1] ldw r9, dp[g_txHandshakeTimeout] @@ -131,7 +128,6 @@ TxHandshakeTimeOut: // Transmitted data, and got something back within the timeout. Check for valid handshake... .align FUNCTION_ALIGNMENT TxHandShakeReceived: -XUD_IN_RxAck: in r11, res[RXD] // Input data from RXD port clrpt res[r1] // Clear port time on valid token port @@ -174,46 +170,45 @@ TxTail0s: // We know this is a < 4 byte // So crc = 0. Note our normal crc calculation works for this, it is // Not a special CRC case, but helps with timing. XUD_IN_TxPid_TailS0: - outpw res[TXD], r11, 8 // PID + outpw res[TXD], r1, 8 // PID XUD_IN_TxCrc_TailS0: - outpw res[TXD], r4, 16 // Output CRC + outpw res[TXD], r4, 16 // Output CRC bu DoneTail .align 32 .skip 0 -TxTail1s: // One tail byte - shl r6, r8, 8 // Concat PID and Data - or r11, r11, r6 - crc8 r7, r8, r8, r9 - crc32 r7, r4, r9 // r4: 0 - not r7, r7 +TxTail1s: // One tail byte + crcn r7, r8, r9, r6 + crc32 r7, r4, r9 // r4: 0 XUD_IN_TxPid_TailS1: - outpw res[TXD], r11, 16 // PID + not r7, r7 + outpw res[TXD], r1, 8 // Output PID + outpw res[TXD], r8, 8 // Output data[0] XUD_IN_TxCrc_TailS1: outpw res[TXD], r7, 16 bu DoneTail .align 32 .skip 0 -TxTail2s: // Two tail byte +TxTail2s: // Two tail byte crcn r7, r8, r9, r6 - shl r6, r8, 8 - crc32 r7, r4, r9 // r4: 0 - {not r7, r7; or r11, r11, r6} + crc32 r7, r4, r9 // r4: 0 XUD_IN_TxPid_TailS2: - outpw res[TXD], r11, 24 // Output PID and 2 bytes of data + outpw res[TXD], r1, 8 // Output PID + outpw res[TXD], r8, 16 // Output data[0:1] + not r7, r7 XUD_IN_TxCrc_TailS2: - outpw res[TXD], r7, 16 // Output CRC16 + outpw res[TXD], r7, 16 // Output CRC16 bu DoneTail .align 32 .skip 0 -TxTail3s: // Three tail byte +TxTail3s: // Three tail byte XUD_IN_TxPid_TailS3: - outpw res[TXD], r11, 8 // PID + outpw res[TXD], r1, 8 // PID outpw res[TXD], r8, 24 crcn r7, r8, r9, r6 - crc32 r7, r4, r9 // r4: 0 + crc32 r7, r4, r9 // r4: 0 not r7, r7 XUD_IN_TxCrc_TailS3: outpw res[TXD], r7, 16 @@ -221,12 +216,12 @@ XUD_IN_TxCrc_TailS3: .align 32 .skip 0 -TxTail4s: // Four tail byte +TxTail4s: // Four tail byte XUD_IN_TxPid_TailS4: - outpw res[TXD], r11, 8 // PID + outpw res[TXD], r1, 8 // PID out res[TXD], r8 crc32 r7, r8, r9 - crc32 r7, r4, r9 // r4: 0 + crc32 r7, r4, r9 // r4: 0 not r7, r7 XUD_IN_TxCrc_TailS4: outpw res[TXD], r7, 16 diff --git a/lib_xud/src/core/included/XUD_Token_Out_DI.S b/lib_xud/src/core/included/XUD_Token_Out_DI.S index 04b842ef..55996bd5 100755 --- a/lib_xud/src/core/included/XUD_Token_Out_DI.S +++ b/lib_xud/src/core/included/XUD_Token_Out_DI.S @@ -19,10 +19,10 @@ CheckEpTypeOut: OutReady: stw r11, r5[r10] // Clear ready straight away - we don't to CRC checking on Iso - else we would have to wait for end of packet bl doRXData - clre + {clre; + ldw r11, r3[1]} // Load EP chanend InformEP_Iso: // Iso EP - no handshake - ldw r11, r3[1] // Load EP chanend {out res[r11], r4; ldw r7, sp[STACK_TXCRC_INIT]} // Output datalength (words) & CRC 16 Init (IN) {outt res[r11], r8; ldw r6, sp[STACK_RXCRC_INIT]} // CRC16 init (out) - Needs reseting after an out & Send tail length #ifndef __XS3A__ @@ -39,16 +39,6 @@ DoOutNonIso: doRXDataReturn_NonIso: bf r1, NextTokenAfterOut // Check for bad crc - ldaw r6, dp[handshakeTable_OUT] // Load the handshake table. - {ldw r11, r6[r10] // Get the handshake PID for this EP - ldc r1, USB_PIDn_STALL} // as well as the STALL PID - eq r1, r11, r1 // and compare them. - nop // NOP to ensure minimum interpacket delay. - bt r1, XUD_TokenOut_Handshake // If the handshake PID for this EP is STALL, then - // go and send the handshake without clearing ready - // or communicating back to the application that - // the packet has been received. - ldc r11, USB_PIDn_ACK // Data CRC good, EP not Iso, and EP not halted: Send Ack outpw res[TXD], r11, 8 syncr res[TXD] @@ -80,13 +70,12 @@ Err_RxErr: // RxError signal high during da XUD_TokenOut_BufferFull: ldw r9, sp[STACK_RXA_PORT] setc res[r9], XS1_SETC_RUN_CLRBUF - setc res[r9], XS1_SETC_COND_NEQ + inpw r4, res[r0], 8 // Input PID of next packet. + // TODO catch case where PID is not DATA XUD_TokenOut_WaitForPacketEnd: // Wait for end of data then send NAK in r11, res[r9] - setc res[r9], XS1_SETC_COND_EQ - in r11, res[r9] - // TODO: Observe interpacket delay + #ifndef XUD_NAK_ISO_OUT ldw r4, sp[STACK_EPTYPES_OUT] // Load ep type table ldw r4, r4[r10] // load EP type @@ -94,9 +83,11 @@ XUD_TokenOut_WaitForPacketEnd: // Wait for end of data then sen #endif // Load handshake (ACK or STALL) - ldaw r6, dp[handshakeTable_OUT] // Load handshake table XUD_TokenOut_Handshake: - ldw r11, r6[r10] + ldaw r6, dp[ep_addr] + ldw r6, r6[r10] + ldw r11, r6[10] + outpw res[TXD], r11, 8 syncr res[TXD] diff --git a/lib_xud/src/core/included/XUD_Token_Ping.S b/lib_xud/src/core/included/XUD_Token_Ping.S index 79ce7dc2..0ae72f43 100755 --- a/lib_xud/src/core/included/XUD_Token_Ping.S +++ b/lib_xud/src/core/included/XUD_Token_Ping.S @@ -31,11 +31,11 @@ PrimaryBufferFull_PING: // Send NAK (or STALL) nop nop #endif - nop - nop - nop - ldaw r11, dp[handshakeTable_OUT] // Load handshake table - ldw r11, r11[r10] // Load handshake (ACK or STALL) + + ldaw r11, dp[ep_addr] + ldw r11, r11[r10] + ldw r11, r11[10] + outpw res[TXD], r11, 8 bu NextTokenAfterPing .scheduling default diff --git a/lib_xud/src/core/included/XUD_Token_Setup_DI.S b/lib_xud/src/core/included/XUD_Token_Setup_DI.S index 870f1321..81131762 100644 --- a/lib_xud/src/core/included/XUD_Token_Setup_DI.S +++ b/lib_xud/src/core/included/XUD_Token_Setup_DI.S @@ -22,11 +22,16 @@ XUD_SETUP_LoadBuffer: XUD_SETUP_ClearStall: // CRC OK // Have received a SETUP so clear any STALL condition on IN/OUT endpoint. - ldaw r11, dp[handshakeTable_OUT] // Note, we can speed this up by assuming SETUP only received on EP 0 - ldc r6, USB_PIDn_NAK - stw r6, r11[r10] - ldw r11, sp[STACK_HANDSHAKETABLEIN] - stw r1, r11[r10] + // Note, we can speed this up by assuming SETUP only received on EP 0 + ldaw r6, dp[ep_addr] + + ldaw r11, r10[4] // R11 = R10 + 16 + ldw r11, r6[r11] + stw r1, r11[10] // r1: 0 + + ldw r11, r6[r10] + ldc r6, USB_PIDn_NAK + stw r6, r11[10] XUD_SETUP_SendSetupAck: ldc r11, USB_PIDn_ACK diff --git a/lib_xud/src/user/client/XUD_EpFuncs.S b/lib_xud/src/user/client/XUD_EpFuncs.S index 5422500b..b8d7aa03 100644 --- a/lib_xud/src/user/client/XUD_EpFuncs.S +++ b/lib_xud/src/user/client/XUD_EpFuncs.S @@ -67,7 +67,7 @@ XUD_GetSetupData_ResetPid: // We must reset PID toggling on #endif stw r11, r0[4] // Reset OUT toggle - ldc r11, 640 // Assuming MAX_NUM_EPS is 16 and struct size is 40 here! + ldc r11, 768 // Assuming MAX_NUM_EPS is 16 and struct size is 44 here! add r11, r0, r11 ldc r10, USB_PIDn_DATA1 @@ -89,7 +89,7 @@ XUD_GetSetupData_GotOut: // Got an OUT instead not a SETU XUD_GetSetupData_CheckPid: ldw r11, r0[6] // Load received PID from EP structure - shr r11, r11, 24 // Shift down due to inpw + //shr r11, r11, 24 // Shift down due to inpw ldw r10, r0[4] // Load expected PID xor r11, r10, r11 // Do the comparison @@ -138,250 +138,6 @@ XUD_GetSetupData_Reset: .set XUD_GetSetupData.locnointerfaceaccess, 1 .set XUD_GetSetupData.locnonotificationselect, 1 -//int XUD_GetData(XUD_ep c, unsigned char buffer[], unsigned &length); -// r0 r1 r2 -.globl XUD_GetData -.type XUD_GetData, @function -.cc_top XUD_GetData.func -.align FUNCTION_ALIGNMENT -XUD_GetData: -#if defined(__XS2A__) || defined(__XS3A__) -.issue_mode single - ENTSP_lu6 4 -#else - entsp 4 -#endif - stw r10, sp[1] - mov r11, r1 - -XUD_GetData_: - ldw r10, r0[9] // Check if we missed a reset - bt r10, XUD_GetData_Reset - - stw r1, r0[3] // Store buffer address in EP structure - - ldw r10, r0[0] // Load mem address of EP in XUD ep table - stw r0, r10[0] - -XUD_GetData_Retry: - ldw r10, r0[2] // Load our chanend ID to use - // Wait for XUD response - testct r11, res[r10] // Test whether there is a RESET/SUSPEND exception - bt r11, XUD_GetData_Reset - -XUD_GetData_DataEnd: - in r3, res[r10] // Input packet "word" length - -XUD_GetData_SetupCheck: // Check if we have OUT or SETUP - testct r11, res[r10] - bt r11, XUD_GetData_GotSetup - int r11, res[r10] // r11 is tail length (bytes) - shr r11, r11, 3 - bu XUD_GetDataCalcDataLength - -XUD_GetDataCalcDataLength: - shl r3, r3, 2 // Num received words to bytes - add r3, r11, r3 // r11: Total bytes received (Note this includes 2 byte crc) - -XUD_GetData_CheckPid: - ldw r11, r0[6] // Load received PID from EP structure - shr r11, r11, 24 // Shift down due to inpw - ldw r10, r0[4] // Load expected PID - - xor r11, r10, r11 // Do the comparison - bt r11, XUD_GetData_ // Ignore packet... - -XUD_GetData_PidOkay: - ldw r11, r0[5] // Load EP type - bf r11, XUD_GetData_ReturnOk // Jump over PID toggle for ISO - -XUD_GetData_PidToggle: -#ifdef __XS3A__ - ldc r11, 0x88 -#else - ldc r11, 8 -#endif - xor r10, r10, r11 - stw r10, r0[4] - -XUD_GetData_ReturnOk: - sub r0, r3, 2 // Length correction for CRC correction - stw r0, r2[0] // Store in length (passed by ref) - - ldc r0, 0 // Return 0 for success - - ldw r10, sp[1] // TODO should check for <0 as ISO doesn't have CRC check - retsp 4 - -XUD_GetData_Reset: - mkmsk r0, 32 // Return -1 as length - -Return: - ldw r10, sp[1] - retsp 4 - -/////// -XUD_GetData_GotSetup: - inct r11, res[r10] // Expect r11: 0 - -//XUD_GetSetupData_CheckPid: - // We expect data0 else something gone wrong... - // TODO.. - -XUD_GetDataSetupData_ResetPid: // We must reset PID toggling on SETUP (both IN AND OUT) -#ifdef __XS3A__ - ldc r11, USB_PIDn_DATA1 -#else - ldc r11, USB_PID_DATA1 -#endif - stw r11, r0[4] // Reset OUT toggle - - ldc r11, 640 // Assuming MAX_NUM_EPS is 16 and struct size is 40 here! - add r11, r0, r11 - - ldc r10, USB_PIDn_DATA1 - stw r10, r11[4] // Reset IN toggle - - ldc r0, 8 // Return 8 byte length (TODO really could return actual length here) - stw r0, r2[0] - - ldc r0, 1 // Return got control XUD_RES_CTL - - ldw r10, sp[1] - retsp 4 - - - -.size XUD_GetData, .-XUD_GetData -.cc_bottom XUD_GetData.func -.globl XUD_GetData.nstackwords -.globl XUD_GetData.maxchanends -.globl XUD_GetData.maxtimers -.globl XUD_GetData.maxcores -.set XUD_GetData.nstackwords, 4 -.set XUD_GetData.maxchanends, 0 -.set XUD_GetData.maxtimers, 0 -.set XUD_GetData.maxcores, 1 -.globl XUD_GetData.locnoside -.globl XUD_GetData.locnochandec -.globl XUD_GetData.locnoglobalaccess -.globl XUD_GetData.locnointerfaceaccess -.globl XUD_GetData.locnonotificationselect -.set XUD_GetData.locnoside, 1 -.set XUD_GetData.locnochandec, 1 -.set XUD_GetData.locnoglobalaccess, 1 -.set XUD_GetData.locnointerfaceaccess, 1 -.set XUD_GetData.locnonotificationselect, 1 - - -// Note: Assumes startIndex is word aligned -// int XUD_SetData_indexed(XUD_ep e, unsigned buffer[], unsigned datasize, unsigned startIndex unsigned pid); -// r0 r1 r2 r3 -.globl XUD_SetData -.type XUD_SetData, @function -.cc_top XUD_SetData.func -.align FUNCTION_ALIGNMENT -XUD_SetData: -#if defined(__XS2A__) || defined(__XS3A__) -.issue_mode single - ENTSP_lu6 8 -#else - entsp 8 -#endif - stw r5, sp[5] - stw r10, sp[6] - -XUD_SetDataRetry: - stw r4, sp[0] - - ldw r11, r0[9] // Check if we missed a reset - bt r11, XUD_SetData_Reset - -XUD_SetData_NoReq: - add r1, r1, r3 // Add start index to buffer address - -CalcTailLength: - shl r3, r2, 3 // Tail length: bytes to bits - zext r3, 5 - -SetupLoopTerm: - shr r2, r2, 2 // r2: datalength (bytes) ---> r2: datalength (words) - - // TODO do this a bit more effciently.. - // If tail is 0 and word-length not 0. Make tail-length 32 and word-length-- - bt r3, AdjustBufferPointer - bf r2, AdjustBufferPointer - - sub r2, r2, 1 - ldc r3, 32 - -AdjustBufferPointer: - shl r5, r2, 2 // Get end off buffer address - add r1, r1, r5 - - -NegativeIndex: // Produce negtive offset from end of buffer - neg r2, r2 - stw r2, r0[6] // Store index - -XUD_SetData_DataRdy: - ldw r2, r0[0] // Load mem address of EP structure - stw r1, r0[3] // Store buffer address -StoreTailLength: - stw r3, r0[7] // Store tail length (bytes) - - stw r0, r2[0] // Mark ready with address of ep structure - - // Wait for XUD Response - ldw r10, r0[2] // Load our chanend ID to use - testct r11, res[r10] // Test for RESET/SUSPEND exception - bt r11, XUD_SetData_Reset - - in r11, res[r10] // Data sent okay - -XUD_SetData_LoadEpType: - ldw r11, r0[5] // Don't do any toggling for ISO - bf r11, XUD_SetData_DonePid - -XUD_SetData_PidToggle: // - ldw r11, r0[4] // Load EP PID from structure - ldc r4, 0x88 - xor r11, r11, r4 - stw r11, r0[4] // Store back PID - -XUD_SetData_DonePid: - ldc r0, 0 -XUD_SetData_Return: - ldw r4, sp[0] - ldw r5, sp[5] - ldw r10, sp[6] - retsp 8 - -XUD_SetData_Reset: - mkmsk r0, 32 // Return -1 - bu XUD_SetData_Return - -.size XUD_SetData, .-XUD_SetData -.cc_bottom XUD_SetData.func -.globl XUD_SetData.nstackwords -.globl XUD_SetData.maxchanends -.globl XUD_SetData.maxtimers -.globl XUD_SetData.maxcores -.set XUD_SetData.nstackwords, 8 -.set XUD_SetData.maxchanends, 0 -.set XUD_SetData.maxtimers, 0 -.set XUD_SetData.maxcores, 1 -.globl XUD_SetData.locnoside -.globl XUD_SetData.locnochandec -.globl XUD_SetData.locnoglobalaccess -.globl XUD_SetData.locnointerfaceaccess -.globl XUD_SetData.locnonotificationselect -.set XUD_SetData.locnoside, 1 -.set XUD_SetData.locnochandec, 1 -.set XUD_SetData.locnoglobalaccess, 1 -.set XUD_SetData.locnointerfaceaccess, 1 -.set XUD_SetData.locnonotificationselect, 1 - //void XUD_GetData_Select(chan c, XUD_ep ep, unsigned &datalength, XUD_Result_t &result); // r0, r1 r2 r3 .globl XUD_GetData_Select @@ -416,7 +172,7 @@ XUD_GetData_CheckDataLength: XUD_GetData_Select_CheckPid: // Check PID ldw r11, r1[6] // Load received PID from EP structure - shr r11, r11, 24 // Shift off junk + //shr r11, r11, 24 // Shift off junk // Note: We can't just jump back to XUD_GetData_Select since other EP's might need service @@ -531,117 +287,6 @@ XUD_SetData_Select_Reset: .set XUD_SetData_Select.locnonotificationselect, 1 -.globl XUD_SetStallByAddr -.type XUD_SetStallByAddr, @function - -/* R0: ep number */ -.cc_top XUD_SetStallByAddr.func -.align FUNCTION_ALIGNMENT -XUD_SetStallByAddr: -#if defined(__XS2A__) || defined(__XS3A__) -.issue_mode single - ENTSP_lu6 0 -#endif - ldc r2, USB_PIDn_STALL - ldc r11, 0x80 // Check for IN bit - and r11, r11, r0 - bf r11, XUD_SetStallByAddr_OUT - ldaw r1, dp[handshakeTable_IN] - mkmsk r11, 7 - and r11, r11, r0 - stw r2, r1[r11] - - retsp 0 -XUD_SetStallByAddr_OUT: - ldaw r1, dp[handshakeTable_OUT] - stw r2, r1[r0] - retsp 0 -.size XUD_SetStallByAddr, .-XUD_SetStallByAddr -.cc_bottom XUD_SetStallByAddr.func -.globl XUD_SetStallByAddr.nstackwords -.globl XUD_SetStallByAddr.maxchanends -.globl XUD_SetStallByAddr.maxtimers -.globl XUD_SetStallByAddr.maxcores -.set XUD_SetStallByAddr.nstackwords, 0 -.set XUD_SetStallByAddr.maxchanends, 0 -.set XUD_SetStallByAddr.maxtimers, 0 -.set XUD_SetStallByAddr.maxcores, 1 -.globl XUD_SetStallByAddr.locnoside -.globl XUD_SetStallByAddr.locnochandec -.globl XUD_SetStallByAddr.locnoglobalaccess -.globl XUD_SetStallByAddr.locnointerfaceaccess -.globl XUD_SetStallByAddr.locnonotificationselect -.set XUD_SetStallByAddr.locnoside, 1 -.set XUD_SetStallByAddr.locnochandec, 1 -.set XUD_SetStallByAddr.locnoglobalaccess, 1 -.set XUD_SetStallByAddr.locnointerfaceaccess, 1 -.set XUD_SetStallByAddr.locnonotificationselect, 1 - - -.globl XUD_ClearStallByAddr -.type XUD_ClearStallByAddr, @function - -/* R0: ep number */ -.cc_top XUD_ClearStallByAddr.func -.issue_mode single -.align FUNCTION_ALIGNMENT -XUD_ClearStallByAddr: - ENTSP_lu6 0 - ldc r2, USB_PIDn_NAK - ldc r11, 0x80 // Check for IN bit - and r11, r11, r0 - bf r11, XUD_ClearStallByAddr_OUT - ldaw r1, dp[handshakeTable_IN] // Reset Handshake - mkmsk r11, 7 - and r11, r11, r0 - ldc r2, 0 // Clear with 0 (differs to OUT) - stw r2, r1[r11] - // Calc offset for data pid - ldaw r0, r11[4] // Assume MAX_NUM_EP_OUT is 16 here! (r0 = r0 + 4 * 4) - ldc r1, USB_PIDn_DATA0 - bu XUD_ClearStallByAddr_ResetDataPid - -XUD_ClearStallByAddr_OUT: - ldc r2, USB_PIDn_NAK - ldaw r1, dp[handshakeTable_OUT] - stw r2, r1[r0] - -#ifdef __XS3A__ - ldc r1, USB_PIDn_DATA0 -#else - ldc r1, USB_PID_DATA0 -#endif - -XUD_ClearStallByAddr_ResetDataPid: // Reset DATA PID to DATA0 - ldc r2, 40 // Size of XUD_ep_info struct TODO use sizeof() - - mul r0, r0, r2 // Be careful with packing - ldw r2, cp[ep_info_address] - add r0, r2, r0 - stw r1, r0[4] - retsp 0 - - -.size XUD_ClearStallByAddr, .-XUD_ClearStallByAddr -.cc_bottom XUD_ClearStallByAddr.func -.globl XUD_ClearStallByAddr.nstackwords -.globl XUD_ClearStallByAddr.maxchanends -.globl XUD_ClearStallByAddr.maxtimers -.globl XUD_ClearStallByAddr.maxcores -.set XUD_ClearStallByAddr.nstackwords, 0 -.set XUD_ClearStallByAddr.maxchanends, 0 -.set XUD_ClearStallByAddr.maxtimers, 0 -.set XUD_ClearStallByAddr.maxcores, 1 -.globl XUD_ClearStallByAddr.locnoside -.globl XUD_ClearStallByAddr.locnochandec -.globl XUD_ClearStallByAddr.locnoglobalaccess -.globl XUD_ClearStallByAddr.locnointerfaceaccess -.globl XUD_ClearStallByAddr.locnonotificationselect -.set XUD_ClearStallByAddr.locnoside, 1 -.set XUD_ClearStallByAddr.locnochandec, 1 -.set XUD_ClearStallByAddr.locnoglobalaccess, 1 -.set XUD_ClearStallByAddr.locnointerfaceaccess, 1 -.set XUD_ClearStallByAddr.locnonotificationselect, 1 - .globl XUD_ResetEpStateByAddr .type XUD_ResetEpStateByAddr, @function @@ -649,27 +294,25 @@ XUD_ClearStallByAddr_ResetDataPid: // Reset DATA PID to DATA0 .cc_top XUD_ResetEpStateByAddr.func .align FUNCTION_ALIGNMENT XUD_ResetEpStateByAddr: -#if defined(__XS2A__) || defined(__XS3A__) .issue_mode single - ENTSP_lu6 0 -#endif + ENTSP_lu6 0 ldc r1, 0x80 and r2, r0, r1 bf r2, XUD_ResetEpStateByAddr_OUT ldc r1, USB_PIDn_DATA0 bu XUD_ResetEpStateByAddr_ XUD_ResetEpStateByAddr_OUT: -#if defined(__XS3A__) - ldc r1, USB_PIDn_DATA0 -#else +#if defined(__XS2A__) ldc r1, USB_PID_DATA0 +#else + ldc r1, USB_PIDn_DATA0 #endif XUD_ResetEpStateByAddr_: zext r0, 7 // Check for IN bit set bf r2, NoOffset ldaw r0, r0[4] // Assume MAX_NUM_EP_OUT is 16 here! (r0 = r0 + 4 * 4) NoOffset: - ldc r2, 40 // Size of XUD_ep_info struct TODO. FIXME! + ldc r2, 48 // Size of XUD_ep_info struct TODO. FIXME! mul r0, r0, r2 ldw r2, cp[ep_info_address] add r0, r2, r0 diff --git a/lib_xud/src/user/client/XUD_EpFunctions.c b/lib_xud/src/user/client/XUD_EpFunctions.c new file mode 100644 index 00000000..82fcc325 --- /dev/null +++ b/lib_xud/src/user/client/XUD_EpFunctions.c @@ -0,0 +1,242 @@ +// Copyright 2021 XMOS LIMITED. +// This Software is subject to the terms of the XMOS Public Licence: Version 1. + +#include "xud.h" +#include "XUD_USB_Defines.h" + +extern XUD_ep_info ep_info[USB_MAX_NUM_EP]; + +void XUD_SetStallByAddr(int epNum) +{ + if(epNum & 0x80) + { + epNum &= 0x7f; + epNum += 16; + } + + XUD_ep_info *ep = &ep_info[epNum]; + + unsigned *epReadyEntry = (unsigned *)ep->array_ptr; + + if(*epReadyEntry != 0) + { + /* Mark EP as not ready (and save that it was ready at Halting */ + ep->saved_array_ptr = *epReadyEntry; + *epReadyEntry = 0; + } + ep->halted = USB_PIDn_STALL; +} + +void XUD_ClearStallByAddr(int epNum) +{ + unsigned handshake = USB_PIDn_NAK; + + /* Reset data PID */ + XUD_ResetEpStateByAddr(epNum); + + if(epNum & 0x80) + { + epNum &= 0x7f; + epNum += 16; + handshake = 0; + } + + XUD_ep_info *ep = &ep_info[epNum]; + + /* Re-mark as ready if was ready before halting */ + if(ep->saved_array_ptr != 0) + { + unsigned *epReadyEntry = (unsigned *)ep->array_ptr; + *epReadyEntry = ep->saved_array_ptr; + ep->saved_array_ptr = 0; + } + + /* Mark EP as un-halted */ + ep->halted = handshake; +} + + +XUD_Result_t XUD_SetBuffer(XUD_ep e, unsigned char buffer[], unsigned datalength) +{ + volatile XUD_ep_info * ep = (XUD_ep_info*) e; + unsigned isReset; + unsigned tmp; + + while(1) + { + /* Check if we missed a reset */ + if(ep->resetting) + { + return XUD_RES_RST; + } + + /* If EP is marked as halted do not mark as ready.. */ + if(ep->halted == USB_PIDn_STALL) + { + continue; + } + + int lengthWords = datalength >> 2; + unsigned lengthTail = (datalength << 3) & 0x1f; // zext(5)? + + if((lengthTail == 0) && (lengthWords != 0)) + { + lengthWords -= 1; + lengthTail = 32; + } + + /* Store end of buffer address in EP structure */ + ep->buffer = (unsigned) &buffer[0] + (lengthWords * 4); + + /* XUD uses negative index */ + lengthWords *= -1; + ep->actualPid = lengthWords; /* Re-used of actualPid entry - TODO rename */ + ep->tailLength = lengthTail; + + unsigned * array_ptr = (unsigned *)ep->array_ptr; + *array_ptr = (unsigned) ep; + + /* Wait for XUD response */ + asm volatile("testct %0, res[%1]" : "=r"(isReset) : "r"(ep->client_chanend)); + + if(isReset) + { + return XUD_RES_RST; + } + + /* Data sent okay */ + asm volatile("in %0, res[%1]" : "=r"(tmp) : "r"(ep->client_chanend)); + + /* Don't do any PID toggling for Iso EP's */ + if(ep->epType != XUD_EPTYPE_ISO) + { + ep->pid ^= 0x88; + } + + return XUD_RES_OKAY; + } +} + +XUD_Result_t XUD_GetBuffer(XUD_ep e, unsigned char buffer[], unsigned *datalength) +{ + + volatile XUD_ep_info * ep = (XUD_ep_info*) e; + unsigned isReset; + unsigned length; + unsigned lengthTail; + + while(1) + { + /* Check if we missed a reset */ + if(ep->resetting) + { + return XUD_RES_RST; + } + + /* If EP is marked as halted do not mark as ready.. */ + if(ep->halted == USB_PIDn_STALL) + { + continue; + } + + /* Store buffer address in EP structure */ + ep->buffer = (unsigned) &buffer[0]; + + unsigned * array_ptr = (unsigned *)ep->array_ptr; + *array_ptr = (unsigned) ep; + + /* Wait for XUD response */ + asm volatile("testct %0, res[%1]" : "=r"(isReset) : "r"(ep->client_chanend)); + + if(isReset) + { + return XUD_RES_RST; + } + + /* Input packet length (words) */ + asm volatile("in %0, res[%1]" : "=r"(length) : "r"(ep->client_chanend)); + + /* Input tail length (bytes) */ + asm volatile("int %0, res[%1]" : "=r"(lengthTail) : "r"(ep->client_chanend)); + + /* Bits to bytes */ + lengthTail >>= 3; + + /* Words to bytes */ + length <<= 2; + + /* -2 length correction for CRC */ + *datalength = length + lengthTail - 2; + + /* Load received PID */ + unsigned receivedPid = ep->actualPid; + + /* Check received PID vs expected PID */ + if(receivedPid != ep->pid) + { + continue; + } + + // ISO = 0 + if(ep->epType != XUD_EPTYPE_ISO) + { +#ifdef __XS2A__ + ep->pid ^= 0x8; +#else + ep->pid ^= 0x88; +#endif + } + + return XUD_RES_OKAY; + } +} + +XUD_Result_t XUD_SetBuffer_EpMax(XUD_ep ep_in, unsigned char buffer[], unsigned datalength, unsigned epMax) +{ + int i = 0; + XUD_Result_t result; + + /* Note: We could encompass this in the SetData function */ + if (datalength <= epMax) + { + /* Datalength is less than the maximum per transaction of the EP, so just send */ + result = XUD_SetBuffer(ep_in, buffer, datalength); + return result; + } + else + { + /* Send first packet out and reset PID */ + if((result = XUD_SetBuffer(ep_in, buffer, epMax)) != XUD_RES_OKAY) + { + return result; + } + + i += epMax; + datalength -= epMax; + + while (1) + { + unsigned char *bufferPtr = &buffer[i]; + + if (datalength > epMax) + { + /* PID Automatically toggled */ + if ((result = XUD_SetBuffer(ep_in, bufferPtr, epMax)) != XUD_RES_OKAY) + return result; + + datalength -= epMax; + i += epMax; + } + else + { + /* PID automatically toggled */ + if ((result = XUD_SetBuffer(ep_in, bufferPtr, datalength)) != XUD_RES_OKAY) + return result; + + break; //out of while loop + } + } + } + + return XUD_RES_OKAY; +} diff --git a/lib_xud/src/user/client/XUD_EpFunctions.xc b/lib_xud/src/user/client/XUD_EpFunctions.xc index 051f21fd..e82b70dd 100644 --- a/lib_xud/src/user/client/XUD_EpFunctions.xc +++ b/lib_xud/src/user/client/XUD_EpFunctions.xc @@ -7,7 +7,7 @@ #include #include "xud.h" - +#include "XUD_USB_Defines.h" static inline int min(int x, int y) { @@ -16,74 +16,20 @@ static inline int min(int x, int y) return y; } -XUD_Result_t XUD_GetBuffer(XUD_ep c, unsigned char buffer[], unsigned &datalength) -{ - return XUD_GetData(c, buffer, datalength); -} - // To be deprecated - In favour of XUD_GetControlBuffer() XUD_Result_t XUD_GetSetupBuffer(XUD_ep ep_out, unsigned char buffer[], unsigned &length) { return XUD_GetSetupData(ep_out, buffer, length); } -XUD_Result_t XUD_SetBuffer(XUD_ep c, unsigned char buffer[], unsigned datalength) -{ - /* No PID reset, 0 start index */ - return XUD_SetData(c, buffer, datalength, 0, 0); -} - void XUD_Kill(XUD_ep ep) { XUD_SetTestMode(ep, 0); } -XUD_Result_t XUD_SetBuffer_EpMax(XUD_ep ep_in, unsigned char buffer[], unsigned datalength, unsigned epMax) -{ - int i = 0; - XUD_Result_t result; - - /* Note: We could encompass this in the SetData function */ - if (datalength <= epMax) - { - /* Datalength is less than the maximum per transaction of the EP, so just send */ - result = XUD_SetData(ep_in, buffer, datalength, 0, 0); - return result; - } - else - { - /* Send first packet out and reset PID */ - if((result = XUD_SetData(ep_in, buffer, epMax, 0, 0)) != XUD_RES_OKAY) - { - return result; - } - i+= epMax; - datalength-=epMax; - - while (1) - { - if (datalength > epMax) - { - /* PID Automatically toggled */ - if ((result = XUD_SetData(ep_in, buffer, epMax, i, 0)) != XUD_RES_OKAY) - return result; - - datalength-=epMax; - i += epMax; - } - else - { - /* PID automatically toggled */ - if ((result = XUD_SetData(ep_in, buffer, datalength, i, 0)) != XUD_RES_OKAY) - return result; - - break; //out of while loop - } - } - } - - return XUD_RES_OKAY; -} +#ifndef EP0_MAX_PACKET_SIZE +#define EP0_MAX_PACKET_SIZE 64 +#endif /* TODO Should take ep max length as a param - currently hardcoded as 64 (#11384) */ XUD_Result_t XUD_DoGetRequest(XUD_ep ep_out, XUD_ep ep_in, unsigned char buffer[], unsigned length, unsigned requested) @@ -93,20 +39,20 @@ XUD_Result_t XUD_DoGetRequest(XUD_ep ep_out, XUD_ep ep_in, unsigned char buffer[ unsigned sendLength = min(length, requested); XUD_Result_t result; - if ((result = XUD_SetBuffer_EpMax(ep_in, buffer, sendLength, 64)) != XUD_RES_OKAY) + if ((result = XUD_SetBuffer_EpMax(ep_in, buffer, sendLength, EP0_MAX_PACKET_SIZE)) != XUD_RES_OKAY) { return result; } /* USB 2.0 8.5.3.2: Send < 0 length packet when data-length % 64 is 0 * Note, we also don't want to try and send 2 zero-length packets i.e. if sendLength = 0 */ - if ((requested > length) && ((length % 64) == 0)) + if ((requested > length) && ((length % EP0_MAX_PACKET_SIZE) == 0)) { XUD_SetBuffer(ep_in, tmpBuffer, 0); } /* Status stage - this should return -1 for reset or 0 for 0 length status stage packet */ - return XUD_GetData(ep_out, tmpBuffer, rxlength); + return XUD_GetBuffer(ep_out, tmpBuffer, rxlength); } XUD_Result_t XUD_DoSetRequestStatus(XUD_ep ep_in) @@ -114,27 +60,39 @@ XUD_Result_t XUD_DoSetRequestStatus(XUD_ep ep_in) unsigned char tmp[8]; /* Send 0 length packet */ - return XUD_SetData(ep_in, tmp, 0, 0, 0); + return XUD_SetBuffer(ep_in, tmp, 0); } void XUD_SetStall(XUD_ep ep) { - /* Get EP address from XUD_ep structure */ - unsigned int epAddress; + asm volatile ("stw %0, %1[10]"::"r"(USB_PIDn_STALL), "r"(ep)); +} - asm ("ldw %0, %1[8]":"=r"(epAddress):"r"(ep)); +extern XUD_ep_info ep_info[USB_MAX_NUM_EP]; - XUD_SetStallByAddr(epAddress); +unsafe +{ + XUD_ep_info * unsafe ep_info_ = ep_info; } void XUD_ClearStall(XUD_ep ep) { - /* Get EP address from XUD_ep structure */ - unsigned int epAddress; + // Load EP addr and check for IN or OUT + unsigned epAddr; - asm ("ldw %0, %1[8]":"=r"(epAddress):"r"(ep)); - - XUD_ClearStallByAddr(epAddress); + asm volatile("ldw %0, %1[8]":"=r"(epAddr):"r"(ep)); + + if(epAddr & 0x80) + { + asm volatile ("stw %0, %1[10]"::"r"(0), "r"(ep)); + } + else + { + asm volatile ("stw %0, %1[10]"::"r"(USB_PIDn_NAK), "r"(ep)); + } + + /* Reset data PID */ + XUD_ResetEpStateByAddr(epAddr); } void XUD_CloseEndpoint(XUD_ep one) diff --git a/tests/conftest.py b/tests/conftest.py index 29b196a8..1394fb27 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -15,17 +15,21 @@ from xcoverage.xcov import xcov_process, xcov_combine, combine_process # Note, no current support for XS2 so don't copy XS2 xn files -XN_FILES = ["test_xs3_600.xn", "test_xs3_800.xn", "test_xs3_540.xn", "test_xs3_500.xn"] +XN_FILES = [ + "test_xs3_600.xn", + "test_xs3_800.xn", +] combine_test = combine_process(os.path.dirname(os.path.abspath(__file__))) xcov_comb = xcov_combine() +# Note, HS tests will be skipped unless 85MIPS are available to lib_xud PARAMS = { "extended": { "arch": ["xs3"], "ep": [1, 2, 4], "address": [0, 1, 127], "bus_speed": ["HS", "FS"], - "dummy_threads": [0, 5, 6], + "dummy_threads": [0, 3, 5], # Note, plus 2 for test cores "core_freq": [600, 800], }, "default": { @@ -33,15 +37,15 @@ "ep": [1, 2], "address": [0, 1], "bus_speed": ["HS", "FS"], - "dummy_threads": [0, 6], + "dummy_threads": [0, 5], # Note, plus 2 for test cores "core_freq": [600], }, "smoke": { "arch": ["xs3"], "ep": [1], "address": [1], - "bus_speed": ["HS"], - "dummy_threads": [6], + "bus_speed": ["HS", "FS"], + "dummy_threads": [5], # Note, plus 2 for test cores "core_freq": [600], }, } @@ -139,11 +143,17 @@ def test_RunUsbSession( capfd, ): + xcov = eval(os.getenv("xcov")) + + total_threads = dummy_threads + 2 # 1 thread for xud another for test code + if (core_freq / total_threads < 85.0) and bus_speed == "HS": + pytest.skip("HS requires 85 MIPS") + tester_list = [] output = [] # TODO it would be good to sanity check core_freq == xe.freq - (clk_60, usb_phy) = get_usb_clk_phy(core_freq, verbose=False, arch=arch) + (clk_60, usb_phy) = get_usb_clk_phy(verbose=False, arch=arch) tester_list.extend( do_usb_test( arch, @@ -269,10 +279,10 @@ def xcoverage_combination(tmp_path_factory, worker_id, request): fn = root_tmp_dir / "data.json" - def follow(nfile,n): + def follow(nfile, n): nf = open(nfile, "r") lines = len(nf.readlines()) - while (lines != n): + while lines != n: nf.close() nf = open(nfile, "r") lines = len(nf.readlines()) @@ -281,7 +291,7 @@ def follow(nfile,n): def run_at_end(): wkc = os.getenv("PYTEST_XDIST_WORKER_COUNT") if wkc: - follow(fn,int(wkc)) + follow(fn, int(wkc)) coverage = combine_test.do_combine_test(test_dirs) combine_test.generate_merge_src() # teardowm - remove tmp file @@ -289,7 +299,7 @@ def run_at_end(): def status(): f = open(fn, "a") - f.write(str(worker_id+"\n")) + f.write(str(worker_id + "\n")) if worker_id == "master": request.addfinalizer(run_at_end) @@ -299,5 +309,5 @@ def status(): if fn.is_file(): request.addfinalizer(status) else: - fn.write_text(str(worker_id)+"\n") + fn.write_text(str(worker_id) + "\n") request.addfinalizer(run_at_end) diff --git a/tests/helpers.py b/tests/helpers.py index 1b18c9e8..43ac65c5 100644 --- a/tests/helpers.py +++ b/tests/helpers.py @@ -10,8 +10,6 @@ import Pyxsim import subprocess -ARCHITECTURE_CHOICES = ["xs2", "xs3"] -BUSSPEED_CHOICES = ["FS", "HS"] args = {"arch": "xs3"} @@ -22,16 +20,15 @@ def create_if_needed(folder): def get_usb_clk_phy( - coreFreqMhz, verbose=True, do_timeout=True, complete_fn=None, - dut_exit_time=350000, + dut_exit_time=350000 * 1000 * 1000, # in fs arch="xs2", ): if arch == "xs2": - clk = Clock("XS1_USB_CLK", Clock.CLK_60MHz, coreFreqMhz) + clk = Clock("XS1_USB_CLK", Clock.CLK_60MHz) phy = UsbPhyUtmi( "XS1_USB_RXD", "XS1_USB_RXA", # rxa @@ -51,7 +48,7 @@ def get_usb_clk_phy( ) elif arch == "xs3": - clk = Clock("XS1_USB_CLK", Clock.CLK_60MHz, coreFreqMhz) + clk = Clock("XS1_USB_CLK", Clock.CLK_60MHz) phy = UsbPhyUtmi( "XS1_USB_RXD", "XS1_USB_RXA", # rxa @@ -132,6 +129,8 @@ def do_usb_test( ): build_options = [] + xcov = eval(os.getenv("xcov")) + # Flags for makefile for k, v in FIXTURE_TO_DEFINE.items(): build_options += [str(v) + "=" + str(locals()[k])] diff --git a/tests/shared_src/shared.h b/tests/shared_src/shared.h index eda08a01..cd2cdc39 100644 --- a/tests/shared_src/shared.h +++ b/tests/shared_src/shared.h @@ -84,17 +84,22 @@ typedef enum t_runMode RUNMODE_DIE } t_runMode; - #pragma unsafe arrays -XUD_Result_t SendTxPacket(XUD_ep ep, int length, int epNum) +void GenTxPacketBuffer(unsigned char buffer[], int length, int epNum) { - unsigned char buffer[1024]; - - for (int i = 0; i < length; i++) unsafe { buffer[i] = g_txDataCheck[epNum]++; } + return; +} + +#pragma unsafe arrays +XUD_Result_t SendTxPacket(XUD_ep ep, int length, int epNum) +{ + unsigned char buffer[1024]; + + GenTxPacketBuffer(buffer, length, epNum); return XUD_SetBuffer(ep, buffer, length); } diff --git a/tests/shared_src/test_control_basic_get.xc b/tests/shared_src/test_control_basic_get.xc new file mode 100644 index 00000000..1ce1e297 --- /dev/null +++ b/tests/shared_src/test_control_basic_get.xc @@ -0,0 +1,70 @@ +// Copyright 2016-2021 XMOS LIMITED. +// This Software is subject to the terms of the XMOS Public Licence: Version 1. + +/* Endpoint type tables */ +XUD_EpType epTypeTableOut[EP_COUNT_OUT] = {XUD_EPTYPE_CTL, + XUD_EPTYPE_BUL, + XUD_EPTYPE_BUL, + XUD_EPTYPE_BUL, + XUD_EPTYPE_BUL}; +XUD_EpType epTypeTableIn[EP_COUNT_IN] = {XUD_EPTYPE_CTL, XUD_EPTYPE_BUL, XUD_EPTYPE_BUL, XUD_EPTYPE_BUL, XUD_EPTYPE_BUL}; + + +int TestEp_Control(XUD_ep ep0_out, XUD_ep ep0_in, int epNum) +{ + unsigned int slength; + unsigned int length; + XUD_Result_t sres; + XUD_Result_t res; + + /* Buffer for Setup data */ + unsigned char sbuffer[120]; + unsigned char buffer[120]; + + for(int i = PKT_LENGTH_START; i <= PKT_LENGTH_END; i++) + { + unsafe + { + GenTxPacketBuffer(buffer, i, epNum); + + /* Wait for Setup data */ + sres = XUD_GetSetupBuffer(ep0_out, sbuffer, slength); + + res = XUD_DoGetRequest(ep0_out, ep0_in, buffer, i, i); + + /* Do some checking */ + if(slength != 8) + { + return FAIL_RX_DATAERROR; + } + + if(res != XUD_RES_OKAY) + { + return FAIL_RX_BAD_RETURN_CODE; + } + + if(sres != XUD_RES_OKAY) + { + return FAIL_RX_BAD_RETURN_CODE; + } + + if(RxDataCheck(sbuffer, slength, epNum, 8)) + { + return FAIL_RX_DATAERROR; + } + + } + } + return 0; +} + +unsigned test_func(chanend c_ep_out[EP_COUNT_OUT], chanend c_ep_in[EP_COUNT_IN]) +{ + XUD_ep c_ep0_out = XUD_InitEp(c_ep_out[0]); + XUD_ep c_ep0_in = XUD_InitEp(c_ep_in[0]); + + unsigned failed = TestEp_Control(c_ep0_out, c_ep0_in, 0); + + XUD_Kill(c_ep0_out); + return failed; +} diff --git a/tests/shared_src/test_xs3_700.xn b/tests/shared_src/test_xs3_700.xn new file mode 100644 index 00000000..afd525af --- /dev/null +++ b/tests/shared_src/test_xs3_700.xn @@ -0,0 +1,24 @@ + + + + tileref tile[2] + + + + + + + + + + + + + + + + + + diff --git a/tests/test_bulk_loopback.py b/tests/test_bulk_loopback.py index 49d60fef..c0cddb5f 100644 --- a/tests/test_bulk_loopback.py +++ b/tests/test_bulk_loopback.py @@ -35,7 +35,7 @@ def test_session(ep, address, bus_speed): deviceAddress=address, endpointNumber=ep_loopback, endpointType="BULK", - direction="OUT", + transType="OUT", dataLength=pktLength, ) ) @@ -45,7 +45,7 @@ def test_session(ep, address, bus_speed): deviceAddress=address, endpointNumber=ep_loopback, endpointType="BULK", - direction="IN", + transType="IN", dataLength=pktLength, ) ) @@ -59,7 +59,7 @@ def test_session(ep, address, bus_speed): deviceAddress=address, endpointNumber=ep_loopback_kill, endpointType="BULK", - direction="OUT", + transType="OUT", dataLength=pktLength, ) ) @@ -69,7 +69,7 @@ def test_session(ep, address, bus_speed): deviceAddress=address, endpointNumber=ep_loopback_kill, endpointType="BULK", - direction="IN", + transType="IN", dataLength=pktLength, ) ) diff --git a/tests/test_bulk_notready.py b/tests/test_bulk_notready.py index f95d8ee8..668360ae 100644 --- a/tests/test_bulk_notready.py +++ b/tests/test_bulk_notready.py @@ -10,9 +10,6 @@ @pytest.fixture def test_session(ep, address, bus_speed): - if bus_speed == "FS": - pytest.xfail("Known fail when bus_speed = FS") - pktLength = 10 ied = 500 @@ -26,7 +23,7 @@ def test_session(ep, address, bus_speed): deviceAddress=address, endpointNumber=ep, endpointType="BULK", - direction="OUT", + transType="OUT", dataLength=pktLength, ) ) diff --git a/tests/test_bulk_rx_basic.py b/tests/test_bulk_rx_basic.py index 6a783410..431dbdeb 100644 --- a/tests/test_bulk_rx_basic.py +++ b/tests/test_bulk_rx_basic.py @@ -24,7 +24,7 @@ def test_session(ep, address, bus_speed): deviceAddress=address, endpointNumber=ep, endpointType="BULK", - direction="OUT", + transType="OUT", dataLength=pktLength, ) ) diff --git a/tests/test_bulk_rx_basic_badcrc32.py b/tests/test_bulk_rx_basic_badcrc32.py index 940c51d8..bde1b80f 100644 --- a/tests/test_bulk_rx_basic_badcrc32.py +++ b/tests/test_bulk_rx_basic_badcrc32.py @@ -24,7 +24,7 @@ def test_session(ep, address, bus_speed): deviceAddress=address, endpointNumber=ep, endpointType="BULK", - direction="OUT", + transType="OUT", dataLength=10, ) ) @@ -36,7 +36,7 @@ def test_session(ep, address, bus_speed): deviceAddress=address, endpointNumber=ep, endpointType="BULK", - direction="OUT", + transType="OUT", dataLength=11, interEventDelay=6000, ) @@ -49,7 +49,7 @@ def test_session(ep, address, bus_speed): deviceAddress=address, endpointNumber=ep, endpointType="BULK", - direction="OUT", + transType="OUT", dataLength=12, interEventDelay=6000, badDataCrc=True, @@ -64,7 +64,7 @@ def test_session(ep, address, bus_speed): deviceAddress=address, endpointNumber=ep, endpointType="BULK", - direction="OUT", + transType="OUT", dataLength=12, interEventDelay=6000, ) @@ -77,7 +77,7 @@ def test_session(ep, address, bus_speed): deviceAddress=address, endpointNumber=ep, endpointType="BULK", - direction="OUT", + transType="OUT", dataLength=13, interEventDelay=6000, ) @@ -89,7 +89,7 @@ def test_session(ep, address, bus_speed): deviceAddress=address, endpointNumber=ep, endpointType="BULK", - direction="OUT", + transType="OUT", dataLength=14, interEventDelay=6000, ) diff --git a/tests/test_bulk_rx_basic_badpid.py b/tests/test_bulk_rx_basic_badpidseq.py similarity index 93% rename from tests/test_bulk_rx_basic_badpid.py rename to tests/test_bulk_rx_basic_badpidseq.py index 833a72e4..5500646a 100644 --- a/tests/test_bulk_rx_basic_badpid.py +++ b/tests/test_bulk_rx_basic_badpidseq.py @@ -24,7 +24,7 @@ def test_session(ep, address, bus_speed): deviceAddress=address, endpointNumber=ep, endpointType="BULK", - direction="OUT", + transType="OUT", dataLength=10, interEventDelay=interEventDelay, ) @@ -38,7 +38,7 @@ def test_session(ep, address, bus_speed): deviceAddress=address, endpointNumber=ep, endpointType="BULK", - direction="OUT", + transType="OUT", dataLength=11, interEventDelay=interEventDelay, resend=True, @@ -52,7 +52,7 @@ def test_session(ep, address, bus_speed): deviceAddress=address, endpointNumber=ep, endpointType="BULK", - direction="OUT", + transType="OUT", dataLength=12, interEventDelay=interEventDelay, ) @@ -63,7 +63,7 @@ def test_session(ep, address, bus_speed): deviceAddress=address, endpointNumber=ep, endpointType="BULK", - direction="OUT", + transType="OUT", dataLength=13, interEventDelay=interEventDelay, ) @@ -74,7 +74,7 @@ def test_session(ep, address, bus_speed): deviceAddress=address, endpointNumber=ep, endpointType="BULK", - direction="OUT", + transType="OUT", dataLength=14, interEventDelay=interEventDelay, ) diff --git a/tests/test_bulk_rx_basic_badpid/Makefile b/tests/test_bulk_rx_basic_badpidseq/Makefile similarity index 100% rename from tests/test_bulk_rx_basic_badpid/Makefile rename to tests/test_bulk_rx_basic_badpidseq/Makefile diff --git a/tests/test_bulk_rx_basic_badpid/src/main.xc b/tests/test_bulk_rx_basic_badpidseq/src/main.xc similarity index 100% rename from tests/test_bulk_rx_basic_badpid/src/main.xc rename to tests/test_bulk_rx_basic_badpidseq/src/main.xc diff --git a/tests/test_bulk_rx_basic_invalidpid.py b/tests/test_bulk_rx_basic_invalidpid.py new file mode 100644 index 00000000..bcf758a2 --- /dev/null +++ b/tests/test_bulk_rx_basic_invalidpid.py @@ -0,0 +1,90 @@ +# Copyright 2016-2021 XMOS LIMITED. +# This Software is subject to the terms of the XMOS Public Licence: Version 1. +import pytest + +from conftest import PARAMS, test_RunUsbSession # noqa F401 +from usb_session import UsbSession +from usb_transaction import UsbTransaction +from usb_packet import ( + TokenPacket, + TxDataPacket, + USB_PID, +) + + +@pytest.fixture +def test_session(ep, address, bus_speed): + + session = UsbSession( + bus_speed=bus_speed, run_enumeration=False, device_address=address + ) + + # The large inter-frame gap is to give the DUT time to print its output + interEventDelay = 500 + + # Valid OUT transaction + session.add_event( + UsbTransaction( + session, + deviceAddress=address, + endpointNumber=ep, + endpointType="BULK", + transType="OUT", + dataLength=10, + interEventDelay=interEventDelay, + ) + ) + + # OUT Transaction with invalid DATA PID. XCORE should ignore packet - no ACK + session.add_event( + TokenPacket( + pid=USB_PID["OUT"], + address=address, + endpoint=ep, + interEventDelay=interEventDelay, + ) + ) + + session.add_event( + TxDataPacket( + dataPayload=session.getPayload_out(ep, 11, resend=True), + pid=USB_PID["DATA1"] & 0xF, + ) + ) + + # Send some valid OUT transactions + session.add_event( + UsbTransaction( + session, + deviceAddress=address, + endpointNumber=ep, + endpointType="BULK", + transType="OUT", + dataLength=11, + interEventDelay=interEventDelay, + ) + ) + session.add_event( + UsbTransaction( + session, + deviceAddress=address, + endpointNumber=ep, + endpointType="BULK", + transType="OUT", + dataLength=12, + interEventDelay=interEventDelay, + ) + ) + session.add_event( + UsbTransaction( + session, + deviceAddress=address, + endpointNumber=ep, + endpointType="BULK", + transType="OUT", + dataLength=13, + interEventDelay=interEventDelay, + ) + ) + + return session diff --git a/tests/test_stall_epready/Makefile b/tests/test_bulk_rx_basic_invalidpid/Makefile similarity index 100% rename from tests/test_stall_epready/Makefile rename to tests/test_bulk_rx_basic_invalidpid/Makefile diff --git a/tests/test_bulk_rx_basic_invalidpid/src/main.xc b/tests/test_bulk_rx_basic_invalidpid/src/main.xc new file mode 100644 index 00000000..731d385c --- /dev/null +++ b/tests/test_bulk_rx_basic_invalidpid/src/main.xc @@ -0,0 +1,29 @@ +// Copyright 2016-2021 XMOS LIMITED. +// This Software is subject to the terms of the XMOS Public Licence: Version 1. +#include "shared.h" + +#define EP_COUNT_OUT (6) +#define EP_COUNT_IN (6) + +#ifndef PKT_LENGTH_START +#define PKT_LENGTH_START (10) +#endif + +#ifndef PKT_LENGTH_END +#define PKT_LENGTH_END (13) +#endif + +#include "shared.h" + +XUD_EpType epTypeTableOut[EP_COUNT_OUT] = {XUD_EPTYPE_CTL, XUD_EPTYPE_BUL, XUD_EPTYPE_BUL, XUD_EPTYPE_BUL, XUD_EPTYPE_BUL, XUD_EPTYPE_BUL}; +XUD_EpType epTypeTableIn[EP_COUNT_IN] = {XUD_EPTYPE_CTL, XUD_EPTYPE_BUL, XUD_EPTYPE_BUL, XUD_EPTYPE_BUL, XUD_EPTYPE_BUL, XUD_EPTYPE_BUL}; + +unsigned test_func(chanend c_ep_out[EP_COUNT_OUT], chanend c_ep_in[EP_COUNT_IN]) +{ + unsigned fail = TestEp_Rx(c_ep_out[TEST_EP_NUM], TEST_EP_NUM, PKT_LENGTH_START, PKT_LENGTH_END); + + return fail; +} + +#include "test_main.xc" + diff --git a/tests/test_bulk_rx_basic_nodata.py b/tests/test_bulk_rx_basic_nodata.py index d92c670a..eb5275ba 100644 --- a/tests/test_bulk_rx_basic_nodata.py +++ b/tests/test_bulk_rx_basic_nodata.py @@ -11,7 +11,11 @@ @pytest.fixture -def test_session(ep, address, bus_speed): +def test_session(ep, address, bus_speed, core_freq, dummy_threads): + + total_threads = dummy_threads + 2 # 1 thread for xud another for test code + if (core_freq / total_threads < 100.0) and bus_speed == "HS": + pytest.xfail("Test doesn't pass without 100MIPS (issue #277)") # The large inter-event delay is to give the DUT time to perform checking ied = 500 @@ -28,7 +32,7 @@ def test_session(ep, address, bus_speed): deviceAddress=address, endpointNumber=ep, endpointType="BULK", - direction="OUT", + transType="OUT", dataLength=length, interEventDelay=ied, ) diff --git a/tests/test_bulk_rx_basic_rxerror.py b/tests/test_bulk_rx_basic_rxerror.py index 7e27cdaa..97167cb2 100644 --- a/tests/test_bulk_rx_basic_rxerror.py +++ b/tests/test_bulk_rx_basic_rxerror.py @@ -24,7 +24,7 @@ def test_session(ep, address, bus_speed): deviceAddress=address, endpointNumber=ep, endpointType="BULK", - direction="OUT", + transType="OUT", dataLength=10, ) ) @@ -37,7 +37,7 @@ def test_session(ep, address, bus_speed): deviceAddress=address, endpointNumber=ep, endpointType="BULK", - direction="OUT", + transType="OUT", dataLength=11, interEventDelay=ied, rxeAssertDelay_data=5, @@ -51,7 +51,7 @@ def test_session(ep, address, bus_speed): deviceAddress=address, endpointNumber=ep, endpointType="BULK", - direction="OUT", + transType="OUT", dataLength=11, interEventDelay=ied, ) @@ -64,7 +64,7 @@ def test_session(ep, address, bus_speed): deviceAddress=address, endpointNumber=ep, endpointType="BULK", - direction="OUT", + transType="OUT", dataLength=12, interEventDelay=ied, ) @@ -76,7 +76,7 @@ def test_session(ep, address, bus_speed): deviceAddress=address, endpointNumber=ep, endpointType="BULK", - direction="OUT", + transType="OUT", dataLength=13, interEventDelay=ied, rxeAssertDelay_data=1, @@ -90,7 +90,7 @@ def test_session(ep, address, bus_speed): deviceAddress=address, endpointNumber=ep, endpointType="BULK", - direction="OUT", + transType="OUT", dataLength=13, interEventDelay=ied, ) @@ -102,7 +102,7 @@ def test_session(ep, address, bus_speed): deviceAddress=address, endpointNumber=ep, endpointType="BULK", - direction="OUT", + transType="OUT", dataLength=14, interEventDelay=ied, ) diff --git a/tests/test_bulk_rx_multiep.py b/tests/test_bulk_rx_multiep.py index a303db30..7127e110 100644 --- a/tests/test_bulk_rx_multiep.py +++ b/tests/test_bulk_rx_multiep.py @@ -29,7 +29,7 @@ def test_session(ep, address, bus_speed): deviceAddress=address, endpointNumber=ep, endpointType="BULK", - direction="OUT", + transType="OUT", dataLength=pktLength, ) ) @@ -39,7 +39,7 @@ def test_session(ep, address, bus_speed): deviceAddress=address, endpointNumber=4, endpointType="BULK", - direction="OUT", + transType="OUT", dataLength=pktLength, ) ) @@ -49,7 +49,7 @@ def test_session(ep, address, bus_speed): deviceAddress=address, endpointNumber=5, endpointType="BULK", - direction="OUT", + transType="OUT", dataLength=pktLength, ) ) @@ -59,7 +59,7 @@ def test_session(ep, address, bus_speed): deviceAddress=address, endpointNumber=6, endpointType="BULK", - direction="OUT", + transType="OUT", dataLength=pktLength, ) ) diff --git a/tests/test_bulk_rx_traffic.py b/tests/test_bulk_rx_traffic.py index 733a892e..d413169b 100644 --- a/tests/test_bulk_rx_traffic.py +++ b/tests/test_bulk_rx_traffic.py @@ -30,7 +30,7 @@ def test_session(ep, address, bus_speed): deviceAddress=trafficAddress1, endpointNumber=trafficEp1, endpointType="BULK", - direction="OUT", + transType="OUT", dataLength=pktLength, interEventDelay=ied, ) @@ -42,7 +42,7 @@ def test_session(ep, address, bus_speed): deviceAddress=address, endpointNumber=ep, endpointType="BULK", - direction="OUT", + transType="OUT", dataLength=pktLength, interEventDelay=ied, ) @@ -54,7 +54,7 @@ def test_session(ep, address, bus_speed): deviceAddress=trafficAddress2, endpointNumber=trafficEp2, endpointType="BULK", - direction="OUT", + transType="OUT", dataLength=pktLength, interEventDelay=ied, ) diff --git a/tests/test_bulk_tx_badack.py b/tests/test_bulk_tx_badack.py index ff360d59..e262d292 100644 --- a/tests/test_bulk_tx_badack.py +++ b/tests/test_bulk_tx_badack.py @@ -43,7 +43,7 @@ def test_session(ep, address, bus_speed): deviceAddress=address, endpointNumber=ep, endpointType="BULK", - direction="IN", + transType="IN", dataLength=pktLength, interEventDelay=ied, ) diff --git a/tests/test_bulk_tx_basic.py b/tests/test_bulk_tx_basic.py index f967784a..9da26eaf 100644 --- a/tests/test_bulk_tx_basic.py +++ b/tests/test_bulk_tx_basic.py @@ -24,7 +24,7 @@ def test_session(ep, address, bus_speed): deviceAddress=address, endpointNumber=ep, endpointType="BULK", - direction="IN", + transType="IN", dataLength=pktLength, ) ) diff --git a/tests/test_bulk_tx_basic_noack.py b/tests/test_bulk_tx_basic_noack.py index fbb548e5..9c99b3d2 100644 --- a/tests/test_bulk_tx_basic_noack.py +++ b/tests/test_bulk_tx_basic_noack.py @@ -42,7 +42,7 @@ def test_session(ep, address, bus_speed): deviceAddress=address, endpointNumber=ep, endpointType="BULK", - direction="IN", + transType="IN", dataLength=pktLength, interEventDelay=ied, ) diff --git a/tests/test_bulk_tx_basic_short.py b/tests/test_bulk_tx_basic_short.py index fb1e878e..2acb9f93 100644 --- a/tests/test_bulk_tx_basic_short.py +++ b/tests/test_bulk_tx_basic_short.py @@ -24,7 +24,7 @@ def test_session(ep, address, bus_speed): deviceAddress=address, endpointNumber=ep, endpointType="BULK", - direction="IN", + transType="IN", dataLength=pktLength, ) ) diff --git a/tests/test_bulk_tx_multiep.py b/tests/test_bulk_tx_multiep.py index 73a57fee..c1b298ec 100644 --- a/tests/test_bulk_tx_multiep.py +++ b/tests/test_bulk_tx_multiep.py @@ -30,7 +30,7 @@ def test_session(ep, address, bus_speed): deviceAddress=address, endpointNumber=ep, endpointType="BULK", - direction="IN", + transType="IN", dataLength=pktLength, interEventDelay=ied, ) @@ -41,7 +41,7 @@ def test_session(ep, address, bus_speed): deviceAddress=address, endpointNumber=ep + 1, endpointType="BULK", - direction="IN", + transType="IN", dataLength=pktLength, interEventDelay=ied, ) @@ -52,7 +52,7 @@ def test_session(ep, address, bus_speed): deviceAddress=address, endpointNumber=ep + 2, endpointType="BULK", - direction="IN", + transType="IN", dataLength=pktLength, interEventDelay=ied, ) @@ -63,7 +63,7 @@ def test_session(ep, address, bus_speed): deviceAddress=address, endpointNumber=ep + 3, endpointType="BULK", - direction="IN", + transType="IN", dataLength=pktLength, interEventDelay=ied, ) diff --git a/tests/test_control_basic_get.py b/tests/test_control_basic_get.py index 220df7e8..46c649ef 100644 --- a/tests/test_control_basic_get.py +++ b/tests/test_control_basic_get.py @@ -14,6 +14,7 @@ USB_PID, ) from usb_session import UsbSession +from usb_transaction import UsbTransaction # Only test on EP 0 - Update params PARAMS = deepcopy(PARAMS) @@ -24,56 +25,46 @@ @pytest.fixture def test_session(ep, address, bus_speed): - ied = 500 + start_length = 0 + end_length = start_length + 10 session = UsbSession( bus_speed=bus_speed, run_enumeration=False, device_address=address ) - # SETUP transaction - session.add_event( - TokenPacket( - pid=USB_PID["SETUP"], - address=address, - endpoint=ep, - ) - ) - session.add_event( - TxDataPacket( - dataPayload=session.getPayload_out(ep, 8), - pid=USB_PID["DATA0"], - ) - ) - session.add_event(RxHandshakePacket()) + for pktLength in range(start_length, end_length): - # IN transaction - # Note, quite big gap to avoid nak - session.add_event( - TokenPacket( - pid=USB_PID["IN"], - address=address, - endpoint=ep, - interEventDelay=10000, + session.add_event( + UsbTransaction( + session, + deviceAddress=address, + endpointNumber=ep, + endpointType="CONTROL", + transType="SETUP", + dataLength=8, + ) ) - ) - session.add_event( - RxDataPacket( - dataPayload=session.getPayload_in(ep, 10), - pid=USB_PID["DATA1"], + + session.add_event( + UsbTransaction( + session, + deviceAddress=address, + endpointNumber=ep, + endpointType="CONTROL", + transType="IN", + dataLength=pktLength, + ) ) - ) - session.add_event(TxHandshakePacket()) - # Send 0 length OUT transaction - session.add_event( - TokenPacket( - pid=USB_PID["OUT"], - address=address, - endpoint=ep, - interEventDelay=ied, + session.add_event( + UsbTransaction( + session, + deviceAddress=address, + endpointNumber=ep, + endpointType="CONTROL", + transType="OUT", + dataLength=0, + ) ) - ) - session.add_event(TxDataPacket(length=0, pid=USB_PID["DATA1"])) - session.add_event(RxHandshakePacket()) return session diff --git a/tests/test_control_basic_get/src/main.xc b/tests/test_control_basic_get/src/main.xc index e5657420..b880a8fd 100644 --- a/tests/test_control_basic_get/src/main.xc +++ b/tests/test_control_basic_get/src/main.xc @@ -2,67 +2,18 @@ // This Software is subject to the terms of the XMOS Public Licence: Version 1. #include "shared.h" -#define EP_COUNT_OUT (5) -#define EP_COUNT_IN (5) +#define EP_COUNT_OUT (5) +#define EP_COUNT_IN (5) -/* Endpoint type tables */ -XUD_EpType epTypeTableOut[EP_COUNT_OUT] = {XUD_EPTYPE_CTL, - XUD_EPTYPE_BUL, - XUD_EPTYPE_BUL, - XUD_EPTYPE_BUL, - XUD_EPTYPE_BUL}; -XUD_EpType epTypeTableIn[EP_COUNT_IN] = {XUD_EPTYPE_CTL, XUD_EPTYPE_BUL, XUD_EPTYPE_BUL, XUD_EPTYPE_BUL, XUD_EPTYPE_BUL}; +#ifndef PKT_LENGTH_START +#define PKT_LENGTH_START (0) +#endif +#ifndef PKT_LENGTH_END +#define PKT_LENGTH_END (9) +#endif -int TestEp_Control(XUD_ep c_ep0_out, XUD_ep c_ep0_in, int epNum) -{ - unsigned int slength; - unsigned int length; - XUD_Result_t sres; - XUD_Result_t res; +#include "test_control_basic_get.xc" - /* Buffer for Setup data */ - unsigned char sbuffer[120]; - unsigned char buffer[120]; - - unsafe - { - /* Wait for Setup data */ - sres = XUD_GetSetupBuffer(c_ep0_out, sbuffer, slength); - - res = SendTxPacket(c_ep0_in, 10, epNum); - - res = XUD_GetBuffer(c_ep0_out, buffer, length); - - if(length != 0) - { - return FAIL_RX_DATAERROR; - } - - /* Do some checking */ - if(res != XUD_RES_OKAY) - { - return FAIL_RX_BAD_RETURN_CODE; - } - - if(RxDataCheck(sbuffer, slength, epNum, 8)) - { - return FAIL_RX_DATAERROR; - } - - return 0; - } -} - -unsigned test_func(chanend c_ep_out[EP_COUNT_OUT], chanend c_ep_in[EP_COUNT_IN]) -{ - XUD_ep c_ep0_out = XUD_InitEp(c_ep_out[0]); - XUD_ep c_ep0_in = XUD_InitEp(c_ep_in[0]); - - unsigned failed = TestEp_Control(c_ep0_out, c_ep0_in, 0); - - XUD_Kill(c_ep0_out); - return failed; -} #include "test_main.xc" diff --git a/tests/test_control_basic_get_epmax.py b/tests/test_control_basic_get_epmax.py new file mode 100644 index 00000000..fb59b90f --- /dev/null +++ b/tests/test_control_basic_get_epmax.py @@ -0,0 +1,85 @@ +# Copyright 2016-2021 XMOS LIMITED. +# This Software is subject to the terms of the XMOS Public Licence: Version 1. +from copy import deepcopy + +import pytest + +from conftest import PARAMS, test_RunUsbSession # noqa F401 +from usb_packet import ( + TokenPacket, + TxDataPacket, + RxDataPacket, + TxHandshakePacket, + RxHandshakePacket, + USB_PID, +) +from usb_session import UsbSession +from usb_transaction import UsbTransaction + +# Only test on EP 0 - Update params +PARAMS = deepcopy(PARAMS) +for k in PARAMS: + PARAMS[k].update({"ep": [0]}) + + +@pytest.fixture +def test_session(ep, address, bus_speed): + + # Note, EP0_MAX_PACKET_SIZE set to 8 in test to speed things up + maxPktLength = 8 + + startLength = 8 + endLength = 20 + + session = UsbSession( + bus_speed=bus_speed, run_enumeration=False, device_address=address + ) + + for dataLength in range(startLength, endLength + 1): + + session.add_event( + UsbTransaction( + session, + deviceAddress=address, + endpointNumber=ep, + endpointType="CONTROL", + transType="SETUP", + dataLength=8, + interEventDelay=1000, # Large delay to allow for packet generation + ) + ) + + thisDataLength = dataLength + + while thisDataLength > 0: + + pktLength = maxPktLength + + if thisDataLength < maxPktLength: + pktLength = thisDataLength + + thisDataLength = thisDataLength - pktLength + + session.add_event( + UsbTransaction( + session, + deviceAddress=address, + endpointNumber=ep, + endpointType="CONTROL", + transType="IN", + dataLength=pktLength, + ) + ) + + session.add_event( + UsbTransaction( + session, + deviceAddress=address, + endpointNumber=ep, + endpointType="CONTROL", + transType="OUT", + dataLength=0, + ) + ) + + return session diff --git a/tests/test_control_basic_get_epmax/Makefile b/tests/test_control_basic_get_epmax/Makefile new file mode 100644 index 00000000..0cfecb60 --- /dev/null +++ b/tests/test_control_basic_get_epmax/Makefile @@ -0,0 +1,3 @@ +TEST_FLAGS = -DXUD_BYPASS_RESET=1 -DEP0_MAX_PACKET_SIZE=8 + +include ../test_makefile.mak diff --git a/tests/test_control_basic_get_epmax/src/main.xc b/tests/test_control_basic_get_epmax/src/main.xc new file mode 100644 index 00000000..1c6c9a5b --- /dev/null +++ b/tests/test_control_basic_get_epmax/src/main.xc @@ -0,0 +1,19 @@ +// Copyright 2016-2021 XMOS LIMITED. +// This Software is subject to the terms of the XMOS Public Licence: Version 1. +#include "shared.h" + +#define EP_COUNT_OUT (5) +#define EP_COUNT_IN (5) + +#ifndef PKT_LENGTH_START +#define PKT_LENGTH_START (8) +#endif + +#ifndef PKT_LENGTH_END +#define PKT_LENGTH_END (20) +#endif + +#include "test_control_basic_get.xc" + +#include "test_main.xc" + diff --git a/tests/test_control_basic_set.py b/tests/test_control_basic_set.py index 231e0640..0ff0cff2 100644 --- a/tests/test_control_basic_set.py +++ b/tests/test_control_basic_set.py @@ -14,6 +14,7 @@ USB_PID, ) from usb_session import UsbSession +from usb_transaction import UsbTransaction # Only test on EP 0 - Update params PARAMS = deepcopy(PARAMS) @@ -26,57 +27,41 @@ def test_session(ep, address, bus_speed): ied = 500 - # if bus_speed == "HS" and dummy_threads > 4: - # pytest.xfail("Known fail when dummy threads > 4") - session = UsbSession( bus_speed=bus_speed, run_enumeration=False, device_address=address ) - # SETUP transaction - session.add_event( - TokenPacket( - pid=USB_PID["SETUP"], - address=address, - endpoint=ep, - ) - ) session.add_event( - TxDataPacket( - dataPayload=session.getPayload_out(ep, 8), - pid=USB_PID["DATA0"], + UsbTransaction( + session, + deviceAddress=address, + endpointNumber=ep, + endpointType="CONTROL", + transType="SETUP", + dataLength=8, ) ) - session.add_event(RxHandshakePacket()) - # OUT transaction - # Note, quite big gap to avoid nak session.add_event( - TokenPacket( - pid=USB_PID["OUT"], - address=address, - endpoint=ep, - interEventDelay=10000, + UsbTransaction( + session, + deviceAddress=address, + endpointNumber=ep, + endpointType="CONTROL", + transType="OUT", + dataLength=10, ) ) - session.add_event( - TxDataPacket( - dataPayload=session.getPayload_out(ep, 10), - pid=USB_PID["DATA1"], - ) - ) - session.add_event(RxHandshakePacket()) # Expect 0 length IN transaction session.add_event( - TokenPacket( - pid=USB_PID["IN"], - address=address, - endpoint=ep, - interEventDelay=ied, + UsbTransaction( + session, + deviceAddress=address, + endpointNumber=ep, + endpointType="CONTROL", + transType="IN", + dataLength=0, ) ) - session.add_event(RxDataPacket(dataPayload=[], pid=USB_PID["DATA1"])) - session.add_event(TxHandshakePacket()) - return session diff --git a/tests/test_control_traffic.py b/tests/test_control_traffic.py index b062e589..6092d427 100644 --- a/tests/test_control_traffic.py +++ b/tests/test_control_traffic.py @@ -14,6 +14,7 @@ USB_PID, ) from usb_session import UsbSession +from usb_transaction import UsbTransaction # Only test on EP 0 - Update params PARAMS = deepcopy(PARAMS) @@ -29,93 +30,86 @@ def test_session(ep, address, bus_speed): trafficAddress1 = (address + 1) % 128 trafficAddress2 = (address + 127) % 128 + start_length = 0 + end_length = start_length + 10 + session = UsbSession( bus_speed=bus_speed, run_enumeration=False, device_address=address ) - # SETUP to another address (Note, DUT would not see ACK) - session.add_event( - TokenPacket( - pid=USB_PID["SETUP"], - address=trafficAddress1, - endpoint=ep, - ) - ) - session.add_event( - TxDataPacket( - dataPayload=[1, 2, 3, 4, 5, 6, 7, 8], - pid=USB_PID["DATA0"], - ) - ) + for pktLength in range(start_length, end_length): - # SETUP transaction to DUT - session.add_event( - TokenPacket( - pid=USB_PID["SETUP"], - address=address, - endpoint=ep, + # SETUP to another address (Note, DUT would not see ACK) + session.add_event( + TokenPacket( + pid=USB_PID["SETUP"], + address=trafficAddress1, + endpoint=ep, + ) ) - ) - session.add_event( - TxDataPacket( - dataPayload=session.getPayload_out(ep, 8), - pid=USB_PID["DATA0"], + session.add_event( + TxDataPacket( + dataPayload=[1, 2, 3, 4, 5, 6, 7, 8], + pid=USB_PID["DATA0"], + ) ) - ) - session.add_event(RxHandshakePacket()) - - # IN transaction - # Note, quite big gap to avoid nak - session.add_event( - TokenPacket( - pid=USB_PID["IN"], - address=address, - endpoint=ep, - interEventDelay=10000, + + session.add_event( + UsbTransaction( + session, + deviceAddress=address, + endpointNumber=ep, + endpointType="CONTROL", + transType="SETUP", + dataLength=8, + ) ) - ) - session.add_event( - RxDataPacket( - dataPayload=session.getPayload_in(ep, 10), - pid=USB_PID["DATA1"], + + session.add_event( + UsbTransaction( + session, + deviceAddress=address, + endpointNumber=ep, + endpointType="CONTROL", + transType="IN", + dataLength=pktLength, + ) ) - ) - session.add_event(TxHandshakePacket()) - - # SETUP to another address (Note, DUT would not see ACK) - session.add_event( - TokenPacket( - pid=USB_PID["SETUP"], - address=trafficAddress2, - endpoint=ep, + + # SETUP to another address (Note, DUT would not see ACK) + session.add_event( + TokenPacket( + pid=USB_PID["SETUP"], + address=trafficAddress2, + endpoint=ep, + ) ) - ) - session.add_event( - TxDataPacket( - dataPayload=[1, 2, 3, 4, 5, 6, 7, 8], - pid=USB_PID["DATA0"], + session.add_event( + TxDataPacket( + dataPayload=[1, 2, 3, 4, 5, 6, 7, 8], + pid=USB_PID["DATA0"], + ) ) - ) - session.add_event( - TokenPacket( - pid=USB_PID["IN"], - address=trafficAddress2, - endpoint=ep, - interEventDelay=1000, + session.add_event( + TokenPacket( + pid=USB_PID["IN"], + address=trafficAddress2, + endpoint=ep, + interEventDelay=1000, + ) ) - ) - # Send 0 length OUT transaction - session.add_event( - TokenPacket( - pid=USB_PID["OUT"], - address=address, - endpoint=ep, - interEventDelay=ied, + # Send 0 length OUT transaction + session.add_event( + UsbTransaction( + session, + deviceAddress=address, + endpointNumber=ep, + endpointType="CONTROL", + transType="OUT", + dataLength=0, + ) ) - ) - session.add_event(TxDataPacket(length=0, pid=USB_PID["DATA1"])) - session.add_event(RxHandshakePacket()) return session diff --git a/tests/test_device_attach.py b/tests/test_device_attach.py index 78b26167..07ed4237 100644 --- a/tests/test_device_attach.py +++ b/tests/test_device_attach.py @@ -9,6 +9,7 @@ from usb_session import UsbSession from usb_transaction import UsbTransaction from usb_signalling import UsbDeviceAttach +from usb_phy import USB_PKT_TIMINGS # Only need to run device attach tests for one ep/address PARAMS = deepcopy(PARAMS) @@ -22,11 +23,13 @@ def test_session(ep, address, bus_speed): pktLength = 10 frameNumber = 52 # Note, for frame number 52 we expect A5 34 40 on the bus + interEventDelay = USB_PKT_TIMINGS["TX_TO_TX_PACKET_DELAY"] + session = UsbSession( bus_speed=bus_speed, run_enumeration=False, device_address=address, - initial_delay=19000, + initial_delay=19000 * 1000 * 1000, # fs ) session.add_event(UsbDeviceAttach()) @@ -39,9 +42,9 @@ def test_session(ep, address, bus_speed): deviceAddress=address, endpointNumber=ep, endpointType="BULK", - direction="OUT", + transType="OUT", dataLength=pktLength, - interEventDelay=0, + interEventDelay=interEventDelay, ) ) @@ -55,9 +58,9 @@ def test_session(ep, address, bus_speed): deviceAddress=address, endpointNumber=ep, endpointType="BULK", - direction="OUT", + transType="OUT", dataLength=pktLength, - interEventDelay=0, + interEventDelay=interEventDelay, ) ) diff --git a/tests/test_invalidtoken.py b/tests/test_invalidtoken.py index 6d966a28..e5e22da2 100644 --- a/tests/test_invalidtoken.py +++ b/tests/test_invalidtoken.py @@ -51,7 +51,7 @@ def test_session(ep, address, bus_speed): deviceAddress=address, endpointNumber=ep, endpointType="BULK", - direction="OUT", + transType="OUT", dataLength=10, ) ) @@ -73,7 +73,7 @@ def test_session(ep, address, bus_speed): deviceAddress=address, endpointNumber=ep, endpointType="BULK", - direction="OUT", + transType="OUT", dataLength=11, interEventDelay=6000, ) @@ -95,7 +95,7 @@ def test_session(ep, address, bus_speed): deviceAddress=address, endpointNumber=ep, endpointType="BULK", - direction="OUT", + transType="OUT", dataLength=12, interEventDelay=6000, ) @@ -106,7 +106,7 @@ def test_session(ep, address, bus_speed): deviceAddress=address, endpointNumber=ep, endpointType="BULK", - direction="OUT", + transType="OUT", dataLength=13, interEventDelay=6000, ) @@ -117,7 +117,7 @@ def test_session(ep, address, bus_speed): deviceAddress=address, endpointNumber=ep, endpointType="BULK", - direction="OUT", + transType="OUT", dataLength=14, interEventDelay=6000, ) diff --git a/tests/test_iso_loopback.py b/tests/test_iso_loopback.py index 284f65ae..bd6bf122 100644 --- a/tests/test_iso_loopback.py +++ b/tests/test_iso_loopback.py @@ -27,7 +27,7 @@ def test_session(ep, address, bus_speed): deviceAddress=address, endpointNumber=ep_loopback, endpointType="ISO", - direction="OUT", + transType="OUT", dataLength=pktLength, ) ) @@ -42,7 +42,7 @@ def test_session(ep, address, bus_speed): deviceAddress=address, endpointNumber=ep_loopback, endpointType="ISO", - direction="IN", + transType="IN", dataLength=pktLength, interEventDelay=498, ) @@ -57,7 +57,7 @@ def test_session(ep, address, bus_speed): deviceAddress=address, endpointNumber=ep_loopback_kill, endpointType="ISO", - direction="OUT", + transType="OUT", dataLength=pktLength, ) ) @@ -67,7 +67,7 @@ def test_session(ep, address, bus_speed): deviceAddress=address, endpointNumber=ep_loopback_kill, endpointType="ISO", - direction="IN", + transType="IN", dataLength=pktLength, ) ) diff --git a/tests/test_iso_rx_basic.py b/tests/test_iso_rx_basic.py index 90aac9ab..6b257844 100644 --- a/tests/test_iso_rx_basic.py +++ b/tests/test_iso_rx_basic.py @@ -11,21 +11,24 @@ def test_session(ep, address, bus_speed): start_length = 10 - end_length = start_length + 5 + end_length = start_length + 4 session = UsbSession( bus_speed=bus_speed, run_enumeration=False, device_address=address ) - for pktLength in range(start_length, end_length): + interTransactionDelay = 500 + + for pktLength in range(start_length, end_length + 1): session.add_event( UsbTransaction( session, deviceAddress=address, endpointNumber=ep, endpointType="ISO", - direction="OUT", + transType="OUT", dataLength=pktLength, + interEventDelay=interTransactionDelay, ) ) diff --git a/tests/test_iso_rxtx_fastpacket.py b/tests/test_iso_rxtx_fastpacket.py index 040c6886..187ed5d1 100644 --- a/tests/test_iso_rxtx_fastpacket.py +++ b/tests/test_iso_rxtx_fastpacket.py @@ -26,7 +26,7 @@ def test_session(ep, address, bus_speed): deviceAddress=address, endpointNumber=ep, endpointType="ISO", - direction="OUT", + transType="OUT", dataLength=pktLength, interEventDelay=20, ) @@ -38,7 +38,7 @@ def test_session(ep, address, bus_speed): deviceAddress=address, endpointNumber=ep, endpointType="ISO", - direction="IN", + transType="IN", dataLength=pktLength, interEventDelay=58, ) diff --git a/tests/test_iso_tx_basic.py b/tests/test_iso_tx_basic.py index 7765f70b..3df1d131 100644 --- a/tests/test_iso_tx_basic.py +++ b/tests/test_iso_tx_basic.py @@ -14,10 +14,7 @@ def test_session(ep, address, bus_speed): end_length = start_length + 5 session = UsbSession( - bus_speed=bus_speed, - run_enumeration=False, - device_address=address, - initial_delay=100000, + bus_speed=bus_speed, run_enumeration=False, device_address=address ) for pktLength in range(start_length, end_length): @@ -27,7 +24,7 @@ def test_session(ep, address, bus_speed): deviceAddress=address, endpointNumber=ep, endpointType="ISO", - direction="IN", + transType="IN", dataLength=pktLength, ) ) diff --git a/tests/test_makefile.mak b/tests/test_makefile.mak index fb69d14b..36fc9abe 100644 --- a/tests/test_makefile.mak +++ b/tests/test_makefile.mak @@ -21,8 +21,9 @@ COMMON_FLAGS = -DDEBUG_PRINT_ENABLE \ -DUSB_TILE=tile[0] \ -DXUD_SIM_XSIM=1 \ -DXUD_TEST_SPEED_HS=1 \ - -save-temps \ -Xmapper --retain \ + -g \ + -save-temps \ $(CFLAGS) TEST_FLAGS ?= diff --git a/tests/test_ping_rx_basic.py b/tests/test_ping_rx_basic.py index 9f095699..2d2261ad 100644 --- a/tests/test_ping_rx_basic.py +++ b/tests/test_ping_rx_basic.py @@ -49,7 +49,7 @@ def test_session(ep, address, bus_speed): deviceAddress=address, endpointNumber=ep + 1, endpointType="BULK", - direction="OUT", + transType="OUT", dataLength=10, ) ) @@ -83,7 +83,7 @@ def test_session(ep, address, bus_speed): deviceAddress=address, endpointNumber=ep, endpointType="BULK", - direction="OUT", + transType="OUT", dataLength=10, interEventDelay=6000, ) @@ -116,7 +116,7 @@ def test_session(ep, address, bus_speed): deviceAddress=address, endpointNumber=ep + 1, endpointType="BULK", - direction="OUT", + transType="OUT", dataLength=10, ) ) diff --git a/tests/test_ping_stall.py b/tests/test_ping_stall.py index b3f9584e..b952e6ac 100644 --- a/tests/test_ping_stall.py +++ b/tests/test_ping_stall.py @@ -47,7 +47,7 @@ def test_session(ep, address, bus_speed): deviceAddress=address, endpointNumber=ep_ctrl, endpointType="BULK", - direction="OUT", + transType="OUT", dataLength=pktLength, ) ) @@ -59,7 +59,7 @@ def test_session(ep, address, bus_speed): deviceAddress=address, endpointNumber=ep, endpointType="BULK", - direction="OUT", + transType="OUT", dataLength=pktLength, ) ) @@ -70,7 +70,7 @@ def test_session(ep, address, bus_speed): deviceAddress=address, endpointNumber=ep, endpointType="BULK", - direction="OUT", + transType="OUT", dataLength=pktLength, ) ) diff --git a/tests/test_sof_basic.py b/tests/test_sof_basic.py index b5ecb8b2..250a6a5a 100644 --- a/tests/test_sof_basic.py +++ b/tests/test_sof_basic.py @@ -6,6 +6,7 @@ from usb_session import UsbSession from usb_transaction import UsbTransaction from usb_packet import CreateSofToken +from usb_transaction import INTER_TRANSACTION_DELAY @pytest.fixture @@ -24,16 +25,26 @@ def test_session(ep, address, bus_speed): deviceAddress=address, endpointNumber=ep, endpointType="BULK", - direction="OUT", + transType="OUT", dataLength=10, ) ) - session.add_event(CreateSofToken(frameNumber)) - session.add_event(CreateSofToken(frameNumber + 1)) - session.add_event(CreateSofToken(frameNumber + 2)) - session.add_event(CreateSofToken(frameNumber + 3)) - session.add_event(CreateSofToken(frameNumber + 4)) + session.add_event( + CreateSofToken(frameNumber, interEventDelay=INTER_TRANSACTION_DELAY) + ) + session.add_event( + CreateSofToken(frameNumber + 1, interEventDelay=INTER_TRANSACTION_DELAY) + ) + session.add_event( + CreateSofToken(frameNumber + 2, interEventDelay=INTER_TRANSACTION_DELAY) + ) + session.add_event( + CreateSofToken(frameNumber + 3, interEventDelay=INTER_TRANSACTION_DELAY) + ) + session.add_event( + CreateSofToken(frameNumber + 4, interEventDelay=INTER_TRANSACTION_DELAY) + ) # Finish with valid transaction session.add_event( @@ -42,7 +53,7 @@ def test_session(ep, address, bus_speed): deviceAddress=address, endpointNumber=ep, endpointType="BULK", - direction="OUT", + transType="OUT", dataLength=11, interEventDelay=6000, ) diff --git a/tests/test_stall_basic.py b/tests/test_stall_basic.py index a478f1bb..34f660b5 100644 --- a/tests/test_stall_basic.py +++ b/tests/test_stall_basic.py @@ -10,9 +10,6 @@ @pytest.fixture def test_session(ep, address, bus_speed): - if bus_speed == "FS": - pytest.xfail("Known failure at FS") - pktLength = 10 session = UsbSession( @@ -21,6 +18,29 @@ def test_session(ep, address, bus_speed): ep_ctrl = ep + 1 + # Valid transactions on test EP's + session.add_event( + UsbTransaction( + session, + deviceAddress=address, + endpointNumber=ep, + endpointType="BULK", + transType="OUT", + dataLength=pktLength, + ) + ) + + session.add_event( + UsbTransaction( + session, + deviceAddress=address, + endpointNumber=ep, + endpointType="BULK", + transType="IN", + dataLength=pktLength, + ) + ) + # Expect test EP's to be halted session.add_event( UsbTransaction( @@ -28,7 +48,7 @@ def test_session(ep, address, bus_speed): deviceAddress=address, endpointNumber=ep, endpointType="BULK", - direction="OUT", + transType="OUT", dataLength=pktLength, halted=True, ) @@ -40,7 +60,7 @@ def test_session(ep, address, bus_speed): deviceAddress=address, endpointNumber=ep, endpointType="BULK", - direction="OUT", + transType="OUT", dataLength=pktLength, halted=True, ) @@ -52,7 +72,7 @@ def test_session(ep, address, bus_speed): deviceAddress=address, endpointNumber=ep, endpointType="BULK", - direction="IN", + transType="IN", halted=True, ) ) @@ -63,7 +83,7 @@ def test_session(ep, address, bus_speed): deviceAddress=address, endpointNumber=ep, endpointType="BULK", - direction="IN", + transType="IN", halted=True, ) ) @@ -75,18 +95,19 @@ def test_session(ep, address, bus_speed): deviceAddress=address, endpointNumber=ep_ctrl, endpointType="BULK", - direction="OUT", + transType="OUT", dataLength=pktLength, ) ) + # Check EP no working as normal session.add_event( UsbTransaction( session, deviceAddress=address, endpointNumber=ep, endpointType="BULK", - direction="OUT", + transType="OUT", dataLength=pktLength, interEventDelay=1000, ) @@ -98,16 +119,68 @@ def test_session(ep, address, bus_speed): deviceAddress=address, endpointNumber=ep, endpointType="BULK", - direction="IN", + transType="IN", dataLength=pktLength, ) ) - return session + # EP now re-halted + session.add_event( + UsbTransaction( + session, + deviceAddress=address, + endpointNumber=ep, + endpointType="BULK", + transType="OUT", + dataLength=pktLength, + halted=True, + ) + ) + session.add_event( + UsbTransaction( + session, + deviceAddress=address, + endpointNumber=ep, + endpointType="BULK", + transType="IN", + halted=True, + ) + ) + + # Valid transaction to another EP informing test code to clear stall + session.add_event( + UsbTransaction( + session, + deviceAddress=address, + endpointNumber=ep_ctrl, + endpointType="BULK", + transType="OUT", + dataLength=pktLength, + ) + ) + + # Check EP now working as normal + session.add_event( + UsbTransaction( + session, + deviceAddress=address, + endpointNumber=ep, + endpointType="BULK", + transType="OUT", + dataLength=pktLength, + ) + ) + + session.add_event( + UsbTransaction( + session, + deviceAddress=address, + endpointNumber=ep, + endpointType="BULK", + transType="IN", + dataLength=pktLength, + ) + ) -# for result in RunUsbTest( -# gen_test_session, test_arch, test_ep, test_address, -# test_bus_speed, __file__ -# ): -# assert result + return session diff --git a/tests/test_stall_basic/src/main.xc b/tests/test_stall_basic/src/main.xc index 4283bfb6..1d2440c8 100644 --- a/tests/test_stall_basic/src/main.xc +++ b/tests/test_stall_basic/src/main.xc @@ -33,26 +33,39 @@ unsigned test_func(chanend c_ep_out[EP_COUNT_OUT], chanend c_ep_in[EP_COUNT_IN]) { unsigned failed = 0; uint8_t outBuffer[128]; - uint8_t inBuffer[128]; + uint8_t inBuffer0[128]; + uint8_t inBuffer1[128]; + uint8_t inBuffer2[128]; unsigned length; XUD_Result_t result; - for(size_t i = 0; i < sizeof(outBuffer); i++) - inBuffer[i] = i; + for(size_t i = 0; i < PKT_LENGTH_START; i++) + { + inBuffer0[i] = i; + inBuffer1[i] = i + PKT_LENGTH_START; + inBuffer2[i] = i + PKT_LENGTH_START + PKT_LENGTH_START; + } - /* Stall EPs */ XUD_ep ep_out = XUD_InitEp(c_ep_out[TEST_EP_NUM]); - XUD_SetStall(ep_out); - XUD_ep ep_in = XUD_InitEp(c_ep_in[TEST_EP_NUM]); - XUD_SetStall(ep_in); - XUD_ep ep_ctrl = XUD_InitEp(c_ep_out[CTRL_EP_NUM]); + + /* Valid transaction on test OUT EP */ + /* This is somewhat important as this will toggle the expected PID - which should be reset on an un-stall */ + result = XUD_GetBuffer(ep_out, outBuffer, length); + failed = (result != XUD_RES_OKAY); + + result = XUD_SetBuffer(ep_in, inBuffer0, PKT_LENGTH_START); + failed |= (result != XUD_RES_OKAY); + + /* Stall test EPs */ + XUD_SetStall(ep_in); + XUD_SetStall(ep_out); /* Valid transaction on another EP, clear STALL on the test EP's */ result = XUD_GetBuffer(ep_ctrl, outBuffer, length); failed = (result != XUD_RES_OKAY); - + /* Clear stall on the test EP's */ XUD_ClearStall(ep_out); XUD_ClearStall(ep_in); @@ -61,7 +74,26 @@ unsigned test_func(chanend c_ep_out[EP_COUNT_OUT], chanend c_ep_in[EP_COUNT_IN]) result = XUD_GetBuffer(ep_out, outBuffer, length); failed |= (result != XUD_RES_OKAY); - result = XUD_SetBuffer(ep_in, inBuffer, PKT_LENGTH_START); + result = XUD_SetBuffer(ep_in, inBuffer1, PKT_LENGTH_START); + failed |= (result != XUD_RES_OKAY); + + /* Stall both EP's using Addr */ + XUD_SetStallByAddr(TEST_EP_NUM); + XUD_SetStallByAddr(TEST_EP_NUM | 0x80); + + /* Valid transaction on another EP, clear STALL on the test EP's */ + result = XUD_GetBuffer(ep_ctrl, outBuffer, length); + failed = (result != XUD_RES_OKAY); + + /* Clear stall on both EPs using Addr */ + XUD_ClearStallByAddr(TEST_EP_NUM); + XUD_ClearStallByAddr(TEST_EP_NUM | 0x80); + + /* Ensure test EP's now operate as expected */ + result = XUD_GetBuffer(ep_out, outBuffer, length); + failed |= (result != XUD_RES_OKAY); + + result = XUD_SetBuffer(ep_in, inBuffer2, PKT_LENGTH_START); failed |= (result != XUD_RES_OKAY); return failed; diff --git a/tests/test_stall_control.py b/tests/test_stall_control.py index e8b5e310..b46a58f4 100644 --- a/tests/test_stall_control.py +++ b/tests/test_stall_control.py @@ -34,104 +34,78 @@ def test_session(ep, address, bus_speed): ) # Ctrl transaction 0 - - # SETUP transaction - session.add_event( - TokenPacket( - pid=USB_PID["SETUP"], - address=address, - endpoint=ep, - ) - ) session.add_event( - TxDataPacket( - dataPayload=session.getPayload_out(ep, 8), - pid=USB_PID["DATA0"], + UsbTransaction( + session, + deviceAddress=address, + endpointNumber=ep, + endpointType="CONTROL", + transType="SETUP", + dataLength=8, ) ) - session.add_event(RxHandshakePacket()) - # OUT transaction - # Note, quite big gap to avoid nak - session.add_event( - TokenPacket( - pid=USB_PID["OUT"], - address=address, - endpoint=ep, - interEventDelay=10000, - ) - ) session.add_event( - TxDataPacket( - dataPayload=session.getPayload_out(ep, 10), - pid=USB_PID["DATA1"], + UsbTransaction( + session, + deviceAddress=address, + endpointNumber=ep, + endpointType="CONTROL", + transType="OUT", + dataLength=10, ) ) - session.add_event(RxHandshakePacket()) # Expect 0 length IN transaction session.add_event( - TokenPacket( - pid=USB_PID["IN"], - address=address, - endpoint=ep, - interEventDelay=ied, + UsbTransaction( + session, + deviceAddress=address, + endpointNumber=ep, + endpointType="CONTROL", + transType="IN", + dataLength=0, ) ) - session.add_event(RxDataPacket(dataPayload=[], pid=USB_PID["DATA1"])) - session.add_event(TxHandshakePacket()) # Ctrl transaction 1 - - # SETUP transaction - session.add_event( - TokenPacket( - pid=USB_PID["SETUP"], - address=address, - endpoint=ep, - interEventDelay=10000, - ) - ) session.add_event( - TxDataPacket( - dataPayload=session.getPayload_out(ep, 8), - pid=USB_PID["DATA0"], + UsbTransaction( + session, + deviceAddress=address, + endpointNumber=ep, + endpointType="CONTROL", + transType="SETUP", + dataLength=8, ) ) - session.add_event(RxHandshakePacket()) - # Check that the EP is now Halted + # Check that the EP is now Halted - i.e. as if the previous request could not be handled session.add_event( UsbTransaction( session, deviceAddress=address, endpointNumber=ep, endpointType="CONTROL", - direction="IN", + transType="IN", dataLength=pktLength, halted=True, interEventDelay=1000, ) ) + # Check that EP is un-Halted on a SETUP # Ctrl transaction 2 - - # SETUP transaction session.add_event( - TokenPacket( - pid=USB_PID["SETUP"], - address=address, - endpoint=ep, - interEventDelay=10000, - ) - ) - session.add_event( - TxDataPacket( - dataPayload=session.getPayload_out(ep, 8), - pid=USB_PID["DATA0"], + UsbTransaction( + session, + deviceAddress=address, + endpointNumber=ep, + endpointType="CONTROL", + transType="SETUP", + dataLength=8, ) ) - session.add_event(RxHandshakePacket()) session.add_event( UsbTransaction( @@ -139,11 +113,8 @@ def test_session(ep, address, bus_speed): deviceAddress=address, endpointNumber=ep, endpointType="CONTROL", - direction="IN", + transType="IN", dataLength=pktLength, - halted=False, - interEventDelay=1000, - resetDataPid=True, ) ) @@ -152,12 +123,9 @@ def test_session(ep, address, bus_speed): session, deviceAddress=address, endpointNumber=ep, - endpointType="BULK", - direction="OUT", + endpointType="CONTROL", + transType="OUT", dataLength=0, - halted=False, - interEventDelay=1000, - resetDataPid=True, ) ) diff --git a/tests/test_stall_epready/src/main.xc b/tests/test_stall_epready/src/main.xc deleted file mode 100644 index 384405c2..00000000 --- a/tests/test_stall_epready/src/main.xc +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 2016-2021 XMOS LIMITED. -// This Software is subject to the terms of the XMOS Public Licence: Version 1. - - -#define EP_COUNT_OUT (6) -#define EP_COUNT_IN (6) - -#ifndef PKT_LENGTH_START -#define PKT_LENGTH_START (10) -#endif - -#ifndef TEST_EP_NUM -#define TEST_EP_NUM (1) -#endif - -#ifndef CTRL_EP_NUM -#define CTRL_EP_NUM (TEST_EP_NUM + 1) -#endif - -#include "shared.h" - -/* Endpoint type tables */ -XUD_EpType epTypeTableOut[EP_COUNT_OUT] = {XUD_EPTYPE_CTL, XUD_EPTYPE_BUL, XUD_EPTYPE_BUL, XUD_EPTYPE_BUL, XUD_EPTYPE_BUL, XUD_EPTYPE_BUL}; -XUD_EpType epTypeTableIn[EP_COUNT_IN] = {XUD_EPTYPE_CTL, XUD_EPTYPE_BUL, XUD_EPTYPE_BUL, XUD_EPTYPE_BUL, XUD_EPTYPE_BUL, XUD_EPTYPE_BUL}; - -unsigned test_func(chanend c_ep_out[EP_COUNT_OUT], chanend c_ep_in[EP_COUNT_IN]) -{ - unsigned failed = 0; - uint8_t outBuffer[128]; - uint8_t ctrlBuffer[128]; - uint8_t inBuffer[128]; - unsigned length; - XUD_Result_t result; - - for(size_t i = 0; i < sizeof(outBuffer); i++) - inBuffer[i] = i; - - XUD_ep ep_ctrl = XUD_InitEp(c_ep_out[CTRL_EP_NUM]); - - XUD_ep ep_out = XUD_InitEp(c_ep_out[TEST_EP_NUM]); - XUD_ep ep_in = XUD_InitEp(c_ep_in[TEST_EP_NUM]); - XUD_SetStall(ep_out); - XUD_SetStall(ep_in); - - XUD_SetReady_Out(ep_out, outBuffer); - XUD_SetReady_In(ep_in, inBuffer, PKT_LENGTH_START); - XUD_SetReady_Out(ep_ctrl, ctrlBuffer); - - unsigned loop0 = 1; - unsigned loop1 = 1; - while(loop0 | loop1) - { - select - { - case XUD_GetData_Select(c_ep_out[TEST_EP_NUM], ep_out, length, result): - loop0 = 0; - break; - - case XUD_GetData_Select(c_ep_out[CTRL_EP_NUM], ep_ctrl, length, result): - XUD_ClearStall(ep_out); - XUD_ClearStall(ep_in); - break; - - case XUD_SetData_Select(c_ep_in[TEST_EP_NUM], ep_in, result): - loop1 = 0; - break; - } - failed |= (result != XUD_RES_OKAY); - } - - return failed; -} - -#include "test_main.xc" diff --git a/tests/test_stall_epready_in.py b/tests/test_stall_epready_in.py new file mode 100644 index 00000000..f5611095 --- /dev/null +++ b/tests/test_stall_epready_in.py @@ -0,0 +1,125 @@ +#!/usr/bin/env python +# Copyright 2016-2021 XMOS LIMITED. +# This Software is subject to the terms of the XMOS Public Licence: Version 1. + +# Directed test for (github) issue #58 +import pytest + +from conftest import PARAMS, test_RunUsbSession # noqa F401 +from usb_session import UsbSession +from usb_transaction import UsbTransaction + + +@pytest.fixture +def test_session(ep, address, bus_speed): + + pktLength = 10 + + session = UsbSession( + bus_speed=bus_speed, run_enumeration=False, device_address=address + ) + + ep_ctrl = ep + 1 + + # Expect test EP's to be halted + session.add_event( + UsbTransaction( + session, + deviceAddress=address, + endpointNumber=ep, + endpointType="BULK", + transType="IN", + dataLength=pktLength, + halted=True, + ) + ) + + # Inform DUT to un-halt OUT EP via ctrl EP + session.add_event( + UsbTransaction( + session, + deviceAddress=address, + endpointNumber=ep_ctrl, + endpointType="BULK", + transType="OUT", + dataLength=pktLength, + ) + ) + + # Expect normal transaction on IN EP + session.add_event( + UsbTransaction( + session, + deviceAddress=address, + endpointNumber=ep, + endpointType="BULK", + transType="IN", + dataLength=pktLength, + ) + ) + pktLength += 1 + + # ---- + + # Expect normal transaction on IN EP + session.add_event( + UsbTransaction( + session, + deviceAddress=address, + endpointNumber=ep, + endpointType="BULK", + transType="IN", + dataLength=pktLength, + ) + ) + pktLength += 1 + + session.add_event( + UsbTransaction( + session, + deviceAddress=address, + endpointNumber=ep_ctrl, + endpointType="BULK", + transType="OUT", + dataLength=pktLength, + interEventDelay=500, + ) + ) + + # Expect EP to now be re-halted + session.add_event( + UsbTransaction( + session, + deviceAddress=address, + endpointNumber=ep, + endpointType="BULK", + transType="IN", + dataLength=pktLength, + halted=True, + ) + ) + + session.add_event( + UsbTransaction( + session, + deviceAddress=address, + endpointNumber=ep_ctrl, + endpointType="BULK", + transType="OUT", + dataLength=pktLength, + interEventDelay=500, + ) + ) + + session.add_event( + UsbTransaction( + session, + deviceAddress=address, + endpointNumber=ep, + endpointType="BULK", + transType="IN", + dataLength=pktLength, + ) + ) + + return session diff --git a/tests/test_stall_epready_in/Makefile b/tests/test_stall_epready_in/Makefile new file mode 100644 index 00000000..a2c9ee98 --- /dev/null +++ b/tests/test_stall_epready_in/Makefile @@ -0,0 +1,3 @@ +TEST_FLAGS = -DXUD_BYPASS_RESET=1 + +include ../test_makefile.mak diff --git a/tests/test_stall_epready_in/src/main.xc b/tests/test_stall_epready_in/src/main.xc new file mode 100644 index 00000000..5136c936 --- /dev/null +++ b/tests/test_stall_epready_in/src/main.xc @@ -0,0 +1,114 @@ +// Copyright 2016-2021 XMOS LIMITED. +// This Software is subject to the terms of the XMOS Public Licence: Version 1. + + +#define EP_COUNT_OUT (6) +#define EP_COUNT_IN (6) + +#ifndef PKT_LENGTH_START +#define PKT_LENGTH_START (10) +#endif + +#ifndef TEST_EP_NUM +#define TEST_EP_NUM (1) +#endif + +#ifndef CTRL_EP_NUM +#define CTRL_EP_NUM (TEST_EP_NUM + 1) +#endif + +#include "shared.h" + +/* Endpoint type tables */ +XUD_EpType epTypeTableOut[EP_COUNT_OUT] = {XUD_EPTYPE_CTL, XUD_EPTYPE_BUL, XUD_EPTYPE_BUL, XUD_EPTYPE_BUL, XUD_EPTYPE_BUL, XUD_EPTYPE_BUL}; +XUD_EpType epTypeTableIn[EP_COUNT_IN] = {XUD_EPTYPE_CTL, XUD_EPTYPE_BUL, XUD_EPTYPE_BUL, XUD_EPTYPE_BUL, XUD_EPTYPE_BUL, XUD_EPTYPE_BUL}; + +unsigned test_ctrl(chanend c_ctrl, chanend c) +{ + uint8_t ctrlBuffer[128]; + unsigned length; + XUD_Result_t result; + uint32_t failed = 0; + + XUD_ep ep_ctrl = XUD_InitEp(c_ctrl); + + c <: 1; + + XUD_GetBuffer(ep_ctrl, ctrlBuffer, length); + failed |= (length != PKT_LENGTH_START); + + XUD_ClearStallByAddr(TEST_EP_NUM | 0x80); /* Set IN bit */ + + c <: 1; + + XUD_GetBuffer(ep_ctrl, ctrlBuffer, length); + failed |= (length != PKT_LENGTH_START); + + XUD_SetStallByAddr(TEST_EP_NUM | 0x80); + + XUD_GetBuffer(ep_ctrl, ctrlBuffer, length); + failed |= (length != PKT_LENGTH_START); + + XUD_ClearStallByAddr(TEST_EP_NUM | 0x80); + + return failed; +} + + +#define BUFFER_SIZE 128 +unsigned test_ep(chanend c_ep_out, chanend c_ep_in, chanend c) +{ + uint32_t failed = 0; + uint8_t inBuffer[3][BUFFER_SIZE]; + unsigned length = PKT_LENGTH_START; + XUD_Result_t result; + unsigned x = 0; + + for(size_t i = 0; i < 3; i++) + { + for(size_t j = 0; j < length; j++) + { + inBuffer[i][j] = x++; + } + length++; + } + + length = PKT_LENGTH_START; + + XUD_ep ep_in = XUD_InitEp(c_ep_in); + XUD_SetStall(ep_in); + + c :> x; + + /* First test marking EP ready whilst halted + * Then subsequently marked un-halted - this should pause until un-halted */ + XUD_SetBuffer(ep_in, inBuffer[0], length++); + + /* Additional normal IN transaction */ + XUD_SetBuffer(ep_in, inBuffer[1], length++); + + c :> x; + + /* Next test EP marked ready then subsequently marked as halted */ + XUD_SetBuffer(ep_in, inBuffer[2], length); + + /* TODO not currently set */ + return failed; +} + +unsigned test_func(chanend c_ep_out[EP_COUNT_OUT], chanend c_ep_in[EP_COUNT_IN]) +{ + unsigned failedCtrl = 0; + unsigned failedEp = 0; + chan c; + + par + { + failedCtrl = test_ctrl(c_ep_out[CTRL_EP_NUM], c); + failedEp = test_ep(c_ep_out[TEST_EP_NUM], c_ep_in[TEST_EP_NUM], c); + } + + return failedCtrl | failedEp; +} + +#include "test_main.xc" diff --git a/tests/test_stall_epready.py b/tests/test_stall_epready_out.py similarity index 72% rename from tests/test_stall_epready.py rename to tests/test_stall_epready_out.py index a864d198..13309ae7 100644 --- a/tests/test_stall_epready.py +++ b/tests/test_stall_epready_out.py @@ -28,68 +28,84 @@ def test_session(ep, address, bus_speed): deviceAddress=address, endpointNumber=ep, endpointType="BULK", - direction="OUT", + transType="OUT", dataLength=pktLength, halted=True, ) ) + # Inform DUT to un-halt OUT EP via ctrl EP session.add_event( UsbTransaction( session, deviceAddress=address, - endpointNumber=ep, + endpointNumber=ep_ctrl, endpointType="BULK", - direction="OUT", + transType="OUT", dataLength=pktLength, - halted=True, ) ) + # Expect normal transaction on OUT EP session.add_event( UsbTransaction( session, deviceAddress=address, endpointNumber=ep, endpointType="BULK", - direction="IN", - halted=True, + transType="OUT", + dataLength=pktLength, ) ) + # ---- + + # Expect normal transaction on OUT EP session.add_event( UsbTransaction( session, deviceAddress=address, endpointNumber=ep, endpointType="BULK", - direction="IN", - halted=True, + transType="OUT", + dataLength=pktLength, ) ) - # Inform DUT to un halt EP's session.add_event( UsbTransaction( session, deviceAddress=address, endpointNumber=ep_ctrl, endpointType="BULK", - direction="OUT", + transType="OUT", dataLength=pktLength, + interEventDelay=500, ) ) - # Expect normal transactions - # DUT will exit after one normal transaction per EP. + # Expect EP to now be re-halted session.add_event( UsbTransaction( session, deviceAddress=address, endpointNumber=ep, endpointType="BULK", - direction="OUT", + transType="OUT", + dataLength=pktLength, + halted=True, + ) + ) + + session.add_event( + UsbTransaction( + session, + deviceAddress=address, + endpointNumber=ep_ctrl, + endpointType="BULK", + transType="OUT", dataLength=pktLength, + interEventDelay=500, ) ) @@ -99,7 +115,7 @@ def test_session(ep, address, bus_speed): deviceAddress=address, endpointNumber=ep, endpointType="BULK", - direction="IN", + transType="OUT", dataLength=pktLength, ) ) diff --git a/tests/test_stall_epready_out/Makefile b/tests/test_stall_epready_out/Makefile new file mode 100644 index 00000000..a2c9ee98 --- /dev/null +++ b/tests/test_stall_epready_out/Makefile @@ -0,0 +1,3 @@ +TEST_FLAGS = -DXUD_BYPASS_RESET=1 + +include ../test_makefile.mak diff --git a/tests/test_stall_epready_out/src/main.xc b/tests/test_stall_epready_out/src/main.xc new file mode 100644 index 00000000..ba85e424 --- /dev/null +++ b/tests/test_stall_epready_out/src/main.xc @@ -0,0 +1,101 @@ +// Copyright 2016-2021 XMOS LIMITED. +// This Software is subject to the terms of the XMOS Public Licence: Version 1. + + +#define EP_COUNT_OUT (6) +#define EP_COUNT_IN (6) + +#ifndef PKT_LENGTH_START +#define PKT_LENGTH_START (10) +#endif + +#ifndef TEST_EP_NUM +#define TEST_EP_NUM (1) +#endif + +#ifndef CTRL_EP_NUM +#define CTRL_EP_NUM (TEST_EP_NUM + 1) +#endif + +#include "shared.h" + +/* Endpoint type tables */ +XUD_EpType epTypeTableOut[EP_COUNT_OUT] = {XUD_EPTYPE_CTL, XUD_EPTYPE_BUL, XUD_EPTYPE_BUL, XUD_EPTYPE_BUL, XUD_EPTYPE_BUL, XUD_EPTYPE_BUL}; +XUD_EpType epTypeTableIn[EP_COUNT_IN] = {XUD_EPTYPE_CTL, XUD_EPTYPE_BUL, XUD_EPTYPE_BUL, XUD_EPTYPE_BUL, XUD_EPTYPE_BUL, XUD_EPTYPE_BUL}; + +unsigned test_ctrl(chanend c_ctrl, chanend c) +{ + uint8_t ctrlBuffer[128]; + unsigned length; + XUD_Result_t result; + uint32_t failed = 0; + + XUD_ep ep_ctrl = XUD_InitEp(c_ctrl); + + c <: 1; + + XUD_GetBuffer(ep_ctrl, ctrlBuffer, length); + failed |= (length != PKT_LENGTH_START); + + XUD_ClearStallByAddr(TEST_EP_NUM); + + c <: 1; + + XUD_GetBuffer(ep_ctrl, ctrlBuffer, length); + failed |= (length != PKT_LENGTH_START); + + XUD_SetStallByAddr(TEST_EP_NUM); + + XUD_GetBuffer(ep_ctrl, ctrlBuffer, length); + failed |= (length != PKT_LENGTH_START); + + XUD_ClearStallByAddr(TEST_EP_NUM); + + return failed; +} + +unsigned test_ep(chanend c_ep_out, chanend c) +{ + uint32_t failed = 0; + uint8_t outBuffer[128]; + unsigned length; + XUD_Result_t result; + unsigned x; + + XUD_ep ep_out = XUD_InitEp(c_ep_out); + XUD_SetStall(ep_out); + + c :> x; + + /* First test marking EP ready whilst halted + Then subsequently marked un-halted - this should pause until un-halted */ + XUD_GetBuffer(ep_out, outBuffer, length); + + /* Additional normal OUT transaction */ + XUD_GetBuffer(ep_out, outBuffer, length); + + c :> x; + + /* Next test EP marked ready then subsequently marked as halted */ + XUD_GetBuffer(ep_out, outBuffer, length); + + return failed; + +} + +unsigned test_func(chanend c_ep_out[EP_COUNT_OUT], chanend c_ep_in[EP_COUNT_IN]) +{ + unsigned failedCtrl = 0; + unsigned failedEp = 0; + chan c; + + par + { + failedCtrl = test_ctrl(c_ep_out[CTRL_EP_NUM], c); + failedEp = test_ep(c_ep_out[TEST_EP_NUM], c); + } + + return failedCtrl | failedEp; +} + +#include "test_main.xc" diff --git a/tests/test_suspend_resume.py b/tests/test_suspend_resume.py index 088d00be..0b260779 100644 --- a/tests/test_suspend_resume.py +++ b/tests/test_suspend_resume.py @@ -7,6 +7,7 @@ from usb_signalling import UsbSuspend, UsbResume from usb_session import UsbSession from usb_transaction import UsbTransaction +from usb_phy import USB_PKT_TIMINGS @pytest.fixture @@ -15,6 +16,8 @@ def test_session(ep, address, bus_speed): pktLength = 10 frameNumber = 52 # Note, for frame number 52 we expect A5 34 40 on the bus + interEventDelay = USB_PKT_TIMINGS["TX_TO_TX_PACKET_DELAY"] + session = UsbSession( bus_speed=bus_speed, run_enumeration=False, device_address=address ) @@ -25,7 +28,7 @@ def test_session(ep, address, bus_speed): deviceAddress=address, endpointNumber=ep, endpointType="BULK", - direction="OUT", + transType="OUT", dataLength=pktLength, interEventDelay=0, ) @@ -39,15 +42,16 @@ def test_session(ep, address, bus_speed): frameNumber = frameNumber + 1 pktLength = pktLength + 1 session.add_event(CreateSofToken(frameNumber, interEventDelay=2000)) + session.add_event( UsbTransaction( session, deviceAddress=address, endpointNumber=ep, endpointType="BULK", - direction="OUT", + transType="OUT", dataLength=pktLength, - interEventDelay=0, + interEventDelay=interEventDelay, ) ) diff --git a/tests/test_suspend_resume_invalidls.py b/tests/test_suspend_resume_invalidls.py index 47535be7..fda9f623 100644 --- a/tests/test_suspend_resume_invalidls.py +++ b/tests/test_suspend_resume_invalidls.py @@ -7,6 +7,7 @@ from usb_signalling import UsbSuspend, UsbResume from usb_session import UsbSession from usb_transaction import UsbTransaction +from usb_phy import USB_PKT_TIMINGS @pytest.fixture @@ -15,6 +16,8 @@ def test_session(ep, address, bus_speed): pktLength = 10 frameNumber = 52 # Note, for frame number 52 we expect A5 34 40 on the bus + interEventDelay = USB_PKT_TIMINGS["TX_TO_TX_PACKET_DELAY"] + session = UsbSession( bus_speed=bus_speed, run_enumeration=False, device_address=address ) @@ -25,7 +28,7 @@ def test_session(ep, address, bus_speed): deviceAddress=address, endpointNumber=ep, endpointType="BULK", - direction="OUT", + transType="OUT", dataLength=pktLength, interEventDelay=0, ) @@ -39,15 +42,16 @@ def test_session(ep, address, bus_speed): frameNumber = frameNumber + 1 pktLength = pktLength + 1 session.add_event(CreateSofToken(frameNumber, interEventDelay=2000)) + session.add_event( UsbTransaction( session, deviceAddress=address, endpointNumber=ep, endpointType="BULK", - direction="OUT", + transType="OUT", dataLength=pktLength, - interEventDelay=0, + interEventDelay=interEventDelay, ) ) diff --git a/tests/usb_clock.py b/tests/usb_clock.py index 8ecc4e8c..37c8d62f 100644 --- a/tests/usb_clock.py +++ b/tests/usb_clock.py @@ -7,12 +7,11 @@ class Clock(SimThread): CLK_60MHz = 0x0 - def __init__(self, port, clk, coreFreq_Mhz): + def __init__(self, port, clk): self._running = True self._clk = clk if clk == self.CLK_60MHz: - self._period = float(1000000000.0 / 60000000.0) - self._period *= (1.0 / coreFreq_Mhz) * 1000.0 + self._period_fs = 16666667 self._name = "60Mhz" else: raise ValueError("Unsupported Clock Frequency") @@ -25,21 +24,13 @@ def run(self): while True: - time += self._period / 2 + time += self._period_fs / 2 self.wait_until(time) self._val = 1 - self._val if self._running: self.xsi.drive_periph_pin(self._port, self._val) - @property - def period_ns(self): - return self._period - - @property - def period_us(self): - return self._period / 1000 - def is_high(self): return self._val == 1 diff --git a/tests/usb_event.py b/tests/usb_event.py index f5e3db5f..1896d7db 100644 --- a/tests/usb_event.py +++ b/tests/usb_event.py @@ -4,21 +4,14 @@ class UsbEvent(ABC): - def __init__(self, time=0, interEventDelay=None): + def __init__(self, time=0): self._time = time - self._interEventDelay = interEventDelay # TODO so we want to use relative delays or absolute times? @property def time(self): return self._time - # NOTE: its not always sensible for an event to used the IED - for example - # an Rx Packet - @property - def interEventDelay(self): - return self._interEventDelay - @abstractmethod def expected_output(self, bus_speed, offset=0): pass diff --git a/tests/usb_packet.py b/tests/usb_packet.py index e98c7803..a49b8c81 100644 --- a/tests/usb_packet.py +++ b/tests/usb_packet.py @@ -62,15 +62,16 @@ import usb_phy -USB_DATA_VALID_COUNT = {"FS": 39, "HS": 0} +USB_DATA_VALID_COUNT = {"FS": 40, "HS": 1} # In USB clocks # Pad delay not currently simulated in xsim for USB or OTP, so add this # delay here -RXA_END_DELAY = 2 -RXA_START_DELAY = 5 # Taken from RTL sim +RXA_END_DELAY = 0 # Taken from RTL sim +RXA_START_DELAY = {"FS": 1, "HS": 5} # Taken from RTL sim and UTMI spec 6.4.2 +# Note, will get muiltiplied by USB_DATA_VALID_COUNT before use -# TODO shoud we have a PID class? +# TODO should we have a PID class? # TODO remove the inverted check bits USB_PID = { "OUT": 0xE1, @@ -87,7 +88,12 @@ } -def CreateSofToken(frameNumber, badCrc=False, interEventDelay=1000): +def CreateSofToken( + frameNumber, + badCrc=False, + interEventDelay=usb_phy.USB_PKT_TIMINGS["TX_TO_TX_PACKET_DELAY"], +): + ep = (frameNumber >> 7) & 0xF address = (frameNumber) & 0x7F @@ -191,8 +197,7 @@ def __init__(self, **kwargs): self.data_bytes = kwargs.pop("data_bytes", None) self.num_data_bytes = kwargs.pop("length", 0) self.bad_crc = kwargs.pop("bad_crc", False) - ied = kwargs.pop("interEventDelay", None) - super().__init__(interEventDelay=ied) + super().__init__() @property def event_count(self): @@ -295,16 +300,16 @@ def drive(self, usb_phy, bus_speed): # Tx from host i.e. xCORE Rx class TxPacket(UsbPacket): def __init__(self, **kwargs): - self.rxa_start_delay = kwargs.pop("rxa_start_delay", 2) + self.rxa_start_delay = kwargs.pop("rxa_start_delay", RXA_START_DELAY) self.rxa_end_delay = kwargs.pop("rxa_end_delay", RXA_END_DELAY) self.rxe_assert_time = kwargs.pop("rxe_assert_time", 0) self.rxe_assert_length = kwargs.pop("rxe_assert_length", 1) - ied = kwargs.pop( + self.interEventDelay = kwargs.pop( "interEventDelay", usb_phy.USB_PKT_TIMINGS["TX_TO_TX_PACKET_DELAY"], ) - super().__init__(**kwargs, interEventDelay=ied) + super().__init__(**kwargs) def expected_output(self, bus_speed, offset=0): expected_output = "Packet:\tHOST -> DEVICE\n" @@ -320,8 +325,6 @@ def drive(self, usb_phy, bus_speed): if xsi.sample_port_pins(usb_phy._txv) == 1: print("ERROR: Unexpected packet from xCORE (TxPacket 0)") - rxv_count = USB_DATA_VALID_COUNT[bus_speed] - usb_phy.wait_for_clocks(self.interEventDelay) print( @@ -334,34 +337,49 @@ def drive(self, usb_phy, bus_speed): xsi.drive_periph_pin(usb_phy._rxa, 1) # Wait for RXA start delay - rxa_start_delay = RXA_START_DELAY + rxa_start_delay = (RXA_START_DELAY[bus_speed]) * USB_DATA_VALID_COUNT[bus_speed] - while rxa_start_delay != 0: + while rxa_start_delay > 1: wait(lambda x: usb_phy._clock.is_high()) wait(lambda x: usb_phy._clock.is_low()) rxa_start_delay = rxa_start_delay - 1 - for (i, byte) in enumerate(self.get_bytes(do_tokens=False)): + packetBytes = self.get_bytes(do_tokens=False) + + for (i, byte) in enumerate(packetBytes): + + rxv_count = USB_DATA_VALID_COUNT[bus_speed] # xCore should not be trying to send if we are trying to send.. if xsi.sample_port_pins(usb_phy._txv) == 1: print("ERROR: Unexpected packet from xCORE (TxPacket 1)") - wait(lambda x: usb_phy._clock.is_low()) - wait(lambda x: usb_phy._clock.is_high()) - wait(lambda x: usb_phy._clock.is_low()) - xsi.drive_periph_pin(usb_phy._rxdv, 1) xsi.drive_periph_pin(usb_phy._rxd, byte) if (self.rxe_assert_time != 0) and (self.rxe_assert_time == i): xsi.drive_periph_pin(usb_phy._rxer, 1) - while rxv_count != 0: + # Subtract 1 since we always drive for atleast one cycle.. + rxv_count -= 1 + + while rxv_count > USB_DATA_VALID_COUNT[bus_speed] // 2: wait(lambda x: usb_phy._clock.is_high()) wait(lambda x: usb_phy._clock.is_low()) - xsi.drive_periph_pin(usb_phy._rxdv, 0) rxv_count = rxv_count - 1 + # RxV high for 1 cycle + xsi.drive_periph_pin(usb_phy._rxdv, 1) + wait(lambda x: usb_phy._clock.is_high()) + wait(lambda x: usb_phy._clock.is_low()) + xsi.drive_periph_pin(usb_phy._rxdv, 0) + + # Don't delay on last byte (effects FS only) + if i < len(packetBytes) - 1: + while rxv_count > 0: + wait(lambda x: usb_phy._clock.is_high()) + wait(lambda x: usb_phy._clock.is_low()) + rxv_count = rxv_count - 1 + # xCore should not be trying to send if we are trying to send.. # We assume that the Phy internally blocks the TXValid signal # to the Transmit State Machine until the Rx packet has @@ -370,11 +388,9 @@ def drive(self, usb_phy, bus_speed): # if xsi.sample_port_pins(usb_phy._txv) == 1: # print("ERROR: Unexpected packet from xCORE (TxPacket 2)") - rxv_count = USB_DATA_VALID_COUNT[bus_speed] - # Wait for last byte - wait(lambda x: usb_phy._clock.is_high()) - wait(lambda x: usb_phy._clock.is_low()) + # wait(lambda x: usb_phy._clock.is_high()) + # wait(lambda x: usb_phy._clock.is_low()) xsi.drive_periph_pin(usb_phy._rxdv, 0) xsi.drive_periph_pin(usb_phy._rxer, 0) @@ -402,7 +418,7 @@ def get_bytes(self, do_tokens=False): if do_tokens: byte_list.append(self.pid) else: - byte_list.append(self.pid | ((~self.pid) << 4)) + byte_list.append(self.pid) # | ((~self.pid) << 4)) for b in self.data_bytes: byte_list.append(b) return byte_list @@ -425,7 +441,7 @@ def get_bytes(self, do_tokens=False): if do_tokens: byte_list.append(self.pid) else: - byte_list.append(self.pid | (((~self.pid) & 0xF) << 4)) + byte_list.append(self.pid) # | (((~self.pid) & 0xF) << 4)) packet_bytes = self.get_packet_bytes() for byte in packet_bytes: @@ -481,6 +497,7 @@ def __str__(self): # Always TX class TokenPacket(TxPacket): def __init__(self, **kwargs): + super().__init__(**kwargs) self.endpoint = kwargs.pop("endpoint", 0) self.valid = kwargs.pop("valid", 1) diff --git a/tests/usb_phy.py b/tests/usb_phy.py index faf21f29..31e1c2f5 100644 --- a/tests/usb_phy.py +++ b/tests/usb_phy.py @@ -56,11 +56,13 @@ USB_PKT_TIMINGS_TIGHT = { - "TX_TO_RX_PACKET_TIMEOUT": 14, # Timeout between sending DUT a packet + "TX_TO_RX_PACKET_TIMEOUT": 18, # Timeout between sending DUT a packet # and the expected response (in USB # clocks). This is SIE decision time in # UTMI spec - "TX_TO_TX_PACKET_DELAY": 4, # Delay between transmitting two packets + # TODO this needs reducing to 14! + "TX_TO_TX_PACKET_DELAY": 6, # Delay between transmitting two packets + # TODO this needs reducing to 4! } diff --git a/tests/usb_phy_utmi.py b/tests/usb_phy_utmi.py index 1644b5b2..28906572 100644 --- a/tests/usb_phy_utmi.py +++ b/tests/usb_phy_utmi.py @@ -17,7 +17,7 @@ def __init__( xcvrsel, termsel, clock, - initial_delay=64000, + initial_delay=140000000000, # in fs verbose=False, do_timeout=True, complete_fn=None, diff --git a/tests/usb_session.py b/tests/usb_session.py index 2e8cf1fa..30c104d1 100644 --- a/tests/usb_session.py +++ b/tests/usb_session.py @@ -87,25 +87,25 @@ def _pid_toggle(pid_table, n): def data_pid_in(self, n, togglePid=True, resetDataPid=False): if resetDataPid: - self._pidTable_in[n] = usb_packet.USB_PID["DATA1"] - pid = self._pidTable_in[n] - return pid + self._pidTable_in[n] = usb_packet.USB_PID["DATA0"] pid = self._pidTable_in[n] + if togglePid: self._pid_toggle(self._pidTable_in, n) + return pid def data_pid_out(self, n, togglePid=True, resetDataPid=False): if resetDataPid: - self._pidTable_out[n] = usb_packet.USB_PID["DATA1"] - pid = self._pidTable_out[n] - return pid + self._pidTable_out[n] = usb_packet.USB_PID["DATA0"] pid = self._pidTable_out[n] + if togglePid: self._pid_toggle(self._pidTable_out, n) + return pid def __str__(self): diff --git a/tests/usb_signalling.py b/tests/usb_signalling.py index afb671a1..5405739d 100644 --- a/tests/usb_signalling.py +++ b/tests/usb_signalling.py @@ -4,10 +4,13 @@ from usb_event import UsbEvent from usb_phy import USB_LINESTATE, USB_TIMINGS +TIMESTEP_TO_NS = 1000000 # fs to ns + class UsbDeviceAttach(UsbEvent): def __init__(self, interEventDelay=0): - super().__init__(interEventDelay=interEventDelay) + self.interEventDelay = interEventDelay + super().__init__() def __str__(self): return "DeviceAttach" @@ -26,11 +29,15 @@ def event_count(self): return 1 def drive(self, usb_phy, bus_speed): + def time(): + time = xsi.get_time() + return time / TIMESTEP_TO_NS + + def wait_until_ns(time): + usb_phy.wait_until(time * TIMESTEP_TO_NS) wait = usb_phy.wait - wait_until_ns = usb_phy.wait_until xsi = usb_phy.xsi - time = xsi.get_time print("DeviceAttach") tConnect_ns = time() @@ -190,7 +197,8 @@ def __init__( ): self._duration = duration self._glitches = glitches - super().__init__(interEventDelay=interEventDelay) + self.interEventDelay = interEventDelay + super().__init__() def expected_output(self, bus_speed, offset=0): expected_output = "RESUME\n" @@ -211,6 +219,10 @@ def event_count(self): return 1 def drive(self, usb_phy, bus_speed): + def get_time_ns(): + time = xsi.get_time() + return time / TIMESTEP_TO_NS + xsi = usb_phy.xsi wait = usb_phy.wait wait_for_clocks = usb_phy.wait_for_clocks @@ -219,7 +231,7 @@ def drive(self, usb_phy, bus_speed): if xsi.sample_port_pins(usb_phy._txv) == 1: print("ERROR: Unexpected packet from xCORE") - resumeStartTime_ns = xsi.get_time() + resumeStartTime_ns = get_time_ns() print("RESUME") @@ -236,7 +248,7 @@ def drive(self, usb_phy, bus_speed): wait_for_clocks(1) - currentTime_ns = xsi.get_time() + currentTime_ns = get_time_ns() if ( currentTime_ns >= (resumeStartTime_ns + glitchTime) @@ -255,7 +267,7 @@ def drive(self, usb_phy, bus_speed): while True: wait_for_clocks(1) - currentTime_ns = xsi.get_time() + currentTime_ns = get_time_ns() if currentTime_ns >= glitchTime + duration: break @@ -268,7 +280,7 @@ def drive(self, usb_phy, bus_speed): ): break - endResumeStartTime_ns = xsi.get_time() + endResumeStartTime_ns = get_time_ns() # Drive end of resume signalling xsi.drive_periph_pin(usb_phy._ls, USB_LINESTATE["IDLE"]) @@ -277,7 +289,7 @@ def drive(self, usb_phy, bus_speed): wait(lambda x: usb_phy._clock.is_high()) wait(lambda x: usb_phy._clock.is_low()) - currentTime_ns = xsi.get_time() + currentTime_ns = get_time_ns() if currentTime_ns >= endResumeStartTime_ns + ( USB_TIMINGS["RESUME_SE0_US"] * 1000 ): @@ -305,7 +317,8 @@ class UsbSuspend(UsbEvent): # clks? def __init__(self, duration_ns, interEventDelay=0): self._duration_ns = duration_ns - super().__init__(interEventDelay=interEventDelay) + self.interEventDelay = interEventDelay + super().__init__() def expected_output(self, bus_speed, offset=0): expected_output = "SUSPEND START. WAITING FOR DUT TO ENTER FS\n" @@ -321,6 +334,9 @@ def event_count(self): return 1 def drive(self, usb_phy, bus_speed): + def get_time_ns(): + time = xsi.get_time() + return time / TIMESTEP_TO_NS xsi = usb_phy.xsi wait = usb_phy.wait @@ -329,7 +345,7 @@ def drive(self, usb_phy, bus_speed): if xsi.sample_port_pins(usb_phy._txv) == 1: print("ERROR: Unexpected packet from xCORE") - suspendStartTime_ns = xsi.get_time() + suspendStartTime_ns = get_time_ns() # print("SUSPEND START TIME: " + str(suspendStartTime_ns)) assert self.interEventDelay == 0 @@ -355,7 +371,7 @@ def drive(self, usb_phy, bus_speed): # Wait for DUT to move into FS mode if xcvr == 1 and termsel == 1: - fsTime_ns = xsi.get_time() + fsTime_ns = get_time_ns() timeToFs_ns = fsTime_ns - suspendStartTime_ns # print("DEVICE ENTERED FS AT TIME " + str(fsTime_ns/1000) + "(after " + str(timeToFs_ns/1000) +" uS)") # noqa F401 print("DEVICE ENTERED FS MODE") @@ -368,7 +384,7 @@ def drive(self, usb_phy, bus_speed): xsi.drive_periph_pin(usb_phy._ls, USB_LINESTATE["FS_J"]) break - time_ns = xsi.get_time() - suspendStartTime_ns + time_ns = get_time_ns() - suspendStartTime_ns if time_ns > (USB_TIMINGS["IDLE_TO_FS_MAX_US"] * 1000): print("ERROR: DUT DID NOT ENTER FS MODE IN TIME") @@ -389,7 +405,7 @@ def drive(self, usb_phy, bus_speed): if not (xcvr == 1 and termsel == 1): print("ERROR: DUT moved out of FS mode unexpectly during suspend") - time_ns = xsi.get_time() - suspendStartTime_ns + time_ns = get_time_ns() - suspendStartTime_ns if time_ns >= self._duration_ns: print("SUSPEND END") break diff --git a/tests/usb_transaction.py b/tests/usb_transaction.py index 003b3dec..2a8df1bf 100644 --- a/tests/usb_transaction.py +++ b/tests/usb_transaction.py @@ -9,15 +9,15 @@ RxHandshakePacket, RxDataPacket, TxHandshakePacket, + USB_DATA_VALID_COUNT, ) -from usb_packet import USB_DATA_VALID_COUNT +from usb_phy import USB_PKT_TIMINGS INTER_TRANSACTION_DELAY = 500 -USB_DIRECTIONS = ["OUT", "IN"] +USB_TRANS_TYPES = ["OUT", "IN", "SETUP"] USB_EP_TYPES = ["CONTROL", "BULK", "ISO", "INTERRUPT"] - # TODO UsbTransaction_IN and UsbTransaction_OUT class UsbTransaction(UsbEvent): def __init__( @@ -26,7 +26,7 @@ def __init__( deviceAddress=0, endpointNumber=0, endpointType="BULK", - direction="OUT", + transType="OUT", bus_speed="HS", eventTime=0, dataLength=0, @@ -36,12 +36,12 @@ def __init__( rxeAssertDelay_data=0, halted=False, resetDataPid=False, - ): # TODO Enums when we move to py3 + ): self._deviceAddress = deviceAddress self._endpointNumber = endpointNumber self._endpointType = endpointType - self._direction = direction + self._transType = transType self._datalength = dataLength self._bus_speed = bus_speed self._badDataCrc = badDataCrc @@ -49,20 +49,20 @@ def __init__( self._halted = halted assert endpointType in USB_EP_TYPES - assert direction in USB_DIRECTIONS + assert transType in USB_TRANS_TYPES # Populate packet list for a (valid) transaction self._packets = [] # TODO would it be better to generate packets on the fly in drive() # rather than create a packet list? - if direction == "OUT": + if transType in ["OUT", "SETUP"]: packets = [] packets.append( TokenPacket( interEventDelay=interEventDelay, - pid=USB_PID["OUT"], + pid=USB_PID[transType], address=self._deviceAddress, endpoint=self._endpointNumber, data_valid_count=self.data_valid_count, @@ -80,6 +80,9 @@ def __init__( else: togglePid = True + if halted: + resetDataPid = True + expectHandshake = ( (not self._badDataCrc) and (not self._rxeAssertDelay_data) @@ -97,9 +100,20 @@ def __init__( endpointNumber, dataLength, resend=resend ) - pid = session.data_pid_out( - endpointNumber, togglePid=togglePid, resetDataPid=resetDataPid - ) + # Reset data PID's on SETUP transaction + if transType == "SETUP": + pid = session.data_pid_out( + endpointNumber, togglePid=True, resetDataPid=True + ) + + # If SETUP trans then we need to reset and toggle the corresponding IN EP's PID also + in_pid = session.data_pid_in( + endpointNumber, togglePid=True, resetDataPid=True + ) + else: + pid = session.data_pid_out( + endpointNumber, togglePid=togglePid, resetDataPid=resetDataPid + ) # Add data packet to packets list packets.append( @@ -135,12 +149,18 @@ def __init__( self._badDataCrc or self._rxeAssertDelay_data or self._endpointType == "ISO" + or halted ): togglePid = False else: togglePid = True - pid = session.data_pid_in(endpointNumber, togglePid=togglePid) + if halted: + resetDataPid = True + + pid = session.data_pid_in( + endpointNumber, togglePid=togglePid, resetDataPid=resetDataPid + ) # Add data packet to packets list if not halted: @@ -154,7 +174,7 @@ def __init__( if halted: self._packets.append(RxHandshakePacket(pid=USB_PID["STALL"])) - super().__init__(time=eventTime, interEventDelay=interEventDelay) + super().__init__(time=eventTime) # TODO ideally USBTransaction doesnt know about data_valid_count @property