Introduction
I got a TI CC3200 launchpad at some point to play around with a WiFi-enabled MCU platform. Below I describe the procedures used to work with it from a Mac.
In contrast to the Tiva launchpad, which uses ICDI as the debug interface, the CC3200 uses a FTDI-based serial-over-USB interface. This means that the procedure for flashing and debugging is different.
Flashing
Software
For flashing a program to the CC3200, I use the cc3200tool program. You can find it here: https://github.com/ALLTERCO/cc3200tool. It is written in Python, which means you may have to install the pySerial dependency first. I installed both pySerial and cc3200tool systemwide, not using pip but by cloning the repositories and running python setup.py install in the pySerial and cc3200tool directories.
Hardware
In order for cc3200tool to be able to flash your CC3200 launchpad, you have to put it manually in “boot loader” mode by bridging SOP2 jumper. The photo below shows the location of this jumper:
Procedure
The procedure for flashing is as follows:
Make sure you know the device’s serial connection. Typically running “ls /dev/tty.usbserial*” in a terminal will reveal the serial device.
Stop any terminal sessions that show the CC3200’s UART output. This is needed since cc3200tool uses the same serial connection.
Issue the following command in the terminal:
cc3200tool -p /dev/cu.usbserial-cc3101B --reset prompt write_file /usr/local/cc3200-sdk/example/get_time/gcc/exe/get_time.bin /sys/mcuimg.bin
This command is constructed as follows:
cc3200tool -p--reset prompt write_file .bin /sys/mcuimg.bin
/sys/mcuimg.bin is the file that the CC3200 loads and starts on its user-accessible ARM Cortex-M4 core when powered or reset.
The tool will prompt you to bridge the SOP2 jumper and press the reset button on the launchpad:
2016-10-08 21:15:46,086 -- Connecting to target... Reset the device with SOP2 asserted and press Enter
See the picture above for the location of the jumper. Put a wire across the pins (or put on an actual jumper) and press the reset button.
The tool will continue and flash your binary onto the CC3200:
2016-10-08 21:15:53,771 -- Connected, reading version... 2016-10-08 21:15:53,778 -- connected to target 2016-10-08 21:15:53,778 -- Version: CC3x00VersionInfo((0, 4, 1, 2), (0, 0, 0, 0), (0, 0, 0, 0), (0, 0, 0, 0), (16, 0, 0, 0)) 2016-10-08 21:15:53,779 -- This is a CC3200 device 2016-10-08 21:15:53,779 -- Switching to NWP bootloader... 2016-10-08 21:15:53,794 -- Switching UART to APPS... 2016-10-08 21:15:53,810 -- Resetting communications ... 2016-10-08 21:15:57,225 -- timed out while waiting for ack 2016-10-08 21:15:57,634 -- Uploading rbtl3100s.dll... 2016-10-08 21:15:57,637 -- Getting storage list... 2016-10-08 21:15:57,651 -- Getting storage info... 2016-10-08 21:15:57,666 -- storage info bytes: 0x10, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0 2016-10-08 21:15:58,385 -- APPS version: CC3x00VersionInfo((0, 4, 0, 2), (0, 0, 0, 0), (0, 0, 0, 0), (0, 0, 0, 0), (16, 0, 0, 0)) 2016-10-08 21:15:58,402 -- File exists on target, erasing 2016-10-08 21:15:58,418 -- Erasing file /sys/mcuimg.bin... 2016-10-08 21:15:58,530 -- Uploading file /usr/local/cc3200-sdk/example/get_time/gcc/exe/get_time.bin -> /sys/mcuimg.bin [62856]... ................ 2016-10-08 21:16:00,321 -- All commands done, bye.
Remove the jumper, restart your terminal session to receive UART output if desired, and press the reset button again to start your software.
Debugging
Note: debugging with GDB does not work when using FreeRTOS.
The CC3200 SDK from TI has an openOCD config file that you can use to start a GDB session. The file is located in /usr/local/cc3200-sdk/tools/gcc-scripts/cc3200.cfg. It also has a GDB script to run openOCD with the right options: gdbinit
I use the openOCD in the Mac build of the GNU ARM Eclipse project. They have a DMG here: https://github.com/gnuarmeclipse/openocd/releases.
Installing this way implies that openOCD is not added to the path used in the terminal to find binaries, so you won’t be able to type “openocd” in the terminal. So we add it manually:
export PATH=$PATH:/Applications/GNU\ ARM\ Eclipse/OpenOCD/0.10.0-201601101000-dev/bin
I also created 2 symlinks in the /usr/local/cc3200-sdk/tools/gcc-scripts:
mem_helper.tcl -> /Applications/GNU ARM Eclipse/OpenOCD/0.10.0-201601101000-dev/scripts/mem_helper.tcl target -> /Applications/GNU ARM Eclipse/OpenOCD/0.10.0-201601101000-dev/scripts/target/
Then, we can run a GDB session from the gcc-scripts directory:
arm-none-eabi-gdb -x gdbinit /usr/local/cc3200-sdk/example/get_time/gcc/exe/get_time.axf
CC3200 / CC3200MOD GPIO pin mappings
In the CC3200 SDK, peripherals sit between the application code and the device’s pins, to provide abstractions. The application uses peripherals to perform actions: for sending bytes over a serial connection, you use one of the device’s UART peripherals. After configuring the peripherals to use certain pins, you don’t have to think about the pins any more.
The device’s pin multiplexing table (table 3.2 on p.11 of the CC3200MOD datasheet) tells you which physical device pins you can use with a certain peripheral. In the UART example, when you application starts, it will assign 2 physical pins to the UART peripheral you want to use. After this setup, you no longer think about the pins, but your application interacts with the UART peripheral. (For example, using MAP_UARTCharPut to send a character over the serial connection.) In this way, peripherals abstract away the individual pin actions (“high” or “low”) from the programmer.
In contrast to most other peripherals, for GPIOs the application needs to know the mapping from physical pin to peripheral pins, because for every pin status change, the right bit in the right register needs to be set. The CC3200’s GPIO peripheral uses 5 8-bit registers: GPIOA0 to GPIOA4. Setting a bit in one of these registers, will flip the corresponding physical pin to the right status. This means your application needs to deal with registers (GPIO_BASE) and bits within the registers (GPIO pin).
The mapping from physical pins to peripheral registers, and bits within the registers, is not very obvious from TIs SDK and documentation. According to the their on-line PinMux application, this is the full mapping:
Pin | GPIO base | GPIO pin | Pin | GPIO base | GPIO pin | ||
---|---|---|---|---|---|---|---|
PIN_50 | GPIOA0_BASE | GPIO_PIN_0 | PIN_63 | GPIOA1_BASE | GPIO_PIN_0 | ||
PIN_55 | GPIOA0_BASE | GPIO_PIN_1 | PIN_64 | GPIOA1_BASE | GPIO_PIN_1 | ||
PIN_57 | GPIOA0_BASE | GPIO_PIN_2 | PIN_01 | GPIOA1_BASE | GPIO_PIN_2 | ||
PIN_58 | GPIOA0_BASE | GPIO_PIN_3 | PIN_02 | GPIOA1_BASE | GPIO_PIN_3 | ||
PIN_59 | GPIOA0_BASE | GPIO_PIN_4 | PIN_03 | GPIOA1_BASE | GPIO_PIN_4 | ||
PIN_60 | GPIOA0_BASE | GPIO_PIN_5 | PIN_04 | GPIOA1_BASE | GPIO_PIN_5 | ||
PIN_61 | GPIOA0_BASE | GPIO_PIN_6 | PIN_05 | GPIOA1_BASE | GPIO_PIN_6 | ||
PIN_62 | GPIOA0_BASE | GPIO_PIN_7 | PIN_06 | GPIOA1_BASE | GPIO_PIN_7 | ||
Pin | GPIO base | GPIO pin | Pin | GPIO base | GPIO pin | ||
PIN_07 | GPIOA2_BASE | GPIO_PIN_0 | PIN_17 | GPIOA3_BASE | GPIO_PIN_0 | ||
PIN_08 | GPIOA2_BASE | GPIO_PIN_1 | PIN_21 | GPIOA3_BASE | GPIO_PIN_1 | ||
PIN_15 | GPIOA2_BASE | GPIO_PIN_6 | PIN_18 | GPIOA3_BASE | GPIO_PIN_4 | ||
PIN_16 | GPIOA2_BASE | GPIO_PIN_7 | PIN_20 | GPIOA3_BASE | GPIO_PIN_5 | ||
PIN_53 | GPIOA3_BASE | GPIO_PIN_6 | |||||
PIN_52 | GPIOA4_BASE | GPIO_PIN_0 | PIN_45 | GPIOA3_BASE | GPIO_PIN_7 |