COBS/binary suport added, abstraction improved
This commit is contained in:
parent
09893c47d1
commit
985710d517
4 changed files with 111 additions and 53 deletions
|
|
@ -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
|
||||
|
|
|
|||
58
src/demo.c
58
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
#define TINYPRINTF_OVERRIDE_LIBC 0
|
||||
#define TINYPRINTF_DEFINE_TFP_SPRINTF 0
|
||||
#include "tinyprintf.h"
|
||||
#include "cobs.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
|
|
@ -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);
|
||||
void usart_dma_init(struct dma_usart_file *f) {
|
||||
usart_init(f->usart, f->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);
|
||||
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; i<len; i++) {
|
||||
/* 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) {
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue