diff --git a/run.sh b/run.sh
new file mode 100755
index 0000000..a7efaa1
--- /dev/null
+++ b/run.sh
@@ -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 .
+#
+
+openocd -f /usr/share/openocd/scripts/board/st_nucleo_l476rg.cfg &
+sleep 1
+gdb-multiarch -ex "target remote localhost:3333" main.elf
+pkill openocd
diff --git a/src/kernel/clock.c b/src/kernel/clock.c
index 44b7722..5bfc93a 100644
--- a/src/kernel/clock.c
+++ b/src/kernel/clock.c
@@ -19,6 +19,7 @@
*/
#include "clock.h"
+#include "task.h"
#include
// ticks since init
@@ -26,9 +27,16 @@ volatile uint32_t ticks = 0;
volatile uint8_t tim2_finished = 1;
+extern task_t *current;
+
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)
@@ -71,6 +79,11 @@ void clock_init(void)
TIM2->CR1 |= TIM_CR1_OPM | TIM_CR1_CEN;
}
+uint32_t millis(void)
+{
+ return ticks;
+}
+
void delay(uint32_t count)
{
uint32_t target = ticks + count;
diff --git a/src/kernel/clock.h b/src/kernel/clock.h
index c3554f6..3ec7857 100644
--- a/src/kernel/clock.h
+++ b/src/kernel/clock.h
@@ -28,6 +28,8 @@
*/
extern void clock_init(void);
+uint32_t millis(void);
+
/**
* Sleeps for given amount of milliseconds.
* @param ms Number of milliseconds to sleep for
diff --git a/src/kernel/init.c b/src/kernel/init.c
index e4ac115..ca60c3e 100644
--- a/src/kernel/init.c
+++ b/src/kernel/init.c
@@ -27,6 +27,7 @@
extern uint8_t __bss_end__;
extern void user_main(void);
+void init_idle(void);
int main(void)
{
@@ -46,7 +47,14 @@ int main(void)
// enable FPU
//SCB->CPACR |= (0xF << 20);
- task_init(user_main);
+ task_init(init_idle, 512);
while (1);
}
+void init_idle(void)
+{
+ task_start(user_main, 4096);
+
+ while (1)
+ delay(100);
+}
diff --git a/src/kernel/task.c b/src/kernel/task.c
index 1a1c16b..19fa5ea 100644
--- a/src/kernel/task.c
+++ b/src/kernel/task.c
@@ -18,8 +18,9 @@
* along with this program. If not, see .
*/
-#include "task.h"
+#include "clock.h"
#include "heap.h"
+#include "task.h"
#include
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));
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[15] = (uint32_t)task_crt0;
t->sp[16] = 0x01000000;
+ t->sleep = 0;
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->stack = 0;
- task_t *init_task = task_create(init, 4096);
+ task_t *init_task = task_create(init, stackSize);
prev = init_task;
current->next = init_task;
@@ -166,33 +168,29 @@ void PendSV_Handler(void)
if (task_disable != 0)
asm("bx lr");
- // TODO why, and what does this do
// TODO get back to c, implement task sleeping
+
+ // Save current stack pointer
asm("\
mrs r0, psp; \
isb; \
- ldr r1, =current; \
- ldr r2, [r1]; \
stmdb r0!, {r4-r11, r14}; \
- str r0, [r2, #8]; \
- ldr r0, [r2, #0]; \
- ldr r3, =prev; \
- str r2, [r3]; \
- str r0, [r1]; \
- ldr r2, [r1]; \
- ldr r0, [r2, #8]; \
+ mov %0, r0; \
+ " : "=r" (current->sp));
+
+ // Load next task
+ uint32_t ticks = millis();
+ do {
+ current = current->next;
+ } while (current->sleep > ticks);
+ current->sleep = 0;
+
+ // Load stack pointer, return
+ asm("\
+ mov r0, %0; \
ldmia r0!, {r4-r11, r14}; \
msr psp, r0; \
bx lr; \
- ");
- // r1 = current
- // r2 = *current
- // r0 = sp
- // *current.sp = sp
- // r0 = current->next
- // current = r0
- // r2 = *current
- // r0 = *current.sp
- // unpack
+ " :: "r" (current->sp));
}
diff --git a/src/kernel/task.h b/src/kernel/task.h
index 3d331ae..472e909 100644
--- a/src/kernel/task.h
+++ b/src/kernel/task.h
@@ -30,6 +30,7 @@ typedef struct {
void *next; /**< pointer to the next task_t instance */
uint32_t *stack; /**< pointer to the task's stack */
uint32_t *sp; /**< pointer to the task's last sp register value */
+ uint32_t sleep; /**< number of milliseconds task is sleeping for */
} task_t;
/**
@@ -37,7 +38,7 @@ typedef struct {
* This task is given a 4kb stack.
* @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.
diff --git a/src/user/user.c b/src/user/user.c
index fc51d29..0bb2607 100644
--- a/src/user/user.c
+++ b/src/user/user.c
@@ -5,7 +5,16 @@
void task1(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)
{
@@ -14,22 +23,22 @@ void user_main(void)
for (int i = 0; i < 8; i++) {
gpio(GPIO_OUT, 5, !(i & 1));
- delay(200);
+ user_delay(200);
}
}
void task1(void)
{
- delay(400);
+ user_delay(400);
task_start(task2, 1024);
}
void task2(void)
{
int state = 0;
- delay(2500);
+ user_delay(2500);
while (1) {
gpio(GPIO_OUT, 5, state ^= 1);
- delay(500);
+ user_delay(500);
}
}