diff --git a/cpu/cc2430/8051def.h b/cpu/cc2430/8051def.h index add1f7eda..069a42c79 100644 --- a/cpu/cc2430/8051def.h +++ b/cpu/cc2430/8051def.h @@ -4,12 +4,34 @@ * Modified from z80 port for cc2430 port. * * \author - * Takahide Matsutsuka + * Takahide Matsutsuka (Original) + * George Oikonomou - + * (recent updates for the sensinode/cc2430 port) */ #ifndef __8051_DEF_H__ #define __8051_DEF_H__ +#include + +/* + * lint - style defines to help syntax parsers with sdcc-specific 8051 code + * They don't interfere with actual compilation + */ +#if !defined(__SDCC_mcs51) && !defined(SDCC_mcs51) +#define __data +#define __xdata +#define __code +#define __bit bool +#define __sfr volatile unsigned char +#define __sbit volatile bool +#define __critical +#define __at(x) +#define __using(x) +#define __interrupt(x) +#define __naked +#endif + #define CC_CONF_FUNCTION_POINTER_ARGS 1 #define CC_CONF_FASTCALL #define CC_CONF_VA_ARGS 1 @@ -18,30 +40,24 @@ #define CC_CONF_FUNCTION_POINTER_KEYWORD __reentrant /* Generic types. */ -typedef signed char int8_t; -typedef unsigned char uint8_t; -typedef signed short int16_t; -typedef unsigned short uint16_t; -typedef unsigned long uint32_t; typedef unsigned char u8_t; /* 8 bit type */ typedef unsigned short u16_t; /* 16 bit type */ typedef unsigned long u32_t; /* 32 bit type */ typedef signed long s32_t; /* 32 bit type */ typedef unsigned short uip_stats_t; -typedef signed long int32_t; /* 32 bit type */ -#ifndef _SIZE_T_DEFINED -#define _SIZE_T_DEFINED -typedef unsigned int size_t; -#endif + + +/* Time type. */ +typedef unsigned short clock_time_t; +#define MAX_TICKS (~((clock_time_t)0) / 2) /* Compiler configurations */ #define CCIF #define CLIF -#define CC_CONF_CONST_FUNCTION_BUG /* Critical section management */ -#define DISABLE_INTERRUPTS() EA = 0; -#define ENABLE_INTERRUPTS() EA = 1; +#define DISABLE_INTERRUPTS() do {EA = 0;} while(0) +#define ENABLE_INTERRUPTS() do {EA = 1;} while(0) #define ENTER_CRITICAL() \ { \ @@ -64,20 +80,12 @@ typedef unsigned int size_t; __endasm; \ } -/* - * Enable architecture-depend checksum calculation - * for uIP configuration. - * @see uip_arch.h - * @see uip_arch-asm.S - */ -/* - * DO NOT USE UIP_ARCH flags! - * uip_arch code was copied from z80 directory but NOT ported - */ +/* Macro for a soft reset. In many respects better than H/W reboot via W/D */ +#define SOFT_RESET() {((void (__code *) (void)) 0x0000) ();} +/* We don't provide architecture-specific checksum calculations */ #define UIP_ARCH_ADD32 0 #define UIP_ARCH_CHKSUM 0 -#define UIP_ARCH_IPCHKSUM #define CC_CONF_ASSIGN_AGGREGATE(dest, src) \ memcpy(dest, src, sizeof(*dest)) diff --git a/cpu/cc2430/Makefile.cc2430 b/cpu/cc2430/Makefile.cc2430 index 9b54ffc14..3863f6775 100644 --- a/cpu/cc2430/Makefile.cc2430 +++ b/cpu/cc2430/Makefile.cc2430 @@ -2,120 +2,176 @@ CC = sdcc LD = sdcc AS = sdcc -AR = sdcclib +AR = sdcclib OBJCOPY = objcopy STRIP = strip +PACKIHX = packihx +BANK_ALLOC = $(CONTIKI)/cpu/cc2430/bank-alloc.py +SEGMENT_RULES = $(OBJECTDIR)/segment.rules + +CFLAGS += --model-$(MEMORY_MODEL) --stack-auto -DSDCC_CC2430 --std-c99 + +LDFLAGS += --model-$(MEMORY_MODEL) --stack-auto -DSDCC_CC2430 --out-fmt-ihx +LDFLAGS += --xram-loc 0xE000 --xram-size 0x1F00 +LDFLAGS += --code-loc $(START_ADDR) --code-size $(CODE_SIZE) -CFLAGS += --std-c99 --model-large --stack-auto -DSDCC_CC2430 ASFLAGS += -plosgff -LDFLAGS += --model-large --stack-auto -DSDCC_CC2430 --out-fmt-ihx -LDFLAGS += --xram-loc 57344 --xram-size 8192 -##LDFLAGS += -L /home/user/local/share/sdcc/lib/large-stack-auto -##LDFLAGS += --verbose -##LDFLAGS += -V -AROPTS = -a -##HAVE_BANKING=1 -ifeq ($(HAVE_BANKING),1) -#banking -LDFLAGS += --code-size 0x20000 -LDFLAGS += -Wl-bCSEG=0x000000 -LDFLAGS += -Wl-bBANK1=0x018000 -LDFLAGS += -Wl-bBANK2=0x028000 -LDFLAGS += -Wl-bBANK3=0x038000 -#relocated code (for bank switching ) -LDFLAGS += -Wl-r -CFLAGS += -DHAVE_SDCC_BANKING -#use this in $(call code_segment,$<) to get segment for a source file. -code_segment = --codeseg $(word 1,$(shell cat ${OBJECTDIR}/segment.rules | perl ${CONTIKI_CPU}/segment.rules.pl $1 ) CSEG ) +AROPTS = -a + +### Our object files are .rel, so we can't use the default finalize dependency +### generation. Override here. +define FINALIZE_SDCC_DEPENDENCY +cp $(@:.rel=.d) $(@:.rel=.$$$$); \ +sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \ + -e '/^$$/ d' -e 's/$$/ :/' < $(@:.rel=.$$$$) >> $(@:.rel=.d); \ +rm -f $(@:.rel=.$$$$) +endef + +### Banking Guesswork: +### Examples outside examples/sensinode do not specify banking. +### We automatically turn it on if its unspecified and if we are building with +### UIP_CONF_IPV6 +ifndef HAVE_BANKING + ifeq ($(UIP_CONF_IPV6),1) + HAVE_BANKING=1 + else + HAVE_BANKING=0 + endif +endif + +### Does the project want us to offset the firmware? +### define start address and max code size accordingly, turn Disco on +ifeq ($(OFFSET_FIRMWARE),1) + START_ADDR = 0x01000 + HOME_START = 00001000 + ifeq ($(HAVE_BANKING),1) + CODE_SIZE = 0x1F000 + else + CODE_SIZE = 0x0F000 + endif else -#no banking -LDFLAGS += --code-loc 0000 --code-size 65500 -code_segment = + START_ADDR = 0x00000 + HOME_START = 00000000 + ifeq ($(HAVE_BANKING),1) + CODE_SIZE = 0x20000 + else + CODE_SIZE = 0x10000 + endif +endif + +### Are we building with BANKing supoprt? +ifeq ($(HAVE_BANKING),1) + ## Yes + MEMORY_MODEL=huge + LDFLAGS += -Wl-bBANK1=0x018000 + LD_POST_FLAGS += -Wl-bBANK2=0x028000 + LD_POST_FLAGS += -Wl-bBANK3=0x038000 + LDFLAGS += -Wl-r + CFLAGS += -DHAVE_SDCC_BANKING + #use this in $(call c_seg,$<) to get segment for a source file. + c_seg = --codeseg $(shell python $(BANK_ALLOC) $1 $(SEGMENT_RULES) $2) +else + ## No banking + MEMORY_MODEL=large + c_seg = endif ### CPU-dependent cleanup files -CLEAN += *.lnk *.sym *.lib *.ihx *.rel *.mem *.rst *.asm *_linear.hex +CLEAN += *.lnk *.lk *.sym *.lib *.ihx *.rel *.mem *.rst *.asm *.hex *.sensinode +CLEAN += *.omf *.cdb *.banks +CLEAN += symbols.c symbols.h ### CPU-dependent directories CONTIKI_CPU_DIRS = . dev ### CPU-dependent source files -CONTIKI_SOURCEFILES += bus.c clock.c uart.c cc2430_rf.c dma.c -CONTIKI_SOURCEFILES += uart_init.c uart_intr.c cc2430_rf_intr.c dma_intr.c adc.c +CONTIKI_SOURCEFILES += bus.c clock.c uart0.c uart1.c cc2430_rf.c dma.c +CONTIKI_SOURCEFILES += uart_intr.c cc2430_rf_intr.c dma_intr.c +CONTIKI_SOURCEFILES += watchdog-cc2430.c rtimer-arch.c CONTIKI_ASMFILES += -CONTIKI_ASMOBJECTFILES = ${addprefix $(OBJECTDIR)/,$(CONTIKI_ASMFILES:.S=.o)} +CONTIKI_ASMOBJECTFILES = $(addprefix $(OBJECTDIR)/,$(CONTIKI_ASMFILES:.S=.rel)) -CONTIKI_CASMOBJECTFILES = ${addprefix $(OBJECTDIR)/,$(CONTIKI_CASMFILES:.cS=.o)} +CONTIKI_CASMOBJECTFILES = $(addprefix $(OBJECTDIR)/, \ + $(CONTIKI_CASMFILES:.cS=.rel)) CONTIKI_PLATFORM_DIRS = $(PLATFORM_APPDIRS) \ - ${addprefix $(CONTIKI)/platform/$(TARGET)/, $(CONTIKI_TARGET_DIRS)} + $(addprefix $(CONTIKI)/platform/$(TARGET)/, $(CONTIKI_TARGET_DIRS)) -CONTIKI_CPU_DIRS_LIST = ${addprefix $(CONTIKI_CPU)/, \ - $(CONTIKI_CPU_DIRS)} +CONTIKI_CPU_DIRS_LIST = $(addprefix $(CONTIKI_CPU)/, \ + $(CONTIKI_CPU_DIRS)) + +oname = $(patsubst %.c,%.rel,$(patsubst %.S,%.rel,$(1))) + +CONTIKI_OBJECTFILES = $(addprefix $(OBJECTDIR)/, \ + $(call oname, $(CONTIKI_SOURCEFILES))) + +PROJECT_OBJECTFILES = $(addprefix $(OBJECTDIR)/, \ + $(call oname, $(PROJECT_SOURCEFILES))) ### Compilation rules +SEGMENT_RULE_FILES = $(foreach dir, . $(CONTIKI_PLATFORM_DIRS) \ + $(CONTIKI_CPU_DIRS_LIST), $(wildcard $(dir)/segment.rules) ) -SEGMENT_RULE_FILES = ${foreach dir, ${CONTIKI_PLATFORM_DIRS} ${CONTIKI_CPU_DIRS_LIST}, ${wildcard $(dir)/segment.rules} } -${OBJECTDIR}/segment.rules: ${SEGMENT_RULE_FILES} - echo ${SEGMENT_RULE_FILES} - cat ${SEGMENT_RULE_FILES} > $@ - +$(SEGMENT_RULES): $(SEGMENT_RULE_FILES) + cat $(SEGMENT_RULE_FILES) | \ + sed -e 's/#.*$$//' -e 's/^\s*//' -e '/^$$/d' > $@ +CUSTOM_RULE_LINK=1 CUSTOM_RULE_C_TO_OBJECTDIR_O=1 CUSTOM_RULE_ALLOBJS_TO_TARGETLIB=1 -ifdef CUSTOM_RULE_C_TO_OBJECTDIR_O -ifeq ($(HAVE_BANKING),1) -$(OBJECTDIR)/%.o: %.c ${OBJECTDIR}/segment.rules - @echo "Compile:"$<" to segment " $(call code_segment,$<) - $(CC) $(CFLAGS) -MM -c $< > $(@:.o=.d) - $(CC) $(call code_segment,$<) $(CFLAGS) -c $< -o $@ - @$(FINALIZE_DEPENDENCY) -else -$(OBJECTDIR)/%.o: %.c - $(CC) $(CFLAGS) -c $< -o $@ - $(CC) $(CFLAGS) -MM -c $< > $(@:.o=.d) - @$(FINALIZE_DEPENDENCY) -endif -endif +$(OBJECTDIR)/%.rel: %.c $(SEGMENT_RULES) + $(CC) $(call c_seg,$<,$@) $(CFLAGS) -c $< -o $@ -Wp,-MMD,$(@:.rel=.d),-MQ,$@ + @$(FINALIZE_SDCC_DEPENDENCY) -$(OBJECTDIR)/%.rel: $(OBJECTDIR)/%.o - cp $< $@ - - -ifdef CUSTOM_RULE_CS_TO_OBJECTDIR_O -$(OBJECTDIR)/%.o: %.cS +$(OBJECTDIR)/%.rel: %.cS cp $< $(OBJECTDIR)/$*.c $(CC) $(CFLAGS) -E $(OBJECTDIR)/$*.c > $(OBJECTDIR)/tmp perl -pe "s/^#(.*)/;$$1/" $(OBJECTDIR)/tmp > $(OBJECTDIR)/$*.S $(AS) $(ASFLAGS) -o $@ $(OBJECTDIR)/$*.S rm -f $(OBJECTDIR)/tmp -endif -#CUSTOM_RULE_ALLOBJS_TO_TARGETLIB -contiki-$(TARGET).lib: $(CONTIKI_OBJECTFILES) $(PROJECT_OBJECTFILES) $(CONTIKI_ASMOBJECTFILES) $(CONTIKI_CASMOBJECTFILES) +contiki-$(TARGET).lib: $(CONTIKI_OBJECTFILES) $(PROJECT_OBJECTFILES) \ + $(CONTIKI_ASMOBJECTFILES) $(CONTIKI_CASMOBJECTFILES) rm -f $@ for target in $^; do echo $$target >> $@; done -%.$(TARGET): %.ihx %_linear.hex +.PRECIOUS: %.$(TARGET) %.hex -# .rel is the object file default suffix under sdcc -%.rel: %.co - mv $< $@ +# build app/example local object files. We need a separate rule so that we can +# pass -DAUTOSTART_ENABLE for those files only +$(OBJECTDIR)/%.app.rel: %.c $(SEGMENT_RULES) + $(CC) $(call c_seg,$<,$@) -DAUTOSTART_ENABLE $(CFLAGS) -c $< -o $@ # .ihx is the sdcc binary output file -.PRECIOUS: %.ihx %.rel %_linear.hex +%.ihx: $(OBJECTDIR)/%.app.rel $(CONTIKI_TARGET_MAIN) contiki-$(TARGET).lib +# Automatic bank relocation when building banked code +ifeq ($(HAVE_BANKING),1) + @echo "\nFirst Link" + @echo "===============" + $(CC) $(LDFLAGS) -o $@ $(CONTIKI_TARGET_MAIN) $(OBJECTDIR)/$*.app.rel -llibsdcc.lib -lcontiki-$(TARGET).lib > /dev/null + @echo "\nBank Allocation" + @echo "===============" + python $(BANK_ALLOC) $(basename $(@F)) $(SEGMENT_RULES) $(OFFSET_FIRMWARE) + @echo "\nFinal Link" + @echo "===============" +endif + $(CC) $(LDFLAGS) $(LD_POST_FLAGS) -o $@ $(CONTIKI_TARGET_MAIN) $(OBJECTDIR)/$*.app.rel -llibsdcc.lib -lcontiki-$(TARGET).lib > /dev/null -# .ihx is the sdcc binary output file -%.ihx: %.rel $(CONTIKI_TARGET_MAIN:.o=.rel) contiki-$(TARGET).lib - $(CC) $(LDFLAGS) -o $@ $(CONTIKI_TARGET_MAIN:.o=.rel) $*.rel -llibsdcc.lib -lcontiki-$(TARGET).lib - -%_linear.hex: %.ihx - $(CONTIKI)/cpu/cc2430/converter/converter -f $< $@ - -# Force the compilation of %.$(TARGET) to compile the %.ihx file. -%.$(TARGET): %.ihx %_linear.hex - @ +# Pack the hex file for programmers which dislike SDCC output hex format +%.hex: %.ihx + @echo "\nPack hex file" + @echo "===============" +ifeq ($(HAVE_BANKING),1) + srec_cat -disable_sequence_warnings $< -intel -crop 0x10000 0x1FFFF -offset -0x10000 -o bank1.hex -intel + srec_cat -disable_sequence_warnings $< -intel -crop 0x20000 0x2FFFF -offset -0x18000 -o bank2.hex -intel + srec_cat -disable_sequence_warnings $< -intel -crop 0x30000 0x3FFFF -offset -0x20000 -o bank3.hex -intel + srec_cat -disable_sequence_warnings $< -intel -crop 0x00000 0x0FFFF -o home.ihx -intel + srec_cat home.ihx -intel bank1.hex -intel bank2.hex -intel bank3.hex -intel -o $@ -intel + rm -f home.ihx bank1.hex bank2.hex bank3.hex +else + $(PACKIHX) $< > $@ +endif diff --git a/cpu/cc2430/bank-alloc.py b/cpu/cc2430/bank-alloc.py new file mode 100644 index 000000000..10e452577 --- /dev/null +++ b/cpu/cc2430/bank-alloc.py @@ -0,0 +1,228 @@ +#!/usr/bin/env python + +# Copyright (c) 2010, Loughborough University - Computer Science +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the Institute nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# This file is part of the Contiki operating system. + +# \file +# Automatic allocation of modules to code segments for bankable builds +# with SDCC's huge memory model. +# +# \author +# George Oikonomou - +import sys +import re +import operator +import fileinput +import os + +# Open a module object file (.rel) and read it's code size +def retrieve_module_size(file_name): + size_pat = re.compile('^A\s+(?:HOME|BANK[0-9])\s+size\s+([1-9A-F][0-9A-F]*)') + for code_line in open(file_name): + matches = size_pat.search(code_line) + if matches is not None: + return int(matches.group(1), 16) + return 0 + +# Searches for a code segment rule for file_name in the segment_rules file +# If there is a rule, we respect it. Otherwise, we can move the file around +def get_source_seg(source_file, object_file, segment_rules): + for line in open(segment_rules): + tokens = line.split(None) + match = re.search(tokens[1], source_file) + if match is not None: + # Save it in basename.seg + base, ext = os.path.splitext(object_file) + of = open(base + '.seg', 'w') + of.write(tokens[0] + '\n') + of.close + return tokens[0] + return None + +# If segment.rules specified a rule for a source file, the respective object +# file's banking requirement will be stored in object_file.seg +def get_object_seg(object_file): + base, ext = os.path.splitext(object_file) + seg = base + '.seg' + bank = None + if os.path.isfile(seg) is True: + of = open(base + '.seg', 'r') + bank = of.readline().strip() + of.close() + return bank + +# Open project.mem and retreive the project's total code footprint +def get_total_size(project): + mem_file = project + '.mem' + pat = re.compile('FLASH\s+(0x[0-9a-f]+\s+){2}([0-9]+)') + for line in open(mem_file): + l = pat.search(line) + if l is not None: + return int(l.group(2)) + +# Open project.map and retrieve the list of modules linked in +# This will only consider contiki sources, not SDCC libraries +# NB: Sometimes object filenames get truncated: +# contiki-sensinode.lib [ obj_sensinode/watchdog-cc2430.re ] +# See how for this file the 'l' in 'rel' is missing. For that reason, we retrieve +# the filaname until the last '.' but without the extension and we append 'rel' +# As long as the filename doesn't get truncated, we're good +def populate(project, modules, segment_rules, bins): + bankable_total = 0 + user_total = 0 + + map_file = project + '.map' + file_pat = re.compile('obj_sensinode[^ ]+\.') + for line in open(map_file): + file_name = file_pat.search(line) + if file_name is not None: + mod = file_name.group(0) + 'rel' + code_size = retrieve_module_size(mod) + seg = get_object_seg(mod) + if seg is not None: + # This module has been assigned to a bank by the user + #print 'In', seg, file_name.group(0), 'size', code_size + bins[seg][0] += code_size + user_total += code_size + else: + # We are free to allocate this module + modules.append([mod, code_size, "NONE"]) + bankable_total += code_size + return bankable_total, user_total + +# Allocate bankable modules to banks according to a simple +# 'first fit, decreasing' bin packing heuristic. +def bin_pack(modules, bins, offset, log): + if offset==1: + bins['HOME'][1] -= 4096 + + # Sort by size, descending, in=place + modules.sort(key=operator.itemgetter(1), reverse=True) + + for module in modules: + # We want to iterate in a specific order and dict.keys() won't do that + for bin_id in ['BANK1', 'BANK2', 'BANK3', 'HOME']: + if bins[bin_id][0] + module[1] < bins[bin_id][1]: + bins[bin_id][0] += module[1] + module[2] = bin_id + log.writelines(' '.join([module[2].ljust(8), \ + str(module[1]).rjust(5), module[0], '\n'])) + break + else: + if bin_id == 'HOME': + print "Failed to allocate", module[0], "with size", module[1], \ + "to a code bank. This is fatal" + return 1 + return 0 + +# Hack the new bank directly in the .rel file +def relocate(module, bank): + code_pat = re.compile('(A\s+)(?:HOME|BANK[0-9])(\s+size\s+[1-9A-F][0-9A-F]*.+\n)') + + for line in fileinput.input(module, inplace=1): + m = code_pat.search(line) + if m is not None: + line = m.group(1) + bank + m.group(2) + sys.stdout.write(line) + return + +if len(sys.argv) < 3: + print 'Usage:' + print 'bank-alloc.py project path_to_segment_rules [offset]' + print 'bank-alloc.py source_file path_to_segment_rules object_file' + sys.exit(1) + +modules = list() +file_name = sys.argv[1] +segment_rules = sys.argv[2] + +# Magic: Guess whether we want to determine the code bank for a code file +# or whether we want to bin-pack +basename, ext = os.path.splitext(file_name) +if ext == '.c': + # Code Segment determination + if len(sys.argv) < 4: + print 'Usage:' + print 'bank-alloc.py project path_to_segment_rules [offset]' + print 'bank-alloc.py source_file path_to_segment_rules object_file' + sys.exit(1) + object_file = sys.argv[3] + seg = get_source_seg(file_name, object_file, segment_rules) + if seg is None: + print "BANK1" + else: + print seg + exit() + +# Bin-Packing +offset = 0 +if len(sys.argv) > 3 and sys.argv[3] is not None: + offset = int(sys.argv[3]) + +sizes = {'total': 0, 'bankable': 0, 'user': 0, 'libs': 0} + +# Name : [Allocated, capacity] +bins = { + 'HOME': [0, 32768], + 'BANK1': [0, 32768], + 'BANK2': [0, 32768], + 'BANK3': [0, 30720] +} + +sizes['total'] = get_total_size(basename) +sizes['bankable'], sizes['user'] = populate(basename, modules, segment_rules, bins) +sizes['libs'] = sizes['total'] - sizes['bankable'] - sizes['user'] + +print 'Total Size =', sizes['total'], 'bytes (' + \ + str(sizes['bankable']), 'bankable,', \ + str(sizes['user']), 'user-allocated,', \ + str(sizes['libs']), 'const+libs)' + +bins['HOME'][0] += sizes['libs'] + +print 'Preallocations: HOME=' + str(bins['HOME'][0]) + \ + ', BANK1=' + str(bins['BANK1'][0]) + ', BANK2=' + str(bins['BANK2'][0]) + \ + ', BANK3=' + str(bins['BANK3'][0]) + +# Open a log file +of = open(basename + '.banks', 'w') +pack = bin_pack(modules, bins, offset, of) +of.close() + +print "Bin-Packing results (target allocation):" +print "Segment - max - alloc" +for bin_id in ['HOME', 'BANK1', 'BANK2', 'BANK3']: + print bin_id.rjust(7), str(bins[bin_id][1]).rjust(6), str(bins[bin_id][0]).rjust(6) + +if pack > 0: + sys.exit(1) + +# If we reach here we seem to have a sane allocation. Start changing .rel files +for module in modules: + relocate(module[0], module[2]) diff --git a/cpu/cc2430/cc2430_sfr.h b/cpu/cc2430/cc2430_sfr.h index d464bc690..53581cd29 100644 --- a/cpu/cc2430/cc2430_sfr.h +++ b/cpu/cc2430/cc2430_sfr.h @@ -1,706 +1,709 @@ -/** - * - * \file cc2430_sfr.h - * \brief CC2430 registers header file for CC2430. - * - * Definitions for CC2430 SFR registers. - * - * - */ - -#ifndef REG_CC2430_H -#define REG_CC2430_H - -/* BYTE Register */ - -__sfr __at (0x80) P0 ; -/* P0 */ -__sbit __at (0x87) P0_7 ; -__sbit __at (0x86) P0_6 ; -__sbit __at (0x85) P0_5 ; -__sbit __at (0x84) P0_4 ; -__sbit __at (0x83) P0_3 ; -__sbit __at (0x82) P0_2 ; -__sbit __at (0x81) P0_1 ; -__sbit __at (0x80) P0_0 ; - -__sfr __at (0x81) SP ; -__sfr __at (0x82) DPL0 ; -__sfr __at (0x83) DPH0 ; -/*DPL and DPH correspond DPL0 and DPH0 (82-83)*/ -__sfr __at (0x84) DPL1; -__sfr __at (0x85) DPH1; -__sfr __at (0x86) U0CSR; -#define U_MODE 0x80 -#define U_RE 0x40 -#define U_SLAVE 0x20 -#define U_FE 0x10 -#define U_ERR 0x08 -#define U_RXB 0x04 -#define U_TXB 0x02 -#define U_ACTIVE 0x01 - -__sfr __at (0x87) PCON ; -/* PCON (0x87) */ -#define IDLE 0x01 - -__sfr __at (0x88) TCON ; -/* TCON (0x88) */ -__sbit __at (0x8F) TCON_URX1IF; -/*__sbit __at (0x8E) RES;*/ -__sbit __at (0x8D) TCON_ADCIF; -/*__sbit __at (0x8C) RES;*/ -__sbit __at (0x8B) TCON_URX0IF; -__sbit __at (0x8A) TCON_IT1; -__sbit __at (0x89) TCON_RFERRIF; -__sbit __at (0x88) TCON_IT0; - - -__sfr __at (0x89) P0IFG; -__sfr __at (0x8A) P1IFG; -__sfr __at (0x8B) P2IFG; -__sfr __at (0x8C) PICTL; -/*PICTL bits*/ -#define PADSC 0x40 -#define P2IEN 0x20 -#define P0IENH 0x10 -#define P0IENL 0x08 -#define P2ICON 0x04 -#define P1ICON 0x02 -#define P0ICON 0x01 - -__sfr __at (0x8D) P1IEN; -__sfr __at (0x8F) P0INP; - -__sfr __at (0x90) P1 ; -/* P1 */ -__sbit __at (0x90) P1_0 ; -__sbit __at (0x91) P1_1 ; -__sbit __at (0x92) P1_2 ; -__sbit __at (0x93) P1_3 ; -__sbit __at (0x94) P1_4 ; -__sbit __at (0x95) P1_5 ; -__sbit __at (0x96) P1_6 ; -__sbit __at (0x97) P1_7 ; - -__sfr __at (0x91) RFIM; -__sfr __at (0x92) DPS; -__sfr __at (0x93) _XPAGE; /*MPAGE as paging register for sdcc*/ -__sfr __at (0x94) T2CMP; -__sfr __at (0x95) ST0; -__sfr __at (0x96) ST1; -__sfr __at (0x97) ST2; -__sfr __at (0x98) S0CON ; - -__sbit __at (0x99) S0CON_ENCIF_1; -__sbit __at (0x98) S0CON_ENCIF_0; - -__sfr __at (0x99) HSRC; -__sfr __at (0x9A) IEN2; -/*IEN2 bits*/ -#define WDTIE 0x20 -#define P1IE 0x10 -#define UTX1IE 0x08 -#define UTX0IE 0x04 -#define P2IE 0x02 -#define RFIE 0x01 -__sfr __at (0x9B) S1CON; -/*S1CON bits*/ -#define RFIF_1 0x02 -#define RFIF_0 0x01 -__sfr __at (0x9C) T2PEROF0; -__sfr __at (0x9D) T2PEROF1; -__sfr __at (0x9E) T2PEROF2; -/*T2PEROF2 bits*/ -#define CMPIM 0x80 -#define PERIM 0x40 -#define OFCMPIM 0x20 - -#define PEROF23 0x08 -#define PEROF22 0x04 -#define PEROF21 0x02 -#define PEROF20 0x01 - -__sfr __at (0x9F) FMAP; -__sfr __at (0x9F) PSBANK; - -__sfr __at (0xA0) P2 ; -/* P2 */ -__sbit __at (0xA0) P2_0 ; -__sbit __at (0xA1) P2_1 ; -__sbit __at (0xA2) P2_2 ; -__sbit __at (0xA3) P2_3 ; -__sbit __at (0xA4) P2_4 ; -/*__sbit __at (0xA5) P2_5 ; -__sbit __at (0xA6) P2_6 ; -__sbit __at (0xA7) P2_7 ;*/ - -__sfr __at (0xA1) T2OF0; -__sfr __at (0xA2) T2OF1; -__sfr __at (0xA3) T2OF2; -__sfr __at (0xA4) T2CAPLPL; -__sfr __at (0xA5) T2CAPHPH; -__sfr __at (0xA6) T2TLD; -__sfr __at (0xA7) T2THD; - -__sfr __at (0xA8) IE ; -__sfr __at (0xA8) IEN0; -/*IEN0 bits*/ -#define IEN0_EA_MASK 0x80 -#define STIE 0x20 -#define ENCIE 0x10 -#define URX1IE 0x08 -#define URX0IE 0x04 -#define ADCIE 0x02 -#define RFERRIE 0x01 -/* IEN0 (0xA8) */ -__sbit __at (0xAF) EA; -__sbit __at (0xAF) IEN0_EA; -/*__sbit __at (0xAE) RES;*/ -__sbit __at (0xAD) IEN0_STIE; -__sbit __at (0xAC) IEN0_ENCIE; -__sbit __at (0xAB) IEN0_URX1IE; -__sbit __at (0xAA) IEN0_URX0IE; -__sbit __at (0xA9) IEN0_ADCIE; -__sbit __at (0xA8) IEN0_RFERRIE; - -__sfr __at (0xA9) IP0; -/*IP0 bits*/ -#define IP0_5 0x20 -#define IP0_4 0x10 -#define IP0_3 0x08 -#define IP0_2 0x04 -#define IP0_1 0x02 -#define IP0_0 0x01 -__sfr __at (0xAB) FWT; -__sfr __at (0xAC) FADDRL; -__sfr __at (0xAD) FADDRH; - -__sfr __at (0xAE) FCTL; -#define F_BUSY 0x80 -#define F_SWBSY 0x40 -#define F_CONTRD 0x10 -#define F_WRITE 0x02 -#define F_ERASE 0x01 -__sfr __at (0xAF) FWDATA; - -/*No port 3 (0xB0)*/ -__sfr __at (0xB1) ENCDI; -__sfr __at (0xB2) ENCDO; -__sfr __at (0xB3) ENCCS; -#define CCS_MODE2 0x40 -#define CCS_MODE1 0x20 -#define CCS_MODE0 0x10 -#define CCS_RDY 0x08 -#define CCS_CMD1 0x04 -#define CCS_CMD0 0x02 -#define CCS_ST 0x01 -__sfr __at (0xB4) ADCCON1; -/*ADCCON1 bits*/ -#define ADEOC 0x80 -#define ADST 0x40 -#define ADSTS1 0x20 -#define ADSTS0 0x10 -#define ADRCTRL1 0x08 -#define ADRCTRL0 0x04 -__sfr __at (0xB5) ADCCON2; -/*ADCCON2 bits*/ -#define ADSREF1 0x80 -#define ADSREF0 0x40 -#define ADSDIV1 0x20 -#define ADSDIV0 0x10 -#define ADSCH3 0x08 -#define ADSCH2 0x04 -#define ADSCH1 0x02 -#define ADSCH0 0x01 -__sfr __at (0xB6) ADCCON3; -/*ADCCON3 bits*/ -#define ADEREF1 0x80 -#define ADEREF0 0x40 -#define ADEDIV1 0x20 -#define ADEDIV0 0x10 -#define ADECH3 0x08 -#define ADECH2 0x04 -#define ADECH1 0x02 -#define ADECH0 0x01 - -__sfr __at (0xB7) RCCTL; -#undef IP /*this is 0xb8 in base core*/ - -__sfr __at (0xB8) IEN1; -/*IEN1 bits*/ -#define P0IE 0x20 -#define T4IE 0x10 -#define T3IE 0x08 -#define T2IE 0x04 -#define T1IE 0x02 -#define DMAIE 0x01 -/* IEN1 (0xB8) */ -/*__sbit __at (0xBF) IEN1_RES;*/ -/*__sbit __at (0xBE) RES;*/ -__sbit __at (0xBD) IEN1_P0IE; -__sbit __at (0xBC) IEN1_T4IE; -__sbit __at (0xBB) IEN1_T3IE; -__sbit __at (0xBA) IEN1_T2IE; -__sbit __at (0xB9) IEN1_T1IE; -__sbit __at (0xB8) IEN1_DMAIE; - -__sfr __at (0xB9) IP1; -/*IP1 bits*/ -#define IP1_5 0x20 -#define IP1_4 0x10 -#define IP1_3 0x08 -#define IP1_2 0x04 -#define IP1_1 0x02 -#define IP1_0 0x01 - -__sfr __at (0xBA) ADCL; -__sfr __at (0xBB) ADCH; -__sfr __at (0xBC) RNDL; -__sfr __at (0xBD) RNDH; - -__sfr __at (0xBE) SLEEP; -#define XOSC_STB 0x40 -#define HFRC_STB 0x20 -#define RST1 0x10 -#define RST0 0x08 -#define OSC_PD 0x04 -#define SLEEP_MODE1 0x02 -#define SLEEP_MODE0 0x01 - -__sfr __at (0xC0) IRCON; -/*IRCON bits*/ -#define STIF 0x80 -#define P0IF 0x20 -#define T4IF 0x10 -#define T3IF 0x08 -#define T2IF 0x04 -#define T1IF 0x02 -#define DMAIF 0x01 -/* IRCON */ -__sbit __at (0xC7) IRCON_STIF ; -/*__sbit __at (0x86) IRCON_6 ;*/ -__sbit __at (0xC5) IRCON_P0IF; -__sbit __at (0xC4) IRCON_T4IF; -__sbit __at (0xC3) IRCON_T3IF; -__sbit __at (0xC2) IRCON_T2IF; -__sbit __at (0xC1) IRCON_T1IF; -__sbit __at (0xC0) IRCON_DMAIF; - -__sfr __at (0xC1) U0BUF; - -__sfr __at (0xC2) U0BAUD; -__sfr __at (0xC3) T2CNF; -/*T2SEL bits*/ -#define CMPIF 0x80 -#define PERIF 0x40 -#define OFCMPIF 0x20 - -#define CMSEL 0x08 - -#define SYNC 0x02 -#define RUN 0x01 - -__sfr __at (0xC4) U0UCR; -#define U_FLUSH 0x80 -#define U_FLOW 0x40 -#define U_D9 0x20 -#define U_BIT9 0x10 -#define U_PARITY 0x08 -#define U_SPB 0x04 -#define U_STOP 0x02 -#define U_START 0x01 - -__sfr __at (0xC5) U0GCR; -#define U_CPOL 0x80 -#define U_CPHA 0x40 -#define U_ORDER 0x20 -#define U_BAUD_E4 0x10 -#define U_BAUD_E3 0x08 -#define U_BAUD_E2 0x04 -#define U_BAUD_E1 0x02 -#define U_BAUD_E0 0x01 - -__sfr __at (0xC6) CLKCON; -#define OSC32K 0x80 -#define OSC 0x40 -#define TICKSPD2 0x20 -#define TICKSPD1 0x10 -#define TICKSPD0 0x08 -#define CLKSPD 0x01 - -__sfr __at (0xC7) MEMCTR; -#define MUNIF 0x40 -__sfr __at (0xC8) T2CON; - -__sfr __at (0xC9) WDCTL; -#define WDT_CLR3 0x80 -#define WDT_CLR2 0x40 -#define WDT_CLR1 0x20 -#define WDT_CLR0 0x10 -#define WDT_EN 0x08 -#define WDT_MODE 0x04 -#define WDT_INT1 0x02 -#define WDT_INT0 0x01 - -__sfr __at (0xCA) T3CNT; - -__sfr __at (0xCB) T3CTL; -/*T3CTL bits*/ -#define T3DIV2 0x80 -#define T3DIV1 0x40 -#define T3DIV0 0x20 -#define T3START 0x10 -#define T3OVFIM 0x08 -#define T3CLR 0x04 -#define T3MODE1 0x02 -#define T3MODE0 0x01 - -__sfr __at (0xCC) T3CCTL0; -/*T3CCTL0 bits*/ -#define T3IM 0x40 -#define T3CMP2 0x20 -#define T3CMP1 0x10 -#define T3CMP0 0x08 -#define T3MODE 0x04 -#define T3CAP1 0x02 -#define T3CAP0 0x01 - -__sfr __at (0xCD) T3CC0; -__sfr __at (0xCE) T3CCTL1; -/*T3CCTL0 bits apply*/ -__sfr __at (0xCF) T3CC1; - -__sfr __at (0xD0) PSW ; -/* PSW */ -__sbit __at (0xD0) P ; -__sbit __at (0xD1) F1 ; -__sbit __at (0xD2) OV ; -__sbit __at (0xD3) RS0 ; -__sbit __at (0xD4) RS1 ; -__sbit __at (0xD5) F0 ; -__sbit __at (0xD6) AC ; -__sbit __at (0xD7) CY ; - -__sfr __at (0xD1) DMAIRQ; -/*DMAIRQ bits*/ -#define DMAIF4 0x10 -#define DMAIF3 0x08 -#define DMAIF2 0x04 -#define DMAIF1 0x02 -#define DMAIF0 0x01 - -__sfr __at (0xD2) DMA1CFGL; -__sfr __at (0xD3) DMA1CFGH; -__sfr __at (0xD4) DMA0CFGL; -__sfr __at (0xD5) DMA0CFGH; - -__sfr __at (0xD6) DMAARM; -/*DMAARM bits*/ -#define ABORT 0x80 -#define DMAARM4 0x10 -#define DMAARM3 0x08 -#define DMAARM2 0x04 -#define DMAARM1 0x02 -#define DMAARM0 0x01 - -__sfr __at (0xD7) DMAREQ; -/*DMAREQ bits*/ -#define DMAREQ4 0x10 -#define DMAREQ3 0x08 -#define DMAREQ2 0x04 -#define DMAREQ1 0x02 -#define DMAREQ0 0x01 - -__sfr __at (0xD8) TIMIF; -/*TIMIF bits*/ -#define OVFIM 0x40 -#define T4CH1IF 0x20 -#define T4CH0IF 0x10 -#define T4OVFIF 0x08 -#define T3CH1IF 0x04 -#define T3CH0IF 0x02 -#define T3OVFIF 0x01 - -__sfr __at (0xD9) RFD; -__sfr __at (0xDA) T1CC0L; -__sfr __at (0xDB) T1CC0H; -__sfr __at (0xDC) T1CC1L; -__sfr __at (0xDD) T1CC1H; -__sfr __at (0xDE) T1CC2L; -__sfr __at (0xDF) T1CC2H; - -__sfr __at (0xE0) ACC; -__sfr __at (0xE1) RFST; -__sfr __at (0xE2) T1CNTL; -__sfr __at (0xE3) T1CNTH; - -__sfr __at (0xE4) T1CTL; -/*T1CTL bits*/ -#define CH2IF 0x80 -#define CH1IF 0x40 -#define CH0IF 0x20 -#define OVFIF 0x10 -#define T1DIV1 0x08 -#define T1DIV0 0x04 -#define T1MODE1 0x02 -#define T1MODE0 0x01 - -__sfr __at (0xE5) T1CCTL0; -/*T1CCTL0 bits*/ -#define T1CPSEL 0x80 -#define T1IM 0x40 -#define T1CMP2 0x20 -#define T1CMP1 0x10 -#define T1CMP0 0x08 -#define T1MODE 0x04 -#define T1CAP1 0x02 -#define T1CAP0 0x01 - -__sfr __at (0xE6) T1CCTL1; -/*Bits defined in T1CCTL0 */ -__sfr __at (0xE7) T1CCTL2; -/*Bits defined in T1CCTL0 */ -__sfr __at (0xE8) IRCON2; -/*IRCON2 bits*/ -#define WDTIF 0x10 -#define P1IF 0x08 -#define UTX1IF 0x04 -#define UTX0IF 0x02 -#define P2IF 0x01 -/* IRCON 2 */ -/*__sbit __at (0xEF) IRCON2_P1_7 ; -__sbit __at (0xEE) IRCON2_P1_6 ; -__sbit __at (0xED) IRCON2_P1_5 ;*/ -__sbit __at (0xEC) IRCON2_WDTIF ; -__sbit __at (0xEB) IRCON2_P1IF ; -__sbit __at (0xEA) IRCON2_UTX1IF ; -__sbit __at (0xE9) IRCON2_UTX0IF ; -__sbit __at (0xE8) IRCON2_P2IF; - - -__sfr __at (0xE9) RFIF; -/*RFIF bits*/ -#define IRQ_RREG_ON 0x80 -#define IRQ_TXDONE 0x40 -#define IRQ_FIFOP 0x20 -#define IRQ_SFD 0x10 -#define IRQ_CCA 0x08 -#define IRQ_CSP_WT 0x04 -#define IRQ_CSP_STOP 0x02 -#define IRQ_CSP_INT 0x01 - -__sfr __at (0xEA) T4CNT; -__sfr __at (0xEB) T4CTL; -/*T4CTL bits*/ -#define T4DIV2 0x80 -#define T4DIV1 0x40 -#define T4DIV0 0x20 -#define T4START 0x10 -#define T4OVFIM 0x08 -#define T4CLR 0x04 -#define T4MODE1 0x02 -#define T4MODE0 0x01 - -__sfr __at (0xEC) T4CCTL0; -/*T4CCTL0 bits*/ -#define T4IM 0x40 -#define T4CMP2 0x20 -#define T4CMP1 0x10 -#define T4CMP0 0x08 -#define T4MODE 0x04 -#define T4CAP1 0x02 -#define T4CAP0 0x01 - -__sfr __at (0xED) T4CC0; -__sfr __at (0xEE) T4CCTL1; -/*T4CCTL0 bits apply*/ -__sfr __at (0xEF) T4CC1; - -__sfr __at (0xF0) B ; -__sfr __at (0xF1) PERCFG; -/*PERCFG bits*/ -#define T1CFG 0x40 -#define T3CFG 0x20 -#define T4CFG 0x10 -#define U1CFG 0x02 -#define U0CFG 0x01 - -__sfr __at (0xF2) ADCCFG; -/*ADCCFG bits*/ -#define ADC7EN 0x80 -#define ADC6EN 0x40 -#define ADC5EN 0x20 -#define ADC4EN 0x10 -#define ADC3EN 0x08 -#define ADC2EN 0x04 -#define ADC1EN 0x02 -#define ADC0EN 0x01 - -__sfr __at (0xF3) P0SEL; -__sfr __at (0xF4) P1SEL; -__sfr __at (0xF5) P2SEL; -/*P2SEL bits*/ -#define PRI3P1 0x40 -#define PRI2P1 0x20 -#define PRI1P1 0x10 -#define PRI0P1 0x08 -#define SELP2_4 0x04 -#define SELP2_3 0x02 -#define SELP2_0 0x01 - -__sfr __at (0xF6) P1INP; - -__sfr __at (0xF7) P2INP; -/*P2INP bits*/ -#define PDUP2 0x80 -#define PDUP1 0x40 -#define PDUP0 0x20 -#define MDP2_4 0x10 -#define MDP2_3 0x08 -#define MDP2_2 0x04 -#define MDP2_1 0x02 -#define MDP2_0 0x01 - -__sfr __at (0xF8) U1CSR; -__sfr __at (0xF9) U1BUF; -__sfr __at (0xFA) U1BAUD; -__sfr __at (0xFB) U1UCR; -__sfr __at (0xFC) U1GCR; -__sfr __at (0xFD) P0DIR; -__sfr __at (0xFE) P1DIR; - -__sfr __at (0xFF) P2DIR; -/*P2DIR bits*/ -#define PRI1P0 0x80 -#define PRI0P0 0x40 -#define DIRP2_4 0x10 -#define DIRP2_3 0x08 -#define DIRP2_2 0x04 -#define DIRP2_1 0x02 -#define DIRP2_0 0x01 - -/* IEN0 */ -/*__sbit __at (0xA8) EA ; -__sbit __at (0x99) TI ; -__sbit __at (0x9A) RB8 ; -__sbit __at (0x9B) TB8 ; -__sbit __at (0x9C) REN ; -__sbit __at (0x9D) SM2 ; -__sbit __at (0x9E) SM1 ; -__sbit __at (0x9F) SM0 ;*/ - - - -/* Interrupt numbers: address = (number * 8) + 3 */ -/*#undef IE0_VECTOR -#undef TF0_VECTOR -#undef IE1_VECTOR -#undef TF1_VECTOR -#undef SI0_VECTOR*/ - -/* CC2430 interrupt vectors */ -#define RFERR_VECTOR 0 -#define ADC_VECTOR 1 -#define URX0_VECTOR 2 -#define URX1_VECTOR 3 -#define ENC_VECTOR 4 -#define ST_VECTOR 5 -#define P2INT_VECTOR 6 -#define UTX0_VECTOR 7 -#define DMA_VECTOR 8 -#define T1_VECTOR 9 -#define T2_VECTOR 10 -#define T3_VECTOR 11 -#define T4_VECTOR 12 -#define P0INT_VECTOR 13 -#define UTX1_VECTOR 14 -#define P1INT_VECTOR 15 -#define RF_VECTOR 16 -#define WDT_VECTOR 17 - -/* RF control registers*/ -__xdata __at (0xDF02) unsigned char MDMCTRL0H; -__xdata __at (0xDF03) unsigned char MDMCTRL0L; -__xdata __at (0xDF04) unsigned char MDMCTRL1H; -__xdata __at (0xDF05) unsigned char MDMCTRL1L; -__xdata __at (0xDF06) unsigned char RSSIH; -__xdata __at (0xDF07) unsigned char RSSIL; -__xdata __at (0xDF08) unsigned char SYNCWORDH; -__xdata __at (0xDF09) unsigned char SYNCWORDL; -__xdata __at (0xDF0A) unsigned char TXCTRLH; -__xdata __at (0xDF0B) unsigned char TXCTRLL; -__xdata __at (0xDF0C) unsigned char RXCTRL0H; -__xdata __at (0xDF0D) unsigned char RXCTRL0L; -__xdata __at (0xDF0E) unsigned char RXCTRL1H; -__xdata __at (0xDF0F) unsigned char RXCTRL1L; -__xdata __at (0xDF10) unsigned char FSCTRLH; -__xdata __at (0xDF11) unsigned char FSCTRLL; -__xdata __at (0xDF12) unsigned char CSPX; -__xdata __at (0xDF13) unsigned char CSPY; -__xdata __at (0xDF14) unsigned char CSPZ; -__xdata __at (0xDF15) unsigned char CSPCTRL; -__xdata __at (0xDF16) unsigned char CSPT; -__xdata __at (0xDF17) unsigned char RFPWR; -#define ADI_RADIO_PD 0x10 -#define RREG_RADIO_PD 0x08 -#define RREG_DELAY_MASK 0x07 - -__xdata __at (0xDF20) unsigned char FSMTCH; -__xdata __at (0xDF21) unsigned char FSMTCL; -__xdata __at (0xDF22) unsigned char MANANDH; -__xdata __at (0xDF23) unsigned char MANANDL; -__xdata __at (0xDF24) unsigned char MANORH; -__xdata __at (0xDF25) unsigned char MANORL; -__xdata __at (0xDF26) unsigned char AGCCTRLH; -__xdata __at (0xDF27) unsigned char AGCCTRLL; - -__xdata __at (0xDF39) unsigned char FSMSTATE; -__xdata __at (0xDF3A) unsigned char ADCTSTH; -__xdata __at (0xDF3B) unsigned char ADCTSTL; -__xdata __at (0xDF3C) unsigned char DACTSTH; -__xdata __at (0xDF3D) unsigned char DACTSTL; - -__xdata __at (0xDF43) unsigned char IEEE_ADDR0; -__xdata __at (0xDF44) unsigned char IEEE_ADDR1; -__xdata __at (0xDF45) unsigned char IEEE_ADDR2; -__xdata __at (0xDF46) unsigned char IEEE_ADDR3; -__xdata __at (0xDF47) unsigned char IEEE_ADDR4; -__xdata __at (0xDF48) unsigned char IEEE_ADDR5; -__xdata __at (0xDF49) unsigned char IEEE_ADDR6; -__xdata __at (0xDF4A) unsigned char IEEE_ADDR7; -__xdata __at (0xDF4B) unsigned char PANIDH; -__xdata __at (0xDF4C) unsigned char PANIDL; -__xdata __at (0xDF4D) unsigned char SHORTADDRH; -__xdata __at (0xDF4E) unsigned char SHORTADDRL; -__xdata __at (0xDF4F) unsigned char IOCFG0; -__xdata __at (0xDF50) unsigned char IOCFG1; -__xdata __at (0xDF51) unsigned char IOCFG2; -__xdata __at (0xDF52) unsigned char IOCFG3; -__xdata __at (0xDF53) unsigned char RXFIFOCNT; -__xdata __at (0xDF54) unsigned char FSMTC1; -#define ABORTRX_ON_SRXON 0x20 -#define RX_INTERRUPTED 0x10 -#define AUTO_TX2RX_OFF 0x08 -#define RX2RX_TIME_OFF 0x04 -#define PENDING_OR 0x02 -#define ACCEPT_ACKPKT 0x01 - -__xdata __at (0xDF60) unsigned char CHVER; -__xdata __at (0xDF61) unsigned char CHIPID; -__xdata __at (0xDF62) unsigned char RFSTATUS; -#define TX_ACTIVE 0x10 -#define FIFO 0x08 -#define FIFOP 0x04 -#define SFD 0x02 -#define CCA 0x01 - -__xdata __at (0xDFC1) unsigned char U0BUF_SHADOW; - -__xdata __at (0xDFD9) unsigned char RFD_SHADOW; - -__xdata __at (0xDFF9) unsigned char U1BUF_SHADOW; - -__xdata __at (0xDFBA) unsigned int ADC_SHADOW; - -#endif /*REG_CC2430*/ +/** + * + * \file cc2430_sfr.h + * \brief CC2430 registers header file for CC2430. + * + * Definitions for CC2430 SFR registers. + * + * + */ + +#ifndef REG_CC2430_H +#define REG_CC2430_H + +#include "8051def.h" + +/* BYTE Register */ + +__sfr __at (0x80) P0 ; +/* P0 */ +__sbit __at (0x87) P0_7 ; +__sbit __at (0x86) P0_6 ; +__sbit __at (0x85) P0_5 ; +__sbit __at (0x84) P0_4 ; +__sbit __at (0x83) P0_3 ; +__sbit __at (0x82) P0_2 ; +__sbit __at (0x81) P0_1 ; +__sbit __at (0x80) P0_0 ; + +__sfr __at (0x81) SP ; +__sfr __at (0x82) DPL0 ; +__sfr __at (0x83) DPH0 ; +/*DPL and DPH correspond DPL0 and DPH0 (82-83)*/ +__sfr __at (0x84) DPL1; +__sfr __at (0x85) DPH1; +__sfr __at (0x86) U0CSR; +#define U_MODE 0x80 +#define U_RE 0x40 +#define U_SLAVE 0x20 +#define U_FE 0x10 +#define U_ERR 0x08 +#define U_RXB 0x04 +#define U_TXB 0x02 +#define U_ACTIVE 0x01 + +__sfr __at (0x87) PCON ; +/* PCON (0x87) */ +#define IDLE 0x01 + +__sfr __at (0x88) TCON ; +/* TCON (0x88) */ +__sbit __at (0x8F) TCON_URX1IF; +/*__sbit __at (0x8E) RES;*/ +__sbit __at (0x8D) TCON_ADCIF; +/*__sbit __at (0x8C) RES;*/ +__sbit __at (0x8B) TCON_URX0IF; +__sbit __at (0x8A) TCON_IT1; +__sbit __at (0x89) TCON_RFERRIF; +__sbit __at (0x88) TCON_IT0; + + +__sfr __at (0x89) P0IFG; +__sfr __at (0x8A) P1IFG; +__sfr __at (0x8B) P2IFG; +__sfr __at (0x8C) PICTL; +/*PICTL bits*/ +#define PADSC 0x40 +#define P2IEN 0x20 +#define P0IENH 0x10 +#define P0IENL 0x08 +#define P2ICON 0x04 +#define P1ICON 0x02 +#define P0ICON 0x01 + +__sfr __at (0x8D) P1IEN; +__sfr __at (0x8F) P0INP; + +__sfr __at (0x90) P1 ; +/* P1 */ +__sbit __at (0x90) P1_0 ; +__sbit __at (0x91) P1_1 ; +__sbit __at (0x92) P1_2 ; +__sbit __at (0x93) P1_3 ; +__sbit __at (0x94) P1_4 ; +__sbit __at (0x95) P1_5 ; +__sbit __at (0x96) P1_6 ; +__sbit __at (0x97) P1_7 ; + +__sfr __at (0x91) RFIM; +__sfr __at (0x92) DPS; +__sfr __at (0x93) _XPAGE; /*MPAGE as paging register for sdcc*/ +__sfr __at (0x94) T2CMP; +__sfr __at (0x95) ST0; +__sfr __at (0x96) ST1; +__sfr __at (0x97) ST2; +__sfr __at (0x98) S0CON ; + +__sbit __at (0x99) S0CON_ENCIF_1; +__sbit __at (0x98) S0CON_ENCIF_0; + +__sfr __at (0x99) HSRC; +__sfr __at (0x9A) IEN2; +/*IEN2 bits*/ +#define WDTIE 0x20 +#define P1IE 0x10 +#define UTX1IE 0x08 +#define UTX0IE 0x04 +#define P2IE 0x02 +#define RFIE 0x01 +__sfr __at (0x9B) S1CON; +/*S1CON bits*/ +#define RFIF_1 0x02 +#define RFIF_0 0x01 +__sfr __at (0x9C) T2PEROF0; +__sfr __at (0x9D) T2PEROF1; +__sfr __at (0x9E) T2PEROF2; +/*T2PEROF2 bits*/ +#define CMPIM 0x80 +#define PERIM 0x40 +#define OFCMPIM 0x20 + +#define PEROF23 0x08 +#define PEROF22 0x04 +#define PEROF21 0x02 +#define PEROF20 0x01 + +__sfr __at (0x9F) FMAP; +__sfr __at (0x9F) PSBANK; + +__sfr __at (0xA0) P2 ; +/* P2 */ +__sbit __at (0xA0) P2_0 ; +__sbit __at (0xA1) P2_1 ; +__sbit __at (0xA2) P2_2 ; +__sbit __at (0xA3) P2_3 ; +__sbit __at (0xA4) P2_4 ; +/*__sbit __at (0xA5) P2_5 ; +__sbit __at (0xA6) P2_6 ; +__sbit __at (0xA7) P2_7 ;*/ + +__sfr __at (0xA1) T2OF0; +__sfr __at (0xA2) T2OF1; +__sfr __at (0xA3) T2OF2; +__sfr __at (0xA4) T2CAPLPL; +__sfr __at (0xA5) T2CAPHPH; +__sfr __at (0xA6) T2TLD; +__sfr __at (0xA7) T2THD; + +__sfr __at (0xA8) IE ; +__sfr __at (0xA8) IEN0; +/*IEN0 bits*/ +#define IEN0_EA_MASK 0x80 +#define STIE 0x20 +#define ENCIE 0x10 +#define URX1IE 0x08 +#define URX0IE 0x04 +#define ADCIE 0x02 +#define RFERRIE 0x01 +/* IEN0 (0xA8) */ +__sbit __at (0xAF) EA; +__sbit __at (0xAF) IEN0_EA; +/*__sbit __at (0xAE) RES;*/ +__sbit __at (0xAD) IEN0_STIE; +__sbit __at (0xAC) IEN0_ENCIE; +__sbit __at (0xAB) IEN0_URX1IE; +__sbit __at (0xAA) IEN0_URX0IE; +__sbit __at (0xA9) IEN0_ADCIE; +__sbit __at (0xA8) IEN0_RFERRIE; + +__sfr __at (0xA9) IP0; +/*IP0 bits*/ +#define IP0_5 0x20 +#define IP0_4 0x10 +#define IP0_3 0x08 +#define IP0_2 0x04 +#define IP0_1 0x02 +#define IP0_0 0x01 +__sfr __at (0xAB) FWT; +__sfr __at (0xAC) FADDRL; +__sfr __at (0xAD) FADDRH; + +__sfr __at (0xAE) FCTL; +#define F_BUSY 0x80 +#define F_SWBSY 0x40 +#define F_CONTRD 0x10 +#define F_WRITE 0x02 +#define F_ERASE 0x01 +__sfr __at (0xAF) FWDATA; + +/*No port 3 (0xB0)*/ +__sfr __at (0xB1) ENCDI; +__sfr __at (0xB2) ENCDO; +__sfr __at (0xB3) ENCCS; +#define CCS_MODE2 0x40 +#define CCS_MODE1 0x20 +#define CCS_MODE0 0x10 +#define CCS_RDY 0x08 +#define CCS_CMD1 0x04 +#define CCS_CMD0 0x02 +#define CCS_ST 0x01 +__sfr __at (0xB4) ADCCON1; +/*ADCCON1 bits*/ +#define ADEOC 0x80 +#define ADST 0x40 +#define ADSTS1 0x20 +#define ADSTS0 0x10 +#define ADRCTRL1 0x08 +#define ADRCTRL0 0x04 +__sfr __at (0xB5) ADCCON2; +/*ADCCON2 bits*/ +#define ADSREF1 0x80 +#define ADSREF0 0x40 +#define ADSDIV1 0x20 +#define ADSDIV0 0x10 +#define ADSCH3 0x08 +#define ADSCH2 0x04 +#define ADSCH1 0x02 +#define ADSCH0 0x01 +__sfr __at (0xB6) ADCCON3; +/*ADCCON3 bits*/ +#define ADEREF1 0x80 +#define ADEREF0 0x40 +#define ADEDIV1 0x20 +#define ADEDIV0 0x10 +#define ADECH3 0x08 +#define ADECH2 0x04 +#define ADECH1 0x02 +#define ADECH0 0x01 + +__sfr __at (0xB7) RCCTL; +#undef IP /*this is 0xb8 in base core*/ + +__sfr __at (0xB8) IEN1; +/*IEN1 bits*/ +#define P0IE 0x20 +#define T4IE 0x10 +#define T3IE 0x08 +#define T2IE 0x04 +#define T1IE 0x02 +#define DMAIE 0x01 +/* IEN1 (0xB8) */ +/*__sbit __at (0xBF) IEN1_RES;*/ +/*__sbit __at (0xBE) RES;*/ +__sbit __at (0xBD) IEN1_P0IE; +__sbit __at (0xBC) IEN1_T4IE; +__sbit __at (0xBB) IEN1_T3IE; +__sbit __at (0xBA) IEN1_T2IE; +__sbit __at (0xB9) IEN1_T1IE; +__sbit __at (0xB8) IEN1_DMAIE; + +__sfr __at (0xB9) IP1; +/*IP1 bits*/ +#define IP1_5 0x20 +#define IP1_4 0x10 +#define IP1_3 0x08 +#define IP1_2 0x04 +#define IP1_1 0x02 +#define IP1_0 0x01 + +__sfr __at (0xBA) ADCL; +__sfr __at (0xBB) ADCH; +__sfr __at (0xBC) RNDL; +__sfr __at (0xBD) RNDH; + +__sfr __at (0xBE) SLEEP; +#define OSC32K_CALDIS 0x80 +#define XOSC_STB 0x40 +#define HFRC_STB 0x20 +#define RST1 0x10 +#define RST0 0x08 +#define OSC_PD 0x04 +#define SLEEP_MODE1 0x02 +#define SLEEP_MODE0 0x01 + +__sfr __at (0xC0) IRCON; +/*IRCON bits*/ +#define STIF 0x80 +#define P0IF 0x20 +#define T4IF 0x10 +#define T3IF 0x08 +#define T2IF 0x04 +#define T1IF 0x02 +#define DMAIF 0x01 +/* IRCON */ +__sbit __at (0xC7) IRCON_STIF ; +/*__sbit __at (0x86) IRCON_6 ;*/ +__sbit __at (0xC5) IRCON_P0IF; +__sbit __at (0xC4) IRCON_T4IF; +__sbit __at (0xC3) IRCON_T3IF; +__sbit __at (0xC2) IRCON_T2IF; +__sbit __at (0xC1) IRCON_T1IF; +__sbit __at (0xC0) IRCON_DMAIF; + +__sfr __at (0xC1) U0BUF; + +__sfr __at (0xC2) U0BAUD; +__sfr __at (0xC3) T2CNF; +/*T2SEL bits*/ +#define CMPIF 0x80 +#define PERIF 0x40 +#define OFCMPIF 0x20 + +#define CMSEL 0x08 + +#define SYNC 0x02 +#define RUN 0x01 + +__sfr __at (0xC4) U0UCR; +#define U_FLUSH 0x80 +#define U_FLOW 0x40 +#define U_D9 0x20 +#define U_BIT9 0x10 +#define U_PARITY 0x08 +#define U_SPB 0x04 +#define U_STOP 0x02 +#define U_START 0x01 + +__sfr __at (0xC5) U0GCR; +#define U_CPOL 0x80 +#define U_CPHA 0x40 +#define U_ORDER 0x20 +#define U_BAUD_E4 0x10 +#define U_BAUD_E3 0x08 +#define U_BAUD_E2 0x04 +#define U_BAUD_E1 0x02 +#define U_BAUD_E0 0x01 + +__sfr __at (0xC6) CLKCON; +#define OSC32K 0x80 +#define OSC 0x40 +#define TICKSPD2 0x20 +#define TICKSPD1 0x10 +#define TICKSPD0 0x08 +#define CLKSPD 0x01 + +__sfr __at (0xC7) MEMCTR; +#define MUNIF 0x40 +__sfr __at (0xC8) T2CON; + +__sfr __at (0xC9) WDCTL; +#define WDT_CLR3 0x80 +#define WDT_CLR2 0x40 +#define WDT_CLR1 0x20 +#define WDT_CLR0 0x10 +#define WDT_EN 0x08 +#define WDT_MODE 0x04 +#define WDT_INT1 0x02 +#define WDT_INT0 0x01 + +__sfr __at (0xCA) T3CNT; + +__sfr __at (0xCB) T3CTL; +/*T3CTL bits*/ +#define T3DIV2 0x80 +#define T3DIV1 0x40 +#define T3DIV0 0x20 +#define T3START 0x10 +#define T3OVFIM 0x08 +#define T3CLR 0x04 +#define T3MODE1 0x02 +#define T3MODE0 0x01 + +__sfr __at (0xCC) T3CCTL0; +/*T3CCTL0 bits*/ +#define T3IM 0x40 +#define T3CMP2 0x20 +#define T3CMP1 0x10 +#define T3CMP0 0x08 +#define T3MODE 0x04 +#define T3CAP1 0x02 +#define T3CAP0 0x01 + +__sfr __at (0xCD) T3CC0; +__sfr __at (0xCE) T3CCTL1; +/*T3CCTL0 bits apply*/ +__sfr __at (0xCF) T3CC1; + +__sfr __at (0xD0) PSW ; +/* PSW */ +__sbit __at (0xD0) P ; +__sbit __at (0xD1) F1 ; +__sbit __at (0xD2) OV ; +__sbit __at (0xD3) RS0 ; +__sbit __at (0xD4) RS1 ; +__sbit __at (0xD5) F0 ; +__sbit __at (0xD6) AC ; +__sbit __at (0xD7) CY ; + +__sfr __at (0xD1) DMAIRQ; +/*DMAIRQ bits*/ +#define DMAIF4 0x10 +#define DMAIF3 0x08 +#define DMAIF2 0x04 +#define DMAIF1 0x02 +#define DMAIF0 0x01 + +__sfr __at (0xD2) DMA1CFGL; +__sfr __at (0xD3) DMA1CFGH; +__sfr __at (0xD4) DMA0CFGL; +__sfr __at (0xD5) DMA0CFGH; + +__sfr __at (0xD6) DMAARM; +/*DMAARM bits*/ +#define ABORT 0x80 +#define DMAARM4 0x10 +#define DMAARM3 0x08 +#define DMAARM2 0x04 +#define DMAARM1 0x02 +#define DMAARM0 0x01 + +__sfr __at (0xD7) DMAREQ; +/*DMAREQ bits*/ +#define DMAREQ4 0x10 +#define DMAREQ3 0x08 +#define DMAREQ2 0x04 +#define DMAREQ1 0x02 +#define DMAREQ0 0x01 + +__sfr __at (0xD8) TIMIF; +/*TIMIF bits*/ +#define OVFIM 0x40 +#define T4CH1IF 0x20 +#define T4CH0IF 0x10 +#define T4OVFIF 0x08 +#define T3CH1IF 0x04 +#define T3CH0IF 0x02 +#define T3OVFIF 0x01 + +__sfr __at (0xD9) RFD; +__sfr __at (0xDA) T1CC0L; +__sfr __at (0xDB) T1CC0H; +__sfr __at (0xDC) T1CC1L; +__sfr __at (0xDD) T1CC1H; +__sfr __at (0xDE) T1CC2L; +__sfr __at (0xDF) T1CC2H; + +__sfr __at (0xE0) ACC; +__sfr __at (0xE1) RFST; +__sfr __at (0xE2) T1CNTL; +__sfr __at (0xE3) T1CNTH; + +__sfr __at (0xE4) T1CTL; +/*T1CTL bits*/ +#define CH2IF 0x80 +#define CH1IF 0x40 +#define CH0IF 0x20 +#define OVFIF 0x10 +#define T1DIV1 0x08 +#define T1DIV0 0x04 +#define T1MODE1 0x02 +#define T1MODE0 0x01 + +__sfr __at (0xE5) T1CCTL0; +/*T1CCTL0 bits*/ +#define T1CPSEL 0x80 +#define T1IM 0x40 +#define T1CMP2 0x20 +#define T1CMP1 0x10 +#define T1CMP0 0x08 +#define T1MODE 0x04 +#define T1CAP1 0x02 +#define T1CAP0 0x01 + +__sfr __at (0xE6) T1CCTL1; +/*Bits defined in T1CCTL0 */ +__sfr __at (0xE7) T1CCTL2; +/*Bits defined in T1CCTL0 */ +__sfr __at (0xE8) IRCON2; +/*IRCON2 bits*/ +#define WDTIF 0x10 +#define P1IF 0x08 +#define UTX1IF 0x04 +#define UTX0IF 0x02 +#define P2IF 0x01 +/* IRCON 2 */ +/*__sbit __at (0xEF) IRCON2_P1_7 ; +__sbit __at (0xEE) IRCON2_P1_6 ; +__sbit __at (0xED) IRCON2_P1_5 ;*/ +__sbit __at (0xEC) IRCON2_WDTIF ; +__sbit __at (0xEB) IRCON2_P1IF ; +__sbit __at (0xEA) IRCON2_UTX1IF ; +__sbit __at (0xE9) IRCON2_UTX0IF ; +__sbit __at (0xE8) IRCON2_P2IF; + + +__sfr __at (0xE9) RFIF; +/*RFIF bits*/ +#define IRQ_RREG_ON 0x80 +#define IRQ_TXDONE 0x40 +#define IRQ_FIFOP 0x20 +#define IRQ_SFD 0x10 +#define IRQ_CCA 0x08 +#define IRQ_CSP_WT 0x04 +#define IRQ_CSP_STOP 0x02 +#define IRQ_CSP_INT 0x01 + +__sfr __at (0xEA) T4CNT; +__sfr __at (0xEB) T4CTL; +/*T4CTL bits*/ +#define T4DIV2 0x80 +#define T4DIV1 0x40 +#define T4DIV0 0x20 +#define T4START 0x10 +#define T4OVFIM 0x08 +#define T4CLR 0x04 +#define T4MODE1 0x02 +#define T4MODE0 0x01 + +__sfr __at (0xEC) T4CCTL0; +/*T4CCTL0 bits*/ +#define T4IM 0x40 +#define T4CMP2 0x20 +#define T4CMP1 0x10 +#define T4CMP0 0x08 +#define T4MODE 0x04 +#define T4CAP1 0x02 +#define T4CAP0 0x01 + +__sfr __at (0xED) T4CC0; +__sfr __at (0xEE) T4CCTL1; +/*T4CCTL0 bits apply*/ +__sfr __at (0xEF) T4CC1; + +__sfr __at (0xF0) B ; +__sfr __at (0xF1) PERCFG; +/*PERCFG bits*/ +#define T1CFG 0x40 +#define T3CFG 0x20 +#define T4CFG 0x10 +#define U1CFG 0x02 +#define U0CFG 0x01 + +__sfr __at (0xF2) ADCCFG; +/*ADCCFG bits*/ +#define ADC7EN 0x80 +#define ADC6EN 0x40 +#define ADC5EN 0x20 +#define ADC4EN 0x10 +#define ADC3EN 0x08 +#define ADC2EN 0x04 +#define ADC1EN 0x02 +#define ADC0EN 0x01 + +__sfr __at (0xF3) P0SEL; +__sfr __at (0xF4) P1SEL; +__sfr __at (0xF5) P2SEL; +/*P2SEL bits*/ +#define PRI3P1 0x40 +#define PRI2P1 0x20 +#define PRI1P1 0x10 +#define PRI0P1 0x08 +#define SELP2_4 0x04 +#define SELP2_3 0x02 +#define SELP2_0 0x01 + +__sfr __at (0xF6) P1INP; + +__sfr __at (0xF7) P2INP; +/*P2INP bits*/ +#define PDUP2 0x80 +#define PDUP1 0x40 +#define PDUP0 0x20 +#define MDP2_4 0x10 +#define MDP2_3 0x08 +#define MDP2_2 0x04 +#define MDP2_1 0x02 +#define MDP2_0 0x01 + +__sfr __at (0xF8) U1CSR; +__sfr __at (0xF9) U1BUF; +__sfr __at (0xFA) U1BAUD; +__sfr __at (0xFB) U1UCR; +__sfr __at (0xFC) U1GCR; +__sfr __at (0xFD) P0DIR; +__sfr __at (0xFE) P1DIR; + +__sfr __at (0xFF) P2DIR; +/*P2DIR bits*/ +#define PRI1P0 0x80 +#define PRI0P0 0x40 +#define DIRP2_4 0x10 +#define DIRP2_3 0x08 +#define DIRP2_2 0x04 +#define DIRP2_1 0x02 +#define DIRP2_0 0x01 + +/* IEN0 */ +/*__sbit __at (0xA8) EA ; +__sbit __at (0x99) TI ; +__sbit __at (0x9A) RB8 ; +__sbit __at (0x9B) TB8 ; +__sbit __at (0x9C) REN ; +__sbit __at (0x9D) SM2 ; +__sbit __at (0x9E) SM1 ; +__sbit __at (0x9F) SM0 ;*/ + + + +/* Interrupt numbers: address = (number * 8) + 3 */ +/*#undef IE0_VECTOR +#undef TF0_VECTOR +#undef IE1_VECTOR +#undef TF1_VECTOR +#undef SI0_VECTOR*/ + +/* CC2430 interrupt vectors */ +#define RFERR_VECTOR 0 +#define ADC_VECTOR 1 +#define URX0_VECTOR 2 +#define URX1_VECTOR 3 +#define ENC_VECTOR 4 +#define ST_VECTOR 5 +#define P2INT_VECTOR 6 +#define UTX0_VECTOR 7 +#define DMA_VECTOR 8 +#define T1_VECTOR 9 +#define T2_VECTOR 10 +#define T3_VECTOR 11 +#define T4_VECTOR 12 +#define P0INT_VECTOR 13 +#define UTX1_VECTOR 14 +#define P1INT_VECTOR 15 +#define RF_VECTOR 16 +#define WDT_VECTOR 17 + +/* RF control registers*/ +__xdata __at (0xDF02) unsigned char MDMCTRL0H; +__xdata __at (0xDF03) unsigned char MDMCTRL0L; +__xdata __at (0xDF04) unsigned char MDMCTRL1H; +__xdata __at (0xDF05) unsigned char MDMCTRL1L; +__xdata __at (0xDF06) unsigned char RSSIH; +__xdata __at (0xDF07) unsigned char RSSIL; +__xdata __at (0xDF08) unsigned char SYNCWORDH; +__xdata __at (0xDF09) unsigned char SYNCWORDL; +__xdata __at (0xDF0A) unsigned char TXCTRLH; +__xdata __at (0xDF0B) unsigned char TXCTRLL; +__xdata __at (0xDF0C) unsigned char RXCTRL0H; +__xdata __at (0xDF0D) unsigned char RXCTRL0L; +__xdata __at (0xDF0E) unsigned char RXCTRL1H; +__xdata __at (0xDF0F) unsigned char RXCTRL1L; +__xdata __at (0xDF10) unsigned char FSCTRLH; +__xdata __at (0xDF11) unsigned char FSCTRLL; +__xdata __at (0xDF12) unsigned char CSPX; +__xdata __at (0xDF13) unsigned char CSPY; +__xdata __at (0xDF14) unsigned char CSPZ; +__xdata __at (0xDF15) unsigned char CSPCTRL; +__xdata __at (0xDF16) unsigned char CSPT; +__xdata __at (0xDF17) unsigned char RFPWR; +#define ADI_RADIO_PD 0x10 +#define RREG_RADIO_PD 0x08 +#define RREG_DELAY_MASK 0x07 + +__xdata __at (0xDF20) unsigned char FSMTCH; +__xdata __at (0xDF21) unsigned char FSMTCL; +__xdata __at (0xDF22) unsigned char MANANDH; +__xdata __at (0xDF23) unsigned char MANANDL; +__xdata __at (0xDF24) unsigned char MANORH; +__xdata __at (0xDF25) unsigned char MANORL; +__xdata __at (0xDF26) unsigned char AGCCTRLH; +__xdata __at (0xDF27) unsigned char AGCCTRLL; + +__xdata __at (0xDF39) unsigned char FSMSTATE; +__xdata __at (0xDF3A) unsigned char ADCTSTH; +__xdata __at (0xDF3B) unsigned char ADCTSTL; +__xdata __at (0xDF3C) unsigned char DACTSTH; +__xdata __at (0xDF3D) unsigned char DACTSTL; + +__xdata __at (0xDF43) unsigned char IEEE_ADDR0; +__xdata __at (0xDF44) unsigned char IEEE_ADDR1; +__xdata __at (0xDF45) unsigned char IEEE_ADDR2; +__xdata __at (0xDF46) unsigned char IEEE_ADDR3; +__xdata __at (0xDF47) unsigned char IEEE_ADDR4; +__xdata __at (0xDF48) unsigned char IEEE_ADDR5; +__xdata __at (0xDF49) unsigned char IEEE_ADDR6; +__xdata __at (0xDF4A) unsigned char IEEE_ADDR7; +__xdata __at (0xDF4B) unsigned char PANIDH; +__xdata __at (0xDF4C) unsigned char PANIDL; +__xdata __at (0xDF4D) unsigned char SHORTADDRH; +__xdata __at (0xDF4E) unsigned char SHORTADDRL; +__xdata __at (0xDF4F) unsigned char IOCFG0; +__xdata __at (0xDF50) unsigned char IOCFG1; +__xdata __at (0xDF51) unsigned char IOCFG2; +__xdata __at (0xDF52) unsigned char IOCFG3; +__xdata __at (0xDF53) unsigned char RXFIFOCNT; +__xdata __at (0xDF54) unsigned char FSMTC1; +#define ABORTRX_ON_SRXON 0x20 +#define RX_INTERRUPTED 0x10 +#define AUTO_TX2RX_OFF 0x08 +#define RX2RX_TIME_OFF 0x04 +#define PENDING_OR 0x02 +#define ACCEPT_ACKPKT 0x01 + +__xdata __at (0xDF60) unsigned char CHVER; +__xdata __at (0xDF61) unsigned char CHIPID; +__xdata __at (0xDF62) unsigned char RFSTATUS; +#define TX_ACTIVE 0x10 +#define FIFO 0x08 +#define FIFOP 0x04 +#define SFD 0x02 +#define CCA 0x01 + +__xdata __at (0xDFC1) unsigned char U0BUF_SHADOW; + +__xdata __at (0xDFD9) unsigned char RFD_SHADOW; + +__xdata __at (0xDFF9) unsigned char U1BUF_SHADOW; + +__xdata __at (0xDFBA) unsigned int ADC_SHADOW; + +#endif /*REG_CC2430*/ diff --git a/cpu/cc2430/converter/converter b/cpu/cc2430/converter/converter deleted file mode 100755 index 9b47ea14a..000000000 Binary files a/cpu/cc2430/converter/converter and /dev/null differ diff --git a/cpu/cc2430/converter/converter.c b/cpu/cc2430/converter/converter.c index 7ce442bae..56d12ecc9 100644 --- a/cpu/cc2430/converter/converter.c +++ b/cpu/cc2430/converter/converter.c @@ -13,7 +13,7 @@ void usage(char *prg_name) { printf("\nUsage: %s -f ihex file\n", prg_name); printf("General options:\n"); - printf(" -V/--version Get converter version\n"); + printf(" -v/--version Get converter version\n"); } conf_opts_t conf_opts; @@ -22,11 +22,11 @@ static int option_index = 0; int do_exit = 0; -#define OPTIONS_STRING "Vhf:" +#define OPTIONS_STRING "vhf:" /* long option list */ static struct option long_options[] = { - {"version", 0, NULL, 'V'}, + {"version", 0, NULL, 'v'}, {"file", 1, NULL, 'f'}, {"help", 0, NULL, 'h'}, {0, 0, 0, 0} @@ -43,7 +43,7 @@ int parse_opts(int count, char* param[]) { switch(opt) { - case 'V': + case 'v': conf_opts.target_type = VERSION; break; @@ -73,6 +73,7 @@ int main(int argc, char *argv[]) conf_opts.target_type = 0; + printf("Sensinode hex file converter "CONVERTER_VERSION "\n"); if ( (argc < 1) || (error = parse_opts(argc, argv)) ) { usage(argv[0]); @@ -133,14 +134,14 @@ int main(int argc, char *argv[]) } else if (memcmp(&buffer[7], "01", 2) == 0) { /*end file*/ - printf("\nFile read complete.\n"); + printf("File read complete.\n"); break; } else if (memcmp(&buffer[7], "04", 2) == 0) { sscanf((char *)&(buffer[3]),"%4hx", &addr); sscanf((char *)&(buffer[9]),"%4lx", &ext_addr); - printf("\rExtended page address: 0x%8.8lX\r", ext_addr*0x8000 ); + /*printf("Extended page address: 0x%8.8lX\n", ext_addr*0x8000 );*/ if (ext_addr >= 0x0002) sdcc_file = 1; @@ -166,7 +167,7 @@ int main(int argc, char *argv[]) *ptr = 0; } } - strcat(conf_opts.ihex_file, "_linear.hex"); + strcat(conf_opts.ihex_file, ".hex"); printf("Output file: %s.\n", conf_opts.ihex_file); ihex = fopen(conf_opts.ihex_file, "wb"); ext_addr=0; @@ -180,7 +181,7 @@ int main(int argc, char *argv[]) addr = (i & 0x1F) * 2048; if ( ((i / 32) * 0x10000) != ext_addr) { /*write out ext addr*/ - printf("Ext: %4.4X\n", ((i / 32) * 0x10000)); + /*printf("Ext: %4.4X\n", ((i / 32) * 0x10000));*/ ext_addr = (i / 32) * 0x10000; fprintf(ihex, ":02000004%4.4X%2.2X\r\n", (int)(ext_addr>>16), (int)(0xFA-(ext_addr>>16))); @@ -188,7 +189,7 @@ int main(int argc, char *argv[]) if (page_table[i] != 0) { - printf("%4.4X", addr & 0xF800); + /*printf("%4.4X", addr & 0xF800);*/ for (j=0; j<2048; j++) { addr =(i & 0x1F) * 2048 + j; @@ -208,8 +209,10 @@ int main(int argc, char *argv[]) } } } + /* if ((i & 0x07) == 0x07) printf("\n"); else printf(" "); + */ } fprintf(ihex, ":00000001FF\r\n"); printf("Write complete.\n"); @@ -220,9 +223,5 @@ int main(int argc, char *argv[]) { usage(argv[0]); } - else - { - printf("\nSensinode hex file converter "CONVERTER_VERSION "\n"); - } return error; } diff --git a/cpu/cc2430/converter/converter.h b/cpu/cc2430/converter/converter.h index 8457b1809..cde769b72 100644 --- a/cpu/cc2430/converter/converter.h +++ b/cpu/cc2430/converter/converter.h @@ -1,7 +1,7 @@ #ifndef CONVERTER_H #define CONVERTER_H -#define CONVERTER_VERSION "v1.3" +#define CONVERTER_VERSION "v1.4" typedef struct { int target_type; diff --git a/cpu/cc2430/converter/converter.o b/cpu/cc2430/converter/converter.o deleted file mode 100644 index fa67f8fe1..000000000 Binary files a/cpu/cc2430/converter/converter.o and /dev/null differ diff --git a/cpu/cc2430/converter/ihex.o b/cpu/cc2430/converter/ihex.o deleted file mode 100644 index 451888a2b..000000000 Binary files a/cpu/cc2430/converter/ihex.o and /dev/null differ diff --git a/cpu/cc2430/dev/adc.c b/cpu/cc2430/dev/adc.c deleted file mode 100644 index eda932a2a..000000000 --- a/cpu/cc2430/dev/adc.c +++ /dev/null @@ -1,70 +0,0 @@ -/** - * \file - * ADC functions - * \author - * Anthony "Asterisk" Ambuehl - * - * ADC initialization routine, trigger and result conversion routines. - * - */ - -#include -#include "banked.h" -#include "contiki.h" -#include "sys/clock.h" - -#include "cc2430_sfr.h" -#include "dev/adc.h" -#include "dev/dma.h" - -#ifdef HAVE_DMA -xDMAHandle adc_dma=0xff; -unsigned int *adc_dma_dest; -#endif - -/*---------------------------------------------------------------------------*/ -void adc_init(void) __banked -{ - unsigned char jj; - while (!SLEEP&(HFRC_STB)) {} - /* power both 32MHz crystal and 15MHz RC */ - SLEEP &= ~(OSC_PD); - /* printf("SLEEP 1 %x\n",SLEEP); */ - /* then wait for it to stabilize */ - while (!SLEEP&(XOSC_STB)) {} - /* printf("SLEEP 2 %x\n",SLEEP); */ - /* then wait 64uS more */ - clock_delay(150); - /* switch to 32MHz clock */ - /* printf("switch to 32MHz %x\n",CLKCON); */ - CLKCON &= ~(OSC); - /* printf("switched to 32MHz %x\n",CLKCON); */ - /* power down 15MHz RC clock */ - SLEEP |= OSC_PD; - /* printf("pwr down hfrc\n",SLEEP); */ -#ifdef HAVE_DMA - /* preconfigure adc_dma before calling adc_init if a different dma type is desired. */ - if (adc_dma==0xff) { - dma_init(); - /* config DMA channel to copy results to single location */ - adc_dma=dma_config2(ADC_DMA_CONFIG_CHANNEL, &ADC_SHADOW, DMA_NOINC, adc_dma_dest, DMA_NOINC, 1, 1, DMA_VLEN_LEN, DMA_RPT, DMA_T_ADC_CHALL, 0); - } -#endif -} -/* single sample trigger */ -void adc_single_shot(void) __banked -{ - ADCCON1 |= 0x73; -} -/* convert adc results */ -int16_t adc_convert_result(int16_t data) __banked { - data = (0xfffc&data)>>2; - return data; -} -/* read/convert last conversion result */ -int16_t adc_get_last_conv() __banked { - int16_t result; - result = (ADCH<<8)|(ADCL); - result = (0xfffc&result)>>2; - return result; -} diff --git a/cpu/cc2430/dev/adc.h b/cpu/cc2430/dev/adc.h deleted file mode 100644 index 5a8ea431d..000000000 --- a/cpu/cc2430/dev/adc.h +++ /dev/null @@ -1,41 +0,0 @@ -/** - * \file - * Header file for ADC. - * \author - * Anthony "Asterisk" Ambuehl - * - */ - -#ifndef __ADC_H -#define __ADC_H -#define ADC_DMA_CONFIG_CHANNEL 1 -#define ADC_CHANNELS 8 -#include "cc2430_sfr.h" -#include "dma.h" -#include "banked.h" - -typedef struct adc_result -{ - uint16_t adc:14; - uint16_t unused:2; -} adc_result_t; - -typedef enum adc_stsel_t -{ - EXT = 0, /* externally triggered by P2_0 */ - CONTINUOUS = 1, /* continuous full speed conversion */ - TIMER1 = 2, /* Timer 1 channel 0 compare event */ - ST = 3 /* ADCCON1.ST = 1 */ -} adc_stsel_t; - -extern void adc_init(void) __banked; -extern void adc_single_shot(void) __banked; -extern int16_t adc_convert_result(int16_t ptr) __banked; -extern int16_t adc_get_last_conv() __banked; -extern void adc_dma_callback(void) __banked; -#ifdef HAVE_DMA -extern xDMAHandle adc_dma; -extern unsigned int *adc_dma_dest; -#endif - -#endif /*__ADC_H*/ diff --git a/cpu/cc2430/dev/banked.h b/cpu/cc2430/dev/banked.h deleted file mode 100644 index d5cb55ca2..000000000 --- a/cpu/cc2430/dev/banked.h +++ /dev/null @@ -1,40 +0,0 @@ -/** - * \file - * - * SDCC bank switching macro define file - * - * \author - * - * Anthony "Asterisk" Ambuehl - * - * SDCC (small device cross compiler) has built-in support for bank switching using predefined macros __banked. - * To avoid compilation issues on other compilers include this file which will replace __banked with the empty string on unsupported compilers. - * - * In addition, the file can add the codeseg pragma to place code into specific banks, if specific macro is set. - * However the same result can be achieved by using the segment.rules file. - * - */ - -#ifndef __BANKED_H -#ifdef SDCC -#ifndef HAVE_SDCC_BANKING -#define __banked -#else -#ifdef BANKED_IN_HOME -#pragma codeseg HOME -#endif -#ifdef BANKED_IN_BANK1 -#pragma codeseg BANK1 -#endif -#ifdef BANKED_IN_BANK2 -#pragma codeseg BANK2 -#endif -#ifdef BANKED_IN_BANK3 -#pragma codeseg BANK3 -#endif -#endif -#else -#define __banked -#endif - -#endif /*__BANKED_H*/ diff --git a/cpu/cc2430/dev/bus.c b/cpu/cc2430/dev/bus.c index 48470f7f7..0274ce3d6 100644 --- a/cpu/cc2430/dev/bus.c +++ b/cpu/cc2430/dev/bus.c @@ -38,14 +38,14 @@ * Adam Dunkels */ -#include "banked.h" #include "cc2430_sfr.h" #include "dev/bus.h" #include "sys/clock.h" +#include "contiki-conf.h" /*---------------------------------------------------------------------------*/ void -bus_init (void) __banked +bus_init (void) { CLKCON = (0x00 | OSC32K); /* 32k internal */ while(CLKCON != (0x00 | OSC32K)); @@ -65,8 +65,9 @@ bus_init (void) __banked * \param buffer buffer to store data * \param size number of bytes to read */ +#if !SHORTCUTS_CONF_FLASH_READ void -flash_read (uint8_t *buf, uint32_t address, uint8_t size) __banked +flash_read(uint8_t *buf, uint32_t address, uint8_t size) { buf; /*dptr0*/ address; /*stack-6*/ @@ -130,4 +131,5 @@ lp1: ENABLE_INTERRUPTS(); DPL1 = *buf++; } +#endif /*---------------------------------------------------------------------------*/ diff --git a/cpu/cc2430/dev/bus.h b/cpu/cc2430/dev/bus.h index 746fc637d..6c20dac54 100644 --- a/cpu/cc2430/dev/bus.h +++ b/cpu/cc2430/dev/bus.h @@ -44,11 +44,14 @@ #include "cc2430_sfr.h" #include "8051def.h" +#include "contiki-conf.h" #define inline -void bus_init(void) __banked; -void flash_read(uint8_t *buf, uint32_t address, uint8_t size) __banked; -void cc2430_clock_ISR( void ) __interrupt (ST_VECTOR); +void bus_init(void); +#if !SHORTCUTS_CONF_FLASH_READ +void flash_read(uint8_t *buf, uint32_t address, uint8_t size); +#endif +void clock_ISR( void ) __interrupt (ST_VECTOR); #endif /* __BUS_H__ */ diff --git a/cpu/cc2430/dev/cc2430_rf.c b/cpu/cc2430/dev/cc2430_rf.c index ed1d92bba..934bb7a23 100644 --- a/cpu/cc2430/dev/cc2430_rf.c +++ b/cpu/cc2430/dev/cc2430_rf.c @@ -2,7 +2,10 @@ * \file * CC2430 RF driver * \author - * Zach Shelby + * Zach Shelby (Original) + * George Oikonomou - + * (port to the netstack API, hexdump output, RX FIFO overflow fixes + * code cleanup, ...) * * bankable code for cc2430 rf driver. this code can be placed in any bank. * @@ -15,17 +18,31 @@ #include "dev/cc2430_rf.h" #include "cc2430_sfr.h" #include "sys/clock.h" +#include "sys/rtimer.h" #include "net/packetbuf.h" #include "net/rime/rimestats.h" +#include "net/netstack.h" -extern void (* receiver_callback)(const struct radio_driver *); -#ifndef RF_DEFAULT_POWER -#define RF_DEFAULT_POWER 100 +#define CC2430_RF_TX_POWER_RECOMMENDED 0x5F +#ifdef CC2430_RF_CONF_TX_POWER +#define CC2430_RF_TX_POWER CC2430_RF_CONF_TX_POWER +#else +#define CC2430_RF_TX_POWER CC2430_RF_TX_POWER_RECOMMENDED #endif -#ifndef RF_DEFAULT_CHANNEL -#define RF_DEFAULT_CHANNEL 18 +#ifdef CC2430_RF_CONF_CHANNEL +#define CC2430_RF_CHANNEL CC2430_RF_CONF_CHANNEL +#else +#define CC2430_RF_CHANNEL 18 +#endif /* CC2430_RF_CONF_CHANNEL */ +#define CC2430_CHANNEL_MIN 11 +#define CC2430_CHANNEL_MAX 26 + +#ifdef CC2430_RF_CONF_AUTOACK +#define CC2430_RF_AUTOACK CC2430_RF_CONF_AUTOACK +#else +#define CC2430_RF_AUTOACK 1 #endif #ifndef CC2430_CONF_CHECKSUM @@ -42,15 +59,15 @@ extern void (* receiver_callback)(const struct radio_driver *); /* moved leds code to BANK1 to make space for cc2430_rf_process in HOME */ /* can't call code in BANK1 from alternate banks unless it is marked with __banked */ #include "dev/leds.h" -#define RF_RX_LED_ON() leds_on(LEDS_RED); -#define RF_RX_LED_OFF() leds_off(LEDS_RED); -#define RF_TX_LED_ON() leds_on(LEDS_GREEN); -#define RF_TX_LED_OFF() leds_off(LEDS_GREEN); +#define RF_RX_LED_ON() leds_on(LEDS_RED); +#define RF_RX_LED_OFF() leds_off(LEDS_RED); +#define RF_TX_LED_ON() leds_on(LEDS_GREEN); +#define RF_TX_LED_OFF() leds_off(LEDS_GREEN); #else -#define RF_RX_LED_ON() -#define RF_RX_LED_OFF() -#define RF_TX_LED_ON() -#define RF_TX_LED_OFF() +#define RF_RX_LED_ON() +#define RF_RX_LED_OFF() +#define RF_TX_LED_ON() +#define RF_TX_LED_OFF() #endif #define DEBUG 0 #if DEBUG @@ -62,220 +79,48 @@ extern void (* receiver_callback)(const struct radio_driver *); #define RX_ACTIVE 0x80 #define TX_ACK 0x40 #define TX_ON_AIR 0x20 +#define WAS_OFF 0x10 #define RX_NO_DMA +/* Bits of the last byte in the RX FIFO */ +#define CRC_BIT_MASK 0x80 +#define LQI_BIT_MASK 0x7F + +/* 192 ms, radio off -> on interval */ +#define ONOFF_TIME ((RTIMER_ARCH_SECOND / 3125) + 4) + +#if CC2430_RF_CONF_HEXDUMP +#include "uart1.h" +static const uint8_t magic[] = { 0x53, 0x6E, 0x69, 0x66 }; /* Snif */ +#endif #ifdef HAVE_RF_ERROR uint8_t rf_error = 0; #endif -uint8_t rf_initialized = 0; -uint8_t rf_tx_power; -uint8_t rf_flags; -uint8_t rf_channel = 0; -rf_address_mode_t rf_addr_mode; -uint16_t rf_manfid; -uint8_t rf_softack; -uint16_t rf_panid; - /*---------------------------------------------------------------------------*/ -PROCESS_NAME(cc2430_rf_process); +#if !SHORTCUTS_CONF_NETSTACK +PROCESS(cc2430_rf_process, "CC2430 RF driver"); +#endif /*---------------------------------------------------------------------------*/ +static uint8_t rf_initialized = 0; +static uint8_t __data rf_flags; -const struct radio_driver cc2430_rf_driver = - { - cc2430_rf_send, - cc2430_rf_read, - cc2430_rf_set_receiver, - cc2430_rf_on, - cc2430_rf_off, - }; - +static int on(void); /* prepare() needs our prototype */ +static int off(void); /* transmit() needs our prototype */ +static int channel_clear(void); /* transmit() needs our prototype */ /*---------------------------------------------------------------------------*/ -void -cc2430_rf_init(void) __banked -{ - if(rf_initialized) { - return; - } - - PRINTF("cc2430_rf_init called\n"); - - RFPWR &= ~RREG_RADIO_PD; /*make sure it's powered*/ - while((RFPWR & ADI_RADIO_PD) == 1); - while((RFIF & IRQ_RREG_ON) == 0); /*wait for power up*/ - SLEEP &= ~OSC_PD; /*Osc on*/ - while((SLEEP & XOSC_STB) == 0); /*wait for power up*/ - - rf_flags = 0; - rf_softack = 0; - - FSMTC1 = 1; /*don't abort reception, if enable called, accept ack, auto rx after tx*/ - - MDMCTRL0H = 0x02; /* Generic client, standard hysteresis, decoder on 0x0a */ - MDMCTRL0L = 0xE2; /* automatic ACK and CRC, standard CCA and preamble 0xf2 */ - - MDMCTRL1H = 0x30; /* Defaults */ - MDMCTRL1L = 0x0; - - RXCTRL0H = 0x32; /* RX tuning optimized */ - RXCTRL0L = 0xf5; - - /* get ID for MAC */ - rf_manfid = CHVER; - rf_manfid <<= 8; - rf_manfid += CHIPID; - cc2430_rf_channel_set(RF_DEFAULT_CHANNEL); - cc2430_rf_command(ISFLUSHTX); - cc2430_rf_command(ISFLUSHRX); - - cc2430_rf_set_addr(0xffff, 0x0000, NULL); - cc2430_rf_address_decoder_mode(RF_DECODER_NONE); - - RFIM = IRQ_FIFOP; - RFIF &= ~(IRQ_FIFOP); - - S1CON &= ~(RFIF_0 | RFIF_1); - IEN2 |= RFIE; - - RF_TX_LED_OFF(); - RF_RX_LED_OFF(); - rf_initialized = 1; - process_start(&cc2430_rf_process, NULL); -} -/*---------------------------------------------------------------------------*/ -int -cc2430_rf_send_b(void *payload, unsigned short payload_len) __banked -{ - uint8_t i, counter; - - if(rf_flags & TX_ACK) { - return -1; - } - if((rf_flags & RX_ACTIVE) == 0) { - cc2430_rf_rx_enable(); - } - /* Check packet attributes */ - /*printf("packetbuf_attr: txpower = %d\n", packetbuf_attr(PACKETBUF_ATTR_RADIO_TXPOWER));*/ - /* Should set TX power according to this if > 0 */ - - PRINTF("cc2430_rf: sending %ud byte payload\n", payload_len); - - RIMESTATS_ADD(lltx); - - cc2430_rf_command(ISFLUSHTX); - PRINTF("cc2430_rf: sent = "); - /* Send the phy length byte first */ - RFD = payload_len+CHECKSUM_LEN; /* Payload plus FCS */ - PRINTF("(%d)", payload_len+CHECKSUM_LEN); - for(i = 0 ; i < payload_len; i++) { - RFD = ((unsigned char*)(payload))[i]; - PRINTF("%02X", ((unsigned char*)(payload))[i]); - } - PRINTF("\n"); - - /* Leave space for the FCS */ - RFD = 0; - RFD = 0; - - if(cc2430_rf_cca_check(0,0) == -1) { - return -1; - } - - /* Start the transmission */ - - RFIF &= ~IRQ_TXDONE; - cc2430_rf_command(ISTXON); - counter = 0; - while(!(RFSTATUS & TX_ACTIVE) && (counter++ < 3)) { - clock_delay(10); - } - - if(!(RFSTATUS & TX_ACTIVE)) { - PRINTF("cc2430_rf: TX never active.\n"); - cc2430_rf_command(ISFLUSHTX); - return -1; - } else { - RF_RX_LED_OFF(); - RF_TX_LED_ON(); - // rf_flags |= TX_ON_AIR; - } - return 1; -} -/*---------------------------------------------------------------------------*/ -int -cc2430_rf_read_banked(void *buf, unsigned short bufsize) __banked -{ - uint8_t i, len; -#if CC2420_CONF_CHECKSUM - uint16_t checksum; -#endif /* CC2420_CONF_CHECKSUM */ - - /* RX interrupt polled the cc2430_rf_process, now read the RX FIFO */ - - /* Check the length */ - len = RFD; - - /* Check for validity */ - if(len > CC2430_MAX_PACKET_LEN) { - /* Oops, we must be out of sync. */ - PRINTF("error: bad sync\n"); - cc2430_rf_command(ISFLUSHRX); - RIMESTATS_ADD(badsynch); - return 0; - } - - if(len <= CC2430_MIN_PACKET_LEN) { - PRINTF("error: too short\n"); - cc2430_rf_command(ISFLUSHRX); - RIMESTATS_ADD(tooshort); - return 0; - } - - if(len - CHECKSUM_LEN > bufsize) { - PRINTF("error: too long\n"); - cc2430_rf_command(ISFLUSHRX); - RIMESTATS_ADD(toolong); - return 0; - } - - /* Read the buffer */ - PRINTF("cc2430_rf: read = "); - PRINTF("(%d)", len); - for(i = 0; i < (len - CHECKSUM_LEN); i++) { - ((unsigned char*)(buf))[i] = RFD; - PRINTF("%02X", ((unsigned char*)(buf))[i]); - } - PRINTF("\n"); - -#if CC2430_CONF_CHECKSUM - /* Deal with the checksum */ - checksum = RFD * 256; - checksum += RFD; -#endif /* CC2430_CONF_CHECKSUM */ - packetbuf_set_attr(PACKETBUF_ATTR_RSSI, ((int8_t) RFD) - 45); - packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, RFD); - - RFIF &= ~IRQ_FIFOP; - RFSTATUS &= ~FIFO; - cc2430_rf_command(ISFLUSHRX); - cc2430_rf_command(ISFLUSHRX); - RF_RX_LED_OFF(); - - RIMESTATS_ADD(llrx); - - return (len - CHECKSUM_LEN); -} /** * Execute a single CSP command. * * \param command command to execute * */ -void cc2430_rf_command(uint8_t command) __banked +void +cc2430_rf_command(uint8_t command) { - if(command >= 0xE0) { /*immediate strobe*/ + if(command >= 0xE0) { /*immediate strobe*/ uint8_t fifo_count; - switch(command) { /*hardware bug workaround*/ + switch (command) { /*hardware bug workaround*/ case ISRFOFF: case ISRXON: case ISTXON: @@ -283,8 +128,8 @@ void cc2430_rf_command(uint8_t command) __banked RFST = command; clock_delay(2); if(fifo_count != RXFIFOCNT) { - RFST = ISFLUSHRX; - RFST = ISFLUSHRX; + RFST = ISFLUSHRX; + RFST = ISFLUSHRX; } break; @@ -292,17 +137,31 @@ void cc2430_rf_command(uint8_t command) __banked RFST = command; } } else if(command == SSTART) { - RFIF &= ~IRQ_CSP_STOP; /*clear IRQ flag*/ - RFST = SSTOP; /*make sure there is a stop in the end*/ - RFST = ISSTART; /*start execution*/ + RFIF &= ~IRQ_CSP_STOP; /*clear IRQ flag*/ + RFST = SSTOP; /*make sure there is a stop in the end*/ + RFST = ISSTART; /*start execution*/ while((RFIF & IRQ_CSP_STOP) == 0); } else { - RFST = command; /*write command*/ + RFST = command; /*write command*/ } } /*---------------------------------------------------------------------------*/ -/*---------------------------------------------------------------------------*/ +static void +flush_rx() +{ + cc2430_rf_command(ISFLUSHRX); + cc2430_rf_command(ISFLUSHRX); +#if !SHORTCUTS_CONF_NETSTACK + IEN2 |= RFIE; +#endif +#if CC2430_RFERR_INTERRUPT + IEN0 |= RFERRIE; +#endif + + RFIF &= ~IRQ_FIFOP; +} +/*---------------------------------------------------------------------------*/ /** * Select RF channel. * @@ -323,11 +182,11 @@ cc2430_rf_channel_set(uint8_t channel) return -1; } - cc2430_rf_command(ISSTOP); /*make sure CSP is not running*/ + cc2430_rf_command(ISSTOP); /*make sure CSP is not running*/ cc2430_rf_command(ISRFOFF); /* Channel values: 11-26 */ freq = (uint16_t) channel - 11; - freq *= 5; /*channel spacing*/ + freq *= 5; /*channel spacing*/ freq += 357; /*correct channel range*/ freq |= 0x4000; /*LOCK_THR = 1*/ FSCTRLH = (freq >> 8); @@ -335,189 +194,77 @@ cc2430_rf_channel_set(uint8_t channel) cc2430_rf_command(ISRXON); - rf_channel = channel; - return (int8_t) channel; } /*---------------------------------------------------------------------------*/ -/*PA_LEVEL TXCTRL register Output Power [dBm] Current Consumption [mA] - 31 0xA0FF 0 17.4 - 27 0xA0FB -1 16.5 - 23 0xA0F7 -3 15.2 - 19 0xA0F3 -5 13.9 - 15 0xA0EF -7 12.5 - 11 0xA0EB -10 11.2 - 7 0xA0E7 -15 9.9 - 3 0xA0E3 -25 8.5*/ - /** * Select RF transmit power. * - * \param new_power new power level (in per cent) + * \param new_power new power level * - * \return new level or negative (value out of range) + * \return new level */ - -int8_t +uint8_t cc2430_rf_power_set(uint8_t new_power) { - uint16_t power; - - if(new_power > 100) { - return -1; - } - - power = 31 * new_power; - power /= 100; - power += 0xA160; - /* Set transmitter power */ - TXCTRLH = (power >> 8); - TXCTRLL = (uint8_t)power; + TXCTRLL = new_power; - rf_tx_power = (int8_t) new_power; - return rf_tx_power; -} -/*---------------------------------------------------------------------------*/ -/** - * Enable RF receiver. - * - * - * \return pdTRUE - * \return pdFALSE bus not free - */ -int8_t -cc2430_rf_rx_enable(void) __banked -{ - PRINTF("cc2430_rf_rx_enable called\n"); - if(!(rf_flags & RX_ACTIVE)) { - IOCFG0 = 0x7f; // Set the FIFOP threshold 127 - RSSIH = 0xd2; /* -84dbm = 0xd2 default, 0xe0 -70 dbm */ - rf_flags |= RX_ACTIVE; - - RFPWR &= ~RREG_RADIO_PD; /*make sure it's powered*/ - while((RFIF & IRQ_RREG_ON) == 0); /*wait for power up*/ - SLEEP &= ~OSC_PD; /*Osc on*/ - while((SLEEP & XOSC_STB) == 0); /*wait for power up*/ - - cc2430_rf_command(ISRXON); - cc2430_rf_command(ISFLUSHRX); - } - PRINTF("cc2430_rf_rx_enable done\n"); - return 1; -} -/*---------------------------------------------------------------------------*/ -/** - * Disable RF receiver. - * - * - * \return pdTRUE - * \return pdFALSE bus not free - */ -int8_t cc2430_rf_rx_disable(void) __banked -{ - cc2430_rf_command(ISSTOP); /*make sure CSP is not running*/ - cc2430_rf_command(ISRFOFF); - - RFPWR |= RREG_RADIO_PD; /*RF powerdown*/ - - rf_flags = 0; - return 1; + return TXCTRLL; } /*---------------------------------------------------------------------------*/ +#if 0 /* unused */ /** * Enable RF transmitter. * * * \return pdTRUE - * \return pdFALSE bus not free + * \return pdFALSE bus not free */ -int8_t +int cc2430_rf_tx_enable(void) { - DMAARM = 0x80 + (1 << 0); /*ABORT + channel bit*/ + DMAARM = 0x80 + (1 << 0); /*ABORT + channel bit*/ return 1; } - +#endif +/*---------------------------------------------------------------------------*/ /** - * Set MAC addresses - * - * \param pan The PAN address to set - * \param adde The short address to set - * \param ieee_addr The 64-bit IEEE address to set - */ + * Set MAC addresses + * + * \param pan The PAN address to set + * \param adde The short address to set + * \param ieee_addr The 64-bit IEEE address to set + */ void cc2430_rf_set_addr(unsigned pan, unsigned addr, const uint8_t *ieee_addr) { - uint8_t f; - __xdata unsigned char *ptr; + uint8_t f; + __xdata unsigned char *ptr; - rf_panid = pan; - PANIDH = pan >> 8; - PANIDL = pan & 0xff; + PANIDH = pan >> 8; + PANIDL = pan & 0xff; - SHORTADDRH = addr >> 8; - SHORTADDRL = addr & 0xff; + SHORTADDRH = addr >> 8; + SHORTADDRL = addr & 0xff; - if(ieee_addr != NULL) { - ptr = &IEEE_ADDR0; - /* LSB first, MSB last for 802.15.4 addresses in CC2420 */ - for (f = 0; f < 8; f++) { - *ptr++ = ieee_addr[f]; - } - } -} - -/*---------------------------------------------------------------------------*/ -/** - * Set address decoder on/off. - * - * \param param 1=on 0=off. - * \return pdTRUE operation successful - */ -int8_t -cc2430_rf_address_decoder_mode(rf_address_mode_t mode) -{ - int8_t retval = -1; - - rf_softack = 0; - /* set oscillator on*/ - switch(mode) { - case RF_SOFTACK_MONITOR: - rf_softack = 1; - case RF_MONITOR: - MDMCTRL0H |= 0x10; /*Address-decode off , coordinator*/ - MDMCTRL0L &= ~0x10; /*no automatic ACK */ - break; - - case RF_DECODER_COORDINATOR: - MDMCTRL0H |= 0x18; /*Address-decode on , coordinator*/ - MDMCTRL0L |= 0x10; /*automatic ACK */ - break; - - case RF_DECODER_ON: - MDMCTRL0H |= 0x08; /*Address-decode on */ - MDMCTRL0L &= ~0x10; /* no automatic ACK */ - break; - - default: - MDMCTRL0H &= ~0x18; /* Generic client */ - MDMCTRL0L &= ~0x10; /* no automatic ACK */ - break; + if(ieee_addr != NULL) { + ptr = &IEEE_ADDR7; + /* LSB first, MSB last for 802.15.4 addresses in CC2420 */ + for (f = 0; f < 8; f++) { + *ptr-- = ieee_addr[f]; + } } - rf_addr_mode = mode; - - retval = 1; - return retval; } +#if 0 /* currently unused */ /*---------------------------------------------------------------------------*/ /** * Channel energy detect. * * Coordinator use this function detect best channel for PAN-network. * \return RSSI-energy level dBm. - * \return 0 operation failed. + * \return 0 operation failed. */ int8_t @@ -530,54 +277,7 @@ cc2430_rf_analyze_rssi(void) retval -= 45; return retval; } -/*---------------------------------------------------------------------------*/ -/** - * Clear channel assesment check. - * - * \return pdTRUE CCA clear - * \return pdFALSE CCA reserved - */ -int8_t -cc2430_rf_cca_check(uint8_t backoff_count, uint8_t slotted) -{ - uint8_t counter, cca = 1; - int8_t retval = 1; - backoff_count; - cc2430_rf_command(ISRXON); - - clock_delay(64); - switch(slotted) { - case 1: - - if(RFSTATUS & CCA) { - counter = 0; - cca = 1; - while(cca != 0) { - if(counter > 1) { - cca = 0; - } - clock_delay(256); - if(!(RFSTATUS & CCA)) { - cca = 0; - retval = -1; - } - counter++; - } - } else { - retval = -1; - } - break; - - case 0: - if(!(RFSTATUS & CCA)) { - retval = -1; - } else { - - } - break; - } - return retval; -} +#endif /* currently unused */ /*---------------------------------------------------------------------------*/ /** * Send ACK. @@ -585,7 +285,7 @@ cc2430_rf_cca_check(uint8_t backoff_count, uint8_t slotted) *\param pending set up pending flag if pending > 0. */ void -cc2430_rf_send_ack(uint8_t pending) __banked +cc2430_rf_send_ack(uint8_t pending) { if(pending) { cc2430_rf_command(ISACKPEND); @@ -594,3 +294,418 @@ cc2430_rf_send_ack(uint8_t pending) __banked } } /*---------------------------------------------------------------------------*/ +/* Netstack API radio driver functions */ +/*---------------------------------------------------------------------------*/ +static int +init(void) +{ + if(rf_initialized) { + return 0; + } + + PRINTF("cc2430_rf_init called\n"); + + RFPWR &= ~RREG_RADIO_PD; /*make sure it's powered*/ + while((RFPWR & ADI_RADIO_PD) == 1); + while((RFIF & IRQ_RREG_ON) == 0); /*wait for power up*/ + SLEEP &= ~OSC_PD; /*Osc on*/ + while((SLEEP & XOSC_STB) == 0); /*wait for power up*/ + + rf_flags = 0; + + FSMTC1 = 1; /*don't abort reception, if enable called, accept ack, auto rx after tx*/ + + MDMCTRL0H = 0x0A; /* Generic client, standard hysteresis, decoder on 0x0a */ + MDMCTRL0L = 0xE2; /* automatic CRC, standard CCA and preamble 0xE2 */ +#if CC2430_RF_AUTOACK + MDMCTRL0L |= 0x10; +#endif + + MDMCTRL1H = 0x30; /* Defaults */ + MDMCTRL1L = 0x0; + + RXCTRL0H = 0x32; /* RX tuning optimized */ + RXCTRL0L = 0xf5; + + cc2430_rf_channel_set(CC2430_RF_CHANNEL); + cc2430_rf_command(ISFLUSHTX); + cc2430_rf_command(ISFLUSHRX); + + /* Temporary values, main() will sort this out later on */ + cc2430_rf_set_addr(0xffff, 0x0000, NULL); + + RFIM = IRQ_FIFOP; + RFIF &= ~(IRQ_FIFOP); + + S1CON &= ~(RFIF_0 | RFIF_1); +#if !SHORTCUTS_CONF_NETSTACK + IEN2 |= RFIE; +#endif + + /* If contiki-conf.h turns on the RFERR interrupt, enable it here */ +#if CC2430_RFERR_INTERRUPT + IEN0 |= RFERRIE; +#endif + + RF_TX_LED_OFF(); + RF_RX_LED_OFF(); + rf_initialized = 1; + +#if !SHORTCUTS_CONF_NETSTACK + process_start(&cc2430_rf_process, NULL); +#endif + + cc2430_rf_power_set(CC2430_RF_TX_POWER); + + return 1; +} +/*---------------------------------------------------------------------------*/ +static int +prepare(const void *payload, unsigned short payload_len) +{ + uint8_t i; + /* + * When we transmit in very quick bursts, make sure previous transmission + * is not still in progress before re-writing in the TX FIFO + */ + while(RFSTATUS & TX_ACTIVE); + + if(rf_flags & TX_ACK) { + return -1; + } + + if((rf_flags & RX_ACTIVE) == 0) { + on(); + } + + PRINTF("cc2430_rf: sending %u byte payload\n", payload_len); + + cc2430_rf_command(ISFLUSHTX); + PRINTF("cc2430_rf: data = "); + /* Send the phy length byte first */ + RFD = payload_len + CHECKSUM_LEN; /* Payload plus FCS */ + PRINTF("(%d)", payload_len+CHECKSUM_LEN); + for(i = 0; i < payload_len; i++) { + RFD = ((unsigned char*) (payload))[i]; + PRINTF("%02X", ((unsigned char*)(payload))[i]); + } + PRINTF("\n"); + + /* Leave space for the FCS */ + RFD = 0; + RFD = 0; + + return 0; +} +/*---------------------------------------------------------------------------*/ +static int +transmit(unsigned short transmit_len) +{ + uint8_t counter; + int ret = RADIO_TX_ERR; + + if(!(rf_flags & RX_ACTIVE)) { + on(); + rf_flags |= WAS_OFF; + } + + if(channel_clear() == CC2430_CCA_BUSY) { + RIMESTATS_ADD(contentiondrop); + return RADIO_TX_COLLISION; + } + + /* + * prepare() double checked that TX_ACTIVE is low. If SFD is high we are + * receiving. Abort transmission and bail out with RADIO_TX_COLLISION + */ + if(RFSTATUS & SFD) { + RIMESTATS_ADD(contentiondrop); + return RADIO_TX_COLLISION; + } + + /* Start the transmission */ + ENERGEST_OFF(ENERGEST_TYPE_LISTEN); + ENERGEST_ON(ENERGEST_TYPE_TRANSMIT); + + cc2430_rf_command(ISTXON); + counter = 0; + while(!(RFSTATUS & TX_ACTIVE) && (counter++ < 3)) { + clock_delay(10); + } + + if(!(RFSTATUS & TX_ACTIVE)) { + PRINTF("cc2430_rf: TX never active.\n"); + cc2430_rf_command(ISFLUSHTX); + ret = RADIO_TX_ERR; + } else { + /* Wait for the transmission to finish */ + while(RFSTATUS & TX_ACTIVE); + RF_RX_LED_OFF(); + RF_TX_LED_ON(); + ret = RADIO_TX_OK; + // rf_flags |= TX_ON_AIR; + } + ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT); + ENERGEST_ON(ENERGEST_TYPE_LISTEN); + + if(rf_flags & WAS_OFF){ + off(); + } + + RIMESTATS_ADD(lltx); + /* OK, sent. We are now ready to send more */ + return ret; +} +/*---------------------------------------------------------------------------*/ +static int +send(void *payload, unsigned short payload_len) +{ + prepare(payload, payload_len); + return transmit(payload_len); +} +/*---------------------------------------------------------------------------*/ +static int +read(void *buf, unsigned short bufsize) +{ + uint8_t i; + uint8_t len; + uint8_t crc_corr; + int8_t rssi; +#if CC2420_CONF_CHECKSUM + uint16_t checksum; +#endif /* CC2420_CONF_CHECKSUM */ + + /* Don't interrupt us while emptying the FIFO */ +#if !SHORTCUTS_CONF_NETSTACK + IEN2 &= ~RFIE; +#endif +#if CC2430_RFERR_INTERRUPT + IEN0 &= ~RFERRIE; +#endif + + /* RX interrupt polled the cc2430_rf_process, now read the RX FIFO */ + /* Check the length */ + len = RFD; + + /* Check for validity */ + if(len > CC2430_MAX_PACKET_LEN) { + /* Oops, we must be out of sync. */ + PRINTF("error: bad sync\n"); + + RIMESTATS_ADD(badsynch); + flush_rx(); + return 0; + } + + if(len <= CC2430_MIN_PACKET_LEN) { + PRINTF("error: too short\n"); + + RIMESTATS_ADD(tooshort); + flush_rx(); + return 0; + } + + if(len - CHECKSUM_LEN > bufsize) { + PRINTF("error: too long\n"); + + RIMESTATS_ADD(toolong); + flush_rx(); + return 0; + } + +#if CC2430_RF_CONF_HEXDUMP + /* If we reach here, chances are the FIFO is holding a valid frame */ + uart1_writeb(magic[0]); + uart1_writeb(magic[1]); + uart1_writeb(magic[2]); + uart1_writeb(magic[3]); + uart1_writeb(len); +#endif + + PRINTF("cc2430_rf: read = "); + PRINTF("(%d)", len); + len -= CHECKSUM_LEN; + for(i = 0; i < len; ++i) { + ((unsigned char*)(buf))[i] = RFD; +#if CC2430_RF_CONF_HEXDUMP + uart1_writeb(((unsigned char*)(buf))[i]); +#endif + PRINTF("%02X", ((unsigned char*)(buf))[i]); + } + PRINTF("\n"); + +#if CC2430_CONF_CHECKSUM + /* Deal with the checksum */ + checksum = RFD * 256; + checksum += RFD; +#endif /* CC2430_CONF_CHECKSUM */ + + /* Read the RSSI and CRC/Corr bytes */ + rssi = ((int8_t) RFD) - 45; + crc_corr = RFD; + +#if CC2430_RF_CONF_HEXDUMP + uart1_writeb(rssi); + uart1_writeb(crc_corr); +#endif + + /* MS bit CRC OK/Not OK, 7 LS Bits, Correlation value */ + if(crc_corr & CRC_BIT_MASK) { + packetbuf_set_attr(PACKETBUF_ATTR_RSSI, rssi); + packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, crc_corr & LQI_BIT_MASK); + RIMESTATS_ADD(llrx); + } else { + RIMESTATS_ADD(badcrc); + flush_rx(); + return 0; +} + + /* If FIFOP==1 and FIFO==0 then we had a FIFO overflow at some point. */ + if((RFSTATUS & (FIFO | FIFOP)) == FIFOP) { + /* + * If we reach here means that there might be more intact packets in the + * FIFO despite the overflow. This can happen with bursts of small packets. + * + * Only flush if the FIFO is actually empty. If not, then next pass we will + * pick up one more packet or flush due to an error. + */ + if(!RXFIFOCNT) { + flush_rx(); + } + } + + RF_RX_LED_OFF(); + +#if !SHORTCUTS_CONF_NETSTACK + IEN2 |= RFIE; +#endif +#if CC2430_RFERR_INTERRUPT + IEN0 |= RFERRIE; +#endif + + RFIF &= ~IRQ_FIFOP; + + return (len); +} +/*---------------------------------------------------------------------------*/ +static int +channel_clear(void) +{ + if(!(RFSTATUS & CCA)) { + return CC2430_CCA_BUSY; + } + return CC2430_CCA_CLEAR; +} +/*---------------------------------------------------------------------------*/ +static int +receiving_packet(void) +{ + /* + * SFD high while transmitting and receiving. + * TX_ACTIVE high only when transmitting + * + * RFSTATUS & (TX_ACTIVE | SFD) == SFD <=> receiving + */ + return (RFSTATUS & (TX_ACTIVE | SFD) == SFD); +} +/*---------------------------------------------------------------------------*/ +static int +pending_packet(void) +{ + return (RFSTATUS & FIFOP); +} +/*---------------------------------------------------------------------------*/ +/** + * Enable RF receiver. + * + * + * \return pdTRUE + * \return pdFALSE bus not free + */ +static int +on(void) +{ + rtimer_clock_t t0; + PRINTF("cc2430_rf_rx_enable called\n"); + if(!(rf_flags & RX_ACTIVE)) { + t0 = RTIMER_NOW(); + rf_flags |= RX_ACTIVE; + IOCFG0 = 0x7f; /* Set the FIFOP threshold 127 */ + RSSIH = 0xd2; /* -84dbm = 0xd2 default, 0xe0 -70 dbm */ + + RFPWR &= ~RREG_RADIO_PD; /* make sure it's powered */ + while ((RFIF & IRQ_RREG_ON) == 0); /* wait for power up */ + + /* Make sure the RREG On Interrupt Flag is 0 next time we get called */ + RFIF &= ~IRQ_RREG_ON; + + cc2430_rf_command(ISRXON); + cc2430_rf_command(ISFLUSHRX); + while (RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + ONOFF_TIME)); + + } + PRINTF("cc2430_rf_rx_enable done\n"); + ENERGEST_ON(ENERGEST_TYPE_LISTEN); + return 1; +} +/*---------------------------------------------------------------------------*/ +/** + * Disable RF receiver. + * + * + * \return pdTRUE + * \return pdFALSE bus not free + */ + +static int +off(void) +{ + cc2430_rf_command(ISSTOP); /* make sure CSP is not running */ + cc2430_rf_command(ISRFOFF); + + RFPWR |= RREG_RADIO_PD; /* RF powerdown */ + + /* Clear the RREG On Interrupt Flag */ + RFIF &= ~IRQ_RREG_ON; + + rf_flags &= ~RX_ACTIVE; + rf_flags &= ~WAS_OFF; + ENERGEST_OFF(ENERGEST_TYPE_LISTEN); + return 1; +} +/*---------------------------------------------------------------------------*/ +const struct radio_driver cc2430_rf_driver = +{ + init, + prepare, + transmit, + send, + read, + channel_clear, + receiving_packet, + pending_packet, + on, + off, +}; +/*---------------------------------------------------------------------------*/ +#if !SHORTCUTS_CONF_NETSTACK +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(cc2430_rf_process, ev, data) +{ + int len; + PROCESS_BEGIN(); + while(1) { + PROCESS_YIELD_UNTIL(ev == PROCESS_EVENT_POLL); + + packetbuf_clear(); + len = read(packetbuf_dataptr(), PACKETBUF_SIZE); + if(len > 0) { + packetbuf_set_datalen(len); + NETSTACK_RDC.input(); + } + } + + PROCESS_END(); +} +#endif +/*---------------------------------------------------------------------------*/ diff --git a/cpu/cc2430/dev/cc2430_rf.h b/cpu/cc2430/dev/cc2430_rf.h index edaf1e0f5..f64129e09 100644 --- a/cpu/cc2430/dev/cc2430_rf.h +++ b/cpu/cc2430/dev/cc2430_rf.h @@ -8,11 +8,12 @@ #ifndef __CC2430_RF_H__ #define __CC2430_RF_H__ -#include "banked.h" #include "contiki.h" #include "dev/radio.h" #include "cc2430_sfr.h" +#if HAVE_RF_DMA #include "dev/dma.h" +#endif /* Constants */ typedef enum rf_address_mode_t @@ -26,20 +27,20 @@ typedef enum rf_address_mode_t }rf_address_mode_t; /*CSP command set*/ -#define SSTOP 0xDF +#define SSTOP 0xDF /*this is not a real command but a way of having rf_command wait until the script is done*/ #define SSTART 0xDE -#define SNOP 0xC0 +#define SNOP 0xC0 #define STXCALN 0xC1 -#define SRXON 0xC2 -#define STXON 0xC3 +#define SRXON 0xC2 +#define STXON 0xC3 #define STXONCCA 0xC4 #define SRFOFF 0xC5 #define SFLUSHRX 0xC6 #define SFLUSHTX 0xC7 -#define SACK 0xC8 +#define SACK 0xC8 #define SACKPEND 0xC9 #define ISTXCALN 0xE1 @@ -49,7 +50,7 @@ typedef enum rf_address_mode_t #define ISRFOFF 0xE5 #define ISFLUSHRX 0xE6 #define ISFLUSHTX 0xE7 -#define ISACK 0xE8 +#define ISACK 0xE8 #define ISACKPEND 0xE9 #define ISSTOP 0xFF @@ -60,39 +61,31 @@ typedef enum rf_address_mode_t #define CC2430_MAX_PACKET_LEN 127 #define CC2430_MIN_PACKET_LEN 4 +#define CC2430_CCA_CLEAR 1 +#define CC2430_CCA_BUSY 0 + +#ifdef CC2430_CONF_RFERR_INTERRUPT +#define CC2430_RFERR_INTERRUPT CC2430_CONF_RFERR_INTERRUPT +#else +#define CC2430_RFERR_INTERRUPT 0 +#endif + extern const struct radio_driver cc2430_rf_driver; -/* radio_driver functions */ -void cc2430_rf_set_receiver(void (* recv)(const struct radio_driver *)); -int cc2430_rf_on(void); -int cc2430_rf_off(void); -int cc2430_rf_read(void *buf, unsigned short bufsize); -int cc2430_rf_read_banked (void *buf, unsigned short bufsize) __banked; -int cc2430_rf_send(void *data, unsigned short len); -int cc2430_rf_send_b (void *data, unsigned short len) __banked; -extern unsigned short cc2430_rf_payload_len; -extern void *cc2430_rf_payload; - -/* RF driver functions */ -void cc2430_rf_init(void) __banked; -void cc2430_rf_command(uint8_t command) __banked; +void cc2430_rf_command(uint8_t command); int8_t cc2430_rf_channel_set(uint8_t channel); -int8_t cc2430_rf_power_set(uint8_t new_power); -int8_t cc2430_rf_rx_enable(void) __banked; -int8_t cc2430_rf_rx_disable(void) __banked; -int8_t cc2430_rf_tx_enable(void); -int8_t cc2430_rf_address_decoder_mode(rf_address_mode_t mode); -int8_t cc2430_rf_analyze_rssi(void); -int8_t cc2430_rf_cca_check(uint8_t backoff_count, uint8_t slotted); -void cc2430_rf_send_ack(uint8_t pending); +uint8_t cc2430_rf_power_set(uint8_t new_power); void cc2430_rf_set_addr(unsigned pan, unsigned addr, const uint8_t *ieee_addr); +#if !SHORTCUTS_CONF_NETSTACK extern void cc2430_rf_ISR( void ) __interrupt (RF_VECTOR); +#endif +#if CC2430_RFERR_INTERRUPT extern void cc2430_rf_error_ISR( void ) __interrupt (RFERR_VECTOR); +#endif #ifdef HAVE_RF_DMA void rf_dma_callback_isr(void); #endif - #endif /* __CC2430_RF_H__ */ diff --git a/cpu/cc2430/dev/cc2430_rf_intr.c b/cpu/cc2430/dev/cc2430_rf_intr.c index 2c4a26fb0..296024115 100644 --- a/cpu/cc2430/dev/cc2430_rf_intr.c +++ b/cpu/cc2430/dev/cc2430_rf_intr.c @@ -2,11 +2,12 @@ * \file * CC2430 RF driver * \author - * Zach Shelby + * Zach Shelby (Original) + * George Oikonomou - + * (recent updates for the contiki cc2430 port) * * Non-bankable code for cc2430 rf driver. - * Interrupt routine and code called through function pointers - * must be placed into the HOME bank. + * Interrupt routines must be placed into the HOME bank. * */ @@ -23,6 +24,7 @@ #include "net/packetbuf.h" #include "net/rime/rimestats.h" +#include "net/netstack.h" #define DEBUG 0 #if DEBUG #define PRINTF(...) printf(__VA_ARGS__) @@ -46,10 +48,9 @@ uint8_t rf_error = 0; #endif +PROCESS_NAME(cc2430_rf_process); -/*---------------------------------------------------------------------------*/ -PROCESS(cc2430_rf_process, "CC2430 RF driver"); - +#if !SHORTCUTS_CONF_NETSTACK /*---------------------------------------------------------------------------*/ /** * RF interrupt service routine. @@ -59,29 +60,27 @@ void cc2430_rf_ISR( void ) __interrupt (RF_VECTOR) { EA = 0; - if(RFIF & IRQ_TXDONE) { - RF_TX_LED_OFF(); - RFIF &= ~IRQ_TXDONE; - cc2430_rf_command(ISFLUSHTX); - } + ENERGEST_ON(ENERGEST_TYPE_IRQ); + /* + * We only vector here if RFSTATUS.FIFOP goes high. + * Just double check the flag. + */ if(RFIF & IRQ_FIFOP) { - if(RFSTATUS & FIFO) { RF_RX_LED_ON(); /* Poll the RF process which calls cc2430_rf_read() */ process_poll(&cc2430_rf_process); - } else { - cc2430_rf_command(ISFLUSHRX); - cc2430_rf_command(ISFLUSHRX); - RFIF &= ~IRQ_FIFOP; - } } S1CON &= ~(RFIF_0 | RFIF_1); + + ENERGEST_OFF(ENERGEST_TYPE_IRQ); EA = 1; } +#endif /*---------------------------------------------------------------------------*/ +#if CC2430_RFERR_INTERRUPT /** * RF error interrupt service routine. - * + * Turned off by default, can be turned on in contiki-conf.h */ void cc2430_rf_error_ISR( void ) __interrupt (RFERR_VECTOR) @@ -99,57 +98,5 @@ cc2430_rf_error_ISR( void ) __interrupt (RFERR_VECTOR) RF_TX_LED_OFF(); EA = 1; } - -void (* receiver_callback)(const struct radio_driver *); - -void -cc2430_rf_set_receiver(void (* recv)(const struct radio_driver *)) -{ - receiver_callback = recv; -} +#endif /*---------------------------------------------------------------------------*/ -/* - * non-banked functions called through function pointers then call banked code - */ -int -cc2430_rf_off(void) -{ - return cc2430_rf_rx_disable(); -} -/*---------------------------------------------------------------------------*/ -int -cc2430_rf_on(void) -{ - return cc2430_rf_rx_enable(); -} -/*---------------------------------------------------------------------------*/ -int -cc2430_rf_send(void *payload, unsigned short payload_len) -{ - return cc2430_rf_send_b(payload, payload_len); -} -/*---------------------------------------------------------------------------*/ -int -cc2430_rf_read(void *buf, unsigned short bufsize) -{ - return cc2430_rf_read_banked(buf, bufsize); -} -/*---------------------------------------------------------------------------*/ -/*---------------------------------------------------------------------------*/ -PROCESS_THREAD(cc2430_rf_process, ev, data) -{ - PROCESS_BEGIN(); - while(1) { - PROCESS_YIELD_UNTIL(ev == PROCESS_EVENT_POLL); - - if(receiver_callback != NULL) { - PRINTF("cc2430_rf_process: calling receiver callback\n"); - receiver_callback(&cc2430_rf_driver); - } else { - PRINTF("cc2430_rf_process: no receiver callback\n"); - cc2430_rf_command(ISFLUSHRX); - } - } - - PROCESS_END(); -} diff --git a/cpu/cc2430/dev/clock.c b/cpu/cc2430/dev/clock.c index 00513596c..a748f2853 100644 --- a/cpu/cc2430/dev/clock.c +++ b/cpu/cc2430/dev/clock.c @@ -46,20 +46,24 @@ #include "sys/clock.h" #include "sys/etimer.h" #include "cc2430_sfr.h" - +#include "sys/energest.h" /*Sleep timer runs on the 32k RC osc. */ /* One clock tick is 7.8 ms */ -#define TICK_VAL (32768/128) - -#define MAX_TICKS (~((clock_time_t)0) / 2) +#define TICK_VAL (32768/128) /* 256 */ /* Used in sleep timer interrupt for calculating the next interrupt time */ static unsigned long timer_value; /*starts calculating the ticks right after reset*/ -static volatile clock_time_t count = 0; +#if CLOCK_CONF_ACCURATE +static volatile __data clock_time_t count = 0; +#else +volatile __data clock_time_t count = 0; +/* accurate clock is stack hungry */ +volatile __bit sleep_flag; +#endif /*calculates seconds*/ -static volatile clock_time_t seconds = 0; +static volatile __data clock_time_t seconds = 0; /*---------------------------------------------------------------------------*/ /** @@ -103,7 +107,7 @@ clock_seconds(void) void clock_init(void) { - CLKCON = OSC32K | TICKSPD2|TICKSPD1|TICKSPD0; /*tickspeed 250 kHz*/ + CLKCON = OSC32K | TICKSPD2|TICKSPD1; /*tickspeed 500 kHz for timers[1-4]*/ /*Initialize tick value*/ timer_value = ST0; /*sleep timer 0. low bits [7:0]*/ @@ -118,9 +122,18 @@ clock_init(void) } /*---------------------------------------------------------------------------*/ void -cc2430_clock_ISR( void ) __interrupt (ST_VECTOR) +clock_ISR( void ) __interrupt (ST_VECTOR) { IEN0_EA = 0; /*interrupt disable*/ + ENERGEST_ON(ENERGEST_TYPE_IRQ); + + /* + * If the Sleep timer throws an interrupt while we are powering down to + * PM1, we need to abort the power down. Clear SLEEP.MODE, this will signal + * main() to abort the PM1 transition + */ + SLEEP &= 0xFC; + /* When using the cooperative scheduler the timer 2 ISR is only required to increment the RTOS tick count. */ @@ -148,12 +161,17 @@ cc2430_clock_ISR( void ) __interrupt (ST_VECTOR) ++seconds; } +#if CLOCK_CONF_ACCURATE if(etimer_pending() && (etimer_next_expiration_time() - count - 1) > MAX_TICKS) { /*core/sys/etimer.c*/ etimer_request_poll(); } +#else + sleep_flag = 1; +#endif IRCON &= ~STIF; /*IRCON.STIF=Sleep timer interrupt flag. This flag called this interrupt func, now reset it*/ + ENERGEST_OFF(ENERGEST_TYPE_IRQ); IEN0_EA = 1; /*interrupt enable*/ } /*---------------------------------------------------------------------------*/ diff --git a/cpu/cc2430/dev/dma.c b/cpu/cc2430/dev/dma.c index f5b6ca3d7..d549850c5 100644 --- a/cpu/cc2430/dev/dma.c +++ b/cpu/cc2430/dev/dma.c @@ -1,216 +1,69 @@ /** * \file - * DMA driver + * Driver for the cc2430 DMA controller. Can be assigned to any bank + * * \author * Original: Martti Huttunen * Port: Zach Shelby + * Further Modifications: + * George Oikonomou * - * bankable DMA functions */ -#include - #include "contiki.h" -#include "banked.h" - #include "dev/dma.h" #include "cc2430_sfr.h" -dma_config_t dma_conf[4]; -struct process * dma_callback[4]; - +#if DMA_ON +struct dma_config dma_conf[DMA_CHANNEL_COUNT]; /* DMA Descriptors */ +struct process * dma_callback[DMA_CHANNEL_COUNT]; /*---------------------------------------------------------------------------*/ void -dma_init(void) __banked +dma_init(void) { uint16_t tmp_ptr; - memset(dma_conf, 0, 4*sizeof(dma_config_t)); - for(tmp_ptr = 0; tmp_ptr < 4; tmp_ptr++) { + + memset(dma_conf, 0, 4 * sizeof(dma_config_t)); + + for(tmp_ptr = 0; tmp_ptr < DMA_CHANNEL_COUNT; tmp_ptr++) { dma_callback[tmp_ptr] = 0; } - tmp_ptr = (uint16_t) &(dma_conf[0]); + /* The address of the descriptor for Channel 0 is configured separately */ + tmp_ptr = (uint16_t) &(dma_conf[0]); + DMA0CFGH = tmp_ptr >> 8; + DMA0CFGL = tmp_ptr; + + /* + * Descriptors for Channels 1-4 must be consecutive in RAM. + * We write the address of the 1st one to the register and the rest are + * derived by the SoC + */ +#if (DMA_CHANNEL_COUNT > 1) + tmp_ptr = (uint16_t) &(dma_conf[1]); DMA1CFGH = tmp_ptr >> 8; DMA1CFGL = tmp_ptr; - IEN1_DMAIE = 1; /*enable DMA interrupts*/ -} -/*---------------------------------------------------------------------------*/ -#ifdef HAVE_DMA -/** - * Configure a DMA channel except word mode. - * - * \param channel channel ID; - * \param src source address; - * \param src_inc source increment mode; - * \param dst dest address; - * \param dst_inc dest increment mode; - * \param length maximum length; - * \param vlen_mode variable length mode; - * \param t_mode DMA transfer mode; - * \param trigger DMA trigger; - * \param proc process that is upon interrupt; - * - * \return Handle to DMA channel - * \return 0 invalid channel - */ -/* IMPLEMENTED dma_config as macro to reduce stack/code space -xDMAHandle -dma_config(uint8_t channel, void *src, dma_inc_t src_inc, void *dst, dma_inc_t dst_inc, - uint16_t length, dma_vlen_t vlen_mode, dma_type_t t_mode, dma_trigger_t trigger, - struct process * proc) __banked -{ - return dma_config2(channel,src,src_inc, dst, dst_inc, length, 0, vlen_mode, t_mode, trigger, proc); -} -*/ -/*---------------------------------------------------------------------------*/ -/** - * Configure a DMA channel. - * - * \param channel channel ID; - * \param src source address; - * \param src_inc source increment mode; - * \param dst dest address; - * \param dst_inc dest increment mode; - * \param length maximum length; - * \param word_mode set to 1 for 16-bits per transfer; - * \param vlen_mode variable length mode; - * \param t_mode DMA transfer mode; - * \param trigger DMA trigger; - * \param proc process that is upon interrupt; - * - * \return Handle to DMA channel - * \return 0 invalid channel - */ -xDMAHandle -dma_config2(uint8_t channel, void *src, dma_inc_t src_inc, void *dst, dma_inc_t dst_inc, - uint16_t length, uint8_t word_mode, dma_vlen_t vlen_mode, dma_type_t t_mode, dma_trigger_t trigger, - struct process * proc) __banked -{ - unsigned char jj; - if((!channel) || (channel > 4)) { - return 0; - } +#endif - DMAIRQ &= ~(1 << channel); - - channel--; - - dma_conf[channel].src_h = ((uint16_t) src) >> 8; - dma_conf[channel].src_l = ((uint16_t) src); - dma_conf[channel].dst_h = ((uint16_t) dst) >> 8; - dma_conf[channel].dst_l = ((uint16_t) dst); - dma_conf[channel].len_h = vlen_mode + (length >> 8); - dma_conf[channel].len_l = length; - dma_conf[channel].t_mode = ((word_mode&0x1)<<7) | (t_mode << 5) | trigger; - dma_conf[channel].addr_mode = (src_inc << 6) + (dst_inc << 4) + 2; /*DMA has priority*/ - - /*Callback is defined*/ - if(proc) { - dma_conf[channel].addr_mode |= 8; /*set IRQMASK*/ - IEN1_DMAIE = 1; /*enable DMA interrupts*/ - } - dma_callback[channel] = proc; - - return (xDMAHandle)channel + 1; + IEN1_DMAIE = 1; /* Enable DMA interrupts */ } /*---------------------------------------------------------------------------*/ -/** - * Arm a DMA channel. - * - * \param channel channel handle; - * - * \return pdTRUE - * \return pdFALSE semaphore creation failed +/* + * Associate process p with DMA channel c. When a transfer on that channel + * completes, the ISR will poll this process. */ -uint8_t -dma_arm(xDMAHandle channel) __banked -{ - uint8_t ch_id = ((uint8_t)channel); - if(!ch_id || (ch_id > 4)) { - return 0; - } - DMAARM |= (1 << ch_id); - return 1; -} -/*---------------------------------------------------------------------------*/ -/** - * Stop a DMA channel. - * - * \param channel channel handle; - * - * \return pdTRUE - * \return pdFALSE semaphore creation failed - */ -uint8_t -dma_abort(xDMAHandle channel) __banked -{ - uint8_t ch_id = ((uint8_t) channel); - if(!ch_id || (ch_id > 4)) { - return 0; - } - DMAARM = 0x80 + (1 << ch_id); /*ABORT + channel bit*/ - return 1; -} -/*---------------------------------------------------------------------------*/ -/** - * Trigger a DMA channel. - * - * \param channel channel handle; - * - * \return pdTRUE - * \return pdFALSE semaphore creation failed - */ -uint8_t -dma_trigger(xDMAHandle channel) __banked -{ - uint8_t ch_id = ((uint8_t) channel); - if(!ch_id || (ch_id > 4)) { - return 0; - } - DMAREQ |= (1 << ch_id); - return 1; -} -/*---------------------------------------------------------------------------*/ -/** - * Get DMA state. - * - * \param channel channel handle; - * - * \return pdTRUE active - * \return pdFALSE not active - */ -uint8_t -dma_state(xDMAHandle channel) __banked -{ - uint8_t ch_id = ((uint8_t)channel); - if(!ch_id || (ch_id > 4)) { - return 0; - } - if((DMAIRQ &(1 << ch_id)) == 0) { - return 1; - } - return 0; -} -/*---------------------------------------------------------------------------*/ void -dma_config_print(xDMAHandle channel) __banked +dma_associate_process(struct process * p, uint8_t c) { - uint8_t ch_id = channel - 1; - - if(ch_id > 4) { + if((!c) || (c >= DMA_CHANNEL_COUNT)) { return; } - - printf("DMA channel %d @ %x %x ", ch_id, (uint16_t) &(dma_conf[ch_id]) >> 8, (uint16_t) &(dma_conf[ch_id]) & 0xFF); - { - uint8_t i; - uint8_t *ptr = (uint8_t *)&(dma_conf[ch_id]); - for(i = 0; i< 8; i++) { - if(i != 0) { - printf(":%02x", *ptr++); - } - } - printf("\n"); + + if(p) { + dma_conf[c].inc_prio |= 8; /* Enable interrupt generation */ + IEN1_DMAIE = 1; /* Make sure DMA interrupts are acknowledged */ } + dma_callback[c] = p; } +/*---------------------------------------------------------------------------*/ #endif diff --git a/cpu/cc2430/dev/dma.h b/cpu/cc2430/dev/dma.h index f8ac02802..d88167734 100644 --- a/cpu/cc2430/dev/dma.h +++ b/cpu/cc2430/dev/dma.h @@ -1,122 +1,148 @@ /** * \file - * DMA driver header + * Header file for the cc2430 DMA controller + * * \author * Original: Martti Huttunen * Port: Zach Shelby + * Further Modifications: + * George Oikonomou */ #ifndef __DMA_H #define __DMA_H -#include "banked.h" #include "cc2430_sfr.h" -/** DMA triggers */ -typedef enum dma_trigger_t -{ - DMA_T_NONE=0, /*! -extern uint8_t p0ien; -extern uint8_t p2ien; #define HWCONF_PIN(name, port, bit) \ static CC_INLINE void name##_SELECT() {P##port##SEL &= ~(1 << bit);} \ @@ -51,10 +49,10 @@ static CC_INLINE void name##_MAKE_INPUT() {P##port##DIR &= ~(1 << bit); } #define HWCONF_IRQ_XXX(name, port, bit) \ static CC_INLINE void name##_ENABLE_IRQ() { \ - if ( port == 2 ) { PICTL |= P2IEN; p2ien |= 1<=4)) { PICTL |= P0IENH; p0ien |= 1<=4)) { PICTL |= P0IENH; p0ien |= 1<=4 ) { PICTL |= P0IENH; p0ien |= 1<=4) { \ + p0ien &= ~(1< */ #ifndef __LPM_H__ #define __LPM_H__ -#include #include "contiki-conf.h" -#ifdef LPM_CONF_ON -#define LPM_ON LPM_CONF_ON +#define LPM_MODE_NONE 0 /* No LPM - Always on */ +#define LPM_MODE_IDLE 1 /* Set MCU Idle as part of the main loop */ +#define LPM_MODE_PM2 2 /* Drop to PM1 - causes radio packet losses for now */ + +#ifdef LPM_CONF_MODE +#define LPM_MODE LPM_CONF_MODE #else -#define LPM_ON LPM1 -#endif /* LPM_CONF_ON */ - -#ifdef LPM_CONF_OFF -#define LPM_OFF LPM_CONF_OFF -#else -#define LPM_OFF LPM1_EXIT -#endif /* LPM_CONF_OFF */ - -#define LPM_SLEEP() do { if(lpm_status == LPM_STATUS_ON) LPM_ON; } while(0) -#define LPM_AWAKE() do { if(lpm_status == LPM_STATUS_ON) LPM_OFF; } while(0) - -extern unsigned char lpm_status; - -void lpm_on(void); -void lpm_off(void); - -#define LPM_STATUS_OFF 0 -#define LPM_STATUS_ON 1 - +#define LPM_MODE LPM_MODE_IDLE +#endif /* LPM_CONF_MODE */ #endif /* __LPM_H__ */ diff --git a/cpu/cc2430/dev/random.c b/cpu/cc2430/dev/random.c new file mode 100644 index 000000000..639f384e5 --- /dev/null +++ b/cpu/cc2430/dev/random.c @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2010, Loughborough University - Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * Random number generator routines exploiting the cc2430 hardware + * capabilities. + * + * This file overrides core/lib/random.c. + * + * \author + * George Oikonomou - + */ +#include "cc2430_sfr.h" +#include "dev/cc2430_rf.h" +/*---------------------------------------------------------------------------*/ +/** + * \brief Generates a new random number using the cc2430 RNG. + * \return The random number. + */ +unsigned short +random_rand(void) +{ + /* Clock the RNG LSFR once */ + ADCCON1 |= ADRCTRL0; + + return (RNDL | (RNDH << 8)); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Seed the cc2430 random number generator. + * \param seed Seed value for the RNG. + * + * If the SEED argument is 0, seed the RNG with IF_ADC as + * discussed in the cc2430 datasheet (rev. 2.1), section 13.11.2.2, + * page 134. Seeding with this method should not be done during + * normal radio operation. Thus, use this function before + * initialising the network. + * + * If the SEED is provided, seed with this value instead. This will + * result in the same sequence of random numbers each time the node + * reboots. So, don't use it unless you have a reason (e.g. tests) + */ +void +random_init(unsigned short seed) +{ + int i; + + /* Comment out this if() block to save a nice 16 bytes of code size */ + if(seed) { + /* If the caller provides a seed, write the high-byte first and then + * write the low byte */ + RNDL = seed >> 8; /* High byte first */ + RNDL = seed & 0xFF; + return; + } + + /* + * cc2430 Datasheet: + * "When a true random value is required, the LFSR should be seeded by + * writing RNDL with random values from the IF_ADC in the RF receive path." + * + * "To use this seeding method, the radio must first be powered on by + * enabling the voltage regulator" + */ + RFPWR &= ~RREG_RADIO_PD; /* Turn on the voltage regulator */ + while(!(RFIF & IRQ_RREG_ON)); /* Wait for power up*/ + + /* OK, it's powered. The respective interrupt flag has been set, clear it */ + RFIF &= ~IRQ_RREG_ON; + + /* + * "The radio should be placed in infinite TX state, to avoid possible sync + * detect in RX state." + * + * Judging by old chipcon cc2430 code examples as well as by the way cc2530 + * works, this is very likely to be "RX state" (i.e. a typo in the datasheet) + * + * With infinite TX, ADCTSTx always read as 0 so we'll use infinite RX + */ + MDMCTRL1L = 0x02; /* RX mode 10 - RX_INFINITE state */ + + /* "Enter RX State - Immediate" command strobe */ + cc2430_rf_command(ISRXON); + + /* Make sure the RNG is on */ + ADCCON1 &= ~(ADRCTRL1 | ADRCTRL0); + + /* Wait for IF_ADC I-branch and Q-branch values */ + while(!(ADCTSTH & ADCTSTL)); + + /* 32 times as per the chipcon example. This seems to increase randomness */ + for(i = 0; i < 32; i++) { + /* Seed the RNG by writing into RNDL twice with values from ADCTSTx */ + RNDL = ADCTSTH; + RNDL = ADCTSTL; + + /* Clock the RNG LSFR once */ + ADCCON1 |= ADRCTRL0; + } + + /* + * Exit RX state. Just shut down, network initialisation will take care of + * properly starting the radio for us. + */ + RFPWR |= RREG_RADIO_PD; +} diff --git a/cpu/cc2430/dev/rs232.h b/cpu/cc2430/dev/rs232.h deleted file mode 100644 index 865e8a415..000000000 --- a/cpu/cc2430/dev/rs232.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (c) 2007, Takahide Matsutsuka. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * 3. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $Id: rs232.h,v 1.1 2009/09/08 20:07:35 zdshelby Exp $ - * - */ -/* - * \file - * This is RS-232C process based on polling. - * \author - * Takahide Matsutsuka - */ - -#ifndef __RS232_H__ -#define __RS232_H__ - -/* - * Implement the following methods for each platform. - */ - -/* - * An architecture-depend implementation of RS-232C initialization. - */ -void rs232_arch_init(unsigned long ubr); - -/* - * An architecture-depend implementation of RS-232C polling. - * @return character, stat == zero if no input. - */ -unsigned char rs232_arch_poll(unsigned char* stat); - -/* - * An architecture-depend implementation of RS-232C writing a byte. - */ -void rs232_arch_writeb(unsigned char ch); - -PROCESS_NAME(rs232_process); - -/* - * if you want to use simple serial communication, - * define RS232_CONF_CALLBACK as serial_input_byte. - * The default is SLIP. - */ -#ifdef RS232_CONF_CALLBACK -#define RS232_CALLBACK RS232_CONF_CALLBACK -#else /* RS232_CONF_CALLBACK */ -#define RS232_CALLBACK slip_input_byte -#endif /* RS232_CONF_CALLBACK */ - -#ifdef RS232_CONF_BUFISZE -#define RS232_BUFSIZE RS232_CONF_BUFISZE -#else /* RS232_CONF_BUFISZE */ -#define RS232_BUFSIZE 64 -#endif /* RS232_CONF_BUFISZE */ - -#ifdef RS232_CONF_BAUD_RATE -#define RS232_BAUD_RATE RS232_CONF_BAUD_RATE -#else /* RS232_CONF_BAUD_RATE */ -#define RS232_BAUD_RATE 9600 -#endif /* RS232_CONF_BAUD_RATE */ - -#endif /* __RS232_H__ */ diff --git a/cpu/cc2430/dev/uart.c b/cpu/cc2430/dev/uart.c deleted file mode 100644 index 86fc8fc48..000000000 --- a/cpu/cc2430/dev/uart.c +++ /dev/null @@ -1,41 +0,0 @@ -/** - * \file - * - * uart write routines - * - * \author - * - * Anthony "Asterisk" Ambuehl - * - * non-interrupt routines which may be called from ISR's and therefore should be in HOME bank. - * - */ -#include -#include - -#include "cc2430_sfr.h" - -#include "dev/leds.h" -#include "dev/uart.h" - -/*---------------------------------------------------------------------------*/ -/* Write one byte over the UART. */ -void -uart0_writeb(uint8_t byte) -{ - IRCON2_UTX0IF = 0; - U0BUF = byte; - while(!IRCON2_UTX0IF); /* Wait until byte has been transmitted. */ - IRCON2_UTX0IF = 0; -} -/*---------------------------------------------------------------------------*/ -/* Write one byte over the UART. */ -void -uart1_writeb(uint8_t byte) -{ - IRCON2_UTX1IF = 0; - U1BUF = byte; - while(!IRCON2_UTX1IF); /* Wait until byte has been transmitted. */ - IRCON2_UTX1IF = 0; -} -/*---------------------------------------------------------------------------*/ diff --git a/cpu/cc2430/dev/uart.h b/cpu/cc2430/dev/uart.h index 8b39cff3a..e230c3bcd 100644 --- a/cpu/cc2430/dev/uart.h +++ b/cpu/cc2430/dev/uart.h @@ -2,24 +2,42 @@ #define UART_H #include "contiki-conf.h" -#include "banked.h" #include "cc2430_sfr.h" +#include "8051def.h" -void uart0_init(uint32_t speed) __banked; -void uart0_writeb(uint8_t byte); +/*---------------------------------------------------------------------------*/ +/* UART BAUD Rates */ +/* + * Macro to set speed of UART N by setting the UnBAUD SFR to M and the + * UnGCR SRF to E. See the cc2430 datasheet for possible values of M and E + */ +#define UART_SET_SPEED(N, M, E) do{ U##N##BAUD = M; U##N##GCR = E; } while(0) -void uart0_set_input(int (*input)(unsigned char c)); +/* + * Sample Values for M and E in the macro above to achieve some common BAUD + * rates. For more values, see the cc2430 datasheet + */ +/* 2000000 - cc2430 theoretical MAX when using the 32MHz clock */ +#define UART_2K_M 0 +#define UART_2K_E 16 +/* 1000000 - cc2430 theoretical MAX when using the 16MHz clock */ +#define UART_1K_M 0 +#define UART_1K_E 15 +/* 921600 */ +#define UART_921_M 216 +#define UART_921_E 14 +/* 460800 Higher values lead to problems when the node needs to RX */ +#define UART_460_M 216 +#define UART_460_E 13 +/* 115200 */ +#define UART_115_M 216 +#define UART_115_E 11 +/* 38400 */ +#define UART_38_M 59 +#define UART_38_E 10 +/* 9600 */ +#define UART_9_M 59 +#define UART_9_E 8 -void uart0_rxISR( void ) __interrupt (URX0_VECTOR); -void uart0_txISR( void ) __interrupt (UTX0_VECTOR); - -void uart1_init(uint32_t speed) __banked; -void uart1_writeb(uint8_t byte); - -void uart1_set_input(int (*input)(unsigned char c)); - -void uart1_rxISR( void ) __interrupt (URX1_VECTOR); -void uart1_txISR( void ) __interrupt (UTX1_VECTOR); - -#endif /*UART_H*/ +#endif /* UART_H */ diff --git a/cpu/cc2430/dev/uart0.c b/cpu/cc2430/dev/uart0.c new file mode 100644 index 000000000..254dba765 --- /dev/null +++ b/cpu/cc2430/dev/uart0.c @@ -0,0 +1,69 @@ +/** + * \file + * + * uart0 write routines + * + * \author + * + * Anthony "Asterisk" Ambuehl + * + */ +#include +#include + +#include "cc2430_sfr.h" +#include "dev/uart0.h" + +#if UART_ZERO_ENABLE +/*---------------------------------------------------------------------------*/ +void +uart0_init() +{ + UART_SET_SPEED(0, UART_115_M, UART_115_E); + +#ifdef UART0_ALTERNATIVE_2 + PERCFG |= U0CFG; /*alternative port 2 = P1.5-2*/ +#ifdef UART0_RTSCTS + P1SEL |= 0x3C; /*peripheral select for TX and RX, RTS, CTS*/ +#else + P1SEL |= 0x30; /*peripheral select for TX and RX*/ + P1 &= ~0x08; /*RTS down*/ +#endif + P1DIR |= 0x28; /*RTS, TX out*/ + P1DIR &= ~0x14; /*CTS & RX in*/ +#else + PERCFG &= ~U0CFG; /*alternative port 1 = P0.5-2*/ +#ifdef UART0_RTSCTS + P0SEL |= 0x3C; /*peripheral select for TX and RX, RTS, CTS*/ +#else + P0SEL |= 0x0C; /*peripheral select for TX and RX*/ + P0 &= ~0x20; /*RTS down*/ +#endif + P0DIR |= 0x28; /*RTS & TX out*/ + P0DIR &= ~0x14; /*CTS & RX in*/ +#endif + + +#ifdef UART0_RTSCTS + U0UCR = 0x42; /*defaults: 8N1, RTS/CTS, high stop bit*/ +#else + U0UCR = 0x02; /*defaults: 8N1, no flow control, high stop bit*/ +#endif + + U0CSR = U_MODE | U_RE | U_TXB; /*UART mode, receiver enable, TX done*/ + + /*set priority group of group 3 to highest, so the UART won't miss bytes*/ + IP1 |= IP1_3; + IP0 |= IP0_3; +} +/*---------------------------------------------------------------------------*/ +/* Write one byte over the UART. */ +void +uart0_writeb(uint8_t byte) +{ + IRCON2_UTX0IF = 0; + U0BUF = byte; + while(!IRCON2_UTX0IF); /* Wait until byte has been transmitted. */ + IRCON2_UTX0IF = 0; +} +#endif diff --git a/cpu/cc2430/dev/uart0.h b/cpu/cc2430/dev/uart0.h new file mode 100644 index 000000000..7ac56e9f6 --- /dev/null +++ b/cpu/cc2430/dev/uart0.h @@ -0,0 +1,31 @@ +#ifndef UART_0_H +#define UART_0_H + +#include "contiki-conf.h" + +#include "cc2430_sfr.h" +#include "8051def.h" +#include "uart.h" + +/*---------------------------------------------------------------------------*/ +/* UART0 Enable - Disable */ +#ifdef UART_ZERO_CONF_ENABLE +#define UART_ZERO_ENABLE UART_ZERO_CONF_ENABLE +#else +#define UART_ZERO_ENABLE 0 +#endif +/*---------------------------------------------------------------------------*/ +/* UART0 Function Declarations */ +#if UART_ZERO_ENABLE +void uart0_init(); +void uart0_writeb(uint8_t byte); + +void uart0_set_input(int (*input)(unsigned char c)); + +void uart0_rx_ISR( void ) __interrupt (URX0_VECTOR); +void uart0_tx_ISR( void ) __interrupt (UTX0_VECTOR); +/* Macro to turn on / off UART RX Interrupt */ +#define UART0_RX_INT(v) IEN0_URX0IE = v +#endif + +#endif /* UART_0_H */ diff --git a/cpu/cc2430/dev/uart1.c b/cpu/cc2430/dev/uart1.c new file mode 100644 index 000000000..7f388c5b6 --- /dev/null +++ b/cpu/cc2430/dev/uart1.c @@ -0,0 +1,74 @@ +/** + * \file + * + * uart1 write routines + * + * \author + * + * Anthony "Asterisk" Ambuehl + * + */ +#include +#include + +#include "cc2430_sfr.h" +#include "dev/uart1.h" + +#if UART_ONE_ENABLE +/*---------------------------------------------------------------------------*/ +/* UART1 initialization */ +void +uart1_init() +{ +#ifdef UART1_ALTERNATIVE_1 + PERCFG &= ~U1CFG; /*alternative port 1 = P0.5-2*/ +#ifdef UART1_RTSCTS + P0SEL |= 0x3C; /*peripheral select for TX and RX, RTS, CTS*/ +#else + P0SEL |= 0x30; /*peripheral select for TX and RX*/ + P0 &= ~0x08; /*RTS down*/ +#endif + P0DIR |= 0x18; /*RTS, TX out*/ + P0DIR &= ~0x24; /*CTS, RX in*/ +#else + PERCFG |= U1CFG; /*alternative port 2 = P1.7-4*/ +#ifdef UART1_RTSCTS + P1SEL |= 0xF0; /*peripheral select for TX and RX*/ +#else + P1SEL |= 0xC0; /*peripheral select for TX and RX*/ + P1 &= ~0x20; /*RTS down*/ +#endif + P1DIR |= 0x60; /*RTS, TX out*/ + P1DIR &= ~0x90; /*CTS, RX in*/ +#endif + +#if UART_ONE_CONF_HIGH_SPEED + UART_SET_SPEED(1, UART_460_M, UART_460_E); +#else + UART_SET_SPEED(1, UART_115_M, UART_115_E); +#endif + +#ifdef UART1_RTSCTS + U1UCR = 0x42; /*defaults: 8N1, RTS/CTS, high stop bit*/ +#else + U1UCR = 0x02; /*defaults: 8N1, no flow control, high stop bit*/ +#endif + + U1CSR = U_MODE | U_RE; /* UART mode, receiver enable */ + + /*set priority group of group 3 to highest, so the UART won't miss bytes*/ + IP1 |= IP1_3; + IP0 |= IP0_3; +} +/*---------------------------------------------------------------------------*/ +/* Write one byte over the UART. */ +void +uart1_writeb(uint8_t byte) +{ + IRCON2_UTX1IF = 0; + U1BUF = byte; + while(!IRCON2_UTX1IF); /* Wait until byte has been transmitted. */ + IRCON2_UTX1IF = 0; +} +/*---------------------------------------------------------------------------*/ +#endif diff --git a/cpu/cc2430/dev/uart1.h b/cpu/cc2430/dev/uart1.h new file mode 100644 index 000000000..53022a902 --- /dev/null +++ b/cpu/cc2430/dev/uart1.h @@ -0,0 +1,39 @@ +#ifndef UART_1_H +#define UART_1_H + +#include "contiki-conf.h" + +#include "cc2430_sfr.h" +#include "8051def.h" +#include "uart.h" + +/*---------------------------------------------------------------------------*/ +/* UART1 Enable - Disable */ +#ifdef UART_ONE_CONF_ENABLE +#define UART_ONE_ENABLE UART_ONE_CONF_ENABLE +#else +#define UART_ONE_ENABLE 0 +#endif +/*---------------------------------------------------------------------------*/ +/* UART1 Function Declarations */ +#if UART_ONE_ENABLE +void uart1_init(); +void uart1_writeb(uint8_t byte); + +void uart1_set_input(int (*input)(unsigned char c)); +#if UART_ONE_CONF_WITH_INPUT +void uart1_rx_ISR( void ) __interrupt (URX1_VECTOR); +void uart1_tx_ISR( void ) __interrupt (UTX1_VECTOR); +/* Macro to turn on / off UART RX Interrupt */ +#define UART1_RX_INT(v) IEN0_URX1IE = v +#else +#define UART1_RX_INT(v) +#endif /* UART_ONE_CONF_WITH_INPUT */ +#else +#define uart1_init(...) +#define uart1_writeb(...) +#define uart1_set_input(...) +#define UART1_RX_INT(v) +#endif /* UART_ONE_ENABLE */ + +#endif /* UART_1_H */ diff --git a/cpu/cc2430/dev/uart_init.c b/cpu/cc2430/dev/uart_init.c deleted file mode 100644 index 95d5f7284..000000000 --- a/cpu/cc2430/dev/uart_init.c +++ /dev/null @@ -1,133 +0,0 @@ -/** - * \file - * - * uart initialization routines - * - * \author - * - * Anthony "Asterisk" Ambuehl - * - * non-interrupt routines typically only called once, stored in any bank. - * - */ -#include -#include - -#include "banked.h" -#include "cc2430_sfr.h" - -#include "dev/leds.h" -#include "dev/uart.h" - -/*---------------------------------------------------------------------------*/ -void -uart0_init(uint32_t speed) __banked -{ - if(speed == 115200) { - U0BAUD=216; /*115200*/ - U0GCR =11; /*LSB first and 115200*/ - } - else if(speed == 38400) { - U0BAUD=59; /*38400*/ - U0GCR =10; /*LSB first and 38400*/ - } - else if(speed == 9600) { - U0BAUD= 59; /* 9600 */ - U0GCR = 8; /*LSB first and 9600*/ - } - else { return; } - -#ifdef UART0_ALTERNATIVE_2 - PERCFG |= U0CFG; /*alternative port 2 = P1.5-2*/ -#ifdef UART0_RTSCTS - P1SEL |= 0x3C; /*peripheral select for TX and RX, RTS, CTS*/ -#else - P1SEL |= 0x30; /*peripheral select for TX and RX*/ - P1 &= ~0x08; /*RTS down*/ -#endif - P1DIR |= 0x28; /*RTS, TX out*/ - P1DIR &= ~0x14; /*CTS & RX in*/ -#else - PERCFG &= ~U0CFG; /*alternative port 1 = P0.5-2*/ -#ifdef UART0_RTSCTS - P0SEL |= 0x3C; /*peripheral select for TX and RX, RTS, CTS*/ -#else - P0SEL |= 0x0C; /*peripheral select for TX and RX*/ - P0 &= ~0x20; /*RTS down*/ -#endif - P0DIR |= 0x28; /*RTS & TX out*/ - P0DIR &= ~0x14; /*CTS & RX in*/ -#endif - - -#ifdef UART0_RTSCTS - U0UCR = 0x42; /*defaults: 8N1, RTS/CTS, high stop bit*/ -#else - U0UCR = 0x02; /*defaults: 8N1, no flow control, high stop bit*/ -#endif - - U0CSR = U_MODE | U_RE | U_TXB; /*UART mode, receiver enable, TX done*/ - - /*set priority group of group 3 to highest, so the UART won't miss bytes*/ - IP1 |= IP1_3; - IP0 |= IP0_3; - - IEN0_URX0IE = 1; -} -/*---------------------------------------------------------------------------*/ -/* UART1 initialization */ -void -uart1_init(uint32_t speed) __banked -{ -#ifdef UART1_ALTERNATIVE_1 - PERCFG &= ~U1CFG; /*alternative port 1 = P0.5-2*/ -#ifdef UART1_RTSCTS - P0SEL |= 0x3C; /*peripheral select for TX and RX, RTS, CTS*/ -#else - P0SEL |= 0x30; /*peripheral select for TX and RX*/ - P0 &= ~0x08; /*RTS down*/ -#endif - P0DIR |= 0x18; /*RTS, TX out*/ - P0DIR &= ~0x24; /*CTS, RX in*/ -#else - PERCFG |= U1CFG; /*alternative port 2 = P1.7-4*/ -#ifdef UART1_RTSCTS - P1SEL |= 0xF0; /*peripheral select for TX and RX*/ -#else - P1SEL |= 0xC0; /*peripheral select for TX and RX*/ - P1 &= ~0x20; /*RTS down*/ -#endif - P1DIR |= 0x60; /*RTS, TX out*/ - P1DIR &= ~0x90; /*CTS, RX in*/ -#endif - - if(speed == 115200) { - U1BAUD=216; /*115200*/ - U1GCR =11; /*LSB first and 115200*/ - } - - if(speed == 38400) { - U1BAUD=59; /*38400*/ - U1GCR =10; /*LSB first and 38400*/ - } - - if(speed == 9600) { - U1BAUD= 59; /* 9600 */ - U1GCR = 8; /*LSB first and 9600*/ - } - -#ifdef UART1_RTSCTS - U1UCR = 0x42; /*defaults: 8N1, RTS/CTS, high stop bit*/ -#else - U1UCR = 0x02; /*defaults: 8N1, no flow control, high stop bit*/ -#endif - - U1CSR = U_MODE | U_RE | U_TXB; /*UART mode, receiver enable, TX done*/ - - /*set priority group of group 3 to highest, so the UART won't miss bytes*/ - IP1 |= IP1_3; - IP0 |= IP0_3; - - IEN0_URX1IE = 1; /* Enable the RX interrupt */ -} -/*---------------------------------------------------------------------------*/ diff --git a/cpu/cc2430/dev/uart_intr.c b/cpu/cc2430/dev/uart_intr.c index c0f8a7f5f..27803f2a6 100644 --- a/cpu/cc2430/dev/uart_intr.c +++ b/cpu/cc2430/dev/uart_intr.c @@ -16,10 +16,18 @@ #include "cc2430_sfr.h" #include "dev/leds.h" -#include "dev/uart.h" +#include "dev/uart0.h" +#include "dev/uart1.h" +#include "sys/energest.h" +#if UART_ZERO_ENABLE static int (*uart0_input_handler)(unsigned char c); +#endif +#if UART_ONE_ENABLE static int (*uart1_input_handler)(unsigned char c); +#endif + +#if UART_ZERO_ENABLE /*---------------------------------------------------------------------------*/ void uart0_set_input(int (*input)(unsigned char c)) @@ -29,18 +37,22 @@ uart0_set_input(int (*input)(unsigned char c)) /*---------------------------------------------------------------------------*/ void -uart0_rxISR(void) __interrupt (URX0_VECTOR) +uart0_rx_ISR(void) __interrupt (URX0_VECTOR) { + ENERGEST_ON(ENERGEST_TYPE_IRQ); TCON_URX0IF = 0; if(uart0_input_handler != NULL) { uart0_input_handler(U0BUF); } + ENERGEST_OFF(ENERGEST_TYPE_IRQ); } /*---------------------------------------------------------------------------*/ void -uart0_txISR( void ) __interrupt (UTX0_VECTOR) +uart0_tx_ISR( void ) __interrupt (UTX0_VECTOR) { } +#endif /* UART_ZERO_ENABLE */ +#if UART_ONE_ENABLE /*---------------------------------------------------------------------------*/ void uart1_set_input(int (*input)(unsigned char c)) @@ -48,17 +60,22 @@ uart1_set_input(int (*input)(unsigned char c)) uart1_input_handler = input; } /*---------------------------------------------------------------------------*/ +#if UART_ONE_CONF_WITH_INPUT void -uart1_rxISR(void) __interrupt (URX1_VECTOR) +uart1_rx_ISR(void) __interrupt (URX1_VECTOR) { + ENERGEST_ON(ENERGEST_TYPE_IRQ); TCON_URX1IF = 0; if(uart1_input_handler != NULL) { uart1_input_handler(U1BUF); } + ENERGEST_OFF(ENERGEST_TYPE_IRQ); } /*---------------------------------------------------------------------------*/ void -uart1_txISR( void ) __interrupt (UTX1_VECTOR) +uart1_tx_ISR( void ) __interrupt (UTX1_VECTOR) { } /*---------------------------------------------------------------------------*/ +#endif /* UART_ONE_CONF_WITH_INPUT */ +#endif /* UART_ONE_ENABLE */ diff --git a/cpu/cc2430/dev/watchdog-cc2430.c b/cpu/cc2430/dev/watchdog-cc2430.c new file mode 100644 index 000000000..2d59d2923 --- /dev/null +++ b/cpu/cc2430/dev/watchdog-cc2430.c @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2010, Loughborough University - Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * Hardware-dependent functions used for the cc2430 watchdog timer. + * + * This file contains an ISR and must reside in the HOME bank. + * + * \author + * George Oikonomou - + */ + +#include "sys/energest.h" +#include "cc2430_sfr.h" +#include "contiki-conf.h" +#include "dev/watchdog-cc2430.h" + +/*---------------------------------------------------------------------------*/ +/* The watchdog only throws interrupts in timer mode */ +#if WDT_TIMER_MODE +void +cc4230_watchdog_ISR(void) __interrupt (WDT_VECTOR) +{ + EA = 0; + ENERGEST_ON(ENERGEST_TYPE_IRQ); + /* Do something */ + IRCON2 &= ~WDTIF; + ENERGEST_OFF(ENERGEST_TYPE_IRQ); + EA = 1; +} +#endif +/*---------------------------------------------------------------------------*/ +void +watchdog_init(void) +{ + WDCTL = WDT_TIMER_MODE | WDT_INTERVAL; + +#if WDT_TIMER_MODE + /* Enable the watchdog interrupts in timer mode */ + IEN2 |= WDTIE; +#endif + return; +} +/*---------------------------------------------------------------------------*/ +void +watchdog_start(void) +{ + WDCTL |= WDT_EN; +} +/*---------------------------------------------------------------------------*/ +void +watchdog_periodic(void) +{ +#if WDT_TIMER_MODE + /* In timer mode, all we need to do is write 1 to WDT:CLR[0] */ + WDCTL |= WDT_CLR0; +#else + /* Write the 'clear' sequence while maintaining mode and interval setting */ + WDCTL = (WDCTL & 0x0F) | WDT_CLR3 | WDT_CLR1; + WDCTL = (WDCTL & 0x0F) | WDT_CLR2 | WDT_CLR0; +#endif +} +/*---------------------------------------------------------------------------*/ +void +watchdog_stop(void) +{ +#if WDT_TIMER_MODE + /* In timer mode, the watchdog can actually be stopped */ + WDCTL &= ~WDT_EN; + IRCON2 &= ~WDTIF; +#else + /* In watchdog mode, stopping is impossible so we just reset the timer */ + watchdog_periodic(); +#endif +} +/*---------------------------------------------------------------------------*/ +void +watchdog_reboot(void) +{ +#if WDT_TIMER_MODE + /* Switch modes to watchdog, minimum interval, enable */ + WDCTL = WDT_EN | WDT_TIMEOUT_2_MSEC; +#else + /* Let's get this over with ASAP */ + WDCTL = WDT_TIMEOUT_2_MSEC; +#endif + /* Dis-acknowledge all interrupts while we wait for the dog to bark */ + DISABLE_INTERRUPTS(); + /* NOP till the dog barks... */ + while(1) { + __asm + nop + __endasm; + } +} diff --git a/cpu/cc2430/dev/watchdog-cc2430.h b/cpu/cc2430/dev/watchdog-cc2430.h new file mode 100644 index 000000000..8ea81fa2c --- /dev/null +++ b/cpu/cc2430/dev/watchdog-cc2430.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2010, Loughborough University - Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * Hardware-dependent header file for the cc2430 watchdog timer. + * + * The interrupt service routine's prototype must be included by the + * file containing main(). + * + * \author + * George Oikonomou - + */ + +#ifndef WATCHDOG_CC2430_H_ +#define WATCHDOG_CC2430_H_ + +#include "dev/watchdog.h" +#include "cc2430_sfr.h" +#include "contiki-conf.h" + +#define WDT_TIMEOUT_1_SEC 0x00 +#define WDT_TIMEOUT_250_MSEC WDT_INT0 +#define WDT_TIMEOUT_15_MSEC WDT_INT1 +#define WDT_TIMEOUT_2_MSEC WDT_INT1 | WDT_INT0 + +#if WDT_CONF_TIMER_MODE +#define WDT_TIMER_MODE WDT_MODE /* Timer */ +#else +#define WDT_TIMER_MODE 0x00 /* Watchdog */ +#endif + +#ifdef WDT_CONF_INTERVAL +#define WDT_INTERVAL WDT_CONF_INTERVAL +#else +#define WDT_INTERVAL WDT_TIMEOUT_1_SEC /* 2 secs */ +#endif + +/* The watchdog only throws interrupts in timer mode */ +#if WDT_TIMER_MODE +void cc4230_watchdog_ISR(void) __interrupt (WDT_VECTOR); +#endif + +#endif /* WATCHDOG_CC2430_H_ */ diff --git a/cpu/cc2430/io.h b/cpu/cc2430/io.h deleted file mode 100644 index c14ed21f0..000000000 --- a/cpu/cc2430/io.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef __IO_H__ -#define __IO_H__ - -#include - -#ifndef BV -#define BV(x) (1<<(x)) -#endif - -#endif /* __IO_H__ */ diff --git a/cpu/cc2430/mtarch.c b/cpu/cc2430/mtarch.c deleted file mode 100644 index 50f9959dc..000000000 --- a/cpu/cc2430/mtarch.c +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Copyright (c) 2007, Takahide Matsutsuka. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * 3. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - /* - * \file - * Z80 machine-specific implementation for supporting multithread. - * \author - * Takahide Matsutsuka - */ -#include "sys/mt.h" -#include "mtarch.h" - -/*--------------------------------------------------------------------------*/ -void -mtarch_init(void) -{ -} -/*--------------------------------------------------------------------------*/ -void -mtarch_start(struct mtarch_thread *t, - void (*function)(void *), void *data) -{ - uint16_t i; - - for(i = 0; i < MTARCH_STACKSIZE; i++) { - t->stack[i] = i; - } - - t->sp = &t->stack[MTARCH_STACKSIZE - 1]; - - - /* A parameter for method for thread function. */ - *t->sp = (uint16_t)data; - --t->sp; - - /* This will be a return address of thread function. */ - *t->sp = (uint16_t)mt_exit; - --t->sp; - - /* The thread function, is used as a return address of mtarch_switch. */ - *t->sp = (uint16_t)function; - --t->sp; - - /* - * Space for registers. - * af, bc, de, hl, ix, iy, af', bc', de', hl' - */ - /* - * Z80 stack basis: - * push stores the data AFTER decrementing sp. - * pop reads the data BEFORE incrementing sp. - */ - - t->sp = t->sp - 9; -} -/*--------------------------------------------------------------------------*/ -static struct mtarch_thread *running_thread; -static uint16_t *sptmp; -static void -mtarch_switch() -{ - __asm - di ; disable interrupt - ; normal registers - push af - push bc - push de - push hl - push ix - push iy - - ; back registers - ex af,af' - push af - exx - push bc - push de - push hl - - ; swap between running_thread->sp and SP reg - ; _running_thread in asembler below points running_thread->sp - ; sptmp = sp; - ld (_sptmp),sp - - ; sp = *(running_thread->sp); - ld ix,(_running_thread) - ld l,0(ix) - ld h,1(ix) - ld sp,hl - - ; running_thread->sp = sptmp; - ld hl,(_sptmp) - ld 0(ix),l - ld 1(ix),h - - ; back registers - pop hl - pop de - pop bc - exx - pop af - ex af,af' - - ; normal registers - pop iy - pop ix - pop hl - pop de - pop bc - pop af - ei ; enable interrupt - __endasm; - // here sp indicates the address that point the function -} -/*--------------------------------------------------------------------------*/ -void -mtarch_exec(struct mtarch_thread *t) -{ - running_thread = t; - mtarch_switch(); - running_thread = NULL; -} -/*--------------------------------------------------------------------------*/ -void -mtarch_remove() -{ -} -/*--------------------------------------------------------------------------*/ -void -mtarch_yield() -{ - if (running_thread == NULL) { - /* ERROR! we have no runnning thread. */ - return; - } - mtarch_switch(); -} -/*--------------------------------------------------------------------------*/ -void mtarch_stop(struct mtarch_thread *thread) -{ -} -/*--------------------------------------------------------------------------*/ -void -mtarch_pstop() -{ -} -/*--------------------------------------------------------------------------*/ -void -mtarch_pstart() -{ -} -/*--------------------------------------------------------------------------*/ -int -mtarch_stack_usage(struct mtarch_thread *t) -{ - uint16_t i; - for (i = 0; i < MTARCH_STACKSIZE; i++) { - if (t->stack[i] != i) { - return MTARCH_STACKSIZE - i; - } - } - - return 0; -} -/*--------------------------------------------------------------------------*/ diff --git a/cpu/cc2430/mtarch.h b/cpu/cc2430/mtarch.h index f5d2b80b2..b228150ab 100644 --- a/cpu/cc2430/mtarch.h +++ b/cpu/cc2430/mtarch.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, Takahide Matsutsuka. + * Copyright (c) 2010, Loughborough University - Computer Science * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -28,38 +28,23 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ + /* * \file - * Z80 machine-specific difinitions for supporting multithread. - * + * Stub header file for cc2430 multi-threading. It doesn't do anything, it + * just exists so that mt.c can compile cleanly. + * + * This is based on the original mtarch.h for z80 by Takahide Matsutsuka + * * \author - * Takahide Matsutsuka + * George Oikonomou - */ #ifndef __MTARCH_H__ #define __MTARCH_H__ -/* Unit of the stack is 2byte wide. */ -#ifndef MTARCH_STACKSIZE -#define MTARCH_STACKSIZE 128 -#endif /* MTARCH_STACKSIZE */ - struct mtarch_thread { - /* - * On top of the mtarch_thread must be the address for the stack pointer. - * See details at mtarch_switch in mtarch.c - */ - uint16_t *sp; - /* - * Stack is 2-byte wide, so please note that you need 2 * MTARCH_STACKSIZE - * bytes for the stack area for each thread. - */ - uint16_t stack[MTARCH_STACKSIZE]; + unsigned char *sp; }; -/* - * A function for debugging purpose, placed here by following other implementations. - */ -int mtarch_stack_usage(struct mtarch_thread *t); - #endif /* __MTARCH_H__ */ diff --git a/cpu/cc2430/rtimer-arch.c b/cpu/cc2430/rtimer-arch.c new file mode 100644 index 000000000..517886037 --- /dev/null +++ b/cpu/cc2430/rtimer-arch.c @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2010, Loughborough University - Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + */ + +/** + * \file + * Hardware-dependent functions used to support the + * contiki rtimer module. + * + * clock and etimer are using the sleep timer on the cc2430 + * + * clock_init() has set our tick speed prescaler already, so we + * are ticking with 500 kHz freq. + * + * rtimer_clock_t is unsigned short (16bit on the cc2430) + * It thus makes sense to use the 16bit clock (Timer 1) + * + * This file contains an ISR and must reside in the HOME bank + * + * \author + * George Oikonomou - + */ + +#include "sys/rtimer.h" /* Includes rtimer-arch.h for us */ +#include "cc2430_sfr.h" +#include "sys/energest.h" + +#define DEBUG 0 +#if DEBUG +#include +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif + +/*---------------------------------------------------------------------------*/ +void +rtimer_arch_init(void) +{ + PRINTF("rtimer_arch_init() "); + /* + * - Free running mode + * - Prescale by 32: + * Tick Speed has been prescaled to 500 kHz already in clock_init() + * We further prescale by 32 resulting in 15625 Hz for this timer. + */ + T1CTL = (T1DIV1 | T1MODE0); /* 00001001 */ + PRINTF("T1CTL=0x%02x\n", T1CTL); + /* Acknowledge Timer 1 Interrupts */ + IEN1_T1IE = 1; + PRINTF("IEN1_T1IE=0x%02x\n", IEN1_T1IE); + + /* Timer 1, Channel 1. Compare Mode (0x04), Interrupt mask on (0x40) */ + T1CCTL1 = T1MODE + T1IM; + PRINTF("T1CCTL1=0x%02x\n", T1CCTL1); + + /* Interrupt Mask Flags: No interrupt on overflow */ + TIMIF &= ~OVFIM; + PRINTF("TIMIF=0x%02x\n", TIMIF); + + PRINTF("done\n"); +} +/*---------------------------------------------------------------------------*/ +void +rtimer_arch_schedule(rtimer_clock_t t) +{ + PRINTF("rtimer_arch_schedule(%u)\n", t); + + /* set the compare mode values so we can get an interrupt after t */ + T1CC1L = (unsigned char) t; + T1CC1H = (unsigned char) (t >> 8); + PRINTF("T1CC1=%u, t=%u\n", (T1CC1L + (T1CC1H << 8)), t); + + /* Turn on compare mode interrupt */ + PRINTF("T1CTL=0x%02x\n", T1CTL); + T1CCTL1 |= T1IM; +} +/*---------------------------------------------------------------------------*/ +void +cc2430_timer_1_ISR(void) __interrupt (T1_VECTOR) +{ + IEN1_T1IE = 0; /* Ignore Timer 1 Interrupts */ + ENERGEST_ON(ENERGEST_TYPE_IRQ); + /* No more interrupts from Channel 1 till next rtimer_arch_schedule() call. + * Setting the mask will instantly generate an interrupt so we clear the + * flag first. */ + T1CTL &= ~(CH1IF); + T1CCTL1 &= ~T1IM; + + rtimer_run_next(); + + ENERGEST_OFF(ENERGEST_TYPE_IRQ); + IEN1_T1IE = 1; /* Acknowledge Timer 1 Interrupts */ +} diff --git a/cpu/cc2430/rtimer-arch.h b/cpu/cc2430/rtimer-arch.h index be2aec319..89579b37a 100644 --- a/cpu/cc2430/rtimer-arch.h +++ b/cpu/cc2430/rtimer-arch.h @@ -33,18 +33,31 @@ /** * \file - * A brief description of what this file is. + * Hardware-dependent function declarations used to + * support the contiki rtimer module. + * + * We use Timer 1 on the cc2431. + * * \author - * Adam Dunkels + * Zach Shelby (Original) + * George Oikonomou - + * (rtimer-arch implementation for cc2430) */ #ifndef __RTIMER_ARCH_H__ #define __RTIMER_ARCH_H__ #include "contiki-conf.h" +#include "cc2430_sfr.h" -#define RTIMER_ARCH_SECOND 1000 +/* + * 32 MHz clock, prescaled down to 500 kHz for all 4 timers in clock_init(). + * Further prescaled factor 32 for T1, thus T1 is 15625 Hz + */ +#define RTIMER_ARCH_SECOND (15625U) -#define rtimer_arch_now() clock_time() +#define rtimer_arch_now() ((rtimer_clock_t)(T1CNTL + (T1CNTH << 8))) + +void cc2430_timer_1_ISR(void) __interrupt (T1_VECTOR); #endif /* __RTIMER_ARCH_H__ */ diff --git a/cpu/cc2430/segment.rules b/cpu/cc2430/segment.rules index 1534b9e26..3b4ffbdfa 100644 --- a/cpu/cc2430/segment.rules +++ b/cpu/cc2430/segment.rules @@ -1,25 +1,26 @@ -# segment.rules file assigns source code modules to specific banks -# segment.rules is constructed from any segment.rules found in the search path -# the search path is defined in Makefile.cc2430 -# segment.rules get processed by a perl snippet listed in the Makefile.cc2430 -# the processed output is put into the obj_* directory +# segment.rules files assign source code modules to specific banks +# These files are only used when we build code with banking (HAVE_BANKING=1) +# The final segment.rules file is constructed from any segment.rules found in +# the search path, defined in Makefile.cc2430 +# When building bankable code, the bank-alloc.py script automatically allocates +# modules to banks. segment.rules files provide hints, instructing the script +# as to which files are safe to move around and which files to leave alone +# In other words, only specify a rule for a file if you need to # comments starting with "#" are supported -# perl regular expression matching can be used on the file name specification -# -# general rules -- -# some code must be placed in all banks (or SDCC/aslink will complain at link time) -# code called from function pointers must be in HOME/CSEG/BANK0 -# interrupt code must also be in HOME/CSEG/BANK0 -# code not marked with __banked can only be called from code in the same bank +# The file spec in rules is actually interpreted as a python regex so you can +# write a rule that will match multiple files # -HOME intr.c # All interrupt code must live in HOME/BANK0 -HOME bus.c # flash_read cannot be banked. -HOME clock.c # cannot bank clock.c code because header file is part of core. -HOME uart.c -BANK3 uart_init.c -BANK2 dma.c -CSEG cc2430/dev/bus.c -CSEG autostart.c -BANK2 cc2430/dev/cc2430_rf.c -BANK1 cc2430/ -BANK1 . +# general rules -- +# This file is only used when the Makefile defines HAVE_BANKING=1 +# SDCC's standard libraries will always go in CSEG - We don't touch them +# Interrupt code must be in HOME. Specify all files with an ISR here +# All files without an associated rule get allocated to a bank automatically + +# Files with ISRs must be in HOME +HOME intr.c # Match all files ending in intr.c (e.g. uart_intr.c) +HOME rtimer-arch.c +HOME watchdog-cc2430.c +HOME clock.c + +# Some cc2430 files which need special treatment +HOME bus.c # bus.c::flash_read() must be run from HOME (if compiled in) diff --git a/cpu/cc2430/segment.rules.pl b/cpu/cc2430/segment.rules.pl deleted file mode 100644 index 213dd8fa2..000000000 --- a/cpu/cc2430/segment.rules.pl +++ /dev/null @@ -1,11 +0,0 @@ - $match_me = pop @ARGV; - #print "searching for $match_me\n"; - while (<>) { - s/#.*$//; # filter out comments - s/^\s*//; # filter out leading white space - @F=split /\s+/; # split on white space - if (($_ =~ m/\S\s+\S/) && ($match_me =~ m/$F[1]/)) { - print $F[0]."\n"; - exit; #return only first match - } - } diff --git a/cpu/cc2430/uip_arch-asm.S b/cpu/cc2430/uip_arch-asm.S deleted file mode 100644 index e64ddf45a..000000000 --- a/cpu/cc2430/uip_arch-asm.S +++ /dev/null @@ -1,221 +0,0 @@ -;;; -;;; -;;; uip_arch-asm.S -;;; -;;; \file -;;; Z80 architecture-depend uip module -;;; for calculating checksums -;;; -;;; \author -;;; Takahide Matsutsuka -;;; - .module uip_arch-asm - - ;; export symbols - .globl _uip_add32 - .globl _uip_arch_chksum - .globl _uip_chksum - - ;; import symbols - .globl _uip_acc32 - .globl _uip_buf - - .area _DATA - - .area _GSINIT - - .area _CODE - - ;; --------------------------------- - ;; void uip_add32(uint8_t *op32, uint16_t op16); - ;; Stack; retl reth op32l op32h op16l op16h - ;; ABCDEHL____ - ;; return void - ;; _uip_acc32 = op32 + op16 - ;; --------------------------------- -_uip_add32_start:: -_uip_add32: - ;; HL = #_op32l - ld hl, #2 - add hl, sp - - ;; DE = #(_op32) - ld e, (hl) - inc hl - ld d, (hl) - inc hl - - ;; BC = op16 - ld c, (hl) - inc hl - ld b, (hl) - - ;; HL = #(_op32) + 3 - ld hl, #3 - add hl, de - - ;; DE = #_uip_acc32 + 3 - ld de, #_uip_acc32 + 3 - - ;; uip_acc32[3] = op32[3] + op16l; - ld a, (hl) - add a, c - ld (de), a - - ;; uip_acc32[2] = op32[2] + op16h + carry; - dec hl - dec de - ld a, (hl) - adc a, b - ld (de), a - jr nc, _uip_add32_nocarry1 - - ;; uip_acc32[1] - dec hl - dec de - ld a, (hl) - inc a - ld (de), a - jr nz, _uip_add32_nocarry0 - - ;; uip_acc32[0] - dec hl - dec de - ld a, (hl) - inc a - ld (de), a - ret -_uip_add32_nocarry1: - ;; uip_acc32[1] - dec hl - dec de - ld a, (hl) - ld (de), a - -_uip_add32_nocarry0: - ;; uip_acc32[0] - dec hl - dec de - ld a, (hl) - ld (de), a - ret -_uip_add32_end:: - - ;; --------------------------------- - ;; static uint16_t chksum(uint16_t sum, const uint8_t *data, uint16_t len) - ;; Stack; retl reth suml sumh datal datah lenl lenh - ;; ABCDEHL____ - ;; return HL - ;; --------------------------------- -_uip_arch_chksum_start:: -_uip_arch_chksum: - push ix - ;; IX = #_suml - ld ix, #4 - add ix, sp - ;; BC = sum - ld c, 0(ix) - ld b, 1(ix) - ;; DE = #data - ld e, 2(ix) - ld d, 3(ix) - - ;; (lenl, lenh) <- dataptr + len - 1 (last address) - ;; (len) + DE - 1 -> (len) - ld l, 4(ix) - ld h, 5(ix) - add hl, de - dec hl - ld 4(ix), l - ld 5(ix), h - -_uip_arch_chksum_loop: - ;; compare HL(last address) and DE(dataptr) - ;; HL - DE - ;; if (HL < DE) C,NZ else if (HL = DE) NC,Z=1 otherwise NC,NZ - ;; HL = last address, DE = current pointer - ld l, 4(ix) - ld h, 5(ix) - - ld a, h - sub d - jr nz, _uip_arch_chksum_compared - ld a, l - sub e - ;; if (last address == dataptr) _uip_arch_chksum_loop_exit_add_trailing - jr z, _uip_arch_chksum_loop_exit_add_trailing -_uip_arch_chksum_compared: - ;; if (last address > dataptr) _uip_arch_chksum_loop_exit - jr c, _uip_arch_chksum_loop_exit - ;; bc = dataptr[0],dataptr[1] + bc - ld a, (de) - ld h, a - inc de - ld a, (de) - ld l, a - push hl - add hl, bc - inc de - ld b, h - ld c, l - ;; HL = t - pop hl - ;; BC - HL - ;; if (sumBC < tHL) sum++ - ld a, b - sub h - jr nz, _uip_arch_chksum_compared_t - ld a, c - sub l -_uip_arch_chksum_compared_t: - jr nc, _uip_arch_chksum_nocarry_t - inc bc -_uip_arch_chksum_nocarry_t: - jr _uip_arch_chksum_loop -_uip_arch_chksum_loop_exit_add_trailing: - ;; HL = last address - ;; bc = bc + (last address)<<8 - ld a, b - add a, (hl) - ld b, a - jr nc, _uip_arch_chksum_loop_exit - inc bc -_uip_arch_chksum_loop_exit: - ld l, c - ld h, b - pop ix - ret -_uip_arch_chksum_end:: - - ;; --------------------------------- - ;; uint16_t uip_chksum(void); - ;; Stack; retl reth datal datah lenl lenh - ;; ABCDEHL____ - ;; return HL - ;; return htons(chksum(0, (uint8_t *)data, len)); - ;; --------------------------------- -_uip_chksum_start:: -_uip_chksum: - ld hl, #5 - add hl, sp - ;; HL indicates #_lenh - ld b, #2 -_uip_chksum_loop: - ld d, (hl) - dec hl - ld e, (hl) - dec hl - push de - djnz _uip_chksum_loop - ld bc, #0 - push bc - call _uip_arch_chksum - pop af - pop af - pop af - ;; convert to BIG ENDIAN (htons) - ld a, l - ld l, h - ld h, a - ret -_uip_chksum_end:: diff --git a/cpu/cc2430/uip_arch.c b/cpu/cc2430/uip_arch.c deleted file mode 100644 index afa6b601e..000000000 --- a/cpu/cc2430/uip_arch.c +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Copyright (c) 2007, Takahide Matsutsuka. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * 3. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $Id: uip_arch.c,v 1.2 2010/10/19 18:29:04 adamdunkels Exp $ - * - */ - /* - * \file - * Z80 architecture-depend uip module - * for calculating checksums - * \author - * Takahide Matsutsuka - */ - -#include -#include "uip_arch.h" - -static const uint16_t sizeof_uip_ipaddr_t = sizeof(uip_ipaddr_t); -static const uint16_t offset_tcpip_hdr_len = offsetof(struct uip_tcpip_hdr, len); -static const uint16_t offset_tcpip_hdr_srcipaddr = offsetof(struct uip_tcpip_hdr, srcipaddr); - -/*--------------------------------------------------------------------------*/ -static void upper_layer_chksum() { -__asm - ;; --------------------------------- - ;; static uint16_t upper_layer_chksum(uint8_t proto); - ;; Stack; retl reth - ;; @param C proto - ;; ABCDEHL____ - ;; --------------------------------- - ;; HL = BUF = &uip_buf[UIP_LLH_LEN] - ld hl, #_uip_buf - ld de, #UIP_LLH_LEN - add hl, de - push hl - - ;; HL = BUF->len[0] - push ix - ld ix, #_offset_tcpip_hdr_len - ld e, 0(ix) - ld d, 1(ix) - add hl, de - pop ix - - ;; DE = upper layer length - ld d, (hl) - inc hl - ld e, (hl) -#if UIP_CONF_IPV6 -#else - ld a, e - sub a, #UIP_IPH_LEN - ld e, a - jr nc, _upper_layer_chksum_setlen2 - dec d -_upper_layer_chksum_setlen2: -#endif - ;; bc = upper_leyer_len + proto - ld b, d - ld a, e - add a, c - ld c, a - jr nc, _upper_layer_chksum_setlen3 - inc b -_upper_layer_chksum_setlen3: - pop hl ; BUF - push de - push ix - ld ix, #_offset_tcpip_hdr_srcipaddr - ld e, 0(ix) - ld d, 1(ix) - add hl, de - ld e, l - ld d, h - ld ix, #_sizeof_uip_ipaddr_t - ld l, 0(ix) - ld h, 1(ix) - pop ix - sla l - rl h - push hl - push de - push bc - call _uip_arch_chksum ; hl = sum - pop af - pop af - pop af - ;; de is still stacked - - ld b, h - ld c, l - ld hl, #_uip_buf - ld de, #UIP_IPH_LEN - add hl, de -_upper_layer_chksum_call: - ld de, #UIP_LLH_LEN - add hl, de - push hl - push bc - call _uip_arch_chksum - pop af - pop af - pop af - - ld a, h - or a, l - jr nz, _upper_layer_uip_htons - ld hl, #0xffff - jr _upper_layer_ret -_upper_layer_uip_htons: - ld a, l - ld l, h - ld h, a -_upper_layer_ret: -__endasm; -} - -/*--------------------------------------------------------------------------*/ -uint16_t -uip_ipchksum(void) -{ -__asm - ;; --------------------------------- - ;; uint16_t uip_ipchksum(void); - ;; Stack; retl reth - ;; ABCDEHL____ - ;; return HL - ;; --------------------------------- - ld hl, #UIP_IPH_LEN - push hl - ;; HL = BUF = &uip_buf[UIP_LLH_LEN] - ld hl, #_uip_buf - ;; BC = sum = 0 - ld bc, #0 - jp _upper_layer_chksum_call -__endasm; -} - -/*--------------------------------------------------------------------------*/ -#if UIP_CONF_IPV6 -uint16_t -uip_icmp6chksum(void) -{ -__asm - ;; --------------------------------- - ;; uint16_t uip_icmp6chksum(void); - ;; Stack; retl reth - ;; ABCDEHL____ - ;; return HL - ;; --------------------------------- - ld c, #UIP_PROTO_ICMP6 - jp _upper_layer_chksum -__endasm; -} -#endif /* UIP_CONF_IPV6 */ - -/*--------------------------------------------------------------------------*/ -uint16_t -uip_tcpchksum(void) -{ -__asm - ;; --------------------------------- - ;; uint16_t uip_tcpchksum(void); - ;; Stack; retl reth - ;; ABCDEHL____ - ;; return HL - ;; --------------------------------- - ld c, #UIP_PROTO_TCP - jp _upper_layer_chksum -__endasm; -} - -/*--------------------------------------------------------------------------*/ -#if UIP_UDP_CHKSUMS -uint16_t -uip_udpchksum(void) -{ -__asm - ;; --------------------------------- - ;; uint16_t uip_udpchksum(void); - ;; Stack; retl reth - ;; ABCDEHL____ - ;; return HL - ;; --------------------------------- - ld c, #UIP_PROTO_UDP - jp _upper_layer_chksum -__endasm; -} -#endif /* UIP_UDP_CHKSUMS */ -/*--------------------------------------------------------------------------*/ diff --git a/cpu/cc253x/8051def.h b/cpu/cc253x/8051def.h new file mode 100644 index 000000000..7314edcd7 --- /dev/null +++ b/cpu/cc253x/8051def.h @@ -0,0 +1,79 @@ +/* + * \file + * This file contains a set of configuration for using SDCC as a compiler. + * Modified from z80 port for cc2430 port. + * + * \author + * Takahide Matsutsuka (Original) + * George Oikonomou - + * (updates for the cc2530 ports) + */ + +#ifndef __8051_DEF_H__ +#define __8051_DEF_H__ + +#include + +/* + * lint - style defines to help syntax parsers with sdcc-specific 8051 code + * They don't interfere with actual compilation + */ +#if !defined(__SDCC_mcs51) && !defined(SDCC_mcs51) +#define __data +#define __xdata +#define __code +#define __bit bool +#define __sfr volatile unsigned char +#define __sbit volatile bool +#define __critical +#define __at(x) +#define __using(x) +#define __interrupt(x) +#define __naked +#endif + +#define CC_CONF_FUNCTION_POINTER_ARGS 1 +#define CC_CONF_FASTCALL +#define CC_CONF_VA_ARGS 1 +#define CC_CONF_UNSIGNED_CHAR_BUGS 0 +#define CC_CONF_REGISTER_ARGS 0 +#define CC_CONF_FUNCTION_POINTER_KEYWORD __reentrant + +/* Generic types. */ +typedef unsigned char u8_t; /* 8 bit type */ +typedef unsigned short u16_t; /* 16 bit type */ +typedef unsigned long u32_t; /* 32 bit type */ +typedef signed long s32_t; /* 32 bit type */ +typedef unsigned short uip_stats_t; + +/* Compiler configurations */ +#define CCIF +#define CLIF + +/* Single asm instruction without messing up syntax highlighting */ +#if defined SDCC_mcs51 +#define ASM(x) __asm \ + x \ + __endasm +#else +#define ASM(x) +#endif + +/* Critical section management */ +#define DISABLE_INTERRUPTS() do {EA = 0;} while(0) +#define ENABLE_INTERRUPTS() do {EA = 1;} while(0) + +/* Macro for a soft reset. In many respects better than H/W reboot via W/D */ +#define SOFT_RESET() {((void (__code *) (void)) 0x0000) ();} + +/* We don't provide architecture-specific checksum calculations */ +#define UIP_ARCH_ADD32 0 +#define UIP_ARCH_CHKSUM 0 + +#define CC_CONF_ASSIGN_AGGREGATE(dest, src) \ + memcpy(dest, src, sizeof(*dest)) + +#define uip_ipaddr_copy(dest, src) \ + memcpy(dest, src, sizeof(*dest)) + +#endif /* __8051_DEF_H__ */ diff --git a/cpu/cc253x/Makefile.cc253x b/cpu/cc253x/Makefile.cc253x new file mode 100644 index 000000000..568d8f2d9 --- /dev/null +++ b/cpu/cc253x/Makefile.cc253x @@ -0,0 +1,198 @@ +### Compiler definitions +CC = sdcc +LD = sdcc +AS = sdcc +AR = sdcclib +OBJCOPY = objcopy +STRIP = strip + +### Hex file conversions +PACKIHX = packihx +SREC_CAT = srec_cat +SREC_FLAGS = -disable_sequence_warnings + +BANK_ALLOC = $(CONTIKI_CPU)/bank-alloc.py +SEGMENT_RULES = $(OBJECTDIR)/segment.rules + +CFLAGS += --model-$(MEMORY_MODEL) --stack-auto --std-c99 + +LDFLAGS += --model-$(MEMORY_MODEL) --stack-auto --out-fmt-ihx +LDFLAGS += --xram-loc 0x0000 --xram-size 0x1F00 +LDFLAGS += --code-loc $(START_ADDR) --code-size $(CODE_SIZE) + +ASFLAGS += -plosgff + +AROPTS = -a + +### Our object files are .rel, so we can't use the default finalize dependency +### generation. Override here. +define FINALIZE_SDCC_DEPENDENCY +cp $(@:.rel=.d) $(@:.rel=.$$$$); \ +sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \ + -e '/^$$/ d' -e 's/$$/ :/' < $(@:.rel=.$$$$) >> $(@:.rel=.d); \ +rm -f $(@:.rel=.$$$$) +endef + +### Banking Guesswork: +### Generic examples do not specify banking. +### We automatically turn it on if its unspecified and if we are building with +### UIP_CONF_IPV6 +ifndef HAVE_BANKING + ifeq ($(UIP_CONF_IPV6),1) + HAVE_BANKING=1 + else + HAVE_BANKING=0 + endif +endif + +### Does the project want us to offset the firmware? +### define start address and max code size accordingly +ifeq ($(OFFSET_FIRMWARE),1) + START_ADDR = 0x01000 + HOME_START = 00001000 + ifeq ($(HAVE_BANKING),1) + CODE_SIZE = 0x3F000 + else + CODE_SIZE = 0x0F000 + endif +else + START_ADDR = 0x00000 + HOME_START = 00000000 + ifeq ($(HAVE_BANKING),1) + CODE_SIZE = 0x40000 + else + CODE_SIZE = 0x10000 + endif +endif + +### Are we building with BANKing supoprt? +ifeq ($(HAVE_BANKING),1) + ## Yes + MEMORY_MODEL=huge + LDFLAGS += -Wl-r + LD_PRE_FLAGS += -Wl-bBANK1=0x018000 + CFLAGS += -DHAVE_SDCC_BANKING + #use this in $(call c_seg,$<) to get segment for a source file. + c_seg = --codeseg $(shell python $(BANK_ALLOC) $1 $(SEGMENT_RULES) $2) +else + ## No banking + MEMORY_MODEL=large + c_seg = +endif + +### CPU-dependent cleanup files +CLEAN += *.lnk *.lk *.sym *.lib *.ihx *.rel *.mem *.rst *.asm *.hex +CLEAN += *.omf *.cdb *.banks *.flags *.banked-hex +CLEAN += symbols.c symbols.h + +### CPU-dependent directories +CONTIKI_CPU_DIRS = . dev + +### CPU-dependent source files +CONTIKI_SOURCEFILES += soc.c clock.c +CONTIKI_SOURCEFILES += uart0.c uart1.c uart-intr.c +CONTIKI_SOURCEFILES += dma.c dma_intr.c +CONTIKI_SOURCEFILES += cc2530-rf.c +CONTIKI_SOURCEFILES += watchdog.c rtimer-arch.c +CONTIKI_ASMFILES += + +CONTIKI_ASMOBJECTFILES = $(addprefix $(OBJECTDIR)/,$(CONTIKI_ASMFILES:.S=.rel)) + +CONTIKI_CASMOBJECTFILES = $(addprefix $(OBJECTDIR)/, \ + $(CONTIKI_CASMFILES:.cS=.rel)) + +CONTIKI_PLATFORM_DIRS = $(PLATFORM_APPDIRS) \ + $(addprefix $(CONTIKI)/platform/$(TARGET)/, $(CONTIKI_TARGET_DIRS)) + +CONTIKI_CPU_DIRS_LIST = $(addprefix $(CONTIKI_CPU)/, \ + $(CONTIKI_CPU_DIRS)) + +oname = $(patsubst %.c,%.rel,$(patsubst %.S,%.rel,$(1))) + +CONTIKI_OBJECTFILES = $(addprefix $(OBJECTDIR)/, \ + $(call oname, $(CONTIKI_SOURCEFILES))) + +PROJECT_OBJECTFILES = $(addprefix $(OBJECTDIR)/, \ + $(call oname, $(PROJECT_SOURCEFILES))) + +### Compilation rules + +SEGMENT_RULE_FILES = $(foreach dir, . $(CONTIKI_PLATFORM_DIRS) \ + $(CONTIKI_CPU_DIRS_LIST), $(wildcard $(dir)/segment.rules) ) + +$(SEGMENT_RULES): $(SEGMENT_RULE_FILES) + cat $(SEGMENT_RULE_FILES) | \ + sed -e 's/#.*$$//' -e 's/^\s*//' -e '/^$$/d' > $@ + +CUSTOM_RULE_LINK=1 +CUSTOM_RULE_C_TO_OBJECTDIR_O=1 +CUSTOM_RULE_ALLOBJS_TO_TARGETLIB=1 + +$(OBJECTDIR)/%.rel: %.c $(SEGMENT_RULES) + $(CC) $(call c_seg,$<,$@) $(CFLAGS) -c $< -o $@ -Wp,-MMD,$(@:.rel=.d),-MQ,$@ + @$(FINALIZE_SDCC_DEPENDENCY) + +$(OBJECTDIR)/%.rel: %.cS + cp $< $(OBJECTDIR)/$*.c + $(CC) $(CFLAGS) -E $(OBJECTDIR)/$*.c > $(OBJECTDIR)/tmp + perl -pe "s/^#(.*)/;$$1/" $(OBJECTDIR)/tmp > $(OBJECTDIR)/$*.S + $(AS) $(ASFLAGS) -o $@ $(OBJECTDIR)/$*.S + rm -f $(OBJECTDIR)/tmp + +contiki-$(TARGET).lib: $(CONTIKI_OBJECTFILES) $(PROJECT_OBJECTFILES) \ + $(CONTIKI_ASMOBJECTFILES) $(CONTIKI_CASMOBJECTFILES) + rm -f $@ + for target in $^; do echo $$target >> $@; done + +.PRECIOUS: %.$(TARGET) %.hex + +# build app/example local object files. We need a separate rule so that we can +# pass -DAUTOSTART_ENABLE for those files only +$(OBJECTDIR)/%.app.rel: %.c $(SEGMENT_RULES) + $(CC) $(call c_seg,$<,$@) -DAUTOSTART_ENABLE $(CFLAGS) -c $< -o $@ + +# .ihx is the sdcc binary output file +ifeq ($(HAVE_BANKING),1) +### Build bankable firmware +%.ihx: $(OBJECTDIR)/%.app.rel $(CONTIKI_TARGET_MAIN) contiki-$(TARGET).lib + @echo "\nFirst Link" + @echo "===============" + $(CC) $(LDFLAGS) $(LD_PRE_FLAGS) -o $@ $(CONTIKI_TARGET_MAIN) $(OBJECTDIR)/$*.app.rel -llibsdcc.lib -lcontiki-$(TARGET).lib > /dev/null + +%.flags: %.ihx +### Allocate modules to banks and relocate object files + @echo "\nBank Allocation" + @echo "===============" + python $(BANK_ALLOC) $(basename $(@F)) $(SEGMENT_RULES) $(OFFSET_FIRMWARE) + +%.banked-hex: %.flags +### Link again with new bank allocations + @echo "\nFinal Link" + @echo "===============" + $(CC) $(LDFLAGS) $(shell cat $<) -o $@ $(CONTIKI_TARGET_MAIN) $(OBJECTDIR)/$*.app.rel -llibsdcc.lib -lcontiki-$(TARGET).lib > /dev/null + +%.hex: %.banked-hex +### Post-process the hex file for programmers which dislike SDCC output hex format + $(eval BANKS := $(shell egrep '(^BANK[0-9])=' $(@:.hex=.map) | sed -e 's/BANK\([0-9]\).*/\1/' | uniq)) + $(eval FILES := $(addsuffix .hex,$(addprefix bank,$(BANKS)))) + @echo "\nPack hex file" + @echo "===============" + @for bank in $(BANKS); do \ + echo $(SREC_CAT) $(SREC_FLAGS) $(@:.hex=.banked-hex) -intel \ + -crop 0x"$$bank"8000 "0x"$$bank"FFFF" \ + -offset -$$((0x8000 * $$bank + 0x08000)) -o bank"$$bank".hex -intel; \ + $(SREC_CAT) $(SREC_FLAGS) $(@:.hex=.banked-hex) -intel \ + -crop 0x"$$bank"8000 "0x"$$bank"FFFF" \ + -offset -$$((0x8000 * $$bank + 0x08000)) -o bank"$$bank".hex -intel; \ + done + $(SREC_CAT) $(SREC_FLAGS) $(@:.hex=.banked-hex) -intel -crop 0x00000 0x07FFF -o home.ihx -intel + srec_cat home.ihx -intel $(foreach file,$(FILES),$(file) -intel) -o $@ -intel + rm -f home.ihx $(FILES) +else +### Build non-banked firmware +%.ihx: $(OBJECTDIR)/%.app.rel $(CONTIKI_TARGET_MAIN) contiki-$(TARGET).lib + $(CC) $(LDFLAGS) -o $@ $(CONTIKI_TARGET_MAIN) $(OBJECTDIR)/$*.app.rel -llibsdcc.lib -lcontiki-$(TARGET).lib > /dev/null + +%.hex: %.ihx + $(PACKIHX) $< > $@ +endif diff --git a/cpu/cc253x/bank-alloc.py b/cpu/cc253x/bank-alloc.py new file mode 100644 index 000000000..f2d264538 --- /dev/null +++ b/cpu/cc253x/bank-alloc.py @@ -0,0 +1,245 @@ +#!/usr/bin/env python + +# Copyright (c) 2010, Loughborough University - Computer Science +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the Institute nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# This file is part of the Contiki operating system. + +# \file +# Automatic allocation of modules to code segments for bankable builds +# with SDCC's huge memory model. +# +# \author +# George Oikonomou - +import sys +import re +import operator +import fileinput +import os + +# Open a module object file (.rel) and read it's code size +def retrieve_module_size(file_name): + size_pat = re.compile('^A\s+(?:HOME|BANK[0-9])\s+size\s+([1-9A-F][0-9A-F]*)') + for code_line in open(file_name): + matches = size_pat.search(code_line) + if matches is not None: + return int(matches.group(1), 16) + return 0 + +# Searches for a code segment rule for file_name in the segment_rules file +# If there is a rule, we respect it. Otherwise, we can move the file around +def get_source_seg(source_file, object_file, segment_rules): + for line in open(segment_rules): + tokens = line.split(None) + match = re.search(tokens[1], source_file) + if match is not None: + # Save it in basename.seg + base, ext = os.path.splitext(object_file) + of = open(base + '.seg', 'w') + of.write(tokens[0] + '\n') + of.close + return tokens[0] + return None + +# If segment.rules specified a rule for a source file, the respective object +# file's banking requirement will be stored in object_file.seg +def get_object_seg(object_file): + base, ext = os.path.splitext(object_file) + seg = base + '.seg' + bank = None + if os.path.isfile(seg) is True: + of = open(base + '.seg', 'r') + bank = of.readline().strip() + of.close() + return bank + +# Open project.mem and retreive the project's total code footprint +def get_total_size(project): + mem_file = project + '.mem' + pat = re.compile('FLASH\s+(0x[0-9a-f]+\s+){2}([0-9]+)') + for line in open(mem_file): + l = pat.search(line) + if l is not None: + return int(l.group(2)) + +# Open project.map and retrieve the list of modules linked in +# This will only consider contiki sources, not SDCC libraries +# NB: Sometimes object filenames get truncated: +# contiki-sensinode.lib [ obj_sensinode/watchdog-cc2430.re ] +# See how for this file the 'l' in 'rel' is missing. For that reason, we retrieve +# the filaname until the last '.' but without the extension and we append 'rel' +# As long as the filename doesn't get truncated, we're good +def populate(project, modules, segment_rules, bins): + bankable_total = 0 + user_total = 0 + + map_file = project + '.map' + file_pat = re.compile('obj_cc2530dk[^ ]+\.') + for line in open(map_file): + file_name = file_pat.search(line) + if file_name is not None: + mod = file_name.group(0) + 'rel' + code_size = retrieve_module_size(mod) + seg = get_object_seg(mod) + if seg is not None: + # This module has been assigned to a bank by the user + #print 'In', seg, file_name.group(0), 'size', code_size + bins[seg][0] += code_size + user_total += code_size + else: + # We are free to allocate this module + modules.append([mod, code_size, "NONE"]) + bankable_total += code_size + return bankable_total, user_total + +# Allocate bankable modules to banks according to a simple +# 'first fit, decreasing' bin packing heuristic. +def bin_pack(modules, bins, offset, log): + if offset==1: + bins['HOME'][1] -= 4096 + + # Sort by size, descending, in=place + modules.sort(key=operator.itemgetter(1), reverse=True) + + for module in modules: + # We want to iterate in a specific order and dict.keys() won't do that + for bin_id in ['HOME', 'BANK1', 'BANK2', 'BANK3', 'BANK4', 'BANK5', 'BANK6', 'BANK7']: + if bins[bin_id][0] + module[1] < bins[bin_id][1]: + bins[bin_id][0] += module[1] + module[2] = bin_id + log.writelines(' '.join([module[2].ljust(8), \ + str(module[1]).rjust(5), module[0], '\n'])) + break + else: + if bin_id == 'BANK7': + print "Failed to allocate", module[0], "with size", module[1], \ + "to a code bank. This is fatal" + return 1 + return 0 + +# Hack the new bank directly in the .rel file +def relocate(module, bank): + code_pat = re.compile('(A\s+)(?:HOME|BANK[0-9])(\s+size\s+[1-9A-F][0-9A-F]*.+\n)') + + for line in fileinput.input(module, inplace=1): + m = code_pat.search(line) + if m is not None: + line = m.group(1) + bank + m.group(2) + sys.stdout.write(line) + return + +if len(sys.argv) < 3: + print 'Usage:' + print 'bank-alloc.py project path_to_segment_rules [offset]' + print 'bank-alloc.py source_file path_to_segment_rules object_file' + sys.exit(1) + +modules = list() +file_name = sys.argv[1] +segment_rules = sys.argv[2] + +# Magic: Guess whether we want to determine the code bank for a code file +# or whether we want to bin-pack +basename, ext = os.path.splitext(file_name) +if ext == '.c': + # Code Segment determination + if len(sys.argv) < 4: + print 'Usage:' + print 'bank-alloc.py project path_to_segment_rules [offset]' + print 'bank-alloc.py source_file path_to_segment_rules object_file' + sys.exit(1) + object_file = sys.argv[3] + seg = get_source_seg(file_name, object_file, segment_rules) + if seg is None: + print "BANK1" + else: + print seg + exit() + +# Bin-Packing +offset = 0 +if len(sys.argv) > 3 and sys.argv[3] is not None: + offset = int(sys.argv[3]) + +sizes = {'total': 0, 'bankable': 0, 'user': 0, 'libs': 0} + +# Name : [Allocated, capacity, start_addr] +bins = { + 'HOME': [0, 32768, '0x000000'], + 'BANK1': [0, 32768, '0x018000'], + 'BANK2': [0, 32768, '0x028000'], + 'BANK3': [0, 32768, '0x038000'], + 'BANK4': [0, 32768, '0x048000'], + 'BANK5': [0, 32768, '0x058000'], + 'BANK6': [0, 32768, '0x068000'], + 'BANK7': [0, 32768, '0x078000'], +} + +sizes['total'] = get_total_size(basename) +sizes['bankable'], sizes['user'] = populate(basename, modules, segment_rules, bins) +sizes['libs'] = sizes['total'] - sizes['bankable'] - sizes['user'] + +print 'Total Size =', sizes['total'], 'bytes (' + \ + str(sizes['bankable']), 'bankable,', \ + str(sizes['user']), 'user-allocated,', \ + str(sizes['libs']), 'const+libs)' + +bins['HOME'][0] += sizes['libs'] + +print 'Preallocations: HOME=' + str(bins['HOME'][0]), +for bin_id in ['BANK1', 'BANK2', 'BANK3', 'BANK4', 'BANK5', 'BANK6', 'BANK7']: + if bins[bin_id][0] > 0: + print ", " + bin_id + "=" + str(bins[bin_id][0]), +print + +# Open a log file +of = open(basename + '.banks', 'w') +pack = bin_pack(modules, bins, offset, of) +of.close() + +print "Bin-Packing results (target allocation):" +print "Segment - max - alloc" +for bin_id in ['HOME', 'BANK1', 'BANK2', 'BANK3', 'BANK4', 'BANK5', 'BANK6', 'BANK7']: + if bins[bin_id][0] > 0: + print bin_id.rjust(7), str(bins[bin_id][1]).rjust(6), str(bins[bin_id][0]).rjust(6) + +if pack > 0: + sys.exit(1) + +# If we reach here we seem to have a sane allocation. Start changing .rel files +for module in modules: + relocate(module[0], module[2]) + +flags = "" +# Export LD_POST_FLAGS +for bin_id in ['BANK1', 'BANK2', 'BANK3', 'BANK4', 'BANK5', 'BANK6', 'BANK7']: + if bins[bin_id][0] > 0: + flags += "-Wl-b" + bin_id + "=" + bins[bin_id][2] + " " +# Write LD_POST_FLAGS in project.flags +of = open(basename + '.flags', 'w') +of.write(flags + '\n') +of.close() diff --git a/cpu/cc253x/cc253x.h b/cpu/cc253x/cc253x.h new file mode 100644 index 000000000..27c022eec --- /dev/null +++ b/cpu/cc253x/cc253x.h @@ -0,0 +1,669 @@ +/* + * Copyright (c) 2011, George Oikonomou - + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * Definitions for TI/Chipcon cc2530, cc2531 and cc2533 SFR registers. + * + * Based on information in: + * "CC253x System-on-Chip Solution for 2.4-GHz IEEE 802.15.4 and ZigBee® + * Applications" + * Literature Number: SWRU191B. April 2009–Revised September 2010 + * + * \author + * George Oikonomou - + */ + +#ifndef __CC253X_H__ +#define __CC253X_H__ + +/*---------------------------------------------------------------------------*/ +/* Compiler Abstraction */ +#include +/*--------------------------------------------------------------------------- + * Interrupt Vectors + * (Table 2.5, page 40) + *---------------------------------------------------------------------------*/ +#define RFERR_VECTOR 0 /* RF TXFIFO underflow and RXFIFO overflow. */ +#define ADC_VECTOR 1 /* ADC end of conversion */ +#define URX0_VECTOR 2 /* USART 0 RX complete */ +#define URX1_VECTOR 3 /* USART 1 RX complete */ +#define ENC_VECTOR 4 /* AES encryption/decryption complete */ +#define ST_VECTOR 5 /* Sleep Timer compare */ +#define P2INT_VECTOR 6 /* Port 2 inputs/USB/I2C */ +#define UTX0_VECTOR 7 /* USART 0 TX complete */ +#define DMA_VECTOR 8 /* DMA transfer complete */ +#define T1_VECTOR 9 /* Timer 1 (16-bit) capture/compare/overflow */ +#define T2_VECTOR 10 /* Timer 2 (MAC Timer) */ +#define T3_VECTOR 11 /* Timer 3 (8-bit) compare/overflow */ +#define T4_VECTOR 12 /* Timer 4 (8-bit) compare/overflow */ +#define P0INT_VECTOR 13 /* Port 0 inputs */ +#define UTX1_VECTOR 14 /* USART1 TX complete */ +#define P1INT_VECTOR 15 /* Port 1 inputs */ +#define RF_VECTOR 16 /* RF general interrupts */ +#define WDT_VECTOR 17 /* Watchdog overflow in timer mode */ +/*--------------------------------------------------------------------------- + * Special Function Registers and BITs + * (Table 2.1, page 27) + *---------------------------------------------------------------------------*/ +/* 8051 Internals */ +SFR(P0, 0x80); /* Port 0 */ + SBIT(P0_7, 0x80, 7); /* Port 0 bit 7 */ + SBIT(P0_6, 0x80, 6); /* Port 0 bit 6 */ + SBIT(P0_5, 0x80, 5); /* Port 0 bit 5 */ + SBIT(P0_4, 0x80, 4); /* Port 0 bit 4 */ + SBIT(P0_3, 0x80, 3); /* Port 0 bit 3 */ + SBIT(P0_2, 0x80, 2); /* Port 0 bit 2 */ + SBIT(P0_1, 0x80, 1); /* Port 0 bit 1 */ + SBIT(P0_0, 0x80, 0); /* Port 0 bit 0 */ +SFR(SP, 0x81); /* Stack pointer */ +SFR(DPL0, 0x82); /* Data pointer 0 low byte */ +SFR(DPH0, 0x83); /* Data pointer 0 high byte */ +SFR(DPL1, 0x84); /* Data pointer 1 low byte */ +SFR(DPH1, 0x85); /* Data pointer 1 high byte */ +SFR(PCON, 0x87); /* Power mode control */ +SFR(TCON, 0x88); /* Interrupt flags */ + SBIT(URX1IF, 0x88, 7); /* USART1 RX interrupt flag */ + SBIT(ADCIF, 0x88, 5); /* ADC interrupt flag */ + SBIT(URX0IF, 0x88, 3); /* USART0 RX interrupt flag */ + SBIT(IT1, 0x88, 2); /* Reserved. Must always be set to 1 */ + SBIT(RFERRIF, 0x88, 1); /* RF TXFIFO/RXFIFO interrupt flag */ + SBIT(IT0, 0x88, 0); /* Reserved. Must always be set to 1 */ +SFR(P1, 0x90); /* Port 1 */ + SBIT(P1_7, 0x90, 7); /* Port 1 bit 7 */ + SBIT(P1_6, 0x90, 6); /* Port 1 bit 6 */ + SBIT(P1_5, 0x90, 5); /* Port 1 bit 5 */ + SBIT(P1_4, 0x90, 4); /* Port 1 bit 4 */ + SBIT(P1_3, 0x90, 3); /* Port 1 bit 3 */ + SBIT(P1_2, 0x90, 2); /* Port 1 bit 2 */ + SBIT(P1_1, 0x90, 1); /* Port 1 bit 1 */ + SBIT(P1_0, 0x90, 0); /* Port 1 bit 0 */ +SFR(DPS, 0x92); /* Data pointer select */ +SFR(S0CON, 0x98); /* Interrupt flags 2 */ + SBIT(ENCIF_1, 0x98, 1); /* AES Interrupt flag 1 */ + SBIT(ENCIF_0, 0x98, 0); /* AES Interrupt flag 0 */ +SFR(IEN2, 0x9A); /* Interrupt enable 2 */ +SFR(S1CON, 0x9B); /* Interrupt flags 3 */ +SFR(P2, 0xA0); /* Port 2 */ + SBIT(P2_7, 0xA0, 7); /* Port 2 bit 7 */ + SBIT(P2_6, 0xA0, 6); /* Port 2 bit 6 */ + SBIT(P2_5, 0xA0, 5); /* Port 2 bit 5 */ + SBIT(P2_4, 0xA0, 4); /* Port 2 bit 4 */ + SBIT(P2_3, 0xA0, 3); /* Port 2 bit 3 */ + SBIT(P2_2, 0xA0, 2); /* Port 2 bit 2 */ + SBIT(P2_1, 0xA0, 1); /* Port 2 bit 1 */ + SBIT(P2_0, 0xA0, 0); /* Port 2 bit 0 */ +SFR(IEN0, 0xA8); /* Interrupt enable 0 */ + SBIT(EA, 0xA8, 7); /* All interrupts - enable/disable */ + SBIT(STIE, 0xA8, 5); /* Sleep Timer interrupt enable */ + SBIT(ENCIE, 0xA8, 4); /* AES encryption/decryption interrupt enable */ + SBIT(URX1IE, 0xA8, 3); /* USART1 RX interrupt enable */ + SBIT(URX0IE, 0xA8, 2); /* USART0 RX interrupt enable */ + SBIT(ADCIE, 0xA8, 1); /* ADC interrupt enable */ + SBIT(RFERRIE, 0xA8, 0); /* RF TXFIFO/RXFIFO interrupt enable */ +SFR(IP0, 0xA9); /* Interrupt priority 0 */ +SFR(IEN1, 0xB8); /* Interrupt enable 1 */ + SBIT(P0IE, 0xB8, 5); /* Port 0 interrupt enable */ + SBIT(T4IE, 0xB8, 4); /* Timer 4 interrupt enable */ + SBIT(T3IE, 0xB8, 3); /* Timer 3 interrupt enable */ + SBIT(T2IE, 0xB8, 2); /* Timer 2 interrupt enable */ + SBIT(T1IE, 0xB8, 1); /* Timer 1 interrupt enable */ + SBIT(DMAIE, 0xB8, 0); /* DMA Transfer interrupt enable */ +SFR(IP1, 0xB9); /* Interrupt priority 1 */ +SFR(IRCON, 0xC0); /* Interrupt flags 4 */ + SBIT(STIF, 0xC0, 7); /* Sleep Timer interrupt flag */ + SBIT(P0IF, 0xC0, 5); /* Port 0 interrupt flag */ + SBIT(T4IF, 0xC0, 4); /* Timer 4 interrupt flag */ + SBIT(T3IF, 0xC0, 3); /* Timer 3 interrupt flag */ + SBIT(T2IF, 0xC0, 2); /* Timer 2 interrupt flag */ + SBIT(T1IF, 0xC0, 1); /* Timer 1 interrupt flag */ + SBIT(DMAIF, 0xC0, 0); /* DMA-complete interrupt flag */ +SFR(PSW, 0xD0); /* Program status word */ + SBIT(CY, 0xD0, 7); /* Carry flag */ + SBIT(AC, 0xD0, 6); /* Auxiliary carry flag */ + SBIT(F0, 0xD0, 5); /* User-defined flag 1, bit addressable */ + SBIT(RS1, 0xD0, 4); /* Register bank select, bit 1 */ + SBIT(RS0, 0xD0, 3); /* Register bank select, bit 0 */ + SBIT(OV, 0xD0, 2); /* Overflow flag */ + SBIT(F1, 0xD0, 1); /* User-defined flag 0, bit addressable */ + SBIT(P, 0xD0, 0); /* Parity flag */ +SFR(ACC, 0xE0); /* Accumulator */ + SBIT(ACC_7, 0xE0, 7); /* Accumulator bit 7 */ + SBIT(ACC_6, 0xE0, 6); /* Accumulator bit 6 */ + SBIT(ACC_5, 0xE0, 5); /* Accumulator bit 5 */ + SBIT(ACC_4, 0xE0, 4); /* Accumulator bit 4 */ + SBIT(ACC_3, 0xE0, 3); /* Accumulator bit 3 */ + SBIT(ACC_2, 0xE0, 2); /* Accumulator bit 2 */ + SBIT(ACC_1, 0xE0, 1); /* Accumulator bit 1 */ + SBIT(ACC_0, 0xE0, 0); /* Accumulator bit 0 */ +SFR(IRCON2, 0xE8); /* Interrupt flags 5 */ + SBIT(WDTIF, 0xE8, 4); /* Watchdog Timer interrupt flag */ + SBIT(P1IF, 0xE8, 3); /* Port 1 Interrupt flag */ + SBIT(UTX1IF, 0xE8, 2); /* USART1 TX interrupt flag */ + SBIT(UTX0IF, 0xE8, 1); /* USART0 TX interrupt flag */ + SBIT(P2IF, 0xE8, 0); /* Port 2 interrupt flag */ +SFR(B, 0xF0); /* B Register */ + SBIT(B_7, 0xF0, 7); /* Register B bit 7 */ + SBIT(B_6, 0xF0, 6); /* Register B bit 6 */ + SBIT(B_5, 0xF0, 5); /* Register B bit 5 */ + SBIT(B_4, 0xF0, 4); /* Register B bit 4 */ + SBIT(B_3, 0xF0, 3); /* Register B bit 3 */ + SBIT(B_2, 0xF0, 2); /* Register B bit 2 */ + SBIT(B_1, 0xF0, 1); /* Register B bit 1 */ + SBIT(B_0, 0xF0, 0); /* Register B bit 0 */ + +/* ADC */ +SFR(ADCCON1, 0xB4); /* ADC control 1 */ +SFR(ADCCON2, 0xB5); /* ADC control 2 */ +SFR(ADCCON3, 0xB6); /* ADC control 3 */ +SFR(ADCL, 0xBA); /* ADC data low */ +SFR(ADCH, 0xBB); /* ADC data high */ +SFR(RNDL, 0xBC); /* Random number generator data low */ +SFR(RNDH, 0xBD); /* Random number generator data high */ + +/* AES Coprocessor */ +SFR(ENCDI, 0xB1); /* Encryption/decryption input data */ +SFR(ENCDO, 0xB2); /* Encryption/decryption output data */ +SFR(ENCCS, 0xB3); /* Encryption/decryption control and status */ + +/* DMA Controller */ +SFR(DMAIRQ, 0xD1); /* DMA interrupt flag */ +SFR(DMA1CFGL, 0xD2); /* DMA channel 1–4 configuration address low */ +SFR(DMA1CFGH, 0xD3); /* DMA channel 1–4 configuration address high */ +SFR(DMA0CFGL, 0xD4); /* DMA channel 0 configuration address low */ +SFR(DMA0CFGH, 0xD5); /* DMA channel 0 configuration address high */ +SFR(DMAARM, 0xD6); /* DMA channel armed */ +SFR(DMAREQ, 0xD7); /* DMA channel start request and status */ + +/* I/O */ +SFR(P0IFG, 0x89); /* Port 0 interrupt status flag */ +SFR(P1IFG, 0x8A); /* Port 1 interrupt status flag */ +SFR(P2IFG, 0x8B); /* Port 2 interrupt status flag */ +SFR(PICTL, 0x8C); /* Port pins interrupt mask and edge */ +SFR(P0IEN, 0xAB); /* Port 0 interrupt mask */ +SFR(P1IEN, 0x8D); /* Port 1 interrupt mask */ +SFR(P2IEN, 0xAC); /* Port 2 interrupt mask */ +SFR(P0INP, 0x8F); /* Port 0 input Mode */ +SFR(PERCFG, 0xF1); /* Peripheral I/O control */ +SFR(APCFG, 0xF2); /* Analog peripheral I/O configuration */ +SFR(P0SEL, 0xF3); /* Port 0 function select */ +SFR(P1SEL, 0xF4); /* Port 1 function select */ +SFR(P2SEL, 0xF5); /* Port 2 function select */ +SFR(P1INP, 0xF6); /* Port 1 input mode */ +SFR(P2INP, 0xF7); /* Port 2 input mode */ +SFR(P0DIR, 0xFD); /* Port 0 direction */ +SFR(P1DIR, 0xFE); /* Port 1 direction */ +SFR(P2DIR, 0xFF); /* Port 2 direction */ +SFR(PMUX, 0xAE); /* Power-down signal mux */ + +/* Memory */ +SFR(MPAGE, 0x93); /* Memory page select */ +SFR(_XPAGE, 0x93); /* Memory page select - SDCC name */ +SFR(MEMCTR, 0xC7); /* Memory system control */ +SFR(FMAP, 0x9F); /* Flash-memory bank mapping */ +SFR(PSBANK, 0x9F); /* Flash-memory bank mapping - SDCC name */ + +/* RF */ +SFR(RFIRQF1, 0x91); /* RF interrupt flags MSB */ +SFR(RFD, 0xD9); /* RF data */ +SFR(RFST, 0xE1); /* RF command strobe */ +SFR(RFIRQF0, 0xE9); /* RF interrupt flags LSB */ +SFR(RFERRF, 0xBF); /* RF error interrupt flags */ + +/* Sleep Timer */ +SFR(ST0, 0x95); /* Sleep Timer 0 */ +SFR(ST1, 0x96); /* Sleep Timer 1 */ +SFR(ST2, 0x97); /* Sleep Timer 2 */ +SFR(STLOAD, 0xAD); /* Sleep-timer load status */ +SFR(SLEEPCMD, 0xBE); /* Sleep-mode control command */ +SFR(SLEEPSTA, 0x9D); /* Sleep-mode control status */ + +/* Power Management and Clocks */ +SFR(CLKCONCMD, 0xC6); /* Clock control command */ +SFR(CLKCONSTA, 0x9E); /* Clock control status */ + +/* Timer 1 */ +SFR(T1CC0L, 0xDA); /* Timer 1 channel 0 capture/compare value low */ +SFR(T1CC0H, 0xDB); /* Timer 1 channel 0 capture/compare value high */ +SFR(T1CC1L, 0xDC); /* Timer 1 channel 1 capture/compare value low */ +SFR(T1CC1H, 0xDD); /* Timer 1 channel 1 capture/compare value high */ +SFR(T1CC2L, 0xDE); /* Timer 1 channel 2 capture/compare value low */ +SFR(T1CC2H, 0xDF); /* Timer 1 channel 2 capture/compare value high */ +SFR(T1CNTL, 0xE2); /* Timer 1 counter low */ +SFR(T1CNTH, 0xE3); /* Timer 1 counter high */ +SFR(T1CTL, 0xE4); /* Timer 1 control and status */ +SFR(T1CCTL0, 0xE5); /* Timer 1 channel 0 capture/compare control */ +SFR(T1CCTL1, 0xE6); /* Timer 1 channel 1 capture/compare control */ +SFR(T1CCTL2, 0xE7); /* Timer 1 channel 2 capture/compare control */ +SFR(T1STAT, 0xAF); /* Timer 1 status */ + +/* Timer 2 (MAC Timer) */ +SFR(T2CTRL, 0x94); /* Timer 2 control */ +SFR(T2EVTCFG, 0x9C); /* Timer 2 event configuration */ +SFR(T2IRQF, 0xA1); /* Timer 2 interrupt flags */ +SFR(T2M0, 0xA2); /* Timer 2 multiplexed register 0 */ +SFR(T2M1, 0xA3); /* Timer 2 multiplexed register 1 */ +SFR(T2MOVF0, 0xA4); /* Timer 2 multiplexed overflow register 0 */ +SFR(T2MOVF1, 0xA5); /* Timer 2 multiplexed overflow register 1 */ +SFR(T2MOVF2, 0xA6); /* Timer 2 multiplexed overflow register 2 */ +SFR(T2IRQM, 0xA7); /* Timer 2 interrupt mask */ +SFR(T2MSEL, 0xC3); /* Timer 2 multiplex select */ + +/* Timer 3 */ +SFR(T3CNT, 0xCA); /* Timer 3 counter */ +SFR(T3CTL, 0xCB); /* Timer 3 control */ +SFR(T3CCTL0, 0xCC); /* Timer 3 channel 0 compare control */ +SFR(T3CC0, 0xCD); /* Timer 3 channel 0 compare value */ +SFR(T3CCTL1, 0xCE); /* Timer 3 channel 1 compare control */ +SFR(T3CC1, 0xCF); /* Timer 3 channel 1 compare value */ + +/* Timer 4 */ +SFR(T4CNT, 0xEA); /* Timer 4 counter */ +SFR(T4CTL, 0xEB); /* Timer 4 control */ +SFR(T4CCTL0, 0xEC); /* Timer 4 channel 0 compare control */ +SFR(T4CC0, 0xED); /* Timer 4 channel 0 compare value */ +SFR(T4CCTL1, 0xEE); /* Timer 4 channel 1 compare control */ +SFR(T4CC1, 0xEF); /* Timer 4 channel 1 compare value */ + +/* Timer 1, 3, 4 join Interrupts */ +SFR(TIMIF, 0xD8); /* Timers 1/3/4 joint interrupt mask/flags */ + SBIT(OVFIM, 0xD8, 6); /* Timer 1 overflow interrupt mask */ + SBIT(T4CH1IF, 0xD8, 5); /* Timer 4 channel 1 interrupt flag */ + SBIT(T4CH0IF, 0xD8, 4); /* Timer 4 channel 0 interrupt flag */ + SBIT(T4OVFIF, 0xD8, 3); /* Timer 4 overflow interrupt flag */ + SBIT(T3CH1IF, 0xD8, 2); /* Timer 3 channel 1 interrupt flag */ + SBIT(T3CH0IF, 0xD8, 1); /* Timer 3 channel 0 interrupt flag */ + SBIT(T3OVFIF, 0xD8, 0); /* Timer 3 overflow interrupt flag */ + +/* USART 0 */ +SFR(U0CSR, 0x86); /* USART 0 control and status */ +SFR(U0DBUF, 0xC1); /* USART 0 receive/transmit data buffer */ +SFR(U0BAUD, 0xC2); /* USART 0 baud-rate control */ +SFR(U0UCR, 0xC4); /* USART 0 UART control */ +SFR(U0GCR, 0xC5); /* USART 0 generic control */ + +/* USART 1 */ +SFR(U1CSR, 0xF8); /* USART 1 control and status */ + SBIT(MODE, 0xF8, 7); /* USART mode select */ + SBIT(RE, 0xF8, 6); /* UART receiver enable */ + SBIT(SLAVE, 0xF8, 5); /* SPI master- or slave mode select */ + SBIT(FE, 0xF8, 4); /* UART framing error status */ + SBIT(ERR, 0xF8, 3); /* UART parity error status */ + SBIT(RX_BYTE, 0xF8, 2); /* Receive byte status */ + SBIT(TX_BYTE, 0xF8, 1); /* Transmit byte status */ + SBIT(ACTIVE, 0xF8, 0); /* USART transmit/receive active status */ +SFR(U1DBUF, 0xF9); /* USART 1 receive/transmit data buffer */ +SFR(U1BAUD, 0xFA); /* USART 1 baud-rate control */ +SFR(U1UCR, 0xFB); /* USART 1 UART control */ +SFR(U1GCR, 0xFC); /* USART 1 Generic control */ + +/* Watchdog Timer */ +SFR(WDCTL, 0xC9); /* Watchdog Timer Control */ +/*--------------------------------------------------------------------------- + * XREG Registers (0x6000–0x63FF), excluding RF and USB registers + * (Table 2.2, page 31) + *---------------------------------------------------------------------------*/ +SFRX(MONMUX , 0x61A6); /* Operational amplifier mode control (cc2530/31) */ +SFRX(OPAMPMC, 0x61A6); /* Battery monitor MUX (cc2533) */ +/* I2C registers - cc2533 only */ +SFRX(I2CCFG, 0x6230); /* I2C control */ +SFRX(I2CSTAT, 0x6231); /* I2C status */ +SFRX(I2CDATA, 0x6232); /* I2C data */ +SFRX(I2CADDR, 0x6233); /* I2C own slave address */ +SFRX(I2CWC, 0x6234); /* Wrapper Control */ +SFRX(I2CIO, 0x6235); /* GPIO */ +/* End I2C registers */ +SFRX(OBSSEL0, 0x6243); /* Observation output control - register 0 */ +SFRX(OBSSEL1, 0x6244); /* Observation output control - register 1 */ +SFRX(OBSSEL2, 0x6245); /* Observation output control - register 2 */ +SFRX(OBSSEL3, 0x6246); /* Observation output control - register 3 */ +SFRX(OBSSEL4, 0x6247); /* Observation output control - register 4 */ +SFRX(OBSSEL5, 0x6248); /* Observation output control - register 5 */ +SFRX(CHVER, 0x6249); /* Chip version */ +SFRX(CHIPID, 0x624A); /* Chip identification */ +SFRX(TR0, 0x624B); /* Test register 0 */ +SFRX(DBGDATA, 0x6260); /* Debug interface write data */ +SFRX(SRCRC, 0x6262); /* Sleep reset CRC */ +SFRX(BATTMON, 0x6264); /* Battery monitor */ +SFRX(IVCTRL, 0x6265); /* Analog control register */ +SFRX(FCTL, 0x6270); /* Flash control */ +SFRX(FADDRL, 0x6271); /* Flash address low */ +SFRX(FADDRH, 0x6272); /* Flash address high */ +SFRX(FWDATA, 0x6273); /* Flash write data */ +SFRX(CHIPINFO0, 0x6276); /* Chip information byte 0 */ +SFRX(CHIPINFO1, 0x6277); /* Chip information byte 1 */ +SFRX(IRCTL, 0x6281); /* Timer 1 IR generation control */ +SFRX(CLD, 0x6290); /* Clock-loss detection */ +SFRX(XX_T1CCTL0, 0x62A0); /* Timer 1 channel 0 capture/compare control (additional XREG mapping of SFR) */ +SFRX(XX_T1CCTL1, 0x62A1); /* Timer 1 channel 1 capture/compare control (additional XREG mapping of SFR register) */ +SFRX(XX_T1CCTL2, 0x62A2); /* Timer 1 channel 2 capture/compare control (additional XREG mapping of SFR register) */ +SFRX(T1CCTL3, 0x62A3); /* Timer 1 channel 3 capture/compare control */ +SFRX(T1CCTL4, 0x62A4); /* Timer 1 channel 4 capture/compare control */ +SFRX(XX_T1CC0L, 0x62A6); /* Timer 1 channel 0 capture/compare value low (additional XREG mapping of SFR register) */ +SFRX(XX_T1CC0H, 0x62A7); /* Timer 1 channel 0 capture/compare value high (additional XREG mapping of SFR register) */ +SFRX(XX_T1CC1L, 0x62A8); /* Timer 1 channel 1 capture/compare value low (additional XREG mapping of SFR register) */ +SFRX(XX_T1CC1H, 0x62A9); /* Timer 1 channel 1 capture/compare value high (additional XREG mapping of SFR register) */ +SFRX(XX_T1CC2L, 0x62AA); /* Timer 1 channel 2 capture/compare value low (additional XREG mapping of SFR register) */ +SFRX(XX_T1CC2H, 0x62AB); /* Timer 1 channel 2 capture/compare value high (additional XREG mapping of SFR register) */ +SFRX(T1CC3L, 0x62AC); /* Timer 1 channel 3 capture/compare value low */ +SFRX(T1CC3H, 0x62AD); /* Timer 1 channel 3 capture/compare value high */ +SFRX(T1CC4L, 0x62AE); /* Timer 1 channel 4 capture/compare value low */ +SFRX(T1CC4H, 0x62AF); /* Timer 1 channel 4 capture/compare value high */ +SFRX(STCC, 0x62B0); /* Sleep Timer capture control */ +SFRX(STCS, 0x62B1); /* Sleep Timer capture status */ +SFRX(STCV0, 0x62B2); /* Sleep Timer capture value byte 0 */ +SFRX(STCV1, 0x62B3); /* Sleep Timer capture value byte 1 */ +SFRX(STCV2, 0x62B4); /* Sleep Timer capture value byte 2 */ +SFRX(OPAMPC, 0x62C0); /* Operational amplifier control */ +SFRX(OPAMPS, 0x62C1); /* Operational amplifier status */ +SFRX(CMPCTL, 0x62D0); /* Analog comparator control and status */ +/*--------------------------------------------------------------------------- + * Radio Registers + * (Sec. 23, page 211) + *---------------------------------------------------------------------------*/ +SFRX(RFCORE_RAM, 0x6000); /* RF Core Memory Map (0x6000 to 0x0617F) */ +SFRX(RXFIFO, 0x6000); /* TXFIFO Direct Access (0x6000 to 0x607F) */ +SFRX(TXFIFO, 0x6080); /* TXFIFO Direct Access (0x6080 to 0x60FF) */ + +SFRX(SRC_ADDR_TABLE, 0x6100); /* Source Address Table Start */ + +/* Source Address Matching Result */ +SFRX(SRCRESMASK0, 0x6160); /* Extended address matching */ +SFRX(SRCRESMASK1, 0x6161); /* Short address matching */ +SFRX(SRCRESMASK2, 0x6162); /* Source address match - 24-bit mask */ +SFRX(SRCRESINDEX, 0x6163); /* Bit index of least-significant 1 in SRCRESMASK */ + +/* Source Address Matching Control */ +SFRX(SRCEXTPENDEN0, 0x6164); /* Ext. Address bit-mask 0 (LSB) */ +SFRX(SRCEXTPENDEN1, 0x6165); /* Ext. Address bit-mask 1 */ +SFRX(SRCEXTPENDEN2, 0x6166); /* Ext. Address bit-mask 2 (MSB) */ +SFRX(SRCSHORTPENDEN0, 0x6167); /* Short Address bit-mask 0 (LSB) */ +SFRX(SRCSHORTPENDEN1, 0x6168); /* Short Address bit-mask 1 */ +SFRX(SRCSHORTPENDEN2, 0x6169); /* Short Address bit-mask 2 (MSB) */ + +/* Local Address Information (used during destination address filtering) */ +SFRX(EXT_ADDR0, 0x616A); /* IEEE extended address 0 */ +SFRX(EXT_ADDR1, 0x616B); /* IEEE extended address 1 */ +SFRX(EXT_ADDR2, 0x616C); /* IEEE extended address 2 */ +SFRX(EXT_ADDR3, 0x616D); /* IEEE extended address 3 */ +SFRX(EXT_ADDR4, 0x616E); /* IEEE extended address 4 */ +SFRX(EXT_ADDR5, 0x616F); /* IEEE extended address 5 */ +SFRX(EXT_ADDR6, 0x6170); /* IEEE extended address 6 */ +SFRX(EXT_ADDR7, 0x6171); /* IEEE extended address 7 */ +SFRX(PAN_ID0, 0x6172); /* PAN ID 0 */ +SFRX(PAN_ID1, 0x6173); /* PAN ID 1 */ +SFRX(SHORT_ADDR0, 0x6174); /* Short Address 0 */ +SFRX(SHORT_ADDR1, 0x6175); /* Short Address 1 */ + +SFRX(FRMFILT0, 0x6180); /* Frame Filtering 0 */ +SFRX(FRMFILT1, 0x6181); /* Frame Filtering 1 */ +SFRX(SRCMATCH, 0x6182); /* Source Address Matching and Pending Bits */ +SFRX(SRCSHORTEN0, 0x6183); /* Short Address Matching 0 */ +SFRX(SRCSHORTEN1, 0x6184); /* Short Address Matching 1 */ +SFRX(SRCSHORTEN2, 0x6185); /* Short Address Matching 2 */ +SFRX(SRCEXTEN0, 0x6186); /* Extended Address Matching 0 */ +SFRX(SRCEXTEN1, 0x6187); /* Extended Address Matching 1 */ +SFRX(SRCEXTEN2, 0x6188); /* Extended Address Matching 2 */ +SFRX(FRMCTRL0, 0x6189); /* Frame Handling */ +SFRX(FRMCTRL1, 0x618A); /* Frame Handling */ +SFRX(RXENABLE, 0x618B); /* RX Enabling */ +SFRX(RXMASKSET, 0x618C); /* RX Enabling */ +SFRX(RXMASKCLR, 0x618D); /* RX Disabling */ +SFRX(FREQTUNE, 0x618E); /* Crystal Oscillator Frequency Tuning */ +SFRX(FREQCTRL, 0x618F); /* RF Frequency Control */ +SFRX(TXPOWER, 0x6190); /* Controls the Output Power */ +SFRX(TXCTRL, 0x6191); /* Controls the TX Settings */ +SFRX(FSMSTAT0, 0x6192); /* Radio Status Register */ +SFRX(FSMSTAT1, 0x6193); /* Radio Status Register */ +SFRX(FIFOPCTRL, 0x6194); /* FIFOP Threshold */ +SFRX(FSMCTRL, 0x6195); /* FSM Options */ +SFRX(CCACTRL0, 0x6196); /* CCA Threshold */ +SFRX(CCACTRL1, 0x6197); /* Other CCA Options */ +SFRX(RSSI, 0x6198); /* RSSI Status Register */ +SFRX(RSSISTAT, 0x6199); /* RSSI Valid Status Register */ +SFRX(RXFIRST, 0x619A); /* First Byte in RXFIFO */ +SFRX(RXFIFOCNT, 0x619B); /* Number of Bytes in RXFIFO */ +SFRX(TXFIFOCNT, 0x619C); /* Number of Bytes in TXFIFO */ +SFRX(RXFIRST_PTR, 0x619D); /* RXFIFO Pointer */ +SFRX(RXLAST_PTR, 0x619E); /* RXFIFO Pointer */ +SFRX(RXP1_PTR, 0x619F); /* RXFIFO Pointer */ +SFRX(TXFIRST_PTR, 0x61A1); /* TXFIFO Pointer */ +SFRX(TXLAST_PTR, 0x61A2); /* TXFIFO Pointer */ +SFRX(RFIRQM0, 0x61A3); /* RF Interrupt Masks 0 */ +SFRX(RFIRQM1, 0x61A4); /* RF Interrupt Masks 1 */ +SFRX(RFERRM, 0x61A5); /* RF Error Interrupt Mask */ +SFRX(RFRND, 0x61A7); /* Random Data */ +SFRX(MDMCTRL0, 0x61A8); /* Controls Modem 0 */ +SFRX(MDMCTRL1, 0x61A9); /* Controls Modem 1 */ +SFRX(FREQEST, 0x61AA); /* Estimated RF Frequency Offset */ +SFRX(RXCTRL, 0x61AB); /* Tune Receive Section */ +SFRX(FSCTRL, 0x61AC); /* Tune Frequency Synthesizer */ +SFRX(FSCAL0, 0x61AD); /* Tune Frequency Calibration 0 */ +SFRX(FSCAL1, 0x61AE); /* Tune Frequency Calibration 1 */ +SFRX(FSCAL2, 0x61AF); /* Tune Frequency Calibration 2 */ +SFRX(FSCAL3, 0x61B0); /* Tune Frequency Calibration 3 */ +SFRX(AGCCTRL0, 0x61B1); /* AGC Dynamic Range Control */ +SFRX(AGCCTRL1, 0x61B2); /* AGC Reference Level */ +SFRX(AGCCTRL2, 0x61B3); /* AGC Gain Override */ +SFRX(AGCCTRL3, 0x61B4); /* AGC Control */ +SFRX(ADCTEST0, 0x61B5); /* ADC Tuning 0 */ +SFRX(ADCTEST1, 0x61B6); /* ADC Tuning 1 */ +SFRX(ADCTEST2, 0x61B7); /* ADC Tuning 2 */ +SFRX(MDMTEST0, 0x61B8); /* Test Register for Modem 0 */ +SFRX(MDMTEST1, 0x61B9); /* Test Register for Modem 1 */ +SFRX(DACTEST0, 0x61BA); /* DAC Override Value */ +SFRX(DACTEST1, 0x61BB); /* DAC Override Value */ +SFRX(DACTEST2, 0x61BC); /* DAC Test Setting */ +SFRX(ATEST, 0x61BD); /* Analog Test Control */ +SFRX(PTEST0, 0x61BE); /* Override Power-Down Register 0 */ +SFRX(PTEST1, 0x61BF); /* Override Power-Down Register 1 */ +SFRX(TXFILTCFG, 0x61FA); /* TX Filter Configuration */ +SFRX(RFC_OBS_CTRL0, 0x61EB); /* RF Observation Mux Control 0 */ +SFRX(RFC_OBS_CTRL1, 0x61EC); /* RF Observation Mux Control 1 */ +SFRX(RFC_OBS_CTRL2, 0x61ED); /* RF Observation Mux Control 2 */ + +/* Command Strobe/CSMA-CA Processor Registers */ +SFRX(CSPPROG0, 0x61C0); /* CSP Program Memory, Byte 0 */ +SFRX(CSPPROG1, 0x61C1); /* CSP Program Memory, Byte 1 */ +SFRX(CSPPROG2, 0x61C2); /* CSP Program Memory, Byte 2 */ +SFRX(CSPPROG3, 0x61C3); /* CSP Program Memory, Byte 3 */ +SFRX(CSPPROG4, 0x61C4); /* CSP Program Memory, Byte 4 */ +SFRX(CSPPROG5, 0x61C5); /* CSP Program Memory, Byte 5 */ +SFRX(CSPPROG6, 0x61C6); /* CSP Program Memory, Byte 6 */ +SFRX(CSPPROG7, 0x61C7); /* CSP Program Memory, Byte 7 */ +SFRX(CSPPROG8, 0x61C8); /* CSP Program Memory, Byte 8 */ +SFRX(CSPPROG9, 0x61C9); /* CSP Program Memory, Byte 9 */ +SFRX(CSPPROG10, 0x61CA); /* CSP Program Memory, Byte 10 */ +SFRX(CSPPROG11, 0x61CB); /* CSP Program Memory, Byte 11 */ +SFRX(CSPPROG12, 0x61CC); /* CSP Program Memory, Byte 12 */ +SFRX(CSPPROG13, 0x61CD); /* CSP Program Memory, Byte 13 */ +SFRX(CSPPROG14, 0x61CE); /* CSP Program Memory, Byte 14 */ +SFRX(CSPPROG15, 0x61CF); /* CSP Program Memory, Byte 15 */ +SFRX(CSPPROG16, 0x61D0); /* CSP Program Memory, Byte 16 */ +SFRX(CSPPROG17, 0x61D1); /* CSP Program Memory, Byte 17 */ +SFRX(CSPPROG18, 0x61D2); /* CSP Program Memory, Byte 18 */ +SFRX(CSPPROG19, 0x61D3); /* CSP Program Memory, Byte 19 */ +SFRX(CSPPROG20, 0x61D4); /* CSP Program Memory, Byte 20 */ +SFRX(CSPPROG21, 0x61D5); /* CSP Program Memory, Byte 21 */ +SFRX(CSPPROG22, 0x61D6); /* CSP Program Memory, Byte 22 */ +SFRX(CSPPROG23, 0x61D7); /* CSP Program Memory, Byte 23 */ +SFRX(CSPCTRL, 0x61E0); /* CSP Control Bit */ +SFRX(CSPSTAT, 0x61E1); /* CSP Status Register */ +SFRX(CSPX, 0x61E2); /* CSP X Register */ +SFRX(CSPY, 0x61E3); /* CSP Y Register */ +SFRX(CSPZ, 0x61E4); /* CSP Z Register */ +SFRX(CSPT, 0x61E5); /* CSP T Register */ +/*--------------------------------------------------------------------------- + * cc2531 USB Registers + * (Sec. 21.12, page 196) + *---------------------------------------------------------------------------*/ +SFRX(USBADDR, 0x6200); /* Function Address */ +SFRX(USBPOW, 0x6201); /* Power/Control Register */ +SFRX(USBIIF, 0x6202); /* IN Endpoints and EP0 Interrupt Flags */ +SFRX(USBOIF, 0x6204); /* OUT-Endpoint Interrupt Flags */ +SFRX(USBCIF, 0x6206); /* Common USB Interrupt Flags */ +SFRX(USBIIE, 0x6207); /* IN Endpoints and EP0 Interrupt-Enable Mask */ +SFRX(USBOIE, 0x6209); /* Out Endpoints Interrupt Enable Mask */ +SFRX(USBCIE, 0x620B); /* Common USB Interrupt-Enable Mask */ +SFRX(USBFRML, 0x620C); /* Current Frame Number (Low Byte) */ +SFRX(USBFRMH, 0x620D); /* Current Frame Number (High Byte) */ +SFRX(USBINDEX, 0x620E); /* Current-Endpoint Index Register */ +SFRX(USBCTRL, 0x620F); /* USB Control Register */ +SFRX(USBMAXI, 0x6210); /* Max. Packet Size for IN Endpoint{1–5} */ +SFRX(USBCS0, 0x6211); /* EP0 Control and Status (USBINDEX = 0) */ +SFRX(USBCSIL, 0x6211); /* IN EP{1–5} Control and Status, Low */ +SFRX(USBCSIH, 0x6212); /* IN EP{1–5} Control and Status, High */ +SFRX(USBMAXO, 0x6213); /* Max. Packet Size for OUT EP{1–5} */ +SFRX(USBCSOL, 0x6214); /* OUT EP{1–5} Control and Status, Low */ +SFRX(USBCSOH, 0x6215); /* OUT EP{1–5} Control and Status, High */ +SFRX(USBCNT0, 0x6216); /* Number of Received Bytes in EP0 FIFO (USBINDEX = 0) */ +SFRX(USBCNTL, 0x6216); /* Number of Bytes in EP{1–5} OUT FIFO, Low */ +SFRX(USBCNTH, 0x6217); /* Number of Bytes in EP{1–5} OUT FIFO, High */ +SFRX(USBF0, 0x6220); /* Endpoint-0 FIFO */ +SFRX(USBF1, 0x6222); /* Endpoint-1 FIFO */ +SFRX(USBF2, 0x6224); /* Endpoint-2 FIFO */ +SFRX(USBF3, 0x6226); /* Endpoint-3 FIFO */ +SFRX(USBF4, 0x6228); /* Endpoint-4 FIFO */ +SFRX(USBF5, 0x622A); /* Endpoint-5 FIFO */ +/*--------------------------------------------------------------------------- + * SFR Access via XDATA (0x7080 - 0x70FF) + *---------------------------------------------------------------------------*/ +SFRX(X_P0, 0x7080); /* Port 0 - Read Only */ +SFRX(X_U0CSR, 0x7086); /* USART 0 control and status */ +SFRX(X_P0IFG, 0x7089); /* Port 0 interrupt status flag */ +SFRX(X_P1IFG, 0x708A); /* Port 1 interrupt status flag */ +SFRX(X_P2IFG, 0x708B); /* Port 2 interrupt status flag */ +SFRX(X_PICTL, 0x708C); /* Port pins interrupt mask and edge */ +SFRX(X_P1IEN, 0x708D); /* Port 1 interrupt mask */ +SFRX(X_P0INP, 0x708F); /* Port 0 input Mode */ +SFRX(X_P1, 0x7090); /* Port 1 - Read Only */ +SFRX(X_RFIRQF1, 0x7091); /* RF interrupt flags MSB */ +SFRX(X_MPAGE, 0x7093); /* Memory page select */ +SFRX(X__XPAGE, 0x7093); /* Memory page select - SDCC name */ +SFRX(X_T2CTRL, 0x7094); /* Timer 2 control */ +SFRX(X_ST0, 0x7095); /* Sleep Timer 0 */ +SFRX(X_ST1, 0x7096); /* Sleep Timer 1 */ +SFRX(X_ST2, 0x7097); /* Sleep Timer 2 */ +SFRX(X_T2EVTCFG, 0x709C); /* Timer 2 event configuration */ +SFRX(X_SLEEPSTA, 0x709D); /* Sleep-mode control status */ +SFRX(X_CLKCONSTA, 0x709E); /* Clock control status */ +SFRX(X_FMAP, 0x709F); /* Flash-memory bank mapping */ +SFRX(X_PSBANK, 0x709F); /* Flash-memory bank mapping - SDCC name */ +SFRX(X_P2, 0x70A0); /* Port 2 - Read Only */ +SFRX(X_T2IRQF, 0x70A1); /* Timer 2 interrupt flags */ +SFRX(X_T2M0, 0x70A2); /* Timer 2 multiplexed register 0 */ +SFRX(X_T2M1, 0x70A3); /* Timer 2 multiplexed register 1 */ +SFRX(X_T2MOVF0, 0x70A4); /* Timer 2 multiplexed overflow register 0 */ +SFRX(X_T2MOVF1, 0x70A5); /* Timer 2 multiplexed overflow register 1 */ +SFRX(X_T2MOVF2, 0x70A6); /* Timer 2 multiplexed overflow register 2 */ +SFRX(X_T2IRQM, 0x70A7); /* Timer 2 interrupt mask */ +SFRX(X_P0IEN, 0x70AB); /* Port 0 interrupt mask */ +SFRX(X_P2IEN, 0x70AC); /* Port 2 interrupt mask */ +SFRX(X_STLOAD, 0x70AD); /* Sleep-timer load status */ +SFRX(X_PMUX, 0x70AE); /* Power-down signal mux */ +SFRX(X_T1STAT, 0x70AF); /* Timer 1 status */ +SFRX(X_ENCDI, 0x70B1); /* Encryption/decryption input data */ +SFRX(X_ENCDO, 0x70B2); /* Encryption/decryption output data */ +SFRX(X_ENCCS, 0x70B3); /* Encryption/decryption control and status */ +SFRX(X_ADCCON1, 0x70B4); /* ADC control 1 */ +SFRX(X_ADCCON2, 0x70B5); /* ADC control 2 */ +SFRX(X_ADCCON3, 0x70B6); /* ADC control 3 */ +SFRX(X_ADCL, 0x70BA); /* ADC data low */ +SFRX(X_ADCH, 0x70BB); /* ADC data high */ +SFRX(X_RNDL, 0x70BC); /* Random number generator data low */ +SFRX(X_RNDH, 0x70BD); /* Random number generator data high */ +SFRX(X_SLEEPCMD, 0x70BE); /* Sleep-mode control command */ +SFRX(X_RFERRF, 0x70BF); /* RF error interrupt flags */ +SFRX(X_U0DBUF, 0x70C1); /* USART 0 receive/transmit data buffer */ +SFRX(X_U0BAUD, 0x70C2); /* USART 0 baud-rate control */ +SFRX(X_T2MSEL, 0x70C3); /* Timer 2 multiplex select */ +SFRX(X_U0UCR, 0x70C4); /* USART 0 UART control */ +SFRX(X_U0GCR, 0x70C5); /* USART 0 generic control */ +SFRX(X_CLKCONCMD, 0x70C6); /* Clock control command */ +SFRX(X_MEMCTR, 0x70C7); /* Memory system control */ +SFRX(X_WDCTL, 0x70C9); /* Watchdog Timer Control */ +SFRX(X_T3CNT, 0x70CA); /* Timer 3 counter */ +SFRX(X_T3CTL, 0x70CB); /* Timer 3 control */ +SFRX(X_T3CCTL0, 0x70CC); /* Timer 3 channel 0 compare control */ +SFRX(X_T3CC0, 0x70CD); /* Timer 3 channel 0 compare value */ +SFRX(X_T3CCTL1, 0x70CE); /* Timer 3 channel 1 compare control */ +SFRX(X_T3CC1, 0x70CF); /* Timer 3 channel 1 compare value */ +SFRX(X_DMAIRQ, 0x70D1); /* DMA interrupt flag */ +SFRX(X_DMA1CFGL, 0x70D2); /* DMA channel 1–4 configuration address low */ +SFRX(X_DMA1CFGH, 0x70D3); /* DMA channel 1–4 configuration address high */ +SFRX(X_DMA0CFGL, 0x70D4); /* DMA channel 0 configuration address low */ +SFRX(X_DMA0CFGH, 0x70D5); /* DMA channel 0 configuration address high */ +SFRX(X_DMAARM, 0x70D6); /* DMA channel armed */ +SFRX(X_DMAREQ, 0x70D7); /* DMA channel start request and status */ +SFRX(X_TIMIF, 0x70D8); /* Timers 1/3/4 joint interrupt mask/flags */ +SFRX(X_RFD, 0x70D9); /* RF data */ +SFRX(X_T1CC0L, 0x70DA); /* Timer 1 channel 0 capture/compare value low */ +SFRX(X_T1CC0H, 0x70DB); /* Timer 1 channel 0 capture/compare value high */ +SFRX(X_T1CC1L, 0x70DC); /* Timer 1 channel 1 capture/compare value low */ +SFRX(X_T1CC1H, 0x70DD); /* Timer 1 channel 1 capture/compare value high */ +SFRX(X_T1CC2L, 0x70DE); /* Timer 1 channel 2 capture/compare value low */ +SFRX(X_T1CC2H, 0x70DF); /* Timer 1 channel 2 capture/compare value high */ +SFRX(X_RFST, 0x70E1); /* RF command strobe */ +SFRX(X_T1CNTL, 0x70E2); /* Timer 1 counter low */ +SFRX(X_T1CNTH, 0x70E3); /* Timer 1 counter high */ +SFRX(X_T1CTL, 0x70E4); /* Timer 1 control and status */ +SFRX(X_T1CCTL0, 0x70E5); /* Timer 1 channel 0 capture/compare control */ +SFRX(X_T1CCTL1, 0x70E6); /* Timer 1 channel 1 capture/compare control */ +SFRX(X_T1CCTL2, 0x70E7); /* Timer 1 channel 2 capture/compare control */ +SFRX(X_RFIRQF0, 0x70E9); /* RF interrupt flags LSB */ +SFRX(X_T4CNT, 0x70EA); /* Timer 4 counter */ +SFRX(X_T4CTL, 0x70EB); /* Timer 4 control */ +SFRX(X_T4CCTL0, 0x70EC); /* Timer 4 channel 0 compare control */ +SFRX(X_T4CC0, 0x70ED); /* Timer 4 channel 0 compare value */ +SFRX(X_T4CCTL1, 0x70EE); /* Timer 4 channel 1 compare control */ +SFRX(X_T4CC1, 0x70EF); /* Timer 4 channel 1 compare value */ +SFRX(X_PERCFG, 0x70F1); /* Peripheral I/O control */ +SFRX(X_APCFG, 0x70F2); /* Analog peripheral I/O configuration */ +SFRX(X_P0SEL, 0x70F3); /* Port 0 function select */ +SFRX(X_P1SEL, 0x70F4); /* Port 1 function select */ +SFRX(X_P2SEL, 0x70F5); /* Port 2 function select */ +SFRX(X_P1INP, 0x70F6); /* Port 1 input mode */ +SFRX(X_P2INP, 0x70F7); /* Port 2 input mode */ +SFRX(X_U1CSR, 0x70F8); /* USART 1 control and status */ +SFRX(X_U1DBUF, 0x70F9); /* USART 1 receive/transmit data buffer */ +SFRX(X_U1BAUD, 0x70FA); /* USART 1 baud-rate control */ +SFRX(X_U1UCR, 0x70FB); /* USART 1 UART control */ +SFRX(X_U1GCR, 0x70FC); /* USART 1 Generic control */ +SFRX(X_P0DIR, 0x70FD); /* Port 0 direction */ +SFRX(X_P1DIR, 0x70FE); /* Port 1 direction */ +SFRX(X_P2DIR, 0x70FF); /* Port 2 direction */ +/*--------------------------------------------------------------------------- + * Information Page (Read Only) + *---------------------------------------------------------------------------*/ +SFRX(X_INFOPAGE, 0x7800); /* Start of Information Page */ +SFRX(X_IEEE_ADDR, 0x780C); /* Start of unique IEEE Address */ + +#endif /* __CC253X_H__ */ diff --git a/cpu/cc253x/dev/cc2530-rf.c b/cpu/cc253x/dev/cc2530-rf.c new file mode 100644 index 000000000..fc01d8a37 --- /dev/null +++ b/cpu/cc253x/dev/cc2530-rf.c @@ -0,0 +1,489 @@ +/* + * Copyright (c) 2011, George Oikonomou - + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * Implementation of the cc2530 RF driver + * + * \author + * George Oikonomou - + */ +#include "contiki.h" +#include "dev/radio.h" +#include "dev/cc2530-rf.h" +#include "cc253x.h" +#include "sfr-bits.h" +#include "sys/clock.h" +#include "sys/rtimer.h" + +#include "net/packetbuf.h" +#include "net/rime/rimestats.h" +#include "net/netstack.h" + +#include +/*---------------------------------------------------------------------------*/ +#define CHECKSUM_LEN 2 +/*---------------------------------------------------------------------------*/ +#if CC2530_RF_CONF_LEDS +#define CC2530_RF_LEDS CC2530_RF_CONF_LEDS +#else +#define CC2530_RF_LEDS 0 +#endif + +#if CC2530_RF_LEDS +#include "dev/leds.h" +#define RF_RX_LED_ON() leds_on(LEDS_RED); +#define RF_RX_LED_OFF() leds_off(LEDS_RED); +#define RF_TX_LED_ON() leds_on(LEDS_GREEN); +#define RF_TX_LED_OFF() leds_off(LEDS_GREEN); +#else +#define RF_RX_LED_ON() +#define RF_RX_LED_OFF() +#define RF_TX_LED_ON() +#define RF_TX_LED_OFF() +#endif +/*---------------------------------------------------------------------------*/ +#define DEBUG 0 +#if DEBUG +#include "debug.h" +#define PUTSTRING(...) putstring(__VA_ARGS__) +#define PUTHEX(...) puthex(__VA_ARGS__) +#else +#define PUTSTRING(...) +#define PUTHEX(...) +#endif +/*---------------------------------------------------------------------------*/ +/* Local RF Flags */ +#define RX_ACTIVE 0x80 +#define WAS_OFF 0x10 +#define RF_ON 0x01 + +/* Bit Masks for the last byte in the RX FIFO */ +#define CRC_BIT_MASK 0x80 +#define LQI_BIT_MASK 0x7F + +/* 192 ms, radio off -> on interval */ +#define ONOFF_TIME RTIMER_ARCH_SECOND / 3125 +/*---------------------------------------------------------------------------*/ +#if CC2530_RF_CONF_HEXDUMP +#include "uart0.h" +static const uint8_t magic[] = { 0x53, 0x6E, 0x69, 0x66 }; /* Snif */ +#endif +/*---------------------------------------------------------------------------*/ +#ifdef CC2530_RF_CONF_AUTOACK +#define CC2530_RF_AUTOACK CC2530_RF_CONF_AUTOACK +#else +#define CC2530_RF_AUTOACK 1 +#endif +/*---------------------------------------------------------------------------*/ +static uint8_t __data rf_flags; + +static int on(void); /* prepare() needs our prototype */ +static int off(void); /* transmit() needs our prototype */ +static int channel_clear(void); /* transmit() needs our prototype */ +/*---------------------------------------------------------------------------*/ +int8_t +cc2530_rf_channel_set(uint8_t channel) +{ + PUTSTRING("RF: Set Chan\n"); + + if((channel < CC2530_RF_CHANNEL_MIN) || (channel > CC2530_RF_CHANNEL_MAX)) { + return -1; + } + + /* Changes to FREQCTRL take effect after the next recalibration */ + off(); + FREQCTRL = (CC2530_RF_CHANNEL_MIN + + (channel - CC2530_RF_CHANNEL_MIN) * CC2530_RF_CHANNEL_SPACING); + on(); + + return (int8_t) channel; +} +/*---------------------------------------------------------------------------*/ +uint8_t +cc2530_rf_power_set(uint8_t new_power) +{ + PUTSTRING("RF: Set Power\n"); + /* off() */ + TXPOWER = new_power; + /* on() */ + + return TXPOWER; +} +/*---------------------------------------------------------------------------*/ +void +cc2530_rf_set_addr(uint16_t pan) +{ + PAN_ID0 = pan & 0xFF; + PAN_ID1 = pan >> 8; + + SHORT_ADDR0 = ((uint8_t *)&X_IEEE_ADDR)[0]; + SHORT_ADDR1 = ((uint8_t *)&X_IEEE_ADDR)[1]; + + memcpy(&EXT_ADDR0, &X_IEEE_ADDR, 8); +} +/*---------------------------------------------------------------------------*/ +/* Netstack API radio driver functions */ +/*---------------------------------------------------------------------------*/ +static int +init(void) +{ + PUTSTRING("RF: Init\n"); + + if(rf_flags & RF_ON) { + return 0; + } + +#ifdef CC2530_RF_LOW_POWER_RX + /* Reduce RX power consumption current to 20mA at the cost of sensitivity */ + RXCTRL = 0x00; + FSCTRL = 0x50; +#else + RXCTRL = 0x3F; + FSCTRL = 0x55; +#endif /* CC2530_RF_LOW_POWER_RX */ + + CCACTRL0 = CC2530_RF_CCA_THRES; + + /* + * According to the user guide, these registers must be updated from their + * defaults for optimal performance + * + * Table 23-6, Sec. 23.15.1, p. 259 + */ + TXFILTCFG = 0x09; /* TX anti-aliasing filter */ + AGCCTRL1 = 0x15; /* AGC target value */ + FSCAL1 = 0x00; /* Reduce the VCO leakage */ + + /* Auto ACKs and CRC calculation, default RX and TX modes with FIFOs */ + FRMCTRL0 = FRMCTRL0_AUTOCRC; +#if CC2530_RF_AUTOACK + FRMCTRL0 |= FRMCTRL0_AUTOACK; +#endif + + /* Disable source address matching and autopend */ + SRCMATCH = 0; /* investigate */ + + /* MAX FIFOP threshold */ + FIFOPCTRL = CC2530_RF_MAX_PACKET_LEN; + + cc2530_rf_power_set(CC2530_RF_TX_POWER); + cc2530_rf_channel_set(CC2530_RF_CHANNEL); + + RF_TX_LED_OFF(); + RF_RX_LED_OFF(); + + rf_flags |= RF_ON; + + return 1; +} +/*---------------------------------------------------------------------------*/ +static int +prepare(const void *payload, unsigned short payload_len) +{ + uint8_t i; + + PUTSTRING("RF: Prepare 0x"); + PUTHEX(payload_len + CHECKSUM_LEN); + PUTSTRING(" bytes\n"); + + /* + * When we transmit in very quick bursts, make sure previous transmission + * is not still in progress before re-writing to the TX FIFO + */ + while(FSMSTAT1 & FSMSTAT1_TX_ACTIVE); + + if((rf_flags & RX_ACTIVE) == 0) { + on(); + } + + CC2530_CSP_ISFLUSHTX(); + + PUTSTRING("RF: data = "); + /* Send the phy length byte first */ + RFD = payload_len + CHECKSUM_LEN; /* Payload plus FCS */ + for(i = 0; i < payload_len; i++) { + RFD = ((unsigned char*) (payload))[i]; + PUTHEX(((unsigned char*)(payload))[i]); + } + PUTSTRING("\n"); + + /* Leave space for the FCS */ + RFD = 0; + RFD = 0; + + return 0; +} +/*---------------------------------------------------------------------------*/ +static int +transmit(unsigned short transmit_len) +{ + uint8_t counter; + int ret = RADIO_TX_ERR; + rtimer_clock_t t0; + transmit_len; /* hush the warning */ + + if(!(rf_flags & RX_ACTIVE)) { + t0 = RTIMER_NOW(); + on(); + rf_flags |= WAS_OFF; + while (RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + ONOFF_TIME)); + } + + if(channel_clear() == CC2530_RF_CCA_BUSY) { + RIMESTATS_ADD(contentiondrop); + return RADIO_TX_COLLISION; + } + + /* + * prepare() double checked that TX_ACTIVE is low. If SFD is high we are + * receiving. Abort transmission and bail out with RADIO_TX_COLLISION + */ + if(FSMSTAT1 & FSMSTAT1_SFD) { + RIMESTATS_ADD(contentiondrop); + return RADIO_TX_COLLISION; + } + + /* Start the transmission */ + RF_TX_LED_ON(); + ENERGEST_OFF(ENERGEST_TYPE_LISTEN); + ENERGEST_ON(ENERGEST_TYPE_TRANSMIT); + + CC2530_CSP_ISTXON(); + + counter = 0; + while(!(FSMSTAT1 & FSMSTAT1_TX_ACTIVE) && (counter++ < 3)) { + clock_delay(10); + } + + if(!(FSMSTAT1 & FSMSTAT1_TX_ACTIVE)) { + PUTSTRING("RF: TX never active.\n"); + CC2530_CSP_ISFLUSHTX(); + ret = RADIO_TX_ERR; + } else { + /* Wait for the transmission to finish */ + while(FSMSTAT1 & FSMSTAT1_TX_ACTIVE); + ret = RADIO_TX_OK; + } + ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT); + ENERGEST_ON(ENERGEST_TYPE_LISTEN); + + if(rf_flags & WAS_OFF){ + off(); + } + + RIMESTATS_ADD(lltx); + + RF_TX_LED_OFF(); + + /* OK, sent. We are now ready to send more */ + return ret; +} +/*---------------------------------------------------------------------------*/ +static int +send(void *payload, unsigned short payload_len) +{ + prepare(payload, payload_len); + return transmit(payload_len); +} +/*---------------------------------------------------------------------------*/ +static int +read(void *buf, unsigned short bufsize) +{ + uint8_t i; + uint8_t len; + uint8_t crc_corr; + int8_t rssi; + + PUTSTRING("RF: Read\n"); + + /* Check the length */ + len = RFD; + + /* Check for validity */ + if(len > CC2530_RF_MAX_PACKET_LEN) { + /* Oops, we must be out of sync. */ + PUTSTRING("RF: bad sync\n"); + + RIMESTATS_ADD(badsynch); + CC2530_CSP_ISFLUSHRX(); + return 0; + } + + if(len <= CC2530_RF_MIN_PACKET_LEN) { + PUTSTRING("RF: too short\n"); + + RIMESTATS_ADD(tooshort); + CC2530_CSP_ISFLUSHRX(); + return 0; + } + + if(len - CHECKSUM_LEN > bufsize) { + PUTSTRING("RF: too long\n"); + + RIMESTATS_ADD(toolong); + CC2530_CSP_ISFLUSHRX(); + return 0; + } + +#if CC2530_RF_CONF_HEXDUMP + /* If we reach here, chances are the FIFO is holding a valid frame */ + uart0_writeb(magic[0]); + uart0_writeb(magic[1]); + uart0_writeb(magic[2]); + uart0_writeb(magic[3]); + uart0_writeb(len); +#endif + + RF_RX_LED_ON(); + + PUTSTRING("RF: read (0x"); + PUTHEX(len); + PUTSTRING(" bytes) = "); + len -= CHECKSUM_LEN; + for(i = 0; i < len; ++i) { + ((unsigned char*)(buf))[i] = RFD; +#if CC2530_RF_CONF_HEXDUMP + uart0_writeb(((unsigned char*)(buf))[i]); +#endif + PUTHEX(((unsigned char*)(buf))[i]); + } + PUTSTRING("\n"); + + /* Read the RSSI and CRC/Corr bytes */ + rssi = ((int8_t) RFD) - 45; + crc_corr = RFD; + +#if CC2530_RF_CONF_HEXDUMP + uart0_writeb(rssi); + uart0_writeb(crc_corr); +#endif + + /* MS bit CRC OK/Not OK, 7 LS Bits, Correlation value */ + if(crc_corr & CRC_BIT_MASK) { + packetbuf_set_attr(PACKETBUF_ATTR_RSSI, rssi); + packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, crc_corr & LQI_BIT_MASK); + RIMESTATS_ADD(llrx); + } else { + RIMESTATS_ADD(badcrc); + CC2530_CSP_ISFLUSHRX(); + RF_RX_LED_OFF(); + return 0; + } + + /* If FIFOP==1 and FIFO==0 then we had a FIFO overflow at some point. */ + if((FSMSTAT1 & (FSMSTAT1_FIFO | FSMSTAT1_FIFOP)) == FSMSTAT1_FIFOP) { + /* + * If we reach here means that there might be more intact packets in the + * FIFO despite the overflow. This can happen with bursts of small packets. + * + * Only flush if the FIFO is actually empty. If not, then next pass we will + * pick up one more packet or flush due to an error. + */ + if(!RXFIFOCNT) { + CC2530_CSP_ISFLUSHRX(); + } + } + + RF_RX_LED_OFF(); + + return (len); +} +/*---------------------------------------------------------------------------*/ +static int +channel_clear(void) +{ + if(FSMSTAT1 & FSMSTAT1_CCA) { + return CC2530_RF_CCA_CLEAR; + } + return CC2530_RF_CCA_BUSY; +} +/*---------------------------------------------------------------------------*/ +static int +receiving_packet(void) +{ + PUTSTRING("RF: Receiving\n"); + + /* + * SFD high while transmitting and receiving. + * TX_ACTIVE high only when transmitting + * + * FSMSTAT1 & (TX_ACTIVE | SFD) == SFD <=> receiving + */ + return (FSMSTAT1 & (FSMSTAT1_TX_ACTIVE | FSMSTAT1_SFD) == FSMSTAT1_SFD); +} +/*---------------------------------------------------------------------------*/ +static int +pending_packet(void) +{ + return (FSMSTAT1 & FSMSTAT1_FIFOP); +} +/*---------------------------------------------------------------------------*/ +static int +on(void) +{ + if(!(rf_flags & RX_ACTIVE)) { + CC2530_CSP_ISFLUSHRX(); + CC2530_CSP_ISRXON(); + + rf_flags |= RX_ACTIVE; + } + + ENERGEST_ON(ENERGEST_TYPE_LISTEN); + return 1; +} +/*---------------------------------------------------------------------------*/ +static int +off(void) +{ + CC2530_CSP_ISRFOFF(); + CC2530_CSP_ISFLUSHRX(); + + rf_flags = 0; + + ENERGEST_OFF(ENERGEST_TYPE_LISTEN); + return 1; +} +/*---------------------------------------------------------------------------*/ +const struct radio_driver cc2530_rf_driver = +{ + init, + prepare, + transmit, + send, + read, + channel_clear, + receiving_packet, + pending_packet, + on, + off, +}; +/*---------------------------------------------------------------------------*/ diff --git a/cpu/cc253x/dev/cc2530-rf.h b/cpu/cc253x/dev/cc2530-rf.h new file mode 100644 index 000000000..397b952a3 --- /dev/null +++ b/cpu/cc253x/dev/cc2530-rf.h @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2011, George Oikonomou - + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * Implementation of the cc2530 RF driver + * + * \author + * George Oikonomou - + */ +#ifndef __CC2530_RF_H__ +#define __CC2530_RF_H__ + +#include "contiki.h" +#include "dev/radio.h" +#include "cc253x.h" +/*--------------------------------------------------------------------------- + * RF Config + *---------------------------------------------------------------------------*/ +#define CC2530_RF_TX_POWER_RECOMMENDED 0xD5 +#ifdef CC2530_RF_CONF_TX_POWER +#define CC2530_RF_TX_POWER CC2530_RF_CONF_TX_POWER +#else +#define CC2530_RF_TX_POWER CC2530_RF_TX_POWER_RECOMMENDED +#endif /* CC2530_RF_CONF_TX_POWER */ + +#ifdef CC2530_RF_CONF_CCA_THRES +#define CC2530_RF_CCA_THRES CC2530_RF_CONF_CCA_THRES +#else +#define CC2530_RF_CCA_THRES CCA_THRES_USER_GUIDE /* User guide recommendation */ +#endif /* CC2530_RF_CONF_CCA_THRES */ + +#ifdef CC2530_RF_CONF_CHANNEL +#define CC2530_RF_CHANNEL CC2530_RF_CONF_CHANNEL +#else +#define CC2530_RF_CHANNEL 18 +#endif /* CC2530_RF_CONF_CHANNEL */ +#define CC2530_RF_CHANNEL_MIN 11 +#define CC2530_RF_CHANNEL_MAX 26 +#define CC2530_RF_CHANNEL_SPACING 5 + +#ifdef CC2530_RF_CONF_AUTOACK +#define CC2530_RF_AUTOACK CC2530_RF_CONF_AUTOACK +#else +#define CC2530_RF_AUTOACK 1 +#endif /* CC2530_RF_CONF_AUTOACK */ + +#ifdef CC2530_RF_CONF_LOW_POWER_RX +#define CC2530_RF_LOW_POWER_RX CC2530_RF_CONF_LOW_POWER_RX +#else +#define CC2530_RF_LOW_POWER_RX 0 +#endif /* CC2530_RF_CONF_LOW_POWER_RX */ +/*---------------------------------------------------------------------------*/ +#define CCA_THRES_USER_GUIDE 0xF8 +#define CCA_THRES_ALONE 0xFC /* -4-76=-80dBm when CC2530 operated alone or with CC2591 in LGM */ +#define CCA_THR_HGM 0x06 /* 6-76=-70dBm when CC2530 operated with CC2591 in HGM */ +#define CORR_THR 0x14 +/*---------------------------------------------------------------------------*/ +#define CC2530_RF_MAX_PACKET_LEN 127 +#define CC2530_RF_MIN_PACKET_LEN 4 +/*---------------------------------------------------------------------------*/ +#define CC2530_RF_CCA_CLEAR 1 +#define CC2530_RF_CCA_BUSY 0 + +/* Wait for RSSI to be valid. */ +#define CC2530_RF_CCA_VALID_WAIT() while(!(RSSISTAT & RSSIST)) +/*--------------------------------------------------------------------------- + * Command Strobe Processor + *---------------------------------------------------------------------------*/ +/* OPCODES */ +#define CSP_OP_ISRXON 0xE3 +#define CSP_OP_ISTXON 0xE9 +#define CSP_OP_ISTXONCCA 0xEA +#define CSP_OP_ISRFOFF 0xEF +#define CSP_OP_ISFLUSHRX 0xED +#define CSP_OP_ISFLUSHTX 0xEE + +#define CC2530_CSP_ISRXON() do { RFST = CSP_OP_ISRXON; } while(0) +#define CC2530_CSP_ISTXON() do { RFST = CSP_OP_ISTXON; } while(0) +#define CC2530_CSP_ISTXONCCA() do { RFST = CSP_OP_ISTXONCCA; } while(0) +#define CC2530_CSP_ISRFOFF() do { RFST = CSP_OP_ISRFOFF; } while(0) + +/* OP x 2 for flushes */ +#define CC2530_CSP_ISFLUSHRX() do { \ + RFST = CSP_OP_ISFLUSHRX; \ + RFST = CSP_OP_ISFLUSHRX; \ +} while(0) +#define CC2530_CSP_ISFLUSHTX() do { \ + RFST = CSP_OP_ISFLUSHTX; \ + RFST = CSP_OP_ISFLUSHTX; \ +} while(0) +/*---------------------------------------------------------------------------*/ +extern const struct radio_driver cc2530_rf_driver; +/*---------------------------------------------------------------------------*/ +int8_t cc2530_rf_channel_set(uint8_t channel); +uint8_t cc2530_rf_power_set(uint8_t new_power); +void cc2530_rf_set_addr(uint16_t pan); +/*---------------------------------------------------------------------------*/ +#endif /* __CC2530_RF_H__ */ diff --git a/cpu/cc253x/dev/clock-isr.h b/cpu/cc253x/dev/clock-isr.h new file mode 100644 index 000000000..005ac38c6 --- /dev/null +++ b/cpu/cc253x/dev/clock-isr.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2011, George Oikonomou - + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * Declaration of the Sleep timer ISR, used by the clock module + * \author + * George Oikonomou - + */ +#ifndef __CLOCK_ISR_H__ +#define __CLOCK_ISR_H__ + +#include "contiki-conf.h" +#include "cc253x.h" + +void clock_isr(void) __interrupt(ST_VECTOR); + +#endif /* __CLOCK_ISR_H__ */ diff --git a/cpu/cc253x/dev/clock.c b/cpu/cc253x/dev/clock.c new file mode 100644 index 000000000..6d9a5fdc1 --- /dev/null +++ b/cpu/cc253x/dev/clock.c @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2009, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + * $Id: clock.c,v 1.1 2009/09/08 20:07:35 zdshelby Exp $ + */ + +/** + * \file + * Implementation of the clock functions for the 8051 CPU + * \author + * Zach Shelby (zach@sensinode.com) - original + * George Oikonomou - - cc2530 port + */ +#include "sfr-bits.h" +#include "sys/clock.h" +#include "sys/etimer.h" +#include "cc253x.h" +#include "sys/energest.h" + +/* Sleep timer runs on the 32k RC osc. */ +/* One clock tick is 7.8 ms */ +#define TICK_VAL (32768/128) /* 256 */ + +#define MAX_TICKS (~((clock_time_t)0) / 2) +/*---------------------------------------------------------------------------*/ +/* Do NOT remove the absolute address and do NOT remove the initialiser here */ +__xdata __at(0x0000) static unsigned long timer_value = 0; + +static volatile __data clock_time_t count = 0; /* Uptime in ticks */ +static volatile __data clock_time_t seconds = 0; /* Uptime in secs */ +/*---------------------------------------------------------------------------*/ +/** + * One delay is about 0.6 us, so this function delays for len * 0.6 us + */ +void +clock_delay(unsigned int len) +{ + unsigned int i; + for(i = 0; i< len; i++) { + ASM(nop); + } +} +/*---------------------------------------------------------------------------*/ +/** + * Wait for a multiple of ~8 ms (a tick) + */ +void +clock_wait(int i) +{ + clock_time_t start; + + start = clock_time(); + while(clock_time() - start < (clock_time_t)i); +} +/*---------------------------------------------------------------------------*/ +CCIF clock_time_t +clock_time(void) +{ + return count; +} +/*---------------------------------------------------------------------------*/ +CCIF unsigned long +clock_seconds(void) +{ + return seconds; +} +/*---------------------------------------------------------------------------*/ +/* + * There is some ambiguity between TI cc2530 software examples and information + * in the datasheet. + * + * TI examples appear to be writing to SLEEPCMD, initialising hardware in a + * fashion semi-similar to cc2430 + * + * However, the datasheet claims that those bits in SLEEPCMD are reserved + * + * The code here goes by the datasheet (ignore TI examples) and seems to work. + */ +void +clock_init(void) +{ + /* Make sure we know where we stand */ + CLKCONCMD = CLKCONCMD_OSC32K | CLKCONCMD_OSC; + + /* Stay with 32 KHz RC OSC, Chance System Clock to 32 MHz */ + CLKCONCMD &= ~CLKCONCMD_OSC; + while(CLKCONSTA & CLKCONCMD_OSC); + + /* Tickspeed 500 kHz for timers[1-4] */ + CLKCONCMD |= CLKCONCMD_TICKSPD2 | CLKCONCMD_TICKSPD1; + while(CLKCONSTA != CLKCONCMD); + + /*Initialize tick value*/ + timer_value = ST0; + timer_value += ((unsigned long int) ST1) << 8; + timer_value += ((unsigned long int) ST2) << 16; + timer_value += TICK_VAL; + ST2 = (unsigned char) (timer_value >> 16); + ST1 = (unsigned char) (timer_value >> 8); + ST0 = (unsigned char) timer_value; + + STIE = 1; /* IEN0.STIE interrupt enable */ +} +/*---------------------------------------------------------------------------*/ +void +clock_isr(void) __interrupt(ST_VECTOR) +{ + DISABLE_INTERRUPTS(); + ENERGEST_ON(ENERGEST_TYPE_IRQ); + + /* + * If the Sleep timer throws an interrupt while we are powering down to + * PM1, we need to abort the power down. Clear SLEEP.MODE, this will signal + * main() to abort the PM1 transition + * + * On cc2430 this would be: + * SLEEPCMD &= 0xFC; + */ + + /* + * Read value of the ST0:ST1:ST2, add TICK_VAL and write it back. + * Next interrupt occurs after the current time + TICK_VAL + */ + timer_value = ST0; + timer_value += ((unsigned long int) ST1) << 8; + timer_value += ((unsigned long int) ST2) << 16; + timer_value += TICK_VAL; + ST2 = (unsigned char) (timer_value >> 16); + ST1 = (unsigned char) (timer_value >> 8); + ST0 = (unsigned char) timer_value; + + ++count; + + /* Make sure the CLOCK_CONF_SECOND is a power of two, to ensure + that the modulo operation below becomes a logical and and not + an expensive divide. Algorithm from Wikipedia: + http://en.wikipedia.org/wiki/Power_of_two */ +#if (CLOCK_CONF_SECOND & (CLOCK_CONF_SECOND - 1)) != 0 +#error CLOCK_CONF_SECOND must be a power of two (i.e., 1, 2, 4, 8, 16, 32, 64, ...). +#error Change CLOCK_CONF_SECOND in contiki-conf.h. +#endif + if(count % CLOCK_CONF_SECOND == 0) { + ++seconds; + } + + if(etimer_pending() + && (etimer_next_expiration_time() - count - 1) > MAX_TICKS) { + etimer_request_poll(); + } + + STIF = 0; /* IRCON.STIF */ + ENERGEST_OFF(ENERGEST_TYPE_IRQ); + ENABLE_INTERRUPTS(); +} +/*---------------------------------------------------------------------------*/ diff --git a/cpu/cc253x/dev/dma.c b/cpu/cc253x/dev/dma.c new file mode 100644 index 000000000..992c3dd57 --- /dev/null +++ b/cpu/cc253x/dev/dma.c @@ -0,0 +1,69 @@ +/** + * \file + * Driver for the cc2430 DMA controller. Can be assigned to any bank + * + * \author + * Original: Martti Huttunen + * Port: Zach Shelby + * Further Modifications: + * George Oikonomou + * + */ + +#include "contiki.h" +#include "dev/dma.h" +#include "cc253x.h" + +#if DMA_ON +struct dma_config dma_conf[DMA_CHANNEL_COUNT]; /* DMA Descriptors */ +struct process * dma_callback[DMA_CHANNEL_COUNT]; +/*---------------------------------------------------------------------------*/ +void +dma_init(void) +{ + uint16_t tmp_ptr; + + memset(dma_conf, 0, 4 * sizeof(dma_config_t)); + + for(tmp_ptr = 0; tmp_ptr < DMA_CHANNEL_COUNT; tmp_ptr++) { + dma_callback[tmp_ptr] = 0; + } + + /* The address of the descriptor for Channel 0 is configured separately */ + tmp_ptr = (uint16_t) &(dma_conf[0]); + DMA0CFGH = tmp_ptr >> 8; + DMA0CFGL = tmp_ptr; + + /* + * Descriptors for Channels 1-4 must be consecutive in RAM. + * We write the address of the 1st one to the register and the rest are + * derived by the SoC + */ +#if (DMA_CHANNEL_COUNT > 1) + tmp_ptr = (uint16_t) &(dma_conf[1]); + DMA1CFGH = tmp_ptr >> 8; + DMA1CFGL = tmp_ptr; +#endif + + IEN1_DMAIE = 1; /* Enable DMA interrupts */ +} +/*---------------------------------------------------------------------------*/ +/* + * Associate process p with DMA channel c. When a transfer on that channel + * completes, the ISR will poll this process. + */ +void +dma_associate_process(struct process * p, uint8_t c) +{ + if((!c) || (c >= DMA_CHANNEL_COUNT)) { + return; + } + + if(p) { + dma_conf[c].inc_prio |= 8; /* Enable interrupt generation */ + IEN1_DMAIE = 1; /* Make sure DMA interrupts are acknowledged */ + } + dma_callback[c] = p; +} +/*---------------------------------------------------------------------------*/ +#endif diff --git a/cpu/cc253x/dev/dma.h b/cpu/cc253x/dev/dma.h new file mode 100644 index 000000000..83e283a7a --- /dev/null +++ b/cpu/cc253x/dev/dma.h @@ -0,0 +1,148 @@ +/** + * \file + * Header file for the cc2430 DMA controller + * + * \author + * Original: Martti Huttunen + * Port: Zach Shelby + * Further Modifications: + * George Oikonomou + */ + +#ifndef __DMA_H +#define __DMA_H +#include "cc253x.h" + +/* DMA triggers */ +#define DMA_T_NONE 0 /* None, DMAREQ.DMAREQx bits start transfer */ +#define DMA_T_PREV 1 /* completion of previous channel */ +#define DMA_T_T1_CH0 2 /* Timer 1, compare, channel 0 */ +#define DMA_T_T1_CH1 3 /* Timer 1, compare, channel 1 */ +#define DMA_T_T1_CH2 4 /* Timer 1, compare, channel 2 */ +#define DMA_T_T2_COMP 5 /* Timer 2, compare */ +#define DMA_T_T2_OVFL 6 /* Timer 2, overflow */ +#define DMA_T_T3_CH0 7 /* Timer 3, compare, channel 0 */ +#define DMA_T_T3_CH1 8 /* Timer 3, compare, channel 1 */ +#define DMA_T_T4_CH0 9 /* Timer 4, compare, channel 0 */ +#define DMA_T_T4_CH1 10 /* Timer 4, compare, channel 1 */ +#define DMA_T_ST 11 /* Sleep Timer compare */ +#define DMA_T_IOC_0 12 /* Port 0 I/O pin input transition */ +#define DMA_T_IOC_1 13 /* Port 1 I/O pin input transition */ +#define DMA_T_URX0 14 /* USART0 RX complete */ +#define DMA_T_UTX0 15 /* USART0 TX complete */ +#define DMA_T_URX1 16 /* USART1 RX complete */ +#define DMA_T_UTX1 17 /* USART1 TX complete */ +#define DMA_T_FLASH 18 /* Flash data write complete */ +#define DMA_T_RADIO 19 /* RF packet byte received/transmit */ +#define DMA_T_ADC_CHALL 20 /* ADC end of a conversion in a sequence */ +#define DMA_T_ADC_CH11 21 /* ADC end of conversion channel 0 in sequence */ +#define DMA_T_ADC_CH21 22 /* ADC end of conversion channel 1 in sequence */ +#define DMA_T_ADC_CH32 23 /* ADC end of conversion channel 2 in sequence */ +#define DMA_T_ADC_CH42 24 /* ADC end of conversion channel 3 in sequence */ +#define DMA_T_ADC_CH53 25 /* ADC end of conversion channel 4 in sequence */ +#define DMA_T_ADC_CH63 26 /* ADC end of conversion channel 5 in sequence */ +#define DMA_T_ADC_CH74 27 /* ADC end of conversion channel 6 in sequence */ +#define DMA_T_ADC_CH84 28 /* ADC end of conversion channel 7 in sequence */ +#define DMA_T_ENC_DW 29 /* AES processor requests download input data */ +#define DMA_T_ENC_UP 30 /* AES processor requests upload output data */ + +/* variable DMA length modes (VLEN) */ +#define DMA_VLEN_LEN (0 << 5) /* Use LEN for transfer count*/ +/* + * Transfer the number of bytes/words specified by first byte/word + 1 + * (up to a maximum specified by LEN). + * Thus transfer count excludes length byte/word. + */ +#define DMA_VLEN_N1 (1 << 5) + /* + * Transfer the number of bytes/words specified by first byte/word + * (up to a maximum specified by LEN). + * Thus transfer count includes length byte/word. + */ +#define DMA_VLEN_N (2 << 5) + /* + * Transfer the number of bytes/words specified by first byte/word + 2 + * (up to a maximum specified by LEN). + */ +#define DMA_VLEN_N2 (3 << 5) + /* + * Transfer the number of bytes/words specified by first byte/word + 3 + * (up to a maximum specified by LEN). + */ +#define DMA_VLEN_N3 (4 << 5) +#define DMA_VLEN_RES1 (5 << 5) /* reserved */ +#define DMA_VLEN_RES2 (6 << 5) /* reserved */ +#define DMA_VLEN_LEN2 (7 << 5) /* Use LEN for transfer count */ + +/* Transfer Types (Byte 6 [6:5]) */ +#define DMA_SINGLE 0x00 /* Single */ +#define DMA_BLOCK 0x20 /* Block */ +#define DMA_RPT_SINGLE 0x40 /* Repeated single */ +#define DMA_RPT_BLOCK 0x60 /* Repeated block */ + +/* Source Increment Modes (Byte 7 [7:6])*/ +#define DMA_SRC_INC_NO 0x00 /* Source No increment */ +#define DMA_SRC_INC_1 0x40 /* Source Increment 1 */ +#define DMA_SRC_INC_2 0x80 /* Source Increment 2 */ +#define DMA_SRC_DEC 0xC0 /* Source Decrement 1 */ +/* Source Increment Modes (Byte 7 [5:4])*/ +#define DMA_DST_INC_NO 0x00 /* DestinationNo increment */ +#define DMA_DST_INC_1 0x10 /* Destination Increment 1 */ +#define DMA_DST_INC_2 0x20 /* Destination Increment 2 */ +#define DMA_DST_DEC 0x30 /* Destination Decrement 1 */ + +/* Descriptor Byte 7, Bits[3:0] */ +#define DMA_IRQ_MASK_ENABLE 0x08 +#define DMA_MODE_7_BIT 0x04 +#define DMA_PRIO_HIGHEST 0x03 +#define DMA_PRIO_HIGH 0x02 +#define DMA_PRIO_GUARANTEED 0x01 +#define DMA_PRIO_LOW 0x00 + +/** DMA configuration structure */ +typedef struct dma_config { + uint8_t src_h; /* source address high byte*/ + uint8_t src_l; /* source address low byte*/ + uint8_t dst_h; /* dest. address high byte*/ + uint8_t dst_l; /* dest. address low byte*/ + uint8_t len_h; /* [7:5] VLEN, [4:0] length high byte, 5 lowest bits*/ + uint8_t len_l; /* length low byte*/ + uint8_t wtt; /* 7: wordsize, [6:5] transfer mode, [4:0] trigger */ + /* [7:6] src inc, [5:4] dst_inc, 3: IRQ, 2: M8(vlen), [1-0] prio */ + uint8_t inc_prio; +} dma_config_t; + +#ifdef DMA_CONF_ON +#define DMA_ON DMA_CONF_ON +#else +#define DMA_ON 0 +#endif + +/* Number of DMA Channels and their Descriptors */ +#if DMA_ON +#define DMA_CHANNEL_COUNT 2 +extern dma_config_t dma_conf[DMA_CHANNEL_COUNT]; +#endif + +/* DMA-Related Macros */ +#define DMA_ARM(c) (DMAARM |= (1 << c)) /* Arm DMA Channel C */ +#define DMA_TRIGGER(c) (DMAREQ |= (1 << c)) /* Trigger DMA Channel C */ +/* + * Check Channel C for Transfer Status + * 1: Complete, Pending Interrupt, 0: Incomplete + */ +#define DMA_STATUS(c) (DMAIRQ &(1 << c)) +/* Abort Ongoing DMA Transfers on Channel C */ +#define DMA_ABORT(c) (DMAARM = ABORT | (1 << c)) +#define DMA_ABORT_ALL() (DMAARM = 0x9F) /* Abort ALL Ongoing DMA Transfers */ + +/* Functions Declarations */ +void dma_init(void); +void dma_associate_process (struct process * p, uint8_t c); + +/* Only link the ISR when DMA_ON is .... on */ +#if DMA_ON +void dma_isr( void ) __interrupt (DMA_VECTOR); +#endif + +#endif /*__DMA_H*/ diff --git a/cpu/cc253x/dev/dma_intr.c b/cpu/cc253x/dev/dma_intr.c new file mode 100644 index 000000000..9f2336293 --- /dev/null +++ b/cpu/cc253x/dev/dma_intr.c @@ -0,0 +1,68 @@ +/** + * \file + * DMA driver ISRs + * \author + * Original: Martti Huttunen + * Port: Zach Shelby + * + * DMA interrupt routines, must be stored in HOME bank + */ + +#include + +#include "contiki.h" + +#include "dev/dma.h" +#include "cc253x.h" + +#if DMA_ON +extern struct process * dma_callback[DMA_CHANNEL_COUNT]; +#endif + +/*---------------------------------------------------------------------------*/ +#ifdef HAVE_RF_DMA +extern void rf_dma_callback_isr(void); +#endif +#ifdef SPI_DMA_RX +extern void spi_rx_dma_callback(void); +#endif +/*---------------------------------------------------------------------------*/ +/** + * DMA interrupt service routine. + * + * if callback defined a poll is made to that process + */ +void +dma_isr(void) __interrupt (DMA_VECTOR) +{ +#if DMA_ON + uint8_t i; +#endif + EA=0; + DMAIF = 0; +#ifdef HAVE_RF_DMA + if((DMAIRQ & 1) != 0) { + DMAIRQ &= ~1; + DMAARM=0x81; + rf_dma_callback_isr(); + } +#endif +#ifdef SPI_DMA_RX + if((DMAIRQ & 0x08) != 0) { + DMAIRQ &= ~(1 << 3); + spi_rx_dma_callback(); + } +#endif +#if DMA_ON + for(i = 0; i < DMA_CHANNEL_COUNT; i++) { + if((DMAIRQ & (1 << i)) != 0) { + DMAIRQ &= ~(1 << i); + if(dma_callback[i] != 0) { + process_poll(dma_callback[i]); + } + } + } +#endif + EA = 1; +} +/*---------------------------------------------------------------------------*/ diff --git a/cpu/cc253x/dev/lpm.h b/cpu/cc253x/dev/lpm.h new file mode 100644 index 000000000..4a8f14710 --- /dev/null +++ b/cpu/cc253x/dev/lpm.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2010, Loughborough University - Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * Header file for the cc2430 Low Power Modes (LPM) + * We currently support the following: + * - Set MCU IDLE while in PM0. This is working as intended + * - Drop to PM1. This results in incoming radio packet losses. + * + * \author + * George Oikonomou - + */ +#ifndef __LPM_H__ +#define __LPM_H__ + +#include "contiki-conf.h" + +#define LPM_MODE_NONE 0 /* No LPM - Always on */ +#define LPM_MODE_IDLE 1 /* Set MCU Idle as part of the main loop */ +#define LPM_MODE_PM2 2 /* Drop to PM1 - causes radio packet losses for now */ + +#ifdef LPM_CONF_MODE +#define LPM_MODE LPM_CONF_MODE +#else +#define LPM_MODE LPM_MODE_IDLE +#endif /* LPM_CONF_MODE */ + +#endif /* __LPM_H__ */ diff --git a/cpu/cc253x/dev/port.h b/cpu/cc253x/dev/port.h new file mode 100644 index 000000000..6fc69d10c --- /dev/null +++ b/cpu/cc253x/dev/port.h @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2011, George Oikonomou - + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * + * \author + * George Oikonomou - + */ + + +#ifndef PORT_H_ +#define PORT_H_ + +#include "cc253x.h" +#include "sfr-bits.h" +/*---------------------------------------------------------------------------*/ +/* Use these to configure your platform's hardware */ +#define PORT_FUNC_GPIO(port,pin) PORT_FUNC_GPIO_X(port,pin) +#define PORT_FUNC_PER(port,pin) PORT_FUNC_PER_X(port,pin) +#define PORT0_ANALOG_IO(pin) PORT0_ANALOG_IO_X(pin) +#define PORT0_DIGITAL_IO(pin) PORT0_DIGITAL_IO_X(pin) +#define PORT_SET(port,pin) PORT_SET_X(port,pin) +#define PORT_CLEAR(port,pin) PORT_CLEAR_X(port,pin) PORT_CLEAR_X(port,pin) +#define PORT_TOGGLE(port,pin) PORT_TOGGLE_X(port,pin) PORT_TOGGLE_X(port,pin) +#define PORT_READ(port,pin) PORT_READ_X(port,pin) +#define PORT_WRITE(port,pin,v) PORT_WRITE_X(port,pin,v) +#define PORT_DIR_OUTPUT(port,pin) PORT_DIR_OUTPUT_X(port,pin) +#define PORT_DIR_INPUT(port,pin) PORT_DIR_INPUT_X(port,pin) +#define PORT_IRQ_ENABLE(port,pin) PORT_IRQ_ENABLE_X(port,pin) +#define PORT_IRQ_DISABLE(port,pin) PORT_IRQ_DISABLE_X(port,pin) +#define PORT_IRQ_ENABLED(port,pin) PORT_IRQ_ENABLED_X(port,pin) +#define PORT_IRQ_CHECK(port,pin) PORT_IRQ_CHECK_X(port,pin) +#define PORT_IRQ_EDGE_FALL(port,pin) PORT_IRQ_EDGE_FALL_X(port,pin) +#define PORT_IRQ_EDGE_RISE(port,pin) PORT_IRQ_EDGE_RISE_X(port,pin) +#define PORT_IRQ_FLAG_OFF(port,pin) PORT_IRQ_FLAG_OFF_X(port,pin) +/*---------------------------------------------------------------------------*/ +/* Second Round of Macro Substitutions. Normally, you can stop reading here */ +/*---------------------------------------------------------------------------*/ +#define PORT_FUNC_GPIO_X(port,pin) do { P##port##SEL &= ~(1 << pin); } while(0) +#define PORT_FUNC_PER_X(port,pin) do { P##port##SEL |= 1 << pin; } while(0) +#define PORT0_ANALOG_IO_X(port,pin) do { APCFG |= 1 << pin; } while(0) +#define PORT0_DIGITAL_IO_X(port,pin) do { APCFG &= ~(1 << pin); } while(0) +#define PORT_SET_X(port,pin) do { P##port##_##pin = 1; } while(0) +#define PORT_CLEAR_X(port,pin) do { P##port##_##pin = 0; } while(0) +#define PORT_TOGGLE_X(port,pin) do { P##port##_##pin ^= 1; } while(0) +#define PORT_READ_X(port,pin) (P##port##_##pin) +#define PORT_WRITE_X(port,pin,v) do { P##port##_##pin = v;} while(0) +#define PORT_DIR_OUTPUT_X(port,pin) do { P##port##DIR |= 1 << pin; } while(0) +#define PORT_DIR_INPUT_X(port,pin) do { P##port##DIR &= ~(1 << pin); } while(0) +#define PORT_IRQ_ENABLE_X(port,pin) do { \ + P##port##IEN |= 1 << pin; \ + PORT##port##_IRQ_ENABLE(); \ +} while(0) +#define PORT_IRQ_DISABLE_X(port,pin) do { \ + P##port##IEN &= ~(1 << pin); \ + PORT##port##_IRQ_DISABLE(); \ +} while(0) +#define PORT_IRQ_ENABLED_X(port,pin) (P##port##IEN & (1 << pin)) +#define PORT_IRQ_CHECK_X(port,pin) (P##port##IFG & (1 << pin)) +#define PORT_IRQ_EDGE_FALL_X(port,pin) PORT##port##_IRQ_EDGE_FALL(pin) +#define PORT_IRQ_EDGE_RISE_X(port,pin) PORT##port##_IRQ_EDGE_RISE(pin) +#define PORT_IRQ_FLAG_OFF_X(port,pin) do { \ + P##port##IFG &= ~(1 << pin); \ + P##port##IF = 0; \ +} while(0) +/*---------------------------------------------------------------------------*/ +/* To handle SFR diversities + * - P0IE is in IEN1, which is bit-addressable, + * P1IE and P2IE are in IEN2, which is not bit-addressable + * - Edge detection (rising / falling) config is uniform for all pins in + * P0 and P2. For P1, low and high nibble bits are configured separately + * - Pullup/Pulldown/Tristate is quite different for each port + * + * You won't have to invoke these macros directly + */ +#define PORT0_IRQ_ENABLE() do { P0IE = 1; } while(0) +#define PORT0_IRQ_DISABLE() do { P0IE = 0; } while(0) +#define PORT1_IRQ_ENABLE() PORT_IRQ_EN_X(1) +#define PORT1_IRQ_DISABLE() PORT_IRQ_DIS_X(1) +#define PORT2_IRQ_ENABLE() PORT_IRQ_EN_X(2) +#define PORT2_IRQ_DISABLE() PORT_IRQ_DIS_X(2) + +#define PORT_IRQ_EN_X(port) do { IEN2 |= IEN2_P##port##IE; } while(0) +#define PORT_IRQ_DIS_X(port) do { IEN2 &= ~IEN2_P##port##IE; } while(0) +/*---------------------------------------------------------------------------*/ +#define PORT0_IRQ_EDGE_FALL(pin) PORT_IRQ_EDGE_F_X(0) +#define PORT0_IRQ_EDGE_RISE(pin) PORT_IRQ_EDGE_R_X(0) +#define PORT1_IRQ_EDGE_FALL(pin) PORT1_##pin##_IRQ_EDGE_F_X() +#define PORT1_IRQ_EDGE_RISE(pin) PORT1_##pin##_IRQ_EDGE_R_X() +#define PORT2_IRQ_EDGE_FALL(pin) PORT_IRQ_EDGE_F_X(2) +#define PORT2_IRQ_EDGE_RISE(pin) PORT_IRQ_EDGE_R_X(2) + +/* Ports 0 & 2 */ +#define PORT_IRQ_EDGE_F_X(port) do { PICTL |= PICTL_P##port##ICON; } while(0) +#define PORT_IRQ_EDGE_R_X(port) do { PICTL &= ~PICTL_P##port##ICON; } while(0) +/* Port 1 - High Nibble */ +#define PORT1_7_IRQ_EDGE_F_X() do { PICTL |= PICTL_P1ICONH; } while(0) +#define PORT1_7_IRQ_EDGE_R_X() do { PICTL &= ~PICTL_P1ICONH; } while(0) +#define PORT1_6_IRQ_EDGE_F_X() do { PICTL |= PICTL_P1ICONH; } while(0) +#define PORT1_6_IRQ_EDGE_R_X() do { PICTL &= ~PICTL_P1ICONH; } while(0) +#define PORT1_5_IRQ_EDGE_F_X() do { PICTL |= PICTL_P1ICONH; } while(0) +#define PORT1_5_IRQ_EDGE_R_X() do { PICTL &= ~PICTL_P1ICONH; } while(0) +#define PORT1_4_IRQ_EDGE_F_X() do { PICTL |= PICTL_P1ICONH; } while(0) +#define PORT1_4_IRQ_EDGE_R_X() do { PICTL &= ~PICTL_P1ICONH; } while(0) +/* Port 1 - Low Nibble */ +#define PORT1_3_IRQ_EDGE_F_X() do { PICTL |= PICTL_P1ICONL; } while(0) +#define PORT1_3_IRQ_EDGE_R_X() do { PICTL &= ~PICTL_P1ICONL; } while(0) +#define PORT1_2_IRQ_EDGE_F_X() do { PICTL |= PICTL_P1ICONL; } while(0) +#define PORT1_2_IRQ_EDGE_R_X() do { PICTL &= ~PICTL_P1ICONL; } while(0) +#define PORT1_1_IRQ_EDGE_F_X() do { PICTL |= PICTL_P1ICONL; } while(0) +#define PORT1_1_IRQ_EDGE_R_X() do { PICTL &= ~PICTL_P1ICONL; } while(0) +#define PORT1_0_IRQ_EDGE_F_X() do { PICTL |= PICTL_P1ICONL; } while(0) +#define PORT1_0_IRQ_EDGE_R_X() do { PICTL &= ~PICTL_P1ICONL; } while(0) +/*---------------------------------------------------------------------------*/ + +#endif /* __PORT_H__ */ diff --git a/cpu/cc253x/dev/random.c b/cpu/cc253x/dev/random.c new file mode 100644 index 000000000..cc99bbfcf --- /dev/null +++ b/cpu/cc253x/dev/random.c @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2011, George Oikonomou - + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * Random number generator routines exploiting the cc2530 hardware + * capabilities. + * + * This file overrides core/lib/random.c. + * + * \author + * George Oikonomou - + */ +#include "cc253x.h" +#include "sfr-bits.h" +#include "dev/cc2530-rf.h" +/*---------------------------------------------------------------------------*/ +/** + * \brief Generates a new random number using the cc253x RNG. + * \return The random number. + */ +unsigned short +random_rand(void) +{ + /* Clock the RNG LSFR once */ + ADCCON1 |= ADCCON1_RCTRL0; + + return (RNDL | (RNDH << 8)); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Seed the cc253x random number generator. + * \param seed Ignored. It's here because the function prototype is in core. + * + * We form a seed for the RNG by sampling IF_ADC as + * discussed in the user guide. + * Seeding with this method should not be done during + * normal radio operation. Thus, use this function before + * initialising the network. + */ +void +random_init(unsigned short seed) +{ + int i; + + /* Make sure the RNG is on */ + ADCCON1 &= ~(ADCCON1_RCTRL1 | ADCCON1_RCTRL0); + + /* Infinite RX */ + FRMCTRL0 = FRMCTRL0_RX_MODE1; + + /* Turn RF on */ + CC2530_CSP_ISRXON(); + + /* Wait until (user guide sec. 23.12, p 239) "the chip has been in RX long + * enough for the transients to have died out. A convenient way to do this is + * to wait for the RSSI-valid signal to go high." */ + while(!(RSSISTAT & RSSISTAT_RSSI_VALID)); + + /* + * Form the seed by concatenating bits from IF_ADC in the RF receive path. + * Keep sampling until we have read at least 16 bits AND the seed is valid + * + * Invalid seeds are 0x0000 and 0x8003 - User Guide (sec. 14.2.2 p. 146): + * "Note that a seed value of 0x0000 or 0x8003 always leads to an unchanged + * value in the LFSR after clocking, as no values are pushed in via in_bit + * (see Figure 14-1); hence, neither of these seed values should not be used + * for random-number generation." + */ + i = 0; + while(i < 16 || (seed == 0x0000 || seed == 0x8003)) { + seed = (seed << 1) | (RFRND & RFRND_IRND); + seed <<= 1; + i++; + } + + /* High byte first */ + RNDL = seed >> 8; + RNDL = seed & 0xFF; + + /* RF Off. NETSTACK_RADIO.init() will sort out normal RF operation */ + CC2530_CSP_ISRFOFF(); +} diff --git a/cpu/cc253x/dev/uart-intr.c b/cpu/cc253x/dev/uart-intr.c new file mode 100644 index 000000000..b70acfb03 --- /dev/null +++ b/cpu/cc253x/dev/uart-intr.c @@ -0,0 +1,70 @@ +/** + * \file + * + * uart write routines + * + * \author + * + * Anthony "Asterisk" Ambuehl + * + * interrupt routines which must be in HOME bank. handles received data from UART. + * + */ +#include "cc253x.h" + +#include "dev/uart0.h" +#include "dev/uart1.h" +#include "sys/energest.h" +#include "dev/leds.h" + +#if UART0_ENABLE +static int (*uart0_input_handler)(unsigned char c); +#endif +#if UART1_ENABLE +static int (*uart1_input_handler)(unsigned char c); +#endif + +#if UART0_ENABLE +/*---------------------------------------------------------------------------*/ +void +uart0_set_input(int (*input)(unsigned char c)) +{ + uart0_input_handler = input; +} +/*---------------------------------------------------------------------------*/ +#if UART0_CONF_WITH_INPUT +void +uart0_rx_isr(void) __interrupt (URX0_VECTOR) +{ + ENERGEST_ON(ENERGEST_TYPE_IRQ); + leds_toggle(LEDS_YELLOW); + URX0IF = 0; + if(uart0_input_handler != NULL) { + uart0_input_handler(U0DBUF); + } + ENERGEST_OFF(ENERGEST_TYPE_IRQ); +} +#endif +#endif /* UART0_ENABLE */ +#if UART1_ENABLE +/*---------------------------------------------------------------------------*/ +void +uart1_set_input(int (*input)(unsigned char c)) +{ + uart1_input_handler = input; +} +/*---------------------------------------------------------------------------*/ +#if UART_ONE_CONF_WITH_INPUT +void +uart1_rx_isr(void) __interrupt (URX1_VECTOR) +{ + ENERGEST_ON(ENERGEST_TYPE_IRQ); + URX1IF = 0; + if(uart1_input_handler != NULL) { + uart1_input_handler(U1DBUF); + } + ENERGEST_OFF(ENERGEST_TYPE_IRQ); +} +/*---------------------------------------------------------------------------*/ +#endif /* UART_ONE_CONF_WITH_INPUT */ +#endif /* UART1_ENABLE */ diff --git a/cpu/cc253x/dev/uart.h b/cpu/cc253x/dev/uart.h new file mode 100644 index 000000000..1a20fd530 --- /dev/null +++ b/cpu/cc253x/dev/uart.h @@ -0,0 +1,43 @@ +#ifndef UART_H +#define UART_H + +#include "contiki-conf.h" + +#include "cc253x.h" +#include "8051def.h" + +/*---------------------------------------------------------------------------*/ +/* UART BAUD Rates */ +/* + * Macro to set speed of UART N by setting the UnBAUD SFR to M and the + * UnGCR SRF to E. See the cc2530 datasheet for possible values of M and E + */ +#define UART_SET_SPEED(N, M, E) do{ U##N##BAUD = M; U##N##GCR = E; } while(0) + +/* + * Sample Values for M and E in the macro above to achieve some common BAUD + * rates. For more values, see the cc2430 datasheet + */ +/* 2000000 - cc2430 theoretical MAX when using the 32MHz clock */ +#define UART_2K_M 0 +#define UART_2K_E 16 +/* 1000000 - cc2430 theoretical MAX when using the 16MHz clock */ +#define UART_1K_M 0 +#define UART_1K_E 15 +/* 921600 */ +#define UART_921_M 216 +#define UART_921_E 14 +/* 460800 Higher values lead to problems when the node needs to RX */ +#define UART_460_M 216 +#define UART_460_E 13 +/* 115200 */ +#define UART_115_M 216 +#define UART_115_E 11 +/* 38400 */ +#define UART_38_M 59 +#define UART_38_E 10 +/* 9600 */ +#define UART_9_M 59 +#define UART_9_E 8 + +#endif /* UART_H */ diff --git a/cpu/cc253x/dev/uart0.c b/cpu/cc253x/dev/uart0.c new file mode 100644 index 000000000..ba7856e77 --- /dev/null +++ b/cpu/cc253x/dev/uart0.c @@ -0,0 +1,75 @@ +/** + * \file + * + * uart0 write routines + * + * \author + * + * Anthony "Asterisk" Ambuehl + * + */ +#include +#include + +#include "cc253x.h" +#include "sfr-bits.h" +#include "dev/uart0.h" + +#if UART0_ENABLE +/*---------------------------------------------------------------------------*/ +void +uart0_init() +{ +#if UART0_CONF_HIGH_SPEED + UART_SET_SPEED(0, UART_460_M, UART_460_E); +#else + UART_SET_SPEED(0, UART_115_M, UART_115_E); +#endif + +#ifdef UART0_ALTERNATIVE_2 + PERCFG |= PERCFG_U0CFG; / *alternative port 2 = P1.5-2 */ +#ifdef UART0_RTSCTS + P1SEL |= 0x3C; /* peripheral select for TX and RX, RTS, CTS */ +#else + P1SEL |= 0x30; /* peripheral select for TX and RX */ + P1 &= ~0x08; /* RTS down */ +#endif + P1DIR |= 0x28; /* RTS, TX out */ + P1DIR &= ~0x14; /* CTS & RX in */ +#else + PERCFG &= ~PERCFG_U0CFG; /* alternative port 1 = P0.5-2 */ +#ifdef UART0_RTSCTS + P0SEL |= 0x20 | 0x10; /* peripheral select for TX and RX */ +#else + P0SEL |= 0x0C; /* peripheral select for TX and RX */ + P0 &= ~0x20; /* RTS down */ +#endif + P0DIR |= 0x28; /* RTS, TX out */ + P0DIR &= ~0x14; /* CTS, RX in */ +#endif + + +#ifdef UART0_RTSCTS + U0UCR = 0x42; /*defaults: 8N1, RTS/CTS, high stop bit*/ +#else + U0UCR = 0x02; /*defaults: 8N1, no flow control, high stop bit*/ +#endif + + U0CSR = UCSR_MODE; /* UART mode */ + U0UCR = 0x80; /* Flush */ + UART0_RX_EN(); + + UART0_RX_INT(1); + U0DBUF = 0; +} +/*---------------------------------------------------------------------------*/ +/* Write one byte over the UART. */ +void +uart0_writeb(uint8_t byte) +{ + UTX0IF = 0; + U0DBUF = byte; + while(!UTX0IF); /* Wait until byte has been transmitted. */ + UTX0IF = 0; +} +#endif diff --git a/cpu/cc253x/dev/uart0.h b/cpu/cc253x/dev/uart0.h new file mode 100644 index 000000000..45839e120 --- /dev/null +++ b/cpu/cc253x/dev/uart0.h @@ -0,0 +1,41 @@ +#ifndef UART_0_H +#define UART_0_H + +#include "contiki-conf.h" + +#include "cc253x.h" +#include "8051def.h" +#include "uart.h" + +/*---------------------------------------------------------------------------*/ +/* UART0 Enable - Disable */ +#ifdef UART0_CONF_ENABLE +#define UART0_ENABLE UART0_CONF_ENABLE +#else +#define UART0_ENABLE 0 +#endif +/*---------------------------------------------------------------------------*/ +/* UART0 Function Declarations */ +#if UART0_ENABLE +void uart0_init(); +void uart0_writeb(uint8_t byte); + +void uart0_set_input(int (*input)(unsigned char c)); + +#if UART0_CONF_WITH_INPUT +void uart0_rx_isr( void ) __interrupt (URX0_VECTOR); +/* Macro to turn on / off UART RX Interrupt */ +#define UART0_RX_INT(v) do { URX0IE = v; } while(0) +#define UART0_RX_EN() do { U0CSR |= UCSR_RE; } while(0) +#else +#define UART0_RX_INT(v) +#define UART0_RX_EN() +#endif /* UART0_CONF_WITH_INPUT */ +#else +#define uart0_init(...) +#define uart0_writeb(...) +#define uart0_set_input(...) +#define UART0_RX_INT(v) +#define UART0_RX_EN() +#endif /* UART0_ENABLE */ +#endif /* UART_0_H */ diff --git a/cpu/cc253x/dev/uart1.c b/cpu/cc253x/dev/uart1.c new file mode 100644 index 000000000..8b3006c99 --- /dev/null +++ b/cpu/cc253x/dev/uart1.c @@ -0,0 +1,74 @@ +/** + * \file + * + * uart1 write routines + * + * \author + * + * Anthony "Asterisk" Ambuehl + * + */ +#include +#include + +#include "cc253x.h" +#include "dev/uart1.h" + +#if UART1_ENABLE +/*---------------------------------------------------------------------------*/ +/* UART1 initialization */ +void +uart1_init() +{ +#ifdef UART1_ALTERNATIVE_1 + PERCFG &= ~PERCFG_U1CFG; /*alternative port 1 = P0.5-2*/ +#ifdef UART1_RTSCTS + P0SEL |= 0x3C; /*peripheral select for TX and RX, RTS, CTS*/ +#else + P0SEL |= 0x30; /*peripheral select for TX and RX*/ + P0 &= ~0x08; /*RTS down*/ +#endif + P0DIR |= 0x18; /*RTS, TX out*/ + P0DIR &= ~0x24; /*CTS, RX in*/ +#else + PERCFG |= PERCFG_U1CFG; /*alternative port 2 = P1.7-4*/ +#ifdef UART1_RTSCTS + P1SEL |= 0xF0; /*peripheral select for TX and RX*/ +#else + P1SEL |= 0xC0; /*peripheral select for TX and RX*/ + P1 &= ~0x20; /*RTS down*/ +#endif + P1DIR |= 0x60; /*RTS, TX out*/ + P1DIR &= ~0x90; /*CTS, RX in*/ +#endif + +#if UART_ONE_CONF_HIGH_SPEED + UART_SET_SPEED(1, UART_460_M, UART_460_E); +#else + UART_SET_SPEED(1, UART_115_M, UART_115_E); +#endif + +#ifdef UART1_RTSCTS + U1UCR = 0x42; /*defaults: 8N1, RTS/CTS, high stop bit*/ +#else + U1UCR = 0x02; /*defaults: 8N1, no flow control, high stop bit*/ +#endif + + U1CSR = UCSR_MODE; /* UART mode */ + U1UCR = 0x80; /* Flush */ + + UART1_RX_INT(1); + U0DBUF = 0; +} +/*---------------------------------------------------------------------------*/ +/* Write one byte over the UART. */ +void +uart1_writeb(uint8_t byte) +{ + UTX1IF = 0; + U1DBUF = byte; + while(!UTX1IF); /* Wait until byte has been transmitted. */ + UTX1IF = 0; +} +/*---------------------------------------------------------------------------*/ +#endif diff --git a/cpu/cc253x/dev/uart1.h b/cpu/cc253x/dev/uart1.h new file mode 100644 index 000000000..aea8bec48 --- /dev/null +++ b/cpu/cc253x/dev/uart1.h @@ -0,0 +1,38 @@ +#ifndef UART_1_H +#define UART_1_H + +#include "contiki-conf.h" + +#include "cc253x.h" +#include "8051def.h" +#include "uart.h" + +/*---------------------------------------------------------------------------*/ +/* UART1 Enable - Disable */ +#ifdef UART1_CONF_ENABLE +#define UART1_ENABLE UART1_CONF_ENABLE +#else +#define UART1_ENABLE 0 +#endif +/*---------------------------------------------------------------------------*/ +/* UART1 Function Declarations */ +#if UART1_ENABLE +void uart1_init(); +void uart1_writeb(uint8_t byte); + +void uart1_set_input(int (*input)(unsigned char c)); +#if UART1_CONF_WITH_INPUT +void uart1_rx_isr( void ) __interrupt (URX1_VECTOR); +/* Macro to turn on / off UART RX Interrupt */ +#define UART1_RX_INT(v) do { URX1IE = v; } while(0) +#else +#define UART1_RX_INT(v) +#endif /* UART1_CONF_WITH_INPUT */ +#else +#define uart1_init(...) +#define uart1_writeb(...) +#define uart1_set_input(...) +#define UART1_RX_INT(v) +#endif /* UART1_ENABLE */ + +#endif /* UART_1_H */ diff --git a/cpu/cc253x/dev/watchdog.c b/cpu/cc253x/dev/watchdog.c new file mode 100644 index 000000000..92cf40f16 --- /dev/null +++ b/cpu/cc253x/dev/watchdog.c @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2010, Loughborough University - Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * Hardware-dependent functions for the cc253x watchdog. + * + * This file contains an ISR and must reside in the HOME bank. + * + * \author + * George Oikonomou - + */ + +#include "sys/energest.h" +#include "cc253x.h" +#include "sfr-bits.h" +#include "contiki-conf.h" + +#define WDT_TIMEOUT_MIN (WDCTL_INT1 | WDCTL_INT0) +/*---------------------------------------------------------------------------*/ +void +watchdog_init(void) +{ + WDCTL = 0; /* IDLE, Max Interval */ +} +/*---------------------------------------------------------------------------*/ +void +watchdog_start(void) +{ + WDCTL |= WDCTL_MODE1; /* Start in Watchdog mode */ +} +/*---------------------------------------------------------------------------*/ +void +watchdog_periodic(void) +{ + /* Write the 'clear' sequence while maintaining mode and interval setting */ + WDCTL = (WDCTL & 0x0F) | WDCTL_CLR3 | WDCTL_CLR1; + WDCTL = (WDCTL & 0x0F) | WDCTL_CLR2 | WDCTL_CLR0; +} +/*---------------------------------------------------------------------------*/ +void +watchdog_stop(void) +{ + /* In watchdog mode, stopping is impossible so we just reset the timer */ + watchdog_periodic(); +} +/*---------------------------------------------------------------------------*/ +void +watchdog_reboot(void) +{ + WDCTL = WDT_TIMEOUT_MIN; + /* Dis-acknowledge all interrupts while we wait for the dog to bark */ + DISABLE_INTERRUPTS(); + /* NOP till the dog barks... */ + while(1) { + __asm + nop + __endasm; + } +} diff --git a/cpu/cc2430/dev/rs232.c b/cpu/cc253x/mtarch.h similarity index 50% rename from cpu/cc2430/dev/rs232.c rename to cpu/cc253x/mtarch.h index 1dc233348..89d7766e2 100644 --- a/cpu/cc2430/dev/rs232.c +++ b/cpu/cc253x/mtarch.h @@ -1,19 +1,19 @@ /* - * Copyright (c) 2007, Takahide Matsutsuka. - * All rights reserved. + * Copyright (c) 2010, Loughborough University - Computer Science + * All rights reserved. * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided - * with the distribution. + * with the distribution. * 3. The name of the author may not be used to endorse or promote * products derived from this software without specific prior - * written permission. + * written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED @@ -25,52 +25,26 @@ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $Id: rs232.c,v 1.1 2009/09/08 20:07:35 zdshelby Exp $ + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ -/* - * \file - * This is RS-232C process based on polling. - * Note that rs232.c and rs232-slip.c cannot be used at the same time. - * \author - * Takahide Matsutsuka - */ -#include "contiki.h" -#include "dev/slip.h" -#include "dev/serial.h" -#include "dev/rs232.h" + /* + * \file + * Stub header file for multi-threading. It doesn't do anything, it + * just exists so that mt.c can compile cleanly. + * + * This is based on the original mtarch.h for z80 by Takahide Matsutsuka + * + * \author + * George Oikonomou - + */ +#ifndef __MTARCH_H__ +#define __MTARCH_H__ -PROCESS(rs232_process, "RS-232C polling process"); -/*---------------------------------------------------------------------------*/ -PROCESS_THREAD(rs232_process, ev, data) -{ - static struct etimer timer; - char ch; - unsigned char i, stat; - PROCESS_BEGIN(); +struct mtarch_thread { + unsigned char *sp; +}; - rs232_arch_init(RS232_BAUD_RATE); - etimer_set(&timer, CLOCK_SECOND / 16); +#endif /* __MTARCH_H__ */ - while(1) { - PROCESS_WAIT_EVENT(); - - if (etimer_expired(&timer)) { - for (i = 0; i < RS232_BUFSIZE; i++) { - ch = rs232_arch_poll(&stat); - if (stat == 0) { - break; - } - /* We have an input data */ - RS232_CALLBACK(ch); - } - etimer_reset(&timer); - } - } - - PROCESS_END(); -} -/*---------------------------------------------------------------------------*/ diff --git a/cpu/cc253x/rtimer-arch.c b/cpu/cc253x/rtimer-arch.c new file mode 100644 index 000000000..01512a724 --- /dev/null +++ b/cpu/cc253x/rtimer-arch.c @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2010, Loughborough University - Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + */ + +/** + * \file + * Hardware-dependent functions used to support the + * contiki rtimer module. + * + * clock_init() has set our tick speed prescaler already, so we + * are ticking with 500 kHz freq. + * + * Contiki typedefs rtimer_clock_t as unsigned short (16bit) + * It thus makes sense to use the 16bit timer (Timer 1) + * + * This file contains an ISR and must reside in the HOME bank + * + * \author + * George Oikonomou - + */ + +#include "sys/rtimer.h" +#include "sfr-bits.h" +#include "cc253x.h" +#include "sys/energest.h" + +#include "debug.h" +#include + +#define RT_MODE_COMPARE() do { T1CCTL1 |= T1CCTL_MODE; } while(0) +#define RT_MODE_CAPTURE() do { T1CCTL1 &= ~T1CCTL_MODE; } while(0) +/*---------------------------------------------------------------------------*/ +void +rtimer_arch_init(void) +{ + /* + * - Free running mode + * - Prescale by 32: + * Tick Speed has been prescaled to 500 kHz already in clock_init() + * We further prescale by 32 resulting in 15625 Hz for this timer. + */ + T1CTL = (T1CTL_DIV1 | T1CTL_MODE0); + + T1STAT = 0; + + /* Timer 1, Channel 1. Compare Mode (0x04), Interrupt mask on (0x40) */ + T1CCTL1 = T1CCTL_MODE | T1CCTL_IM; + + /* Interrupt Mask Flags: No interrupt on overflow */ + OVFIM = 0; + + /* Acknowledge Timer 1 Interrupts */ + T1IE = 1; +} +/*---------------------------------------------------------------------------*/ +void +rtimer_arch_schedule(rtimer_clock_t t) +{ + /* Switch to capture mode before writing T1CC1x and + * set the compare mode values so we can get an interrupt after t */ + RT_MODE_CAPTURE(); + T1CC1L = (unsigned char) t; + T1CC1H = (unsigned char) (t >> 8); + RT_MODE_COMPARE(); + + /* Turn on compare mode interrupt */ + T1STAT = 0; + T1CCTL1 |= T1CCTL_IM; +} +/*---------------------------------------------------------------------------*/ +void +rtimer_isr(void) __interrupt(T1_VECTOR) +{ + T1IE = 0; /* Ignore Timer 1 Interrupts */ + ENERGEST_ON(ENERGEST_TYPE_IRQ); + + /* No more interrupts from Channel 1 till next rtimer_arch_schedule() call */ + T1STAT &= ~T1STAT_CH1IF; + T1CCTL1 &= ~T1CCTL_IM; + + rtimer_run_next(); + + ENERGEST_OFF(ENERGEST_TYPE_IRQ); + T1IE = 1; /* Acknowledge Timer 1 Interrupts */ +} diff --git a/cpu/cc253x/rtimer-arch.h b/cpu/cc253x/rtimer-arch.h new file mode 100644 index 000000000..d261a95e9 --- /dev/null +++ b/cpu/cc253x/rtimer-arch.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2007, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + * $Id: rtimer-arch.h,v 1.1 2009/09/08 20:07:35 zdshelby Exp $ + */ + +/** + * \file + * Hardware-dependent function declarations used to + * support the contiki rtimer module. + * + * \author + * Zach Shelby (Original) + * George Oikonomou - + * (rtimer-arch implementation for cc2430 and then cc253x) + */ + +#ifndef __RTIMER_ARCH_H__ +#define __RTIMER_ARCH_H__ + +#include "contiki-conf.h" +#include "cc253x.h" + +/* + * 32 MHz clock, prescaled down to 500 kHz for all 4 timers in clock_init(). + * Further prescaled factor 32 for T1, thus T1 is 15625 Hz + */ +#define RTIMER_ARCH_SECOND (15625U) + +#define rtimer_arch_now() (T1CNTL + (T1CNTH << 8)) + +void rtimer_isr(void) __interrupt(T1_VECTOR); + +#endif /* __RTIMER_ARCH_H__ */ diff --git a/cpu/cc253x/segment.rules b/cpu/cc253x/segment.rules new file mode 100644 index 000000000..594675d03 --- /dev/null +++ b/cpu/cc253x/segment.rules @@ -0,0 +1,22 @@ +# segment.rules files assign source code modules to specific banks +# These files are only used when we build code with banking (HAVE_BANKING=1) +# The final segment.rules file is constructed from any segment.rules found in +# the search path, defined in the CPU Makefile +# When building bankable code, the bank-alloc.py script automatically allocates +# modules to banks. segment.rules files provide hints, instructing the script +# as to which files are safe to move around and which files to leave alone +# In other words, only specify a rule for a file if you need to +# comments starting with "#" are supported +# The file spec in rules is actually interpreted as a python regex so you can +# write a rule that will match multiple files +# +# general rules -- +# This file is only used when the Makefile defines HAVE_BANKING=1 +# SDCC's standard libraries will always go in CSEG - We don't touch them +# Interrupt code must be in HOME. Specify all files with an ISR here +# All files without an associated rule get allocated to a bank automatically + +# Files with ISRs must be in HOME +HOME intr.c # Match all files ending in intr.c (e.g. uart-intr.c) +HOME rtimer-arch.c +HOME clock.c diff --git a/cpu/cc253x/sfr-bits.h b/cpu/cc253x/sfr-bits.h new file mode 100644 index 000000000..a3a48be95 --- /dev/null +++ b/cpu/cc253x/sfr-bits.h @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2011, George Oikonomou - + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * Header file with definitions of bit masks for some cc2530 SFRs + * + * \author + * George Oikonomou - + */ + + +#ifndef SFR_BITS_H_ +#define SFR_BITS_H_ + +/* CLKCON */ +#define CLKCONCMD_OSC32K 0x80 +#define CLKCONCMD_OSC 0x40 +#define CLKCONCMD_TICKSPD2 0x20 +#define CLKCONCMD_TICKSPD1 0x10 +#define CLKCONCMD_TICKSPD0 0x08 +#define CLKCONCMD_CLKSPD2 0x04 +#define CLKCONCMD_CLKSPD1 0x02 +#define CLKCONCMD_CLKSPD0 0x01 + +/* SLEEPCMD and SLEEPSTA */ +#define SLEEP_OSC32K_CALDIS 0x80 +#define SLEEP_XOSC_STB 0x40 +#define SLEEP_HFRC_STB 0x20 +#define SLEEP_RST1 0x10 /* SLEEPSTA only */ +#define SLEEP_RST0 0x08 /* SLEEPSTA only */ +#define SLEEP_OSC_PD 0x04 +#define SLEEP_MODE1 0x02 +#define SLEEP_MODE0 0x01 + +/* PCON */ +#define PCON_IDLE 0x01 + +/* T1CTL */ +#define T1CTL_DIV1 0x08 +#define T1CTL_DIV0 0x04 +#define T1CTL_MODE1 0x02 +#define T1CTL_MODE0 0x01 + +/* T1CCTLx */ +#define T1CCTL_RFIRQ 0x80 +#define T1CCTL_IM 0x40 +#define T1CCTL_CMP2 0x20 +#define T1CCTL_CMP1 0x10 +#define T1CCTL_CMP0 0x08 +#define T1CCTL_MODE 0x04 +#define T1CCTL_CAP1 0x02 +#define T1CCTL_CAP0 0x01 + +/* T1STAT */ +#define T1STAT_OVFIF 0x20 +#define T1STAT_CH4IF 0x10 +#define T1STAT_CH3IF 0x08 +#define T1STAT_CH2IF 0x04 +#define T1STAT_CH1IF 0x02 +#define T1STAT_CH0IF 0x01 + +/* WDCTL */ +#define WDCTL_CLR3 0x80 +#define WDCTL_CLR2 0x40 +#define WDCTL_CLR1 0x20 +#define WDCTL_CLR0 0x10 +#define WDCTL_MODE1 0x04 +#define WDCTL_MODE0 0x04 +#define WDCTL_INT1 0x02 +#define WDCTL_INT0 0x01 + +/* ADCCON1 */ +#define ADCCON1_EOC 0x80 +#define ADCCON1_ST 0x40 +#define ADCCON1_STSEL1 0x20 +#define ADCCON1_STSEL0 0x10 +/* ADCCON1 - RNG bits */ +#define ADCCON1_RCTRL1 0x08 +#define ADCCON1_RCTRL0 0x04 + +/* ADCCON3 */ +#define ADCCON3_EREF1 0x80 +#define ADCCON3_EREF0 0x40 +#define ADCCON3_EDIV1 0x20 +#define ADCCON3_EDIV0 0x10 +#define ADCCON3_ECH3 0x08 +#define ADCCON3_ECH2 0x04 +#define ADCCON3_ECH1 0x02 +#define ADCCON3_ECH0 0x01 + +/* PERCFG */ +#define PERCFG_T1CFG 0x40 +#define PERCFG_T3CFG 0x20 +#define PERCFG_T4CFG 0x10 +#define PERCFG_U1CFG 0x02 +#define PERCFG_U0CFG 0x01 + +/* UxCSR */ +#define UCSR_MODE 0x80 +#define UCSR_RE 0x40 +#define UCSR_SLAVE 0x20 +#define UCSR_FE 0x10 +#define UCSR_ERR 0x08 +#define UCSR_RX_BYTE 0x04 +#define UCSR_TX_BYTE 0x02 +#define UCSR_ACTIVE 0x01 + +/* IEN2 */ +#define IEN2_WDTIE 0x20 +#define IEN2_P1IE 0x10 +#define IEN2_UTX1IE 0x08 +#define IEN2_UTX0IE 0x04 +#define IEN2_P2IE 0x02 +#define IEN2_RFIE 0x01 + +/* PICTL */ +#define PICTL_PADSC 0x40 +#define PICTL_P2ICON 0x08 +#define PICTL_P1ICONH 0x04 +#define PICTL_P1ICONL 0x02 +#define PICTL_P0ICON 0x01 +/*--------------------------------------------------------------------------- + * XREG bits, excluding RF and USB + *---------------------------------------------------------------------------*/ +/* FCTL */ +#define FCTL_BUSY 0x80 +#define FCTL_FULL 0x40 +#define FCTL_ABORT 0x20 +#define FCTL_CM1 0x08 +#define FCTL_CM0 0x04 +#define FCTL_WRITE 0x02 +#define FCTL_ERASE 0x01 +/*--------------------------------------------------------------------------- + * Radio Register Bits + *---------------------------------------------------------------------------*/ +/* FRMCTRL0 */ +#define FRMCTRL0_APPEND_DATA_MODE 0x80 +#define FRMCTRL0_AUTOCRC 0x40 +#define FRMCTRL0_AUTOACK 0x20 +#define FRMCTRL0_ENERGY_SCAN 0x10 +#define FRMCTRL0_RX_MODE1 0x08 +#define FRMCTRL0_RX_MODE0 0x04 +#define FRMCTRL0_TX_MODE1 0x02 +#define FRMCTRL0_TX_MODE0 0x01 + +/* FRMCTRL1 */ +#define FRMCTRL1_PENDING_OR 0x04 +#define FRMCTRL1_IGNORE_TX_UNDERF 0x02 +#define FRMCTRL1_SET_RXENMASK_ON_TX 0x01 + +/* FSMSTAT1 */ +#define FSMSTAT1_FIFO 0x80 +#define FSMSTAT1_FIFOP 0x40 +#define FSMSTAT1_SFD 0x20 +#define FSMSTAT1_CCA 0x10 +#define FSMSTAT1_TX_ACTIVE 0x02 +#define FSMSTAT1_RX_ACTIVE 0x01 + +/* RSSISTAT */ +#define RSSISTAT_RSSI_VALID 0x01 + +/* RFRND */ +#define RFRND_QRND 0x02 +#define RFRND_IRND 0x01 + +#endif /* SFR_BITS_H_ */ diff --git a/cpu/cc253x/soc.c b/cpu/cc253x/soc.c new file mode 100644 index 000000000..36d9531e4 --- /dev/null +++ b/cpu/cc253x/soc.c @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2011, George Oikonomou - + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * Init routine for the cc2530 SoC + * + * Bankable + * + * \author + * George Oikonomou - + */ +#include "cc253x.h" +#include "8051def.h" +#include "sfr-bits.h" + +void +soc_init() +{ + /* Flash: Cache with Pre-fetch */ + FCTL = FCTL_CM0; + + /* Enable Global Interrupt */ + ENABLE_INTERRUPTS(); +} + diff --git a/cpu/cc253x/soc.h b/cpu/cc253x/soc.h new file mode 100644 index 000000000..81888e2ab --- /dev/null +++ b/cpu/cc253x/soc.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2011, George Oikonomou - + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * Header file for cc253x SoC hardware init routines + * + * \author + * George Oikonomou - + */ + + +#ifndef __SOC_H__ +#define __SOC_H__ + +void soc_init(); + +#endif /* __SOC_H__ */ diff --git a/examples/cc2530dk/Makefile b/examples/cc2530dk/Makefile new file mode 100644 index 000000000..acffeada8 --- /dev/null +++ b/examples/cc2530dk/Makefile @@ -0,0 +1,6 @@ +CONTIKI_PROJECT = hello-world blink-hello timer-test sensors-demo + +all: $(CONTIKI_PROJECT) + +CONTIKI = ../.. +include $(CONTIKI)/Makefile.include diff --git a/examples/cc2530dk/Makefile.target b/examples/cc2530dk/Makefile.target new file mode 100644 index 000000000..70609bbdb --- /dev/null +++ b/examples/cc2530dk/Makefile.target @@ -0,0 +1 @@ +TARGET = cc2530dk diff --git a/examples/cc2530dk/blink-hello.c b/examples/cc2530dk/blink-hello.c new file mode 100644 index 000000000..98ed76b10 --- /dev/null +++ b/examples/cc2530dk/blink-hello.c @@ -0,0 +1,62 @@ +/* This is a very simple hello_world program. + * It aims to demonstrate the co-existence of two processes: + * One of them prints a hello world message and the other blinks the LEDs + * + * It is largely based on hello_world in $(CONTIKI)/examples/sensinode + * + * Author: George Oikonomou - + */ + +#include "contiki.h" +#include "dev/leds.h" + +#include /* For printf() */ +/*---------------------------------------------------------------------------*/ +static struct etimer et_hello; +static struct etimer et_blink; +static uint16_t count; +static uint8_t blinks; +/*---------------------------------------------------------------------------*/ +PROCESS(hello_world_process, "Hello world process"); +PROCESS(blink_process, "LED blink process"); +AUTOSTART_PROCESSES(&hello_world_process, &blink_process); +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(hello_world_process, ev, data) +{ + PROCESS_BEGIN(); + + etimer_set(&et_hello, CLOCK_SECOND * 4); + count = 0; + + while(1) { + PROCESS_WAIT_EVENT(); + + if(ev == PROCESS_EVENT_TIMER) { + printf("Sensor says #%u\n", count); + count ++; + + etimer_reset(&et_hello); + } + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(blink_process, ev, data) +{ + PROCESS_BEGIN(); + + while(1) { + etimer_set(&et_blink, CLOCK_SECOND); + + PROCESS_WAIT_EVENT_UNTIL(ev == PROCESS_EVENT_TIMER); + + blinks = leds_get(); + leds_off(LEDS_ALL); + leds_on((blinks + 1) & LEDS_ALL); + printf("Blink... (state %0.2X)\n", leds_get()); + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ diff --git a/examples/cc2530dk/border-router/Makefile b/examples/cc2530dk/border-router/Makefile new file mode 100644 index 000000000..eb8b69c2b --- /dev/null +++ b/examples/cc2530dk/border-router/Makefile @@ -0,0 +1,15 @@ +DEFINES+=PROJECT_CONF_H=\"project-conf.h\" + +# We need uIPv6, therefore we also need banking +HAVE_BANKING=1 +UIP_CONF_IPV6=1 + +PROJECT_SOURCEFILES += slip-bridge.c + +CONTIKI_PROJECT = border-router + +all: $(CONTIKI_PROJECT) + +CONTIKI = ../../.. + +include $(CONTIKI)/Makefile.include diff --git a/examples/cc2530dk/border-router/Makefile.target b/examples/cc2530dk/border-router/Makefile.target new file mode 100644 index 000000000..70609bbdb --- /dev/null +++ b/examples/cc2530dk/border-router/Makefile.target @@ -0,0 +1 @@ +TARGET = cc2530dk diff --git a/examples/cc2530dk/border-router/README b/examples/cc2530dk/border-router/README new file mode 100644 index 000000000..3df598278 --- /dev/null +++ b/examples/cc2530dk/border-router/README @@ -0,0 +1,16 @@ +border-router example for the TI SmartRF05EB with a cc2530EM. + +This example is meant to be used with tunslip6 in tools/ + +- Build the code and load it onto your node +- Connect your node to your PC +- run: + sudo ./tunslip6 -s /dev/ttyUSBx
/ + + This will setup tun0 on your PC over device /dev/ttyUSBx. The address + argument should contain the v6 address that you want to assign to tun0 + The node will use this address to obtain the network prefix + + for example: + sudo ./tunslip6 aaaa::1/64 + This will use aaaa:: / 64 as the prefix for the 15.4 network. diff --git a/examples/cc2530dk/border-router/border-router.c b/examples/cc2530dk/border-router/border-router.c new file mode 100644 index 000000000..50de6462a --- /dev/null +++ b/examples/cc2530dk/border-router/border-router.c @@ -0,0 +1,131 @@ +/* + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + */ + +#include "contiki.h" +#include "contiki-lib.h" +#include "contiki-net.h" + +#include + +#define DEBUG DEBUG_PRINT +#include "net/uip-debug.h" +#include "net/rpl/rpl.h" +#include "dev/watchdog.h" +#include "dev/slip.h" +#include "dev/leds.h" +#include "cc253x.h" + +static uint8_t prefix_set; +/*---------------------------------------------------------------------------*/ +PROCESS(border_router_process, "Border Router process"); +AUTOSTART_PROCESSES(&border_router_process); +/*---------------------------------------------------------------------------*/ +static void +print_local_addresses(void) +{ + int i; + uint8_t state; + + PRINTF("Router's IPv6 addresses:\n"); + for(i = 0; i < UIP_DS6_ADDR_NB; i++) { + state = uip_ds6_if.addr_list[i].state; + if(uip_ds6_if.addr_list[i].isused && (state == ADDR_TENTATIVE || state + == ADDR_PREFERRED)) { + PRINTF(" "); + PRINT6ADDR(&uip_ds6_if.addr_list[i].ipaddr); + PRINTF("\n"); + if (state == ADDR_TENTATIVE) { + uip_ds6_if.addr_list[i].state = ADDR_PREFERRED; + } + } + } +} +/*---------------------------------------------------------------------------*/ +void +request_prefix(void) { + /* mess up uip_buf with a dirty request... */ + uip_buf[0] = '?'; + uip_buf[1] = 'P'; + uip_len = 2; + slip_send(); + uip_len = 0; +} +/*---------------------------------------------------------------------------*/ +/* Set our prefix when we receive one over SLIP */ +void +set_prefix_64(uip_ipaddr_t *prefix_64) { + rpl_dag_t *dag; + uip_ipaddr_t ipaddr; + memcpy(&ipaddr, prefix_64, 16); + prefix_set = 1; + uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); + uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF); + + /* Become root of a new DODAG with ID our global v6 address */ + dag = rpl_set_root(RPL_DEFAULT_INSTANCE, &ipaddr); + if(dag != NULL) { + rpl_set_prefix(dag, &ipaddr, 64); + PRINTF("Created a new RPL dag with ID: "); + PRINT6ADDR(&dag->dag_id); + PRINTF("\n"); + } +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(border_router_process, ev, data) +{ + static struct etimer et; + + PROCESS_BEGIN(); + PRINTF("Border Router started\n"); + prefix_set = 0; + + leds_on(LEDS_RED); + + /* Request prefix until it has been received */ + while(!prefix_set) { + leds_on(LEDS_GREEN); + PRINTF("Prefix request.\n"); + etimer_set(&et, CLOCK_SECOND); + request_prefix(); + leds_off(LEDS_GREEN); + PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); + } + + /* We have created a new DODAG when we reach here */ + PRINTF("On Channel %u\n", (uint8_t)((FREQCTRL + 44) / 5)); + + print_local_addresses(); + + leds_off(LEDS_RED); + + PROCESS_EXIT(); + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ diff --git a/examples/cc2530dk/border-router/project-conf.h b/examples/cc2530dk/border-router/project-conf.h new file mode 100644 index 000000000..7f4c6aab1 --- /dev/null +++ b/examples/cc2530dk/border-router/project-conf.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2010, Loughborough University - Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * Project specific configuration defines for the border router / + * slip bridge example for cc253x. + * + * \author + * George Oikonomou - + */ + +#ifndef PROJECT_CONF_H_ +#define PROJECT_CONF_H_ + +#define VIZTOOL_MAX_PAYLOAD_LEN 120 +#define SLIP_ARCH_CONF_ENABLE 1 +#define LPM_CONF_MODE 0 + +#endif /* PROJECT_CONF_H_ */ diff --git a/examples/cc2530dk/border-router/slip-bridge.c b/examples/cc2530dk/border-router/slip-bridge.c new file mode 100644 index 000000000..dc8db1ab9 --- /dev/null +++ b/examples/cc2530dk/border-router/slip-bridge.c @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2010, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: slip-bridge.c,v 1.3 2010/06/08 19:53:49 nifi Exp $ + */ + +/** + * \file + * Slip fallback interface + * \author + * Niclas Finne + * Joakim Eriksson + * Joel Hoglund + * Nicolas Tsiftes + */ + +#include "net/uip.h" +#include "net/uip-ds6.h" +#include "net/rpl/rpl.h" +#include "dev/slip.h" +#include + +#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) + +#define DEBUG DEBUG_NONE +#include "net/uip-debug.h" + +void set_prefix_64(uip_ipaddr_t *); + +static uip_ipaddr_t last_sender; +/*---------------------------------------------------------------------------*/ +static void +slip_input_callback(void) +{ + PRINTF("SIN: %u\n", uip_len); + if((char) uip_buf[0] == '!') { + PRINTF("Got configuration message of type %c\n", uip_buf[1]); + uip_len = 0; + if((char)uip_buf[1] == 'P') { + uip_ipaddr_t prefix; + /* Here we set a prefix !!! */ + memset(&prefix, 0, 16); + memcpy(&prefix, &uip_buf[2], 8); + PRINTF("Setting prefix "); + PRINT6ADDR(&prefix); + PRINTF("\n"); + set_prefix_64(&prefix); + } + } + /* Save the last sender received over SLIP to avoid bouncing the + packet back if no route is found */ + uip_ipaddr_copy(&last_sender, &UIP_IP_BUF->srcipaddr); +} +#include "debug.h" + +/*---------------------------------------------------------------------------*/ +static void +init(void) +{ + process_start(&slip_process, NULL); + slip_set_input_callback(slip_input_callback); +} +/*---------------------------------------------------------------------------*/ +static void +output(void) +{ + if(uip_ipaddr_cmp(&last_sender, &UIP_IP_BUF->srcipaddr)) { + /* Do not bounce packets back over SLIP if the packet was received + over SLIP */ + PRINTF("slip-bridge: Destination off-link but no route\n"); + } else { + PRINTF("SUT: %u\n", uip_len); + slip_send(); + } +} +/*---------------------------------------------------------------------------*/ +struct uip_fallback_interface slip_interface = { + init, output +}; +/*---------------------------------------------------------------------------*/ diff --git a/examples/cc2530dk/hello-world.c b/examples/cc2530dk/hello-world.c new file mode 100644 index 000000000..ec3d2c3d6 --- /dev/null +++ b/examples/cc2530dk/hello-world.c @@ -0,0 +1,23 @@ +/** + * \file + * Basic hello world example + * \author + * Zach Shelby + */ + +#include "contiki.h" +#include /* For printf() */ +/*---------------------------------------------------------------------------*/ +PROCESS(hello_world_process, "Hello world process"); +AUTOSTART_PROCESSES(&hello_world_process); +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(hello_world_process, ev, data) +{ + + PROCESS_BEGIN(); + + printf("Hello World!\n"); + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ diff --git a/examples/cc2530dk/sensors-demo.c b/examples/cc2530dk/sensors-demo.c new file mode 100644 index 000000000..5707fc96b --- /dev/null +++ b/examples/cc2530dk/sensors-demo.c @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2010, Loughborough University - Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * Example to demonstrate-test cc2530 sensor functionality + * + * B1 turns LED_GREEN on and off. + * + * The node takes readings from the various sensors every x seconds and + * prints out the results. + * + * We use floats here to translate the AD conversion results to + * meaningful values. However, our printf does not have %f support so + * we use an ugly hack to print out the value by extracting the integral + * part and then the fractional part. Don't try this at home. + * + * Temperature: + * Math is correct, the sensor needs calibration per device. + * I currently use default values for the math which may result in + * very incorrect values in degrees C. + * See TI Design Note DN102 about the offset calibration. + * + * Supply Voltage (VDD): + * For VDD, math is correct, conversion is correct. + * See DN101 for details. + * + * Make sure you enable/disable things in contiki-conf.h + * + * \author + * George Oikonomou - + */ + +#include "contiki.h" +#include "contiki-conf.h" +#include "dev/leds.h" + +#include "dev/button-sensor.h" +#include "dev/adc-sensor.h" + +#define DEBUG 1 + +#if DEBUG +#include +#define PRINTF(...) printf(__VA_ARGS__) +#else /* DEBUG */ +/* We overwrite (read as annihilate) all output functions here */ +#define PRINTF(...) +#endif /* DEBUG */ +/*---------------------------------------------------------------------------*/ +PROCESS(sensors_test_process, "Sensor Test Process"); +#if BUTTON_SENSOR_ON +PROCESS(buttons_test_process, "Button Test Process"); +AUTOSTART_PROCESSES(&sensors_test_process, &buttons_test_process); +#else +AUTOSTART_PROCESSES(&sensors_test_process); +#endif +/*---------------------------------------------------------------------------*/ +#if BUTTON_SENSOR_ON +PROCESS_THREAD(buttons_test_process, ev, data) +{ + struct sensors_sensor *sensor; + + PROCESS_BEGIN(); + + while (1) { + + PROCESS_WAIT_EVENT_UNTIL(ev == sensors_event); + + /* If we woke up after a sensor event, inform what happened */ + sensor = (struct sensors_sensor *)data; + if(sensor == &button_sensor) { + PRINTF("Button Press\n"); + leds_toggle(LEDS_GREEN); + } + } + + PROCESS_END(); +} +#endif +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(sensors_test_process, ev, data) +{ + static struct etimer et; + + /* Sensor Values */ + static int rv; + static struct sensors_sensor * sensor; + static float sane = 0; + static int dec; + static float frac; + + PROCESS_BEGIN(); + + PRINTF("========================\n"); + PRINTF("Starting Sensor Example.\n"); + PRINTF("========================\n"); + + /* Set an etimer. We take sensor readings when it expires and reset it. */ + etimer_set(&et, CLOCK_SECOND * 2); + + while (1) { + + PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); + + /* + * Request some ADC conversions + * Return value -1 means sensor not available or turned off in conf + */ + sensor = sensors_find(ADC_SENSOR); + if (sensor) { + PRINTF("------------------\n"); + leds_on(LEDS_RED); + /* + * Temperature: + * Using 1.25V ref. voltage (1250mV). + * Typical AD Output at 25°C: 1480 + * Typical Co-efficient : 4.5 mV/°C + * + * Thus, at 12bit decimation (and ignoring the VDD co-efficient as well + * as offsets due to lack of calibration): + * + * AD - 1480 + * T = 25 + --------- + * 4.5 + */ + rv = sensor->value(ADC_SENSOR_TYPE_TEMP); + if(rv != -1) { + sane = 25 + ((rv - 1480) / 4.5); + dec = sane; + frac = sane - dec; + PRINTF(" Temp=%d.%02u C (%d)\n", dec, (unsigned int)(frac*100), rv); + } + /* + * Power Supply Voltage. + * Using 1.25V ref. voltage. + * AD Conversion on VDD/3 + * + * Thus, at 12bit resolution: + * + * ADC x 1.25 x 3 + * Supply = -------------- V + * 2047 + */ + rv = sensor->value(ADC_SENSOR_TYPE_VDD); + if(rv != -1) { + sane = rv * 3.75 / 2047; + dec = sane; + frac = sane - dec; + PRINTF("Supply=%d.%02u V (%d)\n", dec, (unsigned int)(frac*100), rv); + /* Store rv temporarily in dec so we can use it for the battery */ + dec = rv; + } + /* + * Battery Voltage - ToDo + * rv = sensor->value(ADC_SENSOR_TYPE_BATTERY); + */ + + leds_off(LEDS_RED); + } + etimer_reset(&et); + } + PROCESS_END(); + } +/*---------------------------------------------------------------------------*/ diff --git a/examples/cc2530dk/sniffer/Makefile b/examples/cc2530dk/sniffer/Makefile new file mode 100644 index 000000000..d9491a92c --- /dev/null +++ b/examples/cc2530dk/sniffer/Makefile @@ -0,0 +1,10 @@ +DEFINES+=PROJECT_CONF_H +PROJECT_SOURCEFILES += stub-rdc.c + +CONTIKI_PROJECT = sniffer + +all: $(CONTIKI_PROJECT) + +CONTIKI = ../../.. + +include $(CONTIKI)/Makefile.include diff --git a/examples/cc2530dk/sniffer/Makefile.target b/examples/cc2530dk/sniffer/Makefile.target new file mode 100644 index 000000000..70609bbdb --- /dev/null +++ b/examples/cc2530dk/sniffer/Makefile.target @@ -0,0 +1 @@ +TARGET = cc2530dk diff --git a/examples/cc2530dk/sniffer/netstack.c b/examples/cc2530dk/sniffer/netstack.c new file mode 100644 index 000000000..2551f82fe --- /dev/null +++ b/examples/cc2530dk/sniffer/netstack.c @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2010, Loughborough University - Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * Stub file overriding core/net/netstack.c. What we want to achieve + * here is call netstack_init from main without initialising the RDC, + * MAC and Network layers. It will just turn on the radio instead. + * + * \author + * George Oikonomou - + */ + +#include "netstack.h" +/*---------------------------------------------------------------------------*/ +void +netstack_init(void) +{ + NETSTACK_RADIO.init(); +} +/*---------------------------------------------------------------------------*/ + diff --git a/examples/cc2530dk/sniffer/project-conf.h b/examples/cc2530dk/sniffer/project-conf.h new file mode 100644 index 000000000..564f4d760 --- /dev/null +++ b/examples/cc2530dk/sniffer/project-conf.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2010, Loughborough University - Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * Project specific configuration defines for the sniffer example. + * + * \author + * George Oikonomou - + */ + +#ifndef PROJECT_CONF_H_ +#define PROJECT_CONF_H_ + +#define CC2530_RF_CONF_HEXDUMP 1 +#define CC2530_RF_CONF_AUTOACK 0 +#define NETSTACK_CONF_RDC stub_rdc_driver +#define ADC_SENSOR_CONF_ON 0 +#define LPM_CONF_MODE 0 +#define UART0_CONF_HIGH_SPEED 1 + +#endif /* PROJECT_CONF_H_ */ diff --git a/examples/cc2530dk/sniffer/sniffer.c b/examples/cc2530dk/sniffer/sniffer.c new file mode 100644 index 000000000..2183f88d7 --- /dev/null +++ b/examples/cc2530dk/sniffer/sniffer.c @@ -0,0 +1,54 @@ +/* + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + */ + +#include "contiki.h" +#include "cc253x.h" + +#define DEBUG DEBUG_NONE +#include "net/uip-debug.h" + +/*---------------------------------------------------------------------------*/ +PROCESS(sniffer_process, "Sniffer process"); +AUTOSTART_PROCESSES(&sniffer_process); +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(sniffer_process, ev, data) +{ + + PROCESS_BEGIN(); + + PRINTF("Sniffer started\n"); + + /* Turn off RF Address Recognition - We need to accept all frames */ + FRMFILT0 &= ~0x01; + + PROCESS_EXIT(); + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ diff --git a/examples/cc2530dk/sniffer/stub-rdc.c b/examples/cc2530dk/sniffer/stub-rdc.c new file mode 100644 index 000000000..063a43659 --- /dev/null +++ b/examples/cc2530dk/sniffer/stub-rdc.c @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2010, Loughborough University - Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * Definition of a fake RDC driver to be used with passive + * examples. The sniffer will never send packets and it will never + * push incoming packets up the stack. We do this by defining this + * driver as our RDC. We then drop everything + * + * \author + * George Oikonomou - + */ + +#include "net/mac/mac.h" +#include "net/mac/rdc.h" +/*---------------------------------------------------------------------------*/ +static void +send(mac_callback_t sent, void *ptr) +{ + if(sent) { + sent(ptr, MAC_TX_OK, 1); + } +} +/*---------------------------------------------------------------------------*/ +static void +send_list(mac_callback_t sent, void *ptr, struct rdc_buf_list *list) +{ + if(sent) { + sent(ptr, MAC_TX_OK, 1); + } +} +/*---------------------------------------------------------------------------*/ +static void +input(void) +{ +} +/*---------------------------------------------------------------------------*/ +static int +on(void) +{ + return 1; +} +/*---------------------------------------------------------------------------*/ +static int +off(int keep_radio_on) +{ + return keep_radio_on; +} +/*---------------------------------------------------------------------------*/ +static unsigned short +cca(void) +{ + return 0; +} +/*---------------------------------------------------------------------------*/ +static void +init(void) +{ +} +/*---------------------------------------------------------------------------*/ +const struct rdc_driver stub_rdc_driver = { + "stub-rdc", + init, + send, + send_list, + input, + on, + off, + cca, +}; +/*---------------------------------------------------------------------------*/ diff --git a/examples/cc2530dk/timer-test.c b/examples/cc2530dk/timer-test.c new file mode 100644 index 000000000..6843e4df3 --- /dev/null +++ b/examples/cc2530dk/timer-test.c @@ -0,0 +1,139 @@ +/** + * \file + * Tests related to clocks and timers + * + * This is clock_test.c plus a small addition by George Oikonomou + * (Loughborough University) in order to test the rtimer + * + * \author + * Zach Shelby (Original) + * George Oikonomou - (rtimer code) + * + */ + +#include "contiki.h" +#include "sys/clock.h" +#include "sys/rtimer.h" +#include "dev/leds.h" + +#include + +/*---------------------------------------------------------------------------*/ +#define TEST_CLOCK_DELAY 1 +#define TEST_RTIMER 1 +#define TEST_ETIMER 1 +#define TEST_CLOCK_SECONDS 1 +/*---------------------------------------------------------------------------*/ +static struct etimer et; + +#if TEST_CLOCK_DELAY +static clock_time_t start_count, end_count, diff; +#endif + +#if TEST_CLOCK_SECONDS +static unsigned long sec; +#endif + +#if TEST_ETIMER +static clock_time_t count; +#endif + +#if TEST_RTIMER +static struct rtimer rt; +rtimer_clock_t rt_now, rt_for; +static clock_time_t ct; +#endif + +static uint8_t i; +/*---------------------------------------------------------------------------*/ +PROCESS(clock_test_process, "Clock test process"); +AUTOSTART_PROCESSES(&clock_test_process); +/*---------------------------------------------------------------------------*/ +#if TEST_RTIMER +void +rt_callback(struct rtimer *t, void *ptr) { + rt_now = RTIMER_NOW(); + ct = clock_time(); + printf("Task called at %u (clock = %u)\n", rt_now, ct); +} +#endif +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(clock_test_process, ev, data) +{ + + PROCESS_BEGIN(); + + etimer_set(&et, 2 * CLOCK_SECOND); + + PROCESS_YIELD(); + +#if TEST_CLOCK_DELAY + printf("Clock delay test, (10,000 x i) cycles:\n"); + i = 1; + while(i < 6) { + start_count = clock_time(); + clock_delay(10000 * i); + end_count = clock_time(); + diff = end_count - start_count; + printf("Delayed %u = %u ticks = ~%u ms\n", 10000 * i, diff, diff * 8); + i++; + } +#endif + +#if TEST_RTIMER + printf("Rtimer Test, 1 sec (%u rtimer ticks):\n", RTIMER_SECOND); + i = 0; + while(i < 5) { + etimer_set(&et, 2*CLOCK_SECOND); + printf("=======================\n"); + ct = clock_time(); + rt_now = RTIMER_NOW(); + rt_for = rt_now + RTIMER_SECOND; + printf("Now=%u (clock = %u) - For=%u\n", rt_now, ct, rt_for); + if (rtimer_set(&rt, rt_for, 1, + (void (*)(struct rtimer *, void *))rt_callback, NULL) != RTIMER_OK) { + printf("Error setting\n"); + } + + PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); + i++; + } +#endif + +#if TEST_ETIMER + printf("Clock tick and etimer test, 1 sec (%u clock ticks):\n", CLOCK_SECOND); + i = 0; + while(i < 10) { + etimer_set(&et, CLOCK_SECOND); + PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); + etimer_reset(&et); + + count = clock_time(); + printf("%u ticks\n", count); + + leds_toggle(LEDS_RED); + i++; + } +#endif + +#if TEST_CLOCK_SECONDS + printf("Clock seconds test (5s):\n"); + i = 0; + while(i < 10) { + etimer_set(&et, 5 * CLOCK_SECOND); + PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); + etimer_reset(&et); + + sec = clock_seconds(); + printf("%lu seconds\n", sec); + + leds_toggle(LEDS_GREEN); + i++; + } +#endif + + printf("Done!\n"); + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ diff --git a/examples/cc2530dk/udp-ipv6/Makefile b/examples/cc2530dk/udp-ipv6/Makefile new file mode 100644 index 000000000..f21c02ca2 --- /dev/null +++ b/examples/cc2530dk/udp-ipv6/Makefile @@ -0,0 +1,14 @@ +DEFINES+=PROJECT_CONF_H=\"project-conf.h\" + +HAVE_BANKING=1 +UIP_CONF_IPV6=1 + +PROJECT_SOURCEFILES += ping6.c + +CONTIKI_PROJECT = client server + +all: $(CONTIKI_PROJECT) + +CONTIKI = ../../.. + +include $(CONTIKI)/Makefile.include diff --git a/examples/cc2530dk/udp-ipv6/Makefile.target b/examples/cc2530dk/udp-ipv6/Makefile.target new file mode 100644 index 000000000..70609bbdb --- /dev/null +++ b/examples/cc2530dk/udp-ipv6/Makefile.target @@ -0,0 +1 @@ +TARGET = cc2530dk diff --git a/examples/cc2530dk/udp-ipv6/client.c b/examples/cc2530dk/udp-ipv6/client.c new file mode 100644 index 000000000..224a775af --- /dev/null +++ b/examples/cc2530dk/udp-ipv6/client.c @@ -0,0 +1,159 @@ +/* + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + */ + +#include "contiki.h" +#include "contiki-lib.h" +#include "contiki-net.h" + +#include +#include "dev/leds.h" +#include "dev/button-sensor.h" +#include "debug.h" + +#define DEBUG DEBUG_PRINT +#include "net/uip-debug.h" + +#define SEND_INTERVAL 2 * CLOCK_SECOND +#define MAX_PAYLOAD_LEN 40 + +static char buf[MAX_PAYLOAD_LEN]; + +/* Our destinations and udp conns. One link-local and one global */ +#define LOCAL_CONN_PORT 3001 +static struct uip_udp_conn *l_conn; +#if UIP_CONF_ROUTER +#define GLOBAL_CONN_PORT 3002 +static struct uip_udp_conn *g_conn; +#endif + +/*---------------------------------------------------------------------------*/ +PROCESS(udp_client_process, "UDP client process"); +#if BUTTON_SENSOR_ON +PROCESS_NAME(ping6_process); +AUTOSTART_PROCESSES(&udp_client_process, &ping6_process); +#else +AUTOSTART_PROCESSES(&udp_client_process); +#endif +/*---------------------------------------------------------------------------*/ +static void +tcpip_handler(void) +{ + leds_on(LEDS_GREEN); + if(uip_newdata()) { + putstring("0x"); + puthex(uip_datalen()); + putstring(" bytes response=0x"); + puthex((*(uint16_t *) uip_appdata) >> 8); + puthex((*(uint16_t *) uip_appdata) & 0xFF); + putchar('\n'); + } + leds_off(LEDS_GREEN); + return; +} +/*---------------------------------------------------------------------------*/ +static void +timeout_handler(void) +{ + static int seq_id; + struct uip_udp_conn * this_conn; + + leds_on(LEDS_RED); + memset(buf, 0, MAX_PAYLOAD_LEN); + seq_id++; + + /* evens / odds */ + if(seq_id & 0x01) { + this_conn = l_conn; + } else { + this_conn = g_conn; + if(uip_ds6_get_global(ADDR_PREFERRED) == NULL) { + return; + } + } + + PRINTF("Client to: "); + PRINT6ADDR(&this_conn->ripaddr); + + memcpy(buf, &seq_id, sizeof(seq_id)); + + PRINTF(" Remote Port %u,", UIP_HTONS(this_conn->rport)); + PRINTF(" (msg=0x%04x), %u bytes\n", *(uint16_t *) buf, sizeof(seq_id)); + + uip_udp_packet_send(this_conn, buf, sizeof(seq_id)); + leds_off(LEDS_RED); +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(udp_client_process, ev, data) +{ + static struct etimer et; + uip_ipaddr_t ipaddr; + + PROCESS_BEGIN(); + PRINTF("UDP client process started\n"); + + uip_ip6addr(&ipaddr,0xfe80,0,0,0,0x0215,0x2000,0x0002,0x2145); + /* new connection with remote host */ + l_conn = udp_new(&ipaddr, UIP_HTONS(3000), NULL); + if(!l_conn) { + PRINTF("udp_new l_conn error.\n"); + } + udp_bind(l_conn, UIP_HTONS(LOCAL_CONN_PORT)); + + PRINTF("Link-Local connection with "); + PRINT6ADDR(&l_conn->ripaddr); + PRINTF(" local/remote port %u/%u\n", + UIP_HTONS(l_conn->lport), UIP_HTONS(l_conn->rport)); + + uip_ip6addr(&ipaddr,0xaaaa,0,0,0,0x0215,0x2000,0x0002,0x2145); + g_conn = udp_new(&ipaddr, UIP_HTONS(3000), NULL); + if(!g_conn) { + PRINTF("udp_new g_conn error.\n"); + } + udp_bind(g_conn, UIP_HTONS(GLOBAL_CONN_PORT)); + + PRINTF("Global connection with "); + PRINT6ADDR(&g_conn->ripaddr); + PRINTF(" local/remote port %u/%u\n", + UIP_HTONS(g_conn->lport), UIP_HTONS(g_conn->rport)); + + etimer_set(&et, SEND_INTERVAL); + + while(1) { + PROCESS_YIELD(); + if(etimer_expired(&et)) { + timeout_handler(); + etimer_restart(&et); + } else if(ev == tcpip_event) { + tcpip_handler(); + } + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ diff --git a/examples/cc2530dk/udp-ipv6/ping6.c b/examples/cc2530dk/udp-ipv6/ping6.c new file mode 100644 index 000000000..f4cc073ab --- /dev/null +++ b/examples/cc2530dk/udp-ipv6/ping6.c @@ -0,0 +1,139 @@ +/* + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + */ + +#include "contiki.h" +#include "contiki-lib.h" +#include "contiki-net.h" +#include +#include + +#include "dev/button-sensor.h" +#include "debug.h" + +#define DEBUG 1 +#if DEBUG +#include +#define PRINTF(...) printf(__VA_ARGS__) +#define PRINT6ADDR(addr) PRINTF(" %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x ", ((u8_t *)addr)[0], ((u8_t *)addr)[1], ((u8_t *)addr)[2], ((u8_t *)addr)[3], ((u8_t *)addr)[4], ((u8_t *)addr)[5], ((u8_t *)addr)[6], ((u8_t *)addr)[7], ((u8_t *)addr)[8], ((u8_t *)addr)[9], ((u8_t *)addr)[10], ((u8_t *)addr)[11], ((u8_t *)addr)[12], ((u8_t *)addr)[13], ((u8_t *)addr)[14], ((u8_t *)addr)[15]) +#define PRINTLLADDR(lladdr) PRINTF(" %02x:%02x:%02x:%02x:%02x:%02x ",lladdr->addr[0], lladdr->addr[1], lladdr->addr[2], lladdr->addr[3],lladdr->addr[4], lladdr->addr[5]) +#else +#define PRINTF(...) +#define PRINT6ADDR(addr) +#endif + +#define PING6_NB 5 +#define PING6_DATALEN 16 + +#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) +#define UIP_ICMP_BUF ((struct uip_icmp_hdr *)&uip_buf[uip_l2_l3_hdr_len]) + +static struct etimer ping6_periodic_timer; +static u8_t count = 0; +static u16_t addr[8]; +static uip_ipaddr_t dest_addr; + +PROCESS(ping6_process, "PING6 process"); +/*---------------------------------------------------------------------------*/ +static void +ping6handler() +{ + if(count < PING6_NB) { + UIP_IP_BUF->vtc = 0x60; + UIP_IP_BUF->tcflow = 1; + UIP_IP_BUF->flow = 0; + UIP_IP_BUF->proto = UIP_PROTO_ICMP6; + UIP_IP_BUF->ttl = uip_ds6_if.cur_hop_limit; + uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, &dest_addr); + uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr); + + UIP_ICMP_BUF->type = ICMP6_ECHO_REQUEST; + UIP_ICMP_BUF->icode = 0; + /* set identifier and sequence number to 0 */ + memset((uint8_t *)UIP_ICMP_BUF + UIP_ICMPH_LEN, 0, 4); + /* put one byte of data */ + memset((uint8_t *)UIP_ICMP_BUF + UIP_ICMPH_LEN + UIP_ICMP6_ECHO_REQUEST_LEN, + count, PING6_DATALEN); + + + uip_len = UIP_ICMPH_LEN + UIP_ICMP6_ECHO_REQUEST_LEN + UIP_IPH_LEN + PING6_DATALEN; + UIP_IP_BUF->len[0] = (u8_t)((uip_len - 40) >> 8); + UIP_IP_BUF->len[1] = (u8_t)((uip_len - 40) & 0x00FF); + + UIP_ICMP_BUF->icmpchksum = 0; + UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum(); + + + PRINTF("Echo Request to"); + PRINT6ADDR(&UIP_IP_BUF->destipaddr); + PRINTF("from"); + PRINT6ADDR(&UIP_IP_BUF->srcipaddr); + PRINTF("\n"); + UIP_STAT(++uip_stat.icmp.sent); + + tcpip_ipv6_output(); + + count++; + etimer_set(&ping6_periodic_timer, 3 * CLOCK_SECOND); + } else { + count = 0; + } +} + +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(ping6_process, ev, data) +{ + + PROCESS_BEGIN(); + PRINTF("ping6 running.\n"); + PRINTF("Button 1: 5 pings 16 byte payload.\n"); + + uip_ip6addr(&dest_addr,0xaaaa,0,0,0,0x0215,0x2000,0x0002,0x2145); + count = 0; + + icmp6_new(NULL); + + while(1) { + PROCESS_YIELD(); + +#if BUTTON_SENSOR_ON + if(ev == sensors_event && data == &button_sensor && count == 0) { + ping6handler(); + } +#endif + if(ev == PROCESS_EVENT_TIMER && etimer_expired(&ping6_periodic_timer)) { + ping6handler(); + } + if(ev == tcpip_icmp6_event && *(uint8_t *)data == ICMP6_ECHO_REPLY) { + PRINTF("Echo Reply\n"); + } + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ diff --git a/examples/cc2530dk/udp-ipv6/project-conf.h b/examples/cc2530dk/udp-ipv6/project-conf.h new file mode 100644 index 000000000..990a02082 --- /dev/null +++ b/examples/cc2530dk/udp-ipv6/project-conf.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2010, Loughborough University - Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + * $Id$ + */ + +/** + * \file + * Project specific configuration defines for the UDP client/server + * example. + * + * \author + * George Oikonomou - + */ + +#ifndef PROJECT_CONF_H_ +#define PROJECT_CONF_H_ + +#define BUTTON_SENSOR_CONF_ON 1 +#define UIP_CONF_ICMP6 1 + +#endif /* PROJECT_CONF_H_ */ diff --git a/examples/cc2530dk/udp-ipv6/server.c b/examples/cc2530dk/udp-ipv6/server.c new file mode 100644 index 000000000..2d9ff70b7 --- /dev/null +++ b/examples/cc2530dk/udp-ipv6/server.c @@ -0,0 +1,174 @@ +/* + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + */ + +#include "contiki.h" +#include "contiki-lib.h" +#include "contiki-net.h" + +#include + +#define DEBUG DEBUG_PRINT +#include "net/uip-debug.h" +#include "dev/watchdog.h" +#include "dev/leds.h" +#include "net/rpl/rpl.h" +#include "dev/button-sensor.h" +#include "debug.h" + +#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) +#define UIP_UDP_BUF ((struct uip_udp_hdr *)&uip_buf[uip_l2_l3_hdr_len]) + +#define MAX_PAYLOAD_LEN 120 + +static struct uip_udp_conn *server_conn; +static char buf[MAX_PAYLOAD_LEN]; +static uint16_t len; + +#if UIP_CONF_ROUTER +static uip_ipaddr_t ipaddr; +#endif + +#define SERVER_REPLY 1 + +/* Should we act as RPL root? */ +#define SERVER_RPL_ROOT 1 +/*---------------------------------------------------------------------------*/ +PROCESS(udp_server_process, "UDP server process"); +AUTOSTART_PROCESSES(&udp_server_process); +/*---------------------------------------------------------------------------*/ +static void +tcpip_handler(void) +{ + memset(buf, 0, MAX_PAYLOAD_LEN); + if(uip_newdata()) { + leds_on(LEDS_RED); + len = uip_datalen(); + memcpy(buf, uip_appdata, len); + PRINTF("%u bytes from [", len, *(uint16_t *)buf); + PRINT6ADDR(&UIP_IP_BUF->srcipaddr); + PRINTF("]:%u\n", UIP_HTONS(UIP_UDP_BUF->srcport)); +#if SERVER_REPLY + uip_ipaddr_copy(&server_conn->ripaddr, &UIP_IP_BUF->srcipaddr); + server_conn->rport = UIP_UDP_BUF->srcport; + + uip_udp_packet_send(server_conn, buf, len); + /* Restore server connection to allow data from any node */ + uip_create_unspecified(&server_conn->ripaddr); + server_conn->rport = 0; +#endif + } + leds_off(LEDS_RED); + return; +} +/*---------------------------------------------------------------------------*/ +#if (BUTTON_SENSOR_ON && (DEBUG==DEBUG_PRINT)) +static void +print_stats() +{ + PRINTF("tl=%lu, ts=%lu, bs=%lu, bc=%lu\n", + rimestats.toolong, rimestats.tooshort, rimestats.badsynch, rimestats.badcrc); + PRINTF("llrx=%lu, lltx=%lu, rx=%lu, tx=%lu\n", + rimestats.llrx, rimestats.lltx, rimestats.rx, rimestats.tx); +} +#else +#define print_stats() +#endif +/*---------------------------------------------------------------------------*/ +static void +print_local_addresses(void) +{ + int i; + uint8_t state; + + PRINTF("Server IPv6 addresses:\n"); + for(i = 0; i < UIP_DS6_ADDR_NB; i++) { + state = uip_ds6_if.addr_list[i].state; + if(uip_ds6_if.addr_list[i].isused && (state == ADDR_TENTATIVE || state + == ADDR_PREFERRED)) { + PRINTF(" "); + PRINT6ADDR(&uip_ds6_if.addr_list[i].ipaddr); + PRINTF("\n"); + if (state == ADDR_TENTATIVE) { + uip_ds6_if.addr_list[i].state = ADDR_PREFERRED; + } + } + } +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(udp_server_process, ev, data) +{ +#if BUTTON_SENSOR_ON + static struct sensors_sensor *b1; +#endif +#if SERVER_RPL_ROOT + rpl_dag_t *dag; +#endif + PROCESS_BEGIN(); + putstring("Starting UDP server\n"); + +#if BUTTON_SENSOR_ON + putstring("Button 1: Print RIME stats\n"); +#endif + +#if SERVER_RPL_ROOT + uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); + uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); + uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF); + + print_local_addresses(); + + dag = rpl_set_root(RPL_DEFAULT_INSTANCE, &uip_ds6_get_global(ADDR_PREFERRED)->ipaddr); + if(dag != NULL) { + uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); + rpl_set_prefix(dag, &ipaddr, 64); + PRINTF("Created a new RPL dag with ID: "); + PRINT6ADDR(&dag->dag_id); + PRINTF("\n"); + } +#endif /* SERVER_RPL_ROOT */ + + server_conn = udp_new(NULL, UIP_HTONS(0), NULL); + udp_bind(server_conn, UIP_HTONS(3000)); + + PRINTF("Listen port: 3000, TTL=%u\n", server_conn->ttl); + + while(1) { + PROCESS_YIELD(); + if(ev == tcpip_event) { + tcpip_handler(); +#if BUTTON_SENSOR_ON + } else if(ev == sensors_event && data == &button_sensor) { + print_stats(); +#endif /* (CONTIKI_TARGET_SENSINODE && BUTTON_SENSOR_ON) */ + } + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ diff --git a/examples/er-rest-example/plugtest-server.c b/examples/er-rest-example/plugtest-server.c index 79a07be6d..2994cb6f7 100644 --- a/examples/er-rest-example/plugtest-server.c +++ b/examples/er-rest-example/plugtest-server.c @@ -99,14 +99,13 @@ test_handler(void* request, void* response, uint8_t *buffer, uint16_t preferred_ uint8_t method = REST.get_method_type(request); - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_response_payload(response, buffer, snprintf((char *)buffer, MAX_PLUGFEST_PAYLOAD, "Type: %u\nCode: %u\nMID: %u", coap_req->type, coap_req->code, coap_req->mid)); - PRINTF("/test "); if (method & METHOD_GET) { PRINTF("GET "); /* Code 2.05 CONTENT is default. */ + REST.set_header_content_type(response, REST.type.TEXT_PLAIN); + REST.set_response_payload(response, buffer, snprintf((char *)buffer, MAX_PLUGFEST_PAYLOAD, "Type: %u\nCode: %u\nMID: %u", coap_req->type, coap_req->code, coap_req->mid)); } else if (method & METHOD_POST) { @@ -215,7 +214,7 @@ separate_handler(void* request, void* response, uint8_t *buffer, uint16_t prefer } else { - PRINTF("ACKED "); + PRINTF("STORED "); separate_active = 1; /* Take over and skip response by engine. */ @@ -237,7 +236,7 @@ separate_periodic_handler(resource_t *resource) coap_transaction_t *transaction = NULL; if ( (transaction = coap_new_transaction(separate_store->request_metadata.mid, &separate_store->request_metadata.addr, separate_store->request_metadata.port)) ) { - PRINTF("RESPONSE"); + PRINTF("RESPONSE (%s %u)\n", separate_store->request_metadata.type==COAP_TYPE_CON?"CON":"NON", separate_store->request_metadata.mid); coap_packet_t response[1]; /* This way the packet can be treated as pointer as usual. */ @@ -262,7 +261,7 @@ separate_periodic_handler(resource_t *resource) return 1; } else { - PRINTF("ERROR (transaction)"); + PRINTF("ERROR (transaction)\n"); } } /* if (separate_active) */ diff --git a/examples/sensinode/Makefile b/examples/sensinode/Makefile index ef9bc6965..c3b33f6e4 100644 --- a/examples/sensinode/Makefile +++ b/examples/sensinode/Makefile @@ -2,7 +2,17 @@ ifndef TARGET TARGET=sensinode endif +# Make absolutely certain that you specify your device here +DEFINES+=MODEL_N740 + +# These examples don't need code banking so we turn it off +#HAVE_BANKING=1 + CONTIKI_PROJECT = hello_world clock_test rf_test_rx rf_test_tx + +# New examples added by George Oikonomou - Loughborough University +CONTIKI_PROJECT += timer-test blink-hello broadcast-rime + all: $(CONTIKI_PROJECT) CONTIKI = ../.. diff --git a/examples/sensinode/README b/examples/sensinode/README index a9bac42e1..04901ca45 100644 --- a/examples/sensinode/README +++ b/examples/sensinode/README @@ -1,6 +1,11 @@ Sensinode platform example and test applications - by Zach Shelby (zach@sensinode.com) +Some more examples by George Oikonomou - Loughborough University + cc2431-location-engine, udp-ipv6, broadcast-rime + blink-hello, event-post, timer-test + + This directory contains example and test applications for Sensinode CC2430 based devices. By default it is set to use the sensinode platform: @@ -32,8 +37,21 @@ These make options are defined in /platform/sensinode/Makefile.sensinode Descriptions of applications: -hello_world A simple hello world app. -clock_test Test and example of sys/clock.h related features. -rf_test_tx Test for transmitting packets -rf_test_rc Test for receiving packets - \ No newline at end of file +hello_world A simple hello world app. +clock_test Test and example of sys/clock.h related features. +rf_test_tx Test for transmitting packets +rf_test_rc Test for receiving packets + +Recent Additions: +udp-ipv6 UDP client-server example over uIPv6. Uses link-local and global + addresses. Button 1 on the client will send an echo request. +broadcast-rime Just a broadcast rime example, slightly modified +sensors Demonstrating button and ADC functionality +cc2431-location-engine + Example demonstrating the usage cc2431 location engine (blind node) + N.B. Not all sensinode devides have a cc2431 +event-post Demonstrating the interaction between two processes with custom events +blink-hello Hello World with LED blinking. +timer-test Same as clock_test above + testing the rtimer-arch code +border-router 802.15.4 to SLIP bridge example. The node will forward packets + from the 15.4 network to its UART (and thus a connected PC over SLIP) \ No newline at end of file diff --git a/examples/sensinode/blink-hello.c b/examples/sensinode/blink-hello.c new file mode 100644 index 000000000..593589041 --- /dev/null +++ b/examples/sensinode/blink-hello.c @@ -0,0 +1,91 @@ +/* This is a very simple hello_world program. + * It aims to demonstrate the co-existence of two processes: + * One of them prints a hello world message and the other blinks the LEDs + * + * It is largely based on hello_world in $(CONTIKI)/examples/sensinode + * + * Author: George Oikonomou + */ + +#include "contiki.h" +#include "dev/leds.h" + +#include /* For printf() */ +/*---------------------------------------------------------------------------*/ +/* We declare the two processes */ +PROCESS(hello_world_process, "Hello world process"); +PROCESS(blink_process, "LED blink process"); + +/* We require the processes to be started automatically */ +AUTOSTART_PROCESSES(&hello_world_process, &blink_process); +/*---------------------------------------------------------------------------*/ +/* Implementation of the first process */ +PROCESS_THREAD(hello_world_process, ev, data) +{ + /* variables are declared static to ensure their values are maintained + between subsequent calls. + All the code between PROCESS_THREAD and PROCESS_BEGIN() runs each time + the process is invoked. */ + static struct etimer timer; + static int count; + + /* any process must start with this. */ + PROCESS_BEGIN(); + + /* set the etimer module to generate an event in one second. + CLOCK_CONF_SECOND is #define as 128 */ + etimer_set(&timer, CLOCK_CONF_SECOND * 4); + count = 0; + /* Don't declare variables after PROCESS_BEGIN. + * While it will compile fine with TARGET=native (gcc is happy), + * SDCC doesn't like it. Soon as you try TARGET=sensinode you will get: + * syntax error: token -> 'int' ; + * Try uncommenting the line below and observe the results */ + /* int whoops = 0; + * whoops = 0; */ + while (1) + { + /* wait here for an event to happen */ + PROCESS_WAIT_EVENT(); + /* This achieves the same + * PROCESS_WAIT_EVENT_UNTIL(ev == PROCESS_EVENT_TIMER); */ + + /* if the event is the timer event as expected... */ + if(ev == PROCESS_EVENT_TIMER) + { + /* do the process work */ + printf("Sensor says no... #%d\r\n", count); + count ++; + + /* reset the timer so it will generate an other event + * the exact same time after it expired (periodicity guaranteed) */ + etimer_reset(&timer); + } + + /* and loop */ + } + /* any process must end with this, even if it is never reached. */ + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ +/* Implementation of the second process */ +PROCESS_THREAD(blink_process, ev, data) +{ + static struct etimer timer; + PROCESS_BEGIN(); + + while (1) + { + /* we set the timer from here every time */ + etimer_set(&timer, CLOCK_CONF_SECOND); + + /* and wait until the event we receive is the one we're waiting for */ + PROCESS_WAIT_EVENT_UNTIL(ev == PROCESS_EVENT_TIMER); + + printf("Blink... (state %0.2X).\r\n", leds_get()); + /* update the LEDs */ + leds_toggle(LEDS_GREEN); + } + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ diff --git a/examples/sensinode/border-router/Makefile b/examples/sensinode/border-router/Makefile new file mode 100644 index 000000000..b77479824 --- /dev/null +++ b/examples/sensinode/border-router/Makefile @@ -0,0 +1,19 @@ +ifndef TARGET +TARGET=sensinode +endif + +# Make absolutely certain that you specify your device here +DEFINES+=MODEL_N601,PROJECT_CONF_H + +# We need uIPv6, therefore we also need banking +HAVE_BANKING=1 +UIP_CONF_IPV6=1 + +PROJECT_SOURCEFILES += slip-bridge.c + +CONTIKI_PROJECT = border-router +all: $(CONTIKI_PROJECT) + +CONTIKI = ../../.. + +include $(CONTIKI)/Makefile.include diff --git a/examples/sensinode/border-router/README b/examples/sensinode/border-router/README new file mode 100644 index 000000000..060c48ea5 --- /dev/null +++ b/examples/sensinode/border-router/README @@ -0,0 +1,16 @@ +border-router example for sensinode devices. + +This example is meant to be used with tunslip6 in tools/ + +- Build the code and load it onto your node +- Connect your node to your PC over USB +- run: + sudo ./tunslip6
/ + + This will setup tun0 on your PC over device /dev/ttyUSBx. The address + argument should contain the v6 address that you want to assign to tun0 + The node will use this address to obtain the network prefix + + for example: + sudo ./tunslip6 aaaa::1/64 + This will use aaaa:: / 64 as the prefix for the 15.4 network. diff --git a/examples/sensinode/border-router/border-router.c b/examples/sensinode/border-router/border-router.c new file mode 100644 index 000000000..a59ce6e0b --- /dev/null +++ b/examples/sensinode/border-router/border-router.c @@ -0,0 +1,134 @@ +/* + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + */ + +#include "contiki.h" +#include "contiki-lib.h" +#include "contiki-net.h" + +#include + +#define DEBUG DEBUG_NONE +#include "net/uip-debug.h" +#include "net/rpl/rpl.h" +#include "dev/watchdog.h" +#include "dev/slip.h" +#include "dev/leds.h" + +#ifndef CC2430_RF_CONF_CHANNEL +#define CC2430_RF_CONF_CHANNEL 0xFF +#endif + +static uint8_t prefix_set; +/*---------------------------------------------------------------------------*/ +PROCESS(border_router_process, "Border Router process"); +AUTOSTART_PROCESSES(&border_router_process); +/*---------------------------------------------------------------------------*/ +static void +print_local_addresses(void) +{ + int i; + uint8_t state; + + PRINTF("Router's IPv6 addresses:\n"); + for(i = 0; i < UIP_DS6_ADDR_NB; i++) { + state = uip_ds6_if.addr_list[i].state; + if(uip_ds6_if.addr_list[i].isused && (state == ADDR_TENTATIVE || state + == ADDR_PREFERRED)) { + PRINTF(" "); + PRINT6ADDR(&uip_ds6_if.addr_list[i].ipaddr); + PRINTF("\n"); + if (state == ADDR_TENTATIVE) { + uip_ds6_if.addr_list[i].state = ADDR_PREFERRED; + } + } + } +} +/*---------------------------------------------------------------------------*/ +void +request_prefix(void) { + /* mess up uip_buf with a dirty request... */ + uip_buf[0] = '?'; + uip_buf[1] = 'P'; + uip_len = 2; + slip_send(); + uip_len = 0; +} +/*---------------------------------------------------------------------------*/ +/* Set our prefix when we receive one over SLIP */ +void +set_prefix_64(uip_ipaddr_t *prefix_64) { + rpl_dag_t *dag; + uip_ipaddr_t ipaddr; + memcpy(&ipaddr, prefix_64, 16); + prefix_set = 1; + uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); + uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF); + + /* Become root of a new DODAG with ID our global v6 address */ + dag = rpl_set_root(RPL_DEFAULT_INSTANCE, &ipaddr); + if(dag != NULL) { + rpl_set_prefix(dag, &ipaddr, 64); + PRINTF("Created a new RPL dag with ID: "); + PRINT6ADDR(&dag->dag_id); + PRINTF("\n"); + } +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(border_router_process, ev, data) +{ + static struct etimer et; + + PROCESS_BEGIN(); + PRINTF("Border Router started\n"); + prefix_set = 0; + + leds_on(LEDS_RED); + + /* Request prefix until it has been received */ + while(!prefix_set) { + leds_on(LEDS_GREEN); + PRINTF("Prefix request.\n"); + etimer_set(&et, CLOCK_SECOND); + request_prefix(); + leds_off(LEDS_GREEN); + PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); + } + + /* We have created a new DODAG when we reach here */ + PRINTF("On Channel %u\n", CC2430_RF_CONF_CHANNEL); + + print_local_addresses(); + + leds_off(LEDS_RED); + + PROCESS_EXIT(); + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ diff --git a/examples/sensinode/border-router/project-conf.h b/examples/sensinode/border-router/project-conf.h new file mode 100644 index 000000000..f0fdb71fd --- /dev/null +++ b/examples/sensinode/border-router/project-conf.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2010, Loughborough University - Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * Project specific configuration defines for the border router / + * slip bridge example. + * + * We make sure that SLIP is turned on + * + * \author + * George Oikonomou - + */ + +#ifndef PROJECT_CONF_H_ +#define PROJECT_CONF_H_ + +#define VIZTOOL_MAX_PAYLOAD_LEN 120 +#define SLIP_ARCH_CONF_ENABLE 1 +#define LPM_CONF_MODE 0 + +#endif /* PROJECT_CONF_H_ */ diff --git a/examples/sensinode/border-router/slip-bridge.c b/examples/sensinode/border-router/slip-bridge.c new file mode 100644 index 000000000..82ec40920 --- /dev/null +++ b/examples/sensinode/border-router/slip-bridge.c @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2010, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: slip-bridge.c,v 1.3 2010/06/08 19:53:49 nifi Exp $ + */ + +/** + * \file + * Slip fallback interface + * \author + * Niclas Finne + * Joakim Eriksson + * Joel Hoglund + * Nicolas Tsiftes + */ + +#include "net/uip.h" +#include "net/uip-ds6.h" +#include "net/rpl/rpl.h" +#include "dev/slip.h" +#include "dev/uart1.h" +#include + +#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) + +#define DEBUG DEBUG_NONE +#include "net/uip-debug.h" + +void set_prefix_64(uip_ipaddr_t *); + +static uip_ipaddr_t last_sender; +/*---------------------------------------------------------------------------*/ +static void +slip_input_callback(void) +{ + PRINTF("SIN: %u\n", uip_len); + if((char) uip_buf[0] == '!') { + PRINTF("Got configuration message of type %c\n", uip_buf[1]); + uip_len = 0; + if((char)uip_buf[1] == 'P') { + uip_ipaddr_t prefix; + /* Here we set a prefix !!! */ + memset(&prefix, 0, 16); + memcpy(&prefix, &uip_buf[2], 8); + PRINTF("Setting prefix "); + PRINT6ADDR(&prefix); + PRINTF("\n"); + set_prefix_64(&prefix); + } + } + /* Save the last sender received over SLIP to avoid bouncing the + packet back if no route is found */ + uip_ipaddr_copy(&last_sender, &UIP_IP_BUF->srcipaddr); +} +/*---------------------------------------------------------------------------*/ +static void +init(void) +{ + process_start(&slip_process, NULL); + slip_set_input_callback(slip_input_callback); +} +/*---------------------------------------------------------------------------*/ +static void +output(void) +{ + if(uip_ipaddr_cmp(&last_sender, &UIP_IP_BUF->srcipaddr)) { + /* Do not bounce packets back over SLIP if the packet was received + over SLIP */ + PRINTF("slip-bridge: Destination off-link but no route\n"); + } else { + PRINTF("SUT: %u\n", uip_len); + slip_send(); + } +} +/*---------------------------------------------------------------------------*/ +const struct uip_fallback_interface slip_interface = { + init, output +}; +/*---------------------------------------------------------------------------*/ diff --git a/examples/sensinode/broadcast-rime.c b/examples/sensinode/broadcast-rime.c new file mode 100644 index 000000000..adcb479eb --- /dev/null +++ b/examples/sensinode/broadcast-rime.c @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2007, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + * $Id: example-broadcast.c,v 1.2 2009/11/19 17:29:41 nifi Exp $ + */ + +/** + * \file + * Testing the broadcast layer in Rime + * \author + * Adam Dunkels + */ + +#include "contiki.h" +#include "net/rime.h" +#include "lib/random.h" +#include "net/rime/rimestats.h" +#include "dev/leds.h" +#include "dev/models.h" + +#define DEBUG 1 +#if DEBUG +#include +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif + +#define BROADCAST_CHANNEL 129 + +/*---------------------------------------------------------------------------*/ +PROCESS(example_broadcast_process, "BROADCAST example"); +AUTOSTART_PROCESSES(&example_broadcast_process); +/*---------------------------------------------------------------------------*/ +static void broadcast_recv(struct broadcast_conn *c, const rimeaddr_t *from) +{ + leds_toggle(LEDS_RED); + PRINTF("broadcast message received from %02x.%02x\n", from->u8[0], from->u8[1]); + PRINTF("Size=0x%02x: '0x%04x'\n", packetbuf_datalen(), *(uint16_t *) packetbuf_dataptr()); +} + +static void print_rime_stats() +{ + PRINTF("\nNetwork Stats\n"); + PRINTF(" TX=%lu , RX=%lu\n", rimestats.tx, rimestats.rx); + PRINTF("LL-TX=%lu , LL-RX=%lu\n", rimestats.lltx, rimestats.llrx); + PRINTF(" Long=%lu , Short=%lu\n", rimestats.toolong, rimestats.tooshort); + PRINTF("T/Out=%lu , CCA-Err=%lu\n", rimestats.timedout, + rimestats.contentiondrop); +} + +static const struct broadcast_callbacks bc_rx = { broadcast_recv }; +static struct broadcast_conn broadcast; +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(example_broadcast_process, ev, data) +{ + static struct etimer et; + static uint16_t counter; + + PROCESS_EXITHANDLER(broadcast_close(&broadcast);) + + PROCESS_BEGIN(); + + PRINTF("Start\n"); + broadcast_open(&broadcast, BROADCAST_CHANNEL, &bc_rx); + PRINTF("Open Broadcast Connection, channel %u\n", BROADCAST_CHANNEL); + // leds_off(LEDS_ALL); + while(1) { + + /* Delay 2-4 seconds */ + etimer_set(&et, CLOCK_SECOND * 2); + PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); + leds_on(LEDS_GREEN); + packetbuf_copyfrom(&counter, sizeof(counter)); + PRINTF("Sending %u bytes: 0x%04x\n", packetbuf_datalen(), *(uint16_t *) packetbuf_dataptr()); + if (broadcast_send(&broadcast) == 0) { + PRINTF("Error Sending\n"); + } + + print_rime_stats(); + PRINTF("===================================\n"); + counter++; + leds_off(LEDS_GREEN); + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ diff --git a/examples/sensinode/cc2431-location-engine/Makefile b/examples/sensinode/cc2431-location-engine/Makefile new file mode 100644 index 000000000..8fc75d484 --- /dev/null +++ b/examples/sensinode/cc2431-location-engine/Makefile @@ -0,0 +1,17 @@ +ifndef TARGET +TARGET=sensinode +endif + +# Make absolutely certain that you specify your device here +DEFINES+=MODEL_N740 + +# This example doesn't need code banking so we turn it off +#HAVE_BANKING=1 + +CONTIKI_PROJECT = blind-node + +all: $(CONTIKI_PROJECT) + +CONTIKI = ../../.. + +include $(CONTIKI)/Makefile.include diff --git a/examples/sensinode/cc2431-location-engine/blind-node.c b/examples/sensinode/cc2431-location-engine/blind-node.c new file mode 100644 index 000000000..d50865522 --- /dev/null +++ b/examples/sensinode/cc2431-location-engine/blind-node.c @@ -0,0 +1,276 @@ +/* + * Copyright (c) 2010, Loughborough University - Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * Example demonstrating the cc2431 location engine. + * + * This file contains code for the blind node. The blind node must be + * equipped with a cc2431 SoC (as opposed to reference nodes which + * don't need to have a Loc. Eng.) + * + * The blind node receives co-ordinates of reference nodes over + * broadcast rime. Once it has enough data (3+ reference nodes), it + * will calculate its own position. + * + * We calculate with all potential values for parameter 'n' to + * demonstrate how 'n' influences the result of the calculation. + * + * Optionally, send the result of the calculation to a collection node + * + * More information on the cc2431 Location Engine can be found in: + * - cc2431 Datasheet + * - Texas Instruments Application Note 42 + * + * \author + * George Oikonomou - + */ + +#include "contiki.h" +#include "net/rime.h" +#include "cc2431_loc_eng.h" +#include "cc2430_sfr.h" + +#include +#include + +#define MAX_REF_NODES 16 /* Do not change */ + +#define SAMPLE_RSSI 100 /* Used for testing */ +#define SAMPLE_ALPHA 101 + +static struct meas_params parameters; +static struct refcoords ref_coords[MAX_REF_NODES]; + +/* Store our current location here to be transmitted to a collector node */ +static uint8_t coords[2]; + +/*---------------------------------------------------------------------------*/ +PROCESS(blindnode_bcast_rec, "Blind Node"); +AUTOSTART_PROCESSES(&blindnode_bcast_rec); +/*---------------------------------------------------------------------------*/ +/* + * This handles the calculation cycle. Returns non-zero on error, 0 on success. + * + * When we move this outside the example, we will perhaps want to pass + * struct refcoords *, struct meas_params * + * instead of exposing our own data structures. If this happens, we will need + * to add checks to our code to detect non-sane values + */ +static uint8_t +calculate() +{ + static int j, x; + uint8_t valid_rssi = 0; + + /* Turn on the Engine */ + LOCENG = LOCENG_EN; + while(!(LOCENG & LOCENG_EN)); + + /* Reference Coordinate Load Stage */ + LOCENG |= LOCENG_REFLD; + while(!(LOCENG & LOCENG_REFLD)); + + for(j = 0; j < MAX_REF_NODES; j++) { + /* Write the Reference Node x,y into the engine */ + REFCOORD = ref_coords[j].x; + REFCOORD = ref_coords[j].y; + } + + /* Reference Coordinate Load Stage Done. Proceed with measured params */ + LOCENG &= ~LOCENG_REFLD; + LOCENG |= LOCENG_PARLD; + + /* Load Parameters */ + MEASPARM = parameters.alpha; + MEASPARM = parameters.n; + MEASPARM = parameters.x_min; + MEASPARM = parameters.x_delta; + MEASPARM = parameters.y_min; + MEASPARM = parameters.y_delta; + + /* Load Neighbor RSSIs */ + for(j = 0; j < MAX_REF_NODES; j++) { + if(parameters.rssi[j] != 0) { + /* Range-check for the RSSI here, can only be in [-95 dBm , -40 dBm] + * so we only accept 80 <= rssi <= 190*/ + if(parameters.rssi[j] >= 80 && parameters.rssi[j] <= 190) { + valid_rssi++; + } + } + /* Write the value, even if it's zero */ + MEASPARM = parameters.rssi[j]; + } + + /* Done with measured parameters too */ + LOCENG &= ~LOCENG_PARLD; + + /* Only Calculate if we have 3+ reference nodes (non-zero RSSIs) */ + if(valid_rssi >= 3) { + LOCENG |= LOCENG_RUN; + } else { + LOCENG = 0; + printf("some error\n"); + return 1; + } + + /* Block on the calculation, between 50us and 13ms */ + while(!(LOCENG & LOCENG_DONE)); + + /* + * LOCX contains an offset. Remove it to obtain our actual X value. + * cc2431 datasheet, section 2.1.3 + */ + x = (LOCX - parameters.x_min + 1) % (parameters.x_delta + 1) + + parameters.x_min; + coords[0] = x; + coords[1] = LOCY; /* No offset here */ + printf("n=%2u: X=%3u, Y=%3u\n", parameters.n, LOCX, LOCY); + + /* Turn it off */ + LOCENG = 0; + + return 0; +} + +/*---------------------------------------------------------------------------*/ +/* + * We receive X, Y from reference nodes. + * We store this in location J of the ref_coords array, where J is the LSB + * of the reference node's rime address. So we can only accept data from nodes + * with rime address ending in [0 , 15] + */ +static void +broadcast_recv(struct broadcast_conn *c, const rimeaddr_t *from) +{ + packetbuf_attr_t rssi; /* Careful here, this is uint16_t */ + + if(from->u8[1] < MAX_REF_NODES) { + memset(&ref_coords[from->u8[1] - 1], 0, sizeof(struct refcoords)); + + /* Obtain incoming message's RSSI from contiki */ + rssi = packetbuf_attr(PACKETBUF_ATTR_RSSI); + /* Convert RSSI to the loc. eng. format */ + parameters.rssi[from->u8[1] - 1] = (-2 * rssi); + /* Raw dump the packetbuf into the ref_coords struct */ + memcpy(&ref_coords[from->u8[1] - 1], packetbuf_dataptr(), 2 * sizeof(uint8_t)); + } + + return; +} +/* + * Imaginary nodes to test functionality + * All nodes at 1 meter distance, rssi = -40 (80) + * Since the rssi at 1 meter = -40 (A), the blind node should think it's at + * 5,5 + */ +/*---------------------------------------------------------------------------*/ +static void +set_imaginary_ref_nodes() { + ref_coords[0].x = 1; + ref_coords[0].y = 5; + parameters.rssi[0] = SAMPLE_RSSI; + + ref_coords[1].x = 5; + ref_coords[1].y = 1; + parameters.rssi[1] = SAMPLE_RSSI; + + ref_coords[2].x = 5; + ref_coords[2].y = 9; + parameters.rssi[2] = SAMPLE_RSSI; + + ref_coords[3].x = 9; + ref_coords[3].y = 5; + parameters.rssi[3] = SAMPLE_RSSI; +} +/*---------------------------------------------------------------------------*/ +static const struct broadcast_callbacks broadcast_call = { broadcast_recv }; +static struct broadcast_conn broadcast; +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(blindnode_bcast_rec, ev, data) +{ + static struct etimer et; + static uint8_t n; + int i; + + PROCESS_EXITHANDLER(broadcast_close(&broadcast)); + + PROCESS_BEGIN(); + + printf("Reading Chip ID: 0x%02x\n", CHIPID); + /* Read our chip ID. If we are not cc2431, bail out */ + if(CHIPID != CC2431_CHIP_ID) { + printf("Hardware does not have a location engine. Exiting.\n"); + PROCESS_EXIT(); + } + + /* OK, we are cc2431. Do stuff */ + n = 0; + + /* Initalise our structs and parameters */ + memset(ref_coords, 0, sizeof(struct refcoords) * MAX_REF_NODES); + memset(¶meters, 0, sizeof(struct meas_params)); + + /* + * Just hard-coding measurement parameters here. + * Ideally, this should be part of a calibration mechanism + */ + parameters.alpha=SAMPLE_ALPHA; + parameters.x_min=0; + parameters.x_delta=255; + parameters.y_min=0; + parameters.y_delta=255; + + set_imaginary_ref_nodes(); + + broadcast_open(&broadcast, 129, &broadcast_call); + + while(1) { + + etimer_set(&et, CLOCK_SECOND); + + PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); + + /* + * With the hard-coded parameters and locations, we will calculate + * for all possible values of n [0 , 31] + */ + parameters.n=n; + calculate(); + n++; + if(n==32) { n=0; } + + /* Send our calculated location to some monitoring node */ + packetbuf_copyfrom(&coords, 2*sizeof(uint8_t)); + broadcast_send(&broadcast); + } + PROCESS_END(); +} diff --git a/examples/sensinode/cc2431-location-engine/cc2431_loc_eng.h b/examples/sensinode/cc2431-location-engine/cc2431_loc_eng.h new file mode 100644 index 000000000..b5489797c --- /dev/null +++ b/examples/sensinode/cc2431-location-engine/cc2431_loc_eng.h @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2010, Loughborough University - Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * Header file used by the example demonstrating the cc2431 location + * engine. + * + * This file contains declarations of the location engine registers and + * the LOCENG register bits. It also contains some data structures used + * to store calculation parameters and reference node coordinates. + * + * This file only needs to be included bye the blind node code file. + * + * More information on the cc2431 Location Engine can be found in: + * - cc2431 Datasheet + * - K. Aamodt, "CC2431 Location Engine", Texas Instruments Application + * Note 42. + * + * \author + * George Oikonomou - + */ + +#include "8051def.h" +#include /* For syntax parsers */ + +/* Location Engine Registers on the cc2431 */ +__xdata __at (0xDF55) unsigned char REFCOORD; +__xdata __at (0xDF56) unsigned char MEASPARM; +__xdata __at (0xDF57) unsigned char LOCENG; +__xdata __at (0xDF58) unsigned char LOCX; +__xdata __at (0xDF59) unsigned char LOCY; + +/* LOCENG Register Bits */ +#define LOCENG_RUN 0x01 +#define LOCENG_REFLD 0x02 +#define LOCENG_PARLD 0x04 +#define LOCENG_DONE 0x08 +#define LOCENG_EN 0x10 + +/* cc2431 chips report 0x89 when the CHIPID register is read */ +#define CC2431_CHIP_ID 0x89 + +/* + * Struct for the Calculation Parameters. + * Values stored here feed the MEASPARM register. + * + * Values should be stored here in Location Engine format: + * RSSI: 0.5 Precision, without the minus sign. All 16 must be used. Use 0 + * to reduce the number of ref. nodes used in the calculation. + * Value range [-95 dBm , -40 dBm] + * A: 0.5 Precision. Value range [30.0 , 50.0] (Thus [60 , 100] decimal) + * n: Use the n Index value [0 , 31] - See cc2431 datasheet, Table 2. + * delta: Must be present. If we want the calculation to be unrestricted, + * use 0xFF + * + */ +struct meas_params { + uint8_t alpha; + uint8_t n; + uint8_t x_min; + uint8_t x_delta; + uint8_t y_min; + uint8_t y_delta; + uint8_t rssi[16]; +}; + +/* + * Store the reference node coordinates here. + * This will feed REFCOORD. + * + * Values should be stored here in Location Engine format: + * 2 LS bits for the fractional part, 0.25 precision + * 6 MS bits for the integral part. + * Value range [0 , 63.75] (thus [0 , 255]) + */ +struct refcoords { + uint8_t x; + uint8_t y; +}; diff --git a/examples/sensinode/clock_test.c b/examples/sensinode/clock_test.c index dfbe3d23d..758b4d040 100644 --- a/examples/sensinode/clock_test.c +++ b/examples/sensinode/clock_test.c @@ -19,7 +19,7 @@ PROCESS_THREAD(clock_test_process, ev, data) static struct etimer et; static clock_time_t count, start_count, end_count, diff; static unsigned long sec; - static uint8_t i; + static u8_t i; PROCESS_BEGIN(); @@ -56,7 +56,7 @@ PROCESS_THREAD(clock_test_process, ev, data) etimer_reset(&et); sec = clock_seconds(); - printf("%u seconds\n", (uint16_t) sec); + printf("%u seconds\n", (u16_t) sec); leds_toggle(LEDS_GREEN); i++; diff --git a/examples/sensinode/disco/Makefile b/examples/sensinode/disco/Makefile new file mode 100644 index 000000000..51b7be77f --- /dev/null +++ b/examples/sensinode/disco/Makefile @@ -0,0 +1,18 @@ +ifndef TARGET +TARGET=sensinode +endif + +# Make absolutely certain that you specify your device here +DEFINES+=MODEL_N740 + +HAVE_BANKING=1 +UIP_CONF_IPV6=1 +OFFSET_FIRMWARE=1 + +CONTIKI_PROJECT = disco-example + +all: $(CONTIKI_PROJECT) + +CONTIKI = ../../.. + +include $(CONTIKI)/Makefile.include diff --git a/examples/sensinode/disco/disco-example.c b/examples/sensinode/disco/disco-example.c new file mode 100644 index 000000000..8f97a13fc --- /dev/null +++ b/examples/sensinode/disco/disco-example.c @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2010, Loughborough University - Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * Stub project source file. We just need to build contiki with + * OFFSET_FIRMWARE, Makefile does so. + * + * \author + * George Oikonomou - + */ + +#include "contiki.h" + +/*---------------------------------------------------------------------------*/ +PROCESS(stub_process, "Stub process"); +AUTOSTART_PROCESSES(&stub_process); +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(stub_process, ev, data) +{ + PROCESS_BEGIN(); + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ diff --git a/examples/sensinode/energy-scan/Makefile b/examples/sensinode/energy-scan/Makefile new file mode 100644 index 000000000..9020155e3 --- /dev/null +++ b/examples/sensinode/energy-scan/Makefile @@ -0,0 +1,16 @@ +ifndef TARGET +TARGET=sensinode +endif + +# Make absolutely certain that you specify your device here +DEFINES+=MODEL_N740,PROJECT_CONF_H + +PROJECT_SOURCEFILES += stub-rdc.c + +CONTIKI_PROJECT = energy-scan + +all: $(CONTIKI_PROJECT) + +CONTIKI = ../../.. + +include $(CONTIKI)/Makefile.include diff --git a/examples/sensinode/energy-scan/energy-scan.c b/examples/sensinode/energy-scan/energy-scan.c new file mode 100644 index 000000000..07393d507 --- /dev/null +++ b/examples/sensinode/energy-scan/energy-scan.c @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2010, Loughborough University - Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * Minimalistic channel energy detection. + * + * \author + * George Oikonomou - + */ + +#include "contiki.h" +#include "cc2430_sfr.h" + +#include "sensinode-debug.h" +#include "dev/cc2430_rf.h" +#include + +static uint8_t channel; +static int8_t j; +static int8_t cmax; +static int8_t rssi; +static struct etimer et; +static rtimer_clock_t t0; + +#define RSSI_BASE -50 +#define RSSI_SAMPLES 30 +#define SAMPLE_INTERVAL (CLOCK_SECOND) +#define CHANNEL_MIN 11 +#define CHANNEL_MAX 26 +/* ToDo: Do this in infinite RX. Take more samples */ +/*---------------------------------------------------------------------------*/ +PROCESS(energy_scan, "Energy Scanner"); +AUTOSTART_PROCESSES(&energy_scan); +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(energy_scan, ev, data) +{ + + PROCESS_BEGIN(); + + printf("Energy Scanner\n"); + printf("CCA Threshold: %d\n", (int8_t)RSSIH); + printf("Channel scan range: [%u , %u]\n", CHANNEL_MIN, CHANNEL_MAX); + printf("%u samples per channel, interval %u ticks\n", + RSSI_SAMPLES, SAMPLE_INTERVAL); + + channel = CHANNEL_MIN; + while(1) { + cmax = RSSI_BASE; + cc2430_rf_channel_set(channel); + clock_delay(200); + + for(j = 0; j < RSSI_SAMPLES; j++) { + t0 = RTIMER_NOW(); + rssi = RSSIL; + if(rssi > cmax) { + cmax = rssi; + } + while(RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + 25)); + } + printf("%u [%3d]: ", channel, cmax); + for(j = RSSI_BASE; j <= cmax; j++) { + printf("#"); + } + printf("\n"); + if(channel == CHANNEL_MAX) { + printf("===============\n"); + channel = CHANNEL_MIN; + } else { + channel++; + } + + etimer_set(&et, SAMPLE_INTERVAL); + PROCESS_YIELD(); + + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ diff --git a/examples/sensinode/energy-scan/netstack.c b/examples/sensinode/energy-scan/netstack.c new file mode 100644 index 000000000..2551f82fe --- /dev/null +++ b/examples/sensinode/energy-scan/netstack.c @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2010, Loughborough University - Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * Stub file overriding core/net/netstack.c. What we want to achieve + * here is call netstack_init from main without initialising the RDC, + * MAC and Network layers. It will just turn on the radio instead. + * + * \author + * George Oikonomou - + */ + +#include "netstack.h" +/*---------------------------------------------------------------------------*/ +void +netstack_init(void) +{ + NETSTACK_RADIO.init(); +} +/*---------------------------------------------------------------------------*/ + diff --git a/examples/sensinode/energy-scan/project-conf.h b/examples/sensinode/energy-scan/project-conf.h new file mode 100644 index 000000000..91c1917e4 --- /dev/null +++ b/examples/sensinode/energy-scan/project-conf.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2010, Loughborough University - Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * Project specific configuration defines for the sniffer example. + * + * We make sure that the radio driver outputs all packets in hexdump + * format. + * + * \author + * George Oikonomou - + */ + +#ifndef PROJECT_CONF_H_ +#define PROJECT_CONF_H_ + +#define NETSTACK_CONF_RDC stub_rdc_driver +#define ADC_SENSOR_CONF_ON 0 +#define LPM_CONF_MODE 0 + +#endif /* PROJECT_CONF_H_ */ diff --git a/examples/sensinode/energy-scan/stub-rdc.c b/examples/sensinode/energy-scan/stub-rdc.c new file mode 100644 index 000000000..c131d953d --- /dev/null +++ b/examples/sensinode/energy-scan/stub-rdc.c @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2010, Loughborough University - Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * Definition of a fake RDC driver to be used with passive + * examples. The code will never send packets and it will never + * push incoming packets up the stack. We do this by defining this + * driver as our RDC. We then drop everything + * + * \author + * George Oikonomou - + */ + +#include "net/mac/mac.h" +#include "net/mac/rdc.h" +/*---------------------------------------------------------------------------*/ +static void +send(mac_callback_t sent, void *ptr) +{ + if(sent) { + sent(ptr, MAC_TX_OK, 1); + } +} +/*---------------------------------------------------------------------------*/ +static void +send_list(mac_callback_t sent, void *ptr, struct rdc_buf_list *list) +{ + if(sent) { + sent(ptr, MAC_TX_OK, 1); + } +} +/*---------------------------------------------------------------------------*/ +static void +input(void) +{ +} +/*---------------------------------------------------------------------------*/ +static int +on(void) +{ + return 1; +} +/*---------------------------------------------------------------------------*/ +static int +off(int keep_radio_on) +{ + return 1; +} +/*---------------------------------------------------------------------------*/ +static unsigned short +cca(void) +{ + return 0; +} +/*---------------------------------------------------------------------------*/ +static void +init(void) +{ +} +/*---------------------------------------------------------------------------*/ +const struct rdc_driver stub_rdc_driver = { + "stub-rdc", + init, + send, + send_list, + input, + on, + off, + cca, +}; +/*---------------------------------------------------------------------------*/ diff --git a/examples/sensinode/event-post/Makefile b/examples/sensinode/event-post/Makefile new file mode 100644 index 000000000..15113d249 --- /dev/null +++ b/examples/sensinode/event-post/Makefile @@ -0,0 +1,17 @@ +ifndef TARGET +TARGET=sensinode +endif + +# Make absolutely certain that you specify your device here +DEFINES+=MODEL_N740 + +# This example doesn't need code banking so we turn it off +#HAVE_BANKING=1 + +CONTIKI_PROJECT = event-post + +all: $(CONTIKI_PROJECT) + +CONTIKI = ../../.. + +include $(CONTIKI)/Makefile.include diff --git a/examples/sensinode/event-post/event-post.c b/examples/sensinode/event-post/event-post.c new file mode 100644 index 000000000..ed249eeed --- /dev/null +++ b/examples/sensinode/event-post/event-post.c @@ -0,0 +1,132 @@ +/* This file demonstrates the interaction between two processes via events. + * + * - "Sensor process": Throws an event periodically. This can be for example a + * sensor value. + * - "Print process" : Waits for events from "Sensor" and prints a message when + * an event occurs (e.g. prints the sensor value) + * + * This example is derived from the contiki code examples for the WSN430 + * (SensTools - Inria: http://senstools.gforge.inria.fr/) + * + * Author: George Oikonomou + */ + +#include "contiki.h" +//#include "dev/leds.h" +#include +#include /* For printf() */ +#include "event-post.h" + +/* This is our event type */ +static process_event_t event_data_ready; + +/*---------------------------------------------------------------------------*/ +/* Declare the two processes here */ +PROCESS(sensor_process, "Sensor process"); +PROCESS(print_process, "Print process"); + +/* Tell Contiki that we want them to start automatically */ +AUTOSTART_PROCESSES(&sensor_process, &print_process); + +/*---------------------------------------------------------------------------*/ +/* Implementation "Sensor Process" */ +PROCESS_THREAD(sensor_process, ev, data) +{ + /* static variables to preserve values across consecutive calls of this + * process. */ + /* Set an etimer */ + static struct etimer timer; + /* And the 'sensor' monitoring variable */ + static struct event_struct es; + + PROCESS_BEGIN(); + + /* Set some near-the-limit initial values */ + /* signed primitives */ + es.s_val = SHRT_MAX-2; + es.i_val = INT_MAX-2; + es.l_val = LONG_MAX-2; + /* sizeof(long long) == sizeof(long) on sensinodes - see other examples*/ + es.ll_val = LONG_MAX-2; + /* and some typedef-ed unsigned variables */ + es.u8_val = UCHAR_MAX-2; + es.u16_val = USHRT_MAX-2; + es.u32_val = ULONG_MAX-2; + + /* allocate the required event */ + event_data_ready = process_alloc_event(); + + /* process_event_t is actually a u_char. What did the OS allocate for us? */ + printf("Contiki allocated event ID %d.\r\n", event_data_ready); + + /* Set a timer here. We will generate an event every times this timer expires + * etimer_set accepts clock ticks as its 2nd argument. + * CLOCK_CONF_SECOND is the number of ticks per second. + * This CLOCK_CONF_SECOND * N = N seconds */ + etimer_set(&timer, CLOCK_CONF_SECOND * 2); + + while (1) + { + printf("Sensor process: Wait for timer event...\r\n"); + /* Wait on our timer */ + PROCESS_WAIT_EVENT_UNTIL(ev == PROCESS_EVENT_TIMER); + + /* blip */ + /* leds_toggle(LEDS_BLUE); */ + + /* Set the 'sensor' value before throwing the event */ + printf("Sensor Process: Incrementing values...\r\n"); + es.s_val++; + es.i_val++; + es.l_val++; + es.ll_val++; + es.u8_val++; + es.u16_val++; + es.u32_val++; + + /* Post our event. + * N.B. es is declared static. + * Try passing a volatile variable and observe the results... */ + printf("Sensor Process: Generating 'Data Ready' event.\r\n"); + process_post(&print_process, event_data_ready, &es); + + /* reset the timer so we can wait on it again */ + etimer_reset(&timer); + + } + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ +/* Implementation of "Print Process" */ +PROCESS_THREAD(print_process, ev, data) +{ + + struct event_struct * sd; + + PROCESS_BEGIN(); + + while (1) + { + /* Stop here and wait until "event_data_ready" occurs */ + PROCESS_WAIT_EVENT_UNTIL(ev == event_data_ready); + + /* When the event occurs, the incoming data will be stored in + * process_data_t data (careful, this is void *) + * + * Print away... + * es is volatile, we need to set it = data again and dereference it. */ + sd = data; + printf("Print Process - Data Ready:\r\n"); + printf(" s: %d\r\n", sd->s_val); + printf(" i: %d\r\n", sd->i_val); + printf(" l: %ld\r\n", sd->l_val); + printf(" ll: %lld\r\n", sd->ll_val); + printf(" u8: %u\r\n", sd->u8_val); + printf(" u16: %u\r\n", sd->u16_val); + printf(" u32: %lu\r\n", sd->u32_val); + + /* aaaaand back to waiting for the next event */ + } + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ diff --git a/examples/sensinode/event-post/event-post.h b/examples/sensinode/event-post/event-post.h new file mode 100644 index 000000000..2d640441a --- /dev/null +++ b/examples/sensinode/event-post/event-post.h @@ -0,0 +1,22 @@ +/* + * event-post.h + * Header file for the event_post example + * + * Created on: 30 Mar 2010 + * Author: George Oikonomou + */ + +#ifndef EVENT_POST_H_ +#define EVENT_POST_H_ + +struct event_struct { + short s_val; + int i_val; + long l_val; + long long ll_val; + u8_t u8_val; + u16_t u16_val; + u32_t u32_val; +}; + +#endif /* EVENT_POST_H_ */ diff --git a/examples/sensinode/sensors-ipv6/Makefile b/examples/sensinode/sensors-ipv6/Makefile new file mode 100644 index 000000000..608de5c0d --- /dev/null +++ b/examples/sensinode/sensors-ipv6/Makefile @@ -0,0 +1,19 @@ +ifndef TARGET +TARGET=sensinode +endif + +# Make absolutely certain that you specify your device here +DEFINES+=MODEL_N740,PROJECT_CONF_H + +# This example won't fit in flash without banking so we turn it on +HAVE_BANKING=1 +UIP_CONF_IPV6=1 + +CONTIKI_SOURCEFILES += sensors-driver.c + +CONTIKI_PROJECT = sensors-ipv6 +all: $(CONTIKI_PROJECT) + +CONTIKI = ../../.. + +include $(CONTIKI)/Makefile.include diff --git a/examples/sensinode/sensors-ipv6/project-conf.h b/examples/sensinode/sensors-ipv6/project-conf.h new file mode 100644 index 000000000..baa6edfc4 --- /dev/null +++ b/examples/sensinode/sensors-ipv6/project-conf.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2010, Loughborough University - Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * Project specific configuration defines for the UDP client/server + * example. + * + * We make sure that buttons and ADC are on. We also demonstrate the + * new LPM functionality + * + * \author + * George Oikonomou - + */ + +#ifndef PROJECT_CONF_H_ +#define PROJECT_CONF_H_ + +#define BUTTON_SENSOR_CONF_ON 1 +#define ADC_SENSOR_CONF_ON 1 +#define LPM_CONF_MODE 1 + +#endif /* PROJECT_CONF_H_ */ diff --git a/examples/sensinode/sensors-ipv6/sensors-driver.c b/examples/sensinode/sensors-ipv6/sensors-driver.c new file mode 100644 index 000000000..01e118eb2 --- /dev/null +++ b/examples/sensinode/sensors-ipv6/sensors-driver.c @@ -0,0 +1,246 @@ +/* + * Copyright (c) 2010, Loughborough University - Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * This file handles the sensor readings and float conversions + * for sensors-example. We keep this separate in order to place it + * to a higher BANK. + * + * Bankable + * + * \author + * George Oikonomou - + */ + +#include "contiki-conf.h" +#include "uip.h" /* for htons / htonl */ +#include "dev/leds.h" +#if CONTIKI_TARGET_SENSINODE +#include "dev/sensinode-sensors.h" +#include "sensinode-debug.h" +#endif + +#define DEBUG 0 +#if DEBUG +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif +#include +#include + +#define SENSOR_OK 0 +#define SENSOR_ADC_OFF -1 +#define SENSOR_UNKNOWN -2 + +/* Request Bits */ +#define REQUEST_BIT_P0_GET 0x0400 +#define REQUEST_BIT_L2_SET 0x0200 +#define REQUEST_BIT_L1_SET 0x0100 +#define REQUEST_BIT_LED_GET 0x0080 +#define REQUEST_BIT_ACC 0x0040 +#define REQUEST_BIT_BAT 0x0020 +#define REQUEST_BIT_VDD 0x0010 +#define REQUEST_BIT_TEMP 0x0008 +#define REQUEST_BIT_LIGHT 0x0004 +#define REQUEST_BIT_UPTIME 0x0002 +#define REQUEST_BIT_CHIPID 0x0001 + +/*---------------------------------------------------------------------------*/ +int8_t +read_sensor(char * rs) +{ + /* Sensor Values */ + static int rv; + static struct sensors_sensor * sensor; + + /* Those 3 variables are only used for debugging */ +#if DEBUG + static float sane = 0; + static int dec; + static float frac; +#endif + uint16_t r; + uint8_t len = 0; + + sensor = sensors_find(ADC_SENSOR); + if (!sensor) { + PRINTF("ADC not found\n"); + return (SENSOR_ADC_OFF); + } + + /* Fetch the request bytes */ + memcpy(&r, rs, 2); + r = uip_ntohs(r); + PRINTF("R=%u\n", r); + + if (r & REQUEST_BIT_CHIPID) { + uint8_t chipid = CHIPID; + memcpy(rs + len, &chipid, sizeof(chipid)); + len += sizeof(chipid); + PRINTF("ChipID=0x%02x\n", chipid); + } + if (r & REQUEST_BIT_UPTIME) { + /* Uptime */ + unsigned long l; + + l = uip_htonl(clock_seconds()); + memcpy(rs + len, &l, sizeof(l)); + len += sizeof(l); + PRINTF("Uptime=%lu secs\n", uip_ntohl(l)); + } + if (r & REQUEST_BIT_LIGHT) { + rv = sensor->value(ADC_SENSOR_TYPE_LIGHT); + if(rv != -1) { +#if DEBUG + sane = (float)(rv * 0.4071); + dec = sane; + frac = sane - dec; + PRINTF(" Light=%d.%02ulux (%d)\n", dec, (unsigned int)(frac*100), rv); +#endif + memcpy(rs + len, &rv, sizeof(rv)); + len += sizeof(rv); + } + } + if (r & REQUEST_BIT_TEMP) { + rv = sensor->value(ADC_SENSOR_TYPE_TEMP); + if(rv != -1) { +#if DEBUG + sane = ((rv * 0.61065 - 773) / 2.45); + dec = sane; + frac = sane - dec; + PRINTF(" Temp=%d.%02u C (%d)\n", dec, (unsigned int)(frac*100), rv); +#endif + memcpy(rs + len, &rv, sizeof(rv)); + len += sizeof(rv); + } + } + if (r & (REQUEST_BIT_VDD | REQUEST_BIT_BAT)) { + /* We want VDD for both cases */ + rv = sensor->value(ADC_SENSOR_TYPE_VDD); + if(rv != -1) { +#if DEBUG + sane = rv * 3.75 / 2047; + dec = sane; + frac = sane - dec; + PRINTF("Supply=%d.%02uV (%d)\n", dec, (unsigned int)(frac*100), rv); + /* Store rv temporarily in dec so we can use it for the battery */ + dec = rv; +#endif + memcpy(rs + len, &rv, sizeof(rv)); + len += sizeof(rv); + } + /* And then carry on with battery if needed */ + if (r & REQUEST_BIT_BAT) { + rv = sensor->value(ADC_SENSOR_TYPE_BATTERY); + if(rv != -1) { +#if DEBUG + sane = (11.25 * rv * dec) / (0x7FE002); + dec = sane; + frac = sane - dec; + PRINTF(" Batt.=%d.%02uV (%d)\n", dec, (unsigned int)(frac*100), rv); +#endif + memcpy(rs + len, &rv, sizeof(rv)); + len += sizeof(rv); + } + } + } + if (r & REQUEST_BIT_ACC) { + rv = sensor->value(ADC_SENSOR_TYPE_ACC_X); + if(rv != -1) { +#if DEBUG + sane = ((rv * 3.75 / 2047) - 1.65) / 0.44; + dec = sane; + frac = sane - dec; + frac = (frac < 0) ? -frac : frac; + + PRINTF(" AccX="); + if(sane < 0 && dec == 0) { + PRINTF('-'); + } + PRINTF("%d.%02ug (%d)\n", dec, (unsigned int)(frac*100), rv); +#endif + memcpy(rs + len, &rv, sizeof(rv)); + len += sizeof(rv); + } + rv = sensor->value(ADC_SENSOR_TYPE_ACC_Y); + if(rv != -1) { +#if DEBUG + sane = ((rv * 3.75 / 2047) - 1.65) / 0.44; + dec = sane; + frac = sane - dec; + frac = (frac < 0) ? -frac : frac; + PRINTF(" AccY="); + if(sane < 0 && dec == 0) { + PRINTF('-'); + } + PRINTF("%d.%02ug (%d)\n", dec, (unsigned int)(frac*100), rv); +#endif + memcpy(rs + len, &rv, sizeof(rv)); + len += sizeof(rv); + } + rv = sensor->value(ADC_SENSOR_TYPE_ACC_Z); + if(rv != -1) { +#if DEBUG + sane = ((rv * 3.75 / 2047) - 1.65) / 0.44; + dec = sane; + frac = sane - dec; + frac = (frac < 0) ? -frac : frac; + PRINTF(" AccZ="); + if(sane < 0 && dec == 0) { + PRINTF('-'); + } + PRINTF("%d.%02ug (%d)\n", dec, (unsigned int)(frac*100), rv); +#endif + memcpy(rs + len, &rv, sizeof(rv)); + len += sizeof(rv); + } + } + if (r & REQUEST_BIT_L1_SET) { + leds_toggle(LEDS_GREEN); + } + if (r & REQUEST_BIT_L2_SET) { + leds_toggle(LEDS_RED); + } + if (r & REQUEST_BIT_LED_GET) { + uint8_t leds = leds_get(); + memcpy(rs + len, &leds, sizeof(leds)); + len += sizeof(leds); + PRINTF(" LED 2=%u\n", leds); + } + if (r & REQUEST_BIT_P0_GET) { + uint8_t p0 = P0_3; + memcpy(rs + len, &p0, sizeof(p0)); + len += sizeof(p0); + } + return len; +} diff --git a/examples/sensinode/sensors-ipv6/sensors-ipv6.c b/examples/sensinode/sensors-ipv6/sensors-ipv6.c new file mode 100644 index 000000000..ca9589fb4 --- /dev/null +++ b/examples/sensinode/sensors-ipv6/sensors-ipv6.c @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2010, Loughborough University - Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * Example to demonstrate-test the sensors functionality on + * sensinode/cc2430 devices. + * + * A UDP/IPv6 process waits for requests from a monitoring station + * and responds with sensor values. + * + * The message exchange is based on a custom protocol. + * Check sensors-driver.c for protocol details. + * + * \author + * George Oikonomou - + */ + +#include "contiki.h" +#include "contiki-lib.h" +#include "contiki-net.h" + +#include + +#define DEBUG DEBUG_NONE +#include "net/uip-debug.h" +#include "dev/watchdog.h" +#include "dev/leds.h" +#include "net/rpl/rpl.h" +#include + +#if CONTIKI_TARGET_SENSINODE +#include "sensinode-debug.h" +#include "dev/sensinode-sensors.h" +#else +#define putstring(s) +#endif + +#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) +#define UIP_UDP_BUF ((struct uip_udp_hdr *)&uip_buf[uip_l2_l3_hdr_len]) + +#define MAX_PAYLOAD_LEN 120 + +static struct uip_udp_conn *server_conn; +static char buf[MAX_PAYLOAD_LEN]; +static uint16_t len; + +#define SERVER_PORT 60000 + +#define SENSOR_OK 0 +#define SENSOR_ADC_OFF 1 +#define SENSOR_UNKNOWN 2 + +int8_t read_sensor(char * rs); +/*---------------------------------------------------------------------------*/ +extern const struct sensors_sensor adc_sensor; +/*---------------------------------------------------------------------------*/ +PROCESS(udp_server_process, "UDP server process"); +AUTOSTART_PROCESSES(&udp_server_process); +/*---------------------------------------------------------------------------*/ +static void +tcpip_handler(void) +{ + memset(buf, 0, MAX_PAYLOAD_LEN); + + if(uip_newdata()) { + len = uip_datalen(); + memcpy(buf, uip_appdata, len); + PRINTF("%u bytes from [", len); + PRINT6ADDR(&UIP_IP_BUF->srcipaddr); + PRINTF("]:%u\n", UIP_HTONS(UIP_UDP_BUF->srcport)); + len = read_sensor(buf); + if( len ) { + server_conn->rport = UIP_UDP_BUF->srcport; + uip_ipaddr_copy(&server_conn->ripaddr, &UIP_IP_BUF->srcipaddr); + uip_udp_packet_send(server_conn, buf, len); + PRINTF("Sent %u bytes\n", len); + } + + /* Restore server connection to allow data from any node */ + uip_create_unspecified(&server_conn->ripaddr); + server_conn->rport = 0; + } + return; +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(udp_server_process, ev, data) +{ +#if (CONTIKI_TARGET_SENSINODE && BUTTON_SENSOR_ON) + static struct sensors_sensor *b1; + static struct sensors_sensor *b2; +#endif + + PROCESS_BEGIN(); + putstring("Starting UDP server\n"); + +#if (CONTIKI_TARGET_SENSINODE && BUTTON_SENSOR_ON) + putstring("Button X: Toggle LED X\n"); +#endif + + server_conn = udp_new(NULL, UIP_HTONS(0), NULL); + udp_bind(server_conn, UIP_HTONS(SERVER_PORT)); + +#if (CONTIKI_TARGET_SENSINODE && BUTTON_SENSOR_ON) + b1 = sensors_find(BUTTON_1_SENSOR); + b2 = sensors_find(BUTTON_2_SENSOR); +#endif + + while(1) { + PROCESS_YIELD(); + if(ev == tcpip_event) { + tcpip_handler(); +#if (CONTIKI_TARGET_SENSINODE && BUTTON_SENSOR_ON) + } else if(ev == sensors_event && data != NULL) { + if(data == b1) { + leds_toggle(LEDS_GREEN); + } else if(data == b2) { + leds_toggle(LEDS_RED); + } +#endif /* (CONTIKI_TARGET_SENSINODE && BUTTON_SENSOR_ON) */ + } + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ diff --git a/examples/sensinode/sensors/Makefile b/examples/sensinode/sensors/Makefile new file mode 100644 index 000000000..90c05ae80 --- /dev/null +++ b/examples/sensinode/sensors/Makefile @@ -0,0 +1,17 @@ +ifndef TARGET +TARGET=sensinode +endif + +# Make absolutely certain that you specify your device here +DEFINES+=MODEL_N740 + +# This example doesn't need code banking so we turn it off +#HAVE_BANKING=1 + +CONTIKI_PROJECT = sensors-example + +all: $(CONTIKI_PROJECT) + +CONTIKI = ../../.. + +include $(CONTIKI)/Makefile.include diff --git a/examples/sensinode/sensors/sensors-example.c b/examples/sensinode/sensors/sensors-example.c new file mode 100644 index 000000000..ecbaddb17 --- /dev/null +++ b/examples/sensinode/sensors/sensors-example.c @@ -0,0 +1,372 @@ +/* + * Copyright (c) 2010, Loughborough University - Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * Example to demonstrate-test the sensors functionality on + * sensinode/cc2430 devices. + * + * B1 turns L2 on and off. + * B2 reboots the node via the watchdog. + * + * The node takes readings from the various sensors every x seconds and + * prints out the results. + * + * We use floats here to translate the AD conversion results to + * meaningful values. However, our printf does not have %f support so + * we use an ugly hack to print out the value by extracting the integral + * part and then the fractional part. Don't try this at home. + * + * Temperature: + * Math is correct, the sensor needs calibration per device. + * I currently use default values for the math which may result in + * very incorrect values in degrees C. + * See TI Design Note DN102 about the offset calibration. + * + * Supply Voltage (VDD) and Battery Sensor: + * For VDD, math is correct, conversion is correct. See DN101 for details if + * interested. + * Battery reports different values when we run it many times + * in succession. The cause is unknown. + * I am fairly confident that I have captured the connections on the + * device correctly. I am however accepting input/feedback + * + * Light Sensor (Vishay Semiconductors TEPT4400): + * I am uncertain about the math. This needs testing. All I know is + * that 600lux = 0.9V and that the relation is linear. See inline for + * more details + * + * Accelerometer (Freescale Semiconductor MMA7340L): + * Math is correct but the sensor needs calibration. I've not + * attempted one cause the reported values differ per device. + * Place the N740 with the logo facing down to get 1g on the Z axis. + * Place the antenna side facing down to get 1g on the Y axis + * Place the N740 on its longer side while looking at the antenna and + * the D connector. Antenna on the bottom, D connector on the top. + * This should give you 1g on the X axis. + * + * Make sure you enable/disable things in contiki-conf.h + * + * \author + * George Oikonomou - + */ + +#include "contiki.h" +#include "contiki-conf.h" +#include "net/rime.h" +#include "dev/leds.h" +#include "dev/watchdog.h" +#include "lib/random.h" + +#if CONTIKI_TARGET_SENSINODE +#include "dev/sensinode-sensors.h" +#else +#include "lib/sensors.h" +#endif + +#define DEBUG 1 +#if DEBUG +#include +#if CONTIKI_TARGET_SENSINODE +#include "sensinode-debug.h" +#endif /* CONTIKI_TARGET_SENSINODE */ +#define PRINTF(...) printf(__VA_ARGS__) +#else /* DEBUG */ +/* We overwrite (read as annihilate) all output functions here */ +#define PRINTF(...) +#define putstring(...) +#define putchar(...) +#endif /* DEBUG */ + + +#define SEND_BATTERY_INFO 0 +#if SEND_BATTERY_INFO +#include "sensors-example.h" +static void bc_rx(struct broadcast_conn *c, const rimeaddr_t *from) { + return; +} + +static const struct broadcast_callbacks bc_cb = { bc_rx }; +static struct broadcast_conn bc_con; +#endif + +#if BUTTON_SENSOR_ON +extern const struct sensors_sensor button_1_sensor, button_2_sensor; +#endif + +/*---------------------------------------------------------------------------*/ +PROCESS(sensors_test_process, "Sensor Test Process"); +#if (CONTIKI_TARGET_SENSINODE && BUTTON_SENSOR_ON) +PROCESS(buttons_test_process, "Button Test Process"); +AUTOSTART_PROCESSES(&sensors_test_process, &buttons_test_process); +#else +AUTOSTART_PROCESSES(&sensors_test_process); +#endif +/*---------------------------------------------------------------------------*/ +#if BUTTON_SENSOR_ON +PROCESS_THREAD(buttons_test_process, ev, data) +{ + struct sensors_sensor *sensor; + + PROCESS_BEGIN(); + + while (1) { + + PROCESS_WAIT_EVENT_UNTIL(ev == sensors_event); + + /* If we woke up after a sensor event, inform what happened */ + sensor = (struct sensors_sensor *)data; + if(sensor == &button_1_sensor) { + leds_toggle(LEDS_GREEN); + } else if(sensor == &button_2_sensor) { + watchdog_reboot(); + } + } + + PROCESS_END(); +} +#endif +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(sensors_test_process, ev, data) +{ + static struct etimer et; +#if SEND_BATTERY_INFO + /* Node Time */ + static struct sensor_data sd; +#endif + + /* Sensor Values */ + static int rv; + static struct sensors_sensor * sensor; + static float sane = 0; + static int dec; + static float frac; + +#if SEND_BATTERY_INFO + PROCESS_EXITHANDLER(broadcast_close(&bc_con);) +#endif + + PROCESS_BEGIN(); + + putstring("========================\n"); + putstring("Starting Sensor Example.\n"); + putstring("========================\n"); + +#if SEND_BATTERY_INFO + broadcast_open(&bc_con, BATTERY_RIME_CHANNEL, &bc_cb); +#endif + + /* Set an etimer. We take sensor readings when it expires and reset it. */ + etimer_set(&et, CLOCK_SECOND * 2); + + while (1) { + + PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); + + /* + * Request some ADC conversions + * Return value -1 means sensor not available or turned off in conf + */ + sensor = sensors_find(ADC_SENSOR); + if (sensor) { + putstring("------------------\n"); + leds_on(LEDS_RED); + /* + * Temperature: + * Using 1.25V ref. voltage (1250mV). + * Typical Voltage at 0°C : 743 mV + * Typical Co-efficient : 2.45 mV/°C + * Offset at 25°C : 30 (this varies and needs calibration) + * + * Thus, at 12bit resolution: + * + * ADC x 1250 / 2047 - (743 + 30) 0.61065 x ADC - 773 + * T = ------------------------------ ~= ------------------- °C + * 2.45 2.45 + */ + rv = sensor->value(ADC_SENSOR_TYPE_TEMP); + if(rv != -1) { + sane = ((rv * 0.61065 - 773) / 2.45); + dec = sane; + frac = sane - dec; + PRINTF(" Temp=%d.%02u C (%d)\n", dec, (unsigned int)(frac*100), rv); + } + /* + * Accelerometer: Freescale Semiconductor MMA7340L + * Using 1.25V ref. voltage. + * Sensitivity: 0.44 mV/g in ±3g mode. + * 0.1175 mV/g in ±11g mode. + * Typical 0g Vout = 1.65V (both modes, Vdd=3.3V, T=25°C) + * ADC Input Voltage is 1/3 Accelerometer Output Voltage + * + * +3g -> 2.97V Acc Out -> 0.9900V ADC Input -> 1621 + * +1g -> 2.09V Acc Out -> 0.6967V ADC Input -> 1141 + * 0g -> 1.65V Acc Out -> 0.5500V ADC Input -> 901 + * -1g -> 1.21V Acc Out -> 0.4033V ADC Input -> 660 + * -3g -> 0.33V Acc Out -> 0.1100V ADC Input -> 180 + * + * Thus, at 12bit resolution, ±3g mode: + * ADC x 1.25 x 3 + * Vout = -------------- V + * 2047 + * + * Vout - 0g Vout - 1.65 + * Acc = ----------- = ----------- g + * Sensitivity 0.44 + * + * Similar calc. for ±11g with 0.1175V increments + * + * This is only valid if you set ACC_SENSOR_CONF_GSEL 0 in contiki-conf.h + */ + rv = sensor->value(ADC_SENSOR_TYPE_ACC_X); + if(rv != -1) { + sane = ((rv * 3.75 / 2047) - 1.65) / 0.44; + dec = sane; + frac = sane - dec; + frac = (frac < 0) ? -frac : frac; + + /* + * This will fail for numbers like -0.xyz (since there is no such thing + * as -0. We manually add a minus sign in the printout if sane is neg + * and dec is 0. + * This is the wrong way to do it... + */ + putstring(" AccX="); + if(sane < 0 && dec == 0) { + putchar('-'); + } + PRINTF("%d.%02ug (%d)\n", dec, (unsigned int)(frac*100), rv); + } + rv = sensor->value(ADC_SENSOR_TYPE_ACC_Y); + if(rv != -1) { + sane = ((rv * 3.75 / 2047) - 1.65) / 0.44; + dec = sane; + frac = sane - dec; + frac = (frac < 0) ? -frac : frac; + putstring(" AccY="); + if(sane < 0 && dec == 0) { + putchar('-'); + } + PRINTF("%d.%02ug (%d)\n", dec, (unsigned int)(frac*100), rv); + } + rv = sensor->value(ADC_SENSOR_TYPE_ACC_Z); + if(rv != -1) { + sane = ((rv * 3.75 / 2047) - 1.65) / 0.44; + dec = sane; + frac = sane - dec; + frac = (frac < 0) ? -frac : frac; + putstring(" AccZ="); + if(sane < 0 && dec == 0) { + putchar('-'); + } + PRINTF("%d.%02ug (%d)\n", dec, (unsigned int)(frac*100), rv); + } + /* + * Light: Vishay Semiconductors TEPT4400 + * Using 1.25V ref. voltage. + * For 600 Lux illuminance, the sensor outputs 1mA current (0.9V ADC In) + * 600 lux = 1mA output => 1473 ADC value at 12 bit resolution) + * + * Thus, at 12bit resolution: + * 600 x 1.25 x ADC + * Lux = ---------------- ~= ADC * 0.4071 + * 2047 x 0.9 + */ + rv = sensor->value(ADC_SENSOR_TYPE_LIGHT); + if(rv != -1) { + sane = (float)(rv * 0.4071); + dec = sane; + frac = sane - dec; + PRINTF(" Light=%d.%02ulux (%d)\n", dec, (unsigned int)(frac*100), rv); + } + /* + * Power Supply Voltage. + * Using 1.25V ref. voltage. + * AD Conversion on VDD/3 + * + * Thus, at 12bit resolution: + * + * ADC x 1.25 x 3 + * Supply = -------------- V + * 2047 + */ + rv = sensor->value(ADC_SENSOR_TYPE_VDD); +#if SEND_BATTERY_INFO + sd.vdd = rv; +#endif + if(rv != -1) { + sane = rv * 3.75 / 2047; + dec = sane; + frac = sane - dec; + PRINTF("Supply=%d.%02uV (%d)\n", dec, (unsigned int)(frac*100), rv); + /* Store rv temporarily in dec so we can use it for the battery */ + dec = rv; + } + /* + * Battery Voltage - Only 2/3 of the actual voltage reach the ADC input + * Using 1.25V ref. voltage would result in 2047 AD conversions all the + * time since ADC-in would be gt 1.25. We thus use AVDD_SOC as ref. + * + * Thus, at 12bit resolution (assuming VDD is 3.3V): + * + * ADC x 3.3 x 3 ADC x 4.95 + * Battery = ------------- = ---------- V + * 2047 x 2 2047 + * + * Replacing the 3.3V with an ADC reading of the actual VDD would yield + * better accuracy. See monitor-node.c for an example. + * + * 3 x ADC x VDD x 3.75 ADC x VDD x 11.25 + * Battery = -------------------- = ----------------- V + * 2 x 2047 x 2047 0x7FE002 + * + */ + rv = sensor->value(ADC_SENSOR_TYPE_BATTERY); + if(rv != -1) { + /* Instead of hard-coding 3.3 here, use the latest VDD (stored in dec) + * (slightly inaccurate still, but better than crude 3.3) */ + sane = (11.25 * rv * dec) / (0x7FE002); + dec = sane; + frac = sane - dec; + PRINTF(" Batt.=%d.%02uV (%d)\n", dec, (unsigned int)(frac*100), rv); +#if SEND_BATTERY_INFO + sd.bat = rv; + packetbuf_copyfrom(&sd, sizeof(sd)); + broadcast_send(&bc_con); +#endif + } + leds_off(LEDS_RED); + } + etimer_reset(&et); + } + PROCESS_END(); + } +/*---------------------------------------------------------------------------*/ diff --git a/examples/sensinode/sensors/sensors-example.h b/examples/sensinode/sensors/sensors-example.h new file mode 100644 index 000000000..432d25073 --- /dev/null +++ b/examples/sensinode/sensors/sensors-example.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2010, Loughborough University - Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * Header file for the sensors example. Must be included by the + * sensing node as well as the monitor node. + * + * \author + * George Oikonomou - + */ + +#ifndef SENSORSTEST_H_ +#define SENSORSTEST_H_ + +#define BATTERY_RIME_CHANNEL 222 + +/* This is what our PDU looks like */ +struct sensor_data { + int vdd; + int bat; +}; + + +#endif /* SENSORSTEST_H_ */ diff --git a/examples/sensinode/serial-flash/Makefile b/examples/sensinode/serial-flash/Makefile new file mode 100644 index 000000000..b8c8d2fbe --- /dev/null +++ b/examples/sensinode/serial-flash/Makefile @@ -0,0 +1,13 @@ +ifndef TARGET +TARGET=sensinode +endif + +# Make absolutely certain that you specify your device here +DEFINES+=MODEL_N740 + +CONTIKI_PROJECT = flash + +all: $(CONTIKI_PROJECT) + +CONTIKI = ../../.. +include $(CONTIKI)/Makefile.include diff --git a/examples/sensinode/serial-flash/flash.c b/examples/sensinode/serial-flash/flash.c new file mode 100644 index 000000000..6593de3ee --- /dev/null +++ b/examples/sensinode/serial-flash/flash.c @@ -0,0 +1,268 @@ +/* + * Copyright (c) 2010, Loughborough University - Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * + * Example demonstrating the flash memory functionality on + * sensinode N740s + * + * \author + * George Oikonomou - + */ + +#include "contiki.h" +#include "dev/leds.h" +#include "cc2430_sfr.h" +#include "8051def.h" +#include "dev/m25p16.h" +#include "dev/n740.h" + +#define DEBUG 1 +#if DEBUG +#include +#include "sensinode-debug.h" +#define PRINTF(...) printf(__VA_ARGS__) +#define PUTBIN(b) putbin(b) +#else +#define PRINTF(...) +#define PUTBIN(b) +#endif + +static struct m25p16_rdid id; + +#define USE_SECTOR 0x10 +#define MAX_READ_CHUNK 10 +static uint8_t r_addr[3]; /* Read address: {USE_SECTOR, 0, 0} */ +static uint8_t d_buf[MAX_READ_CHUNK]; +static uint8_t rv; +static uint8_t counter; +/*---------------------------------------------------------------------------*/ +PROCESS(serial_flash_process, "Serial Flash example"); +AUTOSTART_PROCESSES(&serial_flash_process); +/*---------------------------------------------------------------------------*/ +static void +rdsr() +{ + rv = 0; + + n740_analog_deactivate(); + rv = m25p16_rdsr(); + n740_analog_activate(); + + PRINTF("RDSR: "); + putbin(rv); + PRINTF("\n"); +} +/*---------------------------------------------------------------------------*/ +static void +rdid() +{ + uint8_t i; + memset(&id, 0, sizeof(struct m25p16_rdid)); + + n740_analog_deactivate(); + m25p16_rdid(&id); + n740_analog_activate(); + + PRINTF("RDID: 0x%02x\n", id.man_id); + PRINTF("Type: 0x%02x\n", id.mem_type); + PRINTF("Size: 0x%02x\n", id.mem_size); + PRINTF("ULen: 0x%02x\n", id.uid_len); + PRINTF(" UID:"); + for(i = 0; i < id.uid_len; i++) { + PRINTF(" %02x", id.uid[i]); + } + PRINTF("\n"); +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(serial_flash_process, ev, data) +{ + static struct etimer et; + uint8_t i; + + PROCESS_BEGIN(); + + PRINTF("Start\n"); + + memset(r_addr, 0, 3); + r_addr[0] = USE_SECTOR; + counter = 1; + + while(1) { + + /* Delay */ + etimer_set(&et, CLOCK_SECOND * 2); + PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); + + leds_on(LEDS_GREEN); + + if(counter == 0) { + n740_analog_deactivate(); + rv = m25p16_rdsr(); + n740_analog_activate(); + /* If counter==0, we started Bulk Erasing earlier. Check if we still are */ + if(rv & M25P16_SR_WIP) { + PRINTF("Yield [%02x]\n", rv); + } else { + counter = 1; + } + } + if(counter) { + /* + * Take us out of Deep Power Down - On first power-on, the device will + * go to stand by mode (which is not DP). However, we drop to DP at the + * end of every loop. RES must be 0x14. This is the old style signature + * and is only still there for backward compatibility. + */ + n740_analog_deactivate(); + rv = m25p16_res_res(); + n740_analog_activate(); + + PRINTF(" RES: 0x%02x\n", rv); + + n740_analog_deactivate(); + rv = M25P16_WIP(); + n740_analog_activate(); + + PRINTF("========\n"); + memset(d_buf, 0, MAX_READ_CHUNK); + + + /* + * Read Device ID: Return values must be: + * man_id: 0x20 (Numonyx) + * mem_type: 0x20 + * mem_size: 0x15 (2 ^ 0x15 bytes = 2MB) + * uid_len: number of bytes in UID + * uid: Either all zeroes or a customized factory data content + * */ + rdid(); + + /* Check the value of our Status Register (SR) */ + rdsr(); + + /* Enable Write: Set Bit 1 in the SR to 1 (bit WEL) */ + PRINTF("WREN\n"); + n740_analog_deactivate(); + m25p16_wren(); + n740_analog_activate(); + + /* Confirm: SR & 0x02 must be 1 */ + rdsr(); + + /* Disable the WEL bit */ + PRINTF("WRDI\n"); + n740_analog_deactivate(); + m25p16_wrdi(); + n740_analog_activate(); + + /* Confirm: SR & 0x02 must be 0 */ + rdsr(); + + /* Write something to the SR. We don't need to explicitly set WEL, wrsr() + * will do it for us. When the cycle ends, WEL will go low */ + PRINTF("WRSR\n"); + n740_analog_deactivate(); + + /* For instance, let's protect sector 31 (that's the highest one) */ + m25p16_wrsr(M25P16_SR_BP0); + + /* + * While this is running, WEL should remain high and WIP (bit 0) should + * also be high. When this ends, WIP and WEL will go low. + * + * While the write is in ongoing, we can still read the SR to check the + * cycle's progress + */ + while(M25P16_WIP()); + + n740_analog_activate(); + + /* Confirm: SR & 0x02 must be 0 */ + rdsr(); + + /* Read MAX_READ_CHUNK bytes from Page 0x000000 */ + memset(d_buf, 0, MAX_READ_CHUNK); + n740_analog_deactivate(); + m25p16_read(r_addr, d_buf, MAX_READ_CHUNK); + n740_analog_activate(); + + PRINTF("READ:"); + for(i = 0; i < MAX_READ_CHUNK; i++) { + PRINTF(" %02x", d_buf[i]); + } + PRINTF("\n"); + + /* Write MAX_READ_CHUNK bytes to the same Page */ + PRINTF("WRITE\n"); + for(i = 0; i < MAX_READ_CHUNK; i++) { + d_buf[i] = i; + } + n740_analog_deactivate(); + + /* We don't need to wren() explicitly, pp() will do that for us */ + m25p16_pp(r_addr, d_buf, MAX_READ_CHUNK); + + /* Wait for the cycle */ + while(M25P16_WIP()); + + /* Trash our data buffer */ + memset(d_buf, 0, MAX_READ_CHUNK); + + PRINTF("ERASE\n"); + n740_analog_deactivate(); + + /* Bulk erase every 4 loops, sector erase otherwise */ + + /* Bulk Erase: This takes a few seconds so we can't really block on it. + * It'd be a bad thing to do and the watchdog would bark anyway. + * Bulk Erase will only be accepted if all SR_BP[2:0] == 0 */ + if((counter % 4) == 0) { + m25p16_wrsr(0); + while(M25P16_WIP()); + m25p16_be(); + counter = 0; + } else { + m25p16_se(USE_SECTOR); + while(M25P16_WIP()); + /* Drop to Deep Power Down */ + m25p16_dp(); + counter ++; + } + n740_analog_activate(); + } + leds_off(LEDS_GREEN); + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ diff --git a/examples/sensinode/sniffer/Makefile b/examples/sensinode/sniffer/Makefile new file mode 100644 index 000000000..07f074069 --- /dev/null +++ b/examples/sensinode/sniffer/Makefile @@ -0,0 +1,16 @@ +ifndef TARGET +TARGET=sensinode +endif + +# Make absolutely certain that you specify your device here +DEFINES+=MODEL_N601,PROJECT_CONF_H + +PROJECT_SOURCEFILES += stub-rdc.c + +CONTIKI_PROJECT = sniffer + +all: $(CONTIKI_PROJECT) + +CONTIKI = ../../.. + +include $(CONTIKI)/Makefile.include diff --git a/examples/sensinode/sniffer/README b/examples/sensinode/sniffer/README new file mode 100644 index 000000000..d51ad2ce8 --- /dev/null +++ b/examples/sensinode/sniffer/README @@ -0,0 +1,14 @@ +A very simple sniffer for sensinode devices. + +The cc2430 RF driver supports outputting all captured packets in hexdump +format. We turn this on, and turn everything else off. We use a stub RDC +driver to make sure no incoming packet ever goes up the stack and no packet is +ever sent out. + +We only initialise the radio driver instead of the entire stack by over-riding +the default netstack.c with the one in this directory. + +You can then pipe the sniffer's output to the n601-cap util, which will convert +the hexdumps to pcap format, which can in turn be piped to wireshark. This is +handy if we want live capture of the lowpan traffic from wireshark. See the +README in n601-cap for more details diff --git a/examples/sensinode/sniffer/netstack.c b/examples/sensinode/sniffer/netstack.c new file mode 100644 index 000000000..2551f82fe --- /dev/null +++ b/examples/sensinode/sniffer/netstack.c @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2010, Loughborough University - Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * Stub file overriding core/net/netstack.c. What we want to achieve + * here is call netstack_init from main without initialising the RDC, + * MAC and Network layers. It will just turn on the radio instead. + * + * \author + * George Oikonomou - + */ + +#include "netstack.h" +/*---------------------------------------------------------------------------*/ +void +netstack_init(void) +{ + NETSTACK_RADIO.init(); +} +/*---------------------------------------------------------------------------*/ + diff --git a/examples/sensinode/sniffer/project-conf.h b/examples/sensinode/sniffer/project-conf.h new file mode 100644 index 000000000..3ed5ec99e --- /dev/null +++ b/examples/sensinode/sniffer/project-conf.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2010, Loughborough University - Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * Project specific configuration defines for the sniffer example. + * + * We make sure that the radio driver outputs all packets in hexdump + * format. + * + * \author + * George Oikonomou - + */ + +#ifndef PROJECT_CONF_H_ +#define PROJECT_CONF_H_ + +#define CC2430_RF_CONF_HEXDUMP 1 +#define CC2430_RF_CONF_AUTOACK 0 +#define NETSTACK_CONF_RDC stub_rdc_driver +#define ADC_SENSOR_CONF_ON 0 +#define LPM_CONF_MODE 0 + +#endif /* PROJECT_CONF_H_ */ diff --git a/examples/sensinode/sniffer/sniffer.c b/examples/sensinode/sniffer/sniffer.c new file mode 100644 index 000000000..ffde21209 --- /dev/null +++ b/examples/sensinode/sniffer/sniffer.c @@ -0,0 +1,54 @@ +/* + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + */ + +#include "contiki.h" +#include "cc2430_sfr.h" + +#define DEBUG DEBUG_NONE +#include "net/uip-debug.h" + +/*---------------------------------------------------------------------------*/ +PROCESS(sniffer_process, "Sniffer process"); +AUTOSTART_PROCESSES(&sniffer_process); +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(sniffer_process, ev, data) +{ + + PROCESS_BEGIN(); + + PRINTF("Sniffer started\n"); + + /* Turn off cc2430 Address Recognition - We need to accept all frames */ + MDMCTRL0H &= ~0x08; + + PROCESS_EXIT(); + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ diff --git a/examples/sensinode/sniffer/stub-rdc.c b/examples/sensinode/sniffer/stub-rdc.c new file mode 100644 index 000000000..063a43659 --- /dev/null +++ b/examples/sensinode/sniffer/stub-rdc.c @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2010, Loughborough University - Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * Definition of a fake RDC driver to be used with passive + * examples. The sniffer will never send packets and it will never + * push incoming packets up the stack. We do this by defining this + * driver as our RDC. We then drop everything + * + * \author + * George Oikonomou - + */ + +#include "net/mac/mac.h" +#include "net/mac/rdc.h" +/*---------------------------------------------------------------------------*/ +static void +send(mac_callback_t sent, void *ptr) +{ + if(sent) { + sent(ptr, MAC_TX_OK, 1); + } +} +/*---------------------------------------------------------------------------*/ +static void +send_list(mac_callback_t sent, void *ptr, struct rdc_buf_list *list) +{ + if(sent) { + sent(ptr, MAC_TX_OK, 1); + } +} +/*---------------------------------------------------------------------------*/ +static void +input(void) +{ +} +/*---------------------------------------------------------------------------*/ +static int +on(void) +{ + return 1; +} +/*---------------------------------------------------------------------------*/ +static int +off(int keep_radio_on) +{ + return keep_radio_on; +} +/*---------------------------------------------------------------------------*/ +static unsigned short +cca(void) +{ + return 0; +} +/*---------------------------------------------------------------------------*/ +static void +init(void) +{ +} +/*---------------------------------------------------------------------------*/ +const struct rdc_driver stub_rdc_driver = { + "stub-rdc", + init, + send, + send_list, + input, + on, + off, + cca, +}; +/*---------------------------------------------------------------------------*/ diff --git a/examples/sensinode/timer-test.c b/examples/sensinode/timer-test.c new file mode 100644 index 000000000..163574326 --- /dev/null +++ b/examples/sensinode/timer-test.c @@ -0,0 +1,123 @@ +/** + * \file + * Tests related to clocks and timers + * + * This is clock_test.c plus a small addition by George Oikonomou + * (Loughborough University)in order to test the rtimer + * + * \author + * Zach Shelby (Original) + * George Oikonomou - (rtimer code) + * + */ + +#include "contiki.h" +#include "sys/clock.h" +#include "sys/rtimer.h" +#include "dev/leds.h" + +#include +/*---------------------------------------------------------------------------*/ +#define TEST_CLOCK_DELAY 1 +#define TEST_RTIMER 1 +#define TEST_ETIMER 1 +#define TEST_CLOCK_SECONDS 1 +/*---------------------------------------------------------------------------*/ +PROCESS(clock_test_process, "Clock test process"); +AUTOSTART_PROCESSES(&clock_test_process); +/*---------------------------------------------------------------------------*/ +#if TEST_RTIMER +void +rt_callback(struct rtimer *t, void *ptr) { + printf("Task called at %u\n", RTIMER_NOW()); +} +#endif +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(clock_test_process, ev, data) +{ + static struct etimer et; + +#if TEST_CLOCK_DELAY + static clock_time_t start_count, end_count, diff; +#endif +#if TEST_CLOCK_SECONDS + static unsigned long sec; +#endif +#if TEST_ETIMER + static clock_time_t count; +#endif +#if TEST_RTIMER + uint16_t rt_now, rt_for; + static struct rtimer rt; +#endif + static uint8_t i; + + PROCESS_BEGIN(); + +#if TEST_CLOCK_DELAY + printf("Clock delay test (10 x (10,000xi) cycles):\n"); + i = 1; + while(i < 6) { + start_count = clock_time(); + clock_delay(10000 * i); + end_count = clock_time(); + diff = end_count - start_count; + printf("Delayed %u = %u ticks = ~%u ms\n", 10000 * i, diff, diff * 8); + i++; + } +#endif + +#if TEST_RTIMER + printf("Rtimer Test (10 x 1s):\n"); + i = 0; + while(i < 10) { + etimer_set(&et, 2*CLOCK_SECOND); + puts("======================="); + rt_now = RTIMER_NOW(); + rt_for = rt_now + RTIMER_SECOND; + printf("%Now=%u - For=%u\n", rt_now, rt_for); + if (rtimer_set(&rt, rt_for, 1, + (void (*)(struct rtimer *, void *))rt_callback, NULL) != RTIMER_OK) { + printf("Error setting\n"); + } + + PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); + i++; + } +#endif + +#if TEST_ETIMER + printf("Clock tick and etimer test (10 x 1s):\n"); + i = 0; + while(i < 10) { + etimer_set(&et, CLOCK_SECOND); + PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); + etimer_reset(&et); + + count = clock_time(); + printf("%u ticks\n", count); + + leds_toggle(LEDS_RED); + i++; + } +#endif + +#if TEST_CLOCK_SECONDS + printf("Clock seconds test (10 x 5s):\n"); + i = 0; + while(i < 10) { + etimer_set(&et, 5 * CLOCK_SECOND); + PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); + etimer_reset(&et); + + sec = clock_seconds(); + printf("%u seconds\n", (u16_t) sec); + + leds_toggle(LEDS_GREEN); + i++; + } +#endif + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ diff --git a/examples/sensinode/udp-ipv6/Makefile b/examples/sensinode/udp-ipv6/Makefile new file mode 100644 index 000000000..00a04ec2d --- /dev/null +++ b/examples/sensinode/udp-ipv6/Makefile @@ -0,0 +1,19 @@ +ifndef TARGET +TARGET=sensinode +endif + +# Make absolutely certain that you specify your device here +DEFINES+=MODEL_N740,PROJECT_CONF_H + +# This example won't fit in flash without banking so we turn it on +HAVE_BANKING=1 +UIP_CONF_IPV6=1 + +CONTIKI_SOURCEFILES += ping6.c + +CONTIKI_PROJECT = client server +all: $(CONTIKI_PROJECT) + +CONTIKI = ../../.. + +include $(CONTIKI)/Makefile.include diff --git a/examples/sensinode/udp-ipv6/client.c b/examples/sensinode/udp-ipv6/client.c new file mode 100644 index 000000000..c20643c54 --- /dev/null +++ b/examples/sensinode/udp-ipv6/client.c @@ -0,0 +1,212 @@ +/* + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + */ + +#include "contiki.h" +#include "contiki-lib.h" +#include "contiki-net.h" + +#include +#include "dev/leds.h" + +#if CONTIKI_TARGET_SENSINODE +#include "dev/sensinode-sensors.h" +#include "sensinode-debug.h" +#else +#define putstring(s) +#define puthex(s) +#define putchar(s) +#endif + +#define DEBUG DEBUG_NONE +#include "net/uip-debug.h" + +#define SEND_INTERVAL 2 * CLOCK_SECOND +#define MAX_PAYLOAD_LEN 40 + +static char buf[MAX_PAYLOAD_LEN]; + +/* Our destinations and udp conns. One link-local and one global */ +#define LOCAL_CONN_PORT 3001 +static struct uip_udp_conn *l_conn; +#if UIP_CONF_ROUTER +#define GLOBAL_CONN_PORT 3002 +static struct uip_udp_conn *g_conn; +#endif + +/*---------------------------------------------------------------------------*/ +PROCESS(udp_client_process, "UDP client process"); +#if BUTTON_SENSOR_ON +PROCESS_NAME(ping6_process); +AUTOSTART_PROCESSES(&udp_client_process, &ping6_process); +#else +AUTOSTART_PROCESSES(&udp_client_process); +#endif +/*---------------------------------------------------------------------------*/ +static void +tcpip_handler(void) +{ + leds_on(LEDS_GREEN); + if(uip_newdata()) { + putstring("0x"); + puthex(uip_datalen()); + putstring(" bytes response=0x"); + puthex((*(uint16_t *) uip_appdata) >> 8); + puthex((*(uint16_t *) uip_appdata) & 0xFF); + putchar('\n'); + } + leds_off(LEDS_GREEN); + return; +} +/*---------------------------------------------------------------------------*/ +static void +timeout_handler(void) +{ + static int seq_id; + struct uip_udp_conn * this_conn; + + leds_on(LEDS_RED); + memset(buf, 0, MAX_PAYLOAD_LEN); + seq_id++; + +#if UIP_CONF_ROUTER + /* evens / odds */ + if(seq_id & 0x01) { + this_conn = l_conn; + } else { + this_conn = g_conn; + } +#else + this_conn = l_conn; +#endif + + PRINTF("Client to: "); + PRINT6ADDR(&this_conn->ripaddr); + + memcpy(buf, &seq_id, sizeof(seq_id)); + + PRINTF(" Remote Port %u,", UIP_HTONS(this_conn->rport)); + PRINTF(" (msg=0x%04x), %u bytes\n", *(uint16_t *) buf, sizeof(seq_id)); + +#if SEND_TOO_LARGE_PACKET_TO_TEST_FRAGMENTATION + uip_udp_packet_send(this_conn, buf, UIP_APPDATA_SIZE); +#else /* SEND_TOO_LARGE_PACKET_TO_TEST_FRAGMENTATION */ + uip_udp_packet_send(this_conn, buf, sizeof(seq_id)); +#endif /* SEND_TOO_LARGE_PACKET_TO_TEST_FRAGMENTATION */ + leds_off(LEDS_RED); +} +/*---------------------------------------------------------------------------*/ +static void +print_local_addresses(void) +{ + int i; + uint8_t state; + + PRINTF("Client IPv6 addresses:\n"); + for(i = 0; i < UIP_DS6_ADDR_NB; i++) { + state = uip_ds6_if.addr_list[i].state; + if(uip_ds6_if.addr_list[i].isused && (state == ADDR_TENTATIVE || state + == ADDR_PREFERRED)) { + PRINT6ADDR(&uip_ds6_if.addr_list[i].ipaddr); + if (state == ADDR_TENTATIVE) { + uip_ds6_if.addr_list[i].state = ADDR_PREFERRED; + } + PRINTF(" state: %u.\n", uip_ds6_if.addr_list[i].state); + } + } + return; +} +/*---------------------------------------------------------------------------*/ +#if UIP_CONF_ROUTER +static void +set_global_address(void) +{ + uip_ipaddr_t ipaddr; + + uip_ip6addr(&ipaddr, 0x2001, 0x630, 0x301, 0x6453, 0, 0, 0, 0); + uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); + uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF); +} +#endif /* UIP_CONF_ROUTER */ +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(udp_client_process, ev, data) +{ + static struct etimer et; + uip_ipaddr_t ipaddr; + + PROCESS_BEGIN(); + PRINTF("UDP client process started\n"); + +#if UIP_CONF_ROUTER + set_global_address(); +#endif + + print_local_addresses(); + + uip_ip6addr(&ipaddr,0xfe80,0,0,0,0x0215,0x2000,0x0002,0x0302); + /* new connection with remote host */ + l_conn = udp_new(&ipaddr, UIP_HTONS(3000), NULL); + if(!l_conn) { + PRINTF("udp_new l_conn error.\n"); + } + udp_bind(l_conn, UIP_HTONS(LOCAL_CONN_PORT)); + + PRINTF("Link-Local connection with "); + PRINT6ADDR(&l_conn->ripaddr); + PRINTF(" local/remote port %u/%u\n", + UIP_HTONS(l_conn->lport), UIP_HTONS(l_conn->rport)); + +#if UIP_CONF_ROUTER + uip_ip6addr(&ipaddr,0x2001,0x630,0x301,0x6453,0x0215,0x2000,0x0002,0x0302); + g_conn = udp_new(&ipaddr, UIP_HTONS(3000), NULL); + if(!g_conn) { + PRINTF("udp_new g_conn error.\n"); + } + udp_bind(g_conn, UIP_HTONS(GLOBAL_CONN_PORT)); + + PRINTF("Global connection with "); + PRINT6ADDR(&g_conn->ripaddr); + PRINTF(" local/remote port %u/%u\n", + UIP_HTONS(g_conn->lport), UIP_HTONS(g_conn->rport)); +#endif + + etimer_set(&et, SEND_INTERVAL); + + while(1) { + PROCESS_YIELD(); + if(etimer_expired(&et)) { + timeout_handler(); + etimer_restart(&et); + } else if(ev == tcpip_event) { + tcpip_handler(); + } + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ diff --git a/examples/sensinode/udp-ipv6/ping6.c b/examples/sensinode/udp-ipv6/ping6.c new file mode 100644 index 000000000..a88ebc7dc --- /dev/null +++ b/examples/sensinode/udp-ipv6/ping6.c @@ -0,0 +1,147 @@ +/* + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + */ + +#include "contiki.h" +#include "contiki-lib.h" +#include "contiki-net.h" +#include +#include + +#if CONTIKI_TARGET_SENSINODE +#include "dev/sensinode-sensors.h" +#include "sensinode-debug.h" +#endif + +#define DEBUG 0 +#if DEBUG +#include +#define PRINTF(...) printf(__VA_ARGS__) +#define PRINT6ADDR(addr) PRINTF(" %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x ", ((u8_t *)addr)[0], ((u8_t *)addr)[1], ((u8_t *)addr)[2], ((u8_t *)addr)[3], ((u8_t *)addr)[4], ((u8_t *)addr)[5], ((u8_t *)addr)[6], ((u8_t *)addr)[7], ((u8_t *)addr)[8], ((u8_t *)addr)[9], ((u8_t *)addr)[10], ((u8_t *)addr)[11], ((u8_t *)addr)[12], ((u8_t *)addr)[13], ((u8_t *)addr)[14], ((u8_t *)addr)[15]) +#define PRINTLLADDR(lladdr) PRINTF(" %02x:%02x:%02x:%02x:%02x:%02x ",lladdr->addr[0], lladdr->addr[1], lladdr->addr[2], lladdr->addr[3],lladdr->addr[4], lladdr->addr[5]) +#else +#define PRINTF(...) +#define PRINT6ADDR(addr) +#endif + +#define PING6_NB 5 +#define PING6_DATALEN 16 + +#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) +#define UIP_ICMP_BUF ((struct uip_icmp_hdr *)&uip_buf[uip_l2_l3_hdr_len]) + +static struct etimer ping6_periodic_timer; +static u8_t count = 0; +static u16_t addr[8]; +static uip_ipaddr_t dest_addr; + +PROCESS(ping6_process, "PING6 process"); +/*---------------------------------------------------------------------------*/ +static void +ping6handler() +{ + if(count < PING6_NB) { + UIP_IP_BUF->vtc = 0x60; + UIP_IP_BUF->tcflow = 1; + UIP_IP_BUF->flow = 0; + UIP_IP_BUF->proto = UIP_PROTO_ICMP6; + UIP_IP_BUF->ttl = uip_ds6_if.cur_hop_limit; + uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, &dest_addr); + uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr); + + UIP_ICMP_BUF->type = ICMP6_ECHO_REQUEST; + UIP_ICMP_BUF->icode = 0; + /* set identifier and sequence number to 0 */ + memset((uint8_t *)UIP_ICMP_BUF + UIP_ICMPH_LEN, 0, 4); + /* put one byte of data */ + memset((uint8_t *)UIP_ICMP_BUF + UIP_ICMPH_LEN + UIP_ICMP6_ECHO_REQUEST_LEN, + count, PING6_DATALEN); + + + uip_len = UIP_ICMPH_LEN + UIP_ICMP6_ECHO_REQUEST_LEN + UIP_IPH_LEN + PING6_DATALEN; + UIP_IP_BUF->len[0] = (u8_t)((uip_len - 40) >> 8); + UIP_IP_BUF->len[1] = (u8_t)((uip_len - 40) & 0x00FF); + + UIP_ICMP_BUF->icmpchksum = 0; + UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum(); + + + PRINTF("Echo Request to"); + PRINT6ADDR(&UIP_IP_BUF->destipaddr); + PRINTF("from"); + PRINT6ADDR(&UIP_IP_BUF->srcipaddr); + PRINTF("\n"); + UIP_STAT(++uip_stat.icmp.sent); + + tcpip_ipv6_output(); + + count++; + etimer_set(&ping6_periodic_timer, 3 * CLOCK_SECOND); + } else { + count = 0; + } +} + +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(ping6_process, ev, data) +{ + +#if (CONTIKI_TARGET_SENSINODE && BUTTON_SENSOR_ON) + static struct sensors_sensor * btn; +#endif + + PROCESS_BEGIN(); + PRINTF("ping6 running.\n"); + PRINTF("Button 1: 5 pings 16 byte payload.\n"); + + uip_ip6addr(&dest_addr,0x2001,0x470,0x55,0,0x0215,0x2000,0x0002,0x0302); + count = 0; + + /* Check if we have buttons */ +#if (CONTIKI_TARGET_SENSINODE && BUTTON_SENSOR_ON) + btn = sensors_find(BUTTON_1_SENSOR); +#endif + + while(1) { + PROCESS_YIELD(); + +#if (CONTIKI_TARGET_SENSINODE && BUTTON_SENSOR_ON) + if(ev == sensors_event) { + if(data == btn && count == 0) { + ping6handler(); + } + } +#endif + if(etimer_expired(&ping6_periodic_timer)) { + ping6handler(); + } + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ diff --git a/examples/sensinode/udp-ipv6/project-conf.h b/examples/sensinode/udp-ipv6/project-conf.h new file mode 100644 index 000000000..672ac522b --- /dev/null +++ b/examples/sensinode/udp-ipv6/project-conf.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2010, Loughborough University - Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + * $Id$ + */ + +/** + * \file + * Project specific configuration defines for the UDP client/server + * example. + * + * We just turn on buttons + * + * \author + * George Oikonomou - + */ + +#ifndef PROJECT_CONF_H_ +#define PROJECT_CONF_H_ + +#define BUTTON_SENSOR_CONF_ON 1 + +#endif /* PROJECT_CONF_H_ */ diff --git a/examples/sensinode/udp-ipv6/server.c b/examples/sensinode/udp-ipv6/server.c new file mode 100644 index 000000000..f3ab93202 --- /dev/null +++ b/examples/sensinode/udp-ipv6/server.c @@ -0,0 +1,197 @@ +/* + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + */ + +#include "contiki.h" +#include "contiki-lib.h" +#include "contiki-net.h" + +#include + +#define DEBUG DEBUG_NONE +#include "net/uip-debug.h" +#include "dev/watchdog.h" +#include "dev/leds.h" +#include "net/rpl/rpl.h" + +#if CONTIKI_TARGET_SENSINODE +#include "dev/sensinode-sensors.h" +#include "sensinode-debug.h" +#else +#define putstring(s) +#endif + +#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) +#define UIP_UDP_BUF ((struct uip_udp_hdr *)&uip_buf[uip_l2_l3_hdr_len]) + +#define MAX_PAYLOAD_LEN 120 + +static struct uip_udp_conn *server_conn; +static char buf[MAX_PAYLOAD_LEN]; +static uint16_t len; + +#if UIP_CONF_ROUTER +static uip_ipaddr_t ipaddr; +#endif + +#define SERVER_REPLY 1 + +/* Should we act as RPL root? */ +#define SERVER_RPL_ROOT 1 +/*---------------------------------------------------------------------------*/ +extern const struct sensors_sensor adc_sensor; +/*---------------------------------------------------------------------------*/ +PROCESS(udp_server_process, "UDP server process"); +AUTOSTART_PROCESSES(&udp_server_process); +/*---------------------------------------------------------------------------*/ +static void +tcpip_handler(void) +{ + memset(buf, 0, MAX_PAYLOAD_LEN); + if(uip_newdata()) { + leds_on(LEDS_RED); + len = uip_datalen(); + memcpy(buf, uip_appdata, len); + PRINTF("%u bytes from [", len, *(uint16_t *)buf); + PRINT6ADDR(&UIP_IP_BUF->srcipaddr); + PRINTF("]:%u", UIP_HTONS(UIP_UDP_BUF->srcport)); + PRINTF(" V=%u", *buf); + PRINTF(" I=%u", *(buf + 1)); + PRINTF(" T=%u", *(buf + 2)); + PRINTF(" Val=%u\n", *(uint16_t *)(buf + 3)); +#if SERVER_REPLY + uip_ipaddr_copy(&server_conn->ripaddr, &UIP_IP_BUF->srcipaddr); + server_conn->rport = UIP_UDP_BUF->srcport; + + uip_udp_packet_send(server_conn, buf, len); + /* Restore server connection to allow data from any node */ + uip_create_unspecified(&server_conn->ripaddr); + server_conn->rport = 0; +#endif + } + leds_off(LEDS_RED); + PRINTF("sent\n"); + return; +} +/*---------------------------------------------------------------------------*/ +#if (CONTIKI_TARGET_SENSINODE && BUTTON_SENSOR_ON && (DEBUG==DEBUG_PRINT)) +static void +print_stats() +{ + PRINTF("tl=%lu, ts=%lu, bs=%lu, bc=%lu\n", + rimestats.toolong, rimestats.tooshort, rimestats.badsynch, rimestats.badcrc); + PRINTF("llrx=%lu, lltx=%lu, rx=%lu, tx=%lu\n", + rimestats.llrx, rimestats.lltx, rimestats.rx, rimestats.tx); +} +#else +#define print_stats() +#endif +/*---------------------------------------------------------------------------*/ +static void +print_local_addresses(void) +{ + int i; + uint8_t state; + + PRINTF("Server IPv6 addresses:\n"); + for(i = 0; i < UIP_DS6_ADDR_NB; i++) { + state = uip_ds6_if.addr_list[i].state; + if(uip_ds6_if.addr_list[i].isused && (state == ADDR_TENTATIVE || state + == ADDR_PREFERRED)) { + PRINTF(" "); + PRINT6ADDR(&uip_ds6_if.addr_list[i].ipaddr); + PRINTF("\n"); + if (state == ADDR_TENTATIVE) { + uip_ds6_if.addr_list[i].state = ADDR_PREFERRED; + } + } + } +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(udp_server_process, ev, data) +{ +#if (CONTIKI_TARGET_SENSINODE && BUTTON_SENSOR_ON) + static struct sensors_sensor *b1; + static struct sensors_sensor *b2; +#endif +#if SERVER_RPL_ROOT + rpl_dag_t *dag; +#endif + PROCESS_BEGIN(); + putstring("Starting UDP server\n"); + +#if (CONTIKI_TARGET_SENSINODE && BUTTON_SENSOR_ON) + putstring("Button 1: Print RIME stats\n"); + putstring("Button 2: Reboot\n"); +#endif + +#if SERVER_RPL_ROOT + uip_ip6addr(&ipaddr, 0x2001, 0x630, 0x301, 0x6453, 0, 0, 0, 0); + uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); + uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF); + + print_local_addresses(); + + dag = rpl_set_root(RPL_DEFAULT_INSTANCE, &uip_ds6_get_global(ADDR_PREFERRED)->ipaddr); + if(dag != NULL) { + uip_ip6addr(&ipaddr, 0x2001, 0x630, 0x301, 0x6453, 0, 0, 0, 0); + rpl_set_prefix(dag, &ipaddr, 64); + PRINTF("Created a new RPL dag with ID: "); + PRINT6ADDR(&dag->dag_id); + PRINTF("\n"); + } +#endif /* SERVER_RPL_ROOT */ + + server_conn = udp_new(NULL, UIP_HTONS(0), NULL); + udp_bind(server_conn, UIP_HTONS(3000)); + + PRINTF("Listen port: 3000, TTL=%u\n", server_conn->ttl); + +#if (CONTIKI_TARGET_SENSINODE && BUTTON_SENSOR_ON) + b1 = sensors_find(BUTTON_1_SENSOR); + b2 = sensors_find(BUTTON_2_SENSOR); +#endif + + while(1) { + PROCESS_YIELD(); + if(ev == tcpip_event) { + tcpip_handler(); +#if (CONTIKI_TARGET_SENSINODE && BUTTON_SENSOR_ON) + } else if(ev == sensors_event && data != NULL) { + if(data == b1) { + print_stats(); + } else if(data == b2) { + watchdog_reboot(); + } +#endif /* (CONTIKI_TARGET_SENSINODE && BUTTON_SENSOR_ON) */ + } + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ diff --git a/platform/cc2530dk/Makefile.cc2530dk b/platform/cc2530dk/Makefile.cc2530dk new file mode 100644 index 000000000..12001350f --- /dev/null +++ b/platform/cc2530dk/Makefile.cc2530dk @@ -0,0 +1,52 @@ +# cc2530dk platform makefile + +ifndef CONTIKI + $(error CONTIKI not defined! You must specify where CONTIKI resides!) +endif + +CONTIKI_TARGET_DIRS = . dev +CONTIKI_TARGET_MAIN = $(addprefix $(OBJECTDIR)/,contiki-main.rel) + +CONTIKI_TARGET_SOURCEFILES = contiki-main.c +CONTIKI_TARGET_SOURCEFILES += leds.c leds-arch.c +CONTIKI_TARGET_SOURCEFILES += sensors.c smartrf-sensors.c +CONTIKI_TARGET_SOURCEFILES += button-sensor.c adc-sensor.c smartrf-sensors.c +CONTIKI_TARGET_SOURCEFILES += serial-line.c slip-arch.c slip.c #serial-flash.c +CONTIKI_TARGET_SOURCEFILES += putchar.c debug.c + +CONTIKI_SOURCEFILES += $(CONTIKI_TARGET_SOURCEFILES) + +CLEAN += *.cc2530dk + +ifdef UIP_CONF_IPV6 + CONTIKI_TARGET_SOURCEFILES += viztool.c +endif + +FORCE: + +# .sensinode target so we can behave similar to other targets +%.$(TARGET): %.hex FORCE + cp $< $(<:.hex=.$(TARGET)) + @echo "\nReport" + @echo "===============" + @echo 'Code footprint:' + @echo 'Area Addr Size' \ + ' Decimal' + @echo '---------------------------------- -------- --------' \ + ' --------' + @echo -n 'HOME,CSEG,CONST,XINIT,GS* $(HOME_START) ' + @egrep ',CODE\)' $(<:.hex=.map) | egrep -v '(^BANK[1-9][^=])' | uniq | \ + awk '{ SUM += $$5 } END { printf "%08X = %8d", SUM, SUM }' + @echo '. bytes (REL,CON,CODE)' + @egrep '(^BANK[1-9][^=])' $(<:.hex=.map) | uniq | sort + @egrep -A 5 'Other memory' $(<:.hex=.mem) + +%.upload: %.hex + $(PROG) -P $< + +sensinode.serialdump: + $(SERIALDUMP) + +### Define the CPU directory +CONTIKI_CPU=$(CONTIKI)/cpu/cc253x +include $(CONTIKI_CPU)/Makefile.cc253x diff --git a/platform/cc2530dk/contiki-conf.h b/platform/cc2530dk/contiki-conf.h new file mode 100644 index 000000000..4eae96016 --- /dev/null +++ b/platform/cc2530dk/contiki-conf.h @@ -0,0 +1,225 @@ +#ifndef __CONTIKI_CONF_H__ +#define __CONTIKI_CONF_H__ + +#include "8051def.h" +#include "sys/cc.h" +#include + +/* Include Project Specific conf */ +#ifdef PROJECT_CONF_H +#include "project-conf.h" +#endif /* PROJECT_CONF_H */ + +/* Time type. */ +typedef unsigned short clock_time_t; + +/* Defines tick counts for a second. */ +#define CLOCK_CONF_SECOND 128 + +/* Energest Module */ +#ifndef ENERGEST_CONF_ON +#define ENERGEST_CONF_ON 0 +#endif + +/* Verbose Startup? Turning this off saves plenty of bytes of CODE in HOME */ +#define STARTUP_CONF_VERBOSE 0 + +/* More CODE space savings by turning off process names */ +#define PROCESS_CONF_NO_PROCESS_NAMES 1 + +/* + * USARTs: + * SmartRF RS232 -> USART0 / Alternative 1 (UART) + * SmartRF LCD -> USART1 / Alternative 2 (SPI) + */ +#define UART_ON_USART 0 + +#define UART1_CONF_ENABLE 0 + +#ifndef UART0_CONF_ENABLE +#define UART0_CONF_ENABLE 1 +#endif +#ifndef UART0_CONF_WITH_INPUT +#define UART0_CONF_WITH_INPUT 0 +#endif + +#ifndef UART0_CONF_HIGH_SPEED +#define UART0_CONF_HIGH_SPEED 0 +#endif + +/* Are we a SLIP bridge? */ +#if SLIP_ARCH_CONF_ENABLE +/* Make sure the UART is enabled, with interrupts */ +#undef UART0_CONF_ENABLE +#undef UART0_CONF_WITH_INPUT +#define UART0_CONF_ENABLE 1 +#define UART0_CONF_WITH_INPUT 1 +#define UIP_FALLBACK_INTERFACE slip_interface +#endif + +/* Output all captured frames over the UART in hexdump format */ +#ifndef CC2530_RF_CONF_HEXDUMP +#define CC2530_RF_CONF_HEXDUMP 0 +#endif + +#if CC2530_RF_CONF_HEXDUMP +/* We need UART1 output */ +#undef UART_ZERO_CONF_ENABLE +#define UART_ZERO_CONF_ENABLE 1 +#endif + +/* Code Shortcuts */ +/* + * When set, the RF driver is no longer a contiki process and the RX ISR is + * disabled. Instead of polling the radio process when data arrives, we + * periodically check for data by directly invoking the driver from main() + + * When set, this directive also configures the following bypasses: + * - process_post_synch() in tcpip_input() (we call packet_input()) + * - process_post_synch() in tcpip_uipcall (we call the relevant pthread) + * - mac_call_sent_callback() is replaced with sent() in various places + * + * These are good things to do, we reduce stack usage, RAM size and code size + */ +#define SHORTCUTS_CONF_NETSTACK 1 + +/* + * Sensors + * It is harmless to #define XYZ 1 + * even if the sensor is not present on our device + */ +#ifndef BUTTON_SENSOR_CONF_ON +#define BUTTON_SENSOR_CONF_ON 1 /* Buttons */ +#endif +/* ADC - Turning this off will disable everything below */ +#ifndef ADC_SENSOR_CONF_ON +#define ADC_SENSOR_CONF_ON 1 +#endif +#define TEMP_SENSOR_CONF_ON 1 /* Temperature */ +#define VDD_SENSOR_CONF_ON 1 /* Supply Voltage */ +#define BATTERY_SENSOR_CONF_ON 0 /* Battery */ + +/* Low Power Modes - We only support PM0/Idle and PM1 */ +#ifndef LPM_CONF_MODE +#define LPM_CONF_MODE 0 /* 0: no LPM, 1: MCU IDLE, 2: Drop to PM1 */ +#endif + +/* Some files include leds.h before us */ +#undef LEDS_YELLOW +#undef LEDS_RED +#define LEDS_YELLOW 4 +#define LEDS_RED 2 + +/* DMA Configuration */ +#ifndef DMA_CONF_ON +#define DMA_CONF_ON 0 +#endif + +/* Viztool on by default for IPv6 builds */ +#if UIP_CONF_IPV6 +#ifndef VIZTOOL_CONF_ON +#define VIZTOOL_CONF_ON 1 +#endif /* VIZTOOL_CONF_ON */ +#endif /* UIP_CONF_IPV6 */ + +/* Network Stack */ +#if UIP_CONF_IPV6 +#define NETSTACK_CONF_NETWORK sicslowpan_driver +#else +#define NETSTACK_CONF_NETWORK rime_driver +#endif + +#ifndef NETSTACK_CONF_MAC +#define NETSTACK_CONF_MAC csma_driver +#endif + +#ifndef NETSTACK_CONF_RDC +#define NETSTACK_CONF_RDC nullrdc_driver +#define NULLRDC_802154_AUTOACK 1 +#define NULLRDC_802154_AUTOACK_HW 1 +#endif + +#ifndef NETSTACK_CONF_RDC_CHANNEL_CHECK_RATE +#define NETSTACK_CONF_RDC_CHANNEL_CHECK_RATE 8 +#endif + +#define NETSTACK_CONF_FRAMER framer_802154 +#define NETSTACK_CONF_RADIO cc2530_rf_driver + +/* RF Config */ +#define IEEE802154_CONF_PANID 0x5449 /* TI */ + +#ifndef CC2530_RF_CONF_CHANNEL +#define CC2530_RF_CONF_CHANNEL 25 +#endif /* CC2530_RF_CONF_CHANNEL */ + +#ifndef CC2530_RF_CONF_AUTOACK +#define CC2530_RF_CONF_AUTOACK 1 +#endif /* CC2530_CONF_AUTOACK */ + +#if UIP_CONF_IPV6 +/* Addresses, Sizes and Interfaces */ +/* 8-byte addresses here, 2 otherwise */ +#define RIMEADDR_CONF_SIZE 8 +#define UIP_CONF_LL_802154 1 +#define UIP_CONF_LLH_LEN 0 +#define UIP_CONF_NETIF_MAX_ADDRESSES 3 + +/* TCP, UDP, ICMP */ +#define UIP_CONF_TCP 0 +#define UIP_CONF_UDP 1 +#define UIP_CONF_UDP_CHECKSUMS 1 + +/* ND and Routing */ +#define UIP_CONF_ROUTER 1 +#define UIP_CONF_IPV6_RPL 1 +#define UIP_CONF_ND6_SEND_RA 0 +#define UIP_CONF_IP_FORWARD 0 +#define RPL_CONF_STATS 0 +#define RPL_CONF_MAX_DAG_ENTRIES 1 +#ifndef RPL_CONF_OF +#define RPL_CONF_OF rpl_of_etx +#endif + +#define UIP_CONF_ND6_REACHABLE_TIME 600000 +#define UIP_CONF_ND6_RETRANS_TIMER 10000 + +#ifndef UIP_CONF_DS6_NBR_NBU +#define UIP_CONF_DS6_NBR_NBU 4 /* Handle n Neighbors */ +#endif +#ifndef UIP_CONF_DS6_ROUTE_NBU +#define UIP_CONF_DS6_ROUTE_NBU 4 /* Handle n Routes */ +#endif + +/* uIP */ +#define UIP_CONF_BUFFER_SIZE 240 +#define UIP_CONF_IPV6_QUEUE_PKT 0 +#define UIP_CONF_IPV6_CHECKS 1 +#define UIP_CONF_IPV6_REASSEMBLY 0 + +/* 6lowpan */ +#define SICSLOWPAN_CONF_COMPRESSION SICSLOWPAN_COMPRESSION_HC06 +#ifndef SICSLOWPAN_CONF_FRAG +#define SICSLOWPAN_CONF_FRAG 0 /* About 2KB of CODE if 1 */ +#endif +#define SICSLOWPAN_CONF_MAXAGE 8 + +/* Define our IPv6 prefixes/contexts here */ +#define SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS 1 +#define SICSLOWPAN_CONF_ADDR_CONTEXT_0 { \ + addr_contexts[0].prefix[0] = 0xaa; \ + addr_contexts[0].prefix[1] = 0xaa; \ +} + +#define MAC_CONF_CHANNEL_CHECK_RATE 8 +#define QUEUEBUF_CONF_NUM 6 + +#else /* UIP_CONF_IPV6 */ +/* Network setup for non-IPv6 (rime). */ +#define UIP_CONF_IP_FORWARD 1 +#define UIP_CONF_BUFFER_SIZE 108 +#define RIME_CONF_NO_POLITE_ANNOUCEMENTS 0 +#define QUEUEBUF_CONF_NUM 8 +#endif /* UIP_CONF_IPV6 */ + +#endif /* __CONTIKI_CONF_H__ */ diff --git a/platform/cc2530dk/contiki-main.c b/platform/cc2530dk/contiki-main.c new file mode 100644 index 000000000..e5b89a682 --- /dev/null +++ b/platform/cc2530dk/contiki-main.c @@ -0,0 +1,333 @@ +#include "contiki.h" +#include "soc.h" +#include "sys/clock.h" +#include "sys/autostart.h" +#include "dev/serial-line.h" +#include "dev/slip.h" +#include "dev/leds.h" +#include "dev/uart0.h" +#include "dev/dma.h" +#include "dev/cc2530-rf.h" +#include "dev/watchdog.h" +#include "dev/clock-isr.h" +#include "dev/lpm.h" +#include "dev/button-sensor.h" +#include "dev/adc-sensor.h" +#include "dev/leds-arch.h" +#include "net/rime.h" +#include "net/netstack.h" +#include "net/mac/frame802154.h" +#include "debug.h" +#include "cc253x.h" +#include "sfr-bits.h" +#include "contiki-lib.h" +#include "contiki-net.h" +/*---------------------------------------------------------------------------*/ +#if VIZTOOL_CONF_ON +PROCESS_NAME(viztool_process); +#endif +/*---------------------------------------------------------------------------*/ +#ifdef STARTUP_CONF_VERBOSE +#define STARTUP_VERBOSE STARTUP_CONF_VERBOSE +#else +#define STARTUP_VERBOSE 0 +#endif + +#if STARTUP_VERBOSE +#define PUTSTRING(...) putstring(__VA_ARGS__) +#define PUTHEX(...) puthex(__VA_ARGS__) +#define PUTBIN(...) putbin(__VA_ARGS__) +#define PUTCHAR(...) putchar(__VA_ARGS__) +#else +#define PUTSTRING(...) do {} while(0) +#define PUTHEX(...) do {} while(0) +#define PUTBIN(...) do {} while(0) +#define PUTCHAR(...) do {} while(0) +#endif +/*---------------------------------------------------------------------------*/ +extern rimeaddr_t rimeaddr_node_addr; +static __data int r; +static __data int len; +/*---------------------------------------------------------------------------*/ +#if ENERGEST_CONF_ON +static unsigned long irq_energest = 0; +#define ENERGEST_IRQ_SAVE(a) do { \ + a = energest_type_time(ENERGEST_TYPE_IRQ); } while(0) +#define ENERGEST_IRQ_RESTORE(a) do { \ + energest_type_set(ENERGEST_TYPE_IRQ, a); } while(0) +#else +#define ENERGEST_IRQ_SAVE(a) do {} while(0) +#define ENERGEST_IRQ_RESTORE(a) do {} while(0) +#endif +/*---------------------------------------------------------------------------*/ +static void +fade(int l) +{ + volatile int i, a; + int k, j; + for(k = 0; k < 400; ++k) { + j = k > 200? 400 - k: k; + + leds_on(l); + for(i = 0; i < j; ++i) { + a = i; + } + leds_off(l); + for(i = 0; i < 200 - j; ++i) { + a = i; + } + } +} +/*---------------------------------------------------------------------------*/ +static void +set_rime_addr(void) +{ + uint8_t *addr_long = NULL; + uint16_t addr_short = 0; + char i; + + __xdata unsigned char * macp = &X_IEEE_ADDR; + + PUTSTRING("Rime is 0x"); + PUTHEX(sizeof(rimeaddr_t)); + PUTSTRING(" bytes long\n"); + + PUTSTRING("Reading MAC from Info Page\n"); + + for(i = (RIMEADDR_SIZE - 1); i >= 0; --i) { + rimeaddr_node_addr.u8[i] = *macp; + macp++; + } + + /* Now the address is stored MSB first */ +#if STARTUP_VERBOSE + PUTSTRING("Rime configured with address "); + for(i = 0; i < RIMEADDR_SIZE - 1; i++) { + PUTHEX(rimeaddr_node_addr.u8[i]); + PUTCHAR(':'); + } + PUTHEX(rimeaddr_node_addr.u8[i]); + PUTCHAR('\n'); +#endif + + cc2530_rf_set_addr(IEEE802154_PANID); +} +/*---------------------------------------------------------------------------*/ +int +main(void) +{ + /* Hardware initialization */ + clock_init(); + soc_init(); + rtimer_init(); + + /* Init LEDs here */ + leds_init(); + leds_off(LEDS_ALL); + fade(LEDS_GREEN); + + /* initialize process manager. */ + process_init(); + + /* Init UART */ + uart0_init(); + +#if DMA_ON + dma_init(); +#endif + +#if SLIP_ARCH_CONF_ENABLE + slip_arch_init(0); +#else + uart0_set_input(serial_line_input_byte); + serial_line_init(); +#endif + fade(LEDS_RED); + + PUTSTRING("##########################################\n"); + putstring(CONTIKI_VERSION_STRING "\n"); + putstring("TI SmartRF05 EB\n"); + switch(CHIPID) { + case 0xA5: + putstring("cc2530"); + break; + case 0xB5: + putstring("cc2531"); + break; + case 0x95: + putstring("cc2533"); + break; + case 0x8D: + putstring("cc2540"); + break; + } + + putstring("-F"); + switch(CHIPINFO0 & 0x70) { + case 0x40: + putstring("256, "); + break; + case 0x30: + putstring("128, "); + break; + case 0x20: + putstring("64, "); + break; + case 0x10: + putstring("32, "); + break; + } + puthex(CHIPINFO1 + 1); + putstring("KB SRAM\n"); + + PUTSTRING("\nSDCC Build:\n"); +#if STARTUP_VERBOSE +#ifdef HAVE_SDCC_BANKING + PUTSTRING(" With Banking.\n"); +#endif /* HAVE_SDCC_BANKING */ +#ifdef SDCC_MODEL_LARGE + PUTSTRING(" --model-large\n"); +#endif /* SDCC_MODEL_LARGE */ +#ifdef SDCC_MODEL_HUGE + PUTSTRING(" --model-huge\n"); +#endif /* SDCC_MODEL_HUGE */ +#ifdef SDCC_STACK_AUTO + PUTSTRING(" --stack-auto\n"); +#endif /* SDCC_STACK_AUTO */ + + PUTCHAR('\n'); + + PUTSTRING(" Net: "); + PUTSTRING(NETSTACK_NETWORK.name); + PUTCHAR('\n'); + PUTSTRING(" MAC: "); + PUTSTRING(NETSTACK_MAC.name); + PUTCHAR('\n'); + PUTSTRING(" RDC: "); + PUTSTRING(NETSTACK_RDC.name); + PUTCHAR('\n'); + + PUTSTRING("##########################################\n"); +#endif + + watchdog_init(); + + /* Initialise the H/W RNG engine. */ + random_init(0); + + /* start services */ + process_start(&etimer_process, NULL); + ctimer_init(); + + /* initialize the netstack */ + netstack_init(); + set_rime_addr(); + +#if BUTTON_SENSOR_ON || ADC_SENSOR_ON + process_start(&sensors_process, NULL); + BUTTON_SENSOR_ACTIVATE(); + ADC_SENSOR_ACTIVATE(); +#endif + +#if UIP_CONF_IPV6 + memcpy(&uip_lladdr.addr, &rimeaddr_node_addr, sizeof(uip_lladdr.addr)); + queuebuf_init(); + process_start(&tcpip_process, NULL); +#endif /* UIP_CONF_IPV6 */ + +#if VIZTOOL_CONF_ON + process_start(&viztool_process, NULL); +#endif + + energest_init(); + ENERGEST_ON(ENERGEST_TYPE_CPU); + + autostart_start(autostart_processes); + + watchdog_start(); + + fade(LEDS_YELLOW); + + while(1) { + do { + /* Reset watchdog and handle polls and events */ + watchdog_periodic(); + r = process_run(); + } while(r > 0); +#if SHORTCUTS_CONF_NETSTACK + len = NETSTACK_RADIO.pending_packet(); + if(len) { + packetbuf_clear(); + len = NETSTACK_RADIO.read(packetbuf_dataptr(), PACKETBUF_SIZE); + if(len > 0) { + packetbuf_set_datalen(len); + NETSTACK_RDC.input(); + } + } +#endif + +#if LPM_MODE +#if (LPM_MODE==LPM_MODE_PM2) + SLEEP &= ~OSC_PD; /* Make sure both HS OSCs are on */ + while(!(SLEEP & HFRC_STB)); /* Wait for RCOSC to be stable */ + CLKCON |= OSC; /* Switch to the RCOSC */ + while(!(CLKCON & OSC)); /* Wait till it's happened */ + SLEEP |= OSC_PD; /* Turn the other one off */ +#endif /* LPM_MODE==LPM_MODE_PM2 */ + + /* + * Set MCU IDLE or Drop to PM1. Any interrupt will take us out of LPM + * Sleep Timer will wake us up in no more than 7.8ms (max idle interval) + */ + SLEEPCMD = (SLEEPCMD & 0xFC) | (LPM_MODE - 1); + +#if (LPM_MODE==LPM_MODE_PM2) + /* + * Wait 3 NOPs. Either an interrupt occurred and SLEEP.MODE was cleared or + * no interrupt occurred and we can safely power down + */ + __asm + nop + nop + nop + __endasm; + + if(SLEEPCMD & SLEEP_MODE0) { +#endif /* LPM_MODE==LPM_MODE_PM2 */ + + ENERGEST_OFF(ENERGEST_TYPE_CPU); + ENERGEST_ON(ENERGEST_TYPE_LPM); + + /* We are only interested in IRQ energest while idle or in LPM */ + ENERGEST_IRQ_RESTORE(irq_energest); + + /* Go IDLE or Enter PM1 */ + PCON |= PCON_IDLE; + + /* First instruction upon exiting PM1 must be a NOP */ + __asm + nop + __endasm; + + /* Remember energest IRQ for next pass */ + ENERGEST_IRQ_SAVE(irq_energest); + + ENERGEST_ON(ENERGEST_TYPE_CPU); + ENERGEST_OFF(ENERGEST_TYPE_LPM); + +#if (LPM_MODE==LPM_MODE_PM2) + SLEEPCMD &= ~SLEEP_OSC_PD; /* Make sure both HS OSCs are on */ + while(!(SLEEPCMD & SLEEP_XOSC_STB)); /* Wait for XOSC to be stable */ + CLKCONCMD &= ~CLKCONCMD_OSC; /* Switch to the XOSC */ + /* + * On occasion the XOSC is reported stable when in reality it's not. + * We need to wait for a safeguard of 64us or more before selecting it + */ + clock_delay(10); + while(CLKCONCMD & CLKCONCMD_OSC); /* Wait till it's happened */ + } +#endif /* LPM_MODE==LPM_MODE_PM2 */ +#endif /* LPM_MODE */ + } +} +/*---------------------------------------------------------------------------*/ diff --git a/platform/cc2530dk/debug.c b/platform/cc2530dk/debug.c new file mode 100644 index 000000000..29efccf06 --- /dev/null +++ b/platform/cc2530dk/debug.c @@ -0,0 +1,42 @@ +/** + * \file + * + * Definition of some debugging functions. + * + * putstring() and puthex() are from msp430/watchdog.c + * + * \author + * George Oikonomou - + */ + +#include "8051def.h" +#include "debug.h" + +static const char hexconv[] = "0123456789abcdef"; +static const char binconv[] = "01"; +/*---------------------------------------------------------------------------*/ +void +putstring(char *s) +{ + while(*s) { + putchar(*s++); + } +} +/*---------------------------------------------------------------------------*/ +void +puthex(uint8_t c) +{ + putchar(hexconv[c >> 4]); + putchar(hexconv[c & 0x0f]); +} +/*---------------------------------------------------------------------------*/ +void +putbin(uint8_t c) +{ + unsigned char i = 0x80; + while(i) { + putchar(binconv[(c & i) != 0]); + i >>= 1; + } +} +/*---------------------------------------------------------------------------*/ diff --git a/platform/cc2530dk/debug.h b/platform/cc2530dk/debug.h new file mode 100644 index 000000000..a3c5cb01a --- /dev/null +++ b/platform/cc2530dk/debug.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2005, Swedish Institute of Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + */ + +/** + * \file + * Header file for debugging functions used by the sensinode port. + * + * putstring() and puthex() are from msp430/watchdog.c + * + * \author + * George Oikonomou - + */ + +#ifndef __DEBUG_H__ +#define __DEBUG_H__ + +#include "8051def.h" +#include "dev/uart1.h" + +void putchar(char c); +void putstring(char *s); +void puthex(uint8_t c); +void putbin(uint8_t c); + +#endif /* __DEBUG_H__ */ diff --git a/platform/cc2530dk/dev/adc-sensor.c b/platform/cc2530dk/dev/adc-sensor.c new file mode 100644 index 000000000..005852d96 --- /dev/null +++ b/platform/cc2530dk/dev/adc-sensor.c @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2011, George Oikonomou - + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * ADC sensor module for TI SmartRF05EB devices. + * + * \author + * George Oikonomou - + */ +#include "sfr-bits.h" +#include "cc253x.h" +#include "adc-sensor.h" + +#if ADC_SENSOR_ON +/*---------------------------------------------------------------------------*/ +static int +value(int type) +{ + uint16_t reading; + /* + * For single-shot AD conversions, we may only write to ADCCON3[3:0] once + * (This write triggers the conversion). We thus use the variable 'command' + * to store intermediate steps (reference, decimation rate, input channel) + */ + uint8_t command; + + /* 1.25V ref, max decimation rate */ + command = ADCCON3_EDIV1 | ADCCON3_EDIV0; + + /* Clear the Interrupt Flag */ + ADCIF = 0; + + /* Depending on the desired reading, append the input bits to 'command' and + * enable the corresponding input channel in ADCCFG if necessary */ + switch(type) { +#if TEMP_SENSOR_ON + case ADC_SENSOR_TYPE_TEMP: + command |= ADCCON3_ECH3 | ADCCON3_ECH2 | ADCCON3_ECH1; + break; +#endif +#if VDD_SENSOR_ON + case ADC_SENSOR_TYPE_VDD: + command |= ADCCON3_ECH3 | ADCCON3_ECH2 | ADCCON3_ECH1 | ADCCON3_ECH0; + break; +#endif + default: + /* If the sensor is not present or disabled in conf, return -1 */ + return -1; + } + + /* Writing in bits 3:0 of ADCCON3 will trigger a single conversion */ + ADCCON3 = command; + + /* + * When the conversion is complete, the ADC interrupt flag is set. We don't + * use an ISR here, we just wait on the flag and clear it afterwards. + */ + while(!ADCIF); + + /* Clear the Interrupt Flag */ + ADCIF = 0; + + reading = ADCL; + reading |= (((uint8_t) ADCH) << 8); + /* 12-bit decimation rate: 4 LS bits are noise */ + reading >>= 4; + + return reading; +} +/*---------------------------------------------------------------------------*/ +static int +status(int type) +{ + return 1; +} +/*---------------------------------------------------------------------------*/ +static int +configure(int type, int value) +{ + switch(type) { + case SENSORS_HW_INIT: +#if TEMP_SENSOR_ON + /* Connect temperature sensor to the SoC */ + ATEST = 1; + TR0 = 1; +#endif + APCFG = 0; /* Disables Input Channels */ + break; + } + return 1; +} +/*---------------------------------------------------------------------------*/ +SENSORS_SENSOR(adc_sensor, ADC_SENSOR, value, configure, status); +#endif /* ADC_SENSOR_ON */ diff --git a/platform/cc2530dk/dev/adc-sensor.h b/platform/cc2530dk/dev/adc-sensor.h new file mode 100644 index 000000000..45b0a9985 --- /dev/null +++ b/platform/cc2530dk/dev/adc-sensor.h @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2011, George Oikonomou - + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * Header file for ADC sensors on the SmartRF05EB. + * + * Sensors will be off by default, unless turned on explicitly + * in contiki-conf.h + * + * \author + * George Oikonomou - + */ + +#ifndef __ADC_SENSOR_H__ +#define __ADC_SENSOR_H__ + +#include "cc253x.h" +#include "contiki-conf.h" +#include "lib/sensors.h" + +/* ADC Sensor Types */ +#define ADC_SENSOR "ADC" + +#define ADC_SENSOR_TYPE_TEMP 0 +#define ADC_SENSOR_TYPE_VDD 4 + +#ifdef ADC_SENSOR_CONF_ON +#define ADC_SENSOR_ON ADC_SENSOR_CONF_ON +#endif /* ADC_SENSOR_CONF_ON */ + +#if ADC_SENSOR_ON +extern const struct sensors_sensor adc_sensor; +#define ADC_SENSOR_ACTIVATE() adc_sensor.configure(SENSORS_ACTIVE, 1) +#else +#define ADC_SENSOR_ACTIVATE() +#endif /* ADC_SENSOR_ON */ + +/* Battery - SmartRF stuff */ +#ifdef BATTERY_SENSOR_CONF_ON +#define BATTERY_SENSOR_ON BATTERY_SENSOR_CONF_ON +#endif /* BATTERY_SENSOR_CONF_ON */ + +/* Temperature - Available on all devices */ +#ifdef TEMP_SENSOR_CONF_ON +#define TEMP_SENSOR_ON TEMP_SENSOR_CONF_ON +#endif /* TEMP_SENSOR_CONF_ON */ + +/* Supply Voltage (VDD / 3) - Available on all devices*/ +#ifdef VDD_SENSOR_CONF_ON +#define VDD_SENSOR_ON VDD_SENSOR_CONF_ON +#endif /* VDD_SENSOR_CONF_ON */ + +#endif /* __ADC_SENSOR_H__ */ diff --git a/platform/cc2530dk/dev/button-sensor.c b/platform/cc2530dk/dev/button-sensor.c new file mode 100644 index 000000000..d2d9856d2 --- /dev/null +++ b/platform/cc2530dk/dev/button-sensor.c @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2005, Swedish Institute of Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/* + * This file contains ISRs: Keep it in the HOME bank. + */ +#include "dev/port.h" +#include "dev/button-sensor.h" +/*---------------------------------------------------------------------------*/ +#if BUTTON_SENSOR_ON +static __data struct timer debouncetimer; +/*---------------------------------------------------------------------------*/ +static +int value(int type) +{ + return BUTTON_READ() || !timer_expired(&debouncetimer); +} +/*---------------------------------------------------------------------------*/ +static +int status(int type) +{ + switch (type) { + case SENSORS_ACTIVE: + case SENSORS_READY: + return BUTTON_IRQ_ENABLED(); + } + return 0; +} +/*---------------------------------------------------------------------------*/ +static +int configure(int type, int value) +{ + switch(type) { + case SENSORS_HW_INIT: + P0INP |= 2; /* Tri-state */ + BUTTON_IRQ_ON_PRESS(); + BUTTON_FUNC_GPIO(); + BUTTON_DIR_INPUT(); + return 1; + case SENSORS_ACTIVE: + if(value) { + if(!BUTTON_IRQ_ENABLED()) { + timer_set(&debouncetimer, 0); + BUTTON_IRQ_FLAG_OFF(); + BUTTON_IRQ_ENABLE(); + } + } else { + BUTTON_IRQ_DISABLE(); + } + return 1; + } + return 0; +} +/*---------------------------------------------------------------------------*/ +void +port_0_isr(void) __interrupt(P0INT_VECTOR) +{ + EA = 0; + ENERGEST_ON(ENERGEST_TYPE_IRQ); + + /* This ISR is for the entire port. Check if the interrupt was caused by our + * button's pin. */ + if(BUTTON_IRQ_CHECK()) { + if(timer_expired(&debouncetimer)) { + timer_set(&debouncetimer, CLOCK_SECOND / 8); + sensors_changed(&button_sensor); + } + } + + BUTTON_IRQ_FLAG_OFF(); + + ENERGEST_OFF(ENERGEST_TYPE_IRQ); + EA = 1; +} +/*---------------------------------------------------------------------------*/ +SENSORS_SENSOR(button_sensor, BUTTON_SENSOR, value, configure, status); +#endif /* BUTTON_SENSOR_ON */ diff --git a/platform/cc2530dk/dev/button-sensor.h b/platform/cc2530dk/dev/button-sensor.h new file mode 100644 index 000000000..9eb13b89e --- /dev/null +++ b/platform/cc2530dk/dev/button-sensor.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2011, George Oikonomou - + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * Override core/dev/button-sensor.h + * + * \author + * George Oikonomou - + */ + +#ifndef __BUTTON_SENSOR_H__ +#define __BUTTON_SENSOR_H__ + +#include "contiki-conf.h" +#include "lib/sensors.h" + +#define BUTTON_PORT 0 +#define BUTTON_PIN 1 + +#define BUTTON_SENSOR "Button" + +/* + * SmartRF Buttons + * B1: P0_1, B2: Not Connected + */ +#ifdef BUTTON_SENSOR_CONF_ON +#define BUTTON_SENSOR_ON BUTTON_SENSOR_CONF_ON +#endif /* BUTTON_SENSOR_CONF_ON */ + +#if BUTTON_SENSOR_ON +extern const struct sensors_sensor button_sensor; +/* Button 1: P0_1 - Port 0 ISR needed */ +void port_0_isr(void) __interrupt(P0INT_VECTOR); +#define BUTTON_SENSOR_ACTIVATE() button_sensor.configure(SENSORS_ACTIVE, 1) +#else +#define BUTTON_SENSOR_ACTIVATE() +#endif /* BUTTON_SENSOR_ON */ + +/* Define macros for button 1 */ +#define BUTTON_READ() PORT_READ(BUTTON_PORT, BUTTON_PIN) +#define BUTTON_FUNC_GPIO() PORT_FUNC_GPIO(BUTTON_PORT, BUTTON_PIN) +#define BUTTON_DIR_INPUT() PORT_DIR_INPUT(BUTTON_PORT, BUTTON_PIN) +#define BUTTON_IRQ_ENABLED() PORT_IRQ_ENABLED(BUTTON_PORT, BUTTON_PIN) +#define BUTTON_IRQ_CHECK() PORT_IRQ_CHECK(BUTTON_PORT, BUTTON_PIN) +#define BUTTON_IRQ_ENABLE() PORT_IRQ_ENABLE(BUTTON_PORT, BUTTON_PIN) +#define BUTTON_IRQ_DISABLE() PORT_IRQ_DISABLE(BUTTON_PORT, BUTTON_PIN) +#define BUTTON_IRQ_FLAG_OFF() PORT_IRQ_FLAG_OFF(BUTTON_PORT, BUTTON_PIN) +#define BUTTON_IRQ_ON_PRESS() PORT_IRQ_EDGE_RISE(BUTTON_PORT, BUTTON_PIN) +#define BUTTON_IRQ_ON_RELEASE() PORT_IRQ_EDGE_FALL(BUTTON_PORT, BUTTON_PIN) + +#endif /* __BUTTON_SENSOR_H__ */ diff --git a/platform/cc2530dk/dev/leds-arch.c b/platform/cc2530dk/dev/leds-arch.c new file mode 100644 index 000000000..fb583a5c2 --- /dev/null +++ b/platform/cc2530dk/dev/leds-arch.c @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2011, George Oikonomou - + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * Platform-specific led driver for the TI SmartRF05 Eval. Board. + * + * \author + * George Oikonomou - + */ +#include "contiki-conf.h" +#include "dev/leds.h" +#include "dev/leds-arch.h" +#include "cc253x.h" + +/* + * LEDS + * 1: P1_0 + * 2: P1_1 + * 3: P1_4 + * 4: P0_1 (LED4 shares port/pin with B1 and is currently unused) + */ + +/* H/W Connections */ +#define LED1_PIN P1_0 +#define LED2_PIN P1_1 +#define LED3_PIN P1_4 + +/* P0DIR and P0SEL masks */ +#define LED1_MASK 0x01 +#define LED2_MASK 0x02 +#define LED3_MASK 0x10 +#define LED4_MASK 0x02 +/*---------------------------------------------------------------------------*/ +void +leds_arch_init(void) +{ + P1SEL &= ~(LED1_MASK | LED2_MASK | LED3_MASK); + P1DIR |= (LED1_MASK | LED2_MASK | LED3_MASK); +} +/*---------------------------------------------------------------------------*/ +unsigned char +leds_arch_get(void) +{ + unsigned char v; + + v = (unsigned char) (LED1_PIN | (LED2_PIN << 1) | (LED3_PIN << 2)); + + return v; +} +/*---------------------------------------------------------------------------*/ +void +leds_arch_set(unsigned char leds) +{ + LED1_PIN = leds & 0x01; + LED2_PIN = (leds & 0x02) >> 1; + LED3_PIN = (leds & 0x04) >> 2; +} +/*---------------------------------------------------------------------------*/ diff --git a/platform/cc2530dk/dev/leds-arch.h b/platform/cc2530dk/dev/leds-arch.h new file mode 100644 index 000000000..b19d5cf9d --- /dev/null +++ b/platform/cc2530dk/dev/leds-arch.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2011, George Oikonomou - + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * Header file for platform-specific led functionality + * + * \author + * George Oikonomou - + */ + + +#ifndef __LEDS_ARCH_H__ +#define __LEDS_ARCH_H__ + +#include "dev/port.h" + +/* Led 4 on the SmartRF05EB is multiplexed with Button 1 on P0_1 */ +#define LED4_READ() PORT_READ(LED4_PORT, LED4_PIN) +#define LED4_WRITE(v) PORT_WRITE(LED4_PORT, LED4_PIN, v) +#define LED4_FUNC_GPIO() PORT_FUNC_GPIO(LED4_PORT, LED4_PIN) +#define LED4_DIR_INPUT() PORT_DIR_INPUT(LED4_PORT, LED4_PIN) +#define LED4_DIR_OUTPUT() PORT_DIR_OUTPUT(LED4_PORT, LED4_PIN) + +#endif /* __LEDS_ARCH_H__ */ diff --git a/platform/cc2530dk/dev/slip-arch.c b/platform/cc2530dk/dev/slip-arch.c new file mode 100644 index 000000000..1b0437494 --- /dev/null +++ b/platform/cc2530dk/dev/slip-arch.c @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2006, Swedish Institute of Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)$Id: slip_uart1.c,v 1.8 2008/02/03 20:59:35 adamdunkels Exp $ + */ + +/* + * Machine dependent cc2530eb SLIP routines for UART1. + */ + +#include "dev/slip.h" +#include "dev/uart0.h" +/*---------------------------------------------------------------------------*/ +void +slip_arch_writeb(unsigned char c) +{ + uart0_writeb(c); +} +/*---------------------------------------------------------------------------*/ +void +slip_arch_init(unsigned long ubr) +{ + uart0_set_input(slip_input_byte); +} +/*---------------------------------------------------------------------------*/ diff --git a/platform/cc2530dk/dev/smartrf-sensors.c b/platform/cc2530dk/dev/smartrf-sensors.c new file mode 100644 index 000000000..c40cf101b --- /dev/null +++ b/platform/cc2530dk/dev/smartrf-sensors.c @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2011, George Oikonomou - + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * Data structures for SmartRF05EB sensing elements + * + * \author + * George Oikonomou - + */ + +#include "dev/button-sensor.h" +#include "dev/adc-sensor.h" +#include "sys/energest.h" + +const struct sensors_sensor *sensors[] = { +#if ADC_SENSOR_ON + &adc_sensor, +#endif +#if BUTTON_SENSOR_ON + &button_sensor, +#endif + 0 +}; + +unsigned char sensors_flags[(sizeof(sensors) / sizeof(struct sensors_sensor *))]; diff --git a/platform/cc2530dk/putchar.c b/platform/cc2530dk/putchar.c new file mode 100644 index 000000000..18c4b04a1 --- /dev/null +++ b/platform/cc2530dk/putchar.c @@ -0,0 +1,38 @@ +/** + * \file + * hardware-specific putchar() routine for TI SmartRF05EB + * + * \author + * George Oikonomou - + */ + +#include "contiki-conf.h" +#include "dev/uart0.h" +/*---------------------------------------------------------------------------*/ +void +putchar(char c) +{ +#if SLIP_ARCH_CONF_ENABLE +#define SLIP_END 0300 + static char debug_frame = 0; + + if(!debug_frame) { /* Start of debug output */ + uart0_writeb(SLIP_END); + uart0_writeb('\r'); /* Type debug line == '\r' */ + debug_frame = 1; + } +#endif + + uart0_writeb((char)c); + +#if SLIP_ARCH_CONF_ENABLE + /* + * Line buffered output, a newline marks the end of debug output and + * implicitly flushes debug output. + */ + if(c == '\n') { + uart0_writeb(SLIP_END); + debug_frame = 0; + } +#endif +} diff --git a/platform/cc2530dk/segment.rules b/platform/cc2530dk/segment.rules new file mode 100644 index 000000000..4810b5129 --- /dev/null +++ b/platform/cc2530dk/segment.rules @@ -0,0 +1,13 @@ +# segment.rules - platform + +# segment.rules file for platform code +# Please see cpu/cc2430/segment.rules for more info on code segments +# and for rules of thumb on what to do and what not to do + +# Keep main() in HOME +HOME contiki-main.c + +# Files with ISRs must be in HOME +HOME button-sensor.c + +# segment.rules - platform - end diff --git a/platform/cc2530dk/viztool.c b/platform/cc2530dk/viztool.c new file mode 100644 index 000000000..777ffc855 --- /dev/null +++ b/platform/cc2530dk/viztool.c @@ -0,0 +1,298 @@ +/* + * Copyright (c) 2010, Loughborough University - Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * Small UDP app used to retrieve neighbor cache and routing table + * entries and send them to an external endpoint + * + * \author + * George Oikonomou - + */ + +#include "contiki.h" +#include "contiki-lib.h" +#include "contiki-net.h" + +#include + +#define DEBUG DEBUG_NONE +#include "net/uip-debug.h" + +#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) +#define UIP_UDP_BUF ((struct uip_udp_hdr *)&uip_buf[uip_l2_l3_hdr_len]) + +#ifndef VIZTOOL_MAX_PAYLOAD_LEN +#define VIZTOOL_MAX_PAYLOAD_LEN 60 +#endif + +static struct uip_udp_conn *server_conn; +static unsigned char buf[VIZTOOL_MAX_PAYLOAD_LEN]; +static int8_t len; + +#define VIZTOOL_UDP_PORT 60001 + +/* Request Bits */ +#define REQUEST_TYPE_ND 1 +#define REQUEST_TYPE_RT 2 +#define REQUEST_TYPE_DRT 3 +#define REQUEST_TYPE_ADDR 4 +#define REQUEST_TYPE_TOTALS 0xFF + +extern uip_ds6_netif_t uip_ds6_if; +extern uip_ds6_route_t uip_ds6_routing_table[UIP_DS6_ROUTE_NB]; +extern uip_ds6_nbr_t uip_ds6_nbr_cache[UIP_DS6_NBR_NB]; +extern uip_ds6_defrt_t uip_ds6_defrt_list[UIP_DS6_DEFRT_NB]; +extern u16_t uip_len; +/*---------------------------------------------------------------------------*/ +static uint8_t +process_request() +{ + uint8_t len; + uint8_t count; /* How many did we pack? */ + uint8_t i; + uint8_t left; + uint8_t entry_size; + + left = VIZTOOL_MAX_PAYLOAD_LEN - 1; + len = 2; /* start filling the buffer from position [2] */ + count = 0; + if(buf[0] == REQUEST_TYPE_ND) { + /* Neighbors */ + PRINTF("Neighbors\n"); + for(i = buf[1]; i < UIP_DS6_NBR_NB; i++) { + if(uip_ds6_nbr_cache[i].isused) { + entry_size = sizeof(i) + sizeof(uip_ipaddr_t) + sizeof(uip_lladdr_t) + + sizeof(uip_ds6_nbr_cache[i].state); + PRINTF("%02u: ", i); + PRINT6ADDR(&uip_ds6_nbr_cache[i].ipaddr); + PRINTF(" - "); + PRINTLLADDR(&uip_ds6_nbr_cache[i].lladdr); + PRINTF(" - %u\n", uip_ds6_nbr_cache[i].state); + + memcpy(buf + len, &i, sizeof(i)); + len += sizeof(i); + memcpy(buf + len, &uip_ds6_nbr_cache[i].ipaddr, sizeof(uip_ipaddr_t)); + len += sizeof(uip_ipaddr_t); + memcpy(buf + len, &uip_ds6_nbr_cache[i].lladdr, sizeof(uip_lladdr_t)); + len += sizeof(uip_lladdr_t); + memcpy(buf + len, &uip_ds6_nbr_cache[i].state, + sizeof(uip_ds6_nbr_cache[i].state)); + len += sizeof(uip_ds6_nbr_cache[i].state); + + count++; + left -= entry_size; + + if(left < entry_size) { + break; + } + } + } + } else if(buf[0] == REQUEST_TYPE_RT) { + uint32_t flip = 0; + PRINTF("Routing table\n"); + for(i = buf[1]; i < UIP_DS6_ROUTE_NB; i++) { + if(uip_ds6_routing_table[i].isused) { + entry_size = sizeof(i) + sizeof(uip_ds6_routing_table[i].ipaddr) + + sizeof(uip_ds6_routing_table[i].length) + + sizeof(uip_ds6_routing_table[i].metric) + + sizeof(uip_ds6_routing_table[i].nexthop) + + sizeof(uip_ds6_routing_table[i].state.lifetime) + + sizeof(uip_ds6_routing_table[i].state.learned_from); + + memcpy(buf + len, &i, sizeof(i)); + len += sizeof(i); + memcpy(buf + len, &uip_ds6_routing_table[i].ipaddr, + sizeof(uip_ds6_routing_table[i].ipaddr)); + len += sizeof(uip_ds6_routing_table[i].ipaddr); + memcpy(buf + len, &uip_ds6_routing_table[i].length, + sizeof(uip_ds6_routing_table[i].length)); + len += sizeof(uip_ds6_routing_table[i].length); + memcpy(buf + len, &uip_ds6_routing_table[i].metric, + sizeof(uip_ds6_routing_table[i].metric)); + len += sizeof(uip_ds6_routing_table[i].metric); + memcpy(buf + len, &uip_ds6_routing_table[i].nexthop, + sizeof(uip_ds6_routing_table[i].nexthop)); + len += sizeof(uip_ds6_routing_table[i].nexthop); + + PRINT6ADDR(&uip_ds6_routing_table[i].ipaddr); + PRINTF(" - %02x", uip_ds6_routing_table[i].length); + PRINTF(" - %02x", uip_ds6_routing_table[i].metric); + PRINTF(" - "); + PRINT6ADDR(&uip_ds6_routing_table[i].nexthop); + + flip = uip_htonl(uip_ds6_routing_table[i].state.lifetime); + memcpy(buf + len, &flip, sizeof(flip)); + len += sizeof(flip); + PRINTF(" - %08lx", uip_ds6_routing_table[i].state.lifetime); + + memcpy(buf + len, &uip_ds6_routing_table[i].state.learned_from, + sizeof(uip_ds6_routing_table[i].state.learned_from)); + len += sizeof(uip_ds6_routing_table[i].state.learned_from); + + PRINTF(" - %02x [%u]\n", uip_ds6_routing_table[i].state.learned_from, + entry_size); + + count++; + left -= entry_size; + + if(left < entry_size) { + break; + } + } + } + } else if (buf[0] == REQUEST_TYPE_DRT) { + uint32_t flip = 0; + PRINTF("Default Routes\n"); + for(i = buf[1]; i < UIP_DS6_DEFRT_NB; i++) { + if(uip_ds6_defrt_list[i].isused) { + entry_size = sizeof(i) + sizeof(uip_ds6_defrt_list[i].ipaddr) + + sizeof(uip_ds6_defrt_list[i].isinfinite); + + memcpy(buf + len, &i, sizeof(i)); + len += sizeof(i); + memcpy(buf + len, &uip_ds6_defrt_list[i].ipaddr, + sizeof(uip_ds6_defrt_list[i].ipaddr)); + len += sizeof(uip_ds6_defrt_list[i].ipaddr); + memcpy(buf + len, &uip_ds6_defrt_list[i].isinfinite, + sizeof(uip_ds6_defrt_list[i].isinfinite)); + len += sizeof(uip_ds6_defrt_list[i].isinfinite); + + PRINT6ADDR(&uip_ds6_defrt_list[i].ipaddr); + PRINTF(" - %u\n", uip_ds6_defrt_list[i].isinfinite); + count++; + left -= entry_size; + + if(left < entry_size) { + break; + } + } + } + } else if (buf[0] == REQUEST_TYPE_ADDR) { + PRINTF("Unicast Addresses\n"); + for(i = buf[1]; i < UIP_DS6_ADDR_NB; i++) { + if(uip_ds6_if.addr_list[i].isused) { + entry_size = sizeof(i) + sizeof(uip_ds6_if.addr_list[i].ipaddr); + + memcpy(buf + len, &i, sizeof(i)); + len += sizeof(i); + memcpy(buf + len, &uip_ds6_if.addr_list[i].ipaddr, + sizeof(uip_ds6_if.addr_list[i].ipaddr)); + len += sizeof(uip_ds6_if.addr_list[i].ipaddr); + + PRINT6ADDR(&uip_ds6_if.addr_list[i].ipaddr); + PRINTF("\n"); + count++; + left -= entry_size; + + if(left < entry_size) { + break; + } + } + } + } else if (buf[0] == REQUEST_TYPE_TOTALS) { + memset(&buf[2], 0, 4); + for(i = 0; i < UIP_DS6_ADDR_NB; i++) { + if(uip_ds6_if.addr_list[i].isused) { + buf[2]++; + } + } + for(i = 0; i < UIP_DS6_NBR_NB; i++) { + if(uip_ds6_nbr_cache[i].isused) { + buf[3]++; + } + } + for(i = 0; i < UIP_DS6_ROUTE_NB; i++) { + if(uip_ds6_routing_table[i].isused) { + buf[4]++; + } + } + for(i = 0; i < UIP_DS6_DEFRT_NB; i++) { + if(uip_ds6_defrt_list[i].isused) { + buf[5]++; + } + } + len += 4; + count = 4; + } else { + return 0; + } + buf[1] = count; + return len; +} +/*---------------------------------------------------------------------------*/ +PROCESS(viztool_process, "Network Visualization Tool Process"); +/*---------------------------------------------------------------------------*/ +static void +tcpip_handler(void) +{ + if(uip_newdata()) { + memset(buf, 0, VIZTOOL_MAX_PAYLOAD_LEN); + + PRINTF("%u bytes from [", uip_datalen()); + PRINT6ADDR(&UIP_IP_BUF->srcipaddr); + PRINTF("]:%u\n", UIP_HTONS(UIP_UDP_BUF->srcport)); + + memcpy(buf, uip_appdata, uip_datalen()); + + len = process_request(); + if(len) { + server_conn->rport = UIP_UDP_BUF->srcport; + uip_ipaddr_copy(&server_conn->ripaddr, &UIP_IP_BUF->srcipaddr); + uip_udp_packet_send(server_conn, buf, len); + PRINTF("Sent %u bytes\n", len); + } + + /* Restore server connection to allow data from any node */ + uip_create_unspecified(&server_conn->ripaddr); + server_conn->rport = 0; + } + return; +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(viztool_process, ev, data) +{ + + PROCESS_BEGIN(); + + server_conn = udp_new(NULL, UIP_HTONS(0), NULL); + udp_bind(server_conn, UIP_HTONS(VIZTOOL_UDP_PORT)); + + while(1) { + PROCESS_YIELD(); + if(ev == tcpip_event) { + tcpip_handler(); + } + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ diff --git a/platform/minimal-net/contiki-main.c b/platform/minimal-net/contiki-main.c index cf09c2718..64301d38f 100644 --- a/platform/minimal-net/contiki-main.c +++ b/platform/minimal-net/contiki-main.c @@ -140,6 +140,7 @@ sprint_ip6(uip_ip6addr_t addr) unsigned char i = 0; unsigned char zerocnt = 0; unsigned char numprinted = 0; + unsigned char notskipped = 0; char thestring[40]; char *result = thestring; @@ -149,10 +150,11 @@ sprint_ip6(uip_ip6addr_t addr) while(addr.u16[zerocnt + i] == 0) { zerocnt++; } - if(zerocnt == 1) { + if(zerocnt == 1 && notskipped) { *result++ = '0'; numprinted++; - break; + notskipped = 1; + continue; } i += zerocnt; numprinted += zerocnt; @@ -290,7 +292,7 @@ main(void) { uint8_t i; for(i = 0; i < UIP_DS6_ADDR_NB; i++) { - if(uip_ds6_if.addr_list[i].isused) { + if(uip_ds6_if.addr_list[i].isused) { printf("IPV6 Addresss: "); sprint_ip6(uip_ds6_if.addr_list[i].ipaddr); printf("\n"); diff --git a/platform/sensinode/Makefile.sensinode b/platform/sensinode/Makefile.sensinode index baf3c92e9..a1daf96e6 100644 --- a/platform/sensinode/Makefile.sensinode +++ b/platform/sensinode/Makefile.sensinode @@ -1,20 +1,32 @@ # Sensinode CC2430 platform makefile # Supported products: N100, N600, N601, N710, N711 +# Support for N740 is experimental. -# /dev supports defines for product models using the following format +# We support defines for product models using the following format # e.g. MODEL_N601. Run make TARGET=sensinode DEFINES=MODEL_N601 to # automatically configure the correct LED, button, UART etc. settings -# for that product model. If no model is defined, MODEL_N100 is chosen by default. -# Models settings are defined in /dev/models.h +# for that product model. If undefined, MODEL_N100 is chosen by default. +# Model settings are defined in /dev/models.h # make sensinode.upload - Will use nano_programmer to upload file using D2xx Devboard # make sensinode.serialdump - Will use the Contiki serialdump tool on the default UART +# make foo.model - Will copy foo.ihx to foo-XYZ.ihx (e.g. foo-n740.ihx) +PATH:=$(CONTIKI)/platform/$(TARGET)/tools/bin:$(PATH) +export PATH ifndef CONTIKI $(error CONTIKI not defined! You must specify where CONTIKI resides!) endif -CFLAGS += -DRIME_CONF_NO_POLITE_ANNOUCEMENTS -RIME_CONF_NO_POLITE_ANNOUCEMENTS = 1 + +# Determine our model and (later on) add it as part of the .ihx filename +# Handy when building for various models so we can easily tell which ihx +# is for what model. +# Defaults to N100 (which is what the contiki code does as well) +MODEL_SUFFIX=n100 +ifdef DEFINES + MODEL_SUFFIX=$(patsubst MODEL_N%,n%, \ + $(filter MODEL_%,$(subst $(COMMA), ,$(DEFINES)))) +endif # Define the default UART for tools and tool commands DEFUART = /dev/ttyUSB0 @@ -22,16 +34,48 @@ PROG = $(CONTIKI)/tools/sensinode/nano_programmer/nano_programmer -d $(DEFUART) SERIALDUMP = $(CONTIKI)/tools/sky/serialdump-linux -b115200 $(DEFUART) CONTIKI_TARGET_DIRS = . dev -CONTIKI_TARGET_MAIN = ${addprefix $(OBJECTDIR)/,contiki-sensinode-main.o} +CONTIKI_TARGET_MAIN = $(addprefix $(OBJECTDIR)/,contiki-sensinode-main.rel) -CONTIKI_TARGET_SOURCEFILES = contiki-sensinode-main.c \ - leds.c leds-arch.c serial-line.c +CONTIKI_TARGET_SOURCEFILES = contiki-sensinode-main.c +CONTIKI_TARGET_SOURCEFILES += leds.c leds-arch.c serial-line.c sensors.c +CONTIKI_TARGET_SOURCEFILES += sensinode-sensors.c button-sensor.c adc-sensor.c +CONTIKI_TARGET_SOURCEFILES += n740.c models.c m25p16.c slip-arch.c slip.c +CONTIKI_TARGET_SOURCEFILES += putchar.c sensinode-debug.c CONTIKI_SOURCEFILES += $(CONTIKI_TARGET_SOURCEFILES) -.SUFFIXES: +ifdef UIP_CONF_IPV6 + ifeq ($(OFFSET_FIRMWARE),1) + CFLAGS += -DDISCO_ENABLED=1 + CONTIKI_TARGET_SOURCEFILES += disco.c + endif + CONTIKI_TARGET_SOURCEFILES += viztool.c + CONTIKI_SOURCEFILES += rpl-of0.c +endif -%.upload: %.ihx +FORCE: + +# .sensinode target so we can behave similar to other targets +# Lastly, it will create a %-$(MODEL).ihx file +%.$(TARGET): %.hex FORCE + cp $< $(<:.hex=.$(TARGET)) + if [ -f $(<:.hex=.ihx) ] ; then \ + cp $(<:.hex=.ihx) $(<:.hex=-$(MODEL_SUFFIX).ihx); fi + @echo "\nReport" + @echo "===============" + @echo 'Code footprint:' + @echo 'Area Addr Size' \ + ' Decimal' + @echo '---------------------------------- -------- --------' \ + ' --------' + @echo -n 'HOME,CSEG,CONST,XINIT,GS* $(HOME_START) ' + @egrep ',CODE\)' $(<:.hex=.map) | egrep -v '(^BANK[1-9][^=])' | uniq | \ + awk '{ SUM += $$5 } END { printf "%08X = %8d", SUM, SUM }' + @echo '. bytes (REL,CON,CODE)' + @egrep '(^BANK[1-9][^=])' $(<:.hex=.map) | uniq | sort + @egrep -A 5 'Other memory' $(<:.hex=.mem) + +%.upload: %.hex $(PROG) -P $< sensinode.serialdump: @@ -41,4 +85,4 @@ sensinode.serialdump: CONTIKI_CPU=$(CONTIKI)/cpu/cc2430 include $(CONTIKI)/cpu/cc2430/Makefile.cc2430 -contiki-$(TARGET).a:# ${addprefix $(OBJECTDIR)/,symbols.o} +contiki-$(TARGET).a:# $(addprefix $(OBJECTDIR)/,symbols.rel) diff --git a/platform/sensinode/apps/batmon/Makefile.batmon b/platform/sensinode/apps/batmon/Makefile.batmon new file mode 100644 index 000000000..1ad4809da --- /dev/null +++ b/platform/sensinode/apps/batmon/Makefile.batmon @@ -0,0 +1,3 @@ +batmon_src = batmon.c + +CFLAGS += -DBATMON_CONF_ON=1 \ No newline at end of file diff --git a/platform/sensinode/apps/batmon/batmon.c b/platform/sensinode/apps/batmon/batmon.c new file mode 100644 index 000000000..5f8797ef7 --- /dev/null +++ b/platform/sensinode/apps/batmon/batmon.c @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2010, Loughborough University - Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * Sources for the BATtery MONitor app. It dumps a log entry to the + * external flash periodically as well as upon external trigger. + * + * It started off as a VDD and battery logger but now it also stores + * energest values and other goodies. + * + * \author + * George Oikonomou - + */ + +#include "contiki.h" + +#define DEBUG 0 +#if DEBUG +#include +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif + +#include "sys/etimer.h" +#include "sys/energest.h" +#include "dev/sensinode-sensors.h" +#include "dev/n740.h" +#include "dev/m25p16.h" + +#define BATMON_LOG_PERIOD 60 /* in seconds */ +/*---------------------------------------------------------------------------*/ +static const uint8_t magic[3] = { 0x0B, 0xEE, 0xF0 }; +/*---------------------------------------------------------------------------*/ +struct record { + uint8_t magic[3]; + uint8_t trigger; + unsigned long c; /* uptime */ + int v; /* VDD (reference) */ + int b; /* Voltage ADC */ +#if ENERGEST_CONF_ON + unsigned long mcu; + unsigned long lpm; + unsigned long irq; + unsigned long tx; + unsigned long rx; + unsigned long f_write; + unsigned long f_read; +#endif +}; + +#define RECORD_SIZE 64 +#define LAST_WRITE (0xFFFF - RECORD_SIZE) + +#define LOG_TRIGGER_PERIODIC 0xFF +/*---------------------------------------------------------------------------*/ +struct flash_address { + uint8_t s; /* sector */ + uint8_t p; /* page */ + uint8_t a; /* address */ +}; +static struct flash_address f; + +static struct record r; +static struct sensors_sensor * s; +static struct etimer et; +#define FLASH_START_ADDR 0x1E0000 +#define FLASH_END_ADDR 0x1FFFFF +/*---------------------------------------------------------------------------*/ +PROCESS(batmon_process, "Logger Process"); +/*---------------------------------------------------------------------------*/ +static int +find_gap() +{ + uint8_t seq[3]; + uint32_t address = FLASH_START_ADDR; + memset(&f, 0, sizeof(f)); + + for(address = FLASH_START_ADDR; address <= FLASH_END_ADDR; address += + RECORD_SIZE) { + n740_analog_deactivate(); + f.s = ((address & 0xFF0000) >> 16); + f.p = ((address & 0xFF00) >> 8); + f.a = address & 0xFF; + m25p16_read_fast((uint8_t *)&f, seq, sizeof(magic)); + n740_analog_activate(); + if(memcmp(seq, magic, sizeof(magic)) != 0) { + PRINTF("BatMon: Resume write @ 0x%02x%02x%02x\n", f.s, f.p, f.a); + return 1; + } + } + + /* If we reach here, we ran out of flash */ + return -1; +} +/*---------------------------------------------------------------------------*/ +static void +abort() +{ + PRINTF("BatMon: Abort\n"); + etimer_stop(&et); + process_exit(&batmon_process); +} +/*---------------------------------------------------------------------------*/ +void +batmon_log(uint8_t trigger) +{ + uint32_t next; + + /* Only continue if the process (us) is running */ + if(!process_is_running(&batmon_process)) { + return; + } + + next = f.a; + next |= (((uint32_t) f.p) << 8); + next |= (((uint32_t) f.s) << 16); + + memcpy(r.magic, magic, sizeof(magic)); + r.trigger = trigger; + r.c = clock_seconds(); + + /* Read VDD and use as ADC reference */ + r.v = s->value(ADC_SENSOR_TYPE_VDD); + + /* And then carry on with battery */ + r.b = s->value(ADC_SENSOR_TYPE_BATTERY); + +#if ENERGEST_CONF_ON + /* ENERGEST values */ + r.mcu = energest_type_time(ENERGEST_TYPE_CPU); + r.lpm = energest_type_time(ENERGEST_TYPE_LPM); + r.irq = energest_type_time(ENERGEST_TYPE_IRQ); + r.tx = energest_type_time(ENERGEST_TYPE_TRANSMIT); + r.rx = energest_type_time(ENERGEST_TYPE_LISTEN); + r.f_write = energest_type_time(ENERGEST_TYPE_FLASH_WRITE); + r.f_read = energest_type_time(ENERGEST_TYPE_FLASH_READ); +#endif + + n740_analog_deactivate(); + /* Make sure we're on */ + if(M25P16_WIP()) { + m25p16_res(); + } + m25p16_pp((uint8_t *)&f, (uint8_t *)&r, sizeof(r)); + n740_analog_activate(); + + PRINTF("BatMon: @%lu [%u] ", r.c, r.trigger); + PRINTF("BatMon: 0x%02x%02x%02x\n", f.s, f.p, f.a); + + next += RECORD_SIZE; + + if(next >= FLASH_END_ADDR) { + abort(); + return; + } + + f.s = ((next & 0xFF0000) >> 16); + f.p = ((next & 0xFF00) >> 8); + f.a = next & 0xFF; + + if(trigger == LOG_TRIGGER_PERIODIC) { + etimer_reset(&et); + } +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(batmon_process, ev, data) +{ + + PROCESS_BEGIN(); + + PRINTF("BatMon\n", sizeof(r)); + + s = sensors_find(ADC_SENSOR); + if (!s) { + PRINTF("BatMon: ADC not found\n"); + PROCESS_EXIT(); + } + + n740_analog_deactivate(); + m25p16_res(); + n740_analog_activate(); + + /* Find last written location */ + if(find_gap() == -1) { + PRINTF("BatMon: Flash storage full\n"); + PROCESS_EXIT(); + } + + etimer_set(&et, BATMON_LOG_PERIOD * CLOCK_SECOND); + + while(1) { + PROCESS_YIELD(); + if(ev == PROCESS_EVENT_TIMER && etimer_expired(&et)) { + batmon_log(LOG_TRIGGER_PERIODIC); + } + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ diff --git a/platform/sensinode/contiki-conf.h b/platform/sensinode/contiki-conf.h index 2f8148ae5..894c2174a 100644 --- a/platform/sensinode/contiki-conf.h +++ b/platform/sensinode/contiki-conf.h @@ -1,21 +1,23 @@ - #ifndef __CONTIKI_CONF_H__ #define __CONTIKI_CONF_H__ #include "8051def.h" #include "sys/cc.h" -#include #include -#include "log.h" -/* Time type. */ -/*typedef unsigned long clock_time_t;*/ -typedef unsigned short clock_time_t; +/* Include Project Specific conf */ +#ifdef PROJECT_CONF_H +#include "project-conf.h" +#endif /* PROJECT_CONF_H */ /* Defines tick counts for a second. */ #define CLOCK_CONF_SECOND 128 -#define rtimer_arch_now() clock_time() +/* The clock ISR is stack-hungry and may cause crashes. + * Define this as 0 if you are suffering from frequent stack overflows */ +#ifndef CLOCK_CONF_ACCURATE +#define CLOCK_CONF_ACCURATE 1 +#endif /* Memory filesystem RAM size. */ #define CFS_RAM_CONF_SIZE 512 @@ -23,7 +25,256 @@ typedef unsigned short clock_time_t; /* Logging.. */ #define LOG_CONF_ENABLED 0 +/* Energest Module */ +#ifndef ENERGEST_CONF_ON +#define ENERGEST_CONF_ON 0 +#endif + +/* Verbose Startup? Turning this off saves 700+ bytes of CODE in HOME */ +#define STARTUP_CONF_VERBOSE 0 + +/* More CODE space savings by turning off process names */ +#define PROCESS_CONF_NO_PROCESS_NAMES 1 + +/* + * UARTs: 1=>Enabled, 0=>Disabled. Default: Both Disabled (see uart.h) + * Disabling UART0 saves ~200 bytes of CODE. + * Disabling UART1 saves ~500 bytes of CODE but also disables all debugging + * output. Should be used when nodes are meant to run on batteries + * + * On N740, by enabling UART1, you are also enabling an ugly hack which aims + * to detect the USB connection during execution. It will then turn on/off + * UART1 RX interrupts accordingly. This seems to work but you have been warned + * If you start seeing random crashes when on battery, this is where to look. + */ +#ifndef UART_ONE_CONF_ENABLE +#define UART_ONE_CONF_ENABLE 1 +#endif +#ifndef UART_ONE_CONF_WITH_INPUT +#define UART_ONE_CONF_WITH_INPUT 0 +#endif +#define UART_ZERO_CONF_ENABLE 0 + +#ifndef UART_ONE_CONF_HIGH_SPEED +#define UART_ONE_CONF_HIGH_SPEED 0 +#endif + +/* Are we a SLIP bridge? */ +#if SLIP_ARCH_CONF_ENABLE +/* Make sure UART1 is enabled, with interrupts */ +#undef UART_ONE_CONF_ENABLE +#undef UART_ONE_CONF_WITH_INPUT +#define UART_ONE_CONF_ENABLE 1 +#define UART_ONE_CONF_WITH_INPUT 1 +#define UIP_FALLBACK_INTERFACE slip_interface +#endif + +/* Output all captured frames over the UART in hexdump format */ +#ifndef CC2430_RF_CONF_HEXDUMP +#define CC2430_RF_CONF_HEXDUMP 0 +#endif + +#if CC2430_RF_CONF_HEXDUMP +/* We need UART1 output */ +#undef UART_ONE_CONF_ENABLE +#define UART_ONE_CONF_ENABLE 1 +#endif + +/* Code Shortcuts */ +/* + * When set, the RF driver is no longer a contiki process and the RX ISR is + * disabled. Instead of polling the radio process when data arrives, we + * periodically check for data by directly invoking the driver from main() + + * When set, this directive also configures the following bypasses: + * - process_post_synch() in tcpip_input() (we call packet_input()) + * - process_post_synch() in tcpip_uipcall (we call the relevant pthread) + * - mac_call_sent_callback() is replaced with sent() in various places + * + * These are good things to do, we reduce stack usage, RAM size and code size + */ +#define SHORTCUTS_CONF_NETSTACK 1 + +/* + * Directly read mac from flash with a __code pointer, instead of using the + * generic flash_read() routine. This reduces HOME code size + */ +#define SHORTCUTS_CONF_FLASH_READ 1 + +/* + * Sensors + * It is harmless to #define XYZ 1 + * even if the sensor is not present on our device + */ +#ifndef BUTTON_SENSOR_CONF_ON +#define BUTTON_SENSOR_CONF_ON 1 /* Buttons */ +#endif +/* ADC - Turning this off will disable everything below */ +#ifndef ADC_SENSOR_CONF_ON +#define ADC_SENSOR_CONF_ON 1 +#endif +#define TEMP_SENSOR_CONF_ON 1 /* Temperature */ +#define BATTERY_SENSOR_CONF_ON 1 /* Battery */ +#define VDD_SENSOR_CONF_ON 1 /* Supply Voltage */ +#define ACC_SENSOR_CONF_ON 1 /* Accelerometer */ +#define ACC_SENSOR_CONF_GSEL 0 /* Acc. g-Select => 1: +/-11g, 0: +/-3g */ +#define LIGHT_SENSOR_CONF_ON 1 /* Light */ + +/* Watchdog */ +#define WDT_CONF_INTERVAL 0 +#define WDT_CONF_TIMER_MODE 0 /* 0 or undefined for watchdog mode */ + +/* Low Power Modes - We only support PM0/Idle and PM1 */ +#ifndef LPM_CONF_MODE +#define LPM_CONF_MODE 1 /* 0: no LPM, 1: MCU IDLE, 2: Drop to PM1 */ +#endif + +/* DMA Configuration */ +#ifndef DMA_CONF_ON +#define DMA_CONF_ON 0 +#endif + +/* N740 Serial Flash */ +#ifndef M25P16_CONF_ON +#define M25P16_CONF_ON 1 +#endif + /* XXX argh, ugly hack to make stuff compile! */ #define snprintf(BUF, SIZE, ...) sprintf(BUF, __VA_ARGS__) +/* Sensinode-Specific Tools and APPs */ +/* Viztool on by default for IPv6 builds */ +#if UIP_CONF_IPV6 +#ifndef VIZTOOL_CONF_ON +#define VIZTOOL_CONF_ON 1 +#endif /* VIZTOOL_CONF_ON */ +#endif /* UIP_CONF_IPV6 */ + +/* BatMon off by default unless we build with APPS += batmon */ +#ifndef BATMON_CONF_ON +#define BATMON_CONF_ON 0 +#endif + +/* Network Stack */ +#if UIP_CONF_IPV6 +#define NETSTACK_CONF_NETWORK sicslowpan_driver +#else +#define NETSTACK_CONF_NETWORK rime_driver +#endif + +#ifndef NETSTACK_CONF_MAC +#define NETSTACK_CONF_MAC csma_driver +#endif + +#ifndef NETSTACK_CONF_RDC +#define NETSTACK_CONF_RDC nullrdc_driver +#define NULLRDC_802154_AUTOACK 1 +#define NULLRDC_802154_AUTOACK_HW 1 +#endif + +#ifndef NETSTACK_CONF_RDC_CHANNEL_CHECK_RATE +#define NETSTACK_CONF_RDC_CHANNEL_CHECK_RATE 8 +#endif + +#define NETSTACK_CONF_FRAMER framer_802154 +#define NETSTACK_CONF_RADIO cc2430_rf_driver + +/* RF Config */ +#define IEEE802154_CONF_PANID 0x4C55 /* LU */ + +#ifndef CC2430_RF_CONF_CHANNEL +#define CC2430_RF_CONF_CHANNEL 25 +#endif /* CC2430_RF_CONF_CHANNEL */ + +#ifndef CC2430_RF_CONF_TX_POWER +#define CC2430_RF_CONF_TX_POWER 0x5F /* Datasheet recommended value */ +#endif + +#ifndef CC2430_RF_CONF_AUTOACK +#define CC2430_RF_CONF_AUTOACK 1 +#endif /* CC2430_CONF_AUTOACK */ + +#if UIP_CONF_IPV6 +/* Addresses, Sizes and Interfaces */ +/* 8-byte addresses here, 2 otherwise */ +#define RIMEADDR_CONF_SIZE 8 +#define UIP_CONF_LL_802154 1 +#define UIP_CONF_LLH_LEN 0 +#define UIP_CONF_NETIF_MAX_ADDRESSES 3 + +/* TCP, UDP, ICMP */ +#define UIP_CONF_TCP 0 +#define UIP_CONF_UDP 1 +#define UIP_CONF_UDP_CHECKSUMS 1 + +/* ND and Routing */ +#define UIP_CONF_ROUTER 1 +#define UIP_CONF_IPV6_RPL 1 +#define UIP_CONF_ND6_SEND_RA 0 +#define UIP_CONF_IP_FORWARD 0 +#define RPL_CONF_STATS 0 +#define RPL_CONF_MAX_DAG_ENTRIES 1 +#ifndef RPL_CONF_OF +#define RPL_CONF_OF rpl_of_etx +#endif + +#define UIP_CONF_ND6_REACHABLE_TIME 600000 +#define UIP_CONF_ND6_RETRANS_TIMER 10000 + +#ifndef UIP_CONF_DS6_NBR_NBU +#define UIP_CONF_DS6_NBR_NBU 4 /* Handle n Neighbors */ +#endif +#ifndef UIP_CONF_DS6_ROUTE_NBU +#define UIP_CONF_DS6_ROUTE_NBU 4 /* Handle n Routes */ +#endif + +/* uIP */ +#define UIP_CONF_BUFFER_SIZE 240 +#define UIP_CONF_IPV6_QUEUE_PKT 0 +#define UIP_CONF_IPV6_CHECKS 1 +#define UIP_CONF_IPV6_REASSEMBLY 0 + +/* 6lowpan */ +#define SICSLOWPAN_CONF_COMPRESSION SICSLOWPAN_COMPRESSION_HC06 +#ifndef SICSLOWPAN_CONF_FRAG +#define SICSLOWPAN_CONF_FRAG 0 /* About 2KB of CODE if 1 */ +#endif +#define SICSLOWPAN_CONF_MAXAGE 8 + +/* Define our IPv6 prefixes/contexts here */ +#define SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS 2 +#define SICSLOWPAN_CONF_ADDR_CONTEXT_0 { \ + addr_contexts[0].prefix[0] = 0x20; \ + addr_contexts[0].prefix[1] = 0x01; \ + addr_contexts[0].prefix[2] = 0x06; \ + addr_contexts[0].prefix[3] = 0x30; \ + addr_contexts[0].prefix[4] = 0x03; \ + addr_contexts[0].prefix[5] = 0x01; \ + addr_contexts[0].prefix[6] = 0x64; \ + addr_contexts[0].prefix[7] = 0x53; \ +} +#define SICSLOWPAN_CONF_ADDR_CONTEXT_1 { \ + addr_contexts[1].prefix[0] = 0x20; \ + addr_contexts[1].prefix[1] = 0x01; \ + addr_contexts[1].prefix[2] = 0x06; \ + addr_contexts[1].prefix[3] = 0x30; \ + addr_contexts[1].prefix[4] = 0x03; \ + addr_contexts[1].prefix[5] = 0x01; \ + addr_contexts[1].prefix[6] = 0x11; \ + addr_contexts[1].prefix[7] = 0x00; \ +} + +#define MAC_CONF_CHANNEL_CHECK_RATE 8 +#ifndef QUEUEBUF_CONF_NUM +#define QUEUEBUF_CONF_NUM 6 +#endif + +#else /* UIP_CONF_IPV6 */ +/* Network setup for non-IPv6 (rime). */ +#define UIP_CONF_IP_FORWARD 1 +#define UIP_CONF_BUFFER_SIZE 108 +#define RIME_CONF_NO_POLITE_ANNOUCEMENTS 0 +#define QUEUEBUF_CONF_NUM 8 +#endif /* UIP_CONF_IPV6 */ + #endif /* __CONTIKI_CONF_H__ */ diff --git a/platform/sensinode/contiki-sensinode-main.c b/platform/sensinode/contiki-sensinode-main.c index dc59c6cb7..a1f9abb9d 100644 --- a/platform/sensinode/contiki-sensinode-main.c +++ b/platform/sensinode/contiki-sensinode-main.c @@ -1,44 +1,83 @@ -#include - #include "contiki.h" #include "sys/clock.h" #include "sys/autostart.h" #include "dev/serial-line.h" +#include "dev/slip.h" #include "dev/bus.h" #include "dev/leds.h" -#include "dev/uart.h" +#include "dev/uart1.h" +#include "dev/dma.h" #include "dev/models.h" #include "dev/cc2430_rf.h" -#include "net/mac/sicslowmac.h" -#include "net/mac/frame802154.h" +#include "dev/watchdog.h" +#include "dev/lpm.h" #include "net/rime.h" +#include "net/netstack.h" +#include "net/mac/frame802154.h" +#include "sensinode-debug.h" +#include "dev/watchdog-cc2430.h" +#include "dev/sensinode-sensors.h" +#include "disco.h" +#include "contiki-lib.h" +#include "contiki-net.h" -volatile int i, a; unsigned short node_id = 0; /* Manually sets MAC address when > 0 */ -/*---------------------------------------------------------------------------*/ -static void -print_processes(struct process * const processes[]) -{ - printf("Starting"); - while(*processes != NULL) { - printf(" '%s'", (*processes)->name); - processes++; - } - printf("\n"); -} -/*---------------------------------------------------------------------------*/ -void -putchar(char c) -{ - /* UART1 used for debugging on Sensinode products. */ - uart1_writeb(c); -} +#if VIZTOOL_CONF_ON +PROCESS_NAME(viztool_process); +#endif + +#if BATMON_CONF_ON +PROCESS_NAME(batmon_process); +#endif + +#if SHORTCUTS_CONF_NETSTACK +static __data int len; +#endif + +#ifdef STARTUP_CONF_VERBOSE +#define STARTUP_VERBOSE STARTUP_CONF_VERBOSE +#else +#define STARTUP_VERBOSE 0 +#endif + +#if STARTUP_VERBOSE +#define PUTSTRING(...) putstring(__VA_ARGS__) +#define PUTHEX(...) puthex(__VA_ARGS__) +#define PUTBIN(...) putbin(__VA_ARGS__) +#define PUTCHAR(...) putchar(__VA_ARGS__) +#else +#define PUTSTRING(...) do {} while(0) +#define PUTHEX(...) do {} while(0) +#define PUTBIN(...) do {} while(0) +#define PUTCHAR(...) do {} while(0) +#endif + + +#if !CLOCK_CONF_ACCURATE +extern volatile __data clock_time_t count; +/* accurate clock is stack hungry */ +extern volatile __bit sleep_flag; +#endif + +extern rimeaddr_t rimeaddr_node_addr; +static __data int r; +#if ENERGEST_CONF_ON +static unsigned long irq_energest = 0; +#define ENERGEST_IRQ_SAVE(a) do { \ + a = energest_type_time(ENERGEST_TYPE_IRQ); } while(0) +#define ENERGEST_IRQ_RESTORE(a) do { \ + energest_type_set(ENERGEST_TYPE_IRQ, a); } while(0) +#else +#define ENERGEST_IRQ_SAVE(a) do {} while(0) +#define ENERGEST_IRQ_RESTORE(a) do {} while(0) +#endif /*---------------------------------------------------------------------------*/ static void fade(int l) { + volatile int i, a; int k, j; for(k = 0; k < 400; ++k) { j = k > 200? 400 - k: k; @@ -57,52 +96,86 @@ fade(int l) static void set_rime_addr(void) { - rimeaddr_t addr; - uint8_t ft_buffer[8]; uint8_t *addr_long = NULL; uint16_t addr_short = 0; - int i; + char i; - /* TODO: This flash_read routine currently gets a different address - * than nano_programmer -m... something broken or misconfigured... - */ - - flash_read(&ft_buffer[0], 0x1FFF8, 8); - - printf("Read MAC from flash: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", - ft_buffer[0], ft_buffer[1], ft_buffer[2], ft_buffer[3], - ft_buffer[4], ft_buffer[5], ft_buffer[6], ft_buffer[7]); - - memset(&addr, 0, sizeof(rimeaddr_t)); - -#if UIP_CONF_IPV6 - memcpy(addr.u8, ft_buffer, sizeof(addr.u8)); +#if SHORTCUTS_CONF_FLASH_READ + __code unsigned char * macp; #else - if(node_id == 0) { - for(i = 0; i < sizeof(rimeaddr_t); ++i) { - addr.u8[i] = ft_buffer[7 - i]; - } - } else { - printf("Setting manual address from node_id\n"); - addr.u8[1] = node_id >> 8; - addr.u8[0] = node_id & 0xff; - } + static uint8_t ft_buffer[8]; #endif - rimeaddr_set_node_addr(&addr); - printf("Rime configured with address "); - for(i = (sizeof(addr.u8)) - 1; i > 0; i--) { - printf("%02x:", addr.u8[i]); + PUTSTRING("Rime is 0x"); + PUTHEX(sizeof(rimeaddr_t)); + PUTSTRING(" bytes long\n"); + + if(node_id == 0) { + PUTSTRING("Reading MAC from flash\n"); +#if SHORTCUTS_CONF_FLASH_READ + /* + * The MAC is always stored in 0x1FFF8 of our flash. This maps to address + * 0xFFF8 of our CODE segment, when BANK3 is selected. + * Switch to BANK3, read 8 bytes starting at 0xFFF8 and restore last BANK + * Since we are called from main(), this MUST be BANK1 or something is very + * wrong. This code can be used even without banking + */ + + /* Don't interrupt us to make sure no BANK switching happens while working */ + DISABLE_INTERRUPTS(); + + /* Switch to BANK3, map CODE: 0x8000 – 0xFFFF to FLASH: 0x18000 – 0x1FFFF */ + FMAP = 3; + + /* Set our pointer to the correct address and fetch 8 bytes of MAC */ + macp = (__code unsigned char *) 0xFFF8; + + for(i = (RIMEADDR_SIZE - 1); i >= 0; --i) { + rimeaddr_node_addr.u8[i] = *macp; + macp++; + } + + /* Remap 0x8000 – 0xFFFF to BANK1 */ + FMAP = 1; + ENABLE_INTERRUPTS(); +#else + /* + * Or use the more generic flash_read() routine which can read from any + * address of our flash + */ + flash_read(ft_buffer, 0x1FFF8, 8); + + /* Flip the byte order and store MSB first */ + for(i = (RIMEADDR_SIZE - 1); i >= 0; --i) { + rimeaddr_node_addr.u8[RIMEADDR_SIZE - 1 - i] = ft_buffer[i]; + } +#endif + + } else { + PUTSTRING("Setting manual address from node_id\n"); + rimeaddr_node_addr.u8[RIMEADDR_SIZE - 1] = node_id >> 8; + rimeaddr_node_addr.u8[RIMEADDR_SIZE - 2] = node_id & 0xff; } - printf("%02x\n", addr.u8[i]); + + /* Now the address is stored MSB first */ +#if STARTUP_VERBOSE + PUTSTRING("Rime configured with address "); + for(i = 0; i < RIMEADDR_SIZE - 1; i++) { + PUTHEX(rimeaddr_node_addr.u8[i]); + PUTCHAR(':'); + } + PUTHEX(rimeaddr_node_addr.u8[i]); + PUTCHAR('\n'); +#endif /* Set the cc2430 RF addresses */ - if (sizeof(addr.u8) == 6) - addr_long = (uint8_t *) addr.u8; - else - addr_short = (addr.u8[1] * 256) + addr.u8[0]; - - cc2430_rf_set_addr(0xffff, addr_short, addr_long); +#if (RIMEADDR_SIZE==8) + addr_short = (rimeaddr_node_addr.u8[6] * 256) + rimeaddr_node_addr.u8[7]; + addr_long = (uint8_t *) &rimeaddr_node_addr; +#else + addr_short = (rimeaddr_node_addr.u8[0] * 256) + rimeaddr_node_addr.u8[1]; +#endif + cc2430_rf_set_addr(IEEE802154_PANID, addr_short, addr_long); } /*---------------------------------------------------------------------------*/ int @@ -111,37 +184,220 @@ main(void) /* Hardware initialization */ bus_init(); + rtimer_init(); + /* model-specific h/w init. */ + model_init(); + + /* Init LEDs here */ leds_init(); fade(LEDS_GREEN); - uart1_init(115200); - uart1_set_input(serial_line_input_byte); - /* initialize process manager. */ process_init(); + /* Init UART1 */ + uart1_init(); + +#if DMA_ON + dma_init(); +#endif + +#if SLIP_ARCH_CONF_ENABLE + /* On cc2430, the argument is not used */ + slip_arch_init(0); +#else + uart1_set_input(serial_line_input_byte); serial_line_init(); +#endif - printf("\n" CONTIKI_VERSION_STRING " started\n"); - printf("model: " SENSINODE_MODEL "\n\n"); + PUTSTRING("##########################################\n"); + putstring(CONTIKI_VERSION_STRING "\n"); + putstring(SENSINODE_MODEL " (CC24"); + puthex(((CHIPID >> 3) | 0x20)); + putstring("-" FLASH_SIZE ")\n"); - /* initialize the radio driver */ +#if STARTUP_VERBOSE +#ifdef HAVE_SDCC_BANKING + PUTSTRING(" With Banking.\n"); +#endif /* HAVE_SDCC_BANKING */ +#ifdef SDCC_MODEL_LARGE + PUTSTRING(" --model-large\n"); +#endif /* SDCC_MODEL_LARGE */ +#ifdef SDCC_MODEL_HUGE + PUTSTRING(" --model-huge\n"); +#endif /* SDCC_MODEL_HUGE */ +#ifdef SDCC_STACK_AUTO + PUTSTRING(" --stack-auto\n"); +#endif /* SDCC_STACK_AUTO */ - cc2430_rf_init(); - rime_init(sicslowmac_init(&cc2430_rf_driver)); - set_rime_addr(); + PUTCHAR('\n'); + + PUTSTRING(" Net: "); + PUTSTRING(NETSTACK_NETWORK.name); + PUTCHAR('\n'); + PUTSTRING(" MAC: "); + PUTSTRING(NETSTACK_MAC.name); + PUTCHAR('\n'); + PUTSTRING(" RDC: "); + PUTSTRING(NETSTACK_RDC.name); + PUTCHAR('\n'); + + PUTSTRING("##########################################\n"); +#endif + + watchdog_init(); + + /* Initialise the cc2430 RNG engine. */ + random_init(0); /* start services */ process_start(&etimer_process, NULL); + ctimer_init(); + + /* initialize the netstack */ + netstack_init(); + set_rime_addr(); + +#if BUTTON_SENSOR_ON || ADC_SENSOR_ON + process_start(&sensors_process, NULL); + sensinode_sensors_activate(); +#endif + +#if UIP_CONF_IPV6 + memcpy(&uip_lladdr.addr, &rimeaddr_node_addr, sizeof(uip_lladdr.addr)); + queuebuf_init(); + process_start(&tcpip_process, NULL); + +#if DISCO_ENABLED + process_start(&disco_process, NULL); +#endif /* DISCO_ENABLED */ + +#if VIZTOOL_CONF_ON + process_start(&viztool_process, NULL); +#endif + +#if (!UIP_CONF_IPV6_RPL) + { + uip_ipaddr_t ipaddr; + + uip_ip6addr(&ipaddr, 0x2001, 0x630, 0x301, 0x6453, 0, 0, 0, 0); + uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); + uip_ds6_addr_add(&ipaddr, 0, ADDR_TENTATIVE); + } +#endif /* UIP_CONF_IPV6_RPL */ +#endif /* UIP_CONF_IPV6 */ + + /* + * Acknowledge the UART1 RX interrupt + * now that we're sure we are ready to process it + */ + model_uart_intr_en(); + + energest_init(); + ENERGEST_ON(ENERGEST_TYPE_CPU); fade(LEDS_RED); +#if BATMON_CONF_ON + process_start(&batmon_process, NULL); +#endif + autostart_start(autostart_processes); + watchdog_start(); + while(1) { - process_run(); - etimer_request_poll(); + do { + /* Reset watchdog and handle polls and events */ + watchdog_periodic(); + + /**/ +#if !CLOCK_CONF_ACCURATE + if(sleep_flag) { + if(etimer_pending() && + (etimer_next_expiration_time() - count - 1) > MAX_TICKS) { /*core/sys/etimer.c*/ + etimer_request_poll(); + } + sleep_flag = 0; + } +#endif + r = process_run(); + } while(r > 0); +#if SHORTCUTS_CONF_NETSTACK + len = NETSTACK_RADIO.pending_packet(); + if(len) { + packetbuf_clear(); + len = NETSTACK_RADIO.read(packetbuf_dataptr(), PACKETBUF_SIZE); + if(len > 0) { + packetbuf_set_datalen(len); + NETSTACK_RDC.input(); + } + } +#endif + +#if LPM_MODE +#if (LPM_MODE==LPM_MODE_PM2) + SLEEP &= ~OSC_PD; /* Make sure both HS OSCs are on */ + while(!(SLEEP & HFRC_STB)); /* Wait for RCOSC to be stable */ + CLKCON |= OSC; /* Switch to the RCOSC */ + while(!(CLKCON & OSC)); /* Wait till it's happened */ + SLEEP |= OSC_PD; /* Turn the other one off */ +#endif /* LPM_MODE==LPM_MODE_PM2 */ + + /* + * Set MCU IDLE or Drop to PM1. Any interrupt will take us out of LPM + * Sleep Timer will wake us up in no more than 7.8ms (max idle interval) + */ + SLEEP = (SLEEP & 0xFC) | (LPM_MODE - 1); + +#if (LPM_MODE==LPM_MODE_PM2) + /* + * Wait 3 NOPs. Either an interrupt occurred and SLEEP.MODE was cleared or + * no interrupt occurred and we can safely power down + */ + __asm + nop + nop + nop + __endasm; + + if (SLEEP & SLEEP_MODE0) { +#endif /* LPM_MODE==LPM_MODE_PM2 */ + + ENERGEST_OFF(ENERGEST_TYPE_CPU); + ENERGEST_ON(ENERGEST_TYPE_LPM); + + /* We are only interested in IRQ energest while idle or in LPM */ + ENERGEST_IRQ_RESTORE(irq_energest); + + /* Go IDLE or Enter PM1 */ + PCON |= IDLE; + + /* First instruction upon exiting PM1 must be a NOP */ + __asm + nop + __endasm; + + /* Remember energest IRQ for next pass */ + ENERGEST_IRQ_SAVE(irq_energest); + + ENERGEST_ON(ENERGEST_TYPE_CPU); + ENERGEST_OFF(ENERGEST_TYPE_LPM); + +#if (LPM_MODE==LPM_MODE_PM2) + SLEEP &= ~OSC_PD; /* Make sure both HS OSCs are on */ + while(!(SLEEP & XOSC_STB)); /* Wait for XOSC to be stable */ + CLKCON &= ~OSC; /* Switch to the XOSC */ + /* + * On occasion the XOSC is reported stable when in reality it's not. + * We need to wait for a safeguard of 64us or more before selecting it + */ + clock_delay(10); + while(CLKCON & OSC); /* Wait till it's happened */ + } +#endif /* LPM_MODE==LPM_MODE_PM2 */ +#endif /* LPM_MODE */ } } /*---------------------------------------------------------------------------*/ diff --git a/platform/sensinode/dev/adc-sensor.c b/platform/sensinode/dev/adc-sensor.c index e69de29bb..8de2deb04 100644 --- a/platform/sensinode/dev/adc-sensor.c +++ b/platform/sensinode/dev/adc-sensor.c @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2010, Loughborough University - Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * ADC sensor module for sensinode devices. + * + * This file respects configuration in contiki-conf.h. It also turns + * off features which are not present in the model that we are + * building for. + * + * \author + * George Oikonomou - + */ +#include "dev/sensinode-sensors.h" + +#if ADC_SENSOR_ON +SENSORS_SENSOR(adc_sensor, ADC_SENSOR, value, configure, status); + +static uint8_t ready; + +/*---------------------------------------------------------------------------*/ +static int +value(int type) +{ + uint16_t reading; + /* + * For single-shot AD conversions, we may only write to ADCCON3[3:0] once + * (This write triggers the conversion). We thus use the variable 'command' + * to store intermediate steps (reference, decimation rate, input channel) + */ + uint8_t command; + + ADCCFG = 0; /* Enables/Disables Input Channel */ + + /* 1.25V ref, max decimation rate */ + command = ADEDIV1 | ADEDIV0; + + /* Clear the Interrupt Flag */ + TCON_ADCIF = 0; + + /* Depending on the desired reading, append the input bits to 'command' and + * enable the corresponding input channel in ADCCFG if necessary */ + switch(type) { +#if TEMP_SENSOR_ON + case ADC_SENSOR_TYPE_TEMP: + command |= ADECH3 | ADECH2 | ADECH1; + break; +#endif +#if ACC_SENSOR_ON + case ADC_SENSOR_TYPE_ACC_X: + ADCCFG = ADC5EN; + command |= ADECH2 | ADECH0; + break; + case ADC_SENSOR_TYPE_ACC_Y: + ADCCFG = ADC6EN; + command |= ADECH2 | ADECH1; + break; + case ADC_SENSOR_TYPE_ACC_Z: + ADCCFG = ADC7EN; + command |= ADECH2 | ADECH1 | ADECH0; + break; +#endif +#if VDD_SENSOR_ON + case ADC_SENSOR_TYPE_VDD: + command |= ADECH3 | ADECH2 | ADECH1 | ADECH0; + break; +#endif +#if LIGHT_SENSOR_ON + case ADC_SENSOR_TYPE_LIGHT: + ADCCFG = ADC0EN; + break; +#endif +#if BATTERY_SENSOR_ON + case ADC_SENSOR_TYPE_BATTERY: + ADCCFG = ADC1EN; + command |= ADECH0 | ADEREF1; /* AVDD_SOC reference */ + break; +#endif + default: + /* If the sensor is not present or disabled in conf, return -1 */ + return -1; + } + + /* Writing in bits 3:0 of ADCCON3 will trigger a single conversion */ + ADCCON3 = command; + + /* + * When the conversion is complete, the ADC interrupt flag is set. We don't + * use an ISR here, we just wait on the flag and clear it afterwards. + */ + while(!TCON_ADCIF); + + /* Clear the Interrupt Flag */ + TCON_ADCIF = 0; + + reading = 0; + reading = ADCL; + reading |= (((uint8_t) ADCH) << 8); + /* 12-bit decimation rate: 4 LS bits are noise */ + reading >>= 4; + + return reading; +} +/*---------------------------------------------------------------------------*/ +static int +status(int type) +{ + return ready; + } +/*---------------------------------------------------------------------------*/ +/* + * On N740 we can control Ill and Acc individually: + * ADC_VAL_OTHERS 0x01 + * ADC_VAL_LIGHT_ON 0x04 + * ADC_VAL_ACC_ON 0x08 + * ADC_VAL_ACC_GSEL 0x10 + * + * Return Value is always light | acc | acc_gsel + * + * SENSORS_ACTIVE: + * - 1: Activate everything, use default setting for ACC G-select + * - 0: Turn everything off + * - xyz: Mask with the defines above and act accordingly. + * + * SENSORS_READY: + * - Return Status (0: all off or a value based on the defines above) + */ +static int +configure(int type, int value) +{ +#ifdef MODEL_N740 + /* + * Read current state of the ser-par, ignoring current sensor settings + * Those will be set all over depending on VALUE + */ + uint8_t ser_par_val = n740_ser_par_get() & 0xF2; +#endif /* MODEL_N740 */ + + /* 'Others' are either compiled in or not. Can't be turned on/off */ + ready = ADC_VAL_ALL; + + switch(type) { + case SENSORS_HW_INIT: + case SENSORS_ACTIVE: +#ifdef MODEL_N740 + if(value == ADC_VAL_ALL) { + value = ADC_VAL_ACC_ON | ADC_VAL_LIGHT_ON; +#if ACC_SENSOR_GSEL + value |= ADC_VAL_ACC_GSEL; +#endif /* ACC_SENSOR_GSEL */ + } +#endif /* MODEL_N740 */ + + /* OK, Now value definitely specifies our bits, start masking + * We will refuse to turn things on if they are specified OFF in conf. */ +#ifdef MODEL_N740 +#if ACC_SENSOR_ON + if(value & ADC_VAL_ACC_ON) { + P0SEL |= 0x80 | 0x40 | 0x20; + ser_par_val |= N740_SER_PAR_ACC; + ready |= ADC_VAL_ACC_ON; +#if ACC_SENSOR_GSEL + if(value & ADC_VAL_ACC_GSEL) { + ser_par_val |= N740_SER_PAR_ACC_GSEL; + ready |= ADC_VAL_ACC_GSEL; + } +#endif /*ACC_SENSOR_GSEL */ + } +#endif /* ACC_SENSOR_ON */ + +#if LIGHT_SENSOR_ON + if(value & ADC_VAL_LIGHT_ON) { + ser_par_val |= N740_SER_PAR_LIGHT; + ready |= ADC_VAL_LIGHT_ON; + } +#endif /* LIGHT_SENSOR_ON */ + n740_ser_par_set(ser_par_val); +#endif /* MODEL_N740 */ + } + return ready; +} + +#endif /* ADC_SENSOR_ON */ diff --git a/platform/sensinode/dev/button-sensor.c b/platform/sensinode/dev/button-sensor.c index deccf2290..ac239fe09 100644 --- a/platform/sensinode/dev/button-sensor.c +++ b/platform/sensinode/dev/button-sensor.c @@ -27,87 +27,174 @@ * SUCH DAMAGE. * * This file is part of the Contiki operating system. - * - * @(#)$Id: button-sensor.c,v 1.1 2009/09/08 20:06:28 zdshelby Exp $ */ -#include "lib/sensors.h" -/*#include "dev/hwconf.h"*/ -#include "dev/button-sensor.h" -#include "dev/leds.h" - -const struct sensors_sensor button_sensor; - -static struct timer debouncetimer; - /* -HWCONF_PIN(BUTTON, 2, 7); -HWCONF_IRQ(BUTTON, 2, 7); -*/ + * Portions of this file build on button-sensor.c in platforms sky and esb + * This file contains ISRs: Keep it in the HOME bank. + */ + +#include "dev/models.h" +#include "lib/sensors.h" +#include "dev/hwconf.h" +#include "dev/sensinode-sensors.h" + +#if BUTTON_SENSOR_ON +static uint8_t p0ien; +static uint8_t p2ien; +static __data struct timer debouncetimer[2]; + +#ifdef MODEL_N740 +HWCONF_PIN(BUTTON_1, 1, 0) +HWCONF_PORT_1_IRQ(BUTTON_1, 0) +HWCONF_PIN(BUTTON_2, 0, 4) +HWCONF_PORT_0_IRQ(BUTTON_2, 4) +#endif /* MODEL_N740 */ + +#ifdef MODEL_N711 +HWCONF_PIN(BUTTON_1, 0, 6) +HWCONF_PORT_0_IRQ(BUTTON_1, 6) +HWCONF_PIN(BUTTON_2, 0, 7) +HWCONF_PORT_0_IRQ(BUTTON_2, 7) +#endif /* MODEL_N711 */ /*---------------------------------------------------------------------------*/ -static void -init(void) +static +int value_b1(int type) { - timer_set(&debouncetimer, 0); - BUTTON_IRQ_EDGE_SELECTD(); - - BUTTON_SELECT(); - BUTTON_MAKE_INPUT(); + return BUTTON_1_READ() || !timer_expired(&debouncetimer[0]); } /*---------------------------------------------------------------------------*/ -static int -irq(void) +static +int status_b1(int type) { - if(BUTTON_CHECK_IRQ()) { - if(timer_expired(&debouncetimer)) { - timer_set(&debouncetimer, CLOCK_SECOND / 4); - sensors_changed(&button_sensor); - return 1; + switch (type) { + case SENSORS_ACTIVE: + case SENSORS_READY: + return BUTTON_1_IRQ_ENABLED(); + } + return 0; +} +/*---------------------------------------------------------------------------*/ +static +int configure_b1(int type, int value) +{ + switch(type) { + case SENSORS_HW_INIT: + /* Generates INT when pressed */ + BUTTON_1_IRQ_EDGE_SELECTD(); + BUTTON_1_SELECT(); + BUTTON_1_MAKE_INPUT(); + return 1; + case SENSORS_ACTIVE: + if(value) { + if(!BUTTON_1_IRQ_ENABLED()) { + timer_set(&debouncetimer[0], 0); + BUTTON_1_IRQ_FLAG_OFF(); + BUTTON_1_ENABLE_IRQ(); +} + } else { + BUTTON_1_DISABLE_IRQ(); + } + return 1; + } + return 0; +} +/*---------------------------------------------------------------------------*/ +static +int value_b2(int type) +{ + return BUTTON_2_READ() || !timer_expired(&debouncetimer[1]); +} +/*---------------------------------------------------------------------------*/ +static +int status_b2(int type) +{ + switch (type) { + case SENSORS_ACTIVE: + case SENSORS_READY: + return BUTTON_2_IRQ_ENABLED(); + } + return 0; +} +/*---------------------------------------------------------------------------*/ +static +int configure_b2(int type, int value) +{ + switch(type) { + case SENSORS_HW_INIT: + /* Generates INT when released */ + /* BUTTON_2_IRQ_EDGE_SELECTD(); */ + BUTTON_2_SELECT(); + BUTTON_2_MAKE_INPUT(); + return 1; + case SENSORS_ACTIVE: + if(value) { + if(!BUTTON_2_IRQ_ENABLED()) { + timer_set(&debouncetimer[1], 0); + BUTTON_2_IRQ_FLAG_OFF(); + BUTTON_2_ENABLE_IRQ(); + } + } else { + BUTTON_2_DISABLE_IRQ(); + } + return 1; + } + return 0; +} +/*---------------------------------------------------------------------------*/ +void +port_0_ISR(void) __interrupt (P0INT_VECTOR) +{ + EA = 0; + ENERGEST_ON(ENERGEST_TYPE_IRQ); + + /* This ISR is for the entire port. Check if the interrupt was caused by our + * button's pin. */ + /* Check B1 for N711 */ +#ifdef MODEL_N711 + if(BUTTON_1_CHECK_IRQ()) { + if(timer_expired(&debouncetimer[0])) { + timer_set(&debouncetimer[0], CLOCK_SECOND / 4); + sensors_changed(&button_1_sensor); } } +#endif /* MODEL_N711 */ + if(BUTTON_2_CHECK_IRQ()) { + if(timer_expired(&debouncetimer[1])) { + timer_set(&debouncetimer[1], CLOCK_SECOND / 4); + sensors_changed(&button_2_sensor); + } + } + P0IFG = 0; + IRCON_P0IF = 0; + ENERGEST_OFF(ENERGEST_TYPE_IRQ); + EA = 1; +} +/*---------------------------------------------------------------------------*/ +/* We only need this ISR for N740 */ +#ifdef MODEL_N740 +void +port_1_ISR(void) __interrupt (P1INT_VECTOR) +{ + EA = 0; + ENERGEST_ON(ENERGEST_TYPE_IRQ); - return 0; + /* This ISR is for the entire port. Check if the interrupt was caused by our + * button's pin. This can only be B1 for N740 */ + if(BUTTON_1_CHECK_IRQ()) { + if(timer_expired(&debouncetimer[0])) { + timer_set(&debouncetimer[0], CLOCK_SECOND / 4); + sensors_changed(&button_1_sensor); + } + } + P1IFG = 0; + IRCON2_P1IF = 0; + ENERGEST_OFF(ENERGEST_TYPE_IRQ); + EA = 1; } -/*---------------------------------------------------------------------------*/ -static void -activate(void) -{ - sensors_add_irq(&button_sensor, BUTTON_IRQ_PORT()); - BUTTON_ENABLE_IRQ(); -} -/*---------------------------------------------------------------------------*/ -static void -deactivate(void) -{ - BUTTON_DISABLE_IRQ(); - sensors_remove_irq(&button_sensor, BUTTON_IRQ_PORT()); -} -/*---------------------------------------------------------------------------*/ -static int -active(void) -{ - return BUTTON_IRQ_ENABLED(); -} -/*---------------------------------------------------------------------------*/ -static unsigned int -value(int type) -{ - return BUTTON_READ() || !timer_expired(&debouncetimer); -} -/*---------------------------------------------------------------------------*/ -static int -configure(int type, void *c) -{ - return 0; -} -/*---------------------------------------------------------------------------*/ -static void * -status(int type) -{ - return NULL; -} -/*---------------------------------------------------------------------------*/ -SENSORS_SENSOR(button_sensor, BUTTON_SENSOR, - init, irq, activate, deactivate, active, - value, configure, status); +#endif /* MODEL_N740 */ + +SENSORS_SENSOR(button_1_sensor, BUTTON_1_SENSOR, value_b1, configure_b1, status_b1); +SENSORS_SENSOR(button_2_sensor, BUTTON_2_SENSOR, value_b2, configure_b2, status_b2); +#endif /* BUTTON_SENSOR_ON */ diff --git a/platform/sensinode/dev/button-sensor.h b/platform/sensinode/dev/button-sensor.h new file mode 100644 index 000000000..df3ee6e19 --- /dev/null +++ b/platform/sensinode/dev/button-sensor.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2005, Swedish Institute of Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * Override core/dev/button-sensor.h + * + * We simply include "dev/sensinode-sensors.h". We do this so that apps + * and examples including button-sensor.h will compile for sensinodes + * + * \author + * George Oikonomou - + */ + +#ifndef __BUTTON_SENSOR_H__ +#define __BUTTON_SENSOR_H__ + +#include "dev/sensinode-sensors.h" + +#endif /* __BUTTON_SENSOR_H__ */ diff --git a/platform/sensinode/dev/leds-arch.c b/platform/sensinode/dev/leds-arch.c index 08616f98b..5d4154d2f 100644 --- a/platform/sensinode/dev/leds-arch.c +++ b/platform/sensinode/dev/leds-arch.c @@ -6,14 +6,22 @@ /* * Sensinode v1.0 HW products have 2 red LEDs, LED1 is mapped to the Contiki - * LEDS_RED and LED2 is mapped to LEDS_GREEN. + * LEDS_GREEN and LED2 is mapped to LEDS_RED. */ /*---------------------------------------------------------------------------*/ void leds_arch_init(void) { +#ifdef MODEL_N740 + /* + * We don't need explicit led initialisation for N740s. They are controlled + * by the ser/par chip which is initalised already + */ + return; +#else P0DIR |= 0x30; +#endif } /*---------------------------------------------------------------------------*/ unsigned char @@ -21,29 +29,62 @@ leds_arch_get(void) { unsigned char l = 0; - if(LED1_PIN) { - l |= LEDS_RED; - } - if(LED2_PIN) { +#ifdef MODEL_N740 + /* Read the current ser-par chip status */ + uint8_t ser_par; + ser_par = n740_ser_par_get(); + /* Check bits 7 & 8, ignore the rest */ + if(ser_par & N740_SER_PAR_LED_GREEN) { l |= LEDS_GREEN; } + if(ser_par & N740_SER_PAR_LED_RED) { + l |= LEDS_RED; + } +#else + if(LED1_PIN) { + l |= LEDS_GREEN; + } + if(LED2_PIN) { + l |= LEDS_RED; + } +#endif return l; } /*---------------------------------------------------------------------------*/ void leds_arch_set(unsigned char leds) { +#ifdef MODEL_N740 + /* Read the current ser-par chip status - we want to change bits 7 & 8 but + * the remaining bit values should be retained */ + uint8_t ser_par; + ser_par = n740_ser_par_get(); + if(leds & LEDS_GREEN) { + ser_par |= N740_SER_PAR_LED_GREEN; /* Set bit 7 */ + } else { + ser_par &= ~N740_SER_PAR_LED_GREEN; /* Unset bit 7 */ + } + if(leds & LEDS_RED) { + ser_par |= N740_SER_PAR_LED_RED; /* Set bit 8 */ + } else { + ser_par &= ~N740_SER_PAR_LED_RED; /* Unset bit 8 */ + } + + /* Write the new status back to the chip */ + n740_ser_par_set(ser_par); +#else + if(leds & LEDS_GREEN) { LED1_PIN = 1; } else { LED1_PIN = 0; } - if(leds & LEDS_GREEN) { + if(leds & LEDS_RED) { LED2_PIN = 1; } else { LED2_PIN = 0; } - +#endif } /*---------------------------------------------------------------------------*/ diff --git a/platform/sensinode/dev/m25p16.c b/platform/sensinode/dev/m25p16.c new file mode 100644 index 000000000..5239dbf74 --- /dev/null +++ b/platform/sensinode/dev/m25p16.c @@ -0,0 +1,316 @@ +/* + * Copyright (c) 2010, Loughborough University - Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * This file provides functions to control the M25P16 on sensinode N740s. + * This is a Numonyx Forte Serial Flash Memory (16Mbit) + * The S signal (Chip Select) is controlled via 0x02 on the 74HC595D + * The other instructions and timing are performed with bit bang + * + * We can enable, disable, read/write data, erase pages, hold, enter/exit + * deep sleep etc. + * + * Clock (C) => P1_5, + * Ser. I (D) => P1_6, + * Ser. O (Q) => P1_7, + * Hold => Pull Up, + * Write Prot => Pull Up, + * Chip Sel => 74HC595D (0x02) + * + * This file can be placed in any bank. + * + * \author + * George Oikonomou - + */ + +#include "dev/n740.h" +#include "dev/m25p16.h" +#include "sys/clock.h" +#include "sys/energest.h" +#include "cc2430_sfr.h" + +#define CLOCK_RISING() {M25P16_PIN_CLOCK = 1; M25P16_PIN_CLOCK = 0;} +#define CLOCK_FALLING() {M25P16_PIN_CLOCK = 0; M25P16_PIN_CLOCK = 1;} +/*---------------------------------------------------------------------------*/ +/* Bit-Bang write a byte to the chip */ +static void +bit_bang_write(uint8_t byte) +{ + uint8_t i; + uint8_t bit; + + /* bit-by-bit */ + for(i = 0x80; i > 0; i >>= 1) { + /* Is the bit set? */ + bit = 0; + if(i & byte) { + /* If it was set, we want to send 1 */ + bit = 1; + } + /* Send the bit */ + M25P16_PIN_SER_I = bit; + /* Clock - Rising */ + CLOCK_RISING(); + } +} +/*---------------------------------------------------------------------------*/ +/* Bit-Bang read a byte from the chip */ +static uint8_t +bit_bang_read() +{ + int8_t i; + uint8_t bits = 0; + + /* bit-by-bit */ + for(i = 7; i >= 0; i--) { + /* Clock - Falling */ + CLOCK_FALLING(); + + /* Read the bit */ + bits |= (M25P16_PIN_SER_O << i); + } + return bits; +} +/*---------------------------------------------------------------------------*/ +static void +select() +{ + /* Read current ser/par value */ + uint8_t ser_par = n740_ser_par_get(); + + M25P16_PIN_CLOCK = 0; + + ser_par &= ~N740_SER_PAR_CHIP_SEL; /* Select Flash */ + + /* Write the new status back to the ser/par */ + n740_ser_par_set(ser_par); +} +/*---------------------------------------------------------------------------*/ +static void +deselect() +{ + /* Read current ser/par value */ + uint8_t ser_par = n740_ser_par_get(); + + ser_par |= N740_SER_PAR_CHIP_SEL; /* De-Select Flash */ + + /* Write the new status back to the ser/par */ + n740_ser_par_set(ser_par); +} +/*---------------------------------------------------------------------------*/ +void +m25p16_wren() +{ + select(); + bit_bang_write(M25P16_I_WREN); + deselect(); + + while(!M25P16_WEL()); +} +/*---------------------------------------------------------------------------*/ +void +m25p16_wrdi() +{ + select(); + bit_bang_write(M25P16_I_WRDI); + deselect(); +} +/*---------------------------------------------------------------------------*/ +void +m25p16_rdid(struct m25p16_rdid * rdid) +{ + uint8_t i; + + select(); + bit_bang_write(M25P16_I_RDID); + + rdid->man_id = bit_bang_read(); + rdid->mem_type = bit_bang_read(); /* Device ID MSB */ + rdid->mem_size = bit_bang_read(); /* Device ID LSB */ + rdid->uid_len = bit_bang_read(); + for(i = 0; i < rdid->uid_len; i++) { + rdid->uid[i] = bit_bang_read(); + } + deselect(); +} +/*---------------------------------------------------------------------------*/ +uint8_t +m25p16_rdsr() +{ + uint8_t rv; + + select(); + bit_bang_write(M25P16_I_RDSR); + rv = bit_bang_read(); + deselect(); + + return rv; +} +/*---------------------------------------------------------------------------*/ +void +m25p16_wrsr(uint8_t val) +{ + m25p16_wren(); /* Write Enable */ + + select(); + ENERGEST_ON(ENERGEST_TYPE_FLASH_WRITE); + bit_bang_write(M25P16_I_WRSR); + bit_bang_write(val); + ENERGEST_OFF(ENERGEST_TYPE_FLASH_WRITE); + deselect(); +} +/*---------------------------------------------------------------------------*/ +void +m25p16_read(uint8_t * addr, uint8_t * buff, uint8_t buff_len) +{ + uint8_t i; + + select(); + ENERGEST_ON(ENERGEST_TYPE_FLASH_READ); + +#if M25P16_READ_FAST + bit_bang_write(M25P16_I_FAST_READ); +#else + bit_bang_write(M25P16_I_READ); +#endif + + /* Write the address, MSB in addr[0], bits [7:5] of the MSB: 'don't care' */ + for(i = 0; i < 3; i++) { + bit_bang_write(addr[i]); + } + + /* For FAST_READ, send the dummy byte */ +#if M25P16_READ_FAST + bit_bang_write(M25P16_DUMMY_BYTE); +#endif + + for(i = 0; i < buff_len; i++) { + buff[i] = ~bit_bang_read(); + } + ENERGEST_OFF(ENERGEST_TYPE_FLASH_READ); + deselect(); +} +/*---------------------------------------------------------------------------*/ +void +m25p16_pp(uint8_t * addr, uint8_t * buff, uint8_t buff_len) +{ + uint8_t i; + + m25p16_wren(); /* Write Enable */ + + select(); + ENERGEST_ON(ENERGEST_TYPE_FLASH_WRITE); + bit_bang_write(M25P16_I_PP); + + /* Write the address, MSB in addr[0] */ + for(i = 0; i < 3; i++) { + bit_bang_write(addr[i]); + } + + /* Write the bytes */ + for(i=0; i + */ + +#ifndef M25P16_H_ +#define M25P16_H_ + +/* Instruction Set */ +#define M25P16_I_WREN 0x06 /* Write Enable */ +#define M25P16_I_WRDI 0x04 /* Write Disable */ +#define M25P16_I_RDID 0x9F /* Read Identification */ +#define M25P16_I_RDSR 0x05 /* Read Status Register */ +#define M25P16_I_WRSR 0x01 /* Write Status Register */ +#define M25P16_I_READ 0x03 /* Read Data Bytes */ +#define M25P16_I_FAST_READ 0x0B /* Read Data Bytes at Higher Speed */ +#define M25P16_I_PP 0x02 /* Page Program */ +#define M25P16_I_SE 0xD8 /* Sector Erase */ +#define M25P16_I_BE 0xC7 /* Bulk Erase */ +#define M25P16_I_DP 0xB9 /* Deep Power-down */ +#define M25P16_I_RES 0xAB /* Release from Deep Power-down */ + +/* Dummy Byte - Used in FAST_READ and RES */ +#define M25P16_DUMMY_BYTE 0x00 + +/* Pins */ +#define M25P16_PIN_CLOCK P1_5 +#define M25P16_PIN_SER_I P1_6 +#define M25P16_PIN_SER_O P1_7 + +/* Status Register Bits */ +#define M25P16_SR_SRWD 0x80 /* Status Register Write Disable */ +#define M25P16_SR_BP2 0x10 /* Block Protect 2 */ +#define M25P16_SR_BP1 0x08 /* Block Protect 1 */ +#define M25P16_SR_BP0 0x04 /* Block Protect 0 */ +#define M25P16_SR_BP 0x1C /* All Block Protect Bits */ +#define M25P16_SR_WEL 0x02 /* Write Enable Latch */ +#define M25P16_SR_WIP 0x01 /* Write in Progress */ + +/* Do we use READ or FAST_READ to read? Fast by default */ +#ifdef M25P16_CONF_READ_FAST +#define M25P16_READ_FAST M25P16_CONF_READ_FAST +#else +#define M25P16_READ_FAST 1 +#endif +/*---------------------------------------------------------------------------*/ +/** \brief Device Identifier + * + * Holds the value of the device identifier, returned by the RDID instruction. + * + * After a correct RDID, this structure should hold the following values: + * man_id = 0x20, mem_type = 0x20, mem_size = 0x15, uid_len = 0x10. + * + * UID holds optional Customized Factory Data (CFD) content. The CFD bytes are + * read-only and can be programmed with customers data upon their request. + * If the customers do not make requests, the devices are shipped with all the + * CFD bytes programmed to 0x00. + */ +struct m25p16_rdid { + uint8_t man_id; /** Manufacturer ID */ + uint8_t mem_type; /** Memory Type */ + uint8_t mem_size; /** Memory Size */ + uint8_t uid_len; /** Unique ID length */ + uint8_t uid[16]; /** Unique ID */ +}; +/*---------------------------------------------------------------------------*/ +/** + * \brief Retrieve Block Protect Bits from the status register + * + * This macro returns the software block protect status on the device + * by reading the value of the BP bits ([5:3]) in the Status Register + */ +#define M25P16_BP() (m25p16_rdsr() & M25P16_SR_BP) +/** + * \brief Check for Write in Progress + * \retval 1 Write in progress + * \retval 0 Write not in progress + * + * This macro checks if the device is currently in the middle of a write cycle + * by reading the value of the WIP bit (bit 0) in the Status Register + */ +#define M25P16_WIP() (m25p16_rdsr() & M25P16_SR_WIP) +/** + * \brief Check for Write-Enable + * \retval 1 Write enabled + * \retval 0 Write disabled + * + * This macro checks if the device is ready to accept a write instruction + * by reading the value of the WEL bit (bit 1) in the Status Register + */ +#define M25P16_WEL() (m25p16_rdsr() & M25P16_SR_WEL) +/*---------------------------------------------------------------------------*/ +/** + * \brief Write Enable (WREN) instruction. + * + * Completing a WRDI, PP, SE, BE and WRSR + * resets the write enable latch bit, so this instruction should be used every + * time before trying to write. + */ +void m25p16_wren(); + +/** + * \brief Write Disable (WRDI) instruction + */ +void m25p16_wrdi(); + +/** + * \brief Read Identifier (RDID)instruction + * + * \param rdid Pointer to a struct which will hold the information returned + * by the RDID instruction + */ +void m25p16_rdid(struct m25p16_rdid * rdid); + +/** + * \brief Read Status Register (RDSR) instruction + * + * \return Value of the status register + * + * Reads and returns the value of the status register on the Flash Chip + */ +uint8_t m25p16_rdsr(); + +/** + * \brief Write Status Register (WRSR) instruction + * \param val Value to be written to the status register + * + * This instruction does not afect bits 6, 5, 1 and 0 of the SR. + */ +void m25p16_wrsr(uint8_t val); + +/** + * \brief Read Data Bytes (READ) instruction + * \param addr 3 byte array holding the read start address. MSB stored in + * addr[0] and LSB in addr[2] + * \param buff Pointer to a buffer to hold the read bytes. + * \param buff_len Number of bytes to read. buff must be long enough to hold + * buff_len bytes + * + * The bytes will be inverted after being read, so that a value of 0xFF (empty) + * in the flash will read as 0x00 + */ +void m25p16_read(uint8_t * addr, uint8_t * buff, uint8_t buff_len); + +/** + * \brief Program Page (PP) instruction + * \param addr 3 byte array holding the write start address. MSB stored in + * addr[0] and LSB in addr[2] + * \param buff Pointer to a buffer with the data to be written + * \param buff_len Number of bytes to write, Maximum 256 bytes. + * + * Write BUFF_LEN bytes stored in BUFF to flash, starting from location + * ADDR. BUFF_LEN may not exceed 256. ADDR should point to a 3 byte array, + * with the address MSB stored in position 0 and LSB in position 2 + * + * If the start address + buff_len exceed page boundaries, the write will + * wrap to the start of the same page (the page at addr[2:1]). + * + * The bytes will be inverted before being written, so that a value of 0xFF + * will be written as 0x00 (and subsequently correctly read as 0xFF by READ) + * + * This function will set the WEL bit on the SR before attempting to write, + * so the calling function doesn't need to worry about this. + * + * This call is asynchronous. It will return before the write cycle has + * completed. Thus, user software must check the WIP bit Write In Progress) + * before sending further instructions. This can take up to 5 msecs (typical + * duration for a 256 byte write is 640 usec) + */ +void m25p16_pp(uint8_t * addr, uint8_t * buff, uint8_t buff_len); + +/** + * \brief Sector Erase (SE) instruction + * \param s The number of the sector to be erased + * + * Delete the entire sector number s, by setting it's contents to all 0xFF + * (which will read as 0x00 by READ). The flash is broken down into 32 sectors, + * 64 KBytes each. + * + * This function will set the WEL bit on the SR before attempting to write, + * so the calling function doesn't need to worry about this. + * + * This call is asynchronous. It will return before the write cycle has + * completed. Thus, user software must check the WIP bit Write In Progress) + * before sending further instructions. This can take up to 3 secs (typical + * duration 600 msec) + */ +void m25p16_se(uint8_t s); /* Sector Erase */ + + +/** + * \brief Bulk Erase (SE) instruction + * + * Delete the entire memory, by setting it's contents to all 0xFF + * (which will read as 0x00 by READ). + * + * This function will set the WEL bit on the SR before attempting to write, + * so the calling function doesn't need to worry about this. + * + * This call is asynchronous. It will return before the write cycle has + * completed. Thus, user software must check the WIP bit Write In Progress) + * before sending further instructions. + * + * This instructions takes a very long time to complete and must be used with + * care. It can take up to 40 secs (yes, secs). A typical duration is 13 secs + */ +void m25p16_be(); + +/** + * \brief Deep Power Down (DP) instruction + * + * Puts the device into its lowers power consumption mode (This is not the same + * as the stand-by mode caused by de-selecting the device). While the device + * is in DP, it will accept no instruction except a RES (Release from DP). + * + * This call is asynchronous and will return as soon as the instruction + * sequence has been written but before the device has actually entered DP + * + * Dropping to DP takes 3usec and Resuming from DP takes at least 1.8usec, so + * this sequence should not be used when the sleep interval is estimated to be + * short (read as: don't DP then RES then DP repeatedly) + */ +void m25p16_dp(); /* Deep Power down */ + +/** + * \brief Release from Deep Power Down (RES) instruction + * + * Take the device out of the Deep Power Down mode and bring it to standby. + * Does not read the electronic signature. + * + * This call is synchronous. When it returns the device will be in standby + * mode. + * + * Dropping to DP takes 3usec and Resuming from DP takes at least 1.8usec, so + * this sequence should not be used when the sleep interval is estimated to be + * short (read as: don't DP then RES then DP repeatedly) + */ +void m25p16_res(); + +/** + * \brief Release from Deep Power Down (RES) and Read Electronic + * Signature instruction + * + * \return The value of the electronic signature. This is provided for backward + * compatibility and must always be 0x14 + * + * Take the device out of the Deep Power Down mode and bring it to standby. + * Does not read the electronic signature. + * + * This call is synchronous. When it returns the device will be in standby + * mode. + * + * Dropping to DP takes 3usec and Resuming from DP takes at least 1.8usec, so + * this sequence should not be used when the sleep interval is estimated to be + * short (read as: don't DP then RES then DP repeatedly) + */ +uint8_t m25p16_res_res(); + +#endif /* M25P16_H_ */ diff --git a/platform/sensinode/dev/models.c b/platform/sensinode/dev/models.c new file mode 100644 index 000000000..15b21fffa --- /dev/null +++ b/platform/sensinode/dev/models.c @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2010, Loughborough University - Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * Model-specific functions for Sensinode devices. + * + * Bankable + * + * \author + * George Oikonomou - + */ + +#include "dev/models.h" +#include "dev/uart1.h" +#include "dev/m25p16.h" +/*---------------------------------------------------------------------------*/ +void +model_init() +{ +#ifdef MODEL_N740 + /* + * We want to prevent the dongle from controlling the state of the + * analog switch on the N740s. + * + * Set P0_3 as out and start with P0_3=0 (USB and Light selected) + */ + P0DIR |= 0x08; /* P0_3 out */ + P0_3 = 0; + + /* Init the serial-parallel chip for N740s. This will also 'init' LEDs */ + n740_ser_par_init(); + + /* Put the Serial Flash in Deep Power mode */ + n740_analog_deactivate(); + +#if M25P16_CONF_ON + m25p16_dp(); +#endif /* SERIAL_FLASH_CONF_ON */ + + n740_ser_par_set(0); +#endif +} +/*---------------------------------------------------------------------------*/ +void +model_uart_intr_en() +{ +#ifdef MODEL_N740 + /* + * Dirty, ugly hack for the N740 USART1 RX issue: + * When the USB is for whatever reason disabled (either disconnected or the + * analog switch has switched to the D-connector), RX starts flowing down + * pin 1.7 (and the line stays low), resulting in non-stop UART1_RX + * interrupts. So, we only acknowledge the interrupt when the line is + * high and the dongle is connected (thus we are on USB). + * + * For all other models, just turn the interrupt on + * + * Interrupts will only turn on if UART_ONE_CONF_WITH_INPUT is defined 1 + */ + if(P1_7 == 1 && P0_3 == 0) { + UART1_RX_INT(1); + } +#else + UART1_RX_INT(1); +#endif +} diff --git a/platform/sensinode/dev/models.h b/platform/sensinode/dev/models.h index 22e1e99f5..500932b17 100644 --- a/platform/sensinode/dev/models.h +++ b/platform/sensinode/dev/models.h @@ -3,31 +3,44 @@ /* Define model text */ #ifdef MODEL_N100 -#define SENSINODE_MODEL "N100 Module (CC2431-F128)" +#define SENSINODE_MODEL "N100 Module" #endif #ifdef MODEL_N600 -#define SENSINODE_MODEL "N600 NanoRouter USB (CC2430-F128)" +#define SENSINODE_MODEL "N600 NanoRouter USB" #endif #ifdef MODEL_N601 -#define SENSINODE_MODEL "N601 NanoRouter USB (CC2431-F128)" +#define SENSINODE_MODEL "N601 NanoRouter USB" #endif #ifdef MODEL_N710 -#define SENSINODE_MODEL "N710 NanoSensor (CC2430-F128)" +#define SENSINODE_MODEL "N710 NanoSensor" #endif #ifdef MODEL_N711 -#define SENSINODE_MODEL "N711 NanoSensor (CC2431-F128)" +#define SENSINODE_MODEL "N711 NanoSensor" +#endif +#ifdef MODEL_N740 +#define SENSINODE_MODEL "N740 NanoSensor" #endif #ifndef SENSINODE_MODEL -#define MODEL_N100 -#define SENSINODE_MODEL "Sensinode N100 (CC2431-F128)" +#define SENSINODE_MODEL "N100 Module" #endif -/* All current models use these LED pins */ +#ifndef FLASH_SIZE +#define FLASH_SIZE "F128" +#endif + +/* + * N740 has a serial-parallel chip onboard + * Defines and functions to control it + */ +#ifdef MODEL_N740 +#include "dev/n740.h" + +#else +/* All other models use these LED pins */ #define LED1_PIN P0_4 #define LED2_PIN P0_5 - -/* Buttons */ +#endif #ifdef MODEL_N711 #define BUTTON1_PIN P0_6 @@ -41,4 +54,7 @@ #define TEMP_PIN P0_1 #endif +/* Model-Specific startup functions */ +void model_init(); +void model_uart_intr_en(); #endif /* __MODELS_H__ */ diff --git a/platform/sensinode/dev/n740.c b/platform/sensinode/dev/n740.c new file mode 100644 index 000000000..d47aa3f6a --- /dev/null +++ b/platform/sensinode/dev/n740.c @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2010, Loughborough University - Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * This file provides functions to control various chips on the + * Sensinode N740s: + * + * - The 74HC595D is an 8-bit serial in-parallel out shift register. + * LEDs are connected to this chip. It also serves other functions such as + * enabling/disabling the Accelerometer (see n740.h). + * - The 74HC4053D is a triple, 2-channel analog mux/de-mux. + * It switches I/O between the USB and the D-Connector. + * It also controls P0_0 input source (Light Sensor / External I/O) + * + * Mux/De-mux: Connected to P0_3 (set to output in models.c + * Changing the state of the mux/demux can have catastrophic (tm) results + * on our software. If we are not careful, we risk entering a state where + * UART1 RX interrupts are being generated non-stop. Only change its state + * via the function in this file. + * + * Shift Register: + * For the shift register we can: + * - write a new instruction + * - remember and retrieve the last instruction sent + * + * The chip is connected to CPU pins as follows: + * - P0_2: Serial Data Input + * - P1_3: Shift Register Clock Input + * - P1_1: Storage Register Clock + * + * This file can be placed in any bank. + * + * \author + * George Oikonomou - + */ + +#include "dev/n740.h" +#include "dev/uart1.h" + +/* + * This variable stores the most recent instruction sent to the ser-par chip. + * We declare it as static and return its value through n740_ser_par_get(). + */ +static __data uint8_t ser_par_status; + +/*---------------------------------------------------------------------------*/ +/* Init the serial-parallel chip: + * - Set I/O direction for all 3 pins (P0_2, P1_1 and P1_3) to output + */ +void +n740_ser_par_init() +{ + /* bus_init and uart1_init also touch the I/O direction for those pins */ + P1DIR |= 0x0A; + P0DIR |= 0x04; +} +/*---------------------------------------------------------------------------*/ +/* + * Send a command to the N740 serial-parallel chip. Each command is a single + * byte, each bit controls a different feature on the sensor. + */ +void +n740_ser_par_set(uint8_t data) +{ + uint8_t i; + uint8_t mask = 1; + uint8_t temp = 0; + + DISABLE_INTERRUPTS(); + /* bit-by-bit */ + for(i = 0; i < 8; i++) { + temp = (data & mask); + /* Is the bit set? */ + if(i && temp) { + /* If it was set, we want to send 1 */ + temp >>= i; + } + /* Send the bit */ + P0_2 = temp; + /* Shift */ + P1_3 = 1; + P1_3 = 0; + mask <<= 1; + } + /* Move to Par-Out */ + P1_1 = 1; + P1_1 = 0; + ENABLE_INTERRUPTS(); + + /* Right, we're done. Save the new status in ser_par_status */ + ser_par_status = data; +} +/*---------------------------------------------------------------------------*/ +/* This function returns the last value sent to the ser-par chip on the N740. + * + * The caveat here is that we must always use n740_set_ser_par() to send + * commands to the ser-par chip, never write directly. + * + * If any other function sends a command directly, ser_par_status and the + * actual status will end up out of sync. + */ +uint8_t +n740_ser_par_get() +{ + return ser_par_status; +} +/*---------------------------------------------------------------------------*/ +void +n740_analog_switch(uint8_t state) +{ + /* Turn off the UART RX interrupt before switching */ + DISABLE_INTERRUPTS(); + UART1_RX_INT(0); + + /* Switch */ + P0_3 = state; + + /* If P0_3 now points to the USB and nothing is flowing down P1_7, + * enable the interrupt again */ + if(P1_7 == 1 && P0_3 == N740_ANALOG_SWITCH_USB) { + UART1_RX_INT(1); + } + ENABLE_INTERRUPTS(); +} +/*---------------------------------------------------------------------------*/ +/* + * Activate the the 74HC4053D analog switch U5 on the N740 and at the same + * time set relevant pins to Peripheral I/O mode. This stops communications + * with the serial flash and enables UART1 I/O + */ +void +n740_analog_activate() +{ + uint8_t ser_par = n740_ser_par_get(); + ser_par &= ~N740_SER_PAR_U5_ENABLE; /* Turn on */ + + N740_PINS_PER_IO(); + + n740_ser_par_set(ser_par); +} +/*---------------------------------------------------------------------------*/ +/* + * De-Activate the the 74HC4053D analog switch U5 on the N740 and at the same + * time set relevant pins to GP I/O mode. This effectively prepares us to + * start talking with the serial flash chip + */ +void +n740_analog_deactivate() +{ + uint8_t ser_par = n740_ser_par_get(); + ser_par |= N740_SER_PAR_U5_ENABLE; /* Turn off */ + + n740_ser_par_set(ser_par); + + N740_PINS_GPIO(); +} +/*---------------------------------------------------------------------------*/ diff --git a/platform/sensinode/dev/n740.h b/platform/sensinode/dev/n740.h new file mode 100644 index 000000000..3af1f2821 --- /dev/null +++ b/platform/sensinode/dev/n740.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2010, Loughborough University - Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * Header File for the module which controls the Sensinode N740 + * 8-bit serial-in/serial or parallel-out shift register. + * + * This is where the Accelerometer, Leds, Light and Battery Sensors + * are connected. + * + * \author + * George Oikonomou - + */ + +#ifndef N740SERPAR_H_ +#define N740SERPAR_H_ + +#include "8051def.h" + +#define N740_SER_PAR_ACC_GSEL 0x01 /* Acceleration Sensor g-Select */ +#define N740_SER_PAR_CHIP_SEL 0x02 /* Flash Chip Select */ +#define N740_SER_PAR_LIGHT 0x04 /* Light Sensor */ +#define N740_SER_PAR_ACC 0x08 /* Acceleration Sensor */ +#define N740_SER_PAR_RF_IN_GAIN 0x10 /* Receiver Amplifier, best not set */ +#define N740_SER_PAR_U5_ENABLE 0x20 /* U5 analog switch enable */ +#define N740_SER_PAR_LED_GREEN 0x40 /* Led 1 */ +#define N740_SER_PAR_LED_RED 0x80 /* Led 2 */ + +#define N740_ANALOG_SWITCH_USB 0 +#define N740_ANALOG_SWITCH_SERIAL 1 + +#define N740_PINS 0xE0 +#define N740_PINS_GPIO() {P1SEL &= ~N740_PINS;} +#define N740_PINS_PER_IO() {P1SEL |= N740_PINS;} + +/* Serial/Parallel Shift Register (74HC595D) Functions */ +void n740_ser_par_init(void); +void n740_ser_par_set(uint8_t data) ; +uint8_t n740_ser_par_get(void); + +/* Analog Switch (U5 - 74HC4053D) Functions */ +void n740_analog_switch(uint8_t state); +void n740_analog_activate(); +void n740_analog_deactivate(); + +#endif /* N740SERPAR_H_ */ diff --git a/platform/sensinode/dev/sensinode-sensors.c b/platform/sensinode/dev/sensinode-sensors.c new file mode 100644 index 000000000..f94878077 --- /dev/null +++ b/platform/sensinode/dev/sensinode-sensors.c @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2010, Loughborough University - Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * This module centrally controls all sensors on sensinode devices + * + * It respects configuration in contiki-conf.h + * + * \author + * George Oikonomou - + */ + +#include "dev/sensinode-sensors.h" +#include "sys/energest.h" + +const struct sensors_sensor *sensors[] = { +#if ADC_SENSOR_ON + &adc_sensor, +#endif +#if BUTTON_SENSOR_ON + &button_1_sensor, + &button_2_sensor, +#endif + 0 +}; + +unsigned char sensors_flags[(sizeof(sensors) / sizeof(struct sensors_sensor *))]; + +/*---------------------------------------------------------------------------*/ +void +sensinode_sensors_activate() +{ + struct sensors_sensor *sensor; + sensor = sensors_first(); + while (sensor) { + sensor->configure(SENSORS_ACTIVE, 1); + sensor = sensors_next(sensor); + } + ENERGEST_ON(ENERGEST_TYPE_SENSORS); +} +/*---------------------------------------------------------------------------*/ +void +sensinode_sensors_deactivate() +{ + struct sensors_sensor *sensor; + sensor = sensors_first(); + while (sensor) { + sensor->configure(SENSORS_ACTIVE, 0); + sensor = sensors_next(sensor); + } + ENERGEST_OFF(ENERGEST_TYPE_SENSORS); +} diff --git a/platform/sensinode/dev/sensinode-sensors.h b/platform/sensinode/dev/sensinode-sensors.h new file mode 100644 index 000000000..503499ec8 --- /dev/null +++ b/platform/sensinode/dev/sensinode-sensors.h @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2010, Loughborough University - Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * Defines for the sensors on the various Sensinode models. + * + * Sensors will be off by default, unless turned on explicitly + * in contiki-conf.h + * + * If you enable sensors generating interrupts, make sure you include + * this file in the file containing main(). + * + * \author + * George Oikonomou - + */ + +#ifndef SENSINODE_SENSORS_H_ +#define SENSINODE_SENSORS_H_ + +#include "cc2430_sfr.h" +#include "contiki-conf.h" +#include "dev/models.h" +#include "lib/sensors.h" + +void sensinode_sensors_activate(); +void sensinode_sensors_deactivate(); + +/* ADC Sensor Types */ +#define ADC_SENSOR "ADC" + +#define ADC_SENSOR_TYPE_TEMP 0 +#define ADC_SENSOR_TYPE_ACC_X 1 +#define ADC_SENSOR_TYPE_ACC_Y 2 +#define ADC_SENSOR_TYPE_ACC_Z 3 +#define ADC_SENSOR_TYPE_VDD 4 +#define ADC_SENSOR_TYPE_LIGHT 5 +#define ADC_SENSOR_TYPE_BATTERY 6 + +/* Defines to help us control Acc and Ill individually */ +#define ADC_VAL_NONE 0x00 +#define ADC_VAL_ALL 0x01 +#define ADC_VAL_LIGHT_ON 0x04 +#define ADC_VAL_ACC_ON 0x08 +#define ADC_VAL_ACC_GSEL 0x10 + +#ifdef ADC_SENSOR_CONF_ON +#define ADC_SENSOR_ON ADC_SENSOR_CONF_ON +#endif /* ADC_SENSOR_CONF_ON */ + +#if ADC_SENSOR_ON +extern const struct sensors_sensor adc_sensor; +#endif /* ADC_SENSOR_ON */ + +/* + * Accelerometer. Available on N740 only. + * This is a Freescale Semiconductor MMA7340L (3 axis, 3/11g) + * X: P0_5 + * Y: P0_6 + * Z: P0_7 + */ +#ifdef MODEL_N740 +#ifdef ACC_SENSOR_CONF_ON +#define ACC_SENSOR_ON ACC_SENSOR_CONF_ON +#endif /* ACC_SENSOR_CONF_ON */ + +/* Accelerometer g-Select - Define for +/-11g, +/-3g Otherwise */ +#if ACC_SENSOR_ON +#ifdef ACC_SENSOR_CONF_GSEL +#define ACC_SENSOR_GSEL ACC_SENSOR_CONF_GSEL +#endif /* ACC_SENSOR_CONF_GSEL */ +#endif /* ACC_SENSOR_ON */ +#endif /* MODEL_N740 */ + +/* + * Buttons + * N740: P1_0, P0_4 + * N711: P0_6, P0_7 + * N710: Unknown. This will mainly influence which ISRs to declare here + */ +#if defined(MODEL_N740) || defined(MODEL_N711) +#ifdef BUTTON_SENSOR_CONF_ON +#define BUTTON_SENSOR_ON BUTTON_SENSOR_CONF_ON +#endif /* BUTTON_SENSOR_CONF_ON */ +#endif /* defined(MODEL_FOO) */ + +#define BUTTON_1_SENSOR "Button 1" +#define BUTTON_2_SENSOR "Button 2" +#define BUTTON_SENSOR BUTTON_1_SENSOR + +#if BUTTON_SENSOR_ON +extern const struct sensors_sensor button_1_sensor; +extern const struct sensors_sensor button_2_sensor; +#define button_sensor button_1_sensor + +/* Port 0 ISR needed for both models */ +void port_0_ISR(void) __interrupt (P0INT_VECTOR); + +/* Only declare the Port 1 ISR for N740 */ +#ifdef MODEL_N740 +void port_1_ISR(void) __interrupt (P1INT_VECTOR); +#endif /* MODEL_N740 */ +#endif /* BUTTON_SENSOR_ON */ + +/* + * Light - N710, N711, N740 + * N740: P0_0 + * N711: P0_0 + * N710: P?_? + */ +#if defined(MODEL_N740) || defined(MODEL_N711) || defined(MODEL_N710) +#ifdef LIGHT_SENSOR_CONF_ON +#define LIGHT_SENSOR_ON LIGHT_SENSOR_CONF_ON +#endif /* LIGHT_SENSOR_CONF_ON */ +#endif /* defined(MODEL_FOO) */ + +/* + * Battery - N711, N740, (N710 likely) + * N740: P0_1 + * Unknown for other models + */ +#if defined(MODEL_N740) || defined(MODEL_N711) || defined(MODEL_N710) +#ifdef BATTERY_SENSOR_CONF_ON +#define BATTERY_SENSOR_ON BATTERY_SENSOR_CONF_ON +#endif /* BATTERY_SENSOR_CONF_ON */ +#endif /* defined(MODEL_FOO) */ + +/* Temperature - Available on all cc2430 devices */ +#ifdef TEMP_SENSOR_CONF_ON +#define TEMP_SENSOR_ON TEMP_SENSOR_CONF_ON +#endif /* TEMP_SENSOR_CONF_ON */ + +/* Supply Voltage - Available on all cc2430 devices*/ +#ifdef VDD_SENSOR_CONF_ON +#define VDD_SENSOR_ON VDD_SENSOR_CONF_ON +#endif /* VDD_SENSOR_CONF_ON */ + +#endif /* SENSINODE_SENSORS_H_ */ diff --git a/platform/sensinode/dev/slip-arch.c b/platform/sensinode/dev/slip-arch.c new file mode 100644 index 000000000..bf6e1b291 --- /dev/null +++ b/platform/sensinode/dev/slip-arch.c @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2006, Swedish Institute of Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)$Id: slip_uart1.c,v 1.8 2008/02/03 20:59:35 adamdunkels Exp $ + */ + +/* + * Sensinode/cc2430 SLIP routines (over UART1). + */ + +#include "dev/slip.h" +#include "dev/uart1.h" +/*---------------------------------------------------------------------------*/ +void +slip_arch_writeb(unsigned char c) +{ + uart1_writeb(c); +} +/*---------------------------------------------------------------------------*/ +void +slip_arch_init(unsigned long ubr) +{ + uart1_set_input(slip_input_byte); +} +/*---------------------------------------------------------------------------*/ diff --git a/platform/sensinode/disco.c b/platform/sensinode/disco.c new file mode 100644 index 000000000..12c1146cb --- /dev/null +++ b/platform/sensinode/disco.c @@ -0,0 +1,347 @@ +/* + * Copyright (c) 2010, Loughborough University - Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * Disco server sources + * (embedded part of the DISCOBALL project) + * + * It objective is to receive a code file over UDP, store it in + * external flash and disseminate it to other nodes of the + * 6LoWPAN network. + * + * For this to work, the image must be co-hosted with the BooTTY! + * bootloader, which will move the image from external to internal + * flash. + * + * To link this application in your contiki image, all you need to + * do is to add this line: + * OFFSET_FIRMWARE=1 + * to your project's makefile + * + * \author + * George Oikonomou - + */ + +#include "contiki.h" +#include "contiki-net.h" +#include "sys/clock.h" +#include "sys/ctimer.h" +#include "dev/watchdog.h" + +#include "dev/n740.h" +#include "dev/m25p16.h" + +#include "disco.h" +/*---------------------------------------------------------------------------*/ +#define DEBUG DEBUG_NONE +#include "net/uip-debug.h" +/*---------------------------------------------------------------------------*/ +#if BATMON_CONF_ENABLED +void batmon_log(uint8_t trigger); + +#define LOG_TRIGGER_OAP_DISCO_START 0x01 +#define LOG_TRIGGER_OAP_DISCO_DONE 0x02 +#define LOG_TRIGGER_OAP_DISCO_ABORT 0x03 +#else +#define batmon_log(t) do { } while(0); +#endif +/*---------------------------------------------------------------------------*/ +static struct uip_udp_conn *server_conn; +static struct disco_request_pdu * req; +static struct disco_response_pdu resp; +static struct disco_seed seed; +static uint8_t state; +static uint8_t sector; +static uint16_t interval; +static struct ctimer disco_timer; + +#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) +#define UIP_UDP_BUF ((struct uip_udp_hdr *)&uip_buf[uip_l2_l3_hdr_len]) + +extern uint16_t uip_len; +extern void *uip_appdata; + +__xdata __at(BOOTTY_CMD_LOCATION) static uint8_t bd; +/*---------------------------------------------------------------------------*/ +static void timer_handler(void * p); +/*---------------------------------------------------------------------------*/ +static void +abort() +{ + PRINTF("Disco: Abort @ %lu\n", clock_seconds()); + n740_analog_deactivate(); + m25p16_dp(); + n740_analog_activate(); + state = DISCO_STATE_LISTENING; + memset(&seed, 0, sizeof(seed)); + ctimer_stop(&disco_timer); + batmon_log(LOG_TRIGGER_OAP_DISCO_ABORT); +} +/*---------------------------------------------------------------------------*/ +static void +restart_timer(uint16_t t) +{ + interval = t; + ctimer_stop(&disco_timer); + ctimer_set(&disco_timer, interval, timer_handler, &state); +} +/*---------------------------------------------------------------------------*/ +static void +timer_handler(void * p) +{ + uint8_t * s = p; + uint8_t wip; + + PRINTF("Disco: @ %lu, s: %u\n", clock_seconds(), *s); + + if(*s == DISCO_STATE_PREPARING) { + n740_analog_deactivate(); + wip = M25P16_WIP(); + n740_analog_activate(); + + if(wip) { + restart_timer(DISCO_TIMEOUT_PREPARE); + } else { + PRINTF("Disco: Erased %u\n", sector); + if((sector & 1) == 0) { + sector++; + PRINTF("Disco: Next %u\n", sector); + n740_analog_deactivate(); + m25p16_se(sector); + n740_analog_activate(); + restart_timer(DISCO_TIMEOUT_PREPARE); + } else { + PRINTF("Disco: Ready\n"); + *s = DISCO_STATE_READY; + resp.status = DISCO_CMD_INIT; + restart_timer(DISCO_TIMEOUT_ABORT); + server_conn->rport = seed.port; + uip_ipaddr_copy(&server_conn->ripaddr, &seed.addr); + uip_udp_packet_send(server_conn, &resp, DISCO_RESP_LEN_INIT); + + /* Restore server connection to allow data from any node */ + uip_create_unspecified(&server_conn->ripaddr); + server_conn->rport = 0; + } + } + } else if(*s == DISCO_STATE_READY) { + abort(); + } else if(*s == DISCO_STATE_REBOOTING) { + watchdog_reboot(); + } +} +/*---------------------------------------------------------------------------*/ +static uint8_t is_protected(uint8_t a) { + uint8_t bp = M25P16_BP() >> 2; + + if(bp > 5) { + return SECTOR_PROTECTED; + } + + bp -= 1; + + if(a >= (32 - (1 << bp))) { + return SECTOR_PROTECTED; + } + return SECTOR_UNPROTECTED; +} +/*---------------------------------------------------------------------------*/ +static uint8_t +cmd_init() +{ + PRINTF("Disco: Init 0x%02x\n", req->addr[0]); + if(uip_datalen() != DISCO_LEN_INIT) { + PRINTF("Disco: Bad len (%u)\n", uip_datalen()); + resp.status = DISCO_ERR_BAD_LEN; + return DISCO_RESP_LEN_ERR; + } + n740_analog_deactivate(); + m25p16_res(); + sector = 2 * req->addr[0]; + if(is_protected(sector) == SECTOR_PROTECTED + || is_protected(sector + 1) == SECTOR_PROTECTED) { + resp.status = DISCO_ERR_PROTECTED; + n740_analog_activate(); + return DISCO_RESP_LEN_ERR; + } + m25p16_se(sector); + n740_analog_activate(); + state = DISCO_STATE_PREPARING; + restart_timer(DISCO_TIMEOUT_PREPARE); + + /* Store the sender's address/port so we can reply when ready */ + seed.port = UIP_UDP_BUF->srcport; + uip_ipaddr_copy(&seed.addr, &UIP_IP_BUF->srcipaddr); + PRINTF("Disco: OK\n"); + + batmon_log(LOG_TRIGGER_OAP_DISCO_START); + + return DISCO_RESPONSE_NONE; +} +/*---------------------------------------------------------------------------*/ +static uint8_t +cmd_write() +{ + PRINTF("Disco: Write 0x%02x%02x%02x\n", req->addr[0], req->addr[1], req->addr[2]); + if(uip_datalen() != DISCO_LEN_WRITE) { + resp.status = DISCO_ERR_BAD_LEN; + return DISCO_RESP_LEN_ERR; + } + restart_timer(DISCO_TIMEOUT_ABORT); + n740_analog_deactivate(); + m25p16_pp(req->addr, req->data, DISCO_FLEN_DATA); + watchdog_periodic(); + while(M25P16_WIP()); + n740_analog_activate(); + resp.status = DISCO_CMD_WRITE; + memcpy(resp.addr, req->addr, DISCO_FLEN_ADDR); + return DISCO_RESP_LEN_WRITE; +} +/*---------------------------------------------------------------------------*/ +static uint8_t +cmd_switch() +{ + PRINTF("Disco: Switch 0x%02x\n", req->addr[0]); + if(uip_datalen() != DISCO_LEN_SWITCH) { + resp.status = DISCO_ERR_BAD_LEN; + return DISCO_RESP_LEN_ERR; + } + if(req->addr[0] > 15) { + resp.status = DISCO_ERR_BAD_OFFSET; + return DISCO_RESP_LEN_ERR; + } + + bd = BOOTTY_CMD_COPY_IMAGE; + bd |= req->addr[0]; + + resp.status = DISCO_CMD_SWITCH; + resp.addr[0] = req->addr[0]; + + restart_timer(DISCO_TIMEOUT_REBOOT); + state = DISCO_STATE_REBOOTING; + + return DISCO_RESP_LEN_SWITCH; +} +/*---------------------------------------------------------------------------*/ +static uint8_t +cmd_done() +{ + PRINTF("Disco: Done\n"); + if(uip_datalen() != DISCO_LEN_DONE) { + resp.status = DISCO_ERR_BAD_LEN; + return DISCO_RESP_LEN_ERR; + } + resp.status = DISCO_CMD_DONE; + + batmon_log(LOG_TRIGGER_OAP_DISCO_DONE); + + return DISCO_RESP_LEN_DONE; +} +/*---------------------------------------------------------------------------*/ +static uint8_t +event_handler(process_event_t ev) +{ + uint8_t rv = DISCO_RESPONSE_NONE; + + if(ev != tcpip_event) { + return rv; + } + + /* Always accept CMD_DONE */ + if(req->cmd == DISCO_CMD_DONE) { + return cmd_done(); + } + + /* Always accept switch too */ + if(req->cmd == DISCO_CMD_SWITCH) { + return cmd_switch(); + } + + switch(state) { + case DISCO_STATE_LISTENING: + req = uip_appdata; + if(req->cmd == DISCO_CMD_INIT) { + rv = cmd_init(); + } + break; + case DISCO_STATE_PREPARING: + PRINTF("Disco: Not Ready\n"); + resp.status = DISCO_ERR_NOT_READY; + rv = DISCO_RESP_LEN_ERR; + break; + case DISCO_STATE_READY: + req = uip_appdata; + if(req->cmd == DISCO_CMD_WRITE) { + rv = cmd_write(); + } else if(req->cmd == DISCO_CMD_INIT) { + resp.status = DISCO_ERR_INIT_DONE; + rv = DISCO_RESP_LEN_ERR; + } else if(req->cmd == DISCO_CMD_SWITCH) { + rv = cmd_switch(); + } + break; + } + return rv; +} +/*---------------------------------------------------------------------------*/ +PROCESS(disco_process, "Disco Server Process"); +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(disco_process, ev, data) +{ + uint8_t len; + + PROCESS_BEGIN(); + + PRINTF("Disco Server\n"); + + server_conn = udp_new(NULL, UIP_HTONS(0), NULL); + udp_bind(server_conn, UIP_HTONS(DISCO_UDP_PORT)); + + state = DISCO_STATE_LISTENING; + + while(1) { + PROCESS_YIELD(); + len = event_handler(ev); + + if(len > 0) { + server_conn->rport = UIP_UDP_BUF->srcport; + uip_ipaddr_copy(&server_conn->ripaddr, &UIP_IP_BUF->srcipaddr); + uip_udp_packet_send(server_conn, &resp, len); + /* Restore server connection to allow data from any node */ + uip_create_unspecified(&server_conn->ripaddr); + server_conn->rport = 0; + } + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ diff --git a/platform/sensinode/disco.h b/platform/sensinode/disco.h new file mode 100644 index 000000000..81549ab8d --- /dev/null +++ b/platform/sensinode/disco.h @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2010, Loughborough University - Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * Header file for the Disco server + * (embedded part of the DISCOBALL project) + * + * \author + * George Oikonomou - + */ + +#ifndef DISCO_H_ +#define DISCO_H_ + +#include "contiki.h" +#include "contiki-net.h" +/*---------------------------------------------------------------------------*/ +#define DISCO_UDP_PORT 60002 +#define DISCO_DESCRIPTORS_LOC /* In external Flash */ + +#define DATA_CHUNK_LEN 64 + +/* Intervals - Timeouts */ +#define DISCO_TIMEOUT_PREPARE (CLOCK_SECOND / 2) +#define DISCO_TIMEOUT_ABORT (CLOCK_SECOND * 10) +#define DISCO_TIMEOUT_REBOOT CLOCK_SECOND + +/* Disco State Machine */ +#define DISCO_STATE_LISTENING 0x00 /* Waiting for a transaction to start */ +#define DISCO_STATE_PREPARING 0x01 /* Erasing Sectors */ +#define DISCO_STATE_READY 0x02 +#define DISCO_STATE_REBOOTING 0x03 /* Reboot to BooTTY and copy new image */ + +/* Instructions */ +#define DISCO_CMD_INIT 0x00 /* Prepare flash area for writes */ +#define DISCO_CMD_SWITCH 0x01 /* Copy image from ext. to int. flash */ +#define DISCO_CMD_WRITE 0x02 /* Write Image to Ext Flash */ +#define DISCO_CMD_DONE 0x03 /* All Done */ + +/* Error Codes */ +#define DISCO_ERR_GENERIC 0xFF /* Generic Error */ +#define DISCO_ERR_BAD_LEN 0xFE /* Incorrect Length */ +#define DISCO_ERR_NOT_READY 0xFD /* Not Initialised */ +#define DISCO_ERR_BAD_OFFSET 0xFC /* Bad Offset */ +#define DISCO_ERR_PROTECTED 0xFB /* Target sector is protected */ +#define DISCO_ERR_INIT_DONE 0xFA /* Already Initialized */ + +/* Message Sizes */ +#define DISCO_FLEN_CMD 1 +#define DISCO_FLEN_IMG 1 +#define DISCO_FLEN_ADDR 3 +#define DISCO_FLEN_DATA 64 + +/* Request Lengths */ +#define DISCO_LEN_INIT (DISCO_FLEN_CMD + DISCO_FLEN_IMG) +#define DISCO_LEN_DONE DISCO_FLEN_CMD +#define DISCO_LEN_WRITE (DISCO_FLEN_CMD + DISCO_FLEN_ADDR + DISCO_FLEN_DATA) +#define DISCO_LEN_SWITCH (DISCO_FLEN_CMD + DISCO_FLEN_IMG) + +/* Response Lengths */ +#define DISCO_RESPONSE_NONE 0 +#define DISCO_RESP_LEN_ERR DISCO_FLEN_CMD +#define DISCO_RESP_LEN_INIT DISCO_FLEN_CMD +#define DISCO_RESP_LEN_DONE DISCO_FLEN_CMD +#define DISCO_RESP_LEN_WRITE (DISCO_FLEN_CMD + DISCO_FLEN_ADDR) +#define DISCO_RESP_LEN_SWITCH (DISCO_FLEN_CMD + DISCO_FLEN_IMG) + +/* Tell BooTTy! what to do after we jump: + * BOOTY_CMD + * [7:5]: Command + * [5:4]: Reserved + * [4:0]: Image number + */ +#define BOOTTY_CMD_LOCATION 0xFEFF + +#define BOOTTY_CMD_JUMP_TO_APP 0x80 +#define BOOTTY_CMD_COPY_IMAGE 0x40 + +#define SECTOR_UNPROTECTED 0 +#define SECTOR_PROTECTED 1 +/*---------------------------------------------------------------------------*/ +PROCESS_NAME(disco_process); +/*---------------------------------------------------------------------------*/ +struct disco_request_pdu { + uint8_t cmd; + uint8_t addr[3]; + uint8_t data[DATA_CHUNK_LEN]; +}; + +struct disco_response_pdu { + uint8_t status; + uint8_t addr[3]; +}; + +struct disco_seed { + uip_ipaddr_t addr; + uint16_t port; +}; +/*---------------------------------------------------------------------------*/ +#endif /* DISCO_H_ */ diff --git a/platform/sensinode/putchar.c b/platform/sensinode/putchar.c new file mode 100644 index 000000000..8d19ef4d3 --- /dev/null +++ b/platform/sensinode/putchar.c @@ -0,0 +1,39 @@ +/** + * \file + * hardware-specific putchar() routine for sensinode motes + * + * \author + * George Oikonomou - + */ + +#include "contiki-conf.h" +#include "dev/uart1.h" + +/*---------------------------------------------------------------------------*/ +void +putchar(char c) +{ +#if SLIP_ARCH_CONF_ENABLE +#define SLIP_END 0300 + static char debug_frame = 0; + + if(!debug_frame) { /* Start of debug output */ + uart1_writeb(SLIP_END); + uart1_writeb('\r'); /* Type debug line == '\r' */ + debug_frame = 1; + } +#endif + + uart1_writeb((char)c); + +#if SLIP_ARCH_CONF_ENABLE + /* + * Line buffered output, a newline marks the end of debug output and + * implicitly flushes debug output. + */ + if(c == '\n') { + uart1_writeb(SLIP_END); + debug_frame = 0; + } +#endif +} diff --git a/platform/sensinode/segment.rules b/platform/sensinode/segment.rules new file mode 100644 index 000000000..0dc7a4a60 --- /dev/null +++ b/platform/sensinode/segment.rules @@ -0,0 +1,13 @@ +# segment.rules - platform/sensinode + +# segment.rules file for code in platform/sensinode +# Please see cpu/cc2430/segment.rules for more info on code segments +# and for rules of thumb on what to do and what not to do + +# Keep main() in HOME +HOME contiki-sensinode-main.c + +# Files with ISRs must be in HOME +HOME platform/sensinode/dev/button-sensor.c + +# segment.rules - platform/sensinode - end diff --git a/platform/sensinode/sensinode-debug.c b/platform/sensinode/sensinode-debug.c new file mode 100644 index 000000000..031e0ccb5 --- /dev/null +++ b/platform/sensinode/sensinode-debug.c @@ -0,0 +1,46 @@ +/** + * \file + * + * Definition of some debugging functions for the sensinode port. + * + * This file is bankable. + * + * putstring() and puthex() are from msp430/watchdog.c + * + * \author + * George Oikonomou - + */ + +#include "cc2430_sfr.h" +#include "8051def.h" +#include "sensinode-debug.h" + +static const char hexconv[] = "0123456789abcdef"; +static const char binconv[] = "01"; + +/*---------------------------------------------------------------------------*/ +void +putstring(char *s) +{ + while(*s) { + putchar(*s++); + } +} +/*---------------------------------------------------------------------------*/ +void +puthex(uint8_t c) +{ + putchar(hexconv[c >> 4]); + putchar(hexconv[c & 0x0f]); +} +/*---------------------------------------------------------------------------*/ +void +putbin(uint8_t c) +{ + unsigned char i = 0x80; + while(i) { + putchar(binconv[(c & i) != 0]); + i >>= 1; + } +} +/*---------------------------------------------------------------------------*/ diff --git a/platform/sensinode/sensinode-debug.h b/platform/sensinode/sensinode-debug.h new file mode 100644 index 000000000..683f1ba44 --- /dev/null +++ b/platform/sensinode/sensinode-debug.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2005, Swedish Institute of Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + */ + +/** + * \file + * Header file for debugging functions used by the sensinode port. + * + * putstring() and puthex() are from msp430/watchdog.c + * + * \author + * George Oikonomou - + */ + +#ifndef SENSINODE_DEBUG_H_ +#define SENSINODE_DEBUG_H_ + +#include "8051def.h" +#include "dev/uart1.h" + +void putchar(char c); +void putstring(char *s); +void puthex(uint8_t c); +void putbin(uint8_t c); + +#endif /* SENSINODE_DEBUG_H_ */ diff --git a/platform/sensinode/viztool.c b/platform/sensinode/viztool.c new file mode 100644 index 000000000..777ffc855 --- /dev/null +++ b/platform/sensinode/viztool.c @@ -0,0 +1,298 @@ +/* + * Copyright (c) 2010, Loughborough University - Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * Small UDP app used to retrieve neighbor cache and routing table + * entries and send them to an external endpoint + * + * \author + * George Oikonomou - + */ + +#include "contiki.h" +#include "contiki-lib.h" +#include "contiki-net.h" + +#include + +#define DEBUG DEBUG_NONE +#include "net/uip-debug.h" + +#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) +#define UIP_UDP_BUF ((struct uip_udp_hdr *)&uip_buf[uip_l2_l3_hdr_len]) + +#ifndef VIZTOOL_MAX_PAYLOAD_LEN +#define VIZTOOL_MAX_PAYLOAD_LEN 60 +#endif + +static struct uip_udp_conn *server_conn; +static unsigned char buf[VIZTOOL_MAX_PAYLOAD_LEN]; +static int8_t len; + +#define VIZTOOL_UDP_PORT 60001 + +/* Request Bits */ +#define REQUEST_TYPE_ND 1 +#define REQUEST_TYPE_RT 2 +#define REQUEST_TYPE_DRT 3 +#define REQUEST_TYPE_ADDR 4 +#define REQUEST_TYPE_TOTALS 0xFF + +extern uip_ds6_netif_t uip_ds6_if; +extern uip_ds6_route_t uip_ds6_routing_table[UIP_DS6_ROUTE_NB]; +extern uip_ds6_nbr_t uip_ds6_nbr_cache[UIP_DS6_NBR_NB]; +extern uip_ds6_defrt_t uip_ds6_defrt_list[UIP_DS6_DEFRT_NB]; +extern u16_t uip_len; +/*---------------------------------------------------------------------------*/ +static uint8_t +process_request() +{ + uint8_t len; + uint8_t count; /* How many did we pack? */ + uint8_t i; + uint8_t left; + uint8_t entry_size; + + left = VIZTOOL_MAX_PAYLOAD_LEN - 1; + len = 2; /* start filling the buffer from position [2] */ + count = 0; + if(buf[0] == REQUEST_TYPE_ND) { + /* Neighbors */ + PRINTF("Neighbors\n"); + for(i = buf[1]; i < UIP_DS6_NBR_NB; i++) { + if(uip_ds6_nbr_cache[i].isused) { + entry_size = sizeof(i) + sizeof(uip_ipaddr_t) + sizeof(uip_lladdr_t) + + sizeof(uip_ds6_nbr_cache[i].state); + PRINTF("%02u: ", i); + PRINT6ADDR(&uip_ds6_nbr_cache[i].ipaddr); + PRINTF(" - "); + PRINTLLADDR(&uip_ds6_nbr_cache[i].lladdr); + PRINTF(" - %u\n", uip_ds6_nbr_cache[i].state); + + memcpy(buf + len, &i, sizeof(i)); + len += sizeof(i); + memcpy(buf + len, &uip_ds6_nbr_cache[i].ipaddr, sizeof(uip_ipaddr_t)); + len += sizeof(uip_ipaddr_t); + memcpy(buf + len, &uip_ds6_nbr_cache[i].lladdr, sizeof(uip_lladdr_t)); + len += sizeof(uip_lladdr_t); + memcpy(buf + len, &uip_ds6_nbr_cache[i].state, + sizeof(uip_ds6_nbr_cache[i].state)); + len += sizeof(uip_ds6_nbr_cache[i].state); + + count++; + left -= entry_size; + + if(left < entry_size) { + break; + } + } + } + } else if(buf[0] == REQUEST_TYPE_RT) { + uint32_t flip = 0; + PRINTF("Routing table\n"); + for(i = buf[1]; i < UIP_DS6_ROUTE_NB; i++) { + if(uip_ds6_routing_table[i].isused) { + entry_size = sizeof(i) + sizeof(uip_ds6_routing_table[i].ipaddr) + + sizeof(uip_ds6_routing_table[i].length) + + sizeof(uip_ds6_routing_table[i].metric) + + sizeof(uip_ds6_routing_table[i].nexthop) + + sizeof(uip_ds6_routing_table[i].state.lifetime) + + sizeof(uip_ds6_routing_table[i].state.learned_from); + + memcpy(buf + len, &i, sizeof(i)); + len += sizeof(i); + memcpy(buf + len, &uip_ds6_routing_table[i].ipaddr, + sizeof(uip_ds6_routing_table[i].ipaddr)); + len += sizeof(uip_ds6_routing_table[i].ipaddr); + memcpy(buf + len, &uip_ds6_routing_table[i].length, + sizeof(uip_ds6_routing_table[i].length)); + len += sizeof(uip_ds6_routing_table[i].length); + memcpy(buf + len, &uip_ds6_routing_table[i].metric, + sizeof(uip_ds6_routing_table[i].metric)); + len += sizeof(uip_ds6_routing_table[i].metric); + memcpy(buf + len, &uip_ds6_routing_table[i].nexthop, + sizeof(uip_ds6_routing_table[i].nexthop)); + len += sizeof(uip_ds6_routing_table[i].nexthop); + + PRINT6ADDR(&uip_ds6_routing_table[i].ipaddr); + PRINTF(" - %02x", uip_ds6_routing_table[i].length); + PRINTF(" - %02x", uip_ds6_routing_table[i].metric); + PRINTF(" - "); + PRINT6ADDR(&uip_ds6_routing_table[i].nexthop); + + flip = uip_htonl(uip_ds6_routing_table[i].state.lifetime); + memcpy(buf + len, &flip, sizeof(flip)); + len += sizeof(flip); + PRINTF(" - %08lx", uip_ds6_routing_table[i].state.lifetime); + + memcpy(buf + len, &uip_ds6_routing_table[i].state.learned_from, + sizeof(uip_ds6_routing_table[i].state.learned_from)); + len += sizeof(uip_ds6_routing_table[i].state.learned_from); + + PRINTF(" - %02x [%u]\n", uip_ds6_routing_table[i].state.learned_from, + entry_size); + + count++; + left -= entry_size; + + if(left < entry_size) { + break; + } + } + } + } else if (buf[0] == REQUEST_TYPE_DRT) { + uint32_t flip = 0; + PRINTF("Default Routes\n"); + for(i = buf[1]; i < UIP_DS6_DEFRT_NB; i++) { + if(uip_ds6_defrt_list[i].isused) { + entry_size = sizeof(i) + sizeof(uip_ds6_defrt_list[i].ipaddr) + + sizeof(uip_ds6_defrt_list[i].isinfinite); + + memcpy(buf + len, &i, sizeof(i)); + len += sizeof(i); + memcpy(buf + len, &uip_ds6_defrt_list[i].ipaddr, + sizeof(uip_ds6_defrt_list[i].ipaddr)); + len += sizeof(uip_ds6_defrt_list[i].ipaddr); + memcpy(buf + len, &uip_ds6_defrt_list[i].isinfinite, + sizeof(uip_ds6_defrt_list[i].isinfinite)); + len += sizeof(uip_ds6_defrt_list[i].isinfinite); + + PRINT6ADDR(&uip_ds6_defrt_list[i].ipaddr); + PRINTF(" - %u\n", uip_ds6_defrt_list[i].isinfinite); + count++; + left -= entry_size; + + if(left < entry_size) { + break; + } + } + } + } else if (buf[0] == REQUEST_TYPE_ADDR) { + PRINTF("Unicast Addresses\n"); + for(i = buf[1]; i < UIP_DS6_ADDR_NB; i++) { + if(uip_ds6_if.addr_list[i].isused) { + entry_size = sizeof(i) + sizeof(uip_ds6_if.addr_list[i].ipaddr); + + memcpy(buf + len, &i, sizeof(i)); + len += sizeof(i); + memcpy(buf + len, &uip_ds6_if.addr_list[i].ipaddr, + sizeof(uip_ds6_if.addr_list[i].ipaddr)); + len += sizeof(uip_ds6_if.addr_list[i].ipaddr); + + PRINT6ADDR(&uip_ds6_if.addr_list[i].ipaddr); + PRINTF("\n"); + count++; + left -= entry_size; + + if(left < entry_size) { + break; + } + } + } + } else if (buf[0] == REQUEST_TYPE_TOTALS) { + memset(&buf[2], 0, 4); + for(i = 0; i < UIP_DS6_ADDR_NB; i++) { + if(uip_ds6_if.addr_list[i].isused) { + buf[2]++; + } + } + for(i = 0; i < UIP_DS6_NBR_NB; i++) { + if(uip_ds6_nbr_cache[i].isused) { + buf[3]++; + } + } + for(i = 0; i < UIP_DS6_ROUTE_NB; i++) { + if(uip_ds6_routing_table[i].isused) { + buf[4]++; + } + } + for(i = 0; i < UIP_DS6_DEFRT_NB; i++) { + if(uip_ds6_defrt_list[i].isused) { + buf[5]++; + } + } + len += 4; + count = 4; + } else { + return 0; + } + buf[1] = count; + return len; +} +/*---------------------------------------------------------------------------*/ +PROCESS(viztool_process, "Network Visualization Tool Process"); +/*---------------------------------------------------------------------------*/ +static void +tcpip_handler(void) +{ + if(uip_newdata()) { + memset(buf, 0, VIZTOOL_MAX_PAYLOAD_LEN); + + PRINTF("%u bytes from [", uip_datalen()); + PRINT6ADDR(&UIP_IP_BUF->srcipaddr); + PRINTF("]:%u\n", UIP_HTONS(UIP_UDP_BUF->srcport)); + + memcpy(buf, uip_appdata, uip_datalen()); + + len = process_request(); + if(len) { + server_conn->rport = UIP_UDP_BUF->srcport; + uip_ipaddr_copy(&server_conn->ripaddr, &UIP_IP_BUF->srcipaddr); + uip_udp_packet_send(server_conn, buf, len); + PRINTF("Sent %u bytes\n", len); + } + + /* Restore server connection to allow data from any node */ + uip_create_unspecified(&server_conn->ripaddr); + server_conn->rport = 0; + } + return; +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(viztool_process, ev, data) +{ + + PROCESS_BEGIN(); + + server_conn = udp_new(NULL, UIP_HTONS(0), NULL); + udp_bind(server_conn, UIP_HTONS(VIZTOOL_UDP_PORT)); + + while(1) { + PROCESS_YIELD(); + if(ev == tcpip_event) { + tcpip_handler(); + } + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ diff --git a/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/ESBMote.java b/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/ESBMote.java index c3e5475e5..8c4fb6608 100644 --- a/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/ESBMote.java +++ b/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/ESBMote.java @@ -32,10 +32,10 @@ package se.sics.cooja.mspmote; import java.io.File; + import org.apache.log4j.Logger; -import se.sics.cooja.MoteInterfaceHandler; + import se.sics.cooja.Simulation; -import se.sics.cooja.interfaces.*; import se.sics.mspsim.platform.esb.ESBNode; /** diff --git a/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/MspMote.java b/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/MspMote.java index d2d2e154f..ecc77fafa 100644 --- a/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/MspMote.java +++ b/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/MspMote.java @@ -31,12 +31,13 @@ package se.sics.cooja.mspmote; -import java.awt.event.ActionListener; import java.io.File; import java.io.IOException; import java.io.PrintStream; import java.util.ArrayList; import java.util.Collection; +import java.util.Enumeration; +import java.util.Hashtable; import java.util.Observable; import org.apache.log4j.Logger; @@ -56,14 +57,12 @@ import se.sics.cooja.interfaces.IPAddress; import se.sics.cooja.motes.AbstractEmulatedMote; import se.sics.cooja.mspmote.interfaces.MspSerial; import se.sics.cooja.mspmote.plugins.CodeVisualizerSkin; -import se.sics.cooja.mspmote.plugins.MspBreakpointContainer; -import se.sics.cooja.plugins.BufferListener.BufferAccess; +import se.sics.cooja.mspmote.plugins.MspBreakpoint; import se.sics.cooja.plugins.Visualizer; import se.sics.mspsim.cli.CommandContext; import se.sics.mspsim.cli.CommandHandler; import se.sics.mspsim.cli.LineListener; import se.sics.mspsim.cli.LineOutputStream; -import se.sics.mspsim.core.CPUMonitor; import se.sics.mspsim.core.EmulationException; import se.sics.mspsim.core.MSP430; import se.sics.mspsim.core.MSP430Constants; @@ -95,7 +94,7 @@ public abstract class MspMote extends AbstractEmulatedMote implements Mote, Watc private MspMoteMemory myMemory = null; private MoteInterfaceHandler myMoteInterfaceHandler = null; public ComponentRegistry registry = null; - + /* Stack monitoring variables */ private boolean stopNextInstruction = false; private boolean monitorStackUsage = false; @@ -103,15 +102,11 @@ public abstract class MspMote extends AbstractEmulatedMote implements Mote, Watc private int heapStartAddress; private StackOverflowObservable stackOverflowObservable = new StackOverflowObservable(); - private MspBreakpointContainer breakpointsContainer; - public MspMote() { myMoteType = null; myCpu = null; myMemory = null; myMoteInterfaceHandler = null; - - /* Scheduled from setConfigXML */ } public MspMote(MspMoteType moteType, Simulation simulation) { @@ -121,7 +116,7 @@ public abstract class MspMote extends AbstractEmulatedMote implements Mote, Watc /* Schedule us immediately */ requestImmediateWakeup(); } - + protected void initMote() { if (myMoteType != null) { initEmulator(myMoteType.getContikiFirmwareFile()); @@ -130,9 +125,8 @@ public abstract class MspMote extends AbstractEmulatedMote implements Mote, Watc /* TODO Setup COOJA-specific window manager */ registry.registerComponent("windowManager", new JFrameWindowManager()); - /* Create watchpoint container */ try { - breakpointsContainer = new MspBreakpointContainer(this, ((MspMoteType)getType()).getFirmwareDebugInfo()); + debuggingInfo = ((MspMoteType)getType()).getFirmwareDebugInfo(); } catch (IOException e) { throw (RuntimeException) new RuntimeException("Error: " + e.getMessage()).initCause(e); } @@ -300,10 +294,9 @@ public abstract class MspMote extends AbstractEmulatedMote implements Mote, Watc if (stopNextInstruction) { stopNextInstruction = false; - /*sendCLICommandAndPrint("trace 1000");*/ /* TODO Enable */ scheduleNextWakeup(t); throw new RuntimeException("MSPSim requested simulation stop"); - } + } if (lastExecute < 0) { /* Always execute one microsecond the first time */ @@ -312,12 +305,12 @@ public abstract class MspMote extends AbstractEmulatedMote implements Mote, Watc if (t < lastExecute) { throw new RuntimeException("Bad event ordering: " + lastExecute + " < " + t); } - + /* Execute MSPSim-based mote */ /* TODO Try-catch overhead */ try { - nextExecute = - t + duration + + nextExecute = + t + duration + myCpu.stepMicros(t - lastExecute, duration); lastExecute = t; } catch (EmulationException e) { @@ -332,8 +325,12 @@ public abstract class MspMote extends AbstractEmulatedMote implements Mote, Watc } /*logger.debug(t + ": Schedule next wakeup at " + nextExecute);*/ scheduleNextWakeup(nextExecute); - - + + if (stopNextInstruction) { + stopNextInstruction = false; + throw new RuntimeException("MSPSim requested simulation stop"); + } + /* XXX TODO Reimplement stack monitoring using MSPSim internals */ /*if (monitorStackUsage) { int newStack = cpu.reg[MSP430.SP]; @@ -349,7 +346,7 @@ public abstract class MspMote extends AbstractEmulatedMote implements Mote, Watc } }*/ } - + public String getStackTrace() { return executeCLICommand("stacktrace"); } @@ -357,7 +354,7 @@ public abstract class MspMote extends AbstractEmulatedMote implements Mote, Watc public int executeCLICommand(String cmd, CommandContext context) { return commandHandler.executeCommand(cmd, context); } - + public String executeCLICommand(String cmd) { final StringBuilder sb = new StringBuilder(); LineListener ll = new LineListener() { @@ -369,14 +366,14 @@ public abstract class MspMote extends AbstractEmulatedMote implements Mote, Watc CommandContext c = new CommandContext(commandHandler, null, "", new String[0], 1, null); c.out = po; c.err = po; - + if (0 != executeCLICommand(cmd, c)) { sb.append("\nWarning: command failed"); } - + return sb.toString(); } - + public int getCPUFrequency() { return myCpu.getDCOFrequency(); } @@ -384,16 +381,15 @@ public abstract class MspMote extends AbstractEmulatedMote implements Mote, Watc public int getID() { return getInterfaces().getMoteID().getMoteID(); } - + public boolean setConfigXML(Simulation simulation, Collection configXML, boolean visAvailable) { setSimulation(simulation); if (myMoteInterfaceHandler == null) { myMoteInterfaceHandler = createMoteInterfaceHandler(); } - /* Create watchpoint container */ try { - breakpointsContainer = new MspBreakpointContainer(this, ((MspMoteType)getType()).getFirmwareDebugInfo()); + debuggingInfo = ((MspMoteType)getType()).getFirmwareDebugInfo(); } catch (IOException e) { throw (RuntimeException) new RuntimeException("Error: " + e.getMessage()).initCause(e); } @@ -404,7 +400,7 @@ public abstract class MspMote extends AbstractEmulatedMote implements Mote, Watc if (name.equals("motetype_identifier")) { /* Ignored: handled by simulation */ } else if ("breakpoints".equals(element.getName())) { - breakpointsContainer.setConfigXML(element.getChildren(), visAvailable); + setWatchpointConfigXML(element.getChildren(), visAvailable); } else if (name.equals("interface_config")) { String intfClass = element.getText().trim(); if (intfClass.equals("se.sics.cooja.mspmote.interfaces.MspIPAddress")) { @@ -440,7 +436,7 @@ public abstract class MspMote extends AbstractEmulatedMote implements Mote, Watc /* Breakpoints */ element = new Element("breakpoints"); - element.addContent(breakpointsContainer.getConfigXML()); + element.addContent(getWatchpointConfigXML()); config.add(element); // Mote interfaces @@ -458,41 +454,15 @@ public abstract class MspMote extends AbstractEmulatedMote implements Mote, Watc return config; } - - /* Watchpoints: Forward to breakpoint container */ - public void addWatchpointListener(ActionListener listener) { - breakpointsContainer.addWatchpointListener(listener); - } - - public Watchpoint getLastWatchpoint() { - return breakpointsContainer.getLastWatchpoint(); - } - - public Mote getMote() { - return breakpointsContainer.getMote(); - } - - public ActionListener[] getWatchpointListeners() { - return breakpointsContainer.getWatchpointListeners(); - } - - public void removeWatchpointListener(ActionListener listener) { - breakpointsContainer.removeWatchpointListener(listener); - } - - public MspBreakpointContainer getBreakpointsContainer() { - return breakpointsContainer; - } - public String getExecutionDetails() { return executeCLICommand("stacktrace"); } public String getPCString() { int pc = myCpu.getPC(); - ELF elf = (ELF)myCpu.getRegistry().getComponent(ELF.class); + ELF elf = myCpu.getRegistry().getComponent(ELF.class); DebugInfo di = elf.getDebugInfo(pc); - + /* Following code examples from MSPsim, DebugCommands.java */ if (di == null) { di = elf.getDebugInfo(pc + 1); @@ -510,7 +480,7 @@ public abstract class MspMote extends AbstractEmulatedMote implements Mote, Watc } } String name = mapEntry.getName(); - return file + ":?:" + name; + return file + ":?:" + name; } return String.format("*%02x", myCpu.reg[MSP430Constants.PC]); } catch (Exception e) { @@ -525,7 +495,7 @@ public abstract class MspMote extends AbstractEmulatedMote implements Mote, Watc /* strip path */ file = file.substring(file.lastIndexOf('/')+1, file.length()); } - + String function = di.getFunction(); function = function==null?"":function; if (function.contains(":")) { @@ -536,7 +506,147 @@ public abstract class MspMote extends AbstractEmulatedMote implements Mote, Watc function = "?"; } return file + ":" + lineNo + ":" + function; - + /*return executeCLICommand("line " + myCpu.getPC());*/ } + + + /* WatchpointMote */ + private ArrayList watchpointListeners = new ArrayList(); + private ArrayList watchpoints = new ArrayList(); + private Hashtable> debuggingInfo = null; + + public void addWatchpointListener(WatchpointListener listener) { + watchpointListeners.add(listener); + } + public void removeWatchpointListener(WatchpointListener listener) { + watchpointListeners.remove(listener); + } + public WatchpointListener[] getWatchpointListeners() { + return watchpointListeners.toArray(new WatchpointListener[0]); + } + + public Watchpoint addBreakpoint(File codeFile, int lineNr, int address) { + MspBreakpoint bp = new MspBreakpoint(this, address, codeFile, new Integer(lineNr)); + watchpoints.add(bp); + + for (WatchpointListener listener: watchpointListeners) { + listener.watchpointsChanged(); + } + return bp; + } + public void removeBreakpoint(Watchpoint watchpoint) { + ((MspBreakpoint)watchpoint).unregisterBreakpoint(); + watchpoints.remove(watchpoint); + + for (WatchpointListener listener: watchpointListeners) { + listener.watchpointsChanged(); + } + } + public Watchpoint[] getBreakpoints() { + return watchpoints.toArray(new Watchpoint[0]); + } + + public boolean breakpointExists(int address) { + if (address < 0) { + return false; + } + for (Watchpoint watchpoint: watchpoints) { + if (watchpoint.getExecutableAddress() == address) { + return true; + } + } + return false; + } + public boolean breakpointExists(File file, int lineNr) { + for (Watchpoint watchpoint: watchpoints) { + if (watchpoint.getCodeFile() == null) { + continue; + } + if (watchpoint.getCodeFile().compareTo(file) != 0) { + continue; + } + if (watchpoint.getLineNumber() != lineNr) { + continue; + } + return true; + } + return false; + } + + public Integer getExecutableAddressOf(File file, int lineNr) { + if (file == null || lineNr < 0 || debuggingInfo == null) { + return null; + } + + /* Match file */ + Hashtable lineTable = debuggingInfo.get(file); + if (lineTable == null) { + Enumeration fileEnum = debuggingInfo.keys(); + while (fileEnum.hasMoreElements()) { + File f = fileEnum.nextElement(); + if (f != null && f.getName().equals(file.getName())) { + lineTable = debuggingInfo.get(f); + break; + } + } + } + if (lineTable == null) { + return null; + } + + /* Match line number */ + Integer address = lineTable.get(lineNr); + if (address != null) { + Enumeration lineEnum = lineTable.keys(); + while (lineEnum.hasMoreElements()) { + Integer l = lineEnum.nextElement(); + if (l != null && l.intValue() == lineNr) { + /* Found line address */ + return lineTable.get(l); + } + } + } + + return null; + } + + public void signalBreakpointTrigger(MspBreakpoint b) { + if (b.stopsSimulation() && getSimulation().isRunning()) { + /* Stop simulation immediately */ + stopNextInstruction(); + } + + /* Notify listeners */ + WatchpointListener[] listeners = getWatchpointListeners(); + for (WatchpointListener listener: listeners) { + listener.watchpointTriggered(b); + } + } + + public Collection getWatchpointConfigXML() { + ArrayList config = new ArrayList(); + Element element; + + for (MspBreakpoint breakpoint: watchpoints) { + element = new Element("breakpoint"); + element.addContent(breakpoint.getConfigXML()); + config.add(element); + } + + return config; + } + public boolean setWatchpointConfigXML(Collection configXML, boolean visAvailable) { + for (Element element : configXML) { + if (element.getName().equals("breakpoint")) { + MspBreakpoint breakpoint = new MspBreakpoint(this); + if (!breakpoint.setConfigXML(element.getChildren(), visAvailable)) { + logger.warn("Could not restore breakpoint: " + breakpoint); + } else { + watchpoints.add(breakpoint); + } + } + } + return true; + } } diff --git a/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/plugins/BreakpointsUI.java b/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/plugins/BreakpointsUI.java index 7a9d0bdb9..ede9fc111 100644 --- a/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/plugins/BreakpointsUI.java +++ b/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/plugins/BreakpointsUI.java @@ -31,26 +31,32 @@ package se.sics.cooja.mspmote.plugins; -import java.awt.*; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.io.File; -import java.util.ArrayList; -import javax.swing.*; +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.JColorChooser; +import javax.swing.JMenuItem; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JPopupMenu; +import javax.swing.JSeparator; +import javax.swing.JTable; +import javax.swing.SwingUtilities; import javax.swing.table.AbstractTableModel; import javax.swing.table.DefaultTableCellRenderer; -import javax.swing.table.TableCellEditor; import org.apache.log4j.Logger; import se.sics.cooja.GUI; -import se.sics.cooja.Mote; -import se.sics.cooja.MoteType; -import se.sics.cooja.Simulation; -import se.sics.cooja.mspmote.MspMote; +import se.sics.cooja.Watchpoint; +import se.sics.cooja.WatchpointMote; /** * Displays a set of breakpoints. @@ -60,27 +66,27 @@ import se.sics.cooja.mspmote.MspMote; public class BreakpointsUI extends JPanel { private static Logger logger = Logger.getLogger(BreakpointsUI.class); - private static final int COLUMN_INFO = 0; - private static final int COLUMN_ADDRESS = 1; - private static final int COLUMN_FILELINE = 2; + private static final int COLUMN_ADDRESS = 0; + private static final int COLUMN_FILELINE = 1; + private static final int COLUMN_INFO = 2; private static final int COLUMN_STOP = 3; - private static final int COLUMN_REMOVE = 4; private static final String[] COLUMN_NAMES = { - "Info", "Address", - "File", - "Stop", - "Remove" + "Source", + "Info", + "Stops simulation" }; - private MspBreakpointContainer breakpoints = null; + private WatchpointMote mote; + private MspCodeWatcher codeWatcher; private JTable table = null; - private MspBreakpoint popupBreakpoint = null; + private Watchpoint selectedWatchpoint = null; - public BreakpointsUI(MspBreakpointContainer breakpoints, final MspCodeWatcher codeWatcher) { - this.breakpoints = breakpoints; + public BreakpointsUI(WatchpointMote mote, final MspCodeWatcher codeWatcher) { + this.mote = mote; + this.codeWatcher = codeWatcher; /* Breakpoints table */ table = new JTable(tableModel) { @@ -93,15 +99,20 @@ public class BreakpointsUI extends JPanel { int realColumnIndex = table.convertColumnIndexToModel(colIndex); if (realColumnIndex == COLUMN_FILELINE) { - MspBreakpoint[] allBreakpoints = BreakpointsUI.this.breakpoints.getBreakpoints(); + Watchpoint[] allBreakpoints = BreakpointsUI.this.mote.getBreakpoints(); if (rowIndex < 0 || rowIndex >= allBreakpoints.length) { return null; } - File file = allBreakpoints[rowIndex].getCodeFile(); + Watchpoint watchpoint = allBreakpoints[rowIndex]; + File file = watchpoint.getCodeFile(); if (file == null) { - return null; + return String.format("[unknown @ 0x%04x]", watchpoint.getExecutableAddress()); } - return file.getPath() + ":" + allBreakpoints[rowIndex].getLineNumber(); + Integer line = watchpoint.getLineNumber(); + if (line == null) { + return file.getPath() + ":?"; + } + return file.getPath() + ":" + line; } if (realColumnIndex == COLUMN_INFO) { @@ -111,53 +122,41 @@ public class BreakpointsUI extends JPanel { if (realColumnIndex == COLUMN_STOP) { return "Indicates whether the watchpoint will stop the simulation when triggered"; } - - if (realColumnIndex == COLUMN_REMOVE) { - return "Remove breakpoint from this mote only. (Right-click for more options)"; - } return null; } }; - table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); - table.getColumnModel().getColumn(COLUMN_ADDRESS).setPreferredWidth(60); /* XXX */ - table.getColumnModel().getColumn(COLUMN_ADDRESS).setMaxWidth(60); - table.getColumnModel().getColumn(COLUMN_INFO).setPreferredWidth(60); - table.getColumnModel().getColumn(COLUMN_INFO).setMaxWidth(60); - table.getColumnModel().getColumn(COLUMN_INFO).setCellRenderer( - new DefaultTableCellRenderer() { - public Component getTableCellRendererComponent(JTable table, Object value, - boolean isSelected, boolean hasFocus, int row, int column) { - Component c = super.getTableCellRendererComponent( - table, value, isSelected, hasFocus, row, column); - if (column != COLUMN_INFO) { - return c; - } - - MspBreakpoint[] allBreakpoints = BreakpointsUI.this.breakpoints.getBreakpoints(); - if (row < 0 || row >= allBreakpoints.length) { - return c; - } - MspBreakpoint breakpoint = allBreakpoints[row]; - if (breakpoint.getColor() == null) { - return c; - } - - /* Use watchpoint color */ - c.setForeground(breakpoint.getColor()); - return c; - } - }); - table.getColumnModel().getColumn(COLUMN_STOP).setPreferredWidth(60); - table.getColumnModel().getColumn(COLUMN_STOP).setMaxWidth(60); - table.getColumnModel().getColumn(COLUMN_REMOVE).setPreferredWidth(60); - table.getColumnModel().getColumn(COLUMN_REMOVE).setMaxWidth(60); + table.getColumnModel().getColumn(COLUMN_INFO).setCellRenderer(new DefaultTableCellRenderer() { + public Component getTableCellRendererComponent(JTable table, Object value, + boolean isSelected, boolean hasFocus, int row, int column) { + Component c = super.getTableCellRendererComponent( + table, value, isSelected, hasFocus, row, column); + if (column != COLUMN_INFO) { + return c; + } + + Watchpoint[] allBreakpoints = BreakpointsUI.this.mote.getBreakpoints(); + if (row < 0 || row >= allBreakpoints.length) { + return c; + } + Watchpoint breakpoint = allBreakpoints[row]; + if (breakpoint.getColor() == null) { + return c; + } + + /* Use watchpoint color */ + c.setBackground(Color.WHITE); + c.setForeground(breakpoint.getColor()); + return c; + } + }); /* Popup menu: register on all motes */ final JPopupMenu popupMenu = new JPopupMenu(); - popupMenu.add(new JMenuItem(addToMoteTypeAction)); - popupMenu.add(new JMenuItem(delFromMoteTypeAction)); + popupMenu.add(new JMenuItem(gotoCodeAction)); + popupMenu.add(new JSeparator()); + popupMenu.add(new JMenuItem(removeWatchpointAction)); + popupMenu.add(new JMenuItem(configureWatchpointAction)); - /* Show source file on breakpoint mouse click */ table.addMouseListener(new MouseAdapter() { public void mouseClicked(MouseEvent e) { java.awt.Point p = e.getPoint(); @@ -167,63 +166,32 @@ public class BreakpointsUI extends JPanel { if (realColumnIndex != COLUMN_ADDRESS && realColumnIndex != COLUMN_FILELINE - && realColumnIndex != COLUMN_REMOVE && realColumnIndex != COLUMN_INFO) { return; } - MspBreakpoint[] allBreakpoints = BreakpointsUI.this.breakpoints.getBreakpoints(); + Watchpoint[] allBreakpoints = BreakpointsUI.this.mote.getBreakpoints(); if (rowIndex < 0 || rowIndex >= allBreakpoints.length) { return; } - MspBreakpoint breakpoint = allBreakpoints[rowIndex]; + Watchpoint breakpoint = allBreakpoints[rowIndex]; if (e.isPopupTrigger() || SwingUtilities.isRightMouseButton(e)) { - popupBreakpoint = breakpoint; + selectedWatchpoint = breakpoint; popupMenu.show(table, e.getX(), e.getY()); return; } if (realColumnIndex == COLUMN_INFO) { - String msg = JOptionPane.showInputDialog( - GUI.getTopParentContainer(), - "Enter description", - "Watchpoint Description", - JOptionPane.QUESTION_MESSAGE); - if (msg != null) { - breakpoint.setUserMessage(msg); - } - Color newColor = JColorChooser.showDialog( - GUI.getTopParentContainer(), - "Watchpoint Color", - breakpoint.getColor()); - if (newColor != null) { - breakpoint.setColor(newColor); - } + configureWatchpointInfo(breakpoint); return; } - File file = allBreakpoints[rowIndex].getCodeFile(); + /*File file = allBreakpoints[rowIndex].getCodeFile(); int line = allBreakpoints[rowIndex].getLineNumber(); if (file == null) { return; - } - - /* Display source code */ - codeWatcher.displaySourceFile(file, line); - } - }); - - /* Update when breakpoints are triggered/added/removed */ - breakpoints.addWatchpointListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - MspBreakpoint triggered = BreakpointsUI.this.breakpoints.getLastWatchpoint(); - if (triggered == null) { - table.repaint(); - return; - } - - flashBreakpoint(triggered); + }*/ } }); @@ -232,24 +200,41 @@ public class BreakpointsUI extends JPanel { add(BorderLayout.CENTER, table); } - private void flashBreakpoint(MspBreakpoint breakpoint) { - /* Locate breakpoints table index */ - int index = -1; - MspBreakpoint[] all = breakpoints.getBreakpoints(); - for (int i=0; i < breakpoints.getBreakpointsCount(); i++) { - if (breakpoint == all[i]) { - index = i; - break; - } - } - if (index < 0) { + private void configureWatchpointInfo(Watchpoint breakpoint) { + String msg = (String) JOptionPane.showInputDialog( + GUI.getTopParentContainer(), + "Enter description;", + "Watchpoint description", + JOptionPane.QUESTION_MESSAGE, null, null, breakpoint.getUserMessage()); + if (msg == null) { return; } + breakpoint.setUserMessage(msg); + Color newColor = JColorChooser.showDialog( + GUI.getTopParentContainer(), + "Watchpoint color", + breakpoint.getColor()); + if (newColor == null) { + return; + } + breakpoint.setColor(newColor); + } - final int breakpointIndex = index; + public void selectBreakpoint(final Watchpoint breakpoint) { + if (breakpoint == null) { + return; + } + /* Locate breakpoints table index */ SwingUtilities.invokeLater(new Runnable() { public void run() { - table.setRowSelectionInterval(breakpointIndex, breakpointIndex); + Watchpoint[] watchpoints = mote.getBreakpoints(); + for (int i=0; i < watchpoints.length; i++) { + if (breakpoint == watchpoints[i]) { + /* Select */ + table.setRowSelectionInterval(i, i); + return; + } + } } }); } @@ -259,18 +244,18 @@ public class BreakpointsUI extends JPanel { return COLUMN_NAMES[col].toString(); } public int getRowCount() { - return breakpoints.getBreakpointsCount(); + return mote.getBreakpoints().length; } public int getColumnCount() { return COLUMN_NAMES.length; } public Object getValueAt(int row, int col) { - MspBreakpoint breakpoint = breakpoints.getBreakpoints()[row]; + Watchpoint breakpoint = mote.getBreakpoints()[row]; /* Executable address in hexadecimal */ if (col == COLUMN_ADDRESS) { Integer address = breakpoint.getExecutableAddress(); - return "0x" + Integer.toHexString(address.intValue()); + return String.format("0x%04x", address.intValue()); } /* Source file + line number */ @@ -300,7 +285,7 @@ public class BreakpointsUI extends JPanel { return getColumnClass(col) == Boolean.class; } public void setValueAt(Object value, int row, int col) { - MspBreakpoint breakpoint = breakpoints.getBreakpoints()[row]; + Watchpoint breakpoint = mote.getBreakpoints()[row]; if (col == COLUMN_STOP) { /* Toggle stop state */ @@ -308,109 +293,36 @@ public class BreakpointsUI extends JPanel { fireTableCellUpdated(row, col); return; } - - if (col == COLUMN_REMOVE) { - /* Remove breakpoint */ - Integer address = breakpoint.getExecutableAddress(); - breakpoints.removeBreakpoint(address); - fireTableCellUpdated(row, col); - return; - } } public Class getColumnClass(int c) { return getValueAt(0, c).getClass(); } }; - private Action addToMoteTypeAction = new AbstractAction("Register on all motes (mote type)") { + private Action gotoCodeAction = new AbstractAction("Show in source code") { public void actionPerformed(ActionEvent e) { - if (popupBreakpoint == null) { - logger.fatal("No breakpoint to add"); + if (selectedWatchpoint == null) { + return; } - - /* Extract all motes of the same mote type */ - Simulation sim = popupBreakpoint.getMote().getSimulation(); - MoteType type = popupBreakpoint.getMote().getType(); - ArrayList motes = new ArrayList(); - for (Mote m: sim.getMotes()) { - if (m.getType() == type) { - if (!(m instanceof MspMote)) { - logger.fatal("At least one mote was not a MSP mote: " + m); - return; - } - - motes.add((MspMote)m); - } - } - - /* Register breakpoints */ - int reregistered = 0; - for (MspMote m: motes) { - /* Avoid duplicates (match executable addresses) */ - MspBreakpointContainer container = m.getBreakpointsContainer(); - MspBreakpoint[] breakpoints = container.getBreakpoints(); - for (MspBreakpoint w: breakpoints) { - if (popupBreakpoint.getExecutableAddress().intValue() == - w.getExecutableAddress().intValue()) { - logger.info("Reregistering breakpoint at mote: " + m); - container.removeBreakpoint(w.getExecutableAddress()); - reregistered++; - } - } - - MspBreakpoint newBreakpoint = container.addBreakpoint( - popupBreakpoint.getCodeFile(), - popupBreakpoint.getLineNumber(), - popupBreakpoint.getExecutableAddress()); - newBreakpoint.setUserMessage(popupBreakpoint.getUserMessage()); - newBreakpoint.setColor(popupBreakpoint.getColor()); - newBreakpoint.setStopsSimulation(popupBreakpoint.stopsSimulation()); - } - - JOptionPane.showMessageDialog(GUI.getTopParentContainer(), - "Registered " + motes.size() + " breakpoints (" + reregistered + " re-registered)", - "Breakpoints added", JOptionPane.INFORMATION_MESSAGE); + codeWatcher.displaySourceFile(selectedWatchpoint.getCodeFile(), selectedWatchpoint.getLineNumber(), false); } }; - private Action delFromMoteTypeAction = new AbstractAction("Delete from all motes (mote type)") { + private Action removeWatchpointAction = new AbstractAction("Remove watchpoint") { public void actionPerformed(ActionEvent e) { - if (popupBreakpoint == null) { - logger.fatal("No breakpoint to delete"); + if (selectedWatchpoint == null) { + return; } - - /* Extract all motes of the same mote type */ - Simulation sim = popupBreakpoint.getMote().getSimulation(); - MoteType type = popupBreakpoint.getMote().getType(); - ArrayList motes = new ArrayList(); - for (Mote m: sim.getMotes()) { - if (m.getType() == type) { - if (!(m instanceof MspMote)) { - logger.fatal("At least one mote was not a MSP mote: " + m); - return; - } - - motes.add((MspMote)m); - } + mote.removeBreakpoint(selectedWatchpoint); + table.invalidate(); + table.repaint(); + } + }; + private Action configureWatchpointAction = new AbstractAction("Configure watchpoint information") { + public void actionPerformed(ActionEvent e) { + if (selectedWatchpoint == null) { + return; } - - /* Delete breakpoints */ - int deleted = 0; - for (MspMote m: motes) { - /* Avoid duplicates (match executable addresses) */ - MspBreakpointContainer container = m.getBreakpointsContainer(); - MspBreakpoint[] breakpoints = container.getBreakpoints(); - for (MspBreakpoint w: breakpoints) { - if (popupBreakpoint.getExecutableAddress().intValue() == - w.getExecutableAddress().intValue()) { - container.removeBreakpoint(w.getExecutableAddress()); - deleted++; - } - } - } - - JOptionPane.showMessageDialog(GUI.getTopParentContainer(), - "Deleted " + deleted + " breakpoints", - "Breakpoints deleted", JOptionPane.INFORMATION_MESSAGE); + configureWatchpointInfo(selectedWatchpoint); } }; } diff --git a/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/plugins/CodeUI.java b/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/plugins/CodeUI.java index c034d6f0a..e58257b66 100644 --- a/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/plugins/CodeUI.java +++ b/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/plugins/CodeUI.java @@ -34,32 +34,33 @@ package se.sics.cooja.mspmote.plugins; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; -import java.awt.Font; import java.awt.Point; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; import java.io.File; import java.util.ArrayList; -import java.util.Iterator; -import java.util.Vector; +import java.util.HashMap; -import javax.swing.AbstractListModel; -import javax.swing.JLabel; -import javax.swing.JList; +import javax.swing.JEditorPane; import javax.swing.JMenuItem; import javax.swing.JPanel; import javax.swing.JPopupMenu; -import javax.swing.JSeparator; -import javax.swing.ListCellRenderer; +import javax.swing.JScrollPane; import javax.swing.SwingUtilities; +import javax.swing.event.PopupMenuEvent; +import javax.swing.event.PopupMenuListener; +import javax.swing.text.BadLocationException; +import javax.swing.text.Highlighter; +import javax.swing.text.Highlighter.HighlightPainter; + +import jsyntaxpane.DefaultSyntaxKit; +import jsyntaxpane.components.Markers.SimpleMarker; import org.apache.log4j.Logger; -import se.sics.mspsim.extutil.highlight.CScanner; -import se.sics.mspsim.extutil.highlight.Token; -import se.sics.mspsim.extutil.highlight.TokenTypes; +import se.sics.cooja.Watchpoint; +import se.sics.cooja.WatchpointMote; +import se.sics.cooja.util.JSyntaxAddBreakpoint; +import se.sics.cooja.util.JSyntaxRemoveBreakpoint; +import se.sics.cooja.util.StringUtils; /** * Displays source code and allows a user to add and remove breakpoints. @@ -69,184 +70,231 @@ import se.sics.mspsim.extutil.highlight.TokenTypes; public class CodeUI extends JPanel { private static Logger logger = Logger.getLogger(CodeUI.class); - private JPanel panel = null; - private JList codeList = null; + { + DefaultSyntaxKit.initKit(); + } - private MspBreakpointContainer breakpoints = null; + private JEditorPane codeEditor = null; + private HashMap codeEditorLines = null; protected File displayedFile = null; - private Token tokensArray[][] = null; - private int tokensStartPos[] = null; + private static final HighlightPainter CURRENT_LINE_MARKER = new SimpleMarker(Color.ORANGE); + private static final HighlightPainter SELECTED_LINE_MARKER = new SimpleMarker(Color.GREEN); + private static final HighlightPainter BREAKPOINTS_MARKER = new SimpleMarker(Color.LIGHT_GRAY); + private final Object currentLineTag; + private final Object selectedLineTag; + private final ArrayList breakpointsLineTags = new ArrayList(); - /** - * @param breakpoints Breakpoints - */ - public CodeUI(MspBreakpointContainer breakpoints) { - this.breakpoints = breakpoints; + private JSyntaxAddBreakpoint actionAddBreakpoint = null; + private JSyntaxRemoveBreakpoint actionRemoveBreakpoint = null; + + private WatchpointMote mote; + + public CodeUI(WatchpointMote mote) { + this.mote = mote; + + { + /* Workaround to configure jsyntaxpane */ + JEditorPane e = new JEditorPane(); + new JScrollPane(e); + e.setContentType("text/c"); + DefaultSyntaxKit kit = (DefaultSyntaxKit) e.getEditorKit(); + kit.setProperty("Action.addbreakpoint", JSyntaxAddBreakpoint.class.getName()); + kit.setProperty("Action.removebreakpoint", JSyntaxRemoveBreakpoint.class.getName()); + kit.setProperty("PopupMenu", "copy-to-clipboard,-,find,find-next,goto-line,-,addbreakpoint,removebreakpoint"); + } setLayout(new BorderLayout()); + codeEditor = new JEditorPane(); + add(new JScrollPane(codeEditor), BorderLayout.CENTER); + doLayout(); - panel = new JPanel(new BorderLayout()); - add(panel, BorderLayout.CENTER); - displayNoCode(); + codeEditorLines = new HashMap(); + codeEditor.setContentType("text/c"); + DefaultSyntaxKit kit = (DefaultSyntaxKit) codeEditor.getEditorKit(); + kit.setProperty("Action.addbreakpoint", JSyntaxAddBreakpoint.class.getName()); + kit.setProperty("Action.removebreakpoint", JSyntaxRemoveBreakpoint.class.getName()); + kit.setProperty("PopupMenu", "copy-to-clipboard,-,find,find-next,goto-line,-,addbreakpoint,removebreakpoint"); - breakpoints.addWatchpointListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - /* Only update code list if simulation is not running */ - if (CodeUI.this.breakpoints.getMote().getSimulation().isRunning() || - CodeUI.this.breakpoints.getLastWatchpoint() != null) { + JPopupMenu p = codeEditor.getComponentPopupMenu(); + for (Component c: p.getComponents()) { + if (c instanceof JMenuItem) { + if (((JMenuItem) c).getAction() != null && + ((JMenuItem) c).getAction() instanceof JSyntaxAddBreakpoint) { + actionAddBreakpoint = (JSyntaxAddBreakpoint)(((JMenuItem) c).getAction()); + actionAddBreakpoint.setMenuText("Add breakpoint"); + } + if (((JMenuItem) c).getAction() != null && + ((JMenuItem) c).getAction() instanceof JSyntaxRemoveBreakpoint) { + actionRemoveBreakpoint = (JSyntaxRemoveBreakpoint)(((JMenuItem) c).getAction()); + actionRemoveBreakpoint.setMenuText("Remove breakpoint"); + } + } + } + + codeEditor.setText(""); + codeEditorLines.clear(); + codeEditor.setEditable(false); + + Highlighter hl = codeEditor.getHighlighter(); + Object o = null; + try { + o = hl.addHighlight(0, 0, CURRENT_LINE_MARKER); + } catch (BadLocationException e1) { + } + currentLineTag = o; + + o = null; + try { + o = hl.addHighlight(0, 0, SELECTED_LINE_MARKER); + } catch (BadLocationException e1) { + } + selectedLineTag = o; + + codeEditor.getComponentPopupMenu().addPopupMenuListener(new PopupMenuListener() { + public void popupMenuWillBecomeVisible(PopupMenuEvent e) { + /* Disable breakpoint actions */ + actionAddBreakpoint.setEnabled(false); + actionRemoveBreakpoint.setEnabled(false); + + int line = getCodeEditorMouseLine(); + if (line < 1) { return; } - - SwingUtilities.invokeLater(new Runnable() { - public void run() { - if (codeList != null) { - codeList.updateUI(); - } - } - }); + + /* Configure breakpoint menu options */ + Integer address = + CodeUI.this.mote.getExecutableAddressOf(displayedFile, line); + if (address == null) { + return; + } + final int start = codeEditorLines.get(line); + int end = codeEditorLines.get(line+1); + Highlighter hl = codeEditor.getHighlighter(); + try { + hl.changeHighlight(selectedLineTag, start, end); + } catch (BadLocationException e1) { + } + boolean hasBreakpoint = + CodeUI.this.mote.breakpointExists(address); + if (!hasBreakpoint) { + actionAddBreakpoint.setEnabled(true); + actionAddBreakpoint.putValue("WatchpointMote", CodeUI.this.mote); + actionAddBreakpoint.putValue("WatchpointFile", displayedFile); + actionAddBreakpoint.putValue("WatchpointLine", new Integer(line)); + actionAddBreakpoint.putValue("WatchpointAddress", new Integer(address)); + } else { + actionRemoveBreakpoint.setEnabled(true); + actionRemoveBreakpoint.putValue("WatchpointMote", CodeUI.this.mote); + actionRemoveBreakpoint.putValue("WatchpointFile", displayedFile); + actionRemoveBreakpoint.putValue("WatchpointLine", new Integer(line)); + actionRemoveBreakpoint.putValue("WatchpointAddress", new Integer(address)); + } + } + public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { + Highlighter hl = codeEditor.getHighlighter(); + try { + hl.changeHighlight(selectedLineTag, 0, 0); + } catch (BadLocationException e1) { + } + } + public void popupMenuCanceled(PopupMenuEvent e) { } }); + + displayNoCode(true); + } + + public void updateBreakpoints() { + Highlighter hl = codeEditor.getHighlighter(); + + for (Object breakpointsLineTag: breakpointsLineTags) { + hl.removeHighlight(breakpointsLineTag); + } + breakpointsLineTags.clear(); + + for (Watchpoint w: mote.getBreakpoints()) { + if (!w.getCodeFile().equals(displayedFile)) { + continue; + } + + final int start = codeEditorLines.get(w.getLineNumber()); + int end = codeEditorLines.get(w.getLineNumber()+1); + try { + breakpointsLineTags.add(hl.addHighlight(start, end, BREAKPOINTS_MARKER)); + } catch (BadLocationException e1) { + } + } + } + + private int getCodeEditorMouseLine() { + if (codeEditorLines == null) { + return -1; + } + Point mousePos = codeEditor.getMousePosition(); + if (mousePos == null) { + return -1; + } + int modelPos = codeEditor.viewToModel(mousePos); + int line = 1; + while (codeEditorLines.containsKey(line+1)) { + int next = codeEditorLines.get(line+1); + if (modelPos < next) { + return line; + } + line++; + } + return -1; } /** * Remove any shown source code. */ - public void displayNoCode() { - // Display "no code" message + public void displayNoCode(final boolean markCurrent) { SwingUtilities.invokeLater(new Runnable() { public void run() { - panel.removeAll(); - panel.repaint(); + displayedFile = null; + codeEditor.setText(null); + codeEditorLines.clear(); + displayLine(-1, markCurrent); } }); - displayedFile = null; - return; - } - - private void createTokens(String[] codeData) { - - /* Merge code lines */ - StringBuilder sb = new StringBuilder(); - for (String line: codeData) { - sb.append(line); - sb.append('\n'); - } - String code = sb.toString(); - - /* Scan code */ - CScanner cScanner = new CScanner(); - cScanner.change(0, 0, code.length()); - int nrTokens; - nrTokens = cScanner.scan(code.toCharArray(), 0, code.length()); - - /* Extract tokens */ - ArrayList codeTokensVector = new ArrayList(); - for (int i=0; i < nrTokens; i++) { - Token token = cScanner.getToken(i); - codeTokensVector.add(token); - } - - /* Create new line token array */ - Token newTokensArray[][] = new Token[codeData.length][]; - int[] newTokensStartPos = new int[codeData.length]; - int lineStart=0, lineEnd=-1; - Iterator tokens = codeTokensVector.iterator(); - Token currentToken = tokens.next(); - for (int i=0; i < newTokensArray.length; i++) { - lineStart = lineEnd + 1; - lineEnd = lineStart + codeData[i].length(); - - newTokensStartPos[i] = lineStart;; - - /* Advance tokens until correct line */ - while (currentToken.position + currentToken.symbol.name.length() < lineStart) { - if (!tokens.hasNext()) { - break; - } - currentToken = tokens.next(); - } - - /* Advance tokens until last token on line */ - Vector lineTokens = new Vector(); - while (currentToken.position < lineEnd) { - lineTokens.add(currentToken); - - if (!tokens.hasNext()) { - break; - } - currentToken = tokens.next(); - } - - if (currentToken == null) { - break; - } - - /* Store line tokens */ - Token[] lineTokensArray = new Token[lineTokens.size()]; - for (int j=0; j < lineTokens.size(); j++) { - lineTokensArray[j] = lineTokens.get(j); - } - newTokensArray[i] = lineTokensArray; - } - - /* Start using tokens array */ - tokensArray = newTokensArray; - tokensStartPos = newTokensStartPos; } /** * Display given source code and mark given line. * * @param codeFile Source code file - * @param codeData Source code * @param lineNr Line numer */ - public void displayNewCode(File codeFile, String[] codeData, final int lineNr) { - displayedFile = codeFile; + public void displayNewCode(final File codeFile, final int lineNr, final boolean markCurrent) { + if (!codeFile.equals(displayedFile)) { + /* Read from disk */ + final String data = StringUtils.loadFromFile(codeFile); + if (data == null || data.length() == 0) { + displayNoCode(markCurrent); + return; + } - if (codeData == null || codeData.length == 0) { - displayNoCode(); - return; + String[] lines = data.split("\n"); + logger.info("Opening " + codeFile + " (" + lines.length + " lines)"); + int length = 0; + codeEditorLines.clear(); + for (int line=1; line-1 < lines.length; line++) { + codeEditorLines.put(line, length); + length += lines[line-1].length()+1; + } + codeEditor.setText(data.toString()); + displayedFile = codeFile; + updateBreakpoints(); } - logger.info("Opening " + codeFile + " (" + codeData.length + " lines)"); - - /* Create new list */ - final JList newList = new JList(new CodeListModel(codeData)); - newList.setBackground(Color.WHITE); - newList.setFont(new Font("courier", 0, 12)); - newList.setCellRenderer(new CodeCellRenderer(lineNr)); - ((CodeCellRenderer)newList.getCellRenderer()).setNice(false); - newList.setFixedCellHeight(12); - newList.addMouseListener(new MouseAdapter() { - public void mousePressed(MouseEvent e) { - handleMouseEvent(e); - } - public void mouseReleased(MouseEvent e) { - handleMouseEvent(e); - } - public void mouseEntered(MouseEvent e) { - handleMouseEvent(e); - } - public void mouseExited(MouseEvent e) { - handleMouseEvent(e); - } - public void mouseClicked(MouseEvent e) { - handleMouseEvent(e); - } - }); - createTokens(codeData); - SwingUtilities.invokeLater(new Runnable() { public void run() { - panel.removeAll(); - codeList = newList; - panel.add(codeList); - panel.validate(); - displayLine(lineNr); + displayLine(lineNr, markCurrent); } }); + } /** @@ -255,290 +303,35 @@ public class CodeUI extends JPanel { * * @param lineNumber Line number */ - public void displayLine(int lineNumber) { - if (codeList == null) { - return; - } - - ((CodeCellRenderer) codeList.getCellRenderer()).setNice(false); - ((CodeCellRenderer) codeList.getCellRenderer()).changeCurrentLine(lineNumber); - ((CodeCellRenderer) codeList.getCellRenderer()).validate(); - - if (lineNumber > 0) { - int index = lineNumber - 1; - codeList.setSelectedIndex(index); - codeList.ensureIndexIsVisible(Math.max(0, index-3)); - codeList.ensureIndexIsVisible(Math.min(index+3, codeList.getModel().getSize())); - codeList.ensureIndexIsVisible(index); - } - - codeList.updateUI(); - SwingUtilities.invokeLater(new Runnable() { - public void run() { - ((CodeCellRenderer) codeList.getCellRenderer()).setNice(true); - codeList.repaint(); - } - }); - } - - private void handleMouseEvent(MouseEvent event) { - if (event.isPopupTrigger()) { - Point menuLocation = codeList.getPopupLocation(event); - if (menuLocation == null) { - menuLocation = new Point( - codeList.getLocationOnScreen().x + event.getX(), - codeList.getLocationOnScreen().y + event.getY()); + private void displayLine(int lineNumber, boolean markCurrent) { + try { + if (markCurrent) { + /* remove previous highlight */ + Highlighter hl = codeEditor.getHighlighter(); + hl.changeHighlight(currentLineTag, 0, 0); } - final int currentLine = codeList.locationToIndex(new Point(event.getX(), event.getY())) + 1; - codeList.setSelectedIndex(currentLine - 1); - JPopupMenu popupMenu = createPopupMenu(displayedFile, currentLine); - - popupMenu.setLocation(menuLocation); - popupMenu.setInvoker(codeList); - popupMenu.setVisible(true); - } - } - - private JPopupMenu createPopupMenu(final File codeFile, final int lineNr) { - final Integer executableAddress = breakpoints.getExecutableAddressOf(codeFile, lineNr); - boolean breakpointExists = breakpoints.breakpointExists(codeFile, lineNr); - - JPopupMenu menuMotePlugins = new JPopupMenu(); - JMenuItem headerMenuItem = new JMenuItem("Breakpoints:"); - headerMenuItem.setEnabled(false); - menuMotePlugins.add(headerMenuItem); - menuMotePlugins.add(new JSeparator()); - - JMenuItem addBreakpointMenuItem = new JMenuItem("Add breakpoint on line " + lineNr); - if (executableAddress == null || breakpointExists) { - addBreakpointMenuItem.setEnabled(false); - } else { - addBreakpointMenuItem.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - breakpoints.addBreakpoint(codeFile, lineNr, executableAddress); + if (lineNumber >= 0) { + final int start = codeEditorLines.get(lineNumber); + int end = codeEditorLines.get(lineNumber+1); + if (markCurrent) { + /* highlight code */ + Highlighter hl = codeEditor.getHighlighter(); + hl.changeHighlight(currentLineTag, start, end); } - }); - } - menuMotePlugins.add(addBreakpointMenuItem); - JMenuItem delBreakpointMenuItem = new JMenuItem("Delete breakpoint on line " + lineNr); - if (executableAddress == null || !breakpointExists) { - delBreakpointMenuItem.setEnabled(false); - } else { - delBreakpointMenuItem.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - breakpoints.removeBreakpoint(executableAddress); - } - }); - } - menuMotePlugins.add(delBreakpointMenuItem); - - return menuMotePlugins; - } - - private class CodeListModel extends AbstractListModel { - private String[] codeData; - - public CodeListModel(String[] codeData) { - super(); - this.codeData = codeData; - } - - public int getSize() { - if (codeData == null || codeData.length == 0) { - return 0; - } - - return codeData.length; - } - - public Object getElementAt(int index) { - if (codeData == null || codeData.length == 0) { - return "No code to display"; - } - - return codeData[index]; - } - } - - /* FROM: http://www.rgagnon.com/javadetails/java-0306.html, 03/19/2008 */ - private static String stringToHTMLString(String string) { - StringBuffer sb = new StringBuffer(string.length()); - boolean lastWasBlankChar = false; - int len = string.length(); - char c; - - for (int i = 0; i < len; i++) - { - c = string.charAt(i); - if (c == ' ') { - if (lastWasBlankChar) { - lastWasBlankChar = false; - sb.append(" "); - } - else { - lastWasBlankChar = true; - sb.append(' '); - } - } - else { - lastWasBlankChar = false; - // - // HTML Special Chars - if (c == '"') { - sb.append("""); - } else if (c == '&') { - sb.append("&"); - } else if (c == '<') { - sb.append("<"); - } else if (c == '>') { - sb.append(">"); - } else if (c == '\n') { - // Handle Newline - sb.append("<br/>"); - } else { - int ci = 0xffff & c; - if (ci < 160 ) { - // nothing special only 7 Bit - sb.append(c); - } else { - // Not 7 Bit use the unicode system - sb.append("&#"); - sb.append(new Integer(ci).toString()); - sb.append(';'); + /* ensure visible */ + SwingUtilities.invokeLater(new Runnable() { + public void run() { + try { + codeEditor.scrollRectToVisible(codeEditor.modelToView(start)); + } catch (BadLocationException e) { + } } - } + }); } + } catch (Exception e) { + logger.warn("Error when highlighting current line: " + e.getMessage(), e); } - return sb.toString(); } - - private class CodeCellRenderer extends JLabel implements ListCellRenderer { - private int currentIndex; - private boolean nice = true; - - public CodeCellRenderer(int currentLineNr) { - this.currentIndex = currentLineNr - 1; - } - - public void setNice(boolean b) { - nice = b; - } - - public void changeCurrentLine(int currentLineNr) { - this.currentIndex = currentLineNr - 1; - } - - private String getColoredLabelText(int lineNr, int lineStartPos, Token[] tokens, String code) { - StringBuilder sb = new StringBuilder(); - sb.append(""); - - /* Add line number */ - String lineString = "0000" + Integer.toString(lineNr); - lineString = lineString.substring(lineString.length() - 4); - sb.append(""); - sb.append(lineString); - sb.append(": "); - - /* Add code */ - if (tokens == null || tokens.length == 0 || lineStartPos < 0) { - sb.append(""); - sb.append(code); - sb.append(""); - } else { - for (int i=tokens.length-1; i >= 0; i--) { - Token subToken = tokens[i]; - - String colorString = "000000"; - - /* Determine code color */ - final int type = subToken.symbol.type; - switch (type) { - case TokenTypes.COMMENT: - case TokenTypes.START_COMMENT: - case TokenTypes.MID_COMMENT: - case TokenTypes.END_COMMENT: - colorString = "00AA00"; - break; - case TokenTypes.STRING: - colorString = "0000AA"; - break; - case TokenTypes.KEYWORD: - case TokenTypes.KEYWORD2: - colorString = "AA0000"; - break; - } - - /* Extract part of token residing in current line */ - int tokenLinePos; - String subCode; - if (subToken.position < lineStartPos) { - subCode = subToken.symbol.name.substring(lineStartPos - subToken.position); - tokenLinePos = 0; - } else if (subToken.position + subToken.symbol.name.length() > lineStartPos + code.length()) { - subCode = subToken.symbol.name.substring(0, code.length() + lineStartPos - subToken.position); - tokenLinePos = subToken.position - lineStartPos; - } else { - subCode = subToken.symbol.name; - tokenLinePos = subToken.position - lineStartPos; - } - - subCode = stringToHTMLString(subCode); - String firstPart = code.substring(0, tokenLinePos); - String coloredSubCode = "" + subCode + ""; - String lastPart = - tokenLinePos + subToken.symbol.name.length() >= code.length()? - "":code.substring(tokenLinePos + subToken.symbol.name.length()); - - code = firstPart + coloredSubCode + lastPart; - } - - code = code.replace(" ", "  "); - sb.append(code); - } - - sb.append(""); - return sb.toString(); - } - - public Component getListCellRendererComponent( - JList list, - Object value, - int index, - boolean isSelected, - boolean cellHasFocus) - { - int lineNr = index + 1; - if (!nice) { - setText((String) value); - } else if (tokensArray != null && index < tokensArray.length && tokensArray[index] != null) { - setText(getColoredLabelText(lineNr, tokensStartPos[index], tokensArray[index], (String) value)); - } else { - setText(getColoredLabelText(lineNr, 0, null, (String) value)); - } - - if (index == currentIndex) { - setBackground(Color.green); - } else if (isSelected) { - setBackground(list.getSelectionBackground()); - setForeground(list.getSelectionForeground()); - } else { - setBackground(list.getBackground()); - setForeground(list.getForeground()); - } - setEnabled(list.isEnabled()); - - if (breakpoints.breakpointExists(displayedFile, lineNr)) { - setFont(list.getFont().deriveFont(Font.BOLD)); - } else { - setFont(list.getFont()); - } - - setOpaque(true); - - return this; - } - } - } diff --git a/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/plugins/MspBreakpoint.java b/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/plugins/MspBreakpoint.java index 7f2c18a81..e6d881e97 100644 --- a/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/plugins/MspBreakpoint.java +++ b/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/plugins/MspBreakpoint.java @@ -34,129 +34,151 @@ package se.sics.cooja.mspmote.plugins; import java.awt.Color; import java.io.File; import java.io.IOException; +import java.util.ArrayList; import java.util.Collection; -import java.util.Vector; import org.apache.log4j.Logger; import org.jdom.Element; import se.sics.cooja.Watchpoint; import se.sics.cooja.mspmote.MspMote; +import se.sics.cooja.util.StringUtils; import se.sics.mspsim.core.CPUMonitor; /** - * Breakpoint. - * Contains meta data such source code file and line number. + * Mspsim watchpoint. * * @author Fredrik Osterlind */ public class MspBreakpoint implements Watchpoint { private static Logger logger = Logger.getLogger(MspBreakpoint.class); - private MspBreakpointContainer breakpoints; private MspMote mspMote; + private int address = -1; /* Binary address */ + private File codeFile = null; /* Source code, may be null*/ + private int lineNr = -1; /* Source code line number, may be null */ + private CPUMonitor cpuMonitor = null; private boolean stopsSimulation = true; - private Integer address = null; /* Binary address */ - - private File codeFile = null; /* Source code, may be null*/ - private Integer lineNr = null; /* Source code line number, may be null */ - private String msg = null; private Color color = Color.BLACK; - public MspBreakpoint(MspBreakpointContainer breakpoints, MspMote mote) { - this.breakpoints = breakpoints; + private String contikiCode = null; + + public MspBreakpoint(MspMote mote) { this.mspMote = mote; + /* expects setConfigXML(..) */ } - public MspBreakpoint(MspBreakpointContainer breakpoints, MspMote mote, Integer address) { - this(breakpoints, mote); + public MspBreakpoint(MspMote mote, Integer address, File codeFile, Integer lineNr) { + this(mote); this.address = address; + this.codeFile = codeFile; + this.lineNr = lineNr; createMonitor(); } - public MspBreakpoint(MspBreakpointContainer breakpoints, MspMote mote, Integer address, File codeFile, Integer lineNr) { - this(breakpoints, mote, address); - this.codeFile = codeFile; - this.lineNr = lineNr; - } - - /** - * @return MSP mote - */ public MspMote getMote() { return mspMote; } - /** - * @return Executable address - */ - public Integer getExecutableAddress() { - return address; + public Color getColor() { + return color; } - - /** - * @return Source code file - */ + public void setColor(Color color) { + this.color = color; + } + + public String getDescription() { + String desc = ""; + if (codeFile != null) { + desc += codeFile.getPath() + ":" + lineNr + " (0x" + Integer.toHexString(address) + ")"; + } else if (address >= 0) { + desc += "0x" + Integer.toHexString(address); + } + if (msg != null) { + desc += "\n\n" + msg; + } + return desc; + } + public void setUserMessage(String msg) { + this.msg = msg; + } + public String getUserMessage() { + return msg; + } + public File getCodeFile() { return codeFile; } - - /** - * @return Source code file line number - */ - public Integer getLineNumber() { + public int getLineNumber() { return lineNr; } - - public boolean stopsSimulation() { - return stopsSimulation; + public int getExecutableAddress() { + return address; } public void setStopsSimulation(boolean stops) { stopsSimulation = stops; } + public boolean stopsSimulation() { + return stopsSimulation; + } private void createMonitor() { cpuMonitor = new CPUMonitor() { public void cpuAction(int type, int adr, int data) { - breakpoints.signalBreakpointTrigger(MspBreakpoint.this); + if (type != CPUMonitor.EXECUTE) { + return; + } + + mspMote.signalBreakpointTrigger(MspBreakpoint.this); } }; mspMote.getCPU().addWatchPoint(address, cpuMonitor); + + + /* Remember Contiki code, to verify it when reloaded */ + if (contikiCode == null) { + final String code = StringUtils.loadFromFile(codeFile); + if (code != null) { + String[] lines = code.split("\n"); + if (lineNr-1 < lines.length) { + contikiCode = lines[lineNr-1].trim(); + } + } + } + } - + public void unregisterBreakpoint() { mspMote.getCPU().removeWatchPoint(address, cpuMonitor); } public Collection getConfigXML() { - Vector config = new Vector(); + ArrayList config = new ArrayList(); Element element; - element = new Element("address"); - element.setText(address.toString()); - config.add(element); - element = new Element("stops"); element.setText("" + stopsSimulation); config.add(element); - if (codeFile != null) { - element = new Element("codefile"); - File file = mspMote.getSimulation().getGUI().createPortablePath(codeFile); - element.setText(file.getPath().replaceAll("\\\\", "/")); - config.add(element); - } + element = new Element("codefile"); + File file = mspMote.getSimulation().getGUI().createPortablePath(codeFile); + element.setText(file.getPath().replaceAll("\\\\", "/")); + config.add(element); - if (lineNr != null) { - element = new Element("line"); - element.setText(lineNr.toString()); + element = new Element("line"); + element.setText("" + lineNr); + config.add(element); + + if (contikiCode != null) { + element = new Element("contikicode"); + element.setText(contikiCode); config.add(element); } @@ -177,7 +199,7 @@ public class MspBreakpoint implements Watchpoint { public boolean setConfigXML(Collection configXML, boolean visAvailable) { /* Already knows mote and breakpoints */ - + for (Element element : configXML) { if (element.getName().equals("codefile")) { File file = new File(element.getText()); @@ -193,8 +215,23 @@ public class MspBreakpoint implements Watchpoint { } } else if (element.getName().equals("line")) { lineNr = Integer.parseInt(element.getText()); - } else if (element.getName().equals("address")) { - address = Integer.parseInt(element.getText()); + } else if (element.getName().equals("contikicode")) { + String lastContikiCode = element.getText().trim(); + + /* Verify that Contiki code did not change */ + final String code = StringUtils.loadFromFile(codeFile); + if (code != null) { + String[] lines = code.split("\n"); + if (lineNr-1 < lines.length) { + contikiCode = lines[lineNr-1].trim(); + } + } + + if (!lastContikiCode.equals(contikiCode)) { + logger.warn("Detected modified Contiki code at breakpoint: " + codeFile.getPath() + ":" + lineNr + "."); + logger.warn("From: '" + lastContikiCode + "'"); + logger.warn(" To: '" + contikiCode + "'"); + } } else if (element.getName().equals("msg")) { msg = element.getText(); } else if (element.getName().equals("color")) { @@ -204,51 +241,18 @@ public class MspBreakpoint implements Watchpoint { } } - if (address == null) { + /* Update executable address */ + address = mspMote.getExecutableAddressOf(codeFile, lineNr); + if (address < 0) { + logger.fatal("Could not restore breakpoint, did source code change?"); return false; } - - /* TODO Save source code line */ - - if (codeFile != null && lineNr != null) { - /* Update executable address */ - address = mspMote.getBreakpointsContainer().getExecutableAddressOf(codeFile, lineNr); - if (address == null) { - logger.fatal("Could not restore breakpoint, did source code change?"); - address = 0; - } - } - createMonitor(); + return true; } - public void setUserMessage(String msg) { - this.msg = msg; + public String toString() { + return getMote() + ": " + getDescription(); } - public String getUserMessage() { - return msg; - } - - public void setColor(Color color) { - this.color = color; - } - - public String getDescription() { - String desc = ""; - if (codeFile != null) { - desc += codeFile.getPath() + ":" + lineNr + " (0x" + Integer.toHexString(address.intValue()) + ")"; - } else if (address != null) { - desc += "0x" + Integer.toHexString(address.intValue()); - } - if (msg != null) { - desc += "\n\n" + msg; - } - return desc; - } - - public Color getColor() { - return color; - } - } diff --git a/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/plugins/MspBreakpointContainer.java b/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/plugins/MspBreakpointContainer.java deleted file mode 100644 index 27c721615..000000000 --- a/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/plugins/MspBreakpointContainer.java +++ /dev/null @@ -1,280 +0,0 @@ -/* - * Copyright (c) 2009, Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $Id: MspBreakpointContainer.java,v 1.3 2010/01/21 22:32:32 fros4943 Exp $ - */ - -package se.sics.cooja.mspmote.plugins; - -import java.awt.event.ActionListener; -import java.io.File; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Enumeration; -import java.util.Hashtable; -import java.util.Vector; - -import org.apache.log4j.Logger; -import org.jdom.Element; - -import se.sics.cooja.WatchpointMote; -import se.sics.cooja.mspmote.MspMote; - -/** - * Breakpoint collection - * - * @author Fredrik Osterlind - */ -public class MspBreakpointContainer implements WatchpointMote { - private static Logger logger = Logger.getLogger(MspBreakpointContainer.class); - - private Hashtable> debuggingInfo = null; - private MspMote mspMote; - - private ArrayList breakpoints = new ArrayList(); - private ArrayList listeners = new ArrayList(); - private MspBreakpoint lastTriggeredBreakpoint = null; - - /** - * @param debuggingInfo Debugging information read from firmware file - * @param mote Mote - */ - public MspBreakpointContainer(MspMote mote, Hashtable> debuggingInfo) { - this.mspMote = mote; - this.debuggingInfo = debuggingInfo; - } - - /** - * Add breakpoint at given address. - * - * @param address Executable address - */ - public void addBreakpoint(Integer address) { - addBreakpoint((File) null, (Integer) null, address); - } - - /** - * Add breakpoint at given address with given meta data. - * - * @param codeFile Source code file - * @param lineNr Source code file line number - * @param address Executable address - * @return Added breakpoint - */ - public MspBreakpoint addBreakpoint(File codeFile, int lineNr, Integer address) { - MspBreakpoint bp = new MspBreakpoint(this, mspMote, address, codeFile, new Integer(lineNr)); - breakpoints.add(bp); - - /* Notify listeners */ - lastTriggeredBreakpoint = null; - for (ActionListener listener: listeners) { - listener.actionPerformed(null); - } - return bp; - } - - /** - * Remove breakpoint at given address. - * - * @param address Executable address - */ - public MspBreakpoint removeBreakpoint(Integer address) { - MspBreakpoint breakpointToRemove = null; - for (MspBreakpoint breakpoint: breakpoints) { - if (breakpoint.getExecutableAddress().intValue() == address.intValue()) { - breakpointToRemove = breakpoint; - break; - } - } - if (breakpointToRemove == null) { - return null; - } - - breakpointToRemove.unregisterBreakpoint(); - breakpoints.remove(breakpointToRemove); - - /* Notify listeners */ - lastTriggeredBreakpoint = null; - for (ActionListener listener: listeners) { - listener.actionPerformed(null); - } - return breakpointToRemove; - } - - /** - * Checks if a breakpoint exists at given address. - * - * @param address Executable address - * @return True if breakpoint exists, false otherwise - */ - public boolean breakpointExists(Integer address) { - if (address == null) { - return false; - } - - for (MspBreakpoint breakpoint: breakpoints) { - if (breakpoint.getExecutableAddress().intValue() == address.intValue()) { - return true; - } - } - return false; - } - - public boolean breakpointExists(File file, int lineNr) { - for (MspBreakpoint breakpoint: breakpoints) { - if (breakpoint.getCodeFile() == null) { - continue; - } - if (breakpoint.getCodeFile().compareTo(file) != 0) { - continue; - } - if (breakpoint.getLineNumber().intValue() != lineNr) { - continue; - } - return true; - } - return false; - } - - /** - * @return All breakpoints - */ - public MspBreakpoint[] getBreakpoints() { - return breakpoints.toArray(new MspBreakpoint[0]); - } - - public int getBreakpointsCount() { - return breakpoints.size(); - } - - public void addWatchpointListener(ActionListener listener) { - listeners.add(listener); - } - - public void removeWatchpointListener(ActionListener listener) { - listeners.remove(listener); - } - - public ActionListener[] getWatchpointListeners() { - return listeners.toArray(new ActionListener[0]); - } - - protected void signalBreakpointTrigger(MspBreakpoint b) { - if (b.stopsSimulation() && mspMote.getSimulation().isRunning()) { - /* Stop simulation immediately */ - mspMote.stopNextInstruction(); - } - - /* Notify listeners */ - lastTriggeredBreakpoint = b; - ActionListener[] arr = getWatchpointListeners(); - for (ActionListener listener: arr) { - listener.actionPerformed(null); - } - } - - public MspMote getMote() { - return mspMote; - } - - public MspBreakpoint getLastWatchpoint() { - return lastTriggeredBreakpoint; - } - - /** - * Tries to calculate the executable address of given file. - * Using debugging information from firmware file, - * - * @param file Source code file - * @param lineNr Source code file line number - * @return Executable address or null if not found - */ - public Integer getExecutableAddressOf(File file, int lineNr) { - if (file == null || lineNr < 0 || debuggingInfo == null) { - return null; - } - - /* Match file */ - Hashtable lineTable = debuggingInfo.get(file); - if (lineTable == null) { - Enumeration fileEnum = debuggingInfo.keys(); - while (fileEnum.hasMoreElements()) { - File f = fileEnum.nextElement(); - if (f != null && f.getName().equals(file.getName())) { - lineTable = debuggingInfo.get(f); - break; - } - } - } - if (lineTable == null) { - return null; - } - - /* Match line number */ - Integer address = lineTable.get(lineNr); - if (address != null) { - Enumeration lineEnum = lineTable.keys(); - while (lineEnum.hasMoreElements()) { - Integer l = lineEnum.nextElement(); - if (l != null && l.intValue() == lineNr) { - /* Found line address */ - return lineTable.get(l); - } - } - } - - return null; - } - - public Collection getConfigXML() { - Vector config = new Vector(); - Element element; - - for (MspBreakpoint breakpoint: breakpoints) { - element = new Element("breakpoint"); - element.addContent(breakpoint.getConfigXML()); - config.add(element); - } - - return config; - } - - public boolean setConfigXML(Collection configXML, boolean visAvailable) { - for (Element element : configXML) { - if (element.getName().equals("breakpoint")) { - MspBreakpoint breakpoint = new MspBreakpoint(this, mspMote); - if (!breakpoint.setConfigXML(element.getChildren(), visAvailable)) { - logger.warn("Could not restore breakpoint: " + breakpoint); - } else { - breakpoints.add(breakpoint); - } - } - } - return true; - } -} diff --git a/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/plugins/MspCodeWatcher.java b/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/plugins/MspCodeWatcher.java index 4ad0ca2e1..a11e31592 100644 --- a/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/plugins/MspCodeWatcher.java +++ b/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/plugins/MspCodeWatcher.java @@ -30,18 +30,16 @@ package se.sics.cooja.mspmote.plugins; import java.awt.BorderLayout; +import java.awt.Color; import java.awt.Component; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.File; import java.io.IOException; -import java.net.MalformedURLException; -import java.net.URL; import java.util.ArrayList; import java.util.Collection; import java.util.Observable; import java.util.Observer; -import java.util.Vector; import javax.swing.AbstractAction; import javax.swing.Action; @@ -54,8 +52,7 @@ import javax.swing.JLabel; import javax.swing.JList; import javax.swing.JOptionPane; import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JSplitPane; +import javax.swing.JTabbedPane; import javax.swing.JTextField; import javax.swing.SwingUtilities; import javax.swing.filechooser.FileFilter; @@ -72,11 +69,12 @@ import se.sics.cooja.MotePlugin; import se.sics.cooja.PluginType; import se.sics.cooja.Simulation; import se.sics.cooja.VisPlugin; +import se.sics.cooja.Watchpoint; +import se.sics.cooja.WatchpointMote; +import se.sics.cooja.WatchpointMote.WatchpointListener; import se.sics.cooja.mspmote.MspMote; import se.sics.cooja.mspmote.MspMoteType; -import se.sics.cooja.util.StringUtils; import se.sics.mspsim.core.EmulationException; -import se.sics.mspsim.core.MSP430; import se.sics.mspsim.ui.DebugUI; import se.sics.mspsim.util.DebugInfo; import se.sics.mspsim.util.ELFDebug; @@ -85,25 +83,31 @@ import se.sics.mspsim.util.ELFDebug; @PluginType(PluginType.MOTE_PLUGIN) public class MspCodeWatcher extends VisPlugin implements MotePlugin { private static final long serialVersionUID = -8463196456352243367L; + + private static final int SOURCECODE = 0; + private static final int BREAKPOINTS = 2; + private static Logger logger = Logger.getLogger(MspCodeWatcher.class); private Simulation simulation; private Observer simObserver; - private MspMote mspMote; private File currentCodeFile = null; private int currentLineNumber = -1; - private JSplitPane leftSplitPane, rightSplitPane; private DebugUI assCodeUI; private CodeUI sourceCodeUI; private BreakpointsUI breakpointsUI; - private MspBreakpointContainer breakpoints = null; + private MspMote mspMote; /* currently the only supported mote */ + private WatchpointMote watchpointMote; + private WatchpointListener watchpointListener; private JComboBox fileComboBox; private String[] debugInfoMap = null; private File[] sourceFiles; - + + private JTabbedPane mainPane; + /** * Mini-debugger for MSP Motes. * Visualizes instructions, source code and allows a user to manipulate breakpoints. @@ -113,15 +117,13 @@ public class MspCodeWatcher extends VisPlugin implements MotePlugin { * @param gui Simulator */ public MspCodeWatcher(Mote mote, Simulation simulationToVisualize, GUI gui) { - super("Msp Code Watcher", gui); - this.mspMote = (MspMote) mote; + super("Msp Code Watcher - " + mote, gui); simulation = simulationToVisualize; + this.mspMote = (MspMote) mote; + this.watchpointMote = (WatchpointMote) mote; getContentPane().setLayout(new BorderLayout()); - /* Breakpoints */ - breakpoints = mspMote.getBreakpointsContainer(); - /* Create source file list */ fileComboBox = new JComboBox(); fileComboBox.addActionListener(new ActionListener() { @@ -149,58 +151,68 @@ public class MspCodeWatcher extends VisPlugin implements MotePlugin { } }); updateFileComboBox(); - + /* Browse code control (north) */ - JButton currentFileButton = new JButton(currentFileAction); - JButton mapButton = new JButton(mapAction); - - Box browseBox = Box.createHorizontalBox(); - browseBox.add(Box.createHorizontalStrut(10)); - browseBox.add(new JLabel("Program counter: ")); - browseBox.add(currentFileButton); - browseBox.add(Box.createHorizontalGlue()); - browseBox.add(new JLabel("Browse: ")); - browseBox.add(fileComboBox); - browseBox.add(Box.createHorizontalStrut(10)); - browseBox.add(mapButton); - browseBox.add(Box.createHorizontalStrut(10)); + Box sourceCodeControl = Box.createHorizontalBox(); + sourceCodeControl.add(new JButton(stepAction)); + sourceCodeControl.add(Box.createHorizontalStrut(10)); + sourceCodeControl.add(new JLabel("Current location: ")); + sourceCodeControl.add(new JButton(currentFileAction)); + sourceCodeControl.add(Box.createHorizontalGlue()); + sourceCodeControl.add(new JLabel("Source files: ")); + sourceCodeControl.add(fileComboBox); + sourceCodeControl.add(Box.createHorizontalStrut(5)); + sourceCodeControl.add(new JButton(mapAction)); + sourceCodeControl.add(Box.createHorizontalStrut(10)); - /* Execution control panel (south) */ - JPanel controlPanel = new JPanel(); - JButton button = new JButton(stepAction); - controlPanel.add(button); + /* Execution control panel (south of source code panel) */ + + /* Layout */ + mainPane = new JTabbedPane(); + + sourceCodeUI = new CodeUI(watchpointMote); + JPanel sourceCodePanel = new JPanel(new BorderLayout()); + sourceCodePanel.add(BorderLayout.CENTER, sourceCodeUI); + sourceCodePanel.add(BorderLayout.SOUTH, sourceCodeControl); + mainPane.addTab("Source code", null, sourceCodePanel, null); /* SOURCECODE */ - - /* Main components: assembler and C code + breakpoints (center) */ assCodeUI = new DebugUI(this.mspMote.getCPU(), true); - breakpointsUI = new BreakpointsUI(breakpoints, this); - sourceCodeUI = new CodeUI(breakpoints); - leftSplitPane = new JSplitPane( - JSplitPane.HORIZONTAL_SPLIT, - new JScrollPane(assCodeUI), - new JScrollPane(breakpointsUI) - ); - leftSplitPane.setOneTouchExpandable(true); - leftSplitPane.setDividerLocation(0.0); - rightSplitPane = new JSplitPane( - JSplitPane.HORIZONTAL_SPLIT, - leftSplitPane, - new JScrollPane(sourceCodeUI) - ); - rightSplitPane.setOneTouchExpandable(true); - rightSplitPane.setDividerLocation(0.0); + for (Component c: assCodeUI.getComponents()) { + c.setBackground(Color.WHITE); + } + mainPane.addTab("Instructions", null, assCodeUI, null); - add(BorderLayout.NORTH, browseBox); - add(BorderLayout.CENTER, rightSplitPane); - add(BorderLayout.SOUTH, controlPanel); + breakpointsUI = new BreakpointsUI(mspMote, this); + mainPane.addTab("Breakpoints", null, breakpointsUI, "Right-click source code to add"); /* BREAKPOINTS */ + + add(BorderLayout.CENTER, mainPane); + + /* Listen for breakpoint changes */ + watchpointMote.addWatchpointListener(watchpointListener = new WatchpointListener() { + public void watchpointTriggered(final Watchpoint watchpoint) { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + logger.info("Watchpoint triggered: " + watchpoint); + if (simulation.isRunning()) { + return; + } + breakpointsUI.selectBreakpoint(watchpoint); + sourceCodeUI.updateBreakpoints(); + showCurrentPC(); + } + }); + } + public void watchpointsChanged() { + sourceCodeUI.updateBreakpoints(); + } + }); - /* Observe when simulation starts/stops */ simulation.addObserver(simObserver = new Observer() { public void update(Observable obs, Object obj) { if (!simulation.isRunning()) { stepAction.setEnabled(true); - updateInfo(); + showCurrentPC(); } else { stepAction.setEnabled(false); } @@ -208,7 +220,7 @@ public class MspCodeWatcher extends VisPlugin implements MotePlugin { }); setSize(750, 500); - updateInfo(); + showCurrentPC(); } private void updateFileComboBox() { @@ -221,25 +233,12 @@ public class MspCodeWatcher extends VisPlugin implements MotePlugin { fileComboBox.setSelectedIndex(0); } - public void displaySourceFile(File file, final int line) { - if (file != null && - sourceCodeUI.displayedFile != null && - file.compareTo(sourceCodeUI.displayedFile) == 0) { - /* No need to reload source file */ - SwingUtilities.invokeLater(new Runnable() { - public void run() { - sourceCodeUI.displayLine(line); - } - }); - return; - } - - /* Load source file from disk */ - String[] codeData = readTextFile(file); - if (codeData == null) { - return; - } - sourceCodeUI.displayNewCode(file, codeData, line); + public void displaySourceFile(final File file, final int line, final boolean markCurrent) { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + mainPane.setSelectedIndex(SOURCECODE); /* code */ + sourceCodeUI.displayNewCode(file, line, markCurrent); + }}); } private void sourceFileSelectionChanged() { @@ -249,32 +248,40 @@ public class MspCodeWatcher extends VisPlugin implements MotePlugin { } File selectedFile = sourceFiles[index-1]; - displaySourceFile(selectedFile, -1); + displaySourceFile(selectedFile, -1, false); } - private void updateInfo() { + private void showCurrentPC() { /* Instructions */ assCodeUI.updateRegs(); assCodeUI.repaint(); /* Source */ updateCurrentSourceCodeFile(); - if (currentCodeFile == null) { + File file = currentCodeFile; + Integer line = currentLineNumber; + if (file == null || line == null) { currentFileAction.setEnabled(false); currentFileAction.putValue(Action.NAME, "[unknown]"); currentFileAction.putValue(Action.SHORT_DESCRIPTION, null); return; } currentFileAction.setEnabled(true); - currentFileAction.putValue(Action.NAME, currentCodeFile.getName() + ":" + currentLineNumber); - currentFileAction.putValue(Action.SHORT_DESCRIPTION, currentCodeFile.getAbsolutePath() + ":" + currentLineNumber); - fileComboBox.setSelectedItem(currentCodeFile.getName()); + currentFileAction.putValue(Action.NAME, file.getName() + ":" + line); + currentFileAction.putValue(Action.SHORT_DESCRIPTION, file.getAbsolutePath() + ":" + line); + fileComboBox.setSelectedItem(file.getName()); - displaySourceFile(currentCodeFile, currentLineNumber); + displaySourceFile(file, line, true); } public void closePlugin() { + watchpointMote.removeWatchpointListener(watchpointListener); + watchpointListener = null; + simulation.deleteObserver(simObserver); + simObserver = null; + + /* TODO XXX Unregister breakpoints? */ } private void updateCurrentSourceCodeFile() { @@ -285,8 +292,12 @@ public class MspCodeWatcher extends VisPlugin implements MotePlugin { if (debug == null) { return; } - DebugInfo debugInfo = debug.getDebugInfo(mspMote.getCPU().reg[MSP430.PC]); + int pc = mspMote.getCPU().getPC(); + DebugInfo debugInfo = debug.getDebugInfo(pc); if (debugInfo == null) { + if (pc != 0) { + logger.warn("No sourcecode info at " + String.format("0x%04x", mspMote.getCPU().getPC())); + } return; } @@ -321,6 +332,7 @@ public class MspCodeWatcher extends VisPlugin implements MotePlugin { private void tryMapDebugInfo() { final String[] debugFiles; try { + ELFDebug debug = ((MspMoteType)mspMote.getType()).getELF().getDebug(); debugFiles = debug != null ? debug.getSourceFiles() : null; if (debugFiles == null) { @@ -343,7 +355,7 @@ public class MspCodeWatcher extends VisPlugin implements MotePlugin { "\"Next File\" proceeds to the next source file in the debug info.\n\n" + debugFiles[counter] + " (" + (counter+1) + '/' + debugFiles.length + ')', "Select source file to locate", JOptionPane.YES_NO_CANCEL_OPTION, - JOptionPane.QUESTION_MESSAGE, null, + JOptionPane.QUESTION_MESSAGE, null, new String[] { "Next File", "Locate File", "Cancel"}, "Next File"); if (n == JOptionPane.CANCEL_OPTION || n == JOptionPane.CLOSED_OPTION) { return null; @@ -421,14 +433,14 @@ public class MspCodeWatcher extends VisPlugin implements MotePlugin { optionPane.setOptions(new String[] { "OK" }); optionPane.setInitialValue("OK"); JDialog dialog = optionPane.createDialog( - GUI.getTopParentContainer(), - "Mapping debug info to real sources"); + GUI.getTopParentContainer(), + "Mapping debug info to real sources"); dialog.setVisible(true); - + replace = replaceInput.getText(); replacement = replacementInput.getText(); } - + replace = replace.replace('\\', '/'); replacement = replacement.replace('\\', '/'); return new String[] { replace, replacement }; @@ -444,7 +456,7 @@ public class MspCodeWatcher extends VisPlugin implements MotePlugin { updateFileComboBox(); } } - + private static File[] getSourceFiles(MspMote mote, String[] map) { final String[] sourceFiles; try { @@ -465,7 +477,7 @@ public class MspCodeWatcher extends VisPlugin implements MotePlugin { } catch (IOException e1) { } } - + /* Verify that files exist */ ArrayList existing = new ArrayList(); for (String sourceFile: sourceFiles) { @@ -512,7 +524,7 @@ public class MspCodeWatcher extends VisPlugin implements MotePlugin { "Make sure the source files were not moved after the firmware compilation.\n" + "\n" + "If you want to manually locate the sources, click \"Map\" button.", - "No source files found", + "No source files found", JOptionPane.WARNING_MESSAGE); return true; } @@ -530,7 +542,7 @@ public class MspCodeWatcher extends VisPlugin implements MotePlugin { } sorted.add(index, file); } - + /* Add Contiki source first */ if (contikiSource != null && contikiSource.exists()) { sorted.add(0, contikiSource); @@ -539,63 +551,21 @@ public class MspCodeWatcher extends VisPlugin implements MotePlugin { return sorted.toArray(new File[0]); } - /** - * Tries to open and read given text file. - * - * @param file File - * @return Line-by-line text in file - */ - public static String[] readTextFile(File file) { - if (GUI.isVisualizedInApplet()) { - /* Download from web server instead */ - String path = file.getPath(); - - /* Extract Contiki build path */ - String contikiBuildPath = GUI.getExternalToolsSetting("PATH_CONTIKI_BUILD"); - String contikiWebPath = GUI.getExternalToolsSetting("PATH_CONTIKI_WEB"); - - if (!path.startsWith(contikiBuildPath)) { - return null; - } - - try { - /* Replace Contiki parent path with web server code base */ - path = contikiWebPath + '/' + path.substring(contikiBuildPath.length()); - path = path.replace('\\', '/'); - URL url = new URL(GUI.getAppletCodeBase(), path); - String data = StringUtils.loadFromURL(url); - return data!=null?data.split("\n"):null; - } catch (MalformedURLException e) { - logger.warn("Failure to read source code: " + e); - return null; - } - } - - String data = StringUtils.loadFromFile(file); - return data!=null?data.split("\n"):null; - } - public Collection getConfigXML() { - Vector config = new Vector(); + ArrayList config = new ArrayList(); Element element; - - element = new Element("split_1"); - element.addContent("" + leftSplitPane.getDividerLocation()); + + element = new Element("tab"); + element.addContent("" + mainPane.getSelectedIndex()); config.add(element); - - element = new Element("split_2"); - element.addContent("" + rightSplitPane.getDividerLocation()); - config.add(element); - + return config; } public boolean setConfigXML(Collection configXML, boolean visAvailable) { for (Element element : configXML) { - if (element.getName().equals("split_1")) { - leftSplitPane.setDividerLocation(Integer.parseInt(element.getText())); - } else if (element.getName().equals("split_2")) { - rightSplitPane.setDividerLocation(Integer.parseInt(element.getText())); + if (element.getName().equals("tab")) { + mainPane.setSelectedIndex(Integer.parseInt(element.getText())); } } return true; @@ -608,11 +578,11 @@ public class MspCodeWatcher extends VisPlugin implements MotePlugin { if (currentCodeFile == null) { return; } - displaySourceFile(currentCodeFile, currentLineNumber); + displaySourceFile(currentCodeFile, currentLineNumber, true); } }; - private AbstractAction mapAction = new AbstractAction("Map") { + private AbstractAction mapAction = new AbstractAction("Locate sources") { private static final long serialVersionUID = -3929432830596292495L; public void actionPerformed(ActionEvent e) { @@ -622,14 +592,13 @@ public class MspCodeWatcher extends VisPlugin implements MotePlugin { private AbstractAction stepAction = new AbstractAction("Step instruction") { private static final long serialVersionUID = 3520750710757816575L; - public void actionPerformed(ActionEvent e) { try { mspMote.getCPU().stepInstructions(1); } catch (EmulationException ex) { logger.fatal("Error: ", ex); } - updateInfo(); + showCurrentPC(); } }; diff --git a/tools/cooja/build.xml b/tools/cooja/build.xml index 3ad01fb00..ac98ecce7 100644 --- a/tools/cooja/build.xml +++ b/tools/cooja/build.xml @@ -50,6 +50,7 @@ The COOJA Simulator + @@ -62,6 +63,7 @@ The COOJA Simulator + @@ -74,6 +76,7 @@ The COOJA Simulator + @@ -104,6 +107,7 @@ The COOJA Simulator + @@ -118,6 +122,7 @@ The COOJA Simulator + @@ -131,6 +136,7 @@ The COOJA Simulator + @@ -144,6 +150,7 @@ The COOJA Simulator + @@ -156,6 +163,7 @@ The COOJA Simulator + @@ -170,6 +178,7 @@ The COOJA Simulator + @@ -190,6 +199,7 @@ The COOJA Simulator + @@ -214,7 +224,7 @@ The COOJA Simulator - + diff --git a/tools/cooja/java/se/sics/cooja/GUI.java b/tools/cooja/java/se/sics/cooja/GUI.java index 091592634..3d2227f8e 100644 --- a/tools/cooja/java/se/sics/cooja/GUI.java +++ b/tools/cooja/java/se/sics/cooja/GUI.java @@ -34,6 +34,7 @@ import java.awt.Color; import java.awt.Component; import java.awt.Container; import java.awt.Dialog; +import java.awt.Dialog.ModalityType; import java.awt.Dimension; import java.awt.Frame; import java.awt.GraphicsDevice; @@ -41,7 +42,6 @@ import java.awt.GraphicsEnvironment; import java.awt.Point; import java.awt.Rectangle; import java.awt.Window; -import java.awt.Dialog.ModalityType; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ComponentAdapter; @@ -271,7 +271,7 @@ public class GUI extends Observable { "COMMAND_DATA_START", "COMMAND_DATA_END", "COMMAND_BSS_START", "COMMAND_BSS_END", "COMMAND_COMMON_START", "COMMAND_COMMON_END", - + "HIDE_WARNINGS" }; @@ -299,7 +299,7 @@ public class GUI extends Observable { private Vector startedPlugins = new Vector(); private ArrayList guiActions = new ArrayList(); - + // Platform configuration variables // Maintained via method reparseProjectConfig() private ProjectConfig projectConfig; @@ -380,12 +380,12 @@ public class GUI extends Observable { quickHelpScroll = new JScrollPane(quickHelpTextPane, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); quickHelpScroll.setPreferredSize(new Dimension(200, 0)); quickHelpScroll.setBorder(BorderFactory.createCompoundBorder( - BorderFactory.createLineBorder(Color.GRAY), + BorderFactory.createLineBorder(Color.GRAY), BorderFactory.createEmptyBorder(0, 3, 0, 0) )); quickHelpScroll.setVisible(false); loadQuickHelp("KEYBOARD_SHORTCUTS"); - + // Load default and overwrite with user settings (if any) loadExternalToolsDefaultSettings(); loadExternalToolsUserSettings(); @@ -597,7 +597,7 @@ public class GUI extends Observable { menu.add(lastItem); } } - + private void doLoadConfigAsync(final boolean ask, final boolean quick, final File file) { new Thread(new Runnable() { public void run() { @@ -646,7 +646,7 @@ public class GUI extends Observable { for (GUIAction a: guiActions) { a.setEnabled(a.shouldBeEnabled()); } - + /* Mote and mote type menues */ if (menuMoteTypeClasses != null) { menuMoteTypeClasses.setEnabled(getSimulation() != null); @@ -655,7 +655,7 @@ public class GUI extends Observable { menuMoteTypes.setEnabled(getSimulation() != null); } } - + private JMenuBar createMenuBar() { JMenuBar menuBar = new JMenuBar(); JMenu menu; @@ -673,7 +673,7 @@ public class GUI extends Observable { guiActions.add(startStopSimulationAction); guiActions.add(removeAllMotesAction); guiActions.add(showBufferSettingsAction); - + /* File menu */ menu = new JMenu("File"); menu.addMenuListener(new MenuListener() { @@ -733,7 +733,7 @@ public class GUI extends Observable { }); menu.setMnemonic(KeyEvent.VK_S); menuBar.add(menu); - + menu.add(new JMenuItem(startStopSimulationAction)); GUIAction guiAction = new StartPluginGUIAction("Control panel"); @@ -929,7 +929,7 @@ public class GUI extends Observable { menuItem.setEnabled(false); menuItem.setToolTipText("Not available in applet version"); } - + menuItem = new JMenuItem("Contiki mote configuration wizard"); menuItem.setActionCommand("configuration wizard"); menuItem.addActionListener(guiEventHandler); @@ -940,7 +940,7 @@ public class GUI extends Observable { } menu.add(new JMenuItem(showBufferSettingsAction)); - + /* Help */ menu = new JMenu("Help"); menu.setMnemonic(KeyEvent.VK_H); @@ -950,7 +950,7 @@ public class GUI extends Observable { menu.add(checkBox); menuBar.add(menu); - menu.addSeparator(); + menu.addSeparator(); menuItem = new JMenuItem("Java version: " + System.getProperty("java.version") + " (" @@ -965,7 +965,7 @@ public class GUI extends Observable { + System.getProperty("sun.arch.data.model")); menuItem.setEnabled(false); menu.add(menuItem); - + // Mote plugins popup menu (not available via menu bar) if (menuMotePluginClasses == null) { menuMotePluginClasses = new Vector>(); @@ -1356,7 +1356,7 @@ public class GUI extends Observable { unregisterPositioners(); unregisterRadioMediums(); projectDirClassLoader = null; - + /* Build cooja configuration */ try { projectConfig = new ProjectConfig(true); @@ -1381,7 +1381,7 @@ public class GUI extends Observable { "Error when reading project config: " + e.getMessage()).initCause(e); } } - + /* Create project class loader */ try { projectDirClassLoader = createClassLoader(currentProjects); @@ -1585,7 +1585,7 @@ public class GUI extends Observable { * Same as the {@link #startPlugin(Class, GUI, Simulation, Mote)} method, * but does not throw exceptions. If COOJA is visualised, an error dialog * is shown if plugin could not be started. - * + * * @see #startPlugin(Class, GUI, Simulation, Mote) * @param pluginClass Plugin class * @param argGUI Plugin GUI argument @@ -1609,7 +1609,7 @@ public class GUI extends Observable { return null; } } while (cause != null && (cause=cause.getCause()) != null); - + logger.fatal("Error when starting plugin", ex); } } @@ -1622,15 +1622,15 @@ public class GUI extends Observable { } public Plugin startPlugin(final Class pluginClass, - final GUI argGUI, final Simulation argSimulation, final Mote argMote) - throws PluginConstructionException + final GUI argGUI, final Simulation argSimulation, final Mote argMote) + throws PluginConstructionException { return startPlugin(pluginClass, argGUI, argSimulation, argMote, true); } /** * Starts given plugin. If visualized, the plugin is also shown. - * + * * @see PluginType * @param pluginClass Plugin class * @param argGUI Plugin GUI argument @@ -1665,7 +1665,7 @@ public class GUI extends Observable { throw new PluginConstructionException("No mote argument for mote plugin"); } - plugin = + plugin = pluginClass.getConstructor(new Class[] { Mote.class, Simulation.class, GUI.class }) .newInstance(argMote, argSimulation, argGUI); @@ -1678,7 +1678,7 @@ public class GUI extends Observable { throw new PluginConstructionException("No simulation argument for simulation plugin"); } - plugin = + plugin = pluginClass.getConstructor(new Class[] { Simulation.class, GUI.class }) .newInstance(argSimulation, argGUI); @@ -1717,7 +1717,7 @@ public class GUI extends Observable { if (activate && plugin.getGUI() != null) { myGUI.showPlugin(plugin); } - + return plugin; } @@ -1807,7 +1807,7 @@ public class GUI extends Observable { // Create 'start plugin'-menu item JMenuItem menuItem; String tooltip = ""; - + /* Sort menu according to plugin type */ int itemIndex=0; if (pluginType == PluginType.COOJA_PLUGIN || pluginType == PluginType.COOJA_STANDARD_PLUGIN) { @@ -1892,7 +1892,7 @@ public class GUI extends Observable { /** * Returns started plugin that ends with given class name, if any. - * + * * @param classname Class name * @return Plugin instance */ @@ -1904,10 +1904,10 @@ public class GUI extends Observable { } return null; } - + /** * Returns started plugin with given class name, if any. - * + * * @param classname Class name * @return Plugin instance * @deprecated @@ -1977,21 +1977,21 @@ public class GUI extends Observable { /** * Creates a new mote type of the given mote type class. * This may include displaying a dialog for user configurations. - * + * * If mote type is created successfully, the add motes dialog will appear. - * + * * @param moteTypeClass Mote type class */ public void doCreateMoteType(Class moteTypeClass) { doCreateMoteType(moteTypeClass, true); } - + /** * Creates a new mote type of the given mote type class. * This may include displaying a dialog for user configurations. - * + * * @param moteTypeClass Mote type class - * @param addMotes Show add motes dialog after successfully adding mote type + * @param addMotes Show add motes dialog after successfully adding mote type */ public void doCreateMoteType(Class moteTypeClass, boolean addMotes) { if (mySimulation == null) { @@ -2236,7 +2236,7 @@ public class GUI extends Observable { PROGRESS_WARNINGS.clear(); newSim = loadSimulationConfig(fileToLoad, quick); myGUI.setSimulation(newSim, false); - + /* Optionally show compilation warnings */ boolean hideWarn = Boolean.parseBoolean( GUI.getExternalToolsSetting("HIDE_WARNINGS", "false") @@ -2245,7 +2245,7 @@ public class GUI extends Observable { showWarningsDialog(frame, PROGRESS_WARNINGS.toArray(new String[0])); } PROGRESS_WARNINGS.clear(); - + } catch (UnsatisfiedLinkError e) { shouldRetry = showErrorDialog(GUI.getTopParentContainer(), "Simulation load error", e, true); } catch (SimulationCreationException e) { @@ -2276,7 +2276,7 @@ public class GUI extends Observable { if (warnMemory()) { return; } - + final JDialog progressDialog = new JDialog(frame, "Reloading", true); final Thread loadThread = new Thread(new Runnable() { public void run() { @@ -2305,7 +2305,7 @@ public class GUI extends Observable { if (autoStart) { newSim.startSimulation(); } - + /* Optionally show compilation warnings */ boolean hideWarn = Boolean.parseBoolean( GUI.getExternalToolsSetting("HIDE_WARNINGS", "false") @@ -2314,7 +2314,7 @@ public class GUI extends Observable { showWarningsDialog(frame, PROGRESS_WARNINGS.toArray(new String[0])); } PROGRESS_WARNINGS.clear(); - + } catch (UnsatisfiedLinkError e) { shouldRetry = showErrorDialog(frame, "Simulation reload error", e, true); @@ -2459,7 +2459,7 @@ public class GUI extends Observable { return saveFile; } else { JOptionPane.showMessageDialog( - getTopParentContainer(), "No write access to " + saveFile, "Save failed", + getTopParentContainer(), "No write access to " + saveFile, "Save failed", JOptionPane.ERROR_MESSAGE); logger.fatal("No write access to file: " + saveFile.getAbsolutePath()); } @@ -2757,8 +2757,8 @@ public class GUI extends Observable { ExternalToolsDialog.showDialog(GUI.getTopParentContainer()); } else if (e.getActionCommand().equals("manage projects")) { COOJAProject[] newProjects = ProjectDirectoriesDialog.showDialog( - GUI.getTopParentContainer(), - GUI.this, + GUI.getTopParentContainer(), + GUI.this, getProjects() ); if (newProjects != null) { @@ -3029,7 +3029,7 @@ public class GUI extends Observable { System.exit(1); } GUI gui = sim.getGUI(); - + /* Make sure at least one test editor is controlling the simulation */ boolean hasEditor = false; for (Plugin startedPlugin : gui.startedPlugins) { @@ -3051,7 +3051,12 @@ public class GUI extends Observable { System.exit(1); } plugin.updateScript(scriptFile); - plugin.setScriptActive(true); + try { + plugin.setScriptActive(true); + } catch (Exception e) { + logger.fatal("Error: " + e.getMessage(), e); + System.exit(1); + } sim.setDelayTime(0); sim.startSimulation(); } else { @@ -3059,7 +3064,7 @@ public class GUI extends Observable { System.exit(1); } } - + } else if (args.length > 0 && args[0].startsWith("-applet")) { String tmpWebPath=null, tmpBuildPath=null, tmpEsbFirmware=null, tmpSkyFirmware=null; @@ -3258,11 +3263,11 @@ public class GUI extends Observable { // Create and write to document Document doc = new Document(extractSimulationConfig()); OutputStream out = new FileOutputStream(file); - + if (file.getName().endsWith(".gz")) { out = new GZIPOutputStream(out); } - + XMLOutputter outputter = new XMLOutputter(); outputter.setFormat(Format.getPrettyFormat()); outputter.output(doc, out); @@ -3274,7 +3279,7 @@ public class GUI extends Observable { e.printStackTrace(); } } - + public Element extractSimulationConfig() { // Create simulation config Element root = new Element("simconf"); @@ -3391,7 +3396,7 @@ public class GUI extends Observable { projectFile = projectFile.getCanonicalFile(); } catch (IOException e) { } - + boolean found = false; for (COOJAProject currentProject: currentProjects) { if (projectFile.getPath().replaceAll("\\\\", "/"). @@ -3473,7 +3478,7 @@ public class GUI extends Observable { /* Activate plugin */ startedPlugin.startPlugin(); - + /* If Cooja not visualized, ignore window configuration */ if (startedPlugin.getGUI() == null) { continue; @@ -3511,7 +3516,7 @@ public class GUI extends Observable { pluginGUI.setIcon(true); } catch (PropertyVetoException e) { } - }; + }; }); } } @@ -3618,7 +3623,7 @@ public class GUI extends Observable { list.addPopupMenuItem(null, true); tabbedPane.addTab("Contiki error", new JScrollPane(list)); } - + /* Compilation output */ MessageList compilationOutput = null; if (exception instanceof MoteTypeCreationException @@ -3704,7 +3709,7 @@ public class GUI extends Observable { private static void showWarningsDialog(final Frame parent, final String[] warnings) { new RunnableInEDT() { public Boolean work() { - final JDialog dialog = new JDialog((Frame)parent, "Compilation warnings", false); + final JDialog dialog = new JDialog(parent, "Compilation warnings", false); Box buttonBox = Box.createHorizontalBox(); /* Warnings message list */ @@ -3748,7 +3753,7 @@ public class GUI extends Observable { } }.invokeAndWait(); } - + /** * Runs work method in event dispatcher thread. * Worker method returns a value. @@ -3885,9 +3890,9 @@ public class GUI extends Observable { /** * Tries to convert given file to be "portable". * The portable path is either relative to Contiki, or to the configuration (.csc) file. - * + * * If this method fails, it returns the original file. - * + * * @param file Original file * @return Portable file, or original file is conversion failed */ @@ -3897,7 +3902,7 @@ public class GUI extends Observable { public File createPortablePath(File file, boolean allowConfigRelativePaths) { File portable = null; - + portable = createContikiRelativePath(file); if (portable != null) { /*logger.info("Generated Contiki relative path '" + file.getPath() + "' to '" + portable.getPath() + "'");*/ @@ -3911,7 +3916,7 @@ public class GUI extends Observable { return portable; } } - + logger.warn("Path is not portable: '" + file.getPath()); return file; } @@ -3919,7 +3924,7 @@ public class GUI extends Observable { /** * Tries to restore a previously "portable" file to be "absolute". * If the given file already exists, no conversion is performed. - * + * * @see #createPortablePath(File) * @param file Portable file * @return Absolute file @@ -3942,7 +3947,7 @@ public class GUI extends Observable { /*logger.info("Restored config relative path '" + file.getPath() + "' to '" + absolute.getPath() + "'");*/ return absolute; } - + /*logger.info("Portable path was not restored: '" + file.getPath());*/ return file; } @@ -3962,10 +3967,10 @@ public class GUI extends Observable { /* Replace Contiki's canonical path with Contiki identifier */ String portablePath = fileCanonical.replaceFirst( - java.util.regex.Matcher.quoteReplacement(contikiCanonical), + java.util.regex.Matcher.quoteReplacement(contikiCanonical), java.util.regex.Matcher.quoteReplacement(PATH_CONTIKI_IDENTIFIER)); File portable = new File(portablePath); - + /* Verify conversion */ File verify = restoreContikiRelativePath(portable); if (verify == null || !verify.exists()) { @@ -4028,10 +4033,10 @@ public class GUI extends Observable { /* Replace config's canonical path with config identifier */ String portablePath = fileCanonical.replaceFirst( - java.util.regex.Matcher.quoteReplacement(configCanonical), + java.util.regex.Matcher.quoteReplacement(configCanonical), java.util.regex.Matcher.quoteReplacement(id)); File portable = new File(portablePath); - + /* Verify conversion */ File verify = restoreConfigRelativePath(portable); if (verify == null || !verify.exists()) { @@ -4087,11 +4092,11 @@ public class GUI extends Observable { */ public String getQuickHelp(); } - + /** * Load quick help for given object or identifier. Note that this method does not * show the quick help pane. - * + * * @param obj If string: help identifier. Else, the class name of the argument * is used as help identifier. */ @@ -4106,7 +4111,7 @@ public class GUI extends Observable { } else { key = obj.getClass().getName(); } - + String help = null; if (obj instanceof HasQuickHelp) { help = ((HasQuickHelp) obj).getQuickHelp(); @@ -4292,13 +4297,13 @@ public class GUI extends Observable { } outputFile.delete(); } - + final File finalOutputFile = outputFile; setExternalToolsSetting("EXECUTE_JAR_LAST", outputFile.getPath()); new Thread() { public void run() { try { - ExecuteJAR.buildExecutableJAR(GUI.this, finalOutputFile); + ExecuteJAR.buildExecutableJAR(GUI.this, finalOutputFile); } catch (RuntimeException ex) { JOptionPane.showMessageDialog(GUI.getTopParentContainer(), ex.getMessage(), @@ -4359,7 +4364,7 @@ public class GUI extends Observable { public void actionPerformed(final ActionEvent e) { new Thread(new Runnable() { public void run() { - Class pluginClass = + Class pluginClass = (Class) ((JMenuItem) e.getSource()).getClientProperty("class"); Mote mote = (Mote) ((JMenuItem) e.getSource()).getClientProperty("mote"); tryStartPlugin(pluginClass, myGUI, mySimulation, mote); @@ -4434,5 +4439,5 @@ public class GUI extends Observable { return mySimulation != null; } }; - + } diff --git a/tools/cooja/java/se/sics/cooja/Watchpoint.java b/tools/cooja/java/se/sics/cooja/Watchpoint.java index f266d5194..c65182a94 100644 --- a/tools/cooja/java/se/sics/cooja/Watchpoint.java +++ b/tools/cooja/java/se/sics/cooja/Watchpoint.java @@ -32,24 +32,26 @@ package se.sics.cooja; import java.awt.Color; +import java.io.File; /** * @author Fredrik Osterlind */ public interface Watchpoint { - - /** - * @return Short watchpoint description - */ - public String getDescription(); - /** - * @return Mote - */ - public Mote getMote(); - - /** - * @return Color - */ + public WatchpointMote getMote(); + public Color getColor(); + public void setColor(Color newColor); + + public String getDescription(); + public void setUserMessage(String msg); + public String getUserMessage(); + + public File getCodeFile(); + public int getLineNumber(); + public int getExecutableAddress(); + + public void setStopsSimulation(boolean b); + public boolean stopsSimulation(); } diff --git a/tools/cooja/java/se/sics/cooja/WatchpointMote.java b/tools/cooja/java/se/sics/cooja/WatchpointMote.java index 970c96a40..ba5886213 100644 --- a/tools/cooja/java/se/sics/cooja/WatchpointMote.java +++ b/tools/cooja/java/se/sics/cooja/WatchpointMote.java @@ -31,12 +31,17 @@ package se.sics.cooja; -import java.awt.event.ActionListener; +import java.io.File; /** * @author Fredrik Osterlind */ -public interface WatchpointMote { +public interface WatchpointMote extends Mote { + + public interface WatchpointListener { + public void watchpointTriggered(Watchpoint watchpoint); + public void watchpointsChanged(); + } /** * Adds a breakpoint listener. @@ -44,28 +49,27 @@ public interface WatchpointMote { * * @param listener Action listener */ - public void addWatchpointListener(ActionListener listener); + public void addWatchpointListener(WatchpointListener listener); /** * Removes previously registered listener. - * + * * @param listener Listeners */ - public void removeWatchpointListener(ActionListener listener); + public void removeWatchpointListener(WatchpointListener listener); /** * @return All registered listeners */ - public ActionListener[] getWatchpointListeners(); + public WatchpointListener[] getWatchpointListeners(); - /** - * @return Last triggered watchpoint - */ - public Watchpoint getLastWatchpoint(); + public Watchpoint addBreakpoint(File codeFile, int lineNr, int address); + public void removeBreakpoint(Watchpoint watchpoint); + public Watchpoint[] getBreakpoints(); - /** - * @return Mote - */ - public Mote getMote(); + public boolean breakpointExists(int address); + public boolean breakpointExists(File file, int lineNr); + + public Integer getExecutableAddressOf(File file, int lineNr); } diff --git a/tools/cooja/java/se/sics/cooja/plugins/LogScriptEngine.java b/tools/cooja/java/se/sics/cooja/plugins/LogScriptEngine.java index 5a6fd82fd..2e867da80 100644 --- a/tools/cooja/java/se/sics/cooja/plugins/LogScriptEngine.java +++ b/tools/cooja/java/se/sics/cooja/plugins/LogScriptEngine.java @@ -64,9 +64,9 @@ public class LogScriptEngine { private static Logger logger = Logger.getLogger(LogScriptEngine.class); private static final long DEFAULT_TIMEOUT = 20*60*1000*Simulation.MILLISECOND; /* 1200s = 20 minutes */ - private ScriptEngine engine = + private ScriptEngine engine = new ScriptEngineManager().getEngineByName("JavaScript"); - + /* Log output listener */ private LogOutputListener logOutputListener = new LogOutputListener() { public void moteWasAdded(Mote mote) { @@ -97,6 +97,11 @@ public class LogScriptEngine { private boolean scriptActive = false; + private long timeout; + private long startTime; + private long startRealTime; + private long nextProgress; + private interface ScriptLog { public void log(String log); public void testOK(); @@ -104,6 +109,10 @@ public class LogScriptEngine { public void generateMessage(long delay, String msg); } + public LogScriptEngine(Simulation simulation) { + this.simulation = simulation; + } + /* Only called from the simulation loop */ private void stepScript() { /* Release script - halt simulation */ @@ -130,10 +139,6 @@ public class LogScriptEngine { } } - public LogScriptEngine(Simulation simulation) { - this.simulation = simulation; - } - /* Only called from the simulation loop */ private void handleNewMoteOutput(Mote mote, int id, long time, String msg) { try { @@ -195,37 +200,31 @@ public class LogScriptEngine { } scriptActive = false; - if (semaphoreScript == null) { - /*logger.warn("semaphoreScript is not initialized");*/ - } - if (semaphoreSim == null) { - /*logger.warn("semaphoreSim is not initialized");*/ - } - if (scriptThread == null) { - /*logger.warn("scriptThread is not initialized");*/ - } - timeoutEvent.remove(); timeoutProgressEvent.remove(); - + simulation.getEventCentral().removeLogOutputListener(logOutputListener); engine.put("SHUTDOWN", true); try { - semaphoreScript.release(100); + if (semaphoreScript != null) { + semaphoreScript.release(100); + } } catch (Exception e) { } finally { semaphoreScript = null; } try { - semaphoreSim.release(100); + if (semaphoreSim != null) { + semaphoreSim.release(100); + } } catch (Exception e) { } finally { semaphoreSim = null; } - if (scriptThread != null && + if (scriptThread != null && scriptThread != Thread.currentThread() /* XXX May deadlock */ ) { try { scriptThread.join(); @@ -235,7 +234,6 @@ public class LogScriptEngine { } } scriptThread = null; - } public void activateScript(String scriptCode) throws ScriptException { @@ -245,43 +243,29 @@ public class LogScriptEngine { scriptActive = true; if (semaphoreScript != null) { - logger.warn("semaphoreScript is already initialized"); + logger.warn("Semaphores were not reset correctly"); + semaphoreScript.release(100); + semaphoreScript = null; } if (semaphoreSim != null) { - logger.warn("semaphoreSim is already initialized"); - } - if (scriptThread != null) { - logger.warn("scriptThread is already initialized"); + logger.warn("Semaphores were not reset correctly"); + semaphoreSim.release(100); + semaphoreSim = null; } + scriptThread = null; /* Parse current script */ ScriptParser parser = new ScriptParser(scriptCode); String jsCode = parser.getJSCode(); - long timeoutTime = parser.getTimeoutTime(); - if (timeoutTime < 0) { - logger.info("No timeout defined, using default (us): " + DEFAULT_TIMEOUT); - timeoutTime = DEFAULT_TIMEOUT; + timeout = parser.getTimeoutTime(); + if (timeout < 0) { + timeout = DEFAULT_TIMEOUT; + logger.info("Default script timeout in " + (timeout/Simulation.MILLISECOND) + " ms"); + } else { + logger.info("Script timeout in " + (timeout/Simulation.MILLISECOND) + " ms"); } - final long duration = timeoutTime; - simulation.invokeSimulationThread(new Runnable() { - public void run() { - final long startTime = simulation.getSimulationTime(); - final long interval = (long) (0.01*5*duration); - - simulation.scheduleEvent(timeoutProgressEvent = new TimeEvent(0) { - public void execute(long t) { - int percent = (int) (5*(t-startTime)/interval); - logger.info("Test script at " + percent + "%"); - simulation.scheduleEvent(this, t+interval); - } - }, startTime+interval); - - simulation.scheduleEvent(timeoutEvent, startTime + duration); - } - }); - engine.eval(jsCode); /* Setup script control */ @@ -352,95 +336,7 @@ public class LogScriptEngine { simulation.getEventCentral().addLogOutputListener(logOutputListener); /* Create script output logger */ - engine.put("log", new ScriptLog() { - public void log(String msg) { - if (scriptLogObserver != null) { - scriptLogObserver.update(null, msg); - } - } - public void append(String filename, String msg) { - try{ - FileWriter fstream = new FileWriter(filename, true); - BufferedWriter out = new BufferedWriter(fstream); - out.write(msg); - out.close(); - } catch (Exception e) { - logger.warn("Test append failed: " + filename + ": " + e.getMessage()); - } - } - public void testOK() { - log("TEST OK\n"); - - if (GUI.isVisualized()) { - log("[if test was run without visualization, COOJA would now have been terminated]\n"); - stopSimulation = true; - simulation.invokeSimulationThread(stopSimulationRunnable); - } else { - quitCooja = true; - simulation.invokeSimulationThread(quitRunnable); - } - - timeoutEvent.remove(); - timeoutProgressEvent.remove(); - - semaphoreSim.release(100); - throw new RuntimeException("test script killed"); - } - public void writeFile(String filename, String msg) { - try{ - FileWriter fstream = new FileWriter(filename, false); - BufferedWriter out = new BufferedWriter(fstream); - out.write(msg); - out.close(); - } catch (Exception e) { - logger.warn("Write file failed: " + filename + ": " + e.getMessage()); - } - } - public void testFailed() { - log("TEST FAILED\n"); - - if (GUI.isVisualized()) { - log("[if test was run without visualization, COOJA would now have been terminated]\n"); - stopSimulation = true; - simulation.invokeSimulationThread(stopSimulationRunnable); - } else { - quitCooja = true; - simulation.invokeSimulationThread(quitRunnable); - } - - semaphoreSim.release(100); - throw new RuntimeException("test script killed"); - } - - public void generateMessage(final long delay, final String msg) { - final Mote currentMote = (Mote) engine.get("mote"); - final TimeEvent generateEvent = new TimeEvent(0) { - public void execute(long t) { - if (scriptThread == null || - !scriptThread.isAlive()) { - logger.info("script thread not alive. try deactivating script."); - /*scriptThread.isInterrupted()*/ - return; - } - - /* Update script variables */ - engine.put("mote", currentMote); - engine.put("id", currentMote.getID()); - engine.put("time", currentMote.getSimulation().getSimulationTime()); - engine.put("msg", msg); - - stepScript(); - } - }; - simulation.invokeSimulationThread(new Runnable() { - public void run() { - simulation.scheduleEvent( - generateEvent, - simulation.getSimulationTime() + delay*Simulation.MILLISECOND); - } - }); - } - }); + engine.put("log", scriptLog); Hashtable hash = new Hashtable(); engine.put("global", hash); @@ -449,27 +345,53 @@ public class LogScriptEngine { scriptMote = new ScriptMote(); engine.put("node", scriptMote); + + Runnable activate = new Runnable() { + public void run() { + startRealTime = System.currentTimeMillis(); + startTime = simulation.getSimulationTime(); + long endTime = startTime + timeout; + nextProgress = startTime + (endTime - startTime)/20; + + timeoutProgressEvent.remove(); + simulation.scheduleEvent(timeoutProgressEvent, nextProgress); + timeoutEvent.remove(); + simulation.scheduleEvent(timeoutEvent, endTime); + } + }; + if (simulation.isRunning()) { + simulation.invokeSimulationThread(activate); + } else { + activate.run(); + } } private TimeEvent timeoutEvent = new TimeEvent(0) { public void execute(long t) { - if (!scriptActive) { - return; - } + if (!scriptActive) { + return; + } logger.info("Timeout event @ " + t); engine.put("TIMEOUT", true); stepScript(); } }; private TimeEvent timeoutProgressEvent = new TimeEvent(0) { - public void execute(long t) { } - }; - + public void execute(long t) { + nextProgress = t + timeout/20; + simulation.scheduleEvent(this, nextProgress); + + double progress = 1.0*(t - startTime)/timeout; + long realDuration = System.currentTimeMillis()-startRealTime; + double estimatedLeft = 1.0*realDuration/progress - realDuration; + if (estimatedLeft == 0) estimatedLeft = 1; + logger.info(String.format("Test script at %2.2f%%, done in %2.1f sec", 100*progress, estimatedLeft/1000)); + } + }; + private Runnable stopSimulationRunnable = new Runnable() { public void run() { simulation.stopSimulation(); - timeoutEvent.remove(); - timeoutProgressEvent.remove(); } }; private Runnable quitRunnable = new Runnable() { @@ -491,4 +413,83 @@ public class LogScriptEngine { } }; + private ScriptLog scriptLog = new ScriptLog() { + public void log(String msg) { + if (scriptLogObserver != null) { + scriptLogObserver.update(null, msg); + } + } + public void append(String filename, String msg) { + try{ + FileWriter fstream = new FileWriter(filename, true); + BufferedWriter out = new BufferedWriter(fstream); + out.write(msg); + out.close(); + } catch (Exception e) { + logger.warn("Test append failed: " + filename + ": " + e.getMessage()); + } + } + public void writeFile(String filename, String msg) { + try{ + FileWriter fstream = new FileWriter(filename, false); + BufferedWriter out = new BufferedWriter(fstream); + out.write(msg); + out.close(); + } catch (Exception e) { + logger.warn("Write file failed: " + filename + ": " + e.getMessage()); + } + } + + public void testOK() { + log("TEST OK\n"); + deactive(); + } + public void testFailed() { + log("TEST FAILED\n"); + deactive(); + } + private void deactive() { + deactivateScript(); + + if (GUI.isVisualized()) { + log("[if test was run without visualization, COOJA would now have been terminated]\n"); + stopSimulation = true; + simulation.invokeSimulationThread(stopSimulationRunnable); + } else { + quitCooja = true; + simulation.invokeSimulationThread(quitRunnable); + } + + throw new RuntimeException("test script killed"); + } + + public void generateMessage(final long delay, final String msg) { + final Mote currentMote = (Mote) engine.get("mote"); + final TimeEvent generateEvent = new TimeEvent(0) { + public void execute(long t) { + if (scriptThread == null || + !scriptThread.isAlive()) { + logger.info("script thread not alive. try deactivating script."); + /*scriptThread.isInterrupted()*/ + return; + } + + /* Update script variables */ + engine.put("mote", currentMote); + engine.put("id", currentMote.getID()); + engine.put("time", currentMote.getSimulation().getSimulationTime()); + engine.put("msg", msg); + + stepScript(); + } + }; + simulation.invokeSimulationThread(new Runnable() { + public void run() { + simulation.scheduleEvent( + generateEvent, + simulation.getSimulationTime() + delay*Simulation.MILLISECOND); + } + }); + } + }; } diff --git a/tools/cooja/java/se/sics/cooja/plugins/ScriptRunner.java b/tools/cooja/java/se/sics/cooja/plugins/ScriptRunner.java index 89fd6ca9e..d67d86384 100644 --- a/tools/cooja/java/se/sics/cooja/plugins/ScriptRunner.java +++ b/tools/cooja/java/se/sics/cooja/plugins/ScriptRunner.java @@ -32,7 +32,9 @@ package se.sics.cooja.plugins; import java.awt.BorderLayout; +import java.awt.Component; import java.awt.Dimension; +import java.awt.GraphicsEnvironment; import java.awt.Insets; import java.awt.Window; import java.awt.event.ActionEvent; @@ -53,9 +55,12 @@ import java.util.Observer; import javax.script.ScriptException; import javax.swing.AbstractAction; +import javax.swing.Action; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JDialog; +import javax.swing.JEditorPane; +import javax.swing.JFileChooser; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JPanel; @@ -63,8 +68,10 @@ import javax.swing.JPopupMenu; import javax.swing.JScrollPane; import javax.swing.JSplitPane; import javax.swing.JTextArea; -import javax.swing.event.DocumentEvent; -import javax.swing.event.DocumentListener; +import javax.swing.filechooser.FileFilter; + +import jsyntaxpane.DefaultSyntaxKit; +import jsyntaxpane.actions.DefaultSyntaxAction; import org.apache.log4j.Logger; import org.jdom.Element; @@ -83,6 +90,14 @@ public class ScriptRunner extends VisPlugin { private static final long serialVersionUID = 7614358340336799109L; private static Logger logger = Logger.getLogger(ScriptRunner.class); + static boolean headless; + { + headless = GraphicsEnvironment.isHeadless(); + if (!headless) { + DefaultSyntaxKit.initKit(); + } + } + final String[] EXAMPLE_SCRIPTS = new String[] { "basic.js", "Various commands", "helloworld.js", "Wait for 'Hello, world'", @@ -97,24 +112,19 @@ public class ScriptRunner extends VisPlugin { private static BufferedWriter logWriter = null; /* For non-GUI tests */ - private JTextArea scriptTextArea = null; + private JEditorPane codeEditor = null; private JTextArea logTextArea = null; private JButton toggleButton = null; private JButton examplesButton = null; - private int scriptFirstLinesNumber; + private JSyntaxLinkFile actionLinkFile = null; + private File linkedFile = null; public ScriptRunner(Simulation simulation, GUI gui) { super("Contiki Test Editor", gui, false); this.simulation = simulation; - final JTextArea lineTextArea = new JTextArea(); - lineTextArea.setEnabled(false); - lineTextArea.setMargin(new Insets(5,0,5,0)); - - scriptFirstLinesNumber = 1; - /* Examples popup menu */ final JPopupMenu popupMenu = new JPopupMenu(); JMenuItem moteItem; @@ -148,65 +158,21 @@ public class ScriptRunner extends VisPlugin { } }); + { + /* Workaround to configure jsyntaxpane */ + JEditorPane e = new JEditorPane(); + new JScrollPane(e); + e.setContentType("text/javascript"); + if (e.getEditorKit() instanceof DefaultSyntaxKit) { + DefaultSyntaxKit kit = (DefaultSyntaxKit) e.getEditorKit(); + kit.setProperty("PopupMenu", "copy-to-clipboard,-,find,find-next,goto-line,-,linkfile"); + kit.setProperty("Action.linkfile", JSyntaxLinkFile.class.getName()); + } + } + /* Script area */ - scriptTextArea = new JTextArea(12,50); - scriptTextArea.getDocument().addDocumentListener(new DocumentListener() { - private int lastLines = -1; - - private void update() { - int lines = scriptTextArea.getLineCount() + scriptFirstLinesNumber; - if (lines == lastLines) { - return; - } - lastLines = lines; - - String txt = ""; - for (int i=scriptFirstLinesNumber; i < 10; i++) { - if (i > lines) { - break; - } - txt += "00" + i + "\n"; - } - for (int i=10; i < 100; i++) { - if (i > lines) { - break; - } - txt += "0" + i + "\n"; - } - for (int i=100; i < 1000; i++) { - if (i > lines) { - break; - } - txt += i + "\n"; - } - lineTextArea.setText(txt); - - /*ScriptParser parser; - try { - parser = new ScriptParser(scriptTextArea.getText()); - String tooltip = parser.getJSCode(); - tooltip = tooltip.replaceAll("\n", "
"); - tooltip = "Generated code:

" + tooltip + ""; - lineTextArea.setToolTipText(tooltip); - } catch (ScriptSyntaxErrorException e) { - lineTextArea.setToolTipText("Unable to generate code: " + e.getMessage()); - }*/ - } - - public void changedUpdate(DocumentEvent e) { - update(); - } - public void insertUpdate(DocumentEvent e) { - update(); - } - public void removeUpdate(DocumentEvent e) { - update(); - } - }); - scriptTextArea.setMargin(new Insets(5,0,5,5)); - scriptTextArea.setEditable(true); - scriptTextArea.setCursor(null); - scriptTextArea.setTabSize(1); + setLayout(new BorderLayout()); + codeEditor = new JEditorPane(); logTextArea = new JTextArea(12,50); logTextArea.setMargin(new Insets(5,5,5,5)); @@ -216,10 +182,14 @@ public class ScriptRunner extends VisPlugin { toggleButton = new JButton("Activate"); toggleButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ev) { - if (toggleButton.getText().equals("Activate")) { - setScriptActive(true); - } else { - setScriptActive(false); + try { + if (!isActive()) { + setScriptActive(true); + } else { + setScriptActive(false); + } + } catch (Exception e) { + logger.fatal("Error: " + e.getMessage(), e); } } }); @@ -231,22 +201,40 @@ public class ScriptRunner extends VisPlugin { } }); - JPanel scriptArea = new JPanel(new BorderLayout()); - scriptArea.setEnabled(false); - scriptArea.add(BorderLayout.WEST, lineTextArea); - scriptArea.add(BorderLayout.CENTER, scriptTextArea); - + doLayout(); JSplitPane centerPanel = new JSplitPane( JSplitPane.VERTICAL_SPLIT, - new JScrollPane(scriptArea), + new JScrollPane(codeEditor), new JScrollPane(logTextArea) ); + + codeEditor.setContentType("text/javascript"); + if (codeEditor.getEditorKit() instanceof DefaultSyntaxKit) { + DefaultSyntaxKit kit = (DefaultSyntaxKit) codeEditor.getEditorKit(); + kit.setProperty("PopupMenu", "copy-to-clipboard,-,find,find-next,goto-line,-,linkfile"); + kit.setProperty("Action.linkfile", JSyntaxLinkFile.class.getName()); + } + + JPopupMenu p = codeEditor.getComponentPopupMenu(); + if (p != null) { + for (Component c: p.getComponents()) { + if (c instanceof JMenuItem) { + if (((JMenuItem) c).getAction() != null && + ((JMenuItem) c).getAction() instanceof JSyntaxLinkFile) { + actionLinkFile = (JSyntaxLinkFile)(((JMenuItem) c).getAction()); + actionLinkFile.setMenuText("Link script to disk file"); + actionLinkFile.putValue("ScriptRunner", this); + } + } + } + } + centerPanel.setOneTouchExpandable(true); centerPanel.setResizeWeight(0.5); JPanel buttonPanel = new JPanel(new BorderLayout()); buttonPanel.add(BorderLayout.CENTER, toggleButton); - buttonPanel.add(BorderLayout.WEST, examplesButton); + buttonPanel.add(BorderLayout.WEST, examplesButton); buttonPanel.add(BorderLayout.EAST, runTestButton); JPanel southPanel = new JPanel(new BorderLayout()); @@ -271,21 +259,44 @@ public class ScriptRunner extends VisPlugin { } } - public void setScriptActive(boolean active) { - /* Reload script from file */ - if (scriptFile != null) { - String script = StringUtils.loadFromFile(scriptFile); - if (script == null) { - logger.fatal("Failed to load script from: " + scriptFile.getAbsolutePath()); - } else { - updateScript(script); - } + public void setLinkFile(File source) { + linkedFile = source; + if (source == null) { + updateScript(""); + + actionLinkFile.setMenuText("Link script to disk file"); + actionLinkFile.putValue("JavascriptSource", null); + + codeEditor.setEditable(true); + } else { + updateScript(linkedFile); + + actionLinkFile.setMenuText("Unlink script: " + source.getName()); + actionLinkFile.putValue("JavascriptSource", source); + + codeEditor.setEditable(false); } - + updateTitle(); + } + + public void setScriptActive(boolean active) + throws Exception { if (active) { + /* setScriptActive(true) */ + /* Free any resources */ setScriptActive(false); + /* Reload script from file */ + if (linkedFile != null) { + String script = StringUtils.loadFromFile(linkedFile); + if (script == null) { + logger.fatal("Failed to load script from: " + linkedFile.getAbsolutePath()); + } else { + updateScript(script); + } + } + /* Create new engine */ engine = new LogScriptEngine(simulation); if (GUI.isVisualized()) { @@ -331,14 +342,16 @@ public class ScriptRunner extends VisPlugin { /* Activate engine */ try { - engine.activateScript(scriptTextArea.getText()); + engine.activateScript(codeEditor.getText()); - toggleButton.setText("Deactivate"); - examplesButton.setEnabled(false); - logTextArea.setText(""); - scriptTextArea.setEnabled(false); - setTitle("Contiki Test Editor (ACTIVE) " - + (scriptFile==null?"":" (" + scriptFile.getName() + ")")); + if (!headless) { + actionLinkFile.setEnabled(false); + toggleButton.setText("Deactivate"); + examplesButton.setEnabled(false); + logTextArea.setText(""); + codeEditor.setEnabled(false); + updateTitle(); + } logger.info("Test script activated"); @@ -355,19 +368,19 @@ public class ScriptRunner extends VisPlugin { } } else { - if (engine == null) { - return; - } + /* setScriptActive(false) */ - /* Deactivate script */ - engine.deactivateScript(); - engine.setScriptLogObserver(null); - engine = null; + if (engine != null) { + /* Deactivate script */ + engine.deactivateScript(); + engine.setScriptLogObserver(null); + engine = null; + } if (logWriter != null) { try { logWriter.write( - "Test ended at simulation time: " + + "Test ended at simulation time: " + (simulation!=null?simulation.getSimulationTime():"?") + "\n"); logWriter.flush(); logWriter.close(); @@ -376,15 +389,28 @@ public class ScriptRunner extends VisPlugin { logWriter = null; } - toggleButton.setText("Activate"); - examplesButton.setEnabled(true); - scriptTextArea.setEnabled(scriptFile==null?true:false); + if (!headless) { + actionLinkFile.setEnabled(true); + toggleButton.setText("Activate"); + examplesButton.setEnabled(linkedFile==null?true:false); + codeEditor.setEnabled(true); + updateTitle(); + } logger.info("Test script deactivated"); - setTitle("Contiki Test Editor" - + (scriptFile==null?"":" (" + scriptFile.getName() + ")")); } } + private void updateTitle() { + String title = "Contiki Test Editor "; + if (linkedFile != null) { + title += ": " + linkedFile.getName() + " "; + } + if (isActive()) { + title += "(ACTIVE) "; + } + setTitle(title); + } + private void exportAndRun() { /* Save simulation config */ File configFile = simulation.getGUI().doSaveConfig(true); @@ -423,6 +449,7 @@ public class ScriptRunner extends VisPlugin { String command[] = { "java", + "-Djava.awt.headless=true", "-jar", "../dist/cooja.jar", "-nogui=" + configFile.getAbsolutePath() @@ -432,7 +459,7 @@ public class ScriptRunner extends VisPlugin { String s1 = "Start"; String s2 = "Cancel"; int n = JOptionPane.showOptionDialog(GUI.getTopParentContainer(), - "Starting COOJA in " + coojaBuild.getPath() + ":\n" + + "Starting COOJA in " + coojaBuild.getPath() + ":\n" + " " + command[0] + " " + command[1] + " " + command[2] + " " + command[3] + "\n", "Starting COOJA without GUI", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null, new Object[] { s1, s2 }, s1); @@ -558,7 +585,7 @@ public class ScriptRunner extends VisPlugin { return; } - scriptTextArea.setText(script); + codeEditor.setText(script); logTextArea.setText(""); } @@ -566,29 +593,35 @@ public class ScriptRunner extends VisPlugin { ArrayList config = new ArrayList(); Element element; - if (scriptFile != null) { + if (linkedFile != null) { element = new Element("scriptfile"); - element.setText(simulation.getGUI().createPortablePath(scriptFile).getPath().replace('\\', '/')); + element.setText(simulation.getGUI().createPortablePath(linkedFile).getPath().replace('\\', '/')); config.add(element); /*StringUtils.saveToFile(scriptFile, scriptTextArea.getText());*/ } else { element = new Element("script"); - element.setText(scriptTextArea.getText()); + element.setText(codeEditor.getText()); config.add(element); } element = new Element("active"); - element.setText("" + (engine != null)); + element.setText("" + isActive()); config.add(element); return config; } + public boolean isActive() { + return engine != null; + + } public void closePlugin() { - setScriptActive(false); + try { + setScriptActive(false); + } catch (Exception e) { + } } - private File scriptFile = null; public boolean setConfigXML(Collection configXML, boolean visAvailable) { for (Element element : configXML) { String name = element.getName(); @@ -598,25 +631,26 @@ public class ScriptRunner extends VisPlugin { } } else if ("scriptfile".equals(name)) { File file = simulation.getGUI().restorePortablePath(new File(element.getText().trim())); - String script = StringUtils.loadFromFile(file); - if (script == null) { - logger.fatal("Failed to load script from: " + file.getAbsolutePath()); - } else { - updateScript(script); - } - scriptFile = file; - scriptTextArea.setEnabled(false); + setLinkFile(file); } else if ("active".equals(name)) { boolean active = Boolean.parseBoolean(element.getText()); if (GUI.isVisualized()) { - setScriptActive(active); + try { + setScriptActive(active); + } catch (Exception e) { + logger.fatal("Error: " + e.getMessage(), e); + } } } } if (!GUI.isVisualized()) { /* Automatically activate script */ - setScriptActive(true); + try { + setScriptActive(true); + } catch (Exception e) { + logger.fatal("Error: " + e.getMessage(), e); + } simulation.setDelayTime(0); simulation.startSimulation(); } @@ -627,4 +661,45 @@ public class ScriptRunner extends VisPlugin { return StringUtils.loadFromURL(ScriptRunner.class.getResource("/scripts/" + file)); } + public static class JSyntaxLinkFile extends DefaultSyntaxAction { + private static Logger logger = Logger.getLogger(JSyntaxLinkFile.class); + + public JSyntaxLinkFile() { + super("linkfile"); + } + + public void actionPerformed(ActionEvent e) { + JMenuItem menuItem = (JMenuItem) e.getSource(); + Action action = menuItem.getAction(); + ScriptRunner scriptRunner = (ScriptRunner) action.getValue("ScriptRunner"); + File currentSource = (File) action.getValue("JavascriptSource"); + + if (currentSource != null) { + scriptRunner.setLinkFile(null); + return; + } + + JFileChooser fileChooser = new JFileChooser(); + fileChooser.setCurrentDirectory(new java.io.File(".")); + fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); + fileChooser.setDialogTitle("Select script file"); + fileChooser.setFileFilter(new FileFilter() { + public boolean accept(File file) { + if (file.isDirectory()) { return true; } + if (file.getName().endsWith(".js")) { + return true; + } + return false; + } + public String getDescription() { + return "Javascript"; + } + }); + if (fileChooser.showOpenDialog(scriptRunner) != JFileChooser.APPROVE_OPTION) { + logger.debug("cancel"); + return; + } + scriptRunner.setLinkFile(fileChooser.getSelectedFile()); + } + } } diff --git a/tools/cooja/java/se/sics/cooja/plugins/TimeLine.java b/tools/cooja/java/se/sics/cooja/plugins/TimeLine.java index 6244740a8..4aefbc074 100644 --- a/tools/cooja/java/se/sics/cooja/plugins/TimeLine.java +++ b/tools/cooja/java/se/sics/cooja/plugins/TimeLine.java @@ -88,11 +88,12 @@ import se.sics.cooja.GUI; import se.sics.cooja.Mote; import se.sics.cooja.Plugin; import se.sics.cooja.PluginType; +import se.sics.cooja.SimEventCentral.MoteCountListener; import se.sics.cooja.Simulation; import se.sics.cooja.VisPlugin; import se.sics.cooja.Watchpoint; import se.sics.cooja.WatchpointMote; -import se.sics.cooja.SimEventCentral.MoteCountListener; +import se.sics.cooja.WatchpointMote.WatchpointListener; import se.sics.cooja.interfaces.LED; import se.sics.cooja.interfaces.Radio; import se.sics.cooja.interfaces.Radio.RadioEvent; @@ -100,7 +101,7 @@ import se.sics.cooja.motes.AbstractEmulatedMote; /** * Shows events such as mote logs, LEDs, and radio transmissions, in a timeline. - * + * * @author Fredrik Osterlind */ @ClassDescription("Timeline") @@ -118,13 +119,13 @@ public class TimeLine extends VisPlugin { private double currentPixelDivisor = 200; - private static final long[] ZOOM_LEVELS = { - 1, 2, 5, 10, - 20, 50, 100, 200, 500, 1000, - 2000, 5000, 10000, 20000, 50000, 100000 }; + private static final long[] ZOOM_LEVELS = { + 1, 2, 5, 10, + 20, 50, 100, 200, 500, 1000, + 2000, 5000, 10000, 20000, 50000, 100000 }; private boolean needZoomOut = false; - + private static Logger logger = Logger.getLogger(TimeLine.class); private int paintedMoteHeight = EVENT_PIXEL_HEIGHT; @@ -137,7 +138,7 @@ public class TimeLine extends VisPlugin { private JComponent timeline; private Box eventCheckboxes; private JSplitPane splitPane; - + private Observer moteHighlightObserver = null; private ArrayList highlightedMotes = new ArrayList(); private final static Color HIGHLIGHT_COLOR = Color.CYAN; @@ -162,9 +163,9 @@ public class TimeLine extends VisPlugin { public TimeLine(final Simulation simulation, final GUI gui) { super("Timeline (Add motes to observe by clicking +)", gui); this.simulation = simulation; - + currentPixelDivisor = ZOOM_LEVELS[ZOOM_LEVELS.length/2]; - + /* Box: events to observe */ eventCheckboxes = Box.createVerticalBox(); JCheckBox eventCheckBox; @@ -281,7 +282,7 @@ public class TimeLine extends VisPlugin { for (Mote m: simulation.getMotes()) { addMote(m); } - + /* Update timeline for the duration of the plugin */ repaintTimelineTimer.start(); @@ -351,12 +352,12 @@ public class TimeLine extends VisPlugin { public void actionPerformed(ActionEvent e) { JComponent b = (JComponent) e.getSource(); Mote m = (Mote) b.getClientProperty("mote"); - + /* Sort by distance */ ArrayList sortedMoteEvents = new ArrayList(); for (MoteEvents me: allMoteEvents.toArray(new MoteEvents[0])) { double d = me.mote.getInterfaces().getPosition().getDistanceTo(m); - + int i=0; for (i=0; i < sortedMoteEvents.size(); i++) { double d2 = m.getInterfaces().getPosition().getDistanceTo(sortedMoteEvents.get(i).mote); @@ -365,7 +366,7 @@ public class TimeLine extends VisPlugin { } } sortedMoteEvents.add(i, me); - + } allMoteEvents = sortedMoteEvents; numberMotesWasUpdated(); @@ -376,7 +377,7 @@ public class TimeLine extends VisPlugin { public void actionPerformed(ActionEvent e) { JComponent b = (JComponent) e.getSource(); Mote m = (Mote) b.getClientProperty("mote"); - + /* Sort by distance */ MoteEvents mEvent = null; for (MoteEvents me: allMoteEvents.toArray(new MoteEvents[0])) { @@ -441,7 +442,7 @@ public class TimeLine extends VisPlugin { int leftPixel = (int) (focusTime/currentPixelDivisor - focusCenter*w); Rectangle r = new Rectangle( - leftPixel, 0, + leftPixel, 0, w, 1 ); @@ -456,7 +457,7 @@ public class TimeLine extends VisPlugin { } }); } - + private Action zoomInAction = new AbstractAction("Zoom in (Ctrl+)") { private static final long serialVersionUID = -2592452356547803615L; public void actionPerformed(ActionEvent e) { @@ -476,13 +477,13 @@ public class TimeLine extends VisPlugin { if (currentPixelDivisor <= ZOOM_LEVELS[zoomLevel]) break; zoomLevel++; } - + if (zoomLevel > 0) { zoomLevel--; /* zoom in */ } currentPixelDivisor = ZOOM_LEVELS[zoomLevel]; logger.info("Zoom level: " + currentPixelDivisor + " microseconds/pixel " + ((zoomLevel==0)?"(MIN)":"")); - + forceRepaintAndFocus(centerTime, 0.5); } }; @@ -516,7 +517,7 @@ public class TimeLine extends VisPlugin { forceRepaintAndFocus(centerTime, 0.5); } }; - + private Action zoomSliderAction = new AbstractAction("Zoom slider (Ctrl+Mouse)") { private static final long serialVersionUID = -4288046377707363837L; public void actionPerformed(ActionEvent e) { @@ -532,27 +533,27 @@ public class TimeLine extends VisPlugin { zoomSlider.setPaintLabels(false); final long centerTime = (long) (popupLocation.x*currentPixelDivisor); - + zoomSlider.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { int zoomLevel = zoomSlider.getValue(); - + currentPixelDivisor = ZOOM_LEVELS[zoomLevel]; logger.info("Zoom level: " + currentPixelDivisor + " microseconds/pixel " + ((zoomLevel==ZOOM_LEVELS.length-1)?"(MAX)":"")); forceRepaintAndFocus(centerTime, 0.5); } }); - + final JPopupMenu zoomPopup = new JPopupMenu(); zoomPopup.add(zoomSlider); zoomPopup.show(TimeLine.this, TimeLine.this.getWidth()/2, 0); zoomSlider.requestFocus(); } }; - + /** - * Save logged raw data to file for post-processing. + * Save logged raw data to file for post-processing. */ private Action saveDataAction = new AbstractAction("Save raw data to file") { private static final long serialVersionUID = 975176793514425718L; @@ -641,15 +642,15 @@ public class TimeLine extends VisPlugin { } repaint(); } - - + + private class MoteStatistics { Mote mote; long onTimeRedLED = 0, onTimeGreenLED = 0, onTimeBlueLED = 0; int nrLogs = 0; long radioOn = 0; long onTimeRX = 0, onTimeTX = 0, onTimeInterfered = 0; - + public String toString() { return toString(true, true, true, true); } @@ -685,7 +686,7 @@ public class TimeLine extends VisPlugin { logger.info(extractStatistics()); } }; - + public String extractStatistics() { return extractStatistics(true, true, true, true); } @@ -743,7 +744,7 @@ public class TimeLine extends VisPlugin { stats.nrLogs++; } } - + /* TODO Radio channels */ if (radioHW) { @@ -760,7 +761,7 @@ public class TimeLine extends VisPlugin { } } } - + if (radioRXTX) { for (MoteEvent ev: moteEvents.radioRXTXEvents) { if (!(ev instanceof RadioRXTXEvent)) continue; @@ -790,7 +791,7 @@ public class TimeLine extends VisPlugin { } } } - + /* TODO Watchpoints */ output.append(stats.toString(logs, leds, radioHW, radioRXTX)); @@ -799,7 +800,7 @@ public class TimeLine extends VisPlugin { if (allStats.size() == 0) { return output.toString(); } - + /* Average */ MoteStatistics average = new MoteStatistics(); for (MoteStatistics stats: allStats) { @@ -822,7 +823,7 @@ public class TimeLine extends VisPlugin { output.append(average.toString(logs, leds, radioHW, radioRXTX)); return output.toString(); } - + public void trySelectTime(final long toTime) { java.awt.EventQueue.invokeLater(new Runnable() { public void run() { @@ -841,23 +842,23 @@ public class TimeLine extends VisPlugin { forceRepaintAndFocus(toTime, 0.5, false); } - }); + }); } - + private Action radioLoggerAction = new AbstractAction("in Radio Logger") { private static final long serialVersionUID = 7690116136861949864L; public void actionPerformed(ActionEvent e) { if (popupLocation == null) { return; } - long time = (long) ((double)popupLocation.x*currentPixelDivisor); + long time = (long) (popupLocation.x*currentPixelDivisor); Plugin[] plugins = simulation.getGUI().getStartedPlugins(); for (Plugin p: plugins) { if (!(p instanceof RadioLogger)) { continue; } - + /* Select simulation time */ RadioLogger plugin = (RadioLogger) p; plugin.trySelectTime(time); @@ -870,14 +871,14 @@ public class TimeLine extends VisPlugin { if (popupLocation == null) { return; } - long time = (long) ((double)popupLocation.x*currentPixelDivisor); + long time = (long) (popupLocation.x*currentPixelDivisor); Plugin[] plugins = simulation.getGUI().getStartedPlugins(); for (Plugin p: plugins) { if (!(p instanceof LogListener)) { continue; } - + /* Select simulation time */ LogListener plugin = (LogListener) p; plugin.trySelectTime(time); @@ -929,8 +930,8 @@ public class TimeLine extends VisPlugin { private Mote mote; private WatchpointMote watchpointMote; /* XXX */ - private ActionListener watchpointListener; /* XXX */ - + private WatchpointListener watchpointListener; /* XXX */ + public MoteObservation(Mote mote, Observable observable, Observer observer) { this.mote = mote; this.observable = observable; @@ -938,12 +939,12 @@ public class TimeLine extends VisPlugin { } /* XXX Special case, should be generalized */ - public MoteObservation(Mote mote, WatchpointMote watchpointMote, ActionListener listener) { + public MoteObservation(Mote mote, WatchpointMote watchpointMote, WatchpointListener listener) { this.mote = mote; this.watchpointMote = watchpointMote; this.watchpointListener = listener; } - + public Mote getMote() { return mote; } @@ -958,7 +959,7 @@ public class TimeLine extends VisPlugin { observable = null; observer = null; } - + /* XXX */ if (watchpointMote != null) { watchpointMote.removeWatchpointListener(watchpointListener); @@ -971,7 +972,7 @@ public class TimeLine extends VisPlugin { private void addMoteObservers(final Mote mote, final MoteEvents moteEvents) { /* TODO Log: final Log moteLog = mote.getInterfaces().getLog(); */ /* TODO Unknown state event */ - + /* LEDs */ final LED moteLEDs = mote.getInterfaces().getLED(); if (moteLEDs != null) { @@ -1021,7 +1022,7 @@ public class TimeLine extends VisPlugin { return; } lastChannel = nowChannel; - + RadioHWEvent ev = new RadioHWEvent( simulation.getSimulationTime(), moteRadio.isReceiverOn()); if (radioChannels) { @@ -1067,7 +1068,7 @@ public class TimeLine extends VisPlugin { radioEv == RadioEvent.RECEPTION_STARTED || radioEv == RadioEvent.RECEPTION_INTERFERED || radioEv == RadioEvent.RECEPTION_FINISHED) { - + RadioRXTXEvent ev; /* Override events, instead show state */ if (moteRadio.isTransmitting()) { @@ -1086,9 +1087,9 @@ public class TimeLine extends VisPlugin { ev = new RadioRXTXEvent( simulation.getSimulationTime(), RXTXRadioEvent.IDLE); } - + moteEvents.addRadioRXTX(ev); - + if (executionDetails && mote instanceof AbstractEmulatedMote) { String details = ((AbstractEmulatedMote) mote).getExecutionDetails(); if (details != null) { @@ -1106,22 +1107,26 @@ public class TimeLine extends VisPlugin { moteRadio.addObserver(observer); activeMoteObservers.add(new MoteObservation(mote, moteRadio, observer)); } - + /* XXX Experimental: Watchpoints */ if (mote instanceof WatchpointMote) { final WatchpointMote watchpointMote = ((WatchpointMote)mote); - ActionListener listener = new ActionListener() { - public void actionPerformed(ActionEvent e) { - if (watchpointMote.getLastWatchpoint() == null) { - return; + WatchpointListener listener = new WatchpointListener() { + public void watchpointTriggered(Watchpoint watchpoint) { + WatchpointEvent ev = new WatchpointEvent(simulation.getSimulationTime(), watchpoint); + + if (executionDetails && mote instanceof AbstractEmulatedMote) { + String details = ((AbstractEmulatedMote) mote).getExecutionDetails(); + if (details != null) { + details = "
" + details.replace("\n", "
"); + ev.details = details; + } } - WatchpointEvent ev = new WatchpointEvent( - simulation.getSimulationTime(), - watchpointMote.getLastWatchpoint() - ); moteEvents.addWatchpoint(ev); } + public void watchpointsChanged() { + } }; watchpointMote.addWatchpointListener(listener); @@ -1209,7 +1214,7 @@ public class TimeLine extends VisPlugin { } simulation.getEventCentral().removeMoteCountListener(newMotesListener); - + /* Remove active mote interface observers */ for (MoteObservation o: activeMoteObservers) { o.dispose(); @@ -1295,7 +1300,7 @@ public class TimeLine extends VisPlugin { for (MoteEvents moteEvents: allMoteEventsArr) { removeMote(moteEvents.mote); } - + for (Element element : configXML) { String name = element.getName(); if ("mote".equals(name)) { @@ -1349,20 +1354,20 @@ public class TimeLine extends VisPlugin { return true; } - + private int mousePixelPositionX = -1; private int mousePixelPositionY = -1; - private int mouseDownPixelPositionX = -1; + private int mouseDownPixelPositionX = -1; class Timeline extends JComponent { private static final long serialVersionUID = 2206491823778169359L; public Timeline() { setLayout(null); setToolTipText(null); setBackground(COLOR_BACKGROUND); - + addMouseListener(mouseAdapter); addMouseMotionListener(mouseAdapter); - + /* Popup menu */ final JPopupMenu popupMenu = new JPopupMenu(); @@ -1379,7 +1384,7 @@ public class TimeLine extends VisPlugin { popupMenu.add(new JMenuItem(saveDataAction)); popupMenu.add(new JMenuItem(statisticsAction)); popupMenu.add(new JMenuItem(clearAction)); - + popupMenu.addSeparator(); JMenu focusMenu = new JMenu("Show in"); @@ -1417,7 +1422,7 @@ public class TimeLine extends VisPlugin { popupLocation = e.getPoint(); showInAllAction.actionPerformed(null); - long time = (long) ((double)popupLocation.x*currentPixelDivisor); + long time = (long) (popupLocation.x*currentPixelDivisor); Plugin[] plugins = simulation.getGUI().getStartedPlugins(); for (Plugin p: plugins) { if (!(p instanceof TimeLine)) { @@ -1486,7 +1491,7 @@ public class TimeLine extends VisPlugin { forceRepaintAndFocus(zoomCenterTime, zoomCenter); return; } - + if (mousePixelPositionX >= 0) { mousePixelPositionX = e.getX(); mousePixelPositionY = e.getY(); @@ -1507,7 +1512,7 @@ public class TimeLine extends VisPlugin { zoomCenterTime = (long) (e.getX()*currentPixelDivisor); return; } - + if (popUpToolTip != null) { popUpToolTip.hide(); popUpToolTip = null; @@ -1524,7 +1529,34 @@ public class TimeLine extends VisPlugin { if (t.getTipText() == null || t.getTipText().equals("")) { return; } - popUpToolTip = PopupFactory.getSharedInstance().getPopup(timeline, t, e.getXOnScreen(), e.getYOnScreen()); + t.validate(); + + /* Check tooltip width */ + Rectangle screenBounds = timeline.getGraphicsConfiguration().getBounds(); + int x; + { + int tooltip = e.getLocationOnScreen().x + t.getPreferredSize().width; + int screen = screenBounds.x + screenBounds.width; + if (tooltip > screen) { + x = e.getLocationOnScreen().x - (tooltip-screen); + } else { + x = e.getLocationOnScreen().x; + } + } + + /* Check tooltip height */ + int y; + { + int tooltip = e.getLocationOnScreen().y + t.getPreferredSize().height; + int screen = screenBounds.y + screenBounds.height; + if (tooltip > screen) { + y = e.getLocationOnScreen().y - (tooltip-screen); + } else { + y = e.getLocationOnScreen().y; + } + } + + popUpToolTip = PopupFactory.getSharedInstance().getPopup(null, t, x, y); popUpToolTip.show(); } } @@ -1544,7 +1576,7 @@ public class TimeLine extends VisPlugin { public void paintComponent(Graphics g) { Rectangle bounds = g.getClipBounds(); /*logger.info("Clip bounds: " + bounds);*/ - + if (needZoomOut) { /* Need zoom out */ g.setColor(Color.RED); @@ -1556,12 +1588,12 @@ public class TimeLine extends VisPlugin { FontMetrics fm = g.getFontMetrics(); int msgWidth = fm.stringWidth(msg); int msgHeight = fm.getHeight(); - g.drawString(msg, + g.drawString(msg, vis.x + vis.width/2 - msgWidth/2, vis.y + vis.height/2 + msgHeight/2); return; } - + long intervalStart = (long)(bounds.x*currentPixelDivisor); long intervalEnd = (long) (intervalStart + bounds.width*currentPixelDivisor); @@ -1584,12 +1616,12 @@ public class TimeLine extends VisPlugin { int lineHeightOffset = FIRST_MOTE_PIXEL_OFFSET; boolean dark = true; for (int mIndex = 0; mIndex < allMoteEvents.size(); mIndex++) { - + /* Mote separators */ if (dark) { g.setColor(SEPARATOR_COLOR); g.fillRect( - 0, lineHeightOffset-2, + 0, lineHeightOffset-2, getWidth(), paintedMoteHeight ); } @@ -1680,23 +1712,23 @@ public class TimeLine extends VisPlugin { while (time <= end) { if (time % (100*Simulation.MILLISECOND) == 0) { g.drawLine( - (int) (time/currentPixelDivisor), (int)0, - (int) (time/currentPixelDivisor), (int)TIME_MARKER_PIXEL_HEIGHT); + (int) (time/currentPixelDivisor), 0, + (int) (time/currentPixelDivisor), TIME_MARKER_PIXEL_HEIGHT); } else { g.drawLine( - (int) (time/currentPixelDivisor), (int)0, - (int) (time/currentPixelDivisor), (int)TIME_MARKER_PIXEL_HEIGHT/2); - } + (int) (time/currentPixelDivisor), 0, + (int) (time/currentPixelDivisor), TIME_MARKER_PIXEL_HEIGHT/2); + } time += (10*Simulation.MILLISECOND); } } private void drawMouseTime(Graphics g, long start, long end) { if (mousePixelPositionX >= 0) { - long time = (long) ((double)mousePixelPositionX*currentPixelDivisor); - long diff = (long) ((double)Math.abs(mouseDownPixelPositionX-mousePixelPositionX)*currentPixelDivisor); - String str = - "Time (ms): " + (double)time/Simulation.MILLISECOND + + long time = (long) (mousePixelPositionX*currentPixelDivisor); + long diff = (long) (Math.abs(mouseDownPixelPositionX-mousePixelPositionX)*currentPixelDivisor); + String str = + "Time (ms): " + (double)time/Simulation.MILLISECOND + " (" + (double)diff/Simulation.MILLISECOND + ")"; int h = g.getFontMetrics().getHeight(); @@ -1707,21 +1739,21 @@ public class TimeLine extends VisPlugin { /* Line */ g.setColor(Color.GRAY); g.drawLine( - mousePixelPositionX, 0, + mousePixelPositionX, 0, mousePixelPositionX, getHeight()); /* Text box */ g.setColor(Color.DARK_GRAY); g.fillRect( - mousePixelPositionX-delta, y, + mousePixelPositionX-delta, y, w, h); g.setColor(Color.BLACK); g.drawRect( - mousePixelPositionX-delta, y, + mousePixelPositionX-delta, y, w, h); g.setColor(Color.WHITE); - g.drawString(str, - mousePixelPositionX+3-delta, + g.drawString(str, + mousePixelPositionX+3-delta, y+h-1); } } @@ -1738,7 +1770,7 @@ public class TimeLine extends VisPlugin { int mote = (event.getPoint().y-FIRST_MOTE_PIXEL_OFFSET)/paintedMoteHeight; if (mote < 0 || mote >= allMoteEvents.size()) { return null; - } + } String tooltip = "Mote: " + allMoteEvents.get(mote).mote + "
"; /* Time */ @@ -1789,7 +1821,7 @@ public class TimeLine extends VisPlugin { MoteEvent ev = getFirstIntervalEvent(events, time); if (ev != null && time >= ev.time) { tooltip += ev + "
"; - + if (ev.details != null) { tooltip += "Details:
" + ev.details; } @@ -1846,7 +1878,7 @@ public class TimeLine extends VisPlugin { private Mote getMote(Point p) { if (p.y < FIRST_MOTE_PIXEL_OFFSET) { - return null; + return null; } int m = (p.y-FIRST_MOTE_PIXEL_OFFSET)/paintedMoteHeight; if (m < allMoteEvents.size()) { @@ -1899,9 +1931,9 @@ public class TimeLine extends VisPlugin { /** * Used by the default paint method to color events. * The event is not painted if the returned color is null. - * + * * @see #paintInterval(Graphics, int, long) - * @return Event color or null + * @return Event color or null */ public abstract Color getEventColor(); @@ -1937,7 +1969,7 @@ public class TimeLine extends VisPlugin { g.setColor(color); g.fillRect( - (int)(ev.time/currentPixelDivisor), lineHeightOffset, + (int)(ev.time/currentPixelDivisor), lineHeightOffset, w, EVENT_PIXEL_HEIGHT ); @@ -1987,7 +2019,7 @@ public class TimeLine extends VisPlugin { if (state == RXTXRadioEvent.IDLE) { return "Radio idle from " + time + "
"; } else if (state == RXTXRadioEvent.TRANSMITTING) { - return "Radio transmitting from " + time + "
"; + return "Radio transmitting from " + time + "
"; } else if (state == RXTXRadioEvent.RECEIVING) { return "Radio receiving from " + time + "
"; } else if (state == RXTXRadioEvent.INTERFERED) { @@ -2007,18 +2039,18 @@ public class TimeLine extends VisPlugin { } /* TODO Which colors? */ - private final static Color[] CHANNEL_COLORS = new Color[] { - Color.decode("0x008080"), Color.decode("0x808080"), Color.decode("0xC00000"), - Color.decode("0x000020"), Color.decode("0x202000"), Color.decode("0x200020"), + private final static Color[] CHANNEL_COLORS = new Color[] { + Color.decode("0x008080"), Color.decode("0x808080"), Color.decode("0xC00000"), + Color.decode("0x000020"), Color.decode("0x202000"), Color.decode("0x200020"), Color.decode("0x002020"), Color.decode("0x202020"), Color.decode("0x006060"), - Color.decode("0x606060"), Color.decode("0xA00000"), Color.decode("0x00A000"), + Color.decode("0x606060"), Color.decode("0xA00000"), Color.decode("0x00A000"), Color.decode("0x0000A0"), Color.decode("0x400040"), Color.decode("0x004040"), Color.decode("0x404040"), Color.decode("0x200000"), Color.decode("0x002000"), - Color.decode("0xA0A000"), Color.decode("0xA000A0"), Color.decode("0x00A0A0"), + Color.decode("0xA0A000"), Color.decode("0xA000A0"), Color.decode("0x00A0A0"), Color.decode("0xA0A0A0"), Color.decode("0xE00000"), Color.decode("0x600000"), - Color.decode("0x000040"), Color.decode("0x404000"), Color.decode("0xFF0000"), - Color.decode("0x00FF00"), Color.decode("0x0000FF"), Color.decode("0xFFFF00"), - Color.decode("0xFF00FF"), Color.decode("0x808000"), Color.decode("0x800080"), + Color.decode("0x000040"), Color.decode("0x404000"), Color.decode("0xFF0000"), + Color.decode("0x00FF00"), Color.decode("0x0000FF"), Color.decode("0xFFFF00"), + Color.decode("0xFF00FF"), Color.decode("0x808000"), Color.decode("0x800080"), }; class RadioHWEvent extends MoteEvent { boolean on; @@ -2098,21 +2130,21 @@ public class TimeLine extends VisPlugin { if (color.getRed() > 0) { g.setColor(new Color(color.getRed(), 0, 0)); g.fillRect( - (int)(ev.time/currentPixelDivisor), lineHeightOffset, + (int)(ev.time/currentPixelDivisor), lineHeightOffset, w, LED_PIXEL_HEIGHT ); } if (color.getGreen() > 0) { g.setColor(new Color(0, color.getGreen(), 0)); g.fillRect( - (int)(ev.time/currentPixelDivisor), lineHeightOffset+LED_PIXEL_HEIGHT, + (int)(ev.time/currentPixelDivisor), lineHeightOffset+LED_PIXEL_HEIGHT, w, LED_PIXEL_HEIGHT ); } if (color.getBlue() > 0) { g.setColor(new Color(0, 0, color.getBlue())); g.fillRect( - (int)(ev.time/currentPixelDivisor), lineHeightOffset+2*LED_PIXEL_HEIGHT, + (int)(ev.time/currentPixelDivisor), lineHeightOffset+2*LED_PIXEL_HEIGHT, w, LED_PIXEL_HEIGHT ); } @@ -2120,7 +2152,7 @@ public class TimeLine extends VisPlugin { } } public String toString() { - return + return "LED state:
" + "Red = " + (red?"ON":"OFF") + "
" + "Green = " + (green?"ON":"OFF") + "
" + @@ -2151,7 +2183,7 @@ public class TimeLine extends VisPlugin { public String toString() { String desc = watchpoint.getDescription(); desc = desc.replace("\n", "
"); - return + return "Watchpoint triggered at time (ms): " + time/Simulation.MILLISECOND + ".
" + desc + "
"; } @@ -2171,7 +2203,7 @@ public class TimeLine extends VisPlugin { g.setColor(color); g.fillRect( - (int)(ev.time/currentPixelDivisor), lineHeightOffset, + (int)(ev.time/currentPixelDivisor), lineHeightOffset, w, EVENT_PIXEL_HEIGHT ); @@ -2184,7 +2216,7 @@ public class TimeLine extends VisPlugin { ArrayList radioRXTXEvents; ArrayList radioChannelEvents; ArrayList radioHWEvents; - ArrayList ledEvents; + ArrayList ledEvents; ArrayList logEvents; ArrayList watchpointEvents; @@ -2245,7 +2277,7 @@ public class TimeLine extends VisPlugin { watchpointEvents.add(lastWatchpointEvent); } } - + public void addRadioRXTX(RadioRXTXEvent ev) { /* Link with previous events */ if (lastRadioRXTXEvent != null) { @@ -2317,7 +2349,7 @@ public class TimeLine extends VisPlugin { if (now == lastRepaintSimulationTime) { return; } - lastRepaintSimulationTime = now; + lastRepaintSimulationTime = now; /* Update timeline size */ int newWidth; @@ -2330,10 +2362,10 @@ public class TimeLine extends VisPlugin { needZoomOut = false; } - Rectangle visibleRectangle = timeline.getVisibleRect(); + Rectangle visibleRectangle = timeline.getVisibleRect(); boolean isTracking = visibleRectangle.x + visibleRectangle.width >= timeline.getWidth(); - int newHeight = (int) (FIRST_MOTE_PIXEL_OFFSET + paintedMoteHeight * allMoteEvents.size()); + int newHeight = (FIRST_MOTE_PIXEL_OFFSET + paintedMoteHeight * allMoteEvents.size()); timeline.setPreferredSize(new Dimension( newWidth, newHeight @@ -2348,7 +2380,7 @@ public class TimeLine extends VisPlugin { /* Update visible rectangle */ if (isTracking) { Rectangle r = new Rectangle( - newWidth-1, visibleRectangle.y, + newWidth-1, visibleRectangle.y, 1, 1); timeline.scrollRectToVisible(r); } diff --git a/tools/cooja/java/se/sics/cooja/util/JSyntaxAddBreakpoint.java b/tools/cooja/java/se/sics/cooja/util/JSyntaxAddBreakpoint.java new file mode 100644 index 000000000..b2e394c8c --- /dev/null +++ b/tools/cooja/java/se/sics/cooja/util/JSyntaxAddBreakpoint.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2012, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: CodeUI.java,v 1.8 2009/09/23 08:16:06 fros4943 Exp $ + */ + +package se.sics.cooja.util; + +import java.awt.event.ActionEvent; +import java.io.File; + +import javax.swing.Action; +import javax.swing.JMenuItem; +import javax.swing.text.JTextComponent; + +import jsyntaxpane.SyntaxDocument; +import jsyntaxpane.actions.DefaultSyntaxAction; + +import org.apache.log4j.Logger; + +import se.sics.cooja.WatchpointMote; + +public class JSyntaxAddBreakpoint extends DefaultSyntaxAction { + private static Logger logger = Logger.getLogger(JSyntaxAddBreakpoint.class); + + public JSyntaxAddBreakpoint() { + super("addbreakpoint"); + } + + public void actionPerformed(ActionEvent e) { + JMenuItem menuItem = (JMenuItem) e.getSource(); + Action action = menuItem.getAction(); + WatchpointMote watchpointMote = (WatchpointMote) action.getValue("WatchpointMote"); + if (watchpointMote == null) { + logger.warn("Error: No source, cannot configure breakpoint"); + return; + } + + File file = (File) action.getValue("WatchpointFile"); + Integer line = (Integer) action.getValue("WatchpointLine"); + Integer address = (Integer) action.getValue("WatchpointAddress"); + if (file == null || line == null || address == null) { + logger.warn("Error: Bad breakpoint info, cannot add breakpoint"); + return; + } + + watchpointMote.addBreakpoint(file, line, address); + } +} diff --git a/tools/cooja/java/se/sics/cooja/util/JSyntaxRemoveBreakpoint.java b/tools/cooja/java/se/sics/cooja/util/JSyntaxRemoveBreakpoint.java new file mode 100644 index 000000000..85bb3245d --- /dev/null +++ b/tools/cooja/java/se/sics/cooja/util/JSyntaxRemoveBreakpoint.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2012, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: CodeUI.java,v 1.8 2009/09/23 08:16:06 fros4943 Exp $ + */ + +package se.sics.cooja.util; + +import java.awt.event.ActionEvent; +import java.io.File; + +import javax.swing.Action; +import javax.swing.JMenuItem; + +import jsyntaxpane.actions.DefaultSyntaxAction; + +import org.apache.log4j.Logger; + +import se.sics.cooja.Watchpoint; +import se.sics.cooja.WatchpointMote; + +public class JSyntaxRemoveBreakpoint extends DefaultSyntaxAction { + private static Logger logger = Logger.getLogger(JSyntaxRemoveBreakpoint.class); + + public JSyntaxRemoveBreakpoint() { + super("removebreakpoint"); + } + + public void actionPerformed(ActionEvent e) { + JMenuItem menuItem = (JMenuItem) e.getSource(); + Action action = menuItem.getAction(); + WatchpointMote watchpointMote = (WatchpointMote) action.getValue("WatchpointMote"); + if (watchpointMote == null) { + logger.warn("Error: No source, cannot configure breakpoint"); + return; + } + + File file = (File) action.getValue("WatchpointFile"); + Integer line = (Integer) action.getValue("WatchpointLine"); + Integer address = (Integer) action.getValue("WatchpointAddress"); + if (file == null || line == null || address == null) { + logger.warn("Error: Bad breakpoint info, cannot remove breakpoint"); + return; + } + for (Watchpoint w: watchpointMote.getBreakpoints()) { + if (file.equals(w.getCodeFile()) && line.equals(w.getLineNumber()) && address.equals(w.getExecutableAddress())) { + watchpointMote.removeBreakpoint(w); + } + } + + } +} diff --git a/tools/cooja/lib/JSYNTAXPANE_LICENSE b/tools/cooja/lib/JSYNTAXPANE_LICENSE new file mode 100644 index 000000000..01f0c7c35 --- /dev/null +++ b/tools/cooja/lib/JSYNTAXPANE_LICENSE @@ -0,0 +1,4 @@ +Downloaded from http://code.google.com/p/jsyntaxpane/. + +Apache License 2.0: +http://www.apache.org/licenses/LICENSE-2.0 diff --git a/tools/cooja/lib/jsyntaxpane.jar b/tools/cooja/lib/jsyntaxpane.jar new file mode 100644 index 000000000..8bca1f6ec Binary files /dev/null and b/tools/cooja/lib/jsyntaxpane.jar differ