Compare commits

..

9 Commits

Author SHA1 Message Date
Jonathan Bell
99c5156cd7 cdc_acm: turn on UART_TX LED when sending break signals
Software typically asserts line break for an extended period
(e.g. PuTTY will assert continuously until the next keypress), so
provide feedback via the LED.

Also declare variables used in both tinyusb callback and uart_thread context
as volatile.
2024-03-18 15:58:03 +00:00
Jonathan Bell
30a605f5cd cdc_uart: add CTS/RTS configuration options to board_example_config
For high data rate applications it's desirable to use hardware flow control
to prevent characters getting dropped when faced with the vagaries of RTOS
and kernel latencies. Adding PROBE_UART_HWFC enables the UART's CTS/RTS pins,
and SET_LINE_STATE messages no longer affect the RTS pin.
2024-03-18 15:16:37 +00:00
Jonathan Bell
68f01543c6 cdc_uart: add break handling
Implement break set/unset and declare the interface as capable of sending
line breaks.
2024-03-18 15:16:37 +00:00
geekman
a7aa0766f0 Make target reset functionality work out-of-the-box (#123)
* Fix up target reset functionality.

- Correct GPIO direction logic error in `probe_assert_reset`
- Remember to de-assert nRESET on deinit

* board_pico_config: use pin 1 for reset

This pin is normally used for UART debug output, but that is
undocumented. Repurpose it as reset output.

Signed-off-by: Sean Cross <sean@xobs.io>

* main: move stdio_uart_init() before DAP_Setup()

When using GP1 as a reset line, this is necessary to overwrite the
stdio function call from reusing the pin as a debug output.

Signed-off-by: Sean Cross <sean@xobs.io>

---------

Signed-off-by: Sean Cross <sean@xobs.io>
Co-authored-by: Sean Cross <sean@xobs.io>
2024-03-18 15:12:46 +00:00
David Lynch
b09854c639 fix: Corrected typo in preprocessor ifdef
* Changed PROBE_UART_RX_LED to PROBE_UART_TX_LED in ifdef to control TX LED
2024-03-18 09:33:57 +00:00
Jonathan Bell
327e15f176 board_debug_probe_config.h - nit 2024-02-05 16:17:46 +00:00
Jonathan Bell
62f4a31335 Update README.md 2024-02-05 16:17:46 +00:00
Jonathan Bell
abf675ca8c More renaming
- Prefix DAP-specific defines with DAP_
- PROBE_ defines refer to config options selected by a board type
2024-02-05 16:17:46 +00:00
Jonathan Bell
d0c03d2564 Rename picoprobe to debugprobe
Picoprobe is a registered trademark. Rename to debugprobe, and make it clear
that the code in this repository is firmware for the Debug Probe.
2024-02-05 16:17:46 +00:00
7 changed files with 84 additions and 13 deletions

View File

@@ -37,6 +37,10 @@
/* Include CDC interface to bridge to target UART. Omit if not used. */
#define PROBE_CDC_UART
/* Board implements hardware flow control for UART RTS/CTS instead of ACM control */
#define PROBE_UART_HWFC
/* Target reset GPIO (active-low). Omit if not used.*/
#define PROBE_PIN_RESET 1
@@ -68,9 +72,17 @@
#define PROBE_UART_RX 5
#define PROBE_UART_INTERFACE uart1
#define PROBE_UART_BAUDRATE 115200
/* Flow control - some or all of these can be omitted if not used */
#if defined(PROBE_UART_HWFC)
/* Hardware flow control - see 1.4.3 in the RP2040 datasheet for valid pin settings */
#define PROBE_UART_CTS 6
#define PROBE_UART_RTS 7
#else
/* Software flow control - RTS and DTR can be omitted if not used */
#define PROBE_UART_RTS 9
#endif
#define PROBE_UART_DTR 10
#endif
/* LED config - some or all of these can be omitted if not used */

View File

@@ -49,4 +49,4 @@
#define PROBE_PRODUCT_STRING "Debugprobe on Pico (CMSIS-DAP)"
#endif
#endif

View File

@@ -33,6 +33,8 @@
TaskHandle_t uart_taskhandle;
TickType_t last_wake, interval = 100;
volatile TickType_t break_expiry;
volatile bool timed_break;
/* Max 1 FIFO worth of data */
static uint8_t tx_buf[32];
@@ -42,7 +44,7 @@ static uint8_t rx_buf[32];
static uint debounce_ticks = 5;
#ifdef PROBE_UART_TX_LED
static uint tx_led_debounce;
static volatile uint tx_led_debounce;
#endif
#ifdef PROBE_UART_RX_LED
@@ -56,11 +58,23 @@ void cdc_uart_init(void) {
gpio_set_pulls(PROBE_UART_RX, 1, 0);
uart_init(PROBE_UART_INTERFACE, PROBE_UART_BAUDRATE);
#ifdef PROBE_UART_HWFC
/* HWFC implies that hardware flow control is implemented and the
* UART operates in "full-duplex" mode (See USB CDC PSTN120 6.3.12).
* Default to pulling in the active direction, so an unconnected CTS
* behaves the same as if CTS were not enabled. */
gpio_set_pulls(PROBE_UART_CTS, 0, 1);
gpio_set_function(PROBE_UART_RTS, GPIO_FUNC_UART);
gpio_set_function(PROBE_UART_CTS, GPIO_FUNC_UART);
uart_set_hw_flow(PROBE_UART_INTERFACE, true, true);
#else
#ifdef PROBE_UART_RTS
gpio_init(PROBE_UART_RTS);
gpio_set_dir(PROBE_UART_RTS, GPIO_OUT);
gpio_put(PROBE_UART_RTS, 1);
#endif
#endif
#ifdef PROBE_UART_DTR
gpio_init(PROBE_UART_DTR);
gpio_set_dir(PROBE_UART_DTR, GPIO_OUT);
@@ -68,11 +82,12 @@ void cdc_uart_init(void) {
#endif
}
void cdc_task(void)
bool cdc_task(void)
{
static int was_connected = 0;
static uint cdc_tx_oe = 0;
uint rx_len = 0;
bool keep_alive = false;
// Consume uart fifo regardless even if not connected
while(uart_is_readable(PROBE_UART_INTERFACE) && (rx_len < sizeof(rx_buf))) {
@@ -126,23 +141,40 @@ void cdc_task(void)
gpio_put(PROBE_UART_TX_LED, 0);
#endif
}
/* Pending break handling */
if (timed_break) {
if (((int)break_expiry - (int)xTaskGetTickCount()) < 0) {
timed_break = false;
uart_set_break(PROBE_UART_INTERFACE, false);
tx_led_debounce = 0;
} else {
keep_alive = true;
}
}
} else if (was_connected) {
tud_cdc_write_clear();
uart_set_break(PROBE_UART_INTERFACE, false);
timed_break = false;
was_connected = 0;
tx_led_debounce = 0;
cdc_tx_oe = 0;
}
return keep_alive;
}
void cdc_thread(void *ptr)
{
BaseType_t delayed;
last_wake = xTaskGetTickCount();
bool keep_alive;
/* Threaded with a polling interval that scales according to linerate */
while (1) {
cdc_task();
delayed = xTaskDelayUntil(&last_wake, interval);
if (delayed == pdFALSE)
last_wake = xTaskGetTickCount();
keep_alive = cdc_task();
if (!keep_alive) {
delayed = xTaskDelayUntil(&last_wake, interval);
if (delayed == pdFALSE)
last_wake = xTaskGetTickCount();
}
}
}
@@ -229,10 +261,32 @@ void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts)
gpio_put(PROBE_UART_RX_LED, 0);
rx_led_debounce = 0;
#endif
#ifdef PROBE_UART_RX_LED
#ifdef PROBE_UART_TX_LED
gpio_put(PROBE_UART_TX_LED, 0);
tx_led_debounce = 0;
#endif
} else
vTaskResume(uart_taskhandle);
}
void tud_cdc_send_break_cb(uint8_t itf, uint16_t wValue) {
switch(wValue) {
case 0:
uart_set_break(PROBE_UART_INTERFACE, false);
timed_break = false;
break;
case 0xffff:
uart_set_break(PROBE_UART_INTERFACE, true);
timed_break = false;
gpio_put(PROBE_UART_TX_LED, 1);
tx_led_debounce = 1 << 30;
break;
default:
uart_set_break(PROBE_UART_INTERFACE, true);
timed_break = true;
gpio_put(PROBE_UART_TX_LED, 1);
break_expiry = xTaskGetTickCount() + (wValue * (configTICK_RATE_HZ / 1000));
tx_led_debounce = 1 << 30;
break;
}
}

