From 2025e8be90d6e72227067118862e962f162d6501 Mon Sep 17 00:00:00 2001 From: Ed Date: Fri, 8 Dec 2023 16:38:04 +0000 Subject: [PATCH 1/6] Working extern XUD_EXTERNAL_RESOURCES solution --- .../XCORE-AI-EXPLORER-2V0-JG-800-4TILE.xn | 87 ++++ .../src/config.xscope | 3 + examples/dual_AN00127_video_class/src/main.xc | 121 ++++++ .../dual_AN00127_video_class/src/usb_video.h | 19 + .../dual_AN00127_video_class/src/usb_video.xc | 379 ++++++++++++++++++ .../dual_AN00127_video_class/src/uvc_defs.h | 78 ++++ .../dual_AN00127_video_class/src/uvc_req.c | 113 ++++++ .../dual_AN00127_video_class/src/uvc_req.h | 44 ++ .../src/xud_wrapper.c | 35 ++ .../src/xud_wrapper.h | 16 + lib_xud/api/xud.h | 16 + lib_xud/src/core/XUD_DeviceAttach.xc | 27 +- lib_xud/src/core/XUD_HAL.xc | 93 +++-- lib_xud/src/core/XUD_Main.xc | 143 +++++-- lib_xud/src/core/XUD_TestMode.xc | 16 +- lib_xud/src/core/XUD_resources.c | 11 + 16 files changed, 1108 insertions(+), 93 deletions(-) create mode 100644 examples/dual_AN00127_video_class/XCORE-AI-EXPLORER-2V0-JG-800-4TILE.xn create mode 100644 examples/dual_AN00127_video_class/src/config.xscope create mode 100644 examples/dual_AN00127_video_class/src/main.xc create mode 100644 examples/dual_AN00127_video_class/src/usb_video.h create mode 100644 examples/dual_AN00127_video_class/src/usb_video.xc create mode 100644 examples/dual_AN00127_video_class/src/uvc_defs.h create mode 100644 examples/dual_AN00127_video_class/src/uvc_req.c create mode 100644 examples/dual_AN00127_video_class/src/uvc_req.h create mode 100644 examples/dual_AN00127_video_class/src/xud_wrapper.c create mode 100644 examples/dual_AN00127_video_class/src/xud_wrapper.h create mode 100644 lib_xud/src/core/XUD_resources.c diff --git a/examples/dual_AN00127_video_class/XCORE-AI-EXPLORER-2V0-JG-800-4TILE.xn b/examples/dual_AN00127_video_class/XCORE-AI-EXPLORER-2V0-JG-800-4TILE.xn new file mode 100644 index 00000000..8f031f29 --- /dev/null +++ b/examples/dual_AN00127_video_class/XCORE-AI-EXPLORER-2V0-JG-800-4TILE.xn @@ -0,0 +1,87 @@ + + + Board + xcore.ai Explorer Kit x2 Wired as 4 tile system + + + tileref tile[4] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/dual_AN00127_video_class/src/config.xscope b/examples/dual_AN00127_video_class/src/config.xscope new file mode 100644 index 00000000..4b96626a --- /dev/null +++ b/examples/dual_AN00127_video_class/src/config.xscope @@ -0,0 +1,3 @@ + + + diff --git a/examples/dual_AN00127_video_class/src/main.xc b/examples/dual_AN00127_video_class/src/main.xc new file mode 100644 index 00000000..a894e409 --- /dev/null +++ b/examples/dual_AN00127_video_class/src/main.xc @@ -0,0 +1,121 @@ +// Copyright 2015-2022 XMOS LIMITED. +// This Software is subject to the terms of the XMOS Public Licence: Version 1. + +/* Includes */ +#include +#include +#include +#include +#include + +#include "usb_video.h" +#include "xud.h" +extern "C"{ + #include "xud_wrapper.h" +} + +/* xSCOPE Setup Function */ +#if (USE_XSCOPE == 1) +void xscope_user_init(void) { + xscope_register(0, 0, "", 0, ""); + xscope_config_io(XSCOPE_IO_BASIC); /* Enable fast printing over XTAG */ +} +#endif + +/* USB Endpoint Defines */ +#define EP_COUNT_OUT 1 // 1 OUT EP0 +#define EP_COUNT_IN 3 // (1 IN EP0 + 1 INTERRUPT IN EP + 1 ISO IN EP) + +/* Endpoint type tables - informs XUD what the transfer types for each Endpoint in use and also + * if the endpoint wishes to be informed of USB bus resets + */ +XUD_EpType epTypeTableOut[EP_COUNT_OUT] = {XUD_EPTYPE_CTL | XUD_STATUS_ENABLE}; +XUD_EpType epTypeTableIn[EP_COUNT_IN] = {XUD_EPTYPE_CTL | XUD_STATUS_ENABLE, XUD_EPTYPE_INT, XUD_EPTYPE_ISO}; + +XUD_EpType epTypeTableOut2[EP_COUNT_OUT] = {XUD_EPTYPE_CTL | XUD_STATUS_ENABLE}; +XUD_EpType epTypeTableIn2[EP_COUNT_IN] = {XUD_EPTYPE_CTL | XUD_STATUS_ENABLE, XUD_EPTYPE_INT, XUD_EPTYPE_ISO}; + + +/* + #define PORT_USB_CLK on USB_TILE: XS1_PORT_1J + #define PORT_USB_TXD on USB_TILE: XS1_PORT_8A + #define PORT_USB_RXD on USB_TILE: XS1_PORT_8B + #define PORT_USB_TX_READYOUT on USB_TILE: XS1_PORT_1K + #define PORT_USB_TX_READYIN on USB_TILE: XS1_PORT_1H + #define PORT_USB_RX_READY on USB_TILE: XS1_PORT_1I + #define PORT_USB_FLAG0 on USB_TILE: XS1_PORT_1E + #define PORT_USB_FLAG1 on USB_TILE: XS1_PORT_1F +*/ + +XUD_resources_t resources = +{ + on tile[0]: XS1_PORT_1E, // flag0_port + on tile[0]: XS1_PORT_1F, // flag1_port + null, // flag2_port + on tile[0]: XS1_PORT_1J, // p_usb_clk + on tile[0]: XS1_PORT_8A, // p_usb_txd + on tile[0]: XS1_PORT_8B, // p_usb_rxd + on tile[0]: XS1_PORT_1K, // tx_readyout + on tile[0]: XS1_PORT_1H, // tx_readyin + on tile[0]: XS1_PORT_1I, // rx_rdy + on tile[0]: XS1_CLKBLK_4, // tx_usb_clk + on tile[0]: XS1_CLKBLK_5, // rx_usb_clk +}; + +XUD_resources_t resources2 = +{ + on tile[2]: XS1_PORT_1E, + on tile[2]: XS1_PORT_1F, + null, + on tile[2]: XS1_PORT_1J, + on tile[2]: XS1_PORT_8A, + on tile[2]: XS1_PORT_8B, + on tile[2]: XS1_PORT_1K, + on tile[2]: XS1_PORT_1H, + on tile[2]: XS1_PORT_1I, + on tile[2]: XS1_CLKBLK_4, + on tile[2]: XS1_CLKBLK_5, +}; + +int main() { + + chan c_ep_out[EP_COUNT_OUT], c_ep_in[EP_COUNT_IN]; + chan c_ep_out2[EP_COUNT_OUT], c_ep_in2[EP_COUNT_IN]; + + + /* 'Par' statement to run the following tasks in parallel */ + par + { + on USB_TILE: + { + init_xud_resources(&resources); + printstr("XUD\n"); + XUD_Main(c_ep_out, EP_COUNT_OUT, c_ep_in, EP_COUNT_IN, + null, epTypeTableOut, epTypeTableIn, + XUD_SPEED_HS, XUD_PWR_BUS); + } + + on USB_TILE: Endpoint0(c_ep_out[0], c_ep_in[0], PRODUCT_ID); + + on USB_TILE: VideoEndpointsHandler(c_ep_in[1], c_ep_in[2], 0); + +#undef USB_TILE +#define USB_TILE tile[2] + + on USB_TILE: + { + init_xud_resources(&resources2); + printstr("XUD\n"); + XUD_Main_wrapper(c_ep_out2, EP_COUNT_OUT, c_ep_in2, EP_COUNT_IN, + null, epTypeTableOut2, epTypeTableIn2, + XUD_SPEED_HS, XUD_PWR_BUS); + } + + on USB_TILE: Endpoint0_wrapper(c_ep_out2[0], c_ep_in2[0], PRODUCT_ID + 1); + + on USB_TILE: VideoEndpointsHandler_wrapper(c_ep_in2[1], c_ep_in2[2], 1); + + + } + return 0; +} diff --git a/examples/dual_AN00127_video_class/src/usb_video.h b/examples/dual_AN00127_video_class/src/usb_video.h new file mode 100644 index 00000000..b4fff83d --- /dev/null +++ b/examples/dual_AN00127_video_class/src/usb_video.h @@ -0,0 +1,19 @@ +// Copyright 2015-2021 XMOS LIMITED. +// This Software is subject to the terms of the XMOS Public Licence: Version 1. + +#ifndef USB_VIDEO_H_ +#define USB_VIDEO_H_ + +#include "xud_device.h" +#include "uvc_req.h" +#include "uvc_defs.h" + +#define DEBUG 0 + +/* Function to handle all endpoints of the Video class excluding control endpoint0 */ +void VideoEndpointsHandler(chanend c_epint_in, chanend c_episo_in, unsigned instance); + +/* Endpoint 0 handles both std USB requests and Video class-specific requests */ +void Endpoint0(chanend chan_ep0_out, chanend chan_ep0_in, unsigned short PID); + +#endif /* USB_VIDEO_H_ */ diff --git a/examples/dual_AN00127_video_class/src/usb_video.xc b/examples/dual_AN00127_video_class/src/usb_video.xc new file mode 100644 index 00000000..04210907 --- /dev/null +++ b/examples/dual_AN00127_video_class/src/usb_video.xc @@ -0,0 +1,379 @@ +// Copyright 2015-2021 XMOS LIMITED. +// This Software is subject to the terms of the XMOS Public Licence: Version 1. + +#include "string.h" +#include "usb_video.h" + +/* Definition of Descriptors */ +/* USB Device Descriptor */ +static unsigned char devDesc[] = +{ + 0x12, /* 0 bLength */ + USB_DESCTYPE_DEVICE, /* 1 bdescriptorType - Device*/ + 0x00, /* 2 bcdUSB version */ + 0x02, /* 3 bcdUSB version */ + 0xEF, /* 4 bDeviceClass - USB Miscellaneous Class */ + 0x02, /* 5 bDeviceSubClass - Common Class */ + 0x01, /* 6 bDeviceProtocol - Interface Association Descriptor */ + 0x40, /* 7 bMaxPacketSize for EP0 - max = 64*/ + (VENDOR_ID & 0xFF), /* 8 idVendor */ + (VENDOR_ID >> 8), /* 9 idVendor */ + (PRODUCT_ID & 0xFF), /* 10 idProduct */ + (PRODUCT_ID >> 8), /* 11 idProduct */ + (BCD_DEVICE & 0xFF), /* 12 bcdDevice */ + (BCD_DEVICE >> 8), /* 13 bcdDevice */ + 0x01, /* 14 iManufacturer - index of string*/ + 0x02, /* 15 iProduct - index of string*/ + 0x00, /* 16 iSerialNumber - index of string*/ + 0x01 /* 17 bNumConfigurations */ +}; + +/* USB Configuration Descriptor */ +static unsigned char cfgDesc[] = { + + 0x09, /* 0 bLength */ + USB_DESCTYPE_CONFIGURATION, /* 1 bDescriptorType - Configuration*/ + 0xAE,00, /* 2 wTotalLength */ + 0x02, /* 4 bNumInterfaces */ + 0x01, /* 5 bConfigurationValue */ + 0x03, /* 6 iConfiguration - index of string */ + 0x80, /* 7 bmAttributes - Bus powered */ + 0xFA, /* 8 bMaxPower (in 2mA units) - 500mA */ + + /* Interface Association Descriptor */ + 0x08, /* 0 bLength */ + USB_DESCTYPE_INTERFACE_ASSOCIATION, /* 1 bDescriptorType - Interface Association */ + 0x00, /* 2 bFirstInterface - VideoControl i/f */ + 0x02, /* 3 bInterfaceCount - 2 Interfaces */ + USB_CLASS_VIDEO, /* 4 bFunctionClass - Video Class */ + USB_VIDEO_INTERFACE_COLLECTION, /* 5 bFunctionSubClass - Video Interface Collection */ + 0x00, /* 6 bFunctionProtocol - No protocol */ + 0x02, /* 7 iFunction - index of string */ + + /* Video Control (VC) Interface Descriptor */ + 0x09, /* 0 bLength */ + USB_DESCTYPE_INTERFACE, /* 1 bDescriptorType - Interface */ + 0x00, /* 2 bInterfaceNumber - Interface 0 */ + 0x00, /* 3 bAlternateSetting */ + 0x01, /* 4 bNumEndpoints */ + USB_CLASS_VIDEO, /* 5 bInterfaceClass - Video Class */ + USB_VIDEO_CONTROL, /* 6 bInterfaceSubClass - VideoControl Interface */ + 0x00, /* 7 bInterfaceProtocol - No protocol */ + 0x02, /* 8 iInterface - Index of string (same as iFunction of IAD) */ + + /* Class-specific VC Interface Header Descriptor */ + 0x0D, /* 0 bLength */ + USB_DESCTYPE_CS_INTERFACE, /* 1 bDescriptorType - Class-specific Interface */ + USB_VC_HEADER, /* 2 bDescriptorSubType - HEADER */ + 0x10, 0x01, /* 3 bcdUVC - Video class revision 1.1 */ + 0x28, 0x00, /* 5 wTotalLength - till output terminal */ + WORD_CHARS(100000000), /* 7 dwClockFrequency - 100MHz (Deprecated) */ + 0x01, /* 11 bInCollection - One Streaming Interface */ + 0x01, /* 12 baInterfaceNr - Number of the Streaming interface */ + + /* Input Terminal (Camera) Descriptor - Represents the CCD sensor (Simulated here in this demo) */ + 0x12, /* 0 bLength */ + USB_DESCTYPE_CS_INTERFACE, /* 1 bDescriptorType - Class-specific Interface */ + USB_VC_INPUT_TERMINAL, /* 2 bDescriptorSubType - INPUT TERMINAL */ + 0x01, /* 3 bTerminalID */ + 0x01, 0x02, /* 4 wTerminalType - ITT_CAMERA type (CCD Sensor) */ + 0x00, /* 6 bAssocTerminal - No association */ + 0x00, /* 7 iTerminal - Unused */ + 0x00, 0x00, /* 8 wObjectiveFocalLengthMin - No optical zoom supported */ + 0x00, 0x00, /* 10 wObjectiveFocalLengthMax - No optical zoom supported*/ + 0x00, 0x00, /* 12 wOcularFocalLength - No optical zoom supported */ + 0x03, /* 14 bControlSize - 3 bytes */ + 0x00, 0x00, 0x00, /* 15 bmControls - No controls are supported */ + + /* Output Terminal Descriptor */ + 0x09, /* 0 bLength */ + USB_DESCTYPE_CS_INTERFACE, /* 1 bDescriptorType - Class-specific Interface */ + USB_VC_OUPUT_TERMINAL, /* 2 bDescriptorSubType - OUTPUT TERMINAL */ + 0x02, /* 3 bTerminalID */ + 0x01, 0x01, /* 4 wTerminalType - TT_STREAMING type */ + 0x00, /* 6 bAssocTerminal - No association */ + 0x01, /* 7 bSourceID - Source is Input terminal 1 */ + 0x00, /* 8 iTerminal - Unused */ + + /* Standard Interrupt Endpoint Descriptor */ + 0x07, /* 0 bLength */ + USB_DESCTYPE_ENDPOINT, /* 1 bDescriptorType */ + (VIDEO_STATUS_EP_NUM | 0x80), /* 2 bEndpointAddress - IN endpoint*/ + 0x03, /* 3 bmAttributes - Interrupt transfer */ + 0x40, 0x00, /* 4 wMaxPacketSize - 64 bytes */ + 0x09, /* 6 bInterval - 2^(9-1) microframes = 32ms */ + + /* Class-specific Interrupt Endpoint Descriptor */ + 0x05, /* 0 bLength */ + USB_DESCTYPE_CS_ENDPOINT, /* 1 bDescriptorType - Class-specific Endpoint */ + 0x03, /* 2 bDescriptorSubType - Interrupt Endpoint */ + 0x40, 0x00, /* 3 wMaxTransferSize - 64 bytes */ + + /* Video Streaming Interface Descriptor */ + /* Zero-bandwidth Alternate Setting 0 */ + 0x09, /* 0 bLength */ + USB_DESCTYPE_INTERFACE, /* 1 bDescriptorType - Interface */ + 0x01, /* 2 bInterfaceNumber - Interface 1 */ + 0x00, /* 3 bAlternateSetting - 0 */ + 0x00, /* 4 bNumEndpoints - No bandwidth used */ + USB_CLASS_VIDEO, /* 5 bInterfaceClass - Video Class */ + USB_VIDEO_STREAMING, /* 6 bInterfaceSubClass - VideoStreaming Interface */ + 0x00, /* 7 bInterfaceProtocol - No protocol */ + 0x00, /* 8 iInterface - Unused */ + + /* Class-specific VS Interface Input Header Descriptor */ + 0x0E, /* 0 bLength */ + USB_DESCTYPE_CS_INTERFACE, /* 1 bDescriptorType - Class-specific Interface */ + USB_VS_INPUT_HEADER, /* 2 bDescriptorSubType - INPUT HEADER */ + 0x01, /* 3 bNumFormats - One format supported */ + 0x47, 0x00, /* 4 wTotalLength - Size of class-specific VS descriptors */ + (VIDEO_DATA_EP_NUM | 0x80), /* 6 bEndpointAddress - Iso EP for video streaming */ + 0x00, /* 7 bmInfo - No dynamic format change */ + 0x02, /* 8 bTerminalLink - Denotes the Output Terminal */ + 0x01, /* 9 bStillCaptureMethod - Method 1 supported */ + 0x00, /* 10 bTriggerSupport - No Hardware Trigger */ + 0x00, /* 11 bTriggerUsage */ + 0x01, /* 12 bControlSize - 1 byte */ + 0x00, /* 13 bmaControls - No Controls supported */ + + /* Class-specific VS Format Descriptor */ + 0x1B, /* 0 bLength */ + USB_DESCTYPE_CS_INTERFACE, /* 1 bDescriptorType - Class-specific Interface */ + USB_VS_FORMAT_UNCOMPRESSED, /* 2 bDescriptorSubType - FORMAT UNCOMPRESSED */ + 0x01, /* 3 bFormatIndex */ + 0x01, /* 4 bNumFrameDescriptors - 1 Frame descriptor followed */ + 0x59,0x55,0x59,0x32, + 0x00,0x00,0x10,0x00, + 0x80,0x00,0x00,0xAA, + 0x00,0x38,0x9B,0x71, /* 5 guidFormat - YUY2 Video format */ + BITS_PER_PIXEL, /* 21 bBitsPerPixel - 16 bits */ + 0x01, /* 22 bDefaultFrameIndex */ + 0x00, /* 23 bAspectRatioX */ + 0x00, /* 24 bAspectRatioY */ + 0x00, /* 25 bmInterlaceFlags - No interlaced mode */ + 0x00, /* 26 bCopyProtect - No restrictions on duplication */ + + /* Class-specific VS Frame Descriptor */ + 0x1E, /* 0 bLength */ + USB_DESCTYPE_CS_INTERFACE, /* 1 bDescriptorType - Class-specific Interface */ + USB_VS_FRAME_UNCOMPRESSED, /* 2 bDescriptorSubType */ + 0x01, /* 3 bFrameIndex */ + 0x01, /* 4 bmCapabilities - Still image capture method 1 */ + SHORT_CHARS(WIDTH), /* 5 wWidth - 480 pixels */ + SHORT_CHARS(HEIGHT), /* 7 wHeight - 320 pixels */ + WORD_CHARS(MIN_BIT_RATE), /* 9 dwMinBitRate */ + WORD_CHARS(MAX_BIT_RATE), /* 13 dwMaxBitRate */ + WORD_CHARS(MAX_FRAME_SIZE), /* 17 dwMaxVideoFrameBufSize */ + WORD_CHARS(FRAME_INTERVAL), /* 21 dwDefaultFrameInterval (in 100ns units) */ + 0x01, /* 25 bFrameIntervalType */ + WORD_CHARS(FRAME_INTERVAL), /* 26 dwFrameInterval (in 100ns units) */ + + /* Video Streaming Interface Descriptor */ + /* Alternate Setting 1 */ + 0x09, /* 0 bLength */ + USB_DESCTYPE_INTERFACE, /* 1 bDescriptorType - Interface */ + 0x01, /* 2 bInterfaceNumber - Interface 1 */ + 0x01, /* 3 bAlternateSetting - 1 */ + 0x01, /* 4 bNumEndpoints */ + USB_CLASS_VIDEO, /* 5 bInterfaceClass - Video Class */ + USB_VIDEO_STREAMING, /* 6 bInterfaceSubClass - VideoStreaming Interface */ + 0x00, /* 7 bInterfaceProtocol - No protocol */ + 0x00, /* 8 iInterface - Unused */ + + /* Standard VS Isochronous Video Data Endpoint Descriptor */ + 0x07, /* 0 bLength */ + USB_DESCTYPE_ENDPOINT, /* 1 bDescriptorType */ + (VIDEO_DATA_EP_NUM | 0x80), /* 2 bEndpointAddress - IN Endpoint */ + 0x05, /* 3 bmAttributes - Isochronous EP (Asynchronous) */ + 0x00, 0x04, /* 4 wMaxPacketSize 1x 1024 bytes*/ + 0x01, /* 6 bInterval */ + +}; + +unsafe{ + /* String table - unsafe as accessed via shared memory */ + static char * unsafe stringDescriptors[]= + { + "\x09\x04", /* Language ID string (US English) */ + "XMOS", /* iManufacturer */ + "XMOS USB Video Device",/* iProduct */ + "Config", /* iConfiguration string */ + }; +} + +/* Endpoint 0 handles both std USB requests and Video class-specific requests */ +void Endpoint0(chanend chan_ep0_out, chanend chan_ep0_in, unsigned short PID) +{ + devDesc[10] = PID & 0xff; + devDesc[11] = PID >> 8; + + USB_SetupPacket_t sp; + + unsigned bmRequestType; + XUD_BusSpeed_t usbBusSpeed; + + XUD_ep ep0_out = XUD_InitEp(chan_ep0_out); + XUD_ep ep0_in = XUD_InitEp(chan_ep0_in); + + UVC_InitProbeCommitData(); + + while(1) + { + /* Returns XUD_RES_OKAY on success */ + XUD_Result_t result = USB_GetSetupPacket(ep0_out, ep0_in, sp); + + if(result == XUD_RES_OKAY) + { + /* Set result to ERR, we expect it to get set to OKAY if a request is handled */ + result = XUD_RES_ERR; + + /* Stick bmRequest type back together for an easier parse... */ + bmRequestType = (sp.bmRequestType.Direction<<7) | + (sp.bmRequestType.Type<<5) | + (sp.bmRequestType.Recipient); + + if ((bmRequestType == USB_BMREQ_H2D_STANDARD_DEV) && + (sp.bRequest == USB_SET_ADDRESS)) + { + // Host has set device address, value contained in sp.wValue + } + + switch(bmRequestType) + { + /* Direction: Device-to-host and Host-to-device + * Type: Class + * Recipient: Interface / Endpoint + */ + case USB_BMREQ_H2D_CLASS_INT: + case USB_BMREQ_D2H_CLASS_INT: + case USB_BMREQ_H2D_CLASS_EP: + case USB_BMREQ_D2H_CLASS_EP: + + /* Inspect for VideoControl Class interface number or + * VideoStreaming Class interface number or EP number; + * If an Entity is addressed, the High byte has to be checked + * for Entity ID */ + if(sp.wIndex == 0 || sp.wIndex == 1 || sp.wIndex == (VIDEO_DATA_EP_NUM | 0x80)) + { + /* Returns XUD_RES_OKAY if handled, + * XUD_RES_ERR if not handled, + * XUD_RES_RST for bus reset */ + result = UVC_InterfaceClassRequests(ep0_out, ep0_in, sp); + } + break; + } + } /* if ends */ + + /* If we haven't handled the request about then do standard enumeration requests */ + if(result == XUD_RES_ERR ) + { + /* Returns XUD_RES_OKAY if handled okay, + * XUD_RES_ERR if request was not handled (STALLed), + * XUD_RES_RST for USB Reset */ + unsafe{ + result = USB_StandardRequests(ep0_out, ep0_in, devDesc, + sizeof(devDesc), cfgDesc, sizeof(cfgDesc), + null, 0, null, 0, stringDescriptors, sizeof(stringDescriptors)/sizeof(stringDescriptors[0]), + sp, usbBusSpeed); + } + } + + /* USB bus reset detected, reset EP and get new bus speed */ + if(result == XUD_RES_RST) + { + usbBusSpeed = XUD_ResetEndpoint(ep0_out, ep0_in); + } + } +} + +/* Buffer to hold Video data in YUYV format */ +unsigned int gVideoBuffer[3][PAYLOAD_SIZE / 4]; + +/* Function to handle all endpoints of the Video class excluding control endpoint0 */ +void VideoEndpointsHandler(chanend c_epint_in, chanend c_episo_in, unsigned instance) +{ + XUD_Result_t result; + int frame = 0x0C; + int pts, tmrValue = 0; + timer presentationTimer; + + int sofCounts = 0, frameCounts = 0; + unsigned int index = 0; + unsigned int i_index = 0; + int split = (MAX_FRAME_SIZE / 6); + int i_split = (MAX_FRAME_SIZE / 6); + + /* Initialize all endpoints */ + XUD_ep epint_in = XUD_InitEp(c_epint_in); + XUD_ep episo_in = XUD_InitEp(c_episo_in); + + /* Just to keep compiler happy */ + epint_in = epint_in; + /* XUD will NAK if the endpoint is not ready to communicate with XUD */ + + /* Fill video buffers with different color data */ + for(int i = 0; i < (PAYLOAD_SIZE/4); i++) { + /* Set RED color */ + gVideoBuffer[0][i] = 0x7010D010 * instance; + /* Set GREEN color */ + gVideoBuffer[2][i] = 0x00000000; + /* Set BLUE color */ + gVideoBuffer[1][i] = 0xDC206020; + } + + while(1) + { + int expectedPixels = MAX_FRAME_SIZE; + presentationTimer :> pts; + + /* Fill the buffers with payload header */ + for(int i=0; i<3; i++) + { + /* Make the Payload header */ + (gVideoBuffer[i], unsigned char[])[0] = PAYLOAD_HEADER_LENGTH; + (gVideoBuffer[i], unsigned char[])[1] = frame; + /* Set dwPresentationTime */ + (gVideoBuffer[i], unsigned short[])[1] = pts; + (gVideoBuffer[i], unsigned short[])[2] = pts>>16; + /* Set scrSourceClock */ + (gVideoBuffer[i], unsigned short[])[3] = pts; + (gVideoBuffer[i], unsigned short[])[4] = pts>>16; + (gVideoBuffer[i], unsigned short[])[5] = (sofCounts>>3) & 2047; + } + + /* Just to simulate the motion in the video frames */ + i_split = (i_split - ((WIDTH)*8)); + if(i_split <= 0) { + i_split = MAX_FRAME_SIZE / 6; + i_index = (i_index + 1) % 3; + } + presentationTimer :> tmrValue; + + /* Let the frames scroll */ + index = i_index; + split = i_split; + + /* Transmits single frame */ + while(expectedPixels > 0) + { + if(expectedPixels < (PAYLOAD_SIZE - PAYLOAD_HEADER_LENGTH)) { + /* Payload transfer */ + result = XUD_SetBuffer(episo_in, (gVideoBuffer[index], unsigned char[]), expectedPixels+PAYLOAD_HEADER_LENGTH); + } else { + /* Payload transfer */ + result = XUD_SetBuffer(episo_in, (gVideoBuffer[index], unsigned char[]), 1024); + } + /* Note down the SOF counts */ + sofCounts++; + + expectedPixels -= ((PAYLOAD_SIZE)- PAYLOAD_HEADER_LENGTH); + + if(expectedPixels <= (MAX_FRAME_SIZE - split)) { + index = (index + 1) % 3; + split += (MAX_FRAME_SIZE / 6); + } + } + frame = frame ^ 1; /* Toggle FID bit */ + frameCounts++; + } +} diff --git a/examples/dual_AN00127_video_class/src/uvc_defs.h b/examples/dual_AN00127_video_class/src/uvc_defs.h new file mode 100644 index 00000000..0c30e6ac --- /dev/null +++ b/examples/dual_AN00127_video_class/src/uvc_defs.h @@ -0,0 +1,78 @@ +// Copyright 2015-2021 XMOS LIMITED. +// This Software is subject to the terms of the XMOS Public Licence: Version 1. + +#ifndef UVC_DEFS_H_ +#define UVC_DEFS_H_ + +/* USB Video device product defines */ +#define BCD_DEVICE 0x0100 +#define VENDOR_ID 0x20B1 +#define PRODUCT_ID 0x1DE0 + +/* USB Sub class and Protocol codes */ +#define USB_VIDEO_CONTROL 0x01 +#define USB_VIDEO_STREAMING 0x02 +#define USB_VIDEO_INTERFACE_COLLECTION 0x03 + +/* Descriptor types */ +#define USB_DESCTYPE_CS_INTERFACE 0x24 +#define USB_DESCTYPE_CS_ENDPOINT 0x25 + +/* USB Video Control Subtype Descriptors */ +#define USB_VC_HEADER 0x01 +#define USB_VC_INPUT_TERMINAL 0x02 +#define USB_VC_OUPUT_TERMINAL 0x03 +#define USB_VC_SELECTOR_UNIT 0x04 +#define USB_VC_PROCESSING_UNIT 0x05 + +/* USB Video Streaming Subtype Descriptors */ +#define USB_VS_INPUT_HEADER 0x01 +#define USB_VS_OUPUT_HEADER 0x02 +#define USB_VS_STILL_IMAGE_FRAME 0x03 +#define USB_VS_FORMAT_UNCOMPRESSED 0x04 +#define USB_VS_FRAME_UNCOMPRESSED 0x05 +#define USB_VS_FORMAT_MJPEG 0x06 +#define USB_VS_FRAME_MJPEG 0x07 + +/* USB Video resolution */ +#define BITS_PER_PIXEL 16 +#define WIDTH 480 +#define HEIGHT 320 + +/* Frame rate */ +#define FPS 30 + +#define MAX_FRAME_SIZE (WIDTH * HEIGHT * BITS_PER_PIXEL / 8) +#define MIN_BIT_RATE (MAX_FRAME_SIZE * FPS * 8) +#define MAX_BIT_RATE (MIN_BIT_RATE) +#define PAYLOAD_SIZE (1 * 1024) + +/* Interval defined in 100ns units */ +#define FRAME_INTERVAL (10000000/FPS) + +/* To split numbers into Little Endian format */ +#define WORD_CHARS(x) (x&0xff), ((x>>8)&0xff), ((x>>16)&0xff), ((x>>24)&0xff) +#define SHORT_CHARS(x) (x&0xff), ((x>>8)&0xff) + +/* Endpoint Addresses for Video device */ +#define VIDEO_STATUS_EP_NUM 1 /* (0x81) */ +#define VIDEO_DATA_EP_NUM 2 /* (0x82) */ + +/* Video Class-specific Request codes */ +#define SET_CUR 0x01 +#define GET_CUR 0x81 +#define GET_MIN 0x82 +#define GET_MAX 0x83 +#define GET_RES 0x84 +#define GET_LEN 0x85 +#define GET_INFO 0x86 +#define GET_DEF 0x87 + +/* Video Streaming Interface Control selectors */ +#define VS_PROBE_CONTROL 0x01 +#define VS_COMMIT_CONTROL 0x02 + +/* Video Stream related */ +#define PAYLOAD_HEADER_LENGTH 12 + +#endif /* UVC_DEFS_H_ */ diff --git a/examples/dual_AN00127_video_class/src/uvc_req.c b/examples/dual_AN00127_video_class/src/uvc_req.c new file mode 100644 index 00000000..06a23f9c --- /dev/null +++ b/examples/dual_AN00127_video_class/src/uvc_req.c @@ -0,0 +1,113 @@ +// Copyright 2015-2021 XMOS LIMITED. +// This Software is subject to the terms of the XMOS Public Licence: Version 1. + +#include +#include "uvc_req.h" +#include "uvc_defs.h" + +UVC_ProbeCommit_Ctrl_t dataProbeCommit; + +/* Initializes Probe/Commit control parameters with defaul values */ +void UVC_InitProbeCommitData() +{ + dataProbeCommit.bmHint = 0; + dataProbeCommit.bFormatIndex = 0x01; + dataProbeCommit.bFrameIndex = 0x01; + dataProbeCommit.dwFrameInterval = FRAME_INTERVAL; + dataProbeCommit.wKeyFrameRate = 0; + dataProbeCommit.wPFrameRate = 0; + dataProbeCommit.wCompQuality = 0; + dataProbeCommit.wCompWindowSize = 0; + dataProbeCommit.wDelay = 0; + dataProbeCommit.dwMaxVideoFrameSize = MAX_FRAME_SIZE; + dataProbeCommit.dwMaxPayloadTransferSize = PAYLOAD_SIZE; + dataProbeCommit.dwClockFrequency = 100000000; +} + + +/* Video Class-specific requests handler function */ +XUD_Result_t UVC_InterfaceClassRequests(XUD_ep ep_out, XUD_ep ep_in, USB_SetupPacket_t *sp) +{ + /* Word aligned buffer */ + unsigned int probe_buffer[16]; + unsigned int buffer[16]; + unsigned int length; + XUD_Result_t result = XUD_RES_ERR; + +#if defined (DEBUG) && (DEBUG == 1) + printhexln(sp->bRequest); +#endif + + switch(sp->bRequest) + { + case SET_CUR: + /* VideoStreaming Interface */ + if(sp->wIndex == 0x01) + { + switch((sp->wValue >> 8) & 0xFF) + { + /* Negotiation of Video parameters */ + case VS_COMMIT_CONTROL: + case VS_PROBE_CONTROL: + /* Get the parameters in Probe buffer */ + if((result = XUD_GetBuffer(ep_out, (unsigned char *) probe_buffer, &length)) != XUD_RES_OKAY) + { + return result; + } + /* Set the given parameters */ + if(length == sizeof(dataProbeCommit)) { + //memcpy(((unsigned char *) &dataProbeCommit)+2, ((unsigned char*)probe_buffer)+2, length-2); + } + break; + } + } + else + { + if((result = XUD_GetBuffer(ep_out, (unsigned char *) buffer, &length)) != XUD_RES_OKAY) + { + return result; + } + } + + result = XUD_DoSetRequestStatus(ep_in); + return result; + break; + + case GET_DEF: + case GET_MIN: + case GET_MAX: + case GET_CUR: + /* VideoControl Interface */ + if(sp->wIndex == 0x00) + { + /* Handle VideoControl interface requests here */ + } + /* VideoStreaming Interface */ + else if(sp->wIndex == 0x01) + { + switch((sp->wValue >> 8) & 0xFF) + { + case VS_PROBE_CONTROL: + if(sp->wLength <= sizeof(dataProbeCommit)) { + length = sp->wLength; + result = XUD_DoGetRequest(ep_out, ep_in, (unsigned char *) (&dataProbeCommit), length, sp->wLength); + return result; + } + break; + + default: + // Unknown command + break; + } + } + break; + + default: + // Error case + printhexln(sp->bRequest); + return result; + break; + } + return XUD_RES_ERR; +} + diff --git a/examples/dual_AN00127_video_class/src/uvc_req.h b/examples/dual_AN00127_video_class/src/uvc_req.h new file mode 100644 index 00000000..09c24420 --- /dev/null +++ b/examples/dual_AN00127_video_class/src/uvc_req.h @@ -0,0 +1,44 @@ +// Copyright 2015-2021 XMOS LIMITED. +// This Software is subject to the terms of the XMOS Public Licence: Version 1. + +#ifndef UVC_REQ_H_ +#define UVC_REQ_H_ + +#include +#include "xud_device.h" + +/* Video Class-specific requests definitions */ + +#ifdef __STDC__ + +/* Video Probe and Commit Controls (Table 4-47 , UVC 1.1) */ +typedef struct +{ + unsigned short bmHint; + unsigned char bFormatIndex; + unsigned char bFrameIndex; + unsigned int dwFrameInterval; + unsigned short wKeyFrameRate; + unsigned short wPFrameRate; + unsigned short wCompQuality; + unsigned short wCompWindowSize; + unsigned short wDelay; + unsigned int dwMaxVideoFrameSize; + unsigned int dwMaxPayloadTransferSize; + unsigned int dwClockFrequency; + unsigned char bmFramingInfo; + unsigned char bPreferedVersion; + unsigned char bMinVersion; + unsigned char bMaxVersion; +} __attribute__((packed)) UVC_ProbeCommit_Ctrl_t; + +extern UVC_ProbeCommit_Ctrl_t dataProbeCommit; + +#endif + +void UVC_InitProbeCommitData(); + +XUD_Result_t UVC_InterfaceClassRequests(XUD_ep ep_out, XUD_ep ep_in, REFERENCE_PARAM(USB_SetupPacket_t,sp)); + + +#endif /* UVC_REQ_H_ */ diff --git a/examples/dual_AN00127_video_class/src/xud_wrapper.c b/examples/dual_AN00127_video_class/src/xud_wrapper.c new file mode 100644 index 00000000..1707e929 --- /dev/null +++ b/examples/dual_AN00127_video_class/src/xud_wrapper.c @@ -0,0 +1,35 @@ +#include +#include + +#include "xud.h" +#include "usb_video.h" + + +int XUD_Main_wrapper(chanend c_epOut[], int noEpOut, + chanend c_epIn[], int noEpIn, + NULLABLE_RESOURCE(chanend, c_sof), + XUD_EpType epTypeTableOut[], XUD_EpType epTypeTableIn[], + XUD_BusSpeed_t desiredSpeed, + XUD_PwrConfig pwrConfig +){ + + return XUD_Main(c_epOut, noEpOut, c_epIn, noEpIn, + c_sof, epTypeTableOut, epTypeTableIn, + desiredSpeed, pwrConfig); +} + +void Endpoint0_wrapper(chanend chan_ep0_out, chanend chan_ep0_in, unsigned short PID){ + Endpoint0(chan_ep0_out, chan_ep0_in, PID); +} + +void VideoEndpointsHandler_wrapper(chanend c_epint_in, chanend c_episo_in, unsigned instance){ + VideoEndpointsHandler(c_epint_in, c_episo_in, instance); +} + + +extern XUD_resources_t * resource_ptr; +void init_xud_resources(XUD_resources_t * resources) +{ + printf("d: %p s: %p\n", resource_ptr, resources); + memcpy(resource_ptr, resources, sizeof(XUD_resources_t)); +} \ No newline at end of file diff --git a/examples/dual_AN00127_video_class/src/xud_wrapper.h b/examples/dual_AN00127_video_class/src/xud_wrapper.h new file mode 100644 index 00000000..30350284 --- /dev/null +++ b/examples/dual_AN00127_video_class/src/xud_wrapper.h @@ -0,0 +1,16 @@ +#include + +#include "xud.h" +#include "usb_video.h" + + +int XUD_Main_wrapper(chanend c_epOut[], int noEpOut, + chanend c_epIn[], int noEpIn, + NULLABLE_RESOURCE(chanend, c_sof), + XUD_EpType epTypeTableOut[], XUD_EpType epTypeTableIn[], + XUD_BusSpeed_t desiredSpeed, + XUD_PwrConfig pwrConfig); + +void Endpoint0_wrapper(chanend chan_ep0_out, chanend chan_ep0_in, unsigned short PID); +void VideoEndpointsHandler_wrapper(chanend c_epint_in, chanend c_episo_in, unsigned instance); +void init_xud_resources(XUD_resources_t * resources); \ No newline at end of file diff --git a/lib_xud/api/xud.h b/lib_xud/api/xud.h index 72842308..0c3a59ef 100644 --- a/lib_xud/api/xud.h +++ b/lib_xud/api/xud.h @@ -120,6 +120,22 @@ typedef enum XUD_Result XUD_RES_ERR = 2, } XUD_Result_t; +/* All of the resources accessed by XUD */ +typedef struct XUD_resources_t +{ + port flag0_port; + port flag1_port; + NULLABLE_RESOURCE(port, flag2_port); + in_buffered_port_32_t p_usb_clk; + out_buffered_port_32_t p_usb_txd; + in_buffered_port_32_t p_usb_rxd ; + port tx_readyout; + port tx_readyin; + port rx_rdy; + xcore_clock_t tx_usb_clk; + xcore_clock_t rx_usb_clk; +} XUD_resources_t; + /** This performs the low-level USB I/O operations. Note that this * needs to run in a thread with at least 80 MIPS worst case execution * speed. diff --git a/lib_xud/src/core/XUD_DeviceAttach.xc b/lib_xud/src/core/XUD_DeviceAttach.xc index d1808327..d8624896 100755 --- a/lib_xud/src/core/XUD_DeviceAttach.xc +++ b/lib_xud/src/core/XUD_DeviceAttach.xc @@ -8,10 +8,6 @@ #include "XUD_TimingDefines.h" #include "XUD_HAL.h" -extern in port flag0_port; -extern in port flag1_port; -extern in port flag2_port; -extern out buffered port:32 p_usb_txd; #define TUCHEND_DELAY_us (1500) // 1.5ms #define TUCHEND_DELAY (TUCHEND_DELAY_us * PLATFORM_REFERENCE_MHZ) @@ -23,6 +19,7 @@ extern out buffered port:32 p_usb_txd; #define INVALID_DELAY (INVALID_DELAY_us * PLATFORM_REFERENCE_MHZ) extern int resetCount; +extern XUD_resources_t * unsafe resource_ptr; /* Assumptions: * - In full speed mode @@ -38,7 +35,7 @@ int XUD_DeviceAttachHS(XUD_PwrConfig pwrConfig) int tx; unsigned int chirpCount = 0; - clearbuf(p_usb_txd); + unsafe{clearbuf(resource_ptr->p_usb_txd);} /* On detecting the SE0 move into chirp mode */ XUD_HAL_EnterMode_PeripheralChirp(); @@ -49,8 +46,8 @@ int XUD_DeviceAttachHS(XUD_PwrConfig pwrConfig) #else for (int i = 0; i < 16000; i++) // 16000 words @ 480 MBit = 1.066 ms #endif - { - p_usb_txd <: 0; + unsafe{ + resource_ptr->p_usb_txd <: 0; } // J, K, SE0 on flag ports 0, 1, 2 respectively (on XS2) @@ -62,7 +59,7 @@ int XUD_DeviceAttachHS(XUD_PwrConfig pwrConfig) t :> start_time; while(1) - { + unsafe{ select { case t when timerafter(start_time + INVALID_DELAY) :> void: @@ -76,8 +73,8 @@ int XUD_DeviceAttachHS(XUD_PwrConfig pwrConfig) /* TODO Use a timer to save some juice...*/ #if !defined(__XS2A__) unsigned dp, dm; - flag0_port :> dm; - flag1_port :> dp; + resource_ptr->flag0_port :> dm; + resource_ptr->flag1_port :> dp; if(dp || dm) { @@ -85,7 +82,7 @@ int XUD_DeviceAttachHS(XUD_PwrConfig pwrConfig) return 0; } #else - flag2_port :> tmp; + resource_ptr->flag2_port :> tmp; if(!tmp) { @@ -106,11 +103,11 @@ int XUD_DeviceAttachHS(XUD_PwrConfig pwrConfig) #if !defined(__XS2A__) // Note, J and K definitions are reversed in XS3A -#define j_port flag1_port -#define k_port flag0_port +#define j_port resource_ptr->flag1_port +#define k_port resource_ptr->flag0_port #else -#define k_port flag1_port -#define j_port flag0_port +#define k_port resource_ptr->flag1_port +#define j_port resource_ptr->flag0_port #endif case detecting_k => k_port when pinseq(1):> void @ tx: // K Chirp k_port @ tx + T_FILT_ticks :> tmp; diff --git a/lib_xud/src/core/XUD_HAL.xc b/lib_xud/src/core/XUD_HAL.xc index 32ad1961..2687e877 100644 --- a/lib_xud/src/core/XUD_HAL.xc +++ b/lib_xud/src/core/XUD_HAL.xc @@ -10,14 +10,9 @@ #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; -extern buffered in port:32 p_usb_clk; + #else -extern in port flag0_port; /* For XS3: RXA or DP */ -extern in port flag1_port; /* For XS3: RXE or DM */ -extern buffered in port:32 p_usb_clk; + void XUD_SetCrcTableAddr(unsigned addr); unsigned XtlSelFromMhz(unsigned m) { // NOCOVER @@ -48,7 +43,8 @@ unsigned XtlSelFromMhz(unsigned m) return 0b000; } #endif -extern clock rx_usb_clk; + +extern XUD_resources_t * unsafe resource_ptr; unsigned int XUD_EnableUsbPortMux(); @@ -88,10 +84,12 @@ void XUD_HAL_EnableUsb(unsigned pwrConfig) #endif /* Wait for USB clock (typically 1ms after reset) */ - p_usb_clk when pinseq(1) :> int _; - p_usb_clk when pinseq(0) :> int _; - p_usb_clk when pinseq(1) :> int _; - p_usb_clk when pinseq(0) :> int _; + unsafe{ + resource_ptr->p_usb_clk when pinseq(1) :> int _; + resource_ptr->p_usb_clk when pinseq(0) :> int _; + resource_ptr->p_usb_clk when pinseq(1) :> int _; + resource_ptr->p_usb_clk when pinseq(0) :> int _; + } #ifdef __XS2A__ /* Some extra settings are required for proper operation on XS2A */ @@ -210,6 +208,7 @@ void XUD_HAL_EnterMode_PeripheralHighSpeed_Start() 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); } } + void XUD_HAL_EnterMode_PeripheralHighSpeed_Complete() { unsafe @@ -288,11 +287,11 @@ void XUD_HAL_EnterMode_TristateDrivers() void XUD_HAL_Mode_Signalling() { /* Reset port to use XS1_CLKBLK_REF (from rx_usb_clk) */ - set_port_use_on(flag1_port); + unsafe{set_port_use_on(resource_ptr->flag1_port);} #ifdef __XS2A__ /* For XS2 we invert VALID_TOKEN port for data-transfer mode, so undo this for signalling */ - set_port_no_inv(flag2_port); + set_port_no_inv(resource_ptr->flag2_port); write_periph_word(USB_TILE_REF, XS1_GLX_PER_UIFM_CHANEND_NUM, XS1_GLX_PER_UIFM_MASK_NUM, ((1<flag1_port, resource_ptr->rx_usb_clk); + set_pad_delay(resource_ptr->flag1_port, 2); + } #ifdef __XS2A__ /* Set UIFM to CHECK TOKENS mode and enable LINESTATE_DECODE @@ -325,7 +326,7 @@ void XUD_HAL_Mode_DataTransfer() | ((1< j; - flag1_port :> k; - flag2_port :> se0; + unsafe{ + resource_ptr->flag0_port :> j; + resource_ptr->flag1_port :> k; + resource_ptr->flag2_port :> se0; + } if(j) return XUD_LINESTATE_HS_J_FS_K; @@ -367,8 +370,10 @@ XUD_LineState_t XUD_HAL_GetLineState(/*XUD_HAL_t &xudHal*/) return XUD_LINESTATE_SE1; #else unsigned dp, dm; - dp_port :> dp; - dm_port :> dm; + unsafe{ + resource_ptr->dp_port :> dp; + resource_ptr->dm_port :> dm; + } return LinesToLineState(dp, dm); #endif } @@ -388,16 +393,18 @@ unsigned XUD_HAL_WaitForLineStateChange(XUD_LineState_t ¤tLs, unsigned tim 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; + unsafe{ + select + { + case resource_ptr->flag0_port when pinsneq(j) :> void: + break; + case resource_ptr->flag1_port when pinsneq(k) :> void: + break; + case resource_ptr->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 */ @@ -410,16 +417,18 @@ unsigned XUD_HAL_WaitForLineStateChange(XUD_LineState_t ¤tLs, unsigned tim {dp, dm} = LineStateToLines(currentLs); /* Wait for change */ - select - { - case dp_port when pinsneq(dp) :> dp: - dm_port :> dm; //Both might have changed! - break; - case dm_port when pinsneq(dm) :> dm: - dp_port :> dp; //Both might have changed! - break; - case timeout != null => t when timerafter(time + timeout) :> int _: - return 1; + unsafe{ + select + { + case resource_ptr->dp_port when pinsneq(dp) :> dp: + resource_ptr->dm_port :> dm; //Both might have changed! + break; + case resource_ptr->dm_port when pinsneq(dm) :> dm: + resource_ptr->dp_port :> dp; //Both might have changed! + break; + case timeout != null => t when timerafter(time + timeout) :> int _: + return 1; + } } /* Return new linestate */ diff --git a/lib_xud/src/core/XUD_Main.xc b/lib_xud/src/core/XUD_Main.xc index ef53f213..6db6007f 100755 --- a/lib_xud/src/core/XUD_Main.xc +++ b/lib_xud/src/core/XUD_Main.xc @@ -10,6 +10,7 @@ #include #include #include +#include #include "xud.h" /* External user include file */ #include "XUD_USB_Defines.h" @@ -39,6 +40,8 @@ unsigned g_curSpeed; unsigned g_desSpeed; unsigned g_txHandshakeTimeout; +#if !XUD_EXTERNAL_RESOURCES + in port flag0_port = PORT_USB_FLAG0; /* For XS3: Mission: RXE, XS2 is configurable and set to RXE in mission mode */ in port flag1_port = PORT_USB_FLAG1; /* For XS3: Mission: RXA, XS2 is configuratble and set to RXA in mission mode*/ @@ -59,6 +62,60 @@ in port rx_rdy = PORT_USB_RX_READY; on USB_TILE: clock tx_usb_clk = XS1_CLKBLK_4; on USB_TILE: clock rx_usb_clk = XS1_CLKBLK_5; +#else + +#if XUD_EXTERNAL_RESOURCES +/* These are globals to allow assembler functions to access resource IDs */ +int rx_rdy = 0; +int flag1_port = 0; +int p_usb_rxd = 0; +int p_usb_txd = 0; + +extern XUD_resources_t XUD_resources; + +// XUD_resources_t XUD_resources = { +// PORT_USB_FLAG0, +// PORT_USB_FLAG1, +// #ifdef __XS2A__ +// PORT_USB_FLAG2 +// #else +// null, +// #endif +// PORT_USB_CLK, +// PORT_USB_TXD, +// PORT_USB_RXD, +// PORT_USB_TX_READYOUT, +// PORT_USB_TX_READYIN, +// PORT_USB_RX_READY, +// XS1_CLKBLK_4, +// XS1_CLKBLK_5 +// }; +/* + port flag1_port; + NULLABLE_RESOURCE(port, flag2_port); + in_buffered_port_32_t p_usb_clk; + out_buffered_port_32_t p_usb_txd; + in_buffered_port_32_t p_usb_rxd ; + port tx_readyout; + port tx_readyin; + port rx_rdy; + xcore_clock_t tx_usb_clk; + xcore_clock_t rx_usb_clk; + #define PORT_USB_CLK on USB_TILE: XS1_PORT_1J + #define PORT_USB_TXD on USB_TILE: XS1_PORT_8A + #define PORT_USB_RXD on USB_TILE: XS1_PORT_8B + #define PORT_USB_TX_READYOUT on USB_TILE: XS1_PORT_1K + #define PORT_USB_TX_READYIN on USB_TILE: XS1_PORT_1H + #define PORT_USB_RX_READY on USB_TILE: XS1_PORT_1I + #define PORT_USB_FLAG0 on USB_TILE: XS1_PORT_1E + #define PORT_USB_FLAG1 on USB_TILE: XS1_PORT_1F + #define PORT_USB_FLAG2 on USB_TILE: XS1_PORT_1G; +*/ +unsafe{ XUD_resources_t * unsafe resource_ptr = &XUD_resources;} +#endif + +#endif + // We use a single array instrad of two here and append epAddr_Ready_setup on the end to save some instructions in the Setup // token handling code. i.e. what we really want is the following, but's less efficient. // unsigned epAddr_Ready[USB_MAN_NUM_EP] @@ -155,14 +212,16 @@ static int XUD_Manager_loop(XUD_chan epChans0[], XUD_chan epAddr_Ready[], chane int reset = 1; /* Flag for if device is returning from a reset */ /* Make sure ports are on and reset port states */ - set_port_use_on(p_usb_clk); - set_port_use_on(p_usb_txd); - set_port_use_on(p_usb_rxd); - set_port_use_on(flag0_port); - set_port_use_on(flag1_port); + unsafe{ + set_port_use_on(resource_ptr->p_usb_clk); + set_port_use_on(resource_ptr->p_usb_txd); + set_port_use_on(resource_ptr->p_usb_rxd); + set_port_use_on(resource_ptr->flag0_port); + set_port_use_on(resource_ptr->flag1_port); + #if defined(__XS2A__) /* Extra flag port in XS2 */ - set_port_use_on(flag2_port); + set_port_use_on(resource_ptr->flag2_port); #endif #if !defined(__XS2A__) @@ -208,38 +267,41 @@ static int XUD_Manager_loop(XUD_chan epChans0[], XUD_chan epAddr_Ready[], chane #endif // Handshaken ports need USB clock - configure_clock_src(tx_usb_clk, p_usb_clk); - configure_clock_src(rx_usb_clk, p_usb_clk); + configure_clock_src(resource_ptr->tx_usb_clk, resource_ptr->p_usb_clk); + configure_clock_src(resource_ptr->rx_usb_clk, resource_ptr->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 - set_port_inv(p_usb_clk); - set_port_sample_delay(p_usb_clk); + set_port_inv(resource_ptr->p_usb_clk); + set_port_sample_delay(resource_ptr->p_usb_clk); // This delay controls the capture of rdy - set_clock_rise_delay(tx_usb_clk, TX_RISE_DELAY); + set_clock_rise_delay(resource_ptr->tx_usb_clk, TX_RISE_DELAY); // This delay controls the launch of data. - set_clock_fall_delay(tx_usb_clk, TX_FALL_DELAY); + set_clock_fall_delay(resource_ptr->tx_usb_clk, TX_FALL_DELAY); // This delay the capture of the rdyIn and data. - set_clock_rise_delay(rx_usb_clk, RX_RISE_DELAY); - set_clock_fall_delay(rx_usb_clk, RX_FALL_DELAY); + set_clock_rise_delay(resource_ptr->rx_usb_clk, RX_RISE_DELAY); + set_clock_fall_delay(resource_ptr->rx_usb_clk, RX_FALL_DELAY); - set_pad_delay(flag1_port, 2); + set_pad_delay(resource_ptr->flag1_port, 2); - start_clock(tx_usb_clk); - start_clock(rx_usb_clk); + start_clock(resource_ptr->tx_usb_clk); + start_clock(resource_ptr->rx_usb_clk); - configure_out_port_handshake(p_usb_txd, tx_readyin, tx_readyout, tx_usb_clk, 0); - configure_in_port_strobed_slave(p_usb_rxd, rx_rdy, rx_usb_clk); + configure_out_port_handshake(resource_ptr->p_usb_txd, resource_ptr->tx_readyin, resource_ptr->tx_readyout, resource_ptr->tx_usb_clk, 0); + configure_in_port_strobed_slave(resource_ptr->p_usb_rxd, resource_ptr->rx_rdy, resource_ptr->rx_usb_clk); /* Clock RxA port from USB clock - helps fall event */ - configure_in_port(flag1_port, rx_usb_clk); + configure_in_port(resource_ptr->flag1_port, resource_ptr->rx_usb_clk); + + } // unsafe unsigned noExit = 1; + while(noExit) { unsigned settings[] = {0}; @@ -400,7 +462,18 @@ static int XUD_Manager_loop(XUD_chan epChans0[], XUD_chan epAddr_Ready[], chane /* flag0: Rx Error flag1: Rx Active flag2: Null / Valid Token */ - noExit = XUD_LLD_IoLoop(p_usb_rxd, flag1_port, p_usb_txd, flag0_port, flag2_port, epTypeTableOut, epTypeTableIn, epAddr_Ready, noEpOut, c_sof); + unsafe{ + noExit = XUD_LLD_IoLoop(resource_ptr->p_usb_rxd, + resource_ptr->flag1_port, + resource_ptr->p_usb_txd, + resource_ptr->flag0_port, + resource_ptr->flag2_port, + epTypeTableOut, + epTypeTableIn, + epAddr_Ready, + noEpOut, + c_sof); + } set_thread_fast_mode_off(); @@ -411,15 +484,18 @@ static int XUD_Manager_loop(XUD_chan epChans0[], XUD_chan epAddr_Ready[], chane /* TODO stop clock blocks */ + unsafe{ + /* Turn ports off */ - set_port_use_off(p_usb_txd); - set_port_use_off(p_usb_rxd); - set_port_use_off(flag0_port); - set_port_use_off(flag1_port); + set_port_use_off(resource_ptr->p_usb_txd); + set_port_use_off(resource_ptr->p_usb_rxd); + set_port_use_off(resource_ptr->flag0_port); + set_port_use_off(resource_ptr->flag1_port); #ifdef __XS2A__ - set_port_use_off(flag2_port); + set_port_use_off(resource_ptr->flag2_port); #endif - set_port_use_off(p_usb_clk); + set_port_use_off(resource_ptr->p_usb_clk); + } // unsafe return 0; } @@ -559,7 +635,6 @@ void SetupEndpoints(chanend c_ep_out[], int noEpOut, chanend c_ep_in[], int noEp } } - #pragma unsafe arrays int XUD_Main(chanend c_ep_out[], int noEpOut, chanend c_ep_in[], int noEpIn, @@ -569,6 +644,18 @@ int XUD_Main(chanend c_ep_out[], int noEpOut, { g_desSpeed = speed; + printstr("XUD\n"); +#if XUD_EXTERNAL_RESOURCES + /* Ensure global resids accessed by ASM are initt'd */ + assert(resource_ptr); + unsafe{ + rx_rdy = (int)resource_ptr->rx_rdy; + flag1_port = (int)resource_ptr->flag1_port; + p_usb_rxd = (int)resource_ptr->p_usb_rxd; + p_usb_txd = (int)resource_ptr->p_usb_txd; + } +#endif + SetupEndpoints(c_ep_out, noEpOut, c_ep_in, noEpIn, epTypeTableOut, epTypeTableIn); #if 0 diff --git a/lib_xud/src/core/XUD_TestMode.xc b/lib_xud/src/core/XUD_TestMode.xc index 1b588af1..0303908b 100644 --- a/lib_xud/src/core/XUD_TestMode.xc +++ b/lib_xud/src/core/XUD_TestMode.xc @@ -5,7 +5,7 @@ #include "xud.h" #include "XUD_TestMode.h" -extern out buffered port:32 p_usb_txd; +extern XUD_resources_t * unsafe resource_ptr; #define T_INTER_TEST_PACKET_us 2 #define T_INTER_TEST_PACKET (T_INTER_TEST_PACKET_us * PLATFORM_REFERENCE_MHZ) @@ -39,8 +39,8 @@ int XUD_UsbTestModeHandler(unsigned cmd) XUD_HAL_EnterMode_PeripheralTestJTestK(); while(1) - { - p_usb_txd <: 0xffffffff; + unsafe{ + resource_ptr->p_usb_txd <: 0xffffffff; } break; @@ -49,8 +49,8 @@ int XUD_UsbTestModeHandler(unsigned cmd) XUD_HAL_EnterMode_PeripheralTestJTestK(); while(1) - { - p_usb_txd <: 0; + unsafe{ + resource_ptr->p_usb_txd <: 0; } break; @@ -74,13 +74,13 @@ int XUD_UsbTestModeHandler(unsigned cmd) #pragma unsafe arrays while (1) - { + unsafe{ #pragma loop unroll for (i=0; i < sizeof(test_packet)/sizeof(test_packet[0]); i++) { - p_usb_txd <: test_packet[i]; + resource_ptr->p_usb_txd <: test_packet[i]; }; - sync(p_usb_txd); + sync(resource_ptr->p_usb_txd); test_packet_timer :> i; test_packet_timer when timerafter (i + T_INTER_TEST_PACKET) :> int _; } diff --git a/lib_xud/src/core/XUD_resources.c b/lib_xud/src/core/XUD_resources.c new file mode 100644 index 00000000..2e4b4cb0 --- /dev/null +++ b/lib_xud/src/core/XUD_resources.c @@ -0,0 +1,11 @@ +#include "xud.h" + +/* This is the global declaration of the resources struct used to keep + the resource IDs of this instance of XUD. Needs initialising if + multiple instances of XUD are used and XUD_EXTERNAL_RESOURCES defined. + This needs to be declared in C to avoid checks and is initialised + before the call to XUD_Main */ + +#if XUD_EXTERNAL_RESOURCES +XUD_resources_t XUD_resources; +#endif From 8282811e2e7cab7c35b5faa5accbe0431f1c7246 Mon Sep 17 00:00:00 2001 From: Ed Date: Fri, 8 Dec 2023 17:07:05 +0000 Subject: [PATCH 2/6] access resources directly rather than pointer and tidy unsafe regions --- examples/dual_AN00127_video_class/src/main.xc | 4 +- .../src/xud_wrapper.c | 8 -- .../src/xud_wrapper.h | 1 - lib_xud/api/xud.h | 15 ++- lib_xud/src/core/XUD_DeviceAttach.xc | 27 ++-- lib_xud/src/core/XUD_HAL.xc | 82 +++++------- lib_xud/src/core/XUD_Main.xc | 125 ++++++------------ lib_xud/src/core/XUD_TestMode.xc | 16 +-- lib_xud/src/core/XUD_resources.c | 12 +- 9 files changed, 124 insertions(+), 166 deletions(-) diff --git a/examples/dual_AN00127_video_class/src/main.xc b/examples/dual_AN00127_video_class/src/main.xc index a894e409..e3da33b4 100644 --- a/examples/dual_AN00127_video_class/src/main.xc +++ b/examples/dual_AN00127_video_class/src/main.xc @@ -88,7 +88,7 @@ int main() { { on USB_TILE: { - init_xud_resources(&resources); + init_xud_resources(resources); printstr("XUD\n"); XUD_Main(c_ep_out, EP_COUNT_OUT, c_ep_in, EP_COUNT_IN, null, epTypeTableOut, epTypeTableIn, @@ -104,7 +104,7 @@ int main() { on USB_TILE: { - init_xud_resources(&resources2); + init_xud_resources(resources2); printstr("XUD\n"); XUD_Main_wrapper(c_ep_out2, EP_COUNT_OUT, c_ep_in2, EP_COUNT_IN, null, epTypeTableOut2, epTypeTableIn2, diff --git a/examples/dual_AN00127_video_class/src/xud_wrapper.c b/examples/dual_AN00127_video_class/src/xud_wrapper.c index 1707e929..96f68acc 100644 --- a/examples/dual_AN00127_video_class/src/xud_wrapper.c +++ b/examples/dual_AN00127_video_class/src/xud_wrapper.c @@ -25,11 +25,3 @@ void Endpoint0_wrapper(chanend chan_ep0_out, chanend chan_ep0_in, unsigned short void VideoEndpointsHandler_wrapper(chanend c_epint_in, chanend c_episo_in, unsigned instance){ VideoEndpointsHandler(c_epint_in, c_episo_in, instance); } - - -extern XUD_resources_t * resource_ptr; -void init_xud_resources(XUD_resources_t * resources) -{ - printf("d: %p s: %p\n", resource_ptr, resources); - memcpy(resource_ptr, resources, sizeof(XUD_resources_t)); -} \ No newline at end of file diff --git a/examples/dual_AN00127_video_class/src/xud_wrapper.h b/examples/dual_AN00127_video_class/src/xud_wrapper.h index 30350284..3c34d530 100644 --- a/examples/dual_AN00127_video_class/src/xud_wrapper.h +++ b/examples/dual_AN00127_video_class/src/xud_wrapper.h @@ -13,4 +13,3 @@ int XUD_Main_wrapper(chanend c_epOut[], int noEpOut, void Endpoint0_wrapper(chanend chan_ep0_out, chanend chan_ep0_in, unsigned short PID); void VideoEndpointsHandler_wrapper(chanend c_epint_in, chanend c_episo_in, unsigned instance); -void init_xud_resources(XUD_resources_t * resources); \ No newline at end of file diff --git a/lib_xud/api/xud.h b/lib_xud/api/xud.h index 0c3a59ef..998fda1f 100644 --- a/lib_xud/api/xud.h +++ b/lib_xud/api/xud.h @@ -71,6 +71,10 @@ #endif #endif // PORT_USB_CLK +#ifndef XUD_EXTERNAL_RESOURCES +#define XUD_EXTERNAL_RESOURCES 0 +#endif + /** * \var typedef XUD_EpTransferType * \brief Typedef for endpoint data transfer types. Note: it is important that ISO is 0 @@ -532,5 +536,14 @@ typedef struct XUD_ep_info unsigned int array_ptr_setup; // 12 } XUD_ep_info; -#endif +/** + * \brief Resource initialisation for cases where we have multiple instances of XUD in a project. + * This MUST be called prior to running XUD_Main otherwise XUD will assert 0 + * \param resources A struct of type XUD_resources_t declared in XC containing the XUD + * resources which must be placed on a specific tile. + */ +void init_xud_resources(REFERENCE_PARAM(XUD_resources_t, resources)); + +#endif // __ASSEMBLER__ + #endif // _XUD_H_ diff --git a/lib_xud/src/core/XUD_DeviceAttach.xc b/lib_xud/src/core/XUD_DeviceAttach.xc index d8624896..f5bb829c 100755 --- a/lib_xud/src/core/XUD_DeviceAttach.xc +++ b/lib_xud/src/core/XUD_DeviceAttach.xc @@ -19,7 +19,7 @@ #define INVALID_DELAY (INVALID_DELAY_us * PLATFORM_REFERENCE_MHZ) extern int resetCount; -extern XUD_resources_t * unsafe resource_ptr; +extern XUD_resources_t XUD_resources; /* Assumptions: * - In full speed mode @@ -34,8 +34,7 @@ int XUD_DeviceAttachHS(XUD_PwrConfig pwrConfig) int detecting_k = 1; int tx; unsigned int chirpCount = 0; - - unsafe{clearbuf(resource_ptr->p_usb_txd);} + clearbuf(XUD_resources.p_usb_txd); /* On detecting the SE0 move into chirp mode */ XUD_HAL_EnterMode_PeripheralChirp(); @@ -46,10 +45,8 @@ int XUD_DeviceAttachHS(XUD_PwrConfig pwrConfig) #else for (int i = 0; i < 16000; i++) // 16000 words @ 480 MBit = 1.066 ms #endif - unsafe{ - resource_ptr->p_usb_txd <: 0; - } - + XUD_resources.p_usb_txd <: 0; + // J, K, SE0 on flag ports 0, 1, 2 respectively (on XS2) // XS3 has raw linestate on flag port 0 and 1 // Wait for fs chirp k (i.e. HS chirp j) @@ -59,7 +56,7 @@ int XUD_DeviceAttachHS(XUD_PwrConfig pwrConfig) t :> start_time; while(1) - unsafe{ + { select { case t when timerafter(start_time + INVALID_DELAY) :> void: @@ -73,8 +70,8 @@ int XUD_DeviceAttachHS(XUD_PwrConfig pwrConfig) /* TODO Use a timer to save some juice...*/ #if !defined(__XS2A__) unsigned dp, dm; - resource_ptr->flag0_port :> dm; - resource_ptr->flag1_port :> dp; + XUD_resources.flag0_port :> dm; + XUD_resources.flag1_port :> dp; if(dp || dm) { @@ -82,7 +79,7 @@ int XUD_DeviceAttachHS(XUD_PwrConfig pwrConfig) return 0; } #else - resource_ptr->flag2_port :> tmp; + XUD_resources.flag2_port :> tmp; if(!tmp) { @@ -103,11 +100,11 @@ int XUD_DeviceAttachHS(XUD_PwrConfig pwrConfig) #if !defined(__XS2A__) // Note, J and K definitions are reversed in XS3A -#define j_port resource_ptr->flag1_port -#define k_port resource_ptr->flag0_port +#define j_port XUD_resources.flag1_port +#define k_port XUD_resources.flag0_port #else -#define k_port resource_ptr->flag1_port -#define j_port resource_ptr->flag0_port +#define k_port XUD_resources.flag1_port +#define j_port XUD_resources.flag0_port #endif case detecting_k => k_port when pinseq(1):> void @ tx: // K Chirp k_port @ tx + T_FILT_ticks :> tmp; diff --git a/lib_xud/src/core/XUD_HAL.xc b/lib_xud/src/core/XUD_HAL.xc index 2687e877..757a7e91 100644 --- a/lib_xud/src/core/XUD_HAL.xc +++ b/lib_xud/src/core/XUD_HAL.xc @@ -44,7 +44,7 @@ unsigned XtlSelFromMhz(unsigned m) } #endif -extern XUD_resources_t * unsafe resource_ptr; +extern XUD_resources_t XUD_resources; unsigned int XUD_EnableUsbPortMux(); @@ -84,12 +84,10 @@ void XUD_HAL_EnableUsb(unsigned pwrConfig) #endif /* Wait for USB clock (typically 1ms after reset) */ - unsafe{ - resource_ptr->p_usb_clk when pinseq(1) :> int _; - resource_ptr->p_usb_clk when pinseq(0) :> int _; - resource_ptr->p_usb_clk when pinseq(1) :> int _; - resource_ptr->p_usb_clk when pinseq(0) :> int _; - } + XUD_resources.p_usb_clk when pinseq(1) :> int _; + XUD_resources.p_usb_clk when pinseq(0) :> int _; + XUD_resources.p_usb_clk when pinseq(1) :> int _; + XUD_resources.p_usb_clk when pinseq(0) :> int _; #ifdef __XS2A__ /* Some extra settings are required for proper operation on XS2A */ @@ -287,11 +285,11 @@ void XUD_HAL_EnterMode_TristateDrivers() void XUD_HAL_Mode_Signalling() { /* Reset port to use XS1_CLKBLK_REF (from rx_usb_clk) */ - unsafe{set_port_use_on(resource_ptr->flag1_port);} + set_port_use_on(XUD_resources.flag1_port); #ifdef __XS2A__ /* For XS2 we invert VALID_TOKEN port for data-transfer mode, so undo this for signalling */ - set_port_no_inv(resource_ptr->flag2_port); + set_port_no_inv(XUD_resources.flag2_port); write_periph_word(USB_TILE_REF, XS1_GLX_PER_UIFM_CHANEND_NUM, XS1_GLX_PER_UIFM_MASK_NUM, ((1<flag1_port, resource_ptr->rx_usb_clk); - set_pad_delay(resource_ptr->flag1_port, 2); - } + configure_in_port(XUD_resources.flag1_port, XUD_resources.rx_usb_clk); + set_pad_delay(XUD_resources.flag1_port, 2); #ifdef __XS2A__ /* Set UIFM to CHECK TOKENS mode and enable LINESTATE_DECODE @@ -326,7 +322,7 @@ void XUD_HAL_Mode_DataTransfer() | ((1<flag0_port :> j; - resource_ptr->flag1_port :> k; - resource_ptr->flag2_port :> se0; - } + XUD_resources.flag0_port :> j; + XUD_resources.flag1_port :> k; + XUD_resources.flag2_port :> se0; if(j) return XUD_LINESTATE_HS_J_FS_K; @@ -370,10 +364,8 @@ XUD_LineState_t XUD_HAL_GetLineState(/*XUD_HAL_t &xudHal*/) return XUD_LINESTATE_SE1; #else unsigned dp, dm; - unsafe{ - resource_ptr->dp_port :> dp; - resource_ptr->dm_port :> dm; - } + XUD_resources.dp_port :> dp; + XUD_resources.dm_port :> dm; return LinesToLineState(dp, dm); #endif } @@ -393,18 +385,16 @@ unsigned XUD_HAL_WaitForLineStateChange(XUD_LineState_t ¤tLs, unsigned tim unsigned k = currentLs == XUD_LINESTATE_HS_K_FS_J; /* Wait for a change on any flag port */ - unsafe{ - select - { - case resource_ptr->flag0_port when pinsneq(j) :> void: - break; - case resource_ptr->flag1_port when pinsneq(k) :> void: - break; - case resource_ptr->flag2_port when pinsneq(se0) :> void: - break; - case timeout != null => t when timerafter(time + timeout) :> int _: - return 1; - } + select + { + case XUD_resources.flag0_port when pinsneq(j) :> void: + break; + case XUD_resources.flag1_port when pinsneq(k) :> void: + break; + case XUD_resources.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 */ @@ -417,18 +407,16 @@ unsigned XUD_HAL_WaitForLineStateChange(XUD_LineState_t ¤tLs, unsigned tim {dp, dm} = LineStateToLines(currentLs); /* Wait for change */ - unsafe{ - select - { - case resource_ptr->dp_port when pinsneq(dp) :> dp: - resource_ptr->dm_port :> dm; //Both might have changed! - break; - case resource_ptr->dm_port when pinsneq(dm) :> dm: - resource_ptr->dp_port :> dp; //Both might have changed! - break; - case timeout != null => t when timerafter(time + timeout) :> int _: - return 1; - } + select + { + case XUD_resources.dp_port when pinsneq(dp) :> dp: + XUD_resources.dm_port :> dm; //Both might have changed! + break; + case XUD_resources.dm_port when pinsneq(dm) :> dm: + XUD_resources.dp_port :> dp; //Both might have changed! + break; + case timeout != null => t when timerafter(time + timeout) :> int _: + return 1; } /* Return new linestate */ diff --git a/lib_xud/src/core/XUD_Main.xc b/lib_xud/src/core/XUD_Main.xc index 6db6007f..b5b1f090 100755 --- a/lib_xud/src/core/XUD_Main.xc +++ b/lib_xud/src/core/XUD_Main.xc @@ -64,56 +64,14 @@ on USB_TILE: clock rx_usb_clk = XS1_CLKBLK_5; #else -#if XUD_EXTERNAL_RESOURCES -/* These are globals to allow assembler functions to access resource IDs */ +/* These are globals to allow assembler functions to access resource IDs + using the DP relative addressing mode*/ int rx_rdy = 0; int flag1_port = 0; int p_usb_rxd = 0; int p_usb_txd = 0; extern XUD_resources_t XUD_resources; - -// XUD_resources_t XUD_resources = { -// PORT_USB_FLAG0, -// PORT_USB_FLAG1, -// #ifdef __XS2A__ -// PORT_USB_FLAG2 -// #else -// null, -// #endif -// PORT_USB_CLK, -// PORT_USB_TXD, -// PORT_USB_RXD, -// PORT_USB_TX_READYOUT, -// PORT_USB_TX_READYIN, -// PORT_USB_RX_READY, -// XS1_CLKBLK_4, -// XS1_CLKBLK_5 -// }; -/* - port flag1_port; - NULLABLE_RESOURCE(port, flag2_port); - in_buffered_port_32_t p_usb_clk; - out_buffered_port_32_t p_usb_txd; - in_buffered_port_32_t p_usb_rxd ; - port tx_readyout; - port tx_readyin; - port rx_rdy; - xcore_clock_t tx_usb_clk; - xcore_clock_t rx_usb_clk; - #define PORT_USB_CLK on USB_TILE: XS1_PORT_1J - #define PORT_USB_TXD on USB_TILE: XS1_PORT_8A - #define PORT_USB_RXD on USB_TILE: XS1_PORT_8B - #define PORT_USB_TX_READYOUT on USB_TILE: XS1_PORT_1K - #define PORT_USB_TX_READYIN on USB_TILE: XS1_PORT_1H - #define PORT_USB_RX_READY on USB_TILE: XS1_PORT_1I - #define PORT_USB_FLAG0 on USB_TILE: XS1_PORT_1E - #define PORT_USB_FLAG1 on USB_TILE: XS1_PORT_1F - #define PORT_USB_FLAG2 on USB_TILE: XS1_PORT_1G; -*/ -unsafe{ XUD_resources_t * unsafe resource_ptr = &XUD_resources;} -#endif - #endif // We use a single array instrad of two here and append epAddr_Ready_setup on the end to save some instructions in the Setup @@ -212,16 +170,16 @@ static int XUD_Manager_loop(XUD_chan epChans0[], XUD_chan epAddr_Ready[], chane int reset = 1; /* Flag for if device is returning from a reset */ /* Make sure ports are on and reset port states */ - unsafe{ - set_port_use_on(resource_ptr->p_usb_clk); - set_port_use_on(resource_ptr->p_usb_txd); - set_port_use_on(resource_ptr->p_usb_rxd); - set_port_use_on(resource_ptr->flag0_port); - set_port_use_on(resource_ptr->flag1_port); + set_port_use_on(XUD_resources.p_usb_clk); + set_port_use_on(XUD_resources.p_usb_txd); + set_port_use_on(XUD_resources.p_usb_rxd); + set_port_use_on(XUD_resources.flag0_port); + set_port_use_on(XUD_resources.flag1_port); + #if defined(__XS2A__) /* Extra flag port in XS2 */ - set_port_use_on(resource_ptr->flag2_port); + set_port_use_on(XUD_resources.flag2_port); #endif #if !defined(__XS2A__) @@ -267,37 +225,35 @@ static int XUD_Manager_loop(XUD_chan epChans0[], XUD_chan epAddr_Ready[], chane #endif // Handshaken ports need USB clock - configure_clock_src(resource_ptr->tx_usb_clk, resource_ptr->p_usb_clk); - configure_clock_src(resource_ptr->rx_usb_clk, resource_ptr->p_usb_clk); + configure_clock_src(XUD_resources.tx_usb_clk, XUD_resources.p_usb_clk); + configure_clock_src(XUD_resources.rx_usb_clk, XUD_resources.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 - set_port_inv(resource_ptr->p_usb_clk); - set_port_sample_delay(resource_ptr->p_usb_clk); + set_port_inv(XUD_resources.p_usb_clk); + set_port_sample_delay(XUD_resources.p_usb_clk); // This delay controls the capture of rdy - set_clock_rise_delay(resource_ptr->tx_usb_clk, TX_RISE_DELAY); + set_clock_rise_delay(XUD_resources.tx_usb_clk, TX_RISE_DELAY); // This delay controls the launch of data. - set_clock_fall_delay(resource_ptr->tx_usb_clk, TX_FALL_DELAY); + set_clock_fall_delay(XUD_resources.tx_usb_clk, TX_FALL_DELAY); // This delay the capture of the rdyIn and data. - set_clock_rise_delay(resource_ptr->rx_usb_clk, RX_RISE_DELAY); - set_clock_fall_delay(resource_ptr->rx_usb_clk, RX_FALL_DELAY); + set_clock_rise_delay(XUD_resources.rx_usb_clk, RX_RISE_DELAY); + set_clock_fall_delay(XUD_resources.rx_usb_clk, RX_FALL_DELAY); - set_pad_delay(resource_ptr->flag1_port, 2); + set_pad_delay(XUD_resources.flag1_port, 2); - start_clock(resource_ptr->tx_usb_clk); - start_clock(resource_ptr->rx_usb_clk); + start_clock(XUD_resources.tx_usb_clk); + start_clock(XUD_resources.rx_usb_clk); - configure_out_port_handshake(resource_ptr->p_usb_txd, resource_ptr->tx_readyin, resource_ptr->tx_readyout, resource_ptr->tx_usb_clk, 0); - configure_in_port_strobed_slave(resource_ptr->p_usb_rxd, resource_ptr->rx_rdy, resource_ptr->rx_usb_clk); + configure_out_port_handshake(XUD_resources.p_usb_txd, XUD_resources.tx_readyin, XUD_resources.tx_readyout, XUD_resources.tx_usb_clk, 0); + configure_in_port_strobed_slave(XUD_resources.p_usb_rxd, XUD_resources.rx_rdy, XUD_resources.rx_usb_clk); /* Clock RxA port from USB clock - helps fall event */ - configure_in_port(resource_ptr->flag1_port, resource_ptr->rx_usb_clk); - - } // unsafe + configure_in_port(XUD_resources.flag1_port, XUD_resources.rx_usb_clk); unsigned noExit = 1; @@ -463,11 +419,11 @@ static int XUD_Manager_loop(XUD_chan epChans0[], XUD_chan epAddr_Ready[], chane flag1: Rx Active flag2: Null / Valid Token */ unsafe{ - noExit = XUD_LLD_IoLoop(resource_ptr->p_usb_rxd, - resource_ptr->flag1_port, - resource_ptr->p_usb_txd, - resource_ptr->flag0_port, - resource_ptr->flag2_port, + noExit = XUD_LLD_IoLoop(XUD_resources.p_usb_rxd, + XUD_resources.flag1_port, + XUD_resources.p_usb_txd, + XUD_resources.flag0_port, + XUD_resources.flag2_port, epTypeTableOut, epTypeTableIn, epAddr_Ready, @@ -487,14 +443,14 @@ static int XUD_Manager_loop(XUD_chan epChans0[], XUD_chan epAddr_Ready[], chane unsafe{ /* Turn ports off */ - set_port_use_off(resource_ptr->p_usb_txd); - set_port_use_off(resource_ptr->p_usb_rxd); - set_port_use_off(resource_ptr->flag0_port); - set_port_use_off(resource_ptr->flag1_port); + set_port_use_off(XUD_resources.p_usb_txd); + set_port_use_off(XUD_resources.p_usb_rxd); + set_port_use_off(XUD_resources.flag0_port); + set_port_use_off(XUD_resources.flag1_port); #ifdef __XS2A__ - set_port_use_off(resource_ptr->flag2_port); + set_port_use_off(XUD_resources.flag2_port); #endif - set_port_use_off(resource_ptr->p_usb_clk); + set_port_use_off(XUD_resources.p_usb_clk); } // unsafe return 0; } @@ -646,13 +602,16 @@ int XUD_Main(chanend c_ep_out[], int noEpOut, printstr("XUD\n"); #if XUD_EXTERNAL_RESOURCES + for(int i = 0; i < sizeof(XUD_resources_t) / 4; i++){ + int resid = 0; + // assert() + } /* Ensure global resids accessed by ASM are initt'd */ - assert(resource_ptr); unsafe{ - rx_rdy = (int)resource_ptr->rx_rdy; - flag1_port = (int)resource_ptr->flag1_port; - p_usb_rxd = (int)resource_ptr->p_usb_rxd; - p_usb_txd = (int)resource_ptr->p_usb_txd; + rx_rdy = (int)XUD_resources.rx_rdy; + flag1_port = (int)XUD_resources.flag1_port; + p_usb_rxd = (int)XUD_resources.p_usb_rxd; + p_usb_txd = (int)XUD_resources.p_usb_txd; } #endif diff --git a/lib_xud/src/core/XUD_TestMode.xc b/lib_xud/src/core/XUD_TestMode.xc index 0303908b..b658b399 100644 --- a/lib_xud/src/core/XUD_TestMode.xc +++ b/lib_xud/src/core/XUD_TestMode.xc @@ -5,7 +5,7 @@ #include "xud.h" #include "XUD_TestMode.h" -extern XUD_resources_t * unsafe resource_ptr; +extern XUD_resources_t XUD_resources; #define T_INTER_TEST_PACKET_us 2 #define T_INTER_TEST_PACKET (T_INTER_TEST_PACKET_us * PLATFORM_REFERENCE_MHZ) @@ -39,8 +39,8 @@ int XUD_UsbTestModeHandler(unsigned cmd) XUD_HAL_EnterMode_PeripheralTestJTestK(); while(1) - unsafe{ - resource_ptr->p_usb_txd <: 0xffffffff; + { + XUD_resources.p_usb_txd <: 0xffffffff; } break; @@ -49,8 +49,8 @@ int XUD_UsbTestModeHandler(unsigned cmd) XUD_HAL_EnterMode_PeripheralTestJTestK(); while(1) - unsafe{ - resource_ptr->p_usb_txd <: 0; + { + XUD_resources.p_usb_txd <: 0; } break; @@ -74,13 +74,13 @@ int XUD_UsbTestModeHandler(unsigned cmd) #pragma unsafe arrays while (1) - unsafe{ + { #pragma loop unroll for (i=0; i < sizeof(test_packet)/sizeof(test_packet[0]); i++) { - resource_ptr->p_usb_txd <: test_packet[i]; + XUD_resources.p_usb_txd <: test_packet[i]; }; - sync(resource_ptr->p_usb_txd); + sync(XUD_resources.p_usb_txd); test_packet_timer :> i; test_packet_timer when timerafter (i + T_INTER_TEST_PACKET) :> int _; } diff --git a/lib_xud/src/core/XUD_resources.c b/lib_xud/src/core/XUD_resources.c index 2e4b4cb0..e8d66f3a 100644 --- a/lib_xud/src/core/XUD_resources.c +++ b/lib_xud/src/core/XUD_resources.c @@ -1,3 +1,4 @@ +#include #include "xud.h" /* This is the global declaration of the resources struct used to keep @@ -7,5 +8,14 @@ before the call to XUD_Main */ #if XUD_EXTERNAL_RESOURCES -XUD_resources_t XUD_resources; +XUD_resources_t XUD_resources = {0}; #endif + + +extern XUD_resources_t XUD_resources; + +void init_xud_resources(XUD_resources_t * resources) +{ + printf("d: %p s: %p\n", &XUD_resources, resources); + memcpy(&XUD_resources, resources, sizeof(XUD_resources_t)); +} \ No newline at end of file From 540c4164dcc9d707a24e1eba6099afd176202f04 Mon Sep 17 00:00:00 2001 From: Ed Date: Mon, 11 Dec 2023 09:24:10 +0000 Subject: [PATCH 3/6] Fix single tile and XS2 --- lib_xud/src/core/XUD_DeviceAttach.xc | 4 +-- lib_xud/src/core/XUD_HAL.xc | 18 +++++----- lib_xud/src/core/XUD_Main.xc | 51 +++++++++++++++------------- 3 files changed, 39 insertions(+), 34 deletions(-) diff --git a/lib_xud/src/core/XUD_DeviceAttach.xc b/lib_xud/src/core/XUD_DeviceAttach.xc index f5bb829c..29822b37 100755 --- a/lib_xud/src/core/XUD_DeviceAttach.xc +++ b/lib_xud/src/core/XUD_DeviceAttach.xc @@ -51,7 +51,7 @@ int XUD_DeviceAttachHS(XUD_PwrConfig pwrConfig) // XS3 has raw linestate on flag port 0 and 1 // Wait for fs chirp k (i.e. HS chirp j) #if defined(__XS2A__) - flag1_port when pinseq(0) :> tmp; // Wait for out k to go + XUD_resources.flag1_port when pinseq(0) :> tmp; // Wait for out k to go #endif t :> start_time; @@ -131,7 +131,7 @@ int XUD_DeviceAttachHS(XUD_PwrConfig pwrConfig) // TODO ideally dont use a polling loop here while (XUD_HAL_GetLineState() != XUD_LINESTATE_SE0); #else - flag2_port when pinseq(1) :> tmp; + XUD_resources.flag2_port when pinseq(1) :> tmp; #endif /* Return 1 to indicate successful HS handshake*/ diff --git a/lib_xud/src/core/XUD_HAL.xc b/lib_xud/src/core/XUD_HAL.xc index 757a7e91..f70b4da4 100644 --- a/lib_xud/src/core/XUD_HAL.xc +++ b/lib_xud/src/core/XUD_HAL.xc @@ -322,7 +322,7 @@ void XUD_HAL_Mode_DataTransfer() | ((1< dp; - XUD_resources.dm_port :> dm; + dp_port :> dp; + dm_port :> dm; return LinesToLineState(dp, dm); #endif } @@ -409,11 +409,11 @@ unsigned XUD_HAL_WaitForLineStateChange(XUD_LineState_t ¤tLs, unsigned tim /* Wait for change */ select { - case XUD_resources.dp_port when pinsneq(dp) :> dp: - XUD_resources.dm_port :> dm; //Both might have changed! + case dp_port when pinsneq(dp) :> dp: + dm_port :> dm; //Both might have changed! break; - case XUD_resources.dm_port when pinsneq(dm) :> dm: - XUD_resources.dp_port :> dp; //Both might have changed! + case dm_port when pinsneq(dm) :> dm: + dp_port :> dp; //Both might have changed! break; case timeout != null => t when timerafter(time + timeout) :> int _: return 1; diff --git a/lib_xud/src/core/XUD_Main.xc b/lib_xud/src/core/XUD_Main.xc index b5b1f090..b05e4ae5 100755 --- a/lib_xud/src/core/XUD_Main.xc +++ b/lib_xud/src/core/XUD_Main.xc @@ -42,38 +42,41 @@ unsigned g_txHandshakeTimeout; #if !XUD_EXTERNAL_RESOURCES -in port flag0_port = PORT_USB_FLAG0; /* For XS3: Mission: RXE, XS2 is configurable and set to RXE in mission mode */ -in port flag1_port = PORT_USB_FLAG1; /* For XS3: Mission: RXA, XS2 is configuratble and set to RXA in mission mode*/ - /* XS2A has an additonal flag port. In Mission mode this is set to VALID_TOKEN */ #ifdef __XS2A__ -in port flag2_port = PORT_USB_FLAG2; +#define FLAG2_PORT PORT_USB_FLAG2 #else -#define flag2_port null +#define FLAG2_PORT null #endif -in buffered port:32 p_usb_clk = PORT_USB_CLK; -out buffered port:32 p_usb_txd = PORT_USB_TXD; -in buffered port:32 p_usb_rxd = PORT_USB_RXD; -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_4; -on USB_TILE: clock rx_usb_clk = XS1_CLKBLK_5; +XUD_resources_t XUD_resources = { + PORT_USB_FLAG0, /* For XS3: Mission: RXE, XS2 is configurable and set to RXE in mission mode */ + PORT_USB_FLAG1, /* For XS3: Mission: RXA, XS2 is configuratble and set to RXA in mission mode*/ + FLAG2_PORT, + PORT_USB_CLK, + PORT_USB_TXD, + PORT_USB_RXD, + PORT_USB_TX_READYOUT, + PORT_USB_TX_READYIN, + PORT_USB_RX_READY, + on USB_TILE: XS1_CLKBLK_4, + on USB_TILE: XS1_CLKBLK_5 +}; #else +extern XUD_resources_t XUD_resources; + +#endif + /* These are globals to allow assembler functions to access resource IDs using the DP relative addressing mode*/ int rx_rdy = 0; int flag1_port = 0; +int flag2_port = 0; int p_usb_rxd = 0; int p_usb_txd = 0; -extern XUD_resources_t XUD_resources; -#endif - // We use a single array instrad of two here and append epAddr_Ready_setup on the end to save some instructions in the Setup // token handling code. i.e. what we really want is the following, but's less efficient. // unsigned epAddr_Ready[USB_MAN_NUM_EP] @@ -600,19 +603,21 @@ int XUD_Main(chanend c_ep_out[], int noEpOut, { g_desSpeed = speed; - printstr("XUD\n"); -#if XUD_EXTERNAL_RESOURCES - for(int i = 0; i < sizeof(XUD_resources_t) / 4; i++){ - int resid = 0; - // assert() - } /* Ensure global resids accessed by ASM are initt'd */ unsafe{ rx_rdy = (int)XUD_resources.rx_rdy; flag1_port = (int)XUD_resources.flag1_port; + flag2_port = (int)XUD_resources.flag2_port; p_usb_rxd = (int)XUD_resources.p_usb_rxd; p_usb_txd = (int)XUD_resources.p_usb_txd; } + + printstr("XUD\n"); +#if XUD_EXTERNAL_RESOURCES + for(int i = 0; i < sizeof(XUD_resources_t) / 4; i++){ + int resid = 0; + // assert() + } #endif SetupEndpoints(c_ep_out, noEpOut, c_ep_in, noEpIn, epTypeTableOut, epTypeTableIn); From 5e38bc4aef8ed6fa06bc7dd33a9120454933d4c5 Mon Sep 17 00:00:00 2001 From: Ed Date: Mon, 11 Dec 2023 09:44:58 +0000 Subject: [PATCH 4/6] Remove debug and improve comments --- lib_xud/api/xud.h | 7 ++++--- lib_xud/src/core/XUD_resources.c | 1 - 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib_xud/api/xud.h b/lib_xud/api/xud.h index 998fda1f..45daaa80 100644 --- a/lib_xud/api/xud.h +++ b/lib_xud/api/xud.h @@ -538,9 +538,10 @@ typedef struct XUD_ep_info /** * \brief Resource initialisation for cases where we have multiple instances of XUD in a project. - * This MUST be called prior to running XUD_Main otherwise XUD will assert 0 - * \param resources A struct of type XUD_resources_t declared in XC containing the XUD - * resources which must be placed on a specific tile. + * This is only relevant when the XUD_EXTERNAL_RESOURCES define is set to non-zero. + * This MUST be called prior to running XUD_Main otherwise XUD will assert 0. + * \param resources A struct of type XUD_resources_t declared in XC by the user application + * containing the XUD resources (see XUD_resources_t). These must be placed on a specific tile. */ void init_xud_resources(REFERENCE_PARAM(XUD_resources_t, resources)); diff --git a/lib_xud/src/core/XUD_resources.c b/lib_xud/src/core/XUD_resources.c index e8d66f3a..f9414265 100644 --- a/lib_xud/src/core/XUD_resources.c +++ b/lib_xud/src/core/XUD_resources.c @@ -16,6 +16,5 @@ extern XUD_resources_t XUD_resources; void init_xud_resources(XUD_resources_t * resources) { - printf("d: %p s: %p\n", &XUD_resources, resources); memcpy(&XUD_resources, resources, sizeof(XUD_resources_t)); } \ No newline at end of file From 8ea94c8b49a95e12d3387f72b99c11f6d9727d92 Mon Sep 17 00:00:00 2001 From: Ed Date: Mon, 11 Dec 2023 09:46:22 +0000 Subject: [PATCH 5/6] Remove check since the compiler will find the issue --- lib_xud/src/core/XUD_Main.xc | 8 -------- 1 file changed, 8 deletions(-) diff --git a/lib_xud/src/core/XUD_Main.xc b/lib_xud/src/core/XUD_Main.xc index b05e4ae5..aaa9e2ec 100755 --- a/lib_xud/src/core/XUD_Main.xc +++ b/lib_xud/src/core/XUD_Main.xc @@ -612,14 +612,6 @@ int XUD_Main(chanend c_ep_out[], int noEpOut, p_usb_txd = (int)XUD_resources.p_usb_txd; } - printstr("XUD\n"); -#if XUD_EXTERNAL_RESOURCES - for(int i = 0; i < sizeof(XUD_resources_t) / 4; i++){ - int resid = 0; - // assert() - } -#endif - SetupEndpoints(c_ep_out, noEpOut, c_ep_in, noEpIn, epTypeTableOut, epTypeTableIn); #if 0 From da2debc44dd0f251c279d8f9d3f50100f3eb3e21 Mon Sep 17 00:00:00 2001 From: Ed Date: Mon, 11 Dec 2023 10:16:22 +0000 Subject: [PATCH 6/6] Rename dual explorer XN and change to 600MHz --- ...RER-2V0-JG-800-4TILE.xn => XCORE-AI-EXPLORER-2V0-4TILE.xn} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename examples/dual_AN00127_video_class/{XCORE-AI-EXPLORER-2V0-JG-800-4TILE.xn => XCORE-AI-EXPLORER-2V0-4TILE.xn} (95%) diff --git a/examples/dual_AN00127_video_class/XCORE-AI-EXPLORER-2V0-JG-800-4TILE.xn b/examples/dual_AN00127_video_class/XCORE-AI-EXPLORER-2V0-4TILE.xn similarity index 95% rename from examples/dual_AN00127_video_class/XCORE-AI-EXPLORER-2V0-JG-800-4TILE.xn rename to examples/dual_AN00127_video_class/XCORE-AI-EXPLORER-2V0-4TILE.xn index 8f031f29..f2f66d2f 100644 --- a/examples/dual_AN00127_video_class/XCORE-AI-EXPLORER-2V0-JG-800-4TILE.xn +++ b/examples/dual_AN00127_video_class/XCORE-AI-EXPLORER-2V0-4TILE.xn @@ -13,7 +13,7 @@ - + @@ -31,7 +31,7 @@ - +