summaryrefslogtreecommitdiff
path: root/hardware/fw/packet_interface.c
blob: 099993b24dd2bae927200d2630540a7d39f0fd7e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include "packet_interface.h"
#include "cobs.h"

void usart2_isr(void) {
    TRACING_SET(TR_HOST_IF_USART_IRQ);
    static struct cobs_decode_state host_cobs_state = {0};
    if (USART2_SR & USART_SR_ORE) { /* Overrun handling */
        LOG_PRINTF("USART2 data register overrun\n");
        /* Clear interrupt flag */
        (void)USART2_DR; /* FIXME make sure this read is not optimized out */
        host_packet_length = -1;
        TRACING_CLEAR(TR_HOST_IF_USART_IRQ);
        return;
    }

    uint8_t data = USART2_DR; /* This automatically acknowledges the IRQ */

    if (host_packet_length) {
        LOG_PRINTF("USART2 COBS buffer overrun\n");
        host_packet_length = -1;
        TRACING_CLEAR(TR_HOST_IF_USART_IRQ);
        return;
    }

    ssize_t rv = cobs_decode_incremental(&host_cobs_state, (char *)host_packet_buf, sizeof(host_packet_buf), data);
    if (rv == -2) {
        LOG_PRINTF("Host interface COBS packet too large\n");
        host_packet_length = -1;
    } else if (rv == -3) {
        LOG_PRINTF("Got double null byte from host\n");
    } else if (rv < 0) {
        LOG_PRINTF("Host interface COBS framing error\n");
        host_packet_length = -1;
    } else if (rv > 0) {
        host_packet_length = rv;
    } /* else just return and wait for next byte */
    TRACING_CLEAR(TR_HOST_IF_USART_IRQ);
}

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);
}