From cb60104a10eac2865936681b936a72770cdb66c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20I=2E=20B=C3=B6ttcher?= Date: Mon, 30 Mar 2026 11:04:13 +0200 Subject: [PATCH 1/2] git_poll: assember implementation --- src/Makefile | 4 +- src/spi.c | 239 +++++++++++++++++++++++++++++++++++++++++++++++++ src/spi.h | 33 +++++++ src/spi_poll.S | 204 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 478 insertions(+), 2 deletions(-) create mode 100644 src/spi_poll.S diff --git a/src/Makefile b/src/Makefile index 60c61e7..a9cd663 100644 --- a/src/Makefile +++ b/src/Makefile @@ -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) \ diff --git a/src/spi.c b/src/spi.c index 85cf3fa..98a4329 100644 --- a/src/spi.c +++ b/src/spi.c @@ -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(); diff --git a/src/spi.h b/src/spi.h index e1e01cc..83c480f 100644 --- a/src/spi.h +++ b/src/spi.h @@ -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); diff --git a/src/spi_poll.S b/src/spi_poll.S new file mode 100644 index 0000000..c11c529 --- /dev/null +++ b/src/spi_poll.S @@ -0,0 +1,204 @@ +#include +#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< Date: Mon, 30 Mar 2026 12:14:14 +0200 Subject: [PATCH 2/2] config: fpga_config_page --- src/config.c | 4 ++++ src/config.h | 2 ++ 2 files changed, 6 insertions(+) diff --git a/src/config.c b/src/config.c index 25ee61e..9cca87f 100644 --- a/src/config.c +++ b/src/config.c @@ -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 }; //////////////////////////////////////////////////////////////////////////////// diff --git a/src/config.h b/src/config.h index 3412198..c87f9bb 100644 --- a/src/config.h +++ b/src/config.h @@ -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 {