Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add picoprobe-only EXTRA_UART cmake option #103

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,22 @@ option (DEBUGPROBE "compile for the debugprobe" OFF)
if (DEBUGPROBE)
target_compile_definitions (picoprobe PRIVATE
DEBUGPROBE=1
CDC_UARTS=1
)
set_target_properties(picoprobe PROPERTIES
OUTPUT_NAME "debugprobe"
)
else ()
option (EXTRA_UART "bridge both probe UARTs")
if (EXTRA_UART)
target_compile_definitions (picoprobe PRIVATE
CDC_UARTS=2
)
else ()
target_compile_definitions (picoprobe PRIVATE
CDC_UARTS=1
)
endif ()
endif ()


Expand Down
12 changes: 10 additions & 2 deletions include/board_pico_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,22 @@
#define PROBE_PIN_RESET 1
#endif

// UART config
// UART config, ttyACMn
#define PICOPROBE_UART_TX 4
#define PICOPROBE_UART_RX 5
#define PICOPROBE_UART_INTERFACE uart1
#define PICOPROBE_UART_BAUDRATE 115200

#if CDC_UARTS == 2
// if enabled, always ttyACM(n+1)
#define PICOPROBE_EXTRA_UART_TX 0
#define PICOPROBE_EXTRA_UART_RX 1
#define PICOPROBE_EXTRA_UART_INTERFACE uart0
#define PICOPROBE_EXTRA_UART_BAUDRATE 115200
#endif

#define PICOPROBE_USB_CONNECTED_LED 25

#define PROBE_PRODUCT_STRING "Picoprobe (CMSIS-DAP)"

#endif
#endif
105 changes: 71 additions & 34 deletions src/cdc_uart.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,10 @@
TaskHandle_t uart_taskhandle;
TickType_t last_wake, interval = 100;

static uint8_t tx_buf[CFG_TUD_CDC_TX_BUFSIZE];
static uint8_t rx_buf[CFG_TUD_CDC_RX_BUFSIZE];
static uint8_t tx_buf[CDC_UARTS][CFG_TUD_CDC_TX_BUFSIZE];
static uint8_t rx_buf[CDC_UARTS][CFG_TUD_CDC_RX_BUFSIZE];
static int was_connected[CDC_UARTS];

// Actually s^-1 so 25ms
#define DEBOUNCE_MS 40
static uint debounce_ticks = 5;
Expand All @@ -54,75 +56,100 @@ void cdc_uart_init(void) {
gpio_set_pulls(PICOPROBE_UART_TX, 1, 0);
gpio_set_pulls(PICOPROBE_UART_RX, 1, 0);
uart_init(PICOPROBE_UART_INTERFACE, PICOPROBE_UART_BAUDRATE);

#if CDC_UARTS == 2
gpio_set_function(PICOPROBE_EXTRA_UART_TX, GPIO_FUNC_UART);
gpio_set_function(PICOPROBE_EXTRA_UART_RX, GPIO_FUNC_UART);
gpio_set_pulls(PICOPROBE_EXTRA_UART_TX, 1, 0);
gpio_set_pulls(PICOPROBE_EXTRA_UART_RX, 1, 0);
uart_init(PICOPROBE_EXTRA_UART_INTERFACE, PICOPROBE_EXTRA_UART_BAUDRATE);
#endif
for (int n = 0; n < CDC_UARTS; n++) { was_connected[n] = 0; }
}

