branch merge

This commit is contained in:
Stephan Zeisberg 2010-11-30 11:04:57 +01:00
commit 8264cde342
125 changed files with 4618 additions and 450 deletions

5
.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
*.o
doc/doxygen/html
doc/doxygen/latex
doc/doxygen/man
*bin

View File

@ -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) ;

View File

@ -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 ] ;

View File

@ -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 -
}

1
README
View File

@ -7,3 +7,4 @@ License
a separate license.
All code files contain licensing information.

View File

@ -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) ;

View File

@ -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 ] ;

View File

@ -201,7 +201,7 @@ void board_init() {
msp430_cpu_init();
msb_ports_init();
RED_ON;
LED_RED_ON;
msp430_set_cpu_speed(7372800uL);
}

View File

@ -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 <msp430x16x.h>
#include <bitarithm.h>
/* 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_ */

32
board/msb-430/Jamfile Normal file
View File

@ -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) ;

View File

@ -0,0 +1,3 @@
BOARD = msb-430 ;
include $(TOP)/board/msb-430-common/Jamrules.msb-430-common ;

View File

@ -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
*
<h2>Compontents</h2>
\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 <msp430x16x.h>
/** @} */
#endif // _MSB_BOARD_H

View File

@ -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) ;

View File

@ -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 ;

View File

@ -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 <msp430x16x.h>

View File

@ -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)" ;

View File

@ -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_ */

View File

@ -35,6 +35,7 @@ and the mailinglist (subscription via web site)
#include <stdio.h>
#include "lpc23xx.h"
#include "VIC.h"
#include <kernel.h>
#include <board_uart0.h>
@ -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<length;i++) {
while (!(U0LSR & BIT5));
U0THR = astring[i];
}
*/
/* */
return length;
}
@ -199,7 +202,8 @@ bl_uart_init(void)
/* irq */
install_irq(UART0_INT, UART0_IRQHandler, 6);
U0IER |= BIT0 | BIT1; // enable RX+TX irq
// U0IER |= BIT0 | BIT1; // enable RX+TX irq
U0IER |= BIT0; // enable only RX irq
return 1;
}

View File

@ -12,9 +12,11 @@ PSEUDOTERM_OBJS = ${addprefix obj/,${patsubst %.c,%.o,$(PSEUDOTERM_SRC)}}
TARGETDIR = bin
lpc2k_pgm: $(OBJS)
mkdir -p $(TARGETDIR)
$(CC) -o $(TARGETDIR)/lpc2k_pgm $(OBJS)
pseudoterm: $(PSEUDOTERM_OBJS)
mkdir -p $(TARGETDIR)
$(CC) -lpthread -o $(TARGETDIR)/pseudoterm $(PSEUDOTERM_OBJS)
chipinfo.o: boot_2xxx.h boot_23xx.h

View File

@ -78,8 +78,6 @@ int main(int argc, char **argv)
char* port_name = argv[1];
char* file_name = argv[2];
sleep(1);
if (open_serial_port(port_name) < 0) {
return(1);
}

View File

@ -1,135 +1,156 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <sys/ioctl.h>
#include <signal.h>
#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 <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <sys/ioctl.h>
#include <signal.h>
#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;
}

View File

@ -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 ;

View File

@ -15,8 +15,6 @@
#include <stdio.h>
#define ARCH_32_BIT (__INT_MAX__ == 2147483647)
unsigned
number_of_highest_bit(unsigned v)
{

43
core/cib.c Normal file
View File

@ -0,0 +1,43 @@
#include <cib.h>
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);
}
*/

View File

