Integrating Radiotftp_process to Your Contiki-Os Applications

You are running a Contiki-Os application and want to relay some data over a VHF/UHF link? Follow through this guide and you should be able to set up a radiotftp link without trouble.

If you are eager not to wait you can start by checking out the repository and example fibonacci application in here. When you are ready, we will first explain the structure of the example fibonacci application and later on we will tell how to import Radiotftp_process into your application by copying the necessary sources from the Radiotftp_process repository.

Before you start:

  • You need an environment where you can compile Contiki applications. The easiest way to get your hands onto such environment is to download instant Contiki from Contiki website.
  • It’s not a must but it’s better if you understand the basics of embedded C programming. It makes easier to understand the concepts.
  • Except above, it’s also better if you know about the basics of Contiki-Os programming. It’s still C programming but Contiki-Os has its tweaks and nice features to know about.

The Fibonnacci Application

The fibonacci application is a sample Contiki application which consists of a single thread which periodically computes the next number in the Fibonacci sequence. After the computation the fibonacci process calls the radiotftp_process to send the data through radio.

  • Let’s start by cloning the radiotftp_process to our home directory from github. And cd into the radiotftp_process directory.
cd ~
git clone https://github.com/alpsayin/radiotftp_process.git
cd radiotftp_process
  • Then open the fibonacci.c file with an editor. On line 21 you’ll see that we define the process prototype for the fibonacci process which is “measurement_process”, and we also give it a string identifier “Measurement Process”. The string identifier is sometimes useful to find a process by its name, but we are not going to use it.
21
PROCESS(measurement_process, "Measurement Process");
  • On line 22 you’ll see that we define the auto-started processes. These processes are only defined once in the whole project, defining twice could cause unpredictable problems. Since we want the measurement_process to started automatically, we define that. And also as a requirement to use the radiotftp_process, it MUST be always auto-started.
22
AUTOSTART_PROCESSES(&measurement_process, &radiotftp_process);
  • On line 24 we start defining the actual measurement_process. “ev” is the variable name for the event that caused the process to start. And “data” is the variable name for the pointer that points to the data that was passed in when the process is started.
24
PROCESS_THREAD(measurement_process, ev, data)
  • As a rule of Contiki processes, before starting the process we define all variable that we are going to use. We define these variables as static so they keep their value even if the process exits and/or restarted. These variables are
    • counter: A simple integer to keep the fibonacci sequence index
    • numBytes: An integer to keep the number of bytes in our string buffer
    • fibo: An integer array to keep the last three computed values of the fibonacci sequence. We initialize it to the first three elements of the sequence manually.
    • measurement_timer: A Contiki etimer struct to fire periodic events. These structs are like posix alarms. They have to be set-up each time they’re burned.
    • fake_measurement_string: A string buffer to fill in with fake measurement data, in our case; the next number in fibonacci sequence.
26
27
28
29
30
static uint32_t counter=0;
static uint16_t numBytes=0;
static uint64_t fibo[3] = {0, 1, 1};
static struct etimer measurement_timer;
static uint8_t fake_measurement_string[450];
  • On line 31 we mark the execution start of the process. This is again a Contiki process rule.
31
PROCESS_BEGIN();
  • After that on line 33, the first and only thing we do is to set up the etimer that we have initialized before. We give the etimer a period of 2 seconds.
33
etimer_set(&measurement_timer, CLOCK_SECOND*2);
  • And after setting up our time on line 34 we enter an infinite loop. From now on this process will never exit the boundaries of this loop and it will always execute this loop whenever the measurement_process gets the CPU.
  • The first thing we do in our infinite loop is to wait for an event. This is a special event waiting call of Contiki. This call checks if the event is ready, and if the event is not ready it yields the CPU to other processes so they can get their share of CPU time. When the event is ready, measurement_process will continue from this line.
36
PROCESS_WAIT_EVENT();
  • When the etimer fires the event that we were waiting for after 2 seconds, Contiki-Os gives the CPU to measurement_process again, and measurement_process continues execution from line 37.
  • Between lines 37 and 43, Fibonacci logic is applied and fake_measurement_string is filled in.
