From 5009a152801f3b14486cabffe81360603f48b44a Mon Sep 17 00:00:00 2001 From: jaseg Date: Tue, 6 Nov 2018 09:15:37 +0900 Subject: DMA-supported LOG_PRINTF works --- CMakeLists.txt | 10 +++- src/demo.c | 9 ++- src/tinyprintf.c | 2 + src/usart_helpers.c | 156 ++++++++++++++++++++-------------------------------- src/usart_helpers.h | 7 ++- 5 files changed, 80 insertions(+), 104 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7b28316..5abb56c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,8 +17,10 @@ set (USE_STM32F4_FS TRUE CACHE BOOL "Use USB full speed (FS) host periphery") set (USE_STM32F4_HS TRUE CACHE BOOL "Use USB high speed (HS) host periphery") set (USE_USART_DEBUG TRUE CACHE BOOL "Enable human-readable serial debug output") set (DEBUG_USART USART1 CACHE STRING "USART to use for debug output") -set (DEBUG_USART_DMA DMA2 CACHE STRING "DMA controller to use for debug usart") +set (DEBUG_USART_BAUDRATE 1000000 CACHE STRING "Baud rate to use for debug USART") +set (DEBUG_USART_DMA_NUM 2 CACHE STRING "DMA controller number to use for debug usart") set (DEBUG_USART_DMA_STREAM_NUM 7 CACHE STRING "DMA stream number to use for debug usart. This must be the stream mapped to the [DEBUG_USART]_TX channel") +set (DEBUG_USART_DMA_CHANNEL_NUM 4 CACHE STRING "DMA channel number to use for debug usart. This must be the channel mapped to the [DEBUG_USART]_TX channel") # Set compiler and linker flags @@ -90,6 +92,12 @@ if (USE_USART_DEBUG) endif (USE_USART_DEBUG) message (STATUS "Setup done") +add_definitions (-DDEBUG_USART=${DEBUG_USART}) +add_definitions (-DDEBUG_USART_BAUDRATE=${DEBUG_USART_BAUDRATE}) +add_definitions (-DDEBUG_USART_DMA_NUM=${DEBUG_USART_DMA_NUM}) +add_definitions (-DDEBUG_USART_DMA_STREAM_NUM=${DEBUG_USART_DMA_STREAM_NUM}) +add_definitions (-DDEBUG_USART_DMA_CHANNEL_NUM=${DEBUG_USART_DMA_CHANNEL_NUM}) + add_custom_target (README.md SOURCES README.md ) diff --git a/src/demo.c b/src/demo.c index d61460f..4458dd6 100644 --- a/src/demo.c +++ b/src/demo.c @@ -38,8 +38,6 @@ #include #include -#define UNUSED(var) ((void)var) - static inline void delay_ms_busy_loop(uint32_t ms) { for (volatile uint32_t i = 0; i < 14903*ms; i++); } @@ -55,8 +53,8 @@ static void clock_setup(void) { rcc_periph_clock_enable(RCC_USART1); rcc_periph_clock_enable(RCC_USART2); rcc_periph_clock_enable(RCC_OTGFS); - rcc_periph_clock_enable(RCC_OTGHS); rcc_periph_clock_enable(RCC_TIM6); + rcc_periph_clock_enable(RCC_DMA2); } @@ -159,9 +157,14 @@ int main(void) LOG_PRINTF("USB init complete\n"); + int i = 0, j = 0; while (23) { usbh_poll(tim6_get_time_us()); delay_ms_busy_loop(1); /* approx 1ms interval between usbh_poll() */ + if (i++ == 200) { + i = 0; + LOG_PRINTF("Loop iteration %d\n", j++); + } } return 0; } diff --git a/src/tinyprintf.c b/src/tinyprintf.c index bb22700..0f9ec4e 100644 --- a/src/tinyprintf.c +++ b/src/tinyprintf.c @@ -380,7 +380,9 @@ void tfp_format(void *putp, putcf putf, const char *fmt, va_list va) lng = 2; # endif #endif + __attribute__((fallthrough)); case 'x': + __attribute__((fallthrough)); case 'X': p.base = 16; p.uc = (ch == 'X')?1:0; diff --git a/src/usart_helpers.c b/src/usart_helpers.c index 97aa0f0..6ba9cea 100644 --- a/src/usart_helpers.c +++ b/src/usart_helpers.c @@ -31,86 +31,12 @@ #include #include #include +#include +#include +#include -uint32_t debug_usart = 0; - -#define USART_FIFO_OUT_SIZE (4096) -uint8_t usart_fifo_out_data[USART_FIFO_OUT_SIZE]; -uint32_t usart_fifo_out_len = 0; -uint32_t usart_fifo_out_index = 0; - -#define USART_FIFO_IN_SIZE (1024) -uint8_t usart_fifo_in_data[USART_FIFO_IN_SIZE]; -uint32_t usart_fifo_in_len = 0; -uint32_t usart_fifo_in_index = 0; - -static uint32_t usart = 0; - -static uint8_t usart_fifo_pop(void) -{ - uint8_t ret; - usart_fifo_out_len--; - ret = usart_fifo_out_data[usart_fifo_out_index]; - usart_fifo_out_index++; - if (usart_fifo_out_index == USART_FIFO_OUT_SIZE ) { - usart_fifo_out_index = 0; - } - return ret; -} - -static void usart_fifo_push(uint8_t aData) -{ - uint32_t i; - if( (usart_fifo_out_len + 1) == USART_FIFO_OUT_SIZE)//overflow - { - usart_fifo_out_len = 0; - LOG_PRINTF("OVERFLOW!"); - return; - } - - i = usart_fifo_out_index + usart_fifo_out_len; - if (i >= USART_FIFO_OUT_SIZE) { - i -= USART_FIFO_OUT_SIZE; - } - usart_fifo_out_data[i] = aData; - usart_fifo_out_len++; -} - - -static uint8_t usart_fifo_in_pop(void) -{ - uint8_t ret; - usart_fifo_in_len--; - ret = usart_fifo_in_data[usart_fifo_in_index]; - usart_fifo_in_index++; - if (usart_fifo_in_index == USART_FIFO_IN_SIZE ) { - usart_fifo_in_index = 0; - } - return ret; -} - -static void usart_fifo_in_push(uint8_t aData) -{ - uint32_t i; - if( (usart_fifo_in_len + 1) == USART_FIFO_IN_SIZE)//overflow - { - usart_fifo_in_len = 0; - return; - } - - i = usart_fifo_in_index + usart_fifo_in_len; - if (i >= USART_FIFO_IN_SIZE) { - i -= USART_FIFO_IN_SIZE; - } - usart_fifo_in_data[i] = aData; - usart_fifo_in_len++; -} - -static void putf(void *arg, char c) -{ - //unused argument - (void)arg; - +static void putf(void *file, char c) { + UNUSED(file); usart_fifo_push(c); } @@ -135,41 +61,77 @@ void usart_init(uint32_t arg_usart, uint32_t baudrate) #define WRITE_BUF_LEN 256 struct tx_buf { - buf[WRITE_BUF_LEN]; - int pos; + uint8_t buf[WRITE_BUF_LEN]; + uint32_t pos; } tx_buf[2]; int tx_buf_active; -#define DEBUG_USART_DMA_STREAM (DMA_STREAM##DEBUG_USART_DMA_STREAM_NUM) -#define DEBUG_USART_NVIC_DMA_IRQ (NVIC_##DEBUG_USART_DMA##_##DEBUG_USART_DMA_STREAM##_IRQ) -#define DEBUG_USART_DMA_ISR (DEBUG_USART_DMA##_##DEBUG_USART_DMA_STREAM##_IRQHandler) +/* This macro abomination templates a bunch of dma-specific register/constant names from preprocessor macros passed in + * from cmake. */ +#define DEBUG_USART_DMA_PASTE(num) DMA ## num +#define DEBUG_USART_DMA_EVAL(num) DEBUG_USART_DMA_PASTE(num) +#define DEBUG_USART_DMA DEBUG_USART_DMA_EVAL(DEBUG_USART_DMA_NUM) + +#define DEBUG_USART_DMA_STREAM_PASTE(num) DMA_STREAM ## num +#define DEBUG_USART_DMA_STREAM_EVAL(num) DEBUG_USART_DMA_STREAM_PASTE(num) +#define DEBUG_USART_DMA_STREAM DEBUG_USART_DMA_STREAM_EVAL(DEBUG_USART_DMA_STREAM_NUM) + +#define DEBUG_USART_NVIC_DMA_IRQ_PASTE(dma, stream) NVIC_ ## DMA ## dma ## _ ## STREAM ## stream ## _IRQ +#define DEBUG_USART_NVIC_DMA_IRQ_EVAL(dma, stream) DEBUG_USART_NVIC_DMA_IRQ_PASTE(dma, stream) +#define DEBUG_USART_NVIC_DMA_IRQ DEBUG_USART_NVIC_DMA_IRQ_EVAL(DEBUG_USART_DMA_NUM, DEBUG_USART_DMA_STREAM_NUM) + +#define DEBUG_USART_DMA_ISR_PASTE(dma, stream) DMA ## dma ## _ ## STREAM ## stream ## _IRQHandler +#define DEBUG_USART_DMA_ISR_EVAL(dma, stream) DEBUG_USART_DMA_ISR_PASTE(dma, stream) +#define DEBUG_USART_DMA_ISR DEBUG_USART_DMA_ISR_EVAL(DEBUG_USART_DMA_NUM, DEBUG_USART_DMA_STREAM_NUM) + +#define DEBUG_USART_DMA_CHANNEL_PASTE(channel) DMA_SxCR_CHSEL_ ## channel +#define DEBUG_USART_DMA_CHANNEL_EVAL(channel) DEBUG_USART_DMA_CHANNEL_PASTE(channel) +#define DEBUG_USART_DMA_CHANNEL DEBUG_USART_DMA_CHANNEL_EVAL(DEBUG_USART_DMA_CHANNEL_NUM) + void debug_usart_init() { tx_buf[0].pos = tx_buf[1].pos = 0; tx_buf_active = 1; - usart_init(DEBUG_USART, DEBUG_BAUDRATE); + usart_init(DEBUG_USART, DEBUG_USART_BAUDRATE); dma_stream_reset(DEBUG_USART_DMA, DEBUG_USART_DMA_STREAM); - dma_set_peripheral_address(DEBUG_USART_DMA, DEBUG_USART_DMA_STREAM, (uint32_t)&DEBUG_USART##_DR); - dma_set_memory_address(DEBUG_USART_DMA, DEBUG_USART_DMA_STREAM, (uint32_t)tx_buf[1].buf); - dma_set_number_of_data(DEBUG_USART_DMA, DEBUG_USART_DMA_STREAM, size); - dma_set_read_from_memory(DEBUG_USART_DMA, DEBUG_USART_DMA_STREAM); + dma_channel_select(DEBUG_USART_DMA, DEBUG_USART_DMA_STREAM, DEBUG_USART_DMA_CHANNEL); + dma_set_peripheral_address(DEBUG_USART_DMA, DEBUG_USART_DMA_STREAM, (uint32_t)&USART_DR(DEBUG_USART)); + dma_set_transfer_mode(DEBUG_USART_DMA, DEBUG_USART_DMA_STREAM, DMA_SxCR_DIR_MEM_TO_PERIPHERAL); dma_enable_memory_increment_mode(DEBUG_USART_DMA, DEBUG_USART_DMA_STREAM); - dma_set_peripheral_size(DEBUG_USART_DMA, DEBUG_USART_DMA_STREAM, DMA_CCR_PSIZE_8BIT); - dma_set_memory_size(DEBUG_USART_DMA, DEBUG_USART_DMA_STREAM, DMA_CCR_MSIZE_8BIT); - dma_set_priority(DEBUG_USART_DMA, DEBUG_USART_DMA_STREAM, DMA_CCR_PL_VERY_HIGH); + dma_set_peripheral_size(DEBUG_USART_DMA, DEBUG_USART_DMA_STREAM, DMA_SxCR_PSIZE_8BIT); + dma_set_memory_size(DEBUG_USART_DMA, DEBUG_USART_DMA_STREAM, DMA_SxCR_MSIZE_8BIT); + dma_set_priority(DEBUG_USART_DMA, DEBUG_USART_DMA_STREAM, DMA_SxCR_PL_VERY_HIGH); dma_enable_transfer_complete_interrupt(DEBUG_USART_DMA, DEBUG_USART_DMA_STREAM); - dma_enable_channel(DEBUG_USART_DMA, DEBUG_USART_DMA_STREAM); usart_enable_tx_dma(DEBUG_USART); - nvic_enable_irq(DEBUG_USART_NVIC_DMA_IRQ); } -void DEBUG_USART_DMA_ISR +static void usart_kickoff_dma(void) { + tx_buf[tx_buf_active].pos = 0; /* clear old buffer */ + tx_buf_active = !tx_buf_active; /* swap buffers */ + /* initiate transmission of new buffer */ + dma_set_memory_address(DEBUG_USART_DMA, DEBUG_USART_DMA_STREAM, (uint32_t)&tx_buf[tx_buf_active].buf); /* select active buffer address */ + dma_set_number_of_data(DEBUG_USART_DMA, DEBUG_USART_DMA_STREAM, tx_buf[tx_buf_active].pos); + dma_enable_stream(DEBUG_USART_DMA, DEBUG_USART_DMA_STREAM); +} + +void DEBUG_USART_DMA_ISR(void) { + dma_clear_interrupt_flags(DEBUG_USART_DMA, DEBUG_USART_DMA_STREAM, DMA_TCIF); + + struct tx_buf *buf = &tx_buf[!tx_buf_active]; /* select inactive buffer */ + if (buf->pos != 0) { + usart_kickoff_dma(); + } +} void usart_fifo_push(uint8_t c) { + nvic_disable_irq(DEBUG_USART_NVIC_DMA_IRQ); struct tx_buf *buf = &tx_buf[!tx_buf_active]; /* select inactive buffer */ buf->buf[buf->pos++] = c; - nvic_disable_irq(DEBUG_USART_NVIC_DMA_IRQ); - if + if (!(DMA_SCR(DEBUG_USART_DMA, DEBUG_USART_DMA_STREAM) & DMA_SxCR_EN) /* DMA is not running */ + && !dma_get_interrupt_flag(DEBUG_USART_DMA, DEBUG_USART_DMA_STREAM, DMA_TCIF)/* DMA interrupt is clear */) { + usart_kickoff_dma(); + } + nvic_enable_irq(DEBUG_USART_NVIC_DMA_IRQ); } diff --git a/src/usart_helpers.h b/src/usart_helpers.h index 445a477..18de3b4 100644 --- a/src/usart_helpers.h +++ b/src/usart_helpers.h @@ -32,16 +32,17 @@ BEGIN_DECLS #ifdef USART_DEBUG void usart_init(uint32_t usart, uint32_t baudrate); void usart_printf(const char *str, ...); -void usart_fifo_send(void); -void usart_interrupt(void); +void usart_fifo_push(uint8_t c); -void debug_usart_init() { +void debug_usart_init(void); #define LOG_PRINTF(format, ...) usart_printf(format, ##__VA_ARGS__); #else #define LOG_PRINTF(dummy, ...) ((void)dummy) #endif +#define UNUSED(var) ((void)var) + END_DECLS #endif -- cgit