From b8ce2afa0f0454d6937f9d4447bddb547738bc08 Mon Sep 17 00:00:00 2001 From: Hardy Griech Date: Mon, 1 May 2023 10:23:38 +0200 Subject: [PATCH 001/118] sigrok can now be enabled/disabled completely --- CMakeLists.txt | 37 ++++++++++++++++++++++++++++-------- Makefile | 10 +++++----- include/picoprobe_config.h | 1 - include/tusb_config.h | 8 +++++--- src/main.c | 12 ++++++------ src/pico-sigrok/cdc_sigrok.c | 8 -------- src/pico-sigrok/cdc_sigrok.h | 16 +++++++++------- src/pico-sigrok/sigrok.h | 4 +++- src/usb_descriptors.c | 8 ++++---- 9 files changed, 61 insertions(+), 43 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b6e6ddbc7..217bf0fcb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,15 +1,32 @@ +# CMakeLists.txt for YaPicoprobe +# +# Parameters +# ---------- +# - PICO_BOARD pico|pico_w|pico_debug_probe, default "pico" +# - PICOPROBE_VERSION_MAJOR major version number +# - PICOPROBE_VERSION_MINOR minor version number +# - OPT_SIGROK enable/disable sigrok module, default "1" +# +# - GIT_HASH short git hash +# - PROJECT project name for cmake +# cmake_minimum_required(VERSION 3.12) # -# board definition: pico or pico_w, default is pico +# Compile options # if(PICO_BOARD STREQUAL "") set(PICO_BOARD pico) endif() -set(PICO_STDIO_UART 0) +option(OPT_SIGROK "Enable sigrok" 1) # -# below order is important +# SDK options +# +set(PICO_STDIO_UART 0) # disable stdio UART, actually this goes to a CDC + +# +# below (and above) order is important # include(pico_sdk_import.cmake) @@ -148,18 +165,22 @@ add_compile_definitions(DRAG_N_DROP_SUPPORT=1) # # this is for SIGROK operation (taken from https://github.com/pico-coder/sigrok-pico) # -target_sources(${PROJECT} PRIVATE +if(OPT_SIGROK) + target_sources(${PROJECT} PRIVATE src/pico-sigrok/cdc_sigrok.c src/pico-sigrok/sigrok.c src/pico-sigrok/sigrok_int.c -) + ) -target_link_libraries(${PROJECT} PRIVATE + target_link_libraries(${PROJECT} PRIVATE hardware_adc hardware_dma -) + ) -pico_generate_pio_header(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}/src/pico-sigrok/sigrok.pio) + pico_generate_pio_header(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}/src/pico-sigrok/sigrok.pio) + + add_compile_definitions(OPT_SIGROK=1) +endif() #-------------------------------------------------------------------------------------------------- diff --git a/Makefile b/Makefile index bcdb7c82f..a60f7dc6b 100755 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ # VERSION_MAJOR := 1 -VERSION_MINOR := 14 +VERSION_MINOR := 15 BUILD_DIR := build PROJECT := picoprobe @@ -45,7 +45,7 @@ details: all .PHONY: cmake-create-debug cmake-create-debug: - cmake -B $(BUILD_DIR) -G Ninja -DCMAKE_BUILD_TYPE=Debug -DCMAKE_EXPORT_COMPILE_COMMANDS=1 -DPICO_BOARD=$(PICO_BOARD) $(CMAKE_FLAGS) + cmake -B $(BUILD_DIR) -G Ninja -DCMAKE_BUILD_TYPE=Debug -DCMAKE_EXPORT_COMPILE_COMMANDS=1 -DPICO_BOARD=$(PICO_BOARD) -DOPT_SIGROK=$(OPT_SIGROK) $(CMAKE_FLAGS) # don't know if this is required @cd $(BUILD_DIR) && sed -i 's/arm-none-eabi-gcc/gcc/' compile_commands.json @@ -73,16 +73,16 @@ flash: all .PHONY: create-images create-images: $(MAKE) clean-build - $(MAKE) cmake-create-debug PICO_BOARD=pico + $(MAKE) cmake-create-debug PICO_BOARD=pico OPT_SIGROK=1 $(MAKE) all mkdir -p images cp $(BUILD_DIR)/$(PROJECT).uf2 images/yapicoprobe-$(shell printf "%02d%02d" $(VERSION_MAJOR) $(VERSION_MINOR))-pico-$(GIT_HASH).uf2 # - $(MAKE) cmake-create-debug PICO_BOARD=pico_w + $(MAKE) cmake-create-debug PICO_BOARD=pico_w OPT_SIGROK=1 $(MAKE) all cp $(BUILD_DIR)/$(PROJECT).uf2 images/yapicoprobe-$(shell printf "%02d%02d" $(VERSION_MAJOR) $(VERSION_MINOR))-picow-$(GIT_HASH).uf2 # - $(MAKE) cmake-create-debug PICO_BOARD=pico_debug_probe + $(MAKE) cmake-create-debug PICO_BOARD=pico_debug_probe OPT_SIGROK=0 $(MAKE) all cp $(BUILD_DIR)/$(PROJECT).uf2 images/yapicoprobe-$(shell printf "%02d%02d" $(VERSION_MAJOR) $(VERSION_MINOR))-picodebugprobe-$(GIT_HASH).uf2 diff --git a/include/picoprobe_config.h b/include/picoprobe_config.h index 63d190bdf..886de2984 100644 --- a/include/picoprobe_config.h +++ b/include/picoprobe_config.h @@ -28,7 +28,6 @@ #define INCLUDE_RTT_CONSOLE -#define INCLUDE_SIGROK #if !defined(NDEBUG) diff --git a/include/tusb_config.h b/include/tusb_config.h index 2006e51aa..598c2dcd9 100644 --- a/include/tusb_config.h +++ b/include/tusb_config.h @@ -71,10 +71,10 @@ //********************************************** #define CFG_TUD_CDC_UART 1 // CDC for target UART IO -#if !defined(TARGET_BOARD_PICO_DEBUG_PROBE) +#if OPT_SIGROK #define CFG_TUD_CDC_SIGROK 1 // CDC for sigrok IO #else - #define CFG_TUD_CDC_SIGROK 0 // no sigrok for debug probe + #define CFG_TUD_CDC_SIGROK 0 #endif #if !defined(NDEBUG) #define CFG_TUD_CDC_DEBUG 1 // CDC for debug output of the probe @@ -90,7 +90,9 @@ // CDC numbering (must go 0.. consecutive) #define CDC_UART_N (CFG_TUD_CDC_UART - 1) -#define CDC_SIGROK_N (CFG_TUD_CDC_UART + CFG_TUD_CDC_SIGROK - 1) +#if OPT_SIGROK + #define CDC_SIGROK_N (CFG_TUD_CDC_UART + CFG_TUD_CDC_SIGROK - 1) +#endif #define CDC_DEBUG_N (CFG_TUD_CDC_UART + CFG_TUD_CDC_SIGROK + CFG_TUD_CDC_DEBUG - 1) //------------- BUFFER SIZES -------------// diff --git a/src/main.c b/src/main.c index eb4ff1547..d3813af9c 100644 --- a/src/main.c +++ b/src/main.c @@ -63,7 +63,7 @@ #if defined(INCLUDE_RTT_CONSOLE) #include "rtt_console.h" #endif -#if defined(INCLUDE_SIGROK) +#if OPT_SIGROK #include "pico-sigrok/cdc_sigrok.h" #include "pico-sigrok/sigrok.h" #endif @@ -124,7 +124,7 @@ void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts) cdc_debug_line_state_cb(dtr, rts); } #endif -#if CFG_TUD_CDC_SIGROK +#if OPT_SIGROK if (itf == CDC_SIGROK_N) { cdc_sigrok_line_state_cb(dtr, rts); } @@ -148,7 +148,7 @@ void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const* line_coding) void tud_cdc_rx_cb(uint8_t itf) { -#if CFG_TUD_CDC_SIGROK +#if OPT_SIGROK if (itf == CDC_SIGROK_N) { cdc_sigrok_rx_cb(); } @@ -164,7 +164,7 @@ void tud_cdc_rx_cb(uint8_t itf) void tud_cdc_tx_complete_cb(uint8_t itf) { -#if CFG_TUD_CDC_SIGROK +#if OPT_SIGROK if (itf == CDC_SIGROK_N) { cdc_sigrok_tx_complete_cb(); } @@ -462,7 +462,7 @@ void usb_thread(void *ptr) rtt_console_init(RTT_CONSOLE_TASK_PRIO); #endif -#if defined(INCLUDE_SIGROK) +#if OPT_SIGROK sigrok_init(SIGROK_TASK_PRIO); #endif @@ -516,7 +516,7 @@ int main(void) #if CFG_TUD_CDC_UART picoprobe_info_out(" [UART -> CDC]"); #endif -#if CFG_TUD_CDC_SIGROK +#if OPT_SIGROK picoprobe_info_out(" [sigrok CDC]"); #endif #if CFG_TUD_CDC_DEBUG diff --git a/src/pico-sigrok/cdc_sigrok.c b/src/pico-sigrok/cdc_sigrok.c index b0a253662..eac482e0d 100755 --- a/src/pico-sigrok/cdc_sigrok.c +++ b/src/pico-sigrok/cdc_sigrok.c @@ -71,12 +71,10 @@ void cdc_sigrok_line_state_cb(bool dtr, bool rts) * This seems to be necessary to survive e.g. a restart of the host (Linux) */ { -#if CFG_TUD_CDC_SIGROK tud_cdc_n_write_clear(CDC_SIGROK_N); tud_cdc_n_read_flush(CDC_SIGROK_N); m_connected = (dtr || rts);; xEventGroupSetBits(events, EV_STREAM); -#endif } // cdc_uart_line_state_cb @@ -114,7 +112,6 @@ void cdc_sigrok_write(const char *buf, int length) -#if CFG_TUD_CDC_SIGROK //Process incoming character stream //Return true if the device rspstr has a response to send to host //Be sure that rspstr does not have \n or \r. @@ -302,7 +299,6 @@ static bool process_char(sr_device_t *d, char charin) //default return 0 means to not send any kind of response return ret; } // process_char -#endif @@ -317,7 +313,6 @@ void cdc_sigrok_thread() { for (;;) { -#if CFG_TUD_CDC_SIGROK static uint8_t cdc_tx_buf[CFG_TUD_CDC_TX_BUFSIZE]; EventBits_t ev = EV_RX | EV_TX | EV_STREAM; size_t cdc_rx_chars; @@ -395,9 +390,6 @@ void cdc_sigrok_thread() } } tud_cdc_n_write_flush(CDC_SIGROK_N); -#else - xEventGroupWaitBits(events, EV_RX | EV_TX | EV_STREAM | EV_RX, pdTRUE, pdFALSE, pdMS_TO_TICKS(10000)); -#endif } } // cdc_sigrok_thread diff --git a/src/pico-sigrok/cdc_sigrok.h b/src/pico-sigrok/cdc_sigrok.h index 117dd0f58..217cef6c6 100755 --- a/src/pico-sigrok/cdc_sigrok.h +++ b/src/pico-sigrok/cdc_sigrok.h @@ -35,13 +35,15 @@ #endif -void cdc_sigrok_init(uint32_t task_prio); -void cdc_sigrok_write(const char *buf, int length); -void cdc_sigrok_rx_cb(void); -void cdc_sigrok_tx_complete_cb(void); -void cdc_sigrok_line_state_cb(bool dtr, bool rts); - -void core1_code(); +#if OPT_SIGROK + void cdc_sigrok_init(uint32_t task_prio); + void cdc_sigrok_write(const char *buf, int length); + void cdc_sigrok_rx_cb(void); + void cdc_sigrok_tx_complete_cb(void); + void cdc_sigrok_line_state_cb(bool dtr, bool rts); + + void core1_code(); +#endif #ifdef __cplusplus diff --git a/src/pico-sigrok/sigrok.h b/src/pico-sigrok/sigrok.h index c19d1a751..95e1f887c 100755 --- a/src/pico-sigrok/sigrok.h +++ b/src/pico-sigrok/sigrok.h @@ -36,7 +36,9 @@ #endif -void sigrok_init(uint32_t task_prio); +#if OPT_SIGROK + void sigrok_init(uint32_t task_prio); +#endif #ifdef __cplusplus diff --git a/src/usb_descriptors.c b/src/usb_descriptors.c index 111636da7..d8cb92f6d 100644 --- a/src/usb_descriptors.c +++ b/src/usb_descriptors.c @@ -74,7 +74,7 @@ enum ITF_NUM_CDC_COM, ITF_NUM_CDC_DATA, #endif -#if CFG_TUD_CDC_SIGROK +#if OPT_SIGROK ITF_NUM_CDC_SIGROK_COM, ITF_NUM_CDC_SIGROK_DATA, #endif @@ -106,7 +106,7 @@ enum CDC_DATA_OUT_EP_CNT, CDC_DATA_IN_EP_CNT, #endif -#if CFG_TUD_CDC_SIGROK +#if OPT_SIGROK CDC_SIGROK_NOTIFICATION_EP_CNT, CDC_SIGROK_DATA_OUT_EP_CNT, CDC_SIGROK_DATA_IN_EP_CNT, @@ -135,7 +135,7 @@ enum #define CDC_DATA_OUT_EP_NUM (CDC_DATA_OUT_EP_CNT + 0x00) #define CDC_DATA_IN_EP_NUM (CDC_DATA_IN_EP_CNT + 0x80) #endif -#if CFG_TUD_CDC_SIGROK +#if OPT_SIGROK #define CDC_SIGROK_NOTIFICATION_EP_NUM (CDC_SIGROK_NOTIFICATION_EP_CNT + 0x80) #define CDC_SIGROK_DATA_OUT_EP_NUM (CDC_SIGROK_DATA_OUT_EP_CNT + 0x00) #define CDC_SIGROK_DATA_IN_EP_NUM (CDC_SIGROK_DATA_IN_EP_CNT + 0x80) @@ -189,7 +189,7 @@ uint8_t const desc_configuration[] = TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_COM, 7, CDC_NOTIFICATION_EP_NUM, 64, CDC_DATA_OUT_EP_NUM, CDC_DATA_IN_EP_NUM, 64), #endif -#if CFG_TUD_CDC_SIGROK +#if OPT_SIGROK // Interface 4 + 5: CDC SIGROK TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_SIGROK_COM, 8, CDC_SIGROK_NOTIFICATION_EP_NUM, 64, CDC_SIGROK_DATA_OUT_EP_NUM, CDC_SIGROK_DATA_IN_EP_NUM, 64), #endif From 185292241f9c07747a073b21672df208c9172d1d Mon Sep 17 00:00:00 2001 From: Hardy Griech Date: Mon, 1 May 2023 11:18:00 +0200 Subject: [PATCH 002/118] USB string descriptors now with enum --- Makefile | 2 +- src/usb_descriptors.c | 56 +++++++++++++++++++++++++++++-------------- 2 files changed, 39 insertions(+), 19 deletions(-) diff --git a/Makefile b/Makefile index a60f7dc6b..7d2e6fd9c 100755 --- a/Makefile +++ b/Makefile @@ -45,7 +45,7 @@ details: all .PHONY: cmake-create-debug cmake-create-debug: - cmake -B $(BUILD_DIR) -G Ninja -DCMAKE_BUILD_TYPE=Debug -DCMAKE_EXPORT_COMPILE_COMMANDS=1 -DPICO_BOARD=$(PICO_BOARD) -DOPT_SIGROK=$(OPT_SIGROK) $(CMAKE_FLAGS) + cmake -B $(BUILD_DIR) -G Ninja -DCMAKE_BUILD_TYPE=Debug -DCMAKE_EXPORT_COMPILE_COMMANDS=1 -DPICO_BOARD=$(PICO_BOARD) $(if $(OPT_SIGROK),-DOPT_SIGROK=$(OPT_SIGROK)) $(CMAKE_FLAGS) # don't know if this is required @cd $(BUILD_DIR) && sed -i 's/arm-none-eabi-gcc/gcc/' compile_commands.json diff --git a/src/usb_descriptors.c b/src/usb_descriptors.c index d8cb92f6d..5f9ebb1dc 100644 --- a/src/usb_descriptors.c +++ b/src/usb_descriptors.c @@ -58,6 +58,26 @@ uint8_t const * tud_descriptor_device_cb(void) return (uint8_t const *) &desc_device; } + +//--------------------------------------------------------------------+ +// String enums +//--------------------------------------------------------------------+ + +enum +{ + STRID_LANGID = 0, + STRID_MANUFACTURER, + STRID_PRODUCT, + STRID_SERIAL, + STRID_INTERFACE_DAP2, + STRID_INTERFACE_DAP1, + STRID_INTERFACE_MSC, + STRID_INTERFACE_CDC_UART, + STRID_INTERFACE_CDC_SIGROK, + STRID_INTERFACE_CDC_DEBUG, +}; + + //--------------------------------------------------------------------+ // Configuration Descriptor //--------------------------------------------------------------------+ @@ -170,38 +190,38 @@ uint8_t const * tud_hid_descriptor_report_cb(uint8_t itf) // // note that there is a 64byte packet limit for full speed! // -uint8_t const desc_configuration[] = +static uint8_t const desc_configuration[] = { TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 500), #if CFG_TUD_VENDOR // Interface 0: Bulk (named interface), CMSIS-DAPv2 - TUD_VENDOR_DESCRIPTOR(ITF_NUM_PROBE_VENDOR, 4, PROBE_VENDOR_OUT_EP_NUM, PROBE_VENDOR_IN_EP_NUM, 64), + TUD_VENDOR_DESCRIPTOR(ITF_NUM_PROBE_VENDOR, STRID_INTERFACE_DAP2, PROBE_VENDOR_OUT_EP_NUM, PROBE_VENDOR_IN_EP_NUM, 64), #endif #if CFG_TUD_HID // Interface 1: HID (named interface), CMSIS-DAP v1 - TUD_HID_INOUT_DESCRIPTOR(ITF_NUM_PROBE_HID, 5, HID_ITF_PROTOCOL_NONE, sizeof(desc_hid_report), PROBE_HID_OUT_EP_NUM, PROBE_HID_IN_EP_NUM, CFG_TUD_HID_EP_BUFSIZE, 1), + TUD_HID_INOUT_DESCRIPTOR(ITF_NUM_PROBE_HID, STRID_INTERFACE_DAP1, HID_ITF_PROTOCOL_NONE, sizeof(desc_hid_report), PROBE_HID_OUT_EP_NUM, PROBE_HID_IN_EP_NUM, CFG_TUD_HID_EP_BUFSIZE, 1), #endif #if CFG_TUD_CDC_UART // Interface 2 + 3: CDC UART (target) - TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_COM, 7, CDC_NOTIFICATION_EP_NUM, 64, CDC_DATA_OUT_EP_NUM, CDC_DATA_IN_EP_NUM, 64), + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_COM, STRID_INTERFACE_CDC_UART, CDC_NOTIFICATION_EP_NUM, 64, CDC_DATA_OUT_EP_NUM, CDC_DATA_IN_EP_NUM, 64), #endif #if OPT_SIGROK // Interface 4 + 5: CDC SIGROK - TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_SIGROK_COM, 8, CDC_SIGROK_NOTIFICATION_EP_NUM, 64, CDC_SIGROK_DATA_OUT_EP_NUM, CDC_SIGROK_DATA_IN_EP_NUM, 64), + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_SIGROK_COM, STRID_INTERFACE_CDC_SIGROK, CDC_SIGROK_NOTIFICATION_EP_NUM, 64, CDC_SIGROK_DATA_OUT_EP_NUM, CDC_SIGROK_DATA_IN_EP_NUM, 64), #endif // Interface 6: MSC #if CFG_TUD_MSC - TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 6, MSC_OUT_EP_NUM, MSC_IN_EP_NUM, 64), + TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, STRID_INTERFACE_MSC, MSC_OUT_EP_NUM, MSC_IN_EP_NUM, 64), #endif #if CFG_TUD_CDC_DEBUG // Interface 7 + 8: CDC DEBUG (internal) - TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_DEBUG_COM, 9, CDC_DEBUG_NOTIFICATION_EP_NUM, 64, CDC_DEBUG_DATA_OUT_EP_NUM, CDC_DEBUG_DATA_IN_EP_NUM, 64), + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_DEBUG_COM, STRID_INTERFACE_CDC_DEBUG, CDC_DEBUG_NOTIFICATION_EP_NUM, 64, CDC_DEBUG_DATA_OUT_EP_NUM, CDC_DEBUG_DATA_IN_EP_NUM, 64), #endif }; @@ -219,18 +239,18 @@ uint8_t const * tud_descriptor_configuration_cb(uint8_t index) //--------------------------------------------------------------------+ // array of pointer to string descriptors -char const* string_desc_arr [] = +static char const* string_desc_arr[] = { - (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409) - "RaspberryPi", // 1: Manufacturer - "YAPicoprobe CMSIS-DAP", // 2: Product, **MUST** contain "CMSIS-DAP" to enable "CMSIS-DAP v1" - usb_serial, // 3: Serial, uses flash unique ID - "YAPicoprobe CMSIS-DAP v2", // 4: Interface descriptor for Bulk transport, **MUST** contain "CMSIS-DAP" to enable "CMSIS-DAP v2" - "YAPicoprobe CMSIS-DAP v1", // 5: Interface descriptor for HID transport - "YAPicoprobe Flash Drive", // 6: Interface descriptor for MSC interface - "YAPicoprobe CDC-UART", // 7: Interface descriptor for CDC UART (from target) - "YAPicoprobe CDC-SIGROK", // 8: Interface descriptor for CDC SIGROK - "YAPicoprobe CDC-DEBUG", // 9: Interface descriptor for CDC DEBUG + [STRID_LANGID] = (const char[]) { 0x09, 0x04 }, // is supported language is English (0x0409) + [STRID_MANUFACTURER] = "RaspberryPi", // Manufacturer + [STRID_PRODUCT] = "YAPicoprobe CMSIS-DAP", // Product, **MUST** contain "CMSIS-DAP" to enable "CMSIS-DAP v1" + [STRID_SERIAL] = usb_serial, // Serial, uses flash unique ID + [STRID_INTERFACE_DAP2] = "YAPicoprobe CMSIS-DAP v2", // Interface descriptor for Bulk transport, **MUST** contain "CMSIS-DAP" to enable "CMSIS-DAP v2" + [STRID_INTERFACE_DAP1] = "YAPicoprobe CMSIS-DAP v1", // Interface descriptor for HID transport + [STRID_INTERFACE_MSC] = "YAPicoprobe Flash Drive", // Interface descriptor for MSC interface + [STRID_INTERFACE_CDC_UART] = "YAPicoprobe CDC-UART", // Interface descriptor for CDC UART (from target) + [STRID_INTERFACE_CDC_SIGROK] = "YAPicoprobe CDC-SIGROK", // Interface descriptor for CDC SIGROK + [STRID_INTERFACE_CDC_DEBUG] = "YAPicoprobe CDC-DEBUG", // Interface descriptor for CDC DEBUG }; static uint16_t _desc_str[32]; From cc4f27bda835f5b2c5b1dd07aa855e575d8005d1 Mon Sep 17 00:00:00 2001 From: Hardy Griech Date: Mon, 1 May 2023 13:45:35 +0200 Subject: [PATCH 003/118] USB descriptors for RNDIS, some cb functions are missing, will switch soon to NCM --- CMakeLists.txt | 21 ++++++- include/arch/cc.h | 75 +++++++++++++++++++++++ include/tusb_config.h | 5 +- src/usb_descriptors.c | 135 ++++++++++++++++++++++++++++++------------ 4 files changed, 196 insertions(+), 40 deletions(-) create mode 100755 include/arch/cc.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 217bf0fcb..f644f38ca 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,6 +6,7 @@ # - PICOPROBE_VERSION_MAJOR major version number # - PICOPROBE_VERSION_MINOR minor version number # - OPT_SIGROK enable/disable sigrok module, default "1" +# - OPT_SYSVIEW_RNDIS enable/disable sysview via RNDIS, default "0" # # - GIT_HASH short git hash # - PROJECT project name for cmake @@ -18,7 +19,8 @@ cmake_minimum_required(VERSION 3.12) if(PICO_BOARD STREQUAL "") set(PICO_BOARD pico) endif() -option(OPT_SIGROK "Enable sigrok" 1) +option(OPT_SIGROK "Enable sigrok" 0) +option(OPT_SYSVIEW_RNDIS "Enable SysView over RNDIS" 1) # # SDK options @@ -182,6 +184,23 @@ if(OPT_SIGROK) add_compile_definitions(OPT_SIGROK=1) endif() +#-------------------------------------------------------------------------------------------------- +# +# this is for SystemView operation (requires RTT) +# +if(OPT_SYSVIEW_RNDIS) + add_compile_definitions(OPT_SYSVIEW_RNDIS=1) + + target_include_directories(${PROJECT} PRIVATE + ${PICO_TINYUSB_PATH}/lib/networking + ${PICO_TINYUSB_PATH}/lib/lwip/src/include + ) + + target_sources(${PROJECT} PRIVATE + ${PICO_TINYUSB_PATH}/lib/networking/rndis_reports.c + ) +endif() + #-------------------------------------------------------------------------------------------------- target_compile_options(${PROJECT} PRIVATE -Wall) diff --git a/include/arch/cc.h b/include/arch/cc.h new file mode 100755 index 000000000..9f30b91cb --- /dev/null +++ b/include/arch/cc.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __CC_H__ +#define __CC_H__ + +//#include "cpu.h" + +typedef int sys_prot_t; + + + +/* define compiler specific symbols */ +#if defined (__ICCARM__) + +#define PACK_STRUCT_BEGIN +#define PACK_STRUCT_STRUCT +#define PACK_STRUCT_END +#define PACK_STRUCT_FIELD(x) x +#define PACK_STRUCT_USE_INCLUDES + +#elif defined (__CC_ARM) + +#define PACK_STRUCT_BEGIN __packed +#define PACK_STRUCT_STRUCT +#define PACK_STRUCT_END +#define PACK_STRUCT_FIELD(x) x + +#elif defined (__GNUC__) + +#define PACK_STRUCT_BEGIN +#define PACK_STRUCT_STRUCT __attribute__ ((__packed__)) +#define PACK_STRUCT_END +#define PACK_STRUCT_FIELD(x) x + +#elif defined (__TASKING__) + +#define PACK_STRUCT_BEGIN +#define PACK_STRUCT_STRUCT +#define PACK_STRUCT_END +#define PACK_STRUCT_FIELD(x) x + +#endif + +#define LWIP_PLATFORM_ASSERT(x) do { if(!(x)) while(1); } while(0) + +#endif /* __CC_H__ */ diff --git a/include/tusb_config.h b/include/tusb_config.h index 598c2dcd9..0935aa36e 100644 --- a/include/tusb_config.h +++ b/include/tusb_config.h @@ -86,7 +86,10 @@ #define CFG_TUD_VENDOR 1 // CMSIS-DAPv2 #define CFG_TUD_MSC 1 // DAPLink drive #define CFG_TUD_CDC (CFG_TUD_CDC_UART + CFG_TUD_CDC_SIGROK + CFG_TUD_CDC_DEBUG) - +#if OPT_SYSVIEW_RNDIS + #define CFG_TUD_ECM_RNDIS 1 + #define CFG_TUD_NCM 0 +#endif // CDC numbering (must go 0.. consecutive) #define CDC_UART_N (CFG_TUD_CDC_UART - 1) diff --git a/src/usb_descriptors.c b/src/usb_descriptors.c index 5f9ebb1dc..5afda437c 100644 --- a/src/usb_descriptors.c +++ b/src/usb_descriptors.c @@ -26,12 +26,45 @@ */ #include "tusb.h" +#include "pico/unique_id.h" #include "get_serial.h" #include "picoprobe_config.h" + +#if OPT_SYSVIEW_RNDIS + uint8_t tud_network_mac_address[6] = {0}; +#endif + + +//--------------------------------------------------------------------+ +// String enums +//--------------------------------------------------------------------+ + +enum +{ + STRID_LANGID = 0, + STRID_MANUFACTURER, + STRID_PRODUCT, + STRID_SERIAL, + STRID_INTERFACE_DAP2, + STRID_INTERFACE_DAP1, + STRID_INTERFACE_MSC, + STRID_INTERFACE_CDC_UART, +#if OPT_SIGROK + STRID_INTERFACE_CDC_SIGROK, +#endif + STRID_INTERFACE_CDC_DEBUG, +#if OPT_SYSVIEW_RNDIS + STRID_INTERFACE_RNDIS, + STRID_MAC, +#endif +}; + + //--------------------------------------------------------------------+ // Device Descriptors //--------------------------------------------------------------------+ + tusb_desc_device_t const desc_device = { .bLength = sizeof(tusb_desc_device_t), @@ -45,39 +78,25 @@ tusb_desc_device_t const desc_device = .idVendor = 0x2E8A, // Pi .idProduct = 0x000c, // CMSIS-DAP adapter .bcdDevice = (PICOPROBE_VERSION_MAJOR << 8) + (16*(PICOPROBE_VERSION_MINOR / 10)) + PICOPROBE_VERSION_MINOR % 10, - .iManufacturer = 0x01, - .iProduct = 0x02, - .iSerialNumber = 0x03, - .bNumConfigurations = 0x01 + .iManufacturer = STRID_MANUFACTURER, + .iProduct = STRID_PRODUCT, + .iSerialNumber = STRID_SERIAL, + .bNumConfigurations = 1 }; // Invoked when received GET DEVICE DESCRIPTOR // Application return pointer to descriptor uint8_t const * tud_descriptor_device_cb(void) { +#if OPT_SYSVIEW_RNDIS + pico_unique_board_id_t id; + pico_get_unique_board_id( &id); + memcpy(tud_network_mac_address, &id, sizeof(tud_network_mac_address)); +#endif return (uint8_t const *) &desc_device; } -//--------------------------------------------------------------------+ -// String enums -//--------------------------------------------------------------------+ - -enum -{ - STRID_LANGID = 0, - STRID_MANUFACTURER, - STRID_PRODUCT, - STRID_SERIAL, - STRID_INTERFACE_DAP2, - STRID_INTERFACE_DAP1, - STRID_INTERFACE_MSC, - STRID_INTERFACE_CDC_UART, - STRID_INTERFACE_CDC_SIGROK, - STRID_INTERFACE_CDC_DEBUG, -}; - - //--------------------------------------------------------------------+ // Configuration Descriptor //--------------------------------------------------------------------+ @@ -104,6 +123,10 @@ enum #if CFG_TUD_CDC_DEBUG ITF_NUM_CDC_DEBUG_COM, ITF_NUM_CDC_DEBUG_DATA, +#endif +#if OPT_SYSVIEW_RNDIS + ITF_NUM_RNDIS, + ITF_NUM_RNDIS_ECM, #endif ITF_NUM_TOTAL }; @@ -140,6 +163,11 @@ enum CDC_DEBUG_DATA_OUT_EP_CNT, CDC_DEBUG_DATA_IN_EP_CNT, #endif +#if OPT_SYSVIEW_RNDIS + RNDIS_NOTIFICATION_EP_CNT, + RNDIS_DATA_OUT_EP_CNT, + RNDIS_DATA_IN_EP_CNT, +#endif }; #if CFG_TUD_VENDOR @@ -169,21 +197,28 @@ enum #define CDC_DEBUG_DATA_OUT_EP_NUM (CDC_DEBUG_DATA_OUT_EP_CNT + 0x00) #define CDC_DEBUG_DATA_IN_EP_NUM (CDC_DEBUG_DATA_IN_EP_CNT + 0x80) #endif +#if OPT_SYSVIEW_RNDIS + #define RNDIS_NOTIFICATION_EP_NUM (RNDIS_NOTIFICATION_EP_CNT + 0x80) + #define RNDIS_DATA_OUT_EP_NUM (RNDIS_DATA_OUT_EP_CNT + 0x00) + #define RNDIS_DATA_IN_EP_NUM (RNDIS_DATA_IN_EP_CNT + 0x80) +#endif -#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + CFG_TUD_CDC*TUD_CDC_DESC_LEN + CFG_TUD_VENDOR*TUD_VENDOR_DESC_LEN + CFG_TUD_HID*TUD_HID_INOUT_DESC_LEN + CFG_TUD_MSC*TUD_MSC_DESC_LEN) +#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + CFG_TUD_CDC*TUD_CDC_DESC_LEN + CFG_TUD_VENDOR*TUD_VENDOR_DESC_LEN \ + + CFG_TUD_HID*TUD_HID_INOUT_DESC_LEN + CFG_TUD_MSC*TUD_MSC_DESC_LEN \ + + CFG_TUD_ECM_RNDIS*TUD_RNDIS_DESC_LEN) #if CFG_TUD_HID -static uint8_t const desc_hid_report[] = -{ - TUD_HID_REPORT_DESC_GENERIC_INOUT(CFG_TUD_HID_EP_BUFSIZE) -}; - -uint8_t const * tud_hid_descriptor_report_cb(uint8_t itf) -{ - (void)itf; - return desc_hid_report; -} + static uint8_t const desc_hid_report[] = + { + TUD_HID_REPORT_DESC_GENERIC_INOUT(CFG_TUD_HID_EP_BUFSIZE) + }; + + uint8_t const * tud_hid_descriptor_report_cb(uint8_t itf) + { + (void)itf; + return desc_hid_report; + } #endif @@ -192,7 +227,9 @@ uint8_t const * tud_hid_descriptor_report_cb(uint8_t itf) // static uint8_t const desc_configuration[] = { - TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 500), + // Config number, interface count, string index, total length, attribute, power in mA + //TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 500), + TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0, 200), #if CFG_TUD_VENDOR // Interface 0: Bulk (named interface), CMSIS-DAPv2 @@ -223,6 +260,12 @@ static uint8_t const desc_configuration[] = // Interface 7 + 8: CDC DEBUG (internal) TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_DEBUG_COM, STRID_INTERFACE_CDC_DEBUG, CDC_DEBUG_NOTIFICATION_EP_NUM, 64, CDC_DEBUG_DATA_OUT_EP_NUM, CDC_DEBUG_DATA_IN_EP_NUM, 64), #endif + +#if OPT_SYSVIEW_RNDIS + // Interface 9 + 10: RNDIS for SysView + TUD_RNDIS_DESCRIPTOR(ITF_NUM_RNDIS, STRID_INTERFACE_RNDIS, RNDIS_NOTIFICATION_EP_NUM, 64, RNDIS_DATA_OUT_EP_NUM, RNDIS_DATA_IN_EP_NUM, 64), + TUD_CDC_ECM_DESCRIPTOR(ITF_NUM_RNDIS, STRID_INTERFACE_RNDIS, STRID_MAC, RNDIS_NOTIFICATION_EP_NUM, 64, RNDIS_DATA_OUT_EP_NUM, RNDIS_DATA_IN_EP_NUM, 64, 1500) +#endif }; // Invoked when received GET CONFIGURATION DESCRIPTOR @@ -249,8 +292,14 @@ static char const* string_desc_arr[] = [STRID_INTERFACE_DAP1] = "YAPicoprobe CMSIS-DAP v1", // Interface descriptor for HID transport [STRID_INTERFACE_MSC] = "YAPicoprobe Flash Drive", // Interface descriptor for MSC interface [STRID_INTERFACE_CDC_UART] = "YAPicoprobe CDC-UART", // Interface descriptor for CDC UART (from target) +#if OPT_SIGROK [STRID_INTERFACE_CDC_SIGROK] = "YAPicoprobe CDC-SIGROK", // Interface descriptor for CDC SIGROK +#endif [STRID_INTERFACE_CDC_DEBUG] = "YAPicoprobe CDC-DEBUG", // Interface descriptor for CDC DEBUG +#if OPT_SYSVIEW_RNDIS + [STRID_INTERFACE_RNDIS] = "YaPicoprobe RNDIS SysView", // Interface descriptor for SysView RNDIS + [STRID_MAC] = "", +#endif }; static uint16_t _desc_str[32]; @@ -261,12 +310,22 @@ uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid) { (void)langid; - uint8_t chr_count; + uint8_t chr_count = 0; - if (index == 0) { - memcpy(&_desc_str[1], string_desc_arr[0], 2); + if (index == STRID_LANGID) { + memcpy( &_desc_str[1], string_desc_arr[0], 2); chr_count = 1; } + else if (index == STRID_MAC) { + // take first 6 bytes of serial number + memcpy( &_desc_str[1], usb_serial, 12); + chr_count = 12; + // Convert MAC address into UTF-16 + for (unsigned i = 0; i < sizeof(tud_network_mac_address); ++i) { + _desc_str[1+chr_count++] = "0123456789ABCDEF"[(tud_network_mac_address[i] >> 4) & 0xf]; + _desc_str[1+chr_count++] = "0123456789ABCDEF"[(tud_network_mac_address[i] >> 0) & 0xf]; + } + } else { // Convert ASCII string into UTF-16 From 2ac80d8a3b2f7e9b40e102a72744aab6341718fb Mon Sep 17 00:00:00 2001 From: Hardy Griech Date: Mon, 1 May 2023 16:18:23 +0200 Subject: [PATCH 004/118] compiles but does not connect RNDIS interface --- CMakeLists.txt | 18 +++- include/arch/cc.h | 2 +- include/arch/sys_arch.h | 95 ++++++++++++++++ include/lwipopts.h | 155 +++++++++++---------------- include/tusb_config.h | 3 + src/rtt_console.c | 232 ++++++++++++++++++++++++++++++++++++++-- src/usb_descriptors.c | 50 ++++++--- 7 files changed, 435 insertions(+), 120 deletions(-) create mode 100755 include/arch/sys_arch.h diff --git a/CMakeLists.txt b/CMakeLists.txt index f644f38ca..20669edef 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -191,14 +191,30 @@ endif() if(OPT_SYSVIEW_RNDIS) add_compile_definitions(OPT_SYSVIEW_RNDIS=1) + target_link_libraries(${PROJECT} PRIVATE + pico_lwip_freertos + ) + target_include_directories(${PROJECT} PRIVATE ${PICO_TINYUSB_PATH}/lib/networking - ${PICO_TINYUSB_PATH}/lib/lwip/src/include + #${PICO_LWIP_PATH}/contrib/ports/freertos/include + #${PICO_TINYUSB_PATH}/lib/lwip/src/include + #${PICO_LWIP_PATH}/test/unit +# ${PICO_LWIP_PATH}/lib/lwip/src/include +# ${PICO_LWIP_PATH}/lib/lwip/src/include/ipv4 +# ${PICO_LWIP_PATH}/lib/lwip/src/include/lwip/apps + ) target_sources(${PROJECT} PRIVATE + ${PICO_TINYUSB_PATH}/lib/networking/dhserver.c + ${PICO_TINYUSB_PATH}/lib/networking/dnserver.c ${PICO_TINYUSB_PATH}/lib/networking/rndis_reports.c ) + +# message("--------- " ${PICO_LWIP_PATH}) +# message("--------- " ${PICO_LWIP_CONTRIB_PATH}) +# message("--------- " ${PICO_TINYUSB_PATH}) endif() #-------------------------------------------------------------------------------------------------- diff --git a/include/arch/cc.h b/include/arch/cc.h index 9f30b91cb..c7927fdb4 100755 --- a/include/arch/cc.h +++ b/include/arch/cc.h @@ -34,7 +34,7 @@ //#include "cpu.h" -typedef int sys_prot_t; +//typedef int sys_prot_t; diff --git a/include/arch/sys_arch.h b/include/arch/sys_arch.h new file mode 100755 index 000000000..0cfc889de --- /dev/null +++ b/include/arch/sys_arch.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2017 Simon Goldschmidt + * All rights reserved. + * + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Simon Goldschmdit + * + */ +#ifndef LWIP_ARCH_SYS_ARCH_H +#define LWIP_ARCH_SYS_ARCH_H + +#include "lwip/opt.h" +#include "lwip/arch.h" + +/** This is returned by _fromisr() sys functions to tell the outermost function + * that a higher priority task was woken and the scheduler needs to be invoked. + */ +#define ERR_NEED_SCHED 123 + +/* This port includes FreeRTOS headers in sys_arch.c only. + * FreeRTOS uses pointers as object types. We use wrapper structs instead of + * void pointers directly to get a tiny bit of type safety. + */ + +void sys_arch_msleep(u32_t delay_ms); +#define sys_msleep(ms) sys_arch_msleep(ms) + +#if SYS_LIGHTWEIGHT_PROT +typedef u32_t sys_prot_t; +#endif /* SYS_LIGHTWEIGHT_PROT */ + +#if !LWIP_COMPAT_MUTEX +struct _sys_mut { + void *mut; +}; +typedef struct _sys_mut sys_mutex_t; +#define sys_mutex_valid_val(mutex) ((mutex).mut != NULL) +#define sys_mutex_valid(mutex) (((mutex) != NULL) && sys_mutex_valid_val(*(mutex))) +#define sys_mutex_set_invalid(mutex) ((mutex)->mut = NULL) +#endif /* !LWIP_COMPAT_MUTEX */ + +struct _sys_sem { + void *sem; +}; +typedef struct _sys_sem sys_sem_t; +#define sys_sem_valid_val(sema) ((sema).sem != NULL) +#define sys_sem_valid(sema) (((sema) != NULL) && sys_sem_valid_val(*(sema))) +#define sys_sem_set_invalid(sema) ((sema)->sem = NULL) + +struct _sys_mbox { + void *mbx; +}; +typedef struct _sys_mbox sys_mbox_t; +#define sys_mbox_valid_val(mbox) ((mbox).mbx != NULL) +#define sys_mbox_valid(mbox) (((mbox) != NULL) && sys_mbox_valid_val(*(mbox))) +#define sys_mbox_set_invalid(mbox) ((mbox)->mbx = NULL) + +struct _sys_thread { + void *thread_handle; +}; +typedef struct _sys_thread sys_thread_t; + +#if LWIP_NETCONN_SEM_PER_THREAD +sys_sem_t* sys_arch_netconn_sem_get(void); +void sys_arch_netconn_sem_alloc(void); +void sys_arch_netconn_sem_free(void); +#define LWIP_NETCONN_THREAD_SEM_GET() sys_arch_netconn_sem_get() +#define LWIP_NETCONN_THREAD_SEM_ALLOC() sys_arch_netconn_sem_alloc() +#define LWIP_NETCONN_THREAD_SEM_FREE() sys_arch_netconn_sem_free() +#endif /* LWIP_NETCONN_SEM_PER_THREAD */ + +#endif /* LWIP_ARCH_SYS_ARCH_H */ diff --git a/include/lwipopts.h b/include/lwipopts.h index 850eda84b..f233d6800 100755 --- a/include/lwipopts.h +++ b/include/lwipopts.h @@ -1,104 +1,73 @@ -#ifndef _LWIPOPTS_EXAMPLE_COMMONH_H -#define _LWIPOPTS_EXAMPLE_COMMONH_H +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Simon Goldschmidt + * + */ +#ifndef __LWIPOPTS_H__ +#define __LWIPOPTS_H__ -// Common settings used in most of the pico_w examples -// (see https://www.nongnu.org/lwip/2_1_x/group__lwip__opts.html for details) +/* Prevent having to link sys_arch.c (we don't test the API layers in unit tests) */ +#define NO_SYS 0 +#define MEM_ALIGNMENT 4 +#define LWIP_RAW 0 +#define LWIP_NETCONN 0 +#define LWIP_SOCKET 0 +#define LWIP_DHCP 0 +#define LWIP_ICMP 1 +#define LWIP_UDP 1 +#define LWIP_TCP 1 +#define LWIP_IPV4 1 +#define LWIP_IPV6 0 +#define ETH_PAD_SIZE 0 +#define LWIP_IP_ACCEPT_UDP_PORT(p) ((p) == PP_NTOHS(67)) -// allow override in some examples -#ifndef NO_SYS - #define NO_SYS 0 -#endif +#define TCP_MSS (1500 /*mtu*/ - 20 /*iphdr*/ - 20 /*tcphhr*/) +#define TCP_SND_BUF (2 * TCP_MSS) +#define TCP_WND (TCP_MSS) -// allow override in some examples -#ifndef LWIP_SOCKET - #define LWIP_SOCKET 0 -#endif +#define ETHARP_SUPPORT_STATIC_ENTRIES 1 -#if PICO_CYW43_ARCH_POLL - #define MEM_LIBC_MALLOC 1 -#else - // MEM_LIBC_MALLOC is incompatible with non polling versions - #define MEM_LIBC_MALLOC 0 -#endif +#define LWIP_HTTPD_CGI 0 +#define LWIP_HTTPD_SSI 0 +#define LWIP_HTTPD_SSI_INCLUDE_TAG 0 -#define MEM_ALIGNMENT 4 -#define MEM_SIZE 4000 -#define MEMP_NUM_TCP_SEG 32 -#define MEMP_NUM_ARP_QUEUE 10 -#define PBUF_POOL_SIZE 24 -#define LWIP_ARP 1 -#define LWIP_ETHERNET 1 -#define LWIP_ICMP 1 -#define LWIP_RAW 1 -#define TCP_WND (8 * TCP_MSS) -#define TCP_MSS 1460 -#define TCP_SND_BUF (8 * TCP_MSS) -#define TCP_SND_QUEUELEN ((4 * (TCP_SND_BUF) + (TCP_MSS - 1)) / (TCP_MSS)) -#define LWIP_NETIF_STATUS_CALLBACK 1 -#define LWIP_NETIF_LINK_CALLBACK 1 -#define LWIP_NETIF_HOSTNAME 1 -#define LWIP_NETCONN 0 -#define MEM_STATS 0 -#define SYS_STATS 0 -#define MEMP_STATS 0 -#define LINK_STATS 0 -// #define ETH_PAD_SIZE 2 -#define LWIP_CHKSUM_ALGORITHM 3 -#define LWIP_DHCP 1 -#define LWIP_IPV4 1 -#define LWIP_TCP 1 -#define LWIP_UDP 1 -#define LWIP_DNS 1 -#define LWIP_TCP_KEEPALIVE 1 -#define LWIP_NETIF_TX_SINGLE_PBUF 1 -#define DHCP_DOES_ARP_CHECK 0 -#define LWIP_DHCP_DOES_ACD_CHECK 0 +#define LWIP_SINGLE_NETIF 1 -#ifndef NDEBUG - #define LWIP_DEBUG 1 - #define LWIP_STATS 1 - #define LWIP_STATS_DISPLAY 1 -#endif +#define PBUF_POOL_SIZE 2 -#define ETHARP_DEBUG LWIP_DBG_OFF -#define NETIF_DEBUG LWIP_DBG_OFF -#define PBUF_DEBUG LWIP_DBG_OFF -#define API_LIB_DEBUG LWIP_DBG_OFF -#define API_MSG_DEBUG LWIP_DBG_OFF -#define SOCKETS_DEBUG LWIP_DBG_OFF -#define ICMP_DEBUG LWIP_DBG_OFF -#define INET_DEBUG LWIP_DBG_OFF -#define IP_DEBUG LWIP_DBG_OFF -#define IP_REASS_DEBUG LWIP_DBG_OFF -#define RAW_DEBUG LWIP_DBG_OFF -#define MEM_DEBUG LWIP_DBG_OFF -#define MEMP_DEBUG LWIP_DBG_OFF -#define SYS_DEBUG LWIP_DBG_OFF -#define TCP_DEBUG LWIP_DBG_OFF -#define TCP_INPUT_DEBUG LWIP_DBG_OFF -#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF -#define TCP_RTO_DEBUG LWIP_DBG_OFF -#define TCP_CWND_DEBUG LWIP_DBG_OFF -#define TCP_WND_DEBUG LWIP_DBG_OFF -#define TCP_FR_DEBUG LWIP_DBG_OFF -#define TCP_QLEN_DEBUG LWIP_DBG_OFF -#define TCP_RST_DEBUG LWIP_DBG_OFF -#define UDP_DEBUG LWIP_DBG_OFF -#define TCPIP_DEBUG LWIP_DBG_OFF -#define PPP_DEBUG LWIP_DBG_OFF -#define SLIP_DEBUG LWIP_DBG_OFF -#define DHCP_DEBUG LWIP_DBG_OFF +#define HTTPD_USE_CUSTOM_FSDATA 0 +#define LWIP_MULTICAST_PING 1 +#define LWIP_BROADCAST_PING 1 +#define LWIP_IPV6_MLD 0 +#define LWIP_IPV6_SEND_ROUTER_SOLICIT 0 -#if !NO_SYS - #define TCPIP_THREAD_STACKSIZE 1024 - #define DEFAULT_THREAD_STACKSIZE 1024 - #define DEFAULT_RAW_RECVMBOX_SIZE 8 - #define TCPIP_MBOX_SIZE 8 - #define LWIP_TIMEVAL_PRIVATE 0 - - // not necessary, can be done either way - #define LWIP_TCPIP_CORE_LOCKING_INPUT 1 -#endif +#define LWIP_PROVIDE_ERRNO 1 #endif /* __LWIPOPTS_H__ */ diff --git a/include/tusb_config.h b/include/tusb_config.h index 0935aa36e..85f50f4c1 100644 --- a/include/tusb_config.h +++ b/include/tusb_config.h @@ -110,6 +110,9 @@ // note: this is optimized for DAPLink write speed #define CFG_TUD_MSC_EP_BUFSIZE 512 +#if OPT_SYSVIEW_RNDIS + #define CFG_TUD_NET_MTU 800 +#endif #ifdef __cplusplus } diff --git a/src/rtt_console.c b/src/rtt_console.c index 27e343871..e06c119b2 100755 --- a/src/rtt_console.c +++ b/src/rtt_console.c @@ -51,6 +51,9 @@ #define STREAM_RTT_SIZE 128 #define STREAM_RTT_TRIGGER 1 +#define RTT_CHANNEL_CONSOLE 1 +#define RTT_POLL_INT_MS 1 + #define EV_RTT_TO_TARGET 0x01 static const uint32_t segger_alignment = 4; @@ -59,11 +62,44 @@ static uint32_t prev_rtt_cb = 0; static bool rtt_console_running = false; static TaskHandle_t task_rtt_console = NULL; -static StreamBufferHandle_t stream_rtt; +static StreamBufferHandle_t stream_rtt; // small stream for host->probe->target communication static EventGroupHandle_t events; +#if OPT_SYSVIEW_RNDIS + +#include "lwip/init.h" +#include "lwip/ip.h" +#include "lwip/etharp.h" +#include "lwip/timeouts.h" +#include "dhserver.h" +#include "dnserver.h" + + +/* lwip context */ +static struct netif netif_data; + +/* shared between tud_network_recv_cb() and service_traffic() */ +static struct pbuf *received_frame; + + +static void service_traffic(void) +{ + /* handle any packet received by tud_network_recv_cb() */ + if (received_frame) { + ethernet_input(received_frame, &netif_data); + pbuf_free(received_frame); + received_frame = NULL; + tud_network_recv_renew(); + } + sys_check_timeouts(); +} // service_traffic + +#endif + + + static uint32_t check_buffer_for_rtt_cb(uint8_t *buf, uint32_t buf_size, uint32_t base_addr) { uint32_t rtt_cb = 0; @@ -135,7 +171,7 @@ static void do_rtt_console(uint32_t rtt_cb) { SEGGER_RTT_BUFFER_UP aUp; // Up buffer, transferring information up from target via debug probe to host SEGGER_RTT_BUFFER_DOWN aDown; // Down buffer, transferring information from host via debug probe to target - uint8_t buf[128]; + uint8_t buf[256]; bool ok = true; static_assert(sizeof(uint32_t) == sizeof(unsigned int)); // why doesn't segger use uint32_t? @@ -144,19 +180,21 @@ static void do_rtt_console(uint32_t rtt_cb) return; } - ok = ok && swd_read_memory(rtt_cb + offsetof(SEGGER_RTT_CB, aUp), + ok = ok && swd_read_memory(rtt_cb + offsetof(SEGGER_RTT_CB, aUp[RTT_CHANNEL_CONSOLE]), (uint8_t *)&aUp, sizeof(aUp)); - ok = ok && swd_read_memory(rtt_cb + offsetof(SEGGER_RTT_CB, aDown), + ok = ok && swd_read_memory(rtt_cb + offsetof(SEGGER_RTT_CB, aDown[RTT_CHANNEL_CONSOLE]), (uint8_t *)&aDown, sizeof(aDown)); // do operations rtt_console_running = true; while (ok && !sw_unlock_requested()) { - ok = ok && swd_read_word(rtt_cb + offsetof(SEGGER_RTT_CB, aUp[0].WrOff), (uint32_t *)&aUp.WrOff); + service_traffic(); + + ok = ok && swd_read_word(rtt_cb + offsetof(SEGGER_RTT_CB, aUp[RTT_CHANNEL_CONSOLE].WrOff), (uint32_t *)&aUp.WrOff); if (aUp.WrOff == aUp.RdOff) { // -> no characters available - xEventGroupWaitBits(events, EV_RTT_TO_TARGET, pdTRUE, pdFALSE, pdMS_TO_TICKS(10)); + xEventGroupWaitBits(events, EV_RTT_TO_TARGET, pdTRUE, pdFALSE, pdMS_TO_TICKS(RTT_POLL_INT_MS)); } else { // @@ -175,7 +213,7 @@ static void do_rtt_console(uint32_t rtt_cb) memset(buf, 0, sizeof(buf)); ok = ok && swd_read_memory((uint32_t)aUp.pBuffer + aUp.RdOff, buf, cnt); aUp.RdOff = (aUp.RdOff + cnt) % aUp.SizeOfBuffer; - ok = ok && swd_write_word(rtt_cb + offsetof(SEGGER_RTT_CB, aUp[0].RdOff), aUp.RdOff); + ok = ok && swd_write_word(rtt_cb + offsetof(SEGGER_RTT_CB, aUp[RTT_CHANNEL_CONSOLE].RdOff), aUp.RdOff); // put received data into CDC UART cdc_uart_write(buf, cnt); @@ -187,7 +225,7 @@ static void do_rtt_console(uint32_t rtt_cb) // // send data to target // - ok = ok && swd_read_word(rtt_cb + offsetof(SEGGER_RTT_CB, aDown[0].RdOff), (uint32_t *)&(aDown.RdOff)); + ok = ok && swd_read_word(rtt_cb + offsetof(SEGGER_RTT_CB, aDown[RTT_CHANNEL_CONSOLE].RdOff), (uint32_t *)&(aDown.RdOff)); if ((aDown.WrOff + 1) % aDown.SizeOfBuffer != aDown.RdOff) { // -> space left in RTT buffer on target uint32_t cnt; @@ -205,7 +243,7 @@ static void do_rtt_console(uint32_t rtt_cb) if (r > 0) { ok = ok && swd_write_memory((uint32_t)aDown.pBuffer + aDown.WrOff, buf, r); aDown.WrOff = (aDown.WrOff + r) % aDown.SizeOfBuffer; - ok = ok && swd_write_word(rtt_cb + offsetof(SEGGER_RTT_CB, aDown[0].WrOff), aDown.WrOff); + ok = ok && swd_write_word(rtt_cb + offsetof(SEGGER_RTT_CB, aDown[RTT_CHANNEL_CONSOLE].WrOff), aDown.WrOff); led_state(LS_UART_TX_DATA); } @@ -333,6 +371,178 @@ void rtt_console_send_byte(uint8_t ch) +//---------------------------------------------------------------------------------------------------------------------- +// +// TCP server for SystemView +// - using RNDIS / ECM because it is driver free for Windows / Linux / iOS +// - we leave the IPv6 stuff outside +// - TODO this should become its own module, but this is more or less a PoC +// but everything required is contained here, including headers / definitions and so on. +// +#if OPT_SYSVIEW_RNDIS + + +#define INIT_IP4(a,b,c,d) { PP_HTONL(LWIP_MAKEU32(a,b,c,d)) } + +/* network parameters of this MCU */ +static const ip4_addr_t ipaddr = INIT_IP4(192, 168, 2, 99); +static const ip4_addr_t netmask = INIT_IP4(255, 255, 255, 0); +static const ip4_addr_t gateway = INIT_IP4(0, 0, 0, 0); + +/* database IP addresses that can be offered to the host; this must be in RAM to store assigned MAC addresses */ +static dhcp_entry_t entries[] = +{ + /* mac ip address lease time */ + { {0}, INIT_IP4(192, 168, 0, 2), 24 * 60 * 60 }, + { {0}, INIT_IP4(192, 168, 0, 3), 24 * 60 * 60 }, + { {0}, INIT_IP4(192, 168, 0, 4), 24 * 60 * 60 }, +}; + +static const dhcp_config_t dhcp_config = +{ + .router = INIT_IP4(0, 0, 0, 0), /* router address (if any) */ + .port = 67, /* listen port */ + .dns = INIT_IP4(192, 168, 0, 5), /* dns server (if any) */ + "usb", /* dns suffix */ + TU_ARRAY_SIZE(entries), /* num entry */ + entries /* entries */ +}; + + + +/* handle any DNS requests from dns-server */ +bool dns_query_proc(const char *name, ip4_addr_t *addr) +{ + if (0 == strcmp(name, "tiny.usb")) { + *addr = ipaddr; + return true; + } + return false; +} // dns_query_proc + + + +void tud_network_init_cb(void) +{ + /* if the network is re-initializing and we have a leftover packet, we must do a cleanup */ + if (received_frame) + { + pbuf_free(received_frame); + received_frame = NULL; + } +} // tud_network_init_cb + + + +bool tud_network_recv_cb(const uint8_t *src, uint16_t size) +{ + /* this shouldn't happen, but if we get another packet before + parsing the previous, we must signal our inability to accept it */ + if (received_frame) + return false; + + if (size) { + struct pbuf *p = pbuf_alloc(PBUF_RAW, size, PBUF_POOL); + + if (p) { + /* pbuf_alloc() has already initialized struct; all we need to do is copy the data */ + memcpy(p->payload, src, size); + + /* store away the pointer for service_traffic() to later handle */ + received_frame = p; + } + } + return true; +} // tud_network_recv_cb + + + +uint16_t tud_network_xmit_cb(uint8_t *dst, void *ref, uint16_t arg) +{ + struct pbuf *p = (struct pbuf *)ref; + + (void)arg; /* unused for this example */ + + return pbuf_copy_partial(p, dst, p->tot_len, 0); +} // tud_network_xmit_cb + + + +static err_t linkoutput_fn(struct netif *netif, struct pbuf *p) +{ + (void)netif; + + for (;;) { + /* if TinyUSB isn't ready, we must signal back to lwip that there is nothing we can do */ + if (!tud_ready()) + return ERR_USE; + + /* if the network driver can accept another packet, we make it happen */ + if (tud_network_can_xmit(p->tot_len)) { + tud_network_xmit(p, 0 /* unused for this example */); + return ERR_OK; + } + + /* transfer execution to TinyUSB in the hopes that it will finish transmitting the prior packet */ + tud_task(); + } +} // linkoutput_fn + + + +static err_t ip4_output_fn(struct netif *netif, struct pbuf *p, const ip4_addr_t *addr) +{ + return etharp_output(netif, p, addr); +} // ip4_output_fn + + + +static err_t netif_init_cb(struct netif *netif) +{ + LWIP_ASSERT("netif != NULL", (netif != NULL)); + netif->mtu = CFG_TUD_NET_MTU; + netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP | NETIF_FLAG_UP; + netif->state = NULL; + netif->name[0] = 'E'; + netif->name[1] = 'X'; + netif->linkoutput = linkoutput_fn; + netif->output = ip4_output_fn; + return ERR_OK; +} // netif_init_cb + + + +static void init_lwip(void) +{ + struct netif *netif = &netif_data; + + lwip_init(); + + /* the lwip virtual MAC address must be different from the host's; to ensure this, we toggle the LSbit */ + netif->hwaddr_len = sizeof(tud_network_mac_address); + memcpy(netif->hwaddr, tud_network_mac_address, sizeof(tud_network_mac_address)); + netif->hwaddr[5] ^= 0x01; + + netif = netif_add(netif, &ipaddr, &netmask, &gateway, NULL, netif_init_cb, ip_input); + netif_set_default(netif); + + while ( !netif_is_up(&netif_data)) + ; +#if 0 + while (dhserv_init(&dhcp_config) != ERR_OK) + ; + while (dnserv_init(IP_ADDR_ANY, 53, dns_query_proc) != ERR_OK) + ; +#endif +} // init_lwip + + +#endif + +//---------------------------------------------------------------------------------------------------------------------- + + + void rtt_console_init(uint32_t task_prio) { picoprobe_debug("rtt_console_init()\n"); @@ -349,4 +559,8 @@ void rtt_console_init(uint32_t task_prio) { picoprobe_error("rtt_console_init: cannot create task_rtt_console\n"); } + +#if OPT_SYSVIEW_RNDIS + init_lwip(); +#endif } // rtt_console_init diff --git a/src/usb_descriptors.c b/src/usb_descriptors.c index 5afda437c..e70171453 100644 --- a/src/usb_descriptors.c +++ b/src/usb_descriptors.c @@ -89,9 +89,15 @@ tusb_desc_device_t const desc_device = uint8_t const * tud_descriptor_device_cb(void) { #if OPT_SYSVIEW_RNDIS - pico_unique_board_id_t id; - pico_get_unique_board_id( &id); - memcpy(tud_network_mac_address, &id, sizeof(tud_network_mac_address)); + static bool initialized; + + if ( !initialized) { + pico_unique_board_id_t id; + + initialized = true; + pico_get_unique_board_id( &id); + memcpy(tud_network_mac_address, &id, sizeof(tud_network_mac_address)); + } #endif return (uint8_t const *) &desc_device; } @@ -125,8 +131,8 @@ enum ITF_NUM_CDC_DEBUG_DATA, #endif #if OPT_SYSVIEW_RNDIS - ITF_NUM_RNDIS, - ITF_NUM_RNDIS_ECM, + ITF_NUM_CDC_RNDIS_COM, + ITF_NUM_CDC_RNDIS_DATA, #endif ITF_NUM_TOTAL }; @@ -164,9 +170,9 @@ enum CDC_DEBUG_DATA_IN_EP_CNT, #endif #if OPT_SYSVIEW_RNDIS - RNDIS_NOTIFICATION_EP_CNT, - RNDIS_DATA_OUT_EP_CNT, - RNDIS_DATA_IN_EP_CNT, + CDC_RNDIS_NOTIFICATION_EP_CNT, + CDC_RNDIS_DATA_OUT_EP_CNT, + CDC_RNDIS_DATA_IN_EP_CNT, #endif }; @@ -198,9 +204,9 @@ enum #define CDC_DEBUG_DATA_IN_EP_NUM (CDC_DEBUG_DATA_IN_EP_CNT + 0x80) #endif #if OPT_SYSVIEW_RNDIS - #define RNDIS_NOTIFICATION_EP_NUM (RNDIS_NOTIFICATION_EP_CNT + 0x80) - #define RNDIS_DATA_OUT_EP_NUM (RNDIS_DATA_OUT_EP_CNT + 0x00) - #define RNDIS_DATA_IN_EP_NUM (RNDIS_DATA_IN_EP_CNT + 0x80) + #define CDC_RNDIS_NOTIFICATION_EP_NUM (CDC_RNDIS_NOTIFICATION_EP_CNT + 0x80) + #define CDC_RNDIS_DATA_OUT_EP_NUM (CDC_RNDIS_DATA_OUT_EP_CNT + 0x00) + #define CDC_RNDIS_DATA_IN_EP_NUM (CDC_RNDIS_DATA_IN_EP_CNT + 0x80) #endif #define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + CFG_TUD_CDC*TUD_CDC_DESC_LEN + CFG_TUD_VENDOR*TUD_VENDOR_DESC_LEN \ @@ -208,6 +214,19 @@ enum + CFG_TUD_ECM_RNDIS*TUD_RNDIS_DESC_LEN) +enum +{ +#if CFG_TUD_ECM_RNDIS + CONFIG_ID_RNDIS = 0, + CONFIG_ID_ECM = 1, +#else + CONFIG_ID_NCM = 0, +#endif + CONFIG_ID_COUNT +}; + + + #if CFG_TUD_HID static uint8_t const desc_hid_report[] = { @@ -263,8 +282,8 @@ static uint8_t const desc_configuration[] = #if OPT_SYSVIEW_RNDIS // Interface 9 + 10: RNDIS for SysView - TUD_RNDIS_DESCRIPTOR(ITF_NUM_RNDIS, STRID_INTERFACE_RNDIS, RNDIS_NOTIFICATION_EP_NUM, 64, RNDIS_DATA_OUT_EP_NUM, RNDIS_DATA_IN_EP_NUM, 64), - TUD_CDC_ECM_DESCRIPTOR(ITF_NUM_RNDIS, STRID_INTERFACE_RNDIS, STRID_MAC, RNDIS_NOTIFICATION_EP_NUM, 64, RNDIS_DATA_OUT_EP_NUM, RNDIS_DATA_IN_EP_NUM, 64, 1500) + TUD_RNDIS_DESCRIPTOR(ITF_NUM_CDC_RNDIS_COM, STRID_INTERFACE_RNDIS, CDC_RNDIS_NOTIFICATION_EP_NUM, 8, CDC_RNDIS_DATA_OUT_EP_NUM, CDC_RNDIS_DATA_IN_EP_NUM, 64), + TUD_CDC_ECM_DESCRIPTOR(ITF_NUM_CDC_RNDIS_COM, STRID_INTERFACE_RNDIS, STRID_MAC, CDC_RNDIS_NOTIFICATION_EP_NUM, 64, CDC_RNDIS_DATA_OUT_EP_NUM, CDC_RNDIS_DATA_IN_EP_NUM, 64, CFG_TUD_NET_MTU) #endif }; @@ -316,16 +335,15 @@ uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid) memcpy( &_desc_str[1], string_desc_arr[0], 2); chr_count = 1; } +#if OPT_SYSVIEW_RNDIS else if (index == STRID_MAC) { - // take first 6 bytes of serial number - memcpy( &_desc_str[1], usb_serial, 12); - chr_count = 12; // Convert MAC address into UTF-16 for (unsigned i = 0; i < sizeof(tud_network_mac_address); ++i) { _desc_str[1+chr_count++] = "0123456789ABCDEF"[(tud_network_mac_address[i] >> 4) & 0xf]; _desc_str[1+chr_count++] = "0123456789ABCDEF"[(tud_network_mac_address[i] >> 0) & 0xf]; } } +#endif else { // Convert ASCII string into UTF-16 From 14ec894a284c532fa19508544029e80d31d82736 Mon Sep 17 00:00:00 2001 From: Hardy Griech Date: Mon, 1 May 2023 23:37:08 +0200 Subject: [PATCH 005/118] playing around (without success) --- CMakeLists.txt | 9 +- include/FreeRTOSConfig.h | 4 +- include/arch/cc.h | 6 +- include/lwipopts.h | 6 +- include/tusb_config.h | 9 +- src/usb_descriptors.c | 177 +++++++++++++++++++++------------------ 6 files changed, 111 insertions(+), 100 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 20669edef..f988c6944 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -192,18 +192,11 @@ if(OPT_SYSVIEW_RNDIS) add_compile_definitions(OPT_SYSVIEW_RNDIS=1) target_link_libraries(${PROJECT} PRIVATE - pico_lwip_freertos + pico_lwip_nosys ) target_include_directories(${PROJECT} PRIVATE ${PICO_TINYUSB_PATH}/lib/networking - #${PICO_LWIP_PATH}/contrib/ports/freertos/include - #${PICO_TINYUSB_PATH}/lib/lwip/src/include - #${PICO_LWIP_PATH}/test/unit -# ${PICO_LWIP_PATH}/lib/lwip/src/include -# ${PICO_LWIP_PATH}/lib/lwip/src/include/ipv4 -# ${PICO_LWIP_PATH}/lib/lwip/src/include/lwip/apps - ) target_sources(${PROJECT} PRIVATE diff --git a/include/FreeRTOSConfig.h b/include/FreeRTOSConfig.h index c79ddf475..da4f93ce2 100644 --- a/include/FreeRTOSConfig.h +++ b/include/FreeRTOSConfig.h @@ -52,7 +52,7 @@ #define configTICK_RATE_HZ ( ( TickType_t ) 1000 ) #define configMAX_PRIORITIES 32 -#define configMINIMAL_STACK_SIZE ((configSTACK_DEPTH_TYPE) 1024) +#define configMINIMAL_STACK_SIZE ((configSTACK_DEPTH_TYPE) 2048) #define configUSE_16_BIT_TICKS 0 #define configIDLE_SHOULD_YIELD 1 @@ -78,7 +78,7 @@ /* Memory allocation related definitions. */ #define configSUPPORT_STATIC_ALLOCATION 1 #define configSUPPORT_DYNAMIC_ALLOCATION 1 -#define configTOTAL_HEAP_SIZE (105*1024) +#define configTOTAL_HEAP_SIZE (155*1024) #define configAPPLICATION_ALLOCATED_HEAP 0 /* Hook function related definitions. */ diff --git a/include/arch/cc.h b/include/arch/cc.h index c7927fdb4..75ee97965 100755 --- a/include/arch/cc.h +++ b/include/arch/cc.h @@ -32,10 +32,10 @@ #ifndef __CC_H__ #define __CC_H__ -//#include "cpu.h" - -//typedef int sys_prot_t; +#if NO_SYS + typedef int sys_prot_t; +#endif /* define compiler specific symbols */ diff --git a/include/lwipopts.h b/include/lwipopts.h index f233d6800..18995c658 100755 --- a/include/lwipopts.h +++ b/include/lwipopts.h @@ -33,12 +33,12 @@ #define __LWIPOPTS_H__ /* Prevent having to link sys_arch.c (we don't test the API layers in unit tests) */ -#define NO_SYS 0 +#define NO_SYS 1 #define MEM_ALIGNMENT 4 -#define LWIP_RAW 0 +#define LWIP_RAW 1 #define LWIP_NETCONN 0 #define LWIP_SOCKET 0 -#define LWIP_DHCP 0 +#define LWIP_DHCP 1 #define LWIP_ICMP 1 #define LWIP_UDP 1 #define LWIP_TCP 1 diff --git a/include/tusb_config.h b/include/tusb_config.h index 85f50f4c1..e72650c77 100644 --- a/include/tusb_config.h +++ b/include/tusb_config.h @@ -26,6 +26,8 @@ #ifndef _TUSB_CONFIG_H_ #define _TUSB_CONFIG_H_ +#include + #ifdef __cplusplus extern "C" { #endif @@ -88,6 +90,9 @@ #define CFG_TUD_CDC (CFG_TUD_CDC_UART + CFG_TUD_CDC_SIGROK + CFG_TUD_CDC_DEBUG) #if OPT_SYSVIEW_RNDIS #define CFG_TUD_ECM_RNDIS 1 + #define CFG_TUD_NCM (1 - CFG_TUD_ECM_RNDIS) +#else + #define CFG_TUD_ECM_RNDIS 0 #define CFG_TUD_NCM 0 #endif @@ -111,7 +116,9 @@ #define CFG_TUD_MSC_EP_BUFSIZE 512 #if OPT_SYSVIEW_RNDIS - #define CFG_TUD_NET_MTU 800 + #define CFG_TUD_NET_MTU 1500 + + extern uint8_t tud_network_mac_address[6]; #endif #ifdef __cplusplus diff --git a/src/usb_descriptors.c b/src/usb_descriptors.c index e70171453..1a7cc122f 100644 --- a/src/usb_descriptors.c +++ b/src/usb_descriptors.c @@ -32,7 +32,7 @@ #if OPT_SYSVIEW_RNDIS - uint8_t tud_network_mac_address[6] = {0}; + uint8_t tud_network_mac_address[6] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; #endif @@ -61,6 +61,42 @@ enum }; +enum +{ +#if CFG_TUD_VENDOR + ITF_NUM_PROBE_VENDOR, // Old versions of Keil MDK only look at interface 0 +#endif +#if CFG_TUD_HID + ITF_NUM_PROBE_HID, +#endif +#if CFG_TUD_CDC_UART + ITF_NUM_CDC_UART_COM, + ITF_NUM_CDC_UART_DATA, +#endif +#if OPT_SIGROK + ITF_NUM_CDC_SIGROK_COM, + ITF_NUM_CDC_SIGROK_DATA, +#endif +#if CFG_TUD_MSC + ITF_NUM_MSC, +#endif +#if CFG_TUD_CDC_DEBUG + ITF_NUM_CDC_DEBUG_COM, + ITF_NUM_CDC_DEBUG_DATA, +#endif +#if OPT_SYSVIEW_RNDIS + #if CFG_TUD_ECM_RNDIS + ITF_NUM_CDC_RNDIS_COM, + ITF_NUM_CDC_RNDIS_DATA, + #else + ITF_NUM_CDC_NCM_COM, + ITF_NUM_CDC_NCM_DATA, + #endif +#endif + ITF_NUM_TOTAL +}; + + //--------------------------------------------------------------------+ // Device Descriptors //--------------------------------------------------------------------+ @@ -70,9 +106,12 @@ tusb_desc_device_t const desc_device = .bLength = sizeof(tusb_desc_device_t), .bDescriptorType = TUSB_DESC_DEVICE, .bcdUSB = 0x0210, // USB Specification version 2.1 for BOS - .bDeviceClass = 0x00, // Each interface specifies its own - .bDeviceSubClass = 0x00, // Each interface specifies its own - .bDeviceProtocol = 0x00, + + // Use Interface Association Descriptor (IAD) device class + .bDeviceClass = TUSB_CLASS_MISC, + .bDeviceSubClass = MISC_SUBCLASS_COMMON, + .bDeviceProtocol = MISC_PROTOCOL_IAD, + .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, .idVendor = 0x2E8A, // Pi @@ -81,7 +120,7 @@ tusb_desc_device_t const desc_device = .iManufacturer = STRID_MANUFACTURER, .iProduct = STRID_PRODUCT, .iSerialNumber = STRID_SERIAL, - .bNumConfigurations = 1 + .bNumConfigurations = 1, }; // Invoked when received GET DEVICE DESCRIPTOR @@ -89,6 +128,7 @@ tusb_desc_device_t const desc_device = uint8_t const * tud_descriptor_device_cb(void) { #if OPT_SYSVIEW_RNDIS +#if 0 static bool initialized; if ( !initialized) { @@ -98,6 +138,7 @@ uint8_t const * tud_descriptor_device_cb(void) pico_get_unique_board_id( &id); memcpy(tud_network_mac_address, &id, sizeof(tud_network_mac_address)); } +#endif #endif return (uint8_t const *) &desc_device; } @@ -107,37 +148,6 @@ uint8_t const * tud_descriptor_device_cb(void) // Configuration Descriptor //--------------------------------------------------------------------+ -enum -{ -#if CFG_TUD_VENDOR - ITF_NUM_PROBE_VENDOR, // Old versions of Keil MDK only look at interface 0 -#endif -#if CFG_TUD_HID - ITF_NUM_PROBE_HID, -#endif -#if CFG_TUD_CDC_UART - ITF_NUM_CDC_COM, - ITF_NUM_CDC_DATA, -#endif -#if OPT_SIGROK - ITF_NUM_CDC_SIGROK_COM, - ITF_NUM_CDC_SIGROK_DATA, -#endif -#if CFG_TUD_MSC - ITF_NUM_MSC, -#endif -#if CFG_TUD_CDC_DEBUG - ITF_NUM_CDC_DEBUG_COM, - ITF_NUM_CDC_DEBUG_DATA, -#endif -#if OPT_SYSVIEW_RNDIS - ITF_NUM_CDC_RNDIS_COM, - ITF_NUM_CDC_RNDIS_DATA, -#endif - ITF_NUM_TOTAL -}; - - // don't know if consecutive numbering is required. Let's do it anyway enum { @@ -151,9 +161,9 @@ enum PROBE_HID_IN_EP_CNT, #endif #if CFG_TUD_CDC_UART - CDC_NOTIFICATION_EP_CNT, - CDC_DATA_OUT_EP_CNT, - CDC_DATA_IN_EP_CNT, + CDC_UART_NOTIFICATION_EP_CNT, + CDC_UART_DATA_OUT_EP_CNT, + CDC_UART_DATA_IN_EP_CNT, #endif #if OPT_SIGROK CDC_SIGROK_NOTIFICATION_EP_CNT, @@ -170,12 +180,19 @@ enum CDC_DEBUG_DATA_IN_EP_CNT, #endif #if OPT_SYSVIEW_RNDIS - CDC_RNDIS_NOTIFICATION_EP_CNT, - CDC_RNDIS_DATA_OUT_EP_CNT, - CDC_RNDIS_DATA_IN_EP_CNT, + #if CFG_TUD_ECM_RNDIS + CDC_RNDIS_NOTIFICATION_EP_CNT, + CDC_RNDIS_DATA_OUT_EP_CNT, + CDC_RNDIS_DATA_IN_EP_CNT, + #else + CDC_NCM_NOTIFICATION_EP_CNT, + CDC_NCM_DATA_OUT_EP_CNT, + CDC_NCM_DATA_IN_EP_CNT, + #endif #endif }; + #if CFG_TUD_VENDOR #define PROBE_VENDOR_OUT_EP_NUM (PROBE_VENDOR_OUT_EP_CNT + 0x00) #define PROBE_VENDOR_IN_EP_NUM (PROBE_VENDOR_IN_EP_CNT + 0x80) @@ -185,9 +202,9 @@ enum #define PROBE_HID_IN_EP_NUM (PROBE_HID_IN_EP_CNT + 0x80) #endif #if CFG_TUD_CDC_UART - #define CDC_NOTIFICATION_EP_NUM (CDC_NOTIFICATION_EP_CNT + 0x80) - #define CDC_DATA_OUT_EP_NUM (CDC_DATA_OUT_EP_CNT + 0x00) - #define CDC_DATA_IN_EP_NUM (CDC_DATA_IN_EP_CNT + 0x80) + #define CDC_UART_NOTIFICATION_EP_NUM (CDC_UART_NOTIFICATION_EP_CNT + 0x80) + #define CDC_UART_DATA_OUT_EP_NUM (CDC_UART_DATA_OUT_EP_CNT + 0x00) + #define CDC_UART_DATA_IN_EP_NUM (CDC_UART_DATA_IN_EP_CNT + 0x80) #endif #if OPT_SIGROK #define CDC_SIGROK_NOTIFICATION_EP_NUM (CDC_SIGROK_NOTIFICATION_EP_CNT + 0x80) @@ -204,28 +221,22 @@ enum #define CDC_DEBUG_DATA_IN_EP_NUM (CDC_DEBUG_DATA_IN_EP_CNT + 0x80) #endif #if OPT_SYSVIEW_RNDIS - #define CDC_RNDIS_NOTIFICATION_EP_NUM (CDC_RNDIS_NOTIFICATION_EP_CNT + 0x80) - #define CDC_RNDIS_DATA_OUT_EP_NUM (CDC_RNDIS_DATA_OUT_EP_CNT + 0x00) - #define CDC_RNDIS_DATA_IN_EP_NUM (CDC_RNDIS_DATA_IN_EP_CNT + 0x80) + #if CFG_TUD_ECM_RNDIS + #define CDC_RNDIS_NOTIFICATION_EP_NUM (CDC_RNDIS_NOTIFICATION_EP_CNT + 0x80) + #define CDC_RNDIS_DATA_OUT_EP_NUM (CDC_RNDIS_DATA_OUT_EP_CNT + 0x00) + #define CDC_RNDIS_DATA_IN_EP_NUM (CDC_RNDIS_DATA_IN_EP_CNT + 0x80) + #else + #define CDC_NCM_NOTIFICATION_EP_NUM (CDC_NCM_NOTIFICATION_EP_CNT + 0x80) + #define CDC_NCM_DATA_OUT_EP_NUM (CDC_NCM_DATA_OUT_EP_CNT + 0x00) + #define CDC_NCM_DATA_IN_EP_NUM (CDC_NCM_DATA_IN_EP_CNT + 0x80) + #endif #endif + #define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + CFG_TUD_CDC*TUD_CDC_DESC_LEN + CFG_TUD_VENDOR*TUD_VENDOR_DESC_LEN \ + CFG_TUD_HID*TUD_HID_INOUT_DESC_LEN + CFG_TUD_MSC*TUD_MSC_DESC_LEN \ - + CFG_TUD_ECM_RNDIS*TUD_RNDIS_DESC_LEN) - - -enum -{ -#if CFG_TUD_ECM_RNDIS - CONFIG_ID_RNDIS = 0, - CONFIG_ID_ECM = 1, -#else - CONFIG_ID_NCM = 0, -#endif - CONFIG_ID_COUNT -}; - - + + CFG_TUD_ECM_RNDIS*TUD_RNDIS_DESC_LEN \ + + CFG_TUD_NCM*TUD_CDC_NCM_DESC_LEN) #if CFG_TUD_HID static uint8_t const desc_hid_report[] = @@ -241,52 +252,47 @@ enum #endif + // // note that there is a 64byte packet limit for full speed! // +#define CURR_MA 200 + static uint8_t const desc_configuration[] = { // Config number, interface count, string index, total length, attribute, power in mA //TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 500), - TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0, 200), - + TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0, CURR_MA), #if CFG_TUD_VENDOR - // Interface 0: Bulk (named interface), CMSIS-DAPv2 TUD_VENDOR_DESCRIPTOR(ITF_NUM_PROBE_VENDOR, STRID_INTERFACE_DAP2, PROBE_VENDOR_OUT_EP_NUM, PROBE_VENDOR_IN_EP_NUM, 64), #endif - #if CFG_TUD_HID - // Interface 1: HID (named interface), CMSIS-DAP v1 TUD_HID_INOUT_DESCRIPTOR(ITF_NUM_PROBE_HID, STRID_INTERFACE_DAP1, HID_ITF_PROTOCOL_NONE, sizeof(desc_hid_report), PROBE_HID_OUT_EP_NUM, PROBE_HID_IN_EP_NUM, CFG_TUD_HID_EP_BUFSIZE, 1), #endif - #if CFG_TUD_CDC_UART - // Interface 2 + 3: CDC UART (target) - TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_COM, STRID_INTERFACE_CDC_UART, CDC_NOTIFICATION_EP_NUM, 64, CDC_DATA_OUT_EP_NUM, CDC_DATA_IN_EP_NUM, 64), + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_UART_COM, STRID_INTERFACE_CDC_UART, CDC_UART_NOTIFICATION_EP_NUM, 64, CDC_UART_DATA_OUT_EP_NUM, CDC_UART_DATA_IN_EP_NUM, 64), #endif - #if OPT_SIGROK - // Interface 4 + 5: CDC SIGROK TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_SIGROK_COM, STRID_INTERFACE_CDC_SIGROK, CDC_SIGROK_NOTIFICATION_EP_NUM, 64, CDC_SIGROK_DATA_OUT_EP_NUM, CDC_SIGROK_DATA_IN_EP_NUM, 64), #endif - - // Interface 6: MSC #if CFG_TUD_MSC TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, STRID_INTERFACE_MSC, MSC_OUT_EP_NUM, MSC_IN_EP_NUM, 64), #endif - #if CFG_TUD_CDC_DEBUG - // Interface 7 + 8: CDC DEBUG (internal) TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_DEBUG_COM, STRID_INTERFACE_CDC_DEBUG, CDC_DEBUG_NOTIFICATION_EP_NUM, 64, CDC_DEBUG_DATA_OUT_EP_NUM, CDC_DEBUG_DATA_IN_EP_NUM, 64), #endif - #if OPT_SYSVIEW_RNDIS - // Interface 9 + 10: RNDIS for SysView - TUD_RNDIS_DESCRIPTOR(ITF_NUM_CDC_RNDIS_COM, STRID_INTERFACE_RNDIS, CDC_RNDIS_NOTIFICATION_EP_NUM, 8, CDC_RNDIS_DATA_OUT_EP_NUM, CDC_RNDIS_DATA_IN_EP_NUM, 64), - TUD_CDC_ECM_DESCRIPTOR(ITF_NUM_CDC_RNDIS_COM, STRID_INTERFACE_RNDIS, STRID_MAC, CDC_RNDIS_NOTIFICATION_EP_NUM, 64, CDC_RNDIS_DATA_OUT_EP_NUM, CDC_RNDIS_DATA_IN_EP_NUM, 64, CFG_TUD_NET_MTU) + #if CFG_TUD_ECM_RNDIS + TUD_RNDIS_DESCRIPTOR(ITF_NUM_CDC_RNDIS_COM, STRID_INTERFACE_RNDIS, CDC_RNDIS_NOTIFICATION_EP_NUM, 8, CDC_RNDIS_DATA_OUT_EP_NUM, CDC_RNDIS_DATA_IN_EP_NUM, 64), + // TODO ECM must be an alternative to RNDIS, RNDIS works on Windows, ECM on iOS, Linux can handle both!? + // TUD_CDC_ECM_DESCRIPTOR(ITF_NUM_CDC_RNDIS_COM, STRID_INTERFACE_RNDIS, STRID_MAC, CDC_RNDIS_NOTIFICATION_EP_NUM, 64, CDC_RNDIS_DATA_OUT_EP_NUM, CDC_RNDIS_DATA_IN_EP_NUM, 64, CFG_TUD_NET_MTU), + #else + TUD_CDC_NCM_DESCRIPTOR(ITF_NUM_CDC_NCM_COM, STRID_INTERFACE_RNDIS, STRID_MAC, CDC_NCM_NOTIFICATION_EP_NUM, 64, CDC_NCM_DATA_OUT_EP_NUM, CDC_NCM_DATA_IN_EP_NUM, 64, CFG_TUD_NET_MTU), + #endif #endif }; + // Invoked when received GET CONFIGURATION DESCRIPTOR // Application return pointer to descriptor // Descriptor contents must exist long enough for transfer to complete @@ -294,7 +300,8 @@ uint8_t const * tud_descriptor_configuration_cb(uint8_t index) { (void)index; // for multiple configurations return desc_configuration; -} +} // tud_descriptor_configuration_cb + //--------------------------------------------------------------------+ // String Descriptors @@ -316,7 +323,11 @@ static char const* string_desc_arr[] = #endif [STRID_INTERFACE_CDC_DEBUG] = "YAPicoprobe CDC-DEBUG", // Interface descriptor for CDC DEBUG #if OPT_SYSVIEW_RNDIS - [STRID_INTERFACE_RNDIS] = "YaPicoprobe RNDIS SysView", // Interface descriptor for SysView RNDIS + #if CFG_TUD_ECM_RNDIS + [STRID_INTERFACE_RNDIS] = "YaPicoprobe SysView RNDIS", // Interface descriptor for SysView RNDIS + #else + [STRID_INTERFACE_RNDIS] = "YaPicoprobe SysView NCM", // Interface descriptor for SysView NCM + #endif [STRID_MAC] = "", #endif }; From 929df4a5b231fa640206bbb33417020e27f3c610 Mon Sep 17 00:00:00 2001 From: Hardy Griech Date: Tue, 2 May 2023 19:02:41 +0200 Subject: [PATCH 006/118] now lwip stuff in an extra module (still not working) --- CMakeLists.txt | 20 +-- README.adoc | 2 + include/arch/cc.h | 3 + include/lwipopts.h | 39 ++++++ src/main.c | 7 + src/net_starter.c | 333 +++++++++++++++++++++++++++++++++++++++++++++ src/net_starter.h | 46 +++++++ src/rtt_console.c | 211 ---------------------------- 8 files changed, 441 insertions(+), 220 deletions(-) create mode 100755 src/net_starter.c create mode 100755 src/net_starter.h diff --git a/CMakeLists.txt b/CMakeLists.txt index f988c6944..562746ad4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -168,6 +168,8 @@ add_compile_definitions(DRAG_N_DROP_SUPPORT=1) # this is for SIGROK operation (taken from https://github.com/pico-coder/sigrok-pico) # if(OPT_SIGROK) + add_compile_definitions(OPT_SIGROK=1) + target_sources(${PROJECT} PRIVATE src/pico-sigrok/cdc_sigrok.c src/pico-sigrok/sigrok.c @@ -180,8 +182,6 @@ if(OPT_SIGROK) ) pico_generate_pio_header(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}/src/pico-sigrok/sigrok.pio) - - add_compile_definitions(OPT_SIGROK=1) endif() #-------------------------------------------------------------------------------------------------- @@ -191,18 +191,20 @@ endif() if(OPT_SYSVIEW_RNDIS) add_compile_definitions(OPT_SYSVIEW_RNDIS=1) - target_link_libraries(${PROJECT} PRIVATE - pico_lwip_nosys + target_sources(${PROJECT} PRIVATE + src/net_starter.c + + ${PICO_TINYUSB_PATH}/lib/networking/dhserver.c + ${PICO_TINYUSB_PATH}/lib/networking/dnserver.c + ${PICO_TINYUSB_PATH}/lib/networking/rndis_reports.c ) - + target_include_directories(${PROJECT} PRIVATE ${PICO_TINYUSB_PATH}/lib/networking ) - target_sources(${PROJECT} PRIVATE - ${PICO_TINYUSB_PATH}/lib/networking/dhserver.c - ${PICO_TINYUSB_PATH}/lib/networking/dnserver.c - ${PICO_TINYUSB_PATH}/lib/networking/rndis_reports.c + target_link_libraries(${PROJECT} PRIVATE + pico_lwip_nosys ) # message("--------- " ${PICO_LWIP_PATH}) diff --git a/README.adoc b/README.adoc index 425bbb2db..77edfc84c 100644 --- a/README.adoc +++ b/README.adoc @@ -80,6 +80,8 @@ For information about cabling between Pico Debug Probe and target refer to the c https://www.raspberrypi.com/documentation/microcontrollers/debug-probe.html[documentation]. For details about probe pin assignments see the link:doc/hardware.adoc[hardware section]. +Ochamodev wrote a nice https://github.com/ochamodev/raspberry_pico_setup_guide[setup guide], +containing the steps from installation until debugging in VSCode. diff --git a/include/arch/cc.h b/include/arch/cc.h index 75ee97965..6d504d3c6 100755 --- a/include/arch/cc.h +++ b/include/arch/cc.h @@ -72,4 +72,7 @@ #define LWIP_PLATFORM_ASSERT(x) do { if(!(x)) while(1); } while(0) +#include +#define LWIP_PLATFORM_DIAG(x) do {printf x;} while(0) + #endif /* __CC_H__ */ diff --git a/include/lwipopts.h b/include/lwipopts.h index 18995c658..95053c345 100755 --- a/include/lwipopts.h +++ b/include/lwipopts.h @@ -70,4 +70,43 @@ #define LWIP_PROVIDE_ERRNO 1 + +// meine Versuche +#define LWIP_TCPIP_CORE_LOCKING 1 + + + + +// Debugging (was sonst?) +#define LWIP_DEBUG + +#define API_LIB_DEBUG LWIP_DBG_ON +#define API_MSG_DEBUG LWIP_DBG_ON +#define AUTOIP_DEBUG LWIP_DBG_ON +#define DHCP_DEBUG LWIP_DBG_ON +#define DNS_DEBUG LWIP_DBG_ON +#define ETHARP_DEBUG LWIP_DBG_ON +#define ICMP_DEBUG LWIP_DBG_ON +#define IGMP_DEBUG LWIP_DBG_ON +#define INET_DEBUG LWIP_DBG_ON +#define IP_DEBUG LWIP_DBG_ON +#define NETIF_DEBUG LWIP_DBG_ON +#define PBUF_DEBUG LWIP_DBG_ON +#define RAW_DEBUG LWIP_DBG_ON +#define SLIP_DEBUG LWIP_DBG_ON +#define SOCKETS_DEBUG LWIP_DBG_ON +#define SYS_DEBUG LWIP_DBG_ON +#define TCP_DEBUG LWIP_DBG_ON +#define TCP_INPUT_DEBUG LWIP_DBG_ON +#define TCP_FR_DEBUG LWIP_DBG_ON +#define TCP_RTO_DEBUG LWIP_DBG_ON +#define TCP_CWND_DEBUG LWIP_DBG_ON +#define TCP_WND_DEBUG LWIP_DBG_ON +#define TCP_RST_DEBUG LWIP_DBG_ON +#define TCP_OUTPUT_DEBUG LWIP_DBG_ON +#define TCP_QLEN_DEBUG LWIP_DBG_ON +#define TCPIP_DEBUG LWIP_DBG_ON +#define TIMERS_DEBUG LWIP_DBG_OFF +#define UDP_DEBUG LWIP_DBG_ON + #endif /* __LWIPOPTS_H__ */ diff --git a/src/main.c b/src/main.c index d3813af9c..d8fa55d1d 100644 --- a/src/main.c +++ b/src/main.c @@ -67,6 +67,9 @@ #include "pico-sigrok/cdc_sigrok.h" #include "pico-sigrok/sigrok.h" #endif +#if OPT_SYSVIEW_RNDIS + #include "net_starter.h" +#endif /* @@ -466,6 +469,10 @@ void usb_thread(void *ptr) sigrok_init(SIGROK_TASK_PRIO); #endif +#if OPT_SYSVIEW_RNDIS + net_starter_init(3); // TODO +#endif + #if CFG_TUD_VENDOR xTaskCreateAffinitySet(dap_task, "CMSIS-DAP", configMINIMAL_STACK_SIZE, NULL, DAP_TASK_PRIO, 2, &dap_taskhandle); #endif diff --git a/src/net_starter.c b/src/net_starter.c new file mode 100755 index 000000000..51e37fe99 --- /dev/null +++ b/src/net_starter.c @@ -0,0 +1,333 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2021 Raspberry Pi (Trading) Ltd. + * + * 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. + * + */ + + +//---------------------------------------------------------------------------------------------------------------------- +// +// TCP server for SystemView +// - using RNDIS / ECM because it is driver free for Windows / Linux / iOS +// - we leave the IPv6 stuff outside +// + + +#include +#include +#include + +#include "picoprobe_config.h" + +#include "lwip/init.h" +#include "lwip/ip.h" +#include "lwip/etharp.h" +#include "lwip/tcpip.h" +#include "lwip/timeouts.h" +#include "dhserver.h" +#include "dnserver.h" + +#include "FreeRTOS.h" +#include "tusb.h" + + + +/* lwip context */ +static struct netif netif_data; + +/* shared between tud_network_recv_cb() and service_traffic() */ +static struct pbuf *received_frame; + +#define INIT_IP4(a,b,c,d) { PP_HTONL(LWIP_MAKEU32(a,b,c,d)) } + +/* network parameters of this MCU */ +static const ip4_addr_t ipaddr = INIT_IP4(192, 168, 7, 5); +static const ip4_addr_t netmask = INIT_IP4(255, 255, 255, 0); +static const ip4_addr_t gateway = INIT_IP4(0, 0, 0, 0); + +/* database IP addresses that can be offered to the host; this must be in RAM to store assigned MAC addresses */ +static dhcp_entry_t entries[] = +{ + /* mac ip address lease time */ + { {0}, INIT_IP4(192, 168, 7, 2), 24 * 60 * 60 }, + { {0}, INIT_IP4(192, 168, 7, 3), 24 * 60 * 60 }, + { {0}, INIT_IP4(192, 168, 7, 4), 24 * 60 * 60 }, +}; + +static const dhcp_config_t dhcp_config = +{ + .router = INIT_IP4(192, 168, 0, 1), /* router address (if any) */ + .port = 67, /* listen port */ + .dns = INIT_IP4(192, 168, 0, 1), /* dns server (if any) */ + "usb", /* dns suffix */ + TU_ARRAY_SIZE(entries), /* num entry */ + entries /* entries */ +}; + +static TaskHandle_t task_net_starter = NULL; + + + +#if 0 +static void service_traffic(void) +{ + /* handle any packet received by tud_network_recv_cb() */ + if (received_frame) { + printf("service_traffic(): %p\n", received_frame); + + ethernet_input(received_frame, &netif_data); + pbuf_free(received_frame); + received_frame = NULL; + tud_network_recv_renew(); + } + sys_check_timeouts(); +} // service_traffic +#endif + + + +/* handle any DNS requests from dns-server */ +bool dns_query_proc(const char *name, ip4_addr_t *addr) +{ + printf("dns_query_proc(%s,.)\n", name); + + if (0 == strcmp(name, "tiny.usb")) { + *addr = ipaddr; + return true; + } + return false; +} // dns_query_proc + + + +void tud_network_init_cb(void) +{ + printf("tud_network_init_cb() - %p\n", received_frame); + + /* if the network is re-initializing and we have a leftover packet, we must do a cleanup */ + if (received_frame) + { + pbuf_free(received_frame); + received_frame = NULL; + } + + printf("tud_network_init_cb() a\n"); + while ( !netif_is_up(&netif_data)) + ; + printf("tud_network_init_cb() b\n"); + while (dhserv_init(&dhcp_config) != ERR_OK) + ; + printf("tud_network_init_cb() c\n"); + while (dnserv_init(IP_ADDR_ANY, 53, dns_query_proc) != ERR_OK) + ; + printf("tud_network_init_cb() d\n"); +} // tud_network_init_cb + + + +bool tud_network_recv_cb(const uint8_t *src, uint16_t size) +{ + printf("tud_network_recv_cb()\n"); + + /* this shouldn't happen, but if we get another packet before + parsing the previous, we must signal our inability to accept it */ + if (received_frame) + return false; + + if (size) { + struct pbuf *p = pbuf_alloc(PBUF_RAW, size, PBUF_POOL); + + if (p) { + /* pbuf_alloc() has already initialized struct; all we need to do is copy the data */ + memcpy(p->payload, src, size); + + /* store away the pointer for service_traffic() to later handle */ + received_frame = p; + } + } + return true; +} // tud_network_recv_cb + + + +uint16_t tud_network_xmit_cb(uint8_t *dst, void *ref, uint16_t arg) +{ + printf("tud_network_xmit_cb()\n"); + + struct pbuf *p = (struct pbuf *)ref; + + (void)arg; /* unused for this example */ + + return pbuf_copy_partial(p, dst, p->tot_len, 0); +} // tud_network_xmit_cb + + + +static err_t linkoutput_fn(struct netif *netif, struct pbuf *p) +{ + (void)netif; + + printf("linkoutput_fn()\n"); + + for (;;) { + /* if TinyUSB isn't ready, we must signal back to lwip that there is nothing we can do */ + if (!tud_ready()) + return ERR_USE; + + /* if the network driver can accept another packet, we make it happen */ + if (tud_network_can_xmit(p->tot_len)) { + tud_network_xmit(p, 0 /* unused for this example */); + return ERR_OK; + } + + /* transfer execution to TinyUSB in the hopes that it will finish transmitting the prior packet */ + tud_task(); + } +} // linkoutput_fn + + + +static err_t ip4_output_fn(struct netif *netif, struct pbuf *p, const ip4_addr_t *addr) +{ + printf("ip4_output_fn()\n"); + + return etharp_output(netif, p, addr); +} // ip4_output_fn + + + +static err_t netif_init_cb(struct netif *netif) +{ + printf("netif_init_cb(%p)\n", netif); + + LWIP_ASSERT("netif != NULL", (netif != NULL)); + netif->mtu = CFG_TUD_NET_MTU; + netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP | NETIF_FLAG_UP; + netif->hwaddr_len = ETHARP_HWADDR_LEN; + netif->state = NULL; + netif->name[0] = 'E'; + netif->name[1] = 'X'; + netif->linkoutput = linkoutput_fn; + netif->output = ip4_output_fn; + return ERR_OK; +} // netif_init_cb + + + +static void init_lwip(void) +{ + struct netif *netif = &netif_data; + + printf("init_lwip()\n"); +#if NO_SYS + lwip_init(); +#else + tcpip_init(NULL, NULL); +#endif + + /* the lwip virtual MAC address must be different from the host's; to ensure this, we toggle the LSbit */ +#if 0 + netif->hwaddr_len = sizeof(tud_network_mac_address); + memcpy(netif->hwaddr, tud_network_mac_address, sizeof(tud_network_mac_address)); + //netif->hwaddr[5] ^= 0x01; +#else + netif->hwaddr_len = NETIF_MAX_HWADDR_LEN; + memcpy(netif->hwaddr, tud_network_mac_address, NETIF_MAX_HWADDR_LEN); +#endif + + netif = netif_add(netif, &ipaddr, &netmask, &gateway, NULL, netif_init_cb, ip_input); + printf("init_lwip() - %p\n", netif); + netif_set_default(netif); + +#if 1 + printf("init_lwip() a\n"); + while ( !netif_is_up(&netif_data)) + printf("init_lwip() ax\n"); + printf("init_lwip() b\n"); + while (dhserv_init(&dhcp_config) != ERR_OK) + printf("init_lwip() bx\n"); + printf("init_lwip() c\n"); + while (dnserv_init(IP_ADDR_ANY, 53, dns_query_proc) != ERR_OK) + printf("init_lwip() cx\n"); +#endif + printf("init_lwip() d\n"); +} // init_lwip + + + +void net_starter_thread(void *ptr) +{ + vTaskDelay(pdMS_TO_TICKS(20)); + +#if 0 + printf("net_starter_thread() a\n"); + while ( !netif_is_up(&netif_data)) + ; + printf("net_starter_thread() b\n"); + while (dhserv_init(&dhcp_config) != ERR_OK) + printf("net_starter_thread() bx\n"); + printf("net_starter_thread() c\n"); + while (dnserv_init(IP_ADDR_ANY, 53, dns_query_proc) != ERR_OK) + printf("net_starter_thread() cx\n"); + printf("net_starter_thread() d\n"); +#endif + + for (;;) { + vTaskDelay(pdMS_TO_TICKS(200)); + + /* handle any packet received by tud_network_recv_cb() */ + if (received_frame) { + printf("service_traffic(): %p\n", received_frame); + + ethernet_input(received_frame, &netif_data); + pbuf_free(received_frame); + received_frame = NULL; + tud_network_recv_renew(); + } + sys_check_timeouts(); + } +} // net_starter_thread + + + +void net_starter_init(uint32_t task_prio) +{ + printf("net_starter_init()\n"); + + tud_init(0); + init_lwip(); + +#if 0 + events = xEventGroupCreate(); + + stream_rtt = xStreamBufferCreate(STREAM_RTT_SIZE, STREAM_RTT_TRIGGER); + if (stream_rtt == NULL) { + picoprobe_error("net_starter_init: cannot create stream_rtt\n"); + } +#endif + + xTaskCreateAffinitySet(net_starter_thread, "NET_STARTER", configMINIMAL_STACK_SIZE, NULL, task_prio, 1, &task_net_starter); + if (task_net_starter == NULL) + { + picoprobe_error("net_starter_init: cannot create task_net_starter\n"); + } +} // net_starter_init diff --git a/src/net_starter.h b/src/net_starter.h new file mode 100755 index 000000000..0a1c671c9 --- /dev/null +++ b/src/net_starter.h @@ -0,0 +1,46 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2021 Raspberry Pi (Trading) Ltd. + * + * 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. + * + */ + +#ifndef _NET_STARTER_H +#define _NET_STARTER_H + + +#include + + +#ifdef __cplusplus + extern "C" { +#endif + + +void net_starter_init(uint32_t task_prio); + + +#ifdef __cplusplus + } +#endif + + +#endif diff --git a/src/rtt_console.c b/src/rtt_console.c index e06c119b2..4c8aa8b55 100755 --- a/src/rtt_console.c +++ b/src/rtt_console.c @@ -67,39 +67,6 @@ static EventGroupHandle_t events; -#if OPT_SYSVIEW_RNDIS - -#include "lwip/init.h" -#include "lwip/ip.h" -#include "lwip/etharp.h" -#include "lwip/timeouts.h" -#include "dhserver.h" -#include "dnserver.h" - - -/* lwip context */ -static struct netif netif_data; - -/* shared between tud_network_recv_cb() and service_traffic() */ -static struct pbuf *received_frame; - - -static void service_traffic(void) -{ - /* handle any packet received by tud_network_recv_cb() */ - if (received_frame) { - ethernet_input(received_frame, &netif_data); - pbuf_free(received_frame); - received_frame = NULL; - tud_network_recv_renew(); - } - sys_check_timeouts(); -} // service_traffic - -#endif - - - static uint32_t check_buffer_for_rtt_cb(uint8_t *buf, uint32_t buf_size, uint32_t base_addr) { uint32_t rtt_cb = 0; @@ -188,8 +155,6 @@ static void do_rtt_console(uint32_t rtt_cb) // do operations rtt_console_running = true; while (ok && !sw_unlock_requested()) { - service_traffic(); - ok = ok && swd_read_word(rtt_cb + offsetof(SEGGER_RTT_CB, aUp[RTT_CHANNEL_CONSOLE].WrOff), (uint32_t *)&aUp.WrOff); if (aUp.WrOff == aUp.RdOff) { @@ -371,178 +336,6 @@ void rtt_console_send_byte(uint8_t ch) -//---------------------------------------------------------------------------------------------------------------------- -// -// TCP server for SystemView -// - using RNDIS / ECM because it is driver free for Windows / Linux / iOS -// - we leave the IPv6 stuff outside -// - TODO this should become its own module, but this is more or less a PoC -// but everything required is contained here, including headers / definitions and so on. -// -#if OPT_SYSVIEW_RNDIS - - -#define INIT_IP4(a,b,c,d) { PP_HTONL(LWIP_MAKEU32(a,b,c,d)) } - -/* network parameters of this MCU */ -static const ip4_addr_t ipaddr = INIT_IP4(192, 168, 2, 99); -static const ip4_addr_t netmask = INIT_IP4(255, 255, 255, 0); -static const ip4_addr_t gateway = INIT_IP4(0, 0, 0, 0); - -/* database IP addresses that can be offered to the host; this must be in RAM to store assigned MAC addresses */ -static dhcp_entry_t entries[] = -{ - /* mac ip address lease time */ - { {0}, INIT_IP4(192, 168, 0, 2), 24 * 60 * 60 }, - { {0}, INIT_IP4(192, 168, 0, 3), 24 * 60 * 60 }, - { {0}, INIT_IP4(192, 168, 0, 4), 24 * 60 * 60 }, -}; - -static const dhcp_config_t dhcp_config = -{ - .router = INIT_IP4(0, 0, 0, 0), /* router address (if any) */ - .port = 67, /* listen port */ - .dns = INIT_IP4(192, 168, 0, 5), /* dns server (if any) */ - "usb", /* dns suffix */ - TU_ARRAY_SIZE(entries), /* num entry */ - entries /* entries */ -}; - - - -/* handle any DNS requests from dns-server */ -bool dns_query_proc(const char *name, ip4_addr_t *addr) -{ - if (0 == strcmp(name, "tiny.usb")) { - *addr = ipaddr; - return true; - } - return false; -} // dns_query_proc - - - -void tud_network_init_cb(void) -{ - /* if the network is re-initializing and we have a leftover packet, we must do a cleanup */ - if (received_frame) - { - pbuf_free(received_frame); - received_frame = NULL; - } -} // tud_network_init_cb - - - -bool tud_network_recv_cb(const uint8_t *src, uint16_t size) -{ - /* this shouldn't happen, but if we get another packet before - parsing the previous, we must signal our inability to accept it */ - if (received_frame) - return false; - - if (size) { - struct pbuf *p = pbuf_alloc(PBUF_RAW, size, PBUF_POOL); - - if (p) { - /* pbuf_alloc() has already initialized struct; all we need to do is copy the data */ - memcpy(p->payload, src, size); - - /* store away the pointer for service_traffic() to later handle */ - received_frame = p; - } - } - return true; -} // tud_network_recv_cb - - - -uint16_t tud_network_xmit_cb(uint8_t *dst, void *ref, uint16_t arg) -{ - struct pbuf *p = (struct pbuf *)ref; - - (void)arg; /* unused for this example */ - - return pbuf_copy_partial(p, dst, p->tot_len, 0); -} // tud_network_xmit_cb - - - -static err_t linkoutput_fn(struct netif *netif, struct pbuf *p) -{ - (void)netif; - - for (;;) { - /* if TinyUSB isn't ready, we must signal back to lwip that there is nothing we can do */ - if (!tud_ready()) - return ERR_USE; - - /* if the network driver can accept another packet, we make it happen */ - if (tud_network_can_xmit(p->tot_len)) { - tud_network_xmit(p, 0 /* unused for this example */); - return ERR_OK; - } - - /* transfer execution to TinyUSB in the hopes that it will finish transmitting the prior packet */ - tud_task(); - } -} // linkoutput_fn - - - -static err_t ip4_output_fn(struct netif *netif, struct pbuf *p, const ip4_addr_t *addr) -{ - return etharp_output(netif, p, addr); -} // ip4_output_fn - - - -static err_t netif_init_cb(struct netif *netif) -{ - LWIP_ASSERT("netif != NULL", (netif != NULL)); - netif->mtu = CFG_TUD_NET_MTU; - netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP | NETIF_FLAG_UP; - netif->state = NULL; - netif->name[0] = 'E'; - netif->name[1] = 'X'; - netif->linkoutput = linkoutput_fn; - netif->output = ip4_output_fn; - return ERR_OK; -} // netif_init_cb - - - -static void init_lwip(void) -{ - struct netif *netif = &netif_data; - - lwip_init(); - - /* the lwip virtual MAC address must be different from the host's; to ensure this, we toggle the LSbit */ - netif->hwaddr_len = sizeof(tud_network_mac_address); - memcpy(netif->hwaddr, tud_network_mac_address, sizeof(tud_network_mac_address)); - netif->hwaddr[5] ^= 0x01; - - netif = netif_add(netif, &ipaddr, &netmask, &gateway, NULL, netif_init_cb, ip_input); - netif_set_default(netif); - - while ( !netif_is_up(&netif_data)) - ; -#if 0 - while (dhserv_init(&dhcp_config) != ERR_OK) - ; - while (dnserv_init(IP_ADDR_ANY, 53, dns_query_proc) != ERR_OK) - ; -#endif -} // init_lwip - - -#endif - -//---------------------------------------------------------------------------------------------------------------------- - - - void rtt_console_init(uint32_t task_prio) { picoprobe_debug("rtt_console_init()\n"); @@ -559,8 +352,4 @@ void rtt_console_init(uint32_t task_prio) { picoprobe_error("rtt_console_init: cannot create task_rtt_console\n"); } - -#if OPT_SYSVIEW_RNDIS - init_lwip(); -#endif } // rtt_console_init From 17e50687a993157d66a635d5b0c7458546959dc1 Mon Sep 17 00:00:00 2001 From: Hardy Griech Date: Wed, 3 May 2023 08:39:03 +0200 Subject: [PATCH 007/118] wip: RNDIS under Windows works only if there is just a single RNDIS and no other class --- include/lwipopts.h | 34 ++-- include/tusb_config.h | 2 +- src/net_starter.c | 409 ++++++++++++++++++++++++++++++++++++++---- src/usb_descriptors.c | 29 ++- 4 files changed, 417 insertions(+), 57 deletions(-) diff --git a/include/lwipopts.h b/include/lwipopts.h index 95053c345..a1462a0ce 100755 --- a/include/lwipopts.h +++ b/include/lwipopts.h @@ -35,10 +35,10 @@ /* Prevent having to link sys_arch.c (we don't test the API layers in unit tests) */ #define NO_SYS 1 #define MEM_ALIGNMENT 4 -#define LWIP_RAW 1 +#define LWIP_RAW 0 #define LWIP_NETCONN 0 #define LWIP_SOCKET 0 -#define LWIP_DHCP 1 +#define LWIP_DHCP 0 #define LWIP_ICMP 1 #define LWIP_UDP 1 #define LWIP_TCP 1 @@ -49,7 +49,7 @@ #define TCP_MSS (1500 /*mtu*/ - 20 /*iphdr*/ - 20 /*tcphhr*/) #define TCP_SND_BUF (2 * TCP_MSS) -#define TCP_WND (TCP_MSS) +//#define TCP_WND (TCP_MSS) #define ETHARP_SUPPORT_STATIC_ENTRIES 1 @@ -59,20 +59,20 @@ #define LWIP_SINGLE_NETIF 1 -#define PBUF_POOL_SIZE 2 - -#define HTTPD_USE_CUSTOM_FSDATA 0 - -#define LWIP_MULTICAST_PING 1 -#define LWIP_BROADCAST_PING 1 -#define LWIP_IPV6_MLD 0 -#define LWIP_IPV6_SEND_ROUTER_SOLICIT 0 - -#define LWIP_PROVIDE_ERRNO 1 - - -// meine Versuche -#define LWIP_TCPIP_CORE_LOCKING 1 +//#define PBUF_POOL_SIZE 2 +// +//#define HTTPD_USE_CUSTOM_FSDATA 0 +// +//#define LWIP_MULTICAST_PING 1 +//#define LWIP_BROADCAST_PING 1 +//#define LWIP_IPV6_MLD 0 +//#define LWIP_IPV6_SEND_ROUTER_SOLICIT 0 +// +//#define LWIP_PROVIDE_ERRNO 1 +// +// +//// meine Versuche +//#define LWIP_TCPIP_CORE_LOCKING 1 diff --git a/include/tusb_config.h b/include/tusb_config.h index e72650c77..38e6362a3 100644 --- a/include/tusb_config.h +++ b/include/tusb_config.h @@ -89,7 +89,7 @@ #define CFG_TUD_MSC 1 // DAPLink drive #define CFG_TUD_CDC (CFG_TUD_CDC_UART + CFG_TUD_CDC_SIGROK + CFG_TUD_CDC_DEBUG) #if OPT_SYSVIEW_RNDIS - #define CFG_TUD_ECM_RNDIS 1 + #define CFG_TUD_ECM_RNDIS 0 // RNDIS under Windows works only if it's the only class, so we try NCM for Linux #define CFG_TUD_NCM (1 - CFG_TUD_ECM_RNDIS) #else #define CFG_TUD_ECM_RNDIS 0 diff --git a/src/net_starter.c b/src/net_starter.c index 51e37fe99..d1727cfea 100755 --- a/src/net_starter.c +++ b/src/net_starter.c @@ -60,7 +60,7 @@ static struct pbuf *received_frame; #define INIT_IP4(a,b,c,d) { PP_HTONL(LWIP_MAKEU32(a,b,c,d)) } /* network parameters of this MCU */ -static const ip4_addr_t ipaddr = INIT_IP4(192, 168, 7, 5); +static const ip4_addr_t ipaddr = INIT_IP4(192, 168, 7, 1); static const ip4_addr_t netmask = INIT_IP4(255, 255, 255, 0); static const ip4_addr_t gateway = INIT_IP4(0, 0, 0, 0); @@ -75,9 +75,9 @@ static dhcp_entry_t entries[] = static const dhcp_config_t dhcp_config = { - .router = INIT_IP4(192, 168, 0, 1), /* router address (if any) */ + .router = INIT_IP4(0, 0, 0, 0), /* router address (if any) */ .port = 67, /* listen port */ - .dns = INIT_IP4(192, 168, 0, 1), /* dns server (if any) */ + .dns = INIT_IP4(0, 0, 0, 0), /* dns server (if any) */ "usb", /* dns suffix */ TU_ARRAY_SIZE(entries), /* num entry */ entries /* entries */ @@ -86,6 +86,332 @@ static const dhcp_config_t dhcp_config = static TaskHandle_t task_net_starter = NULL; +//---------------------------------------------------------------------------------------------------------------------- +#if 1 + +#include "lwip/debug.h" +#include "lwip/stats.h" +#include "lwip/tcp.h" + + +static struct tcp_pcb *echo_pcb; + +enum echo_states +{ + ES_NONE = 0, + ES_ACCEPTED, + ES_RECEIVED, + ES_CLOSING +}; + +struct echo_state +{ + u8_t state; + u8_t retries; + struct tcp_pcb *pcb; + /* pbuf (chain) to recycle */ + struct pbuf *p; +}; + +err_t echo_accept(void *arg, struct tcp_pcb *newpcb, err_t err); +err_t echo_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err); +void echo_error(void *arg, err_t err); +err_t echo_poll(void *arg, struct tcp_pcb *tpcb); +err_t echo_sent(void *arg, struct tcp_pcb *tpcb, u16_t len); +void echo_send(struct tcp_pcb *tpcb, struct echo_state *es); +void echo_close(struct tcp_pcb *tpcb, struct echo_state *es); + +void +echo_init(void) +{ + printf("!!!!!!!!!!!!!!!!!!!! echo_init\n"); + echo_pcb = tcp_new(); + if (echo_pcb != NULL) + { + err_t err; + + err = tcp_bind(echo_pcb, IP_ADDR_ANY, 7); + if (err == ERR_OK) + { + echo_pcb = tcp_listen(echo_pcb); + tcp_accept(echo_pcb, echo_accept); + } + else + { + /* abort? output diagnostic? */ + printf("!!!!!!!!!!!!!!!!!!!! cannot bind\n"); + } + } + else + { + /* abort? output diagnostic? */ + printf("!!!!!!!!!!!!!!!!!!!! tcp_new\n"); + } +} + + +err_t +echo_accept(void *arg, struct tcp_pcb *newpcb, err_t err) +{ + err_t ret_err; + struct echo_state *es; + + LWIP_UNUSED_ARG(arg); + LWIP_UNUSED_ARG(err); + + /* commonly observed practive to call tcp_setprio(), why? */ + tcp_setprio(newpcb, TCP_PRIO_MIN); + + es = (struct echo_state *)mem_malloc(sizeof(struct echo_state)); + if (es != NULL) + { + es->state = ES_ACCEPTED; + es->pcb = newpcb; + es->retries = 0; + es->p = NULL; + /* pass newly allocated es to our callbacks */ + tcp_arg(newpcb, es); + tcp_recv(newpcb, echo_recv); + tcp_err(newpcb, echo_error); + tcp_poll(newpcb, echo_poll, 0); + ret_err = ERR_OK; + } + else + { + ret_err = ERR_MEM; + } + return ret_err; +} + +err_t +echo_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) +{ + struct echo_state *es; + err_t ret_err; + + LWIP_ASSERT("arg != NULL",arg != NULL); + es = (struct echo_state *)arg; + if (p == NULL) + { + /* remote host closed connection */ + es->state = ES_CLOSING; + if(es->p == NULL) + { + /* we're done sending, close it */ + echo_close(tpcb, es); + } + else + { + /* we're not done yet */ + tcp_sent(tpcb, echo_sent); + echo_send(tpcb, es); + } + ret_err = ERR_OK; + } + else if(err != ERR_OK) + { + /* cleanup, for unkown reason */ + if (p != NULL) + { + es->p = NULL; + pbuf_free(p); + } + ret_err = err; + } + else if(es->state == ES_ACCEPTED) + { + /* first data chunk in p->payload */ + es->state = ES_RECEIVED; + /* store reference to incoming pbuf (chain) */ + es->p = p; + /* install send completion notifier */ + tcp_sent(tpcb, echo_sent); + echo_send(tpcb, es); + ret_err = ERR_OK; + } + else if (es->state == ES_RECEIVED) + { + /* read some more data */ + if(es->p == NULL) + { + es->p = p; + tcp_sent(tpcb, echo_sent); + echo_send(tpcb, es); + } + else + { + struct pbuf *ptr; + + /* chain pbufs to the end of what we recv'ed previously */ + ptr = es->p; + pbuf_chain(ptr,p); + } + ret_err = ERR_OK; + } + else if(es->state == ES_CLOSING) + { + /* odd case, remote side closing twice, trash data */ + tcp_recved(tpcb, p->tot_len); + es->p = NULL; + pbuf_free(p); + ret_err = ERR_OK; + } + else + { + /* unkown es->state, trash data */ + tcp_recved(tpcb, p->tot_len); + es->p = NULL; + pbuf_free(p); + ret_err = ERR_OK; + } + return ret_err; +} + +void +echo_error(void *arg, err_t err) +{ + struct echo_state *es; + + LWIP_UNUSED_ARG(err); + + es = (struct echo_state *)arg; + if (es != NULL) + { + mem_free(es); + } +} + +err_t +echo_poll(void *arg, struct tcp_pcb *tpcb) +{ + err_t ret_err; + struct echo_state *es; + + es = (struct echo_state *)arg; + if (es != NULL) + { + if (es->p != NULL) + { + /* there is a remaining pbuf (chain) */ + tcp_sent(tpcb, echo_sent); + echo_send(tpcb, es); + } + else + { + /* no remaining pbuf (chain) */ + if(es->state == ES_CLOSING) + { + echo_close(tpcb, es); + } + } + ret_err = ERR_OK; + } + else + { + /* nothing to be done */ + tcp_abort(tpcb); + ret_err = ERR_ABRT; + } + return ret_err; +} + +err_t +echo_sent(void *arg, struct tcp_pcb *tpcb, u16_t len) +{ + struct echo_state *es; + + LWIP_UNUSED_ARG(len); + + es = (struct echo_state *)arg; + es->retries = 0; + + if(es->p != NULL) + { + /* still got pbufs to send */ + tcp_sent(tpcb, echo_sent); + echo_send(tpcb, es); + } + else + { + /* no more pbufs to send */ + if(es->state == ES_CLOSING) + { + echo_close(tpcb, es); + } + } + return ERR_OK; +} + +void +echo_send(struct tcp_pcb *tpcb, struct echo_state *es) +{ + struct pbuf *ptr; + err_t wr_err = ERR_OK; + + while ((wr_err == ERR_OK) && + (es->p != NULL) && + (es->p->len <= tcp_sndbuf(tpcb))) + { + ptr = es->p; + + /* enqueue data for transmission */ + wr_err = tcp_write(tpcb, ptr->payload, ptr->len, 1); + if (wr_err == ERR_OK) + { + u16_t plen; + u8_t freed; + + plen = ptr->len; + /* continue with next pbuf in chain (if any) */ + es->p = ptr->next; + if(es->p != NULL) + { + /* new reference! */ + pbuf_ref(es->p); + } + /* chop first pbuf from chain */ + do + { + /* try hard to free pbuf */ + freed = pbuf_free(ptr); + } + while(freed == 0); + /* we can read more data now */ + tcp_recved(tpcb, plen); + } + else if(wr_err == ERR_MEM) + { + /* we are low on memory, try later / harder, defer to poll */ + es->p = ptr; + } + else + { + /* other problem ?? */ + } + } +} + +void +echo_close(struct tcp_pcb *tpcb, struct echo_state *es) +{ + tcp_arg(tpcb, NULL); + tcp_sent(tpcb, NULL); + tcp_recv(tpcb, NULL); + tcp_err(tpcb, NULL); + tcp_poll(tpcb, NULL, 0); + + if (es != NULL) + { + mem_free(es); + } + tcp_close(tpcb); +} +#endif + + +//---------------------------------------------------------------------------------------------------------------------- + + #if 0 static void service_traffic(void) @@ -130,6 +456,7 @@ void tud_network_init_cb(void) received_frame = NULL; } +#if 0 printf("tud_network_init_cb() a\n"); while ( !netif_is_up(&netif_data)) ; @@ -139,6 +466,7 @@ void tud_network_init_cb(void) printf("tud_network_init_cb() c\n"); while (dnserv_init(IP_ADDR_ANY, 53, dns_query_proc) != ERR_OK) ; +#endif printf("tud_network_init_cb() d\n"); } // tud_network_init_cb @@ -146,7 +474,7 @@ void tud_network_init_cb(void) bool tud_network_recv_cb(const uint8_t *src, uint16_t size) { - printf("tud_network_recv_cb()\n"); + printf("tud_network_recv_cb(%p,%u)\n", src, size); /* this shouldn't happen, but if we get another packet before parsing the previous, we must signal our inability to accept it */ @@ -171,7 +499,7 @@ bool tud_network_recv_cb(const uint8_t *src, uint16_t size) uint16_t tud_network_xmit_cb(uint8_t *dst, void *ref, uint16_t arg) { - printf("tud_network_xmit_cb()\n"); + printf("tud_network_xmit_cb(%p,%p,%u)\n", dst, ref, arg); struct pbuf *p = (struct pbuf *)ref; @@ -182,11 +510,18 @@ uint16_t tud_network_xmit_cb(uint8_t *dst, void *ref, uint16_t arg) -static err_t linkoutput_fn(struct netif *netif, struct pbuf *p) +void tud_network_link_state_cb(bool state) +{ + printf("tud_network_link_state_cb(%d)\n", state); +} // tud_network_link_state_cb + + + +static err_t my_linkoutput_fn(struct netif *netif, struct pbuf *p) { (void)netif; - printf("linkoutput_fn()\n"); + printf("my_linkoutput_fn()\n"); for (;;) { /* if TinyUSB isn't ready, we must signal back to lwip that there is nothing we can do */ @@ -202,34 +537,51 @@ static err_t linkoutput_fn(struct netif *netif, struct pbuf *p) /* transfer execution to TinyUSB in the hopes that it will finish transmitting the prior packet */ tud_task(); } -} // linkoutput_fn +} // my_linkoutput_fn -static err_t ip4_output_fn(struct netif *netif, struct pbuf *p, const ip4_addr_t *addr) +static err_t my_ip4_output_fn(struct netif *netif, struct pbuf *p, const ip4_addr_t *addr) { - printf("ip4_output_fn()\n"); + printf("my_ip4_output_fn()\n"); return etharp_output(netif, p, addr); -} // ip4_output_fn +} // my_ip4_output_fn + + + +err_t my_ip_input(struct pbuf *p, struct netif *inp) +{ + printf("my_ip_input(%p,%p)\n", p, inp); + if (p != NULL) { + if (IP_HDR_GET_VERSION(p->payload) == 6) { + printf("my_ip_input 6\n"); + //return ip6_input(p, inp); + return ERR_ABRT; + } + printf("my_ip_input 4\n"); + return ip4_input(p, inp); + } + return ERR_VAL; +} // my_ip_input -static err_t netif_init_cb(struct netif *netif) +static err_t my_netif_init_cb(struct netif *netif) { - printf("netif_init_cb(%p)\n", netif); + printf("my_netif_init_cb(%p)\n", netif); LWIP_ASSERT("netif != NULL", (netif != NULL)); netif->mtu = CFG_TUD_NET_MTU; netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP | NETIF_FLAG_UP; - netif->hwaddr_len = ETHARP_HWADDR_LEN; + //netif->hwaddr_len = ETHARP_HWADDR_LEN; netif->state = NULL; netif->name[0] = 'E'; netif->name[1] = 'X'; - netif->linkoutput = linkoutput_fn; - netif->output = ip4_output_fn; + netif->linkoutput = my_linkoutput_fn; + netif->output = my_ip4_output_fn; return ERR_OK; -} // netif_init_cb +} // my_netif_init_cb @@ -248,13 +600,13 @@ static void init_lwip(void) #if 0 netif->hwaddr_len = sizeof(tud_network_mac_address); memcpy(netif->hwaddr, tud_network_mac_address, sizeof(tud_network_mac_address)); - //netif->hwaddr[5] ^= 0x01; #else netif->hwaddr_len = NETIF_MAX_HWADDR_LEN; memcpy(netif->hwaddr, tud_network_mac_address, NETIF_MAX_HWADDR_LEN); #endif + netif->hwaddr[5] ^= 0x01; - netif = netif_add(netif, &ipaddr, &netmask, &gateway, NULL, netif_init_cb, ip_input); + netif = netif_add(netif, &ipaddr, &netmask, &gateway, NULL, my_netif_init_cb, my_ip_input); printf("init_lwip() - %p\n", netif); netif_set_default(netif); @@ -262,12 +614,14 @@ static void init_lwip(void) printf("init_lwip() a\n"); while ( !netif_is_up(&netif_data)) printf("init_lwip() ax\n"); +#if 1 printf("init_lwip() b\n"); while (dhserv_init(&dhcp_config) != ERR_OK) printf("init_lwip() bx\n"); printf("init_lwip() c\n"); while (dnserv_init(IP_ADDR_ANY, 53, dns_query_proc) != ERR_OK) printf("init_lwip() cx\n"); +#endif #endif printf("init_lwip() d\n"); } // init_lwip @@ -276,20 +630,9 @@ static void init_lwip(void) void net_starter_thread(void *ptr) { - vTaskDelay(pdMS_TO_TICKS(20)); + vTaskDelay(pdMS_TO_TICKS(2000)); -#if 0 - printf("net_starter_thread() a\n"); - while ( !netif_is_up(&netif_data)) - ; - printf("net_starter_thread() b\n"); - while (dhserv_init(&dhcp_config) != ERR_OK) - printf("net_starter_thread() bx\n"); - printf("net_starter_thread() c\n"); - while (dnserv_init(IP_ADDR_ANY, 53, dns_query_proc) != ERR_OK) - printf("net_starter_thread() cx\n"); - printf("net_starter_thread() d\n"); -#endif + echo_init(); for (;;) { vTaskDelay(pdMS_TO_TICKS(200)); @@ -313,7 +656,7 @@ void net_starter_init(uint32_t task_prio) { printf("net_starter_init()\n"); - tud_init(0); + //tud_init(0); init_lwip(); #if 0 diff --git a/src/usb_descriptors.c b/src/usb_descriptors.c index 1a7cc122f..9061d1428 100644 --- a/src/usb_descriptors.c +++ b/src/usb_descriptors.c @@ -32,7 +32,7 @@ #if OPT_SYSVIEW_RNDIS - uint8_t tud_network_mac_address[6] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; + uint8_t tud_network_mac_address[6] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x89}; #endif @@ -40,6 +40,9 @@ // String enums //--------------------------------------------------------------------+ +// 0 -> ECM, OPT_SYSVIEW_RNDIS must be enabled +#define USE_RNDIS 0 + enum { STRID_LANGID = 0, @@ -105,7 +108,7 @@ tusb_desc_device_t const desc_device = { .bLength = sizeof(tusb_desc_device_t), .bDescriptorType = TUSB_DESC_DEVICE, - .bcdUSB = 0x0210, // USB Specification version 2.1 for BOS + .bcdUSB = 0x0200, // USB Specification version 2.1 for BOS (DAPv2) under Windows // Use Interface Association Descriptor (IAD) device class .bDeviceClass = TUSB_CLASS_MISC, @@ -233,10 +236,17 @@ enum #endif +#if USE_RNDIS #define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + CFG_TUD_CDC*TUD_CDC_DESC_LEN + CFG_TUD_VENDOR*TUD_VENDOR_DESC_LEN \ + CFG_TUD_HID*TUD_HID_INOUT_DESC_LEN + CFG_TUD_MSC*TUD_MSC_DESC_LEN \ + CFG_TUD_ECM_RNDIS*TUD_RNDIS_DESC_LEN \ + CFG_TUD_NCM*TUD_CDC_NCM_DESC_LEN) +#else +#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + CFG_TUD_CDC*TUD_CDC_DESC_LEN + CFG_TUD_VENDOR*TUD_VENDOR_DESC_LEN \ + + CFG_TUD_HID*TUD_HID_INOUT_DESC_LEN + CFG_TUD_MSC*TUD_MSC_DESC_LEN \ + + CFG_TUD_ECM_RNDIS*TUD_CDC_ECM_DESC_LEN \ + + CFG_TUD_NCM*TUD_CDC_NCM_DESC_LEN) +#endif #if CFG_TUD_HID static uint8_t const desc_hid_report[] = @@ -283,9 +293,12 @@ static uint8_t const desc_configuration[] = #endif #if OPT_SYSVIEW_RNDIS #if CFG_TUD_ECM_RNDIS - TUD_RNDIS_DESCRIPTOR(ITF_NUM_CDC_RNDIS_COM, STRID_INTERFACE_RNDIS, CDC_RNDIS_NOTIFICATION_EP_NUM, 8, CDC_RNDIS_DATA_OUT_EP_NUM, CDC_RNDIS_DATA_IN_EP_NUM, 64), - // TODO ECM must be an alternative to RNDIS, RNDIS works on Windows, ECM on iOS, Linux can handle both!? - // TUD_CDC_ECM_DESCRIPTOR(ITF_NUM_CDC_RNDIS_COM, STRID_INTERFACE_RNDIS, STRID_MAC, CDC_RNDIS_NOTIFICATION_EP_NUM, 64, CDC_RNDIS_DATA_OUT_EP_NUM, CDC_RNDIS_DATA_IN_EP_NUM, 64, CFG_TUD_NET_MTU), + #if USE_RNDIS + TUD_RNDIS_DESCRIPTOR(ITF_NUM_CDC_RNDIS_COM, STRID_INTERFACE_RNDIS, CDC_RNDIS_NOTIFICATION_EP_NUM, 8, CDC_RNDIS_DATA_OUT_EP_NUM, CDC_RNDIS_DATA_IN_EP_NUM, 64), + #else + // TODO ECM must be an alternative to RNDIS, RNDIS works on Windows, ECM on iOS, Linux can handle both!? + TUD_CDC_ECM_DESCRIPTOR(ITF_NUM_CDC_RNDIS_COM, STRID_INTERFACE_RNDIS, STRID_MAC, CDC_RNDIS_NOTIFICATION_EP_NUM, 64, CDC_RNDIS_DATA_OUT_EP_NUM, CDC_RNDIS_DATA_IN_EP_NUM, 64, CFG_TUD_NET_MTU), + #endif #else TUD_CDC_NCM_DESCRIPTOR(ITF_NUM_CDC_NCM_COM, STRID_INTERFACE_RNDIS, STRID_MAC, CDC_NCM_NOTIFICATION_EP_NUM, 64, CDC_NCM_DATA_OUT_EP_NUM, CDC_NCM_DATA_IN_EP_NUM, 64, CFG_TUD_NET_MTU), #endif @@ -324,7 +337,11 @@ static char const* string_desc_arr[] = [STRID_INTERFACE_CDC_DEBUG] = "YAPicoprobe CDC-DEBUG", // Interface descriptor for CDC DEBUG #if OPT_SYSVIEW_RNDIS #if CFG_TUD_ECM_RNDIS - [STRID_INTERFACE_RNDIS] = "YaPicoprobe SysView RNDIS", // Interface descriptor for SysView RNDIS + #if USE_RNDIS + [STRID_INTERFACE_RNDIS] = "YaPicoprobe SysView RNDIS", // Interface descriptor for SysView RNDIS + #else + [STRID_INTERFACE_RNDIS] = "YaPicoprobe SysView ECM", // Interface descriptor for SysView RNDIS + #endif #else [STRID_INTERFACE_RNDIS] = "YaPicoprobe SysView NCM", // Interface descriptor for SysView NCM #endif From 20054d2509a422305fbad43c3ac2ababe962606e Mon Sep 17 00:00:00 2001 From: Hardy Griech Date: Wed, 3 May 2023 08:41:56 +0200 Subject: [PATCH 008/118] bcdUSB must be 2.1 for CMSIS-DAPv2 (under Windows) --- src/usb_descriptors.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/usb_descriptors.c b/src/usb_descriptors.c index 9061d1428..4fff98a24 100644 --- a/src/usb_descriptors.c +++ b/src/usb_descriptors.c @@ -108,7 +108,7 @@ tusb_desc_device_t const desc_device = { .bLength = sizeof(tusb_desc_device_t), .bDescriptorType = TUSB_DESC_DEVICE, - .bcdUSB = 0x0200, // USB Specification version 2.1 for BOS (DAPv2) under Windows + .bcdUSB = 0x0210, // USB Specification version 2.1 for BOS (DAPv2) under Windows // Use Interface Association Descriptor (IAD) device class .bDeviceClass = TUSB_CLASS_MISC, From d93d3dd23b3177a67dcf03b8f7b7b770be2a5b9b Mon Sep 17 00:00:00 2001 From: Hardy Griech Date: Sat, 6 May 2023 12:31:46 +0200 Subject: [PATCH 009/118] this version has a working lwip, culprit was the MAC :-/ --- CMakeLists.txt | 2 +- README.adoc | 5 +- include/arch/cc.h | 26 ------ include/lwipopts.h | 33 ++++---- include/tusb_config.h | 5 +- src/get_serial.c | 17 +++- src/get_serial.h | 4 + src/net_starter.c | 184 ++++++++++++++++++++++++++---------------- src/usb_descriptors.c | 132 +++++++++++++----------------- 9 files changed, 216 insertions(+), 192 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 562746ad4..463ecec18 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -204,7 +204,7 @@ if(OPT_SYSVIEW_RNDIS) ) target_link_libraries(${PROJECT} PRIVATE - pico_lwip_nosys + pico_lwip_freertos ) # message("--------- " ${PICO_LWIP_PATH}) diff --git a/README.adoc b/README.adoc index 77edfc84c..26c21d402 100644 --- a/README.adoc +++ b/README.adoc @@ -109,6 +109,9 @@ containing the steps from installation until debugging in VSCode. |`cp firmware.uf2 /media/picoprobe` |=== +NOTE: For best RP2040 support, OpenOCD bundled with PlatformIO is recommended. + See <> + #### Parameter Optimization @@ -355,7 +358,7 @@ ACTION=="add", SUBSYSTEMS=="usb", SUBSYSTEM=="block", ENV{ID_FS_USAGE}=="filesys ACTION=="remove", SUBSYSTEMS=="usb", SUBSYSTEM=="block", ENV{ID_FS_USAGE}=="filesystem", ATTRS{idVendor}=="2e8a", ATTRS{idProduct}=="0003", RUN+="/usr/bin/logger --tag rpi-pico-mount Unmounting what seems to be a Raspberry Pi Pico", RUN+="/usr/bin/systemd-umount /media/pico" ---- -#### PlatformIO +#### PlatformIO [[platformio]] https://platformio.org/[PlatformIO] configuration in `platformio.ini` is pretty straight forward: .PlatformIO configuration diff --git a/include/arch/cc.h b/include/arch/cc.h index 6d504d3c6..ed116576b 100755 --- a/include/arch/cc.h +++ b/include/arch/cc.h @@ -38,37 +38,11 @@ #endif -/* define compiler specific symbols */ -#if defined (__ICCARM__) - -#define PACK_STRUCT_BEGIN -#define PACK_STRUCT_STRUCT -#define PACK_STRUCT_END -#define PACK_STRUCT_FIELD(x) x -#define PACK_STRUCT_USE_INCLUDES - -#elif defined (__CC_ARM) - -#define PACK_STRUCT_BEGIN __packed -#define PACK_STRUCT_STRUCT -#define PACK_STRUCT_END -#define PACK_STRUCT_FIELD(x) x - -#elif defined (__GNUC__) - #define PACK_STRUCT_BEGIN #define PACK_STRUCT_STRUCT __attribute__ ((__packed__)) #define PACK_STRUCT_END #define PACK_STRUCT_FIELD(x) x -#elif defined (__TASKING__) - -#define PACK_STRUCT_BEGIN -#define PACK_STRUCT_STRUCT -#define PACK_STRUCT_END -#define PACK_STRUCT_FIELD(x) x - -#endif #define LWIP_PLATFORM_ASSERT(x) do { if(!(x)) while(1); } while(0) diff --git a/include/lwipopts.h b/include/lwipopts.h index a1462a0ce..77a4a5982 100755 --- a/include/lwipopts.h +++ b/include/lwipopts.h @@ -33,17 +33,17 @@ #define __LWIPOPTS_H__ /* Prevent having to link sys_arch.c (we don't test the API layers in unit tests) */ -#define NO_SYS 1 +#define NO_SYS 0 #define MEM_ALIGNMENT 4 #define LWIP_RAW 0 -#define LWIP_NETCONN 0 +#define LWIP_NETCONN 0 // ???? #define LWIP_SOCKET 0 #define LWIP_DHCP 0 #define LWIP_ICMP 1 #define LWIP_UDP 1 #define LWIP_TCP 1 -#define LWIP_IPV4 1 -#define LWIP_IPV6 0 +//#define LWIP_IPV4 1 +//#define LWIP_IPV6 0 #define ETH_PAD_SIZE 0 #define LWIP_IP_ACCEPT_UDP_PORT(p) ((p) == PP_NTOHS(67)) @@ -53,16 +53,16 @@ #define ETHARP_SUPPORT_STATIC_ENTRIES 1 -#define LWIP_HTTPD_CGI 0 -#define LWIP_HTTPD_SSI 0 -#define LWIP_HTTPD_SSI_INCLUDE_TAG 0 +//#define LWIP_HTTPD_CGI 0 +//#define LWIP_HTTPD_SSI 0 +//#define LWIP_HTTPD_SSI_INCLUDE_TAG 0 #define LWIP_SINGLE_NETIF 1 //#define PBUF_POOL_SIZE 2 -// -//#define HTTPD_USE_CUSTOM_FSDATA 0 -// +//// +////#define HTTPD_USE_CUSTOM_FSDATA 0 +//// //#define LWIP_MULTICAST_PING 1 //#define LWIP_BROADCAST_PING 1 //#define LWIP_IPV6_MLD 0 @@ -73,25 +73,30 @@ // //// meine Versuche //#define LWIP_TCPIP_CORE_LOCKING 1 - +#define LWIP_PROVIDE_ERRNO 1 +#define TCPIP_MBOX_SIZE 32 +#define TCPIP_THREAD_STACKSIZE 2048 +#define TCPIP_THREAD_PRIO 10 +//#define LWIP_ETHERNET 1 // bringt nix +//#define LWIP_ARP 1 // bringt nix // Debugging (was sonst?) -#define LWIP_DEBUG +//#define LWIP_DEBUG #define API_LIB_DEBUG LWIP_DBG_ON #define API_MSG_DEBUG LWIP_DBG_ON #define AUTOIP_DEBUG LWIP_DBG_ON #define DHCP_DEBUG LWIP_DBG_ON #define DNS_DEBUG LWIP_DBG_ON -#define ETHARP_DEBUG LWIP_DBG_ON +#define ETHARP_DEBUG LWIP_DBG_OFF #define ICMP_DEBUG LWIP_DBG_ON #define IGMP_DEBUG LWIP_DBG_ON #define INET_DEBUG LWIP_DBG_ON #define IP_DEBUG LWIP_DBG_ON #define NETIF_DEBUG LWIP_DBG_ON -#define PBUF_DEBUG LWIP_DBG_ON +#define PBUF_DEBUG LWIP_DBG_OFF #define RAW_DEBUG LWIP_DBG_ON #define SLIP_DEBUG LWIP_DBG_ON #define SOCKETS_DEBUG LWIP_DBG_ON diff --git a/include/tusb_config.h b/include/tusb_config.h index 38e6362a3..c26fe0885 100644 --- a/include/tusb_config.h +++ b/include/tusb_config.h @@ -89,7 +89,8 @@ #define CFG_TUD_MSC 1 // DAPLink drive #define CFG_TUD_CDC (CFG_TUD_CDC_UART + CFG_TUD_CDC_SIGROK + CFG_TUD_CDC_DEBUG) #if OPT_SYSVIEW_RNDIS - #define CFG_TUD_ECM_RNDIS 0 // RNDIS under Windows works only if it's the only class, so we try NCM for Linux + // lsusb output of NCM looks the same as setup from lwip webserver example + #define CFG_TUD_ECM_RNDIS 1 // RNDIS under Windows works only if it's the only class, so we try NCM for Linux #define CFG_TUD_NCM (1 - CFG_TUD_ECM_RNDIS) #else #define CFG_TUD_ECM_RNDIS 0 @@ -116,7 +117,7 @@ #define CFG_TUD_MSC_EP_BUFSIZE 512 #if OPT_SYSVIEW_RNDIS - #define CFG_TUD_NET_MTU 1500 + #define CFG_TUD_NET_MTU 1514 extern uint8_t tud_network_mac_address[6]; #endif diff --git a/src/get_serial.c b/src/get_serial.c index 04bf77a33..13ca0505e 100644 --- a/src/get_serial.c +++ b/src/get_serial.c @@ -28,16 +28,29 @@ #include "pico/unique_id.h" #include "get_serial.h" + /* C string for iSerialNumber in USB Device Descriptor, two chars per byte + terminating NUL */ char usb_serial[PICO_UNIQUE_BOARD_ID_SIZE_BYTES * 2 + 1]; -/* Why a uint8_t[8] array inside a struct instead of an uint64_t an inquiring mind might wonder */ -static pico_unique_board_id_t uID; +#if OPT_SYSVIEW_RNDIS + uint8_t tud_network_mac_address[6]; +#endif + void usb_serial_init(void) { + pico_unique_board_id_t uID; + pico_get_unique_board_id(&uID); +#if OPT_SYSVIEW_RNDIS + tud_network_mac_address[0] = 0x02; // never ever use 0x11 here! + for (int i = 1; i < sizeof(tud_network_mac_address); ++i) + { + tud_network_mac_address[i] = uID.id[PICO_UNIQUE_BOARD_ID_SIZE_BYTES - i]; + } +#endif + for (int i = 0; i < PICO_UNIQUE_BOARD_ID_SIZE_BYTES * 2; i++) { /* Byte index inside the uid array */ diff --git a/src/get_serial.h b/src/get_serial.h index ebad45ed0..39c10dc63 100644 --- a/src/get_serial.h +++ b/src/get_serial.h @@ -29,6 +29,10 @@ /* Contains unique serial number string (NUL terminated) after call to init_usb_serial */ extern char usb_serial[]; +#if OPT_SYSVIEW_RNDIS + extern uint8_t tud_network_mac_address[]; +#endif + /* Fills unique_serial with the flash unique id */ extern void usb_serial_init(void); diff --git a/src/net_starter.c b/src/net_starter.c index d1727cfea..ccb37c2b2 100755 --- a/src/net_starter.c +++ b/src/net_starter.c @@ -38,13 +38,24 @@ #include "picoprobe_config.h" -#include "lwip/init.h" -#include "lwip/ip.h" -#include "lwip/etharp.h" -#include "lwip/tcpip.h" -#include "lwip/timeouts.h" -#include "dhserver.h" -#include "dnserver.h" +#if 0 + #include "lwip/init.h" + #include "lwip/ip.h" + #include "lwip/etharp.h" + #include "lwip/ethip6.h" + #include "lwip/tcpip.h" + #include "lwip/timeouts.h" +#else + #include "lwip/init.h" + #include "lwip/timeouts.h" + #include "lwip/ethip6.h" + + #include "lwip/tcpip.h" +#endif +#if LWIP_IPV4 + #include "dhserver.h" + #include "dnserver.h" +#endif #include "FreeRTOS.h" #include "tusb.h" @@ -57,31 +68,31 @@ static struct netif netif_data; /* shared between tud_network_recv_cb() and service_traffic() */ static struct pbuf *received_frame; -#define INIT_IP4(a,b,c,d) { PP_HTONL(LWIP_MAKEU32(a,b,c,d)) } - -/* network parameters of this MCU */ -static const ip4_addr_t ipaddr = INIT_IP4(192, 168, 7, 1); -static const ip4_addr_t netmask = INIT_IP4(255, 255, 255, 0); -static const ip4_addr_t gateway = INIT_IP4(0, 0, 0, 0); +#if LWIP_IPV4 + /* network parameters of this MCU */ + static const ip4_addr_t ipaddr = IPADDR4_INIT_BYTES(192, 168, 10, 1); + static const ip4_addr_t netmask = IPADDR4_INIT_BYTES(255, 255, 255, 0); + static const ip4_addr_t gateway = IPADDR4_INIT_BYTES(0, 0, 0, 0); -/* database IP addresses that can be offered to the host; this must be in RAM to store assigned MAC addresses */ -static dhcp_entry_t entries[] = -{ - /* mac ip address lease time */ - { {0}, INIT_IP4(192, 168, 7, 2), 24 * 60 * 60 }, - { {0}, INIT_IP4(192, 168, 7, 3), 24 * 60 * 60 }, - { {0}, INIT_IP4(192, 168, 7, 4), 24 * 60 * 60 }, -}; + /* database IP addresses that can be offered to the host; this must be in RAM to store assigned MAC addresses */ + static dhcp_entry_t entries[] = + { + /* mac ip address lease time */ + { {0}, IPADDR4_INIT_BYTES(192, 168, 10, 2), 24 * 60 * 60 }, + { {0}, IPADDR4_INIT_BYTES(192, 168, 10, 3), 24 * 60 * 60 }, + { {0}, IPADDR4_INIT_BYTES(192, 168, 10, 4), 24 * 60 * 60 }, + }; -static const dhcp_config_t dhcp_config = -{ - .router = INIT_IP4(0, 0, 0, 0), /* router address (if any) */ - .port = 67, /* listen port */ - .dns = INIT_IP4(0, 0, 0, 0), /* dns server (if any) */ - "usb", /* dns suffix */ - TU_ARRAY_SIZE(entries), /* num entry */ - entries /* entries */ -}; + static const dhcp_config_t dhcp_config = + { + .router = IPADDR4_INIT_BYTES(0, 0, 0, 0), /* router address (if any) */ + .port = 67, /* listen port */ + .dns = IPADDR4_INIT_BYTES(0, 0, 0, 0), /* dns server (if any) */ + "usb", /* dns suffix */ + TU_ARRAY_SIZE(entries), /* num entry */ + entries /* entries */ + }; +#endif static TaskHandle_t task_net_starter = NULL; @@ -431,6 +442,7 @@ static void service_traffic(void) +#if LWIP_IPV4 /* handle any DNS requests from dns-server */ bool dns_query_proc(const char *name, ip4_addr_t *addr) { @@ -442,12 +454,13 @@ bool dns_query_proc(const char *name, ip4_addr_t *addr) } return false; } // dns_query_proc +#endif void tud_network_init_cb(void) { - printf("tud_network_init_cb() - %p\n", received_frame); + printf("!!!!!!!!!!!!!!tud_network_init_cb() - %p\n", received_frame); /* if the network is re-initializing and we have a leftover packet, we must do a cleanup */ if (received_frame) @@ -455,18 +468,6 @@ void tud_network_init_cb(void) pbuf_free(received_frame); received_frame = NULL; } - -#if 0 - printf("tud_network_init_cb() a\n"); - while ( !netif_is_up(&netif_data)) - ; - printf("tud_network_init_cb() b\n"); - while (dhserv_init(&dhcp_config) != ERR_OK) - ; - printf("tud_network_init_cb() c\n"); - while (dnserv_init(IP_ADDR_ANY, 53, dns_query_proc) != ERR_OK) - ; -#endif printf("tud_network_init_cb() d\n"); } // tud_network_init_cb @@ -474,7 +475,7 @@ void tud_network_init_cb(void) bool tud_network_recv_cb(const uint8_t *src, uint16_t size) { - printf("tud_network_recv_cb(%p,%u)\n", src, size); + //printf("!!!!!!!!!!!!!!tud_network_recv_cb(%p,%u)\n", src, size); /* this shouldn't happen, but if we get another packet before parsing the previous, we must signal our inability to accept it */ @@ -499,21 +500,43 @@ bool tud_network_recv_cb(const uint8_t *src, uint16_t size) uint16_t tud_network_xmit_cb(uint8_t *dst, void *ref, uint16_t arg) { - printf("tud_network_xmit_cb(%p,%p,%u)\n", dst, ref, arg); + //printf("!!!!!!!!!!!!!!tud_network_xmit_cb(%p,%p,%u)\n", dst, ref, arg); +#if 1 + struct pbuf *p = (struct pbuf *)ref; + struct pbuf *q; + uint16_t len = 0; + + (void)arg; /* unused for this example */ + + /* traverse the "pbuf chain"; see ./lwip/src/core/pbuf.c for more info */ + for (q = p; q != NULL; q = q->next) + { + memcpy(dst, (char *)q->payload, q->len); + dst += q->len; + len += q->len; + if (q->len == q->tot_len) + break; + } + + return len; +#else struct pbuf *p = (struct pbuf *)ref; (void)arg; /* unused for this example */ return pbuf_copy_partial(p, dst, p->tot_len, 0); +#endif } // tud_network_xmit_cb +#if 1 void tud_network_link_state_cb(bool state) { - printf("tud_network_link_state_cb(%d)\n", state); + printf("!!!!!!!!!!!!!!tud_network_link_state_cb(%d)\n", state); } // tud_network_link_state_cb +#endif @@ -521,7 +544,7 @@ static err_t my_linkoutput_fn(struct netif *netif, struct pbuf *p) { (void)netif; - printf("my_linkoutput_fn()\n"); + //printf("my_linkoutput_fn()\n"); for (;;) { /* if TinyUSB isn't ready, we must signal back to lwip that there is nothing we can do */ @@ -535,21 +558,37 @@ static err_t my_linkoutput_fn(struct netif *netif, struct pbuf *p) } /* transfer execution to TinyUSB in the hopes that it will finish transmitting the prior packet */ - tud_task(); +#if NO_SYS + //tud_task(); +#endif } } // my_linkoutput_fn +#if LWIP_IPV4 static err_t my_ip4_output_fn(struct netif *netif, struct pbuf *p, const ip4_addr_t *addr) { - printf("my_ip4_output_fn()\n"); + //printf("my_ip4_output_fn()\n"); return etharp_output(netif, p, addr); } // my_ip4_output_fn +#endif +#if LWIP_IPV6 +static err_t my_ip6_output_fn(struct netif *netif, struct pbuf *p, const ip6_addr_t *addr) +{ + printf("my_ip6_output_fn()\n"); + + return ethip6_output(netif, p, addr); +} // my_ip6_output_fn +#endif + + + +#if 0 err_t my_ip_input(struct pbuf *p, struct netif *inp) { printf("my_ip_input(%p,%p)\n", p, inp); @@ -564,6 +603,7 @@ err_t my_ip_input(struct pbuf *p, struct netif *inp) } return ERR_VAL; } // my_ip_input +#endif @@ -574,12 +614,16 @@ static err_t my_netif_init_cb(struct netif *netif) LWIP_ASSERT("netif != NULL", (netif != NULL)); netif->mtu = CFG_TUD_NET_MTU; netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP | NETIF_FLAG_UP; - //netif->hwaddr_len = ETHARP_HWADDR_LEN; netif->state = NULL; netif->name[0] = 'E'; netif->name[1] = 'X'; netif->linkoutput = my_linkoutput_fn; +#if LWIP_IPV4 netif->output = my_ip4_output_fn; +#endif +#if LWIP_IPV6 + netif->output_ip6 = my_ip6_output_fn; +#endif return ERR_OK; } // my_netif_init_cb @@ -601,27 +645,32 @@ static void init_lwip(void) netif->hwaddr_len = sizeof(tud_network_mac_address); memcpy(netif->hwaddr, tud_network_mac_address, sizeof(tud_network_mac_address)); #else - netif->hwaddr_len = NETIF_MAX_HWADDR_LEN; - memcpy(netif->hwaddr, tud_network_mac_address, NETIF_MAX_HWADDR_LEN); + netif->hwaddr_len = 6; + memcpy(netif->hwaddr, tud_network_mac_address, 6); #endif netif->hwaddr[5] ^= 0x01; - netif = netif_add(netif, &ipaddr, &netmask, &gateway, NULL, my_netif_init_cb, my_ip_input); +#if LWIP_IPV4 + netif = netif_add(netif, &ipaddr, &netmask, &gateway, NULL, my_netif_init_cb, ip_input); +#else + netif = netif_add(netif, NULL, my_netif_init_cb, ip_input); +#endif printf("init_lwip() - %p\n", netif); +#if LWIP_IPV6 + netif_create_ip6_linklocal_address(netif, 1); +#endif netif_set_default(netif); -#if 1 printf("init_lwip() a\n"); - while ( !netif_is_up(&netif_data)) + while ( !netif_is_up(netif)) printf("init_lwip() ax\n"); -#if 1 +#if LWIP_IPV4 printf("init_lwip() b\n"); while (dhserv_init(&dhcp_config) != ERR_OK) printf("init_lwip() bx\n"); printf("init_lwip() c\n"); while (dnserv_init(IP_ADDR_ANY, 53, dns_query_proc) != ERR_OK) printf("init_lwip() cx\n"); -#endif #endif printf("init_lwip() d\n"); } // init_lwip @@ -635,18 +684,21 @@ void net_starter_thread(void *ptr) echo_init(); for (;;) { - vTaskDelay(pdMS_TO_TICKS(200)); + vTaskDelay(pdMS_TO_TICKS(10)); +#if NO_SYS + tud_task(); +#endif /* handle any packet received by tud_network_recv_cb() */ if (received_frame) { - printf("service_traffic(): %p\n", received_frame); + //printf("service_traffic(): %p\n", received_frame); ethernet_input(received_frame, &netif_data); pbuf_free(received_frame); received_frame = NULL; tud_network_recv_renew(); } - sys_check_timeouts(); + //sys_check_timeouts(); } } // net_starter_thread @@ -656,21 +708,13 @@ void net_starter_init(uint32_t task_prio) { printf("net_starter_init()\n"); - //tud_init(0); +#if 1 init_lwip(); -#if 0 - events = xEventGroupCreate(); - - stream_rtt = xStreamBufferCreate(STREAM_RTT_SIZE, STREAM_RTT_TRIGGER); - if (stream_rtt == NULL) { - picoprobe_error("net_starter_init: cannot create stream_rtt\n"); - } -#endif - xTaskCreateAffinitySet(net_starter_thread, "NET_STARTER", configMINIMAL_STACK_SIZE, NULL, task_prio, 1, &task_net_starter); if (task_net_starter == NULL) { picoprobe_error("net_starter_init: cannot create task_net_starter\n"); } +#endif } // net_starter_init diff --git a/src/usb_descriptors.c b/src/usb_descriptors.c index 4fff98a24..25e9e0f01 100644 --- a/src/usb_descriptors.c +++ b/src/usb_descriptors.c @@ -31,17 +31,12 @@ #include "picoprobe_config.h" -#if OPT_SYSVIEW_RNDIS - uint8_t tud_network_mac_address[6] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x89}; -#endif - - //--------------------------------------------------------------------+ // String enums //--------------------------------------------------------------------+ // 0 -> ECM, OPT_SYSVIEW_RNDIS must be enabled -#define USE_RNDIS 0 +#define USE_RNDIS 1 enum { @@ -64,42 +59,6 @@ enum }; -enum -{ -#if CFG_TUD_VENDOR - ITF_NUM_PROBE_VENDOR, // Old versions of Keil MDK only look at interface 0 -#endif -#if CFG_TUD_HID - ITF_NUM_PROBE_HID, -#endif -#if CFG_TUD_CDC_UART - ITF_NUM_CDC_UART_COM, - ITF_NUM_CDC_UART_DATA, -#endif -#if OPT_SIGROK - ITF_NUM_CDC_SIGROK_COM, - ITF_NUM_CDC_SIGROK_DATA, -#endif -#if CFG_TUD_MSC - ITF_NUM_MSC, -#endif -#if CFG_TUD_CDC_DEBUG - ITF_NUM_CDC_DEBUG_COM, - ITF_NUM_CDC_DEBUG_DATA, -#endif -#if OPT_SYSVIEW_RNDIS - #if CFG_TUD_ECM_RNDIS - ITF_NUM_CDC_RNDIS_COM, - ITF_NUM_CDC_RNDIS_DATA, - #else - ITF_NUM_CDC_NCM_COM, - ITF_NUM_CDC_NCM_DATA, - #endif -#endif - ITF_NUM_TOTAL -}; - - //--------------------------------------------------------------------+ // Device Descriptors //--------------------------------------------------------------------+ @@ -130,19 +89,6 @@ tusb_desc_device_t const desc_device = // Application return pointer to descriptor uint8_t const * tud_descriptor_device_cb(void) { -#if OPT_SYSVIEW_RNDIS -#if 0 - static bool initialized; - - if ( !initialized) { - pico_unique_board_id_t id; - - initialized = true; - pico_get_unique_board_id( &id); - memcpy(tud_network_mac_address, &id, sizeof(tud_network_mac_address)); - } -#endif -#endif return (uint8_t const *) &desc_device; } @@ -151,6 +97,42 @@ uint8_t const * tud_descriptor_device_cb(void) // Configuration Descriptor //--------------------------------------------------------------------+ +enum +{ +#if CFG_TUD_VENDOR + ITF_NUM_PROBE_VENDOR, // Old versions of Keil MDK only look at interface 0 +#endif +#if CFG_TUD_HID + ITF_NUM_PROBE_HID, +#endif +#if CFG_TUD_CDC_UART + ITF_NUM_CDC_UART_COM, + ITF_NUM_CDC_UART_DATA, +#endif +#if OPT_SIGROK + ITF_NUM_CDC_SIGROK_COM, + ITF_NUM_CDC_SIGROK_DATA, +#endif +#if CFG_TUD_MSC + ITF_NUM_MSC, +#endif +#if OPT_SYSVIEW_RNDIS + #if CFG_TUD_ECM_RNDIS + ITF_NUM_CDC_RNDIS_COM, + ITF_NUM_CDC_RNDIS_DATA, + #else + ITF_NUM_CDC_NCM_COM, + ITF_NUM_CDC_NCM_DATA, + #endif +#endif +#if CFG_TUD_CDC_DEBUG + ITF_NUM_CDC_DEBUG_COM, + ITF_NUM_CDC_DEBUG_DATA, +#endif + ITF_NUM_TOTAL +}; + + // don't know if consecutive numbering is required. Let's do it anyway enum { @@ -177,22 +159,20 @@ enum MSC_OUT_EP_CNT, MSC_IN_EP_CNT, #endif -#if CFG_TUD_CDC_DEBUG - CDC_DEBUG_NOTIFICATION_EP_CNT, - CDC_DEBUG_DATA_OUT_EP_CNT, - CDC_DEBUG_DATA_IN_EP_CNT, -#endif #if OPT_SYSVIEW_RNDIS #if CFG_TUD_ECM_RNDIS CDC_RNDIS_NOTIFICATION_EP_CNT, - CDC_RNDIS_DATA_OUT_EP_CNT, - CDC_RNDIS_DATA_IN_EP_CNT, + CDC_RNDIS_DATA_EP_CNT, #else CDC_NCM_NOTIFICATION_EP_CNT, - CDC_NCM_DATA_OUT_EP_CNT, - CDC_NCM_DATA_IN_EP_CNT, + CDC_NCM_DATA_EP_CNT, #endif #endif +#if CFG_TUD_CDC_DEBUG + CDC_DEBUG_NOTIFICATION_EP_CNT, + CDC_DEBUG_DATA_OUT_EP_CNT, + CDC_DEBUG_DATA_IN_EP_CNT, +#endif }; @@ -218,22 +198,22 @@ enum #define MSC_OUT_EP_NUM (MSC_OUT_EP_CNT + 0x00) #define MSC_IN_EP_NUM (MSC_IN_EP_CNT + 0x80) #endif -#if CFG_TUD_CDC_DEBUG - #define CDC_DEBUG_NOTIFICATION_EP_NUM (CDC_DEBUG_NOTIFICATION_EP_CNT + 0x80) - #define CDC_DEBUG_DATA_OUT_EP_NUM (CDC_DEBUG_DATA_OUT_EP_CNT + 0x00) - #define CDC_DEBUG_DATA_IN_EP_NUM (CDC_DEBUG_DATA_IN_EP_CNT + 0x80) -#endif #if OPT_SYSVIEW_RNDIS #if CFG_TUD_ECM_RNDIS #define CDC_RNDIS_NOTIFICATION_EP_NUM (CDC_RNDIS_NOTIFICATION_EP_CNT + 0x80) - #define CDC_RNDIS_DATA_OUT_EP_NUM (CDC_RNDIS_DATA_OUT_EP_CNT + 0x00) - #define CDC_RNDIS_DATA_IN_EP_NUM (CDC_RNDIS_DATA_IN_EP_CNT + 0x80) + #define CDC_RNDIS_DATA_OUT_EP_NUM (CDC_RNDIS_DATA_EP_CNT + 0x00) + #define CDC_RNDIS_DATA_IN_EP_NUM (CDC_RNDIS_DATA_EP_CNT + 0x80) #else #define CDC_NCM_NOTIFICATION_EP_NUM (CDC_NCM_NOTIFICATION_EP_CNT + 0x80) - #define CDC_NCM_DATA_OUT_EP_NUM (CDC_NCM_DATA_OUT_EP_CNT + 0x00) - #define CDC_NCM_DATA_IN_EP_NUM (CDC_NCM_DATA_IN_EP_CNT + 0x80) + #define CDC_NCM_DATA_OUT_EP_NUM (CDC_NCM_DATA_EP_CNT + 0x00) + #define CDC_NCM_DATA_IN_EP_NUM (CDC_NCM_DATA_EP_CNT + 0x80) #endif #endif +#if CFG_TUD_CDC_DEBUG + #define CDC_DEBUG_NOTIFICATION_EP_NUM (CDC_DEBUG_NOTIFICATION_EP_CNT + 0x80) + #define CDC_DEBUG_DATA_OUT_EP_NUM (CDC_DEBUG_DATA_OUT_EP_CNT + 0x00) + #define CDC_DEBUG_DATA_IN_EP_NUM (CDC_DEBUG_DATA_IN_EP_CNT + 0x80) +#endif #if USE_RNDIS @@ -288,9 +268,6 @@ static uint8_t const desc_configuration[] = #if CFG_TUD_MSC TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, STRID_INTERFACE_MSC, MSC_OUT_EP_NUM, MSC_IN_EP_NUM, 64), #endif -#if CFG_TUD_CDC_DEBUG - TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_DEBUG_COM, STRID_INTERFACE_CDC_DEBUG, CDC_DEBUG_NOTIFICATION_EP_NUM, 64, CDC_DEBUG_DATA_OUT_EP_NUM, CDC_DEBUG_DATA_IN_EP_NUM, 64), -#endif #if OPT_SYSVIEW_RNDIS #if CFG_TUD_ECM_RNDIS #if USE_RNDIS @@ -303,6 +280,9 @@ static uint8_t const desc_configuration[] = TUD_CDC_NCM_DESCRIPTOR(ITF_NUM_CDC_NCM_COM, STRID_INTERFACE_RNDIS, STRID_MAC, CDC_NCM_NOTIFICATION_EP_NUM, 64, CDC_NCM_DATA_OUT_EP_NUM, CDC_NCM_DATA_IN_EP_NUM, 64, CFG_TUD_NET_MTU), #endif #endif +#if CFG_TUD_CDC_DEBUG + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_DEBUG_COM, STRID_INTERFACE_CDC_DEBUG, CDC_DEBUG_NOTIFICATION_EP_NUM, 64, CDC_DEBUG_DATA_OUT_EP_NUM, CDC_DEBUG_DATA_IN_EP_NUM, 64), +#endif }; From b1dbe22a829e9e08e6a40850bfcb2b227d59ca31 Mon Sep 17 00:00:00 2001 From: Hardy Griech Date: Sat, 6 May 2023 17:29:58 +0200 Subject: [PATCH 010/118] clean up & correct MAC address --- include/lwipopts.h | 16 ++---- src/get_serial.c | 4 +- src/net_starter.c | 139 +++++++-------------------------------------- 3 files changed, 27 insertions(+), 132 deletions(-) diff --git a/include/lwipopts.h b/include/lwipopts.h index 77a4a5982..6ebf5bec1 100755 --- a/include/lwipopts.h +++ b/include/lwipopts.h @@ -32,39 +32,31 @@ #ifndef __LWIPOPTS_H__ #define __LWIPOPTS_H__ -/* Prevent having to link sys_arch.c (we don't test the API layers in unit tests) */ #define NO_SYS 0 #define MEM_ALIGNMENT 4 #define LWIP_RAW 0 -#define LWIP_NETCONN 0 // ???? +#define LWIP_NETCONN 0 #define LWIP_SOCKET 0 -#define LWIP_DHCP 0 +#define LWIP_DHCP 1 #define LWIP_ICMP 1 #define LWIP_UDP 1 #define LWIP_TCP 1 -//#define LWIP_IPV4 1 -//#define LWIP_IPV6 0 #define ETH_PAD_SIZE 0 #define LWIP_IP_ACCEPT_UDP_PORT(p) ((p) == PP_NTOHS(67)) #define TCP_MSS (1500 /*mtu*/ - 20 /*iphdr*/ - 20 /*tcphhr*/) #define TCP_SND_BUF (2 * TCP_MSS) -//#define TCP_WND (TCP_MSS) #define ETHARP_SUPPORT_STATIC_ENTRIES 1 -//#define LWIP_HTTPD_CGI 0 -//#define LWIP_HTTPD_SSI 0 -//#define LWIP_HTTPD_SSI_INCLUDE_TAG 0 - #define LWIP_SINGLE_NETIF 1 //#define PBUF_POOL_SIZE 2 //// ////#define HTTPD_USE_CUSTOM_FSDATA 0 //// -//#define LWIP_MULTICAST_PING 1 -//#define LWIP_BROADCAST_PING 1 +#define LWIP_MULTICAST_PING 1 +#define LWIP_BROADCAST_PING 1 //#define LWIP_IPV6_MLD 0 //#define LWIP_IPV6_SEND_ROUTER_SOLICIT 0 // diff --git a/src/get_serial.c b/src/get_serial.c index 13ca0505e..2e55dff1d 100644 --- a/src/get_serial.c +++ b/src/get_serial.c @@ -44,10 +44,10 @@ void usb_serial_init(void) pico_get_unique_board_id(&uID); #if OPT_SYSVIEW_RNDIS - tud_network_mac_address[0] = 0x02; // never ever use 0x11 here! + tud_network_mac_address[0] = 0xfe; // 0xfe is allowed for local use, never use odd numbers here (group/multicast) for (int i = 1; i < sizeof(tud_network_mac_address); ++i) { - tud_network_mac_address[i] = uID.id[PICO_UNIQUE_BOARD_ID_SIZE_BYTES - i]; + tud_network_mac_address[i] = uID.id[i + (PICO_UNIQUE_BOARD_ID_SIZE_BYTES - sizeof(tud_network_mac_address))]; } #endif diff --git a/src/net_starter.c b/src/net_starter.c index ccb37c2b2..3d71e6fd2 100755 --- a/src/net_starter.c +++ b/src/net_starter.c @@ -38,20 +38,11 @@ #include "picoprobe_config.h" -#if 0 - #include "lwip/init.h" - #include "lwip/ip.h" - #include "lwip/etharp.h" - #include "lwip/ethip6.h" - #include "lwip/tcpip.h" - #include "lwip/timeouts.h" -#else - #include "lwip/init.h" - #include "lwip/timeouts.h" - #include "lwip/ethip6.h" +#include "lwip/init.h" +#include "lwip/timeouts.h" +#include "lwip/ethip6.h" - #include "lwip/tcpip.h" -#endif +#include "lwip/tcpip.h" #if LWIP_IPV4 #include "dhserver.h" #include "dnserver.h" @@ -423,25 +414,6 @@ echo_close(struct tcp_pcb *tpcb, struct echo_state *es) //---------------------------------------------------------------------------------------------------------------------- - -#if 0 -static void service_traffic(void) -{ - /* handle any packet received by tud_network_recv_cb() */ - if (received_frame) { - printf("service_traffic(): %p\n", received_frame); - - ethernet_input(received_frame, &netif_data); - pbuf_free(received_frame); - received_frame = NULL; - tud_network_recv_renew(); - } - sys_check_timeouts(); -} // service_traffic -#endif - - - #if LWIP_IPV4 /* handle any DNS requests from dns-server */ bool dns_query_proc(const char *name, ip4_addr_t *addr) @@ -460,15 +432,12 @@ bool dns_query_proc(const char *name, ip4_addr_t *addr) void tud_network_init_cb(void) { - printf("!!!!!!!!!!!!!!tud_network_init_cb() - %p\n", received_frame); - /* if the network is re-initializing and we have a leftover packet, we must do a cleanup */ if (received_frame) { pbuf_free(received_frame); received_frame = NULL; } - printf("tud_network_init_cb() d\n"); } // tud_network_init_cb @@ -502,7 +471,7 @@ uint16_t tud_network_xmit_cb(uint8_t *dst, void *ref, uint16_t arg) { //printf("!!!!!!!!!!!!!!tud_network_xmit_cb(%p,%p,%u)\n", dst, ref, arg); -#if 1 +#if 0 struct pbuf *p = (struct pbuf *)ref; struct pbuf *q; uint16_t len = 0; @@ -531,21 +500,10 @@ uint16_t tud_network_xmit_cb(uint8_t *dst, void *ref, uint16_t arg) -#if 1 -void tud_network_link_state_cb(bool state) -{ - printf("!!!!!!!!!!!!!!tud_network_link_state_cb(%d)\n", state); -} // tud_network_link_state_cb -#endif - - - -static err_t my_linkoutput_fn(struct netif *netif, struct pbuf *p) +static err_t linkoutput_fn(struct netif *netif, struct pbuf *p) { (void)netif; - //printf("my_linkoutput_fn()\n"); - for (;;) { /* if TinyUSB isn't ready, we must signal back to lwip that there is nothing we can do */ if (!tud_ready()) @@ -556,76 +514,46 @@ static err_t my_linkoutput_fn(struct netif *netif, struct pbuf *p) tud_network_xmit(p, 0 /* unused for this example */); return ERR_OK; } - - /* transfer execution to TinyUSB in the hopes that it will finish transmitting the prior packet */ -#if NO_SYS - //tud_task(); -#endif } -} // my_linkoutput_fn +} // linkoutput_fn #if LWIP_IPV4 -static err_t my_ip4_output_fn(struct netif *netif, struct pbuf *p, const ip4_addr_t *addr) +static err_t ip4_output_fn(struct netif *netif, struct pbuf *p, const ip4_addr_t *addr) { - //printf("my_ip4_output_fn()\n"); - return etharp_output(netif, p, addr); -} // my_ip4_output_fn +} // ip4_output_fn #endif #if LWIP_IPV6 -static err_t my_ip6_output_fn(struct netif *netif, struct pbuf *p, const ip6_addr_t *addr) +static err_t ip6_output_fn(struct netif *netif, struct pbuf *p, const ip6_addr_t *addr) { - printf("my_ip6_output_fn()\n"); - return ethip6_output(netif, p, addr); -} // my_ip6_output_fn -#endif - - - -#if 0 -err_t my_ip_input(struct pbuf *p, struct netif *inp) -{ - printf("my_ip_input(%p,%p)\n", p, inp); - if (p != NULL) { - if (IP_HDR_GET_VERSION(p->payload) == 6) { - printf("my_ip_input 6\n"); - //return ip6_input(p, inp); - return ERR_ABRT; - } - printf("my_ip_input 4\n"); - return ip4_input(p, inp); - } - return ERR_VAL; -} // my_ip_input +} // ip6_output_fn #endif -static err_t my_netif_init_cb(struct netif *netif) +static err_t netif_init_cb(struct netif *netif) { - printf("my_netif_init_cb(%p)\n", netif); - LWIP_ASSERT("netif != NULL", (netif != NULL)); netif->mtu = CFG_TUD_NET_MTU; netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP | NETIF_FLAG_UP; netif->state = NULL; netif->name[0] = 'E'; netif->name[1] = 'X'; - netif->linkoutput = my_linkoutput_fn; + netif->linkoutput = linkoutput_fn; #if LWIP_IPV4 - netif->output = my_ip4_output_fn; + netif->output = ip4_output_fn; #endif #if LWIP_IPV6 - netif->output_ip6 = my_ip6_output_fn; + netif->output_ip6 = ip6_output_fn; #endif return ERR_OK; -} // my_netif_init_cb +} // netif_init_cb @@ -633,46 +561,31 @@ static void init_lwip(void) { struct netif *netif = &netif_data; - printf("init_lwip()\n"); -#if NO_SYS - lwip_init(); -#else tcpip_init(NULL, NULL); -#endif /* the lwip virtual MAC address must be different from the host's; to ensure this, we toggle the LSbit */ -#if 0 netif->hwaddr_len = sizeof(tud_network_mac_address); memcpy(netif->hwaddr, tud_network_mac_address, sizeof(tud_network_mac_address)); -#else - netif->hwaddr_len = 6; - memcpy(netif->hwaddr, tud_network_mac_address, 6); -#endif netif->hwaddr[5] ^= 0x01; #if LWIP_IPV4 - netif = netif_add(netif, &ipaddr, &netmask, &gateway, NULL, my_netif_init_cb, ip_input); + netif = netif_add(netif, &ipaddr, &netmask, &gateway, NULL, netif_init_cb, ip_input); #else - netif = netif_add(netif, NULL, my_netif_init_cb, ip_input); + netif = netif_add(netif, NULL, netif_init_cb, ip_input); #endif - printf("init_lwip() - %p\n", netif); #if LWIP_IPV6 netif_create_ip6_linklocal_address(netif, 1); #endif netif_set_default(netif); - printf("init_lwip() a\n"); while ( !netif_is_up(netif)) - printf("init_lwip() ax\n"); + ; #if LWIP_IPV4 - printf("init_lwip() b\n"); while (dhserv_init(&dhcp_config) != ERR_OK) - printf("init_lwip() bx\n"); - printf("init_lwip() c\n"); + ; while (dnserv_init(IP_ADDR_ANY, 53, dns_query_proc) != ERR_OK) - printf("init_lwip() cx\n"); + ; #endif - printf("init_lwip() d\n"); } // init_lwip @@ -685,20 +598,14 @@ void net_starter_thread(void *ptr) for (;;) { vTaskDelay(pdMS_TO_TICKS(10)); -#if NO_SYS - tud_task(); -#endif /* handle any packet received by tud_network_recv_cb() */ if (received_frame) { - //printf("service_traffic(): %p\n", received_frame); - ethernet_input(received_frame, &netif_data); pbuf_free(received_frame); received_frame = NULL; tud_network_recv_renew(); } - //sys_check_timeouts(); } } // net_starter_thread @@ -706,9 +613,6 @@ void net_starter_thread(void *ptr) void net_starter_init(uint32_t task_prio) { - printf("net_starter_init()\n"); - -#if 1 init_lwip(); xTaskCreateAffinitySet(net_starter_thread, "NET_STARTER", configMINIMAL_STACK_SIZE, NULL, task_prio, 1, &task_net_starter); @@ -716,5 +620,4 @@ void net_starter_init(uint32_t task_prio) { picoprobe_error("net_starter_init: cannot create task_net_starter\n"); } -#endif } // net_starter_init From 4d4b8d31fb08ec3d4d9e37b360b41ea9aa8d97b9 Mon Sep 17 00:00:00 2001 From: Hardy Griech Date: Sat, 6 May 2023 17:43:26 +0200 Subject: [PATCH 011/118] split and rename net_starter --- include/lwipopts.h | 2 +- src/main.c | 4 +- src/net_echo.c | 348 ++++++++++++++++++++++++++++++ src/net_echo.h | 43 ++++ src/{net_starter.c => net_glue.c} | 327 ---------------------------- src/{net_starter.h => net_glue.h} | 4 +- 6 files changed, 397 insertions(+), 331 deletions(-) create mode 100755 src/net_echo.c create mode 100755 src/net_echo.h rename src/{net_starter.c => net_glue.c} (56%) rename src/{net_starter.h => net_glue.h} (96%) diff --git a/include/lwipopts.h b/include/lwipopts.h index 6ebf5bec1..a93f97ac0 100755 --- a/include/lwipopts.h +++ b/include/lwipopts.h @@ -37,7 +37,7 @@ #define LWIP_RAW 0 #define LWIP_NETCONN 0 #define LWIP_SOCKET 0 -#define LWIP_DHCP 1 +#define LWIP_DHCP 0 #define LWIP_ICMP 1 #define LWIP_UDP 1 #define LWIP_TCP 1 diff --git a/src/main.c b/src/main.c index d8fa55d1d..572c303c6 100644 --- a/src/main.c +++ b/src/main.c @@ -68,7 +68,8 @@ #include "pico-sigrok/sigrok.h" #endif #if OPT_SYSVIEW_RNDIS - #include "net_starter.h" + #include "net_glue.h" + #include "net_echo.h" #endif @@ -471,6 +472,7 @@ void usb_thread(void *ptr) #if OPT_SYSVIEW_RNDIS net_starter_init(3); // TODO + net_echo_init(); #endif #if CFG_TUD_VENDOR diff --git a/src/net_echo.c b/src/net_echo.c new file mode 100755 index 000000000..98e130865 --- /dev/null +++ b/src/net_echo.c @@ -0,0 +1,348 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2021 Raspberry Pi (Trading) Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + + +#include "lwip/debug.h" +#include "lwip/stats.h" +#include "lwip/tcp.h" + + + +static struct tcp_pcb *echo_pcb; + +enum echo_states +{ + ES_NONE = 0, + ES_ACCEPTED, + ES_RECEIVED, + ES_CLOSING +}; + +struct echo_state +{ + u8_t state; + u8_t retries; + struct tcp_pcb *pcb; + /* pbuf (chain) to recycle */ + struct pbuf *p; +}; + +err_t echo_accept(void *arg, struct tcp_pcb *newpcb, err_t err); +err_t echo_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err); +void echo_error(void *arg, err_t err); +err_t echo_poll(void *arg, struct tcp_pcb *tpcb); +err_t echo_sent(void *arg, struct tcp_pcb *tpcb, u16_t len); +void echo_send(struct tcp_pcb *tpcb, struct echo_state *es); +void echo_close(struct tcp_pcb *tpcb, struct echo_state *es); + + + +void net_echo_init(void) +{ + echo_pcb = tcp_new(); + if (echo_pcb != NULL) + { + err_t err; + + err = tcp_bind(echo_pcb, IP_ADDR_ANY, 7); + if (err == ERR_OK) + { + echo_pcb = tcp_listen(echo_pcb); + tcp_accept(echo_pcb, echo_accept); + } + else + { + /* abort? output diagnostic? */ + } + } + else + { + /* abort? output diagnostic? */ + } +} + + + +err_t echo_accept(void *arg, struct tcp_pcb *newpcb, err_t err) +{ + err_t ret_err; + struct echo_state *es; + + LWIP_UNUSED_ARG(arg); + LWIP_UNUSED_ARG(err); + + /* commonly observed practive to call tcp_setprio(), why? */ + tcp_setprio(newpcb, TCP_PRIO_MIN); + + es = (struct echo_state *)mem_malloc(sizeof(struct echo_state)); + if (es != NULL) + { + es->state = ES_ACCEPTED; + es->pcb = newpcb; + es->retries = 0; + es->p = NULL; + /* pass newly allocated es to our callbacks */ + tcp_arg(newpcb, es); + tcp_recv(newpcb, echo_recv); + tcp_err(newpcb, echo_error); + tcp_poll(newpcb, echo_poll, 0); + ret_err = ERR_OK; + } + else + { + ret_err = ERR_MEM; + } + return ret_err; +} + + + +err_t echo_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) +{ + struct echo_state *es; + err_t ret_err; + + LWIP_ASSERT("arg != NULL",arg != NULL); + es = (struct echo_state *)arg; + if (p == NULL) + { + /* remote host closed connection */ + es->state = ES_CLOSING; + if(es->p == NULL) + { + /* we're done sending, close it */ + echo_close(tpcb, es); + } + else + { + /* we're not done yet */ + tcp_sent(tpcb, echo_sent); + echo_send(tpcb, es); + } + ret_err = ERR_OK; + } + else if(err != ERR_OK) + { + /* cleanup, for unkown reason */ + if (p != NULL) + { + es->p = NULL; + pbuf_free(p); + } + ret_err = err; + } + else if(es->state == ES_ACCEPTED) + { + /* first data chunk in p->payload */ + es->state = ES_RECEIVED; + /* store reference to incoming pbuf (chain) */ + es->p = p; + /* install send completion notifier */ + tcp_sent(tpcb, echo_sent); + echo_send(tpcb, es); + ret_err = ERR_OK; + } + else if (es->state == ES_RECEIVED) + { + /* read some more data */ + if(es->p == NULL) + { + es->p = p; + tcp_sent(tpcb, echo_sent); + echo_send(tpcb, es); + } + else + { + struct pbuf *ptr; + + /* chain pbufs to the end of what we recv'ed previously */ + ptr = es->p; + pbuf_chain(ptr,p); + } + ret_err = ERR_OK; + } + else if(es->state == ES_CLOSING) + { + /* odd case, remote side closing twice, trash data */ + tcp_recved(tpcb, p->tot_len); + es->p = NULL; + pbuf_free(p); + ret_err = ERR_OK; + } + else + { + /* unkown es->state, trash data */ + tcp_recved(tpcb, p->tot_len); + es->p = NULL; + pbuf_free(p); + ret_err = ERR_OK; + } + return ret_err; +} + + + +void echo_error(void *arg, err_t err) +{ + struct echo_state *es; + + LWIP_UNUSED_ARG(err); + + es = (struct echo_state *)arg; + if (es != NULL) + { + mem_free(es); + } +} + + + +err_t echo_poll(void *arg, struct tcp_pcb *tpcb) +{ + err_t ret_err; + struct echo_state *es; + + es = (struct echo_state *)arg; + if (es != NULL) + { + if (es->p != NULL) + { + /* there is a remaining pbuf (chain) */ + tcp_sent(tpcb, echo_sent); + echo_send(tpcb, es); + } + else + { + /* no remaining pbuf (chain) */ + if(es->state == ES_CLOSING) + { + echo_close(tpcb, es); + } + } + ret_err = ERR_OK; + } + else + { + /* nothing to be done */ + tcp_abort(tpcb); + ret_err = ERR_ABRT; + } + return ret_err; +} + + + +err_t echo_sent(void *arg, struct tcp_pcb *tpcb, u16_t len) +{ + struct echo_state *es; + + LWIP_UNUSED_ARG(len); + + es = (struct echo_state *)arg; + es->retries = 0; + + if(es->p != NULL) + { + /* still got pbufs to send */ + tcp_sent(tpcb, echo_sent); + echo_send(tpcb, es); + } + else + { + /* no more pbufs to send */ + if(es->state == ES_CLOSING) + { + echo_close(tpcb, es); + } + } + return ERR_OK; +} + + + +void echo_send(struct tcp_pcb *tpcb, struct echo_state *es) +{ + struct pbuf *ptr; + err_t wr_err = ERR_OK; + + while ((wr_err == ERR_OK) && + (es->p != NULL) && + (es->p->len <= tcp_sndbuf(tpcb))) + { + ptr = es->p; + + /* enqueue data for transmission */ + wr_err = tcp_write(tpcb, ptr->payload, ptr->len, 1); + if (wr_err == ERR_OK) + { + u16_t plen; + u8_t freed; + + plen = ptr->len; + /* continue with next pbuf in chain (if any) */ + es->p = ptr->next; + if(es->p != NULL) + { + /* new reference! */ + pbuf_ref(es->p); + } + /* chop first pbuf from chain */ + do + { + /* try hard to free pbuf */ + freed = pbuf_free(ptr); + } + while(freed == 0); + /* we can read more data now */ + tcp_recved(tpcb, plen); + } + else if(wr_err == ERR_MEM) + { + /* we are low on memory, try later / harder, defer to poll */ + es->p = ptr; + } + else + { + /* other problem ?? */ + } + } +} + + + +void echo_close(struct tcp_pcb *tpcb, struct echo_state *es) +{ + tcp_arg(tpcb, NULL); + tcp_sent(tpcb, NULL); + tcp_recv(tpcb, NULL); + tcp_err(tpcb, NULL); + tcp_poll(tpcb, NULL, 0); + + if (es != NULL) + { + mem_free(es); + } + tcp_close(tpcb); +} diff --git a/src/net_echo.h b/src/net_echo.h new file mode 100755 index 000000000..32ded9ee0 --- /dev/null +++ b/src/net_echo.h @@ -0,0 +1,43 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2021 Raspberry Pi (Trading) Ltd. + * + * 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. + * + */ + +#ifndef _NET_ECHO_H +#define _NET_ECHO_H + + +#ifdef __cplusplus + extern "C" { +#endif + + +void net_echo_init(void); + + +#ifdef __cplusplus + } +#endif + + +#endif diff --git a/src/net_starter.c b/src/net_glue.c similarity index 56% rename from src/net_starter.c rename to src/net_glue.c index 3d71e6fd2..bc7ebe2c9 100755 --- a/src/net_starter.c +++ b/src/net_glue.c @@ -88,331 +88,6 @@ static struct pbuf *received_frame; static TaskHandle_t task_net_starter = NULL; -//---------------------------------------------------------------------------------------------------------------------- -#if 1 - -#include "lwip/debug.h" -#include "lwip/stats.h" -#include "lwip/tcp.h" - - -static struct tcp_pcb *echo_pcb; - -enum echo_states -{ - ES_NONE = 0, - ES_ACCEPTED, - ES_RECEIVED, - ES_CLOSING -}; - -struct echo_state -{ - u8_t state; - u8_t retries; - struct tcp_pcb *pcb; - /* pbuf (chain) to recycle */ - struct pbuf *p; -}; - -err_t echo_accept(void *arg, struct tcp_pcb *newpcb, err_t err); -err_t echo_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err); -void echo_error(void *arg, err_t err); -err_t echo_poll(void *arg, struct tcp_pcb *tpcb); -err_t echo_sent(void *arg, struct tcp_pcb *tpcb, u16_t len); -void echo_send(struct tcp_pcb *tpcb, struct echo_state *es); -void echo_close(struct tcp_pcb *tpcb, struct echo_state *es); - -void -echo_init(void) -{ - printf("!!!!!!!!!!!!!!!!!!!! echo_init\n"); - echo_pcb = tcp_new(); - if (echo_pcb != NULL) - { - err_t err; - - err = tcp_bind(echo_pcb, IP_ADDR_ANY, 7); - if (err == ERR_OK) - { - echo_pcb = tcp_listen(echo_pcb); - tcp_accept(echo_pcb, echo_accept); - } - else - { - /* abort? output diagnostic? */ - printf("!!!!!!!!!!!!!!!!!!!! cannot bind\n"); - } - } - else - { - /* abort? output diagnostic? */ - printf("!!!!!!!!!!!!!!!!!!!! tcp_new\n"); - } -} - - -err_t -echo_accept(void *arg, struct tcp_pcb *newpcb, err_t err) -{ - err_t ret_err; - struct echo_state *es; - - LWIP_UNUSED_ARG(arg); - LWIP_UNUSED_ARG(err); - - /* commonly observed practive to call tcp_setprio(), why? */ - tcp_setprio(newpcb, TCP_PRIO_MIN); - - es = (struct echo_state *)mem_malloc(sizeof(struct echo_state)); - if (es != NULL) - { - es->state = ES_ACCEPTED; - es->pcb = newpcb; - es->retries = 0; - es->p = NULL; - /* pass newly allocated es to our callbacks */ - tcp_arg(newpcb, es); - tcp_recv(newpcb, echo_recv); - tcp_err(newpcb, echo_error); - tcp_poll(newpcb, echo_poll, 0); - ret_err = ERR_OK; - } - else - { - ret_err = ERR_MEM; - } - return ret_err; -} - -err_t -echo_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) -{ - struct echo_state *es; - err_t ret_err; - - LWIP_ASSERT("arg != NULL",arg != NULL); - es = (struct echo_state *)arg; - if (p == NULL) - { - /* remote host closed connection */ - es->state = ES_CLOSING; - if(es->p == NULL) - { - /* we're done sending, close it */ - echo_close(tpcb, es); - } - else - { - /* we're not done yet */ - tcp_sent(tpcb, echo_sent); - echo_send(tpcb, es); - } - ret_err = ERR_OK; - } - else if(err != ERR_OK) - { - /* cleanup, for unkown reason */ - if (p != NULL) - { - es->p = NULL; - pbuf_free(p); - } - ret_err = err; - } - else if(es->state == ES_ACCEPTED) - { - /* first data chunk in p->payload */ - es->state = ES_RECEIVED; - /* store reference to incoming pbuf (chain) */ - es->p = p; - /* install send completion notifier */ - tcp_sent(tpcb, echo_sent); - echo_send(tpcb, es); - ret_err = ERR_OK; - } - else if (es->state == ES_RECEIVED) - { - /* read some more data */ - if(es->p == NULL) - { - es->p = p; - tcp_sent(tpcb, echo_sent); - echo_send(tpcb, es); - } - else - { - struct pbuf *ptr; - - /* chain pbufs to the end of what we recv'ed previously */ - ptr = es->p; - pbuf_chain(ptr,p); - } - ret_err = ERR_OK; - } - else if(es->state == ES_CLOSING) - { - /* odd case, remote side closing twice, trash data */ - tcp_recved(tpcb, p->tot_len); - es->p = NULL; - pbuf_free(p); - ret_err = ERR_OK; - } - else - { - /* unkown es->state, trash data */ - tcp_recved(tpcb, p->tot_len); - es->p = NULL; - pbuf_free(p); - ret_err = ERR_OK; - } - return ret_err; -} - -void -echo_error(void *arg, err_t err) -{ - struct echo_state *es; - - LWIP_UNUSED_ARG(err); - - es = (struct echo_state *)arg; - if (es != NULL) - { - mem_free(es); - } -} - -err_t -echo_poll(void *arg, struct tcp_pcb *tpcb) -{ - err_t ret_err; - struct echo_state *es; - - es = (struct echo_state *)arg; - if (es != NULL) - { - if (es->p != NULL) - { - /* there is a remaining pbuf (chain) */ - tcp_sent(tpcb, echo_sent); - echo_send(tpcb, es); - } - else - { - /* no remaining pbuf (chain) */ - if(es->state == ES_CLOSING) - { - echo_close(tpcb, es); - } - } - ret_err = ERR_OK; - } - else - { - /* nothing to be done */ - tcp_abort(tpcb); - ret_err = ERR_ABRT; - } - return ret_err; -} - -err_t -echo_sent(void *arg, struct tcp_pcb *tpcb, u16_t len) -{ - struct echo_state *es; - - LWIP_UNUSED_ARG(len); - - es = (struct echo_state *)arg; - es->retries = 0; - - if(es->p != NULL) - { - /* still got pbufs to send */ - tcp_sent(tpcb, echo_sent); - echo_send(tpcb, es); - } - else - { - /* no more pbufs to send */ - if(es->state == ES_CLOSING) - { - echo_close(tpcb, es); - } - } - return ERR_OK; -} - -void -echo_send(struct tcp_pcb *tpcb, struct echo_state *es) -{ - struct pbuf *ptr; - err_t wr_err = ERR_OK; - - while ((wr_err == ERR_OK) && - (es->p != NULL) && - (es->p->len <= tcp_sndbuf(tpcb))) - { - ptr = es->p; - - /* enqueue data for transmission */ - wr_err = tcp_write(tpcb, ptr->payload, ptr->len, 1); - if (wr_err == ERR_OK) - { - u16_t plen; - u8_t freed; - - plen = ptr->len; - /* continue with next pbuf in chain (if any) */ - es->p = ptr->next; - if(es->p != NULL) - { - /* new reference! */ - pbuf_ref(es->p); - } - /* chop first pbuf from chain */ - do - { - /* try hard to free pbuf */ - freed = pbuf_free(ptr); - } - while(freed == 0); - /* we can read more data now */ - tcp_recved(tpcb, plen); - } - else if(wr_err == ERR_MEM) - { - /* we are low on memory, try later / harder, defer to poll */ - es->p = ptr; - } - else - { - /* other problem ?? */ - } - } -} - -void -echo_close(struct tcp_pcb *tpcb, struct echo_state *es) -{ - tcp_arg(tpcb, NULL); - tcp_sent(tpcb, NULL); - tcp_recv(tpcb, NULL); - tcp_err(tpcb, NULL); - tcp_poll(tpcb, NULL, 0); - - if (es != NULL) - { - mem_free(es); - } - tcp_close(tpcb); -} -#endif - - -//---------------------------------------------------------------------------------------------------------------------- - #if LWIP_IPV4 /* handle any DNS requests from dns-server */ @@ -594,8 +269,6 @@ void net_starter_thread(void *ptr) { vTaskDelay(pdMS_TO_TICKS(2000)); - echo_init(); - for (;;) { vTaskDelay(pdMS_TO_TICKS(10)); diff --git a/src/net_starter.h b/src/net_glue.h similarity index 96% rename from src/net_starter.h rename to src/net_glue.h index 0a1c671c9..4a2f3fd2a 100755 --- a/src/net_starter.h +++ b/src/net_glue.h @@ -23,8 +23,8 @@ * */ -#ifndef _NET_STARTER_H -#define _NET_STARTER_H +#ifndef _NET_GLUE_H +#define _NET_GLUE_H #include From b9f71d452bd5cbdf64ad15b446aa2a1282607698 Mon Sep 17 00:00:00 2001 From: Hardy Griech Date: Sat, 6 May 2023 17:58:09 +0200 Subject: [PATCH 012/118] OPT_MSC --- CMakeLists.txt | 23 ++++++++++++++++++----- include/tusb_config.h | 14 ++++++++++---- src/main.c | 6 +++--- src/msc/msc_drive.c | 4 ---- src/usb_descriptors.c | 6 +++--- 5 files changed, 34 insertions(+), 19 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 463ecec18..b6825248f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,8 +19,9 @@ cmake_minimum_required(VERSION 3.12) if(PICO_BOARD STREQUAL "") set(PICO_BOARD pico) endif() -option(OPT_SIGROK "Enable sigrok" 0) -option(OPT_SYSVIEW_RNDIS "Enable SysView over RNDIS" 1) +option(OPT_SYSVIEW_RNDIS "Enable SysView over RNDIS" 1) +option(OPT_SIGROK "Enable sigrok" 0) +option(OPT_MSC "Enable Mass Storage Device" ) # # SDK options @@ -121,8 +122,6 @@ target_include_directories(${PROJECT} PRIVATE # this is for MSC/DAPLink operation # target_sources(${PROJECT} PRIVATE - src/msc/msc_drive.c - src/msc/msc_utils.c src/daplink/daplink/util.c src/daplink/daplink/drag-n-drop/flash_manager.c src/daplink/daplink/interface/swd_host.c @@ -192,7 +191,8 @@ if(OPT_SYSVIEW_RNDIS) add_compile_definitions(OPT_SYSVIEW_RNDIS=1) target_sources(${PROJECT} PRIVATE - src/net_starter.c + src/net_glue.c + src/net_echo.c ${PICO_TINYUSB_PATH}/lib/networking/dhserver.c ${PICO_TINYUSB_PATH}/lib/networking/dnserver.c @@ -212,6 +212,19 @@ if(OPT_SYSVIEW_RNDIS) # message("--------- " ${PICO_TINYUSB_PATH}) endif() +#-------------------------------------------------------------------------------------------------- +# +# this is for MSC operation +# +if(OPT_MSC) + add_compile_definitions(OPT_MSC=1) + + target_sources(${PROJECT} PRIVATE + src/msc/msc_drive.c + src/msc/msc_utils.c + ) +endif() + #-------------------------------------------------------------------------------------------------- target_compile_options(${PROJECT} PRIVATE -Wall) diff --git a/include/tusb_config.h b/include/tusb_config.h index c26fe0885..053cf1f62 100644 --- a/include/tusb_config.h +++ b/include/tusb_config.h @@ -86,11 +86,15 @@ #define CFG_TUD_HID 1 // CMSIS-DAPv1 #define CFG_TUD_VENDOR 1 // CMSIS-DAPv2 -#define CFG_TUD_MSC 1 // DAPLink drive +#if OPT_MSC + #define CFG_TUD_MSC 1 // DAPLink drive +#else + #define CFG_TUD_MSC 0 +#endif #define CFG_TUD_CDC (CFG_TUD_CDC_UART + CFG_TUD_CDC_SIGROK + CFG_TUD_CDC_DEBUG) #if OPT_SYSVIEW_RNDIS // lsusb output of NCM looks the same as setup from lwip webserver example - #define CFG_TUD_ECM_RNDIS 1 // RNDIS under Windows works only if it's the only class, so we try NCM for Linux + #define CFG_TUD_ECM_RNDIS 0 // RNDIS under Windows works only if it's the only class, so we try NCM for Linux #define CFG_TUD_NCM (1 - CFG_TUD_ECM_RNDIS) #else #define CFG_TUD_ECM_RNDIS 0 @@ -113,8 +117,10 @@ #define CFG_TUD_VENDOR_RX_BUFSIZE 1024 #define CFG_TUD_VENDOR_TX_BUFSIZE CFG_TUD_VENDOR_RX_BUFSIZE - // note: this is optimized for DAPLink write speed -#define CFG_TUD_MSC_EP_BUFSIZE 512 +#if OPT_MSC + // note: this is optimized for DAPLink write speed + #define CFG_TUD_MSC_EP_BUFSIZE 512 +#endif #if OPT_SYSVIEW_RNDIS #define CFG_TUD_NET_MTU 1514 diff --git a/src/main.c b/src/main.c index 572c303c6..bdf4adeb2 100644 --- a/src/main.c +++ b/src/main.c @@ -57,7 +57,7 @@ #include "target_board.h" // DAPLink -#if CFG_TUD_MSC +#if OPT_MSC #include "msc/msc_utils.h" #endif #if defined(INCLUDE_RTT_CONSOLE) @@ -458,7 +458,7 @@ void usb_thread(void *ptr) cdc_uart_init(UART_TASK_PRIO); -#if CFG_TUD_MSC +#if OPT_MSC msc_init(MSC_WRITER_THREAD_PRIO); #endif @@ -531,7 +531,7 @@ int main(void) #if CFG_TUD_CDC_DEBUG picoprobe_info_out(" [probe debug CDC]"); #endif -#if CFG_TUD_MSC +#if OPT_MSC picoprobe_info_out(" [DAPLink MSC]"); #endif picoprobe_info_out("\n"); diff --git a/src/msc/msc_drive.c b/src/msc/msc_drive.c index 2d6ad6f9c..bb05d15d7 100644 --- a/src/msc/msc_drive.c +++ b/src/msc/msc_drive.c @@ -48,8 +48,6 @@ #define INCLUDE_RAM_UF2 -#if CFG_TUD_MSC - #define ADWORD(X) (X) & 0xff, ((X) & 0xff00) >> 8, ((X) & 0xff0000) >> 16, ((X) & 0xff000000) >> 24 #define AWORD(X) (X) & 0xff, ((X) & 0xff00) >> 8 #define ADATE(Y,M,D) AWORD((((Y)-1980) << 9) + ((M) << 5) + (D)) @@ -691,5 +689,3 @@ int32_t tud_msc_scsi_cb(uint8_t lun, uint8_t const scsi_cmd[16], void* buffer, u return resplen; } // tud_msc_scsi_cb - -#endif diff --git a/src/usb_descriptors.c b/src/usb_descriptors.c index 25e9e0f01..229191cf4 100644 --- a/src/usb_descriptors.c +++ b/src/usb_descriptors.c @@ -113,7 +113,7 @@ enum ITF_NUM_CDC_SIGROK_COM, ITF_NUM_CDC_SIGROK_DATA, #endif -#if CFG_TUD_MSC +#if OPT_MSC ITF_NUM_MSC, #endif #if OPT_SYSVIEW_RNDIS @@ -155,7 +155,7 @@ enum CDC_SIGROK_DATA_OUT_EP_CNT, CDC_SIGROK_DATA_IN_EP_CNT, #endif -#if CFG_TUD_MSC +#if OPT_MSC MSC_OUT_EP_CNT, MSC_IN_EP_CNT, #endif @@ -194,7 +194,7 @@ enum #define CDC_SIGROK_DATA_OUT_EP_NUM (CDC_SIGROK_DATA_OUT_EP_CNT + 0x00) #define CDC_SIGROK_DATA_IN_EP_NUM (CDC_SIGROK_DATA_IN_EP_CNT + 0x80) #endif -#if CFG_TUD_MSC +#if OPT_MSC #define MSC_OUT_EP_NUM (MSC_OUT_EP_CNT + 0x00) #define MSC_IN_EP_NUM (MSC_IN_EP_CNT + 0x80) #endif From 1ede084368aa13356e5e2e8c7202c352f8b46e39 Mon Sep 17 00:00:00 2001 From: Hardy Griech Date: Sat, 6 May 2023 18:13:33 +0200 Subject: [PATCH 013/118] cmake options for CMSIS-DAPv1/2 --- CMakeLists.txt | 15 ++++++++++++++- include/tusb_config.h | 20 ++++++++++++++------ src/main.c | 14 +++++++------- src/usb_descriptors.c | 26 +++++++++++++++----------- 4 files changed, 50 insertions(+), 25 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b6825248f..2074cee75 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,9 +19,11 @@ cmake_minimum_required(VERSION 3.12) if(PICO_BOARD STREQUAL "") set(PICO_BOARD pico) endif() +option(OPT_CMSIS_DAPV1 "Enable CMSIS-DAPv1" 1) +option(OPT_CMSIS_DAPV2 "Enable CMSIS-DAPv2" 1) option(OPT_SYSVIEW_RNDIS "Enable SysView over RNDIS" 1) option(OPT_SIGROK "Enable sigrok" 0) -option(OPT_MSC "Enable Mass Storage Device" ) +option(OPT_MSC "Enable Mass Storage Device" 1) # # SDK options @@ -117,6 +119,17 @@ target_include_directories(${PROJECT} PRIVATE include/ ) +#-------------------------------------------------------------------------------------------------- +# +# Enable/disable CMSIS-DAP USB endpoints +# +if(OPT_CMSIS_DAPV1) + add_compile_definitions(OPT_CMSIS_DAPV1=1) +endif() +if(OPT_CMSIS_DAPV2) + add_compile_definitions(OPT_CMSIS_DAPV2=1) +endif() + #-------------------------------------------------------------------------------------------------- # # this is for MSC/DAPLink operation diff --git a/include/tusb_config.h b/include/tusb_config.h index 053cf1f62..747850215 100644 --- a/include/tusb_config.h +++ b/include/tusb_config.h @@ -73,8 +73,8 @@ //********************************************** #define CFG_TUD_CDC_UART 1 // CDC for target UART IO -#if OPT_SIGROK - #define CFG_TUD_CDC_SIGROK 1 // CDC for sigrok IO +#if OPT_SIGROK // CDC for sigrok IO + #define CFG_TUD_CDC_SIGROK 1 #else #define CFG_TUD_CDC_SIGROK 0 #endif @@ -84,10 +84,18 @@ #define CFG_TUD_CDC_DEBUG 0 #endif -#define CFG_TUD_HID 1 // CMSIS-DAPv1 -#define CFG_TUD_VENDOR 1 // CMSIS-DAPv2 -#if OPT_MSC - #define CFG_TUD_MSC 1 // DAPLink drive +#if OPT_CMSIS_DAPV1 // CMSIS-DAPv1 + #define CFG_TUD_HID 1 +#else + #define CFG_TUD_HID 0 +#endif +#if OPT_CMSIS_DAPV2 // CMSIS-DAPv2 + #define CFG_TUD_VENDOR 1 +#else + #define CFG_TUD_VENDOR 0 +#endif +#if OPT_MSC // DAPLink drive + #define CFG_TUD_MSC 1 #else #define CFG_TUD_MSC 0 #endif diff --git a/src/main.c b/src/main.c index bdf4adeb2..e277d4d9f 100644 --- a/src/main.c +++ b/src/main.c @@ -187,7 +187,7 @@ void tud_cdc_tx_complete_cb(uint8_t itf) -#if CFG_TUD_VENDOR +#if OPT_CMSIS_DAPV2 void tud_vendor_rx_cb(uint8_t itf) { if (itf == 0) { @@ -198,7 +198,7 @@ void tud_vendor_rx_cb(uint8_t itf) -#if CFG_TUD_VENDOR +#if OPT_CMSIS_DAPV2 /** * CMSIS-DAP task. * Receive DAP requests, execute them via DAP_ExecuteCommand() and transmit the response. @@ -475,7 +475,7 @@ void usb_thread(void *ptr) net_echo_init(); #endif -#if CFG_TUD_VENDOR +#if OPT_CMSIS_DAPV2 xTaskCreateAffinitySet(dap_task, "CMSIS-DAP", configMINIMAL_STACK_SIZE, NULL, DAP_TASK_PRIO, 2, &dap_taskhandle); #endif @@ -516,10 +516,10 @@ int main(void) picoprobe_info(" Welcome to Yet Another Picoprobe v" PICOPROBE_VERSION_STRING "-" GIT_HASH "\n"); picoprobe_info("Features:\n"); picoprobe_info(" "); -#if CFG_TUD_VENDOR +#if OPT_CMSIS_DAPV2 picoprobe_info_out(" [CMSIS-DAPv2]"); #endif -#if CFG_TUD_HID +#if OPT_CMSIS_DAPV1 picoprobe_info_out(" [CMSIS-DAPv1]"); #endif #if CFG_TUD_CDC_UART @@ -557,7 +557,7 @@ int main(void) -#if CFG_TUD_HID +#if OPT_CMSIS_DAPV1 static bool hid_swd_connected; static bool hid_swd_disconnect_requested; static TimerHandle_t timer_hid_disconnect = NULL; @@ -661,7 +661,7 @@ void tud_hid_set_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t rep -#if CFG_TUD_VENDOR +#if OPT_CMSIS_DAPV2 extern uint8_t const desc_ms_os_20[]; bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) diff --git a/src/usb_descriptors.c b/src/usb_descriptors.c index 229191cf4..3c45a07d2 100644 --- a/src/usb_descriptors.c +++ b/src/usb_descriptors.c @@ -67,7 +67,11 @@ tusb_desc_device_t const desc_device = { .bLength = sizeof(tusb_desc_device_t), .bDescriptorType = TUSB_DESC_DEVICE, - .bcdUSB = 0x0210, // USB Specification version 2.1 for BOS (DAPv2) under Windows +#if OPT_CMSIS_DAPV2 // USB Specification version 2.1 for BOS (DAPv2) under Windows + .bcdUSB = 0x0210, +#else + .bcdUSB = 0x0200, +#endif // Use Interface Association Descriptor (IAD) device class .bDeviceClass = TUSB_CLASS_MISC, @@ -99,10 +103,10 @@ uint8_t const * tud_descriptor_device_cb(void) enum { -#if CFG_TUD_VENDOR +#if OPT_CMSIS_DAPV2 ITF_NUM_PROBE_VENDOR, // Old versions of Keil MDK only look at interface 0 #endif -#if CFG_TUD_HID +#if OPT_CMSIS_DAPV1 ITF_NUM_PROBE_HID, #endif #if CFG_TUD_CDC_UART @@ -137,11 +141,11 @@ enum enum { DUMMY_CNT = 0, -#if CFG_TUD_VENDOR +#if OPT_CMSIS_DAPV2 PROBE_VENDOR_OUT_EP_CNT, PROBE_VENDOR_IN_EP_CNT, #endif -#if CFG_TUD_HID +#if OPT_CMSIS_DAPV1 PROBE_HID_OUT_EP_CNT, PROBE_HID_IN_EP_CNT, #endif @@ -176,11 +180,11 @@ enum }; -#if CFG_TUD_VENDOR +#if OPT_CMSIS_DAPV2 #define PROBE_VENDOR_OUT_EP_NUM (PROBE_VENDOR_OUT_EP_CNT + 0x00) #define PROBE_VENDOR_IN_EP_NUM (PROBE_VENDOR_IN_EP_CNT + 0x80) #endif -#if CFG_TUD_HID +#if OPT_CMSIS_DAPV1 #define PROBE_HID_OUT_EP_NUM (PROBE_HID_OUT_EP_CNT + 0x00) #define PROBE_HID_IN_EP_NUM (PROBE_HID_IN_EP_CNT + 0x80) #endif @@ -228,7 +232,7 @@ enum + CFG_TUD_NCM*TUD_CDC_NCM_DESC_LEN) #endif -#if CFG_TUD_HID +#if OPT_CMSIS_DAPV1 static uint8_t const desc_hid_report[] = { TUD_HID_REPORT_DESC_GENERIC_INOUT(CFG_TUD_HID_EP_BUFSIZE) @@ -253,10 +257,10 @@ static uint8_t const desc_configuration[] = // Config number, interface count, string index, total length, attribute, power in mA //TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 500), TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0, CURR_MA), -#if CFG_TUD_VENDOR +#if OPT_CMSIS_DAPV2 TUD_VENDOR_DESCRIPTOR(ITF_NUM_PROBE_VENDOR, STRID_INTERFACE_DAP2, PROBE_VENDOR_OUT_EP_NUM, PROBE_VENDOR_IN_EP_NUM, 64), #endif -#if CFG_TUD_HID +#if OPT_CMSIS_DAPV1 TUD_HID_INOUT_DESCRIPTOR(ITF_NUM_PROBE_HID, STRID_INTERFACE_DAP1, HID_ITF_PROTOCOL_NONE, sizeof(desc_hid_report), PROBE_HID_OUT_EP_NUM, PROBE_HID_IN_EP_NUM, CFG_TUD_HID_EP_BUFSIZE, 1), #endif #if CFG_TUD_CDC_UART @@ -377,7 +381,7 @@ uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid) } -#if CFG_TUD_VENDOR +#if OPT_CMSIS_DAPV2 /* [incoherent gibbering to make Windows happy] */ //--------------------------------------------------------------------+ From 5a46213eb2b8065ebdd2dbc1d799de2a995ed336 Mon Sep 17 00:00:00 2001 From: Hardy Griech Date: Sat, 6 May 2023 18:29:41 +0200 Subject: [PATCH 014/118] USB target uart as an option --- CMakeLists.txt | 40 +++++++++++++++++++++++----------------- include/tusb_config.h | 6 +++++- src/cdc_uart.c | 8 -------- src/cdc_uart.h | 6 +++--- src/main.c | 16 ++++++++++------ src/rtt_console.c | 6 +++++- src/usb_descriptors.c | 10 +++++----- 7 files changed, 51 insertions(+), 41 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2074cee75..d50032e33 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,11 +19,12 @@ cmake_minimum_required(VERSION 3.12) if(PICO_BOARD STREQUAL "") set(PICO_BOARD pico) endif() -option(OPT_CMSIS_DAPV1 "Enable CMSIS-DAPv1" 1) -option(OPT_CMSIS_DAPV2 "Enable CMSIS-DAPv2" 1) -option(OPT_SYSVIEW_RNDIS "Enable SysView over RNDIS" 1) -option(OPT_SIGROK "Enable sigrok" 0) -option(OPT_MSC "Enable Mass Storage Device" 1) +option(OPT_TARGET_UART "Enable CDC for target UART I/O" 1) +option(OPT_CMSIS_DAPV1 "Enable CMSIS-DAPv1" 1) +option(OPT_CMSIS_DAPV2 "Enable CMSIS-DAPv2" 1) +option(OPT_SYSVIEW_RNDIS "Enable SysView over RNDIS" 1) +option(OPT_SIGROK "Enable sigrok" 0) +option(OPT_MSC "Enable Mass Storage Device" 1) # # SDK options @@ -87,7 +88,6 @@ endif() add_executable(${PROJECT} - src/cdc_uart.c src/dap_util.c src/get_serial.c src/led.c @@ -119,17 +119,6 @@ target_include_directories(${PROJECT} PRIVATE include/ ) -#-------------------------------------------------------------------------------------------------- -# -# Enable/disable CMSIS-DAP USB endpoints -# -if(OPT_CMSIS_DAPV1) - add_compile_definitions(OPT_CMSIS_DAPV1=1) -endif() -if(OPT_CMSIS_DAPV2) - add_compile_definitions(OPT_CMSIS_DAPV2=1) -endif() - #-------------------------------------------------------------------------------------------------- # # this is for MSC/DAPLink operation @@ -175,6 +164,23 @@ add_compile_definitions(DAPLINK_HIC_ID=0x08154711) # required to get required DAPLink functions add_compile_definitions(DRAG_N_DROP_SUPPORT=1) +#-------------------------------------------------------------------------------------------------- +# +# Enable/disable several USB endpoints +# +if(OPT_TARGET_UART) + add_compile_definitions(OPT_TARGET_UART=1) + target_sources(${PROJECT} PRIVATE + src/cdc_uart.c + ) +endif() +if(OPT_CMSIS_DAPV1) + add_compile_definitions(OPT_CMSIS_DAPV1=1) +endif() +if(OPT_CMSIS_DAPV2) + add_compile_definitions(OPT_CMSIS_DAPV2=1) +endif() + #-------------------------------------------------------------------------------------------------- # # this is for SIGROK operation (taken from https://github.com/pico-coder/sigrok-pico) diff --git a/include/tusb_config.h b/include/tusb_config.h index 747850215..70ae6fce1 100644 --- a/include/tusb_config.h +++ b/include/tusb_config.h @@ -72,7 +72,11 @@ // This will change in the future. //********************************************** -#define CFG_TUD_CDC_UART 1 // CDC for target UART IO +#if OPT_TARGET_UART // CDC for target UART IO + #define CFG_TUD_CDC_UART 1 +#else + #define CFG_TUD_CDC_UART 0 +#endif #if OPT_SIGROK // CDC for sigrok IO #define CFG_TUD_CDC_SIGROK 1 #else diff --git a/src/cdc_uart.c b/src/cdc_uart.c index d821a2429..f458dc4b9 100644 --- a/src/cdc_uart.c +++ b/src/cdc_uart.c @@ -81,7 +81,6 @@ void cdc_thread(void *ptr) static uint8_t cdc_tx_buf[CFG_TUD_CDC_TX_BUFSIZE]; for (;;) { -#if CFG_TUD_CDC_UART uint32_t cdc_rx_chars; if ( !m_connected) { @@ -170,15 +169,11 @@ void cdc_thread(void *ptr) } } } -#else - xStreamBufferReceive(stream_uart, cdc_tx_buf, sizeof(cdc_tx_buf), pdMS_TO_TICKS(500)); -#endif } } // cdc_thread -#if CFG_TUD_CDC_UART void cdc_uart_line_coding_cb(cdc_line_coding_t const* line_coding) /** * CDC bitrate updates are reflected on \a PICOPROBE_UART_INTERFACE @@ -186,7 +181,6 @@ void cdc_uart_line_coding_cb(cdc_line_coding_t const* line_coding) { uart_set_baudrate(PICOPROBE_UART_INTERFACE, line_coding->bit_rate); } // cdc_uart_line_coding_cb -#endif @@ -196,12 +190,10 @@ void cdc_uart_line_state_cb(bool dtr, bool rts) * This seems to be necessary to survive e.g. a restart of the host (Linux) */ { -#if CFG_TUD_CDC_UART tud_cdc_n_write_clear(CDC_UART_N); tud_cdc_n_read_flush(CDC_UART_N); m_connected = (dtr || rts); xEventGroupSetBits(events, EV_TX_COMPLETE); -#endif } // cdc_uart_line_state_cb diff --git a/src/cdc_uart.h b/src/cdc_uart.h index 546f1e83e..47d4bd83a 100644 --- a/src/cdc_uart.h +++ b/src/cdc_uart.h @@ -30,10 +30,10 @@ #include #include "tusb.h" -void cdc_uart_write(const uint8_t *buf, uint32_t cnt); -void cdc_uart_init(uint32_t task_prio); +#if OPT_TARGET_UART + void cdc_uart_write(const uint8_t *buf, uint32_t cnt); + void cdc_uart_init(uint32_t task_prio); -#if CFG_TUD_CDC_UART void cdc_uart_line_state_cb(bool dtr, bool rts); void cdc_uart_line_coding_cb(cdc_line_coding_t const* line_coding); void cdc_uart_tx_complete_cb(void); diff --git a/src/main.c b/src/main.c index e277d4d9f..d53a69d20 100644 --- a/src/main.c +++ b/src/main.c @@ -47,7 +47,9 @@ #ifndef NDEBUG #include "cdc_debug.h" #endif -#include "cdc_uart.h" +#if OPT_TARGET_UART + #include "cdc_uart.h" +#endif #include "dap_util.h" #include "get_serial.h" #include "led.h" @@ -118,7 +120,7 @@ static EventGroupHandle_t events; void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts) { -#if CFG_TUD_CDC_UART +#if OPT_TARGET_UART if (itf == CDC_UART_N) { cdc_uart_line_state_cb(dtr, rts); } @@ -140,7 +142,7 @@ void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts) #if CFG_TUD_CDC void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const* line_coding) { -#if CFG_TUD_CDC_UART +#if OPT_TARGET_UART if (itf == CDC_UART_N) { cdc_uart_line_coding_cb(line_coding); } @@ -157,7 +159,7 @@ void tud_cdc_rx_cb(uint8_t itf) cdc_sigrok_rx_cb(); } #endif -#if CFG_TUD_CDC_UART +#if OPT_TARGET_UART if (itf == CDC_UART_N) { cdc_uart_rx_cb(); } @@ -173,7 +175,7 @@ void tud_cdc_tx_complete_cb(uint8_t itf) cdc_sigrok_tx_complete_cb(); } #endif -#if CFG_TUD_CDC_UART +#if OPT_TARGET_UART if (itf == CDC_UART_N) { cdc_uart_tx_complete_cb(); } @@ -456,7 +458,9 @@ void usb_thread(void *ptr) g_board_info.prerun_board_config(); } +#if OPT_TARGET_UART cdc_uart_init(UART_TASK_PRIO); +#endif #if OPT_MSC msc_init(MSC_WRITER_THREAD_PRIO); @@ -522,7 +526,7 @@ int main(void) #if OPT_CMSIS_DAPV1 picoprobe_info_out(" [CMSIS-DAPv1]"); #endif -#if CFG_TUD_CDC_UART +#if OPT_TARGET_UART picoprobe_info_out(" [UART -> CDC]"); #endif #if OPT_SIGROK diff --git a/src/rtt_console.c b/src/rtt_console.c index 4c8aa8b55..cec73bd4c 100755 --- a/src/rtt_console.c +++ b/src/rtt_console.c @@ -40,7 +40,9 @@ #include "rtt_console.h" #include "sw_lock.h" #include "RTT/SEGGER_RTT.h" -#include "cdc_uart.h" +#if OPT_TARGET_UART + #include "cdc_uart.h" +#endif #include "led.h" @@ -180,8 +182,10 @@ static void do_rtt_console(uint32_t rtt_cb) aUp.RdOff = (aUp.RdOff + cnt) % aUp.SizeOfBuffer; ok = ok && swd_write_word(rtt_cb + offsetof(SEGGER_RTT_CB, aUp[RTT_CHANNEL_CONSOLE].RdOff), aUp.RdOff); +#if OPT_TARGET_UART // put received data into CDC UART cdc_uart_write(buf, cnt); +#endif led_state(LS_RTT_RX_DATA); } diff --git a/src/usb_descriptors.c b/src/usb_descriptors.c index 3c45a07d2..b93b82a78 100644 --- a/src/usb_descriptors.c +++ b/src/usb_descriptors.c @@ -109,7 +109,7 @@ enum #if OPT_CMSIS_DAPV1 ITF_NUM_PROBE_HID, #endif -#if CFG_TUD_CDC_UART +#if OPT_TARGET_UART ITF_NUM_CDC_UART_COM, ITF_NUM_CDC_UART_DATA, #endif @@ -149,7 +149,7 @@ enum PROBE_HID_OUT_EP_CNT, PROBE_HID_IN_EP_CNT, #endif -#if CFG_TUD_CDC_UART +#if OPT_TARGET_UART CDC_UART_NOTIFICATION_EP_CNT, CDC_UART_DATA_OUT_EP_CNT, CDC_UART_DATA_IN_EP_CNT, @@ -188,7 +188,7 @@ enum #define PROBE_HID_OUT_EP_NUM (PROBE_HID_OUT_EP_CNT + 0x00) #define PROBE_HID_IN_EP_NUM (PROBE_HID_IN_EP_CNT + 0x80) #endif -#if CFG_TUD_CDC_UART +#if OPT_TARGET_UART #define CDC_UART_NOTIFICATION_EP_NUM (CDC_UART_NOTIFICATION_EP_CNT + 0x80) #define CDC_UART_DATA_OUT_EP_NUM (CDC_UART_DATA_OUT_EP_CNT + 0x00) #define CDC_UART_DATA_IN_EP_NUM (CDC_UART_DATA_IN_EP_CNT + 0x80) @@ -263,13 +263,13 @@ static uint8_t const desc_configuration[] = #if OPT_CMSIS_DAPV1 TUD_HID_INOUT_DESCRIPTOR(ITF_NUM_PROBE_HID, STRID_INTERFACE_DAP1, HID_ITF_PROTOCOL_NONE, sizeof(desc_hid_report), PROBE_HID_OUT_EP_NUM, PROBE_HID_IN_EP_NUM, CFG_TUD_HID_EP_BUFSIZE, 1), #endif -#if CFG_TUD_CDC_UART +#if OPT_TARGET_UART TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_UART_COM, STRID_INTERFACE_CDC_UART, CDC_UART_NOTIFICATION_EP_NUM, 64, CDC_UART_DATA_OUT_EP_NUM, CDC_UART_DATA_IN_EP_NUM, 64), #endif #if OPT_SIGROK TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_SIGROK_COM, STRID_INTERFACE_CDC_SIGROK, CDC_SIGROK_NOTIFICATION_EP_NUM, 64, CDC_SIGROK_DATA_OUT_EP_NUM, CDC_SIGROK_DATA_IN_EP_NUM, 64), #endif -#if CFG_TUD_MSC +#if OPT_MSC TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, STRID_INTERFACE_MSC, MSC_OUT_EP_NUM, MSC_IN_EP_NUM, 64), #endif #if OPT_SYSVIEW_RNDIS From 4322bac0083888d13bbac027322312ad3af0cbe9 Mon Sep 17 00:00:00 2001 From: Hardy Griech Date: Sat, 6 May 2023 18:50:35 +0200 Subject: [PATCH 015/118] new OPT_PROBE_DEBUG_OUT --- CMakeLists.txt | 32 ++++++++++++++++++++------------ include/FreeRTOSConfig.h | 4 ++-- include/tusb_config.h | 2 +- src/cdc_debug.c | 7 ------- src/cdc_debug.h | 8 +++++--- src/main.c | 10 +++++----- src/usb_descriptors.c | 8 ++++---- 7 files changed, 37 insertions(+), 34 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d50032e33..bdc82b7aa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,12 +19,20 @@ cmake_minimum_required(VERSION 3.12) if(PICO_BOARD STREQUAL "") set(PICO_BOARD pico) endif() -option(OPT_TARGET_UART "Enable CDC for target UART I/O" 1) -option(OPT_CMSIS_DAPV1 "Enable CMSIS-DAPv1" 1) -option(OPT_CMSIS_DAPV2 "Enable CMSIS-DAPv2" 1) -option(OPT_SYSVIEW_RNDIS "Enable SysView over RNDIS" 1) -option(OPT_SIGROK "Enable sigrok" 0) -option(OPT_MSC "Enable Mass Storage Device" 1) +option(OPT_TARGET_UART "Enable CDC for target UART I/O" 1) +option(OPT_CMSIS_DAPV1 "Enable CMSIS-DAPv1" 1) +option(OPT_CMSIS_DAPV2 "Enable CMSIS-DAPv2" 1) +option(OPT_SYSVIEW_RNDIS "Enable SysView over RNDIS" 1) +option(OPT_SIGROK "Enable sigrok" 0) +option(OPT_MSC "Enable Mass Storage Device" 1) + +if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug") + set(DEFAULT_OPT_PROBE_DEBUG_OUT 1) +else() + set(DEFAULT_OPT_PROBE_DEBUG_OUT 0) +endif() +option(OPT_PROBE_DEBUG_OUT "Enable CDC for probe debug output" ${DEFAULT_OPT_PROBE_DEBUG_OUT}) + # # SDK options @@ -100,12 +108,6 @@ add_executable(${PROJECT} src/usb_descriptors.c ) -if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug") - target_sources(${PROJECT} PRIVATE - src/cdc_debug.c - ) -endif() - target_sources(${PROJECT} PRIVATE CMSIS_5/CMSIS/DAP/Firmware/Source/DAP.c CMSIS_5/CMSIS/DAP/Firmware/Source/JTAG_DP.c @@ -174,6 +176,12 @@ if(OPT_TARGET_UART) src/cdc_uart.c ) endif() +if(OPT_PROBE_DEBUG_OUT) + add_compile_definitions(OPT_PROBE_DEBUG_OUT=1) + target_sources(${PROJECT} PRIVATE + src/cdc_debug.c + ) +endif() if(OPT_CMSIS_DAPV1) add_compile_definitions(OPT_CMSIS_DAPV1=1) endif() diff --git a/include/FreeRTOSConfig.h b/include/FreeRTOSConfig.h index da4f93ce2..c79ddf475 100644 --- a/include/FreeRTOSConfig.h +++ b/include/FreeRTOSConfig.h @@ -52,7 +52,7 @@ #define configTICK_RATE_HZ ( ( TickType_t ) 1000 ) #define configMAX_PRIORITIES 32 -#define configMINIMAL_STACK_SIZE ((configSTACK_DEPTH_TYPE) 2048) +#define configMINIMAL_STACK_SIZE ((configSTACK_DEPTH_TYPE) 1024) #define configUSE_16_BIT_TICKS 0 #define configIDLE_SHOULD_YIELD 1 @@ -78,7 +78,7 @@ /* Memory allocation related definitions. */ #define configSUPPORT_STATIC_ALLOCATION 1 #define configSUPPORT_DYNAMIC_ALLOCATION 1 -#define configTOTAL_HEAP_SIZE (155*1024) +#define configTOTAL_HEAP_SIZE (105*1024) #define configAPPLICATION_ALLOCATED_HEAP 0 /* Hook function related definitions. */ diff --git a/include/tusb_config.h b/include/tusb_config.h index 70ae6fce1..57ec3761e 100644 --- a/include/tusb_config.h +++ b/include/tusb_config.h @@ -82,7 +82,7 @@ #else #define CFG_TUD_CDC_SIGROK 0 #endif -#if !defined(NDEBUG) +#if OPT_PROBE_DEBUG_OUT #define CFG_TUD_CDC_DEBUG 1 // CDC for debug output of the probe #else #define CFG_TUD_CDC_DEBUG 0 diff --git a/src/cdc_debug.c b/src/cdc_debug.c index fa10138f4..7a0816fc5 100644 --- a/src/cdc_debug.c +++ b/src/cdc_debug.c @@ -68,7 +68,6 @@ void cdc_debug_thread(void *ptr) */ { for (;;) { -#if CFG_TUD_CDC_DEBUG if ( !m_connected) { // wait here until connected (and until my terminal program is ready) while ( !m_connected) { @@ -108,10 +107,6 @@ void cdc_debug_thread(void *ptr) tud_cdc_n_read(CDC_UART_N, &ch, sizeof(ch)); } - -#else - xStreamBufferReceive(stream_printf, cdc_debug_buf, sizeof(cdc_debug_buf), pdMS_TO_TICKS(500)); -#endif } } // cdc_debug_thread @@ -123,12 +118,10 @@ void cdc_debug_line_state_cb(bool dtr, bool rts) * This seems to be necessary to survive e.g. a restart of the host (Linux) */ { -#if CFG_TUD_CDC_DEBUG tud_cdc_n_write_clear(CDC_DEBUG_N); tud_cdc_n_read_flush(CDC_DEBUG_N); m_connected = (dtr || rts); xEventGroupSetBits(events, EV_TX_COMPLETE); -#endif } // cdc_debug_line_state_cb diff --git a/src/cdc_debug.h b/src/cdc_debug.h index 369d93ff3..41d3db650 100644 --- a/src/cdc_debug.h +++ b/src/cdc_debug.h @@ -29,8 +29,10 @@ #include #include -void cdc_debug_init(uint32_t task_prio); -void cdc_debug_line_state_cb(bool dtr, bool rts); -void cdc_debug_tx_complete_cb(void); +#if OPT_PROBE_DEBUG_OUT + void cdc_debug_init(uint32_t task_prio); + void cdc_debug_line_state_cb(bool dtr, bool rts); + void cdc_debug_tx_complete_cb(void); +#endif #endif diff --git a/src/main.c b/src/main.c index d53a69d20..cc3e59c13 100644 --- a/src/main.c +++ b/src/main.c @@ -44,7 +44,7 @@ #include "picoprobe_config.h" #include "probe.h" -#ifndef NDEBUG +#if OPT_PROBE_DEBUG_OUT #include "cdc_debug.h" #endif #if OPT_TARGET_UART @@ -125,7 +125,7 @@ void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts) cdc_uart_line_state_cb(dtr, rts); } #endif -#if CFG_TUD_CDC_DEBUG +#if OPT_PROBE_DEBUG_OUT if (itf == CDC_DEBUG_N) { cdc_debug_line_state_cb(dtr, rts); } @@ -180,7 +180,7 @@ void tud_cdc_tx_complete_cb(uint8_t itf) cdc_uart_tx_complete_cb(); } #endif -#if CFG_TUD_CDC_DEBUG +#if OPT_PROBE_DEBUG_OUT if (itf == CDC_DEBUG_N) { cdc_debug_tx_complete_cb(); } @@ -507,7 +507,7 @@ int main(void) usb_serial_init(); // initialize stdio and should be done before anything else (that does printf()) -#if !defined(NDEBUG) +#if OPT_PROBE_DEBUG_OUT cdc_debug_init(CDC_DEBUG_TASK_PRIO); #endif @@ -532,7 +532,7 @@ int main(void) #if OPT_SIGROK picoprobe_info_out(" [sigrok CDC]"); #endif -#if CFG_TUD_CDC_DEBUG +#if OPT_PROBE_DEBUG_OUT picoprobe_info_out(" [probe debug CDC]"); #endif #if OPT_MSC diff --git a/src/usb_descriptors.c b/src/usb_descriptors.c index b93b82a78..3d57e8979 100644 --- a/src/usb_descriptors.c +++ b/src/usb_descriptors.c @@ -129,7 +129,7 @@ enum ITF_NUM_CDC_NCM_DATA, #endif #endif -#if CFG_TUD_CDC_DEBUG +#if OPT_PROBE_DEBUG_OUT ITF_NUM_CDC_DEBUG_COM, ITF_NUM_CDC_DEBUG_DATA, #endif @@ -172,7 +172,7 @@ enum CDC_NCM_DATA_EP_CNT, #endif #endif -#if CFG_TUD_CDC_DEBUG +#if OPT_PROBE_DEBUG_OUT CDC_DEBUG_NOTIFICATION_EP_CNT, CDC_DEBUG_DATA_OUT_EP_CNT, CDC_DEBUG_DATA_IN_EP_CNT, @@ -213,7 +213,7 @@ enum #define CDC_NCM_DATA_IN_EP_NUM (CDC_NCM_DATA_EP_CNT + 0x80) #endif #endif -#if CFG_TUD_CDC_DEBUG +#if OPT_PROBE_DEBUG_OUT #define CDC_DEBUG_NOTIFICATION_EP_NUM (CDC_DEBUG_NOTIFICATION_EP_CNT + 0x80) #define CDC_DEBUG_DATA_OUT_EP_NUM (CDC_DEBUG_DATA_OUT_EP_CNT + 0x00) #define CDC_DEBUG_DATA_IN_EP_NUM (CDC_DEBUG_DATA_IN_EP_CNT + 0x80) @@ -284,7 +284,7 @@ static uint8_t const desc_configuration[] = TUD_CDC_NCM_DESCRIPTOR(ITF_NUM_CDC_NCM_COM, STRID_INTERFACE_RNDIS, STRID_MAC, CDC_NCM_NOTIFICATION_EP_NUM, 64, CDC_NCM_DATA_OUT_EP_NUM, CDC_NCM_DATA_IN_EP_NUM, 64, CFG_TUD_NET_MTU), #endif #endif -#if CFG_TUD_CDC_DEBUG +#if OPT_PROBE_DEBUG_OUT TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_DEBUG_COM, STRID_INTERFACE_CDC_DEBUG, CDC_DEBUG_NOTIFICATION_EP_NUM, 64, CDC_DEBUG_DATA_OUT_EP_NUM, CDC_DEBUG_DATA_IN_EP_NUM, 64), #endif }; From daf0822cf33c5747119486c0f5e9068cf0adbce1 Mon Sep 17 00:00:00 2001 From: Hardy Griech Date: Sat, 6 May 2023 19:55:57 +0200 Subject: [PATCH 016/118] performance enhancement: "nmap -p- 192.168.10.1" factor >10 and no more polling --- include/lwipopts.h | 2 +- src/main.c | 3 ++- src/net_glue.c | 29 ++++++++++++++++++----------- src/net_glue.h | 2 +- 4 files changed, 22 insertions(+), 14 deletions(-) diff --git a/include/lwipopts.h b/include/lwipopts.h index a93f97ac0..728599272 100755 --- a/include/lwipopts.h +++ b/include/lwipopts.h @@ -68,7 +68,7 @@ #define LWIP_PROVIDE_ERRNO 1 #define TCPIP_MBOX_SIZE 32 #define TCPIP_THREAD_STACKSIZE 2048 -#define TCPIP_THREAD_PRIO 10 +#define TCPIP_THREAD_PRIO 11 //#define LWIP_ETHERNET 1 // bringt nix //#define LWIP_ARP 1 // bringt nix diff --git a/src/main.c b/src/main.c index cc3e59c13..56e566ee2 100644 --- a/src/main.c +++ b/src/main.c @@ -105,6 +105,7 @@ static uint8_t RxDataBuffer[_DAP_PACKET_COUNT_OPENOCD * CFG_TUD_VENDOR_RX_BUFSIZ // prios are critical and determine throughput #define TUD_TASK_PRIO (tskIDLE_PRIORITY + 20) // uses one core continuously (no longer valid with FreeRTOS usage) #define LED_TASK_PRIO (tskIDLE_PRIORITY + 12) // simple task which may interrupt everything else for periodic blinking +#define NET_GLUE_TASK_PRIO (tskIDLE_PRIORITY + 10) // task which copies frames from tinyusb to lwip #define SIGROK_TASK_PRIO (tskIDLE_PRIORITY + 9) // Sigrok digital/analog signals (does nothing at the moment) #define MSC_WRITER_THREAD_PRIO (tskIDLE_PRIORITY + 8) // this is only running on writing UF2 files #define UART_TASK_PRIO (tskIDLE_PRIORITY + 5) // target -> host via UART @@ -475,7 +476,7 @@ void usb_thread(void *ptr) #endif #if OPT_SYSVIEW_RNDIS - net_starter_init(3); // TODO + net_glue_init(NET_GLUE_TASK_PRIO); net_echo_init(); #endif diff --git a/src/net_glue.c b/src/net_glue.c index bc7ebe2c9..5e6e02df3 100755 --- a/src/net_glue.c +++ b/src/net_glue.c @@ -49,9 +49,13 @@ #endif #include "FreeRTOS.h" +#include "event_groups.h" + #include "tusb.h" +#define EV_RCVFRAME_READY 1 + /* lwip context */ static struct netif netif_data; @@ -85,7 +89,9 @@ static struct pbuf *received_frame; }; #endif -static TaskHandle_t task_net_starter = NULL; +static TaskHandle_t task_net_glue = NULL; + +static EventGroupHandle_t events; @@ -135,6 +141,7 @@ bool tud_network_recv_cb(const uint8_t *src, uint16_t size) /* store away the pointer for service_traffic() to later handle */ received_frame = p; + xEventGroupSetBits(events, EV_RCVFRAME_READY); } } return true; @@ -265,12 +272,10 @@ static void init_lwip(void) -void net_starter_thread(void *ptr) +void net_glue_thread(void *ptr) { - vTaskDelay(pdMS_TO_TICKS(2000)); - for (;;) { - vTaskDelay(pdMS_TO_TICKS(10)); + xEventGroupWaitBits(events, EV_RCVFRAME_READY, pdTRUE, pdFALSE, pdMS_TO_TICKS(100)); /* handle any packet received by tud_network_recv_cb() */ if (received_frame) { @@ -280,17 +285,19 @@ void net_starter_thread(void *ptr) tud_network_recv_renew(); } } -} // net_starter_thread +} // net_glue_thread -void net_starter_init(uint32_t task_prio) +void net_glue_init(uint32_t task_prio) { + events = xEventGroupCreate(); + init_lwip(); - xTaskCreateAffinitySet(net_starter_thread, "NET_STARTER", configMINIMAL_STACK_SIZE, NULL, task_prio, 1, &task_net_starter); - if (task_net_starter == NULL) + xTaskCreateAffinitySet(net_glue_thread, "NET_GLUE", configMINIMAL_STACK_SIZE, NULL, task_prio, 1, &task_net_glue); + if (task_net_glue == NULL) { - picoprobe_error("net_starter_init: cannot create task_net_starter\n"); + picoprobe_error("net_glue_init: cannot create task_net_glue\n"); } -} // net_starter_init +} // net_glue_init diff --git a/src/net_glue.h b/src/net_glue.h index 4a2f3fd2a..d2e1fa87f 100755 --- a/src/net_glue.h +++ b/src/net_glue.h @@ -35,7 +35,7 @@ #endif -void net_starter_init(uint32_t task_prio); +void net_glue_init(uint32_t task_prio); #ifdef __cplusplus From e836531b76baec9e5faeed06747867ebc7bf5773 Mon Sep 17 00:00:00 2001 From: Hardy Griech Date: Sat, 6 May 2023 20:49:06 +0200 Subject: [PATCH 017/118] DNS as an option --- CMakeLists.txt | 30 +++++++++++-------- include/lwipopts.h | 15 ++++++---- include/tusb_config.h | 4 +-- src/get_serial.c | 4 +-- src/get_serial.h | 2 +- src/main.c | 4 +-- src/net_glue.c | 70 +++++++++++++++++++++---------------------- src/usb_descriptors.c | 16 +++++----- 8 files changed, 76 insertions(+), 69 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bdc82b7aa..d0c278114 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,8 +5,7 @@ # - PICO_BOARD pico|pico_w|pico_debug_probe, default "pico" # - PICOPROBE_VERSION_MAJOR major version number # - PICOPROBE_VERSION_MINOR minor version number -# - OPT_SIGROK enable/disable sigrok module, default "1" -# - OPT_SYSVIEW_RNDIS enable/disable sysview via RNDIS, default "0" +# - lot more options below # # - GIT_HASH short git hash # - PROJECT project name for cmake @@ -19,19 +18,20 @@ cmake_minimum_required(VERSION 3.12) if(PICO_BOARD STREQUAL "") set(PICO_BOARD pico) endif() -option(OPT_TARGET_UART "Enable CDC for target UART I/O" 1) -option(OPT_CMSIS_DAPV1 "Enable CMSIS-DAPv1" 1) -option(OPT_CMSIS_DAPV2 "Enable CMSIS-DAPv2" 1) -option(OPT_SYSVIEW_RNDIS "Enable SysView over RNDIS" 1) -option(OPT_SIGROK "Enable sigrok" 0) -option(OPT_MSC "Enable Mass Storage Device" 1) - if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug") set(DEFAULT_OPT_PROBE_DEBUG_OUT 1) else() set(DEFAULT_OPT_PROBE_DEBUG_OUT 0) endif() + +option(OPT_CMSIS_DAPV1 "Enable CMSIS-DAPv1" 0) +option(OPT_CMSIS_DAPV2 "Enable CMSIS-DAPv2" 0) +option(OPT_TARGET_UART "Enable CDC for target UART I/O" 1) option(OPT_PROBE_DEBUG_OUT "Enable CDC for probe debug output" ${DEFAULT_OPT_PROBE_DEBUG_OUT}) +option(OPT_SIGROK "Enable sigrok" 0) +option(OPT_MSC "Enable Mass Storage Device" 0) +option(OPT_NET_SYSVIEW "Enable SysView over TCPIP" 1) +option(OPT_NET_DNS "Enable DNS on the Pico" 0) # all DNS is going over the Pico!? # @@ -214,15 +214,14 @@ endif() # # this is for SystemView operation (requires RTT) # -if(OPT_SYSVIEW_RNDIS) - add_compile_definitions(OPT_SYSVIEW_RNDIS=1) +if(OPT_NET_SYSVIEW) + add_compile_definitions(OPT_NET_SYSVIEW=1) target_sources(${PROJECT} PRIVATE src/net_glue.c src/net_echo.c ${PICO_TINYUSB_PATH}/lib/networking/dhserver.c - ${PICO_TINYUSB_PATH}/lib/networking/dnserver.c ${PICO_TINYUSB_PATH}/lib/networking/rndis_reports.c ) @@ -233,6 +232,13 @@ if(OPT_SYSVIEW_RNDIS) target_link_libraries(${PROJECT} PRIVATE pico_lwip_freertos ) + + if(OPT_NET_DNS) + add_compile_definitions(OPT_NET_DNS=1) + target_sources(${PROJECT} PRIVATE + ${PICO_TINYUSB_PATH}/lib/networking/dnserver.c + ) + endif() # message("--------- " ${PICO_LWIP_PATH}) # message("--------- " ${PICO_LWIP_CONTRIB_PATH}) diff --git a/include/lwipopts.h b/include/lwipopts.h index 728599272..74a0ed1df 100755 --- a/include/lwipopts.h +++ b/include/lwipopts.h @@ -37,7 +37,7 @@ #define LWIP_RAW 0 #define LWIP_NETCONN 0 #define LWIP_SOCKET 0 -#define LWIP_DHCP 0 +#define LWIP_DHCP 1 #define LWIP_ICMP 1 #define LWIP_UDP 1 #define LWIP_TCP 1 @@ -60,17 +60,20 @@ //#define LWIP_IPV6_MLD 0 //#define LWIP_IPV6_SEND_ROUTER_SOLICIT 0 // -//#define LWIP_PROVIDE_ERRNO 1 -// -// + + +//#define LWIP_AUTOIP 1 +//#define LWIP_DHCP_AUTOIP_COOP (LWIP_DHCP && LWIP_AUTOIP) + + //// meine Versuche //#define LWIP_TCPIP_CORE_LOCKING 1 #define LWIP_PROVIDE_ERRNO 1 + +// for freertos mode #define TCPIP_MBOX_SIZE 32 #define TCPIP_THREAD_STACKSIZE 2048 #define TCPIP_THREAD_PRIO 11 -//#define LWIP_ETHERNET 1 // bringt nix -//#define LWIP_ARP 1 // bringt nix diff --git a/include/tusb_config.h b/include/tusb_config.h index 57ec3761e..cba575945 100644 --- a/include/tusb_config.h +++ b/include/tusb_config.h @@ -104,7 +104,7 @@ #define CFG_TUD_MSC 0 #endif #define CFG_TUD_CDC (CFG_TUD_CDC_UART + CFG_TUD_CDC_SIGROK + CFG_TUD_CDC_DEBUG) -#if OPT_SYSVIEW_RNDIS +#if OPT_NET_SYSVIEW // lsusb output of NCM looks the same as setup from lwip webserver example #define CFG_TUD_ECM_RNDIS 0 // RNDIS under Windows works only if it's the only class, so we try NCM for Linux #define CFG_TUD_NCM (1 - CFG_TUD_ECM_RNDIS) @@ -134,7 +134,7 @@ #define CFG_TUD_MSC_EP_BUFSIZE 512 #endif -#if OPT_SYSVIEW_RNDIS +#if OPT_NET_SYSVIEW #define CFG_TUD_NET_MTU 1514 extern uint8_t tud_network_mac_address[6]; diff --git a/src/get_serial.c b/src/get_serial.c index 2e55dff1d..3a043ebd8 100644 --- a/src/get_serial.c +++ b/src/get_serial.c @@ -32,7 +32,7 @@ /* C string for iSerialNumber in USB Device Descriptor, two chars per byte + terminating NUL */ char usb_serial[PICO_UNIQUE_BOARD_ID_SIZE_BYTES * 2 + 1]; -#if OPT_SYSVIEW_RNDIS +#if OPT_NET_SYSVIEW uint8_t tud_network_mac_address[6]; #endif @@ -43,7 +43,7 @@ void usb_serial_init(void) pico_get_unique_board_id(&uID); -#if OPT_SYSVIEW_RNDIS +#if OPT_NET_SYSVIEW tud_network_mac_address[0] = 0xfe; // 0xfe is allowed for local use, never use odd numbers here (group/multicast) for (int i = 1; i < sizeof(tud_network_mac_address); ++i) { diff --git a/src/get_serial.h b/src/get_serial.h index 39c10dc63..ee5e5160f 100644 --- a/src/get_serial.h +++ b/src/get_serial.h @@ -29,7 +29,7 @@ /* Contains unique serial number string (NUL terminated) after call to init_usb_serial */ extern char usb_serial[]; -#if OPT_SYSVIEW_RNDIS +#if OPT_NET_SYSVIEW extern uint8_t tud_network_mac_address[]; #endif diff --git a/src/main.c b/src/main.c index 56e566ee2..eaf1bebb5 100644 --- a/src/main.c +++ b/src/main.c @@ -69,7 +69,7 @@ #include "pico-sigrok/cdc_sigrok.h" #include "pico-sigrok/sigrok.h" #endif -#if OPT_SYSVIEW_RNDIS +#if OPT_NET_SYSVIEW #include "net_glue.h" #include "net_echo.h" #endif @@ -475,7 +475,7 @@ void usb_thread(void *ptr) sigrok_init(SIGROK_TASK_PRIO); #endif -#if OPT_SYSVIEW_RNDIS +#if OPT_NET_SYSVIEW net_glue_init(NET_GLUE_TASK_PRIO); net_echo_init(); #endif diff --git a/src/net_glue.c b/src/net_glue.c index 5e6e02df3..b2d23496a 100755 --- a/src/net_glue.c +++ b/src/net_glue.c @@ -43,8 +43,8 @@ #include "lwip/ethip6.h" #include "lwip/tcpip.h" -#if LWIP_IPV4 - #include "dhserver.h" +#include "dhserver.h" +#if OPT_NET_DNS #include "dnserver.h" #endif @@ -63,31 +63,33 @@ static struct netif netif_data; /* shared between tud_network_recv_cb() and service_traffic() */ static struct pbuf *received_frame; -#if LWIP_IPV4 - /* network parameters of this MCU */ - static const ip4_addr_t ipaddr = IPADDR4_INIT_BYTES(192, 168, 10, 1); - static const ip4_addr_t netmask = IPADDR4_INIT_BYTES(255, 255, 255, 0); - static const ip4_addr_t gateway = IPADDR4_INIT_BYTES(0, 0, 0, 0); +/* network parameters of this MCU */ +static const ip4_addr_t ipaddr = IPADDR4_INIT_BYTES(192, 168, 10, 1); +static const ip4_addr_t netmask = IPADDR4_INIT_BYTES(255, 255, 255, 0); +static const ip4_addr_t gateway = IPADDR4_INIT_BYTES(0, 0, 0, 0); - /* database IP addresses that can be offered to the host; this must be in RAM to store assigned MAC addresses */ - static dhcp_entry_t entries[] = - { - /* mac ip address lease time */ - { {0}, IPADDR4_INIT_BYTES(192, 168, 10, 2), 24 * 60 * 60 }, - { {0}, IPADDR4_INIT_BYTES(192, 168, 10, 3), 24 * 60 * 60 }, - { {0}, IPADDR4_INIT_BYTES(192, 168, 10, 4), 24 * 60 * 60 }, - }; +/* database IP addresses that can be offered to the host; this must be in RAM to store assigned MAC addresses */ +static dhcp_entry_t entries[] = +{ + /* mac ip address lease time */ + { {0}, IPADDR4_INIT_BYTES(192, 168, 10, 2), 24 * 60 * 60 }, + { {0}, IPADDR4_INIT_BYTES(192, 168, 10, 3), 24 * 60 * 60 }, + { {0}, IPADDR4_INIT_BYTES(192, 168, 10, 4), 24 * 60 * 60 }, +}; - static const dhcp_config_t dhcp_config = - { - .router = IPADDR4_INIT_BYTES(0, 0, 0, 0), /* router address (if any) */ - .port = 67, /* listen port */ - .dns = IPADDR4_INIT_BYTES(0, 0, 0, 0), /* dns server (if any) */ - "usb", /* dns suffix */ - TU_ARRAY_SIZE(entries), /* num entry */ - entries /* entries */ - }; +static const dhcp_config_t dhcp_config = +{ + .router = IPADDR4_INIT_BYTES(0, 0, 0, 0), /* router address (if any) */ + .port = 67, /* listen port */ +#if OPT_NET_DNS + .dns = IPADDR4_INIT_BYTES(192, 168, 10, 1),/* dns server (if any) */ +#else + .dns = IPADDR4_INIT_BYTES(0, 0, 0, 0), #endif + "usb", /* dns suffix */ + TU_ARRAY_SIZE(entries), /* num entry */ + entries /* entries */ +}; static TaskHandle_t task_net_glue = NULL; @@ -95,9 +97,12 @@ static EventGroupHandle_t events; -#if LWIP_IPV4 -/* handle any DNS requests from dns-server */ -bool dns_query_proc(const char *name, ip4_addr_t *addr) +#if OPT_NET_DNS +static bool dns_query_proc(const char *name, ip4_addr_t *addr) +/** + * Handle any DNS requests from dns-server + * If enabled all DNS requests seem to go over the Pico!? + */ { printf("dns_query_proc(%s,.)\n", name); @@ -201,12 +206,10 @@ static err_t linkoutput_fn(struct netif *netif, struct pbuf *p) -#if LWIP_IPV4 static err_t ip4_output_fn(struct netif *netif, struct pbuf *p, const ip4_addr_t *addr) { return etharp_output(netif, p, addr); } // ip4_output_fn -#endif @@ -228,9 +231,7 @@ static err_t netif_init_cb(struct netif *netif) netif->name[0] = 'E'; netif->name[1] = 'X'; netif->linkoutput = linkoutput_fn; -#if LWIP_IPV4 netif->output = ip4_output_fn; -#endif #if LWIP_IPV6 netif->output_ip6 = ip6_output_fn; #endif @@ -250,11 +251,7 @@ static void init_lwip(void) memcpy(netif->hwaddr, tud_network_mac_address, sizeof(tud_network_mac_address)); netif->hwaddr[5] ^= 0x01; -#if LWIP_IPV4 netif = netif_add(netif, &ipaddr, &netmask, &gateway, NULL, netif_init_cb, ip_input); -#else - netif = netif_add(netif, NULL, netif_init_cb, ip_input); -#endif #if LWIP_IPV6 netif_create_ip6_linklocal_address(netif, 1); #endif @@ -262,9 +259,10 @@ static void init_lwip(void) while ( !netif_is_up(netif)) ; -#if LWIP_IPV4 + while (dhserv_init(&dhcp_config) != ERR_OK) ; +#if OPT_NET_DNS while (dnserv_init(IP_ADDR_ANY, 53, dns_query_proc) != ERR_OK) ; #endif diff --git a/src/usb_descriptors.c b/src/usb_descriptors.c index 3d57e8979..be683e121 100644 --- a/src/usb_descriptors.c +++ b/src/usb_descriptors.c @@ -35,7 +35,7 @@ // String enums //--------------------------------------------------------------------+ -// 0 -> ECM, OPT_SYSVIEW_RNDIS must be enabled +// 0 -> ECM, OPT_NET_SYSVIEW must be enabled #define USE_RNDIS 1 enum @@ -52,7 +52,7 @@ enum STRID_INTERFACE_CDC_SIGROK, #endif STRID_INTERFACE_CDC_DEBUG, -#if OPT_SYSVIEW_RNDIS +#if OPT_NET_SYSVIEW STRID_INTERFACE_RNDIS, STRID_MAC, #endif @@ -120,7 +120,7 @@ enum #if OPT_MSC ITF_NUM_MSC, #endif -#if OPT_SYSVIEW_RNDIS +#if OPT_NET_SYSVIEW #if CFG_TUD_ECM_RNDIS ITF_NUM_CDC_RNDIS_COM, ITF_NUM_CDC_RNDIS_DATA, @@ -163,7 +163,7 @@ enum MSC_OUT_EP_CNT, MSC_IN_EP_CNT, #endif -#if OPT_SYSVIEW_RNDIS +#if OPT_NET_SYSVIEW #if CFG_TUD_ECM_RNDIS CDC_RNDIS_NOTIFICATION_EP_CNT, CDC_RNDIS_DATA_EP_CNT, @@ -202,7 +202,7 @@ enum #define MSC_OUT_EP_NUM (MSC_OUT_EP_CNT + 0x00) #define MSC_IN_EP_NUM (MSC_IN_EP_CNT + 0x80) #endif -#if OPT_SYSVIEW_RNDIS +#if OPT_NET_SYSVIEW #if CFG_TUD_ECM_RNDIS #define CDC_RNDIS_NOTIFICATION_EP_NUM (CDC_RNDIS_NOTIFICATION_EP_CNT + 0x80) #define CDC_RNDIS_DATA_OUT_EP_NUM (CDC_RNDIS_DATA_EP_CNT + 0x00) @@ -272,7 +272,7 @@ static uint8_t const desc_configuration[] = #if OPT_MSC TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, STRID_INTERFACE_MSC, MSC_OUT_EP_NUM, MSC_IN_EP_NUM, 64), #endif -#if OPT_SYSVIEW_RNDIS +#if OPT_NET_SYSVIEW #if CFG_TUD_ECM_RNDIS #if USE_RNDIS TUD_RNDIS_DESCRIPTOR(ITF_NUM_CDC_RNDIS_COM, STRID_INTERFACE_RNDIS, CDC_RNDIS_NOTIFICATION_EP_NUM, 8, CDC_RNDIS_DATA_OUT_EP_NUM, CDC_RNDIS_DATA_IN_EP_NUM, 64), @@ -319,7 +319,7 @@ static char const* string_desc_arr[] = [STRID_INTERFACE_CDC_SIGROK] = "YAPicoprobe CDC-SIGROK", // Interface descriptor for CDC SIGROK #endif [STRID_INTERFACE_CDC_DEBUG] = "YAPicoprobe CDC-DEBUG", // Interface descriptor for CDC DEBUG -#if OPT_SYSVIEW_RNDIS +#if OPT_NET_SYSVIEW #if CFG_TUD_ECM_RNDIS #if USE_RNDIS [STRID_INTERFACE_RNDIS] = "YaPicoprobe SysView RNDIS", // Interface descriptor for SysView RNDIS @@ -347,7 +347,7 @@ uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid) memcpy( &_desc_str[1], string_desc_arr[0], 2); chr_count = 1; } -#if OPT_SYSVIEW_RNDIS +#if OPT_NET_SYSVIEW else if (index == STRID_MAC) { // Convert MAC address into UTF-16 for (unsigned i = 0; i < sizeof(tud_network_mac_address); ++i) { From fa664c1e55f734eeada38764fdd659f72e46feb6 Mon Sep 17 00:00:00 2001 From: Hardy Griech Date: Sat, 6 May 2023 20:54:32 +0200 Subject: [PATCH 018/118] rename OPT_NET_SYSVIEW -> OPT_NET --- CMakeLists.txt | 5 +++-- include/tusb_config.h | 4 ++-- src/get_serial.c | 4 ++-- src/get_serial.h | 2 +- src/main.c | 4 ++-- src/usb_descriptors.c | 16 ++++++++-------- 6 files changed, 18 insertions(+), 17 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d0c278114..a6640356d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,6 +30,7 @@ option(OPT_TARGET_UART "Enable CDC for target UART I/O" 1) option(OPT_PROBE_DEBUG_OUT "Enable CDC for probe debug output" ${DEFAULT_OPT_PROBE_DEBUG_OUT}) option(OPT_SIGROK "Enable sigrok" 0) option(OPT_MSC "Enable Mass Storage Device" 0) +option(OPT_NET "Enable lwIP on the Pico" 1) option(OPT_NET_SYSVIEW "Enable SysView over TCPIP" 1) option(OPT_NET_DNS "Enable DNS on the Pico" 0) # all DNS is going over the Pico!? @@ -214,8 +215,8 @@ endif() # # this is for SystemView operation (requires RTT) # -if(OPT_NET_SYSVIEW) - add_compile_definitions(OPT_NET_SYSVIEW=1) +if(OPT_NET) + add_compile_definitions(OPT_NET=1) target_sources(${PROJECT} PRIVATE src/net_glue.c diff --git a/include/tusb_config.h b/include/tusb_config.h index cba575945..0094f53c2 100644 --- a/include/tusb_config.h +++ b/include/tusb_config.h @@ -104,7 +104,7 @@ #define CFG_TUD_MSC 0 #endif #define CFG_TUD_CDC (CFG_TUD_CDC_UART + CFG_TUD_CDC_SIGROK + CFG_TUD_CDC_DEBUG) -#if OPT_NET_SYSVIEW +#if OPT_NET // lsusb output of NCM looks the same as setup from lwip webserver example #define CFG_TUD_ECM_RNDIS 0 // RNDIS under Windows works only if it's the only class, so we try NCM for Linux #define CFG_TUD_NCM (1 - CFG_TUD_ECM_RNDIS) @@ -134,7 +134,7 @@ #define CFG_TUD_MSC_EP_BUFSIZE 512 #endif -#if OPT_NET_SYSVIEW +#if OPT_NET #define CFG_TUD_NET_MTU 1514 extern uint8_t tud_network_mac_address[6]; diff --git a/src/get_serial.c b/src/get_serial.c index 3a043ebd8..922cbe7d6 100644 --- a/src/get_serial.c +++ b/src/get_serial.c @@ -32,7 +32,7 @@ /* C string for iSerialNumber in USB Device Descriptor, two chars per byte + terminating NUL */ char usb_serial[PICO_UNIQUE_BOARD_ID_SIZE_BYTES * 2 + 1]; -#if OPT_NET_SYSVIEW +#if OPT_NET uint8_t tud_network_mac_address[6]; #endif @@ -43,7 +43,7 @@ void usb_serial_init(void) pico_get_unique_board_id(&uID); -#if OPT_NET_SYSVIEW +#if OPT_NET tud_network_mac_address[0] = 0xfe; // 0xfe is allowed for local use, never use odd numbers here (group/multicast) for (int i = 1; i < sizeof(tud_network_mac_address); ++i) { diff --git a/src/get_serial.h b/src/get_serial.h index ee5e5160f..47247c24e 100644 --- a/src/get_serial.h +++ b/src/get_serial.h @@ -29,7 +29,7 @@ /* Contains unique serial number string (NUL terminated) after call to init_usb_serial */ extern char usb_serial[]; -#if OPT_NET_SYSVIEW +#if OPT_NET extern uint8_t tud_network_mac_address[]; #endif diff --git a/src/main.c b/src/main.c index eaf1bebb5..9d626062f 100644 --- a/src/main.c +++ b/src/main.c @@ -69,7 +69,7 @@ #include "pico-sigrok/cdc_sigrok.h" #include "pico-sigrok/sigrok.h" #endif -#if OPT_NET_SYSVIEW +#if OPT_NET #include "net_glue.h" #include "net_echo.h" #endif @@ -475,7 +475,7 @@ void usb_thread(void *ptr) sigrok_init(SIGROK_TASK_PRIO); #endif -#if OPT_NET_SYSVIEW +#if OPT_NET net_glue_init(NET_GLUE_TASK_PRIO); net_echo_init(); #endif diff --git a/src/usb_descriptors.c b/src/usb_descriptors.c index be683e121..e4065fab8 100644 --- a/src/usb_descriptors.c +++ b/src/usb_descriptors.c @@ -35,7 +35,7 @@ // String enums //--------------------------------------------------------------------+ -// 0 -> ECM, OPT_NET_SYSVIEW must be enabled +// 0 -> ECM, OPT_NET must be enabled #define USE_RNDIS 1 enum @@ -52,7 +52,7 @@ enum STRID_INTERFACE_CDC_SIGROK, #endif STRID_INTERFACE_CDC_DEBUG, -#if OPT_NET_SYSVIEW +#if OPT_NET STRID_INTERFACE_RNDIS, STRID_MAC, #endif @@ -120,7 +120,7 @@ enum #if OPT_MSC ITF_NUM_MSC, #endif -#if OPT_NET_SYSVIEW +#if OPT_NET #if CFG_TUD_ECM_RNDIS ITF_NUM_CDC_RNDIS_COM, ITF_NUM_CDC_RNDIS_DATA, @@ -163,7 +163,7 @@ enum MSC_OUT_EP_CNT, MSC_IN_EP_CNT, #endif -#if OPT_NET_SYSVIEW +#if OPT_NET #if CFG_TUD_ECM_RNDIS CDC_RNDIS_NOTIFICATION_EP_CNT, CDC_RNDIS_DATA_EP_CNT, @@ -202,7 +202,7 @@ enum #define MSC_OUT_EP_NUM (MSC_OUT_EP_CNT + 0x00) #define MSC_IN_EP_NUM (MSC_IN_EP_CNT + 0x80) #endif -#if OPT_NET_SYSVIEW +#if OPT_NET #if CFG_TUD_ECM_RNDIS #define CDC_RNDIS_NOTIFICATION_EP_NUM (CDC_RNDIS_NOTIFICATION_EP_CNT + 0x80) #define CDC_RNDIS_DATA_OUT_EP_NUM (CDC_RNDIS_DATA_EP_CNT + 0x00) @@ -272,7 +272,7 @@ static uint8_t const desc_configuration[] = #if OPT_MSC TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, STRID_INTERFACE_MSC, MSC_OUT_EP_NUM, MSC_IN_EP_NUM, 64), #endif -#if OPT_NET_SYSVIEW +#if OPT_NET #if CFG_TUD_ECM_RNDIS #if USE_RNDIS TUD_RNDIS_DESCRIPTOR(ITF_NUM_CDC_RNDIS_COM, STRID_INTERFACE_RNDIS, CDC_RNDIS_NOTIFICATION_EP_NUM, 8, CDC_RNDIS_DATA_OUT_EP_NUM, CDC_RNDIS_DATA_IN_EP_NUM, 64), @@ -319,7 +319,7 @@ static char const* string_desc_arr[] = [STRID_INTERFACE_CDC_SIGROK] = "YAPicoprobe CDC-SIGROK", // Interface descriptor for CDC SIGROK #endif [STRID_INTERFACE_CDC_DEBUG] = "YAPicoprobe CDC-DEBUG", // Interface descriptor for CDC DEBUG -#if OPT_NET_SYSVIEW +#if OPT_NET #if CFG_TUD_ECM_RNDIS #if USE_RNDIS [STRID_INTERFACE_RNDIS] = "YaPicoprobe SysView RNDIS", // Interface descriptor for SysView RNDIS @@ -347,7 +347,7 @@ uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid) memcpy( &_desc_str[1], string_desc_arr[0], 2); chr_count = 1; } -#if OPT_NET_SYSVIEW +#if OPT_NET else if (index == STRID_MAC) { // Convert MAC address into UTF-16 for (unsigned i = 0; i < sizeof(tud_network_mac_address); ++i) { From 88e8e8a304a2821cdbf604a5b4febeb304bd569d Mon Sep 17 00:00:00 2001 From: Hardy Griech Date: Sun, 7 May 2023 10:11:22 +0200 Subject: [PATCH 019/118] options: OPT_NET_ECHO_SERVER and OPT_NET_IPERF_SERVER --- include/lwipopts.h | 70 ++++++++++++++++++++++++---------------- src/main.c | 18 +++++++++-- src/{ => net}/net_echo.c | 0 src/{ => net}/net_echo.h | 0 src/{ => net}/net_glue.c | 2 +- src/{ => net}/net_glue.h | 0 6 files changed, 59 insertions(+), 31 deletions(-) rename src/{ => net}/net_echo.c (100%) rename src/{ => net}/net_echo.h (100%) rename src/{ => net}/net_glue.c (99%) rename src/{ => net}/net_glue.h (100%) diff --git a/include/lwipopts.h b/include/lwipopts.h index 74a0ed1df..868c7e983 100755 --- a/include/lwipopts.h +++ b/include/lwipopts.h @@ -34,52 +34,68 @@ #define NO_SYS 0 #define MEM_ALIGNMENT 4 -#define LWIP_RAW 0 -#define LWIP_NETCONN 0 -#define LWIP_SOCKET 0 -#define LWIP_DHCP 1 -#define LWIP_ICMP 1 +#define LWIP_IPV6 0 // default: 0 +#define LWIP_RAW 0 // default: 0 +#define LWIP_NETCONN 0 // default: 0 +#define LWIP_SOCKET 0 // default: 0, provide socket API #define LWIP_UDP 1 #define LWIP_TCP 1 -#define ETH_PAD_SIZE 0 -#define LWIP_IP_ACCEPT_UDP_PORT(p) ((p) == PP_NTOHS(67)) -#define TCP_MSS (1500 /*mtu*/ - 20 /*iphdr*/ - 20 /*tcphhr*/) -#define TCP_SND_BUF (2 * TCP_MSS) +// ARP +#define LWIP_ARP 1 // default: 1 +//#define ETH_PAD_SIZE 0 +//#define ETHARP_SUPPORT_STATIC_ENTRIES 1 +#define ARP_TABLE_SIZE 4 -#define ETHARP_SUPPORT_STATIC_ENTRIES 1 +// ICMP +#define LWIP_ICMP 1 // default: 1 +//#define LWIP_MULTICAST_PING 1 +//#define LWIP_BROADCAST_PING 1 -#define LWIP_SINGLE_NETIF 1 +// DHCP TODO required? +#define LWIP_DHCP 1 +//#define LWIP_IP_ACCEPT_UDP_PORT(p) ((p) == PP_NTOHS(67)) -//#define PBUF_POOL_SIZE 2 -//// -////#define HTTPD_USE_CUSTOM_FSDATA 0 -//// -#define LWIP_MULTICAST_PING 1 -#define LWIP_BROADCAST_PING 1 -//#define LWIP_IPV6_MLD 0 -//#define LWIP_IPV6_SEND_ROUTER_SOLICIT 0 -// +// AUTOIP +//#define LWIP_AUTOIP 1 // default: 0 +//#define LWIP_DHCP_AUTOIP_COOP (LWIP_DHCP && LWIP_AUTOIP) +// netif +#define LWIP_SINGLE_NETIF 1 -//#define LWIP_AUTOIP 1 -//#define LWIP_DHCP_AUTOIP_COOP (LWIP_DHCP && LWIP_AUTOIP) +//-------------------------------------- +// performance tuning +#define TCP_MSS (1500 - 20 - 20) // MTU minus header sizes (best value til now) +//#define TCP_SND_BUF (2 * TCP_MSS) +//#define TCP_OVERSIZE TCP_MSS -//// meine Versuche -//#define LWIP_TCPIP_CORE_LOCKING 1 -#define LWIP_PROVIDE_ERRNO 1 +//-------------------------------------- // for freertos mode #define TCPIP_MBOX_SIZE 32 #define TCPIP_THREAD_STACKSIZE 2048 #define TCPIP_THREAD_PRIO 11 +//-------------------------------------- +// trying... +#define LWIP_PROVIDE_ERRNO 1 +#if LWIP_SOCKET + #define LWIP_TIMEVAL_PRIVATE 0 // required for LWIP_SOCKET +#endif -// Debugging (was sonst?) -//#define LWIP_DEBUG +//-------------------------------------- +// statistics +//#define LWIP_STATS 1 +//#define LWIP_STATS_DISPLAY 1 +//#define LINK_STATS 1 + + +//-------------------------------------- +// debugging +//#define LWIP_DEBUG #define API_LIB_DEBUG LWIP_DBG_ON #define API_MSG_DEBUG LWIP_DBG_ON #define AUTOIP_DEBUG LWIP_DBG_ON diff --git a/src/main.c b/src/main.c index 9d626062f..c460979a5 100644 --- a/src/main.c +++ b/src/main.c @@ -70,8 +70,13 @@ #include "pico-sigrok/sigrok.h" #endif #if OPT_NET - #include "net_glue.h" - #include "net_echo.h" + #include "net/net_glue.h" + #if OPT_NET_ECHO_SERVER + #include "net/net_echo.h" + #endif + #if OPT_NET_IPERF_SERVER + #include "lwip/apps/lwiperf.h" + #endif #endif @@ -103,6 +108,7 @@ static uint8_t RxDataBuffer[_DAP_PACKET_COUNT_OPENOCD * CFG_TUD_VENDOR_RX_BUFSIZ // prios are critical and determine throughput +// there is one more task prio in lwipopts.h #define TUD_TASK_PRIO (tskIDLE_PRIORITY + 20) // uses one core continuously (no longer valid with FreeRTOS usage) #define LED_TASK_PRIO (tskIDLE_PRIORITY + 12) // simple task which may interrupt everything else for periodic blinking #define NET_GLUE_TASK_PRIO (tskIDLE_PRIORITY + 10) // task which copies frames from tinyusb to lwip @@ -477,7 +483,13 @@ void usb_thread(void *ptr) #if OPT_NET net_glue_init(NET_GLUE_TASK_PRIO); - net_echo_init(); + #if OPT_NET_ECHO_SERVER + net_echo_init(); + #endif + #if OPT_NET_IPERF_SERVER + // test with: iperf -c 192.168.10.1 -e -i 1 -l 1024 + lwiperf_start_tcp_server_default(NULL, NULL); + #endif #endif #if OPT_CMSIS_DAPV2 diff --git a/src/net_echo.c b/src/net/net_echo.c similarity index 100% rename from src/net_echo.c rename to src/net/net_echo.c diff --git a/src/net_echo.h b/src/net/net_echo.h similarity index 100% rename from src/net_echo.h rename to src/net/net_echo.h diff --git a/src/net_glue.c b/src/net/net_glue.c similarity index 99% rename from src/net_glue.c rename to src/net/net_glue.c index b2d23496a..fc21ddc12 100755 --- a/src/net_glue.c +++ b/src/net/net_glue.c @@ -249,7 +249,7 @@ static void init_lwip(void) /* the lwip virtual MAC address must be different from the host's; to ensure this, we toggle the LSbit */ netif->hwaddr_len = sizeof(tud_network_mac_address); memcpy(netif->hwaddr, tud_network_mac_address, sizeof(tud_network_mac_address)); - netif->hwaddr[5] ^= 0x01; + //netif->hwaddr[5] ^= 0x01; netif = netif_add(netif, &ipaddr, &netmask, &gateway, NULL, netif_init_cb, ip_input); #if LWIP_IPV6 diff --git a/src/net_glue.h b/src/net/net_glue.h similarity index 100% rename from src/net_glue.h rename to src/net/net_glue.h From e6bcc07af21eb3a62f1036fc86bbab7607a9a903 Mon Sep 17 00:00:00 2001 From: Hardy Griech Date: Sun, 7 May 2023 11:12:33 +0200 Subject: [PATCH 020/118] added static at some places --- src/net/net_echo.c | 28 ++++++++++++++-------------- src/net/net_glue.c | 2 +- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/net/net_echo.c b/src/net/net_echo.c index 98e130865..ebf2c3783 100755 --- a/src/net/net_echo.c +++ b/src/net/net_echo.c @@ -49,13 +49,13 @@ struct echo_state struct pbuf *p; }; -err_t echo_accept(void *arg, struct tcp_pcb *newpcb, err_t err); -err_t echo_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err); -void echo_error(void *arg, err_t err); -err_t echo_poll(void *arg, struct tcp_pcb *tpcb); -err_t echo_sent(void *arg, struct tcp_pcb *tpcb, u16_t len); -void echo_send(struct tcp_pcb *tpcb, struct echo_state *es); -void echo_close(struct tcp_pcb *tpcb, struct echo_state *es); +static err_t echo_accept(void *arg, struct tcp_pcb *newpcb, err_t err); +static err_t echo_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err); +static void echo_error(void *arg, err_t err); +static err_t echo_poll(void *arg, struct tcp_pcb *tpcb); +static err_t echo_sent(void *arg, struct tcp_pcb *tpcb, u16_t len); +static void echo_send(struct tcp_pcb *tpcb, struct echo_state *es); +static void echo_close(struct tcp_pcb *tpcb, struct echo_state *es); @@ -85,7 +85,7 @@ void net_echo_init(void) -err_t echo_accept(void *arg, struct tcp_pcb *newpcb, err_t err) +static err_t echo_accept(void *arg, struct tcp_pcb *newpcb, err_t err) { err_t ret_err; struct echo_state *es; @@ -119,7 +119,7 @@ err_t echo_accept(void *arg, struct tcp_pcb *newpcb, err_t err) -err_t echo_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) +static err_t echo_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) { struct echo_state *es; err_t ret_err; @@ -204,7 +204,7 @@ err_t echo_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) -void echo_error(void *arg, err_t err) +static void echo_error(void *arg, err_t err) { struct echo_state *es; @@ -219,7 +219,7 @@ void echo_error(void *arg, err_t err) -err_t echo_poll(void *arg, struct tcp_pcb *tpcb) +static err_t echo_poll(void *arg, struct tcp_pcb *tpcb) { err_t ret_err; struct echo_state *es; @@ -254,7 +254,7 @@ err_t echo_poll(void *arg, struct tcp_pcb *tpcb) -err_t echo_sent(void *arg, struct tcp_pcb *tpcb, u16_t len) +static err_t echo_sent(void *arg, struct tcp_pcb *tpcb, u16_t len) { struct echo_state *es; @@ -282,7 +282,7 @@ err_t echo_sent(void *arg, struct tcp_pcb *tpcb, u16_t len) -void echo_send(struct tcp_pcb *tpcb, struct echo_state *es) +static void echo_send(struct tcp_pcb *tpcb, struct echo_state *es) { struct pbuf *ptr; err_t wr_err = ERR_OK; @@ -332,7 +332,7 @@ void echo_send(struct tcp_pcb *tpcb, struct echo_state *es) -void echo_close(struct tcp_pcb *tpcb, struct echo_state *es) +static void echo_close(struct tcp_pcb *tpcb, struct echo_state *es) { tcp_arg(tpcb, NULL); tcp_sent(tpcb, NULL); diff --git a/src/net/net_glue.c b/src/net/net_glue.c index fc21ddc12..a671bddc7 100755 --- a/src/net/net_glue.c +++ b/src/net/net_glue.c @@ -270,7 +270,7 @@ static void init_lwip(void) -void net_glue_thread(void *ptr) +static void net_glue_thread(void *ptr) { for (;;) { xEventGroupWaitBits(events, EV_RCVFRAME_READY, pdTRUE, pdFALSE, pdMS_TO_TICKS(100)); From a79c5d4f01eb0ed07b282a841f7e2bda94152453 Mon Sep 17 00:00:00 2001 From: Hardy Griech Date: Sun, 7 May 2023 11:13:16 +0200 Subject: [PATCH 021/118] OPT_NET_SYSVIEW_SERVER as an option (currently the echo server) --- CMakeLists.txt | 44 ++++-- src/main.c | 6 + src/net/net_sysview.c | 353 ++++++++++++++++++++++++++++++++++++++++++ src/net/net_sysview.h | 43 +++++ 4 files changed, 435 insertions(+), 11 deletions(-) create mode 100755 src/net/net_sysview.c create mode 100755 src/net/net_sysview.h diff --git a/CMakeLists.txt b/CMakeLists.txt index a6640356d..ba5149209 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,15 +24,17 @@ else() set(DEFAULT_OPT_PROBE_DEBUG_OUT 0) endif() -option(OPT_CMSIS_DAPV1 "Enable CMSIS-DAPv1" 0) -option(OPT_CMSIS_DAPV2 "Enable CMSIS-DAPv2" 0) -option(OPT_TARGET_UART "Enable CDC for target UART I/O" 1) -option(OPT_PROBE_DEBUG_OUT "Enable CDC for probe debug output" ${DEFAULT_OPT_PROBE_DEBUG_OUT}) -option(OPT_SIGROK "Enable sigrok" 0) -option(OPT_MSC "Enable Mass Storage Device" 0) -option(OPT_NET "Enable lwIP on the Pico" 1) -option(OPT_NET_SYSVIEW "Enable SysView over TCPIP" 1) -option(OPT_NET_DNS "Enable DNS on the Pico" 0) # all DNS is going over the Pico!? +option(OPT_CMSIS_DAPV1 "Enable CMSIS-DAPv1" 0) +option(OPT_CMSIS_DAPV2 "Enable CMSIS-DAPv2" 0) +option(OPT_TARGET_UART "Enable CDC for target UART I/O" 1) +option(OPT_PROBE_DEBUG_OUT "Enable CDC for probe debug output" ${DEFAULT_OPT_PROBE_DEBUG_OUT}) +option(OPT_SIGROK "Enable sigrok" 0) +option(OPT_MSC "Enable Mass Storage Device" 0) +option(OPT_NET "Enable lwIP on the Pico" 1) +option(OPT_NET_DNS "Enable DNS on the Pico" 0) # all DNS is going over the Pico!? +option(OPT_NET_ECHO_SERVER "Enable echo server for testing" 1) +option(OPT_NET_IPERF_SERVER "Enable iperf server for tuning" 1) +option(OPT_NET_SYSVIEW_SERVER "Enable SysView over TCPIP" 1) # @@ -219,8 +221,7 @@ if(OPT_NET) add_compile_definitions(OPT_NET=1) target_sources(${PROJECT} PRIVATE - src/net_glue.c - src/net_echo.c + src/net/net_glue.c ${PICO_TINYUSB_PATH}/lib/networking/dhserver.c ${PICO_TINYUSB_PATH}/lib/networking/rndis_reports.c @@ -241,6 +242,27 @@ if(OPT_NET) ) endif() + if(OPT_NET_SYSVIEW_SERVER) + add_compile_definitions(OPT_NET_SYSVIEW_SERVER=1) + target_sources(${PROJECT} PRIVATE + src/net/net_sysview.c + ) + endif() + + if(OPT_NET_ECHO_SERVER) + add_compile_definitions(OPT_NET_ECHO_SERVER=1) + target_sources(${PROJECT} PRIVATE + src/net/net_echo.c + ) + endif() + + if(OPT_NET_IPERF_SERVER) + add_compile_definitions(OPT_NET_IPERF_SERVER=1) + target_sources(${PROJECT} PRIVATE + ${PICO_LWIP_PATH}/src/apps/lwiperf/lwiperf.c + ) + endif() + # message("--------- " ${PICO_LWIP_PATH}) # message("--------- " ${PICO_LWIP_CONTRIB_PATH}) # message("--------- " ${PICO_TINYUSB_PATH}) diff --git a/src/main.c b/src/main.c index c460979a5..e3888df25 100644 --- a/src/main.c +++ b/src/main.c @@ -77,6 +77,9 @@ #if OPT_NET_IPERF_SERVER #include "lwip/apps/lwiperf.h" #endif + #if OPT_NET_SYSVIEW_SERVER + #include "net/net_sysview.h" + #endif #endif @@ -483,6 +486,9 @@ void usb_thread(void *ptr) #if OPT_NET net_glue_init(NET_GLUE_TASK_PRIO); + #if OPT_NET_SYSVIEW_SERVER + net_sysview_init(); + #endif #if OPT_NET_ECHO_SERVER net_echo_init(); #endif diff --git a/src/net/net_sysview.c b/src/net/net_sysview.c new file mode 100755 index 000000000..7c37b07e7 --- /dev/null +++ b/src/net/net_sysview.c @@ -0,0 +1,353 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2021 Raspberry Pi (Trading) Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + + +#include "lwip/debug.h" +#include "lwip/stats.h" +#include "lwip/tcp.h" + +#include "net_sysview.h" + + + +#define PORT_SYSVIEW 19111 + + + +static struct tcp_pcb *sysview_pcb; + +enum echo_states +{ + ES_NONE = 0, + ES_ACCEPTED, + ES_RECEIVED, + ES_CLOSING +}; + + +struct sysview_state +{ + u8_t state; + u8_t retries; + struct tcp_pcb *pcb; + /* pbuf (chain) to recycle */ + struct pbuf *p; +}; + + + +void sysview_error(void *arg, err_t err) +{ + struct sysview_state *svs; + + printf("sysview_error(): %d\n", err); + + svs = (struct sysview_state *)arg; + if (svs != NULL) + { + mem_free(svs); + } +} // sysview_error + + + +void sysview_close(struct tcp_pcb *tpcb, struct sysview_state *svs) +{ + tcp_arg(tpcb, NULL); + tcp_sent(tpcb, NULL); + tcp_recv(tpcb, NULL); + tcp_err(tpcb, NULL); + tcp_poll(tpcb, NULL, 0); + + if (svs != NULL) + { + mem_free(svs); + } + tcp_close(tpcb); +} // sysview_close + + + +static void sysview_send(struct tcp_pcb *tpcb, struct sysview_state *svs) +{ + struct pbuf *ptr; + err_t wr_err = ERR_OK; + + while ((wr_err == ERR_OK) && + (svs->p != NULL) && + (svs->p->len <= tcp_sndbuf(tpcb))) + { + ptr = svs->p; + + /* enqueue data for transmission */ + wr_err = tcp_write(tpcb, ptr->payload, ptr->len, 1); + if (wr_err == ERR_OK) + { + u16_t plen; + u8_t freed; + + plen = ptr->len; + /* continue with next pbuf in chain (if any) */ + svs->p = ptr->next; + if(svs->p != NULL) + { + /* new reference! */ + pbuf_ref(svs->p); + } + /* chop first pbuf from chain */ + do + { + /* try hard to free pbuf */ + freed = pbuf_free(ptr); + } + while(freed == 0); + /* we can read more data now */ + tcp_recved(tpcb, plen); + } + else if(wr_err == ERR_MEM) + { + /* we are low on memory, try later / harder, defer to poll */ + svs->p = ptr; + } + else + { + /* other problem ?? */ + } + } +} // sysview_send + + + +static err_t sysview_sent(void *arg, struct tcp_pcb *tpcb, u16_t len) +{ + struct sysview_state *svs; + + svs = (struct sysview_state *)arg; + svs->retries = 0; + + if(svs->p != NULL) + { + /* still got pbufs to send */ + tcp_sent(tpcb, sysview_sent); + sysview_send(tpcb, svs); + } + else + { + /* no more pbufs to send */ + if(svs->state == ES_CLOSING) + { + sysview_close(tpcb, svs); + } + } + return ERR_OK; +} // sysview_sent + + + +static err_t sysview_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) +{ + struct sysview_state *svs; + err_t ret_err; + + LWIP_ASSERT("arg != NULL", arg != NULL); + + svs = (struct sysview_state *)arg; + if (p == NULL) + { + /* remote host closed connection */ + svs->state = ES_CLOSING; + if(svs->p == NULL) + { + /* we're done sending, close it */ + sysview_close(tpcb, svs); + } + else + { + /* we're not done yet */ + tcp_sent(tpcb, sysview_sent); + sysview_send(tpcb, svs); + } + ret_err = ERR_OK; + } + else if(err != ERR_OK) + { + /* cleanup, for unkown reason */ + if (p != NULL) + { + svs->p = NULL; + pbuf_free(p); + } + ret_err = err; + } + else if(svs->state == ES_ACCEPTED) + { + /* first data chunk in p->payload */ + svs->state = ES_RECEIVED; + /* store reference to incoming pbuf (chain) */ + svs->p = p; + /* install send completion notifier */ + tcp_sent(tpcb, sysview_sent); + sysview_send(tpcb, svs); + ret_err = ERR_OK; + } + else if (svs->state == ES_RECEIVED) + { + /* read some more data */ + if(svs->p == NULL) + { + svs->p = p; + tcp_sent(tpcb, sysview_sent); + sysview_send(tpcb, svs); + } + else + { + struct pbuf *ptr; + + /* chain pbufs to the end of what we recv'ed previously */ + ptr = svs->p; + pbuf_chain(ptr,p); + } + ret_err = ERR_OK; + } + else if(svs->state == ES_CLOSING) + { + /* odd case, remote side closing twice, trash data */ + tcp_recved(tpcb, p->tot_len); + svs->p = NULL; + pbuf_free(p); + ret_err = ERR_OK; + } + else + { + /* unkown es->state, trash data */ + tcp_recved(tpcb, p->tot_len); + svs->p = NULL; + pbuf_free(p); + ret_err = ERR_OK; + } + return ret_err; +} // sysview_recv + + + +err_t sysview_poll(void *arg, struct tcp_pcb *tpcb) +{ + err_t ret_err; + struct sysview_state *svs; + + svs = (struct sysview_state *)arg; + if (svs != NULL) + { + if (svs->p != NULL) + { + /* there is a remaining pbuf (chain) */ + tcp_sent(tpcb, sysview_sent); + sysview_send(tpcb, svs); + } + else + { + /* no remaining pbuf (chain) */ + if(svs->state == ES_CLOSING) + { + sysview_close(tpcb, svs); + } + } + ret_err = ERR_OK; + } + else + { + /* nothing to be done */ + tcp_abort(tpcb); + ret_err = ERR_ABRT; + } + return ret_err; +} // sysview_poll + + + +static err_t sysview_accept(void *arg, struct tcp_pcb *newpcb, err_t err) +{ + err_t ret_err; + struct sysview_state *svs; + + /* commonly observed practive to call tcp_setprio(), why? */ + tcp_setprio(newpcb, TCP_PRIO_MAX); + + svs = (struct sysview_state *)mem_malloc(sizeof(struct sysview_state)); + if (svs != NULL) + { + svs->state = ES_ACCEPTED; + svs->pcb = newpcb; + svs->retries = 0; + svs->p = NULL; + /* pass newly allocated es to our callbacks */ + tcp_arg(newpcb, svs); + tcp_recv(newpcb, sysview_recv); + tcp_err(newpcb, sysview_error); + tcp_poll(newpcb, sysview_poll, 0); // TODO interval? + ret_err = ERR_OK; + } + else + { + printf("sysview_accept(): cannot allow\n"); + ret_err = ERR_MEM; + } + return ret_err; +} // sysview_accept + + + +void net_sysview_init(void) +{ + err_t err; + struct tcp_pcb *pcb; + + pcb = tcp_new_ip_type(IPADDR_TYPE_ANY); + if (pcb == NULL) + { + printf("net_sysview_init(): cannot get pcb\n"); + return; + } + + err = tcp_bind(pcb, IP_ADDR_ANY, PORT_SYSVIEW); + if (err != ERR_OK) + { + printf("net_sysview_init(): cannot bind, err:%d\n", err); + return; + } + + sysview_pcb = tcp_listen_with_backlog(pcb, 1); + if (sysview_pcb == NULL) + { + if (pcb != NULL) + { + tcp_close(pcb); + } + printf("net_sysview_init(): cannot listen\n"); + return; + } + + tcp_accept(sysview_pcb, sysview_accept); +} // net_sysview_init diff --git a/src/net/net_sysview.h b/src/net/net_sysview.h new file mode 100755 index 000000000..3533225c4 --- /dev/null +++ b/src/net/net_sysview.h @@ -0,0 +1,43 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2021 Raspberry Pi (Trading) Ltd. + * + * 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. + * + */ + +#ifndef _NET_SYSVIEW_H +#define _NET_SYSVIEW_H + + +#ifdef __cplusplus + extern "C" { +#endif + + +void net_sysview_init(void); + + +#ifdef __cplusplus + } +#endif + + +#endif From c9ac19f28823f47953156ab50cdf5243e834c643 Mon Sep 17 00:00:00 2001 From: Hardy Griech Date: Sun, 7 May 2023 14:30:15 +0200 Subject: [PATCH 022/118] server frame --- src/net/net_sysview.c | 232 +++++++++++++++--------------------------- 1 file changed, 82 insertions(+), 150 deletions(-) diff --git a/src/net/net_sysview.c b/src/net/net_sysview.c index 7c37b07e7..c575abfa8 100755 --- a/src/net/net_sysview.c +++ b/src/net/net_sysview.c @@ -27,33 +27,48 @@ #include "lwip/debug.h" #include "lwip/stats.h" #include "lwip/tcp.h" +#include "lwip/err.h" #include "net_sysview.h" - -#define PORT_SYSVIEW 19111 - - - +/** + * Some definitions for server communication + * - server port + * - "Hello" message expected by SystemView App: SEGGER SystemView VM.mm.rr + */ +#define SEGGER_SYSVIEW_MAJOR 3 +#define SEGGER_SYSVIEW_MINOR 32 +#define SEGGER_SYSVIEW_REV 0 +#ifndef SYSVIEW_COMM_SERVER_PORT + #define SYSVIEW_COMM_SERVER_PORT 19111 +#endif +#define SYSVIEW_COMM_APP_HELLO_SIZE 32 +#define SYSVIEW_COMM_TARGET_HELLO_SIZE 32 +static const uint8_t sysview_hello[SYSVIEW_COMM_TARGET_HELLO_SIZE] = { 'S', 'E', 'G', 'G', 'E', 'R', ' ', 'S', 'y', 's', 't', 'e', 'm', 'V', 'i', 'e', 'w', ' ', 'V', + '0' + SEGGER_SYSVIEW_MAJOR, '.', + '0' + (SEGGER_SYSVIEW_MINOR / 10), '0' + (SEGGER_SYSVIEW_MINOR % 10), '.', + '0' + (SEGGER_SYSVIEW_REV / 10), '0' + (SEGGER_SYSVIEW_REV % 10), '\0', 0, 0, 0, 0, 0 }; + + +// pcb for socket listening static struct tcp_pcb *sysview_pcb; + enum echo_states { - ES_NONE = 0, - ES_ACCEPTED, - ES_RECEIVED, - ES_CLOSING + SVS_NONE = 0, + SVS_WAIT_HELLO, + SVS_SEND_HELLO, + SVS_READY, }; +// state of the server socket struct sysview_state { - u8_t state; - u8_t retries; + uint8_t state; struct tcp_pcb *pcb; - /* pbuf (chain) to recycle */ - struct pbuf *p; }; @@ -75,6 +90,8 @@ void sysview_error(void *arg, err_t err) void sysview_close(struct tcp_pcb *tpcb, struct sysview_state *svs) { + printf("sysview_close(%p,%p): %d\n", tpcb, svs, svs->state); + tcp_arg(tpcb, NULL); tcp_sent(tpcb, NULL); tcp_recv(tpcb, NULL); @@ -90,77 +107,17 @@ void sysview_close(struct tcp_pcb *tpcb, struct sysview_state *svs) -static void sysview_send(struct tcp_pcb *tpcb, struct sysview_state *svs) +static err_t sysview_sent(void *arg, struct tcp_pcb *tpcb, uint16_t len) { - struct pbuf *ptr; - err_t wr_err = ERR_OK; + struct sysview_state *svs = (struct sysview_state *)arg; - while ((wr_err == ERR_OK) && - (svs->p != NULL) && - (svs->p->len <= tcp_sndbuf(tpcb))) - { - ptr = svs->p; + printf("sysview_sent(%p,%p,%d) %d\n", arg, tpcb, len, svs->state); - /* enqueue data for transmission */ - wr_err = tcp_write(tpcb, ptr->payload, ptr->len, 1); - if (wr_err == ERR_OK) - { - u16_t plen; - u8_t freed; - - plen = ptr->len; - /* continue with next pbuf in chain (if any) */ - svs->p = ptr->next; - if(svs->p != NULL) - { - /* new reference! */ - pbuf_ref(svs->p); - } - /* chop first pbuf from chain */ - do - { - /* try hard to free pbuf */ - freed = pbuf_free(ptr); - } - while(freed == 0); - /* we can read more data now */ - tcp_recved(tpcb, plen); - } - else if(wr_err == ERR_MEM) - { - /* we are low on memory, try later / harder, defer to poll */ - svs->p = ptr; - } - else - { - /* other problem ?? */ - } - } -} // sysview_send - - - -static err_t sysview_sent(void *arg, struct tcp_pcb *tpcb, u16_t len) -{ - struct sysview_state *svs; - - svs = (struct sysview_state *)arg; - svs->retries = 0; - - if(svs->p != NULL) - { - /* still got pbufs to send */ - tcp_sent(tpcb, sysview_sent); - sysview_send(tpcb, svs); - } - else + if (svs->state == SVS_SEND_HELLO) { - /* no more pbufs to send */ - if(svs->state == ES_CLOSING) - { - sysview_close(tpcb, svs); - } + svs->state = SVS_READY; } + return ERR_OK; } // sysview_sent @@ -168,82 +125,71 @@ static err_t sysview_sent(void *arg, struct tcp_pcb *tpcb, u16_t len) static err_t sysview_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) { - struct sysview_state *svs; + struct sysview_state *svs = (struct sysview_state *)arg; err_t ret_err; + printf("sysview_recv(%p,%p,%p,%d) %d\n", arg, tpcb, p, err, svs->state); + LWIP_ASSERT("arg != NULL", arg != NULL); - svs = (struct sysview_state *)arg; if (p == NULL) { - /* remote host closed connection */ - svs->state = ES_CLOSING; - if(svs->p == NULL) - { - /* we're done sending, close it */ - sysview_close(tpcb, svs); - } - else - { - /* we're not done yet */ - tcp_sent(tpcb, sysview_sent); - sysview_send(tpcb, svs); - } + // + // remote host closed connection + // + sysview_close(tpcb, svs); ret_err = ERR_OK; } - else if(err != ERR_OK) + else if (err != ERR_OK) { - /* cleanup, for unkown reason */ + // + // cleanup, for unknown reason + // + // TODO actually return pbuf only, if !ERR_ABRT ?? if (p != NULL) { - svs->p = NULL; pbuf_free(p); } ret_err = err; } - else if(svs->state == ES_ACCEPTED) - { - /* first data chunk in p->payload */ - svs->state = ES_RECEIVED; - /* store reference to incoming pbuf (chain) */ - svs->p = p; - /* install send completion notifier */ - tcp_sent(tpcb, sysview_sent); - sysview_send(tpcb, svs); - ret_err = ERR_OK; - } - else if (svs->state == ES_RECEIVED) + else if (svs->state == SVS_WAIT_HELLO) { - /* read some more data */ - if(svs->p == NULL) + // + // expecting hello message + // + printf("sysview_recv, %d:'%s'\n", p->len, (const char *)p->payload); + if (p->len != SYSVIEW_COMM_APP_HELLO_SIZE) { - svs->p = p; - tcp_sent(tpcb, sysview_sent); - sysview_send(tpcb, svs); + // invalid hello + pbuf_free(p); + tcp_abort(tpcb); + // TODO close here? + ret_err = ERR_ABRT; } else { - struct pbuf *ptr; - - /* chain pbufs to the end of what we recv'ed previously */ - ptr = svs->p; - pbuf_chain(ptr,p); + // valid hello, response with hello back + tcp_recved(tpcb, SYSVIEW_COMM_APP_HELLO_SIZE); + pbuf_free(p); + tcp_write(tpcb, sysview_hello, SYSVIEW_COMM_TARGET_HELLO_SIZE, 0); + svs->state = SVS_SEND_HELLO; + ret_err = ERR_OK; } - ret_err = ERR_OK; } - else if(svs->state == ES_CLOSING) + else if (svs->state == SVS_READY) { - /* odd case, remote side closing twice, trash data */ - tcp_recved(tpcb, p->tot_len); - svs->p = NULL; + // + // send received data to RTT SysView + // + tcp_recved(tpcb, p->len); + // TODO data to RTT pbuf_free(p); ret_err = ERR_OK; } else { - /* unkown es->state, trash data */ + /* unknown svs->state, trash data */ tcp_recved(tpcb, p->tot_len); - svs->p = NULL; pbuf_free(p); ret_err = ERR_OK; } @@ -255,25 +201,12 @@ static err_t sysview_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err_t sysview_poll(void *arg, struct tcp_pcb *tpcb) { err_t ret_err; - struct sysview_state *svs; + struct sysview_state *svs = (struct sysview_state *)arg; + + printf("sysview_poll(%p,%p) %d\n", arg, tpcb, svs->state); - svs = (struct sysview_state *)arg; if (svs != NULL) { - if (svs->p != NULL) - { - /* there is a remaining pbuf (chain) */ - tcp_sent(tpcb, sysview_sent); - sysview_send(tpcb, svs); - } - else - { - /* no remaining pbuf (chain) */ - if(svs->state == ES_CLOSING) - { - sysview_close(tpcb, svs); - } - } ret_err = ERR_OK; } else @@ -298,20 +231,19 @@ static err_t sysview_accept(void *arg, struct tcp_pcb *newpcb, err_t err) svs = (struct sysview_state *)mem_malloc(sizeof(struct sysview_state)); if (svs != NULL) { - svs->state = ES_ACCEPTED; + svs->state = SVS_WAIT_HELLO; svs->pcb = newpcb; - svs->retries = 0; - svs->p = NULL; - /* pass newly allocated es to our callbacks */ - tcp_arg(newpcb, svs); + /* pass newly allocated svs to our callbacks */ + tcp_arg(newpcb, svs); + tcp_err(newpcb, sysview_error); tcp_recv(newpcb, sysview_recv); - tcp_err(newpcb, sysview_error); tcp_poll(newpcb, sysview_poll, 0); // TODO interval? + tcp_sent(newpcb, sysview_sent); ret_err = ERR_OK; } else { - printf("sysview_accept(): cannot allow\n"); + printf("sysview_accept(): cannot alloc\n"); ret_err = ERR_MEM; } return ret_err; @@ -331,7 +263,7 @@ void net_sysview_init(void) return; } - err = tcp_bind(pcb, IP_ADDR_ANY, PORT_SYSVIEW); + err = tcp_bind(pcb, IP_ADDR_ANY, SYSVIEW_COMM_SERVER_PORT); if (err != ERR_OK) { printf("net_sysview_init(): cannot bind, err:%d\n", err); From 9662d38698a84bac79aa799a5763c0e7610c76b0 Mon Sep 17 00:00:00 2001 From: Hardy Griech Date: Sun, 7 May 2023 15:11:36 +0200 Subject: [PATCH 023/118] send characters to SysView target (untested) --- src/net/net_sysview.c | 6 +- src/rtt_console.c | 180 +++++++++++++++++++++++++++--------------- src/rtt_console.h | 5 ++ 3 files changed, 128 insertions(+), 63 deletions(-) diff --git a/src/net/net_sysview.c b/src/net/net_sysview.c index c575abfa8..a853216e8 100755 --- a/src/net/net_sysview.c +++ b/src/net/net_sysview.c @@ -30,6 +30,7 @@ #include "lwip/err.h" #include "net_sysview.h" +#include "rtt_console.h" /** @@ -181,8 +182,11 @@ static err_t sysview_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t // // send received data to RTT SysView // + for (uint16_t ndx = 0; ndx < p->len; ++ndx) + { + rtt_sysview_send_byte(((uint8_t *)p->payload)[ndx]); + } tcp_recved(tpcb, p->len); - // TODO data to RTT pbuf_free(p); ret_err = ERR_OK; } diff --git a/src/rtt_console.c b/src/rtt_console.c index cec73bd4c..099f11098 100755 --- a/src/rtt_console.c +++ b/src/rtt_console.c @@ -47,25 +47,32 @@ -#define TARGET_RAM_START g_board_info.target_cfg->ram_regions[0].start -#define TARGET_RAM_END g_board_info.target_cfg->ram_regions[0].end +#define TARGET_RAM_START g_board_info.target_cfg->ram_regions[0].start +#define TARGET_RAM_END g_board_info.target_cfg->ram_regions[0].end -#define STREAM_RTT_SIZE 128 -#define STREAM_RTT_TRIGGER 1 +#define STREAM_RTT_SIZE 128 +#define STREAM_RTT_TRIGGER 1 -#define RTT_CHANNEL_CONSOLE 1 -#define RTT_POLL_INT_MS 1 +#define RTT_CHANNEL_CONSOLE 0 +#define RTT_POLL_INT_MS 10 -#define EV_RTT_TO_TARGET 0x01 +#define EV_RTT_TO_TARGET 0x01 -static const uint32_t segger_alignment = 4; -static const uint8_t seggerRTT[16] = "SEGGER RTT\0\0\0\0\0\0"; -static uint32_t prev_rtt_cb = 0; -static bool rtt_console_running = false; +static const uint32_t segger_alignment = 4; +static const uint8_t seggerRTT[16] = "SEGGER RTT\0\0\0\0\0\0"; +static uint32_t prev_rtt_cb = 0; +static bool rtt_console_running = false; -static TaskHandle_t task_rtt_console = NULL; -static StreamBufferHandle_t stream_rtt; // small stream for host->probe->target communication -static EventGroupHandle_t events; +static TaskHandle_t task_rtt_console = NULL; +static StreamBufferHandle_t stream_rtt_console_to_target; // small stream for host->probe->target console communication +static EventGroupHandle_t events; + +#if OPT_NET_SYSVIEW_SERVER + #define RTT_CHANNEL_SYSVIEW 1 + #undef RTT_POLL_INT_MS + #define RTT_POLL_INT_MS 1 // faster polling + static StreamBufferHandle_t stream_rtt_sysview_to_target; // small stream for host->probe->target sysview communication +#endif @@ -136,10 +143,51 @@ static uint32_t search_for_rtt_cb(void) +static void rtt_to_target(uint32_t rtt_cb, StreamBufferHandle_t stream, uint16_t channel, SEGGER_RTT_BUFFER_DOWN *aDown) +{ + bool ok = true; + uint8_t buf[16]; + + if ( !xStreamBufferIsEmpty(stream)) { + // + // send data to target + // + ok = ok && swd_read_word(rtt_cb + offsetof(SEGGER_RTT_CB, aDown[channel].RdOff), (uint32_t *)&(aDown->RdOff)); + if ((aDown->WrOff + 1) % aDown->SizeOfBuffer != aDown->RdOff) { + // -> space left in RTT buffer on target + uint32_t cnt; + size_t r; + + if (aDown->WrOff >= aDown->RdOff) { + cnt = aDown->SizeOfBuffer - aDown->WrOff; + } + else { + cnt = (aDown->RdOff - aDown->WrOff) - 1; + } + cnt = MIN(cnt, sizeof(buf)); + + r = xStreamBufferReceive(stream, &buf, cnt, 0); + if (r > 0) { + ok = ok && swd_write_memory((uint32_t)aDown->pBuffer + aDown->WrOff, buf, r); + aDown->WrOff = (aDown->WrOff + r) % aDown->SizeOfBuffer; + ok = ok && swd_write_word(rtt_cb + offsetof(SEGGER_RTT_CB, aDown[channel].WrOff), aDown->WrOff); + + led_state(LS_UART_TX_DATA); + } + } + } +} // rtt_to_target + + + static void do_rtt_console(uint32_t rtt_cb) { - SEGGER_RTT_BUFFER_UP aUp; // Up buffer, transferring information up from target via debug probe to host - SEGGER_RTT_BUFFER_DOWN aDown; // Down buffer, transferring information from host via debug probe to target + SEGGER_RTT_BUFFER_UP aUpConsole; // Up buffer, transferring information up from target via debug probe to host + SEGGER_RTT_BUFFER_DOWN aDownConsole; // Down buffer, transferring information from host via debug probe to target +#if OPT_NET_SYSVIEW_SERVER + SEGGER_RTT_BUFFER_UP aUpSysView; // Up buffer, transferring information up from target via debug probe to host + SEGGER_RTT_BUFFER_DOWN aDownSysView; // Down buffer, transferring information from host via debug probe to target +#endif uint8_t buf[256]; bool ok = true; @@ -150,16 +198,22 @@ static void do_rtt_console(uint32_t rtt_cb) } ok = ok && swd_read_memory(rtt_cb + offsetof(SEGGER_RTT_CB, aUp[RTT_CHANNEL_CONSOLE]), - (uint8_t *)&aUp, sizeof(aUp)); + (uint8_t *)&aUpConsole, sizeof(aUpConsole)); ok = ok && swd_read_memory(rtt_cb + offsetof(SEGGER_RTT_CB, aDown[RTT_CHANNEL_CONSOLE]), - (uint8_t *)&aDown, sizeof(aDown)); + (uint8_t *)&aDownConsole, sizeof(aDownConsole)); +#if OPT_NET_SYSVIEW_SERVER + ok = ok && swd_read_memory(rtt_cb + offsetof(SEGGER_RTT_CB, aUp[RTT_CHANNEL_SYSVIEW]), + (uint8_t *)&aUpSysView, sizeof(aUpSysView)); + ok = ok && swd_read_memory(rtt_cb + offsetof(SEGGER_RTT_CB, aDown[RTT_CHANNEL_SYSVIEW]), + (uint8_t *)&aDownSysView, sizeof(aDownSysView)); +#endif // do operations rtt_console_running = true; while (ok && !sw_unlock_requested()) { - ok = ok && swd_read_word(rtt_cb + offsetof(SEGGER_RTT_CB, aUp[RTT_CHANNEL_CONSOLE].WrOff), (uint32_t *)&aUp.WrOff); + ok = ok && swd_read_word(rtt_cb + offsetof(SEGGER_RTT_CB, aUp[RTT_CHANNEL_CONSOLE].WrOff), (uint32_t *)&aUpConsole.WrOff); - if (aUp.WrOff == aUp.RdOff) { + if (aUpConsole.WrOff == aUpConsole.RdOff) { // -> no characters available xEventGroupWaitBits(events, EV_RTT_TO_TARGET, pdTRUE, pdFALSE, pdMS_TO_TICKS(RTT_POLL_INT_MS)); } @@ -169,18 +223,18 @@ static void do_rtt_console(uint32_t rtt_cb) // uint32_t cnt; - if (aUp.WrOff > aUp.RdOff) { - cnt = aUp.WrOff - aUp.RdOff; + if (aUpConsole.WrOff > aUpConsole.RdOff) { + cnt = aUpConsole.WrOff - aUpConsole.RdOff; } else { - cnt = aUp.SizeOfBuffer - aUp.RdOff; + cnt = aUpConsole.SizeOfBuffer - aUpConsole.RdOff; } cnt = MIN(cnt, sizeof(buf)); memset(buf, 0, sizeof(buf)); - ok = ok && swd_read_memory((uint32_t)aUp.pBuffer + aUp.RdOff, buf, cnt); - aUp.RdOff = (aUp.RdOff + cnt) % aUp.SizeOfBuffer; - ok = ok && swd_write_word(rtt_cb + offsetof(SEGGER_RTT_CB, aUp[RTT_CHANNEL_CONSOLE].RdOff), aUp.RdOff); + ok = ok && swd_read_memory((uint32_t)aUpConsole.pBuffer + aUpConsole.RdOff, buf, cnt); + aUpConsole.RdOff = (aUpConsole.RdOff + cnt) % aUpConsole.SizeOfBuffer; + ok = ok && swd_write_word(rtt_cb + offsetof(SEGGER_RTT_CB, aUp[RTT_CHANNEL_CONSOLE].RdOff), aUpConsole.RdOff); #if OPT_TARGET_UART // put received data into CDC UART @@ -190,34 +244,13 @@ static void do_rtt_console(uint32_t rtt_cb) led_state(LS_RTT_RX_DATA); } - if ( !xStreamBufferIsEmpty(stream_rtt)) { - // - // send data to target - // - ok = ok && swd_read_word(rtt_cb + offsetof(SEGGER_RTT_CB, aDown[RTT_CHANNEL_CONSOLE].RdOff), (uint32_t *)&(aDown.RdOff)); - if ((aDown.WrOff + 1) % aDown.SizeOfBuffer != aDown.RdOff) { - // -> space left in RTT buffer on target - uint32_t cnt; - size_t r; - - if (aDown.WrOff >= aDown.RdOff) { - cnt = aDown.SizeOfBuffer - aDown.WrOff; - } - else { - cnt = (aDown.RdOff - aDown.WrOff) - 1; - } - cnt = MIN(cnt, sizeof(buf)); - - r = xStreamBufferReceive(stream_rtt, &buf, cnt, 0); - if (r > 0) { - ok = ok && swd_write_memory((uint32_t)aDown.pBuffer + aDown.WrOff, buf, r); - aDown.WrOff = (aDown.WrOff + r) % aDown.SizeOfBuffer; - ok = ok && swd_write_word(rtt_cb + offsetof(SEGGER_RTT_CB, aDown[RTT_CHANNEL_CONSOLE].WrOff), aDown.WrOff); - - led_state(LS_UART_TX_DATA); - } - } - } + // + // transfer RTT data to target + // + rtt_to_target(rtt_cb, stream_rtt_console_to_target, RTT_CHANNEL_CONSOLE, &aDownConsole); +#if OPT_NET_SYSVIEW_SERVER + rtt_to_target(rtt_cb, stream_rtt_console_to_target, RTT_CHANNEL_SYSVIEW, &aDownSysView); +#endif } rtt_console_running = false; } // do_rtt_console @@ -317,39 +350,62 @@ bool rtt_console_cb_exists(void) -void rtt_console_send_byte(uint8_t ch) +void rtt_send_byte(StreamBufferHandle_t stream, uint8_t ch) /** * Write a byte into the RTT stream. * If there is no space left in the stream, wait 10ms and then try again. * If there is still no space, then drop a byte from the stream. */ { - size_t available = xStreamBufferSpacesAvailable(stream_rtt); + size_t available = xStreamBufferSpacesAvailable(stream); if (available < sizeof(ch)) { vTaskDelay(pdMS_TO_TICKS(10)); - available = xStreamBufferSpacesAvailable(stream_rtt); + available = xStreamBufferSpacesAvailable(stream); if (available < sizeof(ch)) { uint8_t dummy; - xStreamBufferReceive(stream_rtt, &dummy, sizeof(dummy), 0); + xStreamBufferReceive(stream, &dummy, sizeof(dummy), 0); picoprobe_error("rtt_console_send_byte: drop byte\n"); } } - xStreamBufferSend(stream_rtt, &ch, sizeof(ch), 0); + xStreamBufferSend(stream, &ch, sizeof(ch), 0); xEventGroupSetBits(events, EV_RTT_TO_TARGET); +} // rtt_send_byte + + + +void rtt_console_send_byte(uint8_t ch) +{ + rtt_send_byte(stream_rtt_console_to_target, ch); } // rtt_console_send_byte +#if OPT_NET_SYSVIEW_SERVER +void rtt_sysview_send_byte(uint8_t ch) +{ + rtt_send_byte(stream_rtt_sysview_to_target, ch); +} // rtt_sysview_send_byte +#endif + + + void rtt_console_init(uint32_t task_prio) { picoprobe_debug("rtt_console_init()\n"); events = xEventGroupCreate(); - stream_rtt = xStreamBufferCreate(STREAM_RTT_SIZE, STREAM_RTT_TRIGGER); - if (stream_rtt == NULL) { - picoprobe_error("rtt_console_init: cannot create stream_rtt\n"); + stream_rtt_console_to_target = xStreamBufferCreate(STREAM_RTT_SIZE, STREAM_RTT_TRIGGER); + if (stream_rtt_console_to_target == NULL) { + picoprobe_error("rtt_console_init: cannot create stream_rtt_console_to_target\n"); + } + +#if OPT_NET_SYSVIEW_SERVER + stream_rtt_sysview_to_target = xStreamBufferCreate(STREAM_RTT_SIZE, STREAM_RTT_TRIGGER); + if (stream_rtt_sysview_to_target == NULL) { + picoprobe_error("rtt_console_init: cannot create stream_rtt_sysview_to_target\n"); } +#endif xTaskCreateAffinitySet(rtt_console_thread, "RTT_CONSOLE", configMINIMAL_STACK_SIZE, NULL, task_prio, 1, &task_rtt_console); if (task_rtt_console == NULL) diff --git a/src/rtt_console.h b/src/rtt_console.h index c2e4ed486..23635d91b 100755 --- a/src/rtt_console.h +++ b/src/rtt_console.h @@ -28,6 +28,7 @@ #include +#include #ifdef __cplusplus @@ -39,6 +40,10 @@ void rtt_console_init(uint32_t task_prio); void rtt_console_send_byte(uint8_t ch); bool rtt_console_cb_exists(void); +#if OPT_NET_SYSVIEW_SERVER + void rtt_sysview_send_byte(uint8_t ch); +#endif + #ifdef __cplusplus } From ef14311fdbf7bca8a506df2e9446a098bf2c21e3 Mon Sep 17 00:00:00 2001 From: Hardy Griech Date: Sun, 7 May 2023 18:33:41 +0200 Subject: [PATCH 024/118] INCLUDE_RAM_UF2 -> OPT_MSC_RAM_UF2 --- CMakeLists.txt | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ba5149209..22fb8df34 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,12 +24,13 @@ else() set(DEFAULT_OPT_PROBE_DEBUG_OUT 0) endif() -option(OPT_CMSIS_DAPV1 "Enable CMSIS-DAPv1" 0) -option(OPT_CMSIS_DAPV2 "Enable CMSIS-DAPv2" 0) +option(OPT_CMSIS_DAPV1 "Enable CMSIS-DAPv1" 1) +option(OPT_CMSIS_DAPV2 "Enable CMSIS-DAPv2" 1) option(OPT_TARGET_UART "Enable CDC for target UART I/O" 1) option(OPT_PROBE_DEBUG_OUT "Enable CDC for probe debug output" ${DEFAULT_OPT_PROBE_DEBUG_OUT}) option(OPT_SIGROK "Enable sigrok" 0) -option(OPT_MSC "Enable Mass Storage Device" 0) +option(OPT_MSC "Enable Mass Storage Device" 1) +option(OPT_MSC_RAM_UF2 "Enable file 'RAM.UF2' on Mass Storage" 1) option(OPT_NET "Enable lwIP on the Pico" 1) option(OPT_NET_DNS "Enable DNS on the Pico" 0) # all DNS is going over the Pico!? option(OPT_NET_ECHO_SERVER "Enable echo server for testing" 1) @@ -279,6 +280,10 @@ if(OPT_MSC) src/msc/msc_drive.c src/msc/msc_utils.c ) + + if(OPT_MSC_RAM_UF2) + add_compile_definitions(OPT_MSC_RAM_UF2=1) + endif() endif() #-------------------------------------------------------------------------------------------------- From a69fb44948333541d5b7cfeefd0edc05be205ce9 Mon Sep 17 00:00:00 2001 From: Hardy Griech Date: Sun, 7 May 2023 18:34:29 +0200 Subject: [PATCH 025/118] INCLUDE_RAM_UF2 -> OPT_MSC_RAM_UF2 part II --- src/msc/msc_drive.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/msc/msc_drive.c b/src/msc/msc_drive.c index bb05d15d7..c62e3af6a 100644 --- a/src/msc/msc_drive.c +++ b/src/msc/msc_drive.c @@ -45,9 +45,6 @@ #include "msc_utils.h" -#define INCLUDE_RAM_UF2 - - #define ADWORD(X) (X) & 0xff, ((X) & 0xff00) >> 8, ((X) & 0xff0000) >> 16, ((X) & 0xff000000) >> 24 #define AWORD(X) (X) & 0xff, ((X) & 0xff00) >> 8 #define ADATE(Y,M,D) AWORD((((Y)-1980) << 9) + ((M) << 5) + (D)) @@ -86,7 +83,7 @@ Board-ID: %s\r\n" #define BPB_BytsPerSec 512UL #define BPB_BytsPerClus 65536UL -#define BPB_TotSec (128*1024*2+20) // 16MB + some offset for FAT overhead +#define BPB_TotSec (128*1024*2+20) // 128MB + some offset for FAT overhead #if (BPB_TotSec < 65536) const uint16_t BPB_TotSec16 = BPB_TotSec; @@ -121,7 +118,7 @@ const uint32_t c_DataStartSector = c_RootDirStartSector + c_RootDirSectors; #define TARGET_FLASH_IMG_SIZE (g_board_info.target_cfg->flash_regions[0].end - g_board_info.target_cfg->flash_regions[0].start) #define TARGET_FLASH_UF2_SIZE (2 * TARGET_FLASH_IMG_SIZE) -#ifdef INCLUDE_RAM_UF2 +#if OPT_MSC_RAM_UF2 #define TARGET_RAM_IMG_BASE (g_board_info.target_cfg->ram_regions[0].start) #define TARGET_RAM_IMG_SIZE (g_board_info.target_cfg->ram_regions[0].end - g_board_info.target_cfg->ram_regions[0].start) #define TARGET_RAM_UF2_SIZE (2 * TARGET_RAM_IMG_SIZE) @@ -151,7 +148,7 @@ const uint32_t f_IndexHtmSectors = BPB_SecPerClus * f_IndexHtmClusters; #define f_CurrentUF2StartSector (c_FirstSectorofCluster(f_CurrentUF2StartCluster)) #define f_CurrentUF2Sectors (BPB_SecPerClus * f_CurrentUF2Clusters) -#ifdef INCLUDE_RAM_UF2 +#if OPT_MSC_RAM_UF2 #define f_RAMUF2StartCluster (f_CurrentUF2StartCluster + f_CurrentUF2Clusters) #define f_RAMUF2Clusters (CLUSTERS(TARGET_RAM_UF2_SIZE)) #define f_RAMUF2StartSector (c_FirstSectorofCluster(f_RAMUF2StartCluster)) @@ -505,7 +502,7 @@ int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void* buff insert_fat_entry(buffer, block_no * BPB_BytsPerSec, cluster, cluster < (f_CurrentUF2StartCluster + f_CurrentUF2Clusters - 1) ? cluster + 1 : 0xfff); } -#ifdef INCLUDE_RAM_UF2 +#if OPT_MSC_RAM_UF2 for (uint16_t cluster = f_RAMUF2StartCluster; cluster < f_RAMUF2StartCluster + f_RAMUF2Clusters; ++cluster) { insert_fat_entry(buffer, block_no * BPB_BytsPerSec, cluster, cluster < (f_RAMUF2StartCluster + f_RAMUF2Clusters - 1) ? cluster + 1 : 0xfff); @@ -519,7 +516,7 @@ int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void* buff // picoprobe_info(" ROOTDIR\n"); r = read_sector_from_buffer(buffer, rootdirsector, sizeof(rootdirsector), lba - c_RootDirStartSector); append_dir_entry(buffer, "CURRENT UF2", f_CurrentUF2StartCluster, TARGET_FLASH_UF2_SIZE); -#ifdef INCLUDE_RAM_UF2 +#if OPT_MSC_RAM_UF2 append_dir_entry(buffer, "RAM UF2", f_RAMUF2StartCluster, TARGET_RAM_UF2_SIZE); #endif } @@ -564,7 +561,7 @@ int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void* buff } } } -#ifdef INCLUDE_RAM_UF2 +#if OPT_MSC_RAM_UF2 else if (lba >= f_RAMUF2StartSector && lba < f_RAMUF2StartSector + f_RAMUF2Sectors) { const uint32_t payload_size = 256; const uint32_t num_blocks = f_RAMUF2Sectors; From a214ec80c57decd10dedba01ef1c10dbb9d8b4c5 Mon Sep 17 00:00:00 2001 From: Hardy Griech Date: Sun, 7 May 2023 18:35:34 +0200 Subject: [PATCH 026/118] sysview server works first time --- include/lwipopts.h | 5 ++ src/main.c | 3 +- src/net/net_sysview.c | 204 ++++++++++++++++++++++++++---------------- src/net/net_sysview.h | 3 +- src/rtt_console.c | 100 ++++++++++++++------- 5 files changed, 202 insertions(+), 113 deletions(-) diff --git a/include/lwipopts.h b/include/lwipopts.h index 868c7e983..5d39398f9 100755 --- a/include/lwipopts.h +++ b/include/lwipopts.h @@ -71,6 +71,11 @@ //#define TCP_OVERSIZE TCP_MSS +//-------------------------------------- +// memory +#define MEM_SIZE 10000 + + //-------------------------------------- // for freertos mode #define TCPIP_MBOX_SIZE 32 diff --git a/src/main.c b/src/main.c index e3888df25..8ddcffb5c 100644 --- a/src/main.c +++ b/src/main.c @@ -117,6 +117,7 @@ static uint8_t RxDataBuffer[_DAP_PACKET_COUNT_OPENOCD * CFG_TUD_VENDOR_RX_BUFSIZ #define NET_GLUE_TASK_PRIO (tskIDLE_PRIORITY + 10) // task which copies frames from tinyusb to lwip #define SIGROK_TASK_PRIO (tskIDLE_PRIORITY + 9) // Sigrok digital/analog signals (does nothing at the moment) #define MSC_WRITER_THREAD_PRIO (tskIDLE_PRIORITY + 8) // this is only running on writing UF2 files +#define NET_SYSVIEW_PRIO (tskIDLE_PRIORITY + 7) // net_sysview: send data to host (client) #define UART_TASK_PRIO (tskIDLE_PRIORITY + 5) // target -> host via UART #define RTT_CONSOLE_TASK_PRIO (tskIDLE_PRIORITY + 4) // target -> host via RTT #define CDC_DEBUG_TASK_PRIO (tskIDLE_PRIORITY + 4) // probe debugging output @@ -487,7 +488,7 @@ void usb_thread(void *ptr) #if OPT_NET net_glue_init(NET_GLUE_TASK_PRIO); #if OPT_NET_SYSVIEW_SERVER - net_sysview_init(); + net_sysview_init(NET_SYSVIEW_PRIO); #endif #if OPT_NET_ECHO_SERVER net_echo_init(); diff --git a/src/net/net_sysview.c b/src/net/net_sysview.c index a853216e8..6e2d8748f 100755 --- a/src/net/net_sysview.c +++ b/src/net/net_sysview.c @@ -24,11 +24,17 @@ */ +#include "FreeRTOS.h" +#include "stream_buffer.h" +#include "task.h" +#include "event_groups.h" + #include "lwip/debug.h" #include "lwip/stats.h" #include "lwip/tcp.h" #include "lwip/err.h" +#include "picoprobe_config.h" #include "net_sysview.h" #include "rtt_console.h" @@ -51,10 +57,8 @@ static const uint8_t sysview_hello[SYSVIEW_COMM_TARGET_HELLO_SIZE] = { 'S', 'E', '0' + (SEGGER_SYSVIEW_MINOR / 10), '0' + (SEGGER_SYSVIEW_MINOR % 10), '.', '0' + (SEGGER_SYSVIEW_REV / 10), '0' + (SEGGER_SYSVIEW_REV % 10), '\0', 0, 0, 0, 0, 0 }; - // pcb for socket listening -static struct tcp_pcb *sysview_pcb; - +static struct tcp_pcb *m_pcb_listen; enum echo_states { @@ -64,34 +68,37 @@ enum echo_states SVS_READY, }; +// only one client instance is possible +static uint8_t m_state; +struct tcp_pcb *m_pcb_client; -// state of the server socket -struct sysview_state -{ - uint8_t state; - struct tcp_pcb *pcb; -}; + +#define STREAM_SYSVIEW_SIZE 4096 +#define STREAM_SYSVIEW_TRIGGER 32 + +static TaskHandle_t task_sysview = NULL; +static StreamBufferHandle_t stream_sysview_to_host; + +#define EV_STREAM 0x01 +#define EV_SENT 0x02 + +/// event flags +static EventGroupHandle_t events; void sysview_error(void *arg, err_t err) { - struct sysview_state *svs; + printf("picoprobe_error: %d\n", err); - printf("sysview_error(): %d\n", err); - - svs = (struct sysview_state *)arg; - if (svs != NULL) - { - mem_free(svs); - } + m_state = SVS_NONE; } // sysview_error -void sysview_close(struct tcp_pcb *tpcb, struct sysview_state *svs) +void sysview_close(struct tcp_pcb *tpcb) { - printf("sysview_close(%p,%p): %d\n", tpcb, svs, svs->state); + //printf("sysview_close(%p): %d\n", tpcb, m_state); tcp_arg(tpcb, NULL); tcp_sent(tpcb, NULL); @@ -99,25 +106,23 @@ void sysview_close(struct tcp_pcb *tpcb, struct sysview_state *svs) tcp_err(tpcb, NULL); tcp_poll(tpcb, NULL, 0); - if (svs != NULL) - { - mem_free(svs); - } tcp_close(tpcb); + + m_state = SVS_NONE; } // sysview_close static err_t sysview_sent(void *arg, struct tcp_pcb *tpcb, uint16_t len) { - struct sysview_state *svs = (struct sysview_state *)arg; + //printf("sysview_sent(%p,%p,%d) %d\n", arg, tpcb, len, m_state); - printf("sysview_sent(%p,%p,%d) %d\n", arg, tpcb, len, svs->state); - - if (svs->state == SVS_SEND_HELLO) + if (m_state == SVS_SEND_HELLO) { - svs->state = SVS_READY; + m_state = SVS_READY; + xStreamBufferReset(stream_sysview_to_host); } + xEventGroupSetBits(events, EV_SENT); return ERR_OK; } // sysview_sent @@ -126,19 +131,16 @@ static err_t sysview_sent(void *arg, struct tcp_pcb *tpcb, uint16_t len) static err_t sysview_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) { - struct sysview_state *svs = (struct sysview_state *)arg; err_t ret_err; - printf("sysview_recv(%p,%p,%p,%d) %d\n", arg, tpcb, p, err, svs->state); - - LWIP_ASSERT("arg != NULL", arg != NULL); + //printf("sysview_recv(%p,%p,%p,%d) %d\n", arg, tpcb, p, err, m_state); if (p == NULL) { // // remote host closed connection // - sysview_close(tpcb, svs); + sysview_close(tpcb); ret_err = ERR_OK; } else if (err != ERR_OK) @@ -153,12 +155,12 @@ static err_t sysview_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t } ret_err = err; } - else if (svs->state == SVS_WAIT_HELLO) + else if (m_state == SVS_WAIT_HELLO) { // // expecting hello message // - printf("sysview_recv, %d:'%s'\n", p->len, (const char *)p->payload); + //printf("sysview_recv, %d:'%s'\n", p->len, (const char *)p->payload); if (p->len != SYSVIEW_COMM_APP_HELLO_SIZE) { // invalid hello @@ -173,11 +175,11 @@ static err_t sysview_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t tcp_recved(tpcb, SYSVIEW_COMM_APP_HELLO_SIZE); pbuf_free(p); tcp_write(tpcb, sysview_hello, SYSVIEW_COMM_TARGET_HELLO_SIZE, 0); - svs->state = SVS_SEND_HELLO; + m_state = SVS_SEND_HELLO; ret_err = ERR_OK; } } - else if (svs->state == SVS_READY) + else if (m_state == SVS_READY) { // // send received data to RTT SysView @@ -204,86 +206,134 @@ static err_t sysview_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err_t sysview_poll(void *arg, struct tcp_pcb *tpcb) { - err_t ret_err; - struct sysview_state *svs = (struct sysview_state *)arg; + //printf("sysview_poll(%p,%p) %d\n", arg, tpcb, m_state); - printf("sysview_poll(%p,%p) %d\n", arg, tpcb, svs->state); - - if (svs != NULL) - { - ret_err = ERR_OK; - } - else - { - /* nothing to be done */ - tcp_abort(tpcb); - ret_err = ERR_ABRT; - } - return ret_err; + return ERR_OK; } // sysview_poll static err_t sysview_accept(void *arg, struct tcp_pcb *newpcb, err_t err) { - err_t ret_err; - struct sysview_state *svs; - /* commonly observed practive to call tcp_setprio(), why? */ tcp_setprio(newpcb, TCP_PRIO_MAX); - svs = (struct sysview_state *)mem_malloc(sizeof(struct sysview_state)); - if (svs != NULL) + m_state = SVS_WAIT_HELLO; + m_pcb_client = newpcb; + /* pass newly allocated svs to our callbacks */ + tcp_arg(newpcb, NULL); + tcp_err(newpcb, sysview_error); + tcp_recv(newpcb, sysview_recv); + tcp_poll(newpcb, sysview_poll, 0); // TODO interval? + tcp_sent(newpcb, sysview_sent); + + return ERR_OK; +} // sysview_accept + + + +static void sysview_thread(void *ptr) +{ + for (;;) { + xEventGroupWaitBits(events, EV_STREAM | EV_SENT, pdTRUE, pdFALSE, pdMS_TO_TICKS(1000)); + + if (m_state == SVS_READY && !xStreamBufferIsEmpty(stream_sysview_to_host)) { + size_t cnt; + size_t max_cnt; + uint8_t tx_buf[64]; + err_t err; + + //printf("sysview_thread: %d\n", xStreamBufferBytesAvailable(stream_sysview_to_host)); + + max_cnt = tcp_sndbuf(m_pcb_client); + if (max_cnt != 0) { + max_cnt = MIN(sizeof(tx_buf), max_cnt); + cnt = xStreamBufferReceive(stream_sysview_to_host, tx_buf, max_cnt, pdMS_TO_TICKS(10)); + if (cnt != 0) { + if (xStreamBufferIsEmpty(stream_sysview_to_host)) + { + err = tcp_write(m_pcb_client, tx_buf, cnt, TCP_WRITE_FLAG_COPY); + if (err != ERR_OK) + picoprobe_error("sysview_thread/a: %d\n", err); + err = tcp_output(m_pcb_client); + if (err != ERR_OK) + picoprobe_error("sysview_thread/b: %d\n", err); + } + else + { + err = tcp_write(m_pcb_client, tx_buf, cnt, TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE); + if (err != ERR_OK) + picoprobe_error("sysview_thread/c: %d\n", err); + xEventGroupSetBits(events, EV_STREAM); + } + } + } + } + } +} // sysview_thread + + + +void net_sysview_send(const uint8_t *buf, uint32_t cnt) +{ + //printf("net_sysview_send(%p,%lu) %d\n", buf, cnt, m_state); + + if (m_state != SVS_READY) { - svs->state = SVS_WAIT_HELLO; - svs->pcb = newpcb; - /* pass newly allocated svs to our callbacks */ - tcp_arg(newpcb, svs); - tcp_err(newpcb, sysview_error); - tcp_recv(newpcb, sysview_recv); - tcp_poll(newpcb, sysview_poll, 0); // TODO interval? - tcp_sent(newpcb, sysview_sent); - ret_err = ERR_OK; + xStreamBufferReset(stream_sysview_to_host); } else { - printf("sysview_accept(): cannot alloc\n"); - ret_err = ERR_MEM; + xStreamBufferSend(stream_sysview_to_host, buf, cnt, pdMS_TO_TICKS(5)); + xEventGroupSetBits(events, EV_STREAM); } - return ret_err; -} // sysview_accept +} // net_sysview_send -void net_sysview_init(void) +void net_sysview_init(uint32_t task_prio) { err_t err; struct tcp_pcb *pcb; + // + // initialize some infrastructure + // + events = xEventGroupCreate(); + + stream_sysview_to_host = xStreamBufferCreate(STREAM_SYSVIEW_SIZE, STREAM_SYSVIEW_TRIGGER); + if (stream_sysview_to_host == NULL) { + picoprobe_error("net_sysview_init: cannot create stream_sysview_to_host\n"); + } + xTaskCreateAffinitySet(sysview_thread, "net_sysview", configMINIMAL_STACK_SIZE, NULL, task_prio, 1, &task_sysview); + + // + // initialize socket listener + // pcb = tcp_new_ip_type(IPADDR_TYPE_ANY); if (pcb == NULL) { - printf("net_sysview_init(): cannot get pcb\n"); + picoprobe_error("net_sysview_init: cannot get pcb\n"); return; } err = tcp_bind(pcb, IP_ADDR_ANY, SYSVIEW_COMM_SERVER_PORT); if (err != ERR_OK) { - printf("net_sysview_init(): cannot bind, err:%d\n", err); + picoprobe_error("net_sysview_init: cannot bind, err:%d\n", err); return; } - sysview_pcb = tcp_listen_with_backlog(pcb, 1); - if (sysview_pcb == NULL) + m_pcb_listen = tcp_listen_with_backlog(pcb, 1); + if (m_pcb_listen == NULL) { if (pcb != NULL) { tcp_close(pcb); } - printf("net_sysview_init(): cannot listen\n"); + picoprobe_error("net_sysview_init: cannot listen\n"); return; } - tcp_accept(sysview_pcb, sysview_accept); + tcp_accept(m_pcb_listen, sysview_accept); } // net_sysview_init diff --git a/src/net/net_sysview.h b/src/net/net_sysview.h index 3533225c4..6080defb3 100755 --- a/src/net/net_sysview.h +++ b/src/net/net_sysview.h @@ -32,7 +32,8 @@ #endif -void net_sysview_init(void); + void net_sysview_init(uint32_t task_prio); +void net_sysview_send(const uint8_t *buf, uint32_t cnt); #ifdef __cplusplus diff --git a/src/rtt_console.c b/src/rtt_console.c index 099f11098..2f17de772 100755 --- a/src/rtt_console.c +++ b/src/rtt_console.c @@ -43,9 +43,13 @@ #if OPT_TARGET_UART #include "cdc_uart.h" #endif +#if OPT_NET_SYSVIEW_SERVER + #include "net/net_sysview.h" +#endif #include "led.h" +typedef void (*rtt_data_to_host)(const uint8_t *buf, uint32_t cnt); #define TARGET_RAM_START g_board_info.target_cfg->ram_regions[0].start #define TARGET_RAM_END g_board_info.target_cfg->ram_regions[0].end @@ -143,7 +147,49 @@ static uint32_t search_for_rtt_cb(void) -static void rtt_to_target(uint32_t rtt_cb, StreamBufferHandle_t stream, uint16_t channel, SEGGER_RTT_BUFFER_DOWN *aDown) +static bool rtt_from_target(uint32_t rtt_cb, uint16_t channel, SEGGER_RTT_BUFFER_UP *aUp, + rtt_data_to_host data_to_host, bool *worked) +{ + bool ok; + uint8_t buf[256]; + + ok = swd_read_word(rtt_cb + offsetof(SEGGER_RTT_CB, aUp[channel].WrOff), (uint32_t *)&(aUp->WrOff)); + + if (ok && aUp->WrOff != aUp->RdOff) { + // + // fetch characters from target + // + uint32_t cnt; + + if (aUp->WrOff > aUp->RdOff) { + cnt = aUp->WrOff - aUp->RdOff; + } + else { + cnt = aUp->SizeOfBuffer - aUp->RdOff; + } + cnt = MIN(cnt, sizeof(buf)); + + memset(buf, 0, sizeof(buf)); + ok = ok && swd_read_memory((uint32_t)aUp->pBuffer + aUp->RdOff, buf, cnt); + aUp->RdOff = (aUp->RdOff + cnt) % aUp->SizeOfBuffer; + ok = ok && swd_write_word(rtt_cb + offsetof(SEGGER_RTT_CB, aUp[channel].RdOff), aUp->RdOff); + + if (data_to_host != NULL) + { + // direct received data to host + data_to_host(buf, cnt); + } + + led_state(LS_RTT_RX_DATA); + *worked = true; + } + return ok; +} // rtt_from_target + + + +static bool rtt_to_target(uint32_t rtt_cb, StreamBufferHandle_t stream, uint16_t channel, + SEGGER_RTT_BUFFER_DOWN *aDown, bool *worked) { bool ok = true; uint8_t buf[16]; @@ -175,7 +221,9 @@ static void rtt_to_target(uint32_t rtt_cb, StreamBufferHandle_t stream, uint16_t led_state(LS_UART_TX_DATA); } } + *worked = true; } + return ok; } // rtt_to_target @@ -188,7 +236,6 @@ static void do_rtt_console(uint32_t rtt_cb) SEGGER_RTT_BUFFER_UP aUpSysView; // Up buffer, transferring information up from target via debug probe to host SEGGER_RTT_BUFFER_DOWN aDownSysView; // Down buffer, transferring information from host via debug probe to target #endif - uint8_t buf[256]; bool ok = true; static_assert(sizeof(uint32_t) == sizeof(unsigned int)); // why doesn't segger use uint32_t? @@ -211,46 +258,31 @@ static void do_rtt_console(uint32_t rtt_cb) // do operations rtt_console_running = true; while (ok && !sw_unlock_requested()) { - ok = ok && swd_read_word(rtt_cb + offsetof(SEGGER_RTT_CB, aUp[RTT_CHANNEL_CONSOLE].WrOff), (uint32_t *)&aUpConsole.WrOff); - - if (aUpConsole.WrOff == aUpConsole.RdOff) { - // -> no characters available - xEventGroupWaitBits(events, EV_RTT_TO_TARGET, pdTRUE, pdFALSE, pdMS_TO_TICKS(RTT_POLL_INT_MS)); - } - else { - // - // fetch characters from target - // - uint32_t cnt; - - if (aUpConsole.WrOff > aUpConsole.RdOff) { - cnt = aUpConsole.WrOff - aUpConsole.RdOff; - } - else { - cnt = aUpConsole.SizeOfBuffer - aUpConsole.RdOff; - } - cnt = MIN(cnt, sizeof(buf)); - - memset(buf, 0, sizeof(buf)); - ok = ok && swd_read_memory((uint32_t)aUpConsole.pBuffer + aUpConsole.RdOff, buf, cnt); - aUpConsole.RdOff = (aUpConsole.RdOff + cnt) % aUpConsole.SizeOfBuffer; - ok = ok && swd_write_word(rtt_cb + offsetof(SEGGER_RTT_CB, aUp[RTT_CHANNEL_CONSOLE].RdOff), aUpConsole.RdOff); + bool worked = false; + // + // transfer RTT from target to host + // #if OPT_TARGET_UART - // put received data into CDC UART - cdc_uart_write(buf, cnt); + ok = ok && rtt_from_target(rtt_cb, RTT_CHANNEL_CONSOLE, &aUpConsole, cdc_uart_write, &worked); +#endif +#if OPT_NET_SYSVIEW_SERVER + ok = ok && rtt_from_target(rtt_cb, RTT_CHANNEL_SYSVIEW, &aUpSysView, net_sysview_send, &worked); #endif - - led_state(LS_RTT_RX_DATA); - } // - // transfer RTT data to target + // transfer RTT data from host to target // - rtt_to_target(rtt_cb, stream_rtt_console_to_target, RTT_CHANNEL_CONSOLE, &aDownConsole); + ok = ok && rtt_to_target(rtt_cb, stream_rtt_console_to_target, RTT_CHANNEL_CONSOLE, &aDownConsole, &worked); #if OPT_NET_SYSVIEW_SERVER - rtt_to_target(rtt_cb, stream_rtt_console_to_target, RTT_CHANNEL_SYSVIEW, &aDownSysView); + ok = ok && rtt_to_target(rtt_cb, stream_rtt_sysview_to_target, RTT_CHANNEL_SYSVIEW, &aDownSysView, &worked); #endif + + if ( !worked) + { + // -> did nothing in the previous run -> delay + xEventGroupWaitBits(events, EV_RTT_TO_TARGET, pdTRUE, pdFALSE, pdMS_TO_TICKS(RTT_POLL_INT_MS)); + } } rtt_console_running = false; } // do_rtt_console From f5cf635ce9517e9198648befd728754f48ec2547 Mon Sep 17 00:00:00 2001 From: Hardy Griech Date: Mon, 8 May 2023 02:03:40 +0200 Subject: [PATCH 027/118] correct handling of tcp_write() without additional thread --- src/main.c | 3 +- src/net/net_sysview.c | 115 +++++++++++++++++++----------------------- src/net/net_sysview.h | 2 +- 3 files changed, 53 insertions(+), 67 deletions(-) diff --git a/src/main.c b/src/main.c index 8ddcffb5c..e3888df25 100644 --- a/src/main.c +++ b/src/main.c @@ -117,7 +117,6 @@ static uint8_t RxDataBuffer[_DAP_PACKET_COUNT_OPENOCD * CFG_TUD_VENDOR_RX_BUFSIZ #define NET_GLUE_TASK_PRIO (tskIDLE_PRIORITY + 10) // task which copies frames from tinyusb to lwip #define SIGROK_TASK_PRIO (tskIDLE_PRIORITY + 9) // Sigrok digital/analog signals (does nothing at the moment) #define MSC_WRITER_THREAD_PRIO (tskIDLE_PRIORITY + 8) // this is only running on writing UF2 files -#define NET_SYSVIEW_PRIO (tskIDLE_PRIORITY + 7) // net_sysview: send data to host (client) #define UART_TASK_PRIO (tskIDLE_PRIORITY + 5) // target -> host via UART #define RTT_CONSOLE_TASK_PRIO (tskIDLE_PRIORITY + 4) // target -> host via RTT #define CDC_DEBUG_TASK_PRIO (tskIDLE_PRIORITY + 4) // probe debugging output @@ -488,7 +487,7 @@ void usb_thread(void *ptr) #if OPT_NET net_glue_init(NET_GLUE_TASK_PRIO); #if OPT_NET_SYSVIEW_SERVER - net_sysview_init(NET_SYSVIEW_PRIO); + net_sysview_init(); #endif #if OPT_NET_ECHO_SERVER net_echo_init(); diff --git a/src/net/net_sysview.c b/src/net/net_sysview.c index 6e2d8748f..b270c2c17 100755 --- a/src/net/net_sysview.c +++ b/src/net/net_sysview.c @@ -26,12 +26,11 @@ #include "FreeRTOS.h" #include "stream_buffer.h" -#include "task.h" -#include "event_groups.h" #include "lwip/debug.h" #include "lwip/stats.h" #include "lwip/tcp.h" +#include "lwip/tcpip.h" #include "lwip/err.h" #include "picoprobe_config.h" @@ -76,20 +75,13 @@ struct tcp_pcb *m_pcb_client; #define STREAM_SYSVIEW_SIZE 4096 #define STREAM_SYSVIEW_TRIGGER 32 -static TaskHandle_t task_sysview = NULL; static StreamBufferHandle_t stream_sysview_to_host; -#define EV_STREAM 0x01 -#define EV_SENT 0x02 - -/// event flags -static EventGroupHandle_t events; - void sysview_error(void *arg, err_t err) { - printf("picoprobe_error: %d\n", err); + picoprobe_error("sysview_error: %d\n", err); m_state = SVS_NONE; } // sysview_error @@ -98,7 +90,7 @@ void sysview_error(void *arg, err_t err) void sysview_close(struct tcp_pcb *tpcb) { - //printf("sysview_close(%p): %d\n", tpcb, m_state); + printf("sysview_close(%p): %d\n", tpcb, m_state); tcp_arg(tpcb, NULL); tcp_sent(tpcb, NULL); @@ -113,16 +105,56 @@ void sysview_close(struct tcp_pcb *tpcb) +static void sysview_try_send(void *ctx) +{ + if (/* m_state == SVS_READY && */ !xStreamBufferIsEmpty(stream_sysview_to_host)) { + size_t cnt; + size_t max_cnt; + uint8_t tx_buf[64]; + err_t err; + + //printf("sysview_try_send: %d\n", xStreamBufferBytesAvailable(stream_sysview_to_host)); + + max_cnt = tcp_sndbuf(m_pcb_client); + if (max_cnt != 0) { + max_cnt = MIN(sizeof(tx_buf), max_cnt); + cnt = xStreamBufferReceive(stream_sysview_to_host, tx_buf, max_cnt, pdMS_TO_TICKS(10)); + if (cnt != 0) { + if (xStreamBufferIsEmpty(stream_sysview_to_host)) + { + err = tcp_write(m_pcb_client, tx_buf, cnt, TCP_WRITE_FLAG_COPY); + if (err != ERR_OK) + picoprobe_error("sysview_try_send/a: %d\n", err); +#if 0 + err = tcp_output(m_pcb_client); + if (err != ERR_OK) + picoprobe_error("sysview_try_send/b: %d\n", err); +#endif + } + else + { + err = tcp_write(m_pcb_client, tx_buf, cnt, TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE); + if (err != ERR_OK) + picoprobe_error("sysview_try_send/c: %d\n", err); + tcpip_callback_with_block(sysview_try_send, NULL, 0); + } + } + } + } +} // sysview_try_send + + + static err_t sysview_sent(void *arg, struct tcp_pcb *tpcb, uint16_t len) { - //printf("sysview_sent(%p,%p,%d) %d\n", arg, tpcb, len, m_state); + printf("sysview_sent(%p,%p,%d) %d\n", arg, tpcb, len, m_state); if (m_state == SVS_SEND_HELLO) { m_state = SVS_READY; xStreamBufferReset(stream_sysview_to_host); } - xEventGroupSetBits(events, EV_SENT); + tcpip_callback_with_block(sysview_try_send, NULL, 0); return ERR_OK; } // sysview_sent @@ -133,7 +165,7 @@ static err_t sysview_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t { err_t ret_err; - //printf("sysview_recv(%p,%p,%p,%d) %d\n", arg, tpcb, p, err, m_state); + // printf("sysview_recv(%p,%p,%p,%d) %d\n", arg, tpcb, p, err, m_state); if (p == NULL) { @@ -160,7 +192,7 @@ static err_t sysview_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t // // expecting hello message // - //printf("sysview_recv, %d:'%s'\n", p->len, (const char *)p->payload); + printf("sysview_recv, %d:'%s'\n", p->len, (const char *)p->payload); if (p->len != SYSVIEW_COMM_APP_HELLO_SIZE) { // invalid hello @@ -206,7 +238,7 @@ static err_t sysview_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err_t sysview_poll(void *arg, struct tcp_pcb *tpcb) { - //printf("sysview_poll(%p,%p) %d\n", arg, tpcb, m_state); + // printf("sysview_poll(%p,%p) %d\n", arg, tpcb, m_state); return ERR_OK; } // sysview_poll @@ -232,51 +264,9 @@ static err_t sysview_accept(void *arg, struct tcp_pcb *newpcb, err_t err) -static void sysview_thread(void *ptr) -{ - for (;;) { - xEventGroupWaitBits(events, EV_STREAM | EV_SENT, pdTRUE, pdFALSE, pdMS_TO_TICKS(1000)); - - if (m_state == SVS_READY && !xStreamBufferIsEmpty(stream_sysview_to_host)) { - size_t cnt; - size_t max_cnt; - uint8_t tx_buf[64]; - err_t err; - - //printf("sysview_thread: %d\n", xStreamBufferBytesAvailable(stream_sysview_to_host)); - - max_cnt = tcp_sndbuf(m_pcb_client); - if (max_cnt != 0) { - max_cnt = MIN(sizeof(tx_buf), max_cnt); - cnt = xStreamBufferReceive(stream_sysview_to_host, tx_buf, max_cnt, pdMS_TO_TICKS(10)); - if (cnt != 0) { - if (xStreamBufferIsEmpty(stream_sysview_to_host)) - { - err = tcp_write(m_pcb_client, tx_buf, cnt, TCP_WRITE_FLAG_COPY); - if (err != ERR_OK) - picoprobe_error("sysview_thread/a: %d\n", err); - err = tcp_output(m_pcb_client); - if (err != ERR_OK) - picoprobe_error("sysview_thread/b: %d\n", err); - } - else - { - err = tcp_write(m_pcb_client, tx_buf, cnt, TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE); - if (err != ERR_OK) - picoprobe_error("sysview_thread/c: %d\n", err); - xEventGroupSetBits(events, EV_STREAM); - } - } - } - } - } -} // sysview_thread - - - void net_sysview_send(const uint8_t *buf, uint32_t cnt) { - //printf("net_sysview_send(%p,%lu) %d\n", buf, cnt, m_state); + printf("net_sysview_send(%p,%lu) %d\n", buf, cnt, m_state); if (m_state != SVS_READY) { @@ -285,13 +275,13 @@ void net_sysview_send(const uint8_t *buf, uint32_t cnt) else { xStreamBufferSend(stream_sysview_to_host, buf, cnt, pdMS_TO_TICKS(5)); - xEventGroupSetBits(events, EV_STREAM); + tcpip_callback_with_block(sysview_try_send, NULL, 0); } } // net_sysview_send -void net_sysview_init(uint32_t task_prio) +void net_sysview_init(void) { err_t err; struct tcp_pcb *pcb; @@ -299,13 +289,10 @@ void net_sysview_init(uint32_t task_prio) // // initialize some infrastructure // - events = xEventGroupCreate(); - stream_sysview_to_host = xStreamBufferCreate(STREAM_SYSVIEW_SIZE, STREAM_SYSVIEW_TRIGGER); if (stream_sysview_to_host == NULL) { picoprobe_error("net_sysview_init: cannot create stream_sysview_to_host\n"); } - xTaskCreateAffinitySet(sysview_thread, "net_sysview", configMINIMAL_STACK_SIZE, NULL, task_prio, 1, &task_sysview); // // initialize socket listener diff --git a/src/net/net_sysview.h b/src/net/net_sysview.h index 6080defb3..7fe1a157d 100755 --- a/src/net/net_sysview.h +++ b/src/net/net_sysview.h @@ -32,7 +32,7 @@ #endif - void net_sysview_init(uint32_t task_prio); + void net_sysview_init(void); void net_sysview_send(const uint8_t *buf, uint32_t cnt); From 429a949adb3746c254f5e08efc1548b23fb008df Mon Sep 17 00:00:00 2001 From: Hardy Griech Date: Tue, 9 May 2023 12:03:12 +0200 Subject: [PATCH 028/118] config: give tasks big stacks --- include/FreeRTOSConfig.h | 4 ++-- include/lwipopts.h | 7 +++++-- include/tusb_config.h | 6 ++++-- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/include/FreeRTOSConfig.h b/include/FreeRTOSConfig.h index c79ddf475..fc4f87789 100644 --- a/include/FreeRTOSConfig.h +++ b/include/FreeRTOSConfig.h @@ -78,7 +78,7 @@ /* Memory allocation related definitions. */ #define configSUPPORT_STATIC_ALLOCATION 1 #define configSUPPORT_DYNAMIC_ALLOCATION 1 -#define configTOTAL_HEAP_SIZE (105*1024) +#define configTOTAL_HEAP_SIZE (150*1024) #define configAPPLICATION_ALLOCATED_HEAP 0 /* Hook function related definitions. */ @@ -87,7 +87,7 @@ #define configUSE_DAEMON_TASK_STARTUP_HOOK 0 /* Run time and task stats gathering related definitions. */ -#define configUSE_TRACE_FACILITY 0 // switch on task status output +#define configUSE_TRACE_FACILITY 1 // switch on task status output #define configGENERATE_RUN_TIME_STATS configUSE_TRACE_FACILITY #define configUSE_STATS_FORMATTING_FUNCTIONS 0 diff --git a/include/lwipopts.h b/include/lwipopts.h index 5d39398f9..4b836e1f4 100755 --- a/include/lwipopts.h +++ b/include/lwipopts.h @@ -74,12 +74,15 @@ //-------------------------------------- // memory #define MEM_SIZE 10000 +//#define MEM_LIBC_MALLOC 1 +//#define MEMP_MEM_MALLOC 1 +//#define LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT 1 //-------------------------------------- // for freertos mode -#define TCPIP_MBOX_SIZE 32 -#define TCPIP_THREAD_STACKSIZE 2048 +#define TCPIP_MBOX_SIZE 128 +#define TCPIP_THREAD_STACKSIZE 60000 #define TCPIP_THREAD_PRIO 11 diff --git a/include/tusb_config.h b/include/tusb_config.h index 0094f53c2..032b820a9 100644 --- a/include/tusb_config.h +++ b/include/tusb_config.h @@ -64,6 +64,8 @@ #define CFG_TUD_ENDPOINT0_SIZE 64 #endif +#define CFG_TUD_TASK_QUEUE_SZ 128 + //------------- CLASS -------------// //********************************************** @@ -106,7 +108,7 @@ #define CFG_TUD_CDC (CFG_TUD_CDC_UART + CFG_TUD_CDC_SIGROK + CFG_TUD_CDC_DEBUG) #if OPT_NET // lsusb output of NCM looks the same as setup from lwip webserver example - #define CFG_TUD_ECM_RNDIS 0 // RNDIS under Windows works only if it's the only class, so we try NCM for Linux + #define CFG_TUD_ECM_RNDIS 1 // RNDIS under Windows works only if it's the only class, so we try NCM for Linux #define CFG_TUD_NCM (1 - CFG_TUD_ECM_RNDIS) #else #define CFG_TUD_ECM_RNDIS 0 @@ -131,7 +133,7 @@ #if OPT_MSC // note: this is optimized for DAPLink write speed - #define CFG_TUD_MSC_EP_BUFSIZE 512 + #define CFG_TUD_MSC_EP_BUFSIZE 512 #endif #if OPT_NET From a4418584670579ba4edc56bbd9efbe6b65d2d212 Mon Sep 17 00:00:00 2001 From: Hardy Griech Date: Tue, 9 May 2023 12:03:38 +0200 Subject: [PATCH 029/118] print_task_stat() is now an extra task --- src/main.c | 81 ++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 51 insertions(+), 30 deletions(-) diff --git a/src/main.c b/src/main.c index e3888df25..09b3a5911 100644 --- a/src/main.c +++ b/src/main.c @@ -341,6 +341,10 @@ void dap_task(void *ptr) #if configUSE_TRACE_FACILITY +static uint32_t tusb_count; +static TimerHandle_t timer_task_stat; +static EventGroupHandle_t events_task_stat; + char task_state(eTaskState state) { static const char state_ch[] = "RrBSDI"; @@ -348,26 +352,35 @@ char task_state(eTaskState state) } // task_state +void trigger_task_stat(TimerHandle_t xTimer) +{ + xEventGroupSetBits(events_task_stat, 0x01); +} // trigger_task_stat + -void print_task_stat(void) +void print_task_stat(void *ptr) { - static uint32_t prev_s = (uint32_t)-8; - static bool initialized; - uint32_t curr_s; - - curr_s = (uint32_t)(time_us_64() / 1000000); - if (curr_s - prev_s >= 10) { - #define NUM_ENTRY 15 - HeapStats_t heap_status; - static TaskStatus_t task_status[NUM_ENTRY]; - uint32_t total_run_time; - - picoprobe_info("---------------------------------------\n"); +#define NUM_ENTRY 15 + bool initialized = false; + uint32_t prev_tusb_count = 0; + HeapStats_t heap_status; + TaskStatus_t task_status[NUM_ENTRY]; + uint32_t total_run_time; + + vTaskDelay(pdMS_TO_TICKS(100)); + + timer_task_stat = xTimerCreate("task stat", pdMS_TO_TICKS(10000), pdTRUE, NULL, trigger_task_stat); // just for fun: exact period of 10s + events_task_stat = xEventGroupCreate(); + + xTimerReset(timer_task_stat, 0); + + for (;;) { + printf("---------------------------------------\n"); if ( !initialized) { uint32_t cnt; initialized = true; - picoprobe_info("assign IDLE tasks to certain core\n"); + printf("assign IDLE tasks to certain core\n"); cnt = uxTaskGetSystemState(task_status, NUM_ENTRY, &total_run_time); for (uint32_t n = 0; n < cnt; ++n) { if (strcmp(task_status[n].pcTaskName, "IDLE0") == 0) { @@ -379,13 +392,15 @@ void print_task_stat(void) } } + printf("TinyUSB counter : %lu\n", tusb_count - prev_tusb_count); + prev_tusb_count = tusb_count; vPortGetHeapStats( &heap_status); - //picoprobe_info("curr heap free: %d\n", heap_status.xAvailableHeapSpaceInBytes); - picoprobe_info("min heap free : %d\n", heap_status.xMinimumEverFreeBytesRemaining); + printf("curr heap free : %d\n", heap_status.xAvailableHeapSpaceInBytes); + printf("min heap free : %d\n", heap_status.xMinimumEverFreeBytesRemaining); - picoprobe_info("number of tasks : %lu\n", uxTaskGetNumberOfTasks()); + printf("number of tasks : %lu\n", uxTaskGetNumberOfTasks()); if (uxTaskGetNumberOfTasks() > NUM_ENTRY) { - picoprobe_info("!!!!!!!!!!!!!!! redefine NUM_ENTRY to see task state\n"); + printf("!!!!!!!!!!!!!!! redefine NUM_ENTRY to see task state\n"); } else { // this part is critical concerning overflow because the numbers are getting quickly very big (us timer resolution) @@ -405,10 +420,10 @@ void print_task_stat(void) curr_tick_sum += task_status[n].ulRunTimeCounter; delta_tick_sum += task_status[n].ulRunTimeCounter - prev_tick[prev_ndx]; } - picoprobe_info("delta tick sum : %lu\n", delta_tick_sum); + printf("delta tick sum : %lu\n", delta_tick_sum); - picoprobe_info("NUM PRI S/AM CPU TOT STACK NAME\n"); - picoprobe_info("---------------------------------------\n"); + printf("NUM PRI S/AM CPU TOT STACK NAME\n"); + printf("---------------------------------------\n"); curr_tick_sum /= configNUM_CORES; delta_tick_sum /= configNUM_CORES; @@ -429,7 +444,7 @@ void print_task_stat(void) percent_sum += percent; percent_total_sum += percent_total; - picoprobe_info("%3lu %2lu %c/%2d %4lu %4lu %5lu %s\n", + printf("%3lu %2lu %c/%2d %4lu %4lu %5lu %s\n", task_status[n].xTaskNumber, task_status[n].uxCurrentPriority, task_state(task_status[n].eCurrentState), (int)task_status[n].uxCoreAffinityMask, @@ -439,12 +454,12 @@ void print_task_stat(void) prev_tick[prev_ndx] = curr_tick; } - picoprobe_info("---------------------------------------\n"); - picoprobe_info(" %3lu %3lu\n", percent_sum, percent_total_sum); + printf("---------------------------------------\n"); + printf(" %3lu %3lu\n", percent_sum, percent_total_sum); } - picoprobe_info("---------------------------------------\n"); + printf("---------------------------------------\n"); - prev_s = curr_s; + xEventGroupWaitBits(events_task_stat, 0x01, pdTRUE, pdFALSE, pdMS_TO_TICKS(60000)); } } // print_task_stat #endif @@ -502,13 +517,19 @@ void usb_thread(void *ptr) xTaskCreateAffinitySet(dap_task, "CMSIS-DAP", configMINIMAL_STACK_SIZE, NULL, DAP_TASK_PRIO, 2, &dap_taskhandle); #endif +#if configUSE_TRACE_FACILITY + { + TaskHandle_t task_stat_handle; + xTaskCreateAffinitySet(print_task_stat, "Print Task Stat", configMINIMAL_STACK_SIZE, NULL, 30, -1, &task_stat_handle); + } +#endif + tusb_init(); for (;;) { - tud_task(); // the FreeRTOS version goes into blocking state if its event queue is empty - #if configUSE_TRACE_FACILITY - print_task_stat(); + ++tusb_count; #endif + tud_task(); // the FreeRTOS version goes into blocking state if its event queue is empty } } // usb_thread @@ -572,7 +593,7 @@ int main(void) events = xEventGroupCreate(); // it seems that lwip does not like affinity setting in its thread, so the affinity of the USB thread is corrected in the task itself - xTaskCreateAffinitySet(usb_thread, "TinyUSB Main", configMINIMAL_STACK_SIZE, NULL, TUD_TASK_PRIO, -1, &tud_taskhandle); + xTaskCreateAffinitySet(usb_thread, "TinyUSB Main", 8000, NULL, TUD_TASK_PRIO, -1, &tud_taskhandle); vTaskStartScheduler(); return 0; From 821e54890d45219c99c0c54de25424efc1d560f4 Mon Sep 17 00:00:00 2001 From: Hardy Griech Date: Tue, 9 May 2023 12:03:59 +0200 Subject: [PATCH 030/118] minor --- src/usb_descriptors.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/usb_descriptors.c b/src/usb_descriptors.c index e4065fab8..ebcc5c9d1 100644 --- a/src/usb_descriptors.c +++ b/src/usb_descriptors.c @@ -26,7 +26,6 @@ */ #include "tusb.h" -#include "pico/unique_id.h" #include "get_serial.h" #include "picoprobe_config.h" From d882346d51504572173800d305c9651c59e7c116 Mon Sep 17 00:00:00 2001 From: Hardy Griech Date: Tue, 9 May 2023 12:04:58 +0200 Subject: [PATCH 031/118] debugging around with lock-ups --- src/net/net_sysview.c | 59 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 48 insertions(+), 11 deletions(-) diff --git a/src/net/net_sysview.c b/src/net/net_sysview.c index b270c2c17..71ce3adf8 100755 --- a/src/net/net_sysview.c +++ b/src/net/net_sysview.c @@ -70,13 +70,15 @@ enum echo_states // only one client instance is possible static uint8_t m_state; struct tcp_pcb *m_pcb_client; - +static uint32_t m_xmt_cnt; #define STREAM_SYSVIEW_SIZE 4096 #define STREAM_SYSVIEW_TRIGGER 32 static StreamBufferHandle_t stream_sysview_to_host; +static bool block_call_back_message; // TODO trying, not final + void sysview_error(void *arg, err_t err) @@ -100,6 +102,8 @@ void sysview_close(struct tcp_pcb *tpcb) tcp_close(tpcb); + xStreamBufferReset(stream_sysview_to_host); + m_state = SVS_NONE; } // sysview_close @@ -107,15 +111,16 @@ void sysview_close(struct tcp_pcb *tpcb) static void sysview_try_send(void *ctx) { + block_call_back_message = false; + if (/* m_state == SVS_READY && */ !xStreamBufferIsEmpty(stream_sysview_to_host)) { size_t cnt; size_t max_cnt; - uint8_t tx_buf[64]; + uint8_t tx_buf[512]; err_t err; - //printf("sysview_try_send: %d\n", xStreamBufferBytesAvailable(stream_sysview_to_host)); - max_cnt = tcp_sndbuf(m_pcb_client); + //printf("sysview_try_send: %d %d\n", xStreamBufferBytesAvailable(stream_sysview_to_host), max_cnt); if (max_cnt != 0) { max_cnt = MIN(sizeof(tx_buf), max_cnt); cnt = xStreamBufferReceive(stream_sysview_to_host, tx_buf, max_cnt, pdMS_TO_TICKS(10)); @@ -123,21 +128,38 @@ static void sysview_try_send(void *ctx) if (xStreamBufferIsEmpty(stream_sysview_to_host)) { err = tcp_write(m_pcb_client, tx_buf, cnt, TCP_WRITE_FLAG_COPY); - if (err != ERR_OK) + if (err != ERR_OK) { picoprobe_error("sysview_try_send/a: %d\n", err); + sysview_close(m_pcb_client); + } #if 0 err = tcp_output(m_pcb_client); - if (err != ERR_OK) + if (err != ERR_OK) { picoprobe_error("sysview_try_send/b: %d\n", err); + sysview_close(m_pcb_client); + } #endif } else { err = tcp_write(m_pcb_client, tx_buf, cnt, TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE); - if (err != ERR_OK) - picoprobe_error("sysview_try_send/c: %d\n", err); + if (err != ERR_OK) { + picoprobe_error("sysview_try_send/c: %d\n", err); sysview_close(m_pcb_client); + } tcpip_callback_with_block(sysview_try_send, NULL, 0); } + m_xmt_cnt += cnt; + if (m_xmt_cnt > 1000) + { + m_xmt_cnt = 0; +#if 1 + err = tcp_output(m_pcb_client); + if (err != ERR_OK) { + picoprobe_error("sysview_try_send/d: %d\n", err); + sysview_close(m_pcb_client); + } +#endif + } } } } @@ -156,6 +178,8 @@ static err_t sysview_sent(void *arg, struct tcp_pcb *tpcb, uint16_t len) } tcpip_callback_with_block(sysview_try_send, NULL, 0); + m_xmt_cnt = 0; + return ERR_OK; } // sysview_sent @@ -240,6 +264,7 @@ err_t sysview_poll(void *arg, struct tcp_pcb *tpcb) { // printf("sysview_poll(%p,%p) %d\n", arg, tpcb, m_state); + sysview_try_send(NULL); return ERR_OK; } // sysview_poll @@ -266,7 +291,8 @@ static err_t sysview_accept(void *arg, struct tcp_pcb *newpcb, err_t err) void net_sysview_send(const uint8_t *buf, uint32_t cnt) { - printf("net_sysview_send(%p,%lu) %d\n", buf, cnt, m_state); + if (m_state != SVS_NONE) + printf("net_sysview_send(%p,%lu) %d\n", buf, cnt, m_state); if (m_state != SVS_READY) { @@ -274,8 +300,19 @@ void net_sysview_send(const uint8_t *buf, uint32_t cnt) } else { - xStreamBufferSend(stream_sysview_to_host, buf, cnt, pdMS_TO_TICKS(5)); - tcpip_callback_with_block(sysview_try_send, NULL, 0); + xStreamBufferSend(stream_sysview_to_host, buf, cnt, pdMS_TO_TICKS(1)); + + if ( !block_call_back_message) + { + err_t err; + + block_call_back_message = true; + err = tcpip_callback_with_block(sysview_try_send, NULL, 0); + if (err != ERR_OK) { + printf("net_sysview_send: queue %d\n", err); + sysview_close(m_pcb_client); + } + } } } // net_sysview_send From 9ab3ff96fc2fdd402237d4611f5753fd32ff0831 Mon Sep 17 00:00:00 2001 From: Hardy Griech Date: Tue, 9 May 2023 12:05:56 +0200 Subject: [PATCH 032/118] assure that the up/down buffers exist on target (to target of sysview is still not working) --- src/rtt_console.c | 111 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 83 insertions(+), 28 deletions(-) diff --git a/src/rtt_console.c b/src/rtt_console.c index 2f17de772..b12d2c1f3 100755 --- a/src/rtt_console.c +++ b/src/rtt_console.c @@ -147,6 +147,44 @@ static uint32_t search_for_rtt_cb(void) +static bool rtt_check_channel_from_target(uint32_t rtt_cb, uint16_t channel, SEGGER_RTT_BUFFER_UP *aUp) +{ + bool ok; + int32_t buff_cnt; + + ok = (rtt_cb >= TARGET_RAM_START && rtt_cb <= TARGET_RAM_END); + ok = ok && swd_read_word(rtt_cb + offsetof(SEGGER_RTT_CB, MaxNumUpBuffers), (uint32_t *)&(buff_cnt)); + ok = ok && (buff_cnt > channel); + ok = ok && swd_read_memory(rtt_cb + offsetof(SEGGER_RTT_CB, aUp[channel]), (uint8_t *)aUp, sizeof(SEGGER_RTT_BUFFER_UP)); + ok = ok && (aUp->SizeOfBuffer > 0 && aUp->SizeOfBuffer < TARGET_RAM_END - TARGET_RAM_START); + ok = ok && ((uint32_t)aUp->pBuffer >= TARGET_RAM_START && (uint32_t)aUp->pBuffer + aUp->SizeOfBuffer <= TARGET_RAM_END); + if (ok) { + printf("rtt_check_channel_from_target: %u %p %u %u %u\n", channel, aUp->pBuffer, aUp->SizeOfBuffer, aUp->RdOff, aUp->WrOff); + } + return ok; +} // rtt_check_channel_from_target + + + +static bool rtt_check_channel_to_target(uint32_t rtt_cb, uint16_t channel, SEGGER_RTT_BUFFER_DOWN *aDown) +{ + bool ok; + int32_t buff_cnt; + + ok = (rtt_cb >= TARGET_RAM_START && rtt_cb <= TARGET_RAM_END); + ok = ok && swd_read_word(rtt_cb + offsetof(SEGGER_RTT_CB, MaxNumDownBuffers), (uint32_t *)&(buff_cnt)); + ok = ok && (buff_cnt > channel); + ok = ok && swd_read_memory(rtt_cb + offsetof(SEGGER_RTT_CB, aDown[channel]), (uint8_t *)aDown, sizeof(SEGGER_RTT_BUFFER_DOWN)); + ok = ok && (aDown->SizeOfBuffer > 0 && aDown->SizeOfBuffer < TARGET_RAM_END - TARGET_RAM_START); + ok = ok && ((uint32_t)aDown->pBuffer >= TARGET_RAM_START && (uint32_t)aDown->pBuffer + aDown->SizeOfBuffer <= TARGET_RAM_END); + if (ok) { + printf("rtt_check_channel_to_target: %u %p %u %u %u\n", channel, aDown->pBuffer, aDown->SizeOfBuffer, aDown->RdOff, aDown->WrOff); + } + return ok; +} // rtt_check_channel_to_target + + + static bool rtt_from_target(uint32_t rtt_cb, uint16_t channel, SEGGER_RTT_BUFFER_UP *aUp, rtt_data_to_host data_to_host, bool *worked) { @@ -211,9 +249,11 @@ static bool rtt_to_target(uint32_t rtt_cb, StreamBufferHandle_t stream, uint16_t cnt = (aDown->RdOff - aDown->WrOff) - 1; } cnt = MIN(cnt, sizeof(buf)); + printf("a cnt: %u %u %lu\n", channel, aDown->WrOff, cnt); r = xStreamBufferReceive(stream, &buf, cnt, 0); if (r > 0) { + printf("b addr: %u %lx %d\n", channel, (uint32_t)aDown->pBuffer + aDown->WrOff, r); ok = ok && swd_write_memory((uint32_t)aDown->pBuffer + aDown->WrOff, buf, r); aDown->WrOff = (aDown->WrOff + r) % aDown->SizeOfBuffer; ok = ok && swd_write_word(rtt_cb + offsetof(SEGGER_RTT_CB, aDown[channel].WrOff), aDown->WrOff); @@ -230,11 +270,17 @@ static bool rtt_to_target(uint32_t rtt_cb, StreamBufferHandle_t stream, uint16_t static void do_rtt_console(uint32_t rtt_cb) { +#if OPT_TARGET_UART SEGGER_RTT_BUFFER_UP aUpConsole; // Up buffer, transferring information up from target via debug probe to host SEGGER_RTT_BUFFER_DOWN aDownConsole; // Down buffer, transferring information from host via debug probe to target + bool ok_console_from_target = false; + bool ok_console_to_target = false; +#endif #if OPT_NET_SYSVIEW_SERVER SEGGER_RTT_BUFFER_UP aUpSysView; // Up buffer, transferring information up from target via debug probe to host SEGGER_RTT_BUFFER_DOWN aDownSysView; // Down buffer, transferring information from host via debug probe to target + bool ok_sysview_from_target = false; + bool ok_sysview_to_target = false; #endif bool ok = true; @@ -244,39 +290,47 @@ static void do_rtt_console(uint32_t rtt_cb) return; } - ok = ok && swd_read_memory(rtt_cb + offsetof(SEGGER_RTT_CB, aUp[RTT_CHANNEL_CONSOLE]), - (uint8_t *)&aUpConsole, sizeof(aUpConsole)); - ok = ok && swd_read_memory(rtt_cb + offsetof(SEGGER_RTT_CB, aDown[RTT_CHANNEL_CONSOLE]), - (uint8_t *)&aDownConsole, sizeof(aDownConsole)); -#if OPT_NET_SYSVIEW_SERVER - ok = ok && swd_read_memory(rtt_cb + offsetof(SEGGER_RTT_CB, aUp[RTT_CHANNEL_SYSVIEW]), - (uint8_t *)&aUpSysView, sizeof(aUpSysView)); - ok = ok && swd_read_memory(rtt_cb + offsetof(SEGGER_RTT_CB, aDown[RTT_CHANNEL_SYSVIEW]), - (uint8_t *)&aDownSysView, sizeof(aDownSysView)); -#endif - // do operations rtt_console_running = true; while (ok && !sw_unlock_requested()) { bool worked = false; + #if OPT_TARGET_UART + if ( !ok_console_from_target) + ok_console_from_target = rtt_check_channel_from_target(rtt_cb, RTT_CHANNEL_CONSOLE, &aUpConsole); + if ( !ok_console_to_target) + ok_console_to_target = rtt_check_channel_to_target(rtt_cb, RTT_CHANNEL_CONSOLE, &aDownConsole); + #endif + #if OPT_NET_SYSVIEW_SERVER + if ( !ok_sysview_from_target) + ok_sysview_from_target = rtt_check_channel_from_target(rtt_cb, RTT_CHANNEL_SYSVIEW, &aUpSysView); + if ( !ok_sysview_to_target) + ok_sysview_to_target = rtt_check_channel_to_target(rtt_cb, RTT_CHANNEL_SYSVIEW, &aDownSysView); + #endif + // // transfer RTT from target to host // -#if OPT_TARGET_UART - ok = ok && rtt_from_target(rtt_cb, RTT_CHANNEL_CONSOLE, &aUpConsole, cdc_uart_write, &worked); -#endif -#if OPT_NET_SYSVIEW_SERVER - ok = ok && rtt_from_target(rtt_cb, RTT_CHANNEL_SYSVIEW, &aUpSysView, net_sysview_send, &worked); -#endif + #if OPT_TARGET_UART + if (ok_console_from_target) + ok = ok && rtt_from_target(rtt_cb, RTT_CHANNEL_CONSOLE, &aUpConsole, cdc_uart_write, &worked); + #endif + #if OPT_NET_SYSVIEW_SERVER + if (ok_sysview_from_target) + ok = ok && rtt_from_target(rtt_cb, RTT_CHANNEL_SYSVIEW, &aUpSysView, net_sysview_send, &worked); + #endif // // transfer RTT data from host to target // - ok = ok && rtt_to_target(rtt_cb, stream_rtt_console_to_target, RTT_CHANNEL_CONSOLE, &aDownConsole, &worked); -#if OPT_NET_SYSVIEW_SERVER - ok = ok && rtt_to_target(rtt_cb, stream_rtt_sysview_to_target, RTT_CHANNEL_SYSVIEW, &aDownSysView, &worked); -#endif + #if OPT_TARGET_UART + if (ok_console_to_target) + ok = ok && rtt_to_target(rtt_cb, stream_rtt_console_to_target, RTT_CHANNEL_CONSOLE, &aDownConsole, &worked); + #endif + #if OPT_NET_SYSVIEW_SERVER + if (ok_sysview_to_target) + ok = ok && rtt_to_target(rtt_cb, stream_rtt_sysview_to_target, RTT_CHANNEL_SYSVIEW, &aDownSysView, &worked); + #endif if ( !worked) { @@ -348,7 +402,7 @@ void rtt_console_thread(void *ptr) } } - vTaskDelay(pdMS_TO_TICKS(100)); + vTaskDelay(pdMS_TO_TICKS(100)); // give the target some time for startup if ( !target_connect()) { led_state(LS_NO_TARGET); target_online = false; @@ -382,7 +436,7 @@ bool rtt_console_cb_exists(void) -void rtt_send_byte(StreamBufferHandle_t stream, uint8_t ch) +void rtt_send_byte(StreamBufferHandle_t stream, uint16_t channel, uint8_t ch, bool allow_drop) /** * Write a byte into the RTT stream. * If there is no space left in the stream, wait 10ms and then try again. @@ -390,13 +444,13 @@ void rtt_send_byte(StreamBufferHandle_t stream, uint8_t ch) */ { size_t available = xStreamBufferSpacesAvailable(stream); - if (available < sizeof(ch)) { + if ( !allow_drop && available < sizeof(ch)) { vTaskDelay(pdMS_TO_TICKS(10)); available = xStreamBufferSpacesAvailable(stream); if (available < sizeof(ch)) { uint8_t dummy; xStreamBufferReceive(stream, &dummy, sizeof(dummy), 0); - picoprobe_error("rtt_console_send_byte: drop byte\n"); + picoprobe_error("rtt_console_send_byte: drop byte on channel %d\n", channel); } } xStreamBufferSend(stream, &ch, sizeof(ch), 0); @@ -407,7 +461,7 @@ void rtt_send_byte(StreamBufferHandle_t stream, uint8_t ch) void rtt_console_send_byte(uint8_t ch) { - rtt_send_byte(stream_rtt_console_to_target, ch); + rtt_send_byte(stream_rtt_console_to_target, RTT_CHANNEL_CONSOLE, ch, false); } // rtt_console_send_byte @@ -415,7 +469,8 @@ void rtt_console_send_byte(uint8_t ch) #if OPT_NET_SYSVIEW_SERVER void rtt_sysview_send_byte(uint8_t ch) { - rtt_send_byte(stream_rtt_sysview_to_target, ch); + // TODO der muss noch auf NULL checken! + //rtt_send_byte(stream_rtt_sysview_to_target, RTT_CHANNEL_SYSVIEW, ch, true); } // rtt_sysview_send_byte #endif @@ -439,7 +494,7 @@ void rtt_console_init(uint32_t task_prio) } #endif - xTaskCreateAffinitySet(rtt_console_thread, "RTT_CONSOLE", configMINIMAL_STACK_SIZE, NULL, task_prio, 1, &task_rtt_console); + xTaskCreateAffinitySet(rtt_console_thread, "RTT", configMINIMAL_STACK_SIZE, NULL, task_prio, 1, &task_rtt_console); if (task_rtt_console == NULL) { picoprobe_error("rtt_console_init: cannot create task_rtt_console\n"); From c527f8e775c9e1fa84e74415e50708284dee4598 Mon Sep 17 00:00:00 2001 From: Hardy Griech Date: Tue, 9 May 2023 13:32:44 +0200 Subject: [PATCH 033/118] no threading in lwIP! --- src/net/net_glue.c | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/src/net/net_glue.c b/src/net/net_glue.c index a671bddc7..e0f68bd85 100755 --- a/src/net/net_glue.c +++ b/src/net/net_glue.c @@ -48,8 +48,8 @@ #include "dnserver.h" #endif -#include "FreeRTOS.h" -#include "event_groups.h" +//#include "FreeRTOS.h" +//#include "event_groups.h" #include "tusb.h" @@ -91,9 +91,9 @@ static const dhcp_config_t dhcp_config = entries /* entries */ }; -static TaskHandle_t task_net_glue = NULL; +//static TaskHandle_t task_net_glue = NULL; -static EventGroupHandle_t events; +//static EventGroupHandle_t events; @@ -128,6 +128,22 @@ void tud_network_init_cb(void) +static void net_glue_usb_to_lwip(void *ptr) +/** + * handle any packet received by tud_network_recv_cb() in context of lwIP + */ +{ + // printf("net_glue_usb_to_lwip\n"); + if (received_frame != NULL) { + ethernet_input(received_frame, &netif_data); + pbuf_free(received_frame); + received_frame = NULL; + tud_network_recv_renew(); + } +} // net_glue_usb_to_lwip + + + bool tud_network_recv_cb(const uint8_t *src, uint16_t size) { //printf("!!!!!!!!!!!!!!tud_network_recv_cb(%p,%u)\n", src, size); @@ -146,7 +162,8 @@ bool tud_network_recv_cb(const uint8_t *src, uint16_t size) /* store away the pointer for service_traffic() to later handle */ received_frame = p; - xEventGroupSetBits(events, EV_RCVFRAME_READY); + //xEventGroupSetBits(events, EV_RCVFRAME_READY); + tcpip_callback_with_block(net_glue_usb_to_lwip, NULL, 0); } } return true; @@ -273,8 +290,9 @@ static void init_lwip(void) static void net_glue_thread(void *ptr) { for (;;) { - xEventGroupWaitBits(events, EV_RCVFRAME_READY, pdTRUE, pdFALSE, pdMS_TO_TICKS(100)); + //xEventGroupWaitBits(events, EV_RCVFRAME_READY, pdTRUE, pdFALSE, pdMS_TO_TICKS(100)); +#if 0 /* handle any packet received by tud_network_recv_cb() */ if (received_frame) { ethernet_input(received_frame, &netif_data); @@ -282,6 +300,7 @@ static void net_glue_thread(void *ptr) received_frame = NULL; tud_network_recv_renew(); } +#endif } } // net_glue_thread @@ -289,13 +308,15 @@ static void net_glue_thread(void *ptr) void net_glue_init(uint32_t task_prio) { - events = xEventGroupCreate(); + //events = xEventGroupCreate(); init_lwip(); +#if 0 xTaskCreateAffinitySet(net_glue_thread, "NET_GLUE", configMINIMAL_STACK_SIZE, NULL, task_prio, 1, &task_net_glue); if (task_net_glue == NULL) { picoprobe_error("net_glue_init: cannot create task_net_glue\n"); } +#endif } // net_glue_init From e6a8b95fbfc4ed92222a2fc24a2c2896d6b17ca2 Mon Sep 17 00:00:00 2001 From: Hardy Griech Date: Tue, 9 May 2023 13:38:23 +0200 Subject: [PATCH 034/118] clean up --- src/main.c | 58 +++++++++++++++++++++++++++++++--------------- src/net/net_glue.c | 46 +----------------------------------- src/net/net_glue.h | 2 +- 3 files changed, 41 insertions(+), 65 deletions(-) diff --git a/src/main.c b/src/main.c index 09b3a5911..3b7651885 100644 --- a/src/main.c +++ b/src/main.c @@ -114,7 +114,6 @@ static uint8_t RxDataBuffer[_DAP_PACKET_COUNT_OPENOCD * CFG_TUD_VENDOR_RX_BUFSIZ // there is one more task prio in lwipopts.h #define TUD_TASK_PRIO (tskIDLE_PRIORITY + 20) // uses one core continuously (no longer valid with FreeRTOS usage) #define LED_TASK_PRIO (tskIDLE_PRIORITY + 12) // simple task which may interrupt everything else for periodic blinking -#define NET_GLUE_TASK_PRIO (tskIDLE_PRIORITY + 10) // task which copies frames from tinyusb to lwip #define SIGROK_TASK_PRIO (tskIDLE_PRIORITY + 9) // Sigrok digital/analog signals (does nothing at the moment) #define MSC_WRITER_THREAD_PRIO (tskIDLE_PRIORITY + 8) // this is only running on writing UF2 files #define UART_TASK_PRIO (tskIDLE_PRIORITY + 5) // target -> host via UART @@ -361,12 +360,28 @@ void trigger_task_stat(TimerHandle_t xTimer) void print_task_stat(void *ptr) { #define NUM_ENTRY 15 - bool initialized = false; uint32_t prev_tusb_count = 0; HeapStats_t heap_status; TaskStatus_t task_status[NUM_ENTRY]; uint32_t total_run_time; +#if defined(configUSE_CORE_AFFINITY) && configUSE_CORE_AFFINITY != 0 + { + uint32_t cnt; + + printf("assign IDLE tasks to certain core\n"); + cnt = uxTaskGetSystemState(task_status, NUM_ENTRY, &total_run_time); + for (uint32_t n = 0; n < cnt; ++n) { + if (strcmp(task_status[n].pcTaskName, "IDLE0") == 0) { + vTaskCoreAffinitySet(task_status[n].xHandle, 1 << 0); + } + else if (strcmp(task_status[n].pcTaskName, "IDLE1") == 0) { + vTaskCoreAffinitySet(task_status[n].xHandle, 1 << 1); + } + } + } +#endif + vTaskDelay(pdMS_TO_TICKS(100)); timer_task_stat = xTimerCreate("task stat", pdMS_TO_TICKS(10000), pdTRUE, NULL, trigger_task_stat); // just for fun: exact period of 10s @@ -376,21 +391,6 @@ void print_task_stat(void *ptr) for (;;) { printf("---------------------------------------\n"); - if ( !initialized) { - uint32_t cnt; - - initialized = true; - printf("assign IDLE tasks to certain core\n"); - cnt = uxTaskGetSystemState(task_status, NUM_ENTRY, &total_run_time); - for (uint32_t n = 0; n < cnt; ++n) { - if (strcmp(task_status[n].pcTaskName, "IDLE0") == 0) { - vTaskCoreAffinitySet(task_status[n].xHandle, 1 << 0); - } - else if (strcmp(task_status[n].pcTaskName, "IDLE1") == 0) { - vTaskCoreAffinitySet(task_status[n].xHandle, 1 << 1); - } - } - } printf("TinyUSB counter : %lu\n", tusb_count - prev_tusb_count); prev_tusb_count = tusb_count; @@ -419,6 +419,13 @@ void print_task_stat(void *ptr) assert(prev_ndx < NUM_ENTRY + 1); curr_tick_sum += task_status[n].ulRunTimeCounter; delta_tick_sum += task_status[n].ulRunTimeCounter - prev_tick[prev_ndx]; + +#if defined(configUSE_CORE_AFFINITY) && configUSE_CORE_AFFINITY != 0 + if (strcmp(task_status[n].pcTaskName, "IDLE1") != 0 && vTaskCoreAffinityGet(task_status[n].xHandle) != 1) { + printf("!!!! change affinity of '%s' to 1\n", task_status[n].pcTaskName); + vTaskCoreAffinitySet(task_status[n].xHandle, 1); + } +#endif } printf("delta tick sum : %lu\n", delta_tick_sum); @@ -444,6 +451,7 @@ void print_task_stat(void *ptr) percent_sum += percent; percent_total_sum += percent_total; +#if defined(configUSE_CORE_AFFINITY) && configUSE_CORE_AFFINITY != 0 printf("%3lu %2lu %c/%2d %4lu %4lu %5lu %s\n", task_status[n].xTaskNumber, task_status[n].uxCurrentPriority, @@ -451,6 +459,15 @@ void print_task_stat(void *ptr) percent, percent_total, task_status[n].usStackHighWaterMark, task_status[n].pcTaskName); +#else + printf("%3lu %2lu %c/%2d %4lu %4lu %5lu %s\n", + task_status[n].xTaskNumber, + task_status[n].uxCurrentPriority, + task_state(task_status[n].eCurrentState), 1, + percent, percent_total, + task_status[n].usStackHighWaterMark, + task_status[n].pcTaskName); +#endif prev_tick[prev_ndx] = curr_tick; } @@ -476,7 +493,9 @@ void usb_thread(void *ptr) led_init(LED_TASK_PRIO); +#if defined(configUSE_CORE_AFFINITY) && configUSE_CORE_AFFINITY != 0 vTaskCoreAffinitySet(tud_taskhandle, 1); +#endif // do a first initialization, dynamic target detection is done in rtt_console if (g_board_info.prerun_board_config != NULL) { @@ -500,7 +519,8 @@ void usb_thread(void *ptr) #endif #if OPT_NET - net_glue_init(NET_GLUE_TASK_PRIO); + net_glue_init(); + #if OPT_NET_SYSVIEW_SERVER net_sysview_init(); #endif @@ -592,7 +612,7 @@ int main(void) events = xEventGroupCreate(); - // it seems that lwip does not like affinity setting in its thread, so the affinity of the USB thread is corrected in the task itself + // it seems that TinyUSB does not like affinity setting in its thread, so the affinity of the USB thread is corrected in the task itself xTaskCreateAffinitySet(usb_thread, "TinyUSB Main", 8000, NULL, TUD_TASK_PRIO, -1, &tud_taskhandle); vTaskStartScheduler(); diff --git a/src/net/net_glue.c b/src/net/net_glue.c index e0f68bd85..bbf6aa9e6 100755 --- a/src/net/net_glue.c +++ b/src/net/net_glue.c @@ -48,9 +48,6 @@ #include "dnserver.h" #endif -//#include "FreeRTOS.h" -//#include "event_groups.h" - #include "tusb.h" @@ -91,10 +88,6 @@ static const dhcp_config_t dhcp_config = entries /* entries */ }; -//static TaskHandle_t task_net_glue = NULL; - -//static EventGroupHandle_t events; - #if OPT_NET_DNS @@ -162,7 +155,6 @@ bool tud_network_recv_cb(const uint8_t *src, uint16_t size) /* store away the pointer for service_traffic() to later handle */ received_frame = p; - //xEventGroupSetBits(events, EV_RCVFRAME_READY); tcpip_callback_with_block(net_glue_usb_to_lwip, NULL, 0); } } @@ -257,7 +249,7 @@ static err_t netif_init_cb(struct netif *netif) -static void init_lwip(void) +void net_glue_init(void) { struct netif *netif = &netif_data; @@ -283,40 +275,4 @@ static void init_lwip(void) while (dnserv_init(IP_ADDR_ANY, 53, dns_query_proc) != ERR_OK) ; #endif -} // init_lwip - - - -static void net_glue_thread(void *ptr) -{ - for (;;) { - //xEventGroupWaitBits(events, EV_RCVFRAME_READY, pdTRUE, pdFALSE, pdMS_TO_TICKS(100)); - -#if 0 - /* handle any packet received by tud_network_recv_cb() */ - if (received_frame) { - ethernet_input(received_frame, &netif_data); - pbuf_free(received_frame); - received_frame = NULL; - tud_network_recv_renew(); - } -#endif - } -} // net_glue_thread - - - -void net_glue_init(uint32_t task_prio) -{ - //events = xEventGroupCreate(); - - init_lwip(); - -#if 0 - xTaskCreateAffinitySet(net_glue_thread, "NET_GLUE", configMINIMAL_STACK_SIZE, NULL, task_prio, 1, &task_net_glue); - if (task_net_glue == NULL) - { - picoprobe_error("net_glue_init: cannot create task_net_glue\n"); - } -#endif } // net_glue_init diff --git a/src/net/net_glue.h b/src/net/net_glue.h index d2e1fa87f..f3b7a0a76 100755 --- a/src/net/net_glue.h +++ b/src/net/net_glue.h @@ -35,7 +35,7 @@ #endif -void net_glue_init(uint32_t task_prio); +void net_glue_init(void); #ifdef __cplusplus From 677a890f67319eaeafd561b8957073bd5c58f612 Mon Sep 17 00:00:00 2001 From: Hardy Griech Date: Tue, 9 May 2023 16:19:56 +0200 Subject: [PATCH 035/118] cleaning up --- include/FreeRTOSConfig.h | 15 ++++++++---- include/lwipopts.h | 4 ++-- include/tusb_config.h | 2 +- src/main.c | 2 +- src/net/net_glue.c | 5 ++-- src/net/net_sysview.c | 50 +++++++++++----------------------------- 6 files changed, 30 insertions(+), 48 deletions(-) diff --git a/include/FreeRTOSConfig.h b/include/FreeRTOSConfig.h index fc4f87789..46a14366f 100644 --- a/include/FreeRTOSConfig.h +++ b/include/FreeRTOSConfig.h @@ -82,12 +82,12 @@ #define configAPPLICATION_ALLOCATED_HEAP 0 /* Hook function related definitions. */ -#define configCHECK_FOR_STACK_OVERFLOW 0 +#define configCHECK_FOR_STACK_OVERFLOW 1 #define configUSE_MALLOC_FAILED_HOOK 1 #define configUSE_DAEMON_TASK_STARTUP_HOOK 0 /* Run time and task stats gathering related definitions. */ -#define configUSE_TRACE_FACILITY 1 // switch on task status output +#define configUSE_TRACE_FACILITY 0 // switch on task status output #define configGENERATE_RUN_TIME_STATS configUSE_TRACE_FACILITY #define configUSE_STATS_FORMATTING_FUNCTIONS 0 @@ -118,10 +118,15 @@ */ /* SMP port only */ -#define configNUM_CORES 2 +#define configNUM_CORES 1 #define configTICK_CORE 1 #define configRUN_MULTIPLE_PRIORITIES 1 -#define configUSE_CORE_AFFINITY 1 +#if configNUM_CORES != 1 + #define configUSE_CORE_AFFINITY 1 +#endif +#if !defined(configUSE_CORE_AFFINITY) || configUSE_CORE_AFFINITY == 0 + #define xTaskCreateAffinitySet(FUN,NAM,STK,PAR,PRI,AFF,HND) xTaskCreate(FUN,NAM,STK,PAR,PRI,HND) +#endif /* RP2040 specific */ #define configSUPPORT_PICO_SYNC_INTEROP 1 @@ -140,7 +145,7 @@ to exclude the API function. */ #define INCLUDE_vTaskDelayUntil 0 #define INCLUDE_vTaskDelay 1 #define INCLUDE_xTaskGetSchedulerState 0 -#define INCLUDE_xTaskGetCurrentTaskHandle 0 +#define INCLUDE_xTaskGetCurrentTaskHandle 1 #define INCLUDE_uxTaskGetStackHighWaterMark 0 #define INCLUDE_xTaskGetIdleTaskHandle 0 #define INCLUDE_eTaskGetState 0 diff --git a/include/lwipopts.h b/include/lwipopts.h index 4b836e1f4..8baa2ff6b 100755 --- a/include/lwipopts.h +++ b/include/lwipopts.h @@ -81,8 +81,8 @@ //-------------------------------------- // for freertos mode -#define TCPIP_MBOX_SIZE 128 -#define TCPIP_THREAD_STACKSIZE 60000 +#define TCPIP_MBOX_SIZE 64 +#define TCPIP_THREAD_STACKSIZE 8192 #define TCPIP_THREAD_PRIO 11 diff --git a/include/tusb_config.h b/include/tusb_config.h index 032b820a9..90cb776f7 100644 --- a/include/tusb_config.h +++ b/include/tusb_config.h @@ -64,7 +64,7 @@ #define CFG_TUD_ENDPOINT0_SIZE 64 #endif -#define CFG_TUD_TASK_QUEUE_SZ 128 +#define CFG_TUD_TASK_QUEUE_SZ 64 //------------- CLASS -------------// diff --git a/src/main.c b/src/main.c index 3b7651885..431bffd77 100644 --- a/src/main.c +++ b/src/main.c @@ -613,7 +613,7 @@ int main(void) events = xEventGroupCreate(); // it seems that TinyUSB does not like affinity setting in its thread, so the affinity of the USB thread is corrected in the task itself - xTaskCreateAffinitySet(usb_thread, "TinyUSB Main", 8000, NULL, TUD_TASK_PRIO, -1, &tud_taskhandle); + xTaskCreateAffinitySet(usb_thread, "TinyUSB Main", 4096, NULL, TUD_TASK_PRIO, -1, &tud_taskhandle); vTaskStartScheduler(); return 0; diff --git a/src/net/net_glue.c b/src/net/net_glue.c index bbf6aa9e6..260a52bb9 100755 --- a/src/net/net_glue.c +++ b/src/net/net_glue.c @@ -112,7 +112,7 @@ static bool dns_query_proc(const char *name, ip4_addr_t *addr) void tud_network_init_cb(void) { /* if the network is re-initializing and we have a leftover packet, we must do a cleanup */ - if (received_frame) + if (received_frame != NULL) { pbuf_free(received_frame); received_frame = NULL; @@ -126,7 +126,8 @@ static void net_glue_usb_to_lwip(void *ptr) * handle any packet received by tud_network_recv_cb() in context of lwIP */ { - // printf("net_glue_usb_to_lwip\n"); + //printf("net_glue_usb_to_lwip\n"); + if (received_frame != NULL) { ethernet_input(received_frame, &netif_data); pbuf_free(received_frame); diff --git a/src/net/net_sysview.c b/src/net/net_sysview.c index 71ce3adf8..f2b7cd96f 100755 --- a/src/net/net_sysview.c +++ b/src/net/net_sysview.c @@ -92,7 +92,7 @@ void sysview_error(void *arg, err_t err) void sysview_close(struct tcp_pcb *tpcb) { - printf("sysview_close(%p): %d\n", tpcb, m_state); + //printf("sysview_close(%p): %d\n", tpcb, m_state); tcp_arg(tpcb, NULL); tcp_sent(tpcb, NULL); @@ -113,7 +113,7 @@ static void sysview_try_send(void *ctx) { block_call_back_message = false; - if (/* m_state == SVS_READY && */ !xStreamBufferIsEmpty(stream_sysview_to_host)) { + if ( !xStreamBufferIsEmpty(stream_sysview_to_host)) { size_t cnt; size_t max_cnt; uint8_t tx_buf[512]; @@ -125,41 +125,15 @@ static void sysview_try_send(void *ctx) max_cnt = MIN(sizeof(tx_buf), max_cnt); cnt = xStreamBufferReceive(stream_sysview_to_host, tx_buf, max_cnt, pdMS_TO_TICKS(10)); if (cnt != 0) { - if (xStreamBufferIsEmpty(stream_sysview_to_host)) - { - err = tcp_write(m_pcb_client, tx_buf, cnt, TCP_WRITE_FLAG_COPY); - if (err != ERR_OK) { - picoprobe_error("sysview_try_send/a: %d\n", err); - sysview_close(m_pcb_client); - } -#if 0 - err = tcp_output(m_pcb_client); - if (err != ERR_OK) { - picoprobe_error("sysview_try_send/b: %d\n", err); - sysview_close(m_pcb_client); - } -#endif + // the write has either 512 bytes (so send it) or the stream is empty (so send it as well) + err = tcp_write(m_pcb_client, tx_buf, cnt, TCP_WRITE_FLAG_COPY); + if (err != ERR_OK) { + picoprobe_error("sysview_try_send/a: %d\n", err); + sysview_close(m_pcb_client); } - else - { - err = tcp_write(m_pcb_client, tx_buf, cnt, TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE); - if (err != ERR_OK) { - picoprobe_error("sysview_try_send/c: %d\n", err); sysview_close(m_pcb_client); - } + if ( !xStreamBufferIsEmpty(stream_sysview_to_host)) { tcpip_callback_with_block(sysview_try_send, NULL, 0); } - m_xmt_cnt += cnt; - if (m_xmt_cnt > 1000) - { - m_xmt_cnt = 0; -#if 1 - err = tcp_output(m_pcb_client); - if (err != ERR_OK) { - picoprobe_error("sysview_try_send/d: %d\n", err); - sysview_close(m_pcb_client); - } -#endif - } } } } @@ -169,7 +143,7 @@ static void sysview_try_send(void *ctx) static err_t sysview_sent(void *arg, struct tcp_pcb *tpcb, uint16_t len) { - printf("sysview_sent(%p,%p,%d) %d\n", arg, tpcb, len, m_state); + //printf("sysview_sent(%p,%p,%d) %d\n", arg, tpcb, len, m_state); if (m_state == SVS_SEND_HELLO) { @@ -216,7 +190,7 @@ static err_t sysview_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t // // expecting hello message // - printf("sysview_recv, %d:'%s'\n", p->len, (const char *)p->payload); + // printf("sysview_recv, %d:'%s'\n", p->len, (const char *)p->payload); if (p->len != SYSVIEW_COMM_APP_HELLO_SIZE) { // invalid hello @@ -291,8 +265,10 @@ static err_t sysview_accept(void *arg, struct tcp_pcb *newpcb, err_t err) void net_sysview_send(const uint8_t *buf, uint32_t cnt) { +#if 0 if (m_state != SVS_NONE) printf("net_sysview_send(%p,%lu) %d\n", buf, cnt, m_state); +#endif if (m_state != SVS_READY) { @@ -309,7 +285,7 @@ void net_sysview_send(const uint8_t *buf, uint32_t cnt) block_call_back_message = true; err = tcpip_callback_with_block(sysview_try_send, NULL, 0); if (err != ERR_OK) { - printf("net_sysview_send: queue %d\n", err); + picoprobe_error("net_sysview_send: error %d\n", err); sysview_close(m_pcb_client); } } From e189c1f42445c5a6498505d4c341b63c59e06843 Mon Sep 17 00:00:00 2001 From: Hardy Griech Date: Tue, 9 May 2023 16:31:22 +0200 Subject: [PATCH 036/118] again with dual core --- include/FreeRTOSConfig.h | 2 +- src/main.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/FreeRTOSConfig.h b/include/FreeRTOSConfig.h index 46a14366f..a70347dff 100644 --- a/include/FreeRTOSConfig.h +++ b/include/FreeRTOSConfig.h @@ -118,7 +118,7 @@ */ /* SMP port only */ -#define configNUM_CORES 1 +#define configNUM_CORES 2 #define configTICK_CORE 1 #define configRUN_MULTIPLE_PRIORITIES 1 #if configNUM_CORES != 1 diff --git a/src/main.c b/src/main.c index 431bffd77..fb4deef6b 100644 --- a/src/main.c +++ b/src/main.c @@ -420,7 +420,7 @@ void print_task_stat(void *ptr) curr_tick_sum += task_status[n].ulRunTimeCounter; delta_tick_sum += task_status[n].ulRunTimeCounter - prev_tick[prev_ndx]; -#if defined(configUSE_CORE_AFFINITY) && configUSE_CORE_AFFINITY != 0 +#if 0 && defined(configUSE_CORE_AFFINITY) && configUSE_CORE_AFFINITY != 0 if (strcmp(task_status[n].pcTaskName, "IDLE1") != 0 && vTaskCoreAffinityGet(task_status[n].xHandle) != 1) { printf("!!!! change affinity of '%s' to 1\n", task_status[n].pcTaskName); vTaskCoreAffinitySet(task_status[n].xHandle, 1); @@ -493,7 +493,7 @@ void usb_thread(void *ptr) led_init(LED_TASK_PRIO); -#if defined(configUSE_CORE_AFFINITY) && configUSE_CORE_AFFINITY != 0 +#if 0 && defined(configUSE_CORE_AFFINITY) && configUSE_CORE_AFFINITY != 0 vTaskCoreAffinitySet(tud_taskhandle, 1); #endif From e12c42e5722ec69a31d4b7286ee18ba0baae62ba Mon Sep 17 00:00:00 2001 From: Hardy Griech Date: Tue, 9 May 2023 18:27:51 +0200 Subject: [PATCH 037/118] reworked downstream a little bit, but SysView to target disabled --- src/rtt_console.c | 116 +++++++++++++++++++++++++++++++++------------- 1 file changed, 84 insertions(+), 32 deletions(-) diff --git a/src/rtt_console.c b/src/rtt_console.c index b12d2c1f3..f30aa03f6 100755 --- a/src/rtt_console.c +++ b/src/rtt_console.c @@ -66,6 +66,8 @@ static const uint32_t segger_alignment = 4; static const uint8_t seggerRTT[16] = "SEGGER RTT\0\0\0\0\0\0"; static uint32_t prev_rtt_cb = 0; static bool rtt_console_running = false; +static bool ok_console_from_target = false; +static bool ok_console_to_target = false; static TaskHandle_t task_rtt_console = NULL; static StreamBufferHandle_t stream_rtt_console_to_target; // small stream for host->probe->target console communication @@ -76,6 +78,8 @@ static EventGroupHandle_t events; #undef RTT_POLL_INT_MS #define RTT_POLL_INT_MS 1 // faster polling static StreamBufferHandle_t stream_rtt_sysview_to_target; // small stream for host->probe->target sysview communication + static bool ok_sysview_from_target = false; + static bool ok_sysview_to_target = false; #endif @@ -159,7 +163,7 @@ static bool rtt_check_channel_from_target(uint32_t rtt_cb, uint16_t channel, SEG ok = ok && (aUp->SizeOfBuffer > 0 && aUp->SizeOfBuffer < TARGET_RAM_END - TARGET_RAM_START); ok = ok && ((uint32_t)aUp->pBuffer >= TARGET_RAM_START && (uint32_t)aUp->pBuffer + aUp->SizeOfBuffer <= TARGET_RAM_END); if (ok) { - printf("rtt_check_channel_from_target: %u %p %u %u %u\n", channel, aUp->pBuffer, aUp->SizeOfBuffer, aUp->RdOff, aUp->WrOff); + picoprobe_info("rtt_check_channel_from_target: %u %p %u %u %u\n", channel, aUp->pBuffer, aUp->SizeOfBuffer, aUp->RdOff, aUp->WrOff); } return ok; } // rtt_check_channel_from_target @@ -178,13 +182,35 @@ static bool rtt_check_channel_to_target(uint32_t rtt_cb, uint16_t channel, SEGGE ok = ok && (aDown->SizeOfBuffer > 0 && aDown->SizeOfBuffer < TARGET_RAM_END - TARGET_RAM_START); ok = ok && ((uint32_t)aDown->pBuffer >= TARGET_RAM_START && (uint32_t)aDown->pBuffer + aDown->SizeOfBuffer <= TARGET_RAM_END); if (ok) { - printf("rtt_check_channel_to_target: %u %p %u %u %u\n", channel, aDown->pBuffer, aDown->SizeOfBuffer, aDown->RdOff, aDown->WrOff); + picoprobe_info("rtt_check_channel_to_target: %u %p %u %u %u\n", channel, aDown->pBuffer, aDown->SizeOfBuffer, aDown->RdOff, aDown->WrOff); } return ok; } // rtt_check_channel_to_target +static unsigned rtt_get_write_space(SEGGER_RTT_BUFFER_DOWN *pRing) +/** + * Return the number of space left in the target buffer + */ +{ + unsigned rd_off; + unsigned wr_off; + unsigned r; + + rd_off = pRing->RdOff; + wr_off = pRing->WrOff; + if (rd_off <= wr_off) { + r = pRing->SizeOfBuffer - 1u - wr_off + rd_off; + } + else { + r = rd_off - wr_off - 1u; + } + return r; +} // rtt_get_write_space + + + static bool rtt_from_target(uint32_t rtt_cb, uint16_t channel, SEGGER_RTT_BUFFER_UP *aUp, rtt_data_to_host data_to_host, bool *worked) { @@ -231,36 +257,56 @@ static bool rtt_to_target(uint32_t rtt_cb, StreamBufferHandle_t stream, uint16_t { bool ok = true; uint8_t buf[16]; + unsigned num_bytes; if ( !xStreamBufferIsEmpty(stream)) { // // send data to target // ok = ok && swd_read_word(rtt_cb + offsetof(SEGGER_RTT_CB, aDown[channel].RdOff), (uint32_t *)&(aDown->RdOff)); - if ((aDown->WrOff + 1) % aDown->SizeOfBuffer != aDown->RdOff) { - // -> space left in RTT buffer on target - uint32_t cnt; - size_t r; - if (aDown->WrOff >= aDown->RdOff) { - cnt = aDown->SizeOfBuffer - aDown->WrOff; + num_bytes = rtt_get_write_space(aDown); + if (num_bytes > 0) { + //printf("a cnt: %u -> ", num_bytes); + + num_bytes = MIN(num_bytes, sizeof(buf)); + num_bytes = xStreamBufferReceive(stream, &buf, num_bytes, 0); + } + + if (num_bytes > 0) { + unsigned wr_off; + unsigned remaining; + + wr_off = aDown->WrOff; + remaining = aDown->SizeOfBuffer - wr_off; + + //printf("%u %u %u %u", channel, aDown->WrOff, num_bytes, remaining); + + if (remaining > num_bytes) { + // + // All data fits before wrap around + // + ok = ok && swd_write_memory((uint32_t)aDown->pBuffer + wr_off, buf, num_bytes); + aDown->WrOff = wr_off + num_bytes; } else { - cnt = (aDown->RdOff - aDown->WrOff) - 1; + // + // We reach the end of the buffer, so need to wrap around + // + unsigned num_bytes_at_once; + + num_bytes_at_once = remaining; + ok = ok && swd_write_memory((uint32_t)aDown->pBuffer + wr_off, buf, num_bytes_at_once); + num_bytes_at_once = num_bytes - remaining; + ok = ok && swd_write_memory((uint32_t)aDown->pBuffer, buf + remaining, num_bytes_at_once); + aDown->WrOff = num_bytes_at_once; } - cnt = MIN(cnt, sizeof(buf)); - printf("a cnt: %u %u %lu\n", channel, aDown->WrOff, cnt); - r = xStreamBufferReceive(stream, &buf, cnt, 0); - if (r > 0) { - printf("b addr: %u %lx %d\n", channel, (uint32_t)aDown->pBuffer + aDown->WrOff, r); - ok = ok && swd_write_memory((uint32_t)aDown->pBuffer + aDown->WrOff, buf, r); - aDown->WrOff = (aDown->WrOff + r) % aDown->SizeOfBuffer; - ok = ok && swd_write_word(rtt_cb + offsetof(SEGGER_RTT_CB, aDown[channel].WrOff), aDown->WrOff); + ok = ok && swd_write_word(rtt_cb + offsetof(SEGGER_RTT_CB, aDown[channel].WrOff), aDown->WrOff); - led_state(LS_UART_TX_DATA); - } + //printf(" -> %u\n", aDown->WrOff); } + *worked = true; } return ok; @@ -268,19 +314,19 @@ static bool rtt_to_target(uint32_t rtt_cb, StreamBufferHandle_t stream, uint16_t -static void do_rtt_console(uint32_t rtt_cb) +static void do_rtt_io(uint32_t rtt_cb) { #if OPT_TARGET_UART SEGGER_RTT_BUFFER_UP aUpConsole; // Up buffer, transferring information up from target via debug probe to host SEGGER_RTT_BUFFER_DOWN aDownConsole; // Down buffer, transferring information from host via debug probe to target - bool ok_console_from_target = false; - bool ok_console_to_target = false; + ok_console_from_target = false; + ok_console_to_target = false; #endif #if OPT_NET_SYSVIEW_SERVER SEGGER_RTT_BUFFER_UP aUpSysView; // Up buffer, transferring information up from target via debug probe to host SEGGER_RTT_BUFFER_DOWN aDownSysView; // Down buffer, transferring information from host via debug probe to target - bool ok_sysview_from_target = false; - bool ok_sysview_to_target = false; + ok_sysview_from_target = false; + ok_sysview_to_target = false; #endif bool ok = true; @@ -339,7 +385,7 @@ static void do_rtt_console(uint32_t rtt_cb) } } rtt_console_running = false; -} // do_rtt_console +} // do_rtt_io @@ -369,7 +415,7 @@ static void target_disconnect(void) -void rtt_console_thread(void *ptr) +void rtt_io_thread(void *ptr) { uint32_t rtt_cb; bool target_online = false; @@ -416,7 +462,7 @@ void rtt_console_thread(void *ptr) rtt_cb = search_for_rtt_cb(); if (rtt_cb != 0) { led_state(LS_RTT_CB_FOUND); - do_rtt_console(rtt_cb); + do_rtt_io(rtt_cb); } target_disconnect(); @@ -425,13 +471,13 @@ void rtt_console_thread(void *ptr) sw_unlock("RTT"); vTaskDelay(pdMS_TO_TICKS(300)); // give the other task the opportunity to catch sw_lock(); } -} // rtt_console_thread +} // rtt_io_thread bool rtt_console_cb_exists(void) { - return rtt_console_running; + return rtt_console_running && ok_console_to_target; } // rtt_console_cb_exists @@ -468,9 +514,15 @@ void rtt_console_send_byte(uint8_t ch) #if OPT_NET_SYSVIEW_SERVER void rtt_sysview_send_byte(uint8_t ch) +/** + * Send a byte to the SysView channel of the target + * + * TODO currently this is disabled because this aborts SysView operation. Has to be investigated. + */ { - // TODO der muss noch auf NULL checken! - //rtt_send_byte(stream_rtt_sysview_to_target, RTT_CHANNEL_SYSVIEW, ch, true); +#if 0 + rtt_send_byte(stream_rtt_sysview_to_target, RTT_CHANNEL_SYSVIEW, ch, true); +#endif } // rtt_sysview_send_byte #endif @@ -494,7 +546,7 @@ void rtt_console_init(uint32_t task_prio) } #endif - xTaskCreateAffinitySet(rtt_console_thread, "RTT", configMINIMAL_STACK_SIZE, NULL, task_prio, 1, &task_rtt_console); + xTaskCreateAffinitySet(rtt_io_thread, "RTT", configMINIMAL_STACK_SIZE, NULL, task_prio, 1, &task_rtt_console); if (task_rtt_console == NULL) { picoprobe_error("rtt_console_init: cannot create task_rtt_console\n"); From 5752b129596e484b638fabb070ef47a4531ad37a Mon Sep 17 00:00:00 2001 From: Hardy Griech Date: Wed, 10 May 2023 22:44:56 +0200 Subject: [PATCH 038/118] lot of minor(?) changes - removed DNS support - docu updates - performance tuning - option for the subnet - RTT: check for channels if "idle" - do not use RNDIS --- CMakeLists.txt | 19 +++++---------- README.adoc | 45 ++++++++++++++++++++++++++--------- doc/lwIP-notes.adoc | 55 +++++++++++++++++++++++++++++++++++++++++++ include/lwipopts.h | 8 +++---- src/net/net_glue.c | 44 +++++++--------------------------- src/rtt_console.c | 31 +++++++++++++----------- src/usb_descriptors.c | 3 ++- 7 files changed, 127 insertions(+), 78 deletions(-) create mode 100755 doc/lwIP-notes.adoc diff --git a/CMakeLists.txt b/CMakeLists.txt index 22fb8df34..5d840316e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,10 +29,10 @@ option(OPT_CMSIS_DAPV2 "Enable CMSIS-DAPv2" 1) option(OPT_TARGET_UART "Enable CDC for target UART I/O" 1) option(OPT_PROBE_DEBUG_OUT "Enable CDC for probe debug output" ${DEFAULT_OPT_PROBE_DEBUG_OUT}) option(OPT_SIGROK "Enable sigrok" 0) -option(OPT_MSC "Enable Mass Storage Device" 1) +option(OPT_MSC "Enable Mass Storage Device" 0) option(OPT_MSC_RAM_UF2 "Enable file 'RAM.UF2' on Mass Storage" 1) option(OPT_NET "Enable lwIP on the Pico" 1) -option(OPT_NET_DNS "Enable DNS on the Pico" 0) # all DNS is going over the Pico!? +set(OPT_NET_192_168 10 CACHE STRING "Set the subnet of 192.168.x") option(OPT_NET_ECHO_SERVER "Enable echo server for testing" 1) option(OPT_NET_IPERF_SERVER "Enable iperf server for tuning" 1) option(OPT_NET_SYSVIEW_SERVER "Enable SysView over TCPIP" 1) @@ -54,6 +54,9 @@ include(FreeRTOS_Kernel_import.cmake) set(PICO_BOARD_HEADER_DIRS ${CMAKE_CURRENT_LIST_DIR}/include/boards) pico_sdk_init() +# message("--------- " ${PICO_LWIP_PATH}) +# message("--------- " ${PICO_LWIP_CONTRIB_PATH}) +# message("--------- " ${PICO_TINYUSB_PATH}) project(${PROJECT}) @@ -220,6 +223,7 @@ endif() # if(OPT_NET) add_compile_definitions(OPT_NET=1) + add_compile_definitions(OPT_NET_192_168=${OPT_NET_192_168}) target_sources(${PROJECT} PRIVATE src/net/net_glue.c @@ -236,13 +240,6 @@ if(OPT_NET) pico_lwip_freertos ) - if(OPT_NET_DNS) - add_compile_definitions(OPT_NET_DNS=1) - target_sources(${PROJECT} PRIVATE - ${PICO_TINYUSB_PATH}/lib/networking/dnserver.c - ) - endif() - if(OPT_NET_SYSVIEW_SERVER) add_compile_definitions(OPT_NET_SYSVIEW_SERVER=1) target_sources(${PROJECT} PRIVATE @@ -263,10 +260,6 @@ if(OPT_NET) ${PICO_LWIP_PATH}/src/apps/lwiperf/lwiperf.c ) endif() - -# message("--------- " ${PICO_LWIP_PATH}) -# message("--------- " ${PICO_LWIP_CONTRIB_PATH}) -# message("--------- " ${PICO_TINYUSB_PATH}) endif() #-------------------------------------------------------------------------------------------------- diff --git a/README.adoc b/README.adoc index 26c21d402..4da9b25f8 100644 --- a/README.adoc +++ b/README.adoc @@ -32,8 +32,9 @@ Finally there is **Y**et **A**nother **Picoprobe** around, the YAPicoprobe. ** UART connection between target and probe is redirected ** RTT terminal channel is automatically redirected into this CDC (if there is no CMSIS-DAPv2/MSC connection) -* CDC - virtual com port for logging of the probe -* CDC sigrok probe - data collection on eight digital and three analog channels +* https://www.segger.com/products/development-tools/systemview/[SystemView] support over TCP/IP +* CDC - virtual com port for (debug) logging of the probe +* optional CDC sigrok probe - data collection on eight digital and three analog channels (logic analyzer and oscilloscope) with auto-trigger capability * LED for state indication * Other Benefits @@ -148,7 +149,7 @@ Unfortunately DAP converts internally the frequency into delays which are always That means that actual clock speeds are `125MHz / (2*n)`, `n>=3` -> 20833kHz, 12500kHz, 10417kHz, ... Normally the requested frequency is rounded down according to the possible values from above. But if the specified frequency -is completely out of range, the allowed maximum SWD frequency of the RP2040 is used, which is 24MHz. +is completely out of range, the allowed maximum target SWD frequency is used, e.g. for the RP2040 24MHz. Actually usable frequency depends on cabling and the DAP speed. If the DAP cannot access memory with speed determined by the host, it responds with WAIT and the host needs to retry. @@ -194,17 +195,16 @@ Because CMSIS-DAP access should be generic, flashing of other SWD compatible dev ### RTT - Real Time Transfer https://www.segger.com/products/debug-probes/j-link/technology/about-real-time-transfer/[RTT] -allows transfer from the target to the host in "realtime". YAPicoprobe currently reads -channel 0 of the targets RTT and sends it into the CDC of the target. Effectively this -allows RTT debug output into a terminal. +allows transfer from the target to the host in "realtime" via the SWD interface. -If an RTT control block has been detected, characters received via the target CDC are transmitted -with RTT to the target. +The RTT control block on the target is automatically detected. Currently channels 0 and 1 are supported. + +To get the RTT channels running, code on the target has to be either instrumented or adopted. [NOTE] ==== * only the devices RAM is scanned for an RTT control block, for unknown devices - RAM in the range 0x20000000-0x2003ffff is assumed + RAM the range 0x20000000-0x2003ffff is assumed * don't be too overwhelmed about Seggers numbers in the above mentioned document. The data must still be transferred which is not taken into account in the diagram @@ -216,11 +216,32 @@ with RTT to the target. ==== +#### Terminal I/O + +RTT channel 0 is used for bidirectional console communication. This channel is directed into the UART CDC +of the target device. + + +#### SystemView + +RTT channel 1 is used for communication with Seggers https://www.segger.com/products/development-tools/systemview/[SystemView]. +YAPicoprobe provides the data over TCP/IP at port 19111 which is the default for SystemViews communication. +Default IP address of the probe (if not built otherwise) is 192.168.10.1. + + +[NOTE] +==== +SystemView communication via TCP/IP had been chosen to spare you from another CDC port and also +because SystemView over COM port works on my Linux device just until v3.30 (Segger promises +a fix for > 3.50a, nevertheless TCP/IP is used...) +==== + + ### Sigrok - Data Collection [IMPORTANT] ==== -Sigrok is disabled on the Pico Debug Probe. +Sigrok is no longer compiled per default into the probe firmware. If you want sigrok support, +the <> have to be checked. ==== The probe allows data collection for a https://sigrok.org/[sigrok] compatible @@ -432,7 +453,7 @@ rtt.println("sub module"); ## Internals -### Building from Source +### Building from Source [[how-to-build]] Building from source is done with the help of a stub Makefile which eases integration into Eclipse (but can be used from command line as well). The Makefile creates via cmake a `build.ninja` which is responsible for @@ -441,6 +462,8 @@ the actual build process. To build the project, there must be somewhere a recent https://github.com/raspberrypi/pico-sdk[Pico SDK] and the environment variable `PICO_SDK_PATH` must point to it. +If you want to adopt YAPicoprobe options to your needs, check CMakeLists.txt and invoke cmake accordingly. + Requirements: * arm-none-eabi-gcc diff --git a/doc/lwIP-notes.adoc b/doc/lwIP-notes.adoc new file mode 100755 index 000000000..7701d7723 --- /dev/null +++ b/doc/lwIP-notes.adoc @@ -0,0 +1,55 @@ +:imagesdir: png +:source-highlighter: rouge +:toc: +:toclevels: 5 + + + + +## Some lwIP Notes + +lwIP is used for creation of a network interface of YAPicoprobe to avoid +an uncountable number of additional CDC com ports. + +Currently just a Segger SysView server is listening on port 19111. +But I guess there is more to come. + +lwIP had some traps waiting for me. Despite reading the official +https://www.nongnu.org/lwip/2_1_x/pitfalls.html[Common Pitfalls] +I took some of them. + +MAC:: Do not use a random MAC! At least not for the first byte. + I was "lucky" choosing one with an odd first byte. Unfortunately + bit 0 marks a group address. At least Linux rejects such MAC + addresses with a more or less useless error message in the syslog. + Took a while until I found out that the MAC address was the culprit + for no communication. + + Finally I have used 0xfe as the first byte and the remaining five + bytes of the MAC address are copied from the last bytes of Picos serial number + (which actually is the serial number of the external flash). + +OS Mode:: *really* take it serious what they are writing about "raw" APIs + and only using the TCPIP thread for any calls to it. + + Use `tcpip_callback_with_block(, , 0)` for + non-blocking invocations of some function. This also saves you + from creating extra simple threads for communication tasks line + in the TineUSB/lwIP glue code. That was my first idea and it took + a while until I found out how bad that idea was. + + Same was true for the thread(!) which stuffed data for SysView into + it's server: bad idea! + + Effect of wrong API handling were random crashes or connection + disruptions. + +RNDIS/ECM/NCM:: + * *RNDIS*: this was my former favorite, because it is supported by all + relevant OSs. Also throughput seemed to be good. + Unfortunately RNDIS seems to manipulate routing in a way that the + default route on my Linux wants to go through the probe. Not + really what I want... + * *NCM*: is said to be the best choice. I did not manage to get an + acceptable throughput. Transfer seems to get stuck from time to time + and SystemView aborts. So also not the favorite. + * *ECM*: works good, packets are transferred continuously, throughput + also seems to be ok. So this is the way to go. + + Unfortunately there is no driver integrated into Win10, so possible + extra trouble appears. + diff --git a/include/lwipopts.h b/include/lwipopts.h index 8baa2ff6b..beb88f269 100755 --- a/include/lwipopts.h +++ b/include/lwipopts.h @@ -65,15 +65,15 @@ //-------------------------------------- -// performance tuning +// performance tuning (do not change without extensive testing, optimized for ECM) #define TCP_MSS (1500 - 20 - 20) // MTU minus header sizes (best value til now) -//#define TCP_SND_BUF (2 * TCP_MSS) -//#define TCP_OVERSIZE TCP_MSS +#define TCP_SND_BUF (4 * TCP_MSS) // good tuning +//#define TCP_OVERSIZE (TCP_MSS / 4) // til now no good value found //-------------------------------------- // memory -#define MEM_SIZE 10000 +#define MEM_SIZE 20000 //#define MEM_LIBC_MALLOC 1 //#define MEMP_MEM_MALLOC 1 //#define LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT 1 diff --git a/src/net/net_glue.c b/src/net/net_glue.c index 260a52bb9..c94c1fe36 100755 --- a/src/net/net_glue.c +++ b/src/net/net_glue.c @@ -44,9 +44,6 @@ #include "lwip/tcpip.h" #include "dhserver.h" -#if OPT_NET_DNS - #include "dnserver.h" -#endif #include "tusb.h" @@ -60,8 +57,12 @@ static struct netif netif_data; /* shared between tud_network_recv_cb() and service_traffic() */ static struct pbuf *received_frame; +#ifndef OPT_NET_192_168 + #define OPT_NET_192_168 10 +#endif + /* network parameters of this MCU */ -static const ip4_addr_t ipaddr = IPADDR4_INIT_BYTES(192, 168, 10, 1); +static const ip4_addr_t ipaddr = IPADDR4_INIT_BYTES(192, 168, OPT_NET_192_168, 1); static const ip4_addr_t netmask = IPADDR4_INIT_BYTES(255, 255, 255, 0); static const ip4_addr_t gateway = IPADDR4_INIT_BYTES(0, 0, 0, 0); @@ -69,46 +70,23 @@ static const ip4_addr_t gateway = IPADDR4_INIT_BYTES(0, 0, 0, 0); static dhcp_entry_t entries[] = { /* mac ip address lease time */ - { {0}, IPADDR4_INIT_BYTES(192, 168, 10, 2), 24 * 60 * 60 }, - { {0}, IPADDR4_INIT_BYTES(192, 168, 10, 3), 24 * 60 * 60 }, - { {0}, IPADDR4_INIT_BYTES(192, 168, 10, 4), 24 * 60 * 60 }, + { {0}, IPADDR4_INIT_BYTES(192, 168, OPT_NET_192_168, 2), 24 * 60 * 60 }, + { {0}, IPADDR4_INIT_BYTES(192, 168, OPT_NET_192_168, 3), 24 * 60 * 60 }, + { {0}, IPADDR4_INIT_BYTES(192, 168, OPT_NET_192_168, 4), 24 * 60 * 60 }, }; static const dhcp_config_t dhcp_config = { .router = IPADDR4_INIT_BYTES(0, 0, 0, 0), /* router address (if any) */ .port = 67, /* listen port */ -#if OPT_NET_DNS - .dns = IPADDR4_INIT_BYTES(192, 168, 10, 1),/* dns server (if any) */ -#else .dns = IPADDR4_INIT_BYTES(0, 0, 0, 0), -#endif - "usb", /* dns suffix */ + "", /* dns suffix */ TU_ARRAY_SIZE(entries), /* num entry */ entries /* entries */ }; -#if OPT_NET_DNS -static bool dns_query_proc(const char *name, ip4_addr_t *addr) -/** - * Handle any DNS requests from dns-server - * If enabled all DNS requests seem to go over the Pico!? - */ -{ - printf("dns_query_proc(%s,.)\n", name); - - if (0 == strcmp(name, "tiny.usb")) { - *addr = ipaddr; - return true; - } - return false; -} // dns_query_proc -#endif - - - void tud_network_init_cb(void) { /* if the network is re-initializing and we have a leftover packet, we must do a cleanup */ @@ -272,8 +250,4 @@ void net_glue_init(void) while (dhserv_init(&dhcp_config) != ERR_OK) ; -#if OPT_NET_DNS - while (dnserv_init(IP_ADDR_ANY, 53, dns_query_proc) != ERR_OK) - ; -#endif } // net_glue_init diff --git a/src/rtt_console.c b/src/rtt_console.c index f30aa03f6..bb3cadc4a 100755 --- a/src/rtt_console.c +++ b/src/rtt_console.c @@ -339,20 +339,9 @@ static void do_rtt_io(uint32_t rtt_cb) // do operations rtt_console_running = true; while (ok && !sw_unlock_requested()) { - bool worked = false; + bool worked; - #if OPT_TARGET_UART - if ( !ok_console_from_target) - ok_console_from_target = rtt_check_channel_from_target(rtt_cb, RTT_CHANNEL_CONSOLE, &aUpConsole); - if ( !ok_console_to_target) - ok_console_to_target = rtt_check_channel_to_target(rtt_cb, RTT_CHANNEL_CONSOLE, &aDownConsole); - #endif - #if OPT_NET_SYSVIEW_SERVER - if ( !ok_sysview_from_target) - ok_sysview_from_target = rtt_check_channel_from_target(rtt_cb, RTT_CHANNEL_SYSVIEW, &aUpSysView); - if ( !ok_sysview_to_target) - ok_sysview_to_target = rtt_check_channel_to_target(rtt_cb, RTT_CHANNEL_SYSVIEW, &aDownSysView); - #endif + worked = false; // // transfer RTT from target to host @@ -380,7 +369,21 @@ static void do_rtt_io(uint32_t rtt_cb) if ( !worked) { - // -> did nothing in the previous run -> delay + // did nothing -> check if RTT channels appeared + #if OPT_TARGET_UART + if ( !ok_console_from_target) + ok_console_from_target = rtt_check_channel_from_target(rtt_cb, RTT_CHANNEL_CONSOLE, &aUpConsole); + if ( !ok_console_to_target) + ok_console_to_target = rtt_check_channel_to_target(rtt_cb, RTT_CHANNEL_CONSOLE, &aDownConsole); + #endif + #if OPT_NET_SYSVIEW_SERVER + if ( !ok_sysview_from_target) + ok_sysview_from_target = rtt_check_channel_from_target(rtt_cb, RTT_CHANNEL_SYSVIEW, &aUpSysView); + if ( !ok_sysview_to_target) + ok_sysview_to_target = rtt_check_channel_to_target(rtt_cb, RTT_CHANNEL_SYSVIEW, &aDownSysView); + #endif + + // -> delay xEventGroupWaitBits(events, EV_RTT_TO_TARGET, pdTRUE, pdFALSE, pdMS_TO_TICKS(RTT_POLL_INT_MS)); } } diff --git a/src/usb_descriptors.c b/src/usb_descriptors.c index ebcc5c9d1..69c185544 100644 --- a/src/usb_descriptors.c +++ b/src/usb_descriptors.c @@ -35,7 +35,8 @@ //--------------------------------------------------------------------+ // 0 -> ECM, OPT_NET must be enabled -#define USE_RNDIS 1 +// ECM is preferred because RNDIS changes DNS setup on Linux and also will likely be thrown out of the kernel +#define USE_RNDIS 0 enum { From 80744a4b6a26e9dfe8864cf978ded7f99874f69f Mon Sep 17 00:00:00 2001 From: Hardy Griech Date: Fri, 12 May 2023 13:55:37 +0200 Subject: [PATCH 039/118] lot of minor things - net: configuration documentation - net: really no DNS setup (hopefully) - fine tuning of option handling plus new OPT_SPECIAL_CLK_FOR_PIO --- CMakeLists.txt | 28 ++++++++++---------- README.adoc | 50 ++++++++++++++++++++++++++++++------ doc/lwIP-notes.adoc | 21 +++++++++++++-- include/lwipopts.h | 48 +++++++++++++++++----------------- include/picoprobe_config.h | 10 ++++---- src/net/net_glue.c | 20 +++++---------- src/pico-sigrok/sigrok.c | 2 +- src/pico-sigrok/sigrok_int.h | 2 +- src/probe.c | 5 +--- src/usb_descriptors.c | 21 +++++++-------- 10 files changed, 126 insertions(+), 81 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5d840316e..5bdcb66c7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,21 +21,22 @@ endif() if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug") set(DEFAULT_OPT_PROBE_DEBUG_OUT 1) else() - set(DEFAULT_OPT_PROBE_DEBUG_OUT 0) + set(DEFAULT_OPT_PROBE_DEBUG_OUT 1) endif() -option(OPT_CMSIS_DAPV1 "Enable CMSIS-DAPv1" 1) -option(OPT_CMSIS_DAPV2 "Enable CMSIS-DAPv2" 1) -option(OPT_TARGET_UART "Enable CDC for target UART I/O" 1) -option(OPT_PROBE_DEBUG_OUT "Enable CDC for probe debug output" ${DEFAULT_OPT_PROBE_DEBUG_OUT}) -option(OPT_SIGROK "Enable sigrok" 0) -option(OPT_MSC "Enable Mass Storage Device" 0) -option(OPT_MSC_RAM_UF2 "Enable file 'RAM.UF2' on Mass Storage" 1) -option(OPT_NET "Enable lwIP on the Pico" 1) -set(OPT_NET_192_168 10 CACHE STRING "Set the subnet of 192.168.x") -option(OPT_NET_ECHO_SERVER "Enable echo server for testing" 1) -option(OPT_NET_IPERF_SERVER "Enable iperf server for tuning" 1) -option(OPT_NET_SYSVIEW_SERVER "Enable SysView over TCPIP" 1) +option(OPT_CMSIS_DAPV1 "Enable CMSIS-DAPv1" 1) +option(OPT_CMSIS_DAPV2 "Enable CMSIS-DAPv2" 1) +option(OPT_TARGET_UART "Enable CDC for target UART I/O" 1) +option(OPT_PROBE_DEBUG_OUT "Enable CDC for probe debug output" ${DEFAULT_OPT_PROBE_DEBUG_OUT}) +option(OPT_SIGROK "Enable sigrok" 0) +option(OPT_MSC "Enable Mass Storage Device" 1) +option(OPT_MSC_RAM_UF2 "Enable file 'RAM.UF2' on Mass Storage" 1) +option(OPT_NET "Enable lwIP on the Pico" 1) +set(OPT_NET_192_168 14 CACHE STRING "Set the subnet of 192.168.x") +option(OPT_NET_ECHO_SERVER "Enable echo server for testing" 1) +option(OPT_NET_IPERF_SERVER "Enable iperf server for tuning" 1) +option(OPT_NET_SYSVIEW_SERVER "Enable SysView over TCPIP" 1) +option(OPT_SPECIAL_CLK_FOR_PIO "Ignore clock frequency request of 1MHz (this is for PlatformIO tuning)" 0) # @@ -70,6 +71,7 @@ add_definitions( -DPICO_HEAP_SIZE=0x0 -DPICO_STACK_SIZE=0x400 -DTARGET_BOARD_${PICO_BOARD_UPPER} + -DOPT_SPECIAL_CLK_FOR_PIO=${OPT_SPECIAL_CLK_FOR_PIO} ) # diff --git a/README.adoc b/README.adoc index 4da9b25f8..b19c6675d 100644 --- a/README.adoc +++ b/README.adoc @@ -32,7 +32,7 @@ Finally there is **Y**et **A**nother **Picoprobe** around, the YAPicoprobe. ** UART connection between target and probe is redirected ** RTT terminal channel is automatically redirected into this CDC (if there is no CMSIS-DAPv2/MSC connection) -* https://www.segger.com/products/development-tools/systemview/[SystemView] support over TCP/IP +* https://www.segger.com/products/development-tools/systemview/[SystemView] support over TCP/IP (ECM/NCM/RNDIS) * CDC - virtual com port for (debug) logging of the probe * optional CDC sigrok probe - data collection on eight digital and three analog channels (logic analyzer and oscilloscope) with auto-trigger capability @@ -225,8 +225,8 @@ of the target device. #### SystemView RTT channel 1 is used for communication with Seggers https://www.segger.com/products/development-tools/systemview/[SystemView]. -YAPicoprobe provides the data over TCP/IP at port 19111 which is the default for SystemViews communication. -Default IP address of the probe (if not built otherwise) is 192.168.10.1. + +YAPicoprobe provides the data over TCP at port 19111 which is the default for SystemView communication. +Default IP address of the probe (if not built otherwise) is 192.168.14.1. [NOTE] ==== @@ -353,9 +353,9 @@ The Pico Debug Probe has four additional LEDs. Assignment is as follows: ==== -### Configuration +## Configuration -#### udev rules for MSC and CMSIS-DAP +### udev rules for MSC and CMSIS-DAP Under Linux one wants to use the following udev rules for convenience. @@ -379,7 +379,29 @@ ACTION=="add", SUBSYSTEMS=="usb", SUBSYSTEM=="block", ENV{ID_FS_USAGE}=="filesys ACTION=="remove", SUBSYSTEMS=="usb", SUBSYSTEM=="block", ENV{ID_FS_USAGE}=="filesystem", ATTRS{idVendor}=="2e8a", ATTRS{idProduct}=="0003", RUN+="/usr/bin/logger --tag rpi-pico-mount Unmounting what seems to be a Raspberry Pi Pico", RUN+="/usr/bin/systemd-umount /media/pico" ---- -#### PlatformIO [[platformio]] +### Network Configuration + +SystemView connectivity over TCP/IP is on most systems not configuration free. On Debian the configuration +is as follows: + +* after connecting the probe with the host, `ip a` shows its network interface, e.g. `enxfe`. + If the network interface already shows an IP address everything is fine and you are ready +* if not, then you can get the IP address with `sudo dhclient enxfe` +* to make the permanent add the following lines to `/etc/network/interfaces`: + +[source] +---- +allow-hotplug enxfe +iface enxfe inet dhcp +---- + +On my system this unfortunately leads to error messages (which are harmless) if the probe is not connected. + +The default address of the probe is 192.168.14.1. If there is a collision with the current setup of the +host, the probe firmware has to be rebuilt with `-DOPT_NET_192_168=`. + + +### PlatformIO [[platformio]] https://platformio.org/[PlatformIO] configuration in `platformio.ini` is pretty straight forward: .PlatformIO configuration @@ -410,12 +432,12 @@ upload_command = cp .pio/build/pico_cp/firmware.uf2 /media/picoprobe I'm sure there are smarter ways to specify the image path. -There is also a special PlatformIO handling in the probe: it ignores the defensive 1MHz clock setting which is used by +Optional: there is also a special PlatformIO handling in the probe: it ignores the defensive 1MHz clock setting which is used by the above contained OpenOCD. Standard clock is thus 15MHz. If this is too fast, set the frequency with `pyocd reset -f 1100000 -t rp2040` or similar. If this is too slow, use `pyocd reset -f 50000000 -t rp2040`. -##### RTT +#### RTT To use RTT for debug/console output the following has to be done: * in `platformio.ini`: @@ -505,6 +527,18 @@ make all make create-images ---- +.Bare call of cmake +[source,bash] +---- +mkdir _build; cd _build +cmake .. -D