November 12, 2023

Let's learn USB! -- Send and Receive

So, let's suppose our F103 has the USB subsystem all set up and initialized, how do we receive and/or send data on an endpoint.

Sending

Remember we can only send on an "IN" endpoint as "IN" is given its name by its role on the host system, and we are talking about the a device on the F103. Also remember that we can only send 64 bytes as that is the "legal limit" as well as the size of the endpoint buffer in PMA ram.

The first thing to do is copy the data to be sent into the proper place in PMA ram as defined by the buffer address pointer in the BTABLE. Remember that we have 16 bit words inside of 32 bit words give the way the PMA ram is accessed from the ARM bus.

Next, put the count into the proper place in the BTABLE.

Finally mark the endpoint as VALID in the endpoint register. The endpoint has two 2 bit status fields, one for Rx, one for Tx -- we want to mark the Tx field as VALID.

Once we have done this, the USB controller will eventually notice that we have valid data in the buffer and will send it. Once that is done, it will change the status from VALID to NAK and set the CTR bit (correct transfer) bit in the endpoint register if everything goes OK. Also, a CTR interrupt will be generated.

Receiving

The first thing that needs to be done is to set up the endpoint buffer. It doesn't matter what is in the buffer, but the count field in the BTABLE needs to be set up. In our case we have a 64 byte buffer, so we set count to 0x8400. The 0x8000 bit indicates we will specify the buffer size in units of 32 bytes. and 0x0400 indicates we have 2 of them, so the buffer is 64 bytes in size!

Once the buffer is set up, we need to mark it as VALID in the endpoint register before packets can be received. We have a 2 bit status field for Rx where we set VALID.

When a packet is actually received, we get a CTR interrupt if enabled, and CTR is set in the endpoint register for Rx. We can then look at the count field in the BTABLE, it will have the actual count in the low 10 bits (in our case only 7 bits since the count cannot exceed 0x40). The status field for Rx in the endpoint register will be changed to NAK to prevent further reception until the packet is processed.

We then copy the packet out of PMA memory, and mark the buffer as VALID again to allow another packet to be received.

What about data toggle?

I don't understand this yet. Data can be marked at DATA0 or DATA1 and there are rules about handling data toggling.

The endpoint register has a bit for this for both Rx and Tx.
For Rx, the statement is made that this bit indicates the expected state of the data toggle bit in the received packet.
For Tx, the statement is made that this bit indicates the required state of the data toggle bit in the next transmitted packet.

The papoon code does not manipulate this bit. It may, at least in some cases, have to do with double buffering.


Feedback? Questions? Drop me a line!

Tom's Computer Info / tom@mmto.org