Project

General

Profile

Setting the ARM as a USB bulk device

Added by Okan Çalış almost 3 years ago

Hi,

I'm using a MityDsp-L138F SoM, with Linux installed. I need to make the ARM side communicate with a PC over USB such that the latter will see it as a USB bulk peripheral device.

I examined the StarterWare examples, which include "usb_dev_bulk.c", but as explained in the TI wiki, those examples will not run on Linux. Currently, I have an example code based on "usb_dev_bulk.c" that runs successfully on the DSP core (without an OS), and I need to move this functionality to the ARM core running Linux.

This sounds like a simple task, yet I couldn't find an answer to it on your wiki or elsewhere.

Thanks in advance.
Okan


Replies (23)

RE: Setting the ARM as a USB bulk device - Added by Jonathan Cormier almost 3 years ago

Okan, Linux calls this a USB gadget. Depending on what peripheral you want to emulate you can enable different "gadgets". We have a wiki page walking through how to use a USB RNDIS (networking) gadget. https://support.criticallink.com/redmine/projects/arm9-platforms/wiki/Enabling_USB_RNDIS_Support

If you want a different peripheral you can change the gadget at this step "Select Ethernet Gadget as shown here".

If you're looking to create your own custom peripheral then you might want to look into gadgetfs though I've not used it.
http://blog.soutade.fr/post/2016/07/create-your-own-usb-gadget-with-gadgetfs.html
Note: If your searching online you may also come across references to configfs and functionfs. These were added in kernels after 3.2 so won't be available.

RE: Setting the ARM as a USB bulk device - Added by Okan Çalış almost 3 years ago

Hi, Jonathan,

Thanks for your help. I've read Soutadé's blog (I had already read about RNDIS in the wiki.), but I can't access the Linux kernel so that I can compile the modules.

The Linux Kernel page tells me to clone git://support.criticallink.com/home/git/linux-davinci.git, which is available as gitweb at https://support.criticallink.com/gitweb/?p=linux-davinci.git

The problem is, my host computer (which has an Ubuntu VM in it) is not connected to the Internet; therefore, I can't issue a clone command on its terminal. And my other PC that has Internet connection does not allow me to install any programs, hence I can't install Git and clone the repository on it, either.

I can only access the Gitweb page, but I couldn't find a way to get the snapshot. How can I get to the Linux Configuration Tool now?

Thanks,
Okan

BTW: the link to Soutadé's blog seems to be broken; the "usb" part should be lowercase.

RE: Setting the ARM as a USB bulk device - Added by Jonathan Cormier almost 3 years ago

Okan Çalış wrote:

Hi, Jonathan,

Thanks for your help. I've read Soutadé's blog (I had already read about RNDIS in the wiki.), but I can't access the Linux kernel so that I can compile the modules.

The Linux Kernel page tells me to clone git://support.criticallink.com/home/git/linux-davinci.git, which is available as gitweb at https://support.criticallink.com/gitweb/?p=linux-davinci.git

The problem is, my host computer (which has an Ubuntu VM in it) is not connected to the Internet; therefore, I can't issue a clone command on its terminal. And my other PC that has Internet connection does not allow me to install any programs, hence I can't install Git and clone the repository on it, either.

Hmm thats a tricky one. Do you have a way to transfer files to this machine? If so I can create a git bundle for you that you can copy to machine and then you can clone the bundle. https://stackoverflow.com/a/11795549/780194

I can only access the Gitweb page, but I couldn't find a way to get the snapshot. How can I get to the Linux Configuration Tool now?

Thanks,
Okan

BTW: the link to Soutadé's blog seems to be broken; the "usb" part should be lowercase.

Hmm thats odd. I updated the link.

RE: Setting the ARM as a USB bulk device - Added by Okan Çalış almost 3 years ago

Hi, Jonathan,
Yes, I can transfer files to the machine.
It occurred to me later that I can clone the repo to my Ubuntu VM at home after work, and transfer it to my workstation via a flash drive tomorrow.
Thanks again. I'll try building the USB modules and continue the thread if I get stuck again.
Okan

RE: Setting the ARM as a USB bulk device - Added by Jonathan Cormier almost 3 years ago

Okay well the bundle file is ~1GB. I can host that here somewhere for a few hours or if you have a somewhere I can upload it.

RE: Setting the ARM as a USB bulk device - Added by Okan Çalış almost 3 years ago

