blackmagic on wifi interface and dap on usb

This commit is contained in:
SG 2022-12-02 20:25:04 +03:00
parent 869c360fd0
commit 5e2807371c
18 changed files with 427 additions and 158 deletions

3
.gitmodules vendored
View File

@ -7,3 +7,6 @@
[submodule "components/tinyusb/tinyusb"]
path = components/tinyusb/tinyusb
url = https://github.com/hathach/tinyusb
[submodule "components/dap-link/free-dap"]
path = components/dap-link/free-dap
url = https://github.com/ataradov/free-dap

View File

@ -24,7 +24,7 @@ bool network_gdb_connected(void);
void network_gdb_send(uint8_t* buffer, size_t size);
/* USB-CDC */
void usb_cdc_gdb_tx_char(uint8_t c, bool flush);
void usb_gdb_tx_char(uint8_t c, bool flush);
size_t gdb_glue_get_free_size(void) {
return xStreamBufferSpacesAvailable(gdb_glue.rx_stream);
@ -94,6 +94,6 @@ void gdb_if_putchar(unsigned char c, int flush) {
}
} else {
// Not sure why, but I could not get it to work with buffer
usb_cdc_gdb_tx_char(c, flush);
usb_gdb_tx_char(c, flush);
}
}

View File

@ -0,0 +1,3 @@
idf_component_register(SRCS "free-dap/dap.c"
PRIV_INCLUDE_DIRS "."
INCLUDE_DIRS "." "free-dap")

View File

