diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..270f8cf773 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +*.o +doc/doxygen/html +doc/doxygen/latex +doc/doxygen/man +*bin diff --git a/Jamfile b/Jamfile index 3c442afa90..3e199228c3 100644 --- a/Jamfile +++ b/Jamfile @@ -67,8 +67,8 @@ Debug debug : $(TARGET) ; ListModules listmodules ; ShowFlags showflags : $(TARGET) ; -SubInclude TOP projects $(PROJECT) ; SubInclude TOP sys ; SubInclude TOP core ; SubInclude TOP drivers ; SubInclude TOP board ; +SubInclude TOP projects $(PROJECT) ; diff --git a/Jamrules b/Jamrules index 8eca19afc7..13a6088f0c 100644 --- a/Jamrules +++ b/Jamrules @@ -31,9 +31,9 @@ include $(TOP)$(SLASH)Jamrules.common ; # -# Setup FeuerWare build system configuration (default values for common options) +# Setup ukleos build system configuration (default values for common options) # -PROJECT = $(PROJECT:E=hello-world) ; +PROJECT = $(PROJECT:E=default) ; BOARD = $(BOARD:E=msba2) ; SUFFIX ?= "" ; # must be at least "" !!! TARGET = "$(BOARD)-$(PROJECT)$(SUFFIX)$(SUFEXE)" ; # main target binary @@ -53,7 +53,6 @@ CCFLAGS += -DBOARD=BOARD_$(BOARD:U) ; # core source directories HDRS += $(TOP) ; HDRS += [ FPath $(TOP) core include ] ; -HDRS += [ FPath $(TOP) hal include ] ; HDRS += [ FPath $(TOP) sys include ] [ FPath $(TOP) sys config ] [ FPath $(TOP) sys drivers include ] [ FPath $(TOP) sys drivers cc110x ] [ FPath $(TOP) sys drivers nanopan5375 ] ; HDRS += [ FPath $(TOP) sys net ] ; HDRS += [ FPath $(TOP) sys lib ] [ FPath $(TOP) sys lib fat include ] ; @@ -74,3 +73,4 @@ HDRS += [ FPath $(TOP) projects $(PROJECT) ] ; # drivers HDRS += [ FPath $(TOP) drivers include ] ; HDRS += [ FPath $(TOP) drivers cc110x ] ; +HDRS += [ FPath $(TOP) drivers cc110x_ng ] ; diff --git a/Jamrules.common b/Jamrules.common index d92882466a..d2f4c9e863 100644 --- a/Jamrules.common +++ b/Jamrules.common @@ -177,7 +177,7 @@ rule Test } actions Test { - for tst in projects/$(PROJECT)/tests/*; do $tst; done + export PORT=$(PORT); for tst in projects/$(PROJECT)/tests/*; do $tst; done } # Reset connected sensor node @@ -357,4 +357,3 @@ actions ShowFlags { echo "" | $(CC) -E -dD - } - diff --git a/README b/README index aed49aaf32..44f24ab49a 100644 --- a/README +++ b/README @@ -7,3 +7,4 @@ License a separate license. All code files contain licensing information. + diff --git a/board/msb-430-common/Jamfile b/board/msb-430-common/Jamfile new file mode 100644 index 0000000000..97c2be0f30 --- /dev/null +++ b/board/msb-430-common/Jamfile @@ -0,0 +1,33 @@ +# ****************************************************************************** +# Copyright 2009, Freie Universitaet Berlin (FUB). All rights reserved. +# +# These sources were developed at the Freie Universitaet Berlin, Computer +# Systems and Telematics group (http://cst.mi.fu-berlin.de). +# ------------------------------------------------------------------------------ +# This file is part of FeuerWare. +# +# 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. +# +# FeuerWare 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 http://www.gnu.org/licenses/ . +# ------------------------------------------------------------------------------ +# For further information and questions please use the web site +# http://scatterweb.mi.fu-berlin.de +# and the mailinglist (subscription via web site) +# scatterweb@lists.spline.inf.fu-berlin.de +# ****************************************************************************** +# $Id$ + +SubDir TOP board msb-430-common ; + +Module board : board_init.c debug_uart.c ; +UseModule board ; + +SubInclude TOP cpu $(CPU) ; diff --git a/board/msb-430-common/Jamrules.msb-430-common b/board/msb-430-common/Jamrules.msb-430-common new file mode 100644 index 0000000000..bfe5a1a6f8 --- /dev/null +++ b/board/msb-430-common/Jamrules.msb-430-common @@ -0,0 +1,37 @@ +# ****************************************************************************** +# Copyright 2009, Freie Universitaet Berlin (FUB). All rights reserved. +# +# These sources were developed at the Freie Universitaet Berlin, Computer +# Systems and Telematics group (http://cst.mi.fu-berlin.de). +# ------------------------------------------------------------------------------ +# This file is part of FeuerWare. +# +# 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. +# +# FeuerWare 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 http://www.gnu.org/licenses/ . +# ------------------------------------------------------------------------------ +# For further information and questions please use the web site +# http://scatterweb.mi.fu-berlin.de +# and the mailinglist (subscription via web site) +# scatterweb@lists.spline.inf.fu-berlin.de +# ****************************************************************************** +# $Id$ + +CPU = msp430 ; +MCU = msp430x1612 ; + +FLASH_PORT ?= /dev/ttyUSB0 ; +FLASHER ?= mspdebug ; +FLASHFLAGS ?= -d $(FLASH_PORT) -j uif ; + +RESET ?= $(FLASHER) $(FLASHFLAGS) reset ; + +HDRS += [ FPath $(TOP) board msb-430-common drivers include ] ; diff --git a/board/msb-430h/board_init.c b/board/msb-430-common/board_init.c similarity index 99% rename from board/msb-430h/board_init.c rename to board/msb-430-common/board_init.c index 7dee70e3b1..4673600445 100644 --- a/board/msb-430h/board_init.c +++ b/board/msb-430-common/board_init.c @@ -201,7 +201,7 @@ void board_init() { msp430_cpu_init(); msb_ports_init(); - RED_ON; + LED_RED_ON; msp430_set_cpu_speed(7372800uL); } diff --git a/board/msb-430h/debug_uart.c b/board/msb-430-common/debug_uart.c similarity index 100% rename from board/msb-430h/debug_uart.c rename to board/msb-430-common/debug_uart.c diff --git a/board/msb-430-common/drivers/include/sht11-board.h b/board/msb-430-common/drivers/include/sht11-board.h new file mode 100644 index 0000000000..a4debd4473 --- /dev/null +++ b/board/msb-430-common/drivers/include/sht11-board.h @@ -0,0 +1,61 @@ +/****************************************************************************** +Copyright 2009, Freie Universitaet Berlin (FUB). All rights reserved. + +These sources were developed at the Freie Universitaet Berlin, Computer Systems +and Telematics group (http://cst.mi.fu-berlin.de). +------------------------------------------------------------------------------- +This file is part of FeuerWare. + +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. + +FeuerWare 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 http://www.gnu.org/licenses/ . +-------------------------------------------------------------------------------- +For further information and questions please use the web site + http://scatterweb.mi.fu-berlin.de +and the mailinglist (subscription via web site) + scatterweb@lists.spline.inf.fu-berlin.de +*******************************************************************************/ + +#ifndef SHT11BOARD_H_ +#define SHT11BOARD_H_ + +/** + * @ingroup msb_430h + * @{ + */ + +/** + * @file + * @brief SHT11 Device Driver Configuration For MSB-430 Platform + * + * @author Freie Universität Berlin, Computer Systems & Telematics, µkleos + * @version $Revision$ + * + * @note $Id$ + */ +#include +#include + +/* SCK = P3B5 + * DATA = P3B4 + */ + +#define SHT11_SCK_LOW P3OUT &= ~(BIT5); /**< serial clock line low */ +#define SHT11_SCK_HIGH P3OUT |= BIT5; /**< serial clock line high */ +#define SHT11_DATA (P3IN & BIT5) /**< read serial I/O */ +#define SHT11_DATA_LOW P3OUT &= ~(BIT5); /**< serial I/O line low */ +#define SHT11_DATA_HIGH P3OUT |= BIT5; /**< serial I/O line high */ +#define SHT11_DATA_IN P3DIR &= ~(BIT5); /**< serial I/O as input */ +#define SHT11_DATA_OUT P3DIR |= BIT5; /**< serial I/O as output */ +#define SHT11_INIT P3DIR |= BIT5; /* FIO1DIR |= BIT25; PINSEL3 &= ~(BIT14|BIT15 | BIT16|BIT17); */ + +/** @} */ +#endif /* SHT11BOARD_H_ */ diff --git a/board/msb-430/Jamfile b/board/msb-430/Jamfile new file mode 100644 index 0000000000..f2592c24cf --- /dev/null +++ b/board/msb-430/Jamfile @@ -0,0 +1,32 @@ +# ****************************************************************************** +# Copyright 2009, Freie Universitaet Berlin (FUB). All rights reserved. +# +# These sources were developed at the Freie Universitaet Berlin, Computer +# Systems and Telematics group (http://cst.mi.fu-berlin.de). +# ------------------------------------------------------------------------------ +# This file is part of FeuerWare. +# +# 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. +# +# FeuerWare 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 http://www.gnu.org/licenses/ . +# ------------------------------------------------------------------------------ +# For further information and questions please use the web site +# http://scatterweb.mi.fu-berlin.de +# and the mailinglist (subscription via web site) +# scatterweb@lists.spline.inf.fu-berlin.de +# ****************************************************************************** +# $Id$ + +SubDir TOP board msb-430 ; + +SubInclude TOP board msb-430-common ; +SubInclude TOP cpu $(CPU) ; + diff --git a/board/msb-430/Jamrules.msb-430 b/board/msb-430/Jamrules.msb-430 new file mode 100644 index 0000000000..ae1d28b444 --- /dev/null +++ b/board/msb-430/Jamrules.msb-430 @@ -0,0 +1,3 @@ +BOARD = msb-430 ; + +include $(TOP)/board/msb-430-common/Jamrules.msb-430-common ; diff --git a/board/msb-430/include/board.h b/board/msb-430/include/board.h new file mode 100644 index 0000000000..18d4a04721 --- /dev/null +++ b/board/msb-430/include/board.h @@ -0,0 +1,70 @@ +/****************************************************************************** +Copyright 2009, Freie Universitaet Berlin (FUB). All rights reserved. + +These sources were developed at the Freie Universitaet Berlin, Computer Systems +and Telematics group (http://cst.mi.fu-berlin.de). +------------------------------------------------------------------------------- +This file is part of FeuerWare. + +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. + +FeuerWare 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 http://www.gnu.org/licenses/ . +-------------------------------------------------------------------------------- +For further information and questions please use the web site + http://scatterweb.mi.fu-berlin.de +and the mailinglist (subscription via web site) + scatterweb@lists.spline.inf.fu-berlin.de +*******************************************************************************/ + +#ifndef _MSB_BOARD_H +#define _MSB_BOARD_H + +/** + * @defgroup msb_430h ScatterWeb MSB-430H + * @ingroup msp430 + * +

Compontents