View File

@@ -28,7 +28,7 @@
void cdc_thread(void *ptr);
void cdc_uart_init(void);
void cdc_task(void);
bool cdc_task(void);
extern TaskHandle_t uart_taskhandle;

View File

@@ -85,9 +85,9 @@ int main(void) {
usb_serial_init();
cdc_uart_init();
tusb_init();
stdio_uart_init();
DAP_Setup();
stdio_uart_init();
led_init();

View File

@@ -72,7 +72,7 @@ void probe_assert_reset(bool state)
{
#if defined(PROBE_PIN_RESET)
/* Change the direction to out to drive pin to 0 or to in to emulate open drain */
gpio_set_dir(PROBE_PIN_RESET, state);
gpio_set_dir(PROBE_PIN_RESET, state == 0 ? GPIO_OUT : GPIO_IN);
#endif
}
@@ -170,6 +170,9 @@ void probe_deinit(void)
probe_read_mode();
pio_sm_set_enabled(pio0, PROBE_SM, 0);
pio_remove_program(pio0, &probe_program, probe.offset);
probe_assert_reset(1); // de-assert nRESET
probe.initted = 0;
}
}

View File

@@ -97,7 +97,7 @@ uint8_t const * tud_hid_descriptor_report_cb(uint8_t itf)
return desc_hid_report;
}
uint8_t const desc_configuration[] =
uint8_t desc_configuration[] =
{
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0, 100),
// Interface 0
@@ -121,6 +121,8 @@ uint8_t const desc_configuration[] =
uint8_t const * tud_descriptor_configuration_cb(uint8_t index)
{
(void) index; // for multiple configurations
/* Hack in CAP_BREAK support */
desc_configuration[CONFIG_TOTAL_LEN - TUD_CDC_DESC_LEN + 8 + 9 + 5 + 5 + 4 - 1] = 0x6;
return desc_configuration;
}