Thanks, but I'm already home. I'll download it from Git. The file is not too large.

RE: Setting the ARM as a USB bulk device - Added by Jonathan Cormier almost 3 years ago

Okan Çalış wrote:

Thanks, but I'm already home. I'll download it from Git. The file is not too large.

Okay. Note if you choose to go the bundle route, I recommend cloning the repo with the --mirror option so it creates all the branches. Then the bundle create command will include them in the bundle. Alternatively you can checkout just the branches you want and then create the bundle.

 $ git checkout origin/mitydsp-linux-v3.2 -b mitydsp-linux-v3.2
 $ git branch
* master
  mitydsp-linux-v3.2

RE: Setting the ARM as a USB bulk device - Added by Okan Çalış almost 3 years ago

Hi,

I downloaded the kernel and launched menuconfig, but as I expected, I got stuck in that step of GadgetFS.

Then, enable
Device Drivers -> USB support -> USB Gadget Support -> USB Gadget Drivers -> Gadget Filesystem
In the same section (or in the section above depending on your controller), select the right Peripheral Controller.

I enabled the "Gadget Filesystem" (which appears to be experimental) as a module by hitting <M>, but I have no idea what the right Peripheral Controller could be. The options are:
  • Faraday FUSB300 USB Peripheral Controller
  • Renesas R8A66597 USB Peripheral Controller
  • Inventra HDRC USB Peripheral Controller (TI, ADI, ...)
  • Renesas M66592 USB Peripheral Controller
  • PLX NET2272
  • Dummy HCD (DEVELOPMENT)

I searched the datasheet for each, but didn't come across any of them. I know you said you've never used GadgetFS, but do you have an idea what I should do now?

Also, I noticed the "Serial Gadget" among the options listed. Do you know how well it performs? Can I use that gadget to transfer bulk data just like the "usb_dev_bulk.c" code (I mean, without modifying the host side)?

RNDIS is still an option, but I have no idea how to use it, apart from the installation.

Thanks again,
Okan

RE: Setting the ARM as a USB bulk device - Added by Jonathan Cormier almost 3 years ago

Okan Çalış wrote:

Hi,

I downloaded the kernel and launched menuconfig, but as I expected, I got stuck in that step of GadgetFS.

Then, enable
Device Drivers -> USB support -> USB Gadget Support -> USB Gadget Drivers -> Gadget Filesystem
In the same section (or in the section above depending on your controller), select the right Peripheral Controller.

I enabled the "Gadget Filesystem" (which appears to be experimental) as a module by hitting <M>, but I have no idea what the right Peripheral Controller could be. The options are:
  • Faraday FUSB300 USB Peripheral Controller
  • Renesas R8A66597 USB Peripheral Controller
  • Inventra HDRC USB Peripheral Controller (TI, ADI, ...)
  • Renesas M66592 USB Peripheral Controller
  • PLX NET2272
  • Dummy HCD (DEVELOPMENT)

I searched the datasheet for each, but didn't come across any of them. I know you said you've never used GadgetFS, but do you have an idea what I should do now?

The RNDIS instructions say to use the "Inventra HDRC USB Peripheral" option.

Also, I noticed the "Serial Gadget" among the options listed. Do you know how well it performs? Can I use that gadget to transfer bulk data just like the "usb_dev_bulk.c" code (I mean, without modifying the host side)?

I'm not sure how usb_dev_bulk.c works. But the serial gadget will create a tty device between the host and the L138. You can then open the serial port on each machine and communicate between them. To verify its working I'd use microcom on the L138 and putty on the host. You should then be able to type on one and see it on the other.
https://www.kernel.org/doc/Documentation/usb/gadget_serial.txt

RNDIS is still an option, but I have no idea how to use it, apart from the installation.

RNDIS is fairly easy to use. It will create a network device on both host and L138. You assign each an ip address and then you can ping and otherwise communicate as if it was a normal ethernet link.

Thanks again,
Okan

RE: Setting the ARM as a USB bulk device - Added by Okan Çalış almost 3 years ago

Hi, Jonathan,
Thanks for your reply.

The RNDIS instructions say to use the "Inventra HDRC USB Peripheral" option.

I should've noticed that, sorry.

