move reports to git

This commit is contained in:
Laila van Reenen 2025-09-23 14:07:59 +02:00
commit 7b622c2577
Signed by: LailaTheElf
GPG Key ID: 8A3EF0226518C12D
7 changed files with 808 additions and 0 deletions

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "wiki"]
path = wiki
url = https://bitbucket.org/HR_ELEKTRO/rts10.git/wiki

BIN
assets/opdr_2_1.zip Normal file

Binary file not shown.

BIN
assets/opdr_2_2.zip Normal file

Binary file not shown.

View File

@ -0,0 +1,256 @@
---
path: /elektro/hr/rts10/
tags: kladjes, elektro, elektro/hr, elektro/hr/rts10
auther:
- Finley van Reenen (0964590@hr.nl)
auther_short: "E.L.F. van Reenen"
---
# Assembly Assignments
This is the first report for _realtime systems 10_. I needed to do the following assignments:
- Assignment 1: Testing a simple LEGv7 Pinky program
- Assignment 2: Writing a simple multiplication program
- Assignment 3: A smarter multiply algorithm
- Assignment 10: Using your multiply function to calculate the dot product of two vectors
## Assignment 1: Testing a simple LEGv7 Pinky program
First is getting a very basic example/base project to compile and run. The university supplied a zip file with a preconfigured project. I imported it into _STM Cube IDE_ and tried to debug.
First I got a message to update the debugger firmware. After doing this, I still got an error. It could not determine the GDB version.
![](https://live.kladjes.nl/uploads/f8f2722d-7a64-4020-9304-e707c8479b4d.png)
Last year I also had problems with GDB, but that time it was because it could not find the Windows version while I'm on Linux. Looking at the command, it does look like the usual Linux command.
In the terminal this command is not found. After searching around on my system, I found it in the install directory from the IDE. Running the command on this executable gave the exact same error as the popup gave.
I have ncruses 6.5 installed, but version 5 is requested. I installed the older version and tried it again. Now I get the same error as last year.
![](https://live.kladjes.nl/uploads/97598c2b-ccee-47a9-8342-e87803281354.png)
I applied the same fix as last year. In the debug config, replace the `\` with an `/` and remove the `.exe` in the path to the OpenOCD command. This fixed the problem that the debugger successfully stated.
![](https://live.kladjes.nl/uploads/cf6add70-f1c3-4d12-a753-3e7b505a899f.png)
## Assignment 2: Writing a simple multiplication program
The algorithm in question is given in C code.
```c-like=
unsigned int multiply(unsigned int a , unsigned int b)
{
unsigned int m = 0;
for (unsigned int i = 0; i != a; i ++)
{
m = m + b;
}
return m;
}
```
This code can be simplified without changing the algorithm by replacing the variable `i` with `b`. This will result in the following code.
```c-like=
unsigned int multiply ( unsigned int a , unsigned int b)
{
unsigned int m = 0;
for (; b > 0; b --)
{
m = m + a;
}
return m;
}
```
This is also the code I have implemented. The compiler puts _a_ in `R0` and _b_ in `R1`, I accepted them in place and used `R2` for _m_. At the end _m_ (`R2`) is moved to `R0` to set it as the return value.
```ass=
.cpu cortex-m4
.thumb
.syntax unified
.globl multiply
.text
.thumb_func
multiply:
MOVS.N R2, #0 // set m to 0
CMP.N R1, #0
BEQ.N mul_exit // goto mul_exit if b == 0
mul_loop:
ADDS.N R2, R0, R2 // add a to m
SUBS.N R1, #1 // substract 1 from b
BNE.N mul_loop // goto mul_loop if b != 0
mul_exit:
MOVS.N R0, R2 // move m to R0
BX.N LR
```
a better representation of the essembly code in C would be:
```c-like=
unsigned int multiply ( unsigned int a , unsigned int b)
{
unsigned int m = 0;
if (b == 0) {
return m;
}
do
{
m = m + b;
b --;
} while (b > 0)
return m;
}
```
![](https://live.kladjes.nl/uploads/4ec10cae-a18d-4f92-b261-7e0bf5daed6f.png)
> How many instructions does it take your procedure to run the code: `multiply(65535, 65535)`?
It does not take the branch at line 10 and at line 14 it takes the branch 65535 times. There are 3 instructions in this loop and 5 outside it, so $3\cdot 65535 + 5 = 196610$ instructions.
## Assignment 3: A smarter multiply algorithm
Now a smarter version.
```c-like=
unsigned int multiply(unsigned int a , unsigned int b)
{
unsigned int m = 0;
while (b != 0)
{
if ((b & 1) == 1) /* b is odd */
{
m = m + a;
}
a = a << 1;
b = b >> 1;
}
return m;
}
```
```asm=
.cpu cortex-m4
.thumb
.syntax unified
.globl better_multiply
.text
.thumb_func
// R0 = a, R1 = b, R2 = result (m), R3 = bitmask or odd/even bit
better_multiply:
MOVS.N R2, #0 // set m to 0
CMP.N R1, #0
BEQ.N bmul_exit // goto bmul_exit if b == 0
bmul_while:
MOVS.N R3, #1 // set R3 to 1 as bit mask
ANDS.N R3, R1 // and R3 (bit mask) with b
BEQ.N bmul_even // goto even if result is 0
ADDS.N R2, R0 // add a to m
bmul_even:
LSLS.N R0, R0, #1 // a = a << 1
LSRS.N R1, R1, #1 // b = b >> 1
BNE.N bmul_while // goto while if b != 0
bmul_exit:
MOVS.N R0, R2 // move m to R0
BX.N LR
```
a better representation of the essembly code in C would be:
```c-like=
unsigned int multiply ( unsigned int a , unsigned int b)
{
unsigned int m = 0;
if (b == 0) {
return m;
}
do
{
unsigned int t = 1;
if ((b & t) != 0) {
m += a;
}
a = a << 1;
b = b >> 1;
} while (b != 0)
return m;
}
```
![](https://live.kladjes.nl/uploads/2c21ba2c-935a-4dc7-81c3-54fc0ea6e37c.png)
> How many instructions does it take your procedure to run the code: `multiply(65535, 65535)`?
There are 7 instructions in the loop where one only runs every `1` bit in `b`. The loop only runs every bit in `b` until it's zero. In this case `b` is $65535$ or 16 ones in a row in binary. The full 7 instructions run 16 times plus the 5 instructions outside the loop. In total it's $16\cdot 7+5=117$ instructions. This is about 1680 times less instructions than the other algarium.
## Assignment 10: Using your multiply function to calculate the dot product of two vectors
```c-like=
unsigned int dotProduct(unsigned int a[], unsigned int b[], size_t n)
{
unsigned int p = 0;
for (size_t i = 0; i != n; i++)
{
p = p + multiply (a[i], b[i]);
}
return p;
}
```
This function needs to call another and remember 5 variables (`*a`, `*b`, `n`, `p` and `i`). `R0` through `R3` are expected to change with a function call. There are only `R4` through `R7` left, only four spots. To solve this problem, I reversed the for loop by using n and decrementing it. This will not change the result since addition is not order sensitive. The code I implemented is the following.
```c-like=
unsigned int dotProduct(unsigned int a[] , unsigned int b[], size_t n)
{
unsigned int p = 0;
if (n == 0) {
return p;
}
unsigned int i = n;
do
{
i--;
p = p + multiply(a[i], b[i]);
} while (i != 0)
return p;
}
```
My assembly code:
```asm=
.cpu cortex-m4
.thumb
.syntax unified
.globl dot_product
.text
.thumb_func
// R4 = a, R5 = b, R6 = i, R7 = p (result)
dot_product:
PUSH.N {R4, R5, R6, R7, LR}
MOVS.N R4, R0 // move *a to R4
MOVS.N R5, R1 // move *b to R5
MOVS.N R7, #0 // set p to 0
MOVS.N R0, R2 // move n to R0
MOVS.N R1, #4 // set R1 to 4
BLX.N =better_multiply // n * 4
MOVS.N R6, R0 // move result to R6
dotp_loop:
SUBS.N R6, R6, #4 // i = i - 4
LDR.N R0, [R4,R6] // load a[i] to R0
LDR.N R1, [R5,R6] // load b[i] to R1
BLX.N =better_multiply
ADDS.N R7, R7, R0 // p = p + result
BNE.N dotp_loop // goto dotp_loop if i != 0
dotp_exit:
MOVS.N R0, R7 // move m to R0
POP.N {R4, R5, R6, R7, PC}
BX.N LR
```

162
report-1/week_1.2.md Normal file
View File

@ -0,0 +1,162 @@
---
path: /elektro/hr/rts10/
tags: kladjes, elektro, elektro/hr, elektro/hr/rts10
auther:
- Finley van Reenen (0964590@hr.nl)
auther_short: "E.L.F. van Reenen"
---
# Report Week 1.2
## volatile
`volatile` is a keyword in c to specify to the comiler it soult not optimize the variable away. This can be usfull for debugging perpeses, if a it is used somewhere the compiler does not reconize or (for example hardwere registers). I learnd this form colleagues on my internship at Erisk.
## assignment 2.2
> will in line 14 and 21^[line numerbers differ from the assignment, becouse change longer lines te prevent linewrapping] to alternate the green and red with oragne and blue.
The pinout is as followed
orange: port D bit 13
green: port D bit 12
red: port D bit 14
blue: port D bit 15
Bit 12 and 14 sould start different as bit 13 and 15. Then invert all four bits every loop to achees the assignment.
I found the defines in the sourcefile where the _modder_ defines are defined.
```c-like=
#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;
// Do forever:
while (1)
{
// Wait a moment
for (volatile int32_t i = 0; i < 1000000; i++);
// Flip all LEDs
GPIOD->ODR ^= GPIO_ODR_OD12
| GPIO_ODR_OD13
| GPIO_ODR_OD14
| GPIO_ODR_OD15;
}
}
```
> How is the assambly generated for line 9 compeard to the magic value `0x55000000`
The compiler regonizes that it can calculate the or opperations at compile time becouse it only used compile time defines as inputs. This reults in the foloing line of assambly.
```asm
mov.w r2, #1426063360 @ 0x55000000
```
## assignment 2.3
skiped
## assignment 2.4
skiped
## assignment 2.5
> Copy the project from assignment 2.2 and update the clock to use the $8 MHz$ external cristal (HSE).
I added line 6 throw 15, the rest is uncheached.
```c-like=
#include <stdint.h>
#include <stm32f4xx.h>
int main(void)
{
// Enable HSE
RCC->CR |= RCC_CR_HSEON;
// Wait until HSE is stable
while ((RCC->CR & RCC_CR_HSERDY) == 0);
// Select HSE as the system clock
RCC->CFGR |= RCC_CFGR_SW_HSE;
// Wait until HSE used as the system clock
while ((RCC->CFGR & RCC_CFGR_SWS_HSE ) == 0);
// Disable HSI
RCC->CR &= ~RCC_CR_HSION;
// 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;
// Do forever:
while (1)
{
// Wait a moment
for (volatile int32_t i = 0; i < 1000000; i++);
// Flip all LEDs
GPIOD->ODR ^= GPIO_ODR_OD12
| GPIO_ODR_OD13
| GPIO_ODR_OD14
| GPIO_ODR_OD15;
}
}
```
I mesured the toggle time to be around 1.5 seconsds. This is what is expected.
> Make use of the PLL to acheef a CPU clock of $100MHz$.
First the power modules needs to be configured to allow for the hige clockspeed.
```c-like
// enable power control
RCC->APB1ENR |= RCC_APB1ENR_PWREN;
// set voltage to support 100 MHz
PWR->CR |= PWR_CR_VOS_0 | PWR_CR_VOS_1;
```
Now the flash latancy is set. The powersupply on the board is $3V$. This means there sould be 3 wait states.
![](https://live.kladjes.nl/uploads/64ef314f-35ef-4435-9d24-16a72257f785.png)
```c-like
// set flash latency to support 100 MHz
FLASH->ACR |= FLASH_ACR_LATENCY_3WS;
// Wait until the wait states are used
while ((FLASH->ACR & /* ... */ ) == 0);
```
Finaly we configur the PLL itself.
$$
f_{(VCO\ clock)} = f_{(PLL\ clock\ input)} \cdot (\frac{PLLN}{PLLM}) \\
f_{(PLL\ general\ clock\ output)} = \frac{f_{(VCO\ clock)}}{PLLP}
$$
$f_{(PLL\ clock\ input)} = 8 MHz$
$f_{(PLL\ general\ clock\ output)} = 100 MHz$
$100 MHz \leq f_{(VCO\ clock)} \leq 432 MHz$
$PLLP \rightarrow \{2, 4, 6, 8\}$
$50 \leq PLLN \leq 432$
$2 \leq PLLM \leq 63$
Becouse of the liminitan of $PLLP$, $f_{(VCO\ clock)}$ can only be 200 or 400 MHz to acheve the correct $f_{(PLL\ general\ clock\ output)}$.
...

386
report-2/week_1.3.md Normal file
View File

@ -0,0 +1,386 @@
---
sub_title: "Real Time Systems 10"
auther:
- name: "Finley van Reenen"
email: "mail@lailatheelf.nl"
name_short: "E.L.F. van Reenen"
---
# Week 1.3
## assignment 3.1
base project [opdr_2_1](/assets/opdr_2_1.zip).
```c
#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
STK_CTRL = (1<<2) | 1;
STK_LOAD = 500000; // 0.5 sec / (8 MHz / 8)
// Do forever:
while (1)
{
// Wait a moment
while ((STK_CTRL & (1 << 16)) == 0);
// Flip all LEDs
GPIOD_ODR ^= 0xF000;
}
}
```
## assignment 3.2
```c
#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 = 500000; // 0.5 sec / (8 MHz / 8)
// 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;
}
}
```
## assignment 3.3
```c
#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 = 500000; // 0.5 sec / (8 MHz / 8)
// Do forever:
while (1)
{
// Wait a moment
while (!flag)
{
__asm__(" WFI"); // sleep until SysTick
}
flag = false;
// Flip all LEDs
GPIOD_ODR ^= 0xF000;
}
}
```
> C) Why must the flag variable be defined as volatile?
becouse the compiler doesn't know when `flag` changes. Without `volatile` optimisations can think it does not change at all.
## assignment 3.4
```c
#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 = 500000; // 0.5 sec / (8 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;
}
}
```
## assignment 3.5
```c
#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 | 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 = 500000; // 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;
}
}
}
}
```
## assignment 3.6
```c
#include <stdint.h>
#include <stm32f4xx.h>
#include <stdbool.h>
volatile uint32_t ISR_Ticks = 0;
struct TASK {
void* fn,
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, uint32_t counter)
{
if (Tasks_len >= 8) {
return false;
}
Tasks[Task_len].fn = fn;
Tasks[Task_len].counter = counter;
Tasks[Task_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 = 1000; // 1 ms / (8 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;
for (uint8_t int=0; i<Tasks_len; i++)
{
if (Tasks[i].counter > ticks)
{
Tasks[i].counter -= ticks;
}
else
{
Tasks[i].counter = 0;
}
}
for (uint8_t int=0; i<Tasks_len; i++)
{
if (Tasks[i].counter == 0)
{
(&(Tasks[i].fn))();
}
}
}
}
```

1
wiki Submodule

@ -0,0 +1 @@
Subproject commit ac9f6543bc2e182a14b2467046fc28cffcf97af8