You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
220 lines
4.2 KiB
220 lines
4.2 KiB
#define MAX_TASKS 2
|
|
#define TASK_STACK_SIZE 256
|
|
|
|
#include "stm32g431xx.h"
|
|
#include "string.h"
|
|
|
|
typedef unsigned int uint;
|
|
|
|
volatile uint32_t sec = 0;
|
|
int task_counter = 0;
|
|
bool stop = false;
|
|
|
|
struct Contexter
|
|
{
|
|
uint R0;
|
|
uint R1;
|
|
uint R2;
|
|
uint R3;
|
|
uint R12;
|
|
uint LR; // адрес возврата из ПП
|
|
uint PC; // счётки команд, на какой остановилась работа ПП
|
|
uint xPSR; // регистр состояния
|
|
};
|
|
|
|
struct Task
|
|
{
|
|
uint sizeStack;
|
|
uint *stack;
|
|
int (*task)();
|
|
bool isActive;
|
|
bool isFirstRun;
|
|
uint returnError;
|
|
};
|
|
|
|
Task task_list[MAX_TASKS];
|
|
|
|
Task myZeroTask;
|
|
uint zeroStack[sizeof(Contexter)];
|
|
|
|
void PendSV_mainHandler();
|
|
|
|
extern "C" void SysTick_Handler()
|
|
{
|
|
sec++;
|
|
SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk;
|
|
}
|
|
|
|
extern "C" __task __stackless void PendSV_Handler(void)
|
|
{
|
|
if (stop)
|
|
{
|
|
asm volatile("MRS %0, PSP" : "=r"(myZeroTask.stack));
|
|
PendSV_mainHandler();
|
|
}
|
|
|
|
asm volatile(
|
|
"CMP R1, #1 \n"
|
|
"IT EQ \n"
|
|
"MSREQ PSP, R0 \n" // если первый раз запускается задача, загружаем указатель на стек из памяти
|
|
|
|
"MRS R0, PSP \n"
|
|
"STMDB R0!, {R4-R11} \n" // Закидываем в стек r4-r11
|
|
"MSR PSP, R0 \n" ::
|
|
|
|
"R0"(task_list[task_counter].stack),
|
|
"R1"(task_list[task_counter].isFirstRun));
|
|
|
|
asm volatile("mov %0, R0" : "=r"(task_list[task_counter].stack));
|
|
|
|
task_list[task_counter].isFirstRun = false;
|
|
|
|
PendSV_mainHandler();
|
|
}
|
|
|
|
void __stackless PendSV_mainHandler()
|
|
{
|
|
// Ищём следующую активную задачу для переключения на неё.
|
|
Task *myTask;
|
|
|
|
int lastIndex = task_counter;
|
|
|
|
do
|
|
{
|
|
task_counter++;
|
|
|
|
if (task_counter > MAX_TASKS - 1)
|
|
task_counter = 0;
|
|
|
|
myTask = &task_list[task_counter];
|
|
|
|
if (myTask->isActive)
|
|
{
|
|
asm volatile("MSR PSP, %[psp]" ::[psp] "r"(myTask->stack));
|
|
|
|
if (!myTask->isFirstRun)
|
|
asm volatile(
|
|
"MRS r0, PSP \n" // Получаем PSP в r0
|
|
"LDMIA r0!, {r4-r11}\n" // Восстанавливаем r4-r11 из стека
|
|
"MSR PSP, r0 \n" // Обновляем PSP
|
|
);
|
|
else
|
|
myTask->isFirstRun = false;
|
|
|
|
asm("mov LR, #0xFFFFFFFD");
|
|
|
|
stop = false;
|
|
|
|
return;
|
|
}
|
|
|
|
} while (task_counter != lastIndex);
|
|
|
|
// Если не нашли активную задачу переходим в заглущку
|
|
asm volatile("" ::"R0"(myZeroTask.stack));
|
|
|
|
asm volatile(
|
|
"MSR PSP, R0 \n" // Обновляем PSP
|
|
);
|
|
|
|
asm volatile("mov LR, #0xFFFFFFFD");
|
|
stop = true;
|
|
}
|
|
|
|
int func1();
|
|
int func2();
|
|
|
|
uint func1Stack[TASK_STACK_SIZE];
|
|
uint func2Stack[TASK_STACK_SIZE];
|
|
|
|
int a, b, c;
|
|
|
|
int func1()
|
|
{
|
|
int arr[10] = {0xab};
|
|
while (1)
|
|
{
|
|
a++;
|
|
// asm("mov R4, #0x12");
|
|
// asm("mov R5, #0x34");
|
|
// asm("mov R6, #0x56");
|
|
}
|
|
}
|
|
|
|
int func2()
|
|
{
|
|
while (1)
|
|
{
|
|
b++;
|
|
// asm("mov R5, #0x79");
|
|
}
|
|
}
|
|
|
|
int mute()
|
|
{
|
|
while (1)
|
|
{
|
|
}
|
|
}
|
|
|
|
int newTask(int (*new_task)(), uint *stack, uint size)
|
|
{
|
|
static int task_index = 0;
|
|
|
|
Task &myTask = task_list[task_index];
|
|
|
|
myTask.stack = stack + size - sizeof(Contexter) / sizeof(uint);
|
|
|
|
myTask.sizeStack = size;
|
|
myTask.task = new_task;
|
|
|
|
myTask.isActive = true;
|
|
myTask.isFirstRun = true;
|
|
|
|
Contexter *cx = (Contexter *)myTask.stack;
|
|
|
|
cx->PC = (uint)new_task;
|
|
cx->xPSR = 0x01000000;
|
|
cx->LR = 0x0800029b; // LR - 0xFFFFFFFD (Возвращаемся в Thread режим, используем стек процесса PSP)
|
|
|
|
task_index++;
|
|
|
|
return task_index;
|
|
}
|
|
|
|
void zeroTask(int (*new_task)(), uint *stack, uint size)
|
|
{
|
|
Task &myTask = myZeroTask;
|
|
|
|
myTask.stack = stack + (size - sizeof(Contexter)) / sizeof(uint);
|
|
|
|
myTask.sizeStack = size;
|
|
myTask.task = new_task;
|
|
|
|
myTask.isActive = false;
|
|
|
|
Contexter *cx = (Contexter *)myTask.stack;
|
|
|
|
cx->PC = (uint)new_task;
|
|
cx->xPSR = 0x01000000;
|
|
cx->LR = 0x0800029b;
|
|
}
|
|
|
|
int main()
|
|
{
|
|
int aaa[100];
|
|
|
|
aaa[99] = 0;
|
|
|
|
SysTick_Config(SystemCoreClock);
|
|
|
|
Task *muteVoid;
|
|
zeroTask(mute, zeroStack, sizeof(Contexter));
|
|
|
|
newTask(func1, func1Stack, TASK_STACK_SIZE);
|
|
newTask(func2, func2Stack, TASK_STACK_SIZE);
|
|
|
|
while (true)
|
|
{
|
|
}
|
|
} |