add code as seperate files
This commit is contained in:
parent
08378672de
commit
43e1596e41
@ -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 <stdint.h>
|
||||
@ -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 <stdint.h>
|
||||
#include <stm32f4xx.h>
|
||||
@ -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 <stdint.h>
|
||||
#include <stdbool.h>
|
||||
@ -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 <stdint.h>
|
||||
#include <stm32f4xx.h>
|
||||
@ -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 <stdint.h>
|
||||
#include <stm32f4xx.h>
|
||||
@ -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 <stdint.h>
|
||||
#include <stm32f4xx.h>
|
||||
@ -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 <stdint.h>
|
||||
#include <stm32f4xx.h>
|
||||
|
||||
32
report-2/week_1.3/assignment_3.1/main.c
Normal file
32
report-2/week_1.3/assignment_3.1/main.c
Normal file
@ -0,0 +1,32 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
}
|
||||
31
report-2/week_1.3/assignment_3.2/main.c
Normal file
31
report-2/week_1.3/assignment_3.2/main.c
Normal file
@ -0,0 +1,31 @@
|
||||
#include <stdint.h>
|
||||
#include <stm32f4xx.h>
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
43
report-2/week_1.3/assignment_3.3/main.c
Normal file
43
report-2/week_1.3/assignment_3.3/main.c
Normal file
@ -0,0 +1,43 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
}
|
||||
43
report-2/week_1.3/assignment_3.4/main.c
Normal file
43
report-2/week_1.3/assignment_3.4/main.c
Normal file
@ -0,0 +1,43 @@
|
||||
#include <stdint.h>
|
||||
#include <stm32f4xx.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
79
report-2/week_1.3/assignment_3.5/main.c
Normal file
79
report-2/week_1.3/assignment_3.5/main.c
Normal file
@ -0,0 +1,79 @@
|
||||
#include <stdint.h>
|
||||
#include <stm32f4xx.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
115
report-2/week_1.3/assignment_3.6/main.c
Normal file
115
report-2/week_1.3/assignment_3.6/main.c
Normal file
@ -0,0 +1,115 @@
|
||||
#include <stdint.h>
|
||||
#include <stm32f4xx.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
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<Tasks_len; i++)
|
||||
{
|
||||
if (Tasks[i].counter > 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<Tasks_len; i++)
|
||||
{
|
||||
if (Tasks[i].counter == 0)
|
||||
{
|
||||
Tasks[i].fn();
|
||||
Tasks[i].counter = Tasks[i].counter_rst;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
115
report-2/week_1.3/assignment_3.7/main.c
Normal file
115
report-2/week_1.3/assignment_3.7/main.c
Normal file
@ -0,0 +1,115 @@
|
||||
#include <stdint.h>
|
||||
#include <stm32f4xx.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
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<Tasks_len; i++)
|
||||
{
|
||||
if (Tasks[i].counter > 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<Tasks_len; i++)
|
||||
{
|
||||
if (Tasks[i].counter == 0)
|
||||
{
|
||||
Tasks[i].fn();
|
||||
Tasks[i].counter = Tasks[i].counter_rst;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
267
report-2/week_1.4/assignment_4.2/VersdOS.c
Normal file
267
report-2/week_1.4/assignment_4.2/VersdOS.c
Normal file
@ -0,0 +1,267 @@
|
||||
/*
|
||||
* Copyright 2015 Daniel Versluis
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* schedule.h
|
||||
*
|
||||
* Created on: 12 nov. 2013
|
||||
* Author: Daniel Versluis
|
||||
* Email: VersD @ hr.nl
|
||||
*
|
||||
* Description:
|
||||
* Contains the scheduler and the systick ISR.
|
||||
* Simple and incomplete implementation.
|
||||
*
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <stm32f4xx.h>
|
||||
#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();
|
||||
}
|
||||
|
||||
|
||||
27
report-2/week_1.4/assignment_4.2/VersdOS.h
Normal file
27
report-2/week_1.4/assignment_4.2/VersdOS.h
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* VersOS.h
|
||||
*
|
||||
* Created on: 12 nov. 2013
|
||||
* Author: VersD @ hr.nl
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef VERSDOS_H_
|
||||
#define VERSDOS_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// 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_ */
|
||||
47
report-2/week_1.4/assignment_4.2/VersdOS_ll.s
Normal file
47
report-2/week_1.4/assignment_4.2/VersdOS_ll.s
Normal file
@ -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
|
||||
|
||||
114
report-2/week_1.4/assignment_4.2/main.c
Normal file
114
report-2/week_1.4/assignment_4.2/main.c
Normal file
@ -0,0 +1,114 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stm32f4xx.h>
|
||||
#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);
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user