Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f030323119 | ||
|
|
89c9a7711f | ||
|
|
451513d4f6 | ||
|
|
ba204d0c24 | ||
|
|
e4585d551a | ||
|
|
46b9613d14 | ||
|
|
2bbe900d68 | ||
|
|
7410b45e1d | ||
|
|
920f717e71 | ||
|
|
34a4ba0e01 | ||
|
|
0476e9cae5 | ||
|
|
c0ff91421a | ||
|
|
b5962e0818 | ||
|
|
ddc028fe18 | ||
|
|
af2540b045 | ||
|
|
d5047e7ef8 |
2
.gitmodules
vendored
2
.gitmodules
vendored
@@ -3,4 +3,4 @@
|
||||
url = https://github.com/ARM-software/CMSIS_5
|
||||
[submodule "freertos"]
|
||||
path = freertos
|
||||
url = https://github.com/FreeRTOS/FreeRTOS-Kernel
|
||||
url = https://github.com/raspberrypi/FreeRTOS-Kernel
|
||||
|
||||
@@ -3,13 +3,18 @@ cmake_minimum_required(VERSION 3.12)
|
||||
include(pico_sdk_import.cmake)
|
||||
|
||||
set(FREERTOS_KERNEL_PATH ${CMAKE_CURRENT_LIST_DIR}/freertos)
|
||||
include(FreeRTOS_Kernel_import.cmake)
|
||||
include(freertos/portable/ThirdParty/GCC/RP2350_ARM_NTZ/FreeRTOS_Kernel_import.cmake)
|
||||
|
||||
project(debugprobe)
|
||||
|
||||
pico_sdk_init()
|
||||
|
||||
if (${PICO_SDK_VERSION_MAJOR} LESS 2)
|
||||
message(SEND_ERROR "Version 2 of the Pico SDK is required to compile this project. Please update your installation at ${PICO_SDK_PATH}")
|
||||
endif ()
|
||||
|
||||
add_executable(debugprobe
|
||||
src/probe_config.c
|
||||
src/led.c
|
||||
src/main.c
|
||||
src/usb_descriptors.c
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
# This is a copy of <FREERTOS_KERNEL_PATH>/portable/ThirdParty/GCC/RP2040/FREERTOS_KERNEL_import.cmake
|
||||
|
||||
# This can be dropped into an external project to help locate the FreeRTOS kernel
|
||||
# It should be include()ed prior to project(). Alternatively this file may
|
||||
# or the CMakeLists.txt in this directory may be included or added via add_subdirectory
|
||||
# respectively.
|
||||
|
||||
if (DEFINED ENV{FREERTOS_KERNEL_PATH} AND (NOT FREERTOS_KERNEL_PATH))
|
||||
set(FREERTOS_KERNEL_PATH $ENV{FREERTOS_KERNEL_PATH})
|
||||
message("Using FREERTOS_KERNEL_PATH from environment ('${FREERTOS_KERNEL_PATH}')")
|
||||
endif ()
|
||||
|
||||
set(FREERTOS_KERNEL_RP2040_RELATIVE_PATH "portable/ThirdParty/GCC/RP2040")
|
||||
# undo the above
|
||||
set(FREERTOS_KERNEL_RP2040_BACK_PATH "../../../..")
|
||||
|
||||
if (NOT FREERTOS_KERNEL_PATH)
|
||||
# check if we are inside the FreeRTOS kernel tree (i.e. this file has been included directly)
|
||||
get_filename_component(_ACTUAL_PATH ${CMAKE_CURRENT_LIST_DIR} REALPATH)
|
||||
get_filename_component(_POSSIBLE_PATH ${CMAKE_CURRENT_LIST_DIR}/${FREERTOS_KERNEL_RP2040_BACK_PATH}/${FREERTOS_KERNEL_RP2040_RELATIVE_PATH} REALPATH)
|
||||
if (_ACTUAL_PATH STREQUAL _POSSIBLE_PATH)
|
||||
get_filename_component(FREERTOS_KERNEL_PATH ${CMAKE_CURRENT_LIST_DIR}/${FREERTOS_KERNEL_RP2040_BACK_PATH} REALPATH)
|
||||
endif()
|
||||
if (_ACTUAL_PATH STREQUAL _POSSIBLE_PATH)
|
||||
get_filename_component(FREERTOS_KERNEL_PATH ${CMAKE_CURRENT_LIST_DIR}/${FREERTOS_KERNEL_RP2040_BACK_PATH} REALPATH)
|
||||
message("Setting FREERTOS_KERNEL_PATH to ${FREERTOS_KERNEL_PATH} based on location of FreeRTOS-Kernel-import.cmake")
|
||||
elseif (PICO_SDK_PATH AND EXISTS "${PICO_SDK_PATH}/../FreeRTOS-Kernel")
|
||||
set(FREERTOS_KERNEL_PATH ${PICO_SDK_PATH}/../FreeRTOS-Kernel)
|
||||
message("Defaulting FREERTOS_KERNEL_PATH as sibling of PICO_SDK_PATH: ${FREERTOS_KERNEL_PATH}")
|
||||
endif()
|
||||
endif ()
|
||||
|
||||
if (NOT FREERTOS_KERNEL_PATH)
|
||||
foreach(POSSIBLE_SUFFIX Source FreeRTOS-Kernel FreeRTOS/Source)
|
||||
# check if FreeRTOS-Kernel exists under directory that included us
|
||||
set(SEARCH_ROOT ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
get_filename_component(_POSSIBLE_PATH ${SEARCH_ROOT}/${POSSIBLE_SUFFIX} REALPATH)
|
||||
if (EXISTS ${_POSSIBLE_PATH}/${FREERTOS_KERNEL_RP2040_RELATIVE_PATH}/CMakeLists.txt)
|
||||
get_filename_component(FREERTOS_KERNEL_PATH ${_POSSIBLE_PATH} REALPATH)
|
||||
message("Setting FREERTOS_KERNEL_PATH to '${FREERTOS_KERNEL_PATH}' found relative to enclosing project")
|
||||
break()
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
if (NOT FREERTOS_KERNEL_PATH)
|
||||
message(FATAL_ERROR "FreeRTOS location was not specified. Please set FREERTOS_KERNEL_PATH.")
|
||||
endif()
|
||||
|
||||
set(FREERTOS_KERNEL_PATH "${FREERTOS_KERNEL_PATH}" CACHE PATH "Path to the FreeRTOS Kernel")
|
||||
|
||||
get_filename_component(FREERTOS_KERNEL_PATH "${FREERTOS_KERNEL_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}")
|
||||
if (NOT EXISTS ${FREERTOS_KERNEL_PATH})
|
||||
message(FATAL_ERROR "Directory '${FREERTOS_KERNEL_PATH}' not found")
|
||||
endif()
|
||||
if (NOT EXISTS ${FREERTOS_KERNEL_PATH}/${FREERTOS_KERNEL_RP2040_RELATIVE_PATH}/CMakeLists.txt)
|
||||
message(FATAL_ERROR "Directory '${FREERTOS_KERNEL_PATH}' does not contain an RP2040 port here: ${FREERTOS_KERNEL_RP2040_RELATIVE_PATH}")
|
||||
endif()
|
||||
set(FREERTOS_KERNEL_PATH ${FREERTOS_KERNEL_PATH} CACHE PATH "Path to the FreeRTOS_KERNEL" FORCE)
|
||||
|
||||
add_subdirectory(${FREERTOS_KERNEL_PATH}/${FREERTOS_KERNEL_RP2040_RELATIVE_PATH} FREERTOS_KERNEL)
|
||||
15
README.md
15
README.md
@@ -47,6 +47,21 @@ This will build with the configuration for the Pico and call the output program
|
||||
|
||||
Note that if you first ran through the whole sequence to compile for the Debug Probe, then you don't need to start back at the top. You can just go back to the `cmake` step and start from there.
|
||||
|
||||
# Building for the Pico 2
|
||||
|
||||
If using an existing debugprobe clone:
|
||||
- You must completely regenerate your build directory, or use a different one.
|
||||
- You must also sync and update submodules as rp2350 needs a downstream FreeRTOS port for now.
|
||||
- `PICO_SDK_PATH` must point to a version 2.0.0 or greater install.
|
||||
|
||||
|
||||
```
|
||||
git submodule sync
|
||||
git submodule update --init
|
||||
mkdir build-pico2
|
||||
cd build-pico2
|
||||
cmake -DDEBUG_ON_PICO=1 -DPICO_BOARD=pico2 -DPICO_PLATFORM=rp2350 ../
|
||||
```
|
||||
|
||||
# TODO
|
||||
- AutoBaud selection, as PIO is a capable frequency counter
|
||||
|
||||
2
freertos
2
freertos
Submodule freertos updated: 2dfdfc4ba4...aa52f214d3
@@ -502,8 +502,8 @@ It is recommended to provide the following LEDs for status indication:
|
||||
- 0: Connect LED OFF: debugger is not connected to CMSIS-DAP Debug Unit.
|
||||
*/
|
||||
__STATIC_INLINE void LED_CONNECTED_OUT (uint32_t bit) {
|
||||
#ifdef DEBUGPROBE_DAP_CONNECTED_LED
|
||||
gpio_put(DEBUGPROBE_DAP_CONNECTED_LED, bit);
|
||||
#ifdef PROBE_DAP_CONNECTED_LED
|
||||
gpio_put(PROBE_DAP_CONNECTED_LED, bit);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -513,8 +513,8 @@ __STATIC_INLINE void LED_CONNECTED_OUT (uint32_t bit) {
|
||||
- 0: Target Running LED OFF: program execution in target stopped.
|
||||
*/
|
||||
__STATIC_INLINE void LED_RUNNING_OUT (uint32_t bit) {
|
||||
#ifdef DEBUGPROBE_DAP_RUNNING_LED
|
||||
gpio_put(DEBUGPROBE_DAP_RUNNING_LED, bit);
|
||||
#ifdef PROBE_DAP_RUNNING_LED
|
||||
gpio_put(PROBE_DAP_RUNNING_LED, bit);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -56,7 +60,7 @@
|
||||
#endif
|
||||
|
||||
/* PIO config for PROBE_IO_OEN - note that SWDIOEN and SWCLK are both side_set signals, so must be consecutive. */
|
||||
#if defined(PROBE_IO_SWDIOEN)
|
||||
#if defined(PROBE_IO_OEN)
|
||||
#define PROBE_PIN_SWDIOEN (PROBE_PIN_OFFSET + 0)
|
||||
#define PROBE_PIN_SWCLK (PROBE_PIN_OFFSET + 1)
|
||||
#define PROBE_PIN_SWDIO (PROBE_PIN_OFFSET + 2)
|
||||
@@ -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 */
|
||||
|
||||
@@ -110,6 +110,13 @@
|
||||
#define configSUPPORT_PICO_SYNC_INTEROP 1
|
||||
#define configSUPPORT_PICO_TIME_INTEROP 1
|
||||
|
||||
/* RP2350 grows some features */
|
||||
#define configENABLE_FPU 1
|
||||
#define configENABLE_MPU 0
|
||||
#define configENABLE_TRUSTZONE 0
|
||||
#define configRUN_FREERTOS_SECURE_ONLY 1
|
||||
#define configMAX_SYSCALL_INTERRUPT_PRIORITY 16
|
||||
|
||||
#include <assert.h>
|
||||
/* Define to trap errors during development. */
|
||||
#define configASSERT(x) assert(x)
|
||||
|
||||
@@ -26,13 +26,14 @@
|
||||
#include <pico/stdlib.h>
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
#include "tusb.h"
|
||||
|
||||
#include "probe_config.h"
|
||||
|
||||
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 +43,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 +57,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 +81,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 +140,44 @@ 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);
|
||||
#ifdef PROBE_UART_TX_LED
|
||||
tx_led_debounce = 0;
|
||||
#endif
|
||||
} 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;
|
||||
#ifdef PROBE_UART_TX_LED
|
||||
tx_led_debounce = 0;
|
||||
#endif
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,7 +190,8 @@ void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const* line_coding)
|
||||
*/
|
||||
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);
|
||||
if (tud_cdc_connected())
|
||||
vTaskSuspend(uart_taskhandle);
|
||||
interval = MAX(1, micros / ((1000 * 1000) / configTICK_RATE_HZ));
|
||||
debounce_ticks = MAX(1, configTICK_RATE_HZ / (interval * DEBOUNCE_MS));
|
||||
probe_info("New baud rate %ld micros %ld interval %lu\n",
|
||||
@@ -209,7 +245,10 @@ void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const* line_coding)
|
||||
}
|
||||
|
||||
uart_set_format(PROBE_UART_INTERFACE, data_bits, stop_bits, parity);
|
||||
vTaskResume(uart_taskhandle);
|
||||
/* Windows likes to arbitrarily set/get line coding after dtr/rts changes, so
|
||||
* don't resume if we shouldn't */
|
||||
if(tud_cdc_connected())
|
||||
vTaskResume(uart_taskhandle);
|
||||
}
|
||||
|
||||
void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts)
|
||||
@@ -223,7 +262,7 @@ 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) {
|
||||
if (!dtr) {
|
||||
vTaskSuspend(uart_taskhandle);
|
||||
#ifdef PROBE_UART_RX_LED
|
||||
gpio_put(PROBE_UART_RX_LED, 0);
|
||||
@@ -236,3 +275,32 @@ void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts)
|
||||
} 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;
|
||||
#ifdef PROBE_UART_TX_LED
|
||||
tx_led_debounce = 0;
|
||||
#endif
|
||||
break;
|
||||
case 0xffff:
|
||||
uart_set_break(PROBE_UART_INTERFACE, true);
|
||||
timed_break = false;
|
||||
#ifdef PROBE_UART_TX_LED
|
||||
gpio_put(PROBE_UART_TX_LED, 1);
|
||||
tx_led_debounce = 1 << 30;
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
uart_set_break(PROBE_UART_INTERFACE, true);
|
||||
timed_break = true;
|
||||
#ifdef PROBE_UART_TX_LED
|
||||
gpio_put(PROBE_UART_TX_LED, 1);
|
||||
tx_led_debounce = 1 << 30;
|
||||
#endif
|
||||
break_expiry = xTaskGetTickCount() + (wValue * (configTICK_RATE_HZ / 1000));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
84
src/main.c
84
src/main.c
@@ -31,7 +31,11 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#if PICO_SDK_VERSION_MAJOR >= 2
|
||||
#include "bsp/board_api.h"
|
||||
#else
|
||||
#include "bsp/board.h"
|
||||
#endif
|
||||
#include "tusb.h"
|
||||
|
||||
#include "probe_config.h"
|
||||
@@ -41,6 +45,7 @@
|
||||
#include "led.h"
|
||||
#include "tusb_edpt_handler.h"
|
||||
#include "DAP.h"
|
||||
#include "hardware/structs/usb.h"
|
||||
|
||||
// UART0 for debugprobe debug
|
||||
// UART1 for debugprobe to target device
|
||||
@@ -54,7 +59,36 @@ static uint8_t RxDataBuffer[CFG_TUD_HID_EP_BUFSIZE];
|
||||
#define TUD_TASK_PRIO (tskIDLE_PRIORITY + 2)
|
||||
#define DAP_TASK_PRIO (tskIDLE_PRIORITY + 1)
|
||||
|
||||
TaskHandle_t dap_taskhandle, tud_taskhandle;
|
||||
TaskHandle_t dap_taskhandle, tud_taskhandle, mon_taskhandle;
|
||||
|
||||
void dev_mon(void *ptr)
|
||||
{
|
||||
uint32_t sof[3];
|
||||
int i = 0;
|
||||
TickType_t wake;
|
||||
wake = xTaskGetTickCount();
|
||||
do {
|
||||
/* ~5 SOF events per tick */
|
||||
xTaskDelayUntil(&wake, 100);
|
||||
if (tud_connected() && !tud_suspended()) {
|
||||
sof[i++] = usb_hw->sof_rd & USB_SOF_RD_BITS;
|
||||
i = i % 3;
|
||||
} else {
|
||||
for (i = 0; i < 3; i++)
|
||||
sof[i] = 0;
|
||||
}
|
||||
if ((sof[0] | sof[1] | sof[2]) != 0) {
|
||||
if ((sof[0] == sof[1]) && (sof[1] == sof[2])) {
|
||||
probe_info("Watchdog timeout! Resetting USBD\n");
|
||||
/* uh oh, signal disconnect (implicitly resets the controller) */
|
||||
tud_deinit(0);
|
||||
/* Make sure the port got the message */
|
||||
xTaskDelayUntil(&wake, 1);
|
||||
tud_init(0);
|
||||
}
|
||||
}
|
||||
} while (1);
|
||||
}
|
||||
|
||||
void usb_thread(void *ptr)
|
||||
{
|
||||
@@ -68,8 +102,11 @@ void usb_thread(void *ptr)
|
||||
else
|
||||
gpio_put(PROBE_USB_CONNECTED_LED, 0);
|
||||
#endif
|
||||
// If suspended or disconnected, delay for 1ms (20 ticks)
|
||||
if (tud_suspended() || !tud_connected())
|
||||
xTaskDelayUntil(&wake, 20);
|
||||
// Go to sleep for up to a tick if nothing to do
|
||||
if (!tud_task_event_ready())
|
||||
else if (!tud_task_event_ready())
|
||||
xTaskDelayUntil(&wake, 1);
|
||||
} while (1);
|
||||
}
|
||||
@@ -80,6 +117,8 @@ void usb_thread(void *ptr)
|
||||
#endif
|
||||
|
||||
int main(void) {
|
||||
// Declare pins in binary information
|
||||
bi_decl_config();
|
||||
|
||||
board_init();
|
||||
usb_serial_init();
|
||||
@@ -94,11 +133,10 @@ int main(void) {
|
||||
probe_info("Welcome to debugprobe!\n");
|
||||
|
||||
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);
|
||||
#if PICO_RP2040
|
||||
xTaskCreate(dev_mon, "WDOG", configMINIMAL_STACK_SIZE, NULL, TUD_TASK_PRIO, &mon_taskhandle);
|
||||
#endif
|
||||
vTaskStartScheduler();
|
||||
}
|
||||
|
||||
@@ -182,6 +220,40 @@ bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_requ
|
||||
}
|
||||
#endif
|
||||
|
||||
void tud_suspend_cb(bool remote_wakeup_en)
|
||||
{
|
||||
probe_info("Suspended\n");
|
||||
/* Join DAP and UART threads? Or just suspend them, for transparency */
|
||||
vTaskSuspend(uart_taskhandle);
|
||||
vTaskSuspend(dap_taskhandle);
|
||||
/* slow down clk_sys for power saving ? */
|
||||
}
|
||||
|
||||
void tud_resume_cb(void)
|
||||
{
|
||||
probe_info("Resumed\n");
|
||||
vTaskResume(uart_taskhandle);
|
||||
vTaskResume(dap_taskhandle);
|
||||
}
|
||||
|
||||
void tud_unmount_cb(void)
|
||||
{
|
||||
probe_info("Disconnected\n");
|
||||
vTaskSuspend(uart_taskhandle);
|
||||
vTaskSuspend(dap_taskhandle);
|
||||
vTaskDelete(uart_taskhandle);
|
||||
vTaskDelete(dap_taskhandle);
|
||||
}
|
||||
|
||||
void tud_mount_cb(void)
|
||||
{
|
||||
probe_info("Connected, Configured\n");
|
||||
/* 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);
|
||||
/* 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);
|
||||
}
|
||||
|
||||
void vApplicationTickHook (void)
|
||||
{
|
||||
};
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
|
||||
#include "led.h"
|
||||
#include "probe_config.h"
|
||||
#include "probe.pio.h"
|
||||
#include "probe.h"
|
||||
#include "tusb.h"
|
||||
|
||||
#define DIV_ROUND_UP(m, n) (((m) + (n) - 1) / (n))
|
||||
|
||||
48
src/probe_config.c
Normal file
48
src/probe_config.c
Normal file
@@ -0,0 +1,48 @@
|
||||
#include "probe_config.h"
|
||||
#include "pico/binary_info.h"
|
||||
|
||||
|
||||
#define STR_HELPER(x) #x
|
||||
#define STR(x) STR_HELPER(x)
|
||||
|
||||
|
||||
void bi_decl_config()
|
||||
{
|
||||
#ifdef PROBE_PIN_RESET
|
||||
bi_decl(bi_1pin_with_name(PROBE_PIN_RESET, "PROBE RESET"));
|
||||
#endif
|
||||
|
||||
#ifdef PROBE_PIN_SWCLK
|
||||
bi_decl(bi_1pin_with_name(PROBE_PIN_SWCLK, "PROBE SWCLK"));
|
||||
#endif
|
||||
|
||||
#ifdef PROBE_PIN_SWDIO
|
||||
bi_decl(bi_1pin_with_name(PROBE_PIN_SWDIO, "PROBE SWDIO"));
|
||||
#endif
|
||||
|
||||
#ifdef PROBE_PIN_SWDI
|
||||
bi_decl(bi_1pin_with_name(PROBE_PIN_SWDI, "PROBE SWDI"));
|
||||
#endif
|
||||
|
||||
#ifdef PROBE_PIN_SWDIOEN
|
||||
bi_decl(bi_1pin_with_name(PROBE_PIN_SWDIOEN, "PROBE SWDIOEN"));
|
||||
#endif
|
||||
|
||||
#ifdef PROBE_CDC_UART
|
||||
bi_decl(bi_program_feature("PROBE UART INTERFACE " STR(PROBE_UART_INTERFACE)));
|
||||
bi_decl(bi_program_feature("PROBE UART BAUDRATE " STR(PROBE_UART_BAUDRATE)));
|
||||
bi_decl(bi_1pin_with_name(PROBE_UART_TX, "PROBE UART TX"));
|
||||
bi_decl(bi_1pin_with_name(PROBE_UART_RX, "PROBE UART RX"));
|
||||
#endif
|
||||
|
||||
#ifdef PROBE_UART_CTS
|
||||
bi_decl(bi_1pin_with_name(PROBE_UART_CTS, "PROBE UART CTS"));
|
||||
#endif
|
||||
#ifdef PROBE_UART_RTS
|
||||
bi_decl(bi_1pin_with_name(PROBE_UART_RTS, "PROBE UART RTS"));
|
||||
#endif
|
||||
#ifdef PROBE_UART_DTR
|
||||
bi_decl(bi_1pin_with_name(PROBE_UART_DTR, "PROBE UART DTR"));
|
||||
#endif
|
||||
|
||||
}
|
||||
@@ -72,6 +72,8 @@ do { \
|
||||
#endif
|
||||
//#include "board_example_config.h"
|
||||
|
||||
// Add the configuration to binary information
|
||||
void bi_decl_config();
|
||||
|
||||
#define PROTO_DAP_V1 1
|
||||
#define PROTO_DAP_V2 2
|
||||
|
||||
@@ -41,6 +41,15 @@ void dap_edpt_init(void) {
|
||||
|
||||
}
|
||||
|
||||
bool dap_edpt_deinit(void)
|
||||
{
|
||||
memset(DAPRequestBuffer, 0, sizeof(DAPRequestBuffer));
|
||||
memset(DAPResponseBuffer, 0, sizeof(DAPResponseBuffer));
|
||||
USBRequestBuffer.wptr = USBRequestBuffer.rptr = 0;
|
||||
USBResponseBuffer.wptr = USBResponseBuffer.rptr = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
void dap_edpt_reset(uint8_t __unused rhport)
|
||||
{
|
||||
itf_num = 0;
|
||||
@@ -198,7 +207,7 @@ void dap_thread(void *ptr)
|
||||
*/
|
||||
n = USBRequestBuffer.rptr;
|
||||
while (USBRequestBuffer.data[n % DAP_PACKET_COUNT][0] == ID_DAP_QueueCommands) {
|
||||
probe_info("%u %u DAP queued cmd %s len %02x\n",
|
||||
probe_info("%lu %lu DAP queued cmd %s len %02x\n",
|
||||
USBRequestBuffer.wptr, USBRequestBuffer.rptr,
|
||||
dap_cmd_string[USBRequestBuffer.data[n % DAP_PACKET_COUNT][0]], USBRequestBuffer.data[n % DAP_PACKET_COUNT][1]);
|
||||
USBRequestBuffer.data[n % DAP_PACKET_COUNT][0] = ID_DAP_ExecuteCommands;
|
||||
@@ -211,7 +220,7 @@ void dap_thread(void *ptr)
|
||||
}
|
||||
// Read a single packet from the USB buffer into the DAP Request buffer
|
||||
memcpy(DAPRequestBuffer, RD_SLOT_PTR(USBRequestBuffer), DAP_PACKET_SIZE);
|
||||
probe_info("%u %u DAP cmd %s len %02x\n",
|
||||
probe_info("%lu %lu DAP cmd %s len %02x\n",
|
||||
USBRequestBuffer.wptr, USBRequestBuffer.rptr,
|
||||
dap_cmd_string[DAPRequestBuffer[0]], DAPRequestBuffer[1]);
|
||||
USBRequestBuffer.rptr++;
|
||||
@@ -227,7 +236,7 @@ void dap_thread(void *ptr)
|
||||
}
|
||||
|
||||
_resp_len = DAP_ExecuteCommand(DAPRequestBuffer, DAPResponseBuffer);
|
||||
probe_info("%u %u DAP resp %s\n",
|
||||
probe_info("%lu %lu DAP resp %s\n",
|
||||
USBResponseBuffer.wptr, USBResponseBuffer.rptr,
|
||||
dap_cmd_string[DAPResponseBuffer[0]]);
|
||||
|
||||
@@ -262,6 +271,7 @@ void dap_thread(void *ptr)
|
||||
usbd_class_driver_t const _dap_edpt_driver =
|
||||
{
|
||||
.init = dap_edpt_init,
|
||||
.deinit = dap_edpt_deinit,
|
||||
.reset = dap_edpt_reset,
|
||||
.open = dap_edpt_open,
|
||||
.control_xfer_cb = dap_edpt_control_xfer_cb,
|
||||
|
||||
@@ -48,7 +48,7 @@ tusb_desc_device_t const desc_device =
|
||||
|
||||
.idVendor = 0x2E8A, // Pi
|
||||
.idProduct = 0x000c, // CMSIS-DAP Debug Probe
|
||||
.bcdDevice = 0x0103, // Version 01.03
|
||||
.bcdDevice = 0x0201, // Version 02.01
|
||||
.iManufacturer = 0x01,
|
||||
.iProduct = 0x02,
|
||||
.iSerialNumber = 0x03,
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user