FreeRTOS

 Безкоштовна ОС жорсткого реального часу з відкритим вихідним кодом.

Розроблена компанією Real Time Engineers ltd спеціально для вбудованих систем.

Реалізована на 35 мікроконтролерах.

Користувачам дозволяється залишати закритим пропрієтарний код із збереженням відкритого коду ядра.

Переваги:

  • Багатозадачність.
  • Часова основа.
  • Обмін даними між завданнями.
  • Синхронізація.

Недоліки:

  • Різке збільшення потрібної пам'яті програм для реалізації ядра
  • Збільшення потрібної ОЗУ для зберігання стека кожного завдання, семафорів, черг, м'ютексів і інших об'єктів ядра системи.
  • Затримки при перемиканні між завданнями на збереження контексту.

Особливості

  • Невеликий обсяг пам'яті, низькі накладні витрати та швидке виконання.
  • Варіанти для малопотужних застосувань.
  • Призначений як для любителів, так і для професійних розробників, що працюють на комерційних продуктах.
  • Підтримка Coroutine (coroutines у FreeRTOS - це прості та легкі завдання із обмеженим використанням стеків викликів ).

Відгалуження

  • «SafeRTOS» - доопрацьований, документований, протестований і пройшов сертифікацію на відповідність стандарту безпеки IEC 61508.
  • SafeRTOS використовується в аерокосмічній промисловості та медичній техніці.
  • OpenRTOS - комерційна версія з гарантією виробника.
  • Amazon FreeRTOS
Планувальник - це частина ядра ОСРЧ, яка визначає, яка з задач, готових до виконання, виконується в даний конкретний момент часу. 
Планувальник може призупиняти, а потім знову поновлювати виконання завдання протягом усього її життєвого циклу (тобто з моменту створення завдання до моменту її знищення).

Планувальник (Scheduler)

Планувальник підтримує 3 типи багатозадачності:

  • - витісняючу (операційна система може тимчасово перервати поточний процес без будь-якої допомоги з його боку).
  • - кооперативну (процеси періодично добровільно поступаються контролем , або перебувають в режимі очікування, для того щоб кілька додатків мали можливість працювати одночасн)
  • - гібридну

Завдання і співпрограми

  • Підтримує завдання і співпрограми. Співпрограми спеціально створені для МК з малим об'ємом ОЗУ.
  • Немає програмних обмежень на кількість одночасно виконуваних завдань.
  • Немає обмеження на кількість пріоритетів завдань.
  • Кільком завданням може бути призначений однаковий пріоритет

Розвинені засоби синхронізації:

  • черги
  • виконавчі семафори
  • рахункові семафори
  • рекурсивні семафори
  • м'ютекси
  • м'ютекси з успадкуванням пріоритету.

Витісняюча багатозадачність

Витісняюча багатозадачність означає, що виконується завдання з низьким пріоритетом перекривається готової завданням з більш високим пріоритетом. 

Перемикання між завданнями відбувається через рівні кванти часу. 

Перш, ніж вископопріорітетная завдання почне виконання, повинен закінчитися поточний квант часу.

Час реакції FreeRTOS на зовнішні події в режимі витісняюої багатозадачності-ні більше одного кванта часу планувальника, який можна задавати в налаштуваннях (за замовчуванням це 1 мс).

Якщо готові до виконання кілька завдань з однаковим пріоритетом, то в такому випадку планувальник виділяє кожної з них по одному кванту часу, після закінчення якого керування отримує наступне завдання з таким же пріоритетом, і так далі по колу.

Кооперативна багатозадачність

Кооперативна багатозадачність відрізняється від витісняючої тим, що планувальник самостійно не може перервати виконання поточного завдання, навіть готовий до виконання завдання з великим пріоритетом. 

Кожне завдання має самостійно передати управління планувальником. 

Таким чином, високопріоритетних завдання чекатиме, поки фонове завершить свою роботу і віддасть управління планувальнику.

Час реакції системи на зовнішню подію стає невизначеним і залежить від того, як довго поточне завдання буде виконуватися до передачі управління.

