From 9a726dc7ed9af8f9b035b18a667105a48d8d6d8a Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Wed, 18 Sep 2019 21:31:38 -0400 Subject: [PATCH] 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;