add code as seperate files

This commit is contained in:
Laila van Reenen 2025-09-30 14:22:05 +02:00
parent 08378672de
commit 43e1596e41
Signed by: LailaTheElf
GPG Key ID: 8A3EF0226518C12D
12 changed files with 927 additions and 2 deletions

View File

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

View 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;
}
}

View 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;
}
}

View 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;
}
}

View 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;
}
}

View 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;
}
}
}
}

View 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;
}
}
}
}

View 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;
}
}
}
}

View 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();
}

View 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_ */

View 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

View 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);
}