2013. május 13., hétfő

Programming the Bluegiga BLE112 Bluetooth 4.0 module with Linux

Why?

BLE112 is a Blutooth 4.0 or Blutooth Low Energy (BLE for short) module that contains a microcontroller packed with an awsome firmware that lets you write Bluetooth 4.0 applications in a very user-friendly language called BGScript.


WARNING!!! if you follow the guide below, you're gonna brick the chip. The recent versions of BLE* firmwares require a license key that built into the chip, and cc-tool wipes it, effectively disabling the radio on the device. The solution is to use the "BLE Update Utility" from BlueGiga. I couldn't start it on older Windows installations nor on Wine. Work in progress. If you manage to start it in Wine, please share the knowledge. Thank you!

You can get more info on the module at:

http://www.bluegiga.com/BLE112_Bluetooth_Smart_module

If you want to use the module, you need a programmer tool from Texas Instruments called cc-debugger:

http://www.ti.com/tool/cc-debugger

And you need to wire up the chip to the computer. You can read about that at the following two links:

http://blog.bluetooth-smart.com/2012/09/11/programming-the-ble112-with-c-code-using-iar/

http://blog.bluetooth-smart.com/2012/09/16/programming-the-ble112-using-bgscript/

The programming software can be downloaded from bluegiga's techforum. These are a collection of windows applications that let you build the program and there's also a nice tool called blegui2.exe that lets you debug you solution.

To try your bluetooth module, you need a bluetooth 4.0 enabled hardware or a bluetooth 4.0 dongle such as BLED112 from Bluegiga:

http://www.bluegiga.com/BLED112_Bluetooth_smart_dongle

This plugs into an USB port. There is a proper driver that works with Windows. I had no problem to set up the software and hardware on my home machine that runs Windows 8. When I switched to Linux, problems popped up.

First of all, I noticed that when I plugged in the dongle, it kept disconnecting, and connecting again. The following output is from dmesg:

[ 5755.444220] cdc_acm 3-1:1.0: ttyACM3: USB ACM device
[ 5755.984120] usb 3-1: USB disconnect, device number 43
[ 5756.524111] usb 3-1: new full-speed USB device number 44 using uhci_hcd
[ 5756.698098] usb 3-1: New USB device found, idVendor=2458, idProduct=0001
[ 5756.698102] usb 3-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[ 5756.698104] usb 3-1: Product: Low Energy Dongle
[ 5756.698106] usb 3-1: Manufacturer: Bluegiga
[ 5756.698108] usb 3-1: SerialNumber: 1
[ 5756.706137] cdc_acm 3-1:1.0: ttyACM3: USB ACM device
[ 5757.224143] usb 3-1: USB disconnect, device number 44
[ 5757.744071] usb 3-1: new full-speed USB device number 45 using uhci_hcd
[ 5757.912164] usb 3-1: New USB device found, idVendor=2458, idProduct=0001
[ 5757.912175] usb 3-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[ 5757.912182] usb 3-1: Product: Low Energy Dongle
[ 5757.912188] usb 3-1: Manufacturer: Bluegiga
[ 5757.912194] usb 3-1: SerialNumber: 1
[ 5757.920274] cdc_acm 3-1:1.0: ttyACM3: USB ACM device
[ 5758.464106] usb 3-1: USB disconnect, device number 45
[ 5758.988078] usb 3-1: new full-speed USB device number 46 using uhci_hcd
[ 5759.160089] usb 3-1: New USB device found, idVendor=2458, idProduct=0001
[ 5759.160100] usb 3-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[ 5759.160107] usb 3-1: Product: Low Energy Dongle
[ 5759.160113] usb 3-1: Manufacturer: Bluegiga
[ 5759.160119] usb 3-1: SerialNumber: 1
[ 5759.168192] cdc_acm 3-1:1.0: ttyACM3: USB ACM device
[ 5759.704175] usb 3-1: USB disconnect, device number 46
[ 5760.220064] usb 3-1: new full-speed USB device number 47 using uhci_hcd
[ 5760.592121] usb 3-1: New USB device found, idVendor=2458, idProduct=0001
[ 5760.592126] usb 3-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[ 5760.592128] usb 3-1: Product: Low Energy Dongle
[ 5760.592130] usb 3-1: Manufacturer: Bluegiga
[ 5760.592132] usb 3-1: SerialNumber: 1

I dug through the Internet for a good few days after I found out that this dongle resets itself if it receives a malformed command. I suspected that there is some process that tries to communicate with it and keeps it resetting over and over.

The solution was to add the device to the udev blacklist. Create a new file under /lib/udev/rules.d (mine is named 77-mm-my.rules), and add the following content:

# BLuegiga BLED112
ATTRS{idVendor}=="2458", ATTRS{idProduct}=="0001", ENV{ID_MM_DEVICE_IGNORE}="1"

The name of the file is important. Use my idea about the name if you don't know udev very well.

After this, restart modem-manager by issuing "sudo killall modem-manager". After this, modem-manager should not interfere with the device.

This trick can save a lot of hardware from being bugged to death by modem-manager. One example is my USB AVR programmer.

After this, ALL bluegiga programs kinda work as expected with wine. No freezes or segfaults! The compliler and builder can be run exactly as you would do from under Windows. Just pay attention to the path / drive mapping where appropriate.

The big surprise is that blegui2.exe is also works like a charm.

