pyGestalt

Logo

A control system framework for personal automation.

View the Project on GitHub imnp/pygestalt

The Standard Gestalt Makefile

Makefiles are necessary in order to compile firmware into a .hex file that can be loaded onto the physical node’s microcontroller. Makefiles are essentially a recipe instructing the compiler how to build a .hex file from an input C++ file.

We have created a “standard” makefile that can be used to compile your Gestalt code. Because makefiles are inherently confusing, we’ll step you thru our standard makefile here.

Key Parameters

The makefile is divided into roughly three sections. The first is where you will define a bunch of parameters that control how your code is compiled.

This is where you provide the name of your node’s main C++ file. Leave off the extension; we assume it ends in .cpp:

PROJECT = projectName

Defines the microcontroller type. This is needed by the AVR-GCC compiler in order to map register definitions correctly. A list of options is avaliable on the AVR-GCC website:

MCU = atmega328p

The clock frequency, in Hz. This is required for time-based macros like _delay_us() to accurately function:

FREQ = 18432000	

The starting memory address of the compiled code. Use the above if you are compiling a standard node application:

ADDRESS = 0x0000

Or, use the below INSTEAD if you are compiling a bootloader. This is valid for the Atmega 328 and 324. If you are compiling for a microcontroller with a different sized memory (e.g. the Atmega 168), you’ll need to check the correct starting memory address for the bootloader section:

ADDRESS = 0x7000

Here we are defining a bunch of flags that alter the functionality of the code by affecting which lines are compiled:

GESTALT_DEFS = -DstandardGestalt -DnetworkedGestalt -Dgestalt328

The following flags are supported by the Gestalt firmware library:

The makefile includes all of the following options. You should comment out all except the one you want, or modify to taste:

#  -> Use for a networked Gestalt node application
GESTALT_DEFS = -DstandardGestalt -DnetworkedGestalt -Dgestalt328

#  -> Use below for a networked Gestalt node bootloader
GESTALT_DEFS = -DstandardGestalt -Dbootloader -DnetworkedGestalt -Dgestalt328

#  -> Use below for a non-networked Gestalt node application
GESTALT_DEFS = -DstandardGestalt -Dgestalt328

#  -> Use below for a non-networked Gestalt node bootloader
GESTALT_DEFS = -DstandardGestalt -Dbootloader -Dgestalt328

Lastly, we’ll tell the compiler where it can find the Gestalt firmware library (gestalt.cpp and gestalt.h). You should change this to match where you’ve installed (or symlinked) the Gestalt library.

GESTALT_DIR = users/imoyer/gsArduino

Collate Build Option Strings

Here the makefile is just taking the options above and putting them into the format needed by the compiler and linker.

This builds up the absolute path of the Gestalt library:

GESTALT_FILE = $(GESTALT_DIR)/gestalt.cpp

Tells the linker where the code section starts:

LDSECTION = --section-start=.text=$(ADDRESS)

Builds a list of the primary source files needed to compile:

SOURCES = $(PROJECT).cpp $(GESTALT_FILE)

Collates all compiler flags:

CFLAGS = -g -Wall -Os -mmcu=$(MCU) -DF_CPU=$(FREQ) -I$(GESTALT_DIR) $(GESTALT_DEFS)

Collates all linker flags:

LDFLAGS = -Wl,$(LDSECTION)

Default Behavior When Calling Make

The following line builds the project and then deletes all intermediate files. This ideally would be in the next section after all of the avr-g++ calls, but for whatever reason this causes the compilation process to stop prematurely:

all: $(PROJECT).hex clean

This is the default behavior, and can be evoked simply by running make.

>> make

Internal Build Process

Builds an object file from the source code:

$(PROJECT).o: $(SOURCES)
	avr-g++ $(CFLAGS) -c -Wall $(SOURCES)

Builds an executable and linkable format (ELF) file from the object file:

$(PROJECT).elf: $(PROJECT).o
	avr-g++ $(CFLAGS) $(LDFLAGS) gestalt.o -o $@ $^

Converts the ELF file into a hex file, and display resource requirements:

$(PROJECT).hex: $(PROJECT).elf
	avr-objcopy -j .text -j .data -O ihex $< $@
	avr-size -C --mcu=$(MCU) $(PROJECT).elf

Additional Command Line Options

The following additional lines in the makefile define options you can invoke from the terminal. Each is presented first as the makefile line, and then the corresponding terminal command.

Deletes all intermediate files created in the build process:

clean:
	rm -rf *.o *.elf

In the terminal:

>> make clean

Deletes ALL files created in the build process. This is typically used in conjuncture with a programmer:

clean-all:
	rm -rf *.o *.elf $(PROJECT).hex

In the terminal:

>> make clean-all

The following builds the code and then programs the target microcontroller using the Universal Personality Programmer. You can alternatively replace the line with the terminal command for avrdude, etc…

flash:
	python UPPloader.py $(PROJECT).hex

In the terminal:

>> make flash

This will build the code, program the microcontroller, and then delete all of the built files:

load: $(PROJECT).hex flash clean

In the terminal:

>> make load

It is worth noting that typically we only use this command when flashing a Gestalt bootloader onto a fresh microcontroller. Application code can be more easily loaded onto the MCU via the virtual node bootloader functions.