Compare commits

...

2 commits

Author SHA1 Message Date
Stephan I. Böttcher
33e969b5a2 uart1: fixes, UART1_RX_FLAG_SEND
- major fixes all over
- directly send the received string/data via `printf()`
  even without providing a buffer
  uart1_receive(s=0, 120, UART1_RX_FLAG_SEND)
2024-11-02 13:28:54 +01:00
Stephan I. Böttcher
d11527f131 gpio.h: enumerate CAP and MAT pin functions 2024-11-02 13:26:32 +01:00
3 changed files with 138 additions and 37 deletions

8
gpio.h
View file

@ -23,7 +23,7 @@
* 0.15: (45) AD1.5 Ineg (EINT) * 0.15: (45) AD1.5 Ineg (EINT)
* 0.16: (46) SSP SSEL/MCLK MAT0.2 * 0.16: (46) SSP SSEL/MCLK MAT0.2
* 0.17: (47) SSP SCK * 0.17: (47) SSP SCK
* 0.18: (53) SSP MISO * 0.18: (53) SSP MISO (CAP1.3)
* 0.19: (54) SSP MOSI * 0.19: (54) SSP MOSI
* 0.20: (55) SSL SSEL ADC * 0.20: (55) SSL SSEL ADC
* 0.21: (1) AD1.6 Vpos (PWM) * 0.21: (1) AD1.6 Vpos (PWM)
@ -33,9 +33,9 @@
* 0.25: (9) AOUT (AD0.4) * 0.25: (9) AOUT (AD0.4)
* 0.26: * 0.26:
* 0.27: * 0.27:
* 0.28: (13) AD0.1 (MAT) * 0.28: (13) AD0.1 (MAT0.2, CAP0.2)
* 0.29: (14) AD0.2 (MAT) * 0.29: (14) AD0.2 (MAT0.3, CAP0.3)
* 0.30: (15) AD0.3 (MAT, EINT) * 0.30: (15) AD0.3 (CAP0.0, EINT3)
* 0.31: (17) USB UP_LED * 0.31: (17) USB UP_LED
* *
* 1.16: (16) GPIO OUT (internal pull-up) * 1.16: (16) GPIO OUT (internal pull-up)

6
uart.h
View file

@ -48,10 +48,12 @@ inline static void streol(char *s, int n)
} }
enum { enum {
UART1_RX_FLAG_READLINE = 1, UART1_RX_FLAG_READLINE = 1,
UART1_RX_FLAG_ALL_OR_NOTHING = 2, UART1_RX_FLAG_ALL_OR_NOTHING = 2,
UART1_RX_FLAG_FLUSH = 4, UART1_RX_FLAG_FLUSH = 4,
UART1_RX_FLAG_SEND = 8
}; };
unsigned int uart1_receive(char *s, unsigned int n, unsigned int flags); unsigned int uart1_receive(char *s, unsigned int n, unsigned int flags);
int uart1_send(const char *s, unsigned int n); int uart1_send(const char *s, unsigned int n);

161
uart1.c
View file