Гібридна багатозадачність

Невитісняюча і кооперативна концепції багатозадачності поєднуються у гібридній багатозадачності.

Виклик планувальника відбувається кожен квант часу, але, на відміну від витісняючої багатозадачності, програміст має можливість зробити це примусово в тілі завдання. 

Особливо корисний цей режим, коли необхідно скоротити час реакції системи на переривання. 

Припустимо:

  • Відбувається фонове завдання, а високопріоритетне очікує настання деякого переривання. 
  • Відбувається переривання. Після закінчення роботи обробника переривань виконання повертається до поточної фонової задачі, а високопріоритетна очікує, поки закінчиться поточний квант часу. 
  • Однак якщо після виконання обробника переривання передати управління планувальнику, то він передасть управління високопріоритетній задачі,

Паралельне виконання

  • У реальному процесорі при роботі ОСРВ виконання завдань має періодичний характер: кожна задача виконується певний час, після чого процесор «перемикається» на наступне завдання

 

Завдання

Будь-яка програма, яка виконується під управлінням FreeRTOS, являє собою безліч окремих незалежних завдань. 

Кожне завдання виконується в своєму власному контексті без залежностей від інших завдань і ядра FreeRTOS.

Контекст завдання

Коли завдання виконується, воно, використовує регістри процесора, пам'ять програм і пам'ять даних.

Разом ці ресурси утворюють контекст завдання (task execution context).

Контекст завдання цілком і повністю описує поточний стан процесора: прапори процесора, яка інструкція зараз виконується, які значення завантажені в регістри процесора, де в пам'яті знаходиться вершина стека і т.д.

Перемикання контексту

Завдання «не знає», коли ядро ​​ОСРВ призупинить її виконання або, навпаки, відновить.

Одна з основних функцій ядра ОСРВ - це забезпечення ідентичності контексту завдання до її припинення і після її відновлення.

Коли ядро ​​призупиняє завдання, воно повинно зберегти контекст завдання, а при її відновленні - відновити.

Процес збереження і відновлення контексту завдання називається перемиканням контексту (context switching).

Основні стани завдань

Серед всіх завдань в системі в один момент часу може виконуватися тільки одне. 

Кажуть, що воно знаходиться в стані виконання. 

Решта завдань в цей момент не виконуються, чекаючи, коли планувальник виділить кожному з них процесорний час. 

Таким чином, завдання може перебувати в двох основних станах: виконуватися і не виконуватися.

Блокування

  • Завдання знаходиться в блокованому стані, якщо воно очікує настання часової або зовнішньої події (event). 
  • Знаходження завдання в блокованому стані обмежене тайм-аутом.
  • Якщо очікувана зовнішня подія не настала протягом тайм-ауту, то завдання повертається в стан готовності до виконання. 
  • Це запобігає «підвисання» завдання при очікуванні зовнішнього події, яке з якихось причин ніколи не настане. Блокована завдання не отримує процесорного часу.
  • Наприклад, викликавши API-функцію vTaskDelay () , завдання переведе себе в блокований стан до тих пір, поки не пройде часовий період затримки (delay): це буде часова подія
  • Завдання блоковане, якщо вона очікує події, пов'язаного з іншими об'єктами ядра - чергами і семафорами: це буде зовнішня подія.

Призупинення

Призупинене (suspended) завдання також не отримує процесорного часу.

На відміну від блокованого стану, перехід в призупинений стан і вихід з нього здійснюється в явному вигляді викликом API-функцій vTaskSuspend () і xTaskResume () . 

Тайм-аут для призупиненого стану не передбачений, і завдання може залишатися призупиненим як завгодно довго.

Створення/видалення завдань

Завдання в FreeRTOS реалізуються у вигляді Сі- функцій. 

Обов'язкові вимога до функції, що реалізує завдання:

  • повинна мати один аргумент типу покажчик на void
  • нічого не повертати (void). 

Покажчик на таку функцію визначено як pdTASK_CODE. 

