Skip to content

Commit

Permalink
pbio/drv/ioport_debug_uart: Follow uart updates.
Browse files Browse the repository at this point in the history
This can be used to debug non-blocking protothreads like the Bluetooth driver. We need to explicitly call back to the relevant process since the uart drivers are no longer broadcasting to every process.
  • Loading branch information
laurensvalk committed Dec 2, 2024
1 parent 158cf0e commit 0309019
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 101 deletions.
3 changes: 1 addition & 2 deletions lib/pbio/drv/bluetooth/bluetooth_btstack.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,7 @@
#endif

#if 0
#include <pbdrv/../../drv/ioport/ioport_debug_uart.h>
#define DEBUG_PRINT pbdrv_ioport_debug_uart_printf
#define DEBUG_PRINT(...)
#else
#define DEBUG_PRINT(...)
#endif
Expand Down
32 changes: 17 additions & 15 deletions lib/pbio/drv/bluetooth/bluetooth_stm32_cc2640.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,26 +43,22 @@

#include "./bluetooth_stm32_cc2640.h"

#define DEBUG_LL (0x01)
#define DEBUG_PT (0x02)
PROCESS(pbdrv_bluetooth_spi_process, "Bluetooth SPI");

// Choose either/or DEBUG_LL | DEBUG_PT
#define DEBUG (0)
#define DEBUG_ON_LAST_UART_PORT (0)

#if DEBUG
#if DEBUG_ON_LAST_UART_PORT
#include <pbdrv/../../drv/ioport/ioport_debug_uart.h>
#endif
#if (DEBUG & DEBUG_LL)
#define DBG pbdrv_ioport_debug_uart_printf
#else
#define DBG(...)
#endif
#if (DEBUG & DEBUG_PT)
#define DEBUG_PRINT pbdrv_ioport_debug_uart_printf
#define DEBUG_PRINT(...)
#define DEBUG_PRINT_PT PBDRV_IOPORT_DEBUG_UART_PT_PRINTF
static void uart_poll_callback(pbdrv_uart_dev_t *uart) {
process_poll(&pbdrv_bluetooth_spi_process);
}
#else
#define DEBUG_PRINT_PT(...)
#define DBG(...)
#define DEBUG_PRINT(...)
#define DEBUG_PRINT_PT(...)
#endif

// hub name goes in special section so that it can be modified when flashing firmware
Expand Down Expand Up @@ -156,8 +152,6 @@ static uint16_t uart_service_handle, uart_service_end_handle, uart_rx_char_handl
// Nordic UART tx notifications enabled
static bool uart_tx_notify_en;

PROCESS(pbdrv_bluetooth_spi_process, "Bluetooth SPI");