The only problem is with wine itself. It does not seem to offer out-of-the-box serial port support.

I managed to find a solution to this problem too:

http://ubuntuforums.org/showthread.php?t=1523814

TL;DR: you have to download a registry file, and integrate it to wine's registry:

$ wget -O comport.reg http://bugs2.winehq.org/attachment.cgi?id=10210
$ regedit comport.reg

After this, wine can show Linux serial devices a Windows comX ports.

To configure the mapping, you have to create symlinks under ~/.wine/dosdevices/comX which point to devices under /dev/ttyXXX. In my case:

$ cd ~/.wine/dosdevices
$ ln -s /dev/ttyACM3 com1

It's actually quite a dull process to look up the device in dmesg and create the symlink myself. Udev can do this! Let's modify the udev rule to create a device symlink to our dongle, and point wine's com1 symlink to that symlink (yo dawg... :) ):

# BLuegiga BLED112
ATTRS{idVendor}=="2458", ATTRS{idProduct}=="0001", ENV{ID_MM_DEVICE_IGNORE}="1", SYMLINK="bluegiga/bled112"

And:

$ cd ~/.wine/dosdevices
$ ln -s /dev/bluegiga/bled112 com1

This way every time we plug out bled112 dongle into the computer, the correct device will be mapped under wine's com1.

So with everything working like that, the only problem is how to write the resulting .hex file onto out ble112 device?

The solution is cc-tool: http://sourceforge.net/projects/cctool/

This tool isn't included in the distributions I know, so you have to download the sources and build it yourself. It's quite easy to do, it follows the usual configure-make-make install process. Just make sure you install the boost and libusb development libraries. If you use Ubuntu, you can do that by issuing the following command:

$ apt-get install libboost-all-dev libusb-1.0-0-dev

After this, you can download and install the cc-tool package. Open up a terminal window, and do the following:

$ wget http://heanet.dl.sourceforge.net/project/cctool/cc-tool-0.26-src.tgz
$ tar -xf cc-tool-0.26-src.tgz
$ cd cc-tool
$ ./configure
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
...
checking for LIBUSB... yes
configure: creating ./config.status
config.status: creating Makefile
config.status: executing libtool commands
$ make
  CXX    src/main.o
...
  CXXLD  cc-tool
$ sudo make install
make[1]: Entering directory `/home/netom/install/cc-tool'
...
make[1]: Leaving directory `/home/netom/install/cc-tool'
$ sudo cc-tool
  CC Debugger device not found

You have to run the cc-tool program as root to be able to access USB. The last line is an error message. It means that the cc-debugger is not connected. When the device is connected, cc-tool recognizes it:
$ sudo cc-tool
  Programmer: CC Debugger
  Target: CC2540
  No actions specified

You can get some info on the target with the -t switch:
$ sudo cc-tool -t
  Programmer: CC Debugger
  Target: CC2540
  Device info: 
   Name: CC Debugger
   Debugger ID: 8561
   Version: 0x05CC
   Revision: 0x0034

  Target info: 
   Name: CC2540
   Revision: 0x20
   Internal ID: 0x8D
   ID: 0x2540
   Flash size: 128 KB
   Flash page size: 2
   RAM size: 8 KB
   Lock data size: 16 B

For more info, just enter cc-tool --help.
Okay. Now everythin should work fine. Let's build the bkble112 thermometer demo. Cd into the ble/example/bkble112 director, and issue the following commands. I'm going to use absolute paths on my own machine. Replace them with your paths.
$ cd ble/example/dkble112
$ wine /home/netom/install/ble/bin/bgbuild.exe project.bgproj
baudm:216 baude:10 rate:57617
UART channel:0
 baudrate   :57600
 actual     :57617
 error%     :0.0295139
 alternate f:2
ports:14336
C:/users/netom/Temp/qt_temp.crifX8
0
C:/users/netom/Temp/qt_temp.dflNl8

RAM Memory
-------------------------------------------------
Core RAM end                    @ 0x00cc5    3269
Top of RAM                      @ 0x01f00    7936
RAM left for data               = 0x0123b    4667
Attribute RAM                   - 0x00007       7
Connections                   1 - 0x00194     404
RAM for packet buffers      109 - 0x0109b    4251

Flash Memory
-------------------------------------------------
Core flash reserved             @ 0x18000   98304
Top of flash                    @ 0x1f800  129024
Flash left for data             = 0x07800   30720
Common configuration            - 0x00070     112
16 bit UUIDs                    - 0x00022      34
128 bit UUIDs                   - 0x00000       0
Attribute database              - 0x00084     132
Constant attributes data        - 0x0007d     125
USB descriptor                  - 0x000c6     198
BGScript                        - 0x001f1     497
Flash for PS Store           14 - 0x07000   28672
$ sudo cc-tool -few out.hex -v
  Programmer: CC Debugger
  Target: CC2540
  Erasing flash...
  Completed       
  Writing flash (128 KB)...
  Completed (1.25 s.)
  Verifying flash...
  Completed (0.54 s.)

If you notice random errors, try programming without the -f (fast) switch.
You can build your own projects similarly to this one.
One more trick: if you are tired entering full paths and wine commands, create and alias
$ echo 'alias bgbuild="wine <install dir>/ble/bin/bgbuild.exe"' >> ~/.bashrc

After this, you only have to type bgbuild project.xml to build your project.