Кожне завдання - це невелика програма зі своєю точкою входу, яка містить нескінченний цикл

void ATaskFunction (  void  * pvParameters ) {

/ * Змінні можуть бути оголошені тут, як і в звичайній функції.

Кожен екземпляр цього завдання матиме свою власну копицю змінної iVariableExample.

Якщо оголосити змінну зі специфікатором static, то буде створена тільки одна змінна

 iVariableExample, доступна з усіх примірників завдання * /

int iVariableExample =  0 ;

/ * Тіло завдання реалізовано як нескінченний цикл * /

for ( ;; ){

/ * Код, який реалізує функціональність завдання * /

}

/ * Якщо все-таки відбудеться вихід з нескінченного циклу, то задача повинна бути знищена ДО кінця функції.

 Параметр NULL означає, що знищується завдання, що викликає API-функцію vTaskDeleteO * /

vTaskDelete (  NULL ) ;

}

xTaskCreate () – створення завдання. Функція xTaskCreate () є однією з найбільш складних API-функцій.

xTaskCreate () в разі успішного створення завдання повертає pdTRUE. 

Якщо ж обсягу пам'яті купи недостатньо для розміщення службових структур даних і стека завдання, то xTaskCreate () повертає errCOULD_NOT_ALLOCATE_REQUIRED_ MEMORY.

Параметри xTaskCreate ()

  • pvTaskCode - покажчик на функцію, що реалізує завдання (фактично - ідентифікатор функції в програмі).
  • pcName - нуль-термінальний (закінчується нулем) рядок, що визначає ім'я функції. Ядром не використовується, а служить лише для наочності при налагодженні.
  • usStackDepth - глибина (розмір) власного стека створюваної завдання. 
    • Розмір задається в словах, що зберігаються в стеку, а не в байтах. 
    • Розмір стека, необхідний для коректної роботи завдання, яка нічого не робить, задається макросом соnfigMINIMAL_STACKJSIZE. 
    • Не рекомендується створювати завдання з меншим розміром стека. 
    • Якщо ж завдання споживає великі обсяги стека, то необхідно задати більше значення usStackDepth.
  • pvParameters - довільний параметр, який передається завданню при її створенні. Здається в вигляді покажчика на void, в тілі завдання може бути перетворений в покажчик на будь-який інший тип. Передача параметра виявляється корисною можливістю при створенні декількох екземплярів одного завдання.
  • uxPriority - визначає пріоритет створюваної завдання. Нуль відповідає найнижчому пріоритету, (cotifigMAX_ PRIORITIES - 1) - найвищого.
  • pxCreatedTask - може використовуватися для отримання дескриптора (handle) створюваної завдання, який поміщається за адресою pxCreatedTask. Якщо в отриманні дескриптора немає необхідності, то pxCreatedTask повинен бути встановлений в NULL.

Знищення завдань

  • Завдання може знищити саме себе або будь-яке інше завдання в програмі за допомогою API-функції vTaskDelete ()
  • Видаленого завдання фізично не існує і, отже, ніколи не виконується. Немає можливості відновити вилучене завдання, єдиний вихід - створити нове.
  • Ядро FreeRTOS влаштовано так, що внутрішня реалізація завдання Бездіяльність відповідає за звільнення пам'яті, яку використовувало віддалене завдання.
  • void vTaskDelete (xTaskHandle pxTaskToDelete) ;
  • pxTaskToDelete - це дескриптор завдання, яке необхідно знищити. 
  • Якщо необхідно знищити завдання, яка викликає API-функцію vTaskDelete () то в якості параметра pxTaskToDelete слід задати NULL.

Часове блокування

Сон та блокування

Завдання може саме припинити своє виконання. 

  • коли задача «хоче» затримати своє виконання на певний проміжок часу (в такому випадку вона переходить в стан сну (sleep)). 
  • коли задача очікує звільнення будь-якого апаратного ресурсу (наприклад, послідовного порту) або настання якоїсь події (event), в цьому випадку говорять, що завдання блокована (block). 

