USB transaction error completion code for Address Device Command with BSR = 0 - usb

I am writing a driver for the xHCI and I have been having a problem with the address assignment.
Here's what I am doing:
Reset the controller by writing 1 to the USBCMD.HCRST and wait for USBSTATUS.CONTROLLER_NOT_READY flag to clear.
Set the maximum slots enabled in the config register to 16 (which is the max supported by my xHC).
Allocate the device context base address register on a 64 byte aligned memory location and write that address to the dcbaap register.
allocate scratchpad buffers, write their addresses in an array, then write the address of that array in the 0th entry of the dcbaap.
Allocate a command ring and write its address in CRCR.
Set the R/S bit and wait for the controller not ready flag CNR to clear.
Allocate event ring, and event ring segment table with one entry, and write the address of table in ERSTBA
Then the software waits until a device is connected on port 12, I connect the device to port 12 and I can see the port goes to the enabled state as indicated by PP, CCS, PED being 1, and PR and PLS being 0.
Submit an enable slot command and I get an event on the event ring with a success completion code and a slot ID.
allocate output and input device contexts data structures and initialize them to valid values.
allocate transfer ring and write its address to the input context.
Submit the first address device command with BSR = 1 and I get an event on the event ring with success completion code.
Here is where things go wrong: submit the second address device command with BSR = 0, and I get USB transaction error for the completion code.
In the xhci spec rev 1.2, it says the USB transaction error is the result of a USB3 DPP(Data Packet Payload) Error. I looked in the USB3.2 rev 1 and it said DPP error could happen due to any of the following:
1.CRC incorrect
2.DPP aborted
3.DPP missing
4.Data Length in the Setup DPH does not match the actual data payload length.
I've been trying on this for about 2-3 weeks now and getting nowhere. I did see a post here where someone had this issue with the EHCI and they fixed it by reducing their delays. I tried to do a similar thing but still didn't fix it.
Does anyone have an idea why am I getting this error or how do I go about fixing it?
Something I want to note is that if skip step 8, an continue to enable slot command, I still get the same results. So I still get a device slot and I still get a successful first Address Device command even though there is no device connected. Which makes me think that the usb device isn't even talking? I'm using a thumb drive, I tried different thumb drives and different ports and still the same issue. I'm using a USB 3.0 thumb drive on a SS port.

Related

USB xHC, CRCR register not reading back written value

I'm going through the process of coding up an xHC interface following the Intel xHCI guide. I'm at the point where I need to give the controller the memory buffer address for the command ring (using the CRCR_LO and CRCR_HI registers).
However, after I write these values, I am not able to read it back to verify. The documentation indicates that the value will be updated after the next doorbell, but that doesn't seem to happen either.
I do see the CRR bit go high (command ring running), so it's at least doing something. But I am also not getting command responses in my event ring (though I am getting port status change messages in the event ring).
Can someone clarify how this register works? Is there a way to verify that command ring buffer address?

Issue with usb deregistration on linux kernel

I am using Linux 4.19.55 armv7l on a omap3 processor. On my target there is a usb modem that gets power from a gpio pin value (defined under /sys/class/gpio). There are occasions when I change the value parameter of this gpio pin to bring down the hardware and while doing so I frequently get an error (thrown by musb_handle_intr_disconnect from inside drivers/usb/musb/musb_core.c ) as under:
"musb_handle_intr_disconnect 843: unhandled DISCONNECT transition (a_idle)"
I tried debugging the issue by mounting debugfs and capturing data from the concerned bus by using usbmon. Bus id is identified from lsusb output and confirmed by observing /sys/kernel/debug/usb/devices. I observe that usbmon is unable to capture data whenever the mentioned error shows up. In a no error scenario the usbmon does capture the traffic from the concerned bus. Please help how to debug this issue.
Just checked that a commit on kernel branch fixes this issue which is present inside the states handled by the glue layer. This is the required commit

STM32f103 HAL USB - UART bridge

