diff --git a/src/.gitignore b/src/.gitignore index 2921dc0..2f8c9ea 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -1,2 +1 @@ thhor.userrow -*.s diff --git a/src/Makefile b/src/Makefile index 60c61e7..5d8d444 100644 --- a/src/Makefile +++ b/src/Makefile @@ -11,13 +11,22 @@ thhor_all: thhor.eeprom thhor.userrow CFLAGS_thhor = -Ibch4369 -DHAVE_FPGA -DSEND_HEX -DTHHOR MCU_thhor = attiny3224 SN_thhor = 1 -# Link order defines ADC packet composition -# main() is first, with .bss.magic -# 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 +C_FILES_thhor = config.c uart.c cmd.c base85.c rtc.c adc.c pwm.c spi.c flash.c bch4369.c pipe.c fpga.c S_FILES_thhor = uart_tx.S base85a.S +dose_all: dose.eeprom dose.userrow +SN_dose = 1 +MCU_dose = $(MCU_$(VAR)) +MCU_nFETs = attiny424 +MCU_FPGA = attiny3224 + +VAR=nFETs +C_FILES_nFETs = +C_FILES_FPGA = fpga.c +CFLAGS_dose = -DHAVE_$(VAR) +C_FILES_dose = config.c rtc.c adc.c pwm.c $(C_FILES_$(VAR)) uart.c cmd.c pipe.c base85.c bch4369.c spi.c flash.c +S_FILES_dose = uart_tx.S base85a.S + MCU = $(MCU_$(PROJ)) OPT = -Os @@ -73,24 +82,23 @@ pMCU-attiny824 = t824 pMCU-attiny3224 = t3224 # WDT -fuse0_thhor= 0x00 +fuse0_dose= 0x00 # BOD -fuse1_thhor= 0x00 +fuse1_dose= 0x00 # OSC, 20 MHz -fuse2_thhor= 0x7e -# Reserved -fuse3_thhor= 0xff -# Reserved -fuse4_thhor= 0xff +fuse2_dose= 0x7e +# ??? +fuse4_dose= 0xff # SYS0 (default 0xf6) RESET, EEPROM erase -fuse5_thhor= 0xf7 +fuse5_dose= 0xf7 # SYS1 startup time (64ms) -fuse6_thhor= 0xff +fuse6_dose= 0xff # APPEND -fuse7_thhor= 0x00 +fuse7_dose= 0x00 # BOOTEND -fuse8_thhor= 0x00 -fuses_thhor =$(patsubst %, 0x%, 00 00 7e ff ff f7 ff 00 00) +fuse8_dose= 0x00 +fuses_dose =$(patsubst %, 0x%, 00 00 7e ff ff f7 ff 00 00) +fuses_thhor = $(fuses_dose) AVRDUDEPROG = avrdude AVRDUDE = $(AVRDUDEPROG) @@ -99,6 +107,8 @@ AVRDUDE_PORT = /dev/ttyUSB0 AD = $(AVRDUDE) -p $(pMCU-$(MCU)) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER) + + sig_dose = 0x1e 0x92 0x2c sig_thhor = 0x1e 0x95 0x28 diff --git a/src/cmd.c b/src/cmd.c index b687341..dd3edc5 100644 --- a/src/cmd.c +++ b/src/cmd.c @@ -244,38 +244,17 @@ void parse_command(const uint8_t *s, uint8_t n) goto send_buffer; break; case 'P': - if (cmd_flag('!')) - pipe.dest = 0; if (have_b) - pipe_config((void*)cmd_buffer, (void*)bptr); + pipe_config((void*)cmd_buffer); r = pipe_poll(); break; #ifdef HAVE_FPGA case 'O': r = fpga_power(); - if (bflg & 1) - // "O1" power off + if (bflg == 1) fpga_power_off(); - if (bflg >= 2) { - // "O2" power on + else if (bflg == 2) fpga_power_on(); - if (!r) { - fpga_reset(); - break; - } - } - if (bflg <= 2) - break; - if (bflg <= 8 && r==as_configured) - // "O2": configure if unconfigured - break; - if (bflg & 8) { - // "O3": power of if unconfigured - fpga_power_off(); - break; - } - // "O4" configure unconditionally - fpga_config(config.fpga_config_page, config.fpga_config_count); break; case 'C': if (cmd_flag('@')) { diff --git a/src/config.h b/src/config.h index 3412198..39d346d 100644 --- a/src/config.h +++ b/src/config.h @@ -23,8 +23,6 @@ struct config { uint16_t pwm_min; uint16_t pwm_max; #endif - uint16_t fpga_config_page; - uint16_t fpga_config_count; }; enum magic_flags { @@ -34,7 +32,7 @@ enum magic_flags { #endif #ifdef HAVE_FPGA MAGIC = 0xC5, - VERSION = 0x00, + VERSION = 0x01, #endif }; @@ -161,8 +159,6 @@ extern struct magic { #if 0 #define _memcopy memcpy #define _memcopyyz memcpy -#define _memcopyzy memcpy -#define _memcmpyz memcmp #else // avoid the avr-libc memcpy. // ¡ n must not be zero ! @@ -196,43 +192,6 @@ void _memcopyyz(uint8_t *d, uint8_t *s, uint8_t n) :: "r0", "memory"); } -static inline -void _memcopyzy(uint8_t *d, uint8_t *s, uint8_t n) -{ - __asm__ volatile ("\n" - "1:" "\n\t" - "ld r0, Y+" "\n\t" - "st Z+, r0" "\n\t" - "dec %[N]" "\n\t" - "brne 1b" "\n" - : [D] "+z" (d), - [S] "+y" (s), - [N] "+r" (n) - :: "r0", "memory"); -} - -static inline -uint8_t _memcmpyz(uint8_t *d, uint8_t *s, uint8_t n) -{ - uint8_t r; - __asm__ volatile ( - "\n" - "1:" "\n\t" - "ld %[R], Y+" "\n\t" - "ld r0, Z+" "\n\t" - "sub %[R], r0" "\n\t" - "breq 1f" "\n\t" - "dec %[N]" "\n\t" - "brne 1b" "\n" - "1:" "\n" - : [D] "+x" (d), - [S] "+y" (s), - [N] "+r" (n), - [R] "=r" (r) - : - : "r0", "memory"); - return r; -} #endif diff --git a/src/eeprom.ld b/src/eeprom.ld index b72db90..0654d25 100644 --- a/src/eeprom.ld +++ b/src/eeprom.ld @@ -4,14 +4,14 @@ */ MEMORY { - eemap (rw!x) : ORIGIN = 0x801400, LENGTH = 0x100 - eedef (rw!x) : ORIGIN = 0x810000, LENGTH = 0x100 - uumap (rw!x) : ORIGIN = 0x801300, LENGTH = 0x020 - uudef (rw!x) : ORIGIN = 0x850000, LENGTH = 0x020 + eemap : ORIGIN = 0x1400, LENGTH = 0x100 + eedef : ORIGIN = 0x810000, LENGTH = 0x100 + uumap : ORIGIN = 0x1300, LENGTH = 0x20 + uudef : ORIGIN = 0x850000, LENGTH = 0x20 } SECTIONS { - .eemap 0x801400: + .eemap 0x1400: { ee1_start = .; *(.eeprom1) @@ -22,7 +22,7 @@ SECTIONS ee9_end = .; ee9_size = ee9_end - ee9_start; } >eemap AT >eedef - .uumap 0x801300: + .uumap 0x1300: { *(.userrow) } >uumap AT >uudef diff --git a/src/flash.h b/src/flash.h index 46af975..c509eee 100644 --- a/src/flash.h +++ b/src/flash.h @@ -28,7 +28,6 @@ uint8_t flash_cmd(uint16_t mode, uint16_t what, uint16_t page, uint16_t byte); extern uint8_t flash_buffer[FB_SIZE]; uint8_t flash_submit_command(uint8_t *cmd); uint8_t flash_start_stream(uint16_t page, uint16_t npages, uint8_t flags); -uint8_t flash_stream_done(); uint8_t flash_poll(uint8_t rr); uint16_t flash_find_free(); @@ -54,6 +53,4 @@ enum { FS_528 = 128, // do 528 byte pages. }; -static inline uint8_t flash_current_block() { return fs.block; } - #endif diff --git a/src/fpga.c b/src/fpga.c index 8b7a770..07d549d 100644 --- a/src/fpga.c +++ b/src/fpga.c @@ -2,7 +2,6 @@ #include "pipe.h" #include "fpga.h" #include "spi.h" -#include uint8_t fpga_reset_poll() { @@ -13,18 +12,6 @@ uint8_t fpga_reset_poll() return r; } -uint8_t fpga_status() -{ - uint8_t r = fpga_power(); - // all three altera pins must be on the same PORT - if (r) - r |= CRCERR_VPORT.IN & - ( 1<n; uint8_t z = c->z; - if (fpga_status() != as_configured) { - c->n = n | fpga_dead; + if (fpga_reset_poll()) { + c->n = n | fpga_busy; return; } if (n & fpga_abort && spi_abort()) { @@ -54,7 +41,7 @@ void fpga_cmd(struct fpga_cmd *c) return; c->n = n | fpga_submitted; - spi_select(n & fpga_configure ? SPI_CONFIG : 0); + spi_select(n & fpga_config ? SPI_CONFIG : 0); spi.csize = n &= fpga_size; spi.zero = z & 0x80; // send 0x0000 or 0x8080 spi.cmd = c->d; @@ -75,106 +62,25 @@ void fpga_cmd(struct fpga_cmd *c) spi_start(); } -struct pipe_fpga_cmd pipe_fpga_cmd; - -uint8_t fpga_start_write() +void fpga_start(uint8_t write) { - uint8_t mode = pipe.fpga.status & SPI_CONFIG; + uint8_t mode = 0; + if (pipe.fpga.zero == SPI_CONFIG) + mode = SPI_CONFIG; spi_select(mode); + _memcopy(&spi.csize, &pipe.fpga.csize, 6); + spi.cmd = pipe.fpga.cmd; spi.wdata = flash_buffer; - uint8_t n = 32; - if (pipe.fpga.count) - pipe.fpga.count--; - else { - uint8_t nn = pipe.fpga.size; - if (nn < n) - n = nn; - pipe.fpga.size -= n; - } - spi.wsize = n<<1; - if (n) - spi_start(); - return n; -} - -uint8_t fpga_start_read() -{ - /************************************************************ - * Send `counts` commands to the FPGA. - * Read `size` Words from each command. - * Fill the `flash_buffer` with 32 Words. - * AS_CONT: - * Continue reading Words after the buffer was used. - * User resets spi.fpga.val when done. - * Return the number of Words to be read now. - ***********************************************************/ - - if (spi_select(0)) - return 0; - if (fpga_status() != as_configured) - return 0; - if (!pipe.fpga.val) - memset(flash_buffer, 0, 64); - uint8_t n = 64 - pipe.fpga.val; + spi.rdata = flash_buffer; + uint8_t n = 64; + if (n > pipe.fpga.size) + n = pipe.fpga.size; + pipe.fpga.size -= n; if (!n) - return n; - spi.rdata = flash_buffer + pipe.fpga.val; - n >>= 1; - if (~pipe.fpga.status & AS_CONT) { - if (!pipe.fpga.count) - return 0; - pipe.fpga.count--; - spi.cmd = pipe_fpga_cmd.cmd; - _memcopy((void*)&spi.csize, (void*)&pipe_fpga_cmd, 6); - pipe.fpga.pos = 0; - pipe.fpga.status |= AS_CONT; - } - uint8_t nn = pipe.fpga.size - pipe.fpga.pos; - if (nn && nn < n) - n = nn; - pipe.fpga.pos += n; - if (pipe.fpga.pos == pipe.fpga.size) - pipe.fpga.status &=~ AS_CONT; - spi.rsize = n << 1; - pipe.fpga.val += spi.rsize; - spi_start(); - return n; -} - -uint8_t fpga_pipe_ready() -{ - /************************************************************ - * Return the number of valid Words read in to the buffer, - * when - * - the FPGA is alive, and - * - the buffer is full, or - * - there is nothing more to read. - * Reset pipe.fpga.val, when returning nonzero, - * assuming those Words will be used now. - ***********************************************************/ - - uint8_t r = pipe.fpga.val; - if (fpga_status() != as_configured) - return 0; - if (r >= 64 || !pipe.fpga.count && ~pipe.fpga.status & AS_CONT) - pipe.fpga.val = 0; + return; + if (write) + spi.wsize = n; else - r = 0; - return r; -} - -const struct pipe pipe_config_fpga_config = { - .source = pipe_flash, - .dest = pipe_fpga, - .fpga = { - .status = AS_CONFIG, - }, -}; - -void fpga_config(uint16_t page, uint16_t count) -{ - fpga_reset(); - pipe = pipe_config_fpga_config; - pipe.fpga.count = count; - flash_start_stream(page, count>>8, FS_Read|FS_528); + spi.rsize = n; + spi_start(); } diff --git a/src/fpga.h b/src/fpga.h index 7576d36..109d992 100644 --- a/src/fpga.h +++ b/src/fpga.h @@ -13,8 +13,7 @@ enum fpga_flags { fpga_aborted = 0x10, fpga_busy = 0x20, fpga_submitted = 0x40, - fpga_configure = 0x80, - fpga_dead = 0x80, + fpga_config = 0x80, fpga_wait_nonzero = 0x01, }; @@ -22,21 +21,8 @@ enum fpga_flags { void fpga_reset(); uint8_t fpga_reset_poll(); void fpga_cmd(struct fpga_cmd *c); -uint8_t fpga_start_read(); -uint8_t fpga_start_write(); -uint8_t fpga_pipe_ready(); -void fpga_config(uint16_t page, uint16_t count); +void fpga_start(uint8_t write); static inline uint8_t fpga_power() { return !!(PEN_VPORT.IN & (1<>4; + pipe.valid |= f>>4; _memcopy(flash_buffer+o, (void*)&magic, n); } adc_done: - // When the flash is done, flag the buffer valid, - // including BCH Bytes. - if (pipe.source & pipe_flash && fs.status & FS_Ready) - valid = bflgs; + if (pipe.source & pipe_flash && fl & FS_Ready) + pipe.valid = bflgs; #ifdef HAVE_FPGA - // The FPGA delivers 64 Bytes. - else if (pipe.source & pipe_fpga && fpga_pipe_ready()) - valid = 0x0f; + else if (pipe.source & pipe_fpga) + pipe.valid = 0x0f; #endif - // The buffer is not here, yet. Nothing we can do now. - if (~valid & 0x0f) + if (~pipe.valid & 0x0f) goto done; - - // The buffer shall include BCH Bytes. if (r & PS_BCH) { - // First buffer of a page, clear the parity - if (!(r & PS_BLK)) + if (!(r&3)) bch4369_init(config.bch_salt); - // Add the current buffer to the parity uint8_t *bend = bch4369_stri(flash_buffer, 64); - // Last buffer of the page: - if (!(~r & PS_BLK)) { - bch4369_fini(); - valid = 0x01f; - // When the Flash is not the source, - // copy the computed parity into the buffer. - if (~pipe.source & pipe_flash) - _memcopyyz(bend, bch_parity, 16); - // When the page as read from flash has invalid parity, - // stop writing to the FPGA. - else if (_memcmpyz(bch_parity, bend, 16)) { - dest &=~ pipe_fpga; - r |= PS_ERR; - } + if (!(~r & 3)) { + // reuse Y=bend + _memcopyyz(bend, bch_parity, 16); + pipe.valid = 0x01f; } } - // We still do not have all data we need - if (~valid & bflgs) + if (~pipe.valid & bflgs) goto done; - // The buffer is full, send it. - r |= PS_OUT; - #ifdef HAVE_FPGA - // Resume the FPGA stream - if (dest & pipe_fpga & ~fpga_start_write()) - dest &=~ pipe_fpga; - else + if (pipe.dest & pipe_fpga) + fpga_start(1); #endif - // Resume the flash stream - if (dest & pipe_flash) { - r &= ~ PS_BLK; - r |= flash_current_block() & PS_BLK; - flash_poll(1); - if (flash_stream_done()) - dest &=~ pipe_flash; - } + r |= PS_OUT; done: - pipe.dest = dest; - pipe.valid = valid; pipe.status = r; return r; } -void pipe_config(const struct pipe_config *c, const struct pipe_fpga_cmd *a) +void pipe_config(const struct pipe_config *c) { - /************************************************************ - * cmd("B0!", «fpga-cmd») optionally configure an FPGA cmd - * cmd("P0:, «pipe-cfg») with `AS_CMD` in `.status` - ***********************************************************/ - - if (c->pipe.dest) { - pipe = c->pipe; - if ((pipe.source | pipe.dest) & pipe_flash) - flash_start_stream(c->page, c->npages, c->flash); - } - else { - // new source (NOT flash) - pipe.source = c->pipe.source; - } + pipe = c->pipe; + if ((pipe.source | pipe.dest) & pipe_flash) + flash_start_stream(c->page, c->npages, c->flash); if (pipe.source & pipe_adc) adc_start_stream(pipe.adc); -#ifdef HAVE_FPGA - if (pipe.source & pipe_fpga) { - if (a && pipe.fpga.status & AS_CMD) - _memcopyzy((void*)&pipe_fpga_cmd, (void*)a, sizeof(*a)); - else - memset(&pipe_fpga_cmd, 0, sizeof(*a)); - fpga_start_read(); - } -#endif } + diff --git a/src/pipe.h b/src/pipe.h index 9d9c3f7..bb23d65 100644 --- a/src/pipe.h +++ b/src/pipe.h @@ -8,15 +8,10 @@ enum pipe_ports { pipe_fpga = 8, PS_OUT = 0x80, - PS_ERR = 0x40, - PS_BCH = 0x20, - PS_528 = 0x10, - PS_BLK = 0x07, + PS_BCH = 0x10, + PS_528 = 0x08, + PS_BLK = 0x03, PS_5 = PS_BLK | PS_528, // need 16 bytes more - - AS_CONT = 1, - AS_CONFIG = SPI_CONFIG, // = 2 - AS_CMD = 4, }; extern @@ -28,11 +23,14 @@ struct pipe { uint8_t adc; #ifdef HAVE_FPGA struct { - uint8_t status; // AS_… - uint16_t count; // number of cmds(read), 64 Bytes(write) - uint8_t size; // Words per cmd (read), extra Words (write), 0==256 - uint8_t val; // Valid Bytes in Buffer (read) - uint8_t pos; // Words read from current cmd (read) + uint16_t size; + uint8_t cmd[4]; + uint8_t csize; + uint8_t zsize; + uint8_t isize; + uint8_t zero; + uint8_t wait; + uint8_t mask; } fpga; #endif } pipe; @@ -44,18 +42,6 @@ struct pipe_config { uint8_t flash; }; -extern -struct pipe_fpga_cmd { - uint8_t csize; - uint8_t zsize; - uint8_t isize; - uint8_t zero; - uint8_t wait; - uint8_t mask; - uint8_t cmd[10]; -} pipe_fpga_cmd; - -uint8_t pipe_busy(); uint8_t pipe_poll(); void pipe_cron(); -void pipe_config(const struct pipe_config *c, const struct pipe_fpga_cmd *a); +void pipe_config(const struct pipe_config *c); diff --git a/src/spi.c b/src/spi.c index 85cf3fa..b1425ac 100644 --- a/src/spi.c +++ b/src/spi.c @@ -31,11 +31,6 @@ ISR(SPI0_INT_vect) d = spi.zero; } else if (spi.wsize) { - // TODO: - // spi.csize = spi.wsize; - // spi.wsize = 0; - // spi.cmd = spi.wdata; - // goto repeat; spi.wsize--; d = *spi.wdata++; } diff --git a/src/thhor.c b/src/thhor.c index e6a2869..32f291a 100644 --- a/src/thhor.c +++ b/src/thhor.c @@ -40,17 +40,8 @@ int main() send_hex_byte_eol(magic.reset_source); while (1) { - // The pipe may become idle before we reach sleep. - // Make sure we have nothing to do before we sleep. - // The sleep command will execute even when an irq - // is pending. It will wake us immediately. - cli(); - if (!command_pending() && (!pipe.dest || pipe_busy())) { - sei(); - sleep_cpu(); - } sei(); + sleep_cpu(); command(); - pipe_poll(); } } diff --git a/src/uart.h b/src/uart.h index f06a422..6438874 100644 --- a/src/uart.h +++ b/src/uart.h @@ -26,10 +26,3 @@ void send_hex_long(uint32_t b) extern uint8_t uart_rx_err; extern uint8_t uart_rx_errors; -extern volatile uint8_t uart_rx_mes; - -static inline -uint8_t command_pending() -{ - return uart_rx_mes; -}