Блоковане або «спляче» завдання не потребує процесорного часу до настання відповідної події або закінчення певного інтервалу часу. 

Функції вимірювання інтервалів часу і обслуговування подій бере на себе ядро ​​ОСРВ

Квант часу

Квант часу роботи планувальника (tick) - це жорстко фіксований відрізок часу, протягом якого планувальник не втручається у виконання завдання. 

Після закінчення кванта часу планувальник отримує можливість призупинити поточне завдання і відновити, готову до виконання. 

Квант часу також називається системним квантом. 

Для відліку системних квантів в МК зазвичай використовується переривання від таймера / лічильника. 

Системний квант використовується як одиниця вимірювання інтервалів часу засобами ОСРВ.

Зміна системного кванту

Зменшуючи тривалість системного кванту, можна домогтися більш швидкої реакції програми на зовнішні події, проте це призведе до збільшення частоти виклику планувальника, що позначиться на продуктивності обчислювальної системи в цілому.

Налаштувати квант часу (FreeRTOSVariant.h)

#define portUSE_WDTO WDTO_15MS

Варіанти:

  • WDTO_15MS
  • WDTO_30MS
  • WDTO_60MS
  • WDTO_120MS
  • WDTO_250MS
  • WDTO_500MS

Отримати тривалість системного кванта

  • Використовуючи макроозначення portTICK_RATE_MS можна отримати тривалість системного кванта в мілісекундах.
  • Поточне значення лічильника квантів може бути отримано за допомогою API- функції xTaskGetTickCount () .

vTaskDelay

  • void vTaskDelay (portTickType xTicksToDelay);    
  • xTicksToDelay - кількість квантів часу затримки.

Нехай завдання викликала функцію xTicksToDelay (100) в момент часу, коли лічильник квантів дорівнював 10000.

Завдання відразу ж блокується, планувальник віддає управління іншому завданню.

Заблоковане завдання повернеться в стан готовності до виконання, тільки коли лічильник квантів досягне значення 10100.

Протягом часу, поки лічильник квантів буде збільшуватися від 10000 до 10100, надасть права на роботу іншим завданням, в тому числі завдання з б леї низьким пріорітетом.

Циклічне виконання

Часто перед програмістом стоїть завдання циклічного виконання якої-небудь дії з чітко фіксованою частотою і, отже, періодом. 

API-функція vTaskDelay () переводить завдання в блокований стан на проміжок часу, який відраховується від моменту виклику vTaskDelay ()

У разі реалізації циклічно повторюваної дії період його виконання складатиметься з часу його виконання + затримки, створюваної функцією vTaskDelay ()

Для забезпечення циклічного виконання з точно заданим періодом, необхідно знати час виконання тіла завдання, щоб скорегувати величину затримки. Це створює додаткові складності.

vTaskDelayUntil ()

Програміст задає період dT, який відраховується з моменту моменту виходу завдання з блокованого стану. 

void vTaskDelayUntil (portTickType * pxPreviousWakeTime, portTickType xTimelncrement);

  • pxPreviousWakeTime - покажчик на змінну, в якій зберігається значення лічильника квантів в момент останнього виходу завдання з блокованого стану. Цей момент використовується як відправна точка для відліку часу, на яке завдання переходить в блоковане стан. 
  • Змінна, на яку посилається покажчик pxPreviousWakeTime , автоматично оновлюється функцією vTaskDelayUntil () , тому при типовому використанні ця змінна не повинна модифікуватися в тілі завдання. Виняток становить початкова ініціалізація.
  • xTimelncrement - безпосередньо задає період виконання завдання. Здається в квантах; для завдання в мілісекундах може використовуватися макроозначень portTICK_RATE_MS .

