One of the most attractive features of Luminardo is its USB Host functionality built around MAX3421E chip and amazing USB Host Library for Arduino written and maintained by TKJ Electronics and by Circuits@Home. Today we are going to compile their library for our Luminardo and try to run a ‘quality test’ to make sure that SPI interface is functional, MAX3421E is accessible and it detects and can communicate to a random USB dongle being plugged in to Luminardo’s USB connector.
First thing to do is to get the latest Luminardo library (if you haven’t done it yet) from Luminardo Github repository. This post describes in detail how to install the library.
Second thing is to get the latest USB Host 2.0 for Arduino from USB Host 2.0 Library for Arduino Github Repository. Follow the instructions provided with the library to make it available for your Arduino IDE environment. Now we need to make a small change to make the library aware of our hardware platform. Find UsbCore.h and open it for editing. Find the piece of code at the beginnig of the file and add two highlighted lines as shown below:
/* shield pins. First parameter - SS pin, second parameter - INT pin */ #ifdef BOARD_BLACK_WIDDOW typedef MAX3421e<P6, P3> MAX3421E; // Black Widow #elif defined(CORE_TEENSY) && (defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)) #if EXT_RAM typedef MAX3421e<P20, P7> MAX3421E; // Teensy++ 2.0 with XMEM2 #else typedef MAX3421e<P9, P8> MAX3421E; // Teensy++ 1.0 and 2.0 #endif #elif defined(BOARD_MEGA_ADK) typedef MAX3421e<P53, P54> MAX3421E; // Arduino Mega ADK #elif defined(ARDUINO_AVR_BALANDUINO) typedef MAX3421e<P20, P19> MAX3421E; // Balanduino #elif defined(LUMINARDO) typedef MAX3421e<P4, P18> MAX3421E; //Luminardo #else typedef MAX3421e<P10, P9> MAX3421E; // Official Arduinos (UNO, Duemilanove, Mega, 2560, Leonardo, Due etc.) or Teensy 2.0 and 3.0 #endif
Now open your Arduino IDE, create an empty sketch then copy-and-paste the content of the sketch below:
/* USB Host Shield 2.0 board quality control routine */ /* To see the output set your terminal speed to 115200 */ /* for GPIO test to pass you need to connect GPIN0 to GPOUT7, GPIN1 to GPOUT6, etc. */ /* otherwise press any key after getting GPIO error to complete the test */ /**/ #include <usbhub.h> // Satisfy IDE, which only needs to see the include statment in the ino. /* variables */ uint8_t rcode; uint8_t usbstate; uint8_t laststate; USB_DEVICE_DESCRIPTOR buf; /* objects */ USB Usb; void setup() { laststate = 0; Serial.begin(57600); E_Notify(PSTR("\r\nCircuits At Home 2011"), 0x80); E_Notify(PSTR("\r\nUSB Host Shield Quality Control Routine"), 0x80); E_Notify(PSTR("\r\nModified in Magictale Electronics for testing Luminardo boards"), 0x80); /* SPI quick test - check revision register */ E_Notify(PSTR("\r\nReading REVISION register... Die revision "), 0x80); Usb.Init(); // Initializes SPI, we don't care about the return value here { uint8_t tmpbyte = Usb.regRd(rREVISION); switch (tmpbyte) { case( 0x01): //rev.01 E_Notify(PSTR("01"), 0x80); break; case( 0x12): //rev.02 E_Notify(PSTR("02"), 0x80); break; case( 0x13): //rev.03 E_Notify(PSTR("03"), 0x80); break; default: E_Notify(PSTR("invalid. Value returned: "), 0x80); print_hex(tmpbyte, 8); halt55(); break; }//switch( tmpbyte... }//check revision register /* SPI long test */ { E_Notify(PSTR("\r\nSPI long test. Transfers 1MB of data. Each dot is 64K"), 0x80); uint8_t sample_wr = 0; uint8_t sample_rd = 0; uint8_t gpinpol_copy = Usb.regRd(rGPINPOL); for (uint8_t i = 0; i < 16; i++) { for (uint16_t j = 0; j < 65535; j++) { Usb.regWr(rGPINPOL, sample_wr); sample_rd = Usb.regRd(rGPINPOL); if (sample_rd != sample_wr) { E_Notify(PSTR("\r\nTest failed. "), 0x80); E_Notify(PSTR("Value written: "), 0x80); print_hex(sample_wr, 8); E_Notify(PSTR(" read: "), 0x80); print_hex(sample_rd, 8); halt55(); }//if( sample_rd != sample_wr.. sample_wr++; }//for( uint16_t j... E_Notify(PSTR("."), 0x80); }//for( uint8_t i... Usb.regWr(rGPINPOL, gpinpol_copy); E_Notify(PSTR(" SPI long test passed"), 0x80); }//SPI long test /* PLL test. Stops/starts MAX3421E oscillator several times */ { E_Notify(PSTR("\r\nPLL test. 100 chip resets will be performed"), 0x80); /* check current state of the oscillator */ if (!(Usb.regRd(rUSBIRQ) & bmOSCOKIRQ)) { //wrong state - should be on E_Notify(PSTR("\r\nCurrent oscillator state unexpected."), 0x80); press_any_key(); } /* Restart oscillator */ E_Notify(PSTR("\r\nResetting oscillator\r\n"), 0x80); for (uint16_t i = 0; i < 100; i++) { E_Notify(PSTR("\rReset number "), 0x80); Serial.print(i, DEC); Usb.regWr(rUSBCTL, bmCHIPRES); //reset if (Usb.regRd(rUSBIRQ) & bmOSCOKIRQ) { //wrong state - should be off E_Notify(PSTR("\r\nCurrent oscillator state unexpected."), 0x80); halt55(); } Usb.regWr(rUSBCTL, 0x00); //release from reset uint16_t j = 0; for (j = 0; j < 65535; j++) { //tracking off to on time if (Usb.regRd(rUSBIRQ) & bmOSCOKIRQ) { E_Notify(PSTR(" Time to stabilize - "), 0x80); Serial.print(j, DEC); E_Notify(PSTR(" cycles\r\n"), 0x80); break; } }//for( uint16_t j = 0; j < 65535; j++ if (j == 0) { E_Notify(PSTR("PLL failed to stabilize"), 0x80); press_any_key(); } }//for( uint8_t i = 0; i < 255; i++ }//PLL test /* initializing USB stack */ if (Usb.Init() == -1) { E_Notify(PSTR("\r\nOSCOKIRQ failed to assert"), 0x80); halt55(); } E_Notify(PSTR("\r\nChecking USB device communication.\r\n"), 0x80); } void loop() { delay(200); Usb.Task(); usbstate = Usb.getUsbTaskState(); if (usbstate != laststate) { laststate = usbstate; /**/ switch (usbstate) { case( USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE): E_Notify(PSTR("\r\nWaiting for device..."), 0x80); E_Notify(PSTR("Enabling VBus..."), 0x80); Usb.gpioWr(1); E_Notify(PSTR(" enabled"), 0x80); break; case( USB_ATTACHED_SUBSTATE_RESET_DEVICE): E_Notify(PSTR("\r\nDevice connected. Resetting..."), 0x80); break; case( USB_ATTACHED_SUBSTATE_WAIT_SOF): E_Notify(PSTR("\r\nReset complete. Waiting for the first SOF..."), 0x80); break; case( USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE): E_Notify(PSTR("\r\nSOF generation started. Enumerating device..."), 0x80); break; case( USB_STATE_ADDRESSING): E_Notify(PSTR("\r\nSetting device address..."), 0x80); break; case( USB_STATE_RUNNING): E_Notify(PSTR("\r\nGetting device descriptor"), 0x80); rcode = Usb.getDevDescr(1, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*) & buf); if (rcode) { E_Notify(PSTR("\r\nError reading device descriptor. Error code "), 0x80); print_hex(rcode, 8); } else { /**/ E_Notify(PSTR("\r\nDescriptor Length:\t"), 0x80); print_hex(buf.bLength, 8); E_Notify(PSTR("\r\nDescriptor type:\t"), 0x80); print_hex(buf.bDescriptorType, 8); E_Notify(PSTR("\r\nUSB version:\t\t"), 0x80); print_hex(buf.bcdUSB, 16); E_Notify(PSTR("\r\nDevice class:\t\t"), 0x80); print_hex(buf.bDeviceClass, 8); E_Notify(PSTR("\r\nDevice Subclass:\t"), 0x80); print_hex(buf.bDeviceSubClass, 8); E_Notify(PSTR("\r\nDevice Protocol:\t"), 0x80); print_hex(buf.bDeviceProtocol, 8); E_Notify(PSTR("\r\nMax.packet size:\t"), 0x80); print_hex(buf.bMaxPacketSize0, 8); E_Notify(PSTR("\r\nVendor ID:\t\t"), 0x80); print_hex(buf.idVendor, 16); E_Notify(PSTR("\r\nProduct ID:\t\t"), 0x80); print_hex(buf.idProduct, 16); E_Notify(PSTR("\r\nRevision ID:\t\t"), 0x80); print_hex(buf.bcdDevice, 16); E_Notify(PSTR("\r\nMfg.string index:\t"), 0x80); print_hex(buf.iManufacturer, 8); E_Notify(PSTR("\r\nProd.string index:\t"), 0x80); print_hex(buf.iProduct, 8); E_Notify(PSTR("\r\nSerial number index:\t"), 0x80); print_hex(buf.iSerialNumber, 8); E_Notify(PSTR("\r\nNumber of conf.:\t"), 0x80); print_hex(buf.bNumConfigurations, 8); /**/ E_Notify(PSTR("\r\n\nAll tests passed. Press RESET to restart test"), 0x80); while (1); } break; case( USB_STATE_ERROR): E_Notify(PSTR("\r\nUSB state machine reached error state"), 0x80); break; default: break; }//switch( usbstate... } }//loop()... /* constantly transmits 0x55 via SPI to aid probing */ void halt55() { E_Notify(PSTR("\r\nUnrecoverable error - test halted!!"), 0x80); E_Notify(PSTR("\r\n0x55 pattern is transmitted via SPI"), 0x80); E_Notify(PSTR("\r\nPress RESET to restart test"), 0x80); while (1) { Usb.regWr(0x55, 0x55); } } /* prints hex numbers with leading zeroes */ void print_hex(int v, int num_places) { int mask = 0, n, num_nibbles, digit; for (n = 1; n <= num_places; n++) { mask = (mask << 1) | 0x0001; } v = v & mask; // truncate v to specified number of places num_nibbles = num_places / 4; if ((num_places % 4) != 0) { ++num_nibbles; } do { digit = ((v >> (num_nibbles - 1) * 4)) & 0x0f; Serial.print(digit, HEX); } while (--num_nibbles); } /* prints "Press any key" and returns when key is pressed */ void press_any_key() { E_Notify(PSTR("\r\nPress any key to continue..."), 0x80); while (Serial.available() <= 0); //wait for input Serial.read(); //empty input buffer return; }
Pick a random USB dongle (we used a Bluetooth dongle ‘Targus’) and plug it into Luminardo board as shown on the picture below:
Compile the sketch, upload it to Luminardo, open terminal application, configure select appropriate serial port and baudrate (57600bps in our case) and watch what is being reported. If everything is done correctly you should be able so see something like this:
Circuits At Home 2011 USB Host Shield Quality Control Routine Modified in Magictale Electronics for testing Luminardo boards Reading REVISION register... Die revision 03 SPI long test. Transfers 1MB of data. Each dot is 64K................ SPI long test passed PLL test. 100 chip resets will be performed Resetting oscillator Reset number 0 Time to stabilize - 349 cycles Reset number 1 Time to stabilize - 350 cycles ... Reset number 99 Time to stabilize - 349 cycles Checking USB device communication. Waiting for device...Enabling VBus... enabled Reset complete. Waiting for the first SOF... Getting device descriptor Descriptor Length: 12 Descriptor type: 01 USB version: 0200 Device class: E0 Device Subclass: 01 Device Protocol: 01 Max.packet size: 40 Vendor ID: 0A12 Product ID: 0001 Revision ID: 3164 Mfg.string index: 00 Prod.string index: 02 Serial number index: 00 Number of conf.: 01 All tests passed. Press RESET to restart test
If there is ‘All tests passed’ at the end it means that the hardware is functional and USB Host library is configured correctly. The platform is ready for real experiments!
Leave a Reply
You must be logged in to post a comment.