From 1cae96951f59e7549ff1a2d5643cda66784c22a1 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Sat, 14 Sep 2019 12:13:11 -0400 Subject: [PATCH 01/45] Add usbtmc class driver. --- examples/device/usbtmc/Makefile | 12 + examples/device/usbtmc/src/main.c | 113 +++++ examples/device/usbtmc/src/tusb_config.h | 66 +++ examples/device/usbtmc/src/usb_descriptors.c | 254 +++++++++++ examples/device/usbtmc/src/usbtmc_app.c | 133 ++++++ examples/rules.mk | 1 + src/class/usbtmc/usbtmc.h | 267 ++++++++++++ src/class/usbtmc/usbtmc_device.c | 420 +++++++++++++++++++ src/class/usbtmc/usbtmc_device.h | 130 ++++++ src/device/usbd.c | 16 + src/tusb.h | 4 + src/tusb_option.h | 4 + 12 files changed, 1420 insertions(+) create mode 100644 examples/device/usbtmc/Makefile create mode 100644 examples/device/usbtmc/src/main.c create mode 100644 examples/device/usbtmc/src/tusb_config.h create mode 100644 examples/device/usbtmc/src/usb_descriptors.c create mode 100644 examples/device/usbtmc/src/usbtmc_app.c create mode 100644 src/class/usbtmc/usbtmc.h create mode 100644 src/class/usbtmc/usbtmc_device.c create mode 100644 src/class/usbtmc/usbtmc_device.h diff --git a/examples/device/usbtmc/Makefile b/examples/device/usbtmc/Makefile new file mode 100644 index 000000000..69b633fea --- /dev/null +++ b/examples/device/usbtmc/Makefile @@ -0,0 +1,12 @@ +include ../../../tools/top.mk +include ../../make.mk + +INC += \ + src \ + $(TOP)/hw \ + +# Example source +EXAMPLE_SOURCE += $(wildcard src/*.c) +SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) + +include ../../rules.mk diff --git a/examples/device/usbtmc/src/main.c b/examples/device/usbtmc/src/main.c new file mode 100644 index 000000000..0293261ad --- /dev/null +++ b/examples/device/usbtmc/src/main.c @@ -0,0 +1,113 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#include +#include +#include + +#include "bsp/board.h" +#include "tusb.h" + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF PROTYPES +//--------------------------------------------------------------------+ + +/* Blink pattern + * - 250 ms : device not mounted + * - 1000 ms : device mounted + * - 2500 ms : device is suspended + */ +enum { + BLINK_NOT_MOUNTED = 250, + BLINK_MOUNTED = 1000, + BLINK_SUSPENDED = 2500, +}; + +static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED; + +void led_blinking_task(void); + +/*------------- MAIN -------------*/ +int main(void) +{ + board_init(); + + tusb_init(); + + while (1) + { + tud_task(); // tinyusb device task + led_blinking_task(); + } + + return 0; +} + +//--------------------------------------------------------------------+ +// Device callbacks +//--------------------------------------------------------------------+ + +// Invoked when device is mounted +void tud_mount_cb(void) +{ + blink_interval_ms = BLINK_MOUNTED; +} + +// Invoked when device is unmounted +void tud_umount_cb(void) +{ + blink_interval_ms = BLINK_NOT_MOUNTED; +} + +// Invoked when usb bus is suspended +// remote_wakeup_en : if host allow us to perform remote wakeup +// Within 7ms, device must draw an average of current less than 2.5 mA from bus +void tud_suspend_cb(bool remote_wakeup_en) +{ + (void) remote_wakeup_en; + blink_interval_ms = BLINK_SUSPENDED; +} + +// Invoked when usb bus is resumed +void tud_resume_cb(void) +{ + blink_interval_ms = BLINK_MOUNTED; +} + +//--------------------------------------------------------------------+ +// BLINKING TASK +//--------------------------------------------------------------------+ +void led_blinking_task(void) +{ + static uint32_t start_ms = 0; + static bool led_state = false; + + // Blink every interval ms + if ( board_millis() - start_ms < blink_interval_ms) return; // not enough time + start_ms += blink_interval_ms; + + board_led_write(led_state); + led_state = 1 - led_state; // toggle +} diff --git a/examples/device/usbtmc/src/tusb_config.h b/examples/device/usbtmc/src/tusb_config.h new file mode 100644 index 000000000..022dc7691 --- /dev/null +++ b/examples/device/usbtmc/src/tusb_config.h @@ -0,0 +1,66 @@ +/* + * tusb_config.h + * + * Created on: Sep 5, 2019 + * Author: nconrad + */ + +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +//-------------------------------------------------------------------- +// COMMON CONFIGURATION +//-------------------------------------------------------------------- + +// defined by compiler flags for flexibility +#ifndef CFG_TUSB_MCU + #error CFG_TUSB_MCU must be defined +#endif + +#if CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_LPC18XX +#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | OPT_MODE_HIGH_SPEED) +#else +#define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE +#endif + +#define CFG_TUSB_OS OPT_OS_NONE + +// CFG_TUSB_DEBUG is defined by compiler in DEBUG build +// #define CFG_TUSB_DEBUG 0 + +/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment. + * Tinyusb use follows macros to declare transferring memory so that they can be put + * into those specific section. + * e.g + * - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") )) + * - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4))) + */ +#ifndef CFG_TUSB_MEM_SECTION +#define CFG_TUSB_MEM_SECTION +#endif + +#ifndef CFG_TUSB_MEM_ALIGN +#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4))) +#endif + +//-------------------------------------------------------------------- +// DEVICE CONFIGURATION +//-------------------------------------------------------------------- + +#define CFG_TUD_ENDOINT0_SIZE 64 + +//------------- CLASS -------------// + +#define CFG_TUD_USBTMC 1 +#define CFG_TUD_USBTMC_ENABLE_INT_EP +//#define USBTMC_CFG_ENABLE_488 0 + +#ifdef __cplusplus + } +#endif + +#endif /* TUSB_CONFIG_H_ */ diff --git a/examples/device/usbtmc/src/usb_descriptors.c b/examples/device/usbtmc/src/usb_descriptors.c new file mode 100644 index 000000000..296636359 --- /dev/null +++ b/examples/device/usbtmc/src/usb_descriptors.c @@ -0,0 +1,254 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#include "tusb.h" +#include "class/usbtmc/usbtmc.h" +#include "class/usbtmc/usbtmc_device.h" + +/* A combination of interfaces must have a unique product id, since PC will save device driver after the first plug. + * Same VID/PID with different interface e.g MSC (first), then CDC (later) will possibly cause system error on PC. + * + * Auto ProductID layout's Bitmap: + * [MSB] HID | MSC | CDC [LSB] + */ +#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) ) +#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ + _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) ) + +//--------------------------------------------------------------------+ +// Device Descriptors +//--------------------------------------------------------------------+ +tusb_desc_device_t const desc_device = +{ + .bLength = sizeof(tusb_desc_device_t), + .bDescriptorType = TUSB_DESC_DEVICE, + .bcdUSB = 0x0200, + + #if CFG_TUD_CDC + // Use Interface Association Descriptor (IAD) for CDC + // As required by USB Specs IAD's subclass must be common class (2) and protocol must be IAD (1) + .bDeviceClass = TUSB_CLASS_MISC, + .bDeviceSubClass = MISC_SUBCLASS_COMMON, + .bDeviceProtocol = MISC_PROTOCOL_IAD, + #else + .bDeviceClass = 0x00, + .bDeviceSubClass = 0x00, + .bDeviceProtocol = 0x00, + #endif + + .bMaxPacketSize0 = CFG_TUD_ENDOINT0_SIZE, + + .idVendor = 0xCafe, + .idProduct = USB_PID, + .bcdDevice = 0x0100, + + .iManufacturer = 0x01, + .iProduct = 0x02, + .iSerialNumber = 0x03, + + .bNumConfigurations = 0x01 +}; + +// Invoked when received GET DEVICE DESCRIPTOR +// Application return pointer to descriptor +uint8_t const * tud_descriptor_device_cb(void) +{ + return (uint8_t const *) &desc_device; +} + +//--------------------------------------------------------------------+ +// HID Report Descriptor +//--------------------------------------------------------------------+ +#if CFG_TUD_HID + +uint8_t const desc_hid_report[] = +{ + TUD_HID_REPORT_DESC_KEYBOARD( HID_REPORT_ID(REPORT_ID_KEYBOARD), ), + TUD_HID_REPORT_DESC_MOUSE ( HID_REPORT_ID(REPORT_ID_MOUSE), ) +}; + +// Invoked when received GET HID REPORT DESCRIPTOR +// Application return pointer to descriptor +// Descriptor contents must exist long enough for transfer to complete +uint8_t const * tud_hid_descriptor_report_cb(void) +{ + return desc_hid_report; +} + +#endif + +//--------------------------------------------------------------------+ +// Configuration Descriptor +//--------------------------------------------------------------------+ + +#if defined(CFG_TUD_USBTMC) + +# define USBTMC_DESC_MAIN(_itfnum,_bNumEndpoints) \ + USBTMC_IF_DESCRIPTOR(_itfnum, _bNumEndpoints, /*_stridx = */ 7u, USBTMC_PROTOCOL_USB488), \ + USBTMC_BULK_DESCRIPTORS(/* OUT = */0x03, /* IN = */ 0x83) + +#if defined(CFG_TUD_USBTMC_ENABLE_INT_EP) + +# define USBTMC_DESC(_itfnum) \ + USBTMC_DESC_MAIN(_itfnum, /* _epCount = */ 3), \ + USBTMC_INT_DESCRIPTOR(/* INT ep # */ 0x84, /* epMaxSize = */ 64, /* bInterval = */16u ) +# define USBTMC_DESC_LEN (USBTMC_IF_DESCRIPTOR_LEN + USBTMC_BULK_DESCRIPTORS_LEN + USBTMC_INT_DESCRIPTOR_LEN) + +#else + +# define USBTMC_DESC(_itfnum) \ + USBTMC_DESC_MAIN(_itfnum, /* _epCount = */ 2u) +# define USBTMC_DESC_LEN (USBTMC_IF_DESCRIPTOR_LEN + USBTMC_BULK_DESCRIPTORS_LEN) + +#endif /* CFG_TUD_USBTMC_ENABLE_INT_EP */ + +#else +# define USBTMC_DESC_LEN (0) +#endif /* CFG_TUD_USBTMC */ + +enum +{ +#if CFG_TUD_CDC + ITF_NUM_CDC = 0, + ITF_NUM_CDC_DATA, +#endif + +#if CFG_TUD_MSC + ITF_NUM_MSC, +#endif + +#if CFG_TUD_HID + ITF_NUM_HID, +#endif +#if CFG_TUD_USBTMC + ITF_NUM_USBTMC, +#endif + ITF_NUM_TOTAL +}; + + +#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + CFG_TUD_CDC*TUD_CDC_DESC_LEN + CFG_TUD_MSC*TUD_MSC_DESC_LEN + \ + CFG_TUD_HID*TUD_HID_DESC_LEN + (CFG_TUD_USBTMC)*USBTMC_DESC_LEN) + +#if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX + // LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number + // 0 control, 1 In, 2 Bulk, 3 Iso, 4 In etc ... + // Note: since CDC EP ( 1 & 2), HID (4) are spot-on, thus we only need to force + // endpoint number for MSC to 5 + #define EPNUM_MSC 0x05 +#else + #define EPNUM_MSC 0x03 +#endif + + +uint8_t const desc_configuration[] = +{ + // Interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), + +#if CFG_TUD_CDC + // Interface number, string index, EP notification address and size, EP data address (out, in) and size. + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 1, 0x81, 8, 0x02, 0x82, 64), +#endif + +#if CFG_TUD_USBTMC + USBTMC_DESC(ITF_NUM_USBTMC), +#endif + +#if CFG_TUD_MSC + // Interface number, string index, EP Out & EP In address, EP size + TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 5, EPNUM_MSC, 0x80 | EPNUM_MSC, (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 512 : 64), +#endif + +#if CFG_TUD_HID + // Interface number, string index, protocol, report descriptor len, EP In address, size & polling interval + TUD_HID_DESCRIPTOR(ITF_NUM_HID, 6, HID_PROTOCOL_NONE, sizeof(desc_hid_report), 0x84, 16, 10) +#endif +}; + + +// Invoked when received GET CONFIGURATION DESCRIPTOR +// Application return pointer to descriptor +// Descriptor contents must exist long enough for transfer to complete +uint8_t const * tud_descriptor_configuration_cb(uint8_t index) +{ + (void) index; // for multiple configurations + return desc_configuration; +} + +//--------------------------------------------------------------------+ +// String Descriptors +//--------------------------------------------------------------------+ + +// array of pointer to string descriptors +char const* string_desc_arr [] = +{ + (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409) + "TinyUSB", // 1: Manufacturer + "TinyUSB Device", // 2: Product + "123456", // 3: Serials, should use chip ID + "TinyUSB CDC", // 4: CDC Interface + "TinyUSB MSC", // 5: MSC Interface + "TinyUSB HID", // 6: HID + "TinyUSB USBTMC", // 7: USBTMC +}; + +static uint16_t _desc_str[32]; + +// Invoked when received GET STRING DESCRIPTOR request +// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete +uint16_t const* tud_descriptor_string_cb(uint8_t index) +{ + uint8_t chr_count; + + if ( index == 0) + { + memcpy(&_desc_str[1], string_desc_arr[0], 2); + chr_count = 1; + }else + { + // Convert ASCII string into UTF-16 + + if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) ) return NULL; + + const char* str = string_desc_arr[index]; + + // Cap at max char + chr_count = strlen(str); + if ( chr_count > 31 ) { + chr_count = 31; + } + + for(uint8_t i=0; i +#include "class/usbtmc/usbtmc_device.h" + +#if (USBTMC_CFG_ENABLE_488) +usbtmc_response_capabilities_488_t const +#else +usbtmc_response_capabilities_t const +#endif +usbtmcd_app_capabilities = +{ + .USBTMC_status = USBTMC_STATUS_SUCCESS, + .bcdUSBTMC = USBTMC_VERSION, + .bmIntfcCapabilities = + { + .listenOnly = 0, + .talkOnly = 0, + .supportsIndicatorPulse = 0 + }, + .bmDevCapabilities = { + .canEndBulkInOnTermChar = 0 + }, + +#if (USBTMC_CFG_ENABLE_488) + .bcdUSB488 = USBTMC_488_VERSION, + .bmIntfcCapabilities488 = + { + .supportsTrigger = 0, + .supportsREN_GTL_LLO = 0, + .is488_2 = 1 + }, + .bmDevCapabilities488 = + { + .SCPI = 1, + .SR1 = 0, + .RL1 = 0, + .DT1 =0, + } +#endif +}; + +static const char idn[] = "TinyUSB,ModelNumber,SerialNumber,FirmwareVer"; +static uint8_t status; +static bool queryReceived = false; + + +bool usbtmcd_app_msgBulkOut_start(usbtmc_msg_request_dev_dep_out const * msgHeader) +{ + (void)msgHeader; + return true; +} + + +bool usbtmcd_app_msg_data(void *data, size_t len, bool transfer_complete) +{ + (void)transfer_complete; + if(transfer_complete && (len >=4) && !strncasecmp("*idn?",data,4)) { + queryReceived = true; + } + return true; +} + +bool usbtmcd_app_msgBulkIn_complete(uint8_t rhport) +{ + (void)rhport; + return true; +} + +static uint8_t noQueryMsg[] = "ERR: No query"; +bool usbtmcd_app_msgBulkIn_request(uint8_t rhport, usbtmc_msg_request_dev_dep_in const * request) +{ + usbtmc_msg_dev_dep_msg_in_header_t hdr = { + .header = + { + .MsgID = request->header.MsgID, + .bTag = request->header.bTag, + .bTagInverse = request->header.bTagInverse + }, + .TransferSize = sizeof(idn)-1, + .bmTransferAttributes = + { + .EOM = 1, + .UsingTermChar = 0 + } + }; + if(queryReceived) + { + usbtmcd_transmit_dev_msg_data(rhport, &hdr, idn); + } + else + { + hdr.TransferSize = sizeof(noQueryMsg)-1; + usbtmcd_transmit_dev_msg_data(rhport, &hdr, noQueryMsg); + } + queryReceived = false; + return true; +} + +// Return status byte, but put the transfer result status code in the rspResult argument. +uint8_t usbtmcd_app_get_stb(uint8_t rhport, uint8_t *rspResult) +{ + (void)rhport; + *rspResult = USBTMC_STATUS_SUCCESS; + // Increment status so that we see different results on each read... + status++; + + return status; +} + diff --git a/examples/rules.mk b/examples/rules.mk index 478a5907a..c3daf9dac 100644 --- a/examples/rules.mk +++ b/examples/rules.mk @@ -15,6 +15,7 @@ SRC_C += \ src/class/cdc/cdc_device.c \ src/class/hid/hid_device.c \ src/class/midi/midi_device.c \ + src/class/usbtmc/usbtmc_device.c \ src/class/vendor/vendor_device.c \ src/portable/$(VENDOR)/$(CHIP_FAMILY)/dcd_$(CHIP_FAMILY).c diff --git a/src/class/usbtmc/usbtmc.h b/src/class/usbtmc/usbtmc.h new file mode 100644 index 000000000..846c0e38d --- /dev/null +++ b/src/class/usbtmc/usbtmc.h @@ -0,0 +1,267 @@ + +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 N Conrad + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef _TUSB_USBTMC_H__ +#define _TUSB_USBTMC_H__ + +#include "common/tusb_common.h" + + +/* Implements USBTMC Revision 1.0, April 14, 2003 + + String descriptors must have a "LANGID=0x409"/US English string. + Characters must be 0x20 (' ') to 0x7E ('~') ASCII, + But MUST not contain: "/:?\* + Also must not have leading or trailing space (' ') + Device descriptor must state USB version 0x0200 or greater + + If USB488DeviceCapabilites.D2 = 1 (SR1), then there must be a INT endpoint. +*/ + +#define USBTMC_VERSION 0x0100 +#define USBTMC_488_VERSION 0x0100 + +typedef enum { + USBTMC_MSGID_DEV_DEP_MSG_OUT = 1u, + USBTMC_MSGID_DEV_DEP_MSG_IN = 2u, + USBTMC_MSGID_VENDOR_SPECIFIC_MSG_OUT = 126u, + USBTMC_MSGID_VENDOR_SPECIFIC_IN = 127u, + USBTMC_MSGID_USB488_TRIGGER = 128u, +} usbtmc_msgid_enum; + +/// \brief Message header (For BULK OUT and BULK IN); 4 bytes +typedef struct TU_ATTR_PACKED +{ + uint8_t MsgID ; ///< Message type ID (usbtmc_msgid_enum) + uint8_t bTag ; ///< Transfer ID 1<=bTag<=255 + uint8_t bTagInverse ; ///< Complement of the tag + uint8_t _reserved ; ///< Must be 0x00 +} usbtmc_msg_header_t; + +typedef struct TU_ATTR_PACKED +{ + usbtmc_msg_header_t header; + uint8_t data[8]; +} usbtmc_msg_generic_t; + +/* Uses on the bulk-out endpoint: */ +// Next 8 bytes are message-specific +typedef struct TU_ATTR_PACKED { + usbtmc_msg_header_t header ; ///< Header + uint32_t TransferSize ; ///< Transfer size; LSB first + struct { + uint8_t EOM : 1 ; ///< EOM set on last byte + } bmTransferAttributes; + uint8_t _reserved[3]; +} usbtmc_msg_request_dev_dep_out; + +// Next 8 bytes are message-specific +typedef struct TU_ATTR_PACKED { + usbtmc_msg_header_t header ; ///< Header + uint32_t TransferSize ; ///< Transfer size; LSB first + struct { + uint8_t : 0; + uint8_t TermCharEnabled : 1 ; ///< "The Bulk-IN transfer must terminate on the specified TermChar."; CAPABILITIES must list TermChar + } bmTransferAttributes; + uint8_t TermChar; + uint8_t _reserved[2]; +} usbtmc_msg_request_dev_dep_in; + +/* Bulk-in headers */ + +typedef struct TU_ATTR_PACKED +{ + usbtmc_msg_header_t header; + uint32_t TransferSize; + struct { + uint8_t EOM: 1; ///< Last byte of transfer is the end of the message + uint8_t UsingTermChar: 1; ///< Support TermChar && Request.TermCharEnabled && last char in transfer is TermChar + } bmTransferAttributes; + uint8_t _reserved[3]; +} usbtmc_msg_dev_dep_msg_in_header_t; + + +/* Unsupported vendor things.... Are these ever used?*/ + +typedef struct TU_ATTR_PACKED { + usbtmc_msg_header_t header ; ///< Header + uint32_t TransferSize ; ///< Transfer size; LSB first + uint8_t _reserved[4]; +} usbtmc_msg_request_vendor_specific_out; + + +typedef struct TU_ATTR_PACKED { + usbtmc_msg_header_t header ; ///< Header + uint32_t TransferSize ; ///< Transfer size; LSB first + uint8_t _reserved[4]; +} usbtmc_msg_request_vendor_specific_in; + +// Control request type should use tusb_control_request_t + +/* +typedef struct TU_ATTR_PACKED { + struct { + uint8_t Recipient : 5 ; ///< EOM set on last byte + uint8_t Type : 2 ; ///< EOM set on last byte + uint8_t DirectionToHost : 1 ; ///< 0 is OUT, 1 is IN + } bmRequestType; + uint8_t bRequest ; ///< If bmRequestType.Type = Class, see usmtmc_request_type_enum + uint16_t wValue ; + uint16_t wIndex ; + uint16_t wLength ; // Number of bytes in data stage +} usbtmc_class_specific_control_req; + +*/ +// bulk-in protocol errors +enum { + USBTMC_BULK_IN_ERR_INCOMPLETE_HEADER = 1u, + USBTMC_BULK_IN_ERR_UNSUPPORTED = 2u, + USBTMC_BULK_IN_ERR_BAD_PARAMETER = 3u, + USBTMC_BULK_IN_ERR_DATA_TOO_SHORT = 4u, + USBTMC_BULK_IN_ERR_DATA_TOO_LONG = 5u, +}; +// bult-in halt errors +enum { + USBTMC_BULK_IN_ERR = 1u, ///< receives a USBTMC command message that expects a response while a + /// Bulk-IN transfer is in progress +}; + +typedef enum { + USBTMC_bREQUEST_INITIATE_ABORT_BULK_OUT = 1u, + USBTMC_bREQUEST_CHECK_ABORT_BULK_OUT_STATUS = 2u, + USBTMC_bREQUEST_INITIATE_ABORT_BULK_IN = 3u, + USBTMC_bREQUEST_CHECK_ABORT_BULK_IN_STATUS = 4u, + USBTMC_bREQUEST_INITIATE_CLEAR = 5u, + USBTMC_bREQUEST_CHECK_CLEAR_STATUS = 6u, + USBTMC_bREQUEST_GET_CAPABILITIES = 7u, + + USBTMC_bREQUEST_INDICATOR_PULSE = 64u, // Optional +} usmtmc_request_type_enum; + +typedef enum { + USBTMC488_bREQUEST_READ_STATUS_BYTE = 128u, + USBTMC488_bREQUEST_REN_CONTROL = 160u, + USBTMC488_bREQUEST_GO_TO_LOCAL = 161u, + USBTMC488_bREQUEST_LOCAL_LOCKOUT = 162u, +} usbtmc_request_type_488_enum; + +typedef enum { + USBTMC_STATUS_SUCCESS = 0x01, + USBTMC_STATUS_PENDING = 0x02, + USBTMC_STATUS_FAILED = 0x80, + USBTMC_STATUS_TRANSFER_NOT_IN_PROGRESS = 0x81, + USBTMC_STATUS_SPLIT_NOT_IN_PROGRESS = 0x82, + USBTMC_STATUS_SPLIT_IN_PROGRESS = 0x83 +} usbtmc_status_enum; + +/************************************************************ + * Control Responses + */ + +typedef struct TU_ATTR_PACKED { + uint8_t USBTMC_status; ///< usbtmc_status_enum + uint8_t _reserved; + uint16_t bcdUSBTMC; ///< USBTMC_VERSION + + struct { + uint8_t listenOnly :1; + uint8_t talkOnly :1; + uint8_t supportsIndicatorPulse :1; + } bmIntfcCapabilities; + struct { + uint8_t canEndBulkInOnTermChar :1; + } bmDevCapabilities; + uint8_t _reserved2[6]; + uint8_t _reserved3[12]; +} usbtmc_response_capabilities_t; + +TU_VERIFY_STATIC(sizeof(usbtmc_response_capabilities_t) == 0x18, "struct wrong length"); + +typedef struct TU_ATTR_PACKED +{ + uint8_t USBTMC_status; ///< usbtmc_status_enum + uint8_t _reserved; + uint16_t bcdUSBTMC; ///< USBTMC_VERSION + + struct + { + uint8_t listenOnly :1; + uint8_t talkOnly :1; + uint8_t supportsIndicatorPulse :1; + } bmIntfcCapabilities; + + struct + { + uint8_t canEndBulkInOnTermChar :1; + } bmDevCapabilities; + + uint8_t _reserved2[6]; + uint16_t bcdUSB488; + + struct + { + uint8_t is488_2 :1; + uint8_t supportsREN_GTL_LLO :1; + uint8_t supportsTrigger :1; + } bmIntfcCapabilities488; + + struct + { + uint8_t SCPI :1; + uint8_t SR1 :1; + uint8_t RL1 :1; + uint8_t DT1 :1; + } bmDevCapabilities488; + uint8_t _reserved3[8]; +} usbtmc_response_capabilities_488_t; + +TU_VERIFY_STATIC(sizeof(usbtmc_response_capabilities_488_t) == 0x18, "struct wrong length"); + +typedef struct TU_ATTR_PACKED +{ + uint8_t USBTMC_status; + uint8_t bTag; + uint8_t statusByte; +} usbtmc_read_stb_rsp_488_t; + +TU_VERIFY_STATIC(sizeof(usbtmc_read_stb_rsp_488_t) == 3u, "struct wrong length"); + +typedef struct TU_ATTR_PACKET +{ + union { + struct { + uint8_t bTag : 7; + uint8_t one : 1; + } bNotify1Struct; + uint8_t bNotify1; + }; + uint8_t StatusByte; +} usbtmc_read_stb_interrupt_488_t; +TU_VERIFY_STATIC(sizeof(usbtmc_read_stb_interrupt_488_t) == 2u, "struct wrong length"); + +#endif + diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c new file mode 100644 index 000000000..4bb21f354 --- /dev/null +++ b/src/class/usbtmc/usbtmc_device.c @@ -0,0 +1,420 @@ +/* + * usbtmc.c + * + * Created on: Sep 9, 2019 + * Author: nconrad + */ + +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 N Conrad + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#include "tusb_option.h" + +// We don't do any cross-task anything here (everything is in tud or interrupt context). +// You must ensure thread safety in your own app. + + +//Limitations (not planned to be implemented): +// "vendor-specific" commands are not handled + +// TODO: +// USBTMC 3.2.2 error conditions not strictly followed +// No local lock-out, REN, or GTL. +// Cannot issue clear. +// No "capabilities" supported +// Interrupt-IN endpoint +// 488 MsgID=Trigger +// Clear message available status byte at the correct time? (488 4.3.1.3) +// Split transfers +// No CLEAR_FEATURE/HALT (yet) + +#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_USBTMC) + +#include "usbtmc.h" +#include "usbtmc_device.h" +#include "device/dcd.h" +#include "device/usbd.h" + +// FIXME: I shouldn't need to include _pvt headers. +#include "device/usbd_pvt.h" + +typedef enum +{ + STATE_IDLE, + STATE_RCV, + STATE_TX_REQUESTED, + STATE_TX_INITIATED +} usbtmcd_state_enum; + +typedef struct +{ + usbtmcd_state_enum state; + uint8_t itf_id; + uint8_t ep_bulk_in; + uint8_t ep_bulk_out; + uint8_t ep_int_in; + uint8_t ep_bulk_in_buf[64]; + uint8_t ep_bulk_out_buf[64]; + uint8_t lastTag; + + uint32_t transfer_size_remaining; + uint8_t const * devInBuffer; +} usbtmc_interface_state_t; + +static usbtmc_interface_state_t usbtmc_state = +{ + .state = STATE_IDLE, + .itf_id = 0xFF, + .ep_bulk_in = 0, + .ep_bulk_out = 0, + .ep_int_in = 0 +}; + +// We want everything to fit nicely in a single packet, so lets require EP size >32 +// I'm not sure if this is really necessary, though. +TU_VERIFY_STATIC(USBTMCD_MAX_PACKET_SIZE >= 32u,"USBTMC dev EP packet size too small"); + +// called from app +// We keep a reference to the buffer, so it MUST not change until the app is +// notified that the transfer is complete. +// length of data is specified in the hdr. +bool usbtmcd_transmit_dev_msg_data( + uint8_t rhport, + usbtmc_msg_dev_dep_msg_in_header_t const * hdr, + const void *data) +{ + TU_ASSERT(usbtmc_state.state == STATE_TX_REQUESTED); + TU_ASSERT(hdr->TransferSize > 0u); + + // Copy in the header + memcpy(usbtmc_state.ep_bulk_in_buf, hdr, sizeof(*hdr)); + uint packetLen = sizeof(*hdr); + // Single-packet transfer + if((packetLen + hdr->TransferSize) <= USBTMCD_MAX_PACKET_SIZE) + { + memcpy((uint8_t*)(usbtmc_state.ep_bulk_in_buf) + packetLen, data, hdr->TransferSize); + packetLen = (uint16_t)(packetLen+ hdr->TransferSize); + // Pad up to multiple of 4 bytes + while((packetLen % 4) != 0) + { + usbtmc_state.ep_bulk_in_buf[packetLen] = 0; + packetLen++; + } + usbtmc_state.transfer_size_remaining = 0; + usbtmc_state.devInBuffer = NULL; + } + else + { + memcpy((uint8_t*)(usbtmc_state.ep_bulk_in_buf) + packetLen, data, USBTMCD_MAX_PACKET_SIZE - packetLen); + usbtmc_state.transfer_size_remaining = hdr->TransferSize - (USBTMCD_MAX_PACKET_SIZE - packetLen); + usbtmc_state.devInBuffer += (USBTMCD_MAX_PACKET_SIZE - packetLen); + packetLen = USBTMCD_MAX_PACKET_SIZE; + } + usbtmc_state.state = STATE_TX_INITIATED; + TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf,(uint16_t)packetLen)); + return true; +} + +void usbtmcd_init(void) +{ + +} + +bool usbtmcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length) +{ + (void)rhport; + uint8_t const * p_desc; + uint8_t found_endpoints = 0; + + // Perhaps there are other application specific class drivers, so don't assert here. + if( itf_desc->bInterfaceClass != USBTMC_APP_CLASS) + return false; + if( itf_desc->bInterfaceSubClass != USBTMC_APP_SUBCLASS) + return false; + + // Only 2 or 3 endpoints are allowed for USBTMC. + TU_ASSERT((itf_desc->bNumEndpoints == 2) || (itf_desc->bNumEndpoints ==3)); + + // Interface + (*p_length) = 0u; + p_desc = (uint8_t const *) itf_desc; + + usbtmc_state.itf_id = itf_desc->bInterfaceNumber; + + while (found_endpoints < itf_desc->bNumEndpoints) + { + if ( TUSB_DESC_ENDPOINT == p_desc[DESC_OFFSET_TYPE]) + { + tusb_desc_endpoint_t const *ep_desc = (tusb_desc_endpoint_t const *)p_desc; + switch(ep_desc->bmAttributes.xfer) { + case TUSB_XFER_BULK: + if (tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN) + { + usbtmc_state.ep_bulk_in = ep_desc->bEndpointAddress; + } else { + usbtmc_state.ep_bulk_out = ep_desc->bEndpointAddress; + } + + break; + case TUSB_XFER_INTERRUPT: + TU_ASSERT(tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN); + TU_ASSERT(usbtmc_state.ep_int_in == 0); + usbtmc_state.ep_int_in = ep_desc->bEndpointAddress; + break; + default: + TU_ASSERT(false); + } + TU_VERIFY( dcd_edpt_open(rhport, ep_desc)); + found_endpoints++; + } + (*p_length) = (uint8_t)((*p_length) + p_desc[DESC_OFFSET_LEN]); + p_desc = tu_desc_next(p_desc); + } + + // bulk endpoints are required, but interrupt IN is optional + TU_ASSERT(usbtmc_state.ep_bulk_in != 0); + TU_ASSERT(usbtmc_state.ep_bulk_out != 0); + if (itf_desc->bNumEndpoints == 2) { + TU_ASSERT(usbtmc_state.ep_int_in == 0); + } + else if (itf_desc->bNumEndpoints == 2) + { + TU_ASSERT(usbtmc_state.ep_int_in != 0); + } + TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, 64)); + + return true; +} +void usbtmcd_reset(uint8_t rhport) +{ + // FIXME: Do endpoints need to be closed here? + (void)rhport; +} +static bool handle_devMsgOut(uint8_t rhport, void *data, size_t len) +{ + (void)rhport; + bool shortPacket = (len < USBTMCD_MAX_PACKET_SIZE); + if(usbtmc_state.state == STATE_IDLE) + { + // must be a header, should have been confirmed before calling here. + usbtmc_msg_request_dev_dep_out *msg = (usbtmc_msg_request_dev_dep_out*)data; + usbtmc_state.transfer_size_remaining = msg->TransferSize; + TU_VERIFY(usbtmcd_app_msgBulkOut_start(msg)); + len -= sizeof(*msg); + data = (uint8_t*)data + sizeof(*msg); + } + // Packet is to be considered complete when we get enough data or at a short packet. + bool atEnd = false; + if(len >= usbtmc_state.transfer_size_remaining || shortPacket) + atEnd = true; + if(len > usbtmc_state.transfer_size_remaining) + len = usbtmc_state.transfer_size_remaining; + usbtmcd_app_msg_data(data, len, atEnd); + if(atEnd) + usbtmc_state.state = STATE_IDLE; + else + usbtmc_state.state = STATE_RCV; + return true; +} +static bool handle_devMsgIn(uint8_t rhport, void *data, size_t len) +{ + TU_VERIFY(len == sizeof(usbtmc_msg_request_dev_dep_in)); + usbtmc_msg_request_dev_dep_in *msg = (usbtmc_msg_request_dev_dep_in*)data; + TU_VERIFY(usbtmc_state.state == STATE_IDLE); + usbtmc_state.state = STATE_TX_REQUESTED; + usbtmc_state.transfer_size_remaining = msg->TransferSize; + TU_VERIFY(usbtmcd_app_msgBulkIn_request(rhport, msg)); + return true; +} + +bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) +{ + TU_VERIFY(result == XFER_RESULT_SUCCESS); + if(ep_addr == usbtmc_state.ep_bulk_out) + { + switch(usbtmc_state.state) + { + case STATE_IDLE: + TU_VERIFY(xferred_bytes >= sizeof(usbtmc_msg_generic_t)); + usbtmc_msg_generic_t *msg = (usbtmc_msg_generic_t*)(usbtmc_state.ep_bulk_out_buf); + uint8_t invInvTag = (uint8_t)~(msg->header.bTagInverse); + TU_VERIFY(msg->header.bTag == invInvTag); + TU_VERIFY(msg->header.bTag != 0x00); + usbtmc_state.lastTag = msg->header.bTag; + + switch(msg->header.MsgID) { + case USBTMC_MSGID_DEV_DEP_MSG_OUT: + TU_VERIFY(handle_devMsgOut(rhport, msg, xferred_bytes)); + TU_VERIFY(usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, 64)); + break; + case USBTMC_MSGID_DEV_DEP_MSG_IN: + TU_VERIFY(handle_devMsgIn(rhport, msg, xferred_bytes)); + break; + case USBTMC_MSGID_VENDOR_SPECIFIC_MSG_OUT: + case USBTMC_MSGID_VENDOR_SPECIFIC_IN: + case USBTMC_MSGID_USB488_TRIGGER: + default: + TU_VERIFY(false); + } + return true; + + case STATE_RCV: + TU_VERIFY(handle_devMsgOut(rhport, usbtmc_state.ep_bulk_out_buf, xferred_bytes)); + TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, 64)); + return true; + break; + + default: + TU_VERIFY(false); + } + } + else if(ep_addr == usbtmc_state.ep_bulk_in) + { + TU_ASSERT(usbtmc_state.state == STATE_TX_INITIATED); + if(usbtmc_state.transfer_size_remaining == 0) + { + usbtmc_state.state = STATE_IDLE; + TU_VERIFY(usbtmcd_app_msgBulkIn_complete(rhport)); + TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, 64)); + } + else if(usbtmc_state.transfer_size_remaining >= USBTMCD_MAX_PACKET_SIZE) + { + memcpy(usbtmc_state.ep_bulk_in_buf, usbtmc_state.devInBuffer, USBTMCD_MAX_PACKET_SIZE); + usbtmc_state.devInBuffer += USBTMCD_MAX_PACKET_SIZE; + usbtmc_state.transfer_size_remaining -= USBTMCD_MAX_PACKET_SIZE; + TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf,USBTMCD_MAX_PACKET_SIZE)); + } + else // short packet + { + uint packetLen = usbtmc_state.transfer_size_remaining; + memcpy(usbtmc_state.ep_bulk_in_buf, usbtmc_state.devInBuffer, usbtmc_state.transfer_size_remaining); + while((packetLen % 4) != 0) + { + usbtmc_state.ep_bulk_in_buf[packetLen] = 0; + packetLen++; + } + usbtmc_state.transfer_size_remaining = 0; + usbtmc_state.devInBuffer = NULL; + TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf,(uint16_t)packetLen)); + } + return true; + } + else if (ep_addr == usbtmc_state.ep_int_in) { + // Good? + return true; + } + return false; +} + +bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * request) { + +#if (USBTMC_CFG_ENABLE_488) + ushort bTag; +#endif + // We only handle class requests. + if(request->bmRequestType_bit.type != TUSB_REQ_TYPE_CLASS) + return false; + + switch(request->bRequest) + { + // USBTMC required requests + case USBTMC_bREQUEST_INITIATE_ABORT_BULK_OUT: + case USBTMC_bREQUEST_CHECK_ABORT_BULK_OUT_STATUS: + case USBTMC_bREQUEST_INITIATE_ABORT_BULK_IN: + case USBTMC_bREQUEST_CHECK_ABORT_BULK_IN_STATUS: + case USBTMC_bREQUEST_INITIATE_CLEAR: + case USBTMC_bREQUEST_CHECK_CLEAR_STATUS: + TU_VERIFY(false); + break; + + case USBTMC_bREQUEST_GET_CAPABILITIES: + TU_VERIFY(request->bmRequestType == 0xA1); + TU_VERIFY(request->wValue == 0x0000); + TU_VERIFY(request->wIndex == usbtmc_state.itf_id); + TU_VERIFY(request->wLength == sizeof(usbtmcd_app_capabilities)); + TU_VERIFY(tud_control_xfer(rhport, request, (void*)&usbtmcd_app_capabilities, sizeof(usbtmcd_app_capabilities))); + return true; + // USBTMC Optional Requests + case USBTMC_bREQUEST_INDICATOR_PULSE: // Optional + TU_VERIFY(false); + return false; + +#if (USBTMC_CFG_ENABLE_488) + // USB488 required requests + case USBTMC488_bREQUEST_READ_STATUS_BYTE: + + bTag = request->wValue & 0x7F; + TU_VERIFY(request->bmRequestType == 0xA1); + TU_VERIFY((request->wValue & (~0x7F)) == 0u); // Other bits are required to be zero + TU_VERIFY(bTag >= 0x02 && bTag <= 127); + TU_VERIFY(request->wIndex == usbtmc_state.itf_id); + TU_VERIFY(request->wLength == 0x0003); + usbtmc_read_stb_rsp_488_t rsp; + rsp.bTag = (uint8_t)bTag; + if(usbtmc_state.ep_int_in != 0) + { + rsp.USBTMC_status = USBTMC_STATUS_SUCCESS; + rsp.statusByte = 0x00; // Use interrupt endpoint, instead. + + usbtmc_read_stb_interrupt_488_t intMsg = + { + .bNotify1 = (uint8_t)(0x80 | bTag), + .StatusByte = usbtmcd_app_get_stb(rhport, &(rsp.USBTMC_status)) + }; + usbd_edpt_xfer(rhport, usbtmc_state.ep_int_in, (void*)&intMsg,sizeof(intMsg)); + + } + else + { + rsp.statusByte = usbtmcd_app_get_stb(rhport, &(rsp.USBTMC_status)); + } + TU_VERIFY(tud_control_xfer(rhport, request, (void*)&rsp, sizeof(rsp))); + return true; + + // USB488 optional requests + case USBTMC488_bREQUEST_REN_CONTROL: + case USBTMC488_bREQUEST_GO_TO_LOCAL: + case USBTMC488_bREQUEST_LOCAL_LOCKOUT: + TU_VERIFY(false); + return false; +#endif + + default: + TU_VERIFY(false); + } + TU_VERIFY(false); +} + +bool usbtmcd_control_complete(uint8_t rhport, tusb_control_request_t const * request) +{ + (void)rhport; + //------------- Class Specific Request -------------// + TU_VERIFY (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); + + return true; +} + +#endif /* CFG_TUD_TSMC */ diff --git a/src/class/usbtmc/usbtmc_device.h b/src/class/usbtmc/usbtmc_device.h new file mode 100644 index 000000000..c03ca9461 --- /dev/null +++ b/src/class/usbtmc/usbtmc_device.h @@ -0,0 +1,130 @@ +/* + * usbtmc_device.h + * + * Created on: Sep 10, 2019 + * Author: nconrad + */ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 N Conrad + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + + +#ifndef CLASS_USBTMC_USBTMC_DEVICE_H_ +#define CLASS_USBTMC_USBTMC_DEVICE_H_ + +#include "usbtmc.h" + +// Enable 488 mode by default +#if !defined(USBTMC_CFG_ENABLE_488) +#define USBTMC_CFG_ENABLE_488 (1) +#endif + +// USB spec says that full-speed must be 8,16,32, or 64. +// However, this driver implementation requires it to be >=32 +#define USBTMCD_MAX_PACKET_SIZE (64u) + +/*********************************************** + * Functions to be implemeted by the class implementation + */ + +#if (USBTMC_CFG_ENABLE_488) +extern usbtmc_response_capabilities_488_t const usbtmcd_app_capabilities; +#else +extern usbtmc_response_capabilities_t const usbtmcd_app_capabilities; +#endif + +bool usbtmcd_app_msgBulkOut_start(usbtmc_msg_request_dev_dep_out const * msgHeader); + +// transfer_complete does not imply that a message is complete. +bool usbtmcd_app_msg_data(void *data, size_t len, bool transfer_complete); + +bool usbtmcd_app_msgBulkIn_request(uint8_t rhport, usbtmc_msg_request_dev_dep_in const * request); + +bool usbtmcd_app_msgBulkIn_complete(uint8_t rhport); + +#if (USBTMC_CFG_ENABLE_488) +uint8_t usbtmcd_app_get_stb(uint8_t rhport, uint8_t *rspResult); + +//TU_ATTR_WEAK bool usbtmcd_app_go_to_local(uint8_t rhport); +#endif + +/******************************************* + * Called from app + * + * We keep a reference to the buffer, so it MUST not change until the app is + * notified that the transfer is complete. + ******************************************/ + +bool usbtmcd_transmit_dev_msg_data( + uint8_t rhport, + usbtmc_msg_dev_dep_msg_in_header_t const * hdr, + const void *data); + + +/* "callbacks" from USB device core */ + +bool usbtmcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length); +void usbtmcd_reset(uint8_t rhport); +bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); +bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * request); +bool usbtmcd_control_complete(uint8_t rhport, tusb_control_request_t const * request); +void usbtmcd_init(void); + +/************************************************************ + * USBTMC Descriptor Templates + *************************************************************/ + +#define USBTMC_APP_CLASS TUSB_CLASS_APPLICATION_SPECIFIC +#define USBTMC_APP_SUBCLASS 0x03 + +#define USBTMC_PROTOCOL_STD 0x00 +#define USBTMC_PROTOCOL_USB488 0x01 + +// Interface number, number of endpoints, EP string index, USB_TMC_PROTOCOL*, bulk-out endpoint ID, +// bulk-in endpoint ID +#define USBTMC_IF_DESCRIPTOR(_itfnum, _bNumEndpoints, _stridx, _itfProtocol) \ +/* Interface */ \ + 0x09, TUSB_DESC_INTERFACE, _itfnum, 0x00, _bNumEndpoints, USBTMC_APP_CLASS, USBTMC_APP_SUBCLASS, _itfProtocol, _stridx + +#define USBTMC_IF_DESCRIPTOR_LEN 9u + +// bulk-out Size must be a multiple of 4 bytes +#define USBTMC_BULK_DESCRIPTORS(_epout, _epin) \ +/* Endpoint Out */ \ +7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(USBTMCD_MAX_PACKET_SIZE), 0u, \ +/* Endpoint In */ \ +7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(USBTMCD_MAX_PACKET_SIZE), 0u + +#define USBTMC_BULK_DESCRIPTORS_LEN (7u+7u) + +/* optional interrupt endpoint */ \ +// _int_pollingInterval : for LS/FS, expressed in frames (1ms each). 16 may be a good number? +#define USBTMC_INT_DESCRIPTOR(_ep_interrupt, _ep_interrupt_size, _int_pollingInterval ) \ +7, TUSB_DESC_ENDPOINT, _ep_interrupt, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_interrupt_size), 0x16 + +#define USBTMC_INT_DESCRIPTOR_LEN (7u) + + +#endif /* CLASS_USBTMC_USBTMC_DEVICE_H_ */ diff --git a/src/device/usbd.c b/src/device/usbd.c index c92884334..572708f7d 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -145,6 +145,22 @@ static usbd_class_driver_t const usbd_class_drivers[] = .sof = NULL }, #endif + + #if CFG_TUD_USBTMC + // Presently USBTMC is the only defined class with the APP_SPECIFIC class code. + // We maybe need to add subclass codes here, or a callback to ask if a driver can + // handle a particular interface. + { + .class_code = TUSB_CLASS_APPLICATION_SPECIFIC, + .init = usbtmcd_init, + .reset = usbtmcd_reset, + .open = usbtmcd_open, + .control_request = usbtmcd_control_request, + .control_complete = usbtmcd_control_complete, + .xfer_cb = usbtmcd_xfer_cb, + .sof = NULL + }, + #endif }; enum { USBD_CLASS_DRIVER_COUNT = TU_ARRAY_SIZE(usbd_class_drivers) }; diff --git a/src/tusb.h b/src/tusb.h index fe8673726..1a6ff0b10 100644 --- a/src/tusb.h +++ b/src/tusb.h @@ -83,6 +83,10 @@ #if CFG_TUD_VENDOR #include "class/vendor/vendor_device.h" #endif + + #if CFG_TUD_USBTMC + #include "class/usbtmc/usbtmc_device.h" + #endif #endif diff --git a/src/tusb_option.h b/src/tusb_option.h index 9aacb558f..76ea59758 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -181,6 +181,10 @@ #define CFG_TUD_VENDOR 0 #endif +#ifndef CFG_TUD_USBTMC + #define CFG_TUD_USBTMC 0 +#endif + //-------------------------------------------------------------------- // HOST OPTIONS From e74c6b0874a54b86fee61692484e0407d6a97508 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Sat, 14 Sep 2019 15:38:11 -0400 Subject: [PATCH 02/45] Combined status response enum (std with 488), support trigger. --- src/class/usbtmc/usbtmc.h | 6 +-- src/class/usbtmc/usbtmc_device.c | 63 ++++++++++++++++++++++---------- src/class/usbtmc/usbtmc_device.h | 8 ++-- 3 files changed, 50 insertions(+), 27 deletions(-) diff --git a/src/class/usbtmc/usbtmc.h b/src/class/usbtmc/usbtmc.h index 846c0e38d..ecc16a315 100644 --- a/src/class/usbtmc/usbtmc.h +++ b/src/class/usbtmc/usbtmc.h @@ -160,14 +160,14 @@ typedef enum { USBTMC_bREQUEST_GET_CAPABILITIES = 7u, USBTMC_bREQUEST_INDICATOR_PULSE = 64u, // Optional -} usmtmc_request_type_enum; -typedef enum { + /****** USBTMC 488 *************/ USBTMC488_bREQUEST_READ_STATUS_BYTE = 128u, USBTMC488_bREQUEST_REN_CONTROL = 160u, USBTMC488_bREQUEST_GO_TO_LOCAL = 161u, USBTMC488_bREQUEST_LOCAL_LOCKOUT = 162u, -} usbtmc_request_type_488_enum; + +} usmtmc_request_type_enum; typedef enum { USBTMC_STATUS_SUCCESS = 0x01, diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index 4bb21f354..25f943598 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -97,6 +97,10 @@ static usbtmc_interface_state_t usbtmc_state = // I'm not sure if this is really necessary, though. TU_VERIFY_STATIC(USBTMCD_MAX_PACKET_SIZE >= 32u,"USBTMC dev EP packet size too small"); + +static bool handle_devMsgOutStart(uint8_t rhport, void *data, size_t len); +static bool handle_devMsgOut(uint8_t rhport, void *data, size_t len, size_t packetLen); + // called from app // We keep a reference to the buffer, so it MUST not change until the app is // notified that the transfer is complete. @@ -140,7 +144,10 @@ bool usbtmcd_transmit_dev_msg_data( void usbtmcd_init(void) { - +#if USBTMC_CFG_ENABLE_488 + if(usbtmcd_app_capabilities.bmIntfcCapabilities488.supportsTrigger) + TU_ASSERT(usbtmcd_app_msg_trigger != NULL,); +#endif } bool usbtmcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length) @@ -213,32 +220,39 @@ void usbtmcd_reset(uint8_t rhport) // FIXME: Do endpoints need to be closed here? (void)rhport; } -static bool handle_devMsgOut(uint8_t rhport, void *data, size_t len) + +static bool handle_devMsgOutStart(uint8_t rhport, void *data, size_t len) { (void)rhport; - bool shortPacket = (len < USBTMCD_MAX_PACKET_SIZE); - if(usbtmc_state.state == STATE_IDLE) - { - // must be a header, should have been confirmed before calling here. - usbtmc_msg_request_dev_dep_out *msg = (usbtmc_msg_request_dev_dep_out*)data; - usbtmc_state.transfer_size_remaining = msg->TransferSize; - TU_VERIFY(usbtmcd_app_msgBulkOut_start(msg)); - len -= sizeof(*msg); - data = (uint8_t*)data + sizeof(*msg); - } + TU_VERIFY(usbtmc_state.state == STATE_IDLE); + // must be a header, should have been confirmed before calling here. + usbtmc_msg_request_dev_dep_out *msg = (usbtmc_msg_request_dev_dep_out*)data; + usbtmc_state.transfer_size_remaining = msg->TransferSize; + TU_VERIFY(usbtmcd_app_msgBulkOut_start(rhport,msg)); + + TU_VERIFY(handle_devMsgOut(rhport, (uint8_t*)data + sizeof(*msg), len - sizeof(*msg), len)); + return true; +} + +static bool handle_devMsgOut(uint8_t rhport, void *data, size_t len, size_t packetLen) +{ + (void)rhport; + bool shortPacket = (packetLen < USBTMCD_MAX_PACKET_SIZE); + // Packet is to be considered complete when we get enough data or at a short packet. bool atEnd = false; if(len >= usbtmc_state.transfer_size_remaining || shortPacket) atEnd = true; if(len > usbtmc_state.transfer_size_remaining) len = usbtmc_state.transfer_size_remaining; - usbtmcd_app_msg_data(data, len, atEnd); + usbtmcd_app_msg_data(rhport,data, len, atEnd); if(atEnd) usbtmc_state.state = STATE_IDLE; else usbtmc_state.state = STATE_RCV; return true; } + static bool handle_devMsgIn(uint8_t rhport, void *data, size_t len) { TU_VERIFY(len == sizeof(usbtmc_msg_request_dev_dep_in)); @@ -267,25 +281,34 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint switch(msg->header.MsgID) { case USBTMC_MSGID_DEV_DEP_MSG_OUT: - TU_VERIFY(handle_devMsgOut(rhport, msg, xferred_bytes)); - TU_VERIFY(usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, 64)); + TU_VERIFY(handle_devMsgOutStart(rhport, msg, xferred_bytes)); + TU_VERIFY(usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, USBTMCD_MAX_PACKET_SIZE)); break; + case USBTMC_MSGID_DEV_DEP_MSG_IN: TU_VERIFY(handle_devMsgIn(rhport, msg, xferred_bytes)); break; + +#ifdef USBTMC_CFG_ENABLE_488 + case USBTMC_MSGID_USB488_TRIGGER: + // Spec says we halt the EP if we didn't declare we support it. + TU_VERIFY(usbtmcd_app_capabilities.bmIntfcCapabilities488.supportsTrigger); + TU_VERIFY(usbtmcd_app_msg_trigger(rhport, msg)); + TU_VERIFY(usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, USBTMCD_MAX_PACKET_SIZE)); + + break; +#endif case USBTMC_MSGID_VENDOR_SPECIFIC_MSG_OUT: case USBTMC_MSGID_VENDOR_SPECIFIC_IN: - case USBTMC_MSGID_USB488_TRIGGER: default: TU_VERIFY(false); + return false; } return true; case STATE_RCV: - TU_VERIFY(handle_devMsgOut(rhport, usbtmc_state.ep_bulk_out_buf, xferred_bytes)); - TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, 64)); + TU_VERIFY(handle_devMsgOut(rhport, usbtmc_state.ep_bulk_out_buf, xferred_bytes, xferred_bytes)); return true; - break; default: TU_VERIFY(false); @@ -298,7 +321,7 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint { usbtmc_state.state = STATE_IDLE; TU_VERIFY(usbtmcd_app_msgBulkIn_complete(rhport)); - TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, 64)); + TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, USBTMCD_MAX_PACKET_SIZE)); } else if(usbtmc_state.transfer_size_remaining >= USBTMCD_MAX_PACKET_SIZE) { diff --git a/src/class/usbtmc/usbtmc_device.h b/src/class/usbtmc/usbtmc_device.h index c03ca9461..1246d11d1 100644 --- a/src/class/usbtmc/usbtmc_device.h +++ b/src/class/usbtmc/usbtmc_device.h @@ -55,18 +55,18 @@ extern usbtmc_response_capabilities_488_t const usbtmcd_app_capabilities; extern usbtmc_response_capabilities_t const usbtmcd_app_capabilities; #endif -bool usbtmcd_app_msgBulkOut_start(usbtmc_msg_request_dev_dep_out const * msgHeader); +bool usbtmcd_app_msgBulkOut_start(uint8_t rhport, usbtmc_msg_request_dev_dep_out const * msgHeader); // transfer_complete does not imply that a message is complete. -bool usbtmcd_app_msg_data(void *data, size_t len, bool transfer_complete); +bool usbtmcd_app_msg_data(uint8_t rhport, void *data, size_t len, bool transfer_complete); bool usbtmcd_app_msgBulkIn_request(uint8_t rhport, usbtmc_msg_request_dev_dep_in const * request); bool usbtmcd_app_msgBulkIn_complete(uint8_t rhport); #if (USBTMC_CFG_ENABLE_488) -uint8_t usbtmcd_app_get_stb(uint8_t rhport, uint8_t *rspResult); - +uint8_t usbtmcd_app_get_stb(uint8_t rhport, usbtmc_status_enum *rspResult); +TU_ATTR_WEAK bool usbtmcd_app_msg_trigger(uint8_t rhport, usbtmc_msg_generic_t* msg); //TU_ATTR_WEAK bool usbtmcd_app_go_to_local(uint8_t rhport); #endif From acd8fa76505f036858e2d33ebbc58cc7f15e3a8b Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Sat, 14 Sep 2019 16:56:53 -0400 Subject: [PATCH 03/45] (and update the example to match) --- examples/device/usbtmc/src/usbtmc_app.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/examples/device/usbtmc/src/usbtmc_app.c b/examples/device/usbtmc/src/usbtmc_app.c index 515c2a486..4ec6ad90c 100644 --- a/examples/device/usbtmc/src/usbtmc_app.c +++ b/examples/device/usbtmc/src/usbtmc_app.c @@ -49,7 +49,7 @@ usbtmcd_app_capabilities = .bcdUSB488 = USBTMC_488_VERSION, .bmIntfcCapabilities488 = { - .supportsTrigger = 0, + .supportsTrigger = 1, .supportsREN_GTL_LLO = 0, .is488_2 = 1 }, @@ -68,15 +68,21 @@ static uint8_t status; static bool queryReceived = false; -bool usbtmcd_app_msgBulkOut_start(usbtmc_msg_request_dev_dep_out const * msgHeader) +bool usbtmcd_app_msgBulkOut_start(uint8_t rhport, usbtmc_msg_request_dev_dep_out const * msgHeader) { + (void)rhport; (void)msgHeader; return true; } +bool usbtmcd_app_msg_trigger(uint8_t rhport, usbtmc_msg_generic_t* msg) { + (void)rhport; + (void)msg; + return true; +} - -bool usbtmcd_app_msg_data(void *data, size_t len, bool transfer_complete) +bool usbtmcd_app_msg_data(uint8_t rhport, void *data, size_t len, bool transfer_complete) { + (void)rhport; (void)transfer_complete; if(transfer_complete && (len >=4) && !strncasecmp("*idn?",data,4)) { queryReceived = true; @@ -121,7 +127,7 @@ bool usbtmcd_app_msgBulkIn_request(uint8_t rhport, usbtmc_msg_request_dev_dep_in } // Return status byte, but put the transfer result status code in the rspResult argument. -uint8_t usbtmcd_app_get_stb(uint8_t rhport, uint8_t *rspResult) +uint8_t usbtmcd_app_get_stb(uint8_t rhport, usbtmc_status_enum *rspResult) { (void)rhport; *rspResult = USBTMC_STATUS_SUCCESS; From 6e00886ffbbc552cf91be73d57fe8ad0a4842d0b Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Sat, 14 Sep 2019 17:15:34 -0400 Subject: [PATCH 04/45] Handle USBTMC TermChar. --- src/class/usbtmc/usbtmc_device.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index 25f943598..909f8251f 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -61,6 +61,9 @@ // FIXME: I shouldn't need to include _pvt headers. #include "device/usbd_pvt.h" +static uint8_t termChar; +static uint8_t termCharRequested = false; + typedef enum { STATE_IDLE, @@ -113,6 +116,13 @@ bool usbtmcd_transmit_dev_msg_data( TU_ASSERT(usbtmc_state.state == STATE_TX_REQUESTED); TU_ASSERT(hdr->TransferSize > 0u); + if(hdr->bmTransferAttributes.UsingTermChar) + { + TU_ASSERT(usbtmcd_app_capabilities.bmDevCapabilities.canEndBulkInOnTermChar); + TU_ASSERT(termCharRequested); + TU_ASSERT(((uint8_t*)data)[hdr->TransferSize-1] == termChar); + } + // Copy in the header memcpy(usbtmc_state.ep_bulk_in_buf, hdr, sizeof(*hdr)); uint packetLen = sizeof(*hdr); @@ -260,6 +270,12 @@ static bool handle_devMsgIn(uint8_t rhport, void *data, size_t len) TU_VERIFY(usbtmc_state.state == STATE_IDLE); usbtmc_state.state = STATE_TX_REQUESTED; usbtmc_state.transfer_size_remaining = msg->TransferSize; + + termCharRequested = msg->bmTransferAttributes.TermCharEnabled; + termChar = msg->TermChar; + if(termCharRequested) + TU_VERIFY(usbtmcd_app_capabilities.bmDevCapabilities.canEndBulkInOnTermChar); + TU_VERIFY(usbtmcd_app_msgBulkIn_request(rhport, msg)); return true; } @@ -310,6 +326,8 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint TU_VERIFY(handle_devMsgOut(rhport, usbtmc_state.ep_bulk_out_buf, xferred_bytes, xferred_bytes)); return true; + case STATE_TX_REQUESTED: + case STATE_TX_INITIATED: default: TU_VERIFY(false); } From 64bfec79b2d1d75b5c06be2dc2fff83ee385a720 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Sat, 14 Sep 2019 18:07:12 -0400 Subject: [PATCH 05/45] Change requset type parameter back to uint8_t (fix type cast), support USB indicator pulse --- examples/device/usbtmc/src/main.c | 47 ++++++++++++++++++++----- examples/device/usbtmc/src/main.h | 5 +++ examples/device/usbtmc/src/usbtmc_app.c | 13 ++++--- src/class/usbtmc/usbtmc_device.c | 21 ++++++----- src/class/usbtmc/usbtmc_device.h | 4 ++- 5 files changed, 68 insertions(+), 22 deletions(-) create mode 100644 examples/device/usbtmc/src/main.h diff --git a/examples/device/usbtmc/src/main.c b/examples/device/usbtmc/src/main.c index 0293261ad..8bc2a8398 100644 --- a/examples/device/usbtmc/src/main.c +++ b/examples/device/usbtmc/src/main.c @@ -36,12 +36,12 @@ /* Blink pattern * - 250 ms : device not mounted - * - 1000 ms : device mounted + * - 0 ms : device mounted * - 2500 ms : device is suspended */ enum { BLINK_NOT_MOUNTED = 250, - BLINK_MOUNTED = 1000, + BLINK_MOUNTED = 0, BLINK_SUSPENDED = 2500, }; @@ -97,17 +97,46 @@ void tud_resume_cb(void) } //--------------------------------------------------------------------+ -// BLINKING TASK +// BLINKING TASK + Indicator pulse //--------------------------------------------------------------------+ + + +volatile uint8_t doPulse = false; +// called from USB context +void led_indicator_pulse(void) { + doPulse = true; +} + void led_blinking_task(void) { static uint32_t start_ms = 0; static bool led_state = false; + if(blink_interval_ms == BLINK_MOUNTED) // Mounted + { + if(doPulse) + { + led_state = true; + board_led_write(true); + start_ms = board_millis(); + doPulse = false; + } + else if (led_state == true) + { + if ( board_millis() - start_ms < 750) //Spec says blink must be between 500 and 1000 ms. + { + return; // not enough time + } + led_state = false; + board_led_write(false); + } + } + else + { + // Blink every interval ms + if ( board_millis() - start_ms < blink_interval_ms) return; // not enough time + start_ms += blink_interval_ms; - // Blink every interval ms - if ( board_millis() - start_ms < blink_interval_ms) return; // not enough time - start_ms += blink_interval_ms; - - board_led_write(led_state); - led_state = 1 - led_state; // toggle + board_led_write(led_state); + led_state = 1 - led_state; // toggle + } } diff --git a/examples/device/usbtmc/src/main.h b/examples/device/usbtmc/src/main.h new file mode 100644 index 000000000..673247ec7 --- /dev/null +++ b/examples/device/usbtmc/src/main.h @@ -0,0 +1,5 @@ +#ifndef MAIN_H +#define MAIN_H +void led_indicator_pulse(void); + +#endif diff --git a/examples/device/usbtmc/src/usbtmc_app.c b/examples/device/usbtmc/src/usbtmc_app.c index 4ec6ad90c..6b72bb360 100644 --- a/examples/device/usbtmc/src/usbtmc_app.c +++ b/examples/device/usbtmc/src/usbtmc_app.c @@ -25,6 +25,7 @@ #include #include "class/usbtmc/usbtmc_device.h" +#include "main.h" #if (USBTMC_CFG_ENABLE_488) usbtmc_response_capabilities_488_t const @@ -39,7 +40,7 @@ usbtmcd_app_capabilities = { .listenOnly = 0, .talkOnly = 0, - .supportsIndicatorPulse = 0 + .supportsIndicatorPulse = 1 }, .bmDevCapabilities = { .canEndBulkInOnTermChar = 0 @@ -63,7 +64,7 @@ usbtmcd_app_capabilities = #endif }; -static const char idn[] = "TinyUSB,ModelNumber,SerialNumber,FirmwareVer"; +static const char idn[] = "TinyUSB,ModelNumber,SerialNumber,FirmwareVer\n"; static uint8_t status; static bool queryReceived = false; @@ -96,7 +97,7 @@ bool usbtmcd_app_msgBulkIn_complete(uint8_t rhport) return true; } -static uint8_t noQueryMsg[] = "ERR: No query"; +static uint8_t noQueryMsg[] = "ERR: No query\n"; bool usbtmcd_app_msgBulkIn_request(uint8_t rhport, usbtmc_msg_request_dev_dep_in const * request) { usbtmc_msg_dev_dep_msg_in_header_t hdr = { @@ -127,7 +128,7 @@ bool usbtmcd_app_msgBulkIn_request(uint8_t rhport, usbtmc_msg_request_dev_dep_in } // Return status byte, but put the transfer result status code in the rspResult argument. -uint8_t usbtmcd_app_get_stb(uint8_t rhport, usbtmc_status_enum *rspResult) +uint8_t usbtmcd_app_get_stb(uint8_t rhport, uint8_t *rspResult) { (void)rhport; *rspResult = USBTMC_STATUS_SUCCESS; @@ -137,3 +138,7 @@ uint8_t usbtmcd_app_get_stb(uint8_t rhport, usbtmc_status_enum *rspResult) return status; } +bool usbtmcd_app_indicator_pluse(uint8_t rhport, tusb_control_request_t const * msg) +{ + led_indicator_pulse(); +} diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index 909f8251f..7bc768a58 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -39,17 +39,18 @@ //Limitations (not planned to be implemented): // "vendor-specific" commands are not handled +// Dealing with "termchar" must be handled by the application layer, +// though additional error checking is does in this module. // TODO: // USBTMC 3.2.2 error conditions not strictly followed // No local lock-out, REN, or GTL. -// Cannot issue clear. -// No "capabilities" supported -// Interrupt-IN endpoint -// 488 MsgID=Trigger +// Cannot handle clear. +// Not all "capabilities" supported // Clear message available status byte at the correct time? (488 4.3.1.3) // Split transfers -// No CLEAR_FEATURE/HALT (yet) +// No CLEAR_FEATURE/HALT no EP (yet) +// No aborting transfers. #if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_USBTMC) @@ -156,8 +157,11 @@ void usbtmcd_init(void) { #if USBTMC_CFG_ENABLE_488 if(usbtmcd_app_capabilities.bmIntfcCapabilities488.supportsTrigger) - TU_ASSERT(usbtmcd_app_msg_trigger != NULL,); + TU_ASSERT(&usbtmcd_app_msg_trigger != NULL,); #endif + if(usbtmcd_app_capabilities.bmIntfcCapabilities.supportsIndicatorPulse) + TU_ASSERT(&usbtmcd_app_indicator_pluse != NULL,); + } bool usbtmcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length) @@ -400,8 +404,9 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ return true; // USBTMC Optional Requests case USBTMC_bREQUEST_INDICATOR_PULSE: // Optional - TU_VERIFY(false); - return false; + TU_VERIFY(usbtmcd_app_capabilities.bmIntfcCapabilities.supportsIndicatorPulse); + TU_VERIFY(usbtmcd_app_indicator_pluse(rhport, request)); + return true; #if (USBTMC_CFG_ENABLE_488) // USB488 required requests diff --git a/src/class/usbtmc/usbtmc_device.h b/src/class/usbtmc/usbtmc_device.h index 1246d11d1..09cda7c67 100644 --- a/src/class/usbtmc/usbtmc_device.h +++ b/src/class/usbtmc/usbtmc_device.h @@ -64,8 +64,10 @@ bool usbtmcd_app_msgBulkIn_request(uint8_t rhport, usbtmc_msg_request_dev_dep_in bool usbtmcd_app_msgBulkIn_complete(uint8_t rhport); +TU_ATTR_WEAK bool usbtmcd_app_indicator_pluse(uint8_t rhport, tusb_control_request_t const * msg); + #if (USBTMC_CFG_ENABLE_488) -uint8_t usbtmcd_app_get_stb(uint8_t rhport, usbtmc_status_enum *rspResult); +uint8_t usbtmcd_app_get_stb(uint8_t rhport, uint8_t *rspResult); TU_ATTR_WEAK bool usbtmcd_app_msg_trigger(uint8_t rhport, usbtmc_msg_generic_t* msg); //TU_ATTR_WEAK bool usbtmcd_app_go_to_local(uint8_t rhport); #endif From e53e9bd4f0749e53740c9c33e740998ac202dd8a Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Sat, 14 Sep 2019 21:24:52 -0400 Subject: [PATCH 06/45] Simulate query delay; getting to a point where implementing clear/aborts makes sense. Probably adding too many concurance issues; need to figure out semaphores. --- examples/device/usbtmc/src/main.c | 3 +- examples/device/usbtmc/src/usb_descriptors.c | 6 +- examples/device/usbtmc/src/usbtmc_app.c | 91 ++++++++++++++------ examples/device/usbtmc/src/usbtmc_app.h | 7 ++ src/class/usbtmc/usbtmc_device.c | 20 ++++- src/class/usbtmc/usbtmc_device.h | 5 +- 6 files changed, 97 insertions(+), 35 deletions(-) create mode 100644 examples/device/usbtmc/src/usbtmc_app.h diff --git a/examples/device/usbtmc/src/main.c b/examples/device/usbtmc/src/main.c index 8bc2a8398..1fce48f45 100644 --- a/examples/device/usbtmc/src/main.c +++ b/examples/device/usbtmc/src/main.c @@ -29,7 +29,7 @@ #include "bsp/board.h" #include "tusb.h" - +#include "usbtmc_app.h" //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF PROTYPES //--------------------------------------------------------------------+ @@ -60,6 +60,7 @@ int main(void) { tud_task(); // tinyusb device task led_blinking_task(); + usbtmc_app_task_iter(); } return 0; diff --git a/examples/device/usbtmc/src/usb_descriptors.c b/examples/device/usbtmc/src/usb_descriptors.c index 296636359..9567bcab5 100644 --- a/examples/device/usbtmc/src/usb_descriptors.c +++ b/examples/device/usbtmc/src/usb_descriptors.c @@ -110,10 +110,10 @@ uint8_t const * tud_hid_descriptor_report_cb(void) USBTMC_BULK_DESCRIPTORS(/* OUT = */0x03, /* IN = */ 0x83) #if defined(CFG_TUD_USBTMC_ENABLE_INT_EP) - +// Interrupt endpoint should be 2 bytes on a FS USB link # define USBTMC_DESC(_itfnum) \ USBTMC_DESC_MAIN(_itfnum, /* _epCount = */ 3), \ - USBTMC_INT_DESCRIPTOR(/* INT ep # */ 0x84, /* epMaxSize = */ 64, /* bInterval = */16u ) + USBTMC_INT_DESCRIPTOR(/* INT ep # */ 0x84, /* epMaxSize = */ 2, /* bInterval = */16u ) # define USBTMC_DESC_LEN (USBTMC_IF_DESCRIPTOR_LEN + USBTMC_BULK_DESCRIPTORS_LEN + USBTMC_INT_DESCRIPTOR_LEN) #else @@ -248,7 +248,7 @@ uint16_t const* tud_descriptor_string_cb(uint8_t index) } // first byte is length (including header), second byte is string type - _desc_str[0] = (TUSB_DESC_STRING << 8 ) | (2*chr_count + 2); + _desc_str[0] = (((uint16_t)TUSB_DESC_STRING) << 8 ) | (2u*chr_count + 2u); return _desc_str; } diff --git a/examples/device/usbtmc/src/usbtmc_app.c b/examples/device/usbtmc/src/usbtmc_app.c index 6b72bb360..af97939b9 100644 --- a/examples/device/usbtmc/src/usbtmc_app.c +++ b/examples/device/usbtmc/src/usbtmc_app.c @@ -25,6 +25,7 @@ #include #include "class/usbtmc/usbtmc_device.h" +#include "bsp/board.h" #include "main.h" #if (USBTMC_CFG_ENABLE_488) @@ -65,9 +66,21 @@ usbtmcd_app_capabilities = }; static const char idn[] = "TinyUSB,ModelNumber,SerialNumber,FirmwareVer\n"; -static uint8_t status; -static bool queryReceived = false; +static volatile uint8_t status; +// 0=not query, 1=queried, 2=delay,set(MAV), 3=delay 4=ready? +// (to simulate delay) +static volatile uint16_t queryState = 0; +static volatile uint32_t queryDelayStart; +static volatile uint32_t bulkInStarted; + +static usbtmc_msg_dev_dep_msg_in_header_t rspMsg = { + .bmTransferAttributes = + { + .EOM = 1, + .UsingTermChar = 0 + } +}; bool usbtmcd_app_msgBulkOut_start(uint8_t rhport, usbtmc_msg_request_dev_dep_out const * msgHeader) { @@ -86,7 +99,7 @@ bool usbtmcd_app_msg_data(uint8_t rhport, void *data, size_t len, bool transfer_ (void)rhport; (void)transfer_complete; if(transfer_complete && (len >=4) && !strncasecmp("*idn?",data,4)) { - queryReceived = true; + queryState = 1; } return true; } @@ -98,47 +111,73 @@ bool usbtmcd_app_msgBulkIn_complete(uint8_t rhport) } static uint8_t noQueryMsg[] = "ERR: No query\n"; + bool usbtmcd_app_msgBulkIn_request(uint8_t rhport, usbtmc_msg_request_dev_dep_in const * request) { - usbtmc_msg_dev_dep_msg_in_header_t hdr = { - .header = - { - .MsgID = request->header.MsgID, - .bTag = request->header.bTag, - .bTagInverse = request->header.bTagInverse - }, - .TransferSize = sizeof(idn)-1, - .bmTransferAttributes = - { - .EOM = 1, - .UsingTermChar = 0 - } - }; - if(queryReceived) + rspMsg.header.MsgID = request->header.MsgID, + rspMsg.header.bTag = request->header.bTag, + rspMsg.header.bTagInverse = request->header.bTagInverse; + if(queryState != 0) { - usbtmcd_transmit_dev_msg_data(rhport, &hdr, idn); + TU_ASSERT(bulkInStarted == 0); + bulkInStarted = 1; } else { - hdr.TransferSize = sizeof(noQueryMsg)-1; - usbtmcd_transmit_dev_msg_data(rhport, &hdr, noQueryMsg); + rspMsg.TransferSize = sizeof(noQueryMsg)-1; + usbtmcd_transmit_dev_msg_data(rhport, &rspMsg, noQueryMsg); } - queryReceived = false; + // Always return true indicating not to stall the EP. return true; } +void usbtmc_app_task_iter(void) { + uint8_t const rhport = 0; + + switch(queryState) { + case 1: + queryDelayStart = board_millis(); + queryState = 2; + break; + case 2: + if( (board_millis() - queryDelayStart) > 1000u) { + queryDelayStart = board_millis(); + queryState=3; + status |= 0x10u; // MAV + } + break; + case 3: + if( (board_millis() - queryDelayStart) > 1000u) { + queryState = 4; + } + break; + case 4: // time to transmit; + if(bulkInStarted) { + queryState = 0; + bulkInStarted = 0; + rspMsg.TransferSize = sizeof(idn)-1; + usbtmcd_transmit_dev_msg_data(rhport, &rspMsg, idn); + status &= ~(0x10u); // MAV + } + break; + } +} + // Return status byte, but put the transfer result status code in the rspResult argument. -uint8_t usbtmcd_app_get_stb(uint8_t rhport, uint8_t *rspResult) +uint8_t usbtmcd_app_get_stb(uint8_t rhport, uint8_t *tmcResult) { (void)rhport; - *rspResult = USBTMC_STATUS_SUCCESS; + *tmcResult = USBTMC_STATUS_SUCCESS; // Increment status so that we see different results on each read... - status++; return status; } -bool usbtmcd_app_indicator_pluse(uint8_t rhport, tusb_control_request_t const * msg) +bool usbtmcd_app_indicator_pluse(uint8_t rhport, tusb_control_request_t const * msg, uint8_t *tmcResult) { + (void)rhport; + (void)msg; led_indicator_pulse(); + *tmcResult = USBTMC_STATUS_SUCCESS; + return true; } diff --git a/examples/device/usbtmc/src/usbtmc_app.h b/examples/device/usbtmc/src/usbtmc_app.h new file mode 100644 index 000000000..4de30c2ba --- /dev/null +++ b/examples/device/usbtmc/src/usbtmc_app.h @@ -0,0 +1,7 @@ + +#ifndef USBTMC_APP_H +#define USBTMC_APP_H + +void usbtmc_app_task_iter(void); + +#endif diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index 7bc768a58..db0c95a32 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -379,9 +379,11 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ #if (USBTMC_CFG_ENABLE_488) ushort bTag; #endif - // We only handle class requests. + // We only handle class requests, IN direction. if(request->bmRequestType_bit.type != TUSB_REQ_TYPE_CLASS) + { return false; + } switch(request->bRequest) { @@ -390,27 +392,38 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ case USBTMC_bREQUEST_CHECK_ABORT_BULK_OUT_STATUS: case USBTMC_bREQUEST_INITIATE_ABORT_BULK_IN: case USBTMC_bREQUEST_CHECK_ABORT_BULK_IN_STATUS: + TU_VERIFY(request->bmRequestType == 0xA2); // in,class,EP + TU_VERIFY(false); + break; + case USBTMC_bREQUEST_INITIATE_CLEAR: case USBTMC_bREQUEST_CHECK_CLEAR_STATUS: + TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface TU_VERIFY(false); break; case USBTMC_bREQUEST_GET_CAPABILITIES: - TU_VERIFY(request->bmRequestType == 0xA1); + TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface TU_VERIFY(request->wValue == 0x0000); TU_VERIFY(request->wIndex == usbtmc_state.itf_id); TU_VERIFY(request->wLength == sizeof(usbtmcd_app_capabilities)); TU_VERIFY(tud_control_xfer(rhport, request, (void*)&usbtmcd_app_capabilities, sizeof(usbtmcd_app_capabilities))); return true; // USBTMC Optional Requests + case USBTMC_bREQUEST_INDICATOR_PULSE: // Optional + TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface TU_VERIFY(usbtmcd_app_capabilities.bmIntfcCapabilities.supportsIndicatorPulse); - TU_VERIFY(usbtmcd_app_indicator_pluse(rhport, request)); + uint8_t tmcResult; + TU_VERIFY(usbtmcd_app_indicator_pluse(rhport, request, &tmcResult)); + TU_VERIFY(tud_control_xfer(rhport, request, (void*)&tmcResult, sizeof(tmcResult))); + return true; #if (USBTMC_CFG_ENABLE_488) // USB488 required requests case USBTMC488_bREQUEST_READ_STATUS_BYTE: + TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface bTag = request->wValue & 0x7F; TU_VERIFY(request->bmRequestType == 0xA1); @@ -444,6 +457,7 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ case USBTMC488_bREQUEST_REN_CONTROL: case USBTMC488_bREQUEST_GO_TO_LOCAL: case USBTMC488_bREQUEST_LOCAL_LOCKOUT: + TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface TU_VERIFY(false); return false; #endif diff --git a/src/class/usbtmc/usbtmc_device.h b/src/class/usbtmc/usbtmc_device.h index 09cda7c67..84640b136 100644 --- a/src/class/usbtmc/usbtmc_device.h +++ b/src/class/usbtmc/usbtmc_device.h @@ -64,10 +64,11 @@ bool usbtmcd_app_msgBulkIn_request(uint8_t rhport, usbtmc_msg_request_dev_dep_in bool usbtmcd_app_msgBulkIn_complete(uint8_t rhport); -TU_ATTR_WEAK bool usbtmcd_app_indicator_pluse(uint8_t rhport, tusb_control_request_t const * msg); +// Indicator pulse should be 0.5 to 1.0 seconds long +TU_ATTR_WEAK bool usbtmcd_app_indicator_pluse(uint8_t rhport, tusb_control_request_t const * msg, uint8_t *tmcResult); #if (USBTMC_CFG_ENABLE_488) -uint8_t usbtmcd_app_get_stb(uint8_t rhport, uint8_t *rspResult); +uint8_t usbtmcd_app_get_stb(uint8_t rhport, uint8_t *tmcResult); TU_ATTR_WEAK bool usbtmcd_app_msg_trigger(uint8_t rhport, usbtmc_msg_generic_t* msg); //TU_ATTR_WEAK bool usbtmcd_app_go_to_local(uint8_t rhport); #endif From c755aee7d0c1e2486055e02ac353878d8da3ba59 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Sat, 14 Sep 2019 22:55:42 -0400 Subject: [PATCH 07/45] Clear --- examples/device/usbtmc/src/usbtmc_app.c | 44 +++++--- src/class/usbtmc/usbtmc.h | 94 +++++++++++------ src/class/usbtmc/usbtmc_device.c | 135 +++++++++++++++--------- src/class/usbtmc/usbtmc_device.h | 4 + 4 files changed, 182 insertions(+), 95 deletions(-) diff --git a/examples/device/usbtmc/src/usbtmc_app.c b/examples/device/usbtmc/src/usbtmc_app.c index af97939b9..a41d911d2 100644 --- a/examples/device/usbtmc/src/usbtmc_app.c +++ b/examples/device/usbtmc/src/usbtmc_app.c @@ -97,7 +97,9 @@ bool usbtmcd_app_msg_trigger(uint8_t rhport, usbtmc_msg_generic_t* msg) { bool usbtmcd_app_msg_data(uint8_t rhport, void *data, size_t len, bool transfer_complete) { (void)rhport; - (void)transfer_complete; + + // If transfer isn't finished, we just ignore it (for now) + if(transfer_complete && (len >=4) && !strncasecmp("*idn?",data,4)) { queryState = 1; } @@ -107,26 +109,24 @@ bool usbtmcd_app_msg_data(uint8_t rhport, void *data, size_t len, bool transfer_ bool usbtmcd_app_msgBulkIn_complete(uint8_t rhport) { (void)rhport; + + status &= (uint8_t)~(0x10u); // clear MAV + return true; } -static uint8_t noQueryMsg[] = "ERR: No query\n"; - bool usbtmcd_app_msgBulkIn_request(uint8_t rhport, usbtmc_msg_request_dev_dep_in const * request) { rspMsg.header.MsgID = request->header.MsgID, rspMsg.header.bTag = request->header.bTag, rspMsg.header.bTagInverse = request->header.bTagInverse; - if(queryState != 0) - { - TU_ASSERT(bulkInStarted == 0); - bulkInStarted = 1; - } - else - { - rspMsg.TransferSize = sizeof(noQueryMsg)-1; - usbtmcd_transmit_dev_msg_data(rhport, &rspMsg, noQueryMsg); - } + + TU_ASSERT(bulkInStarted == 0); + bulkInStarted = 1; + + // > If a USBTMC interface receives a Bulk-IN request prior to receiving a USBTMC command message + // that expects a response, the device must NAK the request + // Always return true indicating not to stall the EP. return true; } @@ -157,12 +157,28 @@ void usbtmc_app_task_iter(void) { bulkInStarted = 0; rspMsg.TransferSize = sizeof(idn)-1; usbtmcd_transmit_dev_msg_data(rhport, &rspMsg, idn); - status &= ~(0x10u); // MAV + // MAV is cleared in the transfer complete callback. } break; + default: + TU_ASSERT(false,); + return; } } +bool usbtmcd_app_initiate_clear(uint8_t rhport, uint8_t *tmcResult) { + (void)rhport; + *tmcResult = USBTMC_STATUS_SUCCESS; + return true; +} + +bool usbtmcd_app_get_clear_status(uint8_t rhport, usbtmc_get_clear_status_rsp_t *rsp) { + (void)rhport; + rsp->USBTMC_status = USBTMC_STATUS_SUCCESS; + rsp->bmClear.BulkInFifoBytes = 0u; + return true; +} + // Return status byte, but put the transfer result status code in the rspResult argument. uint8_t usbtmcd_app_get_stb(uint8_t rhport, uint8_t *tmcResult) { diff --git a/src/class/usbtmc/usbtmc.h b/src/class/usbtmc/usbtmc.h index ecc16a315..d24a72cb6 100644 --- a/src/class/usbtmc/usbtmc.h +++ b/src/class/usbtmc/usbtmc.h @@ -73,53 +73,67 @@ typedef struct TU_ATTR_PACKED typedef struct TU_ATTR_PACKED { usbtmc_msg_header_t header ; ///< Header uint32_t TransferSize ; ///< Transfer size; LSB first - struct { - uint8_t EOM : 1 ; ///< EOM set on last byte + struct TU_ATTR_PACKED + { + unsigned int EOM : 1 ; ///< EOM set on last byte } bmTransferAttributes; uint8_t _reserved[3]; } usbtmc_msg_request_dev_dep_out; +TU_VERIFY_STATIC(sizeof(usbtmc_msg_request_dev_dep_out) == 12u, "struct wrong length"); + // Next 8 bytes are message-specific -typedef struct TU_ATTR_PACKED { +typedef struct TU_ATTR_PACKED +{ usbtmc_msg_header_t header ; ///< Header uint32_t TransferSize ; ///< Transfer size; LSB first - struct { - uint8_t : 0; - uint8_t TermCharEnabled : 1 ; ///< "The Bulk-IN transfer must terminate on the specified TermChar."; CAPABILITIES must list TermChar + struct TU_ATTR_PACKED + { + unsigned int TermCharEnabled : 1 ; ///< "The Bulk-IN transfer must terminate on the specified TermChar."; CAPABILITIES must list TermChar } bmTransferAttributes; uint8_t TermChar; uint8_t _reserved[2]; } usbtmc_msg_request_dev_dep_in; +TU_VERIFY_STATIC(sizeof(usbtmc_msg_request_dev_dep_in) == 12u, "struct wrong length"); + /* Bulk-in headers */ typedef struct TU_ATTR_PACKED { usbtmc_msg_header_t header; uint32_t TransferSize; - struct { + struct TU_ATTR_PACKED + { uint8_t EOM: 1; ///< Last byte of transfer is the end of the message uint8_t UsingTermChar: 1; ///< Support TermChar && Request.TermCharEnabled && last char in transfer is TermChar } bmTransferAttributes; uint8_t _reserved[3]; } usbtmc_msg_dev_dep_msg_in_header_t; +TU_VERIFY_STATIC(sizeof(usbtmc_msg_dev_dep_msg_in_header_t) == 12u, "struct wrong length"); /* Unsupported vendor things.... Are these ever used?*/ -typedef struct TU_ATTR_PACKED { +typedef struct TU_ATTR_PACKED +{ usbtmc_msg_header_t header ; ///< Header uint32_t TransferSize ; ///< Transfer size; LSB first uint8_t _reserved[4]; } usbtmc_msg_request_vendor_specific_out; -typedef struct TU_ATTR_PACKED { +TU_VERIFY_STATIC(sizeof(usbtmc_msg_request_vendor_specific_out) == 12u, "struct wrong length"); + +typedef struct TU_ATTR_PACKED +{ usbtmc_msg_header_t header ; ///< Header uint32_t TransferSize ; ///< Transfer size; LSB first uint8_t _reserved[4]; } usbtmc_msg_request_vendor_specific_in; +TU_VERIFY_STATIC(sizeof(usbtmc_msg_request_vendor_specific_in) == 12u, "struct wrong length"); + // Control request type should use tusb_control_request_t /* @@ -187,13 +201,15 @@ typedef struct TU_ATTR_PACKED { uint8_t _reserved; uint16_t bcdUSBTMC; ///< USBTMC_VERSION - struct { - uint8_t listenOnly :1; - uint8_t talkOnly :1; - uint8_t supportsIndicatorPulse :1; + struct TU_ATTR_PACKED + { + unsigned int listenOnly :1; + unsigned int talkOnly :1; + unsigned int supportsIndicatorPulse :1; } bmIntfcCapabilities; - struct { - uint8_t canEndBulkInOnTermChar :1; + struct TU_ATTR_PACKED + { + unsigned int canEndBulkInOnTermChar :1; } bmDevCapabilities; uint8_t _reserved2[6]; uint8_t _reserved3[12]; @@ -201,40 +217,51 @@ typedef struct TU_ATTR_PACKED { TU_VERIFY_STATIC(sizeof(usbtmc_response_capabilities_t) == 0x18, "struct wrong length"); +typedef struct TU_ATTR_PACKED +{ + uint8_t USBTMC_status; + struct TU_ATTR_PACKED + { + unsigned int BulkInFifoBytes :1; + } bmClear; +} usbtmc_get_clear_status_rsp_t; + +TU_VERIFY_STATIC(sizeof(usbtmc_get_clear_status_rsp_t) == 2u, "struct wrong length"); + typedef struct TU_ATTR_PACKED { uint8_t USBTMC_status; ///< usbtmc_status_enum uint8_t _reserved; uint16_t bcdUSBTMC; ///< USBTMC_VERSION - struct + struct TU_ATTR_PACKED { - uint8_t listenOnly :1; - uint8_t talkOnly :1; - uint8_t supportsIndicatorPulse :1; + unsigned int listenOnly :1; + unsigned int talkOnly :1; + unsigned int supportsIndicatorPulse :1; } bmIntfcCapabilities; - struct + struct TU_ATTR_PACKED { - uint8_t canEndBulkInOnTermChar :1; + unsigned int canEndBulkInOnTermChar :1; } bmDevCapabilities; uint8_t _reserved2[6]; uint16_t bcdUSB488; - struct + struct TU_ATTR_PACKED { - uint8_t is488_2 :1; - uint8_t supportsREN_GTL_LLO :1; - uint8_t supportsTrigger :1; + unsigned int is488_2 :1; + unsigned int supportsREN_GTL_LLO :1; + unsigned int supportsTrigger :1; } bmIntfcCapabilities488; - struct + struct TU_ATTR_PACKED { - uint8_t SCPI :1; - uint8_t SR1 :1; - uint8_t RL1 :1; - uint8_t DT1 :1; + unsigned int SCPI :1; + unsigned int SR1 :1; + unsigned int RL1 :1; + unsigned int DT1 :1; } bmDevCapabilities488; uint8_t _reserved3[8]; } usbtmc_response_capabilities_488_t; @@ -253,14 +280,15 @@ TU_VERIFY_STATIC(sizeof(usbtmc_read_stb_rsp_488_t) == 3u, "struct wrong length") typedef struct TU_ATTR_PACKET { union { - struct { - uint8_t bTag : 7; - uint8_t one : 1; + struct TU_ATTR_PACKED { + unsigned int bTag : 7; + unsigned int one : 1; } bNotify1Struct; uint8_t bNotify1; }; uint8_t StatusByte; } usbtmc_read_stb_interrupt_488_t; + TU_VERIFY_STATIC(sizeof(usbtmc_read_stb_interrupt_488_t) == 2u, "struct wrong length"); #endif diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index db0c95a32..7264125bb 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -170,6 +170,9 @@ bool usbtmcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16 uint8_t const * p_desc; uint8_t found_endpoints = 0; + + usbtmcd_reset(rhport); + // Perhaps there are other application specific class drivers, so don't assert here. if( itf_desc->bInterfaceClass != USBTMC_APP_CLASS) return false; @@ -232,6 +235,12 @@ bool usbtmcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16 void usbtmcd_reset(uint8_t rhport) { // FIXME: Do endpoints need to be closed here? + usbtmc_state.state = STATE_IDLE; + usbtmc_state.itf_id = 0xFF; + usbtmc_state.ep_bulk_in = 0; + usbtmc_state.ep_bulk_out = 0; + usbtmc_state.ep_int_in = 0; + (void)rhport; } @@ -376,15 +385,19 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * request) { + uint8_t tmcStatusCode = USBTMC_STATUS_FAILED; #if (USBTMC_CFG_ENABLE_488) ushort bTag; #endif // We only handle class requests, IN direction. + // (for now) if(request->bmRequestType_bit.type != TUSB_REQ_TYPE_CLASS) { return false; } + // Verification that we own the interface is unneeded since it's been routed to us specifically. + switch(request->bRequest) { // USBTMC required requests @@ -392,74 +405,100 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ case USBTMC_bREQUEST_CHECK_ABORT_BULK_OUT_STATUS: case USBTMC_bREQUEST_INITIATE_ABORT_BULK_IN: case USBTMC_bREQUEST_CHECK_ABORT_BULK_IN_STATUS: - TU_VERIFY(request->bmRequestType == 0xA2); // in,class,EP - TU_VERIFY(false); - break; + { + TU_VERIFY(request->bmRequestType == 0xA2); // in,class,EP + TU_VERIFY(request->wLength == 1u); + tmcStatusCode = USBTMC_STATUS_FAILED; + usbd_edpt_xfer(rhport, usbtmc_state.ep_int_in, (void*)&tmcStatusCode,sizeof(tmcStatusCode)); + return true; + } case USBTMC_bREQUEST_INITIATE_CLEAR: + { + TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface + TU_VERIFY(request->wLength == sizeof(tmcStatusCode)); + // After receiving an INITIATE_CLEAR request, the device must Halt the Bulk-OUT endpoint, queue the + // control endpoint response shown in Table 31, and clear all input buffers and output buffers. + usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out); + TU_VERIFY(usbtmcd_app_initiate_clear(rhport, &tmcStatusCode)); + TU_VERIFY(usbd_edpt_xfer(rhport, usbtmc_state.ep_int_in, (void*)&tmcStatusCode,sizeof(tmcStatusCode))); + return true; + } + case USBTMC_bREQUEST_CHECK_CLEAR_STATUS: - TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface - TU_VERIFY(false); - break; + { + usbtmc_get_clear_status_rsp_t clearStatusRsp = {0}; + TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface + TU_VERIFY(request->wLength == sizeof(clearStatusRsp)); + TU_VERIFY(usbtmcd_app_get_clear_status(rhport, &clearStatusRsp)); + + TU_VERIFY(usbd_edpt_xfer(rhport, usbtmc_state.ep_int_in, (void*)&clearStatusRsp,sizeof(clearStatusRsp))); + return true; + } case USBTMC_bREQUEST_GET_CAPABILITIES: - TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface - TU_VERIFY(request->wValue == 0x0000); - TU_VERIFY(request->wIndex == usbtmc_state.itf_id); - TU_VERIFY(request->wLength == sizeof(usbtmcd_app_capabilities)); - TU_VERIFY(tud_control_xfer(rhport, request, (void*)&usbtmcd_app_capabilities, sizeof(usbtmcd_app_capabilities))); - return true; + { + TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface + TU_VERIFY(request->wLength == sizeof(usbtmcd_app_capabilities)); + TU_VERIFY(tud_control_xfer(rhport, request, (void*)&usbtmcd_app_capabilities, sizeof(usbtmcd_app_capabilities))); + return true; + } // USBTMC Optional Requests case USBTMC_bREQUEST_INDICATOR_PULSE: // Optional - TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface - TU_VERIFY(usbtmcd_app_capabilities.bmIntfcCapabilities.supportsIndicatorPulse); - uint8_t tmcResult; - TU_VERIFY(usbtmcd_app_indicator_pluse(rhport, request, &tmcResult)); - TU_VERIFY(tud_control_xfer(rhport, request, (void*)&tmcResult, sizeof(tmcResult))); - - return true; - + { + TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface + TU_VERIFY(request->wLength == sizeof(tmcStatusCode)); + TU_VERIFY(usbtmcd_app_capabilities.bmIntfcCapabilities.supportsIndicatorPulse); + TU_VERIFY(usbtmcd_app_indicator_pluse(rhport, request, &tmcStatusCode)); + TU_VERIFY(tud_control_xfer(rhport, request, (void*)&tmcStatusCode, sizeof(tmcStatusCode))); + return true; + } #if (USBTMC_CFG_ENABLE_488) + // USB488 required requests case USBTMC488_bREQUEST_READ_STATUS_BYTE: - TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface - - bTag = request->wValue & 0x7F; - TU_VERIFY(request->bmRequestType == 0xA1); - TU_VERIFY((request->wValue & (~0x7F)) == 0u); // Other bits are required to be zero - TU_VERIFY(bTag >= 0x02 && bTag <= 127); - TU_VERIFY(request->wIndex == usbtmc_state.itf_id); - TU_VERIFY(request->wLength == 0x0003); - usbtmc_read_stb_rsp_488_t rsp; - rsp.bTag = (uint8_t)bTag; - if(usbtmc_state.ep_int_in != 0) { - rsp.USBTMC_status = USBTMC_STATUS_SUCCESS; - rsp.statusByte = 0x00; // Use interrupt endpoint, instead. + usbtmc_read_stb_rsp_488_t rsp; + TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface + TU_VERIFY(request->wLength == sizeof(rsp)); // in,class,interface - usbtmc_read_stb_interrupt_488_t intMsg = + bTag = request->wValue & 0x7F; + TU_VERIFY(request->bmRequestType == 0xA1); + TU_VERIFY((request->wValue & (~0x7F)) == 0u); // Other bits are required to be zero + TU_VERIFY(bTag >= 0x02 && bTag <= 127); + TU_VERIFY(request->wIndex == usbtmc_state.itf_id); + TU_VERIFY(request->wLength == 0x0003); + rsp.bTag = (uint8_t)bTag; + if(usbtmc_state.ep_int_in != 0) { - .bNotify1 = (uint8_t)(0x80 | bTag), - .StatusByte = usbtmcd_app_get_stb(rhport, &(rsp.USBTMC_status)) - }; - usbd_edpt_xfer(rhport, usbtmc_state.ep_int_in, (void*)&intMsg,sizeof(intMsg)); + rsp.USBTMC_status = USBTMC_STATUS_SUCCESS; + rsp.statusByte = 0x00; // Use interrupt endpoint, instead. - } - else - { - rsp.statusByte = usbtmcd_app_get_stb(rhport, &(rsp.USBTMC_status)); - } - TU_VERIFY(tud_control_xfer(rhport, request, (void*)&rsp, sizeof(rsp))); - return true; + usbtmc_read_stb_interrupt_488_t intMsg = + { + .bNotify1 = (uint8_t)(0x80 | bTag), + .StatusByte = usbtmcd_app_get_stb(rhport, &(rsp.USBTMC_status)) + }; + usbd_edpt_xfer(rhport, usbtmc_state.ep_int_in, (void*)&intMsg,sizeof(intMsg)); + } + else + { + rsp.statusByte = usbtmcd_app_get_stb(rhport, &(rsp.USBTMC_status)); + } + TU_VERIFY(tud_control_xfer(rhport, request, (void*)&rsp, sizeof(rsp))); + return true; + } // USB488 optional requests case USBTMC488_bREQUEST_REN_CONTROL: case USBTMC488_bREQUEST_GO_TO_LOCAL: case USBTMC488_bREQUEST_LOCAL_LOCKOUT: - TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface - TU_VERIFY(false); - return false; + { + TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface + TU_VERIFY(false); + return false; + } #endif default: diff --git a/src/class/usbtmc/usbtmc_device.h b/src/class/usbtmc/usbtmc_device.h index 84640b136..702f595e6 100644 --- a/src/class/usbtmc/usbtmc_device.h +++ b/src/class/usbtmc/usbtmc_device.h @@ -64,6 +64,10 @@ bool usbtmcd_app_msgBulkIn_request(uint8_t rhport, usbtmc_msg_request_dev_dep_in bool usbtmcd_app_msgBulkIn_complete(uint8_t rhport); +bool usbtmcd_app_initiate_clear(uint8_t rhport, uint8_t *tmcResult); + +bool usbtmcd_app_get_clear_status(uint8_t rhport, usbtmc_get_clear_status_rsp_t *rsp); + // Indicator pulse should be 0.5 to 1.0 seconds long TU_ATTR_WEAK bool usbtmcd_app_indicator_pluse(uint8_t rhport, tusb_control_request_t const * msg, uint8_t *tmcResult); From e234998c6c8eeedd3ae2e28a3015afd6e910952d Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Sun, 15 Sep 2019 14:57:02 -0400 Subject: [PATCH 08/45] More proper handling of clear. --- examples/device/usbtmc/src/usbtmc_app.c | 23 +++++++++- src/class/usbtmc/usbtmc.h | 8 ++-- src/class/usbtmc/usbtmc_device.c | 58 ++++++++++++++++++------- src/class/usbtmc/usbtmc_device.h | 10 ++--- 4 files changed, 71 insertions(+), 28 deletions(-) diff --git a/examples/device/usbtmc/src/usbtmc_app.c b/examples/device/usbtmc/src/usbtmc_app.c index a41d911d2..7328b6598 100644 --- a/examples/device/usbtmc/src/usbtmc_app.c +++ b/examples/device/usbtmc/src/usbtmc_app.c @@ -117,6 +117,7 @@ bool usbtmcd_app_msgBulkIn_complete(uint8_t rhport) bool usbtmcd_app_msgBulkIn_request(uint8_t rhport, usbtmc_msg_request_dev_dep_in const * request) { + (void)rhport; rspMsg.header.MsgID = request->header.MsgID, rspMsg.header.bTag = request->header.bTag, rspMsg.header.bTagInverse = request->header.bTagInverse; @@ -135,6 +136,8 @@ void usbtmc_app_task_iter(void) { uint8_t const rhport = 0; switch(queryState) { + case 0: + break; case 1: queryDelayStart = board_millis(); queryState = 2; @@ -166,18 +169,34 @@ void usbtmc_app_task_iter(void) { } } -bool usbtmcd_app_initiate_clear(uint8_t rhport, uint8_t *tmcResult) { +bool usbtmcd_app_initiate_clear(uint8_t rhport, uint8_t *tmcResult) +{ (void)rhport; *tmcResult = USBTMC_STATUS_SUCCESS; + queryState = 0; + bulkInStarted = false; + status = 0; return true; } -bool usbtmcd_app_get_clear_status(uint8_t rhport, usbtmc_get_clear_status_rsp_t *rsp) { +bool usbtmcd_app_get_clear_status(uint8_t rhport, usbtmc_get_clear_status_rsp_t *rsp) +{ (void)rhport; + queryState = 0; + bulkInStarted = false; + status = 0; rsp->USBTMC_status = USBTMC_STATUS_SUCCESS; rsp->bmClear.BulkInFifoBytes = 0u; return true; } +void usmtmcd_app_bulkIn_clearFeature(uint8_t rhport) +{ + (void)rhport; +} +void usmtmcd_app_bulkOut_clearFeature(uint8_t rhport) +{ + (void)rhport; +} // Return status byte, but put the transfer result status code in the rspResult argument. uint8_t usbtmcd_app_get_stb(uint8_t rhport, uint8_t *tmcResult) diff --git a/src/class/usbtmc/usbtmc.h b/src/class/usbtmc/usbtmc.h index d24a72cb6..2e4999c2d 100644 --- a/src/class/usbtmc/usbtmc.h +++ b/src/class/usbtmc/usbtmc.h @@ -279,13 +279,11 @@ TU_VERIFY_STATIC(sizeof(usbtmc_read_stb_rsp_488_t) == 3u, "struct wrong length") typedef struct TU_ATTR_PACKET { - union { - struct TU_ATTR_PACKED { + struct TU_ATTR_PACKED + { unsigned int bTag : 7; unsigned int one : 1; - } bNotify1Struct; - uint8_t bNotify1; - }; + } bNotify1; uint8_t StatusByte; } usbtmc_read_stb_interrupt_488_t; diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index 7264125bb..cf8a5069a 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -115,18 +115,19 @@ bool usbtmcd_transmit_dev_msg_data( const void *data) { TU_ASSERT(usbtmc_state.state == STATE_TX_REQUESTED); +#ifndef NDEBUG TU_ASSERT(hdr->TransferSize > 0u); - if(hdr->bmTransferAttributes.UsingTermChar) { TU_ASSERT(usbtmcd_app_capabilities.bmDevCapabilities.canEndBulkInOnTermChar); TU_ASSERT(termCharRequested); TU_ASSERT(((uint8_t*)data)[hdr->TransferSize-1] == termChar); } +#endif // Copy in the header memcpy(usbtmc_state.ep_bulk_in_buf, hdr, sizeof(*hdr)); - uint packetLen = sizeof(*hdr); + size_t packetLen = sizeof(*hdr); // Single-packet transfer if((packetLen + hdr->TransferSize) <= USBTMCD_MAX_PACKET_SIZE) { @@ -155,13 +156,14 @@ bool usbtmcd_transmit_dev_msg_data( void usbtmcd_init(void) { -#if USBTMC_CFG_ENABLE_488 - if(usbtmcd_app_capabilities.bmIntfcCapabilities488.supportsTrigger) - TU_ASSERT(&usbtmcd_app_msg_trigger != NULL,); +#ifndef NDEBUG +# if USBTMC_CFG_ENABLE_488 + if(usbtmcd_app_capabilities.bmIntfcCapabilities488.supportsTrigger) + TU_ASSERT(&usbtmcd_app_msg_trigger != NULL,); +# endif + if(usbtmcd_app_capabilities.bmIntfcCapabilities.supportsIndicatorPulse) + TU_ASSERT(&usbtmcd_app_indicator_pluse != NULL,); #endif - if(usbtmcd_app_capabilities.bmIntfcCapabilities.supportsIndicatorPulse) - TU_ASSERT(&usbtmcd_app_indicator_pluse != NULL,); - } bool usbtmcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length) @@ -204,8 +206,10 @@ bool usbtmcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16 break; case TUSB_XFER_INTERRUPT: +#ifndef NDEBUG TU_ASSERT(tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN); TU_ASSERT(usbtmc_state.ep_int_in == 0); +#endif usbtmc_state.ep_int_in = ep_desc->bEndpointAddress; break; default: @@ -219,6 +223,7 @@ bool usbtmcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16 } // bulk endpoints are required, but interrupt IN is optional +#ifndef NDEBUG TU_ASSERT(usbtmc_state.ep_bulk_in != 0); TU_ASSERT(usbtmc_state.ep_bulk_out != 0); if (itf_desc->bNumEndpoints == 2) { @@ -228,6 +233,7 @@ bool usbtmcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16 { TU_ASSERT(usbtmc_state.ep_int_in != 0); } +#endif TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, 64)); return true; @@ -363,7 +369,7 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint } else // short packet { - uint packetLen = usbtmc_state.transfer_size_remaining; + size_t packetLen = usbtmc_state.transfer_size_remaining; memcpy(usbtmc_state.ep_bulk_in_buf, usbtmc_state.devInBuffer, usbtmc_state.transfer_size_remaining); while((packetLen % 4) != 0) { @@ -387,8 +393,25 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ uint8_t tmcStatusCode = USBTMC_STATUS_FAILED; #if (USBTMC_CFG_ENABLE_488) - ushort bTag; + uint8_t bTag; #endif + + if((request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD) && + (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_ENDPOINT) && + (request->bRequest == TUSB_REQ_CLEAR_FEATURE) && + (request->wValue == TUSB_REQ_FEATURE_EDPT_HALT)) + { + if((request->wIndex) == usbtmc_state.ep_bulk_out) + { + usmtmcd_app_bulkOut_clearFeature(rhport); + } + else if ((request->wIndex) == usbtmc_state.ep_bulk_in) + { + usmtmcd_app_bulkIn_clearFeature(rhport); + } + return false; // We want USBD core to handle sending the status response, and clear the stall condition + } + // We only handle class requests, IN direction. // (for now) if(request->bmRequestType_bit.type != TUSB_REQ_TYPE_CLASS) @@ -409,7 +432,7 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ TU_VERIFY(request->bmRequestType == 0xA2); // in,class,EP TU_VERIFY(request->wLength == 1u); tmcStatusCode = USBTMC_STATUS_FAILED; - usbd_edpt_xfer(rhport, usbtmc_state.ep_int_in, (void*)&tmcStatusCode,sizeof(tmcStatusCode)); + usbd_edpt_xfer(rhport, 0u, (void*)&tmcStatusCode,sizeof(tmcStatusCode)); return true; } @@ -421,7 +444,7 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ // control endpoint response shown in Table 31, and clear all input buffers and output buffers. usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out); TU_VERIFY(usbtmcd_app_initiate_clear(rhport, &tmcStatusCode)); - TU_VERIFY(usbd_edpt_xfer(rhport, usbtmc_state.ep_int_in, (void*)&tmcStatusCode,sizeof(tmcStatusCode))); + TU_VERIFY(tud_control_xfer(rhport, request, (void*)&tmcStatusCode,sizeof(tmcStatusCode))); return true; } @@ -432,7 +455,7 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ TU_VERIFY(request->wLength == sizeof(clearStatusRsp)); TU_VERIFY(usbtmcd_app_get_clear_status(rhport, &clearStatusRsp)); - TU_VERIFY(usbd_edpt_xfer(rhport, usbtmc_state.ep_int_in, (void*)&clearStatusRsp,sizeof(clearStatusRsp))); + TU_VERIFY(tud_control_xfer(rhport, request, (void*)&clearStatusRsp,sizeof(clearStatusRsp))); return true; } @@ -477,11 +500,13 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ usbtmc_read_stb_interrupt_488_t intMsg = { - .bNotify1 = (uint8_t)(0x80 | bTag), - .StatusByte = usbtmcd_app_get_stb(rhport, &(rsp.USBTMC_status)) + .bNotify1 = { + .one = 1, + .bTag = bTag & 0x7Fu, + }, + .StatusByte = usbtmcd_app_get_stb(rhport, &(rsp.USBTMC_status)) }; usbd_edpt_xfer(rhport, usbtmc_state.ep_int_in, (void*)&intMsg,sizeof(intMsg)); - } else { @@ -503,6 +528,7 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ default: TU_VERIFY(false); + return false; } TU_VERIFY(false); } diff --git a/src/class/usbtmc/usbtmc_device.h b/src/class/usbtmc/usbtmc_device.h index 702f595e6..35d4da438 100644 --- a/src/class/usbtmc/usbtmc_device.h +++ b/src/class/usbtmc/usbtmc_device.h @@ -56,13 +56,13 @@ extern usbtmc_response_capabilities_t const usbtmcd_app_capabilities; #endif bool usbtmcd_app_msgBulkOut_start(uint8_t rhport, usbtmc_msg_request_dev_dep_out const * msgHeader); - // transfer_complete does not imply that a message is complete. bool usbtmcd_app_msg_data(uint8_t rhport, void *data, size_t len, bool transfer_complete); +void usmtmcd_app_bulkOut_clearFeature(uint8_t rhport); // Notice to clear and abort the pending BULK out transfer bool usbtmcd_app_msgBulkIn_request(uint8_t rhport, usbtmc_msg_request_dev_dep_in const * request); - bool usbtmcd_app_msgBulkIn_complete(uint8_t rhport); +void usmtmcd_app_bulkIn_clearFeature(uint8_t rhport); // Notice to clear and abort the pending BULK out transfer bool usbtmcd_app_initiate_clear(uint8_t rhport, uint8_t *tmcResult); @@ -104,10 +104,10 @@ void usbtmcd_init(void); *************************************************************/ #define USBTMC_APP_CLASS TUSB_CLASS_APPLICATION_SPECIFIC -#define USBTMC_APP_SUBCLASS 0x03 +#define USBTMC_APP_SUBCLASS 0x03u -#define USBTMC_PROTOCOL_STD 0x00 -#define USBTMC_PROTOCOL_USB488 0x01 +#define USBTMC_PROTOCOL_STD 0x00u +#define USBTMC_PROTOCOL_USB488 0x01u // Interface number, number of endpoints, EP string index, USB_TMC_PROTOCOL*, bulk-out endpoint ID, // bulk-in endpoint ID From 45871001e6d18503f05733ae770538e622313584 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Tue, 17 Sep 2019 13:24:43 -0400 Subject: [PATCH 09/45] Changes1... --- src/class/usbtmc/usbtmc.h | 9 ++ src/class/usbtmc/usbtmc_device.c | 268 ++++++++++++++++++++++++------- 2 files changed, 220 insertions(+), 57 deletions(-) diff --git a/src/class/usbtmc/usbtmc.h b/src/class/usbtmc/usbtmc.h index 2e4999c2d..6893c3743 100644 --- a/src/class/usbtmc/usbtmc.h +++ b/src/class/usbtmc/usbtmc.h @@ -228,6 +228,15 @@ typedef struct TU_ATTR_PACKED TU_VERIFY_STATIC(sizeof(usbtmc_get_clear_status_rsp_t) == 2u, "struct wrong length"); +// Used for both abort bulk IN and bulk OUT +typedef struct TU_ATTR_PACKED +{ + uint8_t USBTMC_status; + uint8_t bTag; +} usbtmc_initiate_abort_rsp_t; + +TU_VERIFY_STATIC(sizeof(usbtmc_get_clear_status_rsp_t) == 2u, "struct wrong length"); + typedef struct TU_ATTR_PACKED { uint8_t USBTMC_status; ///< usbtmc_status_enum diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index cf8a5069a..6d562641e 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -8,7 +8,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2019 N Conrad + * Copyright (c) 2019 Nathan Conrad * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -33,31 +33,53 @@ #include "tusb_option.h" -// We don't do any cross-task anything here (everything is in tud or interrupt context). -// You must ensure thread safety in your own app. +// Synchronization is needed in some spots. +// These functions should NOT be called from interrupts. + +/* The library is designed that its functions can be called by any user task, with need for + * additional locking. In the case of "no OS", this task is never preempted other than by + * interrupts, and the USBTMC code isn't called by interrupts, so all is OK. In the case + * of an OS, this class driver uses the OSAL to perform locking. The code uses a single lock + * and does not call outside of this class with a lock held, so deadlocks won't happen. + * + * This module's application-facing functions are not reentrant. The application must + * only call them from a single thread (or implement its own locking). + */ -//Limitations (not planned to be implemented): -// "vendor-specific" commands are not handled +//Limitations: +// "vendor-specific" commands are not handled. // Dealing with "termchar" must be handled by the application layer, // though additional error checking is does in this module. +// talkOnly and listenOnly are NOT supported. They're no permitted +// in USB488, anyway. + +/* Supported: + * + * Notification pulse + * Trigger + * Read status byte (both by interrupt endpoint and control message) + * + */ + // TODO: // USBTMC 3.2.2 error conditions not strictly followed // No local lock-out, REN, or GTL. // Cannot handle clear. -// Not all "capabilities" supported // Clear message available status byte at the correct time? (488 4.3.1.3) -// Split transfers +// Abort bulk in/out // No CLEAR_FEATURE/HALT no EP (yet) -// No aborting transfers. #if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_USBTMC) +#include #include "usbtmc.h" #include "usbtmc_device.h" #include "device/dcd.h" #include "device/usbd.h" +#include "uart_util.h" +static char logMsg[150]; // FIXME: I shouldn't need to include _pvt headers. #include "device/usbd_pvt.h" @@ -70,21 +92,31 @@ typedef enum STATE_IDLE, STATE_RCV, STATE_TX_REQUESTED, - STATE_TX_INITIATED + STATE_TX_INITIATED, + STATE_CLEARING, + STATE_ABORTING_BULK_IN, + STATE_ABORTING_BULK_OUT, + STATE_NUM_STATES } usbtmcd_state_enum; typedef struct { - usbtmcd_state_enum state; + volatile usbtmcd_state_enum state; + uint8_t itf_id; uint8_t ep_bulk_in; uint8_t ep_bulk_out; uint8_t ep_int_in; - uint8_t ep_bulk_in_buf[64]; - uint8_t ep_bulk_out_buf[64]; - uint8_t lastTag; + // IN buffer is only used for first packet, not the remainder + // in order to deal with prepending header + uint8_t ep_bulk_in_buf[USBTMCD_MAX_PACKET_SIZE]; + // OUT buffer receives one packet at a time + uint8_t ep_bulk_out_buf[USBTMCD_MAX_PACKET_SIZE]; + uint32_t transfer_size_remaining; // also used for requested length for bulk IN. + + uint8_t lastBulkOutTag; // used for aborts (mostly) + uint8_t lastBulkInTag; // used for aborts (mostly) - uint32_t transfer_size_remaining; uint8_t const * devInBuffer; } usbtmc_interface_state_t; @@ -97,39 +129,63 @@ static usbtmc_interface_state_t usbtmc_state = .ep_int_in = 0 }; -// We want everything to fit nicely in a single packet, so lets require EP size >32 -// I'm not sure if this is really necessary, though. +// We need all headers to fit in a single packet in this implementation. TU_VERIFY_STATIC(USBTMCD_MAX_PACKET_SIZE >= 32u,"USBTMC dev EP packet size too small"); - +TU_VERIFY_STATIC( + (sizeof(usbtmc_state.ep_bulk_in_buf) % USBTMCD_MAX_PACKET_SIZE) == 0, + "packet buffer must be a multiple of the packet size"); static bool handle_devMsgOutStart(uint8_t rhport, void *data, size_t len); static bool handle_devMsgOut(uint8_t rhport, void *data, size_t len, size_t packetLen); + +osal_mutex_def_t usbtmcLockBuffer; +static osal_mutex_t usbtmcLock; + +// Our own private lock, mostly for the state variable. +#define criticalEnter() do {osal_mutex_lock(usbtmcLock,OSAL_TIMEOUT_WAIT_FOREVER); } while (0) +#define criticalLeave() do {osal_mutex_unlock(usbtmcLock); } while (0) + // called from app // We keep a reference to the buffer, so it MUST not change until the app is // notified that the transfer is complete. // length of data is specified in the hdr. + +// We can't just send the whole thing at once because we need to concatanate the +// header with the data. bool usbtmcd_transmit_dev_msg_data( uint8_t rhport, - usbtmc_msg_dev_dep_msg_in_header_t const * hdr, - const void *data) + const void * data, size_t len, + bool usingTermChar) { - TU_ASSERT(usbtmc_state.state == STATE_TX_REQUESTED); + const unsigned int txBufLen = sizeof(usbtmc_state.ep_bulk_in_buf); + #ifndef NDEBUG - TU_ASSERT(hdr->TransferSize > 0u); - if(hdr->bmTransferAttributes.UsingTermChar) + TU_ASSERT(len > 0u); + TU_ASSERT(len <= usbtmc_state.transfer_size_remaining); + if(usingTermChar) { TU_ASSERT(usbtmcd_app_capabilities.bmDevCapabilities.canEndBulkInOnTermChar); TU_ASSERT(termCharRequested); - TU_ASSERT(((uint8_t*)data)[hdr->TransferSize-1] == termChar); + TU_ASSERT(((uint8_t*)data)[len-1] == termChar); } #endif + TU_VERIFY(usbtmc_state.state == STATE_TX_REQUESTED); + usbtmc_msg_dev_dep_msg_in_header_t *hdr = (usbtmc_msg_dev_dep_msg_in_header_t*)usbtmc_state.ep_bulk_in_buf; + memset(hdr, 0x00, sizeof(*hdr)); + hdr->header.MsgID = USBTMC_MSGID_DEV_DEP_MSG_IN; + hdr->header.bTag = usbtmc_state.lastBulkInTag; + hdr->header.bTagInverse = (uint8_t)~(usbtmc_state.lastBulkInTag); + hdr->TransferSize = len; + hdr->bmTransferAttributes.EOM = 1u; + hdr->bmTransferAttributes.UsingTermChar = usingTermChar; + // Copy in the header - memcpy(usbtmc_state.ep_bulk_in_buf, hdr, sizeof(*hdr)); size_t packetLen = sizeof(*hdr); - // Single-packet transfer - if((packetLen + hdr->TransferSize) <= USBTMCD_MAX_PACKET_SIZE) + + // If it fits in a single trasnmission: + if((packetLen + hdr->TransferSize) <= txBufLen) { memcpy((uint8_t*)(usbtmc_state.ep_bulk_in_buf) + packetLen, data, hdr->TransferSize); packetLen = (uint16_t)(packetLen+ hdr->TransferSize); @@ -142,15 +198,23 @@ bool usbtmcd_transmit_dev_msg_data( usbtmc_state.transfer_size_remaining = 0; usbtmc_state.devInBuffer = NULL; } - else + else /* partial packet */ { - memcpy((uint8_t*)(usbtmc_state.ep_bulk_in_buf) + packetLen, data, USBTMCD_MAX_PACKET_SIZE - packetLen); - usbtmc_state.transfer_size_remaining = hdr->TransferSize - (USBTMCD_MAX_PACKET_SIZE - packetLen); - usbtmc_state.devInBuffer += (USBTMCD_MAX_PACKET_SIZE - packetLen); - packetLen = USBTMCD_MAX_PACKET_SIZE; + memcpy((uint8_t*)(usbtmc_state.ep_bulk_in_buf) + packetLen, data, txBufLen - packetLen); + usbtmc_state.devInBuffer += txBufLen - packetLen; + usbtmc_state.transfer_size_remaining = hdr->TransferSize - (txBufLen - packetLen); + packetLen = txBufLen; } - usbtmc_state.state = STATE_TX_INITIATED; - TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf,(uint16_t)packetLen)); + + + criticalEnter(); + { + TU_VERIFY(usbtmc_state.state == STATE_TX_REQUESTED); + usbtmc_state.state = STATE_TX_INITIATED; + } + criticalLeave(); + + TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf, (uint16_t)packetLen)); return true; } @@ -158,12 +222,17 @@ void usbtmcd_init(void) { #ifndef NDEBUG # if USBTMC_CFG_ENABLE_488 - if(usbtmcd_app_capabilities.bmIntfcCapabilities488.supportsTrigger) - TU_ASSERT(&usbtmcd_app_msg_trigger != NULL,); + if(usbtmcd_app_capabilities.bmIntfcCapabilities488.supportsTrigger) + TU_ASSERT(&usbtmcd_app_msg_trigger != NULL,); + // Per USB488 spec: table 8 + TU_ASSERT(!usbtmcd_app_capabilities.bmIntfcCapabilities.listenOnly,); + TU_ASSERT(!usbtmcd_app_capabilities.bmIntfcCapabilities.talkOnly,); # endif if(usbtmcd_app_capabilities.bmIntfcCapabilities.supportsIndicatorPulse) TU_ASSERT(&usbtmcd_app_indicator_pluse != NULL,); #endif + + usbtmcLock = osal_mutex_create(&usbtmcLockBuffer); } bool usbtmcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length) @@ -226,10 +295,17 @@ bool usbtmcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16 #ifndef NDEBUG TU_ASSERT(usbtmc_state.ep_bulk_in != 0); TU_ASSERT(usbtmc_state.ep_bulk_out != 0); - if (itf_desc->bNumEndpoints == 2) { + if (itf_desc->bNumEndpoints == 2) + { TU_ASSERT(usbtmc_state.ep_int_in == 0); } - else if (itf_desc->bNumEndpoints == 2) + else if (itf_desc->bNumEndpoints == 3) + { + TU_ASSERT(usbtmc_state.ep_int_in != 0); + } + + if(usbtmcd_app_capabilities.bmIntfcCapabilities488.is488_2 || + usbtmcd_app_capabilities.bmDevCapabilities488.SR1) { TU_ASSERT(usbtmc_state.ep_int_in != 0); } @@ -286,12 +362,22 @@ static bool handle_devMsgIn(uint8_t rhport, void *data, size_t len) { TU_VERIFY(len == sizeof(usbtmc_msg_request_dev_dep_in)); usbtmc_msg_request_dev_dep_in *msg = (usbtmc_msg_request_dev_dep_in*)data; - TU_VERIFY(usbtmc_state.state == STATE_IDLE); - usbtmc_state.state = STATE_TX_REQUESTED; - usbtmc_state.transfer_size_remaining = msg->TransferSize; + + sprintf(logMsg," handle_devMsgIn len=%ul\r\n",len); + uart_tx_str_sync(logMsg); + + criticalEnter(); + { + TU_VERIFY(usbtmc_state.state == STATE_IDLE); + usbtmc_state.state = STATE_TX_REQUESTED; + usbtmc_state.lastBulkInTag = msg->header.bTag; + usbtmc_state.transfer_size_remaining = msg->TransferSize; + } + criticalLeave(); termCharRequested = msg->bmTransferAttributes.TermCharEnabled; termChar = msg->TermChar; + if(termCharRequested) TU_VERIFY(usbtmcd_app_capabilities.bmDevCapabilities.canEndBulkInOnTermChar); @@ -302,8 +388,17 @@ static bool handle_devMsgIn(uint8_t rhport, void *data, size_t len) bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { TU_VERIFY(result == XFER_RESULT_SUCCESS); + uart_tx_str_sync("USBTMC Xfer CB" ); + sprintf(logMsg," STATE=%lu ", (uint32_t)usbtmc_state.state); + uart_tx_str_sync(logMsg); + + if(usbtmc_state.state == STATE_CLEARING) { + return true; /* I think we can ignore everything here */ + } + if(ep_addr == usbtmc_state.ep_bulk_out) { + uart_tx_str_sync("OUT"); switch(usbtmc_state.state) { case STATE_IDLE: @@ -312,15 +407,19 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint uint8_t invInvTag = (uint8_t)~(msg->header.bTagInverse); TU_VERIFY(msg->header.bTag == invInvTag); TU_VERIFY(msg->header.bTag != 0x00); - usbtmc_state.lastTag = msg->header.bTag; + + sprintf(logMsg," type=%lu\r\n",(uint32_t)msg->header.MsgID); + uart_tx_str_sync(logMsg); switch(msg->header.MsgID) { case USBTMC_MSGID_DEV_DEP_MSG_OUT: TU_VERIFY(handle_devMsgOutStart(rhport, msg, xferred_bytes)); TU_VERIFY(usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, USBTMCD_MAX_PACKET_SIZE)); + usbtmc_state.lastBulkOutTag = msg->header.bTag; break; case USBTMC_MSGID_DEV_DEP_MSG_IN: + uart_tx_sync("Handling msg in req\r\n", 21); TU_VERIFY(handle_devMsgIn(rhport, msg, xferred_bytes)); break; @@ -336,6 +435,7 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint case USBTMC_MSGID_VENDOR_SPECIFIC_MSG_OUT: case USBTMC_MSGID_VENDOR_SPECIFIC_IN: default: + TU_VERIFY(false); return false; } @@ -347,12 +447,22 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint case STATE_TX_REQUESTED: case STATE_TX_INITIATED: + case STATE_ABORTING_BULK_IN: + case STATE_ABORTING_BULK_OUT: default: + if(msg == NULL) + sprintf(logMsg," Unknown received control?\r\n "); + else { + sprintf(logMsg," msg=%lu\r\n ", (uint32_t)msg->header.MsgID); + } + uart_tx_str_sync(logMsg); TU_VERIFY(false); } } else if(ep_addr == usbtmc_state.ep_bulk_in) { + sprintf(logMsg,"IN\r\n"); + uart_tx_str_sync(logMsg); TU_ASSERT(usbtmc_state.state == STATE_TX_INITIATED); if(usbtmc_state.transfer_size_remaining == 0) { @@ -360,14 +470,14 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint TU_VERIFY(usbtmcd_app_msgBulkIn_complete(rhport)); TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, USBTMCD_MAX_PACKET_SIZE)); } - else if(usbtmc_state.transfer_size_remaining >= USBTMCD_MAX_PACKET_SIZE) + else if(usbtmc_state.transfer_size_remaining > sizeof(usbtmc_state.devInBuffer)) { - memcpy(usbtmc_state.ep_bulk_in_buf, usbtmc_state.devInBuffer, USBTMCD_MAX_PACKET_SIZE); - usbtmc_state.devInBuffer += USBTMCD_MAX_PACKET_SIZE; - usbtmc_state.transfer_size_remaining -= USBTMCD_MAX_PACKET_SIZE; - TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf,USBTMCD_MAX_PACKET_SIZE)); + memcpy(usbtmc_state.ep_bulk_in_buf, usbtmc_state.devInBuffer, sizeof(usbtmc_state.ep_bulk_in_buf)); + usbtmc_state.devInBuffer += sizeof(usbtmc_state.devInBuffer); + usbtmc_state.transfer_size_remaining -= sizeof(usbtmc_state.devInBuffer); + TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf,sizeof(usbtmc_state.devInBuffer))); } - else // short packet + else // last packet { size_t packetLen = usbtmc_state.transfer_size_remaining; memcpy(usbtmc_state.ep_bulk_in_buf, usbtmc_state.devInBuffer, usbtmc_state.transfer_size_remaining); @@ -401,6 +511,7 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ (request->bRequest == TUSB_REQ_CLEAR_FEATURE) && (request->wValue == TUSB_REQ_FEATURE_EDPT_HALT)) { + uart_tx_str_sync("feature clear\r\n"); if((request->wIndex) == usbtmc_state.ep_bulk_out) { usmtmcd_app_bulkOut_clearFeature(rhport); @@ -426,23 +537,48 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ // USBTMC required requests case USBTMC_bREQUEST_INITIATE_ABORT_BULK_OUT: case USBTMC_bREQUEST_CHECK_ABORT_BULK_OUT_STATUS: - case USBTMC_bREQUEST_INITIATE_ABORT_BULK_IN: + { + TU_VERIFY(request->bmRequestType == 0xA2); // in,class,EP + TU_VERIFY(request->wLength == 1u); + tmcStatusCode = USBTMC_STATUS_FAILED; + usbd_edpt_xfer(rhport, 0u, (void*)&tmcStatusCode,sizeof(tmcStatusCode)); + return true; + } case USBTMC_bREQUEST_CHECK_ABORT_BULK_IN_STATUS: - { - TU_VERIFY(request->bmRequestType == 0xA2); // in,class,EP - TU_VERIFY(request->wLength == 1u); - tmcStatusCode = USBTMC_STATUS_FAILED; - usbd_edpt_xfer(rhport, 0u, (void*)&tmcStatusCode,sizeof(tmcStatusCode)); - return true; - } + { + TU_VERIFY(request->bmRequestType == 0xA2); // in,class,EP + TU_VERIFY(request->wLength == 1u); + usbtmc_get_clear_status_rsp_t clearStatusRsp = {0}; + tmcStatusCode = USBTMC_STATUS_FAILED; + usbd_edpt_xfer(rhport, 0u, (void*)&tmcStatusCode,sizeof(tmcStatusCode)); + return true; + } + + case USBTMC_bREQUEST_INITIATE_ABORT_BULK_IN: + { + usbtmc_initiate_abort_rsp_t rsp = {0}; + uart_tx_str_sync("init abort bulk in\r\n"); + TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface + TU_VERIFY(request->wLength == sizeof(tmcStatusCode)); + TU_VERIFY(request->wIndex == usbtmc_state.ep_int_in); + // wValue is the requested bTag to abort + usbtmc_state.transfer_size_remaining = 0; + usbtmc_state.state = STATE_ABORTING_BULK_IN; + TU_VERIFY(usbtmcd_app_initiate_clear(rhport, &tmcStatusCode)); + TU_VERIFY(tud_control_xfer(rhport, request, (void*)&tmcStatusCode,sizeof(tmcStatusCode))); + return true; + } case USBTMC_bREQUEST_INITIATE_CLEAR: { + uart_tx_str_sync("init clear\r\n"); TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface TU_VERIFY(request->wLength == sizeof(tmcStatusCode)); // After receiving an INITIATE_CLEAR request, the device must Halt the Bulk-OUT endpoint, queue the // control endpoint response shown in Table 31, and clear all input buffers and output buffers. usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out); + usbtmc_state.transfer_size_remaining = 0; + usbtmc_state.state = STATE_CLEARING; TU_VERIFY(usbtmcd_app_initiate_clear(rhport, &tmcStatusCode)); TU_VERIFY(tud_control_xfer(rhport, request, (void*)&tmcStatusCode,sizeof(tmcStatusCode))); return true; @@ -450,17 +586,31 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ case USBTMC_bREQUEST_CHECK_CLEAR_STATUS: { - usbtmc_get_clear_status_rsp_t clearStatusRsp = {0}; + uart_tx_str_sync("check clear\r\n"); TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface + usbtmc_get_clear_status_rsp_t clearStatusRsp = {0}; TU_VERIFY(request->wLength == sizeof(clearStatusRsp)); - TU_VERIFY(usbtmcd_app_get_clear_status(rhport, &clearStatusRsp)); + if(usbd_edpt_busy(rhport, usbtmc_state.ep_bulk_in)) + { + // Stuff stuck in TX buffer? + clearStatusRsp.bmClear.BulkInFifoBytes = 1; + clearStatusRsp.USBTMC_status = USBTMC_STATUS_PENDING; + } + else + { + // Let app check if it's clear + TU_VERIFY(usbtmcd_app_get_clear_status(rhport, &clearStatusRsp)); + } + if(clearStatusRsp.USBTMC_status == USBTMC_STATUS_SUCCESS) + usbtmc_state.state = STATE_IDLE; TU_VERIFY(tud_control_xfer(rhport, request, (void*)&clearStatusRsp,sizeof(clearStatusRsp))); return true; } case USBTMC_bREQUEST_GET_CAPABILITIES: { + uart_tx_str_sync("get capabilities\r\n"); TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface TU_VERIFY(request->wLength == sizeof(usbtmcd_app_capabilities)); TU_VERIFY(tud_control_xfer(rhport, request, (void*)&usbtmcd_app_capabilities, sizeof(usbtmcd_app_capabilities))); @@ -470,6 +620,7 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ case USBTMC_bREQUEST_INDICATOR_PULSE: // Optional { + uart_tx_str_sync("indicate\r\n"); TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface TU_VERIFY(request->wLength == sizeof(tmcStatusCode)); TU_VERIFY(usbtmcd_app_capabilities.bmIntfcCapabilities.supportsIndicatorPulse); @@ -482,6 +633,7 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ // USB488 required requests case USBTMC488_bREQUEST_READ_STATUS_BYTE: { + uart_tx_str_sync("read stb\r\n"); usbtmc_read_stb_rsp_488_t rsp; TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface TU_VERIFY(request->wLength == sizeof(rsp)); // in,class,interface @@ -520,6 +672,7 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ case USBTMC488_bREQUEST_GO_TO_LOCAL: case USBTMC488_bREQUEST_LOCAL_LOCKOUT: { + uart_tx_str_sync("Unsupported REN/GTL/LLO\r\n"); TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface TU_VERIFY(false); return false; @@ -527,6 +680,7 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ #endif default: + uart_tx_str_sync("Default CTRL handler\r\n"); TU_VERIFY(false); return false; } From 91cd247c97a7376133638d960b6c650c0f71d376 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Tue, 17 Sep 2019 13:26:10 -0400 Subject: [PATCH 10/45] changes 2 --- examples/device/usbtmc/src/usb_descriptors.c | 10 ++++----- examples/device/usbtmc/src/usbtmc_app.c | 23 +++++++++++++++----- src/class/usbtmc/usbtmc_device.h | 4 ++-- 3 files changed, 23 insertions(+), 14 deletions(-) diff --git a/examples/device/usbtmc/src/usb_descriptors.c b/examples/device/usbtmc/src/usb_descriptors.c index 9567bcab5..792fff87c 100644 --- a/examples/device/usbtmc/src/usb_descriptors.c +++ b/examples/device/usbtmc/src/usb_descriptors.c @@ -106,7 +106,7 @@ uint8_t const * tud_hid_descriptor_report_cb(void) #if defined(CFG_TUD_USBTMC) # define USBTMC_DESC_MAIN(_itfnum,_bNumEndpoints) \ - USBTMC_IF_DESCRIPTOR(_itfnum, _bNumEndpoints, /*_stridx = */ 7u, USBTMC_PROTOCOL_USB488), \ + USBTMC_IF_DESCRIPTOR(_itfnum, _bNumEndpoints, /*_stridx = */ 4u, USBTMC_PROTOCOL_USB488), \ USBTMC_BULK_DESCRIPTORS(/* OUT = */0x03, /* IN = */ 0x83) #if defined(CFG_TUD_USBTMC_ENABLE_INT_EP) @@ -209,10 +209,7 @@ char const* string_desc_arr [] = "TinyUSB", // 1: Manufacturer "TinyUSB Device", // 2: Product "123456", // 3: Serials, should use chip ID - "TinyUSB CDC", // 4: CDC Interface - "TinyUSB MSC", // 5: MSC Interface - "TinyUSB HID", // 6: HID - "TinyUSB USBTMC", // 7: USBTMC + "TinyUSB USBTMC", // 4: USBTMC }; static uint16_t _desc_str[32]; @@ -227,7 +224,8 @@ uint16_t const* tud_descriptor_string_cb(uint8_t index) { memcpy(&_desc_str[1], string_desc_arr[0], 2); chr_count = 1; - }else + } + else { // Convert ASCII string into UTF-16 diff --git a/examples/device/usbtmc/src/usbtmc_app.c b/examples/device/usbtmc/src/usbtmc_app.c index 7328b6598..e21c3ca22 100644 --- a/examples/device/usbtmc/src/usbtmc_app.c +++ b/examples/device/usbtmc/src/usbtmc_app.c @@ -64,8 +64,8 @@ usbtmcd_app_capabilities = } #endif }; - -static const char idn[] = "TinyUSB,ModelNumber,SerialNumber,FirmwareVer\n"; +//static const char idn[] = "TinyUSB,ModelNumber,SerialNumber,FirmwareVer"; +static const char idn[] = "TinyUSB,ModelNumber,SerialNumber,FirmwareVer and a bunch of other text to make it longer than a packet, perhaps?\n"; static volatile uint8_t status; // 0=not query, 1=queried, 2=delay,set(MAV), 3=delay 4=ready? @@ -86,6 +86,7 @@ bool usbtmcd_app_msgBulkOut_start(uint8_t rhport, usbtmc_msg_request_dev_dep_out { (void)rhport; (void)msgHeader; + uart_tx_str_sync("MSG_OUT_DATA: start\r\n"); return true; } bool usbtmcd_app_msg_trigger(uint8_t rhport, usbtmc_msg_generic_t* msg) { @@ -99,6 +100,11 @@ bool usbtmcd_app_msg_data(uint8_t rhport, void *data, size_t len, bool transfer_ (void)rhport; // If transfer isn't finished, we just ignore it (for now) + uart_tx_str_sync("MSG_OUT_DATA: <<<"); + uart_tx_sync(data,len); + uart_tx_str_sync(">>>\r\n"); + if(transfer_complete) + uart_tx_str_sync("MSG_OUT_DATA: Complete\r\n"); if(transfer_complete && (len >=4) && !strncasecmp("*idn?",data,4)) { queryState = 1; @@ -115,13 +121,18 @@ bool usbtmcd_app_msgBulkIn_complete(uint8_t rhport) return true; } +static unsigned int msgReqLen; + bool usbtmcd_app_msgBulkIn_request(uint8_t rhport, usbtmc_msg_request_dev_dep_in const * request) { (void)rhport; + rspMsg.header.MsgID = request->header.MsgID, rspMsg.header.bTag = request->header.bTag, rspMsg.header.bTagInverse = request->header.bTagInverse; + msgReqLen = request->TransferSize; + uart_tx_str_sync("MSG_IN_DATA: Requested!\r\n"); TU_ASSERT(bulkInStarted == 0); bulkInStarted = 1; @@ -143,14 +154,14 @@ void usbtmc_app_task_iter(void) { queryState = 2; break; case 2: - if( (board_millis() - queryDelayStart) > 1000u) { + if( (board_millis() - queryDelayStart) > 5u) { queryDelayStart = board_millis(); queryState=3; status |= 0x10u; // MAV } break; case 3: - if( (board_millis() - queryDelayStart) > 1000u) { + if( (board_millis() - queryDelayStart) > 10u) { queryState = 4; } break; @@ -158,8 +169,7 @@ void usbtmc_app_task_iter(void) { if(bulkInStarted) { queryState = 0; bulkInStarted = 0; - rspMsg.TransferSize = sizeof(idn)-1; - usbtmcd_transmit_dev_msg_data(rhport, &rspMsg, idn); + usbtmcd_transmit_dev_msg_data(rhport, idn, tu_min32(sizeof(idn)-1,msgReqLen),false); // MAV is cleared in the transfer complete callback. } break; @@ -189,6 +199,7 @@ bool usbtmcd_app_get_clear_status(uint8_t rhport, usbtmc_get_clear_status_rsp_t rsp->bmClear.BulkInFifoBytes = 0u; return true; } + void usmtmcd_app_bulkIn_clearFeature(uint8_t rhport) { (void)rhport; diff --git a/src/class/usbtmc/usbtmc_device.h b/src/class/usbtmc/usbtmc_device.h index 35d4da438..a0ba82e30 100644 --- a/src/class/usbtmc/usbtmc_device.h +++ b/src/class/usbtmc/usbtmc_device.h @@ -86,8 +86,8 @@ TU_ATTR_WEAK bool usbtmcd_app_msg_trigger(uint8_t rhport, usbtmc_msg_generic_t* bool usbtmcd_transmit_dev_msg_data( uint8_t rhport, - usbtmc_msg_dev_dep_msg_in_header_t const * hdr, - const void *data); + const void * data, size_t len, + bool usingTermChar); /* "callbacks" from USB device core */ From c7006a254b167dc5b2c6994c5bcce70fd877f84c Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Tue, 17 Sep 2019 13:27:35 -0400 Subject: [PATCH 11/45] change 3 --- docs/concurrency.md | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 docs/concurrency.md diff --git a/docs/concurrency.md b/docs/concurrency.md new file mode 100644 index 000000000..e05ca6ffe --- /dev/null +++ b/docs/concurrency.md @@ -0,0 +1,36 @@ +# Concurrency + +The TinyUSB library is designed to operate on single-core MCUs with multi-threaded applications in mind. Interaction with interrupts is especially important to pay attention to. +It is compatible with optionally using a RTOS. + +## General + +When writing code, keep in mind that the OS (if using a RTOS) may swap out your code at any time. Also, your code can be preempted by an interrupt at any time. + +## Application Code + +The USB core does not execute application callbacks while in an interrupt context. Calls to application code are from within the USB core task context. Note that the application core will call class drivers from within their own task. + +## Class Drivers + +Class driver code should never be called from an interrupt context by the USB core, though the application is allowed to call class driver functions from interrupts. USB core functions may be called simultaneously by multiple tasks. Use care that proper locking is used to guard the USBD core functions from this case. + +Class drivers are allowed to call `usbd_*` functions, but not `dcd_*` functions. + +## USB Core + +All functions that may be called from an (USB core) interrupt context have a `bool in_isr` parameter to remind the implementer that special care must be taken. + +Interrupt handlers must not directly call class driver code, they must pass a message to the USB core's task. + + `usbd_*` functions may be called from interrupts without any notice. They may also be called simultaneously by multiple tasks. + +## Device Drivers + +Much of the processing of the USB stack is done in an interrupt context, and care must be taken in order to ensure variables are handled in the appropriate ways by the compiler and optimizer. + +In particular: + +- Ensure that all memory-mapped registers (including packet memory) are marked as volatile. GCC's optimizer will even combine memory access (like two 16-bit to be a 32-bit) if you don't mark the pointers as volatile. On some architectures, this can use macros like `_I`, `_O`, or `_IO'. +- All defined global variables are marked as `static`. + From 45b69a30a81a7353f625352efc143a91b02506bd Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Thu, 12 Sep 2019 14:32:16 -0400 Subject: [PATCH 12/45] Correct port assigned on the STM32F070 BSP --- hw/bsp/stm32f070rbnucleo/stm32f070rbnucleo.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/hw/bsp/stm32f070rbnucleo/stm32f070rbnucleo.c b/hw/bsp/stm32f070rbnucleo/stm32f070rbnucleo.c index 50f174b34..6ee73bcc2 100644 --- a/hw/bsp/stm32f070rbnucleo/stm32f070rbnucleo.c +++ b/hw/bsp/stm32f070rbnucleo/stm32f070rbnucleo.c @@ -29,13 +29,13 @@ #include "stm32f0xx.h" #include "stm32f0xx_hal_conf.h" -#define LED_PORT GPIOC -#define LED_PIN GPIO_PIN_13 +#define LED_PORT GPIOA +#define LED_PIN GPIO_PIN_5 #define LED_STATE_ON 1 -#define BUTTON_PORT GPIOA -#define BUTTON_PIN GPIO_PIN_5 -#define BUTTON_STATE_ACTIVE 1 +#define BUTTON_PORT GPIOC +#define BUTTON_PIN GPIO_PIN_13 +#define BUTTON_STATE_ACTIVE 0 void board_init(void) { @@ -75,7 +75,7 @@ void board_init(void) SystemCoreClockUpdate(); // LED - __HAL_RCC_GPIOC_CLK_ENABLE(); + __HAL_RCC_GPIOA_CLK_ENABLE(); GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.Pin = LED_PIN; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; @@ -84,7 +84,7 @@ void board_init(void) HAL_GPIO_Init(LED_PORT, &GPIO_InitStruct); // Button - __HAL_RCC_GPIOA_CLK_ENABLE(); + __HAL_RCC_GPIOC_CLK_ENABLE(); GPIO_InitStruct.Pin = BUTTON_PIN; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_PULLDOWN; From 44013e6e85e859abe6c47c567415a0acea003b1b Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 13 Sep 2019 18:42:58 +0700 Subject: [PATCH 13/45] Update boards.md --- docs/boards.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/boards.md b/docs/boards.md index 96650b20b..de6328aa2 100644 --- a/docs/boards.md +++ b/docs/boards.md @@ -48,8 +48,8 @@ This code base already had supported for a handful of following boards - [STM32F407vg Discovery](https://www.st.com/en/evaluation-tools/stm32f4discovery.html) - [STM32F411ve Discovery](https://www.st.com/en/evaluation-tools/32f411ediscovery.html) - [STM32F412zg Discovery](https://www.st.com/en/evaluation-tools/32f412gdiscovery.html) -- [Nucleo STM32F767zi](https://www.st.com/en/evaluation-tools/nucleo-f767zi.html) -- [Nucleo H743zi](https://www.st.com/en/evaluation-tools/nucleo-h743zi.html) +- [STM32F767zi Nucleo](https://www.st.com/en/evaluation-tools/nucleo-f767zi.html) +- [STM32H743zi Nucleo](https://www.st.com/en/evaluation-tools/nucleo-h743zi.html) ## Add your own board From fd4be239004946cd295b8a85215999a308f0b6ed Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 13 Sep 2019 18:43:46 +0700 Subject: [PATCH 14/45] Update boards.md --- docs/boards.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/boards.md b/docs/boards.md index de6328aa2..30b0eb958 100644 --- a/docs/boards.md +++ b/docs/boards.md @@ -41,15 +41,15 @@ This code base already had supported for a handful of following boards ### ST STM32 -- [STM32F070rb Nucleo](https://www.st.com/en/evaluation-tools/nucleo-f070rb.html) -- [STM32F072rb Discovery](https://www.st.com/en/evaluation-tools/32f072bdiscovery.html) -- [STM32F207zg Nucleo](https://www.st.com/en/evaluation-tools/nucleo-f207zg.html) -- [STM32F303vc Discovery](https://www.st.com/en/evaluation-tools/stm32f3discovery.html) -- [STM32F407vg Discovery](https://www.st.com/en/evaluation-tools/stm32f4discovery.html) -- [STM32F411ve Discovery](https://www.st.com/en/evaluation-tools/32f411ediscovery.html) -- [STM32F412zg Discovery](https://www.st.com/en/evaluation-tools/32f412gdiscovery.html) -- [STM32F767zi Nucleo](https://www.st.com/en/evaluation-tools/nucleo-f767zi.html) -- [STM32H743zi Nucleo](https://www.st.com/en/evaluation-tools/nucleo-h743zi.html) +- [STM32 F070rb Nucleo](https://www.st.com/en/evaluation-tools/nucleo-f070rb.html) +- [STM32 F072rb Discovery](https://www.st.com/en/evaluation-tools/32f072bdiscovery.html) +- [STM32 F207zg Nucleo](https://www.st.com/en/evaluation-tools/nucleo-f207zg.html) +- [STM32 F303vc Discovery](https://www.st.com/en/evaluation-tools/stm32f3discovery.html) +- [STM32 F407vg Discovery](https://www.st.com/en/evaluation-tools/stm32f4discovery.html) +- [STM32 F411ve Discovery](https://www.st.com/en/evaluation-tools/32f411ediscovery.html) +- [STM32 F412zg Discovery](https://www.st.com/en/evaluation-tools/32f412gdiscovery.html) +- [STM32 F767zi Nucleo](https://www.st.com/en/evaluation-tools/nucleo-f767zi.html) +- [STM32 H743zi Nucleo](https://www.st.com/en/evaluation-tools/nucleo-h743zi.html) ## Add your own board From a0b6b8187c036b386f09188a9017301f730096b8 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Fri, 13 Sep 2019 20:28:26 -0400 Subject: [PATCH 15/45] TI compiler quirks, and le byte swapping functions. --- src/common/tusb_compiler.h | 85 +++++++++++++++++++++++++++++++++----- 1 file changed, 74 insertions(+), 11 deletions(-) diff --git a/src/common/tusb_compiler.h b/src/common/tusb_compiler.h index 09768ef88..ca294c20f 100644 --- a/src/common/tusb_compiler.h +++ b/src/common/tusb_compiler.h @@ -53,6 +53,9 @@ // for declaration of reserved field, make use of _TU_COUNTER_ #define TU_RESERVED TU_XSTRCAT(reserved, _TU_COUNTER_) +#define TU_LITTLE_ENDIAN (0x12u) +#define TU_BIG_ENDIAN (0x21u) + //--------------------------------------------------------------------+ // Compiler porting with Attribute and Endian //--------------------------------------------------------------------+ @@ -67,20 +70,80 @@ // Endian conversion use well-known host to network (big endian) naming #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ - #define tu_htonl(u32) __builtin_bswap32(u32) - #define tu_ntohl(u32) __builtin_bswap32(u32) - - #define tu_htons(u16) __builtin_bswap16(u16) - #define tu_ntohs(u16) __builtin_bswap16(u16) + #define TU_BYTE_ORDER TU_LITTLE_ENDIAN #else - #define tu_htonl(u32) (u32) - #define tu_ntohl(u32) (u32) - - #define tu_htons(u16) (u16) - #define tu_ntohs(u16) (u16) + #define TU_BYTE_ORDER TU_BIG_ENDIAN #endif + + static inline uint16_t tu_bswap16(uint16_t u16) + { + return __builtin_bswap16(u16); + } + + static inline uint16_t tu_bswap32(uint16_t u32) + { + return __builtin_bswap32(u32); + } + + #define TU_BSWAP16 + +#elif defined(__TI_COMPILER_VERSION__) + #define TU_ATTR_ALIGNED(Bytes) __attribute__ ((aligned(Bytes))) + #define TU_ATTR_SECTION(sec_name) __attribute__ ((section(#sec_name))) + #define TU_ATTR_PACKED __attribute__ ((packed)) + #define TU_ATTR_PREPACKED + #define TU_ATTR_WEAK __attribute__ ((weak)) + #define TU_ATTR_DEPRECATED(mess) __attribute__ ((deprecated(mess))) // warn if function with this attribute is used + #define TU_ATTR_UNUSED __attribute__ ((unused)) // Function/Variable is meant to be possibly unused + + // __BYTE_ORDER is defined in the TI ARM compiler, but not MSP430 (which is little endian) + #if ((__BYTE_ORDER__) == (__ORDER_LITTLE_ENDIAN__)) || defined(__MSP430__) + #define TU_BYTE_ORDER TU_LITTLE_ENDIAN + #else + #define TU_BYTE_ORDER TU_BIG_ENDIAN + #endif + + static inline uint16_t tu_bswap16(uint16_t u16) + { + return __builtin_bswap16(u16); + } + + static inline uint16_t tu_bswap32(uint16_t u32) + { + return __builtin_bswap32(u32); + } #else - #error "Compiler attribute porting are required" + #error "Compiler attribute porting is required" +#endif + +#if (TU_BYTE_ORDER == TU_LITTLE_ENDIAN) + #define tu_htonl(u32) tu_bswap32(u32) + #define tu_ntohl(u32) tu_bswap32(u32) + + #define tu_htons(u16) tu_bswap16(u16) + #define tu_ntohs(u16) tu_bswap16(u16) + + #define tu_htole16(x) (x) + #define tu_le16toh(x) (x) + + #define tu_htole32(x) (x) + #define tu_le32toh(x) (x) + +#elif (TU_BYTE_ORDER == TU_BIG_ENDIAN) + #define tu_htonl(u32) (x) + #define tu_ntohl(u32) (x) + + #define tu_htons(u16) (x) + #define tu_ntohs(u16) (x) + + #define tu_htole16(x) tu_bswap16(u32) + #define tu_le16toh(x) tu_bswap16(u32) + + #define tu_htole32(x) tu_bswap32(u32) + #define tu_le32toh(x) tu_bswap32(u32) + +#else + #error Byte order is undefined #endif #endif /* _TUSB_COMPILER_H_ */ From 41e8b8752e421ccb63a48eec316f353854abc8a0 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Sun, 15 Sep 2019 15:20:01 -0400 Subject: [PATCH 16/45] Massive copy&paste typo of mine in the 32-bit byte swapping function.... --- src/common/tusb_compiler.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/common/tusb_compiler.h b/src/common/tusb_compiler.h index ca294c20f..df0326afd 100644 --- a/src/common/tusb_compiler.h +++ b/src/common/tusb_compiler.h @@ -80,7 +80,7 @@ return __builtin_bswap16(u16); } - static inline uint16_t tu_bswap32(uint16_t u32) + static inline uint32_t tu_bswap32(uint32_t u32) { return __builtin_bswap32(u32); } @@ -108,7 +108,7 @@ return __builtin_bswap16(u16); } - static inline uint16_t tu_bswap32(uint16_t u32) + static inline uint32_t tu_bswap32(uint32_t u32) { return __builtin_bswap32(u32); } From 8d05b70a72d8132eb67523c789499cd4cdf5d562 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Fri, 13 Sep 2019 23:37:47 -0400 Subject: [PATCH 17/45] Off-by-one error in Synopsys assertions. (and move some braces to their own lines. --- src/portable/st/synopsys/dcd_synopsys.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index b0e7e04bd..2daa16a26 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -268,21 +268,22 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) uint8_t const epnum = tu_edpt_number(desc_edpt->bEndpointAddress); uint8_t const dir = tu_edpt_dir(desc_edpt->bEndpointAddress); - - // Unsupported endpoint numbers/size. - if((desc_edpt->wMaxPacketSize.size > 64) || (epnum > EP_MAX)) { - return false; - } - + + TU_ASSERT((desc_edpt->wMaxPacketSize.size <= 64); + TU_ASSERT(epnum < EP_MAX); + xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); xfer->max_size = desc_edpt->wMaxPacketSize.size; - if(dir == TUSB_DIR_OUT) { + if(dir == TUSB_DIR_OUT) + { out_ep[epnum].DOEPCTL |= (1 << USB_OTG_DOEPCTL_USBAEP_Pos) | \ desc_edpt->bmAttributes.xfer << USB_OTG_DOEPCTL_EPTYP_Pos | \ desc_edpt->wMaxPacketSize.size << USB_OTG_DOEPCTL_MPSIZ_Pos; dev->DAINTMSK |= (1 << (USB_OTG_DAINTMSK_OEPM_Pos + epnum)); - } else { + } + else + { // "USB Data FIFOs" section in reference manual // Peripheral FIFO architecture // From 1ceeab2702c6f5407c00dab8deeade338d176a45 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Fri, 13 Sep 2019 23:52:43 -0400 Subject: [PATCH 18/45] This demonstrates that I don't pre-build things before committing them... oops. --- src/portable/st/synopsys/dcd_synopsys.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 2daa16a26..f15b92edc 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -269,7 +269,7 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) uint8_t const epnum = tu_edpt_number(desc_edpt->bEndpointAddress); uint8_t const dir = tu_edpt_dir(desc_edpt->bEndpointAddress); - TU_ASSERT((desc_edpt->wMaxPacketSize.size <= 64); + TU_ASSERT(desc_edpt->wMaxPacketSize.size <= 64); TU_ASSERT(epnum < EP_MAX); xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); From 192e1de66ed512fdab448bd4862c57259330df59 Mon Sep 17 00:00:00 2001 From: "William D. Jones" Date: Tue, 10 Sep 2019 14:10:33 -0400 Subject: [PATCH 19/45] Add pyboard (v1.1) BSP. cdc_msc_hid example tested. --- hw/bsp/pyboardv11/STM32F405RGTx_FLASH.ld | 189 +++++++++ hw/bsp/pyboardv11/board.mk | 50 +++ hw/bsp/pyboardv11/pyboardv11.c | 200 +++++++++ hw/bsp/pyboardv11/stm32f4xx_hal_conf.h | 489 +++++++++++++++++++++++ 4 files changed, 928 insertions(+) create mode 100644 hw/bsp/pyboardv11/STM32F405RGTx_FLASH.ld create mode 100644 hw/bsp/pyboardv11/board.mk create mode 100644 hw/bsp/pyboardv11/pyboardv11.c create mode 100644 hw/bsp/pyboardv11/stm32f4xx_hal_conf.h diff --git a/hw/bsp/pyboardv11/STM32F405RGTx_FLASH.ld b/hw/bsp/pyboardv11/STM32F405RGTx_FLASH.ld new file mode 100644 index 000000000..57ef61e26 --- /dev/null +++ b/hw/bsp/pyboardv11/STM32F405RGTx_FLASH.ld @@ -0,0 +1,189 @@ +/* +***************************************************************************** +** + +** File : LinkerScript.ld +** +** Abstract : Linker script for STM32F405RGTx Device with +** 1024KByte FLASH, 128KByte RAM +** +** Set heap size, stack size and stack location according +** to application requirements. +** +** Set memory bank area and size if external memory is used. +** +** Target : STMicroelectronics STM32 +** +** +** Distribution: The file is distributed as is, without any warranty +** of any kind. +** +** (c)Copyright Ac6. +** You may use this file as-is or modify it according to the needs of your +** project. Distribution of this file (unmodified or modified) is not +** permitted. Ac6 permit registered System Workbench for MCU users the +** rights to distribute the assembled, compiled & linked contents of this +** file as part of an application binary file, provided that it is built +** using the System Workbench for MCU toolchain. +** +***************************************************************************** +*/ + +/* Entry Point */ +ENTRY(Reset_Handler) + +/* Highest address of the user mode stack */ +_estack = 0x20020000; /* end of RAM */ +/* Generate a link error if heap and stack don't fit into RAM */ +_Min_Heap_Size = 0x200; /* required amount of heap */ +_Min_Stack_Size = 0x400; /* required amount of stack */ + +/* Specify the memory areas */ +MEMORY +{ +RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K +CCMRAM (rw) : ORIGIN = 0x10000000, LENGTH = 64K +FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 1024K +} + +/* Define output sections */ +SECTIONS +{ + /* The startup code goes first into FLASH */ + .isr_vector : + { + . = ALIGN(4); + KEEP(*(.isr_vector)) /* Startup code */ + . = ALIGN(4); + } >FLASH + + /* The program code and other data goes into FLASH */ + .text : + { + . = ALIGN(4); + *(.text) /* .text sections (code) */ + *(.text*) /* .text* sections (code) */ + *(.glue_7) /* glue arm to thumb code */ + *(.glue_7t) /* glue thumb to arm code */ + *(.eh_frame) + + KEEP (*(.init)) + KEEP (*(.fini)) + + . = ALIGN(4); + _etext = .; /* define a global symbols at end of code */ + } >FLASH + + /* Constant data goes into FLASH */ + .rodata : + { + . = ALIGN(4); + *(.rodata) /* .rodata sections (constants, strings, etc.) */ + *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ + . = ALIGN(4); + } >FLASH + + .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH + .ARM : { + __exidx_start = .; + *(.ARM.exidx*) + __exidx_end = .; + } >FLASH + + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array*)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } >FLASH + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array*)) + PROVIDE_HIDDEN (__init_array_end = .); + } >FLASH + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array*)) + PROVIDE_HIDDEN (__fini_array_end = .); + } >FLASH + + /* used by the startup to initialize data */ + _sidata = LOADADDR(.data); + + /* Initialized data sections goes into RAM, load LMA copy after code */ + .data : + { + . = ALIGN(4); + _sdata = .; /* create a global symbol at data start */ + *(.data) /* .data sections */ + *(.data*) /* .data* sections */ + + . = ALIGN(4); + _edata = .; /* define a global symbol at data end */ + } >RAM AT> FLASH + + _siccmram = LOADADDR(.ccmram); + + /* CCM-RAM section + * + * IMPORTANT NOTE! + * If initialized variables will be placed in this section, + * the startup code needs to be modified to copy the init-values. + */ + .ccmram : + { + . = ALIGN(4); + _sccmram = .; /* create a global symbol at ccmram start */ + *(.ccmram) + *(.ccmram*) + + . = ALIGN(4); + _eccmram = .; /* create a global symbol at ccmram end */ + } >CCMRAM AT> FLASH + + + /* Uninitialized data section */ + . = ALIGN(4); + .bss : + { + /* This is used by the startup in order to initialize the .bss secion */ + _sbss = .; /* define a global symbol at bss start */ + __bss_start__ = _sbss; + *(.bss) + *(.bss*) + *(COMMON) + + . = ALIGN(4); + _ebss = .; /* define a global symbol at bss end */ + __bss_end__ = _ebss; + } >RAM + + /* User_heap_stack section, used to check that there is enough RAM left */ + ._user_heap_stack : + { + . = ALIGN(8); + PROVIDE ( end = . ); + PROVIDE ( _end = . ); + . = . + _Min_Heap_Size; + . = . + _Min_Stack_Size; + . = ALIGN(8); + } >RAM + + + + /* Remove information from the standard libraries */ + /DISCARD/ : + { + libc.a ( * ) + libm.a ( * ) + libgcc.a ( * ) + } + + .ARM.attributes 0 : { *(.ARM.attributes) } +} + + diff --git a/hw/bsp/pyboardv11/board.mk b/hw/bsp/pyboardv11/board.mk new file mode 100644 index 000000000..9e328072b --- /dev/null +++ b/hw/bsp/pyboardv11/board.mk @@ -0,0 +1,50 @@ +CFLAGS += \ + -DHSE_VALUE=120000000 \ + -DSTM32F405xx \ + -mthumb \ + -mabi=aapcs \ + -mcpu=cortex-m4 \ + -mfloat-abi=hard \ + -mfpu=fpv4-sp-d16 \ + -nostdlib -nostartfiles \ + -DCFG_TUSB_MCU=OPT_MCU_STM32F4 + +ST_HAL_DRIVER = hw/mcu/st/st_driver/STM32F4xx_HAL_Driver +ST_CMSIS = hw/mcu/st/st_driver/CMSIS/Device/ST/STM32F4xx + +# All source paths should be relative to the top level. +LD_FILE = hw/bsp/pyboardv11/STM32F405RGTx_FLASH.ld + +SRC_C += \ + $(ST_CMSIS)/Source/Templates/system_stm32f4xx.c \ + $(ST_HAL_DRIVER)/Src/stm32f4xx_hal.c \ + $(ST_HAL_DRIVER)/Src/stm32f4xx_hal_cortex.c \ + $(ST_HAL_DRIVER)/Src/stm32f4xx_hal_rcc.c \ + $(ST_HAL_DRIVER)/Src/stm32f4xx_hal_gpio.c + +SRC_S += \ + $(ST_CMSIS)/Source/Templates/gcc/startup_stm32f405xx.s + +INC += \ + $(TOP)/hw/mcu/st/st_driver/CMSIS/Include \ + $(TOP)/$(ST_CMSIS)/Include \ + $(TOP)/$(ST_HAL_DRIVER)/Inc \ + $(TOP)/hw/bsp/$(BOARD) + +# For TinyUSB port source +VENDOR = st +CHIP_FAMILY = synopsys + +# For freeRTOS port source +FREERTOS_PORT = ARM_CM4F + +# For flash-jlink target +JLINK_DEVICE = stm32f407vg +JLINK_IF = swd + +# Path to STM32 Cube Programmer CLI, should be added into system path +STM32Prog = STM32_Programmer_CLI + +# flash target using on-board stlink +flash: $(BUILD)/$(BOARD)-firmware.elf + $(STM32Prog) --connect port=swd --write $< --go diff --git a/hw/bsp/pyboardv11/pyboardv11.c b/hw/bsp/pyboardv11/pyboardv11.c new file mode 100644 index 000000000..85c0eb58f --- /dev/null +++ b/hw/bsp/pyboardv11/pyboardv11.c @@ -0,0 +1,200 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#include "../board.h" + +#include "stm32f4xx.h" +#include "stm32f4xx_hal_conf.h" + +// Blue LED is chosen because the other LEDs are connected to ST-LINK lines. +#define LED_PORT GPIOB +#define LED_PIN GPIO_PIN_4 +#define LED_STATE_ON 1 + +#define BUTTON_PORT GPIOB +#define BUTTON_PIN GPIO_PIN_3 +#define BUTTON_STATE_ACTIVE 1 + +/** + * @brief System Clock Configuration + * The system Clock is configured as follow : + * System Clock source = PLL (HSE) + * SYSCLK(Hz) = 168000000 + * HCLK(Hz) = 168000000 + * AHB Prescaler = 1 + * APB1 Prescaler = 4 + * APB2 Prescaler = 2 + * HSE Frequency(Hz) = 12000000 + * PLL_M = 12 + * PLL_N = 336 + * PLL_P = 2 + * PLL_Q = 7 + * VDD(V) = 3.3 + * Main regulator output voltage = Scale1 mode + * Flash Latency(WS) = 5 + * @param None + * @retval None + */ +static void SystemClock_Config(void) +{ + RCC_ClkInitTypeDef RCC_ClkInitStruct; + RCC_OscInitTypeDef RCC_OscInitStruct; + + /* Enable Power Control clock */ + __HAL_RCC_PWR_CLK_ENABLE(); + + /* The voltage scaling allows optimizing the power consumption when the device is + clocked below the maximum system frequency, to update the voltage scaling value + regarding system frequency refer to product datasheet. */ + __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); + + /* Enable HSE Oscillator and activate PLL with HSE as source */ + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; + RCC_OscInitStruct.HSEState = RCC_HSE_ON; + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; + RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; + RCC_OscInitStruct.PLL.PLLM = 12; + RCC_OscInitStruct.PLL.PLLN = 336; + RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; + RCC_OscInitStruct.PLL.PLLQ = 7; + HAL_RCC_OscConfig(&RCC_OscInitStruct); + + /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 + clocks dividers */ + RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2); + RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; + RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; + RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4; + RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; + HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5); +} + +void board_init(void) +{ +#if CFG_TUSB_OS == OPT_OS_NONE + // 1ms tick timer + SysTick_Config(SystemCoreClock / 1000); +#elif CFG_TUSB_OS == OPT_OS_FREERTOS + // If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher ) + //NVIC_SetPriority(USB0_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY ); +#endif + + SystemClock_Config(); + + // Notify runtime of frequency change. + SystemCoreClockUpdate(); + + __HAL_RCC_GPIOA_CLK_ENABLE(); // USB D+/D- + __HAL_RCC_GPIOB_CLK_ENABLE(); // button, LED + + GPIO_InitTypeDef GPIO_InitStruct; + + // LED + __HAL_RCC_GPIOD_CLK_ENABLE(); + + GPIO_InitStruct.Pin = LED_PIN; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_PULLUP; + GPIO_InitStruct.Speed = GPIO_SPEED_FAST; + HAL_GPIO_Init(LED_PORT, &GPIO_InitStruct); + + board_led_write(false); + + // Button + GPIO_InitStruct.Pin = BUTTON_PIN; + GPIO_InitStruct.Mode = GPIO_MODE_INPUT; + GPIO_InitStruct.Pull = GPIO_PULLDOWN; + GPIO_InitStruct.Speed = GPIO_SPEED_FAST; + HAL_GPIO_Init(BUTTON_PORT, &GPIO_InitStruct); + + // Enable USB OTG clock + __HAL_RCC_USB_OTG_FS_CLK_ENABLE(); + + // USB Pin Init + // PA9- VUSB, PA10- ID, PA11- DM, PA12- DP + __HAL_RCC_GPIOA_CLK_ENABLE(); + + /* Configure DM DP Pins */ + GPIO_InitStruct.Pin = GPIO_PIN_11 | GPIO_PIN_12; + GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Alternate = GPIO_AF10_OTG_FS; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + /* Configure VBUS Pin */ + GPIO_InitStruct.Pin = GPIO_PIN_9; + GPIO_InitStruct.Mode = GPIO_MODE_INPUT; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + /* This for ID line debug */ + GPIO_InitStruct.Pin = GPIO_PIN_10; + GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; + GPIO_InitStruct.Pull = GPIO_PULLUP; + GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF10_OTG_FS; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); +} + +//--------------------------------------------------------------------+ +// Board porting API +//--------------------------------------------------------------------+ + +void board_led_write(bool state) +{ + HAL_GPIO_WritePin(LED_PORT, LED_PIN, state ? LED_STATE_ON : (1-LED_STATE_ON)); +} + +uint32_t board_button_read(void) +{ + return BUTTON_STATE_ACTIVE == HAL_GPIO_ReadPin(BUTTON_PORT, BUTTON_PIN); +} + +#if CFG_TUSB_OS == OPT_OS_NONE +volatile uint32_t system_ticks = 0; +void SysTick_Handler (void) +{ + system_ticks++; +} + +uint32_t board_millis(void) +{ + return system_ticks; +} +#endif + +void HardFault_Handler (void) +{ + asm("bkpt"); +} + +// Required by __libc_init_array in startup code if we are compiling using +// -nostdlib/-nostartfiles. +void _init(void) +{ + +} diff --git a/hw/bsp/pyboardv11/stm32f4xx_hal_conf.h b/hw/bsp/pyboardv11/stm32f4xx_hal_conf.h new file mode 100644 index 000000000..dbef20e0a --- /dev/null +++ b/hw/bsp/pyboardv11/stm32f4xx_hal_conf.h @@ -0,0 +1,489 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_conf.h + * @brief HAL configuration file. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2019 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32F4xx_HAL_CONF_H +#define __STM32F4xx_HAL_CONF_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ + +/* ########################## Module Selection ############################## */ +/** + * @brief This is the list of modules to be used in the HAL driver + */ +#define HAL_MODULE_ENABLED + +/* #define HAL_ADC_MODULE_ENABLED */ +/* #define HAL_CRYP_MODULE_ENABLED */ +/* #define HAL_CAN_MODULE_ENABLED */ +/* #define HAL_CRC_MODULE_ENABLED */ +/* #define HAL_CRYP_MODULE_ENABLED */ +/* #define HAL_DAC_MODULE_ENABLED */ +/* #define HAL_DCMI_MODULE_ENABLED */ +/* #define HAL_DMA2D_MODULE_ENABLED */ +/* #define HAL_ETH_MODULE_ENABLED */ +/* #define HAL_NAND_MODULE_ENABLED */ +/* #define HAL_NOR_MODULE_ENABLED */ +/* #define HAL_PCCARD_MODULE_ENABLED */ +/* #define HAL_SRAM_MODULE_ENABLED */ +/* #define HAL_SDRAM_MODULE_ENABLED */ +/* #define HAL_HASH_MODULE_ENABLED */ +/* #define HAL_I2C_MODULE_ENABLED */ +/* #define HAL_I2S_MODULE_ENABLED */ +/* #define HAL_IWDG_MODULE_ENABLED */ +/* #define HAL_LTDC_MODULE_ENABLED */ +/* #define HAL_RNG_MODULE_ENABLED */ +/* #define HAL_RTC_MODULE_ENABLED */ +/* #define HAL_SAI_MODULE_ENABLED */ +/* #define HAL_SD_MODULE_ENABLED */ +/* #define HAL_MMC_MODULE_ENABLED */ +/* #define HAL_SPI_MODULE_ENABLED */ +/* #define HAL_TIM_MODULE_ENABLED */ +/* #define HAL_UART_MODULE_ENABLED */ +/* #define HAL_USART_MODULE_ENABLED */ +/* #define HAL_IRDA_MODULE_ENABLED */ +/* #define HAL_SMARTCARD_MODULE_ENABLED */ +/* #define HAL_WWDG_MODULE_ENABLED */ +#define HAL_PCD_MODULE_ENABLED +/* #define HAL_HCD_MODULE_ENABLED */ +/* #define HAL_DSI_MODULE_ENABLED */ +/* #define HAL_QSPI_MODULE_ENABLED */ +/* #define HAL_QSPI_MODULE_ENABLED */ +/* #define HAL_CEC_MODULE_ENABLED */ +/* #define HAL_FMPI2C_MODULE_ENABLED */ +/* #define HAL_SPDIFRX_MODULE_ENABLED */ +/* #define HAL_DFSDM_MODULE_ENABLED */ +/* #define HAL_LPTIM_MODULE_ENABLED */ +/* #define HAL_EXTI_MODULE_ENABLED */ +#define HAL_GPIO_MODULE_ENABLED +#define HAL_DMA_MODULE_ENABLED +#define HAL_RCC_MODULE_ENABLED +#define HAL_FLASH_MODULE_ENABLED +#define HAL_PWR_MODULE_ENABLED +#define HAL_CORTEX_MODULE_ENABLED + +/* ########################## HSE/HSI Values adaptation ##################### */ +/** + * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. + * This value is used by the RCC HAL module to compute the system frequency + * (when HSE is used as system clock source, directly or through the PLL). + */ +#if !defined (HSE_VALUE) + #define HSE_VALUE ((uint32_t)12000000U) /*!< Value of the External oscillator in Hz */ +#endif /* HSE_VALUE */ + +#if !defined (HSE_STARTUP_TIMEOUT) + #define HSE_STARTUP_TIMEOUT ((uint32_t)100U) /*!< Time out for HSE start up, in ms */ +#endif /* HSE_STARTUP_TIMEOUT */ + +/** + * @brief Internal High Speed oscillator (HSI) value. + * This value is used by the RCC HAL module to compute the system frequency + * (when HSI is used as system clock source, directly or through the PLL). + */ +#if !defined (HSI_VALUE) + #define HSI_VALUE ((uint32_t)16000000U) /*!< Value of the Internal oscillator in Hz*/ +#endif /* HSI_VALUE */ + +/** + * @brief Internal Low Speed oscillator (LSI) value. + */ +#if !defined (LSI_VALUE) + #define LSI_VALUE ((uint32_t)32000U) /*!< LSI Typical Value in Hz*/ +#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz + The real value may vary depending on the variations + in voltage and temperature.*/ +/** + * @brief External Low Speed oscillator (LSE) value. + */ +#if !defined (LSE_VALUE) + #define LSE_VALUE ((uint32_t)32768U) /*!< Value of the External Low Speed oscillator in Hz */ +#endif /* LSE_VALUE */ + +#if !defined (LSE_STARTUP_TIMEOUT) + #define LSE_STARTUP_TIMEOUT ((uint32_t)5000U) /*!< Time out for LSE start up, in ms */ +#endif /* LSE_STARTUP_TIMEOUT */ + +/** + * @brief External clock source for I2S peripheral + * This value is used by the I2S HAL module to compute the I2S clock source + * frequency, this source is inserted directly through I2S_CKIN pad. + */ +#if !defined (EXTERNAL_CLOCK_VALUE) + #define EXTERNAL_CLOCK_VALUE ((uint32_t)12288000U) /*!< Value of the External audio frequency in Hz*/ +#endif /* EXTERNAL_CLOCK_VALUE */ + +/* Tip: To avoid modifying this file each time you need to use different HSE, + === you can define the HSE value in your toolchain compiler preprocessor. */ + +/* ########################### System Configuration ######################### */ +/** + * @brief This is the HAL system configuration section + */ +#define VDD_VALUE ((uint32_t)3300U) /*!< Value of VDD in mv */ +#define TICK_INT_PRIORITY ((uint32_t)0U) /*!< tick interrupt priority */ +#define USE_RTOS 0U +#define PREFETCH_ENABLE 1U +#define INSTRUCTION_CACHE_ENABLE 1U +#define DATA_CACHE_ENABLE 1U + +/* Copied over manually- STM32Cube didn't generate these for some reason. */ +#define USE_HAL_ADC_REGISTER_CALLBACKS 0U /* ADC register callback disabled */ +#define USE_HAL_CEC_REGISTER_CALLBACKS 0U /* CEC register callback disabled */ +#define USE_HAL_COMP_REGISTER_CALLBACKS 0U /* COMP register callback disabled */ +#define USE_HAL_CRYP_REGISTER_CALLBACKS 0U /* CRYP register callback disabled */ +#define USE_HAL_DAC_REGISTER_CALLBACKS 0U /* DAC register callback disabled */ +#define USE_HAL_DCMI_REGISTER_CALLBACKS 0U /* DCMI register callback disabled */ +#define USE_HAL_DFSDM_REGISTER_CALLBACKS 0U /* DFSDM register callback disabled */ +#define USE_HAL_DMA2D_REGISTER_CALLBACKS 0U /* DMA2D register callback disabled */ +#define USE_HAL_DSI_REGISTER_CALLBACKS 0U /* DSI register callback disabled */ +#define USE_HAL_ETH_REGISTER_CALLBACKS 0U /* ETH register callback disabled */ +#define USE_HAL_FDCAN_REGISTER_CALLBACKS 0U /* FDCAN register callback disabled */ +#define USE_HAL_NAND_REGISTER_CALLBACKS 0U /* NAND register callback disabled */ +#define USE_HAL_NOR_REGISTER_CALLBACKS 0U /* NOR register callback disabled */ +#define USE_HAL_SDRAM_REGISTER_CALLBACKS 0U /* SDRAM register callback disabled */ +#define USE_HAL_SRAM_REGISTER_CALLBACKS 0U /* SRAM register callback disabled */ +#define USE_HAL_HASH_REGISTER_CALLBACKS 0U /* HASH register callback disabled */ +#define USE_HAL_HCD_REGISTER_CALLBACKS 0U /* HCD register callback disabled */ +#define USE_HAL_HRTIM_REGISTER_CALLBACKS 0U /* HRTIM register callback disabled */ +#define USE_HAL_I2C_REGISTER_CALLBACKS 0U /* I2C register callback disabled */ +#define USE_HAL_I2S_REGISTER_CALLBACKS 0U /* I2S register callback disabled */ +#define USE_HAL_JPEG_REGISTER_CALLBACKS 0U /* JPEG register callback disabled */ +#define USE_HAL_LPTIM_REGISTER_CALLBACKS 0U /* LPTIM register callback disabled */ +#define USE_HAL_LTDC_REGISTER_CALLBACKS 0U /* LTDC register callback disabled */ +#define USE_HAL_MDIOS_REGISTER_CALLBACKS 0U /* MDIO register callback disabled */ +#define USE_HAL_OPAMP_REGISTER_CALLBACKS 0U /* MDIO register callback disabled */ +#define USE_HAL_PCD_REGISTER_CALLBACKS 0U /* PCD register callback disabled */ +#define USE_HAL_QSPI_REGISTER_CALLBACKS 0U /* QSPI register callback disabled */ +#define USE_HAL_RNG_REGISTER_CALLBACKS 0U /* RNG register callback disabled */ +#define USE_HAL_RTC_REGISTER_CALLBACKS 0U /* RTC register callback disabled */ +#define USE_HAL_SAI_REGISTER_CALLBACKS 0U /* SAI register callback disabled */ +#define USE_HAL_SPDIFRX_REGISTER_CALLBACKS 0U /* SPDIFRX register callback disabled */ +#define USE_HAL_SMBUS_REGISTER_CALLBACKS 0U /* SMBUS register callback disabled */ +#define USE_HAL_SPI_REGISTER_CALLBACKS 0U /* SPI register callback disabled */ +#define USE_HAL_SWPMI_REGISTER_CALLBACKS 0U /* SWPMI register callback disabled */ +#define USE_HAL_TIM_REGISTER_CALLBACKS 0U /* TIM register callback disabled */ +#define USE_HAL_WWDG_REGISTER_CALLBACKS 0U /* WWDG register callback disabled */ + +/* ########################## Assert Selection ############################## */ +/** + * @brief Uncomment the line below to expanse the "assert_param" macro in the + * HAL drivers code + */ +/* #define USE_FULL_ASSERT 1U */ + +/* ################## Ethernet peripheral configuration ##################### */ + +/* Section 1 : Ethernet peripheral configuration */ + +/* MAC ADDRESS: MAC_ADDR0:MAC_ADDR1:MAC_ADDR2:MAC_ADDR3:MAC_ADDR4:MAC_ADDR5 */ +#define MAC_ADDR0 2U +#define MAC_ADDR1 0U +#define MAC_ADDR2 0U +#define MAC_ADDR3 0U +#define MAC_ADDR4 0U +#define MAC_ADDR5 0U + +/* Definition of the Ethernet driver buffers size and count */ +#define ETH_RX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for receive */ +#define ETH_TX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for transmit */ +#define ETH_RXBUFNB ((uint32_t)4U) /* 4 Rx buffers of size ETH_RX_BUF_SIZE */ +#define ETH_TXBUFNB ((uint32_t)4U) /* 4 Tx buffers of size ETH_TX_BUF_SIZE */ + +/* Section 2: PHY configuration section */ + +/* DP83848_PHY_ADDRESS Address*/ +#define DP83848_PHY_ADDRESS 0x01U +/* PHY Reset delay these values are based on a 1 ms Systick interrupt*/ +#define PHY_RESET_DELAY ((uint32_t)0x000000FFU) +/* PHY Configuration delay */ +#define PHY_CONFIG_DELAY ((uint32_t)0x00000FFFU) + +#define PHY_READ_TO ((uint32_t)0x0000FFFFU) +#define PHY_WRITE_TO ((uint32_t)0x0000FFFFU) + +/* Section 3: Common PHY Registers */ + +#define PHY_BCR ((uint16_t)0x0000U) /*!< Transceiver Basic Control Register */ +#define PHY_BSR ((uint16_t)0x0001U) /*!< Transceiver Basic Status Register */ + +#define PHY_RESET ((uint16_t)0x8000U) /*!< PHY Reset */ +#define PHY_LOOPBACK ((uint16_t)0x4000U) /*!< Select loop-back mode */ +#define PHY_FULLDUPLEX_100M ((uint16_t)0x2100U) /*!< Set the full-duplex mode at 100 Mb/s */ +#define PHY_HALFDUPLEX_100M ((uint16_t)0x2000U) /*!< Set the half-duplex mode at 100 Mb/s */ +#define PHY_FULLDUPLEX_10M ((uint16_t)0x0100U) /*!< Set the full-duplex mode at 10 Mb/s */ +#define PHY_HALFDUPLEX_10M ((uint16_t)0x0000U) /*!< Set the half-duplex mode at 10 Mb/s */ +#define PHY_AUTONEGOTIATION ((uint16_t)0x1000U) /*!< Enable auto-negotiation function */ +#define PHY_RESTART_AUTONEGOTIATION ((uint16_t)0x0200U) /*!< Restart auto-negotiation function */ +#define PHY_POWERDOWN ((uint16_t)0x0800U) /*!< Select the power down mode */ +#define PHY_ISOLATE ((uint16_t)0x0400U) /*!< Isolate PHY from MII */ + +#define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020U) /*!< Auto-Negotiation process completed */ +#define PHY_LINKED_STATUS ((uint16_t)0x0004U) /*!< Valid link established */ +#define PHY_JABBER_DETECTION ((uint16_t)0x0002U) /*!< Jabber condition detected */ + +/* Section 4: Extended PHY Registers */ +#define PHY_SR ((uint16_t)0x10U) /*!< PHY status register Offset */ + +#define PHY_SPEED_STATUS ((uint16_t)0x0002U) /*!< PHY Speed mask */ +#define PHY_DUPLEX_STATUS ((uint16_t)0x0004U) /*!< PHY Duplex mask */ + +/* ################## SPI peripheral configuration ########################## */ + +/* CRC FEATURE: Use to activate CRC feature inside HAL SPI Driver +* Activated: CRC code is present inside driver +* Deactivated: CRC code cleaned from driver +*/ + +#define USE_SPI_CRC 0U + +/* Includes ------------------------------------------------------------------*/ +/** + * @brief Include module's header file + */ + +#ifdef HAL_RCC_MODULE_ENABLED + #include "stm32f4xx_hal_rcc.h" +#endif /* HAL_RCC_MODULE_ENABLED */ + +#ifdef HAL_EXTI_MODULE_ENABLED + #include "stm32f4xx_hal_exti.h" +#endif /* HAL_EXTI_MODULE_ENABLED */ + +#ifdef HAL_GPIO_MODULE_ENABLED + #include "stm32f4xx_hal_gpio.h" +#endif /* HAL_GPIO_MODULE_ENABLED */ + +#ifdef HAL_DMA_MODULE_ENABLED + #include "stm32f4xx_hal_dma.h" +#endif /* HAL_DMA_MODULE_ENABLED */ + +#ifdef HAL_CORTEX_MODULE_ENABLED + #include "stm32f4xx_hal_cortex.h" +#endif /* HAL_CORTEX_MODULE_ENABLED */ + +#ifdef HAL_ADC_MODULE_ENABLED + #include "stm32f4xx_hal_adc.h" +#endif /* HAL_ADC_MODULE_ENABLED */ + +#ifdef HAL_CAN_MODULE_ENABLED + #include "stm32f4xx_hal_can.h" +#endif /* HAL_CAN_MODULE_ENABLED */ + +#ifdef HAL_CRC_MODULE_ENABLED + #include "stm32f4xx_hal_crc.h" +#endif /* HAL_CRC_MODULE_ENABLED */ + +#ifdef HAL_CRYP_MODULE_ENABLED + #include "stm32f4xx_hal_cryp.h" +#endif /* HAL_CRYP_MODULE_ENABLED */ + +#ifdef HAL_DMA2D_MODULE_ENABLED + #include "stm32f4xx_hal_dma2d.h" +#endif /* HAL_DMA2D_MODULE_ENABLED */ + +#ifdef HAL_DAC_MODULE_ENABLED + #include "stm32f4xx_hal_dac.h" +#endif /* HAL_DAC_MODULE_ENABLED */ + +#ifdef HAL_DCMI_MODULE_ENABLED + #include "stm32f4xx_hal_dcmi.h" +#endif /* HAL_DCMI_MODULE_ENABLED */ + +#ifdef HAL_ETH_MODULE_ENABLED + #include "stm32f4xx_hal_eth.h" +#endif /* HAL_ETH_MODULE_ENABLED */ + +#ifdef HAL_FLASH_MODULE_ENABLED + #include "stm32f4xx_hal_flash.h" +#endif /* HAL_FLASH_MODULE_ENABLED */ + +#ifdef HAL_SRAM_MODULE_ENABLED + #include "stm32f4xx_hal_sram.h" +#endif /* HAL_SRAM_MODULE_ENABLED */ + +#ifdef HAL_NOR_MODULE_ENABLED + #include "stm32f4xx_hal_nor.h" +#endif /* HAL_NOR_MODULE_ENABLED */ + +#ifdef HAL_NAND_MODULE_ENABLED + #include "stm32f4xx_hal_nand.h" +#endif /* HAL_NAND_MODULE_ENABLED */ + +#ifdef HAL_PCCARD_MODULE_ENABLED + #include "stm32f4xx_hal_pccard.h" +#endif /* HAL_PCCARD_MODULE_ENABLED */ + +#ifdef HAL_SDRAM_MODULE_ENABLED + #include "stm32f4xx_hal_sdram.h" +#endif /* HAL_SDRAM_MODULE_ENABLED */ + +#ifdef HAL_HASH_MODULE_ENABLED + #include "stm32f4xx_hal_hash.h" +#endif /* HAL_HASH_MODULE_ENABLED */ + +#ifdef HAL_I2C_MODULE_ENABLED + #include "stm32f4xx_hal_i2c.h" +#endif /* HAL_I2C_MODULE_ENABLED */ + +#ifdef HAL_I2S_MODULE_ENABLED + #include "stm32f4xx_hal_i2s.h" +#endif /* HAL_I2S_MODULE_ENABLED */ + +#ifdef HAL_IWDG_MODULE_ENABLED + #include "stm32f4xx_hal_iwdg.h" +#endif /* HAL_IWDG_MODULE_ENABLED */ + +#ifdef HAL_LTDC_MODULE_ENABLED + #include "stm32f4xx_hal_ltdc.h" +#endif /* HAL_LTDC_MODULE_ENABLED */ + +#ifdef HAL_PWR_MODULE_ENABLED + #include "stm32f4xx_hal_pwr.h" +#endif /* HAL_PWR_MODULE_ENABLED */ + +#ifdef HAL_RNG_MODULE_ENABLED + #include "stm32f4xx_hal_rng.h" +#endif /* HAL_RNG_MODULE_ENABLED */ + +#ifdef HAL_RTC_MODULE_ENABLED + #include "stm32f4xx_hal_rtc.h" +#endif /* HAL_RTC_MODULE_ENABLED */ + +#ifdef HAL_SAI_MODULE_ENABLED + #include "stm32f4xx_hal_sai.h" +#endif /* HAL_SAI_MODULE_ENABLED */ + +#ifdef HAL_SD_MODULE_ENABLED + #include "stm32f4xx_hal_sd.h" +#endif /* HAL_SD_MODULE_ENABLED */ + +#ifdef HAL_MMC_MODULE_ENABLED + #include "stm32f4xx_hal_mmc.h" +#endif /* HAL_MMC_MODULE_ENABLED */ + +#ifdef HAL_SPI_MODULE_ENABLED + #include "stm32f4xx_hal_spi.h" +#endif /* HAL_SPI_MODULE_ENABLED */ + +#ifdef HAL_TIM_MODULE_ENABLED + #include "stm32f4xx_hal_tim.h" +#endif /* HAL_TIM_MODULE_ENABLED */ + +#ifdef HAL_UART_MODULE_ENABLED + #include "stm32f4xx_hal_uart.h" +#endif /* HAL_UART_MODULE_ENABLED */ + +#ifdef HAL_USART_MODULE_ENABLED + #include "stm32f4xx_hal_usart.h" +#endif /* HAL_USART_MODULE_ENABLED */ + +#ifdef HAL_IRDA_MODULE_ENABLED + #include "stm32f4xx_hal_irda.h" +#endif /* HAL_IRDA_MODULE_ENABLED */ + +#ifdef HAL_SMARTCARD_MODULE_ENABLED + #include "stm32f4xx_hal_smartcard.h" +#endif /* HAL_SMARTCARD_MODULE_ENABLED */ + +#ifdef HAL_WWDG_MODULE_ENABLED + #include "stm32f4xx_hal_wwdg.h" +#endif /* HAL_WWDG_MODULE_ENABLED */ + +#ifdef HAL_PCD_MODULE_ENABLED + #include "stm32f4xx_hal_pcd.h" +#endif /* HAL_PCD_MODULE_ENABLED */ + +#ifdef HAL_HCD_MODULE_ENABLED + #include "stm32f4xx_hal_hcd.h" +#endif /* HAL_HCD_MODULE_ENABLED */ + +#ifdef HAL_DSI_MODULE_ENABLED + #include "stm32f4xx_hal_dsi.h" +#endif /* HAL_DSI_MODULE_ENABLED */ + +#ifdef HAL_QSPI_MODULE_ENABLED + #include "stm32f4xx_hal_qspi.h" +#endif /* HAL_QSPI_MODULE_ENABLED */ + +#ifdef HAL_CEC_MODULE_ENABLED + #include "stm32f4xx_hal_cec.h" +#endif /* HAL_CEC_MODULE_ENABLED */ + +#ifdef HAL_FMPI2C_MODULE_ENABLED + #include "stm32f4xx_hal_fmpi2c.h" +#endif /* HAL_FMPI2C_MODULE_ENABLED */ + +#ifdef HAL_SPDIFRX_MODULE_ENABLED + #include "stm32f4xx_hal_spdifrx.h" +#endif /* HAL_SPDIFRX_MODULE_ENABLED */ + +#ifdef HAL_DFSDM_MODULE_ENABLED + #include "stm32f4xx_hal_dfsdm.h" +#endif /* HAL_DFSDM_MODULE_ENABLED */ + +#ifdef HAL_LPTIM_MODULE_ENABLED + #include "stm32f4xx_hal_lptim.h" +#endif /* HAL_LPTIM_MODULE_ENABLED */ + +/* Exported macro ------------------------------------------------------------*/ +#ifdef USE_FULL_ASSERT +/** + * @brief The assert_param macro is used for function's parameters check. + * @param expr: If expr is false, it calls assert_failed function + * which reports the name of the source file and the source + * line number of the call that failed. + * If expr is true, it returns no value. + * @retval None + */ + #define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__)) +/* Exported functions ------------------------------------------------------- */ + void assert_failed(uint8_t* file, uint32_t line); +#else + #define assert_param(expr) ((void)0U) +#endif /* USE_FULL_ASSERT */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32F4xx_HAL_CONF_H */ + + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ From ff36957c05cf40c8b73f56f3e039cc00864ca492 Mon Sep 17 00:00:00 2001 From: "William D. Jones" Date: Sat, 14 Sep 2019 04:31:43 -0400 Subject: [PATCH 20/45] pyboardv11: Fix typo in HSE_VALUE define so that SysTick runs at correct frequency. --- hw/bsp/pyboardv11/board.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/bsp/pyboardv11/board.mk b/hw/bsp/pyboardv11/board.mk index 9e328072b..2ba1d3900 100644 --- a/hw/bsp/pyboardv11/board.mk +++ b/hw/bsp/pyboardv11/board.mk @@ -1,5 +1,5 @@ CFLAGS += \ - -DHSE_VALUE=120000000 \ + -DHSE_VALUE=12000000 \ -DSTM32F405xx \ -mthumb \ -mabi=aapcs \ From 8e17fb49106eeb291a36ff5f82ead624e867e6b0 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 16 Sep 2019 11:13:17 +0700 Subject: [PATCH 21/45] follow up to suggestion to pr 155 --- src/common/tusb_types.h | 3 ++- src/device/usbd.c | 19 +++++++++++++------ 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index a50e89934..ad42baad7 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -125,7 +125,8 @@ typedef enum { TUSB_REQ_TYPE_STANDARD = 0, TUSB_REQ_TYPE_CLASS, - TUSB_REQ_TYPE_VENDOR + TUSB_REQ_TYPE_VENDOR, + TUSB_REQ_TYPE_INVALID } tusb_request_type_t; typedef enum diff --git a/src/device/usbd.c b/src/device/usbd.c index 572708f7d..2f8967fae 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -62,7 +62,7 @@ typedef struct { static usbd_device_t _usbd_dev = { 0 }; // Invalid driver ID in itf2drv[] ep2drv[][] mapping -enum { DRVID_INVALID = 0xff }; +enum { DRVID_INVALID = 0xFFu }; //--------------------------------------------------------------------+ // Class Driver @@ -365,6 +365,8 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const { usbd_control_set_complete_callback(NULL); + TU_ASSERT(p_request->bmRequestType_bit.type < TUSB_REQ_TYPE_INVALID); + // Vendor request if ( p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_VENDOR ) { @@ -486,7 +488,8 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const // GET HID REPORT DESCRIPTOR falls into this case // stall control endpoint if driver return false usbd_control_set_complete_callback(usbd_class_drivers[drvid].control_complete); - TU_ASSERT(usbd_class_drivers[drvid].control_request(rhport, p_request)); + TU_ASSERT(usbd_class_drivers[drvid].control_request != NULL && + usbd_class_drivers[drvid].control_request(rhport, p_request)); break; } }else @@ -494,7 +497,8 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const // forward to class driver: "non-STD request to Interface" // stall control endpoint if driver return false usbd_control_set_complete_callback(usbd_class_drivers[drvid].control_complete); - TU_ASSERT(usbd_class_drivers[drvid].control_request(rhport, p_request)); + TU_ASSERT(usbd_class_drivers[drvid].control_request != NULL && + usbd_class_drivers[drvid].control_request(rhport, p_request)); } } break; @@ -515,7 +519,7 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const // We will forward all request targeted endpoint to its class driver // - For non-standard request: driver can ACK or Stall the request by return true/false // - For standard request: usbd decide the ACK stage regardless of driver return value - bool ret; + bool ret = false; if ( TUSB_REQ_TYPE_STANDARD != p_request->bmRequestType_bit.type ) { @@ -523,8 +527,11 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const usbd_control_set_complete_callback(usbd_class_drivers[drv_id].control_complete); } - // Invoke class driver first - ret = usbd_class_drivers[drv_id].control_request(rhport, p_request); + // Invoke class driver first if available + if ( usbd_class_drivers[drv_id].control_request ) + { + ret = usbd_class_drivers[drv_id].control_request(rhport, p_request); + } // Then handle if it is standard request if ( TUSB_REQ_TYPE_STANDARD == p_request->bmRequestType_bit.type ) From 5a2e510af73e84284343420fd76388369e70f7f5 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Sat, 14 Sep 2019 09:02:21 -0400 Subject: [PATCH 22/45] Interpretation of assert vs verify. --- src/common/tusb_verify.h | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/src/common/tusb_verify.h b/src/common/tusb_verify.h index 2727ce043..fae0c88ae 100644 --- a/src/common/tusb_verify.h +++ b/src/common/tusb_verify.h @@ -36,10 +36,34 @@ * as C++ for the sake of code simplicity. Beware of a headache macro * manipulation that you are told to stay away. * - * e.g * - * - TU_VERIFY( cond ) will return false if cond is false - * - TU_VERIFY( cond, err) will return err instead if cond is false + * This contains macros for both VERIFY and ASSERT: + * + * VERIFY: Used when there is an error condition which is not the + * fault of the MCU. For example, bounds checking on data + * sent to the micro over USB should use this function. + * Another example is checking for buffer overflows, where + * returning from the active function causes a NAK. + * + * ASSERT: Used for error conditions that are caused by MCU firmware + * bugs. This is used to discover bugs in the code more + * quickly. One example would be adding assertions in library + * function calls to confirm a function's (untainted) + * parameters are valid. + * + * + * The difference in behaviour is that ASSERT triggers a breakpoint while + * verify does not. + * + * #define TU_VERIFY(cond) if(cond) return false; + * #define TU_VERIFY(cond,ret) if(cond) return ret; + * + * #define TU_VERIFY_HDLR(cond,handler) if(cond) {handler; return false;} + * #define TU_VERIFY_HDLR(cond,ret,handler) if(cond) {handler; return ret;} + * + * #define TU_ASSERT(cond) if(cond) {_MESS_FAILED(); TU_BREAKPOINT(), return false;} + * #define TU_ASSERT(cond,ret) if(cond) {_MESS_FAILED(); TU_BREAKPOINT(), return ret;} + * *------------------------------------------------------------------*/ #ifdef __cplusplus From 237c32b976d605087dd0b2c5013f7f2ae4bae46f Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 16 Sep 2019 13:32:47 +0700 Subject: [PATCH 23/45] fix #143 --- src/portable/nxp/lpc17_40/dcd_lpc17_40.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/portable/nxp/lpc17_40/dcd_lpc17_40.c b/src/portable/nxp/lpc17_40/dcd_lpc17_40.c index 2b49f52e9..d5f90d2a7 100644 --- a/src/portable/nxp/lpc17_40/dcd_lpc17_40.c +++ b/src/portable/nxp/lpc17_40/dcd_lpc17_40.c @@ -293,7 +293,7 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) break; case TUSB_XFER_ISOCHRONOUS: - TU_ASSERT((epnum % 3) == 3 && (epnum != 15)); + TU_ASSERT((epnum % 3) == 0 && (epnum != 0) && (epnum != 15)); break; default: From 6dd2296cfc1b2cd871e577c42de96ee444d4a1d3 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Mon, 16 Sep 2019 11:27:05 -0400 Subject: [PATCH 24/45] Change inline functions to macros, and make all parameter names uniform. --- src/common/tusb_compiler.h | 58 +++++++++++++++----------------------- 1 file changed, 23 insertions(+), 35 deletions(-) diff --git a/src/common/tusb_compiler.h b/src/common/tusb_compiler.h index df0326afd..58732b871 100644 --- a/src/common/tusb_compiler.h +++ b/src/common/tusb_compiler.h @@ -75,17 +75,8 @@ #define TU_BYTE_ORDER TU_BIG_ENDIAN #endif - static inline uint16_t tu_bswap16(uint16_t u16) - { - return __builtin_bswap16(u16); - } - - static inline uint32_t tu_bswap32(uint32_t u32) - { - return __builtin_bswap32(u32); - } - - #define TU_BSWAP16 +#define TU_BSWAP16(u16) (__builtin_bswap16(u16)) +#define TU_BSWAP32(u32) (__builtin_bswap32(u32)) #elif defined(__TI_COMPILER_VERSION__) #define TU_ATTR_ALIGNED(Bytes) __attribute__ ((aligned(Bytes))) @@ -103,44 +94,41 @@ #define TU_BYTE_ORDER TU_BIG_ENDIAN #endif - static inline uint16_t tu_bswap16(uint16_t u16) - { - return __builtin_bswap16(u16); - } + #define TU_BSWAP16(u16) (__builtin_bswap16(u16)) + #define TU_BSWAP32(u32) (__builtin_bswap32(u32)) - static inline uint32_t tu_bswap32(uint32_t u32) - { - return __builtin_bswap32(u32); - } #else #error "Compiler attribute porting is required" #endif #if (TU_BYTE_ORDER == TU_LITTLE_ENDIAN) - #define tu_htonl(u32) tu_bswap32(u32) - #define tu_ntohl(u32) tu_bswap32(u32) - #define tu_htons(u16) tu_bswap16(u16) - #define tu_ntohs(u16) tu_bswap16(u16) + #define tu_htons(u16) (TU_BSWAP16(u16)) + #define tu_ntohs(u16) (TU_BSWAP16(u16)) - #define tu_htole16(x) (x) - #define tu_le16toh(x) (x) + #define tu_htonl(u32) (TU_BSWAP32(u32)) + #define tu_ntohl(u32) (TU_BSWAP32(u32)) - #define tu_htole32(x) (x) - #define tu_le32toh(x) (x) + #define tu_htole16(u16) (u16) + #define tu_le16toh(u16) (u16) + + #define tu_htole32(u32) (u32) + #define tu_le32toh(u32) (u32) #elif (TU_BYTE_ORDER == TU_BIG_ENDIAN) - #define tu_htonl(u32) (x) - #define tu_ntohl(u32) (x) - #define tu_htons(u16) (x) - #define tu_ntohs(u16) (x) + #define tu_htons(u16) (u16) + #define tu_ntohs(u16) (u16) - #define tu_htole16(x) tu_bswap16(u32) - #define tu_le16toh(x) tu_bswap16(u32) + #define tu_htonl(u32) (u32) + #define tu_ntohl(u32) (u32) - #define tu_htole32(x) tu_bswap32(u32) - #define tu_le32toh(x) tu_bswap32(u32) + + #define tu_htole16(u16) (tu_bswap16(u16)) + #define tu_le16toh(u16) (tu_bswap16(u16)) + + #define tu_htole32(u32) (tu_bswap32(u32)) + #define tu_le32toh(u32) (tu_bswap32(u32)) #else #error Byte order is undefined From eea71a8b3b080299ad95ac79a7d45b2dc0d5b6f6 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Wed, 18 Sep 2019 19:24:54 -0400 Subject: [PATCH 25/45] usbtmc updates.... --- examples/device/usbtmc/src/tusb_config.h | 4 +- examples/device/usbtmc/src/usbtmc_app.c | 32 ++- src/class/usbtmc/usbtmc.h | 14 ++ src/class/usbtmc/usbtmc_device.c | 279 +++++++++++++++++------ src/class/usbtmc/usbtmc_device.h | 6 +- 5 files changed, 261 insertions(+), 74 deletions(-) diff --git a/examples/device/usbtmc/src/tusb_config.h b/examples/device/usbtmc/src/tusb_config.h index 022dc7691..16484424a 100644 --- a/examples/device/usbtmc/src/tusb_config.h +++ b/examples/device/usbtmc/src/tusb_config.h @@ -56,8 +56,8 @@ //------------- CLASS -------------// #define CFG_TUD_USBTMC 1 -#define CFG_TUD_USBTMC_ENABLE_INT_EP -//#define USBTMC_CFG_ENABLE_488 0 +#define CFG_TUD_USBTMC_ENABLE_INT_EP 1 +#define USBTMC_CFG_ENABLE_488 1 #ifdef __cplusplus } diff --git a/examples/device/usbtmc/src/usbtmc_app.c b/examples/device/usbtmc/src/usbtmc_app.c index e21c3ca22..03800ab17 100644 --- a/examples/device/usbtmc/src/usbtmc_app.c +++ b/examples/device/usbtmc/src/usbtmc_app.c @@ -64,8 +64,8 @@ usbtmcd_app_capabilities = } #endif }; -//static const char idn[] = "TinyUSB,ModelNumber,SerialNumber,FirmwareVer"; -static const char idn[] = "TinyUSB,ModelNumber,SerialNumber,FirmwareVer and a bunch of other text to make it longer than a packet, perhaps?\n"; +static const char idn[] = "TinyUSB,ModelNumber,SerialNumber,FirmwareVer123456\r\n"; +//static const char idn[] = "TinyUSB,ModelNumber,SerialNumber,FirmwareVer and a bunch of other text to make it longer than a packet, perhaps? lets make it three transfers...\n"; static volatile uint8_t status; // 0=not query, 1=queried, 2=delay,set(MAV), 3=delay 4=ready? @@ -154,14 +154,14 @@ void usbtmc_app_task_iter(void) { queryState = 2; break; case 2: - if( (board_millis() - queryDelayStart) > 5u) { + if( (board_millis() - queryDelayStart) > 200u) { queryDelayStart = board_millis(); queryState=3; status |= 0x10u; // MAV } break; case 3: - if( (board_millis() - queryDelayStart) > 10u) { + if( (board_millis() - queryDelayStart) > 400u) { queryState = 4; } break; @@ -169,6 +169,7 @@ void usbtmc_app_task_iter(void) { if(bulkInStarted) { queryState = 0; bulkInStarted = 0; + uart_tx_str_sync("usbtmc_app_task_iter: sending rsp!\r\n"); usbtmcd_transmit_dev_msg_data(rhport, idn, tu_min32(sizeof(idn)-1,msgReqLen),false); // MAV is cleared in the transfer complete callback. } @@ -189,7 +190,7 @@ bool usbtmcd_app_initiate_clear(uint8_t rhport, uint8_t *tmcResult) return true; } -bool usbtmcd_app_get_clear_status(uint8_t rhport, usbtmc_get_clear_status_rsp_t *rsp) +bool usbtmcd_app_check_clear(uint8_t rhport, usbtmc_get_clear_status_rsp_t *rsp) { (void)rhport; queryState = 0; @@ -199,6 +200,27 @@ bool usbtmcd_app_get_clear_status(uint8_t rhport, usbtmc_get_clear_status_rsp_t rsp->bmClear.BulkInFifoBytes = 0u; return true; } +bool usbtmcd_app_initiate_abort_bulk_in(uint8_t rhport, uint8_t *tmcResult) +{ + bulkInStarted = 0; + *tmcResult = USBTMC_STATUS_SUCCESS; + return true; +} +bool usbtmcd_app_check_abort_bulk_in(uint8_t rhport, usbtmc_check_abort_bulk_rsp_t *rsp) +{ + return true; +} + +bool usbtmcd_app_initiate_abort_bulk_out(uint8_t rhport, uint8_t *tmcResult) +{ + *tmcResult = USBTMC_STATUS_SUCCESS; + return true; + +} +bool usbtmcd_app_check_abort_bulk_out(uint8_t rhport, usbtmc_check_abort_bulk_rsp_t *rsp) +{ + return true; +} void usmtmcd_app_bulkIn_clearFeature(uint8_t rhport) { diff --git a/src/class/usbtmc/usbtmc.h b/src/class/usbtmc/usbtmc.h index 6893c3743..0944c907a 100644 --- a/src/class/usbtmc/usbtmc.h +++ b/src/class/usbtmc/usbtmc.h @@ -237,6 +237,20 @@ typedef struct TU_ATTR_PACKED TU_VERIFY_STATIC(sizeof(usbtmc_get_clear_status_rsp_t) == 2u, "struct wrong length"); +// Used for both check_abort_bulk_in_status and check_abort_bulk_out_status +typedef struct TU_ATTR_PACKED +{ + uint8_t USBTMC_status; + struct TU_ATTR_PACKED + { + unsigned int BulkInFifoBytes : 1; ///< Has queued data or a short packet that is queued + } bmAbortBulkIn; + uint8_t _reserved[2]; ///< Must be zero + uint32_t NBYTES_RXD_TXD; +} usbtmc_check_abort_bulk_rsp_t; + +TU_VERIFY_STATIC(sizeof(usbtmc_check_abort_bulk_rsp_t) == 8u, "struct wrong length"); + typedef struct TU_ATTR_PACKED { uint8_t USBTMC_status; ///< usbtmc_status_enum diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index 6d562641e..c71d4d963 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -93,8 +93,11 @@ typedef enum STATE_RCV, STATE_TX_REQUESTED, STATE_TX_INITIATED, + STATE_TX_SHORTED, STATE_CLEARING, STATE_ABORTING_BULK_IN, + STATE_ABORTING_BULK_IN_SHORTED, // aborting, and short packet has been queued for transmission + STATE_ABORTING_BULK_IN_ABORTED, // aborting, and short packet has been queued for transmission STATE_ABORTING_BULK_OUT, STATE_NUM_STATES } usbtmcd_state_enum; @@ -113,6 +116,7 @@ typedef struct // OUT buffer receives one packet at a time uint8_t ep_bulk_out_buf[USBTMCD_MAX_PACKET_SIZE]; uint32_t transfer_size_remaining; // also used for requested length for bulk IN. + uint32_t transfer_size_sent; // To keep track of data bytes that have been queued in FIFO (not header bytes) uint8_t lastBulkOutTag; // used for aborts (mostly) uint8_t lastBulkInTag; // used for aborts (mostly) @@ -128,6 +132,11 @@ static usbtmc_interface_state_t usbtmc_state = .ep_bulk_out = 0, .ep_int_in = 0 }; +#ifdef xDEBUG +#define TRACE(str) uart_tx_str_sync(str) +#else +#define TRACE(STR) do {} while (0) +#endif // We need all headers to fit in a single packet in this implementation. TU_VERIFY_STATIC(USBTMCD_MAX_PACKET_SIZE >= 32u,"USBTMC dev EP packet size too small"); @@ -188,7 +197,7 @@ bool usbtmcd_transmit_dev_msg_data( if((packetLen + hdr->TransferSize) <= txBufLen) { memcpy((uint8_t*)(usbtmc_state.ep_bulk_in_buf) + packetLen, data, hdr->TransferSize); - packetLen = (uint16_t)(packetLen+ hdr->TransferSize); + packetLen = (uint16_t)(packetLen + hdr->TransferSize); // Pad up to multiple of 4 bytes while((packetLen % 4) != 0) { @@ -196,13 +205,15 @@ bool usbtmcd_transmit_dev_msg_data( packetLen++; } usbtmc_state.transfer_size_remaining = 0; + usbtmc_state.transfer_size_sent = len; usbtmc_state.devInBuffer = NULL; } else /* partial packet */ { memcpy((uint8_t*)(usbtmc_state.ep_bulk_in_buf) + packetLen, data, txBufLen - packetLen); - usbtmc_state.devInBuffer += txBufLen - packetLen; - usbtmc_state.transfer_size_remaining = hdr->TransferSize - (txBufLen - packetLen); + usbtmc_state.devInBuffer = (uint8_t*)data + (txBufLen - packetLen); + usbtmc_state.transfer_size_remaining = len - (txBufLen - packetLen); + usbtmc_state.transfer_size_sent = txBufLen - packetLen; packetLen = txBufLen; } @@ -210,7 +221,8 @@ bool usbtmcd_transmit_dev_msg_data( criticalEnter(); { TU_VERIFY(usbtmc_state.state == STATE_TX_REQUESTED); - usbtmc_state.state = STATE_TX_INITIATED; + // We used packetlen as a max, not the buffer size, so this is OK here, no need for modulus + usbtmc_state.state = (packetLen >= txBufLen) ? STATE_TX_INITIATED : STATE_TX_SHORTED; } criticalLeave(); @@ -322,6 +334,8 @@ void usbtmcd_reset(uint8_t rhport) usbtmc_state.ep_bulk_in = 0; usbtmc_state.ep_bulk_out = 0; usbtmc_state.ep_int_in = 0; + usbtmc_state.lastBulkInTag = 0; + usbtmc_state.lastBulkOutTag = 0; (void)rhport; } @@ -351,10 +365,16 @@ static bool handle_devMsgOut(uint8_t rhport, void *data, size_t len, size_t pack if(len > usbtmc_state.transfer_size_remaining) len = usbtmc_state.transfer_size_remaining; usbtmcd_app_msg_data(rhport,data, len, atEnd); + + usbtmc_state.transfer_size_sent += len; if(atEnd) + { usbtmc_state.state = STATE_IDLE; + } else + { usbtmc_state.state = STATE_RCV; + } return true; } @@ -363,8 +383,10 @@ static bool handle_devMsgIn(uint8_t rhport, void *data, size_t len) TU_VERIFY(len == sizeof(usbtmc_msg_request_dev_dep_in)); usbtmc_msg_request_dev_dep_in *msg = (usbtmc_msg_request_dev_dep_in*)data; +#ifdef xDebug sprintf(logMsg," handle_devMsgIn len=%ul\r\n",len); - uart_tx_str_sync(logMsg); + TRACE(logMsg); +#endif criticalEnter(); { @@ -387,10 +409,13 @@ static bool handle_devMsgIn(uint8_t rhport, void *data, size_t len) bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { + TRACE("USBTMC Xfer CB" ); TU_VERIFY(result == XFER_RESULT_SUCCESS); - uart_tx_str_sync("USBTMC Xfer CB" ); + +#ifdef xDebug sprintf(logMsg," STATE=%lu ", (uint32_t)usbtmc_state.state); - uart_tx_str_sync(logMsg); + TRACE(logMsg); +#endif if(usbtmc_state.state == STATE_CLEARING) { return true; /* I think we can ignore everything here */ @@ -398,23 +423,26 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint if(ep_addr == usbtmc_state.ep_bulk_out) { - uart_tx_str_sync("OUT"); + usbtmc_msg_generic_t *msg = NULL; + TRACE("OUT"); switch(usbtmc_state.state) { case STATE_IDLE: TU_VERIFY(xferred_bytes >= sizeof(usbtmc_msg_generic_t)); - usbtmc_msg_generic_t *msg = (usbtmc_msg_generic_t*)(usbtmc_state.ep_bulk_out_buf); + msg = (usbtmc_msg_generic_t*)(usbtmc_state.ep_bulk_out_buf); uint8_t invInvTag = (uint8_t)~(msg->header.bTagInverse); TU_VERIFY(msg->header.bTag == invInvTag); TU_VERIFY(msg->header.bTag != 0x00); +#ifdef xDebug sprintf(logMsg," type=%lu\r\n",(uint32_t)msg->header.MsgID); - uart_tx_str_sync(logMsg); + TRACE(logMsg); +#endif switch(msg->header.MsgID) { case USBTMC_MSGID_DEV_DEP_MSG_OUT: + usbtmc_state.transfer_size_sent = 0u; TU_VERIFY(handle_devMsgOutStart(rhport, msg, xferred_bytes)); - TU_VERIFY(usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, USBTMCD_MAX_PACKET_SIZE)); usbtmc_state.lastBulkOutTag = msg->header.bTag; break; @@ -428,7 +456,6 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint // Spec says we halt the EP if we didn't declare we support it. TU_VERIFY(usbtmcd_app_capabilities.bmIntfcCapabilities488.supportsTrigger); TU_VERIFY(usbtmcd_app_msg_trigger(rhport, msg)); - TU_VERIFY(usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, USBTMCD_MAX_PACKET_SIZE)); break; #endif @@ -439,58 +466,95 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint TU_VERIFY(false); return false; } + TU_VERIFY(usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, USBTMCD_MAX_PACKET_SIZE)); return true; case STATE_RCV: TU_VERIFY(handle_devMsgOut(rhport, usbtmc_state.ep_bulk_out_buf, xferred_bytes, xferred_bytes)); return true; + case STATE_ABORTING_BULK_OUT: + TU_VERIFY(false); + return false; // Shold be stalled by now... case STATE_TX_REQUESTED: case STATE_TX_INITIATED: case STATE_ABORTING_BULK_IN: - case STATE_ABORTING_BULK_OUT: + case STATE_ABORTING_BULK_IN_SHORTED: + case STATE_ABORTING_BULK_IN_ABORTED: default: + +#ifdef xDebug if(msg == NULL) sprintf(logMsg," Unknown received control?\r\n "); else { sprintf(logMsg," msg=%lu\r\n ", (uint32_t)msg->header.MsgID); } - uart_tx_str_sync(logMsg); + TRACE(logMsg); +#endif TU_VERIFY(false); } } else if(ep_addr == usbtmc_state.ep_bulk_in) { +#ifdef xDebug sprintf(logMsg,"IN\r\n"); - uart_tx_str_sync(logMsg); - TU_ASSERT(usbtmc_state.state == STATE_TX_INITIATED); - if(usbtmc_state.transfer_size_remaining == 0) - { + TRACE(logMsg); +#endif + switch(usbtmc_state.state) { + case STATE_TX_SHORTED: + + TRACE("IN TX shorted done\r\n"); + usbtmc_state.state = STATE_IDLE; TU_VERIFY(usbtmcd_app_msgBulkIn_complete(rhport)); - TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, USBTMCD_MAX_PACKET_SIZE)); - } - else if(usbtmc_state.transfer_size_remaining > sizeof(usbtmc_state.devInBuffer)) - { - memcpy(usbtmc_state.ep_bulk_in_buf, usbtmc_state.devInBuffer, sizeof(usbtmc_state.ep_bulk_in_buf)); - usbtmc_state.devInBuffer += sizeof(usbtmc_state.devInBuffer); - usbtmc_state.transfer_size_remaining -= sizeof(usbtmc_state.devInBuffer); - TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf,sizeof(usbtmc_state.devInBuffer))); - } - else // last packet - { - size_t packetLen = usbtmc_state.transfer_size_remaining; - memcpy(usbtmc_state.ep_bulk_in_buf, usbtmc_state.devInBuffer, usbtmc_state.transfer_size_remaining); - while((packetLen % 4) != 0) + break; + + case STATE_TX_INITIATED: + if(usbtmc_state.transfer_size_remaining >=sizeof(usbtmc_state.ep_bulk_in_buf)) { - usbtmc_state.ep_bulk_in_buf[packetLen] = 0; - packetLen++; + TRACE("IN TX continuing\r\n"); + memcpy(usbtmc_state.ep_bulk_in_buf, usbtmc_state.devInBuffer, sizeof(usbtmc_state.ep_bulk_in_buf)); + usbtmc_state.devInBuffer += sizeof(usbtmc_state.devInBuffer); + usbtmc_state.transfer_size_remaining -= sizeof(usbtmc_state.devInBuffer); + usbtmc_state.transfer_size_sent += sizeof(usbtmc_state.devInBuffer); + TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf,sizeof(usbtmc_state.devInBuffer))); } - usbtmc_state.transfer_size_remaining = 0; - usbtmc_state.devInBuffer = NULL; - TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf,(uint16_t)packetLen)); + else // last packet + { + TRACE("IN TX last packet\r\n"); + size_t packetLen = usbtmc_state.transfer_size_remaining; + memcpy(usbtmc_state.ep_bulk_in_buf, usbtmc_state.devInBuffer, usbtmc_state.transfer_size_remaining); + while((packetLen % 4) != 0) + { + usbtmc_state.ep_bulk_in_buf[packetLen] = 0u; + packetLen++; + } + usbtmc_state.transfer_size_sent += sizeof(usbtmc_state.transfer_size_remaining); + usbtmc_state.transfer_size_remaining = 0; + usbtmc_state.devInBuffer = NULL; + TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf,(uint16_t)packetLen)); + if(((packetLen % USBTMCD_MAX_PACKET_SIZE) != 0) || (packetLen == 0 )) + { + usbtmc_state.state = STATE_TX_SHORTED; + } + } + return true; + case STATE_ABORTING_BULK_IN: + // need to send short packet (ZLP?) + TRACE("IN aborting\r\n"); + TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf,(uint16_t)0u)); + usbtmc_state.state = STATE_ABORTING_BULK_IN_SHORTED; + return true; + case STATE_ABORTING_BULK_IN_SHORTED: + /* Done. :)*/ + TRACE("IN shorted\r\n"); + usbtmc_state.state = STATE_ABORTING_BULK_IN_ABORTED; + return true; + default: + TRACE("IN unknown\r\n"); + TU_ASSERT(false); + return false; } - return true; } else if (ep_addr == usbtmc_state.ep_int_in) { // Good? @@ -505,13 +569,14 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ #if (USBTMC_CFG_ENABLE_488) uint8_t bTag; #endif + TRACE("xfer cb\r\n"); if((request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD) && (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_ENDPOINT) && (request->bRequest == TUSB_REQ_CLEAR_FEATURE) && (request->wValue == TUSB_REQ_FEATURE_EDPT_HALT)) { - uart_tx_str_sync("feature clear\r\n"); + TRACE("feature clear\r\n"); if((request->wIndex) == usbtmc_state.ep_bulk_out) { usmtmcd_app_bulkOut_clearFeature(rhport); @@ -536,42 +601,124 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ { // USBTMC required requests case USBTMC_bREQUEST_INITIATE_ABORT_BULK_OUT: - case USBTMC_bREQUEST_CHECK_ABORT_BULK_OUT_STATUS: { - TU_VERIFY(request->bmRequestType == 0xA2); // in,class,EP - TU_VERIFY(request->wLength == 1u); - tmcStatusCode = USBTMC_STATUS_FAILED; - usbd_edpt_xfer(rhport, 0u, (void*)&tmcStatusCode,sizeof(tmcStatusCode)); + usbtmc_initiate_abort_rsp_t rsp = { + .bTag = usbtmc_state.lastBulkOutTag, + }; + TRACE("init abort bulk out\r\n"); + TU_VERIFY(request->bmRequestType == 0xA2); // in,class,interface + TU_VERIFY(request->wLength == sizeof(rsp)); + TU_VERIFY(request->wIndex == usbtmc_state.ep_bulk_out); + + // wValue is the requested bTag to abort + if(usbtmc_state.state != STATE_RCV) + { + rsp.USBTMC_status = USBTMC_STATUS_FAILED; + TRACE("init abort bulk out failed\r\n"); + } + else if(usbtmc_state.lastBulkOutTag == (request->wValue & 0xf7u)) + { + rsp.USBTMC_status = USBTMC_STATUS_TRANSFER_NOT_IN_PROGRESS; + TRACE("init abort bulk out not inprogress\r\n"); + } + else + { + rsp.USBTMC_status = USBTMC_STATUS_SUCCESS; + // Check if we've queued a short packet + usbtmc_state.state = STATE_ABORTING_BULK_OUT; + TU_VERIFY(usbtmcd_app_initiate_abort_bulk_out(rhport, &(rsp.USBTMC_status))); + usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out); + TRACE("init abort bulk out success\r\n"); + } + TU_VERIFY(tud_control_xfer(rhport, request, (void*)&rsp,sizeof(rsp))); return true; } - case USBTMC_bREQUEST_CHECK_ABORT_BULK_IN_STATUS: + case USBTMC_bREQUEST_CHECK_ABORT_BULK_OUT_STATUS: { + TRACE("init check abort bulk out\r\n"); + usbtmc_check_abort_bulk_rsp_t rsp = { + .USBTMC_status = USBTMC_STATUS_SUCCESS, + .NBYTES_RXD_TXD = usbtmc_state.transfer_size_sent + }; TU_VERIFY(request->bmRequestType == 0xA2); // in,class,EP - TU_VERIFY(request->wLength == 1u); - usbtmc_get_clear_status_rsp_t clearStatusRsp = {0}; - tmcStatusCode = USBTMC_STATUS_FAILED; - usbd_edpt_xfer(rhport, 0u, (void*)&tmcStatusCode,sizeof(tmcStatusCode)); + TU_VERIFY(request->wLength == sizeof(rsp)); + TU_VERIFY(request->wIndex == usbtmc_state.ep_bulk_out); + TU_VERIFY(usbtmcd_app_check_abort_bulk_out(rhport, &(rsp.USBTMC_status))); + TU_VERIFY(usbd_edpt_xfer(rhport, 0u, (void*)&rsp,sizeof(rsp))); return true; } case USBTMC_bREQUEST_INITIATE_ABORT_BULK_IN: { - usbtmc_initiate_abort_rsp_t rsp = {0}; - uart_tx_str_sync("init abort bulk in\r\n"); - TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface - TU_VERIFY(request->wLength == sizeof(tmcStatusCode)); - TU_VERIFY(request->wIndex == usbtmc_state.ep_int_in); + usbtmc_initiate_abort_rsp_t rsp = { + .bTag = usbtmc_state.lastBulkInTag, + }; + TRACE("init abort bulk in\r\n"); + TU_VERIFY(request->bmRequestType == 0xA2); // in,class,interface + TU_VERIFY(request->wLength == sizeof(rsp)); + TU_VERIFY(request->wIndex == usbtmc_state.ep_bulk_in); // wValue is the requested bTag to abort - usbtmc_state.transfer_size_remaining = 0; - usbtmc_state.state = STATE_ABORTING_BULK_IN; - TU_VERIFY(usbtmcd_app_initiate_clear(rhport, &tmcStatusCode)); - TU_VERIFY(tud_control_xfer(rhport, request, (void*)&tmcStatusCode,sizeof(tmcStatusCode))); + if((usbtmc_state.state == STATE_TX_REQUESTED || usbtmc_state.state == STATE_TX_INITIATED) && + usbtmc_state.lastBulkInTag == (request->wValue & 0xf7u)) + { + rsp.USBTMC_status = USBTMC_STATUS_SUCCESS; + usbtmc_state.transfer_size_remaining = 0; + // Check if we've queued a short packet + usbtmc_state.state = ((usbtmc_state.transfer_size_sent % USBTMCD_MAX_PACKET_SIZE) != 0) ? + STATE_ABORTING_BULK_IN : STATE_ABORTING_BULK_IN_SHORTED; + TU_VERIFY(usbtmcd_app_initiate_abort_bulk_in(rhport, &(rsp.USBTMC_status))); + TRACE("init abort bulk success\r\n"); + } + else if((usbtmc_state.state == STATE_TX_REQUESTED || usbtmc_state.state == STATE_TX_INITIATED)) + { // FIXME: Unsure how to check if the OUT endpoint fifo is non-empty.... + rsp.USBTMC_status = USBTMC_STATUS_TRANSFER_NOT_IN_PROGRESS; + TRACE("init abort bulk in not in progress\r\n"); + } + else + { + rsp.USBTMC_status = USBTMC_STATUS_FAILED; + TRACE("init abort bulk in failed\r\n"); + } + TU_VERIFY(tud_control_xfer(rhport, request, (void*)&rsp,sizeof(rsp))); + return true; + } + + case USBTMC_bREQUEST_CHECK_ABORT_BULK_IN_STATUS: + { + TRACE("xfer check abort in\r\n"); + TU_VERIFY(request->bmRequestType == 0xA2); // in,class,EP + TU_VERIFY(request->wLength == 8u); + + usbtmc_check_abort_bulk_rsp_t rsp = + { + .USBTMC_status = USBTMC_STATUS_FAILED, + .bmAbortBulkIn = + { + .BulkInFifoBytes = (usbtmc_state.state == STATE_ABORTING_BULK_IN_ABORTED) + }, + .NBYTES_RXD_TXD = usbtmc_state.transfer_size_sent, + }; + TU_VERIFY(usbtmcd_app_check_abort_bulk_in(rhport, &rsp)); + switch(usbtmc_state.state) + { + case STATE_ABORTING_BULK_IN_ABORTED: + rsp.USBTMC_status = USBTMC_STATUS_SUCCESS; + break; + case STATE_ABORTING_BULK_IN: + case STATE_ABORTING_BULK_OUT: + rsp.USBTMC_status = USBTMC_STATUS_PENDING; + break; + default: + break; + } + TU_VERIFY(tud_control_xfer(rhport, request, (void*)&rsp,sizeof(rsp))); + return true; } case USBTMC_bREQUEST_INITIATE_CLEAR: { - uart_tx_str_sync("init clear\r\n"); + TRACE("init clear\r\n"); TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface TU_VERIFY(request->wLength == sizeof(tmcStatusCode)); // After receiving an INITIATE_CLEAR request, the device must Halt the Bulk-OUT endpoint, queue the @@ -586,7 +733,7 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ case USBTMC_bREQUEST_CHECK_CLEAR_STATUS: { - uart_tx_str_sync("check clear\r\n"); + TRACE("check clear\r\n"); TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface usbtmc_get_clear_status_rsp_t clearStatusRsp = {0}; TU_VERIFY(request->wLength == sizeof(clearStatusRsp)); @@ -600,7 +747,7 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ else { // Let app check if it's clear - TU_VERIFY(usbtmcd_app_get_clear_status(rhport, &clearStatusRsp)); + TU_VERIFY(usbtmcd_app_check_clear(rhport, &clearStatusRsp)); } if(clearStatusRsp.USBTMC_status == USBTMC_STATUS_SUCCESS) usbtmc_state.state = STATE_IDLE; @@ -610,7 +757,7 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ case USBTMC_bREQUEST_GET_CAPABILITIES: { - uart_tx_str_sync("get capabilities\r\n"); + TRACE("get capabilities\r\n"); TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface TU_VERIFY(request->wLength == sizeof(usbtmcd_app_capabilities)); TU_VERIFY(tud_control_xfer(rhport, request, (void*)&usbtmcd_app_capabilities, sizeof(usbtmcd_app_capabilities))); @@ -620,7 +767,7 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ case USBTMC_bREQUEST_INDICATOR_PULSE: // Optional { - uart_tx_str_sync("indicate\r\n"); + TRACE("indicate\r\n"); TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface TU_VERIFY(request->wLength == sizeof(tmcStatusCode)); TU_VERIFY(usbtmcd_app_capabilities.bmIntfcCapabilities.supportsIndicatorPulse); @@ -633,7 +780,7 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ // USB488 required requests case USBTMC488_bREQUEST_READ_STATUS_BYTE: { - uart_tx_str_sync("read stb\r\n"); + TRACE("read stb\r\n"); usbtmc_read_stb_rsp_488_t rsp; TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface TU_VERIFY(request->wLength == sizeof(rsp)); // in,class,interface @@ -672,7 +819,7 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ case USBTMC488_bREQUEST_GO_TO_LOCAL: case USBTMC488_bREQUEST_LOCAL_LOCKOUT: { - uart_tx_str_sync("Unsupported REN/GTL/LLO\r\n"); + TRACE("Unsupported REN/GTL/LLO\r\n"); TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface TU_VERIFY(false); return false; @@ -680,7 +827,7 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ #endif default: - uart_tx_str_sync("Default CTRL handler\r\n"); + TRACE("Default CTRL handler\r\n"); TU_VERIFY(false); return false; } diff --git a/src/class/usbtmc/usbtmc_device.h b/src/class/usbtmc/usbtmc_device.h index a0ba82e30..4c991d5ff 100644 --- a/src/class/usbtmc/usbtmc_device.h +++ b/src/class/usbtmc/usbtmc_device.h @@ -64,9 +64,13 @@ bool usbtmcd_app_msgBulkIn_request(uint8_t rhport, usbtmc_msg_request_dev_dep_in bool usbtmcd_app_msgBulkIn_complete(uint8_t rhport); void usmtmcd_app_bulkIn_clearFeature(uint8_t rhport); // Notice to clear and abort the pending BULK out transfer +bool usbtmcd_app_initiate_abort_bulk_in(uint8_t rhport, uint8_t *tmcResult); +bool usbtmcd_app_initiate_abort_bulk_out(uint8_t rhport, uint8_t *tmcResult); bool usbtmcd_app_initiate_clear(uint8_t rhport, uint8_t *tmcResult); -bool usbtmcd_app_get_clear_status(uint8_t rhport, usbtmc_get_clear_status_rsp_t *rsp); +bool usbtmcd_app_check_abort_bulk_in(uint8_t rhport, usbtmc_check_abort_bulk_rsp_t *rsp); +bool usbtmcd_app_check_abort_bulk_out(uint8_t rhport, usbtmc_check_abort_bulk_rsp_t *rsp); +bool usbtmcd_app_check_clear(uint8_t rhport, usbtmc_get_clear_status_rsp_t *rsp); // Indicator pulse should be 0.5 to 1.0 seconds long TU_ATTR_WEAK bool usbtmcd_app_indicator_pluse(uint8_t rhport, tusb_control_request_t const * msg, uint8_t *tmcResult); From 99d03fcaee64104df96e332a2347aa7ecc1b6172 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Wed, 18 Sep 2019 19:30:44 -0400 Subject: [PATCH 26/45] small fixes --- examples/device/usbtmc/src/usbtmc_app.c | 10 +++++----- src/class/usbtmc/usbtmc_device.c | 13 +++++++++---- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/examples/device/usbtmc/src/usbtmc_app.c b/examples/device/usbtmc/src/usbtmc_app.c index 03800ab17..7132f5143 100644 --- a/examples/device/usbtmc/src/usbtmc_app.c +++ b/examples/device/usbtmc/src/usbtmc_app.c @@ -86,7 +86,7 @@ bool usbtmcd_app_msgBulkOut_start(uint8_t rhport, usbtmc_msg_request_dev_dep_out { (void)rhport; (void)msgHeader; - uart_tx_str_sync("MSG_OUT_DATA: start\r\n"); + //uart_tx_str_sync("MSG_OUT_DATA: start\r\n"); return true; } bool usbtmcd_app_msg_trigger(uint8_t rhport, usbtmc_msg_generic_t* msg) { @@ -100,12 +100,12 @@ bool usbtmcd_app_msg_data(uint8_t rhport, void *data, size_t len, bool transfer_ (void)rhport; // If transfer isn't finished, we just ignore it (for now) - uart_tx_str_sync("MSG_OUT_DATA: <<<"); + /*uart_tx_str_sync("MSG_OUT_DATA: <<<"); uart_tx_sync(data,len); uart_tx_str_sync(">>>\r\n"); if(transfer_complete) uart_tx_str_sync("MSG_OUT_DATA: Complete\r\n"); - +*/ if(transfer_complete && (len >=4) && !strncasecmp("*idn?",data,4)) { queryState = 1; } @@ -132,7 +132,7 @@ bool usbtmcd_app_msgBulkIn_request(uint8_t rhport, usbtmc_msg_request_dev_dep_in rspMsg.header.bTagInverse = request->header.bTagInverse; msgReqLen = request->TransferSize; - uart_tx_str_sync("MSG_IN_DATA: Requested!\r\n"); + //uart_tx_str_sync("MSG_IN_DATA: Requested!\r\n"); TU_ASSERT(bulkInStarted == 0); bulkInStarted = 1; @@ -169,7 +169,7 @@ void usbtmc_app_task_iter(void) { if(bulkInStarted) { queryState = 0; bulkInStarted = 0; - uart_tx_str_sync("usbtmc_app_task_iter: sending rsp!\r\n"); + //uart_tx_str_sync("usbtmc_app_task_iter: sending rsp!\r\n"); usbtmcd_transmit_dev_msg_data(rhport, idn, tu_min32(sizeof(idn)-1,msgReqLen),false); // MAV is cleared in the transfer complete callback. } diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index c71d4d963..0f14fdfb4 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -31,8 +31,6 @@ * This file is part of the TinyUSB stack. */ -#include "tusb_option.h" - // Synchronization is needed in some spots. // These functions should NOT be called from interrupts. @@ -71,6 +69,9 @@ // Abort bulk in/out // No CLEAR_FEATURE/HALT no EP (yet) + +#include "tusb_option.h" + #if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_USBTMC) #include @@ -78,8 +79,12 @@ #include "usbtmc_device.h" #include "device/dcd.h" #include "device/usbd.h" + +#ifdef xDEBUG #include "uart_util.h" static char logMsg[150]; +#endif + // FIXME: I shouldn't need to include _pvt headers. #include "device/usbd_pvt.h" @@ -447,7 +452,7 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint break; case USBTMC_MSGID_DEV_DEP_MSG_IN: - uart_tx_sync("Handling msg in req\r\n", 21); + TRACE("Handling msg in req\r\n"); TU_VERIFY(handle_devMsgIn(rhport, msg, xferred_bytes)); break; @@ -643,7 +648,7 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ TU_VERIFY(request->bmRequestType == 0xA2); // in,class,EP TU_VERIFY(request->wLength == sizeof(rsp)); TU_VERIFY(request->wIndex == usbtmc_state.ep_bulk_out); - TU_VERIFY(usbtmcd_app_check_abort_bulk_out(rhport, &(rsp.USBTMC_status))); + TU_VERIFY(usbtmcd_app_check_abort_bulk_out(rhport, &rsp)); TU_VERIFY(usbd_edpt_xfer(rhport, 0u, (void*)&rsp,sizeof(rsp))); return true; } From 9a726dc7ed9af8f9b035b18a667105a48d8d6d8a Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Wed, 18 Sep 2019 21:31:38 -0400 Subject: [PATCH 27/45] More fixes, and a bit of SRQ. --- examples/device/usbtmc/src/usbtmc_app.c | 78 ++++++++++++++++++------- examples/device/usbtmc/visaQuery.py | 69 ++++++++++++++++++++++ src/class/usbtmc/usbtmc_device.c | 44 +++++++------- 3 files changed, 150 insertions(+), 41 deletions(-) create mode 100644 examples/device/usbtmc/visaQuery.py diff --git a/examples/device/usbtmc/src/usbtmc_app.c b/examples/device/usbtmc/src/usbtmc_app.c index 7132f5143..024f7de10 100644 --- a/examples/device/usbtmc/src/usbtmc_app.c +++ b/examples/device/usbtmc/src/usbtmc_app.c @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2019 N Conrad + * Copyright (c) 2019 Nathan Conrad * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -73,6 +73,11 @@ static volatile uint8_t status; static volatile uint16_t queryState = 0; static volatile uint32_t queryDelayStart; static volatile uint32_t bulkInStarted; +static volatile uint32_t idnQuery; + +static size_t buffer_len; +static uint8_t buffer[225]; // A few packets long should be enough. + static usbtmc_msg_dev_dep_msg_in_header_t rspMsg = { .bmTransferAttributes = @@ -82,16 +87,20 @@ static usbtmc_msg_dev_dep_msg_in_header_t rspMsg = { } }; +bool usbtmcd_app_msg_trigger(uint8_t rhport, usbtmc_msg_generic_t* msg) { + (void)rhport; + (void)msg; + return true; +} + bool usbtmcd_app_msgBulkOut_start(uint8_t rhport, usbtmc_msg_request_dev_dep_out const * msgHeader) { (void)rhport; (void)msgHeader; - //uart_tx_str_sync("MSG_OUT_DATA: start\r\n"); - return true; -} -bool usbtmcd_app_msg_trigger(uint8_t rhport, usbtmc_msg_generic_t* msg) { - (void)rhport; - (void)msg; +#ifdef xDEBUG + uart_tx_str_sync("MSG_OUT_DATA: start\r\n"); +#endif + buffer_len = 0; return true; } @@ -100,14 +109,25 @@ bool usbtmcd_app_msg_data(uint8_t rhport, void *data, size_t len, bool transfer_ (void)rhport; // If transfer isn't finished, we just ignore it (for now) - /*uart_tx_str_sync("MSG_OUT_DATA: <<<"); +#ifdef xDEBUG + uart_tx_str_sync("MSG_OUT_DATA: <<<"); uart_tx_sync(data,len); uart_tx_str_sync(">>>\r\n"); if(transfer_complete) uart_tx_str_sync("MSG_OUT_DATA: Complete\r\n"); -*/ - if(transfer_complete && (len >=4) && !strncasecmp("*idn?",data,4)) { - queryState = 1; +#endif + + if(len + buffer_len < sizeof(buffer)) + { + memcpy(&(buffer[buffer_len]), data, len); + buffer_len += len; + } + queryState = transfer_complete; + idnQuery = 0; + + if(transfer_complete && (len >=4) && !strncasecmp("*idn?",data,4)) + { + idnQuery = 1; } return true; } @@ -116,7 +136,7 @@ bool usbtmcd_app_msgBulkIn_complete(uint8_t rhport) { (void)rhport; - status &= (uint8_t)~(0x10u); // clear MAV + status &= (uint8_t)~(0x50u); // clear MAV and SRQ return true; } @@ -131,8 +151,9 @@ bool usbtmcd_app_msgBulkIn_request(uint8_t rhport, usbtmc_msg_request_dev_dep_in rspMsg.header.bTag = request->header.bTag, rspMsg.header.bTagInverse = request->header.bTagInverse; msgReqLen = request->TransferSize; - - //uart_tx_str_sync("MSG_IN_DATA: Requested!\r\n"); +#ifdef xDEBUG + uart_tx_str_sync("MSG_IN_DATA: Requested!\r\n"); +#endif TU_ASSERT(bulkInStarted == 0); bulkInStarted = 1; @@ -145,7 +166,11 @@ bool usbtmcd_app_msgBulkIn_request(uint8_t rhport, usbtmc_msg_request_dev_dep_in void usbtmc_app_task_iter(void) { uint8_t const rhport = 0; - + uint32_t board_delay = 5u; + if(idnQuery) + { + board_delay = 350u; + } switch(queryState) { case 0: break; @@ -154,14 +179,15 @@ void usbtmc_app_task_iter(void) { queryState = 2; break; case 2: - if( (board_millis() - queryDelayStart) > 200u) { + if( (board_millis() - queryDelayStart) > board_delay) { queryDelayStart = board_millis(); queryState=3; status |= 0x10u; // MAV + status |= 0x40u; // SRQ } break; case 3: - if( (board_millis() - queryDelayStart) > 400u) { + if( (board_millis() - queryDelayStart) > board_delay) { queryState = 4; } break; @@ -169,8 +195,17 @@ void usbtmc_app_task_iter(void) { if(bulkInStarted) { queryState = 0; bulkInStarted = 0; - //uart_tx_str_sync("usbtmc_app_task_iter: sending rsp!\r\n"); - usbtmcd_transmit_dev_msg_data(rhport, idn, tu_min32(sizeof(idn)-1,msgReqLen),false); +#ifdef xDEBUG + uart_tx_str_sync("usbtmc_app_task_iter: sending rsp!\r\n"); +#endif + if(idnQuery) + { + usbtmcd_transmit_dev_msg_data(rhport, idn, tu_min32(sizeof(idn)-1,msgReqLen),false); + } + else + { + usbtmcd_transmit_dev_msg_data(rhport, buffer, tu_min32(buffer_len,msgReqLen),false); + } // MAV is cleared in the transfer complete callback. } break; @@ -235,10 +270,13 @@ void usmtmcd_app_bulkOut_clearFeature(uint8_t rhport) uint8_t usbtmcd_app_get_stb(uint8_t rhport, uint8_t *tmcResult) { (void)rhport; + uint8_t old_status = status; + status = status & ~(0x40); // clear SRQ + *tmcResult = USBTMC_STATUS_SUCCESS; // Increment status so that we see different results on each read... - return status; + return old_status; } bool usbtmcd_app_indicator_pluse(uint8_t rhport, tusb_control_request_t const * msg, uint8_t *tmcResult) diff --git a/examples/device/usbtmc/visaQuery.py b/examples/device/usbtmc/visaQuery.py new file mode 100644 index 000000000..fa3d7f5e8 --- /dev/null +++ b/examples/device/usbtmc/visaQuery.py @@ -0,0 +1,69 @@ +import visa +import time +import sys + + +def test_idn(): + idn = inst.query("*idn?"); + assert idn == "TinyUSB,ModelNumber,SerialNumber,FirmwareVer123456\r\n" + +def test_echo(): + longstr = "0123456789abcdef" * 50 + + #Next try echo from 1 to 175 characters (200 is max buffer size on DUT) + for i in range(49,175): + x = longstr[0:i] + xt = x + inst.write_termination + y = inst.query(x) + assert(xt == y), f"echo {i}" + +def test_mav(): + assert (inst.read_stb() == 0) + inst.write("123") + time.sleep(0.3) + assert (inst.read_stb() & 0x10), "MAV not set after 0.5 seconds" + + rsp = inst.read() + assert(rsp == "123\r\n") + + +def test_srq(): + assert (inst.read_stb() == 0) + inst.write("123") + + #inst.enable_event(visa.constants.VI_EVENT_SERVICE_REQ, visa.constants.VI_QUEUE) + #waitrsp = inst.wait_on_event(visa.constants.VI_EVENT_SERVICE_REQ, 5000) + #inst.discard_events(visa.constants.VI_EVENT_SERVICE_REQ, visa.constants.VI_QUEUE) + #inst.wait_for_srq() + time.sleep(0.3) + stb = inst.read_stb() + msg = "SRQ not set after 0.5 seconds, was {:02x}".format(stb) + assert (stb == 0x50),msg + + assert (inst.read_stb() == 0x10), "SRQ set at second read!" + + rsp = inst.read() + assert(rsp == "123\r\n") + + +rm = visa.ResourceManager("/c/Windows/system32/visa64.dll") +reslist = rm.list_resources("USB?::?*::INSTR") +print(reslist) + +if (len(reslist) == 0): + sys.exit() + +inst = rm.open_resource(reslist[0]); +inst.timeout = 3000 +inst.clear() + +#print(idn); +inst.clear() + +test_idn() +test_echo() +test_mav() +test_srq() + +inst.close() +print("Test complete") diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index 0f14fdfb4..27876852d 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -371,6 +371,7 @@ static bool handle_devMsgOut(uint8_t rhport, void *data, size_t len, size_t pack len = usbtmc_state.transfer_size_remaining; usbtmcd_app_msg_data(rhport,data, len, atEnd); + usbtmc_state.transfer_size_remaining -= len; usbtmc_state.transfer_size_sent += len; if(atEnd) { @@ -476,11 +477,12 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint case STATE_RCV: TU_VERIFY(handle_devMsgOut(rhport, usbtmc_state.ep_bulk_out_buf, xferred_bytes, xferred_bytes)); + TU_VERIFY(usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, USBTMCD_MAX_PACKET_SIZE)); return true; case STATE_ABORTING_BULK_OUT: TU_VERIFY(false); - return false; // Shold be stalled by now... + return false; // Should be stalled by now... case STATE_TX_REQUESTED: case STATE_TX_INITIATED: case STATE_ABORTING_BULK_IN: @@ -516,32 +518,32 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint case STATE_TX_INITIATED: if(usbtmc_state.transfer_size_remaining >=sizeof(usbtmc_state.ep_bulk_in_buf)) - { + { TRACE("IN TX continuing\r\n"); - memcpy(usbtmc_state.ep_bulk_in_buf, usbtmc_state.devInBuffer, sizeof(usbtmc_state.ep_bulk_in_buf)); - usbtmc_state.devInBuffer += sizeof(usbtmc_state.devInBuffer); - usbtmc_state.transfer_size_remaining -= sizeof(usbtmc_state.devInBuffer); + memcpy(usbtmc_state.ep_bulk_in_buf, usbtmc_state.devInBuffer, sizeof(usbtmc_state.ep_bulk_in_buf)); + usbtmc_state.devInBuffer += sizeof(usbtmc_state.devInBuffer); + usbtmc_state.transfer_size_remaining -= sizeof(usbtmc_state.devInBuffer); usbtmc_state.transfer_size_sent += sizeof(usbtmc_state.devInBuffer); - TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf,sizeof(usbtmc_state.devInBuffer))); - } - else // last packet - { + TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf,sizeof(usbtmc_state.devInBuffer))); + } + else // last packet + { TRACE("IN TX last packet\r\n"); - size_t packetLen = usbtmc_state.transfer_size_remaining; - memcpy(usbtmc_state.ep_bulk_in_buf, usbtmc_state.devInBuffer, usbtmc_state.transfer_size_remaining); - while((packetLen % 4) != 0) - { + size_t packetLen = usbtmc_state.transfer_size_remaining; + memcpy(usbtmc_state.ep_bulk_in_buf, usbtmc_state.devInBuffer, usbtmc_state.transfer_size_remaining); + while((packetLen % 4) != 0) + { usbtmc_state.ep_bulk_in_buf[packetLen] = 0u; - packetLen++; - } + packetLen++; + } usbtmc_state.transfer_size_sent += sizeof(usbtmc_state.transfer_size_remaining); - usbtmc_state.transfer_size_remaining = 0; - usbtmc_state.devInBuffer = NULL; - TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf,(uint16_t)packetLen)); + usbtmc_state.transfer_size_remaining = 0; + usbtmc_state.devInBuffer = NULL; + TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf,(uint16_t)packetLen)); if(((packetLen % USBTMCD_MAX_PACKET_SIZE) != 0) || (packetLen == 0 )) { usbtmc_state.state = STATE_TX_SHORTED; - } + } } return true; case STATE_ABORTING_BULK_IN: @@ -554,7 +556,7 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint /* Done. :)*/ TRACE("IN shorted\r\n"); usbtmc_state.state = STATE_ABORTING_BULK_IN_ABORTED; - return true; + return true; default: TRACE("IN unknown\r\n"); TU_ASSERT(false); @@ -667,7 +669,7 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ usbtmc_state.lastBulkInTag == (request->wValue & 0xf7u)) { rsp.USBTMC_status = USBTMC_STATUS_SUCCESS; - usbtmc_state.transfer_size_remaining = 0; + usbtmc_state.transfer_size_remaining = 0; // Check if we've queued a short packet usbtmc_state.state = ((usbtmc_state.transfer_size_sent % USBTMCD_MAX_PACKET_SIZE) != 0) ? STATE_ABORTING_BULK_IN : STATE_ABORTING_BULK_IN_SHORTED; From d4b2dff7c40f005be3ce4d383efcb59182a9a228 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Wed, 18 Sep 2019 23:53:28 -0400 Subject: [PATCH 28/45] Fix more TX bugs... and add variable response delay to the example project. --- examples/device/usbtmc/src/usbtmc_app.c | 27 ++++++++++------ examples/device/usbtmc/visaQuery.py | 37 +++++++++++++++++----- src/class/usbtmc/usbtmc_device.c | 42 ++++++++++--------------- 3 files changed, 63 insertions(+), 43 deletions(-) diff --git a/examples/device/usbtmc/src/usbtmc_app.c b/examples/device/usbtmc/src/usbtmc_app.c index 024f7de10..7c7431928 100644 --- a/examples/device/usbtmc/src/usbtmc_app.c +++ b/examples/device/usbtmc/src/usbtmc_app.c @@ -24,6 +24,7 @@ */ #include +#include /* atoi */ #include "class/usbtmc/usbtmc_device.h" #include "bsp/board.h" #include "main.h" @@ -75,6 +76,7 @@ static volatile uint32_t queryDelayStart; static volatile uint32_t bulkInStarted; static volatile uint32_t idnQuery; +static uint32_t resp_delay = 125u; // Adjustable delay, to allow for better testing static size_t buffer_len; static uint8_t buffer[225]; // A few packets long should be enough. @@ -115,6 +117,8 @@ bool usbtmcd_app_msg_data(uint8_t rhport, void *data, size_t len, bool transfer_ uart_tx_str_sync(">>>\r\n"); if(transfer_complete) uart_tx_str_sync("MSG_OUT_DATA: Complete\r\n"); + sprintf(bigMsg, "len=%u complete=%u\r\n",len,(uint32_t)transfer_complete); + uart_tx_str_sync(bigMsg); #endif if(len + buffer_len < sizeof(buffer)) @@ -129,6 +133,13 @@ bool usbtmcd_app_msg_data(uint8_t rhport, void *data, size_t len, bool transfer_ { idnQuery = 1; } + if(transfer_complete && !strncasecmp("delay ",data,5)) + { + queryState = 0; + resp_delay = atoi((char*)data + 5); + if(resp_delay > 10000u) + resp_delay = 10000u; + } return true; } @@ -166,11 +177,6 @@ bool usbtmcd_app_msgBulkIn_request(uint8_t rhport, usbtmc_msg_request_dev_dep_in void usbtmc_app_task_iter(void) { uint8_t const rhport = 0; - uint32_t board_delay = 5u; - if(idnQuery) - { - board_delay = 350u; - } switch(queryState) { case 0: break; @@ -179,7 +185,7 @@ void usbtmc_app_task_iter(void) { queryState = 2; break; case 2: - if( (board_millis() - queryDelayStart) > board_delay) { + if( (board_millis() - queryDelayStart) > resp_delay) { queryDelayStart = board_millis(); queryState=3; status |= 0x10u; // MAV @@ -187,7 +193,7 @@ void usbtmc_app_task_iter(void) { } break; case 3: - if( (board_millis() - queryDelayStart) > board_delay) { + if( (board_millis() - queryDelayStart) > resp_delay) { queryState = 4; } break; @@ -200,7 +206,7 @@ void usbtmc_app_task_iter(void) { #endif if(idnQuery) { - usbtmcd_transmit_dev_msg_data(rhport, idn, tu_min32(sizeof(idn)-1,msgReqLen),false); + usbtmcd_transmit_dev_msg_data(rhport, idn, tu_min32(sizeof(idn)-1,msgReqLen),false); } else { @@ -237,17 +243,20 @@ bool usbtmcd_app_check_clear(uint8_t rhport, usbtmc_get_clear_status_rsp_t *rsp) } bool usbtmcd_app_initiate_abort_bulk_in(uint8_t rhport, uint8_t *tmcResult) { + (void)rhport; bulkInStarted = 0; *tmcResult = USBTMC_STATUS_SUCCESS; return true; } bool usbtmcd_app_check_abort_bulk_in(uint8_t rhport, usbtmc_check_abort_bulk_rsp_t *rsp) { + (void)rhport; return true; } bool usbtmcd_app_initiate_abort_bulk_out(uint8_t rhport, uint8_t *tmcResult) { + (void)rhport; *tmcResult = USBTMC_STATUS_SUCCESS; return true; @@ -271,7 +280,7 @@ uint8_t usbtmcd_app_get_stb(uint8_t rhport, uint8_t *tmcResult) { (void)rhport; uint8_t old_status = status; - status = status & ~(0x40); // clear SRQ + status = status & ~(0x40u); // clear SRQ *tmcResult = USBTMC_STATUS_SUCCESS; // Increment status so that we see different results on each read... diff --git a/examples/device/usbtmc/visaQuery.py b/examples/device/usbtmc/visaQuery.py index fa3d7f5e8..2034e6ff7 100644 --- a/examples/device/usbtmc/visaQuery.py +++ b/examples/device/usbtmc/visaQuery.py @@ -7,15 +7,20 @@ def test_idn(): idn = inst.query("*idn?"); assert idn == "TinyUSB,ModelNumber,SerialNumber,FirmwareVer123456\r\n" -def test_echo(): - longstr = "0123456789abcdef" * 50 +def test_echo(m,n): + longstr = "0123456789abcdefghijklmnopqrstuvwxyz" * 50 #Next try echo from 1 to 175 characters (200 is max buffer size on DUT) - for i in range(49,175): + for i in range(m,n): + #print(i) x = longstr[0:i] xt = x + inst.write_termination y = inst.query(x) - assert(xt == y), f"echo {i}" + #print(x) + #print (":".join("{:02x}".format(ord(c)) for c in xt)) + #print (":".join("{:02x}".format(ord(c)) for c in y)) + assert(xt == y), f"failed i={i}" + inst.read_stb();# Just to make USB logging easier by sending a control query def test_mav(): assert (inst.read_stb() == 0) @@ -57,12 +62,28 @@ inst = rm.open_resource(reslist[0]); inst.timeout = 3000 inst.clear() -#print(idn); -inst.clear() +#print("+ IDN") +#test_idn() -test_idn() -test_echo() +print("+ random trigger") +#inst.assert_trigger(); + +print("+ echo delay=0") +inst.write("delay 0") +test_echo(1,175) + +print("+ echo delay=2") +inst.write("delay 2") +test_echo(1,175) + +print("+ echo delay=200") +inst.write("delay 200") +test_echo(50,90) +test_echo(165,170) + +print("+ MAV") test_mav() +print("+ SRQ") test_srq() inst.close() diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index 27876852d..eab4397ba 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -203,12 +203,6 @@ bool usbtmcd_transmit_dev_msg_data( { memcpy((uint8_t*)(usbtmc_state.ep_bulk_in_buf) + packetLen, data, hdr->TransferSize); packetLen = (uint16_t)(packetLen + hdr->TransferSize); - // Pad up to multiple of 4 bytes - while((packetLen % 4) != 0) - { - usbtmc_state.ep_bulk_in_buf[packetLen] = 0; - packetLen++; - } usbtmc_state.transfer_size_remaining = 0; usbtmc_state.transfer_size_sent = len; usbtmc_state.devInBuffer = NULL; @@ -518,32 +512,28 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint case STATE_TX_INITIATED: if(usbtmc_state.transfer_size_remaining >=sizeof(usbtmc_state.ep_bulk_in_buf)) - { - TRACE("IN TX continuing\r\n"); - memcpy(usbtmc_state.ep_bulk_in_buf, usbtmc_state.devInBuffer, sizeof(usbtmc_state.ep_bulk_in_buf)); - usbtmc_state.devInBuffer += sizeof(usbtmc_state.devInBuffer); - usbtmc_state.transfer_size_remaining -= sizeof(usbtmc_state.devInBuffer); - usbtmc_state.transfer_size_sent += sizeof(usbtmc_state.devInBuffer); - TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf,sizeof(usbtmc_state.devInBuffer))); - } - else // last packet - { - TRACE("IN TX last packet\r\n"); - size_t packetLen = usbtmc_state.transfer_size_remaining; - memcpy(usbtmc_state.ep_bulk_in_buf, usbtmc_state.devInBuffer, usbtmc_state.transfer_size_remaining); - while((packetLen % 4) != 0) { - usbtmc_state.ep_bulk_in_buf[packetLen] = 0u; - packetLen++; + TRACE("IN TX continuing\r\n"); + // FIXME! This removes const below! + TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, + (void*)usbtmc_state.devInBuffer,sizeof(usbtmc_state.ep_bulk_in_buf))); + usbtmc_state.devInBuffer += sizeof(usbtmc_state.ep_bulk_in_buf); + usbtmc_state.transfer_size_remaining -= sizeof(usbtmc_state.ep_bulk_in_buf); + usbtmc_state.transfer_size_sent += sizeof(usbtmc_state.ep_bulk_in_buf); } + else // last packet + { + TRACE("IN TX last packet\r\n"); + size_t packetLen = usbtmc_state.transfer_size_remaining; + memcpy(usbtmc_state.ep_bulk_in_buf, usbtmc_state.devInBuffer, usbtmc_state.transfer_size_remaining); usbtmc_state.transfer_size_sent += sizeof(usbtmc_state.transfer_size_remaining); - usbtmc_state.transfer_size_remaining = 0; - usbtmc_state.devInBuffer = NULL; - TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf,(uint16_t)packetLen)); + usbtmc_state.transfer_size_remaining = 0; + usbtmc_state.devInBuffer = NULL; + TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf,(uint16_t)packetLen)); if(((packetLen % USBTMCD_MAX_PACKET_SIZE) != 0) || (packetLen == 0 )) { usbtmc_state.state = STATE_TX_SHORTED; - } + } } return true; case STATE_ABORTING_BULK_IN: From 0548f97d3300edb4d57f6920f6307211833917f2 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Thu, 19 Sep 2019 16:25:59 -0400 Subject: [PATCH 29/45] Remove debug printf. --- examples/device/usbtmc/src/usbtmc_app.c | 16 +---- src/class/usbtmc/usbtmc_device.c | 82 ++++--------------------- 2 files changed, 12 insertions(+), 86 deletions(-) diff --git a/examples/device/usbtmc/src/usbtmc_app.c b/examples/device/usbtmc/src/usbtmc_app.c index 7c7431928..8ce468561 100644 --- a/examples/device/usbtmc/src/usbtmc_app.c +++ b/examples/device/usbtmc/src/usbtmc_app.c @@ -99,9 +99,6 @@ bool usbtmcd_app_msgBulkOut_start(uint8_t rhport, usbtmc_msg_request_dev_dep_out { (void)rhport; (void)msgHeader; -#ifdef xDEBUG - uart_tx_str_sync("MSG_OUT_DATA: start\r\n"); -#endif buffer_len = 0; return true; } @@ -111,15 +108,6 @@ bool usbtmcd_app_msg_data(uint8_t rhport, void *data, size_t len, bool transfer_ (void)rhport; // If transfer isn't finished, we just ignore it (for now) -#ifdef xDEBUG - uart_tx_str_sync("MSG_OUT_DATA: <<<"); - uart_tx_sync(data,len); - uart_tx_str_sync(">>>\r\n"); - if(transfer_complete) - uart_tx_str_sync("MSG_OUT_DATA: Complete\r\n"); - sprintf(bigMsg, "len=%u complete=%u\r\n",len,(uint32_t)transfer_complete); - uart_tx_str_sync(bigMsg); -#endif if(len + buffer_len < sizeof(buffer)) { @@ -201,9 +189,7 @@ void usbtmc_app_task_iter(void) { if(bulkInStarted) { queryState = 0; bulkInStarted = 0; -#ifdef xDEBUG - uart_tx_str_sync("usbtmc_app_task_iter: sending rsp!\r\n"); -#endif + if(idnQuery) { usbtmcd_transmit_dev_msg_data(rhport, idn, tu_min32(sizeof(idn)-1,msgReqLen),false); diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index eab4397ba..3a4e9e3e0 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -137,11 +137,6 @@ static usbtmc_interface_state_t usbtmc_state = .ep_bulk_out = 0, .ep_int_in = 0 }; -#ifdef xDEBUG -#define TRACE(str) uart_tx_str_sync(str) -#else -#define TRACE(STR) do {} while (0) -#endif // We need all headers to fit in a single packet in this implementation. TU_VERIFY_STATIC(USBTMCD_MAX_PACKET_SIZE >= 32u,"USBTMC dev EP packet size too small"); @@ -383,11 +378,6 @@ static bool handle_devMsgIn(uint8_t rhport, void *data, size_t len) TU_VERIFY(len == sizeof(usbtmc_msg_request_dev_dep_in)); usbtmc_msg_request_dev_dep_in *msg = (usbtmc_msg_request_dev_dep_in*)data; -#ifdef xDebug - sprintf(logMsg," handle_devMsgIn len=%ul\r\n",len); - TRACE(logMsg); -#endif - criticalEnter(); { TU_VERIFY(usbtmc_state.state == STATE_IDLE); @@ -409,14 +399,8 @@ static bool handle_devMsgIn(uint8_t rhport, void *data, size_t len) bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { - TRACE("USBTMC Xfer CB" ); TU_VERIFY(result == XFER_RESULT_SUCCESS); -#ifdef xDebug - sprintf(logMsg," STATE=%lu ", (uint32_t)usbtmc_state.state); - TRACE(logMsg); -#endif - if(usbtmc_state.state == STATE_CLEARING) { return true; /* I think we can ignore everything here */ } @@ -424,7 +408,7 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint if(ep_addr == usbtmc_state.ep_bulk_out) { usbtmc_msg_generic_t *msg = NULL; - TRACE("OUT"); + switch(usbtmc_state.state) { case STATE_IDLE: @@ -434,11 +418,6 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint TU_VERIFY(msg->header.bTag == invInvTag); TU_VERIFY(msg->header.bTag != 0x00); -#ifdef xDebug - sprintf(logMsg," type=%lu\r\n",(uint32_t)msg->header.MsgID); - TRACE(logMsg); -#endif - switch(msg->header.MsgID) { case USBTMC_MSGID_DEV_DEP_MSG_OUT: usbtmc_state.transfer_size_sent = 0u; @@ -447,7 +426,6 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint break; case USBTMC_MSGID_DEV_DEP_MSG_IN: - TRACE("Handling msg in req\r\n"); TU_VERIFY(handle_devMsgIn(rhport, msg, xferred_bytes)); break; @@ -484,71 +462,52 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint case STATE_ABORTING_BULK_IN_ABORTED: default: -#ifdef xDebug - if(msg == NULL) - sprintf(logMsg," Unknown received control?\r\n "); - else { - sprintf(logMsg," msg=%lu\r\n ", (uint32_t)msg->header.MsgID); - } - TRACE(logMsg); -#endif TU_VERIFY(false); } } else if(ep_addr == usbtmc_state.ep_bulk_in) { -#ifdef xDebug - sprintf(logMsg,"IN\r\n"); - TRACE(logMsg); -#endif switch(usbtmc_state.state) { case STATE_TX_SHORTED: - TRACE("IN TX shorted done\r\n"); - usbtmc_state.state = STATE_IDLE; TU_VERIFY(usbtmcd_app_msgBulkIn_complete(rhport)); break; case STATE_TX_INITIATED: if(usbtmc_state.transfer_size_remaining >=sizeof(usbtmc_state.ep_bulk_in_buf)) - { - TRACE("IN TX continuing\r\n"); + { // FIXME! This removes const below! TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, (void*)usbtmc_state.devInBuffer,sizeof(usbtmc_state.ep_bulk_in_buf))); usbtmc_state.devInBuffer += sizeof(usbtmc_state.ep_bulk_in_buf); usbtmc_state.transfer_size_remaining -= sizeof(usbtmc_state.ep_bulk_in_buf); usbtmc_state.transfer_size_sent += sizeof(usbtmc_state.ep_bulk_in_buf); - } - else // last packet - { - TRACE("IN TX last packet\r\n"); - size_t packetLen = usbtmc_state.transfer_size_remaining; - memcpy(usbtmc_state.ep_bulk_in_buf, usbtmc_state.devInBuffer, usbtmc_state.transfer_size_remaining); + } + else // last packet + { + size_t packetLen = usbtmc_state.transfer_size_remaining; + memcpy(usbtmc_state.ep_bulk_in_buf, usbtmc_state.devInBuffer, usbtmc_state.transfer_size_remaining); usbtmc_state.transfer_size_sent += sizeof(usbtmc_state.transfer_size_remaining); - usbtmc_state.transfer_size_remaining = 0; - usbtmc_state.devInBuffer = NULL; - TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf,(uint16_t)packetLen)); + usbtmc_state.transfer_size_remaining = 0; + usbtmc_state.devInBuffer = NULL; + TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf,(uint16_t)packetLen)); if(((packetLen % USBTMCD_MAX_PACKET_SIZE) != 0) || (packetLen == 0 )) { usbtmc_state.state = STATE_TX_SHORTED; - } + } } return true; case STATE_ABORTING_BULK_IN: // need to send short packet (ZLP?) - TRACE("IN aborting\r\n"); TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf,(uint16_t)0u)); usbtmc_state.state = STATE_ABORTING_BULK_IN_SHORTED; return true; case STATE_ABORTING_BULK_IN_SHORTED: /* Done. :)*/ - TRACE("IN shorted\r\n"); usbtmc_state.state = STATE_ABORTING_BULK_IN_ABORTED; return true; default: - TRACE("IN unknown\r\n"); TU_ASSERT(false); return false; } @@ -566,14 +525,12 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ #if (USBTMC_CFG_ENABLE_488) uint8_t bTag; #endif - TRACE("xfer cb\r\n"); if((request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD) && (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_ENDPOINT) && (request->bRequest == TUSB_REQ_CLEAR_FEATURE) && (request->wValue == TUSB_REQ_FEATURE_EDPT_HALT)) { - TRACE("feature clear\r\n"); if((request->wIndex) == usbtmc_state.ep_bulk_out) { usmtmcd_app_bulkOut_clearFeature(rhport); @@ -602,7 +559,6 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ usbtmc_initiate_abort_rsp_t rsp = { .bTag = usbtmc_state.lastBulkOutTag, }; - TRACE("init abort bulk out\r\n"); TU_VERIFY(request->bmRequestType == 0xA2); // in,class,interface TU_VERIFY(request->wLength == sizeof(rsp)); TU_VERIFY(request->wIndex == usbtmc_state.ep_bulk_out); @@ -611,12 +567,10 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ if(usbtmc_state.state != STATE_RCV) { rsp.USBTMC_status = USBTMC_STATUS_FAILED; - TRACE("init abort bulk out failed\r\n"); } else if(usbtmc_state.lastBulkOutTag == (request->wValue & 0xf7u)) { rsp.USBTMC_status = USBTMC_STATUS_TRANSFER_NOT_IN_PROGRESS; - TRACE("init abort bulk out not inprogress\r\n"); } else { @@ -625,14 +579,12 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ usbtmc_state.state = STATE_ABORTING_BULK_OUT; TU_VERIFY(usbtmcd_app_initiate_abort_bulk_out(rhport, &(rsp.USBTMC_status))); usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out); - TRACE("init abort bulk out success\r\n"); } TU_VERIFY(tud_control_xfer(rhport, request, (void*)&rsp,sizeof(rsp))); return true; } case USBTMC_bREQUEST_CHECK_ABORT_BULK_OUT_STATUS: { - TRACE("init check abort bulk out\r\n"); usbtmc_check_abort_bulk_rsp_t rsp = { .USBTMC_status = USBTMC_STATUS_SUCCESS, .NBYTES_RXD_TXD = usbtmc_state.transfer_size_sent @@ -650,7 +602,6 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ usbtmc_initiate_abort_rsp_t rsp = { .bTag = usbtmc_state.lastBulkInTag, }; - TRACE("init abort bulk in\r\n"); TU_VERIFY(request->bmRequestType == 0xA2); // in,class,interface TU_VERIFY(request->wLength == sizeof(rsp)); TU_VERIFY(request->wIndex == usbtmc_state.ep_bulk_in); @@ -664,17 +615,14 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ usbtmc_state.state = ((usbtmc_state.transfer_size_sent % USBTMCD_MAX_PACKET_SIZE) != 0) ? STATE_ABORTING_BULK_IN : STATE_ABORTING_BULK_IN_SHORTED; TU_VERIFY(usbtmcd_app_initiate_abort_bulk_in(rhport, &(rsp.USBTMC_status))); - TRACE("init abort bulk success\r\n"); } else if((usbtmc_state.state == STATE_TX_REQUESTED || usbtmc_state.state == STATE_TX_INITIATED)) { // FIXME: Unsure how to check if the OUT endpoint fifo is non-empty.... rsp.USBTMC_status = USBTMC_STATUS_TRANSFER_NOT_IN_PROGRESS; - TRACE("init abort bulk in not in progress\r\n"); } else { rsp.USBTMC_status = USBTMC_STATUS_FAILED; - TRACE("init abort bulk in failed\r\n"); } TU_VERIFY(tud_control_xfer(rhport, request, (void*)&rsp,sizeof(rsp))); return true; @@ -682,7 +630,6 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ case USBTMC_bREQUEST_CHECK_ABORT_BULK_IN_STATUS: { - TRACE("xfer check abort in\r\n"); TU_VERIFY(request->bmRequestType == 0xA2); // in,class,EP TU_VERIFY(request->wLength == 8u); @@ -715,7 +662,6 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ case USBTMC_bREQUEST_INITIATE_CLEAR: { - TRACE("init clear\r\n"); TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface TU_VERIFY(request->wLength == sizeof(tmcStatusCode)); // After receiving an INITIATE_CLEAR request, the device must Halt the Bulk-OUT endpoint, queue the @@ -730,7 +676,6 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ case USBTMC_bREQUEST_CHECK_CLEAR_STATUS: { - TRACE("check clear\r\n"); TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface usbtmc_get_clear_status_rsp_t clearStatusRsp = {0}; TU_VERIFY(request->wLength == sizeof(clearStatusRsp)); @@ -754,7 +699,6 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ case USBTMC_bREQUEST_GET_CAPABILITIES: { - TRACE("get capabilities\r\n"); TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface TU_VERIFY(request->wLength == sizeof(usbtmcd_app_capabilities)); TU_VERIFY(tud_control_xfer(rhport, request, (void*)&usbtmcd_app_capabilities, sizeof(usbtmcd_app_capabilities))); @@ -764,7 +708,6 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ case USBTMC_bREQUEST_INDICATOR_PULSE: // Optional { - TRACE("indicate\r\n"); TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface TU_VERIFY(request->wLength == sizeof(tmcStatusCode)); TU_VERIFY(usbtmcd_app_capabilities.bmIntfcCapabilities.supportsIndicatorPulse); @@ -777,7 +720,6 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ // USB488 required requests case USBTMC488_bREQUEST_READ_STATUS_BYTE: { - TRACE("read stb\r\n"); usbtmc_read_stb_rsp_488_t rsp; TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface TU_VERIFY(request->wLength == sizeof(rsp)); // in,class,interface @@ -816,7 +758,6 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ case USBTMC488_bREQUEST_GO_TO_LOCAL: case USBTMC488_bREQUEST_LOCAL_LOCKOUT: { - TRACE("Unsupported REN/GTL/LLO\r\n"); TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface TU_VERIFY(false); return false; @@ -824,7 +765,6 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ #endif default: - TRACE("Default CTRL handler\r\n"); TU_VERIFY(false); return false; } From 0f1435177b15b739188d08d08563e02e1bf2edde Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Thu, 19 Sep 2019 16:43:59 -0400 Subject: [PATCH 30/45] Add trigger test code. --- examples/device/usbtmc/src/usbtmc_app.c | 24 +++++++++++++++++++----- examples/device/usbtmc/visaQuery.py | 23 +++++++++++++++++------ 2 files changed, 36 insertions(+), 11 deletions(-) diff --git a/examples/device/usbtmc/src/usbtmc_app.c b/examples/device/usbtmc/src/usbtmc_app.c index 8ce468561..ea6e6aa6f 100644 --- a/examples/device/usbtmc/src/usbtmc_app.c +++ b/examples/device/usbtmc/src/usbtmc_app.c @@ -65,6 +65,12 @@ usbtmcd_app_capabilities = } #endif }; + +#define IEEE4882_STB_QUESTIONABLE (0x08u) +#define IEEE4882_STB_MAV (0x10u) +#define IEEE4882_STB_SER (0x20u) +#define IEEE4882_STB_SRQ (0x40u) + static const char idn[] = "TinyUSB,ModelNumber,SerialNumber,FirmwareVer123456\r\n"; //static const char idn[] = "TinyUSB,ModelNumber,SerialNumber,FirmwareVer and a bunch of other text to make it longer than a packet, perhaps? lets make it three transfers...\n"; static volatile uint8_t status; @@ -92,6 +98,8 @@ static usbtmc_msg_dev_dep_msg_in_header_t rspMsg = { bool usbtmcd_app_msg_trigger(uint8_t rhport, usbtmc_msg_generic_t* msg) { (void)rhport; (void)msg; + // Let trigger set the SRQ + status |= IEEE4882_STB_SRQ; return true; } @@ -124,9 +132,12 @@ bool usbtmcd_app_msg_data(uint8_t rhport, void *data, size_t len, bool transfer_ if(transfer_complete && !strncasecmp("delay ",data,5)) { queryState = 0; - resp_delay = atoi((char*)data + 5); - if(resp_delay > 10000u) - resp_delay = 10000u; + int d = atoi((char*)data + 5); + if(d > 10000) + d = 10000; + if(d<0) + d=0; + resp_delay = (uint32_t)d; } return true; } @@ -135,7 +146,7 @@ bool usbtmcd_app_msgBulkIn_complete(uint8_t rhport) { (void)rhport; - status &= (uint8_t)~(0x50u); // clear MAV and SRQ + status &= (uint8_t)~(IEEE4882_STB_MAV); // clear MAV return true; } @@ -237,6 +248,7 @@ bool usbtmcd_app_initiate_abort_bulk_in(uint8_t rhport, uint8_t *tmcResult) bool usbtmcd_app_check_abort_bulk_in(uint8_t rhport, usbtmc_check_abort_bulk_rsp_t *rsp) { (void)rhport; + (void)rsp; return true; } @@ -249,6 +261,8 @@ bool usbtmcd_app_initiate_abort_bulk_out(uint8_t rhport, uint8_t *tmcResult) } bool usbtmcd_app_check_abort_bulk_out(uint8_t rhport, usbtmc_check_abort_bulk_rsp_t *rsp) { + (void)rhport; + (void)rsp; return true; } @@ -266,7 +280,7 @@ uint8_t usbtmcd_app_get_stb(uint8_t rhport, uint8_t *tmcResult) { (void)rhport; uint8_t old_status = status; - status = status & ~(0x40u); // clear SRQ + status = (uint8_t)(status & ~(IEEE4882_STB_SRQ)); // clear SRQ *tmcResult = USBTMC_STATUS_SUCCESS; // Increment status so that we see different results on each read... diff --git a/examples/device/usbtmc/visaQuery.py b/examples/device/usbtmc/visaQuery.py index 2034e6ff7..9610cbc8f 100644 --- a/examples/device/usbtmc/visaQuery.py +++ b/examples/device/usbtmc/visaQuery.py @@ -22,6 +22,16 @@ def test_echo(m,n): assert(xt == y), f"failed i={i}" inst.read_stb();# Just to make USB logging easier by sending a control query +def test_trig(): + # clear SRQ + inst.read_stb() + assert (inst.read_stb() == 0) + inst.assert_trigger() + time.sleep(0.3) # SRQ may have some delay + assert (inst.read_stb() & 0x40), "SRQ not set after 0.3 seconds" + assert (inst.read_stb() == 0) + + def test_mav(): assert (inst.read_stb() == 0) inst.write("123") @@ -65,9 +75,6 @@ inst.clear() #print("+ IDN") #test_idn() -print("+ random trigger") -#inst.assert_trigger(); - print("+ echo delay=0") inst.write("delay 0") test_echo(1,175) @@ -76,15 +83,19 @@ print("+ echo delay=2") inst.write("delay 2") test_echo(1,175) -print("+ echo delay=200") -inst.write("delay 200") -test_echo(50,90) +print("+ echo delay=150") +inst.write("delay 150") +test_echo(53,76) test_echo(165,170) print("+ MAV") test_mav() + print("+ SRQ") test_srq() +print("+ TRIG") +test_trig() + inst.close() print("Test complete") From 346443118fa9f22611ca1382ff999e43b6a40b43 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Thu, 19 Sep 2019 18:58:15 -0400 Subject: [PATCH 31/45] Add testcase for aborting bulk in with no data queued (and fix aborting bulk in) --- examples/device/usbtmc/src/usbtmc_app.c | 2 +- examples/device/usbtmc/visaQuery.py | 29 +++++++++++++++++++++++-- src/class/usbtmc/usbtmc_device.c | 14 +++++++++--- 3 files changed, 39 insertions(+), 6 deletions(-) diff --git a/examples/device/usbtmc/src/usbtmc_app.c b/examples/device/usbtmc/src/usbtmc_app.c index ea6e6aa6f..0d03a5ef1 100644 --- a/examples/device/usbtmc/src/usbtmc_app.c +++ b/examples/device/usbtmc/src/usbtmc_app.c @@ -203,7 +203,7 @@ void usbtmc_app_task_iter(void) { if(idnQuery) { - usbtmcd_transmit_dev_msg_data(rhport, idn, tu_min32(sizeof(idn)-1,msgReqLen),false); + usbtmcd_transmit_dev_msg_data(rhport, idn, tu_min32(sizeof(idn)-1,msgReqLen),false); } else { diff --git a/examples/device/usbtmc/visaQuery.py b/examples/device/usbtmc/visaQuery.py index 9610cbc8f..368b66053 100644 --- a/examples/device/usbtmc/visaQuery.py +++ b/examples/device/usbtmc/visaQuery.py @@ -3,6 +3,7 @@ import time import sys + def test_idn(): idn = inst.query("*idn?"); assert idn == "TinyUSB,ModelNumber,SerialNumber,FirmwareVer123456\r\n" @@ -60,6 +61,24 @@ def test_srq(): rsp = inst.read() assert(rsp == "123\r\n") + + +def test_read_timeout(): + inst.timeout = 500 + # First read with no MAV + inst.read_stb() + assert (inst.read_stb() == 0) + inst.write("delay 500") + t0 = time.time() + try: + rsp = inst.read() + assert(false), "Read should have resulted in timeout" + except visa.VisaIOError: + print("Got expected exception") + t = time.time() - t0 + assert ((t*1000.0) > (inst.timeout - 300)) + assert ((t*1000.0) < (inst.timeout + 300)) + print(f"Delay was {t}") rm = visa.ResourceManager("/c/Windows/system32/visa64.dll") reslist = rm.list_resources("USB?::?*::INSTR") @@ -72,8 +91,11 @@ inst = rm.open_resource(reslist[0]); inst.timeout = 3000 inst.clear() -#print("+ IDN") -#test_idn() +print("+ IDN") +test_idn() + +inst.timeout = 3000 + print("+ echo delay=0") inst.write("delay 0") @@ -88,6 +110,9 @@ inst.write("delay 150") test_echo(53,76) test_echo(165,170) +print("+ Read timeout (no MAV") +test_read_timeout() + print("+ MAV") test_mav() diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index 3a4e9e3e0..db00b841f 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -102,7 +102,7 @@ typedef enum STATE_CLEARING, STATE_ABORTING_BULK_IN, STATE_ABORTING_BULK_IN_SHORTED, // aborting, and short packet has been queued for transmission - STATE_ABORTING_BULK_IN_ABORTED, // aborting, and short packet has been queued for transmission + STATE_ABORTING_BULK_IN_ABORTED, // aborting, and short packet has been transmitted STATE_ABORTING_BULK_OUT, STATE_NUM_STATES } usbtmcd_state_enum; @@ -384,6 +384,7 @@ static bool handle_devMsgIn(uint8_t rhport, void *data, size_t len) usbtmc_state.state = STATE_TX_REQUESTED; usbtmc_state.lastBulkInTag = msg->header.bTag; usbtmc_state.transfer_size_remaining = msg->TransferSize; + usbtmc_state.transfer_size_sent = 0u; } criticalLeave(); @@ -612,8 +613,14 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ rsp.USBTMC_status = USBTMC_STATUS_SUCCESS; usbtmc_state.transfer_size_remaining = 0; // Check if we've queued a short packet - usbtmc_state.state = ((usbtmc_state.transfer_size_sent % USBTMCD_MAX_PACKET_SIZE) != 0) ? + usbtmc_state.state = ((usbtmc_state.transfer_size_sent % USBTMCD_MAX_PACKET_SIZE) == 0) ? STATE_ABORTING_BULK_IN : STATE_ABORTING_BULK_IN_SHORTED; + if(usbtmc_state.transfer_size_sent == 0) + { + // Send short packet, nothing is in the buffer yet + TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf,(uint16_t)0u)); + usbtmc_state.state = STATE_ABORTING_BULK_IN_SHORTED; + } TU_VERIFY(usbtmcd_app_initiate_abort_bulk_in(rhport, &(rsp.USBTMC_status))); } else if((usbtmc_state.state == STATE_TX_REQUESTED || usbtmc_state.state == STATE_TX_INITIATED)) @@ -638,7 +645,7 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ .USBTMC_status = USBTMC_STATUS_FAILED, .bmAbortBulkIn = { - .BulkInFifoBytes = (usbtmc_state.state == STATE_ABORTING_BULK_IN_ABORTED) + .BulkInFifoBytes = (usbtmc_state.state != STATE_ABORTING_BULK_IN_ABORTED) }, .NBYTES_RXD_TXD = usbtmc_state.transfer_size_sent, }; @@ -647,6 +654,7 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ { case STATE_ABORTING_BULK_IN_ABORTED: rsp.USBTMC_status = USBTMC_STATUS_SUCCESS; + usbtmc_state.state = STATE_IDLE; break; case STATE_ABORTING_BULK_IN: case STATE_ABORTING_BULK_OUT: From 7e0490bbf32ed4a25e1917a1e5856338b9dc9346 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Thu, 19 Sep 2019 19:51:37 -0400 Subject: [PATCH 32/45] Move descriptors to usbd.h --- examples/device/usbtmc/src/usb_descriptors.c | 20 ++++++------- src/class/usbtmc/usbtmc_device.c | 5 ++-- src/class/usbtmc/usbtmc_device.h | 30 ------------------- src/device/usbd.c | 3 +- src/device/usbd.h | 31 ++++++++++++++++++++ 5 files changed, 46 insertions(+), 43 deletions(-) diff --git a/examples/device/usbtmc/src/usb_descriptors.c b/examples/device/usbtmc/src/usb_descriptors.c index 792fff87c..45e1001ea 100644 --- a/examples/device/usbtmc/src/usb_descriptors.c +++ b/examples/device/usbtmc/src/usb_descriptors.c @@ -105,16 +105,16 @@ uint8_t const * tud_hid_descriptor_report_cb(void) #if defined(CFG_TUD_USBTMC) -# define USBTMC_DESC_MAIN(_itfnum,_bNumEndpoints) \ - USBTMC_IF_DESCRIPTOR(_itfnum, _bNumEndpoints, /*_stridx = */ 4u, USBTMC_PROTOCOL_USB488), \ - USBTMC_BULK_DESCRIPTORS(/* OUT = */0x03, /* IN = */ 0x83) +# define TUD_USBTMC_DESC_MAIN(_itfnum,_bNumEndpoints) \ + TUD_USBTMC_IF_DESCRIPTOR(_itfnum, _bNumEndpoints, /*_stridx = */ 4u, TUD_USBTMC_PROTOCOL_USB488), \ + TUD_USBTMC_BULK_DESCRIPTORS(/* OUT = */0x03, /* IN = */ 0x83, /* packet size = */USBTMCD_MAX_PACKET_SIZE) #if defined(CFG_TUD_USBTMC_ENABLE_INT_EP) // Interrupt endpoint should be 2 bytes on a FS USB link -# define USBTMC_DESC(_itfnum) \ - USBTMC_DESC_MAIN(_itfnum, /* _epCount = */ 3), \ - USBTMC_INT_DESCRIPTOR(/* INT ep # */ 0x84, /* epMaxSize = */ 2, /* bInterval = */16u ) -# define USBTMC_DESC_LEN (USBTMC_IF_DESCRIPTOR_LEN + USBTMC_BULK_DESCRIPTORS_LEN + USBTMC_INT_DESCRIPTOR_LEN) +# define TUD_USBTMC_DESC(_itfnum) \ + TUD_USBTMC_DESC_MAIN(_itfnum, /* _epCount = */ 3), \ + TUD_USBTMC_INT_DESCRIPTOR(/* INT ep # */ 0x84, /* epMaxSize = */ 2, /* bInterval = */16u ) +# define USBTMC_DESC_LEN (TUD_USBTMC_IF_DESCRIPTOR_LEN + TUD_USBTMC_BULK_DESCRIPTORS_LEN + TUD_USBTMC_INT_DESCRIPTOR_LEN) #else @@ -174,7 +174,7 @@ uint8_t const desc_configuration[] = #endif #if CFG_TUD_USBTMC - USBTMC_DESC(ITF_NUM_USBTMC), + TUD_USBTMC_DESC(ITF_NUM_USBTMC), #endif #if CFG_TUD_MSC @@ -218,7 +218,7 @@ static uint16_t _desc_str[32]; // Application return pointer to descriptor, whose contents must exist long enough for transfer to complete uint16_t const* tud_descriptor_string_cb(uint8_t index) { - uint8_t chr_count; + size_t chr_count; if ( index == 0) { @@ -246,7 +246,7 @@ uint16_t const* tud_descriptor_string_cb(uint8_t index) } // first byte is length (including header), second byte is string type - _desc_str[0] = (((uint16_t)TUSB_DESC_STRING) << 8 ) | (2u*chr_count + 2u); + _desc_str[0] = (uint16_t)((((uint16_t)TUSB_DESC_STRING) << 8 ) | (2u*chr_count + 2u)); return _desc_str; } diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index db00b841f..f62bcd2b7 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -251,9 +251,9 @@ bool usbtmcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16 usbtmcd_reset(rhport); // Perhaps there are other application specific class drivers, so don't assert here. - if( itf_desc->bInterfaceClass != USBTMC_APP_CLASS) + if( itf_desc->bInterfaceClass != TUD_USBTMC_APP_CLASS) return false; - if( itf_desc->bInterfaceSubClass != USBTMC_APP_SUBCLASS) + if( itf_desc->bInterfaceSubClass != TUD_USBTMC_APP_SUBCLASS) return false; // Only 2 or 3 endpoints are allowed for USBTMC. @@ -272,6 +272,7 @@ bool usbtmcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16 tusb_desc_endpoint_t const *ep_desc = (tusb_desc_endpoint_t const *)p_desc; switch(ep_desc->bmAttributes.xfer) { case TUSB_XFER_BULK: + TU_ASSERT(ep_desc->wMaxPacketSize.size == USBTMCD_MAX_PACKET_SIZE); if (tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN) { usbtmc_state.ep_bulk_in = ep_desc->bEndpointAddress; diff --git a/src/class/usbtmc/usbtmc_device.h b/src/class/usbtmc/usbtmc_device.h index 4c991d5ff..1e28563dd 100644 --- a/src/class/usbtmc/usbtmc_device.h +++ b/src/class/usbtmc/usbtmc_device.h @@ -107,35 +107,5 @@ void usbtmcd_init(void); * USBTMC Descriptor Templates *************************************************************/ -#define USBTMC_APP_CLASS TUSB_CLASS_APPLICATION_SPECIFIC -#define USBTMC_APP_SUBCLASS 0x03u - -#define USBTMC_PROTOCOL_STD 0x00u -#define USBTMC_PROTOCOL_USB488 0x01u - -// Interface number, number of endpoints, EP string index, USB_TMC_PROTOCOL*, bulk-out endpoint ID, -// bulk-in endpoint ID -#define USBTMC_IF_DESCRIPTOR(_itfnum, _bNumEndpoints, _stridx, _itfProtocol) \ -/* Interface */ \ - 0x09, TUSB_DESC_INTERFACE, _itfnum, 0x00, _bNumEndpoints, USBTMC_APP_CLASS, USBTMC_APP_SUBCLASS, _itfProtocol, _stridx - -#define USBTMC_IF_DESCRIPTOR_LEN 9u - -// bulk-out Size must be a multiple of 4 bytes -#define USBTMC_BULK_DESCRIPTORS(_epout, _epin) \ -/* Endpoint Out */ \ -7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(USBTMCD_MAX_PACKET_SIZE), 0u, \ -/* Endpoint In */ \ -7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(USBTMCD_MAX_PACKET_SIZE), 0u - -#define USBTMC_BULK_DESCRIPTORS_LEN (7u+7u) - -/* optional interrupt endpoint */ \ -// _int_pollingInterval : for LS/FS, expressed in frames (1ms each). 16 may be a good number? -#define USBTMC_INT_DESCRIPTOR(_ep_interrupt, _ep_interrupt_size, _int_pollingInterval ) \ -7, TUSB_DESC_ENDPOINT, _ep_interrupt, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_interrupt_size), 0x16 - -#define USBTMC_INT_DESCRIPTOR_LEN (7u) - #endif /* CLASS_USBTMC_USBTMC_DEVICE_H_ */ diff --git a/src/device/usbd.c b/src/device/usbd.c index 2f8967fae..f8f1da82e 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -151,7 +151,8 @@ static usbd_class_driver_t const usbd_class_drivers[] = // We maybe need to add subclass codes here, or a callback to ask if a driver can // handle a particular interface. { - .class_code = TUSB_CLASS_APPLICATION_SPECIFIC, + .class_code = TUD_USBTMC_APP_CLASS, + //.subclass_code = TUD_USBTMC_APP_SUBCLASS .init = usbtmcd_init, .reset = usbtmcd_reset, .open = usbtmcd_open, diff --git a/src/device/usbd.h b/src/device/usbd.h index 5f96e55a4..f0887f0db 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -261,6 +261,37 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re /* MS Endpoint (connected to embedded jack out) */\ 5, TUSB_DESC_CS_ENDPOINT, MIDI_CS_ENDPOINT_GENERAL, 1, 3 +//------------- TUD_USBTMC/USB488 -------------// +#define TUD_USBTMC_APP_CLASS (TUSB_CLASS_APPLICATION_SPECIFIC) +#define TUD_USBTMC_APP_SUBCLASS 0x03u + +#define TUD_USBTMC_PROTOCOL_STD 0x00u +#define TUD_USBTMC_PROTOCOL_USB488 0x01u + +// Interface number, number of endpoints, EP string index, USB_TMC_PROTOCOL*, bulk-out endpoint ID, +// bulk-in endpoint ID +#define TUD_USBTMC_IF_DESCRIPTOR(_itfnum, _bNumEndpoints, _stridx, _itfProtocol) \ +/* Interface */ \ + 0x09, TUSB_DESC_INTERFACE, _itfnum, 0x00, _bNumEndpoints, TUD_USBTMC_APP_CLASS, TUD_USBTMC_APP_SUBCLASS, _itfProtocol, _stridx + +#define TUD_USBTMC_IF_DESCRIPTOR_LEN 9u + +#define TUD_USBTMC_BULK_DESCRIPTORS(_epout, _epin, _bulk_epsize) \ +/* Endpoint Out */ \ +7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_bulk_epsize), 0u, \ +/* Endpoint In */ \ +7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_bulk_epsize), 0u + +#define TUD_USBTMC_BULK_DESCRIPTORS_LEN (7u+7u) + +/* optional interrupt endpoint */ \ +// _int_pollingInterval : for LS/FS, expressed in frames (1ms each). 16 may be a good number? +#define TUD_USBTMC_INT_DESCRIPTOR(_ep_interrupt, _ep_interrupt_size, _int_pollingInterval ) \ +7, TUSB_DESC_ENDPOINT, _ep_interrupt, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_interrupt_size), 0x16 + +#define TUD_USBTMC_INT_DESCRIPTOR_LEN (7u) + + //------------- Vendor -------------// #define TUD_VENDOR_DESC_LEN (9+7+7) From d742c3e15cb2233e927d6fdc4702863dc41eb65a Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Thu, 19 Sep 2019 19:54:37 -0400 Subject: [PATCH 33/45] s/USBTMC488/USB488/ ; fix types in bitfield --- src/class/usbtmc/usbtmc.h | 14 +++++++------- src/class/usbtmc/usbtmc_device.c | 8 ++++---- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/class/usbtmc/usbtmc.h b/src/class/usbtmc/usbtmc.h index 0944c907a..810b523c5 100644 --- a/src/class/usbtmc/usbtmc.h +++ b/src/class/usbtmc/usbtmc.h @@ -139,9 +139,9 @@ TU_VERIFY_STATIC(sizeof(usbtmc_msg_request_vendor_specific_in) == 12u, "struct w /* typedef struct TU_ATTR_PACKED { struct { - uint8_t Recipient : 5 ; ///< EOM set on last byte - uint8_t Type : 2 ; ///< EOM set on last byte - uint8_t DirectionToHost : 1 ; ///< 0 is OUT, 1 is IN + unsigned int Recipient : 5 ; ///< EOM set on last byte + unsigned int Type : 2 ; ///< EOM set on last byte + unsigned int DirectionToHost : 1 ; ///< 0 is OUT, 1 is IN } bmRequestType; uint8_t bRequest ; ///< If bmRequestType.Type = Class, see usmtmc_request_type_enum uint16_t wValue ; @@ -176,10 +176,10 @@ typedef enum { USBTMC_bREQUEST_INDICATOR_PULSE = 64u, // Optional /****** USBTMC 488 *************/ - USBTMC488_bREQUEST_READ_STATUS_BYTE = 128u, - USBTMC488_bREQUEST_REN_CONTROL = 160u, - USBTMC488_bREQUEST_GO_TO_LOCAL = 161u, - USBTMC488_bREQUEST_LOCAL_LOCKOUT = 162u, + USB488_bREQUEST_READ_STATUS_BYTE = 128u, + USB488_bREQUEST_REN_CONTROL = 160u, + USB488_bREQUEST_GO_TO_LOCAL = 161u, + USB488_bREQUEST_LOCAL_LOCKOUT = 162u, } usmtmc_request_type_enum; diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index f62bcd2b7..6306ab074 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -727,7 +727,7 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ #if (USBTMC_CFG_ENABLE_488) // USB488 required requests - case USBTMC488_bREQUEST_READ_STATUS_BYTE: + case USB488_bREQUEST_READ_STATUS_BYTE: { usbtmc_read_stb_rsp_488_t rsp; TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface @@ -763,9 +763,9 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ return true; } // USB488 optional requests - case USBTMC488_bREQUEST_REN_CONTROL: - case USBTMC488_bREQUEST_GO_TO_LOCAL: - case USBTMC488_bREQUEST_LOCAL_LOCKOUT: + case USB488_bREQUEST_REN_CONTROL: + case USB488_bREQUEST_GO_TO_LOCAL: + case USB488_bREQUEST_LOCAL_LOCKOUT: { TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface TU_VERIFY(false); From f3d6d0127b4e4f1c7d986e27b5c8b42378dda999 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Thu, 19 Sep 2019 19:59:44 -0400 Subject: [PATCH 34/45] Rename USBTMC_CFG_ENABLE_488, and fix build with it off. --- examples/device/usbtmc/src/tusb_config.h | 2 +- examples/device/usbtmc/src/usbtmc_app.c | 4 ++-- src/class/usbtmc/usbtmc_device.c | 11 ++++++----- src/class/usbtmc/usbtmc_device.h | 8 ++++---- 4 files changed, 13 insertions(+), 12 deletions(-) diff --git a/examples/device/usbtmc/src/tusb_config.h b/examples/device/usbtmc/src/tusb_config.h index 16484424a..688fb02be 100644 --- a/examples/device/usbtmc/src/tusb_config.h +++ b/examples/device/usbtmc/src/tusb_config.h @@ -57,7 +57,7 @@ #define CFG_TUD_USBTMC 1 #define CFG_TUD_USBTMC_ENABLE_INT_EP 1 -#define USBTMC_CFG_ENABLE_488 1 +#define CFG_USBTMC_CFG_ENABLE_488 1 #ifdef __cplusplus } diff --git a/examples/device/usbtmc/src/usbtmc_app.c b/examples/device/usbtmc/src/usbtmc_app.c index 0d03a5ef1..895c65b26 100644 --- a/examples/device/usbtmc/src/usbtmc_app.c +++ b/examples/device/usbtmc/src/usbtmc_app.c @@ -29,7 +29,7 @@ #include "bsp/board.h" #include "main.h" -#if (USBTMC_CFG_ENABLE_488) +#if (CFG_USBTMC_CFG_ENABLE_488) usbtmc_response_capabilities_488_t const #else usbtmc_response_capabilities_t const @@ -48,7 +48,7 @@ usbtmcd_app_capabilities = .canEndBulkInOnTermChar = 0 }, -#if (USBTMC_CFG_ENABLE_488) +#if (CFG_USBTMC_CFG_ENABLE_488) .bcdUSB488 = USBTMC_488_VERSION, .bmIntfcCapabilities488 = { diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index 6306ab074..d4a6a0db0 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -227,7 +227,7 @@ bool usbtmcd_transmit_dev_msg_data( void usbtmcd_init(void) { #ifndef NDEBUG -# if USBTMC_CFG_ENABLE_488 +# if CFG_USBTMC_CFG_ENABLE_488 if(usbtmcd_app_capabilities.bmIntfcCapabilities488.supportsTrigger) TU_ASSERT(&usbtmcd_app_msg_trigger != NULL,); // Per USB488 spec: table 8 @@ -310,12 +310,13 @@ bool usbtmcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16 { TU_ASSERT(usbtmc_state.ep_int_in != 0); } - +#if (USBTMC_CFG_ENABLE_488) if(usbtmcd_app_capabilities.bmIntfcCapabilities488.is488_2 || usbtmcd_app_capabilities.bmDevCapabilities488.SR1) { TU_ASSERT(usbtmc_state.ep_int_in != 0); } +#endif #endif TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, 64)); @@ -431,7 +432,7 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint TU_VERIFY(handle_devMsgIn(rhport, msg, xferred_bytes)); break; -#ifdef USBTMC_CFG_ENABLE_488 +#if (CFG_USBTMC_CFG_ENABLE_488) case USBTMC_MSGID_USB488_TRIGGER: // Spec says we halt the EP if we didn't declare we support it. TU_VERIFY(usbtmcd_app_capabilities.bmIntfcCapabilities488.supportsTrigger); @@ -524,7 +525,7 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * request) { uint8_t tmcStatusCode = USBTMC_STATUS_FAILED; -#if (USBTMC_CFG_ENABLE_488) +#if (CFG_USBTMC_CFG_ENABLE_488) uint8_t bTag; #endif @@ -724,7 +725,7 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ TU_VERIFY(tud_control_xfer(rhport, request, (void*)&tmcStatusCode, sizeof(tmcStatusCode))); return true; } -#if (USBTMC_CFG_ENABLE_488) +#if (CFG_USBTMC_CFG_ENABLE_488) // USB488 required requests case USB488_bREQUEST_READ_STATUS_BYTE: diff --git a/src/class/usbtmc/usbtmc_device.h b/src/class/usbtmc/usbtmc_device.h index 1e28563dd..3c8d10572 100644 --- a/src/class/usbtmc/usbtmc_device.h +++ b/src/class/usbtmc/usbtmc_device.h @@ -37,8 +37,8 @@ #include "usbtmc.h" // Enable 488 mode by default -#if !defined(USBTMC_CFG_ENABLE_488) -#define USBTMC_CFG_ENABLE_488 (1) +#if !defined(CFG_USBTMC_CFG_ENABLE_488) +#define CFG_CFG_USBTMC_CFG_ENABLE_488 (1) #endif // USB spec says that full-speed must be 8,16,32, or 64. @@ -49,7 +49,7 @@ * Functions to be implemeted by the class implementation */ -#if (USBTMC_CFG_ENABLE_488) +#if (CFG_USBTMC_CFG_ENABLE_488) extern usbtmc_response_capabilities_488_t const usbtmcd_app_capabilities; #else extern usbtmc_response_capabilities_t const usbtmcd_app_capabilities; @@ -75,7 +75,7 @@ bool usbtmcd_app_check_clear(uint8_t rhport, usbtmc_get_clear_status_rsp_t *rsp) // Indicator pulse should be 0.5 to 1.0 seconds long TU_ATTR_WEAK bool usbtmcd_app_indicator_pluse(uint8_t rhport, tusb_control_request_t const * msg, uint8_t *tmcResult); -#if (USBTMC_CFG_ENABLE_488) +#if (CFG_USBTMC_CFG_ENABLE_488) uint8_t usbtmcd_app_get_stb(uint8_t rhport, uint8_t *tmcResult); TU_ATTR_WEAK bool usbtmcd_app_msg_trigger(uint8_t rhport, usbtmc_msg_generic_t* msg); //TU_ATTR_WEAK bool usbtmcd_app_go_to_local(uint8_t rhport); From 2a7ca15e2ce7df5f0271438bd58007ccf558eb4d Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Thu, 19 Sep 2019 20:08:45 -0400 Subject: [PATCH 35/45] Rename functions to include tud_ and _cb --- examples/device/usbtmc/src/usbtmc_app.c | 34 ++++++------ src/class/usbtmc/usbtmc.h | 2 +- src/class/usbtmc/usbtmc_device.c | 72 ++++++++++++------------- src/class/usbtmc/usbtmc_device.h | 46 ++++++++-------- src/device/usbd.c | 10 ++-- 5 files changed, 82 insertions(+), 82 deletions(-) diff --git a/examples/device/usbtmc/src/usbtmc_app.c b/examples/device/usbtmc/src/usbtmc_app.c index 895c65b26..f8c350f68 100644 --- a/examples/device/usbtmc/src/usbtmc_app.c +++ b/examples/device/usbtmc/src/usbtmc_app.c @@ -25,7 +25,7 @@ #include #include /* atoi */ -#include "class/usbtmc/usbtmc_device.h" +#include "tusb.h" #include "bsp/board.h" #include "main.h" @@ -34,7 +34,7 @@ usbtmc_response_capabilities_488_t const #else usbtmc_response_capabilities_t const #endif -usbtmcd_app_capabilities = +tud_usbtmc_app_capabilities = { .USBTMC_status = USBTMC_STATUS_SUCCESS, .bcdUSBTMC = USBTMC_VERSION, @@ -95,7 +95,7 @@ static usbtmc_msg_dev_dep_msg_in_header_t rspMsg = { } }; -bool usbtmcd_app_msg_trigger(uint8_t rhport, usbtmc_msg_generic_t* msg) { +bool tud_usbtmc_app_msg_trigger_cb(uint8_t rhport, usbtmc_msg_generic_t* msg) { (void)rhport; (void)msg; // Let trigger set the SRQ @@ -103,7 +103,7 @@ bool usbtmcd_app_msg_trigger(uint8_t rhport, usbtmc_msg_generic_t* msg) { return true; } -bool usbtmcd_app_msgBulkOut_start(uint8_t rhport, usbtmc_msg_request_dev_dep_out const * msgHeader) +bool tud_usbtmc_app_msgBulkOut_start_cb(uint8_t rhport, usbtmc_msg_request_dev_dep_out const * msgHeader) { (void)rhport; (void)msgHeader; @@ -111,7 +111,7 @@ bool usbtmcd_app_msgBulkOut_start(uint8_t rhport, usbtmc_msg_request_dev_dep_out return true; } -bool usbtmcd_app_msg_data(uint8_t rhport, void *data, size_t len, bool transfer_complete) +bool tud_usbtmc_app_msg_data_cb(uint8_t rhport, void *data, size_t len, bool transfer_complete) { (void)rhport; @@ -142,7 +142,7 @@ bool usbtmcd_app_msg_data(uint8_t rhport, void *data, size_t len, bool transfer_ return true; } -bool usbtmcd_app_msgBulkIn_complete(uint8_t rhport) +bool tud_usbtmc_app_msgBulkIn_complete_cb(uint8_t rhport) { (void)rhport; @@ -153,7 +153,7 @@ bool usbtmcd_app_msgBulkIn_complete(uint8_t rhport) static unsigned int msgReqLen; -bool usbtmcd_app_msgBulkIn_request(uint8_t rhport, usbtmc_msg_request_dev_dep_in const * request) +bool tud_usbtmc_app_msgBulkIn_request_cb(uint8_t rhport, usbtmc_msg_request_dev_dep_in const * request) { (void)rhport; @@ -218,7 +218,7 @@ void usbtmc_app_task_iter(void) { } } -bool usbtmcd_app_initiate_clear(uint8_t rhport, uint8_t *tmcResult) +bool tud_usbtmc_app_initiate_clear_cb(uint8_t rhport, uint8_t *tmcResult) { (void)rhport; *tmcResult = USBTMC_STATUS_SUCCESS; @@ -228,7 +228,7 @@ bool usbtmcd_app_initiate_clear(uint8_t rhport, uint8_t *tmcResult) return true; } -bool usbtmcd_app_check_clear(uint8_t rhport, usbtmc_get_clear_status_rsp_t *rsp) +bool tud_usbtmc_app_check_clear_cb(uint8_t rhport, usbtmc_get_clear_status_rsp_t *rsp) { (void)rhport; queryState = 0; @@ -238,45 +238,45 @@ bool usbtmcd_app_check_clear(uint8_t rhport, usbtmc_get_clear_status_rsp_t *rsp) rsp->bmClear.BulkInFifoBytes = 0u; return true; } -bool usbtmcd_app_initiate_abort_bulk_in(uint8_t rhport, uint8_t *tmcResult) +bool tud_usbtmc_app_initiate_abort_bulk_in_cb(uint8_t rhport, uint8_t *tmcResult) { (void)rhport; bulkInStarted = 0; *tmcResult = USBTMC_STATUS_SUCCESS; return true; } -bool usbtmcd_app_check_abort_bulk_in(uint8_t rhport, usbtmc_check_abort_bulk_rsp_t *rsp) +bool tud_usbtmc_app_check_abort_bulk_in_cb(uint8_t rhport, usbtmc_check_abort_bulk_rsp_t *rsp) { (void)rhport; (void)rsp; return true; } -bool usbtmcd_app_initiate_abort_bulk_out(uint8_t rhport, uint8_t *tmcResult) +bool tud_usbtmc_app_initiate_abort_bulk_out_cb(uint8_t rhport, uint8_t *tmcResult) { (void)rhport; *tmcResult = USBTMC_STATUS_SUCCESS; return true; } -bool usbtmcd_app_check_abort_bulk_out(uint8_t rhport, usbtmc_check_abort_bulk_rsp_t *rsp) +bool tud_usbtmc_app_check_abort_bulk_out_cb(uint8_t rhport, usbtmc_check_abort_bulk_rsp_t *rsp) { (void)rhport; (void)rsp; return true; } -void usmtmcd_app_bulkIn_clearFeature(uint8_t rhport) +void usmtmcd_app_bulkIn_clearFeature_cb(uint8_t rhport) { (void)rhport; } -void usmtmcd_app_bulkOut_clearFeature(uint8_t rhport) +void usmtmcd_app_bulkOut_clearFeature_cb(uint8_t rhport) { (void)rhport; } // Return status byte, but put the transfer result status code in the rspResult argument. -uint8_t usbtmcd_app_get_stb(uint8_t rhport, uint8_t *tmcResult) +uint8_t tud_usbtmc_app_get_stb_cb(uint8_t rhport, uint8_t *tmcResult) { (void)rhport; uint8_t old_status = status; @@ -288,7 +288,7 @@ uint8_t usbtmcd_app_get_stb(uint8_t rhport, uint8_t *tmcResult) return old_status; } -bool usbtmcd_app_indicator_pluse(uint8_t rhport, tusb_control_request_t const * msg, uint8_t *tmcResult) +bool tud_usbtmc_app_indicator_pluse_cb(uint8_t rhport, tusb_control_request_t const * msg, uint8_t *tmcResult) { (void)rhport; (void)msg; diff --git a/src/class/usbtmc/usbtmc.h b/src/class/usbtmc/usbtmc.h index 810b523c5..7d7005c2e 100644 --- a/src/class/usbtmc/usbtmc.h +++ b/src/class/usbtmc/usbtmc.h @@ -300,7 +300,7 @@ typedef struct TU_ATTR_PACKED TU_VERIFY_STATIC(sizeof(usbtmc_read_stb_rsp_488_t) == 3u, "struct wrong length"); -typedef struct TU_ATTR_PACKET +typedef struct TU_ATTR_PACKED { struct TU_ATTR_PACKED { diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index d4a6a0db0..d550a716f 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -174,7 +174,7 @@ bool usbtmcd_transmit_dev_msg_data( TU_ASSERT(len <= usbtmc_state.transfer_size_remaining); if(usingTermChar) { - TU_ASSERT(usbtmcd_app_capabilities.bmDevCapabilities.canEndBulkInOnTermChar); + TU_ASSERT(tud_usbtmc_app_capabilities.bmDevCapabilities.canEndBulkInOnTermChar); TU_ASSERT(termCharRequested); TU_ASSERT(((uint8_t*)data)[len-1] == termChar); } @@ -224,31 +224,31 @@ bool usbtmcd_transmit_dev_msg_data( return true; } -void usbtmcd_init(void) +void usbtmcd_init_cb(void) { #ifndef NDEBUG # if CFG_USBTMC_CFG_ENABLE_488 - if(usbtmcd_app_capabilities.bmIntfcCapabilities488.supportsTrigger) - TU_ASSERT(&usbtmcd_app_msg_trigger != NULL,); + if(tud_usbtmc_app_capabilities.bmIntfcCapabilities488.supportsTrigger) + TU_ASSERT(&tud_usbtmc_app_msg_trigger_cb != NULL,); // Per USB488 spec: table 8 - TU_ASSERT(!usbtmcd_app_capabilities.bmIntfcCapabilities.listenOnly,); - TU_ASSERT(!usbtmcd_app_capabilities.bmIntfcCapabilities.talkOnly,); + TU_ASSERT(!tud_usbtmc_app_capabilities.bmIntfcCapabilities.listenOnly,); + TU_ASSERT(!tud_usbtmc_app_capabilities.bmIntfcCapabilities.talkOnly,); # endif - if(usbtmcd_app_capabilities.bmIntfcCapabilities.supportsIndicatorPulse) - TU_ASSERT(&usbtmcd_app_indicator_pluse != NULL,); + if(tud_usbtmc_app_capabilities.bmIntfcCapabilities.supportsIndicatorPulse) + TU_ASSERT(&tud_usbtmc_app_indicator_pluse_cb != NULL,); #endif usbtmcLock = osal_mutex_create(&usbtmcLockBuffer); } -bool usbtmcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length) +bool usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length) { (void)rhport; uint8_t const * p_desc; uint8_t found_endpoints = 0; - usbtmcd_reset(rhport); + usbtmcd_reset_cb(rhport); // Perhaps there are other application specific class drivers, so don't assert here. if( itf_desc->bInterfaceClass != TUD_USBTMC_APP_CLASS) @@ -311,8 +311,8 @@ bool usbtmcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16 TU_ASSERT(usbtmc_state.ep_int_in != 0); } #if (USBTMC_CFG_ENABLE_488) - if(usbtmcd_app_capabilities.bmIntfcCapabilities488.is488_2 || - usbtmcd_app_capabilities.bmDevCapabilities488.SR1) + if(tud_usbtmc_app_capabilities.bmIntfcCapabilities488.is488_2 || + tud_usbtmc_app_capabilities.bmDevCapabilities488.SR1) { TU_ASSERT(usbtmc_state.ep_int_in != 0); } @@ -322,7 +322,7 @@ bool usbtmcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16 return true; } -void usbtmcd_reset(uint8_t rhport) +void usbtmcd_reset_cb(uint8_t rhport) { // FIXME: Do endpoints need to be closed here? usbtmc_state.state = STATE_IDLE; @@ -343,7 +343,7 @@ static bool handle_devMsgOutStart(uint8_t rhport, void *data, size_t len) // must be a header, should have been confirmed before calling here. usbtmc_msg_request_dev_dep_out *msg = (usbtmc_msg_request_dev_dep_out*)data; usbtmc_state.transfer_size_remaining = msg->TransferSize; - TU_VERIFY(usbtmcd_app_msgBulkOut_start(rhport,msg)); + TU_VERIFY(tud_usbtmc_app_msgBulkOut_start_cb(rhport,msg)); TU_VERIFY(handle_devMsgOut(rhport, (uint8_t*)data + sizeof(*msg), len - sizeof(*msg), len)); return true; @@ -360,7 +360,7 @@ static bool handle_devMsgOut(uint8_t rhport, void *data, size_t len, size_t pack atEnd = true; if(len > usbtmc_state.transfer_size_remaining) len = usbtmc_state.transfer_size_remaining; - usbtmcd_app_msg_data(rhport,data, len, atEnd); + tud_usbtmc_app_msg_data_cb(rhport,data, len, atEnd); usbtmc_state.transfer_size_remaining -= len; usbtmc_state.transfer_size_sent += len; @@ -394,9 +394,9 @@ static bool handle_devMsgIn(uint8_t rhport, void *data, size_t len) termChar = msg->TermChar; if(termCharRequested) - TU_VERIFY(usbtmcd_app_capabilities.bmDevCapabilities.canEndBulkInOnTermChar); + TU_VERIFY(tud_usbtmc_app_capabilities.bmDevCapabilities.canEndBulkInOnTermChar); - TU_VERIFY(usbtmcd_app_msgBulkIn_request(rhport, msg)); + TU_VERIFY(tud_usbtmc_app_msgBulkIn_request_cb(rhport, msg)); return true; } @@ -435,8 +435,8 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint #if (CFG_USBTMC_CFG_ENABLE_488) case USBTMC_MSGID_USB488_TRIGGER: // Spec says we halt the EP if we didn't declare we support it. - TU_VERIFY(usbtmcd_app_capabilities.bmIntfcCapabilities488.supportsTrigger); - TU_VERIFY(usbtmcd_app_msg_trigger(rhport, msg)); + TU_VERIFY(tud_usbtmc_app_capabilities.bmIntfcCapabilities488.supportsTrigger); + TU_VERIFY(tud_usbtmc_app_msg_trigger_cb(rhport, msg)); break; #endif @@ -474,7 +474,7 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint case STATE_TX_SHORTED: usbtmc_state.state = STATE_IDLE; - TU_VERIFY(usbtmcd_app_msgBulkIn_complete(rhport)); + TU_VERIFY(tud_usbtmc_app_msgBulkIn_complete_cb(rhport)); break; case STATE_TX_INITIATED: @@ -522,7 +522,7 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint return false; } -bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * request) { +bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * request) { uint8_t tmcStatusCode = USBTMC_STATUS_FAILED; #if (CFG_USBTMC_CFG_ENABLE_488) @@ -536,11 +536,11 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ { if((request->wIndex) == usbtmc_state.ep_bulk_out) { - usmtmcd_app_bulkOut_clearFeature(rhport); + usmtmcd_app_bulkOut_clearFeature_cb(rhport); } else if ((request->wIndex) == usbtmc_state.ep_bulk_in) { - usmtmcd_app_bulkIn_clearFeature(rhport); + usmtmcd_app_bulkIn_clearFeature_cb(rhport); } return false; // We want USBD core to handle sending the status response, and clear the stall condition } @@ -580,7 +580,7 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ rsp.USBTMC_status = USBTMC_STATUS_SUCCESS; // Check if we've queued a short packet usbtmc_state.state = STATE_ABORTING_BULK_OUT; - TU_VERIFY(usbtmcd_app_initiate_abort_bulk_out(rhport, &(rsp.USBTMC_status))); + TU_VERIFY(tud_usbtmc_app_initiate_abort_bulk_out_cb(rhport, &(rsp.USBTMC_status))); usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out); } TU_VERIFY(tud_control_xfer(rhport, request, (void*)&rsp,sizeof(rsp))); @@ -595,7 +595,7 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ TU_VERIFY(request->bmRequestType == 0xA2); // in,class,EP TU_VERIFY(request->wLength == sizeof(rsp)); TU_VERIFY(request->wIndex == usbtmc_state.ep_bulk_out); - TU_VERIFY(usbtmcd_app_check_abort_bulk_out(rhport, &rsp)); + TU_VERIFY(tud_usbtmc_app_check_abort_bulk_out_cb(rhport, &rsp)); TU_VERIFY(usbd_edpt_xfer(rhport, 0u, (void*)&rsp,sizeof(rsp))); return true; } @@ -623,7 +623,7 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf,(uint16_t)0u)); usbtmc_state.state = STATE_ABORTING_BULK_IN_SHORTED; } - TU_VERIFY(usbtmcd_app_initiate_abort_bulk_in(rhport, &(rsp.USBTMC_status))); + TU_VERIFY(tud_usbtmc_app_initiate_abort_bulk_in_cb(rhport, &(rsp.USBTMC_status))); } else if((usbtmc_state.state == STATE_TX_REQUESTED || usbtmc_state.state == STATE_TX_INITIATED)) { // FIXME: Unsure how to check if the OUT endpoint fifo is non-empty.... @@ -651,7 +651,7 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ }, .NBYTES_RXD_TXD = usbtmc_state.transfer_size_sent, }; - TU_VERIFY(usbtmcd_app_check_abort_bulk_in(rhport, &rsp)); + TU_VERIFY(tud_usbtmc_app_check_abort_bulk_in_cb(rhport, &rsp)); switch(usbtmc_state.state) { case STATE_ABORTING_BULK_IN_ABORTED: @@ -679,7 +679,7 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out); usbtmc_state.transfer_size_remaining = 0; usbtmc_state.state = STATE_CLEARING; - TU_VERIFY(usbtmcd_app_initiate_clear(rhport, &tmcStatusCode)); + TU_VERIFY(tud_usbtmc_app_initiate_clear_cb(rhport, &tmcStatusCode)); TU_VERIFY(tud_control_xfer(rhport, request, (void*)&tmcStatusCode,sizeof(tmcStatusCode))); return true; } @@ -699,7 +699,7 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ else { // Let app check if it's clear - TU_VERIFY(usbtmcd_app_check_clear(rhport, &clearStatusRsp)); + TU_VERIFY(tud_usbtmc_app_check_clear_cb(rhport, &clearStatusRsp)); } if(clearStatusRsp.USBTMC_status == USBTMC_STATUS_SUCCESS) usbtmc_state.state = STATE_IDLE; @@ -710,8 +710,8 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ case USBTMC_bREQUEST_GET_CAPABILITIES: { TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface - TU_VERIFY(request->wLength == sizeof(usbtmcd_app_capabilities)); - TU_VERIFY(tud_control_xfer(rhport, request, (void*)&usbtmcd_app_capabilities, sizeof(usbtmcd_app_capabilities))); + TU_VERIFY(request->wLength == sizeof(tud_usbtmc_app_capabilities)); + TU_VERIFY(tud_control_xfer(rhport, request, (void*)&tud_usbtmc_app_capabilities, sizeof(tud_usbtmc_app_capabilities))); return true; } // USBTMC Optional Requests @@ -720,8 +720,8 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ { TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface TU_VERIFY(request->wLength == sizeof(tmcStatusCode)); - TU_VERIFY(usbtmcd_app_capabilities.bmIntfcCapabilities.supportsIndicatorPulse); - TU_VERIFY(usbtmcd_app_indicator_pluse(rhport, request, &tmcStatusCode)); + TU_VERIFY(tud_usbtmc_app_capabilities.bmIntfcCapabilities.supportsIndicatorPulse); + TU_VERIFY(tud_usbtmc_app_indicator_pluse_cb(rhport, request, &tmcStatusCode)); TU_VERIFY(tud_control_xfer(rhport, request, (void*)&tmcStatusCode, sizeof(tmcStatusCode))); return true; } @@ -752,13 +752,13 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ .one = 1, .bTag = bTag & 0x7Fu, }, - .StatusByte = usbtmcd_app_get_stb(rhport, &(rsp.USBTMC_status)) + .StatusByte = tud_usbtmc_app_get_stb_cb(rhport, &(rsp.USBTMC_status)) }; usbd_edpt_xfer(rhport, usbtmc_state.ep_int_in, (void*)&intMsg,sizeof(intMsg)); } else { - rsp.statusByte = usbtmcd_app_get_stb(rhport, &(rsp.USBTMC_status)); + rsp.statusByte = tud_usbtmc_app_get_stb_cb(rhport, &(rsp.USBTMC_status)); } TU_VERIFY(tud_control_xfer(rhport, request, (void*)&rsp, sizeof(rsp))); return true; @@ -781,7 +781,7 @@ bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * requ TU_VERIFY(false); } -bool usbtmcd_control_complete(uint8_t rhport, tusb_control_request_t const * request) +bool usbtmcd_control_complete_cb(uint8_t rhport, tusb_control_request_t const * request) { (void)rhport; //------------- Class Specific Request -------------// diff --git a/src/class/usbtmc/usbtmc_device.h b/src/class/usbtmc/usbtmc_device.h index 3c8d10572..5c6ee2a8d 100644 --- a/src/class/usbtmc/usbtmc_device.h +++ b/src/class/usbtmc/usbtmc_device.h @@ -50,35 +50,35 @@ */ #if (CFG_USBTMC_CFG_ENABLE_488) -extern usbtmc_response_capabilities_488_t const usbtmcd_app_capabilities; +extern usbtmc_response_capabilities_488_t const tud_usbtmc_app_capabilities; #else -extern usbtmc_response_capabilities_t const usbtmcd_app_capabilities; +extern usbtmc_response_capabilities_t const tud_usbtmc_app_capabilities; #endif -bool usbtmcd_app_msgBulkOut_start(uint8_t rhport, usbtmc_msg_request_dev_dep_out const * msgHeader); +bool tud_usbtmc_app_msgBulkOut_start_cb(uint8_t rhport, usbtmc_msg_request_dev_dep_out const * msgHeader); // transfer_complete does not imply that a message is complete. -bool usbtmcd_app_msg_data(uint8_t rhport, void *data, size_t len, bool transfer_complete); -void usmtmcd_app_bulkOut_clearFeature(uint8_t rhport); // Notice to clear and abort the pending BULK out transfer +bool tud_usbtmc_app_msg_data_cb(uint8_t rhport, void *data, size_t len, bool transfer_complete); +void usmtmcd_app_bulkOut_clearFeature_cb(uint8_t rhport); // Notice to clear and abort the pending BULK out transfer -bool usbtmcd_app_msgBulkIn_request(uint8_t rhport, usbtmc_msg_request_dev_dep_in const * request); -bool usbtmcd_app_msgBulkIn_complete(uint8_t rhport); -void usmtmcd_app_bulkIn_clearFeature(uint8_t rhport); // Notice to clear and abort the pending BULK out transfer +bool tud_usbtmc_app_msgBulkIn_request_cb(uint8_t rhport, usbtmc_msg_request_dev_dep_in const * request); +bool tud_usbtmc_app_msgBulkIn_complete_cb(uint8_t rhport); +void usmtmcd_app_bulkIn_clearFeature_cb(uint8_t rhport); // Notice to clear and abort the pending BULK out transfer -bool usbtmcd_app_initiate_abort_bulk_in(uint8_t rhport, uint8_t *tmcResult); -bool usbtmcd_app_initiate_abort_bulk_out(uint8_t rhport, uint8_t *tmcResult); -bool usbtmcd_app_initiate_clear(uint8_t rhport, uint8_t *tmcResult); +bool tud_usbtmc_app_initiate_abort_bulk_in_cb(uint8_t rhport, uint8_t *tmcResult); +bool tud_usbtmc_app_initiate_abort_bulk_out_cb(uint8_t rhport, uint8_t *tmcResult); +bool tud_usbtmc_app_initiate_clear_cb(uint8_t rhport, uint8_t *tmcResult); -bool usbtmcd_app_check_abort_bulk_in(uint8_t rhport, usbtmc_check_abort_bulk_rsp_t *rsp); -bool usbtmcd_app_check_abort_bulk_out(uint8_t rhport, usbtmc_check_abort_bulk_rsp_t *rsp); -bool usbtmcd_app_check_clear(uint8_t rhport, usbtmc_get_clear_status_rsp_t *rsp); +bool tud_usbtmc_app_check_abort_bulk_in_cb(uint8_t rhport, usbtmc_check_abort_bulk_rsp_t *rsp); +bool tud_usbtmc_app_check_abort_bulk_out_cb(uint8_t rhport, usbtmc_check_abort_bulk_rsp_t *rsp); +bool tud_usbtmc_app_check_clear_cb(uint8_t rhport, usbtmc_get_clear_status_rsp_t *rsp); // Indicator pulse should be 0.5 to 1.0 seconds long -TU_ATTR_WEAK bool usbtmcd_app_indicator_pluse(uint8_t rhport, tusb_control_request_t const * msg, uint8_t *tmcResult); +TU_ATTR_WEAK bool tud_usbtmc_app_indicator_pluse_cb(uint8_t rhport, tusb_control_request_t const * msg, uint8_t *tmcResult); #if (CFG_USBTMC_CFG_ENABLE_488) -uint8_t usbtmcd_app_get_stb(uint8_t rhport, uint8_t *tmcResult); -TU_ATTR_WEAK bool usbtmcd_app_msg_trigger(uint8_t rhport, usbtmc_msg_generic_t* msg); -//TU_ATTR_WEAK bool usbtmcd_app_go_to_local(uint8_t rhport); +uint8_t tud_usbtmc_app_get_stb_cb(uint8_t rhport, uint8_t *tmcResult); +TU_ATTR_WEAK bool tud_usbtmc_app_msg_trigger_cb(uint8_t rhport, usbtmc_msg_generic_t* msg); +//TU_ATTR_WEAK bool tud_usbtmc_app_go_to_local_cb(uint8_t rhport); #endif /******************************************* @@ -96,12 +96,12 @@ bool usbtmcd_transmit_dev_msg_data( /* "callbacks" from USB device core */ -bool usbtmcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length); -void usbtmcd_reset(uint8_t rhport); +bool usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length); +void usbtmcd_reset_cb(uint8_t rhport); bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); -bool usbtmcd_control_request(uint8_t rhport, tusb_control_request_t const * request); -bool usbtmcd_control_complete(uint8_t rhport, tusb_control_request_t const * request); -void usbtmcd_init(void); +bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * request); +bool usbtmcd_control_complete_cb(uint8_t rhport, tusb_control_request_t const * request); +void usbtmcd_init_cb(void); /************************************************************ * USBTMC Descriptor Templates diff --git a/src/device/usbd.c b/src/device/usbd.c index f8f1da82e..8125d0093 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -153,11 +153,11 @@ static usbd_class_driver_t const usbd_class_drivers[] = { .class_code = TUD_USBTMC_APP_CLASS, //.subclass_code = TUD_USBTMC_APP_SUBCLASS - .init = usbtmcd_init, - .reset = usbtmcd_reset, - .open = usbtmcd_open, - .control_request = usbtmcd_control_request, - .control_complete = usbtmcd_control_complete, + .init = usbtmcd_init_cb, + .reset = usbtmcd_reset_cb, + .open = usbtmcd_open_cb, + .control_request = usbtmcd_control_request_cb, + .control_complete = usbtmcd_control_complete_cb, .xfer_cb = usbtmcd_xfer_cb, .sof = NULL }, From 02b468f56a883ee81d1f635f0548cf43ce454c0d Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Thu, 19 Sep 2019 21:20:04 -0400 Subject: [PATCH 36/45] (little typo fix) --- src/class/usbtmc/usbtmc_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index d550a716f..fcd3376f3 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -310,7 +310,7 @@ bool usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin { TU_ASSERT(usbtmc_state.ep_int_in != 0); } -#if (USBTMC_CFG_ENABLE_488) +#if (CFG_USBTMC_CFG_ENABLE_488) if(tud_usbtmc_app_capabilities.bmIntfcCapabilities488.is488_2 || tud_usbtmc_app_capabilities.bmDevCapabilities488.SR1) { From fa5b5e4561869e26832d817b4a709ba31e666143 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Sat, 21 Sep 2019 21:46:46 -0400 Subject: [PATCH 37/45] Lots of updates (especially error handling) --- examples/device/usbtmc/src/usb_descriptors.c | 4 +- examples/device/usbtmc/src/usbtmc_app.c | 51 +++- examples/device/usbtmc/visaQuery.py | 70 +++++- src/class/usbtmc/usbtmc_device.c | 242 ++++++++++--------- src/class/usbtmc/usbtmc_device.h | 2 +- 5 files changed, 234 insertions(+), 135 deletions(-) diff --git a/examples/device/usbtmc/src/usb_descriptors.c b/examples/device/usbtmc/src/usb_descriptors.c index 45e1001ea..1175ebb99 100644 --- a/examples/device/usbtmc/src/usb_descriptors.c +++ b/examples/device/usbtmc/src/usb_descriptors.c @@ -107,13 +107,13 @@ uint8_t const * tud_hid_descriptor_report_cb(void) # define TUD_USBTMC_DESC_MAIN(_itfnum,_bNumEndpoints) \ TUD_USBTMC_IF_DESCRIPTOR(_itfnum, _bNumEndpoints, /*_stridx = */ 4u, TUD_USBTMC_PROTOCOL_USB488), \ - TUD_USBTMC_BULK_DESCRIPTORS(/* OUT = */0x03, /* IN = */ 0x83, /* packet size = */USBTMCD_MAX_PACKET_SIZE) + TUD_USBTMC_BULK_DESCRIPTORS(/* OUT = */0x01, /* IN = */ 0x81, /* packet size = */USBTMCD_MAX_PACKET_SIZE) #if defined(CFG_TUD_USBTMC_ENABLE_INT_EP) // Interrupt endpoint should be 2 bytes on a FS USB link # define TUD_USBTMC_DESC(_itfnum) \ TUD_USBTMC_DESC_MAIN(_itfnum, /* _epCount = */ 3), \ - TUD_USBTMC_INT_DESCRIPTOR(/* INT ep # */ 0x84, /* epMaxSize = */ 2, /* bInterval = */16u ) + TUD_USBTMC_INT_DESCRIPTOR(/* INT ep # */ 0x82, /* epMaxSize = */ 2, /* bInterval = */16u ) # define USBTMC_DESC_LEN (TUD_USBTMC_IF_DESCRIPTOR_LEN + TUD_USBTMC_BULK_DESCRIPTORS_LEN + TUD_USBTMC_INT_DESCRIPTOR_LEN) #else diff --git a/examples/device/usbtmc/src/usbtmc_app.c b/examples/device/usbtmc/src/usbtmc_app.c index f8c350f68..495746e07 100644 --- a/examples/device/usbtmc/src/usbtmc_app.c +++ b/examples/device/usbtmc/src/usbtmc_app.c @@ -84,6 +84,7 @@ static volatile uint32_t idnQuery; static uint32_t resp_delay = 125u; // Adjustable delay, to allow for better testing static size_t buffer_len; +static size_t buffer_tx_ix; // for transmitting using multiple transfers static uint8_t buffer[225]; // A few packets long should be enough. @@ -108,6 +109,11 @@ bool tud_usbtmc_app_msgBulkOut_start_cb(uint8_t rhport, usbtmc_msg_request_dev_d (void)rhport; (void)msgHeader; buffer_len = 0; + if(msgHeader->TransferSize > sizeof(buffer)) + { + + return false; + } return true; } @@ -122,6 +128,10 @@ bool tud_usbtmc_app_msg_data_cb(uint8_t rhport, void *data, size_t len, bool tra memcpy(&(buffer[buffer_len]), data, len); buffer_len += len; } + else + { + return false; // buffer overflow! + } queryState = transfer_complete; idnQuery = 0; @@ -145,8 +155,13 @@ bool tud_usbtmc_app_msg_data_cb(uint8_t rhport, void *data, size_t len, bool tra bool tud_usbtmc_app_msgBulkIn_complete_cb(uint8_t rhport) { (void)rhport; - - status &= (uint8_t)~(IEEE4882_STB_MAV); // clear MAV + if((buffer_tx_ix == buffer_len) || idnQuery) // done + { + status &= (uint8_t)~(IEEE4882_STB_MAV); // clear MAV + queryState = 0; + bulkInStarted = 0; + buffer_tx_ix = 0; + } return true; } @@ -161,15 +176,25 @@ bool tud_usbtmc_app_msgBulkIn_request_cb(uint8_t rhport, usbtmc_msg_request_dev_ rspMsg.header.bTag = request->header.bTag, rspMsg.header.bTagInverse = request->header.bTagInverse; msgReqLen = request->TransferSize; + #ifdef xDEBUG uart_tx_str_sync("MSG_IN_DATA: Requested!\r\n"); #endif - TU_ASSERT(bulkInStarted == 0); - bulkInStarted = 1; - - // > If a USBTMC interface receives a Bulk-IN request prior to receiving a USBTMC command message - // that expects a response, the device must NAK the request + if(queryState == 0 || (buffer_tx_ix == 0)) + { + TU_ASSERT(bulkInStarted == 0); + bulkInStarted = 1; + // > If a USBTMC interface receives a Bulk-IN request prior to receiving a USBTMC command message + // that expects a response, the device must NAK the request (*not stall*) + } + else + { + size_t txlen = tu_min32(buffer_len-buffer_tx_ix,msgReqLen); + usbtmcd_transmit_dev_msg_data(rhport, &buffer[buffer_tx_ix], txlen, + (buffer_tx_ix+txlen) == buffer_len, false); + buffer_tx_ix += txlen; + } // Always return true indicating not to stall the EP. return true; } @@ -197,17 +222,17 @@ void usbtmc_app_task_iter(void) { } break; case 4: // time to transmit; - if(bulkInStarted) { - queryState = 0; - bulkInStarted = 0; - + if(bulkInStarted && (buffer_tx_ix == 0)) { if(idnQuery) { - usbtmcd_transmit_dev_msg_data(rhport, idn, tu_min32(sizeof(idn)-1,msgReqLen),false); + usbtmcd_transmit_dev_msg_data(rhport, idn, tu_min32(sizeof(idn)-1,msgReqLen),true,false); + queryState = 0; + bulkInStarted = 0; } else { - usbtmcd_transmit_dev_msg_data(rhport, buffer, tu_min32(buffer_len,msgReqLen),false); + buffer_tx_ix = tu_min32(buffer_len,msgReqLen); + usbtmcd_transmit_dev_msg_data(rhport, buffer, buffer_tx_ix, buffer_tx_ix == buffer_len, false); } // MAV is cleared in the transfer complete callback. } diff --git a/examples/device/usbtmc/visaQuery.py b/examples/device/usbtmc/visaQuery.py index 368b66053..4d4b50c4b 100644 --- a/examples/device/usbtmc/visaQuery.py +++ b/examples/device/usbtmc/visaQuery.py @@ -6,7 +6,8 @@ import sys def test_idn(): idn = inst.query("*idn?"); - assert idn == "TinyUSB,ModelNumber,SerialNumber,FirmwareVer123456\r\n" + assert (idn == "TinyUSB,ModelNumber,SerialNumber,FirmwareVer123456\r\n") + assert (inst.is_4882_compliant) def test_echo(m,n): longstr = "0123456789abcdefghijklmnopqrstuvwxyz" * 50 @@ -34,6 +35,8 @@ def test_trig(): def test_mav(): + inst.write("delay 50") + inst.read_stb() # clear STB assert (inst.read_stb() == 0) inst.write("123") time.sleep(0.3) @@ -60,8 +63,6 @@ def test_srq(): rsp = inst.read() assert(rsp == "123\r\n") - - def test_read_timeout(): inst.timeout = 500 @@ -78,7 +79,53 @@ def test_read_timeout(): t = time.time() - t0 assert ((t*1000.0) > (inst.timeout - 300)) assert ((t*1000.0) < (inst.timeout + 300)) - print(f"Delay was {t}") + print(f"Delay was {t:0.3}") + # Response is still in queue, so send a clear (to be more helpful to the next test) + inst.clear() + time.sleep(0.3) + assert(0 == (inst.read_stb() & 0x10)), "MAV not reset after clear" + +def test_abort_in(): + inst.timeout = 200 + # First read with no MAV + inst.read_stb() + assert (inst.read_stb() == 0) + inst.write("delay 500") + inst.write("xxx") + t0 = time.time() + try: + rsp = inst.read() + assert(false), "Read should have resulted in timeout" + except visa.VisaIOError: + print("Got expected exception") + t = time.time() - t0 + assert ((t*1000.0) > (inst.timeout - 300)) + assert ((t*1000.0) < (inst.timeout + 300)) + print(f"Delay was {t:0.3}") + # Response is still in queue, so send a clear (to be more helpful to the next test) + inst.timeout = 800 + y = inst.read() + assert(y == "xxx\r\n") + +def test_indicate(): + # perform indicator pulse + usb_iface = inst.get_visa_attribute(visa.constants.VI_ATTR_USB_INTFC_NUM) + retv = inst.control_in(request_type_bitmap_field=0xA1, request_id=64, request_value=0x0000, index=usb_iface, length=0x0001) + assert((retv[1] == visa.constants.StatusCode(0)) and (retv[0] == b'\x01')), f"indicator pulse failed: retv={retv}" + + +def test_multi_read(): + old_chunk_size = inst.chunk_size + longstr = "0123456789abcdefghijklmnopqrstuvwxyz" * 10 + timeout = 10 + x = longstr[0:174] + inst.chunk_size = 50 # Seems chunk size only applies to read but not write + inst.write(x) + # I'm not sure how to request just the remaining bit using a max count... so just read it all. + y = inst.read() + assert (x + "\r\n" == y) + #inst.chunk_size = old_chunk_size + rm = visa.ResourceManager("/c/Windows/system32/visa64.dll") reslist = rm.list_resources("USB?::?*::INSTR") @@ -89,12 +136,20 @@ if (len(reslist) == 0): inst = rm.open_resource(reslist[0]); inst.timeout = 3000 + inst.clear() print("+ IDN") test_idn() -inst.timeout = 3000 +print("+test abort in") +test_abort_in() + + +inst.timeout = 2000 + +print("+ multi read") +test_multi_read() print("+ echo delay=0") @@ -110,7 +165,7 @@ inst.write("delay 150") test_echo(53,76) test_echo(165,170) -print("+ Read timeout (no MAV") +print("+ Read timeout (no MAV)") test_read_timeout() print("+ MAV") @@ -119,6 +174,9 @@ test_mav() print("+ SRQ") test_srq() +print("+ indicate") +test_indicate() + print("+ TRIG") test_trig() diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index fcd3376f3..2c6c88cf5 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -31,25 +31,31 @@ * This file is part of the TinyUSB stack. */ -// Synchronization is needed in some spots. -// These functions should NOT be called from interrupts. - -/* The library is designed that its functions can be called by any user task, with need for - * additional locking. In the case of "no OS", this task is never preempted other than by - * interrupts, and the USBTMC code isn't called by interrupts, so all is OK. In the case - * of an OS, this class driver uses the OSAL to perform locking. The code uses a single lock - * and does not call outside of this class with a lock held, so deadlocks won't happen. +/* + * This library is not fully reentrant, though it is reentrant from the view + * of either the application layer or the USB stack. Due to its locking, + * it is not safe to call its functions from interrupts. * - * This module's application-facing functions are not reentrant. The application must - * only call them from a single thread (or implement its own locking). + * The one exception is that its functions may not be called from the application + * until the USB stack is initialized. This should not be a problem since the + * device shouldn't be sending messages until it receives a request from the + * host. */ +/* + * In the case of single-CPU "no OS", this task is never preempted other than by + * interrupts, and the USBTMC code isn't called by interrupts, so all is OK. For "no OS", + * the mutex structure's main effect is to disable the USB interrupts. + * With an OS, this class driver uses the OSAL to perform locking. The code uses a single lock + * and does not call outside of this class with a lock held, so deadlocks won't happen. + */ + //Limitations: // "vendor-specific" commands are not handled. // Dealing with "termchar" must be handled by the application layer, // though additional error checking is does in this module. -// talkOnly and listenOnly are NOT supported. They're no permitted +// talkOnly and listenOnly are NOT supported. They're not permitted // in USB488, anyway. /* Supported: @@ -64,10 +70,7 @@ // TODO: // USBTMC 3.2.2 error conditions not strictly followed // No local lock-out, REN, or GTL. -// Cannot handle clear. // Clear message available status byte at the correct time? (488 4.3.1.3) -// Abort bulk in/out -// No CLEAR_FEATURE/HALT no EP (yet) #include "tusb_option.h" @@ -79,21 +82,24 @@ #include "usbtmc_device.h" #include "device/dcd.h" #include "device/usbd.h" +#include "osal/osal.h" + +// FIXME: I shouldn't need to include _pvt headers, but it is necessary for usbd_edpt_xfer, _stall, and _busy +#include "device/usbd_pvt.h" #ifdef xDEBUG #include "uart_util.h" static char logMsg[150]; #endif - -// FIXME: I shouldn't need to include _pvt headers. -#include "device/usbd_pvt.h" - -static uint8_t termChar; -static uint8_t termCharRequested = false; +/* + * The state machine does not allow simultaneous reading and writing. This is + * consistent with USBTMC. + */ typedef enum { + STATE_CLOSED, STATE_IDLE, STATE_RCV, STATE_TX_REQUESTED, @@ -126,16 +132,12 @@ typedef struct uint8_t lastBulkOutTag; // used for aborts (mostly) uint8_t lastBulkInTag; // used for aborts (mostly) - uint8_t const * devInBuffer; + uint8_t const * devInBuffer; // pointer to application-layer used for transmissions } usbtmc_interface_state_t; static usbtmc_interface_state_t usbtmc_state = { - .state = STATE_IDLE, .itf_id = 0xFF, - .ep_bulk_in = 0, - .ep_bulk_out = 0, - .ep_int_in = 0 }; // We need all headers to fit in a single packet in this implementation. @@ -147,6 +149,9 @@ TU_VERIFY_STATIC( static bool handle_devMsgOutStart(uint8_t rhport, void *data, size_t len); static bool handle_devMsgOut(uint8_t rhport, void *data, size_t len, size_t packetLen); +static uint8_t termChar; +static uint8_t termCharRequested = false; + osal_mutex_def_t usbtmcLockBuffer; static osal_mutex_t usbtmcLock; @@ -155,6 +160,23 @@ static osal_mutex_t usbtmcLock; #define criticalEnter() do {osal_mutex_lock(usbtmcLock,OSAL_TIMEOUT_WAIT_FOREVER); } while (0) #define criticalLeave() do {osal_mutex_unlock(usbtmcLock); } while (0) +bool atomicChangeState(usbtmcd_state_enum expectedState, usbtmcd_state_enum newState) +{ + bool ret = true; + criticalEnter(); + usbtmcd_state_enum oldState = usbtmc_state.state; + if (oldState == expectedState) + { + usbtmc_state.state = newState; + } + else + { + ret = false; + } + criticalLeave(); + return ret; +} + // called from app // We keep a reference to the buffer, so it MUST not change until the app is // notified that the transfer is complete. @@ -165,6 +187,7 @@ static osal_mutex_t usbtmcLock; bool usbtmcd_transmit_dev_msg_data( uint8_t rhport, const void * data, size_t len, + bool endOfMessage, bool usingTermChar) { const unsigned int txBufLen = sizeof(usbtmc_state.ep_bulk_in_buf); @@ -172,68 +195,53 @@ bool usbtmcd_transmit_dev_msg_data( #ifndef NDEBUG TU_ASSERT(len > 0u); TU_ASSERT(len <= usbtmc_state.transfer_size_remaining); + TU_ASSERT(usbtmc_state.transfer_size_sent == 0u); if(usingTermChar) { TU_ASSERT(tud_usbtmc_app_capabilities.bmDevCapabilities.canEndBulkInOnTermChar); TU_ASSERT(termCharRequested); - TU_ASSERT(((uint8_t*)data)[len-1] == termChar); + TU_ASSERT(((uint8_t*)data)[len-1u] == termChar); } #endif TU_VERIFY(usbtmc_state.state == STATE_TX_REQUESTED); usbtmc_msg_dev_dep_msg_in_header_t *hdr = (usbtmc_msg_dev_dep_msg_in_header_t*)usbtmc_state.ep_bulk_in_buf; - memset(hdr, 0x00, sizeof(*hdr)); + tu_varclr(hdr); hdr->header.MsgID = USBTMC_MSGID_DEV_DEP_MSG_IN; hdr->header.bTag = usbtmc_state.lastBulkInTag; hdr->header.bTagInverse = (uint8_t)~(usbtmc_state.lastBulkInTag); hdr->TransferSize = len; - hdr->bmTransferAttributes.EOM = 1u; + hdr->bmTransferAttributes.EOM = endOfMessage; hdr->bmTransferAttributes.UsingTermChar = usingTermChar; // Copy in the header - size_t packetLen = sizeof(*hdr); + const size_t headerLen = sizeof(*hdr); + const size_t dataLen = ((headerLen + hdr->TransferSize) <= txBufLen) ? + len : (txBufLen - headerLen); + const size_t packetLen = headerLen + dataLen; - // If it fits in a single trasnmission: - if((packetLen + hdr->TransferSize) <= txBufLen) - { - memcpy((uint8_t*)(usbtmc_state.ep_bulk_in_buf) + packetLen, data, hdr->TransferSize); - packetLen = (uint16_t)(packetLen + hdr->TransferSize); - usbtmc_state.transfer_size_remaining = 0; - usbtmc_state.transfer_size_sent = len; - usbtmc_state.devInBuffer = NULL; - } - else /* partial packet */ - { - memcpy((uint8_t*)(usbtmc_state.ep_bulk_in_buf) + packetLen, data, txBufLen - packetLen); - usbtmc_state.devInBuffer = (uint8_t*)data + (txBufLen - packetLen); - usbtmc_state.transfer_size_remaining = len - (txBufLen - packetLen); - usbtmc_state.transfer_size_sent = txBufLen - packetLen; - packetLen = txBufLen; - } + memcpy((uint8_t*)(usbtmc_state.ep_bulk_in_buf) + headerLen, data, dataLen); + usbtmc_state.transfer_size_remaining = len - dataLen; + usbtmc_state.transfer_size_sent = dataLen; + usbtmc_state.devInBuffer = (uint8_t*)data + (dataLen); - - criticalEnter(); - { - TU_VERIFY(usbtmc_state.state == STATE_TX_REQUESTED); - // We used packetlen as a max, not the buffer size, so this is OK here, no need for modulus - usbtmc_state.state = (packetLen >= txBufLen) ? STATE_TX_INITIATED : STATE_TX_SHORTED; - } - criticalLeave(); - - TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf, (uint16_t)packetLen)); + bool stateChanged = + atomicChangeState(STATE_TX_REQUESTED, (packetLen >= txBufLen) ? STATE_TX_INITIATED : STATE_TX_SHORTED); + TU_VERIFY(stateChanged); + TU_VERIFY(usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf, (uint16_t)packetLen)); return true; } void usbtmcd_init_cb(void) { #ifndef NDEBUG -# if CFG_USBTMC_CFG_ENABLE_488 - if(tud_usbtmc_app_capabilities.bmIntfcCapabilities488.supportsTrigger) - TU_ASSERT(&tud_usbtmc_app_msg_trigger_cb != NULL,); - // Per USB488 spec: table 8 - TU_ASSERT(!tud_usbtmc_app_capabilities.bmIntfcCapabilities.listenOnly,); - TU_ASSERT(!tud_usbtmc_app_capabilities.bmIntfcCapabilities.talkOnly,); -# endif +# if CFG_USBTMC_CFG_ENABLE_488 + if(tud_usbtmc_app_capabilities.bmIntfcCapabilities488.supportsTrigger) + TU_ASSERT(&tud_usbtmc_app_msg_trigger_cb != NULL,); + // Per USB488 spec: table 8 + TU_ASSERT(!tud_usbtmc_app_capabilities.bmIntfcCapabilities.listenOnly,); + TU_ASSERT(!tud_usbtmc_app_capabilities.bmIntfcCapabilities.talkOnly,); +# endif if(tud_usbtmc_app_capabilities.bmIntfcCapabilities.supportsIndicatorPulse) TU_ASSERT(&tud_usbtmc_app_indicator_pluse_cb != NULL,); #endif @@ -244,20 +252,16 @@ void usbtmcd_init_cb(void) bool usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length) { (void)rhport; + TU_ASSERT(usbtmc_state.state == STATE_CLOSED); uint8_t const * p_desc; uint8_t found_endpoints = 0; - - usbtmcd_reset_cb(rhport); - - // Perhaps there are other application specific class drivers, so don't assert here. - if( itf_desc->bInterfaceClass != TUD_USBTMC_APP_CLASS) - return false; - if( itf_desc->bInterfaceSubClass != TUD_USBTMC_APP_SUBCLASS) - return false; - +#ifndef NDEBUG + TU_ASSERT(itf_desc->bInterfaceClass == TUD_USBTMC_APP_CLASS); + TU_ASSERT(itf_desc->bInterfaceSubClass == TUD_USBTMC_APP_SUBCLASS); // Only 2 or 3 endpoints are allowed for USBTMC. TU_ASSERT((itf_desc->bNumEndpoints == 2) || (itf_desc->bNumEndpoints ==3)); +#endif // Interface (*p_length) = 0u; @@ -318,28 +322,27 @@ bool usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin } #endif #endif + usbtmc_state.state = STATE_IDLE; TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, 64)); return true; } void usbtmcd_reset_cb(uint8_t rhport) { - // FIXME: Do endpoints need to be closed here? - usbtmc_state.state = STATE_IDLE; - usbtmc_state.itf_id = 0xFF; - usbtmc_state.ep_bulk_in = 0; - usbtmc_state.ep_bulk_out = 0; - usbtmc_state.ep_int_in = 0; - usbtmc_state.lastBulkInTag = 0; - usbtmc_state.lastBulkOutTag = 0; - (void)rhport; + + criticalEnter(); + tu_varclr(&usbtmc_state); + usbtmc_state.itf_id = 0xFFu; + criticalLeave(); } static bool handle_devMsgOutStart(uint8_t rhport, void *data, size_t len) { (void)rhport; - TU_VERIFY(usbtmc_state.state == STATE_IDLE); + bool stateChanged = atomicChangeState(STATE_IDLE, STATE_RCV); + TU_VERIFY(stateChanged); + // must be a header, should have been confirmed before calling here. usbtmc_msg_request_dev_dep_out *msg = (usbtmc_msg_request_dev_dep_out*)data; usbtmc_state.transfer_size_remaining = msg->TransferSize; @@ -352,6 +355,9 @@ static bool handle_devMsgOutStart(uint8_t rhport, void *data, size_t len) static bool handle_devMsgOut(uint8_t rhport, void *data, size_t len, size_t packetLen) { (void)rhport; + + TU_VERIFY(usbtmc_state.state == STATE_RCV); + bool shortPacket = (packetLen < USBTMCD_MAX_PACKET_SIZE); // Packet is to be considered complete when we get enough data or at a short packet. @@ -360,18 +366,14 @@ static bool handle_devMsgOut(uint8_t rhport, void *data, size_t len, size_t pack atEnd = true; if(len > usbtmc_state.transfer_size_remaining) len = usbtmc_state.transfer_size_remaining; - tud_usbtmc_app_msg_data_cb(rhport,data, len, atEnd); + TU_VERIFY(tud_usbtmc_app_msg_data_cb(rhport,data, len, atEnd)); + // TODO: Go to an error state upon failure other than just stalling the EP? usbtmc_state.transfer_size_remaining -= len; usbtmc_state.transfer_size_sent += len; - if(atEnd) - { - usbtmc_state.state = STATE_IDLE; - } - else - { - usbtmc_state.state = STATE_RCV; - } + bool stateChanged = atomicChangeState(STATE_RCV, atEnd ? STATE_IDLE : STATE_RCV); + TU_VERIFY(stateChanged); + return true; } @@ -379,16 +381,11 @@ static bool handle_devMsgIn(uint8_t rhport, void *data, size_t len) { TU_VERIFY(len == sizeof(usbtmc_msg_request_dev_dep_in)); usbtmc_msg_request_dev_dep_in *msg = (usbtmc_msg_request_dev_dep_in*)data; - - criticalEnter(); - { - TU_VERIFY(usbtmc_state.state == STATE_IDLE); - usbtmc_state.state = STATE_TX_REQUESTED; - usbtmc_state.lastBulkInTag = msg->header.bTag; - usbtmc_state.transfer_size_remaining = msg->TransferSize; - usbtmc_state.transfer_size_sent = 0u; - } - criticalLeave(); + bool stateChanged = atomicChangeState(STATE_IDLE, STATE_TX_REQUESTED); + TU_VERIFY(stateChanged); + usbtmc_state.lastBulkInTag = msg->header.bTag; + usbtmc_state.transfer_size_remaining = msg->TransferSize; + usbtmc_state.transfer_size_sent = 0u; termCharRequested = msg->bmTransferAttributes.TermCharEnabled; termChar = msg->TermChar; @@ -403,7 +400,7 @@ static bool handle_devMsgIn(uint8_t rhport, void *data, size_t len) bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { TU_VERIFY(result == XFER_RESULT_SUCCESS); - + //uart_tx_str_sync("TMC XFER CB\r\n"); if(usbtmc_state.state == STATE_CLEARING) { return true; /* I think we can ignore everything here */ } @@ -457,7 +454,7 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint case STATE_ABORTING_BULK_OUT: TU_VERIFY(false); - return false; // Should be stalled by now... + return false; // Should be stalled by now, shouldn't have received a packet. case STATE_TX_REQUESTED: case STATE_TX_INITIATED: case STATE_ABORTING_BULK_IN: @@ -534,19 +531,26 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r (request->bRequest == TUSB_REQ_CLEAR_FEATURE) && (request->wValue == TUSB_REQ_FEATURE_EDPT_HALT)) { - if((request->wIndex) == usbtmc_state.ep_bulk_out) + uint32_t ep_addr = (request->wIndex); + + if(ep_addr == usbtmc_state.ep_bulk_out) { usmtmcd_app_bulkOut_clearFeature_cb(rhport); + // And start a new OUT xfer request now that things are clear + TU_ASSERT( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, 64)); } - else if ((request->wIndex) == usbtmc_state.ep_bulk_in) + else if (ep_addr == usbtmc_state.ep_bulk_in) { usmtmcd_app_bulkIn_clearFeature_cb(rhport); } - return false; // We want USBD core to handle sending the status response, and clear the stall condition + else + { + return false; + } + return true; } - // We only handle class requests, IN direction. - // (for now) + // Otherwise, we only handle class requests. if(request->bmRequestType_bit.type != TUSB_REQ_TYPE_CLASS) { return false; @@ -571,7 +575,7 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r { rsp.USBTMC_status = USBTMC_STATUS_FAILED; } - else if(usbtmc_state.lastBulkOutTag == (request->wValue & 0xf7u)) + else if(usbtmc_state.lastBulkOutTag == (request->wValue & 0x7Fu)) { rsp.USBTMC_status = USBTMC_STATUS_TRANSFER_NOT_IN_PROGRESS; } @@ -579,7 +583,9 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r { rsp.USBTMC_status = USBTMC_STATUS_SUCCESS; // Check if we've queued a short packet + criticalEnter(); usbtmc_state.state = STATE_ABORTING_BULK_OUT; + criticalLeave(); TU_VERIFY(tud_usbtmc_app_initiate_abort_bulk_out_cb(rhport, &(rsp.USBTMC_status))); usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out); } @@ -610,13 +616,15 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r TU_VERIFY(request->wIndex == usbtmc_state.ep_bulk_in); // wValue is the requested bTag to abort if((usbtmc_state.state == STATE_TX_REQUESTED || usbtmc_state.state == STATE_TX_INITIATED) && - usbtmc_state.lastBulkInTag == (request->wValue & 0xf7u)) + usbtmc_state.lastBulkInTag == (request->wValue & 0x7Fu)) { rsp.USBTMC_status = USBTMC_STATUS_SUCCESS; - usbtmc_state.transfer_size_remaining = 0; + usbtmc_state.transfer_size_remaining = 0u; // Check if we've queued a short packet + criticalEnter(); usbtmc_state.state = ((usbtmc_state.transfer_size_sent % USBTMCD_MAX_PACKET_SIZE) == 0) ? STATE_ABORTING_BULK_IN : STATE_ABORTING_BULK_IN_SHORTED; + criticalLeave(); if(usbtmc_state.transfer_size_sent == 0) { // Send short packet, nothing is in the buffer yet @@ -652,6 +660,7 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r .NBYTES_RXD_TXD = usbtmc_state.transfer_size_sent, }; TU_VERIFY(tud_usbtmc_app_check_abort_bulk_in_cb(rhport, &rsp)); + criticalEnter(); switch(usbtmc_state.state) { case STATE_ABORTING_BULK_IN_ABORTED: @@ -665,6 +674,7 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r default: break; } + criticalLeave(); TU_VERIFY(tud_control_xfer(rhport, request, (void*)&rsp,sizeof(rsp))); return true; @@ -678,7 +688,9 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r // control endpoint response shown in Table 31, and clear all input buffers and output buffers. usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out); usbtmc_state.transfer_size_remaining = 0; + criticalEnter(); usbtmc_state.state = STATE_CLEARING; + criticalLeave(); TU_VERIFY(tud_usbtmc_app_initiate_clear_cb(rhport, &tmcStatusCode)); TU_VERIFY(tud_control_xfer(rhport, request, (void*)&tmcStatusCode,sizeof(tmcStatusCode))); return true; @@ -702,7 +714,11 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r TU_VERIFY(tud_usbtmc_app_check_clear_cb(rhport, &clearStatusRsp)); } if(clearStatusRsp.USBTMC_status == USBTMC_STATUS_SUCCESS) + { + criticalEnter(); usbtmc_state.state = STATE_IDLE; + criticalLeave(); + } TU_VERIFY(tud_control_xfer(rhport, request, (void*)&clearStatusRsp,sizeof(clearStatusRsp))); return true; } @@ -754,7 +770,7 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r }, .StatusByte = tud_usbtmc_app_get_stb_cb(rhport, &(rsp.USBTMC_status)) }; - usbd_edpt_xfer(rhport, usbtmc_state.ep_int_in, (void*)&intMsg,sizeof(intMsg)); + usbd_edpt_xfer(rhport, usbtmc_state.ep_int_in, (void*)&intMsg, sizeof(intMsg)); } else { @@ -785,7 +801,7 @@ bool usbtmcd_control_complete_cb(uint8_t rhport, tusb_control_request_t const * { (void)rhport; //------------- Class Specific Request -------------// - TU_VERIFY (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); + TU_ASSERT (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); return true; } diff --git a/src/class/usbtmc/usbtmc_device.h b/src/class/usbtmc/usbtmc_device.h index 5c6ee2a8d..d33d73905 100644 --- a/src/class/usbtmc/usbtmc_device.h +++ b/src/class/usbtmc/usbtmc_device.h @@ -91,7 +91,7 @@ TU_ATTR_WEAK bool tud_usbtmc_app_msg_trigger_cb(uint8_t rhport, usbtmc_msg_gener bool usbtmcd_transmit_dev_msg_data( uint8_t rhport, const void * data, size_t len, - bool usingTermChar); + bool endOfMessage, bool usingTermChar); /* "callbacks" from USB device core */ From e61f2b7393382387634ab38e14ac5fab70e3c122 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Sun, 22 Sep 2019 09:55:28 -0400 Subject: [PATCH 38/45] Retool stalling EP on xfer errors. --- src/class/usbtmc/usbtmc_device.c | 43 +++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index 2c6c88cf5..e3d2c316e 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -340,8 +340,9 @@ void usbtmcd_reset_cb(uint8_t rhport) static bool handle_devMsgOutStart(uint8_t rhport, void *data, size_t len) { (void)rhport; - bool stateChanged = atomicChangeState(STATE_IDLE, STATE_RCV); - TU_VERIFY(stateChanged); + // return true upon failure, as we can assume error is being handled elsewhere. + TU_VERIFY(atomicChangeState(STATE_IDLE, STATE_RCV), true); + usbtmc_state.transfer_size_sent = 0u; // must be a header, should have been confirmed before calling here. usbtmc_msg_request_dev_dep_out *msg = (usbtmc_msg_request_dev_dep_out*)data; @@ -349,30 +350,36 @@ static bool handle_devMsgOutStart(uint8_t rhport, void *data, size_t len) TU_VERIFY(tud_usbtmc_app_msgBulkOut_start_cb(rhport,msg)); TU_VERIFY(handle_devMsgOut(rhport, (uint8_t*)data + sizeof(*msg), len - sizeof(*msg), len)); + usbtmc_state.lastBulkOutTag = msg->header.bTag; return true; } static bool handle_devMsgOut(uint8_t rhport, void *data, size_t len, size_t packetLen) { (void)rhport; - - TU_VERIFY(usbtmc_state.state == STATE_RCV); + // return true upon failure, as we can assume error is being handled elsewhere. + TU_VERIFY(usbtmc_state.state == STATE_RCV,true); bool shortPacket = (packetLen < USBTMCD_MAX_PACKET_SIZE); // Packet is to be considered complete when we get enough data or at a short packet. bool atEnd = false; if(len >= usbtmc_state.transfer_size_remaining || shortPacket) + { atEnd = true; - if(len > usbtmc_state.transfer_size_remaining) - len = usbtmc_state.transfer_size_remaining; - TU_VERIFY(tud_usbtmc_app_msg_data_cb(rhport,data, len, atEnd)); - // TODO: Go to an error state upon failure other than just stalling the EP? + } + + len = tu_min32(len, usbtmc_state.transfer_size_remaining); + + if(!tud_usbtmc_app_msg_data_cb(rhport,data, len, atEnd)) + { + // TODO: Go to an error state upon failure other than just stalling the EP? + return false; + } usbtmc_state.transfer_size_remaining -= len; usbtmc_state.transfer_size_sent += len; - bool stateChanged = atomicChangeState(STATE_RCV, atEnd ? STATE_IDLE : STATE_RCV); - TU_VERIFY(stateChanged); + TU_VERIFY(atomicChangeState(STATE_RCV, atEnd ? STATE_IDLE : STATE_RCV)); return true; } @@ -420,9 +427,11 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint switch(msg->header.MsgID) { case USBTMC_MSGID_DEV_DEP_MSG_OUT: - usbtmc_state.transfer_size_sent = 0u; - TU_VERIFY(handle_devMsgOutStart(rhport, msg, xferred_bytes)); - usbtmc_state.lastBulkOutTag = msg->header.bTag; + if(!handle_devMsgOutStart(rhport, msg, xferred_bytes)) + { + usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out); + TU_VERIFY(false); + } break; case USBTMC_MSGID_DEV_DEP_MSG_IN: @@ -440,7 +449,7 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint case USBTMC_MSGID_VENDOR_SPECIFIC_MSG_OUT: case USBTMC_MSGID_VENDOR_SPECIFIC_IN: default: - + usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out); TU_VERIFY(false); return false; } @@ -448,7 +457,11 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint return true; case STATE_RCV: - TU_VERIFY(handle_devMsgOut(rhport, usbtmc_state.ep_bulk_out_buf, xferred_bytes, xferred_bytes)); + if(!handle_devMsgOut(rhport, usbtmc_state.ep_bulk_out_buf, xferred_bytes, xferred_bytes)) + { + usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out); + TU_VERIFY(false); + } TU_VERIFY(usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, USBTMCD_MAX_PACKET_SIZE)); return true; From 10105557dc5d9bd315f70243f947386728c7d86c Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Tue, 24 Sep 2019 13:11:45 -0400 Subject: [PATCH 39/45] Let application control interface latency... --- examples/device/usbtmc/src/usbtmc_app.c | 16 ++++++- src/class/usbtmc/usbtmc_device.c | 62 ++++++++++++++++++------- src/class/usbtmc/usbtmc_device.h | 15 +++++- 3 files changed, 74 insertions(+), 19 deletions(-) diff --git a/examples/device/usbtmc/src/usbtmc_app.c b/examples/device/usbtmc/src/usbtmc_app.c index 495746e07..2982675b1 100644 --- a/examples/device/usbtmc/src/usbtmc_app.c +++ b/examples/device/usbtmc/src/usbtmc_app.c @@ -96,6 +96,13 @@ static usbtmc_msg_dev_dep_msg_in_header_t rspMsg = { } }; +void tud_usbtmc_app_open_cb(uint8_t rhport, uint8_t interface_id) +{ + (void)interface_id; + usbtmcd_start_bus_read(rhport); +} + + bool tud_usbtmc_app_msg_trigger_cb(uint8_t rhport, usbtmc_msg_generic_t* msg) { (void)rhport; (void)msg; @@ -149,6 +156,7 @@ bool tud_usbtmc_app_msg_data_cb(uint8_t rhport, void *data, size_t len, bool tra d=0; resp_delay = (uint32_t)d; } + usbtmcd_start_bus_read(rhport); return true; } @@ -162,6 +170,7 @@ bool tud_usbtmc_app_msgBulkIn_complete_cb(uint8_t rhport) bulkInStarted = 0; buffer_tx_ix = 0; } + usbtmcd_start_bus_read(rhport); return true; } @@ -259,6 +268,8 @@ bool tud_usbtmc_app_check_clear_cb(uint8_t rhport, usbtmc_get_clear_status_rsp_t queryState = 0; bulkInStarted = false; status = 0; + buffer_tx_ix = 0u; + buffer_len = 0u; rsp->USBTMC_status = USBTMC_STATUS_SUCCESS; rsp->bmClear.BulkInFifoBytes = 0u; return true; @@ -274,6 +285,7 @@ bool tud_usbtmc_app_check_abort_bulk_in_cb(uint8_t rhport, usbtmc_check_abort_bu { (void)rhport; (void)rsp; + usbtmcd_start_bus_read(rhport); return true; } @@ -288,6 +300,7 @@ bool tud_usbtmc_app_check_abort_bulk_out_cb(uint8_t rhport, usbtmc_check_abort_b { (void)rhport; (void)rsp; + usbtmcd_start_bus_read(rhport); return true; } @@ -298,6 +311,7 @@ void usmtmcd_app_bulkIn_clearFeature_cb(uint8_t rhport) void usmtmcd_app_bulkOut_clearFeature_cb(uint8_t rhport) { (void)rhport; + usbtmcd_start_bus_read(rhport); } // Return status byte, but put the transfer result status code in the rspResult argument. @@ -313,7 +327,7 @@ uint8_t tud_usbtmc_app_get_stb_cb(uint8_t rhport, uint8_t *tmcResult) return old_status; } -bool tud_usbtmc_app_indicator_pluse_cb(uint8_t rhport, tusb_control_request_t const * msg, uint8_t *tmcResult) +bool tud_usbtmc_app_indicator_pulse_cb(uint8_t rhport, tusb_control_request_t const * msg, uint8_t *tmcResult) { (void)rhport; (void)msg; diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index e3d2c316e..401b4acc4 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -99,9 +99,10 @@ static char logMsg[150]; typedef enum { - STATE_CLOSED, - STATE_IDLE, - STATE_RCV, + STATE_CLOSED, // Endpoints have not yet been opened since USB reset + STATE_NAK, // Bulk-out endpoint is in NAK state. + STATE_IDLE, // Bulk-out endpoint is waiting for CMD. + STATE_RCV, // Bulk-out is receiving DEV_DEP message STATE_TX_REQUESTED, STATE_TX_INITIATED, STATE_TX_SHORTED, @@ -243,7 +244,7 @@ void usbtmcd_init_cb(void) TU_ASSERT(!tud_usbtmc_app_capabilities.bmIntfcCapabilities.talkOnly,); # endif if(tud_usbtmc_app_capabilities.bmIntfcCapabilities.supportsIndicatorPulse) - TU_ASSERT(&tud_usbtmc_app_indicator_pluse_cb != NULL,); + TU_ASSERT(&tud_usbtmc_app_indicator_pulse_cb != NULL,); #endif usbtmcLock = osal_mutex_create(&usbtmcLockBuffer); @@ -322,11 +323,37 @@ bool usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin } #endif #endif - usbtmc_state.state = STATE_IDLE; - TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, 64)); + atomicChangeState(STATE_CLOSED, STATE_NAK); + tud_usbtmc_app_open_cb(rhport, itf_desc->iInterface); return true; } +// Tell USBTMC class to set its bulk-in EP to ACK so that it can +// receive USBTMC commands. +// Returns false if it was already in an ACK state or is busy +// processing a command (such as a clear). Returns true if it was +// in the NAK state and successfully transitioned to the ACK wait +// state. +bool usbtmcd_start_bus_read(uint8_t rhport) +{ + usbtmcd_state_enum oldState = usbtmc_state.state; + switch(oldState) + { + // These may transition to IDLE + case STATE_NAK: + case STATE_ABORTING_BULK_IN_ABORTED: + TU_VERIFY(atomicChangeState(oldState, STATE_IDLE)); + break; + // When receiving, let it remain receiving + case STATE_RCV: + break; + default: + TU_VERIFY(false); + } + TU_VERIFY(usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, 64)); + return true; +} + void usbtmcd_reset_cb(uint8_t rhport) { (void)rhport; @@ -367,19 +394,21 @@ static bool handle_devMsgOut(uint8_t rhport, void *data, size_t len, size_t pack if(len >= usbtmc_state.transfer_size_remaining || shortPacket) { atEnd = true; + TU_VERIFY(atomicChangeState(STATE_RCV, STATE_NAK)); } len = tu_min32(len, usbtmc_state.transfer_size_remaining); + usbtmc_state.transfer_size_remaining -= len; + usbtmc_state.transfer_size_sent += len; + + // App may (should?) call the wait_for_bus() command at this point if(!tud_usbtmc_app_msg_data_cb(rhport,data, len, atEnd)) { // TODO: Go to an error state upon failure other than just stalling the EP? return false; } - usbtmc_state.transfer_size_remaining -= len; - usbtmc_state.transfer_size_sent += len; - TU_VERIFY(atomicChangeState(STATE_RCV, atEnd ? STATE_IDLE : STATE_RCV)); return true; } @@ -453,7 +482,6 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint TU_VERIFY(false); return false; } - TU_VERIFY(usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, USBTMCD_MAX_PACKET_SIZE)); return true; case STATE_RCV: @@ -462,7 +490,6 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out); TU_VERIFY(false); } - TU_VERIFY(usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, USBTMCD_MAX_PACKET_SIZE)); return true; case STATE_ABORTING_BULK_OUT: @@ -482,8 +509,7 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint { switch(usbtmc_state.state) { case STATE_TX_SHORTED: - - usbtmc_state.state = STATE_IDLE; + TU_VERIFY(atomicChangeState(STATE_TX_SHORTED, STATE_NAK)); TU_VERIFY(tud_usbtmc_app_msgBulkIn_complete_cb(rhport)); break; @@ -508,7 +534,7 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint if(((packetLen % USBTMCD_MAX_PACKET_SIZE) != 0) || (packetLen == 0 )) { usbtmc_state.state = STATE_TX_SHORTED; - } + } } return true; case STATE_ABORTING_BULK_IN: @@ -548,9 +574,10 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r if(ep_addr == usbtmc_state.ep_bulk_out) { + criticalEnter(); + usbtmc_state.state = STATE_NAK; // USBD core has placed EP in NAK state for us + criticalLeave(); usmtmcd_app_bulkOut_clearFeature_cb(rhport); - // And start a new OUT xfer request now that things are clear - TU_ASSERT( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, 64)); } else if (ep_addr == usbtmc_state.ep_bulk_in) { @@ -605,6 +632,7 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r TU_VERIFY(tud_control_xfer(rhport, request, (void*)&rsp,sizeof(rsp))); return true; } + case USBTMC_bREQUEST_CHECK_ABORT_BULK_OUT_STATUS: { usbtmc_check_abort_bulk_rsp_t rsp = { @@ -750,7 +778,7 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface TU_VERIFY(request->wLength == sizeof(tmcStatusCode)); TU_VERIFY(tud_usbtmc_app_capabilities.bmIntfcCapabilities.supportsIndicatorPulse); - TU_VERIFY(tud_usbtmc_app_indicator_pluse_cb(rhport, request, &tmcStatusCode)); + TU_VERIFY(tud_usbtmc_app_indicator_pulse_cb(rhport, request, &tmcStatusCode)); TU_VERIFY(tud_control_xfer(rhport, request, (void*)&tmcStatusCode, sizeof(tmcStatusCode))); return true; } diff --git a/src/class/usbtmc/usbtmc_device.h b/src/class/usbtmc/usbtmc_device.h index d33d73905..3638b5527 100644 --- a/src/class/usbtmc/usbtmc_device.h +++ b/src/class/usbtmc/usbtmc_device.h @@ -55,6 +55,17 @@ extern usbtmc_response_capabilities_488_t const tud_usbtmc_app_capabilities; extern usbtmc_response_capabilities_t const tud_usbtmc_app_capabilities; #endif +// In order to proceed, app must call call usbtmcd_start_bus_read(rhport) during or soon after: +// * tud_usbtmc_app_open_cb +// * tud_usbtmc_app_msg_data_cb +// * tud_usbtmc_app_msgBulkIn_complete_cb +// * tud_usbtmc_app_msg_trigger_cb +// * (successful) tud_usbtmc_app_check_abort_bulk_out_cb +// * (successful) tud_usbtmc_app_check_abort_bulk_in_cb +// * (successful) usmtmcd_app_bulkOut_clearFeature_cb + +void tud_usbtmc_app_open_cb(uint8_t rhport, uint8_t interface_id); + bool tud_usbtmc_app_msgBulkOut_start_cb(uint8_t rhport, usbtmc_msg_request_dev_dep_out const * msgHeader); // transfer_complete does not imply that a message is complete. bool tud_usbtmc_app_msg_data_cb(uint8_t rhport, void *data, size_t len, bool transfer_complete); @@ -73,7 +84,7 @@ bool tud_usbtmc_app_check_abort_bulk_out_cb(uint8_t rhport, usbtmc_check_abort_b bool tud_usbtmc_app_check_clear_cb(uint8_t rhport, usbtmc_get_clear_status_rsp_t *rsp); // Indicator pulse should be 0.5 to 1.0 seconds long -TU_ATTR_WEAK bool tud_usbtmc_app_indicator_pluse_cb(uint8_t rhport, tusb_control_request_t const * msg, uint8_t *tmcResult); +TU_ATTR_WEAK bool tud_usbtmc_app_indicator_pulse_cb(uint8_t rhport, tusb_control_request_t const * msg, uint8_t *tmcResult); #if (CFG_USBTMC_CFG_ENABLE_488) uint8_t tud_usbtmc_app_get_stb_cb(uint8_t rhport, uint8_t *tmcResult); @@ -93,6 +104,8 @@ bool usbtmcd_transmit_dev_msg_data( const void * data, size_t len, bool endOfMessage, bool usingTermChar); +bool usbtmcd_start_bus_read(uint8_t rhport); + /* "callbacks" from USB device core */ From 624f4bf4ceaf1cd334326ccb3777efa2c954de1b Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Tue, 24 Sep 2019 13:42:29 -0400 Subject: [PATCH 40/45] Remove rhport from app code. If anything, it should be the interface_id. Assume a single interface, for now. --- examples/device/usbtmc/src/usbtmc_app.c | 68 +++++++++---------------- src/class/usbtmc/usbtmc_device.c | 41 +++++++-------- src/class/usbtmc/usbtmc_device.h | 37 +++++++------- 3 files changed, 64 insertions(+), 82 deletions(-) diff --git a/examples/device/usbtmc/src/usbtmc_app.c b/examples/device/usbtmc/src/usbtmc_app.c index 2982675b1..b622d6b9b 100644 --- a/examples/device/usbtmc/src/usbtmc_app.c +++ b/examples/device/usbtmc/src/usbtmc_app.c @@ -96,24 +96,22 @@ static usbtmc_msg_dev_dep_msg_in_header_t rspMsg = { } }; -void tud_usbtmc_app_open_cb(uint8_t rhport, uint8_t interface_id) +void tud_usbtmc_app_open_cb(uint8_t interface_id) { (void)interface_id; - usbtmcd_start_bus_read(rhport); + usbtmcd_start_bus_read(); } -bool tud_usbtmc_app_msg_trigger_cb(uint8_t rhport, usbtmc_msg_generic_t* msg) { - (void)rhport; +bool tud_usbtmc_app_msg_trigger_cb(usbtmc_msg_generic_t* msg) { (void)msg; // Let trigger set the SRQ status |= IEEE4882_STB_SRQ; return true; } -bool tud_usbtmc_app_msgBulkOut_start_cb(uint8_t rhport, usbtmc_msg_request_dev_dep_out const * msgHeader) +bool tud_usbtmc_app_msgBulkOut_start_cb(usbtmc_msg_request_dev_dep_out const * msgHeader) { - (void)rhport; (void)msgHeader; buffer_len = 0; if(msgHeader->TransferSize > sizeof(buffer)) @@ -124,10 +122,8 @@ bool tud_usbtmc_app_msgBulkOut_start_cb(uint8_t rhport, usbtmc_msg_request_dev_d return true; } -bool tud_usbtmc_app_msg_data_cb(uint8_t rhport, void *data, size_t len, bool transfer_complete) +bool tud_usbtmc_app_msg_data_cb(void *data, size_t len, bool transfer_complete) { - (void)rhport; - // If transfer isn't finished, we just ignore it (for now) if(len + buffer_len < sizeof(buffer)) @@ -156,13 +152,12 @@ bool tud_usbtmc_app_msg_data_cb(uint8_t rhport, void *data, size_t len, bool tra d=0; resp_delay = (uint32_t)d; } - usbtmcd_start_bus_read(rhport); + usbtmcd_start_bus_read(); return true; } -bool tud_usbtmc_app_msgBulkIn_complete_cb(uint8_t rhport) +bool tud_usbtmc_app_msgBulkIn_complete_cb() { - (void)rhport; if((buffer_tx_ix == buffer_len) || idnQuery) // done { status &= (uint8_t)~(IEEE4882_STB_MAV); // clear MAV @@ -170,17 +165,15 @@ bool tud_usbtmc_app_msgBulkIn_complete_cb(uint8_t rhport) bulkInStarted = 0; buffer_tx_ix = 0; } - usbtmcd_start_bus_read(rhport); + usbtmcd_start_bus_read(); return true; } static unsigned int msgReqLen; -bool tud_usbtmc_app_msgBulkIn_request_cb(uint8_t rhport, usbtmc_msg_request_dev_dep_in const * request) +bool tud_usbtmc_app_msgBulkIn_request_cb(usbtmc_msg_request_dev_dep_in const * request) { - (void)rhport; - rspMsg.header.MsgID = request->header.MsgID, rspMsg.header.bTag = request->header.bTag, rspMsg.header.bTagInverse = request->header.bTagInverse; @@ -200,7 +193,7 @@ bool tud_usbtmc_app_msgBulkIn_request_cb(uint8_t rhport, usbtmc_msg_request_dev_ else { size_t txlen = tu_min32(buffer_len-buffer_tx_ix,msgReqLen); - usbtmcd_transmit_dev_msg_data(rhport, &buffer[buffer_tx_ix], txlen, + usbtmcd_transmit_dev_msg_data(&buffer[buffer_tx_ix], txlen, (buffer_tx_ix+txlen) == buffer_len, false); buffer_tx_ix += txlen; } @@ -209,7 +202,6 @@ bool tud_usbtmc_app_msgBulkIn_request_cb(uint8_t rhport, usbtmc_msg_request_dev_ } void usbtmc_app_task_iter(void) { - uint8_t const rhport = 0; switch(queryState) { case 0: break; @@ -234,14 +226,14 @@ void usbtmc_app_task_iter(void) { if(bulkInStarted && (buffer_tx_ix == 0)) { if(idnQuery) { - usbtmcd_transmit_dev_msg_data(rhport, idn, tu_min32(sizeof(idn)-1,msgReqLen),true,false); + usbtmcd_transmit_dev_msg_data(idn, tu_min32(sizeof(idn)-1,msgReqLen),true,false); queryState = 0; bulkInStarted = 0; } else { buffer_tx_ix = tu_min32(buffer_len,msgReqLen); - usbtmcd_transmit_dev_msg_data(rhport, buffer, buffer_tx_ix, buffer_tx_ix == buffer_len, false); + usbtmcd_transmit_dev_msg_data(buffer, buffer_tx_ix, buffer_tx_ix == buffer_len, false); } // MAV is cleared in the transfer complete callback. } @@ -252,9 +244,8 @@ void usbtmc_app_task_iter(void) { } } -bool tud_usbtmc_app_initiate_clear_cb(uint8_t rhport, uint8_t *tmcResult) +bool tud_usbtmc_app_initiate_clear_cb(uint8_t *tmcResult) { - (void)rhport; *tmcResult = USBTMC_STATUS_SUCCESS; queryState = 0; bulkInStarted = false; @@ -262,9 +253,8 @@ bool tud_usbtmc_app_initiate_clear_cb(uint8_t rhport, uint8_t *tmcResult) return true; } -bool tud_usbtmc_app_check_clear_cb(uint8_t rhport, usbtmc_get_clear_status_rsp_t *rsp) +bool tud_usbtmc_app_check_clear_cb(usbtmc_get_clear_status_rsp_t *rsp) { - (void)rhport; queryState = 0; bulkInStarted = false; status = 0; @@ -274,50 +264,43 @@ bool tud_usbtmc_app_check_clear_cb(uint8_t rhport, usbtmc_get_clear_status_rsp_t rsp->bmClear.BulkInFifoBytes = 0u; return true; } -bool tud_usbtmc_app_initiate_abort_bulk_in_cb(uint8_t rhport, uint8_t *tmcResult) +bool tud_usbtmc_app_initiate_abort_bulk_in_cb(uint8_t *tmcResult) { - (void)rhport; bulkInStarted = 0; *tmcResult = USBTMC_STATUS_SUCCESS; return true; } -bool tud_usbtmc_app_check_abort_bulk_in_cb(uint8_t rhport, usbtmc_check_abort_bulk_rsp_t *rsp) +bool tud_usbtmc_app_check_abort_bulk_in_cb(usbtmc_check_abort_bulk_rsp_t *rsp) { - (void)rhport; (void)rsp; - usbtmcd_start_bus_read(rhport); + usbtmcd_start_bus_read(); return true; } -bool tud_usbtmc_app_initiate_abort_bulk_out_cb(uint8_t rhport, uint8_t *tmcResult) +bool tud_usbtmc_app_initiate_abort_bulk_out_cb(uint8_t *tmcResult) { - (void)rhport; *tmcResult = USBTMC_STATUS_SUCCESS; return true; } -bool tud_usbtmc_app_check_abort_bulk_out_cb(uint8_t rhport, usbtmc_check_abort_bulk_rsp_t *rsp) +bool tud_usbtmc_app_check_abort_bulk_out_cb(usbtmc_check_abort_bulk_rsp_t *rsp) { - (void)rhport; (void)rsp; - usbtmcd_start_bus_read(rhport); + usbtmcd_start_bus_read(); return true; } -void usmtmcd_app_bulkIn_clearFeature_cb(uint8_t rhport) +void usmtmcd_app_bulkIn_clearFeature_cb(void) { - (void)rhport; } -void usmtmcd_app_bulkOut_clearFeature_cb(uint8_t rhport) +void usmtmcd_app_bulkOut_clearFeature_cb(void) { - (void)rhport; - usbtmcd_start_bus_read(rhport); + usbtmcd_start_bus_read(); } // Return status byte, but put the transfer result status code in the rspResult argument. -uint8_t tud_usbtmc_app_get_stb_cb(uint8_t rhport, uint8_t *tmcResult) +uint8_t tud_usbtmc_app_get_stb_cb(uint8_t *tmcResult) { - (void)rhport; uint8_t old_status = status; status = (uint8_t)(status & ~(IEEE4882_STB_SRQ)); // clear SRQ @@ -327,9 +310,8 @@ uint8_t tud_usbtmc_app_get_stb_cb(uint8_t rhport, uint8_t *tmcResult) return old_status; } -bool tud_usbtmc_app_indicator_pulse_cb(uint8_t rhport, tusb_control_request_t const * msg, uint8_t *tmcResult) +bool tud_usbtmc_app_indicator_pulse_cb(tusb_control_request_t const * msg, uint8_t *tmcResult) { - (void)rhport; (void)msg; led_indicator_pulse(); *tmcResult = USBTMC_STATUS_SUCCESS; diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index 401b4acc4..a65c5e7c4 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -119,6 +119,7 @@ typedef struct volatile usbtmcd_state_enum state; uint8_t itf_id; + uint8_t rhport; uint8_t ep_bulk_in; uint8_t ep_bulk_out; uint8_t ep_int_in; @@ -186,7 +187,6 @@ bool atomicChangeState(usbtmcd_state_enum expectedState, usbtmcd_state_enum newS // We can't just send the whole thing at once because we need to concatanate the // header with the data. bool usbtmcd_transmit_dev_msg_data( - uint8_t rhport, const void * data, size_t len, bool endOfMessage, bool usingTermChar) @@ -229,7 +229,7 @@ bool usbtmcd_transmit_dev_msg_data( bool stateChanged = atomicChangeState(STATE_TX_REQUESTED, (packetLen >= txBufLen) ? STATE_TX_INITIATED : STATE_TX_SHORTED); TU_VERIFY(stateChanged); - TU_VERIFY(usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf, (uint16_t)packetLen)); + TU_VERIFY(usbd_edpt_xfer(usbtmc_state.rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf, (uint16_t)packetLen)); return true; } @@ -269,6 +269,7 @@ bool usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin p_desc = (uint8_t const *) itf_desc; usbtmc_state.itf_id = itf_desc->bInterfaceNumber; + usbtmc_state.rhport = rhport; while (found_endpoints < itf_desc->bNumEndpoints) { @@ -324,7 +325,7 @@ bool usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin #endif #endif atomicChangeState(STATE_CLOSED, STATE_NAK); - tud_usbtmc_app_open_cb(rhport, itf_desc->iInterface); + tud_usbtmc_app_open_cb(itf_desc->iInterface); return true; } @@ -334,7 +335,7 @@ bool usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin // processing a command (such as a clear). Returns true if it was // in the NAK state and successfully transitioned to the ACK wait // state. -bool usbtmcd_start_bus_read(uint8_t rhport) +bool usbtmcd_start_bus_read() { usbtmcd_state_enum oldState = usbtmc_state.state; switch(oldState) @@ -350,7 +351,7 @@ bool usbtmcd_start_bus_read(uint8_t rhport) default: TU_VERIFY(false); } - TU_VERIFY(usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, 64)); + TU_VERIFY(usbd_edpt_xfer(usbtmc_state.rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, 64)); return true; } @@ -374,7 +375,7 @@ static bool handle_devMsgOutStart(uint8_t rhport, void *data, size_t len) // must be a header, should have been confirmed before calling here. usbtmc_msg_request_dev_dep_out *msg = (usbtmc_msg_request_dev_dep_out*)data; usbtmc_state.transfer_size_remaining = msg->TransferSize; - TU_VERIFY(tud_usbtmc_app_msgBulkOut_start_cb(rhport,msg)); + TU_VERIFY(tud_usbtmc_app_msgBulkOut_start_cb(msg)); TU_VERIFY(handle_devMsgOut(rhport, (uint8_t*)data + sizeof(*msg), len - sizeof(*msg), len)); usbtmc_state.lastBulkOutTag = msg->header.bTag; @@ -403,7 +404,7 @@ static bool handle_devMsgOut(uint8_t rhport, void *data, size_t len, size_t pack usbtmc_state.transfer_size_sent += len; // App may (should?) call the wait_for_bus() command at this point - if(!tud_usbtmc_app_msg_data_cb(rhport,data, len, atEnd)) + if(!tud_usbtmc_app_msg_data_cb(data, len, atEnd)) { // TODO: Go to an error state upon failure other than just stalling the EP? return false; @@ -413,7 +414,7 @@ static bool handle_devMsgOut(uint8_t rhport, void *data, size_t len, size_t pack return true; } -static bool handle_devMsgIn(uint8_t rhport, void *data, size_t len) +static bool handle_devMsgIn(void *data, size_t len) { TU_VERIFY(len == sizeof(usbtmc_msg_request_dev_dep_in)); usbtmc_msg_request_dev_dep_in *msg = (usbtmc_msg_request_dev_dep_in*)data; @@ -429,7 +430,7 @@ static bool handle_devMsgIn(uint8_t rhport, void *data, size_t len) if(termCharRequested) TU_VERIFY(tud_usbtmc_app_capabilities.bmDevCapabilities.canEndBulkInOnTermChar); - TU_VERIFY(tud_usbtmc_app_msgBulkIn_request_cb(rhport, msg)); + TU_VERIFY(tud_usbtmc_app_msgBulkIn_request_cb(msg)); return true; } @@ -464,14 +465,14 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint break; case USBTMC_MSGID_DEV_DEP_MSG_IN: - TU_VERIFY(handle_devMsgIn(rhport, msg, xferred_bytes)); + TU_VERIFY(handle_devMsgIn(msg, xferred_bytes)); break; #if (CFG_USBTMC_CFG_ENABLE_488) case USBTMC_MSGID_USB488_TRIGGER: // Spec says we halt the EP if we didn't declare we support it. TU_VERIFY(tud_usbtmc_app_capabilities.bmIntfcCapabilities488.supportsTrigger); - TU_VERIFY(tud_usbtmc_app_msg_trigger_cb(rhport, msg)); + TU_VERIFY(tud_usbtmc_app_msg_trigger_cb(msg)); break; #endif @@ -626,7 +627,7 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r criticalEnter(); usbtmc_state.state = STATE_ABORTING_BULK_OUT; criticalLeave(); - TU_VERIFY(tud_usbtmc_app_initiate_abort_bulk_out_cb(rhport, &(rsp.USBTMC_status))); + TU_VERIFY(tud_usbtmc_app_initiate_abort_bulk_out_cb(&(rsp.USBTMC_status))); usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out); } TU_VERIFY(tud_control_xfer(rhport, request, (void*)&rsp,sizeof(rsp))); @@ -642,7 +643,7 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r TU_VERIFY(request->bmRequestType == 0xA2); // in,class,EP TU_VERIFY(request->wLength == sizeof(rsp)); TU_VERIFY(request->wIndex == usbtmc_state.ep_bulk_out); - TU_VERIFY(tud_usbtmc_app_check_abort_bulk_out_cb(rhport, &rsp)); + TU_VERIFY(tud_usbtmc_app_check_abort_bulk_out_cb(&rsp)); TU_VERIFY(usbd_edpt_xfer(rhport, 0u, (void*)&rsp,sizeof(rsp))); return true; } @@ -672,7 +673,7 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf,(uint16_t)0u)); usbtmc_state.state = STATE_ABORTING_BULK_IN_SHORTED; } - TU_VERIFY(tud_usbtmc_app_initiate_abort_bulk_in_cb(rhport, &(rsp.USBTMC_status))); + TU_VERIFY(tud_usbtmc_app_initiate_abort_bulk_in_cb(&(rsp.USBTMC_status))); } else if((usbtmc_state.state == STATE_TX_REQUESTED || usbtmc_state.state == STATE_TX_INITIATED)) { // FIXME: Unsure how to check if the OUT endpoint fifo is non-empty.... @@ -700,7 +701,7 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r }, .NBYTES_RXD_TXD = usbtmc_state.transfer_size_sent, }; - TU_VERIFY(tud_usbtmc_app_check_abort_bulk_in_cb(rhport, &rsp)); + TU_VERIFY(tud_usbtmc_app_check_abort_bulk_in_cb(&rsp)); criticalEnter(); switch(usbtmc_state.state) { @@ -732,7 +733,7 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r criticalEnter(); usbtmc_state.state = STATE_CLEARING; criticalLeave(); - TU_VERIFY(tud_usbtmc_app_initiate_clear_cb(rhport, &tmcStatusCode)); + TU_VERIFY(tud_usbtmc_app_initiate_clear_cb(&tmcStatusCode)); TU_VERIFY(tud_control_xfer(rhport, request, (void*)&tmcStatusCode,sizeof(tmcStatusCode))); return true; } @@ -752,7 +753,7 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r else { // Let app check if it's clear - TU_VERIFY(tud_usbtmc_app_check_clear_cb(rhport, &clearStatusRsp)); + TU_VERIFY(tud_usbtmc_app_check_clear_cb(&clearStatusRsp)); } if(clearStatusRsp.USBTMC_status == USBTMC_STATUS_SUCCESS) { @@ -778,7 +779,7 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface TU_VERIFY(request->wLength == sizeof(tmcStatusCode)); TU_VERIFY(tud_usbtmc_app_capabilities.bmIntfcCapabilities.supportsIndicatorPulse); - TU_VERIFY(tud_usbtmc_app_indicator_pulse_cb(rhport, request, &tmcStatusCode)); + TU_VERIFY(tud_usbtmc_app_indicator_pulse_cb(request, &tmcStatusCode)); TU_VERIFY(tud_control_xfer(rhport, request, (void*)&tmcStatusCode, sizeof(tmcStatusCode))); return true; } @@ -809,13 +810,13 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r .one = 1, .bTag = bTag & 0x7Fu, }, - .StatusByte = tud_usbtmc_app_get_stb_cb(rhport, &(rsp.USBTMC_status)) + .StatusByte = tud_usbtmc_app_get_stb_cb(&(rsp.USBTMC_status)) }; usbd_edpt_xfer(rhport, usbtmc_state.ep_int_in, (void*)&intMsg, sizeof(intMsg)); } else { - rsp.statusByte = tud_usbtmc_app_get_stb_cb(rhport, &(rsp.USBTMC_status)); + rsp.statusByte = tud_usbtmc_app_get_stb_cb(&(rsp.USBTMC_status)); } TU_VERIFY(tud_control_xfer(rhport, request, (void*)&rsp, sizeof(rsp))); return true; diff --git a/src/class/usbtmc/usbtmc_device.h b/src/class/usbtmc/usbtmc_device.h index 3638b5527..9f88e5e83 100644 --- a/src/class/usbtmc/usbtmc_device.h +++ b/src/class/usbtmc/usbtmc_device.h @@ -64,32 +64,32 @@ extern usbtmc_response_capabilities_t const tud_usbtmc_app_capabilities; // * (successful) tud_usbtmc_app_check_abort_bulk_in_cb // * (successful) usmtmcd_app_bulkOut_clearFeature_cb -void tud_usbtmc_app_open_cb(uint8_t rhport, uint8_t interface_id); +void tud_usbtmc_app_open_cb(uint8_t interface_id); -bool tud_usbtmc_app_msgBulkOut_start_cb(uint8_t rhport, usbtmc_msg_request_dev_dep_out const * msgHeader); +bool tud_usbtmc_app_msgBulkOut_start_cb(usbtmc_msg_request_dev_dep_out const * msgHeader); // transfer_complete does not imply that a message is complete. -bool tud_usbtmc_app_msg_data_cb(uint8_t rhport, void *data, size_t len, bool transfer_complete); -void usmtmcd_app_bulkOut_clearFeature_cb(uint8_t rhport); // Notice to clear and abort the pending BULK out transfer +bool tud_usbtmc_app_msg_data_cb( void *data, size_t len, bool transfer_complete); +void usmtmcd_app_bulkOut_clearFeature_cb(); // Notice to clear and abort the pending BULK out transfer -bool tud_usbtmc_app_msgBulkIn_request_cb(uint8_t rhport, usbtmc_msg_request_dev_dep_in const * request); -bool tud_usbtmc_app_msgBulkIn_complete_cb(uint8_t rhport); -void usmtmcd_app_bulkIn_clearFeature_cb(uint8_t rhport); // Notice to clear and abort the pending BULK out transfer +bool tud_usbtmc_app_msgBulkIn_request_cb(usbtmc_msg_request_dev_dep_in const * request); +bool tud_usbtmc_app_msgBulkIn_complete_cb(); +void usmtmcd_app_bulkIn_clearFeature_cb(); // Notice to clear and abort the pending BULK out transfer -bool tud_usbtmc_app_initiate_abort_bulk_in_cb(uint8_t rhport, uint8_t *tmcResult); -bool tud_usbtmc_app_initiate_abort_bulk_out_cb(uint8_t rhport, uint8_t *tmcResult); -bool tud_usbtmc_app_initiate_clear_cb(uint8_t rhport, uint8_t *tmcResult); +bool tud_usbtmc_app_initiate_abort_bulk_in_cb(uint8_t *tmcResult); +bool tud_usbtmc_app_initiate_abort_bulk_out_cb(uint8_t *tmcResult); +bool tud_usbtmc_app_initiate_clear_cb(uint8_t *tmcResult); -bool tud_usbtmc_app_check_abort_bulk_in_cb(uint8_t rhport, usbtmc_check_abort_bulk_rsp_t *rsp); -bool tud_usbtmc_app_check_abort_bulk_out_cb(uint8_t rhport, usbtmc_check_abort_bulk_rsp_t *rsp); -bool tud_usbtmc_app_check_clear_cb(uint8_t rhport, usbtmc_get_clear_status_rsp_t *rsp); +bool tud_usbtmc_app_check_abort_bulk_in_cb(usbtmc_check_abort_bulk_rsp_t *rsp); +bool tud_usbtmc_app_check_abort_bulk_out_cb(usbtmc_check_abort_bulk_rsp_t *rsp); +bool tud_usbtmc_app_check_clear_cb(usbtmc_get_clear_status_rsp_t *rsp); // Indicator pulse should be 0.5 to 1.0 seconds long -TU_ATTR_WEAK bool tud_usbtmc_app_indicator_pulse_cb(uint8_t rhport, tusb_control_request_t const * msg, uint8_t *tmcResult); +TU_ATTR_WEAK bool tud_usbtmc_app_indicator_pulse_cb(tusb_control_request_t const * msg, uint8_t *tmcResult); #if (CFG_USBTMC_CFG_ENABLE_488) -uint8_t tud_usbtmc_app_get_stb_cb(uint8_t rhport, uint8_t *tmcResult); -TU_ATTR_WEAK bool tud_usbtmc_app_msg_trigger_cb(uint8_t rhport, usbtmc_msg_generic_t* msg); -//TU_ATTR_WEAK bool tud_usbtmc_app_go_to_local_cb(uint8_t rhport); +uint8_t tud_usbtmc_app_get_stb_cb(uint8_t *tmcResult); +TU_ATTR_WEAK bool tud_usbtmc_app_msg_trigger_cb(usbtmc_msg_generic_t* msg); +//TU_ATTR_WEAK bool tud_usbtmc_app_go_to_local_cb(); #endif /******************************************* @@ -100,11 +100,10 @@ TU_ATTR_WEAK bool tud_usbtmc_app_msg_trigger_cb(uint8_t rhport, usbtmc_msg_gener ******************************************/ bool usbtmcd_transmit_dev_msg_data( - uint8_t rhport, const void * data, size_t len, bool endOfMessage, bool usingTermChar); -bool usbtmcd_start_bus_read(uint8_t rhport); +bool usbtmcd_start_bus_read(); /* "callbacks" from USB device core */ From 412a279073b77c6f5d3b6796089eb90509322a7a Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Tue, 24 Sep 2019 13:54:45 -0400 Subject: [PATCH 41/45] I never understood why I need to write void as empty function arguments. --- src/class/usbtmc/usbtmc_device.c | 6 +++--- src/class/usbtmc/usbtmc_device.h | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index a65c5e7c4..dad892f43 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -511,7 +511,7 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint switch(usbtmc_state.state) { case STATE_TX_SHORTED: TU_VERIFY(atomicChangeState(STATE_TX_SHORTED, STATE_NAK)); - TU_VERIFY(tud_usbtmc_app_msgBulkIn_complete_cb(rhport)); + TU_VERIFY(tud_usbtmc_app_msgBulkIn_complete_cb()); break; case STATE_TX_INITIATED: @@ -578,11 +578,11 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r criticalEnter(); usbtmc_state.state = STATE_NAK; // USBD core has placed EP in NAK state for us criticalLeave(); - usmtmcd_app_bulkOut_clearFeature_cb(rhport); + usmtmcd_app_bulkOut_clearFeature_cb(); } else if (ep_addr == usbtmc_state.ep_bulk_in) { - usmtmcd_app_bulkIn_clearFeature_cb(rhport); + usmtmcd_app_bulkIn_clearFeature_cb(); } else { diff --git a/src/class/usbtmc/usbtmc_device.h b/src/class/usbtmc/usbtmc_device.h index 9f88e5e83..a3f0e90e0 100644 --- a/src/class/usbtmc/usbtmc_device.h +++ b/src/class/usbtmc/usbtmc_device.h @@ -69,11 +69,11 @@ void tud_usbtmc_app_open_cb(uint8_t interface_id); bool tud_usbtmc_app_msgBulkOut_start_cb(usbtmc_msg_request_dev_dep_out const * msgHeader); // transfer_complete does not imply that a message is complete. bool tud_usbtmc_app_msg_data_cb( void *data, size_t len, bool transfer_complete); -void usmtmcd_app_bulkOut_clearFeature_cb(); // Notice to clear and abort the pending BULK out transfer +void usmtmcd_app_bulkOut_clearFeature_cb(void); // Notice to clear and abort the pending BULK out transfer bool tud_usbtmc_app_msgBulkIn_request_cb(usbtmc_msg_request_dev_dep_in const * request); -bool tud_usbtmc_app_msgBulkIn_complete_cb(); -void usmtmcd_app_bulkIn_clearFeature_cb(); // Notice to clear and abort the pending BULK out transfer +bool tud_usbtmc_app_msgBulkIn_complete_cb(void); +void usmtmcd_app_bulkIn_clearFeature_cb(void); // Notice to clear and abort the pending BULK out transfer bool tud_usbtmc_app_initiate_abort_bulk_in_cb(uint8_t *tmcResult); bool tud_usbtmc_app_initiate_abort_bulk_out_cb(uint8_t *tmcResult); @@ -103,7 +103,7 @@ bool usbtmcd_transmit_dev_msg_data( const void * data, size_t len, bool endOfMessage, bool usingTermChar); -bool usbtmcd_start_bus_read(); +bool usbtmcd_start_bus_read(void); /* "callbacks" from USB device core */ From 2d4352bfe9d969c76374cd15c3332fbe9f98d66a Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Wed, 25 Sep 2019 11:34:27 -0400 Subject: [PATCH 42/45] Rename USBTMC functions. --- examples/device/usbtmc/src/tusb_config.h | 2 +- examples/device/usbtmc/src/usbtmc_app.c | 26 ++++++++++++------------ src/class/usbtmc/usbtmc_device.c | 18 ++++++++-------- src/class/usbtmc/usbtmc_device.h | 20 +++++++++--------- 4 files changed, 33 insertions(+), 33 deletions(-) diff --git a/examples/device/usbtmc/src/tusb_config.h b/examples/device/usbtmc/src/tusb_config.h index 688fb02be..c20b05fbb 100644 --- a/examples/device/usbtmc/src/tusb_config.h +++ b/examples/device/usbtmc/src/tusb_config.h @@ -57,7 +57,7 @@ #define CFG_TUD_USBTMC 1 #define CFG_TUD_USBTMC_ENABLE_INT_EP 1 -#define CFG_USBTMC_CFG_ENABLE_488 1 +#define CFG_TUD_USBTMC_ENABLE_488 1 #ifdef __cplusplus } diff --git a/examples/device/usbtmc/src/usbtmc_app.c b/examples/device/usbtmc/src/usbtmc_app.c index b622d6b9b..d06014ce8 100644 --- a/examples/device/usbtmc/src/usbtmc_app.c +++ b/examples/device/usbtmc/src/usbtmc_app.c @@ -29,7 +29,7 @@ #include "bsp/board.h" #include "main.h" -#if (CFG_USBTMC_CFG_ENABLE_488) +#if (CFG_TUD_USBTMC_ENABLE_488) usbtmc_response_capabilities_488_t const #else usbtmc_response_capabilities_t const @@ -48,7 +48,7 @@ tud_usbtmc_app_capabilities = .canEndBulkInOnTermChar = 0 }, -#if (CFG_USBTMC_CFG_ENABLE_488) +#if (CFG_TUD_USBTMC_ENABLE_488) .bcdUSB488 = USBTMC_488_VERSION, .bmIntfcCapabilities488 = { @@ -99,7 +99,7 @@ static usbtmc_msg_dev_dep_msg_in_header_t rspMsg = { void tud_usbtmc_app_open_cb(uint8_t interface_id) { (void)interface_id; - usbtmcd_start_bus_read(); + tud_usbtmc_start_bus_read(); } @@ -152,7 +152,7 @@ bool tud_usbtmc_app_msg_data_cb(void *data, size_t len, bool transfer_complete) d=0; resp_delay = (uint32_t)d; } - usbtmcd_start_bus_read(); + tud_usbtmc_start_bus_read(); return true; } @@ -165,7 +165,7 @@ bool tud_usbtmc_app_msgBulkIn_complete_cb() bulkInStarted = 0; buffer_tx_ix = 0; } - usbtmcd_start_bus_read(); + tud_usbtmc_start_bus_read(); return true; } @@ -193,7 +193,7 @@ bool tud_usbtmc_app_msgBulkIn_request_cb(usbtmc_msg_request_dev_dep_in const * r else { size_t txlen = tu_min32(buffer_len-buffer_tx_ix,msgReqLen); - usbtmcd_transmit_dev_msg_data(&buffer[buffer_tx_ix], txlen, + tud_usbtmc_transmit_dev_msg_data(&buffer[buffer_tx_ix], txlen, (buffer_tx_ix+txlen) == buffer_len, false); buffer_tx_ix += txlen; } @@ -226,14 +226,14 @@ void usbtmc_app_task_iter(void) { if(bulkInStarted && (buffer_tx_ix == 0)) { if(idnQuery) { - usbtmcd_transmit_dev_msg_data(idn, tu_min32(sizeof(idn)-1,msgReqLen),true,false); + tud_usbtmc_transmit_dev_msg_data(idn, tu_min32(sizeof(idn)-1,msgReqLen),true,false); queryState = 0; bulkInStarted = 0; } else { buffer_tx_ix = tu_min32(buffer_len,msgReqLen); - usbtmcd_transmit_dev_msg_data(buffer, buffer_tx_ix, buffer_tx_ix == buffer_len, false); + tud_usbtmc_transmit_dev_msg_data(buffer, buffer_tx_ix, buffer_tx_ix == buffer_len, false); } // MAV is cleared in the transfer complete callback. } @@ -273,7 +273,7 @@ bool tud_usbtmc_app_initiate_abort_bulk_in_cb(uint8_t *tmcResult) bool tud_usbtmc_app_check_abort_bulk_in_cb(usbtmc_check_abort_bulk_rsp_t *rsp) { (void)rsp; - usbtmcd_start_bus_read(); + tud_usbtmc_start_bus_read(); return true; } @@ -286,16 +286,16 @@ bool tud_usbtmc_app_initiate_abort_bulk_out_cb(uint8_t *tmcResult) bool tud_usbtmc_app_check_abort_bulk_out_cb(usbtmc_check_abort_bulk_rsp_t *rsp) { (void)rsp; - usbtmcd_start_bus_read(); + tud_usbtmc_start_bus_read(); return true; } -void usmtmcd_app_bulkIn_clearFeature_cb(void) +void tud_usbtmc_app_bulkIn_clearFeature_cb(void) { } -void usmtmcd_app_bulkOut_clearFeature_cb(void) +void tud_usmtmc_app_bulkOut_clearFeature_cb(void) { - usbtmcd_start_bus_read(); + tud_usbtmc_start_bus_read(); } // Return status byte, but put the transfer result status code in the rspResult argument. diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index dad892f43..f0b74fe38 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -186,7 +186,7 @@ bool atomicChangeState(usbtmcd_state_enum expectedState, usbtmcd_state_enum newS // We can't just send the whole thing at once because we need to concatanate the // header with the data. -bool usbtmcd_transmit_dev_msg_data( +bool tud_usbtmc_transmit_dev_msg_data( const void * data, size_t len, bool endOfMessage, bool usingTermChar) @@ -236,7 +236,7 @@ bool usbtmcd_transmit_dev_msg_data( void usbtmcd_init_cb(void) { #ifndef NDEBUG -# if CFG_USBTMC_CFG_ENABLE_488 +# if CFG_TUD_USBTMC_ENABLE_488 if(tud_usbtmc_app_capabilities.bmIntfcCapabilities488.supportsTrigger) TU_ASSERT(&tud_usbtmc_app_msg_trigger_cb != NULL,); // Per USB488 spec: table 8 @@ -316,7 +316,7 @@ bool usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin { TU_ASSERT(usbtmc_state.ep_int_in != 0); } -#if (CFG_USBTMC_CFG_ENABLE_488) +#if (CFG_TUD_USBTMC_ENABLE_488) if(tud_usbtmc_app_capabilities.bmIntfcCapabilities488.is488_2 || tud_usbtmc_app_capabilities.bmDevCapabilities488.SR1) { @@ -335,7 +335,7 @@ bool usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin // processing a command (such as a clear). Returns true if it was // in the NAK state and successfully transitioned to the ACK wait // state. -bool usbtmcd_start_bus_read() +bool tud_usbtmc_start_bus_read() { usbtmcd_state_enum oldState = usbtmc_state.state; switch(oldState) @@ -468,7 +468,7 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint TU_VERIFY(handle_devMsgIn(msg, xferred_bytes)); break; -#if (CFG_USBTMC_CFG_ENABLE_488) +#if (CFG_TUD_USBTMC_ENABLE_488) case USBTMC_MSGID_USB488_TRIGGER: // Spec says we halt the EP if we didn't declare we support it. TU_VERIFY(tud_usbtmc_app_capabilities.bmIntfcCapabilities488.supportsTrigger); @@ -562,7 +562,7 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * request) { uint8_t tmcStatusCode = USBTMC_STATUS_FAILED; -#if (CFG_USBTMC_CFG_ENABLE_488) +#if (CFG_TUD_USBTMC_ENABLE_488) uint8_t bTag; #endif @@ -578,11 +578,11 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r criticalEnter(); usbtmc_state.state = STATE_NAK; // USBD core has placed EP in NAK state for us criticalLeave(); - usmtmcd_app_bulkOut_clearFeature_cb(); + tud_usmtmc_app_bulkOut_clearFeature_cb(); } else if (ep_addr == usbtmc_state.ep_bulk_in) { - usmtmcd_app_bulkIn_clearFeature_cb(); + tud_usbtmc_app_bulkIn_clearFeature_cb(); } else { @@ -783,7 +783,7 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r TU_VERIFY(tud_control_xfer(rhport, request, (void*)&tmcStatusCode, sizeof(tmcStatusCode))); return true; } -#if (CFG_USBTMC_CFG_ENABLE_488) +#if (CFG_TUD_USBTMC_ENABLE_488) // USB488 required requests case USB488_bREQUEST_READ_STATUS_BYTE: diff --git a/src/class/usbtmc/usbtmc_device.h b/src/class/usbtmc/usbtmc_device.h index a3f0e90e0..9f1020e58 100644 --- a/src/class/usbtmc/usbtmc_device.h +++ b/src/class/usbtmc/usbtmc_device.h @@ -37,8 +37,8 @@ #include "usbtmc.h" // Enable 488 mode by default -#if !defined(CFG_USBTMC_CFG_ENABLE_488) -#define CFG_CFG_USBTMC_CFG_ENABLE_488 (1) +#if !defined(CFG_TUD_USBTMC_ENABLE_488) +#define CFG_TUD_USBTMC_ENABLE_488 (1) #endif // USB spec says that full-speed must be 8,16,32, or 64. @@ -49,31 +49,31 @@ * Functions to be implemeted by the class implementation */ -#if (CFG_USBTMC_CFG_ENABLE_488) +#if (CFG_TUD_USBTMC_ENABLE_488) extern usbtmc_response_capabilities_488_t const tud_usbtmc_app_capabilities; #else extern usbtmc_response_capabilities_t const tud_usbtmc_app_capabilities; #endif -// In order to proceed, app must call call usbtmcd_start_bus_read(rhport) during or soon after: +// In order to proceed, app must call call tud_usbtmc_start_bus_read(rhport) during or soon after: // * tud_usbtmc_app_open_cb // * tud_usbtmc_app_msg_data_cb // * tud_usbtmc_app_msgBulkIn_complete_cb // * tud_usbtmc_app_msg_trigger_cb // * (successful) tud_usbtmc_app_check_abort_bulk_out_cb // * (successful) tud_usbtmc_app_check_abort_bulk_in_cb -// * (successful) usmtmcd_app_bulkOut_clearFeature_cb +// * (successful) tud_usmtmc_app_bulkOut_clearFeature_cb void tud_usbtmc_app_open_cb(uint8_t interface_id); bool tud_usbtmc_app_msgBulkOut_start_cb(usbtmc_msg_request_dev_dep_out const * msgHeader); // transfer_complete does not imply that a message is complete. bool tud_usbtmc_app_msg_data_cb( void *data, size_t len, bool transfer_complete); -void usmtmcd_app_bulkOut_clearFeature_cb(void); // Notice to clear and abort the pending BULK out transfer +void tud_usmtmc_app_bulkOut_clearFeature_cb(void); // Notice to clear and abort the pending BULK out transfer bool tud_usbtmc_app_msgBulkIn_request_cb(usbtmc_msg_request_dev_dep_in const * request); bool tud_usbtmc_app_msgBulkIn_complete_cb(void); -void usmtmcd_app_bulkIn_clearFeature_cb(void); // Notice to clear and abort the pending BULK out transfer +void tud_usbtmc_app_bulkIn_clearFeature_cb(void); // Notice to clear and abort the pending BULK out transfer bool tud_usbtmc_app_initiate_abort_bulk_in_cb(uint8_t *tmcResult); bool tud_usbtmc_app_initiate_abort_bulk_out_cb(uint8_t *tmcResult); @@ -86,7 +86,7 @@ bool tud_usbtmc_app_check_clear_cb(usbtmc_get_clear_status_rsp_t *rsp); // Indicator pulse should be 0.5 to 1.0 seconds long TU_ATTR_WEAK bool tud_usbtmc_app_indicator_pulse_cb(tusb_control_request_t const * msg, uint8_t *tmcResult); -#if (CFG_USBTMC_CFG_ENABLE_488) +#if (CFG_TUD_USBTMC_ENABLE_488) uint8_t tud_usbtmc_app_get_stb_cb(uint8_t *tmcResult); TU_ATTR_WEAK bool tud_usbtmc_app_msg_trigger_cb(usbtmc_msg_generic_t* msg); //TU_ATTR_WEAK bool tud_usbtmc_app_go_to_local_cb(); @@ -99,11 +99,11 @@ TU_ATTR_WEAK bool tud_usbtmc_app_msg_trigger_cb(usbtmc_msg_generic_t* msg); * notified that the transfer is complete. ******************************************/ -bool usbtmcd_transmit_dev_msg_data( +bool tud_usbtmc_transmit_dev_msg_data( const void * data, size_t len, bool endOfMessage, bool usingTermChar); -bool usbtmcd_start_bus_read(void); +bool tud_usbtmc_start_bus_read(void); /* "callbacks" from USB device core */ From 3a87dd65d735085845cbf799add77596cf737f44 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Wed, 25 Sep 2019 12:17:49 -0400 Subject: [PATCH 43/45] Change getting the capabilities structure to a callback instead of an extern struct. --- examples/device/usbtmc/src/usbtmc_app.c | 14 ++++++++-- src/class/usbtmc/usbtmc_device.c | 36 ++++++++++++++++--------- src/class/usbtmc/usbtmc_device.h | 12 ++++----- 3 files changed, 42 insertions(+), 20 deletions(-) diff --git a/examples/device/usbtmc/src/usbtmc_app.c b/examples/device/usbtmc/src/usbtmc_app.c index d06014ce8..924a33fab 100644 --- a/examples/device/usbtmc/src/usbtmc_app.c +++ b/examples/device/usbtmc/src/usbtmc_app.c @@ -30,9 +30,9 @@ #include "main.h" #if (CFG_TUD_USBTMC_ENABLE_488) -usbtmc_response_capabilities_488_t const +static usbtmc_response_capabilities_488_t const #else -usbtmc_response_capabilities_t const +static usbtmc_response_capabilities_t const #endif tud_usbtmc_app_capabilities = { @@ -102,6 +102,16 @@ void tud_usbtmc_app_open_cb(uint8_t interface_id) tud_usbtmc_start_bus_read(); } +#if (CFG_TUD_USBTMC_ENABLE_488) +usbtmc_response_capabilities_488_t const * +#else +usbtmc_response_capabilities_t const * +#endif +tud_usbtmc_get_capabilities_cb() +{ + return &tud_usbtmc_app_capabilities; +} + bool tud_usbtmc_app_msg_trigger_cb(usbtmc_msg_generic_t* msg) { (void)msg; diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index f0b74fe38..927ac8ecf 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -114,6 +114,13 @@ typedef enum STATE_NUM_STATES } usbtmcd_state_enum; +#if (CFG_TUD_USBTMC_ENABLE_488) + typedef usbtmc_response_capabilities_488_t usbtmc_capabilities_specific_t; +#else + typedef usbtmc_response_capabilities_t usbtmc_capabilities_specific_t; +#endif + + typedef struct { volatile usbtmcd_state_enum state; @@ -135,6 +142,8 @@ typedef struct uint8_t lastBulkInTag; // used for aborts (mostly) uint8_t const * devInBuffer; // pointer to application-layer used for transmissions + + usbtmc_capabilities_specific_t const * capabilities; } usbtmc_interface_state_t; static usbtmc_interface_state_t usbtmc_state = @@ -199,7 +208,7 @@ bool tud_usbtmc_transmit_dev_msg_data( TU_ASSERT(usbtmc_state.transfer_size_sent == 0u); if(usingTermChar) { - TU_ASSERT(tud_usbtmc_app_capabilities.bmDevCapabilities.canEndBulkInOnTermChar); + TU_ASSERT(usbtmc_state.capabilities->bmDevCapabilities.canEndBulkInOnTermChar); TU_ASSERT(termCharRequested); TU_ASSERT(((uint8_t*)data)[len-1u] == termChar); } @@ -235,15 +244,16 @@ bool tud_usbtmc_transmit_dev_msg_data( void usbtmcd_init_cb(void) { + usbtmc_state.capabilities = tud_usbtmc_get_capabilities_cb(); #ifndef NDEBUG # if CFG_TUD_USBTMC_ENABLE_488 - if(tud_usbtmc_app_capabilities.bmIntfcCapabilities488.supportsTrigger) + if(usbtmc_state.capabilities->bmIntfcCapabilities488.supportsTrigger) TU_ASSERT(&tud_usbtmc_app_msg_trigger_cb != NULL,); // Per USB488 spec: table 8 - TU_ASSERT(!tud_usbtmc_app_capabilities.bmIntfcCapabilities.listenOnly,); - TU_ASSERT(!tud_usbtmc_app_capabilities.bmIntfcCapabilities.talkOnly,); + TU_ASSERT(!usbtmc_state.capabilities->bmIntfcCapabilities.listenOnly,); + TU_ASSERT(!usbtmc_state.capabilities->bmIntfcCapabilities.talkOnly,); # endif - if(tud_usbtmc_app_capabilities.bmIntfcCapabilities.supportsIndicatorPulse) + if(usbtmc_state.capabilities->bmIntfcCapabilities.supportsIndicatorPulse) TU_ASSERT(&tud_usbtmc_app_indicator_pulse_cb != NULL,); #endif @@ -317,8 +327,8 @@ bool usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin TU_ASSERT(usbtmc_state.ep_int_in != 0); } #if (CFG_TUD_USBTMC_ENABLE_488) - if(tud_usbtmc_app_capabilities.bmIntfcCapabilities488.is488_2 || - tud_usbtmc_app_capabilities.bmDevCapabilities488.SR1) + if(usbtmc_state.capabilities->bmIntfcCapabilities488.is488_2 || + usbtmc_state.capabilities->bmDevCapabilities488.SR1) { TU_ASSERT(usbtmc_state.ep_int_in != 0); } @@ -358,9 +368,11 @@ bool tud_usbtmc_start_bus_read() void usbtmcd_reset_cb(uint8_t rhport) { (void)rhport; + usbtmc_capabilities_specific_t const * capabilities = tud_usbtmc_get_capabilities_cb(); criticalEnter(); tu_varclr(&usbtmc_state); + usbtmc_state.capabilities = capabilities; usbtmc_state.itf_id = 0xFFu; criticalLeave(); } @@ -428,7 +440,7 @@ static bool handle_devMsgIn(void *data, size_t len) termChar = msg->TermChar; if(termCharRequested) - TU_VERIFY(tud_usbtmc_app_capabilities.bmDevCapabilities.canEndBulkInOnTermChar); + TU_VERIFY(usbtmc_state.capabilities->bmDevCapabilities.canEndBulkInOnTermChar); TU_VERIFY(tud_usbtmc_app_msgBulkIn_request_cb(msg)); return true; @@ -471,7 +483,7 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint #if (CFG_TUD_USBTMC_ENABLE_488) case USBTMC_MSGID_USB488_TRIGGER: // Spec says we halt the EP if we didn't declare we support it. - TU_VERIFY(tud_usbtmc_app_capabilities.bmIntfcCapabilities488.supportsTrigger); + TU_VERIFY(usbtmc_state.capabilities->bmIntfcCapabilities488.supportsTrigger); TU_VERIFY(tud_usbtmc_app_msg_trigger_cb(msg)); break; @@ -768,8 +780,8 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r case USBTMC_bREQUEST_GET_CAPABILITIES: { TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface - TU_VERIFY(request->wLength == sizeof(tud_usbtmc_app_capabilities)); - TU_VERIFY(tud_control_xfer(rhport, request, (void*)&tud_usbtmc_app_capabilities, sizeof(tud_usbtmc_app_capabilities))); + TU_VERIFY(request->wLength == sizeof(*(usbtmc_state.capabilities))); + TU_VERIFY(tud_control_xfer(rhport, request, (void*)usbtmc_state.capabilities, sizeof(*usbtmc_state.capabilities))); return true; } // USBTMC Optional Requests @@ -778,7 +790,7 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r { TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface TU_VERIFY(request->wLength == sizeof(tmcStatusCode)); - TU_VERIFY(tud_usbtmc_app_capabilities.bmIntfcCapabilities.supportsIndicatorPulse); + TU_VERIFY(usbtmc_state.capabilities->bmIntfcCapabilities.supportsIndicatorPulse); TU_VERIFY(tud_usbtmc_app_indicator_pulse_cb(request, &tmcStatusCode)); TU_VERIFY(tud_control_xfer(rhport, request, (void*)&tmcStatusCode, sizeof(tmcStatusCode))); return true; diff --git a/src/class/usbtmc/usbtmc_device.h b/src/class/usbtmc/usbtmc_device.h index 9f1020e58..adccd65e1 100644 --- a/src/class/usbtmc/usbtmc_device.h +++ b/src/class/usbtmc/usbtmc_device.h @@ -49,12 +49,6 @@ * Functions to be implemeted by the class implementation */ -#if (CFG_TUD_USBTMC_ENABLE_488) -extern usbtmc_response_capabilities_488_t const tud_usbtmc_app_capabilities; -#else -extern usbtmc_response_capabilities_t const tud_usbtmc_app_capabilities; -#endif - // In order to proceed, app must call call tud_usbtmc_start_bus_read(rhport) during or soon after: // * tud_usbtmc_app_open_cb // * tud_usbtmc_app_msg_data_cb @@ -64,6 +58,12 @@ extern usbtmc_response_capabilities_t const tud_usbtmc_app_capabilities; // * (successful) tud_usbtmc_app_check_abort_bulk_in_cb // * (successful) tud_usmtmc_app_bulkOut_clearFeature_cb +#if (CFG_TUD_USBTMC_ENABLE_488) +usbtmc_response_capabilities_488_t const * tud_usbtmc_get_capabilities_cb(void); +#else +usbtmc_response_capabilities_t const * tud_usbtmc_get_capabilities_cb(void); +#endif + void tud_usbtmc_app_open_cb(uint8_t interface_id); bool tud_usbtmc_app_msgBulkOut_start_cb(usbtmc_msg_request_dev_dep_out const * msgHeader); From 6c6a01cbcdc98a1e1346fc74b0d79db90443c7e3 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Wed, 25 Sep 2019 12:18:10 -0400 Subject: [PATCH 44/45] USBTMC: Minor updates to testing script. --- examples/device/usbtmc/visaQuery.py | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/examples/device/usbtmc/visaQuery.py b/examples/device/usbtmc/visaQuery.py index 4d4b50c4b..44b5fd875 100644 --- a/examples/device/usbtmc/visaQuery.py +++ b/examples/device/usbtmc/visaQuery.py @@ -11,6 +11,7 @@ def test_idn(): def test_echo(m,n): longstr = "0123456789abcdefghijklmnopqrstuvwxyz" * 50 + t0 = time.monotonic() #Next try echo from 1 to 175 characters (200 is max buffer size on DUT) for i in range(m,n): @@ -22,7 +23,9 @@ def test_echo(m,n): #print (":".join("{:02x}".format(ord(c)) for c in xt)) #print (":".join("{:02x}".format(ord(c)) for c in y)) assert(xt == y), f"failed i={i}" - inst.read_stb();# Just to make USB logging easier by sending a control query + #inst.read_stb();# Just to make USB logging easier by sending a control query (bad thing is that this made things slow) + t = time.monotonic() - t0 + print(f" elapsed: {t:0.3} sec") def test_trig(): # clear SRQ @@ -70,13 +73,13 @@ def test_read_timeout(): inst.read_stb() assert (inst.read_stb() == 0) inst.write("delay 500") - t0 = time.time() + t0 = time.monotonic() try: rsp = inst.read() assert(false), "Read should have resulted in timeout" except visa.VisaIOError: - print("Got expected exception") - t = time.time() - t0 + print(" Got expected exception") + t = time.monotonic() - t0 assert ((t*1000.0) > (inst.timeout - 300)) assert ((t*1000.0) < (inst.timeout + 300)) print(f"Delay was {t:0.3}") @@ -92,16 +95,16 @@ def test_abort_in(): assert (inst.read_stb() == 0) inst.write("delay 500") inst.write("xxx") - t0 = time.time() + t0 = time.monotonic() try: rsp = inst.read() assert(false), "Read should have resulted in timeout" except visa.VisaIOError: - print("Got expected exception") - t = time.time() - t0 + print(" Got expected exception") + t = time.monotonic() - t0 assert ((t*1000.0) > (inst.timeout - 300)) assert ((t*1000.0) < (inst.timeout + 300)) - print(f"Delay was {t:0.3}") + print(f" Delay was {t:0.3}") # Response is still in queue, so send a clear (to be more helpful to the next test) inst.timeout = 800 y = inst.read() @@ -180,5 +183,11 @@ test_indicate() print("+ TRIG") test_trig() +# Untested: +# abort bulk out +# LLO, GTL, etc +# Throughput rate? +# Transmitting a message using multiple transfers + inst.close() print("Test complete") From 6841b236e89cad45024280c44a77e43490635af2 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Wed, 25 Sep 2019 12:45:39 -0400 Subject: [PATCH 45/45] Remove _app from callback function names. --- examples/device/usbtmc/src/usbtmc_app.c | 32 ++++++++--------- src/class/usbtmc/usbtmc_device.c | 38 ++++++++++---------- src/class/usbtmc/usbtmc_device.h | 46 ++++++++++++------------- 3 files changed, 58 insertions(+), 58 deletions(-) diff --git a/examples/device/usbtmc/src/usbtmc_app.c b/examples/device/usbtmc/src/usbtmc_app.c index 924a33fab..0e39b4227 100644 --- a/examples/device/usbtmc/src/usbtmc_app.c +++ b/examples/device/usbtmc/src/usbtmc_app.c @@ -96,7 +96,7 @@ static usbtmc_msg_dev_dep_msg_in_header_t rspMsg = { } }; -void tud_usbtmc_app_open_cb(uint8_t interface_id) +void tud_usbtmc_open_cb(uint8_t interface_id) { (void)interface_id; tud_usbtmc_start_bus_read(); @@ -113,14 +113,14 @@ tud_usbtmc_get_capabilities_cb() } -bool tud_usbtmc_app_msg_trigger_cb(usbtmc_msg_generic_t* msg) { +bool tud_usbtmc_msg_trigger_cb(usbtmc_msg_generic_t* msg) { (void)msg; // Let trigger set the SRQ status |= IEEE4882_STB_SRQ; return true; } -bool tud_usbtmc_app_msgBulkOut_start_cb(usbtmc_msg_request_dev_dep_out const * msgHeader) +bool tud_usbtmc_msgBulkOut_start_cb(usbtmc_msg_request_dev_dep_out const * msgHeader) { (void)msgHeader; buffer_len = 0; @@ -132,7 +132,7 @@ bool tud_usbtmc_app_msgBulkOut_start_cb(usbtmc_msg_request_dev_dep_out const * m return true; } -bool tud_usbtmc_app_msg_data_cb(void *data, size_t len, bool transfer_complete) +bool tud_usbtmc_msg_data_cb(void *data, size_t len, bool transfer_complete) { // If transfer isn't finished, we just ignore it (for now) @@ -166,7 +166,7 @@ bool tud_usbtmc_app_msg_data_cb(void *data, size_t len, bool transfer_complete) return true; } -bool tud_usbtmc_app_msgBulkIn_complete_cb() +bool tud_usbtmc_msgBulkIn_complete_cb() { if((buffer_tx_ix == buffer_len) || idnQuery) // done { @@ -182,7 +182,7 @@ bool tud_usbtmc_app_msgBulkIn_complete_cb() static unsigned int msgReqLen; -bool tud_usbtmc_app_msgBulkIn_request_cb(usbtmc_msg_request_dev_dep_in const * request) +bool tud_usbtmc_msgBulkIn_request_cb(usbtmc_msg_request_dev_dep_in const * request) { rspMsg.header.MsgID = request->header.MsgID, rspMsg.header.bTag = request->header.bTag, @@ -254,7 +254,7 @@ void usbtmc_app_task_iter(void) { } } -bool tud_usbtmc_app_initiate_clear_cb(uint8_t *tmcResult) +bool tud_usbtmc_initiate_clear_cb(uint8_t *tmcResult) { *tmcResult = USBTMC_STATUS_SUCCESS; queryState = 0; @@ -263,7 +263,7 @@ bool tud_usbtmc_app_initiate_clear_cb(uint8_t *tmcResult) return true; } -bool tud_usbtmc_app_check_clear_cb(usbtmc_get_clear_status_rsp_t *rsp) +bool tud_usbtmc_check_clear_cb(usbtmc_get_clear_status_rsp_t *rsp) { queryState = 0; bulkInStarted = false; @@ -274,42 +274,42 @@ bool tud_usbtmc_app_check_clear_cb(usbtmc_get_clear_status_rsp_t *rsp) rsp->bmClear.BulkInFifoBytes = 0u; return true; } -bool tud_usbtmc_app_initiate_abort_bulk_in_cb(uint8_t *tmcResult) +bool tud_usbtmc_initiate_abort_bulk_in_cb(uint8_t *tmcResult) { bulkInStarted = 0; *tmcResult = USBTMC_STATUS_SUCCESS; return true; } -bool tud_usbtmc_app_check_abort_bulk_in_cb(usbtmc_check_abort_bulk_rsp_t *rsp) +bool tud_usbtmc_check_abort_bulk_in_cb(usbtmc_check_abort_bulk_rsp_t *rsp) { (void)rsp; tud_usbtmc_start_bus_read(); return true; } -bool tud_usbtmc_app_initiate_abort_bulk_out_cb(uint8_t *tmcResult) +bool tud_usbtmc_initiate_abort_bulk_out_cb(uint8_t *tmcResult) { *tmcResult = USBTMC_STATUS_SUCCESS; return true; } -bool tud_usbtmc_app_check_abort_bulk_out_cb(usbtmc_check_abort_bulk_rsp_t *rsp) +bool tud_usbtmc_check_abort_bulk_out_cb(usbtmc_check_abort_bulk_rsp_t *rsp) { (void)rsp; tud_usbtmc_start_bus_read(); return true; } -void tud_usbtmc_app_bulkIn_clearFeature_cb(void) +void tud_usbtmc_bulkIn_clearFeature_cb(void) { } -void tud_usmtmc_app_bulkOut_clearFeature_cb(void) +void tud_usmtmc_bulkOut_clearFeature_cb(void) { tud_usbtmc_start_bus_read(); } // Return status byte, but put the transfer result status code in the rspResult argument. -uint8_t tud_usbtmc_app_get_stb_cb(uint8_t *tmcResult) +uint8_t tud_usbtmc_get_stb_cb(uint8_t *tmcResult) { uint8_t old_status = status; status = (uint8_t)(status & ~(IEEE4882_STB_SRQ)); // clear SRQ @@ -320,7 +320,7 @@ uint8_t tud_usbtmc_app_get_stb_cb(uint8_t *tmcResult) return old_status; } -bool tud_usbtmc_app_indicator_pulse_cb(tusb_control_request_t const * msg, uint8_t *tmcResult) +bool tud_usbtmc_indicator_pulse_cb(tusb_control_request_t const * msg, uint8_t *tmcResult) { (void)msg; led_indicator_pulse(); diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index 927ac8ecf..c8e742fc5 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -248,13 +248,13 @@ void usbtmcd_init_cb(void) #ifndef NDEBUG # if CFG_TUD_USBTMC_ENABLE_488 if(usbtmc_state.capabilities->bmIntfcCapabilities488.supportsTrigger) - TU_ASSERT(&tud_usbtmc_app_msg_trigger_cb != NULL,); + TU_ASSERT(&tud_usbtmc_msg_trigger_cb != NULL,); // Per USB488 spec: table 8 TU_ASSERT(!usbtmc_state.capabilities->bmIntfcCapabilities.listenOnly,); TU_ASSERT(!usbtmc_state.capabilities->bmIntfcCapabilities.talkOnly,); # endif if(usbtmc_state.capabilities->bmIntfcCapabilities.supportsIndicatorPulse) - TU_ASSERT(&tud_usbtmc_app_indicator_pulse_cb != NULL,); + TU_ASSERT(&tud_usbtmc_indicator_pulse_cb != NULL,); #endif usbtmcLock = osal_mutex_create(&usbtmcLockBuffer); @@ -335,7 +335,7 @@ bool usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin #endif #endif atomicChangeState(STATE_CLOSED, STATE_NAK); - tud_usbtmc_app_open_cb(itf_desc->iInterface); + tud_usbtmc_open_cb(itf_desc->iInterface); return true; } @@ -387,7 +387,7 @@ static bool handle_devMsgOutStart(uint8_t rhport, void *data, size_t len) // must be a header, should have been confirmed before calling here. usbtmc_msg_request_dev_dep_out *msg = (usbtmc_msg_request_dev_dep_out*)data; usbtmc_state.transfer_size_remaining = msg->TransferSize; - TU_VERIFY(tud_usbtmc_app_msgBulkOut_start_cb(msg)); + TU_VERIFY(tud_usbtmc_msgBulkOut_start_cb(msg)); TU_VERIFY(handle_devMsgOut(rhport, (uint8_t*)data + sizeof(*msg), len - sizeof(*msg), len)); usbtmc_state.lastBulkOutTag = msg->header.bTag; @@ -416,7 +416,7 @@ static bool handle_devMsgOut(uint8_t rhport, void *data, size_t len, size_t pack usbtmc_state.transfer_size_sent += len; // App may (should?) call the wait_for_bus() command at this point - if(!tud_usbtmc_app_msg_data_cb(data, len, atEnd)) + if(!tud_usbtmc_msg_data_cb(data, len, atEnd)) { // TODO: Go to an error state upon failure other than just stalling the EP? return false; @@ -442,7 +442,7 @@ static bool handle_devMsgIn(void *data, size_t len) if(termCharRequested) TU_VERIFY(usbtmc_state.capabilities->bmDevCapabilities.canEndBulkInOnTermChar); - TU_VERIFY(tud_usbtmc_app_msgBulkIn_request_cb(msg)); + TU_VERIFY(tud_usbtmc_msgBulkIn_request_cb(msg)); return true; } @@ -484,7 +484,7 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint case USBTMC_MSGID_USB488_TRIGGER: // Spec says we halt the EP if we didn't declare we support it. TU_VERIFY(usbtmc_state.capabilities->bmIntfcCapabilities488.supportsTrigger); - TU_VERIFY(tud_usbtmc_app_msg_trigger_cb(msg)); + TU_VERIFY(tud_usbtmc_msg_trigger_cb(msg)); break; #endif @@ -523,7 +523,7 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint switch(usbtmc_state.state) { case STATE_TX_SHORTED: TU_VERIFY(atomicChangeState(STATE_TX_SHORTED, STATE_NAK)); - TU_VERIFY(tud_usbtmc_app_msgBulkIn_complete_cb()); + TU_VERIFY(tud_usbtmc_msgBulkIn_complete_cb()); break; case STATE_TX_INITIATED: @@ -590,11 +590,11 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r criticalEnter(); usbtmc_state.state = STATE_NAK; // USBD core has placed EP in NAK state for us criticalLeave(); - tud_usmtmc_app_bulkOut_clearFeature_cb(); + tud_usmtmc_bulkOut_clearFeature_cb(); } else if (ep_addr == usbtmc_state.ep_bulk_in) { - tud_usbtmc_app_bulkIn_clearFeature_cb(); + tud_usbtmc_bulkIn_clearFeature_cb(); } else { @@ -639,7 +639,7 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r criticalEnter(); usbtmc_state.state = STATE_ABORTING_BULK_OUT; criticalLeave(); - TU_VERIFY(tud_usbtmc_app_initiate_abort_bulk_out_cb(&(rsp.USBTMC_status))); + TU_VERIFY(tud_usbtmc_initiate_abort_bulk_out_cb(&(rsp.USBTMC_status))); usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out); } TU_VERIFY(tud_control_xfer(rhport, request, (void*)&rsp,sizeof(rsp))); @@ -655,7 +655,7 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r TU_VERIFY(request->bmRequestType == 0xA2); // in,class,EP TU_VERIFY(request->wLength == sizeof(rsp)); TU_VERIFY(request->wIndex == usbtmc_state.ep_bulk_out); - TU_VERIFY(tud_usbtmc_app_check_abort_bulk_out_cb(&rsp)); + TU_VERIFY(tud_usbtmc_check_abort_bulk_out_cb(&rsp)); TU_VERIFY(usbd_edpt_xfer(rhport, 0u, (void*)&rsp,sizeof(rsp))); return true; } @@ -685,7 +685,7 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf,(uint16_t)0u)); usbtmc_state.state = STATE_ABORTING_BULK_IN_SHORTED; } - TU_VERIFY(tud_usbtmc_app_initiate_abort_bulk_in_cb(&(rsp.USBTMC_status))); + TU_VERIFY(tud_usbtmc_initiate_abort_bulk_in_cb(&(rsp.USBTMC_status))); } else if((usbtmc_state.state == STATE_TX_REQUESTED || usbtmc_state.state == STATE_TX_INITIATED)) { // FIXME: Unsure how to check if the OUT endpoint fifo is non-empty.... @@ -713,7 +713,7 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r }, .NBYTES_RXD_TXD = usbtmc_state.transfer_size_sent, }; - TU_VERIFY(tud_usbtmc_app_check_abort_bulk_in_cb(&rsp)); + TU_VERIFY(tud_usbtmc_check_abort_bulk_in_cb(&rsp)); criticalEnter(); switch(usbtmc_state.state) { @@ -745,7 +745,7 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r criticalEnter(); usbtmc_state.state = STATE_CLEARING; criticalLeave(); - TU_VERIFY(tud_usbtmc_app_initiate_clear_cb(&tmcStatusCode)); + TU_VERIFY(tud_usbtmc_initiate_clear_cb(&tmcStatusCode)); TU_VERIFY(tud_control_xfer(rhport, request, (void*)&tmcStatusCode,sizeof(tmcStatusCode))); return true; } @@ -765,7 +765,7 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r else { // Let app check if it's clear - TU_VERIFY(tud_usbtmc_app_check_clear_cb(&clearStatusRsp)); + TU_VERIFY(tud_usbtmc_check_clear_cb(&clearStatusRsp)); } if(clearStatusRsp.USBTMC_status == USBTMC_STATUS_SUCCESS) { @@ -791,7 +791,7 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface TU_VERIFY(request->wLength == sizeof(tmcStatusCode)); TU_VERIFY(usbtmc_state.capabilities->bmIntfcCapabilities.supportsIndicatorPulse); - TU_VERIFY(tud_usbtmc_app_indicator_pulse_cb(request, &tmcStatusCode)); + TU_VERIFY(tud_usbtmc_indicator_pulse_cb(request, &tmcStatusCode)); TU_VERIFY(tud_control_xfer(rhport, request, (void*)&tmcStatusCode, sizeof(tmcStatusCode))); return true; } @@ -822,13 +822,13 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r .one = 1, .bTag = bTag & 0x7Fu, }, - .StatusByte = tud_usbtmc_app_get_stb_cb(&(rsp.USBTMC_status)) + .StatusByte = tud_usbtmc_get_stb_cb(&(rsp.USBTMC_status)) }; usbd_edpt_xfer(rhport, usbtmc_state.ep_int_in, (void*)&intMsg, sizeof(intMsg)); } else { - rsp.statusByte = tud_usbtmc_app_get_stb_cb(&(rsp.USBTMC_status)); + rsp.statusByte = tud_usbtmc_get_stb_cb(&(rsp.USBTMC_status)); } TU_VERIFY(tud_control_xfer(rhport, request, (void*)&rsp, sizeof(rsp))); return true; diff --git a/src/class/usbtmc/usbtmc_device.h b/src/class/usbtmc/usbtmc_device.h index adccd65e1..4c52989c2 100644 --- a/src/class/usbtmc/usbtmc_device.h +++ b/src/class/usbtmc/usbtmc_device.h @@ -50,13 +50,13 @@ */ // In order to proceed, app must call call tud_usbtmc_start_bus_read(rhport) during or soon after: -// * tud_usbtmc_app_open_cb -// * tud_usbtmc_app_msg_data_cb -// * tud_usbtmc_app_msgBulkIn_complete_cb -// * tud_usbtmc_app_msg_trigger_cb -// * (successful) tud_usbtmc_app_check_abort_bulk_out_cb -// * (successful) tud_usbtmc_app_check_abort_bulk_in_cb -// * (successful) tud_usmtmc_app_bulkOut_clearFeature_cb +// * tud_usbtmc_open_cb +// * tud_usbtmc_msg_data_cb +// * tud_usbtmc_msgBulkIn_complete_cb +// * tud_usbtmc_msg_trigger_cb +// * (successful) tud_usbtmc_check_abort_bulk_out_cb +// * (successful) tud_usbtmc_check_abort_bulk_in_cb +// * (successful) tud_usmtmc_bulkOut_clearFeature_cb #if (CFG_TUD_USBTMC_ENABLE_488) usbtmc_response_capabilities_488_t const * tud_usbtmc_get_capabilities_cb(void); @@ -64,31 +64,31 @@ usbtmc_response_capabilities_488_t const * tud_usbtmc_get_capabilities_cb(void); usbtmc_response_capabilities_t const * tud_usbtmc_get_capabilities_cb(void); #endif -void tud_usbtmc_app_open_cb(uint8_t interface_id); +void tud_usbtmc_open_cb(uint8_t interface_id); -bool tud_usbtmc_app_msgBulkOut_start_cb(usbtmc_msg_request_dev_dep_out const * msgHeader); +bool tud_usbtmc_msgBulkOut_start_cb(usbtmc_msg_request_dev_dep_out const * msgHeader); // transfer_complete does not imply that a message is complete. -bool tud_usbtmc_app_msg_data_cb( void *data, size_t len, bool transfer_complete); -void tud_usmtmc_app_bulkOut_clearFeature_cb(void); // Notice to clear and abort the pending BULK out transfer +bool tud_usbtmc_msg_data_cb( void *data, size_t len, bool transfer_complete); +void tud_usmtmc_bulkOut_clearFeature_cb(void); // Notice to clear and abort the pending BULK out transfer -bool tud_usbtmc_app_msgBulkIn_request_cb(usbtmc_msg_request_dev_dep_in const * request); -bool tud_usbtmc_app_msgBulkIn_complete_cb(void); -void tud_usbtmc_app_bulkIn_clearFeature_cb(void); // Notice to clear and abort the pending BULK out transfer +bool tud_usbtmc_msgBulkIn_request_cb(usbtmc_msg_request_dev_dep_in const * request); +bool tud_usbtmc_msgBulkIn_complete_cb(void); +void tud_usbtmc_bulkIn_clearFeature_cb(void); // Notice to clear and abort the pending BULK out transfer -bool tud_usbtmc_app_initiate_abort_bulk_in_cb(uint8_t *tmcResult); -bool tud_usbtmc_app_initiate_abort_bulk_out_cb(uint8_t *tmcResult); -bool tud_usbtmc_app_initiate_clear_cb(uint8_t *tmcResult); +bool tud_usbtmc_initiate_abort_bulk_in_cb(uint8_t *tmcResult); +bool tud_usbtmc_initiate_abort_bulk_out_cb(uint8_t *tmcResult); +bool tud_usbtmc_initiate_clear_cb(uint8_t *tmcResult); -bool tud_usbtmc_app_check_abort_bulk_in_cb(usbtmc_check_abort_bulk_rsp_t *rsp); -bool tud_usbtmc_app_check_abort_bulk_out_cb(usbtmc_check_abort_bulk_rsp_t *rsp); -bool tud_usbtmc_app_check_clear_cb(usbtmc_get_clear_status_rsp_t *rsp); +bool tud_usbtmc_check_abort_bulk_in_cb(usbtmc_check_abort_bulk_rsp_t *rsp); +bool tud_usbtmc_check_abort_bulk_out_cb(usbtmc_check_abort_bulk_rsp_t *rsp); +bool tud_usbtmc_check_clear_cb(usbtmc_get_clear_status_rsp_t *rsp); // Indicator pulse should be 0.5 to 1.0 seconds long -TU_ATTR_WEAK bool tud_usbtmc_app_indicator_pulse_cb(tusb_control_request_t const * msg, uint8_t *tmcResult); +TU_ATTR_WEAK bool tud_usbtmc_indicator_pulse_cb(tusb_control_request_t const * msg, uint8_t *tmcResult); #if (CFG_TUD_USBTMC_ENABLE_488) -uint8_t tud_usbtmc_app_get_stb_cb(uint8_t *tmcResult); -TU_ATTR_WEAK bool tud_usbtmc_app_msg_trigger_cb(usbtmc_msg_generic_t* msg); +uint8_t tud_usbtmc_get_stb_cb(uint8_t *tmcResult); +TU_ATTR_WEAK bool tud_usbtmc_msg_trigger_cb(usbtmc_msg_generic_t* msg); //TU_ATTR_WEAK bool tud_usbtmc_app_go_to_local_cb(); #endif