37
38
39
40
41
42
43
counter++;
fibo[2]=fibo[1]+fibo[0];
numBytes=sprintf(fake_measurement_string, "Some Data: fibonacci(%d)=", counter);
numBytes+=sprintf(fake_measurement_string+numBytes, "%u [Alp Sayin, KTH Royal Institute of Technology]n", fibo[0]);
printf("%s", fake_measurement_string);
fibo[0]=fibo[1];
fibo[1]=fibo[2];
  • The magic starts at line 44. To use the radiotftp_process, we first set the number of bytes to be sent by calling a function of the radiotftp_process library. This is a very important step, without this step radiotftp_process cannot know how many bytes to send. Also, radiotftp_process uses an internal counter to send the string buffer, when sending is complete internal counter is set to 0. This call sets the internal counter back to a non-zero number.
44
radiotftp_setNumBytesToSend(numBytes);
  • After that we ‘post’ the radiotftp_process with a COM event. Radiotftp_process doesn’t actually care about what kind of event it gets, but it’s good practice to use COM event. We also pass a pointer to fake_measurement_string so that radiotftp_process can use the data inside.
45
process_post_synch(&radiotftp_process, PROCESS_EVENT_COM, (void*)fake_measurement_string);
  • One important point here is that radiotftp_process DOES NOT copy the data inside the buffer, it simply reads and sends it out. So it is up to the programmer to make sure that the data buffer is not modified during transmission.
    • If you are using single block transmissions without acknowledgements the string buffer will be ready for modifications right after the radiotftp_process executes once. So it’s not really easy to tell when, but an approximate wait time can be calculated by using the formula below. The maximum packet load can be 144 bytes, with that maximum wait time should be about 1.5 seconds. Slow, right? This is what happens when you try to send 160 bytes with 2400 baud with manchester encoding (effective baud rate becomes 1200).
    • But if you have enabled acknowledgements, you can simply use the tftp_getStatus() function defined in tftp.h. It returns either TFTP_STATUS_IDLE, TFTP_STATUS_SENDING or TFTP_STATUS_RECEIVING which are also defined in tftp.h.
time = (buffer_length+16)*2*11/2400
  • Anyhow, we only compute a value every 10 seconds, so that’s not a problem for us right now. And finally in our loop, we set-up the etimer again to fire another event which will activate the measurement_process again. But this time we use 10*CLOCK_SECOND to have it fired after 10 seconds.
46
etimer_set(&measurement_timer, CLOCK_SECOND*10);
  • When the event is fired again the whole loop is repeated. And that’s all! It’s actually very simple.

Integrating radiotftp sources to your application:

  • First of all let’s assume that you have a contiki-os application in a directory in your home folder called myApp. And let’s also assume that you have cloned radiotftp_process repository also to your home directory. What you first need to do is to copy the radiotftp_process sources from my repository into your application.
cp ~/radiotftp_process/avr_util.h ~/myApp/
cp ~/radiotftp_process/ax25.h ~/myApp/
cp ~/radiotftp_process/ax25.c ~/myApp/
cp ~/radiotftp_process/ethernet.h ~/myApp/
cp ~/radiotftp_process/ethernet.c ~/myApp/
cp ~/radiotftp_process/manchester.h ~/myApp/
cp ~/radiotftp_process/manchester.c ~/myApp/
cp ~/radiotftp_process/printAsciiHex.h ~/myApp/
cp ~/radiotftp_process/printAsciiHex.c ~/myApp/
cp ~/radiotftp_process/radiotftp.h ~/myApp/
cp ~/radiotftp_process/radiotftp_process.c ~/myApp/
cp ~/radiotftp_process/tftp.h ~/myApp/
cp ~/radiotftp_process/tftp.c ~/myApp/
cp ~/radiotftp_process/timers.h ~/myApp/
cp ~/radiotftp_process/timers.c ~/myApp/
cp ~/radiotftp_process/udp_ip.h ~/myApp/
cp ~/radiotftp_process/udp_ip.c ~/myApp/
cp ~/radiotftp_process/util.h ~/myApp/
cp ~/radiotftp_process/util.c ~/myApp/
  • Then you should create a Makefile. It is possible to compile Contiki-Os applications without a makefile, but if you have more than one source file. It is better to have a makefile. You can see my Makefile below or also in here.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
SRC=fibonacci
RADIOTFTP_SOURCEFILES=ax25.c ethernet.c manchester.c tftp.c timers.c udp_ip.c util.c printAsciiHex.c radiotftp_process.c
 
PROJECT_SOURCEFILES+=$(RADIOTFTP_SOURCEFILES)
 
TARGET=avr-atmega128rfa1
CONTIKI=/home/alpsayin/contiki
 
all: cleanExec $(SRC) $(SRC).lss $(SRC).hex $(SRC).eep $(SRC).size
 
include $(CONTIKI)/Makefile.include
 
cleanExec:
        rm -rf *.hex
        rm -rf *.eep
 
$(SRC).lss: $(SRC).$(TARGET)
        @echo 'Invoking: AVR Create Extended Listing'
        -avr-objdump -h -S $(SRC).$(TARGET)  >"$(SRC).lss"
        @echo 'Finished building: $@'
        @echo ' '
 
$(SRC).hex: $(SRC).$(TARGET)
        @echo 'Create Flash image (ihex format)'
        -avr-objcopy -R .eeprom -R .fuse -R .signature -O ihex $(SRC).$(TARGET)  "$(SRC).hex"
        @echo 'Finished building: $@'
        @echo ' '
 
$(SRC).eep: $(SRC).$(TARGET)
        @echo 'Create eeprom image (ihex format)'
        -avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" --no-change-warnings --change-section-lma .eeprom=0 -O ihex $(SRC).$(TARGET)  "$(SRC).eep"
        @echo 'Finished building: $@'
        @echo ' '
 
$(SRC).size: $(SRC).$(TARGET)
        @echo 'Invoking: Print Size'
        -avr-size --format=berkeley -t $(SRC).$(TARGET)
        @echo 'Finished building: $@'
        @echo ' '
 
install: all
        -avrdude -p m128rfa1 -c avrispmkII -P usb -U eeprom:w:$(SRC).eep
        -avrdude -p m128rfa1 -c avrispmkII -P usb -U flash:w:$(SRC).hex
  • The SRC variable here defines the main C file to be compiled. Its name is also used for creating targets (hex, eep etc.). In your application it should be the main C file that contains your application.
1
SRC=fibonacci
    • After that, your makefile MUST have the second line which defines the radiotftp sources. The header files are not defined because they are automatically searched by make.
2
RADIOTFTP_SOURCEFILES=ax25.c ethernet.c manchester.c tftp.c timers.c udp_ip.c util.c printAsciiHex.c radiotftp_process.c
    • The third line tells make to add the radiotftp_sources to the project sourcefiles. The PROJECT_SOURCEFILES variable is a variable used by the Contiki’s included makefiles. Without this line Contiki’s makefile will not compile the radiotftp sources.
4
PROJECT_SOURCEFILES+=$(RADIOTFTP_SOURCEFILES)
  • After that we define the target architecture. In our case we used AVR’s Atmega128Rfa1 microcontrollers with builtin IEEE 802.15.4 radios. So my target was avr-atmega128rfa. Note that, if your platform (microcontroller) is not supported by Contiki, don’t even try to compile. Contiki has platform codes for a wide range of microcontrollers and boards. These platform codes enable Contiki to do what it does. Every platform gets its name from your contiki installation’s platform folder. To find out if your microcontroller’s target name you should check the Contiki website, or you can try hacking into the contiki sources and finding a suitable platform that would work for you. Anyways, this manual is intended only for Atmega128Rfa1 microcontroller. But if you hack into Contiki you should be able to apply the guidelines here to any platform with several tweaks.
6
TARGET=avr-atmega128rfa1
  •  In the next line we define the Contiki installation folder. In my case it was installed into my home directory.
7
CONTIKI=/home/alpsayin/contiki
  • The next lines just tell the make how to build the application. You can copy them as is. Except for the install command. The install line defines very specific parameters such as the programmer software to use and the programmer hardware to use. If you are not using avrdude and AVR mkII programmer with a USB port you should modify it to your preference before trying to use it.
  • The two lines below flash the eeprom and the flash memory in Atmega128RFA1 with avrdude software and mkII programmer using a USB port.
41
42
43
install: all
        -avrdude -p m128rfa1 -c avrispmkII -P usb -U eeprom:w:$(SRC).eep
        -avrdude -p m128rfa1 -c avrispmkII -P usb -U flash:w:$(SRC).hex
    • After you set up your makefile, just try compiling with typing make all in your application directory. You should first see a huge flow of compilation process in your terminal screen. But towards end you should see lines like below.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
avr-gcc -mmcu=atmega128rfa1 -Wl,-Map=contiki-avr-atmega128rfa1.map -Wl,--section-start=.bootloader=0x1F800  fibonacci.co obj_avr-atmega128rfa1/ax25.o obj_avr-atmega128rfa1/ethernet.o obj_avr-atmega128rfa1/manchester.o obj_avr-atmega128rfa1/tftp.o obj_avr-atmega128rfa1/timers.o obj_avr-atmega128rfa1/udp_ip.o obj_avr-atmega128rfa1/util.o obj_avr-atmega128rfa1/printAsciiHex.o obj_avr-atmega128rfa1/radiotftp_process.o contiki-avr-atmega128rfa1.a  -o fibonacci.avr-atmega128rfa1
Invoking: AVR Create Extended Listing
avr-objdump -h -S fibonacci.avr-atmega128rfa1  >"fibonacci.lss"
Finished building: fibonacci.lss
 
Create Flash image (ihex format)
avr-objcopy -R .eeprom -R .fuse -R .signature -O ihex fibonacci.avr-atmega128rfa1  "fibonacci.hex"
Finished building: fibonacci.hex
 
Create eeprom image (ihex format)
avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" --no-change-warnings --change-section-lma .eeprom=0 -O ihex fibonacci.avr-atmega128rfa1  "fibonacci.eep"
Finished building: fibonacci.eep
 
Invoking: Print Size
avr-size --format=berkeley -t fibonacci.avr-atmega128rfa1
   text	   data	    bss	    dec	    hex	filename
  41319	   3590	   7687	  52596	   cd74	fibonacci.avr-atmega128rfa1
  41319	   3590	   7687	  52596	   cd74	(TOTALS)
Finished building: fibonacci.size
 
rm obj_avr-atmega128rfa1/ax25.o fibonacci.co obj_avr-atmega128rfa1/printAsciiHex.o obj_avr-atmega128rfa1/manchester.o obj_avr-atmega128rfa1/timers.o obj_avr-atmega128rfa1/tftp.o obj_avr-atmega128rfa1/radiotftp_process.o obj_avr-atmega128rfa1/ethernet.o obj_avr-atmega128rfa1/udp_ip.o obj_avr-atmega128rfa1/util.o
  • If you don’t get these lines, hopefully make will tell you what the problem is and you should be able to solve it. If not, try asking me below, maybe I can help 🙂

Finally; remember that there isn’t much documentation about this on the internet. So if you have a question, ask it below and I’ll try to answer. In such way we can build up a knowledge base.

2 thoughts on “Integrating Radiotftp_process to Your Contiki-Os Applications

  • December 11, 2014 at 3:45 pm
    Permalink

    Hello,

    I just started using contiki os. I am facing some problem in uploading a program in AVR’s Atmega128Rfa1. I am using JTAGIC3; can you please tell me what configuration should i use to upload a program using JTAGIC3?? I really appreciate your help!!.

  • April 23, 2015 at 4:38 am
    Permalink

    I am working on contiki os to develop an 6lowpan application using avr-atmega128rfa1p platform. I compiled and uploaded rpl-border router code in one avr-atmega128rfa1. I want another progam that is compatible with avr-atmega128rfa1 for end device. Help me to find a code in the contiki that can be used as end device.

Comments are closed.