LIST(task_queue);
static bool bluetooth_ready;
static pbdrv_bluetooth_on_event_t bluetooth_on_event;
Expand Down Expand Up @@ -2277,6 +2271,14 @@ PROCESS_THREAD(pbdrv_bluetooth_spi_process, ev, data) {

PROCESS_BEGIN();

#if DEBUG_ON_LAST_UART_PORT
// Wait for the UART to be ready for debugging.
while (pbdrv_ioport_debug_uart_init(uart_poll_callback) != PBIO_SUCCESS) {
etimer_set(&timer, 100);
PROCESS_WAIT_EVENT_UNTIL(ev == PROCESS_EVENT_TIMER && etimer_expired(&timer));
}
#endif // DEBUG_ON_LAST_UART_PORT

start:
// take Bluetooth chip out of reset
bluetooth_reset(RESET_STATE_OUT_HIGH);
Expand Down
72 changes: 10 additions & 62 deletions lib/pbio/drv/ioport/ioport_debug_uart.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@

#if PBDRV_CONFIG_IOPORT_DEBUG_UART

#error "This driver can currently not be used."

#include <stdio.h>
#include <string.h>
#include <stdarg.h>
Expand All @@ -22,16 +20,13 @@
#error "PBDRV_CONFIG_IOPORT_DEBUG_UART requires exactly one port"
#endif

static char buffer[64];
static pbdrv_uart_dev_t *debug_uart;

#define UART_TIMEOUT (250)
// Use globals for simplified debug macro inside protothreads.
struct pt debug_printf_thread;
char debug_buffer[64];
pbdrv_uart_dev_t *debug_uart;
pbio_error_t debug_err;

static pbio_error_t pbdrv_ioport_init(void) {
// UART already initialized.
if (debug_uart) {
return PBIO_SUCCESS;
}
pbio_error_t pbdrv_ioport_debug_uart_init(pbdrv_uart_poll_callback_t callback) {

// Get the debug uart from last port.
const pbdrv_ioport_pup_port_platform_data_t *port_data = &pbdrv_ioport_pup_platform_data.ports[PBDRV_CONFIG_IOPORT_NUM_DEV - 1];
Expand All @@ -41,6 +36,8 @@ static pbio_error_t pbdrv_ioport_init(void) {
return err;
}

pbdrv_uart_set_poll_callback(debug_uart, callback);

// Enable and configure uart.
const pbdrv_ioport_pup_pins_t *pins = &port_data->pins;
pbdrv_gpio_alt(&pins->uart_rx, pins->uart_alt);
Expand All @@ -52,60 +49,11 @@ static pbio_error_t pbdrv_ioport_init(void) {
return PBIO_SUCCESS;
}

pbio_error_t pbdrv_ioport_debug_uart_printf(const char *format, ...) {

// Get the debug uart.
pbio_error_t err = pbdrv_ioport_init();
if (err != PBIO_SUCCESS) {
return err;
}

// If still writing, just ignore this debug message.
err = pbdrv_uart_write_end(debug_uart);
if (err != PBIO_SUCCESS) {
return err;
}

// Buffer result.
va_list args;
va_start(args, format);
vsnprintf(buffer, sizeof(buffer), format, args);
va_end(args);

// Write to uart.
return pbdrv_uart_write_begin(debug_uart, (uint8_t *)buffer, strlen(buffer), UART_TIMEOUT);
}

// Protothread set up here for simplified debug macro inside protothreads.
struct pt printf_thread;

PT_THREAD(pbdrv_ioport_debug_uart_printf_thread(struct pt *pt, const char *format, ...)) {
static pbio_error_t err;

PT_BEGIN(pt);

// Only print if port initialized.
err = pbdrv_ioport_init();
if (err != PBIO_SUCCESS) {
PT_EXIT(pt);
}

// Buffer result.
void pbdrv_ioport_debug_uart_printf_buffer(const char *format, ...) {
va_list args;
va_start(args, format);
vsnprintf(buffer, sizeof(buffer), format, args);
vsnprintf(debug_buffer, sizeof(debug_buffer), format, args);
va_end(args);

// Wait for uart to be ready then write.
PT_WAIT_UNTIL((pt), (err = pbdrv_uart_write_begin(debug_uart, (uint8_t *)buffer, strlen(buffer), UART_TIMEOUT)) != PBIO_ERROR_AGAIN);
if (err != PBIO_SUCCESS) {
PT_EXIT(pt);
}

// Wait for uart to finish.
PT_WAIT_UNTIL((pt), (err = pbdrv_uart_write_end(debug_uart)) != PBIO_ERROR_AGAIN);

PT_END(pt);
}

#endif // PBDRV_CONFIG_IOPORT_DEBUG_UART
35 changes: 13 additions & 22 deletions lib/pbio/drv/ioport/ioport_debug_uart.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,28 +9,18 @@
#include <pbio/error.h>

#include <pbdrv/config.h>
#include <pbdrv/uart.h>

#if PBDRV_CONFIG_IOPORT_DEBUG_UART

extern struct pt printf_thread;
extern char debug_buffer[];
extern struct pt debug_printf_thread;
extern pbdrv_uart_dev_t *debug_uart;
extern pbio_error_t debug_err;

/**
* Prints debug information on the last ioport.
*
* Will not print anything if the debug uart is already in use by another
* debug message, to avoid blocking.
*
* Useful outside of a protothread or when timing is more critical while
* complete information is not.
*
* @param [in] format Format string.
* @param [in] ... Arguments.
*
* @return Error code.
*/
pbio_error_t pbdrv_ioport_debug_uart_printf(const char *format, ...);
PT_THREAD(pbdrv_ioport_debug_uart_debug_printf_thread(struct pt *pt, const char *format, ...));

PT_THREAD(pbdrv_ioport_debug_uart_printf_thread(struct pt *pt, const char *format, ...));
void pbdrv_ioport_debug_uart_printf_buffer(const char *format, ...);

/**
* Spawns a task to print debug information on the last ioport.
Expand All @@ -42,13 +32,14 @@ PT_THREAD(pbdrv_ioport_debug_uart_printf_thread(struct pt *pt, const char *forma
* @param [in] ... Format string and arguments.
*/
#define PBDRV_IOPORT_DEBUG_UART_PT_PRINTF(pt, ...) \
PT_SPAWN(pt, &printf_thread, pbdrv_ioport_debug_uart_printf_thread(&printf_thread, __VA_ARGS__))
pbdrv_ioport_debug_uart_printf_buffer(__VA_ARGS__); \
if (debug_uart) { \
PT_SPAWN(pt, &debug_printf_thread, pbdrv_uart_write(&debug_printf_thread, debug_uart, (uint8_t *)debug_buffer, strlen(debug_buffer), 250, &debug_err)); \
} \

#else // PBDRV_CONFIG_IOPORT_DEBUG_UART
pbio_error_t pbdrv_ioport_debug_uart_init(pbdrv_uart_poll_callback_t callback);

static inline pbio_error_t pbdrv_ioport_debug_uart_printf(const char *format, ...) {
return PBIO_ERROR_NOT_SUPPORTED;
}
#else // PBDRV_CONFIG_IOPORT_DEBUG_UART

#define PBDRV_IOPORT_DEBUG_UART_PT_PRINTF(pt, ...)

Expand Down

0 comments on commit 0309019

Please sign in to comment.