DMA-supported LOG_PRINTF works

This commit is contained in:
jaseg 2018-11-06 09:15:37 +09:00
parent 5b4c295d00
commit 5009a15280
5 changed files with 85 additions and 109 deletions

View file

@ -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
)

View file

@ -38,8 +38,6 @@
#include <string.h>
#include <stdlib.h>
#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;
}

View file

@ -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;

View file

@ -31,86 +31,12 @@
#include <stdlib.h>
#include <stdio.h>
#include <libopencm3/stm32/usart.h>
#include <libopencm3/stm32/dma.h>
#include <libopencm3/cm3/nvic.h>
#include <libopencmsis/core_cm3.h>
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);
}
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;
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);
}
void DEBUG_USART_DMA_ISR
void usart_fifo_push(uint8_t c) {
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
}

View file

@ -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