I started getting involved with a new project that involves working with embedded systems for the first time. I started working with TI's CC3200 chip on their Launchpad development board. Unfortunately, their SDK and documentation strictly targets for Windows OS, and even their installer is a Windows executable.

Fortunaltely, I found a few articles that describe how to work with their SDK on a Linux machine. This post will be mainly a summary of this great document along with a couple of other references (see here and here) to be up and running with the SDK on GNU/Linux.

Following versions were used for writing this page

Download CC3200 SDK

  1. Fetch the SDK from TI's website
    I had issues actually creating an account, so instead I used a BugMeNot account.
  2. Extract the content
  3. Unfortunately the SDK comes as a .exe installer. This document says that they had success using wine. Instead, I got a hold of a Windows machine and extracted it directly there. All the required files are bundled in the installed directory.
  4. Copy the installed directory to /path/to/cc3200sdk on your Linux system
    For convenience, assign a variable to this path:
    > echo "export CC3200SDK=/path/to/cc3200sdk" >> ~/.bashrc
    

Configure LaunchXL JTAG debug interface

With the development board plugged in, if you run lsusb you should see something like this:

> lsusb
...
Bus 003 Device 007: ID 0451:c32a Texas Instruments, Inc.
...
Load the ftdi-sio kernel module
su -c "modprobe ftdi-sio"
su -c "echo 0451 c32a > /sys/bus/usb-serial/drivers/ftdi_sio/new_id"

The first four hexadecimal digits 0451 is the Vendor ID and the second c32a is the Device ID. If you are running an old kernel, syntax will be slightly different. See references above.

Make sure a device path exists under /dev/:

> ls /dev/ttyUSB*
# example output: /dev/ttyUSB0
I have only /dev/ttyUSB0 so from this point on, I will refer treat it as the only device path. If you have multiple ones, you can run dmesg --follow and see which which tty it gets assigned to, or you can match tty to the usb device.

Build and Install OpenOCD

OpenOCD is the On-Chip Debugger. Very cool.
  1. Install libusb development libraries

    On Fedora

    yum install libusb-devel
    

    or on openSUSE

    zypper in libusb-1_0-devel
    
  2. Download and build OpenOCD. On OpenSUSE, they're in the default repositories
    zypper in openocd
    
    But on Fedora you might have to build them yourself. Download OpenOCD. and build them. Run the configure executable and make sure that at the end it reports
    MPSSE mode of FTDI based devices yes (auto)
    
    Configure, build, and install:
    > ./configure
    > make -j 4
    > su -c "make install"
    
    Update the group name in contrib/60-openocd.rules, replacing YOUR_GROUP_NAME_GOES_HERE with the group your username actually belongs to:
    > sed -i s/plugdev/YOUR_GROUP_NAME_GOES_HERE/g contrib/60-openocd.rules
    > su -c "cp openocd/contrib/60-openocd.rules /etc/udev/rules.d/"
    
    The rules do not affect devices that are already plugged in. If your board was plugged in, unplug and replug it for the new rules to take effect.
  3. Plug in the CC3200 board and make sure openocd runs
    > openocd -f $CC3200SDK/tools/gcc_scripts/cc3200.cfg
    

    and you should output similar to this:

    Open On-Chip Debugger 0.10.0
    Licensed under GNU GPL v2
    For bug reports, read
            http://openocd.org/doc/doxygen/bugs.html
    adapter speed: 1000 kHz
    Info : auto-selecting first available session transport "jtag". To override use 'transport select <transport>'.
    cc3200_dbginit
    Info : clock speed 1000 kHz
    Info : JTAG tap: cc3200.jrc tap/device found: 0x0b97c02f (mfg: 0x017 (Texas Instruments), part: 0xb97c, ver: 0x0)
    Info : JTAG tap: cc3200.dap enabled
    Info : cc3200.cpu: hardware has 6 breakpoints, 4 watchpoints
    

    Press Ctrl-c to quit. Also, make sure you can access /dev/ttyUSB0

    > cat /dev/ttyUSB0
    

    which should display nothing and just wait. Press Ctrl-c to quit.

Install cross toolchain

  1. Install toolchain
  2. In Fedora, toolchain is available in fedora repos:

    su -c "yum install arm-none-eabi arm-none-eabi-newlib arm-none-eabi-gdb"
    

    For OpenSUSE, build or download prebuild toolchain binaries. Put the binaries in path, e.g.

    > echo "export PATH=$PATH:/opt/gcc-arm-none-eabi-5_4-2016q3/bin/" >> ~.bashrc
    
    and reload your .bashrc
    > . ~/.bashrc
    
  3. Edit $CC3200SDK/tools/gcc_scripts/gdbinit to make sure OpenOCD finds its configuration files. Modified line:
    target remote | openocd -c "gdb_port pipe; log_output openocd.log" -f $CC3200SDK/tools/gcc_scripts/cc3200.cfg
    

Flashing

I've used cc3200tool for flashing (and downloading) files to the board. The README file that comes with it is self-explanatory.

Compile and Run Examples

