From 48db68fe3ced49ea0a47dd35ee43896ccbff7e59 Mon Sep 17 00:00:00 2001 From: corvus Date: Tue, 13 Jul 2010 18:55:26 +0000 Subject: [PATCH] add some self made FreeRTOS scheduler documentation git-svn-id: svn://svn.openpilot.org/OpenPilot/trunk@1088 ebee16cc-31ac-478f-84a7-5cbb03baadba --- .../GCC/Posix/port.c.documentation.txt | 188 ++++++++++++++++++ 1 file changed, 188 insertions(+) create mode 100644 flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/port.c.documentation.txt diff --git a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/port.c.documentation.txt b/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/port.c.documentation.txt new file mode 100644 index 000000000..022ab59df --- /dev/null +++ b/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/port.c.documentation.txt @@ -0,0 +1,188 @@ +File: port.c.documentation.txt +Author: Corvus Corax +Desc: Description of port.c Functions and Directions about porting. +See FreeRTOS documentation ebook for details. + + +FreeRTOS is an architecture independent real time operating system. +Most architecture dependant code sits in a single file: port.c +Architecture dependant definitions sit in: portmacro.h + +Other important files: + +Source/portable/MemMang/head_3.c - memory management - very simple. Provides +functions like malloc and free - very easy to make a wrapper for on any system +that provides memory management. + +FreeRTOS has internal scheduling. The real time scheduler sits in Source/task.c and calls low level functions of port.c for thread management. + +For that port.c needs to provide functions to switch between threads on +request, as well as a tick handler that preempts threads on a periodic basis. + +Only one FreeRTOS thread is active at any time! + + +port.c provides the API defined in portmacro.h. + +Only a subset of the functions is explained here (with the naming from the +posix port. Their macros are sometimes named a bit different) + + +void vPortEnterCritical(void); + +This function is called if a thread enters a "critical section". +In a critical sections the thread must not be preempted. + +(To preempt a thread means to halt its execution when a timer interrupt comes +in, and give execution to another thread) +This function should increase a counter for that thread, since several +"Critical Sections" could be cascaded. Only if the outermost critical section +is exited, is preemtion allowed again. + +void vPortExitCritical(void); +This function is called if a thread leaves a "critical section". +If a thread leaves the outermost critical section, the scheduler is allowed to +preempt it on timer interrupt (or other interrupts) + + +void vPortEnableInterrupts(void); +void vPortDisableInterrupts(void); + +functions to enable and disable interrupts. On "real systems" this means all +interrupts including IO. When "simulating" this means the tick handler/ timer +/ timer interrupt. The tick handler is supposed to not do anything if interrupts are disabled. + + +portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, +pdTASK_CODE pxCode, void *pvParameters ); + +Used to initialize a new thread. The stack memory area, command line +parameters for this task and the entry function (pxCode) are given + +This function needs to initialize the new task/thread, but suspend it +immediately. It is only to be executed later if the scheduler says so. + +returns pxTopOfStack if success and 0 on failure. + +THIS WILL BE THE FIRST FUNCTION FreeRTOS CALLS. +The first thread to be created is likely the idle thread. At this time the +scheduler has not been started yet. Therefore it's important to start all +threads in suspended state! + +void vPortEndScheduler(void); + +Needs to end the scheduler (and as such all Tasks/threads) This means FreeRTOS +terminates - as in (simulated) system shutdown. + + +portBASE_TYPE xPortStartScheduler(void); + +This function doesn't return until someone (another thread) calls +vPortEndScheduler(). You can set up your timer and tick handler here and start +the first thread. Then do what a scheduler does (manage threads) + + +vPortYield() + +Sometimes threads go sleeping on purpose (for example during one of FreeRTOS +system calls - including sleep() ) +This function should send the thread that calls it into suspended state and +not return until the scheduler gives back execution to this thread. + + +=========== +The scheduler. + +What your scheduler needs to do: + +Basically what your self written scheduler is allowed to do is the "dirty +work" for the high level scheduler logic provided by FreeRTOS task.c + +The scheduler is supposed to run a timer interrupt/tick handler that gets +called every portTICK_RATE_MICROSECONDS microseconds. +That value is defined somewhere in OpenPilot and has to be exact as well as +the same on all architectures. + +If you cannot set up a timer with that accuracy you are screwed! + +Anyway. Every time the timer tick happens, you have to + +- check whether you are allowed to execute the tick handler. + If interrupts are disabled and/or the thread is in a critical section, the + tick handler should do nothing + +- Tell FreeRTOS that the tick has happened + Increment the Tick Count using the FreeRTOS function + vTaskIncrementTick(); + +- If preemption is enabled (and in OpenPilot it is!) + Tell the high level Scheduler of FreeRTOS to do its magic, using the + function + vTaskSwitchContext(); + +- You can find out which thread is SUPPOSED to be running with the function + xTaskGetCurrentTaskHandle(); + +- If this is for some reason not the currently running thread, SUSPEND that + thread with whatever method possible (signals, events, operating system + thread.suspend() - I don't know how to do that in Qt. + +- Make the thread returned by xTaskGetCurrentTaskHandle() resume operation as + normal. + +- Make sure that when you return from the tick handler, exactly one thread is + running and that is the one by xTaskGetCurrentTaskHandle() and all others + are suspended! + + + +On top of that, threads can suspend themselves just like that. That happens +every time they call any blocking FreeRTOS function. + +They do that with above mentioned function + +vPortYield() + +When vPortYield is called your scheduler must: + +- Tell the high level Scheduler of FreeRTOS to do its magic, using the + function + vTaskSwitchContext(); + +- You can then find out which thread is SUPPOSED to be running with the function + xTaskGetCurrentTaskHandle(); + +- Make sure that the thread calling this function SUSPENDS and the thread + returned by xTaskGetCurrentTaskHandle() gets executed. Be aware that they + could be the same in which case vPortYield does exactly NOTHING! + +- This function does not return (since the current thread is sent to sleep) + until the scheduler makes it wake up - either by the tick handler, or by + another thread calling vPortYield(). + +- So it must not ever return until xTaskGetCurrentTaskHandle() says the + calling thread is the current task handle. + +- Then it returns to the caller. + + + +===== + +What emthod you use to send threads/tasks to sleep and wake them up again is +up to you. + +The posix implementation uses signals and a signal handler in each thread that +sleeps until a resume signal is received + +The native STM32 implementation manually switches contexts by and uses actual +system interrupts +(so does the native x86 implementation) + +The native Win32 implementation uses win32 API calls to manipulate windows +threads (windows actually provides a call to remote-suspend and resume a +thread - posix doesn't) + +I have no clue what measures for thread control and suspension/interruption Qt +offers. (I hope there are some) +