finish assignment 4.5

This commit is contained in:
Laila van Reenen 2025-10-02 18:06:29 +02:00
parent b72fea6fc4
commit 8a9e02559a
Signed by: LailaTheElf
GPG Key ID: 8A3EF0226518C12D
3 changed files with 222 additions and 70 deletions

View File

@ -266,9 +266,141 @@ void SVC_Handler(void)
}
```
This code worked. The resulting code can be found at [/report-1/week_1.4/assignment_4.4/](https://git.gay/LailaTheElf/RTS10_reports/src/branch/main/report-2/week_1.4/assignment_4.4).
This code worked. The resulting code can be found at [/report-2/week_1.4/assignment_4.4/](https://git.gay/LailaTheElf/RTS10_reports/src/branch/main/report-2/week_1.4/assignment_4.4).
![](https://live.kladjes.nl/uploads/fb408589-67d1-4b37-8eb2-f852c65575f8.png)
## assignment 4.5
> The current scheduler implements a round-robin algorithm. In a real-time situation it would be necessary to give tasks different priorities in order to make important deadlines.
> A) In reality tasks have more important jobs to do than just toggling a LED. This means tasks will take time. Use the original blocking delay function to give tasks a realistic waiting time in a random amount of milliseconds. In order to verify timing requirements with a logic analyzer, you can toggle the LED at the end of the busy waiting period.
The LED is turn on while the task is await, and of when it is sleeping.
| | green | orange | red | blue |
| -------------- | ------ | ------ | ------ | ------ |
| blocking_delay | 100 ms | 200 ms | 300 ms | 400 ms |
| delay (sleep) | 100 ms | 200 ms | 300 ms | 400 ms |
```c
void toggleGreen(void)
{
while(1)
{
GPIOD->ODR |= 1 << GREEN;
blocking_delay(100);
GPIOD->ODR &= ~(1 << GREEN);
delay(100-1);
}
}
void toggleOrange(void)
{
while(1)
{
GPIOD->ODR |= 1 << ORANGE;
blocking_delay(200);
GPIOD->ODR &= ~(1 << ORANGE);
delay(200-1);
}
}
void toggleRed(void)
{
while(1)
{
GPIOD->ODR |= 1 << RED;
blocking_delay(300);
GPIOD->ODR &= ~(1 << RED);
delay(300-1);
}
}
void toggleBlue(void)
{
while(1)
{
GPIOD->ODR |= 1 << BLUE;
blocking_delay(400);
GPIOD->ODR &= ~(1 << BLUE);
delay(400-1);
}
}
```
> B) Implement a priority based scheduling algorithm. When adding tasks you should be able to pass the priority. When there are multiple tasks available with the same priority a round-robin algorithm should be applied. Test this functionality for multiple tasks with and without non-blocking delays.
The priority is already passed with the `addTaskToList` function and this is saved in the task struct. I did update the priorities to have green as the highest priority, then orange, red and blue has the lowest priority.
```c
addTaskToList(toggleGreen, 128, 2);
addTaskToList(toggleOrange, 128, 3);
addTaskToList(toggleRed, 128, 4);
addTaskToList(toggleBlue, 128, 5);
```
> C) The round-robin period thus far equaled the SysTick period. Implement the ability to have a task-dependent round-robin period. E.g. if taskA and taskB have equal priorities, TaskA will run 2 SysTicks, taskB will need 5 SysTicks. This period should also be something passed at task creation. Verify this functionality with a logic analyzer.
I added a new pointer `nextTaskPtr` to store the highest priority task that is ready. The do while loop is updated to first filter all task tasks that aren't ready than if there is no task yet in `nextTaskPtr` it should not compare priorities. Otherwise check if it has a higher priority than the current `nextTaskPtr`, if so replace it.
```c
task * schedule()
{
task* nextTaskPtr = NULL;
task* tempTaskPtr = currentTask;
task* idleTaskPtr = &taskList[IDLE_TASK];
int teller=0;
do
{
tempTaskPtr++;
if( (tempTaskPtr-1) == idleTaskPtr || tempTaskPtr == idleTaskPtr)
{
//since idle task is the last in the list, we've reached the end
//and need to continue at the beginning
tempTaskPtr = &taskList[0];
}
if (tempTaskPtr->state != READY)
{
continue;
}
if (nextTaskPtr == NULL)
{
nextTaskPtr = tempTaskPtr;
continue;
}
if (tempTaskPtr->priority < nextTaskPtr->priority)
{
nextTaskPtr = tempTaskPtr;
continue;
}
} while (teller++ < MAX_TASKS);
//if no task was found
if(nextTaskPtr == NULL)
{
//idle task
nextTaskPtr = idleTaskPtr;
}
return nextTaskPtr;
}
```
The full code is available at [/report-2/week_1.4/assignment_4.5/](https://git.gay/LailaTheElf/RTS10_reports/src/branch/main/report-2/week_1.4/assignment_4.5).
### Testing
![](https://live.kladjes.nl/uploads/cbbdbcdb-0484-4074-8112-4a48b80f424f.png)
Green (`D0`) has the highest priority, so it starts. Orange (`D2`) follows after the $100ms$ green is taking, orange should take $200ms$ but green is correctly halting orange.
![](https://live.kladjes.nl/uploads/a3e2237d-2099-4695-a943-b447098f3ef5.png)
It is also clearly viable that red (`D1`) and blue (`D3`) have lower priorities. It seems to work correctly.

View File

@ -37,6 +37,7 @@ void writePSP(void * ptr);
void returnToPSP(void);
void returnToMSP(void);
void toUnprivileged(void);
uint32_t* getStackpointer(void);
#define TASK_MASK MAX_TASKS-1
#define IDLE_TASK MAX_TASKS
@ -158,14 +159,12 @@ void startVersdOS(uint16_t sysTickPeriodIn_ms) {
// currentTask is running now, return next task to run
task * schedule()
{
task* nextTaskPtr = NULL;
task* tempTaskPtr = currentTask;
task *idleTaskPtr = &taskList[IDLE_TASK];
// tempTaskPtr->state = READY;
task* idleTaskPtr = &taskList[IDLE_TASK];
int teller=0;
//Find next ready, non idle task.
do
{
tempTaskPtr++;
@ -176,16 +175,33 @@ task * schedule()
//and need to continue at the beginning
tempTaskPtr = &taskList[0];
}
}while(tempTaskPtr->state != READY && teller++ <= MAX_TASKS);
//if no task was found
if(tempTaskPtr->state != READY)
if (tempTaskPtr->state != READY)
{
//idle task
tempTaskPtr = idleTaskPtr;
continue;
}
return tempTaskPtr;
if (nextTaskPtr == NULL)
{
nextTaskPtr = tempTaskPtr;
continue;
}
if (tempTaskPtr->priority < nextTaskPtr->priority)
{
nextTaskPtr = tempTaskPtr;
continue;
}
} while (teller++ < MAX_TASKS);
//if no task was found
if(nextTaskPtr == NULL)
{
//idle task
nextTaskPtr = idleTaskPtr;
}
return nextTaskPtr;
}
// flag used in blocking_delay function

View File

@ -27,7 +27,9 @@ void toggleGreen(void)
{
while(1)
{
GPIOD->ODR ^= 1 << GREEN;
GPIOD->ODR |= 1 << GREEN;
blocking_delay(100);
GPIOD->ODR &= ~(1 << GREEN);
delay(100-1);
}
}
@ -36,7 +38,9 @@ void toggleOrange(void)
{
while(1)
{
GPIOD->ODR ^= 1 << ORANGE;
GPIOD->ODR |= 1 << ORANGE;
blocking_delay(200);
GPIOD->ODR &= ~(1 << ORANGE);
delay(200-1);
}
}
@ -45,8 +49,10 @@ void toggleRed(void)
{
while(1)
{
GPIOD->ODR ^= 1 << RED;
delay(400-1);
GPIOD->ODR |= 1 << RED;
blocking_delay(300);
GPIOD->ODR &= ~(1 << RED);
delay(300-1);
}
}
@ -54,12 +60,10 @@ void toggleBlue(void)
{
while(1)
{
GPIOD->ODR ^= 1 << BLUE;
delay(800-1);
setSysTick_10ms();
GPIOD->ODR ^= 1 << BLUE;
delay(800-1);
setSysTick_1ms();
GPIOD->ODR |= 1 << BLUE;
blocking_delay(400);
GPIOD->ODR &= ~(1 << BLUE);
delay(400-1);
}
}
@ -107,9 +111,9 @@ int main(void)
// Create tasks. Provide fpointer, stacksize, and priority:
addTaskToList(toggleGreen, 128, 2);
addTaskToList(toggleOrange, 128, 2);
addTaskToList(toggleRed, 128, 2);
addTaskToList(toggleBlue, 128, 2);
addTaskToList(toggleOrange, 128, 3);
addTaskToList(toggleRed, 128, 4);
addTaskToList(toggleBlue, 128, 5);
// Start VersdOS with 1 ms sysTick
startVersdOS(1);