Vim as C IDE

VIM setup

I you, like me, like a minimal, yet flexible editor to do most of your programming work in; there is a good chance that Vim is the right tool/editor for you. I have been developing software for embedded devices for a while, and my experience is that many code editors out there are either proprietary, single platform, bloated beyond belief or just a pain in the ass to use (sometimes all four). Putting a little effort in configuring Vim to meet your software programming needs is time well spent, and chances are that you will be using this tool for all your code writing projects ..and more.

In this small guide i will be configuring Vim as a C IDE, targeting the Atmega328 micro controller unit (that black squared thingy on the Arduino board).

I will be installing the following Vim plugins: tagbar, youcompleteme, ultisnips In order to compile C code for the Atmega328 i will also be installing avr-gcc and avrdude (to flash binaries to mcu)

I am using vimplug as plugin manager, so adding the aforementioned plugins to Vim is a breeze. First edit your vimrc file and add the plugins as shown below.

  call plug#begin('~/.vimplugged')
  Plug 'SirVer/ultisnips' | Plug 'honza/vim-snippets'
  Plug 'majutsushi/tagbar'
  Plug 'valloric/youcompleteme'
  call plug#end()

After you have edited (and saved) the vimrc (in vim), you reload the vimrc file by typing :so $MYVIMRC . Then :PlugInstall to install plugins.

Install

To install gcc-avr, avr-libc and avrdude

sudo apt-get install gcc-avr avr-libc avrdude

(gdb-avr and simavr later)

Tagbar

Tagbar will display a neetly ordered list of constants, functions and variables for the current file. Use Tagbar to get an overview of your file, and to navigate within the file. You can toggle the Tagbar window(buffer) with F8.

UltiSnips

To setup the keys for ultisnips edit your vimrc and add the following:

let g:UltiSnipsExpandTrigger="<tab>"
let g:UltiSnipsJumpForwardTrigger="<c-j>"
let g:UltiSnipsJumpBackwardTrigger="<c-k>"

save, and reload vimrc as previously described.

YouCompleteMe

Makefile

TARGET = main
#=== Directories ==============================================================
SRC = src
INC = inc
#==============================================================================
DEVICE=atmega328p
CLOCK=16000000UL
#==============================================================================
CFLAGS = -Os -DF_CPU=$(CLOCK) -mmcu=$(DEVICE) -Wall -I $(INC)/
#==============================================================================
CC = avr-gcc
OBJDUMP = avr-objdump
OBJCOPY = avr-objcopy
AR = avr-ar
SIZE = avr-size
NM = avr-nm
MKDIR = mkdir -p
RM = rm -rf
#==============================================================================
MCU = atmega328p
PORT = /dev/ttyACM0
BAUD_RATE = 115200
PROGRAMMER = arduino
AVRDUDE=avrdude 
#==============================================================================
SOURCES= $(wildcard $(SRC)/*.c)
OBJECTS= $(patsubst %.c, %.o, $(SOURCES))
$(info SOURCES are $(SOURCES))
$(info OBJECTS are $(OBJECTS))
#=== RULES ====================================================================
# get file dependencies then build hex
all: Makefile.deps $(TARGET).hex

# include object dependencies
-include Makefile.deps

$(TARGET).elf: $(OBJECTS)
	$(CC) -mmcu=$(DEVICE) -o $@ $^

$(TARGET).hex: $(TARGET).elf
	$(OBJCOPY) -O ihex $< $@

# Genere Object dependencies
Makefile.deps: $(SOURCES)
	$(CC) $(CFLAGS) -MM $^ > Makefile.deps

#==== HELPERS =================================================================
.PHONY: install clean show_fuses
#Flash to MCU
install: ${TARGET}.hex
	${AVRDUDE} -v -c $(PROGRAMMER) -p $(MCU) -P ${PORT} -b ${BAUD_RATE} -D -U flash:w:$<

# Removing build files
clean:
	${RM} src/*.o ${TARGET}.elf ${TARGET}.hex Makefile.deps

show_fuses:
	${AVRDUDE} -nv