Compare commits

...

2 commits

Author SHA1 Message Date
Stephan I. Böttcher
be83ec6ff7 config: fpga_config_page 2026-03-30 12:14:14 +02:00
Stephan I. Böttcher
cb60104a10 git_poll: assember implementation 2026-03-30 11:04:13 +02:00
6 changed files with 484 additions and 2 deletions

View file

@ -16,10 +16,10 @@ SN_thhor = 1
# config.c includes .eeprom `port_config`, that should go second
# .bss: rtc, adc, flash, uart, spi, pipe
C_FILES_thhor = config.c rtc.c adc.c flash.c uart.c cmd.c base85.c pwm.c spi.c bch4369.c pipe.c fpga.c
S_FILES_thhor = uart_tx.S base85a.S
S_FILES_thhor = uart_tx.S base85a.S spi_poll.S
MCU = $(MCU_$(PROJ))
OPT = -Os
OPT = -Os -fverbose-asm
CC=avr-gcc -Wall -Wno-parentheses -MMD -std=c99 $(OPT) \
-mmcu=$(MCU) \

View file

@ -27,6 +27,10 @@ const struct config config = {
.pwm_min = 0x0000,
.pwm_max = 0xffff,
#endif
#ifdef HAVE_FPGA
.fpga_config_page = 1,
.fpga_config_count = 511,
#endif
};
////////////////////////////////////////////////////////////////////////////////

View file

