W tym poście chciałbym opisać sposób przygotowania przykładowej aplikacji pozwalającej
Na samym początku przykład tworzący nowe zadania wraz z priorytetami. Należy pamiętać o tym, że zadania można przypisać w dowolnym momencie działania programu.
Każde z zadań może znajdować w jednym z czterech stanów (Running, Ready, Blocked and Suspended). W stanie Running może znajdować się tylko jedno zadanie. Jeśli chodzi o stan Ready, to kolejność wywołania kilku zadań w tym stanie jest określana przez ich priorytety.
Aby stworzyć zadania należy wywołać następującą instrukcje:
Na samym początku tworzymy domyślne zadanie które będzie wykonywane ciągiem:
Ma ono najwyższy z priorytetów przydzielonych pozostałym zadaniom. W nim odbywają się główne zadania przydzielone zadaniom.
Dalej uruchomienie głównych zadań:
[Źródło: http://www.st.com/en/evaluation-tools/32f746gdiscovery.html]
Na samym początku przykład tworzący nowe zadania wraz z priorytetami. Należy pamiętać o tym, że zadania można przypisać w dowolnym momencie działania programu.
Każde z zadań może znajdować w jednym z czterech stanów (Running, Ready, Blocked and Suspended). W stanie Running może znajdować się tylko jedno zadanie. Jeśli chodzi o stan Ready, to kolejność wywołania kilku zadań w tym stanie jest określana przez ich priorytety.
Aby stworzyć zadania należy wywołać następującą instrukcje:
Na samym początku tworzymy domyślne zadanie które będzie wykonywane ciągiem:
- void createDefaultTask()
- {
- osThreadDef(defaultTask, StartDefaultTask, osPriorityNormal, 0, 1280);
- defaultTaskHandle = osThreadCreate(osThread(defaultTask), NULL);
- }
Ma ono najwyższy z priorytetów przydzielonych pozostałym zadaniom. W nim odbywają się główne zadania przydzielone zadaniom.
Dalej uruchomienie głównych zadań:
- void createAllTask(void)
- {
- defineDataForAllTasks();
- osThreadDef(vtsk1, task1_Propert.taskFunct,
- task1_Propert.priority,
- task1_Propert.instances,
- task1_Propert.stackSize);
- Task1_Handle = osThreadCreate(osThread(vtsk1), (void*)&task1_Propert);
- osThreadDef(vtsk2, task2_Propert.taskFunct,
- task2_Propert.priority,
- task2_Propert.instances,
- task2_Propert.stackSize);
- Task2_Handle = osThreadCreate(osThread(vtsk2), (void*)&task2_Propert);
- osThreadDef(vtsk3, task3_Propert.taskFunct,
- task3_Propert.priority,
- task3_Propert.instances,
- task3_Propert.stackSize);
- Task3_Handle = osThreadCreate(osThread(vtsk3), (void*)&task3_Propert);
- osThreadDef(vtsk4, task4_Propert.taskFunct,
- task4_Propert.priority,
- task4_Propert.instances,
- task4_Propert.stackSize);
- Task4_Handle = osThreadCreate(osThread(vtsk4), (void*)&task4_Propert);
- }
Parametry dla nich definiowane są w strukturze:
Wszystkie zadania z zdefiniowanymi parametrami wyglądają następująco:
Każde zadanie ma osobne funkcje obsługujące. Poniżej przykładowa obsługa dla zadania nr 1:
Tutaj ustawiane są parametry z danymi do struktury, następnie w głównej pętli która jest wywoływana co zadane opóźnienie wyświetlana jest informacja o zadaniu, wraz z ilością jego uruchomienia przechowywanego w zmiennej countTask1Enable.
Jeśli chcemy dynamicznie zmieniać priorytety danego zadania to należy wykorzystać funkcje osThreadSetPriority. W nim podawany jest uchwyt do danego zadania wraz z nowym priorytetem:
Aby uruchomić w projekcie zadanie domyślne oraz 5 zadać zwykłych należy w funkcji main wywołać następujące elementy:
Elementy do projektu można pobrać z dysku Google pod tym linkiem.
- typedef void (*taskFuncPointer)(void const * argument);
- typedef struct taskStruct {
- char taskName[10];
- taskFuncPointer taskFunct;
- osPriority priority;
- uint8_t instances;
- uint16_t stackSize;
- uint16_t screenPosi_y;
- uint16_t delayTime;
- }taskStruct_t;
Wszystkie zadania z zdefiniowanymi parametrami wyglądają następująco:
- taskStruct_t task1_Propert =
- {
- .taskName = "task1",
- .taskFunct = task1Function,
- .priority = osPriorityIdle,
- .instances = 0,
- .stackSize = 128,
- .screenPosi_y = 60,
- .delayTime = 1000
- };
- taskStruct_t task2_Propert =
- {
- .taskName = "task2",
- .taskFunct = task2Function,
- .priority = osPriorityIdle,
- .instances = 0,
- .stackSize = 128,
- .screenPosi_y = 110,
- .delayTime = 677
- };
- taskStruct_t task3_Propert =
- {
- .taskName = "task3",
- .taskFunct = task3Function,
- .priority = osPriorityLow,
- .instances = 0,
- .stackSize = 128,
- .screenPosi_y = 160,
- .delayTime = 439
- };
- taskStruct_t task4_Propert =
- {
- .taskName = "task4",
- .taskFunct = task4Function,
- .priority = osPriorityBelowNormal,
- .instances = 0,
- .stackSize = 128,
- .screenPosi_y = 210,
- .delayTime = 329
- };
Każde zadanie ma osobne funkcje obsługujące. Poniżej przykładowa obsługa dla zadania nr 1:
- void task1Function(void const * task1Structure)
- {
- volatile taskStruct_t *pointer;
- char displayString[60];
- pointer = (taskStruct_t*)task1Structure;
- for(;;)
- {
- ROCKTECH_SetTextColor(LCD_COLOR_RED);
- sprintf(displayString,"%lu %s %d ", countTask1Enable, pointer->taskName, osThreadGetPriority(NULL));
- ROCKTECH_DisplayString(30, pointer->screenPosi_y, (uint8_t *)displayString, LEFT_MODE);
- countTask1Enable++;
- osDelay(pointer->delayTime);
- }
- }
Tutaj ustawiane są parametry z danymi do struktury, następnie w głównej pętli która jest wywoływana co zadane opóźnienie wyświetlana jest informacja o zadaniu, wraz z ilością jego uruchomienia przechowywanego w zmiennej countTask1Enable.
Jeśli chcemy dynamicznie zmieniać priorytety danego zadania to należy wykorzystać funkcje osThreadSetPriority. W nim podawany jest uchwyt do danego zadania wraz z nowym priorytetem:
- osThreadSetPriority(Task1_Handle,osPriorityHigh);
Aby uruchomić w projekcie zadanie domyślne oraz 5 zadać zwykłych należy w funkcji main wywołać następujące elementy:
- Task_createDefault();
- Task_createMyTask();
- createAllTask();
- /* Start scheduler */
- osKernelStart();
- while(1) {}
- }
Elementy do projektu można pobrać z dysku Google pod tym linkiem.