Compare commits
20 Commits
pipeline-p
...
fix_debug
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ccd3fd6871 | ||
|
|
46eb924601 | ||
|
|
cdc33333c9 | ||
|
|
c8eb077c6c | ||
|
|
fbc4116141 | ||
|
|
364adfe1f1 | ||
|
|
08ed872793 | ||
|
|
5a9c6940c4 | ||
|
|
bb1c547b07 | ||
|
|
724e5de6c8 | ||
|
|
1ca6aa36dd | ||
|
|
db24224846 | ||
|
|
e187e5754b | ||
|
|
a2890561c0 | ||
|
|
156a33fa01 | ||
|
|
3bd58697e6 | ||
|
|
599ee88582 | ||
|
|
42d1ff28c8 | ||
|
|
fd445fd8c1 | ||
|
|
3e367acf66 |
@@ -35,14 +35,8 @@ target_include_directories(picoprobe PRIVATE
|
||||
|
||||
target_compile_options(picoprobe PRIVATE -Wall)
|
||||
|
||||
if (DEFINED ENV{PICOPROBE_LED})
|
||||
message("PICOPROBE_LED is defined as " $ENV{PICOPROBE_LED})
|
||||
target_compile_definitions(picoprobe PRIVATE PICOPROBE_LED=$ENV{PICOPROBE_LED})
|
||||
endif()
|
||||
|
||||
set(DBG_PIN_COUNT=4)
|
||||
|
||||
pico_generate_pio_header(picoprobe ${CMAKE_CURRENT_LIST_DIR}/src/probe.pio)
|
||||
pico_generate_pio_header(picoprobe ${CMAKE_CURRENT_LIST_DIR}/src/probe_oen.pio)
|
||||
|
||||
target_include_directories(picoprobe PRIVATE src)
|
||||
|
||||
|
||||
@@ -3,3 +3,9 @@ Picoprobe allows a Pico / RP2040 to be used as USB -> SWD and UART bridge. This
|
||||
|
||||
# Documentation
|
||||
Picoprobe documentation can be found in the [Pico Getting Started Guide](https://datasheets.raspberrypi.com/pico/getting-started-with-pico.pdf). See "Appendix A: Using Picoprobe".
|
||||
|
||||
# TODO
|
||||
- TinyUSB's vendor interface is FIFO-based and not packet-based. Using raw tx/rx callbacks is preferable as this stops DAP command batches from being concatenated, which confused openOCD.
|
||||
- Instead of polling, move the DAP thread to an asynchronously started/stopped one-shot operation to reduce CPU wakeups
|
||||
- AutoBaud selection, as PIO is a capable frequency counter
|
||||
- Possibly include RTT support
|
||||
|
||||
@@ -493,14 +493,22 @@ It is recommended to provide the following LEDs for status indication:
|
||||
- 1: Connect LED ON: debugger is connected to CMSIS-DAP Debug Unit.
|
||||
- 0: Connect LED OFF: debugger is not connected to CMSIS-DAP Debug Unit.
|
||||
*/
|
||||
__STATIC_INLINE void LED_CONNECTED_OUT (uint32_t bit) {}
|
||||
__STATIC_INLINE void LED_CONNECTED_OUT (uint32_t bit) {
|
||||
#ifdef PICOPROBE_DAP_CONNECTED_LED
|
||||
gpio_put(PICOPROBE_DAP_CONNECTED_LED, bit);
|
||||
#endif
|
||||
}
|
||||
|
||||
/** Debug Unit: Set status Target Running LED.
|
||||
\param bit status of the Target Running LED.
|
||||
- 1: Target Running LED ON: program execution in target started.
|
||||
- 0: Target Running LED OFF: program execution in target stopped.
|
||||
*/
|
||||
__STATIC_INLINE void LED_RUNNING_OUT (uint32_t bit) {}
|
||||
__STATIC_INLINE void LED_RUNNING_OUT (uint32_t bit) {
|
||||
#ifdef PICOPROBE_DAP_RUNNING_LED
|
||||
gpio_put(PICOPROBE_DAP_RUNNING_LED, bit);
|
||||
#endif
|
||||
}
|
||||
|
||||
///@}
|
||||
|
||||
|
||||
55
include/board_debugprobe_config.h
Normal file
55
include/board_debugprobe_config.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2023 Raspberry Pi (Trading) Ltd.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BOARD_DEBUGPROBE_H_
|
||||
#define BOARD_DEBUGPROBE_H_
|
||||
|
||||
#define PROBE_IO_SWDI
|
||||
#define PROBE_CDC_UART
|
||||
// No reset pin
|
||||
|
||||
// PIO config
|
||||
#define PROBE_SM 0
|
||||
#define PROBE_PIN_OFFSET 12
|
||||
#define PROBE_PIN_SWCLK (PROBE_PIN_OFFSET + 0)
|
||||
// For level-shifted input.
|
||||
#define PROBE_PIN_SWDI (PROBE_PIN_OFFSET + 1)
|
||||
#define PROBE_PIN_SWDIO (PROBE_PIN_OFFSET + 2)
|
||||
|
||||
// UART config
|
||||
#define PICOPROBE_UART_TX 4
|
||||
#define PICOPROBE_UART_RX 5
|
||||
#define PICOPROBE_UART_INTERFACE uart1
|
||||
#define PICOPROBE_UART_BAUDRATE 115200
|
||||
|
||||
#define PICOPROBE_USB_CONNECTED_LED 2
|
||||
#define PICOPROBE_DAP_CONNECTED_LED 15
|
||||
#define PICOPROBE_DAP_RUNNING_LED 16
|
||||
#define PICOPROBE_UART_RX_LED 7
|
||||
#define PICOPROBE_UART_TX_LED 8
|
||||
|
||||
#define PROBE_PRODUCT_STRING "Debug Probe (CMSIS-DAP)"
|
||||
|
||||
#endif
|
||||
82
include/board_example_config.h
Normal file
82
include/board_example_config.h
Normal file
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2023 Raspberry Pi (Trading) Ltd.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BOARD_EXAMPLE_H_
|
||||
#define BOARD_EXAMPLE_H_
|
||||
#error "Example board configuration requested - specify PICO_BOARD and re-run CMake."
|
||||
|
||||
/* Select one of these. */
|
||||
/* Direct connection - SWCLK/SWDIO on two GPIOs */
|
||||
#define PROBE_IO_RAW
|
||||
/* SWCLK connected to a GPIO, SWDO driven from a GPIO, SWDI sampled via a level shifter */
|
||||
#define PROBE_IO_SWDI
|
||||
/* Level-shifted SWCLK, SWDIO with separate SWDO, SWDI and OE_N pin */
|
||||
#define PROBE_IO_OEN
|
||||
|
||||
/* Include CDC interface to bridge to target UART. Omit if not used. */
|
||||
#define PROBE_CDC_UART
|
||||
/* Target reset GPIO (active-low). Omit if not used.*/
|
||||
#define PROBE_PIN_RESET 0
|
||||
|
||||
#define PROBE_SM 0
|
||||
#define PROBE_PIN_OFFSET 12
|
||||
/* PIO config for PROBE_IO_RAW */
|
||||
#if defined(PROBE_IO_RAW)
|
||||
#define PROBE_PIN_SWCLK (PROBE_PIN_OFFSET + 0)
|
||||
#define PROBE_PIN_SWDIO (PROBE_PIN_OFFSET + 1)
|
||||
#endif
|
||||
|
||||
/* PIO config for PROBE_IO_SWDI */
|
||||
#if defined(PROBE_IO_SWDI)
|
||||
#define PROBE_PIN_SWCLK (PROBE_PIN_OFFSET + 0)
|
||||
#define PROBE_PIN_SWDIO (PROBE_PIN_OFFSET + 1)
|
||||
#define PROBE_PIN_SWDI (PROBE_PIN_OFFSET + 2)
|
||||
#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)
|
||||
#define PROBE_PIN_SWDIOEN (PROBE_PIN_OFFSET + 0)
|
||||
#define PROBE_PIN_SWCLK (PROBE_PIN_OFFSET + 1)
|
||||
#define PROBE_PIN_SWDIO (PROBE_PIN_OFFSET + 2)
|
||||
#define PROBE_PIN_SWDI (PROBE_PIN_OFFSET + 3)
|
||||
#endif
|
||||
|
||||
#if defined(PROBE_CDC_UART)
|
||||
#define PICOPROBE_UART_TX 4
|
||||
#define PICOPROBE_UART_RX 5
|
||||
#define PICOPROBE_UART_INTERFACE uart1
|
||||
#define PICOPROBE_UART_BAUDRATE 115200
|
||||
#endif
|
||||
|
||||
/* LED config - some or all of these can be omitted if not used */
|
||||
#define PICOPROBE_USB_CONNECTED_LED 2
|
||||
#define PICOPROBE_DAP_CONNECTED_LED 15
|
||||
#define PICOPROBE_DAP_RUNNING_LED 16
|
||||
#define PICOPROBE_UART_RX_LED 7
|
||||
#define PICOPROBE_UART_TX_LED 8
|
||||
|
||||
#define PROBE_PRODUCT_STRING "Example Debug Probe"
|
||||
|
||||
#endif
|
||||
50
include/board_pico_config.h
Normal file
50
include/board_pico_config.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2023 Raspberry Pi (Trading) Ltd.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BOARD_PICO_H_
|
||||
#define BOARD_PICO_H_
|
||||
|
||||
#define PROBE_IO_RAW
|
||||
#define PROBE_CDC_UART
|
||||
|
||||
// PIO config
|
||||
#define PROBE_SM 0
|
||||
#define PROBE_PIN_OFFSET 2
|
||||
#define PROBE_PIN_SWCLK (PROBE_PIN_OFFSET + 0) // 2
|
||||
#define PROBE_PIN_SWDIO (PROBE_PIN_OFFSET + 1) // 3
|
||||
// Target reset config
|
||||
#define PROBE_PIN_RESET 1
|
||||
|
||||
// UART config
|
||||
#define PICOPROBE_UART_TX 4
|
||||
#define PICOPROBE_UART_RX 5
|
||||
#define PICOPROBE_UART_INTERFACE uart1
|
||||
#define PICOPROBE_UART_BAUDRATE 115200
|
||||
|
||||
#define PICOPROBE_USB_CONNECTED_LED 25
|
||||
|
||||
#define PROBE_PRODUCT_STRING "Picoprobe (CMSIS-DAP)"
|
||||
|
||||
#endif
|
||||
@@ -3,8 +3,6 @@
|
||||
# This can be dropped into an external project to help locate this SDK
|
||||
# It should be include()ed prior to project()
|
||||
|
||||
# todo document
|
||||
|
||||
if (DEFINED ENV{PICO_SDK_PATH} AND (NOT PICO_SDK_PATH))
|
||||
set(PICO_SDK_PATH $ENV{PICO_SDK_PATH})
|
||||
message("Using PICO_SDK_PATH from environment ('${PICO_SDK_PATH}')")
|
||||
@@ -20,8 +18,8 @@ if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_PATH} AND (NOT PICO_SDK_FETCH_FROM_GIT_P
|
||||
message("Using PICO_SDK_FETCH_FROM_GIT_PATH from environment ('${PICO_SDK_FETCH_FROM_GIT_PATH}')")
|
||||
endif ()
|
||||
|
||||
set(PICO_SDK_PATH "${PICO_SDK_PATH}" CACHE PATH "Path to the PICO SDK")
|
||||
set(PICO_SDK_FETCH_FROM_GIT "${PICO_SDK_FETCH_FROM_GIT}" CACHE BOOL "Set to ON to fetch copy of PICO SDK from git if not otherwise locatable")
|
||||
set(PICO_SDK_PATH "${PICO_SDK_PATH}" CACHE PATH "Path to the Raspberry Pi Pico SDK")
|
||||
set(PICO_SDK_FETCH_FROM_GIT "${PICO_SDK_FETCH_FROM_GIT}" CACHE BOOL "Set to ON to fetch copy of SDK from git if not otherwise locatable")
|
||||
set(PICO_SDK_FETCH_FROM_GIT_PATH "${PICO_SDK_FETCH_FROM_GIT_PATH}" CACHE FILEPATH "location to download SDK")
|
||||
|
||||
if (NOT PICO_SDK_PATH)
|
||||
@@ -31,20 +29,31 @@ if (NOT PICO_SDK_PATH)
|
||||
if (PICO_SDK_FETCH_FROM_GIT_PATH)
|
||||
get_filename_component(FETCHCONTENT_BASE_DIR "${PICO_SDK_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}")
|
||||
endif ()
|
||||
FetchContent_Declare(
|
||||
pico_sdk
|
||||
GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk
|
||||
GIT_TAG master
|
||||
)
|
||||
# GIT_SUBMODULES_RECURSE was added in 3.17
|
||||
if (${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.17.0")
|
||||
FetchContent_Declare(
|
||||
pico_sdk
|
||||
GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk
|
||||
GIT_TAG master
|
||||
GIT_SUBMODULES_RECURSE FALSE
|
||||
)
|
||||
else ()
|
||||
FetchContent_Declare(
|
||||
pico_sdk
|
||||
GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk
|
||||
GIT_TAG master
|
||||
)
|
||||
endif ()
|
||||
|
||||
if (NOT pico_sdk)
|
||||
message("Downloading PICO SDK")
|
||||
message("Downloading Raspberry Pi Pico SDK")
|
||||
FetchContent_Populate(pico_sdk)
|
||||
set(PICO_SDK_PATH ${pico_sdk_SOURCE_DIR})
|
||||
endif ()
|
||||
set(FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR_SAVE})
|
||||
else ()
|
||||
message(FATAL_ERROR
|
||||
"PICO SDK location was not specified. Please set PICO_SDK_PATH or set PICO_SDK_FETCH_FROM_GIT to on to fetch from git."
|
||||
"SDK location was not specified. Please set PICO_SDK_PATH or set PICO_SDK_FETCH_FROM_GIT to on to fetch from git."
|
||||
)
|
||||
endif ()
|
||||
endif ()
|
||||
@@ -56,9 +65,9 @@ endif ()
|
||||
|
||||
set(PICO_SDK_INIT_CMAKE_FILE ${PICO_SDK_PATH}/pico_sdk_init.cmake)
|
||||
if (NOT EXISTS ${PICO_SDK_INIT_CMAKE_FILE})
|
||||
message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' does not appear to contain the PICO SDK")
|
||||
message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' does not appear to contain the Raspberry Pi Pico SDK")
|
||||
endif ()
|
||||
|
||||
set(PICO_SDK_PATH ${PICO_SDK_PATH} CACHE PATH "Path to the PICO SDK" FORCE)
|
||||
set(PICO_SDK_PATH ${PICO_SDK_PATH} CACHE PATH "Path to the Raspberry Pi Pico SDK" FORCE)
|
||||
|
||||
include(${PICO_SDK_INIT_CMAKE_FILE})
|
||||
|
||||
@@ -71,7 +71,7 @@
|
||||
/* Memory allocation related definitions. */
|
||||
#define configSUPPORT_STATIC_ALLOCATION 0
|
||||
#define configSUPPORT_DYNAMIC_ALLOCATION 1
|
||||
#define configTOTAL_HEAP_SIZE (128*1024)
|
||||
#define configTOTAL_HEAP_SIZE (64*1024)
|
||||
#define configAPPLICATION_ALLOCATED_HEAP 0
|
||||
|
||||
/* Hook function related definitions. */
|
||||
|
||||
@@ -36,6 +36,17 @@ 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];
|
||||
// Actually s^-1 so 25ms
|
||||
#define DEBOUNCE_MS 40
|
||||
static uint debounce_ticks = 5;
|
||||
|
||||
#ifdef PICOPROBE_UART_TX_LED
|
||||
static uint tx_led_debounce;
|
||||
#endif
|
||||
|
||||
#ifdef PICOPROBE_UART_RX_LED
|
||||
static uint rx_led_debounce;
|
||||
#endif
|
||||
|
||||
void cdc_uart_init(void) {
|
||||
gpio_set_function(PICOPROBE_UART_TX, GPIO_FUNC_UART);
|
||||
@@ -61,21 +72,43 @@ void cdc_task(void)
|
||||
/* 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) {
|
||||
#ifdef PICOPROBE_UART_RX_LED
|
||||
gpio_put(PICOPROBE_UART_RX_LED, 1);
|
||||
rx_led_debounce = debounce_ticks;
|
||||
#endif
|
||||
written = MIN(tud_cdc_write_available(), rx_len);
|
||||
if (written > 0) {
|
||||
tud_cdc_write(rx_buf, written);
|
||||
tud_cdc_write_flush();
|
||||
}
|
||||
} else {
|
||||
#ifdef PICOPROBE_UART_RX_LED
|
||||
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));
|
||||
if (watermark > 0) {
|
||||
size_t tx_len;
|
||||
#ifdef PICOPROBE_UART_TX_LED
|
||||
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);
|
||||
} else {
|
||||
#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();
|
||||
@@ -102,11 +135,11 @@ void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const* line_coding)
|
||||
* 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",
|
||||
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();
|
||||
@@ -119,8 +152,16 @@ 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 && !rts) {
|
||||
vTaskSuspend(uart_taskhandle);
|
||||
else
|
||||
#ifdef PICOPROBE_UART_RX_LED
|
||||
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;
|
||||
#endif
|
||||
} else
|
||||
vTaskResume(uart_taskhandle);
|
||||
}
|
||||
|
||||
49
src/led.c
49
src/led.c
@@ -28,34 +28,25 @@
|
||||
|
||||
#include "picoprobe_config.h"
|
||||
|
||||
#define LED_COUNT_SHIFT 14
|
||||
#define LED_COUNT_MAX 5 * (1 << LED_COUNT_SHIFT)
|
||||
|
||||
static uint32_t led_count;
|
||||
|
||||
void led_init(void) {
|
||||
led_count = 0;
|
||||
|
||||
gpio_init(PICOPROBE_LED);
|
||||
gpio_set_dir(PICOPROBE_LED, GPIO_OUT);
|
||||
gpio_put(PICOPROBE_LED, 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void led_task(void) {
|
||||
if (led_count != 0) {
|
||||
--led_count;
|
||||
gpio_put(PICOPROBE_LED, !((led_count >> LED_COUNT_SHIFT) & 1));
|
||||
}
|
||||
}
|
||||
|
||||
void led_signal_activity(uint total_bits) {
|
||||
if (led_count == 0) {
|
||||
gpio_put(PICOPROBE_LED, 0);
|
||||
}
|
||||
|
||||
if (led_count < LED_COUNT_MAX) {
|
||||
led_count += total_bits;
|
||||
}
|
||||
#ifdef PICOPROBE_USB_CONNECTED_LED
|
||||
gpio_init(PICOPROBE_USB_CONNECTED_LED);
|
||||
gpio_set_dir(PICOPROBE_USB_CONNECTED_LED, GPIO_OUT);
|
||||
#endif
|
||||
#ifdef PICOPROBE_DAP_CONNECTED_LED
|
||||
gpio_init(PICOPROBE_DAP_CONNECTED_LED);
|
||||
gpio_set_dir(PICOPROBE_DAP_CONNECTED_LED, GPIO_OUT);
|
||||
#endif
|
||||
#ifdef PICOPROBE_DAP_RUNNING_LED
|
||||
gpio_init(PICOPROBE_DAP_RUNNING_LED);
|
||||
gpio_set_dir(PICOPROBE_DAP_RUNNING_LED, GPIO_OUT);
|
||||
#endif
|
||||
#ifdef PICOPROBE_UART_RX_LED
|
||||
gpio_init(PICOPROBE_UART_RX_LED);
|
||||
gpio_set_dir(PICOPROBE_UART_RX_LED, GPIO_OUT);
|
||||
#endif
|
||||
#ifdef PICOPROBE_UART_TX_LED
|
||||
gpio_init(PICOPROBE_UART_TX_LED);
|
||||
gpio_set_dir(PICOPROBE_UART_TX_LED, GPIO_OUT);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -27,7 +27,5 @@
|
||||
#define LED_H
|
||||
|
||||
void led_init(void);
|
||||
void led_task(void);
|
||||
void led_signal_activity(uint total_bits);
|
||||
|
||||
#endif
|
||||
|
||||
30
src/main.c
30
src/main.c
@@ -59,11 +59,22 @@ void usb_thread(void *ptr)
|
||||
{
|
||||
do {
|
||||
tud_task();
|
||||
#ifdef PICOPROBE_USB_CONNECTED_LED
|
||||
if (!gpio_get(PICOPROBE_USB_CONNECTED_LED) && tud_ready())
|
||||
gpio_put(PICOPROBE_USB_CONNECTED_LED, 1);
|
||||
else
|
||||
gpio_put(PICOPROBE_USB_CONNECTED_LED, 0);
|
||||
#endif
|
||||
// Trivial delay to save power
|
||||
vTaskDelay(1);
|
||||
} while (1);
|
||||
}
|
||||
|
||||
// Workaround API change in 0.13
|
||||
#if (TUSB_VERSION_MAJOR == 0) && (TUSB_VERSION_MINOR <= 12)
|
||||
#define tud_vendor_flush(x) ((void)0)
|
||||
#endif
|
||||
|
||||
void dap_thread(void *ptr)
|
||||
{
|
||||
uint32_t resp_len;
|
||||
@@ -72,26 +83,24 @@ void dap_thread(void *ptr)
|
||||
tud_vendor_read(RxDataBuffer, sizeof(RxDataBuffer));
|
||||
resp_len = DAP_ProcessCommand(RxDataBuffer, TxDataBuffer);
|
||||
tud_vendor_write(TxDataBuffer, resp_len);
|
||||
tud_vendor_flush();
|
||||
} else {
|
||||
// Trivial delay to save power
|
||||
vTaskDelay(2);
|
||||
vTaskDelay(1);
|
||||
}
|
||||
} while (1);
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
uint32_t resp_len;
|
||||
|
||||
board_init();
|
||||
usb_serial_init();
|
||||
cdc_uart_init();
|
||||
tusb_init();
|
||||
#if (PICOPROBE_DEBUG_PROTOCOL == PROTO_OPENOCD_CUSTOM)
|
||||
probe_gpio_init();
|
||||
probe_init();
|
||||
#else
|
||||
|
||||
DAP_Setup();
|
||||
#endif
|
||||
stdio_uart_init();
|
||||
|
||||
led_init();
|
||||
|
||||
picoprobe_info("Welcome to Picoprobe!\n");
|
||||
@@ -108,11 +117,10 @@ int main(void) {
|
||||
while (!THREADED) {
|
||||
tud_task();
|
||||
cdc_task();
|
||||
#if (PICOPROBE_DEBUG_PROTOCOL == PROTO_OPENOCD_CUSTOM)
|
||||
probe_task();
|
||||
led_task();
|
||||
#elif (PICOPROBE_DEBUG_PROTOCOL == PROTO_DAP_V2)
|
||||
|
||||
#if (PICOPROBE_DEBUG_PROTOCOL == PROTO_DAP_V2)
|
||||
if (tud_vendor_available()) {
|
||||
uint32_t resp_len;
|
||||
tud_vendor_read(RxDataBuffer, sizeof(RxDataBuffer));
|
||||
resp_len = DAP_ProcessCommand(RxDataBuffer, TxDataBuffer);
|
||||
tud_vendor_write(TxDataBuffer, resp_len);
|
||||
|
||||
@@ -26,53 +26,50 @@
|
||||
#ifndef PICOPROBE_H_
|
||||
#define PICOPROBE_H_
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
#if false
|
||||
#define picoprobe_info(format,args...) printf(format, ## args)
|
||||
#define picoprobe_info(format,args...) \
|
||||
do { \
|
||||
vTaskSuspendAll(); \
|
||||
printf(format, ## args); \
|
||||
xTaskResumeAll(); \
|
||||
} while (0)
|
||||
#else
|
||||
#define picoprobe_info(format,...) ((void)0)
|
||||
#endif
|
||||
|
||||
|
||||
#if false
|
||||
#define picoprobe_debug(format,args...) printf(format, ## args)
|
||||
#define picoprobe_debug(format,args...) \
|
||||
do { \
|
||||
vTaskSuspendAll(); \
|
||||
printf(format, ## args); \
|
||||
xTaskResumeAll(); \
|
||||
} while (0)
|
||||
#else
|
||||
#define picoprobe_debug(format,...) ((void)0)
|
||||
#endif
|
||||
|
||||
#if false
|
||||
#define picoprobe_dump(format,args...) printf(format, ## args)
|
||||
#define picoprobe_dump(format,args...)\
|
||||
do { \
|
||||
vTaskSuspendAll(); \
|
||||
printf(format, ## args); \
|
||||
xTaskResumeAll(); \
|
||||
} while (0)
|
||||
#else
|
||||
#define picoprobe_dump(format,...) ((void)0)
|
||||
#endif
|
||||
|
||||
// TODO tie this up with PICO_BOARD defines in the main SDK
|
||||
|
||||
// PIO config
|
||||
#define PROBE_SM 0
|
||||
#define PROBE_PIN_OFFSET 2
|
||||
#define PROBE_PIN_SWCLK (PROBE_PIN_OFFSET + 0) // 2
|
||||
#define PROBE_PIN_SWDIO (PROBE_PIN_OFFSET + 1) // 3
|
||||
#include "board_pico_config.h"
|
||||
//#include "board_debugprobe_config.h"
|
||||
//#include "board_example_config.h"
|
||||
|
||||
// Target reset config
|
||||
#define PROBE_PIN_RESET 6
|
||||
|
||||
// UART config
|
||||
#define PICOPROBE_UART_TX 4
|
||||
#define PICOPROBE_UART_RX 5
|
||||
#define PICOPROBE_UART_INTERFACE uart1
|
||||
#define PICOPROBE_UART_BAUDRATE 115200
|
||||
|
||||
// LED config
|
||||
#ifndef PICOPROBE_LED
|
||||
|
||||
#ifndef PICO_DEFAULT_LED_PIN
|
||||
#error PICO_DEFAULT_LED_PIN is not defined, run PICOPROBE_LED=<led_pin> cmake
|
||||
#elif PICO_DEFAULT_LED_PIN == -1
|
||||
#error PICO_DEFAULT_LED_PIN is defined as -1, run PICOPROBE_LED=<led_pin> cmake
|
||||
#else
|
||||
#define PICOPROBE_LED PICO_DEFAULT_LED_PIN
|
||||
#endif
|
||||
|
||||
#define PROTO_OPENOCD_CUSTOM 0
|
||||
#define PROTO_DAP_V1 1
|
||||
#define PROTO_DAP_V2 2
|
||||
|
||||
@@ -82,5 +79,3 @@
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
182
src/probe.c
182
src/probe.c
@@ -52,15 +52,6 @@ CU_REGISTER_DEBUG_PINS(probe_timing)
|
||||
|
||||
#define PROBE_BUF_SIZE 8192
|
||||
struct _probe {
|
||||
// Total length
|
||||
uint tx_len;
|
||||
// Data back to host
|
||||
uint8_t tx_buf[PROBE_BUF_SIZE];
|
||||
|
||||
// CMD / Data RX'd from
|
||||
uint rx_len;
|
||||
uint8_t rx_buf[PROBE_BUF_SIZE];
|
||||
|
||||
// PIO offset
|
||||
uint offset;
|
||||
uint initted;
|
||||
@@ -68,25 +59,6 @@ struct _probe {
|
||||
|
||||
static struct _probe probe;
|
||||
|
||||
enum PROBE_CMDS {
|
||||
PROBE_INVALID = 0, // Invalid command
|
||||
PROBE_WRITE_BITS = 1, // Host wants us to write bits
|
||||
PROBE_READ_BITS = 2, // Host wants us to read bits
|
||||
PROBE_SET_FREQ = 3, // Set TCK
|
||||
PROBE_RESET = 4, // Reset all state
|
||||
PROBE_TARGET_RESET = 5, // Reset target
|
||||
};
|
||||
|
||||
struct __attribute__((__packed__)) probe_cmd_hdr {
|
||||
uint8_t id;
|
||||
uint8_t cmd;
|
||||
uint32_t bits;
|
||||
};
|
||||
|
||||
struct __attribute__((__packed__)) probe_pkt_hdr {
|
||||
uint32_t total_packet_length;
|
||||
};
|
||||
|
||||
void probe_set_swclk_freq(uint freq_khz) {
|
||||
uint clk_sys_freq_khz = clock_get_hz(clk_sys) / 1000;
|
||||
picoprobe_info("Set swclk freq %dKHz sysclk %dkHz\n", freq_khz, clk_sys_freq_khz);
|
||||
@@ -97,8 +69,10 @@ void probe_set_swclk_freq(uint freq_khz) {
|
||||
|
||||
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);
|
||||
#endif
|
||||
}
|
||||
|
||||
void probe_write_bits(uint bit_count, uint32_t data_byte) {
|
||||
@@ -129,51 +103,21 @@ uint32_t probe_read_bits(uint bit_count) {
|
||||
|
||||
void probe_read_mode(void) {
|
||||
pio_sm_exec(pio0, PROBE_SM, pio_encode_jmp(probe.offset + probe_offset_in_posedge));
|
||||
while(pio0->dbg_padoe & (1 << PROBE_PIN_SWDIO));
|
||||
while(pio_sm_get_pc(pio0, PROBE_SM) != probe.offset + probe_offset_in_idle);
|
||||
}
|
||||
|
||||
void probe_write_mode(void) {
|
||||
pio_sm_exec(pio0, PROBE_SM, pio_encode_jmp(probe.offset + probe_offset_out_negedge));
|
||||
while(!(pio0->dbg_padoe & (1 << PROBE_PIN_SWDIO)));
|
||||
}
|
||||
|
||||
void probe_gpio_init()
|
||||
{
|
||||
// Funcsel pins
|
||||
pio_gpio_init(pio0, PROBE_PIN_SWCLK);
|
||||
pio_gpio_init(pio0, PROBE_PIN_SWDIO);
|
||||
// Make sure SWDIO has a pullup on it. Idle state is high
|
||||
gpio_pull_up(PROBE_PIN_SWDIO);
|
||||
while(pio_sm_get_pc(pio0, PROBE_SM) != probe.offset + probe_offset_out_idle);
|
||||
}
|
||||
|
||||
void probe_init() {
|
||||
// Target reset pin: pull up, input to emulate open drain pin
|
||||
gpio_pull_up(PROBE_PIN_RESET);
|
||||
// gpio_init will leave the pin cleared and set as input
|
||||
gpio_init(PROBE_PIN_RESET);
|
||||
if (!probe.initted) {
|
||||
uint offset = pio_add_program(pio0, &probe_program);
|
||||
probe.offset = offset;
|
||||
|
||||
pio_sm_config sm_config = probe_program_get_default_config(offset);
|
||||
|
||||
// Set SWCLK as a sideset pin
|
||||
sm_config_set_sideset_pins(&sm_config, PROBE_PIN_SWCLK);
|
||||
|
||||
// Set SWDIO offset
|
||||
sm_config_set_out_pins(&sm_config, PROBE_PIN_SWDIO, 1);
|
||||
sm_config_set_set_pins(&sm_config, PROBE_PIN_SWDIO, 1);
|
||||
sm_config_set_in_pins(&sm_config, PROBE_PIN_SWDIO);
|
||||
|
||||
// Set SWD and SWDIO pins as output to start. This will be set in the sm
|
||||
pio_sm_set_consecutive_pindirs(pio0, PROBE_SM, PROBE_PIN_OFFSET, 2, true);
|
||||
|
||||
// shift output right, autopull off, autopull threshold
|
||||
sm_config_set_out_shift(&sm_config, true, false, 0);
|
||||
// shift input right as swd data is lsb first, autopush off
|
||||
sm_config_set_in_shift(&sm_config, true, false, 0);
|
||||
|
||||
// Init SM with config
|
||||
probe_sm_init(&sm_config);
|
||||
pio_sm_init(pio0, PROBE_SM, offset, &sm_config);
|
||||
|
||||
// Set up divisor
|
||||
@@ -197,119 +141,3 @@ void probe_deinit(void)
|
||||
probe.initted = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void probe_handle_read(uint total_bits) {
|
||||
picoprobe_debug("Read %d bits\n", total_bits);
|
||||
probe_read_mode();
|
||||
|
||||
uint chunk;
|
||||
uint bits = total_bits;
|
||||
while (bits > 0) {
|
||||
if (bits > 8) {
|
||||
chunk = 8;
|
||||
} else {
|
||||
chunk = bits;
|
||||
}
|
||||
probe.tx_buf[probe.tx_len] = (uint8_t)probe_read_bits(chunk);
|
||||
probe.tx_len++;
|
||||
// Decrement remaining bits
|
||||
bits -= chunk;
|
||||
}
|
||||
}
|
||||
|
||||
void probe_handle_write(uint8_t *data, uint total_bits) {
|
||||
picoprobe_debug("Write %d bits\n", total_bits);
|
||||
|
||||
led_signal_activity(total_bits);
|
||||
|
||||
probe_write_mode();
|
||||
|
||||
uint chunk;
|
||||
uint bits = total_bits;
|
||||
while (bits > 0) {
|
||||
if (bits > 8) {
|
||||
chunk = 8;
|
||||
} else {
|
||||
chunk = bits;
|
||||
}
|
||||
|
||||
probe_write_bits(chunk, (uint32_t)*data++);
|
||||
bits -= chunk;
|
||||
}
|
||||
}
|
||||
|
||||
void probe_prepare_read_header(struct probe_cmd_hdr *hdr) {
|
||||
// We have a read so need to prefix the data with the cmd header
|
||||
if (probe.tx_len == 0) {
|
||||
// Reserve some space for probe_pkt_hdr
|
||||
probe.tx_len += sizeof(struct probe_pkt_hdr);
|
||||
}
|
||||
|
||||
memcpy((void*)&probe.tx_buf[probe.tx_len], hdr, sizeof(struct probe_cmd_hdr));
|
||||
probe.tx_len += sizeof(struct probe_cmd_hdr);
|
||||
}
|
||||
|
||||
void probe_handle_pkt(void) {
|
||||
uint8_t *pkt = &probe.rx_buf[0] + sizeof(struct probe_pkt_hdr);
|
||||
uint remaining = probe.rx_len - sizeof(struct probe_pkt_hdr);
|
||||
|
||||
DEBUG_PINS_SET(probe_timing, DBG_PIN_PKT);
|
||||
|
||||
picoprobe_debug("Processing packet of length %d\n", probe.rx_len);
|
||||
|
||||
probe.tx_len = 0;
|
||||
while (remaining) {
|
||||
struct probe_cmd_hdr *hdr = (struct probe_cmd_hdr*)pkt;
|
||||
uint data_bytes = DIV_ROUND_UP(hdr->bits, 8);
|
||||
pkt += sizeof(struct probe_cmd_hdr);
|
||||
remaining -= sizeof(struct probe_cmd_hdr);
|
||||
|
||||
if (hdr->cmd == PROBE_WRITE_BITS) {
|
||||
uint8_t *data = pkt;
|
||||
probe_handle_write(data, hdr->bits);
|
||||
pkt += data_bytes;
|
||||
remaining -= data_bytes;
|
||||
} else if (hdr->cmd == PROBE_READ_BITS) {
|
||||
probe_prepare_read_header(hdr);
|
||||
probe_handle_read(hdr->bits);
|
||||
} else if (hdr->cmd == PROBE_SET_FREQ) {
|
||||
probe_set_swclk_freq(hdr->bits);
|
||||
} else if (hdr->cmd == PROBE_RESET) {
|
||||
// TODO: Is there anything to do after a reset?
|
||||
// tx len and rx len should already be 0
|
||||
;
|
||||
} else if (hdr->cmd == PROBE_TARGET_RESET) {
|
||||
probe_assert_reset(hdr->bits);
|
||||
}
|
||||
}
|
||||
probe.rx_len = 0;
|
||||
|
||||
if (probe.tx_len) {
|
||||
// Fill in total packet length before sending
|
||||
struct probe_pkt_hdr *tx_hdr = (struct probe_pkt_hdr*)&probe.tx_buf[0];
|
||||
tx_hdr->total_packet_length = probe.tx_len;
|
||||
tud_vendor_write(&probe.tx_buf[0], probe.tx_len);
|
||||
picoprobe_debug("Picoprobe wrote %d response bytes\n", probe.tx_len);
|
||||
}
|
||||
probe.tx_len = 0;
|
||||
|
||||
DEBUG_PINS_CLR(probe_timing, DBG_PIN_PKT);
|
||||
}
|
||||
|
||||
// USB bits
|
||||
void probe_task(void) {
|
||||
if ( tud_vendor_available() ) {
|
||||
uint count = tud_vendor_read(&probe.rx_buf[probe.rx_len], 64);
|
||||
if (count == 0) {
|
||||
return;
|
||||
}
|
||||
probe.rx_len += count;
|
||||
}
|
||||
|
||||
if (probe.rx_len >= sizeof(struct probe_pkt_hdr)) {
|
||||
struct probe_pkt_hdr *pkt_hdr = (struct probe_pkt_hdr*)&probe.rx_buf[0];
|
||||
if (pkt_hdr->total_packet_length == probe.rx_len) {
|
||||
probe_handle_pkt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
13
src/probe.h
13
src/probe.h
@@ -26,6 +26,14 @@
|
||||
#ifndef PROBE_H_
|
||||
#define PROBE_H_
|
||||
|
||||
#if defined(PROBE_IO_RAW) || defined(PROBE_IO_SWDI)
|
||||
#include "probe.pio.h"
|
||||
#endif
|
||||
|
||||
#if defined(PROBE_IO_OEN)
|
||||
#include "probe_oen.pio.h"
|
||||
#endif
|
||||
|
||||
void probe_set_swclk_freq(uint freq_khz);
|
||||
void probe_write_bits(uint bit_count, uint32_t data_byte);
|
||||
uint32_t probe_read_bits(uint bit_count);
|
||||
@@ -33,11 +41,6 @@ uint32_t probe_read_bits(uint bit_count);
|
||||
void probe_read_mode(void);
|
||||
void probe_write_mode(void);
|
||||
|
||||
void probe_handle_read(uint total_bits);
|
||||
void probe_handle_write(uint8_t *data, uint total_bits);
|
||||
|
||||
void probe_task(void);
|
||||
void probe_gpio_init(void);
|
||||
void probe_init(void);
|
||||
void probe_deinit(void);
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
|
||||
public out_negedge:
|
||||
set pindirs, 1 side 0x0 ; Init OE clock 0
|
||||
public out_idle:
|
||||
pull ; Pull number of bits to shift -1 from tx fifo and put into output shift register
|
||||
mov x, osr ; mov bits to shift -1 from output shift register into x
|
||||
pull ; Pull data to shift out
|
||||
@@ -40,6 +41,7 @@ out_negedge_bitloop:
|
||||
|
||||
public in_posedge:
|
||||
set pindirs, 0 side 0x0 ; INIT IE clock 0
|
||||
public in_idle:
|
||||
pull ; Pull number of bits to shift -1 from tx fifo and put into output shift register
|
||||
mov x, osr ; mov bits to shift -1 from output shift register into x into x
|
||||
in_posedge_bitloop:
|
||||
@@ -47,3 +49,47 @@ in_posedge_bitloop:
|
||||
jmp x-- in_posedge_bitloop side 0x0 ;
|
||||
push ; Push to rx fifo when done
|
||||
jmp in_posedge ; Jump back to start
|
||||
|
||||
; Implement probe_gpio_init() and probe_sm_init() methods here - set pins, offsets, sidesets etc
|
||||
% c-sdk {
|
||||
|
||||
static inline void probe_gpio_init()
|
||||
{
|
||||
#if defined(PROBE_PIN_RESET)
|
||||
// Target reset pin: pull up, input to emulate open drain pin
|
||||
gpio_pull_up(PROBE_PIN_RESET);
|
||||
// gpio_init will leave the pin cleared and set as input
|
||||
gpio_init(PROBE_PIN_RESET);
|
||||
#endif
|
||||
// Funcsel pins
|
||||
pio_gpio_init(pio0, PROBE_PIN_SWCLK);
|
||||
pio_gpio_init(pio0, PROBE_PIN_SWDIO);
|
||||
// Make sure SWDIO has a pullup on it. Idle state is high
|
||||
gpio_pull_up(PROBE_PIN_SWDIO);
|
||||
}
|
||||
|
||||
static inline void probe_sm_init(pio_sm_config* sm_config) {
|
||||
|
||||
// Set SWCLK as a sideset pin
|
||||
sm_config_set_sideset_pins(sm_config, PROBE_PIN_SWCLK);
|
||||
|
||||
// Set SWDIO offset
|
||||
sm_config_set_out_pins(sm_config, PROBE_PIN_SWDIO, 1);
|
||||
sm_config_set_set_pins(sm_config, PROBE_PIN_SWDIO, 1);
|
||||
#ifdef PROBE_IO_SWDI
|
||||
sm_config_set_in_pins(sm_config, PROBE_PIN_SWDI);
|
||||
#else
|
||||
sm_config_set_in_pins(sm_config, PROBE_PIN_SWDIO);
|
||||
#endif
|
||||
|
||||
|
||||
// Set SWD and SWDIO pins as output to start. This will be set in the sm
|
||||
pio_sm_set_consecutive_pindirs(pio0, PROBE_SM, PROBE_PIN_OFFSET, 2, true);
|
||||
|
||||
// shift output right, autopull off, autopull threshold
|
||||
sm_config_set_out_shift(sm_config, true, false, 0);
|
||||
// shift input right as swd data is lsb first, autopush off
|
||||
sm_config_set_in_shift(sm_config, true, false, 0);
|
||||
}
|
||||
|
||||
%}
|
||||
|
||||
73
src/probe_oen.pio
Normal file
73
src/probe_oen.pio
Normal file
@@ -0,0 +1,73 @@
|
||||
; Output-enable active-low variant of the SWD probe
|
||||
|
||||
.program probe
|
||||
.side_set 2 opt
|
||||
|
||||
; SWDIO_OEN is pin 0, SWCLK pin 1, SWDIO (out) pin 2, SWDI (in) pin 3.
|
||||
; Pin 0 and 1 are sideset pins
|
||||
public out_negedge:
|
||||
set pindirs, 0x1 side 0x0 ; OE_N 0, data high, clock 0
|
||||
public out_idle:
|
||||
pull ; pull nbits - 1
|
||||
mov x, osr
|
||||
pull ; pull data
|
||||
public out_negedge_bitloop:
|
||||
out pins, 1 side 0x0
|
||||
jmp x-- out_negedge_bitloop side 0x2 ; OE_N 0, clock high
|
||||
set pins, 1 side 0x0 ; drive data high (idle bus state)
|
||||
push ; Push to rx fifo just so processor knows when done
|
||||
jmp out_negedge ; Wait for next transaction
|
||||
|
||||
public in_posedge:
|
||||
set pindirs, 0x0 side 0x1 ; OE_N 1, data high, clock 0
|
||||
public in_idle:
|
||||
pull
|
||||
mov x, osr
|
||||
in_posedge_bitloop:
|
||||
in pins, 1 side 0x1 ; OE_N 1, clock 0
|
||||
jmp x-- in_posedge_bitloop side 0x3 ; OE_N 1, clock 1
|
||||
push
|
||||
jmp in_posedge
|
||||
|
||||
|
||||
; Implement probe_gpio_init() and probe_sm_init() methods here - set pins, offsets, sidesets etc
|
||||
% c-sdk {
|
||||
|
||||
void probe_gpio_init()
|
||||
{
|
||||
#if defined(PROBE_PIN_RESET)
|
||||
// Target reset pin: pull up, input to emulate open drain pin
|
||||
gpio_pull_up(PROBE_PIN_RESET);
|
||||
// gpio_init will leave the pin cleared and set as input
|
||||
gpio_init(PROBE_PIN_RESET);
|
||||
#endif
|
||||
// Funcsel pins
|
||||
pio_gpio_init(pio0, PROBE_PIN_SWDIOEN);
|
||||
pio_gpio_init(pio0, PROBE_PIN_SWCLK);
|
||||
pio_gpio_init(pio0, PROBE_PIN_SWDIO);
|
||||
|
||||
// Make sure SWDIO has a pullup on it. Idle state is high
|
||||
gpio_pull_up(PROBE_PIN_SWDIO);
|
||||
gpio_pull_up(PROBE_PIN_SWDIOEN);
|
||||
}
|
||||
|
||||
void probe_sm_init(pio_sm_config* sm_config) {
|
||||
|
||||
// Set SWDIOEN and SWCLK as sideset pins
|
||||
sm_config_set_sideset_pins(&sm_config, PROBE_PIN_SWDIOEN);
|
||||
|
||||
// Set SWDIO offset
|
||||
sm_config_set_out_pins(sm_config, PROBE_PIN_SWDIO, 1);
|
||||
sm_config_set_set_pins(sm_config, PROBE_PIN_SWDIO, 1);
|
||||
sm_config_set_in_pins(sm_config, PROBE_PIN_SWDI);
|
||||
|
||||
// Set SWDIOEN, SWD and SWDIO pins as output to start. This will be set in the sm
|
||||
pio_sm_set_consecutive_pindirs(pio0, PROBE_SM, PROBE_PIN_OFFSET, 3, true);
|
||||
|
||||
// shift output right, autopull off, autopull threshold
|
||||
sm_config_set_out_shift(sm_config, true, false, 0);
|
||||
// shift input right as swd data is lsb first, autopush off
|
||||
sm_config_set_in_shift(sm_config, true, false, 0);
|
||||
}
|
||||
|
||||
%}
|
||||
@@ -74,6 +74,10 @@
|
||||
#define CFG_TUD_VENDOR_RX_BUFSIZE 8192
|
||||
#define CFG_TUD_VENDOR_TX_BUFSIZE 8192
|
||||
|
||||
#ifndef TUD_OPT_RP2040_USB_DEVICE_UFRAME_FIX
|
||||
#define TUD_OPT_RP2040_USB_DEVICE_UFRAME_FIX 1
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -47,11 +47,7 @@ tusb_desc_device_t const desc_device =
|
||||
.bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
|
||||
|
||||
.idVendor = 0x2E8A, // Pi
|
||||
#if (PICOPROBE_DEBUG_PROTOCOL == PROTO_OPENOCD_CUSTOM)
|
||||
.idProduct = 0x0004, // Picoprobe
|
||||
#else
|
||||
.idProduct = 0x000c, // CMSIS-DAP adapter
|
||||
#endif
|
||||
.idProduct = 0x000c, // CMSIS-DAP Debug Probe
|
||||
.bcdDevice = 0x0101, // Version 01.01
|
||||
.iManufacturer = 0x01,
|
||||
.iProduct = 0x02,
|
||||
@@ -137,11 +133,11 @@ char const* string_desc_arr [] =
|
||||
{
|
||||
(const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409)
|
||||
"Raspberry Pi", // 1: Manufacturer
|
||||
"Picoprobe CMSIS-DAP", // 2: Product
|
||||
PROBE_PRODUCT_STRING, // 2: Product
|
||||
usb_serial, // 3: Serial, uses flash unique ID
|
||||
"Picoprobe CMSIS-DAP v1", // 4: Interface descriptor for HID transport
|
||||
"Picoprobe CMSIS-DAP v2", // 5: Interface descriptor for Bulk transport
|
||||
"Picoprobe CDC-ACM UART", // 6: Interface descriptor for CDC
|
||||
"CMSIS-DAP v1 Interface", // 4: Interface descriptor for HID transport
|
||||
"CMSIS-DAP v2 Interface", // 5: Interface descriptor for Bulk transport
|
||||
"CDC-ACM UART Interface", // 6: Interface descriptor for CDC
|
||||
};
|
||||
|
||||
static uint16_t _desc_str[32];
|
||||
|
||||
Reference in New Issue
Block a user