Instrukcja dla bili lab5

Instrukcja dla debili Lab5

Opracował: Maciej CZERWIŃSKI

Celem tej instrukcji jest pozwolić Ci zaliczyć na spokojnie przedmiot AKiSO. Są to już ostatnie zajęcia jakie będziemy razem realizować. Mam nadzieję że wyniosłeś z całego przedmiotu choć odrobinę więcej niż tylko ocenę. Dobra bierzmy się do pracy.

Zadanie zostały wykonane przeze mnie i działały w sposób jaki zinterpretowałem tą instrukcje przekazaną do laborki. Jeśli nie przygotujesz się teoretycznie do tych zajęć słabo widzę osiągnięcie sensownego wyniku w trakcie zajęć.

Całe informacje odnośnie systemy FreeRTOS możemy wziąć z tych miejsc:

-http://www.freertos.org/a00106.html – tutaj mamy wszystko dotyczące wszystkich funkcji API dla RTOS-a. Możemy sobie otworzyć każdą dowolną funkcję gdzie będziemy mieli opisane wszystkie jej właściwości oraz parametry potrzebne do prawidłowego działania

-http://ep.com.pl/files/2434.pdf

-http://ep.com.pl/files/2562.pdf – to są 2 artykuły stworzone przez człowieka który napisał książkę o STM-ach, dosyć długie ale z fajnym i zrozumiałym opisem całości

Zagadnienia do wejściówki:

-Zadanie- są wykorzystywane standardowo w systemach operacyjnych czasu rzeczywistego, są to niezależne od siebie procesy wyposażone we własne konteksty- z perspektywy takiego zadania wszystkie rejestry i stos mikrokontrolera należą tylko do niego. O tym które zadanie jest wykonywane w danym momencie decyduje algorytm szeregowania.

-Semafor – chroniona zmienna lub abstrakcyjny typ danych, który stanowi klasyczną metodę kontroli dostępu przez wiele procesów do wspólnego zasobu w środowisku programowania równoległego.

-Kolejka – liniowa struktura danych, w której nowe dane dopisywane są na końcu kolejki, a z początku kolejki pobierane są dane do dalszego przetwarzania (bufor typu FIFO, First In, First Out; pierwszy na wejściu, pierwszy na wyjściu).

Jak zwykle trzeba będzie zacząć od utworzenia na samym wstępie projektu. Tworzenie projektu:

Zgodnie z instrukcją lab5 będziemy korzystać jak zwykle z pliku evbLib. Dodatkowo mamy do dołączenia całkiem sporo plików dodatkowych.

  1. W keilu wybieramy Project> new uvision project

  2. Wybieramy mikroprocesor ten co zawsze czyli stm32f103vb

  3. Ok>ok

  4. Tworzymy main, File>New>Save>”main.c”

  5. Wciskamy 3 klocki kolorowe

  6. Dodajemy evbLib (ten większy plik-lib)

  7. Dodajemy plik main.c

  8. Dodajemy pozostałe potrzebne biblioteki:

  9. W ustawieniach (różdżka) wybieramy w zakładce Debug zaznaczamy programator ST-Link Debugger, później Settings>Flash Download > i zaznaczamy opcje reset and run

  10. W C/C++ dodajemy w paths ścieżki do:

  11. Robimy dopisek w polu Define : STM32F10X_MD, USE_STDPERIPH_DRIVER

  12. Dodajemy w main na samej górze dopisek dołączający biblioteki

#include "evbLib.h"

#include "FreeRTOS.h"

#include "task.h"

#include <stdio.h> // do uzycia funkcji sprintf

#include "semphr.h" // do obslugi semafora

  1. Dodajemy pusty szkielet programu (main i while i patrzymy czy się skompiluje i wgra na procesor)

  2. Jeśli tak to projekt gotowy!

Komentarzu wymaga dodanie do bibliotek heap_2.c zamiast zgodnie z instrukcją heap_3.c. Sam Pan Sawicki skomentował to w ten sposób:

Instrukcje pisałem z myślą o projekcie samodzielnym ale potem zdecydowałem się dołączyć do tego skompilowaną bibliotekę żeby nie zawracać Wam głowy konfigurowaniem LCD czy diodek a skupić się na samym mechanizmie działania RTOS. startup w kompilowany do tych bibliotek ma ustawioną bardzo mała stertę. Dlatego model 3 który korzysta z malloc implementowanego przez kompilator spowoduje że przy dwóch zadaniach RTOS sie nie uruchomi bo nie bedzie już pamięci. Model heap2 sam implementuje funkcje alokacji pamięci i ma jej do dyspozycji tyle ile ustawiono we freeRTOS_config.h. 

Dobra przystępujemy do wykonywania zadań:

1 zad

void task1(void *param) //stworzenie zadania 1

{

while(1)

{

ledToggle(1);

vTaskDelay(100); // dzieki zastosowanie tej funkcji nie mamy problemu z wykonywaniem funkcji o jednakowym priorytecie w tym samym momencie

}

}

void task2(void *param) //stworzenie zadania 2

{

while(1)

{

ledToggle(2);

vTaskDelay(500);

}

}

int main(void) //stworzenie programu glownego