@ -16,18 +16,14 @@
*/
#include <stdio.h>
#include "hwtimer.h"
#include "hwtimer_cpu.h"
#include "hwtimer_arch.h"
#include <hwtimer.h>
#include <hwtimer_cpu.h>
#include <hwtimer_arch.h>
#include <bitarithm.h>
#define USE_NONBLOCKING_WAIT 1
#if USE_NONBLOCKING_WAIT
//#include <stdlib.h>
#include "kernel.h"
#include "mutex.h"
#endif
#include <kernel.h>
#include <thread.h>
/*---------------------------------------------------------------------------*/
@ -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 of waiting thread */
} hwtimer_wait_t;
#define HWTIMER_QUEUESIZE ARCH_MAXTIMERS
#define Q_FULL HWTIMER_QUEUESIZE + 1
#define HWTIMER_WAIT_BACKOFF (10)
static hwtimer_t timer[HWTIMER_QUEUESIZE];
static int queue[HWTIMER_QUEUESIZE];
@ -52,8 +54,8 @@ static volatile long available_timers = 0;
/*---------------------------------------------------------------------------*/
static int enqueue(int item) {
// Test if timer is already cleared:
// (hack to prevent race-condition with proccing timer (ISR) and manual hwtimer_remove)
/* Test if timer is already cleared:
* (hack to prevent race-condition with proccing timer (ISR) and manual hwtimer_remove) */
if (available_timers & (1 << item)) {
return 1;
}
@ -62,7 +64,8 @@ static int enqueue(int item) {
queue_tail = (queue_tail + 1) % HWTIMER_QUEUESIZE;
queue_items++;
if (queue_items == HWTIMER_QUEUESIZE) {
lpm_prevent_sleep &= ~LPM_PREVENT_SLEEP_HWTIMER; // Allow power down
/* Allow power down */
lpm_prevent_sleep &= ~LPM_PREVENT_SLEEP_HWTIMER;
}
return 1;
}
@ -71,10 +74,12 @@ static int dequeue(void) {
register int ret;
if (!queue_items)
return Q_FULL;
lpm_prevent_sleep |= LPM_PREVENT_SLEEP_HWTIMER; // No power down while a timer is active
/* No power down while a timer is active */
lpm_prevent_sleep |= LPM_PREVENT_SLEEP_HWTIMER;
queue_items--;
ret = queue[queue_head];
queue[queue_head] = 0xff; // Mark as empty
/* Mark as empty */
queue[queue_head] = 0xff;
available_timers &= ~(1 << ret);
queue_head = (queue_head + 1) % HWTIMER_QUEUESIZE;
return ret;
@ -85,8 +90,11 @@ static void multiplexer(int source) {
timer[source].callback(timer[source].data);
}
static void hwtimer_releasemutex(void* mutex) {
mutex_unlock((mutex_t*)mutex, true);
static void hwtimer_wakeup(void* hwt) {
((hwtimer_wait_t*)hwt)->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;
}

View File

@ -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

15
core/include/cib.h Normal file
View File

@ -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 */

View File

@ -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
/**

View File

@ -30,7 +30,7 @@
#define __HWTIMER_H
#include <stdint.h>
#include "hwtimer_cpu.h"
#include <hwtimer_cpu.h>
/**
* @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 */

View File

@ -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;

View File

@ -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 */

View File

@ -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;

View File

@ -17,33 +17,39 @@
#define TCB_H_
#include <stdint.h>
#include "queue.h"
#include "clist.h"
#include <queue.h>
#include <clist.h>
#include <cib.h>
#include <msg.h>
/* 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;

View File

@ -14,12 +14,15 @@
*/
#include <kernel.h>
#include <tcb.h>
/** 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.

View File

@ -17,6 +17,7 @@
#include <stdint.h>
#include <stdbool.h>
#include <errno.h>
<<<<<<< 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 <tcb.h>
#include <kernel.h>
#include <kernel_intern.h>
#include <sched.h>
#include <flags.h>
#include <cpu.h>
#include <lpm.h>
#include <thread.h>
#include <hwtimer.h>
>>>>>>> master
#ifdef MODULE_AUTO_INIT
#include <auto_init.h>
#endif
#define ENABLE_DEBUG
#include "debug.h"
#include <debug.h>
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");
}

View File

@ -20,32 +20,56 @@
#include "tcb.h"
#include <stddef.h>
#include <irq.h>
#include <cib.h>
#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;
}

View File

@ -20,6 +20,10 @@
#include "tcb.h"
#include "kernel.h"
#include "sched.h"
<<<<<<< HEAD
=======
#include <irq.h>
>>>>>>> master
//#define ENABLE_DEBUG
#include <debug.h>
@ -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
}

View File

@ -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;

View File

@ -14,15 +14,22 @@
*/
#include <stdint.h>
<<<<<<< HEAD:core/sched.c
#include <malloc.h>
#include "sched.h"
#include "kernel.h"
#include "kernel_intern.h"
#include "clist.h"
=======
#include <sched.h>
#include <kernel.h>
#include <kernel_intern.h>
#include <clist.h>
>>>>>>> master:core/sched.c
#include <bitarithm.h>
//#define ENABLE_DEBUG
#include "debug.h"
#include <debug.h>
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();
}

View File

@ -14,7 +14,6 @@
*/
#include <errno.h>
#include <malloc.h>
#include <stdio.h>
#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();

View File

@ -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 ;

254
cpu/arm_common/iap.c Normal file
View File

@ -0,0 +1,254 @@
/* iap driver
*
* based on iap driver for LPC2148 Controller made by Andreas Weschenfelder, 2008
* see:
*
*/
#include <iap.h>
#include <lpc2387.h>
#define ENABLE_DEBUG
#include <debug.h>
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);
}