void vTaskFunction (  void  * pvParameters ) {

  / * Змінна, яка буде зберігати значення лічильника квантів в момент виходу завдання з блокованого стану * /

  portTickType xLastWakeTime ;

  / * Змінна xLastWakeTime потребує ініціалізації поточним значенням лічильника квантів.

Це єдиний випадок, коли її значення задається явно.* /

  XLastWakeTime = xTaskGetTickCount яйце ;

  for (;;) {

    / * Корисна робота* /

    VTaskDelayUntil(xlastWakeTime,(50 / portTICK_RATE_MS ) );

  }

}

Пріоритети

Механізм пріоритетів завдань

У будь-якій програмі реального часу є менш та більш відповідальні задачі. 

Під «відповідальністю» завдання тут розуміється час реакції програми на зовнішню подію, яке обробляється завданням. 

Наприклад, до часу реакції на спрацьовування датчика у виробничій установці пред'являються куди суворіші вимоги, ніж до часу реакції на натискання клавіші на клавіатурі. 

Для забезпечення переваги на виконання найвідповідальніших завдань у FreeRTOS застосовується механізм пріоритетів завдань (Task priorities).

Серед усіх завдань, які перебувають у стані готовності, планувальник віддасть управління завданню, яке має найвищий пріоритет. 

Завдання буде виконуватися до тих пір, поки воно не буде блоковане або припинене, або поки не з'явиться готове до виконання завдання з таким чи більш високим пріоритетом.

Кожній задачі призначається пріоритет від 0 до (configMAX_PRIORITIES - 1). 

Менше значення пріоритету відповідає меншому пріоритету. 

Найнижчий пріоритет у завдання «бездіяльність», значення якого визначено в tskIDLE_PRIORITY як 0.

Змінюючи значення configMAX_PRIORITIES, можна визначити будь-яке число можливих пріоритетів, однак зменшення configMAX_PRIORITIES дозволяє зменшити обсяг ОЗУ, споживаний ядром.

Найчастіше завдання реалізується як корисна дія, яка циклічно повторюється із заданою частотою / періодом. 

Кожній задачі призначаються пріоритет і частота її циклічного виконання. 

Для досягнення заданого часу реакції системи на зовнішні події розробник повинен відповідним чином призначити пріоритети завданням і визначити частоту їх виконання.

Rate Monotonic Scheduling

Оскільки FreeRTOS відноситься до ОСРВ з плануванням з фіксованими пріоритетами, то рекомендованої стратегією призначення пріоритетів є використання принципу «чим менше період виконання завдання, тим вище у неї пріоритет» ( Rate Monotonic Scheduling , RMS).

Всі завдання поділяються за необхідним часом реакції на відповідну зовнішню подію. 

Кожній задачі призначається унікальний пріоритет (у програмі не повинно бути двох завдань з однаковим пріоритетом), причому пріоритет тим вище, чим коротше час реакції завдання на подію. 

Динамічна зміна пріоритету завдань

FreeRTOS дозволяє динамічно змінювати пріоритет завдання під час виконання програми: 

  • uxTaskPriorityGet () - отримання пріоритету завдання.
  • vTaskPrioritySet () - завдання пріоритету завдання.

unsigned portBASE_TYPE uxTaskPriorityGet (xTaskHandle pxTask) ;

pxTask - дескриптор завдання, пріоритет якої необхідно отримати. 

Якщо необхідно отримати пріоритет завдання, яка викликає uxTaskPriorityGet (), то в якості параметра pxTask слід задати NULL.

void vTaskPrioritySet (xTaskHandle pxTask, unsigned portBASE_TYPE uxNewPriority);

  • pxTask -дескріптор (handle) завдання, пріоритет якої необхідно змінити. Дескриптор завдання може бути отриманий при створенні екземпляра задачі xTaskCreate () (параметр pxCreatedTask ). 
  • Якщо необхідно змінити пріоритет завдання, яка викликає API-функцію vTaskPrioritySet () , то в якості параметра pxTask слід задати NULL.
  • uxNewPriority - нове значення пріоритету, який буде присвоєно задачі.

Завдання Бездіяльність (Idle task).

Хоча б одне завдання повинно постійно перебувати в стані готовності до виконання. 

