* integrated makefiles

* fixed some prototypes
* restructured sys
This commit is contained in:
Oleg Hahm 2013-02-06 13:20:21 +01:00
parent 784ef52390
commit 3791039974
52 changed files with 3531 additions and 43 deletions

View File

@ -17,10 +17,10 @@
#define KERNEL_INTERN_H_
void kernel_init(void);
void board_init_drivers();
void board_init_drivers(void);
char *thread_stack_init(void *task_func, void *stack_start);
void sched_task_exit(void);
void thread_print_stack ();
void thread_print_stack (void);
int thread_measure_stack_usage(char* stack);
/** @} */

View File

@ -21,8 +21,8 @@
#define SCHED_PRIO_LEVELS 16
#endif
void sched_init();
void sched_run();
void sched_init(void);
void sched_run(void);
void sched_set_status(tcb_t *process, unsigned int status);
void sched_switch(uint16_t current_prio, uint16_t other_prio, int in_isr);

View File

@ -46,7 +46,7 @@ unsigned int thread_getstatus(int pid);
/**
* @brief Puts the current thread into sleep mode. Has to be woken up externally.
*/
void thread_sleep();
void thread_sleep(void);
/**
* @brief Wakes up a sleeping thread.
@ -60,13 +60,13 @@ int thread_wakeup(int pid);
* @brief Returns the process ID of the currently running thread.
* @return Obviously you are not a golfer.
*/
int thread_getpid();
int thread_getpid(void);
/**
* @brief Returns the process ID of the thread running before the current one.
* @return Obviously you are not a golfer.
*/
int thread_getlastpid();
int thread_getlastpid(void);
/**
* @brief Measures the stack usage of a stack.

5
core/makefile Normal file
View File

@ -0,0 +1,5 @@
MODULE =core
INCLUDES = -Iinclude/ -I../sys/include -I../sys/lib -I../sys/drivers/include -I../cpu/$(CPU)/include/ -I../..
include $(RIOTBASE)/makefile.base

View File

@ -40,7 +40,7 @@ int mutex_trylock(struct mutex_t* mutex) {
return (atomic_set_return(&mutex->val, thread_pid ) == 0);
}
int prio() {
int prio(void) {
return active_thread->priority;
}

View File

@ -23,12 +23,12 @@
#define ENABLE_DEBUG
#include <debug.h>
extern void *sbrk(int incr);
//extern void *sbrk(int incr);
void *_malloc(size_t size) {
void* ptr = sbrk(size);
DEBUG("_malloc(): allocating block of size %u at 0x%X.\n", size, (unsigned int)ptr);
DEBUG("_malloc(): allocating block of size %u at 0x%X.\n", (unsigned int) size, (unsigned int)ptr);
if (ptr != (void*)-1) {
return ptr;

View File

@ -17,7 +17,6 @@ along with Micro-Mesh; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include "board.h"
#include "VIC.h"
#include <stdbool.h>

View File

@ -8,10 +8,10 @@
#define NEW_TASK_CPSR 0x1F
#define WORDSIZE 32
extern void dINT();
extern void eINT();
extern void dINT(void);
extern void eINT(void);
void thread_yield();
void thread_yield(void);
uint32_t get_system_speed(void);
void cpu_clock_scale(uint32_t source, uint32_t target, uint32_t* prescale);

7
cpu/arm_common/makefile Normal file
View File

@ -0,0 +1,7 @@
MODULE =arm_common
INCLUDES = -Iinclude -I../$(CPU)/include -I../../sys/lib -I../../drivers/include -I../../core/include -I../../sys/include -I../../hal/include -I../../.. -I../../sys/lib/fat
include $(RIOTBASE)/makefile.base

13
cpu/cc430/makefile Normal file
View File

@ -0,0 +1,13 @@
MODULE =cpu
INCLUDES = -Iinclude -Idrivers/include -I../arm_common/include -I../../sys/lib -I../../sys/drivers/include -I../../core/include -I../../sys/include -I../../hal/include -I../../..
DIRS =
all: $(BINDIR)$(MODULE).a
@for i in $(DIRS) ; do $(MAKE) -C $$i ; done ;
include $(RIOTBASE)/makefile.base
clean::
@for i in $(DIRS) ; do $(MAKE) -C $$i clean ; done ;

32
cpu/lpc214x/makefile Normal file
View File

@ -0,0 +1,32 @@
SRC = blocklist.c kernel_init.c msg.c scheduler.c blocklist_malloc.c ktimer.c mutex.c thread.c clist.c queue.c
OBJ = $(SRC:%.c=../bin/%.o)
INCLUDES = -Iinclude/ -I../sys/include -I../sys/lib -I../sys/drivers/include -I../cpu/$(CPU)/include/
ifeq ($(CPU),lpc2387)
INCLUDES += -I../cpu/arm_common/include/
CPUINCLUDE = -includecpu-conf.h
endif
ifeq ($(CPU),lpc214x)
INCLUDES += -I../cpu/arm_common/include/
endif
../bin/core.a: $(OBJ)
$(AR) rcs ../bin/core.a $(OBJ)
# pull in dependency info for *existing* .o files
-include $(OBJ:.o=.d)
# compile and generate dependency info
../bin/%.o: %.c
$(CC) $(CFLAGS) $(INCLUDES) $(BOARDINCLUDE) $(PROJECTINCLUDE) $(CPUINCLUDE) -c $*.c -o ../bin/$*.o
$(CC) $(CFLAGS) $(INCLUDES) $(BOARDINCLUDE) $(PROJECTINCLUDE) $(CPUINCLUDE) -MM $*.c > ../bin/$*.d
@printf "../bin/"|cat - ../bin/$*.d > /tmp/fw_out && mv /tmp/fw_out ../bin/$*.d
# remove compilation products
clean:
rm -f ../bin/core.a ../bin/*.o ../bin/*.d

View File

@ -43,7 +43,6 @@ and the mailinglist (subscription via web site)
#include <stdio.h>
#include <stdint.h>
#include "board.h"
#include "lpc23xx.h"
#include "lpc2387.h"
#include "lpm.h"

13
cpu/lpc2387/makefile Normal file
View File

@ -0,0 +1,13 @@
MODULE =cpu
INCLUDES = -Iinclude -Idrivers/include -I../arm_common/include -I../../sys/lib -I../../drivers/include -I../../core/include -I../../sys/include -I../../hal/include -I../../..
DIRS =
all: $(BINDIR)$(MODULE).a
@for i in $(DIRS) ; do $(MAKE) -C $$i ; done ;
include $(RIOTBASE)/makefile.base
clean::
@for i in $(DIRS) ; do $(MAKE) -C $$i clean ; done ;

29
cpu/makefile Normal file
View File

@ -0,0 +1,29 @@
ifeq ($(CPU),lpc2387)
DIRS = arm_common lpc2387
endif
ifeq ($(CPU),lpc214x)
DIRS = arm_common lpc214x
endif
ifeq ($(CPU),cc430)
DIRS = msp430 cc430
endif
.PHONY: cpus
.PHONY: $(DIRS)
cpus: $(DIRS)
$(DIRS):
@$(MAKE) -C $@
clean:
@$(MAKE) -C lpc2387 clean
@$(MAKE) -C arm_common clean
@$(MAKE) -C cc430 clean
@$(MAKE) -C msp430-common clean
@$(MAKE) -C msp430x16x clean

View File

@ -0,0 +1,13 @@
MODULE =cpu
INCLUDES = -Iinclude -Idrivers/include -I../arm_common/include -I../../sys/lib -I../../sys/drivers/include -I../../core/include -I../../sys/include -I../../hal/include -I../../..
DIRS =
all: $(BINDIR)$(MODULE).a
@for i in $(DIRS) ; do $(MAKE) -C $$i ; done ;
include $(RIOTBASE)/makefile.base
clean::
@for i in $(DIRS) ; do $(MAKE) -C $$i clean ; done ;

7
drivers/cc110x/makefile Normal file
View File

@ -0,0 +1,7 @@
INCLUDES = -I../../include -I../../net -I../include -I../../lib -I../../../.. -I../../../cpu/ -I../../../core/include -I../../
MODULE =cc110x
include $(MAKEBASE)/makefile.base

View File

@ -0,0 +1,5 @@
INCLUDES = -I../../include -I../../net -I../include -I../../lib -I../../../.. -I../../../cpu/ -I../../../core/include -I../../ -Iinclude/
MODULE =cc110x_ng
include $(MAKEBASE)/makefile.base

View File

@ -3,15 +3,15 @@
#include <ltc4150_arch.h>
void ltc4150_init();
void ltc4150_start();
void ltc4150_stop();
void ltc4150_init(void);
void ltc4150_start(void);
void ltc4150_stop(void);
double ltc4150_get_current_mA();
double ltc4150_get_total_mAh();
double ltc4150_get_current_mA(void);
double ltc4150_get_total_mAh(void);
double ltc4150_get_total_Joule(void);
double ltc4150_get_avg_mA();
int ltc4150_get_interval();
double ltc4150_get_avg_mA(void);
int ltc4150_get_interval(void);
long ltc4150_get_intcount(void);
#endif /* __LTC4150_H */

