* integrated makefiles
* fixed some prototypes * restructured sys
This commit is contained in:
parent
784ef52390
commit
3791039974
|
@ -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);
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
@ -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 ;
|
||||
|
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
|
@ -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"
|
||||
|
|
|
@ -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 ;
|
||||
|
|
@ -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
|
||||
|
||||
|
||||
|
|
@ -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 ;
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
@ -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 ;
|
||||
|
||||
|
||||
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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 ;
|
||||
|
||||
|
|
@ -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)
|
||||
|
|
@ -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
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
@ -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);
|
||||
}
|
|
@ -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
|
||||
|
||||
|
|
@ -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 ;
|
||||
|
||||
|
||||
|
|
@ -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 ;
|
||||
|
|
@ -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
|
||||
|
|
@ -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 |