I have a third party device that is UART programmable.
I need to create a USB - UART bridge with a functional password (programming only after entering the correct password)
generated the code using the latest version of STM32CubeMX for Atollic TrueSTUDIO for STM32 9.3.0 ...
I transfer data between USB and UART through a buffer (one for usb-uart, and another one for uart-usb)
when I try to transfer several characters everything is OK, but when I try to transfer a large data packet, problems start due to the fact that the USB speed is much higher than the UART ...
there are two questions:
1.How do I tell USB that I need to stop transferring data and wait until the UART (buffer) is busy
2.How on the side of the microcontroller to get the baud rate set on the PC (set when the terminal is connected to the virtual COM port)
USB provides flow control. That's what you need to implement. A general introduction can be found here:
https://medium.com/#manuel.bl/usb-for-microcontrollers-part-4-handling-large-amounts-of-data-f577565c4c7d
Basically, the setup for the USB-to-UART direction should be:
Indicate that the code is ready to receive a USB packet
Receive a USB packet
Indicate that you are no longer ready to receive a USB packet
Transmit the data via UART
Start over
Step 0: Initial setup
Call USBD_CDC_SetRxBuffer to set the buffer for receiving the USB data. Unless you use several buffers to achieve higher throughput, a single call at the start of the program is sufficient.
Step 1: Ready to receive data
Call USBD_CDC_ReceivePacket. Other than what the name implies, this function indicates that the app is ready to receive data. It immediately returns before the data has actually been received.
Step 2: Receive a USB packet
You don't need to do anything here. It will happen automatically. Once it's complete, CDC_Itf_Receive will be called.
Step 3: Indicate that you are no longer ready to receive a USB packet
Nothing to do here. This happens automatically whenever a packet has been received (and double buffering is not enabled).
Step 4: Transmit the data via UART
I guess you know how to do this. It's up to you whether you want to do it in a blocking fashion or using DMA.
Since a callback is involved, you cannot put this code into the main loop. It might be possible to put all code into CDC_Itf_Receive if blocking UART is used. It would appear in the order 2, 3, 4, 1. Additionally, initialization is needed (0 and 1).
In the UART-to-USB direction, you would need to implement flow control on the UART. The USB flow control is managed by the host. Even though USB is much faster than UART, flow control is relevant as the application on the host can process data as slow as it likes to.
Regarding question 2: I'm not sure I understand it... The microcontroller cannot set the baud rate on the host. Either the host can specify a baud rate (transmitted over USB and applied to UART), or if the UART has a fixed baud rate, you can ignore baud rate (any baud rate set on the host side will work as it does not apply to USB).

Accurately measuring Time for an event ( relay contact closure) using GPS PPS

I have a relay contact closure event that needs to be timestamped accurately ( 1 msec) with a GPS and the PPS output... I am not sure how to feed the relay contact output to a microcontroller and then synchronize the microcontroller clock to the GPS ...plus how to get the UTC afterall?
Can you please help me.
thanks
If your microcontroller has at least two interrupts based on hardware pins, you could connect the relay to one of the interrupt-generating pins, and the PPS to the other interrupt-generating pin.
You will need to connect the NMEA (or other proprietary protocol of your GPS) to the corresponding port in your microcontroller. Some common buses are UART or SIP.
Then, every time that you get a PPS interrupt, you enable a global flag that can be used in the main loop to reset a counter. This counter will tell you how far apart from the PPS the relay switched (if it happens within that second). If you know the base frequency of your counter, you can convert the counter into fractions of seconds. Note that if both edges of the relay state change have to be detected, you will need an interrupt source capable to interrupt on both edges (or use two interrupts)
Then, if the Relay interrupt goes off, you can get the value of the counter upon interrupt, and save it in storage, send it to host, etc. (Note, it would be best to save the value in RAM, lift a flag of "value present", and leave the sending/storing to the main loop, then turning off the flag).
Finally, when you receive a complete NMEA message (this could be being parsed in your main loop by a state machine for instance), you can send this information to the host or storage along with the counter that you saved to time your relay state change. Note please that the NMEA message will be generated and decoded with a certain delay from the PPS, so you will need to compensate for that.