@ -0,0 +1,191 @@
#pragma once
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2022, Alex Taradov <alex@taradov.com>. All rights reserved.
/*- Includes ----------------------------------------------------------------*/
#include <stdint.h>
#include <driver/gpio.h>
#include <rom/ets_sys.h>
#include <hal/gpio_ll.h>
#include <esp_rom_gpio.h>
/*- Definitions -------------------------------------------------------------*/
// #define DAP_CONFIG_ENABLE_JTAG
#define DAP_CONFIG_DEFAULT_PORT DAP_PORT_SWD
#define DAP_CONFIG_DEFAULT_CLOCK 8000000 // Hz
#define DAP_CONFIG_PACKET_SIZE 64
#define DAP_CONFIG_PACKET_COUNT 1
#define DAP_CONFIG_JTAG_DEV_COUNT 8
// DAP_CONFIG_PRODUCT_STR must contain "CMSIS-DAP" to be compatible with the standard
#define DAP_CONFIG_VENDOR_STR "Flipper Devices"
#define DAP_CONFIG_PRODUCT_STR "Generic CMSIS-DAP Adapter"
#define DAP_CONFIG_SER_NUM_STR "1234567890"
#define DAP_CONFIG_CMSIS_DAP_VER_STR "2.0.0"
// Attribute to use for performance-critical functions
#define DAP_CONFIG_PERFORMANCE_ATTR IRAM_ATTR
// A value at which dap_clock_test() produces 1 kHz output on the SWCLK pin
#define DAP_CONFIG_DELAY_CONSTANT 24000
// A threshold for switching to fast clock (no added delays)
// This is the frequency produced by dap_clock_test(1) on the SWCLK pin
#define DAP_CONFIG_FAST_CLOCK 8000000 // Hz
#define ESP_SWCLK_PIN (1)
#define ESP_SWDIO_PIN (2)
/*- Prototypes --------------------------------------------------------------*/
/*- Implementations ---------------------------------------------------------*/
//-----------------------------------------------------------------------------
static inline void DAP_CONFIG_SWCLK_TCK_write(int value) {
if(value) {
GPIO.out_w1ts = (1 << ESP_SWCLK_PIN);
} else {
GPIO.out_w1tc = (1 << ESP_SWCLK_PIN);
}
}
//-----------------------------------------------------------------------------
static inline void DAP_CONFIG_SWDIO_TMS_write(int value) {
if(value) {
GPIO.out_w1ts = (1 << ESP_SWDIO_PIN);
} else {
GPIO.out_w1tc = (1 << ESP_SWDIO_PIN);
}
}
//-----------------------------------------------------------------------------
static inline void DAP_CONFIG_TDI_write(int value) {
// Do nothing
}
//-----------------------------------------------------------------------------
static inline void DAP_CONFIG_TDO_write(int value) {
// Do nothing
}
//-----------------------------------------------------------------------------
static inline void DAP_CONFIG_nTRST_write(int value) {
// Do nothing
}
//-----------------------------------------------------------------------------
static inline void DAP_CONFIG_nRESET_write(int value) {
// Do nothing
}
//-----------------------------------------------------------------------------
static inline int DAP_CONFIG_SWCLK_TCK_read(void) {
int level = (GPIO.in >> ESP_SWCLK_PIN) & 0x1;
return level;
}
//-----------------------------------------------------------------------------
static inline int DAP_CONFIG_SWDIO_TMS_read(void) {
int level = (GPIO.in >> ESP_SWDIO_PIN) & 0x1;
return level;
}
//-----------------------------------------------------------------------------
static inline int DAP_CONFIG_TDO_read(void) {
// Do nothing
return 0;
}
//-----------------------------------------------------------------------------
static inline int DAP_CONFIG_TDI_read(void) {
// Do nothing
return 0;
}
//-----------------------------------------------------------------------------
static inline int DAP_CONFIG_nTRST_read(void) {
// Do nothing
return 0;
}
//-----------------------------------------------------------------------------
static inline int DAP_CONFIG_nRESET_read(void) {
// Do nothing
return 0;
}
//-----------------------------------------------------------------------------
static inline void DAP_CONFIG_SWCLK_TCK_set(void) {
GPIO.out_w1ts = (1 << ESP_SWCLK_PIN);
}
//-----------------------------------------------------------------------------
static inline void DAP_CONFIG_SWCLK_TCK_clr(void) {
GPIO.out_w1tc = (1 << ESP_SWCLK_PIN);
}
//-----------------------------------------------------------------------------
static inline void DAP_CONFIG_SWDIO_TMS_in(void) {
gpio_ll_output_disable(&GPIO, ESP_SWDIO_PIN);
gpio_ll_input_enable(&GPIO, ESP_SWDIO_PIN);
}
//-----------------------------------------------------------------------------
static inline void DAP_CONFIG_SWDIO_TMS_out(void) {
GPIO.enable_w1ts = (0x1 << ESP_SWDIO_PIN);
esp_rom_gpio_connect_out_signal(ESP_SWDIO_PIN, SIG_GPIO_OUT_IDX, false, false);
}
//-----------------------------------------------------------------------------
static inline void DAP_CONFIG_SETUP(void) {
// since the blackmagic probe is not have connect and disconnect callbacks
// we can't enable the gpio
// gpio_ll_output_disable(&GPIO, ESP_SWDIO_PIN);
// gpio_ll_input_enable(&GPIO, ESP_SWDIO_PIN);
// gpio_ll_output_disable(&GPIO, ESP_SWCLK_PIN);
// gpio_ll_input_enable(&GPIO, ESP_SWCLK_PIN);
}
//-----------------------------------------------------------------------------
static inline void DAP_CONFIG_DISCONNECT(void) {
// since the blackmagic probe is not have connect and disconnect callbacks
// we can't disable the gpio
// gpio_ll_output_disable(&GPIO, ESP_SWDIO_PIN);
// gpio_ll_input_enable(&GPIO, ESP_SWDIO_PIN);
// gpio_ll_output_disable(&GPIO, ESP_SWCLK_PIN);
// gpio_ll_input_enable(&GPIO, ESP_SWCLK_PIN);
}
//-----------------------------------------------------------------------------
static inline void DAP_CONFIG_CONNECT_SWD(void) {
GPIO.enable_w1ts = (0x1 << ESP_SWDIO_PIN);
esp_rom_gpio_connect_out_signal(ESP_SWDIO_PIN, SIG_GPIO_OUT_IDX, false, false);
GPIO.enable_w1ts = (0x1 << ESP_SWCLK_PIN);
esp_rom_gpio_connect_out_signal(ESP_SWCLK_PIN, SIG_GPIO_OUT_IDX, false, false);
}
//-----------------------------------------------------------------------------
static inline void DAP_CONFIG_CONNECT_JTAG(void) {
// Do nothing
}
//-----------------------------------------------------------------------------
static inline void DAP_CONFIG_LED(int index, int state) {
(void)index;
(void)state;
// Do nothing
}
//-----------------------------------------------------------------------------
__attribute__((always_inline)) static inline void DAP_CONFIG_DELAY(uint32_t cycles) {
register int32_t cnt;
for(cnt = cycles; --cnt > 0;)
;
}