+\li MSP430 +\li CC1100 + +* @{ +*/ + +/** + * @file + * @brief MSB-430H Board + * + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @version $Revision$ + * + * @note $Id$ + */ + +//MSB430 core +#define MSP430_INITIAL_CPU_SPEED 7372800uL +#define MSP430_HAS_DCOR 1 +#define MSP430_HAS_EXTERNAL_CRYSTAL 0 + +/* LEDs ports MSB430 */ +#define LEDS_PxDIR P5DIR +#define LEDS_PxOUT P5OUT +#define LEDS_CONF_RED 0x80 +#define LEDS_CONF_GREEN 0x00 +#define LEDS_CONF_YELLOW 0x00 + +#define LED_RED_ON LEDS_PxOUT &=~LEDS_CONF_RED +#define LED_RED_OFF LEDS_PxOUT |= LEDS_CONF_RED +#define LED_RED_TOGGLE LEDS_PxOUT ^= LEDS_CONF_RED + +#include + +/** @} */ +#endif // _MSB_BOARD_H diff --git a/board/msb-430h/Jamfile b/board/msb-430h/Jamfile index b1181a57db..79e6f920c0 100644 --- a/board/msb-430h/Jamfile +++ b/board/msb-430h/Jamfile @@ -27,9 +27,8 @@ SubDir TOP board msb-430h ; -Module board : board_init.c debug_uart.c ; -UseModule board ; - Module board_cc1100 : driver_cc1100.c ; +SubInclude TOP board msb-430-common ; SubInclude TOP cpu $(CPU) ; + diff --git a/board/msb-430h/Jamrules.msb-430h b/board/msb-430h/Jamrules.msb-430h index 41bf0779d9..d1913ed542 100644 --- a/board/msb-430h/Jamrules.msb-430h +++ b/board/msb-430h/Jamrules.msb-430h @@ -1,37 +1,3 @@ -# ****************************************************************************** -# Copyright 2009, Freie Universitaet Berlin (FUB). All rights reserved. -# -# These sources were developed at the Freie Universitaet Berlin, Computer -# Systems and Telematics group (http://cst.mi.fu-berlin.de). -# ------------------------------------------------------------------------------ -# This file is part of FeuerWare. -# -# 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. -# -# FeuerWare 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 http://www.gnu.org/licenses/ . -# ------------------------------------------------------------------------------ -# For further information and questions please use the web site -# http://scatterweb.mi.fu-berlin.de -# and the mailinglist (subscription via web site) -# scatterweb@lists.spline.inf.fu-berlin.de -# ****************************************************************************** -# $Id$ - BOARD = msb-430h ; -CPU = msp430 ; -MCU = msp430x1612 ; - -FLASH_PORT ?= /dev/ttyUSB0 ; -FLASHER ?= mspdebug ; -FLASHFLAGS ?= -d $(FLASH_PORT) -j uif ; - -RESET ?= $(FLASHER) $(FLASHFLAGS) reset ; +include $(TOP)/board/msb-430-common/Jamrules.msb-430-common ; diff --git a/board/msb-430h/include/board.h b/board/msb-430h/include/board.h index ef2bbb6585..d9634d6b4d 100644 --- a/board/msb-430h/include/board.h +++ b/board/msb-430h/include/board.h @@ -60,8 +60,9 @@ and the mailinglist (subscription via web site) #define LEDS_CONF_GREEN 0x00 #define LEDS_CONF_YELLOW 0x00 -#define RED_ON LEDS_PxOUT &=~LEDS_CONF_RED -#define RED_OFF LEDS_PxOUT |= LEDS_CONF_RED +#define LED_RED_ON LEDS_PxOUT &=~LEDS_CONF_RED +#define LED_RED_OFF LEDS_PxOUT |= LEDS_CONF_RED +#define LED_RED_TOGGLE LEDS_PxOUT ^= LEDS_CONF_RED #include diff --git a/board/msba2/Jamrules.msba2 b/board/msba2/Jamrules.msba2 index 5111de74d3..b0ad55f759 100644 --- a/board/msba2/Jamrules.msba2 +++ b/board/msba2/Jamrules.msba2 @@ -29,5 +29,5 @@ CPU = lpc2387 ; HDRS += [ FPath $(TOP) board $(BOARD) drivers include ] ; -FLASHER ?= $(POSIXSHELL) $(TOP)/board/msba2/tools/flashutil.sh ; -FLASHFLAGS ?= --basedir $(TOP)/board/msba2/tools --id "MSB-A2" --ports "$(PORT)" ; +FLASHER ?= $(POSIXSHELL) lpc2k_pgm ; +FLASHFLAGS ?= "$(PORT)" ; diff --git a/board/msba2/drivers/include/sht11-board.h b/board/msba2/drivers/include/sht11-board.h index fc0313906a..c35fb00788 100644 --- a/board/msba2/drivers/include/sht11-board.h +++ b/board/msba2/drivers/include/sht11-board.h @@ -54,10 +54,5 @@ and the mailinglist (subscription via web site) #define SHT11_DATA_OUT (FIO1DIR |= BIT26) // serial I/O as output #define SHT11_INIT FIO1DIR |= BIT25; PINSEL3 &= ~(BIT14|BIT15 | BIT16|BIT17); -/* time to wait after toggling the data line */ -#define SHT11_DATA_WAIT (50) -/* time to wait after toggling the clock line */ -#define SHT11_CLK_WAIT (10) - /** @} */ #endif /* SHT11BOARD_H_ */ diff --git a/board/msba2/drivers/msba2-uart0.c b/board/msba2/drivers/msba2-uart0.c index 9198f50bb2..3107e8d40c 100644 --- a/board/msba2/drivers/msba2-uart0.c +++ b/board/msba2/drivers/msba2-uart0.c @@ -35,6 +35,7 @@ and the mailinglist (subscription via web site) #include #include "lpc23xx.h" #include "VIC.h" +#include #include @@ -78,12 +79,14 @@ static inline void dequeue(void) { static void push_queue(void) { running = 1; + lpm_prevent_sleep |= LPM_PREVENT_SLEEP_UART; start: if (!actual) { if (queue_items) { dequeue(); } else { running = 0; + lpm_prevent_sleep &= ~LPM_PREVENT_SLEEP_UART; if (!fifo) while(!(U0LSR & BIT6)){}; return; @@ -149,7 +152,7 @@ void UART0_IRQHandler(void) static inline int uart0_puts(char *astring,int length) { - while (queue_items == (QUEUESIZE-1)) {} ; +/* while (queue_items == (QUEUESIZE-1)) {} ; U0IER = 0; queue[queue_tail] = malloc(length+sizeof(unsigned int)); queue[queue_tail]->len = length; @@ -158,14 +161,14 @@ static inline int uart0_puts(char *astring,int length) if (!running) push_queue(); U0IER |= BIT0 | BIT1; // enable RX irq - - /* alternative without queue: +*/ + /* alternative without queue:*/ int i; for (i=0;i -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "serial.h" -#include "pthread.h" -#include "download.h" - -int tty_fd; -int stopped = 0; -char* port_name = "/dev/ttyUSB1"; -pthread_t serial_reader; - -void* serial_reader_func(void* arg) { - unsigned char buf[255]; - while(1) { - int n = read_serial_port(buf, sizeof(buf)); - if (n > 0) { - write(tty_fd, buf, n); - } - } -} - -int init() { - int result = open_serial_port(port_name); - pthread_create(&serial_reader, NULL, serial_reader_func, NULL); - hard_reset_to_user_code(); - return result; -} - -void sig_handler(int signal) { - if (signal == SIGUSR1) { - if (stopped) { - stopped = 0; - printf("\nSignal received, opening port.\r\n"); - if (init() < 0) { - printf("Cannot open port.\r\n"); - exit(1); - } - } - } else if (signal == SIGUSR2) { - if (!stopped) { - stopped = 1; - printf("\nSignal received, closing port. \r\n"); - pthread_cancel(serial_reader); - close_serial_port(); - } - } -} - -int open_tty(void) -{ - int r, fd; - struct termios term_setting; - - fd = open("/dev/tty", O_RDWR); - if (fd < 0) return -1; - r = tcgetattr(fd, &term_setting); - if (r != 0) return -2; - term_setting.c_oflag |= ( ONLRET ); - term_setting.c_iflag |= (IGNBRK | IGNPAR); - term_setting.c_iflag &= ~(ISTRIP | BRKINT); - term_setting.c_lflag &= ~(ICANON | ISIG | ECHO); - term_setting.c_cflag |= CREAD; - term_setting.c_cc[VMIN] = 1; - term_setting.c_cc[VTIME] = 1; - r = tcsetattr(fd, TCSANOW, &term_setting); - if (r != 0) return -3; - return fd; -} - -void install_sighandler() { - struct sigaction action; - sigemptyset (&action.sa_mask); - sigaddset( &action.sa_mask, SIGUSR1 ); - sigaddset( &action.sa_mask, SIGUSR2 ); - action.sa_flags = 0; - action.sa_handler = sig_handler; - sigaction(SIGUSR1, &action, NULL); - sigaction(SIGUSR2, &action, NULL); -} - -int main(int argc, char** argv) { - if (argc == 2) { - port_name = argv[1]; - } - - printf("Using %s as serial device.\n", port_name); - - char ttybuf[255]; - tty_fd = open_tty(); - if (tty_fd < 0) { - printf("Error opening terminal.\n"); - return(1); - } - - install_sighandler(); - - if (init() < 0) { - printf("Cannot open port.\r\n"); - exit(1); - } - - while (1) { - int n = read(tty_fd, ttybuf, sizeof(ttybuf)); - int i; - - /* check for 0x3 (ctrl-c), clean exit */ - for (i = 0; i < n; i++) { - if (ttybuf[i] == 0x3) { - if (i > 0) { - write_serial_port(ttybuf, i); - } - close_serial_port(); - system("tset -c"); - return 0; - } - - } - write_serial_port(ttybuf,n); - } - - close_serial_port(); - return 0; -} - - +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "serial.h" +#include "pthread.h" +#include "download.h" + +int tty_fd; +int stopped = 0; +char* port_name = "/dev/ttyUSB1"; +pthread_t serial_reader; + +void* serial_reader_func(void* arg) { + unsigned char buf[255]; + while(1) { + int n = read_serial_port(buf, sizeof(buf)); + if (n > 0) { + write(tty_fd, buf, n); + } + } +} + +int init() { + int result = open_serial_port(port_name); + pthread_create(&serial_reader, NULL, serial_reader_func, NULL); + hard_reset_to_user_code(); + return result; +} + +struct termios old_term_setting; + +void close_tty() { + tcsetattr(tty_fd, TCSANOW, &old_term_setting); +} + +void sig_handler(int signal) { + if (signal == SIGUSR1) { + if (stopped) { + stopped = 0; + printf("\nSignal received, opening port.\r\n"); + if (init() < 0) { + printf("Cannot open port.\r\n"); + close_tty(); + exit(1); + } + } + } else if (signal == SIGUSR2) { + if (!stopped) { + stopped = 1; + printf("\nSignal received, closing port. \r\n"); + pthread_cancel(serial_reader); + close_serial_port(); + } + } else if (signal == SIGINT) { + printf("SIGINT received, exiting...\n"); + pthread_cancel(serial_reader); + close_serial_port(); + close_tty(); + exit(0); + } +} + +int open_tty(void) +{ + int r, fd; + struct termios term_setting; + + fd = open("/dev/tty", O_RDWR); + if (fd < 0) return -1; + r = tcgetattr(fd, &term_setting); + if (r != 0) return -2; + + old_term_setting = term_setting; + + term_setting.c_oflag |= ( ONLRET ); + term_setting.c_iflag |= (/*IGNBRK |*/ BRKINT | IGNPAR); + term_setting.c_iflag &= ~(ISTRIP); + term_setting.c_lflag &= ~(ICANON |/* ISIG |*/ ECHO); + term_setting.c_lflag |= ( ISIG ); + term_setting.c_cflag |= CREAD; + term_setting.c_cc[VMIN] = 1; + term_setting.c_cc[VTIME] = 1; + r = tcsetattr(fd, TCSANOW, &term_setting); + if (r != 0) return -3; + return fd; +} + +void install_sighandler() { + struct sigaction action; + sigemptyset (&action.sa_mask); + sigaddset( &action.sa_mask, SIGINT ); + sigaddset( &action.sa_mask, SIGUSR1 ); + sigaddset( &action.sa_mask, SIGUSR2 ); + action.sa_flags = 0; + action.sa_handler = sig_handler; + sigaction(SIGINT, &action, NULL); + sigaction(SIGUSR1, &action, NULL); + sigaction(SIGUSR2, &action, NULL); +} + +int main(int argc, char** argv) { + if (argc == 2) { + port_name = argv[1]; + } + + printf("Using %s as serial device.\n", port_name); + + char ttybuf[255]; + tty_fd = open_tty(); + if (tty_fd < 0) { + printf("Error opening terminal.\n"); + return(1); + } + + install_sighandler(); + + if (init() < 0) { + printf("Cannot open port.\r\n"); + exit(1); + } + + while (1) { + int n = read(tty_fd, ttybuf, sizeof(ttybuf)); + int i; + + /* check for 0x3 (ctrl-c), clean exit */ + for (i = 0; i < n; i++) { + if (ttybuf[i] == 0x3) { + if (i > 0) { + write_serial_port(ttybuf, i); + } + close_serial_port(); + close_tty(); + system("tset -c"); + return 0; + } + + } + write_serial_port(ttybuf,n); + } + + close_tty(); + close_serial_port(); + return 0; +} + + diff --git a/core/Jamfile b/core/Jamfile index 2787dcbc76..bd92e8221e 100644 --- a/core/Jamfile +++ b/core/Jamfile @@ -28,7 +28,11 @@ SubDir TOP core ; Module core : kernel_init.c sched.c mutex.c msg.c queue.c +<<<<<<< HEAD clist.c thread.c bitarithm.c ; +======= + clist.c thread.c bitarithm.c cib.c ; +>>>>>>> master Module hwtimer : hwtimer.c : hwtimer_cpu ; diff --git a/core/bitarithm.c b/core/bitarithm.c index bf9ee86991..7ffd031400 100644 --- a/core/bitarithm.c +++ b/core/bitarithm.c @@ -15,8 +15,6 @@ #include -#define ARCH_32_BIT (__INT_MAX__ == 2147483647) - unsigned number_of_highest_bit(unsigned v) { diff --git a/core/cib.c b/core/cib.c new file mode 100644 index 0000000000..b588fe671e --- /dev/null +++ b/core/cib.c @@ -0,0 +1,43 @@ +#include + +void cib_init(cib_t *cib, unsigned int size) { + cib->read_count = 0; + cib->write_count = 0; + cib->complement = 0-size; +} + +int cib_avail (cib_t *cib) { + return cib->write_count - cib->read_count; +} + +int cib_get(cib_t *cib) { + int avail = cib_avail (cib); + + if (avail > 0) { + return cib->read_count++ & ~cib->complement; + } + + return -1; +} + +int cib_put(cib_t *cib) { + int avail = cib_avail (cib); + + if ((int)(avail + cib->complement) < 0 ) { + return cib->write_count++ & ~(cib->complement); + } + + return -1; +} + +/* +int main() { + cib_t cib; + + cib_init(&cib, 0); + + int res = cib_get(&cib); + + printf("%i\n", res); +} +*/ diff --git a/core/hwtimer.c b/core/hwtimer.c index 01600a4f77..e19c8a2a8f 100644 --- a/core/hwtimer.c +++ b/core/hwtimer.c @@ -16,18 +16,14 @@ */ #include -#include "hwtimer.h" -#include "hwtimer_cpu.h" -#include "hwtimer_arch.h" +#include +#include +#include #include -#define USE_NONBLOCKING_WAIT 1 -#if USE_NONBLOCKING_WAIT -//#include -#include "kernel.h" -#include "mutex.h" -#endif +#include +#include /*---------------------------------------------------------------------------*/ @@ -37,8 +33,14 @@ typedef struct hwtimer_t { uint8_t checksum; } hwtimer_t; +typedef struct hwtimer_wait_t { + unsigned int pid; /**< pid of waiting thread */ + uint8_t state; /**state = 0; + while (!(thread_wakeup((*((hwtimer_wait_t*)hwt)).pid))) { + hwtimer_set(HWTIMER_WAIT_BACKOFF, hwtimer_wakeup, (void*) &hwt); + } } void hwtimer_spin(unsigned long ticks) @@ -113,7 +121,8 @@ void hwtimer_init_comp(uint32_t fcpu) { available_timers = 0; hwtimer_arch_init(multiplexer, fcpu); for (i = 0; i < HWTIMER_QUEUESIZE; i++) { - queue[i] = 0xff; // init queue as empty + /* init queue as empty */ + queue[i] = 0xff; } for (i = 0; i < HWTIMER_QUEUESIZE; i++) { enqueue(i); @@ -123,7 +132,7 @@ void hwtimer_init_comp(uint32_t fcpu) { /*---------------------------------------------------------------------------*/ int hwtimer_active(void) { - return queue_items != HWTIMER_QUEUESIZE; + return (queue_items != HWTIMER_QUEUESIZE); } /*---------------------------------------------------------------------------*/ @@ -137,34 +146,37 @@ unsigned long hwtimer_now(void) void hwtimer_wait(unsigned long ticks) { - mutex_t mutex; - if (ticks <= 4 || inISR()) { + if (ticks <= 6 || inISR()) { hwtimer_spin(ticks); return; } - mutex_init(&mutex); - mutex_lock(&mutex); - // -2 is to adjust the real value - int res = hwtimer_set(ticks-2, hwtimer_releasemutex, &mutex); + hwtimer_wait_t hwt; + hwt.pid = active_thread->pid; + hwt.state = 1; + /* -2 is to adjust the real value */ + int res = hwtimer_set(ticks-2, hwtimer_wakeup, (void*) &hwt); if (res == -1) { - mutex_unlock(&mutex, true); hwtimer_spin(ticks); return; } - mutex_lock(&mutex); + while (hwt.state) { + thread_sleep(); + } } /*---------------------------------------------------------------------------*/ static int _hwtimer_set(unsigned long offset, void (*callback)(void*), void *ptr, bool absolute) { - if (! inISR() ) dINT(); -// hwtimer_arch_disable_interrupt(); + if (!inISR()) { + dINT(); + } int x = dequeue(); if (x == Q_FULL) { + if (! inISR()) { + eINT(); + } printf("[KT] no timers left\n"); -// hwtimer_arch_enable_interrupt(); - if (! inISR()) eINT(); return -1; } @@ -172,13 +184,16 @@ static int _hwtimer_set(unsigned long offset, void (*callback)(void*), void *ptr timer[x].data = ptr; timer[x].checksum = ++timer_id; - if (absolute) + if (absolute) { hwtimer_arch_set_absolute(offset, x); - else + } + else { hwtimer_arch_set(offset, x); + } - //hwtimer_arch_enable_interrupt(); - if (! inISR()) eINT(); + if (!inISR()) { + eINT(); + } return (timer[x].checksum << 8) + x; } diff --git a/core/include/bitarithm.h b/core/include/bitarithm.h index de06c50241..d159f33348 100644 --- a/core/include/bitarithm.h +++ b/core/include/bitarithm.h @@ -64,6 +64,8 @@ #endif /** @} */ +#define ARCH_32_BIT (__INT_MAX__ == 2147483647) + /** * @brief Returns the number of the highest '1' bit in a value * @param[in] v Input value diff --git a/core/include/cib.h b/core/include/cib.h new file mode 100644 index 0000000000..7ef179280d --- /dev/null +++ b/core/include/cib.h @@ -0,0 +1,15 @@ +#ifndef __CIB_H +#define __CIB_H + +typedef struct cib_t { + unsigned int read_count; + unsigned int write_count; + unsigned int complement; +} cib_t; + +void cib_init(cib_t *cib, unsigned int size); +int cib_get(cib_t *cib); +int cib_put(cib_t *cib); +int cib_avail(cib_t *cib); + +#endif /* __CIB_H */ diff --git a/core/include/flags.h b/core/include/flags.h index 97da2efa8a..462133ef70 100644 --- a/core/include/flags.h +++ b/core/include/flags.h @@ -15,9 +15,9 @@ #ifndef _FLAGS_H #define _FLAGS_H -#define CREATE_WOUT_YIELD 4 #define CREATE_SLEEPING 1 -#define EXPECTS_REPLY 2 +#define AUTO_FREE 2 +#define CREATE_WOUT_YIELD 4 #define CREATE_STACKTEST 8 /** diff --git a/core/include/hwtimer.h b/core/include/hwtimer.h index 39f2c0f189..d17137edeb 100644 --- a/core/include/hwtimer.h +++ b/core/include/hwtimer.h @@ -30,7 +30,7 @@ #define __HWTIMER_H #include -#include "hwtimer_cpu.h" +#include /** * @def HWTIMER_SPEED @@ -124,6 +124,7 @@ void hwtimer_t0_enable_interrupt(void); void hwtimer_t0_set(unsigned long value, short timer); void hwtimer_t0_unset(short timer); unsigned long hwtimer_t0_now(void); +unsigned long hwtimer_now(void); /** @} */ #endif /* __HWTIMER_H */ diff --git a/core/include/kernel.h b/core/include/kernel.h index 97313916e9..7aeac5ada1 100644 --- a/core/include/kernel.h +++ b/core/include/kernel.h @@ -70,15 +70,7 @@ #define PRIORITY_MIN SCHED_PRIO_LEVELS-1 #define PRIORITY_IDLE PRIORITY_MIN -#define PRIORITY_MAIN PRIORITY_MIN-1 -#define PRIORITY_CMD_THREADS PRIORITY_MIN-2 ///< all cmd handler threads -#define PRIORITY_CBD PRIORITY_MIN-3 -#define PRIORITY_CMDD PRIORITY_MIN-4 ///< cmdengine demon -#define PRIORITY_PRINTTHREAD PRIORITY_MIN-5 ///< mprint worker thread -#define PRIORITY_HAL PRIORITY_MIN-6 -#define PRIORITY_UTIMER PRIORITY_MIN-7 -#define PRIORITY_MMREQ PRIORITY_MIN-8 -#define PRIORITY_CC1100 PRIORITY_MIN-9 +#define PRIORITY_MAIN (PRIORITY_MIN - (SCHED_PRIO_LEVELS/2)) /** * @brief Check whether called from interrupt service routine @@ -88,6 +80,7 @@ */ int inISR(void); +#define LPM_PREVENT_SLEEP_UART BIT2 #define LPM_PREVENT_SLEEP_HWTIMER BIT1 extern volatile int lpm_prevent_sleep; diff --git a/core/include/msg.h b/core/include/msg.h index 4a0504c7f7..4d9a0b9aba 100644 --- a/core/include/msg.h +++ b/core/include/msg.h @@ -105,7 +105,13 @@ int msg_send_receive(msg *m, msg *reply, unsigned int target_pid); */ int msg_reply(msg *m, msg *reply); -uint16_t msg_alloc_event(void); +/** + * @brief Initialize the current thread's message queue. + * + * @param array Pointer to preallocated array of msg objects + * @param num Number of msg objects in array. MUST BE POWER OF TWO! + */ +int msg_init_queue(msg* array, int num); /** @} */ #endif /* __MSG_H */ diff --git a/core/include/sched.h b/core/include/sched.h index ca5f74ddb1..ad30cfb601 100644 --- a/core/include/sched.h +++ b/core/include/sched.h @@ -15,7 +15,7 @@ #define MAXTHREADS 32 -#ifdef ARCH_32_BIT +#if ARCH_32_BIT #define SCHED_PRIO_LEVELS 32 #else #define SCHED_PRIO_LEVELS 16 @@ -25,6 +25,7 @@ void sched_init(); void sched_run(); void sched_set_status(tcb *process, unsigned int status); +void sched_switch(uint16_t current_prio, uint16_t other_prio, int in_isr); volatile unsigned int sched_context_switch_request; diff --git a/core/include/tcb.h b/core/include/tcb.h index 66ef085e3f..d5d2a63645 100644 --- a/core/include/tcb.h +++ b/core/include/tcb.h @@ -17,33 +17,39 @@ #define TCB_H_ #include -#include "queue.h" -#include "clist.h" +#include +#include +#include +#include /* uneven means has to be on runqueue */ -#define STATUS_NOT_FOUND 0 -#define STATUS_ON_RUNQUEUE 1 -#define STATUS_RUNNING 2 + STATUS_ON_RUNQUEUE -#define STATUS_PENDING 4 + STATUS_ON_RUNQUEUE -#define STATUS_STOPPED 8 -#define STATUS_SLEEPING 16 -#define STATUS_MUTEX_BLOCKED 32 -#define STATUS_RECEIVE_BLOCKED 64 -#define STATUS_SEND_BLOCKED 128 -#define STATUS_REPLY_BLOCKED 256 +#define STATUS_NOT_FOUND (0x0000) +#define STATUS_ON_RUNQUEUE (0x0001) +#define STATUS_RUNNING (0x0002) + STATUS_ON_RUNQUEUE +#define STATUS_PENDING (0x0004) + STATUS_ON_RUNQUEUE +#define STATUS_STOPPED (0x0008) +#define STATUS_SLEEPING (0x0010) +#define STATUS_MUTEX_BLOCKED (0x0020) +#define STATUS_RECEIVE_BLOCKED (0x0040) +#define STATUS_SEND_BLOCKED (0x0080) +#define STATUS_REPLY_BLOCKED (0x0100) +#define STATUS_TIMER_WAITING (0x0200) typedef struct tcb { char* sp; - unsigned int status; + uint16_t status; uint16_t pid; uint16_t priority; - void* wait_data; - queue_node_t msg_queue; - clist_node_t rq_entry; + void* wait_data; + queue_node_t msg_waiters; + + cib_t msg_queue; + msg* msg_array; + const char* name; char* stack_start; int stack_size; diff --git a/core/include/thread.h b/core/include/thread.h index b81e07dcd1..359d778d91 100644 --- a/core/include/thread.h +++ b/core/include/thread.h @@ -14,12 +14,15 @@ */ #include +#include +/** Minimum stack size */ +#define MINIMUM_STACK_SIZE (sizeof(tcb)) /** * @brief Creates a new thread. - * This version will allocate it's stack itself using malloc. - * + * + * @param stack Lowest address of preallocated stack space * @param stacksize * @param flags Options: * YIELD: force context switch. @@ -32,7 +35,7 @@ * * @return returns <0 on error, pid of newly created task else. */ -int thread_create(int stacksize, char priority, int flags, void (*function) (void), const char* name); +int thread_create(char *stack, int stacksize, char priority, int flags, void (*function) (void), const char* name); /** * @brief returns the status of a process. diff --git a/core/kernel_init.c b/core/kernel_init.c index e511c13067..6296e59a24 100644 --- a/core/kernel_init.c +++ b/core/kernel_init.c @@ -17,6 +17,7 @@ #include #include #include +<<<<<<< HEAD #include "tcb.h" #include "kernel.h" #include "kernel_intern.h" @@ -26,13 +27,24 @@ #include "lpm.h" #include "thread.h" #include "hwtimer.h" +======= +#include +#include +#include +#include +#include +#include +#include +#include +#include +>>>>>>> master #ifdef MODULE_AUTO_INIT #include #endif #define ENABLE_DEBUG -#include "debug.h" +#include volatile tcb *sched_threads[MAXTHREADS]; volatile tcb *active_thread; @@ -57,6 +69,9 @@ static void idle_thread(void) { const char *main_name = "main"; const char *idle_name = "idle"; +static char main_stack[KERNEL_CONF_STACKSIZE_MAIN]; +static char idle_stack[KERNEL_CONF_STACKSIZE_IDLE]; + #ifdef MODULE_AUTO_INIT #define MAIN_FUNC auto_init #else @@ -66,15 +81,19 @@ const char *idle_name = "idle"; void kernel_init(void) { dINT(); - printf("kernel_init(): This is µkleos!\n"); + printf("kernel_init(): This is ukleos!\n"); sched_init(); +<<<<<<< HEAD if (thread_create(KERNEL_CONF_STACKSIZE_IDLE, PRIORITY_IDLE, CREATE_WOUT_YIELD | CREATE_STACKTEST, idle_thread, idle_name) < 0) { +======= + if (thread_create(idle_stack, sizeof(idle_stack), PRIORITY_IDLE, CREATE_WOUT_YIELD | CREATE_STACKTEST, idle_thread, idle_name) < 0) { +>>>>>>> master printf("kernel_init(): error creating idle task.\n"); } - if (thread_create(KERNEL_CONF_STACKSIZE_MAIN, PRIORITY_MAIN, CREATE_WOUT_YIELD | CREATE_STACKTEST, MAIN_FUNC, main_name) < 0) { + if (thread_create(main_stack, sizeof(main_stack), PRIORITY_MAIN, CREATE_WOUT_YIELD | CREATE_STACKTEST, MAIN_FUNC, main_name) < 0) { printf("kernel_init(): error creating main task.\n"); } diff --git a/core/msg.c b/core/msg.c index 32eda613fc..e93b6a3c98 100644 --- a/core/msg.c +++ b/core/msg.c @@ -20,32 +20,56 @@ #include "tcb.h" #include #include +#include #include "flags.h" //#define ENABLE_DEBUG #include "debug.h" +static int queue_msg(tcb *target, msg *m) { + int n = cib_put(&(target->msg_queue)); + + if (n != -1) { + target->msg_array[n] = *m; + return 1; + } + + return 0; +} + int msg_send(msg* m, unsigned int target_pid, bool block) { if (inISR()) { return msg_send_int(m, target_pid); } +<<<<<<< HEAD int result = 1; tcb *target = (tcb*)sched_threads[target_pid]; m->sender_pid = thread_pid; if (m->sender_pid == target_pid) return -1; +======= + tcb *target = (tcb*)sched_threads[target_pid]; +>>>>>>> master - dINT(); - - if (target == NULL) { - eINT(); + m->sender_pid = thread_pid; + if (m->sender_pid == target_pid) { return -1; } + if (target == NULL) { + return -1; + } + + dINT(); if (target->status != STATUS_RECEIVE_BLOCKED) { + if (target->msg_array && queue_msg(target, m)) { + eINT(); + return 1; + } + if (! block ) { DEBUG("%s: receiver not waiting. block=%u\n", active_thread->name, block); eINT(); @@ -56,9 +80,13 @@ int msg_send(msg* m, unsigned int target_pid, bool block) { queue_node_t n; n.priority = active_thread->priority; n.data = (unsigned int) active_thread; +<<<<<<< HEAD DEBUG("%s: Adding node to msg_queue:\n", active_thread->name); +======= + DEBUG("%s: Adding node to msg_waiters:\n", active_thread->name); +>>>>>>> master - queue_priority_add(&(target->msg_queue), &n); + queue_priority_add(&(target->msg_waiters), &n); active_thread->wait_data = (void*) m; @@ -83,7 +111,7 @@ int msg_send(msg* m, unsigned int target_pid, bool block) { eINT(); thread_yield(); - return result; + return 1; } int msg_send_int(msg* m, unsigned int target_pid) { @@ -103,9 +131,8 @@ int msg_send_int(msg* m, unsigned int target_pid) { return 1; } else { DEBUG("msg_send_int: receiver not waiting.\n"); - return 0; + return (queue_msg(target, m)); } - } int msg_send_receive(msg *m, msg *reply, unsigned int target_pid) { @@ -148,35 +175,68 @@ int msg_reply_int(msg *m, msg *reply) { return -1; } msg* target_message = (msg*)target->wait_data; - *target_message = *m; + *target_message = *reply; sched_set_status(target, STATUS_PENDING); sched_context_switch_request = 1; return 1; } - int msg_receive(msg* m) { dINT(); DEBUG("%s: msg_receive.\n", active_thread->name); tcb *me = (tcb*) sched_threads[thread_pid]; - me->wait_data = (void*) m; + int n = -1; + if (me->msg_array) { + n = cib_get(&(me->msg_queue)); + } - queue_node_t *n = queue_remove_head(&(me->msg_queue)); + if (n >= 0) { + DEBUG("%s: msg_receive(): We've got a queued message.\n", active_thread->name); + *m = me->msg_array[n]; + } else { + me->wait_data = (void*) m; + } +<<<<<<< HEAD if (n == NULL) { DEBUG("%s: msg_receive blocked\n", active_thread->name); sched_set_status(me, STATUS_RECEIVE_BLOCKED); eINT(); thread_yield(); +======= + queue_node_t *node = queue_remove_head(&(me->msg_waiters)); - /* sender copied message */ + if (node == NULL) { + DEBUG("%s: msg_receive(): No thread in waiting list.\n", active_thread->name); + if (n < 0) { + DEBUG("%s: msg_receive(): No msg in queue. Going blocked.\n", active_thread->name); + sched_set_status(me, STATUS_RECEIVE_BLOCKED); +>>>>>>> master + + eINT(); + thread_yield(); + + /* sender copied message */ + } return 1; } else { +<<<<<<< HEAD DEBUG("%s: msg_receive direct copy.\n", active_thread->name); tcb *sender = (tcb*)n->data; +======= + DEBUG("%s: msg_receive(): Wakeing up waiting thread.\n", active_thread->name); + tcb *sender = (tcb*)node->data; + + if (n >= 0) { + /* we've already got a messgage from the queue. as there is a + * waiter, take it's message into the just freed queue space. + */ + m = &(me->msg_array[cib_put(&(me->msg_queue))]); + } +>>>>>>> master /* copy msg */ msg* sender_msg = (msg*)sender->wait_data; @@ -190,3 +250,15 @@ int msg_receive(msg* m) { return 1; } } + +int msg_init_queue(msg* array, int num) { + /* make sure brainfuck condition is met */ + if (num && (num & (num - 1)) == 0) { + tcb *me = (tcb*)active_thread; + me->msg_array = array; + cib_init(&(me->msg_queue), num); + return 0; + } + + return -1; +} diff --git a/core/mutex.c b/core/mutex.c index be33fba931..72fd9cc686 100644 --- a/core/mutex.c +++ b/core/mutex.c @@ -20,6 +20,10 @@ #include "tcb.h" #include "kernel.h" #include "sched.h" +<<<<<<< HEAD +======= +#include +>>>>>>> master //#define ENABLE_DEBUG #include @@ -35,6 +39,7 @@ int mutex_init(struct mutex_t* mutex) { } int mutex_trylock(struct mutex_t* mutex) { +<<<<<<< HEAD return (atomic_set_return(&mutex->val, thread_pid ) == 0); } @@ -46,12 +51,23 @@ int mutex_lock(struct mutex_t* mutex) { DEBUG("%s: trying to get mutex. val: %u\n", active_thread->name, mutex->val); if (atomic_set_return(&mutex->val,thread_pid) != 0) { +======= + DEBUG("%s: trylocking to get mutex. val: %u\n", active_thread->name, mutex->val); + return atomic_set_return(&mutex->val, 1 ) == 0; +} + +int mutex_lock(struct mutex_t* mutex) { + DEBUG("%s: trying to get mutex. val: %u\n", active_thread->name, mutex->val); + + if (atomic_set_return(&mutex->val,1) != 0) { +>>>>>>> master // mutex was locked. mutex_wait(mutex); } return 1; } +<<<<<<< HEAD void mutex_unlock(struct mutex_t* mutex, int yield) { DEBUG("%s: unlocking mutex. val: %u pid: %u\n", active_thread->name, mutex->val, thread_pid); int me_value; @@ -71,12 +87,20 @@ void mutex_unlock(struct mutex_t* mutex, int yield) { void mutex_wait(struct mutex_t *mutex) { dINT(); +======= +void mutex_wait(struct mutex_t *mutex) { + int irqstate = disableIRQ(); +>>>>>>> master DEBUG("%s: Mutex in use. %u\n", active_thread->name, mutex->val); if (mutex->val == 0) { // somebody released the mutex. return. mutex->val = thread_pid; DEBUG("%s: mutex_wait early out. %u\n", active_thread->name, mutex->val); +<<<<<<< HEAD eINT(); +======= + restoreIRQ(irqstate); +>>>>>>> master return; } @@ -87,17 +111,22 @@ void mutex_wait(struct mutex_t *mutex) { n.data = (unsigned int) active_thread; n.next = NULL; +<<<<<<< HEAD DEBUG("%s: Adding node to mutex queue: prio: %u data: %u\n", active_thread->name, n.priority, n.data); +======= + DEBUG("%s: Adding node to mutex queue: prio: %u\n", active_thread->name, n.priority); +>>>>>>> master queue_priority_add(&(mutex->queue), &n); - eINT(); + restoreIRQ(irqstate); thread_yield(); /* we were woken up by scheduler. waker removed us from queue. we have the mutex now. */ } +<<<<<<< HEAD void mutex_wake_waiters(struct mutex_t *mutex, int flags) { if ( ! (flags & MUTEX_INISR)) dINT(); DEBUG("%s: waking up waiters.\n", active_thread->name); @@ -122,5 +151,25 @@ void mutex_wake_waiters(struct mutex_t *mutex, int flags) { } else { sched_context_switch_request = 1; } +======= +void mutex_unlock(struct mutex_t* mutex, int yield) { + DEBUG("%s: unlocking mutex. val: %u pid: %u\n", active_thread->name, mutex->val, thread_pid); + int irqstate = disableIRQ(); + + if (mutex->val != 0) { + if (mutex->queue.next) { + queue_node_t *next = queue_remove_head(&(mutex->queue)); + tcb* process = (tcb*)next->data; + DEBUG("%s: waking up waiter %s.\n", process->name); + sched_set_status(process, STATUS_PENDING); + + sched_switch(active_thread->priority, process->priority, inISR()); + } else { + mutex->val = 0; + } + } + + restoreIRQ(irqstate); +>>>>>>> master } diff --git a/core/queue.c b/core/queue.c index edb9927f7f..bfc50b4ce0 100644 --- a/core/queue.c +++ b/core/queue.c @@ -56,7 +56,7 @@ void queue_priority_add(queue_node_t* root, queue_node_t* new_obj) { queue_node_t* node = root; while (node->next != NULL) { - if (node->next->priority < new_obj->priority) { + if (node->next->priority > new_obj->priority) { new_obj->next = node->next; node->next = new_obj; return; diff --git a/core/sched.c b/core/sched.c index 7cd222a3b8..3ebdbf01bf 100644 --- a/core/sched.c +++ b/core/sched.c @@ -14,15 +14,22 @@ */ #include +<<<<<<< HEAD:core/sched.c #include #include "sched.h" #include "kernel.h" #include "kernel_intern.h" #include "clist.h" +======= +#include +#include +#include +#include +>>>>>>> master:core/sched.c #include //#define ENABLE_DEBUG -#include "debug.h" +#include volatile int num_tasks = 0; @@ -144,6 +151,20 @@ void sched_set_status(tcb *process, unsigned int status) { process->status = status; } +<<<<<<< HEAD:core/sched.c +======= +void sched_switch(uint16_t current_prio, uint16_t other_prio, int in_isr) { + DEBUG("%s: %i %i %i\n", active_thread->name, (int)current_prio, (int)other_prio, in_isr); + if (current_prio <= other_prio) { + if (in_isr) { + sched_context_switch_request = 1; + } else { + thread_yield(); + } + } +} + +>>>>>>> master:core/sched.c extern void cpu_switch_context_exit(void); void sched_task_exit(void) { @@ -152,9 +173,15 @@ void sched_task_exit(void) { dINT(); sched_threads[active_thread->pid] = NULL; num_tasks--; +<<<<<<< HEAD:core/sched.c sched_set_status((tcb*)active_thread, STATUS_STOPPED); free(((tcb*)active_thread)->stack_start); +======= + + sched_set_status((tcb*)active_thread, STATUS_STOPPED); + +>>>>>>> master:core/sched.c active_thread = NULL; cpu_switch_context_exit(); } diff --git a/core/thread.c b/core/thread.c index 33adb3e31c..43da40f12a 100644 --- a/core/thread.c +++ b/core/thread.c @@ -14,7 +14,6 @@ */ #include -#include #include #include "thread.h" @@ -45,11 +44,19 @@ void thread_sleep() { } int thread_wakeup(int pid) { + DEBUG("thread_wakeup: Trying to wakeup PID %i...\n", pid); int isr = inISR(); - if (! isr) dINT(); + if (! isr) { + DEBUG("thread_wakeup: Not in interrupt.\n"); + dINT(); + } int result = sched_threads[pid]->status; if (result == STATUS_SLEEPING) { +<<<<<<< HEAD +======= + DEBUG("thread_wakeup: Thread is sleeping.\n"); +>>>>>>> master sched_set_status((tcb*)sched_threads[pid], STATUS_RUNNING); if (!isr) { eINT(); @@ -57,8 +64,9 @@ int thread_wakeup(int pid) { } else { sched_context_switch_request = 1; } - return 0; + return 1; } else { + DEBUG("thread_wakeup: Thread is not sleeping!\n"); if (!isr) eINT(); return STATUS_NOT_FOUND; } @@ -74,32 +82,28 @@ int thread_measure_stack_usage(char* stack) { return space; } -int thread_create(int stacksize, char priority, int flags, void (*function) (void), const char* name) +int thread_create(char *stack, int stacksize, char priority, int flags, void (*function) (void), const char* name) { - /* stacksize must be a multitude of 4 for alignment and stacktest */ -// assert( ((stacksize & 0x03) == 0) && (stacksize > 0) ); + /* allocate our thread control block at the top of our stackspace */ + int total_stacksize = stacksize; + stacksize -= sizeof(tcb); - // TODO: shall we autoalign the stack? - // stacksize += 4-(~(stacksize & 0x0003)); + /* align tcb address on 32bit boundary */ + unsigned int tcb_address = (unsigned int) stack + stacksize; + if ( tcb_address & 1 ) { + tcb_address--; + stacksize--; + } + if ( tcb_address & 2 ) { + tcb_address-=2; + stacksize-=2; + } + tcb *cb = (tcb*) tcb_address; if (priority >= SCHED_PRIO_LEVELS) { return -EINVAL; } - tcb *pd = (tcb*)malloc(sizeof(tcb)); - if ( pd == NULL) { - DEBUG("thread_create(): out of memory\n"); - return -ENOMEM; - } - - char *stack = (char*)malloc(stacksize); - if (stack==NULL) - { - DEBUG("thread_create(): out of memory\n"); - free (pd); - return -ENOMEM; - } - if (flags & CREATE_STACKTEST) { /* assign each int of the stack the value of it's address */ unsigned int *stackmax = (unsigned int*) ((char*)stack + stacksize); @@ -120,8 +124,13 @@ int thread_create(int stacksize, char priority, int flags, void (*function) (voi int pid = 0; while (pid < MAXTHREADS) { if (sched_threads[pid] == NULL) { +<<<<<<< HEAD sched_threads[pid] = pd; pd->pid = pid; +======= + sched_threads[pid] = cb; + cb->pid = pid; +>>>>>>> master break; } pid++; @@ -130,42 +139,48 @@ int thread_create(int stacksize, char priority, int flags, void (*function) (voi if (pid == MAXTHREADS) { DEBUG("thread_create(): too many threads!\n"); - free (pd); - free (stack); - if (! inISR()) { eINT(); } return -EOVERFLOW; } +<<<<<<< HEAD pd->sp = thread_stack_init(function,stack+stacksize); pd->stack_start = stack; pd->stack_size = stacksize; +======= + cb->sp = thread_stack_init(function,stack+stacksize); + cb->stack_start = stack; + cb->stack_size = total_stacksize; - pd->priority = priority; - pd->status = 0; + cb->priority = priority; + cb->status = 0; +>>>>>>> master - pd->name = name; + cb->rq_entry.data = (unsigned int) cb; + cb->rq_entry.next = NULL; + cb->rq_entry.prev = NULL; - pd->wait_data = NULL; + cb->name = name; - pd->msg_queue.data = 0; - pd->msg_queue.priority = 0; - pd->msg_queue.next = NULL; + cb->wait_data = NULL; - pd->rq_entry.data = (unsigned int) pd; - pd->rq_entry.next = NULL; - pd->rq_entry.prev = NULL; + cb->msg_waiters.data = 0; + cb->msg_waiters.priority = 0; + cb->msg_waiters.next = NULL; + + cib_init(&(cb->msg_queue),0); + cb->msg_array = NULL; num_tasks++; - DEBUG("Created thread %s. PID: %u. Priority: %u.\n", name, pd->pid, priority); + DEBUG("Created thread %s. PID: %u. Priority: %u.\n", name, cb->pid, priority); if (flags & CREATE_SLEEPING) { - sched_set_status(pd, STATUS_SLEEPING); + sched_set_status(cb, STATUS_SLEEPING); } else { - sched_set_status(pd, STATUS_PENDING); + sched_set_status(cb, STATUS_PENDING); if (!(flags & CREATE_WOUT_YIELD)) { if (! inISR()) { eINT(); diff --git a/cpu/arm_common/Jamfile b/cpu/arm_common/Jamfile index 5438882366..0252c75781 100644 --- a/cpu/arm_common/Jamfile +++ b/cpu/arm_common/Jamfile @@ -27,7 +27,7 @@ SubDir TOP cpu arm_common ; -Module arm_common : common.s bootloader.c VIC.c atomic.s arm_cpu.c ; +Module arm_common : common.s bootloader.c VIC.c atomic.s arm_cpu.c iap.c ; UseModule arm_common ; Module hwtimer_cpu : hwtimer_cpu.c ; diff --git a/cpu/arm_common/iap.c b/cpu/arm_common/iap.c new file mode 100644 index 0000000000..92f8ff82c4 --- /dev/null +++ b/cpu/arm_common/iap.c @@ -0,0 +1,254 @@ +/* iap driver + * + * based on iap driver for LPC2148 Controller made by Andreas Weschenfelder, 2008 + * see: + * + */ + +#include +#include + +#define ENABLE_DEBUG +#include + +static unsigned int iap_command[5]; // contains parameters for IAP command +static unsigned int iap_result[2]; // contains results +typedef void (*IAP) (unsigned int[],unsigned int[]); // typedefinition for IAP entry function +IAP IAP_Entry; + +/* some function prototypes */ +static uint32_t blank_check_sector(uint32_t tmp_sect1, uint32_t tmp_sect2); +static uint32_t prepare_sectors(uint32_t tmp_sect1, uint32_t tmp_sect2); +static uint32_t erase_sectors(uint32_t tmp_sect1, uint32_t tmp_sect2); +static uint32_t copy_ram_to_flash(uint32_t tmp_adr_dst, uint32_t tmp_adr_src, uint32_t tmp_size); +static uint32_t compare(uint32_t tmp_adr_dst, uint32_t tmp_adr_src, uint32_t tmp_size); +static uint32_t iap(uint32_t code, uint32_t p1, uint32_t p2, uint32_t p3, uint32_t p4); + +/****************************************************************************** + * P U B L I C F U N C T I O N S + *****************************************************************************/ +uint8_t iap_write(uint32_t dst, char *src, uint32_t size) { + char err; + uint32_t buffer_vic; + uint8_t sec; + + buffer_vic = VICIntEnable; // save interrupt enable + VICIntEnClr = 0xFFFFFFFF; // clear vic + + sec = iap_get_sector(dst); + + /* check sector */ + if(blank_check_sector(sec, sec) == SECTOR_NOT_BLANK) { + DEBUG("Warning: Sector %i not blank\n", sec); + } + + /* prepare sector */ + err = prepare_sectors(iap_get_sector(dst), iap_get_sector(dst)); + if (err) { + DEBUG("\n-- ERROR: PREPARE_SECTOR_FOR_WRITE_OPERATION: %u", err); + /* set interrupts back and return */ + VICIntEnable = buffer_vic; + return 0; + } + /* write flash */ + else { + err = copy_ram_to_flash(dst, (uint32_t) src, size); + if(err) { + DEBUG("ERROR: COPY_RAM_TO_FLASH: %u\n", err); + /* set interrupts back and return */ + VICIntEnable = buffer_vic; + return 0; + } + /* check result */ + else { + err = compare(dst, (uint32_t) src, size); + if (err) { + DEBUG("ERROR: COMPARE: %i (at position %u)\n", err, iap_result[1]); + /* set interrupts back and return */ + VICIntEnable = buffer_vic; + return 0; + } + else + { + DEBUG("Data successfully written!\n"); + /* set interrupts back and return */ + return 1; + } + } + } +} + + +uint8_t iap_erase(uint32_t addr) { + /* check sector */ + if (!blank_check_sector(iap_get_sector(addr), iap_get_sector(addr))) { + DEBUG("Sector already blank!\n"); + return 1; + } + /* prepare sector */ + if (prepare_sectors(iap_get_sector(addr), iap_get_sector(addr))) { + DEBUG("-- ERROR: PREPARE_SECTOR_FOR_WRITE_OPERATION --\n"); + return 0; + } + /* erase sector */ + if (erase_sectors(iap_get_sector(addr), iap_get_sector(addr))) { + DEBUG("-- ERROR: ERASE SECTOR --\n"); + return 0; + } + /* check again */ + if (blank_check_sector(iap_get_sector(addr), iap_get_sector(addr))) { + DEBUG("-- ERROR: BLANK_CHECK_SECTOR\n"); + return 0; + } + DEBUG("Sector successfully erased.\n"); + return 1; +} + + +/****************************************************************************** + * PRIVATE FUNCTIONS + *****************************************************************************/ + +static uint32_t iap(uint32_t code, uint32_t p1, uint32_t p2, uint32_t p3, uint32_t p4) { + iap_command[0] = code; // set command code + iap_command[1] = p1; // set 1st param + iap_command[2] = p2; // set 2nd param + iap_command[3] = p3; // set 3rd param + iap_command[4] = p4; // set 4th param + + ((void (*)())0x7ffffff1)(iap_command, iap_result); // IAP entry point + return *iap_result; +} + +/****************************************************************************** + * Function: blank_check_sector + * + * Description: This command is used to blank check a sector or multiple sectors + * of on-chip Flash memory. To blank check a single sector use the + * same "Start" and "End" sector numbers. + * Command: 53 + * Param0: Start Sector Number + * Param1: End Sector Number (should be greater than equal to the start + * sector number) + * + * Parameters: long tmp_sect1: Param0 + * long tmp_sect2: Param1 + * + * Return: Code CMD_SUCCESS | + * BUSY | + * SECTOR_NOT_BLANK | + * INVALID_SECTOR + * Result0: Offset of the first non blank word location if the status code is SECTOR_NOT_BLANK. + * Result1: Contents of non blank wird location. + *****************************************************************************/ +uint32_t blank_check_sector(uint32_t tmp_sect1, uint32_t tmp_sect2) { + return iap(BLANK_CHECK_SECTOR, tmp_sect1, tmp_sect2, 0 , 0); +} + + +/****************************************************************************** + * Function: copy_ram_to_flash + * + * Description: This command is used to programm the flash memory. the affected should be + * prepared first by calling "Prepare Sector for Write Operation" command. the + * affected sectors are automatically protected again once the copy command is + * successfully executed. the boot sector cannot be written by this command. + * Command: 51 + * Param0: (DST) Destination Flash adress where data bytes are to be written. + * This address should be a 512 byte boundary. + * Param1: (SRC) Source RAM adress from which data byre are to be read. + * Param2: Number of bytes to be written. Should be 512 | 1024 | 4096 | 8192. + * Param3: System Clock Frequency (CCLK) in KHz. + * + * Parameters: long tmp_adr_dst: Param0 + * long tmp_adr_src: Param1 + * long tmp_size: Param2 + * + * Return: Code CMD_SUCCESS | + * SRC_ADDR_ERROR (Address not on word boundary) | + * DST_ADDR_ERROR (Address not on correct boundary) | + * SRC_ADDR_NOT_MAPPED | + * DST_ADDR_NOT_MAPPED | + * COUNT_ERROR (Byte count is not 512 | 1024 | 4096 | 8192) | + * SECTOR_NOT_PREPARED_FOR_WRITE_OPERATION | + * BUSY + *****************************************************************************/ +uint32_t copy_ram_to_flash(uint32_t tmp_adr_dst, uint32_t tmp_adr_src, uint32_t tmp_size) { + return iap(COPY_RAM_TO_FLASH, tmp_adr_dst, tmp_adr_src, tmp_size, _XTAL); +} + + +/****************************************************************************** + * Function: Prepare_Sector + * + * Description: This command must be executed before executing "Copy RAM to Flash" or "Erase Sector(s)" + * command. Successful execution of the "Copy RAM to Flash" or "Erase Sector(s)" command causes + * relevant sectors to be protected again. The boot sector can not be prepared by this command. To + * prepare a single sector use the same "Start" and "End" sector numbers.. + * Command code: 50 + * Param0: Start Sector Number + * Param1: End Sector Number: Should be greater than or equal to start sector number. + * + * Parameters: long tmp_sect1: Param0 + * long tmp_sect2: Param1 + * + * Return: Code CMD_SUCCESS | + * BUSY | + * INVALID_SECTOR + *****************************************************************************/ +uint32_t prepare_sectors(uint32_t tmp_sect1, uint32_t tmp_sect2) { + return iap(PREPARE_SECTOR_FOR_WRITE_OPERATION, tmp_sect1, tmp_sect2, 0 , 0); +} + + +/****************************************************************************** + * Function: erase_sectors + * + * Description: This command is used to erase a sector or multiple sectors of on-chip Flash memory. The boot + * sector can not be erased by this command. To erase a single sector use the same "Start" and "End" + * sector numbers. + * Command code: 52 + * Param0: Start Sector Number + * Param1: End Sector Number: Should be greater than or equal to start sector number. + * Param2: System Clock Frequency (CCLK) in KHz. + * + * Parameters: long tmp_sect1: Param0 + * long tmp_sect2: Param1 + * + * Return: Code CMD_SUCCESS | + * BUSY | + * SECTOR_NOT_PREPARED_FOR_WRITE_OPERATION | + * INVALID_SECTOR + *****************************************************************************/ +uint32_t erase_sectors(uint32_t tmp_sect1, uint32_t tmp_sect2) { + return iap(ERASE_SECTOR, tmp_sect1, tmp_sect2, _XTAL, 0); +} + + +/****************************************************************************** + * Function: compare + * + * Description: This command is used to compare the memory contents at two locations. compare result may not + * be correct when source or destination address contains any of the first 64 bytes starting + * from address zero. First 64 bytes can be re-mapped to RAM. + * Command Code: 56 + * Param0(DST): Starting Flash or RAM address from where data bytes are to be + * address should be a word boundary. + * Param1(SRC): Starting Flash or RAM address from where data bytes are to be + * address should be a word boundary. + * Param2: Number of bytes to be compared. Count should be in multiple of 4. + * + * Parameters: long tmp_adr_dst + * long tmp_adr_src + * long tmp_size + * + * Return: Code CMD_SUCCESS | + * COMPARE_ERROR | + * COUNT_ERROR (Byte count is not multiple of 4) | + * ADDR_ERROR | + * ADDR_NOT_MAPPED + * Result0: Offset of the first mismatch if the Status Code is COMPARE_ERROR. + *****************************************************************************/ +uint32_t compare(uint32_t tmp_adr_dst, uint32_t tmp_adr_src, uint32_t tmp_size) { + return iap(COMPARE, tmp_adr_dst, tmp_adr_src, tmp_size, 0); +} diff --git a/cpu/arm_common/include/iap.h b/cpu/arm_common/include/iap.h new file mode 100644 index 0000000000..1ec589eab2 --- /dev/null +++ b/cpu/arm_common/include/iap.h @@ -0,0 +1,67 @@ +#ifndef IAP_H_ +#define IAP_H_ + +#include + +/* IAP-Commands */ +#define PREPARE_SECTOR_FOR_WRITE_OPERATION (50) +#define COPY_RAM_TO_FLASH (51) +#define ERASE_SECTOR (52) +#define BLANK_CHECK_SECTOR (53) +#define READ_PART_ID (54) +#define READ_BOOT_CODE_VERSION (55) +#define COMPARE (56) + +/* IAP status codes */ +#define CMD_SUCCESS (0) +#define INVALID_COMMAND (1) +#define SRC_ADDR_ERROR (2) +#define DST_ADDR_ERROR (3) +#define SRC_ADDR_NOT_MAPPED (4) +#define DST_ADDR_NOT_MAPPED (5) +#define COUNT_ERROR (6) +#define INVALID_SECTOR (7) +#define SECTOR_NOT_BLANK (8) +#define SECTOR_NOT_PREPARED_FOR_WRITE_OPERATION (9) +#define COMPARE_ERROR (10) +#define BUSY (11) + +/* IAP start location on flash */ +#define IAP_LOCATION (0x7FFFFFF1) + +/* PLL */ +#define PLLCON_PLLE (0x01) ///< PLL Enable +#define PLLCON_PLLD (0x00) ///< PLL Disable +#define PLLCON_PLLC (0x03) ///< PLL Connect +#define PLLSTAT_PLOCK (0x0400) // #include #include "lpc2387.h" -#include "clock.h" /* ------------------------------------------------------------------------- */ /** @@ -82,9 +81,9 @@ enum rtc_alarm_mask { * @internal * During reboots only alarms are reset. */ -void _rtc_init(void); +void rtc_init(void); -void _rtc_reset(void); +void rtc_reset(void); /** * @brief Returns the time of compilation in seconds @@ -92,6 +91,12 @@ void _rtc_reset(void); */ time_t rtc_get_compile_time(void) __attribute__((noinline)); +/** + * @brief Sets the current time in broken down format directly from to RTC + * @param[in] localt Pointer to structure with time to set + */ +void rtc_set_localtime(struct tm* localt); + /** * @brief Returns the current clock time * @param[out] time optional return value @@ -132,7 +137,7 @@ void rtc_get_localtime(struct tm* localt); * * @see ::rtc_alarm_mask */ -void _rtc_set_alarm(struct tm* localt, enum rtc_alarm_mask mask); +void rtc_set_alarm(struct tm* localt, enum rtc_alarm_mask mask); /** * @brief Gets the current alarm setting diff --git a/cpu/lpc2387/include/lpc2387.h b/cpu/lpc2387/include/lpc2387.h index d70853a775..27bcb69b4b 100644 --- a/cpu/lpc2387/include/lpc2387.h +++ b/cpu/lpc2387/include/lpc2387.h @@ -9,8 +9,8 @@ #ifndef __LPC2387_H #define __LPC2387_H -#include "lpc23xx.h" -#include "bitarithm.h" +#include +#include #define F_CCO 288000000 #define CL_CPU_DIV 4 ///< CPU clock divider @@ -23,6 +23,8 @@ #define GPIO_INT 17 #define IRQP_GPIO 4 +#define _XTAL (72000) + /** * @name Timer Symbols * @{ diff --git a/cpu/lpc2387/linkerscript.x b/cpu/lpc2387/linkerscript.x index 7048298937..a0fc127b5e 100644 --- a/cpu/lpc2387/linkerscript.x +++ b/cpu/lpc2387/linkerscript.x @@ -28,6 +28,7 @@ and the mailinglist (subscription via web site) MEMORY { flash : ORIGIN = 0, LENGTH = 512K /* FLASH ROM */ + infomem : ORIGIN = 0x0007D000, LENGTH = 4K /* Last sector in FLASH ROM for config data */ ram_battery : ORIGIN = 0xE0084000, LENGTH = 2K /* Battery RAM */ ram : ORIGIN = 0x40000000, LENGTH = 64K /* LOCAL ON-CHIP STATIC RAM */ ram_usb : ORIGIN = 0x7FD00000, LENGTH = 16K /* USB RAM */ @@ -98,6 +99,13 @@ SECTIONS . = ALIGN(4); _etext = . ; /* define a global symbol _etext just after the last code byte */ + .config : + { + *(.configmem) + . = ALIGN(256); + } >infomem + . = ALIGN(4); + /************************************************************************** * RAM **************************************************************************/ diff --git a/cpu/lpc2387/lpc2387-lpm.c b/cpu/lpc2387/lpc2387-lpm.c index d36829b1cf..ff83433e3c 100644 --- a/cpu/lpc2387/lpc2387-lpm.c +++ b/cpu/lpc2387/lpc2387-lpm.c @@ -55,22 +55,14 @@ static enum lpm_mode lpm; extern void init_clks1(void); extern void init_clks2(void); -#define DEBUG 0 -#if DEBUG -#include -#define PRINTF(...) printf(__VA_ARGS__) -#else -#define PRINTF(...) -#endif +#define ENABLE_DEBUG 0 +#include - -void -lpm_init(void) -{ +void lpm_init(void) { lpm = LPM_ON; } -#define LPM_DEBUG 0 +#define LPM_DEBUG 1 void lpm_begin_awake(void) { if (lpm >= LPM_SLEEP ) { // wake up from deep sleep @@ -96,7 +88,7 @@ void lpm_awake(void) { // Debug tests #if LPM_DEBUG usec = RTC_CTC-usec; - printf("Wakeup in %lu usecs\n",usec * 31); + DEBUG("Wakeup in %lu usecs\n",usec * 31); #endif } lpm = LPM_ON; @@ -118,8 +110,8 @@ enum lpm_mode lpm_set(enum lpm_mode target) { lpm = target; - #if DEBUG - PRINTF("# LPM power down %u -> %u", lpm, target); + #if iENABLE_DEBUG + DEBUG("# LPM power down %u -> %u", lpm, target); #endif PCON |= target_flags; // set target power mode diff --git a/cpu/lpc2387/lpc2387-rtc.c b/cpu/lpc2387/lpc2387-rtc.c index 7ab60e09c4..4642042a6b 100644 --- a/cpu/lpc2387/lpc2387-rtc.c +++ b/cpu/lpc2387/lpc2387-rtc.c @@ -45,20 +45,12 @@ and the mailinglist (subscription via web site) #include "lpc2387.h" #include "lpc2387-rtc.h" #include "lpm.h" -#include "clock.h" #define PREINT_RTC 0x000001C8 /* Prescaler value, integer portion, PCLK = 15Mhz */ #define PREFRAC_RTC 0x000061C0 /* Prescaler value, fraction portion, PCLK = 15Mhz */ -#define DEBUG 0 -#if DEBUG -#include -#define PRINTF(fmt, args...) printf("rtc: " fmt "\n", ##args) -#else -#define PRINTF(fmt, args...) -#endif - -extern void _clock_alarm(void); +#define ENABLE_DEBUG 0 +#include /** * @brief epoch time in hour granularity @@ -70,7 +62,7 @@ static volatile time_t epoch; * @brief Sets the current time in broken down format directly from to RTC * @param[in] localt Pointer to structure with time to set */ -static void +void rtc_set_localtime(struct tm* localt) { if( localt == NULL ) @@ -95,14 +87,14 @@ void rtc_set(time_t time) { } /*---------------------------------------------------------------------------*/ /// set clock to start of unix epoch -void _rtc_reset(void) +void rtc_reset(void) { rtc_set(0); epoch = 0; } /*---------------------------------------------------------------------------*/ void -_rtc_set_alarm(struct tm* localt, enum rtc_alarm_mask mask) +rtc_set_alarm(struct tm* localt, enum rtc_alarm_mask mask) { if( localt != NULL ) { RTC_ALSEC = localt->tm_sec; @@ -114,7 +106,7 @@ _rtc_set_alarm(struct tm* localt, enum rtc_alarm_mask mask) RTC_ALMON = localt->tm_mon + 1; RTC_ALYEAR = localt->tm_year; RTC_AMR = ~mask; // set wich alarm fields to check - PRINTF("alarm set %2lu.%2lu.%4lu %2lu:%2lu:%2lu", + DEBUG("alarm set %2lu.%2lu.%4lu %2lu:%2lu:%2lu\n", RTC_ALDOM, RTC_ALMON, RTC_ALYEAR, RTC_ALHOUR, RTC_ALMIN, RTC_ALSEC); } else { RTC_AMR = 0xff; @@ -122,7 +114,7 @@ _rtc_set_alarm(struct tm* localt, enum rtc_alarm_mask mask) } /*---------------------------------------------------------------------------*/ enum rtc_alarm_mask -_rtc_get_alarm(struct tm* localt) +rtc_get_alarm(struct tm* localt) { if( localt != NULL ) { localt->tm_sec = RTC_ALSEC; @@ -153,9 +145,8 @@ void RTC_IRQHandler (void) } else if( RTC_ILR & ILR_RTCALF ) { RTC_ILR |= ILR_RTCALF; RTC_AMR = 0xff; // disable alarm irq - PRINTF("alarm"); + DEBUG("Ring\n"); lpm_end_awake(); - _clock_alarm(); } VICVectAddr = 0; // Acknowledge Interrupt @@ -172,7 +163,7 @@ void rtc_enable(void) epoch = now - (now % 3600); } /*---------------------------------------------------------------------------*/ -void _rtc_init(void) +void rtc_init(void) { PCONP |= BIT9; RTC_AMR = 0xff; // disable alarm irq @@ -186,10 +177,10 @@ void _rtc_init(void) /* initialize clock with valid unix compatible values * If RTC_YEAR contains an value larger unix time_t we must reset. */ if( RTC_YEAR > 2037 ) { - _rtc_reset(); + rtc_reset(); } - PRINTF("%2lu.%2lu.%4lu %2lu:%2lu:%2lu epoch %lu", + DEBUG("%2lu.%2lu.%4lu %2lu:%2lu:%2lu epoch %lu\n", RTC_DOM, RTC_MONTH, RTC_YEAR, RTC_HOUR, RTC_MIN, RTC_SEC, epoch); } @@ -245,7 +236,7 @@ rtc_get_localtime(struct tm* localt) } } /*---------------------------------------------------------------------------*/ -void _gettimeofday_r(struct _reent *r, struct timeval *ptimeval, struct timezone *ptimezone) +void gettimeofday_r(struct _reent *r, struct timeval *ptimeval, struct timezone *ptimezone) { r->_errno = 0; if( ptimeval != NULL ) { diff --git a/cpu/lpc2387/lpc23xx-iap.c b/cpu/lpc2387/lpc23xx-iap.c new file mode 100644 index 0000000000..febe5c8d27 --- /dev/null +++ b/cpu/lpc2387/lpc23xx-iap.c @@ -0,0 +1,92 @@ +#include + +uint8_t iap_get_sector(uint32_t addr) { + if ((addr >=0x00000000) && (addr <= 0x00000FFF)) { + return 0; + } + if ((addr >=0x00001000) && (addr <= 0x00001FFF)) { + return 1; + } + if ((addr >=0x00002000) && (addr <= 0x00002FFF)) { + return 2; + } + if ((addr >=0x00003000) && (addr <= 0x00003FFF)) { + return 3; + } + if ((addr >=0x00004000) && (addr <= 0x00004FFF)) { + return 4; + } + if ((addr >=0x00005000) && (addr <= 0x00005FFF)) { + return 5; + } + if ((addr >=0x00006000) && (addr <= 0x00006FFF)) { + return 6; + } + if ((addr >=0x00007000) && (addr <= 0x00007FFF)) { + return 7; + } + + if ((addr >=0x00008000) && (addr <= 0x0000FFFF)) { + return 8; + } + if ((addr >=0x00010000) && (addr <= 0x00017FFF)) { + return 9; + } + if ((addr >=0x00018000) && (addr <= 0x0001FFFF)) { + return 10; + } + if ((addr >=0x00020000) && (addr <= 0x00027FFF)) { + return 11; + } + if ((addr >=0x00028000) && (addr <= 0x0002FFFF)) { + return 12; + } + if ((addr >=0x00030000) && (addr <= 0x00037FFF)) { + return 13; + } + if ((addr >=0x00038000) && (addr <= 0x0003FFFF)) { + return 14; + } + if ((addr >=0x00040000) && (addr <= 0x00047FFF)) { + return 15; + } + if ((addr >=0x00048000) && (addr <= 0x0004FFFF)) { + return 16; + } + if ((addr >=0x00050000) && (addr <= 0x00057FFF)) { + return 17; + } + if ((addr >=0x00058000) && (addr <= 0x0005FFFF)) { + return 18; + } + if ((addr >=0x00060000) && (addr <= 0x00067FFF)) { + return 19; + } + if ((addr >=0x00068000) && (addr <= 0x0006FFFF)) { + return 20; + } + if ((addr >=0x00070000) && (addr <= 0x00077FFF)) { + return 21; + } + if ((addr >=0x00078000) && (addr <= 0x00078FFF)) { + return 22; + } + if ((addr >=0x00079000) && (addr <= 0x00079FFF)) { + return 23; + } + if ((addr >=0x0007A000) && (addr <= 0x0007AFFF)) { + return 24; + } + if ((addr >=0x0007B000) && (addr <= 0x0007BFFF)) { + return 25; + } + if ((addr >=0x0007C000) && (addr <= 0x0007CFFF)) { + return 26; + } + if ((addr >=0x0007D000) && (addr <= 0x0007DFFF)) { + return 27; + } + + /* no valid address within flash */ + return 0xFF; +} diff --git a/cpu/msp430/startup.c b/cpu/msp430/startup.c index d4a3219135..8e04b9b97d 100644 --- a/cpu/msp430/startup.c +++ b/cpu/msp430/startup.c @@ -1,6 +1,6 @@ #include -#include "board.h" -#include "kernel_intern.h" +#include +#include extern void board_init(); @@ -10,7 +10,7 @@ __attribute__ ((constructor)) static void startup() { board_init(); - puts("FireKernel MSP430 hardware initialization complete.\n"); + puts("ukleos MSP430 hardware initialization complete.\n"); kernel_init(); } diff --git a/doc/doxygen/ukleos.doxyfile b/doc/doxygen/ukleos.doxyfile index bbf20122e9..490fd04f21 100644 --- a/doc/doxygen/ukleos.doxyfile +++ b/doc/doxygen/ukleos.doxyfile @@ -85,7 +85,7 @@ WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- -INPUT = ../../core ../../cpu ../../board ../../sys ../manual +INPUT = ../../core ../../cpu ../../board ../../sys ../manual ../../drivers INPUT_ENCODING = UTF-8 FILE_PATTERNS = *.doc *.c *.h RECURSIVE = YES @@ -125,7 +125,7 @@ HTML_OUTPUT = html HTML_FILE_EXTENSION = .html HTML_HEADER = src/ukleos-header.html HTML_FOOTER = src/ukleos-footer.html -HTML_STYLESHEET = src/ukleos.css +HTML_STYLESHEET = HTML_ALIGN_MEMBERS = YES HTML_DYNAMIC_SECTIONS = YES GENERATE_DOCSET = NO diff --git a/drivers/Jamfile b/drivers/Jamfile index e0223c05a1..9713df17fd 100644 --- a/drivers/Jamfile +++ b/drivers/Jamfile @@ -32,3 +32,4 @@ Module sht11 : sht11.c : hwtimer ; Module ltc4150 : ltc4150.c : board_ltc4150 ; SubInclude TOP drivers cc110x ; +SubInclude TOP drivers cc110x_ng ; diff --git a/drivers/cc110x/cc1100_phy.c b/drivers/cc110x/cc1100_phy.c index 90cc800ac8..441b7d6a28 100644 --- a/drivers/cc110x/cc1100_phy.c +++ b/drivers/cc110x/cc1100_phy.c @@ -60,6 +60,8 @@ and the mailinglist (subscription via web site) #include "msg.h" #include "debug.h" +#define PRIORITY_CC1100 PRIORITY_MAIN-1 + #define MSG_POLL 12346 #define FLAGS_IDENTIFICATION (0x01) ///< Bit mask for reading the identification out of the flags field @@ -94,10 +96,13 @@ static const pm_table_t handler_table; static const char *cc1100_event_handler_name = "cc1100_event_handler"; static mutex_t cc1100_mutex; volatile int cc1100_mutex_pid; +static swtimer_t cc1100_watch_dog; +static swtime_t cc1100_watch_dog_period = 0; + static uint16_t cc1100_event_handler_pid; static void cc1100_event_handler_function(void); -static swtimer_t cc1100_watch_dog; -static uint64_t cc1100_watch_dog_period = 0; + +static char event_handler_stack[KERNEL_CONF_STACKSIZE_MAIN]; /*---------------------------------------------------------------------------*/ // Sequence number buffer management data structures @@ -188,7 +193,7 @@ void cc1100_phy_init() mutex_init(&cc1100_mutex); // Allocate event numbers and start cc1100 event process - cc1100_event_handler_pid = thread_create(2500, PRIORITY_CC1100, CREATE_STACKTEST, + cc1100_event_handler_pid = thread_create(event_handler_stack, sizeof(event_handler_stack), PRIORITY_CC1100, CREATE_STACKTEST, cc1100_event_handler_function, cc1100_event_handler_name); // Active watchdog for the first time diff --git a/drivers/cc110x_ng/Jamfile b/drivers/cc110x_ng/Jamfile new file mode 100755 index 0000000000..55995d823d --- /dev/null +++ b/drivers/cc110x_ng/Jamfile @@ -0,0 +1,33 @@ +# ****************************************************************************** +# Copyright 2010, Freie Universitaet Berlin (FUB). All rights reserved. +# +# These sources were developed at the Freie Universitaet Berlin, Computer +# Systems and Telematics group (http://cst.mi.fu-berlin.de). +# ------------------------------------------------------------------------------ +# This file is part of µkleos. +# +# 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. +# +# FeuerWare 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 http://www.gnu.org/licenses/ . +# ------------------------------------------------------------------------------ +# For further information and questions please use the web site +# http://scatterweb.mi.fu-berlin.de +# and the mailinglist (subscription via web site) +# scatterweb@lists.spline.inf.fu-berlin.de +# ****************************************************************************** +# $Id: Jamfile 832 2009-03-13 16:45:41Z kaspar $ + +SubDir TOP drivers cc110x_ng ; + +HDRS += $(TOP)/drivers/cc110x_ng ; + +Module cc110x_ng : cc1100.c cc1100-rx.c cc1100-tx.c cc1100-defaultSettings.c cc1100_spi.c : board_cc1100 swtimer gpioint ; + diff --git a/drivers/cc110x_ng/cc1100-arch.h b/drivers/cc110x_ng/cc1100-arch.h new file mode 100644 index 0000000000..ef61dd61c9 --- /dev/null +++ b/drivers/cc110x_ng/cc1100-arch.h @@ -0,0 +1,50 @@ +/****************************************************************************** +Copyright 2008, Freie Universitaet Berlin (FUB). All rights reserved. + +These sources were developed at the Freie Universitaet Berlin, Computer Systems +and Telematics group (http://cst.mi.fu-berlin.de). +------------------------------------------------------------------------------- +This file is part of FeuerWare. + +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. + +FeuerWare 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 http://www.gnu.org/licenses/ . +-------------------------------------------------------------------------------- +For further information and questions please use the web site + http://scatterweb.mi.fu-berlin.de +and the mailinglist (subscription via web site) + scatterweb@lists.spline.inf.fu-berlin.de +*******************************************************************************/ + +/** + * @file + * @ingroup LPC2387 + * @brief CC1100 LPC2387 dependend functions + * + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @author Heiko Will + * @version $Revision: 1775 $ + * + * @note $Id: arch_cc1100.h 1775 2010-01-26 09:37:03Z hillebra $ + */ + +#include + +uint8_t cc1100_txrx(uint8_t c); + +void cc1100_gdo0_enable(void); +void cc1100_gdo0_disable(void); +void cc1100_gdo2_enable(void); +void cc1100_gdo2_disable(void); +void cc1100_init_interrupts(void); + +void cc1100_before_send(void); +void cc1100_after_send(void); diff --git a/drivers/cc110x_ng/cc1100-config.h b/drivers/cc110x_ng/cc1100-config.h new file mode 100644 index 0000000000..e7e039d882 --- /dev/null +++ b/drivers/cc110x_ng/cc1100-config.h @@ -0,0 +1,94 @@ +#ifndef CC1100_CONFIG_H +#define CC1100_CONFIG_H + +/** CC1100 register configuration */ +typedef struct { + uint8_t IOCFG2; + uint8_t IOCFG1; + uint8_t IOCFG0; + uint8_t FIFOTHR; + uint8_t SYNC1; + uint8_t SYNC0; + uint8_t PKTLEN; + uint8_t PKTCTRL1; + uint8_t PKTCTRL0; + uint8_t ADDR; + uint8_t CHANNR; + uint8_t FSCTRL1; + uint8_t FSCTRL0; + uint8_t FREQ2; + uint8_t FREQ1; + uint8_t FREQ0; + uint8_t MDMCFG4; + uint8_t MDMCFG3; + uint8_t MDMCFG2; + uint8_t MDMCFG1; + uint8_t MDMCFG0; + uint8_t DEVIATN; + uint8_t MCSM2; + uint8_t MCSM1; + uint8_t MCSM0; + uint8_t FOCCFG; + uint8_t BSCFG; + uint8_t AGCCTRL2; + uint8_t AGCCTRL1; + uint8_t AGCCTRL0; + uint8_t WOREVT1; + uint8_t WOREVT0; + uint8_t WORCTRL; + uint8_t FREND1; + uint8_t FREND0; + uint8_t FSCAL3; + uint8_t FSCAL2; + uint8_t FSCAL1; + uint8_t FSCAL0; +} cc1100_reg_t; + +/** CC1100 radio configuration */ +typedef struct { + cc1100_reg_t reg_cfg; ///< CC1100 register configuration + uint8_t pa_power; ///< Output power setting +} cc1100_cfg_t; + +/** + * @brief Radio Control Flags + */ +typedef struct +{ + uint32_t TOF; ///< Time of flight of the last packet and last ACK + uint32_t TCP; ///< Time to compute packet + unsigned RPS : 16; ///< Raw packets sent to transmit last packet + unsigned RTC : 8; ///< Retransmission count of last send packet + unsigned RSSI : 8; ///< The RSSI value of last received packet + unsigned RSSI_SEND : 8; ///< The RSSI value of the last send unicast packet of this node + unsigned LQI : 8; ///< The LQI value of the last received packet + unsigned LL_ACK : 1; ///< Is set if Link-Level ACK is received, otherwise 0 (reset on new burst) + unsigned CAA : 1; ///< The status of the air (1 = air free, 0 = air not free) + unsigned CRC : 1; ///< The CRC status of last received packet (1 = OK, 0 = not OK) + unsigned SEQ : 1; ///< Sequence number (toggles between 0 and 1) + unsigned MAN_WOR : 1; ///< Manual WOR set (for randomized WOR times => no synch) + unsigned KT_RES_ERR : 1; ///< A hwtimer resource error has occurred (no free timers available) + unsigned TX : 1; ///< State machine TX lock, only ACKs will be received + unsigned WOR_RST : 1; ///< Reset CC1100 real time clock (WOR) on next WOR strobe +} cc1100_flags; + +/** + * @brief Statistic interface for debugging + */ +typedef struct cc1100_statistic { + uint32_t packets_in; + uint32_t packets_in_crc_fail; + uint32_t packets_in_while_tx; + uint32_t packets_in_dups; + uint32_t packets_in_up; + uint32_t packets_out; + uint32_t packets_out_acked; + uint32_t packets_out_broadcast; + uint32_t raw_packets_out; + uint32_t raw_packets_out_acked; + uint32_t acks_send; + uint32_t rx_buffer_max; + uint32_t watch_dog_resets; +} cc1100_statistic_t; + +#endif diff --git a/drivers/cc110x_ng/cc1100-defaultSettings.c b/drivers/cc110x_ng/cc1100-defaultSettings.c new file mode 100644 index 0000000000..6eb9ae2327 --- /dev/null +++ b/drivers/cc110x_ng/cc1100-defaultSettings.c @@ -0,0 +1,141 @@ +/****************************************************************************** +Copyright 2008, Freie Universitaet Berlin (FUB). All rights reserved. + +These sources were developed at the Freie Universitaet Berlin, Computer Systems +and Telematics group (http://cst.mi.fu-berlin.de). +------------------------------------------------------------------------------- +This file is part of FeuerWare. + +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. + +FeuerWare 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 http://www.gnu.org/licenses/ . +-------------------------------------------------------------------------------- +For further information and questions please use the web site + http://scatterweb.mi.fu-berlin.de +and the mailinglist (subscription via web site) + scatterweb@lists.spline.inf.fu-berlin.de +*******************************************************************************/ + +/** + * @ingroup dev_cc110x + * @{ + */ + +/** + * @file + * @brief TI Chipcon CC110x default settings + * + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @author Thomas Hillebrandt + * @author Heiko Will + * @version $Revision: 2058 $ + * + * @note $Id: cc1100-defaultSettings.c 2058 2010-03-31 08:59:31Z hillebra $ + */ + +#include + +/** + * Usable, non overlapping channels and corresponding frequencies + * for use with CC1100. CHANNR is the register for selecting a channel. + * + * channel number | CHANNR | frequency [MHz] + * ----------------------------------------- + * 0 | 0 | 869.525 + * 1 | 10 | 871.61 + * 2 | 20 | 873.58 ~ seems to be bad (hang-ups with this channel) + * 3 | 30 | 875.61 + * 4 | 40 | 877.58 + * 5 | 50 | 879.61 + * 6 | 60 | 881.58 + * 7 | 70 | 883.61 + * 8 | 80 | 885.58 + * 9 | 90 | 887.61 + * 10 | 100 | 889.58 + * 11 | 110 | 891.57 + * 12 | 120 | 893.58 + * 13 | 130 | 895.61 + * 14 | 140 | 897.58 + * 15 | 150 | 899.57 + * 16 | 160 | 901.57 + * 17 | 170 | 903.61 + * 18 | 180 | 905.57 + * 19 | 190 | 907.57 + * 20 | 200 | 909.57 + * 21 | 210 | 911.57 + * 22 | 220 | 913.57 + * 23 | 230 | 915.61 + * 24 | 240 | 917.61 + */ + +// 400 kbps, MSK, X-tal: 26 MHz (Chip Revision F) +char cc1100_conf[] = { + 0x06, // IOCFG2 + 0x2E, // IOCFG1 + 0x0E, // IOCFG0 + 0x0F, // FIFOTHR + 0x9B, // SYNC1 + 0xAD, // SYNC0 + 0x3D, // PKTLEN (maximum value of packet length byte = 61) + 0x06, // PKTCTRL1 + 0x45, // PKTCTRL0 (variable packet length) + 0xFF, // ADDR + CC1100_DEFAULT_CHANNR*10, // CHANNR + 0x0B, // FSCTRL1 + 0x00, // FSCTRL0 + 0x21, // FREQ2 + 0x71, // FREQ1 + 0x7A, // FREQ0 + 0x2D, // MDMCFG4 + 0xF8, // MDMCFG3 + 0x73, // MDMCFG2 + 0x42, // MDMCFG1 + 0xF8, // MDMCFG0 + 0x00, // DEVIATN + 0x07, // MCSM2 + 0x03, // MCSM1 + 0x18, // MCSM0 + 0x1D, // FOCCFG + 0x1C, // BSCFG + 0xC0, // AGCCTRL2 + 0x49, // AGCCTRL1, (old value was 0x49 -> made carrier sense less sensitive!) + // 0x47 - 7 dB above MAGN_TARGET setting + 0xB2, // AGCCTRL0 + 0x87, // WOREVT1 + 0x6B, // WOREVT0 + 0xF8, // WORCTRL + 0xB6, // FREND1 + 0x10, // FREND0 + 0xEA, // FSCAL3 + 0x2A, // FSCAL2 + 0x00, // FSCAL1 + 0x1F, // FSCAL0 + 0x00 // padding to 4 bytes +}; + +uint8_t pa_table_index = PATABLE; ///< Current PATABLE Index +uint8_t pa_table[] = { ///< PATABLE with available output powers + 0x00, ///< -52 dBm + 0x03, ///< -30 dBm + 0x0D, ///< -20 dBm + 0x1C, ///< -15 dBm + 0x34, ///< -10 dBm + 0x57, ///< - 5 dBm + 0x3F, ///< - 1 dBm + 0x8E, ///< 0 dBm + 0x85, ///< + 5 dBm + 0xCC, ///< + 7 dBm + 0xC6, ///< + 9 dBm + 0xC3 ///< +10 dBm +}; // If PATABLE is changed in size, adjust MAX_OUTPUT_POWER definition in CC1100 interface! + + +/** @} */ diff --git a/drivers/cc110x_ng/cc1100-defaultSettings.h b/drivers/cc110x_ng/cc1100-defaultSettings.h new file mode 100644 index 0000000000..d3c92d4a09 --- /dev/null +++ b/drivers/cc110x_ng/cc1100-defaultSettings.h @@ -0,0 +1,110 @@ +/****************************************************************************** +Copyright 2008, Freie Universitaet Berlin (FUB). All rights reserved. + +These sources were developed at the Freie Universitaet Berlin, Computer Systems +and Telematics group (http://cst.mi.fu-berlin.de). +------------------------------------------------------------------------------- +This file is part of FeuerWare. + +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. + +FeuerWare 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 http://www.gnu.org/licenses/ . +-------------------------------------------------------------------------------- +For further information and questions please use the web site + http://scatterweb.mi.fu-berlin.de +and the mailinglist (subscription via web site) + scatterweb@lists.spline.inf.fu-berlin.de +*******************************************************************************/ + +#ifndef CC1100_DEFAULTSETTINGS_H +#define CC1100_DEFAULTSETTINGS_H + +/** + * @ingroup dev_cc110x + * @{ + */ + +/** + * @file + * @brief TI Chipcon CC110x default settings + * + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @author Thomas Hillebrandt + * @author Heiko Will + * @version $Revision: 2139 $ + * + * @note $Id: cc1100-defaultSettings.h 2139 2010-05-26 08:04:04Z hillebra $ + */ + +#include + +// returns hwtimer ticks per us +#define RTIMER_TICKS(us) HWTIMER_TICKS(us) + +#define TIMER_TICK_USEC_RES (122) + +// Default PA table index (output power) +#define PATABLE (11) + +// Watchdog cycle time in seconds, set 0 to disable watchdog +#define CC1100_WATCHDOG_PERIOD (5) + +// Number of transmission retries for unicast packets (constant RX mode) +#define TRANSMISSION_RETRIES_CRX_UC (5) + +// Number of transmission retries for unicast packets (WOR mode) +#define TRANSMISSION_RETRIES_WOR_UC (1) + +// Number of transmission retries for broadcast packets (constant RX mode) +#define TRANSMISSION_RETRIES_CRX_BC (0) + +// Number of transmission retries for broadcast packets (WOR mode) +#define TRANSMISSION_RETRIES_WOR_BC (0) + +// Time before chip goes back to RX (= stays in PWD after incoming packet) +#define WOR_TIMEOUT_1 (3200) // ~ 32 milliseconds + +// Time before chip goes back to WOR (= stays in RX after elapsed WOR_TIMEOUT_1) +#define WOR_TIMEOUT_2 (800) // ~ 8 milliseconds + +// XOSC startup + FS calibration (300 + 809 us ~ 1.38 ms) +#define FS_CAL_TIME RTIMER_TICKS(12 * TIMER_TICK_USEC_RES) + +// Manual FS calibration (721 us) +#define MANUAL_FS_CAL_TIME RTIMER_TICKS(7 * TIMER_TICK_USEC_RES) + +// Reset wait time (in reset procedure) +#define RESET_WAIT_TIME RTIMER_TICKS(4 * TIMER_TICK_USEC_RES) + +// Time chip needs to go to RX +#define IDLE_TO_RX_TIME RTIMER_TICKS(1 * TIMER_TICK_USEC_RES) + +// Time chip needs to go to RX and CS signal is ready +#define CS_READY_TIME RTIMER_TICKS(3 * TIMER_TICK_USEC_RES) + +// Default RX interval for WOR in milliseconds +#define T_RX_INTERVAL (542) + +// Time of packet interval in microseconds (at 400 kbps) +#define T_PACKET_INTERVAL (3800) + +// The size of the configuration array for CC1100 in bytes +#define CC1100_CONF_SIZE (39) + +// The default channel number (0-24) for CC1100 +#define CC1100_DEFAULT_CHANNR (0) + +// Burst retry to TX switch time (measured ~ 230 us) +#define BURST_RETRY_TX_SWITCH_TIME (23) + + +/** @} */ +#endif diff --git a/drivers/cc110x_ng/cc1100-internal.h b/drivers/cc110x_ng/cc1100-internal.h new file mode 100644 index 0000000000..bf7309db9f --- /dev/null +++ b/drivers/cc110x_ng/cc1100-internal.h @@ -0,0 +1,218 @@ +/****************************************************************************** +Copyright 2008, Freie Universitaet Berlin (FUB). All rights reserved. + +These sources were developed at the Freie Universitaet Berlin, Computer Systems +and Telematics group (http://cst.mi.fu-berlin.de). +------------------------------------------------------------------------------- +This file is part of FeuerWare. + +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. + +FeuerWare 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 http://www.gnu.org/licenses/ . +-------------------------------------------------------------------------------- +For further information and questions please use the web site + http://scatterweb.mi.fu-berlin.de +and the mailinglist (subscription via web site) + scatterweb@lists.spline.inf.fu-berlin.de +*******************************************************************************/ + +#ifndef CC1100_INTERNAL_H +#define CC1100_INTERNAL_H + +/** + * @ingroup dev_cc110x + * @{ + */ + +/** + * @file + * @internal + * @brief TI Chipcon CC110x internal hardware constants + * + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @author Thomas Hillebrandt + * @author Heiko Will + * @version $Revision: 1231 $ + * + * @note $Id: cc1100-internal.h 1231 2009-08-20 08:31:32Z baar $ + */ + +#define FIXED_PKTLEN (0x00) ///< Fixed length packets, length configured in PKTLEN register. +#define VARIABLE_PKTLEN (0x01) ///< Variable length packets, packet length configured by the first + ///< byte after synch word. + +/** + * @name Bitmasks for reading out status register values + * @{ + */ + +/** + * @brief Bitmask (=10000000) for reading CRC_OK. + * + * If CRC_OK == 1: CRC for received data OK (or CRC disabled). + * If CRC_OK == 0: CRC error in received data. + */ +#define CRC_OK (0x80) +/** + * @brief Bitmask (=01111111) for reading LQI_EST. + * + * The Link Quality Indicator estimates how easily a received signal can be demodulated. + */ +#define LQI_EST (0x7F) +#define I_RSSI (0x00) ///< Index 0 contains RSSI information (from optionally appended packet status bytes). +#define I_LQI (0x01) ///< Index 1 contains LQI & CRC_OK information (from optionally appended packet status bytes). +#define MARC_STATE (0x1F) ///< Bitmask (=00011111) for reading MARC_STATE in MARCSTATE status register. +#define CS (0x40) ///< Bitmask (=01000000) for reading CS (Carrier Sense) in PKTSTATUS status register. +#define PQT_REACHED (0x20) ///< Bitmask (=00100000) for reading PQT_REACHED (Preamble Quality reached) in PKTSTATUS status register. +#define CCA (0x10) ///< Bitmask (=00010000) for reading CCA (clear channel assessment) in PKTSTATUS status register. +#define SFD (0x08) ///< Bitmask (=00001000) for reading SFD (Sync word found) in PKTSTATUS status register. +#define GDO2 (0x04) ///< Bitmask (=00000100) for reading GDO2 (current value on GDO2 pin) in PKTSTATUS status register. +#define GDO1 (0x02) ///< Bitmask (=00000010) for reading GDO1 (current value on GDO1 pin) in PKTSTATUS status register. +#define GDO0 (0x01) ///< Bitmask (=00000001) for reading GDO0 (current value on GDO0 pin) in PKTSTATUS status register. +#define TXFIFO_UNDERFLOW (0x80) ///< Bitmask (=10000000) for reading TXFIFO_UNDERFLOW in TXBYTES status register. +#define BYTES_IN_TXFIFO (0x7F) ///< Bitmask (=01111111) for reading NUM_TXBYTES in TXBYTES status register. +#define RXFIFO_OVERFLOW (0xBF) ///< Bitmask (=10000000) for reading RXFIFO_OVERFLOW in RXBYTES status register. +#define BYTES_IN_RXFIFO (0xFF) ///< Bitmask (=01111111) for reading NUM_RXBYTES in RXBYTES status register. +/** @} */ + +/** + * @name Bitmasks for reading out configuration register values + * @{ + */ +#define PKT_LENGTH_CONFIG (0x03) ///< Bitmask (=00000011) for reading LENGTH_CONFIG in PKTCTRL0 configuration register. +/** @} */ + +/** + * @name Definitions to support burst/single access + * @{ + */ +#define CC1100_WRITE_BURST (0x40) ///< Offset for burst write. +#define CC1100_READ_SINGLE (0x80) ///< Offset for read single byte. +#define CC1100_READ_BURST (0xC0) ///< Offset for read burst. +#define CC1100_NOBYTE (0x00) ///< No command (for reading). +/** @} */ + +/** + * @name Configuration Registers (47x) + * @{ + */ +#define CC1100_IOCFG2 (0x00) ///< GDO2 output pin configuration +#define CC1100_IOCFG1 (0x01) ///< GDO1 output pin configuration +#define CC1100_IOCFG0 (0x02) ///< GDO0 output pin configuration +#define CC1100_FIFOTHR (0x03) ///< RX FIFO and TX FIFO thresholds +#define CC1100_SYNC1 (0x04) ///< Sync word, high byte +#define CC1100_SYNC0 (0x05) ///< Sync word, low byte +#define CC1100_PKTLEN (0x06) ///< Packet length +#define CC1100_PKTCTRL1 (0x07) ///< Packet automation control +#define CC1100_PKTCTRL0 (0x08) ///< Packet automation control +#define CC1100_ADDR (0x09) ///< Device address +#define CC1100_CHANNR (0x0A) ///< Channel number +#define CC1100_FSCTRL1 (0x0B) ///< Frequency synthesizer control +#define CC1100_FSCTRL0 (0x0C) ///< Frequency synthesizer control +#define CC1100_FREQ2 (0x0D) ///< Frequency control word, high byte +#define CC1100_FREQ1 (0x0E) ///< Frequency control word, middle byte +#define CC1100_FREQ0 (0x0F) ///< Frequency control word, low byte +#define CC1100_MDMCFG4 (0x10) ///< Modem configuration +#define CC1100_MDMCFG3 (0x11) ///< Modem configuration +#define CC1100_MDMCFG2 (0x12) ///< Modem configuration +#define CC1100_MDMCFG1 (0x13) ///< Modem configuration +#define CC1100_MDMCFG0 (0x14) ///< Modem configuration +#define CC1100_DEVIATN (0x15) ///< Modem deviation setting +#define CC1100_MCSM2 (0x16) ///< Main Radio Control State Machine configuration +#define CC1100_MCSM1 (0x17) ///< Main Radio Control State Machine configuration +#define CC1100_MCSM0 (0x18) ///< Main Radio Control State Machine configuration +#define CC1100_FOCCFG (0x19) ///< Frequency Offset Compensation configuration +#define CC1100_BSCFG (0x1A) ///< Bit Synchronization configuration +#define CC1100_AGCCTRL2 (0x1B) ///< AGC control +#define CC1100_AGCCTRL1 (0x1C) ///< AGC control +#define CC1100_AGCCTRL0 (0x1D) ///< AGC control +#define CC1100_WOREVT1 (0x1E) ///< High byte Event 0 timeout +#define CC1100_WOREVT0 (0x1F) ///< Low byte Event 0 timeout +#define CC1100_WORCTRL (0x20) ///< Wake On Radio control +#define CC1100_FREND1 (0x21) ///< Front end RX configuration +#define CC1100_FREND0 (0x22) ///< Front end TX configuration +#define CC1100_FSCAL3 (0x23) ///< Frequency synthesizer calibration +#define CC1100_FSCAL2 (0x24) ///< Frequency synthesizer calibration +#define CC1100_FSCAL1 (0x25) ///< Frequency synthesizer calibration +#define CC1100_FSCAL0 (0x26) ///< Frequency synthesizer calibration +#define CC1100_RCCTRL1 (0x27) ///< RC oscillator configuration +#define CC1100_RCCTRL0 (0x28) ///< RC oscillator configuration +#define CC1100_FSTEST (0x29) ///< Frequency synthesizer calibration control +#define CC1100_PTEST (0x2A) ///< Production test +#define CC1100_AGCTEST (0x2B) ///< AGC test +#define CC1100_TEST2 (0x2C) ///< Various test settings +#define CC1100_TEST1 (0x2D) ///< Various test settings +#define CC1100_TEST0 (0x2E) ///< Various test settings +/** @} */ + +/** + * @name Strobe commands (14x) + * @{ + */ +#define CC1100_SRES (0x30) ///< Reset chip. +/** + * @brief Enable and calibrate frequency synthesizer (if MCSM0.FS_AUTOCAL=1). + * + * If in RX/TX: Go to a wait state where only the synthesizer is running (for quick RX / TX turnaround). + */ +#define CC1100_SFSTXON (0x31) +#define CC1100_SXOFF (0x32) ///< Turn off crystal oscillator. +#define CC1100_SCAL (0x33) ///< Calibrate frequency synthesizer and turn it off (enables quick start). +#define CC1100_SRX (0x34) ///< Enable RX. Perform calibration first if coming from IDLE and MCSM0.FS_AUTOCAL=1. +/** + * In IDLE state: Enable TX. Perform calibration first if MCSM0.FS_AUTOCAL=1. + * If in RX state and CCA is enabled: Only go to TX if channel is clear. + */ +#define CC1100_STX (0x35) +#define CC1100_SIDLE (0x36) ///< Exit RX / TX, turn off frequency synthesizer and exit WOR mode if applicable. +#define CC1100_SAFC (0x37) ///< Perform AFC adjustment of the frequency synthesizer +#define CC1100_SWOR (0x38) ///< Start automatic RX polling sequence (Wake-on-Radio) +#define CC1100_SPWD (0x39) ///< Enter power down mode when CSn goes high. +#define CC1100_SFRX (0x3A) ///< Flush the RX FIFO buffer (CC1100 should be in IDLE state). +#define CC1100_SFTX (0x3B) ///< Flush the TX FIFO buffer (CC1100 should be in IDLE state). +#define CC1100_SWORRST (0x3C) ///< Reset real time clock. +#define CC1100_SNOP (0x3D) ///< No operation. May be used to pad strobe commands to two bytes for simpler software. +/** @} */ + +/** + * @name Status registers (12x) + * @{ + */ +#define CC1100_PARTNUM (0x30) ///< Part number of CC1100. +#define CC1100_VERSION (0x31) ///< Current version number. +#define CC1100_FREQEST (0x32) ///< Frequency Offset Estimate. +#define CC1100_LQI (0x33) ///< Demodulator estimate for Link Quality. +#define CC1100_RSSI (0x34) ///< Received signal strength indication. +#define CC1100_MARCSTATE (0x35) ///< Control state machine state. +#define CC1100_WORTIME1 (0x36) ///< High byte of WOR timer. +#define CC1100_WORTIME0 (0x37) ///< Low byte of WOR timer. +#define CC1100_PKTSTATUS (0x38) ///< Current GDOx status and packet status. +#define CC1100_VCO_VC_DAC (0x39) ///< Current setting from PLL calibration module. +#define CC1100_TXBYTES (0x3A) ///< Underflow and number of bytes in the TX FIFO. +#define CC1100_RXBYTES (0x3B) ///< Overflow and number of bytes in the RX FIFO. +/** @} */ + +/** + * @name Multi byte registers + * @{ + */ +/** + * @brief Register for eight user selected output power settings. + * + * 3-bit FREND0.PA_POWER value selects the PATABLE entry to use. + */ +#define CC1100_PATABLE (0x3E) +#define CC1100_TXFIFO (0x3F) ///< TX FIFO: Write operations write to the TX FIFO (SB: +0x00; BURST: +0x40) +#define CC1100_RXFIFO (0x3F) ///< RX FIFO: Read operations read from the RX FIFO (SB: +0x80; BURST: +0xC0) + +/** @} */ + +#endif diff --git a/drivers/cc110x_ng/cc1100-rx.c b/drivers/cc110x_ng/cc1100-rx.c new file mode 100644 index 0000000000..de8f615575 --- /dev/null +++ b/drivers/cc110x_ng/cc1100-rx.c @@ -0,0 +1,153 @@ +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +static uint8_t receive_packet_variable(uint8_t *rxBuffer, uint8_t length); +static uint8_t receive_packet(uint8_t *rxBuffer, uint8_t length); + +rx_buffer_t cc1100_rx_buffer[RX_BUF_SIZE]; ///< RX buffer +volatile uint8_t rx_buffer_next; ///< Next packet in RX queue + +void cc1100_rx_handler(void) { + uint8_t res = 0; + + // Possible packet received, RX -> IDLE (0.1 us) + rflags.CAA = 0; + rflags.MAN_WOR = 0; + cc1100_statistic.packets_in++; + + res = receive_packet((uint8_t*)&(cc1100_rx_buffer[rx_buffer_next].packet), sizeof(cc1100_packet_t)); + if (res) { + // If we are sending a burst, don't accept packets. + // Only ACKs are processed (for stopping the burst). + // Same if state machine is in TX lock. + if (radio_state == RADIO_SEND_BURST || rflags.TX) + { + cc1100_statistic.packets_in_while_tx++; + return; + } + cc1100_rx_buffer[rx_buffer_next].rssi = rflags.RSSI; + cc1100_rx_buffer[rx_buffer_next].lqi = rflags.LQI; + + // Valid packet. After a wake-up, the radio should be in IDLE. + // So put CC1100 to RX for WOR_TIMEOUT (have to manually put + // the radio back to sleep/WOR). + //cc1100_spi_write_reg(CC1100_MCSM0, 0x08); // Turn off FS-Autocal + cc1100_spi_write_reg(CC1100_MCSM2, 0x07); // Configure RX_TIME (until end of packet) + cc1100_spi_strobe(CC1100_SRX); + hwtimer_wait(IDLE_TO_RX_TIME); + radio_state = RADIO_RX; + + /* notify transceiver thread if any */ + if (transceiver_pid) { + msg m; + m.type = (uint16_t) RCV_PKT_CC1100; + m.content.value = rx_buffer_next; + msg_send_int(&m, transceiver_pid); + } + + /* shift to next buffer element */ + if (++rx_buffer_next == RX_BUF_SIZE) { + rx_buffer_next = 0; + } + return; + } + else + { + // No ACK received so TOF is unpredictable + rflags.TOF = 0; + + // CRC false or RX buffer full -> clear RX FIFO in both cases + cc1100_spi_strobe(CC1100_SIDLE); // Switch to IDLE (should already be)... + cc1100_spi_strobe(CC1100_SFRX); // ...for flushing the RX FIFO + + // If packet interrupted this nodes send call, + // don't change anything after this point. + if (radio_state == RADIO_AIR_FREE_WAITING) + { + cc1100_spi_strobe(CC1100_SRX); + hwtimer_wait(IDLE_TO_RX_TIME); + return; + } + // If currently sending, exit here (don't go to RX/WOR) + if (radio_state == RADIO_SEND_BURST) + { + cc1100_statistic.packets_in_while_tx++; + return; + } + + // No valid packet, so go back to RX/WOR as soon as possible + cc1100_switch_to_rx(); + } +} + + +static uint8_t receive_packet_variable(uint8_t *rxBuffer, uint8_t length) { + uint8_t status[2]; + uint8_t packetLength = 0; + + /* Any bytes available in RX FIFO? */ + if ((cc1100_spi_read_status(CC1100_RXBYTES) & BYTES_IN_RXFIFO)) { + LED_GREEN_TOGGLE; + // Read length byte (first byte in RX FIFO) + packetLength = cc1100_spi_read_reg(CC1100_RXFIFO); + // Read data from RX FIFO and store in rxBuffer + if (packetLength <= length) + { + // Put length byte at first position in RX Buffer + rxBuffer[0] = packetLength; + + // Read the rest of the packet + cc1100_spi_readburst_reg(CC1100_RXFIFO, (char*)rxBuffer+1, packetLength); + + // Read the 2 appended status bytes (status[0] = RSSI, status[1] = LQI) + cc1100_spi_readburst_reg(CC1100_RXFIFO, (char*)status, 2); + + // Store RSSI value of packet + rflags.RSSI = status[I_RSSI]; + + // MSB of LQI is the CRC_OK bit + rflags.CRC = (status[I_LQI] & CRC_OK) >> 7; + if (!rflags.CRC) { + cc1100_statistic.packets_in_crc_fail++; + } + + // Bit 0-6 of LQI indicates the link quality (LQI) + rflags.LQI = status[I_LQI] & LQI_EST; + + return rflags.CRC; + } + /* too many bytes in FIFO */ + else { + // RX FIFO get automatically flushed if return value is false + return 0; + } + } + /* no bytes in RX FIFO */ + else { + LED_RED_TOGGLE; + // RX FIFO get automatically flushed if return value is false + return 0; + } +} + +static uint8_t receive_packet(uint8_t *rxBuffer, uint8_t length) { + uint8_t pkt_len_cfg = cc1100_spi_read_reg(CC1100_PKTCTRL0) & PKT_LENGTH_CONFIG; + if (pkt_len_cfg == VARIABLE_PKTLEN) + { + return receive_packet_variable(rxBuffer, length); + } + // Fixed packet length not supported. + // RX FIFO get automatically flushed if return value is false + return 0; +} + + diff --git a/drivers/cc110x_ng/cc1100-tx.c b/drivers/cc110x_ng/cc1100-tx.c new file mode 100644 index 0000000000..d8a79b37cb --- /dev/null +++ b/drivers/cc110x_ng/cc1100-tx.c @@ -0,0 +1,76 @@ +#include + +#include +#include +#include +#include +#include + +#include + +#include + +uint8_t cc1100_send(cc1100_packet_t *packet) { + volatile uint32_t abort_count; + uint8_t size; + /* TODO: burst sending */ + radio_state = RADIO_SEND_BURST; + rflags.LL_ACK = 0; + + /* + * Number of bytes to send is: + * length of phy payload (packet->length) + * + size of length field (1 byte) + */ + size = packet->length + 1; + + // The number of bytes to be transmitted must be smaller + // or equal to PACKET_LENGTH (62 bytes). So the receiver + // can put the whole packet in its RX-FIFO (with appended + // packet status bytes). + if (size > PACKET_LENGTH) { + return 0; + } + + packet->phy_src = cc1100_get_address(); + + // Disables RX interrupt etc. + cc1100_before_send(); + + // But CC1100 in IDLE mode to flush the FIFO + cc1100_spi_strobe(CC1100_SIDLE); + // Flush TX FIFO to be sure it is empty + cc1100_spi_strobe(CC1100_SFTX); + // Write packet into TX FIFO + cc1100_spi_writeburst_reg(CC1100_TXFIFO, (char*) packet, size); + // Switch to TX mode + abort_count = 0; + unsigned int cpsr = disableIRQ(); + cc1100_spi_strobe(CC1100_STX); + // Wait for GDO2 to be set -> sync word transmitted + while (cc1100_get_gdo2() == 0) { + abort_count++; + if (abort_count > CC1100_SYNC_WORD_TX_TIME) { + // Abort waiting. CC1100 maybe in wrong mode + // e.g. sending preambles for always + puts("[CC1100 TX] fatal error\n"); + break; + } + } + restoreIRQ(cpsr); + // Wait for GDO2 to be cleared -> end of packet + while (cc1100_get_gdo2() != 0); + + // Experimental - TOF Measurement + cc1100_after_send(); + cc1100_statistic.raw_packets_out++; + + // Store number of transmission retries + rflags.TX = 0; + + // Go to mode after TX (CONST_RX -> RX, WOR -> WOR) + cc1100_switch_to_rx(); + + return true; +} + diff --git a/drivers/cc110x_ng/cc1100.c b/drivers/cc110x_ng/cc1100.c new file mode 100644 index 0000000000..55b7fd526d --- /dev/null +++ b/drivers/cc110x_ng/cc1100.c @@ -0,0 +1,302 @@ +#include +#include +#include +#include +#include +#include + +#include + +//#define ENABLE_DEBUG (1) +#include + +/* some externals */ +extern uint8_t pa_table[]; ///< PATABLE with available output powers +extern uint8_t pa_table_index; ///< Current PATABLE Index + +/* global variables */ + +cc1100_statistic_t cc1100_statistic; + +volatile cc1100_flags rflags; ///< Radio control flags +volatile uint8_t radio_state = RADIO_UNKNOWN; ///< Radio state + +static uint8_t radio_address; ///< Radio address +static uint8_t radio_channel; ///< Radio channel + +int transceiver_pid; ///< the transceiver thread pid + +/* internal function prototypes */ +static int rd_set_mode(int mode); +static void reset(void); +static void power_up_reset(void); +static void write_register(uint8_t r, uint8_t value); + +/*---------------------------------------------------------------------------*/ +// Radio Driver API +/*---------------------------------------------------------------------------*/ +void cc1100_init(int tpid) { + transceiver_pid = tpid; + DEBUG("Transceiver PID: %i\n", transceiver_pid); + + rx_buffer_next = 0; + + /* Initialize SPI */ + cc1100_spi_init(); + + /* Load driver & reset */ + power_up_reset(); + + /* Write configuration to configuration registers */ + cc1100_spi_writeburst_reg(0x00, cc1100_conf, CC1100_CONF_SIZE); + + /* Write PATABLE (power settings) */ + cc1100_spi_write_reg(CC1100_PATABLE, pa_table[pa_table_index]); + + /* Initialize Radio Flags */ + rflags.RSSI = 0x00; + rflags.LL_ACK = 0; + rflags.CAA = 0; + rflags.CRC = 0; + rflags.SEQ = 0; + rflags.MAN_WOR = 0; + rflags.KT_RES_ERR = 0; + rflags.TX = 0; + rflags.WOR_RST = 0; + + /* Set default channel number */ + cc1100_set_channel(CC1100_DEFAULT_CHANNR); + DEBUG("CC1100 initialized and set to channel %i\n", radio_channel); + + // Switch to desired mode (WOR or RX) + rd_set_mode(RADIO_MODE_ON); +} + +void cc1100_disable_interrupts(void) { + cc1100_gdo2_disable(); + cc1100_gdo0_disable(); +} + +void cc1100_gdo0_irq(void) { + // Air was not free -> Clear CCA flag + rflags.CAA = false; + // Disable carrier sense detection (GDO0 interrupt) + cc1100_gdo0_disable(); +} + +void cc1100_gdo2_irq(void) { + cc1100_rx_handler(); +} + +uint8_t cc1100_get_buffer_pos(void) { + return (rx_buffer_next-1); +} + +radio_address_t cc1100_get_address() { + return radio_address; +} + +radio_address_t cc1100_set_address(radio_address_t address) { + if ((address < MIN_UID) || (address > MAX_UID)) { + return 0; + } + + uint8_t id = (uint8_t) address; + if (radio_state != RADIO_UNKNOWN) { + write_register(CC1100_ADDR, id); + } + + radio_address = id; + return radio_address; +} + +void cc1100_set_monitor(uint8_t mode) { + if (mode) { + write_register(CC1100_PKTCTRL1, (0x04)); + } + else { + write_register(CC1100_PKTCTRL1, (0x06)); + } +} + +void cc1100_setup_rx_mode(void) { + // Stay in RX mode until end of packet + cc1100_spi_write_reg(CC1100_MCSM2, 0x07); + cc1100_switch_to_rx(); +} + +void cc1100_switch_to_rx(void) { + radio_state = RADIO_RX; + cc1100_spi_strobe(CC1100_SRX); +} + +void cc1100_wakeup_from_rx(void) { + if (radio_state != RADIO_RX) { + return; + } + DEBUG("CC1100 going to idle\n"); + cc1100_spi_strobe(CC1100_SIDLE); + radio_state = RADIO_IDLE; +} + +char* cc1100_get_marc_state(void) { + uint8_t state; + + // Save old radio state + uint8_t old_state = radio_state; + + // Read content of status register + state = cc1100_spi_read_status(CC1100_MARCSTATE) & MARC_STATE; + + // Make sure in IDLE state. + // Only goes to IDLE if state was RX/WOR + cc1100_wakeup_from_rx(); + + // Have to put radio back to WOR/RX if old radio state + // was WOR/RX, otherwise no action is necessary + if (old_state == RADIO_WOR || old_state == RADIO_RX) { + cc1100_switch_to_rx(); + } + + switch (state) + { + // Note: it is not possible to read back the SLEEP or XOFF state numbers + // because setting CSn low will make the chip enter the IDLE mode from the + // SLEEP (0) or XOFF (2) states. + case 1: return "IDLE"; + case 3: case 4: case 5: return "MANCAL"; + case 6: case 7: return "FS_WAKEUP"; + case 8: case 12: return "CALIBRATE"; + case 9: case 10: case 11: return "SETTLING"; + case 13: case 14: case 15: return "RX"; + case 16: return "TXRX_SETTLING"; + case 17: return "RXFIFO_OVERFLOW"; + case 18: return "FSTXON"; + case 19: case 20: return "TX"; + case 21: return "RXTX_SETTLING"; + case 22: return "TXFIFO_UNDERFLOW"; + default: return "UNKNOWN"; + } +} + +char* cc1100_state_to_text(uint8_t state) { + switch (state) + { + case RADIO_UNKNOWN: + return "Unknown"; + case RADIO_AIR_FREE_WAITING: + return "CS"; + case RADIO_WOR: + return "WOR"; + case RADIO_IDLE: + return "IDLE"; + case RADIO_SEND_BURST: + return "TX BURST"; + case RADIO_RX: + return "RX"; + case RADIO_SEND_ACK: + return "TX ACK"; + case RADIO_PWD: + return "PWD"; + default: + return "unknown"; + } +} + + +void cc1100_print_config(void) { + printf("Current radio state: %s\r\n", cc1100_state_to_text(radio_state)); + printf("Current MARC state: %s\r\n", cc1100_get_marc_state()); + printf("Current channel number: %u\r\n", radio_channel); +} + +void switch_to_pwd(void) { + cc1100_wakeup_from_rx(); + cc1100_spi_strobe(CC1100_SPWD); + radio_state = RADIO_PWD; +} + +/*---------------------------------------------------------------------------*/ +int16_t cc1100_set_channel(uint8_t channr) { + uint8_t state = cc1100_spi_read_status(CC1100_MARCSTATE) & MARC_STATE; + if ((state != 1) && (channr > MAX_CHANNR)) { + return 0; + } + write_register(CC1100_CHANNR, channr*10); + radio_channel = channr; + return radio_channel; +} + +int16_t cc1100_get_channel(void) { + return radio_channel; +} + + +/*---------------------------------------------------------------------------*/ +// CC1100 reset functionality +/*---------------------------------------------------------------------------*/ + +static void reset(void) { + cc1100_wakeup_from_rx(); + cc1100_spi_select(); + cc1100_spi_strobe(CC1100_SRES); + hwtimer_wait(RTIMER_TICKS(10)); +} + +static void power_up_reset(void) { + cc1100_spi_unselect(); + cc1100_spi_cs(); + cc1100_spi_unselect(); + hwtimer_wait(RESET_WAIT_TIME); + reset(); + radio_state = RADIO_IDLE; +} + +static void write_register(uint8_t r, uint8_t value) { + // Save old radio state + uint8_t old_state = radio_state; + + /* Wake up from WOR/RX (if in WOR/RX, else no effect) */ + cc1100_wakeup_from_rx(); + cc1100_spi_write_reg(r, value); + + // Have to put radio back to WOR/RX if old radio state + // was WOR/RX, otherwise no action is necessary + if ((old_state == RADIO_WOR) || (old_state == RADIO_RX)) { + cc1100_switch_to_rx(); + } +} + +static int rd_set_mode(int mode) { + int result; + + // Get current radio mode + if ((radio_state == RADIO_UNKNOWN) || (radio_state == RADIO_PWD)) { + result = RADIO_MODE_OFF; + } + else { + result = RADIO_MODE_ON; + } + + switch (mode) { + case RADIO_MODE_ON: + DEBUG("Enabling rx mode\n"); + cc1100_init_interrupts(); // Enable interrupts + cc1100_setup_rx_mode(); // Set chip to desired mode + break; + case RADIO_MODE_OFF: + cc1100_disable_interrupts(); // Disable interrupts + cc1100_switch_to_pwd(); // Set chip to power down mode + break; + case RADIO_MODE_GET: + // do nothing, just return current mode + default: + // do nothing + break; + } + + // Return previous mode + return result; +} + + diff --git a/drivers/cc110x_ng/cc1100_ng.h b/drivers/cc110x_ng/cc1100_ng.h new file mode 100644 index 0000000000..3431f2e7b0 --- /dev/null +++ b/drivers/cc110x_ng/cc1100_ng.h @@ -0,0 +1,122 @@ +#ifndef CC1100_H +#define CC1100_H + +#include +#include +#include +#include + +#define RX_BUF_SIZE (10) + +#define CC1100_MAX_DATA_LENGTH (58) + +#define CC1100_HEADER_LENGTH (3) ///< Header covers SRC, DST and FLAGS + +#define CC1100_BROADCAST_ADDRESS (0x00) ///< CC1100 broadcast address + +#define MAX_UID (0xFF) ///< Maximum UID of a node is 255 +#define MIN_UID (0x01) ///< Minimum UID of a node is 1 + +#define MIN_CHANNR (0) ///< Minimum channel number +#define MAX_CHANNR (24) ///< Maximum channel number + +#define MIN_OUTPUT_POWER (0) ///< Minimum output power value +#define MAX_OUTPUT_POWER (11) ///< Maximum output power value + +#define PACKET_LENGTH (0x3E) ///< Packet length = 62 Bytes. +#define CC1100_SYNC_WORD_TX_TIME (90000) // loop count (max. timeout ~ 15 ms) to wait for + // sync word to be transmitted (GDO2 from low to high) +/** + * @name Defines used as state values for state machine + * @{ + */ +#define RADIO_UNKNOWN (0) +#define RADIO_AIR_FREE_WAITING (1) +#define RADIO_WOR (2) +#define RADIO_IDLE (3) +#define RADIO_SEND_BURST (4) +#define RADIO_RX (5) +#define RADIO_SEND_ACK (6) +#define RADIO_PWD (7) + +/** @} */ + + +extern volatile cc1100_flags rflags; ///< Radio flags +extern char cc1100_conf[]; + +/** + * @brief CC1100 layer 0 protocol + * + *
+---------------------------------------------------
+|        |         |         |       |            |
+| Length | Address | PhySrc  | Flags |    Data    |
+|        |         |         |       |            |
+---------------------------------------------------
+  1 byte   1 byte    1 byte   1 byte   <= 58 bytes
+
+Flags:
+		Bit | Meaning
+		--------------------
+		7:4	| -
+		3:1 | Protocol
+		  0 | Identification
+
+Notes: +\li length & address are given by CC1100 +\li Identification is increased is used to scan duplicates. It must be increased + for each new packet and kept for packet retransmissions. + */ +typedef struct __attribute__ ((packed)) { + uint8_t length; ///< Length of the packet (without length byte) + uint8_t address; ///< Destination address + uint8_t phy_src; ///< Source address (physical source) + uint8_t flags; ///< Flags + uint8_t data[CC1100_MAX_DATA_LENGTH]; ///< Data (high layer protocol) +} cc1100_packet_t; + +typedef struct { + uint8_t rssi; + uint8_t lqi; + cc1100_packet_t packet; +} rx_buffer_t; + +enum radio_mode { + RADIO_MODE_GET = -1, ///< leave mode unchanged + RADIO_MODE_OFF = 0, ///< turn radio off + RADIO_MODE_ON = 1 ///< turn radio on +}; + +extern rx_buffer_t cc1100_rx_buffer[]; + +extern volatile uint8_t rx_buffer_next; ///< Next packet in RX queue + +extern volatile uint8_t radio_state; ///< Radio state +extern cc1100_statistic_t cc1100_statistic; + +int transceiver_pid; ///< the transceiver thread pid + +void cc1100_init(int transceiver_pid); + +void cc1100_rx_handler(void); + +uint8_t cc1100_send(cc1100_packet_t *pkt); + +uint8_t cc1100_get_buffer_pos(void); + +void cc1100_setup_rx_mode(void); +void cc1100_switch_to_rx(void); +void cc1100_wakeup_from_rx(void); +void cc1100_switch_to_pwd(void); + +void cc1100_disable_interrupts(void); +int16_t cc1100_set_channel(uint8_t channr); +int16_t cc1100_get_channel(void); + +radio_address_t cc1100_set_address(radio_address_t addr); +radio_address_t cc1100_get_address(void); +void cc1100_set_monitor(uint8_t mode); + +void cc1100_print_config(void); +#endif diff --git a/drivers/cc110x_ng/cc1100_spi.c b/drivers/cc110x_ng/cc1100_spi.c new file mode 100644 index 0000000000..0eaa70d572 --- /dev/null +++ b/drivers/cc110x_ng/cc1100_spi.c @@ -0,0 +1,128 @@ +/****************************************************************************** +Copyright 2010, Freie Universitaet Berlin (FUB). All rights reserved. + +These sources were developed at the Freie Universitaet Berlin, Computer Systems +and Telematics group (http://cst.mi.fu-berlin.de). +------------------------------------------------------------------------------- +This file is part of µkleos. + +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. + +FeuerWare 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 http://www.gnu.org/licenses/ . +-------------------------------------------------------------------------------- +For further information and questions please use the web site + http://scatterweb.mi.fu-berlin.de +and the mailinglist (subscription via web site) + scatterweb@lists.spline.inf.fu-berlin.de +*******************************************************************************/ + +/** + * @ingroup dev_cc110x + * @{ + */ + +/** + * @file + * @internal + * @brief TI Chipcon CC1100 SPI driver + * + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @author Thomas Hillebrandt + * @author Heiko Will + * @version $Revision: 1775 $ + * + * @note $Id: cc1100_spi.c 1775 2010-01-26 09:37:03Z hillebra $ + */ + +#include + +#include +#include +#include +#include + +#include + +/*---------------------------------------------------------------------------*/ +// CC1100 SPI access +/*---------------------------------------------------------------------------*/ + +#define NOBYTE 0xFF + +uint8_t cc1100_spi_writeburst_reg(uint8_t addr, char *src, uint8_t count) { + int i = 0; + unsigned int cpsr = disableIRQ(); + cc1100_spi_select(); + cc1100_txrx(addr | CC1100_WRITE_BURST); + while (i < count) { + cc1100_txrx(src[i]); + i++; + } + cc1100_spi_unselect(); + restoreIRQ(cpsr); + return count; +} + +void cc1100_spi_readburst_reg(uint8_t addr, char *buffer, uint8_t count) { + int i = 0; + unsigned int cpsr = disableIRQ(); + cc1100_spi_select(); + cc1100_txrx(addr | CC1100_READ_BURST); + while (i < count) { + buffer[i] = cc1100_txrx(NOBYTE); + i++; + } + cc1100_spi_unselect(); + restoreIRQ(cpsr); +} + +void cc1100_spi_write_reg(uint8_t addr, uint8_t value) { + unsigned int cpsr = disableIRQ(); + cc1100_spi_select(); + cc1100_txrx(addr); + cc1100_txrx(value); + cc1100_spi_unselect(); + restoreIRQ(cpsr); +} + +uint8_t cc1100_spi_read_reg(uint8_t addr) { + uint8_t result; + unsigned int cpsr = disableIRQ(); + cc1100_spi_select(); + cc1100_txrx(addr | CC1100_READ_SINGLE); + result = cc1100_txrx(NOBYTE); + cc1100_spi_unselect(); + restoreIRQ(cpsr); + return result; +} + +uint8_t cc1100_spi_read_status(uint8_t addr) { + uint8_t result; + unsigned int cpsr = disableIRQ(); + cc1100_spi_select(); + cc1100_txrx(addr | CC1100_READ_BURST); + result = cc1100_txrx(NOBYTE); + cc1100_spi_unselect(); + restoreIRQ(cpsr); + return result; +} + +uint8_t cc1100_spi_strobe(uint8_t c) { + uint8_t result; + unsigned int cpsr = disableIRQ(); + cc1100_spi_select(); + result = cc1100_txrx(c); + cc1100_spi_unselect(); + restoreIRQ(cpsr); + return result; +} + +/** @} */ diff --git a/drivers/cc110x_ng/cc1100_spi.h b/drivers/cc110x_ng/cc1100_spi.h new file mode 100644 index 0000000000..736f982187 --- /dev/null +++ b/drivers/cc110x_ng/cc1100_spi.h @@ -0,0 +1,64 @@ +/****************************************************************************** +Copyright 2008, Freie Universitaet Berlin (FUB). All rights reserved. + +These sources were developed at the Freie Universitaet Berlin, Computer Systems +and Telematics group (http://cst.mi.fu-berlin.de). +------------------------------------------------------------------------------- +This file is part of FeuerWare. + +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. + +FeuerWare 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 http://www.gnu.org/licenses/ . +-------------------------------------------------------------------------------- +For further information and questions please use the web site + http://scatterweb.mi.fu-berlin.de +and the mailinglist (subscription via web site) + scatterweb@lists.spline.inf.fu-berlin.de +*******************************************************************************/ +/** + * @ingroup dev_cc110x + * @{ + */ + +/** + * @file + * @internal + * @brief TI Chipcon CC1100 SPI driver + * + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @author Thomas Hillebrandt + * @author Heiko Will + * @version $Revision: 1775 $ + * + * @note $Id: cc1100_spi.h 1775 2010-01-26 09:37:03Z hillebra $ + */ + +#ifndef CC1100_SPI_H_ +#define CC1100_SPI_H_ + +int cc1100_get_gdo0(void); +int cc1100_get_gdo1(void); +int cc1100_get_gdo2(void); + +void cc1100_spi_init(void); +void cc1100_spi_cs(void); +void cc1100_spi_select(void); +void cc1100_spi_unselect(void); + +uint8_t cc1100_spi_writeburst_reg(uint8_t addr, char *buffer, uint8_t count); +void cc1100_spi_readburst_reg(uint8_t addr, char *buffer, uint8_t count); +void cc1100_spi_write_reg(uint8_t addr, uint8_t value); +uint8_t cc1100_spi_read_reg(uint8_t addr); +uint8_t cc1100_spi_read_status(uint8_t addr); +uint8_t cc1100_spi_strobe(uint8_t c); + +/** @} */ +#endif /* CC1100_SPI_H_ */ diff --git a/drivers/include/ltc4150.h b/drivers/include/ltc4150.h index e7fbad663f..88160c8913 100644 --- a/drivers/include/ltc4150.h +++ b/drivers/include/ltc4150.h @@ -8,7 +8,8 @@ void ltc4150_start(); void ltc4150_stop(); double ltc4150_get_current_mA(); -double ltc4150_get_total_mA(); +double ltc4150_get_total_mAh(); double ltc4150_get_avg_mA(); +int ltc4150_get_interval(); #endif /* __LTC4150_H */ diff --git a/drivers/include/sht11.h b/drivers/include/sht11.h index c649f402d8..227569f5e1 100644 --- a/drivers/include/sht11.h +++ b/drivers/include/sht11.h @@ -40,6 +40,7 @@ and the mailinglist (subscription via web site) * * @note $Id: sht11.h 667 2009-02-19 15:06:38Z baar $ */ +#include #define SHT11_NO_ACK (0) #define SHT11_ACK (1) @@ -50,17 +51,21 @@ and the mailinglist (subscription via web site) #define SHT11_MEASURE_HUMI (0x05) //000 0010 1 #define SHT11_RESET (0x1E) //000 1111 0 +/* time to wait after toggling the data line */ +#define SHT11_DATA_WAIT (HWTIMER_TICKS(1)) +/* time to wait after toggling the clock line */ +#define SHT11_CLK_WAIT (HWTIMER_TICKS(1)) + /* set measurement timeout to 1 second */ #define SHT11_MEASURE_TIMEOUT (1000) -/** sht11 measureable data */ +/** + * @brief sht11 measureable data + */ typedef struct { - /* temperature value */ - float temperature; - /* linear relative humidity */ - float relhum; - /* temperature compensated relative humidity */ - float relhum_temp; + float temperature; /**< temperature value */ + float relhum; /**< linear relative humidity */ + float relhum_temp; /**< temperature compensated relative humidity */ } sht11_val_t; /** @@ -79,9 +84,14 @@ void sht11_init(void); /** * @brief Read sensor * + * @param value The struct to be filled with measured values + * @param mode Specifies type of data to be read + * + * @return 1 on success, 0 otherwise + * * Example: - * \code struct sht11_val sht11; - * sht11_Read_Sensor(&sht11, HUMIDITY|TEMPERATURE); + * \code sht11_val sht11; + * sht11_read_sensor(&sht11, HUMIDITY|TEMPERATURE); * printf("%-6.2f °C %5.2f %% %5.2f %%\n", sht11.temperature, sht11.relhum, sht11.relhum_temp); \endcode */ uint8_t sht11_read_sensor(sht11_val_t *value, sht11_mode_t mode); diff --git a/drivers/ltc4150.c b/drivers/ltc4150.c index bcc166b70b..7c50553a85 100644 --- a/drivers/ltc4150.c +++ b/drivers/ltc4150.c @@ -62,7 +62,7 @@ double ltc4150_get_current_mA() { return 1000000000/(ltc4150_get_last_int_duration_us()*(_GFH * _R_SENSE)); } -double ltc4150_get_total_mA() { +double ltc4150_get_total_mAh() { return coulomb_to_mA(int_to_coulomb(int_count)); } @@ -70,6 +70,10 @@ double ltc4150_get_avg_mA() { return (int_to_coulomb(int_count)*1000000000)/HWTIMER_TICKS_TO_US(last_int_time - start_time); } +int ltc4150_get_interval() { + return HWTIMER_TICKS_TO_US(last_int_time - start_time); +} + unsigned long ltc4150_get_intcount() { return int_count; } diff --git a/drivers/sht11.c b/drivers/sht11.c index b0d77e03ab..d4bb6ec964 100644 --- a/drivers/sht11.c +++ b/drivers/sht11.c @@ -37,7 +37,6 @@ and the mailinglist (subscription via web site) * @note $Id: sht11.c 2396 2010-07-06 15:12:35Z ziegert $ */ -#include #include #include @@ -46,6 +45,11 @@ and the mailinglist (subscription via web site) #include #include +//#define ENABLE_DEBUG (1) +#include + +float sht11_temperature_offset; + /** * @brief Perform measurement * @@ -147,6 +151,7 @@ static uint8_t read_byte (uint8_t ack) value = value << 1; SHT11_SCK_HIGH; hwtimer_wait(SHT11_CLK_WAIT); + if (SHT11_DATA) { /* increase data by one when DATA is high */ value++; @@ -230,10 +235,10 @@ static uint8_t measure(uint8_t *p_value, uint8_t *p_checksum, uint8_t mode) uint8_t ack = 1; uint16_t i; - transmission_start(); + transmission_start(); error = write_byte(mode); - hwtimer_wait(HWTIMER_MSEC); + hwtimer_wait(HWTIMER_TICKS(1000)); /* wait untile sensor has finished measurement or timeout */ for (i = 0; (i < SHT11_MEASURE_TIMEOUT) && (!error); i++) { @@ -242,7 +247,7 @@ static uint8_t measure(uint8_t *p_value, uint8_t *p_checksum, uint8_t mode) if (!ack) { break; } - hwtimer_wait(HWTIMER_MSEC); + hwtimer_wait(HWTIMER_TICKS(1000)); } error += ack; @@ -257,9 +262,10 @@ static uint8_t measure(uint8_t *p_value, uint8_t *p_checksum, uint8_t mode) } /*---------------------------------------------------------------------------*/ void sht11_init(void) { + sht11_temperature_offset = 0; mutex_init(&sht11_mutex); SHT11_INIT; - hwtimer_wait(11 * HWTIMER_MSEC); + hwtimer_wait(11 * HWTIMER_TICKS(1000)); } /*---------------------------------------------------------------------------*/ uint8_t sht11_read_status(uint8_t *p_value, uint8_t *p_checksum) { @@ -303,7 +309,9 @@ uint8_t sht11_read_sensor(sht11_val_t *value, sht11_mode_t mode) { const float T2 = +0.00008; /* check for valid buffer */ - assert(value != NULL); + if (value == NULL) { + return 0; + } value->temperature = 0; value->relhum = 0; @@ -329,7 +337,7 @@ uint8_t sht11_read_sensor(sht11_val_t *value, sht11_mode_t mode) { } if (mode & TEMPERATURE) { - value->temperature = D1 + (D2 * ((float) temp_int)); + value->temperature = D1 + (D2 * ((float) temp_int)) + sht11_temperature_offset; } if (mode & HUMIDITY) { value->relhum = C1 + (C2 * ((float) humi_int)) + (C3 * ((float) humi_int) * ((float) humi_int)); diff --git a/projects/cc110x/main.c b/projects/cc110x/main.c index e515189602..4847b47cb3 100644 --- a/projects/cc110x/main.c +++ b/projects/cc110x/main.c @@ -58,7 +58,7 @@ int main(void) // radio stack cc1100_init(); cc1100_set_packet_handler(4, protocol_handler); - cc1100_set_channel(10); + cc1100_set_channel(0); // cc1100_set_output_power(5); printf("cc1100..[OK]\n"); @@ -72,6 +72,7 @@ int main(void) puts("."); int result = cc1100_send_csmaca(1, 4, 2, i, sizeof(i)); printf("%i\n", result); + hwtimer_wait(1000 * 1000); } #else cc1100_set_address(1); diff --git a/projects/default/Jamfile b/projects/default/Jamfile new file mode 100644 index 0000000000..2c8d376edc --- /dev/null +++ b/projects/default/Jamfile @@ -0,0 +1,11 @@ +# +# ukleos default project. Consists of a shell. +# +# Copyright (C) 2008, 2009 Kaspar Schleiser +# + +SubDir TOP projects default ; + +Module default_project : main.c : shell posix_io uart0 shell_commands ps rtc sht11 ltc4150 cc110x auto_init ; + +UseModule default_project ; diff --git a/projects/default/main.c b/projects/default/main.c new file mode 100644 index 0000000000..959c694616 --- /dev/null +++ b/projects/default/main.c @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2008, 2009, 2010 Kaspar Schleiser + */ + +#include +#include + +#include +#include +#include +#include +#include + +int shell_readc() { + char c = 0; + posix_read(uart0_handler_pid, &c, 1); + return c; +} + +void shell_putchar(int c) { + putchar(c); +} + +int main(void) { + posix_open(uart0_handler_pid, 0); + ltc4150_start(); + + puts("Welcome to ukleos!"); + + shell_t shell; + shell_init(&shell, NULL, shell_readc, shell_putchar); + + shell_run(&shell); + + return 0; +} + + diff --git a/projects/laser/Jamfile b/projects/laser/Jamfile new file mode 100644 index 0000000000..562d4305a7 --- /dev/null +++ b/projects/laser/Jamfile @@ -0,0 +1,5 @@ +SubDir TOP projects laser ; + +Module laser : main.c : sht11 swtimer auto_init ; + +UseModule laser ; diff --git a/projects/laser/main.c b/projects/laser/main.c new file mode 100644 index 0000000000..902ffc3088 --- /dev/null +++ b/projects/laser/main.c @@ -0,0 +1,30 @@ +#include +#include +#include +#include +#include + +int main(void) +{ + sht11_val_t sht11_val; + uint8_t success = 0; + + puts(""); + puts("LaSeR: Longterm Sensor Reader initialized."); + puts("Printing \"temperature in °C;relative humidity;temperature compensated relative humidity\"."); + puts(""); + + ltc4150_start(); + + while (1) { + success = sht11_read_sensor(&sht11_val, HUMIDITY|TEMPERATURE); + if (!success) { + printf("error;error;error\n"); + } + else { + printf("%.2f;%.2f;%.2f\n", sht11_val.temperature, sht11_val.relhum, sht11_val.relhum_temp); + } + LED_RED_TOGGLE; + swtimer_usleep(60 * 1000*1000); + } +} diff --git a/projects/pingpong/Jamfile b/projects/pingpong/Jamfile index e2ed342b57..2de8f82530 100644 --- a/projects/pingpong/Jamfile +++ b/projects/pingpong/Jamfile @@ -1,6 +1,4 @@ SubDir TOP projects pingpong ; -# LOCATE_TARGET = $(SEARCH_SOURCE)/bin ; -Library pingpong : main.c ; - -LinkLibraries $(BOARD).elf : pingpong ; +Module pingpong : main.c ; +UseModule pingpong ; diff --git a/projects/pingpong/main.c b/projects/pingpong/main.c index daf898b88d..2c9f214571 100644 --- a/projects/pingpong/main.c +++ b/projects/pingpong/main.c @@ -15,13 +15,15 @@ void second_thread(void) { } } +char second_thread_stack[KERNEL_CONF_STACKSIZE_MAIN]; + int main(void) { printf("Hello world!\n"); msg m; - int pid = thread_create(KERNEL_CONF_STACKSIZE_MAIN, PRIORITY_MAIN-1, CREATE_WOUT_YIELD | CREATE_STACKTEST, second_thread, "pong"); + int pid = thread_create(second_thread_stack, sizeof(second_thread_stack), PRIORITY_MAIN-1, CREATE_WOUT_YIELD | CREATE_STACKTEST, second_thread, "pong"); m.content.value = 1; diff --git a/projects/pingpong_sync/main.c b/projects/pingpong_sync/main.c index 739ec3acf7..8e1fd4d7d4 100644 --- a/projects/pingpong_sync/main.c +++ b/projects/pingpong_sync/main.c @@ -15,13 +15,15 @@ void second_thread(void) { } } +char second_thread_stack[8192]; + int main(void) { printf("Hello world!\n"); msg m; - int pid = thread_create(8192, PRIORITY_MAIN-1, CREATE_WOUT_YIELD | CREATE_STACKTEST, second_thread, "pong"); + int pid = thread_create(second_thread_stack, sizeof(second_thread_stack), PRIORITY_MAIN-1, CREATE_WOUT_YIELD | CREATE_STACKTEST, second_thread, "pong"); m.content.value = 1; diff --git a/projects/skel/tests/hello-world b/projects/skel/tests/hello-world index 6f4a6ca811..acde8265fe 100755 --- a/projects/skel/tests/hello-world +++ b/projects/skel/tests/hello-world @@ -2,7 +2,7 @@ set timeout 5 -spawn board/msba2/tools/bin/pseudoterm $env(PORT) +spawn pseudoterm $env(PORT) expect { "Hello World!" {} diff --git a/projects/test_cc110x_ng/Jamfile b/projects/test_cc110x_ng/Jamfile new file mode 100644 index 0000000000..28bf8b6f1a --- /dev/null +++ b/projects/test_cc110x_ng/Jamfile @@ -0,0 +1,5 @@ +SubDir TOP projects test_cc110x_ng ; + +Module test_cc110x_ng : main.c : cc110x_ng shell shell_commands transceiver ps rtc posix_io uart0 auto_init ; + +UseModule test_cc110x_ng ; diff --git a/projects/test_cc110x_ng/main.c b/projects/test_cc110x_ng/main.c new file mode 100644 index 0000000000..86c8b9f717 --- /dev/null +++ b/projects/test_cc110x_ng/main.c @@ -0,0 +1,129 @@ +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SHELL_STACK_SIZE (2048) +#define RADIO_STACK_SIZE (2048) + +#define SND_BUFFER_SIZE (100) +#define RCV_BUFFER_SIZE (64) + +#define SENDING_DELAY (1000) + +char shell_stack_buffer[SHELL_STACK_SIZE]; +char radio_stack_buffer[RADIO_STACK_SIZE]; + +uint8_t snd_buffer[SND_BUFFER_SIZE][CC1100_MAX_DATA_LENGTH]; + +msg msg_q[RCV_BUFFER_SIZE]; + +static msg mesg; +static transceiver_command_t tcmd; +static radio_packet_t p; + +void sender(char *count); +void print_buffer(char *unused); + +shell_t shell; +const shell_command_t sc[] = { + {"snd", "", sender}, + {"buffer", "", print_buffer}, + {NULL, NULL, NULL}}; + +void shell_runner(void) { + shell_init(&shell, sc, uart0_readc, uart0_putc); + posix_open(uart0_handler_pid, 0); + shell_run(&shell); +} + +void sender(char *count) { + unsigned int c, i; + + mesg.type = SND_PKT; + mesg.content.ptr = (char*) &tcmd; + + tcmd.transceivers = TRANSCEIVER_CC1100; + tcmd.data = &p; + + p.length = CC1100_MAX_DATA_LENGTH; + p.dst = 0; + + sscanf(count, "snd %u", &c); + for (i = 0; i < c; i++) { + puts("."); + p.data = snd_buffer[i % SND_BUFFER_SIZE]; + msg_send(&mesg, transceiver_pid, 1); + swtimer_usleep(SENDING_DELAY); + } +} + +void print_buffer(char *unused) { + uint8_t i; + extern radio_packet_t transceiver_buffer[]; + for (i = 0; i < TRANSCEIVER_BUFFER_SIZE; i++) { + printf("[%u] %u # %u # %u\n", i, transceiver_buffer[i].processing, transceiver_buffer[i].length, transceiver_buffer[i].data[i]); + } + extern rx_buffer_t cc1100_rx_buffer[]; + for (i = 0; i < TRANSCEIVER_BUFFER_SIZE; i++) { + printf("[%u] %u # %u \n", i, cc1100_rx_buffer[i].packet.length, cc1100_rx_buffer[i].packet.data[i]); + } +} + +void radio(void) { + msg m; + radio_packet_t *p; + uint8_t i; + + msg_init_queue(msg_q, RCV_BUFFER_SIZE); + + while (1) { + msg_receive(&m); + if (m.type == PKT_PENDING) { + p = (radio_packet_t*) m.content.ptr; + printf("Packet waiting, process %p...\n", p); + printf("\tLength:\t%u\n", p->length); + printf("\tSrc:\t%u\n", p->src); + printf("\tDst:\t%u\n", p->dst); + + for (i = 0; i < p->length; i++) { + printf("%02X ", p->data[i]); + } + p->processing--; + printf("\n"); + } + else if (m.type == ENOBUFFER) { + puts("Transceiver buffer full"); + } + else { + puts("Unknown packet received"); + } + } +} + +int main(void) { + int radio_pid; + uint8_t i; + for (i = 0; i < SND_BUFFER_SIZE; i++) { + memset(snd_buffer[i], i, CC1100_MAX_DATA_LENGTH); + } + thread_create(shell_stack_buffer, SHELL_STACK_SIZE, PRIORITY_MAIN-1, CREATE_STACKTEST, shell_runner, "shell"); + radio_pid = thread_create(radio_stack_buffer, RADIO_STACK_SIZE, PRIORITY_MAIN-2, CREATE_STACKTEST, radio, "radio"); + transceiver_init(TRANSCEIVER_CC1100); + transceiver_start(); + transceiver_register(TRANSCEIVER_CC1100, radio_pid); + + while (1) { +// LED_GREEN_TOGGLE; + hwtimer_wait(1000 * 1000); + } +} diff --git a/projects/test_cc110x_ng/tests/hello-world b/projects/test_cc110x_ng/tests/hello-world new file mode 100755 index 0000000000..acde8265fe --- /dev/null +++ b/projects/test_cc110x_ng/tests/hello-world @@ -0,0 +1,13 @@ +#!/usr/bin/expect + +set timeout 5 + +spawn pseudoterm $env(PORT) + +expect { + "Hello World!" {} + timeout { exit 1 } +} + +puts "\nTest successful!\n" + diff --git a/projects/test_hwtimer_basic/Jamfile b/projects/test_hwtimer_basic/Jamfile new file mode 100644 index 0000000000..e9f9af9ec8 --- /dev/null +++ b/projects/test_hwtimer_basic/Jamfile @@ -0,0 +1,5 @@ +SubDir TOP projects test_hwtimer ; + +Module test_hwtimer : main.c : hwtimer ; + +UseModule test_hwtimer ; diff --git a/projects/test_hwtimer_basic/main.c b/projects/test_hwtimer_basic/main.c new file mode 100644 index 0000000000..8e215d1056 --- /dev/null +++ b/projects/test_hwtimer_basic/main.c @@ -0,0 +1,29 @@ +#include +#include +#include +#include + +void callback(void* ptr) { + puts((char*)ptr); +} + +extern uint32_t hwtimer_now(); + +int main(void) +{ + puts("hwtimer test project."); + + puts("Initializing hwtimer..."); + hwtimer_init(); + + puts("Initializing hwtimer [OK]."); + + +// while (TA0R < 20000); + + hwtimer_set(20000LU, callback, (void*)"callback1"); + hwtimer_set(50000LU, callback, (void*)"callback2"); + hwtimer_set(30000LU, callback, (void*)"callback3"); + + puts("hwtimer set."); +} diff --git a/projects/test_hwtimer_basic/tests/test_hwtimer.py b/projects/test_hwtimer_basic/tests/test_hwtimer.py new file mode 100755 index 0000000000..261c511bb1 --- /dev/null +++ b/projects/test_hwtimer_basic/tests/test_hwtimer.py @@ -0,0 +1,17 @@ +#!/usr/bin/python + +import pexpect +import os +import subprocess + +child = pexpect.spawn ("board/msba2/tools/bin/pseudoterm %s" % os.environ["PORT"]) + +null = open('/dev/null', 'wb') +subprocess.call(['jam', 'reset'], stdout=null) + +child.expect ('OK\r\n'); +child.expect ('callback1\r\n'); +child.expect ('callback3\r\n'); +child.expect ('callback2\r\n'); +print("Test successful!") + diff --git a/projects/test_shell/test_shell.c b/projects/test_shell/test_shell.c index 7499c9b85b..6839969af9 100644 --- a/projects/test_shell/test_shell.c +++ b/projects/test_shell/test_shell.c @@ -29,9 +29,9 @@ void shell_putchar(int c) { } const shell_command_t shell_commands[] = { - {"start_test", print_teststart}, - {"end_test", print_testend}, - {NULL, NULL} + {"start_test", "", print_teststart}, + {"end_test", "", print_testend}, + {NULL, NULL, NULL} }; int main(void) { @@ -43,10 +43,8 @@ int main(void) { posix_open(uart0_handler_pid, 0); shell_t shell; - shell_init(&shell, shell_readc, shell_putchar); + shell_init(&shell, shell_commands, shell_readc, shell_putchar); - shell.command_list = shell_commands; - shell_run(&shell); return 0; diff --git a/projects/test_sleep/Jamfile b/projects/test_sleep/Jamfile index eee5c1fa22..83289e1e2e 100644 --- a/projects/test_sleep/Jamfile +++ b/projects/test_sleep/Jamfile @@ -1,5 +1,5 @@ SubDir TOP projects test_sleep ; -Module test_sleep : main.c : hwtimer ; +Module test_sleep : main.c : hwtimer ps ; UseModule test_sleep ; diff --git a/projects/test_sleep/main.c b/projects/test_sleep/main.c index b352b2f68d..b1945d89e0 100644 --- a/projects/test_sleep/main.c +++ b/projects/test_sleep/main.c @@ -2,6 +2,7 @@ #include #include #include +#include int integer = 0; int i = 0; @@ -11,21 +12,20 @@ void second_thread(void) { while(1) { integer++; printf("sleeper: running. integer=%i, i=%i.\n", integer, i); - if (integer % 100 == 0) { + if (integer % 1 == 0) { printf("Going to sleep.\n"); thread_sleep(); } } } +char second_thread_stack[KERNEL_CONF_STACKSIZE_DEFAULT*2]; int main(void) { hwtimer_init(); - printf("Hello world!\n"); - - int pid = thread_create(KERNEL_CONF_STACKSIZE_DEFAULT, PRIORITY_MAIN-1, CREATE_STACKTEST | CREATE_SLEEPING | CREATE_WOUT_YIELD, second_thread, "sleeper"); + int pid = thread_create(second_thread_stack, sizeof(second_thread_stack), PRIORITY_MAIN-1, CREATE_STACKTEST | CREATE_SLEEPING | CREATE_WOUT_YIELD, second_thread, "sleeper"); if (pid < 0) { puts("Error creating second_thread! Stopping test."); @@ -35,9 +35,14 @@ int main(void) while(1) { i++; printf(" main: running. integer=%i, i=%i.\n", integer, i); - if (i % 100 == 0) { + if (i % 1 == 0) { + thread_print_all(); printf("Waking up sleeper.\n"); thread_wakeup(pid); +<<<<<<< HEAD +======= + thread_print_all(); +>>>>>>> master thread_yield(); } } diff --git a/projects/test_suite/Jamfile b/projects/test_suite/Jamfile new file mode 100644 index 0000000000..dfb96deb7d --- /dev/null +++ b/projects/test_suite/Jamfile @@ -0,0 +1,12 @@ +# +# Copyright (C) 2008, 2009, 2010 FU Berlin +# +# Author: Kaspar Schleiser +# + +SubDir TOP projects test_suite ; + +Module test_suite : test_suite.c mutex_trylock_fail.c thread_sleep.c + : shell posix_io ps uart0 hwtimer ; + +UseModule test_suite ; diff --git a/projects/test_suite/mutex_trylock_fail.c b/projects/test_suite/mutex_trylock_fail.c new file mode 100644 index 0000000000..079d0d960c --- /dev/null +++ b/projects/test_suite/mutex_trylock_fail.c @@ -0,0 +1,30 @@ +#include +#include + +#include +#include +#include + +mutex_t mutex; + +static void second_thread(void) { + puts(" 2nd: trying to lock mutex..."); + mutex_trylock(&mutex); + puts(" 2nd: done."); +} + +static char second_stack[KERNEL_CONF_STACKSIZE_MAIN]; + +void mutex_trylock_fail(char* cmdline) +{ + puts("main: locking mutex..."); + mutex_lock(&mutex); + + puts("main: creating thread..."); + thread_create(second_stack, KERNEL_CONF_STACKSIZE_MAIN, PRIORITY_MAIN-1, CREATE_STACKTEST, second_thread, "nr2"); + + puts("main: thread created. Unlocking mutex..."); + mutex_unlock(&mutex, true); + + puts("main: mutex unlocked."); +} diff --git a/projects/test_suite/test_suite.c b/projects/test_suite/test_suite.c new file mode 100644 index 0000000000..40a019fc02 --- /dev/null +++ b/projects/test_suite/test_suite.c @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2008, 2009, 2010 Kaspar Schleiser + */ + +#include +#include +#include + +#include +#include +#include + +void print_teststart(char* str) { + printf("[TEST_START]\n"); +} + +void print_testend(char* str) { + printf("[TEST_END]\n"); +} + +int shell_readc() { + char c = 0; + posix_read(uart0_handler_pid, &c, 1); + return c; +} + +void shell_putchar(int c) { + putchar(c); +} + +void mutex_trylock_fail(char* cmdline); +void test_thread_sleep(char* line); + +const shell_command_t shell_commands[] = { + {"start_test", "", print_teststart}, + {"end_test", "", print_testend}, + {"mutex_trylock_fail", "", mutex_trylock_fail}, + {"thread_sleep", "", test_thread_sleep}, + {NULL, NULL, NULL} +}; + +int main(void) { + //printf("Moin. build on %s %s SVN-Revision: %s\n", kernel_builddate, kernel_buildtime, kernel_svnrevision); + printf("test_shell.\n"); + + board_uart0_init(); + + posix_open(uart0_handler_pid, 0); + + shell_t shell; + shell_init(&shell, shell_commands, shell_readc, shell_putchar); + + shell_run(&shell); + + return 0; +} + + diff --git a/projects/test_suite/tests/01-basic b/projects/test_suite/tests/01-basic new file mode 100755 index 0000000000..bdeb117734 --- /dev/null +++ b/projects/test_suite/tests/01-basic @@ -0,0 +1,30 @@ +#!/usr/bin/expect + +set timeout 5 + +spawn pseudoterm $env(PORT) + +expect { + ">$" {} + timeout { exit 1 } +} + +send "start_test\n" +expect { + "\[TEST_START\]" {} + timeout { exit 1 } +} + +expect { + ">$" {} + timeout { exit 1 } +} + +send "end_test\n" + +expect { + "\[TEST_END\]" {} + timeout { exit 1 } +} + +puts "\nTest successful!\n" diff --git a/projects/test_suite/tests/02-inputlength-regression b/projects/test_suite/tests/02-inputlength-regression new file mode 100755 index 0000000000..ae130f5517 --- /dev/null +++ b/projects/test_suite/tests/02-inputlength-regression @@ -0,0 +1,81 @@ +#!/usr/bin/expect + +set timeout 1 + +spawn pseudoterm $env(PORT) + +sleep 1 + +expect { + ">$" {} + timeout { exit 1 } +} + +send "123456789012345678901234567890123456789012345678901234567890\n" +expect { + "shell: command not found." {} + timeout { exit 1 } +} + +send "123456789012345678901234567890123456789012345678901234567890\n" +expect { + "shell: command not found." {} + timeout { exit 1 } +} + +send "123456789012345678901234567890123456789012345678901234567890\n" +expect { + "shell: command not found." {} + timeout { exit 1 } +} + +send "123456789012345678901234567890123456789012345678901234567890\n" +expect { + "shell: command not found." {} + timeout { exit 1 } +} + +send "123456789012345678901234567890123456789012345678901234567890\n" +expect { + "shell: command not found." {} + timeout { exit 1 } +} + +send "123456789012345678901234567890123456789012345678901234567890\n" +expect { + "shell: command not found." {} + timeout { exit 1 } +} + +send "123456789012345678901234567890123456789012345678901234567890\n" +expect { + "shell: command not found." {} + timeout { exit 1 } +} + +send "123456789012345678901234567890123456789012345678901234567890\n" +expect { + "shell: command not found." {} + timeout { exit 1 } +} + + +send "start_test\n" +expect { + "\[TEST_START\]" {} + timeout { exit 1 } +} + +expect { + ">$" {} + timeout { exit 1 } +} + +send "end_test\n" + +expect { + "\[TEST_END\]" {} + timeout { exit 1 } +} + +puts "\nTest successful!\n" diff --git a/projects/test_suite/tests/02-unknown-command b/projects/test_suite/tests/02-unknown-command new file mode 100755 index 0000000000..4dc6250422 --- /dev/null +++ b/projects/test_suite/tests/02-unknown-command @@ -0,0 +1,20 @@ +#!/usr/bin/expect + +set timeout 2 + +spawn pseudoterm $env(PORT) + +sleep 1 + +expect { + ">$" {} + timeout { exit 1 } +} + +send "some_definately_unknown_command\n" +expect { + "shell: command "some_definately_unknown_command" not found." {} + timeout { exit 1 } +} + +puts "\nTest successful!\n" diff --git a/projects/test_suite/tests/03-mutex_trylock_fail b/projects/test_suite/tests/03-mutex_trylock_fail new file mode 100755 index 0000000000..e9fa068275 --- /dev/null +++ b/projects/test_suite/tests/03-mutex_trylock_fail @@ -0,0 +1,56 @@ +#!/usr/bin/expect + +set timeout 5 + +spawn pseudoterm $env(PORT) + +expect { + ">$" {} + timeout { exit 1 } +} + +send "start_test\n" +expect { + "\[TEST_START\]" {} + timeout { exit 1 } +} + +expect { + ">$" {} + timeout { exit 1 } +} + +send "mutex_trylock_fail\n" +expect { + "main: locking mutex..." {} + timeout { exit 1 } +} +expect { + "main: creating thread..." {} + timeout { exit 1 } +} +expect { + "2nd: trying to lock mutex..." {} + timeout { exit 1 } +} +expect { + "2nd: done." {} + timeout { exit 1 } +} +expect { + "main: thread created. Unlocking mutex..." {} + timeout { exit 1 } +} +expect { + "main: mutex unlocked." {} + timeout { exit 1 } +} + +send "end_test\n" + +expect { + "\[TEST_END\]" {} + timeout { exit 1 } +} + +puts "\nTest successful!\n" diff --git a/projects/test_suite/tests/04-thread_sleep b/projects/test_suite/tests/04-thread_sleep new file mode 100755 index 0000000000..1734706b7a --- /dev/null +++ b/projects/test_suite/tests/04-thread_sleep @@ -0,0 +1,70 @@ +#!/usr/bin/expect + +set timeout 5 + +spawn pseudoterm $env(PORT) + +expect { + ">$" {} + timeout { exit 1 } +} + +send "start_test\n" +expect { + "\[TEST_START\]" {} + timeout { exit 1 } +} + +expect { + ">$" {} + timeout { exit 1 } +} + +send "thread_sleep\n" +expect { +" main: running. integer=0, i=1." {} +" main: running. integer=0, i=2." {} +"Waking up sleeper." {} +"sleeper: running. integer=1, i=2." {} +"sleeper: running. integer=2, i=2." {} +"Going to sleep." {} +" main: running. integer=2, i=3." {} +" main: running. integer=2, i=4." {} +"Waking up sleeper." {} +"Woke up!" {} +"sleeper: running. integer=3, i=4." {} +"sleeper: running. integer=4, i=4." {} +"Going to sleep." {} +" main: running. integer=4, i=5." {} +" main: running. integer=4, i=6." {} +"Waking up sleeper." {} +"Woke up!" {} +"sleeper: running. integer=5, i=6." {} +"sleeper: running. integer=6, i=6." {} +"Going to sleep." {} +" main: running. integer=6, i=7." {} +" main: running. integer=6, i=8." {} +"Waking up sleeper." {} +"Woke up!" {} +"sleeper: running. integer=7, i=8." {} +"sleeper: running. integer=8, i=8." {} +"Going to sleep." {} +" main: running. integer=8, i=9." {} +" main: running. integer=8, i=10." {} +"Waking up sleeper." {} +"Woke up!" {} +"sleeper: running. integer=9, i=10." {} +"sleeper: running. integer=10, i=10." {} +"Going to sleep." {} + ">$" {} + timeout { exit 1 } +} + +send "end_test\n" + +expect { + "\[TEST_END\]" {} + timeout { exit 1 } +} + +puts "\nTest successful!\n" diff --git a/projects/test_suite/thread_sleep.c b/projects/test_suite/thread_sleep.c new file mode 100644 index 0000000000..c88c015503 --- /dev/null +++ b/projects/test_suite/thread_sleep.c @@ -0,0 +1,39 @@ +#include +#include +#include + +static int integer = 0; +static int i = 0; + +static void second_thread(void) { + while(1) { + integer++; + printf("sleeper: running. integer=%i, i=%i.\n", integer, i); + if (integer % 2 == 0) { + printf("Going to sleep.\n"); + thread_sleep(); + printf("Woke up!\n"); + } + } +} + +static char second_thread_stack[KERNEL_CONF_STACKSIZE_DEFAULT*2]; + +void test_thread_sleep(char* line) +{ + int pid = thread_create(second_thread_stack, sizeof(second_thread_stack), PRIORITY_MAIN-1, CREATE_STACKTEST | CREATE_SLEEPING | CREATE_WOUT_YIELD, second_thread, "sleeper"); + + if (pid < 0) { + puts("Error creating second_thread! Stopping test."); + while(1); + } + + while(i < 10) { + i++; + printf(" main: running. integer=%i, i=%i.\n", integer, i); + if (i % 2 == 0) { + printf("Waking up sleeper.\n"); + thread_wakeup(pid); + } + } +} diff --git a/projects/test_swtimer_basic/Jamfile b/projects/test_swtimer_basic/Jamfile new file mode 100644 index 0000000000..7a5e6acb08 --- /dev/null +++ b/projects/test_swtimer_basic/Jamfile @@ -0,0 +1,5 @@ +SubDir TOP projects expect_swtimer ; + +Module expect_swtimer : main.c : swtimer ; + +UseModule expect_swtimer ; diff --git a/projects/test_swtimer_basic/main.c b/projects/test_swtimer_basic/main.c new file mode 100644 index 0000000000..25837a3ace --- /dev/null +++ b/projects/test_swtimer_basic/main.c @@ -0,0 +1,45 @@ +#include +#include +#include +#include +#include +#include + +void callback(void* ptr){ + puts((char*)ptr); +} + +void wakeup_thread(void){ + puts("wakeup"); +} + +void msg_thread(void){ + msg m; + msg_receive(&m); + printf("%s\n",(char*)m.content.ptr); +} + +int main(void) +{ + hwtimer_init(); + swtimer_init(); + + int pid1 = thread_create(8192, PRIORITY_MAIN-1, + CREATE_WOUT_YIELD | CREATE_SLEEPING | CREATE_STACKTEST, wakeup_thread, "nr1"); + + int pid2 = thread_create(8192, PRIORITY_MAIN-1, + /*CREATE_WOUT_YIELD | CREATE_SLEEPING |*/ CREATE_STACKTEST, msg_thread, "nr2"); + + + swtimer_t cbt; + swtimer_t wut; + swtimer_t mst; + /* test callback */ + swtimer_set_cb(&cbt,1000L,callback,"callback"); + /* test wake-up */ + swtimer_set_wakeup(&wut, 1000L, pid1); + /* test message */ + swtimer_set_msg(&mst,1000L, pid2, "message"); + + while(1); +} diff --git a/projects/test_swtimer_basic/tests/test_swtimer.py b/projects/test_swtimer_basic/tests/test_swtimer.py new file mode 100755 index 0000000000..465e5562ad --- /dev/null +++ b/projects/test_swtimer_basic/tests/test_swtimer.py @@ -0,0 +1,15 @@ +#!/usr/bin/python + +import pexpect +import os +import subprocess + +child = pexpect.spawn ("pseudoterm %s" % os.environ["PORT"]) + +null = open('/dev/null', 'wb') +subprocess.call(['jam', 'reset'], stdout=null) + +child.expect ('callback\r\n'); +child.expect ('wakeup\r\n'); +child.expect ('message\r\n'); +print("Test successful!") diff --git a/projects/test_thread_basic/Jamfile b/projects/test_thread_basic/Jamfile new file mode 100644 index 0000000000..3f9c7e01da --- /dev/null +++ b/projects/test_thread_basic/Jamfile @@ -0,0 +1,5 @@ +SubDir TOP projects test_thread_exit ; + +Module test_thread_exit : main.c ; + +UseModule test_thread_exit ; diff --git a/projects/test_thread_basic/main.c b/projects/test_thread_basic/main.c new file mode 100644 index 0000000000..ff95845563 --- /dev/null +++ b/projects/test_thread_basic/main.c @@ -0,0 +1,14 @@ +#include +#include +#include +#include + +void second_thread(void) { + puts("second thread\n"); +} + +int main(void) +{ + int pid = thread_create(8192, PRIORITY_MAIN-1, CREATE_WOUT_YIELD | CREATE_STACKTEST, second_thread, "nr2"); + puts("first thread\n"); +} diff --git a/projects/test_thread_basic/tests/test_thread.py b/projects/test_thread_basic/tests/test_thread.py new file mode 100755 index 0000000000..40df9e651e --- /dev/null +++ b/projects/test_thread_basic/tests/test_thread.py @@ -0,0 +1,15 @@ +#!/usr/bin/python + +import pexpect +import os +import subprocess + +child = pexpect.spawn("board/msba2/tools/bin/pseudoterm %s" % os.environ["PORT"]) + +null = open('/dev/null', 'wb') +subprocess.call(['jam', 'reset'], stdout=null) + +child.expect ('first thread\r\n') +child.expect ('second thread\r\n') +print("Test successful!") + diff --git a/projects/test_thread_exit/main.c b/projects/test_thread_exit/main.c index 3f09c7284e..363d437a22 100644 --- a/projects/test_thread_exit/main.c +++ b/projects/test_thread_exit/main.c @@ -9,8 +9,10 @@ void second_thread(void) { puts("2nd: running..."); } +char second_thread_stack[8192]; + int main(void) { - int pid = thread_create(8192, PRIORITY_MAIN-1, CREATE_WOUT_YIELD | CREATE_STACKTEST, second_thread, "nr2"); + int pid = thread_create(second_thread_stack, sizeof(second_thread_stack), PRIORITY_MAIN-1, CREATE_WOUT_YIELD | CREATE_STACKTEST, second_thread, "nr2"); puts("Main thread exiting..."); } diff --git a/sys/Jamfile b/sys/Jamfile index 82e44e197a..c8464217ab 100644 --- a/sys/Jamfile +++ b/sys/Jamfile @@ -35,6 +35,8 @@ Module auto_init : auto_init.c ; Module chardev_thread : chardev_thread.c : ringbuffer ; Module uart0 : uart0.c : ringbuffer chardev_thread ; +Module transceiver : transceiver.c ; + SubInclude TOP sys net ; SubInclude TOP sys lib ; SubInclude TOP sys shell ; diff --git a/sys/auto_init.c b/sys/auto_init.c index d872c0354f..c92b2b0176 100644 --- a/sys/auto_init.c +++ b/sys/auto_init.c @@ -1,5 +1,7 @@ #include #include +#include +#include #include #define ENABLE_DEBUG @@ -16,6 +18,15 @@ void auto_init(void) { DEBUG("Auto init swtimer module.\n"); swtimer_init(); #endif +#ifdef MODULE_UART0 + DEBUG("Auto init uart0 module.\n"); + board_uart0_init(); +#endif +#ifdef MODULE_RTC + DEBUG("Auto init rtc module.\n"); + rtc_init(); + rtc_enable(); +#endif #ifdef MODULE_SHT11 DEBUG("Auto init SHT11 module.\n"); sht11_init(); diff --git a/sys/include/board_uart0.h b/sys/include/board_uart0.h index 2819ef61b0..d38c22c75b 100644 --- a/sys/include/board_uart0.h +++ b/sys/include/board_uart0.h @@ -3,8 +3,11 @@ extern int uart0_handler_pid; -void board_uart0_init(); +void board_uart0_init(void); void uart0_handle_incoming(int c); -void uart0_notify_thread(); +void uart0_notify_thread(void); + +int uart0_readc(void); +void uart0_putc(int c); #endif /* __BOARD_UART0_H */ diff --git a/sys/include/radio/types.h b/sys/include/radio/types.h index 7018480f65..f5b88c9c0e 100644 --- a/sys/include/radio/types.h +++ b/sys/include/radio/types.h @@ -73,6 +73,21 @@ typedef struct __attribute__ ((packed)) packet_info_t bool promiscuous; ///< Radio layer: whether network interface is in promiscuous mode } packet_info_t; + +/** + * @brief General link layer packet format + */ +typedef struct __attribute__ ((packed)) { + uint8_t processing; ///< internal processing state + uint16_t src; ///< Radio source address + uint16_t dst; ///< Radio destination address + uint8_t rssi; ///< Radio Signal Strength Indication + uint8_t lqi; ///< Link Quality Indicator + uint8_t length; ///< Length of payload + uint8_t *data; ///< Payload +} radio_packet_t; + + /** * Packet handler (receive function) of all layers. * @param [in/out] payload Pointer to packet payload data diff --git a/sys/include/shell.h b/sys/include/shell.h index daa739b531..9020914c88 100644 --- a/sys/include/shell.h +++ b/sys/include/shell.h @@ -34,8 +34,9 @@ and the mailinglist (subscription via web site) //#include "hashtable.h" -typedef struct shell_commant_t { +typedef struct shell_command_t { char* name; + char* desc; void (*handler)(char*); } shell_command_t; @@ -47,16 +48,12 @@ typedef struct shell_t { /** * @brief Initialize a shell object + * @param shell Pointer to preallocated shell object + * @param shell_commands Pointer to shell command structure. See test_shell project for example. + * @param read_char Pointer to input device read function. Should return exactly one byte or block. + * @param put_char Pointer to output funtion. currently unused, shell code will use printf. */ -void shell_init(shell_t *shell, int(*read_char)(void), void (*put_char)(int)); - -/** - * @brief Register a new command handler for a shell. - * @param shell Shell object. - * @param name Name of the command to register. - * @param handler Function pointer to handler that takes the complete command line as parameter. - */ -//void shell_register_cmd(shell_t *shell, char* name, void (*handler)(char* args)); +void shell_init(shell_t *shell, const shell_command_t *shell_commands, int(*read_char)(void), void (*put_char)(int)); /** * @brief Endless loop that waits for command and executes handler. diff --git a/sys/include/shell_commands.h b/sys/include/shell_commands.h new file mode 100644 index 0000000000..1e0ec85759 --- /dev/null +++ b/sys/include/shell_commands.h @@ -0,0 +1,8 @@ +#ifndef __SHELL_COMMANDS_H +#define __SHELL_COMMANDS_H + +#include + +extern const shell_command_t _shell_command_list[]; + +#endif /* __SHELL_COMMANDS_H */ diff --git a/sys/include/swtimer.h b/sys/include/swtimer.h index 9f7d9a9730..14835348df 100644 --- a/sys/include/swtimer.h +++ b/sys/include/swtimer.h @@ -28,11 +28,7 @@ #undef wakeup -#if WORDSIZE == 32 -typedef uint64_t swtime_t; -#else typedef uint32_t swtime_t; -#endif /** * A swtimer. @@ -64,14 +60,23 @@ typedef struct swtimer_t { } action; } swtimer_t; +/** + * @brief Current system time + * @return Time in ticks since system boot + */ swtime_t swtimer_now(); +/** + * @brief Initializes swtimer + * @return always 0 + */ int swtimer_init(); /** * @brief set swtimer interval and activate * @param[in] t pointer to preinitialised swtimer_t * @param[in] interval swtimer interval + * @return always 0 */ int swtimer_set(swtimer_t *t, swtime_t interval); diff --git a/sys/include/transceiver.h b/sys/include/transceiver.h new file mode 100644 index 0000000000..a31876bd7f --- /dev/null +++ b/sys/include/transceiver.h @@ -0,0 +1,89 @@ +#ifndef TRANSCEIVER_H +#define TRANSCEIVER_H + +#include + +/* Packets to buffer */ +#define TRANSCEIVER_BUFFER_SIZE (10) +/* Stack size for transceiver thread */ +#define TRANSCEIVER_STACK_SIZE (2048) + +/* The maximum of threads to register */ +#define TRANSCEIVER_MAX_REGISTERED (10) + +/* The size of the message queue between driver and transceiver (must be power + * of two */ +#define TRANSCEIVER_MSG_BUFFER_SIZE (64) + +/** + * @brief Message types for transceiver interface + */ +enum transceiver_msg_type_t { + /* Packet types for driver <-> transceiver communication */ + RCV_PKT_CC1020, ///< packet was received by CC1020 transceiver + RCV_PKT_CC1100, ///< packet was received by CC1100 transceiver + + /* Packet types for transceiver <-> upper layer communication */ + PKT_PENDING, ///< packet pending in transceiver buffer + SND_PKT, ///< request for sending a packet + SND_ACK, ///< request for sending an acknowledgement + SWITCH_RX, ///< switch transceiver to RX sate + POWERDOWN, ///< power down transceiver + GET_CHANNEL, ///< Get current channel + SET_CHANNEL, ///< Set a new channel + GET_ADDRESS, ///< Get the radio address + SET_ADDRESS, ///< Set the radio address + SET_MONITOR, ///< Set transceiver to monitor mode (disable address checking) + + /* Error messages */ + ENOBUFFER, ///< No buffer left +}; + +/** + * @brief All supported transceivers + */ +typedef enum { + TRANSCEIVER_NONE, ///< Invalid + TRANSCEIVER_CC1100, ///< CC110X transceivers + TRANSCEIVER_CC1020 ///< CC1020 transceivers +} transceiver_type_t; + +/** + * @brief Manage registered threads per transceiver + */ +typedef struct { + transceiver_type_t transceivers; ///< the tranceivers the thread is registered for + int pid; ///< the thread's pid +} registered_t; + +typedef struct { + transceiver_type_t transceivers; + void *data; +} transceiver_command_t;; + +/* The transceiver thread's pid */ +extern int transceiver_pid; + +/** + * @brief Initializes the transceiver module for certain transceiver types + * + * @param transceivers Specifies all transceivers to init + **/ +void transceiver_init(transceiver_type_t transceivers); + +/** + * @brief Runs the transceiver thread + */ +int transceiver_start(void); + +/** + * @brief register a thread for events from certain transceivers + * + * @param transceivers The transceiver types to register for + * @param pid The pid of the thread to register + * + * return 1 on success, 0 otherwise + */ +uint8_t transceiver_register(transceiver_type_t transceivers, int pid); + +#endif /* TRANSCEIVER_H */ diff --git a/sys/shell/Jamfile b/sys/shell/Jamfile index 195b04fd8c..fa8b989d31 100644 --- a/sys/shell/Jamfile +++ b/sys/shell/Jamfile @@ -28,7 +28,7 @@ SubDir TOP sys shell ; Module shell : shell.c ; -Module shell_commands : shell_commands.c : shell ; +Module shell_commands : shell_commands.c rtc.c sht11.c ltc4150.c cc1100.c cc1100_ng.c : shell ; Module ps : ps.c ; diff --git a/sys/shell/cc1100.c b/sys/shell/cc1100.c new file mode 100644 index 0000000000..4236f517da --- /dev/null +++ b/sys/shell/cc1100.c @@ -0,0 +1,24 @@ +#include +#include + +void _cc1100_get_address_handler(char *str) { + radio_address_t addr = cc1100_get_address(); + printf("cc1100 address: %i\n", addr); +} + +void _cc1100_set_address_handler(char *str) { + int addr; + int res = sscanf(str, "cc1100_set_address %i", &addr); + if (res == 1) { + cc1100_set_address((radio_address_t)addr); + printf("Setting cc1100 address to %i: ", addr); + if (cc1100_get_address() == (radio_address_t)addr) { + puts("OK"); + } else { + puts("Error!"); + } + } else { + puts("usage: cc1100_set_address
"); + } +} + diff --git a/sys/shell/cc1100_ng.c b/sys/shell/cc1100_ng.c new file mode 100644 index 0000000000..3ae631520c --- /dev/null +++ b/sys/shell/cc1100_ng.c @@ -0,0 +1,86 @@ +#include +#include +#include +#include +#include + +#define TEXT_SIZE CC1100_MAX_DATA_LENGTH + +char text_msg[TEXT_SIZE]; +msg mesg; +transceiver_command_t tcmd; + +void _cc1100_ng_get_set_address_handler(char *addr) { + int16_t a; + + tcmd.transceivers = TRANSCEIVER_CC1100; + tcmd.data = &a; + mesg.content.ptr = (char*) &tcmd; + if (sscanf(addr, "addr %hi", &a) > 0) { + printf("[cc1100] Trying to set address %i\n", a); + mesg.type = SET_ADDRESS; + } + else { + mesg.type = GET_ADDRESS; + } + msg_send_receive(&mesg, &mesg, transceiver_pid); + printf("[cc1100] Got address: %i\n", a); +} + +void _cc1100_ng_get_set_channel_handler(char *chan) { + int16_t c; + + tcmd.transceivers = TRANSCEIVER_CC1100; + tcmd.data = &c; + mesg.content.ptr = (char*) &tcmd; + if (sscanf(chan, "chan %hi", &c) > 0) { + printf("[cc1100] Trying to set channel %i\n", c); + mesg.type = SET_CHANNEL; + } + else { + mesg.type = GET_CHANNEL; + } + msg_send_receive(&mesg, &mesg, transceiver_pid); + printf("[cc1100] Got channel: %i\n", c); +} + +void _cc1100_ng_send_handler(char *pkt) { + radio_packet_t p; + uint32_t response; + tcmd.transceivers = TRANSCEIVER_CC1100; + tcmd.data = &p; + uint16_t addr; + + if (sscanf(pkt, "txtsnd %hu %s", &(addr), text_msg) == 2) { + p.data = (uint8_t*) text_msg; + p.length = strlen(text_msg); + p.dst = addr; + mesg.type = SND_PKT; + mesg.content.ptr = (char*) &tcmd; + printf("[cc1100] Sending packet of length %u to %hu: %s\n", p.length, p.dst, (char*) p.data); + msg_send_receive(&mesg, &mesg, transceiver_pid); + response = mesg.content.value; + printf("[cc1100] Packet sent: %lu\n", response); + } + else { + puts("Usage:\ttxtsnd "); + } +} + +void _cc1100_ng_monitor_handler(char *mode) { + unsigned int m; + + tcmd.transceivers = TRANSCEIVER_CC1100; + tcmd.data = &m; + mesg.content.ptr = (char*) &tcmd; + if (sscanf(mode, "monitor %u", &m) == 1) { + printf("Setting monitor mode: %u\n", m); + mesg.type = SET_MONITOR; + msg_send(&mesg, transceiver_pid, 1); + } + else { + puts("Usage:\nmonitor "); + } +} + + diff --git a/sys/shell/ltc4150.c b/sys/shell/ltc4150.c new file mode 100644 index 0000000000..c29519c14c --- /dev/null +++ b/sys/shell/ltc4150.c @@ -0,0 +1,10 @@ +#include +#include + +void _get_current_handler(char* unused) { + printf("Power usage: %.4f mA (%.4f mA avg/ %.4f mAh total / %i usec)\n", ltc4150_get_current_mA(), ltc4150_get_avg_mA(), ltc4150_get_total_mAh(), ltc4150_get_interval()); +} + +void _reset_current_handler(char* unused) { + ltc4150_start(); +} diff --git a/sys/shell/rtc.c b/sys/shell/rtc.c new file mode 100644 index 0000000000..25f99c089e --- /dev/null +++ b/sys/shell/rtc.c @@ -0,0 +1,48 @@ +#include +#include +#include +#include +#include + +void _gettime_handler(void) { + struct tm now; + rtc_get_localtime(&now); + + printf("%s", asctime(&now)); +} + +void _settime_handler(char* c) { + struct tm now; + int res; + uint16_t month, epoch_year; + + res = sscanf(c, "date %hu-%hu-%u %u:%u:%u", + &epoch_year, + &month, + (unsigned int*) &(now.tm_mday), + (unsigned int*) &(now.tm_hour), + (unsigned int*) &(now.tm_min), + (unsigned int*) &(now.tm_sec)); + + if (res < 6) { + printf("Usage: date YYYY-MM-DD hh:mm:ss\n"); + return; + } + else { + puts("OK"); + } + + now.tm_year = epoch_year - 1900; + now.tm_mon = month - 1; + time_t t = mktime(&now); + rtc_set(t); +} + +void _date_handler(char* c) { + if (strlen(c) == 4) { + _gettime_handler(); + } + else { + _settime_handler(c); + } +} diff --git a/sys/shell/shell.c b/sys/shell/shell.c index 6a960b47f0..37ad42892c 100644 --- a/sys/shell/shell.c +++ b/sys/shell/shell.c @@ -44,39 +44,79 @@ and the mailinglist (subscription via web site) #include #include #include -#include #include #include +#include +#include static void(*find_handler(const shell_command_t *command_list, char *command))(char*) { - const shell_command_t *entry = command_list; - - while(entry->name != NULL) { + const shell_command_t* entry = command_list; + if (entry) { + while (entry->name != NULL) { + if ( strcmp(entry->name, command) == 0) { + return entry->handler; + } else { + entry++; + } + } + } + +#ifdef MODULE_SHELL_COMMANDS + entry = _shell_command_list; + while (entry->name != NULL) { if ( strcmp(entry->name, command) == 0) { return entry->handler; } else { - command_list++; + entry++; } } +#endif return NULL; } +static void print_help(const shell_command_t *command_list) { + const shell_command_t *entry = command_list; + + printf("%-20s %s\n", "Command", "Description"); + puts("---------------------------------------"); + + if (entry) { + while (entry->name != NULL) { + printf("%-20s %s\n", entry->name, entry->desc); + entry++; + } + } + +#ifdef MODULE_SHELL_COMMANDS + entry = _shell_command_list; + while (entry->name != NULL) { + printf("%-20s %s\n", entry->name, entry->desc); + entry++; + } +#endif +} + static void handle_input_line(shell_t *shell, char* line) { char* saveptr; - char* command = strtok_r(line, " ", &saveptr); + char* linedup = strdup(line); + char* command = strtok_r(linedup, " ", &saveptr); void (*handler)(char*) = NULL; if (command) { handler = find_handler(shell->command_list, command); - if (handler) { + if (handler != NULL) { handler(line); } else { - printf("shell: command \"%s\" not found.\n", command); + if ( strcmp("help", command) == 0) { + print_help(shell->command_list); + } else { + puts("shell: command not found."); + } } } - - free(line); + + free(linedup); } int readline(shell_t *shell, char* buf, int size) { @@ -109,12 +149,15 @@ void shell_run(shell_t *shell) { shell->put_char('>'); int res = readline(shell, line_buf, sizeof(line_buf)); if (! res ) { - handle_input_line(shell, strdup(line_buf)); + char* line_copy = strdup(line_buf); + handle_input_line(shell, line_copy); + free(line_copy); } } } -void shell_init(shell_t *shell, int(*readchar)(void), void(*put_char)(int)) { +void shell_init(shell_t *shell, const shell_command_t *shell_commands, int(*readchar)(void), void(*put_char)(int)) { + shell->command_list = shell_commands; shell->readchar = readchar; shell->put_char = put_char; } diff --git a/sys/shell/shell_commands.c b/sys/shell/shell_commands.c index 5223597d6c..e894b2456c 100644 --- a/sys/shell/shell_commands.c +++ b/sys/shell/shell_commands.c @@ -1,9 +1,69 @@ #include +#include + +#ifdef MODULE_PS +extern void _ps_handler(char* unused); +#endif + +#ifdef MODULE_RTC +extern void _date_handler(char* now); +#endif + +#ifdef MODULE_SHT11 +extern void _get_temperature_handler(char* unused); +extern void _get_humidity_handler(char* unused); +extern void _get_weather_handler(char* unused); +extern void _set_offset_handler(char* offset); +#endif + +#ifdef MODULE_LTC4150 +extern void _get_current_handler(char* unused); +extern void _reset_current_handler(char* unused); +#endif + +#ifdef MODULE_CC110X +extern void _cc1100_get_address_handler(char *unused); +extern void _cc1100_set_address_handler(char *ptr); +#endif + +#ifdef MODULE_TRANSCEIVER +#ifdef MODULE_CC110X_NG +extern void _cc1100_ng_get_set_address_handler(char *addr); +extern void _cc1100_ng_get_set_channel_handler(char *chan); +extern void _cc1100_ng_send_handler(char *pkt); +extern void _cc1100_ng_monitor_handler(char *mode); +#endif +#endif const shell_command_t _shell_command_list[] = { #ifdef MODULE_PS - {"ps", ps_handler}, + {"ps", "Prints information about running threads.", _ps_handler}, #endif - {NULL, NULL} +#ifdef MODULE_RTC + {"date", "Geets or gets current date and time.", _date_handler}, +#endif +#ifdef MODULE_SHT11 + {"temp", "Prints measured temperature.", _get_temperature_handler}, + {"hum", "Prints measured humidity.", _get_humidity_handler}, + {"weather", "Prints measured humidity and temperature.", _get_weather_handler}, + {"offset", "Set temperature offset.", _set_offset_handler}, +#endif +#ifdef MODULE_LTC4150 + {"cur", "Prints current and average power consumption.", _get_current_handler}, + {"rstcur", "Resets coulomb counter.", _reset_current_handler}, +#endif +#ifdef MODULE_CC110X + {"cc1100_get_address", "", _cc1100_get_address_handler}, + {"cc1100_set_address", "", _cc1100_set_address_handler}, +#endif +#ifdef MODULE_TRANSCEIVER +#ifdef MODULE_CC110X_NG + {"addr", "Gets or sets the address for the CC1100 transceiver", _cc1100_ng_get_set_address_handler}, + {"chan", "Gets or sets the channel for the CC1100 transceiver", _cc1100_ng_get_set_channel_handler}, + {"txtsnd", "Sends a text message to a given node via the CC1100 transceiver", _cc1100_ng_send_handler}, + {"monitor", "Enables or disables address checking for the CC1100 transceiver", _cc1100_ng_monitor_handler}, +#endif +#endif + {NULL, NULL, NULL} }; diff --git a/sys/shell/sht11.c b/sys/shell/sht11.c new file mode 100644 index 0000000000..e008444538 --- /dev/null +++ b/sys/shell/sht11.c @@ -0,0 +1,53 @@ +#include +#include +#include +#include + +extern float sht11_temperature_offset; + +void _get_humidity_handler(char* unused) { + uint8_t success; + sht11_val_t sht11_val; + success = sht11_read_sensor(&sht11_val, HUMIDITY|TEMPERATURE); + if (!success) { + printf("Error reading SHT11\n"); + } + else { + printf("Relative humidity: %5.2f%% / Temperature compensated humidity; %5.2f%%\n", + sht11_val.relhum, sht11_val.relhum_temp); + } +} +void _get_temperature_handler(char* unused) { + uint8_t success; + sht11_val_t sht11_val; + success = sht11_read_sensor(&sht11_val, TEMPERATURE); + if (!success) { + printf("Error reading SHT11\n"); + } + else { + printf("Temperature: %-6.2f°C\n", sht11_val.temperature); + } +} +void _get_weather_handler(char* unused) { + uint8_t success; + sht11_val_t sht11_val; + success = sht11_read_sensor(&sht11_val, HUMIDITY|TEMPERATURE); + if (!success) { + printf("Error reading SHT11\n"); + } + else { + printf("Relative humidity: %5.2f%% / Temperature compensated humidity; %5.2f%% ", + sht11_val.relhum, sht11_val.relhum_temp); + printf("Temperature: %-6.2f°C\n", sht11_val.temperature); + } +} + +void _set_offset_handler(char* offset) { + if (strlen(offset) == 6) { + puts("Usage: offset "); + } + else { + sscanf(offset, "offset %f", &sht11_temperature_offset); + printf("Temperature offset set to %f\n", sht11_temperature_offset); + } +} diff --git a/sys/transceiver.c b/sys/transceiver.c new file mode 100644 index 0000000000..d3828d1861 --- /dev/null +++ b/sys/transceiver.c @@ -0,0 +1,366 @@ +#include +#include +#include + +#include +#include + +#include +#include + +#define PAYLOAD_SIZE (0) + +/* supported transceivers */ +#ifdef MODULE_CC110X_NG +#include +#if (CC1100_MAX_DATA_LENGTH > PAYLOAD_SIZE) + #undef PAYLOAD_SIZE + #define PAYLOAD_SIZE (CC1100_MAX_DATA_LENGTH) +#endif +#endif + +#define ENABLE_DEBUG (1) +#include + +/*------------------------------------------------------------------------------------*/ +/* used transceiver types */ +transceiver_type_t transceivers = TRANSCEIVER_NONE; + +/* registered upper layer threads */ +registered_t reg[TRANSCEIVER_MAX_REGISTERED]; + +/* packet buffers */ +radio_packet_t transceiver_buffer[TRANSCEIVER_BUFFER_SIZE]; +uint8_t data_buffer[TRANSCEIVER_BUFFER_SIZE * PAYLOAD_SIZE]; + +/* message buffer */ +msg msg_buffer[TRANSCEIVER_MSG_BUFFER_SIZE]; + +uint32_t response; ///< response bytes for messages to upper layer threads + +int transceiver_pid; ///< the transceiver thread's pid + +static volatile uint8_t rx_buffer_pos = 0; +static volatile uint8_t transceiver_buffer_pos = 0; + +/* transceiver stack */ +char transceiver_stack[TRANSCEIVER_STACK_SIZE]; + +/*------------------------------------------------------------------------------------*/ +/* function prototypes */ +static void run(void); +static void receive_packet(uint16_t type, uint8_t pos); +static void receive_cc1100_packet(radio_packet_t *trans_p); +static uint8_t send_packet(transceiver_type_t t, void *pkt); +static int16_t get_channel(transceiver_type_t t); +static int16_t set_channel(transceiver_type_t t, void *channel); +static int16_t get_address(transceiver_type_t t); +static int16_t set_address(transceiver_type_t t, void *address); +static void set_monitor(transceiver_type_t t, void *mode); + +/*------------------------------------------------------------------------------------*/ +/* Transceiver init */ +void transceiver_init(transceiver_type_t t) { + uint8_t i; + for (i = 0; i < TRANSCEIVER_MAX_REGISTERED; i++) { + reg[i].transceivers = TRANSCEIVER_NONE; + reg[i].pid = 0; + } + if (t & TRANSCEIVER_CC1100) { + transceivers |= t; + } + else { + puts("Invalid transceiver type"); + } +} + +/* Start the transceiver thread */ +int transceiver_start(void) { + transceiver_pid = thread_create(transceiver_stack, TRANSCEIVER_STACK_SIZE, PRIORITY_MAIN-3, CREATE_STACKTEST, run, "Transceiver"); + if (transceiver_pid < 0) { + puts("Error creating transceiver thread"); + } + else if (transceivers & TRANSCEIVER_CC1100) { + DEBUG("Transceiver started for CC1100\n"); + cc1100_init(transceiver_pid); + } + return transceiver_pid; +} + +/* Register an upper layer thread */ +uint8_t transceiver_register(transceiver_type_t t, int pid) { + uint8_t i; + for (i = 0; ((reg[i].pid != pid) && + (i < TRANSCEIVER_MAX_REGISTERED) && + (reg[i].transceivers != TRANSCEIVER_NONE)); i++); + + if (i >= TRANSCEIVER_MAX_REGISTERED) { + return ENOMEM; + } + else { + reg[i].transceivers |= t; + reg[i].pid = pid; + DEBUG("Thread %i registered for %i\n", reg[i].pid, reg[i].transceivers); + return 1; + } +} + +/*------------------------------------------------------------------------------------*/ +/* Internal functions */ +/*------------------------------------------------------------------------------------*/ + +/* + * @brief The main thread run, receiving and processing messages in an infinite + * loop + */ +void run(void) { + msg m; + transceiver_command_t *cmd; + + msg_init_queue(msg_buffer, TRANSCEIVER_MSG_BUFFER_SIZE); + while (1) { + msg_receive(&m); + /* only makes sense for messages for upper layers */ + cmd = (transceiver_command_t*) m.content.ptr; + DEBUG("Transceiver: Message received\n"); + switch (m.type) { + case RCV_PKT_CC1020: + case RCV_PKT_CC1100: + receive_packet(m.type, m.content.value); + break; + case SND_PKT: + response = send_packet(cmd->transceivers, cmd->data); + m.content.value = response; + msg_reply(&m, &m); + break; + case GET_CHANNEL: + *((int16_t*) cmd->data) = get_channel(cmd->transceivers); + msg_reply(&m, &m); + break; + case SET_CHANNEL: + *((int16_t*) cmd->data) = set_channel(cmd->transceivers, cmd->data); + msg_reply(&m, &m); + break; + case GET_ADDRESS: + *((int16_t*) cmd->data) = get_address(cmd->transceivers); + msg_reply(&m, &m); + break; + case SET_ADDRESS: + *((int16_t*) cmd->data) = set_address(cmd->transceivers, cmd->data); + msg_reply(&m, &m); + break; + case SET_MONITOR: + set_monitor(cmd->transceivers, cmd->data); + break; + default: + DEBUG("Unknown message received\n"); + break; + } + } +} + +/*------------------------------------------------------------------------------------*/ +/* + * @brief Processes a packet received by any transceiver device + * + * @param type The message type to determine which device has received the + * packet + * @param pos The current device driver's buffer position + */ +static void receive_packet(uint16_t type, uint8_t pos) { + uint8_t i = 0; + transceiver_type_t t; + rx_buffer_pos = pos; + msg m; + + DEBUG("Packet received\n"); + switch (type) { + case RCV_PKT_CC1020: + t = TRANSCEIVER_CC1020; + break; + case RCV_PKT_CC1100: + t = TRANSCEIVER_CC1100; + break; + default: + t = TRANSCEIVER_NONE; + break; + } + + /* search first free position in transceiver buffer */ + for (i = 0; (i < TRANSCEIVER_BUFFER_SIZE) && (transceiver_buffer[transceiver_buffer_pos].processing); i++) { + if (++transceiver_buffer_pos == TRANSCEIVER_BUFFER_SIZE) { + transceiver_buffer_pos = 0; + } + } + /* no buffer left */ + if (i >= TRANSCEIVER_BUFFER_SIZE) { + /* inform upper layers of lost packet */ + m.type = ENOBUFFER; + m.content.value = t; + } + /* copy packet and handle it */ + else { + radio_packet_t *trans_p = &(transceiver_buffer[transceiver_buffer_pos]); + m.type = PKT_PENDING; + + if (type == RCV_PKT_CC1100) { + receive_cc1100_packet(trans_p); + } + else { + puts("Invalid transceiver type"); + return; + } + } + + /* finally notify waiting upper layers + * this is done non-blocking, so packets can get lost */ + i = 0; + while (reg[i].transceivers != TRANSCEIVER_NONE) { + if (reg[i].transceivers & t) { + m.content.ptr = (char*) &(transceiver_buffer[transceiver_buffer_pos]); + DEBUG("Notify thread %i\n", reg[i].pid); + if (msg_send(&m, reg[i].pid, false)) { + transceiver_buffer[transceiver_buffer_pos].processing++; + } + } + i++; + } +} + +/* + * @brief process packets from CC1100 + * + * @param trans_p The current entry in the transceiver buffer + */ +static void receive_cc1100_packet(radio_packet_t *trans_p) { + DEBUG("Handling CC1100 packet\n"); + /* disable interrupts while copying packet */ + dINT(); + cc1100_packet_t p = cc1100_rx_buffer[rx_buffer_pos].packet; + + trans_p->src = p.phy_src; + trans_p->dst = p.address; + trans_p->rssi = cc1100_rx_buffer[rx_buffer_pos].rssi; + trans_p->lqi = cc1100_rx_buffer[rx_buffer_pos].lqi; + trans_p->length = p.length - CC1100_HEADER_LENGTH; + memcpy((void*) &(data_buffer[transceiver_buffer_pos * PAYLOAD_SIZE]), p.data, CC1100_MAX_DATA_LENGTH); + eINT(); + + DEBUG("Packet %p was from %hu to %hu, size: %u\n", trans_p, trans_p->src, trans_p->dst, trans_p->length); + trans_p->data = (uint8_t*) &(data_buffer[transceiver_buffer_pos * CC1100_MAX_DATA_LENGTH]); +} + +/*------------------------------------------------------------------------------------*/ +/* + * @brief Sends a radio packet to the receiver + * + * @param t The transceiver device + * @param pkt Generic pointer to the packet + * + * @return 1 on success, 0 otherwise + */ +static uint8_t send_packet(transceiver_type_t t, void *pkt) { + uint8_t res = 0; + radio_packet_t p = *((radio_packet_t*) pkt); + cc1100_packet_t cc1100_pkt; + + switch (t) { + case TRANSCEIVER_CC1100: + cc1100_pkt.length = p.length + CC1100_HEADER_LENGTH; + cc1100_pkt.address = p.dst; + cc1100_pkt.flags = 0; + memcpy(cc1100_pkt.data, p.data, p.length); + + res = cc1100_send(&cc1100_pkt); + break; + default: + puts("Unknown transceiver"); + break; + } + return res; +} + +/*------------------------------------------------------------------------------------*/ +/* + * @brief Sets the radio channel for any transceiver device + * + * @param t The transceiver device + * @param channel The channel to be set + * + * @return The radio channel AFTER calling the set command, -1 on error + */ +static int16_t set_channel(transceiver_type_t t, void *channel) { + uint8_t c = *((uint8_t*) channel); + switch (t) { + case TRANSCEIVER_CC1100: + return cc1100_set_channel(c); + default: + return -1; + } +} + +/* + * @brief Get the radio channel of any transceiver device + * + * @param t The transceiver device + * + * @return The current radio channel of the transceiver, -1 on error + */ +static int16_t get_channel(transceiver_type_t t) { + switch (t) { + case TRANSCEIVER_CC1100: + return cc1100_get_channel(); + default: + return -1; + } +} +/*------------------------------------------------------------------------------------*/ +/* + * @brief Get the current address of transceiver device + * + * @param t The transciever device + * + * @return The configured address of the device, -1 on error + */ +static int16_t get_address(transceiver_type_t t) { + switch (t) { + case TRANSCEIVER_CC1100: + return cc1100_get_address(); + default: + return -1; + } +} + +/* + * @brief Set the address of the transceiver device + * + * @param t The transceiver device + * @param address Generic pointer to the address to set + * + * @return The new radio address of the device + */ +static int16_t set_address(transceiver_type_t t, void *address) { + radio_address_t addr = *((radio_address_t*) address); + switch (t) { + case TRANSCEIVER_CC1100: + return cc1100_set_address(addr); + default: + return -1; + } +} + +/* + * @brief Set the transceiver device into monitor mode (disabling address check) + * + * @param t The transceiver device + * @param mode 1 for enabling monitor mode, 0 for enabling address check + */ +static void set_monitor(transceiver_type_t t, void *mode) { + switch (t) { + case TRANSCEIVER_CC1100: + cc1100_set_monitor(*((uint8_t*) mode)); + break; + default: + break; + } +} diff --git a/sys/uart0.c b/sys/uart0.c index e6ad35bc38..04182b082c 100644 --- a/sys/uart0.c +++ b/sys/uart0.c @@ -3,23 +3,27 @@ #include #include #include +#include #include -#define UART0_BUFSIZE 32 +#define UART0_BUFSIZE (32) +#define UART0_STACKSIZE (MINIMUM_STACK_SIZE + 256) ringbuffer uart0_ringbuffer; int uart0_handler_pid; static char buffer[UART0_BUFSIZE]; -static void uart0_loop() { +static char uart0_thread_stack[UART0_STACKSIZE]; + +static void uart0_loop(void) { chardev_loop(&uart0_ringbuffer); } -void board_uart0_init() { +void board_uart0_init(void) { ringbuffer_init(&uart0_ringbuffer, buffer, UART0_BUFSIZE); - int pid = thread_create(KERNEL_CONF_STACKSIZE_MAIN, PRIORITY_MAIN-1, CREATE_STACKTEST, uart0_loop, "uart0"); + int pid = thread_create(uart0_thread_stack, sizeof(uart0_thread_stack), PRIORITY_MAIN-1, CREATE_STACKTEST, uart0_loop, "uart0"); uart0_handler_pid = pid; puts("uart0_init() [OK]"); } @@ -28,8 +32,18 @@ void uart0_handle_incoming(int c) { rb_add_element(&uart0_ringbuffer, c); } -void uart0_notify_thread() { +void uart0_notify_thread(void) { msg m; m.type = 0; msg_send_int(&m, uart0_handler_pid); } + +int uart0_readc(void) { + char c = 0; + posix_read(uart0_handler_pid, &c, 1); + return c; +} + +void uart0_putc(int c) { + putchar(c); +} diff --git a/tools/pyterm/pyterm.py b/tools/pyterm/pyterm.py new file mode 100755 index 0000000000..59eadcfbd1 --- /dev/null +++ b/tools/pyterm/pyterm.py @@ -0,0 +1,122 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +import cmd, serial, sys, threading, readline, time, ConfigParser +from datetime import datetime +from os import path + +class SerCmd(cmd.Cmd): + + def __init__(self, port=None): + cmd.Cmd.__init__(self) + self.port = port + self.aliases = dict() + self.load_config() + try: + readline.read_history_file() + except IOError: + pass + + def preloop(self): + if not self.port: + sys.stderr.write("No port specified!\n") + sys.exit(-1) + self.ser = serial.Serial(port=self.port, baudrate=115200, dsrdtr=0, rtscts=0) + #self.ser.setDTR(0) + #self.ser.setRTS(0) + + # start serial->console thread + receiver_thread = threading.Thread(target=reader, args=(self.ser,)) + receiver_thread.setDaemon(1) + receiver_thread.start() + + def default(self, line): + for tok in line.split(';'): + tok = self.get_alias(tok) + self.ser.write(tok.strip() + "\n") + + def do_help(self, line): + self.ser.write("help\n") + + def complete_date(self, text, line, begidx, endidm): + date = datetime.now().strftime("%Y-%m-%d %H:%M:%S") + return ["%s" % date] + + def do_reset(self, line): + self.ser.setDTR(1) + self.ser.setRTS(1) + self.ser.setDTR(0) + self.ser.setRTS(0) + + def do_exit(self, line): + readline.write_history_file() + sys.exit(0) + + def do_save(self, line): + if not self.config.has_section("general"): + self.config.add_section("general") + self.config.set("general", "port", self.port) + if len(self.aliases): + if not self.config.has_section("aliases"): + self.config.add_section("aliases") + for alias in self.aliases: + self.config.set("aliases", alias, self.aliases[alias]) + + with open(path.expanduser('~/.pyterm'), 'wb') as config_fd: + self.config.write(config_fd) + print("Config saved") + + def do_show_config(self, line): + for key in self.__dict__: + print(str(key) + ": " + str(self.__dict__[key])) + + def do_alias(self, line): + if line.endswith("list"): + for alias in self.aliases: + print("%s = %s" % (alias, self.aliases[alias])) + return + if not line.count("="): + sys.stderr.write("Usage: alias = \n") + return + self.aliases[line.split('=')[0].strip()] = line.split('=')[1].strip() + + def do_rmalias(self, line): + if not self.aliases.pop(line, None): + sys.stderr.write("Alias not found") + + def get_alias(self, tok): + for alias in self.aliases: + if tok.split()[0] == alias: + return self.aliases[alias] + tok[len(alias):] + return tok + + def load_config(self): + self.config = ConfigParser.SafeConfigParser() + self.config.read([path.expanduser('~/.pyterm')]) + + for sec in self.config.sections(): + if sec == "aliases": + for opt in self.config.options(sec): + self.aliases[opt] = self.config.get(sec, opt) + else: + for opt in self.config.options(sec): + if not self.__dict__.has_key(opt): + self.__dict__[opt] = self.config.get(sec, opt) + + +def reader(ser): + while (1): + c = ser.read(1) + sys.stdout.write(c) + sys.stdout.flush() + +if __name__ == "__main__": + if (len(sys.argv) > 1): + port = sys.argv[1] + else: + port = None + + myshell = SerCmd(port) + myshell.prompt = '' + + myshell.cmdloop("Welcome to pyterm")