For all examples, make sure the jumpers on the board are set correctly. See reference above, the $CC3200SDK/docs/Getting_Started_Guide.pdf, and $CC3200SDK/docs/example/ documents.

Example 1: Blinky

  1. Build
    > cd $CC3200SDK/example/blinky/gcc
    > make
    
  2. Run a GDB session with the built file
    > arm-none-eabi-gdb -x $CC3200SDK/tools/gcc_scripts/gdbinit exe/blinky.axf
    
    You should see a GDB session launch with a breakpoint at beginning of main function
    Type "apropos word" to search for commands related to "word"...
    Reading symbols from exe/blinky.axf...done.
    Open On-Chip Debugger 0.10.0
    Licensed under GNU GPL v2
    For bug reports, read
            http://openocd.org/doc/doxygen/bugs.html
    0x20005e74 in pui32Stack ()
    Loading section .text, size 0xf78 lma 0x20004000
    Loading section .data, size 0x18 lma 0x20004f78
    Start address 0x20004778, load size 3984
    Transfer rate: 61 KB/sec, 1992 bytes/write.
    Breakpoint 1 at 0x20004474: file ../main.c, line 199.
    
    Breakpoint 1, main () at ../main.c:199
    199         BoardInit();
    (gdb)
    
    Press c to continue execution of the code
  3. You should see the LED lights on the board periodically flashing. Press Ctrl-c followed by q to quit

Example 2: AP

The $CC3200SDK/example/getting_started_with_wlan_ap example sets the WiFi chip to AP mode and waits for a device to connect to it. But the code prompts you to enter the SSID of the wifi board, which is hard to do if you never actually see the prompt.
  1. Set the jumpers on the board in the right configuration (see previous note)
  2. Build the application
    > cd $CC3200SDK/example/blinky/gcc
    > make
    
  3. Read the contents of the serial port of the board
    > cat /dev/ttyUSB0
    
    Leave this running. Alternatively, you can use screen for this. More on this later.
  4. Run a GDB session in a separate terminal
    > arm-none-eabi-gdb -x ~/cc3200-sdk/tools/gcc_scripts/gdbinit exe/wlan_ap.axf
    
    and press c to continue code execution You should see the terminal running cat being filled with program output and asking for an SSID input:
                          *************************************************
                                 CC3200 WLAN AP Application
                          *************************************************
    
    Host Driver Version: 1.0.1.11
    Build Version 2.2.0.1.31.1.2.0.2.1.0.3.23
    Device is configured in default state
    Device started as STATION
    Enter the AP SSID name:
    
  5. Of course, cat doesn't accept inputs. Open another terminal and send the SSID by directly writing to the tty
    > echo "this is my ssid" > /dev/ttyUSB0
    
    and it should start up in AP mode.
Instead of cating and echoing to the buffer, you can use screen:
  1. Get the terminal's baudrate
    > stty < /dev/ttyUSB0
    
  2. Open a screen
    > screen /dev/ttyUSB0 insert_baudrate_here
    
    and replace insert_baudrate_here with the actual baudrate

Example 3: TCP socket

The $CC3200SDK/example/tcp_socket lets you open TCP sockets and both receive or send packets. We can use nc and telnet that comes shipped with your distro for testing both.

First, for sending packets to CC3200

  1. Overwrite SSID_NAME, SECURITY_TYPE, and SECURITY_KEY
    These macros that are defined in $CC3200SDK/example/common/common.h file. Since common.h is shared with other examples, you may want to consider doing it in the main.c file instead: I'll have it connect to my router with SSID "FreeWifi" that uses WPA2 protocols.
    // $CC3200SDK/example/tcp_socket
    #undef SSID_NAME
    #define SSID_NAME "FreeWifi"
    #undef SECURITY_TYPE
    #define SECURITY_TYPE SL_SEC_TYPE_WPA
    #undef SECURITY_KEY
    #define SECURITY_KEY "YgfHhueTKg+ZRG1AS8BImFG3"
    
  2. Build the example as before
  3. cat the /dev/ttyUSB0 tty (or use screen)
  4. Run a GDB session with the built file
  5. Make selections in prompted options
    Make the "Packet size" to be 10 so we fill it quickly by hand.
  6. Navigate the menus and make CC3200 listen for packets
  7. Start a telnet connection to the CC3200
    > telnet <LOCAL_IP_ADDRESS_OF_CC3200> 5001
    
    Obviously, your computer has to be on the same network as the CC3200. Start typing random strings followed by enter. Repeat a total of 10 times.

Receiving packets on CC3200

  1. Change settings
    Follow the prompt and make following selections:
    • Packet size: 10
    • Destination IP: Local IP of your computer
    • Port: 5001
  2. Configure your local firewall
    Your OS may by default be blocking incoming traffics. Make sure that incoming connections from CC3200's IP to port 5001 are allowed. You can use other ports if you prefer, and you generally need root access for binding to ports below 1024.
  3. Start a server on local machine
    > nc -vl <LOCAL_COMPUTER_IP_ADDRESS> 5001
    
  4. Nagivate the menus on CC3200 and set it to send packets to server (your computer)