finish assignment 4.5
This commit is contained in:
parent
b72fea6fc4
commit
8a9e02559a
@ -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).
|
||||
|
||||

|
||||
|
||||
|
||||
## 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
|
||||
|
||||

|
||||
|
||||
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.
|
||||
|
||||

|
||||
|
||||
It is also clearly viable that red (`D1`) and blue (`D3`) have lower priorities. It seems to work correctly.
|
||||
@ -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 (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(tempTaskPtr->state != READY)
|
||||
if(nextTaskPtr == NULL)
|
||||
{
|
||||
//idle task
|
||||
tempTaskPtr = idleTaskPtr;
|
||||
nextTaskPtr = idleTaskPtr;
|
||||
}
|
||||
|
||||
return tempTaskPtr;
|
||||
return nextTaskPtr;
|
||||
}
|
||||
|
||||
// flag used in blocking_delay function
|
||||
|
||||
@ -15,20 +15,22 @@
|
||||
// keep the CPU busy for at least ticks SysTicks
|
||||
void blocking_delay(unsigned int ticks)
|
||||
{
|
||||
while (ticks != 0) {
|
||||
extern bool SysTick_flag;
|
||||
while (SysTick_flag == false); // busy wait
|
||||
SysTick_flag = false;
|
||||
ticks--;
|
||||
}
|
||||
while (ticks != 0) {
|
||||
extern bool SysTick_flag;
|
||||
while (SysTick_flag == false); // busy wait
|
||||
SysTick_flag = false;
|
||||
ticks--;
|
||||
}
|
||||
}
|
||||
|
||||
void toggleGreen(void)
|
||||
{
|
||||
while(1)
|
||||
{
|
||||
GPIOD->ODR ^= 1 << GREEN;
|
||||
delay(100-1);
|
||||
GPIOD->ODR |= 1 << GREEN;
|
||||
blocking_delay(100);
|
||||
GPIOD->ODR &= ~(1 << GREEN);
|
||||
delay(100-1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -36,8 +38,10 @@ void toggleOrange(void)
|
||||
{
|
||||
while(1)
|
||||
{
|
||||
GPIOD->ODR ^= 1 << ORANGE;
|
||||
delay(200-1);
|
||||
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,65 +60,63 @@ 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);
|
||||
}
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
// Use HSE (8 MHz)
|
||||
// Enable HSE
|
||||
RCC->CR |= RCC_CR_HSEON;
|
||||
// Wait until HSE is stable
|
||||
while ((RCC->CR & RCC_CR_HSERDY) == 0);
|
||||
// Use HSE (8 MHz)
|
||||
// Enable HSE
|
||||
RCC->CR |= RCC_CR_HSEON;
|
||||
// Wait until HSE is stable
|
||||
while ((RCC->CR & RCC_CR_HSERDY) == 0);
|
||||
|
||||
// Power interface clock enable
|
||||
RCC->APB1ENR |= RCC_APB1ENR_PWREN;
|
||||
// Regulator voltage scaling output selection Scale 1 mode <= 100 MHz
|
||||
PWR->CR |= PWR_CR_VOS;
|
||||
// Use 3 wait states when reading Flash at 100 MHz.
|
||||
FLASH->ACR = FLASH_ACR_LATENCY_3WS;
|
||||
// Wait until 3 wait states are used
|
||||
while ((FLASH->ACR & FLASH_ACR_LATENCY_3WS) == 0);
|
||||
// Enable flash prefetch buffer, instruction and data cache
|
||||
FLASH->ACR |= FLASH_ACR_PRFTEN | FLASH_ACR_ICEN | FLASH_ACR_DCEN;
|
||||
// Power interface clock enable
|
||||
RCC->APB1ENR |= RCC_APB1ENR_PWREN;
|
||||
// Regulator voltage scaling output selection Scale 1 mode <= 100 MHz
|
||||
PWR->CR |= PWR_CR_VOS;
|
||||
// Use 3 wait states when reading Flash at 100 MHz.
|
||||
FLASH->ACR = FLASH_ACR_LATENCY_3WS;
|
||||
// Wait until 3 wait states are used
|
||||
while ((FLASH->ACR & FLASH_ACR_LATENCY_3WS) == 0);
|
||||
// Enable flash prefetch buffer, instruction and data cache
|
||||
FLASH->ACR |= FLASH_ACR_PRFTEN | FLASH_ACR_ICEN | FLASH_ACR_DCEN;
|
||||
|
||||
// Use PLL to generate 100 MHz clock
|
||||
// PLL output = 8 / M * N / P: M = 4, N = 100, P = 2 to generate 100 MHz
|
||||
RCC->PLLCFGR = 0x20000000
|
||||
| RCC_PLLCFGR_PLLSRC_HSE
|
||||
| (0 << RCC_PLLCFGR_PLLP_Pos)
|
||||
| (100 << RCC_PLLCFGR_PLLN_Pos)
|
||||
| (4 << RCC_PLLCFGR_PLLM_Pos);
|
||||
// Enable PLL
|
||||
RCC->CR |= RCC_CR_PLLON;
|
||||
// Wait until PLL is locked
|
||||
while ((RCC->CR & RCC_CR_PLLRDY) == 0);
|
||||
// Select PLL as the system clock. AHB clock divided by 2.
|
||||
RCC->CFGR |= RCC_CFGR_SW_PLL | RCC_CFGR_PPRE1_DIV2;
|
||||
// Wait until PLL used as the system clock
|
||||
while ((RCC->CFGR & RCC_CFGR_SWS_PLL) == 0);
|
||||
// Disable HSI
|
||||
RCC->CR &= ~RCC_CR_HSION;
|
||||
// Use PLL to generate 100 MHz clock
|
||||
// PLL output = 8 / M * N / P: M = 4, N = 100, P = 2 to generate 100 MHz
|
||||
RCC->PLLCFGR = 0x20000000
|
||||
| RCC_PLLCFGR_PLLSRC_HSE
|
||||
| (0 << RCC_PLLCFGR_PLLP_Pos)
|
||||
| (100 << RCC_PLLCFGR_PLLN_Pos)
|
||||
| (4 << RCC_PLLCFGR_PLLM_Pos);
|
||||
// Enable PLL
|
||||
RCC->CR |= RCC_CR_PLLON;
|
||||
// Wait until PLL is locked
|
||||
while ((RCC->CR & RCC_CR_PLLRDY) == 0);
|
||||
// Select PLL as the system clock. AHB clock divided by 2.
|
||||
RCC->CFGR |= RCC_CFGR_SW_PLL | RCC_CFGR_PPRE1_DIV2;
|
||||
// Wait until PLL used as the system clock
|
||||
while ((RCC->CFGR & RCC_CFGR_SWS_PLL) == 0);
|
||||
// Disable HSI
|
||||
RCC->CR &= ~RCC_CR_HSION;
|
||||
|
||||
// GPIO Port D Clock Enable
|
||||
RCC->AHB1ENR |= RCC_AHB1ENR_GPIODEN;
|
||||
// GPIO Port D led pins Push/Pull Output
|
||||
GPIOD->MODER |= 1 << 2 * GREEN | 1 << 2 * ORANGE | 1 << 2 * RED | 1 << 2 * BLUE;
|
||||
// GPIO Port D Clock Enable
|
||||
RCC->AHB1ENR |= RCC_AHB1ENR_GPIODEN;
|
||||
// GPIO Port D led pins Push/Pull Output
|
||||
GPIOD->MODER |= 1 << 2 * GREEN | 1 << 2 * ORANGE | 1 << 2 * RED | 1 << 2 * BLUE;
|
||||
|
||||
// Create tasks. Provide fpointer, stacksize, and priority:
|
||||
addTaskToList(toggleGreen, 128, 2);
|
||||
addTaskToList(toggleOrange, 128, 2);
|
||||
addTaskToList(toggleRed, 128, 2);
|
||||
addTaskToList(toggleBlue, 128, 2);
|
||||
addTaskToList(toggleGreen, 128, 2);
|
||||
addTaskToList(toggleOrange, 128, 3);
|
||||
addTaskToList(toggleRed, 128, 4);
|
||||
addTaskToList(toggleBlue, 128, 5);
|
||||
|
||||
// Start VersdOS with 1 ms sysTick
|
||||
startVersdOS(1);
|
||||
// Start VersdOS with 1 ms sysTick
|
||||
startVersdOS(1);
|
||||
|
||||
while(1);
|
||||
while(1);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user