@ -5,17 +5,20 @@
#include <lpc2148/vic.h> #include <lpc2148/vic.h>
#include <string.h> #include <string.h>
#include "mainloop.h" #include "mainloop.h"
#include "message.h"
#include "parser.h"
static char uart1_buffer[128]; static char uart1_buffer[128];
#define buffer_size (sizeof(uart1_buffer)) #define buffer_size (sizeof(uart1_buffer))
#define buffer(p) uart1_buffer[(p) & (buffer_size - 1)] #define buffer_mask (buffer_size-1)
#define buffer(p) uart1_buffer[(p) & buffer_mask]
// all access must be with irqs disabled, no volatile // all access must be with irqs disabled, no volatile
unsigned int tx_read; static unsigned int tx_read;
unsigned int tx_write; static unsigned int tx_write;
unsigned int rx_read; static unsigned int rx_read;
unsigned int rx_write; static unsigned int rx_write;
// uart1_buffer invariants: // uart1_buffer invariants:
// buffer_size = 2^n // buffer_size = 2^n
@ -28,20 +31,21 @@ unsigned int rx_write;
inline static inline static
void free_rx_space() void free_rx_space()
{ {
if (rx_read + buffer_size == tx_write)
return;
if (rx_read == rx_write) { if (rx_read == rx_write) {
rx_read = rx_write = tx_read - buffer_size; rx_read = rx_write = tx_write - buffer_size;
return; return;
} }
if (tx_read == tx_write) { if (tx_read == tx_write) {
tx_read = tx_write = rx_read + buffer_size; tx_read = tx_write = rx_read + buffer_size;
return; return;
} }
if (rx_read == tx_write)
return;
unsigned int nrx_write = tx_write - buffer_size; unsigned int nrx_write = tx_write - buffer_size;
rx_read = nrx_write; unsigned int nrx_read = nrx_write;
while (rx_read != rx_write) while (rx_read != rx_write)
buffer(nrx_write++) = buffer(rx_read++); buffer(nrx_write++) = buffer(rx_read++);
rx_read = nrx_read;
rx_write = nrx_write; rx_write = nrx_write;
} }
@ -109,6 +113,29 @@ int uart1_status()
unsigned int uart1_interrupt_count; unsigned int uart1_interrupt_count;
unsigned int uart1_overflow; unsigned int uart1_overflow;
unsigned int uart1_frame_errors; unsigned int uart1_frame_errors;
unsigned int uart1_mode;
struct uart1_match {
unsigned char size; // available message length
unsigned char val; // eol char
unsigned char max; // max line length to wait for
unsigned char mask; // mask char for eol
} uart1_match = {
.size = 0,
.max = 96,
.mask = 0xff,
.val = '\n',
};
const struct keywords uart1_variable_names[] = {
VARIABLE("uart_mode", &uart1_mode),
VARIABLE("uart_match", &uart1_match),
VARIABLE("uart_irqs", &uart1_interrupt_count),
VARIABLE("uart_overflow", &uart1_overflow),
VARIABLE("uart_errors", &uart1_frame_errors),
VARIABLE("uart_buffer", &uart1_buffer),
KW_END
};
inline static inline static
unsigned int drain_rx_fifo(unsigned int lsr) unsigned int drain_rx_fifo(unsigned int lsr)
@ -127,10 +154,16 @@ unsigned int drain_rx_fifo(unsigned int lsr)
break; break;
} }
} }
buffer(rx_write++) = U1RBR; char d = U1RBR;
buffer(rx_write++) = d;
iir = U1IIR; iir = U1IIR;
lsr = U1LSR; lsr = U1LSR;
unsigned int n = rx_write - rx_read;
if ((d & uart1_match.mask) == uart1_match.val
|| n >= uart1_match.max)
uart1_match.size = n;
} }
if (!(lsr & UART_LSR_RDR)) if (!(lsr & UART_LSR_RDR))
U1IER |= UART_IER_RBR; U1IER |= UART_IER_RBR;
return lsr; return lsr;
@ -164,7 +197,8 @@ void uart1_init()
U1LCR = 0; U1LCR = 0;
U1IER = 0; U1IER = 0;
barrier(); barrier();
tx_read = tx_write = rx_read = rx_write = 0; rx_read = rx_write = 0;
tx_read = tx_write = buffer_size;
U1FCR = UART_FCR_Enable | UART_FCR_RxReset | UART_FCR_TxReset | UART_FCR_RxTrigger_14; U1FCR = UART_FCR_Enable | UART_FCR_RxReset | UART_FCR_TxReset | UART_FCR_RxTrigger_14;
U1LCR = UART_LCR_DLAB; U1LCR = UART_LCR_DLAB;
@ -176,7 +210,8 @@ void uart1_init()
U1LCR = UART_LCR_8bits | UART_LCR_ParityNone; U1LCR = UART_LCR_8bits | UART_LCR_ParityNone;
baudrate1 = baud_rates[baud1_select].baud; baudrate1 = baud_rates[baud1_select].baud;
U1IER |= UART_IER_RBR;
VICVectAddrs[IrqVec_UART1] = uart1_isr; VICVectAddrs[IrqVec_UART1] = uart1_isr;
VICVectCntl[IrqVec_UART1] = VICVectCntl_UART1; VICVectCntl[IrqVec_UART1] = VICVectCntl_UART1;
VICIntEnable = VIC_UART1; VICIntEnable = VIC_UART1;
@ -185,11 +220,19 @@ void uart1_init()
int uart1_send(const char *s, unsigned int n) int uart1_send(const char *s, unsigned int n)
{ {
unsigned int iflag = disable_irq(IRQ_DISABLE); unsigned int iflag = disable_irq(IRQ_DISABLE);
if (free_tx_space(n) < n) if (free_tx_space(n) < n) {
return 0; n = 0;
unsigned int tx_write = tx_write; goto full;
memcpy(&buffer(tx_write), s , n); }
unsigned int nn = buffer_size - (tx_write & buffer_mask);
if (nn >= n)
memcpy(&buffer(tx_write), s, n);
else {
memcpy(&buffer(tx_write), s, nn);
memcpy(&buffer(0), s+nn, n - nn);
}
tx_write += n; tx_write += n;
full:
uart1_poll(U1LSR); uart1_poll(U1LSR);
enable_irq(iflag); enable_irq(iflag);
return n; return n;
@ -199,31 +242,87 @@ unsigned int uart1_receive(char *s, unsigned int n, unsigned int flags)
{ {
unsigned int iflag = disable_irq(IRQ_DISABLE); unsigned int iflag = disable_irq(IRQ_DISABLE);
drain_rx_fifo(U1LSR); drain_rx_fifo(U1LSR);
unsigned int b = rx_write - rx_read;
enable_irq(iflag);
unsigned int r = 0; unsigned int r = 0;
if (rx_write - rx_read < n && flags & UART1_RX_FLAG_ALL_OR_NOTHING)
goto empty;
if (!n) if (!n)
goto flush; goto flush;
if (b > n)
b = n;
if (flags & UART1_RX_FLAG_READLINE) { if (flags & UART1_RX_FLAG_READLINE) {
if (b >= n)
b = n - 1;
unsigned int i; unsigned int i;
for (i = rx_read; i < rx_write; i++) for (i = 0; i < b; i++)
if (buffer(i) == '\n') if ((buffer(rx_read+i) & uart1_match.mask) == uart1_match.val)
break; break;
i -= rx_read; if (i == b && i < uart1_match.max && n > uart1_match.max)
i++; b = 0;
if (i >= n) else
i = n - 1; b = i;
n = i; if (s)
s[n] = '\0'; s[b] = '\0';
} }
unsigned int b = rx_write - rx_read; else if (b < n && flags & UART1_RX_FLAG_ALL_OR_NOTHING)
if (n) goto empty;
memcpy(s, &buffer(rx_read), n);
rx_read += n; if (!b)
goto empty;
unsigned int bb = buffer_size - (rx_read & buffer_mask);
if (s)
if (bb >= b)
memcpy(s, &buffer(rx_read), b);
else {
memcpy(s, &buffer(rx_read), bb);
memcpy(s + bb, &buffer(0), b - bb);
}
if (flags & UART1_RX_FLAG_SEND)
if (flags & UART1_RX_FLAG_READLINE) {
if (s)
printf("UT %s←UT\n", s);
else if (bb >= b)
printf("UT %.*s←UT\n", b, &buffer(rx_read));
else
printf("UT %.*s%.*s←UT\n",
bb, &buffer(rx_read),
b - bb, &buffer(rx_read + bb) );
}
else {
printf("UX");
for (unsigned int i=0; i < b; i++)
printf(" %02x", buffer(rx_read+i));
printf("\n");
}
rx_read += b;
r = b;
flush: flush:
if (flags & UART1_RX_FLAG_FLUSH) if (flags & UART1_RX_FLAG_FLUSH) {
rx_read = rx_write; rx_read = rx_write;
uart1_match.size = 0;
}
empty: empty:
U1IER |= UART_IER_RBR;
iflag = disable_irq(IRQ_DISABLE);
b = rx_write - rx_read;
if (b >= uart1_match.max)
uart1_match.size = b;
else {
uart1_match.size = 0;
for (unsigned int i=0; i<b; i++)
if ((buffer(rx_read+i) & uart1_match.mask) == uart1_match.val) {
uart1_match.size = i;
break;
}
}
enable_irq(iflag); enable_irq(iflag);
return r; return r;
} }