View File

@ -0,0 +1,67 @@
#ifndef IAP_H_
#define IAP_H_
#include <stdint.h>
/* 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) //</ PLL Lock Status
/*
* @brief Erase sector
*
* @param addr Address within a flash sector to erase
*
* @return 1 on success, 0 otherwise
*/
uint8_t iap_erase(uint32_t addr);
/* @brief Write buffer from ram to flash
*
* @param dst Address within a flash sector to write, must be a 256 byte boundary
* @param src Address within ram, must be a word boundary
* @param size Bytes to write
*
* @return 1 on success, 0 otherwise
*/
uint8_t iap_write(uint32_t dst, char *src, uint32_t size);
/*
* @brief: Converts 'addr' to sector number
* @note: Sector table (Users Manual P. 610)
*
* @param addr Flash address
*
* @return Sector number. 0xFF on error
*/
uint8_t iap_get_sector(uint32_t addr);
#endif /*IAP_H_*/

View File

@ -27,7 +27,7 @@
SubDir TOP cpu lpc2387 ;
Module cpu : cpu.c lpc2387-lpm.c ;
Module cpu : cpu.c lpc2387-lpm.c lpc23xx-iap.c ;
UseModule cpu ;
Module rtc : lpc2387-rtc.c ;

View File

@ -68,7 +68,7 @@ and the mailinglist (subscription via web site)
* @{
*/
#ifndef KERNEL_CONF_STACKSIZE_DEFAULT
#define KERNEL_CONF_STACKSIZE_DEFAULT 2500
#define KERNEL_CONF_STACKSIZE_DEFAULT 4500
#endif
#define KERNEL_CONF_STACKSIZE_IDLE 500

View File

@ -51,7 +51,6 @@ and the mailinglist (subscription via web site)
#include <time.h>
#include <sys/time.h>
#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

View File

@ -9,8 +9,8 @@
#ifndef __LPC2387_H
#define __LPC2387_H
#include "lpc23xx.h"
#include "bitarithm.h"
#include <lpc23xx.h>
#include <bitarithm.h>
#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
* @{

View File

@ -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
**************************************************************************/

View File

@ -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 <stdio.h>
#define PRINTF(...) printf(__VA_ARGS__)
#else
#define PRINTF(...)
#endif
#define ENABLE_DEBUG 0
#include <debug.h>
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

View File

@ -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 <stdio.h>
#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 <debug.h>
/**
* @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 ) {

92
cpu/lpc2387/lpc23xx-iap.c Normal file
View File

@ -0,0 +1,92 @@
#include <stdint.h>
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;
}

View File

@ -1,6 +1,6 @@
#include <stdio.h>
#include "board.h"
#include "kernel_intern.h"
#include <board.h>
#include <kernel_intern.h>
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();
}

View File

@ -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

View File

@ -32,3 +32,4 @@ Module sht11 : sht11.c : hwtimer ;
Module ltc4150 : ltc4150.c : board_ltc4150 ;
SubInclude TOP drivers cc110x ;
SubInclude TOP drivers cc110x_ng ;

View File

@ -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

33
drivers/cc110x_ng/Jamfile Executable file
View File

@ -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 ;

View File

@ -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 <hwill@inf.fu-berlin.de>
* @version $Revision: 1775 $
*
* @note $Id: arch_cc1100.h 1775 2010-01-26 09:37:03Z hillebra $
*/
#include <stdint.h>
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);

View File

@ -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

View File

@ -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 <hillebra@inf.fu-berlin.de>
* @author Heiko Will <hwill@inf.fu-berlin.de>
* @version $Revision: 2058 $
*
* @note $Id: cc1100-defaultSettings.c 2058 2010-03-31 08:59:31Z hillebra $
*/
#include <cc1100-defaultSettings.h>
/**
* 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!
/** @} */

View File

@ -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 <hillebra@inf.fu-berlin.de>
* @author Heiko Will <hwill@inf.fu-berlin.de>
* @version $Revision: 2139 $
*
* @note $Id: cc1100-defaultSettings.h 2139 2010-05-26 08:04:04Z hillebra $
*/
#include <stdint.h>
// 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

View File

@ -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 <hillebra@inf.fu-berlin.de>
* @author Heiko Will <hwill@inf.fu-berlin.de>
* @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

View File

@ -0,0 +1,153 @@
#include <cc1100_ng.h>
#include <cc1100-internal.h>
#include <cc1100-config.h>
#include <cc1100-defaultSettings.h>
#include <cc1100_spi.h>
#include <hwtimer.h>
#include <msg.h>
#include <transceiver.h>
#include <board.h>
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;
}

