DMA-supported LOG_PRINTF works
This commit is contained in:
parent
5b4c295d00
commit
5009a15280
5 changed files with 85 additions and 109 deletions
|
|
@ -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
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue