From f93ab955074e213ad6f2bf60522cc86952d57d83 Mon Sep 17 00:00:00 2001 From: Jakob Odersky Date: Sun, 30 Mar 2014 22:38:35 +0200 Subject: major update --- Makefile | 2 +- kernel/io/include/io/usart.h | 31 ++++++ kernel/io/usart.c | 103 ++++++++++++++++++ kernel/sched/idle.c | 17 --- kernel/sched/include/sched/idle.h | 6 - kernel/sched/include/sched/sched.h | 115 -------------------- kernel/sched/mcu/atmega2560/context.c | 98 ----------------- .../mcu/atmega2560/include/mcu/sched/context.h | 121 --------------------- kernel/sched/sched.c | 84 -------------- kernel/serial/include/serial/serial.h | 51 --------- kernel/serial/serial.c | 115 -------------------- kernel/task/idle.c | 18 +++ kernel/task/include/task/sched.h | 2 +- kernel/task/include/task/task.h | 19 +++- kernel/task/sched.c | 10 +- main.c | 42 +++---- shell.c | 1 + test/locks/main.c | 55 ++++++++++ test/scheduler/main.c | 59 ++++++++++ 19 files changed, 309 insertions(+), 640 deletions(-) create mode 100644 kernel/io/include/io/usart.h create mode 100644 kernel/io/usart.c delete mode 100644 kernel/sched/idle.c delete mode 100644 kernel/sched/include/sched/idle.h delete mode 100644 kernel/sched/include/sched/sched.h delete mode 100644 kernel/sched/mcu/atmega2560/context.c delete mode 100644 kernel/sched/mcu/atmega2560/include/mcu/sched/context.h delete mode 100644 kernel/sched/sched.c delete mode 100644 kernel/serial/include/serial/serial.h delete mode 100644 kernel/serial/serial.c create mode 100644 kernel/task/idle.c create mode 100644 test/locks/main.c create mode 100644 test/scheduler/main.c 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/io/usart.c b/kernel/io/usart.c new file mode 100644 index 0000000..2046630 --- /dev/null +++ b/kernel/io/usart.c @@ -0,0 +1,103 @@ + +#include +#include +#include +#include "task/sched.h" +#include "io/usart.h" +#include "bug/debug.h" +#include "mcu/task/context.h" + +static struct usart_device_t umain = USART_DEVICE_INIT(umain); +static int umain_putc(char c); +static int umain_getc(); + +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 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; +} + +int umain_putc(char c) { + if (c == '\n') umain_putc('\r'); + int r = 0; + do { + cli(); + r = rbuffer_write_char(&umain.tx_buffer, c); + sei(); + UCSR0B |= (1 << UDRIE0); + } while (r != 1); + return c; +} + +int umain_getc() { + while (rbuffer_empty(&umain.rx_buffer)) { + cli(); + sleep_queue(&umain.rx_queue); + yield(); + } + cli(); + char c = 0; + size_t r = rbuffer_read_char(&umain.rx_buffer, &c); + sei(); + if (r) return (int) c; + else return EOF; +} + +//called when byte is received +ISR(USART0_RX_vect, ISR_NAKED) { + context_save(); + char c = UDR0; + 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(&umain.tx_buffer, &c)) { + UDR0 = c; + } else { + UCSR0B &= ~(1 << UDRIE0); //buffer empty, disable interruot + } +} + +/* +void serial_read() { + ENTER_CRITICAL(); + list_move_tail(¤t->list, &serial_rx_q); + EXIT_CRITICAL(); + yield(); +} +*/ +/* +void serial_write_str(const char* const str) { + for (size_t i = 0; str[i] != '\0'; ++i) { + ENTER_CRITICAL(); + rbuffer_write(&serial_dev.tx_buffer, str[i]); + EXIT_CRITICAL(); + UCSR0B |= (1 << UDRIE0); + } +}*/ + + +/* +ISR(INT3_vect, ISR_NAKED) { + SAVE_CONTEXT(); + if (!list_empty(&serial_rx_q)) { + list_move_tail(serial_rx_q.next, &ready); + } + schedule(); + RESTORE_CONTEXT(); + asm volatile ("reti"); +} +*/ diff --git a/kernel/sched/idle.c b/kernel/sched/idle.c deleted file mode 100644 index 360cb8d..0000000 --- a/kernel/sched/idle.c +++ /dev/null @@ -1,17 +0,0 @@ -#include -#include -#include -#include "sched/idle.h" - -void idle_entry(char args) { - while(1) { - debug_led(0,1); - set_sleep_mode(SLEEP_MODE_IDLE); - cli(); - sleep_enable(); - sei(); - sleep_cpu(); - sleep_disable(); - }; -} - 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(¤t->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 - -/* - * 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 -#include - -#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/serial/serial.c b/kernel/serial/serial.c deleted file mode 100644 index e7d52a7..0000000 --- a/kernel/serial/serial.c +++ /dev/null @@ -1,115 +0,0 @@ -#include -#include "serial/serial.h" -#include "sched/sched.h" -#include "bug/debug.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 serial_device_t serial = SERIAL_DEVICE_INIT(serial); - -void serial_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); -} - -size_t serial_read(char* const data, size_t size) { - while (rbuffer_empty(&serial.rx_buffer)) { - 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; -} - -int serial_getc() { - while (rbuffer_empty(&serial.rx_buffer)) { - cli(); - sleep_on(&serial.rx_q); - yield(); - } - cli(); - char c = 0; - size_t r = rbuffer_read_char(&serial.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(); - char c = UDR0; - rbuffer_write_char(&serial.rx_buffer, c); - wake_all(&serial.rx_q); - RESTORE_CONTEXT(); - asm volatile ("reti"); -} - -//called when data register is empty -ISR(USART0_UDRE_vect) { - char c; - if (rbuffer_read_char(&serial.tx_buffer, &c)) { - UDR0 = c; - } else { - UCSR0B &= ~(1 << UDRIE0); //buffer empty, disable interruot - } -} - -/* -void serial_read() { - ENTER_CRITICAL(); - list_move_tail(¤t->list, &serial_rx_q); - EXIT_CRITICAL(); - yield(); -} -*/ -/* -void serial_write_str(const char* const str) { - for (size_t i = 0; str[i] != '\0'; ++i) { - ENTER_CRITICAL(); - rbuffer_write(&serial_dev.tx_buffer, str[i]); - EXIT_CRITICAL(); - UCSR0B |= (1 << UDRIE0); - } -}*/ - - -/* -ISR(INT3_vect, ISR_NAKED) { - SAVE_CONTEXT(); - if (!list_empty(&serial_rx_q)) { - list_move_tail(serial_rx_q.next, &ready); - } - schedule(); - RESTORE_CONTEXT(); - asm volatile ("reti"); -} -*/ diff --git a/kernel/task/idle.c b/kernel/task/idle.c new file mode 100644 index 0000000..6bd8494 --- /dev/null +++ b/kernel/task/idle.c @@ -0,0 +1,18 @@ +#include +#include +#include +#include +#include "task/idle.h" +#include "task/task.h" + +void idle_entry(char args) { + while(1) { + set_sleep_mode(SLEEP_MODE_IDLE); + cli(); + sleep_enable(); + sei(); + sleep_cpu(); + sleep_disable(); + }; +} + 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 @@ -3,6 +3,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 #include #include -#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 +#include +#include +#include +#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 +#include +#include +#include +#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){} +} -- cgit v1.2.3