Showing posts with label USB. Show all posts
Showing posts with label USB. Show all posts

Sunday, January 9, 2011

Tools for A.R. Drone

I finally released some tools for A.R. Drone:
  1. libplf - A library to read / write plf files
  2. plf_inst_extract - A tool to extract and patch a ardrone_installer.plf from a given ardrone_update.plf
  3. usb_flash - A tool to flash a ardrone_update.plf over USB. This tool requires:
    1. ardrone_update.plf - the firmware to flash
    2. ardrone_installer.plf - can be obtained from ardrone_update.plf with plf_inst_extract
    3. ardrone_usb_bootloader.bin - was delivered with the old flash tool. I will probably write an open-source boot loader sooner or later.
Have a look at my goolge code project:

http://code.google.com/p/ardrone-tool

A.R. Drone's boot sequence

In order to be able to flash a custom kernel to A.R. Drone, it is necessary to understand it's boot sequence:
  1. After reset, the program counter starts at the beginning P6 internal ROM. In this internal ROM, some kind of pre-bootloader exists that evaluates external pins and selects the corresponding boot mode (e.g. boot over USB, NAND, IIC, UART, ... ). Depending on the selected mode, the peripherals are set-up and it is tried to boot over this peripheral.
    • Boot over NAND: The pre-bootloader starts the memory controller, copies the bootloader from NAND to internal RAM and sets the program counter to the address in internal RAM which basically starts the bootloader.
    • Boot over USB: The pre-bootloader listens to USB and waits for the "Hello P6" command. If received, it replies and awaits an image (the usb_bootloader.bin). The received data is copied to internal RAM and the program counter is changed to the internal RAM address wich in effect starts the bootloader.

  2. Depending on the started bootloader, either the UBI partitions are "mounted" and the kernel image is read or the bootloader waits until the kernel image is sent over USB.
  3. If the installer.plf (which is basically a kernel image) is booted over USB, the "init" command of this image awaits the actual firmware (ardrone_update.plf) over USB and installs the content to NAND.

Friday, December 31, 2010

A.R. Drone USB (Updated)

A word of warning: You should not do anything like the following if you do not know what you do. You may ruin your drone.

As A.R. Drone has an USB OTG Port, it should be possible to use this port for extending the functionality of A.R. Drone.

But sadly Parrot disabled this port and only allows to use it for flashing purpose. Luckily they provide the source code for the driver [1].

So... let's have a closer look to this USB port..

First, Parrot defined the port as device only.

arch/arm/parrot6/mykonos.c, line 109:
static dwc_otg_info_t usb0_info = {
 .ctrl_mode = 2,
 .sof_filter = 7,
 .reset_pin = -1,
 .vbus_detection = 0,
 .fiq_enable = 0,
};

According to dwc_otg driver:
drivers/parrot/usb/dwc_otg/dwc_otg_cil.h
 /**
  * Controller mode
  * 0 - OTG
  * 1 - host only
  * 2 - device only
  */
 int32_t ctrl_mode;
#define DWC_OTG_HOST_DEVICE 0
#define DWC_OTG_HOST_ONLY   1
#define DWC_OTG_DEVICE_ONLY 2

In order to enable the USB host mode, it is required to overwrite/ignore the usb0_info defined in mykonos.c.

This can be achieved by patching dwc_otg_driver.c where the platform data is copied to the local parameter data. This is done by function "dwc_otg_set_specific_param". Also, by default (if not overwritten by platform data) the local parameters are configured as DWC_OTG_HOST_DEVICE. So simply not copying this parameter would prevent the driver from going to DEVICE_ONLY mode.

Thus the driver is modified and the assignment "params->ctrl_mode = info->ctrl_mode" is removed:
drivers/parrot/usb/dwc_otg/dwc_otg_driver.c, line 224:

/**
 * This function is called to set specific configuration parameters
 */
static void 
dwc_otg_set_specific_param
(
dwc_otg_info_t *info,
dwc_otg_core_params_t *params,
int port
)
{
 params->sof_filter = info->sof_filter;
 params->reset_pin = info->reset_pin;
 params->speed = info->speed;
 if (port == 0) {
  //params->ctrl_mode = info->ctrl_mode;
  //params->vbus_detection = info->vbus_detection;
 }
 if (port == 1 && !usb1_disable_fiq) {
  params->fiq_enable = info->fiq_enable;
 }
}

[Update]
As noted by MAPGPS [3], there is still an issue with the driver causing Oops. To fix this issue, it is necessary to change the overcurrent_pin from 89 to -1:

drivers/parrot/usb/dwc_otg/dwc_otg_driver.c, line 135:

.overcurrent_pin = -1, /* default */
[/Update]



After compiling, ftp-ing the module to the drone and calling

# insmod dwc_otg.ko

Oh no! dmesg shows that something gone wrong.. also VBus is still +0 V :-(

[   39.862534] dwc_otg: version 2.70a-parrot 22/03/2009
[   39.862703] dwc_otg dwc_otg.0: dwc_otg_driver_probe(c034d578)
[   39.862736] dwc_otg dwc_otg.0: start=0xc0400000
[   39.862851] dwc_otg dwc_otg.0: base=0xc8e00000
[   39.862883] dwc_otg dwc_otg.0: specific configuration
[   39.862914] dwc_otg dwc_otg.0: dwc_otg_device=0xc7a0b6e0
[   39.873574] DWC_otg: dwc_otg_core_reset() HANG! Soft Reset
 GRSTCTL=80000001
[   39.980233] DWC_otg: dwc_otg_core_reset() HANG! Soft Reset
 GRSTCTL=80000001

Looking at the drivers code, it seems like this HANG! message indicates a communication problem with the PHY. Checking the voltage levels of the PHY, it seems like almost all pins are tri-stated.

Having a look at the PCB, a SMSC USB3317 can be identified. According to its datasheet there is a pin named RESETB. When this pin is set to low the PHY is suspended and all I/O are tri-stated.

By monitoring RESETB it can be observed that RESETB is toggled by program.elf. So dumping all GPIO registers before and after starting program.elf the pin can be found.

And voilá: GPIO_127 is used to enable/disable the PHY. Program.elf sets it to output a high level which then switches a transistor and pulls RESETB to low.

In order to activate the USB as host GPIO_127 needs to be set to input level. This can be done either by ioctl or by the gpio command:

# gpio 127 -d i

After re-inserting dwc_otg.ko, dmesg no longer shows the HANG! message and VBUS has +5V :-)

Let's try to connect an USB device. The pinout for the USB connector is described in [2]. I use an old USB thumb drive (128MB) for testing.

dmesg shows:

[ 1675.054378] usb-storage: USB Mass Storage device detected
[ 1675.054650] usb-storage: -- associate_dev
[ 1675.054680] usb-storage: Vendor: 0x0ea0, Product: 0x2168,
 Revision: 0x0200
[ 1675.054707] usb-storage: Interface Subclass: 0x06, Protocol:
 0x50
[ 1675.054741] usb-storage: Transport: Bulk
[ 1675.054761] usb-storage: Protocol: Transparent SCSI
[ 1675.055439] scsi1 : SCSI emulation for USB Mass Storage devices
[...]
[ 1680.071311] scsi 1:0:0:0: Direct-Access              128MB       
     2.00 PQ: 0 ANSI: 2

Seems to work :-)


[1] https://projects.ardrone.org/documents/show/19
[2] https://projects.ardrone.org/attachments/167/ARDrone-USB-Cable.png
[3] http://www.ardrone-flyers.com/forum/viewtopic.php?p=5823#p5823