Якщо всі завдання в програмі заблоковані, МК буде виконувати завдання Бездіяльність, яке постійно знаходиться в стані готовності до виконання.

Його пріоритет задається макровизначенням tskIDLE_PRIORITY як найнижчий в програмі (зазвичай 0). Це гарантує, що завдання Бездіяльність не виконуватиметься, поки в програмі є хоча б одна задача в стані готовності до виконання. 

Як тільки з'явиться будь-яка готова до виконання завдання, завдання Бездіяльність буде витіснена нею.

Додавання свого функціоналу в функцію завдання Бездіяльність

  • Реалізація фонових завдань.
  • Вимірювання резерву МК по продуктивності. Під час виконання завдання Бездіяльність процесор не зайнятий корисною роботою, тобто простоює. Відношення часу простою процесора до всього часу виконання програми дає уявлення про резерв процесора по продуктивності, тобто про можливість додати додаткові завдання в програму.
  • Зниження енергоспоживання МК. У багатьох МК є можливість переходу в режим зниженого енергоспоживання для економії електроенергії. Це актуально, наприклад, в разі проектування пристрою на батарейках. Вихід з режиму енергозбереження в багатьох МК можливий по перериванню від таймера. Якщо налаштувати МК так, щоб вхід в режим зниженого енергоспоживання відбувався в тілі функції завдання Бездіяльність, а вихід - по перериванню від того ж таймера, що використовується ядром FreeRTOS для формування квантів часу, то це дозволить значно знизити енергоспоживання пристрою під час простою процесора.

Обмеження на реалізацію функції Бездіяльність

Завдання Бездіяльність не можна намагатися перевести в блокований або припинений стан.

Якщо програма допускає використання API-функції знищення завдання vTaskDelete () , то функція завдання Бездіяльність повинна завершувати своє виконання в розумні строки. Ця вимога пояснюється тим, що функція завдання Бездіяльність відповідальна за звільнення ресурсів ядра після знищення завдання. Таким чином, затримка в тілі функції завдання Бездіяльність призведе до такої ж затримки в очищенні ресурсів, пов'язаних з знищеним завданням, і ресурси ядра не будуть звільнені вчасно. 

Кооперативна багатозадачність

  • Найвагоміша відмінність кооперативної багатозадачності - те, що планувальник не отримує управління кожен системний квант часу. 
  • Замість цього тіло функції, що реалізує завдання, має містити явний виклик API-функції планувальника taskYIELD().
  • Результатом виклику taskYIELD() може бути як перемикання на інше завдання, так і відсутність перемикання, якщо інших завдань, готових до виконання, немає. 
  • Виклик API- функції, яка переводить завдання в блоковане стан, також призводить до виклику планувальника.
  • Відлік квантів часу ядро ​​FreeRTOS виконує при використанні будь-якого типу багатозадачності, тому API-функції, пов'язані з відліком часу, коректно працюють і в режимі кооперативної багатозадачності. 
  • Як і для витісняючої, в разі застосування кооперативної багатозадачності кожного завдання необхідний власний стек для зберігання свого контексту.

Переваги кооперативної багатозадачності:

  • Менше споживання пам'яті стека при перемиканні контексту завдання, відповідно, більш швидке переключення контексту. 
  • З точки зору компілятора виклик планувальника «виглядає» як виклик функції, тому в стеці автоматично зберігаються регістри процесора і немає необхідності їх повторного збереження в рамках збереження контексту завдання.
  • Спрощується проблема спільного доступу декількох завдань до одного апаратного ресурсу. Наприклад, не потрібно побоюватися, що кілька завдань одночасно будуть модифікувати одну змінну, так як операція модифікації не може бути перервана планувальником.

Недоліки кооперативної багатозадачності

  • Програміст повинен в явному вигляді викликати API-функцію taskYIELD() в тілі завдання, що збільшує складність програми.
  • Одна задача, яка з якихось причин не викликала API-функцію taskYIELD() призводить до «зависання» всієї програми.
  • Важко гарантувати заданий час реакції системи на зовнішнє подія, так як воно залежить від максимального часового проміжку між викликами taskYIELD () .
  • Виклик taskYIELD () всередині циклів може уповільнити виконання програми.

