summaryrefslogtreecommitdiff
path: root/src/usart_helpers.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/usart_helpers.c')
-rw-r--r--src/usart_helpers.c80
1 files changed, 56 insertions, 24 deletions
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 <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);
-
- 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; 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);
+}
+