From c755aee7d0c1e2486055e02ac353878d8da3ba59 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Sat, 14 Sep 2019 22:55:42 -0400 Subject: [PATCH 01/18] 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 02/18] 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 03/18] 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 04/18] 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 05/18] 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 06/18] 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 07/18] 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 08/18] 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 09/18] 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 10/18] 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 11/18] 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 12/18] 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 13/18] 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 14/18] 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 15/18] 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 16/18] 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 17/18] 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 18/18] 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