181 lines
5.6 KiB
Plaintext
181 lines
5.6 KiB
Plaintext
AT91SAM7 firmware for RC632 based reader.
|
|
|
|
0. Architecture
|
|
|
|
We have a Philips CL RC632 connected via SPI to the AT91SAM7.
|
|
The AT91SAM7 has a USB device port that is connected to a USB host.
|
|
|
|
|
|
1. USB Protocol / Interface
|
|
|
|
The AT91SAM7 has four USB endpoints, of which one is used for the control pipe,
|
|
and three are available for the user application.
|
|
|
|
Ideally, the device will provide two configurations, each with one interface
|
|
providing three endpoints: IN, OUT, INTERRUPT.
|
|
|
|
|
|
|
|
2. Interface configurations
|
|
|
|
2.1 Dumb interface
|
|
|
|
In this mode, the AT91SAM7 acts as a stupid interface between SPI and USB. It
|
|
provides access to the following primitives:
|
|
|
|
- Write Register
|
|
- Read Register
|
|
- Write FIFO
|
|
- Read FIFO
|
|
- Write Virtual FIFO
|
|
- Read Virtual FIFO
|
|
- Signal Interrupt
|
|
|
|
Since the FIFO of the RC632 are only 64byte deep, and the USB latency is too
|
|
big to facilitate FIFO refill while transmit, esp. at 424/848kbps RFID bitrate,
|
|
the AT91SAM7 has to provide bigger 'virtual' FIFO buffers to the USB host.
|
|
|
|
Thus, the USB host can fill a 1024byte-sized buffer using multiple USB packets,
|
|
and then ask the AT91SAM7 to write the first 64bytes to the FIFO. The RC632
|
|
will be programmed by the USB host to generate FIFO Level interrupts, to which
|
|
the AT91SAM7 will react automatically and re-fill the RC632 FIFO until all host
|
|
data has been sent to the RC632.
|
|
|
|
For the FIFO RX path, the opposite pattern is used: The AT91SAM7 has a 1024 byte
|
|
sized buffer, into which data can be read from the FIFO.
|
|
|
|
|
|
2.2 Intelligent interface
|
|
|
|
This interface will be optionally implemented at some later point. It provides
|
|
a 14443 protocol implementation inside the AT91SAM7.
|
|
|
|
|
|
2. Interface configurations
|
|
|
|
2.1 Dumb interface
|
|
|
|
EP0 control
|
|
EP1 bulk in
|
|
EP2 bulk out
|
|
EP3 interrupt
|
|
|
|
|
|
3. USB Protocol
|
|
|
|
3.1 dumb interface
|
|
|
|
struct usb_pcd_out_hdr {
|
|
u_int8_t cmd; /* command */
|
|
u_int8_t flags;
|
|
u_int8_t reg; /* register */
|
|
u_int8_t res;
|
|
u_int16_t len;
|
|
u_int8_t data[0];
|
|
} __attribute__ ((packed));
|
|
|
|
#define USB_PCD_CMD_WRITE_REG 0x01
|
|
#define USB_PCD_CMD_WRITE_FIFO 0x02
|
|
#define USB_PCD_CMD_WRITE_VFIFO 0x03
|
|
#define USB_PCD_CMD_READ_REG 0x11
|
|
#define USB_PCD_CMD_READ_FIFO 0x12
|
|
#define USB_PCD_CMD_WRITE_VFIFO 0x13
|
|
|
|
TBD
|
|
|
|
3.2 Intelligent interface
|
|
|
|
TBD
|
|
|
|
|
|
4. Firmware code flow architecture
|
|
|
|
The general idea is to make the firmware as interrupt-driven as possible.
|
|
Synchronous waiting for I/O (SPI, USB, ...) should be avoided, and restricted
|
|
to slow path operations (such as USB configuration) only.
|
|
|
|
Another design goal is to avoid using a dynamic memory allocator. Dynamic
|
|
memory allocation can be costly, leads to all sorts of fragmentation problems,
|
|
and will lead to the question of what to do in the case of an OOM situation.
|
|
|
|
Therefore, all data structures such as buffers will be pre-allocated and
|
|
declared as static variables.
|
|
|
|
4.x Data structures
|
|
|
|
Any action of the PCD is host-driven. Therefore, the UDC maintains a set
|
|
(2..32) request context structures. Upon completion of a USB OUT EP DMA,
|
|
the corresponding request context is passed on to other parts of the code.
|
|
Once the reply to that request has been processed, the context structure
|
|
is released.
|
|
|
|
The context structures are statically allocated, and a single u_int32_t
|
|
represents a bitmask of busy context structures. ffs() or a similar function
|
|
is used to search for a free buffer using which the UDC RX DMA can be refilled.
|
|
|
|
|
|
4.1 Examples
|
|
|
|
4.1.1 Performing SPI Register Read
|
|
|
|
[ UDC has configured RX FIFO for reception of usb packets ]
|
|
- UDC issues interrupt that USB endpoint receive has completed (FIFO)
|
|
- UDC driver defragments multiple packets into one transfer [optional]
|
|
- UDC driver submits another buffer for DMA reception
|
|
- UDC driver parses PCD ommand header and calls rc632 API
|
|
- RC632 driver configures SPI DMA transceive
|
|
- End of UDC interrupt
|
|
- idle loop
|
|
- SPI DMA completion interrupt happens for TX [do nothing]
|
|
- SPI DMA completion interrupt happens for RX
|
|
- callback into UDC driver using request state data
|
|
- UDC driver sends IN packet/transfer back to host
|
|
- End of SPI DMA interrupt
|
|
|
|
4.1.2 Performing SPI register read
|
|
|
|
much like register write, although the deferred completion could be skipped and
|
|
the usb transfer approved immediately after having submitted the SPI write
|
|
request to the RC632
|
|
|
|
5.1.3 Performing FIFO read
|
|
|
|
much like register read. Only difference is size and duration of transfer
|
|
|
|
5.1.4 Performing FIFO write
|
|
|
|
much like register write. Only difference is size and duration of transfer
|
|
|
|
5.1.5 Performing virtual FIFO read
|
|
|
|
much like a FIFO write, but make sure to enable FIFO watermark IRQ in RC632.
|
|
|
|
5.1.6 Performing virtual FIFO write
|
|
|
|
much like a FIFO read, but make sure to enable FIFO watermark IRQ in RC632.
|
|
Response to USB host is only sent after the full virtual FIFO has been emptied
|
|
into the physical FIFO.
|
|
|
|
5.1.6 Reporting RC632 interrupts
|
|
|
|
Upon reception of a RC632 interrupt, the primary and secondary status registers
|
|
are read from the IRQ handler, and an USB packet on the Interrupt In enddpoint is
|
|
created and submitted for transmission.
|
|
|
|
Some special handling (filtering) of FIFO over/underrun interrupts has to be
|
|
implemented for transparent handling of the virtual FIFO.
|
|
|
|
5.1.7 Reporting virtual FIFO interrupts
|
|
|
|
The virtual FIFO itself can generate over/underrun interrupts on the USB. They
|
|
are signalled pretty much like real RC632 interrupts.
|
|
|
|
|
|
6. Interrupt priorities
|
|
|
|
UDC DMA low priority, since we don't want to overflow with usb packets?
|
|
SPI DMA higher than UDC since it might complete while in UDC code?
|
|
RC632_IRQ high priority, since FIFO refill might be required
|
|
DEBUG_UART do we want it to use IRQ at all? if yes it should have highest prio.
|
|
|