blackmagic glue works

This commit is contained in:
SG 2022-11-30 19:59:10 +03:00
parent 59d0ea87a5
commit a51f611066
6 changed files with 132 additions and 178 deletions

View File

@ -56,7 +56,8 @@ target_sources(${COMPONENT_TARGET} INTERFACE
"${COMPONENT_DIR}/tinyusb/src/host/usbh_control.c"
"${COMPONENT_DIR}/drivers/usb-glue.c"
"${COMPONENT_DIR}/drivers/dual-cdc/dual-cdc-driver.c"
# "${COMPONENT_DIR}/drivers/dual-cdc/dual-cdc-driver.c"
"${COMPONENT_DIR}/drivers/dual-cdc/dual-cdc-descriptors.c"
# "${COMPONENT_DIR}/drivers/dap-link/vendor_device.c"

View File

@ -1,76 +0,0 @@
#include <tusb.h>
#include <class/cdc/cdc_device.h>
#include <driver/gpio.h>
#include <driver/periph_ctrl.h>
#include <hal/usb_hal.h>
#include <soc/gpio_periph.h>
#include <soc/usb_periph.h>
#include <esp_rom_gpio.h>
#include <hal/gpio_ll.h>
#include <esp_log.h>
#include <esp_check.h>
#include "dual-cdc-driver.h"
#define TAG "usb-dual-cdc"
#define CONFIG_TINYUSB_TASK_STACK_SIZE 4096
#define CONFIG_TINYUSB_TASK_PRIORITY 17
static void configure_pins(usb_hal_context_t* usb) {
/* usb_periph_iopins currently configures USB_OTG as USB Device.
* Introduce additional parameters in usb_hal_context_t when adding support
* for USB Host.
*/
for(const usb_iopin_dsc_t* iopin = usb_periph_iopins; iopin->pin != -1; ++iopin) {
if((usb->use_external_phy) || (iopin->ext_phy_only == 0)) {
esp_rom_gpio_pad_select_gpio(iopin->pin);
if(iopin->is_output) {
esp_rom_gpio_connect_out_signal(iopin->pin, iopin->func, false, false);
} else {
esp_rom_gpio_connect_in_signal(iopin->pin, iopin->func, false);
if((iopin->pin != GPIO_FUNC_IN_LOW) && (iopin->pin != GPIO_FUNC_IN_HIGH)) {
gpio_ll_input_enable(&GPIO, iopin->pin);
}
}
esp_rom_gpio_pad_unhold(iopin->pin);
}
}
if(!usb->use_external_phy) {
gpio_set_drive_capability(USBPHY_DM_NUM, GPIO_DRIVE_CAP_3);
gpio_set_drive_capability(USBPHY_DP_NUM, GPIO_DRIVE_CAP_3);
}
}
static void tusb_device_task(void* arg) {
ESP_LOGD(TAG, "tinyusb task started");
while(1) { // RTOS forever loop
tud_task();
}
}
esp_err_t dual_cdc_driver_install(void) {
// Enable APB CLK to USB peripheral
periph_module_enable(PERIPH_USB_MODULE);
periph_module_reset(PERIPH_USB_MODULE);
// Initialize HAL layer
usb_hal_context_t hal = {.use_external_phy = false};
usb_hal_init(&hal);
configure_pins(&hal);
ESP_RETURN_ON_FALSE(tusb_init(), ESP_FAIL, TAG, "init TinyUSB failed");
TaskHandle_t s_tusb_tskh;
xTaskCreate(
tusb_device_task,
"TinyUSB",
CONFIG_TINYUSB_TASK_STACK_SIZE,
NULL,
CONFIG_TINYUSB_TASK_PRIORITY,
&s_tusb_tskh);
ESP_RETURN_ON_FALSE(s_tusb_tskh, ESP_FAIL, TAG, "create TinyUSB main task failed");
ESP_LOGI(TAG, "TinyUSB Driver installed");
return ESP_OK;
}

View File

@ -1,22 +0,0 @@
/**
* @file dual-cdc-driver.h
* @author Sergey Gavrilov (who.just.the.doctor@gmail.com)
* @version 1.0
* @date 2021-12-16
*
* Dual CDC driver
*/
#pragma once
#include <stdint.h>
#include <esp_err.h>
#include <tusb_config.h>
#define CDC_IF_COUNT CFG_TUD_CDC
/**
*
* @return esp_err_t
*/
esp_err_t dual_cdc_driver_install(void);

View File

@ -3,6 +3,10 @@
#include "dual-cdc/dual-cdc-descriptors.h"
#include "usb-glue.h"
#define TAG "usb-glue"
#define CONFIG_TINYUSB_TASK_STACK_SIZE 4096
#define CONFIG_TINYUSB_TASK_PRIORITY 17
typedef struct {
uint8_t const* desc_device;
uint8_t const* desc_config;
@ -165,6 +169,11 @@ bool tud_vendor_control_xfer_cb(
return true;
}
void tud_vendor_rx_cb(uint8_t itf) {
(void)itf;
callback_dap_receive();
}
void tud_mount_cb(void) {
callback_connected();
}
@ -226,10 +235,101 @@ void tud_cdc_line_coding_cb(uint8_t interface, cdc_line_coding_t const* p_line_c
}
}
/***** HAL *****/
#include <driver/gpio.h>
#include <driver/periph_ctrl.h>
#include <hal/usb_hal.h>
#include <soc/usb_periph.h>
#include <esp_rom_gpio.h>
#include <hal/gpio_ll.h>
#include <delay.h>
#include <esp_log.h>
#include <esp_check.h>
static void usb_hal_init_pins(usb_hal_context_t* usb) {
/* usb_periph_iopins currently configures USB_OTG as USB Device.
* Introduce additional parameters in usb_hal_context_t when adding support
* for USB Host.
*/
for(const usb_iopin_dsc_t* iopin = usb_periph_iopins; iopin->pin != -1; ++iopin) {
if((usb->use_external_phy) || (iopin->ext_phy_only == 0)) {
esp_rom_gpio_pad_select_gpio(iopin->pin);
if(iopin->is_output) {
esp_rom_gpio_connect_out_signal(iopin->pin, iopin->func, false, false);
} else {
esp_rom_gpio_connect_in_signal(iopin->pin, iopin->func, false);
if((iopin->pin != GPIO_FUNC_IN_LOW) && (iopin->pin != GPIO_FUNC_IN_HIGH)) {
gpio_ll_input_enable(&GPIO, iopin->pin);
}
}
esp_rom_gpio_pad_unhold(iopin->pin);
}
}
if(!usb->use_external_phy) {
gpio_set_drive_capability(USBPHY_DM_NUM, GPIO_DRIVE_CAP_3);
gpio_set_drive_capability(USBPHY_DP_NUM, GPIO_DRIVE_CAP_3);
}
}
static void usb_hal_bus_reset() {
gpio_config_t io_conf;
io_conf.intr_type = GPIO_PIN_INTR_DISABLE;
io_conf.mode = GPIO_MODE_OUTPUT_OD;
io_conf.pin_bit_mask = ((1 << USBPHY_DM_NUM) | (1 << USBPHY_DP_NUM));
io_conf.pull_down_en = GPIO_PULLDOWN_ENABLE;
io_conf.pull_up_en = GPIO_PULLUP_DISABLE;
gpio_config(&io_conf);
gpio_set_level(USBPHY_DM_NUM, 0);
gpio_set_level(USBPHY_DP_NUM, 0);
delay(100);
gpio_set_level(USBPHY_DM_NUM, 1);
gpio_set_level(USBPHY_DP_NUM, 1);
}
static void usb_hal_tusb_device_task(void* arg) {
ESP_LOGD(TAG, "tinyusb task started");
while(1) { // RTOS forever loop
tud_task();
}
}
/***** Glue *****/
void usb_glue_init(USBDeviceType device_type) {
esp_err_t usb_glue_init(USBDeviceType device_type) {
usb_device_type = device_type;
usb_hal_bus_reset();
// Enable APB CLK to USB peripheral
periph_module_enable(PERIPH_USB_MODULE);
periph_module_reset(PERIPH_USB_MODULE);
// Initialize HAL layer
usb_hal_context_t hal = {.use_external_phy = false};
usb_hal_init(&hal);
usb_hal_init_pins(&hal);
ESP_RETURN_ON_FALSE(tusb_init(), ESP_FAIL, TAG, "init TinyUSB failed");
TaskHandle_t s_tusb_tskh;
xTaskCreate(
usb_hal_tusb_device_task,
"TinyUSB",
CONFIG_TINYUSB_TASK_STACK_SIZE,
NULL,
CONFIG_TINYUSB_TASK_PRIORITY,
&s_tusb_tskh);
ESP_RETURN_ON_FALSE(s_tusb_tskh, ESP_FAIL, TAG, "create TinyUSB main task failed");
ESP_LOGI(TAG, "TinyUSB Driver installed");
return ESP_OK;
}
void usb_glue_reset_bus() {
usb_hal_bus_reset();
}
void usb_glue_set_connected_callback(void (*callback)(void* context), void* context) {
@ -310,4 +410,5 @@ void usb_glue_dap_send(const uint8_t* buf, size_t len, bool flush) {
size_t usb_glue_dap_receive(uint8_t* buf, size_t len) {
// TODO
return 0;
}

View File

@ -1,6 +1,8 @@
#pragma once
#include <stdint.h>
#include <stddef.h>
#include <esp_err.h>
#include <tusb.h>
typedef enum {
USBDeviceTypeDapLink,
@ -9,7 +11,9 @@ typedef enum {
/***** Common *****/
void usb_glue_init(USBDeviceType device_type);
esp_err_t usb_glue_init(USBDeviceType device_type);
void usb_glue_reset_bus();
void usb_glue_set_connected_callback(void (*callback)(void* context), void* context);

View File

@ -18,7 +18,7 @@
#include "led.h"
#include "delay.h"
#include <gdb-glue.h>
#include <dual-cdc-driver.h>
#include <usb-glue.h>
#include <class/cdc/cdc_device.h>
#define USB_DN_PIN (19)
@ -37,32 +37,19 @@ typedef struct {
static USBCDC usb_cdc;
typedef enum {
CDCTypeGDB = 0,
CDCTypeUART = 1,
} CDCType;
static void usb_cdc_tx_char(CDCType type, uint8_t c, bool flush) {
tud_cdc_n_write(type, &c, 1);
if(flush) {
tud_cdc_n_write_flush(type);
}
}
void usb_cdc_gdb_tx_char(uint8_t c, bool flush) {
usb_cdc_tx_char(CDCTypeGDB, c, flush);
usb_glue_gdb_send(&c, 1, flush);
}
void usb_cdc_uart_tx_char(uint8_t c, bool flush) {
usb_cdc_tx_char(CDCTypeUART, c, flush);
usb_glue_cdc_send(&c, 1, flush);
}
void usb_cdc_gdb_rx_callback(void) {
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 = tud_cdc_n_read(CDCTypeGDB, gdb_buffer_rx, max_len);
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);
@ -72,43 +59,28 @@ void usb_cdc_gdb_rx_callback(void) {
}
}
void usb_cdc_uart_rx_callback(void) {
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 = tud_cdc_n_read(CDCTypeUART, uart_buffer_rx, max_len);
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);
}
}
void tud_cdc_rx_cb(uint8_t interface) {
do {
if(interface == CDCTypeGDB) {
usb_cdc_gdb_rx_callback();
} else if(interface == CDCTypeUART) {
usb_cdc_uart_rx_callback();
} else {
tud_cdc_n_read_flush(interface);
}
} while(false);
static void usb_cdc_line_state_cb(bool dtr, bool rts, void* context) {
usb_uart_set_line_state(dtr, rts);
}
void tud_cdc_line_state_cb(uint8_t interface, bool dtr, bool rts) {
if(interface == CDCTypeUART) {
usb_uart_set_line_state(dtr, rts);
}
}
void tud_cdc_line_coding_cb(uint8_t interface, cdc_line_coding_t const* p_line_coding) {
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;
if(interface == CDCTypeUART) {
usb_uart_set_line_coding(bit_rate, stop_bits, parity, data_bits);
}
usb_uart_set_line_coding(bit_rate, stop_bits, parity, data_bits);
}
//--------------------------------------------------------------------+
@ -121,7 +93,7 @@ static void usb_cdc_event_blink(void) {
led_set_blue(0);
}
static void usb_cdc_to_connected(void) {
static void usb_cdc_to_connected(void* context) {
if(!usb_cdc.connected) {
usb_cdc_event_blink();
}
@ -129,7 +101,7 @@ static void usb_cdc_to_connected(void) {
ESP_LOGI(TAG, "connect");
}
static void usb_cdc_from_connected(void) {
static void usb_cdc_from_connected(void* context) {
if(usb_cdc.connected) {
usb_cdc_event_blink();
}
@ -138,45 +110,19 @@ static void usb_cdc_from_connected(void) {
ESP_LOGI(TAG, "disconnect");
}
void tud_mount_cb(void) {
usb_cdc_to_connected();
}
void tud_umount_cb(void) {
usb_cdc_from_connected();
}
void tud_resume_cb(void) {
usb_cdc_to_connected();
}
void tud_suspend_cb(bool remote_wakeup_en) {
usb_cdc_from_connected();
}
static void usb_cdc_bus_reset() {
gpio_config_t io_conf;
io_conf.intr_type = GPIO_PIN_INTR_DISABLE;
io_conf.mode = GPIO_MODE_OUTPUT_OD;
io_conf.pin_bit_mask = ((1 << USB_DN_PIN) | (1 << USB_DP_PIN));
io_conf.pull_down_en = GPIO_PULLDOWN_ENABLE;
io_conf.pull_up_en = GPIO_PULLUP_DISABLE;
gpio_config(&io_conf);
gpio_set_level(USB_DN_PIN, 0);
gpio_set_level(USB_DP_PIN, 0);
delay(100);
gpio_set_level(USB_DN_PIN, 1);
gpio_set_level(USB_DP_PIN, 1);
}
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_cdc_bus_reset();
dual_cdc_driver_install();
usb_glue_init(USBDeviceTypeDualCDC);
ESP_LOGI(TAG, "init done");
}