From: Keith Packard Date: Fri, 12 Aug 2011 11:41:19 +0000 (-0700) Subject: altos-avr: Completely replace the spi slave code X-Git-Url: https://git.gag.com/?a=commitdiff_plain;h=b3ba69f3eda0d07d7f2fc0922556a011c95d7951;p=fw%2Faltos altos-avr: Completely replace the spi slave code Turns out the AVR we're using sucks at doing SPI slave. To get it running at a reasonable data rate, I had to completely gut the 'sensible' code and run everything from the ISR with interrupts disabled. Even with this, the maximum SPI clock rate is somewhere around 200kHz. That's due to the singled buffered nature of the transmit queue, the amount of time available between finishing one byte and starting the next is very very small. Signed-off-by: Keith Packard --- diff --git a/src-avr/ao.h b/src-avr/ao.h index c548c618..fb3612d4 100644 --- a/src-avr/ao.h +++ b/src-avr/ao.h @@ -201,7 +201,7 @@ struct ao_adc { * ao_adc.c */ -#define AO_ADC_RING 16 +#define AO_ADC_RING 8 #define ao_adc_ring_next(n) (((n) + 1) & (AO_ADC_RING - 1)) #define ao_adc_ring_prev(n) (((n) - 1) & (AO_ADC_RING - 1)) @@ -1343,6 +1343,7 @@ struct ao_fifo { (f).remove = ((f).remove + 1) & (AO_FIFO_SIZE-1); \ } while(0) +#define ao_fifo_reset(f) ((f).insert = (f).remove = 0) #define ao_fifo_full(f) ((((f).insert + 1) & (AO_FIFO_SIZE-1)) == (f).remove) #define ao_fifo_empty(f) ((f).insert == (f).remove) @@ -1423,12 +1424,15 @@ ao_debug_init(void); /* ao_spi_slave.c */ -void +int ao_spi_slave_read(uint8_t *data, int len); -void +int ao_spi_slave_write(uint8_t *data, int len); +void +ao_spi_slave_debug(void); + void ao_spi_slave_init(void); diff --git a/src-avr/ao_log_telescience.c b/src-avr/ao_log_telescience.c index 6022ad21..62e0493c 100644 --- a/src-avr/ao_log_telescience.c +++ b/src-avr/ao_log_telescience.c @@ -19,7 +19,7 @@ #include "ao_product.h" static struct ao_task ao_log_task; -static struct ao_task ao_spi_task; +//static struct ao_task ao_spi_task; uint8_t ao_log_running; uint8_t ao_log_mutex; @@ -233,47 +233,11 @@ ao_log_delete(void) printf ("Erased\n"); } -void -ao_spi_telescience(void) -{ - static union { - struct ao_companion_command command; - struct ao_companion_setup setup; - struct ao_adc data; - } u; - - for (;;) { - ao_spi_slave_read((uint8_t *) &u.command, sizeof (struct ao_companion_command)); - switch (u.command.command) { - case AO_COMPANION_SETUP: - u.setup.board_id = AO_idProduct_NUMBER; - u.setup.board_id_inverse = ~AO_idProduct_NUMBER; - u.setup.update_period = 10; - u.setup.channels = NUM_ADC; - ao_spi_slave_write((uint8_t *) &u.setup, - sizeof (struct ao_companion_setup)); - break; - case AO_COMPANION_FETCH: - ao_adc_get(&u.data); - ao_spi_slave_write((uint8_t *) &u.data.adc, - NUM_ADC * sizeof (uint16_t)); - if (u.command.flight_state >= ao_flight_boost && - u.command.flight_state < ao_flight_landed) { - if (!ao_log_running) - ao_log_start(); - } else { - if (ao_log_running) - ao_log_stop(); - } - break; - } - } -} - const struct ao_cmds ao_log_cmds[] = { { ao_log_set, "L <0 off, 1 on>\0Set logging mode" }, { ao_log_list, "l\0List stored flight logs" }, { ao_log_delete, "d 1\0Delete all stored flights" }, + { ao_spi_slave_debug, "s\0Dump SPI slave data" }, { 0, NULL }, }; @@ -285,5 +249,5 @@ ao_log_init(void) ao_cmd_register(&ao_log_cmds[0]); ao_add_task(&ao_log_task, ao_log_telescience, "log"); - ao_add_task(&ao_spi_task, ao_spi_telescience, "spi"); +// ao_add_task(&ao_spi_task, ao_spi_telescience, "spi"); } diff --git a/src-avr/ao_pins.h b/src-avr/ao_pins.h index b927bc4b..afe1e941 100644 --- a/src-avr/ao_pins.h +++ b/src-avr/ao_pins.h @@ -28,7 +28,7 @@ #define USE_SERIAL_STDIN 0 #define HAS_EEPROM 1 #define USE_INTERNAL_FLASH 0 - #define HAS_DBG 1 + #define HAS_DBG 0 #define DBG_ON_P1 1 #define DBG_ON_P0 0 #define IGNITE_ON_P2 1 @@ -54,7 +54,7 @@ #define HAS_ADC 1 #define HAS_EEPROM 1 #define USE_INTERNAL_FLASH 0 - #define HAS_DBG 1 + #define HAS_DBG 0 #define DBG_ON_P1 1 #define DBG_ON_P0 0 #define IGNITE_ON_P2 1 diff --git a/src-avr/ao_spi_slave.c b/src-avr/ao_spi_slave.c index 5f1990d5..8e01f586 100644 --- a/src-avr/ao_spi_slave.c +++ b/src-avr/ao_spi_slave.c @@ -16,83 +16,85 @@ */ #include "ao.h" +#include "ao_product.h" -__xdata struct ao_fifo ao_spi_slave_rx_fifo; -__xdata struct ao_fifo ao_spi_slave_tx_fifo; +static struct ao_companion_command ao_companion_command; +static const struct ao_companion_setup ao_companion_setup = { + .board_id = AO_idProduct_NUMBER, + .board_id_inverse = ~AO_idProduct_NUMBER, + .update_period = 50, + .channels = NUM_ADC +}; -static volatile uint8_t ao_spi_slave_tx_started; - -static void -ao_spi_slave_tx_start(void) +static void ao_spi_slave_recv(void) { - if (!ao_spi_slave_tx_started && !ao_fifo_empty(ao_spi_slave_tx_fifo)) { - ao_spi_slave_tx_started = 1; - ao_fifo_remove(ao_spi_slave_tx_fifo, SPDR); - } -} + uint8_t *buf; + uint8_t len; -ISR(SPI_STC_vect) -{ - uint8_t spsr; + len = sizeof (ao_companion_command); + buf = (uint8_t *) &ao_companion_command; + while (len--) { + while (!(SPSR & (1 << SPIF))) + ; + *buf++ = SPDR; + } - spsr = SPSR; - if (SPIF & (1 << SPIF)) { - uint8_t byte = SPDR; - if (!ao_fifo_full(ao_spi_slave_rx_fifo)) - ao_fifo_insert(ao_spi_slave_rx_fifo, byte); - ao_spi_slave_tx_started = 0; - ao_spi_slave_tx_start(); - ao_wakeup(&ao_spi_slave_rx_fifo); - ao_wakeup(&ao_spi_slave_tx_fifo); + /* Figure out the outbound data */ + switch (ao_companion_command.command) { + case AO_COMPANION_SETUP: + buf = (uint8_t *) &ao_companion_setup; + len = sizeof (ao_companion_setup); + break; + case AO_COMPANION_FETCH: + buf = (uint8_t *) &ao_adc_ring[ao_adc_ring_prev(ao_adc_head)].adc; + len = NUM_ADC * sizeof (uint16_t); + break; + default: + return; } -} -static void -ao_spi_slave_put(uint8_t b) __critical -{ - cli(); - while (ao_fifo_full(ao_spi_slave_tx_fifo)) - ao_sleep(&ao_spi_slave_tx_fifo); - ao_fifo_insert(ao_spi_slave_tx_fifo, b); - ao_spi_slave_tx_start(); - sei(); + /* Send the outbound data */ + while (len--) { + SPDR = *buf++; + while (!(SPSR & (1 << SPIF))) + ; + } + (void) SPDR; } -static uint8_t -ao_spi_slave_get(void) __critical -{ - uint8_t b; - - cli(); - while (ao_fifo_empty(ao_spi_slave_rx_fifo)) - ao_sleep(&ao_spi_slave_rx_fifo); - ao_fifo_remove(ao_spi_slave_rx_fifo, b); - sei(); - return b; -} +static uint8_t ao_spi_slave_running; -void -ao_spi_slave_read(uint8_t *data, int len) +ISR(PCINT0_vect) { - while (len--) { - ao_spi_slave_put(0); - *data++ = ao_spi_slave_get(); + if ((PINB & (1 << PINB0)) == 0) { + if (!(PCMSK0 & (1 << PCINT1))) + PCMSK0 |= (1 << PCINT1); + else { + PCMSK0 &= ~(1 << PCINT1); + cli(); + if (!ao_spi_slave_running) { + ao_spi_slave_running = 1; + ao_spi_slave_recv(); + } + sei(); + } + } else { + ao_spi_slave_running = 0; } } -void -ao_spi_slave_write(uint8_t *data, int len) -{ - while (len--) { - ao_spi_slave_put(*data++); - (void) ao_spi_slave_get(); - } +void ao_spi_slave_debug(void) { + printf ("slave running %d\n", ao_spi_slave_running); } void ao_spi_slave_init(void) { - SPCR = (1 << SPIE) | /* Enable SPI interrupts */ + PCMSK0 |= (1 << PCINT0); /* Enable PCINT0 pin change */ + PCICR |= (1 << PCIE0); /* Enable pin change interrupt */ + + DDRB = (DDRB & 0xf0) | (1 << 3); + SPCR = (0 << SPIE) | /* Disable SPI interrupts */ (1 << SPE) | /* Enable SPI */ (0 << DORD) | /* MSB first */ (0 << MSTR) | /* Slave mode */ diff --git a/src-avr/ao_telescience.c b/src-avr/ao_telescience.c index f0f88c51..e8d4e0c2 100644 --- a/src-avr/ao_telescience.c +++ b/src-avr/ao_telescience.c @@ -29,6 +29,7 @@ main(void) ao_timer_init(); ao_cmd_init(); ao_spi_init(); + ao_spi_slave_init(); ao_storage_init(); ao_usb_init(); ao_adc_init(); diff --git a/src-avr/telescience/Makefile b/src-avr/telescience/Makefile index b50559a9..9b04fa6e 100644 --- a/src-avr/telescience/Makefile +++ b/src-avr/telescience/Makefile @@ -18,7 +18,7 @@ DUDECPUTYPE=m32u4 PROGRAMMER=usbtiny LOADCMD=avrdude LOADARG=-p $(DUDECPUTYPE) -c $(PROGRAMMER) -e -U flash:w: -CC=avr-gcc -v +CC=avr-gcc OBJCOPY=avr-objcopy ifndef VERSION @@ -59,7 +59,7 @@ PRODUCT=TeleScience-v0.1 MCU=atmega32u4 PRODUCT_DEF=-DTELESCIENCE IDPRODUCT=0x000a -CFLAGS += -g -mmcu=$(MCU) -Wall -Wstrict-prototypes -Os -mcall-prologues $(PRODUCT_DEF) -I. -DAVR +CFLAGS += -g -mmcu=$(MCU) -Wall -Wstrict-prototypes -O3 -mcall-prologues $(PRODUCT_DEF) -I. -DAVR NICKLE=nickle