Convert to threaded operation by default
Rather than polling each interface in turn, execute the interface handling periodically. Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
This commit is contained in:
@@ -24,11 +24,16 @@
|
||||
*/
|
||||
|
||||
#include <pico/stdlib.h>
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
#include "tusb.h"
|
||||
|
||||
#include "picoprobe_config.h"
|
||||
|
||||
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];
|
||||
|
||||
@@ -40,7 +45,9 @@ void cdc_uart_init(void) {
|
||||
uart_init(PICOPROBE_UART_INTERFACE, PICOPROBE_UART_BAUDRATE);
|
||||
}
|
||||
|
||||
void cdc_task(void) {
|
||||
void cdc_task(void)
|
||||
{
|
||||
static int was_connected = 0;
|
||||
uint rx_len = 0;
|
||||
|
||||
// Consume uart fifo regardless even if not connected
|
||||
@@ -49,6 +56,7 @@ void cdc_task(void) {
|
||||
}
|
||||
|
||||
if (tud_cdc_connected()) {
|
||||
was_connected = 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... */
|
||||
@@ -69,17 +77,50 @@ void cdc_task(void) {
|
||||
tx_len = tud_cdc_read(tx_buf, watermark);
|
||||
uart_write_blocking(PICOPROBE_UART_INTERFACE, tx_buf, tx_len);
|
||||
}
|
||||
} else {
|
||||
/* Clear out characters that may be left
|
||||
- note that this doesn't include buffers already under hardware control */
|
||||
} else if (was_connected) {
|
||||
tud_cdc_write_clear();
|
||||
was_connected = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const* line_coding) {
|
||||
picoprobe_info("New baud rate %d\n", line_coding->bit_rate);
|
||||
uart_deinit(PICOPROBE_UART_INTERFACE);
|
||||
tud_cdc_write_clear();
|
||||
tud_cdc_read_flush();
|
||||
uart_init(PICOPROBE_UART_INTERFACE, line_coding->bit_rate);
|
||||
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();
|
||||
delayed = xTaskDelayUntil(&last_wake, interval);
|
||||
if (delayed == pdFALSE)
|
||||
last_wake = xTaskGetTickCount();
|
||||
}
|
||||
}
|
||||
|
||||
void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const* line_coding)
|
||||
{
|
||||
/* 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.
|
||||
*/
|
||||
uint32_t micros = (1000 * 1000 * 16 * 10) / MAX(line_coding->bit_rate, 1);
|
||||
|
||||
/* Modifying state, so park the thread before changing it. */
|
||||
vTaskSuspend(uart_taskhandle);
|
||||
interval = MAX(1, micros / ((1000 * 1000) / configTICK_RATE_HZ));
|
||||
picoprobe_info("New baud rate %d micros %d interval %u\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);
|
||||
vTaskResume(uart_taskhandle);
|
||||
}
|
||||
|
||||
void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts)
|
||||
{
|
||||
/* 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);
|
||||
else
|
||||
vTaskResume(uart_taskhandle);
|
||||
}
|
||||
|
||||
@@ -26,7 +26,10 @@
|
||||
#ifndef CDC_UART_H
|
||||
#define CDC_UART_H
|
||||
|
||||
void cdc_thread(void *ptr);
|
||||
void cdc_uart_init(void);
|
||||
void cdc_task(void);
|
||||
|
||||
extern TaskHandle_t uart_taskhandle;
|
||||
|
||||
#endif
|
||||
63
src/main.c
63
src/main.c
@@ -47,9 +47,40 @@
|
||||
static uint8_t TxDataBuffer[CFG_TUD_HID_EP_BUFSIZE];
|
||||
static uint8_t RxDataBuffer[CFG_TUD_HID_EP_BUFSIZE];
|
||||
|
||||
void dap_task(void);
|
||||
#define THREADED 1
|
||||
|
||||
#define UART_TASK_PRIO (tskIDLE_PRIORITY + 3)
|
||||
#define TUD_TASK_PRIO (tskIDLE_PRIORITY + 2)
|
||||
#define DAP_TASK_PRIO (tskIDLE_PRIORITY + 1)
|
||||
|
||||
static TaskHandle_t dap_taskhandle, tud_taskhandle;
|
||||
|
||||
void usb_thread(void *ptr)
|
||||
{
|
||||
do {
|
||||
tud_task();
|
||||
// Trivial delay to save power
|
||||
vTaskDelay(1);
|
||||
} while (1);
|
||||
}
|
||||
|
||||
void dap_thread(void *ptr)
|
||||
{
|
||||
uint32_t resp_len;
|
||||
do {
|
||||
if (tud_vendor_available()) {
|
||||
tud_vendor_read(RxDataBuffer, sizeof(RxDataBuffer));
|
||||
resp_len = DAP_ProcessCommand(RxDataBuffer, TxDataBuffer);
|
||||
tud_vendor_write(TxDataBuffer, resp_len);
|
||||
} else {
|
||||
// Trivial delay to save power
|
||||
vTaskDelay(2);
|
||||
}
|
||||
} while (1);
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
uint32_t resp_len;
|
||||
|
||||
board_init();
|
||||
usb_serial_init();
|
||||
@@ -64,31 +95,33 @@ int main(void) {
|
||||
|
||||
picoprobe_info("Welcome to Picoprobe!\n");
|
||||
|
||||
while (1) {
|
||||
tud_task(); // tinyusb device task
|
||||
if (THREADED) {
|
||||
/* UART needs to preempt USB as if we don't, characters get lost */
|
||||
xTaskCreate(cdc_thread, "UART", configMINIMAL_STACK_SIZE, NULL, UART_TASK_PRIO, &uart_taskhandle);
|
||||
xTaskCreate(usb_thread, "TUD", configMINIMAL_STACK_SIZE, NULL, TUD_TASK_PRIO, &tud_taskhandle);
|
||||
/* Lowest priority thread is debug - need to shuffle buffers before we can toggle swd... */
|
||||
xTaskCreate(dap_thread, "DAP", configMINIMAL_STACK_SIZE, NULL, DAP_TASK_PRIO, &dap_taskhandle);
|
||||
vTaskStartScheduler();
|
||||
}
|
||||
|
||||
while (!THREADED) {
|
||||
tud_task();
|
||||
cdc_task();
|
||||
#if (PICOPROBE_DEBUG_PROTOCOL == PROTO_OPENOCD_CUSTOM)
|
||||
probe_task();
|
||||
led_task();
|
||||
#elif (PICOPROBE_DEBUG_PROTOCOL == PROTO_DAP_V2)
|
||||
dap_task();
|
||||
if (tud_vendor_available()) {
|
||||
tud_vendor_read(RxDataBuffer, sizeof(RxDataBuffer));
|
||||
resp_len = DAP_ProcessCommand(RxDataBuffer, TxDataBuffer);
|
||||
tud_vendor_write(TxDataBuffer, resp_len);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void dap_task(void)
|
||||
{
|
||||
uint32_t count;
|
||||
uint32_t resp_len;
|
||||
if (tud_vendor_available()) {
|
||||
count = tud_vendor_read(RxDataBuffer, sizeof(RxDataBuffer));
|
||||
resp_len = DAP_ProcessCommand(RxDataBuffer, TxDataBuffer);
|
||||
tud_vendor_write(TxDataBuffer, resp_len);
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t tud_hid_get_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen)
|
||||
{
|
||||
// TODO not Implemented
|
||||
|
||||
Reference in New Issue
Block a user