Anyways, I've built "GadgetFS" and "Inventra HDRC USB Peripheral Controller" as modules, which created a "gadgetfs.ko" file, but I can't find any module files; there is only an object file at "linux-davinci/drivers/usb/musb/musb_hdrc.o", but no "*.ko" file.

I copied "gadgetfs.ko" to "/lib/modules/3.2.0/extra" on the target and insmod'ed it. Then, I issued the mounting command (mount -t gadgetfs gadgetfs /dev/gadget), but it returns "nop musb-hdrc: failed to start (null): -120".

What could be wrong?

Thanks again,
Okan

(I asked this on Soutadé's blog, too, and waiting for their answer.)

RE: Setting the ARM as a USB bulk device - Added by Okan Çalış almost 3 years ago

I meant: "but I can't find any module files for the peripheral controller."

RE: Setting the ARM as a USB bulk device - Added by Okan Çalış almost 3 years ago

The author of the blog advises me to flash the kernel again as the peripheral controller could be included built-in (though I can't imagine why, because I included it as <M>).

I need to reflash the kernel now; may I overwrite the current kernel on the SPI flash? This forum post warns not to do so, yet I don't understand why.

Lastly, I just noticed that, in the wiki, the Linux Kernel article says to use:

alias makearm="make ARCH=arm CROSS_COMPILE=arm-angstrom-linux-gnueabi-" 
makearm industrialio_defconfig
makearm menuconfig

whereas in Enabling USB RNDIS Support, it says:
make CROSS_COMPILE=arm-arago-linux-gnueabi- ARCH=arm menuconfig

I remember issuing angstrom all the time; I think arago threw a missing toolchain error. What's the difference? Could it be the reason behind the missing *.ko file?

Thanks,
Okan

RE: Setting the ARM as a USB bulk device - Added by Jonathan Cormier almost 3 years ago

Okan Çalış wrote:

The author of the blog advises me to flash the kernel again as the peripheral controller could be included built-in (though I can't imagine why, because I included it as <M>).

Worth a shot.

I need to reflash the kernel now; may I overwrite the current kernel on the SPI flash? This forum post warns not to do so, yet I don't understand why.

Yes you can. See https://support.criticallink.com/redmine/projects/arm9-platforms/wiki/Linux_Kernel#Installing-the-Kernel-on-SPI-FLASH
Note if you are compiling the kernel several times it can be easier to setup your bootcmd to auto tftp the kernel and boot directly from RAM.

set bootcmd_old $bootcmd
set bootcmd tftp 0xC0700000 192.168.0.23:/uImage; bootm 0xC0700000
saveenv

Lastly, I just noticed that, in the wiki, the Linux Kernel article says to use:
[...]
whereas in Enabling USB RNDIS Support, it says:
[...]

The CROSS_COMPILE argument will depend on which toolchain you are using. You may use the makearm alias as a shortcut to replace any make CROSS_COMPILE=.. ARCH=.. <> lines.

I remember issuing angstrom all the time; I think arago threw a missing toolchain error. What's the difference? Could it be the reason behind the missing *.ko file?

I believe the arago toolchain was an older toolchain. You should continue to use the one you installed. Its likely TI never designed musb_hdrc to be built as a module.

Thanks,
Okan

RE: Setting the ARM as a USB bulk device - Added by Jonathan Cormier almost 3 years ago

Note if you do break the unit you can reprogram it from scratch. Reprogramming_a_Dead_Board

RE: Setting the ARM as a USB bulk device - Added by Okan Çalış almost 3 years ago

Hi, Jonathan,

I managed to rebuild a kernel and boot the OS. Thanks for helping me out.

I was also able to use the serial gadget module g_serial.ko, send and receive terminal messages using TeraTerm on my Windows host. The problem is, the serial gadget, as I suspected, is not compatible with our host-side app because the host can see the device just like a COM port, but not as a USB bulk device.

I looked it up further and came across this Xilinx forum, which mentions GadgetFS again. I'd already built gadgetfs.ko as a module, so I downloaded the codes usb.c, usbstring.c, and usbstring.h from http://www.linux-usb.org/gadget/ and built them. (As pointed out in the Xilinx forum, one needs to correct the "musb_hdrc" string in usb.c, which is supposed to be "musb-hdrc".) I also have the LibUsbDotNet library installed on my Windows host, which offers a sample Bulk Test application.

However, when I execute the binary in the target, my host throws an error saying it could not find the necessary driver for the device. I tried manually installing it, and found a "Stellaris Bulk Device" driver. I installed it; and the host now sees it as a generic bulk device, and the target application prints the "connected" string. However, when I try getting data from the device, I end up with 64 Bytes of zeros every time, which is not what I expect.

I'll keep searching.
Okan

RE: Setting the ARM as a USB bulk device - Added by Okan Çalış almost 3 years ago

However, when I try getting data from the device, I end up with 64 Bytes of zeros every time, which is not what I expect.

Actually, I thought the char* serial string in usb.c was the message to be sent to the host, but it turned out to be just a randomly-generated serial number. I was expecting to see it as an incoming message on the host side.

Still looking for a way to send and receive bulk data.

RE: Setting the ARM as a USB bulk device - Added by Michael Williamson almost 3 years ago

So a long time ago, I implemented a bulk transfer protocol on the MityDSP-L138 using gadgetfs in order to emulate a legacy camera protocol.

I am attaching the relevant code files used for interfacing to gadgetfs that were used for the project.

usbctrl.cpp creates a C++ wrapper class, tcUSB, that sets up the presented device descriptors (which obviously you'd need to change), an EP0 (control) handler, and bulk input and output endpoints. There is a thread that reads input data from the bulk endpoint and there is also a mechanism to send data to the output endpoint. The bulk endpoint IO has compile time options for using asynchronous IO, which I found had better outbound throughput, if you were pushing large data packet sizes.

The code made it through initial prototype testing, and then was abandoned as we migrated to a different platform. There's probably some error handling that is lacking. Hopefully this moves you down a useful path. I suspect that, in principle, most of this should still work with the later revisions of the kernel/gadgetfs, but the AIO stuff may need attention.

To run this, I had to ensure gadgetfs was mounted (and was built into the kernel or available as a module):

mkdir /dev/gadgetfs
mount -t gadgetfs gadgetfs /dev/gadgetfs

-Mike

usbctrl.cpp View (15.5 KB)

usbctrl.h View (1.13 KB)

usbstring.c View (3.42 KB)

usbstring.h View (1.01 KB)

RE: Setting the ARM as a USB bulk device - Added by Michael Williamson almost 3 years ago

Looking further, I think most of that code was based on the usb.c example you already looked at, so maybe this won't help very much. You sort of need example code on both ends. libusb might be a good start for the PC side of things.

-Mike

RE: Setting the ARM as a USB bulk device - Added by Okan Çalış almost 3 years ago

Hi, Jonathan and Mike,

Thanks for your help.

With the usb.c code in Linux-USB.org, I managed to send and receive bulk data using GadgetFS last week. I modified the code to solve some minor problems (e.g. #define'd a DO_PIPE) and it works now. The bulk-out (or, peripheral-to-host) transfers achieve a throughput of ~5MB/s on high speed. Is this acceptable?

Thanks again,
Okan

RE: Setting the ARM as a USB bulk device - Added by Jonathan Cormier almost 3 years ago

Looking at some of the speed tests we ran with RNDIS, we were seeing about 10Mb/s or ~1.25 MB/s. So you results seem pretty good in comparison.

RE: Setting the ARM as a USB bulk device - Added by Michael Williamson almost 3 years ago

That is reasonable. Using large transfers and Async IO, we were able to get up to 14 MB/sec with the camera application. But 5 MB/sec sounds OK for a nominal transfer scenario.

I guess the question is if that is acceptable for your application?

-Mike

RE: Setting the ARM as a USB bulk device - Added by Okan Çalış almost 3 years ago

Thank you.

RE: Setting the ARM as a USB bulk device - Added by Okan Çalış almost 3 years ago

Michael Williamson wrote:

That is reasonable. Using large transfers and Async IO, we were able to get up to 14 MB/sec with the camera application. But 5 MB/sec sounds OK for a nominal transfer scenario.

I guess the question is if that is acceptable for your application?

Actually, the project we're working on is time-sensitive. The device will be sending, for instance, large FFT data to the host, and the faster it does so, the better.

How did you reach 14MB/s? I'm not using Async I/O, but that's not supposed to improve the throughput, is it?

Also, which driver were you using on the host side? I'm using StellarisWare Embedded USB Drivers for Windows, available here, and it works. Should I be using some kind of Linux driver for Windows instead? Would that affect the transmission rate?

    (1-23/23)
    Add picture from clipboard (Maximum size: 500 MB)