8051 UART, Receiving bytes serially

I have to send file byte-by-byte to serially connected AT89s52 from computer (VB.NET).
Every sended byte have some job to do in microcontroller what require some time.
Here is relevant part of my C code to receiving bytes:
SCON = 0x50;
TMOD = 0x20; // timer 1, mode 2, 8-bit reload
TH1 = 0xFD; // reload value for 9600 baud
TR1 = 1;
TI = 1;
again:
while(RI!=0)
{
P1=SBUF; // show data on led's
RI=0;
receivedBytes++;
}
if (key1==0)
{
goto exitreceive; // break receiving
}
show_lcd_received_bytes(receivedBytes);
// here is one more loop
// with different duration for every byte
goto again;
And here is VB.NET code for sending bytes:
For a As Integer = 1 To 10
For t As Integer = 0 To 255
SerialPort1.Write(Chr(t))
Next t
Next a
Problem is that mC have some job to do after every received byte and VB.NET don't know for that and send bytes too fast so in mC finishes just a part of all bytes (about 10%).
I can incorporate "Sleep(20)" in VB loop ant then thing will work but I have many of wasted time because every byte need different time to process and that would be unacceptable slow communication.
Now, my question is if 8051 can set some busy status on UART which VB can read before sending to decide to send byte or not.
Or how otherwise to setup such communication as described?
I also try to receive bytes with serial interrupt on mC side with same results.
Hardware is surely OK because I can send data to computer well (as expected).
Your problem is architectural. Don't try to do processing on the received data in the interrupt that handles byte Rx. Have your byte Rx interrupt only copy the received byte to a separate Rx data buffer, and have a background task that does the actual processing of the incoming data without blocking the Rx interrupt handler. If you can't keep up due to overall throughput issue, then RTS/CTS flow control is the appropriate mechanism. For example, when your Rx buffer gets 90% full, deassert the flow control signal to pause the transmit side.
As #TJD mentions hardware flow control can be used to stop the PC from sending characters while the microcomputer is processing received bytes. In the past I have implemented hardware flow by using an available port line as an output. The output needs to be connected to an TTL to RS-232 driver(if you are currently using a RS-232 you may have and extra driver available). If you are using a USB virtual serial port or RS-422/485 you will need to implement software flow control. Typically a control-S is sent to tell the PC to stop sending and a control-Q to continue. In order to take full advantage of flow control you most likely will need to also implement a fully interrupt driven FIFO to receive/send characters.
If you would like additional information concerning hardware flow control, check out http://electronics.stackexchange.com.
Blast from the past, I remember using break out boxes to serial line tracers debugging this kind of stuff.
With serial communication, if you have all the pins/wires utililzed then there is flow control via the RTS (Ready To Send) and DTR (Data Terminal Ready) that are used to signal when it is OK to send more data. Do you have control over that in the device you are coding via C? IN VB.NET, there are events used to receive these signals, or they can be queried using properties on the SerialPort object.
A lot of these answers are suggesting hardware flow control, but you also have the option of enhancing your transmission to be more robust by using software flow control. Currently, your communication is strong, but if you start running a higher baud rate or a longer distance or even just have a noisy connection, characters could be received that are incorrect, or characters could be dropped.
You could add a simple two-byte ACK sequence upon completion of whatever action is set to happen. It could look something like this:
Host sends command byte: <0x00>
Device echoes command byte: <0x00>
Device executes whatever action is needed
Device sends ACK/NAK byte (based on result):
This would allow you to see on the host side if communication is breaking down. The echoed character may mismatch what was sent which would alert you to an issue. Additionally, if a character is not received by the host within some timeout, the host can try retransmitting. Finally, the ACK/NAK gives you the option of returning a status, but most importantly it will let the host know that you've completed the operation and that it can send another command.
This can be extended to include a checksum to give the device a way to verify that the command received was valid (A simple logical inverse sent alongside the command byte would be sufficient).
The advantage to this solution is that it does not require extra lines or UART support on either end for hardware flow control.