Using the BlackIce II in a Vagrant Virtual Machine - mystorm-org/BlackIce-II GitHub Wiki

Introduction

While I do have a real Linux desktop that's sometimes used for electronics tinkering, I use my MacBook much more. And while most tools can be made to work under OS X, I prefer to keep my development environments consistent.

That's why I use a Vagrant (in combination with VirtualBox) to run a Linux virtual machine.

There are plenty of articles online that explain how to get started with Vagrant, but the most important part is that you'll eventually end up with a file called Vagrantfile, which is used to configure the virtual machine.

By default, you'll get an isolate virtual machine that can not access the physical interfaces of your host (your MacBook).

However, when I'm playing with the BlackIce board, I want to be able to access the USB interfaces just like I can on my Linux desktop.

To do that, we need to configure the virtual machine such that specific USB devices can be accessed by the virtual machine.

Finding the USB device information of the BlackIce-II board

Each USB device has a vendor ID and a product ID. We need to find the ID combos for all USB devices that can be present on the BlackIce-II board. Out of the box, there are there 3 such combos.

On USB1 (the one used to download a bitstream into the FPGA):

  • In normal mode, with the jumper between pins 14 and 16 present
  • In DFU (Device Firmware Update) mode, with the jumper between pins 14 and 16 removed

On USB2:

  • a serial device created by the CH340 chip

To figure out the vendor ID and product ID of each mode, just plug in the USB cable in the different ports, with or with jumper present, and type the following:

/Applications/VirtualBox.app/Contents/MacOS/VBoxManage list usbhost

(VBoxManage is a command line tool that comes with VirtualBox, which you should already have installed as part of the Vagrant installation procedure.)

You will see a lot of USB devices that are standard on your MacBook, but there will also be the following:

USB1, normal mode:

UUID:               <some unique identifier string>
VendorId:           0x0483 (0483)
ProductId:          0x5740 (5740)
Revision:           2.0 (0200)
Port:               1
USB version/speed:  0/Full
Manufacturer:       STMicroelectronics
Product:            STM32 Virtual ComPort
SerialNumber:       00000000001A
Address:            p=0x5740;v=0x0483;s=0x0007dd78f1fe0531;l=0x14100000
Current State:      Busy

USB1, DFU mode:

UUID:               <some unique identifier string>
VendorId:           0x0483 (0483)
ProductId:          0xdf11 (DF11)
Revision:           34.0 (3400)
Port:               1
USB version/speed:  0/Full
Manufacturer:       STMicroelectronics
Product:            STM32  BOOTLOADER
SerialNumber:       207D32833141
Address:            p=0xdf11;v=0x0483;s=0x0007ddd0c5b6a41b;l=0x14100000
Current State:      Available

USB2:

UUID:               <some unique identifier string>
VendorId:           0x1a86 (1A86)
ProductId:          0x7523 (7523)
Revision:           2.99 (0299)
Port:               1
USB version/speed:  0/Full
Manufacturer:       QinHeng Electronics
Product:            USB2.0-Serial
Address:            p=0x7523;v=0x1a86;s=0x0007ddd83ceb620d;l=0x14100000
Current State:      Available

The only thing we really care about here are the product name, the vendor ID and the product ID fields.

Product:            STM32 Virtual ComPort
VendorId:           0x0483 (0483)
ProductId:          0x5740 (5740)

Product:            STM32  BOOTLOADER
VendorId:           0x0483 (0483)
ProductId:          0xdf11 (DF11)

Product:            USB2.0-Serial
VendorId:           0x1a86 (1A86)
ProductId:          0x7523 (7523)

We now need to tell the virtual machine that these USB devices need to be passed on.

Adding the USB Devices to the Virtual Machine Configuration

In your Vagrantfile, you should have something like this:

  config.vm.provider "virtualbox" do |vb|
    # Display the VirtualBox GUI when booting the machine
    vb.gui = false

    # Customize the amount of memory on the VM:
    vb.memory = "2048"
  end

Some values may be different...

