From 42483d67b4b8800752870c261bc340896861a1db Mon Sep 17 00:00:00 2001 From: Werner Almesberger Date: Thu, 7 Jul 2011 15:51:07 -0300 Subject: [PATCH] atusb/fw/: added improved support for interrupt synchronization At an interrupt barrier, the host must be able to ensure that no interrupt generated before reaching the barrier is still pending and will be delivered after crossing the barrier. For this, we introduce the following concept: - interrupts have a serial number. This number is sent to the host on EP 1 (currently bulk) to signal the interrupt, instead of the zero byte we used previously. - the new request ATUSB_SPI_WRITE2_SYNC returns the interrupt serial number from after the register write (the register write itself is the interrupt barrier). - the host can now check if the serial indicated from bulk and the serial from ATUSB_SPI_WRITE2_SYNC are the same. If yes, interrupts are synchronized. If not, it has to wait for the interrupt to be signaled on EP 1. We should also consider the case that the interrupt serial has gotten ahead of ATUSB_SPI_WRITE2_SYNC. But that seems to happen rarely. In any case, it's something for the host driver to worry about, not for the firmware. - board.h (irq_serial), board_app.c (irq_serial, INT0_vect): count the interrupt serial number and return it when signaling the interrupt - include/atusb/ep0.h (ATUSB_SPI_WRITE2_SYNC), ep0.c (my_setup): new request ATUSB_SPI_WRITE2_SYNC that does a register write, then returns the interrupt serial --- atusb/fw/board.h | 1 + atusb/fw/board_app.c | 8 +++++--- atusb/fw/ep0.c | 10 ++++++++++ atusb/fw/include/atusb/ep0.h | 2 ++ 4 files changed, 18 insertions(+), 3 deletions(-) diff --git a/atusb/fw/board.h b/atusb/fw/board.h index 9f16e5a..09ec915 100644 --- a/atusb/fw/board.h +++ b/atusb/fw/board.h @@ -73,6 +73,7 @@ #define HAS_BOARD_SERNUM extern uint8_t board_sernum[42]; +extern uint8_t irq_serial; void reset_rf(void); diff --git a/atusb/fw/board_app.c b/atusb/fw/board_app.c index 80eed69..22b93c3 100644 --- a/atusb/fw/board_app.c +++ b/atusb/fw/board_app.c @@ -150,13 +150,15 @@ static void done(void *user) } +uint8_t irq_serial; + + ISR(INT0_vect) { - static uint8_t buf; - if (eps[1].state == EP_IDLE) { led(1); - usb_send(&eps[1], &buf, 1, done, NULL); + irq_serial++; + usb_send(&eps[1], &irq_serial, 1, done, NULL); } } diff --git a/atusb/fw/ep0.c b/atusb/fw/ep0.c index 83ab075..c1be341 100644 --- a/atusb/fw/ep0.c +++ b/atusb/fw/ep0.c @@ -217,6 +217,16 @@ static int my_setup(const struct setup_request *setup) else do_buf_write(NULL); return 1; + case ATUSB_FROM_DEV(ATUSB_SPI_WRITE2_SYNC): + spi_begin(); + spi_send(setup->wValue); + spi_send(setup->wIndex); + spi_end(); + buf[0] = irq_serial; + if (setup->wLength) + usb_send(&eps[0], buf, 1, NULL, NULL); + return 1; + case ATUSB_FROM_DEV(ATUSB_SPI_READ1): case ATUSB_FROM_DEV(ATUSB_SPI_READ2): spi_begin(); diff --git a/atusb/fw/include/atusb/ep0.h b/atusb/fw/include/atusb/ep0.h index 391b114..55bc222 100644 --- a/atusb/fw/include/atusb/ep0.h +++ b/atusb/fw/include/atusb/ep0.h @@ -39,6 +39,7 @@ * host-> ATUSB_SPI_WRITE byte0 byte1 #bytes * ->host ATUSB_SPI_READ1 byte0 - #bytes * ->host ATUSB_SPI_READ2 byte0 byte1 #bytes + * ->host ATUSB_SPI_WRITE2_SYNC byte0 bute1 0/1 */ /* @@ -91,6 +92,7 @@ enum atspi_requests { ATUSB_SPI_WRITE = 0x30, /* SPI group */ ATUSB_SPI_READ1, ATUSB_SPI_READ2, + ATUSB_SPI_WRITE2_SYNC, };