View File

@ -52,7 +52,7 @@ void ltc4150_disable_int(void);
void ltc4150_enable_int(void);
void ltc4150_sync_blocking(void);
void ltc4150_arch_init(void);
void ltc4150_interrupt();
void ltc4150_interrupt(void);
/** @} */
#endif /* __LTC4150_ARCH_H */

5
drivers/ltc4150/makefile Normal file
View File

@ -0,0 +1,5 @@
INCLUDES = -I../../include -I../../lib -I../../../cpu/$(CPU)/include -I../../../cpu/ -I../../../hal/include -I../../../core/include -I../../config -I../include
MODULE =ltc4150
include $(MAKEBASE)/makefile.base

36
drivers/makefile Normal file
View File

@ -0,0 +1,36 @@
DIRS=
ifneq (,$(findstring powermon,$(USEMODULE)))
DIRS += powermon
endif
ifneq (,$(findstring sht11,$(USEMODULE)))
DIRS += sht11
endif
ifneq (,$(findstring ltc4150,$(USEMODULE)))
DIRS += ltc4150
endif
ifneq (,$(findstring cc110x,$(USEMODULE)))
ifneq (,$(findstring cc110x_ng,$(USEMODULE)))
DIRS += cc110x_ng
else
DIRS += cc110x
endif
endif
ifneq (,$(findstring gps_ublox,$(USEMODULE)))
DIRS += gps_ublox
endif
ifneq (,$(findstring cc110x_ng,$(USEMODULE)))
DIRS += cc110x_ng
endif
all:
@for i in $(DIRS) ; do $(MAKE) -C $$i ; done ;
include $(RIOTBASE)/makefile.base
# remove compilation products
clean::
@for i in $(DIRS) ; do $(MAKE) -C $$i clean ; done ;