Вибір режиму кооперативної багатозадачності

  • Задати значення макроозначення configUSE_PREEMPTION у файлі FreeRTOSConfig.h рівним 0:
  • #define configUSE_PREEMPTION 0
  • Значення соnfigUSE__PREEMPTION , рівне 1, дає розпорядження ядру FreeRTOS працювати в режимі витісняючої багатозадачності.

Гібридна багатозадачність

Гібридна багатозадачність поєднує:

  • автоматичний виклик планувальника кожен квант часу,
  • можливість примусового, явного виклику планувальника. 

Корисною гібридна багатозадачність може виявитися, коли необхідно скоротити час реакції системи на переривання. 

В цьому випадку в кінці тіла обробника переривання виробляють виклик планувальника, що призводить до придбання конкретної завдання, яка очікує настання цього переривання.

portYIELD_FROM_ISR () - викликає планувальник з тіла обробника переривання. 

Спеціального дії для включення режиму гібридної багатозадачності не існує. 

Досить дозволити виклик планувальника кожен квант часу (макроозначень configUSE_PREEMPTION в файлі FreeRTOSConfig.h має бути рівним 1) і в явному вигляді викликати планувальник в функціях, що реалізують завдання, і в обробниках переривань за допомогою API-функцій taskYIELD () і portYIELD_ FROM_ISR () відповідно .

Витісняюча багатозадачність без поділу часу

Ідея полягає в тому, що виклик планувальника відбувається тільки в обробниках переривань. 

Завдання виконується до тих пір, поки не відбудеться якесь переривання. 

Після чого вона витісняється завданням, відповідальної за обробку зовнішнього події, пов'язаного з цим перериванням. 

Таким чином, завдань не змінюють один одного по закінченні кванта часу, це відбувається тільки по зовнішній події.

Такий тип багатозадачності більш ефективний щодо продуктивності, ніж витісняюча багатозадачність з поділом часу. 

Процесорний час не витрачається даремно на виконання коду планувальника кожен квант часу.

Для використання цього типу багатозадачності:

  • configUSE_ PREEMPTION в файлі FreeRTOSConfig.h має бути рівним 0;
  • кожен обробник переривання повинен містити явний виклик планувальника portYIELD_FROM_ISR ()

 

Програма, що створює два потоки

#include <Arduino_FreeRTOS.h>

void TaskBlink1( void *pvParameters );

void TaskBlink2( void *pvParameters );

void setup() {

xTaskCreate(TaskBlink1,(const portCHAR *)"B1",128,NULL,2,NULL);

xTaskCreate(TaskBlink2,(const portCHAR *)"B2",128,NULL,1,NULL);

}

void loop(){

}

void TaskBlink1(void *pvParameters){

pinMode(2, OUTPUT);

for (;;){

digitalWrite(2, HIGH);

vTaskDelay(1000 / portTICK_PERIOD_MS);

digitalWrite(2, LOW);

vTaskDelay(1000 / portTICK_PERIOD_MS);

}

}

void TaskBlink2(void *pvParameters){

pinMode(3, OUTPUT);

               for (;;){

digitalWrite(3, HIGH);

vTaskDelay(500 / portTICK_PERIOD_MS);

digitalWrite(3, LOW);

vTaskDelay(500 / portTICK_PERIOD_MS);

}

}

Остання зміна: четвер, 7 жовтня 2021, 15:01
Доступність

Шрифти Шрифти

Розмір шрифта Розмір шрифта

1

Колір тексту Колір тексту

Колір тла Колір тла

Кернінг шрифтів Кернінг шрифтів

Видимість картинок Видимість картинок

Інтервал між літерами Інтервал між літерами

0

Висота рядка Висота рядка

1.2

Виділити посилання Виділити посилання

Вирівнювання тексту Вирівнювання тексту

Ширина абзацу Ширина абзацу

0