Change that as follows:

  config.vm.provider "virtualbox" do |vb|
    # Display the VirtualBox GUI when booting the machine
    vb.gui = false

    # Customize the amount of memory on the VM:
    vb.memory = "2048"

    # Give virtual machine access to physical USB interface
    vb.customize ["modifyvm", :id, "--usb", "on"]
    # Allow the following devices to be visible in the virtual machine
    vb.customize ['usbfilter', 'add', '0', '--target', :id, '--name', 'STM32 Virtual ComPort', '--vendorid', '0x0483', '--productid', '0x5740']
    vb.customize ['usbfilter', 'add', '1', '--target', :id, '--name', 'STM32  BOOTLOADER',     '--vendorid', '0x0483', '--productid', '0xdf11']
    vb.customize ['usbfilter', 'add', '2', '--target', :id, '--name', 'USB2.0-Serial',         '--vendorid', '0x1a86', '--productid', '0x7523']
  end

If you are really interested in how to further configure your Virtualbox, you can find the details about these commands in the VirtualBox manual.

Intermediate Result

After doing vagrant up with the updated Vagrantfile, and then running vagrant ssh, you can run slush in your virtual Linux machine.

You should seem something like this for the different USB devices:

ubuntu@ubuntu-xenial:~$ lsusb
Bus 001 Device 002: ID 1a86:7523 QinHeng Electronics HL-340 USB-Serial adapter
Bus 001 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
ubuntu@ubuntu-xenial:~$ lsusb
Bus 001 Device 003: ID 0483:5740 STMicroelectronics STM32F407
Bus 001 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
ubuntu@ubuntu-xenial:~$ lsusb
Bus 001 Device 004: ID 0483:df11 STMicroelectronics STM Device in DFU Mode
Bus 001 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
ubuntu@ubuntu-xenial:~$

However, after plugging in USB1 in normal mode, you will not see /dev/ttyACM0 show up in the /dev directory. Similarly, /dev/ttyUSB0 will be absent when plugging in USB2.

The reason for this is that the Linux kernel module are not included by default for the virtual machine.

Install Dedicated Linux USB Drivers

To add the necessary drivers, add the following command to the Vagrantfile or execute it inside the virtual machine:

sudo apt-get install linux-image-extra-virtual

Take down the virtual machine with vagrant halt, restart it again with vagrant up, log in with vagrant ssh.

Result

Inside the virtual machine, now type the following:

dmesg -w

When you plug in USB1, you will now see the following:

[  602.440327] usb 1-1: new full-speed USB device number 5 using ohci-pci
[  602.726637] usb 1-1: New USB device found, idVendor=0483, idProduct=5740
[  602.726642] usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[  602.726644] usb 1-1: Product: STM32 Virtual ComPort
[  602.726646] usb 1-1: Manufacturer: STMicroelectronics
[  602.726648] usb 1-1: SerialNumber: 00000000001A
[  602.735397] cdc_acm 1-1:1.0: ttyACM0: USB ACM device

Success! ttyACM0 has been added as a device.

You will also see it in the /dev directory:

ubuntu@ubuntu-xenial:~$ ls -als  /dev/ttyACM*
0 crw-rw---- 1 root dialout 166, 0 Feb 22 07:18 /dev/ttyACM0

Similarly for USB2, dmesg -w will show the following:

[  816.417666] usb 1-1: new full-speed USB device number 9 using ohci-pci
[  816.688523] usb 1-1: New USB device found, idVendor=1a86, idProduct=7523
[  816.688527] usb 1-1: New USB device strings: Mfr=0, Product=2, SerialNumber=0
[  816.688530] usb 1-1: Product: USB2.0-Serial
[  816.694740] ch341 1-1:1.0: ch341-uart converter detected
[  816.750916] usb 1-1: ch341-uart converter now attached to ttyUSB0

And, indeed, ttyUSB0 will be present as well:

ubuntu@ubuntu-xenial:~$ ls -als /dev/ttyUSB*
0 crw-rw---- 1 root dialout 188, 0 Feb 22 07:20 /dev/ttyUSB0

Success!

Finally, we can now reproduce the Linux example of the Getting Started Guide of the BlackIce-II Wiki:

ubuntu@ubuntu-xenial:~$ sudo bash
root@ubuntu-xenial:~# stty -F /dev/ttyACM0 raw
root@ubuntu-xenial:~# cat /dev/ttyACM0
<Iceboot 0.4> Config done

and

ubuntu@ubuntu-xenial:~/projects/BlackIce-II/examples/blink$ sudo cat chip.bin > /dev/ttyACM0