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