diff --git a/.gitignore b/.gitignore index e0379411..ae69db1d 100644 --- a/.gitignore +++ b/.gitignore @@ -30,6 +30,8 @@ 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 **/venv/** diff --git a/CHANGELOG.rst b/CHANGELOG.rst index e57ab8b5..b34c7fd6 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,27 +1,38 @@ lib_xud Change Log ================== +2.0.1 +----- + + * CHANGE: Shared test code moved to test_support repo + * CHANGE: Clock-blocks 4 & 5 now used (was 2 & 3) + * CHANGE: Most differences required to support different architectures are + now handled in a Hardware Abstraction Layer + * RESOLVED: Intermittent enumeration issues at full-speed on XS3A based + devices (#259) + 2.0.0 ----- * ADDED: Initial support for XS3A based devices - * ADDED: Requirement to define XUD_CORE_CLOCK with xcore core clock speed + * ADDED: Requirement to define XUD_CORE_CLOCK with xCORE core clock speed in MHz * CHANGE: Removed support for XS1-G, and XS1-L (including U series) based devices * RESOLVED: Exception when Endpoint marked as disabled - * CHANGE: Use common XN files for tests + * RESOLVED: A halted endpoint does not issue a STALL when PINGed (#59) + * RESOLVED: A halted endpoint does not issue a STALL if the endpoint is + marked ready (#58) 1.2.0 ----- - * CHANGED: Use XMOS Public Licence Version 1 + * CHANGE: Use XMOS Public Licence Version 1 1.1.2 ----- - * CHANGED: Pin Python package versions - * REMOVED: not necessary cpanfile + * CHANGE: Python package pinned to versions 1.1.1 ----- @@ -38,7 +49,7 @@ lib_xud Change Log 1.0.0 ----- - * CHANGE: Version for first major release. + * CHANGE: First major release. 0.2.0 ----- diff --git a/README.rst b/README.rst index 179fc779..b815cd4a 100644 --- a/README.rst +++ b/README.rst @@ -23,8 +23,8 @@ Features Known Issues ............ - * Operation on XS3 based devices only supported at 700MHz * SOF tokens are not CRC checked on XS3 based devices (see tests/test_sof_badcrc) + * Documentation not updated for removal of XS1 and addition of XS3 based devices Software version and dependencies ................................. diff --git a/examples/AN00129_hid_class/Makefile b/examples/AN00129_hid_class/Makefile index e8effa65..a5c8c121 100644 --- a/examples/AN00129_hid_class/Makefile +++ b/examples/AN00129_hid_class/Makefile @@ -14,7 +14,7 @@ APP_NAME = app_hid_mouse_demo # These flags define two build configurations - one for xCORE-200 and one for # the xCORE.AI series. -BUILD_FLAGS = -O3 -report +BUILD_FLAGS = -O3 -report -fxscope XCC_FLAGS_200 = $(BUILD_FLAGS) -DXUD_CORE_CLOCK=500 XCC_FLAGS_AI = $(BUILD_FLAGS) -DXUD_CORE_CLOCK=600 diff --git a/examples/AN00129_hid_class/src/XCORE-AI-EXPLORER-NO-DDR.xn b/examples/AN00129_hid_class/src/XCORE-AI-EXPLORER-NO-DDR.xn deleted file mode 100644 index b39d5abe..00000000 --- a/examples/AN00129_hid_class/src/XCORE-AI-EXPLORER-NO-DDR.xn +++ /dev/null @@ -1,60 +0,0 @@ - - - Board - xcore.ai Explorer Kit - - - tileref tile[2] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/AN00129_hid_class/src/XCORE-AI-EXPLORER.xn b/examples/AN00129_hid_class/src/XCORE-AI-EXPLORER.xn deleted file mode 100644 index 0cc287dd..00000000 --- a/examples/AN00129_hid_class/src/XCORE-AI-EXPLORER.xn +++ /dev/null @@ -1,60 +0,0 @@ - - - Board - xcore.ai Explorer Kit - - - tileref tile[2] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/lib_xud/module_build_info b/lib_xud/module_build_info index a089bc44..c84082d9 100644 --- a/lib_xud/module_build_info +++ b/lib_xud/module_build_info @@ -1,4 +1,4 @@ -VERSION = 2.0.0 +VERSION = 2.0.1 MODULE_XCC_FLAGS = $(XCC_FLAGS) \ -O3 \ diff --git a/lib_xud/src/core/XUD_HAL.h b/lib_xud/src/core/XUD_HAL.h index af6ecbc1..d6e38f28 100644 --- a/lib_xud/src/core/XUD_HAL.h +++ b/lib_xud/src/core/XUD_HAL.h @@ -13,7 +13,7 @@ #ifdef __XS3A__ #include -// TODO should be properlty in HAL +// TODO should be properly in HAL unsigned XtlSelFromMhz(unsigned m); #else #include "XUD_USBTile_Support.h" @@ -23,19 +23,24 @@ unsigned XtlSelFromMhz(unsigned m); /** * \enum XUD_LineState_t - * \brief USB Line States + * \brief USB Line States */ typedef enum XUD_LineState_t { XUD_LINESTATE_SE0 = 0, /**< SE0 State */ - XUD_LINESTATE_J = 1, /**< J State */ - XUD_LINESTATE_K = 2, /**< K State */ - XUD_LINESTATE_SE1 = 3 /**< Invalid bus state both lines high **/ + XUD_LINESTATE_HS_J_FS_K = 1,/**< J/K State */ + XUD_LINESTATE_HS_K_FS_J = 2,/**< K/J State */ + XUD_LINESTATE_SE1 = 3 /**< Invalid bus state - both lines high **/ } XUD_LineState_t; void XUD_HAL_EnterMode_PeripheralChirp(); void XUD_HAL_EnterMode_PeripheralFullSpeed(); void XUD_HAL_EnterMode_PeripheralHighSpeed(); +#ifdef __XS2A__ +/* Special case for __XS2A__ where writing to USB register is relatively slow */ +void XUD_HAL_EnterMode_PeripheralHighSpeed_Start(); +void XUD_HAL_EnterMode_PeripheralHighSpeed_Complete(); +#endif void XUD_HAL_EnterMode_PeripheralTestJTestK(); void XUD_HAL_EnterMode_TristateDrivers(); @@ -43,7 +48,7 @@ void XUD_HAL_EnterMode_TristateDrivers(); * \brief Get current linestate status * \return XUD_LineState_t representing current line status **/ -XUD_LineState_t XUD_HAL_GetLineState(/*XUD_HAL_t &xudHal*/); +XUD_LineState_t XUD_HAL_GetLineState(); /** * \brief Wait for a change in linestate and return, or timeout @@ -58,7 +63,7 @@ unsigned XUD_HAL_WaitForLineStateChange(XUD_LineState_t ¤tLs, unsigned tim * * TODO Should this be combined with EnterMode_PeripheralChirp()? **/ -void XUD_HAL_Mode_PowerSig(); +void XUD_HAL_Mode_Signalling(); /** * \brief HAL function to set xCORE into data transfer mode diff --git a/lib_xud/src/core/XUD_HAL.xc b/lib_xud/src/core/XUD_HAL.xc index 8865167b..d878e000 100644 --- a/lib_xud/src/core/XUD_HAL.xc +++ b/lib_xud/src/core/XUD_HAL.xc @@ -9,6 +9,7 @@ #ifdef __XS2A__ #include "xs1_to_glx.h" #include "xs2_su_registers.h" +#include "XUD_USBTile_Support.h" extern in port flag0_port; extern in port flag1_port; extern in port flag2_port; @@ -125,7 +126,10 @@ void XUD_HAL_EnableUsb(unsigned pwrConfig) void XUD_HAL_EnterMode_PeripheralFullSpeed() { -#ifdef __XS3A__ +#ifdef __XS2A__ + write_periph_word(USB_TILE_REF, XS1_SU_PER_UIFM_CHANEND_NUM, XS1_SU_PER_UIFM_FUNC_CONTROL_NUM, + (1< dp;//flag1 - dm_port :> dm;//flag0 - return LinesToLineState(dp, dm); -#else +#ifdef __XS2A__ unsigned j, k, se0; flag0_port :> j; flag1_port :> k; flag2_port :> se0; if(j) - return XUD_LINESTATE_J; + return XUD_LINESTATE_HS_J_FS_K; if(k) - return XUD_LINESTATE_K; + return XUD_LINESTATE_HS_K_FS_J; if(se0) return XUD_LINESTATE_SE0; return XUD_LINESTATE_SE1; +#else + unsigned dp, dm; + dp_port :> dp; + dm_port :> dm; + return LinesToLineState(dp, dm); #endif } +// TODO debounce? unsigned XUD_HAL_WaitForLineStateChange(XUD_LineState_t ¤tLs, unsigned timeout) { -#ifdef __XS3A__ - unsigned dp, dm; - timer t; unsigned time; + timer t; + + if (timeout != null) + t :> time; + +#ifdef XS2A + unsigned se0 = currentLs == XUD_LINESTATE_SE0; + unsigned j = currentLs == XUD_LINESTATE_HS_J_FS_K; + unsigned k = currentLs == XUD_LINESTATE_HS_K_FS_J; + + /* Wait for a change on any flag port */ + select + { + case flag0_port when pinsneq(j) :> void: + break; + case flag1_port when pinsneq(k) :> void: + break; + case flag2_port when pinsneq(se0) :> void: + break; + case timeout != null => t when timerafter(time + timeout) :> int _: + return 1; + } + + /* Read current line state - two lines may have change e.g k/j to SE0 */ + currentLs = XUD_HAL_GetLineState(); + return 0; +#else + unsigned dp, dm; /* Look up line values from linestate */ {dp, dm} = LineStateToLines(currentLs); - if (timeout != null) - t :> time; - /* Wait for change */ select { @@ -369,25 +413,20 @@ unsigned XUD_HAL_WaitForLineStateChange(XUD_LineState_t ¤tLs, unsigned tim break; case timeout != null => t when timerafter(time + timeout) :> int _: return 1; - } /* Return new linestate */ currentLs = LinesToLineState(dp, dm); return 0; -#else - //TODO XUD_HAL_WaitForLineStateChange() not implemented for XS2 - //Note, this is not currently used for XS2 - return 1; #endif } void XUD_HAL_SetDeviceAddress(unsigned char address) { -#ifdef __XS3A__ - XUD_SetCrcTableAddr(address); -#else +#ifdef __XS2A__ write_periph_word(USB_TILE_REF, XS1_SU_PER_UIFM_CHANEND_NUM, XS1_SU_PER_UIFM_DEVICE_ADDRESS_NUM, address); +#else + XUD_SetCrcTableAddr(address); #endif } diff --git a/lib_xud/src/core/XUD_Main.xc b/lib_xud/src/core/XUD_Main.xc index 09318418..95b0c0c3 100755 --- a/lib_xud/src/core/XUD_Main.xc +++ b/lib_xud/src/core/XUD_Main.xc @@ -6,15 +6,6 @@ * @brief XMOS USB Device (XUD) Layer * @author Ross Owen **/ -/* Error printing functions */ -#ifdef XUD_DEBUG_VERSION -void XUD_Error(char errString[]); -void XUD_Error_hex(char errString[], int i_err); -#else -#define XUD_Error(a) /* */ -#define XUD_Error_hex(a, b) /* */ -#endif - #include #include #include @@ -65,8 +56,8 @@ out port tx_readyout = PORT_USB_TX_READYOUT; in port tx_readyin = PORT_USB_TX_READYIN; in port rx_rdy = PORT_USB_RX_READY; -on USB_TILE: clock tx_usb_clk = XS1_CLKBLK_2; -on USB_TILE: clock rx_usb_clk = XS1_CLKBLK_3; +on USB_TILE: clock tx_usb_clk = XS1_CLKBLK_4; +on USB_TILE: clock rx_usb_clk = XS1_CLKBLK_5; XUD_chan epChans[USB_MAX_NUM_EP]; XUD_chan epChans0[USB_MAX_NUM_EP]; @@ -102,15 +93,14 @@ 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]; -unsigned g_stallTable_IN[USB_MAX_NUM_EP_IN] = {0}; -unsigned handshakeTable_OUT[USB_MAX_NUM_EP_OUT]; +unsigned handshakeTable_IN[USB_MAX_NUM_EP_IN] = {0}; // 0 or STALL +unsigned handshakeTable_OUT[USB_MAX_NUM_EP_OUT]; // NAK or STALL unsigned sentReset=0; unsigned crcmask = 0b11111111111; unsigned chanArray; -#define RESET_TIME_us 5 // 5us +#define RESET_TIME_us (5) #define RESET_TIME (RESET_TIME_us * REF_CLK_FREQ) #if (XUD_OPT_SOFTCRC5 == 1) @@ -180,28 +170,48 @@ static int XUD_Manager_loop(XUD_chan epChans0[], XUD_chan epChans[], chanend ?c set_port_use_on(flag0_port); set_port_use_on(flag1_port); #if defined(__XS2A__) + /* Extra flag port in XS2 */ set_port_use_on(flag2_port); #endif #if defined(__XS3A__) + #ifndef XUD_CORE_CLOCK #error XUD_CORE_CLOCK not defined (in MHz) #endif - #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 + + #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 + #endif + #else + #if (XUD_CORE_CLOCK >= 600) + #define RX_RISE_DELAY 1 + #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 + #define TX_RISE_DELAY 1 + #define TX_FALL_DELAY 1 + #else + #error XUD_CORE_CLOCK must be >= 500 + #endif #endif #else #define RX_RISE_DELAY 5 @@ -209,19 +219,14 @@ static int XUD_Manager_loop(XUD_chan epChans0[], XUD_chan epChans[], chanend ?c #define TX_RISE_DELAY 5 #define TX_FALL_DELAY 1 #endif - - // Set up USB ports. Done in ASM as read port used in both directions initially. - // Main difference from xevious is IFM not enabled. - // GLX_UIFM_PortConfig (p_usb_clk, txd, rxd, flag0_port, flag1_port, flag2_port); - // Xevious needed asm as non-standard usage (to avoid clogging 1-bit ports) - // GLX uses 1bit ports so shouldn't be needed. + // Handshaken ports need USB clock configure_clock_src(tx_usb_clk, p_usb_clk); configure_clock_src(rx_usb_clk, p_usb_clk); - //this along with the following delays forces the clock - //to the ports to be effectively controlled by the - //previous usb clock edges + // This, along with the following delays, forces the clock + // to the ports to be effectively controlled by the + // previous usb clock edges set_port_inv(p_usb_clk); set_port_sample_delay(p_usb_clk); @@ -285,10 +290,9 @@ static int XUD_Manager_loop(XUD_chan epChans0[], XUD_chan epChans[], chanend ?c /* Go into full speed mode: XcvrSelect and Term Select (and suspend) high */ XUD_HAL_EnterMode_PeripheralFullSpeed(); - - + /* Setup flags for power signalling - i.e. J/K/SE0 line state*/ - XUD_HAL_Mode_PowerSig(); + XUD_HAL_Mode_Signalling(); if (one) { @@ -487,7 +491,7 @@ int XUD_Main(chanend c_ep_out[], int noEpOut, for(int i = 0; i < USB_MAX_NUM_EP_IN; i++) { - handshakeTable_IN[i] = USB_PIDn_NAK; + 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; } @@ -559,7 +563,7 @@ int XUD_Main(chanend c_ep_out[], int noEpOut, /* Check for control on IN/OUT 0 */ if(epTypeTableOut[0] != XUD_EPTYPE_CTL || epTypeTableIn[0] != XUD_EPTYPE_CTL) { - XUD_Error("XUD_Manager: Ep 0 must be control for IN and OUT"); + __builtin_trap(); } #if 0 @@ -590,94 +594,3 @@ int XUD_Main(chanend c_ep_out[], int noEpOut, return 0; } - -/* Various messages for error cases */ -void ERR_BadToken() -{ -#ifdef XUD_DEBUG_VERSION - printstrln("BAD TOKEN RECEVED"); -#endif -} - -void ERR_BadCrc(unsigned a, unsigned b) -{ - while(1); -} - -void ERR_SetupBuffFull() -{ -#ifdef XUD_DEBUG_VERSION - printstrln("SETUP BUFFER FULL"); -#endif -} - -void ERR_UnsupportedToken(unsigned x) -{ -#ifdef XUD_DEBUG_VERSION - printstr("UNSUPPORTED TOKEN: "); - printhexln(x); -#endif -} - -void ERR_BadTxHandshake(unsigned x) -{ -#ifdef XUD_DEBUG_VERSION - printstr("BAD TX HANDSHAKE: "); - printhexln(x); -#endif -} - -void ERR_GotSplit() -{ -#ifdef XUD_DEBUG_VERSION - printstrln("ERR: Got a split"); -#endif -} - -void ERR_TxHandshakeTimeout() -{ -#ifdef XUD_DEBUG_VERSION - printstrln("WARNING: TX HANDSHAKE TIMEOUT"); - while(1); -#endif -} - -void ERR_OutDataTimeout() -{ -#ifdef XUD_DEBUG_VERSION - printstrln("ERR: Out data timeout"); -#endif -} - -void ERR_EndIn4() -{ -#ifdef XUD_DEBUG_VERSION - printstrln("ERR: Endin4"); - while(1); - -#endif -} - -void ERR_EndIn5(int x) -{ -#ifdef XUD_DEBUG_VERSION - printhex(x); - printstrln(" ERR: Endin5"); - while(1); -#endif -} - -void ResetDetected(int x) -{ -#ifdef XUD_DEBUG_VERSION - printint(x); - printstr(" rrrreeeset\n"); -#endif -} - -void SuspendDetected() -{ -#ifdef XUD_DEBUG_VERSION - printstr("Suspend!\n"); -#endif -} diff --git a/lib_xud/src/core/XUD_Signalling.xc b/lib_xud/src/core/XUD_Signalling.xc index 736922c2..13aa2d14 100755 --- a/lib_xud/src/core/XUD_Signalling.xc +++ b/lib_xud/src/core/XUD_Signalling.xc @@ -17,19 +17,9 @@ #define T_FILTSE0 250 #ifndef SUSPEND_VBUS_POLL_TIMER_TICKS -#define SUSPEND_VBUS_POLL_TIMER_TICKS 500000 +#define SUSPEND_VBUS_POLL_TIMER_TICKS (500000) #endif -extern buffered in port:32 p_usb_clk; -extern in port reg_read_port; -extern in port flag0_port; -extern in port flag1_port; - -extern in port flag2_port; - -extern out port p_usb_txd; -extern in buffered port:32 p_usb_rxd; - extern unsigned g_curSpeed; int XUD_Init() @@ -37,12 +27,11 @@ int XUD_Init() /* Wait for host */ while (1) { -#ifdef __XS3A__ XUD_LineState_t currentLs = XUD_HAL_GetLineState(); - + switch (currentLs) { - + /* SE0 State */ case XUD_LINESTATE_SE0: unsigned timedOut = XUD_HAL_WaitForLineStateChange(currentLs, T_WTRSTFS); @@ -54,9 +43,10 @@ int XUD_Init() /* Otherwise SE0 went away.. keep looking */ break; - case XUD_LINESTATE_J: + /* J State */ + case XUD_LINESTATE_HS_K_FS_J: - unsigned timedOut = XUD_HAL_WaitForLineStateChange(currentLs, STATE_START_TO); + unsigned timedOut = XUD_HAL_WaitForLineStateChange(currentLs, STATE_START_TO); /* If no change in LS then return 0 for suspend */ if(timedOut) @@ -69,155 +59,46 @@ int XUD_Init() /* Shouldn't expect to get here, but ignore anyway */ break; } - -#else - timer SE0_timer; - unsigned SE0_start_time = 0; - - select - { - /* SE0 State */ - case flag2_port when pinseq(1) :> void: - SE0_timer :> SE0_start_time; - select - { - case flag2_port when pinseq(0) :> void: - break; - - case SE0_timer when timerafter(SE0_start_time + T_WTRSTFS) :> int: - return 1; - break; - } - break; - - /* J State */ - case flag0_port when pinseq(1) :> void: - SE0_timer :> SE0_start_time; - select - { - case flag0_port when pinseq(0) :> void: - break; - - case SE0_timer when timerafter(SE0_start_time + STATE_START_TO) :> int: - return 0; - break; - } - break; - } -#endif } __builtin_trap(); return -1; } - -#ifndef __XS3A__ /** XUD_Suspend * @brief Function called when device is suspended. This should include any clock down code etc. - * @return True if reset detected during resume */ -int XUD_Suspend(XUD_PwrConfig pwrConfig) -{ - timer t; - unsigned time; - - while (1) - { - t :> time; - - // linestate is K on flag0 (inverted), J on flag1, SE0 on flag2 - // note that if you look in device-attach function, high-speed chirps are opposite polarity - // that is chirp K on flag1 and chirp J on flag0 (inverted) - select - { - case (pwrConfig == XUD_PWR_SELF) => t when timerafter(time + SUSPEND_VBUS_POLL_TIMER_TICKS) :> void: - if(!XUD_HAL_GetVBusState()) - { - // VBUS not valid - write_periph_word(USB_TILE_REF, XS1_SU_PER_UIFM_CHANEND_NUM, XS1_SU_PER_UIFM_FUNC_CONTROL_NUM, 4 /* OpMode 01 */); - return -1; - } - break; - - // SE0, that looks like a reset - case flag2_port when pinseq(1) :> void: - t :> time; - select - { - case flag2_port when pinseq(0) :> void: - // SE0 gone away, keep looping - break; - - case t when timerafter(time + T_FILTSE0) :> void: - // consider 2.5ms a complete reset - t :> time; - t when timerafter(time + 250000) :> void; - return 1; - } - break; - - // K, start of resume - case flag0_port when pinseq(1) :> void: - // TODO debounce? - unsafe chanend c; - asm("getr %0, 2" : "=r"(c)); // XS1_RES_TYPE_CHANEND=2 (no inline assembly immediate operands in xC) - - if (g_curSpeed == XUD_SPEED_HS) - { - // start high-speed switch so it's completed as quickly as possible after end of resume is seen - unsafe { - write_periph_word_two_part_start((chanend)c, USB_TILE_REF, XS1_SU_PER_UIFM_CHANEND_NUM, XS1_SU_PER_UIFM_FUNC_CONTROL_NUM, 0); - } - } - - select - { - // J, unexpected, return - case flag1_port when pinseq(1) :> void: - // we have to complete the high-speed switch now - // revert to full speed straight away - causes a blip on the bus - // Note, switching to HS then back to FS is not ideal - if (g_curSpeed == XUD_SPEED_HS) - { - unsafe { - write_periph_word_two_part_end((chanend)c, 0); - } - } - write_periph_word(USB_TILE_REF, XS1_SU_PER_UIFM_CHANEND_NUM, XS1_SU_PER_UIFM_FUNC_CONTROL_NUM, (1 << XS1_SU_UIFM_FUNC_CONTROL_XCVRSELECT_SHIFT) | (1 << XS1_SU_UIFM_FUNC_CONTROL_TERMSELECT_SHIFT)); - break; - - // SE0, end of resume - case flag2_port when pinseq(1) :> void: - if (g_curSpeed == XUD_SPEED_HS) - { - // complete the high-speed switch - unsafe { - write_periph_word_two_part_end((chanend)c, 0); - } - } - break; - } - - asm("freer res[%0]" :: "r"(c)); - return 0; - } - } - __builtin_trap(); - return -1; -} - -#else + * @return non-zero if reset detected during resume */ int XUD_Suspend(XUD_PwrConfig pwrConfig) { timer t; unsigned time; - XUD_LineState_t currentLs = XUD_LINESTATE_J; + XUD_LineState_t currentLs = XUD_LINESTATE_HS_K_FS_J; while(1) { - unsigned timedOut = XUD_HAL_WaitForLineStateChange(currentLs, 0); + unsigned timeOutTime = 0; + + if(pwrConfig == XUD_PWR_SELF) + timeOutTime = SUSPEND_VBUS_POLL_TIMER_TICKS; + + unsigned timedOut = XUD_HAL_WaitForLineStateChange(currentLs, timeOutTime); + if(timedOut) + { + if(!XUD_HAL_GetVBusState()) + { + /* VBUS not valid */ + XUD_HAL_EnterMode_TristateDrivers(); + return -1; + } + else + { + /* VBUS still valid, keep looking for LS change */ + continue; + } + } + switch(currentLs) { /* Reset signalliung */ @@ -240,37 +121,60 @@ int XUD_Suspend(XUD_PwrConfig pwrConfig) break; /* K, start of resume */ - case XUD_LINESTATE_K: - - /* TODO debounce? */ - XUD_HAL_WaitForLineStateChange(currentLs, 0); - - switch(currentLs) + case XUD_LINESTATE_HS_J_FS_K: +#ifdef __XS2A__ + if (g_curSpeed == XUD_SPEED_HS) { - /* SE0, end of resume */ - case XUD_LINESTATE_SE0: - if (g_curSpeed == XUD_SPEED_HS) - { - /* Move back into high-speed mode - Notes, writes to XS3A registers orders of magnitude faster than XS2A */ - XUD_HAL_EnterMode_PeripheralHighSpeed(); + /* Special case for XS2A - start high-speed switch so it is completed as soon as possible after end of resume is seen */ + XUD_HAL_EnterMode_PeripheralHighSpeed_Start(); + } +#endif + while(1) + { + XUD_HAL_WaitForLineStateChange(currentLs, 0); + + switch(currentLs) + { + /* J, unexpected, return */ + case XUD_LINESTATE_HS_K_FS_J: +#ifdef __XS2A__ + /* For XS2 we have to complete the high-speed switch now, since we started it already.. + we then revert to full speed straight away - causes a blip on the bus, non-ideal */ + if (g_curSpeed == XUD_SPEED_HS) + { + unsafe + { + XUD_HAL_EnterMode_PeripheralHighSpeed_Complete(); + } + } + + XUD_HAL_EnterMode_PeripheralFullSpeed(); +#endif + return 0; + /* SE0, end of resume */ + case XUD_LINESTATE_SE0: + if (g_curSpeed == XUD_SPEED_HS) + { +#ifdef __XS2A__ + /* For XS2 we now have to complete the switch back to high-speed */ + XUD_HAL_EnterMode_PeripheralHighSpeed_Complete(); +#else + /* Move back into high-speed mode - Notes, writes to XS3A registers orders of magnitude faster than XS2A */ + XUD_HAL_EnterMode_PeripheralHighSpeed(); +#endif + } /* Return 0 for resumed */ return 0; - } - break; - /* J, unexpected, return to suspend.. */ - case XUD_LINESTATE_J: - default: - break; + default: + // Keep looping + break; + } } - break; - - case XUD_LINESTATE_J: - default: - /* Do nothing */ - break; - } + + break; + } } } -#endif + diff --git a/lib_xud/src/core/XUD_TokenJmp.S b/lib_xud/src/core/XUD_TokenJmp.S index 19fb0507..c04387bb 100644 --- a/lib_xud/src/core/XUD_TokenJmp.S +++ b/lib_xud/src/core/XUD_TokenJmp.S @@ -2,7 +2,7 @@ // This Software is subject to the terms of the XMOS Public Licence: Version 1. #ifndef __XS3A__ - ldaw r10, dp[PidJumpTable] // TODO Could load from sp here + ldaw r10, dp[PidJumpTable] // TODO Could load from sp here // We receive: | 0000 4-bit EP | 0000 4-bit PID | inpw r11, res[RXD], 8 // Read 8 bit PID shr r11, r11, 24 // Shift off junk 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 846ceda6..965515f4 100755 --- a/lib_xud/src/core/included/XUD_Token_In_DI.S +++ b/lib_xud/src/core/included/XUD_Token_In_DI.S @@ -24,15 +24,25 @@ .align FUNCTION_ALIGNMENT XUD_IN_NotReady: ldw r11, sp[STACK_EPTYPES_IN] - ldw r11, r11[r10] // Load EP Type - bt r11, XUD_IN_TxNak - ldc r11, 0xc3 // Create 0-length packet + ldw r11, r11[r10] // Load EP Type + bt r11, XUD_IN_TxHandshake + ldc r11, 0xc3 // Create 0-length packet outpw res[TXD], r11, 24 #include "XUD_TokenJmp.S" -XUD_IN_TxNak: // Non-Iso - ldaw r11, dp[handshakeTable_IN] // Load handshake table - ldw r11, r11[r10] // Load handshake PID +XUD_IN_TxHandshake: // Non-Iso + ldaw r11, dp[handshakeTable_IN] // Load handshake table + ldw r11, r11[r10] // Load handshake PID (or 0) + bf r11, XUD_IN_TxNak + outpw res[TXD], r11, 8 // Output STALL + #include "XUD_TokenJmp.S" + +XUD_IN_TxNak: + ldc r11, USB_PIDn_NAK + outpw res[TXD], r11, 8 + #include "XUD_TokenJmp.S" + +XUD_IN_TxStall: outpw res[TXD], r11, 8 #include "XUD_TokenJmp.S" @@ -43,9 +53,9 @@ Pid_In: ldw r4, r5[r3] // Load EP structure address bf r4, XUD_IN_NotReady - ldaw r1, dp[g_stallTable_IN] - ldw r11, r1[r10] - bt r11, XUD_IN_NotReady // Note, user could potentially stall an ISO EP. + 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 diff --git a/lib_xud/src/core/included/XUD_Token_Ping.S b/lib_xud/src/core/included/XUD_Token_Ping.S index 142096af..79ce7dc2 100755 --- a/lib_xud/src/core/included/XUD_Token_Ping.S +++ b/lib_xud/src/core/included/XUD_Token_Ping.S @@ -7,11 +7,11 @@ Pid_Ping: #include "XUD_CrcAddrCheck.S" LoadStatTablePing: - ldw r11, r5[r10] // Load relevant EP chanend + ldw r11, r5[r10] // Load relevant EP chanend bf r11, PrimaryBufferFull_PING .scheduling off -PrimaryBufferEmpty_PING: // Send ACK +PrimaryBufferEmpty_PING: // Send ACK #if (XUD_CORE_CLOCK > 400) nop nop @@ -25,7 +25,7 @@ PrimaryBufferEmpty_PING: // Send ACK outpw res[TXD], r11, 8 bu NextTokenAfterPing -PrimaryBufferFull_PING: // Send NAK +PrimaryBufferFull_PING: // Send NAK (or STALL) #if (XUD_CORE_CLOCK > 400) nop nop @@ -34,10 +34,8 @@ PrimaryBufferFull_PING: // Send NAK nop nop nop - // ldc r11, USB_PIDn_NA - // Load handshake (ACK or STALL) - ldaw r11, dp[handshakeTable_OUT] // Load handshake table - ldw r11, r11[r10] + ldaw r11, dp[handshakeTable_OUT] // Load handshake table + ldw r11, r11[r10] // Load handshake (ACK or STALL) 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 fbd72316..870f1321 100644 --- a/lib_xud/src/core/included/XUD_Token_Setup_DI.S +++ b/lib_xud/src/core/included/XUD_Token_Setup_DI.S @@ -10,31 +10,29 @@ Pid_Setup: #include "XUD_CrcAddrCheck.S" ldw r3, r5[r10] // Load relevant EP pointer - bf r3, SBuffFull + bf r3, XUD_SETUP_BuffFull ldw r1, r3[3] // Load buffer -LoadSetupBuffer: +XUD_SETUP_LoadBuffer: bl doRXData // RXData writes available data to buffer and does crc check. // r8: Data tail size (bytes) - {clre; eq r1, r6, r11} // Check for good CRC16 - bf r1, NextTokenAfterOut // Check for bad crc + xor r1, r6, r11 // Check for good CRC16 + {clre; + bt r1, XUD_SETUP_NotReady} // Branch based on CRC good/bad -ClearStall: // CRC OK +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] - ldc r1, 0} - stw r6, r11[r10] - ldaw r11, dp[g_stallTable_IN] + ldw r11, sp[STACK_HANDSHAKETABLEIN] stw r1, r11[r10] -SendSetupAck: +XUD_SETUP_SendSetupAck: ldc r11, USB_PIDn_ACK outpw res[TXD], r11, 8 -StoreTailData: // TODO: don't assume setups are 8 bytes + crc +XUD_SETUP_StoreTailData: // TODO: don't assume setups are 8 bytes + crc stw r1, r5[r10] // Clear ready ldw r11, r3[1] // Load chanend @@ -42,9 +40,14 @@ StoreTailData: // TODO: don't assume setups are outct res[r11], 0 // Send zero control token for SETUP. Tail ignored since always expect 8 bytes bu NextTokenAfterOut // Go to next wait for next token -SBuffFull: +XUD_SETUP_BuffFull: ldw r10, sp[STACK_RXA_PORT] // Load RxA Port ID (r1) in r11, res[r10] // RXA event cond = 0 TODO: Wait for RXA high first? endin r11, res[RXD] in r11, res[RXD] bu NextTokenAfterOut + + +.align FUNCTION_ALIGNMENT +XUD_SETUP_NotReady: + bu NextTokenAfterOut diff --git a/lib_xud/src/user/client/XUD_EpFuncs.S b/lib_xud/src/user/client/XUD_EpFuncs.S index 95c0e1b6..5422500b 100644 --- a/lib_xud/src/user/client/XUD_EpFuncs.S +++ b/lib_xud/src/user/client/XUD_EpFuncs.S @@ -543,7 +543,7 @@ XUD_SetStallByAddr: ENTSP_lu6 0 #endif ldc r2, USB_PIDn_STALL - ldc r11, 0x80 // Check for IN bit + ldc r11, 0x80 // Check for IN bit and r11, r11, r0 bf r11, XUD_SetStallByAddr_OUT ldaw r1, dp[handshakeTable_IN] @@ -551,9 +551,6 @@ XUD_SetStallByAddr: and r11, r11, r0 stw r2, r1[r11] - ldaw r1, dp[g_stallTable_IN] // Mark stall table with non-zero entry - stw r2, r1[r11] - retsp 0 XUD_SetStallByAddr_OUT: ldaw r1, dp[handshakeTable_OUT] @@ -597,19 +594,16 @@ XUD_ClearStallByAddr: 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] - - ldaw r1, dp[g_stallTable_IN] - ldc r2, 0 - stw r2, r1[r11] // Mark stall with zero entry - // 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: - ldaw r1, dp[handshakeTable_OUT] + ldc r2, USB_PIDn_NAK + ldaw r1, dp[handshakeTable_OUT] stw r2, r1[r0] #ifdef __XS3A__ @@ -619,13 +613,11 @@ XUD_ClearStallByAddr_OUT: #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 diff --git a/tests/Pyxsim/__init__.py b/tests/Pyxsim/__init__.py deleted file mode 100644 index ceff7eeb..00000000 --- a/tests/Pyxsim/__init__.py +++ /dev/null @@ -1,135 +0,0 @@ -# Copyright 2016-2021 XMOS LIMITED. -# This Software is subject to the terms of the XMOS Public Licence: Version 1. -""" -Pyxsim pytest framework - -This module provides functions to run tests for XMOS applications and libraries. -""" -import sys -import Pyxsim.pyxsim -from Pyxsim.xmostest_subprocess import call_get_output -import platform -import multiprocessing -import tempfile -import re -import os - -clean_only = False - -# This function is called automatically by the runners -def _build(xe_path, build_config=None, env={}, do_clean=False, build_options=[]): - - # Work out the Makefile path - path = None - m = re.match("(.*)/bin/(.*)", xe_path) - if m: - path = m.groups(0)[0] - binpath = m.groups(0)[1] - m = re.match("(.*)/(.*)", binpath) - if m: - build_config = m.groups(0)[0] - - if not path: - msg = "ERROR: Cannot determine path to build: %s\n" % xe_path - sys.stderr.write(msg) - return (False, msg) - - # Copy the environment, to avoid modifying the env of the current shell - my_env = os.environ.copy() - for key in env: - my_env[key] = str(env[key]) - - if clean_only: - cmd = ["xmake", "clean"] - do_clean = False - else: - cmd = ["xmake", "all"] - - if do_clean: - clean_output = call_get_output(["xmake", "clean"], cwd=path, env=my_env) - - if build_config is not None: - cmd += ["CONFIG=%s" % build_config] - - cmd += build_options - - output = call_get_output(cmd, cwd=path, env=my_env, merge_out_and_err=True) - - success = True - for x in output: - s = str(x) - if s.find("Error") != -1: - success = False - # if re.match('xmake: \*\*\* .* Stop.', x) != None: - if re.match(r"xmake: \*\*\* .* Stop.", s) != None: - success = False - - if not success: - sys.stderr.write("ERROR: build failed.\n") - for x in output: - s = str(x) - sys.stderr.write(s + "\n") - - return (success, output) - - -def do_run_pyxsim(xe, simargs, appargs, simthreads): - xsi = pyxsim.Xsi(xe_path=xe, simargs=simargs, appargs=appargs) - for x in simthreads: - xsi.register_simthread(x) - xsi.run() - xsi.terminate() - - -def run_with_pyxsim( - xe, - simthreads, - xscope_io=False, - loopback=[], - simargs=[], - appargs=[], - suppress_multidrive_messages=False, - tester=None, - timeout=600, - initial_delay=None, - start_after_started=[], - start_after_completed=[], -): - - p = multiprocessing.Process( - target=do_run_pyxsim, args=(xe, simargs, appargs, simthreads) - ) - p.start() - p.join(timeout=timeout) - if p.is_alive(): - sys.stderr.write("Simulator timed out\n") - p.terminate() - return None - - -def run_tester(caps, tester_list): - result = [] - for i, ele in enumerate(caps): - ele.remove("") - if tester_list[i] != "Build Failed": - result.append(tester_list[i].run(ele)) - else: - result.append(False) - return result - - -class SimThread(object): - def run(self, xsi): - pass - - def wait(self, f): - self.xsi._user_wait(f) - - def wait_for_port_pins_change(self, ps): - self.xsi._wait_for_port_pins_change(ps) - - def wait_for_next_cycle(self): - self.xsi._wait_for_next_cycle() - - def wait_until(self, t): - self.xsi._wait_until(t) diff --git a/tests/Pyxsim/pyxsim.py b/tests/Pyxsim/pyxsim.py deleted file mode 100644 index e8a15a40..00000000 --- a/tests/Pyxsim/pyxsim.py +++ /dev/null @@ -1,466 +0,0 @@ -# Copyright 2016-2021 XMOS LIMITED. -# This Software is subject to the terms of the XMOS Public Licence: Version 1. - -import os, re, struct -from ctypes import cdll, byref, c_void_p, c_char_p, c_int, create_string_buffer -from Pyxsim.xe import Xe -from Pyxsim.testers import TestError -import threading -import traceback -import Pyxsim -import sys -from Pyxsim.xmostest_subprocess import platform_is_windows - -ALL_BITS = 0xFFFFFF - -if platform_is_windows(): - xsi_lib_path = os.path.abspath( - os.environ["XCC_EXEC_PREFIX"] + "../lib/xsidevice.dll" - ) -else: - xsi_lib_path = os.path.abspath( - os.environ["XCC_EXEC_PREFIX"] + "../lib/libxsidevice.so" - ) - -xsi_lib = cdll.LoadLibrary(xsi_lib_path) - - -def xsi_is_valid_port(port): - return re.match(r"XS1_PORT_\d+\w", port) != None - - -def xsi_get_port_width(port): - if not xsi_is_valid_port(port): - return None - else: - return int(re.match(r"^XS1_PORT_(\d+)\w", port).groups(0)[0]) - - -class EnumExceptionSet: - def __init__(self, enum_list, valid_list=[]): - self.enum_list = enum_list - self.valid_list = valid_list - - def __getattr__(self, name): - if name in self.enum_list: - return self.enum_list.index(name) - raise AttributeErr - - def is_valid(self, value): - if value < len(self.enum_list): - enum = self.enum_list[value] - return enum in self.valid_list - - def error_if_not_valid(self, value): - if value < len(self.enum_list): - enum = self.enum_list[value] - if not enum in self.valid_list: - raise type("XSI_ERROR_" + enum, (Exception,), {}) - - def error(self, value): - if value < len(self.enum_list): - enum = self.enum_list[value] - raise type("XSI_ERROR_" + enum, (Exception,), {}) - - -XsiStatus = EnumExceptionSet( - [ - "OK", - "DONE", - "TIMEOUT", - "INVALID_FILE", - "INVALID_INSTANCE", - "INVALID_TILE", - "INVALID_PACKAGE", - "INVALID_PIN", - "INVALID_PORT", - "MEMORY_ERROR", - "PSWITCH_ERROR", - "INVALID_ARGS", - "NULL_ARG", - "INCOMPATIBLE_VERSION", - ], - valid_list=["OK", "DONE"], -) - - -def parse_port(p): - m = re.match(r"(tile.*)\:([^\.]*)\.?(\d*)", p) - if m: - tile = m.groups(0)[0] - port = m.groups(0)[1] - bit = m.groups(0)[2] - if bit == "": - bit = None - if bit != None: - bit = int(bit) - else: - raise TestError("Cannot parse port: %s" % p) - if bit != None: - mask = 1 << bit - else: - mask = ALL_BITS - return (tile, port, bit, mask) - - -def parse_periph_pin(p): - m = re.match("^[^_]+_([^_]+)_([^_]+)", p) - if m: - perif = m.groups(0)[0] - pin = m.groups(0)[1] - else: - raise TestError("Cannot parse periph pin: %s" % p) - mask = ALL_BITS - return (perif, pin, mask) - - -class SimThreadImpl(threading.Thread): - def __init__(self, xsi, st, args): - def _fn(*args): - st.run(*args) - - super(SimThreadImpl, self).__init__() - self._fn = _fn - self._args = args - self.get_time = xsi.get_time - self.resume_event = threading.Event() - self.complete_event = threading.Event() - self._xsi = xsi - self.had_exception = False - self.terminate_flag = False - st.xsi = self - - def _wait(self, resume_check): - self.resume_condition = resume_check - self.complete_event.set() - self.resume_event.wait() - self.resume_event.clear() - - def _user_wait(self, resume_check): - def _resume(xsi): - return resume_check(self) - - self._wait(_resume) - - def _wait_until(self, time): - def _resume(xsi): - return xsi.get_time() >= time - - self._wait(_resume) - - def _wait_for_port_pins_change(self, ps): - is_driving = [] - vals = [] - ps = [(self._xsi.xe.get_port_pins(p)[0], parse_port(p)) for p in ps] - for ((package, pin, _), (tile, p, bit, mask)) in ps: - d = self._xsi.is_pin_driving(package, pin) - is_driving.append(d) - if d: - v = self._xsi.sample_port_pins(tile, p, mask) - if bit: - v = v >> bit - vals.append(v) - else: - vals.append(0) - - def _resume(xsi): - for i, psval in enumerate(ps): - (package, pin, _), (tile, p, bit, mask) = psval - d = xsi.is_pin_driving(package, pin) - if d != is_driving[i]: - return True - if d: - v = xsi.sample_port_pins(tile, p, mask) - if bit: - v = v >> bit - else: - v = 0 - if v != vals[i]: - return True - return False - - self._wait(_resume) - - def _wait_for_next_cycle(self): - self._wait(lambda x: True) - - def is_port_driving(self, port): - (package, pin, _) = self._xsi.xe.get_port_pins(port)[0] - return self._xsi.is_pin_driving(package, pin) - - def drive_port_pins(self, port, val): - (tile, p, bit, mask) = parse_port(port) - if bit: - val <<= bit - self._xsi.drive_port_pins(tile, p, mask, val) - - def sample_port_pins(self, port): - (tile, p, bit, mask) = parse_port(port) - val = self._xsi.sample_port_pins(tile, p, mask) - if bit: - val >>= bit - return val - - # TODO make this pin*s* - def drive_periph_pin(self, pin, val): - (periph, pin, mask) = parse_periph_pin(pin) - self._xsi.drive_periph_pin(periph, pin, mask, val) - - # TODO make this pin*s* - def sample_periph_pin(self, pin): - (periph, pin, mask) = parse_periph_pin(pin) - return self._xsi.sample_periph_pin(periph, pin, mask) - - def terminate(self): - self.terminate_flag = True - self._wait(lambda x: False) - - def run(self): - args = self._args - try: - self._fn(*args) - except: - self.had_exception = True - sys.stderr.write("---------Exception in simthread--------------\n") - traceback.print_exc() - sys.stderr.write("---------------------------------------------\n") - self.resume_condition = lambda x: False - self.complete_event.set() - - -class Xsi(object): - def __init__(self, xe_path=None, simargs=[], appargs=[]): - self.xsim = c_void_p() - self.xe_path = xe_path - args = " ".join( - ['"{}"'.format(x) for x in (simargs + [self.xe_path] + appargs)] - ) - if platform_is_windows: - args = args.replace("\\", "/") - c_args = c_char_p(args.encode("utf-8")) - status = xsi_lib.xsi_create(byref(self.xsim), c_args) - self._plugins = [] - self._simthreads = [] - self._time = 0 - - def register_plugin(self, plugin): - self._plugins.append(plugin) - - def register_simthread(self, fn): - if isinstance(fn, tuple): - xs = list(fn) - fn = xs[0] - args = xs[1:] - else: - args = [] - - simthread = SimThreadImpl(self, fn, args) - simthread.daemon = True - self._simthreads.append(simthread) - - def wait_for_simthread(self, simthread): - simthread.complete_event.wait() - simthread.complete_event.clear() - if simthread.had_exception: - raise TestError("Simthread encoutered an exception") - - def clock(self): - status = xsi_lib.xsi_clock(self.xsim) - self._time += self._time_step - if XsiStatus.is_valid(status): - for plugin in self._plugins: - plugin.clock(self) - for simthread in self._simthreads: - if simthread.resume_condition(self): - simthread.resume_event.set() - self.wait_for_simthread(simthread) - if simthread.terminate_flag: - return XsiStatus.DONE - - return status - - def get_time(self): - return self._time - - def run(self): - self.xe = Xe(self.xe_path) - self._time_step = 1000.0 / self.xe.freq - status = XsiStatus.OK - for simthread in self._simthreads: - simthread.start() - self.wait_for_simthread(simthread) - - while status != XsiStatus.DONE: - status = self.clock() - XsiStatus.error_if_not_valid(status) - - def terminate(self): - status = xsi_lib.xsi_terminate(self.xsim) - XsiStatus.error_if_not_valid(status) - - def sample_pin(self, package, pin): - c_package = c_char_p(package) - c_pin = c_char_p(pin) - c_value = c_int() - status = xsi_lib.xsi_sample_pin(self.xsim, c_package, c_pin, byref(c_value)) - XsiStatus.error_if_not_valid(status) - return c_value.value - - def sample_port_pins(self, tile, port, mask): - c_tile = c_char_p(tile.encode("utf-8")) - c_port = c_char_p(port.encode("utf-8")) - c_mask = c_int(mask) - c_value = c_int() - status = xsi_lib.xsi_sample_port_pins( - self.xsim, c_tile, c_port, c_mask, byref(c_value) - ) - XsiStatus.error_if_not_valid(status) - return c_value.value - - def drive_pin(self, package, pin, value): - c_package = c_char_p(package) - c_pin = c_char_p(pin) - c_value = c_int(value) - status = xsi_lib.xsi_drive_pin(self.xsim, c_package, c_pin, c_value) - XsiStatus.error_if_not_valid(status) - - def drive_port_pins(self, tile, port, mask, value): - c_tile = c_char_p(tile.encode("utf-8")) - c_port = c_char_p(port.encode("utf-8")) - c_mask = c_int(mask) - c_value = c_int(value) - status = xsi_lib.xsi_drive_port_pins(self.xsim, c_tile, c_port, c_mask, c_value) - XsiStatus.error_if_not_valid(status) - - # TOOD make this pin*s* - def drive_periph_pin(self, periph, pin, mask, value): - c_periph = c_char_p(periph.encode("utf-8")) - c_pin = c_char_p(pin.encode("utf-8")) - c_mask = c_int(mask) - c_value = c_int(value) - status = xsi_lib.xsi_drive_periph_pin( - self.xsim, c_periph, c_pin, c_mask, c_value - ) - XsiStatus.error_if_not_valid(status) - - # TOOD make this pin*s* - def sample_periph_pin(self, periph, pin, mask): - c_periph = c_char_p(periph.encode("utf-8")) - c_pin = c_char_p(pin.encode("utf-8")) - c_mask = c_int(mask) - c_value = c_int() - status = xsi_lib.xsi_sample_periph_pin( - self.xsim, c_periph, c_pin, c_mask, byref(c_value) - ) - XsiStatus.error_if_not_valid(status) - return c_value.value - - def is_pin_driving(self, package, pin): - c_package = c_char_p(package) - c_pin = c_char_p(pin) - c_value = c_int() - status = xsi_lib.xsi_is_pin_driving(self.xsim, c_package, c_pin, byref(c_value)) - XsiStatus.error_if_not_valid(status) - return c_value.value - - def is_port_pins_driving(self, tile, port): - c_tile = c_char_p(tile) - c_port = c_char_p(port) - c_value = c_int() - status = xsi_lib.xsi_is_port_pins_driving( - self.xsim, c_tile, c_port, byref(c_value) - ) - XsiStatus.error_if_not_valid(status) - return c_value.value - - def read_mem(self, tile, address, num_bytes, return_ctype=False): - c_tile = c_char_p(tile) - c_address = c_int(address) - c_num_bytes = c_int(num_bytes) - buf = create_string_buffer(num_bytes) - status = xsi_lib.xsi_read_mem(self.xsim, c_tile, c_address, c_num_bytes, buf) - XsiStatus.error_if_not_valid(status) - if return_ctype: - return buf - else: - return list(buf) - - def read_symbol_word(self, tile, symbol, offset=0): - address = self.xe.symtab[tile, symbol] - address += offset - buf = self.read_mem(tile, address, 4, return_ctype=True) - return struct.unpack("= num_expected: - self.record_failure("Length of expected output less than output") - break - - if self._ordered: - if regexp: - match = re.match(expected[line_num] + "$", output[i].strip()) - else: - match = expected[line_num] == output[i].strip() - - if not match: - self.record_failure( - ( - "Line %d of output does not match expected\n" - + " Expected: %s\n" - + " Actual : %s" - ) - % (line_num, expected[line_num].strip(), output[i].strip()) - ) - else: # Unordered testing - stripped = output[i].strip() - if regexp: - match = any(re.match(e + "$", stripped) for e in expected) - else: - match = any(e == stripped for e in expected) - - if not match: - self.record_failure( - ("Line %d of output not found in expected\n" + " Actual : %s") - % (line_num, output[i].strip()) - ) - - if num_expected > line_num + 1: - self.record_failure( - "Length of expected output greater than output\nMissing:\n" - + "\n".join(expected[line_num + 1 :]) - ) - output = {"output": "".join(output)} - - if not self.result: - output["failures"] = "".join(self.failures) - - if self.result: - sys.stdout.write( - "%-30s %-6s %-6s Pass\n" - % (test, config.get("arch"), config.get("speed")) - ) - else: - sys.stderr.write( - "%-30s %-6s %-6s Fail\n" - % (test, config.get("arch"), config.get("speed")) - ) - - return self.result diff --git a/tests/Pyxsim/xe.py b/tests/Pyxsim/xe.py deleted file mode 100644 index 1a3dc866..00000000 --- a/tests/Pyxsim/xe.py +++ /dev/null @@ -1,101 +0,0 @@ -# Copyright 2016-2021 XMOS LIMITED. -# This Software is subject to the terms of the XMOS Public Licence: Version 1. -from Pyxsim.xmostest_subprocess import call, call_get_output -from Pyxsim.testers import TestError -import os, tempfile -from xml.dom.minidom import parse -import re -from fractions import gcd - - -def lcm(a, b): - return (a * b) // gcd(a, b) - - -class Xe: - def _get_platform_info(self): - call(["xobjdump", "--split", self.path], silent=True, cwd=self._tempdir) - xn = parse("%s/platform_def.xn" % self._tempdir) - self._tile_map = {} - self.tiles = [] - lcm_freq = 1 - for node in xn.getElementsByTagName("Node"): - freq = node.getAttribute("SystemFrequency") - if freq: - freq = int(freq.replace("MHz", "")) - lcm_freq = lcm(lcm_freq, freq) - cm = {} - for tile in node.getElementsByTagName("Tile"): - self._tile_map[ - node.getAttribute("Id"), tile.getAttribute("Number") - ] = tile.getAttribute("Reference") - self.tiles.append(tile.getAttribute("Reference")) - self.freq = lcm_freq - - config = parse("%s/config.xml" % self._tempdir) - self._port_map = {} - for pin_node in config.getElementsByTagName("Pin"): - name = pin_node.getAttribute("name") - (package, pin) = name.split(":") - for port_node in pin_node.getElementsByTagName("Port"): - port = "tile[%s]:%s" % ( - port_node.getAttribute("core"), - port_node.getAttribute("name"), - ) - bitnum = int(port_node.getAttribute("bitNum")) - if not port in self._port_map: - self._port_map[port] = [] - self._port_map[port].append((package, pin, bitnum)) - - def get_port_pins(self, port): - m = re.match(r"([^\.]*)\.(\d*)", port) - if m: - port = m.groups(0)[0] - bit = int(m.groups(0)[1]) - pins = self._port_map[port] - for (package, pin, bitnum) in pins: - if bitnum == bit: - return [(package, pin, bitnum)] - raise TestError("Cannot find port pins") - else: - return self._port_map[port] - - def _get_symtab(self): - stdout, stderr = call_get_output(["xobjdump", "-t", self.path]) - current_tile = None - symtab = {} - for line in stdout: - line = str(line) - if line == "": - break - m = re.match(r"Loadable.*for (.*) \(node \"(\d*)\", tile (\d*)", line) - - if m: - current_tile = m.groups(0)[0] - m = re.match(r"(0x[0-9a-fA-F]*).....([^ ]*) *(0x[0-9a-fA-F]*) (.*)$", line) - if m and current_tile != None: - (address, section, size, name) = m.groups(0) - if section != "*ABS*": - address = int(address, 0) - symtab[current_tile, name] = address - self.symtab = symtab - - def __init__(self, path): - if not os.path.isfile(path): - raise IOError("Cannot find file: %s" % path) - self.path = os.path.abspath(path) - self._symtab = {} - self._tempdir = tempfile.mkdtemp() - self._get_platform_info() - self._get_symtab() - - def __del__(self): - if self._tempdir != None: - for root, dirs, files in os.walk(self._tempdir, topdown=False): - for f in files: - p = os.path.join(root, f) - os.remove(p) - for d in dirs: - p = os.path.join(root, d) - os.rmdir(p) - os.rmdir(self._tempdir) diff --git a/tests/Pyxsim/xmostest_subprocess.py b/tests/Pyxsim/xmostest_subprocess.py deleted file mode 100644 index 110b3981..00000000 --- a/tests/Pyxsim/xmostest_subprocess.py +++ /dev/null @@ -1,273 +0,0 @@ -# Copyright 2016-2021 XMOS LIMITED. -# This Software is subject to the terms of the XMOS Public Licence: Version 1. -import platform -import re -import subprocess -import sys -import tempfile -import multiprocessing -import time -import os -import signal -import errno -from Pyxsim.testers import TestError - - -def pstreekill(process): - pid = process.pid - if platform_is_windows(): - # Try allowing a clean shutdown first - subprocess.call(["taskkill", "/t", "/pid", str(pid)]) - confirmed_termination = False - timeout = time.time() + 10 # Timeout in seconds - while time.time() < timeout: - # Check the current status of the process - status = subprocess.call(["tasklist", "/nh", "/fi", '"PID eq %s"' % pid]) - if status.startswith( - "INFO: No tasks are running which match the specified criteria" - ): - # Process has shutdown - confirmed_termination = True - break - time.sleep(0.1) # Avoid spinning too fast while in the timeout loop - if not confirmed_termination: - # If the process hasn't shutdown politely yet kill it - sys.stdout.write("Force kill PID %d that hasn't responded to kill\n" % pid) - subprocess.call(["taskkill", "/t", "/f", "/pid", str(pid)]) - else: - # Send SIGINT to the process group to notify all processes that we - # are going down now - os.killpg(os.getpgid(pid), signal.SIGINT) - - # Now terminate and join the main process. If the join has not returned - # within 10 seconds then we will have to forcibly kill the process group - process.terminate() - process.join(timeout=10) - - if process.is_alive(): - # If the process hasn't shutdown politely yet kill it - try: - sys.stderr.write( - "Sending SIGKILL to PID %d that hasn't responded to SIGINT\n" % pid - ) - os.killpg(os.getpgid(pid), signal.SIGKILL) - except OSError as err: - # ESRCH == No such process - presumably exited since timeout... - if err.errno != errno.ESRCH: - raise - - -## Annoying OS incompatability, not sure why this is needed - - -def log_debug(msg): - pass - - -def platform_is_osx(): - ostype = platform.system() - if re.match(".*Darwin.*", ostype): - return True - else: - return False - - -def platform_is_windows(): - ostype = platform.system() - if not re.match(".*Darwin.*", ostype) and re.match(".*[W|w]in.*", ostype): - return True - else: - return False - - -if platform_is_windows(): - concat_args = True - use_shell = True - # Windows version of Python 2.7 doesn't support SIGINT - if sys.version_info < (3, 0): - raise TestError( - "Doesn't support Python version < 3, please upgrade to Python 3 or higher." - ) - SIGINT = signal.SIGTERM -else: - concat_args = False - use_shell = False - SIGINT = signal.SIGINT - - -def quote_string(s): - """For Windows need to put quotes around arguments with spaces in them""" - if re.search(r"\s", s): - return '"%s"' % s - else: - return s - - -def Popen(*args, **kwargs): - kwargs["shell"] = use_shell - if concat_args: - args = (" ".join([quote_string(arg) for arg in args[0]]),) + args[1:] - cmd = args[0] - else: - cmd = " ".join(args[0]) - - log_debug("Run '%s' in %s" % (cmd, kwargs.get("cwd", "."))) - return subprocess.Popen(*args, **kwargs) - - -def wait_with_timeout(p_and_sig, timeout): - (ev, pidv, process) = p_and_sig - process.start() - try: - if timeout: - finished = ev.wait(timeout) - if not finished: - pstreekill(process) - return (not finished, 0) - else: - ev.wait() - return (False, 0) - except KeyboardInterrupt: - pstreekill(process) - - return (False, 0) - - -def do_cmd(ev, pidv, *args, **kwargs): - if not platform_is_windows(): - os.setpgid(os.getpid(), 0) - if "stdout_fname" in kwargs: - fname = kwargs.pop("stdout_fname") - kwargs["stdout"] = open(fname, "w") - if "stderr_fname" in kwargs: - fname = kwargs.pop("stderr_fname") - kwargs["stderr"] = open(fname, "w") - process = Popen(*args, **kwargs) - pidv.value = process.pid - try: - process.wait() - except KeyboardInterrupt: - # Catch the KeyboardInterrupt raised due to the SIGINT signal - # sent by pstreekill() - pass - ev.set() - - -def create_cmd_process(*args, **kwargs): - ev = multiprocessing.Event() - pidv = multiprocessing.Value("d", 0) - args = tuple([ev, pidv] + list(args)) - process = multiprocessing.Process(target=do_cmd, args=args, kwargs=kwargs) - - return (ev, pidv, process) - - -def remove(name): - """On windows, OS.remove() will cause an exception if the file is still in use. - It is assumed there is a release race, hence the multiple attempts here. - """ - attempt = 0 - while attempt < 3: - try: - os.remove(name) - return - except OSError: - attempt = attempt + 1 - time.sleep(0.1 * attempt) - sys.stdout.write("ERROR: Unable to remove file `%s`\n" % name) - - -def call(*args, **kwargs): - """If silent, then create temporary files to pass stdout and stderr to since - on Windows the less/more-like behaviour waits for a keypress if it goes to stdout. - """ - silent = kwargs.pop("silent", False) - retval = 0 - timeout = None - if "timeout" in kwargs: - timeout = kwargs["timeout"] - kwargs.pop("timeout") - - if silent: - out = tempfile.NamedTemporaryFile(delete=False) - kwargs["stdout_fname"] = out.name - kwargs["stderr"] = subprocess.STDOUT - - process = create_cmd_process(*args, **kwargs) - (timed_out, retval) = wait_with_timeout(process, timeout) - out.seek(0) - stdout_lines = out.readlines() - out.close() - remove(out.name) - for line in stdout_lines: - line = line.decode("utf-8") - log_debug(" " + line.rstrip()) - else: - process = create_cmd_process(*args, **kwargs) - (timed_out, retval) = wait_with_timeout(process, timeout) - # Ensure spawned processes are not left running past this point - # There should be no children running now (as they would be orphaned) - process[2].terminate() - process[2].join(timeout=0.1) # Avoid always printing wait message - while process[2].is_alive(): - sys.stdout.write("Waiting for PID %d to terminate\n" % process[2].pid) - process[2].join(timeout=1.0) - - if timeout: - return (timed_out, retval) - else: - return retval - - -def call_get_output(*args, **kwargs): - """Create temporary files to pass stdout and stderr to since on Windows the - less/more-like behaviour waits for a keypress if it goes to stdout. - """ - merge = kwargs.pop("merge_out_and_err", False) - - out = tempfile.NamedTemporaryFile(delete=False) - kwargs["stdout_fname"] = out.name - timeout = None - if "timeout" in kwargs: - timeout = kwargs["timeout"] - kwargs.pop("timeout") - - if merge: - kwargs["stderr"] = subprocess.STDOUT - else: - err = tempfile.NamedTemporaryFile(delete=False) - stderr_fname = err.name - kwargs["stderr_fname"] = stderr_fname - err.close() - - process = create_cmd_process(*args, **kwargs) - (timed_out, retval) = wait_with_timeout(process, timeout) - out.seek(0) - stdout_lines = out.readlines() - out.close() - remove(out.name) - - for line in stdout_lines: - line = line.decode("utf-8") - log_debug(" " + line.rstrip()) - - if not merge: - err = open(stderr_fname, "r") - stderr_lines = err.readlines() - err.close() - remove(stderr_fname) - for line in stderr_lines: - line = line.decode("utf-8") - log_debug(" err:" + line.rstrip()) - - if merge: - if timeout: - return (timed_out, stdout_lines) - else: - return stdout_lines - - else: - if timeout: - return (timed_out, stdout_lines, stderr_lines) - else: - return (stdout_lines, stderr_lines) diff --git a/tests/conftest.py b/tests/conftest.py index b573ee52..bec350c6 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,17 +1,17 @@ # Copyright 2021 XMOS LIMITED. # This Software is subject to the terms of the XMOS Public Licence: Version 1. -import pytest +from pathlib import Path import os -import random +import shutil import sys -import Pyxsim -from Pyxsim import testers + +import pytest + from helpers import get_usb_clk_phy, do_usb_test -from pathlib import Path -import shutil +import Pyxsim # Note, no current support for XS2 so don't copy XS2 xn files -XN_FILES = ["test_xs3_600.xn", "test_xs3_800.xn"] +XN_FILES = ["test_xs3_600.xn", "test_xs3_800.xn", "test_xs3_540.xn", "test_xs3_500.xn"] PARAMS = { "extended": { @@ -56,15 +56,9 @@ def pytest_configure(config): os.environ["enabletracing"] = str(config.getoption("enabletracing")) -# TODO: this is deprecated, find a better way -def pytest_cmdline_preparse(config, args): - if "--smoke" in args and "--extended" in args: - raise pytest.UsageError('Only one of "--smoke" and "--extended" can be used') - - def pytest_generate_tests(metafunc): try: - PARAMS = metafunc.module.PARAMS + PARAMS = metafunc.module.PARAMS # noqa F401 if metafunc.config.getoption("smoke"): params = PARAMS.get("smoke", PARAMS["default"]) elif metafunc.config.getoption("extended"): @@ -123,8 +117,6 @@ def test_RunUsbSession( tester_list = [] output = [] - testname, extension = os.path.splitext(os.path.basename(__file__)) - seed = random.randint(0, sys.maxsize) # 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) @@ -140,7 +132,6 @@ def test_RunUsbSession( usb_phy, [test_session], test_file, - seed, ) ) cap_output, err = capfd.readouterr() @@ -158,7 +149,10 @@ def test_RunUsbSession( def copy_common_xn_files( - test_dir, path=".", common_dir="shared_src", source_dir="src", xn_files=XN_FILES + test_dir, + common_dir="shared_src", + source_dir="src", + xn_files=XN_FILES, ): src_dir = os.path.join(test_dir, source_dir) for xn_file in xn_files: @@ -166,9 +160,7 @@ def copy_common_xn_files( shutil.copy(xn, src_dir) -def delete_test_specific_xn_files( - test_dir, path=".", source_dir="src", xn_files=XN_FILES -): +def delete_test_specific_xn_files(test_dir, source_dir="src", xn_files=XN_FILES): src_dir = os.path.join(test_dir, source_dir) for xn_file in xn_files: xn = os.path.join(src_dir, xn_file) @@ -183,9 +175,8 @@ def delete_test_specific_xn_files( def worker_id(request): if hasattr(request.config, "slaveinput"): return request.config.slaveinput["slaveid"] - else: - # Master means not executing with multiple workers - return "master" + # Master means not executing with multiple workers + return "master" # Runs after all tests are collected, but before all tests are run @@ -194,11 +185,12 @@ def worker_id(request): def copy_xn_files(worker_id, request): # Attempt to only run copy/delete once.. - if worker_id == "master" or worker_id == "gw0": + if worker_id in ("master", "gw0"): session = request.node - # There will be duplicates (same test name with different params) so treat as set + # There will be duplicates (same test name with different params) sos + # treat as set test_dirs = set([]) # Go through collected tests and copy over XN files @@ -211,14 +203,14 @@ def copy_xn_files(worker_id, request): for test_dir in test_dirs: copy_common_xn_files(test_dir) - def delete_xn_files(): + # def delete_xn_files(): - # Run deletion on one process only - if worker_id == "master" or worker_id == "gw0": + # # Run deletion on one process only + # if worker_id in ("master", "gw0"): - # Go through collected tests deleting XN files - for test_dir in test_dirs: - delete_test_specific_xn_files(test_dir) + # # Go through collected tests deleting XN files + # for test_dir in test_dirs: + # delete_test_specific_xn_files(test_dir) # Setup tear down # Deletion removed for now - doesn't seem important diff --git a/tests/helpers.py b/tests/helpers.py index 501a371a..f67256d0 100644 --- a/tests/helpers.py +++ b/tests/helpers.py @@ -1,16 +1,13 @@ #!/usr/bin/env python # Copyright 2016-2021 XMOS LIMITED. # This Software is subject to the terms of the XMOS Public Licence: Version 1. -import Pyxsim -from Pyxsim import testers import os -import random import sys + +from Pyxsim import testers from usb_clock import Clock -from usb_phy import UsbPhy -from usb_phy_shim import UsbPhyShim from usb_phy_utmi import UsbPhyUtmi -from usb_packet import RxPacket, USB_DATA_VALID_COUNT +import Pyxsim ARCHITECTURE_CHOICES = ["xs2", "xs3"] BUSSPEED_CHOICES = ["FS", "HS"] @@ -83,7 +80,7 @@ def run_on_simulator(xe, simthreads, **kwargs): for k in ["do_xe_prebuild", "build_env", "clean_before_build"]: if k in kwargs: kwargs.pop(k) - return Pyxsim.run_with_pyxsim(xe, simthreads, **kwargs) + Pyxsim.run_with_pyxsim(xe, simthreads, **kwargs) def run_on(**kwargs): @@ -102,6 +99,7 @@ def run_on(**kwargs): "dummy_threads": "TEST_DTHREADS", "ep": "TEST_EP_NUM", "address": "XUD_STARTUP_ADDRESS", + "bus_speed": "BUS_SPEED", } @@ -116,8 +114,6 @@ def do_usb_test( phy, sessions, test_file, - seed, - level="nightly", extra_tasks=[], verbose=False, ): @@ -135,21 +131,16 @@ def do_usb_test( build_options = build_options + [build_options_str] - """Shared test code for all RX tests using the test_rx application.""" - testname, extension = os.path.splitext(os.path.basename(test_file)) + # Shared test code for all RX tests using the test_rx application + testname, _ = os.path.splitext(os.path.basename(test_file)) tester_list = [] - binary = "{testname}/bin/{arch}_{core_freq}_{dummy_threads}_{ep}_{address}/{testname}_{arch}_{core_freq}_{dummy_threads}_{ep}_{address}.xe".format( - testname=testname, - arch=arch, - core_freq=core_freq, - dummy_threads=dummy_threads, - ep=ep, - address=address, - ) + desc = f"{arch}_{core_freq}_{dummy_threads}_{ep}_{address}_{bus_speed}" + binary = f"{testname}/bin/{desc}/{testname}_{desc}.xe" - # Do not need to clean since different build will different params go to separate binaries - build_success, build_output = Pyxsim._build( + # Do not need to clean since different build will different params go to + # separate binaries + build_success, _ = Pyxsim._build( binary, do_clean=False, build_options=build_options ) @@ -163,13 +154,11 @@ def do_usb_test( expect_filename = "{folder}/{test}_{arch}_{usb_speed}.expect".format( folder=expect_folder, test=testname, - phy=phy.name, - clk=clk.get_name(), arch=arch, usb_speed=bus_speed, ) - create_expect(arch, session, expect_filename, verbose=verbose) + create_expect(session, expect_filename, verbose=verbose) tester = testers.ComparisonTester( open(expect_filename), @@ -180,7 +169,7 @@ def do_usb_test( ) tester_list.append(tester) - simargs = get_sim_args(testname, clk, phy, arch) + simargs = get_sim_args(testname, clk, arch) simthreads = [clk, phy] + extra_tasks run_on_simulator(binary, simthreads, simargs=simargs) else: @@ -189,19 +178,18 @@ def do_usb_test( return tester_list -def create_expect(arch, session, filename, verbose=False): +def create_expect(session, filename, verbose=False): + """Create the expect file for what packets should be reported by the DUT""" events = session.events - """ Create the expect file for what packets should be reported by the DUT - """ with open(filename, "w") as f: packet_offset = 0 if verbose: print("EXPECTED OUTPUT:") - for i, event in enumerate(events): + for event in events: expect_str = event.expected_output(session.bus_speed, offset=packet_offset) packet_offset += event.event_count @@ -217,17 +205,24 @@ def create_expect(arch, session, filename, verbose=False): print("Test done\n") -def get_sim_args(testname, clk, phy, arch="xs2"): +def get_sim_args(testname, clk, arch="xs2"): sim_args = [] if eval(os.getenv("enabletracing")): log_folder = create_if_needed("logs") filename = "{log}/xsim_trace_{test}_{clk}_{arch}".format( - log=log_folder, test=testname, clk=clk.get_name(), phy=phy.name, arch=arch + log=log_folder, + test=testname, + clk=clk.get_name(), + arch=arch, ) - sim_args += ["--trace-to", "{0}.txt".format(filename), "--enable-fnop-tracing"] + sim_args += [ + "--trace-to", + "{0}.txt".format(filename), + "--enable-fnop-tracing", + ] vcd_args = "-o {0}.vcd".format(filename) vcd_args += ( diff --git a/tests/shared_src/test_main.xc b/tests/shared_src/test_main.xc index 32d13a0b..aa2734e9 100644 --- a/tests/shared_src/test_main.xc +++ b/tests/shared_src/test_main.xc @@ -24,6 +24,7 @@ int main() } { + set_thread_fast_mode_on(); unsigned fail = test_func(c_ep_out, c_ep_in); #ifdef XUD_SIM_RTL diff --git a/tests/shared_src/test_xs3_500.xn b/tests/shared_src/test_xs3_500.xn new file mode 100644 index 00000000..6ea38caf --- /dev/null +++ b/tests/shared_src/test_xs3_500.xn @@ -0,0 +1,24 @@ + + + + tileref tile[2] + + + + + + + + + + + + + + + + + + diff --git a/tests/shared_src/test_xs3_540.xn b/tests/shared_src/test_xs3_540.xn new file mode 100644 index 00000000..b6205d84 --- /dev/null +++ b/tests/shared_src/test_xs3_540.xn @@ -0,0 +1,24 @@ + + + + tileref tile[2] + + + + + + + + + + + + + + + + + + diff --git a/tests/test_bulk_loopback.py b/tests/test_bulk_loopback.py index 9f8b9d1e..49d60fef 100644 --- a/tests/test_bulk_loopback.py +++ b/tests/test_bulk_loopback.py @@ -1,11 +1,13 @@ # 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_session import UsbSession from usb_transaction import UsbTransaction -import pytest -from conftest import PARAMS, test_RunUsbSession -from copy import deepcopy PARAMS = deepcopy(PARAMS) for k in PARAMS: diff --git a/tests/test_bulk_notready.py b/tests/test_bulk_notready.py new file mode 100644 index 00000000..f95d8ee8 --- /dev/null +++ b/tests/test_bulk_notready.py @@ -0,0 +1,62 @@ +# Copyright 2016-2021 XMOS LIMITED. +# This Software is subject to the terms of the XMOS Public Licence: Version 1. +from usb_session import UsbSession +from usb_transaction import UsbTransaction +from usb_packet import TokenPacket, TxDataPacket, RxHandshakePacket, USB_PID +import pytest +from conftest import PARAMS, test_RunUsbSession + + +@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 + + session = UsbSession( + bus_speed=bus_speed, run_enumeration=False, device_address=address + ) + + session.add_event( + UsbTransaction( + session, + deviceAddress=address, + endpointNumber=ep, + endpointType="BULK", + direction="OUT", + dataLength=pktLength, + ) + ) + + # Expect NAK's from DUT + session.add_event( + TokenPacket( + pid=USB_PID["IN"], + address=address, + endpoint=ep, + ) + ) + session.add_event(RxHandshakePacket(pid=USB_PID["NAK"])) + + session.add_event( + TokenPacket( + pid=USB_PID["OUT"], + address=address, + endpoint=ep, + interEventDelay=ied, + ) + ) + + session.add_event( + TxDataPacket( + dataPayload=session.getPayload_out(ep, pktLength), + pid=USB_PID["DATA0"], + ) + ) + + session.add_event(RxHandshakePacket(pid=USB_PID["NAK"])) + + return session diff --git a/tests/test_control_basic_short/Makefile b/tests/test_bulk_notready/Makefile similarity index 100% rename from tests/test_control_basic_short/Makefile rename to tests/test_bulk_notready/Makefile diff --git a/tests/test_bulk_notready/src/main.xc b/tests/test_bulk_notready/src/main.xc new file mode 100644 index 00000000..48e91ea4 --- /dev/null +++ b/tests/test_bulk_notready/src/main.xc @@ -0,0 +1,41 @@ +// 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) + +#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]) +{ + + XUD_ep ep_out1 = XUD_InitEp(c_ep_out[TEST_EP_NUM]); + + unsigned char buffer[1024]; + unsigned length; + + XUD_GetBuffer(ep_out1, buffer, length); + + /* Just give testbench some time to send some reqs that the DUT should NAK */ + timer t; + unsigned time; + t :> time; + t when timerafter(time + 10000) :> void; + return 0; +} + +#include "test_main.xc" + + diff --git a/tests/test_bulk_rx_basic.py b/tests/test_bulk_rx_basic.py index 5a06b8c6..6a783410 100644 --- a/tests/test_bulk_rx_basic.py +++ b/tests/test_bulk_rx_basic.py @@ -1,22 +1,23 @@ # 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 -import pytest -from conftest import PARAMS, test_RunUsbSession @pytest.fixture def test_session(ep, address, bus_speed): start_length = 10 - end_length = 19 + end_length = start_length + 10 session = UsbSession( bus_speed=bus_speed, run_enumeration=False, device_address=address ) - for pktLength in range(10, end_length + 1): + for pktLength in range(start_length, end_length): session.add_event( UsbTransaction( session, diff --git a/tests/test_bulk_rx_basic_badcrc32.py b/tests/test_bulk_rx_basic_badcrc32.py index a29587d4..940c51d8 100644 --- a/tests/test_bulk_rx_basic_badcrc32.py +++ b/tests/test_bulk_rx_basic_badcrc32.py @@ -1,15 +1,17 @@ # 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 -import pytest -from conftest import PARAMS, test_RunUsbSession @pytest.fixture def test_session(ep, address, bus_speed): - # The large inter-event delays are to give the DUT time to do checking on the fly + # The large inter-event delays are to give the DUT time to do checking on + # the fly session = UsbSession( bus_speed=bus_speed, run_enumeration=False, device_address=address @@ -54,7 +56,8 @@ def test_session(ep, address, bus_speed): ) ) - # Due to bad CRC, XUD will not ACK and expect a resend of the same packet - DATA PID won't be toggled + # Due to bad CRC, XUD will not ACK and expect a resend of the same + # packet - DATA PID won't be toggled session.add_event( UsbTransaction( session, diff --git a/tests/test_bulk_rx_basic_badpid.py b/tests/test_bulk_rx_basic_badpid.py index ac43b9f6..833a72e4 100644 --- a/tests/test_bulk_rx_basic_badpid.py +++ b/tests/test_bulk_rx_basic_badpid.py @@ -1,10 +1,10 @@ # 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 -import pytest -from conftest import PARAMS, test_RunUsbSession @pytest.fixture @@ -30,7 +30,8 @@ def test_session(ep, address, bus_speed): ) ) - # Pretend the ACK went missing on the way to host. Re-send same packet. xCORE should ACK but throw pkt away + # Pretend the ACK went missing on the way to host. Re-send same packet + # xCORE should ACK but throw pkt away session.add_event( UsbTransaction( session, diff --git a/tests/test_bulk_rx_basic_nodata.py b/tests/test_bulk_rx_basic_nodata.py index 679acfaf..d92c670a 100644 --- a/tests/test_bulk_rx_basic_nodata.py +++ b/tests/test_bulk_rx_basic_nodata.py @@ -1,10 +1,11 @@ # 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, USB_PID -import pytest -from conftest import PARAMS, test_RunUsbSession # Rx out of seq (but valid.. ) data PID diff --git a/tests/test_bulk_rx_basic_rxerror.py b/tests/test_bulk_rx_basic_rxerror.py index 4385d537..7e27cdaa 100644 --- a/tests/test_bulk_rx_basic_rxerror.py +++ b/tests/test_bulk_rx_basic_rxerror.py @@ -1,10 +1,10 @@ # 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 -import pytest -from conftest import PARAMS, test_RunUsbSession @pytest.fixture diff --git a/tests/test_bulk_rx_multiep.py b/tests/test_bulk_rx_multiep.py index 8860b377..a303db30 100644 --- a/tests/test_bulk_rx_multiep.py +++ b/tests/test_bulk_rx_multiep.py @@ -1,10 +1,12 @@ # Copyright 2019-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_session import UsbSession from usb_transaction import UsbTransaction -import pytest -from conftest import PARAMS, test_RunUsbSession -from copy import deepcopy # EP numbers currently fixed for this test - set in params PARAMS = deepcopy(PARAMS) diff --git a/tests/test_bulk_rx_traffic.py b/tests/test_bulk_rx_traffic.py index 5394c88e..733a892e 100644 --- a/tests/test_bulk_rx_traffic.py +++ b/tests/test_bulk_rx_traffic.py @@ -1,11 +1,11 @@ # 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_phy import USB_MAX_EP_ADDRESS -import pytest -from conftest import PARAMS, test_RunUsbSession @pytest.fixture @@ -69,8 +69,6 @@ def test_session(ep, address, bus_speed): if trafficEp1 < 0: trafficEp1 = USB_MAX_EP_ADDRESS - trafficEp2 + trafficEp2 + 1 - # Don't clash with test EP if trafficEp2 == ep: trafficEp2 = trafficEp1 + 1 diff --git a/tests/test_bulk_tx_badack.py b/tests/test_bulk_tx_badack.py index 49173cd1..ff360d59 100644 --- a/tests/test_bulk_tx_badack.py +++ b/tests/test_bulk_tx_badack.py @@ -1,11 +1,11 @@ # 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_packet import TokenPacket, RxDataPacket, TxHandshakePacket, USB_PID from usb_session import UsbSession from usb_transaction import UsbTransaction -import pytest -from conftest import PARAMS, test_RunUsbSession @pytest.fixture diff --git a/tests/test_bulk_tx_basic.py b/tests/test_bulk_tx_basic.py index 334dbb7b..f967784a 100644 --- a/tests/test_bulk_tx_basic.py +++ b/tests/test_bulk_tx_basic.py @@ -1,22 +1,23 @@ # 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 -import pytest -from conftest import PARAMS, test_RunUsbSession @pytest.fixture def test_session(ep, address, bus_speed): start_length = 10 - end_length = 19 + end_length = start_length + 10 session = UsbSession( bus_speed=bus_speed, run_enumeration=False, device_address=address ) - for pktLength in range(10, end_length + 1): + for pktLength in range(start_length, end_length): session.add_event( UsbTransaction( session, diff --git a/tests/test_bulk_tx_basic_noack.py b/tests/test_bulk_tx_basic_noack.py index 4fd309fd..fbb548e5 100644 --- a/tests/test_bulk_tx_basic_noack.py +++ b/tests/test_bulk_tx_basic_noack.py @@ -1,10 +1,11 @@ # 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_packet import USB_PID, TokenPacket, RxDataPacket from usb_session import UsbSession from usb_transaction import UsbTransaction -import pytest -from conftest import PARAMS, test_RunUsbSession @pytest.fixture diff --git a/tests/test_bulk_tx_basic_short.py b/tests/test_bulk_tx_basic_short.py index 949d302d..fb1e878e 100644 --- a/tests/test_bulk_tx_basic_short.py +++ b/tests/test_bulk_tx_basic_short.py @@ -1,13 +1,14 @@ # 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 -import pytest -from conftest import PARAMS, test_RunUsbSession @pytest.fixture -def test_session(ep, address, bus_speed, dummy_threads): +def test_session(ep, address, bus_speed): start_length = 0 end_length = 7 diff --git a/tests/test_bulk_tx_multiep.py b/tests/test_bulk_tx_multiep.py index af36d8e3..73a57fee 100644 --- a/tests/test_bulk_tx_multiep.py +++ b/tests/test_bulk_tx_multiep.py @@ -1,10 +1,12 @@ # 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_session import UsbSession from usb_transaction import UsbTransaction -import pytest -from conftest import PARAMS, test_RunUsbSession -from copy import deepcopy # EP numbers currently fixed for this test - set in params PARAMS = deepcopy(PARAMS) diff --git a/tests/test_control_basic_badcrc32.py_ b/tests/test_control_basic_badcrc32.py_ deleted file mode 100644 index 8d2779c0..00000000 --- a/tests/test_control_basic_badcrc32.py_ +++ /dev/null @@ -1,59 +0,0 @@ -#!/usr/bin/env python -# Copyright 2016-2021 XMOS LIMITED. -# This Software is subject to the terms of the XMOS Public Licence: Version 1. - -import random -import xmostest -from usb_packet import * -from usb_clock import Clock -from helpers import do_rx_test, packet_processing_time, get_dut_address -from helpers import choose_small_frame_size, check_received_packet, runall_rx - - -# Single, setup transaction to EP 0 - -def do_test(arch, tx_clk, tx_phy, data_valid_count, usb_speed, seed): - rand = random.Random() - rand.seed(seed) - - dev_address = get_dut_address() - ep = 0 - - # The inter-frame gap is to give the DUT time to print its output - packets = [] - - AppendSetupToken(packets, ep) - - # DATA0 data packet with bad CRC - packets.append(TxDataPacket(rand, data_valid_count=data_valid_count, length=8, pid=3, bad_crc=True)) - - # Dont expect an ACK due to bad CRC - #packets.append(RxHandshakePacket()) - - AppendSetupToken(packets, ep, inter_pkt_gap=400) - packets.append(TxDataPacket(rand, data_valid_count=data_valid_count, length=8, pid=3, bad_crc=False )) - packets.append(RxHandshakePacket(data_valid_count=data_valid_count, timeout=11)) - - # Note, quite big gap to allow checking. - - AppendOutToken(packets, ep, inter_pkt_gap=2000) - - packets.append(TxDataPacket(rand, data_valid_count=data_valid_count, length=10, pid=0xb)) - - packets.append(RxHandshakePacket(data_valid_count=data_valid_count)) - - #IN - AppendInToken(packets, ep, inter_pkt_gap=500) - - #Expect 0-length - packets.append(RxDataPacket(rand, data_valid_count=data_valid_count, length=0, pid=0x4b)) - - # Send ACK - packets.append(TxHandshakePacket(data_valid_count=data_valid_count)) - - do_rx_test(arch, tx_clk, tx_phy, usb_speed, packets, __file__, seed, - level='smoke', extra_tasks=[]) - -def runtest(): - random.seed(1) - runall_rx(do_test) diff --git a/tests/test_control_basic_badcrc32/Makefile b/tests/test_control_basic_badcrc32/Makefile deleted file mode 100644 index f0398897..00000000 --- a/tests/test_control_basic_badcrc32/Makefile +++ /dev/null @@ -1,42 +0,0 @@ -# The TARGET variable determines what target system the application is -# compiled for. It either refers to an XN file in the source directories -# or a valid argument for the --target option when compiling. - -TARGET = test.xn - -# The APP_NAME variable determines the name of the final .xe file. It should -# not include the .xe postfix. If left blank the name will default to -# the project name - -APP_NAME = - -# The flags passed to xcc when building the application -# You can also set the following to override flags for a particular language: -# -# XCC_XC_FLAGS, XCC_C_FLAGS, XCC_ASM_FLAGS, XCC_CPP_FLAGS -# -# If the variable XCC_MAP_FLAGS is set it overrides the flags passed to -# xcc for the final link (mapping) stage. - -SHARED_CODE = ../../shared_src - -COMMON_FLAGS = -g -report -DDEBUG_PRINT_ENABLE -save-temps -O3 -Xmapper --map -Xmapper MAPFILE -I$(SHARED_CODE) -DUSB_TILE=tile[0] -DSIMULATION -DARCH_L - -XCC_FLAGS_xs2 = $(COMMON_FLAGS) -DARCH_X200 -DXUD_SERIES_SUPPORT=XUD_X200_SERIES - -ifeq ($(CONFIG),$(filter $(CONFIG),xs2)) - TARGET = test_xs2.xn -endif - - - -# The USED_MODULES variable lists other module used by the application. -USED_MODULES = lib_xud - - -#============================================================================= -# The following part of the Makefile includes the common build infrastructure -# for compiling XMOS applications. You should not need to edit below here. - -XMOS_MAKE_PATH ?= ../.. -include $(XMOS_MAKE_PATH)/xcommon/module_xcommon/build/Makefile.common diff --git a/tests/test_control_basic_badcrc32/src/main.xc b/tests/test_control_basic_badcrc32/src/main.xc deleted file mode 100644 index d57acc45..00000000 --- a/tests/test_control_basic_badcrc32/src/main.xc +++ /dev/null @@ -1,203 +0,0 @@ -// Copyright 2016-2021 XMOS LIMITED. -// This Software is subject to the terms of the XMOS Public Licence: Version 1. -/* - * Test the use of the ExampleTestbench. Test that the value 0 and 1 can be sent - * in both directions between the ports. - * - * NOTE: The src/testbenches/ExampleTestbench must have been compiled for this to run without error. - * - */ -#include -#include -#include -#include "xud.h" -#include "platform.h" -#include "xc_ptr.h" - -#define XUD_EP_COUNT_OUT 5 -#define XUD_EP_COUNT_IN 5 - - -/* Endpoint type tables */ -XUD_EpType epTypeTableOut[XUD_EP_COUNT_OUT] = {XUD_EPTYPE_CTL, - XUD_EPTYPE_BUL, - XUD_EPTYPE_ISO, - XUD_EPTYPE_BUL, - XUD_EPTYPE_BUL}; -XUD_EpType epTypeTableIn[XUD_EP_COUNT_IN] = {XUD_EPTYPE_CTL, XUD_EPTYPE_BUL, XUD_EPTYPE_ISO, XUD_EPTYPE_BUL, XUD_EPTYPE_BUL}; - -void Endpoint0( chanend c_ep0_out, chanend c_ep0_in, chanend ?c_usb_test); - -void exit(int); - -#define FAIL_RX_DATAERROR 0 - -unsigned fail(int x) -{ - - printstr("\nXCORE: ### FAIL ******"); - switch(x) - { - case FAIL_RX_DATAERROR: - printstr("XCORE RX Data Error\n"); - - break; - - } - - exit(1); -} - -unsigned char g_rxDataCheck[5] = {0, 0, 0, 0, 0}; -unsigned char g_txDataCheck[5] = {0,0,0,0,0,}; -unsigned g_txLength[5] = {0,0,0,0,0}; - - -#pragma unsafe arrays -void SendTxPacket(XUD_ep ep, int length, int epNum) -{ - unsigned char buffer[1024]; - - for (int i = 0; i < length; i++) - { - buffer[i] = g_txDataCheck[epNum]++; - } - - XUD_SetBuffer(ep, buffer, length); -} - -#pragma unsafe arrays -int RxDataCheck(unsigned char b[], int l, int epNum) -{ - int fail = 0; - unsigned char x; - - for (int i = 0; i < l; i++) - { - unsigned char y; - //read_byte_via_xc_ptr_indexed(y, p_rxDataCheck, epNum); - if(b[i] != g_rxDataCheck[epNum]) - { - printstr("#### Mismatch on EP: "); - printint(epNum); - printstr(". Got:"); - printhex(b[i]); - printstr(" Expected:"); - printhexln(g_rxDataCheck[epNum]); - //printintln(l); // Packet length - return 1; - } - - g_rxDataCheck[epNum]++; - } - - return 0; -} - -/* Out EP Should receive some data, perform some test process (crc or similar) to check okay */ -/* Answers should be responded to in the IN ep */ - -int TestEp_Control(chanend c_out, chanend c_in, int epNum) -{ - unsigned int slength; - unsigned int length; - XUD_Result_t res; - - XUD_ep c_ep0_out = XUD_InitEp(c_out); - XUD_ep c_ep0_in = XUD_InitEp(c_in); - - /* Buffer for Setup data */ - unsigned char buffer[120]; - - //while(1) - { - /* Wait for Setup data */ - res = XUD_GetControlBuffer(c_ep0_out, buffer, slength); - - if(slength != 8) - { - printintln(length); - fail(FAIL_RX_DATAERROR); - } - - if(RxDataCheck(buffer, slength, epNum)) - { - fail(FAIL_RX_DATAERROR); - } - - res = XUD_GetBuffer(c_ep0_out, buffer, slength); - - if(RxDataCheck(buffer, length, epNum)) - { - fail(FAIL_RX_DATAERROR); - } - - - /* Send 0 length back */ - SendTxPacket(c_ep0_in, 0, epNum); - -#if 0 - res = XUD_GetBuffer(c_ep0_out, buffer, length); - if(RxDataCheck(buffer, length, epNum)) - { - fail(FAIL_RX_DATAERROR); - } - - res = XUD_GetBuffer(c_ep0_out, buffer, length); - if(RxDataCheck(buffer, length, epNum)) - { - fail(FAIL_RX_DATAERROR); - } - - - /* Send 0 length back */ - SendTxPacket(c_ep0_in, 0, epNum); - - /* Wait for Setup data */ - res = XUD_GetSetupBuffer(c_ep0_out, buffer, slength); - - if(slength != 8) - { - printintln(length); - fail(FAIL_RX_DATAERROR); - } - - if(RxDataCheck(buffer, slength, epNum)) - { - fail(FAIL_RX_DATAERROR); - } - - - SendTxPacket(c_ep0_in, length, epNum); - SendTxPacket(c_ep0_in, length, epNum); - SendTxPacket(c_ep0_in, length, epNum); - - res = XUD_GetBuffer(c_ep0_out, buffer, length); - if(length != 0) - { - fail(FAIL_RX_DATAERROR); - } -#endif - exit(0); - - - } -} - -#define USB_CORE 0 -int main() -{ - chan c_ep_out[XUD_EP_COUNT_OUT], c_ep_in[XUD_EP_COUNT_IN]; - - par - { - - XUD_Main(c_ep_out, XUD_EP_COUNT_OUT, c_ep_in, XUD_EP_COUNT_IN, - null, epTypeTableOut, epTypeTableIn, - XUD_SPEED_HS, XUD_PWR_BUS); - - TestEp_Control(c_ep_out[0], c_ep_in[0], 0); - } - - return 0; -} diff --git a/tests/test_control_basic_badcrc32/src/xc_ptr.h b/tests/test_control_basic_badcrc32/src/xc_ptr.h deleted file mode 100644 index 8fa5a04e..00000000 --- a/tests/test_control_basic_badcrc32/src/xc_ptr.h +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2016-2021 XMOS LIMITED. -// This Software is subject to the terms of the XMOS Public Licence: Version 1. -#ifndef __xc_ptr__ -#define __xc_ptr__ - -typedef unsigned int xc_ptr; - -// Note that this function is marked as const to avoid the XC -// parallel usage checks, this is only really going to work if this -// is the *only* way the array a is accessed (and everything else uses -// the xc_ptr) -inline xc_ptr array_to_xc_ptr(const unsigned a[]) -{ - xc_ptr x; - asm("mov %0, %1":"=r"(x):"r"(a)); - return x; -} - -inline xc_ptr char_array_to_xc_ptr(const unsigned char a[]) -{ - xc_ptr x; - asm("mov %0, %1":"=r"(x):"r"(a)); - return x; -} - -#define write_via_xc_ptr_indexed(p,i,x) asm volatile("stw %0, %1[%2]"::"r"(x),"r"(p),"r"(i)) -#define write_byte_via_xc_ptr_indexed(p,i,x) asm volatile("st8 %0, %1[%2]"::"r"(x),"r"(p),"r"(i)) -#define write_byte_via_xc_ptr_indexed(p,i,x) asm volatile("st8 %0, %1[%2]"::"r"(x),"r"(p),"r"(i)) -#define write_short_via_xc_ptr_indexed(p,i,x) asm volatile("st16 %0, %1[%2]"::"r"(x),"r"(p),"r"(i)) - -#define write_via_xc_ptr(p,x) asm volatile("stw %0, %1[0]"::"r"(x),"r"(p)) -// No immediate st8 format -#define write_byte_via_xc_ptr(p,x) write_byte_via_xc_ptr_indexed(p, 0, x) -#define write_short_via_xc_ptr(p,x) write_short_via_xc_ptr_indexed(p, 0, x) - -#define read_via_xc_ptr_indexed(x,p,i) asm("ldw %0, %1[%2]":"=r"(x):"r"(p),"r"(i)); -#define read_byte_via_xc_ptr_indexed(x,p,i) asm("ld8u %0, %1[%2]":"=r"(x):"r"(p),"r"(i)); -#define read_short_via_xc_ptr_indexed(x,p,i) asm("ld16s %0, %1[%2]":"=r"(x):"r"(p),"r"(i)); - -#define read_via_xc_ptr(x,p) asm("ldw %0, %1[0]":"=r"(x):"r"(p)); -// No immediate ld8u format -#define read_byte_via_xc_ptr(x,p) read_byte_via_xc_ptr_indexed(x, p, 0) -#define read_short_via_xc_ptr(x,p) read_short_via_xc_ptr_indexed(x, p, 0) - -#define GET_SHARED_GLOBAL(x, g) asm volatile("ldw %0, dp[" #g "]":"=r"(x)::"memory") -#define SET_SHARED_GLOBAL(g, v) asm volatile("stw %0, dp[" #g "]"::"r"(v):"memory") - -#endif diff --git a/tests/test_control_basic_get.py b/tests/test_control_basic_get.py index 57f40c2a..220df7e8 100644 --- a/tests/test_control_basic_get.py +++ b/tests/test_control_basic_get.py @@ -1,5 +1,10 @@ # 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, @@ -9,10 +14,6 @@ USB_PID, ) from usb_session import UsbSession -from usb_transaction import UsbTransaction -import pytest -from conftest import PARAMS, test_RunUsbSession -from copy import deepcopy # Only test on EP 0 - Update params PARAMS = deepcopy(PARAMS) @@ -66,7 +67,10 @@ def test_session(ep, address, bus_speed): # Send 0 length OUT transaction session.add_event( TokenPacket( - pid=USB_PID["OUT"], address=address, endpoint=ep, interEventDelay=ied + pid=USB_PID["OUT"], + address=address, + endpoint=ep, + interEventDelay=ied, ) ) session.add_event(TxDataPacket(length=0, pid=USB_PID["DATA1"])) diff --git a/tests/test_control_basic_set.py b/tests/test_control_basic_set.py index b34ae639..231e0640 100644 --- a/tests/test_control_basic_set.py +++ b/tests/test_control_basic_set.py @@ -1,5 +1,10 @@ # 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, @@ -9,10 +14,6 @@ USB_PID, ) from usb_session import UsbSession -from usb_transaction import UsbTransaction -import pytest -from conftest import PARAMS, test_RunUsbSession -from copy import deepcopy # Only test on EP 0 - Update params PARAMS = deepcopy(PARAMS) @@ -21,7 +22,7 @@ @pytest.fixture -def test_session(ep, address, bus_speed, dummy_threads): +def test_session(ep, address, bus_speed): ied = 500 @@ -69,7 +70,10 @@ def test_session(ep, address, bus_speed, dummy_threads): # Expect 0 length IN transaction session.add_event( TokenPacket( - pid=USB_PID["IN"], address=address, endpoint=ep, interEventDelay=ied + pid=USB_PID["IN"], + address=address, + endpoint=ep, + interEventDelay=ied, ) ) session.add_event(RxDataPacket(dataPayload=[], pid=USB_PID["DATA1"])) diff --git a/tests/test_control_basic_short.py_ b/tests/test_control_basic_short.py_ deleted file mode 100644 index 5da143de..00000000 --- a/tests/test_control_basic_short.py_ +++ /dev/null @@ -1,67 +0,0 @@ -#!/usr/bin/env python -# Copyright 2016-2021 XMOS LIMITED. -# This Software is subject to the terms of the XMOS Public Licence: Version 1. - -#Generate a SETUP transaction that is too short... with a bad CRC -#Dont really expect a short packet with a good CRC - would be a very bad host (though would be good to be able to handle this..) - -import random -import xmostest -from usb_packet import AppendSetupToken, TxDataPacket, RxDataPacket, TokenPacket, RxHandshakePacket, TxHandshakePacket -from usb_clock import Clock -from helpers import do_rx_test, packet_processing_time, get_dut_address -from helpers import choose_small_frame_size, check_received_packet, runall_rx - - -# Single, setup transaction to EP 0 - -def do_test(arch, tx_clk, tx_phy, data_valid_count, usb_speed, seed): - rand = random.Random() - rand.seed(seed) - - dev_address = get_dut_address() - ep = 0 - - # The inter-frame gap is to give the DUT time to print its output - packets = [] - - AppendSetupToken(packets, ep) - packets.append(TxDataPacket(rand, data_valid_count=data_valid_count, length=3, pid=3, bad_crc=True)) - #packets.append(RxHandshakePacket(data_valid_count=data_valid_count)) - - AppendSetupToken(packets, ep) - packets.append(TxDataPacket(rand, data_valid_count=data_valid_count, length=8, pid=3, bad_crc=False)) - packets.append(RxHandshakePacket(data_valid_count=data_valid_count, timeout=11)) - - # Note, quite big gap to allow checking. - - packets.append(TokenPacket( - data_valid_count=data_valid_count, - inter_pkt_gap=2000, - pid=0xe1, #OUT - address=dev_address, - endpoint=ep)) - - packets.append(TxDataPacket(rand, data_valid_count=data_valid_count, length=10, pid=0xb)) - - packets.append(RxHandshakePacket(data_valid_count=data_valid_count)) - - packets.append(TokenPacket( - data_valid_count=data_valid_count, - inter_pkt_gap=2000, - pid=0x69, #OUT - address=dev_address, - endpoint=ep)) - - #Expect 0-length - packets.append(RxDataPacket(rand, data_valid_count=data_valid_count, length=0, pid=0x4b)) - - # Send ACK - packets.append(TxHandshakePacket(data_valid_count=data_valid_count)) - - do_rx_test(arch, tx_clk, tx_phy, usb_speed, packets, __file__, seed, - level='smoke', extra_tasks=[]) - -def runtest(): - random.seed(1) - runall_rx(do_test) diff --git a/tests/test_control_basic_short/src/main.xc b/tests/test_control_basic_short/src/main.xc deleted file mode 100644 index cf20ea0f..00000000 --- a/tests/test_control_basic_short/src/main.xc +++ /dev/null @@ -1,239 +0,0 @@ -// Copyright 2016-2021 XMOS LIMITED. -// This Software is subject to the terms of the XMOS Public Licence: Version 1. -/* - * Test the use of the ExampleTestbench. Test that the value 0 and 1 can be sent - * in both directions between the ports. - * - * NOTE: The src/testbenches/ExampleTestbench must have been compiled for this to run without error. - * - */ -#include -#include -#include -#include "xud.h" -#include "platform.h" -//#include "test.h" -#include "xc_ptr.h" - -//#error - -#define XUD_EP_COUNT_OUT 5 -#define XUD_EP_COUNT_IN 5 - -//extern xc_ptr char_array_to_xc_ptr(const unsigned char a[]); - -/* Endpoint type tables */ -XUD_EpType epTypeTableOut[XUD_EP_COUNT_OUT] = {XUD_EPTYPE_CTL, - XUD_EPTYPE_BUL, - XUD_EPTYPE_ISO, - XUD_EPTYPE_BUL, - XUD_EPTYPE_BUL}; -XUD_EpType epTypeTableIn[XUD_EP_COUNT_IN] = {XUD_EPTYPE_CTL, XUD_EPTYPE_BUL, XUD_EPTYPE_ISO, XUD_EPTYPE_BUL, XUD_EPTYPE_BUL}; - -/* USB Port declarations */ -//on stdcore[0]: out port p_usb_rst = XS1_PORT_1A; -//on stdcore[0]: clock clk = XS1_CLKBLK_3; - -//on stdcore[0] : out port p_test = XS1_PORT_1I; - -void Endpoint0( chanend c_ep0_out, chanend c_ep0_in, chanend ?c_usb_test); - -void exit(int); - -#define FAIL_RX_DATAERROR 0 - -unsigned fail(int x) -{ - - printstr("\nXCORE: ### FAIL ******"); - switch(x) - { - case FAIL_RX_DATAERROR: - printstr("XCORE RX Data Error\n"); - - break; - - } - - exit(1); -} - -unsigned char g_rxDataCheck[5] = {0, 0, 0, 0, 0}; -unsigned char g_txDataCheck[5] = {0,0,0,0,0,}; -unsigned g_txLength[5] = {0,0,0,0,0}; - - -#pragma unsafe arrays -void SendTxPacket(XUD_ep ep, int length, int epNum) -{ - unsigned char buffer[1024]; - unsigned char x; - - for (int i = 0; i < length; i++) - { - buffer[i] = g_txDataCheck[epNum]++; - - //asm("ld8u %0, %1[%2]":"=r"(x):"r"(g_txDataCheck),"r"(epNum)); - // read_byte_via_xc_ptr_indexed(x, p_txDataCheck, epNum); - - //buffer[i] = x; - //x++; - //asm("st8 %0, %1[%2]"::"r"(x),"r"(g_txDataCheck),"r"(epNum)); - //write_byte_via_xc_ptr_indexed(p_txDataCheck,epNum,x); - } - - XUD_SetBuffer(ep, buffer, length); -} - - - - - -//xc_ptr p_rxDataCheck; -//xc_ptr p_txDataCheck; -//xc_ptr p_txLength; - -#pragma unsafe arrays -int RxDataCheck(unsigned char b[], int l, int epNum) -{ - int fail = 0; - unsigned char x; - - for (int i = 0; i < l; i++) - { - unsigned char y; - //read_byte_via_xc_ptr_indexed(y, p_rxDataCheck, epNum); - if(b[i] != g_rxDataCheck[epNum]) - { - printstr("#### Mismatch on EP: "); - printint(epNum); - printstr(". Got:"); - printhex(b[i]); - printstr(" Expected:"); - printhexln(g_rxDataCheck[epNum]); - //printintln(l); // Packet length - return 1; - } - - g_rxDataCheck[epNum]++; - //read_byte_via_xc_ptr_indexed(x, p_rxDataCheck, epNum); - //x++; - //write_byte_via_xc_ptr_indexed(p_rxDataCheck,epNum,x); - } - - return 0; -} - -/* Out EP Should receive some data, perform some test process (crc or similar) to check okay */ -/* Answers should be responded to in the IN ep */ - -int TestEp_Control(chanend c_out, chanend c_in, int epNum) -{ - unsigned int slength; - unsigned int length; - XUD_Result_t res; - - XUD_ep c_ep0_out = XUD_InitEp(c_out); - XUD_ep c_ep0_in = XUD_InitEp(c_in); - - /* Buffer for Setup data */ - unsigned char buffer[120]; - - //while(1) - { - /* Wait for Setup data */ - res = XUD_GetControlBuffer(c_ep0_out, buffer, slength); - - if(slength != 8) - { - printintln(length); - fail(FAIL_RX_DATAERROR); - } - - if(RxDataCheck(buffer, slength, epNum)) - { - fail(FAIL_RX_DATAERROR); - } - - res = XUD_GetBuffer(c_ep0_out, buffer, slength); - - if(RxDataCheck(buffer, length, epNum)) - { - fail(FAIL_RX_DATAERROR); - } - - - /* Send 0 length back */ - SendTxPacket(c_ep0_in, 0, epNum); - -#if 0 - res = XUD_GetBuffer(c_ep0_out, buffer, length); - if(RxDataCheck(buffer, length, epNum)) - { - fail(FAIL_RX_DATAERROR); - } - - res = XUD_GetBuffer(c_ep0_out, buffer, length); - if(RxDataCheck(buffer, length, epNum)) - { - fail(FAIL_RX_DATAERROR); - } - - - /* Send 0 length back */ - SendTxPacket(c_ep0_in, 0, epNum); - - /* Wait for Setup data */ - res = XUD_GetSetupBuffer(c_ep0_out, buffer, slength); - - if(slength != 8) - { - printintln(length); - fail(FAIL_RX_DATAERROR); - } - - if(RxDataCheck(buffer, slength, epNum)) - { - fail(FAIL_RX_DATAERROR); - } - - - SendTxPacket(c_ep0_in, length, epNum); - SendTxPacket(c_ep0_in, length, epNum); - SendTxPacket(c_ep0_in, length, epNum); - - res = XUD_GetBuffer(c_ep0_out, buffer, length); - if(length != 0) - { - fail(FAIL_RX_DATAERROR); - } -#endif - exit(0); - - - } -} - -#define USB_CORE 0 -int main() -{ - chan c_ep_out[XUD_EP_COUNT_OUT], c_ep_in[XUD_EP_COUNT_IN]; - chan c_sync; - chan c_sync_iso; - - //p_rxDataCheck = char_array_to_xc_ptr(g_rxDataCheck); - //p_txDataCheck = char_array_to_xc_ptr(g_txDataCheck); - //p_txLength = array_to_xc_ptr(g_txLength); - - par - { - - XUD_Manager( c_ep_out, XUD_EP_COUNT_OUT, c_ep_in, XUD_EP_COUNT_IN, - null, epTypeTableOut, epTypeTableIn, - XUD_SPEED_HS, XUD_PWR_BUS); - - TestEp_Control(c_ep_out[0], c_ep_in[0], 0); - } - - return 0; -} diff --git a/tests/test_control_basic_short/src/xc_ptr.h b/tests/test_control_basic_short/src/xc_ptr.h deleted file mode 100644 index 8fa5a04e..00000000 --- a/tests/test_control_basic_short/src/xc_ptr.h +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2016-2021 XMOS LIMITED. -// This Software is subject to the terms of the XMOS Public Licence: Version 1. -#ifndef __xc_ptr__ -#define __xc_ptr__ - -typedef unsigned int xc_ptr; - -// Note that this function is marked as const to avoid the XC -// parallel usage checks, this is only really going to work if this -// is the *only* way the array a is accessed (and everything else uses -// the xc_ptr) -inline xc_ptr array_to_xc_ptr(const unsigned a[]) -{ - xc_ptr x; - asm("mov %0, %1":"=r"(x):"r"(a)); - return x; -} - -inline xc_ptr char_array_to_xc_ptr(const unsigned char a[]) -{ - xc_ptr x; - asm("mov %0, %1":"=r"(x):"r"(a)); - return x; -} - -#define write_via_xc_ptr_indexed(p,i,x) asm volatile("stw %0, %1[%2]"::"r"(x),"r"(p),"r"(i)) -#define write_byte_via_xc_ptr_indexed(p,i,x) asm volatile("st8 %0, %1[%2]"::"r"(x),"r"(p),"r"(i)) -#define write_byte_via_xc_ptr_indexed(p,i,x) asm volatile("st8 %0, %1[%2]"::"r"(x),"r"(p),"r"(i)) -#define write_short_via_xc_ptr_indexed(p,i,x) asm volatile("st16 %0, %1[%2]"::"r"(x),"r"(p),"r"(i)) - -#define write_via_xc_ptr(p,x) asm volatile("stw %0, %1[0]"::"r"(x),"r"(p)) -// No immediate st8 format -#define write_byte_via_xc_ptr(p,x) write_byte_via_xc_ptr_indexed(p, 0, x) -#define write_short_via_xc_ptr(p,x) write_short_via_xc_ptr_indexed(p, 0, x) - -#define read_via_xc_ptr_indexed(x,p,i) asm("ldw %0, %1[%2]":"=r"(x):"r"(p),"r"(i)); -#define read_byte_via_xc_ptr_indexed(x,p,i) asm("ld8u %0, %1[%2]":"=r"(x):"r"(p),"r"(i)); -#define read_short_via_xc_ptr_indexed(x,p,i) asm("ld16s %0, %1[%2]":"=r"(x):"r"(p),"r"(i)); - -#define read_via_xc_ptr(x,p) asm("ldw %0, %1[0]":"=r"(x):"r"(p)); -// No immediate ld8u format -#define read_byte_via_xc_ptr(x,p) read_byte_via_xc_ptr_indexed(x, p, 0) -#define read_short_via_xc_ptr(x,p) read_short_via_xc_ptr_indexed(x, p, 0) - -#define GET_SHARED_GLOBAL(x, g) asm volatile("ldw %0, dp[" #g "]":"=r"(x)::"memory") -#define SET_SHARED_GLOBAL(g, v) asm volatile("stw %0, dp[" #g "]"::"r"(v):"memory") - -#endif diff --git a/tests/test_control_repeatedsetup.py_ b/tests/test_control_repeatedsetup.py_ deleted file mode 100644 index aec6de1f..00000000 --- a/tests/test_control_repeatedsetup.py_ +++ /dev/null @@ -1,60 +0,0 @@ -#!/usr/bin/env python -# Copyright 2016-2021 XMOS LIMITED. -# This Software is subject to the terms of the XMOS Public Licence: Version 1. - -import random -import xmostest -from usb_packet import AppendSetupToken, TxDataPacket, RxDataPacket, TokenPacket, RxHandshakePacket, TxHandshakePacket -from usb_clock import Clock -from helpers import do_rx_test, packet_processing_time, get_dut_address -from helpers import choose_small_frame_size, check_received_packet, runall_rx - - -# Single, setup transaction to EP 0 - -def do_test(arch, tx_clk, tx_phy, data_valid_count, usb_speed, seed): - rand = random.Random() - rand.seed(seed) - - ep = 0 - - # The inter-frame gap is to give the DUT time to print its output - packets = [] - - AppendSetupToken(packets, ep) - packets.append(TxDataPacket(rand, data_valid_count=data_valid_count, length=8, pid=3)) - packets.append(RxHandshakePacket(data_valid_count=data_valid_count, timeout=11)) - - # Note, quite big gap to allow checking. - - # Send Setup transaction again (simulated ACK lost on way to host - AppendSetupToken(packets, ep, inter_pkt_gap=2000) - packets.append(TxDataPacket(rand, data_valid_count=data_valid_count, length=8, pid=3)) - packets.append(RxHandshakePacket(data_valid_count=data_valid_count, timeout=11)) - - packets.append(TokenPacket( - data_valid_count=data_valid_count, - inter_pkt_gap=2000, - pid=0xe1, #OUT - endpoint=ep)) - packets.append(TxDataPacket(rand, data_valid_count=data_valid_count, length=10, pid=0xb)) - packets.append(RxHandshakePacket(data_valid_count=data_valid_count)) - - packets.append(TokenPacket( - data_valid_count=data_valid_count, - inter_pkt_gap=2000, - pid=0x69, #IN - endpoint=ep)) - - #Expect 0-length - packets.append(RxDataPacket(rand, data_valid_count=data_valid_count, length=0, pid=0x4b)) - - # Send ACK - packets.append(TxHandshakePacket(data_valid_count=data_valid_count)) - - do_rx_test(arch, tx_clk, tx_phy, usb_speed, packets, __file__, seed, - level='smoke', extra_tasks=[]) - -def runtest(): - random.seed(1) - runall_rx(do_test) diff --git a/tests/test_control_repeatedsetup/Makefile b/tests/test_control_repeatedsetup/Makefile deleted file mode 100644 index f0398897..00000000 --- a/tests/test_control_repeatedsetup/Makefile +++ /dev/null @@ -1,42 +0,0 @@ -# The TARGET variable determines what target system the application is -# compiled for. It either refers to an XN file in the source directories -# or a valid argument for the --target option when compiling. - -TARGET = test.xn - -# The APP_NAME variable determines the name of the final .xe file. It should -# not include the .xe postfix. If left blank the name will default to -# the project name - -APP_NAME = - -# The flags passed to xcc when building the application -# You can also set the following to override flags for a particular language: -# -# XCC_XC_FLAGS, XCC_C_FLAGS, XCC_ASM_FLAGS, XCC_CPP_FLAGS -# -# If the variable XCC_MAP_FLAGS is set it overrides the flags passed to -# xcc for the final link (mapping) stage. - -SHARED_CODE = ../../shared_src - -COMMON_FLAGS = -g -report -DDEBUG_PRINT_ENABLE -save-temps -O3 -Xmapper --map -Xmapper MAPFILE -I$(SHARED_CODE) -DUSB_TILE=tile[0] -DSIMULATION -DARCH_L - -XCC_FLAGS_xs2 = $(COMMON_FLAGS) -DARCH_X200 -DXUD_SERIES_SUPPORT=XUD_X200_SERIES - -ifeq ($(CONFIG),$(filter $(CONFIG),xs2)) - TARGET = test_xs2.xn -endif - - - -# The USED_MODULES variable lists other module used by the application. -USED_MODULES = lib_xud - - -#============================================================================= -# The following part of the Makefile includes the common build infrastructure -# for compiling XMOS applications. You should not need to edit below here. - -XMOS_MAKE_PATH ?= ../.. -include $(XMOS_MAKE_PATH)/xcommon/module_xcommon/build/Makefile.common diff --git a/tests/test_control_repeatedsetup/src/main.xc b/tests/test_control_repeatedsetup/src/main.xc deleted file mode 100644 index baa95519..00000000 --- a/tests/test_control_repeatedsetup/src/main.xc +++ /dev/null @@ -1,139 +0,0 @@ -// Copyright 2016-2021 XMOS LIMITED. -// This Software is subject to the terms of the XMOS Public Licence: Version 1. -/* - * Test the use of the ExampleTestbench. Test that the value 0 and 1 can be sent - * in both directions between the ports. - * - * NOTE: The src/testbenches/ExampleTestbench must have been compiled for this to run without error. - * - */ -#include -#include -#include -#include "xud.h" -#include "platform.h" -#include "shared.h" - -#define XUD_EP_COUNT_OUT 5 -#define XUD_EP_COUNT_IN 5 - -/* Endpoint type tables */ -XUD_EpType epTypeTableOut[XUD_EP_COUNT_OUT] = {XUD_EPTYPE_CTL, - XUD_EPTYPE_BUL, - XUD_EPTYPE_ISO, - XUD_EPTYPE_BUL, - XUD_EPTYPE_BUL}; -XUD_EpType epTypeTableIn[XUD_EP_COUNT_IN] = {XUD_EPTYPE_CTL, XUD_EPTYPE_BUL, XUD_EPTYPE_ISO, XUD_EPTYPE_BUL, XUD_EPTYPE_BUL}; - -int TestEp_Control(chanend c_out, chanend c_in, int epNum) -{ - unsigned int slength; - unsigned int length; - XUD_Result_t res; - - XUD_ep c_ep0_out = XUD_InitEp(c_out); - XUD_ep c_ep0_in = XUD_InitEp(c_in); - - /* Buffer for Setup data */ - unsigned char buffer[120]; - - unsafe - { - /* Wait for Setup data */ - - res = XUD_GetControlBuffer(c_ep0_out, buffer, slength); - - if(slength != 8) - { - fail(FAIL_RX_DATAERROR); - } - - if(RxDataCheck(buffer, slength, epNum)) - { - fail(FAIL_RX_DATAERROR); - } - - if(res != XUD_RES_CTL) - { - fail(FAIL_RX_EXPECTED_CTL); - } - - g_rxDataCheck_[epNum] = 0; - - res = XUD_GetControlBuffer(c_ep0_out, buffer, slength); - - if(RxDataCheck(buffer, length, epNum)) - { - fail(FAIL_RX_DATAERROR); - } - - res = XUD_GetControlBuffer(c_ep0_out, buffer, slength); - - /* Send 0 length back */ - SendTxPacket(c_ep0_in, 0, epNum); - -#if 0 - res = XUD_GetControlBuffer(c_ep0_out, buffer, length); - if(RxDataCheck(buffer, length, epNum)) - { - fail(FAIL_RX_DATAERROR); - } - - res = XUD_GetControlBuffer(c_ep0_out, buffer, length); - if(RxDataCheck(buffer, length, epNum)) - { - fail(FAIL_RX_DATAERROR); - } - - - /* Send 0 length back */ - SendTxPacket(c_ep0_in, 0, epNum); - - /* Wait for Setup data */ - res = XUD_GetControlBuffer(c_ep0_out, buffer, slength); - - if(slength != 8) - { - printintln(length); - fail(FAIL_RX_DATAERROR); - } - - if(RxDataCheck(buffer, slength, epNum)) - { - fail(FAIL_RX_DATAERROR); - } - - - SendTxPacket(c_ep0_in, length, epNum); - SendTxPacket(c_ep0_in, length, epNum); - SendTxPacket(c_ep0_in, length, epNum); - - res = XUD_GetControlBuffer(c_ep0_out, buffer, length); - if(length != 0) - { - fail(FAIL_RX_DATAERROR); - } -#endif - exit(0); - - - } -} - -#define USB_CORE 0 -int main() -{ - chan c_ep_out[XUD_EP_COUNT_OUT], c_ep_in[XUD_EP_COUNT_IN]; - - par - { - - XUD_Main( c_ep_out, XUD_EP_COUNT_OUT, c_ep_in, XUD_EP_COUNT_IN, - null, epTypeTableOut, epTypeTableIn, - null, null, -1, XUD_SPEED_HS, XUD_PWR_BUS); - - TestEp_Control(c_ep_out[0], c_ep_in[0], 0); - } - - return 0; -} diff --git a/tests/test_control_repeatedsetup/src/xc_ptr.h b/tests/test_control_repeatedsetup/src/xc_ptr.h deleted file mode 100644 index 8fa5a04e..00000000 --- a/tests/test_control_repeatedsetup/src/xc_ptr.h +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2016-2021 XMOS LIMITED. -// This Software is subject to the terms of the XMOS Public Licence: Version 1. -#ifndef __xc_ptr__ -#define __xc_ptr__ - -typedef unsigned int xc_ptr; - -// Note that this function is marked as const to avoid the XC -// parallel usage checks, this is only really going to work if this -// is the *only* way the array a is accessed (and everything else uses -// the xc_ptr) -inline xc_ptr array_to_xc_ptr(const unsigned a[]) -{ - xc_ptr x; - asm("mov %0, %1":"=r"(x):"r"(a)); - return x; -} - -inline xc_ptr char_array_to_xc_ptr(const unsigned char a[]) -{ - xc_ptr x; - asm("mov %0, %1":"=r"(x):"r"(a)); - return x; -} - -#define write_via_xc_ptr_indexed(p,i,x) asm volatile("stw %0, %1[%2]"::"r"(x),"r"(p),"r"(i)) -#define write_byte_via_xc_ptr_indexed(p,i,x) asm volatile("st8 %0, %1[%2]"::"r"(x),"r"(p),"r"(i)) -#define write_byte_via_xc_ptr_indexed(p,i,x) asm volatile("st8 %0, %1[%2]"::"r"(x),"r"(p),"r"(i)) -#define write_short_via_xc_ptr_indexed(p,i,x) asm volatile("st16 %0, %1[%2]"::"r"(x),"r"(p),"r"(i)) - -#define write_via_xc_ptr(p,x) asm volatile("stw %0, %1[0]"::"r"(x),"r"(p)) -// No immediate st8 format -#define write_byte_via_xc_ptr(p,x) write_byte_via_xc_ptr_indexed(p, 0, x) -#define write_short_via_xc_ptr(p,x) write_short_via_xc_ptr_indexed(p, 0, x) - -#define read_via_xc_ptr_indexed(x,p,i) asm("ldw %0, %1[%2]":"=r"(x):"r"(p),"r"(i)); -#define read_byte_via_xc_ptr_indexed(x,p,i) asm("ld8u %0, %1[%2]":"=r"(x):"r"(p),"r"(i)); -#define read_short_via_xc_ptr_indexed(x,p,i) asm("ld16s %0, %1[%2]":"=r"(x):"r"(p),"r"(i)); - -#define read_via_xc_ptr(x,p) asm("ldw %0, %1[0]":"=r"(x):"r"(p)); -// No immediate ld8u format -#define read_byte_via_xc_ptr(x,p) read_byte_via_xc_ptr_indexed(x, p, 0) -#define read_short_via_xc_ptr(x,p) read_short_via_xc_ptr_indexed(x, p, 0) - -#define GET_SHARED_GLOBAL(x, g) asm volatile("ldw %0, dp[" #g "]":"=r"(x)::"memory") -#define SET_SHARED_GLOBAL(g, v) asm volatile("stw %0, dp[" #g "]"::"r"(v):"memory") - -#endif diff --git a/tests/test_control_traffic.py b/tests/test_control_traffic.py index 37f38ce4..b062e589 100644 --- a/tests/test_control_traffic.py +++ b/tests/test_control_traffic.py @@ -1,5 +1,10 @@ # 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, @@ -9,10 +14,6 @@ USB_PID, ) from usb_session import UsbSession -from usb_transaction import UsbTransaction -import pytest -from conftest import PARAMS, test_RunUsbSession -from copy import deepcopy # Only test on EP 0 - Update params PARAMS = deepcopy(PARAMS) @@ -108,7 +109,10 @@ def test_session(ep, address, bus_speed): # Send 0 length OUT transaction session.add_event( TokenPacket( - pid=USB_PID["OUT"], address=address, endpoint=ep, interEventDelay=ied + pid=USB_PID["OUT"], + address=address, + endpoint=ep, + interEventDelay=ied, ) ) session.add_event(TxDataPacket(length=0, pid=USB_PID["DATA1"])) diff --git a/tests/test_device_attach.py b/tests/test_device_attach.py index d4b653e9..78b26167 100644 --- a/tests/test_device_attach.py +++ b/tests/test_device_attach.py @@ -1,12 +1,14 @@ # 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 CreateSofToken from usb_session import UsbSession from usb_transaction import UsbTransaction from usb_signalling import UsbDeviceAttach -import pytest -from conftest import PARAMS, test_RunUsbSession -from copy import deepcopy # Only need to run device attach tests for one ep/address PARAMS = deepcopy(PARAMS) @@ -17,8 +19,6 @@ @pytest.fixture def test_session(ep, address, bus_speed): - start_length = 10 - end_length = 12 pktLength = 10 frameNumber = 52 # Note, for frame number 52 we expect A5 34 40 on the bus diff --git a/tests/test_invalidtoken.py b/tests/test_invalidtoken.py index e868c4ed..6d966a28 100644 --- a/tests/test_invalidtoken.py +++ b/tests/test_invalidtoken.py @@ -2,18 +2,12 @@ # This Software is subject to the terms of the XMOS Public Licence: Version 1. # Same as simple RX bulk test but some invalid tokens also included -from usb_packet import ( - TokenPacket, - TxDataPacket, - RxDataPacket, - TxHandshakePacket, - RxHandshakePacket, - USB_PID, -) +import pytest + +from conftest import PARAMS, test_RunUsbSession # noqa F401 +from usb_packet import TokenPacket, USB_PID from usb_session import UsbSession from usb_transaction import UsbTransaction -import pytest -from conftest import PARAMS, test_RunUsbSession @pytest.fixture diff --git a/tests/test_iso_loopback.py b/tests/test_iso_loopback.py index f3af6362..284f65ae 100644 --- a/tests/test_iso_loopback.py +++ b/tests/test_iso_loopback.py @@ -1,9 +1,10 @@ # 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 -import pytest -from conftest import PARAMS, test_RunUsbSession @pytest.fixture diff --git a/tests/test_iso_rx_basic.py b/tests/test_iso_rx_basic.py index 37e41a4a..90aac9ab 100644 --- a/tests/test_iso_rx_basic.py +++ b/tests/test_iso_rx_basic.py @@ -1,22 +1,23 @@ # 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 -import pytest -from conftest import PARAMS, test_RunUsbSession @pytest.fixture def test_session(ep, address, bus_speed): start_length = 10 - end_length = 14 + end_length = start_length + 5 session = UsbSession( bus_speed=bus_speed, run_enumeration=False, device_address=address ) - for pktLength in range(10, end_length + 1): + for pktLength in range(start_length, end_length): session.add_event( UsbTransaction( session, diff --git a/tests/test_iso_rxtx_fastpacket.py b/tests/test_iso_rxtx_fastpacket.py index dc157bc8..040c6886 100644 --- a/tests/test_iso_rxtx_fastpacket.py +++ b/tests/test_iso_rxtx_fastpacket.py @@ -1,9 +1,10 @@ # 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 -import pytest -from conftest import PARAMS, test_RunUsbSession @pytest.fixture diff --git a/tests/test_iso_tx_basic.py b/tests/test_iso_tx_basic.py index 1a65d543..7765f70b 100644 --- a/tests/test_iso_tx_basic.py +++ b/tests/test_iso_tx_basic.py @@ -1,16 +1,17 @@ # 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 -import pytest -from conftest import PARAMS, test_RunUsbSession @pytest.fixture -def test_session(ep, address, bus_speed, dummy_threads): +def test_session(ep, address, bus_speed): start_length = 10 - end_length = 14 + end_length = start_length + 5 session = UsbSession( bus_speed=bus_speed, @@ -19,7 +20,7 @@ def test_session(ep, address, bus_speed, dummy_threads): initial_delay=100000, ) - for pktLength in range(10, end_length + 1): + for pktLength in range(start_length, end_length): session.add_event( UsbTransaction( session, diff --git a/tests/test_makefile.mak b/tests/test_makefile.mak index 13501762..27658d3c 100644 --- a/tests/test_makefile.mak +++ b/tests/test_makefile.mak @@ -44,7 +44,7 @@ ifndef XUD_STARTUP_ADDRESS $(error XUD_STARTUP_ADDRESS is not set) endif -XCC_FLAGS_$(TEST_ARCH)_$(TEST_FREQ)_$(TEST_DTHREADS)_$(TEST_EP_NUM)_$(XUD_STARTUP_ADDRESS) = $(TEST_FLAGS) $(COMMON_FLAGS) +XCC_FLAGS_$(TEST_ARCH)_$(TEST_FREQ)_$(TEST_DTHREADS)_$(TEST_EP_NUM)_$(XUD_STARTUP_ADDRESS)_$(BUS_SPEED) = $(TEST_FLAGS) $(COMMON_FLAGS) # The TARGET variable determines what target system the application is # compiled for. It either refers to an XN file in the source directories diff --git a/tests/test_ping_rx_basic.py b/tests/test_ping_rx_basic.py index 90f77e29..9f095699 100644 --- a/tests/test_ping_rx_basic.py +++ b/tests/test_ping_rx_basic.py @@ -3,18 +3,16 @@ # This Software is subject to the terms of the XMOS Public Licence: Version 1. # Basic check of PING functionality +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 -import pytest -from conftest import PARAMS, test_RunUsbSession @pytest.fixture diff --git a/tests/test_ping_stall.py b/tests/test_ping_stall.py index 7a27b558..b3f9584e 100644 --- a/tests/test_ping_stall.py +++ b/tests/test_ping_stall.py @@ -1,11 +1,12 @@ # 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, USB_PID, RxHandshakePacket -import pytest -from conftest import PARAMS, test_RunUsbSession @pytest.fixture diff --git a/tests/test_shorttoken.py b/tests/test_shorttoken.py index fea5e86a..aed20601 100644 --- a/tests/test_shorttoken.py +++ b/tests/test_shorttoken.py @@ -1,11 +1,13 @@ #!/usr/bin/env python # Copyright 2019-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_packet import TxPacket, USB_PID from usb_session import UsbSession from usb_transaction import UsbTransaction -import pytest -from conftest import PARAMS, test_RunUsbSession + # TODO Can this be moved? @pytest.fixture @@ -38,7 +40,8 @@ def test_session(ep, address, bus_speed, arch): ) ) - # tmp hack for xs2 - for xs2 the shim will throw away the short token and it will never be seen by the xCORE + # tmp hack for xs2 - for xs2 the shim will throw away the short token and + # it will never be seen by the xCORE if arch == "xs3": # Create a short token, only PID and 2nd byte shorttoken = TxPacket( diff --git a/tests/test_sof_badcrc.py b/tests/test_sof_badcrc.py index f83558e7..6700fc53 100644 --- a/tests/test_sof_badcrc.py +++ b/tests/test_sof_badcrc.py @@ -1,11 +1,12 @@ #!/usr/bin/env python # Copyright 2019-2021 XMOS LIMITED. # This Software is subject to the terms of the XMOS Public Licence: Version 1. -from usb_packet import TokenPacket, USB_PID, CreateSofToken +import pytest + +from conftest import PARAMS, test_RunUsbSession # noqa F401 +from usb_packet import CreateSofToken from usb_session import UsbSession from usb_transaction import UsbTransaction -import pytest -from conftest import PARAMS, test_RunUsbSession @pytest.fixture diff --git a/tests/test_sof_basic.py b/tests/test_sof_basic.py index e2f2edae..b5ecb8b2 100644 --- a/tests/test_sof_basic.py +++ b/tests/test_sof_basic.py @@ -1,10 +1,11 @@ # Copyright 2019-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 CreateSofToken -import pytest -from conftest import PARAMS, test_RunUsbSession @pytest.fixture diff --git a/tests/test_stall_basic.py b/tests/test_stall_basic.py index 7ee02d3a..a478f1bb 100644 --- a/tests/test_stall_basic.py +++ b/tests/test_stall_basic.py @@ -1,9 +1,10 @@ # 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 -import pytest -from conftest import PARAMS, test_RunUsbSession @pytest.fixture @@ -106,6 +107,7 @@ def test_session(ep, address, bus_speed): # for result in RunUsbTest( -# gen_test_session, test_arch, test_ep, test_address, test_bus_speed, __file__ +# gen_test_session, test_arch, test_ep, test_address, +# test_bus_speed, __file__ # ): # assert result diff --git a/tests/test_stall_control.py b/tests/test_stall_control.py index 1705dd42..e8b5e310 100644 --- a/tests/test_stall_control.py +++ b/tests/test_stall_control.py @@ -1,5 +1,10 @@ # 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, @@ -10,9 +15,6 @@ ) from usb_session import UsbSession from usb_transaction import UsbTransaction -import pytest -from conftest import PARAMS, test_RunUsbSession -from copy import deepcopy # Only test on EP 0 - Update params PARAMS = deepcopy(PARAMS) @@ -22,7 +24,7 @@ @pytest.fixture -def test_session(ep, address, bus_speed, dummy_threads): +def test_session(ep, address, bus_speed): ied = 500 pktLength = 10 @@ -31,7 +33,7 @@ def test_session(ep, address, bus_speed, dummy_threads): bus_speed=bus_speed, run_enumeration=False, device_address=address ) - #### Ctrl transaction 0 + # Ctrl transaction 0 # SETUP transaction session.add_event( @@ -70,13 +72,16 @@ def test_session(ep, address, bus_speed, dummy_threads): # Expect 0 length IN transaction session.add_event( TokenPacket( - pid=USB_PID["IN"], address=address, endpoint=ep, interEventDelay=ied + pid=USB_PID["IN"], + address=address, + endpoint=ep, + interEventDelay=ied, ) ) session.add_event(RxDataPacket(dataPayload=[], pid=USB_PID["DATA1"])) session.add_event(TxHandshakePacket()) - #### Ctrl transaction 1 + # Ctrl transaction 1 # SETUP transaction session.add_event( @@ -109,7 +114,7 @@ def test_session(ep, address, bus_speed, dummy_threads): ) ) - #### Ctrl transaction 2 + # Ctrl transaction 2 # SETUP transaction session.add_event( diff --git a/tests/test_stall_epready.py b/tests/test_stall_epready.py index 2615d300..a864d198 100644 --- a/tests/test_stall_epready.py +++ b/tests/test_stall_epready.py @@ -3,12 +3,11 @@ # This Software is subject to the terms of the XMOS Public Licence: Version 1. # Directed test for (github) issue #58 -from usb_packet import * -import usb_packet +import pytest + +from conftest import PARAMS, test_RunUsbSession # noqa F401 from usb_session import UsbSession from usb_transaction import UsbTransaction -import pytest -from conftest import PARAMS, test_RunUsbSession @pytest.fixture diff --git a/tests/test_suspend_resume.py b/tests/test_suspend_resume.py index 68aff185..088d00be 100644 --- a/tests/test_suspend_resume.py +++ b/tests/test_suspend_resume.py @@ -1,18 +1,17 @@ # 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_packet import CreateSofToken from usb_signalling import UsbSuspend, UsbResume from usb_session import UsbSession from usb_transaction import UsbTransaction -import pytest -from conftest import PARAMS, test_RunUsbSession @pytest.fixture def test_session(ep, address, bus_speed): - start_length = 10 - end_length = 12 pktLength = 10 frameNumber = 52 # Note, for frame number 52 we expect A5 34 40 on the bus diff --git a/tests/test_suspend_resume_invalidls.py b/tests/test_suspend_resume_invalidls.py new file mode 100644 index 00000000..47535be7 --- /dev/null +++ b/tests/test_suspend_resume_invalidls.py @@ -0,0 +1,54 @@ +# 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_packet import CreateSofToken +from usb_signalling import UsbSuspend, UsbResume +from usb_session import UsbSession +from usb_transaction import UsbTransaction + + +@pytest.fixture +def test_session(ep, address, bus_speed): + + pktLength = 10 + frameNumber = 52 # Note, for frame number 52 we expect A5 34 40 on the bus + + session = UsbSession( + bus_speed=bus_speed, run_enumeration=False, device_address=address + ) + + session.add_event( + UsbTransaction( + session, + deviceAddress=address, + endpointNumber=ep, + endpointType="BULK", + direction="OUT", + dataLength=pktLength, + interEventDelay=0, + ) + ) + + session.add_event(CreateSofToken(frameNumber)) + + session.add_event(UsbSuspend(350000)) + session.add_event(UsbResume(glitches=[("SE_1", 10)])) + + 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", + dataLength=pktLength, + interEventDelay=0, + ) + ) + + return session diff --git a/tests/test_suspend_resume_invalidls/Makefile b/tests/test_suspend_resume_invalidls/Makefile new file mode 100644 index 00000000..6dd0ad9e --- /dev/null +++ b/tests/test_suspend_resume_invalidls/Makefile @@ -0,0 +1,4 @@ + +TEST_FLAGS = -DSUSPEND_TIMEOUT_us=300 -DSUSPEND_T_WTWRSTHS_us=20 -DXUD_BYPASS_RESET=1 + +include ../test_makefile.mak diff --git a/tests/test_suspend_resume_invalidls/src/main.xc b/tests/test_suspend_resume_invalidls/src/main.xc new file mode 100644 index 00000000..0d6d6e90 --- /dev/null +++ b/tests/test_suspend_resume_invalidls/src/main.xc @@ -0,0 +1,68 @@ +// Copyright 2016-2021 XMOS LIMITED. +// This Software is subject to the terms of the XMOS Public Licence: Version 1. +#include +#include +#include +#include "xud.h" +#include "platform.h" +#include "shared.h" + +#define XUD_EP_COUNT_OUT 5 +#define XUD_EP_COUNT_IN 5 + +#ifndef PKT_LENGTH_START +#define PKT_LENGTH_START 10 +#endif + +#ifndef PKT_LENGTH_END +#define PKT_LENGTH_END 11 +#endif + +#ifndef TEST_EP_NUM +#error +#endif + +/* Endpoint type tables */ +XUD_EpType epTypeTableOut[XUD_EP_COUNT_OUT] = {XUD_EPTYPE_CTL, XUD_EPTYPE_BUL, XUD_EPTYPE_BUL, XUD_EPTYPE_BUL, XUD_EPTYPE_BUL}; +XUD_EpType epTypeTableIn[XUD_EP_COUNT_IN] = {XUD_EPTYPE_CTL, XUD_EPTYPE_BUL, XUD_EPTYPE_BUL, XUD_EPTYPE_BUL, XUD_EPTYPE_BUL}; + +#ifdef XUD_SIM_RTL +int testmain() +#else +int main() +#endif +{ + chan c_ep_out[XUD_EP_COUNT_OUT], c_ep_in[XUD_EP_COUNT_IN]; + + par + { + { + #if defined(XUD_TEST_SPEED_FS) + unsigned speed = XUD_SPEED_FS; + #elif defined(XUD_TEST_SPEED_HS) + unsigned speed = XUD_SPEED_HS; + #else + #error XUD_TEST_SPEED_XX not defined + #endif + + XUD_Main(c_ep_out, XUD_EP_COUNT_OUT, c_ep_in, XUD_EP_COUNT_IN, + null, epTypeTableOut, epTypeTableIn, speed, XUD_PWR_BUS); + } + + { + unsigned fail = TestEp_Rx(c_ep_out[TEST_EP_NUM], TEST_EP_NUM, PKT_LENGTH_START, PKT_LENGTH_END); + + + XUD_ep ep0 = XUD_InitEp(c_ep_out[0]); + XUD_Kill(ep0); + + if(fail) + TerminateFail(fail); + else + TerminatePass(fail); + + } + } + + return 0; +} diff --git a/tests/usb_clock.py b/tests/usb_clock.py index a39a59f8..8ecc4e8c 100644 --- a/tests/usb_clock.py +++ b/tests/usb_clock.py @@ -1,8 +1,6 @@ # Copyright 2016-2021 XMOS LIMITED. # This Software is subject to the terms of the XMOS Public Licence: Version 1. from Pyxsim import SimThread -import sys -import zlib class Clock(SimThread): diff --git a/tests/usb_event.py b/tests/usb_event.py index f445eb91..f5e3db5f 100644 --- a/tests/usb_event.py +++ b/tests/usb_event.py @@ -1,6 +1,6 @@ # Copyright 2016-2021 XMOS LIMITED. # This Software is subject to the terms of the XMOS Public Licence: Version 1. -from abc import ABC, abstractmethod, abstractproperty +from abc import ABC, abstractmethod class UsbEvent(ABC): @@ -13,7 +13,8 @@ def __init__(self, time=0, interEventDelay=None): def time(self): return self._time - # NOTE: its not always sensible for an event to used the IED - for example an Rx Packet + # NOTE: its not always sensible for an event to used the IED - for example + # an Rx Packet @property def interEventDelay(self): return self._interEventDelay @@ -28,7 +29,8 @@ def drive(self, usb_phy, bus_speed): pass # Note, an event might contain events - @abstractproperty + @property + @abstractmethod def event_count(self): pass diff --git a/tests/usb_packet.py b/tests/usb_packet.py index 2531622b..e98c7803 100644 --- a/tests/usb_packet.py +++ b/tests/usb_packet.py @@ -65,7 +65,9 @@ USB_DATA_VALID_COUNT = {"FS": 39, "HS": 0} # In USB clocks -RXA_END_DELAY = 2 # Pad delay not currently simulated in xsim for USB or OTP, so add this delay here +# 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 # TODO shoud we have a PID class? @@ -97,27 +99,12 @@ def CreateSofToken(frameNumber, badCrc=False, interEventDelay=1000): crc5=0xFF, interEventDelay=interEventDelay, ) - else: - return TokenPacket( - pid=USB_PID["SOF"], - address=address, - endpoint=ep, - interEventDelay=interEventDelay, - ) - - -def reflect(val, numBits): - - valRef = 0 - for i in range(numBits): - valRef <<= 1 - - if val & 1: - valRef |= 1 - - val >>= 1 - - return valRef + return TokenPacket( + pid=USB_PID["SOF"], + address=address, + endpoint=ep, + interEventDelay=interEventDelay, + ) def GenCrc16(data: bytes): @@ -180,16 +167,16 @@ def create_data_expect(args): def create_data_expect_step(args): - step, num_data_bytes = args + step, _num_data_bytes = args return "Step = {0}\n".format(step) def create_data_expect_same(args): - value, num_data_bytes = args + value, _num_data_bytes = args return "Value = {0}\n".format(value) -class BusReset(object): +class BusReset: def __init__(self, **kwargs): self.duration_ms = kwargs.pop("duraton", 10) # Duration of reset self.bus_speed = kwargs.pop("bus_speed", "high") # Bus speed to reset into @@ -205,7 +192,7 @@ def __init__(self, **kwargs): self.num_data_bytes = kwargs.pop("length", 0) self.bad_crc = kwargs.pop("bad_crc", False) ied = kwargs.pop("interEventDelay", None) - super(UsbPacket, self).__init__(interEventDelay=ied) + super().__init__(interEventDelay=ied) @property def event_count(self): @@ -227,7 +214,7 @@ def __init__(self, **kwargs): self._timeout = kwargs.pop( "timeout", usb_phy.USB_PKT_TIMINGS["TX_TO_RX_PACKET_TIMEOUT"] ) - super(RxPacket, self).__init__(**kwargs) + super().__init__(**kwargs) @property def timeout(self): @@ -236,7 +223,7 @@ def timeout(self): def expected_output(self, bus_speed, offset=0): expected_output = "Packet:\tDEVICE -> HOST\n" - for (i, byte) in enumerate(self.get_bytes()): + for byte in self.get_bytes(): expected_output += "\tRX byte: {0:#x}\n".format(byte) return expected_output @@ -263,10 +250,10 @@ def drive(self, usb_phy, bus_speed): in_rx_packet = True break - if in_rx_packet == False: + if not in_rx_packet: print("ERROR: Timed out waiting for packet") else: - while in_rx_packet == True: + while in_rx_packet: # TODO txrdy pulsing xsi.drive_port_pins(usb_phy._txrdy, 1) @@ -286,10 +273,10 @@ def drive(self, usb_phy, bus_speed): xsi.drive_port_pins(usb_phy._txrdy, 0) # Check packet against expected - expected = self.get_bytes(do_tokens=False) + expected = self.get_bytes() if len(expected) != len(rx_packet): print( - "ERROR: Rx packet length bad. Expecting: {} actual: {}".format( + "ERROR: Rx packet length bad. Expecting: {} actual: {}".format( # noqa E501 len(expected), len(rx_packet) ) ) @@ -314,16 +301,17 @@ def __init__(self, **kwargs): self.rxe_assert_length = kwargs.pop("rxe_assert_length", 1) ied = kwargs.pop( - "interEventDelay", usb_phy.USB_PKT_TIMINGS["TX_TO_TX_PACKET_DELAY"] + "interEventDelay", + usb_phy.USB_PKT_TIMINGS["TX_TO_TX_PACKET_DELAY"], ) - super(TxPacket, self).__init__(**kwargs, interEventDelay=ied) + super().__init__(**kwargs, interEventDelay=ied) def expected_output(self, bus_speed, offset=0): expected_output = "Packet:\tHOST -> DEVICE\n" expected_output += "\tPID: {} ({:#x})\n".format(self.get_pid_str(), self.pid) return expected_output - def drive(self, usb_phy, bus_speed, verbose=True): + def drive(self, usb_phy, bus_speed): xsi = usb_phy.xsi wait = usb_phy.wait @@ -375,8 +363,9 @@ def drive(self, usb_phy, bus_speed, verbose=True): 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 completed + # We assume that the Phy internally blocks the TXValid signal + # to the Transmit State Machine until the Rx packet has + # completed # if xsi.sample_port_pins(usb_phy._txv) == 1: # print("ERROR: Unexpected packet from xCORE (TxPacket 2)") @@ -399,8 +388,8 @@ def drive(self, usb_phy, bus_speed, verbose=True): rxa_end_delay = rxa_end_delay - 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 completed + # We assume that the Phy internally blocks the TXValid signal to + # the Transmit State Machine # until the Rx packet has completed # if xsi.sample_port_pins(usb_phy._txv) == 1: # print("ERROR: Unexpected packet from xCORE (TxPacket 3)") @@ -409,55 +398,49 @@ def drive(self, usb_phy, bus_speed, verbose=True): # Implemented such that we can generate malformed packets def get_bytes(self, do_tokens=False): - bytes = [] + byte_list = [] if do_tokens: - bytes.append(self.pid) + byte_list.append(self.pid) else: - bytes.append(self.pid | ((~self.pid) << 4)) - for x in range(len(self.data_bytes)): - bytes.append(self.data_bytes[x]) - return bytes + byte_list.append(self.pid | ((~self.pid) << 4)) + for b in self.data_bytes: + byte_list.append(b) + return byte_list # DataPacket class, inherits from Usb Packet class DataPacket(UsbPacket): def __init__(self, dataPayload=[], **kwargs): - super(DataPacket, self).__init__(**kwargs) + super().__init__(**kwargs) self.pid = kwargs.pop("pid", 0x3) # DATA0 self.data_bytes = dataPayload def get_packet_bytes(self): - packet_bytes = [] - packet_bytes = self.data_bytes - return packet_bytes - - def get_crc(self, packet_bytes): - crc = GenCrc16(packet_bytes) - return crc + return self.data_bytes def get_bytes(self, do_tokens=False): - bytes = [] + byte_list = [] if do_tokens: - bytes.append(self.pid) + byte_list.append(self.pid) else: - bytes.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: - bytes.append(byte) + byte_list.append(byte) - if self.bad_crc == True: + if self.bad_crc: crc = 0xBEEF else: - crc = self.get_crc(packet_bytes) + crc = GenCrc16(packet_bytes) # Append the 2 bytes of CRC onto the packet for i in range(0, 2): - bytes.append((crc >> (8 * i)) & 0xFF) + byte_list.append((crc >> (8 * i)) & 0xFF) - return bytes + return byte_list class RxDataPacket(RxPacket, DataPacket): @@ -465,15 +448,13 @@ def __init__(self, **kwargs): _pid = self.pid = kwargs.pop("pid", 0x3) # DATA0 # Re-construct full PID - xCORE sends out full PIDn | PID on Tx - super(RxDataPacket, self).__init__( - pid=(_pid & 0xF) | (((~_pid) & 0xF) << 4), **kwargs - ) + super().__init__(pid=(_pid & 0xF) | (((~_pid) & 0xF) << 4), **kwargs) def __str__(self): return ( - super(DataPacket, self).__str__() + super().__str__() + ": RX DataPacket: " - + super(DataPacket, self).get_pid_str() + + super().get_pid_str() + " " + str(self.data_bytes) ) @@ -481,13 +462,13 @@ def __str__(self): class TxDataPacket(DataPacket, TxPacket): def __init__(self, **kwargs): - super(TxDataPacket, self).__init__(**kwargs) + super().__init__(**kwargs) def __str__(self): return ( - super(DataPacket, self).__str__() + super().__str__() + ": TX DataPacket: " - + super(DataPacket, self).get_pid_str() + + super().get_pid_str() + " " + str(self.data_bytes) + " Valid CRC: " @@ -500,7 +481,7 @@ def __str__(self): # Always TX class TokenPacket(TxPacket): def __init__(self, **kwargs): - super(TokenPacket, self).__init__(**kwargs) + super().__init__(**kwargs) self.endpoint = kwargs.pop("endpoint", 0) self.valid = kwargs.pop("valid", 1) self.address = kwargs.pop("address", 0) @@ -514,28 +495,24 @@ def __init__(self, **kwargs): # TODO Always override data_valid count to match IFM for archs < XS3 def get_bytes(self, do_tokens=False): - bytes = [] + byte_list = [] if do_tokens: - bytes.append(self.pid & 0xF) - bytes.append(self.endpoint) + byte_list.append(self.pid & 0xF) + byte_list.append(self.endpoint) else: - bytes.append(self.pid) + byte_list.append(self.pid) tokenbyte0 = self.address | ((self.endpoint & 1) << 7) tokenbyte1 = (self.endpoint >> 1) | (self.crc5 << 3) - bytes.append(tokenbyte0) - bytes.append(tokenbyte1) + byte_list.append(tokenbyte0) + byte_list.append(tokenbyte1) - return bytes + return byte_list def __str__(self): - return ( - super(TokenPacket, self).__str__() - + ": TokenPacket: " - + super(TokenPacket, self).get_pid_str() - ) + return super().__str__() + ": TokenPacket: " + super().get_pid_str() # Token valid def get_token_valid(self): @@ -544,46 +521,36 @@ def get_token_valid(self): class HandshakePacket(UsbPacket): def __init__(self, **kwargs): - super(HandshakePacket, self).__init__(**kwargs) + super().__init__(**kwargs) self.pid = kwargs.pop("pid", USB_PID["ACK"]) # Default to ACK - def get_bytes(self, do_tokens=False): - bytes = [] - bytes.append(self.pid) - return bytes + def get_bytes(self): + byte_list = [] + byte_list.append(self.pid) + return byte_list class RxHandshakePacket(HandshakePacket, RxPacket): def __init__(self, **kwargs): - super(RxHandshakePacket, self).__init__(**kwargs) + super().__init__(**kwargs) self.pid = kwargs.pop( "pid", 0xD2 ) # Default to ACK (not expect inverted bits on Rx) - # self._timeout = kwargs.pop("timeout", RX_TX_DELAY) # TODO handled by Super() + # self._timeout = kwargs.pop("timeout", RX_TX_DELAY) + # TODO handled by Super() def __str__(self): - return ( - super(RxHandshakePacket, self).__str__() - + ": RX HandshakePacket: " - + super(RxHandshakePacket, self).get_pid_str() - ) + return super().__str__() + ": RX HandshakePacket: " + super().get_pid_str() class TxHandshakePacket(HandshakePacket, TxPacket): - def __init__(self, **kwargs): - super(TxHandshakePacket, self).__init__(**kwargs) - def get_bytes(self, do_tokens=False): - bytes = [] + byte_list = [] if do_tokens: - bytes.append(self.pid) + byte_list.append(self.pid) else: - bytes.append(self.pid | ((~self.pid) << 4)) - return bytes + byte_list.append(self.pid | ((~self.pid) << 4)) + return byte_list def __str__(self): - return ( - super(TxHandshakePacket, self).__str__() - + ": TX HandshakePacket: " - + super(TxHandshakePacket, self).get_pid_str() - ) + return super().__str__() + ": TX HandshakePacket: " + super().get_pid_str() diff --git a/tests/usb_phy.py b/tests/usb_phy.py index ac21367a..faf21f29 100644 --- a/tests/usb_phy.py +++ b/tests/usb_phy.py @@ -1,10 +1,6 @@ # Copyright 2016-2021 XMOS LIMITED. # This Software is subject to the terms of the XMOS Public Licence: Version 1. -import random import Pyxsim -import sys -import zlib -import usb_packet USB_MAX_EP_ADDRESS = 15 @@ -14,6 +10,7 @@ "FS_K": 1, "HS_J": 1, "HS_K": 2, + "SE_1": 3, } # TODO want two sets of these, one "spec" and one "fast" for testing @@ -25,12 +22,16 @@ "T_UCHEND": 7000, # Upstream Chirp end time "T_UCH_US": 1000, # Upstream Chirp length "T_WTDCH_US": 100, - "T_SIGATT_US": 100000, # Maximum time from Vbus valid to when the device must signal attach - "T_ATTDB_US": 10, # 100000 Debouce interval. The device now enters the HS Detection Handshake protocol + "T_SIGATT_US": 100000, # Maximum time from Vbus valid to when the device + # must signal attach + "T_ATTDB_US": 10, # 100000 Debouce interval. The device now enters the HS + # Detection Handshake protocol "T_DCHBIT_MIN_US": 40, "T_DCHBIT_MAX_US": 60, - "CHIRP_COUNT_MIN": 3, # Minimum chirp pairs DUT must detect before moving into HS mode - "CHIRP_COUNT_MAX": 10, # TODO should these chirp defines be removed and use timing? + "CHIRP_COUNT_MIN": 3, # Minimum chirp pairs DUT must detect before moving + # into HS mode + "CHIRP_COUNT_MAX": 10, # TODO should these chirp defines be removed and + # use timing? } USB_TIMINGS_SHORT = { @@ -41,17 +42,24 @@ "T_UCHEND": 7000, # Upstream Chirp end time "T_UCH_US": 10, # Upstream Chirp length "T_WTDCH_US": 50, - "T_SIGATT_US": 100000, # Maximum time from Vbus valid to when the device must signal attach - "T_ATTDB_US": 10, # 100000 Debouce interval. The device now enters the HS Detection Handshake protocol + "T_SIGATT_US": 100000, # Maximum time from Vbus valid to when the device + # must signal attach + "T_ATTDB_US": 10, # 100000 Debouce interval. The device now enters the HS + # Detection Handshake protocol "T_DCHBIT_MIN_US": 4, # Spec: 40us "T_DCHBIT_MAX_US": 6, # Spec: 60us - "CHIRP_COUNT_MIN": 3, # Minimum chirp pairs DUT must detect before moving into HS mode - "CHIRP_COUNT_MAX": 10, # TODO should these chirp defines be removed and use timing? + "CHIRP_COUNT_MIN": 3, # Minimum chirp pairs DUT must detect before moving + # into HS mode + "CHIRP_COUNT_MAX": 10, # TODO should these chirp defines be removed and + # use timing? } USB_PKT_TIMINGS_TIGHT = { - "TX_TO_RX_PACKET_TIMEOUT": 14, # Timeout between sending DUT a packet and the expected response (in USB clocks). This is SIE decision time in UTMI spec + "TX_TO_RX_PACKET_TIMEOUT": 14, # 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 } @@ -171,10 +179,8 @@ def wait_for_clocks(self, clockCount): def run(self): - xsi = self.xsi - - # TODO ideally each session could have it's own start up delay rather than modifying the - # phy start up delay + # TODO ideally each session could have it's own start up delay rather + # than modifying the phy start up delay if self._session.initial_delay is not None: self._initial_delay = self._session.initial_delay diff --git a/tests/usb_phy_shim.py b/tests/usb_phy_shim.py index 1dfc71e7..18647cc0 100644 --- a/tests/usb_phy_shim.py +++ b/tests/usb_phy_shim.py @@ -1,8 +1,7 @@ # Copyright 2016-2021 XMOS LIMITED. # This Software is subject to the terms of the XMOS Public Licence: Version 1. -import random import sys -import zlib + from usb_packet import RxPacket, TokenPacket from usb_phy import UsbPhy @@ -31,7 +30,7 @@ def __init__( # Shim adds a valid token line self._vld = vld - super(UsbPhyShim, self).__init__( + super().__init__( "mii", rxd, rxa, @@ -77,11 +76,11 @@ def run(self): in_rx_packet = True break - if in_rx_packet == False: + if not in_rx_packet: print("ERROR: Timed out waiting for packet") else: - while in_rx_packet == True: + while in_rx_packet: # TODO txrdy pulsing xsi.drive_port_pins(self._txrdy, 1) @@ -104,7 +103,7 @@ def run(self): expected = packet.get_bytes(do_tokens=True) if len(expected) != len(rx_packet): print( - "ERROR: Rx packet length bad. Expecting: {} actual: {}".format( + "ERROR: Rx packet length bad. Expecting: {} actual: {}".format( # noqa E501 len(expected), len(rx_packet) ) ) @@ -147,7 +146,8 @@ def run(self): for (i, byte) in enumerate(packet.get_bytes(do_tokens=True)): - # xCore should not be trying to send if we are trying to send.. + # xCore should not be trying to send if we are trying to + # send.. if xsi.sample_port_pins(self._txv) == 1: print("ERROR: Unexpected packet from xCORE") @@ -167,7 +167,8 @@ def run(self): xsi.drive_port_pins(self._rxdv, 0) rxv_count = rxv_count - 1 - # xCore should not be trying to send if we are trying to send.. + # xCore should not be trying to send if we are trying + # to send.. if xsi.sample_port_pins(self._txv) == 1: print("ERROR: Unexpected packet from xCORE") @@ -194,7 +195,8 @@ def run(self): self.wait(lambda x: self._clock.is_low()) rxa_end_delay = rxa_end_delay - 1 - # xCore should not be trying to send if we are trying to send.. + # xCore should not be trying to send if we are trying to + # send.. if xsi.sample_port_pins(self._txv) == 1: print("ERROR: Unexpected packet from xCORE") diff --git a/tests/usb_phy_utmi.py b/tests/usb_phy_utmi.py index 0437e134..1644b5b2 100644 --- a/tests/usb_phy_utmi.py +++ b/tests/usb_phy_utmi.py @@ -1,7 +1,5 @@ # Copyright 2016-2021 XMOS LIMITED. # This Software is subject to the terms of the XMOS Public Licence: Version 1. -from usb_packet import RxPacket, TokenPacket -import usb_packet from usb_phy import UsbPhy @@ -19,7 +17,7 @@ def __init__( xcvrsel, termsel, clock, - initial_delay=60000, + initial_delay=64000, verbose=False, do_timeout=True, complete_fn=None, @@ -28,7 +26,7 @@ def __init__( self._do_tokens = False - super(UsbPhyUtmi, self).__init__( + super().__init__( "UsbPhyUtmi", rxd, rxa, diff --git a/tests/usb_session.py b/tests/usb_session.py index dcc789dd..2e8cf1fa 100644 --- a/tests/usb_session.py +++ b/tests/usb_session.py @@ -2,27 +2,25 @@ # This Software is subject to the terms of the XMOS Public Licence: Version 1. from usb_packet import USB_DATA_VALID_COUNT -import usb_transaction import usb_packet # TODO should EP numbers include the IN bit? def CounterByte(startVal=0, length=0): - l = startVal - while l < length: - yield l % 256 - l += 1 + i = startVal + while i < length: + yield i % 256 + i += 1 -class UsbSession(object): +class UsbSession: def __init__( self, bus_speed="HS", run_enumeration=False, device_address=0, initial_delay=None, - **kwargs ): self._initial_delay = initial_delay self._bus_speed = bus_speed @@ -35,7 +33,7 @@ def __init__( self._dataGen_in = [0] * 16 self._dataGen_out = [0] * 16 - assert run_enumeration == False, "Not yet supported" + assert run_enumeration is False, "Not yet supported" @property def initial_delay(self): @@ -78,7 +76,8 @@ def getPayload_in(self, n, length, resend=False): self._dataGen_in[n] += length return payload - def _pid_toggle(self, pid_table, n): + @staticmethod + def _pid_toggle(pid_table, n): if pid_table[n] == usb_packet.USB_PID["DATA0"]: pid_table[n] = usb_packet.USB_PID["DATA1"] @@ -123,8 +122,9 @@ def add_event(self, e): self._events.append(e) - def pop_event(self, e): + def pop_event(self): self.events.pop(0) - def _sort_events_by_time(self, events): + @staticmethod + def _sort_events_by_time(events): return sorted(events, key=lambda x: x.time, reverse=True) diff --git a/tests/usb_signalling.py b/tests/usb_signalling.py index 699bcfdf..afb671a1 100644 --- a/tests/usb_signalling.py +++ b/tests/usb_signalling.py @@ -49,7 +49,9 @@ def drive(self, usb_phy, bus_speed): while True: if (time() - tConnect_ns) > USB_TIMINGS["T_SIGATT_US"]: - print("ERROR: DUT didnt not assert XcvrSel & TermSel quickly enough") + print( + "ERROR: DUT didnt not assert XcvrSel & TermSel quickly enough" # noqa E501 + ) # Check device asserts XcvrSel and TermSel before T_SIGATT xcvrsel = xsi.sample_periph_pin(usb_phy._xcvrsel) @@ -70,7 +72,8 @@ def drive(self, usb_phy, bus_speed): xsi.drive_periph_pin(usb_phy._ls, USB_LINESTATE["IDLE"]) - # Check DUT enables HS Transceiver and asserts Chirp K on the bus (XcvrSel low, TxValid high) + # Check DUT enables HS Transceiver and asserts Chirp K on the bus + # (XcvrSel low, TxValid high) # (This needs to be done before T_UCHEND - T_UCH) while True: xcvrsel = xsi.sample_periph_pin(usb_phy._xcvrsel) @@ -123,13 +126,16 @@ def drive(self, usb_phy, bus_speed): xsi.drive_periph_pin(usb_phy._ls, USB_LINESTATE["FS_K"]) wait_until_ns(time() + USB_TIMINGS["T_DCHBIT_MIN_US"] * 1000) - # After between T_DCHBIT_MIN and T_DCHBIT_MAX toogle chirp K to chirp J + # After between T_DCHBIT_MIN and T_DCHBIT_MAX toogle chirp K to + # chirp J xsi.drive_periph_pin(usb_phy._ls, USB_LINESTATE["FS_J"]) wait_until_ns(time() + USB_TIMINGS["T_DCHBIT_MIN_US"] * 1000) - # After between T_DCHBIT_MIN and T_DCHBIT_MAX toogle chirp J to chirp K + # After between T_DCHBIT_MIN and T_DCHBIT_MAX toogle chirp J to + # chirp K - # After atleast 3 chirp pairs ensure DUT de-asserts TermSel to enter HS mode + # After atleast 3 chirp pairs ensure DUT de-asserts TermSel to + # enter HS mode if xsi.sample_periph_pin(usb_phy._termsel) != 0: print("ERROR: DUT didnt enter HS as expected") else: @@ -143,11 +149,13 @@ def drive(self, usb_phy, bus_speed): xsi.drive_periph_pin(usb_phy._ls, USB_LINESTATE["FS_K"]) wait_until_ns(time() + USB_TIMINGS["T_DCHBIT_MIN_US"] * 1000) - # After between T_DCHBIT_MIN and T_DCHBIT_MAX toogle chirp K to chirp J + # After between T_DCHBIT_MIN and T_DCHBIT_MAX toogle chirp K + # to chirp J xsi.drive_periph_pin(usb_phy._ls, USB_LINESTATE["FS_J"]) wait_until_ns(time() + USB_TIMINGS["T_DCHBIT_MIN_US"] * 1000) - # Terminate downstream chirp K-J Sequence (between T_DCHSE0_MAX and T_DCHSE0_MIN + # Terminate downstream chirp K-J Sequence (between T_DCHSE0_MAX and + # T_DCHSE0_MIN # Ensure DUT enters HS before T0 + T_DRST @@ -174,8 +182,14 @@ def drive(self, usb_phy, bus_speed): class UsbResume(UsbEvent): - def __init__(self, duration=USB_TIMINGS["RESUME_FSK_MIN_US"], interEventDelay=0): + def __init__( + self, + duration=USB_TIMINGS["RESUME_FSK_MIN_US"], + interEventDelay=0, + glitches=[], + ): self._duration = duration + self._glitches = glitches super().__init__(interEventDelay=interEventDelay) def expected_output(self, bus_speed, offset=0): @@ -199,6 +213,7 @@ def event_count(self): def drive(self, usb_phy, bus_speed): xsi = usb_phy.xsi wait = usb_phy.wait + wait_for_clocks = usb_phy.wait_for_clocks # xCore should not be trying to send if we are trying to send.. if xsi.sample_port_pins(usb_phy._txv) == 1: @@ -206,24 +221,56 @@ def drive(self, usb_phy, bus_speed): resumeStartTime_ns = xsi.get_time() - # print("RESUME: " + str(resumeStartTime_ns)) print("RESUME") + # Drive out any glitches mid resume signalling + # TODO we could make the drive time a param + glitchTime = (USB_TIMINGS["RESUME_FSK_MIN_US"] * 1000) / 2 + # Drive resume signalling xsi.drive_periph_pin(usb_phy._ls, USB_LINESTATE["FS_K"]) + glitchTimeMet = False + while True: - wait(lambda x: usb_phy._clock.is_high()) - wait(lambda x: usb_phy._clock.is_low()) + + wait_for_clocks(1) currentTime_ns = xsi.get_time() + + if ( + currentTime_ns >= (resumeStartTime_ns + glitchTime) + and not glitchTimeMet + ): + + glitchTimeMet = True + + if self._glitches: + + for ls, duration in self._glitches: + + # Drive the glitch + xsi.drive_periph_pin(usb_phy._ls, USB_LINESTATE[ls]) + + while True: + wait_for_clocks(1) + + currentTime_ns = xsi.get_time() + + if currentTime_ns >= glitchTime + duration: + break + + # Back to driving resume signalling + xsi.drive_periph_pin(usb_phy._ls, USB_LINESTATE["FS_K"]) + if currentTime_ns >= resumeStartTime_ns + ( USB_TIMINGS["RESUME_FSK_MIN_US"] * 1000 ): break endResumeStartTime_ns = xsi.get_time() - # print("TB SE0: " + str(endResumeStartTime_ns)) + + # Drive end of resume signalling xsi.drive_periph_pin(usb_phy._ls, USB_LINESTATE["IDLE"]) while True: @@ -237,7 +284,6 @@ def drive(self, usb_phy, bus_speed): break print("RESUME END") - # print("RESUME END: " + str(currentTime_ns)) if bus_speed == "HS": # Check that the DUT has re-entered HS @@ -255,7 +301,8 @@ def drive(self, usb_phy, bus_speed): class UsbSuspend(UsbEvent): - # TODO create instance of Suspend with duracton in seconds and convert to clks? + # TODO create instance of Suspend with duracton in seconds and convert to + # clks? def __init__(self, duration_ns, interEventDelay=0): self._duration_ns = duration_ns super().__init__(interEventDelay=interEventDelay) @@ -310,7 +357,7 @@ def drive(self, usb_phy, bus_speed): fsTime_ns = xsi.get_time() timeToFs_ns = fsTime_ns - suspendStartTime_ns - # print("DEVICE ENTERED FS AT TIME " + str(fsTime_ns/1000) + "(after " + str(timeToFs_ns/1000) +" uS)") + # print("DEVICE ENTERED FS AT TIME " + str(fsTime_ns/1000) + "(after " + str(timeToFs_ns/1000) +" uS)") # noqa F401 print("DEVICE ENTERED FS MODE") if bus_speed == "HS": diff --git a/tests/usb_transaction.py b/tests/usb_transaction.py index 7bfdbd5d..003b3dec 100644 --- a/tests/usb_transaction.py +++ b/tests/usb_transaction.py @@ -17,6 +17,7 @@ USB_DIRECTIONS = ["OUT", "IN"] USB_EP_TYPES = ["CONTROL", "BULK", "ISO", "INTERRUPT"] + # TODO UsbTransaction_IN and UsbTransaction_OUT class UsbTransaction(UsbEvent): def __init__( @@ -53,7 +54,8 @@ def __init__( # 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? + # TODO would it be better to generate packets on the fly in drive() + # rather than create a packet list? if direction == "OUT": packets = [] @@ -78,15 +80,12 @@ def __init__( else: togglePid = True - if ( + expectHandshake = ( (not self._badDataCrc) and (not self._rxeAssertDelay_data) and (deviceAddress == session.deviceAddress) and (self._endpointType != "ISO") - ): - expectHandshake = True - else: - expectHandshake = False + ) if expectHandshake or self._endpointType == "ISO": resend = False @@ -155,19 +154,13 @@ def __init__( if halted: self._packets.append(RxHandshakePacket(pid=USB_PID["STALL"])) - super(UsbTransaction, self).__init__( - time=eventTime, interEventDelay=interEventDelay - ) + super().__init__(time=eventTime, interEventDelay=interEventDelay) # TODO ideally USBTransaction doesnt know about data_valid_count @property def data_valid_count(self): return USB_DATA_VALID_COUNT[self.bus_speed] - @property - def endpointAddress(self): - return self._endpointAddress - @property def endpointType(self): return self._endpointType @@ -200,7 +193,7 @@ def event_count(self): def expected_output(self, bus_speed, offset=0): expected_output = "" - for i, p in enumerate(self.packets): + for p in self.packets: expected_output += p.expected_output(bus_speed) return expected_output @@ -212,5 +205,5 @@ def __str__(self): return s def drive(self, usb_phy, bus_speed): - for i, p in enumerate(self.packets): + for p in self.packets: p.drive(usb_phy, bus_speed)