aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakob Odersky <jodersky@gmail.com>2014-03-30 22:38:35 +0200
committerJakob Odersky <jodersky@gmail.com>2014-03-30 22:38:35 +0200
commitf93ab955074e213ad6f2bf60522cc86952d57d83 (patch)
tree65af07c02d6f0541f31cddef9cd564189395952b
parent2500120f64db83fc682f38a83f7f9e03ed8a5123 (diff)
downloadmux-f93ab955074e213ad6f2bf60522cc86952d57d83.tar.gz
mux-f93ab955074e213ad6f2bf60522cc86952d57d83.tar.bz2
mux-f93ab955074e213ad6f2bf60522cc86952d57d83.zip
major update
-rw-r--r--Makefile2
-rw-r--r--kernel/io/include/io/usart.h31
-rw-r--r--kernel/io/usart.c (renamed from kernel/serial/serial.c)76
-rw-r--r--kernel/sched/include/sched/idle.h6
-rw-r--r--kernel/sched/include/sched/sched.h115
-rw-r--r--kernel/sched/mcu/atmega2560/context.c98
-rw-r--r--kernel/sched/mcu/atmega2560/include/mcu/sched/context.h121
-rw-r--r--kernel/sched/sched.c84
-rw-r--r--kernel/serial/include/serial/serial.h51
-rw-r--r--kernel/task/idle.c (renamed from kernel/sched/idle.c)5
-rw-r--r--kernel/task/include/task/sched.h2
-rw-r--r--kernel/task/include/task/task.h19
-rw-r--r--kernel/task/sched.c10
-rw-r--r--main.c42
-rw-r--r--shell.c1
-rw-r--r--test/locks/main.c55
-rw-r--r--test/scheduler/main.c59
17 files changed, 223 insertions, 554 deletions
diff --git a/Makefile b/Makefile
index e7d4dc5..17cb279 100644
--- a/Makefile
+++ b/Makefile
@@ -12,7 +12,7 @@ SERIAL=/dev/ttyACM0
BAUD=115200
# Modules to include in kernel
-MODULES=bug collection task tshield time
+MODULES=bug collection task tshield time io
# Toolchain flags
CC=avr-gcc
diff --git a/kernel/io/include/io/usart.h b/kernel/io/include/io/usart.h
new file mode 100644
index 0000000..62e2768
--- /dev/null
+++ b/kernel/io/include/io/usart.h
@@ -0,0 +1,31 @@
+#ifndef SERIAL_H
+#define SERIAL_H
+
+#include "collection/rbuffer.h"
+#include "collection/list.h"
+
+#define USARTS 1
+#define USART_BUFFER_SIZE 64
+
+struct usart_device_t {
+ volatile char __rx_buffer[USART_BUFFER_SIZE];
+ volatile char __tx_buffer[USART_BUFFER_SIZE];
+
+ struct rbuffer_t rx_buffer;
+ struct rbuffer_t tx_buffer;
+
+ struct list_head rx_queue;
+ struct list_head tx_queue;
+};
+
+#define USART_DEVICE_INIT(name) \
+ { \
+ .rx_buffer = RBUFFER_ARRAY_INIT(name.__rx_buffer, USART_BUFFER_SIZE), \
+ .tx_buffer = RBUFFER_ARRAY_INIT(name.__tx_buffer, USART_BUFFER_SIZE), \
+ .rx_queue = LIST_HEAD_INIT(name.rx_queue), \
+ .tx_queue = LIST_HEAD_INIT(name.tx_queue) \
+ }
+
+void usart_init(unsigned long baud);
+
+#endif \ No newline at end of file
diff --git a/kernel/serial/serial.c b/kernel/io/usart.c
index e7d52a7..2046630 100644
--- a/kernel/serial/serial.c
+++ b/kernel/io/usart.c
@@ -1,82 +1,70 @@
+
+#include <stddef.h>
+#include <stdio.h>
#include <avr/interrupt.h>
-#include "serial/serial.h"
-#include "sched/sched.h"
+#include "task/sched.h"
+#include "io/usart.h"
#include "bug/debug.h"
+#include "mcu/task/context.h"
- FILE serial_out = FDEV_SETUP_STREAM(serial_putc, NULL, _FDEV_SETUP_WRITE);
- FILE serial_in = FDEV_SETUP_STREAM(NULL, serial_getc, _FDEV_SETUP_READ);
+static struct usart_device_t umain = USART_DEVICE_INIT(umain);
+static int umain_putc(char c);
+static int umain_getc();
-static struct serial_device_t serial = SERIAL_DEVICE_INIT(serial);
+FILE umain_out = FDEV_SETUP_STREAM(umain_putc, NULL, _FDEV_SETUP_WRITE);
+FILE umain_in = FDEV_SETUP_STREAM(NULL, umain_getc, _FDEV_SETUP_READ);
-void serial_init(unsigned long baud) {
+void usart_init(unsigned long baud) {
UCSR0A |= (1 << U2X0); //enable double speed transmission
uint16_t baud_setting = (F_CPU / 4 / baud - 1) / 2;
UBRR0H = baud_setting >> 8;
UBRR0L = baud_setting;
UCSR0B |= (1 << RXEN0) | (1 << TXEN0) | (1 << RXCIE0); // 8-bit, no parity, 1 stop bit
UCSR0B &= ~(1 << UDRIE0);
+ stdout = &umain_out;
+ stdin = &umain_in;
}
-size_t serial_read(char* const data, size_t size) {
- while (rbuffer_empty(&serial.rx_buffer)) {
+int umain_putc(char c) {
+ if (c == '\n') umain_putc('\r');
+ int r = 0;
+ do {
cli();
- sleep_on(&serial.rx_q);
- yield();
- }
- cli();
- size_t r = rbuffer_read(&serial.rx_buffer, data, size);
- sei();
- return r;
-}
-
-size_t serial_write(const char* const data, size_t size) {
- cli();
- size_t r = rbuffer_write(&serial.tx_buffer, data, size);
- sei();
- UCSR0B |= (1 << UDRIE0);
- return r;
+ r = rbuffer_write_char(&umain.tx_buffer, c);
+ sei();
+ UCSR0B |= (1 << UDRIE0);
+ } while (r != 1);
+ return c;
}
-int serial_getc() {
- while (rbuffer_empty(&serial.rx_buffer)) {
+int umain_getc() {
+ while (rbuffer_empty(&umain.rx_buffer)) {
cli();
- sleep_on(&serial.rx_q);
+ sleep_queue(&umain.rx_queue);
yield();
}
cli();
char c = 0;
- size_t r = rbuffer_read_char(&serial.rx_buffer, &c);
+ size_t r = rbuffer_read_char(&umain.rx_buffer, &c);
sei();
if (r) return (int) c;
else return EOF;
}
-int serial_putc(char c) {
- if (c == '\n') serial_putc('\r');
- int r = 0;
- do {
- cli();
- r = rbuffer_write_char(&serial.tx_buffer, c);
- sei();
- UCSR0B |= (1 << UDRIE0);
- } while (r != 1);
- return c;
-}
-
//called when byte is received
ISR(USART0_RX_vect, ISR_NAKED) {
- SAVE_CONTEXT();
+ context_save();
char c = UDR0;
- rbuffer_write_char(&serial.rx_buffer, c);
- wake_all(&serial.rx_q);
- RESTORE_CONTEXT();
+ rbuffer_write_char(&umain.rx_buffer, c);
+ wake_all_queue(&umain.rx_queue);
+ context_restore();
asm volatile ("reti");
}
//called when data register is empty
ISR(USART0_UDRE_vect) {
char c;
- if (rbuffer_read_char(&serial.tx_buffer, &c)) {
+ if (rbuffer_read_char(&umain.tx_buffer, &c)) {
UDR0 = c;
} else {
UCSR0B &= ~(1 << UDRIE0); //buffer empty, disable interruot
diff --git a/kernel/sched/include/sched/idle.h b/kernel/sched/include/sched/idle.h
deleted file mode 100644
index 3b6e40a..0000000
--- a/kernel/sched/include/sched/idle.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef IDLE_H
-#define IDLE_H
-
-void idle_entry(char args);
-
-#endif \ No newline at end of file
diff --git a/kernel/sched/include/sched/sched.h b/kernel/sched/include/sched/sched.h
deleted file mode 100644
index 5db0502..0000000
--- a/kernel/sched/include/sched/sched.h
+++ /dev/null
@@ -1,115 +0,0 @@
-#ifndef SCHED_H
-#define SCHED_H
-
-#include "collection/list.h"
-#include "mcu/sched/context.h"
-
-/** Proposed default stack size, you may use this definition for declaring tasks. */
-#define STACK_SIZE 256
-
-/** Stack size to be allocated for the idle task. */
-#define IDLE_STACK_SIZE 64
-
-/**
- * Task control block, contains runtime
- * information about tasks.
- */
-struct tcb_t {
- /** Stack pointer of this task. (must be first in structure) */
- char* volatile sp;
-
- /** Lowest address of this task's memory (inclusive). */
- char* mem_low;
-
- /** Highest address of this task's memory (inclusive). */
- char* mem_high;
-
- /** Entry function of this task. */
- void (*entry)(char);
-
- /** Current wait queue that this task is in. */
- struct list_head q;
-
- long sleep_left;
-
-};
-
-/**
- * Utility for declaring a task with statically allocated memory.
- * Note: for a task to be scheduled, it must first be spawned (see spawn()).
-*/
-#define DECLARE_TASK(name, stack_size, entry_function) \
- static char declared_stack_##name[stack_size]; \
- static struct tcb_t name = { \
- .sp = 0, \
- .mem_low = declared_stack_##name, \
- .mem_high = declared_stack_##name + stack_size - 1, \
- .entry = entry_function, \
- .q = {}, \
- .sleep_left = 0 \
- };
-
-/**
- * Points to currently executing task. If no scheduling has been enabled,
- * this points to NULL
- */
-extern struct tcb_t* volatile current;
-
-/**
- * Queue that contains all tasks that are ready to be run, awaiting their
- * turn from the scheduler.
- */
-extern struct list_head ready;
-
-/**
- * Stack pointer for operations performed out of task context, including any
- * calls made after SAVE_CONTEXT().
- */
-extern char* volatile kstack;
-
-/**
- * Makes the current task sleep on a specific queue.
- * This moves the current task to the given queue's tail.
- */
-static inline void sleep_on(struct list_head* queue) {
- list_move_tail(&current->q, queue);
-}
-
-/**
- * Wakes all tasks waiting in the given queue.
- * This moves all tasks contained in the queue to the ready queue.
- */
-void wake_all(struct list_head* queue);
-
-/**
- * Initializes the scheduler by setting up kstack, initializing the idle task
- * and selecting the first task to run.
- */
-void sched_init();
-
-/**
- * Enters the scheduler, setting current to the next runnable task.
- */
-void schedule();
-
-/**
- * Ticks the scheduler.
- */
-void sched_tick();
-
-/**
- * Initializes a given task and adds it to the ready queue.
- */
-void spawn(struct tcb_t* const tcb, char args);
-
-/**
- * Voluntarily yields control of the CPU to the scheduler.
- */
-void yield() __attribute__ ( ( naked ) );
-
-void sleep(long ms) __attribute__ ( ( naked) );
-
-#define ENTER_CRITICAL() cli()
-#define EXIT_CRITICAL() sei()
-
-#endif
diff --git a/kernel/sched/mcu/atmega2560/context.c b/kernel/sched/mcu/atmega2560/context.c
deleted file mode 100644
index 10f16a9..0000000
--- a/kernel/sched/mcu/atmega2560/context.c
+++ /dev/null
@@ -1,98 +0,0 @@
-#include "mcu/sched/context.h"
-
-char* init_stack(const char* const mem_low, const char* const mem_high, void (*entry)(char), char args) {
- char* sp = (char*) mem_high;
- unsigned long address = (unsigned long) entry;
-
- // pattern for debugging purposes
- *sp = (char) 0x1;
- sp--;
- *sp = (char) 0x2;
- sp--;
- *sp = (char) 0x1;
- sp--;
- *sp = (char) 0x2;
- sp--;
-
- // put return address on stack
- *sp = (char) ( address & (unsigned short) 0x00ff );
- sp--;
-
- *sp = (char) ( (address >> 8) & ( unsigned short ) 0x00ff );
- sp--;
-
- *sp = (char) ( (address >> 16) & ( unsigned short ) 0x00ff );
- sp--;
-
- // save registers
- *sp = (char) 0x00; //r0
- sp--;
- *sp = (char) 0x80; //SREG, enable interrupts when task starts
- sp--;
- *sp = ( char ) 0x00; //r1
- sp--;
- *sp = ( char ) 0x00; //r2
- sp--;
- *sp = ( char ) 0x00; //r3
- sp--;
- *sp = ( char ) 0x00; //r4
- sp--;
- *sp = ( char ) 0x00; //r5
- sp--;
- *sp = ( char ) 0x00; //r6
- sp--;
- *sp = ( char ) 0x00; //r7
- sp--;
- *sp = ( char ) 0x00; //r8
- sp--;
- *sp = ( char ) 0x00; //r9
- sp--;
- *sp = ( char ) 0x00; //r10
- sp--;
- *sp = ( char ) 0x00; //r11
- sp--;
- *sp = ( char ) 0x00; //r12
- sp--;
- *sp = ( char ) 0x00; //r13
- sp--;
- *sp = ( char ) 0x00; //r14
- sp--;
- *sp = ( char ) 0x00; //r15
- sp--;
- *sp = ( char ) 0x00; //r16
- sp--;
- *sp = ( char ) 0x00; //r17
- sp--;
- *sp = ( char ) 0x00; //r18
- sp--;
- *sp = ( char ) 0x00; //r19
- sp--;
- *sp = ( char ) 0x00; //r20
- sp--;
- *sp = ( char ) 0x00; //r21
- sp--;
- *sp = ( char ) 0x00; //r22
- sp--;
- *sp = ( char ) 0x00; //r23
- sp--;
-
- *sp = (char) ( args ); //place first argument in register 24
- sp--;
-
- *sp = ( char ) 0x00; //r25
- sp--;
- *sp = ( char ) 0x00; //r26
- sp--;
- *sp = ( char ) 0x00; //r27
- sp--;
- *sp = ( char ) 0x00; //r28
- sp--;
- *sp = ( char ) 0x00; //r29
- sp--;
- *sp = ( char ) 0x00; //r30
- sp--;
- *sp = ( char ) 0x00; //r31
- sp--;
-
- return sp;
-}
diff --git a/kernel/sched/mcu/atmega2560/include/mcu/sched/context.h b/kernel/sched/mcu/atmega2560/include/mcu/sched/context.h
deleted file mode 100644
index 437e7f3..0000000
--- a/kernel/sched/mcu/atmega2560/include/mcu/sched/context.h
+++ /dev/null
@@ -1,121 +0,0 @@
-#ifndef CONTEXT_H
-#define CONTEXT_H
-
-#include <avr/interrupt.h>
-
-/*
- * The macros SAVE_CONTEXT(), RESTORE_CONTEXT() as well as the code contained in
- * init_stack is adapted from the FreeRTOS kernel (http://www.freertos.org/).
- * Here by copyright, credits attributed to wherever they belong.
- */
-
-#define SAVE_CONTEXT() \
- asm volatile ( \
- "push r0 \n\t" \
- "in r0, __SREG__ \n\t" \
- "push r0 \n\t" \
- "push r1 \n\t" \
- "clr r1 \n\t" \
- "push r2 \n\t" \
- "push r3 \n\t" \
- "push r4 \n\t" \
- "push r5 \n\t" \
- "push r6 \n\t" \
- "push r7 \n\t" \
- "push r8 \n\t" \
- "push r9 \n\t" \
- "push r10 \n\t" \
- "push r11 \n\t" \
- "push r12 \n\t" \
- "push r13 \n\t" \
- "push r14 \n\t" \
- "push r15 \n\t" \
- "push r16 \n\t" \
- "push r17 \n\t" \
- "push r18 \n\t" \
- "push r19 \n\t" \
- "push r20 \n\t" \
- "push r21 \n\t" \
- "push r22 \n\t" \
- "push r23 \n\t" \
- "push r24 \n\t" \
- "push r25 \n\t" \
- "push r26 \n\t" \
- "push r27 \n\t" \
- "push r28 \n\t" \
- "push r29 \n\t" \
- "push r30 \n\t" \
- "push r31 \n\t" \
- "lds r26, current \n\t" \
- "lds r27, current +1 \n\t" \
- "in r0, __SP_L__ \n\t" \
- "st x+, r0 \n\t" \
- "in r0, __SP_H__ \n\t" \
- "st x+, r0 \n\t" \
- "lds r26, kstack \n\t" \
- "lds r27, kstack + 1 \n\t" \
- "ld r28, x+ \n\t" \
- "out __SP_L__, r28 \n\t" \
- "ld r29, x+ \n\t" \
- "out __SP_H__, r29 \n\t" \
- )
-
-#define RESTORE_CONTEXT() \
- asm volatile ( \
- "lds r26, kstack \n\t" \
- "lds r27, kstack +1 \n\t" \
- "in r0, __SP_L__ \n\t" \
- "st x+, r0 \n\t" \
- "in r0, __SP_H__ \n\t" \
- "st x+, r0 \n\t" \
- "lds r26, current \n\t" \
- "lds r27, current + 1 \n\t" \
- "ld r28, x+ \n\t" \
- "out __SP_L__, r28 \n\t" \
- "ld r29, x+ \n\t" \
- "out __SP_H__, r29 \n\t" \
- "pop r31 \n\t" \
- "pop r30 \n\t" \
- "pop r29 \n\t" \
- "pop r28 \n\t" \
- "pop r27 \n\t" \
- "pop r26 \n\t" \
- "pop r25 \n\t" \
- "pop r24 \n\t" \
- "pop r23 \n\t" \
- "pop r22 \n\t" \
- "pop r21 \n\t" \
- "pop r20 \n\t" \
- "pop r19 \n\t" \
- "pop r18 \n\t" \
- "pop r17 \n\t" \
- "pop r16 \n\t" \
- "pop r15 \n\t" \
- "pop r14 \n\t" \
- "pop r13 \n\t" \
- "pop r12 \n\t" \
- "pop r11 \n\t" \
- "pop r10 \n\t" \
- "pop r9 \n\t" \
- "pop r8 \n\t" \
- "pop r7 \n\t" \
- "pop r6 \n\t" \
- "pop r5 \n\t" \
- "pop r4 \n\t" \
- "pop r3 \n\t" \
- "pop r2 \n\t" \
- "pop r1 \n\t" \
- "pop r0 \n\t" \
- "out __SREG__, r0 \n\t" \
- "pop r0 \n\t" \
- )
-
-char* init_stack(const char* const mem_low, const char* const mem_high, void (*entry)(char), char args);
-
-static inline void init_kstack(char **kstack) {
- *kstack = (char*) SP;
-}
-
-#define RETURN() asm volatile("ret");
-
-#endif
diff --git a/kernel/sched/sched.c b/kernel/sched/sched.c
deleted file mode 100644
index 3f4d003..0000000
--- a/kernel/sched/sched.c
+++ /dev/null
@@ -1,84 +0,0 @@
-#include "sched/sched.h"
-#include "sched/idle.h"
-#include "time/timer.h"
-#include "mcu/sched/context.h"
-
-struct tcb_t* volatile current = 0;
-DECLARE_TASK(idle, IDLE_STACK_SIZE, idle_entry);
-
-struct list_head ready = LIST_HEAD_INIT(ready);
-static struct list_head sleeping = LIST_HEAD_INIT(sleeping);
-char* volatile kstack;
-
-static void init_idle() {
- idle.sp = init_stack(idle.mem_low, idle.mem_high, idle.entry, 0);
- INIT_LIST_HEAD(&idle.q);
-}
-
-void sched_init() {
- init_idle();
- init_kstack((char **) &kstack);
- schedule();
- sei();
- RESTORE_CONTEXT();
- RETURN();
-}
-
-void schedule() {
- if(!list_empty(&ready)) {
-
- if (current == &idle) {
- debug_led(0,0);
- }
-
- current = list_entry(ready.next, struct tcb_t, q);
- list_move_tail(ready.next, &ready);
- } else {
- current = &idle;
- }
-}
-
-void sched_tick() {
- struct tcb_t* it;
- struct tcb_t* tmp;
- list_for_each_entry_safe(it, tmp, &sleeping, q) {
- it->sleep_left -= 1000 / HZ;
- if (it->sleep_left <= 0) {
- list_move_tail(&it->q, &ready);
- }
- }
- schedule(); //in a round-robin scheduler, scheduling is called after every tick
-}
-
-void wake_all(struct list_head* queue) {
- list_splice_init(queue, ready.prev);
- if (current == &idle) {
- schedule();
- }
-}
-
-void spawn(struct tcb_t* const tcb, char args) {
- tcb->sp = init_stack(tcb->mem_low, tcb->mem_high, tcb->entry, args);
- INIT_LIST_HEAD(&tcb->q);
- list_add_tail(&tcb->q, &ready);
-}
-
-void yield(void) {
- cli();
- SAVE_CONTEXT();
- schedule();
- RESTORE_CONTEXT();
- sei();
- RETURN();
-}
-
-void sleep(long ms) {
- cli();
- SAVE_CONTEXT();
- current->sleep_left = ms;
- sleep_on(&sleeping);
- schedule();
- RESTORE_CONTEXT();
- sei();
- RETURN();
-} \ No newline at end of file
diff --git a/kernel/serial/include/serial/serial.h b/kernel/serial/include/serial/serial.h
deleted file mode 100644
index 49ac63c..0000000
--- a/kernel/serial/include/serial/serial.h
+++ /dev/null
@@ -1,51 +0,0 @@
-#ifndef SERIAL_H
-#define SERIAL_H
-
-#include <stddef.h>
-#include <stdio.h>
-
-#include "collection/rbuffer.h"
-#include "collection/list.h"
-
-#define USARTS 1
-#define SERIAL_BUFFER_SIZE 64
-
-struct serial_device_t {
- volatile char __rx_buffer[SERIAL_BUFFER_SIZE];
- volatile char __tx_buffer[SERIAL_BUFFER_SIZE];
-
- struct rbuffer_t rx_buffer;
- struct rbuffer_t tx_buffer;
-
- struct list_head rx_q;
- struct list_head tx_q;
-};
-
-#define SERIAL_DEVICE_INIT(name) \
- { \
- .rx_buffer = RBUFFER_ARRAY_INIT(name.__rx_buffer, SERIAL_BUFFER_SIZE), \
- .tx_buffer = RBUFFER_ARRAY_INIT(name.__tx_buffer, SERIAL_BUFFER_SIZE), \
- .rx_q = LIST_HEAD_INIT(name.rx_q), \
- .tx_q = LIST_HEAD_INIT(name.tx_q) \
- }
-
-void serial_init(unsigned long baud);
-
-size_t serial_read(char* const data, size_t size);
-
-size_t serial_write(const char* const data, size_t size);
-
-inline void serial_write_str(const char* const str) {
- size_t length = 0;
- for (length = 0; str[length] != 0; ++length){}
- serial_write(str, length);
-}
-
-int serial_getc();
-
-int serial_putc(char c);
-
-extern FILE serial_in;
-extern FILE serial_out;
-
-#endif \ No newline at end of file
diff --git a/kernel/sched/idle.c b/kernel/task/idle.c
index 360cb8d..6bd8494 100644
--- a/kernel/sched/idle.c
+++ b/kernel/task/idle.c
@@ -1,11 +1,12 @@
+#include <avr/power.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <avr/power.h>
-#include "sched/idle.h"
+#include "task/idle.h"
+#include "task/task.h"
void idle_entry(char args) {
while(1) {
- debug_led(0,1);
set_sleep_mode(SLEEP_MODE_IDLE);
cli();
sleep_enable();
diff --git a/kernel/task/include/task/sched.h b/kernel/task/include/task/sched.h
index c14a85b..6dcd67c 100644
--- a/kernel/task/include/task/sched.h
+++ b/kernel/task/include/task/sched.h
@@ -19,7 +19,7 @@ extern struct list_head ready;
/**
* Stack pointer for operations performed out of task context, including any
- * calls made after SAVE_CONTEXT().
+ * calls made after context save.
*/
extern void* volatile kstack;
diff --git a/kernel/task/include/task/task.h b/kernel/task/include/task/task.h
index 40f18a0..99f16dc 100644
--- a/kernel/task/include/task/task.h
+++ b/kernel/task/include/task/task.h
@@ -4,6 +4,18 @@
#include "collection/list.h"
/**
+ * Wakeup sources define the minimum power level
+ * at which a task that is waiting in a queue
+ * can be woken up
+ */
+enum wakeup_src {
+ WAKEUP_SRC_OFF = 0, //processor off, external interrupts may trigger this source
+ WAKEUP_SRC_CLOCK = 1, //main clock required
+ WAKEUP_SRC_IDLE = 2, //processor can be put in idle state
+ WAKEUP_SRC_ON = 3 //processor must stay on
+};
+
+/**
* Task control block, contains runtime
* information about tasks.
*/
@@ -23,8 +35,12 @@ struct tcb_t {
/** Current wait queue that this task is in.*/
struct list_head queue;
+ /** ID of task. */
char id;
+
+ enum wakeup_src wakeup_src;
+
};
/**
@@ -39,7 +55,8 @@ struct tcb_t {
.mem_high = _declared_stack_##name + stack_size - 1, \
.entry = entry_function, \
.queue = {}, \
- .id = pid \
+ .id = pid, \
+ .wakeup_src = WAKEUP_SRC_ON \
};
#endif \ No newline at end of file
diff --git a/kernel/task/sched.c b/kernel/task/sched.c
index ceaf9bb..1ffd369 100644
--- a/kernel/task/sched.c
+++ b/kernel/task/sched.c
@@ -7,6 +7,8 @@
struct tcb_t* volatile current = 0;
+static struct tcb_t* volatile idle = 0;
+
struct list_head ready = LIST_HEAD_INIT(ready);
void* volatile kstack;
@@ -17,6 +19,12 @@ void spawn(struct tcb_t* const tcb) {
list_add_tail(&tcb->queue, &ready);
}
+void spawn_idle(struct tcb_t* const tcb) {
+ spawn(tcb);
+ list_del(&tcb->queue);
+ idle = tcb;
+}
+
void yield(void) {
cli();
context_save();
@@ -50,6 +58,6 @@ void schedule() {
current = list_entry(ready.next, struct tcb_t, queue);
list_move_tail(ready.next, &ready);
} else {
- panic();
+ current = idle;
}
} \ No newline at end of file
diff --git a/main.c b/main.c
index 526d75f..f8dde1e 100644
--- a/main.c
+++ b/main.c
@@ -2,50 +2,34 @@
#include <stdio.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
-#include "task/task.h"
-#include "task/sched.h"
#include "bug/panic.h"
#include "bug/debug.h"
+#include "task/task.h"
+#include "task/sched.h"
#include "task/lock.h"
+#include "task/idle.h"
#include "time/clock.h"
-#include "mcu/task/context.h"
+#include "io/usart.h"
#include "tshield/tshield.h"
+#include "mcu/task/context.h"
+#include "shell.h"
-#define WAIT_CYCLES(cycles) for (volatile unsigned long i = 0; i < cycles; ++i) {}
-
-spin_lock_t on_lock = SPIN_LOCK_UNLOCKED;
-volatile char on = 0;
-
-void read(char id) {
- while(1) {
- spin_lock(&on_lock);
- debug_led(0,on);
- spin_unlock(&on_lock);
- }
-}
-
-void write( char id) {
- while(1) {
- spin_lock(&on_lock);
- on = !on;
- WAIT_CYCLES(30000);
- spin_unlock(&on_lock);
- }
-}
+#define IN_LENGTH 64
+#define WAIT_CYCLES(cycles) for (volatile unsigned long i = 0; i < cycles; ++i) {}
-DECLARE_TASK(task1, DEFAULT_STACK_SIZE, read, 1);
-DECLARE_TASK(task2, DEFAULT_STACK_SIZE, write, 2);
+DECLARE_TASK(task_idle, IDLE_STACK_SIZE, idle_entry, 0);
+DECLARE_TASK(task1, DEFAULT_STACK_SIZE, shell, 1);
int main(int argc, char *argv[]) {
cli();
tshield_init();
-
+ usart_init(115200);
+ spawn_idle(&task_idle);
spawn(&task1);
- spawn(&task2);
-
+
sei();
clock_init(10, schedule);
clock_start();
diff --git a/shell.c b/shell.c
index dc8d10d..b45e2cb 100644
--- a/shell.c
+++ b/shell.c
@@ -18,6 +18,7 @@ void shell() {
printf ("root@arduino$ ");
fgets(in, IN_LENGTH, stdin);
+ printf("got: %d\n", in[0]);
argc = 0;
char *p = strtok (in," \n\r");
diff --git a/test/locks/main.c b/test/locks/main.c
new file mode 100644
index 0000000..526d75f
--- /dev/null
+++ b/test/locks/main.c
@@ -0,0 +1,55 @@
+#include <stddef.h>
+#include <stdio.h>
+#include <avr/pgmspace.h>
+#include <avr/interrupt.h>
+#include "task/task.h"
+#include "task/sched.h"
+#include "bug/panic.h"
+#include "bug/debug.h"
+#include "task/lock.h"
+#include "time/clock.h"
+#include "mcu/task/context.h"
+#include "tshield/tshield.h"
+
+#define WAIT_CYCLES(cycles) for (volatile unsigned long i = 0; i < cycles; ++i) {}
+
+spin_lock_t on_lock = SPIN_LOCK_UNLOCKED;
+volatile char on = 0;
+
+void read(char id) {
+ while(1) {
+ spin_lock(&on_lock);
+ debug_led(0,on);
+ spin_unlock(&on_lock);
+ }
+}
+
+void write( char id) {
+ while(1) {
+ spin_lock(&on_lock);
+ on = !on;
+ WAIT_CYCLES(30000);
+ spin_unlock(&on_lock);
+ }
+}
+
+
+DECLARE_TASK(task1, DEFAULT_STACK_SIZE, read, 1);
+DECLARE_TASK(task2, DEFAULT_STACK_SIZE, write, 2);
+
+
+int main(int argc, char *argv[]) {
+ cli();
+ tshield_init();
+
+
+ spawn(&task1);
+ spawn(&task2);
+
+ sei();
+ clock_init(10, schedule);
+ clock_start();
+ sched_init();
+ panic(); //should never reach here
+ while(1){}
+}
diff --git a/test/scheduler/main.c b/test/scheduler/main.c
new file mode 100644
index 0000000..79ca41b
--- /dev/null
+++ b/test/scheduler/main.c
@@ -0,0 +1,59 @@
+#include <stddef.h>
+#include <stdio.h>
+#include <avr/pgmspace.h>
+#include <avr/interrupt.h>
+#include "task/task.h"
+#include "task/sched.h"
+#include "bug/panic.h"
+#include "bug/debug.h"
+#include "mcu/task/context.h"
+#include "tshield/tshield.h"
+
+#define WAIT_CYCLES(cycles) for (volatile unsigned long i = 0; i < cycles; ++i) {}
+
+struct list_head frozen = LIST_HEAD_INIT(frozen);
+
+void freeze() __attribute__ ( ( naked ) );
+void freeze() {
+ context_save();
+ sleep_queue(&frozen);
+ schedule();
+ context_restore();
+}
+
+void blink( char id) {
+ while(1) {
+ debug_led(id - 1,1);
+ WAIT_CYCLES((long) 30000);
+ debug_led(id - 1,0);
+ WAIT_CYCLES((long) 30000);
+ }
+}
+
+
+DECLARE_TASK(task1, DEFAULT_STACK_SIZE, blink, 1);
+DECLARE_TASK(task2, DEFAULT_STACK_SIZE, blink, 2);
+DECLARE_TASK(task3, DEFAULT_STACK_SIZE, blink, 3);
+DECLARE_TASK(task4, DEFAULT_STACK_SIZE, blink, 4);
+
+
+int main(int argc, char *argv[]) {
+ cli();
+ tshield_init();
+
+
+
+ spawn(&task1);
+ spawn(&task2);
+ spawn(&task3);
+ spawn(&task4);
+
+ sei();
+ clock_init(10, schedule);
+ clock_start();
+ sched_init();
+
+
+ panic(); //should never reach here
+ while(1){}
+}