Nut/OS LED Tutorial
We will now start with our first application. It will initialize the port bit and then switch on and off the LED in an endless loop.
ATmega Ports
Almost all digital ports of the ATmega128 can be individually configured for input or output. Three registers are used to control or monitor each port.
-
Port register
When the port is configured for output, we can clear each bit to drive the corresponding output low or set the bit to drive it high. -
Pin register
When the port is configured for input, then each bit reflects the status at the corresponding input pin. The bit is zero, when the input is low or set if the input is driven high. -
Data direction register
This register is used to configure the mode of each port pin. When the bit is set, then the port pin works in output mode.
Initialization
Standard C does not provide functions to access port registers. But the AVR library, that comes with your compiler, offers such capabilities. Almost all AVR compilers allow to handle ports like predefined variables. To set bit 2 of data direction register of Port E, we can write
DDRE |= 0x04;
DDRE |= _BV(2);
However, using predefined variables to access port registers makes the code less portable. With Nut/OS we prefer to use macros instead. To set bit 2 of the data direction register, we use
sbi(DDRE, 2);
cbi(DDRE, 2);
Blinking LED
Setting and clearing the output pin can be done in a similar way:
for { cbi(PORTE, 2); sbi(PORTE, 2); }
Building the Application Code
You should have created a sample application directory by following the Ethernut Software Manual. Within this directory create a new subdirectory named led01. Within this directory create a new C source file name led01.c and put in the following contents.
/* * This header contains the Nut/OS timer function * prototypes. We need it for calling NutSleep. */ #include <sys/timer.h> /* * Ethernut LED example #1. */ int main(void) { /* * Configure port E bit 2 as an output. */ sbi(DDRE, 2); /* * An endless loop. */ for (;;) { /* * Set port E bit 2 to low. This will lit the LED. */ cbi(PORTE, 2); /* * Sleep 1000 milliseconds. */ NutSleep(1000); /* * Setting port E bit 2 to high switches off the LED. */ sbi(PORTE, 2); /* * Sleep for another 1000 milliseconds. */ NutSleep(1000); } }
If you're using the ImageCraft IDE, then you will probably create a project. Again, check the Ethernut Software Manual for specific project settings.
For the GCC compiler we need to create a file name Makefile in the same directory, which contains:
PROJ = led01 include ../Makedefs SRCS = $(PROJ).c OBJS = $(SRCS:.c=.o) LIBS = $(LIBDIR)/nutinit.o -lnutos -lnutdev $(ADDLIBS) TARG = $(PROJ).hex all: $(OBJS) $(TARG) include ../Makerules
SET PATH=C:\ethernut\nut\tools\win32;C:\WinAVR\bin;C:\WinAVR\utils\bin;%PATH%
make
avr-gcc -c -mmcu=atmega128 -Os -fno-delete-null-pointer-checks -Wall -Wstrict-prototypes -Wa,-ahlms=led01.lst -D__HARVARD_ARCH__ -DETHERNUT2 -IC:/ethernut-3.9.8/nutbld-21b/include -IC:/ethernut-3.9.8/nut/include led01.c -o led01.o avr-gcc led01.o -mmcu=atmega128 -Wl,--defsym=main=0,-Map=led01.map,--cref -LC:/ethernut-3.9.8/nutbld-21b/lib C:/ethernut-3.9.8/nutbld-21b/lib/nutinit.o -lnutos -lnutdev -o led01.elf avr-objcopy -R .eeprom -O ihex led01.elf led01.hex rm led01.elf
As a result you'll find several new files in your application directory. The most important one is led01.hex, which contains the code to be transfered to the Ethernut Board in Intel Hex Format.
Building the Application Code
It's time to attach the programmer and power up your Ethernut.
The ImageCraft compiler offers an integrated programming tool. With GCC you can use
make burn
uisp -dprog=stk500 -dserial=/dev/ttyS0 -dspeed=115200 -dpart=atmega128 --erase --upload if=led01.hex Firmware Version: 49.48 Atmel AVR ATmega128 is found. Uploading: flash
If everything worked well, your LED should start blinking.