From b6181e4a21b1bc3b5615604e175c6a297b661687 Mon Sep 17 00:00:00 2001 From: Jakob Odersky Date: Thu, 3 Apr 2014 18:48:59 +0200 Subject: add uniform io interface --- kernel/collection/include/collection/rbuffer.h | 84 +++++------- kernel/io/include/io/io.h | 30 +++++ kernel/io/include/io/usart.h | 31 ----- kernel/io/io.c | 25 ++++ kernel/io/mcu/atmega2560/include/mcu/io/usart.h | 12 ++ kernel/io/mcu/atmega2560/usart.c | 148 +++++++++++++++++++++ kernel/io/usart.c | 103 -------------- kernel/task/include/task/sched.h | 6 - kernel/task/include/task/task.h | 18 +-- kernel/task/mcu/atmega2560/context.c | 48 +++---- .../task/mcu/atmega2560/include/mcu/task/context.h | 26 +--- kernel/task/sched.c | 10 -- kernel/time/include/time/clock.h | 13 ++ main.c | 43 +++++- test/read-write/main.c | 70 ++++++++++ 15 files changed, 394 insertions(+), 273 deletions(-) create mode 100644 kernel/io/include/io/io.h delete mode 100644 kernel/io/include/io/usart.h create mode 100644 kernel/io/io.c create mode 100644 kernel/io/mcu/atmega2560/include/mcu/io/usart.h create mode 100644 kernel/io/mcu/atmega2560/usart.c delete mode 100644 kernel/io/usart.c create mode 100644 test/read-write/main.c diff --git a/kernel/collection/include/collection/rbuffer.h b/kernel/collection/include/collection/rbuffer.h index 01d5418..dceaeb0 100644 --- a/kernel/collection/include/collection/rbuffer.h +++ b/kernel/collection/include/collection/rbuffer.h @@ -4,67 +4,45 @@ #include struct rbuffer_t { - char* address_begin; - char* address_end; - char* volatile head; - char* volatile tail; + char* address_begin; + char* address_end; + char* volatile head; + char* volatile tail; }; -#define RBUFFER_ARRAY_INIT(array, length) \ - { \ - .address_begin = array, \ - .address_end = array + length, \ - .head=array, \ - .tail=array \ - } +#define RBUFFER_INIT(array, length) \ + { \ + .address_begin = array, \ + .address_end = array + length, \ + .head = array, \ + .tail = array \ + } + +#define INIT_RBUFFER(buffer, array, length) \ + (buffer)->address_begin = (array); \ + (buffer)->address_end = (array) + (length); \ + (buffer)->head = (array); \ + (buffer)->tail = (array) static inline int rbuffer_empty(struct rbuffer_t* const rb) { - return rb->head == rb->tail; + return rb->head == rb->tail; } -#define __rbuffer_overlap(rb, ptr) \ - if (ptr >= rb->address_end) ptr = rb->address_begin - -static inline int rbuffer_write_char(struct rbuffer_t* const rb, char data) { - char* next_head = rb->head + 1; - __rbuffer_overlap(rb, next_head); - if (rb->tail == next_head) return 0; - *rb->head = data; - rb->head = next_head; - return 1; +static inline int rbuffer_write(struct rbuffer_t* const rb, char data) { + char* next_head = rb->head + 1; + if(next_head >= rb->address_end) next_head = rb->address_begin; + if (rb->tail == next_head) return -1; + *rb->head = data; + rb->head = next_head; + return 0; } -static inline int rbuffer_read_char(struct rbuffer_t* const rb, char* const data) { - if (rbuffer_empty(rb)) return 0; - *data = *rb->tail; - rb->tail += 1; - __rbuffer_overlap(rb, rb->tail); - return 1; +static inline int rbuffer_read(struct rbuffer_t* const rb, char* const data) { + if (rbuffer_empty(rb)) return -1; + *data = *rb->tail; + rb->tail += 1; + if(rb->tail >= rb->address_end) rb->tail = rb->address_begin; + return 0; } -static inline size_t rbuffer_write(struct rbuffer_t* const rb, const char* const data, size_t size) { - size_t wrote = 0; - for (size_t i = 0; i < size; ++i) { - if (rbuffer_write_char(rb, data[i])) { - wrote += 1; - } else { - return wrote; - } - } - return wrote; -} - -static inline size_t rbuffer_read(struct rbuffer_t* const rb, char* const data, size_t size) { - size_t read = 0; - for (size_t i = 0; i < size; ++i) { - if (rbuffer_read_char(rb, &data[i])) { - read += 1; - } else { - return read; - } - } - return read; -} - - #endif diff --git a/kernel/io/include/io/io.h b/kernel/io/include/io/io.h new file mode 100644 index 0000000..a715f1b --- /dev/null +++ b/kernel/io/include/io/io.h @@ -0,0 +1,30 @@ +#ifndef IO_H +#define IO_H + +#include + +typedef long ssize_t; + +struct file; +struct file_operations; + +struct file { + struct file_operations* fops; + void* private_data; +}; + +struct file_operations { + int (*open)(struct file* file); + int (*ioctl)(struct file* file, int cmd, long args); + ssize_t (*read)(struct file* file, char* const buffer, size_t size); + ssize_t (*write)(struct file* file, const char* const buffer, size_t size); + int (*close)(struct file* file); +}; + +int open(struct file* file); +int ioctl(struct file* file, int cmd, long args); +ssize_t read(struct file* file, char* const buffer, size_t size); +ssize_t write(struct file* file, const char* const buffer, size_t size); +int close(struct file* file); + +#endif \ No newline at end of file diff --git a/kernel/io/include/io/usart.h b/kernel/io/include/io/usart.h deleted file mode 100644 index 62e2768..0000000 --- a/kernel/io/include/io/usart.h +++ /dev/null @@ -1,31 +0,0 @@ -#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/io.c b/kernel/io/io.c new file mode 100644 index 0000000..f39168b --- /dev/null +++ b/kernel/io/io.c @@ -0,0 +1,25 @@ +#include "io/io.h" + +int open(struct file* file) { + file->fops->open(file); +} + +int ioctl(struct file* file, int cmd, long args) { + file->fops->ioctl(file, cmd, args); +} + +ssize_t read(struct file* file, char* const buffer, size_t size) { + struct file_operations* fops = file->fops; + if (fops->read == NULL) return -1; + else fops->read(file, buffer, size); +} + +ssize_t write(struct file* file, const char* const buffer, size_t size) { + struct file_operations* fops = file->fops; + if (fops->write == NULL) return -1; + else fops->write(file, buffer, size); +} + +int close(struct file* file) { + file->fops->close(file); +} \ No newline at end of file diff --git a/kernel/io/mcu/atmega2560/include/mcu/io/usart.h b/kernel/io/mcu/atmega2560/include/mcu/io/usart.h new file mode 100644 index 0000000..6b210fe --- /dev/null +++ b/kernel/io/mcu/atmega2560/include/mcu/io/usart.h @@ -0,0 +1,12 @@ +#ifndef MCU_USART +#define MCU_USART + +#include "io/io.h" + +#define USART_BUFFER_SIZE 64 +#define IOCTL_SET_BAUD 0 + +extern struct file usart0; + + +#endif \ No newline at end of file diff --git a/kernel/io/mcu/atmega2560/usart.c b/kernel/io/mcu/atmega2560/usart.c new file mode 100644 index 0000000..381f403 --- /dev/null +++ b/kernel/io/mcu/atmega2560/usart.c @@ -0,0 +1,148 @@ +#include "io/io.h" +#include "collection/list.h" +#include "collection/rbuffer.h" +#include "task/sched.h" +#include "mcu/io/usart.h" +#include "mcu/task/context.h" +#include +#include + +struct usart_private { + char __rx_buffer[USART_BUFFER_SIZE]; + 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; + + volatile unsigned char* const ucsrxa; + volatile unsigned char* const ubrrxh; + volatile unsigned char* const ubrrxl; + volatile unsigned char* const ucsrxb; + char u2xx; + char rxenx; + char txenx; + char rxciex; + char udriex; +}; + +int usart_open(struct file* usart) { + struct usart_private* priv = (struct usart_private*) usart->private_data; + + INIT_LIST_HEAD(&priv->rx_queue); + INIT_LIST_HEAD(&priv->tx_queue); + INIT_RBUFFER(&priv->rx_buffer, priv->__rx_buffer, USART_BUFFER_SIZE); + INIT_RBUFFER(&priv->tx_buffer, priv->__tx_buffer, USART_BUFFER_SIZE); + + return 0; +} + +int usart_ioctl(struct file* usart, int cmd, long args) { + struct usart_private* priv = (struct usart_private*) usart->private_data; + + switch (cmd) { + case IOCTL_SET_BAUD: { + long baud = args; + (*priv->ucsrxa) |= (1 << priv->u2xx); + long baud_setting = (F_CPU / 4 / baud - 1) / 2; + (*priv->ubrrxh) = baud_setting >> 8; + (*priv->ubrrxl) = baud_setting; + (*priv->ucsrxb) |= (1 << priv->rxenx) | (1 << priv->txenx) | (1 << priv->rxciex); + (*priv->ucsrxb) &= ~(1 << priv->udriex); + return 0; + } + default: + return -1; + } +} + +ssize_t usart_write(struct file* usart, const char* const buffer, size_t length) { + struct usart_private* priv = (struct usart_private*) usart->private_data; + volatile unsigned char* ucsrxb = (priv->ucsrxb); + char write_enable = (1 << priv->udriex); + + ssize_t wrote = 0; + int r = 0; + do { + cli(); + r = rbuffer_write(&priv->tx_buffer, buffer[wrote]); + wrote += 1; + sei(); + *ucsrxb |= write_enable; + } while (r == 0 && wrote < length); + return wrote; +} + +ssize_t usart_read(struct file* usart, char* const buffer, size_t length) { + struct usart_private* priv = (struct usart_private*) usart->private_data; + while (rbuffer_empty(&priv->rx_buffer)) { + sleep_queue(&priv->rx_queue); + yield(); + } + size_t read = 0; + size_t r = 0; + while (!rbuffer_empty(&priv->rx_buffer) && read < length && r == 0) { + cli(); + r = rbuffer_read(&priv->rx_buffer, buffer + read); + read += 1; + sei(); + } + return read; +} + +int usart_close(struct file* usart) { + return 0; +} + +struct file_operations usart_fops = { + .open = usart_open, + .ioctl = usart_ioctl, + .read = usart_read, + .write = usart_write, + .close = usart_close +}; + +struct usart_private _usart0 = { + .ucsrxa = &UCSR0A, + .ubrrxh = &UBRR0H, + .ubrrxl = &UBRR0L, + .ucsrxb = &UCSR0B, + .u2xx = U2X0, + .rxenx = RXEN0, + .txenx = TXEN0, + .rxciex = RXCIE0, + .udriex = UDRIE0 +}; + +struct file usart0 = { + .fops = &usart_fops, + .private_data = &_usart0 +}; + +//called when data register is empty +ISR(USART0_UDRE_vect) { + struct usart_private* priv = (struct usart_private*) usart0.private_data; + char c; + + if (rbuffer_read(&priv->tx_buffer, &c) == 0) { + UDR0 = c; + } else { + UCSR0B &= ~(1 << UDRIE0); //buffer empty, disable interruot + } +} + +//called when byte is received +ISR(USART0_RX_vect, ISR_NAKED) { + context_save(); + + struct usart_private* priv = (struct usart_private*) usart0.private_data; + + char c = UDR0; + rbuffer_write(&priv->rx_buffer, c); + wake_all_queue(&priv->rx_queue); + + context_restore(); + asm volatile ("reti"); +} \ No newline at end of file diff --git a/kernel/io/usart.c b/kernel/io/usart.c deleted file mode 100644 index 2046630..0000000 --- a/kernel/io/usart.c +++ /dev/null @@ -1,103 +0,0 @@ - -#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/task/include/task/sched.h b/kernel/task/include/task/sched.h index 6dcd67c..b8946db 100644 --- a/kernel/task/include/task/sched.h +++ b/kernel/task/include/task/sched.h @@ -17,12 +17,6 @@ extern struct tcb_t* volatile current; */ extern struct list_head ready; -/** - * Stack pointer for operations performed out of task context, including any - * calls made after context save. - */ -extern void* volatile kstack; - /** * Makes the current task sleep on a specific queue. * This moves the current task to the given queue's tail. diff --git a/kernel/task/include/task/task.h b/kernel/task/include/task/task.h index 99f16dc..120bda4 100644 --- a/kernel/task/include/task/task.h +++ b/kernel/task/include/task/task.h @@ -3,18 +3,6 @@ #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. @@ -38,9 +26,6 @@ struct tcb_t { /** ID of task. */ char id; - - enum wakeup_src wakeup_src; - }; /** @@ -55,8 +40,7 @@ struct tcb_t { .mem_high = _declared_stack_##name + stack_size - 1, \ .entry = entry_function, \ .queue = {}, \ - .id = pid, \ - .wakeup_src = WAKEUP_SRC_ON \ + .id = pid \ }; #endif \ No newline at end of file diff --git a/kernel/task/mcu/atmega2560/context.c b/kernel/task/mcu/atmega2560/context.c index bcc2130..9bb7036 100644 --- a/kernel/task/mcu/atmega2560/context.c +++ b/kernel/task/mcu/atmega2560/context.c @@ -5,26 +5,26 @@ char* stack_init(const char* const mem_low, const char* const mem_high, void (*e 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--; + *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 ); + // 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 = (char) ( (address >> 16) & ( unsigned short ) 0x00ff ); sp--; - // save registers + // save registers *sp = (char) 0x00; //r0 sp--; *sp = (char) 0x80; //SREG, enable interrupts when task starts @@ -69,30 +69,30 @@ char* stack_init(const char* const mem_low, const char* const mem_high, void (*e sp--; *sp = ( char ) 0x00; //r20 sp--; - *sp = ( char ) 0x00; //r21 + *sp = ( char ) 0x00; //r21 sp--; - *sp = ( char ) 0x00; //r22 + *sp = ( char ) 0x00; //r22 sp--; - *sp = ( char ) 0x00; //r23 + *sp = ( char ) 0x00; //r23 sp--; - *sp = (char) ( args ); //place first argument in register 24 + *sp = (char) ( args ); //place first argument in register 24 sp--; - *sp = ( char ) 0x00; //r25 + *sp = ( char ) 0x00; //r25 sp--; - *sp = ( char ) 0x00; //r26 + *sp = ( char ) 0x00; //r26 sp--; - *sp = ( char ) 0x00; //r27 + *sp = ( char ) 0x00; //r27 sp--; - *sp = ( char ) 0x00; //r28 + *sp = ( char ) 0x00; //r28 sp--; - *sp = ( char ) 0x00; //r29 + *sp = ( char ) 0x00; //r29 sp--; - *sp = ( char ) 0x00; //r30 + *sp = ( char ) 0x00; //r30 sp--; - *sp = ( char ) 0x00; //r31 + *sp = ( char ) 0x00; //r31 sp--; - return sp; + return sp; } diff --git a/kernel/task/mcu/atmega2560/include/mcu/task/context.h b/kernel/task/mcu/atmega2560/include/mcu/task/context.h index b717991..0de1fb4 100644 --- a/kernel/task/mcu/atmega2560/include/mcu/task/context.h +++ b/kernel/task/mcu/atmega2560/include/mcu/task/context.h @@ -1,5 +1,5 @@ -#ifndef CONTEXT_H -#define CONTEXT_H +#ifndef MCU_CONTEXT_H +#define MCU_CONTEXT_H #include #define ret() asm volatile ( "ret" ) @@ -20,6 +20,7 @@ asm volatile ( \ "push r0 \n\t" \ "in r0, __SREG__ \n\t" \ + "cli \n\t" \ "push r0 \n\t" \ "push r1 \n\t" \ "clr r1 \n\t" \ @@ -59,12 +60,6 @@ "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" \ ) @@ -74,12 +69,6 @@ */ #define context_restore() \ 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" \ @@ -125,13 +114,4 @@ /** Initialize the given memory addresses to contain a valid, initial stackframe. */ char* stack_init(const char* const mem_low, const char* const mem_high, void (*entry)(char), char args); -/** Initialize the given memory addresses to contain a valid, initial stackframe. */ -static inline void kstack_init(void **kstack) { - //this sets the kernel stack to the default stack location - //of this mcu, namely the top (stacks of tasks will typically - //be contained in memory allocated on the head and thus should - //overflow with the kernel stack) - *kstack = (void*) SP; -} - #endif diff --git a/kernel/task/sched.c b/kernel/task/sched.c index 1ffd369..da7b59d 100644 --- a/kernel/task/sched.c +++ b/kernel/task/sched.c @@ -2,7 +2,6 @@ #include "task/task.h" #include "task/sched.h" #include "mcu/task/context.h" -#include "mcu/task/context.h" struct tcb_t* volatile current = 0; @@ -11,8 +10,6 @@ static struct tcb_t* volatile idle = 0; struct list_head ready = LIST_HEAD_INIT(ready); -void* volatile kstack; - void spawn(struct tcb_t* const tcb) { tcb->sp = stack_init(tcb->mem_low, tcb->mem_high, tcb->entry, tcb->id); INIT_LIST_HEAD(&tcb->queue); @@ -26,32 +23,25 @@ void spawn_idle(struct tcb_t* const tcb) { } void yield(void) { - cli(); context_save(); schedule(); context_restore(); - sei(); ret(); } - void sched_init() { - kstack_init(&kstack); schedule(); context_restore(); sei(); ret(); } - #include void toggle_led() { DDRB |= (1 << 7); PORTB ^= (1 << 7); } - - void schedule() { toggle_led(); if(!list_empty(&ready)) { diff --git a/kernel/time/include/time/clock.h b/kernel/time/include/time/clock.h index 3d90cf0..0a247a8 100644 --- a/kernel/time/include/time/clock.h +++ b/kernel/time/include/time/clock.h @@ -1,8 +1,21 @@ #ifndef CLOCK_H #define CLOCK_H +/** + * Initializes main system clock. + * @ms time between each tick in milliseconds + * @tick function to run every tick + */ void clock_init(int ms, void (*tick)()); + +/** + * Starts main system clock. + */ void clock_start(); + +/** + * Stops main system clock. + */ void clock_stop(); #endif \ No newline at end of file diff --git a/main.c b/main.c index f8dde1e..0ed45da 100644 --- a/main.c +++ b/main.c @@ -9,26 +9,57 @@ #include "task/lock.h" #include "task/idle.h" #include "time/clock.h" -#include "io/usart.h" +#include "io/io.h" +#include "mcu/io/usart.h" #include "tshield/tshield.h" -#include "mcu/task/context.h" -#include "shell.h" - #define IN_LENGTH 64 #define WAIT_CYCLES(cycles) for (volatile unsigned long i = 0; i < cycles; ++i) {} +void writer() { + + char* buffer = "hello world"; + size_t length = 11; + + + while(1) { + debug_led(1, 0); + WAIT_CYCLES(300000); + debug_led(1, 1); + write(&usart0, buffer, length); + } +} + +void reader() { + char in; + + while(1) { + debug_led(2, 0); + debug_led(3, 0); + if (read(&usart0, &in, 1) >= 0) { + debug_led(2, 1); + } else { + debug_led(3, 1); + WAIT_CYCLES(30000); + } + + } +} DECLARE_TASK(task_idle, IDLE_STACK_SIZE, idle_entry, 0); -DECLARE_TASK(task1, DEFAULT_STACK_SIZE, shell, 1); +DECLARE_TASK(task1, DEFAULT_STACK_SIZE, writer, 1); +DECLARE_TASK(task2, DEFAULT_STACK_SIZE, reader, 2); int main(int argc, char *argv[]) { cli(); tshield_init(); - usart_init(115200); + + open(&usart0); + ioctl(&usart0, IOCTL_SET_BAUD, 115200); spawn_idle(&task_idle); spawn(&task1); + spawn(&task2); sei(); clock_init(10, schedule); diff --git a/test/read-write/main.c b/test/read-write/main.c new file mode 100644 index 0000000..0ed45da --- /dev/null +++ b/test/read-write/main.c @@ -0,0 +1,70 @@ +#include +#include +#include +#include +#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 "io/io.h" +#include "mcu/io/usart.h" +#include "tshield/tshield.h" +#define IN_LENGTH 64 + +#define WAIT_CYCLES(cycles) for (volatile unsigned long i = 0; i < cycles; ++i) {} + +void writer() { + + char* buffer = "hello world"; + size_t length = 11; + + + while(1) { + debug_led(1, 0); + WAIT_CYCLES(300000); + debug_led(1, 1); + write(&usart0, buffer, length); + } +} + +void reader() { + char in; + + while(1) { + debug_led(2, 0); + debug_led(3, 0); + if (read(&usart0, &in, 1) >= 0) { + debug_led(2, 1); + } else { + debug_led(3, 1); + WAIT_CYCLES(30000); + } + + } +} + +DECLARE_TASK(task_idle, IDLE_STACK_SIZE, idle_entry, 0); +DECLARE_TASK(task1, DEFAULT_STACK_SIZE, writer, 1); +DECLARE_TASK(task2, DEFAULT_STACK_SIZE, reader, 2); + +int main(int argc, char *argv[]) { + cli(); + tshield_init(); + + open(&usart0); + ioctl(&usart0, IOCTL_SET_BAUD, 115200); + + spawn_idle(&task_idle); + spawn(&task1); + spawn(&task2); + + sei(); + clock_init(10, schedule); + clock_start(); + sched_init(); + panic(); //should never reach here + while(1){} +} -- cgit v1.2.3