RFC: Small additions to the atusb driver code

Stefan Schmidt stefan at datenfreihafen.org
Thu Jun 23 06:54:00 EDT 2011


Hello.

On Thu, 2011-06-23 at 06:26, Werner Almesberger wrote:
> Richard Sharpe wrote:
> > I will have to go back and look at the documentation, but you are
> > probably correct.
> 
> A quick update on how atusb presents itself on USB now:
> 
> - two interfaces: #0 is the good old atusb. This is what any atusb
>   application should use. #1 is to prepare switching into DFU mode,
>   for use by dfu-util.

OK. So we ignore interface 1 on the kernel driver side.

> - two endpoints (on interface #0): EP0  is the usual control
>   endpoint, EP 1 is a bulk input, used to signal interrupts.

OK

> EP 1 should eventually become an interrupt endpoint, but that seems
> to be more of a cosmetical change than a functional one.
> 
> EP 1 currently works like this: if there's a transceiver interrupt,
> the AVR reads IRQ_STATUS and enqueues this byte on EP 1, clearing
> the interrupt. If another interrupt occurs before the previous
> interrupt data has been retrieved, is is ignored, with the idea
> being that the application/kernel reads IRQ_STATUS when waiting for
> interrupts.
> 
> This approach doesn't quite seem to work, not even in the sheltered
> world of my user-space applications. I think I'll remove reading
> IRQ_STATUS in the MCU, so that the host only receives a zero byte
> indicating that an interrupt has happened, but not trying to tell
> it which.

Passing the IRQ through and letting the host driver take care of
reading the register on its own. Lets hope we don't hit any timing
problems with this approach.

> This still leaves a few races if we try to use the transceiver as
> if it wasn't on USB. E.g., if we receive a frame just an instant
> before switching the transceiver from receiving to sending, we have
> a pending send/receive interrupt (transmit and receive interrupts
> are shared, TRX_END). Once the switch is done, there can be no
> 
> - transceiver is in state RX_ON (receive any incoming frame)
> 
> - frame arrives, setting TRX_END
> 
> - MCU enqueues an interrupt notification on EP 1
> 
> - not yet aware of the new frame, host decides to transmit a frame

The problem that the received frame is still in the buffer while the
new one should be written into it is something we can solve with
emulating two different buffer for rx and tx. That would also be true
for having two different interrupts instead a shared one.

The downside is that we have more complex MCU code and need to change
some of the logic of the original driver. That may be a bit to much of
a downside to consider this. Hmm...

> - host commands a transition from RX_ON to PLL_ON (PLL_ON means
>   that we're ready to send or receive but presently do neither)
> 
> - host waits until all interrupts already pending at the host are
>   processed (so that we're sure anything that happened before we
>   stopped receiving has been processed). Since we haven't seen the
>   byte waiting at the MCU in EP 1 yet, we do nothing.
> 
> - USB gets around to fetch the data at EP 1
> 
> - host learns of the new interrupt, at a time no TRX_END
>   interrupts are possible
> 
> - host gets confused
> 
> That's the conundrum I'm currently banging my head on.
> 
> > 2. Decide on a git repository for committing code ...
> 
> How about qi-hardware's qi-kernel ? This is where I keep my branch.
> Richard already has commit access.

Fine with me. Will use it as base for my updated patch set later
today.

> > 4. Perhaps finish of this driver to expose all the relevant registers
> > via /sys/class/xxx/etc
> 
> Hmm, if things keep on going in the direction of this just being
> an SPI device, the driver wouldn't actually know what registers
> are. All it would see are certain patterns of SPI transfers that
> it translates into the three ATUSB_SPI_* request types.
> 
> The ATUSB_SPI_* requests we have:
> 
> - ATUSB_SPI_WRITE: send >= 2 bytes on SPI, without receiving anything.
>   The first two bytes are passed in wValue and wIndex, the rest in the
>   data phase. If we only have two bytes (e.g., in a register write),
>   there's no data phase.
> 
>   This is for register writes, frame buffer writes, and SRAM writes.
> 
> - ATUSB_SPI_READ1: send one byte (wValue), then receive any number of
>   bytes in the data phase.
> 
>   This is for register reads and frame buffer reads. 
> 
> - ATUSB_SPI_READ2: send two bytes (wValue and wIndex), then receive
>   any number of bytes in the data phase.
> 
>   This is for SRAM reads.
> 
> An SPI driver for atusb would simply look at the requests it gets and
> see if it can fit them into any of these patterns. If not, it would
> complain and return an error.

As I said on IRC I like the abstraction of this...

> Note that I'm not sure yet if this is a good direction. If there's no
> other solution to the USB interrupt problem than adapting the
> driver's control flow, then we can just use the old
> ATUSB_{REG,BUF,SRAM}_* requests.

...while I think this is more straight forward.

regards
Stefan Schmidt




More information about the discussion mailing list


interactive