5
drivers/sht11/makefile Normal file
View File

@ -0,0 +1,5 @@
INCLUDES = -I../../include -I../../lib -I../../../cpu/$(CPU)/include -I../../../cpu/ -I../../../hal/include -I../../../core/include -I../../config -I../include
MODULE =sht11
include $(MAKEBASE)/makefile.base

9
makefile Normal file
View File

@ -0,0 +1,9 @@
DIRS = cpu core drivers sys
all:
@for i in $(DIRS) ; do $(MAKE) -C $$i ; done ;
clean:
@for i in $(DIRS) ; do $(MAKE) -C $$i clean ; done ;

42
makefile.base Normal file
View File

@ -0,0 +1,42 @@
ASMSRC = $(wildcard *.s)
ASMOBJ = $(ASMSRC:%.s=$(BINDIR)%.o)
SRC = $(wildcard *.c)
OBJ = $(SRC:%.c=$(BINDIR)%.o)
DEP = $(SRC:%.c=$(BINDIR)%.d)
ifeq ($(CPU),lpc2387)
INCLUDES += -I$(MAKEBASE)/cpu/arm_common/include/
INCLUDES += -I$(MAKEBASE)/cpu/lpc2387/include
endif
ifeq ($(CPU),lpc214x)
INCLUDES += -I$(MAKEBASE)/cpu/arm_common/include/
INCLUDES += -I$(MAKEBASE)/cpu/lpc214x/include
endif
ifeq ($(CPU),msp430x16x)
INCLUDES += -I$(MAKEBASE)/cpu/msp430-common/include/
INCLUDES += -I$(MAKEBASE)/cpu/msp430x16x/include/
endif
ifeq ($(CPU),cc430)
INCLUDES += -I$(MAKEBASE)/cpu/msp430-common/include/
INCLUDES += -I$(MAKEBASE)/cpu/cc430/include/
endif
$(BINDIR)$(MODULE).a: $(OBJ) $(ASMOBJ)
$(AR) -rc $(BINDIR)$(MODULE).a $(OBJ) $(ASMOBJ)
# pull in dependency info for *existing* .o files
-include $(OBJ:.o=.d)
# compile and generate dependency info
$(BINDIR)%.o: %.c
$(CC) $(CFLAGS) $(PROJECTINCLUDE) $(BOARDINCLUDE) $(INCLUDES) -c $*.c -o $(BINDIR)$*.o
$(CC) $(CFLAGS) $(PROJECTINCLUDE) $(BOARDINCLUDE) $(INCLUDES) -MM $*.c > $(BINDIR)$*.d
@printf "$(BINDIR)"|cat - $(BINDIR)$*.d > /tmp/riot_out && mv /tmp/riot_out $(BINDIR)$*.d
$(BINDIR)%.o: %.s
$(AS) $(ASFLAGS) $*.s -o $(BINDIR)$*.o
# remove compilation products
clean::
rm -f $(BINDIR)$(MODULE).a $(OBJ) $(DEP) $(ASMOBJ)

26
makefile.modules Normal file
View File

@ -0,0 +1,26 @@
export MAKEBASE =$(RIOTBASE)
export BINDIR =$(RIOTBASE)/bin/
#UNDEF = $(BINDIR)startup.o $(BINDIR)builddate.o
UNDEF = $(BINDIR)startup.o
### Minimal setup
ifeq ($(CPU),lpc2387)
USEMODULE += arm_common
UNDEF += $(BINDIR)syscalls.o
endif
ifeq ($(CPU),lpc214x)
USEMODULE += arm_common
UNDEF += $(BINDIR)syscalls.o
endif
ifeq ($(CPU),cc430)
USEMODULE += cpu core lib sys
else
#USEMODULE += cpu_drivers cpu core lib sys
USEMODULE += cpu core sys
endif
ED = $(USEMODULE:%=-D MODULE_%)
EXTDEFINES = $(shell echo $(ED)|tr 'a-z' 'A-Z')
export BASELIBS=$(USEMODULE:%= $(BINDIR)%.a)
CFLAGS += $(EXTDEFINES)
export USEMODULE

View File