@ -23,8 +23,10 @@ struct config {
uint16_t pwm_min;
uint16_t pwm_max;
#endif
#ifdef HAVE_FPGA
uint16_t fpga_config_page;
uint16_t fpga_config_count;
#endif
};
enum magic_flags {

239
src/spi.c
View file

@ -15,6 +15,243 @@ struct_ioconf(spi_config) = {
conf_io(SPI.CTRLA, SPI_MASTER_bm | SPI_ENABLE_bm | SPI_SPEED),
};
#ifndef SPI_USE_IRQ
#ifdef SPI_POLL_C
static
uint8_t spi_poll_delay()
{
uint8_t t = 0xff;
uint8_t ifg;
do {
ifg = SPI.INTFLAGS & SPI_RXCIF_bm;
} while (~ifg && t--);
return ifg;
}
static
void spi_poll_drop_tail()
{
uint8_t ifg;
do {
ifg = SPI.INTFLAGS;
SPI.DATA;
} while (~ifg & SPI_TXCIF_bm);
spi_poll_delay();
SPI.DATA;
}
static
void spi_poll_write_drop(uint8_t n, const uint8_t *c)
{
do {
uint8_t ifg = SPI.INTFLAGS;
if (ifg & SPI_DREIF_bm) {
SPI.DATA = *c++;
SPI.INTFLAGS = SPI_TXCIF_bm;
n--;
}
SPI.DATA;
} while (n);
spi_poll_drop_tail();
}
static
void spi_poll_zero_drop(uint8_t n)
{
uint8_t z = spi.zero;
do {
uint8_t ifg = SPI.INTFLAGS;
if (ifg & SPI_DREIF_bm) {
SPI.DATA = z;
SPI.INTFLAGS = SPI_TXCIF_bm;
n--;
}
SPI.DATA;
} while (n);
spi_poll_drop_tail();
}
static
uint8_t spi_poll_drop(uint8_t n, const uint8_t *c)
{
if (c)
spi_poll_write_drop(n, c);
else
spi_poll_zero_drop(n);
return n;
}
static
void spi_poll_read_tail(uint8_t r, uint8_t *d)
{
uint8_t ifg;
do {
ifg = SPI.INTFLAGS;
if (ifg & SPI_RXCIF_bm) {
*d++ = SPI.DATA;
if (!--r)
goto done;
}
} while (~ifg & SPI_TXCIF_bm);
if (spi_poll_delay()) {
*d = SPI.DATA;
r--;
}
done:
spi.rdata = d;
spi.rsize = r;
}
static
uint8_t spi_poll_write_read(uint8_t n, const uint8_t *c)
{
uint8_t r = spi.rsize;
uint8_t *d = spi.rdata;
uint8_t w = n;
do {
uint8_t ifg = SPI.INTFLAGS;
if (ifg & SPI_DREIF_bm) {
SPI.DATA = *c++;
SPI.INTFLAGS = SPI_TXCIF_bm;
if (!--n) {
spi_poll_read_tail(r, d);
return w;
}
}
if (ifg & SPI_RXCIF_bm) {
*d++ = SPI.DATA;
r--;
}
} while(r);
spi.rdata = d;
spi.rsize = r;
return w-n;
}
static
uint8_t spi_poll_read(uint8_t n, uint8_t r, uint8_t *d)
{
uint8_t z = spi.zero;
uint8_t w = n;
do {
uint8_t ifg = SPI.INTFLAGS;
if (ifg & SPI_DREIF_bm) {
SPI.DATA = z;
SPI.INTFLAGS = SPI_TXCIF_bm;
if (!--n) {
spi_poll_read_tail(r, d);
return w;
}
}
if (ifg & SPI_RXCIF_bm) {
*d++ = SPI.DATA;
r--;
}
} while(r);
spi.rdata = d;
spi.rsize = r;
return w-n;
}
static
uint8_t spi_poll_wait(uint8_t n)
{
uint8_t r = spi.rsize;
uint8_t *d = spi.rdata;
uint8_t z = spi.zero;
uint8_t w = n;
do {
uint8_t ifg = SPI.INTFLAGS;
if (ifg & SPI_DREIF_bm) {
SPI.DATA = z;
SPI.INTFLAGS = SPI_TXCIF_bm;
if (!--n) {
spi_poll_read_tail(r, d);
return w;
}
}
if (ifg & SPI_RXCIF_bm) {
uint8_t b = SPI.DATA;
if ((b & spi.mask) == spi.wait) {
*d++ = SPI.DATA;
r--;
spi.mask = 0;
break;
}
else
n++;
}
} while (1);
if (r)
return w - n + spi_poll_read(n, r, d);
spi.rdata = d;
spi.rsize = r;
return w-n;
}
static
uint8_t spi_poll_write(uint8_t n, const uint8_t *c)
{
uint8_t i = spi.isize;
uint8_t r = spi.rsize;
uint8_t w =0;
while (n) {
if (!r)
i = n;
if (i) {
if (i < n) {
uint8_t ww = spi_poll_drop(i, c);
w += ww;
c += ww;
n -= ww;
spi.isize = i = 0;
continue;
}
spi.isize = i -= n;
uint8_t ww = spi_poll_drop(n, c);
w += ww;
return w;
}
if (c)
w += spi_poll_write_read(n, c);
else if (spi.mask)
w += spi_poll_wait(n);
else
w += spi_poll_read(n, r, spi.rdata);
}
return w;
}
uint8_t spi_poll()
{
uint8_t n;
n = spi_poll_write(spi.csize, spi.cmd);
spi.cmd += n;
spi.csize -= n;
n = spi_poll_write(spi.zsize, 0);
spi.zsize -= n;
n = spi_poll_write(spi.wsize, spi.wdata);
spi.wdata += n;
spi.wsize -= n;
return 0;
}
#endif // SPI_POLL_C
#else // SPI_USE_IRQ
/****************************************************
The SPI is way to fast for this CPU, the job is done
in a single IRQ invocation.
Running the SPI synchronously allows other Interrupts
to happen.
****************************************************/
#if 0
ISR(SPI0_INT_vect)
{
@ -227,6 +464,8 @@ ISR(SPI0_INT_vect, ISR_NAKED)
}
#endif
#endif // SPI_USE_IRQ
uint8_t spi_select(uint8_t mode)
{
uint8_t s = spi_busy_p();

View file

@ -33,6 +33,37 @@ enum spi_mode_bits {
SPI_CONT = 0x80,
};
#define SPI_USE_IRQ
#ifndef SPI_USE_IRQ
#ifdef SPI_POLL_C
uint8_t spi_poll();
#else
uint8_t _spi_poll();
#define spi_poll _spi_poll
#endif
static inline
uint8_t spi_abort()
{
return spi_poll();
}
static inline
uint8_t spi_busy_p()
{
return spi_poll();
}
static inline
void spi_start()
{
spi_poll();
}
#else // SPI_USE_IRQ
static inline
uint8_t spi_abort()
{
@ -55,6 +86,8 @@ void spi_start()
SPI.INTCTRL = SPI_DREIF_bm | SPI_TXCIF_bm| SPI_RXCIF_bm;
}
#endif // SPI_USE_IRQ
static inline void barrier() { __asm__("":::"memory"); }
void init_spi(uint8_t spi_div);
uint8_t spi_select(uint8_t mode);

204
src/spi_poll.S Normal file
View file

@ -0,0 +1,204 @@
#include <avr/io.h>
#define INTFLAGS SPI0_INTFLAGS
#define DATA SPI0_DATA
#define RXC SPI_RXCIF_bp
#define TXC SPI_TXCIF_bp
#define DRE SPI_DREIF_bp
#define csize Y+1
#define zsize Y+2
#define isize Y+3
#define zero Y+4
#define wait Y+5
#define mask Y+6
#define rsize Y+7
#define wsize Y+8
#define cmd Y+9
#define rdata Y+11
#define wdata Y+13
.global _spi_poll
_spi_poll:
push r28
push r29
ldi r28, lo8(spi)
ldi r29, hi8(spi)
ldd r18, mask
; r19, wait, …
ldd r20, isize
ldd r21, zero
ldd r22, rsize
ldi r23, 1<<TXC
; r24, [czw]size
; r25, INTFLAG
; X, [cw]data
ldd r30, rdata
ldd r31, rdata+1
ldd r24, csize
tst r24
breq 1f
ldd r26, cmd
ldd r27, cmd+1
rcall _write
std csize, r24
std cmd, r26
std cmd+1, r27
1: ldd r24, zsize
tst r24
breq 1f
mov r26, r1
mov r27, r1
rcall _write
std zsize, r24
1: ldd r24, wsize
tst r24
breq 1f
ldd r26, wdata
ldd r27, wdata+1
rcall _write
std wsize, r24
std wdata, r26
std wdata+1, r27
1: std isize, r21
std rsize, r22
std rdata, r30
std rdata+1, r31
mov r24, 0
pop r29
pop r28
ret
_write_read:
lds r25, INTFLAGS
sbrs r25, DRE
rjmp 1f
ld r0, X+
sts DATA, r0
sts INTFLAGS, r23
subi r24, 1
breq _read_tail
sbrs r25, RXC
rjmp _write_read
lds r0, DATA
st Z+, r0
subi r22, 1
brne _write_read
rjmp _write_drop
_read_tail:
lds r25, INTFLAGS
sbrs r25, RXC
rjmp 1f
lds r0, DATA
st Z+, r0
subi r22, 1
breq 9f
1: sbrs r25, TXC
rjmp _read_tail
rcall _delay
sbrs r25, RXC
rjmp 9f
lds r0, DATA
st Z+, r0
subi r22, 1
9: ret
_w1: mov r20, r24 ; no rsize, i=n
_w2: sub r20, r24 ; isize = i-n
brcc _drop
add r24, r20 ; n = n + (i-n) = i
neg r20 ; next n = n-i
push r20
mov r20, r1 ; i = 0
rcall _drop
pop r24
_write:
tst r22
breq _w1
tst r20
brne _w2
mov r0, r26
or r0, r27
brne _write_read
_zero_read:
lds r25, INTFLAGS
sbrs r25, DRE
rjmp 1f
sts DATA, r21
sts INTFLAGS, r23
subi r24, 1
breq _read_tail
1: sbrs r25, RXC
rjmp _zero_read
lds r0, DATA
_zr: st Z+, r0
subi r22, 1
brne _zero_read
9: ret
_zero_wait:
lds r25, INTFLAGS
sbrs r25, DRE
rjmp 1f
sts DATA, r21
sts INTFLAGS, r23
subi r24, 1
breq _read_tail
1: sbrs r25, RXC
rjmp _zero_wait
subi r24, -1
lds r0, DATA
ldd r19, wait
eor r19, r0
and r19, r18
brne _zero_wait
subi r24, 1
rjmp _zr
_drop:
mov r0, r26
or r0, r27
brne _write_drop
tst r18
brne _zero_wait
_zero_drop:
lds r25, INTFLAGS
lds r0, DATA
sbrs r25, DRE
rjmp _zero_drop
sts DATA, r21
sts INTFLAGS, r23
subi r24, 1
brne _zero_drop
rjmp _drop_tail
_write_drop:
lds r25, INTFLAGS
lds r0, DATA
sbrs r25, DRE
rjmp _write_drop
ld r0, X+
sts DATA, r0
sts INTFLAGS, r23
subi r24, 1
brne _write_drop
_drop_tail:
lds r25, INTFLAGS
lds r0, DATA
sbrs r25, TXC
rjmp _drop_tail
rcall _delay
lds r0, DATA
9: ret
_delay:
ldi r19, 0xff
1: lds r25, INTFLAGS
sbrc r25, RXC
ret
subi r19, 1
brcc 1b
9: ret
_spi_poll_end: