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.c b/cpu/cc2430/dev/rs232.c deleted file mode 100644 index 1dc233348..000000000 --- a/cpu/cc2430/dev/rs232.c +++ /dev/null @@ -1,76 +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.c,v 1.1 2009/09/08 20:07:35 zdshelby Exp $ - * - */ -/* - * \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" - -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(); - - rs232_arch_init(RS232_BAUD_RATE); - etimer_set(&timer, CLOCK_SECOND / 16); - - 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/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/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..c9a616aac --- /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_PRINT +#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..605153d1b --- /dev/null +++ b/examples/sensinode/energy-scan/stub-rdc.c @@ -0,0 +1,91 @@ +/* + * 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 +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, + 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..603552c97 --- /dev/null +++ b/examples/sensinode/sniffer/stub-rdc.c @@ -0,0 +1,91 @@ +/* + * 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 +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, + 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..24e490ff3 --- /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_PRINT +#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/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(); +} +/*---------------------------------------------------------------------------*/