View File

@ -0,0 +1,76 @@
#include <stdio.h>
#include <cc1100_ng.h>
#include <cc1100-defaultSettings.h>
#include <cc1100-internal.h>
#include <cc1100-arch.h>
#include <cc1100_spi.h>
#include <irq.h>
#include <board.h>
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;
}

302
drivers/cc110x_ng/cc1100.c Normal file
View File

@ -0,0 +1,302 @@
#include <cc1100_ng.h>
#include <cc1100-arch.h>
#include <cc1100-config.h>
#include <cc1100-defaultSettings.h>
#include <cc1100-internal.h>
#include <cc1100_spi.h>
#include <hwtimer.h>
//#define ENABLE_DEBUG (1)
#include <debug.h>
/* 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;
}

View File

@ -0,0 +1,122 @@
#ifndef CC1100_H
#define CC1100_H
#include <radio/radio.h>
#include <radio/types.h>
#include <stdint.h>
#include <cc1100-config.h>
#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
*
* <pre>
---------------------------------------------------
| | | | | |
| 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
</pre>
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

View File

@ -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 <hillebra@inf.fu-berlin.de>
* @author Heiko Will <hwill@inf.fu-berlin.de>
* @version $Revision: 1775 $
*
* @note $Id: cc1100_spi.c 1775 2010-01-26 09:37:03Z hillebra $
*/
#include <stdio.h>
#include <cc1100_ng.h>
#include <cc1100-arch.h>
#include <cc1100-internal.h>
#include <cc1100_spi.h>
#include <irq.h>
/*---------------------------------------------------------------------------*/
// 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;
}
/** @} */

View File

@ -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 <hillebra@inf.fu-berlin.de>
* @author Heiko Will <hwill@inf.fu-berlin.de>
* @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_ */

View File

@ -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 */

View File

@ -40,6 +40,7 @@ and the mailinglist (subscription via web site)
*
* @note $Id: sht11.h 667 2009-02-19 15:06:38Z baar $
*/
#include <stdint.h>
#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);

View File

@ -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;
}

View File

