unpriviledged sleep wip

master
tcsullivan 6 years ago
parent c66410f631
commit 34684b28a4

@ -0,0 +1,25 @@
#!/bin/bash
#
# @file run.sh
# Starts openocd and connects gdb to the target, for programming/debugging
#
# Copyright (C) 2018 Clyne Sullivan
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
#
openocd -f /usr/share/openocd/scripts/board/st_nucleo_l476rg.cfg &
sleep 1
gdb-multiarch -ex "target remote localhost:3333" main.elf
pkill openocd

@ -19,6 +19,7 @@
*/ */
#include "clock.h" #include "clock.h"
#include "task.h"
#include <arch/stm/stm32l476xx.h> #include <arch/stm/stm32l476xx.h>
// ticks since init // ticks since init
@ -26,9 +27,16 @@ volatile uint32_t ticks = 0;
volatile uint8_t tim2_finished = 1; volatile uint8_t tim2_finished = 1;
extern task_t *current;
void clock_svc(uint32_t *args) void clock_svc(uint32_t *args)
{ {
udelay(args[0]); if (args[0] == 0) {
current->sleep = ticks + args[1];
SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk;
} else if (args[0] == 1) {
udelay(args[1]);
}
} }
void clock_init(void) void clock_init(void)
@ -71,6 +79,11 @@ void clock_init(void)
TIM2->CR1 |= TIM_CR1_OPM | TIM_CR1_CEN; TIM2->CR1 |= TIM_CR1_OPM | TIM_CR1_CEN;
} }
uint32_t millis(void)
{
return ticks;
}
void delay(uint32_t count) void delay(uint32_t count)
{ {
uint32_t target = ticks + count; uint32_t target = ticks + count;

@ -28,6 +28,8 @@
*/ */
extern void clock_init(void); extern void clock_init(void);
uint32_t millis(void);
/** /**
* Sleeps for given amount of milliseconds. * Sleeps for given amount of milliseconds.
* @param ms Number of milliseconds to sleep for * @param ms Number of milliseconds to sleep for

@ -27,6 +27,7 @@
extern uint8_t __bss_end__; extern uint8_t __bss_end__;
extern void user_main(void); extern void user_main(void);
void init_idle(void);
int main(void) int main(void)
{ {
@ -46,7 +47,14 @@ int main(void)
// enable FPU // enable FPU
//SCB->CPACR |= (0xF << 20); //SCB->CPACR |= (0xF << 20);
task_init(user_main); task_init(init_idle, 512);
while (1); while (1);
} }
void init_idle(void)
{
task_start(user_main, 4096);
while (1)
delay(100);
}

@ -18,8 +18,9 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
#include "task.h" #include "clock.h"
#include "heap.h" #include "heap.h"
#include "task.h"
#include <arch/stm/stm32l476xx.h> #include <arch/stm/stm32l476xx.h>
task_t *current, *prev; task_t *current, *prev;
@ -71,7 +72,7 @@ void task_crt0(void)
"); ");
} }
task_t *task_create(void (*code)(void), uint32_t stackSize) task_t *task_create(void (*code)(void), uint16_t stackSize)
{ {
task_t *t = (task_t *)malloc(sizeof(task_t)); task_t *t = (task_t *)malloc(sizeof(task_t));
t->next = 0; t->next = 0;
@ -95,15 +96,16 @@ task_t *task_create(void (*code)(void), uint32_t stackSize)
t->sp[14] = (uint32_t)code; t->sp[14] = (uint32_t)code;
t->sp[15] = (uint32_t)task_crt0; t->sp[15] = (uint32_t)task_crt0;
t->sp[16] = 0x01000000; t->sp[16] = 0x01000000;
t->sleep = 0;
return t; return t;
} }
void task_init(void (*init)(void)) void task_init(void (*init)(void), uint16_t stackSize)
{ {
current = (task_t *)malloc(sizeof(task_t)); current = (task_t *)malloc(sizeof(task_t));
current->stack = 0; current->stack = 0;
task_t *init_task = task_create(init, 4096); task_t *init_task = task_create(init, stackSize);
prev = init_task; prev = init_task;
current->next = init_task; current->next = init_task;
@ -166,33 +168,29 @@ void PendSV_Handler(void)
if (task_disable != 0) if (task_disable != 0)
asm("bx lr"); asm("bx lr");
// TODO why, and what does this do
// TODO get back to c, implement task sleeping // TODO get back to c, implement task sleeping
// Save current stack pointer
asm("\ asm("\
mrs r0, psp; \ mrs r0, psp; \
isb; \ isb; \
ldr r1, =current; \
ldr r2, [r1]; \
stmdb r0!, {r4-r11, r14}; \ stmdb r0!, {r4-r11, r14}; \
str r0, [r2, #8]; \ mov %0, r0; \
ldr r0, [r2, #0]; \ " : "=r" (current->sp));
ldr r3, =prev; \
str r2, [r3]; \ // Load next task
str r0, [r1]; \ uint32_t ticks = millis();
ldr r2, [r1]; \ do {
ldr r0, [r2, #8]; \ current = current->next;
} while (current->sleep > ticks);
current->sleep = 0;
// Load stack pointer, return
asm("\
mov r0, %0; \
ldmia r0!, {r4-r11, r14}; \ ldmia r0!, {r4-r11, r14}; \
msr psp, r0; \ msr psp, r0; \
bx lr; \ bx lr; \
"); " :: "r" (current->sp));
// r1 = current
// r2 = *current
// r0 = sp
// *current.sp = sp
// r0 = current->next
// current = r0
// r2 = *current
// r0 = *current.sp
// unpack
} }

@ -30,6 +30,7 @@ typedef struct {
void *next; /**< pointer to the next task_t instance */ void *next; /**< pointer to the next task_t instance */
uint32_t *stack; /**< pointer to the task's stack */ uint32_t *stack; /**< pointer to the task's stack */
uint32_t *sp; /**< pointer to the task's last sp register value */ uint32_t *sp; /**< pointer to the task's last sp register value */
uint32_t sleep; /**< number of milliseconds task is sleeping for */
} task_t; } task_t;
/** /**
@ -37,7 +38,7 @@ typedef struct {
* This task is given a 4kb stack. * This task is given a 4kb stack.
* @param init the initial thread to run * @param init the initial thread to run
*/ */
void task_init(void (*init)(void)); void task_init(void (*init)(void), uint16_t stackSize);
/** /**
* Starts a new task. * Starts a new task.

@ -5,7 +5,16 @@
void task1(void); void task1(void);
void task2(void); void task2(void);
void user_delay(uint32_t ms)
{
register uint32_t r1 asm("r1") = ms;
asm("\
mov r0, 0; \
mov r1, %0; \
svc 2; \
" :: "r" (r1));
}
void user_main(void) void user_main(void)
{ {
@ -14,22 +23,22 @@ void user_main(void)
for (int i = 0; i < 8; i++) { for (int i = 0; i < 8; i++) {
gpio(GPIO_OUT, 5, !(i & 1)); gpio(GPIO_OUT, 5, !(i & 1));
delay(200); user_delay(200);
} }
} }
void task1(void) void task1(void)
{ {
delay(400); user_delay(400);
task_start(task2, 1024); task_start(task2, 1024);
} }
void task2(void) void task2(void)
{ {
int state = 0; int state = 0;
delay(2500); user_delay(2500);
while (1) { while (1) {
gpio(GPIO_OUT, 5, state ^= 1); gpio(GPIO_OUT, 5, state ^= 1);
delay(500); user_delay(500);
} }
} }

Loading…
Cancel
Save