From 985710d517e38a93be7658d4e4e8967c356a4ef9 Mon Sep 17 00:00:00 2001 From: jaseg Date: Tue, 6 Nov 2018 17:18:34 +0900 Subject: COBS/binary suport added, abstraction improved --- src/CMakeLists.txt | 12 ++------ src/demo.c | 58 ++++++++++++++++++++++++++++---------- src/usart_helpers.c | 80 +++++++++++++++++++++++++++++++++++++---------------- src/usart_helpers.h | 16 +++++++---- 4 files changed, 112 insertions(+), 54 deletions(-) (limited to 'src') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d6fa3bd..25d8683 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,12 +1,3 @@ -if (USE_USART_DEBUG) - set (USART_HELPERS - usart_helpers.c - tinyprintf.c - ) -else (USE_USART_DEBUG) - set (USART_HELPERS "") -endif (USE_USART_DEBUG) - set (inc ${CMAKE_SOURCE_DIR}/include) add_library (usbhost @@ -28,6 +19,9 @@ add_library (usbhost usbh_driver_hub.c usbh_driver_hub_private.h usbh_lld_stm32f4.c + usart_helpers.c + tinyprintf.c + cobs.c ) target_link_libraries (usbhost diff --git a/src/demo.c b/src/demo.c index aa07378..fdd61e7 100644 --- a/src/demo.c +++ b/src/demo.c @@ -58,6 +58,7 @@ static void clock_setup(void) { rcc_periph_clock_enable(RCC_OTGFS); rcc_periph_clock_enable(RCC_TIM6); rcc_periph_clock_enable(RCC_DMA2); + rcc_periph_clock_enable(RCC_DMA1); } @@ -83,6 +84,7 @@ static void gpio_setup(void) { /* D2, D3 LEDs */ gpio_mode_setup(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO6 | GPIO7); + gpio_set(GPIOA, GPIO6 | GPIO7); /* USB OTG FS phy outputs */ gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO11 | GPIO12); @@ -136,18 +138,14 @@ static const hid_config_t hid_config = { volatile struct { struct dma_buf dma; uint8_t data[256]; -} debug_buf = { - .dma = { - .xfr_start = -1, - .xfr_end = 0, - .wr_pos = 0, - .len = sizeof(debug_buf.data) - } -}; +} debug_buf = { .dma = { .len = sizeof(debug_buf.data) } }; struct dma_usart_file debug_out_s = { + .usart = DEBUG_USART, + .baudrate = DEBUG_USART_BAUDRATE, .dma = DMA(DEBUG_USART_DMA_NUM), .stream = DEBUG_USART_DMA_STREAM_NUM, + .channel = DEBUG_USART_DMA_CHANNEL_NUM, .irqn = NVIC_DMA_IRQ(DEBUG_USART_DMA_NUM, DEBUG_USART_DMA_STREAM_NUM), .buf = &debug_buf.dma }; @@ -160,6 +158,31 @@ void DMA_ISR(DEBUG_USART_DMA_NUM, DEBUG_USART_DMA_STREAM_NUM)(void) { schedule_dma(debug_out); } + +volatile struct { + struct dma_buf dma; + uint8_t data[128]; +} usart2_buf = { .dma = { .len = sizeof(usart2_buf.data) } }; + +struct dma_usart_file usart2_out_s = { + .usart = USART2, + .baudrate = 1000000, + .dma = DMA1, + .stream = 6, + .channel = 4, + .irqn = NVIC_DMA_IRQ(1, 6), + .buf = &usart2_buf.dma +}; +struct dma_usart_file *usart2_out = &usart2_out_s; + +void dma1_stream6_isr(void) { + dma_clear_interrupt_flags(usart2_out->dma, usart2_out->stream, DMA_TCIF); + + if (usart2_out->buf->wr_pos != usart2_out->buf->xfr_end) /* buffer not empty */ + schedule_dma(usart2_out); +} + + int main(void) { clock_setup(); @@ -168,10 +191,14 @@ int main(void) /* provides time_curr_us to usbh_poll function */ tim6_setup(); - usart_init(USART2, 1000000); - DEBUG_USART_INIT(); +#ifdef USART_DEBUG + usart_dma_init(debug_out); +#endif + usart_dma_init(usart2_out); - LOG_PRINTF("SecureHID device side initializing"); + LOG_PRINTF("\n==================================\n"); + LOG_PRINTF("SecureHID device side initializing\n"); + LOG_PRINTF("==================================\n"); hid_driver_init(&hid_config); hub_driver_init(); @@ -191,11 +218,12 @@ int main(void) while (23) { usbh_poll(tim6_get_time_us()); delay_ms_busy_loop(1); /* approx 1ms interval between usbh_poll() */ - //if (i++ == 200) { + if (i++ == 1000) { i = 0; - LOG_PRINTF("0123456789ABCDEF\n"); - //LOG_PRINTF("%x %x %x %x\n", j++, debug_buf.dma.xfr_start, debug_buf.dma.xfr_end, debug_buf.dma.wr_pos); - //} + const char *s = "foobarfoobarfoobarfoobarfoobar"; + send_packet(usart2_out, (uint8_t *)s, strlen(s)); + LOG_PRINTF("Loop iteration %d\n", 1000*(j++)); + } } return 0; } diff --git a/src/usart_helpers.c b/src/usart_helpers.c index 41b5533..493c019 100644 --- a/src/usart_helpers.c +++ b/src/usart_helpers.c @@ -25,6 +25,7 @@ #define TINYPRINTF_OVERRIDE_LIBC 0 #define TINYPRINTF_DEFINE_TFP_SPRINTF 0 #include "tinyprintf.h" +#include "cobs.h" #include #include @@ -39,8 +40,9 @@ void usart_fprintf(struct dma_usart_file *f, const char *str, ...) { va_list va; va_start(va, str); - tfp_format(f, putf, str, va); + tfp_format(f, (void (*)(void *, char c))putf, str, va); va_end(va); + flush(f); } void usart_init(uint32_t arg_usart, uint32_t baudrate) { @@ -53,22 +55,26 @@ void usart_init(uint32_t arg_usart, uint32_t baudrate) { usart_enable(arg_usart); } -void usart_dma_init(uint32_t usart, uint32_t baudrate, uint32_t dma, uint8_t stream, uint8_t channel) { - usart_init(usart, baudrate); - - dma_stream_reset(dma, stream); - dma_channel_select(dma, stream, DMA_SxCR_CHSEL(channel)); - dma_set_peripheral_address(dma, stream, (uint32_t)&USART_DR(usart)); - dma_set_transfer_mode(dma, stream, DMA_SxCR_DIR_MEM_TO_PERIPHERAL); - dma_enable_memory_increment_mode(dma, stream); - dma_set_peripheral_size(dma, stream, DMA_SxCR_PSIZE_8BIT); - dma_set_memory_size(dma, stream, DMA_SxCR_MSIZE_8BIT); - dma_set_priority(dma, stream, DMA_SxCR_PL_VERY_HIGH); - dma_enable_transfer_complete_interrupt(dma, stream); - usart_enable_tx_dma(usart); +void usart_dma_init(struct dma_usart_file *f) { + usart_init(f->usart, f->baudrate); + + f->buf->xfr_start = -1, + f->buf->xfr_end = 0, + f->buf->wr_pos = 0, + + dma_stream_reset(f->dma, f->stream); + dma_channel_select(f->dma, f->stream, DMA_SxCR_CHSEL(f->channel)); + dma_set_peripheral_address(f->dma, f->stream, (uint32_t)&USART_DR(f->usart)); + dma_set_transfer_mode(f->dma, f->stream, DMA_SxCR_DIR_MEM_TO_PERIPHERAL); + dma_enable_memory_increment_mode(f->dma, f->stream); + dma_set_peripheral_size(f->dma, f->stream, DMA_SxCR_PSIZE_8BIT); + dma_set_memory_size(f->dma, f->stream, DMA_SxCR_MSIZE_8BIT); + dma_set_priority(f->dma, f->stream, DMA_SxCR_PL_VERY_HIGH); + dma_enable_transfer_complete_interrupt(f->dma, f->stream); + usart_enable_tx_dma(f->usart); } -void usart_kickoff_dma(uint32_t dma, uint8_t stream, uint8_t *buf, size_t len) { +void usart_kickoff_dma(uint32_t dma, uint8_t stream, volatile uint8_t *buf, size_t len) { /* initiate transmission of new buffer */ dma_set_memory_address(dma, stream, (uint32_t)buf); /* select active buffer address */ dma_set_number_of_data(dma, stream, len); @@ -76,7 +82,7 @@ void usart_kickoff_dma(uint32_t dma, uint8_t stream, uint8_t *buf, size_t len) { } void schedule_dma(volatile struct dma_usart_file *f) { - struct dma_buf *buf = f->buf; + volatile struct dma_buf *buf = f->buf; uint32_t xfr_len, xfr_start = buf->xfr_end; if (buf->wr_pos > xfr_start) /* no wraparound */ @@ -98,23 +104,49 @@ int dma_fifo_push(volatile struct dma_buf *buf, char c) { return 0; } -void putf(void *file, char c) { +int putf(void *file, char c) { volatile struct dma_usart_file *f = (struct dma_usart_file *)file; nvic_disable_irq(f->irqn); - { + /* push char to fifo, busy-loop if stalled to wait for USART to empty fifo via DMA */ + while (dma_fifo_push(f->buf, c) == -EBUSY) { + nvic_enable_irq(f->irqn); + nvic_disable_irq(f->irqn); + } + nvic_enable_irq(f->irqn); + return 0; +} + +int putb(void *file, const uint8_t *buf, size_t len) { + volatile struct dma_usart_file *f = (struct dma_usart_file *)file; + + nvic_disable_irq(f->irqn); + for (size_t i=0; ibuf, c) == -EBUSY) { + while (dma_fifo_push(f->buf, buf[i]) == -EBUSY) { nvic_enable_irq(f->irqn); nvic_disable_irq(f->irqn); } + } + nvic_enable_irq(f->irqn); + return 0; +} - /* If the DMA stream is idle right now, schedule a transfer */ - if (!(DMA_SCR(f->dma, f->stream) & DMA_SxCR_EN) /* DMA is not running */ - && !dma_get_interrupt_flag(f->dma, f->stream, DMA_TCIF)/* DMA interrupt is clear */) { - schedule_dma(f); - } +void flush(void *file) { + volatile struct dma_usart_file *f = (struct dma_usart_file *)file; + + nvic_disable_irq(f->irqn); + /* If the DMA stream is idle right now, schedule a transfer */ + if (!(DMA_SCR(f->dma, f->stream) & DMA_SxCR_EN) /* DMA is not running */ + && !dma_get_interrupt_flag(f->dma, f->stream, DMA_TCIF)/* DMA interrupt is clear */) { + schedule_dma(f); } nvic_enable_irq(f->irqn); } +void send_packet(struct dma_usart_file *f, const uint8_t *data, size_t len) { + /* ignore return value as putf is blocking and always succeeds */ + (void)cobs_encode_incremental(f, putf, (char *)data, len); + flush(f); +} + diff --git a/src/usart_helpers.h b/src/usart_helpers.h index d2cee0c..bd50d00 100644 --- a/src/usart_helpers.h +++ b/src/usart_helpers.h @@ -39,10 +39,13 @@ struct dma_buf { }; struct dma_usart_file { + uint32_t usart; + uint32_t baudrate; uint32_t dma; uint8_t stream; + uint8_t channel; uint8_t irqn; - struct dma_buf *buf; + volatile struct dma_buf *buf; }; @@ -53,11 +56,14 @@ void usart_init(uint32_t usart, uint32_t baudrate); void usart_fprintf(struct dma_usart_file *f, const char *str, ...); void usart_fifo_push(uint8_t c); -void usart_dma_init(uint32_t usart, uint32_t baudrate, uint32_t dma, uint8_t stream, uint8_t channel); -void usart_kickoff_dma(uint32_t dma, uint8_t stream, uint8_t *buf, size_t len); +void usart_dma_init(struct dma_usart_file *f); +void usart_kickoff_dma(uint32_t dma, uint8_t stream, volatile uint8_t *buf, size_t len); void schedule_dma(volatile struct dma_usart_file *f); int dma_fifo_push(volatile struct dma_buf *buf, char c); -void putf(void *file, char c); +int putf(void *file, char c); +int putb(void *file, const uint8_t *buf, size_t len); +void flush(void *file); +void send_packet(struct dma_usart_file *f, const uint8_t *data, size_t len); /* This macro abomination templates a bunch of dma-specific register/constant names from preprocessor macros passed in * from cmake. */ @@ -71,10 +77,8 @@ void putf(void *file, char c); #define DMA_ISR(dma, stream) DMA_ISR_PASTE(dma, stream) #ifdef USART_DEBUG -#define DEBUG_USART_INIT() usart_dma_init(DEBUG_USART, DEBUG_USART_BAUDRATE, DMA(DEBUG_USART_DMA_NUM), DEBUG_USART_DMA_STREAM_NUM, DEBUG_USART_DMA_CHANNEL_NUM) #define LOG_PRINTF(format, ...) usart_fprintf(debug_out, format, ##__VA_ARGS__); #else -#define DEBUG_USART_INIT() ((void)0) #define LOG_PRINTF(dummy, ...) ((void)dummy) #endif -- cgit