diff --git a/report-2/week_1.3.md b/report-2/week_1.3.md index af3fc9b..81683c1 100644 --- a/report-2/week_1.3.md +++ b/report-2/week_1.3.md @@ -19,7 +19,7 @@ $$ T = \frac{AHB/8}{f_{out}} = \frac{16\cdot 10^6/8}{2} = 10^6 $$ -My resulting code: +My resulting code^[also available at [/report-1/week_1.3/assignment_3.1/main.c](https://git.gay/LailaTheElf/RTS10_reports/src/branch/main/report-1/week_1.3/assignment_3.1/main.c)]: ```c {.numberLines} #include @@ -64,6 +64,8 @@ I measured the resulting frequency with an logic analyser ([[#logic-analiser-vie > Configure the SysTick timer to set the `COUNTFLAG` in the `STK_CTRL` register every $0.5s$ using the CMSIS API. Replace the for-loop with the following C code: `while ((SysTick->CTRL & (1 << 16)) == 0);` The symbol SysTick is defined in the CMSIS API. Build and debug the project. If all is well, the user LEDs will blink with a frequency of $1 Hz$. +code also available at [/report-1/week_1.3/assignment_3.2/main.c](https://git.gay/LailaTheElf/RTS10_reports/src/branch/main/report-1/week_1.3/assignment_3.2/main.c) + ```c {.numberLines} #include #include @@ -104,6 +106,8 @@ This time I measured $499.586ms$ with the logic analyser. > B) Configure the SysTick timer to generate an interrupt (also called an exception) every `0.5s`. +code also available at [/report-1/week_1.3/assignment_3.3/main.c](https://git.gay/LailaTheElf/RTS10_reports/src/branch/main/report-1/week_1.3/assignment_3.3/main.c) + ```c {.numberLines} #include #include @@ -158,6 +162,8 @@ because the compiler doesn't know when `flag` changes. Without `volatile` optimi > Configure the SysTick timer to generate an interrupt every `0.5s`. This can be done by using the function `SysTick_Config` from the CMSIS API. +code also available at [/report-1/week_1.3/assignment_3.4/main.c](https://git.gay/LailaTheElf/RTS10_reports/src/branch/main/report-1/week_1.3/assignment_3.4/main.c) + ```c {.numberLines} #include #include @@ -208,6 +214,8 @@ int main(void) > Now based on project opdr_3_4 create a rotation loop which simulates a simple traffic light: green (5 seconds), orange (1 second), red (4 seconds). The time each light is on must be easily adjustable with a granularity of $0.5s$. The processor must be put to sleep in between interrupts. Make use of an enumeration construct (`enum`) for the colors and a `switch`-`case`-statement for the rotation. +code also available at [/report-1/week_1.3/assignment_3.5/main.c](https://git.gay/LailaTheElf/RTS10_reports/src/branch/main/report-1/week_1.3/assignment_3.5/main.c) + ```c {.numberLines} #include #include @@ -306,6 +314,8 @@ Again I validated the timings with the logic-analyser. > - Create a function runReadyTasks() that will walk through the task list and execute any task in the READY state. Replace your switch-case rotation in the function main with a call to this function. > - Make use of a logic analyzer to verify the timing of the tasks +code also available at [/report-1/week_1.3/assignment_3.6/main.c](https://git.gay/LailaTheElf/RTS10_reports/src/branch/main/report-1/week_1.3/assignment_3.6/main.c) + ```c {.numberLines} #include #include @@ -430,7 +440,7 @@ int main(void) > Now add initial delays (in systicks) to your tasks. Use an initial delay of 100, 200, 300, and 400 for green, orange, red, and blue respectively. Make use of a logic analyser to verify the timing. -When A task is created, in the version of [[#Assignment 3.7]], the following function is used: +When A task is created, in the version of [Assignment 3.6](#assignment-36), the following function is used: ```c bool addTask(void (*fn)(void), uint32_t counter) @@ -450,6 +460,8 @@ Here the `counter` and `counter_rst` members are set to the same value. `counter Setting `counter` to the initial delay already solves this assignment. The following code implements this change. +code also available at [/report-1/week_1.3/assignment_3.7/main.c](https://git.gay/LailaTheElf/RTS10_reports/src/branch/main/report-1/week_1.3/assignment_3.7/main.c) + ```c {.numberLines} #include #include diff --git a/report-2/week_1.3/assignment_3.1/main.c b/report-2/week_1.3/assignment_3.1/main.c new file mode 100644 index 0000000..cdeecea --- /dev/null +++ b/report-2/week_1.3/assignment_3.1/main.c @@ -0,0 +1,32 @@ +#include + +#define RCC_AHB1ENR_BIT_GPIODEN *(volatile uint32_t*)(0x42000000 + 0x00023830 * 32 + 3 * 4) +#define GPIOD_BASE 0x40020C00 +#define GPIOD_MODER *(volatile uint32_t*)(GPIOD_BASE + 0x00) +#define GPIOD_ODR *(volatile uint32_t*)(GPIOD_BASE + 0x14) + +#define STK_CTRL *(volatile uint32_t*)(0xE000E010) +#define STK_LOAD *(volatile uint32_t*)(0xE000E014) + +int main(void) +{ + // GPIO Port D Clock Enable + RCC_AHB1ENR_BIT_GPIODEN = 1; + // GPIO Port D Pin 15 down to 12 Push/Pull Output + GPIOD_MODER = 0x55000000; + // Set green and red LEDs + GPIOD_ODR = 0x5000; + + // SysTick enable with clk source to AHB/8 + // (AHB is by default HSI; 16 MHz/8) + STK_CTRL = 1; + STK_LOAD = 1000000; // 16 MHz / 8 / 2 Hz + // Do forever: + while (1) + { + // Wait a moment + while ((STK_CTRL & (1 << 16)) == 0); + // Flip all LEDs + GPIOD_ODR ^= 0xF000; + } +} diff --git a/report-2/week_1.3/assignment_3.2/main.c b/report-2/week_1.3/assignment_3.2/main.c new file mode 100644 index 0000000..fc4ed7e --- /dev/null +++ b/report-2/week_1.3/assignment_3.2/main.c @@ -0,0 +1,31 @@ +#include +#include + +int main(void) +{ + // GPIO Port D Clock Enable + RCC->AHB1ENR = RCC_AHB1ENR_GPIODEN; + // GPIO Port D Pin 15 down to 12 Push/Pull Output + GPIOD->MODER = GPIO_MODER_MODER12_0 + | GPIO_MODER_MODER13_0 + | GPIO_MODER_MODER14_0 + | GPIO_MODER_MODER15_0; + // Set green and red LEDs + GPIOD->ODR = GPIO_ODR_OD12 | GPIO_ODR_OD14; + + // SysTick enable with clk source to AHB/8 + SysTick->CTRL = SysTick_CTRL_ENABLE_Msk; + SysTick->LOAD = 1000000; // 16 MHz / 8 / 2 Hz + + // Do forever: + while (1) + { + // Wait a moment + while ((SysTick->CTRL & (1 << 16)) == 0); + // Flip all LEDs + GPIOD->ODR ^= GPIO_ODR_OD12 + | GPIO_ODR_OD13 + | GPIO_ODR_OD14 + | GPIO_ODR_OD15; + } +} diff --git a/report-2/week_1.3/assignment_3.3/main.c b/report-2/week_1.3/assignment_3.3/main.c new file mode 100644 index 0000000..e54578f --- /dev/null +++ b/report-2/week_1.3/assignment_3.3/main.c @@ -0,0 +1,43 @@ +#include +#include + +#define RCC_AHB1ENR_BIT_GPIODEN *(volatile uint32_t*)(0x42000000 + 0x00023830 * 32 + 3 * 4) +#define GPIOD_BASE 0x40020C00 +#define GPIOD_MODER *(volatile uint32_t*)(GPIOD_BASE + 0x00) +#define GPIOD_ODR *(volatile uint32_t*)(GPIOD_BASE + 0x14) + +#define STK_CTRL *(volatile uint32_t*)(0xE000E010) +#define STK_LOAD *(volatile uint32_t*)(0xE000E014) + +volatile bool flag = false; + +void SysTick_Handler() +{ + flag = true; +} + +int main(void) +{ + // GPIO Port D Clock Enable + RCC_AHB1ENR_BIT_GPIODEN = 1; + // GPIO Port D Pin 15 down to 12 Push/Pull Output + GPIOD_MODER = 0x55000000; + // Set green and red LEDs + GPIOD_ODR = 0x5000; + + // SysTick enable with interupt and clk source to AHB/8 + STK_CTRL = (1<<1) | 1; + STK_LOAD = 1000000; // 0.5 sec / (16 MHz / 8) + // Do forever: + while (1) + { + // Wait a moment + while (!flag) + { + __asm__(" WFI"); // sleep until SysTick + } + flag = false; + // Flip all LEDs + GPIOD_ODR ^= 0xF000; + } +} diff --git a/report-2/week_1.3/assignment_3.4/main.c b/report-2/week_1.3/assignment_3.4/main.c new file mode 100644 index 0000000..2ce2c9f --- /dev/null +++ b/report-2/week_1.3/assignment_3.4/main.c @@ -0,0 +1,43 @@ +#include +#include +#include + +volatile bool flag = false; + +void SysTick_Handler() +{ + flag = true; +} + +int main(void) +{ + // GPIO Port D Clock Enable + RCC->AHB1ENR = RCC_AHB1ENR_GPIODEN; + // GPIO Port D Pin 15 down to 12 Push/Pull Output + GPIOD->MODER = GPIO_MODER_MODER12_0 + | GPIO_MODER_MODER13_0 + | GPIO_MODER_MODER14_0 + | GPIO_MODER_MODER15_0; + // Set green and red LEDs + GPIOD->ODR = GPIO_ODR_OD12 | GPIO_ODR_OD14; + + // SysTick enable with interupt and clk source to AHB/8 + SysTick->CTRL = SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk; + SysTick->LOAD = 1000000; // 0.5 sec / (16 MHz / 8) + + // Do forever: + while (1) + { + // Wait a moment + while (!flag) + { + __asm__(" WFI"); // sleep until SysTick + } + flag = false; + // Flip all LEDs + GPIOD->ODR ^= GPIO_ODR_OD12 + | GPIO_ODR_OD13 + | GPIO_ODR_OD14 + | GPIO_ODR_OD15; + } +} diff --git a/report-2/week_1.3/assignment_3.5/main.c b/report-2/week_1.3/assignment_3.5/main.c new file mode 100644 index 0000000..17d0338 --- /dev/null +++ b/report-2/week_1.3/assignment_3.5/main.c @@ -0,0 +1,79 @@ +#include +#include +#include + +volatile bool flag = false; + +void SysTick_Handler() +{ + flag = true; +} + +enum STATE { + STATE_GREEN, + STATE_ORANGE, + STATE_RED +}; + +int main(void) +{ + // GPIO Port D Clock Enable + RCC->AHB1ENR = RCC_AHB1ENR_GPIODEN; + // GPIO Port D Pin 15 down to 12 Push/Pull Output + GPIOD->MODER = GPIO_MODER_MODER12_0 + | GPIO_MODER_MODER13_0 + | GPIO_MODER_MODER14_0 + | GPIO_MODER_MODER15_0; + // Set green and red LEDs + GPIOD->ODR = GPIO_ODR_OD12; + + // SysTick enable with interupt and clk source to AHB/8 + SysTick->CTRL = SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk; + SysTick->LOAD = 1000000; // 0.5 sec / (8 MHz / 8) + + // time of each color in half seconds + const uint32_t time_green = 10; // 5 seconds + const uint32_t time_orange = 2; // 1 seconds + const uint32_t time_red = 8; // 4 seconds + + uint32_t timer = time_green; + enum STATE State = STATE_GREEN; + + // Do forever: + while (1) + { + // Wait a moment + while (!flag) + { + __asm__(" WFI"); // sleep until SysTick + } + flag = false; + + timer--; + if (timer == 0) + { + // turn off all leds + GPIOD->ODR &= ~(GPIO_ODR_OD12 + | GPIO_ODR_OD13 + | GPIO_ODR_OD14 + | GPIO_ODR_OD15); + switch (State) { + case STATE_GREEN: + State = STATE_ORANGE; + GPIOD->ODR |= GPIO_ODR_OD13; + timer = time_orange; + break; + case STATE_ORANGE: + State = STATE_RED; + GPIOD->ODR |= GPIO_ODR_OD14; + timer = time_red; + break; + case STATE_RED: + State = STATE_GREEN; + GPIOD->ODR |= GPIO_ODR_OD12; + timer = time_green; + break; + } + } + } +} diff --git a/report-2/week_1.3/assignment_3.6/main.c b/report-2/week_1.3/assignment_3.6/main.c new file mode 100644 index 0000000..774b66a --- /dev/null +++ b/report-2/week_1.3/assignment_3.6/main.c @@ -0,0 +1,115 @@ +#include +#include +#include + +volatile uint32_t ISR_Ticks = 0; + +struct TASK { + void (*fn)(void); + uint32_t counter; + uint32_t counter_rst; +}; + +uint8_t Tasks_len = 0; +struct TASK Tasks[8]; + +void SysTick_Handler() +{ + ISR_Ticks++; +} + +bool addTask(void (*fn)(void), uint32_t counter) +{ + if (Tasks_len >= 8) { + return false; + } + Tasks[Tasks_len].fn = fn; + Tasks[Tasks_len].counter = counter; + Tasks[Tasks_len].counter_rst = counter; + Tasks_len++; + return true; +} + +void taskGreen() +{ + GPIOD->ODR ^= GPIO_ODR_OD12; +} + +void taskOrange() +{ + GPIOD->ODR ^= GPIO_ODR_OD13; +} + +void taskRed() +{ + GPIOD->ODR ^= GPIO_ODR_OD14; +} + +void taskBlue() +{ + GPIOD->ODR ^= GPIO_ODR_OD15; +} + +enum STATE { + STATE_GREEN, + STATE_ORANGE, + STATE_RED +}; + +int main(void) +{ + // GPIO Port D Clock Enable + RCC->AHB1ENR = RCC_AHB1ENR_GPIODEN; + // GPIO Port D Pin 15 down to 12 Push/Pull Output + GPIOD->MODER = GPIO_MODER_MODER12_0 + | GPIO_MODER_MODER13_0 + | GPIO_MODER_MODER14_0 + | GPIO_MODER_MODER15_0; + // Set all leds off + GPIOD->ODR = 0; + + + // SysTick enable with interupt and clk source to AHB/8 + SysTick->CTRL = SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk; + SysTick->LOAD = 2000; // 1 ms / (16 MHz / 8) + + addTask(*taskGreen, 200); + addTask(*taskOrange, 500); + addTask(*taskRed, 750); + addTask(*taskBlue, 300); + + // Do forever: + while (1) + { + // Wait a moment + while (ISR_Ticks == 0) + { + __asm__(" WFI"); // sleep until SysTick + } + uint32_t ticks = ISR_Ticks; + ISR_Ticks = 0; + + // decrement all counters + for (uint8_t i=0; i ticks) + { + Tasks[i].counter -= ticks; + } + else + { + Tasks[i].counter = 0; + } + } + + // rust all tasks where the counter has run out + for (uint8_t i=0; i +#include +#include + +volatile uint32_t ISR_Ticks = 0; + +struct TASK { + void (*fn)(void); + uint32_t counter; + uint32_t counter_rst; +}; + +uint8_t Tasks_len = 0; +struct TASK Tasks[8]; + +void SysTick_Handler() +{ + ISR_Ticks++; +} + +bool addTask(void (*fn)(void), uint32_t counter, uint32_t counter_init) +{ + if (Tasks_len >= 8) { + return false; + } + Tasks[Tasks_len].fn = fn; + Tasks[Tasks_len].counter = counter_init; + Tasks[Tasks_len].counter_rst = counter; + Tasks_len++; + return true; +} + +void taskGreen() +{ + GPIOD->ODR ^= GPIO_ODR_OD12; +} + +void taskOrange() +{ + GPIOD->ODR ^= GPIO_ODR_OD13; +} + +void taskRed() +{ + GPIOD->ODR ^= GPIO_ODR_OD14; +} + +void taskBlue() +{ + GPIOD->ODR ^= GPIO_ODR_OD15; +} + +enum STATE { + STATE_GREEN, + STATE_ORANGE, + STATE_RED +}; + +int main(void) +{ + // GPIO Port D Clock Enable + RCC->AHB1ENR = RCC_AHB1ENR_GPIODEN; + // GPIO Port D Pin 15 down to 12 Push/Pull Output + GPIOD->MODER = GPIO_MODER_MODER12_0 + | GPIO_MODER_MODER13_0 + | GPIO_MODER_MODER14_0 + | GPIO_MODER_MODER15_0; + // Set all leds off + GPIOD->ODR = 0; + + + // SysTick enable with interupt and clk source to AHB/8 + SysTick->CTRL = SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk; + SysTick->LOAD = 2000; // 1 ms / (16 MHz / 8) + + addTask(*taskGreen, 200, 100); + addTask(*taskOrange, 500, 200); + addTask(*taskRed, 750, 300); + addTask(*taskBlue, 300, 400); + + // Do forever: + while (1) + { + // Wait a moment + while (ISR_Ticks == 0) + { + __asm__(" WFI"); // sleep until SysTick + } + uint32_t ticks = ISR_Ticks; + ISR_Ticks = 0; + + // decrement all counters + for (uint8_t i=0; i ticks) + { + Tasks[i].counter -= ticks; + } + else + { + Tasks[i].counter = 0; + } + } + + // rust all tasks where the counter has run out + for (uint8_t i=0; i +#include +#include +#include "VersdOS.h" + +//The (external) assembly functions +void pushRegistersToCurrentPSP(void); +void popRegistersFromCurrentPSP(void); +void * readPSP(void); +void writePSP(void * ptr); +void returnToPSP(void); +void returnToMSP(void); + +#define TASK_MASK MAX_TASKS-1 +#define IDLE_TASK MAX_TASKS + +//What states can our task have? +enum taskState {UNUSED = 0, RUNNING, READY, SLEEPING_DELAY}; + +//The task itself +typedef struct _task{ + int *stack; // pointer to the stack on the heap + uint32_t counter; // a counter for delays + void (*function)(void); // function to execute + enum taskState state; // state + int8_t priority; // priority +} task; + +// List of tasks +//add one space for idle task +task taskList[MAX_TASKS+1]; +task * currentTask; +task * taskToExecute; + +// Idle task +void idleTask(void) +{ + while (1) + { + __asm(" wfi"); // Sleep until next SysTick + } +} + + + +void addTaskToListAtIndex(void (*function)(void), uint32_t stackSize, int8_t priority, size_t pos) +{ + task *taskToAdd = &taskList[pos]; + + taskToAdd->function = function; + // Allocate memory... do we wanna use malloc or our own implementation ;-) ? + taskToAdd->stack = (int *)malloc(stackSize)+stackSize; + + /* + * For debugging purposes we initialize the stack with + * values that we can recognize. + */ + *(--(taskToAdd->stack)) = 0x01000000; //XSPR Thumb bit set + *(--(taskToAdd->stack)) = (int)taskToAdd->function; //set PC to function pointer, cast as int to silence the compiler + *(--(taskToAdd->stack)) = 0xFFFFFFFD; //LR, return with process stack (PSP) + *(--(taskToAdd->stack)) = 0x0000000C; //R12 Initial values used for debugging purposes + *(--(taskToAdd->stack)) = 0x00000003; //R3 + *(--(taskToAdd->stack)) = 0x00000002; //R2 + *(--(taskToAdd->stack)) = 0x00000001; //R1 + *(--(taskToAdd->stack)) = 0x00000000; //R0 + + if(pos!=IDLE_TASK) + { + *(--(taskToAdd->stack)) = 0x0000000B; //R11 + *(--(taskToAdd->stack)) = 0x0000000A; //R10 + *(--(taskToAdd->stack)) = 0x00000009; //R9 + *(--(taskToAdd->stack)) = 0x00000008; //R8 + *(--(taskToAdd->stack)) = 0x00000007; //R7 + *(--(taskToAdd->stack)) = 0x00000006; //R6 + *(--(taskToAdd->stack)) = 0x00000005; //R5 + *(--(taskToAdd->stack)) = 0x00000004; //R4 + // Initialize the task properties + taskToAdd->state = READY; + }else{ + taskToAdd->state = RUNNING; + currentTask = taskToAdd; + // Update the CPU PSP with our new stack pointer + writePSP(taskToAdd->stack); + } + + taskToAdd->priority = priority; +} + +/* + * Function to add a new task to the taskList + * Not sorted, prioritized or any of that kind. + * + * It simply allocates memory for the new task stack, + * fills the stack up so that the context switch will + * successfully pop these registers and start running + * at the correct address when returning from the SysTick ISR + */ +void addTaskToList(void (*function)(void), uint32_t stackSize, int8_t priority) +{ + size_t i = 0; + // Simply find the next empty slot + // Loops when no more slots are available + while(taskList[i].state != UNUSED) + { + //increment i and roll back at the limit + i++; + i &= TASK_MASK; + } + addTaskToListAtIndex(function, stackSize, priority, i); +} + +void startVersdOS(uint16_t sysTickPeriodIn_ms) { + // Configure SysTick of 1 ms + SysTick->LOAD = sysTickPeriodIn_ms * CLOCK_FREQ_IN_KHz - 1; + SysTick->VAL = 0; + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk //Clock source selection = Processor clock (AHB) + | SysTick_CTRL_TICKINT_Msk //Counting down to zero to asserts the SysTick exception request + | SysTick_CTRL_ENABLE_Msk; //Counter enable + + //set systick and pendsv interrupt priority to lowest. + //svc will be highest. + SCB->SHP[2] |= 0xFF<<24; + SCB->SHP[2] |= 0xFF<<16; + + // Create Idle task + addTaskToListAtIndex(idleTask, 128, -1, IDLE_TASK); + + __asm(" wfi"); // Sleep until next SysTick +} + +// currentTask is running now, return next task to run +task * schedule() +{ + task* tempTaskPtr = currentTask; + task *idleTaskPtr = &taskList[IDLE_TASK]; + +// tempTaskPtr->state = READY; + + int teller=0; + + //Find next ready, non idle task. + 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]; + } + }while(tempTaskPtr->state != READY && teller++ <= MAX_TASKS); + + //if no task was found + if(tempTaskPtr->state != READY) + { + //idle task + tempTaskPtr = idleTaskPtr; + } + + return tempTaskPtr; +} + +// flag used in blocking_delay function +bool SysTick_flag; + +void decrement_sleeping_delay() +{ + for (size_t i=0; i < MAX_TASKS; i++) + { + if (taskList[i].state == SLEEPING_DELAY) + { + if (taskList[i].counter == 0) + { + taskList[i].state = READY; + } + else + { + taskList[i].counter--; + } + } + } +} + +/* + * Interrupt routine for the Systick timer + * simply calls the scheduler + * */ +void SysTick_Handler(void) +{ + SysTick_flag = true; + //decrement counter for task in SLEEPING_DELAY + decrement_sleeping_delay(); + //select the next task + taskToExecute = schedule(); + //request context switch + SCB->ICSR |= (1<<28); +} + +__attribute__((naked)) // No function entry and exit code +void PendSV_Handler(void) +{ + //Push {R4-R11} context to PSP + pushRegistersToCurrentPSP(); + //Save the new stack pointer after the push + currentTask->stack = readPSP(); + + currentTask = taskToExecute; + + //Load the new stack pointer from (new) currentTask + writePSP(currentTask->stack); + + //Pop {R4-R11} context from PSP + popRegistersFromCurrentPSP(); + + returnToPSP(); +} + +/* The most simple SVC implementation + */ + +void SVC_Handler(void) +{ + taskToExecute = schedule(); + SCB->ICSR |= (1<<28); +} + +//Call Super Visor +void taskYield(void) +{ + asm(" svc #1"); +} + +void delay(uint32_t ticks) +{ + currentTask->state = SLEEPING_DELAY; + currentTask->counter = ticks; + taskYield(); +} + + diff --git a/report-2/week_1.4/assignment_4.2/VersdOS.h b/report-2/week_1.4/assignment_4.2/VersdOS.h new file mode 100644 index 0000000..b1a0405 --- /dev/null +++ b/report-2/week_1.4/assignment_4.2/VersdOS.h @@ -0,0 +1,27 @@ +/* + * VersOS.h + * + * Created on: 12 nov. 2013 + * Author: VersD @ hr.nl + * + */ + +#ifndef VERSDOS_H_ +#define VERSDOS_H_ + +#include + +// define the clock frequency you use. You have to configure it YOURSELF! +#define CLOCK_FREQ_IN_KHz 100000 +// define the max number of task you can use +#define MAX_TASKS 4 // MUST be a power of 2 + +// Add new task to the taskList +// priority can be between 0 and 127, higher number means higher priority +void addTaskToList(void(*function)(void), uint32_t stackSize, int8_t priority); +// Start OS +void startVersdOS(uint16_t sysTickPeriodIn_ms); + +void delay(uint32_t ticks); + +#endif /* VERSDOS_H_ */ diff --git a/report-2/week_1.4/assignment_4.2/VersdOS_ll.s b/report-2/week_1.4/assignment_4.2/VersdOS_ll.s new file mode 100644 index 0000000..7ae887f --- /dev/null +++ b/report-2/week_1.4/assignment_4.2/VersdOS_ll.s @@ -0,0 +1,47 @@ +// Author: Daniel Versluis +// Email: VersD@hr.nl +// Description: Contains all neccesary low-level functions +// for pushing and popping CPU/Stack + + .thumb + .syntax unified + + .global pushRegistersToCurrentPSP + .global popRegistersFromCurrentPSP + .global readPSP + .global writePSP + .global returnToPSP + .global returnToMSP + // .global SVC_Handler + +pushRegistersToCurrentPSP: + MRS r0 , psp //Move PSP to register R0 (the function argument) + STMDB r0! , {r4-r11} //Store multiple registers decrement address before each access, + //when done write back last used address to %0 (new SP location) + MSR psp , r0 //Move register %0 to psp to update to the new SP, output to scratch + MOV PC , LR //return by moving link-register to program counter + +popRegistersFromCurrentPSP: + MRS R0 , psp //Move PSP to register R0 + LDMIA R0! , {r4-r11} //Load multiple registers increment address after each access, + //when done write back last used address to R0 (new SP location) + MSR psp , R0 //Move register R0 to psp to update to the new SP, output to scratch + MOV PC , LR //return by moving link-register to program counter + +readPSP: + MRS R0 , psp //move psp to r0 + MOV PC , LR //return by moving link-register to program counter + +writePSP: + MSR psp , R0 //Move r0 to psp. + ISB //flush pipeline + MOV PC , LR //return by moving link-register to program counter + +returnToPSP: + ldr lr, =0xFFFFFFFD //terug met process stack + bx lr + +returnToMSP: + ldr lr, =0xFFFFFFF9 //terug met process stack + bx lr + diff --git a/report-2/week_1.4/assignment_4.2/main.c b/report-2/week_1.4/assignment_4.2/main.c new file mode 100644 index 0000000..b13530a --- /dev/null +++ b/report-2/week_1.4/assignment_4.2/main.c @@ -0,0 +1,114 @@ +#include +#include +#include +#include "VersdOS.h" + +/*-------------------------------pin numbers for leds ---------------------------*/ + +#define GREEN 12 +#define ORANGE 13 +#define RED 14 +#define BLUE 15 + +/*------------------------------------DEMO---------------------------------------*/ +// blocking delay function +// 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--; + } +} + +void toggleGreen(void) +{ + while(1) + { + GPIOD->ODR ^= 1 << GREEN; + delay(100-1); + } +} + +void toggleOrange(void) +{ + while(1) + { + GPIOD->ODR ^= 1 << ORANGE; + delay(200-1); + } +} + +void toggleRed(void) +{ + while(1) + { + GPIOD->ODR ^= 1 << RED; + delay(400-1); + } +} + +void toggleBlue(void) +{ + while(1) + { + GPIOD->ODR ^= 1 << BLUE; + delay(800-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); + + // 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; + + // 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); + + // Start VersdOS with 1 ms sysTick + startVersdOS(1); + + while(1); +}