@ -37,7 +37,6 @@ and the mailinglist (subscription via web site)
* @note $Id: sht11.c 2396 2010-07-06 15:12:35Z ziegert $
*/
#include <assert.h>
#include <stdio.h>
#include <stdint.h>
@ -46,6 +45,11 @@ and the mailinglist (subscription via web site)
#include <sht11.h>
#include <sht11-board.h>
//#define ENABLE_DEBUG (1)
#include <debug.h>
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));

View File

@ -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);

11
projects/default/Jamfile Normal file
View File

@ -0,0 +1,11 @@
#
# ukleos default project. Consists of a shell.
#
# Copyright (C) 2008, 2009 Kaspar Schleiser <kaspar@schleiser.de>
#
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 ;

38
projects/default/main.c Normal file
View File

@ -0,0 +1,38 @@
/*
* Copyright (C) 2008, 2009, 2010 Kaspar Schleiser <kaspar@schleiser.de>
*/
#include <stdio.h>
#include <string.h>
#include <posix_io.h>
#include <ltc4150.h>
#include <shell.h>
#include <shell_commands.h>
#include <board_uart0.h>
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;
}

5
projects/laser/Jamfile Normal file
View File

@ -0,0 +1,5 @@
SubDir TOP projects laser ;
Module laser : main.c : sht11 swtimer auto_init ;
UseModule laser ;

30
projects/laser/main.c Normal file
View File

@ -0,0 +1,30 @@
#include <stdio.h>
#include <sht11.h>
#include <board.h>
#include <swtimer.h>
#include <ltc4150.h>
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);
}
}

View File

@ -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 ;

View File

@ -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;

View File

@ -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;

View File

@ -2,7 +2,7 @@
set timeout 5
spawn board/msba2/tools/bin/pseudoterm $env(PORT)
spawn pseudoterm $env(PORT)
expect {
"Hello World!" {}

View File

@ -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 ;

View File

@ -0,0 +1,129 @@
#include <stdio.h>
#include <string.h>
#include <shell.h>
#include <board_uart0.h>
#include <posix_io.h>
#include <thread.h>
#include <board.h>
#include <hwtimer.h>
#include <swtimer.h>
#include <msg.h>
#include <transceiver.h>
#include <cc1100_ng.h>
#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);
}
}

View File

@ -0,0 +1,13 @@
#!/usr/bin/expect
set timeout 5
spawn pseudoterm $env(PORT)
expect {
"Hello World!" {}
timeout { exit 1 }
}
puts "\nTest successful!\n"

View File

@ -0,0 +1,5 @@
SubDir TOP projects test_hwtimer ;
Module test_hwtimer : main.c : hwtimer ;
UseModule test_hwtimer ;

View File

@ -0,0 +1,29 @@
#include <stdio.h>
#include <hwtimer.h>
#include <kernel.h>
#include <board.h>
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.");
}

View File

@ -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!")

View File

@ -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;

View File

@ -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 ;

View File

@ -2,6 +2,7 @@
#include <thread.h>
#include <kernel.h>
#include <hwtimer.h>
#include <ps.h>
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();
}
}

View File

@ -0,0 +1,12 @@
#
# Copyright (C) 2008, 2009, 2010 FU Berlin
#
# Author: Kaspar Schleiser <kaspar.schleiser@fu-berlin.de>
#
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 ;

View File

@ -0,0 +1,30 @@
#include <stdio.h>
#include <mutex.h>
#include <thread.h>
#include <flags.h>
#include <kernel.h>
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.");
}

View File

@ -0,0 +1,58 @@
/*
* Copyright (C) 2008, 2009, 2010 Kaspar Schleiser <kaspar@schleiser.de>
*/
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <posix_io.h>
#include <shell.h>
#include <board_uart0.h>
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;
}

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -0,0 +1,39 @@
#include <stdio.h>
#include <thread.h>
#include <kernel.h>
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);
}
}
}

View File

@ -0,0 +1,5 @@
SubDir TOP projects expect_swtimer ;
Module expect_swtimer : main.c : swtimer ;
UseModule expect_swtimer ;

Some files were not shown because too many files have changed in this diff Show More