Introduction to FreeRTOS

Slides:



Advertisements
Similar presentations
Chapter 7 - Resource Access Protocols (Critical Sections) Protocols: No Preemptions During Critical Sections Once a job enters a critical section, it cannot.
Advertisements

Copyright © 2000, Daniel W. Lewis. All Rights Reserved. CHAPTER 8 SCHEDULING.
Concurrency: Mutual Exclusion and Synchronization Chapter 5.
Resource management and Synchronization Akos Ledeczi EECE 354, Fall 2010 Vanderbilt University.
Real-Time Library: RTX
CprE 458/558: Real-Time Systems (G. Manimaran)1 CprE 458/558: Real-Time Systems Resource Access Control Protocols.
FreeRTOS.
Ch. 7 Process Synchronization (1/2) I Background F Producer - Consumer process :  Compiler, Assembler, Loader, · · · · · · F Bounded buffer.
Chapter 6: Process Synchronization
Silberschatz, Galvin and Gagne ©2009 Operating System Concepts – 8 th Edition, Chapter 6: Process Synchronization.
5.6 Semaphores Semaphores –Software construct that can be used to enforce mutual exclusion –Contains a protected variable Can be accessed only via wait.
Introduction to Operating Systems – Windows process and thread management In this lecture we will cover Threads and processes in Windows Thread priority.
Concurrency: Mutual Exclusion, Synchronization, Deadlock, and Starvation in Representative Operating Systems.
Race Conditions CS550 Operating Systems. Review So far, we have discussed Processes and Threads and talked about multithreading and MPI processes by example.
MicroC/OS-II Embedded Systems Design and Implementation.
FreeRTOS.
Introduction to Embedded Systems
The Functions of Operating Systems Interrupts. Learning Objectives Explain how interrupts are used to obtain processor time. Explain how processing of.
Tami Meredith, Ph.D. CSCI  Devices need CPU access  E.g., NIC has a full buffer it needs to empty  These device needs are often asynchronous.
Operating Systems Process Management.
CE Operating Systems Lecture 11 Windows – Object manager and process management.
© Janice Regan, CMPT 300, May CMPT 300 Introduction to Operating Systems Mutual Exclusion.
FreeRTOS.
Lecture 7: Scheduling preemptive/non-preemptive scheduler CPU bursts
Overview Task State Diagram Task Priority Idle Hook AND Co-Routines
RTX - 51 Objectives  Resources needed  Architecture  Components of RTX-51 - Task - Memory pools - Mail box - Signals.
ECGR-6185 µC/OS II Nayana Rao University of North Carolina at Charlotte.
1 Computer Systems II Introduction to Processes. 2 First Two Major Computer System Evolution Steps Led to the idea of multiprogramming (multiple concurrent.
MicroC/OS-II S O T R.  MicroC/OS-II (commonly termed as µC/OS- II or uC/OS-II), is the acronym for Micro-Controller Operating Systems Version 2.  It.
1 VxWorks 5.4 Group A3: Wafa’ Jaffal Kathryn Bean.
CE Operating Systems Lecture 2 Low level hardware support for operating systems.
1 Run-to-Completion Non-Preemptive Scheduler. 2 In These Notes... What is Scheduling? What is non-preemptive scheduling? Examples Run to completion (cooperative)
Slides created by: Professor Ian G. Harris Operating Systems  Allow the processor to perform several tasks at virtually the same time Ex. Web Controlled.
CSCI1600: Embedded and Real Time Software Lecture 17: Concurrent Programming Steven Reiss, Fall 2015.
Mutual Exclusion -- Addendum. Mutual Exclusion in Critical Sections.
Embedded Real-Time Systems Processing interrupts Lecturer Department University.
Task Management 김백규. Task states(1/2)  Running  currently utilising the processor.  Ready  tasks are those that are able to execute.  they are not.
Process Scheduling. Scheduling Strategies Scheduling strategies can broadly fall into two categories  Co-operative scheduling is where the currently.
Semaphore 김백규. What is Semaphore?  A semaphore is a protected variable.  method for restricting access to shared resources (e.g. storage) in a multiprogramming.
Outlines  Introduction  Kernel Structure  Porting.
Process Synchronization. Concurrency Definition: Two or more processes execute concurrently when they execute different activities on different devices.
LPC2148's RTOS Bruce Chhuon 4/10/07. What is a Real Time Operating System? ● A Real Time Operating System (RTOS) manages hardware and software resources.
Introduction In this lab , we will learn
Outline Introduction to task synchronization Queues of FreeRTOS
REAL-TIME OPERATING SYSTEMS
EEE Embedded Systems Design Process in Operating Systems 서강대학교 전자공학과
CS4101 嵌入式系統概論 Real-Time Operating System
Topics Covered What is Real Time Operating System (RTOS)
CS703 – Advanced Operating Systems
Background on the need for Synchronization
CS4101 Introduction to Embedded Systems Lab 12: Task Synchronization
Round Robin Non-Preemptive Scheduler
CS4101 嵌入式系統概論 Tasks and Scheduling
CS4101 嵌入式系統概論 RT Scheduling & Synchronization
Chapter 2.2 : Process Scheduling
Real-time Software Design
Process management Information maintained by OS for process management
Chapter 6: CPU Scheduling
Computer System Overview
Operating System Concepts
Processor Fundamentals
Chapter 2: The Linux System Part 3
Transmitter Interrupts
Lecture 2 Part 2 Process Synchronization
CSCI1600: Embedded and Real Time Software
CSE 153 Design of Operating Systems Winter 19
CSCI1600: Embedded and Real Time Software
Akos Ledeczi EECE 6354, Fall 2017 Vanderbilt University
Akos Ledeczi EECE 6354, Fall 2015 Vanderbilt University
Chapter 13: I/O Systems “The two main jobs of a computer are I/O and [CPU] processing. In many cases, the main job is I/O, and the [CPU] processing is.
Presentation transcript:

Introduction to FreeRTOS A real-time operating system

Real-Time Operating Systems (RTOS) An operating system (OS) is software that manages the hardware and software resources and provides common services to applications. Real-time programs must guarantee a response within specified time constraints. A real-time operating system (RTOS) is an OS designed for real-time applications. FreeRTOS is an RTOS for embedded applications.

Some Benefits … Modularity: Software can be developed in the form of a number of tasks, each task having a well-defined function. Modularity helps team development, code reuse, and testing. Software can be entirely event driven, without wasting time and energy by polling for events that have not occurred. Highly responsive applications: ISRs can be made very short, by deferring processing to a task. Application development can be shorter and simpler when using the functions provided by the RTOS.

Some Drawbacks … A bare metal system has no OS. A bare metal approach may result in more efficient applications, but these may take more time develop. Some resources are reserved by the RTOS and are no longer available. The SysTick, SVCall, and PendSV interrupts are normally reserved. In principle, these could still be used with FreeRTOS by modifying the handler definitions of port.c.

TASKS The user writes the program in the form of a number of tasks. A task is implemented by a function that never returns. FreeRTOS provides a scheduler that ensures the user defined tasks run concurrently. CPU time is divided into slices. During each time slice, exactly one task uses the CPU. In this way, the tasks that are ready to run can share the CPU. Scheduling details will be covered in more detail later.

CREATING TASKS #include"FreeRTOS.h" #include"task.h“ BaseType_t xTaskCreate(TaskFunction_t pxTaskCode, const char* const pcName, \ const configSTACK_DEPTH_TYPE usStackDepth, void* const pvParameters, \ UBaseType_t uxPriority, TaskHandle_t* const pxCreatedTask ); The stack depth needs special attention: insufficient stack space may cause abnormal program execution and debugger malfunction. Due to limited RAM space (KL43 has 32KB), the stack cannot be too big. Stack depth has to be specified in words, not bytes. The stack is private; each task has its own stack.

CREATING TASKS—EXAMPLE void vTask1(void *pv) { volatile int z, v; for(;;) { z = id; v = SysTick->VAL; z = z + 1 + (int)pv; } void vTask3(void* pv) { volatile uint32_t z, u; u = (int)pv; for(z = 0;;) { id = u + 1; stck = SysTick->VAL; z = z + 2 + u; } int main(void) { … xTaskCreate(vTask1, "TASK A", configMINIMAL_STACK_SIZE + 10, 1, 0, NULL); xTaskCreate(vTask1, "TASK B", configMINIMAL_STACK_SIZE + 10, 2, 0, NULL); xTaskCreate(vTask3, "TASK P", configMINIMAL_STACK_SIZE + 100, 3, 0, NULL); vTaskStartScheduler(); // returns only if the scheduler cannot start for(;;); // the main function must not return return 0; // a return value has to be specified }

TASK STATES A task is Running when using the CPU. Ready when waiting for the CPU. Blocked when waiting for an event. Suspended when unavailable to the scheduler.

TASK PRIORITIES The user is free to define the priority of his tasks. The priority of a task is a number between 0 and configMAX_PRIORITIES – 1. A higher number indicates a higher priority. configMAX_PRIORITIES can be adjusted in FreeRTOSConfig.h. The default is: #define configMAX_PRIORITIES 5 In addition to the user defined tasks, the RTOS will also start the idle task and the timer service task. The idle task has 0 (minimum) priority. It frees the memory used by deleted tasks. The timer service task is used (among others) to manage user defined timers. By default, it has maximum priority: #define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES - 1)

TASK SCHEDULING The scheduling algorithm determines how the CPU is shared by the tasks. It can be selected in FreeRTOSConfig.h. The most common is Prioritized Preemptive Scheduling with Time Slicing. It is selected with: #define configUSE_PREEMPTION 1 #define configUSE_TIME_SLICING 1 The algorithm will not change task priority (fixed priority). A running task will be preempted when a higher priority task becomes ready. At any time, the running task will have a priority higher or equal than any ready task. Time slicing is used to share processing time between ready tasks of equal priority. A “take it in turn” policy (round robin scheduling) is used for tasks of equal priority. See section 3.12.

TASK SCHEDULING—TIME SLICES Any time a task becomes ready, if it has a higher priority than the running task, it will preempt it and start immediately to run. At the end of each time slice, if there are ready tasks of equal priority to the running task, a ready task will be selected and will run next. A time slice equals the interval between two SysTick interrupts. By default: #define configTICK_RATE_HZ ((TickType_t)200) See section 3.12.

TASK SCHEDULING—STARVATION If higher priority tasks are always ready or running, the low priority tasks will never be executed. A task that cannot enter the running state is said to be starved. If higher priority tasks never block to wait for events, lower priority tasks will be starved. When no user task can run, the idle task is run. The idle task (a zero priority always-ready task) must not be starved. If there are other ready tasks of zero priority, the idle task can be configured to yield before finishing its time slice. The default is #define configIDLE_SHOULD_YIELD 1

TASK SCHEDULING—SAVING ENERGY Normally, the idle task runs when nothing else can run. The idle task includes an infinite loop. A callback function (the idle hook function) can be called from each iteration. This function can set the CPU in a low power mode. To enable the idle hook function: #define configUSE_IDLE_HOOK 1 The prototype of the idle hook function is void vApplicationIdleHook( void ); Example: void vApplicationIdleHook(void) { __asm volatile ("wfe"); // wait for interrupt; CPU waits in low power mode }

TASK SCHEDULING—USEFUL HOOKS Other callback functions that may be helpful (must be enabled before use): void vApplicationTickHook( void ); // called after a SysTick interrupt void vApplicationStackOverflowHook( TaskHandle_t xTask, char *pcTaskName ); // called when the stack of xTask overflows void vApplicationMallocFailedHook( void ); // called if out of memory Enabled with #define configUSE_TICK_HOOK 1 #define configCHECK_FOR_STACK_OVERFLOW 1 #define configUSE_MALLOC_FAILED_HOOK 1

QUEUES A queue is a first in first out (FIFO) data structure allowing one or more sender processes to send data to one or more receiver processes. Some useful functions (available via #include"queue.h" ): QueueHandle_t xQueueCreate( UBaseType_t uxQueueLength, UBaseType_t uxItemSize ); BaseType_t xQueueSend( QueueHandle_t xQueue, const void *pvItemToQueue, TickType_t xTicksToWait ); BaseType_t xQueueReceive( QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait );

QUEUES A process that sends an item to a full queue will be blocked until the queue is no longer full or the timeout expires. A process that attempts to take one item from an empty queue will be blocked until the queue is no longer empty or the timeout expires. The timeout is specified by xTicksToWait. If INCLUDE_vTaskSuspend is enabled (this is the default) and xTicksToWait == portMAX_DELAY, then the task will wait indefinitely (no timeout). Otherwise, the timeout will have xTicksToWait tick periods. (The definition of configTICK_RATE_HZ specifies the tick frequency in Hz.) ISRs may only call the FromISR version of functions, such as xQueueSendFromISR and xQueueReceiveFromISR.

IMPORTANT! FreeRTOS has two versions of functions: One for code executed from ISRs. One for code that is not executed from ISRs. The functions that may be called from ISRs have the FromISR suffix. The functions that may be called from other contexts do not have this suffix. NOT FROM ISR FROM ISR xQueueSend xQueueSendFromISR xQueueReceive xQueueReceiveFromISR xQueueCreate —

INTERRUPTS To ensure system responsiveness, an ISR should be short. The ISR should Process the operations that need immediate attention (e.g. clear flags). Defer lengthy operations to a task. There are several ways to defer data processing to a task. The ISR writes data to a queue and a task reads it and processes it. With a pendable function executed by the timer service task. The ISR signals a task that data is ready by means of a semaphore. …

PENDABLE FUNCTIONS An ISR can ask the timer service task to run a certain function. The timer service task will process the request when it will run. BaseType_t xTimerPendFunctionCallFromISR(PendedFunction_t vFunction, void *pvParam1, uint32_t ulParam2, BaseType_t *pxHigherPriorityTaskWoken); Format of pended function: void vFunction( void *pvParam1, uint32_t ulParam2 ); Example: void TPM1_IRQHandler(void) { BaseType_t woken = pdFALSE; TPM1->SC |= TPM_SC_TOF_MASK; // clear the flag bit xTimerPendFunctionCallFromISR(vTimerPendFn3, 0, 0, &woken); portYIELD_FROM_ISR(woken); }

PENDABLE FUNCTIONS By using portYIELD_FROM_ISR(woken), the example ensures that if the task interrupted by the interrupt has a lower priority than the timer service task, the system will switch to the latter and execute it right-away. By default, the timer service task has the highest task priority: #define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES - 1) When the ISR asks the timer service task to execute the function, the request is placed into a queue. The timer service task reads commands from the queue and executes them. The default queue length is: #define configTIMER_QUEUE_LENGTH 10

SEMAPHORES ISRs can defer a function call to the timer service task. Processing can also be deferred to other tasks by means of semaphores. A binary semaphore is similar to a queue of length 1. The queue is full when it has an item and empty otherwise. A binary semaphore can be used for deferred processing as follows: A task waits in the blocked state until the semaphore is given. When the ISR occurs, it gives the semaphore, unblocking in this way the task. The task takes the semaphore and performs the deferred processing.

SOME REMARKABLE FUNCTIONS #include“semphr.h” SemaphoreHandle_t xSemaphoreCreateBinary( void ); BaseType_t xSemaphoreGiveFromISR(SemaphoreHandle_t xSemaphore,\ BaseType_t *pxHigherPriorityTaskWoken ); BaseType_t xSemaphoreTake( SemaphoreHandle_t xSemaphore, \ TickType_t xTicksToWait ); void vSemaphoreDelete( SemaphoreHandle_t xSemaphore );

IMPORTANT! Some FreeRTOS functions (see xSemaphoreGiveFromISR) may not be called before the task scheduler has started. The following function can be used to check the scheduler state: #include"task.h" BaseType_t xTaskGetSchedulerState( void );

EXAMPLE SemaphoreHandle_t semA; void vTaskPB(void *pv) { int main(void) { … semA = xSemaphoreCreateBinary(); vTaskStartScheduler(); } void vTaskPB(void *pv) { // The task waiting for the semaphore while(1) { xSemaphoreTake(semA, portMAX_DELAY); printf("\nThe semaphore was taken."); } void PORTA_IRQHandler(void) { // The ISR giving the semaphore BaseType_t woken = pdFALSE; PORTA->PCR[4] |= PORT_PCR_ISF_MASK; // clear the interrupt flag if(xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) { xSemaphoreGiveFromISR(semA, &woken); portYIELD_FROM_ISR(woken); }

MUTUAL EXCLUSION Tasks and ISRs may share common resources, such as variables. Inconsistent and wrong results may occur when more than one task or ISR attempt to use a shared resource at the same time. It is necessary to ensure that the critical sections of code that access a shared resource have exclusive access to the resource. Mutual exclusion can be ensured with semaphores. FreeRTOS provides mutex semaphores for mutual exclusion.

MUTUAL EXCLUSION Mutex semaphores and binary semaphores differ in several respects: Different initial state: a mutex semaphore can be taken as soon as it is created. A binary semaphore has to be given before being taken. The semaphore must be returned: A task or ISR taking a mutex semaphore, has to give it back. Otherwise, no other task or ISR can use the shared resource. Priority inheritance: A task holding a mutex semaphore inherits the highest priority among the tasks waiting for the semaphore. This is done in order to avoid priority inversion.

EXAMPLE Implement mutual exclusion between the critical sections of tasks A and B. Note the function used to create mutex semaphores. void vTaskA(void *pv) { while(1) { xSemaphoreTake(mtx, portMAX_DELAY); // The critical section begins … // The critical section ends xSemaphoreGive(mtx); } SemaphoreHandle_t mtx; int main(void) { … mtx = xSemaphoreCreateMutex(); vTaskStartScheduler(); } void vTaskB(void *pv) { while(1) { xSemaphoreTake(mtx, portMAX_DELAY); // The critical section begins … // The critical section ends xSemaphoreGive(mtx); }

INTERRUPTS—CONFIGURATION Mutual exclusion is enforced by disabling interrupts. In this way the critical section code cannot be interrupted. Cortex-M3 cores and higher, allow disabling all interrupts that have a priority below a prespecified level. FreeRTOS uses this feature in order to implement mutual exclusion. Given the maximum priority of the interrupts that use RTOS functions, mutual exclusion is implemented by disabling all interrupts of lower or equal priority.

INTERRUPTS—CONFIGURATION FreeRTOS needs to know The lowest interrupt priority (the tick interrupt uses it). The highest priority of the interrupts that call RTOS functions. A critical section is created by writing configMAX_SYSCALL_INTERRUPT_PRIORITY into the Cortex-M BASEPRI register. This disables interrupts of lower or equal priority. As priority 0 interrupts (the highest priority possible) cannot be masked with BASEPRI, configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. Example: Specify the lowest priority of K22 and set the highest priority to 1. #define configKERNEL_INTERRUPT_PRIORITY 0b11100000 //see section 3.2.2.1 #define configMAX_SYSCALL_INTERRUPT_PRIORITY 0b00100000 // Lowest priority on KL43 (see section 3.2.1) is 3 (0b11000000). See for more details https://www.freertos.org/RTOS-Cortex-M3-M4.html

PRIORITIES Both tasks and interrupts have priorities. The priority of tasks determines the order in which the RTOS schedules them. The priority of interrupts determines the order in which the NVIC of the ARM core responds to concurrent requests. Task and interrupt priorities are completely unrelated. Any enabled interrupt can interrupt any task (of any priority). The lowest priority interrupt can interrupt the highest priority task. The tick interrupt, which is used for scheduling tasks, has normally the lowest interrupt priority. See for more details https://www.freertos.org/RTOS-Cortex-M3-M4.html

DELAYS void vTaskDelay( TickType_t xTicksToDelay ); #include"FreeRTOS.h" #include"task.h“ void vTaskDelay( TickType_t xTicksToDelay ); This function blocks the task for xTicksToDelay ticks. The definition of configTICK_RATE_HZ specifies the tick frequency in Hz. Examples: vTaskDelay(100); // blocks the task for 100 ticks vTaskDelay(pdMS_TO_TICKS(100)); //blocks for 100 milliseconds