Using the ICD-U40 with linux

update: I modified the script to allow a filename to be passed to it for immediate flashing.

The ICD-U40 is an in-circuit programmer for Microchip PIC processors, and the company that makes it,CCS, was nice enough to provide linux drivers for the beast. However, there doesn’t seem to be any documentation on the product. Here are the steps that I took to get it working on my system (Ubuntu Feisty Fawn x86_64):

1. First download the driver from the manufacturers website and extract the files to a temporary location:

2. Plug in the device and note which port it shows up on:

~$ dmesg
[276383.429792] usb 5-4.3: new full speed USB device using ehci_hcd and address 22
[276383.472990] usb 5-4.3: configuration #1 chosen from 1 choice
[276383.473075] ftdi_sio 5-4.3:1.0: FTDI USB Serial Device converter detected
[276383.473080] drivers/usb/serial/ftdi_sio.c: Detected FT8U232AM
[276383.473179] usb 5-4.3: FTDI USB Serial Device converter now attached to ttyUSB0

For me, it shows up as ttyUSB0. If the device is not recognized, you will need to add the ftdi module to your kernel.

3. Clobber an unused serial terminal, and symlink it to the one that the device uses:
The program is apparently hardwired to only use the serial ports ttyS0 – ttyS7. To get the program to recognize the device, one of these serial ports will have to be symlinked to the actual device (determined in step 2). There is an elegant solution on the ccs website, however an easy hack is to just make the link manually (note that this will have to be performed each time the device is removed/plugged back in):

~$ cd /dev
/dev$ sudo rm ttyS3
/dev$ sudo ln -s ttyUSB0 ttyS3
/dev$ ls -l ttyS3
lrwxrwxrwx 1 root root 7 2007-09-26 23:20 ttyS3 -> ttyUSB0

4. Get a better launcher script :
The launcher script (icd_linux) is fairly simple and assumes that the program will be installed in a single users directory, and that a file named Tex3.hex will be flashed. Here is a slightly nicer one that allows the program to be installed in a central location (say, /usr/local/icd-linux), while storing the configuration files in the users home directory (do this in the temporary directory where the files were extracted to in step 1):

~/temp/icd-linux$ wget -O icd-linux
~/temp/icd-linux$ chmod 755 icd-linux

note: In case this file is no longer available, I have placed the contents of this script at the end of this post.

5. Copy the files to the /usr/local directory (do this in the temporary directory where the files were extracted to in step 1):

~/temp/icd-linux$ sudo mkdir /usr/local/icd-linux
~/temp/icd-linux$ sudo cp -R ./ /usr/local/icd-linux
~/temp/icd-linux$ sudo ln -s  /usr/local/icd-linux/icd-linux /usr/local/bin/icd-linux

6. Run the program
Assuming that /usr/local/bin is in your path, you should be able to run the program at any time now using the command icd-linux. Settings will be saved in the directory .icd-linux, which should be placed in your home directory. To remove the program, simply delete the /usr/local/icd-linux directory and the icd-linux symlink in the /usr/local/bin directory.

Appendix: icd-linux script for step 4:


# Set these to correspond to whatever is most appropriate for you

# If an argument was passed, assume it is a filename.  Expand the path to
# an absolute path (so the icd will be able to find it), and add it to the
# argument list.
if [ "$#" -eq 1 ]; then
    if [ -f $1 ]; then
        DIRNAME=`dirname $1`
        FULLDIRNAME=`cd $DIRNAME; pwd`
        FILENAME=`basename $1`

# Create the config directory and walk to there so that the program stores
# he config and log files locally
if [ ! -d $SETTINGS_PATH ]; then
    mkdir $SETTINGS_PATH

    if [ ! -d $SETTINGS_PATH ]; then
        echo Error creating settings directory: $SETTINGS_PATH
        echo Please create this directory manually and then re-run the script.


# change the LD_LIBRARY_PATH so that it can find its libraries

# symlink the files it needs into the config directory
rm -f $SETTINGS_PATH/icd $SETTINGS_PATH/devices.dat $SETTINGS_PATH/spbu.bmp
ln -s $INSTALLED_PATH/devices.dat $SETTINGS_PATH/devices.dat
ln -s $INSTALLED_PATH/spbu.bmp $SETTINGS_PATH/spbu.bmp

if [ -e ./icd -a -e ./devices.dat -a -e ./spbu.bmp ]; then 
    ./icd $ARGS
    echo Error copying files, please make sure that icd-linux is installed
    echo in the directory: $INSTALLED_PATH.

# then clean up the linked files
rm -f $SETTINGS_PATH/icd $SETTINGS_PATH/devices.dat $SETTINGS_PATH/spbu.bmp
This entry was posted in tech. Bookmark the permalink.

4 Responses to Using the ICD-U40 with linux

  1. Carl says:

    Thanks for posting that. I was using a much simpler loader but it had the extra feature of passing any arguments on to the main program so I could just run “icd-linux -Tmyfile.hex” and bypass the GUI file selector. It wasn’t ideal because I had to type in the full path to the hex file, never managed to fix that.

    I have an ICD2 from Microchip and an ICD-U40 from CCS but right now neither of them work :-( When using the ICD-U40 the CPU usage goes straight to 100% and the app just hangs. I have the correct symlinks, RW permissions on the device, and the kernel detects the ICD correctly. I’m sure the loader was at least detecting the ICD last week but something must have changed. I always get this problem when moving to a different computer but the same solution never works twice.


  2. mahto says:

    Hi Carl- I like the idea of being able to pass a filename to the script for immediate flashing; i have updated my script to allow this. Unfortunately, it doesn’t seem to work with files that have spaces in their names. I’m not sure how to handle that except maybe to have it copy the target file over to a temporary directory, but i think this is good enough for me. Note that you don’t need to specify -T, just the filename will work.

    I’ve seen a little bit of weirdness with FTDI-based serial devices in Linux, but I haven’t been able to pinpoint it to anything specific. One thing that was definitely a problem was when I was using an older laptop with a number of usb devices and the laptop was not able to supply enough power- things would randomly stop working, or work intermittently. I don’t know if that helps in your case though.

  3. Adam says:


    I have been messing around with the icd-linux for a while now, thanks to your page. I am not sure if you are still working with the software but I found something that you didn’t mention here. If you just use the icd program and not the icd-linux program a new / different window comes up, allowing you to update firmware test comports and some other things, I get it to run with the command $icd_install_directory/icd ./ext2.hex

  4. mahto says:

    Hi Adam,
    I think you get the same window if you run icd-linux without any options. That’s actually how I use it- that way the window stays open all the time, and I can just click on the little arrow button next to ‘download to target’ to download again, because it remembers the last program that was flashed.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>