background image

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 

background image

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" 

background image

#include "task.h"  
#include <stdio.h> // do uzycia funkcji sprintf 
#include "semphr.h" // do obslugi semafora 

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

procesor) 

14) 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 

background image

  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) 

background image

 

 

 

 

 

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; 

background image

 

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); 

background image

 

 

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 

background image

 

 

 

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(); 

background image

 

 

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(); 

   

background image

  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.