@ -0,0 +1 @@
Subproject commit e7752beb5e8a69119af67b70b9179cb3c90f3ac5

View File

@ -1 +1 @@
main.svelte-bny5z.svelte-bny5z{border:4px dashed #000;margin:10px auto;padding:10px;max-width:800px;overflow:hidden}.svelte-bny5z.svelte-bny5z{-moz-user-select:none;-o-user-select:none;-khtml-user-select:none;-webkit-user-select:none;-ms-user-select:none;user-select:none}tabs.svelte-bny5z.svelte-bny5z{border-bottom:4px dashed #000;width:100%;display:block}tab.svelte-bny5z.svelte-bny5z{margin-right:10px;padding:5px 10px;margin-bottom:5px;display:inline-block}tab.svelte-bny5z.svelte-bny5z:hover,tab.selected.svelte-bny5z.svelte-bny5z:hover{background:rgb(255, 255, 255);color:#000000}tab.selected.svelte-bny5z.svelte-bny5z{background-color:black;color:white}tabs-content.svelte-bny5z.svelte-bny5z{display:block;margin-top:10px}error.svelte-bny5z.svelte-bny5z{padding:5px 10px;background-color:rgb(255, 0, 0);color:black}@font-face{font-family:"DOS";src:url("../assets/ega8.otf") format("opentype");font-weight:normal;font-style:normal;-webkit-font-kerning:none;font-kerning:none;font-synthesis:none;-webkit-font-variant-ligatures:none;font-variant-ligatures:none;font-variant-numeric:tabular-nums}body{padding:0;margin:0;background-color:#ffa21c;color:#000;font-size:28px;font-family:"DOS", monospace;line-height:1;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:rgba(0, 0, 0, 0)}.grid.svelte-bny5z.svelte-bny5z{display:inline-grid;grid-template-columns:auto auto}.grid.svelte-bny5z>div.svelte-bny5z{margin-top:10px}.value-name.svelte-bny5z.svelte-bny5z{text-align:right}task-list.svelte-bny5z.svelte-bny5z{display:inline-grid;grid-template-columns:auto auto auto auto auto;width:100%}.button-css.svelte-yar6m3{background-color:black;color:white;font-size:28px;font-family:"DOS", monospace;line-height:1;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:rgba(0, 0, 0, 0);border:0;padding:5px 10px;display:inline-block;max-width:100%}.button-css.svelte-yar6m3:hover{background:rgb(255, 255, 255);color:#000000}popup-wrapper.svelte-1ufadaz{background-color:rgba(0, 0, 0, 0.863);width:100%;height:100%;display:table;table-layout:fixed;z-index:999;overflow:auto;position:fixed;top:0;left:0;right:0;bottom:0}popup-body.svelte-1ufadaz{margin:auto;display:table-cell;text-align:center;vertical-align:middle;width:100%}popup-content.svelte-1ufadaz{background-color:#ffa21c;display:inline-block;outline:none;position:relative;text-align:initial;max-width:100vw}popup-border.svelte-1ufadaz{display:block;border:4px dashed #000;margin:10px;padding:10px}popup-close.svelte-1ufadaz{background-color:#000;display:inline-block;color:#ffa21c;position:absolute;width:24px;right:0px;top:0px;text-align:center}popup-close.svelte-1ufadaz:hover{background-color:#fff;color:#000}.input-text-css.svelte-4h7oz2{display:inline-block;color:#000;font-size:28px;font-family:"DOS", monospace;line-height:1;box-sizing:border-box;margin:0;border:0;border-bottom:4px solid #000;padding:0 5px 0 5px;box-shadow:none;border-radius:0;-moz-appearance:none;-webkit-appearance:none;appearance:none;background-color:#ffa21c;height:32px}.input-text-css.svelte-4h7oz2:focus-visible,.input-text-css.svelte-4h7oz2:hover{outline:0;background-color:white}@keyframes svelte-1471rey-spinner-animation{0%{content:"|"}25%{content:"/"}50%{content:"-"}75%{content:"\\"}100%{content:"|"}}spinner.svelte-1471rey::after{display:inline-block;animation:svelte-1471rey-spinner-animation 0.6s linear infinite alternate;content:"|"}select.svelte-1rf61qb.svelte-1rf61qb{display:inline-block;color:#000;font-size:28px;font-family:"DOS", monospace;line-height:1;box-sizing:border-box;margin:0;border:0;border-bottom:4px solid #000;padding:0 5px 0 5px;box-shadow:none;border-radius:0;-moz-appearance:none;-webkit-appearance:none;appearance:none;background-color:#ffa21c}select.svelte-1rf61qb.svelte-1rf61qb::-ms-expand{display:none}select.svelte-1rf61qb.svelte-1rf61qb:hover{background:rgb(255, 255, 255);color:#000000}select.svelte-1rf61qb.svelte-1rf61qb:focus{box-shadow:none;outline:none;background:rgb(255, 255, 255);color:#000000}select.svelte-1rf61qb option.svelte-1rf61qb{font-weight:normal}.button.svelte-1rqr1h4{box-sizing:border-box;display:inline-block;font-size:28px;font-family:"DOS", monospace;line-height:1;border:0;padding:0 5px 0 5px;box-shadow:none;border-radius:0;display:inline-block;max-width:100%}.black.svelte-1rqr1h4{color:white;background-color:black;border-bottom:4px solid #000}.black.svelte-1rqr1h4:hover{background:#fff;color:#000}.normal.svelte-1rqr1h4{color:#000;background-color:#ffa21c;border-bottom:4px solid #ffa21c}.normal.svelte-1rqr1h4:hover{background:#000;color:#fff}
main.svelte-bny5z.svelte-bny5z{border:4px dashed #000;margin:10px auto;padding:10px;max-width:800px;overflow:hidden}.svelte-bny5z.svelte-bny5z{-moz-user-select:none;-o-user-select:none;-khtml-user-select:none;-webkit-user-select:none;-ms-user-select:none;user-select:none}tabs.svelte-bny5z.svelte-bny5z{border-bottom:4px dashed #000;width:100%;display:block}tab.svelte-bny5z.svelte-bny5z{margin-right:10px;padding:5px 10px;margin-bottom:5px;display:inline-block}tab.svelte-bny5z.svelte-bny5z:hover,tab.selected.svelte-bny5z.svelte-bny5z:hover{background:rgb(255, 255, 255);color:#000000}tab.selected.svelte-bny5z.svelte-bny5z{background-color:black;color:white}tabs-content.svelte-bny5z.svelte-bny5z{display:block;margin-top:10px}error.svelte-bny5z.svelte-bny5z{padding:5px 10px;background-color:rgb(255, 0, 0);color:black}@font-face{font-family:"DOS";src:url("../assets/ega8.otf") format("opentype");font-weight:normal;font-style:normal;-webkit-font-kerning:none;font-kerning:none;font-synthesis:none;-webkit-font-variant-ligatures:none;font-variant-ligatures:none;font-variant-numeric:tabular-nums}body{padding:0;margin:0;background-color:#ffa21c;color:#000;font-size:28px;font-family:"DOS", monospace;line-height:1;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:rgba(0, 0, 0, 0)}.grid.svelte-bny5z.svelte-bny5z{display:inline-grid;grid-template-columns:auto auto}.grid.svelte-bny5z>div.svelte-bny5z{margin-top:10px}.value-name.svelte-bny5z.svelte-bny5z{text-align:right}task-list.svelte-bny5z.svelte-bny5z{display:inline-grid;grid-template-columns:auto auto auto auto auto;width:100%}.button-css.svelte-yar6m3{background-color:black;color:white;font-size:28px;font-family:"DOS", monospace;line-height:1;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:rgba(0, 0, 0, 0);border:0;padding:5px 10px;display:inline-block;max-width:100%}.button-css.svelte-yar6m3:hover{background:rgb(255, 255, 255);color:#000000}popup-wrapper.svelte-1ufadaz{background-color:rgba(0, 0, 0, 0.863);width:100%;height:100%;display:table;table-layout:fixed;z-index:999;overflow:auto;position:fixed;top:0;left:0;right:0;bottom:0}popup-body.svelte-1ufadaz{margin:auto;display:table-cell;text-align:center;vertical-align:middle;width:100%}popup-content.svelte-1ufadaz{background-color:#ffa21c;display:inline-block;outline:none;position:relative;text-align:initial;max-width:100vw}popup-border.svelte-1ufadaz{display:block;border:4px dashed #000;margin:10px;padding:10px}popup-close.svelte-1ufadaz{background-color:#000;display:inline-block;color:#ffa21c;position:absolute;width:24px;right:0px;top:0px;text-align:center}popup-close.svelte-1ufadaz:hover{background-color:#fff;color:#000}@keyframes svelte-1471rey-spinner-animation{0%{content:"|"}25%{content:"/"}50%{content:"-"}75%{content:"\\"}100%{content:"|"}}spinner.svelte-1471rey::after{display:inline-block;animation:svelte-1471rey-spinner-animation 0.6s linear infinite alternate;content:"|"}.button.svelte-1rqr1h4{box-sizing:border-box;display:inline-block;font-size:28px;font-family:"DOS", monospace;line-height:1;border:0;padding:0 5px 0 5px;box-shadow:none;border-radius:0;display:inline-block;max-width:100%}.black.svelte-1rqr1h4{color:white;background-color:black;border-bottom:4px solid #000}.black.svelte-1rqr1h4:hover{background:#fff;color:#000}.normal.svelte-1rqr1h4{color:#000;background-color:#ffa21c;border-bottom:4px solid #ffa21c}.normal.svelte-1rqr1h4:hover{background:#000;color:#fff}select.svelte-1rf61qb.svelte-1rf61qb{display:inline-block;color:#000;font-size:28px;font-family:"DOS", monospace;line-height:1;box-sizing:border-box;margin:0;border:0;border-bottom:4px solid #000;padding:0 5px 0 5px;box-shadow:none;border-radius:0;-moz-appearance:none;-webkit-appearance:none;appearance:none;background-color:#ffa21c}select.svelte-1rf61qb.svelte-1rf61qb::-ms-expand{display:none}select.svelte-1rf61qb.svelte-1rf61qb:hover{background:rgb(255, 255, 255);color:#000000}select.svelte-1rf61qb.svelte-1rf61qb:focus{box-shadow:none;outline:none;background:rgb(255, 255, 255);color:#000000}select.svelte-1rf61qb option.svelte-1rf61qb{font-weight:normal}.input-text-css.svelte-4h7oz2{display:inline-block;color:#000;font-size:28px;font-family:"DOS", monospace;line-height:1;box-sizing:border-box;margin:0;border:0;border-bottom:4px solid #000;padding:0 5px 0 5px;box-shadow:none;border-radius:0;-moz-appearance:none;-webkit-appearance:none;appearance:none;background-color:#ffa21c;height:32px}.input-text-css.svelte-4h7oz2:focus-visible,.input-text-css.svelte-4h7oz2:hover{outline:0;background-color:white}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -405,10 +405,13 @@ size_t usb_glue_gdb_receive(uint8_t* buf, size_t len) {
}
void usb_glue_dap_send(const uint8_t* buf, size_t len, bool flush) {
// TODO
if(usb_device_type == USBDeviceTypeDapLink) {
tud_vendor_write(buf, len);
} else {
esp_system_abort("Wrong USB device type");
}
}
size_t usb_glue_dap_receive(uint8_t* buf, size_t len) {
// TODO
return 0;
return tud_vendor_read(buf, len);
}

3
debug.log Normal file
View File

@ -0,0 +1,3 @@
2022-12-02 17:56:11,918 - Debug Adapter (main) - CRITICAL - Debug adapter -> Extension: DEBUG_ADAPTER_STARTED
2022-12-02 17:56:11,919 - Debug Adapter (main) - CRITICAL - Debug adapter -> Extension: DEBUG_ADAPTER_READY2CONNECT
2022-12-02 17:56:24,064 - Debug Adapter (main) - CRITICAL - Debug adapter -> Extension: DEBUG_ADAPTER_STOPPED

View File

@ -1,6 +1,6 @@
set(SOURCES
set(SOURCES
"main.c"
"usb-cdc.c"
"usb.c"
"usb-uart.c"
"nvs.c"
"nvs-config.c"
@ -23,12 +23,12 @@ set(SOURCES
"factory-reset-service.c"
)
set(INCLUDES
set(INCLUDES
"."
)
idf_component_register(SRCS ${SOURCES}
INCLUDE_DIRS ${INCLUDES})
INCLUDE_DIRS ${INCLUDES})
# Commit
execute_process(

View File

@ -4,7 +4,7 @@
#include <freertos/task.h>
#include <rom/ets_sys.h>
#include "usb-cdc.h"
#include "usb.h"
#include "nvs.h"
#include "gdb_main.h"
#include "led.h"
@ -67,7 +67,7 @@ void app_main(void) {
// network_uart_server_init();
network_gdb_server_init();
usb_cdc_init();
usb_init();
cli_uart_init();
// TODO uart and i2c share the same pins, need switching mechanics

View File

@ -14,6 +14,14 @@
#define CFG_WIFI_MODE_AP "AP"
#define CFG_WIFI_MODE_STA "STA"
#define CFG_USB_MODE_BLACKMAGIC "BLACKMAGIC"
#define CFG_USB_MODE_DAP "DAP"
typedef enum {
UsbModeBM, // Blackmagic-probe
UsbModeDAP, // Dap-link
} UsbMode;
typedef enum {
WiFiModeAP, // host of a WiFi network
WiFiModeSTA, // connected to existing WiFi AP

View File

@ -1,128 +0,0 @@
/**
* @file usb-cdc.c
* Do not forget to take pid's when implement own USB device class
*
* https://github.com/espressif/usb-pids
*
*/
#include <stdint.h>
#include <esp_log.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <freertos/stream_buffer.h>
#include <sdkconfig.h>
#include <driver/gpio.h>
#include "usb-cdc.h"
#include "usb-uart.h"
#include "led.h"
#include "delay.h"
#include <gdb-glue.h>
#include <usb-glue.h>
#include <class/cdc/cdc_device.h>
#define USB_DN_PIN (19)
#define USB_DP_PIN (20)
#define GDB_BUF_RX_SIZE 64
#define UART_BUF_RX_SIZE 64
static const char* TAG = "usb-cdc";
static uint8_t gdb_buffer_rx[GDB_BUF_RX_SIZE];
static uint8_t uart_buffer_rx[UART_BUF_RX_SIZE];
typedef struct {
volatile bool connected;
} USBCDC;
static USBCDC usb_cdc;
void usb_cdc_gdb_tx_char(uint8_t c, bool flush) {
usb_glue_gdb_send(&c, 1, flush);
}
void usb_cdc_uart_tx_char(uint8_t c, bool flush) {
usb_glue_cdc_send(&c, 1, flush);
}
static void usb_cdc_gdb_rx_callback(void* context) {
if(gdb_glue_can_receive()) {
size_t max_len = gdb_glue_get_free_size();
if(max_len > GDB_BUF_RX_SIZE) max_len = GDB_BUF_RX_SIZE;
uint32_t rx_size = usb_glue_gdb_receive(gdb_buffer_rx, max_len);
if(rx_size > 0) {
gdb_glue_receive(gdb_buffer_rx, rx_size);
}
} else {
esp_system_abort("No free space in GDB buffer");
}
}
static void usb_cdc_uart_rx_callback(void* context) {
size_t max_len = gdb_glue_get_free_size();
if(max_len > UART_BUF_RX_SIZE) max_len = UART_BUF_RX_SIZE;
uint32_t rx_size = usb_glue_cdc_receive(uart_buffer_rx, max_len);
if(rx_size > 0) {
usb_uart_write(uart_buffer_rx, rx_size);
}
}
static void usb_cdc_line_state_cb(bool dtr, bool rts, void* context) {
usb_uart_set_line_state(dtr, rts);
}
static void
usb_cdc_set_line_coding_callback(cdc_line_coding_t const* p_line_coding, void* context) {
uint32_t bit_rate = p_line_coding->bit_rate;
uint8_t stop_bits = p_line_coding->stop_bits;
uint8_t parity = p_line_coding->parity;
uint8_t data_bits = p_line_coding->data_bits;
usb_uart_set_line_coding(bit_rate, stop_bits, parity, data_bits);
}
//--------------------------------------------------------------------+
// Device callbacks
//--------------------------------------------------------------------+
static void usb_cdc_event_blink(void) {
led_set_blue(255);
delay(10);
led_set_blue(0);
}
static void usb_cdc_to_connected(void* context) {
if(!usb_cdc.connected) {
usb_cdc_event_blink();
}
usb_cdc.connected = true;
ESP_LOGI(TAG, "connect");
}
static void usb_cdc_from_connected(void* context) {
if(usb_cdc.connected) {
usb_cdc_event_blink();
}
usb_cdc.connected = false;
ESP_LOGI(TAG, "disconnect");
}
void usb_cdc_init(void) {
ESP_LOGI(TAG, "init");
usb_glue_set_connected_callback(usb_cdc_to_connected, NULL);
usb_glue_set_disconnected_callback(usb_cdc_from_connected, NULL);
usb_glue_cdc_set_line_coding_callback(usb_cdc_set_line_coding_callback, NULL);
usb_glue_cdc_set_line_state_callback(usb_cdc_line_state_cb, NULL);
usb_glue_cdc_set_receive_callback(usb_cdc_uart_rx_callback, NULL);
usb_glue_gdb_set_receive_callback(usb_cdc_gdb_rx_callback, NULL);
usb_cdc.connected = false;
usb_uart_init();
usb_glue_init(USBDeviceTypeDualCDC);
ESP_LOGI(TAG, "init done");
}

View File

@ -1,10 +0,0 @@
#pragma once
/**
* Init usb subsystem
*/
void usb_cdc_init(void);
void usb_cdc_gdb_tx_char(uint8_t c, bool flush);
void usb_cdc_uart_tx_char(uint8_t c, bool flush);

View File

@ -3,7 +3,7 @@
#include <freertos/task.h>
#include <freertos/stream_buffer.h>
#include <esp_log.h>
#include "usb-cdc.h"
#include "usb.h"
#include "usb-uart.h"
#define USB_UART_PORT_NUM UART_NUM_0
@ -41,9 +41,6 @@ void usb_uart_init() {
};
simple_uart_init(&config);
usb_uart_write((const uint8_t*)"Go", 2);
ESP_LOGI(TAG, "init done");
}
@ -129,9 +126,9 @@ static void usb_uart_rx_task(void* pvParameters) {
if(length > 0) {
for(size_t i = 0; i < length; i++) {
if((i + 1) == length) {
usb_cdc_uart_tx_char(data[i], true);
usb_uart_tx_char(data[i], true);
} else {
usb_cdc_uart_tx_char(data[i], false);
usb_uart_tx_char(data[i], false);
}
}
}

188
main/usb.c Normal file
View File

@ -0,0 +1,188 @@
/**
* @file usb.c
* Do not forget to take pid's when implement own USB device class
*
* https://github.com/espressif/usb-pids
*
*/
#include <stdint.h>
#include <esp_log.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <freertos/stream_buffer.h>
#include <sdkconfig.h>
#include <driver/gpio.h>
#include "usb.h"
#include "usb-uart.h"
#include "led.h"
#include "delay.h"
#include "nvs-config.h"
#include <gdb-glue.h>
#include <usb-glue.h>
#include <class/cdc/cdc_device.h>
#define USB_DN_PIN (19)
#define USB_DP_PIN (20)
#define GDB_BUF_RX_SIZE 64
#define UART_BUF_RX_SIZE 64
static const char* TAG = "usb";
static uint8_t gdb_buffer_rx[GDB_BUF_RX_SIZE];
static uint8_t uart_buffer_rx[UART_BUF_RX_SIZE];
typedef struct {
volatile bool connected;
} UsbState;
static UsbState usb_state;
void usb_gdb_tx_char(uint8_t c, bool flush) {
usb_glue_gdb_send(&c, 1, flush);
}
void usb_uart_tx_char(uint8_t c, bool flush) {
usb_glue_cdc_send(&c, 1, flush);
}
static void usb_gdb_rx_callback(void* context) {
if(gdb_glue_can_receive()) {
size_t max_len = gdb_glue_get_free_size();
if(max_len > GDB_BUF_RX_SIZE) max_len = GDB_BUF_RX_SIZE;
uint32_t rx_size = usb_glue_gdb_receive(gdb_buffer_rx, max_len);
if(rx_size > 0) {
gdb_glue_receive(gdb_buffer_rx, rx_size);
}
} else {
esp_system_abort("No free space in GDB buffer");
}
}
static void usb_uart_rx_callback(void* context) {
size_t max_len = gdb_glue_get_free_size();
if(max_len > UART_BUF_RX_SIZE) max_len = UART_BUF_RX_SIZE;
uint32_t rx_size = usb_glue_cdc_receive(uart_buffer_rx, max_len);
if(rx_size > 0) {
usb_uart_write(uart_buffer_rx, rx_size);
}
}
static void usb_line_state_cb(bool dtr, bool rts, void* context) {
usb_uart_set_line_state(dtr, rts);
}
static void usb_set_line_coding_callback(cdc_line_coding_t const* p_line_coding, void* context) {
uint32_t bit_rate = p_line_coding->bit_rate;
uint8_t stop_bits = p_line_coding->stop_bits;
uint8_t parity = p_line_coding->parity;
uint8_t data_bits = p_line_coding->data_bits;
usb_uart_set_line_coding(bit_rate, stop_bits, parity, data_bits);
}
//--------------------------------------------------------------------+
// Device callbacks
//--------------------------------------------------------------------+
static void usb_event_blink(void) {
led_set_blue(255);
delay(10);
led_set_blue(0);
}
static void usb_to_connected(void* context) {
if(!usb_state.connected) {
usb_event_blink();
}
usb_state.connected = true;
ESP_LOGI(TAG, "connect");
}
static void usb_from_connected(void* context) {
if(usb_state.connected) {
usb_event_blink();
}
usb_state.connected = false;
ESP_LOGI(TAG, "disconnect");
}
#define CONFIG_DAP_TASK_STACK_SIZE 4096
#define CONFIG_DAP_TASK_PRIORITY 5
#define DAP_RECEIVE_FLAG (1 << 0)
#include "dap.h"
#include "dap_config.h"
TaskHandle_t dap_task_handle;
static void dap_rx_callback(void* context) {
xTaskNotify(dap_task_handle, DAP_RECEIVE_FLAG, eSetBits);
}
static void dap_task(void* arg) {
ESP_LOGI("dap_task", "started");
uint32_t notified_value;
dap_init();
while(1) {
BaseType_t xResult = xTaskNotifyWait(pdFALSE, ULONG_MAX, &notified_value, portMAX_DELAY);
if(xResult == pdPASS) {
if((notified_value & DAP_RECEIVE_FLAG) != 0) {
uint8_t rx_data[DAP_CONFIG_PACKET_SIZE];
uint8_t tx_data[DAP_CONFIG_PACKET_SIZE];
memset(tx_data, 0, DAP_CONFIG_PACKET_SIZE);
memset(rx_data, 0, DAP_CONFIG_PACKET_SIZE);
size_t rx_size = usb_glue_dap_receive(rx_data, sizeof(rx_data));
size_t tx_size = dap_process_request(rx_data, rx_size, tx_data, sizeof(tx_data));
usb_glue_dap_send(tx_data, tx_size, true);
}
}
}
}
void usb_init(void) {
ESP_LOGI(TAG, "init");
// TODO get from config
UsbMode usb_mode = UsbModeDAP;
if(usb_mode == UsbModeBM) {
usb_glue_set_connected_callback(usb_to_connected, NULL);
usb_glue_set_disconnected_callback(usb_from_connected, NULL);
usb_glue_cdc_set_line_coding_callback(usb_set_line_coding_callback, NULL);
usb_glue_cdc_set_line_state_callback(usb_line_state_cb, NULL);
usb_glue_cdc_set_receive_callback(usb_uart_rx_callback, NULL);
usb_glue_gdb_set_receive_callback(usb_gdb_rx_callback, NULL);
usb_state.connected = false;
usb_uart_init();
usb_glue_init(USBDeviceTypeDualCDC);
} else {
usb_glue_set_connected_callback(usb_to_connected, NULL);
usb_glue_set_disconnected_callback(usb_from_connected, NULL);
usb_glue_cdc_set_line_coding_callback(usb_set_line_coding_callback, NULL);
usb_glue_cdc_set_line_state_callback(usb_line_state_cb, NULL);
usb_glue_cdc_set_receive_callback(usb_uart_rx_callback, NULL);
usb_glue_dap_set_receive_callback(dap_rx_callback, NULL);
xTaskCreate(
dap_task,
"DAP",
CONFIG_DAP_TASK_STACK_SIZE,
NULL,
CONFIG_DAP_TASK_PRIORITY,
&dap_task_handle);
usb_state.connected = false;
usb_uart_init();
usb_glue_init(USBDeviceTypeDapLink);
}
ESP_LOGI(TAG, "init done");
}

10
main/usb.h Normal file
View File

@ -0,0 +1,10 @@
#pragma once
/**
* Init usb subsystem
*/
void usb_init(void);
void usb_gdb_tx_char(uint8_t c, bool flush);
void usb_uart_tx_char(uint8_t c, bool flush);