We are looking for possible reasons that a control transfer would begin so late in a frame that the device response would occur on top of the next SOF. wMaxPacketSize is 0x40 (64 decimal). We can rig the Host Controller Driver to hold off to next SOF when time is close; however we believe this to be the responsibility of the Host Controller.
We are open to thoughts and possible solutions.
Related
I'm doing a USB device is to control stepper motors. I've done this before using a parallel port. because these ports do not exist in current motherboards, I decided to implement a USB communication between my device and the PC (host).
To achieve My objective, I endowed the freescale microcontroller the device with that has a USB module 12Mbps.
My USB device must receive 4 bytes (one for each motor driver) at a given time, because every byte is a step that should move the engine.
In the PC (Host) an application of user processes a text file with information and make the trajectory coordinates sending bytes at a certain rate for each motor (time is trivial to achieve the acceleration and speed of the motors) .
Using the parallel port was an easy the task because each byte is sent sequentially to a time determined by the user app.
doing a little research about full speed USB protocol understood that the frame is sent every 1ms.
then you can send 4 byte or many more every 1ms but I can not manage time like I did with the parallel port.
My microcontroller can send up to 64 bytes per frame (Based on transfer papers type Control, Bulk, Int, Iso ..).
question 1:
I want to know in what way I can send 4-byte packets faster than every 1 ms?
question 2:
What type of transfer can advise me for these type of devices?
Thanks.
Like Ricardo said, USB-serial will suffice.
As for the type of transfer, try implementing a CDC stack and use your SCI receiver to listen for PC commands. That will give you a receive buffer which will meet your needs.
Initialize your SCI (baud, etc)
Enable receiver and interrupt
On data receive, move it to your 4-byte command buffer
Clear receive buffer, wait for more
When you have all 4 bytes, fire off the steppers! Four bytes should take µs.
Check with Freescale to see if your processor is supported.
http://cache.freescale.com/files/microcontrollers/doc/support_info/USB_STACK_RELEASE_NOTES_V4.1.1.pdf?fpsp=1
There might even be some sample code to get you started.
-Cheers
I am achieving the same goal (driving/control CNC machines) like this:
the USB device is just synchronous I/O parallel port. Using continuous bulk transfer one pipe as input and one as output. This way I was able to achieve synchronous 64bit parallel communication with ~70KHz sample rate. It uses traffic around (i)4.27+(o)4.27 MBit/s that is limit for mine MCU and code. Bigger speeds cause jitter on the output due to USB events interrupts.
How to do it (on MCU side)
I have 2 FIFO's one for ingoing and one for outgoing data. I have timer interrupt occurring with sample rate frequency. In it I read the inputs and feed it to the first FIFO and read data from the other FIFO and send it to the outputs.
On top of that the USB task is called (inside the same interrupt) checking FIFO for sending to and incoming data from USB handling the transfer itself
I choose ATMEL AT32UC3A chips for this task. After a long and pain full research I decided these MCU's because they have enough memory for both FIFO's and program so no need for additional IC. It has FPGA package which can be used (BGA is not an option). It has HS USB (most USB MCU's have only FS like yours). It runs at 66MHz. It supports many interesting features (did interesting projects with it in the past) and of coarse I have experience with ATMEL MCU's from past
So if you want to achieve something similar then
start with bulk transfer (PC -> USB -> MCU -> output)
add FIFO if needed
do not know the sample rate you need. The old LPT's could handle from 80-196KHz depend on the manufactor. The modern ones are much much slower (which is silly and sad).
measure the critical sample rate
you need oscilloscope or very good hearing for this. The output data must be synchronous so no holes in it, no jitter, etc...
if any of these are present you have to lower the sample rate. Mine setup could handle even 1MHz sample rate but the USB jitter was present (sometimes USB event froze the sending for longer that one sample...) so I achieve only 70KHz of stable output.
if needed also inputs then add them
but only if the output is working as it should. Do not forget to lower the sample rate after this too ... Use separate bulk pipes and FIFOs for input and output.
I'm using a Synopsys OTG core in device mode. Programming an isochronous IN high speed endpoint (USB 2.0) for the maximum transfer per microframe (3 packets of 1024 bytes) using a periodic FIFO dedicated to this endpoint. It works 99+% of the time. But occasionally the transfer is truncated. For example, the first 1024 bytes will go onto the bus with the DATA0 PID (instead of the correct DATA2 PID) and the remaining 2048 bytes will not be sent. Since I've programmed the packet count, multicount, max packet size and transfer size correctly I'm not sure what is causing this.
Obviously this is a very specific question and I don't have much hope of getting an answer, but I figured a shot in the dark was worth a try. Thanks in advance.
Isochronous transfers does not guarantee packet delivery. So if host controller has other active transfers, it will silently drop isochronous packets. If you need guaranteed packed delivery, you should use bulk transfers (but then it will not guarantee delivery time).
Isochronous is ideal for applications, like sound or video streaming, where you need constant delivery time, but loss of some frames is ok.
The specification places limits on the bus, allowing no more than 90% of any frame to be allocated for periodic transfers (Interrupt and Isochronous) on a full speed bus. On high speed buses this limitation gets reduced to no more than 80% of a microframe can be allocated for periodic transfers. (c) http://www.beyondlogic.org/usbnutshell/usb4.shtml
Answering my own question in case it may help someone else. It appears this OTG controller has a bug where the TX FIFO does not always empty properly. I found a successful workaround is to flush the FIFO after each TX. It's quick and the truncation symptom goes away.
I'm using USB for communication. Our device sends 100k/s data (ARM7, very small memory size), and the PC needs to receive and process it all.
My previous design was implemented as a mass storage device, and extended a command for the communication protocol. The PC software runs a thread with a loop to receive the data.
The issue is: sometime it loses data.
So we used another solution: usb sim com (RS232).
But I don't know whether or not the OS can contain that much data before I get it using MFC (or pyserial). How can I get/set the buffer size?
We regularly punch about 100KByte/sec through our USB CDC implementation, the PC is fast enough to receive all data. But it seems that the built-in limits are lower with usb-serial (CDC) than with mass-storage protocol (in our case ~600KB/s versus ~100KB/s CDC).
The PC receive thread should have a buffer that's "big enough".
Edit: I don't know Windows' Buffer sizes, or how to get them, though.
This question is a bit vague, and I apologzie for that, but a fairly vague answer will do :)
How do people typically access memory adresses of external devices (say, connected to a PC through USB, or even just say, a multipurpose microcontroller)? I'm wondering how software is able to find address to write to registers or EEPROM space.
For example if I want to write a value to register 0x1234, does software just send this information (the register and the value to be written) to some sort of driver that "talks" to the device and takes care of the value change through hardware?
Is implementation of this functionality mostly a hardware endeavor?
Thanks!
Let's use as an example a fairly common USB peripheral controller that is based on an 8-bit 8051 microcontroller core. One side of it attaches to the USB host controller on a desktop computer. The other end goes to a USB device controller that presents itself as a FIFO endpoint to the host.
Some 8051 firmware will be required to initialize the device side. A class driver will be required on the host side. Once those are in place, the application developer will have a device name on the host side which may be opened for read/write. Sometimes a vendor will provide a library to perform device specific tasks and isolate the user from the raw device. Often a Windows DLL is available to hide the low level I/O and present device operations as function calls.
Additional 8051 firmware monitors the FIFO from device end and interprets messages sent from the host application or DLL then takes actions. These actions may be low level such as read/write from a memory location or register. They may be high level such as setting the PWM value of a programmable counter array.
So your hypothetical description of a write to register 0x1234 is not far from how it is often implemented.
I'm using a microSD card in an embedded design. The card is connected to a microcontroller using the SPI interface. It worked fine for all cards I've used before, but now my new card will not initialize. The card is a Transcend 2 GB microSD card (TS2GUSD).
After sending the initial clock train to switch to SPI mode, I do the following:
CMD0 (Argument 0, CRC 0x95) -> Response 0x01 -> OK
CMD8 (Argument 0x000001AA, CRC 0x87) -> Response 0x01 0x000001AA -> Means it's SDC V2+ card, the voltage range 2.7 V - 3.6 V is supported -> OK
Then I should send the ACMD41 command, but when sending the CMD55 (argument 0, CRC 0) that must precede CMD41, I get response 0x05 -> Illegal Command.
I've also tried to send CMD1 (for MMC cards), but it gives a similar illegal command response. The code works fine with my Sandisk 2 GB microSD card.
How do I fix this problem?
I seem to have found the issue. When I calculate the correct CRC for CMD55 and send that instead of a dummy CRC, the command is accepted (result 0x01). If you look at the physical layer specification in section 7.2.2, it explicitly says that:
The SPI interface is initialized in the CRC OFF mode in default. (except for commands CMD0 and CMD8).
This doesn't seem to be the case with this series of Transcend cards, thus violating the specification. Also in case of a CRC error the reply should be 0x09 instead of 0x05. I've tried to explicitly turn off CRC checking with CMD59, but that doesn't seem to help.
=> Calculating the correct CRC for (all?) commands makes the card work.
I'm in contact with Transcend support about this. If I learn something useful I'll you know here.
Note that I used other 2 GB Transcend cards before, but they were made in Taiwan, while the new one is made in Korea (and seems to be a Samsung card (MMAGR02GUDCA)).
I had almost the same issue. When sending ACMD41, I sent CMD55 followed by CMD41. The response for CMD55 was 0x01, indicating idle state and running the initialization process (this is normal, I think). CMD41 would respond with 0x05, indicating illegal command. It turns out that my particular card does the CRC check by default, even in SPI mode, and misreports CRC errors as illegal commands (i.e., it doesn't follow the SD spec). When I calculate the proper CRC, it works fine. Here is the CRC7 calculation code I used, it has worked well for me:
https://github.com/hazelnusse/crc7
Unless you have taken care to disable CRC checking, I think it is probably best to assume it isn't disabled and make sure you calculate the proper CRC for each command frame. From what I can tell, some cards disable it by default in SPI mode and others enable it, even though the SD specification states it should be disabled by default in SPI mode except for CMD8.
You said you used CRC 0 for the failing command. I assume that you meant that you sent the whole last byte as 0x00. Note that the CRC7 is only the first 7 bits of the last byte - the last bit called end bit should always be 1. So if you were sending 0x00 as the last byte, with 0 as the last bit, the failure would be understandable, and even the error code would make sense. If you send 1 as the last bit, it should work, ie. use something like 0x01 or 0xFF as the last byte.
It's normal, it's likely the internal charge-pump used to make erase voltage that takes longer than usual to be ready... you have to insist on the CMD55+ACMD41 combo until initialization finishes.
The CMD58 could also help you to check if you're supplying correct voltage levels (sometimes sockets have contact problems).
Sending CMD0 with chip select(0) alone does not initialize the card in SPI mode. This only sets SPI mode.
Card is not initialized until ACMD41 returns accepted. Then CRC is off by default.
Insert several dummy SPI cycles after CMD55 (0xFF sent+received) and before CMD41.
I had to do this for both my old test cards - 16MB Panasonic and Sandisk 64MB.
Note: I realize I'm quite late to the party, but I'm hoping it may help someone in future.