void cdc_task(void)
void cdc_task(uint8_t tty)
{
static int was_connected = 0;
uint rx_len = 0;

uart_inst_t* uart_ptr = PICOPROBE_UART_INTERFACE;
#if CDC_UARTS == 2
if (tty) { uart_ptr = PICOPROBE_EXTRA_UART_INTERFACE; }
#endif

// Consume uart fifo regardless even if not connected
while(uart_is_readable(PICOPROBE_UART_INTERFACE) && (rx_len < sizeof(rx_buf))) {
rx_buf[rx_len++] = uart_getc(PICOPROBE_UART_INTERFACE);
while(uart_is_readable(uart_ptr) && (rx_len < sizeof(rx_buf[tty]))) {
rx_buf[tty][rx_len++] = uart_getc(uart_ptr);
}

if (tud_cdc_connected()) {
was_connected = 1;
if (tud_cdc_n_connected(tty)) {
was_connected[tty] = 1;
int written = 0;
/* Implicit overflow if we don't write all the bytes to the host.
* Also throw away bytes if we can't write... */
if (rx_len) {
if (!tty) {
#ifdef PICOPROBE_UART_RX_LED
gpio_put(PICOPROBE_UART_RX_LED, 1);
rx_led_debounce = debounce_ticks;
gpio_put(PICOPROBE_UART_RX_LED, 1);
rx_led_debounce = debounce_ticks;
#endif
written = MIN(tud_cdc_write_available(), rx_len);
}
written = MIN(tud_cdc_n_write_available(tty), rx_len);
if (written > 0) {
tud_cdc_write(rx_buf, written);
tud_cdc_write_flush();
tud_cdc_n_write(tty, rx_buf[tty], written);
tud_cdc_n_write_flush(tty);
}
} else {
if (!tty) {
#ifdef PICOPROBE_UART_RX_LED
if (rx_led_debounce)
rx_led_debounce--;
else
gpio_put(PICOPROBE_UART_RX_LED, 0);
if (rx_led_debounce)
rx_led_debounce--;
else
gpio_put(PICOPROBE_UART_RX_LED, 0);
#endif
}
}

/* Reading from a firehose and writing to a FIFO. */
size_t watermark = MIN(tud_cdc_available(), sizeof(tx_buf));
size_t watermark = MIN(tud_cdc_n_available(tty), sizeof(tx_buf[tty]));
if (watermark > 0) {
size_t tx_len;
if (!tty) {
#ifdef PICOPROBE_UART_TX_LED
gpio_put(PICOPROBE_UART_TX_LED, 1);
tx_led_debounce = debounce_ticks;
gpio_put(PICOPROBE_UART_TX_LED, 1);
tx_led_debounce = debounce_ticks;
#endif
}
/* Batch up to half a FIFO of data - don't clog up on RX */
watermark = MIN(watermark, 16);
tx_len = tud_cdc_read(tx_buf, watermark);
uart_write_blocking(PICOPROBE_UART_INTERFACE, tx_buf, tx_len);
tx_len = tud_cdc_n_read(tty, tx_buf[tty], watermark);
uart_write_blocking(uart_ptr, tx_buf[tty], tx_len);
} else {
if (!tty) {
#ifdef PICOPROBE_UART_TX_LED
if (tx_led_debounce)
tx_led_debounce--;
else
gpio_put(PICOPROBE_UART_TX_LED, 0);
#endif
}
}
} else if (was_connected) {
tud_cdc_write_clear();
was_connected = 0;
} else if (was_connected[tty]) {
tud_cdc_n_write_clear(tty);
was_connected[tty] = 0;
}
}

void cdc_tasks(void) {
for (int tty = 0; tty < CDC_UARTS; tty++) { cdc_task(tty); }
}

void cdc_thread(void *ptr)
{
BaseType_t delayed;
last_wake = xTaskGetTickCount();
/* Threaded with a polling interval that scales according to linerate */
while (1) {
cdc_task();
cdc_tasks();
delayed = xTaskDelayUntil(&last_wake, interval);
if (delayed == pdFALSE)
last_wake = xTaskGetTickCount();
Expand All @@ -131,6 +158,7 @@ void cdc_thread(void *ptr)

void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const* line_coding)
{
uint8_t tty = itf;
/* Set the tick thread interval to the amount of time it takes to
* fill up half a FIFO. Millis is too coarse for integer divide.
*/
Expand All @@ -141,27 +169,36 @@ void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const* line_coding)
debounce_ticks = MAX(1, configTICK_RATE_HZ / (interval * DEBOUNCE_MS));
picoprobe_info("New baud rate %ld micros %ld interval %lu\n",
line_coding->bit_rate, micros, interval);
uart_deinit(PICOPROBE_UART_INTERFACE);
tud_cdc_write_clear();
tud_cdc_read_flush();
uart_init(PICOPROBE_UART_INTERFACE, line_coding->bit_rate);

uart_inst_t* uart_ptr = PICOPROBE_UART_INTERFACE;
#if CDC_UARTS == 2
if (tty) { uart_ptr = PICOPROBE_EXTRA_UART_INTERFACE; }
#endif

uart_deinit(uart_ptr);
tud_cdc_n_write_clear(tty);
tud_cdc_n_read_flush(tty);
uart_init(uart_ptr, line_coding->bit_rate);
vTaskResume(uart_taskhandle);
}

void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts)
{
uint8_t tty = itf;
/* CDC drivers use linestate as a bodge to activate/deactivate the interface.
* Resume our UART polling on activate, stop on deactivate */
if (!dtr && !rts) {
vTaskSuspend(uart_taskhandle);
if (!tty) {
#ifdef PICOPROBE_UART_RX_LED
gpio_put(PICOPROBE_UART_RX_LED, 0);
rx_led_debounce = 0;
gpio_put(PICOPROBE_UART_RX_LED, 0);
rx_led_debounce = 0;
#endif
#ifdef PICOPROBE_UART_RX_LED
gpio_put(PICOPROBE_UART_TX_LED, 0);
tx_led_debounce = 0;
gpio_put(PICOPROBE_UART_TX_LED, 0);
tx_led_debounce = 0;
#endif
}
} else
vTaskResume(uart_taskhandle);
}
4 changes: 2 additions & 2 deletions src/cdc_uart.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@

void cdc_thread(void *ptr);
void cdc_uart_init(void);
void cdc_task(void);
void cdc_tasks(void);

extern TaskHandle_t uart_taskhandle;

#endif
#endif
4 changes: 2 additions & 2 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
#include "led.h"
#include "DAP.h"

// UART0 for Picoprobe debug
// UART0 available / for Picoprobe debug
// UART1 for picoprobe to target device

static uint8_t TxDataBuffer[CFG_TUD_HID_EP_BUFSIZE];
Expand Down Expand Up @@ -116,7 +116,7 @@ int main(void) {

while (!THREADED) {
tud_task();
cdc_task();
cdc_tasks();

#if (PICOPROBE_DEBUG_PROTOCOL == PROTO_DAP_V2)
if (tud_vendor_available()) {
Expand Down
16 changes: 13 additions & 3 deletions src/picoprobe_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,21 @@ do { \

// TODO tie this up with PICO_BOARD defines in the main SDK

#ifndef DEBUGPROBE
#ifndef DEBUGPROBE

#if CDC_UARTS < 1 || CDC_UARTS > 2
#error "PICOPROBE only supports one or two UARTs"
#endif
#include "board_pico_config.h"
#else
#include "board_debugprobe_config.h"

#else /* DEBUGPROBE */

#if CDC_UARTS != 1
#error "DEBUGPROBE only supports one UART"
#endif
#include "board_debugprobe_config.h"

#endif /* DEBUGPROBE */
//#include "board_example_config.h"


Expand Down
2 changes: 1 addition & 1 deletion src/tusb_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@

//------------- CLASS -------------//
#define CFG_TUD_HID 1
#define CFG_TUD_CDC 1
#define CFG_TUD_CDC CDC_UARTS
#define CFG_TUD_MSC 0
#define CFG_TUD_MIDI 0
#define CFG_TUD_VENDOR 1
Expand Down
17 changes: 15 additions & 2 deletions src/usb_descriptors.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@ enum
ITF_NUM_PROBE, // Old versions of Keil MDK only look at interface 0
ITF_NUM_CDC_COM,
ITF_NUM_CDC_DATA,
#if (CDC_UARTS == 2)
ITF_NUM_CDC_EX_COM,
ITF_NUM_CDC_EX_DATA,
#endif
ITF_NUM_TOTAL
};

Expand All @@ -80,10 +84,16 @@ enum
#define PROBE_OUT_EP_NUM 0x04
#define PROBE_IN_EP_NUM 0x85

#if (CDC_UARTS == 2)
#define CDC_EX_NOTIFICATION_EP_NUM 0x86
#define CDC_EX_DATA_OUT_EP_NUM 0x07
#define CDC_EX_DATA_IN_EP_NUM 0x88
#endif

#if (PICOPROBE_DEBUG_PROTOCOL == PROTO_DAP_V1)
#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN + TUD_HID_INOUT_DESC_LEN)
#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN * CDC_UARTS + TUD_HID_INOUT_DESC_LEN)
#else
#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN + TUD_VENDOR_DESC_LEN)
#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN * CDC_UARTS + TUD_VENDOR_DESC_LEN)
#endif

static uint8_t const desc_hid_report[] =
Expand Down Expand Up @@ -113,6 +123,9 @@ uint8_t const desc_configuration[] =
#endif
// Interface 1 + 2
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_COM, 6, CDC_NOTIFICATION_EP_NUM, 64, CDC_DATA_OUT_EP_NUM, CDC_DATA_IN_EP_NUM, 64),
#if (CDC_UARTS == 2)
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_EX_COM, 6, CDC_EX_NOTIFICATION_EP_NUM, 64, CDC_EX_DATA_OUT_EP_NUM, CDC_EX_DATA_IN_EP_NUM, 64),
#endif
};

// Invoked when received GET CONFIGURATION DESCRIPTOR
Expand Down