OSX: Getting Pesky FTDI Debugging Devices to Work

Updated: 2018-12-19

Many useful FTDI-based debugging devices exist for those of us working in the embedded world. These devices are extremely useful and provide JTAG and SWD capabilities, as well as acting as I2C, SPI, or Serial protocol converters. With an FTDI debug tool, you can use your host machine to debug and interface with a variety of parts.

However, one fact that complicates things greatly is that most parts use their own USB product and vendor ID codes, which means that you have to manually modify the FTDI driver kext in order for your device to be detected. There are many guides on the internet for enabling custom FTDI device support, but most of them now seem out of date. This guide is valid as of OSX 10.12, which requires additional steps to disable OSX's "System Integrity Protection."

Testing a Connection

In order to judge whether an FTDI device is properly detected or not, I attempt to open a serial connection. Without the correct drivers, no usbserial devices show up. Your device will likely have a different name.

For example, here's how I connect to a TUMPA debugger on my host machine.

picocom -b 115200 /dev/tty.usbserial-TIM01416B

If you are unable to connect, you likely need to perform the steps below.


If you are unsure of what serial program to use, run the following commands to enable miniterm.py:

$ sudo easy_install pip
$ sudo pip install pyserial

After installing pyserial, you can run miniterm.py, which will show you a list of connected serial devices:

$ miniterm.py
--- Available ports:
--- /dev/cu.Bluetooth-Incoming-Port n/a
--- /dev/cu.MuadDib-WirelessiAP n/a

Note above that I have no USB serial device connected, indicating a problem.

Try Your Device

Before doing anything, try plugging your device into the computer and make sure the AppleUSBFTDI driver doesn't already support your device.

If you don't see the FTDI serial device, there's still another step to try with the native OSX drivers. Try these steps, then attempt to connect:

sudo kextunload -p -b com.apple.driver.AppleUSBFTDI
sudo kextutil -b com.apple.driver.AppleUSBFTDI -p AppleUSBEFTDI-6010-1

If you see the FTDI serial device, stop reading!

Download the FTDI Drivers

If your device didn't work with the native FTDI driver, you will want to try the "official" FTDI drivers. [Download them for your machine here.][2]

Once installed, check your device again and see if it connects.

If you see the FTDI serial device, stop reading!

Unload the FTDI Driver and Reload Apple

When swapping between devices, you may have problems when using the FTDI kext, but not the Apple kext. The FTDI kext is often preferentially loaded over the Apple version.

You might need unload the FTDI kext and reload the Apple FTDI kext before your device works:

$ sudo kextunload /System/Library/Extensions/FTDIUSBSerialDriver.kext/
$ sudo kextload -b com.apple.driver.AppleUSBFTDI

Kext Modification

Find your PID/VID

At this point, it is likely that your FTDI device has a PID/VID combination that isn't listed in the FTDI kext. My TUMPA falls into this boat.

Connect your device, and issue the following command in the shell:

$ system_profiler SPUSBDataType

This command will print information for all USB devices connected to your computer. Look for your FTDI device entry:

TIAO USB Multi-Protocol Adapter:
    Product ID: 0x8a98
    Vendor ID: 0x0403  (Future Technology Devices International Limited)
    Version: 7.00
    Serial Number: TIM01416
    Speed: Up to 480 Mb/sec
    Manufacturer: TIAO
    Location ID: 0x14100000 / 5
    Current Available (mA): 500
    Current Required (mA): 450
    Extra Operating Current (mA): 0

Note down the Product ID and Vendor ID, and convert those numbers to decimal.

Modifying the FTDI kext

First, make a copy of the FTDI Info.plist so you have a backup:

$ sudo cp /System/Library/Extensions/FTDIUSBSerialDriver.kext/Contents/Info.plist /System/Library/Extensions/FTDIUSBSerialDriver.kext/Contents/Info.plist.orig

Open the FTDI kext Info.plist file in your favorite text editor, located at /System/Library/Extensions/FTDIUSBSerialDriver.kext/Contents/Info.plist

You will need to add a new device entry with the PID/VID for your product supplied. Copy one of the device entries, supply a new name corresponding to your device, and modify the VID/PID to match your product.

Here's an example for my TUMPA:

<key>TIAO USB Multi-protocol Adapter</key>
<key>TIAO USB Multi-protocol Adapter</key>

I have two entries here because my device has two FTDI interfaces. Whether you have one or two interfaces depends on your part - do some digging :)

Disabling SIP

Modern OSX enables "System Integrity Protection" by default, which will prevent our modified FTDI driver from loading since the signature no longer matches the driver contents. You will need to disable SIP to use the modified driver on your system.

  • Boot to Recovery OS by restarting your machine and holding down the Command and R keys at startup.
  • Launch Terminal from the Utilities menu.
  • Enter the following command to disable SIP:
    $ csrutil disable
  • Reboot your computer

If you want to enable SIP again, simply follow the steps and issue the following command:

$ csrutil enable

Loading/Unloading the Driver

After rebooting your system, you should be good to go. However, if you have already disabled SIP and are making modifications to the driver, you can manually load/unload in the shell:

$ sudo kextunload /System/Library/Extensions/FTDIUSBSerialDriver.kext/
$ sudo kextload /System/Library/Extensions/FTDIUSBSerialDriver.kext/

Further Reading

Change Log

  • 20181219:
    • Improved debug notes
    • Links open in external tabs
    • Added another link to Further Reading section


JTAG and wfi do not place nicely together. You've probably noticed this yourself, wondering why JTAG can't connect or a halt/breakpoint doesn't work.

When the ARM core is executing the wait for interrupt operation, the core is placed into a low power mode and the core clock is gated. This wreaks havoc with JTAG, as the core clock is required to detect the JTAG clock transitions.

The simplest way to keep your debugging sanity is to provide hooks to disable wfi when JTAG is needed. One option is to use a #define to control whether your idle loop performs wfi or spins the processor. In quick pseudo-code:


However, once you need to debug returned units, reliability units, or factory failures it's not always feasible to reflash a unit. A more complicated implementation is to incorporate an NVRAM library and set a software flag (more on that in the future). On boot, the software checks the flag and uses the correct idle loop. If you then need to debug a device but can't re-flash it, simply set the NVRAM flag, reboot, et voila!

Note that this strategy will have an effect on timing and power consumption, so it will not be the holy grail for all cases. But it will certainly make your life easier if you're running into the wfi wall.

Debugging Strategy: Finding Version from a Memory Dump

Have you ever had a device that's in a weird state, and you're curious what version of software is on it so you can load the correct debug symbols? Here's a strategy for figuring that out:

  • Connect to device over JTAG when it's in the desired state
  • Use your JTAG tool to dump the contents of memory into a binary file on your host
    • Example using openocd:
      • dump_image sram.bin 0x300000 0x20000
    • You will need to know where in memory your binary gets loaded, as well as the size of the binary
  • Run strings on the downloaded binary file. You will need to look for something representative for your version string.
    • For example, "buildbot" is the jenkins machine that builds nightly images for my current project.
    • strings sram.bin | grep buildbot
      master 0.1.10 Wed Sep 21 03:10:25 PDT 2016 buildbot@company.io
  • Once you know the version of software you have, you can grab the debug symbols for that build and continue on your merry way.

Happy hunting!