Lightweight USB Host. Part 4 – The code.

MAX3421E breakout

MAX3421E breakout

A couple of updates. First, second prototype for the breakout board arrived from BatchPCB (pictured on the right ). I placed an order for the first batch with PCBcart, it is supposed to be here in 2 weeks. Also, I made this prototype public at BatchPCB, this is the product link. The prototype has a little defect – the USB connector is placed a little bit too close to resistors; however, it’s totally buildable, just make sure you insert USB connector last, when the rest is soldered and checked.

Second, I created a code repository for the project. From now on, all firmware development will be posted there. The hardware files don’t change that often; they will still be hosted here in downloads section.

At present, the code doesn’t do much past enumeration. From USB point of view, it knows how to generate control and bulk-IN transfers; bulk-OUT is going to be written together with mass storage client driver code, which is going to be next big step. Also, it is probably buggy and this is my reason for publishing it – “given enough eyeballs, all bugs are shallow”. If you try the code and it doesn’t work, let me know. Or better yet, fork a code, fix it and let me know what you fixed and why.

The code is developed in MPLAB. I use IDE version 8.20 and C18 v3.22. The IDE project file is posted along with source code files; it may or may not work, depending on your setup. If project won’t compile, open the .mcp file in text editor and check file paths. Alternatively, you can make your own project by including all .c files and copy compiler/linker keys from .mcp file.

I use standard PIC headers and linker script – if compiler complains about standard headers, check file paths. In some versions of MPLAB you need to set path to libraries explicitly, even if it’s installed in the default location.

What follows is a short description of code structure and module functions.

MAX3421E.c module contains MAX3421E interface functions, such as single- and multibyte reads and writes, initialization, and interrupt handler intended to be run from the main loop.

transfer.c module contains functions implementing various USB transfers – control and bulk. There is also USB_Task() function, which performs automatic USB tasks, such as resets and enumeration. USB_Task runs from the main loop also.

The cli.c module contains command-line interface functions. It’s primary purpose is to aid in debugging – the facility which shows you MAX3421E registers, USB state machine state and whatever else you might need, is quite handy. I designed it so it can easily be dropped to save memory, CPU time, or when debugging is completed.

I’m hoping to decide what next step I’m going to take with this code – it will be either client driver or Arduino port. In any case, results will be posted here. Stay tuned.


12 comments to Lightweight USB Host. Part 4 – The code.

  • João Gomes

    Hello Felis

    I’m following this project to achieve the goal of a USB Host for playback of PEN DRIVE.
    As you said he has no place in the PIC18 I’m using a LPC21xx.

    Using your code by adding the laboratory code MAXIM, I managed to achieve with the routines SEND PACKET, the error 0x0D>> FSTimeout.
    This same error is reported in many forums, without anyone to disclose the settlement reached, and one would you suggest this channel to detail the possible solutions.

    The question is how is it possible to control the timeout and to successfully run the routines that use the SEND PACKET?

    The technical support of MAXIM claims to be a software problem and out of reach propose a solution. And with you?

    I noticed that some functions, for example XferSetAddr () is not available. You developed it by chance.



  • Jason

    Hi oleg, very informative codes and description !
    Here is my situation, i am in my final year project where i want to be able to detect a pendrive and then show the file’s name in the pendrive on the 4×20 LCD screen that i have. For now i just want to be able to detect the pendrive and the LCD will display ” pendrive found”. Which of the codes do i have to use only? Like the max3421e.c , max3421e.h , project_config.h . what else do i need from the code? starting out slow first so i can understand whats going on properly. Thanks!! much help appreciated 🙂

  • Jason

    Oh and im using PIC18f4550. thanks 🙂

  • Jason

    The thing is that i dont know how to configure my PIC to arduino code. It is already complex trying to understand the basic stuff. Do you know how to configure the code that you wrote in arduino to support what i am trying to achieve? Thanks

    • I don’t think Arduino code can be easily ported to PIC. I was suggesting to switch your development to Arduino platform.

  • Jason

    Oh . I dont think that is possible because i am already in the midst of my project and its due in 3 weeks, i just got to be able to detect the pendrive from my usb port. So if you can help me to achieve that with just the required code i would really appreciate that :). The thing is that after looking at some examples all over the internet, i just cant find the right coding except on this page since u were using a 18F PIC so i thought maybe if u could help me point out just the required Void or header file then i could achieve my goal d . much help appreciated! thanks!

  • Jason

    Hi oleg, if you dont mind helping me out, could you explain to me how the KSTATUS and JSTATUS bit determine if the device connected is high speed or low speed? and what does it have to do with the LOWSPEED bit? does the LOWSPEED updates itself when a device is connected? i am having trouble finding out the flow of how the device is detected. thanks.

    Here is my concept of how it works, pls correct me if im wrong.
    B4 a device is detected, the cpu set the HOST =1 , DPPULLDN = 1 and DMPULLDN = 1 to make the logic in the D+ and D- low. then when a device is plug in, depend on the device(if its high speed or low speed) it will make the D+ or D- to have voltage through it. so when a device is detected, the cpu ( my 18f4550) reads the rHRSL register and examines the KSTATUS and JSTATUS bit when SAMPLEBUS = 1 ( does it automatic update the kstatus and jstatus itself ? ). So if it is a high speed device, the Kstatus should be high right according to the datasheet? and so in the end its all about checking on the kstatus and jstatus.

    my main question is really on how the kstatus and jstatus update itself and when D+ is high voltage and D- is low voltage, does that mean it updates the kstatus ? sorry if some question could be the same, i just have to be certain. thanks !! pls reply as soon as possible.

    • Low-speed device has one data line pulled up by a resistor an full-speed device has other data line pulled up by the resistor. Host controller has both data lines pulled down by larger resistors. It reads data lines and determines speed by whatever data line is high at the moment. The J, K are updated automatically after device connect. If you start host controller with device already attached, you need to set SAMPLEBUS, wait for it to reset and then read JSTATUS,KSTATUS. Relation between JSTATUS,KSTATUS and speed depend on state of LOWSPEED – take a look at busprobe() function in USB Host code to see how it works.

      • Jason

        so does that mean the LOWSPEED bit also update itself when the device is connected? like when a lowspeed device is connected the lowspeed bit will go high in the rMODE and when it is use to check with the bmLOWSPEED and rMODE , it is use to determine if its high or low speed according to the KSTATUS or JSTATUS right?