Skip to content

Commit 4b57c92

Browse files
committed
Added a test function to raise the PendSV flag (in C and Assembly)
PendSV is a special software-initiated interrupt in the ARM chip architecture, needed to copy the context (stack and intermediate data) of tasks into RAM (after executing the PendSV interrupt handler, it is assumed that another task will be executed)
1 parent 855e99e commit 4b57c92

11 files changed

Lines changed: 137 additions & 30 deletions

File tree

doc/asm/create_tasks_explainig.md

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,11 @@ And here we go - look at `create_tasks.S` file - there's include! But...what the
66
What moves the data from .c-file into .h-file? Makefile does. And it does it with a regular expression: `'s/^-> \([^ ]*\) [\$$#]\?\([^ ]*\).*/#define \1 \2/p'`. This shit is absolutely fucked up. In two words it searches the string from .c-file where macro works and inserts needed data when it needs. Then, in the `gen_offsets.c` file are a couple of this things - and actually these data is Makefile searches for. This data what we can get after executing the macro
77
Let's break down the mechanics:
88
1. Search and Boundaries (.* at the beginning and end) .* at the beginning and end means "I don't care what comes before our -> arrow and what comes after the number." The compiler often adds tabs or comments on the same line. This expression tells sed to discard all unnecessary stuff and keep only what we'll extract into the "pockets."
9-
2. Marker and Spaces (->[[:space:]]*). -> is our hard-coded "anchor." [[:space:]]* is a very important part. It means "any number of spaces or tabs." Different versions of gcc may indent the line after the arrow differently, and this command makes the search universal.
10-
3. First Pocket: Constant Name (\([A-Z_0-9]*\)). \( ... \) are "remembering brackets" (pockets). Whatever ends up here, we'll later call it with \1.
11-
[A-Z_0-9]* — we only allow uppercase letters, numbers, and underscores in the name. This is the standard for #define.
12-
4. Garbage before a number ([#$$]\?). In ARM assembler, constants are often written as #12 or $12. [#$$]\?] says: "There might be a # or $ symbol here, or there might not be one (?)." We find this symbol, but don't put it in the pocket, thereby simply deleting it.
13-
5. Second pocket: Value (\([0-9]*\)). \([0-9]*\) — we only take digits. This value will go in \2.
14-
6. Replacement (/#define \1 \2/p). This is where the constructor is assembled. sed takes the word from the first pocket and the number from the second, then concatenates them into a ready-made C string: #define SCH_TASK_SIZE 12.
9+
2. Marker and Spaces `(->[[:space:]]*). -> is our hard-coded "anchor." [[:space:]]*` is a very important part. It means "any number of spaces or tabs." Different versions of gcc may indent the line after the arrow differently, and this command makes the search universal.
10+
3. First Pocket: Constant Name `(\([A-Z_0-9]*\))`. `\( ... \)` are "remembering brackets" (pockets). Whatever ends up here, we'll later call it with `\1. [A-Z_0-9]*` — we only allow uppercase letters, numbers, and underscores in the name. This is the standard for `#define`.
11+
4. Garbage before a number `([#$$]\?)`. In ARM assembler, constants are often written as `#12` or `$12`. `[#$$]\?]` says: "There might be a # or $ symbol here, or there might not be one (?)." We find this symbol, but don't put it in the pocket, thereby simply deleting it.
12+
5. Second pocket: Value `(\([0-9]*\))`. `\([0-9]*\)` — we only take digits. This value will go in \2.
13+
6. Replacement `(/#define \1 \2/p)`. This is where the constructor is assembled. sed takes the word from the first pocket and the number from the second, then concatenates them into a ready-made C string: `#define SCH_TASK_SIZE 12`.
1514

1615
The p flag at the end (along with sed's -n switch) forces the utility to print only those lines where the replacement was successful. All other assembly code from gen_offsets.s is simply removed.
1716

examples/stm32f4x/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ app/src/syscalls.c \
4949
app/src/sysmem.c \
5050
../../sch/src/sch.c \
5151
../../sch/port/stm32f4xx/sch_find_most_significant_task.s \
52+
../../sch/port/stm32f4xx/sch_context_change.s \
5253

5354
all: $(TARGET).elf
5455

examples/stm32f4x/app/src/main.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ int main(void)
2626
MX_GPIO_Init();
2727
MX_USART2_UART_Init();
2828

29+
sch_task_t first_task;
30+
sch_task_t second_task;
31+
sch_task_t echo_data;
32+
sch_task_t another_system_task;
33+
2934
sch_task_create(&first_task, -3, 0, sch_task_dispatch, sch_task_init);
3035
sch_task_activate(&first_task);
3136

sch/inc/sch.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,10 @@ extern "C" {
1919

2020
#include "sch_config.h"
2121
#include "sch_assertion.h"
22-
#include "sch_change_of_context.h"
22+
#include "sch_context_change.h"
2323
#include "sch_common.h"
2424
#include "sch_task_management.h"
25+
#include "sch_event_management.h"
2526

2627
#ifdef __cplusplus
2728
}

sch/inc/sch_change_of_context.h

Lines changed: 0 additions & 22 deletions
This file was deleted.

sch/inc/sch_context_change.h

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#ifndef SCH_CHANGE_OF_CONTEXT_H
2+
#define SCH_CHANGE_OF_CONTEXT_H
3+
4+
#ifdef __cplusplus
5+
extern "C" {
6+
#endif
7+
8+
#include "sch_common.h"
9+
10+
/**
11+
* @brief Function for finding the most significant task flag
12+
* in the "registry" what'd been imaged in variable
13+
*
14+
* @param sch_system_tasks_ready_set
15+
*/
16+
uint8_t sch_find_most_significant_task(uint32_t sch_system_tasks_ready_set);
17+
18+
/**
19+
* @brief Function for changing the context
20+
*
21+
*/
22+
void sch_context_change(void);
23+
24+
/**
25+
* @brief Function for planning goddammit
26+
*
27+
*/
28+
void sch_call_dispatch(uint8_t sch_most_significant_task);
29+
30+
/**
31+
* @brief Function an optional function that is executed as
32+
* a postcondition after calling the context change function
33+
*
34+
* @return void
35+
*/
36+
__WEAK void sch_context_change_postfunc(void);
37+
38+
#ifdef __cplusplus
39+
}
40+
#endif
41+
42+
#endif

sch/inc/sch_event_management.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#ifndef SCH_EVENT_MANAGEMENT_H
2+
#define SCH_EVENT_MANAGEMENT_H
3+
4+
#ifdef __cplusplus
5+
extern "C" {
6+
#endif
7+
8+
typedef struct {
9+
uint16_t sig;
10+
} sch_event_header;
11+
12+
typedef struct {
13+
sch_event_header event_header;
14+
int16_t first_data;
15+
int16_t second_data;
16+
} sch_event;
17+
18+
#ifdef __cplusplus
19+
}
20+
#endif
21+
22+
#endif
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/**
2+
* @file sch_change_of_context.c
3+
* @author Mike Strangewood (michael.a.strangewood@gmail.com)
4+
* @brief
5+
* @version 0.1
6+
* @date 2026-01-07
7+
*/
8+
9+
/*
10+
Note:
11+
i'll try to correct the pathes and architecture of the project actually,
12+
but for now you can use the implementation of fucntions in C or in ASM,
13+
choosing actually the implementation in Makefile for concrete project in
14+
the folder 'examples/PROJECT_NAME/Makefile', and there you can even change
15+
the source file in there...but be careful
16+
*/
17+
18+
#include "sch_change_of_context.h"
19+
20+
#define SCH_SCS_BASE (0xE000E000UL)
21+
#define SCH_ICSR_OFFSET (0xD04)
22+
#define SCH_ICSR (*(volatile uint32_t*)(SCH_SCS_BASE + SCH_ICSR_OFFSET))
23+
#define SCH_ICSR_PENDSVET_BIT (1UL << 28)
24+
25+
void sch_context_change(void) {
26+
SCH_ICSR = SCH_ICSR_PENDSVET_BIT;
27+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
.thumb
2+
.cpu cortex-m4
3+
4+
.equ __sch_scs_base, (0xE000E000UL)
5+
.equ __sch_icsr_offset, (0xD04)
6+
.equ __sch_icsr, (__sch_scs_base + __sch_icsr_offset)
7+
.equ __sch_icsr_pendvset, (1 << 28)
8+
9+
.section .text.sch_context_change
10+
11+
.type sch_context_change, %function
12+
.type sch_call_dispatch, %function
13+
14+
15+
.global sch_call_dispatch
16+
sch_call_dispatch:
17+
ldr r1, =sch_task_registry
18+
lsl r0, r0, #2
19+
add r0, r1, r0
20+
ldr r0, [r0]
21+
ldr r3, [r0]
22+
blx r3
23+
bx lr
24+
25+
26+
.global sch_context_change
27+
sch_context_change:
28+
ldr r0, =__sch_icsr
29+
ldr r1, =__sch_icsr_pendvset
30+
str r1, [r0]
31+
bx lr

sch/port/stm32f4xx/sch_find_most_significant_task.s

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,4 @@ sch_find_most_significant_task:
1313
.is_data_zero:
1414
mov r0, #0
1515
bx lr
16+

0 commit comments

Comments
 (0)