serial if seems to work
This commit is contained in:
parent
a8ef857d2a
commit
e6e49ee481
3 changed files with 82 additions and 84 deletions
16
.gitignore
vendored
Normal file
16
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
.ipynb_checkpoints
|
||||||
|
Netzfrequenz_Sekundenwerte_2012_KW37.csv
|
||||||
|
__pycache__
|
||||||
|
gm_platform/platform/gerber.out
|
||||||
|
gm_platform/platform/gerber
|
||||||
|
*.kicad_pcb-bak
|
||||||
|
*.sch-bak
|
||||||
|
*.aux
|
||||||
|
*.bbl
|
||||||
|
*.bcf
|
||||||
|
*.blg
|
||||||
|
*.log
|
||||||
|
*.out
|
||||||
|
*.run.xml
|
||||||
|
*.toc
|
||||||
|
*.bib~
|
||||||
|
|
@ -43,18 +43,23 @@ static void usart_schedule_dma(void);
|
||||||
static int usart_putc_nonblocking(uint8_t c);
|
static int usart_putc_nonblocking(uint8_t c);
|
||||||
|
|
||||||
|
|
||||||
void usart_dma_init() {
|
void usart_dma_reset() {
|
||||||
usart_tx_buf.xfr_start = -1;
|
usart_tx_buf.xfr_start = -1;
|
||||||
usart_tx_buf.xfr_end = 0;
|
usart_tx_buf.xfr_end = 0;
|
||||||
usart_tx_buf.wr_pos = 0;
|
usart_tx_buf.wr_pos = 0;
|
||||||
usart_tx_buf.wr_idx = 0;
|
usart_tx_buf.wr_idx = 0;
|
||||||
usart_tx_buf.cur_packet = -1;
|
usart_tx_buf.xfr_next = 0;
|
||||||
usart_tx_buf.retransmit_rq = 0;
|
usart_tx_buf.wraparound = false;
|
||||||
usart_tx_buf.wraparound = 0;
|
usart_tx_buf.ack = false;
|
||||||
|
|
||||||
for (size_t i=0; i<ARRAY_LEN(usart_tx_buf.packet_end); i++)
|
for (size_t i=0; i<ARRAY_LEN(usart_tx_buf.packet_end); i++)
|
||||||
usart_tx_buf.packet_end[i] = -1;
|
usart_tx_buf.packet_end[i] = -1;
|
||||||
|
|
||||||
cobs_decode_incremental_initialize(&cobs_state);
|
cobs_decode_incremental_initialize(&cobs_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
void usart_dma_init() {
|
||||||
|
usart_dma_reset();
|
||||||
|
|
||||||
/* Configure DMA 1 Channel 2 to handle uart transmission */
|
/* Configure DMA 1 Channel 2 to handle uart transmission */
|
||||||
DMA1_Channel2->CPAR = (uint32_t)&(USART1->TDR);
|
DMA1_Channel2->CPAR = (uint32_t)&(USART1->TDR);
|
||||||
|
|
@ -74,7 +79,7 @@ void usart_dma_init() {
|
||||||
|
|
||||||
/* triggered on transfer completion. We use this to process the ADC data */
|
/* triggered on transfer completion. We use this to process the ADC data */
|
||||||
NVIC_EnableIRQ(DMA1_Channel2_3_IRQn);
|
NVIC_EnableIRQ(DMA1_Channel2_3_IRQn);
|
||||||
NVIC_SetPriority(DMA1_Channel2_3_IRQn, 1<<5);
|
NVIC_SetPriority(DMA1_Channel2_3_IRQn, 2<<5);
|
||||||
|
|
||||||
USART1->CR1 = /* 8-bit -> M1, M0 clear */
|
USART1->CR1 = /* 8-bit -> M1, M0 clear */
|
||||||
/* OVER8 clear. Use default 16x oversampling */
|
/* OVER8 clear. Use default 16x oversampling */
|
||||||
|
|
@ -100,7 +105,7 @@ void usart_dma_init() {
|
||||||
|
|
||||||
/* Enable receive interrupt */
|
/* Enable receive interrupt */
|
||||||
NVIC_EnableIRQ(USART1_IRQn);
|
NVIC_EnableIRQ(USART1_IRQn);
|
||||||
NVIC_SetPriority(USART1_IRQn, 3<<5);
|
NVIC_SetPriority(USART1_IRQn, 1<<5);
|
||||||
|
|
||||||
/* And... go! */
|
/* And... go! */
|
||||||
USART1->CR1 |= USART_CR1_UE;
|
USART1->CR1 |= USART_CR1_UE;
|
||||||
|
|
@ -137,17 +142,11 @@ void USART1_IRQHandler() {
|
||||||
|
|
||||||
switch (pkt->type) {
|
switch (pkt->type) {
|
||||||
case CTRL_PKT_RESET:
|
case CTRL_PKT_RESET:
|
||||||
for (size_t i=0; i<ARRAY_LEN(usart_tx_buf.packet_end); i++)
|
usart_dma_reset();
|
||||||
usart_tx_buf.packet_end[i] = -1;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CTRL_PKT_ACK:
|
case CTRL_PKT_ACK:
|
||||||
if (usart_ack_packet(pkt->orig_id))
|
usart_tx_buf.ack = true;
|
||||||
rx_protocol_errors++;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CTRL_PKT_RETRANSMIT:
|
|
||||||
usart_tx_buf.retransmit_rq = 1;
|
|
||||||
if (!(DMA1_Channel2->CCR & DMA_CCR_EN))
|
if (!(DMA1_Channel2->CCR & DMA_CCR_EN))
|
||||||
usart_schedule_dma();
|
usart_schedule_dma();
|
||||||
break;
|
break;
|
||||||
|
|
@ -161,98 +160,81 @@ void USART1_IRQHandler() {
|
||||||
|
|
||||||
|
|
||||||
void usart_schedule_dma() {
|
void usart_schedule_dma() {
|
||||||
/* This function is only called when the DMA channel is disabled. This means we don't have to guard it in IRQ
|
|
||||||
* disables. */
|
|
||||||
volatile struct dma_tx_buf *buf = &usart_tx_buf;
|
volatile struct dma_tx_buf *buf = &usart_tx_buf;
|
||||||
|
|
||||||
ssize_t next_start, next_idx;
|
ssize_t xfr_start, xfr_end, xfr_len;
|
||||||
if (buf->wraparound) {
|
if (buf->wraparound) {
|
||||||
buf->wraparound = 0;
|
buf->wraparound = false;
|
||||||
next_idx = buf->cur_packet;
|
xfr_start = 0;
|
||||||
next_start = 0;
|
xfr_len = buf->xfr_end;
|
||||||
|
xfr_end = buf->xfr_end;
|
||||||
|
|
||||||
} else if (buf->retransmit_rq) {
|
} else if (buf->ack) {
|
||||||
buf->retransmit_rq = 0;
|
if (buf->packet_end[buf->xfr_next] == -1)
|
||||||
next_idx = buf->cur_packet;
|
return; /* Nothing to trasnmit */
|
||||||
next_start = buf->xfr_start;
|
|
||||||
|
buf->ack = false;
|
||||||
|
|
||||||
|
xfr_start = buf->xfr_end;
|
||||||
|
xfr_end = buf->packet_end[buf->xfr_next];
|
||||||
|
buf->packet_end[buf->xfr_next] = -1;
|
||||||
|
buf->xfr_next = (buf->xfr_next + 1) % ARRAY_LEN(buf->packet_end);
|
||||||
|
|
||||||
|
if (xfr_end > xfr_start) { /* no wraparound */
|
||||||
|
xfr_len = xfr_end - xfr_start;
|
||||||
|
|
||||||
|
} else { /* wraparound */
|
||||||
|
if (xfr_end != 0)
|
||||||
|
buf->wraparound = true;
|
||||||
|
xfr_len = sizeof(buf->data) - xfr_start;
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
next_idx = (buf->cur_packet + 1) % ARRAY_LEN(usart_tx_buf.packet_end);
|
/* retransmit */
|
||||||
next_start = buf->xfr_end;
|
/* First, send a zero to delimit any garbage from the following good packet */
|
||||||
|
USART1->TDR = 0x00;
|
||||||
|
|
||||||
|
xfr_start = buf->xfr_start;
|
||||||
|
xfr_end = buf->xfr_end;
|
||||||
|
|
||||||
|
if (xfr_end > xfr_start) { /* no wraparound */
|
||||||
|
xfr_len = xfr_end - xfr_start;
|
||||||
|
|
||||||
|
} else { /* wraparound */
|
||||||
|
if (xfr_end != 0)
|
||||||
|
buf->wraparound = true;
|
||||||
|
xfr_len = sizeof(buf->data) - xfr_start;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t next_end = buf->packet_end[next_idx];
|
buf->xfr_start = xfr_start;
|
||||||
|
buf->xfr_end = xfr_end;
|
||||||
/* Nothing to trasnmit */
|
|
||||||
if (next_end == -1)
|
|
||||||
return;
|
|
||||||
|
|
||||||
ssize_t xfr_len;
|
|
||||||
if (next_end > next_start) /* no wraparound */
|
|
||||||
xfr_len = next_end - next_start;
|
|
||||||
else /* wraparound */
|
|
||||||
xfr_len = sizeof(buf->data) - next_start; /* schedule transfer until end of buffer */
|
|
||||||
|
|
||||||
buf->xfr_start = next_start;
|
|
||||||
buf->xfr_end = (next_start + xfr_len) % sizeof(buf->data); /* handle wraparound */
|
|
||||||
buf->cur_packet = next_idx;
|
|
||||||
|
|
||||||
/* initiate transmission of new buffer */
|
/* initiate transmission of new buffer */
|
||||||
DMA1_Channel2->CMAR = (uint32_t)(buf->data + next_start);
|
DMA1_Channel2->CMAR = (uint32_t)(buf->data + xfr_start);
|
||||||
DMA1_Channel2->CNDTR = xfr_len;
|
DMA1_Channel2->CNDTR = xfr_len;
|
||||||
DMA1_Channel2->CCR |= DMA_CCR_EN;
|
DMA1_Channel2->CCR |= DMA_CCR_EN;
|
||||||
}
|
}
|
||||||
|
|
||||||
int usart_ack_packet(uint8_t idx) {
|
int usart_putc_nonblocking(uint8_t c) {
|
||||||
if (idx > ARRAY_LEN(usart_tx_buf.packet_end))
|
volatile struct dma_tx_buf *buf = &usart_tx_buf;
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
if (idx != usart_tx_buf.cur_packet)
|
if (buf->wr_pos == buf->xfr_start)
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
usart_tx_buf.packet_end[idx] = -1;
|
|
||||||
|
|
||||||
/* If the DMA stream is idle right now, schedule the next transfer */
|
|
||||||
if (!(DMA1_Channel2->CCR & DMA_CCR_EN))
|
|
||||||
usart_schedule_dma();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int usart_dma_fifo_push(volatile struct dma_tx_buf *buf, uint8_t c) {
|
|
||||||
/* This function must be guarded by IRQ disable since the IRQ may schedule a new transfer and charge pos/start. */
|
|
||||||
NVIC_DisableIRQ(DMA1_Channel2_3_IRQn);
|
|
||||||
|
|
||||||
if (buf->wr_pos == buf->xfr_start) {
|
|
||||||
NVIC_EnableIRQ(DMA1_Channel2_3_IRQn);
|
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
|
||||||
|
|
||||||
buf->data[buf->wr_pos] = c;
|
buf->data[buf->wr_pos] = c;
|
||||||
buf->wr_pos = (buf->wr_pos + 1) % sizeof(buf->data);
|
buf->wr_pos = (buf->wr_pos + 1) % sizeof(buf->data);
|
||||||
|
|
||||||
NVIC_EnableIRQ(DMA1_Channel2_3_IRQn);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int usart_putc(uint8_t c) {
|
|
||||||
/* push char to fifo, busy-loop if stalled to wait for USART to empty fifo via DMA */
|
|
||||||
while (usart_dma_fifo_push(&usart_tx_buf, c) == -EBUSY) {
|
|
||||||
/* idle */
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int usart_putc_nonblocking(uint8_t c) {
|
|
||||||
return usart_dma_fifo_push(&usart_tx_buf, c);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void DMA1_Channel2_3_IRQHandler(void) {
|
void DMA1_Channel2_3_IRQHandler(void) {
|
||||||
/* Transfer complete */
|
/* Transfer complete */
|
||||||
DMA1->IFCR |= DMA_IFCR_CTCIF2;
|
DMA1->IFCR |= DMA_IFCR_CTCIF2;
|
||||||
|
|
||||||
DMA1_Channel2->CCR &= ~DMA_CCR_EN;
|
DMA1_Channel2->CCR &= ~DMA_CCR_EN;
|
||||||
if (usart_tx_buf.retransmit_rq || usart_tx_buf.wraparound)
|
if (usart_tx_buf.wraparound)
|
||||||
usart_schedule_dma();
|
usart_schedule_dma();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -266,7 +248,7 @@ int usart_send_packet_nonblocking(struct ll_pkt *pkt, size_t pkt_len) {
|
||||||
}
|
}
|
||||||
|
|
||||||
pkt->pid = usart_tx_buf.wr_idx;
|
pkt->pid = usart_tx_buf.wr_idx;
|
||||||
pkt->_pad = 0;
|
pkt->_pad = usart_tx_buf.xfr_next;
|
||||||
|
|
||||||
/* make the value this wonky-ass CRC implementation produces match zlib etc. */
|
/* make the value this wonky-ass CRC implementation produces match zlib etc. */
|
||||||
CRC->CR = CRC_CR_REV_OUT | (1<<CRC_CR_REV_IN_Pos) | CRC_CR_RESET;
|
CRC->CR = CRC_CR_REV_OUT | (1<<CRC_CR_REV_IN_Pos) | CRC_CR_RESET;
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
#include "global.h"
|
#include "global.h"
|
||||||
|
|
||||||
|
|
@ -33,9 +34,10 @@ struct dma_tx_buf {
|
||||||
/* The following fields are accessed only from DMA ISR */
|
/* The following fields are accessed only from DMA ISR */
|
||||||
ssize_t xfr_start; /* Start index of running DMA transfer */
|
ssize_t xfr_start; /* Start index of running DMA transfer */
|
||||||
ssize_t xfr_end; /* End index of running DMA transfer plus one */
|
ssize_t xfr_end; /* End index of running DMA transfer plus one */
|
||||||
ssize_t cur_packet;
|
bool wraparound;
|
||||||
int retransmit_rq;
|
ssize_t xfr_next;
|
||||||
int wraparound;
|
bool ack;
|
||||||
|
|
||||||
|
|
||||||
/* The following fields are written only from non-interrupt code */
|
/* The following fields are written only from non-interrupt code */
|
||||||
ssize_t wr_pos; /* Next index to be written */
|
ssize_t wr_pos; /* Next index to be written */
|
||||||
|
|
@ -57,7 +59,6 @@ struct __attribute__((__packed__)) ll_pkt {
|
||||||
enum ctrl_pkt_type {
|
enum ctrl_pkt_type {
|
||||||
CTRL_PKT_RESET = 1,
|
CTRL_PKT_RESET = 1,
|
||||||
CTRL_PKT_ACK = 2,
|
CTRL_PKT_ACK = 2,
|
||||||
CTRL_PKT_RETRANSMIT = 3,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct __attribute__((__packed__)) ctrl_pkt {
|
struct __attribute__((__packed__)) ctrl_pkt {
|
||||||
|
|
@ -68,7 +69,6 @@ struct __attribute__((__packed__)) ctrl_pkt {
|
||||||
extern volatile struct dma_tx_buf usart_tx_buf;
|
extern volatile struct dma_tx_buf usart_tx_buf;
|
||||||
|
|
||||||
void usart_dma_init(void);
|
void usart_dma_init(void);
|
||||||
int usart_dma_fifo_push(volatile struct dma_tx_buf *buf, uint8_t c);
|
|
||||||
int usart_send_packet_nonblocking(struct ll_pkt *pkt, size_t pkt_len);
|
int usart_send_packet_nonblocking(struct ll_pkt *pkt, size_t pkt_len);
|
||||||
int usart_ack_packet(uint8_t idx);
|
int usart_ack_packet(uint8_t idx);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue