AVR-GCC. FreeRTOS.

Πολύ πρόσφατα έριξα μία ματιά στο FreeRTOS για AVR-GCC. Το FreeRTOS είναι είναι ένας ανοικτού κώδικα πυρήνας πραγματικού χρόνου για μικροελεγκτές. Δεν θα επεκταθώ στο τι είναι ένα λειτουργικό σύστημα πραγματικού χρόνου και που μας βοηθά. Ήθελα ένα πολύ απλό λειτουργικό παράδειγμα με FreeRTOS σε κάποιον AVR ώστε να μπορέσω να κάνω δοκιμές και να μάθω λίγα πράγματα παραπάνω. Ο μικροελεγκτής που επέλεξα είναι ο ATmega168. Βασικά ο πρώτος που βρήκα στο συρτάρι μου και είχε “κάμποση” μνήμη Flash.

Άρθρο της Wikipedia για RTOS.
FreeRTOS.
Τεκμηρίωση του ATmega168

Το πρόγραμμα είναι πολύ απλό. Απλά δημιουργεί δύο διεργασίες που η κάθε μία αναβοσβήνει ένα LED που είναι συνδεδεμένο στον ATmega168.

Τα αρχεία του προγράμματος.

#include <avr/io.h>
#include <util/delay.h>


/*Η παρακάτω δήλωση ελέγχει αν στον compiler έχουμε βάλει την παράμετρο F_CPU.
  Αν όχι, την περνά. */

#ifndef F_CPU
    #warning "H F_CPU den exei oristei 8a parei thn timh 8000000"
    #define F_CPU 8000000UL  //  Use unsigned long
#endif

/* Scheduler include files. */
#include "FreeRTOS.h"
#include "task.h"
#include "croutine.h"

void vLEDInit1(void);
void vLEDToggle1(void);
static void vLEDTask1(void* pvParameters);

void vLEDInit2(void);
void vLEDToggle2(void);
static void vLEDTask2(void* pvParameters);

int main(void){

    // Δημιουργία τον διεργασιών.
    xTaskCreate ( vLEDTask1, (signed char *) "LED", configMINIMAL_STACK_SIZE, NULL , 1, NULL);
    xTaskCreate ( vLEDTask2, (signed char *) "LED", configMINIMAL_STACK_SIZE, NULL ,1, NULL);


    // Εκκίνηση του scheduler.
	vTaskStartScheduler();

	/* Σε αυτό το σημείο υπό κανονικές
	   συνθήκες το πρόγραμμά μας δεν
	   θα φτάσει ποτέ. */

    while(1){

    };

    return 0;
}


static void vLEDTask1(void* pvParameters){

    // Ενημέρωση του LED κάθε ~250 msec.
    const uint16_t blinkDelay = 250 ;

    // Αρχικοποίηση του LED.
    vLEDInit1();


     // Ατέρμον βρόχος.
     while (1){

         // Μπλοκάρισμα της διεργασίας για χρόνο blinkDelay.
         vTaskDelay(blinkDelay);

		 vLEDToggle1();

         // Μπλοκάρισμα της διεργασίας για χρόνο blinkDelay.
         vTaskDelay(blinkDelay);

    }
}

static void vLEDTask2(void* pvParameters){

    // Ενημέρωση του LED κάθε ~500 msec.
    const uint16_t blinkDelay = 500;

    // Αρχικοποίηση του LED.
    vLEDInit2();


     // Ατέρμον βρόχος.
     while (1){

         // Μπλοκάρισμα της διεργασίας για χρόνο blinkDelay.
         vTaskDelay(blinkDelay);

		 vLEDToggle2();

         // Μπλοκάρισμα της διεργασίας για χρόνο blinkDelay.
         vTaskDelay(blinkDelay);

    }
}

void vLEDInit1(void){

    // PB0 ως έξοδος.
    DDRB |= (1<<PB0);

}

void vLEDInit2(void){

    // PB1 ως έξοδος.
    DDRB |= (1<<PB1);
}

void vLEDToggle1(void){

   // Εναλλαγή του LED.
   PORTB ^= (1<<PB0);
}

void vLEDToggle2(void){

   // Εναλλαγή του LED.
   PORTB ^= (1<<PB1);
}
Advertisements
This entry was posted in AVR, Electronics and tagged , , , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s