Tag Archives: tiny program

Programming in the Small – Part #5

Bringing it all together!

So, now that we know what all the extra stuff is- and we know that we don’t need it- let’s get rid of it!

Here is the final program..

/*
 * TinyestProject.c
 *
 * Created: 11/11/2013 2:21:26 PM
 *  Author: josh
 */

// This tiny program it will toggle bit A0 at 1 mhz
// It is a very short program, using only 6 bytes total

// Note that for this to really compile down to 6 bytes,
// you need to give the option -nostartfiles to the linker

#include <avr/io.h>

// The "section" attribute tells the linker to put our
// function at the very start of program memory where the
// vectors typically go. The location of the "vectors"
// section is set inside the linker script.

void start (void)  __attribute__ ((section (".vectors")));

void start(void)
{

	DDRA |= 0x01;

	while(1) {
		PINA |=0x01;
	}

}

It does not look very different from the original program.

First, we’ve added the line…

void start (void) __attribute__ ((section (".vectors")));

This tells the compiler to tell the linker to put our code at the very start of program memory at location 0. Now the first byte of our program is sitting right where the Reset vector would normally go, so our program will start running as soon as the chip powers up. We will be running “bare metal”.

The next change is just as important, but not part of the code. We must tell the compiler not to include all the various start-up stuff that it normally does include. We do this with the -nostartfiles option. In AVR Studio, you can set that in the Project Options here…

nostartfiles

Keep in mind that even though the changes we made to the code were very small, it took a long way to get here. If you just make these changes without understanding each thing we got rid of, you can get into trouble fast. If we decided to expand this tiny program and tried to add an interrupt to it, things would fail hard when the chip jumped into the non-existent interrupt entry in the vector table.  If we did something as small as adding a statically initialized global variable, it would not work because we are not running the normal C start-up code that does the initialization.  Heck, we would not get far trying to write any real program without the code that normally zeros out R1 since lots of compiled C code takes that for granted.

So was this just a silly exercise? No. The production Ognite code very carefully works around all these issues while at the same staying significantly smaller than if it used the normal C start-up stuff. 

Is the space saved worth it? Maybe not for most programs but if you are designing a product that you expect to make 1,000,000 copies of, then using these techniques may let you fit into the next size smaller chip which could have a huge total impact.