mirror of
git://projects.qi-hardware.com/ben-wpan.git
synced 2024-11-04 23:14:06 +02:00
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
This commit is contained in:
parent
50595979f5
commit
42483d67b4
@ -73,6 +73,7 @@
|
||||
#define HAS_BOARD_SERNUM
|
||||
|
||||
extern uint8_t board_sernum[42];
|
||||
extern uint8_t irq_serial;
|
||||
|
||||
|
||||
void reset_rf(void);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user