# PeriodicScheduler_Semaphore
**Repository Path**: End-ING/PeriodicScheduler_Semaphore
## Basic Information
- **Project Name**: PeriodicScheduler_Semaphore
- **Description**: PeriodicScheduler_Semaphore
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2026-10-06
- **Last Updated**: 2026-10-18
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# Real-Time Operating Systems (RTOS)
Task scheduling is an important concept in Real-Time Operating Systems (Task, thread, process are interchangeable). Take your daily life for example, when trying to listen to music on your cellphone while surfing news websites through the internet (receiving data from wi-fi router in the meantime). How does it work under only one core of CPU (CPU can only execute one command at a time)? Each task such as open the browser may require hundred or thousand lines of codes, then how can we listen to music and open websites at the same time? It comes to task scheduling. We will use STM32F411RE Nucleo64 and ST7735S TFT LCD to demonstrate the concept. If any reference link in this tutorial cannot be accessed, please refer to the Reference folder above.
1. [What is the Goal](https://github.com/Dungyichao/PeriodicScheduler_Semaphore#1-what-is-the-goal-)
2. [Basic Knowledge](https://github.com/Dungyichao/PeriodicScheduler_Semaphore#2-basic-knowledge-)
3. [Code Concept of Preemptive Scheduling with Round Robin](https://github.com/Dungyichao/PeriodicScheduler_Semaphore#3-code-concept-of-preemptive-scheduling-with-round-robin-)
* 3.1 [The Essential Elements of the Code](https://github.com/Dungyichao/PeriodicScheduler_Semaphore#31-the-essential-elements-of-the-code)
* 3.2 [Implement Task, Stack, Thread Control Block and Context Switch](https://github.com/Dungyichao/PeriodicScheduler_Semaphore#32-implement-task-stack-thread-control-block-and-context-switch-)
* 3.2.1 [Task](https://github.com/Dungyichao/PeriodicScheduler_Semaphore#321-task-)
* 3.2.2 [Stack](https://github.com/Dungyichao/PeriodicScheduler_Semaphore#322-stack-)
* 3.2.3 [Thread Control Block](https://github.com/Dungyichao/PeriodicScheduler_Semaphore#323-thread-control-block-)
* 3.2.4 [Context Switch (Part I)](https://github.com/Dungyichao/PeriodicScheduler_Semaphore#324-context-switch-part-i-)
* 3.2.5 [Context Switch (Part II)](https://github.com/Dungyichao/PeriodicScheduler_Semaphore#325-context-switch-part-ii-)
* 3.2.6 [Configure SysTick](https://github.com/Dungyichao/PeriodicScheduler_Semaphore#326-configure-systick-)
* 3.3 [Result](https://github.com/Dungyichao/PeriodicScheduler_Semaphore#33-result-)
* 3.4 [Non-preemptive method (Optional)](https://github.com/Dungyichao/PeriodicScheduler_Semaphore#34-non-preemptive-method-optional)
4. [Process Synchronization](https://github.com/Dungyichao/PeriodicScheduler_Semaphore#4-process-synchronization)
* 4.1 [Spin-lock semaphore](https://github.com/Dungyichao/PeriodicScheduler_Semaphore#41-spin-lock-semaphore-)
* 4.2 [Cooperative spin-lock semaphore](https://github.com/Dungyichao/PeriodicScheduler_Semaphore#42-cooperative-spin-lock-semaphore-)
* 4.3 [Rendezvous (Optional)](https://github.com/Dungyichao/PeriodicScheduler_Semaphore#43-rendezvous-optional)
5. [Implement on LCD](https://github.com/Dungyichao/PeriodicScheduler_Semaphore#5-implement-on-lcd-)
* 5.1 [Configure CubeMX](https://github.com/Dungyichao/PeriodicScheduler_Semaphore#51-configure-cubemx-)
* 5.2 [Download code and Copy to our project](https://github.com/Dungyichao/PeriodicScheduler_Semaphore#52-download-code-and-copy-to-our-project-)
* 5.3 [Fix the duplicate SysTick_Handler problem in the code](https://github.com/Dungyichao/PeriodicScheduler_Semaphore#53-fix-the-duplicate-systick_handler-problem-in-the-code-)
* 5.4 [Include header file and clear out comment in main.c](https://github.com/Dungyichao/PeriodicScheduler_Semaphore#54-include-header-file-and-clear-out-comment-in-mainc-)
* 5.5 [Compile and Download to the board](https://github.com/Dungyichao/PeriodicScheduler_Semaphore#55-compile-and-download-to-the-board)
------------------------------------Advance (Optional)-------------------------------------------
6. [Using PendSV for Context Switch](https://github.com/Dungyichao/PeriodicScheduler_Semaphore/blob/master/README.md#6-using-pendsv-thread-switcher)
7. [Period Scheduling](https://github.com/Dungyichao/PeriodicScheduler_Semaphore#7-period-scheduling)
* 7.1 [Method 1 - Multiple Periodic Threads](https://github.com/Dungyichao/PeriodicScheduler_Semaphore#71-method-1---multiple-periodic-threads)
* 7.2 [Method 2 - Timer Interrupts](https://github.com/Dungyichao/PeriodicScheduler_Semaphore#72-method-2---timer-interrupts)
* 7.3 [Method 3 - Thread Control Blocks (TCB)](https://github.com/Dungyichao/PeriodicScheduler_Semaphore#73-method-3---thread-control-blocks-tcb)
* 7.4 [TCB + Timer Interrupts](https://github.com/Dungyichao/PeriodicScheduler_Semaphore#74-tcb--timer-interrupts)
* 7.5 [Method 4 - Thread Sleep](https://github.com/Dungyichao/PeriodicScheduler_Semaphore/blob/master/README.md#75-method-4---thread-sleep)
8. [Other Scheduling Method](https://github.com/Dungyichao/PeriodicScheduler_Semaphore/blob/master/README.md#8-other-scheduling-method)
* 8.1 [Priority Scheduling](https://github.com/Dungyichao/PeriodicScheduler_Semaphore/blob/master/README.md#81-priority-scheduling)
* 8.2 [Sporadic Scheduling](https://github.com/Dungyichao/PeriodicScheduler_Semaphore/blob/master/README.md#82-sporadic-scheduling)
* 8.3 [Fixed Scheduling](https://github.com/Dungyichao/PeriodicScheduler_Semaphore/blob/master/README.md#83-fixed-scheduling)
9. [Inter-Thread Data Transfer](https://github.com/Dungyichao/PeriodicScheduler_Semaphore/blob/master/README.md#9-inter-thread-data-transfer)
10. [Reference and conclusion](https://github.com/Dungyichao/PeriodicScheduler_Semaphore/blob/master/README.md#10-reference-and-conclusion)
# 1. What is the Goal
Let's first take a look at what are we going to achieve after this tutorial.
| Task scheduling | Detail |
|---|---|
| Preemptive Scheduling | The resources (mainly CPU cycles) are allocated to the process for the limited amount of time and then is taken away, and the process is again placed back in the ready queue if that process still has CPU burst time remaining. That process stays in ready queue till it gets next chance to execute. Algorithms: Round Robin (RR),Shortest Remaining Time First (SRTF), Priority (preemptive version), etc. |
| Non-Preemptive Scheduling | Once the resources (CPU cycles) is allocated to a process, the process holds the CPU till it gets terminated or it reaches a waiting state. In case of non-preemptive scheduling does not interrupt a process running CPU in middle of the execution. Instead, it waits till the process complete its CPU burst time and then it can allocate the CPU to another process. Algorithms: Shortest Job First (SJF basically non preemptive) and Priority (non preemptive version), etc. |
| Item | Example |
|---|---|
| Registers | Registers store value for CPU fetching or storing temporary data. The data accessing speed of registers is way more faster than RAM. |
| Stack | We assign a place in RAM as stack. When exception happens, CPU would store some of the registers value into the stack. After the CPU finish handling the exception, CPU can restore those data (stored in the stack) back to registers and keep doing on what the CPU has left. |
| Element | Concept |
|---|---|
| Registers | R0~R12: General-purpose registers. Maybe store the function parameter, store the function return value R13(SP): Stack Pointer. There are 2 kinds, Main Stack Pointer(MSP) and Process Stack Pointer(PSP). When an exception happens, a stack frame (R0~R3, R12, R14, R15, xPSR) gets pushed to the currently active stack pointer. R14(LR):Link Register. LR is used to store the return program counter (PC) when a subroutine or function is called. On reset, the processor loads the LR value 0xFFFFFFFF. R15(PC):Program Counter. It store the address of the next command or instruction. xPSR:Special-purpose Program Status Registers. The reset value is 0x01000000. * ASPR: contains the current state of the condition flags from previous instruction executions. * IPSR: contains the exception type number of the current Interrupt Service Routine(ISR). * EPSR: contains the Thumb state bit, and the execution state bits. |
| Stack | Think of the stack as a container which implement Last-In-First-Out(LIFO) rule. Take a look at the following animation to understand the stack operation rule.
However, Cortex-M4 implements the stack in a different way. It implements a full-descending stack(http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0552a/BABIAJHJ.html) .
|
| Task | Keep doing some jobs in a task. Let's take a look at a simple task we are going to implement in our tutorial.
void TaskX(void)
{
while(true)
{
countX = countX + 1;
}
}
This is simply a function with no return value and no input parameter. Inside the function is a while loop which will never stop. We will have three tasks, Task0(keep counting count0), Task1(keep counting count1), Task2(keep counting count2). In normal conditions, whenever you enter a while(true) loop, you will never go out this loop until you close the program because the condition is always true. You can add more instructions inside the while loop. |
| Context Switch | The operation of switching from one task to another is known as a context switch. A Real Time Operating System (RTOS) will typically provide this functionality. Reference link: (https://interrupt.memfault.com/blog/cortex-m-rtos-context-switching) We have three tasks and each task keep doing their own job without breaking the loop, then how can we do task0, task1, task2? Context switch comes to the place and will switch the task to another and then after visiting all the tasks, it will come back loop through all the tasks again and again. |
| Exception | Exception is anything that breaks the normal program flow, and invokes a handler from the vector table, and Interrupts are a subset of Exceptions, coming from the peripherals outside the ARM core. Exceptions have an Exception Number, starting from 0. Interrupts (IRQ) have an IRQ Number, starting from 0. Because all Interrupts are Exceptions, they all get an Exception Number, which is 16 higher than the IRQ Number. Exceptions that are not Interrupts have IRQ Numbers too, which by extension fall into the range from -16 to -1.
In this section, we only use Systick as a trigger to let us perform the context switch. A SysTick exception is an exception the system timer generates when it reaches zero. Software can also generate a SysTick exception. In an OS environment, the processor can use this exception as system tick. Reading resource: https://interrupt.memfault.com/arm-cortex-m-exceptions-and-nvic#built-in-exceptions |
| Thread Control Block | Think of this as a summary of all the tasks. It should contain the information of where the current task's information and where is the next task information. |
| Configure | Detail | Purpose |
|---|---|---|
| Timers: TIM2 | Clock Source: Internal Clock Prescaler: 16000 Counter Period: 1 Trigger Event Selection: Update Event NVIC Settings: click enabled |
For HAL_Delay function. Important for LCD initialization |
| Connectivity: SPI1 | Mode: Transmit Only Master Prescaler: 32 SPI1_MOSI: PB5 SPI1_SCK: PB3 |
For STM32F411 Nucleo64 board sending data to LCD |
| GPIO_Output | PB15: Name it to LCD_CS PB14: Name it to LCD_RS PB12: Name it to LCD_RST |
For assisting STM32F411 Nucleo64 board sending data to LCD |
| Clock Configure | HCLK (MHz): 16 |
Slow down the clock |
| Configure | Detail |
|---|---|
| RCC Register | To enable the clock of TIM3, we need to set the bit1 of RCC_APB1ENR to 1
|
| TIMx->PSC | TIMx prescaler
|
| TIMx->ARR | TIMx auto-reload register
|
| TIMx->CR1 | TIMx control register 1
|
| TIMx->DIER | TIMx DMA/Interrupt enable register
|
| NVIC_EnableIRQ | Functions to access the Nested Vector Interrupt Controller (NVIC). To enable certain interrupt according it's IRQ number.
https://www.keil.com/pack/doc/CMSIS/Core/html/group__NVIC__gr.html
|
| TIMx->SR | TIMx status register
|