@ -1,13 +1,13 @@
#include "radio/radio.h"
void init_payload();
void init_payload(void);
void ping_init(protocol_t protocol, uint8_t channr, radio_address_t addr);
void ping(radio_address_t addr, uint8_t channr);
void calc_rtt();
void print_success();
void print_failed();
void gpio_n_timer_init();
void adjust_timer();
void calc_rtt(void);
void print_success(void);
void print_failed(void);
void gpio_n_timer_init(void);
void adjust_timer(void);
static void ping_handler(void *payload, int payload_size,
packet_info_t *packet_info);
static void pong_handler(void *payload, int payload_size,

View File

@ -65,13 +65,13 @@ typedef struct swtimer_t {
* @brief Current system time
* @return Time in ticks since system boot
*/
swtime_t swtimer_now();
swtime_t swtimer_now(void);
/**
* @brief Initializes swtimer
* @return always 0
*/
int swtimer_init();
int swtimer_init(void);
/**
* @brief set swtimer interval and activate

View File

@ -43,14 +43,14 @@ typedef struct vtimer_t {
* @brief Current system time
* @return Time as timex_t since system boot
*/
timex_t vtimer_now();
timex_t vtimer_now(void);
/**
* @brief Initializes the vtimer subsystem. To be called once at system initialization. Will be initialized by auto_init.
*
* @return always 0
*/
int vtimer_init();
int vtimer_init(void);
/**
* @brief will cause the calling thread to be suspended from excecution until the number of microseconds has elapsed

6
sys/lib/makefile Normal file
View File

@ -0,0 +1,6 @@
INCLUDES = -I../include -I../drivers/include -I../lib -I../../cpu/$(CPU)/include -I../../cpu/ -I../lib/cmdengine -I../net -I../../hal/include -I../../core/include -I../config
MODULE =shell
include $(RIOTBASE)/makefile.base

193
sys/logd/logd.c Normal file
View File

@ -0,0 +1,193 @@
/******************************************************************************
Copyright 2009-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 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
* @brief Simple logging demon implementation
*
* @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project
* @author Thomas Hillebrandt <hillebra@inf.fu-berlin.de>
* @version $Revision: 3854 $
*
* @note $Id: logd.c 3854 2011-12-06 15:27:01Z hwill $
*/
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
// core
#include "msg.h"
#include "flags.h"
#include "mutex.h"
#include "thread.h"
#include "kernel.h"
// system
#include "logd.h"
#include "list.h"
typedef struct log_queue_t
{
list_node_t listnode;
char* str;
int str_len;
} log_queue_t;
static volatile int log_pid = -1;
static int logd_stack_size = LOGD_STACK_SIZE_NORMAL;
static FILE* fh = NULL;
static int log_count = 0;
static mutex_t log_mutex;
static list_t log_msg_queue;
static volatile bool exit_flag = false;
static volatile bool echo_on = false;
/*---------------------------------------------------------------------------*/
static void close_file_handle(void)
{
if (fh != NULL) {
fclose(fh);
fh = NULL;
}
}
static void write_to_file(char* str, int str_len)
{
if (fh != NULL && str_len > 0) {
if (fwrite(str, sizeof(char), str_len, fh) != str_len) {
if (echo_on && logd_stack_size >= LOGD_STACK_SIZE_CONSOLE) {
printf("LOGD [WARN]: file write failed, closing file\n");
}
close_file_handle();
return;
}
if (fflush(fh) == EOF) {
if (echo_on && logd_stack_size >= LOGD_STACK_SIZE_CONSOLE) {
printf("LOGD [WARN]: file write failed, closing file\n");
}
close_file_handle();
return;
}
} else {
fh = fopen("/LOGD.LOG", "w");
if (!fh) {
if (echo_on && logd_stack_size >= LOGD_STACK_SIZE_CONSOLE) {
printf("LOGD [WARN]: file reopen failed, damn!\n");
}
} else {
write_to_file(str, str_len);
}
}
}
static void logd_process(void)
{
msg m;
log_queue_t* node;
do
{
if (!exit_flag) msg_receive(&m);
mutex_lock(&log_mutex);
while ((node = (log_queue_t*) list_remove_head(&log_msg_queue)) != NULL) {
write_to_file(node->str, node->str_len);
if (echo_on && logd_stack_size >= LOGD_STACK_SIZE_CONSOLE) {
printf("%s", node->str);
}
log_count++;
free(node->str);
free(node);
}
mutex_unlock(&log_mutex, 0);
} while (m.type != MSG_EXIT && !exit_flag);
/* Logging thread is terminating, close log file */
close_file_handle();
}
/*---------------------------------------------------------------------------*/
static void logd_init0(void) {
fh = fopen("/LOGD.LOG", "w");
if (!fh) return;
log_pid = thread_create(logd_stack_size, PRIORITY_LOGD, CREATE_STACKTEST, logd_process, "logd");
}
void logd_init(int stack_size)
{
logd_stack_size = stack_size;
mutex_init(&log_mutex);
list_init(&log_msg_queue);
logd_init0();
}
void logd_set_console_enabled(bool enabled)
{
echo_on = enabled;
}
bool logd_log(char* str, int str_len)
{
msg m;
// Test if logd process was created
if (log_pid == -1) {
// no logd created, because fopen() on log file failed. So try again
logd_init0();
if (log_pid == -1) {
// Still errors opening log file, exit now
return false;
}
}
log_queue_t* lq = malloc(sizeof(*lq));
if (lq == NULL) return false;
lq->str = malloc(sizeof(char) * str_len + 1); // 1 byte for string termination char
if (lq->str == NULL) {
free(lq);
return false;
}
strncpy(lq->str, str, str_len);
lq->str_len = str_len;
lq->str[str_len] = '\0'; // add string termination char at end of buffer
mutex_lock(&log_mutex);
list_append(&log_msg_queue, (list_node_t*) lq);
mutex_unlock(&log_mutex, 0);
m.type = MSG_POLL;
m.content.ptr = NULL;
msg_send(&m, log_pid, false);
return true;
}
void logd_exit(void)
{
msg m;
// Test if logd process was created
if (log_pid == -1) {
return;
}
exit_flag = true;
m.type = MSG_EXIT;
m.content.ptr = NULL;
msg_send(&m, log_pid, false);
}

7
sys/logd/makefile Normal file
View File

@ -0,0 +1,7 @@
INCLUDES = -I../include -I../drivers/include -I../lib -I../../cpu/$(CPU)/include -I../../cpu/ -I../lib/cmdengine -I../net -I../../hal/include -I../../core/include -I../config
MODULE =logd
include $(MAKEBASE)/makefile.base

58
sys/makefile Normal file
View File

@ -0,0 +1,58 @@
INCLUDES = -Iinclude -I$(RIOTBASE)/drivers/ -I$(RIOTBASE)/drivers/include -Ilib -I../.. -I../cpu/$(CPU)/include -I../cpu/ -Ilib/cmdengine -Inet -I../hal/include -I../core/include -Iconfig
MODULE =sys
ifneq (,$(findstring config,$(USEMODULE)))
DIRS += config
endif
ifneq (,$(findstring net,$(USEMODULE)))
DIRS += net
endif
ifneq (,$(findstring lib,$(USEMODULE)))
DIRS += lib
endif
ifneq (,$(findstring logd,$(USEMODULE)))
DIRS += logd
endif
ifneq (,$(findstring cmdd,$(USEMODULE)))
DIRS += cmdd
endif
ifneq (,$(findstring mprint,$(USEMODULE)))
DIRS += mprint
endif
ifneq (,$(findstring sync_read,$(USEMODULE)))
DIRS += sync_read
endif
ifneq (,$(findstring syslog,$(USEMODULE)))
DIRS += syslog
endif
ifneq (,$(findstring sysmon,$(USEMODULE)))
DIRS += sysmon
endif
ifneq (,$(findstring utimer,$(USEMODULE)))
DIRS += utimer
endif
ifneq (,$(findstring mqueue,$(USEMODULE)))
DIRS += mqueue
endif
ifneq (,$(findstring shell,$(USEMODULE)))
DIRS += shell
endif
ifneq (,$(findstring tracelog,$(USEMODULE)))
DIRS += tracelog
endif
ifneq (,$(findstring transceiver,$(USEMODULE)))
DIRS += transceiver
endif
all: $(BINDIR)$(MODULE).a
@for i in $(DIRS) ; do $(MAKE) -C $$i ; done ;
include $(RIOTBASE)/makefile.base
# remove compilation products
clean::
@for i in $(DIRS) ; do $(MAKE) -C $$i clean ; done ;

31
sys/net/mm/Jamfile Normal file
View File

@ -0,0 +1,31 @@
# ******************************************************************************
# 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: Jamfile 1253 2009-08-25 10:31:47Z hillebra $
SubDir TOP sys net mm ;
Module net_mm : mmr.c mmstack.c : net_kernel ;

6
sys/net/mm/makefile Normal file
View File

@ -0,0 +1,6 @@
INCLUDES = -I.. -I../../include -I../../drivers/include -I../../../core/include -I../../lib -I../../lib/cmdengine -I../../../hal/include
MODULE =net_mm
include $(MAKEBASE)/makefile.base

907
sys/net/mm/mmr.c Normal file
View File

@ -0,0 +1,907 @@
/******************************************************************************
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
*******************************************************************************/
/**
* @file
* @internal
* @brief Micro Mesh Routing
*
* @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project
* @author Thomas Hillebrandt <hillebra@inf.fu-berlin.de>
* @version $Revision: 3854 $
*
* @note $Id: mmr.c 3854 2011-12-06 15:27:01Z hwill $
*/
#include "configure.h"
#include "mmr.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "net.h"
#include "clock.h"
#include "utimer.h"
#include "kernel.h"
#include "thread.h"
#include "msg.h"
#define LEVEL_INFO 2 ///< All messages are printed
#define LEVEL_WARN 1 ///< Only warnings and error messages are printed
#define LEVEL_ERROR 0 ///< Only error messages are printed
#define MMR_INFO_LEVEL LEVEL_WARN ///< Current information level
#define DEBUG(...)
//#define DEBUG(...) printf(__VA_ARGS__)
#define CONSTANT_SECOND (1)
#define RREQ_ID_SEQUENCE_NUMBER_START (1)
#define RREQ_THRESHOLD (3)
#define RREQ_NONE (0xFF) // Send no RREQs for these messages, value
// must be greater than RREQ_THRESHOLD
#define TTL_START (1)
#define TTL_THRESHOLD (10)
#define RREQ_TIMEOUT_BASE (2*CONSTANT_SECOND)
#define RREQ_TIMEOUT_PER_TTL (1*CONSTANT_SECOND)
/*---------------------------------------------------------------------------*/
// Message queue data structures
/*---------------------------------------------------------------------------*/
#define MESSAGE_QUEUE_SIZE (20)
typedef struct message_queue_entry_t
{
net_message_t message;
volatile uint32_t timestamp;
uint8_t retry_count;
} message_queue_entry_t;
static message_queue_entry_t message_queue[MESSAGE_QUEUE_SIZE];
/*---------------------------------------------------------------------------*/
// RREQ-Timeout data structures
/*---------------------------------------------------------------------------*/
static struct utimer ut;
static volatile bool rreq_to_active = false; // RREQ timeout active bit
static const char *rreq_timeout_process_name = "mmrd";
static uint16_t rreq_timeout_process_pid;
static void rreq_timeout_process(void);
static void post_next_rreq_timeout(void);
/*---------------------------------------------------------------------------*/
// Statistic data structures
/*---------------------------------------------------------------------------*/
typedef struct mmr_stat
{
uint32_t rreq_originated;
uint32_t rrep_originated;
uint32_t rerr_originated;
uint32_t rreq_received;
uint32_t rrep_received;
uint32_t rerr_received;
uint32_t messages_no_route_found; // RREQ found no route
uint32_t messages_no_route_avail_on_forward; // Forwarding: no route in route table
uint32_t messages_broken_link_on_forward; // Forwarding: broken link detected
uint32_t rreq_duplicated;
} mmr_stat_t;
static mmr_stat_t mmr_stats;
/*---------------------------------------------------------------------------*/
/**
* Returns time of RTC in seconds.
*
* @return Time of RTC in seconds
*/
static uint32_t rtc_now(void)
{
return (uint32_t)(clock_get_systemtime()/1000);
}
/*---------------------------------------------------------------------------*/
// Routing table management
/*---------------------------------------------------------------------------*/
/**
* @brief Extract route information and store them in route table.
*
* @param local_addr Local network address of this node
* @param length Length of address list
* @param list Address list with route information
*/
static void rt_extract_routes(uint16_t local_addr, uint8_t length, uint16_t* list)
{
DEBUG("call [%u]: rt_extract_routes\n", fk_thread->pid);
uint16_t net_id = NETWORK_ADDR_BC(list[0]); // BC address of source of RREQ
route_table_entry_t* rte = rt_lookup_route(net_id); // Should exist (preconfigured)
if (rte == NULL) {
DEBUG("exit [%u]: rt_extract_routes\n", fk_thread->pid);
return; // else exit here
}
int i = 0;
while (i < length && list[i] != local_addr) i++;
if (i == length) {
DEBUG("exit [%u]: rt_extract_routes\n", fk_thread->pid);
return;
}
int pos = i;
int leftNeighbour = -1;
int rightNeighbour = -1;
if (pos > 0)
{
leftNeighbour = list[pos-1];
}
if (pos+1 != length)
{
rightNeighbour = list[pos+1];
}
i = 0;
while (i < length)
{
uint16_t next = list[i];
if (local_addr != next)
{
int distance = pos - i;
int router = leftNeighbour;
if (distance < 0) { router = rightNeighbour; distance *= -1; }
rt_add_route(next, (uint16_t)router, (uint8_t)distance, rte->interface_id);
}
i++;
}
DEBUG("exit [%u]: rt_extract_routes\n", fk_thread->pid);
}
/*---------------------------------------------------------------------------*/
// Message queue management
/*---------------------------------------------------------------------------*/
/**
* @brief Add a message to the message queue.
*
* @param msg The packet to add to the queue
*
* @return A pointer to a message queue entry or NULL if
* message queue is full.
*/
static message_queue_entry_t* mq_add(net_message_t* msg)
{
DEBUG("call [%u]: mq_add\n", fk_thread->pid);
// Holds eventually first active RREQ to same destination
message_queue_entry_t* pFirstFoundDup = NULL;
// Find the first active RREQ to this destination
int i;
for (i = 0; i < MESSAGE_QUEUE_SIZE; i++)
{
if (message_queue[i].timestamp != 0 && message_queue[i].message.destination == msg->destination &&
message_queue[i].retry_count != RREQ_NONE)
{
DEBUG("%s FOUND Duplicated Request to %u.%u in route req queue\n",__FUNCTION__,(0xFF00&msg->destination)>>8,(0xFF&msg->destination));
// Save the first found entry to modify later if insertion was successful
pFirstFoundDup = &message_queue[i];
break;
}
}
// If RREQ for same destination found then reset values
// even if the new message will get dropped later on because of
// limited queue space. Route to this destination gets queried
// again for sure so make new RREQ as soon as possible...
if (pFirstFoundDup != NULL) {
pFirstFoundDup->retry_count = 0;
pFirstFoundDup->timestamp = 1;
mmr_stats.rreq_duplicated++;
}
// Find free position to insert new message
for (i = 0; i < MESSAGE_QUEUE_SIZE; i++)
{
if (message_queue[i].timestamp == 0)
{
// Free position found, add entry
message_queue[i].message = *msg;
if (pFirstFoundDup != NULL) {
// There is already a RREQ for this destination, so don't generate a new one
message_queue[i].retry_count = RREQ_NONE;
} else {
// Set initial RREQ retry counter to zero
message_queue[i].retry_count = 0;
}
message_queue[i].timestamp = 1;
DEBUG("exit [%u]: mq_add\n", fk_thread->pid);
return &message_queue[i];
}
}
DEBUG("exit [%u]: mq_add\n", fk_thread->pid);
return NULL;
}
/**
* @brief Count messages for given destination.
*
* @param dst Destination address
*
* @return The number of messages for the destination.
*/
static int mq_msgs_for_destination(uint16_t dst)
{
DEBUG("call [%u]: mq_msgs_for_destination\n", fk_thread->pid);
int i, dst_count = 0;
for (i = 0; i < MESSAGE_QUEUE_SIZE; i++)
{
if (message_queue[i].timestamp != 0 && message_queue[i].message.destination == dst)
{
dst_count++;
}
}
DEBUG("exit [%u]: mq_msgs_for_destination\n", fk_thread->pid);
return dst_count;
}
/**
* @brief Remove all messages for given destination out of message queue.
*
* @param dst Destination address
*/
static void mq_remove_msgs_for_destination(uint16_t dst)
{
DEBUG("call [%u]: mq_remove_msgs_for_destination\n", fk_thread->pid);
int i;
for (i = 0; i < MESSAGE_QUEUE_SIZE; i++)
{
if (message_queue[i].timestamp != 0 && message_queue[i].message.destination == dst)
{
message_queue[i].timestamp = 0;
}
}
DEBUG("exit [%u]: mq_remove_msgs_for_destination\n", fk_thread->pid);
}
/**
* @brief Send all queued messages for given destination.
*
* @param dst Destination address
*/
static void mq_dequeue_and_send(uint16_t dst)
{
int i;
DEBUG("call [%u]: mq_dequeue_and_send\n", fk_thread->pid);
// Stop any pending RREQ-Timeout, it's possibly handled now
rreq_to_active = false;
utimer_remove(&ut);
// Prioritize packets for given destination, route entry should exist
route_table_entry_t* rte = rt_lookup_route(dst);
if (rte != NULL)
{
for (i = 0; i < MESSAGE_QUEUE_SIZE; i++)
{
if (message_queue[i].timestamp != 0 && message_queue[i].message.destination == dst)
{
bool res = net_enqueue_for_transmission(&message_queue[i].message, rte->interface_id, rte->gateway, true);
if (res) message_queue[i].timestamp = 0;
}
}
}
// Now all other packets
for (i = 0; i < MESSAGE_QUEUE_SIZE; i++)
{
if (message_queue[i].timestamp != 0 && message_queue[i].message.destination != dst)
{
route_table_entry_t* rte = rt_lookup_route(message_queue[i].message.destination);
if (rte != NULL)
{
bool res = net_enqueue_for_transmission(&message_queue[i].message, rte->interface_id, rte->gateway, true);
if (res) message_queue[i].timestamp = 0;
}
}
}
// This function was triggered either by RREP packet or RREQ-Timeout.
// So update or set new RREQ-Timeout for other packets in queue.
post_next_rreq_timeout();
DEBUG("exit [%u]: mq_dequeue_and_send\n", fk_thread->pid);
}
/*---------------------------------------------------------------------------*/
// Initialization of MMR layer
/*---------------------------------------------------------------------------*/
void mmr_init(void)
{
rt_init();
memset(message_queue, 0, sizeof(message_queue_entry_t) * MESSAGE_QUEUE_SIZE);
rreq_timeout_process_pid = thread_create(2500, PRIORITY_MMREQ, CREATE_STACKTEST,
rreq_timeout_process, rreq_timeout_process_name);
}
/*---------------------------------------------------------------------------*/
// Send & receive functions
/*---------------------------------------------------------------------------*/
/**
* @brief Tests if the net message contains a RERR.
*
* @param msg The net message to test
*
* @return true if the net message contains a RERR; false otherwise.
*/
static bool is_route_error(net_message_t* msg)
{
if (msg->protocol == LAYER_2_PROTOCOL_MMR)
{
// First byte in {RREQ, RREP, RERR} is always type
if (msg->payload[0] == MMR_TYPE_RERR) return true;
}
return false;
}
/**
* @brief Generates a route reply message.
*
* @param rreq_msg Corresponding route request message
*/
static void generate_route_reply_message(mmr_rreq_message_t* rreq_msg)
{
DEBUG("call [%u]: generate_route_reply_message\n", fk_thread->pid);
// Create RREP message
mmr_rrep_message_t rrep_msg;
rrep_msg.type = MMR_TYPE_RREP;
rrep_msg.length = rreq_msg->length;
rrep_msg.destination = rreq_msg->source;
rrep_msg.source = rreq_msg->destination;
memcpy(rrep_msg.address, rreq_msg->address, rreq_msg->length * sizeof(uint16_t));
// Create MMR message containing the RREP message
net_message_t net_msg;
net_msg.protocol = LAYER_2_PROTOCOL_MMR;
net_msg.flags_tos = PRIORITY_ALARM;
net_msg.seq_clr_id = 0;
net_msg.ttl = TTL_THRESHOLD;
net_msg.source = rrep_msg.source;
net_msg.destination = rrep_msg.destination;
memcpy(net_msg.payload, (void*)&rrep_msg, sizeof(mmr_rrep_message_t));
// Source address must exist in route table to find correct
// interface id and next hop (should be created by RREQ)
route_table_entry_t* rte = rt_lookup_route(net_msg.destination);
if (rte != NULL)
{
// Send message to next hop
mmr_stats.rrep_originated++;
net_enqueue_for_transmission(&net_msg, rte->interface_id, rte->gateway, true);
}
DEBUG("exit [%u]: generate_route_reply_message\n", fk_thread->pid);
}
/**
* @brief Generates a route error message.
*
* @param dst Destination address of RERR packet
* @param gateway Next hop network address of RERR packet
* @param intf Interface id of RERR packet
* @param type Error type of RERR packet
* @param type_data Type specific data of RERR packet
*/
static void generate_route_error_message(uint16_t dst, uint16_t gateway, int intf, uint8_t type, uint16_t type_data)
{
DEBUG("call [%u]: generate_route_error_message\n", fk_thread->pid);
// Define RERR message
mmr_rerr_message_t rerr_msg;
rerr_msg.type = MMR_TYPE_RERR;
rerr_msg.error_type = type;
rerr_msg.type_specific_info = type_data;
// Wrap RERR message in net message
net_message_t net_msg;
net_msg.protocol = LAYER_2_PROTOCOL_MMR;
net_msg.flags_tos = PRIORITY_DATA;
net_msg.seq_clr_id = 0;
net_msg.ttl = TTL_THRESHOLD;
net_msg.source = net_get_address_in_subnet(dst);
net_msg.destination = dst;
memcpy(net_msg.payload, (void*)&rerr_msg, sizeof(mmr_rerr_message_t));
// Send message to next hop
mmr_stats.rerr_originated++;
net_enqueue_for_transmission(&net_msg, intf, gateway, true);
DEBUG("exit [%u]: generate_route_error_message\n", fk_thread->pid);
}
/**
* @brief Receive a route request message.
*
* @param msg The route request packet
* @param packet_info Additional packet information
*/
static void receive_route_request_message(mmr_rreq_message_t* msg, packet_info_t* packet_info)
{
DEBUG("call [%u]: receive_route_request_message\n", fk_thread->pid);
uint16_t my_addr = net_get_address_in_subnet(msg->source);
#if (MMR_INFO_LEVEL >= LEVEL_WARN)
if (my_addr == 0)
{
puts("MMR [WARN]: received RREQ with unknown network part of source address");
puts("MMR [WARN]: => can't find own net address in sub net!");
}
#endif
// If address list of RREQ message has enough space
if (msg->length < ADDRESS_LIST_SIZE)
{
// append our node id to list
msg->address[msg->length++] = my_addr;
// add routes with overhearing
rt_extract_routes(my_addr, msg->length, msg->address);
}
// Distance between sender and receiver is too long, discard packet
else
{
// Drop RREQ packet => set TTL to zero
*packet_info->ttl_ptr = 0;
DEBUG("exit [%u]: receive_route_request_message\n", fk_thread->pid);
return;
}
// If RREQ message was send to us, then send RREP message
if (msg->destination == my_addr)
{
// Don't forward RREQ packet any further => set TTL to zero
*packet_info->ttl_ptr = 0;
generate_route_reply_message(msg);
}
DEBUG("exit [%u]: receive_route_request_message\n", fk_thread->pid);
}
/**
* @brief Receive a route reply message.
*
* @param msg The route reply packet
* @param packet_info Additional packet information
*/
static void receive_route_reply_message(mmr_rrep_message_t* msg, packet_info_t* packet_info)
{
DEBUG("call [%u]: receive_route_reply_message\n", fk_thread->pid);
// RREP received: Send out queued packets for which routes are now known
mq_dequeue_and_send(msg->source);
DEBUG("exit [%u]: receive_route_reply_message\n", fk_thread->pid);
}
/**
* @brief Receive a route error message.
*
* @param msg The route error packet
* @param packet_info Additional packet information
*/
static void receive_route_error_message(mmr_rerr_message_t* msg, packet_info_t* packet_info)
{
DEBUG("call [%u]: receive_route_error_message\n", fk_thread->pid);
switch (msg->error_type)
{
case RERR_NODE_UNREACHABLE:
rt_remove_route(msg->type_specific_info);
break;
default:
#if (MMR_INFO_LEVEL >= LEVEL_INFO)
puts("MMR [INFO]: RERR error type is unknown");
#endif
break;
}
DEBUG("exit [%u]: receive_route_error_message\n", fk_thread->pid);
}
/**
* @brief Computes the RREQ timeout period, given a
* TTL and destination address value.
*
* @param ttl Time to live
* @param dst Network destination address
*
* @return RREQ timeout period in seconds
*/
static int compute_rreq_timeout(int ttl, uint16_t dst)
{
int t_hop = net_get_interface_transmission_duration(dst);
if (t_hop == -1) {
t_hop = RREQ_TIMEOUT_PER_TTL * ttl;
} else {
t_hop = (t_hop * ttl + 999) / 1000;
}
return RREQ_TIMEOUT_BASE + 2 * t_hop;
}
/**
* @brief Broadcast a RREQ message.
*
* A single route request can repeatedly broadcast RREQ messages,
* with increasing TTL value, until a route has been found.
*
* @param mq_entry Pointer to a message queue entry (the packet
* for which to find the route)
*/
static void rreq_broadcast(message_queue_entry_t* mq_entry)
{
DEBUG("call [%u]: rreq_broadcast\n", fk_thread->pid);
if(mq_entry->retry_count == RREQ_NONE)
{
DEBUG("call [%u]: rreq duplicated do not send\n", fk_thread->pid);
return;
}
// Create RREQ message
mmr_rreq_message_t rreq_msg;
rreq_msg.type = MMR_TYPE_RREQ;
rreq_msg.length = 1;
rreq_msg.destination = mq_entry->message.destination;
rreq_msg.source = mq_entry->message.source;
rreq_msg.address[0] = mq_entry->message.source;
// Wrap RREQ message in net message
net_message_t net_msg;
net_msg.protocol = LAYER_2_PROTOCOL_MMR;
net_msg.flags_tos = PRIORITY_DATA;
net_msg.seq_clr_id = 0;
net_msg.ttl = mq_entry->retry_count == 0 ? TTL_START : TTL_THRESHOLD;
net_msg.source = rreq_msg.source;
net_msg.destination = NETWORK_ADDR_BC(rreq_msg.destination);
memcpy(net_msg.payload, (void*)&rreq_msg, sizeof(mmr_rreq_message_t));
// Broadcast the net message
mq_entry->retry_count++;
mq_entry->timestamp = rtc_n