{

xTaskCreate(task1,"Zadanie 1",configMINIMAL_STACK_SIZE,NULL,1,NULL); //tworzenie zadan z jednakowym priorytetem i rozmiarem stosu

xTaskCreate(task2,"Zadanie 2",configMINIMAL_STACK_SIZE,NULL,1 ,NULL);

vTaskStartScheduler(); // uruchomienie planisty

return 0;

}

2 zad

void task1(void *pvParameters)

{

while(1)

{

if(( int ) pvParameters ==1) //pojebane ale dziala

{

ledToggle(1);

}

if(( int ) pvParameters== 2)

{

ledToggle(2);

}

if(( int ) pvParameters== 3)

{

ledToggle(3);

}

if(( int ) pvParameters==4)

{

ledToggle(4);

}

if(( int ) pvParameters==5)

{

ledToggle(5);

}

if(( int ) pvParameters==6)

{

ledToggle(6);

}

if(( int ) pvParameters==7)

{

ledToggle(7);

}

if(( int ) pvParameters==8)

{

ledToggle(8);

}

vTaskDelay(200);

}

}

int main(void) //stworzenie programu glownego

{

int i;

char nazwa[10];

for(i=0;i<8;i++)

{

sprintf(nazwa,"Zadanie %i",i);

xTaskCreate(&task1, nazwa,configMINIMAL_STACK_SIZE, (void *) (i+1),1,NULL);

}

vTaskStartScheduler(); // uruchomienie planisty

return 0; }

Komentarzu wymaga tutaj spora ilość if-ów w tasku. Niestety nie udało mi się opracować pobierania innego typu zmiennych niż typu int więc żeby dało radę działać z tym co mam zastosowałem ify do tego. Mało eleganckie a wręcz głupie i nielogiczne ale działa.

3 zad

Wer. 1 ze zmienną globalną

int zmienna_globalna=1;

void czyszczenie_lcd()

{

lcdGoTo(0,0);

lcdWrite(" ");

lcdGoTo(0,0);

}

void task1(void *param)

{

TickType_t xLastWakeTime;

const TickType_t xFrequency = 1000;

while(1)

{

if(zmienna_globalna==1)

{

lcdWrite("kbzddm");

zmienna_globalna++;

}

if(zmienna_globalna==3)

{

czyszczenie_lcd();

xLastWakeTime = xTaskGetTickCount();

vTaskDelayUntil(&xLastWakeTime, xFrequency);

zmienna_globalna=1;

}

}

}

void task2(void *param) //stworzenie zadania 2

{

TickType_t xLastWakeTime;

const TickType_t xFrequency = 1000;

while(1)

{

if(zmienna_globalna==2)

{

xLastWakeTime = xTaskGetTickCount();

lcdGoTo(1,0);

lcdWrite("serio");

vTaskDelayUntil(&xLastWakeTime, xFrequency);

zmienna_globalna++;

}

}

}

int main(void) //stworzenie programu glownego

{

xTaskCreate(task1,"Zadanie 1",configMINIMAL_STACK_SIZE,NULL,1,NULL); //tworzenie zadan z jednakowym priorytetem i rozmiarem stosu

xTaskCreate(task2,"Zadanie 2",configMINIMAL_STACK_SIZE,NULL,1 ,NULL);

vTaskStartScheduler(); // uruchomienie planisty

return 0;

}

3 zad

Wer. 2 z semaforem

xSemaphoreHandle semafor;

void czyszczenie_lcd()

{

lcdGoTo(0,0);

lcdWrite(" ");

lcdGoTo(0,0);

}

void task1(void *param)

{

TickType_t xLastWakeTime;

const TickType_t xFrequency = 2000;

while(1)

{

if(xSemaphoreTake(semafor, 1000 ))

{

xLastWakeTime = xTaskGetTickCount();

lcdWrite("kbzddm");

xSemaphoreGive(semafor);

vTaskDelayUntil(&xLastWakeTime, xFrequency);

xSemaphoreTake(semafor, 1000);

czyszczenie_lcd();

xLastWakeTime = xTaskGetTickCount();

vTaskDelayUntil(&xLastWakeTime, xFrequency);

xSemaphoreGive(semafor);

}

}

}

void task2(void *param) //stworzenie zadania 2

{

TickType_t xLastWakeTime;

const TickType_t xFrequency = 1000;

vTaskDelay(1);

while(1)

{

if(xSemaphoreTake(semafor, 1000 ))

{

lcdGoTo(1,0);

lcdWrite("kbzddm2");

xSemaphoreGive(semafor);

}

}

}

int main(void) //stworzenie programu glownego

{

semafor = xSemaphoreCreateMutex();

xTaskCreate(task1,"Zadanie 1",configMINIMAL_STACK_SIZE,NULL,1,NULL); xTaskCreate(task2,"Zadanie 2",configMINIMAL_STACK_SIZE,NULL,1 ,NULL);

vTaskStartScheduler(); // uruchomienie planisty

return 0;

}

I tutaj najważniejsza kwestia dotycząca tego zadania. Aby program z semaforem działał musimy dodać jeszcze jedną linijkę kodu w pliku konfiguracyjnym RTOS-a.

#define configUSE_MUTEXES 1

Aby wejść w ten plik wystarczy że przeniesiemy się do definicji przy configMINIMAL_STACK_SIZE i tam wklejamy tą linijkę kodu i po problemie.


Wyszukiwarka