From 91ae1eb6fdba1ee2048b4a58eeb9cec403b600d7 Mon Sep 17 00:00:00 2001 From: Kaspar Schleiser Date: Wed, 22 Sep 2010 15:10:42 +0200 Subject: [PATCH] * import from old firekernel repository --- Jamfile | 72 ++ Jamrules | 74 ++ Jamrules.common | 342 +++++ LICENSE | 674 ++++++++++ README | 9 + board/Jamfile | 3 + board/eZ430-Chronos/Jamfile | 10 + board/eZ430-Chronos/Jamrules.eZ430-Chronos | 12 + board/eZ430-Chronos/board_init.c | 2 + board/eZ430-Chronos/debug_uart.c | 21 + board/eZ430-Chronos/drivers/Jamfile | 5 + board/eZ430-Chronos/drivers/display.c | 519 ++++++++ board/eZ430-Chronos/drivers/display.h | 360 ++++++ board/eZ430-Chronos/drivers/display1.c | 226 ++++ board/eZ430-Chronos/include/board.h | 10 + board/msb-430h/Jamfile | 35 + board/msb-430h/Jamrules.msb-430h | 37 + board/msb-430h/board_init.c | 207 +++ board/msb-430h/debug_uart.c | 21 + board/msb-430h/driver_cc1100.c | 343 +++++ board/msb-430h/include/board.h | 69 + board/msba2/Jamfile | 35 + board/msba2/Jamfile.msba2 | 31 + board/msba2/Jamrules.msba2 | 33 + board/msba2/board_init.c | 156 +++ board/msba2/drivers/Jamfile | 6 + board/msba2/drivers/include/hal-board.h | 68 + board/msba2/drivers/include/sht11-board.h | 63 + board/msba2/drivers/msba2-cc1100.c | 243 ++++ board/msba2/drivers/msba2-ltc4150.c | 65 + board/msba2/drivers/msba2-uart0.c | 205 +++ board/msba2/include/board-conf.h | 68 + board/msba2/include/board.h | 62 + board/msba2/lpc2387-timer3.c | 37 + board/msba2/tools/CHANGES | 23 + board/msba2/tools/COPYING | 339 +++++ board/msba2/tools/Makefile | 43 + board/msba2/tools/README.txt | 144 +++ board/msba2/tools/armtools.txt | 15 + board/msba2/tools/flash.cmd | 2 + board/msba2/tools/flashutil.sh | 113 ++ board/msba2/tools/mkbootc | 28 + board/msba2/tools/mkstaticlist | 47 + board/msba2/tools/obj/boot_23xx.d | 3 + board/msba2/tools/obj/boot_2xxx.d | 3 + board/msba2/tools/obj/chipinfo.d | 8 + board/msba2/tools/obj/control_2xxx.d | 6 + board/msba2/tools/obj/download.d | 19 + board/msba2/tools/obj/ihex.d | 3 + board/msba2/tools/obj/lpc2k_pgm.d | 8 + board/msba2/tools/obj/pseudoterm.d | 6 + board/msba2/tools/obj/serial.d | 3 + board/msba2/tools/obj/uuencode.d | 3 + board/msba2/tools/src/Jamfile | 9 + board/msba2/tools/src/boot.h | 9 + board/msba2/tools/src/boot_23xx.armasm | 32 + board/msba2/tools/src/boot_23xx.c | 5 + board/msba2/tools/src/boot_23xx.h | 2 + board/msba2/tools/src/boot_2xxx.armasm | 15 + board/msba2/tools/src/boot_2xxx.c | 5 + board/msba2/tools/src/boot_2xxx.h | 2 + board/msba2/tools/src/chipinfo.c | 159 +++ board/msba2/tools/src/chipinfo.h | 20 + board/msba2/tools/src/cksum_test.c | 76 ++ board/msba2/tools/src/control_2xxx.c | 31 + board/msba2/tools/src/control_2xxx.h | 8 + board/msba2/tools/src/download.c | 972 ++++++++++++++ board/msba2/tools/src/download.h | 8 + board/msba2/tools/src/gui.c | 387 ++++++ board/msba2/tools/src/gui.h | 3 + board/msba2/tools/src/ihex.c | 229 ++++ board/msba2/tools/src/ihex.h | 7 + board/msba2/tools/src/lpc2k_pgm.c | 98 ++ board/msba2/tools/src/lpc2k_pgm.h | 12 + board/msba2/tools/src/pseudoterm.c | 135 ++ board/msba2/tools/src/serial.c | 350 +++++ board/msba2/tools/src/serial.h | 19 + board/msba2/tools/src/settings.c | 172 +++ board/msba2/tools/src/settings.h | 12 + board/msba2/tools/src/uuencode.c | 98 ++ board/msba2/tools/src/uuencode.h | 3 + board/msba2/tools/termctrl.sh | 22 + board/olimex_lpc2148/Jamfile | 10 + board/olimex_lpc2148/Jamfile.olimex_lpc2148 | 4 + board/olimex_lpc2148/Jamrules.olimex_lpc2148 | 9 + board/olimex_lpc2148/board_init.c | 88 ++ board/olimex_lpc2148/debug_uart.c | 14 + board/olimex_lpc2148/include/board.h | 1 + board/olimex_lpc2148/include/rs232.h | 40 + board/olimex_lpc2148/rs232.c | 65 + board/olimex_lpc2148/tick.c | 63 + board/olimex_lpc2148/tools/lpc2148_flash.gdb | 22 + board/pttu/Jamfile | 35 + board/pttu/Jamfile.pttu | 28 + board/pttu/Jamrules.pttu | 37 + board/pttu/board_init.c | 239 ++++ board/pttu/drivers/Jamfile | 4 + board/pttu/drivers/pttu-uart0.c | 204 +++ board/pttu/include/board.h | 56 + board/pttu/tools/jtag.txt | 14 + board/pttu/tools/olimex-arm-usb-ocd.cfg | 9 + board/pttu/tools/openocd-pttu.cfg | 75 ++ board/pttu/tools/openocd-pttu.sh | 30 + board/pttu/tools/pttu_debug.gdb | 15 + core/Jamfile | 37 + core/bitarithm.c | 65 + core/clist.c | 102 ++ core/hwtimer.c | 223 ++++ core/include/atomic.h | 28 + core/include/bitarithm.h | 98 ++ core/include/clist.h | 47 + core/include/debug.h | 25 + core/include/flags.h | 27 + core/include/hwtimer.h | 129 ++ core/include/hwtimer_arch.h | 62 + core/include/irq.h | 59 + core/include/kernel.h | 96 ++ core/include/kernel_intern.h | 27 + core/include/lpm.h | 60 + core/include/msg.h | 111 ++ core/include/mutex.h | 79 ++ core/include/oneway_malloc.h | 18 + core/include/queue.h | 28 + core/include/scheduler.h | 50 + core/include/tcb.h | 54 + core/include/thread.h | 69 + core/kernel_init.c | 85 ++ core/msg.c | 174 +++ core/mutex.c | 126 ++ core/oneway_malloc.c | 41 + core/queue.c | 137 ++ core/scheduler.c | 161 +++ core/thread.c | 185 +++ cpu/Jamfile | 30 + cpu/arm_common/Jamfile | 40 + cpu/arm_common/Jamrules.arm_common | 53 + cpu/arm_common/VIC.c | 101 ++ cpu/arm_common/arm_cpu.c | 88 ++ cpu/arm_common/atomic.s | 18 + cpu/arm_common/bootloader.c | 183 +++ cpu/arm_common/common.s | 177 +++ cpu/arm_common/hwtimer_cpu.c | 174 +++ cpu/arm_common/include/VIC.h | 96 ++ cpu/arm_common/include/arm_common.h | 114 ++ cpu/arm_common/include/arm_cpu.h | 21 + cpu/arm_common/include/hwtimer_cpu.h | 21 + cpu/arm_common/syscalls.c | 239 ++++ cpu/lpc214x/Jamfile | 33 + cpu/lpc214x/cpu.c | 41 + cpu/lpc214x/include/cpu.h | 33 + cpu/lpc214x/include/lpc2148.h | 24 + cpu/lpc214x/include/lpc214x.h | 438 +++++++ cpu/lpc214x/linkerscript.x | 197 +++ cpu/lpc214x/startup.s | 112 ++ cpu/lpc2387/Jamfile | 39 + cpu/lpc2387/Jamrules.lpc2387 | 31 + cpu/lpc2387/cpu.c | 101 ++ cpu/lpc2387/doc/lpc2387.doc | 48 + cpu/lpc2387/include/cpu-conf.h | 88 ++ cpu/lpc2387/include/cpu.h | 46 + cpu/lpc2387/include/lpc2387-rtc.h | 149 +++ cpu/lpc2387/include/lpc2387.h | 208 +++ cpu/lpc2387/include/lpc23xx.h | 1131 +++++++++++++++++ cpu/lpc2387/linkerscript.x | 194 +++ cpu/lpc2387/lpc2387-gpioint.c | 174 +++ cpu/lpc2387/lpc2387-lpm.c | 134 ++ cpu/lpc2387/lpc2387-rtc.c | 254 ++++ cpu/lpc2387/startup.s | 128 ++ cpu/lpc2387/tools/openocd-lpc2387.cfg | 49 + cpu/msp430/Jamfile | 38 + cpu/msp430/Jamrules.msp430 | 39 + cpu/msp430/atomic.c | 10 + cpu/msp430/cpu.c | 128 ++ cpu/msp430/hwtimer_cpu.c | 151 +++ cpu/msp430/include/cpu-conf.h | 42 + cpu/msp430/include/cpu.h | 131 ++ cpu/msp430/include/errno-base.h | 39 + cpu/msp430/include/errno.h | 109 ++ cpu/msp430/include/hwtimer_cpu.h | 52 + cpu/msp430/include/malloc.h | 9 + cpu/msp430/include/msp430.h | 106 ++ cpu/msp430/irq.c | 24 + cpu/msp430/msp430-main.c | 172 +++ cpu/msp430/startup.c | 16 + doc/doxygen/src/ukleos-footer.html | 2 + doc/doxygen/src/ukleos-header.html | 11 + doc/doxygen/src/ukleos.css | 409 ++++++ doc/doxygen/ukleos.doxyfile | 257 ++++ drivers/Jamfile | 34 + drivers/cc110x/Jamfile | 35 + drivers/cc110x/arch_cc1100.h | 50 + drivers/cc110x/cc1100-csmaca-mac.c | 216 ++++ drivers/cc110x/cc1100-csmaca-mac.h | 68 + drivers/cc110x/cc1100-defaultSettings.c | 124 ++ drivers/cc110x/cc1100-defaultSettings.h | 109 ++ drivers/cc110x/cc1100-interface.h | 217 ++++ drivers/cc110x/cc1100-internal.h | 218 ++++ drivers/cc110x/cc1100.c | 905 +++++++++++++ drivers/cc110x/cc1100.h | 348 +++++ drivers/cc110x/cc1100_phy.c | 863 +++++++++++++ drivers/cc110x/cc1100_phy.h | 156 +++ drivers/cc110x/cc1100_spi.c | 136 ++ drivers/cc110x/cc1100_spi.h | 64 + drivers/include/gpioint.h | 96 ++ drivers/include/ltc4150.h | 14 + drivers/include/ltc4150_arch.h | 57 + drivers/include/sht11.h | 110 ++ drivers/ltc4150.c | 108 ++ drivers/sht11.c | 345 +++++ projects/blinker/Jamfile | 6 + projects/blinker/main.c | 22 + projects/blinker/tests/hello-world | 13 + projects/cc110x/Jamfile | 9 + projects/cc110x/main.c | 83 ++ projects/hello-world/Jamfile | 5 + projects/hello-world/main.c | 12 + projects/hello-world/tests/hello-world | 18 + projects/hello-world/tests/hello-world.py | 11 + projects/hi_earth/Jamfile | 5 + projects/hi_earth/main.c | 53 + projects/long_term/Jamfile | 5 + projects/long_term/main.c | 18 + projects/new_project.sh | 15 + projects/pingpong/Jamfile | 6 + projects/pingpong/main.c | 33 + projects/pingpong/tests/hello-world | 13 + projects/pingpong_sync/Jamfile | 6 + projects/pingpong_sync/main.c | 32 + projects/pingpong_sync/tests/hello-world | 13 + projects/simple_weather_station/Jamfile | 5 + projects/simple_weather_station/main.c | 27 + projects/skel/Jamfile | 5 + projects/skel/main.c | 8 + projects/skel/tests/hello-world | 13 + projects/test_float/Jamfile | 5 + projects/test_float/main.c | 17 + projects/test_getpid/Jamfile | 5 + projects/test_getpid/main.c | 8 + projects/test_hwtimer/Jamfile | 5 + projects/test_hwtimer/main.c | 29 + projects/test_hwtimer/tests/test_ktimer | 29 + projects/test_ltc4150/Jamfile | 5 + projects/test_ltc4150/main.c | 18 + projects/test_periodic_sleep/Jamfile | 5 + projects/test_periodic_sleep/main.c | 26 + .../test_periodic_sleep/tests/hello-world | 13 + projects/test_sleep/Jamfile | 5 + projects/test_sleep/main.c | 44 + projects/test_swtimer/Jamfile | 5 + projects/test_swtimer/main.c | 63 + projects/test_swtimer/primes.h | 80 ++ projects/test_swtimer_remove/Jamfile | 5 + projects/test_swtimer_remove/main.c | 50 + .../test_swtimer_remove/tests/hello-world | 13 + projects/test_thread_exit/Jamfile | 5 + projects/test_thread_exit/main.c | 16 + projects/test_thread_exit/tests/hello-world | 13 + sys/Jamfile | 33 + sys/auto_init.c | 36 + sys/include/auto_init.h | 30 + sys/include/ping.h | 25 + sys/include/radio/radio.h | 99 ++ sys/include/radio/types.h | 95 ++ sys/include/swtimer.h | 141 ++ sys/net/Jamfile | 31 + sys/net/protocol-multiplex.c | 145 +++ sys/net/protocol-multiplex.h | 69 + sys/ping.c | 78 ++ sys/swtimer.c | 306 +++++ testsuite/build_and_generate_html.sh | 10 + testsuite/generate_html.sh | 27 + testsuite/html/footer | 1 + testsuite/html/header | 6 + testsuite/parse_buildlog.sh | 43 + testsuite/run_tests.sh | 43 + testsuite/svn_test_revision.sh | 46 + tools/testsuite/build_and_generate_html.sh | 10 + tools/testsuite/generate_html.sh | 27 + tools/testsuite/html/footer | 1 + tools/testsuite/html/header | 6 + tools/testsuite/parse_buildlog.sh | 43 + tools/testsuite/run_tests.sh | 43 + tools/testsuite/svn_test_revision.sh | 46 + tools/toolchains/build_gnuarm.sh | 170 +++ 284 files changed, 24839 insertions(+) create mode 100644 Jamfile create mode 100644 Jamrules create mode 100644 Jamrules.common create mode 100644 LICENSE create mode 100644 README create mode 100644 board/Jamfile create mode 100644 board/eZ430-Chronos/Jamfile create mode 100644 board/eZ430-Chronos/Jamrules.eZ430-Chronos create mode 100644 board/eZ430-Chronos/board_init.c create mode 100644 board/eZ430-Chronos/debug_uart.c create mode 100644 board/eZ430-Chronos/drivers/Jamfile create mode 100644 board/eZ430-Chronos/drivers/display.c create mode 100644 board/eZ430-Chronos/drivers/display.h create mode 100644 board/eZ430-Chronos/drivers/display1.c create mode 100644 board/eZ430-Chronos/include/board.h create mode 100644 board/msb-430h/Jamfile create mode 100644 board/msb-430h/Jamrules.msb-430h create mode 100644 board/msb-430h/board_init.c create mode 100644 board/msb-430h/debug_uart.c create mode 100644 board/msb-430h/driver_cc1100.c create mode 100644 board/msb-430h/include/board.h create mode 100644 board/msba2/Jamfile create mode 100644 board/msba2/Jamfile.msba2 create mode 100644 board/msba2/Jamrules.msba2 create mode 100644 board/msba2/board_init.c create mode 100644 board/msba2/drivers/Jamfile create mode 100644 board/msba2/drivers/include/hal-board.h create mode 100644 board/msba2/drivers/include/sht11-board.h create mode 100644 board/msba2/drivers/msba2-cc1100.c create mode 100644 board/msba2/drivers/msba2-ltc4150.c create mode 100644 board/msba2/drivers/msba2-uart0.c create mode 100644 board/msba2/include/board-conf.h create mode 100644 board/msba2/include/board.h create mode 100644 board/msba2/lpc2387-timer3.c create mode 100644 board/msba2/tools/CHANGES create mode 100644 board/msba2/tools/COPYING create mode 100644 board/msba2/tools/Makefile create mode 100644 board/msba2/tools/README.txt create mode 100644 board/msba2/tools/armtools.txt create mode 100755 board/msba2/tools/flash.cmd create mode 100755 board/msba2/tools/flashutil.sh create mode 100644 board/msba2/tools/mkbootc create mode 100644 board/msba2/tools/mkstaticlist create mode 100644 board/msba2/tools/obj/boot_23xx.d create mode 100644 board/msba2/tools/obj/boot_2xxx.d create mode 100644 board/msba2/tools/obj/chipinfo.d create mode 100644 board/msba2/tools/obj/control_2xxx.d create mode 100644 board/msba2/tools/obj/download.d create mode 100644 board/msba2/tools/obj/ihex.d create mode 100644 board/msba2/tools/obj/lpc2k_pgm.d create mode 100644 board/msba2/tools/obj/pseudoterm.d create mode 100644 board/msba2/tools/obj/serial.d create mode 100644 board/msba2/tools/obj/uuencode.d create mode 100644 board/msba2/tools/src/Jamfile create mode 100644 board/msba2/tools/src/boot.h create mode 100644 board/msba2/tools/src/boot_23xx.armasm create mode 100644 board/msba2/tools/src/boot_23xx.c create mode 100644 board/msba2/tools/src/boot_23xx.h create mode 100644 board/msba2/tools/src/boot_2xxx.armasm create mode 100644 board/msba2/tools/src/boot_2xxx.c create mode 100644 board/msba2/tools/src/boot_2xxx.h create mode 100644 board/msba2/tools/src/chipinfo.c create mode 100644 board/msba2/tools/src/chipinfo.h create mode 100644 board/msba2/tools/src/cksum_test.c create mode 100644 board/msba2/tools/src/control_2xxx.c create mode 100644 board/msba2/tools/src/control_2xxx.h create mode 100644 board/msba2/tools/src/download.c create mode 100644 board/msba2/tools/src/download.h create mode 100644 board/msba2/tools/src/gui.c create mode 100644 board/msba2/tools/src/gui.h create mode 100644 board/msba2/tools/src/ihex.c create mode 100644 board/msba2/tools/src/ihex.h create mode 100644 board/msba2/tools/src/lpc2k_pgm.c create mode 100644 board/msba2/tools/src/lpc2k_pgm.h create mode 100644 board/msba2/tools/src/pseudoterm.c create mode 100644 board/msba2/tools/src/serial.c create mode 100644 board/msba2/tools/src/serial.h create mode 100644 board/msba2/tools/src/settings.c create mode 100644 board/msba2/tools/src/settings.h create mode 100644 board/msba2/tools/src/uuencode.c create mode 100644 board/msba2/tools/src/uuencode.h create mode 100755 board/msba2/tools/termctrl.sh create mode 100644 board/olimex_lpc2148/Jamfile create mode 100644 board/olimex_lpc2148/Jamfile.olimex_lpc2148 create mode 100644 board/olimex_lpc2148/Jamrules.olimex_lpc2148 create mode 100644 board/olimex_lpc2148/board_init.c create mode 100644 board/olimex_lpc2148/debug_uart.c create mode 100644 board/olimex_lpc2148/include/board.h create mode 100644 board/olimex_lpc2148/include/rs232.h create mode 100644 board/olimex_lpc2148/rs232.c create mode 100644 board/olimex_lpc2148/tick.c create mode 100644 board/olimex_lpc2148/tools/lpc2148_flash.gdb create mode 100644 board/pttu/Jamfile create mode 100644 board/pttu/Jamfile.pttu create mode 100644 board/pttu/Jamrules.pttu create mode 100644 board/pttu/board_init.c create mode 100644 board/pttu/drivers/Jamfile create mode 100644 board/pttu/drivers/pttu-uart0.c create mode 100644 board/pttu/include/board.h create mode 100644 board/pttu/tools/jtag.txt create mode 100644 board/pttu/tools/olimex-arm-usb-ocd.cfg create mode 100644 board/pttu/tools/openocd-pttu.cfg create mode 100755 board/pttu/tools/openocd-pttu.sh create mode 100644 board/pttu/tools/pttu_debug.gdb create mode 100644 core/Jamfile create mode 100644 core/bitarithm.c create mode 100644 core/clist.c create mode 100644 core/hwtimer.c create mode 100644 core/include/atomic.h create mode 100644 core/include/bitarithm.h create mode 100644 core/include/clist.h create mode 100644 core/include/debug.h create mode 100644 core/include/flags.h create mode 100644 core/include/hwtimer.h create mode 100644 core/include/hwtimer_arch.h create mode 100644 core/include/irq.h create mode 100644 core/include/kernel.h create mode 100644 core/include/kernel_intern.h create mode 100644 core/include/lpm.h create mode 100644 core/include/msg.h create mode 100644 core/include/mutex.h create mode 100644 core/include/oneway_malloc.h create mode 100644 core/include/queue.h create mode 100644 core/include/scheduler.h create mode 100644 core/include/tcb.h create mode 100644 core/include/thread.h create mode 100644 core/kernel_init.c create mode 100644 core/msg.c create mode 100644 core/mutex.c create mode 100644 core/oneway_malloc.c create mode 100644 core/queue.c create mode 100644 core/scheduler.c create mode 100644 core/thread.c create mode 100644 cpu/Jamfile create mode 100644 cpu/arm_common/Jamfile create mode 100644 cpu/arm_common/Jamrules.arm_common create mode 100644 cpu/arm_common/VIC.c create mode 100644 cpu/arm_common/arm_cpu.c create mode 100644 cpu/arm_common/atomic.s create mode 100644 cpu/arm_common/bootloader.c create mode 100644 cpu/arm_common/common.s create mode 100644 cpu/arm_common/hwtimer_cpu.c create mode 100644 cpu/arm_common/include/VIC.h create mode 100644 cpu/arm_common/include/arm_common.h create mode 100644 cpu/arm_common/include/arm_cpu.h create mode 100644 cpu/arm_common/include/hwtimer_cpu.h create mode 100644 cpu/arm_common/syscalls.c create mode 100644 cpu/lpc214x/Jamfile create mode 100644 cpu/lpc214x/cpu.c create mode 100644 cpu/lpc214x/include/cpu.h create mode 100644 cpu/lpc214x/include/lpc2148.h create mode 100644 cpu/lpc214x/include/lpc214x.h create mode 100644 cpu/lpc214x/linkerscript.x create mode 100644 cpu/lpc214x/startup.s create mode 100644 cpu/lpc2387/Jamfile create mode 100644 cpu/lpc2387/Jamrules.lpc2387 create mode 100644 cpu/lpc2387/cpu.c create mode 100644 cpu/lpc2387/doc/lpc2387.doc create mode 100644 cpu/lpc2387/include/cpu-conf.h create mode 100644 cpu/lpc2387/include/cpu.h create mode 100644 cpu/lpc2387/include/lpc2387-rtc.h create mode 100644 cpu/lpc2387/include/lpc2387.h create mode 100644 cpu/lpc2387/include/lpc23xx.h create mode 100644 cpu/lpc2387/linkerscript.x create mode 100644 cpu/lpc2387/lpc2387-gpioint.c create mode 100644 cpu/lpc2387/lpc2387-lpm.c create mode 100644 cpu/lpc2387/lpc2387-rtc.c create mode 100644 cpu/lpc2387/startup.s create mode 100644 cpu/lpc2387/tools/openocd-lpc2387.cfg create mode 100644 cpu/msp430/Jamfile create mode 100644 cpu/msp430/Jamrules.msp430 create mode 100644 cpu/msp430/atomic.c create mode 100644 cpu/msp430/cpu.c create mode 100644 cpu/msp430/hwtimer_cpu.c create mode 100644 cpu/msp430/include/cpu-conf.h create mode 100644 cpu/msp430/include/cpu.h create mode 100644 cpu/msp430/include/errno-base.h create mode 100644 cpu/msp430/include/errno.h create mode 100644 cpu/msp430/include/hwtimer_cpu.h create mode 100644 cpu/msp430/include/malloc.h create mode 100644 cpu/msp430/include/msp430.h create mode 100644 cpu/msp430/irq.c create mode 100644 cpu/msp430/msp430-main.c create mode 100644 cpu/msp430/startup.c create mode 100644 doc/doxygen/src/ukleos-footer.html create mode 100644 doc/doxygen/src/ukleos-header.html create mode 100644 doc/doxygen/src/ukleos.css create mode 100644 doc/doxygen/ukleos.doxyfile create mode 100644 drivers/Jamfile create mode 100755 drivers/cc110x/Jamfile create mode 100644 drivers/cc110x/arch_cc1100.h create mode 100644 drivers/cc110x/cc1100-csmaca-mac.c create mode 100644 drivers/cc110x/cc1100-csmaca-mac.h create mode 100644 drivers/cc110x/cc1100-defaultSettings.c create mode 100644 drivers/cc110x/cc1100-defaultSettings.h create mode 100644 drivers/cc110x/cc1100-interface.h create mode 100755 drivers/cc110x/cc1100-internal.h create mode 100644 drivers/cc110x/cc1100.c create mode 100644 drivers/cc110x/cc1100.h create mode 100644 drivers/cc110x/cc1100_phy.c create mode 100755 drivers/cc110x/cc1100_phy.h create mode 100644 drivers/cc110x/cc1100_spi.c create mode 100644 drivers/cc110x/cc1100_spi.h create mode 100644 drivers/include/gpioint.h create mode 100644 drivers/include/ltc4150.h create mode 100644 drivers/include/ltc4150_arch.h create mode 100644 drivers/include/sht11.h create mode 100644 drivers/ltc4150.c create mode 100644 drivers/sht11.c create mode 100644 projects/blinker/Jamfile create mode 100644 projects/blinker/main.c create mode 100755 projects/blinker/tests/hello-world create mode 100644 projects/cc110x/Jamfile create mode 100644 projects/cc110x/main.c create mode 100644 projects/hello-world/Jamfile create mode 100644 projects/hello-world/main.c create mode 100755 projects/hello-world/tests/hello-world create mode 100644 projects/hello-world/tests/hello-world.py create mode 100644 projects/hi_earth/Jamfile create mode 100644 projects/hi_earth/main.c create mode 100644 projects/long_term/Jamfile create mode 100644 projects/long_term/main.c create mode 100644 projects/new_project.sh create mode 100644 projects/pingpong/Jamfile create mode 100644 projects/pingpong/main.c create mode 100755 projects/pingpong/tests/hello-world create mode 100644 projects/pingpong_sync/Jamfile create mode 100644 projects/pingpong_sync/main.c create mode 100755 projects/pingpong_sync/tests/hello-world create mode 100644 projects/simple_weather_station/Jamfile create mode 100644 projects/simple_weather_station/main.c create mode 100644 projects/skel/Jamfile create mode 100644 projects/skel/main.c create mode 100755 projects/skel/tests/hello-world create mode 100644 projects/test_float/Jamfile create mode 100644 projects/test_float/main.c create mode 100644 projects/test_getpid/Jamfile create mode 100644 projects/test_getpid/main.c create mode 100644 projects/test_hwtimer/Jamfile create mode 100644 projects/test_hwtimer/main.c create mode 100755 projects/test_hwtimer/tests/test_ktimer create mode 100644 projects/test_ltc4150/Jamfile create mode 100644 projects/test_ltc4150/main.c create mode 100644 projects/test_periodic_sleep/Jamfile create mode 100644 projects/test_periodic_sleep/main.c create mode 100755 projects/test_periodic_sleep/tests/hello-world create mode 100644 projects/test_sleep/Jamfile create mode 100644 projects/test_sleep/main.c create mode 100644 projects/test_swtimer/Jamfile create mode 100644 projects/test_swtimer/main.c create mode 100644 projects/test_swtimer/primes.h create mode 100644 projects/test_swtimer_remove/Jamfile create mode 100644 projects/test_swtimer_remove/main.c create mode 100755 projects/test_swtimer_remove/tests/hello-world create mode 100644 projects/test_thread_exit/Jamfile create mode 100644 projects/test_thread_exit/main.c create mode 100755 projects/test_thread_exit/tests/hello-world create mode 100644 sys/Jamfile create mode 100644 sys/auto_init.c create mode 100644 sys/include/auto_init.h create mode 100644 sys/include/ping.h create mode 100644 sys/include/radio/radio.h create mode 100644 sys/include/radio/types.h create mode 100755 sys/include/swtimer.h create mode 100644 sys/net/Jamfile create mode 100644 sys/net/protocol-multiplex.c create mode 100644 sys/net/protocol-multiplex.h create mode 100644 sys/ping.c create mode 100644 sys/swtimer.c create mode 100755 testsuite/build_and_generate_html.sh create mode 100755 testsuite/generate_html.sh create mode 100644 testsuite/html/footer create mode 100644 testsuite/html/header create mode 100755 testsuite/parse_buildlog.sh create mode 100755 testsuite/run_tests.sh create mode 100755 testsuite/svn_test_revision.sh create mode 100755 tools/testsuite/build_and_generate_html.sh create mode 100755 tools/testsuite/generate_html.sh create mode 100644 tools/testsuite/html/footer create mode 100644 tools/testsuite/html/header create mode 100755 tools/testsuite/parse_buildlog.sh create mode 100755 tools/testsuite/run_tests.sh create mode 100755 tools/testsuite/svn_test_revision.sh create mode 100755 tools/toolchains/build_gnuarm.sh diff --git a/Jamfile b/Jamfile new file mode 100644 index 0000000000..278cc95015 --- /dev/null +++ b/Jamfile @@ -0,0 +1,72 @@ +# ****************************************************************************** +# Copyright 2009, Freie Universitaet Berlin (FUB). All rights reserved. +# +# These sources were developed at the Freie Universitaet Berlin, Computer +# Systems and Telematics group (http://cst.mi.fu-berlin.de). +# ------------------------------------------------------------------------------ +# This file is part of FeuerWare. +# +# This program is free software: you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation, either version 3 of the License, or (at your option) any later +# version. +# +# FeuerWare is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with +# this program. If not, see http://www.gnu.org/licenses/ . +# ------------------------------------------------------------------------------ +# For further information and questions please use the web site +# http://scatterweb.mi.fu-berlin.de +# and the mailinglist (subscription via web site) +# scatterweb@lists.spline.inf.fu-berlin.de +# ****************************************************************************** +# $Id$ + +SubDir TOP ; + +# +# Target directory: bin directory located in BUILD_ROOT +# +TARGET_DIR ?= [ FPath $(BUILD_ROOT) bin $(BOARD) $(PROJECT) ] ; +LOCATE_TARGET = $(TARGET_DIR) ; +ALL_LOCATE_TARGET = $(TARGET_DIR) ; + +echo "Building project '$(PROJECT)' for '$(BOARD)' board." ; + +# +# Buil utility targets +# +Help ? ; # display usage from manual +Help help ; +Help usage ; +Help targets ; +Cleanall cleanall ; # clean all binaries + +# +# Main target +# +Main $(TARGET) ; +Depends all : $(TARGET:S=.hex) ; # always build a hex-file + +LOCATE on $(TARGET) = bin ; +LOCATE on $(TARGET:S=.hex) = bin ; + +# +# Utility targets +# +Doc doc ; # build the documentation +Flash flash : $(TARGET:S=.hex) ; +Reset reset ; + +Debug debug : $(TARGET) ; +ListModules listmodules ; +ShowFlags showflags : $(TARGET) ; + +SubInclude TOP projects $(PROJECT) ; +SubInclude TOP sys ; +SubInclude TOP core ; +SubInclude TOP drivers ; +SubInclude TOP board ; diff --git a/Jamrules b/Jamrules new file mode 100644 index 0000000000..6ae86240f2 --- /dev/null +++ b/Jamrules @@ -0,0 +1,74 @@ +# ****************************************************************************** +# Copyright 2009, Freie Universitaet Berlin (FUB). All rights reserved. +# +# These sources were developed at the Freie Universitaet Berlin, Computer +# Systems and Telematics group (http://cst.mi.fu-berlin.de). +# ------------------------------------------------------------------------------ +# This file is part of FeuerWare. +# +# This program is free software: you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation, either version 3 of the License, or (at your option) any later +# version. +# +# FeuerWare is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with +# this program. If not, see http://www.gnu.org/licenses/ . +# ------------------------------------------------------------------------------ +# For further information and questions please use the web site +# http://scatterweb.mi.fu-berlin.de +# and the mailinglist (subscription via web site) +# scatterweb@lists.spline.inf.fu-berlin.de +# ****************************************************************************** +# $Id$ + +# +# Include build system functionality +# +include $(TOP)$(SLASH)Jamrules.common ; + +# +# Setup FeuerWare build system configuration (default values for common options) +# +PROJECT = $(PROJECT:E=hello-world) ; +BOARD = $(BOARD:E=msba2) ; +SUFFIX ?= "" ; # must be at least "" !!! +TARGET = "$(BOARD)-$(PROJECT)$(SUFFIX)$(SUFEXE)" ; # main target binary +OPENOCD_IF ?= olimex-jtag-tiny-a ; + +if $(NT) || $(OS) = CYGWIN { + PORT = $(PORT:E=1) ; +} else { + PORT = $(PORT:E=/dev/ttyUSB0) ; +} + +CCFLAGS += -DBOARD=BOARD_$(BOARD:U) ; + +# +# core source directories +HDRS += $(TOP) ; +HDRS += [ FPath $(TOP) core include ] ; +HDRS += [ FPath $(TOP) hal include ] ; +HDRS += [ FPath $(TOP) sys include ] [ FPath $(TOP) sys config ] [ FPath $(TOP) sys drivers include ] [ FPath $(TOP) sys drivers cc110x ] [ FPath $(TOP) sys drivers nanopan5375 ] ; +HDRS += [ FPath $(TOP) sys net ] ; +HDRS += [ FPath $(TOP) sys lib ] [ FPath $(TOP) sys lib fat include ] ; +HDRS += [ FPath $(TOP) sys lib gps ] [ FPath $(TOP) sys lib gps drivers ] [ FPath $(TOP) sys lib gps geo ] ; +HDRS += [ FPath $(TOP) sys net phy ] [ FPath $(TOP) sys net mm ] ; + +# Include board files +include [ FPath $(TOP) board $(BOARD) Jamrules.$(BOARD) ] ; +# Include cpu files +include [ FPath $(TOP) cpu $(CPU) Jamrules.$(CPU) ] ; + +# +# standard target source directories +HDRS += [ FPath $(TOP) board $(BOARD) include ] ; +HDRS += [ FPath $(TOP) cpu $(CPU) include ] ; +HDRS += [ FPath $(TOP) projects $(PROJECT) ] ; + +# drivers +HDRS += [ FPath $(TOP) drivers include ] ; +HDRS += [ FPath $(TOP) drivers cc110x ] ; diff --git a/Jamrules.common b/Jamrules.common new file mode 100644 index 0000000000..014c6813f9 --- /dev/null +++ b/Jamrules.common @@ -0,0 +1,342 @@ +# ****************************************************************************** +# Copyright 2009, Freie Universitaet Berlin (FUB). All rights reserved. +# +# These sources were developed at the Freie Universitaet Berlin, Computer +# Systems and Telematics group (http://cst.mi.fu-berlin.de). +# ------------------------------------------------------------------------------ +# This file is part of FeuerWare. +# +# This program is free software: you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation, either version 3 of the License, or (at your option) any later +# version. +# +# FeuerWare is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with +# this program. If not, see http://www.gnu.org/licenses/ . +# ------------------------------------------------------------------------------ +# For further information and questions please use the web site +# http://scatterweb.mi.fu-berlin.de +# and the mailinglist (subscription via web site) +# scatterweb@lists.spline.inf.fu-berlin.de +# ****************************************************************************** +# $Id$ + +# +# OS specifics +# +if $(NT) { + POSIXSHELL = sh ; + NULLDEV = NUL ; + CAT = type ; + NOARSCAN = true ; + + # redefine build rules for gcc on NT + SUFOBJ = .o ; + SUFLIB = .a ; + actions As + { + $(AS) $(ASFLAGS) $(ASHDRS) -o $(<) $(>) + } + actions Cc + { + $(CC) -c -o $(<) $(CCFLAGS) -D$(MODULE_DEFINES) $(CCDEFS) $(CCHDRS) $(>) + } + rule FDefines { return -D$(<) ; } + rule FIncludes { return -I$(<) ; } + +} else { + NULLDEV = /dev/null ; + CAT = cat ; + RM = rm -rf ; + + # use english language output for gcc + actions Cc + { + LANG=C $(CC) -c -o $(<) $(CCFLAGS) -D$(MODULE_DEFINES) $(CCDEFS) $(CCHDRS) $(>) + } + + switch $(OS) { + case CYGWIN : + # archive scanning does not work on cygwin, so leave object files + NOARSCAN = true ; + } +} + +# +# Plausbility checks and defaults +# +SUFEXE = .elf ; + +# +# Rules and Actions +# + +# +# Concatenates path-segments into a OS specific path string +# Usage: PATH = [ FPath path-segments ] ; +rule FPath +{ + return $(<:J=$(SLASH)) ; +} + +# +# Generate object archive +actions updated together piecemeal Archive +{ + $(AR) $(ARFLAGS) $(<) $(>) +} + +# +# Link target +rule Link +{ + # add map file + Clean clean : $(<:S=.map) ; + # generation of hex file + Hexfile $(<:S=.hex) : $(<) ; +} +actions Link bind NEEDLIBS +{ + echo "Old firmware size:" + $(TOOLCHAIN)size $(<) 2> $(NULLDEV) || echo " No old binary for size comparison..." + + $(LINK) $(LINKFLAGS) -o $(<) $(UNDEFS) $(>) -Wl,--start-group $(NEEDLIBS) $(LINKLIBS) -lm -Wl,--end-group -Wl,-Map=$(<:S=.map) || $(RM) -f $(<) $(<:S=.map) $(<:S=.hex) + + echo "New firmware size:" + $(TOOLCHAIN)size $(<) +} + +# +# Clean binaries +actions piecemeal together existing Clean +{ + # remove all jam targets + $(RM) $(>) +} + +# +# Clean binaries regardless of project and board +rule Cleanall { } +actions Cleanall +{ + echo "> Cleaning binaries" + $(RM) bin$(SLASH)* + make -C $(TOP)$(SLASH)doc clean +} + +# +# Display usage text from manual +rule Help { } +actions Help +{ + $(CAT) $(TOP)$(SLASH)doc$(SLASH)src$(SLASH)manual$(SLASH)examples$(SLASH)jam-usage.txt +} + +# +# Compile documentation +rule Doc { } +actions Doc +{ + make -C $(TOP)$(SLASH)doc all +} + +# +# Generate hex-file from binary +rule Hexfile +{ + MakeLocate $(<) : $(LOCATE_TARGET) ; + Depends $(<) : $(>) ; + SEARCH on $(>) = $(LOCATE_TARGET) ; + Clean clean : $(<) ; +} +actions Hexfile +{ + $(OBJCOPY) -O ihex $(>) $(<) +} + +# +# Program binary to target device +rule Flash +{ + Depends $(<) : $(>) ; +} +actions Flash +{ + $(FLASHER) $(FLASHFLAGS) $(>) +} + +# Reset connected sensor node +actions Reset +{ + $(RESET) > /dev/null 2>&1 +} + +# +# Run debug server +rule Debug +{ + Depends $(<) : $(>) ; +} +actions Debug +{ + $(GDB) $(GDBFLAGS) $(>) +} + +# +# Rules for convenient module building & dependency tracking +rule Module +{ + local _m = $(<:S=$(SUFLIB)) ; + +# echo Module Name: $(<) Files: $(>) Dependencies: $(3) ; + + DEFINED_MODULES += $(_m) ; + + ModuleFromObjects $(<) : $(>:S=$(SUFOBJ)) ; + ObjectsNoDep $(>) ; + + ModuleDepends $(_m) : $(3) ; + + if $(_m) in $(USE_MODULES) { + UseModule $(_m) ; + } +} + +# Add a pre-built library as module +# Syntax: BinModule ; +rule BinModule +{ + local _m = $(<:S=$(SUFLIB)) ; + + DEFINED_MODULES += $(_m) ; + BINARY_MODULES += $(_m) ; + + ModuleDepends $(_m) : $(3) ; + + if $(_m) in $(USE_MODULES) { + UseModule $(_m) ; + } +} + +rule ModuleDepends +{ + local _m = $(<:S=$(SUFLIB)) ; + local _d = $(>:S=$(SUFLIB)) ; + +# for DEP in $(_d) { + Depends $(_m) : $(_d) ; + DEPENDS.$(_m) += $(_d) ; +# } +} + +rule UseModule +{ + local _m = $(<:S=$(SUFLIB)) ; + + if $(_m) in $(BINARY_MODULES) { + local _l _s ; + _l = $(<:S=$(SUFLIB)) ; # name of the library file + _s = [ FGristFiles $(_l) ] ; # source + MakeLocate $(_l) : $(LOCATE_TARGET) ; # locate to bin directory + File $(TARGET_DIR)/$(_l) : $(_s) ; + } + +# echo UseModule $(<) ; + if ! $(_m) in $(DEFINED_MODULES) { +# echo Module not defined yet. ; + USE_MODULES += $(_m) ; + } else { + LinkLibraries $(TARGET) : $(<) ; + local _mdefine = MODULE_$(_m:S=:U) ; + if ! $(_mdefine) in $(MODULE_DEFINES) { + MODULE_DEFINES += $(_mdefine) ; + } +# echo Dependencies of $(_m): $(DEPENDS.$(_m)) ; + for DEP in $(DEPENDS.$(_m)) { + UseModule $(DEP) ; + } + } +} + +# (slightly modified version of LibraryFromObjects) +rule ModuleFromObjects +{ + local _i _l _s ; + + # Add grist to file names + + _s = [ FGristFiles $(>) ] ; + _l = $(<:S=$(SUFLIB)) ; + + # Set LOCATE for the library and its contents. The bound + # value shows up as $(NEEDLIBS) on the Link actions. + # For compatibility, we only do this if the library doesn't + # already have a path. + + if ! $(_l:D) + { + MakeLocate $(_l) $(_l)($(_s:BS)) : $(LOCATE_TARGET) ; + } + + if $(NOARSCAN) + { + # If we can't scan the library to timestamp its contents, + # we have to just make the library depend directly on the + # on-disk object files. + + Depends $(_l) : $(_s) ; + } + else + { + # If we can scan the library, we make the library depend + # on its members and each member depend on the on-disk + # object file. + + Depends $(_l) : $(_l)($(_s:BS)) ; + + for _i in $(_s) + { + Depends $(_l)($(_i:BS)) : $(_i) ; + } + } + + Clean clean : $(_l) ; + + if $(CRELIB) { CreLib $(_l) : $(_s[1]) ; } + + Archive $(_l) : $(_s) ; + + if $(RANLIB) { Ranlib $(_l) ; } + + # If we can't scan the library, we have to leave the .o's around. + + if ! ( $(NOARSCAN) || $(NOARUPDATE) ) { RmTemps $(_l) : $(_s) ; } +} + +# +# Like Objects, but doesn't set dependencies on obj pѕeudotarget. +rule ObjectsNoDep +{ + local _i ; + + for _i in [ FGristFiles $(<) ] + { + Object $(_i:S=$(SUFOBJ)) : $(_i) ; + } +} + +actions ListModules { + echo $(MODULE_DEFINES) | tr ' ' '\n' | sort +} + +actions ShowFlags { + echo "CCFLAGS: " + echo $(CCFLAGS) $(CCDEFS) -D$(MODULE_DEFINES) | tr ' ' '\n ' | sort + echo "" | $(CC) -E -dD - +} + + diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000000..94a9ed024d --- /dev/null +++ b/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/README b/README new file mode 100644 index 0000000000..aed49aaf32 --- /dev/null +++ b/README @@ -0,0 +1,9 @@ +License +======= +* All sources and binaries that have been developed at Freie Universität Berlin are + licensed under the GNU General Public License version 3 as published by the + Free Software Foundation. +* Some external sources, especially files developed by SICS are published under + a separate license. + +All code files contain licensing information. diff --git a/board/Jamfile b/board/Jamfile new file mode 100644 index 0000000000..ad37fbe5b6 --- /dev/null +++ b/board/Jamfile @@ -0,0 +1,3 @@ +SubDir TOP board ; + +SubInclude TOP board $(BOARD) ; diff --git a/board/eZ430-Chronos/Jamfile b/board/eZ430-Chronos/Jamfile new file mode 100644 index 0000000000..ea723c95a9 --- /dev/null +++ b/board/eZ430-Chronos/Jamfile @@ -0,0 +1,10 @@ +SubDir TOP board eZ430-Chronos ; + +HDRS += $(TOP)/board/$(CPU)/include ; + +Module board : debug_uart.c board_init.c ; +UseModule board ; + +SubInclude TOP board $(BOARD) drivers ; +SubInclude TOP cpu $(CPU) ; + diff --git a/board/eZ430-Chronos/Jamrules.eZ430-Chronos b/board/eZ430-Chronos/Jamrules.eZ430-Chronos new file mode 100644 index 0000000000..eef3a03017 --- /dev/null +++ b/board/eZ430-Chronos/Jamrules.eZ430-Chronos @@ -0,0 +1,12 @@ +# ****************************************************************************** +# Copyright 2010, Freie Universitaet Berlin (FUB). All rights reserved. +# ****************************************************************************** +# $Id$ + +BOARD = eZ430-Chronos ; +CPU = msp430 ; +MCU = cc430x6137 ; + +FLASHER ?= mspdebug ; +FLASHFLAGS ?= rf2500 ; + diff --git a/board/eZ430-Chronos/board_init.c b/board/eZ430-Chronos/board_init.c new file mode 100644 index 0000000000..aa52e65af9 --- /dev/null +++ b/board/eZ430-Chronos/board_init.c @@ -0,0 +1,2 @@ +void board_init() { +} diff --git a/board/eZ430-Chronos/debug_uart.c b/board/eZ430-Chronos/debug_uart.c new file mode 100644 index 0000000000..d80c9c6e83 --- /dev/null +++ b/board/eZ430-Chronos/debug_uart.c @@ -0,0 +1,21 @@ +#include +#include "board.h" + +#define UART1_TX TXBUF1 +#define UART1_WAIT_TXDONE() while( (UTCTL1 & TXEPT) == 0 ) { _NOP(); } + + +int putchar(int c) +{ +// UART1_TX = c; +// UART1_WAIT_TXDONE(); +// +// if (c == 10) { +// UART1_TX = 13; +// UART1_WAIT_TXDONE(); +// } + + return c; +} + + diff --git a/board/eZ430-Chronos/drivers/Jamfile b/board/eZ430-Chronos/drivers/Jamfile new file mode 100644 index 0000000000..b2fb968fae --- /dev/null +++ b/board/eZ430-Chronos/drivers/Jamfile @@ -0,0 +1,5 @@ +SubDir TOP board eZ430-Chronos drivers ; + +UseModule board_common ; + +Module board_common : display.c display1.c ; diff --git a/board/eZ430-Chronos/drivers/display.c b/board/eZ430-Chronos/drivers/display.c new file mode 100644 index 0000000000..c0418f544e --- /dev/null +++ b/board/eZ430-Chronos/drivers/display.c @@ -0,0 +1,519 @@ +// ************************************************************************************************* +// +// Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/ +// +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 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. +// +// Neither the name of Texas Instruments Incorporated 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 COPYRIGHT HOLDERS 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 COPYRIGHT +// OWNER 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. +// +// ************************************************************************************************* +// Display functions. +// ************************************************************************************************* + + +// ************************************************************************************************* +// Include section + +// system +#include + +// driver +#include "cc430x613x.h" +#include "display.h" + + +// ************************************************************************************************* +// Prototypes section +void write_lcd_mem(uint8_t * lcdmem, uint8_t bits, uint8_t bitmask, uint8_t state); +void clear_line(uint8_t line); +void display_symbol(uint8_t symbol, uint8_t mode); +void display_char(uint8_t segment, uint8_t chr, uint8_t mode); +void display_chars(uint8_t segments, uint8_t * str, uint8_t mode); + + +// ************************************************************************************************* +// Defines section + + + +// ************************************************************************************************* +// Global Variable section + +// Display flags +volatile s_display_flags display; + +// Global return string for itoa function +uint8_t itoa_str[8]; + + + +// ************************************************************************************************* +// @fn lcd_init +// @brief Erase LCD memory. Init LCD peripheral. +// @param none +// @return none +// ************************************************************************************************* +void lcd_init(void) +{ + // Clear entire display memory + LCDBMEMCTL |= LCDCLRBM + LCDCLRM; + + // LCD_FREQ = ACLK/16/8 = 256Hz + // Frame frequency = 256Hz/4 = 64Hz, LCD mux 4, LCD on + LCDBCTL0 = (LCDDIV0 + LCDDIV1 + LCDDIV2 + LCDDIV3) | (LCDPRE0 + LCDPRE1) | LCD4MUX | LCDON; + + // LCB_BLK_FREQ = ACLK/8/4096 = 1Hz + LCDBBLKCTL = LCDBLKPRE0 | LCDBLKPRE1 | LCDBLKDIV0 | LCDBLKDIV1 | LCDBLKDIV2 | LCDBLKMOD0; + + // I/O to COM outputs + P5SEL |= (BIT5 | BIT6 | BIT7); + P5DIR |= (BIT5 | BIT6 | BIT7); + + // Activate LCD output + LCDBPCTL0 = 0xFFFF; // Select LCD segments S0-S15 + LCDBPCTL1 = 0x00FF; // Select LCD segments S16-S22 + +#ifdef USE_LCD_CHARGE_PUMP + // Charge pump voltage generated internally, internal bias (V2-V4) generation + LCDBVCTL = LCDCPEN | VLCD_2_72; +#endif +} + + +// ************************************************************************************************* +// @fn clear_display_all +// @brief Erase LINE1 and LINE2 segments. Clear also function-specific content. +// @param none +// @return none +// ************************************************************************************************* +void clear_display_all(void) +{ + // Clear generic content + clear_line(LINE1); + clear_line(LINE2); + + +} + + +// ************************************************************************************************* +// @fn clear_display +// @brief Erase LINE1 and LINE2 segments. Keep icons. +// @param none +// @return none +// ************************************************************************************************* +void clear_display(void) +{ + clear_line(LINE1); + clear_line(LINE2); +} + + +// ************************************************************************************************* +// @fn clear_line +// @brief Erase segments of a given line. +// @param uint8_t line LINE1, LINE2 +// @return none +// ************************************************************************************************* +void clear_line(uint8_t line) +{ + display_chars(switch_seg(line, LCD_SEG_L1_3_0, LCD_SEG_L2_5_0), NULL, SEG_OFF); + if (line == LINE1) + { + display_symbol(LCD_SEG_L1_DP1, SEG_OFF); + display_symbol(LCD_SEG_L1_DP0, SEG_OFF); + display_symbol(LCD_SEG_L1_COL, SEG_OFF); + } + else // line == LINE2 + { + display_symbol(LCD_SEG_L2_DP, SEG_OFF); + display_symbol(LCD_SEG_L2_COL1, SEG_OFF); + display_symbol(LCD_SEG_L2_COL0, SEG_OFF); + } +} + + +// ************************************************************************************************* +// @fn write_segment +// @brief Write to one or multiple LCD segments +// @param lcdmem Pointer to LCD byte memory +// bits Segments to address +// bitmask Bitmask for particular display item +// mode On, off or blink segments +// @return +// ************************************************************************************************* +void write_lcd_mem(uint8_t * lcdmem, uint8_t bits, uint8_t bitmask, uint8_t state) +{ + if (state == SEG_ON) + { + // Clear segments before writing + *lcdmem = (uint8_t)(*lcdmem & ~bitmask); + + // Set visible segments + *lcdmem = (uint8_t)(*lcdmem | bits); + } + else if (state == SEG_OFF) + { + // Clear segments + *lcdmem = (uint8_t)(*lcdmem & ~bitmask); + } + else if (state == SEG_ON_BLINK_ON) + { + // Clear visible / blink segments before writing + *lcdmem = (uint8_t)(*lcdmem & ~bitmask); + *(lcdmem+0x20) = (uint8_t)(*(lcdmem+0x20) & ~bitmask); + + // Set visible / blink segments + *lcdmem = (uint8_t)(*lcdmem | bits); + *(lcdmem+0x20) = (uint8_t)(*(lcdmem+0x20) | bits); + } + else if (state == SEG_ON_BLINK_OFF) + { + // Clear visible segments before writing + *lcdmem = (uint8_t)(*lcdmem & ~bitmask); + + // Set visible segments + *lcdmem = (uint8_t)(*lcdmem | bits); + + // Clear blink segments + *(lcdmem+0x20) = (uint8_t)(*(lcdmem+0x20) & ~bitmask); + } + else if (state == SEG_OFF_BLINK_OFF) + { + // Clear segments + *lcdmem = (uint8_t)(*lcdmem & ~bitmask); + + // Clear blink segments + *(lcdmem+0x20) = (uint8_t)(*(lcdmem+0x20) & ~bitmask); + } +} + + +// ************************************************************************************************* +// @fn itoa +// @brief Generic integer to array routine. Converts integer n to string. +// Default conversion result has leading zeros, e.g. "00123" +// Option to convert leading '0' into whitespace (blanks) +// @param uint32_t n integer to convert +// uint8_t digits number of digits +// uint8_t blanks fill up result string with number of whitespaces instead of leading zeros +// @return uint8_t string +// ************************************************************************************************* +uint8_t * itoa(uint32_t n, uint8_t digits, uint8_t blanks) +{ + uint8_t i; + uint8_t digits1 = digits; + + // Preset result string + memcpy(itoa_str, "0000000", 7); + + // Return empty string if number of digits is invalid (valid range for digits: 1-7) + if ((digits == 0) || (digits > 7)) return (itoa_str); + + // Numbers 0 .. 180 can be copied from itoa_conversion_table without conversion + if (n <= 180) + { + if (digits >= 3) + { + memcpy(itoa_str+(digits-3), itoa_conversion_table[n], 3); + } + else // digits == 1 || 2 + { + memcpy(itoa_str, itoa_conversion_table[n]+(3-digits), digits); + } + } + else // For n > 180 need to calculate string content + { + // Calculate digits from least to most significant number + do + { + itoa_str[digits-1] = n % 10 + '0'; + n /= 10; + } while (--digits > 0); + } + + // Remove specified number of leading '0', always keep last one + i = 0; + while ((itoa_str[i] == '0') && (i < digits1-1)) + { + if (blanks > 0) + { + // Convert only specified number of leading '0' + itoa_str[i]=' '; + blanks--; + } + i++; + } + + return (itoa_str); +} + + +// ************************************************************************************************* +// @fn display_value1 +// @brief Generic decimal display routine. Used exclusively by set_value function. +// @param uint8_t segments LCD segments where value is displayed +// uint32_t value Integer value to be displayed +// uint8_t digits Number of digits to convert +// uint8_t blanks Number of leadings blanks in itoa result string +// @return none +// ************************************************************************************************* +void display_value1(uint8_t segments, uint32_t value, uint8_t digits, uint8_t blanks, uint8_t disp_mode) +{ + uint8_t * str; + + str = itoa(value, digits, blanks); + + // Display string in blink mode + display_chars(segments, str, disp_mode); +} + + +// ************************************************************************************************* +// @fn display_symbol +// @brief Switch symbol on or off on LCD. +// @param uint8_t symbol A valid LCD symbol (index 0..42) +// uint8_t state SEG_ON, SEG_OFF, SEG_BLINK +// @return none +// ************************************************************************************************* +void display_symbol(uint8_t symbol, uint8_t mode) +{ + uint8_t * lcdmem; + uint8_t bits; + uint8_t bitmask; + + if (symbol <= LCD_SEG_L2_DP) + { + // Get LCD memory address for symbol from table + lcdmem = (uint8_t *)segments_lcdmem[symbol]; + + // Get bits for symbol from table + bits = segments_bitmask[symbol]; + + // Bitmask for symbols equals bits + bitmask = bits; + + // Write LCD memory + write_lcd_mem(lcdmem, bits, bitmask, mode); + } +} + + +// ************************************************************************************************* +// @fn display_char +// @brief Write to 7-segment characters. +// @param uint8_t segment A valid LCD segment +// uint8_t chr Character to display +// uint8_t mode SEG_ON, SEG_OFF, SEG_BLINK +// @return none +// ************************************************************************************************* +void display_char(uint8_t segment, uint8_t chr, uint8_t mode) +{ + uint8_t * lcdmem; // Pointer to LCD memory + uint8_t bitmask; // Bitmask for character + uint8_t bits, bits1; // Bits to write + + // Write to single 7-segment character + if ((segment >= LCD_SEG_L1_3) && (segment <= LCD_SEG_L2_DP)) + { + // Get LCD memory address for segment from table + lcdmem = (uint8_t *)segments_lcdmem[segment]; + + // Get bitmask for character from table + bitmask = segments_bitmask[segment]; + + // Get bits from font set + if ((chr >= 0x30) && (chr <= 0x5A)) + { + // Use font set + bits = lcd_font[chr-0x30]; + } + else if (chr == 0x2D) + { + // '-' not in font set + bits = BIT1; + } + else + { + // Other characters map to ' ' (blank) + bits = 0; + } + + // When addressing LINE2 7-segment characters need to swap high- and low-nibble, + // because LCD COM/SEG assignment is mirrored against LINE1 + if (segment >= LCD_SEG_L2_5) + { + bits1 = ((bits << 4) & 0xF0) | ((bits >> 4) & 0x0F); + bits = bits1; + + // When addressing LCD_SEG_L2_5, need to convert ASCII '1' and 'L' to 1 bit, + // because LCD COM/SEG assignment is special for this incomplete character + if (segment == LCD_SEG_L2_5) + { + if ((chr == '1') || (chr == 'L')) bits = BIT7; + } + } + + // Physically write to LCD memory + write_lcd_mem(lcdmem, bits, bitmask, mode); + } +} + + +// ************************************************************************************************* +// @fn display_chars +// @brief Write to consecutive 7-segment characters. +// @param uint8_t segments LCD segment array +// uint8_t * str Pointer to a string +// uint8_t mode SEG_ON, SEG_OFF, SEG_BLINK +// @return none +// ************************************************************************************************* +void display_chars(uint8_t segments, uint8_t * str, uint8_t mode) +{ + uint8_t i; + uint8_t length = 0; // Write length + uint8_t char_start = 0; // Starting point for consecutive write + + switch (segments) + { + // LINE1 + case LCD_SEG_L1_3_0: length=4; char_start=LCD_SEG_L1_3; break; + case LCD_SEG_L1_2_0: length=3; char_start=LCD_SEG_L1_2; break; + case LCD_SEG_L1_1_0: length=2; char_start=LCD_SEG_L1_1; break; + case LCD_SEG_L1_3_1: length=3; char_start=LCD_SEG_L1_3; break; + case LCD_SEG_L1_3_2: length=2; char_start=LCD_SEG_L1_3; break; + + // LINE2 + case LCD_SEG_L2_5_0: length=6; char_start=LCD_SEG_L2_5; break; + case LCD_SEG_L2_4_0: length=5; char_start=LCD_SEG_L2_4; break; + case LCD_SEG_L2_3_0: length=4; char_start=LCD_SEG_L2_3; break; + case LCD_SEG_L2_2_0: length=3; char_start=LCD_SEG_L2_2; break; + case LCD_SEG_L2_1_0: length=2; char_start=LCD_SEG_L2_1; break; + case LCD_SEG_L2_5_4: length=2; char_start=LCD_SEG_L2_5; break; + case LCD_SEG_L2_5_2: length=4; char_start=LCD_SEG_L2_5; break; + case LCD_SEG_L2_3_2: length=2; char_start=LCD_SEG_L2_3; break; + case LCD_SEG_L2_4_2: length=3; char_start=LCD_SEG_L2_4; break; + } + + // Write to consecutive digits + for(i=0; i) + SEG_A+SEG_B+ SEG_E+ SEG_G, // Displays "?" + 0 , // Displays " " (@) + SEG_A+SEG_B+SEG_C+ SEG_E+SEG_F+SEG_G, // Displays "A" + SEG_C+SEG_D+SEG_E+SEG_F+SEG_G, // Displays "b" + SEG_D+SEG_E+ SEG_G, // Displays "c" + SEG_B+SEG_C+SEG_D+SEG_E+ SEG_G, // Displays "d" + SEG_A+ +SEG_D+SEG_E+SEG_F+SEG_G, // Displays "E" + SEG_A+ SEG_E+SEG_F+SEG_G, // Displays "f" + SEG_A+SEG_B+SEG_C+SEG_D+ SEG_F+SEG_G, // Displays "g" same as 9 + SEG_C+ SEG_E+SEG_F+SEG_G, // Displays "h" + SEG_E , // Displays "i" + SEG_A+SEG_B+SEG_C+SEG_D , // Displays "J" + SEG_D+ SEG_F+SEG_G, // Displays "k" + SEG_D+SEG_E+SEG_F , // Displays "L" + SEG_A+SEG_B+SEG_C+ SEG_E+SEG_F , // Displays "M" + SEG_C+ SEG_E+ SEG_G, // Displays "n" + SEG_C+SEG_D+SEG_E+ SEG_G, // Displays "o" + SEG_A+SEG_B+ SEG_E+SEG_F+SEG_G, // Displays "P" + SEG_A+SEG_B+SEG_C+ SEG_F+SEG_G, // Displays "q" + SEG_E+ SEG_G, // Displays "r" + SEG_A+ SEG_C+SEG_D+ SEG_F+SEG_G, // Displays "S" same as 5 + SEG_D+SEG_E+SEG_F+SEG_G, // Displays "t" + SEG_C+SEG_D+SEG_E , // Displays "u" + SEG_C+SEG_D+SEG_E , // Displays "v" same as u + SEG_B+SEG_C+SEG_D+SEG_E+SEG_F+SEG_G, // Displays "W" + SEG_B+SEG_C+ +SEG_E+SEG_F+SEG_G, // Displays "X" as H + SEG_B+SEG_C+SEG_D+ SEG_F+SEG_G, // Displays "Y" + SEG_A+SEG_B+ SEG_D+SEG_E+ SEG_G, // Displays "Z" same as 2 +}; + + +// Table with memory address for each display element +const uint8_t * segments_lcdmem[] = +{ + LCD_SYMB_AM_MEM, + LCD_SYMB_PM_MEM, + LCD_SYMB_ARROW_UP_MEM, + LCD_SYMB_ARROW_DOWN_MEM, + LCD_SYMB_PERCENT_MEM, + LCD_SYMB_TOTAL_MEM, + LCD_SYMB_AVERAGE_MEM, + LCD_SYMB_MAX_MEM, + LCD_SYMB_BATTERY_MEM, + LCD_UNIT_L1_FT_MEM, + LCD_UNIT_L1_K_MEM, + LCD_UNIT_L1_M_MEM, + LCD_UNIT_L1_I_MEM, + LCD_UNIT_L1_PER_S_MEM, + LCD_UNIT_L1_PER_H_MEM, + LCD_UNIT_L1_DEGREE_MEM, + LCD_UNIT_L2_KCAL_MEM, + LCD_UNIT_L2_KM_MEM, + LCD_UNIT_L2_MI_MEM, + LCD_ICON_HEART_MEM, + LCD_ICON_STOPWATCH_MEM, + LCD_ICON_RECORD_MEM, + LCD_ICON_ALARM_MEM, + LCD_ICON_BEEPER1_MEM, + LCD_ICON_BEEPER2_MEM, + LCD_ICON_BEEPER3_MEM, + LCD_SEG_L1_3_MEM, + LCD_SEG_L1_2_MEM, + LCD_SEG_L1_1_MEM, + LCD_SEG_L1_0_MEM, + LCD_SEG_L1_COL_MEM, + LCD_SEG_L1_DP1_MEM, + LCD_SEG_L1_DP0_MEM, + LCD_SEG_L2_5_MEM, + LCD_SEG_L2_4_MEM, + LCD_SEG_L2_3_MEM, + LCD_SEG_L2_2_MEM, + LCD_SEG_L2_1_MEM, + LCD_SEG_L2_0_MEM, + LCD_SEG_L2_COL1_MEM, + LCD_SEG_L2_COL0_MEM, + LCD_SEG_L2_DP_MEM, +}; + + +// Table with bit mask for each display element +const uint8_t segments_bitmask[] = +{ + LCD_SYMB_AM_MASK, + LCD_SYMB_PM_MASK, + LCD_SYMB_ARROW_UP_MASK, + LCD_SYMB_ARROW_DOWN_MASK, + LCD_SYMB_PERCENT_MASK, + LCD_SYMB_TOTAL_MASK, + LCD_SYMB_AVERAGE_MASK, + LCD_SYMB_MAX_MASK, + LCD_SYMB_BATTERY_MASK, + LCD_UNIT_L1_FT_MASK, + LCD_UNIT_L1_K_MASK, + LCD_UNIT_L1_M_MASK, + LCD_UNIT_L1_I_MASK, + LCD_UNIT_L1_PER_S_MASK, + LCD_UNIT_L1_PER_H_MASK, + LCD_UNIT_L1_DEGREE_MASK, + LCD_UNIT_L2_KCAL_MASK, + LCD_UNIT_L2_KM_MASK, + LCD_UNIT_L2_MI_MASK, + LCD_ICON_HEART_MASK, + LCD_ICON_STOPWATCH_MASK, + LCD_ICON_RECORD_MASK, + LCD_ICON_ALARM_MASK, + LCD_ICON_BEEPER1_MASK, + LCD_ICON_BEEPER2_MASK, + LCD_ICON_BEEPER3_MASK, + LCD_SEG_L1_3_MASK, + LCD_SEG_L1_2_MASK, + LCD_SEG_L1_1_MASK, + LCD_SEG_L1_0_MASK, + LCD_SEG_L1_COL_MASK, + LCD_SEG_L1_DP1_MASK, + LCD_SEG_L1_DP0_MASK, + LCD_SEG_L2_5_MASK, + LCD_SEG_L2_4_MASK, + LCD_SEG_L2_3_MASK, + LCD_SEG_L2_2_MASK, + LCD_SEG_L2_1_MASK, + LCD_SEG_L2_0_MASK, + LCD_SEG_L2_COL1_MASK, + LCD_SEG_L2_COL0_MASK, + LCD_SEG_L2_DP_MASK, +}; + + +// Quick integer to array conversion table for most common integer values +const uint8_t itoa_conversion_table[][3] = +{ + "000", "001", "002", "003", "004", "005", "006", "007", "008", "009", "010", "011", "012", "013", "014", "015", + "016", "017", "018", "019", "020", "021", "022", "023", "024", "025", "026", "027", "028", "029", "030", "031", + "032", "033", "034", "035", "036", "037", "038", "039", "040", "041", "042", "043", "044", "045", "046", "047", + "048", "049", "050", "051", "052", "053", "054", "055", "056", "057", "058", "059", "060", "061", "062", "063", + "064", "065", "066", "067", "068", "069", "070", "071", "072", "073", "074", "075", "076", "077", "078", "079", + "080", "081", "082", "083", "084", "085", "086", "087", "088", "089", "090", "091", "092", "093", "094", "095", + "096", "097", "098", "099", "100", "101", "102", "103", "104", "105", "106", "107", "108", "109", "110", "111", + "112", "113", "114", "115", "116", "117", "118", "119", "120", "121", "122", "123", "124", "125", "126", "127", + "128", "129", "130", "131", "132", "133", "134", "135", "136", "137", "138", "139", "140", "141", "142", "143", + "144", "145", "146", "147", "148", "149", "150", "151", "152", "153", "154", "155", "156", "157", "158", "159", + "160", "161", "162", "163", "164", "165", "166", "167", "168", "169", "170", "171", "172", "173", "174", "175", + "176", "177", "178", "179", "180", +}; + diff --git a/board/eZ430-Chronos/include/board.h b/board/eZ430-Chronos/include/board.h new file mode 100644 index 0000000000..af0a99b5da --- /dev/null +++ b/board/eZ430-Chronos/include/board.h @@ -0,0 +1,10 @@ +#ifndef _MSB_BOARD_H +#define _MSB_BOARD_H + +#include + +#define MSP430_INITIAL_CPU_SPEED 7372800uL +#define MSP430_HAS_DCOR 1 +#define MSP430_HAS_EXTERNAL_CRYSTAL 1 + +#endif // _MSB_BOARD_H diff --git a/board/msb-430h/Jamfile b/board/msb-430h/Jamfile new file mode 100644 index 0000000000..b1181a57db --- /dev/null +++ b/board/msb-430h/Jamfile @@ -0,0 +1,35 @@ +# ****************************************************************************** +# Copyright 2009, Freie Universitaet Berlin (FUB). All rights reserved. +# +# These sources were developed at the Freie Universitaet Berlin, Computer +# Systems and Telematics group (http://cst.mi.fu-berlin.de). +# ------------------------------------------------------------------------------ +# This file is part of FeuerWare. +# +# This program is free software: you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation, either version 3 of the License, or (at your option) any later +# version. +# +# FeuerWare is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with +# this program. If not, see http://www.gnu.org/licenses/ . +# ------------------------------------------------------------------------------ +# For further information and questions please use the web site +# http://scatterweb.mi.fu-berlin.de +# and the mailinglist (subscription via web site) +# scatterweb@lists.spline.inf.fu-berlin.de +# ****************************************************************************** +# $Id$ + +SubDir TOP board msb-430h ; + +Module board : board_init.c debug_uart.c ; +UseModule board ; + +Module board_cc1100 : driver_cc1100.c ; + +SubInclude TOP cpu $(CPU) ; diff --git a/board/msb-430h/Jamrules.msb-430h b/board/msb-430h/Jamrules.msb-430h new file mode 100644 index 0000000000..41bf0779d9 --- /dev/null +++ b/board/msb-430h/Jamrules.msb-430h @@ -0,0 +1,37 @@ +# ****************************************************************************** +# Copyright 2009, Freie Universitaet Berlin (FUB). All rights reserved. +# +# These sources were developed at the Freie Universitaet Berlin, Computer +# Systems and Telematics group (http://cst.mi.fu-berlin.de). +# ------------------------------------------------------------------------------ +# This file is part of FeuerWare. +# +# This program is free software: you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation, either version 3 of the License, or (at your option) any later +# version. +# +# FeuerWare is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with +# this program. If not, see http://www.gnu.org/licenses/ . +# ------------------------------------------------------------------------------ +# For further information and questions please use the web site +# http://scatterweb.mi.fu-berlin.de +# and the mailinglist (subscription via web site) +# scatterweb@lists.spline.inf.fu-berlin.de +# ****************************************************************************** +# $Id$ + +BOARD = msb-430h ; +CPU = msp430 ; +MCU = msp430x1612 ; + +FLASH_PORT ?= /dev/ttyUSB0 ; +FLASHER ?= mspdebug ; +FLASHFLAGS ?= -d $(FLASH_PORT) -j uif ; + +RESET ?= $(FLASHER) $(FLASHFLAGS) reset ; + diff --git a/board/msb-430h/board_init.c b/board/msb-430h/board_init.c new file mode 100644 index 0000000000..7dee70e3b1 --- /dev/null +++ b/board/msb-430h/board_init.c @@ -0,0 +1,207 @@ +#include "cpu.h" +#include "board.h" +#include "kernel_intern.h" +#include "msp430.h" +#include "debug.h" + +volatile static uint32_t __msp430_cpu_speed = MSP430_INITIAL_CPU_SPEED; + +/*---------------------------------------------------------------------------*/ +static uint8_t calc_umctl(uint16_t br) { + // from TI slaa049 + register uint8_t CMOD = 256 * br - 256 * (br + 1) / 2; + register uint8_t c = 0; + register int i = 0; + register uint8_t a = CMOD; + a <<= 1; + do { + if( a & 0x80 ) { // Overflow to integer? + a = a - 128 + CMOD; // Yes, subtract 1.000000 + c |= 0x80; + } else { + a += CMOD; // No, add fraction + } + if( i == 7 ) + return c; + i++; + c >>= 1; + } while(1); +} + +static void msb_ports_init(void) +{ + // Port 1: Free port, for energy saving all outputs are set to zero. + P1SEL = 0x00; // Port1 Zweitfunktion + P1OUT = 0x00; // Port1 Ausgangsregister: 00000000 = 0x00 + P1DIR = 0xFF; // Port1 Direction: 11111111 = 0xFF + + P2SEL = 0x20; // Port2 Zweitfunktion + P2OUT = 0x00; // Port2 Ausgangsregister: 00000000 = 0x00 + P2DIR = 0x1C; // Port2 Direction: 00011010 = 0x1C + // 0 - P2.0 [IN ] - + // 0 - P2.1 [OUT] - + // 1 - P2.2 [IN ] - + // 1 - P2.3 [OUT] - + // 1 - P2.4 [OUT] - + // 0 - P2.5 [IN ] - + // 0 - P2.6 [IN ] - SD-KARTE Protect + // 0 - P2.7 [IN ] - SD-KARTE Detect + + P3SEL = 0xC0; // Port3 Zweitfunktion + P3OUT = 0x09; // Port3 Ausgangsregister: 00001001 = 0x09 + P3DIR = 0x2B; // Port3 Direction + // 1 - P3.0 + // 1 - P3.1 + // 0 - P3.2 + // 1 - P3.3 + // 0 - P3.4 [IN ] - SHT 11 DATA (OUT/IN) + // 1 - P3.5 [OUT] - SHT 11 CLK + // 0 - P3.6 [2-Funktion] - RS232_RxD + // 0 - P3.7 [2-Funktion] - RS232_TxD + + // Port 4: Free port, for energy saving all outputs are set to zero. + P4SEL = 0x00; // Port4 Zweitfunktion + P4OUT = 0x00; // Port4 Ausgangsregister: 00000000 = 0x00 + P4DIR = 0xFF; // Port4 Direction: 11111111 = 0xFF + // 1 - P4.0 [OUT] - unused + // 1 - P4.1 [OUT] - unused + // 1 - P4.2 [OUT] - unused + // 1 - P4.3 [OUT] - unused + // 1 - P4.4 [OUT] - unused + // 1 - P4.5 [OUT] - unused + // 1 - P4.6 [OUT] - unused + // 1 - P4.7 [OUT] - unused + + P5SEL = 0x00; // Port5 Zweitfunktion: 00000000 = 0x00 + P5OUT = 0x80; // Port5 Ausgangsregister: 00001001 = 0x09 + P5DIR = 0xFF; // Port5 Direction: 11111011 = 0xFB + // 1 - P5.0 [OUT] - SD-KARTE /CS + // 1 - P5.1 [OUT] - SD-KARTE DI + // 0 - P5.2 [IN ] - SD-KARTE DO + // 1 - P5.3 [OUT] - SD-KARTE DCLK + // 1 - P5.4 [OUT] - MMA GS1 + // 1 - P5.5 [OUT] - MMA GS2 + // 1 - P5.6 [OUT] - MMA /SLEEP + // 1 - P5.7 [OUT] - LED_ROT 0-an, 1-aus + + P6SEL = 0x00; // Port6 Zweitfunktion = 0x07 + P6OUT = 0x00; // Port6 Ausgangsregister: 00000000 = 0x00 + P6DIR = 0xFF; // Port6 Direction: 11111000 = 0xF8 + // 0 - P6.0 [AD-IN] - MMA X-Achse + // 0 - P6.1 [AD-IN] - MMA Y-Achse + // 0 - P6.2 [AD-IN] - MMA Z-Achse + // 1 - P6.3 [OUT] - unused + // 1 - P6.4 [OUT] - unused + // 1 - P6.5 [OUT] - unused + // 1 - P6.6 [OUT] - unused + // 1 - P6.7 [OUT] - unused +} + +void msp430_set_cpu_speed(uint32_t speed) +{ + dint(); + __msp430_cpu_speed = speed; + msp430_init_dco(); + uint16_t br; + UCTL1 = SWRST | CHAR; // 8-bit character + UTCTL1 |= SSEL1 | URXSE; // UCLK = MCLK + // activate + U1ME |= UTXE1 | URXE1; // Enable USART1 TXD/RXD + br = (uint16_t)(__msp430_cpu_speed / 115200uL); + UBR01 = br; // set baudrate + UBR11 = br>>8; + UMCTL1 = calc_umctl(br); // set modulation + + UCTL1 &= ~SWRST; + //clock_init(); + eint(); +} + +/*---------------------------------------------------------------------------*/ +void +msp430_init_dco() +{ + #if MSP430_HAS_EXTERNAL_CRYSTAL + /*------------------ use external oszillator -----------------------*/ + uint16_t i; + + // Stop watchdog + WDTCTL = WDTPW + WDTHOLD; + + //Init crystal for mclk + //XT2 = HF XTAL + BCSCTL1 = RSEL2; + + // Wait for xtal to stabilize + do { + IFG1 &= ~OFIFG; // Clear oscillator fault flag + for (i = 0xFF; i > 0; i--); // Time for flag to set + } + while ((IFG1 & OFIFG) != 0); // Oscillator fault flag still set? + BCSCTL2 = SELM_2 + SELS; // MCLK und SMCLK = XT2 (safe) + #else + /* Thdeltais code taken from the FU Berlin sources and reformatted. */ + int delta = __msp430_cpu_speed >> 12; + //#define DELTA 600 + + unsigned int compare, oldcapture = 0; + unsigned int i; + + + BCSCTL1 = 0xa4; /* ACLK is devided by 4. RSEL=6 no division for MCLK + and SSMCLK. XT2 is off. */ + + // Init FLL to desired frequency using the 32762Hz crystal + #if MSP430_HAS_DCOR + BCSCTL2 = 0x01; + #else + BCSCTL2 = 0x00; + #endif + + WDTCTL = WDTPW + WDTHOLD; /* Stop WDT */ + BCSCTL1 |= DIVA1 + DIVA0; /* ACLK = LFXT1CLK/8 */ + for(i = 0xffff; i > 0; i--); /* Delay for XTAL to settle */ + + CCTL2 = CCIS0 + CM0 + CAP; // Define CCR2, CAP, ACLK + TACTL = TASSEL1 + TACLR + MC1; // SMCLK, continous mode + + + while(1) { + + while((CCTL2 & CCIFG) != CCIFG); /* Wait until capture occured! */ + CCTL2 &= ~CCIFG; /* Capture occured, clear flag */ + compare = CCR2; /* Get current captured SMCLK */ + compare = compare - oldcapture; /* SMCLK difference */ + oldcapture = CCR2; /* Save current captured SMCLK */ + + if(delta == compare) { + break; /* if equal, leave "while(1)" */ + } else if(delta < compare) { /* DCO is too fast, slow it down */ + DCOCTL--; + if(DCOCTL == 0xFF) { /* Did DCO role under? */ + BCSCTL1--; + } + } else { /* -> Select next lower RSEL */ + DCOCTL++; + if(DCOCTL == 0x00) { /* Did DCO role over? */ + BCSCTL1++; + } + /* -> Select next higher RSEL */ + } + } + + CCTL2 = 0; /* Stop CCR2 function */ + TACTL = 0; /* Stop Timer_A */ + + BCSCTL1 &= ~(DIVA1 + DIVA0); /* remove /8 divisor from ACLK again */ + #endif +} + +void board_init() { + msp430_cpu_init(); + msb_ports_init(); + + RED_ON; + + msp430_set_cpu_speed(7372800uL); +} diff --git a/board/msb-430h/debug_uart.c b/board/msb-430h/debug_uart.c new file mode 100644 index 0000000000..7abad1d4e3 --- /dev/null +++ b/board/msb-430h/debug_uart.c @@ -0,0 +1,21 @@ +#include "board.h" + +#define UART1_TX TXBUF1 +#define UART1_WAIT_TXDONE() while( (UTCTL1 & TXEPT) == 0 ) { _NOP(); } + +#include + +int putchar(int c) +{ + UART1_TX = c; + UART1_WAIT_TXDONE(); + + if (c == 10) { + UART1_TX = 13; + UART1_WAIT_TXDONE(); + } + + return c; +} + + diff --git a/board/msb-430h/driver_cc1100.c b/board/msb-430h/driver_cc1100.c new file mode 100644 index 0000000000..9575bee6a5 --- /dev/null +++ b/board/msb-430h/driver_cc1100.c @@ -0,0 +1,343 @@ +/* Copyright (C) 2005, 2006, 2007, 2008 by Thomas Hillebrandt and Heiko Will + +This file is part of the Micro-mesh SensorWeb Firmware. + +Micro-Mesh is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +Micro-Mesh is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Micro-Mesh; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +#include + +#include +#include +#include + +#include +#include + +#define CC1100_GDO0 (P2IN & 0x02) // read serial I/O (GDO0) +#define CC1100_GDO1 (P3IN & 0x04) // read serial I/O (GDO1) +#define CC1100_GDO2 (P2IN & 0x01) // read serial I/O (GDO2) + +#define CC1100_CS_LOW (P3OUT &= ~0x01) +#define CC1100_CS_HIGH (P3OUT |= 0x01) + +#define CC1100_GDO1_LOW_COUNT (2700) // loop count (timeout ~ 500 us) to wait +#define CC1100_GDO1_LOW_RETRY (100) // max. retries for GDO1 to go low + +volatile int abort_count; +volatile int retry_count = 0; + +void cc1100_gdo0_enable(void) +{ + P2IFG &= ~0x02; /* Clear IFG for GDO0 */ + P2IE |= 0x02; /* Enable interrupt for GDO0 */ +} + +void cc1100_gdo0_disable(void) +{ + P2IE &= ~0x02; /* Disable interrupt for GDO0 */ + P2IFG &= ~0x02; /* Clear IFG for GDO0 */ +} + +void cc1100_gdo2_enable(void) +{ + P2IFG &= ~0x01; /* Clear IFG for GDO2 */ + P2IE |= 0x01; /* Enable interrupt for GDO2 */ +} + +void cc1100_gdo2_disable(void) +{ + P2IE &= ~0x01; /* Disable interrupt for GDO2 */ + P2IFG &= ~0x01; /* Clear IFG for GDO2 */ +} + +void cc1100_before_send(void) +{ + // Disable GDO2 interrupt before sending packet + cc1100_gdo2_disable(); +} + +void cc1100_after_send(void) +{ + // Enable GDO2 interrupt after sending packet + cc1100_gdo2_enable(); +} + + +int cc1100_get_gdo0(void) { + return CC1100_GDO0; +} + +int cc1100_get_gdo1(void) { + return CC1100_GDO1; +} + +int cc1100_get_gdo2(void) { + return CC1100_GDO2; +} + +void cc1100_spi_cs(void) +{ + CC1100_CS_LOW; +} + +uint8_t cc1100_txrx(uint8_t data) +{ + /* Ensure TX Buf is empty */ + long c = 0; + IFG1 &= ~UTXIFG0; + IFG1 &= ~URXIFG0; + TXBUF0 = data; + while(!(IFG1 & UTXIFG0)) + { + if (c++ == 1000000) + puts("cc1100_txrx alarm()"); + } + /* Wait for Byte received */ + c = 0; + while(!(IFG1 & URXIFG0)) + { + if (c++ == 1000000) + puts("cc1100_txrx alarm()"); + } + return RXBUF0; +} + + +void cc1100_spi_select(void) +{ + // Switch to GDO mode + P3SEL &= ~0x04; + P3DIR &= ~0x04; + cs_low: + // CS to low + abort_count = 0; + CC1100_CS_LOW; + // Wait for SO to go low (voltage regulator + // has stabilized and the crystal is running) + loop: +// asm volatile ("nop"); + if (CC1100_GDO1) { + abort_count++; + if (abort_count > CC1100_GDO1_LOW_COUNT) { + retry_count++; + if (retry_count > CC1100_GDO1_LOW_RETRY) { + puts("[CC1100 SPI] fatal error\n"); + goto final; + } + CC1100_CS_HIGH; + goto cs_low; // try again + } + goto loop; + } + final: + /* Switch to SPI mode */ + P3SEL |= 0x04; +} + +void cc1100_spi_unselect(void) { + CC1100_CS_HIGH; +} + +void cc1100_init_interrupts(void) +{ + unsigned int state = disableIRQ(); /* Disable all interrupts */ + P2SEL = 0x00; /* must be <> 1 to use interrupts */ + P2IES |= 0x01; /* Enables external interrupt on low edge (for GDO2) */ + P2IE |= 0x01; /* Enable interrupt */ + P2IFG &= ~0x01; /* Clears the interrupt flag */ + P2IE &= ~0x02; /* Disable interrupt for GDO0 */ + P2IFG &= ~0x02; /* Clear IFG for GDO0 */ + restoreIRQ(state); /* Enable all interrupts */ +} + +void cc1100_spi_init(uint8_t clockrate) +{ + // Switch off async UART + while(!(UTCTL0 & TXEPT)); // Wait for empty UxTXBUF register + IE1 &= ~(URXIE0 + UTXIE0); // Disable USART0 receive&transmit interrupt + ME1 &= ~(UTXE0 + URXE0); + P3SEL |= 0x0E; // Set pin as SPI + + // Keep peripheral in reset state + UCTL0 = SWRST; + + // 8-bit SPI Master 3-pin mode, with SMCLK as clock source + // CKPL works also, but not CKPH+CKPL or none of them!! + UCTL0 |= CHAR + SYNC + MM; + UTCTL0 = CKPH + SSEL1 + SSEL0 + STC; + + // Ignore clockrate argument for now, just use clock source/2 + // SMCLK = 7,3728 MHz + UBR00 = 0x02; // Ensure baud rate >= 2 + UBR10 = 0x00; + UMCTL0 = 0x00; // No modulation + URCTL0 = 0x00; // Reset Receive Control Register + + // Enable SPI mode + ME1 |= USPIE0; + + // Release for operation + UCTL0 &= ~SWRST; +} + + +// #include +// #include +// #include "type.h" +// #include "cc1100_defines.h" +// #include "driver_cc1100.h" +// #include "driver_system.h" +// #include "spi0.h" +// +// static callback_t _paket_cb; +// static callback_t _cs_cb; +// +// //------------------------------------------------------------------------------------------------------- +// // Public CC1100 communication functions (SPI) +// //------------------------------------------------------------------------------------------------------- +// +// //------------------------------------------------------------------------------------------------------- +// // void spiInitTrx(void) +// // +// // DESCRIPTION: +// // This function puts the cc1100 into spi mode. You have to call this bevore every spi transaction. +// // +// //------------------------------------------------------------------------------------------------------- +// +// +// void drivercc1100_spiwriteburstreg(uint8_t addr, unsigned char *buffer, uint8_t count) +// { +// uint8_t i; +// long c; +// drivercc1100_spiinittrx(); +// drivercc1100_trxspi(addr | CC1100_WRITE_BURST); +// for (i = 0; i < count; i++) +// { +// c = 0; +// IFG1 &= ~UTXIFG0; +// IFG1 &= ~URXIFG0; +// TXBUF0 = buffer[i]; +// /* Wait for TX to finish */ +// while(!(IFG1 & UTXIFG0)) +// { +// if (c++ == 1000000) +// alarm(); +// } +// } +// /* Wait for Byte received */ +// c = 0; +// while(!(IFG1 & URXIFG0)) +// { +// if (c++ == 1000000) +// alarm(); +// } +// CC1100_CS_HIGH; +// } +// +// void drivercc1100_spireadburstreg(uint8_t addr, char *buffer, uint8_t count) +// { +// uint8_t i; +// drivercc1100_spiinittrx(); +// drivercc1100_trxspi(addr | CC1100_READ_BURST); +// for (i = 0; i < count; i++) +// { +// long c = 0; +// IFG1 &= ~UTXIFG0; +// IFG1 &= ~URXIFG0; +// TXBUF0 = NOBYTE; +// while(!(IFG1 & UTXIFG0)) +// { +// if (c++ == 1000000) +// alarm(); +// } +// /* Wait for Byte received */ +// c = 0; +// while(!(IFG1 & URXIFG0)) +// { +// if (c++ == 1000000) +// alarm(); +// } +// buffer[i] = RXBUF0; +// } +// CC1100_CS_HIGH; +// } +// +// void drivercc1100_load(callback_t cs_cb,callback_t paket_cb) +// { +// _paket_cb = paket_cb; +// _cs_cb = cs_cb; +// spi0_init(0); +// } +// +// void drivercc1100_aftersend(void) +// { +// CLEAR(P2IFG, 0x01); +// SET(P2IE, 0x01); /* Enable interrupts on port 2 pin 0 */ +// CLEAR(P4OUT, 0x08); /* Turn off Sending Led*/ +// } +// +// void drivercc1100_initinterrupts(void) +// { +// _DINT(); /* Disable all interrupts */ +// P2SEL = 0x00; /* must be <> 1 to use interrupts */ +// SET(P2IES, 0x01); /* Enables external interrupt on low edge (for GDO2) */ +// SET(P2IE, 0x01); /* Enable interrupt */ +// CLEAR(P2IFG, 0x01); /* Clears the interrupt flag */ +// CLEAR(P2IE, 0x02); /* Disable interrupt for GDO0 */ +// CLEAR(P2IFG, 0x02); /* Clear IFG for GDO0 */ +// _EINT(); /* Enable all interrupts */ +// } +// +// void drivercc1100_beforesend(void) +// { +// /* Turn on Led while sending paket for debug reasons */ +// SET(P4OUT, 0x08); +// /* Disable interrupts on port 2 pin 0 */ +// CLEAR(P2IE, 0x01); +// } +// +// +// /* +// * Private functions +// */ +// +// + +/* + * CC1100 receive interrupt + */ +interrupt (PORT2_VECTOR) __attribute__ ((naked)) cc1100_isr(void){ + __enter_isr(); +puts("cc1100_isr()"); +// if (system_state.POWERDOWN) SPI_INIT; /* Initialize SPI after wakeup */ + /* Check IFG */ + if ((P2IFG & 0x01) != 0) { + P2IFG &= ~0x01; + cc1100_gdo2_irq(); + } + else if ((P2IFG & 0x02) != 0) { + cc1100_gdo0_irq(); + P2IE &= ~0x02; // Disable interrupt for GDO0 + P2IFG &= ~0x02; // Clear IFG for GDO0 + } else { + puts("cc1100_isr(): unexpected IFG!"); + /* Should not occur - only Port 2 Pin 0 interrupts are enabled */ +// CLEAR(P2IFG, 0xFF); /* Clear all flags */ + } +// if (system_state.POWERDOWN != 0) END_LPM3; + __exit_isr(); +} + diff --git a/board/msb-430h/include/board.h b/board/msb-430h/include/board.h new file mode 100644 index 0000000000..ef2bbb6585 --- /dev/null +++ b/board/msb-430h/include/board.h @@ -0,0 +1,69 @@ +/****************************************************************************** +Copyright 2009, Freie Universitaet Berlin (FUB). All rights reserved. + +These sources were developed at the Freie Universitaet Berlin, Computer Systems +and Telematics group (http://cst.mi.fu-berlin.de). +------------------------------------------------------------------------------- +This file is part of FeuerWare. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +FeuerWare is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see http://www.gnu.org/licenses/ . +-------------------------------------------------------------------------------- +For further information and questions please use the web site + http://scatterweb.mi.fu-berlin.de +and the mailinglist (subscription via web site) + scatterweb@lists.spline.inf.fu-berlin.de +*******************************************************************************/ + +#ifndef _MSB_BOARD_H +#define _MSB_BOARD_H + +/** + * @defgroup msb_430h ScatterWeb MSB-430H + * @ingroup msp430 + * +

Compontents

+\li MSP430 +\li CC1100 + +* @{ +*/ + +/** + * @file + * @brief MSB-430H Board + * + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @version $Revision$ + * + * @note $Id$ + */ + +//MSB430 core +#define MSP430_INITIAL_CPU_SPEED 7372800uL +#define MSP430_HAS_DCOR 1 +#define MSP430_HAS_EXTERNAL_CRYSTAL 1 + +/* LEDs ports MSB430 */ +#define LEDS_PxDIR P5DIR +#define LEDS_PxOUT P5OUT +#define LEDS_CONF_RED 0x80 +#define LEDS_CONF_GREEN 0x00 +#define LEDS_CONF_YELLOW 0x00 + +#define RED_ON LEDS_PxOUT &=~LEDS_CONF_RED +#define RED_OFF LEDS_PxOUT |= LEDS_CONF_RED + +#include + +/** @} */ +#endif // _MSB_BOARD_H diff --git a/board/msba2/Jamfile b/board/msba2/Jamfile new file mode 100644 index 0000000000..88106e45cb --- /dev/null +++ b/board/msba2/Jamfile @@ -0,0 +1,35 @@ +# ****************************************************************************** +# Copyright 2009, Freie Universitaet Berlin (FUB). All rights reserved. +# +# These sources were developed at the Freie Universitaet Berlin, Computer +# Systems and Telematics group (http://cst.mi.fu-berlin.de). +# ------------------------------------------------------------------------------ +# This file is part of FeuerWare. +# +# This program is free software: you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation, either version 3 of the License, or (at your option) any later +# version. +# +# FeuerWare is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with +# this program. If not, see http://www.gnu.org/licenses/ . +# ------------------------------------------------------------------------------ +# For further information and questions please use the web site +# http://scatterweb.mi.fu-berlin.de +# and the mailinglist (subscription via web site) +# scatterweb@lists.spline.inf.fu-berlin.de +# ****************************************************************************** +# $Id$ + +SubDir TOP board msba2 ; + +Module board : board_init.c ; +UseModule board ; +UseModule board_common ; + +SubInclude TOP board $(BOARD) drivers ; +SubInclude TOP cpu $(CPU) ; diff --git a/board/msba2/Jamfile.msba2 b/board/msba2/Jamfile.msba2 new file mode 100644 index 0000000000..44014a6c96 --- /dev/null +++ b/board/msba2/Jamfile.msba2 @@ -0,0 +1,31 @@ +# ****************************************************************************** +# Copyright 2009, Freie Universitaet Berlin (FUB). All rights reserved. +# +# These sources were developed at the Freie Universitaet Berlin, Computer +# Systems and Telematics group (http://cst.mi.fu-berlin.de). +# ------------------------------------------------------------------------------ +# This file is part of FeuerWare. +# +# This program is free software: you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation, either version 3 of the License, or (at your option) any later +# version. +# +# FeuerWare is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with +# this program. If not, see http://www.gnu.org/licenses/ . +# ------------------------------------------------------------------------------ +# For further information and questions please use the web site +# http://scatterweb.mi.fu-berlin.de +# and the mailinglist (subscription via web site) +# scatterweb@lists.spline.inf.fu-berlin.de +# ****************************************************************************** +# $Id$ + +#LinkLibraries $(BOARD).elf : sys-drivers.a net_mm.a sys-lib.a fat-lib.a +# cpu_drivers.a board_drivers.a cc110x.a hal.a hal_drivers.a lpc2387_hal.a ; + +include [ FPath $(TOP) cpu arm_common Jamfile.arm_common ] ; diff --git a/board/msba2/Jamrules.msba2 b/board/msba2/Jamrules.msba2 new file mode 100644 index 0000000000..fdcf4b6f65 --- /dev/null +++ b/board/msba2/Jamrules.msba2 @@ -0,0 +1,33 @@ +# ****************************************************************************** +# Copyright 2009, Freie Universitaet Berlin (FUB). All rights reserved. +# +# These sources were developed at the Freie Universitaet Berlin, Computer +# Systems and Telematics group (http://cst.mi.fu-berlin.de). +# ------------------------------------------------------------------------------ +# This file is part of FeuerWare. +# +# This program is free software: you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation, either version 3 of the License, or (at your option) any later +# version. +# +# FeuerWare is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with +# this program. If not, see http://www.gnu.org/licenses/ . +# ------------------------------------------------------------------------------ +# For further information and questions please use the web site +# http://scatterweb.mi.fu-berlin.de +# and the mailinglist (subscription via web site) +# scatterweb@lists.spline.inf.fu-berlin.de +# ****************************************************************************** +# $Id$ + +CPU = lpc2387 ; + +HDRS += [ FPath $(TOP) board $(BOARD) drivers include ] ; + +FLASHER = $(POSIXSHELL) $(TOP)/board/msba2/tools/flashutil.sh ; +FLASHFLAGS = --basedir $(TOP)/board/msba2/tools --id "MSB-A2" --ports "$(PORT)" ; diff --git a/board/msba2/board_init.c b/board/msba2/board_init.c new file mode 100644 index 0000000000..d12cc4058e --- /dev/null +++ b/board/msba2/board_init.c @@ -0,0 +1,156 @@ +/****************************************************************************** +Copyright 2008-2009, Freie Universitaet Berlin (FUB). All rights reserved. + +These sources were developed at the Freie Universitaet Berlin, Computer Systems +and Telematics group (http://cst.mi.fu-berlin.de). +------------------------------------------------------------------------------- +This file is part of FeuerWare. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +FeuerWare is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see http://www.gnu.org/licenses/ . +-------------------------------------------------------------------------------- +For further information and questions please use the web site + http://scatterweb.mi.fu-berlin.de +and the mailinglist (subscription via web site) + scatterweb@lists.spline.inf.fu-berlin.de +*******************************************************************************/ + +/** + * @ingroup pttu + * @{ + */ + +/** + * @file + * @brief MSB-A2 board initialization + * + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @author Heiko Will + * @author Kaspar Schleiser + * @author Michael Baar + * + * @note $Id$ + */ +#include +#include +#include "VIC.h" +#include "cpu.h" + +#define PCRTC BIT9 +#define CL_CPU_DIV 4 + +/*---------------------------------------------------------------------------*/ +/** + * @brief Enabling MAM and setting number of clocks used for Flash memory fetch + * @internal + */ +static void +init_mam(void) +{ + MAMCR = 0x0000; + MAMTIM = 0x0003; + MAMCR = 0x0002; +} +/*---------------------------------------------------------------------------*/ +static inline void +pllfeed(void) +{ + PLLFEED = 0xAA; + PLLFEED = 0x55; +} +/*---------------------------------------------------------------------------*/ +void init_clks1(void) +{ + // Disconnect PLL + PLLCON &= ~0x0002; + pllfeed(); + + // Disable PLL + PLLCON &= ~0x0001; + pllfeed(); + + SCS |= 0x20; // Enable main OSC + while( !(SCS & 0x40) ); // Wait until main OSC is usable + + /* select main OSC, 16MHz, as the PLL clock source */ + CLKSRCSEL = 0x0001; + + // Setting Multiplier and Divider values + PLLCFG = 0x0008; // M=9 N=1 Fcco = 288 MHz + pllfeed(); + + // Enabling the PLL */ + PLLCON = 0x0001; + pllfeed(); + + /* Set clock divider to 4 (value+1) */ + CCLKCFG = CL_CPU_DIV - 1; // Fcpu = 72 MHz + +#if USE_USB + USBCLKCFG = USBCLKDivValue; /* usbclk = 288 MHz/6 = 48 MHz */ +#endif +} + +void init_clks2(void){ + // Wait for the PLL to lock to set frequency + while(!(PLLSTAT & BIT26)); + + // Connect the PLL as the clock source + PLLCON = 0x0003; + pllfeed(); + + /* Check connect bit status */ + while (!(PLLSTAT & BIT25)); +} + +void bl_init_clks(void) +{ + PCONP = PCRTC; // switch off everything except RTC + init_clks1(); + init_clks2(); + init_mam(); +} + +void bl_init_ports(void) +{ + SCS |= BIT0; // Set IO Ports to fast switching mode + + /* UART0 */ + PINSEL0 |= BIT4 + BIT6; // RxD0 and TxD0 + PINSEL0 &= ~(BIT5 + BIT7); + + /* LEDS */ + FIO3DIR |= LED_RED_PIN; + FIO3DIR |= LED_GREEN_PIN; + LED_RED_OFF; + LED_GREEN_OFF; +} + +void loop_delay(void) { + volatile uint16_t i, j; + for (i = 1; i < 30; i++) { + for (j = 1; j != 0; j++) { + asm volatile (" nop "); + } + } +} + +void bl_blink(void) { + LED_RED_ON; + LED_GREEN_ON; + + loop_delay(); + + LED_RED_OFF; + LED_GREEN_OFF; +} + diff --git a/board/msba2/drivers/Jamfile b/board/msba2/drivers/Jamfile new file mode 100644 index 0000000000..79705aca0a --- /dev/null +++ b/board/msba2/drivers/Jamfile @@ -0,0 +1,6 @@ +SubDir TOP board msba2 drivers ; + +Module board_cc1100 : msba2-cc1100.c ; +Module board_hal : msba2-hal.c ; +Module board_ltc4150 : msba2-ltc4150.c : gpioint ; +Module board_common : msba2-uart0.c ; diff --git a/board/msba2/drivers/include/hal-board.h b/board/msba2/drivers/include/hal-board.h new file mode 100644 index 0000000000..a4dfc293ab --- /dev/null +++ b/board/msba2/drivers/include/hal-board.h @@ -0,0 +1,68 @@ +/****************************************************************************** +Copyright 2008, Freie Universitaet Berlin (FUB). All rights reserved. + +These sources were developed at the Freie Universitaet Berlin, Computer Systems +and Telematics group (http://cst.mi.fu-berlin.de). +------------------------------------------------------------------------------- +This file is part of FeuerWare. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +FeuerWare is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see http://www.gnu.org/licenses/ . +-------------------------------------------------------------------------------- +For further information and questions please use the web site + http://scatterweb.mi.fu-berlin.de +and the mailinglist (subscription via web site) + scatterweb@lists.spline.inf.fu-berlin.de +*******************************************************************************/ + +#ifndef HALPLATFORM_H_ +#define HALPLATFORM_H_ + +/** + * @ingroup msba2 + * @{ + */ + +/** + * @file + * @brief + * + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @author baar + * @version $Revision$ + * + * @note $Id$ + */ + +#include "vdevice.h" +#include "device-gpio.h" +#include "device-rs232.h" +#include "device-serial.h" + +VDEVICE_NAME(vdevice_gpio, gpio_led_green); +VDEVICE_NAME(vdevice_gpio, gpio_led_red); +VDEVICE_NAME(vdevice_gpio, gpio_led_usb); + +/** + * @var tty0 + * @brief RS232 TTY0 device on UART0 + */ +VDEVICE_NAME(vdevice_rs232, tty0); + +/** + * @var console0 + * @brief console device on tty0 + */ +VDEVICE_NAME(vdevice_serial, console0); + +/** @} */ +#endif /* HALPLATFORM_H_ */ diff --git a/board/msba2/drivers/include/sht11-board.h b/board/msba2/drivers/include/sht11-board.h new file mode 100644 index 0000000000..fc0313906a --- /dev/null +++ b/board/msba2/drivers/include/sht11-board.h @@ -0,0 +1,63 @@ +/****************************************************************************** +Copyright 2009, Freie Universitaet Berlin (FUB). All rights reserved. + +These sources were developed at the Freie Universitaet Berlin, Computer Systems +and Telematics group (http://cst.mi.fu-berlin.de). +------------------------------------------------------------------------------- +This file is part of FeuerWare. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +FeuerWare is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see http://www.gnu.org/licenses/ . +-------------------------------------------------------------------------------- +For further information and questions please use the web site + http://scatterweb.mi.fu-berlin.de +and the mailinglist (subscription via web site) + scatterweb@lists.spline.inf.fu-berlin.de +*******************************************************************************/ + +#ifndef SHT11BOARD_H_ +#define SHT11BOARD_H_ + +/** + * @ingroup lpc2387 + * @{ + */ + +/** + * @file + * @brief LPC2387 SHT11 Device Driver + * + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @version $Revision$ + * + * @note $Id$ + */ + +#include +#include + +#define SHT11_SCK_LOW FIO1CLR = BIT25; // serial clock line low +#define SHT11_SCK_HIGH FIO1SET = BIT25; // serial clock line high +#define SHT11_DATA ((FIO1PIN & BIT26) != 0) // read serial I/O +#define SHT11_DATA_LOW (FIO1CLR = BIT26); // serial I/O line low +#define SHT11_DATA_HIGH (FIO1SET = BIT26); // serial I/O line high +#define SHT11_DATA_IN (FIO1DIR &= ~BIT26) // serial I/O as input +#define SHT11_DATA_OUT (FIO1DIR |= BIT26) // serial I/O as output +#define SHT11_INIT FIO1DIR |= BIT25; PINSEL3 &= ~(BIT14|BIT15 | BIT16|BIT17); + +/* time to wait after toggling the data line */ +#define SHT11_DATA_WAIT (50) +/* time to wait after toggling the clock line */ +#define SHT11_CLK_WAIT (10) + +/** @} */ +#endif /* SHT11BOARD_H_ */ diff --git a/board/msba2/drivers/msba2-cc1100.c b/board/msba2/drivers/msba2-cc1100.c new file mode 100644 index 0000000000..726d585506 --- /dev/null +++ b/board/msba2/drivers/msba2-cc1100.c @@ -0,0 +1,243 @@ +/****************************************************************************** +Copyright 2008, Freie Universitaet Berlin (FUB). All rights reserved. + +These sources were developed at the Freie Universitaet Berlin, Computer Systems +and Telematics group (http://cst.mi.fu-berlin.de). +------------------------------------------------------------------------------- +This file is part of FeuerWare. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +FeuerWare is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see http://www.gnu.org/licenses/ . +-------------------------------------------------------------------------------- +For further information and questions please use the web site + http://scatterweb.mi.fu-berlin.de +and the mailinglist (subscription via web site) + scatterweb@lists.spline.inf.fu-berlin.de +*******************************************************************************/ + +/** + * @file + * @ingroup LPC2387 + * @brief CC1100 LPC2387 dependend functions + * + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @author Heiko Will + * @author Thomas Hillebrandt + * @version $Revision: 1781 $ + * + * @note $Id: msba2-cc1100.c 1781 2010-01-26 13:39:36Z hillebra $ + */ + +#include +#include +// core +#include +#include +// sys +#include "cc1100.h" +#include "arch_cc1100.h" +#include "cc1100_spi.h" +#include "gpioint.h" + +#define CC1100_GDO0 (FIO0PIN & BIT27) // read serial I/O (GDO0) +#define CC1100_GDO1 (FIO1PIN & BIT23) // read serial I/O (GDO1) +#define CC1100_GDO2 (FIO0PIN & BIT28) // read serial I/O (GDO2) + +#define SPI_TX_EMPTY (SSP0SR & SSPSR_TFE) +#define SPI_BUSY (SSP0SR & SSPSR_BSY) +#define SPI_RX_AVAIL (SSP0SR & SSPSR_RNE) + +#define CC1100_GDO1_LOW_RETRY (100) // max. retries for GDO1 to go low +#define CC1100_GDO1_LOW_COUNT (2700) // loop count (timeout ~ 500 us) to wait + // for GDO1 to go low when CS low + +//#define DEBUG +#ifdef DEBUG + +#include "stdio.h" + +static unsigned long time_value; + +static void set_time(void) { + time_value = 0; +} + +static int test_time(int code) { + time_value++; + if (time_value > 10000000) { + printf("CC1100 SPI alarm: %u!\n", code); + time_value = 0; + return 1; + } + return 0; +} +#endif + +int cc1100_get_gdo0(void) { + return CC1100_GDO0; +} + +int cc1100_get_gdo1(void) { + return CC1100_GDO1; +} + +int cc1100_get_gdo2(void) { + return CC1100_GDO2; +} + +void cc1100_spi_init(void) +{ + // configure chip-select + FIO1DIR |= BIT21; + FIO1SET = BIT21; + + // Power + PCONP |= PCSSP0; // Enable power for SSP0 (default is on) + + // PIN Setup + PINSEL3 |= BIT8 + BIT9; // Set CLK function to SPI + PINSEL3 |= BIT14 + BIT15; // Set MISO function to SPI + PINSEL3 |= BIT16 + BIT17; // Set MOSI function to SPI + + // Interface Setup + SSP0CR0 = 7; + + // Clock Setup + uint32_t pclksel; + uint32_t cpsr; + lpc2387_pclk_scale(F_CPU/1000, 6000, &pclksel, &cpsr); + PCLKSEL1 &= ~(BIT10|BIT11); // CCLK to PCLK divider + PCLKSEL1 |= pclksel << 10; + SSP0CPSR = cpsr; + + // Enable + SSP0CR1 |= BIT1; // SSP-Enable + int dummy; + // Clear RxFIFO: + while( SPI_RX_AVAIL ) { // while RNE (Receive FIFO Not Empty)... + dummy = SSP0DR; // read data + } +} + +uint8_t +cc1100_txrx(uint8_t c) { + uint8_t result; + SSP0DR = c; +#ifdef DEBUG + set_time(); +#endif + while (!SPI_TX_EMPTY) { +#ifdef DEBUG + test_time(0); +#endif + } +#ifdef DEBUG + set_time(); +#endif + while (SPI_BUSY) { +#ifdef DEBUG + test_time(1); +#endif + } +#ifdef DEBUG + set_time(); +#endif + while (!SPI_RX_AVAIL) { +#ifdef DEBUG + test_time(2); +#endif + } + result = (uint8_t)SSP0DR; + return result; +} + +void cc1100_spi_cs(void) +{ + FIO1CLR = BIT21; +} + +void +cc1100_spi_select(void) +{ + volatile int retry_count = 0; + volatile int abort_count; + // Switch to GDO mode input + PINSEL3 &= ~(BIT14 + BIT15);// Set MISO function to GPIO + FIO1DIR &= ~BIT23; + cs_low: + // CS to low + abort_count = 0; + FIO1CLR = BIT21; + // Wait for SO to go low (voltage regulator + // has stabilized and the crystal is running) + loop: + asm volatile ("nop"); + if (CC1100_GDO1) { + abort_count++; + if (abort_count > CC1100_GDO1_LOW_COUNT) { + retry_count++; + if (retry_count > CC1100_GDO1_LOW_RETRY) { + puts("[CC1100 SPI] fatal error\n"); + goto final; + } + FIO1SET = BIT21; // CS to high + goto cs_low; // try again + } + goto loop; + } + final: + // Switch to SPI mode + PINSEL3 |= (BIT14 + BIT15); // Set MISO function to SPI +} + +void +cc1100_spi_unselect(void) +{ + FIO1SET = BIT21; +} + +void cc1100_before_send(void) +{ + // Disable GDO2 interrupt before sending packet + cc1100_gdo2_disable(); +} + +void cc1100_after_send(void) +{ + // Enable GDO2 interrupt after sending packet + cc1100_gdo2_enable(); +} + +void cc1100_gdo0_enable(void) { + gpioint_set(0, BIT27, GPIOINT_RISING_EDGE, &cc1100_gdo0_irq); +} + +void cc1100_gdo0_disable(void) { + gpioint_set(0, BIT27, GPIOINT_DISABLE, NULL); +} + +void cc1100_gdo2_disable(void) { + gpioint_set(0, BIT28, GPIOINT_DISABLE, NULL); +} + +void cc1100_gdo2_enable(void) { + gpioint_set(0, BIT28, GPIOINT_FALLING_EDGE, &cc1100_gdo2_irq); +} + +void cc1100_init_interrupts(void) +{ + // Enable external interrupt on low edge (for GDO2) + FIO0DIR &= ~BIT28; + cc1100_gdo2_enable(); + // Enable external interrupt on low edge (for GDO0) + FIO0DIR &= ~BIT27; +} diff --git a/board/msba2/drivers/msba2-ltc4150.c b/board/msba2/drivers/msba2-ltc4150.c new file mode 100644 index 0000000000..c590dee8db --- /dev/null +++ b/board/msba2/drivers/msba2-ltc4150.c @@ -0,0 +1,65 @@ +/****************************************************************************** +Copyright 2008-2009, Freie Universitaet Berlin (FUB). All rights reserved. + +These sources were developed at the Freie Universitaet Berlin, Computer Systems +and Telematics group (http://cst.mi.fu-berlin.de). +------------------------------------------------------------------------------- +This file is part of FeuerWare. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +FeuerWare is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see http://www.gnu.org/licenses/ . +-------------------------------------------------------------------------------- +For further information and questions please use the web site + http://scatterweb.mi.fu-berlin.de +and the mailinglist (subscription via web site) + scatterweb@lists.spline.inf.fu-berlin.de +*******************************************************************************/ + +/** + * @ingroup msba2 + * @ingroup ltc4150 + * @{ + */ + +/** + * @file + * @brief LTC4150 MSB-A2 specific implemetation + * + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @author Heiko Will + * @author Michael Baar + * @author Kaspar Schleiser + */ + +#include +#include "lpc2387.h" +#include "ltc4150_arch.h" +#include "gpioint.h" + +void ltc4150_disable_int(void) { + gpioint_set(0, BIT4, GPIOINT_DISABLE, NULL); +} + +void ltc4150_enable_int(void) { + gpioint_set(0, BIT4, GPIOINT_FALLING_EDGE, <c4150_interrupt); +} + +void ltc4150_sync_blocking(void) { + while(!(FIO0PIN & BIT4)) {}; +} + +void ltc4150_arch_init() { + FIO0DIR |= BIT5; + FIO0SET = BIT5; +} + +/** @} */ diff --git a/board/msba2/drivers/msba2-uart0.c b/board/msba2/drivers/msba2-uart0.c new file mode 100644 index 0000000000..01aaf609dc --- /dev/null +++ b/board/msba2/drivers/msba2-uart0.c @@ -0,0 +1,205 @@ +/****************************************************************************** +Copyright 2008-2009, Freie Universitaet Berlin (FUB). All rights reserved. + +These sources were developed at the Freie Universitaet Berlin, Computer Systems +and Telematics group (http://cst.mi.fu-berlin.de). +------------------------------------------------------------------------------- +This file is part of FeuerWare. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +FeuerWare is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see http://www.gnu.org/licenses/ . +-------------------------------------------------------------------------------- +For further information and questions please use the web site + http://scatterweb.mi.fu-berlin.de +and the mailinglist (subscription via web site) + scatterweb@lists.spline.inf.fu-berlin.de +*******************************************************************************/ + +/* + * debug_uart.c: provides initial serial debug output + * + * Copyright (C) 2008, 2009 Kaspar Schleiser + * Heiko Will + */ +#include +#include +#include +#include "lpc23xx.h" +#include "VIC.h" + +/** + * @file + * @ingroup lpc2387 + * + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @version $Revision$ + * + * @note $Id$ + */ + +typedef struct toprint { + unsigned int len; + char content[]; +}toprint; + +#define QUEUESIZE 255 +static volatile toprint* queue[QUEUESIZE]; +static volatile unsigned char queue_head = 0; +static volatile unsigned char queue_tail = 0; +static volatile unsigned char queue_items = 0; + +static volatile unsigned int actual_pos = 0; +static volatile unsigned int running = 0; +static volatile unsigned int fifo = 0; + +static volatile toprint* actual = NULL; +void (*uart0_callback)(int); + +static inline void enqueue(void) { + queue_items++; + queue_tail++; +} + +static inline void dequeue(void) { + actual = (queue[queue_head]); + queue_items--; + queue_head++; +} + +static void push_queue(void) { + running = 1; +start: + if (!actual) { + if (queue_items) { + dequeue(); + } else { + running = 0; + if (!fifo) + while(!(U0LSR & BIT6)){}; + return; + } + } + while ((actual_pos < actual->len) && (fifo++ < 16)){ + U0THR = actual->content[actual_pos++]; + } + if (actual_pos == actual->len) { + free((void*)actual); + actual = NULL; + actual_pos = 0; + goto start; + } +} + +int uart_active(void){ + return (running || fifo); +} + +static inline void receive(int c) +{ + if (uart0_callback != NULL) uart0_callback(c); +} + +void stdio_flush(void) +{ + U0IER &= ~BIT1; // disable THRE interrupt + while(running) { + while(!(U0LSR & (BIT5|BIT6))){}; // transmit fifo + fifo=0; + push_queue(); // dequeue to fifo + } + U0IER |= BIT1; // enable THRE interrupt +} + +void UART0_IRQHandler(void) __attribute__((interrupt("IRQ"))); +void UART0_IRQHandler(void) +{ + int iir; + iir = U0IIR; + + switch(iir & UIIR_ID_MASK) { + case UIIR_THRE_INT: // Transmit Holding Register Empty + fifo=0; + push_queue(); + break; + + case UIIR_CTI_INT: // Character Timeout Indicator + case UIIR_RDA_INT: // Receive Data Available + do { + int c = U0RBR; + receive(c); + } while (U0LSR & ULSR_RDR); + break; + + default: + U0LSR; + U0RBR; + break; + } // switch + VICVectAddr = 0; // Acknowledge Interrupt +} + +static inline int uart0_puts(char *astring,int length) +{ + while (queue_items == (QUEUESIZE-1)) {} ; + U0IER = 0; + queue[queue_tail] = malloc(length+sizeof(unsigned int)); + queue[queue_tail]->len = length; + memcpy(&queue[queue_tail]->content,astring,length); + enqueue(); + if (!running) + push_queue(); + U0IER |= BIT0 | BIT1; // enable RX irq + + /* alternative without queue: + int i; + for (i=0;iconfig->speed + /* + * Baudrate calculation + * BR = PCLK (9 MHz) / (16 x 256 x DLM + DLL) x (1/(DIVADDVAL/MULVAL)) + */ + U0FDR = 0x92; // DIVADDVAL = 0010 = 2, MULVAL = 1001 = 9 + U0DLM = 0x00; + U0DLL = 0x04; + + U0LCR = 0x03; // DLAB = 0 + U0FCR = 0x07; // Enable and reset TX and RX FIFO + + /* irq */ + install_irq(UART0_INT, UART0_IRQHandler, 6); + U0IER |= BIT0 | BIT1; // enable RX+TX irq + return 1; +} + diff --git a/board/msba2/include/board-conf.h b/board/msba2/include/board-conf.h new file mode 100644 index 0000000000..2c8824f1fc --- /dev/null +++ b/board/msba2/include/board-conf.h @@ -0,0 +1,68 @@ +/****************************************************************************** +Copyright 2008, Freie Universitaet Berlin (FUB). All rights reserved. + +These sources were developed at the Freie Universitaet Berlin, Computer Systems +and Telematics group (http://cst.mi.fu-berlin.de). +------------------------------------------------------------------------------- +This file is part of FeuerWare. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +FeuerWare is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see http://www.gnu.org/licenses/ . +-------------------------------------------------------------------------------- +For further information and questions please use the web site + http://scatterweb.mi.fu-berlin.de +and the mailinglist (subscription via web site) + scatterweb@lists.spline.inf.fu-berlin.de +*******************************************************************************/ + +#ifndef BOARDCONF_H_ +#define BOARDCONF_H_ + +/** + * @ingroup conf + * @ingroup msba2 + * + * @{ + */ + +/** + * @file + * @brief MSB-A2 board configuration + * + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @author baar + * @version $Revision$ + * + * @note $Id$ + */ + +#define FEUERWARE_CONF_BOARD_NAME "FU Berlin MSB-A2" + +#ifdef MODULE_CC110X +#define FEUERWARE_CONF_NUM_RADIOS 1 +#else +#define FEUERWARE_CONF_NUM_RADIOS 0 +#endif + +// if FAT is enabled this board supports files +#define FEUERWARE_CONF_CORE_SUPPORTS_FILES defined(MODULE_FAT) + +#ifdef MODULE_FAT +#define CFG_CONF_MEM_SIZE 0x7FFFFFFF +#define SYSLOG_CONF_NUM_INTERFACES 2 +#else +#define SYSLOG_CONF_NUM_INTERFACES 1 +#endif + + +/** @} */ +#endif /* BOARDCONF_H_ */ diff --git a/board/msba2/include/board.h b/board/msba2/include/board.h new file mode 100644 index 0000000000..4356e4423f --- /dev/null +++ b/board/msba2/include/board.h @@ -0,0 +1,62 @@ +/****************************************************************************** +Copyright 2008, Freie Universitaet Berlin (FUB). All rights reserved. + +These sources were developed at the Freie Universitaet Berlin, Computer Systems +and Telematics group (http://cst.mi.fu-berlin.de). +------------------------------------------------------------------------------- +This file is part of FeuerWare. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +FeuerWare is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see http://www.gnu.org/licenses/ . +-------------------------------------------------------------------------------- +For further information and questions please use the web site + http://scatterweb.mi.fu-berlin.de +and the mailinglist (subscription via web site) + scatterweb@lists.spline.inf.fu-berlin.de +*******************************************************************************/ + +#ifndef __BOARD_H +#define __BOARD_H + +/** + * @ingroup msb_a2 + * @{ + */ + +/** + * @file + * @brief MSB-A2 Board + * + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @author Kaspar Schleiser + * @version $Revision$ + * + * @note $Id$ + */ + +#include + +#define VICIntEnClear VICIntEnClr + +#define LED_RED_PIN (BIT25) +#define LED_GREEN_PIN (BIT26) + +#define LED_GREEN_OFF (FIO3SET = LED_GREEN_PIN) +#define LED_GREEN_ON (FIO3CLR = LED_GREEN_PIN) +#define LED_GREEN_TOGGLE (FIO3PIN ^= LED_GREEN_PIN) + +#define LED_RED_OFF (FIO3SET = LED_RED_PIN) +#define LED_RED_ON (FIO3CLR = LED_RED_PIN) +#define LED_RED_TOGGLE (FIO3PIN ^= LED_RED_PIN) + +/** @} */ +#endif // __BOARD_H diff --git a/board/msba2/lpc2387-timer3.c b/board/msba2/lpc2387-timer3.c new file mode 100644 index 0000000000..8978390e9a --- /dev/null +++ b/board/msba2/lpc2387-timer3.c @@ -0,0 +1,37 @@ +/* + * lpc2387_timer0.c + * + * Created on: 13.01.2009 + * Author: heiko + */ + +#include +#include +#include "lpc2387.h" +#include "benchmark.h" + +void benchmark_init(void) +{ + PCLKSEL1 = (PCLKSEL1 & ~(BIT14|BIT15)) | (1 << 14); // CCLK to PCLK divider + PCONP |= PCTIM3; + T3TCR = 0; // disable timer + T3MCR = 0; // disable interrupt + T3CCR = 0; // capture is disabled. + T3EMR = 0; // no external match output. + T3PR = 0; // set prescaler + T3TC = 0; // reset counter +} + +void benchmark_reset_start(void) +{ + T3TCR = 0; // disable timer + T3TC = 0; // reset counter + T3TCR = BIT0; +} + +unsigned int benchmark_read_stop(void) +{ + T3TCR = 0; // disable timer + return T3TC; +} + diff --git a/board/msba2/tools/CHANGES b/board/msba2/tools/CHANGES new file mode 100644 index 0000000000..dd9e6ec1ea --- /dev/null +++ b/board/msba2/tools/CHANGES @@ -0,0 +1,23 @@ +(heavily hacked by Heiko Will & Kaspar Schleiser since then) + +1.05 (9-Apr-2007) +----------------- +Added boot jump code specific to 2378 (and similar chips) to +disable the PLL before jumping to the user's code. + +1.04 (19-Dec-2006) +------------------ +Added 2364, 2366, 2368, 2378 & 2468 to list. Untested. + +1.03 (2-Jun-2006) +----------------- +Added 2103 chip to chip list. ID numbers for 2101 and 2102 unknown + +1.02 (31-Jul-2005) +------------------ +Added support for other chips +Added soft boot code +Added user configurable crystal value (for baud sync protocol) + + + diff --git a/board/msba2/tools/COPYING b/board/msba2/tools/COPYING new file mode 100644 index 0000000000..a43ea2126f --- /dev/null +++ b/board/msba2/tools/COPYING @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/board/msba2/tools/Makefile b/board/msba2/tools/Makefile new file mode 100644 index 0000000000..91d44fdf78 --- /dev/null +++ b/board/msba2/tools/Makefile @@ -0,0 +1,43 @@ +CFLAGS = -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" +CC = gcc + +all: lpc2k_pgm pseudoterm + +SRC = lpc2k_pgm.c download.c uuencode.c ihex.c serial.c chipinfo.c boot_2xxx.c boot_23xx.c control_2xxx.c +OBJS = ${addprefix obj/,${patsubst %.c,%.o,$(SRC)}} + +PSEUDOTERM_SRC = pseudoterm.c serial.c control_2xxx.c +PSEUDOTERM_OBJS = ${addprefix obj/,${patsubst %.c,%.o,$(PSEUDOTERM_SRC)}} + +TARGETDIR = bin + +lpc2k_pgm: $(OBJS) + $(CC) -o $(TARGETDIR)/lpc2k_pgm $(OBJS) + +pseudoterm: $(PSEUDOTERM_OBJS) + $(CC) -lpthread -o $(TARGETDIR)/pseudoterm $(PSEUDOTERM_OBJS) + +chipinfo.o: boot_2xxx.h boot_23xx.h + +static: $(OBJS) mkstaticlist + $(CC) -o $(TARGETDIR)/lpc2k_pgm $(OBJS) `./mkstaticlist` + +obj/%.o : src/%.c + $(CC) $(CFLAGS) -c $< -o $@ + +cksum_test: cksum_test.c uuencode.o cksum_test.o + $(CC) $(CFLAGS) -o $(TARGETDIR)/cksum_test obj/cksum_test.o obj/uuencode.o + +boot_2xxx.c boot_2xxx.h: boot_2xxx.armasm mkbootc + arm-elf-as -o boot_2xxx.armobj boot_2xxx.armasm + arm-elf-objdump -d boot_2xxx.armobj | ./mkbootc boot_2xxx + +boot_23xx.c boot_23xx.h: src/boot_23xx.armasm mkbootc + arm-elf-as -o obj/boot_23xx.armobj src/boot_23xx.armasm + arm-elf-objdump -d obj/boot_23xx.armobj | ./mkbootc boot_23xx + +clean: + rm -f bin/lpc2k_pgm cksum_test obj/*.o core core.* obj/*.armobj bin/pseudoterm + +obj/gui.o: src/gui.c + $(CC) $(CFLAGS) `gtk-config --cflags` -c src/gui.c -o obj/gui.o diff --git a/board/msba2/tools/README.txt b/board/msba2/tools/README.txt new file mode 100644 index 0000000000..8fd6adb012 --- /dev/null +++ b/board/msba2/tools/README.txt @@ -0,0 +1,144 @@ +This utility downloads code to Philip LPC 2000 series chips, using the +bootloader communication protocol documented in the LPC2106/2105/2104 +User Manual, Sept 2003 revision, pages 177 to 192. This code has also +been tested with LPC2131 and LPC2138 chips (thanks to New Micros for +providing eval boards). It may work with other Philips ARM LPC parts. + + + +Usage: +----- + +When you start the program, it's small control window appears, and a +xterm terminal window is launched. The Xterm window allows you to +simply leave lpc2k_pgm running and interface with the LPC uart using +that window. Most people configure "printf" on in their code to print +to UART0, which will appear in this window. + +This program has 4 settings: + +Firmware: The intel-hex file with your LPC firmware to program. +Port: Which serial device to use. +Baud: The baud rate to communicate. +Crystal: The speed of the crystal on your LPC board. + +Once you have set up these values, simply press the "Program Now" +button to write your firmware to the LPC flash memory, and automatically +run it. If your firmware communicates on UART0, its messages will appear +in the xterm window, and anything you type in that window will be +transmitted to your board. + +The "Reboot" button may be used to reboot your code (assuming you have +connected DTR appropriately). The "Bootloader" button may be used to +stop your code by rebooting into the bootloader, rather than your program. + + + +Hardware Requirements: +--------------------- + +You must have a compatible Philips LPC chip with its UART0 interfaced +to a serial port on your PC. + +You must be able to reset the chip and cause it to enter bootloader mode. +Normally, this is done by connecting the (TTL level translated) DTR signal +to the LPC reset, so that when DTR is high (the TTL version is low), the +Philips chip is in reset mode. Alternately, a pushbutton may be used, +but you will need to manually press the button every time you want to get +back into bootloader mode (while this program attempts to sync baud rates), +rather than letting DTR do it automatically. A few minutes spent wiring +up your circuit so DTR can reset the board will save you much trouble as +you develop code. + +P0.14 must be connected low shortly after reset. Normally, this pin +is just shorted to ground using a jumper. Starting with version 1.02, +you can simply leave this shorted to ground. If your design needs to +use this pin, you may also build a simple circuit that forces this pin +to ground when RTS is high. + + + +Software Requirements: +--------------------- + +You must have a Linux-based system running X Windows. This code has +been tested with Linux kernel 2.4.20 and 2.6.8, and should work with +almost any linux system. + +You must have the "xterm" program installed. Nearly all linux +distrubtions provide this, and it is often installed by default. If +you do not have it, simply install from your linux distribution. + +Your serial port device file (usually /dev/ttyS0 or /dev/ttyS1) must +allow permission for you to use the serial port. + +GTK 1.2 is used for the GUI. Many newer systems only have GTK version +2 (or higher). If you have one of these systems, perhaps you can +install GTK 1.2 (including the development libraries) to allow you to +compile this code. Alternately, you may be able to use the semi-static +build, which includes a copy of this code built into the program. + + + +Building and Installation: +------------------------- + +This software is only provided semi-static binary and source code form. + +To use the semi-static binary, simply copy it to a location where you +can run it, and change the permissions if necessary: + + cp lpc2k_pgm /usr/local/bin + chmod 755 /usr/local/bin/lpc2k_pgm + +The semi-static binary has all of the GTK and X11 libraries statically +linked into it, for maximum compatibility with all linux distributions. +The only disadvantage is, of course, that this uses an extra 1.4 megs +of RAM, with (might) otherwise be shared with other programs. If you +simply want to run this program with minimal work, using the semi-static +binary may be the easiest way. + +If you compile from the source code, the result should be a small +binary that is optimal for your system. + +To build from source, you must have GTK+ 1.2 development libraries +and GCC properly installed. Nearly all linux distributions provide +these as packages, but you may need to install them before you can +compile the code. + +TODO: specific instructions for Debian stable +TODO: specific instructions for Debian testing/unstable +TODO: specific instructions for Fedora +TODO: specific instructions for Suse + +Simply type "make" to build the code. The resulting "lpc2k_pgm" +program can be run from any location. Simply copy to /usr/local/bin, +or where ever you like. + + + +Contact Info: +------------ + +Paul Stoffregen +paul@pjrc.com +http://www.pjrc.com/arm/lpc2k_pgm + +If you discover a bug, you want to request a new feature, or you have +a new Philips LPC chip which is not recognized, please attempt to +provide COMPLETE information in your message. + +If you have problems building from source, please contact me with ALL +of the following: + +1: Complete copy of all messages during the build. +2: Output of "gtk-config --version" +3: Output of "gtk-config --libs" +4: Output of "gtk-config --cflags" +5: Output of "uname -a" +6: Other info... which linux distribution, version, other software + +If you get "Command not found" when trying to run "gtk-config", this +is a sure sign that you do not have GTK+ 1.2 installed. + + diff --git a/board/msba2/tools/armtools.txt b/board/msba2/tools/armtools.txt new file mode 100644 index 0000000000..c91a4853f7 --- /dev/null +++ b/board/msba2/tools/armtools.txt @@ -0,0 +1,15 @@ +This directory contains flash & terminal-utilities for use with +the msb_av2 platform used by the FeuerWhere-Project. + +Usage: +Running "./pseudoterm /dev/ttyUSB1" will start the terminal-emulator, +open the specified port and reset the connected msb_av2-board. +If it receives a SIGUSR2, the terminal closes the port an waits. +On reception of a SIGUSR1, it reopens the port and resets the ARM. + +"./lpc2k_pgm /dev/ttyUSB1 /path/to/firmware.ihex" will do what you +expect, but it will additionally run "killall -SIGUSR2 pseudoterm" before +anѕ "killall -SIGUSR1 pseudoterm" after flashing. + +Together, the tools enable you to have a terminal connected to the board +at all times, but let you flash whenever you feel like. diff --git a/board/msba2/tools/flash.cmd b/board/msba2/tools/flash.cmd new file mode 100755 index 0000000000..e957ca2b65 --- /dev/null +++ b/board/msba2/tools/flash.cmd @@ -0,0 +1,2 @@ +fm.exe "COM(%1, 230400) DEVICE(LPC2387, 16.000000) HARDWARE(BOOTEXEC, 50, 100) HIGHSPEED(0, 230400) ERASEUSED(%2, PROTECTISP) HEXFILE(%2, NOCHECKSUMS, NOFILL, PROTECTISP) RESET" +sleep 2 diff --git a/board/msba2/tools/flashutil.sh b/board/msba2/tools/flashutil.sh new file mode 100755 index 0000000000..c97d7c9a63 --- /dev/null +++ b/board/msba2/tools/flashutil.sh @@ -0,0 +1,113 @@ +#/bin/bash + +linux_checkid() { + udevinfo -a -n ${1} | grep -q "ATTRS{product}==\"${2}\"" +} + +windows_flash_fm() { + echo "Checking FTDI device on COM${1}" + PORTINFO=`${BASEDIR}/../../../tools/windows/ftdiinfo/bin/Debug/ftdiinfo.exe /l COM${1}` + PORTCHECK=`echo ${PORTINFO} | awk '{ print $1 }'` + BOARDCHECK=`echo ${PORTINFO} | awk '{ print $3 }'` + SERIAL=`echo ${PORTINFO} | awk '{ print $2 }'` + if [ "${PORTCHECK}" != "COM${1}" ]; then + echo " port mismatch / ftdiinfo failed" + exit 1 + fi + if [ "${BOARDCHECK}" != "\"${FTDI_ID}\"" ]; then + echo " target mismatch: target board is \"${FTDI_ID}\", connected is ${BOARDCHECK}" + exit 1 + fi + + echo "Flashing ${HEXFILE} to COM${1} (${BOARDCHECK} serial ${SERIAL})" + # Using FlashMagic on Windows (in separate window) + cmd /C start "FlashMagic ${HEXFILE} to ${BOARDCHECK} on COM${1}" fm.exe "COM(${1}, 230400) DEVICE(LPC2387, 16.000000) HARDWARE(BOOTEXEC, 50, 100) HIGHSPEED(0, 230400) ERASEUSED(${HEXFILE}, PROTECTISP) HEXFILE(${HEXFILE}, NOCHECKSUMS, NOFILL, PROTECTISP) RESET" +} + +windows_flash_openocd() { + echo "Flashing ${HEXFILE} through JTAG" + # Using OpenOcd on Windows + #cmd /C start "OpenOCD ${HEXFILE} to ${BOARDCHECK}" + bash -x ${OPENOCD} ${OPENOCD_IF} "mt_flash ${HEXFILE}; reset run; shutdown" +} + +TEMP=`getopt -a -o b:i:p:f:: --long basedir:,id:,ports:,file:,openocd:,openocd-if:,xxx:: \ + -n 'flashutil.sh' -- "$@"` + +if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi + +# Note the quotes around `$TEMP': they are essential! +eval set -- "$TEMP" + +while true ; do + echo $1: $2 + case "$1" in + -b|--basedir) BASEDIR=$2 ; shift 2 ;; + -i|--id) FTDI_ID=$2; shift 2 ;; + -p|--ports) PORTS=`echo $2 | sed -e 's:,: :g'`; shift 2 ;; + --openocd) OPENOCD=$2; shift 2 ;; + --openocd-if) OPENOCD_IF=$2; shift 2 ;; + + --) HEXFILE=$2 ; shift ; break ;; + *) echo "Internal error!" ; exit 1 ;; + esac +done + +if [ "${OS}" = "Windows_NT" ]; then + WINDOWS=1 +fi + +FLASHUTIL_SHELL=${FLASHUTIL_SHELL:-"xterm -e"} + +if [ "x${WINDOWS}x" = "xx" ]; then + echo Pausing terminal + ${BASEDIR}/termctrl.sh pause +else + HEXFILE=`echo ${HEXFILE} | sed -e 's:/:\\\\:g'` + BASEDIRWIN=`echo ${BASEDIR} | sed -e 's:/:\\\\:g'` +fi + +pids="" + +# +# for OpenOCD let the user verify, that the correct board is connected +# +if [ ${PORTS} = "openocd" ]; then + [ "$OPENOCD" != "" ] || exit 1 + [ "$OPENOCD_IF" != "" ] || exit 1 +# echo -n "Is the board connected to the JTAG a '${FTDI_ID}' (y/n)? " +# read REPLY +# [ "$REPLY" = "y" ] || exit 1 +fi +# +# start a flasher for each port +# +for PORT in $PORTS; do + if [ "x${WINDOWS}x" != "xx" ]; then + if [ "${PORT}" = "openocd" ]; then + windows_flash_openocd + else + windows_flash_fm ${PORT} + fi + else + if [ "${PORT}" = "openocd" ]; then + ${OPENOCD} ${OPENOCD_IF} "mt_flash ${HEXFILE}; reset run; shutdown" + else + echo Flashing ${HEXFILE} to ${PORT} + # using homemade lpc2k_pgm else + ${FLASHUTIL_SHELL} "${BASEDIR}/bin/lpc2k_pgm ${PORT} ${HEXFILE}; sleep 2" & + pids="${pids} $!" + fi + fi +done + +### wait for all flasher processes to finish +echo Waiting until all devices have been programmed... +for pid in "${pids}"; do + wait ${pid} +done + +if [ "x${WINDOWS}x" = "xx" ]; then + echo Resuming terminal + ${BASEDIR}/termctrl.sh continue +fi diff --git a/board/msba2/tools/mkbootc b/board/msba2/tools/mkbootc new file mode 100644 index 0000000000..4c0d9554dc --- /dev/null +++ b/board/msba2/tools/mkbootc @@ -0,0 +1,28 @@ +#! /usr/bin/perl + +$h = '[0-9A-Fa-f]'; +$n = 1; +while () { + next unless /^\s*$h+:\s+($h{8})/; + $data[$n++] = "0x$1"; +} +$data[0] = $n; +#$size = $ARGV[0]; +#$size =~ tr/a-z/A-Z/; +#$size .= '_SIZE'; + +open H, ">$ARGV[0].h" or die "unable to write boot.h\n"; +print H "/* automatically generated from $ARGV[0].armasm */\n"; +#print H "#define $size $n\n"; +print H "extern const unsigned int ${ARGV[0]}[];\n"; +close H; + +open C, ">$ARGV[0].c" or die "unable to write boot.c\n"; +print C "/* automatically generated from $ARGV[0].armasm */\n"; +print C "#include \"$ARGV[0].h\"\n"; +print C "const unsigned int ${ARGV[0]}[] = {\n"; +print C "\t", join(', ', @data), "\n"; +print C "};\n"; +close C; + + diff --git a/board/msba2/tools/mkstaticlist b/board/msba2/tools/mkstaticlist new file mode 100644 index 0000000000..4ad31030ca --- /dev/null +++ b/board/msba2/tools/mkstaticlist @@ -0,0 +1,47 @@ +#! /usr/bin/perl + +@arg = split(/\s+/, `gtk-config --libs`); + +%liblist = ( + 'libgtk.a', '/usr/lib/libgtk.a', + 'libgdk.a', '/usr/lib/libgdk.a', + 'libgmodule.a', '/usr/lib/libgmodule.a', + 'libglib.a', '/usr/lib/libglib.a', + 'libXi.a', '/usr/X11R6/lib/libXi.a', + 'libXext.a', '/usr/X11R6/lib/libXext.a', + 'libX11.a', '/usr/X11R6/lib/libX11.a' +); + + +for ($i=0; $i<@arg; $i++) { + $a = $arg[$i]; + next if $a eq '-rdynamic'; # always delete -rdynamic + if (($a eq '-lm') || ($a eq '-ldl') || ($a =~ /^-L/)) { + # a few things we never change + print "$a "; + next; + } + if ($a =~ /^-l/) { + $lib = $'; + $lib = 'lib' . $lib . '.a'; + # first check if it's in the known location + if (-f $liblist{$lib}) { + print $liblist{$lib}, " "; + next; + } + # resort to trying whereis to find it + @source = split(/\s+/, `whereis $lib`); + undef($static); + for ($j=0; $j<@source; $j++) { + $static = $source[$j] if $source[$j] =~ /$lib$/; + } + # if we found a static lib, use it. + if ($static) { + print $static, " "; + } else { + print $a, " "; + } + } +} +print "\n"; + diff --git a/board/msba2/tools/obj/boot_23xx.d b/board/msba2/tools/obj/boot_23xx.d new file mode 100644 index 0000000000..874c0d70ef --- /dev/null +++ b/board/msba2/tools/obj/boot_23xx.d @@ -0,0 +1,3 @@ +obj/boot_23xx.d obj/boot_23xx.o: src/boot_23xx.c src/boot_23xx.h + +src/boot_23xx.h: diff --git a/board/msba2/tools/obj/boot_2xxx.d b/board/msba2/tools/obj/boot_2xxx.d new file mode 100644 index 0000000000..b33d065787 --- /dev/null +++ b/board/msba2/tools/obj/boot_2xxx.d @@ -0,0 +1,3 @@ +obj/boot_2xxx.d obj/boot_2xxx.o: src/boot_2xxx.c src/boot_2xxx.h + +src/boot_2xxx.h: diff --git a/board/msba2/tools/obj/chipinfo.d b/board/msba2/tools/obj/chipinfo.d new file mode 100644 index 0000000000..b6840f4c8d --- /dev/null +++ b/board/msba2/tools/obj/chipinfo.d @@ -0,0 +1,8 @@ +obj/chipinfo.d obj/chipinfo.o: src/chipinfo.c src/chipinfo.h \ + src/boot_2xxx.h src/boot_23xx.h + +src/chipinfo.h: + +src/boot_2xxx.h: + +src/boot_23xx.h: diff --git a/board/msba2/tools/obj/control_2xxx.d b/board/msba2/tools/obj/control_2xxx.d new file mode 100644 index 0000000000..d91c1b90fe --- /dev/null +++ b/board/msba2/tools/obj/control_2xxx.d @@ -0,0 +1,6 @@ +obj/control_2xxx.d obj/control_2xxx.o: src/control_2xxx.c \ + src/control_2xxx.h src/serial.h + +src/control_2xxx.h: + +src/serial.h: diff --git a/board/msba2/tools/obj/download.d b/board/msba2/tools/obj/download.d new file mode 100644 index 0000000000..1bdc25ec41 --- /dev/null +++ b/board/msba2/tools/obj/download.d @@ -0,0 +1,19 @@ +obj/download.d obj/download.o: src/download.c src/lpc2k_pgm.h \ + src/download.h src/serial.h src/ihex.h src/uuencode.h src/chipinfo.h \ + src/boot.h src/control_2xxx.h + +src/lpc2k_pgm.h: + +src/download.h: + +src/serial.h: + +src/ihex.h: + +src/uuencode.h: + +src/chipinfo.h: + +src/boot.h: + +src/control_2xxx.h: diff --git a/board/msba2/tools/obj/ihex.d b/board/msba2/tools/obj/ihex.d new file mode 100644 index 0000000000..e2430e90ca --- /dev/null +++ b/board/msba2/tools/obj/ihex.d @@ -0,0 +1,3 @@ +obj/ihex.d obj/ihex.o: src/ihex.c src/ihex.h + +src/ihex.h: diff --git a/board/msba2/tools/obj/lpc2k_pgm.d b/board/msba2/tools/obj/lpc2k_pgm.d new file mode 100644 index 0000000000..50838bbfcf --- /dev/null +++ b/board/msba2/tools/obj/lpc2k_pgm.d @@ -0,0 +1,8 @@ +obj/lpc2k_pgm.d obj/lpc2k_pgm.o: src/lpc2k_pgm.c src/lpc2k_pgm.h \ + src/serial.h src/download.h + +src/lpc2k_pgm.h: + +src/serial.h: + +src/download.h: diff --git a/board/msba2/tools/obj/pseudoterm.d b/board/msba2/tools/obj/pseudoterm.d new file mode 100644 index 0000000000..3524292e42 --- /dev/null +++ b/board/msba2/tools/obj/pseudoterm.d @@ -0,0 +1,6 @@ +obj/pseudoterm.d obj/pseudoterm.o: src/pseudoterm.c src/serial.h \ + src/download.h + +src/serial.h: + +src/download.h: diff --git a/board/msba2/tools/obj/serial.d b/board/msba2/tools/obj/serial.d new file mode 100644 index 0000000000..70d6d9d7dc --- /dev/null +++ b/board/msba2/tools/obj/serial.d @@ -0,0 +1,3 @@ +obj/serial.d obj/serial.o: src/serial.c src/serial.h + +src/serial.h: diff --git a/board/msba2/tools/obj/uuencode.d b/board/msba2/tools/obj/uuencode.d new file mode 100644 index 0000000000..fa6d25aca3 --- /dev/null +++ b/board/msba2/tools/obj/uuencode.d @@ -0,0 +1,3 @@ +obj/uuencode.d obj/uuencode.o: src/uuencode.c src/uuencode.h + +src/uuencode.h: diff --git a/board/msba2/tools/src/Jamfile b/board/msba2/tools/src/Jamfile new file mode 100644 index 0000000000..43ead81f93 --- /dev/null +++ b/board/msba2/tools/src/Jamfile @@ -0,0 +1,9 @@ +Library liblpc2k : download.c uuencode.c ihex.c serial.c chipinfo.c boot_2xxx.c boot_23xx.c control_2xxx.c ; + +LinkLibraries lpc2k_pgm : liblpc2k ; + +LinkLibraries pseudoterm : liblpc2k ; +LINKFLAGS on pseudoterm = -lrt ; + +Main lpc2k_pgm : lpc2k_pgm.c ; +Main pseudoterm : pseudoterm.c ; diff --git a/board/msba2/tools/src/boot.h b/board/msba2/tools/src/boot.h new file mode 100644 index 0000000000..1560f10380 --- /dev/null +++ b/board/msba2/tools/src/boot.h @@ -0,0 +1,9 @@ + +typedef struct { + int size; + const int *prog; +} boot_t; + + + + diff --git a/board/msba2/tools/src/boot_23xx.armasm b/board/msba2/tools/src/boot_23xx.armasm new file mode 100644 index 0000000000..50e29957ff --- /dev/null +++ b/board/msba2/tools/src/boot_23xx.armasm @@ -0,0 +1,32 @@ + /* ARM code to run user code */ + /* on the LPC23xx chips, the bootloader defaults to using the RC */ + /* osciallator and it activates the PLL to create 14.78 MHz, even */ + /* if there is no crystal. However, when we use try to jump to */ + /* the user's code, their startup routine may (incorrectly) assume */ + /* the PLL is not enabled and crash if it is. So in addition to */ + /* remapping the reset vector to flash, we have to shut off the */ + /* PLL so the user's startup code sees the same conditions as it */ + /* would following a hard reset */ +begin: + adr r0, const + ldr r1, [r0] /* r1 points to MEMMAP register */ + ldr r2, [r0,#4] /* r2 points to PLLCON */ + ldr r3, [r0,#8] /* r3 points to PLLFEED */ + mov r0, #1 + str r0, [r1] /* remap interrupt vectors to flash */ + mov r4, #0xAA + mov r5, #0x55 + str r0, [r2] /* disconnect the PLL, PLLCON = 1 */ + str r4, [r3] + str r5, [r3] + mov r0, #0 + str r0, [r2] /* disable the PLL, PLLCON = 0 */ + str r4, [r3] + str r5, [r3] + mov pc, #0 /* and then jump to the user's code */ +const: + .int 0xE01FC040 /* MEMMAP register */ + .int 0xE01FC080 /* PLLCON */ + .int 0xE01FC08C /* PLLFEED */ + + diff --git a/board/msba2/tools/src/boot_23xx.c b/board/msba2/tools/src/boot_23xx.c new file mode 100644 index 0000000000..9901171cc0 --- /dev/null +++ b/board/msba2/tools/src/boot_23xx.c @@ -0,0 +1,5 @@ +/* automatically generated from boot_23xx.armasm */ +#include "boot_23xx.h" +const unsigned int boot_23xx[] = { + 20, 0xe28f0038, 0xe5901000, 0xe5902004, 0xe5903008, 0xe3a00001, 0xe5810000, 0xe3a040aa, 0xe3a05055, 0xe5820000, 0xe5834000, 0xe5835000, 0xe3a00000, 0xe5820000, 0xe5834000, 0xe5835000, 0xe3a0f000, 0xe01fc040, 0xe01fc080, 0xe01fc08c +}; diff --git a/board/msba2/tools/src/boot_23xx.h b/board/msba2/tools/src/boot_23xx.h new file mode 100644 index 0000000000..0696a29312 --- /dev/null +++ b/board/msba2/tools/src/boot_23xx.h @@ -0,0 +1,2 @@ +/* automatically generated from boot_23xx.armasm */ +extern const unsigned int boot_23xx[]; diff --git a/board/msba2/tools/src/boot_2xxx.armasm b/board/msba2/tools/src/boot_2xxx.armasm new file mode 100644 index 0000000000..38e171520a --- /dev/null +++ b/board/msba2/tools/src/boot_2xxx.armasm @@ -0,0 +1,15 @@ + /* ARM code to run user code */ + /* This allows us to jump to the user's code in flash. We have */ + /* to remap the flash before jumping. */ +begin: + adr r0, const + ldr r1, [r0] /* r1 points to MEMMAP register */ + mov r0, #1 + str r0, [r1] /* remap interrupt vectors to flash */ + mov pc, #0 /* and then jump to the user's code */ +const: + .int 0xE01FC040 /* MEMMAP register */ + + + + diff --git a/board/msba2/tools/src/boot_2xxx.c b/board/msba2/tools/src/boot_2xxx.c new file mode 100644 index 0000000000..4d9b367ebe --- /dev/null +++ b/board/msba2/tools/src/boot_2xxx.c @@ -0,0 +1,5 @@ +/* automatically generated from boot_2xxx.armasm */ +#include "boot_2xxx.h" +const unsigned int boot_2xxx[] = { + 7, 0xe28f000c, 0xe5901000, 0xe3a00001, 0xe5810000, 0xe3a0f000, 0xe01fc040 +}; diff --git a/board/msba2/tools/src/boot_2xxx.h b/board/msba2/tools/src/boot_2xxx.h new file mode 100644 index 0000000000..333188def2 --- /dev/null +++ b/board/msba2/tools/src/boot_2xxx.h @@ -0,0 +1,2 @@ +/* automatically generated from boot_2xxx.armasm */ +extern const unsigned int boot_2xxx[]; diff --git a/board/msba2/tools/src/chipinfo.c b/board/msba2/tools/src/chipinfo.c new file mode 100644 index 0000000000..4f3f1a9d7e --- /dev/null +++ b/board/msba2/tools/src/chipinfo.c @@ -0,0 +1,159 @@ +/* + * LPC 2000 Loader, http://www.pjrc.com/arm/lpc2k_pgm + * Copyright (c) 2004, PJRC.COM, LLC, + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include +#include "chipinfo.h" +#include "boot_2xxx.h" +#include "boot_23xx.h" + + +struct sector_info_struct lpc2106_layout[] = { + {0x00000000, 0x2000}, + {0x00002000, 0x2000}, + {0x00004000, 0x2000}, + {0x00006000, 0x2000}, + {0x00008000, 0x2000}, + {0x0000A000, 0x2000}, + {0x0000C000, 0x2000}, + {0x0000E000, 0x2000}, + {0x00010000, 0x2000}, + {0x00012000, 0x2000}, + {0x00014000, 0x2000}, + {0x00016000, 0x2000}, + {0x00018000, 0x2000}, + {0x0001A000, 0x2000}, + {0x0001C000, 0x2000} +}; + +struct sector_info_struct lpc2214_layout[] = { + {0x00000000, 0x2000}, + {0x00002000, 0x2000}, + {0x00004000, 0x2000}, + {0x00006000, 0x2000}, + {0x00008000, 0x2000}, + {0x0000A000, 0x2000}, + {0x0000C000, 0x2000}, + {0x0000E000, 0x2000}, + {0x00010000, 0x10000}, + {0x00020000, 0x10000}, + {0x00030000, 0x2000}, + {0x00032000, 0x2000}, + {0x00034000, 0x2000}, + {0x00036000, 0x2000}, + {0x00038000, 0x2000}, + {0x0003A000, 0x2000}, + {0x0003C000, 0x2000} +}; + +struct sector_info_struct lpc2138_layout[] = { + {0x00000000, 0x1000}, + {0x00001000, 0x1000}, + {0x00002000, 0x1000}, + {0x00003000, 0x1000}, + {0x00004000, 0x1000}, + {0x00005000, 0x1000}, + {0x00006000, 0x1000}, + {0x00007000, 0x1000}, + {0x00008000, 0x8000}, + {0x00010000, 0x8000}, + {0x00018000, 0x8000}, + {0x00020000, 0x8000}, + {0x00028000, 0x8000}, + {0x00030000, 0x8000}, + {0x00038000, 0x8000}, + {0x00040000, 0x8000}, + {0x00048000, 0x8000}, + {0x00050000, 0x8000}, + {0x00058000, 0x8000}, + {0x00060000, 0x8000}, + {0x00068000, 0x8000}, + {0x00070000, 0x8000}, + {0x00078000, 0x1000}, + {0x00079000, 0x1000}, + {0x0007A000, 0x1000}, + {0x0007B000, 0x1000}, + {0x0007C000, 0x1000} +}; + + + +// chunk_size is the number of bytes that will be sent with each +// "C" (Copy RAM to Flash) command. This must be one of the sizes +// supported by that command. Beware that different chips support +// different sets of sizes, so check the user manual specific to +// the chip. You must choose a chunk_size which is an an integer +// multiple of all the sector sizes, and it must be able to fit +// entirely within the RAM (allowing for the bootloader memory and +// stack usage). Currently, all available chunk sizes meet these +// requirements, but who knows what Philips will do in the future? +// +// ram_addr is the location in RAM where the chunks are sent by the +// "W" (Write to RAM) command. + + +struct chip_info_struct chip_info[] = { +// chunk num +//part_number id_string ram_addr _size sec sector layout boot code +{"LPC2104 (120k)", "4293984018", 0x40000200, 0x2000, 15, lpc2106_layout, boot_2xxx}, +{"LPC2105 (120k)", "4293984034", 0x40000200, 0x2000, 15, lpc2106_layout, boot_2xxx}, +{"LPC2106 (120k)", "4293984050", 0x40000200, 0x2000, 15, lpc2106_layout, boot_2xxx}, +{"LPC2114 (120k)", "16908050", 0x40000200, 0x2000, 15, lpc2106_layout, boot_2xxx}, +{"LPC2119 (120k)", "33685266", 0x40000200, 0x2000, 15, lpc2106_layout, boot_2xxx}, +{"LPC2124 (120k)", "16908051", 0x40000200, 0x2000, 15, lpc2106_layout, boot_2xxx}, +{"LPC2129 (248k)", "33685267", 0x40000200, 0x2000, 17, lpc2214_layout, boot_2xxx}, +{"LPC2131 (32k)", "196353", 0x40000200, 0x1000, 8, lpc2138_layout, boot_2xxx}, +{"LPC2132 (64k)", "196369", 0x40000200, 0x1000, 9, lpc2138_layout, boot_2xxx}, +{"LPC2134 (128k)", "196370", 0x40000200, 0x1000, 11, lpc2138_layout, boot_2xxx}, +{"LPC2136 (256k)", "196387", 0x40000200, 0x1000, 15, lpc2138_layout, boot_2xxx}, +{"LPC2138 (500k)", "196389", 0x40000200, 0x1000, 27, lpc2138_layout, boot_2xxx}, +{"LPC2141 (32k)", "67305217", 0x40000200, 0x1000, 8, lpc2138_layout, boot_2xxx}, +{"LPC2142 (64k)", "67305233", 0x40000200, 0x1000, 9, lpc2138_layout, boot_2xxx}, +{"LPC2144 (128k)", "67305234", 0x40000200, 0x1000, 11, lpc2138_layout, boot_2xxx}, +{"LPC2146 (256k)", "67305251", 0x40000200, 0x1000, 15, lpc2138_layout, boot_2xxx}, +{"LPC2148 (500k)", "67305253", 0x40000200, 0x1000, 27, lpc2138_layout, boot_2xxx}, +{"LPC2194 (248k)", "50462483", 0x40000200, 0x2000, 17, lpc2214_layout, boot_2xxx}, +{"LPC2212 (248k)", "67239698", 0x40000200, 0x2000, 17, lpc2214_layout, boot_2xxx}, +{"LPC2214 (248k)", "100794131", 0x40000200, 0x2000, 17, lpc2214_layout, boot_2xxx}, +{"LPC2292 (248k)", "67239699", 0x40000200, 0x2000, 17, lpc2214_layout, boot_2xxx}, +{"LPC2294 (248k)", "84016915", 0x40000200, 0x2000, 17, lpc2214_layout, boot_2xxx}, +//{"LPC2101 (8k)", "??????", 0x40000200, 0x1000, 2, lpc2138_layout, boot_2xxx}, +//{"LPC2102 (16k)", "??????", 0x40000200, 0x1000, 4, lpc2138_layout, boot_2xxx}, +{"LPC2103 (32k)", "327441", 0x40000200, 0x1000, 8, lpc2138_layout, boot_2xxx}, +{"LPC2364 (128k)", "100924162", 0x40000200, 0x1000, 11, lpc2138_layout, boot_23xx}, +{"LPC2366 (256k)", "100924195", 0x40000200, 0x1000, 15, lpc2138_layout, boot_23xx}, +{"LPC2368 (500k)", "100924197", 0x40000200, 0x1000, 27, lpc2138_layout, boot_23xx}, +{"LPC2378 (500k)", "117702437", 0x40000200, 0x1000, 27, lpc2138_layout, boot_23xx}, +{"LPC2387 (500k)", "402716981", 0x40000200, 0x1000, 27, lpc2138_layout, boot_23xx}, +{"LPC2387 (500k)", "385941301", 0x40000200, 0x1000, 27, lpc2138_layout, boot_23xx}, +{"LPC2468 (500k)", "100925237", 0x40000200, 0x1000, 27, lpc2138_layout, boot_23xx}, +{NULL, NULL, 0, 0, 0, NULL} +}; + + + +char *lpc_return_strings[] = { + "CMD_SUCCESS", "INVALID_COMMAND", "SRC_ADDR_ERROR", "DST_ADDR_ERROR", + "SRC_ADDR_NOT_MAPPED", "DST_ADDR_NOT_MAPPED", "COUNT_ERROR", "INVALID_SECTOR", + "SECTOR_NOT_BLANK", "SECTOR_NOT_PREPARED_FOR_WRITE_OPERATION", "COMPARE_ERROR", + "BUSY", "PARAM_ERROR", "ADDR_ERROR", "ADDR_NOT_MAPPED", "CMD_LOCKED", + "INVALID_CODE", "INVALID_BAUD_RATE", "INVALID_STOP_BIT", + "CODE_READ_PROTECTION_ENABLED" +}; + diff --git a/board/msba2/tools/src/chipinfo.h b/board/msba2/tools/src/chipinfo.h new file mode 100644 index 0000000000..1b12bb3666 --- /dev/null +++ b/board/msba2/tools/src/chipinfo.h @@ -0,0 +1,20 @@ +extern char *lpc_return_strings[]; + +struct sector_info_struct { // an array of + int address; // where each sector is located + int size; // and how big it is +}; + +struct chip_info_struct { + char *part_number; // human readable part number + char *id_string; // id string sent by "J" command + unsigned int ram_addr; // where to download into RAM + int chunk_size; // download to ram chunk size + int num_sector; // number of flash sectors + struct sector_info_struct *layout; // layout of sectors + const unsigned int *bootprog; // code that boots into user program (NULL = DTR/RTS only) +}; + +extern struct chip_info_struct chip_info[]; + + diff --git a/board/msba2/tools/src/cksum_test.c b/board/msba2/tools/src/cksum_test.c new file mode 100644 index 0000000000..8cff9b55e2 --- /dev/null +++ b/board/msba2/tools/src/cksum_test.c @@ -0,0 +1,76 @@ +/* + * LPC 2000 Loader, http://www.pjrc.com/arm/lpc2k_pgm + * Copyright (c) 2004, PJRC.COM, LLC, + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +/* If this code fails to build, please provide at least the following + * information when requesting (free) technical support. + * + * 1: Complete copy of all messages during the build. + * 2: Output of "gtk-config --version" + * 3: Output of "gtk-config --libs" + * 4: Output of "gtk-config --cflags" + * 5: Output of "uname -a" + * 6: Version of GTK installed... eg, type: ls -l /lib/libgtk* + * 7: Other info... which linux distribution, version, other software + */ + + +#include +#include +#include + +#include "uuencode.h" + + +unsigned int sum=0; + + + +void cksum(const char *str) +{ + int num, i; + unsigned char data[256]; + + if (str == NULL) return; + num = uudecode(str, data, sizeof(data)); + for (i=0; i +#include +#include + +#include "serial.h" + +void hard_reset_to_bootloader(void) +{ + printf("Reset CPU (into bootloader)\r\n"); + set_rts(1); // RTS (ttl level) connects to P0.14 + set_dtr(1); // DTR (ttl level) connects to RST + send_break_signal(); // or break detect circuit to RST + usleep(75000); + set_dtr(0); // allow the CPU to run + set_baud(baud_rate); + set_rts(1); // set RTS again (as it has been reset by set_baudrate) + usleep(40000); +} + +void hard_reset_to_user_code(void) +{ + printf("Reset CPU (into user code)\r\n"); + set_rts(0); // RTS (ttl level) connects to P0.14 + set_dtr(1); // DTR (ttl level) connects to RST + send_break_signal(); // or break detect circuit to RST + usleep(75000); + set_dtr(0); // allow the CPU to run + usleep(40000); +} diff --git a/board/msba2/tools/src/control_2xxx.h b/board/msba2/tools/src/control_2xxx.h new file mode 100644 index 0000000000..e37e2e29d5 --- /dev/null +++ b/board/msba2/tools/src/control_2xxx.h @@ -0,0 +1,8 @@ +#ifndef CONTROL_2XXXX_H +#define CONTROL_2XXXX_H + +void hard_reset_to_bootloader(void); +void hard_reset_to_user_code(void); + +#endif // ..._H + diff --git a/board/msba2/tools/src/download.c b/board/msba2/tools/src/download.c new file mode 100644 index 0000000000..5494661dfd --- /dev/null +++ b/board/msba2/tools/src/download.c @@ -0,0 +1,972 @@ +/* + * LPC 2000 Loader, http://www.pjrc.com/arm/lpc2k_pgm + * Copyright (c) 2004, PJRC.COM, LLC, + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +/* If this code fails to build, please provide at least the following + * information when requesting (free) technical support. + * + * 1: Complete copy of all messages during the build. + * 2: Output of "gtk-config --version" + * 3: Output of "gtk-config --libs" + * 4: Output of "gtk-config --cflags" + * 5: Output of "uname -a" + * 6: Version of GTK installed... eg, type: ls -l /lib/libgtk* + * 7: Other info... which linux distribution, version, other software + */ + +#include +#include +#include +#include +#include +#include + +#include "lpc2k_pgm.h" +#include "download.h" +#include "serial.h" +#include "ihex.h" +#include "uuencode.h" +//#include "gui.h" +#include "chipinfo.h" +#include "boot.h" +#include "control_2xxx.h" + + +// This will cause all bytes send and received to be printed as hex. +// It's a LOT of extra output, but useful for difficult debugging +// of what's _really_ being sent and received. +//#define PRINT_TX_RX_BYTES + + +static void download_main(int event); +static void xmit_cmd(const char *cmd, int max_time); +static void mk_valid_code_vector(void); +static unsigned int sum(unsigned char *data, int num); + + +static int state=0; +static int reboot_only=0; +static char expected_echo_buf[4096]; +static char *expected_echo_ptr=NULL; +static char parsed_response_buf[4096]; +static char *parsed_response_ptr=NULL; +static int response_timer=0; + +extern int programming_done; +extern int done_program(int); + + +char* port_name = "/dev/ttyUSB1"; +char* file_name = ""; +char* crystal = "16"; + +/****************************************************************/ +/* */ +/* Main Download Section */ +/* */ +/****************************************************************/ + +// possible states +#define SYNC_1 1 +#define SYNC_2 2 +#define SYNC_3 3 +#define CHIP_ID 4 +#define UNLOCK 5 +#define BLANK_CHECK_SECTOR 6 +#define ERASE_PREPARE 7 +#define ERASE_SECTOR 8 +#define DOWNLOAD_CODE 9 +#define XMIT_DATA 10 +#define XMIT_CKSUM 11 +#define WRITE_PREPARE 12 +#define WRITE_SECTOR 13 +#define BOOT_HARD 14 +#define BOOT_SOFT 15 +#define BOOT_XMIT_DATA 16 +#define BOOT_XMIT_CKSUM 17 +#define BOOT_RUN_CODE 18 + + +// possible input values for "event" +#define BEGIN 1 +#define RESPONSE 2 +#define TIMEOUT 3 +#define RETRY 4 + + + + +int download_begin(char* file) +{ + int r; + + file_name = file; + + printf("\r\nEntering Bootloader Mode\r\n"); + hard_reset_to_bootloader(); + printf("Read \"%s\"", file_name); + r = read_intel_hex(file_name); + if (r < 0) { + /* abort on ioerror */ + return 0; + } + printf(": %d bytes\r\n", r); + mk_valid_code_vector(); + state = SYNC_1; + reboot_only = 0; + download_main(BEGIN); + return 1; +} + + +void soft_reboot_begin(void) +{ + printf("\r\nEntering Bootloader Mode\r\n"); + hard_reset_to_bootloader(); + state = SYNC_1; + reboot_only = 1; + download_main(BEGIN); +} + +static void mk_valid_code_vector(void) +{ + unsigned char b[4]; + unsigned int sum=0; + int addr; + + for (addr=0; addr<0x20; addr+=4) { + if (addr != 0x14) { + get_ihex_data(addr, 4, b); + sum += (b[0] | (b[1] << 8) | (b[2] << 16) | (b[3] << 24)); + } + } + sum ^= 0xFFFFFFFF; + sum++; + b[0] = (sum >> 0) & 255; + b[1] = (sum >> 8) & 255; + b[2] = (sum >> 16) & 255; + b[3] = (sum >> 24) & 255; + put_ihex_data(0x14, 4, b); +} + + +static unsigned int sum(unsigned char *data, int num) +{ + unsigned int sum=0; + + while (num > 0) { + sum += *data++; + num--; + } + return sum; +} + + +static int num_lines(const char *buf) +{ + const char *p; + int count=0; + + p = buf; + while (p != NULL) { + p = strstr(p, "\r\n"); + if (p != NULL) { + count++; + p += 2; + } + } + return count; +} + +void trim_crlf(char *str) +{ + char *p; + p = strstr(str, "\r\n"); + if (p != NULL) *p = '\0'; +} + +void copy_boot_code_to_memory(struct chip_info_struct *chip) +{ + int i; + unsigned char c[4]; + + for (i=0; i < chip->bootprog[0]; i++) { + c[3] = (chip->bootprog[i+1] >> 24) & 255; + c[2] = (chip->bootprog[i+1] >> 16) & 255; + c[1] = (chip->bootprog[i+1] >> 8) & 255; + c[0] = (chip->bootprog[i+1]) & 255; + put_ihex_data(i * 4, 4, c); + } +} + + +#define NO_SYNC_ERR "\r\n\ +ERROR: Unable to sync to baud rate.\r\n\ +This probably means the LPC2xxx chip is not connected\r\n\ +or it is not being reset, or P0.14 is not low after\r\n\ +reset to cause it to enter the bootloader mode.\r\n\r\n\ +Please check the serial port connection, make sure\r\n\ +pin P0.14 is low (or tied to RTS via RS-232 level\r\n\ +translator), and the chip has been reset (or reset\r\n\ +is tied to DTR via RS-232 level translator).\r\n" + +#define UNKNOWN_CHIP_ERROR "\r\n\ +Unknown chip ID: \"%s\".\r\n\r\n\ +Perhaps you have a new Philips LPC chip which does not\r\n\ +have its ID string and sector map defined in this program?\r\n\ +Please contact paul@pjrc.com. Please include an exact copy\r\n\ +of this message and any info about the chip and other\r\n\ +hardware you may be using. Thanks :-)\r\n" + + +static void download_main(int event) +{ + char buf[4096]; + unsigned char bytes[256]; + double xtal; + int n; + static unsigned int cksum; + static int retry=0; + static int sector; // current sector we're doing + static int sector_offset; + static struct chip_info_struct *chip; // which chip + static int current_addr, num_to_xmit, linecount; + + + while (1) { + switch (state) { + case SYNC_1: + switch (event) { + case BEGIN: + printf("Attempting baud sync"); + retry = 0; + case RETRY: + printf("."); + fflush(stdout); + xmit_cmd("?", 2); + return; + case RESPONSE: + if (strcmp(parsed_response_buf, "Synchronized\r\n") == 0) { + //printf("response: sync'd\n"); + state = SYNC_2; + event = BEGIN; + break; + } + if (strcmp(parsed_response_buf, "?") == 0) { + //printf("response: echo only\n"); + retry++; + if (retry > 150) { + download_cancel(NO_SYNC_ERR); return; + } + event = RETRY; + usleep(30000); + break; + } + snprintf(buf, sizeof(buf), "Unexpected response to sync, \"%s\"", + parsed_response_buf); + download_cancel(buf); return; + case TIMEOUT: + if (retry < 100) { + retry++; + event = RETRY; + break; + } + download_cancel(NO_SYNC_ERR); + return; + } + break; + + + case SYNC_2: + switch(event) { + case BEGIN: + xmit_cmd("Synchronized\r\n", 3); + return; + case RESPONSE: + if (num_lines(parsed_response_buf) != 1) return; + if (strcmp(parsed_response_buf, "OK\r\n") == 0) { + state = SYNC_3; + event = BEGIN; + break; + } else { + snprintf(buf, sizeof(buf), "Unable to complete baud sync, %s", + parsed_response_buf); + download_cancel(buf); return; + } + return; + case TIMEOUT: + download_cancel("No response to complete baud sync"); return; + } + break; + + + case SYNC_3: + switch(event) { + case BEGIN: + if (sscanf(crystal, "%lf", &xtal) != 1) { + printf("\r\n"); + download_cancel("Crystal frequency is required for 3rd step of baud rate sync"); + return; + } + if (xtal < 10.0 || xtal > 25.0) { + printf("\r\n"); + printf("Warning: crystal frequency out of range (10.0 to 25.0), continuing anyway! (hope you know what you're doing)\r\n"); + } + snprintf(buf, sizeof(buf), "%d\r\n", (int)(xtal * 1000.0 + 0.5)); + xmit_cmd(buf, 3); + return; + case RESPONSE: + if (num_lines(parsed_response_buf) != 1) return; + if (strcmp(parsed_response_buf, "OK\r\n") == 0) { + printf("Baud sync sucessful\r\n"); + state = CHIP_ID; + event = BEGIN; + break; + } else { + snprintf(buf, sizeof(buf), "wrong response to crystal: %s", + parsed_response_buf); + download_cancel(buf); return; + } + return; + case TIMEOUT: + download_cancel("No response to crystal speed"); return; + } + break; + + + case CHIP_ID: + switch(event) { + case BEGIN: + xmit_cmd("J\r\n", 3); + return; + case RESPONSE: + if (num_lines(parsed_response_buf) < 2) return; + if (strncmp(parsed_response_buf, "0\r\n", 3) == 0) { + trim_crlf(parsed_response_buf+3); + for (chip=chip_info; chip->part_number != NULL; chip++) { + if (strcmp(parsed_response_buf+3, chip->id_string) == 0) + break; + } + if (chip->part_number == NULL) { + snprintf(buf, sizeof(buf), UNKNOWN_CHIP_ERROR, + parsed_response_buf+3); + download_cancel(buf); + break; + } + printf("Found chip: \"%s\"\r\n", chip->part_number); + //download_cancel("stop here, remove this later"); + state = UNLOCK; + event = BEGIN; + break; + } else { + snprintf(buf, sizeof(buf), "wrong response to ID: %s", + parsed_response_buf); + download_cancel(buf); return; + } + return; + case TIMEOUT: + download_cancel("No response to unlock command"); return; + } + break; + + + case UNLOCK: + switch(event) { + case BEGIN: + xmit_cmd("U 23130\r\n", 3); + return; + case RESPONSE: + if (num_lines(parsed_response_buf) != 1) return; + if (strcmp(parsed_response_buf, "0\r\n") == 0) { + printf("Device Unlocked\r\n"); + if (reboot_only) { + state = BOOT_SOFT; + } else { + state = BLANK_CHECK_SECTOR; + printf("Erasing....\r\n"); + sector = 0; + } + event = BEGIN; + break; + } else { + snprintf(buf, sizeof(buf), "wrong response unlock: %s", + parsed_response_buf); + download_cancel(buf); return; + } + return; + case TIMEOUT: + download_cancel("No response to unlock command"); return; + } + break; + + + case BLANK_CHECK_SECTOR: + switch(event) { + case BEGIN: + if (sector >= chip->num_sector) { + printf("Programming....\r\n"); + state = DOWNLOAD_CODE; + sector = sector_offset = 0; + event = BEGIN; + break; + } + printf(" Sector %2d: ", sector); + fflush(stdout); + if (!bytes_within_range(chip->layout[sector].address, + chip->layout[sector].address + chip->layout[sector].size - 1)) { + printf("not used\r\n"); + sector++; + break; + } + if (sector == 0) { + // can't blank check sector 0, so always erase it + state = ERASE_PREPARE; + break; + } + snprintf(buf, sizeof(buf), "I %d %d\r\n", sector, sector); + xmit_cmd(buf, 5); + return; + case RESPONSE: + if (num_lines(parsed_response_buf) == 1 && + strcmp(parsed_response_buf, "0\r\n") == 0) { + printf("already blank\r\n"); + sector++; + event = BEGIN; + break; + } else { + if (num_lines(parsed_response_buf) < 3) return; + state = ERASE_PREPARE; + event = BEGIN; + break; + } + case TIMEOUT: + download_cancel("No response to blank check"); return; + } + break; + + + + case ERASE_PREPARE: + switch(event) { + case BEGIN: + printf("prep, "); + fflush(stdout); + snprintf(buf, sizeof(buf), "P %d %d\r\n", sector, sector); + xmit_cmd(buf, 8); + return; + case RESPONSE: + if (num_lines(parsed_response_buf) != 1) return; + if (strcmp(parsed_response_buf, "0\r\n") == 0) { + state = ERASE_SECTOR; + event = BEGIN; + break; + } else { + download_cancel("Unable to prep for write"); return; + } + case TIMEOUT: + download_cancel("No response"); return; + } + break; + + + + case ERASE_SECTOR: + switch(event) { + case BEGIN: + printf("erase... "); + fflush(stdout); + snprintf(buf, sizeof(buf), "E %d %d\r\n", sector, sector); + xmit_cmd(buf, 25); + return; + case RESPONSE: + if (num_lines(parsed_response_buf) < 1) return; + if (strcmp(parsed_response_buf, "0\r\n") == 0) { + printf("Ok\r\n"); + sector++; + state = BLANK_CHECK_SECTOR; + event = BEGIN; + break; + } else { + printf("Error\r\n"); + download_cancel("Unable to erase flash"); return; + } + case TIMEOUT: + download_cancel("No response"); return; + } + break; + + + + case DOWNLOAD_CODE: + switch(event) { + case BEGIN: + if (sector >= chip->num_sector) { + state = BOOT_HARD; + sector = 0; + event = BEGIN; + break; + } + printf(" Sector %2d (0x%08X-0x%08X): ", sector, + chip->layout[sector].address + sector_offset, + chip->layout[sector].address + sector_offset + chip->chunk_size - 1); + fflush(stdout); + if (!bytes_within_range(chip->layout[sector].address + sector_offset, + chip->layout[sector].address + sector_offset + chip->chunk_size - 1)) { + printf("not used\r\n"); + sector_offset += chip->chunk_size; + if (sector_offset >= chip->layout[sector].size) { + sector_offset = 0; + sector++; + } + break; + } + snprintf(buf, sizeof(buf), "W %d %d\r\n", chip->ram_addr, chip->chunk_size); + xmit_cmd(buf, 4); + return; + case RESPONSE: + if (num_lines(parsed_response_buf) != 1) return; + if (strcmp(parsed_response_buf, "0\r\n") == 0) { + state = XMIT_DATA; + printf("xmit"); + current_addr = chip->layout[sector].address + sector_offset; + num_to_xmit = chip->chunk_size; + linecount = 0; + cksum = 0; + event = BEGIN; + break; + } else { + download_cancel("can't xmit to ram"); return; + } + case TIMEOUT: + download_cancel("No response"); return; + } + break; + + + case XMIT_DATA: + switch(event) { + case BEGIN: + n = num_to_xmit; + if (n > 45) n = 45; + get_ihex_data(current_addr, n, bytes); + cksum += sum(bytes, n); + uuencode(buf, bytes, n); + current_addr += n; + num_to_xmit -= n; + linecount++; + xmit_cmd(buf, 5); + write_serial_port("\r\n", 2); + return; + case RESPONSE: + if (num_lines(parsed_response_buf) != 1) return; + if (strcmp(parsed_response_buf, "\r\n") == 0) { + if (linecount >= 20 || num_to_xmit <= 0) { + state = XMIT_CKSUM; + } + event = BEGIN; + break; + } else { + download_cancel("data xmit did not echo"); return; + } + case TIMEOUT: + download_cancel("No response"); return; + } + break; + + + case XMIT_CKSUM: + switch(event) { + case BEGIN: + snprintf(buf, sizeof(buf), "%d\r\n", cksum); + xmit_cmd(buf, 3); + return; + case RESPONSE: + if (num_lines(parsed_response_buf) != 1) return; + if (strcmp(parsed_response_buf, "OK\r\n") == 0) { + if (num_to_xmit > 0) { + printf("."); + fflush(stdout); + state = XMIT_DATA; + event = BEGIN; + linecount = 0; + cksum = 0; + break; + } + state = WRITE_PREPARE; + event = BEGIN; + break; + } else { + download_cancel("bad checksum"); return; + } + case TIMEOUT: + download_cancel("No response"); return; + } + break; + + + case WRITE_PREPARE: + switch(event) { + case BEGIN: + printf("prep, "); + fflush(stdout); + snprintf(buf, sizeof(buf), "P %d %d\r\n", sector, sector); + xmit_cmd(buf, 5); + return; + case RESPONSE: + if (num_lines(parsed_response_buf) != 1) return; + if (strcmp(parsed_response_buf, "0\r\n") == 0) { + state = WRITE_SECTOR; + event = BEGIN; + break; + } else { + download_cancel("Unable to prep for write"); return; + } + case TIMEOUT: + download_cancel("No response"); return; + } + break; + + + case WRITE_SECTOR: + switch(event) { + case BEGIN: + printf("write, "); + fflush(stdout); + snprintf(buf, sizeof(buf), "C %d %d %d\r\n", + chip->layout[sector].address + sector_offset, + chip->ram_addr, chip->chunk_size); + xmit_cmd(buf, 5); + return; + case RESPONSE: + if (num_lines(parsed_response_buf) != 1) return; + if (strcmp(parsed_response_buf, "0\r\n") == 0) { + printf("Ok\r\n"); + sector_offset += chip->chunk_size; + if (sector_offset >= chip->layout[sector].size) { + sector_offset = 0; + sector++; + } + state = DOWNLOAD_CODE; + event = BEGIN; + } else { + download_cancel("Unable to prep for write"); return; + } + break; + case TIMEOUT: + download_cancel("No response"); return; + } + break; + + + case BOOT_HARD: + // if (chip->bootprog) { + // state = BOOT_SOFT; + // break; + // } else { + printf("Booting (hardware reset)...\r\n\r\n"); + hard_reset_to_user_code(); + done_program(0); + return; + // } + + case BOOT_SOFT: + switch(event) { + case BEGIN: + printf("Booting (soft jump)...\r\n"); + printf("loading jump code\r\n"); + // would be nice if we could simply jump to the user's code, but + // Philips didn't think of that. The interrupt vector table stays + // mapped to the bootloader, so jumping to zero only runs the + // bootloader again. Intead, we need to download a tiny ARM + // program that reconfigures the hardware and then jumps to zero. + //snprintf(buf, sizeof(buf), "G %d A\r\n", 0); + snprintf(buf, sizeof(buf), "W %d %d\r\n", chip->ram_addr, chip->bootprog[0] * 4); + xmit_cmd(buf, 4); + return; + case RESPONSE: + if (num_lines(parsed_response_buf) < 1) return; + if (strcmp(parsed_response_buf, "0\r\n") == 0) { + current_addr = 0; + num_to_xmit = chip->bootprog[0] * 4; + copy_boot_code_to_memory(chip); + linecount = 0; + cksum = 0; + state = BOOT_XMIT_DATA; + event = BEGIN; + } else { + download_cancel("can't xmit to ram"); return; + } + break; + case TIMEOUT: + download_cancel("No response"); return; + } + break; + + + case BOOT_XMIT_DATA: + switch(event) { + case BEGIN: + n = num_to_xmit; + if (n > 45) n = 45; + get_ihex_data(current_addr, n, bytes); + cksum += sum(bytes, n); + uuencode(buf, bytes, n); + current_addr += n; + num_to_xmit -= n; + linecount++; + //printf("send: %s\r\n", buf); + xmit_cmd(buf, 5); + write_serial_port("\r\n", 2); + return; + case RESPONSE: + if (num_lines(parsed_response_buf) != 1) return; + if (strcmp(parsed_response_buf, "\r\n") == 0) { + if (linecount >= 20 || num_to_xmit <= 0) { + state = BOOT_XMIT_CKSUM; + } + event = BEGIN; + break; + } else { + download_cancel("data xmit did not echo"); return; + } + case TIMEOUT: + download_cancel("No response"); return; + } + break; + + + case BOOT_XMIT_CKSUM: + switch(event) { + case BEGIN: + snprintf(buf, sizeof(buf), "%d\r\n", cksum); + //printf("send: %s", buf); + xmit_cmd(buf, 3); + return; + case RESPONSE: + if (num_lines(parsed_response_buf) != 1) return; + if (strcmp(parsed_response_buf, "OK\r\n") == 0) { + if (num_to_xmit > 0) { + printf("."); + fflush(stdout); + state = BOOT_XMIT_DATA; + event = BEGIN; + linecount = 0; + cksum = 0; + break; + } + state = BOOT_RUN_CODE; + event = BEGIN; + break; + } else { + download_cancel("bad checksum"); return; + } + case TIMEOUT: + download_cancel("No response"); return; + } + break; + + + case BOOT_RUN_CODE: + switch(event) { + case BEGIN: + printf("jumping now!\r\n"); + snprintf(buf, sizeof(buf), "G %d A\r\n", chip->ram_addr); + xmit_cmd(buf, 4); + return; + case RESPONSE: + if (num_lines(parsed_response_buf) < 1) return; + if (strcmp(parsed_response_buf, "0\r\n") == 0) { + done_program(0); + return; + } else { + printf("response = %s", parsed_response_buf); + download_cancel("couldn't run program"); return; + } + break; + case TIMEOUT: + done_program(0); + return; + // Philips user name says it responds, but it does not. + // It seems to just immediately jump to the code without + // any "0" response. + //download_cancel("No response"); return; + } + break; + + + + default: + snprintf(buf, sizeof(buf), "unknown state %d\r\n", state); + download_cancel(buf); + return; + } + } +} + + +void download_cancel(const char *mesg) +{ + printf("\r\nDownload Canceled"); + if (mesg && *mesg) printf(": %s", mesg); + printf("\r\n"); + // need to do some cleanup for various states??? + done_program(1); +} + + +/****************************************************************/ +/* */ +/* Transmit Commands to Bootloader */ +/* */ +/****************************************************************/ + + + +static void xmit_cmd(const char *cmd, int max_time) +{ + int len; + + if (cmd == NULL || *cmd == '\0') return; + len = strlen(cmd); + +#ifdef PRINT_TX_RX_BYTES + printf("tx %d bytes: %s\n", len, cmd); +#endif + + input_flush_serial_port(); + + write_serial_port(cmd, len); + + snprintf(expected_echo_buf, sizeof(expected_echo_buf), "%s", cmd); + if (state == SYNC_1) { + // special case, baud sync doesn't echo + expected_echo_buf[0] = '\0'; + } + expected_echo_ptr = expected_echo_buf; + parsed_response_ptr = parsed_response_buf; + + response_timer = max_time; +} + + + +/****************************************************************/ +/* */ +/* Handlers that respond to input */ +/* */ +/****************************************************************/ + + +/* +Whenever the main gtk event loop detects more input has arrived from the +serial port, and we're in the process of a download, it calls here to +hand off the data. We're supposed to match it up to the echo buffer, +and then store it into the parsed response buffer and if it looks like +this might be a complete response, call download_main with a response +event. +*/ +void download_rx_port(const unsigned char *buf, int num) +{ + int i=0; + + if (num <= 0) return; + + // echo the data + //write(term_fd, buf, num); + +#ifdef PRINT_TX_RX_BYTES + printf("rx %d bytes:", num); + for (i=0; i "); +#endif + // ignore incorrect echo (will timeout) + expected_echo_ptr = NULL; + return; + } + expected_echo_ptr++; + continue; + } + // store this into a parsed response buffer + *parsed_response_ptr++ = buf[i]; + } + + // if the last two characters of the response are "\r\n", + // then it's likely we've got a complete response. + *parsed_response_ptr = '\0'; + if (parsed_response_ptr > parsed_response_buf + 1 + && *(parsed_response_ptr - 2) == '\r' + && *(parsed_response_ptr - 1) == '\n') { + //response_timer = 0; + download_main(RESPONSE); + } +} + + + +/* +During a download, this is supposed to get called at 100 Hz. Whenever +something is transmitted and we expect a response, the response_timer +is initialized to the maximum time we will wait. +*/ +void download_timer(void) +{ + if (response_timer > 0) { + response_timer--; + if (response_timer == 0) { + expected_echo_ptr = NULL; + download_main(TIMEOUT); + } + } +} + +/* +During a download, all input the user types into the terminal is sent +to this function, instead of passing it to xterm for display +*/ +void download_rx_term(const unsigned char *buf, int num) +{ + // discard anything the user types into the terminal + // while we are in the middle of downloading. Maybe + // we should look for CTRL-C and abort?? +} + + diff --git a/board/msba2/tools/src/download.h b/board/msba2/tools/src/download.h new file mode 100644 index 0000000000..4d57bfa5d0 --- /dev/null +++ b/board/msba2/tools/src/download.h @@ -0,0 +1,8 @@ +extern int download_begin(char* file); +extern void soft_reboot_begin(void); +extern void hard_reset_to_bootloader(void); +extern void hard_reset_to_user_code(void); +extern void download_cancel(const char *mesg); +extern void download_rx_term(const unsigned char *buf, int num); +extern void download_rx_port(const unsigned char *buf, int num); +extern void download_timer(void); diff --git a/board/msba2/tools/src/gui.c b/board/msba2/tools/src/gui.c new file mode 100644 index 0000000000..ce6d13c96e --- /dev/null +++ b/board/msba2/tools/src/gui.c @@ -0,0 +1,387 @@ +/* + * LPC 2000 Loader, http://www.pjrc.com/arm/lpc2k_pgm + * Copyright (c) 2004, PJRC.COM, LLC, + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +/* If this code fails to build, please provide at least the following + * information when requesting (free) technical support. + * + * 1: Complete copy of all messages during the build. + * 2: Output of "gtk-config --version" + * 3: Output of "gtk-config --libs" + * 4: Output of "gtk-config --cflags" + * 5: Output of "uname -a" + * 6: Version of GTK installed... eg, type: ls -l /lib/libgtk* + * 7: Other info... which linux distribution, version, other software + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "gui.h" +#include "settings.h" +#include "serial.h" +#include "lpc2k_pgm.h" +#include "download.h" + + +static GtkWidget *firmware_label, *firmware_entry, *program_button; +static GtkWidget *port_label, *port_entry, *baud_label, *baud_combo; +static GtkWidget *crystal_label, *crystal_entry, *mhz_label; +static GtkWidget *reboot_button, *bootloader_button, *quit_button; +static GtkWidget *line1_hbox, *line2_hbox, *line3_hbox, *line4_hbox; +static GtkWidget *main_vbox, *main_window; + +static int port_timeout=0; +static int baud_timeout=0; +static int download_in_progress=0; + +gint do_quit(GtkWidget *widget, gpointer *data) +{ + gtk_main_quit(); + return FALSE; +} + +gint do_program(GtkWidget *widget, gpointer *data) +{ + if (download_in_progress) { + // error... not supposed to get here + gtk_widget_set_sensitive(program_button, FALSE); + return FALSE; + } + download_in_progress = 1; + gtk_widget_set_sensitive(program_button, FALSE); + gtk_widget_set_sensitive(reboot_button, FALSE); + gtk_widget_set_sensitive(bootloader_button, TRUE); + download_begin(); + return FALSE; +} + +int file_exists(const char *filename) +{ + struct stat file_stats; + int r; + + r = stat(filename, &file_stats); + if (r != 0) return 0; + if (!S_ISREG(file_stats.st_mode)) return 0; + return 1; +} + +void done_program(int still_in_bootloader) +{ + download_in_progress = 0; + + if (file_exists(gtk_entry_get_text(GTK_ENTRY(firmware_entry)))) { + gtk_widget_set_sensitive(program_button, TRUE); + } else { + gtk_widget_set_sensitive(program_button, FALSE); + } + gtk_widget_set_sensitive(bootloader_button, TRUE); + gtk_widget_set_sensitive(reboot_button, TRUE); +} + +gint do_reboot(GtkWidget *widget, gpointer *data) +{ + if (download_in_progress) { + download_cancel(NULL); + gtk_widget_set_sensitive(program_button, FALSE); + gtk_widget_set_sensitive(reboot_button, FALSE); + gtk_widget_set_sensitive(bootloader_button, FALSE); + } + gtk_widget_set_sensitive(program_button, FALSE); + gtk_widget_set_sensitive(reboot_button, FALSE); + gtk_widget_set_sensitive(bootloader_button, FALSE); + + hard_reset_to_user_code(); + +#if 0 + download_in_progress = 1; + soft_reboot_begin(); +#endif + if (file_exists(gtk_entry_get_text(GTK_ENTRY(firmware_entry)))) { + gtk_widget_set_sensitive(program_button, TRUE); + } else { + gtk_widget_set_sensitive(program_button, FALSE); + } + gtk_widget_set_sensitive(bootloader_button, TRUE); + return FALSE; +} + +gint do_bootloader(GtkWidget *widget, gpointer *data) +{ + if (download_in_progress) { + download_cancel(NULL); + gtk_widget_set_sensitive(program_button, FALSE); + gtk_widget_set_sensitive(reboot_button, FALSE); + gtk_widget_set_sensitive(bootloader_button, FALSE); + } + + hard_reset_to_bootloader(); + + if (file_exists(gtk_entry_get_text(GTK_ENTRY(firmware_entry)))) { + gtk_widget_set_sensitive(program_button, TRUE); + } else { + gtk_widget_set_sensitive(program_button, FALSE); + } + gtk_widget_set_sensitive(reboot_button, TRUE); + gtk_widget_set_sensitive(bootloader_button, TRUE); + return FALSE; +} + +gint do_new_port(GtkWidget *widget, gpointer *data) +{ + port_timeout = 12; + return FALSE; +} + +gint do_new_baud(GtkWidget *widget, gpointer *data) +{ + baud_timeout = 7; + return FALSE; +} + +gint do_new_file(GtkWidget *widget, gpointer *data) +{ + const char *filename; + + filename = gtk_entry_get_text(GTK_ENTRY(firmware_entry)); + if (file_exists(filename)) { + new_file_setting(filename); + if (download_in_progress) { + gtk_widget_set_sensitive(program_button, FALSE); + } else { + gtk_widget_set_sensitive(program_button, TRUE); + } + } else { + gtk_widget_set_sensitive(program_button, FALSE); + } + return FALSE; +} + +gint do_new_crystal(GtkWidget *widget, gpointer *data) +{ + const char *xtal; + + xtal = gtk_entry_get_text(GTK_ENTRY(crystal_entry)); + new_crystal_setting(xtal); + return FALSE; +} + + +gint do_timer(gpointer data) +{ + if (port_timeout && --port_timeout == 0) { + open_serial_port(gtk_entry_get_text(GTK_ENTRY(port_entry))); + } + if (baud_timeout && --baud_timeout == 0) { + change_baud(gtk_entry_get_text(GTK_ENTRY( + GTK_COMBO(baud_combo)->entry))); + } + if (download_in_progress) { + download_timer(); + } + return TRUE; +} + +void do_term_input(gpointer data, int fd, GdkInputCondition cond) +{ + char buf[256]; + int num, flags; + + flags = fcntl(term_fd, F_GETFL); + fcntl(term_fd, F_SETFL, flags | O_NONBLOCK); + num = read(term_fd, buf, sizeof(buf)); + fcntl(term_fd, F_SETFL, flags); + if (num > 0) { + if (download_in_progress) { + download_rx_term(buf, num); + } else { + write_serial_port(buf, num); + } + } +} + +void do_port_input(gpointer data, int fd, GdkInputCondition cond) +{ + char buf[256]; + int num; + + num = read_serial_port_nb((unsigned char *)buf, sizeof(buf)); + if (num > 0) { + if (download_in_progress) { + download_rx_port(buf, num); + } else { + write(term_fd, buf, num); + } + } +} + + +void run_gui(void) +{ + gtk_signal_connect(GTK_OBJECT(main_window), "delete_event", + GTK_SIGNAL_FUNC(do_quit), NULL); + gtk_signal_connect(GTK_OBJECT(quit_button), "pressed", + GTK_SIGNAL_FUNC(do_quit), NULL); + gtk_signal_connect(GTK_OBJECT(port_entry), "changed", + GTK_SIGNAL_FUNC(do_new_port), NULL); + gtk_signal_connect(GTK_OBJECT(GTK_COMBO(baud_combo)->entry), "changed", + GTK_SIGNAL_FUNC(do_new_baud), NULL); + gtk_signal_connect(GTK_OBJECT(firmware_entry), "changed", + GTK_SIGNAL_FUNC(do_new_file), NULL); + gtk_signal_connect(GTK_OBJECT(crystal_entry), "changed", + GTK_SIGNAL_FUNC(do_new_crystal), NULL); + gtk_signal_connect(GTK_OBJECT(program_button), "pressed", + GTK_SIGNAL_FUNC(do_program), NULL); + gtk_signal_connect(GTK_OBJECT(reboot_button), "pressed", + GTK_SIGNAL_FUNC(do_reboot), NULL); + gtk_signal_connect(GTK_OBJECT(bootloader_button), "pressed", + GTK_SIGNAL_FUNC(do_bootloader), NULL); + + gtk_timeout_add(100, do_timer, NULL); + gdk_input_add(term_fd, GDK_INPUT_READ, do_term_input, NULL); + gdk_input_add(serial_port_fd(), GDK_INPUT_READ, do_port_input, NULL); + + gtk_main(); +} + + +void create_window(int *argc, char ***argv) +{ + GList *gtk_baud_list=NULL; + int i; + + gtk_init(argc, argv); + + firmware_label = gtk_label_new("Firmware:"); + gtk_label_set_justify(GTK_LABEL(firmware_label), GTK_JUSTIFY_RIGHT); + gtk_widget_show(firmware_label); + + firmware_entry = gtk_entry_new(); + gtk_widget_set_usize(firmware_entry, 110, 0); + gtk_entry_set_text(GTK_ENTRY(firmware_entry), file_setting()); + gtk_widget_show(firmware_entry); + + program_button = gtk_button_new_with_label("Program Now"); + if (file_exists(file_setting())) { + gtk_widget_set_sensitive(program_button, TRUE); + } else { + gtk_widget_set_sensitive(program_button, FALSE); + } + gtk_widget_show(program_button); + + line1_hbox = gtk_hbox_new(FALSE, 2); + gtk_box_pack_start(GTK_BOX(line1_hbox), firmware_label, FALSE, FALSE, 2); + gtk_box_pack_start(GTK_BOX(line1_hbox), firmware_entry, TRUE, TRUE, 2); + gtk_box_pack_start(GTK_BOX(line1_hbox), program_button, FALSE, FALSE, 2); + gtk_widget_show(line1_hbox); + + + port_label = gtk_label_new("Port:"); + gtk_label_set_justify(GTK_LABEL(port_label), GTK_JUSTIFY_RIGHT); + gtk_widget_show(port_label); + + port_entry = gtk_entry_new(); + gtk_widget_set_usize(port_entry, 80, 0); + gtk_entry_set_text(GTK_ENTRY(port_entry), port_setting()); + open_serial_port(port_setting()); + gtk_widget_show(port_entry); + + baud_label = gtk_label_new("Baud:"); + gtk_label_set_justify(GTK_LABEL(baud_label), GTK_JUSTIFY_RIGHT); + gtk_widget_show(baud_label); + + baud_combo = gtk_combo_new(); + for (i=0; baud_list[i] != NULL; i++) { + gtk_baud_list = g_list_append(gtk_baud_list, baud_list[i]); + } + gtk_combo_set_popdown_strings(GTK_COMBO(baud_combo), gtk_baud_list); + gtk_entry_set_editable(GTK_ENTRY(GTK_COMBO(baud_combo)->entry), FALSE); + gtk_widget_set_usize(baud_combo, 75, 0); + for (i=0; baud_list[i] != NULL; i++) { + if (strcmp(baud_list[i], baud_setting()) == 0) { + gtk_list_select_item(GTK_LIST(GTK_COMBO(baud_combo)->list), i); + break; + } + } + gtk_widget_show(baud_combo); + + line2_hbox = gtk_hbox_new(FALSE, 2); + gtk_box_pack_start(GTK_BOX(line2_hbox), port_label, FALSE, FALSE, 2); + gtk_box_pack_start(GTK_BOX(line2_hbox), port_entry, TRUE, TRUE, 2); + gtk_box_pack_start(GTK_BOX(line2_hbox), baud_label, FALSE, FALSE, 2); + gtk_box_pack_start(GTK_BOX(line2_hbox), baud_combo, FALSE, FALSE, 2); + gtk_widget_show(line2_hbox); + + + crystal_label = gtk_label_new("Crystal:"); + gtk_label_set_justify(GTK_LABEL(crystal_label), GTK_JUSTIFY_RIGHT); + gtk_widget_show(crystal_label); + + crystal_entry = gtk_entry_new(); + gtk_widget_set_usize(crystal_entry, 80, 0); + gtk_entry_set_text(GTK_ENTRY(crystal_entry), crystal_setting()); + gtk_widget_show(crystal_entry); + + mhz_label = gtk_label_new("(MHz)"); + gtk_label_set_justify(GTK_LABEL(mhz_label), GTK_JUSTIFY_LEFT); + gtk_widget_show(mhz_label); + + line3_hbox = gtk_hbox_new(FALSE, 2); + gtk_box_pack_start(GTK_BOX(line3_hbox), crystal_label, FALSE, FALSE, 2); + gtk_box_pack_start(GTK_BOX(line3_hbox), crystal_entry, TRUE, TRUE, 2); + gtk_box_pack_start(GTK_BOX(line3_hbox), mhz_label, FALSE, FALSE, 2); + gtk_widget_show(line3_hbox); + + + reboot_button = gtk_button_new_with_label("Reboot"); + gtk_widget_set_sensitive(reboot_button, TRUE); + gtk_widget_show(reboot_button); + + bootloader_button = gtk_button_new_with_label("Booloader"); + gtk_widget_show(bootloader_button); + + quit_button = gtk_button_new_with_label("Quit"); + gtk_widget_show(quit_button); + + line4_hbox = gtk_hbox_new(TRUE, 2); + gtk_box_pack_start(GTK_BOX(line4_hbox), reboot_button, TRUE, TRUE, 2); + gtk_box_pack_start(GTK_BOX(line4_hbox), bootloader_button, TRUE, TRUE, 2); + gtk_box_pack_start(GTK_BOX(line4_hbox), quit_button, TRUE, TRUE, 2); + gtk_widget_show(line4_hbox); + + main_vbox = gtk_vbox_new(FALSE, 2); + gtk_box_pack_start(GTK_BOX(main_vbox), line1_hbox, TRUE, TRUE, 2); + gtk_box_pack_start(GTK_BOX(main_vbox), line2_hbox, TRUE, TRUE, 2); + gtk_box_pack_start(GTK_BOX(main_vbox), line3_hbox, TRUE, TRUE, 2); + gtk_box_pack_start(GTK_BOX(main_vbox), line4_hbox, TRUE, TRUE, 2); + gtk_widget_show(main_vbox); + + main_window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_container_add(GTK_CONTAINER(main_window), main_vbox); + gtk_widget_show(main_window); +} diff --git a/board/msba2/tools/src/gui.h b/board/msba2/tools/src/gui.h new file mode 100644 index 0000000000..fadde6db6d --- /dev/null +++ b/board/msba2/tools/src/gui.h @@ -0,0 +1,3 @@ +extern void create_window(int *argc, char ***argv); +extern void run_gui(void); +extern void done_program(int still_in_bootloader); diff --git a/board/msba2/tools/src/ihex.c b/board/msba2/tools/src/ihex.c new file mode 100644 index 0000000000..cda37af66c --- /dev/null +++ b/board/msba2/tools/src/ihex.c @@ -0,0 +1,229 @@ +/* + * LPC 2000 Loader, http://www.pjrc.com/arm/lpc2k_pgm + * Copyright (c) 2004, PJRC.COM, LLC, + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +/* If this code fails to build, please provide at least the following + * information when requesting (free) technical support. + * + * 1: Complete copy of all messages during the build. + * 2: Output of "gtk-config --version" + * 3: Output of "gtk-config --libs" + * 4: Output of "gtk-config --cflags" + * 5: Output of "uname -a" + * 6: Version of GTK installed... eg, type: ls -l /lib/libgtk* + * 7: Other info... which linux distribution, version, other software + */ + +#include +#include + + +// the maximum flash image size we can support +// chips with larger memory may be used, but only this +// much intel-hex data can be loaded into memory! +#define MAX_MEMORY_SIZE 0x80000 + + +#include "ihex.h" + + +static unsigned char firmware_image[MAX_MEMORY_SIZE]; +static unsigned char firmware_mask[MAX_MEMORY_SIZE]; +static int end_record_seen=0; +static int byte_count; +static unsigned int extended_addr = 0; + + +static int parse_hex_line(char *line); + + +/****************************************************************/ +/* */ +/* Read Intel Hex File */ +/* */ +/****************************************************************/ + + + +int read_intel_hex(const char *filename) +{ + FILE *fp; + int i, lineno=0; + char buf[1024]; + + byte_count = 0; + end_record_seen = 0; + for (i=0; i= MAX_MEMORY_SIZE) return 0; + ptr += 2; + sum = (len & 255) + ((addr >> 8) & 255) + (addr & 255) + (code & 255); + if (code != 0) { + if (code == 1) { + end_record_seen = 1; + return 1; + } + if (code == 2 && len == 2) { + if (!sscanf(ptr, "%04x", &i)) return 1; + ptr += 4; + sum += ((i >> 8) & 255) + (i & 255); + if (!sscanf(ptr, "%02x", &cksum)) return 1; + if (((sum & 255) + (cksum & 255)) & 255) return 1; + extended_addr = i << 4; + //printf("ext addr = %05X\n", extended_addr); + } + if (code == 4 && len == 2) { + if (!sscanf(ptr, "%04x", &i)) return 1; + ptr += 4; + sum += ((i >> 8) & 255) + (i & 255); + if (!sscanf(ptr, "%02x", &cksum)) return 1; + if (((sum & 255) + (cksum & 255)) & 255) return 1; + extended_addr = i << 16; + //printf("ext addr = %08X\n", extended_addr); + } + return 1; // non-data line + } + byte_count += len; + while (num != len) { + if (sscanf(ptr, "%02x", &i) != 1) return 0; + i &= 255; + firmware_image[addr + extended_addr + num] = i; + firmware_mask[addr + extended_addr + num] = 1; + ptr += 2; + sum += i; + (num)++; + if (num >= 256) return 0; + } + if (!sscanf(ptr, "%02x", &cksum)) return 0; + if (((sum & 255) + (cksum & 255)) & 255) return 0; /* checksum error */ + return 1; +} + + +int bytes_within_range(int begin, int end) +{ + int i; + + if (begin < 0 || begin >= MAX_MEMORY_SIZE || + end < 0 || end >= MAX_MEMORY_SIZE) { + return 0; + } + for (i=begin; i<=end; i++) { + if (firmware_mask[i]) return 1; + } + return 0; +} + +void get_ihex_data(int addr, int len, unsigned char *bytes) +{ + int i; + + if (addr < 0 || len < 0 || addr + len >= MAX_MEMORY_SIZE) { + for (i=0; i= MAX_MEMORY_SIZE) { + return; + } + for (i=0; i + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +/* If this code fails to build, please provide at least the following + * information when requesting (free) technical support. + * + * 1: Complete copy of all messages during the build. + * 2: Output of "gtk-config --version" + * 3: Output of "gtk-config --libs" + * 4: Output of "gtk-config --cflags" + * 5: Output of "uname -a" + * 6: Version of GTK installed... eg, type: ls -l /lib/libgtk* + * 7: Other info... which linux distribution, version, other software + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "lpc2k_pgm.h" +#include "serial.h" +#include "download.h" + +int programming_done = 0; + +int done_program(int i) { + printf("Programming done.\n"); + programming_done = 1; + return 0; +} + +void handle_port_input() { + unsigned char buf[256]; + int num; + + num = read_serial_port(buf, sizeof(buf)); + if (num > 0) { + download_rx_port(buf, num); + } +} + +void usage() { + printf("usage: lpc2k_pgm \n"); +} + +int main(int argc, char **argv) +{ + if (argc < 3 ) { + usage(); + exit(1); + } + + char* port_name = argv[1]; + char* file_name = argv[2]; + + sleep(1); + + if (open_serial_port(port_name) < 0) { + return(1); + } + + if (!download_begin(file_name)) { + return 1; + } + while (!programming_done) { + handle_port_input(); + } + + close_serial_port(); + + return 0; +} + diff --git a/board/msba2/tools/src/lpc2k_pgm.h b/board/msba2/tools/src/lpc2k_pgm.h new file mode 100644 index 0000000000..0a5f5a7eeb --- /dev/null +++ b/board/msba2/tools/src/lpc2k_pgm.h @@ -0,0 +1,12 @@ +#ifndef LPC2K_PGM +#define LPC2K_PGM + +/* gets a name like "115200", sets baudrate accordingly. */ +void change_baud(const char *baud_name); + +/* called before/after using serial device, used to have terminal + * close the device. +*/ +void signal_terminal(); + +#endif // LPC2K_PGM diff --git a/board/msba2/tools/src/pseudoterm.c b/board/msba2/tools/src/pseudoterm.c new file mode 100644 index 0000000000..ce8a446b32 --- /dev/null +++ b/board/msba2/tools/src/pseudoterm.c @@ -0,0 +1,135 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "serial.h" +#include "pthread.h" +#include "download.h" + +int tty_fd; +int stopped = 0; +char* port_name = "/dev/ttyUSB1"; +pthread_t serial_reader; + +void* serial_reader_func(void* arg) { + unsigned char buf[255]; + while(1) { + int n = read_serial_port(buf, sizeof(buf)); + if (n > 0) { + write(tty_fd, buf, n); + } + } +} + +int init() { + int result = open_serial_port(port_name); + pthread_create(&serial_reader, NULL, serial_reader_func, NULL); + hard_reset_to_user_code(); + return result; +} + +void sig_handler(int signal) { + if (signal == SIGUSR1) { + if (stopped) { + stopped = 0; + printf("\nSignal received, opening port.\r\n"); + if (init() < 0) { + printf("Cannot open port.\r\n"); + exit(1); + } + } + } else if (signal == SIGUSR2) { + if (!stopped) { + stopped = 1; + printf("\nSignal received, closing port. \r\n"); + pthread_cancel(serial_reader); + close_serial_port(); + } + } +} + +int open_tty(void) +{ + int r, fd; + struct termios term_setting; + + fd = open("/dev/tty", O_RDWR); + if (fd < 0) return -1; + r = tcgetattr(fd, &term_setting); + if (r != 0) return -2; + term_setting.c_oflag |= ( ONLRET ); + term_setting.c_iflag |= (IGNBRK | IGNPAR); + term_setting.c_iflag &= ~(ISTRIP | BRKINT); + term_setting.c_lflag &= ~(ICANON | ISIG | ECHO); + term_setting.c_cflag |= CREAD; + term_setting.c_cc[VMIN] = 1; + term_setting.c_cc[VTIME] = 1; + r = tcsetattr(fd, TCSANOW, &term_setting); + if (r != 0) return -3; + return fd; +} + +void install_sighandler() { + struct sigaction action; + sigemptyset (&action.sa_mask); + sigaddset( &action.sa_mask, SIGUSR1 ); + sigaddset( &action.sa_mask, SIGUSR2 ); + action.sa_flags = 0; + action.sa_handler = sig_handler; + sigaction(SIGUSR1, &action, NULL); + sigaction(SIGUSR2, &action, NULL); +} + +int main(int argc, char** argv) { + if (argc == 2) { + port_name = argv[1]; + } + + printf("Using %s as serial device.\n", port_name); + + char ttybuf[255]; + tty_fd = open_tty(); + if (tty_fd < 0) { + printf("Error opening terminal.\n"); + return(1); + } + + install_sighandler(); + + if (init() < 0) { + printf("Cannot open port.\r\n"); + exit(1); + } + + while (1) { + int n = read(tty_fd, ttybuf, sizeof(ttybuf)); + int i; + + /* check for 0x3 (ctrl-c), clean exit */ + for (i = 0; i < n; i++) { + if (ttybuf[i] == 0x3) { + if (i > 0) { + write_serial_port(ttybuf, i); + } + close_serial_port(); + system("tset -c"); + return 0; + } + + } + write_serial_port(ttybuf,n); + } + + close_serial_port(); + return 0; +} + + diff --git a/board/msba2/tools/src/serial.c b/board/msba2/tools/src/serial.c new file mode 100644 index 0000000000..cd51e1cc5c --- /dev/null +++ b/board/msba2/tools/src/serial.c @@ -0,0 +1,350 @@ +/* + * LPC 2000 Loader, http://www.pjrc.com/arm/lpc2k_pgm + * Copyright (c) 2004, PJRC.COM, LLC, + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +/* If this code fails to build, please provide at least the following + * information when requesting (free) technical support. + * + * 1: Complete copy of all messages during the build. + * 2: Output of "gtk-config --version" + * 3: Output of "gtk-config --libs" + * 4: Output of "gtk-config --cflags" + * 5: Output of "uname -a" + * 6: Version of GTK installed... eg, type: ls -l /lib/libgtk* + * 7: Other info... which linux distribution, version, other software + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef LINUX +#include +#endif + +#include "serial.h" + +static int port_fd=-1; + +static tcflag_t baud_name_to_flags(const char *baud_name); +static void report_open_error(const char *filename, int err); + +char* baud_rate = "115200"; + +int open_serial_port(const char *port_name) +{ + int r; + + if (port_fd >= 0) { + close(port_fd); + } + port_fd = open(port_name, O_RDWR); + if (port_fd < 0) { + report_open_error(port_name, errno); + return -1; + } + r = set_baud(baud_rate); + if (r == 0) { + printf("Port \"%s\" opened at %s baud\r\n", + port_name, baud_rate); + } else { + printf("Port \"%s\" opened, unable to set baud to %s\r\n", + port_name, baud_rate); + } + #ifdef LINUX + { + struct serial_struct kernel_serial_settings; + /* attempt to set low latency mode, but don't worry if we can't */ + r = ioctl(port_fd, TIOCGSERIAL, &kernel_serial_settings); + if (r < 0) return 0; + kernel_serial_settings.flags |= ASYNC_LOW_LATENCY; + ioctl(port_fd, TIOCSSERIAL, &kernel_serial_settings); + } + #endif + return 0; +} + + +/* if the port can't be opened, try to print as much info as + * possible, so the problem can be resolved (usually permissions) + */ +static void report_open_error(const char *filename, int err) +{ + struct stat info; + uid_t my_uid; + gid_t my_gid; + char my_uname[64], my_gname[64], file_uname[64], file_gname[64]; + struct passwd *p; + struct group *g; + mode_t perm; + int r, perm_ok=0; + + printf("\r\n"); + printf("Unable to open \"%s\"\r\n", filename); + if (err == EACCES) { + printf("You don't have permission to access %s\r\n", filename); + } + //printf("Attemping to find more information about %s....\r\n", filename); + r = stat(filename, &info); + if (r < 0) { + if (errno == ENOENT) { + printf("file %s does not exist\r\n", filename); + } else if (errno == ELOOP) { + printf("too many symbolic links\r\n"); + } else if (errno == EACCES) { + printf("permission denied to get file status\r\n"); + } else { + printf("Unable to get file status, err%d\r\n", errno); + } + return; + } + my_uid = getuid(); + my_gid = getgid(); + + p = getpwuid(my_uid); + if (p) { + snprintf(my_uname, sizeof(my_uname), + "\"%s\" (gid=%d)", p->pw_name, (int)my_uid); + } else { + snprintf(my_uname, sizeof(my_uname), + "(gid=%d)", (int)my_uid); + } + + p = getpwuid(info.st_uid); + if (p) { + snprintf(file_uname, sizeof(file_uname), + "\"%s\" (uid=%d)", p->pw_name, (int)info.st_uid); + } else { + snprintf(file_uname, sizeof(file_uname), + "(uid=%d)", (int)info.st_uid); + } + + g = getgrgid(my_gid); + if (g) { + snprintf(my_gname, sizeof(my_gname), + "\"%s\" (gid=%d)", g->gr_name, (int)my_gid); + } else { + snprintf(my_gname, sizeof(my_gname), + "(gid=%d)", (int)my_gid); + } + + g = getgrgid(info.st_gid); + if (g) { + snprintf(file_gname, sizeof(file_gname), + "\"%s\" (uid=%d)", g->gr_name, (int)info.st_gid); + } else { + snprintf(file_gname, sizeof(file_gname), + "(uid=%d)", (int)info.st_gid); + } + + /* printf("%s is owned by: user %s, group %s\r\n", + filename, file_uname, file_gname); */ + + perm = info.st_mode; + + if ((perm & S_IROTH) && (perm & S_IWOTH)) { + printf("%s has read/write permission for everybody\r\n", + filename); + } else { + printf("%s is not read/write for everybody, so\r\n", filename); + printf(" you must match either user or group permission\r\n"); + if ((perm & S_IRUSR) && (perm & S_IWUSR)) { + printf("%s has read/write permission for user %s\r\n", + filename, file_uname); + perm_ok = 1; + } + if ((perm & S_IRGRP) && (perm & S_IWGRP)) { + printf("%s has read/write permission for group %s\r\n", + filename, file_gname); + perm_ok = 1; + } + if (perm_ok == 0) { + printf("%s does not read/write permission for user or group!\r\n", + filename); + } else { + printf("Your access privs: user %s, group %s\r\n", + my_uname, my_gname); + } + } + printf("\r\n"); +} + + + +int write_serial_port(const void *buf, int num) +{ + return(write(port_fd, buf, num)); +} + + +void input_flush_serial_port(void) +{ + tcflush(port_fd, TCIFLUSH); +} + + +int read_serial_port_nb(unsigned char *buf, int bufsize) +{ + int num, flags; + + flags = fcntl(port_fd, F_GETFL); + fcntl(port_fd, F_SETFL, flags | O_NONBLOCK); + num = read(port_fd, buf, bufsize); + fcntl(port_fd, F_SETFL, flags); + return num; +} + +int read_serial_port(unsigned char *buf, int bufsize) +{ + int num; + + num = read(port_fd, buf, bufsize); + + return num; +} + + +void send_break_signal(void) +{ + tcsendbreak(port_fd, 0); +} + + +void close_serial_port(void) +{ + if (port_fd >= 0) { + close(port_fd); + port_fd = -1; + } +} + + +tcflag_t baud_name_to_flags(const char *baud_name) +{ + if (strcmp(baud_name, "230400") == 0) return B230400; + if (strcmp(baud_name, "115200") == 0) return B115200; + if (strcmp(baud_name, "57600") == 0) return B57600; + if (strcmp(baud_name, "38400") == 0) return B38400; + if (strcmp(baud_name, "19200") == 0) return B19200; + if (strcmp(baud_name, "9600") == 0) return B9600; + if (strcmp(baud_name, "4800") == 0) return B4800; + if (strcmp(baud_name, "2400") == 0) return B2400; + if (strcmp(baud_name, "1200") == 0) return B1200; + if (strcmp(baud_name, "300") == 0) return B300; + return B0; +} + + +int set_baud(const char *baud_name) +{ + struct termios port_setting; + tcflag_t baud; + int r; + + if (port_fd < 0) return -1; + baud = baud_name_to_flags(baud_name); + if (baud == B0) return -2; + r = tcgetattr(port_fd, &port_setting); + if (r != 0) return -3; + //port_setting.c_iflag = IGNBRK | IGNPAR | IXANY | IXON; + port_setting.c_iflag = IGNBRK | IGNPAR; + port_setting.c_cflag = baud | CS8 | CREAD | HUPCL | CLOCAL; + port_setting.c_oflag = 0; + port_setting.c_lflag = 0; + r = tcsetattr(port_fd, TCSAFLUSH, &port_setting); + if (r != 0) return -4; + return 0; +} + + +// Normally this should never be used... except to pass the port +// file descriptor to the GTK event monitoring loop. All other +// use of the serial port is supposed to happen in the file. +int serial_port_fd(void) +{ + return port_fd; +} + + + +void set_rts(int val) +{ + int flags; + int result; + + result = ioctl(port_fd, TIOCMGET, &flags); + if( result == -1 ) { + printf("Error %i while reading port io flags\n", errno); + return; + } + + if (val) { + flags |= TIOCM_RTS; + } else { + flags &= ~(TIOCM_RTS); + } + + result = ioctl(port_fd, TIOCMSET, &flags); + if( result == -1 ) + printf("Error %i while setting port io flags\n", errno); +} + + + + + + + +void set_dtr(int val) +{ + int flags; + int result; + + result = ioctl(port_fd, TIOCMGET, &flags); + if( result == -1 ) { + printf("Error %i while reading port io flags\n", errno); + return; + } + + if (val) { + flags |= TIOCM_DTR; + } else { + flags &= ~(TIOCM_DTR); + } + + result = ioctl(port_fd, TIOCMSET, &flags); + if( result == -1 ) + printf("Error %i while setting port io flags\n", errno); +} + + + + + + diff --git a/board/msba2/tools/src/serial.h b/board/msba2/tools/src/serial.h new file mode 100644 index 0000000000..4ef9a82e5b --- /dev/null +++ b/board/msba2/tools/src/serial.h @@ -0,0 +1,19 @@ +#ifndef SERIAL_H +#define SERIAL_H + +extern char* baud_rate; + +int open_serial_port(const char *port_name); +int write_serial_port(const void *buf, int num); +void input_flush_serial_port(void); +int read_serial_port_nb(unsigned char *buf, int bufsize); +int read_serial_port(unsigned char *buf, int bufsize); +void close_serial_port(void); +void send_break_signal(void); +int set_baud(const char *baud_name); +int serial_port_fd(void); +void set_rts(int val); +void set_dtr(int val); +void change_baud(const char *baud_name); + +#endif // SERIAL_H diff --git a/board/msba2/tools/src/settings.c b/board/msba2/tools/src/settings.c new file mode 100644 index 0000000000..d52e24a03f --- /dev/null +++ b/board/msba2/tools/src/settings.c @@ -0,0 +1,172 @@ +/* + * LPC 2000 Loader, http://www.pjrc.com/arm/lpc2k_pgm + * Copyright (c) 2004, PJRC.COM, LLC, + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +/* If this code fails to build, please provide at least the following + * information when requesting (free) technical support. + * + * 1: Complete copy of all messages during the build. + * 2: Output of "gtk-config --version" + * 3: Output of "gtk-config --libs" + * 4: Output of "gtk-config --cflags" + * 5: Output of "uname -a" + * 6: Version of GTK installed... eg, type: ls -l /lib/libgtk* + * 7: Other info... which linux distribution, version, other software + */ + + +#include +#include +#include +#include + +#include "settings.h" + +#define DEFAULT_FILE "" +#define DEFAULT_PORT "/dev/ttyS0" +#define DEFAULT_BAUD "115200" +#define DEFAULT_CRYSTAL "16" + +char *baud_list[]={"115200", "57600", "38400", + "19200", "9600", "4800", "2400", "1200", "300", NULL}; + +static char file[128]={DEFAULT_FILE}; +static char port[64]={DEFAULT_PORT}; +static char baud[64]={DEFAULT_BAUD}; +static char crystal[64]={DEFAULT_CRYSTAL}; + +static char settings_file[256]={'\0'}; + + +void init_settings(void) +{ + const char *home_dir; + FILE *fp; + char buf[1024], *p, *q; + + home_dir = getenv("HOME"); + if (home_dir && *home_dir) { + snprintf(settings_file, sizeof(settings_file), + "%s/.lpc2k_pgm", home_dir); + fp = fopen(settings_file, "r"); + if (fp == NULL) return; + while (!feof(fp)) { + buf[0] = '\0'; + fgets(buf, sizeof(buf), fp); + if (strncmp(buf, "file:", 5) == 0) { + for (p=buf+5; isspace(*p); p++) ; + q = rindex(p, '\n'); if (q) *q = '\0'; + q = rindex(p, '\r'); if (q) *q = '\0'; + snprintf(file, sizeof(file), "%s", p); + } + if (strncmp(buf, "port:", 5) == 0) { + for (p=buf+5; isspace(*p); p++) ; + q = rindex(p, '\n'); if (q) *q = '\0'; + q = rindex(p, '\r'); if (q) *q = '\0'; + snprintf(port, sizeof(port), "%s", p); + } + if (strncmp(buf, "baud:", 5) == 0) { + for (p=buf+5; isspace(*p); p++) ; + q = rindex(p, '\n'); if (q) *q = '\0'; + q = rindex(p, '\r'); if (q) *q = '\0'; + snprintf(baud, sizeof(baud), "%s", p); + } + if (strncmp(buf, "xtal:", 5) == 0) { + for (p=buf+5; isspace(*p); p++) ; + q = rindex(p, '\n'); if (q) *q = '\0'; + q = rindex(p, '\r'); if (q) *q = '\0'; + snprintf(crystal, sizeof(crystal), "%s", p); + } + } + fclose(fp); + } +} + +void write_settings_file(void) +{ + FILE *fp; + + if (settings_file[0] == '\0') return; + fp = fopen(settings_file, "w"); + if (fp == NULL) return; + fprintf(fp, "file: %s\n", file); + fprintf(fp, "port: %s\n", port); + fprintf(fp, "baud: %s\n", baud); + fprintf(fp, "xtal: %s\n", crystal); + fflush(fp); + fclose(fp); +} + +const char * file_setting(void) +{ + return file; +} + +const char * port_setting(void) +{ + return port; +} + +const char * baud_setting(void) +{ + return baud; +} + +const char * crystal_setting(void) +{ + return crystal; +} + +void new_file_setting(const char *new_file) +{ + if (strcmp(file, new_file)) { + snprintf(file, sizeof(file), "%s", new_file); + write_settings_file(); + } +} + +void new_port_setting(const char *new_port) +{ + if (strcmp(port, new_port)) { + snprintf(port, sizeof(port), "%s", new_port); + write_settings_file(); + } +} + +void new_baud_setting(const char *new_baud) +{ + if (strcmp(baud, new_baud)) { + snprintf(baud, sizeof(baud), "%s", new_baud); + write_settings_file(); + } +} + +void new_crystal_setting(const char *new_xtal) +{ + if (strcmp(crystal, new_xtal)) { + snprintf(crystal, sizeof(crystal), "%s", new_xtal); + write_settings_file(); + } +} + + + + + + diff --git a/board/msba2/tools/src/settings.h b/board/msba2/tools/src/settings.h new file mode 100644 index 0000000000..20686821a4 --- /dev/null +++ b/board/msba2/tools/src/settings.h @@ -0,0 +1,12 @@ + +extern void init_settings(void); +extern const char * file_setting(void); +extern const char * port_setting(void); +extern const char * baud_setting(void); +extern const char * crystal_setting(void); +extern void new_file_setting(const char *new_file); +extern void new_port_setting(const char *new_port); +extern void new_baud_setting(const char *new_baud); +extern void new_crystal_setting(const char *new_xtal); + +extern char *baud_list[]; diff --git a/board/msba2/tools/src/uuencode.c b/board/msba2/tools/src/uuencode.c new file mode 100644 index 0000000000..5cc76e796c --- /dev/null +++ b/board/msba2/tools/src/uuencode.c @@ -0,0 +1,98 @@ +/* + * LPC 2000 Loader, http://www.pjrc.com/arm/lpc2k_pgm + * Copyright (c) 2004, PJRC.COM, LLC, + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +/* If this code fails to build, please provide at least the following + * information when requesting (free) technical support. + * + * 1: Complete copy of all messages during the build. + * 2: Output of "gtk-config --version" + * 3: Output of "gtk-config --libs" + * 4: Output of "gtk-config --cflags" + * 5: Output of "uname -a" + * 6: Version of GTK installed... eg, type: ls -l /lib/libgtk* + * 7: Other info... which linux distribution, version, other software + */ + +#include "uuencode.h" + +static char uuchar(unsigned int val); + + +void uuencode(char *str, const unsigned char *data, int num) +{ + int i, n; + unsigned int val; + + *str++ = uuchar(num); + + n = (num + 2) / 3; + for (i=0; i> 18); + *str++ = uuchar(val >> 12); + *str++ = uuchar(val >> 6); + *str++ = uuchar(val >> 0); + data += 3; + } + *str = '\0'; +} + +int uudecode(const char *str, unsigned char *data, int max) +{ + int num=0; + int i, n; + unsigned int val; + + if (*str == '\0') return 0; + + num = *str++ - 32; + if (num < 1 || num > 45) return 0; + + n = (num + 2) / 3; + for (i=0; i 96) return 0; + if (str[1] < 32 || str[1] > 96) return 0; + if (str[2] < 32 || str[2] > 96) return 0; + if (str[3] < 32 || str[3] > 96) return 0; + val = (((str[0] - 32) & 0x3F) << 18) + | (((str[1] - 32) & 0x3F) << 12) + | (((str[2] - 32) & 0x3F) << 6) + | (((str[3] - 32) & 0x3F) << 0); + *data++ = (val >> 16) & 0xFF; + *data++ = (val >> 8) & 0xFF; + *data++ = (val >> 0) & 0xFF; + str += 4; + } + return num; +} + + +static char uuchar(unsigned int val) +{ + val &= 0x3F; + val += 0x20; + if (val == 0x20) val = 0x60; + return val; +} + + + diff --git a/board/msba2/tools/src/uuencode.h b/board/msba2/tools/src/uuencode.h new file mode 100644 index 0000000000..92fecb7d33 --- /dev/null +++ b/board/msba2/tools/src/uuencode.h @@ -0,0 +1,3 @@ +extern void uuencode(char *str, const unsigned char *data, int num); +extern int uudecode(const char *str, unsigned char *data, int max); + diff --git a/board/msba2/tools/termctrl.sh b/board/msba2/tools/termctrl.sh new file mode 100755 index 0000000000..75e87ab21e --- /dev/null +++ b/board/msba2/tools/termctrl.sh @@ -0,0 +1,22 @@ +#!/bin/sh + +pid=`pgrep pseudoterm` + +if test "$pid" = "" ; then + + echo " Pseudoterm not running." + +else + + if test "$1" = "continue" ; then + kill -s USR1 $pid; + elif test "$1" = "pause" ; then + kill -s USR2 $pid ; + elif test "$1" = "stop" ; then + kill $pid ; + else + echo "Usage:"; + echo "termctrl.sh continue/pause/stop"; + fi + +fi diff --git a/board/olimex_lpc2148/Jamfile b/board/olimex_lpc2148/Jamfile new file mode 100644 index 0000000000..43ad7d1baf --- /dev/null +++ b/board/olimex_lpc2148/Jamfile @@ -0,0 +1,10 @@ +SubDir TOP board olimex_lpc2148 ; + +CPU = lpc214x ; + +HDRS += $(TOP)/board/olimex_lpc2148/include ; + +Module board : board_init.c debug_uart.c rs232.c ; +UseModule board ; + +SubInclude TOP cpu lpc214x ; diff --git a/board/olimex_lpc2148/Jamfile.olimex_lpc2148 b/board/olimex_lpc2148/Jamfile.olimex_lpc2148 new file mode 100644 index 0000000000..057aa7b322 --- /dev/null +++ b/board/olimex_lpc2148/Jamfile.olimex_lpc2148 @@ -0,0 +1,4 @@ +################## + +include $(TOP)/Jamfile.arm_common ; + diff --git a/board/olimex_lpc2148/Jamrules.olimex_lpc2148 b/board/olimex_lpc2148/Jamrules.olimex_lpc2148 new file mode 100644 index 0000000000..7a7086d5bc --- /dev/null +++ b/board/olimex_lpc2148/Jamrules.olimex_lpc2148 @@ -0,0 +1,9 @@ +############################ + +BOARD = olimex_lpc2148 ; +CPU = lpc214x ; + +GDB = arm-elf-gdb ; +GDBFLAGS = -x board/olimex_lpc2148/tools/lpc2148_flash.gdb ; + +include $(TOP)/Jamrules.arm_common ; diff --git a/board/olimex_lpc2148/board_init.c b/board/olimex_lpc2148/board_init.c new file mode 100644 index 0000000000..874feb8812 --- /dev/null +++ b/board/olimex_lpc2148/board_init.c @@ -0,0 +1,88 @@ +/* + * bl_board_init.c + * + * Created on: 19.08.2008 + * Author: heiko, kaspar + */ + +#include "cpu.h" +#include "bits.h" +#include "VIC.h" + +#define PLOCK 0x400 + +static void feed(void) +{ + PLL0FEED = 0xAA; + PLL0FEED = 0x55; +} + +void bl_init_clks(void) +{ + + // Setting the Phased Lock Loop (PLL) + // ---------------------------------- + // + // Olimex LPC-P2148 has a 12.0000 mhz crystal + // + // We'd like the LPC2148 to run at 60 mhz (has to be an even multiple of crystal) + // + // According to the Philips LPC2148 manual: M = cclk / Fosc where: M = PLL multiplier (bits 0-4 of PLLCFG) + // cclk = 60000000 hz + // Fosc = 12000000 hz + // + // Solving: M = 60000000 / 12000000 = 5 + // + // Note: M - 1 must be entered into bits 0-4 of PLLCFG (assign 4 to these bits) + // + // + // The Current Controlled Oscilator (CCO) must operate in the range 156 mhz to 320 mhz + // + // According to the Philips LPC2148 manual: Fcco = cclk * 2 * P where: Fcco = CCO frequency + // cclk = 60000000 hz + // P = PLL divisor (bits 5-6 of PLLCFG) + // + // Solving: Fcco = 60000000 * 2 * P + // P = 2 (trial value) + // Fcco = 60000000 * 2 * 2 + // Fcc0 = 240000000 hz (good choice for P since it's within the 156 mhz to 320 mhz range) + // + // From Table 22 (page 34) of Philips LPC2148 manual P = 2, PLLCFG bits 5-6 = 1 (assign 1 to these bits) + // + // Finally: PLLCFG = 0 01 00100 = 0x24 + // + // Final note: to load PLLCFG register, we must use the 0xAA followed 0x55 write sequence to the PLLFEED register + // this is done in the short function feed() below + // + + // Setting Multiplier and Divider values + PLL0CFG = 0x24; + feed(); + + // Enabling the PLL */ + PLL0CON = 0x1; + feed(); + + // Wait for the PLL to lock to set frequency + while(!(PLL0STAT & PLOCK)) ; + + // Connect the PLL as the clock source + PLL0CON = 0x3; + feed(); + + // Enabling MAM and setting number of clocks used for Flash memory fetch + MAMTIM = 0x3; + MAMCR = 0x2; + + // Setting peripheral Clock (pclk) to 1/2 System Clock (cclk) + VPBDIV = PCLK_DIV; +} + + + + +void bl_init_ports(void) +{ + +} + diff --git a/board/olimex_lpc2148/debug_uart.c b/board/olimex_lpc2148/debug_uart.c new file mode 100644 index 0000000000..90f5144dfe --- /dev/null +++ b/board/olimex_lpc2148/debug_uart.c @@ -0,0 +1,14 @@ +#include "lpc214x.h" +#include "bits.h" + +#include "rs232.h" + +void debug_putchar(int character) +{ + UART1WriteChar(character); +} + +void bl_uart_init(void) +{ + UART1Initialize(115200U); +} diff --git a/board/olimex_lpc2148/include/board.h b/board/olimex_lpc2148/include/board.h new file mode 100644 index 0000000000..eaf536b005 --- /dev/null +++ b/board/olimex_lpc2148/include/board.h @@ -0,0 +1 @@ +#include diff --git a/board/olimex_lpc2148/include/rs232.h b/board/olimex_lpc2148/include/rs232.h new file mode 100644 index 0000000000..9fe0bf2c87 --- /dev/null +++ b/board/olimex_lpc2148/include/rs232.h @@ -0,0 +1,40 @@ +//rs232.h +//#include + +#include "lpc214x.h" + +//#define OSCILLATOR_CLOCK_FREQUENCY 14745600 //in MHz +#define OSCILLATOR_CLOCK_FREQUENCY 12000000 //in MHz + +//get real processor clock frequency +unsigned int processorClockFrequency(void); +//get peripheral clock frequency +unsigned int peripheralClockFrequency(void); + +/**** UART0 ****/ +//initialize UART0 interface +void UART0Initialize(unsigned int baud); +//write char to UART0 (RS232); +void UART0WriteChar(int ch0); +//read char from RS232 +unsigned char UART0ReadChar(void); + +//this function read/write char from RS232, +//but they not wait to read/write +unsigned char UART0ReadChar_nostop(void); +void UART0WriteChar_nostop(unsigned char ch0); + + +/**** UART1 ****/ +//initialize UART0 interface +void UART1Initialize(unsigned int baud); +//write char to UART0 (RS232); +void UART1WriteChar(int ch0); +//read char from RS232 +unsigned char UART0ReadChar(void); + +//this function read/write char from RS232, +//but they not wait to read/write +unsigned char UART1ReadChar_nostop(void); +void UART1WriteChar_nostop(unsigned char ch0); + diff --git a/board/olimex_lpc2148/rs232.c b/board/olimex_lpc2148/rs232.c new file mode 100644 index 0000000000..43e70a00f2 --- /dev/null +++ b/board/olimex_lpc2148/rs232.c @@ -0,0 +1,65 @@ +//rs232.c +#include "rs232.h" + +unsigned int processorClockFrequency(void) +{ + //return real processor clock speed + return OSCILLATOR_CLOCK_FREQUENCY * (PLL0CON & 1 ? (PLL0CFG & 0xF) + 1 : 1); +} + +unsigned int peripheralClockFrequency(void) +{ + //VPBDIV - determines the relationship between the processor clock (cclk) + //and the clock used by peripheral devices (pclk). + unsigned int divider = 0; + switch (VPBDIV & 3) + { + case 0: divider = 4; break; + case 1: divider = 1; break; + case 2: divider = 2; break; + } + return processorClockFrequency() / divider; +} + +/**** UART0 ****/ +void UART1Initialize(unsigned int baud) +{ + unsigned int divisor = peripheralClockFrequency() / (16 * baud); + + //set Line Control Register (8 bit, 1 stop bit, no parity, enable DLAB) +// U0LCR_bit.WLS = 0x3; //8 bit +// U0LCR_bit.SBS = 0x0; //1 stop bit +// U0LCR_bit.PE = 0x0; //no parity +// U0LCR_bit.DLAB = 0x1; //enable DLAB + //with one row + U1LCR = 0x83; + + + //devisor + U1DLL = divisor & 0xFF; + U1DLM = (divisor >> 8) & 0xFF; + U1LCR &= ~0x80; + + //set functionalite to pins: port0.0 -> TX0, port0.1 -> RXD0 +// PINSEL0_bit.P0_0 = 0x1; +// PINSEL0_bit.P0_1 = 0x1; + //with one row + PINSEL0 |= BIT16; + PINSEL0 &= ~BIT17; + +} + +void UART1WriteChar(int ch0) +{ + while (!(U1LSR & BIT5)); + U1THR = ch0; +} + +unsigned char UART0ReadChar(void) +{ + //when U0LSR_bit.DR is 1 - U0RBR contains valid data +// while (U0LSR_bit.DR == 0); + return U0RBR; +} + + diff --git a/board/olimex_lpc2148/tick.c b/board/olimex_lpc2148/tick.c new file mode 100644 index 0000000000..08b3dcb0bb --- /dev/null +++ b/board/olimex_lpc2148/tick.c @@ -0,0 +1,63 @@ +/* Copyright (C) 2005, 2006, 2007, 2008 by Thomas Hillebrandt and Heiko Will + +This file is part of the Micro-mesh SensorWeb Firmware. + +Micro-Mesh is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +Micro-Mesh is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Micro-Mesh; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +#include "lpc214x.h" +#include "bits.h" +//#include "tick.h" +#include "minimal_dbg_console.h" +#include "VIC.h" + +void Timer0_IRQHandler (void) __attribute__((interrupt("IRQ"))); + +extern void eINT(); +extern void dINT(); + + +void driver_timer_load(void) +{ + T0TCR = 0; // Disable timer 0. + T0PR = 3000; // Prescaler is set to relevant pclk , counter is incremented every T0PR tact. + T0CCR = 0; // Capture is disabled. + T0EMR = 0; // No external match output. + T0TC= 0; + T0MR0= 1000; + T0MCR|= BIT0 + BIT1; + T0TCR = BIT0; // Enable timer 0. + + dINT(); // Disable all interrupts + VICIntEnable = BIT4; // Enable Interrupthandling for Timer0 + VICVectCntl3 = 4 + BIT5; // Assign Timer0 to IRQ Slot 3 + VICVectAddr3 = (unsigned int)Timer0_IRQHandler; // Assign Isr Address + eINT(); +} + +int counter = 0; + +void Timer0_IRQHandler (void) +{ + extern unsigned int fk_context_switch_request; + counter++; + T0IR |= 0xff; // reset timer1 interrupt flag + sl_printf("#"); + + fk_context_switch_request = 1; + + VICVectAddr = 0; // acknowledge interrupt (if using VIC IRQ) +} + diff --git a/board/olimex_lpc2148/tools/lpc2148_flash.gdb b/board/olimex_lpc2148/tools/lpc2148_flash.gdb new file mode 100644 index 0000000000..cb308752ae --- /dev/null +++ b/board/olimex_lpc2148/tools/lpc2148_flash.gdb @@ -0,0 +1,22 @@ +#winheight regs 11 +set history save on +set history size 1000 +target remote localhost:3333 +monitor reset +monitor sleep 100 +monitor halt +monitor poll +#monitor arm7_9 sw_bkpts disable +#monitor arm7_9 force_hw_bkpts enable +monitor mww 0xE01FC040 0x0001 +monitor mdw 0xE01FC040 +monitor flash erase_sector 0 0 14 +#monitor flash auto_erase on +monitor flash erase_check 0 +#monitor flash write_image /home/kaspar/FeuerWhere/src/x/bin/arm.elf +set remote hardware-watchpoint-limit 2 +load +break bootloader +mon soft_reset_halt +continue +d b 1 diff --git a/board/pttu/Jamfile b/board/pttu/Jamfile new file mode 100644 index 0000000000..a7b4d6df11 --- /dev/null +++ b/board/pttu/Jamfile @@ -0,0 +1,35 @@ +# ****************************************************************************** +# Copyright 2009, Freie Universitaet Berlin (FUB). All rights reserved. +# +# These sources were developed at the Freie Universitaet Berlin, Computer +# Systems and Telematics group (http://cst.mi.fu-berlin.de). +# ------------------------------------------------------------------------------ +# This file is part of FeuerWare. +# +# This program is free software: you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation, either version 3 of the License, or (at your option) any later +# version. +# +# FeuerWare is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with +# this program. If not, see http://www.gnu.org/licenses/ . +# ------------------------------------------------------------------------------ +# For further information and questions please use the web site +# http://scatterweb.mi.fu-berlin.de +# and the mailinglist (subscription via web site) +# scatterweb@lists.spline.inf.fu-berlin.de +# ****************************************************************************** +# $Id: Jamfile 922 2009-03-26 12:52:27Z baar $ + +SubDir TOP board pttu ; + +Module board : board_init.c ; +UseModule board ; +UseModule board_common ; + +SubInclude TOP board $(BOARD) drivers ; +SubInclude TOP cpu $(CPU) ; diff --git a/board/pttu/Jamfile.pttu b/board/pttu/Jamfile.pttu new file mode 100644 index 0000000000..1bce8934fe --- /dev/null +++ b/board/pttu/Jamfile.pttu @@ -0,0 +1,28 @@ +# ****************************************************************************** +# Copyright 2009, Freie Universitaet Berlin (FUB). All rights reserved. +# +# These sources were developed at the Freie Universitaet Berlin, Computer +# Systems and Telematics group (http://cst.mi.fu-berlin.de). +# ------------------------------------------------------------------------------ +# This file is part of FeuerWare. +# +# This program is free software: you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation, either version 3 of the License, or (at your option) any later +# version. +# +# FeuerWare is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with +# this program. If not, see http://www.gnu.org/licenses/ . +# ------------------------------------------------------------------------------ +# For further information and questions please use the web site +# http://scatterweb.mi.fu-berlin.de +# and the mailinglist (subscription via web site) +# scatterweb@lists.spline.inf.fu-berlin.de +# ****************************************************************************** +# $Id: Jamfile.msba2 832 2009-03-13 16:45:41Z kaspar $ + +include [ FPath $(TOP) cpu arm_common Jamfile.arm_common ] ; diff --git a/board/pttu/Jamrules.pttu b/board/pttu/Jamrules.pttu new file mode 100644 index 0000000000..7eff15f0bb --- /dev/null +++ b/board/pttu/Jamrules.pttu @@ -0,0 +1,37 @@ +# ****************************************************************************** +# Copyright 2009, Freie Universitaet Berlin (FUB). All rights reserved. +# +# These sources were developed at the Freie Universitaet Berlin, Computer +# Systems and Telematics group (http://cst.mi.fu-berlin.de). +# ------------------------------------------------------------------------------ +# This file is part of FeuerWare. +# +# This program is free software: you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation, either version 3 of the License, or (at your option) any later +# version. +# +# FeuerWare is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with +# this program. If not, see http://www.gnu.org/licenses/ . +# ------------------------------------------------------------------------------ +# For further information and questions please use the web site +# http://scatterweb.mi.fu-berlin.de +# and the mailinglist (subscription via web site) +# scatterweb@lists.spline.inf.fu-berlin.de +# ****************************************************************************** +# $Id: Jamrules.msba2 881 2009-03-20 12:24:58Z kaspar $ + +CPU = lpc2387 ; + +HDRS += [ FPath $(TOP) board $(BOARD) drivers include ] ; + +FLASHER = $(POSIXSHELL) $(TOP)/board/msba2/tools/flashutil.sh ; +FLASHFLAGS = --basedir $(TOP)/board/msba2/tools --id PTTU --ports "$(PORT)" --openocd $(TOP)/board/pttu/tools/openocd-pttu.sh --openocd-if $(OPENOCD_IF) ; + +GDB = arm-elf-gdb ; +GDBFLAGS = -x board/pttu/tools/pttu_debug.gdb ; + diff --git a/board/pttu/board_init.c b/board/pttu/board_init.c new file mode 100644 index 0000000000..3070bdfce7 --- /dev/null +++ b/board/pttu/board_init.c @@ -0,0 +1,239 @@ +/****************************************************************************** +Copyright 2008-2009, Freie Universitaet Berlin (FUB). All rights reserved. + +These sources were developed at the Freie Universitaet Berlin, Computer Systems +and Telematics group (http://cst.mi.fu-berlin.de). +------------------------------------------------------------------------------- +This file is part of FeuerWare. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +FeuerWare is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see http://www.gnu.org/licenses/ . +-------------------------------------------------------------------------------- +For further information and questions please use the web site + http://scatterweb.mi.fu-berlin.de +and the mailinglist (subscription via web site) + scatterweb@lists.spline.inf.fu-berlin.de +*******************************************************************************/ + +/** + * @ingroup pttu + * @{ + */ + +/** + * @file + * @brief PTTU board initialization + * + * @author Freie Universit�t Berlin, Computer Systems & Telematics, FeuerWhere project + * @author Heiko Will + * @author Kaspar Schleise + * @author Michael Baar + * + * @note $Id: cmdengine-out.c 971 2009-04-07 13:41:36Z baar $ + */ +#include "lpc23xx.h" +#include "VIC.h" +#include "cpu.h" + +#define PCRTC BIT9 +#define CL_CPU_DIV 4 + +/*---------------------------------------------------------------------------*/ +/** + * @brief Enabling MAM and setting number of clocks used for Flash memory fetch + * @internal + */ +void +init_mam(void) +{ + MAMCR = 0x0000; + MAMTIM = 0x0003; + MAMCR = 0x0002; +} +/*---------------------------------------------------------------------------*/ +static inline void +pllfeed(void) +{ + PLLFEED = 0xAA; + PLLFEED = 0x55; +} +/*---------------------------------------------------------------------------*/ +void init_clks1(void) +{ + // Disconnect PLL + PLLCON &= ~0x0002; + pllfeed(); + + // Disable PLL + PLLCON &= ~0x0001; + pllfeed(); + + SCS |= 0x20; // Enable main OSC + while( !(SCS & 0x40) ); // Wait until main OSC is usable + + /* select main OSC, 16MHz, as the PLL clock source */ + CLKSRCSEL = 0x0001; + + // Setting Multiplier and Divider values + PLLCFG = 0x0008; // M=9 N=1 Fcco = 288 MHz + pllfeed(); + + // Enabling the PLL */ + PLLCON = 0x0001; + pllfeed(); + + /* Set clock divider to 4 (value+1) */ + CCLKCFG = CL_CPU_DIV - 1; // Fcpu = 72 MHz + +#if USE_USB + USBCLKCFG = USBCLKDivValue; /* usbclk = 288 MHz/6 = 48 MHz */ +#endif +} + +void init_clks2(void){ + // Wait for the PLL to lock to set frequency + while(!(PLLSTAT & BIT26)); + + // Connect the PLL as the clock source + PLLCON = 0x0003; + pllfeed(); + + /* Check connect bit status */ + while (!(PLLSTAT & BIT25)); +} + +void bl_init_clks(void) +{ + PCONP = PCRTC; // switch off everything except RTC + init_clks1(); + init_clks2(); + init_mam(); +} + + +// Michael, Do not change anything here! even not the redundant parts! +void bl_init_ports(void) +{ + SCS |= BIT0; // Set IO Ports to fast switching mode + + /* UART0 */ + PINSEL0 |= BIT4 + BIT6; // RxD0 and TxD0 + PINSEL0 &= ~(BIT5 + BIT7); + + /*Turn Board on*/ + PINMODE0 |= BIT1; + FIO0DIR |= BIT27; + FIO0CLR = BIT27; + + /* 5V*/ + FIO1DIR |= BIT28; // Synch + FIO1SET = BIT28; // No Powersave + + FIO1DIR |= BIT27; // 5V off + FIO1CLR = BIT27; + + /* Disable Resistors on Buttons */ + PINMODE4 |= BIT9 + BIT11; + + /* Disable Resistors on LED - and Ports to output*/ + PINMODE7 |= BIT19 + BIT21; + PINMODE2 |= BIT1; + FIO1DIR |= BIT0; + FIO3DIR |= BIT25 + BIT26; + FIO1SET = BIT0; + FIO3SET = BIT25 + BIT26; + + // Config and Disable PA + FIO1DIR |= BIT25 + BIT26 + BIT22; + FIO1SET = BIT26; + FIO1CLR = BIT25; + FIO1CLR = BIT22; // PA /Shutdown + FIO0DIR |= BIT26; // ** // Important: First put this Port as DA 2.0V and then turn on PA!! + FIO0SET = BIT26; // ** + + // Configure GPS + PINMODE3 |= BIT3 + BIT7; // No Pullup on 1.17 & 1.19 + PINMODE9 |= BIT27 + BIT25; // No Pullup for Uart + FIO1DIR |= BIT17; + FIO1CLR = BIT17; // Turn off GPS + FIO1DIR |= BIT19; + FIO1CLR = BIT19; // Hold in Reset + PINSEL9 |= BIT24 + BIT25 + BIT26 + BIT27; //4.28 & 4.29 as Uart3 + + // Nanotron + FIO2DIR &= ~BIT8; // nanotron uC IRQ as input + FIO1DIR |= BIT15; // nanotron power on reset + FIO1DIR &= ~BIT14; // nanotron uC RESET as input + FIO1DIR &= ~BIT10; // nanotron uC Vcc as input + FIO1DIR |= BIT9; // nanotron ENABLE as output + FIO1DIR &= ~BIT4; // nanotron Rx/Tx as input + + FIO1CLR = BIT15; + FIO1CLR = BIT9; // Enable power + + PINMODE1 |= BIT1; // No Pullup for CS + FIO0DIR |= BIT16; // CS as output + FIO0SET = BIT16; // drive cs inactive + FIO0DIR |= BIT18 + BIT15; // SPi Output + + // RFID + FIO1DIR |= BIT1; // RFID Power + FIO1CLR = BIT1; // + + FIO0DIR |= BIT1; // RFID Reset + FIO0SET = BIT1; // Hold in Reset + + FIO0DIR &= ~BIT10; // LED as INPUT + FIO0DIR &= ~BIT11; // DATA as INPUT + PINMODE0 |= BIT19 + BIT21; // No Pullups + + // LTC4150 ARM + FIO0DIR |= BIT5; + FIO0CLR = BIT5; + + // LTC4150 System + FIO0DIR |= BIT24; + FIO0CLR = BIT24; + + // Battery Voltage (AD) + PINMODE1 |= BIT19; + PINSEL1 &= ~BIT19; + PINSEL1 |= BIT18; + + //cc1100 + FIO0DIR |= BIT6 + BIT7 + BIT9; + FIO0SET = BIT6; + FIO0SET = BIT7 + BIT9; + + //SD + FIO2DIR |= BIT12 + BIT13 + BIT11; + FIO0DIR |= BIT20 + BIT22 + BIT21; + + //Tetra + FIO2DIR |= BIT0 + BIT7; + + + // No Pullups on any port + int nopullup = BIT1 + BIT3 + BIT5 + BIT7 + BIT9 + BIT11 + BIT13 + BIT15 + BIT17 + BIT19 + BIT21 + BIT23 + BIT25 + BIT27 + BIT29 + BIT31; + PINMODE0 = nopullup - BIT13 - BIT15 - BIT17 - BIT19; + PINMODE1 = BIT1 + BIT3 + BIT5 + BIT7 + BIT9 + BIT11 + BIT13 + BIT15 + BIT17 + BIT19 + BIT21; + PINMODE2 = nopullup; + PINMODE3 = nopullup; + PINMODE4 = nopullup; + PINMODE5 = nopullup; + PINMODE6 = nopullup; + PINMODE7 = nopullup; + PINMODE8 = nopullup; + PINMODE9 = nopullup; +} + +/** @} */ diff --git a/board/pttu/drivers/Jamfile b/board/pttu/drivers/Jamfile new file mode 100644 index 0000000000..26a8b7c2af --- /dev/null +++ b/board/pttu/drivers/Jamfile @@ -0,0 +1,4 @@ +SubDir TOP board pttu drivers ; + +Module board_common : pttu-uart0.c ; + diff --git a/board/pttu/drivers/pttu-uart0.c b/board/pttu/drivers/pttu-uart0.c new file mode 100644 index 0000000000..d542f22602 --- /dev/null +++ b/board/pttu/drivers/pttu-uart0.c @@ -0,0 +1,204 @@ +/****************************************************************************** +Copyright 2008-2009, Freie Universitaet Berlin (FUB). All rights reserved. + +These sources were developed at the Freie Universitaet Berlin, Computer Systems +and Telematics group (http://cst.mi.fu-berlin.de). +------------------------------------------------------------------------------- +This file is part of FeuerWare. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +FeuerWare is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see http://www.gnu.org/licenses/ . +-------------------------------------------------------------------------------- +For further information and questions please use the web site + http://scatterweb.mi.fu-berlin.de +and the mailinglist (subscription via web site) + scatterweb@lists.spline.inf.fu-berlin.de +*******************************************************************************/ + +/* + * debug_uart.c: provides initial serial debug output + * + * Copyright (C) 2008, 2009 Kaspar Schleiser + * Heiko Will + */ +#include +#include +#include +#include "lpc23xx.h" +#include "VIC.h" + +/** + * @file + * @ingroup lpc2387 + * + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @version $Revision$ + * + * @note $Id$ + */ + +typedef struct toprint { + unsigned int len; + char content[]; +}toprint; + +#define QUEUESIZE 255 +static volatile toprint* queue[QUEUESIZE]; +static volatile unsigned char queue_head = 0; +static volatile unsigned char queue_tail = 0; +static volatile unsigned char queue_items = 0; + +static volatile unsigned int actual_pos = 0; +static volatile unsigned int running = 0; +static volatile unsigned int fifo = 0; + +static volatile toprint* actual = NULL; +void (*uart0_callback)(int); + +static inline void enqueue(void) { + queue_items++; + queue_tail++; +} + +static inline void dequeue(void) { + actual = (queue[queue_head]); + queue_items--; + queue_head++; +} + +static void push_queue(void) { + running = 1; +start: + if (!actual) { + if (queue_items) { + dequeue(); + } else { + running = 0; + if (!fifo) + while(!(U0LSR & BIT6)){}; + return; + } + } + while ((actual_pos < actual->len) && (fifo++ < 16)){ + U0THR = actual->content[actual_pos++]; + } + if (actual_pos == actual->len) { + free((void*)actual); + actual = NULL; + actual_pos = 0; + goto start; + } +} + +int uart_active(void){ + return (running || fifo); +} + +static inline void receive(int c) +{ + if (uart0_callback != NULL) uart0_callback(c); +} + +void stdio_flush(void) +{ + U0IER &= ~BIT1; // disable THRE interrupt + while(running) { + while(!(U0LSR & (BIT5|BIT6))){}; // transmit fifo + fifo=0; + push_queue(); // dequeue to fifo + } + U0IER |= BIT1; // enable THRE interrupt +} + +void UART0_IRQHandler(void) __attribute__((interrupt("IRQ"))); +void UART0_IRQHandler(void) +{ + int iir; + iir = U0IIR; + + switch(iir & UIIR_ID_MASK) { + case UIIR_THRE_INT: // Transmit Holding Register Empty + fifo=0; + push_queue(); + break; + + case UIIR_CTI_INT: // Character Timeout Indicator + case UIIR_RDA_INT: // Receive Data Available + do { + int c = U0RBR; + receive(c); + } while (U0LSR & ULSR_RDR); + break; + + default: + U0LSR; + U0RBR; + break; + } // switch + VICVectAddr = 0; // Acknowledge Interrupt +} + +static inline int uart0_puts(char *astring,int length) +{ + while (queue_items == (QUEUESIZE-1)) {} ; + U0IER = 0; + queue[queue_tail] = malloc(length+sizeof(unsigned int)); + queue[queue_tail]->len = length; + memcpy(&queue[queue_tail]->content,astring,length); + enqueue(); + if (!running) + push_queue(); + U0IER |= BIT0 | BIT1; // enable RX irq + + // alternative without queue: +// int i; +// for (i=0;iconfig->speed + /* + * Baudrate calculation + * BR = PCLK (9 MHz) / (16 x 256 x DLM + DLL) x (1/(DIVADDVAL/MULVAL)) + */ + U0FDR = 0x92; // DIVADDVAL = 0010 = 2, MULVAL = 1001 = 9 + U0DLM = 0x00; + U0DLL = 0x04; + + U0LCR = 0x03; // DLAB = 0 + U0FCR = 0x07; // Enable and reset TX and RX FIFO + + /* irq */ + install_irq(UART0_INT, UART0_IRQHandler, 6); + U0IER |= BIT0 | BIT1; // enable RX+TX irq + return 1; +} + diff --git a/board/pttu/include/board.h b/board/pttu/include/board.h new file mode 100644 index 0000000000..850f8d1d17 --- /dev/null +++ b/board/pttu/include/board.h @@ -0,0 +1,56 @@ +/****************************************************************************** +Copyright 2008-2009, Freie Universitaet Berlin (FUB). All rights reserved. + +These sources were developed at the Freie Universitaet Berlin, Computer Systems +and Telematics group (http://cst.mi.fu-berlin.de). +------------------------------------------------------------------------------- +This file is part of FeuerWare. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +FeuerWare is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see http://www.gnu.org/licenses/ . +-------------------------------------------------------------------------------- +For further information and questions please use the web site + http://scatterweb.mi.fu-berlin.de +and the mailinglist (subscription via web site) + scatterweb@lists.spline.inf.fu-berlin.de +*******************************************************************************/ + +#ifndef __BOARD_H +#define __BOARD_H + +/** + * @ingroup pttu + * @{ + */ + +/** + * @file + * @brief PTTU Board + * + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @author Kaspar Schleiser + * @version $Revision$ + * + * @note $Id: board.h 664 2009-02-19 10:54:44Z baar $ + */ + +#include +#include + +#define VICIntEnClear VICIntEnClr + +void init_clks1(void); +void init_clks2(void); +void bl_init_clks(void); + +/** @} */ +#endif // __BOARD_H diff --git a/board/pttu/tools/jtag.txt b/board/pttu/tools/jtag.txt new file mode 100644 index 0000000000..586eea6745 --- /dev/null +++ b/board/pttu/tools/jtag.txt @@ -0,0 +1,14 @@ +compile openocd release v0.1: +[extract to somewhere] +./configure --prefix=CHANGEMEtowhatever --enable-ft2232_libftdi +make +make install + +to flash run from within board/pttu/tools: +./openocd-pttu.sh olimex-usb-jtag-tiny-a "mt_flash CHANGEME/absolute/path/to/hexfile/pttu.hex;shutdown" + + +to debug, first start the following from within board/pttu/tools: +./openocd-pttu.sh olimex-usb-jtag-tiny-a + +then just run "jam debug". this will flash bin/pttu.hex, run it and stop at the bootloader. diff --git a/board/pttu/tools/olimex-arm-usb-ocd.cfg b/board/pttu/tools/olimex-arm-usb-ocd.cfg new file mode 100644 index 0000000000..0aaba1d2bb --- /dev/null +++ b/board/pttu/tools/olimex-arm-usb-ocd.cfg @@ -0,0 +1,9 @@ +# +set CPUTAPID 0x4f1f0f0f + +jtag_speed 100 + +source [find interface/olimex-arm-usb-ocd.cfg] +#source [find target/lpc2148.cfg] +source lpc2378.cfg + diff --git a/board/pttu/tools/openocd-pttu.cfg b/board/pttu/tools/openocd-pttu.cfg new file mode 100644 index 0000000000..b58392f1ee --- /dev/null +++ b/board/pttu/tools/openocd-pttu.cfg @@ -0,0 +1,75 @@ +###### +# parts taken from Martin Thomas +# http://www.siwawi.arubi.uni-kl.de/avr_projects/arm_projects/openocd_intro/index.html +# + +set CPUTAPID 0x4f1f0f0f +jtag_speed 100 + +source [find cpu/lpc2387/tools/openocd-lpc2387.cfg] + +fast disable + +# +# scipts/macros/user commands - this is TCL (variant JIM): +# +proc mt_internal_rc {} { + jtag_khz 100 + reset run + sleep 100 + reset + halt + wait_halt 2 + # PLL disconnect PLLCON + mww 0xE01FC080 0x01 + mww 0xE01FC08C 0xAA + mww 0xE01FC08C 0x55 + # PLL disable PLLCON + mww 0xE01FC080 0x00 + mww 0xE01FC08C 0xAA + mww 0xE01FC08C 0x55 + # no prescaler CCLKCFG + mww 0xE01FC104 0x00 + # internal RC CLKSRCSEL + mww 0xE01FC10C 0x00 + #### main oscil. CLKSRCSEL + #### mww 0xE01FC10C 0x01 + # remap to internal flash + mww 0xE01FC040 0x01 + sleep 100 + jtag_khz 500 + flash probe 0 +} + +proc mt_flash_bin {IMGFILE OFFSET} { + mt_internal_rc + flash write_image erase $IMGFILE $OFFSET + sleep 100 + verify_image $IMGFILE $OFFSET + sleep 100 +} + +proc mt_flash_v {IMGFILE} { + mt_internal_rc + flash write_image erase $IMGFILE + sleep 100 + verify_image $IMGFILE + sleep 100 +} + +proc mt_flash {IMGFILE} { + mt_internal_rc + flash write_image erase $IMGFILE +} + +flash bank lpc2000 0x0 0x7d000 0 0 0 lpc2000_v2 4000 calc_checksum + +arm7_9 dcc_downloads enable + +gdb_flash_program enable + +init + +fast enable +jtag_khz 500 +debug_level 1 diff --git a/board/pttu/tools/openocd-pttu.sh b/board/pttu/tools/openocd-pttu.sh new file mode 100755 index 0000000000..95f11fa148 --- /dev/null +++ b/board/pttu/tools/openocd-pttu.sh @@ -0,0 +1,30 @@ +#/bin/bash + +if [ $# -le 0 ]; then + echo "usage: $0 [openocd interface name] [openocd args]" >&2 + echo " common interfaces: olimex-arm-usb-ocd olimex-jtag-tiny olimex-jtag-tiny-a" + echo "" + echo "using default olimex-jtag-tiny-a" + INTERFACE=olimex-jtag-tiny-a +else + INTERFACE=$1 + shift +fi + +if [ $# -ge 1 ]; then + COMMAND=$@ +else + COMMAND="debug_level 1" +fi + +if [ "${OS}" = "Windows_NT" ]; then + WINDOWS=1 +fi + +if [ "x${WINDOWS}x" = "xx" ]; then + xterm -e "openocd -s ../../.. -f interface/${INTERFACE}.cfg -f board/pttu/tools/openocd-pttu.cfg -c \"${COMMAND}\"|| read" & +else + echo ${COMMAND} + #cmd /C start "OpenOCD PTTU using ${INTERFACE}" + openocd-ftd2xx.exe -s ../../.. -f interface/${INTERFACE}.cfg -f board/pttu/tools/openocd-pttu.cfg -c "${COMMAND}" +fi diff --git a/board/pttu/tools/pttu_debug.gdb b/board/pttu/tools/pttu_debug.gdb new file mode 100644 index 0000000000..2c8ec0df14 --- /dev/null +++ b/board/pttu/tools/pttu_debug.gdb @@ -0,0 +1,15 @@ +#winheight regs 11 +set history save on +set history size 1000 +target remote localhost:3333 +monitor mt_internal_rc +load +compare-sections +monitor soft_reset_halt +set mem inaccessible-by-default off +monitor debug_level 0 + +break bootloader +continue +d b 1 + diff --git a/core/Jamfile b/core/Jamfile new file mode 100644 index 0000000000..64862e7ed7 --- /dev/null +++ b/core/Jamfile @@ -0,0 +1,37 @@ +# ****************************************************************************** +# Copyright 2009, Freie Universitaet Berlin (FUB). All rights reserved. +# +# These sources were developed at the Freie Universitaet Berlin, Computer +# Systems and Telematics group (http://cst.mi.fu-berlin.de). +# ------------------------------------------------------------------------------ +# This file is part of FeuerWare. +# +# This program is free software: you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation, either version 3 of the License, or (at your option) any later +# version. +# +# FeuerWare is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with +# this program. If not, see http://www.gnu.org/licenses/ . +# ------------------------------------------------------------------------------ +# For further information and questions please use the web site +# http://scatterweb.mi.fu-berlin.de +# and the mailinglist (subscription via web site) +# scatterweb@lists.spline.inf.fu-berlin.de +# ****************************************************************************** +# $Id$ + +SubDir TOP core ; + +Module core : kernel_init.c scheduler.c mutex.c msg.c queue.c + clist.c thread.c bitarithm.c ; + +Module hwtimer : hwtimer.c : hwtimer_cpu ; + +Module oneway_malloc : oneway_malloc.c ; + +UseModule core ; diff --git a/core/bitarithm.c b/core/bitarithm.c new file mode 100644 index 0000000000..bf9ee86991 --- /dev/null +++ b/core/bitarithm.c @@ -0,0 +1,65 @@ +/** + * bit arithmetic helper functions + * + * Copyright (C) 2010 Freie Universität Berlin + * + * This file subject to the terms and conditions of the GNU General Public + * License. See the file LICENSE in the top level directory for more details. + * + * \ingroup bitarithm + * \{ + * \file + * \author Kaspar Schleiser + * \} + */ + +#include + +#define ARCH_32_BIT (__INT_MAX__ == 2147483647) + +unsigned +number_of_highest_bit(unsigned v) +{ + register unsigned r; // result of log2(v) will go here + +#if ARCH_32_BIT + register unsigned shift; + + r = (v > 0xFFFF) << 4; v >>= r; + shift = (v > 0xFF ) << 3; v >>= shift; r |= shift; + shift = (v > 0xF ) << 2; v >>= shift; r |= shift; + shift = (v > 0x3 ) << 1; v >>= shift; r |= shift; + r |= (v >> 1); +#else + r = 0; + while (v >>= 1) // unroll for more speed... + r++; +#endif + + return r; +} +/*---------------------------------------------------------------------------*/ +unsigned +number_of_lowest_bit(register unsigned v) +{ + register unsigned r = 0; + + while( (v & 0x01) == 0 ) { + v >>= 1; + r++; + }; + + return r; +} +/*---------------------------------------------------------------------------*/ +unsigned +number_of_bits_set(unsigned v) +{ + unsigned c; // c accumulates the total bits set in v + for (c = 0; v; c++) { + v &= v - 1; // clear the least significant bit set + } + + return c; +} + diff --git a/core/clist.c b/core/clist.c new file mode 100644 index 0000000000..402b6db924 --- /dev/null +++ b/core/clist.c @@ -0,0 +1,102 @@ +/** + * simple circular linked list + * + * Copyright (C) 2010 Freie Universität Berlin + * + * This file subject to the terms and conditions of the GNU General Public + * License. See the file LICENSE in the top level directory for more details. + * + * @ingroup kernel + * @{ + * @file + * @author Kaspar Schleiser + * @} + */ + +#include +#include "clist.h" +#include + +/* inserts new_node after node */ +void clist_add(clist_node_t** node, clist_node_t* new_node) { + if (*node != NULL) { + new_node->next = (*node); + new_node->prev = (*node)->prev; + (*node)->prev->next = new_node; + (*node)->prev = new_node; + if ((*node)->prev == *node) { + (*node)->prev = new_node; + } + } else { + *node = new_node; + new_node->next = new_node; + new_node->prev = new_node; + } +} + +/* removes node. */ +void clist_remove(clist_node_t** list, clist_node_t *node) { + if (node->next != node) { + node->prev->next = node->next; + node->next->prev = node->prev; + if (node == *list) *list = node->next; + } else { + *list = NULL; + } +} + +void clist_print(clist_node_t* clist) { + clist_node_t *start = clist; + + while (clist != NULL ) { + printf("list entry: %u prev=%u next=%u\n", clist->data, clist->prev->data, clist->next->data); + clist = clist->next; + if (clist == start) break; + } +} + +/* +int main (int argc, char* argv[]) { + clist_node_t a; + clist_node_t b; + clist_node_t c; + + clist_node_t* clist = NULL; + + a.data = 0; + a.next = NULL; + a.prev = NULL; + + b.data = 1; + b.next = NULL; + b.prev = NULL; + + c.data = 2; + c.next = NULL; + c.prev = NULL; + + printf("adding a,b,c\n"); + clist_add(&clist,&a); + clist_add(&clist,&b); + clist_add(&clist,&c); + + clist_print(clist); + printf("\n"); + + printf("removing b...\n"); + clist_remove(&clist, &b); + + clist_print(clist); + printf("\n"); + + printf("removing a...\n"); + + clist_remove(&clist, &a); + clist_print(clist); + + printf("removing c...\n"); + + clist_remove(&clist, &c); + clist_print(clist); +} +*/ diff --git a/core/hwtimer.c b/core/hwtimer.c new file mode 100644 index 0000000000..01600a4f77 --- /dev/null +++ b/core/hwtimer.c @@ -0,0 +1,223 @@ +/** + * hardware timer abstraction + * + * Copyright (C) 2010 Freie Universität Berlin + * + * This file subject to the terms and conditions of the GNU General Public + * License. See the file LICENSE in the top level directory for more details. + * + * @ingroup kernel + * @{ + * @file + * @author Heiko Will + * @author Thomas Hillebrandt + * @author Kaspar Schleiser + * @} + */ + +#include +#include "hwtimer.h" +#include "hwtimer_cpu.h" +#include "hwtimer_arch.h" + +#include + +#define USE_NONBLOCKING_WAIT 1 +#if USE_NONBLOCKING_WAIT +//#include +#include "kernel.h" +#include "mutex.h" +#endif + +/*---------------------------------------------------------------------------*/ + +typedef struct hwtimer_t { + void (*callback)(void*); + void* data; + uint8_t checksum; +} hwtimer_t; + +#define HWTIMER_QUEUESIZE ARCH_MAXTIMERS +#define Q_FULL HWTIMER_QUEUESIZE + 1 + +static hwtimer_t timer[HWTIMER_QUEUESIZE]; +static int queue[HWTIMER_QUEUESIZE]; +static short queue_head = 0; +static short queue_tail = 0; +static short queue_items = 0; + +static uint8_t timer_id = 0; +static volatile long available_timers = 0; + +/*---------------------------------------------------------------------------*/ + +static int enqueue(int item) { + // Test if timer is already cleared: + // (hack to prevent race-condition with proccing timer (ISR) and manual hwtimer_remove) + if (available_timers & (1 << item)) { + return 1; + } + queue[queue_tail] = item; + available_timers |= (1 << item); + queue_tail = (queue_tail + 1) % HWTIMER_QUEUESIZE; + queue_items++; + if (queue_items == HWTIMER_QUEUESIZE) { + lpm_prevent_sleep &= ~LPM_PREVENT_SLEEP_HWTIMER; // Allow power down + } + return 1; +} + +static int dequeue(void) { + register int ret; + if (!queue_items) + return Q_FULL; + lpm_prevent_sleep |= LPM_PREVENT_SLEEP_HWTIMER; // No power down while a timer is active + queue_items--; + ret = queue[queue_head]; + queue[queue_head] = 0xff; // Mark as empty + available_timers &= ~(1 << ret); + queue_head = (queue_head + 1) % HWTIMER_QUEUESIZE; + return ret; +} + +static void multiplexer(int source) { + enqueue(source); + timer[source].callback(timer[source].data); +} + +static void hwtimer_releasemutex(void* mutex) { + mutex_unlock((mutex_t*)mutex, true); +} + +void hwtimer_spin(unsigned long ticks) +{ + unsigned long co = hwtimer_arch_now() + ticks; + while (hwtimer_arch_now() > co); + while (hwtimer_arch_now() < co); +} + +/*---------------------------------------------------------------------------*/ + +void hwtimer_init(void) { + hwtimer_init_comp(F_CPU); +} + +/*---------------------------------------------------------------------------*/ + +void hwtimer_init_comp(uint32_t fcpu) { + int i; + queue_head = 0; + queue_tail = 0; + queue_items = 0; + timer_id = 0; + available_timers = 0; + hwtimer_arch_init(multiplexer, fcpu); + for (i = 0; i < HWTIMER_QUEUESIZE; i++) { + queue[i] = 0xff; // init queue as empty + } + for (i = 0; i < HWTIMER_QUEUESIZE; i++) { + enqueue(i); + } +} + +/*---------------------------------------------------------------------------*/ + +int hwtimer_active(void) { + return queue_items != HWTIMER_QUEUESIZE; +} + +/*---------------------------------------------------------------------------*/ + +unsigned long hwtimer_now(void) +{ + return hwtimer_arch_now(); +} + +/*---------------------------------------------------------------------------*/ + +void hwtimer_wait(unsigned long ticks) +{ + mutex_t mutex; + if (ticks <= 4 || inISR()) { + hwtimer_spin(ticks); + return; + } + mutex_init(&mutex); + mutex_lock(&mutex); + // -2 is to adjust the real value + int res = hwtimer_set(ticks-2, hwtimer_releasemutex, &mutex); + if (res == -1) { + mutex_unlock(&mutex, true); + hwtimer_spin(ticks); + return; + } + mutex_lock(&mutex); +} + +/*---------------------------------------------------------------------------*/ + +static int _hwtimer_set(unsigned long offset, void (*callback)(void*), void *ptr, bool absolute) +{ + if (! inISR() ) dINT(); +// hwtimer_arch_disable_interrupt(); + int x = dequeue(); + if (x == Q_FULL) { + printf("[KT] no timers left\n"); +// hwtimer_arch_enable_interrupt(); + if (! inISR()) eINT(); + return -1; + } + + timer[x].callback = callback; + timer[x].data = ptr; + timer[x].checksum = ++timer_id; + + if (absolute) + hwtimer_arch_set_absolute(offset, x); + else + hwtimer_arch_set(offset, x); + + //hwtimer_arch_enable_interrupt(); + if (! inISR()) eINT(); + return (timer[x].checksum << 8) + x; +} + +int hwtimer_set(unsigned long offset, void (*callback)(void*), void *ptr) { + return _hwtimer_set(offset, callback, ptr, false); +} + +int hwtimer_set_absolute(unsigned long offset, void (*callback)(void*), void *ptr) { + return _hwtimer_set(offset, callback, ptr, true); +} + + +/*---------------------------------------------------------------------------*/ + +int hwtimer_remove(int x) +{ + int t = x & 0xff; + uint8_t checksum = (uint8_t) (x >> 8); + if (t < 0 || t >= HWTIMER_QUEUESIZE || timer[t].callback == NULL || timer[t].checksum != checksum) { + return -1; + } + hwtimer_arch_disable_interrupt(); + hwtimer_arch_unset(t); + enqueue(t); + timer[t].callback = NULL; + hwtimer_arch_enable_interrupt(); + return 1; +} + +/*---------------------------------------------------------------------------*/ + +void hwtimer_debug(int timer) +{ + printf("queue size: %i\n", queue_items); + printf("available timers: %lu\n", available_timers); + int t = timer & 0xff; + if (available_timers & (1 << t)) { + printf("timer %i is: not set\n", timer); + } else { + printf("timer %i is: set\n", timer); + } +} diff --git a/core/include/atomic.h b/core/include/atomic.h new file mode 100644 index 0000000000..c24981f9f1 --- /dev/null +++ b/core/include/atomic.h @@ -0,0 +1,28 @@ +/** + * atomic function declarations + * + * Copyright (C) 2010 Freie Universität Berlin + * + * This file subject to the terms and conditions of the GNU General Public + * License. See the file LICENSE in the top level directory for more details. + * + * @ingroup kernel + * @{ + * @file + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @author Kaspar Schleiser + */ + +#ifndef _ATOMIC_H +#define _ATOMIC_H + +/** + * @brief sets "val" to "set", returns old "val", atomically + */ + +extern unsigned int atomic_set_return(unsigned int* val, unsigned int set); + +/** + * @} + */ +#endif /* _ATOMIC_H */ diff --git a/core/include/bitarithm.h b/core/include/bitarithm.h new file mode 100644 index 0000000000..de06c50241 --- /dev/null +++ b/core/include/bitarithm.h @@ -0,0 +1,98 @@ +/** + * Helper functions for bit arithmetic + * + * Copyright (C) 2010 Freie Universität Berlin + * + * This file subject to the terms and conditions of the GNU General Public + * License. See the file LICENSE in the top level directory for more details. + * + * @defgroup bitarithm Bit Arithmetic + * @ingroup lib + * @{ + * @file + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @author Kaspar Schleiser + */ + +#ifndef BITARITHM_H_ +#define BITARITHM_H_ + +#define BS(val, bit) ((val) & (bit)) +#define BS_COND(condition, target, mask) (target) ^= ( (-(condition) ^ (target)) & (mask) ) +#define SETBIT(val, bit) val |= (bit) +#define CLRBIT(val, bit) val &= (~(bit)) + +/** + * @name Single Bit Defines + * @{ + */ +#ifndef BIT0 +#define BIT0 0x00000001 +#define BIT1 0x00000002 +#define BIT2 0x00000004 +#define BIT3 0x00000008 +#define BIT4 0x00000010 +#define BIT5 0x00000020 +#define BIT6 0x00000040 +#define BIT7 0x00000080 +#define BIT8 0x00000100 +#define BIT9 0x00000200 +#define BIT10 0x00000400 +#define BIT11 0x00000800 +#define BIT12 0x00001000 +#define BIT13 0x00002000 +#define BIT14 0x00004000 +#define BIT15 0x00008000 +#endif +#ifndef BIT16 +#define BIT16 0x00010000 +#define BIT17 0x00020000 +#define BIT18 0x00040000 +#define BIT19 0x00080000 +#define BIT20 0x00100000 +#define BIT21 0x00200000 +#define BIT22 0x00400000 +#define BIT23 0x00800000 +#define BIT24 0x01000000 +#define BIT25 0x02000000 +#define BIT26 0x04000000 +#define BIT27 0x08000000 +#define BIT28 0x10000000 +#define BIT29 0x20000000 +#define BIT30 0x40000000 +#define BIT31 0x80000000 +#endif +/** @} */ + +/** + * @brief Returns the number of the highest '1' bit in a value + * @param[in] v Input value + * @return Bit Number + * + * Source: http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogObvious + */ +unsigned number_of_highest_bit(unsigned v); + +/** + * @brief Returns the number of the lowest '1' bit in a value + * @param[in] v Input value + * @return Bit Number + * + * Source: http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogObvious + */ +unsigned number_of_lowest_bit(register unsigned v); + +/** + * @brief Returns the number of bits set in a value + * @param[in] v Input value + * @return Number of set bits + * + * Source: http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogObvious + */ +unsigned number_of_bits_set(unsigned v); + +/** + * @} + */ + +#endif /* BITARITHM_H_ */ diff --git a/core/include/clist.h b/core/include/clist.h new file mode 100644 index 0000000000..2dac25f09b --- /dev/null +++ b/core/include/clist.h @@ -0,0 +1,47 @@ +/** + * Circular linked list implementation + * + * Used by the scheduler + * + * Copyright (C) 2010 Freie Universität Berlin + * + * This file subject to the terms and conditions of the GNU General Public + * License. See the file LICENSE in the top level directory for more details. + * + * @ingroup lib + * @{ + * @file + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @author Kaspar Schleiser + */ + +#ifndef __CLIST_H +#define __CLIST_H + +typedef struct clist_node_t { + struct clist_node_t *next; + struct clist_node_t *prev; + unsigned int data; +} clist_node_t; + +/* inserts new_node after node */ +void clist_add(clist_node_t** node, clist_node_t* new_node); + +/* removes node. */ +void clist_remove(clist_node_t** list, clist_node_t *node); + +/* advances the circle list. second list entry will be first, first is last. */ +/*void clist_advance(clist_node_t** list);*/ + +static inline void clist_advance(clist_node_t** list) { + *list = (*list)->next; +} + + +void clist_print(clist_node_t* clist); + +/** + * @} + */ +#endif // __CLIST_H + diff --git a/core/include/debug.h b/core/include/debug.h new file mode 100644 index 0000000000..d680fd5aa7 --- /dev/null +++ b/core/include/debug.h @@ -0,0 +1,25 @@ +/** + * Debug-Header. + * + * #define ENABLE_DEBUG, include this and then use DEBUG as printf you can toggle. + * + * Copyright (C) 2010 Freie Universität Berlin + * + * This file subject to the terms and conditions of the GNU General Public + * License. See the file LICENSE in the top level directory for more details. + * + * @ingroup kernel + * @{ + * @file + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @author Kaspar Schleiser + * @} + */ + +#include + +#ifdef ENABLE_DEBUG +#define DEBUG(...) printf(__VA_ARGS__) +#else +#define DEBUG(...) +#endif diff --git a/core/include/flags.h b/core/include/flags.h new file mode 100644 index 0000000000..97da2efa8a --- /dev/null +++ b/core/include/flags.h @@ -0,0 +1,27 @@ +/** + * (misc flag definitions) + * + * Copyright (C) 2010 Freie Universität Berlin + * + * This file subject to the terms and conditions of the GNU General Public + * License. See the file LICENSE in the top level directory for more details. + * + * @ingroup kernel + * @{ + * @file + * @author Kaspar Schleiser + */ + +#ifndef _FLAGS_H +#define _FLAGS_H + +#define CREATE_WOUT_YIELD 4 +#define CREATE_SLEEPING 1 +#define EXPECTS_REPLY 2 +#define CREATE_STACKTEST 8 + +/** + * @} + */ +#endif // _FLAGS_H + diff --git a/core/include/hwtimer.h b/core/include/hwtimer.h new file mode 100644 index 0000000000..39f2c0f189 --- /dev/null +++ b/core/include/hwtimer.h @@ -0,0 +1,129 @@ +/** + * Hardware timer interface + * + * The Hardware timers are directly mapped to hardware timers with minimum + * latency. They are intended for short intervals and to be used in time + * critical low-level drivers (e.g. radio). hwtimer callbacks are run in the + * interrupt context and must use the shortest possible execution time (e.g. + * set a flag and trigger a worker thread). + * + * hwtimer must not be used within applications, use \ref swtimer + * instead. + * + * @defgroup hwtimer Hardware timer + * @ingroup kernel + * @{ + * @file + * + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @author Heiko Will + * @author Kaspar Schleiser + * @author Michael Baar + * + * Copyright (C) 2010 Freie Universität Berlin + * + * This file subject to the terms and conditions of the GNU General Public + * License. See the file LICENSE in the top level directory for more details. + */ + +#ifndef __HWTIMER_H +#define __HWTIMER_H + +#include +#include "hwtimer_cpu.h" + +/** + * @def HWTIMER_SPEED + * @brief Number of kernel timer ticks per second + */ +#ifndef HWTIMER_SPEED +#warning "HWTIMER_SPEED undefined. Set HWTIMER_SPEED to number of ticks per second for the current architecture." +#endif + +/** + * @brief Convert microseconds to kernel timer ticks + * @param[in] us number of microseconds + * @return kernel timer ticks + */ +#define HWTIMER_TICKS(us) (us / (1000000L / HWTIMER_SPEED)) + +/** + * @brief Convert ticks to microseconds + * @param[in] ticks number of ticks + * @return microseconds + */ +#define HWTIMER_TICKS_TO_US(ticks) (ticks * (1000000L/HWTIMER_SPEED)) + +/** + * @def HWTIMER_MAXTICKS + * @brief Maximum hwtimer tick count (before overflow) + */ +#ifndef HWTIMER_MAXTICKS +#warning "HWTIMER_MAXTICKS undefined. Set HWTIMER_MAXTICKS to maximum number of ticks countable on the current architecture." +#endif + +/** + * @brief microseconds before hwtimer overflow + */ +#define HWTIMER_OVERFLOW_MICROS() (1000000L / HWTIMER_SPEED * HWTIMER_MAXTICKS) + +typedef uint32_t timer_tick_t; + +void hwtimer_init(void); +void hwtimer_init_comp(uint32_t fcpu); + +/** + * @brief Set a kernel timer + * @param[in] offset Offset until callback invocation in timer ticks + * @param[in] callback Callback function + * @param[in] ptr Argument to callback function + * @return timer id + */ +int hwtimer_set(unsigned long offset, void (*callback)(void*), void *ptr); + +/** + * @brief Set a kernel timer + * @param[in] absolute Absolute timer counter value for invocation of handler + * @param[in] callback Callback function + * @param[in] ptr Argument to callback function + * @return timer id + */ +int hwtimer_set_absolute(unsigned long absolute, void (*callback)(void*), void *ptr); + +/** + * @brief Remove a kernel timer + * @param[in] t Id of timer to remove + * @retval 1 on success + */ +int hwtimer_remove(int t); + +/** + * @brief Delay current thread + * @param[in] ticks Number of kernel ticks to delay + */ +void hwtimer_wait(unsigned long ticks); + +/** + * @brief Delay current thread, spinning. Use only in interrupts for VERY short delays! + * @param[in] ticks Number of kernel ticks to delay + */ +void hwtimer_spin(unsigned long ticks); + +int hwtimer_active(void); + +/* internal */ + +/** + * @brief TODO + * @internal + */ +uint32_t hwtimer_now(); +void hwtimer_cpu_init(void (*handler)(int), uint32_t fcpu); +void hwtimer_t0_disable_interrupt(void); +void hwtimer_t0_enable_interrupt(void); +void hwtimer_t0_set(unsigned long value, short timer); +void hwtimer_t0_unset(short timer); +unsigned long hwtimer_t0_now(void); + +/** @} */ +#endif /* __HWTIMER_H */ diff --git a/core/include/hwtimer_arch.h b/core/include/hwtimer_arch.h new file mode 100644 index 0000000000..ab7e841400 --- /dev/null +++ b/core/include/hwtimer_arch.h @@ -0,0 +1,62 @@ +/** + * Hardware timer abstraction + * + * Copyright (C) 2010 Freie Universität Berlin + * + * This file subject to the terms and conditions of the GNU General Public + * License. See the file LICENSE in the top level directory for more details. + * + * @ingroup kernel + * @{ + * @file + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @author Thomas Hillebrandt + * @author Heiko Will + * @author Kaspar Schleiser + */ +#ifndef HWTIMER_ARCH_H_ +#define HWTIMER_ARCH_H_ + +#include + +/** + * Initialize architecture dependent kernel timer support. + */ +void hwtimer_arch_init(void (*handler)(int), uint32_t fcpu); + +/** + * Enable interrupts of hardware timers. + */ +void hwtimer_arch_enable_interrupt(void); + +/** + * Disable interrupts of hardware timers. + */ +void hwtimer_arch_disable_interrupt(void); + +/** + * Set a kernel timer to raise an interrupt after ::offset kernel timer ticks + * from now. + */ +void hwtimer_arch_set(unsigned long offset, short timer); + +/** + * Set a kernel timer to raise an interrupt after ::offset kernel timer ticks + * from now. + */ +void hwtimer_arch_set_absolute(unsigned long value, short timer); + +/** + * Unset the kernel timer with the given timer ID. + */ +void hwtimer_arch_unset(short timer); + +/** + * Get the current tick count of the default hardware timer. + */ +unsigned long hwtimer_arch_now(void); + +/** + * @} + */ +#endif /* HWTIMER_ARCH_H_ */ diff --git a/core/include/irq.h b/core/include/irq.h new file mode 100644 index 0000000000..dddab56206 --- /dev/null +++ b/core/include/irq.h @@ -0,0 +1,59 @@ +#ifndef IRQ_H_ +#define IRQ_H_ + +/** + * @defgroup irq IRQ Handling + * @ingroup kernel + * + * Provides an API to control interrupt processing. + * + * @{ + */ + +/** + * @file + * @brief IRQ driver interface + * + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @author Michael Baar + * @version $Revision: 1410 $ + * + * @note $Id$ + */ + +#include + +/** + * @brief This function sets the IRQ disable bit in the status register + * @return previous value of status register + */ +unsigned disableIRQ(void); + +/** + * @brief This function clears the IRQ disable bit in the status register + * @return previous value of status register + * + * @example irq-driver-example.c + * @see restoreIRQ + */ +unsigned enableIRQ(void); + +/** + * @brief This function restores the IRQ disable bit in the status register + * to the value contained within passed state + * @param state state to restore + * @return previous state + * + * @example irq-driver-example.c + * @see disableIRQ + */ +void restoreIRQ(unsigned state); + +/** + * @brief Checks if the mcu is currently processing an interrupt. + * @return true, if in interrupt service routine + */ +int inISR(void); + +/** @} */ // end of group dev_irq +#endif /* IRQ_H_ */ diff --git a/core/include/kernel.h b/core/include/kernel.h new file mode 100644 index 0000000000..69e12e6dd8 --- /dev/null +++ b/core/include/kernel.h @@ -0,0 +1,96 @@ +/** + * Kernel compile time configuration + * + * Copyright (C) 2010 Freie Universität Berlin + * + * This file subject to the terms and conditions of the GNU General Public + * License. See the file LICENSE in the top level directory for more details. + * + * @ingroup kernel + * @{ + * @file + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @author Kaspar Schleiser + */ + +#ifndef KERNEL_H_ +#define KERNEL_H_ + +/** + * @defgroup kernel Kernel + * @{ + */ + +#include +#include "tcb.h" +#include "cpu.h" +#include "flags.h" +#include "scheduler.h" +#include "cpu-conf.h" + +/* ------------------------------------------------------------------------- */ +/** + * @name Kernel Compile-Time Configuration + * @{ + */ + +/** + * @def KERNEL_CONF_STACKSIZE_DEFAULT + * @ingroup conf + * @brief A reasonable default stack size that will suffice most smaller tasks + */ +#ifndef KERNEL_CONF_STACKSIZE_DEFAULT +#error KERNEL_CONF_STACKSIZE_DEFAULT must be defined per CPU +#endif + +/** + * @def KERNEL_CONF_STACKSIZE_IDLE + * @ingroup conf + * @brief Size of the idle task's stack in bytes + */ +#ifndef KERNEL_CONF_STACKSIZE_IDLE +#error KERNEL_CONF_STACKSIZE_IDLE must be defined per CPU +#endif + +/** + * @def KERNEL_CONF_STACKSIZE_MAIN + * @ingroup conf + * @brief Size of the main task's stack in bytes + */ +#ifndef KERNEL_CONF_STACKSIZE_MAIN +#define KERNEL_CONF_STACKSIZE_MAIN KERNEL_CONF_STACKSIZE_DEFAULT +#endif + +/** @} */ +/* ------------------------------------------------------------------------- */ + + +#define PID_NULL -1 + +#define PRIORITY_MIN SCHED_PRIO_LEVELS-1 + +#define PRIORITY_IDLE PRIORITY_MIN +#define PRIORITY_MAIN PRIORITY_MIN-1 +#define PRIORITY_CMD_THREADS PRIORITY_MIN-2 ///< all cmd handler threads +#define PRIORITY_CBD PRIORITY_MIN-3 +#define PRIORITY_CMDD PRIORITY_MIN-4 ///< cmdengine demon +#define PRIORITY_PRINTTHREAD PRIORITY_MIN-5 ///< mprint worker thread +#define PRIORITY_HAL PRIORITY_MIN-6 +#define PRIORITY_UTIMER PRIORITY_MIN-7 +#define PRIORITY_MMREQ PRIORITY_MIN-8 +#define PRIORITY_CC1100 PRIORITY_MIN-9 + +/** + * @brief Check whether called from interrupt service routine + * + * @return true if called from within interrupt + * @return false if not. + */ +int inISR(void); + +#define LPM_PREVENT_SLEEP_HWTIMER BIT1 + +extern volatile int lpm_prevent_sleep; + +/** @} */ +#endif /* KERNEL_H_ */ diff --git a/core/include/kernel_intern.h b/core/include/kernel_intern.h new file mode 100644 index 0000000000..a58205319e --- /dev/null +++ b/core/include/kernel_intern.h @@ -0,0 +1,27 @@ +/** + * @ingroup kernel + * @{ + * @file + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @author Kaspar Schleiser + */ + +/* + * kernel_intern.h + * + * Created on: 10.02.09 + * Author: kaspar + */ + +#ifndef KERNEL_INTERN_H_ +#define KERNEL_INTERN_H_ + +void kernel_init(void); +void board_init_drivers(); +char *fk_stack_init(void *task_func, void *stack_start); +void fk_task_exit(void); +void fk_print_stack (); +int fk_measure_stack_free(char* stack); + +/** @} */ +#endif /* KERNEL_INTERN_H_ */ diff --git a/core/include/lpm.h b/core/include/lpm.h new file mode 100644 index 0000000000..95b2d7b5be --- /dev/null +++ b/core/include/lpm.h @@ -0,0 +1,60 @@ +#ifndef LPM_H_ +#define LPM_H_ + +/** + * @defgroup lpm Power Management + * @ingroup kernel + * @{ + */ + +/** + * @file + * @brief Power Management Interface + * + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @version $Revision$ + * + * This interface needs to be implemented for each platform. + * + * @note $Id$ + */ + + +/** + * @brief Available power modes + */ +enum lpm_mode { + LPM_ON, ///< MCU is active + LPM_IDLE, ///< MCU is idle + LPM_SLEEP, ///< MCU in sleep mode + LPM_POWERDOWN, ///< MCU is powered down + LPM_OFF ///< MCU is off +}; + +/** + * @brief Initialization of power management (including clock setup) + * + * This function is invoked once during boot. + */ +void lpm_init(void); + +/** + * @brief Switches the MCU to a new power mode + * @param[in] target Target power mode + */ +enum lpm_mode lpm_set(enum lpm_mode target); + +void lpm_awake(void); + +void lpm_begin_awake(void); +void lpm_end_awake(void); + +/** + * @brief Returns the current power mode + * @return Current power mode + */ +enum lpm_mode lpm_get(void); + + +/** @} */ +#endif /* LPM_H_ */ diff --git a/core/include/msg.h b/core/include/msg.h new file mode 100644 index 0000000000..4a0504c7f7 --- /dev/null +++ b/core/include/msg.h @@ -0,0 +1,111 @@ +/** + * @defgroup kernel_msg Messaging / IPC + * @ingroup kernel + * @{ + */ + +/** + * @file + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @author Kaspar Schleiser + */ + +#ifndef __MSG_H +#define __MSG_H + +#include +#include + +#define MESSAGE_SENT 1 +#define MESSAGE_PROCESS_NOT_WAITING 0 +#define MESSAGE_PROCESS_UNKNOWN 2 + +/** + * @brief Describes a message object which can be sent between threads. + * + * User can set type and one of content.ptr and content.value. (content is a union) + * The meaning of type and the content fields is totally up to the user, + * the corresponding fields are never read by the kernel. + * + */ +typedef struct msg { + uint16_t sender_pid; ///< PID of sending thread. Will be filled in by msg_send + uint16_t type; ///< Type field. + union { + char *ptr; ///< pointer content field + uint32_t value; ///< value content field + } content; +} msg; + + +/** + * @brief Send a message. + * + * This function sends a message to another thread. + * The msg structure has to be allocated (e.g. on the stack) + * before calling the function and can be freed afterwards. + * If called from an interrupt, this function will never block. + * + * @param m Pointer to message structure + * @param target_pid PID of target thread + * @param block If true and receiver is not receive-blocked, function will block. If not, function returns. + * + * @return 1 if sending was successfull + * @return 0 if receiver is not waiting and block == false + * @return -1 on error (invalid PID) + */ +int msg_send(msg* m, unsigned int target_pid, bool block); + + +/** + * @brief Send message from interrupt. + * + * Will be automatically chosen instead of msg_send if inISR() == true + * + * @param m pointer to message structure + * @param target_pid PID of target thread + * + * @return 1 if sending was successfull + * @return 0 if receiver is not waiting and block == false + */ +int msg_send_int(msg* m, unsigned int target_pid); + + +/** + * @brief Receive a message. + * + * This function blocks until a message was received. + * @param m pointer to preallocated msg + * + * @return 1 Function always succeeds or blocks forever. + */ +int msg_receive(msg* m); + +/** + * @brief Send a message, block until reply received. + * + * This function sends a message to target_pid and then blocks until target has sent a reply. + * @param m pointer to preallocated msg + * @param reply pointer to preallocated msg. Reply will be written here. + * @param target pid the pid of the target process + * @return 1 if successful + */ +int msg_send_receive(msg *m, msg *reply, unsigned int target_pid); + +/** + * @brief Replies to a message. + * + * Sender must have sent the message with msg_send_receive(). + * + * @param m msg to reply to. + * @param reply message that target will get as reply + * + * @return 1 if succcessful + * qreturn 0 on error + */ +int msg_reply(msg *m, msg *reply); + +uint16_t msg_alloc_event(void); + +/** @} */ +#endif /* __MSG_H */ diff --git a/core/include/mutex.h b/core/include/mutex.h new file mode 100644 index 0000000000..5140881ee4 --- /dev/null +++ b/core/include/mutex.h @@ -0,0 +1,79 @@ +/** + * @defgroup mutex Mutexes / Synchronization + * @ingroup kernel + * @{ + */ + +/** + * @file + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @author Kaspar Schleiser + */ + +#ifndef _MUTEX_H +#define _MUTEX_H + +#include "queue.h" +#include "tcb.h" + +/** + * @brief Mutex structure. Should never be modified by the user. + */ +typedef struct mutex_t { + /* fields are managed by mutex functions, don't touch */ + unsigned int val; // @internal + queue_node_t queue; // @internal +} mutex_t; + +/** + * @brief Initializes a mutex object + * @param mutex pre-allocated mutex structure. + * @return Always returns 1, always succeeds. + */ +int mutex_init(struct mutex_t* mutex); + + +/** + * @brief Tries to get a mutex, non-blocking. + * + * @param mutex Mutex-Object to lock. Has to be initialized first. + * + * @return 1 if mutex was unlocked, now it is locked. + * @return 0 if the mutex was locked. + */ +int mutex_trylock(struct mutex_t* mutex); + +/** + * @brief Tries to get a mutex, blocking. + * + * @param mutex Mutex-Object to lock. Has to be initialized first. + * + * @return 1 getting the mutex was successful + * @return <1 there was an error. + */ +int mutex_lock(struct mutex_t* mutex); + +/** + * @brief Unlocks the mutex. + * + * @param mutex Mutex-Object to unlock. + * + * @param yield If yield==MUTEX_YIELD, force context-switch after waking up other waiter. + */ +void mutex_unlock(struct mutex_t* mutex, int yield); + +#define MUTEX_YIELD 1 +#define MUTEX_INISR 2 + +/********************** + * internal functions * + **********************/ + +void mutex_wake_waiters(struct mutex_t *mutex, int yield); +void mutex_wait(struct mutex_t *mutex); + +/*struct mutex_entry_t * mutex_create_entry(int prio, struct tcb *proc);*/ + +/** @} */ +#endif /* _MUTEX_H */ + diff --git a/core/include/oneway_malloc.h b/core/include/oneway_malloc.h new file mode 100644 index 0000000000..6a8df5f8e7 --- /dev/null +++ b/core/include/oneway_malloc.h @@ -0,0 +1,18 @@ +/** + * @ingroup kernel + * @{ + * @file + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @author Kaspar Schleiser + */ + +#ifndef _MALLOC_H +#define _MALLOC_H + +#include + +void* _malloc(size_t size); +void _free (void* ptr); + +/** @} */ +#endif /* _MALLOC_H */ diff --git a/core/include/queue.h b/core/include/queue.h new file mode 100644 index 0000000000..d7a122e506 --- /dev/null +++ b/core/include/queue.h @@ -0,0 +1,28 @@ +/** + * @ingroup kernel + * @{ + * @file + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @author Kaspar Schleiser + */ + +#ifndef __QUEUE_H +#define __QUEUE_H + +#include "queue.h" + +typedef struct queue_node_t { + struct queue_node_t *next; + unsigned int data; + unsigned int priority; +} queue_node_t; + +queue_node_t* queue_remove_head(queue_node_t* root); +void queue_add_tail(queue_node_t* root, queue_node_t* new_obj); +void queue_add_head(queue_node_t* root, queue_node_t* new_obj); +queue_node_t *queue_remove_head(queue_node_t* root); +void queue_priority_add(queue_node_t* root, queue_node_t* new_obj); +void queue_priority_add_generic(queue_node_t* root, queue_node_t* new_obj, int(*cmp)(queue_node_t*,queue_node_t*)) ; + +/** @} */ +#endif // __QUEUE_H diff --git a/core/include/scheduler.h b/core/include/scheduler.h new file mode 100644 index 0000000000..afff055c97 --- /dev/null +++ b/core/include/scheduler.h @@ -0,0 +1,50 @@ +/** + * @ingroup kernel + * @{ + * @file + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @author Kaspar Schleiser + */ + +#ifndef _SCHEDULER_H +#define _SCHEDULER_H + +#include +#include +#include "tcb.h" + +#define MAXTHREADS 32 + +#ifdef ARCH_32_BIT +#define SCHED_PRIO_LEVELS 32 +#else +#define SCHED_PRIO_LEVELS 16 +#endif + +void scheduler_init(); +void fk_schedule(); + +void sched_set_status(tcb *process, unsigned int status); + +volatile unsigned int fk_context_switch_request; + +volatile tcb *fk_threads[MAXTHREADS]; +volatile tcb *fk_thread; + +extern volatile int num_tasks; +volatile int fk_pid; + +//#define SCHEDSTATISTICS +#if SCHEDSTATISTICS + + typedef struct schedstat { + unsigned int laststart; + unsigned int schedules; + unsigned int runtime; + }schedstat; + + extern schedstat pidlist[MAXTHREADS]; +#endif + +/** @} */ +#endif // _SCHEDULER_H diff --git a/core/include/tcb.h b/core/include/tcb.h new file mode 100644 index 0000000000..4e077f6303 --- /dev/null +++ b/core/include/tcb.h @@ -0,0 +1,54 @@ +/** + * @ingroup kernel + * @{ + * @file + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @author Kaspar Schleiser + */ + +/* + * tcb.h + * + * Created on: 19.08.2008 + * Author: heiko, kaspar + */ + +#ifndef TCB_H_ +#define TCB_H_ + +#include +#include "queue.h" +#include "clist.h" + + +/* uneven means has to be on runqueue */ +#define STATUS_NOT_FOUND 0 +#define STATUS_ON_RUNQUEUE 1 +#define STATUS_RUNNING 2 + STATUS_ON_RUNQUEUE +#define STATUS_PENDING 4 + STATUS_ON_RUNQUEUE +#define STATUS_STOPPED 8 +#define STATUS_SLEEPING 16 +#define STATUS_MUTEX_BLOCKED 32 +#define STATUS_RECEIVE_BLOCKED 64 +#define STATUS_SEND_BLOCKED 128 +#define STATUS_REPLY_BLOCKED 256 + +typedef struct tcb { + char* sp; + unsigned int status; + + uint16_t pid; + uint16_t priority; + + void* wait_data; + queue_node_t msg_queue; + + clist_node_t rq_entry; + + const char* name; + char* stack_start; + int stack_size; +} tcb; + +/** @} */ +#endif /* TCB_H_ */ diff --git a/core/include/thread.h b/core/include/thread.h new file mode 100644 index 0000000000..1ad4fc06c4 --- /dev/null +++ b/core/include/thread.h @@ -0,0 +1,69 @@ +#ifndef __THREAD_H +#define __THREAD_H + +/** + * @defgroup thread Threading + * @ingroup kernel + * @{ + */ + +/** + * @file + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @author Kaspar Schleiser + */ + + +/** + * @brief Creates a new thread. + * This version will allocate it's stack itself using malloc. + * + * @param stacksize + * @param flags Options: + * YIELD: force context switch. + * CREATE_SLEEPING: set new thread to sleeping state, thread must be woken up manually. + * CREATE_STACKTEST: initialize stack with values needed for stack overflow testing. + * + * @param priority Priority of newly created thread. Lower number means higher + * priority. 0 means highest possible priority. Lowest priority is + * PRIORITY_IDLE-1, usually 30. + * + * @return returns <0 on error, pid of newly created task else. +*/ +int thread_create(int stacksize, char priority, int flags, void (*function) (void), const char* name); + +/** + * @brief returns the status of a process. + * @return STATUS_NOT_FOUND if pid is unknown + */ +unsigned int thread_getstatus(int pid); + +/** + * @brief Puts the current thread into sleep mode. Has to be woken up externally. + */ +void thread_sleep(); + +/** + * @brief Wakes up a sleeping thread. + * @param pid The PID of the thread to be woken up + * @return STATUS_NOT_FOUND if pid is unknown or not sleeping + */ +int thread_wakeup(int pid); + + +/** + * @brief Returns the process ID of the currently running thread. + * @return Obviously you are not a golfer. + */ +int thread_getpid(); + +/** + * @brief Measures the stack usage of a stack. + * Only works if the thread was created with the flag CREATE_STACKTEST. + * + * @param stack The stack you want to measure. try fk_thread->stack_start. + */ +int fk_measure_stack_free(char* stack); + +/* @} */ +#endif /* __THREAD_H */ diff --git a/core/kernel_init.c b/core/kernel_init.c new file mode 100644 index 0000000000..e8a9e57f51 --- /dev/null +++ b/core/kernel_init.c @@ -0,0 +1,85 @@ +/** + * platform-independent kernel initialization + * + * Copyright (C) 2010 Freie Universität Berlin + * + * This file subject to the terms and conditions of the GNU General Public + * License. See the file LICENSE in the top level directory for more details. + * + * @ingroup kernel + * @{ + * @file + * @author Kaspar Schleiser + * @} + */ + +#include +#include +#include +#include +#include "tcb.h" +#include "kernel.h" +#include "kernel_intern.h" +#include "scheduler.h" +#include "flags.h" +#include "cpu.h" +#include "lpm.h" +#include "thread.h" +#include "hwtimer.h" + +#ifdef MODULE_AUTO_INIT +#include +#endif + +#define ENABLE_DEBUG +#include "debug.h" + +volatile tcb *fk_threads[MAXTHREADS]; +volatile tcb *fk_thread; +volatile int lpm_prevent_sleep = 0; + +extern void main(void); +extern void fk_switch_context_exit(void); + +void fk_idle(void) { + while(1) { + if (lpm_prevent_sleep) { + lpm_set(LPM_IDLE); + } + else { + lpm_set(LPM_IDLE); +// lpm_set(LPM_SLEEP); +// lpm_set(LPM_POWERDOWN); + } + } +} + +const char *main_name = "main"; +const char *idle_name = "idle"; + +#ifdef MODULE_AUTO_INIT +#define MAIN_FUNC auto_init +#else +#define MAIN_FUNC main +#endif + +void kernel_init(void) +{ + dINT(); + printf("kernel_init(): This is Fire_Kernel 0.0!\n"); + + scheduler_init(); + + if (thread_create(KERNEL_CONF_STACKSIZE_IDLE, PRIORITY_IDLE, CREATE_WOUT_YIELD | CREATE_STACKTEST, fk_idle, idle_name) < 0) { + printf("kernel_init(): error creating idle task.\n"); + } + + if (thread_create(KERNEL_CONF_STACKSIZE_MAIN, PRIORITY_MAIN, CREATE_WOUT_YIELD | CREATE_STACKTEST, MAIN_FUNC, main_name) < 0) { + printf("kernel_init(): error creating main task.\n"); + } + + printf("kernel_init(): jumping into first task...\n"); + + fk_switch_context_exit(); +} + diff --git a/core/msg.c b/core/msg.c new file mode 100644 index 0000000000..4e77429bc9 --- /dev/null +++ b/core/msg.c @@ -0,0 +1,174 @@ +/** + * kernel messaging implementation + * + * Copyright (C) 2010 Freie Universität Berlin + * + * This file subject to the terms and conditions of the GNU General Public + * License. See the file LICENSE in the top level directory for more details. + * + * @ingroup kernel_msg + * @{ + * @file + * @author Kaspar Schleiser + * @} + */ + +#include "kernel.h" +#include "scheduler.h" +#include "msg.h" +#include "queue.h" +#include "tcb.h" +#include + +#include "flags.h" + +//#define ENABLE_DEBUG +#include "debug.h" + +int msg_send(msg* m, unsigned int target_pid, bool block) { + if (inISR()) { + return msg_send_int(m, target_pid); + } + + int result = 1; + + tcb *target = (tcb*)fk_threads[target_pid]; + + m->sender_pid = fk_pid; + if (m->sender_pid == target_pid) return -1; + + dINT(); + + if (target == NULL) { + eINT(); + return -1; + } + + if (target->status != STATUS_RECEIVE_BLOCKED) { + if (! block ) { + DEBUG("%s: receiver not waiting. block=%u\n", fk_thread->name, block); + eINT(); + return 0; + } + + DEBUG("%s: send_blocked.\n", fk_thread->name); + queue_node_t n; + n.priority = fk_thread->priority; + n.data = (unsigned int) fk_thread; + DEBUG("%s: Adding node to msg_queue:\n", fk_thread->name); + + queue_priority_add(&(target->msg_queue), &n); + + fk_thread->wait_data = (void*) m; + + int newstatus; + if (fk_thread->status == STATUS_REPLY_BLOCKED) { + newstatus = STATUS_REPLY_BLOCKED; + } else { + newstatus = STATUS_SEND_BLOCKED; + } + + sched_set_status((tcb*)fk_thread, newstatus); + + DEBUG("%s: back from send block.\n", fk_thread->name); + } else { + DEBUG("%s: direct msg copy.\n", fk_thread->name); + /* copy msg to target */ + msg* target_message = (msg*)target->wait_data; + *target_message = *m; + sched_set_status(target, STATUS_PENDING); + } + + eINT(); + fk_yield(); + + return result; +} + +int msg_send_int(msg* m, unsigned int target_pid) { + tcb *target = (tcb*)fk_threads[target_pid]; + + if (target->status == STATUS_RECEIVE_BLOCKED) { + DEBUG("msg_send_int: direct msg copy.\n"); + + /* copy msg to target */ + msg* target_message = (msg*)target->wait_data; + *target_message = *m; + sched_set_status(target, STATUS_PENDING); + + fk_context_switch_request = 1; + return 1; + } else { + DEBUG("msg_send_int: receiver not waiting.\n"); + return 0; + } + +} + +int msg_send_receive(msg *m, msg *reply, unsigned int target_pid) { + dINT(); + tcb *me = (tcb*) fk_threads[fk_pid]; + sched_set_status(me, STATUS_REPLY_BLOCKED); + me->wait_data = (void*) reply; + msg_send(m, target_pid, true); + + /* msg_send blocks until reply received */ + + return 1; +} + +int msg_reply(msg *m, msg *reply) { + dINT(); + tcb *target = (tcb*)fk_threads[m->sender_pid]; + if (target->status != STATUS_REPLY_BLOCKED) { + DEBUG("%s: msg_reply(): target \"%s\" not waiting for reply.", fk_thread->name, target->name); + eINT(); + return -1; + } + + DEBUG("%s: msg_reply(): direct msg copy.\n", fk_thread->name); + /* copy msg to target */ + msg* target_message = (msg*)target->wait_data; + *target_message = *m; + sched_set_status(target, STATUS_PENDING); + eINT(); + fk_yield(); + + return 1; +} + +int msg_receive(msg* m) { + dINT(); + DEBUG("%s: msg_receive.\n", fk_thread->name); + + tcb *me = (tcb*) fk_threads[fk_pid]; + + me->wait_data = (void*) m; + + queue_node_t *n = queue_remove_head(&(me->msg_queue)); + + if (n == NULL) { + DEBUG("%s: msg_receive blocked\n", fk_thread->name); + sched_set_status(me, STATUS_RECEIVE_BLOCKED); + + eINT(); + fk_yield(); + + /* sender copied message */ + return 1; + } else { + DEBUG("%s: msg_receive direct copy.\n", fk_thread->name); + tcb *sender = (tcb*)n->data; + + /* copy msg */ + msg* sender_msg = (msg*)sender->wait_data; + *m = *sender_msg; + + /* remove sender from queue */ + sender->wait_data = NULL; + sched_set_status(sender, STATUS_PENDING); + + eINT(); + return 1; + } +} diff --git a/core/mutex.c b/core/mutex.c new file mode 100644 index 0000000000..a9d4722ea3 --- /dev/null +++ b/core/mutex.c @@ -0,0 +1,126 @@ +/** + * kernel mutex implementation + * + * Copyright (C) 2010 Freie Universität Berlin + * + * This file subject to the terms and conditions of the GNU General Public + * License. See the file LICENSE in the top level directory for more details. + * + * @ingroup kernel + * @{ + * @file + * @author Kaspar Schleiser + * @} + */ + +#include +#include "mutex.h" +#include "atomic.h" +#include "queue.h" +#include "tcb.h" +#include "kernel.h" +#include "scheduler.h" + +//#define ENABLE_DEBUG +#include + +int mutex_init(struct mutex_t* mutex) { + mutex->val = 0; + + mutex->queue.priority = 0; + mutex->queue.data = 0; + mutex->queue.next = NULL; + + return 1; +} + +int mutex_trylock(struct mutex_t* mutex) { + return (atomic_set_return(&mutex->val, fk_pid ) == 0); +} + +int prio() { + return fk_thread->priority; +} + +int mutex_lock(struct mutex_t* mutex) { + DEBUG("%s: trying to get mutex. val: %u\n", fk_thread->name, mutex->val); + + if (atomic_set_return(&mutex->val,fk_pid) != 0) { + // mutex was locked. + mutex_wait(mutex); + } + return 1; +} + +void mutex_unlock(struct mutex_t* mutex, int yield) { + DEBUG("%s: unlocking mutex. val: %u pid: %u\n", fk_thread->name, mutex->val, fk_pid); + int me_value; + + if (inISR()) { + me_value = 0; + yield = MUTEX_INISR; + } else { + me_value = fk_pid; + } + + if (atomic_set_return(&mutex->val,0) != me_value ) { + // there were waiters. + mutex_wake_waiters(mutex, yield); + } +} + +void mutex_wait(struct mutex_t *mutex) { + dINT(); + DEBUG("%s: Mutex in use. %u\n", fk_thread->name, mutex->val); + if (mutex->val == 0) { + // somebody released the mutex. return. + mutex->val = fk_pid; + DEBUG("%s: mutex_wait early out. %u\n", fk_thread->name, mutex->val); + eINT(); + return; + } + + sched_set_status((tcb*)fk_thread, STATUS_MUTEX_BLOCKED); + + queue_node_t n; + n.priority = (unsigned int) fk_thread->priority; + n.data = (unsigned int) fk_thread; + n.next = NULL; + + DEBUG("%s: Adding node to mutex queue: prio: %u data: %u\n", fk_thread->name, n.priority, n.data); + + queue_priority_add(&(mutex->queue), &n); + + eINT(); + + fk_yield(); + + /* we were woken up by scheduler. waker removed us from queue. we have the mutex now. */ +} + +void mutex_wake_waiters(struct mutex_t *mutex, int flags) { + if ( ! (flags & MUTEX_INISR)) dINT(); + DEBUG("%s: waking up waiters.\n", fk_thread->name); + + queue_node_t *next = queue_remove_head(&(mutex->queue)); + tcb* process = (tcb*)next->data; + + sched_set_status(process, STATUS_PENDING); + + if ( mutex->queue.next != NULL) { + mutex->val = -1; + } else { + mutex->val = process->pid; + } + + DEBUG("%s: waiters woken up.\n", fk_thread->name); + + /* If called from process, reenable interrupts, yield if requested */ + if (! (flags & MUTEX_INISR)) { + eINT(); + if (flags & MUTEX_YIELD) fk_yield(); + } else { + fk_context_switch_request = 1; + } +} + diff --git a/core/oneway_malloc.c b/core/oneway_malloc.c new file mode 100644 index 0000000000..51d6d53967 --- /dev/null +++ b/core/oneway_malloc.c @@ -0,0 +1,41 @@ +/** + * simple malloc wrapper for sbrk + * + * Needed on platforms without malloc in libc, e.g. msb430 + * + * Copyright (C) 2010 Freie Universität Berlin + * + * This file subject to the terms and conditions of the GNU General Public + * License. See the file LICENSE in the top level directory for more details. + * + * @ingroup kernel + * @{ + * @file + * @author Kaspar Schleiser + * @} + */ + +#include +#include + +#define ENABLE_DEBUG +#include + +extern void *sbrk(int incr); + +void *_malloc(size_t size) { + void* ptr = sbrk(size); + + DEBUG("_malloc(): allocating block of size %u at 0x%X.\n", size, (unsigned int)ptr); + + if (ptr != (void*)-1) { + return ptr; + } else { + return NULL; + } +} + +void _free(void* ptr) { + DEBUG("_free(): block at 0x%X lost.\n", (unsigned int)ptr); +} + diff --git a/core/queue.c b/core/queue.c new file mode 100644 index 0000000000..edb9927f7f --- /dev/null +++ b/core/queue.c @@ -0,0 +1,137 @@ +/** + * simple queue implementation + * + * Copyright (C) 2010 Freie Universität Berlin + * + * This file subject to the terms and conditions of the GNU General Public + * License. See the file LICENSE in the top level directory for more details. + * + * @ingroup kernel + * @{ + * @file + * @author Kaspar Schleiser + * @} + */ + +#include + +#include "queue.h" + +//#define ENABLE_DEBUG 0 +#include "debug.h" + +void queue_remove(queue_node_t* root, queue_node_t *node) { + while (root->next != NULL) { + if (root->next == node) { + root->next = node->next; + node->next = NULL; + return; + } + root = root->next; + } +} + +queue_node_t *queue_remove_head(queue_node_t* root) { + queue_node_t *head = root->next; + if (head != NULL) { + root->next = head->next; + } + return head; +} + +void queue_add_tail(queue_node_t* node, queue_node_t* new_obj) { + while (node->next != NULL) { + node = node->next; + } + node->next = new_obj; + new_obj->next = NULL; +} + +void queue_add_head(queue_node_t* root, queue_node_t* new_obj) { + new_obj->next = root->next; + root->next = new_obj; +} + +void queue_priority_add(queue_node_t* root, queue_node_t* new_obj) { + queue_node_t* node = root; + + while (node->next != NULL) { + if (node->next->priority < new_obj->priority) { + new_obj->next = node->next; + node->next = new_obj; + return; + } + node = node->next; + } + + node->next = new_obj; + new_obj->next = NULL; +} + +void queue_priority_add_generic(queue_node_t* root, queue_node_t* new_obj, int (*cmp)(queue_node_t*,queue_node_t*)) { + queue_node_t* node = root; + + while (node->next != NULL) { + if (cmp(node->next, new_obj) < 0) { + new_obj->next = node->next; + node->next = new_obj; + return; + } + node = node->next; + } + + node->next = new_obj; + new_obj->next = NULL; +} + + +void queue_print(queue_node_t* node) { + printf("queue:\n"); + while (node->next != NULL) { + node = node->next; + printf("Data: %u Priority: %u\n", node->data, node->priority); + } +} + +void queue_print_node(queue_node_t *node) { + printf("Data: %u Priority: %u Next: %u\n", (unsigned int)node->data, node->priority, (unsigned int)node->next); +} + +/* +int main() { + queue_node_t root, a, b, c,d; + + memset(&d, '\0', sizeof(queue_node_t)); + memset(&a, '\0', sizeof(queue_node_t)); + memset(&b, '\0', sizeof(queue_node_t)); + memset(&c, '\0', sizeof(queue_node_t)); + + root.data = 0; + root.next = NULL; + + a.data = 1; + a.priority = 1; + b.data = 2; + b.priority = 2; + c.data = 0; + c.priority = 5; + d.data = 4; + d.priority = 4; + + queue_add_tail(&root, &a); + queue_add_tail(&root, &b); + queue_add_tail(&root, &c); + queue_add_tail(&root, &d); + + queue_print(&root); + + queue_remove(&root, &c); + + queue_print(&root); + + queue_priority_add(&root, &c); + + queue_print(&root); + + return 0; +}*/ diff --git a/core/scheduler.c b/core/scheduler.c new file mode 100644 index 0000000000..279bb456a2 --- /dev/null +++ b/core/scheduler.c @@ -0,0 +1,161 @@ +/** + * The µkleos scheduler implementation + * + * Copyright (C) 2010 Freie Universität Berlin + * + * This file subject to the terms and conditions of the GNU General Public + * License. See the file LICENSE in the top level directory for more details. + * + * @ingroup kernel + * @{ + * @file + * @author Kaspar Schleiser + * @} + */ + +#include +#include +#include "scheduler.h" +#include "kernel.h" +#include "kernel_intern.h" +#include "clist.h" +#include + +//#define ENABLE_DEBUG +#include "debug.h" + +volatile int num_tasks = 0; + +clist_node_t *runqueues[SCHED_PRIO_LEVELS]; +static uint32_t runqueue_bitcache = 0; + +#if SCHEDSTATISTICS + schedstat pidlist[MAXTHREADS]; +#endif + +void scheduler_init() { + printf("Scheduler..."); + int i; + for (i=0; istatus == STATUS_RUNNING) { + my_fk_thread->status = STATUS_PENDING; + } + +#ifdef SCHED_TEST_STACK + if (*((unsigned int*)my_fk_thread->stack_start) != (unsigned int) my_fk_thread->stack_start) { + printf("scheduler(): stack overflow detected, task=%s pid=%u\n", my_fk_thread->name, my_fk_thread->pid); + } +#endif + + } + +#if SCHEDSTATISTICS + extern unsigned long hwtimer_now(void); + unsigned int time = hwtimer_now(); + if (my_fk_thread && (pidlist[my_fk_thread->pid].laststart)) { + pidlist[my_fk_thread->pid].runtime += time - pidlist[my_fk_thread->pid].laststart; + } +#endif + + DEBUG("\nscheduler: previous task: %s\n", ( my_fk_thread == NULL) ? "none" : my_fk_thread->name ); + + if (num_tasks == 0) { + DEBUG("scheduler: no tasks left.\n"); + while(! num_tasks); + DEBUG("scheduler: new task created.\n"); + } + + my_fk_thread = NULL; + while(! my_fk_thread) { + + // for (int i = 0; i < SCHED_PRIO_LEVELS; i++) { /* TODO: introduce bitfield cache */ + // if (runqueues[i]) { + int nextrq = number_of_lowest_bit(runqueue_bitcache); + clist_node_t next = *(runqueues[nextrq]); + DEBUG("scheduler: first in queue: %s\n", ((tcb*)next.data)->name); + clist_advance(&(runqueues[nextrq])); + my_fk_thread = (tcb*)next.data; + fk_pid = (volatile int) my_fk_thread->pid; +#if SCHEDSTATISTICS + pidlist[my_fk_thread->pid].laststart = time; + pidlist[my_fk_thread->pid].schedules ++; +#endif + // break; + // } + // } + } + + DEBUG("scheduler: next task: %s\n", my_fk_thread->name); + + if (my_fk_thread != fk_thread) { + if (fk_thread != NULL) { //TODO: necessary? + if (fk_thread->status == STATUS_RUNNING) { + fk_thread->status = STATUS_PENDING ; + } + } + sched_set_status((tcb*)my_fk_thread, STATUS_RUNNING); + } + + fk_thread = (volatile tcb*) my_fk_thread; + + DEBUG("scheduler: done.\n"); +} + + +void sched_set_status(tcb *process, unsigned int status) { + if (status & STATUS_ON_RUNQUEUE) { + if (! (process->status & STATUS_ON_RUNQUEUE)) { + DEBUG("adding process %s to runqueue %u.\n", process->name, process->priority); + clist_add(&runqueues[process->priority], &(process->rq_entry)); + runqueue_bitcache |= 1 << process->priority; + } + } else { + if (process->status & STATUS_ON_RUNQUEUE) { + DEBUG("removing process %s from runqueue %u.\n", process->name, process->priority); + clist_remove(&runqueues[process->priority], &(process->rq_entry)); + if (! runqueues[process->priority] ) { + runqueue_bitcache &= ~(1 << process->priority); + } + } + } + process->status = status; +} + +extern void fk_switch_context_exit(void); + +void fk_task_exit(void) { + DEBUG("fk_task_exit(): ending task %s...\n", fk_thread->name); + + dINT(); + fk_threads[fk_thread->pid] = NULL; + num_tasks--; + sched_set_status((tcb*)fk_thread, STATUS_STOPPED); + + free(((tcb*)fk_thread)->stack_start); + fk_thread = NULL; + fk_switch_context_exit(); +} + diff --git a/core/thread.c b/core/thread.c new file mode 100644 index 0000000000..a9f4663267 --- /dev/null +++ b/core/thread.c @@ -0,0 +1,185 @@ +/** + * thread functions + * + * Copyright (C) 2010 Freie Universität Berlin + * + * This file subject to the terms and conditions of the GNU General Public + * License. See the file LICENSE in the top level directory for more details. + * + * @ingroup kernel + * @{ + * @file + * @author Kaspar Schleiser + * @} + */ + +#include +#include +#include + +#include "thread.h" +#include "kernel.h" + +//#define ENABLE_DEBUG +#include "debug.h" +#include "kernel_intern.h" +#include "bitarithm.h" +#include "hwtimer.h" +#include "scheduler.h" + +inline int thread_getpid() { + return fk_thread->pid; +} + +unsigned int thread_getstatus(int pid) { + if (fk_threads[pid]==NULL) + return STATUS_NOT_FOUND; + return fk_threads[pid]->status; +} + +void thread_sleep() { + if ( inISR()) return; + dINT(); + sched_set_status((tcb*)fk_thread, STATUS_SLEEPING); + fk_yield(); +} + +int thread_wakeup(int pid) { + int isr = inISR(); + if (! isr) dINT(); + + int result = fk_threads[pid]->status; + if (result == STATUS_SLEEPING) { + sched_set_status((tcb*)fk_threads[pid], STATUS_RUNNING); + if (!isr) { + eINT(); + fk_yield(); + } else { + fk_context_switch_request = 1; + } + return 0; + } else { + if (!isr) eINT(); + return STATUS_NOT_FOUND; + } +} + +int fk_measure_stack_free(char* stack) { + unsigned int* stackp = (unsigned int*)stack; + /* assumption that the comparison fails before or after end of stack */ + while( *stackp == (unsigned int)stackp ) + stackp++; + + int space = (unsigned int)stackp - (unsigned int)stack; + return space; +} + +int thread_create(int stacksize, char priority, int flags, void (*function) (void), const char* name) +{ + /* stacksize must be a multitude of 4 for alignment and stacktest */ +// assert( ((stacksize & 0x03) == 0) && (stacksize > 0) ); + + // TODO: shall we autoalign the stack? + // stacksize += 4-(~(stacksize & 0x0003)); + + if (priority >= SCHED_PRIO_LEVELS) { + return -EINVAL; + } + + tcb *pd = (tcb*)malloc(sizeof(tcb)); + if ( pd == NULL) { + DEBUG("thread_create(): out of memory\n"); + return -ENOMEM; + } + + char *stack = (char*)malloc(stacksize); + if (stack==NULL) + { + DEBUG("thread_create(): out of memory\n"); + free (pd); + return -ENOMEM; + } + + if (flags & CREATE_STACKTEST) { + /* assign each int of the stack the value of it's address */ + unsigned int *stackmax = (unsigned int*) ((char*)stack + stacksize); + unsigned int* stackp = (unsigned int*)stack; + while(stackp < stackmax) { + *stackp = (unsigned int)stackp; + stackp++; + } + } else { + /* create stack guard */ + *stack = (unsigned int)stack; + } + + if (! inISR()) { + dINT(); + } + + int pid = 0; + while (pid < MAXTHREADS) { + if (fk_threads[pid] == NULL) { + fk_threads[pid] = pd; + pd->pid = pid; + break; + } + pid++; + } + + if (pid == MAXTHREADS) { + DEBUG("thread_create(): too many threads!\n"); + + free (pd); + free (stack); + + if (! inISR()) { + eINT(); + } + return -EOVERFLOW; + } + + pd->sp = fk_stack_init(function,stack+stacksize); + pd->stack_start = stack; + pd->stack_size = stacksize; + + pd->priority = priority; + pd->status = 0; + + pd->name = name; + + pd->wait_data = NULL; + + pd->msg_queue.data = 0; + pd->msg_queue.priority = 0; + pd->msg_queue.next = NULL; + + pd->rq_entry.data = (unsigned int) pd; + pd->rq_entry.next = NULL; + pd->rq_entry.prev = NULL; + + num_tasks++; + + DEBUG("Created thread %s. PID: %u. Priority: %u.\n", name, pd->pid, priority); + + if (flags & CREATE_SLEEPING) { + sched_set_status(pd, STATUS_SLEEPING); + } else { + sched_set_status(pd, STATUS_PENDING); + if (!(flags & CREATE_WOUT_YIELD)) { + if (! inISR()) { + eINT(); + fk_yield(); + } else { + fk_context_switch_request = 1; + } + } + } + + if (!inISR() && fk_thread!=NULL) { + eINT(); + } + + return pid; +} + diff --git a/cpu/Jamfile b/cpu/Jamfile new file mode 100644 index 0000000000..809d3a73e2 --- /dev/null +++ b/cpu/Jamfile @@ -0,0 +1,30 @@ +# ****************************************************************************** +# Copyright 2009, Freie Universitaet Berlin (FUB). All rights reserved. +# +# These sources were developed at the Freie Universitaet Berlin, Computer +# Systems and Telematics group (http://cst.mi.fu-berlin.de). +# ------------------------------------------------------------------------------ +# This file is part of FeuerWare. +# +# This program is free software: you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation, either version 3 of the License, or (at your option) any later +# version. +# +# FeuerWare is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with +# this program. If not, see http://www.gnu.org/licenses/ . +# ------------------------------------------------------------------------------ +# For further information and questions please use the web site +# http://scatterweb.mi.fu-berlin.de +# and the mailinglist (subscription via web site) +# scatterweb@lists.spline.inf.fu-berlin.de +# ****************************************************************************** +# $Id$ + +SubDir TOP cpu ; + +# cpu subdirs are included from board specific jamfiles diff --git a/cpu/arm_common/Jamfile b/cpu/arm_common/Jamfile new file mode 100644 index 0000000000..5438882366 --- /dev/null +++ b/cpu/arm_common/Jamfile @@ -0,0 +1,40 @@ +# ****************************************************************************** +# Copyright 2009, Freie Universitaet Berlin (FUB). All rights reserved. +# +# These sources were developed at the Freie Universitaet Berlin, Computer +# Systems and Telematics group (http://cst.mi.fu-berlin.de). +# ------------------------------------------------------------------------------ +# This file is part of FeuerWare. +# +# This program is free software: you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation, either version 3 of the License, or (at your option) any later +# version. +# +# FeuerWare is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with +# this program. If not, see http://www.gnu.org/licenses/ . +# ------------------------------------------------------------------------------ +# For further information and questions please use the web site +# http://scatterweb.mi.fu-berlin.de +# and the mailinglist (subscription via web site) +# scatterweb@lists.spline.inf.fu-berlin.de +# ****************************************************************************** +# $Id$ + +SubDir TOP cpu arm_common ; + +Module arm_common : common.s bootloader.c VIC.c atomic.s arm_cpu.c ; +UseModule arm_common ; + +Module hwtimer_cpu : hwtimer_cpu.c ; + +Objects syscalls.c ; + +DEPENDS $(TARGET) : startup.o ; +DEPENDS $(TARGET) : syscalls.o ; + +LINKFLAGS on $(TARGET) += $(LINKFLAGS) [ FPath $(TARGET_DIR) startup.o ] [ FPath $(TARGET_DIR) syscalls.o ] ; diff --git a/cpu/arm_common/Jamrules.arm_common b/cpu/arm_common/Jamrules.arm_common new file mode 100644 index 0000000000..dac4bff7d8 --- /dev/null +++ b/cpu/arm_common/Jamrules.arm_common @@ -0,0 +1,53 @@ +# ****************************************************************************** +# Copyright 2009, Freie Universitaet Berlin (FUB). All rights reserved. +# +# These sources were developed at the Freie Universitaet Berlin, Computer +# Systems and Telematics group (http://cst.mi.fu-berlin.de). +# ------------------------------------------------------------------------------ +# This file is part of FeuerWare. +# +# This program is free software: you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation, either version 3 of the License, or (at your option) any later +# version. +# +# FeuerWare is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with +# this program. If not, see http://www.gnu.org/licenses/ . +# ------------------------------------------------------------------------------ +# For further information and questions please use the web site +# http://scatterweb.mi.fu-berlin.de +# and the mailinglist (subscription via web site) +# scatterweb@lists.spline.inf.fu-berlin.de +# ****************************************************************************** + +# ============================================================================== +# generic arm definitions & targets +# ============================================================================== + +HDRS += [ FPath $(TOP) cpu arm_common include ] ; + +TOOLCHAIN = arm-elf- ; + +# +# Toolchain setup +# +CC = $(TOOLCHAIN)gcc ; +LINK = $(CC) ; + +OPTIM = -Os ; +#OPTIM = -O0 -g ; +CCFLAGS += -std=gnu99 -Wall -mcpu=arm7tdmi-s -mfloat-abi=soft -mfpu=vfp ; +LINKFLAGS = -mcpu=arm7tdmi-s -static -lgcc -nostartfiles -T [ FPath $(TOP) cpu $(CPU) linkerscript.x ] ; + +AS = $(TOOLCHAIN)as ; +ASFLAGS += -mcpu=arm7tdmi-s --defsym $(CPU)=1 -mfloat-abi=soft -mfpu=vfp ; + +AR = $(TOOLCHAIN)ar ; +ARFLAGS = -rc ; + +OBJCOPY = $(TOOLCHAIN)objcopy ; + diff --git a/cpu/arm_common/VIC.c b/cpu/arm_common/VIC.c new file mode 100644 index 0000000000..f6cd6a3f5d --- /dev/null +++ b/cpu/arm_common/VIC.c @@ -0,0 +1,101 @@ +/* Copyright (C) 2005, 2006, 2007, 2008 by Thomas Hillebrandt and Heiko Will + +This file is part of the Micro-mesh SensorWeb Firmware. + +Micro-Mesh is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +Micro-Mesh is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Micro-Mesh; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +#include "board.h" +#include "VIC.h" +#include + +#define IRQ_MASK 0x00000080 +#define FIQ_MASK 0x00000040 +#define INT_MASK (IRQ_MASK | FIQ_MASK) + +static inline unsigned __get_cpsr(void) +{ + unsigned long retval; + asm volatile (" mrs %0, cpsr" : "=r" (retval) : /* no inputs */ ); + return retval; +} + +int inISR(void) +{ + int retval; + asm volatile (" mrs %0, cpsr" : "=r" (retval) : /* no inputs */ ); + return (retval & INTMode) == 18; +} + +static inline void __set_cpsr(unsigned val) +{ + asm volatile (" msr cpsr, %0" : /* no outputs */ : "r" (val) ); +} + +unsigned disableIRQ(void) +{ + unsigned _cpsr; + + _cpsr = __get_cpsr(); + __set_cpsr(_cpsr | IRQ_MASK); + return _cpsr; +} + +unsigned restoreIRQ(unsigned oldCPSR) +{ + unsigned _cpsr; + + _cpsr = __get_cpsr(); + __set_cpsr((_cpsr & ~IRQ_MASK) | (oldCPSR & IRQ_MASK)); + return _cpsr; +} + +unsigned enableIRQ(void) +{ + unsigned _cpsr; + + _cpsr = __get_cpsr(); + __set_cpsr(_cpsr & ~IRQ_MASK); + return _cpsr; +} + +unsigned disableFIQ(void) +{ + unsigned _cpsr; + + _cpsr = __get_cpsr(); + __set_cpsr(_cpsr | FIQ_MASK); + return _cpsr; +} + +unsigned restoreFIQ(unsigned oldCPSR) +{ + unsigned _cpsr; + + _cpsr = __get_cpsr(); + __set_cpsr((_cpsr & ~FIQ_MASK) | (oldCPSR & FIQ_MASK)); + return _cpsr; +} + +unsigned enableFIQ(void) +{ + unsigned _cpsr; + + _cpsr = __get_cpsr(); + __set_cpsr(_cpsr & ~FIQ_MASK); + return _cpsr; +} + + diff --git a/cpu/arm_common/arm_cpu.c b/cpu/arm_common/arm_cpu.c new file mode 100644 index 0000000000..35a20a47de --- /dev/null +++ b/cpu/arm_common/arm_cpu.c @@ -0,0 +1,88 @@ +/** + * ARM architecture common support functions + * + * Copyright (C) 2008, 2009 Heiko Will + * Copyright (C) 2009 Kaspar Schleiser + * + * This file subject to the terms and conditions of the GNU General Public + * License. See the file LICENSE in the top level directory for more details. + * + * @ingroup arch + * @{ + * @file + * @author Kaspar Schleiser + * @author Heiko Will + * @} + */ +/** + * + * + * + */ + +#include +#include "arm_cpu.h" +#include "scheduler.h" +#include "kernel_intern.h" + +void fk_yield() { + asm("svc 0\n"); +} + +//---------------------------------------------------------------------------- +// Processor specific routine - here for ARM7 +// sizeof(void*) = sizeof(int) +//---------------------------------------------------------------------------- +char * fk_stack_init(void * task_func, void * stack_start) +{ + unsigned int * stk; + stk = (unsigned int *) stack_start; + stk--; + + *stk = 0x77777777; + stk--; + + *stk = (unsigned int)fk_task_exit; // LR + + stk--; + *stk = (unsigned int) stack_start - 4; // SP + + for (int i = 12; i>= 0 ; i--) { // build base stack + stk--; + *stk = i; + } + + stk--; + *stk = ((unsigned int) task_func); // Entry Point + stk--; + *stk = (unsigned int) NEW_TASK_CPSR; // spsr + + return (char*)stk; +} + +void fk_print_stack () { + register void * stack = 0; + asm( "mov %0, sp" : "=r" (stack)); + + register unsigned int * s = (unsigned int*) stack; + printf("task: %X SP: %X\n", (unsigned int)fk_thread, (unsigned int)stack); + register int i = 0; + s += 5; + while (*s != 0x77777777) { + printf("STACK (%u) addr=%X = %X \n",i,(unsigned int) s, (unsigned int)*s); + s++; + i++; + } + printf("STACK (%u)= %X \n",i,*s); +} + +__attribute__((naked,noreturn)) void +arm_reset(void) +{ + dINT(); + WDTC = 0x00FFF; + WDMOD = 0x03; + WDFEED= 0xAA; + WDFEED= 0x55; + while(1); +} diff --git a/cpu/arm_common/atomic.s b/cpu/arm_common/atomic.s new file mode 100644 index 0000000000..3bdeb94dba --- /dev/null +++ b/cpu/arm_common/atomic.s @@ -0,0 +1,18 @@ +/* GCC ARM assembler */ + + .text + .code 32 + .align 4 /* 0 */ + +/* .extern fk_schedule*/ + +/* Public functions declared in this file */ + .global atomic_set_return + +.func +atomic_set_return: + SWP r2,r1,[r0] + MOV r0, r2 + mov pc, lr +.endfunc + diff --git a/cpu/arm_common/bootloader.c b/cpu/arm_common/bootloader.c new file mode 100644 index 0000000000..7634c2017b --- /dev/null +++ b/cpu/arm_common/bootloader.c @@ -0,0 +1,183 @@ +/****************************************************************************** +Copyright 2008-2009, Freie Universitaet Berlin (FUB). All rights reserved. + +These sources were developed at the Freie Universitaet Berlin, Computer Systems +and Telematics group (http://cst.mi.fu-berlin.de). +------------------------------------------------------------------------------- +This file is part of FeuerWare. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +FeuerWare is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see http://www.gnu.org/licenses/ . +-------------------------------------------------------------------------------- +For further information and questions please use the web site + http://scatterweb.mi.fu-berlin.de +and the mailinglist (subscription via web site) + scatterweb@lists.spline.inf.fu-berlin.de +*******************************************************************************/ + +/** + * @ingroup arm_common + * @{ + */ + +/** + * @file + * @internal + * @brief ARM bootloader + * + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @author Heiko Will + * @author Michael Baar + * @version $Revision$ + * @since 19.08.2008 + * + * @note $Id$ + */ + +#include +#include +#include +#include + +void FIQ_Routine (void) __attribute__ ((interrupt("FIQ"))); +//void SWI_Routine (void) __attribute__ ((interrupt("SWI"))); +void UNDEF_Routine (void) __attribute__ ((interrupt("UNDEF"))); + +void IRQ_Routine (void) { + printf("Kernel Panic,\nEarly IRQ call\n"); + while(1){}; +} +/*-----------------------------------------------------------------------------------*/ +void FIQ_Routine (void) { + printf("Kernel Panic,\nEarly FIQ call\n"); + while(1){}; +} +/*-----------------------------------------------------------------------------------*/ +void SWI_Routine (void) { + printf("Kernel Panic,\nEarly SWI call\n"); + while(1){}; +} +/*-----------------------------------------------------------------------------------*/ +void DEBUG_Routine (void) { + printf("DEBUG hit."); + while(1){}; +} +/*-----------------------------------------------------------------------------------*/ +volatile int arm_abortflag = 0; + +void abtorigin(const char* vector, u_long* lnk_ptr1) +{ + register u_long* lnk_ptr2; + register unsigned long* sp; + register unsigned int cpsr, spsr; + + __asm__ __volatile__("mrs %0, cpsr" : "=r" (cpsr) ); // copy current mode + __asm__ __volatile__("mrs %0, spsr" : "=r" (spsr) ); // copy dabt generating mode + __asm__ __volatile__("msr cpsr_c, %0" :: "r" (spsr) ); // switch to dabt generating mode + __asm__ __volatile__("mov %0, lr" : "=r" (lnk_ptr2)); // copy lr + __asm__ __volatile__("mov %0, sp" : "=r" (sp)); // copy sp + __asm__ __volatile__("msr cpsr_c, %0" :: "r" (cpsr) ); // switch back to abt mode + + printf("#! %s abort at %p (0x%08lX) originating from %p (0x%08lX) in mode 0x%X\n", + vector, (void*)lnk_ptr1, *(lnk_ptr1), (void*)lnk_ptr2, *(lnk_ptr2), spsr + ); + stdio_flush(); + + exit(1); +} +/*-----------------------------------------------------------------------------------*/ +void UNDEF_Routine (void) { + register u_long* lnk_ptr; + __asm__ __volatile__("sub %0, lr, #8" : "=r" (lnk_ptr) ); // get aborting instruction + + if( arm_abortflag == 0 ) { + arm_abortflag = 1; // remember state (if printing should fail again) + abtorigin("undef", lnk_ptr); + } + + exit(1); +} +/*-----------------------------------------------------------------------------------*/ +void PABT_Routine (void) { + register u_long* lnk_ptr; + __asm__ __volatile__("sub %0, lr, #8" : "=r" (lnk_ptr) ); // get aborting instruction + + if( arm_abortflag == 0 ) { + arm_abortflag = 1; // remember state (if printing should fail again) + abtorigin("pabt", lnk_ptr); + } + + exit(1); +} +/*-----------------------------------------------------------------------------------*/ +void DABT_Routine (void) { + register u_long* lnk_ptr; + __asm__ __volatile__("sub %0, lr, #8" : "=r" (lnk_ptr) ); // get aborting instruction + + if( arm_abortflag == 0 ) { + arm_abortflag = 1; // remember state (if printing should fail again) + abtorigin("data", lnk_ptr); + } + + exit(1); +} +/*-----------------------------------------------------------------------------------*/ +static inline void +bl_init_data(void) +{ + extern unsigned int _etext; + extern unsigned int _data; + extern unsigned int _edata; + extern unsigned int __bss_start; + extern unsigned int __bss_end; + + register unsigned int* p1; + register unsigned int* p2; + register unsigned int* p3; + + // initialize data from flash + // (linker script ensures that data is 32-bit aligned) + p1 = &_etext; + p2 = &_data; + p3 = &_edata; + while( p2 < p3 ) + *p2++ = *p1++; + + // clear bss + // (linker script ensures that bss is 32-bit aligned) + p1 = &__bss_start; + p2 = &__bss_end; + while( p1 < p2 ) + *p1++ = 0; +} +/*-----------------------------------------------------------------------------------*/ +void bootloader(void) { + extern void bl_uart_init(void); + extern void bl_init_ports(void); + extern void bl_init_clks(void); + extern void bl_blink(void); + + /* board specific setup of clocks */ + bl_init_clks(); + /* initialize bss and data */ + bl_init_data(); + /* board specific setup of i/o pins */ + bl_init_ports(); + /* short blinking of both of the LEDs on startup */ + bl_blink(); + /* board specific setup of UART */ + bl_uart_init(); + + printf("Board initialized.\n"); +} + +/** @} */ diff --git a/cpu/arm_common/common.s b/cpu/arm_common/common.s new file mode 100644 index 0000000000..cd6290530a --- /dev/null +++ b/cpu/arm_common/common.s @@ -0,0 +1,177 @@ + /* GCC ARM assembler */ + + .text + .code 32 + .align 4 /* 0 */ + + /* Constants */ + + .equ USERMODE, 0x10 + .equ FIQMODE, 0x11 + .equ IRQMODE, 0x12 + .equ SVCMODE, 0x13 + .equ ABORTMODE, 0x17 + .equ UNDEFMODE, 0x1b + .equ SYSTEMMODE, 0x1f + .equ MODEMASK, 0x1f + .equ NOINT, 0xc0 /* Disable both IRQ & FIR */ + .equ TBIT, 0x20 + .equ IRQMASK, 0x80 + .equ FIQMASK, 0x40 + + + /* External references */ + + .extern fk_thread + .extern fk_context_switch_request + .extern fk_schedule + .extern DEBUG_Routine + +/* Public functions declared in this file */ + .global fk_cpu_irq_isr + .global fk_switch_context_exit + .global fk_switch_context + .global task_return + .global ctx_switch + .global dINT + .global eINT + +.func +dINT: + mrs r0, cpsr + + orr r0, r0, #NOINT /* Disable Int */ + msr CPSR_c, r0 + mov pc,lr +.endfunc + +.func +eINT: + mrs r0, cpsr + and r0, r0, #~NOINT /* Enable Int */ + msr CPSR_c, r0 + mov pc,lr +.endfunc + +ctx_switch: + /* Save return address on stack */ + stmfd sp!, {lr} + + /* disable interrupts */ + mov lr, #NOINT|SVCMODE + msr CPSR_c, lr + +ctx_switch2: + /* get stack pointer from user mode into lr */ + stmfd sp, {sp}^ + sub sp, sp, #4 + ldmfd sp!, {lr} + + /* save registers on user mode stack pointed to by lr */ + stmfd lr, {r0-r14}^ + sub lr, lr, #60 + + /* restore saved return address from stack */ + ldmfd sp!, {r1} + + /* get spsr into register */ + mrs r0, spsr + + /* store return address and spsr on user mode stack */ + stmfd lr!, {r0, r1} + + /* save user mode stack pointer in *fk_thread */ + ldr r1, =fk_thread /* r1 = &fk_thread */ + ldr r1, [r1] /* r1 = *r1 = fk_thread */ + + str lr, [r1] /* store stack pointer in tasks tcb*/ + /* now the calling task has all its registers saved on its stack and it's SP is saved in its tcb */ + + + /* call scheduler so fk_thread points to the next task */ + bl fk_schedule + b fk_task_return + /* never coming back */ + +fk_switch_context_exit: + mov r0, #NOINT|SVCMODE + msr cpsr, r0 + + /* call scheduler so fk_thread points to the next task */ + bl fk_schedule + + /* continue in fk_task_return: */ + +fk_task_return: + /* load tcb->stackpointer in r0 */ + ldr r0, =fk_thread /* r0 = &fk_thread */ + ldr r0, [r0] /* r0 = *r0 = fk_thread */ + ldr r0, [r0] + + /* restore saved spsr and return address from tasks stack */ + ldmfd r0!, {r1,lr} + msr SPSR, r1 + + /* Restore all registers, PC & cpsr */ + ldmfd r0, {r0-lr}^ + + /* return to task */ + movs pc, lr + +/*---------------------------------------------------------------------------- +* +*----------------------------------------------------------------------------*/ +fk_cpu_irq_isr: + sub lr, lr, #4 + + /* save interrupted tasks PC onto stack */ + stmfd sp!, {lr} + + /* save all registers on isr stack */ + stmfd sp!, {r0-r12} + + /* save spsr on stack */ + MRS R0, SPSR + STMFD SP!, {R0} + + MRS R1, CPSR + MSR SPSR, R1 + + /* jump into vic interrupt */ + mov r0, #0xffffff00 /* lpc23xx */ + +.ifdef lpc214x + sub r0, r0, #0xed0 /* lpc214x won't accept non-8bit aligned constant... */ +.endif + + ldr r0, [r0] + add lr,pc,#4 + mov pc, r0 + + /* restore spsr from stack */ + LDMFD SP!, {R0} + MSR SPSR, R0 + + /* check if context switch was requested by irq */ + ldr r0, =fk_context_switch_request + ldr r0, [r0] + + cmp r0, #0x00 + bne switch_context_int + +exit_irq_int: + /* recover general purpose registers */ + ldmfd sp!, {r0-r12} + + /* recover tasks PC into lr */ + ldmfd sp!, {lr} + + /* now jump back into task */ + movs pc, lr + +switch_context_int: + /* recover general purpose registers */ + ldmfd sp!, {r0-r12} + + b ctx_switch2 + diff --git a/cpu/arm_common/hwtimer_cpu.c b/cpu/arm_common/hwtimer_cpu.c new file mode 100644 index 0000000000..c3dbb0ea16 --- /dev/null +++ b/cpu/arm_common/hwtimer_cpu.c @@ -0,0 +1,174 @@ +/** + * @ingroup arm_common + * @file + * @internal + * @brief ARM kernel timer CPU dependent functions implementation + * + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @author Thomas Hillebrandt + * @author Heiko Will + * + */ + +#include "cpu.h" +#include "board.h" +#include "bitarithm.h" +#include "hwtimer_cpu.h" +#include "hwtimer_arch.h" + +#define VULP(x) ((volatile unsigned long*) (x)) + +/// High level interrupt handler +static void (*int_handler)(int); + +/// Timer 0-3 interrupt handler +static void timer_irq(void) __attribute__((interrupt("IRQ"))); + +inline unsigned long get_base_address(short timer) { + return (volatile unsigned long)(TMR0_BASE_ADDR + (timer / 8) * 0x6C000 + (timer/4 - (timer/8)*2) * 0x4000); +} + +static void timer_irq(void) +{ + short timer = 0; + if (T0IR) { + timer = 0; + } else if (T1IR) { + timer = 4; + } else if (T2IR) { + timer = 8; + } + + volatile unsigned long base = get_base_address(timer); + + if (*VULP(base+TXIR) & BIT0) { + *VULP(base+TXMCR) &= ~BIT0; + *VULP(base+TXIR) = BIT0; + int_handler(timer); + } + if (*VULP(base+TXIR) & BIT1) { + *VULP(base+TXMCR) &= ~BIT3; + *VULP(base+TXIR) = BIT1; + int_handler(timer + 1); + } + if (*VULP(base+TXIR) & BIT2) { + *VULP(base+TXMCR) &= ~BIT6; + *VULP(base+TXIR) = BIT2; + int_handler(timer + 2); + } + if (*VULP(base+TXIR) & BIT3) { + *VULP(base+TXMCR) &= ~BIT9; + *VULP(base+TXIR) = BIT3; + int_handler(timer + 3); + } + + VICVectAddr = 0; // acknowledge interrupt (if using VIC IRQ) +} + +static void timer0_init(uint32_t cpsr) { + PCONP |= PCTIM0; // power up timer + T0TCR = 2; // disable and reset timer + T0MCR = 0; // disable compare + T0CCR = 0; // capture is disabled + T0EMR = 0; // no external match output + T0PR = cpsr; // set prescaler + install_irq(TIMER0_INT, &timer_irq, 1); + T0TCR = 1; // reset counter +} + +static void timer1_init(uint32_t cpsr) { + PCONP |= PCTIM1; // power up timer + T1TCR = 2; // disable and reset timer + T1MCR = 0; // disable compare + T1CCR = 0; // capture is disabled + T1EMR = 0; // no external match output + T1PR = cpsr; // set prescaler + install_irq(TIMER1_INT, &timer_irq, 1); + T1TCR = 1; // reset counter +} + +static void timer2_init(uint32_t cpsr) { + PCONP |= PCTIM2; // power up timer + T2TCR = 2; // disable and reset timer + T2MCR = 0; // disable compare + T2CCR = 0; // capture is disabled + T2EMR = 0; // no external match output + T2PR = cpsr; // set prescaler + install_irq(TIMER2_INT, &timer_irq, 1); + T2TCR = 1; // reset counter +} + +void hwtimer_arch_init(void (*handler)(int), uint32_t fcpu) { + uint32_t cpsr; + int_handler = handler; + cpu_clock_scale(fcpu, HWTIMER_SPEED, &cpsr); + timer0_init(cpsr); + timer1_init(cpsr); + timer2_init(cpsr); +} + +/*---------------------------------------------------------------------------*/ + +void hwtimer_arch_enable_interrupt(void) { + VICIntEnable = 1 << TIMER0_INT; /* Enable Interrupt */ + VICIntEnable = 1 << TIMER1_INT; /* Enable Interrupt */ + VICIntEnable = 1 << TIMER2_INT; /* Enable Interrupt */ +} + +/*---------------------------------------------------------------------------*/ + +void hwtimer_arch_disable_interrupt(void) { + VICIntEnClr = 1 << TIMER0_INT; /* Disable Interrupt */ + VICIntEnClr = 1 << TIMER1_INT; /* Disable Interrupt */ + VICIntEnClr = 1 << TIMER2_INT; /* Disable Interrupt */ +} + +/*---------------------------------------------------------------------------*/ + +void hwtimer_arch_set(unsigned long offset, short timer) { + // Calculate base address of timer register + // Timer 0-3 are matched to TIMER0 + // Timer 4-7 are matched to TIMER1 + // Timer 8-11 are matched to TIMER2 + volatile unsigned long base = get_base_address(timer); + // Calculate match register address of corresponding timer + timer %= 4; + volatile unsigned long* addr = VULP(base + TXMR0 + 4 * timer); + // Calculate match register value + unsigned long value = *VULP(base + TXTC) + offset; + *addr = value; // set match register + *VULP(base+TXIR) = 0x01 << timer; // reset interrupt register value for corresponding match register + *VULP(base+TXMCR) &= ~(7 << (3 * timer)); // Clear all bits + *VULP(base+TXMCR) |= (MR0I << (3 * timer)); // enable interrupt for match register +} + +void hwtimer_arch_set_absolute(unsigned long value, short timer) { + // Calculate base address of timer register + // Timer 0-3 are matched to TIMER0 + // Timer 4-7 are matched to TIMER1 + // Timer 8-11 are matched to TIMER2 + volatile unsigned long base = get_base_address(timer); + // Calculate match register address of corresponding timer + timer %= 4; + volatile unsigned long* addr = VULP(base + TXMR0 + 4 * timer); + // Calculate match register value + *addr = value; // set match register + *VULP(base+TXIR) = 0x01 << timer; // reset interrupt register value for corresponding match register + *VULP(base+TXMCR) &= ~(7 << (3 * timer)); // Clear all bits + *VULP(base+TXMCR) |= (MR0I << (3 * timer)); // enable interrupt for match register +} + +/*---------------------------------------------------------------------------*/ + +void hwtimer_arch_unset(short timer) { + volatile unsigned long base = get_base_address(timer); + timer %= 4; + *VULP(base+TXMCR) &= ~(MR0I << (3 * timer)); // disable interrupt for match register + *VULP(base+TXIR) = 0x01 << timer; // reset interrupt register value for corresponding match register +} + +/*---------------------------------------------------------------------------*/ + +unsigned long hwtimer_arch_now(void) { + return T0TC; +} diff --git a/cpu/arm_common/include/VIC.h b/cpu/arm_common/include/VIC.h new file mode 100644 index 0000000000..9537343744 --- /dev/null +++ b/cpu/arm_common/include/VIC.h @@ -0,0 +1,96 @@ +/* Copyright (C) 2005, 2006, 2007, 2008 by Thomas Hillebrandt and Heiko Will + +This file is part of the Micro-mesh SensorWeb Firmware. + +Micro-Mesh is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +Micro-Mesh is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Micro-Mesh; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +#ifndef __ARM_COMMON_H +#define __ARM_COMMON_H + +/** + * @ingroup arm_common + * @{ + */ + +#define I_Bit 0x80 +#define F_Bit 0x40 + +#define SYS32Mode 0x1F +#define IRQ32Mode 0x12 +#define FIQ32Mode 0x11 + +#define INTMode (FIQ32Mode | IRQ32Mode) + + +/** + * @name IRQ Priority Mapping + */ +//@{ +#define HIGHEST_PRIORITY 0x01 +#define IRQP_RTIMER 1 // FIQ_PRIORITY // TODO: investigate problems with rtimer and FIQ +#define IRQP_TIMER1 1 +#define IRQP_WATCHDOG 1 +#define IRQP_CLOCK 3 +#define IRQP_GPIO 4 +#define IRQP_RTC 8 +#define LOWEST_PRIORITY 0x0F +// @} + + +#define WDT_INT 0 +#define SWI_INT 1 +#define ARM_CORE0_INT 2 +#define ARM_CORE1_INT 3 +#define TIMER0_INT 4 +#define TIMER1_INT 5 +#define UART0_INT 6 +#define UART1_INT 7 +#define PWM0_1_INT 8 +#define I2C0_INT 9 +#define SPI0_INT 10 /* SPI and SSP0 share VIC slot */ +#define SSP0_INT 10 +#define SSP1_INT 11 +#define PLL_INT 12 +#define RTC_INT 13 +#define EINT0_INT 14 +#define EINT1_INT 15 +#define EINT2_INT 16 +#define EINT3_INT 17 +#define ADC0_INT 18 +#define I2C1_INT 19 +#define BOD_INT 20 +#define EMAC_INT 21 +#define USB_INT 22 +#define CAN_INT 23 +#define MCI_INT 24 +#define GPDMA_INT 25 +#define TIMER2_INT 26 +#define TIMER3_INT 27 +#define UART2_INT 28 +#define UART3_INT 29 +#define I2C2_INT 30 +#define I2S_INT 31 + +#define VECT_ADDR_INDEX 0x100 +#define VECT_CNTL_INDEX 0x200 + +#include +#include "cpu.h" + +bool cpu_install_irq( int IntNumber, void *HandlerAddr, int Priority ); + +/** @} */ +#endif /*ARMVIC_H_*/ diff --git a/cpu/arm_common/include/arm_common.h b/cpu/arm_common/include/arm_common.h new file mode 100644 index 0000000000..b4fa499492 --- /dev/null +++ b/cpu/arm_common/include/arm_common.h @@ -0,0 +1,114 @@ +/****************************************************************************** +Copyright 2008-2009, Freie Universitaet Berlin (FUB). All rights reserved. + +These sources were developed at the Freie Universitaet Berlin, Computer Systems +and Telematics group (http://cst.mi.fu-berlin.de). +------------------------------------------------------------------------------- +This file is part of FeuerWare. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +FeuerWare is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see http://www.gnu.org/licenses/ . +-------------------------------------------------------------------------------- +For further information and questions please use the web site + http://scatterweb.mi.fu-berlin.de +and the mailinglist (subscription via web site) + scatterweb@lists.spline.inf.fu-berlin.de +*******************************************************************************/ + +#ifndef __ARM_COMMON_H +#define __ARM_COMMON_H + +/** + * @defgroup arm_common ARM CPU common + * @ingroup cpu + * @{ + */ + +/** + * @file + * @brief ARM CPU common declarations + * + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @version $Revision$ + * + * @note $Id$ + */ + +#include "bitarithm.h" + +/** + * @name PCONP Constants + * @{ + */ +#define PCTIM0 BIT1 +#define PCTIM1 BIT2 +#define PCUART0 BIT3 +#define PCUART1 BIT4 +#define PCPWM1 BIT6 +#define PCI2C0 BIT7 +#define PCSPI BIT8 +#define PCRTC BIT9 +#define PCSSP1 BIT10 +#define PCEMC BIT11 +#define PCAD BIT12 +#define PCAN1 BIT13 +#define PCAN2 BIT14 +#define PCI2C1 BIT19 +#define PCSSP0 BIT21 +#define PCTIM2 BIT22 +#define PCTIM3 BIT23 +#define PCUART2 BIT24 +#define PCUART3 BIT25 +#define PCI2C2 BIT26 +#define PCI2S BIT27 +#define PCSDC BIT28 +#define PCGPDMA BIT29 +#define PCENET BIT30 +#define PCUSB BIT31 +/** @} */ + +/** + * @name PCON Constants + * @{ + */ +#define PM0 BIT0 +#define PM1 BIT1 +#define BODPDM BIT2 +#define BOGD BIT3 +#define BORD BIT4 +#define PM2 BIT7 + +#define PM_IDLE (PM0) +#define PM_SLEEP (PM2|PM0) +#define PM_POWERDOWN (PM1) +/** @} */ + +/** + * @name Timer Symbols + * @{ + */ +#define MR0I BIT0 +#define MR0R BIT1 +#define MR0S BIT2 +#define MR1I BIT3 +#define MR1R BIT4 +#define MR1S BIT5 +#define MR2I BIT6 +#define MR2R BIT7 +#define MR2S BIT8 +#define MR3I BIT9 +#define MR3R BIT10 +#define MR3S BIT11 +/** @} */ + +/** @} */ +#endif // __ARM_COMMON_H diff --git a/cpu/arm_common/include/arm_cpu.h b/cpu/arm_common/include/arm_cpu.h new file mode 100644 index 0000000000..3159c005e7 --- /dev/null +++ b/cpu/arm_common/include/arm_cpu.h @@ -0,0 +1,21 @@ +#ifndef _ARM_CPU_H +#define _ARM_CPU_H + +#include +#include "VIC.h" +#include "arm_common.h" + +#define NEW_TASK_CPSR 0x1F +#define WORDSIZE 32 + +extern void dINT(); +extern void eINT(); + +void fk_yield(); +uint32_t get_system_speed(void); +void cpu_clock_scale(uint32_t source, uint32_t target, uint32_t* prescale); + +void arm_reset(void); +void stdio_flush(void); + +#endif // _ARM_CPU_H diff --git a/cpu/arm_common/include/hwtimer_cpu.h b/cpu/arm_common/include/hwtimer_cpu.h new file mode 100644 index 0000000000..3f2c489095 --- /dev/null +++ b/cpu/arm_common/include/hwtimer_cpu.h @@ -0,0 +1,21 @@ +/* + * lpc2387_timer_0_1.h + * + * Created on: 15.01.2009 + * Author: heiko, kaspar + * + * Changelog: + * 26.01.09 kaspar: renamed file, misc changes for firekernel + */ + +#ifndef HWTIMER_CPU_H_ +#define HWTIMER_CPU_H_ + +#define ARCH_MAXTIMERS 4 +#define HWTIMER_SPEED 1000000 +#define HWTIMER_MAXTICKS (0xFFFFFFFF) + +#define HWTIMER_MSEC (HWTIMER_SPEED/1000) +#define HWTIMER_SEC (HWTIMER_SPEED) + +#endif /* HWTIMER_CPU_H_ */ diff --git a/cpu/arm_common/syscalls.c b/cpu/arm_common/syscalls.c new file mode 100644 index 0000000000..a1e583f4a1 --- /dev/null +++ b/cpu/arm_common/syscalls.c @@ -0,0 +1,239 @@ +/****************************************************************************** +Copyright 2008, Freie Universitaet Berlin (FUB). All rights reserved. + +These sources were developed at the Freie Universitaet Berlin, Computer Systems +and Telematics group (http://cst.mi.fu-berlin.de). +------------------------------------------------------------------------------- +This file is part of FeuerWare. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +FeuerWare is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see http://www.gnu.org/licenses/ . +-------------------------------------------------------------------------------- +For further information and questions please use the web site + http://scatterweb.mi.fu-berlin.de +and the mailinglist (subscription via web site) + scatterweb@lists.spline.inf.fu-berlin.de +*******************************************************************************/ + +/** + * @file + * @ingroup lpc2387 + * @brief LPC2387 NewLib system calls implementation + * + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @author Michael Baar + * @version $Revision$ + * + * @note $Id$ + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +// core +#include "kernel.h" + +#define DEBUG_SYSCALLS 0 +#if DEBUG_SYSCALLS +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif + +/** + * @name Heaps (defined in linker script) + * @{ + */ +#define NUM_HEAPS 2 + +extern uintptr_t __heap1_start; ///< start of heap memory space +extern uintptr_t __heap1_max; ///< maximum for end of heap memory space +extern uintptr_t __heap2_start; ///< start of heap memory space +extern uintptr_t __heap2_max; ///< maximum for end of heap memory space + +/// current position in heap +static caddr_t heap[NUM_HEAPS] = {(caddr_t)&__heap1_start,(caddr_t)&__heap2_start}; +/// maximum position in heap +static const caddr_t heap_max[NUM_HEAPS] = {(caddr_t)&__heap1_max,(caddr_t)&__heap2_max}; +/** @} */ + +/*-----------------------------------------------------------------------------------*/ +void __assert_func(const char *file, int line, const char *func, const char *failedexpr) +{ + printf("#! assertion %s failed\n\t%s() in %s:%u\n", failedexpr, func, file, line ); + _exit(3); +} +/*-----------------------------------------------------------------------------------*/ +void __assert(const char *file, int line, const char *failedexpr) +{ + __assert_func(file, line, "?", failedexpr); +} +/*-----------------------------------------------------------------------------------*/ +caddr_t _sbrk_r(struct _reent *r, size_t incr) +{ + /* check all heaps for a chunk of the requested size */ + for( int i = 0; i < NUM_HEAPS; i++ ) { + caddr_t new_heap = heap[i] + incr; + + if( new_heap <= heap_max[i] ) { + caddr_t prev_heap = heap[i]; + heap[i] = new_heap; + + r->_errno = 0; + return prev_heap; + } + + } + + return NULL; +} +/*---------------------------------------------------------------------------*/ +int _isatty_r(struct _reent *r, int fd) +{ + r->_errno = 0; + if( fd == STDOUT_FILENO || fd == STDERR_FILENO ) + return 1; + else + return 0; +} +/*---------------------------------------------------------------------------*/ +_off_t _lseek_r(struct _reent *r, int fd, _off_t pos, int whence) +{ + _off_t result = -1; + PRINTF("lseek [%i] pos %li whence %i\n", fd, pos, whence); + + r->_errno = ENODEV; + + PRINTF("lseek returned %li (0 is success)\n", result); + return result; +} +/*---------------------------------------------------------------------------*/ +int _open_r(struct _reent *r, const char *name, int mode) +{ + int ret = -1; + PRINTF("open '%s' mode %#x\n", name, mode); + + r->_errno = ENODEV; + + PRINTF("open [%i] errno %i\n", ret, r->_errno); + return ret; +} +/*---------------------------------------------------------------------------*/ +int _stat_r(struct _reent *r, char *name, struct stat *st) +{ + int ret = -1; + + r->_errno = ENODEV; + + return ret; +} +/*---------------------------------------------------------------------------*/ +int _fstat_r(struct _reent *r, int fd, struct stat * st) +{ + int ret = -1; + + memset(st, 0, sizeof(*st)); + if( fd == STDOUT_FILENO || fd == STDERR_FILENO ) { + st->st_mode = S_IFCHR; + ret = 0; + } else { + r->_errno = ENODEV; + } + return ret; +} + +extern int fw_puts(char* data, int count); + +/*---------------------------------------------------------------------------*/ +int _write_r(struct _reent *r, int fd, const void *data, unsigned int count) +{ + int result = EOF; + r->_errno = 0; + + switch(fd) { + case STDOUT_FILENO: + case STDERR_FILENO: + result = fw_puts((char*)data, count); + break; + + default: + PRINTF("write [%i] data @%p count %i\n", fd, data, count); + + PRINTF("write [%i] returned %i errno %i\n", fd, result, r->_errno); + break; + } + + return result; +} +/*---------------------------------------------------------------------------*/ +int _read_r(struct _reent *r, int fd, void *buffer, unsigned int count) +{ + int result = EOF; + r->_errno = 0; + + PRINTF("read [%i] buffer @%p count %i\n", fd, buffer, count); + PRINTF("read [%i] returned %i\n", fd, result); + + return result; +} +/*---------------------------------------------------------------------------*/ +int _close_r(struct _reent *r, int fd) +{ + int result = 0; + r->_errno = 0; + + PRINTF("close [%i]\n", fd); + PRINTF("close returned %i errno %i\n", result, errno); + + return result; +} +/*---------------------------------------------------------------------------*/ +int _unlink_r(struct _reent *r, char* path) +{ + int result = -1; + r->_errno = ENODEV; + + PRINTF("unlink '%s'\n", path); + PRINTF("unlink returned %i errno %i\n", result, errno); + + return result; +} +/*---------------------------------------------------------------------------*/ +void _exit(int n) +{ + printf("#! exit %i: resetting\n", n); + + stdio_flush(); + + while(1); + + arm_reset(); +} +/*---------------------------------------------------------------------------*/ +int _getpid(void) +{ + return fk_thread->pid; +} +/*---------------------------------------------------------------------------*/ +int _kill_r(struct _reent *r, int pid, int sig) +{ + r->_errno = ESRCH; // no such process + return -1; +} +/*---------------------------------------------------------------------------*/ diff --git a/cpu/lpc214x/Jamfile b/cpu/lpc214x/Jamfile new file mode 100644 index 0000000000..2e82c4c061 --- /dev/null +++ b/cpu/lpc214x/Jamfile @@ -0,0 +1,33 @@ +# ****************************************************************************** +# Copyright 2009, Freie Universitaet Berlin (FUB). All rights reserved. +# +# These sources were developed at the Freie Universitaet Berlin, Computer +# Systems and Telematics group (http://cst.mi.fu-berlin.de). +# ------------------------------------------------------------------------------ +# This file is part of FeuerWare. +# +# This program is free software: you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation, either version 3 of the License, or (at your option) any later +# version. +# +# FeuerWare is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with +# this program. If not, see http://www.gnu.org/licenses/ . +# ------------------------------------------------------------------------------ +# For further information and questions please use the web site +# http://scatterweb.mi.fu-berlin.de +# and the mailinglist (subscription via web site) +# scatterweb@lists.spline.inf.fu-berlin.de +# ****************************************************************************** + +SubDir TOP cpu lpc214x ; + +Library cpu.a : cpu.c ; + +Objects startup.s ; + +SubInclude TOP cpu arm_common ; diff --git a/cpu/lpc214x/cpu.c b/cpu/lpc214x/cpu.c new file mode 100644 index 0000000000..322d289b0c --- /dev/null +++ b/cpu/lpc214x/cpu.c @@ -0,0 +1,41 @@ +#include "cpu.h" +#include "bits.h" +#include "VIC.h" + +void cpu_clock_scale(uint32_t source, uint32_t target, uint32_t* prescale) { + *prescale = source / PCLK_DIV / target; +} + +/****************************************************************************** +** Function name: install_irq +** +** Descriptions: Install interrupt handler +** parameters: Interrupt number, interrupt handler address, +** interrupt priority +** Returned value: true or false, return false if IntNum is out of range +** +******************************************************************************/ +#define VIC_BASE_ADDR 0xFFFFF000 + +bool cpu_install_irq( int IntNumber, void *HandlerAddr, int Priority ) +{ + int *vect_addr; + int *vect_cntl; + + VICIntEnClear = 1 << IntNumber; /* Disable Interrupt */ + if ( IntNumber >= VIC_SIZE ) + { + return ( false ); + } + else + { + /* find first un-assigned VIC address for the handler */ + vect_addr = (int *)(VIC_BASE_ADDR + VECT_ADDR_INDEX + Priority*4); + vect_cntl = (int *)(VIC_BASE_ADDR + VECT_CNTL_INDEX + Priority*4); + + *vect_addr = (int)HandlerAddr; /* set interrupt vector */ + *vect_cntl = IntNumber + BIT5; + VICIntEnable = 1 << IntNumber; /* Enable Interrupt */ + return( true ); + } +} diff --git a/cpu/lpc214x/include/cpu.h b/cpu/lpc214x/include/cpu.h new file mode 100644 index 0000000000..e439e61fd1 --- /dev/null +++ b/cpu/lpc214x/include/cpu.h @@ -0,0 +1,33 @@ +/****************************************************************************** +Copyright 2009, Freie Universitaet Berlin (FUB). All rights reserved. + +These sources were developed at the Freie Universitaet Berlin, Computer Systems +and Telematics group (http://cst.mi.fu-berlin.de). +------------------------------------------------------------------------------- +This file is part of FeuerWare. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +FeuerWare is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see http://www.gnu.org/licenses/ . +-------------------------------------------------------------------------------- +For further information and questions please use the web site + http://scatterweb.mi.fu-berlin.de +and the mailinglist (subscription via web site) + scatterweb@lists.spline.inf.fu-berlin.de +*******************************************************************************/ + +#ifndef __CPU_H +#define __CPU_H + +#include "arm_cpu.h" +#include "lpc2148.h" + +#endif /* __CPU_H */ diff --git a/cpu/lpc214x/include/lpc2148.h b/cpu/lpc214x/include/lpc2148.h new file mode 100644 index 0000000000..5b56818ca1 --- /dev/null +++ b/cpu/lpc214x/include/lpc2148.h @@ -0,0 +1,24 @@ +/* + * lpc2148.h + * + * Copyright (C) 2009 Kaspar Schleiser + * + * Parts taken from FeuerWhere-Project, lpc2148.h. + */ + +#ifndef __LPC2148_H +#define __LPC2148_H + +#include "lpc214x.h" + +#define F_CCO 240000000 +#define CL_CPU_DIV 4 ///< CPU clock divider +#define F_CPU (F_CCO / CL_CPU_DIV) ///< CPU target speed in Hz +#define F_RC_OSCILLATOR 12000000 ///< Frequency of internal RC oscillator +#define F_RTC_OSCILLATOR 32767 ///< Frequency of RTC oscillator +#define PCLK_DIV 0x2 ///< PCLK clock divider, F_CPU/PCLK_DIV=PCLK + +#define VIC_SIZE 16 + +#endif // __LPC2148_H + diff --git a/cpu/lpc214x/include/lpc214x.h b/cpu/lpc214x/include/lpc214x.h new file mode 100644 index 0000000000..74f875d091 --- /dev/null +++ b/cpu/lpc214x/include/lpc214x.h @@ -0,0 +1,438 @@ +/* Copyright (C) 2005, 2006, 2007, 2008 by Thomas Hillebrandt and Heiko Will + +This file is part of the Micro-mesh SensorWeb Firmware. + +Micro-Mesh is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +Micro-Mesh is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Micro-Mesh; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +/* As a special exception, if you include this header file into source + files compiled by GCC, this header file does not by itself cause + the resulting executable to be covered by the GNU General Public + License. This exception does not however invalidate any other + reasons why the executable file might be covered by the GNU General + Public License. */ + +#ifndef __LPC214x_H +#define __LPC214x_H +#define BIT0 0x00000001 +#define BIT1 0x00000002 +#define BIT2 0x00000004 +#define BIT3 0x00000008 +#define BIT4 0x00000010 +#define BIT5 0x00000020 +#define BIT6 0x00000040 +#define BIT7 0x00000080 +#define BIT8 0x00000100 +#define BIT9 0x00000200 +#define BIT10 0x00000400 +#define BIT11 0x00000800 +#define BIT12 0x00001000 +#define BIT13 0x00002000 +#define BIT14 0x00004000 +#define BIT15 0x00008000 +#define BIT16 0x00010000 +#define BIT17 0x00020000 +#define BIT18 0x00040000 +#define BIT19 0x00080000 +#define BIT20 0x00100000 +#define BIT21 0x00200000 +#define BIT22 0x00400000 +#define BIT23 0x00800000 +#define BIT24 0x01000000 +#define BIT25 0x02000000 +#define BIT26 0x04000000 +#define BIT27 0x08000000 +#define BIT28 0x10000000 +#define BIT29 0x20000000 +#define BIT30 0x40000000 +#define BIT31 0x80000000 + +/* Vectored Interrupt Controller (VIC) */ +#define VICIRQStatus (*((volatile unsigned long *) 0xFFFFF000)) +#define VICFIQStatus (*((volatile unsigned long *) 0xFFFFF004)) +#define VICRawIntr (*((volatile unsigned long *) 0xFFFFF008)) +#define VICIntSelect (*((volatile unsigned long *) 0xFFFFF00C)) +#define VICIntEnable (*((volatile unsigned long *) 0xFFFFF010)) +#define VICIntEnClr (*((volatile unsigned long *) 0xFFFFF014)) +#define VICIntEnClear (*((volatile unsigned long *) 0xFFFFF014)) +#define VICSoftInt (*((volatile unsigned long *) 0xFFFFF018)) +#define VICSoftIntClr (*((volatile unsigned long *) 0xFFFFF01C)) +#define VICProtection (*((volatile unsigned long *) 0xFFFFF020)) +#define VICVectAddr (*((volatile unsigned long *) 0xFFFFF030)) +#define VICDefVectAddr (*((volatile unsigned long *) 0xFFFFF034)) +#define VICVectAddr0 (*((volatile unsigned long *) 0xFFFFF100)) +#define VICVectAddr1 (*((volatile unsigned long *) 0xFFFFF104)) +#define VICVectAddr2 (*((volatile unsigned long *) 0xFFFFF108)) +#define VICVectAddr3 (*((volatile unsigned long *) 0xFFFFF10C)) +#define VICVectAddr4 (*((volatile unsigned long *) 0xFFFFF110)) +#define VICVectAddr5 (*((volatile unsigned long *) 0xFFFFF114)) +#define VICVectAddr6 (*((volatile unsigned long *) 0xFFFFF118)) +#define VICVectAddr7 (*((volatile unsigned long *) 0xFFFFF11C)) +#define VICVectAddr8 (*((volatile unsigned long *) 0xFFFFF120)) +#define VICVectAddr9 (*((volatile unsigned long *) 0xFFFFF124)) +#define VICVectAddr10 (*((volatile unsigned long *) 0xFFFFF128)) +#define VICVectAddr11 (*((volatile unsigned long *) 0xFFFFF12C)) +#define VICVectAddr12 (*((volatile unsigned long *) 0xFFFFF130)) +#define VICVectAddr13 (*((volatile unsigned long *) 0xFFFFF134)) +#define VICVectAddr14 (*((volatile unsigned long *) 0xFFFFF138)) +#define VICVectAddr15 (*((volatile unsigned long *) 0xFFFFF13C)) +#define VICVectCntl0 (*((volatile unsigned long *) 0xFFFFF200)) +#define VICVectCntl1 (*((volatile unsigned long *) 0xFFFFF204)) +#define VICVectCntl2 (*((volatile unsigned long *) 0xFFFFF208)) +#define VICVectCntl3 (*((volatile unsigned long *) 0xFFFFF20C)) +#define VICVectCntl4 (*((volatile unsigned long *) 0xFFFFF210)) +#define VICVectCntl5 (*((volatile unsigned long *) 0xFFFFF214)) +#define VICVectCntl6 (*((volatile unsigned long *) 0xFFFFF218)) +#define VICVectCntl7 (*((volatile unsigned long *) 0xFFFFF21C)) +#define VICVectCntl8 (*((volatile unsigned long *) 0xFFFFF220)) +#define VICVectCntl9 (*((volatile unsigned long *) 0xFFFFF224)) +#define VICVectCntl10 (*((volatile unsigned long *) 0xFFFFF228)) +#define VICVectCntl11 (*((volatile unsigned long *) 0xFFFFF22C)) +#define VICVectCntl12 (*((volatile unsigned long *) 0xFFFFF230)) +#define VICVectCntl13 (*((volatile unsigned long *) 0xFFFFF234)) +#define VICVectCntl14 (*((volatile unsigned long *) 0xFFFFF238)) +#define VICVectCntl15 (*((volatile unsigned long *) 0xFFFFF23C)) + +/* Pin Connect Block */ +#define PINSEL0 (*((volatile unsigned long *) 0xE002C000)) +#define PINSEL1 (*((volatile unsigned long *) 0xE002C004)) +#define PINSEL2 (*((volatile unsigned long *) 0xE002C014)) + +/* General Purpose Input/Output (GPIO) */ +#define IOPIN0 (*((volatile unsigned long *) 0xE0028000)) +#define IOSET0 (*((volatile unsigned long *) 0xE0028004)) +#define IODIR0 (*((volatile unsigned long *) 0xE0028008)) +#define IOCLR0 (*((volatile unsigned long *) 0xE002800C)) +#define IOPIN1 (*((volatile unsigned long *) 0xE0028010)) +#define IOSET1 (*((volatile unsigned long *) 0xE0028014)) +#define IODIR1 (*((volatile unsigned long *) 0xE0028018)) +#define IOCLR1 (*((volatile unsigned long *) 0xE002801C)) +#define IO0PIN (*((volatile unsigned long *) 0xE0028000)) +#define IO0SET (*((volatile unsigned long *) 0xE0028004)) +#define IO0DIR (*((volatile unsigned long *) 0xE0028008)) +#define IO0CLR (*((volatile unsigned long *) 0xE002800C)) +#define IO1PIN (*((volatile unsigned long *) 0xE0028010)) +#define IO1SET (*((volatile unsigned long *) 0xE0028014)) +#define IO1DIR (*((volatile unsigned long *) 0xE0028018)) +#define IO1CLR (*((volatile unsigned long *) 0xE002801C)) +#define FIO0DIR (*((volatile unsigned long *) 0x3FFFC000)) +#define FIO0MASK (*((volatile unsigned long *) 0x3FFFC010)) +#define FIO0PIN (*((volatile unsigned long *) 0x3FFFC014)) +#define FIO0SET (*((volatile unsigned long *) 0x3FFFC018)) +#define FIO0CLR (*((volatile unsigned long *) 0x3FFFC01C)) +#define FIO1DIR (*((volatile unsigned long *) 0x3FFFC020)) +#define FIO1MASK (*((volatile unsigned long *) 0x3FFFC030)) +#define FIO1PIN (*((volatile unsigned long *) 0x3FFFC034)) +#define FIO1SET (*((volatile unsigned long *) 0x3FFFC038)) +#define FIO1CLR (*((volatile unsigned long *) 0x3FFFC03C)) + +/* Memory Accelerator Module (MAM) */ +#define MAMCR (*((volatile unsigned char *) 0xE01FC000)) +#define MAMTIM (*((volatile unsigned char *) 0xE01FC004)) +#define MEMMAP (*((volatile unsigned char *) 0xE01FC040)) + +/* Phase Locked Loop 0 (PLL0) */ +#define PLL0CON (*((volatile unsigned char *) 0xE01FC080)) +#define PLL0CFG (*((volatile unsigned char *) 0xE01FC084)) +#define PLL0STAT (*((volatile unsigned short*) 0xE01FC088)) +#define PLL0FEED (*((volatile unsigned char *) 0xE01FC08C)) + +/* Phase Locked Loop 1 (PLL1) */ +#define PLL1CON (*((volatile unsigned char *) 0xE01FC0A0)) +#define PLL1CFG (*((volatile unsigned char *) 0xE01FC0A4)) +#define PLL1STAT (*((volatile unsigned short*) 0xE01FC0A8)) +#define PLL1FEED (*((volatile unsigned char *) 0xE01FC0AC)) + +/* VPB Divider */ +#define VPBDIV (*((volatile unsigned char *) 0xE01FC100)) + +/* Power Control */ +#define PCON (*((volatile unsigned char *) 0xE01FC0C0)) +#define PCONP (*((volatile unsigned long *) 0xE01FC0C4)) + +/* External Interrupts */ +#define EXTINT (*((volatile unsigned char *) 0xE01FC140)) +#define INTWAKE (*((volatile unsigned short*) 0xE01FC144)) +#define EXTMODE (*((volatile unsigned char *) 0xE01FC148)) +#define EXTPOLAR (*((volatile unsigned char *) 0xE01FC14C)) + +/* Reset */ +#define RSID (*((volatile unsigned char *) 0xE01FC180)) + +/* Code Security / Debugging */ +#define CSPR (*((volatile unsigned char *) 0xE01FC184)) + +/* System Control Miscellaneous */ +#define SCS (*((volatile unsigned long *) 0xE01FC1A0)) + +/* Timer 0 */ +#define TMR0_BASE_ADDR 0xE0004000 +#define T0IR (*((volatile unsigned long *) 0xE0004000)) +#define T0TCR (*((volatile unsigned long *) 0xE0004004)) +#define T0TC (*((volatile unsigned long *) 0xE0004008)) +#define T0PR (*((volatile unsigned long *) 0xE000400C)) +#define T0PC (*((volatile unsigned long *) 0xE0004010)) +#define T0MCR (*((volatile unsigned long *) 0xE0004014)) +#define T0MR0 (*((volatile unsigned long *) 0xE0004018)) +#define T0MR1 (*((volatile unsigned long *) 0xE000401C)) +#define T0MR2 (*((volatile unsigned long *) 0xE0004020)) +#define T0MR3 (*((volatile unsigned long *) 0xE0004024)) +#define T0CCR (*((volatile unsigned long *) 0xE0004028)) +#define T0CR0 (*((volatile unsigned long *) 0xE000402C)) +#define T0CR1 (*((volatile unsigned long *) 0xE0004030)) +#define T0CR2 (*((volatile unsigned long *) 0xE0004034)) +#define T0CR3 (*((volatile unsigned long *) 0xE0004038)) +#define T0EMR (*((volatile unsigned long *) 0xE000403C)) +#define T0CTCR (*((volatile unsigned long *) 0xE0004070)) + +/* Timer 1 */ +#define TMR1_BASE_ADDR 0xE0008000 +#define T1IR (*((volatile unsigned long *) 0xE0008000)) +#define T1TCR (*((volatile unsigned long *) 0xE0008004)) +#define T1TC (*((volatile unsigned long *) 0xE0008008)) +#define T1PR (*((volatile unsigned long *) 0xE000800C)) +#define T1PC (*((volatile unsigned long *) 0xE0008010)) +#define T1MCR (*((volatile unsigned long *) 0xE0008014)) +#define T1MR0 (*((volatile unsigned long *) 0xE0008018)) +#define T1MR1 (*((volatile unsigned long *) 0xE000801C)) +#define T1MR2 (*((volatile unsigned long *) 0xE0008020)) +#define T1MR3 (*((volatile unsigned long *) 0xE0008024)) +#define T1CCR (*((volatile unsigned long *) 0xE0008028)) +#define T1CR0 (*((volatile unsigned long *) 0xE000802C)) +#define T1CR1 (*((volatile unsigned long *) 0xE0008030)) +#define T1CR2 (*((volatile unsigned long *) 0xE0008034)) +#define T1CR3 (*((volatile unsigned long *) 0xE0008038)) +#define T1EMR (*((volatile unsigned long *) 0xE000803C)) +#define T1CTCR (*((volatile unsigned long *) 0xE0008070)) + +/* Pulse Width Modulator (PWM) */ +#define PWMIR (*((volatile unsigned long *) 0xE0014000)) +#define PWMTCR (*((volatile unsigned long *) 0xE0014004)) +#define PWMTC (*((volatile unsigned long *) 0xE0014008)) +#define PWMPR (*((volatile unsigned long *) 0xE001400C)) +#define PWMPC (*((volatile unsigned long *) 0xE0014010)) +#define PWMMCR (*((volatile unsigned long *) 0xE0014014)) +#define PWMMR0 (*((volatile unsigned long *) 0xE0014018)) +#define PWMMR1 (*((volatile unsigned long *) 0xE001401C)) +#define PWMMR2 (*((volatile unsigned long *) 0xE0014020)) +#define PWMMR3 (*((volatile unsigned long *) 0xE0014024)) +#define PWMMR4 (*((volatile unsigned long *) 0xE0014040)) +#define PWMMR5 (*((volatile unsigned long *) 0xE0014044)) +#define PWMMR6 (*((volatile unsigned long *) 0xE0014048)) +#define PWMPCR (*((volatile unsigned long *) 0xE001404C)) +#define PWMLER (*((volatile unsigned long *) 0xE0014050)) + +/* Universal Asynchronous Receiver Transmitter 0 (UART0) */ +#define U0RBR (*((volatile unsigned char *) 0xE000C000)) +#define U0THR (*((volatile unsigned char *) 0xE000C000)) +#define U0IER (*((volatile unsigned long *) 0xE000C004)) +#define U0IIR (*((volatile unsigned long *) 0xE000C008)) +#define U0FCR (*((volatile unsigned char *) 0xE000C008)) +#define U0LCR (*((volatile unsigned char *) 0xE000C00C)) +#define U0MCR (*((volatile unsigned char *) 0xE000C010)) +#define U0LSR (*((volatile unsigned char *) 0xE000C014)) +#define U0MSR (*((volatile unsigned char *) 0xE000C018)) +#define U0SCR (*((volatile unsigned char *) 0xE000C01C)) +#define U0DLL (*((volatile unsigned char *) 0xE000C000)) +#define U0DLM (*((volatile unsigned char *) 0xE000C004)) +#define U0ACR (*((volatile unsigned long *) 0xE000C020)) +#define U0FDR (*((volatile unsigned long *) 0xE000C028)) +#define U0TER (*((volatile unsigned char *) 0xE000C030)) + +/* Universal Asynchronous Receiver Transmitter 1 (UART1) */ +#define U1RBR (*((volatile unsigned char *) 0xE0010000)) +#define U1THR (*((volatile unsigned char *) 0xE0010000)) +#define U1IER (*((volatile unsigned long *) 0xE0010004)) +#define U1IIR (*((volatile unsigned long *) 0xE0010008)) +#define U1FCR (*((volatile unsigned char *) 0xE0010008)) +#define U1LCR (*((volatile unsigned char *) 0xE001000C)) +#define U1MCR (*((volatile unsigned char *) 0xE0010010)) +#define U1LSR (*((volatile unsigned char *) 0xE0010014)) +#define U1MSR (*((volatile unsigned char *) 0xE0010018)) +#define U1SCR (*((volatile unsigned char *) 0xE001001C)) +#define U1DLL (*((volatile unsigned char *) 0xE0010000)) +#define U1DLM (*((volatile unsigned char *) 0xE0010004)) +#define U1ACR (*((volatile unsigned long *) 0xE0010020)) +#define U1FDR (*((volatile unsigned long *) 0xE0010028)) +#define U1TER (*((volatile unsigned char *) 0xE0010030)) + +/* I2C Interface 0 */ +#define I2C0CONSET (*((volatile unsigned char *) 0xE001C000)) +#define I2C0STAT (*((volatile unsigned char *) 0xE001C004)) +#define I2C0DAT (*((volatile unsigned char *) 0xE001C008)) +#define I2C0ADR (*((volatile unsigned char *) 0xE001C00C)) +#define I2C0SCLH (*((volatile unsigned short*) 0xE001C010)) +#define I2C0SCLL (*((volatile unsigned short*) 0xE001C014)) +#define I2C0CONCLR (*((volatile unsigned char *) 0xE001C018)) + +/* I2C Interface 1 */ +#define I2C1CONSET (*((volatile unsigned char *) 0xE005C000)) +#define I2C1STAT (*((volatile unsigned char *) 0xE005C004)) +#define I2C1DAT (*((volatile unsigned char *) 0xE005C008)) +#define I2C1ADR (*((volatile unsigned char *) 0xE005C00C)) +#define I2C1SCLH (*((volatile unsigned short*) 0xE005C010)) +#define I2C1SCLL (*((volatile unsigned short*) 0xE005C014)) +#define I2C1CONCLR (*((volatile unsigned char *) 0xE005C018)) + +/* SPI0 (Serial Peripheral Interface 0) */ +#define S0SPCR (*((volatile unsigned short*) 0xE0020000)) +#define S0SPSR (*((volatile unsigned char *) 0xE0020004)) +#define S0SPDR (*((volatile unsigned short*) 0xE0020008)) +#define S0SPCCR (*((volatile unsigned char *) 0xE002000C)) +#define S0SPINT (*((volatile unsigned char *) 0xE002001C)) + +/* SSP Controller (SPI1) */ +#define SSPCR0 (*((volatile unsigned short*) 0xE0068000)) +#define SSPCR1 (*((volatile unsigned char *) 0xE0068004)) +#define SSPDR (*((volatile unsigned short*) 0xE0068008)) +#define SSPSR (*((volatile unsigned char *) 0xE006800C)) +#define SSPCPSR (*((volatile unsigned char *) 0xE0068010)) +#define SSPIMSC (*((volatile unsigned char *) 0xE0068014)) +#define SSPRIS (*((volatile unsigned char *) 0xE0068018)) +#define SSPMIS (*((volatile unsigned char *) 0xE006801C)) +#define SSPICR (*((volatile unsigned char *) 0xE0068020)) + +/* Real Time Clock */ +#define ILR (*((volatile unsigned char *) 0xE0024000)) +#define CTC (*((volatile unsigned short*) 0xE0024004)) +#define CCR (*((volatile unsigned char *) 0xE0024008)) +#define CIIR (*((volatile unsigned char *) 0xE002400C)) +#define AMR (*((volatile unsigned char *) 0xE0024010)) +#define CTIME0 (*((volatile unsigned long *) 0xE0024014)) +#define CTIME1 (*((volatile unsigned long *) 0xE0024018)) +#define CTIME2 (*((volatile unsigned long *) 0xE002401C)) +#define SEC (*((volatile unsigned char *) 0xE0024020)) +#define MINUTE (*((volatile unsigned char *) 0xE0024024)) +#define HOUR (*((volatile unsigned char *) 0xE0024028)) +#define DOM (*((volatile unsigned char *) 0xE002402C)) +#define DOW (*((volatile unsigned char *) 0xE0024030)) +#define DOY (*((volatile unsigned short*) 0xE0024034)) +#define MONTH (*((volatile unsigned char *) 0xE0024038)) +#define YEAR (*((volatile unsigned short*) 0xE002403C)) +#define ALSEC (*((volatile unsigned char *) 0xE0024060)) +#define ALMIN (*((volatile unsigned char *) 0xE0024064)) +#define ALHOUR (*((volatile unsigned char *) 0xE0024068)) +#define ALDOM (*((volatile unsigned char *) 0xE002406C)) +#define ALDOW (*((volatile unsigned char *) 0xE0024070)) +#define ALDOY (*((volatile unsigned short*) 0xE0024074)) +#define ALMON (*((volatile unsigned char *) 0xE0024078)) +#define ALYEAR (*((volatile unsigned short*) 0xE002407C)) +#define PREINT (*((volatile unsigned short*) 0xE0024080)) +#define PREFRAC (*((volatile unsigned short*) 0xE0024084)) + +/* A/D Converter 0 (AD0) */ +#define AD0CR (*((volatile unsigned long *) 0xE0034000)) +#define AD0GDR (*((volatile unsigned long *) 0xE0034004)) +#define AD0STAT (*((volatile unsigned long *) 0xE0034030)) +#define AD0INTEN (*((volatile unsigned long *) 0xE003400C)) +#define AD0DR0 (*((volatile unsigned long *) 0xE0034010)) +#define AD0DR1 (*((volatile unsigned long *) 0xE0034014)) +#define AD0DR2 (*((volatile unsigned long *) 0xE0034018)) +#define AD0DR3 (*((volatile unsigned long *) 0xE003401C)) +#define AD0DR4 (*((volatile unsigned long *) 0xE0034020)) +#define AD0DR5 (*((volatile unsigned long *) 0xE0034024)) +#define AD0DR6 (*((volatile unsigned long *) 0xE0034028)) +#define AD0DR7 (*((volatile unsigned long *) 0xE003402C)) + +/* A/D Converter 1 (AD1) */ +#define AD1CR (*((volatile unsigned long *) 0xE0060000)) +#define AD1GDR (*((volatile unsigned long *) 0xE0060004)) +#define AD1STAT (*((volatile unsigned long *) 0xE0060030)) +#define AD1INTEN (*((volatile unsigned long *) 0xE006000C)) +#define AD1DR0 (*((volatile unsigned long *) 0xE0060010)) +#define AD1DR1 (*((volatile unsigned long *) 0xE0060014)) +#define AD1DR2 (*((volatile unsigned long *) 0xE0060018)) +#define AD1DR3 (*((volatile unsigned long *) 0xE006001C)) +#define AD1DR4 (*((volatile unsigned long *) 0xE0060020)) +#define AD1DR5 (*((volatile unsigned long *) 0xE0060024)) +#define AD1DR6 (*((volatile unsigned long *) 0xE0060028)) +#define AD1DR7 (*((volatile unsigned long *) 0xE006002C)) + +/* A/D Converter Global */ +#define ADGSR (*((volatile unsigned long *) 0xE0034008)) + +/* D/A Converter */ +#define DACR (*((volatile unsigned long *) 0xE006C000)) + +/* Watchdog */ +#define WDMOD (*((volatile unsigned char *) 0xE0000000)) +#define WDTC (*((volatile unsigned long *) 0xE0000004)) +#define WDFEED (*((volatile unsigned char *) 0xE0000008)) +#define WDTV (*((volatile unsigned long *) 0xE000000C)) + +/* USB Controller */ +#define USBIntSt (*((volatile unsigned long *) 0xE01FC1C0)) +#define USBDevIntSt (*((volatile unsigned long *) 0xE0090000)) +#define USBDevIntEn (*((volatile unsigned long *) 0xE0090004)) +#define USBDevIntClr (*((volatile unsigned long *) 0xE0090008)) +#define USBDevIntSet (*((volatile unsigned long *) 0xE009000C)) +#define USBDevIntPri (*((volatile unsigned char *) 0xE009002C)) +#define USBEpIntSt (*((volatile unsigned long *) 0xE0090030)) +#define USBEpIntEn (*((volatile unsigned long *) 0xE0090034)) +#define USBEpIntClr (*((volatile unsigned long *) 0xE0090038)) +#define USBEpIntSet (*((volatile unsigned long *) 0xE009003C)) +#define USBEpIntPri (*((volatile unsigned long *) 0xE0090040)) +#define USBReEp (*((volatile unsigned long *) 0xE0090044)) +#define USBEpInd (*((volatile unsigned long *) 0xE0090048)) +#define USBMaxPSize (*((volatile unsigned long *) 0xE009004C)) +#define USBRxData (*((volatile unsigned long *) 0xE0090018)) +#define USBRxPLen (*((volatile unsigned long *) 0xE0090020)) +#define USBTxData (*((volatile unsigned long *) 0xE009001C)) +#define USBTxPLen (*((volatile unsigned long *) 0xE0090024)) +#define USBCtrl (*((volatile unsigned long *) 0xE0090028)) +#define USBCmdCode (*((volatile unsigned long *) 0xE0090010)) +#define USBCmdData (*((volatile unsigned long *) 0xE0090014)) +#define USBDMARSt (*((volatile unsigned long *) 0xE0090050)) +#define USBDMARClr (*((volatile unsigned long *) 0xE0090054)) +#define USBDMARSet (*((volatile unsigned long *) 0xE0090058)) +#define USBUDCAH (*((volatile unsigned long *) 0xE0090080)) +#define USBEpDMASt (*((volatile unsigned long *) 0xE0090084)) +#define USBEpDMAEn (*((volatile unsigned long *) 0xE0090088)) +#define USBEpDMADis (*((volatile unsigned long *) 0xE009008C)) +#define USBDMAIntSt (*((volatile unsigned long *) 0xE0090090)) +#define USBDMAIntEn (*((volatile unsigned long *) 0xE0090094)) +#define USBEoTIntSt (*((volatile unsigned long *) 0xE00900A0)) +#define USBEoTIntClr (*((volatile unsigned long *) 0xE00900A4)) +#define USBEoTIntSet (*((volatile unsigned long *) 0xE00900A8)) +#define USBNDDRIntSt (*((volatile unsigned long *) 0xE00900AC)) +#define USBNDDRIntClr (*((volatile unsigned long *) 0xE00900B0)) +#define USBNDDRIntSet (*((volatile unsigned long *) 0xE00900B4)) +#define USBSysErrIntSt (*((volatile unsigned long *) 0xE00900B8)) +#define USBSysErrIntClr (*((volatile unsigned long *) 0xE00900BC)) +#define USBSysErrIntSet (*((volatile unsigned long *) 0xE00900C0)) + + + +// Pheripherals + +#define PCTIM0 BIT1 +#define PCTIM1 BIT2 +#define PCUART0 BIT3 +#define PCUART1 BIT4 +#define PCPWM0 BIT5 +#define PCI2C0 BIT7 +#define PCSPI0 BIT8 +#define PCRTC BIT9 +#define PCSPI1 BIT10 +#define PCAD0 BIT12 +#define PCI2C1 BIT19 +#define PCAD1 BIT20 +#define PUSB BIT31 + +//inline void TurOffPeripheral(int p); +//inline void TurOnPeripheral(int p); + +#endif + diff --git a/cpu/lpc214x/linkerscript.x b/cpu/lpc214x/linkerscript.x new file mode 100644 index 0000000000..9a573998da --- /dev/null +++ b/cpu/lpc214x/linkerscript.x @@ -0,0 +1,197 @@ +/* ****************************************************************************************************** */ +/* demo2148_blink_flash.cmd LINKER SCRIPT */ +/* */ +/* */ +/* The Linker Script defines how the code and data emitted by the GNU C compiler and assembler are */ +/* to be loaded into memory (code goes into FLASH, variables go into RAM). */ +/* */ +/* Any symbols defined in the Linker Script are automatically global and available to the rest of the */ +/* program. */ +/* */ +/* To force the linker to use this LINKER SCRIPT, just add the -T demo2148_blink_flash.cmd directive */ +/* to the linker flags in the makefile. */ +/* */ +/* LFLAGS = -Map main.map -nostartfiles -T demo2148_blink_flash.cmd */ +/* */ +/* */ +/* The Philips boot loader supports the ISP (In System Programming) via the serial port and the IAP */ +/* (In Application Programming) for flash programming from within your application. */ +/* */ +/* The boot loader uses RAM memory and we MUST NOT load variables or code in these areas. */ +/* */ +/* RAM used by boot loader: 0x40000120 - 0x400001FF (223 bytes) for ISP variables */ +/* 0x40007FE0 - 0x4000FFFF (32 bytes) for ISP and IAP variables */ +/* 0x40007EE0 - 0x40007FE0 (256 bytes) stack for ISP and IAP */ +/* */ +/* */ +/* MEMORY MAP */ +/* | |0x40008000 */ +/* .-------->|---------------------------------| */ +/* . | variables and stack |0x40007FFF */ +/* ram_isp_high | for Philips boot loader | */ +/* . | 32 + 256 = 288 bytes | */ +/* . | | */ +/* . | Do not put anything here |0x40007EE0 */ +/* .-------->|---------------------------------| */ +/* | UDF Stack 4 bytes |0x40007EDC <---------- _stack_end */ +/* .-------->|---------------------------------| */ +/* | ABT Stack 4 bytes |0x40007ED8 */ +/* .-------->|---------------------------------| */ +/* | FIQ Stack 4 bytes |0x40007ED4 */ +/* .-------->|---------------------------------| */ +/* | IRQ Stack 4 bytes |0x40007ED0 */ +/* .-------->|---------------------------------| */ +/* | SVC Stack 4 bytes |0x40007ECC */ +/* .-------->|---------------------------------| */ +/* . | |0x40007EC8 */ +/* . | stack area for user program | */ +/* . | | | */ +/* . | | | */ +/* . | | | */ +/* . | V | */ +/* . | | */ +/* . | | */ +/* . | | */ +/* . | free ram | */ +/* ram | | */ +/* . | | */ +/* . | | */ +/* . |.................................|0x40000234 <---------- _bss_end */ +/* . | | */ +/* . | .bss uninitialized variables | */ +/* . |.................................|0x40000218 <---------- _bss_start, _edata */ +/* . | | */ +/* . | .data initialized variables | */ +/* . | |0x40000200 <---------- _data */ +/* .-------->|---------------------------------| */ +/* . | variables used by |0x400001FF */ +/* ram_isp_low | Philips boot loader | */ +/* . | 223 bytes |0x40000120 */ +/* .-------->|---------------------------------| */ +/* . | |0x4000011F */ +/* ram_vectors | free ram | */ +/* . |---------------------------------|0x40000040 */ +/* . | |0x4000003F */ +/* . | Interrupt Vectors (re-mapped) | */ +/* . | 64 bytes |0x40000000 */ +/* .-------->|---------------------------------| */ +/* | | */ +/* */ +/* */ +/* */ +/* | | */ +/* .--------> |---------------------------------| */ +/* . | |0x0001FFFF */ +/* . | | */ +/* . | | */ +/* . | | */ +/* . | | */ +/* . | | */ +/* . | unused flash eprom | */ +/* . | | */ +/* . |.................................|0x0000032c */ +/* . | | */ +/* . | copy of .data area | */ +/* flash | | */ +/* . |---------------------------------|0x00000314 <----------- _etext */ +/* . | | */ +/* . | |0x00000180 main */ +/* . | |0x00000278 feed */ +/* . | main() |0x000002c4 FIQ_Routine */ +/* . | |0x000002d8 SWI_Routine */ +/* . | |0x000002ec UNDEF_Routine */ +/* . | |0x000002b0 IRQ_routine */ +/* . |---------------------------------|0x000001cc initialize */ +/* . | |0x000000D4 */ +/* . | Startup Code | */ +/* . | (assembler) | */ +/* . | | */ +/* . |---------------------------------|0x00000040 Reset_Handler */ +/* . | |0x0000003F */ +/* . | Interrupt Vector Table (unused) | */ +/* . | 64 bytes | */ +/* .--------->|---------------------------------|0x00000000 _startup * +/* */ +/* */ +/* The easy way to prevent the linker from loading anything into a memory area is to define */ +/* a MEMORY region for it and then avoid assigning any .text, .data or .bss sections into it. */ +/* */ +/* */ +/* MEMORY */ +/* { */ +/* ram_isp_low(A) : ORIGIN = 0x40000120, LENGTH = 223 */ +/* */ +/* } */ +/* */ +/* */ +/* Author: James P. Lynch */ +/* */ +/* ****************************************************************************************************** */ + + +/* identify the Entry Point */ + +ENTRY(_startup) +/* STARTUP(bin/startup.o)*/ + + +/* specify the LPC2148 memory areas */ + +MEMORY +{ + flash : ORIGIN = 0, LENGTH = 512K /* FLASH ROM */ + ram_isp_low(A) : ORIGIN = 0x40000120, LENGTH = 223 /* variables used by Philips ISP bootloader */ + ram : ORIGIN = 0x40000200, LENGTH = 32513 /* free RAM area */ + ram_isp_high(A) : ORIGIN = 0x40007FE0, LENGTH = 32 /* variables used by Philips ISP bootloader */ + ram_usb_dma : ORIGIN = 0x7FD00000, LENGTH = 8192 /* on-chip USB DMA RAM area (not used) */ +} + + + +/* define a global symbol _stack_end */ + +_stack_end = 0x40007EDC; + + + +/* now define the output sections */ + +SECTIONS +{ + . = 0; /* set location counter to address zero */ + + .text : /* collect all sections that should go into FLASH after startup */ + { + *(.vectors) /* Exception Vectors and branch table >= 64 bytes */ + . = ALIGN(64); + *(.init) + *(.text) /* all .text sections (code) */ + *(.rodata) /* all .rodata sections (constants, strings, etc.) */ + *(.rodata*) /* all .rodata* sections (constants, strings, etc.) */ + *(.glue_7) /* all .glue_7 sections (no idea what these are) */ + *(.glue_7t) /* all .glue_7t sections (no idea what these are) */ + _etext = .; /* define a global symbol _etext just after the last code byte */ + } >flash /* put all the above into FLASH */ + + + + + .data : /* collect all initialized .data sections that go into RAM */ + { + _data = .; /* create a global symbol marking the start of the .data section */ + *(.data) /* all .data sections */ + _edata = .; /* define a global symbol marking the end of the .data section */ + } >ram AT >flash /* put all the above into RAM (but load the LMA copy into FLASH) */ + + .bss : /* collect all uninitialized .bss sections that go into RAM */ + { + _bss_start = .; /* define a global symbol marking the start of the .bss section */ + *(.bss) /* all .bss sections */ + } >ram /* put all the above in RAM (it will be cleared in the startup code */ + + . = ALIGN(4); /* advance location counter to the next 32-bit boundary */ + _bss_end = . ; /* define a global symbol marking the end of the .bss section */ +} + _end = .; /* define a global symbol marking the end of application RAM */ + PROVIDE(end = .); + diff --git a/cpu/lpc214x/startup.s b/cpu/lpc214x/startup.s new file mode 100644 index 0000000000..f9b1f6900a --- /dev/null +++ b/cpu/lpc214x/startup.s @@ -0,0 +1,112 @@ +/* *************************************************************************************************************** + + crt.s STARTUP ASSEMBLY CODE + ----------------------- + + + Module includes the interrupt vectors and start-up code. + + *************************************************************************************************************** */ + +/* Stack Sizes */ +.set UND_STACK_SIZE, 0x00000040 /* stack for "undefined instruction" interrupts */ +.set ABT_STACK_SIZE, 0x00000040 /* stack for "abort" interrupts */ +.set FIQ_STACK_SIZE, 0x00000040 /* stack for "FIQ" interrupts */ +.set IRQ_STACK_SIZE, 0X00000100 /* stack for "IRQ" normal interrupts */ +.set SVC_STACK_SIZE, 0x00000400 /* stack for "SVC" supervisor mode */ + + + +/* Standard definitions of Mode bits and Interrupt (I & F) flags in PSRs (program status registers) */ +.set MODE_USR, 0x10 /* Normal User Mode */ +.set MODE_FIQ, 0x11 /* FIQ Processing Fast Interrupts Mode */ +.set MODE_IRQ, 0x12 /* IRQ Processing Standard Interrupts Mode */ +.set MODE_SVC, 0x13 /* Supervisor Processing Software Interrupts Mode */ +.set MODE_ABT, 0x17 /* Abort Processing memory Faults Mode */ +.set MODE_UND, 0x1B /* Undefined Processing Undefined Instructions Mode */ +.set MODE_SYS, 0x1F /* System Running Priviledged Operating System Tasks Mode */ + +.set I_BIT, 0x80 /* when I bit is set, IRQ is disabled (program status registers) */ +.set F_BIT, 0x40 /* when F bit is set, FIQ is disabled (program status registers) */ + + +.text +.arm + +.global Reset_Handler +.global _startup +.func _startup + +_startup: + +# Exception Vectors + +_vectors: ldr PC, Reset_Addr + ldr PC, Undef_Addr + ldr PC, SWI_Addr + ldr PC, PAbt_Addr + ldr PC, DAbt_Addr + nop /* Reserved Vector (holds Philips ISP checksum) */ + ldr PC, IRQ_Addr /* see page 71 of "Insiders Guide to the Philips ARM7-Based Microcontrollers" by Trevor Martin */ + ldr PC, FIQ_Addr + +Reset_Addr: .word Reset_Handler /* defined in this module below */ +Undef_Addr: .word UNDEF_Routine /* defined in main.c */ +SWI_Addr: .word ctx_switch /* defined in main.c */ +PAbt_Addr: .word UNDEF_Routine /* defined in main.c */ +DAbt_Addr: .word UNDEF_Routine /* defined in main.c */ +IRQ_Addr: .word fk_cpu_irq_isr /* defined in main.c */ +FIQ_Addr: .word FIQ_Routine /* defined in main.c */ + .word 0 /* rounds the vectors and ISR addresses to 64 bytes total */ + + +# Reset Handler + +Reset_Handler: + + /* Setup a stack for each mode - note that this only sets up a usable stack + for User mode. Also each mode is setup with interrupts initially disabled. */ + + ldr r0, =_stack_end + msr CPSR_c, #MODE_UND|I_BIT|F_BIT /* Undefined Instruction Mode */ + mov sp, r0 + sub r0, r0, #UND_STACK_SIZE + msr CPSR_c, #MODE_ABT|I_BIT|F_BIT /* Abort Mode */ + mov sp, r0 + sub r0, r0, #ABT_STACK_SIZE + msr CPSR_c, #MODE_FIQ|I_BIT|F_BIT /* FIQ Mode */ + mov sp, r0 + sub r0, r0, #FIQ_STACK_SIZE + msr CPSR_c, #MODE_IRQ|I_BIT|F_BIT /* IRQ Mode */ + mov sp, r0 + sub r0, r0, #IRQ_STACK_SIZE + msr CPSR_c, #MODE_SVC|I_BIT|F_BIT /* Supervisor Mode */ + mov sp, r0 + sub r0, r0, #SVC_STACK_SIZE + msr CPSR_c, #MODE_SYS|I_BIT|F_BIT /* User Mode */ + mov sp, r0 + + /* copy .data section (Copy from ROM to RAM) */ + ldr R1, =_etext + ldr R2, =_data + ldr R3, =_edata +1: cmp R2, R3 + ldrlo R0, [R1], #4 + strlo R0, [R2], #4 + blo 1b + + /* Clear .bss section (Zero init) */ + mov R0, #0 + ldr R1, =_bss_start + ldr R2, =_bss_end +2: cmp R1, R2 + strlo R0, [R1], #4 + blo 2b + + /* Enter the C code */ + bl bootloader + b kernel_init + + +.endfunc +.end diff --git a/cpu/lpc2387/Jamfile b/cpu/lpc2387/Jamfile new file mode 100644 index 0000000000..6b5fb58edb --- /dev/null +++ b/cpu/lpc2387/Jamfile @@ -0,0 +1,39 @@ +# ****************************************************************************** +# Copyright 2009, Freie Universitaet Berlin (FUB). All rights reserved. +# +# These sources were developed at the Freie Universitaet Berlin, Computer +# Systems and Telematics group (http://cst.mi.fu-berlin.de). +# ------------------------------------------------------------------------------ +# This file is part of FeuerWare. +# +# This program is free software: you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation, either version 3 of the License, or (at your option) any later +# version. +# +# FeuerWare is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with +# this program. If not, see http://www.gnu.org/licenses/ . +# ------------------------------------------------------------------------------ +# For further information and questions please use the web site +# http://scatterweb.mi.fu-berlin.de +# and the mailinglist (subscription via web site) +# scatterweb@lists.spline.inf.fu-berlin.de +# ****************************************************************************** +# $Id$ + +SubDir TOP cpu lpc2387 ; + +Module cpu : cpu.c lpc2387-lpm.c ; +UseModule cpu ; + +Module rtc : lpc2387-rtc.c ; +Module gpioint : lpc2387-gpioint.c ; + +Objects startup.s ; + +#SubInclude TOP cpu lpc2387 drivers ; +SubInclude TOP cpu arm_common ; diff --git a/cpu/lpc2387/Jamrules.lpc2387 b/cpu/lpc2387/Jamrules.lpc2387 new file mode 100644 index 0000000000..40c6fd2aa9 --- /dev/null +++ b/cpu/lpc2387/Jamrules.lpc2387 @@ -0,0 +1,31 @@ +# ****************************************************************************** +# Copyright 2009, Freie Universitaet Berlin (FUB). All rights reserved. +# +# These sources were developed at the Freie Universitaet Berlin, Computer +# Systems and Telematics group (http://cst.mi.fu-berlin.de). +# ------------------------------------------------------------------------------ +# This file is part of FeuerWare. +# +# This program is free software: you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation, either version 3 of the License, or (at your option) any later +# version. +# +# FeuerWare is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with +# this program. If not, see http://www.gnu.org/licenses/ . +# ------------------------------------------------------------------------------ +# For further information and questions please use the web site +# http://scatterweb.mi.fu-berlin.de +# and the mailinglist (subscription via web site) +# scatterweb@lists.spline.inf.fu-berlin.de +# ****************************************************************************** +# $Id$ + +HDRS += [ FPath $(TOP) cpu $(CPU) drivers include ] ; +HDRS += [ FPath $(TOP) cpu $(CPU) hal include ] ; + +include [ FPath $(TOP) cpu arm_common Jamrules.arm_common ] ; \ No newline at end of file diff --git a/cpu/lpc2387/cpu.c b/cpu/lpc2387/cpu.c new file mode 100644 index 0000000000..5d2ff8c5c8 --- /dev/null +++ b/cpu/lpc2387/cpu.c @@ -0,0 +1,101 @@ +/****************************************************************************** +Copyright 2009, Freie Universitaet Berlin (FUB). All rights reserved. + +These sources were developed at the Freie Universitaet Berlin, Computer Systems +and Telematics group (http://cst.mi.fu-berlin.de). +------------------------------------------------------------------------------- +This file is part of FeuerWare. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +FeuerWare is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see http://www.gnu.org/licenses/ . +-------------------------------------------------------------------------------- +For further information and questions please use the web site + http://scatterweb.mi.fu-berlin.de +and the mailinglist (subscription via web site) + scatterweb@lists.spline.inf.fu-berlin.de +*******************************************************************************/ + +/** + * @ingroup lpc2387 + * @{ + */ + +#include "cpu.h" +#include +#include "VIC.h" + +void lpc2387_pclk_scale(uint32_t source, uint32_t target, uint32_t* pclksel, uint32_t* prescale) +{ + uint32_t pclkdiv; + *prescale = source / target; + + if( (*prescale % 16) == 0 ) { + *pclksel = 3; + pclkdiv = 8; + } else if( (*prescale % 8) == 0 ) { + *pclksel = 0; + pclkdiv = 4; + } else if( (*prescale % 4) == 0 ) { + *pclksel = 2; + pclkdiv = 2; + } else { + *pclksel = 1; + pclkdiv = 1; + } + *prescale /= pclkdiv; + + if( *prescale % 2 ) + (*prescale)++; +} + +void cpu_clock_scale(uint32_t source, uint32_t target, uint32_t* prescale) { + uint32_t pclksel; + + lpc2387_pclk_scale(source, target, &pclksel, prescale); + + PCLKSEL0 = (PCLKSEL0 & ~(BIT2|BIT3)) | (pclksel << 2); +} + +/****************************************************************************** +** Function name: install_irq +** +** Descriptions: Install interrupt handler +** parameters: Interrupt number, interrupt handler address, +** interrupt priority +** Returned value: true or false, return false if IntNum is out of range +** +******************************************************************************/ +#define VIC_BASE_ADDR 0xFFFFF000 + +bool install_irq( int IntNumber, void *HandlerAddr, int Priority ) +{ + int *vect_addr; + int *vect_cntl; + + VICIntEnClr = 1 << IntNumber; /* Disable Interrupt */ + if ( IntNumber >= VIC_SIZE ) + { + return ( false ); + } + else + { + /* find first un-assigned VIC address for the handler */ + vect_addr = (int *)(VIC_BASE_ADDR + VECT_ADDR_INDEX + IntNumber*4); + vect_cntl = (int *)(VIC_BASE_ADDR + VECT_CNTL_INDEX + IntNumber*4); + *vect_addr = (int)HandlerAddr; /* set interrupt vector */ + *vect_cntl = Priority; + VICIntEnable = 1 << IntNumber; /* Enable Interrupt */ + return( true ); + } +} + +/** @} */ diff --git a/cpu/lpc2387/doc/lpc2387.doc b/cpu/lpc2387/doc/lpc2387.doc new file mode 100644 index 0000000000..8706fdaca4 --- /dev/null +++ b/cpu/lpc2387/doc/lpc2387.doc @@ -0,0 +1,48 @@ +/** + * @defgroup lpc2387_intro LPC2387 Introduction + * @ingroup lpc2387 + +

First steps

+\li See the manual for toolchain and ide setup +\li Documentation + +

Components

+\li \ref arm_common +\li \ref lpc2387_rtc + +

Memory layout

+The following table gives a rough overview of the memory usage. For detailed values please +consider the map file generated by the linker (bin/[BOARD].map). + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
0x0
...
0x7FFFF
512 KB
64 b
remaining
Flash ROM
Vectors
Program
0x40000000
...
...
0x4000FFFF
64 KB
10-20 KB
remaining
5 KB
Main RAM
Variables
Heap
System stack
0x7FD0000016 KBUSB RAM
0x7FE00000
0x7FE00FFF
16 KB
16 KB
Ethernet RAM
Heap
0xE0084000
2 KBBattery RAM
+ +*/ diff --git a/cpu/lpc2387/include/cpu-conf.h b/cpu/lpc2387/include/cpu-conf.h new file mode 100644 index 0000000000..dd0a216d01 --- /dev/null +++ b/cpu/lpc2387/include/cpu-conf.h @@ -0,0 +1,88 @@ +/****************************************************************************** +Copyright 2009, Freie Universitaet Berlin (FUB). All rights reserved. + +These sources were developed at the Freie Universitaet Berlin, Computer Systems +and Telematics group (http://cst.mi.fu-berlin.de). +------------------------------------------------------------------------------- +This file is part of FeuerWare. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +FeuerWare is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see http://www.gnu.org/licenses/ . +-------------------------------------------------------------------------------- +For further information and questions please use the web site + http://scatterweb.mi.fu-berlin.de +and the mailinglist (subscription via web site) + scatterweb@lists.spline.inf.fu-berlin.de +*******************************************************************************/ + +#ifndef CPUCONF_H_ +#define CPUCONF_H_ + +/** + * @ingroup conf + * @ingroup lpc2387 + * + * @{ + */ + +/** + * @file + * @brief LPC2387 CPUconfiguration + * + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @author baar + * @version $Revision$ + * + * @note $Id$ + */ + +#define FEUERWARE_CONF_CPU_NAME "NXP LPC2387" + +/** + * @name CPU capabilities + * @{ + */ +#define FEUERWARE_CPU_LPC2387 1 +#define FEUERWARE_CONF_CORE_SUPPORTS_TIME 1 +/** @} */ + +/** + * @name Stdlib configuration + * @{ + */ +#define __FOPEN_MAX__ 4 +#define __FILENAME_MAX__ 12 +/** @} */ + +/** + * @name Kernel configuration + * @{ + */ +#ifndef KERNEL_CONF_STACKSIZE_DEFAULT +#define KERNEL_CONF_STACKSIZE_DEFAULT 2500 +#endif + +#define KERNEL_CONF_STACKSIZE_IDLE 500 +/** @} */ + +/** + * @name Compiler specifics + * @{ + */ +#define CC_CONF_INLINE inline +#define CC_CONF_USED __attribute__((used)) +#define CC_CONF_NONNULL(...) __attribute__((nonnull(__VA_ARGS__))) +#define CC_CONF_WARN_UNUSED_RESULT __attribute__((warn_unused_result)) +/** @} */ + +/** @} */ +#endif /* CPUCONF_H_ */ diff --git a/cpu/lpc2387/include/cpu.h b/cpu/lpc2387/include/cpu.h new file mode 100644 index 0000000000..70e2bc7e30 --- /dev/null +++ b/cpu/lpc2387/include/cpu.h @@ -0,0 +1,46 @@ +/****************************************************************************** +Copyright 2009, Freie Universitaet Berlin (FUB). All rights reserved. + +These sources were developed at the Freie Universitaet Berlin, Computer Systems +and Telematics group (http://cst.mi.fu-berlin.de). +------------------------------------------------------------------------------- +This file is part of FeuerWare. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +FeuerWare is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see http://www.gnu.org/licenses/ . +-------------------------------------------------------------------------------- +For further information and questions please use the web site + http://scatterweb.mi.fu-berlin.de +and the mailinglist (subscription via web site) + scatterweb@lists.spline.inf.fu-berlin.de +*******************************************************************************/ + +#ifndef __CPU_H +#define __CPU_H + +/** + * @defgroup lpc2387 NXP LPC2387 + * @ingroup cpu + * @{ + */ + +#include +#include "lpc2387.h" +#include "arm_cpu.h" + +extern uintptr_t __stack_start; ///< end of user stack memory space + +void lpc2387_pclk_scale(uint32_t source, uint32_t target, uint32_t* pclksel, uint32_t* prescale); +bool install_irq( int IntNumber, void *HandlerAddr, int Priority ); + +/** @} */ +#endif /* __CPU_H */ diff --git a/cpu/lpc2387/include/lpc2387-rtc.h b/cpu/lpc2387/include/lpc2387-rtc.h new file mode 100644 index 0000000000..4fb8f52e51 --- /dev/null +++ b/cpu/lpc2387/include/lpc2387-rtc.h @@ -0,0 +1,149 @@ +/****************************************************************************** +Copyright 2008, Freie Universitaet Berlin (FUB). All rights reserved. + +These sources were developed at the Freie Universitaet Berlin, Computer Systems +and Telematics group (http://cst.mi.fu-berlin.de). +------------------------------------------------------------------------------- +This file is part of FeuerWare. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +FeuerWare is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see http://www.gnu.org/licenses/ . +-------------------------------------------------------------------------------- +For further information and questions please use the web site + http://scatterweb.mi.fu-berlin.de +and the mailinglist (subscription via web site) + scatterweb@lists.spline.inf.fu-berlin.de +*******************************************************************************/ + +#ifndef __RTC_H +#define __RTC_H + +/** + * @defgroup lpc2387_rtc LPC2387 Real-Time-Clock + * @ingroup lpc2387 + * + * \section lpc2387_rtc_newlib Standard library support + * Currently reading and setting time and date through standard C functions is implemented. + * Standard C timers are not available. + * + * @{ + */ + +/** + * @file + * @brief LPC2387 Real-Time-Clock + * + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @version $Revision: 1998 $ + * + * @note $Id: lpc2387-rtc.h 1998 2010-03-16 13:05:41Z baar $ + */ + +#include +#include +#include "lpc2387.h" +#include "clock.h" + +/* ------------------------------------------------------------------------- */ +/** + * @name LPC2387 RTC Compile-Time Configuration + * @{ + */ + +/** @} */ + +/** + * @brief Mask for RTC alarms + * @see ::rtc_set_alarm, ::rtc_get_alarm + */ +enum rtc_alarm_mask { + RTC_AMR_DISABLED = 0, ///< Alarm disables + RTC_AMR_SEC = AMRSEC, ///< Alarm mask for Seconds + RTC_AMR_MIN = AMRMIN, ///< Alarm mask for Minutes + RTC_AMR_HOUR= AMRHOUR, ///< Alarm mask for Hours + RTC_AMR_DOM = AMRDOM, ///< Alarm mask for Day of Month + RTC_AMR_DOW = AMRDOW, ///< Alarm mask for Day of Week + RTC_AMR_DOY = AMRDOY, ///< Alarm mask for Day of Year + RTC_AMR_MON = AMRMON, ///< Alarm mask for Month + RTC_AMR_YEAR= AMRYEAR, ///< Alarm mask for Year +}; + +/** + * @brief Initializes the RTC + * @internal + * During reboots only alarms are reset. + */ +void _rtc_init(void); + +void _rtc_reset(void); + +/** + * @brief Returns the time of compilation in seconds + * @internal + */ +time_t rtc_get_compile_time(void) __attribute__((noinline)); + +/** + * @brief Returns the current clock time + * @param[out] time optional return value + * @return clock time in seconds + */ +time_t rtc_time(struct timeval* time); + +/** + * @brief Sets the current clock time + * @param[in] time new time in seconds + * @note Any set alarm is shifted + */ +void rtc_set(time_t time); + +/** + * @brief Enables the RTC + */ +void rtc_enable(void); + +/** + * @brief Disables the RTC + */ +void rtc_disable(void); + +/** + * @brief Returns the current time in broken down format directly from the RTC + * @param[out] localt Pointer to structure to receive time + */ +void rtc_get_localtime(struct tm* localt); + +/** + * @brief Sets the alarm + * @internal + * @param[in] localt Alarm time + * @param[in] mask Sets the registers to poll for the alarm + * + * To disable the alarm set mask to RTC_AMR_DISABLED. + * + * @see ::rtc_alarm_mask + */ +void _rtc_set_alarm(struct tm* localt, enum rtc_alarm_mask mask); + +/** + * @brief Gets the current alarm setting + * @internal + * @param[out] localt Pointer to structure to receive alarm time + * @return Alarm mask + * + * @see rtc_set_alarm + * @see ::rtc_alarm_mask + */ +enum rtc_alarm_mask _rtc_get_alarm(struct tm* localt); + +/** @} */ +#endif /* end __RTC_H */ diff --git a/cpu/lpc2387/include/lpc2387.h b/cpu/lpc2387/include/lpc2387.h new file mode 100644 index 0000000000..d70853a775 --- /dev/null +++ b/cpu/lpc2387/include/lpc2387.h @@ -0,0 +1,208 @@ +/* + * lpc2387.h + * + * Copyright (C) 2009 Kaspar Schleiser + * + * Parts taken from FeuerWhere-Project, lpc2387.h. + */ + +#ifndef __LPC2387_H +#define __LPC2387_H + +#include "lpc23xx.h" +#include "bitarithm.h" + +#define F_CCO 288000000 +#define CL_CPU_DIV 4 ///< CPU clock divider +#define F_CPU (F_CCO / CL_CPU_DIV) ///< CPU target speed in Hz +#define F_RC_OSCILLATOR 4000000 ///< Frequency of internal RC oscillator +#define F_RTC_OSCILLATOR 32767 ///< Frequency of RTC oscillator + +#define VIC_SIZE 32 + +#define GPIO_INT 17 +#define IRQP_GPIO 4 + +/** + * @name Timer Symbols + * @{ + */ +#define MR0I BIT0 +#define MR0R BIT1 +#define MR0S BIT2 +#define MR1I BIT3 +#define MR1R BIT4 +#define MR1S BIT5 +#define MR2I BIT6 +#define MR2R BIT7 +#define MR2S BIT8 +#define MR3I BIT9 +#define MR3R BIT10 +#define MR3S BIT11 +/** @} */ + +/** + * @name RTC constants + * @{ + */ +#define IMSEC 0x00000001 +#define IMMIN 0x00000002 +#define IMHOUR 0x00000004 +#define IMDOM 0x00000008 +#define IMDOW 0x00000010 +#define IMDOY 0x00000020 +#define IMMON 0x00000040 +#define IMYEAR 0x00000080 + +#define AMRSEC 0x00000001 /* Alarm mask for Seconds */ +#define AMRMIN 0x00000002 /* Alarm mask for Minutes */ +#define AMRHOUR 0x00000004 /* Alarm mask for Hours */ +#define AMRDOM 0x00000008 /* Alarm mask for Day of Month */ +#define AMRDOW 0x00000010 /* Alarm mask for Day of Week */ +#define AMRDOY 0x00000020 /* Alarm mask for Day of Year */ +#define AMRMON 0x00000040 /* Alarm mask for Month */ +#define AMRYEAR 0x00000080 /* Alarm mask for Year */ + +#define ILR_RTCCIF BIT0 +#define ILR_RTCALF BIT1 +#define ILR_RTSSF BIT2 + +#define CCR_CLKEN 0x01 +#define CCR_CTCRST 0x02 +#define CCR_CLKSRC 0x10 +/** @} */ + +/** + * @name WD constants + * @{ + */ +#define WDEN BIT0 +#define WDRESET BIT1 +#define WDTOF BIT2 +#define WDINT BIT3 +/** @} */ + +/** + * @name PCONP Constants + * @{ + */ +#define PCTIM0 BIT1 +#define PCTIM1 BIT2 +#define PCUART0 BIT3 +#define PCUART1 BIT4 +#define PCPWM1 BIT6 +#define PCI2C0 BIT7 +#define PCSPI BIT8 +#define PCRTC BIT9 +#define PCSSP1 BIT10 +#define PCEMC BIT11 +#define PCAD BIT12 +#define PCAN1 BIT13 +#define PCAN2 BIT14 +#define PCI2C1 BIT19 +#define PCSSP0 BIT21 +#define PCTIM2 BIT22 +#define PCTIM3 BIT23 +#define PCUART2 BIT24 +#define PCUART3 BIT25 +#define PCI2C2 BIT26 +#define PCI2S BIT27 +#define PCSDC BIT28 +#define PCGPDMA BIT29 +#define PCENET BIT30 +#define PCUSB BIT31 +/** @} */ + +/** + * @name PCON Constants + * @{ + */ +#define PM0 BIT0 +#define PM1 BIT1 +#define BODPDM BIT2 +#define BOGD BIT3 +#define BORD BIT4 +#define PM2 BIT7 + +#define PM_IDLE (PM0) +#define PM_SLEEP (PM2|PM0) +#define PM_POWERDOWN (PM1) +/** @} */ + +/** + * @name INTWAKE Constants + * @{ + */ +#define EXTWAKE0 BIT0 +#define EXTWAKE1 BIT1 +#define EXTWAKE2 BIT2 +#define EXTWAKE3 BIT3 +#define ETHWAKE BIT4 +#define USBWAKE BIT5 +#define CANWAKE BIT6 +#define GPIO0WAKE BIT7 +#define GPIO2WAKE BIT8 +#define BODWAKE BIT14 +#define RTCWAKE BIT15 +/** @} */ + +/** + * @name UART Constants + * @{ + */ +#define ULSR_RDR BIT0 +#define ULSR_OE BIT1 +#define ULSR_PE BIT2 +#define ULSR_FE BIT3 +#define ULSR_BI BIT4 +#define ULSR_THRE BIT5 +#define ULSR_TEMT BIT6 +#define ULSR_RXFE BIT7 + +#define UIIR_INT_STATUS (BIT0) ///< Interrupt Status +#define UIIR_THRE_INT (BIT1) ///< Transmit Holding Register Empty +#define UIIR_RDA_INT (BIT2) ///< Receive Data Available +#define UIIR_RLS_INT (BIT1 | BIT2) ///< Receive Line Status +#define UIIR_CTI_INT (BIT2 | BIT3) ///< Character Timeout Indicator +#define UIIR_ID_MASK (BIT1 | BIT2 | BIT3) +#define UIIR_ABEO_INT BIT8 +#define UIIR_ABTO_INT BIT9 +/** @} */ + +/** + * @name SSP Status Register Constants + * @{ + */ +#define SSPSR_TFE BIT0 ///< Transmit FIFO Empty. This bit is 1 is the Transmit FIFO is empty, 0 if not. +#define SSPSR_TNF BIT1 ///< Transmit FIFO Not Full. This bit is 0 if the Tx FIFO is full, 1 if not. +#define SSPSR_RNE BIT2 ///< Receive FIFO Not Empty. This bit is 0 if the Receive FIFO is empty, 1 if not. +#define SSPSR_RFF BIT3 ///< Receive FIFO Full. This bit is 1 if the Receive FIFO is full, 0 if not. +#define SSPSR_BSY BIT4 ///< Busy. This bit is 0 if the SSPn controller is idle, or 1 if it is currently sending/receiving a frame and/or the Tx FIFO is not empty. +/** @} */ + +/** + * @name Timer register offsets + * @{ + */ +#define TXIR 0x00 +#define TXTCR 0x04 +#define TXTC 0x08 ///< Timer counter +#define TXPR 0x0C +#define TXPC 0x10 +#define TXMCR 0x14 +#define TXMR0 0x18 +#define TXMR1 0x1C +#define TXMR2 0x20 +#define TXMR3 0x24 +#define TXCCR 0x28 +#define TXCR0 0x2C +#define TXCR1 0x30 +#define TXCR2 0x34 +#define TXCR3 0x38 +#define TXEMR 0x3C +#define TXCTCR 0x70 +/** @} */ +/** @} */ + +#endif // __LPC2387_H + diff --git a/cpu/lpc2387/include/lpc23xx.h b/cpu/lpc2387/include/lpc23xx.h new file mode 100644 index 0000000000..900fbb7fa0 --- /dev/null +++ b/cpu/lpc2387/include/lpc23xx.h @@ -0,0 +1,1131 @@ +/****************************************************************************** + * LPC23xx.h: Header file for NXP LPC23xx/24xx Family Microprocessors + * The header file is the super set of all hardware definition of the + * peripherals for the LPC23xx/24xx family microprocessor. + * + * Copyright(C) 2006, NXP Semiconductor + * All rights reserved. + * + * History + * 2005.10.01 ver 1.00 Prelimnary version, first Release + * 2007.05.17 ver 1.01 several corrections + * +******************************************************************************/ + +#ifndef __LPC23xx_H +#define __LPC23xx_H + +/* Vectored Interrupt Controller (VIC) */ +#define VIC_BASE_ADDR 0xFFFFF000 +#define VICIRQStatus (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x000)) +#define VICFIQStatus (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x004)) +#define VICRawIntr (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x008)) +#define VICIntSelect (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x00C)) +#define VICIntEnable (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x010)) +#define VICIntEnClr (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x014)) +#define VICSoftInt (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x018)) +#define VICSoftIntClr (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x01C)) +#define VICProtection (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x020)) +#define VICSWPrioMask (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x024)) + +#define VICVectAddr0 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x100)) +#define VICVectAddr1 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x104)) +#define VICVectAddr2 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x108)) +#define VICVectAddr3 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x10C)) +#define VICVectAddr4 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x110)) +#define VICVectAddr5 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x114)) +#define VICVectAddr6 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x118)) +#define VICVectAddr7 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x11C)) +#define VICVectAddr8 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x120)) +#define VICVectAddr9 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x124)) +#define VICVectAddr10 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x128)) +#define VICVectAddr11 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x12C)) +#define VICVectAddr12 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x130)) +#define VICVectAddr13 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x134)) +#define VICVectAddr14 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x138)) +#define VICVectAddr15 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x13C)) +#define VICVectAddr16 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x140)) +#define VICVectAddr17 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x144)) +#define VICVectAddr18 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x148)) +#define VICVectAddr19 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x14C)) +#define VICVectAddr20 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x150)) +#define VICVectAddr21 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x154)) +#define VICVectAddr22 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x158)) +#define VICVectAddr23 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x15C)) +#define VICVectAddr24 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x160)) +#define VICVectAddr25 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x164)) +#define VICVectAddr26 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x168)) +#define VICVectAddr27 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x16C)) +#define VICVectAddr28 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x170)) +#define VICVectAddr29 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x174)) +#define VICVectAddr30 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x178)) +#define VICVectAddr31 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x17C)) + +/* The name convention below is from previous LPC2000 family MCUs, in LPC23xx/24xx, +these registers are known as "VICVectPriority(x)". */ +#define VICVectCntl0 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x200)) +#define VICVectCntl1 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x204)) +#define VICVectCntl2 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x208)) +#define VICVectCntl3 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x20C)) +#define VICVectCntl4 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x210)) +#define VICVectCntl5 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x214)) +#define VICVectCntl6 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x218)) +#define VICVectCntl7 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x21C)) +#define VICVectCntl8 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x220)) +#define VICVectCntl9 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x224)) +#define VICVectCntl10 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x228)) +#define VICVectCntl11 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x22C)) +#define VICVectCntl12 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x230)) +#define VICVectCntl13 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x234)) +#define VICVectCntl14 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x238)) +#define VICVectCntl15 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x23C)) +#define VICVectCntl16 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x240)) +#define VICVectCntl17 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x244)) +#define VICVectCntl18 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x248)) +#define VICVectCntl19 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x24C)) +#define VICVectCntl20 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x250)) +#define VICVectCntl21 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x254)) +#define VICVectCntl22 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x258)) +#define VICVectCntl23 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x25C)) +#define VICVectCntl24 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x260)) +#define VICVectCntl25 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x264)) +#define VICVectCntl26 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x268)) +#define VICVectCntl27 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x26C)) +#define VICVectCntl28 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x270)) +#define VICVectCntl29 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x274)) +#define VICVectCntl30 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x278)) +#define VICVectCntl31 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x27C)) + +#define VICVectAddr (*(volatile unsigned long *)(VIC_BASE_ADDR + 0xF00)) + + +/* Pin Connect Block */ +#define PINSEL_BASE_ADDR 0xE002C000 +#define PINSEL0 (*(volatile unsigned long *)(PINSEL_BASE_ADDR + 0x00)) +#define PINSEL1 (*(volatile unsigned long *)(PINSEL_BASE_ADDR + 0x04)) +#define PINSEL2 (*(volatile unsigned long *)(PINSEL_BASE_ADDR + 0x08)) +#define PINSEL3 (*(volatile unsigned long *)(PINSEL_BASE_ADDR + 0x0C)) +#define PINSEL4 (*(volatile unsigned long *)(PINSEL_BASE_ADDR + 0x10)) +#define PINSEL5 (*(volatile unsigned long *)(PINSEL_BASE_ADDR + 0x14)) +#define PINSEL6 (*(volatile unsigned long *)(PINSEL_BASE_ADDR + 0x18)) +#define PINSEL7 (*(volatile unsigned long *)(PINSEL_BASE_ADDR + 0x1C)) +#define PINSEL8 (*(volatile unsigned long *)(PINSEL_BASE_ADDR + 0x20)) +#define PINSEL9 (*(volatile unsigned long *)(PINSEL_BASE_ADDR + 0x24)) +#define PINSEL10 (*(volatile unsigned long *)(PINSEL_BASE_ADDR + 0x28)) + +#define PINMODE0 (*(volatile unsigned long *)(PINSEL_BASE_ADDR + 0x40)) +#define PINMODE1 (*(volatile unsigned long *)(PINSEL_BASE_ADDR + 0x44)) +#define PINMODE2 (*(volatile unsigned long *)(PINSEL_BASE_ADDR + 0x48)) +#define PINMODE3 (*(volatile unsigned long *)(PINSEL_BASE_ADDR + 0x4C)) +#define PINMODE4 (*(volatile unsigned long *)(PINSEL_BASE_ADDR + 0x50)) +#define PINMODE5 (*(volatile unsigned long *)(PINSEL_BASE_ADDR + 0x54)) +#define PINMODE6 (*(volatile unsigned long *)(PINSEL_BASE_ADDR + 0x58)) +#define PINMODE7 (*(volatile unsigned long *)(PINSEL_BASE_ADDR + 0x5C)) +#define PINMODE8 (*(volatile unsigned long *)(PINSEL_BASE_ADDR + 0x60)) +#define PINMODE9 (*(volatile unsigned long *)(PINSEL_BASE_ADDR + 0x64)) + +/* General Purpose Input/Output (GPIO) */ +#define GPIO_BASE_ADDR 0xE0028000 +#define IOPIN0 (*(volatile unsigned long *)(GPIO_BASE_ADDR + 0x00)) +#define IOSET0 (*(volatile unsigned long *)(GPIO_BASE_ADDR + 0x04)) +#define IODIR0 (*(volatile unsigned long *)(GPIO_BASE_ADDR + 0x08)) +#define IOCLR0 (*(volatile unsigned long *)(GPIO_BASE_ADDR + 0x0C)) +#define IOPIN1 (*(volatile unsigned long *)(GPIO_BASE_ADDR + 0x10)) +#define IOSET1 (*(volatile unsigned long *)(GPIO_BASE_ADDR + 0x14)) +#define IODIR1 (*(volatile unsigned long *)(GPIO_BASE_ADDR + 0x18)) +#define IOCLR1 (*(volatile unsigned long *)(GPIO_BASE_ADDR + 0x1C)) + +/* GPIO Interrupt Registers */ +#define IO0_INT_EN_R (*(volatile unsigned long *)(GPIO_BASE_ADDR + 0x90)) +#define IO0_INT_EN_F (*(volatile unsigned long *)(GPIO_BASE_ADDR + 0x94)) +#define IO0_INT_STAT_R (*(volatile unsigned long *)(GPIO_BASE_ADDR + 0x84)) +#define IO0_INT_STAT_F (*(volatile unsigned long *)(GPIO_BASE_ADDR + 0x88)) +#define IO0_INT_CLR (*(volatile unsigned long *)(GPIO_BASE_ADDR + 0x8C)) + +#define IO2_INT_EN_R (*(volatile unsigned long *)(GPIO_BASE_ADDR + 0xB0)) +#define IO2_INT_EN_F (*(volatile unsigned long *)(GPIO_BASE_ADDR + 0xB4)) +#define IO2_INT_STAT_R (*(volatile unsigned long *)(GPIO_BASE_ADDR + 0xA4)) +#define IO2_INT_STAT_F (*(volatile unsigned long *)(GPIO_BASE_ADDR + 0xA8)) +#define IO2_INT_CLR (*(volatile unsigned long *)(GPIO_BASE_ADDR + 0xAC)) + +#define IO_INT_STAT (*(volatile unsigned long *)(GPIO_BASE_ADDR + 0x80)) + +#define PARTCFG_BASE_ADDR 0x3FFF8000 +#define PARTCFG (*(volatile unsigned long *)(PARTCFG_BASE_ADDR + 0x00)) + +/* Fast I/O setup */ +#define FIO_BASE_ADDR 0x3FFFC000 +#define FIO0DIR (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x00)) +#define FIO0MASK (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x10)) +#define FIO0PIN (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x14)) +#define FIO0SET (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x18)) +#define FIO0CLR (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x1C)) + +#define FIO1DIR (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x20)) +#define FIO1MASK (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x30)) +#define FIO1PIN (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x34)) +#define FIO1SET (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x38)) +#define FIO1CLR (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x3C)) + +#define FIO2DIR (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x40)) +#define FIO2MASK (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x50)) +#define FIO2PIN (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x54)) +#define FIO2SET (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x58)) +#define FIO2CLR (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x5C)) + +#define FIO3DIR (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x60)) +#define FIO3MASK (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x70)) +#define FIO3PIN (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x74)) +#define FIO3SET (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x78)) +#define FIO3CLR (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x7C)) + +#define FIO4DIR (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x80)) +#define FIO4MASK (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x90)) +#define FIO4PIN (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x94)) +#define FIO4SET (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x98)) +#define FIO4CLR (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x9C)) + +/* FIOs can be accessed through WORD, HALF-WORD or BYTE. */ +#define FIO0DIR0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x00)) +#define FIO1DIR0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x20)) +#define FIO2DIR0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x40)) +#define FIO3DIR0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x60)) +#define FIO4DIR0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x80)) + +#define FIO0DIR1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x01)) +#define FIO1DIR1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x21)) +#define FIO2DIR1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x41)) +#define FIO3DIR1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x61)) +#define FIO4DIR1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x81)) + +#define FIO0DIR2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x02)) +#define FIO1DIR2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x22)) +#define FIO2DIR2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x42)) +#define FIO3DIR2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x62)) +#define FIO4DIR2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x82)) + +#define FIO0DIR3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x03)) +#define FIO1DIR3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x23)) +#define FIO2DIR3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x43)) +#define FIO3DIR3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x63)) +#define FIO4DIR3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x83)) + +#define FIO0DIRL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x00)) +#define FIO1DIRL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x20)) +#define FIO2DIRL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x40)) +#define FIO3DIRL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x60)) +#define FIO4DIRL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x80)) + +#define FIO0DIRU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x02)) +#define FIO1DIRU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x22)) +#define FIO2DIRU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x42)) +#define FIO3DIRU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x62)) +#define FIO4DIRU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x82)) + +#define FIO0MASK0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x10)) +#define FIO1MASK0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x30)) +#define FIO2MASK0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x50)) +#define FIO3MASK0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x70)) +#define FIO4MASK0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x90)) + +#define FIO0MASK1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x11)) +#define FIO1MASK1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x21)) +#define FIO2MASK1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x51)) +#define FIO3MASK1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x71)) +#define FIO4MASK1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x91)) + +#define FIO0MASK2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x12)) +#define FIO1MASK2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x32)) +#define FIO2MASK2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x52)) +#define FIO3MASK2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x72)) +#define FIO4MASK2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x92)) + +#define FIO0MASK3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x13)) +#define FIO1MASK3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x33)) +#define FIO2MASK3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x53)) +#define FIO3MASK3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x73)) +#define FIO4MASK3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x93)) + +#define FIO0MASKL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x10)) +#define FIO1MASKL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x30)) +#define FIO2MASKL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x50)) +#define FIO3MASKL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x70)) +#define FIO4MASKL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x90)) + +#define FIO0MASKU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x12)) +#define FIO1MASKU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x32)) +#define FIO2MASKU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x52)) +#define FIO3MASKU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x72)) +#define FIO4MASKU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x92)) + +#define FIO0PIN0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x14)) +#define FIO1PIN0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x34)) +#define FIO2PIN0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x54)) +#define FIO3PIN0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x74)) +#define FIO4PIN0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x94)) + +#define FIO0PIN1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x15)) +#define FIO1PIN1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x25)) +#define FIO2PIN1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x55)) +#define FIO3PIN1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x75)) +#define FIO4PIN1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x95)) + +#define FIO0PIN2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x16)) +#define FIO1PIN2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x36)) +#define FIO2PIN2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x56)) +#define FIO3PIN2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x76)) +#define FIO4PIN2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x96)) + +#define FIO0PIN3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x17)) +#define FIO1PIN3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x37)) +#define FIO2PIN3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x57)) +#define FIO3PIN3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x77)) +#define FIO4PIN3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x97)) + +#define FIO0PINL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x14)) +#define FIO1PINL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x34)) +#define FIO2PINL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x54)) +#define FIO3PINL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x74)) +#define FIO4PINL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x94)) + +#define FIO0PINU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x16)) +#define FIO1PINU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x36)) +#define FIO2PINU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x56)) +#define FIO3PINU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x76)) +#define FIO4PINU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x96)) + +#define FIO0SET0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x18)) +#define FIO1SET0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x38)) +#define FIO2SET0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x58)) +#define FIO3SET0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x78)) +#define FIO4SET0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x98)) + +#define FIO0SET1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x19)) +#define FIO1SET1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x29)) +#define FIO2SET1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x59)) +#define FIO3SET1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x79)) +#define FIO4SET1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x99)) + +#define FIO0SET2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x1A)) +#define FIO1SET2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x3A)) +#define FIO2SET2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x5A)) +#define FIO3SET2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x7A)) +#define FIO4SET2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x9A)) + +#define FIO0SET3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x1B)) +#define FIO1SET3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x3B)) +#define FIO2SET3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x5B)) +#define FIO3SET3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x7B)) +#define FIO4SET3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x9B)) + +#define FIO0SETL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x18)) +#define FIO1SETL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x38)) +#define FIO2SETL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x58)) +#define FIO3SETL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x78)) +#define FIO4SETL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x98)) + +#define FIO0SETU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x1A)) +#define FIO1SETU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x3A)) +#define FIO2SETU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x5A)) +#define FIO3SETU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x7A)) +#define FIO4SETU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x9A)) + +#define FIO0CLR0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x1C)) +#define FIO1CLR0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x3C)) +#define FIO2CLR0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x5C)) +#define FIO3CLR0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x7C)) +#define FIO4CLR0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x9C)) + +#define FIO0CLR1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x1D)) +#define FIO1CLR1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x2D)) +#define FIO2CLR1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x5D)) +#define FIO3CLR1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x7D)) +#define FIO4CLR1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x9D)) + +#define FIO0CLR2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x1E)) +#define FIO1CLR2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x3E)) +#define FIO2CLR2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x5E)) +#define FIO3CLR2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x7E)) +#define FIO4CLR2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x9E)) + +#define FIO0CLR3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x1F)) +#define FIO1CLR3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x3F)) +#define FIO2CLR3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x5F)) +#define FIO3CLR3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x7F)) +#define FIO4CLR3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x9F)) + +#define FIO0CLRL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x1C)) +#define FIO1CLRL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x3C)) +#define FIO2CLRL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x5C)) +#define FIO3CLRL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x7C)) +#define FIO4CLRL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x9C)) + +#define FIO0CLRU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x1E)) +#define FIO1CLRU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x3E)) +#define FIO2CLRU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x5E)) +#define FIO3CLRU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x7E)) +#define FIO4CLRU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x9E)) + + +/* System Control Block(SCB) modules include Memory Accelerator Module, +Phase Locked Loop, VPB divider, Power Control, External Interrupt, +Reset, and Code Security/Debugging */ +#define SCB_BASE_ADDR 0xE01FC000 + +/* Memory Accelerator Module (MAM) */ +#define MAMCR (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x000)) +#define MAMTIM (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x004)) +#define MEMMAP (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x040)) + +/* Phase Locked Loop (PLL) */ +#define PLLCON (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x080)) +#define PLLCFG (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x084)) +#define PLLSTAT (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x088)) +#define PLLFEED (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x08C)) + +/* Power Control */ +#define PCON (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x0C0)) +#define PCONP (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x0C4)) + +/* Clock Divider */ +// #define APBDIV (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x100)) +#define CCLKCFG (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x104)) +#define USBCLKCFG (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x108)) +#define CLKSRCSEL (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x10C)) +#define PCLKSEL0 (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x1A8)) +#define PCLKSEL1 (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x1AC)) + +/* External Interrupts */ +#define EXTINT (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x140)) +#define INTWAKE (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x144)) +#define EXTMODE (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x148)) +#define EXTPOLAR (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x14C)) + +/* Reset, reset source identification */ +#define RSIR (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x180)) + +/* RSID, code security protection */ +#define CSPR (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x184)) + +/* AHB configuration */ +#define AHBCFG1 (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x188)) +#define AHBCFG2 (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x18C)) + +/* System Controls and Status */ +#define SCS (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x1A0)) + +/* MPMC(EMC) registers, note: all the external memory controller(EMC) registers +are for LPC24xx only. */ +#define STATIC_MEM0_BASE 0x80000000 +#define STATIC_MEM1_BASE 0x81000000 +#define STATIC_MEM2_BASE 0x82000000 +#define STATIC_MEM3_BASE 0x83000000 + +#define DYNAMIC_MEM0_BASE 0xA0000000 +#define DYNAMIC_MEM1_BASE 0xB0000000 +#define DYNAMIC_MEM2_BASE 0xC0000000 +#define DYNAMIC_MEM3_BASE 0xD0000000 + +/* External Memory Controller (EMC) */ +#define EMC_BASE_ADDR 0xFFE08000 +#define EMC_CTRL (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x000)) +#define EMC_STAT (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x004)) +#define EMC_CONFIG (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x008)) + +/* Dynamic RAM access registers */ +#define EMC_DYN_CTRL (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x020)) +#define EMC_DYN_RFSH (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x024)) +#define EMC_DYN_RD_CFG (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x028)) +#define EMC_DYN_RP (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x030)) +#define EMC_DYN_RAS (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x034)) +#define EMC_DYN_SREX (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x038)) +#define EMC_DYN_APR (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x03C)) +#define EMC_DYN_DAL (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x040)) +#define EMC_DYN_WR (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x044)) +#define EMC_DYN_RC (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x048)) +#define EMC_DYN_RFC (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x04C)) +#define EMC_DYN_XSR (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x050)) +#define EMC_DYN_RRD (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x054)) +#define EMC_DYN_MRD (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x058)) + +#define EMC_DYN_CFG0 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x100)) +#define EMC_DYN_RASCAS0 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x104)) +#define EMC_DYN_CFG1 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x140)) +#define EMC_DYN_RASCAS1 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x144)) +#define EMC_DYN_CFG2 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x160)) +#define EMC_DYN_RASCAS2 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x164)) +#define EMC_DYN_CFG3 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x180)) +#define EMC_DYN_RASCAS3 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x184)) + +/* static RAM access registers */ +#define EMC_STA_CFG0 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x200)) +#define EMC_STA_WAITWEN0 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x204)) +#define EMC_STA_WAITOEN0 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x208)) +#define EMC_STA_WAITRD0 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x20C)) +#define EMC_STA_WAITPAGE0 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x210)) +#define EMC_STA_WAITWR0 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x214)) +#define EMC_STA_WAITTURN0 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x218)) + +#define EMC_STA_CFG1 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x220)) +#define EMC_STA_WAITWEN1 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x224)) +#define EMC_STA_WAITOEN1 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x228)) +#define EMC_STA_WAITRD1 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x22C)) +#define EMC_STA_WAITPAGE1 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x230)) +#define EMC_STA_WAITWR1 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x234)) +#define EMC_STA_WAITTURN1 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x238)) + +#define EMC_STA_CFG2 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x240)) +#define EMC_STA_WAITWEN2 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x244)) +#define EMC_STA_WAITOEN2 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x248)) +#define EMC_STA_WAITRD2 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x24C)) +#define EMC_STA_WAITPAGE2 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x250)) +#define EMC_STA_WAITWR2 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x254)) +#define EMC_STA_WAITTURN2 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x258)) + +#define EMC_STA_CFG3 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x260)) +#define EMC_STA_WAITWEN3 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x264)) +#define EMC_STA_WAITOEN3 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x268)) +#define EMC_STA_WAITRD3 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x26C)) +#define EMC_STA_WAITPAGE3 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x270)) +#define EMC_STA_WAITWR3 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x274)) +#define EMC_STA_WAITTURN3 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x278)) + +#define EMC_STA_EXT_WAIT (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x880)) + +/* Timer 0 */ +#define TMR0_BASE_ADDR 0xE0004000 +#define T0IR (*(volatile unsigned long *)(TMR0_BASE_ADDR + 0x00)) +#define T0TCR (*(volatile unsigned long *)(TMR0_BASE_ADDR + 0x04)) +#define T0TC (*(volatile unsigned long *)(TMR0_BASE_ADDR + 0x08)) +#define T0PR (*(volatile unsigned long *)(TMR0_BASE_ADDR + 0x0C)) +#define T0PC (*(volatile unsigned long *)(TMR0_BASE_ADDR + 0x10)) +#define T0MCR (*(volatile unsigned long *)(TMR0_BASE_ADDR + 0x14)) +#define T0MR0 (*(volatile unsigned long *)(TMR0_BASE_ADDR + 0x18)) +#define T0MR1 (*(volatile unsigned long *)(TMR0_BASE_ADDR + 0x1C)) +#define T0MR2 (*(volatile unsigned long *)(TMR0_BASE_ADDR + 0x20)) +#define T0MR3 (*(volatile unsigned long *)(TMR0_BASE_ADDR + 0x24)) +#define T0CCR (*(volatile unsigned long *)(TMR0_BASE_ADDR + 0x28)) +#define T0CR0 (*(volatile unsigned long *)(TMR0_BASE_ADDR + 0x2C)) +#define T0CR1 (*(volatile unsigned long *)(TMR0_BASE_ADDR + 0x30)) +#define T0CR2 (*(volatile unsigned long *)(TMR0_BASE_ADDR + 0x34)) +#define T0CR3 (*(volatile unsigned long *)(TMR0_BASE_ADDR + 0x38)) +#define T0EMR (*(volatile unsigned long *)(TMR0_BASE_ADDR + 0x3C)) +#define T0CTCR (*(volatile unsigned long *)(TMR0_BASE_ADDR + 0x70)) + +/* Timer 1 */ +#define TMR1_BASE_ADDR 0xE0008000 +#define T1IR (*(volatile unsigned long *)(TMR1_BASE_ADDR + 0x00)) +#define T1TCR (*(volatile unsigned long *)(TMR1_BASE_ADDR + 0x04)) +#define T1TC (*(volatile unsigned long *)(TMR1_BASE_ADDR + 0x08)) +#define T1PR (*(volatile unsigned long *)(TMR1_BASE_ADDR + 0x0C)) +#define T1PC (*(volatile unsigned long *)(TMR1_BASE_ADDR + 0x10)) +#define T1MCR (*(volatile unsigned long *)(TMR1_BASE_ADDR + 0x14)) +#define T1MR0 (*(volatile unsigned long *)(TMR1_BASE_ADDR + 0x18)) +#define T1MR1 (*(volatile unsigned long *)(TMR1_BASE_ADDR + 0x1C)) +#define T1MR2 (*(volatile unsigned long *)(TMR1_BASE_ADDR + 0x20)) +#define T1MR3 (*(volatile unsigned long *)(TMR1_BASE_ADDR + 0x24)) +#define T1CCR (*(volatile unsigned long *)(TMR1_BASE_ADDR + 0x28)) +#define T1CR0 (*(volatile unsigned long *)(TMR1_BASE_ADDR + 0x2C)) +#define T1CR1 (*(volatile unsigned long *)(TMR1_BASE_ADDR + 0x30)) +#define T1CR2 (*(volatile unsigned long *)(TMR1_BASE_ADDR + 0x34)) +#define T1CR3 (*(volatile unsigned long *)(TMR1_BASE_ADDR + 0x38)) +#define T1EMR (*(volatile unsigned long *)(TMR1_BASE_ADDR + 0x3C)) +#define T1CTCR (*(volatile unsigned long *)(TMR1_BASE_ADDR + 0x70)) + +/* Timer 2 */ +#define TMR2_BASE_ADDR 0xE0070000 +#define T2IR (*(volatile unsigned long *)(TMR2_BASE_ADDR + 0x00)) +#define T2TCR (*(volatile unsigned long *)(TMR2_BASE_ADDR + 0x04)) +#define T2TC (*(volatile unsigned long *)(TMR2_BASE_ADDR + 0x08)) +#define T2PR (*(volatile unsigned long *)(TMR2_BASE_ADDR + 0x0C)) +#define T2PC (*(volatile unsigned long *)(TMR2_BASE_ADDR + 0x10)) +#define T2MCR (*(volatile unsigned long *)(TMR2_BASE_ADDR + 0x14)) +#define T2MR0 (*(volatile unsigned long *)(TMR2_BASE_ADDR + 0x18)) +#define T2MR1 (*(volatile unsigned long *)(TMR2_BASE_ADDR + 0x1C)) +#define T2MR2 (*(volatile unsigned long *)(TMR2_BASE_ADDR + 0x20)) +#define T2MR3 (*(volatile unsigned long *)(TMR2_BASE_ADDR + 0x24)) +#define T2CCR (*(volatile unsigned long *)(TMR2_BASE_ADDR + 0x28)) +#define T2CR0 (*(volatile unsigned long *)(TMR2_BASE_ADDR + 0x2C)) +#define T2CR1 (*(volatile unsigned long *)(TMR2_BASE_ADDR + 0x30)) +#define T2CR2 (*(volatile unsigned long *)(TMR2_BASE_ADDR + 0x34)) +#define T2CR3 (*(volatile unsigned long *)(TMR2_BASE_ADDR + 0x38)) +#define T2EMR (*(volatile unsigned long *)(TMR2_BASE_ADDR + 0x3C)) +#define T2CTCR (*(volatile unsigned long *)(TMR2_BASE_ADDR + 0x70)) + +/* Timer 3 */ +#define TMR3_BASE_ADDR 0xE0074000 +#define T3IR (*(volatile unsigned long *)(TMR3_BASE_ADDR + 0x00)) +#define T3TCR (*(volatile unsigned long *)(TMR3_BASE_ADDR + 0x04)) +#define T3TC (*(volatile unsigned long *)(TMR3_BASE_ADDR + 0x08)) +#define T3PR (*(volatile unsigned long *)(TMR3_BASE_ADDR + 0x0C)) +#define T3PC (*(volatile unsigned long *)(TMR3_BASE_ADDR + 0x10)) +#define T3MCR (*(volatile unsigned long *)(TMR3_BASE_ADDR + 0x14)) +#define T3MR0 (*(volatile unsigned long *)(TMR3_BASE_ADDR + 0x18)) +#define T3MR1 (*(volatile unsigned long *)(TMR3_BASE_ADDR + 0x1C)) +#define T3MR2 (*(volatile unsigned long *)(TMR3_BASE_ADDR + 0x20)) +#define T3MR3 (*(volatile unsigned long *)(TMR3_BASE_ADDR + 0x24)) +#define T3CCR (*(volatile unsigned long *)(TMR3_BASE_ADDR + 0x28)) +#define T3CR0 (*(volatile unsigned long *)(TMR3_BASE_ADDR + 0x2C)) +#define T3CR1 (*(volatile unsigned long *)(TMR3_BASE_ADDR + 0x30)) +#define T3CR2 (*(volatile unsigned long *)(TMR3_BASE_ADDR + 0x34)) +#define T3CR3 (*(volatile unsigned long *)(TMR3_BASE_ADDR + 0x38)) +#define T3EMR (*(volatile unsigned long *)(TMR3_BASE_ADDR + 0x3C)) +#define T3CTCR (*(volatile unsigned long *)(TMR3_BASE_ADDR + 0x70)) + + +/* Pulse Width Modulator (PWM) */ +#define PWM0_BASE_ADDR 0xE0014000 +#define PWM0IR (*(volatile unsigned long *)(PWM0_BASE_ADDR + 0x00)) +#define PWM0TCR (*(volatile unsigned long *)(PWM0_BASE_ADDR + 0x04)) +#define PWM0TC (*(volatile unsigned long *)(PWM0_BASE_ADDR + 0x08)) +#define PWM0PR (*(volatile unsigned long *)(PWM0_BASE_ADDR + 0x0C)) +#define PWM0PC (*(volatile unsigned long *)(PWM0_BASE_ADDR + 0x10)) +#define PWM0MCR (*(volatile unsigned long *)(PWM0_BASE_ADDR + 0x14)) +#define PWM0MR0 (*(volatile unsigned long *)(PWM0_BASE_ADDR + 0x18)) +#define PWM0MR1 (*(volatile unsigned long *)(PWM0_BASE_ADDR + 0x1C)) +#define PWM0MR2 (*(volatile unsigned long *)(PWM0_BASE_ADDR + 0x20)) +#define PWM0MR3 (*(volatile unsigned long *)(PWM0_BASE_ADDR + 0x24)) +#define PWM0CCR (*(volatile unsigned long *)(PWM0_BASE_ADDR + 0x28)) +#define PWM0CR0 (*(volatile unsigned long *)(PWM0_BASE_ADDR + 0x2C)) +#define PWM0CR1 (*(volatile unsigned long *)(PWM0_BASE_ADDR + 0x30)) +#define PWM0CR2 (*(volatile unsigned long *)(PWM0_BASE_ADDR + 0x34)) +#define PWM0CR3 (*(volatile unsigned long *)(PWM0_BASE_ADDR + 0x38)) +#define PWM0EMR (*(volatile unsigned long *)(PWM0_BASE_ADDR + 0x3C)) +#define PWM0MR4 (*(volatile unsigned long *)(PWM0_BASE_ADDR + 0x40)) +#define PWM0MR5 (*(volatile unsigned long *)(PWM0_BASE_ADDR + 0x44)) +#define PWM0MR6 (*(volatile unsigned long *)(PWM0_BASE_ADDR + 0x48)) +#define PWM0PCR (*(volatile unsigned long *)(PWM0_BASE_ADDR + 0x4C)) +#define PWM0LER (*(volatile unsigned long *)(PWM0_BASE_ADDR + 0x50)) +#define PWM0CTCR (*(volatile unsigned long *)(PWM0_BASE_ADDR + 0x70)) + +#define PWM1_BASE_ADDR 0xE0018000 +#define PWM1IR (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x00)) +#define PWM1TCR (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x04)) +#define PWM1TC (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x08)) +#define PWM1PR (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x0C)) +#define PWM1PC (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x10)) +#define PWM1MCR (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x14)) +#define PWM1MR0 (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x18)) +#define PWM1MR1 (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x1C)) +#define PWM1MR2 (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x20)) +#define PWM1MR3 (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x24)) +#define PWM1CCR (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x28)) +#define PWM1CR0 (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x2C)) +#define PWM1CR1 (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x30)) +#define PWM1CR2 (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x34)) +#define PWM1CR3 (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x38)) +#define PWM1EMR (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x3C)) +#define PWM1MR4 (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x40)) +#define PWM1MR5 (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x44)) +#define PWM1MR6 (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x48)) +#define PWM1PCR (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x4C)) +#define PWM1LER (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x50)) +#define PWM1CTCR (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x70)) + + +/* Universal Asynchronous Receiver Transmitter 0 (UART0) */ +#define UART0_BASE_ADDR 0xE000C000 +#define U0RBR (*(volatile unsigned long *)(UART0_BASE_ADDR + 0x00)) +#define U0THR (*(volatile unsigned long *)(UART0_BASE_ADDR + 0x00)) +#define U0DLL (*(volatile unsigned long *)(UART0_BASE_ADDR + 0x00)) +#define U0DLM (*(volatile unsigned long *)(UART0_BASE_ADDR + 0x04)) +#define U0IER (*(volatile unsigned long *)(UART0_BASE_ADDR + 0x04)) +#define U0IIR (*(volatile unsigned long *)(UART0_BASE_ADDR + 0x08)) +#define U0FCR (*(volatile unsigned long *)(UART0_BASE_ADDR + 0x08)) +#define U0LCR (*(volatile unsigned long *)(UART0_BASE_ADDR + 0x0C)) +#define U0LSR (*(volatile unsigned long *)(UART0_BASE_ADDR + 0x14)) +#define U0SCR (*(volatile unsigned long *)(UART0_BASE_ADDR + 0x1C)) +#define U0ACR (*(volatile unsigned long *)(UART0_BASE_ADDR + 0x20)) +#define U0ICR (*(volatile unsigned long *)(UART0_BASE_ADDR + 0x24)) +#define U0FDR (*(volatile unsigned long *)(UART0_BASE_ADDR + 0x28)) +#define U0TER (*(volatile unsigned long *)(UART0_BASE_ADDR + 0x30)) + +/* Universal Asynchronous Receiver Transmitter 1 (UART1) */ +#define UART1_BASE_ADDR 0xE0010000 +#define U1RBR (*(volatile unsigned long *)(UART1_BASE_ADDR + 0x00)) +#define U1THR (*(volatile unsigned long *)(UART1_BASE_ADDR + 0x00)) +#define U1DLL (*(volatile unsigned long *)(UART1_BASE_ADDR + 0x00)) +#define U1DLM (*(volatile unsigned long *)(UART1_BASE_ADDR + 0x04)) +#define U1IER (*(volatile unsigned long *)(UART1_BASE_ADDR + 0x04)) +#define U1IIR (*(volatile unsigned long *)(UART1_BASE_ADDR + 0x08)) +#define U1FCR (*(volatile unsigned long *)(UART1_BASE_ADDR + 0x08)) +#define U1LCR (*(volatile unsigned long *)(UART1_BASE_ADDR + 0x0C)) +#define U1MCR (*(volatile unsigned long *)(UART1_BASE_ADDR + 0x10)) +#define U1LSR (*(volatile unsigned long *)(UART1_BASE_ADDR + 0x14)) +#define U1MSR (*(volatile unsigned long *)(UART1_BASE_ADDR + 0x18)) +#define U1SCR (*(volatile unsigned long *)(UART1_BASE_ADDR + 0x1C)) +#define U1ACR (*(volatile unsigned long *)(UART1_BASE_ADDR + 0x20)) +#define U1FDR (*(volatile unsigned long *)(UART1_BASE_ADDR + 0x28)) +#define U1TER (*(volatile unsigned long *)(UART1_BASE_ADDR + 0x30)) + +/* Universal Asynchronous Receiver Transmitter 2 (UART2) */ +#define UART2_BASE_ADDR 0xE0078000 +#define U2RBR (*(volatile unsigned long *)(UART2_BASE_ADDR + 0x00)) +#define U2THR (*(volatile unsigned long *)(UART2_BASE_ADDR + 0x00)) +#define U2DLL (*(volatile unsigned long *)(UART2_BASE_ADDR + 0x00)) +#define U2DLM (*(volatile unsigned long *)(UART2_BASE_ADDR + 0x04)) +#define U2IER (*(volatile unsigned long *)(UART2_BASE_ADDR + 0x04)) +#define U2IIR (*(volatile unsigned long *)(UART2_BASE_ADDR + 0x08)) +#define U2FCR (*(volatile unsigned long *)(UART2_BASE_ADDR + 0x08)) +#define U2LCR (*(volatile unsigned long *)(UART2_BASE_ADDR + 0x0C)) +#define U2LSR (*(volatile unsigned long *)(UART2_BASE_ADDR + 0x14)) +#define U2SCR (*(volatile unsigned long *)(UART2_BASE_ADDR + 0x1C)) +#define U2ACR (*(volatile unsigned long *)(UART2_BASE_ADDR + 0x20)) +#define U2ICR (*(volatile unsigned long *)(UART2_BASE_ADDR + 0x24)) +#define U2FDR (*(volatile unsigned long *)(UART2_BASE_ADDR + 0x28)) +#define U2TER (*(volatile unsigned long *)(UART2_BASE_ADDR + 0x30)) + +/* Universal Asynchronous Receiver Transmitter 3 (UART3) */ +#define UART3_BASE_ADDR 0xE007C000 +#define U3RBR (*(volatile unsigned long *)(UART3_BASE_ADDR + 0x00)) +#define U3THR (*(volatile unsigned long *)(UART3_BASE_ADDR + 0x00)) +#define U3DLL (*(volatile unsigned long *)(UART3_BASE_ADDR + 0x00)) +#define U3DLM (*(volatile unsigned long *)(UART3_BASE_ADDR + 0x04)) +#define U3IER (*(volatile unsigned long *)(UART3_BASE_ADDR + 0x04)) +#define U3IIR (*(volatile unsigned long *)(UART3_BASE_ADDR + 0x08)) +#define U3FCR (*(volatile unsigned long *)(UART3_BASE_ADDR + 0x08)) +#define U3LCR (*(volatile unsigned long *)(UART3_BASE_ADDR + 0x0C)) +#define U3LSR (*(volatile unsigned long *)(UART3_BASE_ADDR + 0x14)) +#define U3SCR (*(volatile unsigned long *)(UART3_BASE_ADDR + 0x1C)) +#define U3ACR (*(volatile unsigned long *)(UART3_BASE_ADDR + 0x20)) +#define U3ICR (*(volatile unsigned long *)(UART3_BASE_ADDR + 0x24)) +#define U3FDR (*(volatile unsigned long *)(UART3_BASE_ADDR + 0x28)) +#define U3TER (*(volatile unsigned long *)(UART3_BASE_ADDR + 0x30)) + +/* I2C Interface 0 */ +#define I2C0_BASE_ADDR 0xE001C000 +#define I20CONSET (*(volatile unsigned long *)(I2C0_BASE_ADDR + 0x00)) +#define I20STAT (*(volatile unsigned long *)(I2C0_BASE_ADDR + 0x04)) +#define I20DAT (*(volatile unsigned long *)(I2C0_BASE_ADDR + 0x08)) +#define I20ADR (*(volatile unsigned long *)(I2C0_BASE_ADDR + 0x0C)) +#define I20SCLH (*(volatile unsigned long *)(I2C0_BASE_ADDR + 0x10)) +#define I20SCLL (*(volatile unsigned long *)(I2C0_BASE_ADDR + 0x14)) +#define I20CONCLR (*(volatile unsigned long *)(I2C0_BASE_ADDR + 0x18)) + +/* I2C Interface 1 */ +#define I2C1_BASE_ADDR 0xE005C000 +#define I21CONSET (*(volatile unsigned long *)(I2C1_BASE_ADDR + 0x00)) +#define I21STAT (*(volatile unsigned long *)(I2C1_BASE_ADDR + 0x04)) +#define I21DAT (*(volatile unsigned long *)(I2C1_BASE_ADDR + 0x08)) +#define I21ADR (*(volatile unsigned long *)(I2C1_BASE_ADDR + 0x0C)) +#define I21SCLH (*(volatile unsigned long *)(I2C1_BASE_ADDR + 0x10)) +#define I21SCLL (*(volatile unsigned long *)(I2C1_BASE_ADDR + 0x14)) +#define I21CONCLR (*(volatile unsigned long *)(I2C1_BASE_ADDR + 0x18)) + +/* I2C Interface 2 */ +#define I2C2_BASE_ADDR 0xE0080000 +#define I22CONSET (*(volatile unsigned long *)(I2C2_BASE_ADDR + 0x00)) +#define I22STAT (*(volatile unsigned long *)(I2C2_BASE_ADDR + 0x04)) +#define I22DAT (*(volatile unsigned long *)(I2C2_BASE_ADDR + 0x08)) +#define I22ADR (*(volatile unsigned long *)(I2C2_BASE_ADDR + 0x0C)) +#define I22SCLH (*(volatile unsigned long *)(I2C2_BASE_ADDR + 0x10)) +#define I22SCLL (*(volatile unsigned long *)(I2C2_BASE_ADDR + 0x14)) +#define I22CONCLR (*(volatile unsigned long *)(I2C2_BASE_ADDR + 0x18)) + +/* SPI0 (Serial Peripheral Interface 0) */ +#define SPI0_BASE_ADDR 0xE0020000 +#define S0SPCR (*(volatile unsigned long *)(SPI0_BASE_ADDR + 0x00)) +#define S0SPSR (*(volatile unsigned long *)(SPI0_BASE_ADDR + 0x04)) +#define S0SPDR (*(volatile unsigned long *)(SPI0_BASE_ADDR + 0x08)) +#define S0SPCCR (*(volatile unsigned long *)(SPI0_BASE_ADDR + 0x0C)) +#define S0SPINT (*(volatile unsigned long *)(SPI0_BASE_ADDR + 0x1C)) + +/* SSP0 Controller */ +#define SSP0_BASE_ADDR 0xE0068000 +#define SSP0CR0 (*(volatile unsigned long *)(SSP0_BASE_ADDR + 0x00)) +#define SSP0CR1 (*(volatile unsigned long *)(SSP0_BASE_ADDR + 0x04)) +#define SSP0DR (*(volatile unsigned long *)(SSP0_BASE_ADDR + 0x08)) +#define SSP0SR (*(volatile unsigned long *)(SSP0_BASE_ADDR + 0x0C)) +#define SSP0CPSR (*(volatile unsigned long *)(SSP0_BASE_ADDR + 0x10)) +#define SSP0IMSC (*(volatile unsigned long *)(SSP0_BASE_ADDR + 0x14)) +#define SSP0RIS (*(volatile unsigned long *)(SSP0_BASE_ADDR + 0x18)) +#define SSP0MIS (*(volatile unsigned long *)(SSP0_BASE_ADDR + 0x1C)) +#define SSP0ICR (*(volatile unsigned long *)(SSP0_BASE_ADDR + 0x20)) +#define SSP0DMACR (*(volatile unsigned long *)(SSP0_BASE_ADDR + 0x24)) + +/* SSP1 Controller */ +#define SSP1_BASE_ADDR 0xE0030000 +#define SSP1CR0 (*(volatile unsigned long *)(SSP1_BASE_ADDR + 0x00)) +#define SSP1CR1 (*(volatile unsigned long *)(SSP1_BASE_ADDR + 0x04)) +#define SSP1DR (*(volatile unsigned long *)(SSP1_BASE_ADDR + 0x08)) +#define SSP1SR (*(volatile unsigned long *)(SSP1_BASE_ADDR + 0x0C)) +#define SSP1CPSR (*(volatile unsigned long *)(SSP1_BASE_ADDR + 0x10)) +#define SSP1IMSC (*(volatile unsigned long *)(SSP1_BASE_ADDR + 0x14)) +#define SSP1RIS (*(volatile unsigned long *)(SSP1_BASE_ADDR + 0x18)) +#define SSP1MIS (*(volatile unsigned long *)(SSP1_BASE_ADDR + 0x1C)) +#define SSP1ICR (*(volatile unsigned long *)(SSP1_BASE_ADDR + 0x20)) +#define SSP1DMACR (*(volatile unsigned long *)(SSP1_BASE_ADDR + 0x24)) + + +/* Real Time Clock */ +#define RTC_BASE_ADDR 0xE0024000 +#define RTC_ILR (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x00)) +#define RTC_CTC (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x04)) +#define RTC_CCR (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x08)) +#define RTC_CIIR (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x0C)) +#define RTC_AMR (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x10)) +#define RTC_CTIME0 (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x14)) +#define RTC_CTIME1 (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x18)) +#define RTC_CTIME2 (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x1C)) +#define RTC_SEC (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x20)) +#define RTC_MIN (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x24)) +#define RTC_HOUR (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x28)) +#define RTC_DOM (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x2C)) +#define RTC_DOW (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x30)) +#define RTC_DOY (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x34)) +#define RTC_MONTH (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x38)) +#define RTC_YEAR (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x3C)) +#define RTC_CISS (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x40)) +#define RTC_ALSEC (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x60)) +#define RTC_ALMIN (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x64)) +#define RTC_ALHOUR (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x68)) +#define RTC_ALDOM (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x6C)) +#define RTC_ALDOW (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x70)) +#define RTC_ALDOY (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x74)) +#define RTC_ALMON (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x78)) +#define RTC_ALYEAR (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x7C)) +#define RTC_PREINT (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x80)) +#define RTC_PREFRAC (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x84)) + + +/* A/D Converter 0 (AD0) */ +#define AD0_BASE_ADDR 0xE0034000 +#define AD0CR (*(volatile unsigned long *)(AD0_BASE_ADDR + 0x00)) +#define AD0GDR (*(volatile unsigned long *)(AD0_BASE_ADDR + 0x04)) +#define AD0INTEN (*(volatile unsigned long *)(AD0_BASE_ADDR + 0x0C)) +#define AD0DR0 (*(volatile unsigned long *)(AD0_BASE_ADDR + 0x10)) +#define AD0DR1 (*(volatile unsigned long *)(AD0_BASE_ADDR + 0x14)) +#define AD0DR2 (*(volatile unsigned long *)(AD0_BASE_ADDR + 0x18)) +#define AD0DR3 (*(volatile unsigned long *)(AD0_BASE_ADDR + 0x1C)) +#define AD0DR4 (*(volatile unsigned long *)(AD0_BASE_ADDR + 0x20)) +#define AD0DR5 (*(volatile unsigned long *)(AD0_BASE_ADDR + 0x24)) +#define AD0DR6 (*(volatile unsigned long *)(AD0_BASE_ADDR + 0x28)) +#define AD0DR7 (*(volatile unsigned long *)(AD0_BASE_ADDR + 0x2C)) +#define AD0STAT (*(volatile unsigned long *)(AD0_BASE_ADDR + 0x30)) + + +/* D/A Converter */ +#define DAC_BASE_ADDR 0xE006C000 +#define DACR (*(volatile unsigned long *)(DAC_BASE_ADDR + 0x00)) + + +/* Watchdog */ +#define WDG_BASE_ADDR 0xE0000000 +#define WDMOD (*(volatile unsigned long *)(WDG_BASE_ADDR + 0x00)) +#define WDTC (*(volatile unsigned long *)(WDG_BASE_ADDR + 0x04)) +#define WDFEED (*(volatile unsigned long *)(WDG_BASE_ADDR + 0x08)) +#define WDTV (*(volatile unsigned long *)(WDG_BASE_ADDR + 0x0C)) +#define WDCLKSEL (*(volatile unsigned long *)(WDG_BASE_ADDR + 0x10)) + +/* CAN CONTROLLERS AND ACCEPTANCE FILTER */ +#define CAN_ACCEPT_BASE_ADDR 0xE003C000 +#define CAN_AFMR (*(volatile unsigned long *)(CAN_ACCEPT_BASE_ADDR + 0x00)) +#define CAN_SFF_SA (*(volatile unsigned long *)(CAN_ACCEPT_BASE_ADDR + 0x04)) +#define CAN_SFF_GRP_SA (*(volatile unsigned long *)(CAN_ACCEPT_BASE_ADDR + 0x08)) +#define CAN_EFF_SA (*(volatile unsigned long *)(CAN_ACCEPT_BASE_ADDR + 0x0C)) +#define CAN_EFF_GRP_SA (*(volatile unsigned long *)(CAN_ACCEPT_BASE_ADDR + 0x10)) +#define CAN_EOT (*(volatile unsigned long *)(CAN_ACCEPT_BASE_ADDR + 0x14)) +#define CAN_LUT_ERR_ADR (*(volatile unsigned long *)(CAN_ACCEPT_BASE_ADDR + 0x18)) +#define CAN_LUT_ERR (*(volatile unsigned long *)(CAN_ACCEPT_BASE_ADDR + 0x1C)) + +#define CAN_CENTRAL_BASE_ADDR 0xE0040000 +#define CAN_TX_SR (*(volatile unsigned long *)(CAN_CENTRAL_BASE_ADDR + 0x00)) +#define CAN_RX_SR (*(volatile unsigned long *)(CAN_CENTRAL_BASE_ADDR + 0x04)) +#define CAN_MSR (*(volatile unsigned long *)(CAN_CENTRAL_BASE_ADDR + 0x08)) + +#define CAN1_BASE_ADDR 0xE0044000 +#define CAN1MOD (*(volatile unsigned long *)(CAN1_BASE_ADDR + 0x00)) +#define CAN1CMR (*(volatile unsigned long *)(CAN1_BASE_ADDR + 0x04)) +#define CAN1GSR (*(volatile unsigned long *)(CAN1_BASE_ADDR + 0x08)) +#define CAN1ICR (*(volatile unsigned long *)(CAN1_BASE_ADDR + 0x0C)) +#define CAN1IER (*(volatile unsigned long *)(CAN1_BASE_ADDR + 0x10)) +#define CAN1BTR (*(volatile unsigned long *)(CAN1_BASE_ADDR + 0x14)) +#define CAN1EWL (*(volatile unsigned long *)(CAN1_BASE_ADDR + 0x18)) +#define CAN1SR (*(volatile unsigned long *)(CAN1_BASE_ADDR + 0x1C)) +#define CAN1RFS (*(volatile unsigned long *)(CAN1_BASE_ADDR + 0x20)) +#define CAN1RID (*(volatile unsigned long *)(CAN1_BASE_ADDR + 0x24)) +#define CAN1RDA (*(volatile unsigned long *)(CAN1_BASE_ADDR + 0x28)) +#define CAN1RDB (*(volatile unsigned long *)(CAN1_BASE_ADDR + 0x2C)) + +#define CAN1TFI1 (*(volatile unsigned long *)(CAN1_BASE_ADDR + 0x30)) +#define CAN1TID1 (*(volatile unsigned long *)(CAN1_BASE_ADDR + 0x34)) +#define CAN1TDA1 (*(volatile unsigned long *)(CAN1_BASE_ADDR + 0x38)) +#define CAN1TDB1 (*(volatile unsigned long *)(CAN1_BASE_ADDR + 0x3C)) +#define CAN1TFI2 (*(volatile unsigned long *)(CAN1_BASE_ADDR + 0x40)) +#define CAN1TID2 (*(volatile unsigned long *)(CAN1_BASE_ADDR + 0x44)) +#define CAN1TDA2 (*(volatile unsigned long *)(CAN1_BASE_ADDR + 0x48)) +#define CAN1TDB2 (*(volatile unsigned long *)(CAN1_BASE_ADDR + 0x4C)) +#define CAN1TFI3 (*(volatile unsigned long *)(CAN1_BASE_ADDR + 0x50)) +#define CAN1TID3 (*(volatile unsigned long *)(CAN1_BASE_ADDR + 0x54)) +#define CAN1TDA3 (*(volatile unsigned long *)(CAN1_BASE_ADDR + 0x58)) +#define CAN1TDB3 (*(volatile unsigned long *)(CAN1_BASE_ADDR + 0x5C)) + +#define CAN2_BASE_ADDR 0xE0048000 +#define CAN2MOD (*(volatile unsigned long *)(CAN2_BASE_ADDR + 0x00)) +#define CAN2CMR (*(volatile unsigned long *)(CAN2_BASE_ADDR + 0x04)) +#define CAN2GSR (*(volatile unsigned long *)(CAN2_BASE_ADDR + 0x08)) +#define CAN2ICR (*(volatile unsigned long *)(CAN2_BASE_ADDR + 0x0C)) +#define CAN2IER (*(volatile unsigned long *)(CAN2_BASE_ADDR + 0x10)) +#define CAN2BTR (*(volatile unsigned long *)(CAN2_BASE_ADDR + 0x14)) +#define CAN2EWL (*(volatile unsigned long *)(CAN2_BASE_ADDR + 0x18)) +#define CAN2SR (*(volatile unsigned long *)(CAN2_BASE_ADDR + 0x1C)) +#define CAN2RFS (*(volatile unsigned long *)(CAN2_BASE_ADDR + 0x20)) +#define CAN2RID (*(volatile unsigned long *)(CAN2_BASE_ADDR + 0x24)) +#define CAN2RDA (*(volatile unsigned long *)(CAN2_BASE_ADDR + 0x28)) +#define CAN2RDB (*(volatile unsigned long *)(CAN2_BASE_ADDR + 0x2C)) + +#define CAN2TFI1 (*(volatile unsigned long *)(CAN2_BASE_ADDR + 0x30)) +#define CAN2TID1 (*(volatile unsigned long *)(CAN2_BASE_ADDR + 0x34)) +#define CAN2TDA1 (*(volatile unsigned long *)(CAN2_BASE_ADDR + 0x38)) +#define CAN2TDB1 (*(volatile unsigned long *)(CAN2_BASE_ADDR + 0x3C)) +#define CAN2TFI2 (*(volatile unsigned long *)(CAN2_BASE_ADDR + 0x40)) +#define CAN2TID2 (*(volatile unsigned long *)(CAN2_BASE_ADDR + 0x44)) +#define CAN2TDA2 (*(volatile unsigned long *)(CAN2_BASE_ADDR + 0x48)) +#define CAN2TDB2 (*(volatile unsigned long *)(CAN2_BASE_ADDR + 0x4C)) +#define CAN2TFI3 (*(volatile unsigned long *)(CAN2_BASE_ADDR + 0x50)) +#define CAN2TID3 (*(volatile unsigned long *)(CAN2_BASE_ADDR + 0x54)) +#define CAN2TDA3 (*(volatile unsigned long *)(CAN2_BASE_ADDR + 0x58)) +#define CAN2TDB3 (*(volatile unsigned long *)(CAN2_BASE_ADDR + 0x5C)) + + +/* MultiMedia Card Interface(MCI) Controller */ +#define MCI_BASE_ADDR 0xE008C000 +#define MCI_POWER (*(volatile unsigned long *)(MCI_BASE_ADDR + 0x00)) +#define MCI_CLOCK (*(volatile unsigned long *)(MCI_BASE_ADDR + 0x04)) +#define MCI_ARGUMENT (*(volatile unsigned long *)(MCI_BASE_ADDR + 0x08)) +#define MCI_COMMAND (*(volatile unsigned long *)(MCI_BASE_ADDR + 0x0C)) +#define MCI_RESP_CMD (*(volatile unsigned long *)(MCI_BASE_ADDR + 0x10)) +#define MCI_RESP0 (*(volatile unsigned long *)(MCI_BASE_ADDR + 0x14)) +#define MCI_RESP1 (*(volatile unsigned long *)(MCI_BASE_ADDR + 0x18)) +#define MCI_RESP2 (*(volatile unsigned long *)(MCI_BASE_ADDR + 0x1C)) +#define MCI_RESP3 (*(volatile unsigned long *)(MCI_BASE_ADDR + 0x20)) +#define MCI_DATA_TMR (*(volatile unsigned long *)(MCI_BASE_ADDR + 0x24)) +#define MCI_DATA_LEN (*(volatile unsigned long *)(MCI_BASE_ADDR + 0x28)) +#define MCI_DATA_CTRL (*(volatile unsigned long *)(MCI_BASE_ADDR + 0x2C)) +#define MCI_DATA_CNT (*(volatile unsigned long *)(MCI_BASE_ADDR + 0x30)) +#define MCI_STATUS (*(volatile unsigned long *)(MCI_BASE_ADDR + 0x34)) +#define MCI_CLEAR (*(volatile unsigned long *)(MCI_BASE_ADDR + 0x38)) +#define MCI_MASK0 (*(volatile unsigned long *)(MCI_BASE_ADDR + 0x3C)) +#define MCI_MASK1 (*(volatile unsigned long *)(MCI_BASE_ADDR + 0x40)) +#define MCI_FIFO_CNT (*(volatile unsigned long *)(MCI_BASE_ADDR + 0x48)) +#define MCI_FIFO (*(volatile unsigned long *)(MCI_BASE_ADDR + 0x80)) + + +/* I2S Interface Controller (I2S) */ +#define I2S_BASE_ADDR 0xE0088000 +#define I2S_DAO (*(volatile unsigned long *)(I2S_BASE_ADDR + 0x00)) +#define I2S_DAI (*(volatile unsigned long *)(I2S_BASE_ADDR + 0x04)) +#define I2S_TX_FIFO (*(volatile unsigned long *)(I2S_BASE_ADDR + 0x08)) +#define I2S_RX_FIFO (*(volatile unsigned long *)(I2S_BASE_ADDR + 0x0C)) +#define I2S_STATE (*(volatile unsigned long *)(I2S_BASE_ADDR + 0x10)) +#define I2S_DMA1 (*(volatile unsigned long *)(I2S_BASE_ADDR + 0x14)) +#define I2S_DMA2 (*(volatile unsigned long *)(I2S_BASE_ADDR + 0x18)) +#define I2S_IRQ (*(volatile unsigned long *)(I2S_BASE_ADDR + 0x1C)) +#define I2S_TXRATE (*(volatile unsigned long *)(I2S_BASE_ADDR + 0x20)) +#define I2S_RXRATE (*(volatile unsigned long *)(I2S_BASE_ADDR + 0x24)) + + +/* General-purpose DMA Controller */ +#define DMA_BASE_ADDR 0xFFE04000 +#define GPDMA_INT_STAT (*(volatile unsigned long *)(DMA_BASE_ADDR + 0x000)) +#define GPDMA_INT_TCSTAT (*(volatile unsigned long *)(DMA_BASE_ADDR + 0x004)) +#define GPDMA_INT_TCCLR (*(volatile unsigned long *)(DMA_BASE_ADDR + 0x008)) +#define GPDMA_INT_ERR_STAT (*(volatile unsigned long *)(DMA_BASE_ADDR + 0x00C)) +#define GPDMA_INT_ERR_CLR (*(volatile unsigned long *)(DMA_BASE_ADDR + 0x010)) +#define GPDMA_RAW_INT_TCSTAT (*(volatile unsigned long *)(DMA_BASE_ADDR + 0x014)) +#define GPDMA_RAW_INT_ERR_STAT (*(volatile unsigned long *)(DMA_BASE_ADDR + 0x018)) +#define GPDMA_ENABLED_CHNS (*(volatile unsigned long *)(DMA_BASE_ADDR + 0x01C)) +#define GPDMA_SOFT_BREQ (*(volatile unsigned long *)(DMA_BASE_ADDR + 0x020)) +#define GPDMA_SOFT_SREQ (*(volatile unsigned long *)(DMA_BASE_ADDR + 0x024)) +#define GPDMA_SOFT_LBREQ (*(volatile unsigned long *)(DMA_BASE_ADDR + 0x028)) +#define GPDMA_SOFT_LSREQ (*(volatile unsigned long *)(DMA_BASE_ADDR + 0x02C)) +#define GPDMA_CONFIG (*(volatile unsigned long *)(DMA_BASE_ADDR + 0x030)) +#define GPDMA_SYNC (*(volatile unsigned long *)(DMA_BASE_ADDR + 0x034)) + +/* DMA channel 0 registers */ +#define GPDMA_CH0_SRC (*(volatile unsigned long *)(DMA_BASE_ADDR + 0x100)) +#define GPDMA_CH0_DEST (*(volatile unsigned long *)(DMA_BASE_ADDR + 0x104)) +#define GPDMA_CH0_LLI (*(volatile unsigned long *)(DMA_BASE_ADDR + 0x108)) +#define GPDMA_CH0_CTRL (*(volatile unsigned long *)(DMA_BASE_ADDR + 0x10C)) +#define GPDMA_CH0_CFG (*(volatile unsigned long *)(DMA_BASE_ADDR + 0x110)) + +/* DMA channel 1 registers */ +#define GPDMA_CH1_SRC (*(volatile unsigned long *)(DMA_BASE_ADDR + 0x120)) +#define GPDMA_CH1_DEST (*(volatile unsigned long *)(DMA_BASE_ADDR + 0x124)) +#define GPDMA_CH1_LLI (*(volatile unsigned long *)(DMA_BASE_ADDR + 0x128)) +#define GPDMA_CH1_CTRL (*(volatile unsigned long *)(DMA_BASE_ADDR + 0x12C)) +#define GPDMA_CH1_CFG (*(volatile unsigned long *)(DMA_BASE_ADDR + 0x130)) + + +/* USB Controller */ +#define USB_INT_BASE_ADDR 0xE01FC1C0 +#define USB_BASE_ADDR 0xFFE0C200 /* USB Base Address */ + +#define USB_INT_STAT (*(volatile unsigned long *)(USB_INT_BASE_ADDR + 0x00)) + +/* USB Device Interrupt Registers */ +#define DEV_INT_STAT (*(volatile unsigned long *)(USB_BASE_ADDR + 0x00)) +#define DEV_INT_EN (*(volatile unsigned long *)(USB_BASE_ADDR + 0x04)) +#define DEV_INT_CLR (*(volatile unsigned long *)(USB_BASE_ADDR + 0x08)) +#define DEV_INT_SET (*(volatile unsigned long *)(USB_BASE_ADDR + 0x0C)) +#define DEV_INT_PRIO (*(volatile unsigned long *)(USB_BASE_ADDR + 0x2C)) + +/* USB Device Endpoint Interrupt Registers */ +#define EP_INT_STAT (*(volatile unsigned long *)(USB_BASE_ADDR + 0x30)) +#define EP_INT_EN (*(volatile unsigned long *)(USB_BASE_ADDR + 0x34)) +#define EP_INT_CLR (*(volatile unsigned long *)(USB_BASE_ADDR + 0x38)) +#define EP_INT_SET (*(volatile unsigned long *)(USB_BASE_ADDR + 0x3C)) +#define EP_INT_PRIO (*(volatile unsigned long *)(USB_BASE_ADDR + 0x40)) + +/* USB Device Endpoint Realization Registers */ +#define REALIZE_EP (*(volatile unsigned long *)(USB_BASE_ADDR + 0x44)) +#define EP_INDEX (*(volatile unsigned long *)(USB_BASE_ADDR + 0x48)) +#define MAXPACKET_SIZE (*(volatile unsigned long *)(USB_BASE_ADDR + 0x4C)) + +/* USB Device Command Reagisters */ +#define CMD_CODE (*(volatile unsigned long *)(USB_BASE_ADDR + 0x10)) +#define CMD_DATA (*(volatile unsigned long *)(USB_BASE_ADDR + 0x14)) + +/* USB Device Data Transfer Registers */ +#define RX_DATA (*(volatile unsigned long *)(USB_BASE_ADDR + 0x18)) +#define TX_DATA (*(volatile unsigned long *)(USB_BASE_ADDR + 0x1C)) +#define RX_PLENGTH (*(volatile unsigned long *)(USB_BASE_ADDR + 0x20)) +#define TX_PLENGTH (*(volatile unsigned long *)(USB_BASE_ADDR + 0x24)) +#define USB_CTRL (*(volatile unsigned long *)(USB_BASE_ADDR + 0x28)) + +/* USB Device DMA Registers */ +#define DMA_REQ_STAT (*(volatile unsigned long *)(USB_BASE_ADDR + 0x50)) +#define DMA_REQ_CLR (*(volatile unsigned long *)(USB_BASE_ADDR + 0x54)) +#define DMA_REQ_SET (*(volatile unsigned long *)(USB_BASE_ADDR + 0x58)) +#define UDCA_HEAD (*(volatile unsigned long *)(USB_BASE_ADDR + 0x80)) +#define EP_DMA_STAT (*(volatile unsigned long *)(USB_BASE_ADDR + 0x84)) +#define EP_DMA_EN (*(volatile unsigned long *)(USB_BASE_ADDR + 0x88)) +#define EP_DMA_DIS (*(volatile unsigned long *)(USB_BASE_ADDR + 0x8C)) +#define DMA_INT_STAT (*(volatile unsigned long *)(USB_BASE_ADDR + 0x90)) +#define DMA_INT_EN (*(volatile unsigned long *)(USB_BASE_ADDR + 0x94)) +#define EOT_INT_STAT (*(volatile unsigned long *)(USB_BASE_ADDR + 0xA0)) +#define EOT_INT_CLR (*(volatile unsigned long *)(USB_BASE_ADDR + 0xA4)) +#define EOT_INT_SET (*(volatile unsigned long *)(USB_BASE_ADDR + 0xA8)) +#define NDD_REQ_INT_STAT (*(volatile unsigned long *)(USB_BASE_ADDR + 0xAC)) +#define NDD_REQ_INT_CLR (*(volatile unsigned long *)(USB_BASE_ADDR + 0xB0)) +#define NDD_REQ_INT_SET (*(volatile unsigned long *)(USB_BASE_ADDR + 0xB4)) +#define SYS_ERR_INT_STAT (*(volatile unsigned long *)(USB_BASE_ADDR + 0xB8)) +#define SYS_ERR_INT_CLR (*(volatile unsigned long *)(USB_BASE_ADDR + 0xBC)) +#define SYS_ERR_INT_SET (*(volatile unsigned long *)(USB_BASE_ADDR + 0xC0)) + +/* USB Host and OTG registers are for LPC24xx only */ +/* USB Host Controller */ +#define USBHC_BASE_ADDR 0xFFE0C000 +#define HC_REVISION (*(volatile unsigned long *)(USBHC_BASE_ADDR + 0x00)) +#define HC_CONTROL (*(volatile unsigned long *)(USBHC_BASE_ADDR + 0x04)) +#define HC_CMD_STAT (*(volatile unsigned long *)(USBHC_BASE_ADDR + 0x08)) +#define HC_INT_STAT (*(volatile unsigned long *)(USBHC_BASE_ADDR + 0x0C)) +#define HC_INT_EN (*(volatile unsigned long *)(USBHC_BASE_ADDR + 0x10)) +#define HC_INT_DIS (*(volatile unsigned long *)(USBHC_BASE_ADDR + 0x14)) +#define HC_HCCA (*(volatile unsigned long *)(USBHC_BASE_ADDR + 0x18)) +#define HC_PERIOD_CUR_ED (*(volatile unsigned long *)(USBHC_BASE_ADDR + 0x1C)) +#define HC_CTRL_HEAD_ED (*(volatile unsigned long *)(USBHC_BASE_ADDR + 0x20)) +#define HC_CTRL_CUR_ED (*(volatile unsigned long *)(USBHC_BASE_ADDR + 0x24)) +#define HC_BULK_HEAD_ED (*(volatile unsigned long *)(USBHC_BASE_ADDR + 0x28)) +#define HC_BULK_CUR_ED (*(volatile unsigned long *)(USBHC_BASE_ADDR + 0x2C)) +#define HC_DONE_HEAD (*(volatile unsigned long *)(USBHC_BASE_ADDR + 0x30)) +#define HC_FM_INTERVAL (*(volatile unsigned long *)(USBHC_BASE_ADDR + 0x34)) +#define HC_FM_REMAINING (*(volatile unsigned long *)(USBHC_BASE_ADDR + 0x38)) +#define HC_FM_NUMBER (*(volatile unsigned long *)(USBHC_BASE_ADDR + 0x3C)) +#define HC_PERIOD_START (*(volatile unsigned long *)(USBHC_BASE_ADDR + 0x40)) +#define HC_LS_THRHLD (*(volatile unsigned long *)(USBHC_BASE_ADDR + 0x44)) +#define HC_RH_DESCA (*(volatile unsigned long *)(USBHC_BASE_ADDR + 0x48)) +#define HC_RH_DESCB (*(volatile unsigned long *)(USBHC_BASE_ADDR + 0x4C)) +#define HC_RH_STAT (*(volatile unsigned long *)(USBHC_BASE_ADDR + 0x50)) +#define HC_RH_PORT_STAT1 (*(volatile unsigned long *)(USBHC_BASE_ADDR + 0x54)) +#define HC_RH_PORT_STAT2 (*(volatile unsigned long *)(USBHC_BASE_ADDR + 0x58)) + +/* USB OTG Controller */ +#define USBOTG_BASE_ADDR 0xFFE0C100 +#define OTG_INT_STAT (*(volatile unsigned long *)(USBOTG_BASE_ADDR + 0x00)) +#define OTG_INT_EN (*(volatile unsigned long *)(USBOTG_BASE_ADDR + 0x04)) +#define OTG_INT_SET (*(volatile unsigned long *)(USBOTG_BASE_ADDR + 0x08)) +#define OTG_INT_CLR (*(volatile unsigned long *)(USBOTG_BASE_ADDR + 0x0C)) +/* On LPC23xx, the name is USBPortSel, on LPC24xx, the name is OTG_STAT_CTRL */ +#define OTG_STAT_CTRL (*(volatile unsigned long *)(USBOTG_BASE_ADDR + 0x10)) +#define OTG_TIMER (*(volatile unsigned long *)(USBOTG_BASE_ADDR + 0x14)) + +#define USBOTG_I2C_BASE_ADDR 0xFFE0C300 +#define OTG_I2C_RX (*(volatile unsigned long *)(USBOTG_I2C_BASE_ADDR + 0x00)) +#define OTG_I2C_TX (*(volatile unsigned long *)(USBOTG_I2C_BASE_ADDR + 0x00)) +#define OTG_I2C_STS (*(volatile unsigned long *)(USBOTG_I2C_BASE_ADDR + 0x04)) +#define OTG_I2C_CTL (*(volatile unsigned long *)(USBOTG_I2C_BASE_ADDR + 0x08)) +#define OTG_I2C_CLKHI (*(volatile unsigned long *)(USBOTG_I2C_BASE_ADDR + 0x0C)) +#define OTG_I2C_CLKLO (*(volatile unsigned long *)(USBOTG_I2C_BASE_ADDR + 0x10)) + +/* On LPC23xx, the names are USBClkCtrl and USBClkSt; on LPC24xx, the names are +OTG_CLK_CTRL and OTG_CLK_STAT respectively. */ +#define USBOTG_CLK_BASE_ADDR 0xFFE0CFF0 +#define OTG_CLK_CTRL (*(volatile unsigned long *)(USBOTG_CLK_BASE_ADDR + 0x04)) +#define OTG_CLK_STAT (*(volatile unsigned long *)(USBOTG_CLK_BASE_ADDR + 0x08)) + +/* Note: below three register name convention is for LPC23xx USB device only, match +with the spec. update in USB Device Section. */ +#define USBPortSel (*(volatile unsigned long *)(USBOTG_BASE_ADDR + 0x10)) +#define USBClkCtrl (*(volatile unsigned long *)(USBOTG_CLK_BASE_ADDR + 0x04)) +#define USBClkSt (*(volatile unsigned long *)(USBOTG_CLK_BASE_ADDR + 0x08)) + +/* Ethernet MAC (32 bit data bus) -- all registers are RW unless indicated in parentheses */ +#define MAC_BASE_ADDR 0xFFE00000 /* AHB Peripheral # 0 */ +#define MAC_MAC1 (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x000)) /* MAC config reg 1 */ +#define MAC_MAC2 (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x004)) /* MAC config reg 2 */ +#define MAC_IPGT (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x008)) /* b2b InterPacketGap reg */ +#define MAC_IPGR (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x00C)) /* non b2b InterPacketGap reg */ +#define MAC_CLRT (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x010)) /* CoLlision window/ReTry reg */ +#define MAC_MAXF (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x014)) /* MAXimum Frame reg */ +#define MAC_SUPP (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x018)) /* PHY SUPPort reg */ +#define MAC_TEST (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x01C)) /* TEST reg */ +#define MAC_MCFG (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x020)) /* MII Mgmt ConFiG reg */ +#define MAC_MCMD (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x024)) /* MII Mgmt CoMmanD reg */ +#define MAC_MADR (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x028)) /* MII Mgmt ADdRess reg */ +#define MAC_MWTD (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x02C)) /* MII Mgmt WriTe Data reg (WO) */ +#define MAC_MRDD (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x030)) /* MII Mgmt ReaD Data reg (RO) */ +#define MAC_MIND (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x034)) /* MII Mgmt INDicators reg (RO) */ + +#define MAC_SA0 (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x040)) /* Station Address 0 reg */ +#define MAC_SA1 (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x044)) /* Station Address 1 reg */ +#define MAC_SA2 (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x048)) /* Station Address 2 reg */ + +#define MAC_COMMAND (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x100)) /* Command reg */ +#define MAC_STATUS (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x104)) /* Status reg (RO) */ +#define MAC_RXDESCRIPTOR (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x108)) /* Rx descriptor base address reg */ +#define MAC_RXSTATUS (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x10C)) /* Rx status base address reg */ +#define MAC_RXDESCRIPTORNUM (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x110)) /* Rx number of descriptors reg */ +#define MAC_RXPRODUCEINDEX (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x114)) /* Rx produce index reg (RO) */ +#define MAC_RXCONSUMEINDEX (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x118)) /* Rx consume index reg */ +#define MAC_TXDESCRIPTOR (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x11C)) /* Tx descriptor base address reg */ +#define MAC_TXSTATUS (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x120)) /* Tx status base address reg */ +#define MAC_TXDESCRIPTORNUM (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x124)) /* Tx number of descriptors reg */ +#define MAC_TXPRODUCEINDEX (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x128)) /* Tx produce index reg */ +#define MAC_TXCONSUMEINDEX (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x12C)) /* Tx consume index reg (RO) */ + +#define MAC_TSV0 (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x158)) /* Tx status vector 0 reg (RO) */ +#define MAC_TSV1 (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x15C)) /* Tx status vector 1 reg (RO) */ +#define MAC_RSV (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x160)) /* Rx status vector reg (RO) */ + +#define MAC_FLOWCONTROLCNT (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x170)) /* Flow control counter reg */ +#define MAC_FLOWCONTROLSTS (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x174)) /* Flow control status reg */ + +#define MAC_RXFILTERCTRL (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x200)) /* Rx filter ctrl reg */ +#define MAC_RXFILTERWOLSTS (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x204)) /* Rx filter WoL status reg (RO) */ +#define MAC_RXFILTERWOLCLR (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x208)) /* Rx filter WoL clear reg (WO) */ + +#define MAC_HASHFILTERL (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x210)) /* Hash filter LSBs reg */ +#define MAC_HASHFILTERH (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x214)) /* Hash filter MSBs reg */ + +#define MAC_INTSTATUS (*(volatile unsigned long *)(MAC_BASE_ADDR + 0xFE0)) /* Interrupt status reg (RO) */ +#define MAC_INTENABLE (*(volatile unsigned long *)(MAC_BASE_ADDR + 0xFE4)) /* Interrupt enable reg */ +#define MAC_INTCLEAR (*(volatile unsigned long *)(MAC_BASE_ADDR + 0xFE8)) /* Interrupt clear reg (WO) */ +#define MAC_INTSET (*(volatile unsigned long *)(MAC_BASE_ADDR + 0xFEC)) /* Interrupt set reg (WO) */ + +#define MAC_POWERDOWN (*(volatile unsigned long *)(MAC_BASE_ADDR + 0xFF4)) /* Power-down reg */ +#define MAC_MODULEID (*(volatile unsigned long *)(MAC_BASE_ADDR + 0xFFC)) /* Module ID reg (RO) */ + + +#endif // __LPC23xx_H + diff --git a/cpu/lpc2387/linkerscript.x b/cpu/lpc2387/linkerscript.x new file mode 100644 index 0000000000..7048298937 --- /dev/null +++ b/cpu/lpc2387/linkerscript.x @@ -0,0 +1,194 @@ +/****************************************************************************** +Copyright 2008-2009, Freie Universitaet Berlin (FUB). All rights reserved. + +These sources were developed at the Freie Universitaet Berlin, Computer Systems +and Telematics group (http://cst.mi.fu-berlin.de). +------------------------------------------------------------------------------- +This file is part of FeuerWare. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +FeuerWare is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see http://www.gnu.org/licenses/ . +-------------------------------------------------------------------------------- +For further information and questions please use the web site + http://scatterweb.mi.fu-berlin.de +and the mailinglist (subscription via web site) + scatterweb@lists.spline.inf.fu-berlin.de +*******************************************************************************/ + +/* specify the LPC2387 memory areas (see LPC2387 datasheet page 15) */ +MEMORY +{ + flash : ORIGIN = 0, LENGTH = 512K /* FLASH ROM */ + ram_battery : ORIGIN = 0xE0084000, LENGTH = 2K /* Battery RAM */ + ram : ORIGIN = 0x40000000, LENGTH = 64K /* LOCAL ON-CHIP STATIC RAM */ + ram_usb : ORIGIN = 0x7FD00000, LENGTH = 16K /* USB RAM */ + ram_ethernet : ORIGIN = 0x7FE00000, LENGTH = 16K /* ethernet RAM */ +} + +__stack_und_size = 4; /* stack for "undefined instruction" interrupts */ +__stack_abt_size = 4; /* stack for "abort" interrupts */ +__stack_fiq_size = 64; /* stack for "FIQ" interrupts */ +__stack_irq_size = 400; /* stack for "IRQ" normal interrupts */ +__stack_svc_size = 400; /* stack for "SVC" supervisor mode */ +__stack_usr_size = 4096; /* stack for user operation (kernel init) */ +__stack_size = __stack_und_size + __stack_abt_size + __stack_fiq_size + __stack_irq_size + __stack_svc_size + __stack_usr_size; + +/* now define the output sections */ +SECTIONS +{ + .text : /* collect all sections that should go into FLASH after startup */ + { + *(.vectors) /* Exception Vectors and branch table >= 64 bytes */ + . = ALIGN(64); + *(.init) + *(.init0) /* Start here after reset. */ + *(.init1) + *(.init2) /* Copy data loop */ + *(.init3) + *(.init4) /* Clear bss */ + *(.init5) + *(.init6) /* C++ constructors. */ + *(.init7) + *(.init8) + *(.init9) /* Call main(). */ + + *(.text) /* all .text sections (code) */ + *(.text.*) + *(.gnu.linkonce.t.*) + + . = ALIGN(4); + __commands_start = .; + *(.commands) /* command table */ + __commands_end = .; + . = ALIGN(4); + __cfgspec_start = .; + *(.cfgspec) /* configuration spec table */ + __cfgspec_end = .; + . = ALIGN(4); + + *(.rodata .rodata.*) /* all .rodata sections (constants, strings, etc.) */ + *(.gnu.linkonce.r.*) + *(.glue_7) /* all .glue_7 sections (no idea what these are) */ + *(.glue_7t) /* all .glue_7t sections (no idea what these are) */ + + *(.fini9) + *(.fini8) + *(.fini7) + *(.fini6) /* C++ destructors. */ + *(.fini5) + *(.fini4) + *(.fini3) + *(.fini2) + *(.fini1) + *(.fini0) /* Infinite loop after program termination. */ + *(.fini) + + *(.gcc_except_table) + + } >flash /* put all the above into FLASH */ + . = ALIGN(4); + _etext = . ; /* define a global symbol _etext just after the last code byte */ + + /************************************************************************** + * RAM + **************************************************************************/ + + /* + * collect all uninitialized sections that go into RAM + */ + .noinit (NOLOAD) : + { + __noinit_start = .; + PROVIDE(__fiq_handler = .); + *(.fiq) + *(.noinit) + } > ram + . = ALIGN(4); + __noinit_end = .; + + /* + * collect all zero initialized sections that go into RAM + */ + .bss (NOLOAD) : + { + . = ALIGN(4); /* ensure data is aligned so relocation can use 4-byte operations */ + __bss_start = .; /* define a global symbol marking the start of the .bss section */ + *(.bss) /* all .bss sections */ + *(COMMON) + } > ram /* put all the above in RAM (it will be cleared in the startup code */ + . = ALIGN(4); /* ensure data is aligned so relocation can use 4-byte operations */ + __bss_end = . ; /* define a global symbol marking the end of the .bss section */ + + /* + * collect all initialized .data sections that go into RAM + * initial values get placed at the end of .text in flash + */ + .data : AT (_etext) + { + . = ALIGN(4); /* ensure data is aligned so relocation can use 4-byte operations */ + _data = .; /* create a global symbol marking the start of the .data section */ + *(.data) /* all .data sections */ + *(.gnu.linkonce.d*) + } >ram /* put all the above into RAM (but load the LMA copy into FLASH) */ + . = ALIGN(4); /* ensure data is aligned so relocation can use 4-byte operations */ + _edata = .; /* define a global symbol marking the end of the .data section */ + _end = .; /* define a global symbol marking the end of application RAM */ + + __heap1_size = ORIGIN(ram) + LENGTH(ram) - . - __stack_size; + .heap1 (NOLOAD) : + { + PROVIDE(__heap1_start = .); + . = . + __heap1_size; + PROVIDE(__heap1_max = .); + } > ram + + /* + * Stacks + */ + .stack (NOLOAD) : + { + PROVIDE(__stack_start = .); + + . = . + __stack_usr_size; + __stack_usr_start = .; + . = . + __stack_und_size; + __stack_und_start = .; + . = . + __stack_fiq_size; + __stack_fiq_start = .; + . = . + __stack_irq_size; + __stack_irq_start = .; + . = . + __stack_abt_size; + __stack_abt_start = .; + . = . + __stack_svc_size; + __stack_svc_start = .; + + PROVIDE(__stack_end = .); + } > ram + + __heap2_size = LENGTH(ram_ethernet); + .heap2 (NOLOAD) : + { + PROVIDE(__heap2_start = . ); + . = . + __heap2_size; + PROVIDE(__heap2_max = .); /* _heap shall always be < _heap_max */ + } > ram_ethernet + + .usbdata (NOLOAD) : /* USB RAM section, may be used otherwise if USB is disabled */ + { + *(.usbdata) + } > ram_usb + + .batteryram (NOLOAD) : /* battery ram stay on during powerdown but needs to be handled specially */ + { + *(.batteryram) + } > ram_battery +} diff --git a/cpu/lpc2387/lpc2387-gpioint.c b/cpu/lpc2387/lpc2387-gpioint.c new file mode 100644 index 0000000000..e33fc854a4 --- /dev/null +++ b/cpu/lpc2387/lpc2387-gpioint.c @@ -0,0 +1,174 @@ +/****************************************************************************** +Copyright 2009, Freie Universitaet Berlin (FUB). All rights reserved. + +These sources were developed at the Freie Universitaet Berlin, Computer Systems +and Telematics group (http://cst.mi.fu-berlin.de). +------------------------------------------------------------------------------- +This file is part of FeuerWare. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +FeuerWare is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see http://www.gnu.org/licenses/ . +-------------------------------------------------------------------------------- +For further information and questions please use the web site + http://scatterweb.mi.fu-berlin.de +and the mailinglist (subscription via web site) + scatterweb@lists.spline.inf.fu-berlin.de +*******************************************************************************/ + +/** + * @ingroup lpc2387 + * @addtogroup dev_gpioint + * @{ + */ + +/** + * @file + * @brief LPC2387 GPIO Interrupt Multiplexer implementation + * + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @author Michael Baar + * @version $Revision: 1508 $ + * + * @note $Id: lpc2387-gpioint.c 1508 2009-10-26 15:10:02Z baar $ + * @see dev_gpioint + */ + +#include +#include "lpc2387.h" +#include "gpioint.h" +#include "cpu.h" +#include + +struct irq_callback { + fp_irqcb callback; +}; + +static struct irq_callback gpioint0[32]; +static struct irq_callback gpioint2[32]; + + +void gpioint_init(void) { + extern void GPIO_IRQHandler(void); + + /* GPIO Init */ + INTWAKE |= GPIO0WAKE | GPIO2WAKE; // allow GPIO to wake up from power down + install_irq(GPIO_INT, &GPIO_IRQHandler, IRQP_GPIO); // install irq handler +} + +/*---------------------------------------------------------------------------*/ +bool +gpioint_set(int port, uint32_t bitmask, int flags, fp_irqcb callback) +{ + struct irq_callback* cbdata; + unsigned long bit; + volatile unsigned long* en_f; + volatile unsigned long* en_r; + volatile unsigned long* en_clr; + + /* lookup registers */ + bit = number_of_highest_bit(bitmask); // get irq mapping table index + + switch( port ) { + case 0: // PORT0 + cbdata = gpioint0; + en_f = &IO0_INT_EN_F; + en_r = &IO0_INT_EN_R; + en_clr = &IO0_INT_CLR; + break; + + case 2: // PORT2 + cbdata = gpioint2; + en_f = &IO2_INT_EN_F; + en_r = &IO2_INT_EN_R; + en_clr = &IO2_INT_CLR; + break; + + default: // unsupported + return false; // fail + } + + /* reconfigure irq */ + unsigned long cpsr = disableIRQ(); + *en_clr |= bitmask; // clear interrupt + + if( (flags & GPIOINT_FALLING_EDGE) != 0 ) { + *en_f |= bitmask; // enable falling edge + } else { + *en_f &= ~bitmask; // disable falling edge + } + + if( (flags & GPIOINT_RISING_EDGE) != 0 ) { + *en_r |= bitmask; // enable rising edge + } else { + *en_r &= ~bitmask; // disable rising edge + } + + if( ((flags & (GPIOINT_FALLING_EDGE | GPIOINT_RISING_EDGE)) != 0) ) { + cbdata[bit].callback = callback; + + } else { + cbdata[bit].callback = NULL; // remove from interrupt mapping table + } + restoreIRQ(cpsr); + + return true; // success +} +/*---------------------------------------------------------------------------*/ +static void test_irq(int port, unsigned long f_mask, unsigned long r_mask, struct irq_callback* pcb) +{ + /* Test each bit of rising and falling masks, if set trigger interrupt + * on corresponding device */ + do { + if( (pcb->callback != NULL) ) { + if ((r_mask & 1) | (f_mask & 1)) { + pcb->callback(); // pass to handler + } + } + + f_mask >>= 1UL; + r_mask >>= 1UL; + pcb++; + } while( (f_mask != 0) || (r_mask != 0) ); +} +/*---------------------------------------------------------------------------*/ +void GPIO_IRQHandler(void) __attribute__((interrupt("IRQ"))); +/** + * @brief GPIO Interrupt handler function + * @internal + * + * Invoked whenever an activated gpio interrupt is triggered by a rising + * or falling edge. + */ +void GPIO_IRQHandler(void) { + if( IO_INT_STAT & BIT0 ) { // interrupt(s) on PORT0 pending + unsigned long int_stat_f = IO0_INT_STAT_F; // save content + unsigned long int_stat_r = IO0_INT_STAT_R; // save content + + IO0_INT_CLR = int_stat_f; // clear flags of fallen pins + IO0_INT_CLR = int_stat_r; // clear flags of risen pins + + test_irq(0, int_stat_f, int_stat_r, gpioint0); + } + + if( IO_INT_STAT & BIT2 ) { // interrupt(s) on PORT2 pending + unsigned long int_stat_f = IO2_INT_STAT_F; // save content + unsigned long int_stat_r = IO2_INT_STAT_R; // save content + + IO2_INT_CLR = int_stat_f; // clear flags of fallen pins + IO2_INT_CLR = int_stat_r; // clear flags of risen pins + + test_irq(2, int_stat_f, int_stat_r, gpioint2); + } + VICVectAddr = 0; // Acknowledge Interrupt +} +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/cpu/lpc2387/lpc2387-lpm.c b/cpu/lpc2387/lpc2387-lpm.c new file mode 100644 index 0000000000..d36829b1cf --- /dev/null +++ b/cpu/lpc2387/lpc2387-lpm.c @@ -0,0 +1,134 @@ +/****************************************************************************** +Copyright 2009, Freie Universitaet Berlin (FUB). All rights reserved. + +These sources were developed at the Freie Universitaet Berlin, Computer Systems +and Telematics group (http://cst.mi.fu-berlin.de). +------------------------------------------------------------------------------- +This file is part of FeuerWare. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +FeuerWare is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see http://www.gnu.org/licenses/ . +-------------------------------------------------------------------------------- +For further information and questions please use the web site + http://scatterweb.mi.fu-berlin.de +and the mailinglist (subscription via web site) + scatterweb@lists.spline.inf.fu-berlin.de +*******************************************************************************/ + +/** + * @ingroup lpc2387 + * @{ + */ + +/** + * @file + * @brief LPC2387 Low-Power management + * @ingroup lpc2387 + * + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @author Heiko Will + * @version $Revision$ + * + * @note $Id$ + */ + +#include +#include +#include "board.h" +#include "lpc23xx.h" +#include "lpc2387.h" +#include "lpm.h" + +/* lpm is accessed before memory init and initialized separately through code */ +__attribute__((section(".noinit"))) +static enum lpm_mode lpm; + +extern void init_clks1(void); +extern void init_clks2(void); + +#define DEBUG 0 +#if DEBUG +#include +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif + + +void +lpm_init(void) +{ + lpm = LPM_ON; +} + +#define LPM_DEBUG 0 + +void lpm_begin_awake(void) { + if (lpm >= LPM_SLEEP ) { // wake up from deep sleep + init_clks1(); + } +} + +void lpm_end_awake(void) { + if( lpm >= LPM_SLEEP ) { // wake up from deep sleep + init_clks2(); + } + lpm = LPM_ON; +} + +void lpm_awake(void) { +#if LPM_DEBUG + unsigned long usec = RTC_CTC; +#endif + if( lpm >= LPM_SLEEP ) { // wake up from deep sleep + //benchmark + init_clks1(); + init_clks2(); + // Debug tests +#if LPM_DEBUG + usec = RTC_CTC-usec; + printf("Wakeup in %lu usecs\n",usec * 31); +#endif + } + lpm = LPM_ON; +} + +enum lpm_mode lpm_set(enum lpm_mode target) { + unsigned target_flags; + enum lpm_mode last_lpm = lpm; + + /* calculate target mcu power mode */ + if( target == LPM_IDLE ) + target_flags = PM_IDLE; + else if( target == LPM_SLEEP ) + target_flags = PM_SLEEP; + else if( target == LPM_POWERDOWN ) + target_flags = PM_POWERDOWN; + else + target_flags = 0; + + lpm = target; + + #if DEBUG + PRINTF("# LPM power down %u -> %u", lpm, target); + #endif + + PCON |= target_flags; // set target power mode + return last_lpm; +} +/*---------------------------------------------------------------------------*/ +enum lpm_mode +lpm_get(void) { + return lpm; +} +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/cpu/lpc2387/lpc2387-rtc.c b/cpu/lpc2387/lpc2387-rtc.c new file mode 100644 index 0000000000..7ab60e09c4 --- /dev/null +++ b/cpu/lpc2387/lpc2387-rtc.c @@ -0,0 +1,254 @@ +/****************************************************************************** +Copyright 2008-2010, Freie Universitaet Berlin (FUB). All rights reserved. + +These sources were developed at the Freie Universitaet Berlin, Computer Systems +and Telematics group (http://cst.mi.fu-berlin.de). +------------------------------------------------------------------------------- +This file is part of FeuerWare. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +FeuerWare is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see http://www.gnu.org/licenses/ . +-------------------------------------------------------------------------------- +For further information and questions please use the web site + http://scatterweb.mi.fu-berlin.de +and the mailinglist (subscription via web site) + scatterweb@lists.spline.inf.fu-berlin.de +*******************************************************************************/ + +/** + * @file + * @ingroup lpc2387_rtc + * @brief LPC2387 Real-Time-Clock + * + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @author Michael Baar + * @version $Revision: 2005 $ + * + * @note $Id: lpc2387-rtc.c 2005 2010-03-17 10:52:03Z baar $ + */ + +#include +#include +#include + +// cpu +#include "VIC.h" +#include "lpc2387.h" +#include "lpc2387-rtc.h" +#include "lpm.h" +#include "clock.h" + +#define PREINT_RTC 0x000001C8 /* Prescaler value, integer portion, PCLK = 15Mhz */ +#define PREFRAC_RTC 0x000061C0 /* Prescaler value, fraction portion, PCLK = 15Mhz */ + +#define DEBUG 0 +#if DEBUG +#include +#define PRINTF(fmt, args...) printf("rtc: " fmt "\n", ##args) +#else +#define PRINTF(fmt, args...) +#endif + +extern void _clock_alarm(void); + +/** + * @brief epoch time in hour granularity + */ +static volatile time_t epoch; + +/*---------------------------------------------------------------------------*/ +/** + * @brief Sets the current time in broken down format directly from to RTC + * @param[in] localt Pointer to structure with time to set + */ +static void +rtc_set_localtime(struct tm* localt) +{ + if( localt == NULL ) + return; + + /* set clock */ + RTC_SEC = localt->tm_sec; + RTC_MIN = localt->tm_min; + RTC_HOUR = localt->tm_hour; + RTC_DOM = localt->tm_mday; + RTC_DOW = localt->tm_wday; + RTC_DOY = localt->tm_yday; + RTC_MONTH = localt->tm_mon + 1; + RTC_YEAR = localt->tm_year; +} +/*---------------------------------------------------------------------------*/ +void rtc_set(time_t time) { + struct tm* localt; + localt = localtime(&time); // convert seconds to broken-down time + rtc_set_localtime(localt); + epoch = time - localt->tm_sec - localt->tm_min * 60; +} +/*---------------------------------------------------------------------------*/ +/// set clock to start of unix epoch +void _rtc_reset(void) +{ + rtc_set(0); + epoch = 0; +} +/*---------------------------------------------------------------------------*/ +void +_rtc_set_alarm(struct tm* localt, enum rtc_alarm_mask mask) +{ + if( localt != NULL ) { + RTC_ALSEC = localt->tm_sec; + RTC_ALMIN = localt->tm_min; + RTC_ALHOUR = localt->tm_hour; + RTC_ALDOM = localt->tm_mday; + RTC_ALDOW = localt->tm_wday; + RTC_ALDOY = localt->tm_yday; + RTC_ALMON = localt->tm_mon + 1; + RTC_ALYEAR = localt->tm_year; + RTC_AMR = ~mask; // set wich alarm fields to check + PRINTF("alarm set %2lu.%2lu.%4lu %2lu:%2lu:%2lu", + RTC_ALDOM, RTC_ALMON, RTC_ALYEAR, RTC_ALHOUR, RTC_ALMIN, RTC_ALSEC); + } else { + RTC_AMR = 0xff; + } +} +/*---------------------------------------------------------------------------*/ +enum rtc_alarm_mask +_rtc_get_alarm(struct tm* localt) +{ + if( localt != NULL ) { + localt->tm_sec = RTC_ALSEC; + localt->tm_min = RTC_ALMIN; + localt->tm_hour = RTC_ALHOUR; + localt->tm_mday = RTC_ALDOM; + localt->tm_wday = RTC_ALDOW; + localt->tm_yday = RTC_ALDOY; + localt->tm_mon = RTC_ALMON - 1; + localt->tm_year = RTC_ALYEAR; + localt->tm_isdst = -1; // not available + } + return (~RTC_AMR) & 0xff; // return which alarm fields are checked +} +/*---------------------------------------------------------------------------*/ +void RTC_IRQHandler (void) __attribute__ ((interrupt("IRQ"))); +void RTC_IRQHandler (void) +{ + lpm_begin_awake(); + if( RTC_ILR & ILR_RTSSF ) { + // sub second interrupt (does not need flag-clearing) + + } else if( RTC_ILR & ILR_RTCCIF ) { + // counter increase interrupt + RTC_ILR |= ILR_RTCCIF; + epoch += 60 * 60; // add 1 hour + + } else if( RTC_ILR & ILR_RTCALF ) { + RTC_ILR |= ILR_RTCALF; + RTC_AMR = 0xff; // disable alarm irq + PRINTF("alarm"); + lpm_end_awake(); + _clock_alarm(); + } + + VICVectAddr = 0; // Acknowledge Interrupt +} + +/*---------------------------------------------------------------------------*/ +void rtc_enable(void) +{ + RTC_ILR = (ILR_RTSSF | ILR_RTCCIF | ILR_RTCALF); // clear interrupt flags + RTC_CCR |= CCR_CLKEN; // enable clock + install_irq(RTC_INT, &RTC_IRQHandler, IRQP_RTC); // install interrupt handler + + time_t now = rtc_time(NULL); + epoch = now - (now % 3600); +} +/*---------------------------------------------------------------------------*/ +void _rtc_init(void) +{ + PCONP |= BIT9; + RTC_AMR = 0xff; // disable alarm irq + RTC_CIIR = IMHOUR; // enable increase irq + RTC_CISS = 0; // disable subsecond irq + + INTWAKE |= BIT15; // rtc irq wakes up mcu from power down + + RTC_CCR = CCR_CLKSRC; // Clock from external 32 kHz Osc. + + /* initialize clock with valid unix compatible values + * If RTC_YEAR contains an value larger unix time_t we must reset. */ + if( RTC_YEAR > 2037 ) { + _rtc_reset(); + } + + PRINTF("%2lu.%2lu.%4lu %2lu:%2lu:%2lu epoch %lu", + RTC_DOM, RTC_MONTH, RTC_YEAR, RTC_HOUR, RTC_MIN, RTC_SEC, + epoch); +} +/*---------------------------------------------------------------------------*/ +time_t rtc_time(struct timeval* time) +{ + uint32_t sec; + uint32_t usec; + uint32_t min; + + usec = (RTC_CTC >> 1); + sec = RTC_SEC; + min = RTC_MIN; + while (usec != (RTC_CTC>>1) ) { + usec = (RTC_CTC >> 1); + sec = RTC_SEC; + min = RTC_MIN; + } + + sec += min * 60; // add number of minutes + sec += epoch; // add precalculated epoch in hour granularity + + if( time != NULL ) { + usec = usec * 15625; + usec >>= 9; + time->tv_sec = sec; + time->tv_usec = usec; + } + + return sec; +} +/*---------------------------------------------------------------------------*/ +void rtc_disable(void) +{ + RTC_CCR &= ~CCR_CLKEN; // disable clock + install_irq(RTC_INT, NULL, 0); + RTC_ILR = 0; +} +/*---------------------------------------------------------------------------*/ +void +rtc_get_localtime(struct tm* localt) +{ + if( localt != NULL ) { + localt->tm_sec = RTC_SEC; + localt->tm_min = RTC_MIN; + localt->tm_hour = RTC_HOUR; + localt->tm_mday = RTC_DOM; + localt->tm_wday = RTC_DOW; + localt->tm_yday = RTC_DOY; + localt->tm_mon = RTC_MONTH - 1; + localt->tm_year = RTC_YEAR; + localt->tm_isdst = -1; // not available + } +} +/*---------------------------------------------------------------------------*/ +void _gettimeofday_r(struct _reent *r, struct timeval *ptimeval, struct timezone *ptimezone) +{ + r->_errno = 0; + if( ptimeval != NULL ) { + rtc_time(ptimeval); + } +} diff --git a/cpu/lpc2387/startup.s b/cpu/lpc2387/startup.s new file mode 100644 index 0000000000..f9ef062b4b --- /dev/null +++ b/cpu/lpc2387/startup.s @@ -0,0 +1,128 @@ +/* *************************************************************************************************************** + + crt.s STARTUP ASSEMBLY CODE + ----------------------- + + + Module includes the interrupt vectors and start-up code. + + *************************************************************************************************************** */ + +.extern __start_start +.extern __stack_end +.extern __fiq_handler + +/* Stack Positions */ +.extern __stack_usr_start +.extern __stack_abt_start +.extern __stack_und_start +.extern __stack_fiq_start +.extern __start_irq_start +.extern __start_svc_start + +/* Standard definitions of Mode bits and Interrupt (I & F) flags in PSRs (program status registers) */ +.set MODE_USR, 0x10 /* Normal User Mode */ +.set MODE_FIQ, 0x11 /* FIQ Processing Fast Interrupts Mode */ +.set MODE_IRQ, 0x12 /* IRQ Processing Standard Interrupts Mode */ +.set MODE_SVC, 0x13 /* Supervisor Processing Software Interrupts Mode */ +.set MODE_ABT, 0x17 /* Abort Processing memory Faults Mode */ +.set MODE_UND, 0x1B /* Undefined Processing Undefined Instructions Mode */ +.set MODE_SYS, 0x1F /* System Running Priviledged Operating System Tasks Mode */ + +.set I_BIT, 0x80 /* when I bit is set, IRQ is disabled (program status registers) */ +.set F_BIT, 0x40 /* when F bit is set, FIQ is disabled (program status registers) */ + +.text +.arm + +/* Exception vectors and handler addresses. +It is 64 bytes and can be mapped (see documentation 1.4.2). */ +.section .vectors +/* Exception Vectors */ + ldr PC, Reset_Addr /* Reset */ + ldr PC, Undef_Addr /* Undefined Instruction */ + ldr PC, SWI_Addr /* Software Interrupt */ + ldr PC, PAbt_Addr /* Prefetch Abort */ + ldr PC, DAbt_Addr /* Data Abort */ + nop /* Reserved Vector (holds Philips ISP checksum) */ + /* see page 71 of "Insiders Guide to the Philips ARM7-Based Microcontrollers" by Trevor Martin */ +/* ldr PC, [PC,#-0x0120] /* Interrupt Request Interrupt (load from VIC) */ + ldr PC, IRQ_Addr /* Interrupt Request Interrupt (load from VIC) */ + ldr r0, =__fiq_handler /* Fast Interrupt Request Interrupt */ + ldr pc, [r0] /* jump to handler in pointer at __fiq_handler */ + +/* Exception vector handlers branching table */ +Reset_Addr: .word Reset_Handler /* defined in this module below */ +Undef_Addr: .word UNDEF_Routine /* defined in main.c */ +SWI_Addr: .word ctx_switch /* defined in main.c */ +PAbt_Addr: .word PABT_Routine /* defined in main.c */ +DAbt_Addr: .word DABT_Routine /* defined in main.c */ +IRQ_Addr: .word fk_cpu_irq_isr /* defined in main.c */ + +/* Begin of boot code */ +.text +.arm +.section .init + +.global _startup +.func _startup + +_startup: + ldr pc, =Reset_Handler + +/*.func Reset_Handler */ +Reset_Handler: + +.section .init0 + /* Setup a stack for each mode - note that this only sets up a usable stack + for User mode. Also each mode is setup with interrupts initially disabled. */ + ldr r0, = __stack_end + msr CPSR_c, #MODE_UND|I_BIT|F_BIT /* Undefined Instruction Mode */ + ldr sp, =__stack_und_start + msr CPSR_c, #MODE_ABT|I_BIT|F_BIT /* Abort Mode */ + ldr sp, =__stack_abt_start + msr CPSR_c, #MODE_FIQ|I_BIT|F_BIT /* FIQ Mode */ + ldr sp, =__stack_fiq_start + msr CPSR_c, #MODE_IRQ|I_BIT|F_BIT /* IRQ Mode */ + ldr sp, =__stack_irq_start + msr CPSR_c, #MODE_SVC|I_BIT|F_BIT /* Supervisor Mode */ + ldr sp, =__stack_svc_start + msr CPSR_c, #MODE_SYS|I_BIT|F_BIT /* User Mode */ + ldr sp, =__stack_usr_start + +.section .init2 /* copy .data section (Copy from ROM to RAM) */ +.extern _etext +.extern _data +.extern _edata +/* + ldr R1, =_etext + ldr R2, =_data + ldr R3, =_edata +LoopRel: cmp R2, R3 + ldrlo R0, [R1], #4 + strlo R0, [R2], #4 + blo LoopRel +*/ +.section .init4 /* Clear .bss section (Zero init) */ +.extern __bss_start +.extern __bss_end +/* + mov R0, #0 + ldr R1, =__bss_start + ldr R2, =__bss_end +LoopZI: cmp R1, R2 + strlo R0, [R1], #4 + blo LoopZI +*/ + /* Enter the C code */ +.section .init9 + bl bootloader + b kernel_init + + /* Infinite Loop */ +.section .fini0 +__main_exit: B __main_exit + + +.endfunc +.end diff --git a/cpu/lpc2387/tools/openocd-lpc2387.cfg b/cpu/lpc2387/tools/openocd-lpc2387.cfg new file mode 100644 index 0000000000..1d6813b040 --- /dev/null +++ b/cpu/lpc2387/tools/openocd-lpc2387.cfg @@ -0,0 +1,49 @@ + +if { [info exists CHIPNAME] } { + set _CHIPNAME $CHIPNAME +} else { + set _CHIPNAME lpc2378 +} + +if { [info exists ENDIAN] } { + set _ENDIAN $ENDIAN +} else { + set _ENDIAN little +} + +if { [info exists CPUTAPID ] } { + set _CPUTAPID $CPUTAPID +} else { + # force an error till we get a good number + set _CPUTAPID 0xffffffff +} + +#delays on reset lines +jtag_nsrst_delay 200 +jtag_ntrst_delay 200 + +# NOTE!!! LPCs need reset pulled while RTCK is low. 0 to activate +# JTAG, power-on reset is not enough, i.e. you need to perform a +# reset before being able to talk to the LPC2378, attach is not +# possible. + +#use combined on interfaces or targets that can't set TRST/SRST separately +reset_config trst_and_srst srst_pulls_trst + +#jtag scan chain +jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID + +set _TARGETNAME [format "%s.cpu" $_CHIPNAME] +target create $_TARGETNAME arm7tdmi -endian $_ENDIAN -chain-position $_TARGETNAME -variant arm7tdmi-s_r4 +$_TARGETNAME configure -work-area-virt 0 -work-area-phys 0x40000000 -work-area-size 0x10000 -work-area-backup 0 +$_TARGETNAME configure -event reset-init { + # Force target into ARM state + soft_reset_halt + #do not remap 0x0000-0x0020 to anything but the flash + mwb 0xE01FC040 0x01 +} + + +#flash bank lpc2000 0 0 +#flash bank lpc2000 0x0 0x7d000 0 0 0 lpc2000_v2 14765 + diff --git a/cpu/msp430/Jamfile b/cpu/msp430/Jamfile new file mode 100644 index 0000000000..9441b494e9 --- /dev/null +++ b/cpu/msp430/Jamfile @@ -0,0 +1,38 @@ +# ****************************************************************************** +# Copyright 2009, Freie Universitaet Berlin (FUB). All rights reserved. +# +# These sources were developed at the Freie Universitaet Berlin, Computer +# Systems and Telematics group (http://cst.mi.fu-berlin.de). +# ------------------------------------------------------------------------------ +# This file is part of FeuerWare. +# +# This program is free software: you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation, either version 3 of the License, or (at your option) any later +# version. +# +# FeuerWare is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with +# this program. If not, see http://www.gnu.org/licenses/ . +# ------------------------------------------------------------------------------ +# For further information and questions please use the web site +# http://scatterweb.mi.fu-berlin.de +# and the mailinglist (subscription via web site) +# scatterweb@lists.spline.inf.fu-berlin.de +# ****************************************************************************** +# $Id$ + +SubDir TOP cpu msp430 ; + +Module cpu : msp430-main.c cpu.c atomic.c irq.c ; +Module hwtimer_cpu : hwtimer_cpu.c ; + +UseModule cpu ; +UseModule oneway_malloc ; + +Object startup.o : startup.c ; +DEPENDS $(TARGET) : startup.o ; + diff --git a/cpu/msp430/Jamrules.msp430 b/cpu/msp430/Jamrules.msp430 new file mode 100644 index 0000000000..74d65de844 --- /dev/null +++ b/cpu/msp430/Jamrules.msp430 @@ -0,0 +1,39 @@ +# +## msp430 based MCU Jamrules file +# + +echo "Building for board $(BOARD)." ; +echo "Building for MCU $(MCU)." ; + +HDRS += $(TOP)/cpu/$(CPU)/include $(TOP)/board/$(BOARD)/drivers $(TOP)/board/$(BOARD)/include $(TOP)/include $(TOP)/core/include ; + +TOOLCHAIN = msp430- ; +CC = msp430-gcc ; +LINK = msp430-gcc ; +OPTIM = -Os -gdwarf-2 ; +#OPTIM = -O0 -g ; +#OPTIM = -O2 ; +CCFLAGS += -std=gnu99 -Wall -mmcu=$(MCU) ; +LINKFLAGS = -mmcu=$(MCU) -lgcc $(TOP)/bin/$(BOARD)/$(PROJECT)/startup.o ; + +AS = msp430-as ; +ASFLAGS += -mmcu=$(MCU) --defsym $(CPU)=1 --gdwarf-2 ; + +AR = msp430-ar ; +ARFLAGS = -rc ; + +GDB = msp430-gdb ; +GDBFLAGS = -x $(TOP)/board/$(BOARD)/tools/gdbscript ; + +OBJCOPY = msp430-objcopy ; + +FLASHER ?= echo ; +FLASHFLAGS ?= "No flasher defined." ; + +RESET ?= $(FLASHER) $(FLASHFLAGS) reset ; + +# overwrite flash action in order to support mspdebug +actions Flash +{ + $(FLASHER) $(FLASHFLAGS) "prog $(>)" +} diff --git a/cpu/msp430/atomic.c b/cpu/msp430/atomic.c new file mode 100644 index 0000000000..59b7ed5d7e --- /dev/null +++ b/cpu/msp430/atomic.c @@ -0,0 +1,10 @@ +#include +#include + +unsigned int atomic_set_return(unsigned int* val, unsigned int set) { + dINT(); + unsigned int old_val = *val; + *val = set; + eINT(); + return old_val; +} diff --git a/cpu/msp430/cpu.c b/cpu/msp430/cpu.c new file mode 100644 index 0000000000..1ea79aa337 --- /dev/null +++ b/cpu/msp430/cpu.c @@ -0,0 +1,128 @@ +/****************************************************************************** +Copyright 2009, Freie Universitaet Berlin (FUB). All rights reserved. + +These sources were developed at the Freie Universitaet Berlin, Computer Systems +and Telematics group (http://cst.mi.fu-berlin.de). +------------------------------------------------------------------------------- +This file is part of FeuerWare. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +FeuerWare is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see http://www.gnu.org/licenses/ . +-------------------------------------------------------------------------------- +For further information and questions please use the web site + http://scatterweb.mi.fu-berlin.de +and the mailinglist (subscription via web site) + scatterweb@lists.spline.inf.fu-berlin.de +*******************************************************************************/ + +#include "cpu.h" +#include +#include "kernel.h" +#include "kernel_intern.h" +#include "scheduler.h" + +volatile int __inISR = 0; + +char __isr_stack[MSP430_ISR_STACK_SIZE]; + +void fk_yield() { + __save_context(); + + dINT(); + /* have fk_thread point to the next thread */ + fk_schedule(); + eINT(); + + __restore_context(); +} + +// static void __resume_context () { +// __asm__("mov.w %0,r1" : : "m" (fk_thread->sp)); +// +// __asm__("pop r15"); +// __asm__("pop r14"); +// __asm__("pop r13"); +// __asm__("pop r12"); +// __asm__("pop r11"); +// __asm__("pop r10"); +// __asm__("pop r9"); +// __asm__("pop r8"); +// __asm__("pop r7"); +// __asm__("pop r6"); +// __asm__("pop r5"); +// __asm__("pop r4"); +// } + + +// static void __resume_ +// +// } +// +// void __save_context_isr () { +// __asm__("push r4"); +// __asm__("push r5"); +// __asm__("push r6"); +// __asm__("push r7"); +// __asm__("push r8"); +// __asm__("push r9"); +// __asm__("push r10"); +// __asm__("push r11"); +// __asm__("push r12"); +// __asm__("push r13"); +// __asm__("push r14"); +// __asm__("push r15"); +// +// __asm__("mov.w r1,%0" : "=r" (fk_thread->sp)); +// } +// +// +// __return_from_isr + +void fk_switch_context_exit(){ + fk_thread = fk_threads[0]; + fk_schedule(); + + __restore_context(); +} + +//---------------------------------------------------------------------------- +// Processor specific routine - here for MSP +//---------------------------------------------------------------------------- +char *fk_stack_init(void *task_func, void *stack_start) +{ + unsigned short * stk; + stk = (unsigned short *) stack_start; + + *stk = (unsigned short) fk_task_exit; + --stk; + + *stk = (unsigned short) task_func; + --stk; + + /* initial value for SR */ +// unsigned int sr; +// __asm__("mov.w r2,%0" : "=r" (sr)); + + *stk = GIE; + --stk; + + /* Space for registers. */ + for (unsigned int i = 15; i > 4; i--) { + *stk = i; + --stk; + } + //stk -= 11; + + return (char*) stk; +} + +int inISR() { return __inISR; } diff --git a/cpu/msp430/hwtimer_cpu.c b/cpu/msp430/hwtimer_cpu.c new file mode 100644 index 0000000000..e25fd799e7 --- /dev/null +++ b/cpu/msp430/hwtimer_cpu.c @@ -0,0 +1,151 @@ +/****************************************************************************** +Copyright 2009, Freie Universitaet Berlin (FUB). All rights reserved. + +These sources were developed at the Freie Universitaet Berlin, Computer Systems +and Telematics group (http://cst.mi.fu-berlin.de). +------------------------------------------------------------------------------- +This file is part of FeuerWare. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +FeuerWare is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see http://www.gnu.org/licenses/ . +-------------------------------------------------------------------------------- +For further information and questions please use the web site + http://scatterweb.mi.fu-berlin.de +and the mailinglist (subscription via web site) + scatterweb@lists.spline.inf.fu-berlin.de +*******************************************************************************/ + +#include + +#include +#include +#include +#include + +#include "debug.h" + +static uint32_t ticks = 0; + +static void (*int_handler)(int); + +static void timerA_init() +{ + ticks = 0; // Set tick counter value to 0 + TA0CTL = TASSEL_1 + TACLR; // Clear the timer counter, set SMCLK + TA0CTL &= ~TAIFG; // Clear the IFG + TA0CTL &= ~TAIE; // Clear the IFG + + volatile unsigned int *ccr = &TA0CCR0; + volatile unsigned int *ctl = &TA0CCTL0; + + for (int i = 0; i < ARCH_MAXTIMERS; i++) { + *ccr = 0; + *ctl &= ~(CCIFG); + *ctl &= ~(CCIE); + } + + TA0CTL |= MC_2; +} + + +static void TA0_disable_interrupt(short timer) { + volatile unsigned int *ptr = &TA0CCTL0 + (timer); + *ptr &= ~(CCIFG); + *ptr &= ~(CCIE); +} + +static void TA0_enable_interrupt(short timer) { + volatile unsigned int *ptr = &TA0CCTL0 + (timer); + *ptr |= CCIE; + *ptr &= ~(CCIFG); +} + +static void TA0_set_nostart(unsigned long value, short timer) { + volatile unsigned int *ptr = &TA0CCR0 + (timer); + *ptr = value; +} + +static void TA0_set(unsigned long value, short timer) { +// printf("Setting timer %u to %lu\n", timer, value); + TA0_set_nostart(value, timer); + TA0_enable_interrupt(timer); +} + +static void TA0_unset(short timer) { + volatile unsigned int *ptr = &TA0CCR0 + (timer); + TA0_disable_interrupt(timer); + *ptr = 0; +} + +unsigned long hwtimer_arch_now() { + return TA0R; +} + +void hwtimer_arch_init(void (*handler)(int), uint32_t fcpu) { + timerA_init(); + int_handler = handler; +} + +void hwtimer_arch_enable_interrupt(void) { + for (int i = 0; i < ARCH_MAXTIMERS; i++) { + TA0_enable_interrupt(i); + } +} + +void hwtimer_arch_disable_interrupt(void) { + for (int i = 0; i < ARCH_MAXTIMERS; i++) { + TA0_disable_interrupt(i); + } +} + +void hwtimer_arch_set(unsigned long offset, short timer) { + unsigned int value = hwtimer_arch_now() + offset; + hwtimer_arch_set_absolute(value, timer); +} + +void hwtimer_arch_set_absolute(unsigned long value, short timer) { + TA0_set(value,timer); +} + +void hwtimer_arch_unset(short timer) { + TA0_unset(timer); +} + +interrupt(TIMERA0_VECTOR) __attribute__ ((naked)) timer_isr_ccr0(void) +{ + __enter_isr(); + + TA0_unset(0); + int_handler(0); + + __exit_isr(); +} + +interrupt(TIMERA1_VECTOR) __attribute__ ((naked)) timer_isr(void) +{ + __enter_isr(); + + short taiv = TA0IV; + + if (taiv & TAIFG) { + puts("msp430/hwtimer_cpu TAIFG set!"); + // TA0CTL &= ~TAIFG; + // ticks += 0xFFFF; + } else { + + short timer = (taiv/2); + TA0_unset(timer); + int_handler(timer); + } + + __exit_isr(); +} diff --git a/cpu/msp430/include/cpu-conf.h b/cpu/msp430/include/cpu-conf.h new file mode 100644 index 0000000000..62958016e5 --- /dev/null +++ b/cpu/msp430/include/cpu-conf.h @@ -0,0 +1,42 @@ +/****************************************************************************** +Copyright 2009, Freie Universitaet Berlin (FUB). All rights reserved. + +These sources were developed at the Freie Universitaet Berlin, Computer Systems +and Telematics group (http://cst.mi.fu-berlin.de). +------------------------------------------------------------------------------- +This file is part of FeuerWare. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +FeuerWare is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see http://www.gnu.org/licenses/ . +-------------------------------------------------------------------------------- +For further information and questions please use the web site + http://scatterweb.mi.fu-berlin.de +and the mailinglist (subscription via web site) + scatterweb@lists.spline.inf.fu-berlin.de +*******************************************************************************/ + +#ifndef CPUCONF_H_ +#define CPUCONF_H_ + +/** + * @name Kernel configuration + * @{ + */ +#ifndef KERNEL_CONF_STACKSIZE_DEFAULT +#define KERNEL_CONF_STACKSIZE_DEFAULT 1024 +#endif + +#define KERNEL_CONF_STACKSIZE_IDLE 64 +#define MSP430_ISR_STACK_SIZE 256 +/** @} */ + +#endif /* CPUCONF_H_ */ diff --git a/cpu/msp430/include/cpu.h b/cpu/msp430/include/cpu.h new file mode 100644 index 0000000000..7a920aa053 --- /dev/null +++ b/cpu/msp430/include/cpu.h @@ -0,0 +1,131 @@ +/****************************************************************************** +Copyright 2009, Freie Universitaet Berlin (FUB). All rights reserved. + +These sources were developed at the Freie Universitaet Berlin, Computer Systems +and Telematics group (http://cst.mi.fu-berlin.de). +------------------------------------------------------------------------------- +This file is part of FeuerWare. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +FeuerWare is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see http://www.gnu.org/licenses/ . +-------------------------------------------------------------------------------- +For further information and questions please use the web site + http://scatterweb.mi.fu-berlin.de +and the mailinglist (subscription via web site) + scatterweb@lists.spline.inf.fu-berlin.de +*******************************************************************************/ + +#ifndef _CPU_H +#define _CPU_H + +/** + * @defgroup msp430 TI MSP430 + * @ingroup cpu + +

First steps

+\li See the manual for toolchain and ide setup + + * @{ + */ + +#include +#include +#include +#include + +#define WORDSIZE 16 + +#define F_CPU 10000000 + +extern volatile int __inISR; +extern char __isr_stack[MSP430_ISR_STACK_SIZE]; + +//#define eINT() eint() +//#define dINT() dint() + +inline void __save_context_isr() { + __asm__("push r15"); + __asm__("push r14"); + __asm__("push r13"); + __asm__("push r12"); + __asm__("push r11"); + __asm__("push r10"); + __asm__("push r9"); + __asm__("push r8"); + __asm__("push r7"); + __asm__("push r6"); + __asm__("push r5"); + __asm__("push r4"); + + __asm__("mov.w r1,%0" : "=r" (fk_thread->sp)); +} + +inline void __restore_context_isr() { + __asm__("mov.w %0,r1" : : "m" (fk_thread->sp)); + + __asm__("pop r4"); + __asm__("pop r5"); + __asm__("pop r6"); + __asm__("pop r7"); + __asm__("pop r8"); + __asm__("pop r9"); + __asm__("pop r10"); + __asm__("pop r11"); + __asm__("pop r12"); + __asm__("pop r13"); + __asm__("pop r14"); + __asm__("pop r15"); +} + +inline void __enter_isr() { + __save_context_isr(); + __asm__("mov.w %0,r1" : : "i" (__isr_stack+MSP430_ISR_STACK_SIZE)); + __inISR = 1; +} + +inline void __exit_isr() { + __inISR = 0; + if (fk_context_switch_request) fk_schedule(); + __restore_context_isr(); + __asm__("reti"); +} + +inline void __save_context() { + __asm__("push r2"); /* save SR */ + __save_context_isr(); +} + +inline void __restore_context() { + __restore_context_isr(); + __asm__("reti"); +} + +inline void eINT() { +// puts("+"); + eint(); +} + +inline void dINT() { +// puts("-"); + dint(); +} + +#define lpm_set(...) + +void fk_yield(); + + +int inISR(); + +/** @} */ +#endif // _CPU_H + diff --git a/cpu/msp430/include/errno-base.h b/cpu/msp430/include/errno-base.h new file mode 100644 index 0000000000..6511597851 --- /dev/null +++ b/cpu/msp430/include/errno-base.h @@ -0,0 +1,39 @@ +#ifndef _ASM_GENERIC_ERRNO_BASE_H +#define _ASM_GENERIC_ERRNO_BASE_H + +#define EPERM 1 /* Operation not permitted */ +#define ENOENT 2 /* No such file or directory */ +#define ESRCH 3 /* No such process */ +#define EINTR 4 /* Interrupted system call */ +#define EIO 5 /* I/O error */ +#define ENXIO 6 /* No such device or address */ +#define E2BIG 7 /* Argument list too long */ +#define ENOEXEC 8 /* Exec format error */ +#define EBADF 9 /* Bad file number */ +#define ECHILD 10 /* No child processes */ +#define EAGAIN 11 /* Try again */ +#define ENOMEM 12 /* Out of memory */ +#define EACCES 13 /* Permission denied */ +#define EFAULT 14 /* Bad address */ +#define ENOTBLK 15 /* Block device required */ +#define EBUSY 16 /* Device or resource busy */ +#define EEXIST 17 /* File exists */ +#define EXDEV 18 /* Cross-device link */ +#define ENODEV 19 /* No such device */ +#define ENOTDIR 20 /* Not a directory */ +#define EISDIR 21 /* Is a directory */ +#define EINVAL 22 /* Invalid argument */ +#define ENFILE 23 /* File table overflow */ +#define EMFILE 24 /* Too many open files */ +#define ENOTTY 25 /* Not a typewriter */ +#define ETXTBSY 26 /* Text file busy */ +#define EFBIG 27 /* File too large */ +#define ENOSPC 28 /* No space left on device */ +#define ESPIPE 29 /* Illegal seek */ +#define EROFS 30 /* Read-only file system */ +#define EMLINK 31 /* Too many links */ +#define EPIPE 32 /* Broken pipe */ +#define EDOM 33 /* Math argument out of domain of func */ +#define ERANGE 34 /* Math result not representable */ + +#endif diff --git a/cpu/msp430/include/errno.h b/cpu/msp430/include/errno.h new file mode 100644 index 0000000000..be764a8973 --- /dev/null +++ b/cpu/msp430/include/errno.h @@ -0,0 +1,109 @@ +#ifndef _ASM_GENERIC_ERRNO_H +#define _ASM_GENERIC_ERRNO_H + +#include + +#define EDEADLK 35 /* Resource deadlock would occur */ +#define ENAMETOOLONG 36 /* File name too long */ +#define ENOLCK 37 /* No record locks available */ +#define ENOSYS 38 /* Function not implemented */ +#define ENOTEMPTY 39 /* Directory not empty */ +#define ELOOP 40 /* Too many symbolic links encountered */ +#define EWOULDBLOCK EAGAIN /* Operation would block */ +#define ENOMSG 42 /* No message of desired type */ +#define EIDRM 43 /* Identifier removed */ +#define ECHRNG 44 /* Channel number out of range */ +#define EL2NSYNC 45 /* Level 2 not synchronized */ +#define EL3HLT 46 /* Level 3 halted */ +#define EL3RST 47 /* Level 3 reset */ +#define ELNRNG 48 /* Link number out of range */ +#define EUNATCH 49 /* Protocol driver not attached */ +#define ENOCSI 50 /* No CSI structure available */ +#define EL2HLT 51 /* Level 2 halted */ +#define EBADE 52 /* Invalid exchange */ +#define EBADR 53 /* Invalid request descriptor */ +#define EXFULL 54 /* Exchange full */ +#define ENOANO 55 /* No anode */ +#define EBADRQC 56 /* Invalid request code */ +#define EBADSLT 57 /* Invalid slot */ + +#define EDEADLOCK EDEADLK + +#define EBFONT 59 /* Bad font file format */ +#define ENOSTR 60 /* Device not a stream */ +#define ENODATA 61 /* No data available */ +#define ETIME 62 /* Timer expired */ +#define ENOSR 63 /* Out of streams resources */ +#define ENONET 64 /* Machine is not on the network */ +#define ENOPKG 65 /* Package not installed */ +#define EREMOTE 66 /* Object is remote */ +#define ENOLINK 67 /* Link has been severed */ +#define EADV 68 /* Advertise error */ +#define ESRMNT 69 /* Srmount error */ +#define ECOMM 70 /* Communication error on send */ +#define EPROTO 71 /* Protocol error */ +#define EMULTIHOP 72 /* Multihop attempted */ +#define EDOTDOT 73 /* RFS specific error */ +#define EBADMSG 74 /* Not a data message */ +#define EOVERFLOW 75 /* Value too large for defined data type */ +#define ENOTUNIQ 76 /* Name not unique on network */ +#define EBADFD 77 /* File descriptor in bad state */ +#define EREMCHG 78 /* Remote address changed */ +#define ELIBACC 79 /* Can not access a needed shared library */ +#define ELIBBAD 80 /* Accessing a corrupted shared library */ +#define ELIBSCN 81 /* .lib section in a.out corrupted */ +#define ELIBMAX 82 /* Attempting to link in too many shared libraries */ +#define ELIBEXEC 83 /* Cannot exec a shared library directly */ +#define EILSEQ 84 /* Illegal byte sequence */ +#define ERESTART 85 /* Interrupted system call should be restarted */ +#define ESTRPIPE 86 /* Streams pipe error */ +#define EUSERS 87 /* Too many users */ +#define ENOTSOCK 88 /* Socket operation on non-socket */ +#define EDESTADDRREQ 89 /* Destination address required */ +#define EMSGSIZE 90 /* Message too long */ +#define EPROTOTYPE 91 /* Protocol wrong type for socket */ +#define ENOPROTOOPT 92 /* Protocol not available */ +#define EPROTONOSUPPORT 93 /* Protocol not supported */ +#define ESOCKTNOSUPPORT 94 /* Socket type not supported */ +#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ +#define EPFNOSUPPORT 96 /* Protocol family not supported */ +#define EAFNOSUPPORT 97 /* Address family not supported by protocol */ +#define EADDRINUSE 98 /* Address already in use */ +#define EADDRNOTAVAIL 99 /* Cannot assign requested address */ +#define ENETDOWN 100 /* Network is down */ +#define ENETUNREACH 101 /* Network is unreachable */ +#define ENETRESET 102 /* Network dropped connection because of reset */ +#define ECONNABORTED 103 /* Software caused connection abort */ +#define ECONNRESET 104 /* Connection reset by peer */ +#define ENOBUFS 105 /* No buffer space available */ +#define EISCONN 106 /* Transport endpoint is already connected */ +#define ENOTCONN 107 /* Transport endpoint is not connected */ +#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */ +#define ETOOMANYREFS 109 /* Too many references: cannot splice */ +#define ETIMEDOUT 110 /* Connection timed out */ +#define ECONNREFUSED 111 /* Connection refused */ +#define EHOSTDOWN 112 /* Host is down */ +#define EHOSTUNREACH 113 /* No route to host */ +#define EALREADY 114 /* Operation already in progress */ +#define EINPROGRESS 115 /* Operation now in progress */ +#define ESTALE 116 /* Stale NFS file handle */ +#define EUCLEAN 117 /* Structure needs cleaning */ +#define ENOTNAM 118 /* Not a XENIX named type file */ +#define ENAVAIL 119 /* No XENIX semaphores available */ +#define EISNAM 120 /* Is a named type file */ +#define EREMOTEIO 121 /* Remote I/O error */ +#define EDQUOT 122 /* Quota exceeded */ + +#define ENOMEDIUM 123 /* No medium found */ +#define EMEDIUMTYPE 124 /* Wrong medium type */ +#define ECANCELED 125 /* Operation Canceled */ +#define ENOKEY 126 /* Required key not available */ +#define EKEYEXPIRED 127 /* Key has expired */ +#define EKEYREVOKED 128 /* Key has been revoked */ +#define EKEYREJECTED 129 /* Key was rejected by service */ + +/* for robust mutexes */ +#define EOWNERDEAD 130 /* Owner died */ +#define ENOTRECOVERABLE 131 /* State not recoverable */ + +#endif diff --git a/cpu/msp430/include/hwtimer_cpu.h b/cpu/msp430/include/hwtimer_cpu.h new file mode 100644 index 0000000000..1d014640c3 --- /dev/null +++ b/cpu/msp430/include/hwtimer_cpu.h @@ -0,0 +1,52 @@ +/****************************************************************************** +Copyright 2009, Freie Universitaet Berlin (FUB). All rights reserved. + +These sources were developed at the Freie Universitaet Berlin, Computer Systems +and Telematics group (http://cst.mi.fu-berlin.de). +------------------------------------------------------------------------------- +This file is part of FeuerWare. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +FeuerWare is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see http://www.gnu.org/licenses/ . +-------------------------------------------------------------------------------- +For further information and questions please use the web site + http://scatterweb.mi.fu-berlin.de +and the mailinglist (subscription via web site) + scatterweb@lists.spline.inf.fu-berlin.de +*******************************************************************************/ + +#ifndef __HWTIMER_CPU_H +#define __HWTIMER_CPU_H + +#include +#include + +#ifdef __MSP430_HAS_TA2__ +#define ARCH_MAXTIMERS 2 +#endif +#ifdef __MSP430_HAS_TA3__ +#define ARCH_MAXTIMERS 3 +#endif +/*#ifdef __MSP430_HAS_TA5__ +#define ARCH_MAXTIMERS 5 +#endif +*/ + +#ifndef ARCH_MAXTIMERS +#warning "ARCH_MAXTIMERS UNSET!" +#define ARCH_MAXTIMERS 0 +#endif + +#define HWTIMER_SPEED 32768 +#define HWTIMER_MAXTICKS (0xFFFF) + +#endif // __HWTIMER_CPU_H diff --git a/cpu/msp430/include/malloc.h b/cpu/msp430/include/malloc.h new file mode 100644 index 0000000000..faddc99715 --- /dev/null +++ b/cpu/msp430/include/malloc.h @@ -0,0 +1,9 @@ +#ifndef __MALLOC_H +#define __MALLOC_H + +#include "oneway_malloc.h" + +#define malloc _malloc +#define free _free + +#endif /* __MALLOC_H */ diff --git a/cpu/msp430/include/msp430.h b/cpu/msp430/include/msp430.h new file mode 100644 index 0000000000..ef8f7ee0e1 --- /dev/null +++ b/cpu/msp430/include/msp430.h @@ -0,0 +1,106 @@ +/* + * 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$ + */ + +#ifndef __MSP430_H__ +#define __MSP430_H__ + +/** + * @ingroup msp430 + * @{ + */ + +/** + * \file + * MSP430 definitions + * \author + * Adam Dunkels + * Modified by Kaspar Schleiser + */ + +#include +#include + +#include "board.h" + +#ifndef MSP430_INITIAL_CPU_SPEED +#define MSP430_INITIAL_CPU_SPEED 2457600uL +#warning MSP430_INITIAL_CPU_SPEED undefined. MSP430 initial dco speed set to 2.457600 MHz. +#endif + +#ifndef MSP430_HAS_DCOR +#define MSP430_HAS_DCOR 0 +#endif + +#ifndef MSP430_HAS_EXTERNAL_CRYSTAL +#define MSP430_HAS_EXTERNAL_CRYSTAL 0 +#endif + +#define HAVE_STDINT_H + +#define CC_CONF_REGISTER_ARGS 1 +#define CC_CONF_FUNCTION_POINTER_ARGS 1 +#define CC_CONF_INLINE inline +#define CC_CONF_VA_ARGS 1 +//#define CC_CONF_USED // is ignored my mspgcc +#define CC_CONF_NONNULL(...) __attribute__((nonnull(__VA_ARGS__))) +#define CC_CONF_WARN_UNUSED_RESULT __attribute__((warn_unused_result)) + +#if (MSP430_INITIAL_CPU_SPEED > 5000000) && (MSP430_HAS_DCOR != 1) || (MSP430_INITIAL_CPU_SPEED > 10000000) && (MSP430_HAS_DCOR == 1) +#warning MSP430_INITIAL_CPU_SPEED too high +#endif + +extern volatile uint32_t cpu_speed; +#define RTIMER_ARCH_SECOND (32767 / 4) ///< frequency of the rtimer +#define CLOCK_CONF_SECOND (32767 / 8) ///< frequency of the software timers + +void msp430_set_cpu_speed(uint32_t speed); + +void msp430_cpu_init(void); /* Rename to cpu_init() later! */ +#define cpu_init() msp430_cpu_init() + +void msp430_init_dco(); + +void *sbrk(int); + +typedef int spl_t; +void splx_(spl_t); +spl_t splhigh_(void); + +#define splhigh() splhigh_() +#define splx(sr) __asm__ __volatile__("bis %0, r2" : : "r" (sr)) + +void msp430_set_cpu_speed(uint32_t speed); +void msp430_cpu_init(void); + +/** @} */ +#endif /* __MSP430_H__ */ diff --git a/cpu/msp430/irq.c b/cpu/msp430/irq.c new file mode 100644 index 0000000000..8c1d328b8a --- /dev/null +++ b/cpu/msp430/irq.c @@ -0,0 +1,24 @@ +#include +#include +#include + +unsigned int disableIRQ() { + unsigned int state; + __asm__("mov.w r2,%0" : "=r" (state)); + state &= GIE; + if (state) dINT(); + return state; +} + +unsigned int enableIRQ() { + unsigned int state; + __asm__("mov.w r2,%0" : "=r" (state)); + state &= GIE; + if (!state) eINT(); + return state; +} + +void restoreIRQ(unsigned int state) { + if (state) eINT(); +} + diff --git a/cpu/msp430/msp430-main.c b/cpu/msp430/msp430-main.c new file mode 100644 index 0000000000..0a5dc88051 --- /dev/null +++ b/cpu/msp430/msp430-main.c @@ -0,0 +1,172 @@ +/* + * 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. + * + * @(#)$Id$ + * + * Modified by Kaspar Schleiser + */ +#include + +#include "cpu.h" +#include "board.h" +#include "msp430.h" + + +/*---------------------------------------------------------------------------*/ +static void +init_ports(void) +{ + /* Turn everything off, device drivers enable what is needed. */ + + /* All configured for digital I/O */ +#ifdef P1SEL + P1SEL = 0; +#endif +#ifdef P2SEL + P2SEL = 0; +#endif +#ifdef P3SEL + P3SEL = 0; +#endif +#ifdef P4SEL + P4SEL = 0; +#endif +#ifdef P5SEL + P5SEL = 0; +#endif +#ifdef P6SEL + P6SEL = 0; +#endif + + /* All available inputs */ +#ifdef P1DIR + P1DIR = 0; + P1OUT = 0; +#endif +#ifdef P2DIR + P2DIR = 0; + P2OUT = 0; +#endif +#ifdef P3DIR + P3DIR = 0; + P3OUT = 0; +#endif +#ifdef P4DIR + P4DIR = 0; + P4OUT = 0; +#endif + +#ifdef P5DIR + P5DIR = 0; + P5OUT = 0; +#endif + +#ifdef P6DIR + P6DIR = 0; + P6OUT = 0; +#endif + + P1IE = 0; + P2IE = 0; +} + +/*---------------------------------------------------------------------------*/ +/* msp430-ld may align _end incorrectly. Workaround in cpu_init. */ +extern int _end; /* Not in sys/unistd.h */ +static char *cur_break = (char *)&_end; + +void +msp430_cpu_init(void) +{ + dint(); + init_ports(); +// lpm_init(); + eint(); + + if((uintptr_t)cur_break & 1) { /* Workaround for msp430-ld bug! */ + cur_break++; + } +} +/*---------------------------------------------------------------------------*/ +#define asmv(arg) __asm__ __volatile__(arg) + +#define STACK_EXTRA 32 + + +/* + * Allocate memory from the heap. Check that we don't collide with the + * stack right now (some other routine might later). A watchdog might + * be used to check if cur_break and the stack pointer meet during + * runtime. + */ +void *sbrk(int incr) +{ + char *stack_pointer; + + asmv("mov r1, %0" : "=r" (stack_pointer)); + stack_pointer -= STACK_EXTRA; + if(incr > (stack_pointer - cur_break)) + return (void *)-1; /* ENOMEM */ + + void *old_break = cur_break; + cur_break += incr; + /* + * If the stack was never here then [old_break .. cur_break] should + * be filled with zeros. + */ + return old_break; +} +/*---------------------------------------------------------------------------*/ +/* + * Mask all interrupts that can be masked. + */ +int +splhigh_(void) +{ + /* Clear the GIE (General Interrupt Enable) flag. */ + int sr; + asmv("mov r2, %0" : "=r" (sr)); + asmv("bic %0, r2" : : "i" (GIE)); + return sr & GIE; /* Ignore other sr bits. */ +} +/*---------------------------------------------------------------------------*/ +/* + * Restore previous interrupt mask. + */ +void +splx_(int sr) +{ + /* If GIE was set, restore it. */ + asmv("bis %0, r2" : : "r" (sr)); +} +/*---------------------------------------------------------------------------*/ + +extern void board_init(); + diff --git a/cpu/msp430/startup.c b/cpu/msp430/startup.c new file mode 100644 index 0000000000..d4a3219135 --- /dev/null +++ b/cpu/msp430/startup.c @@ -0,0 +1,16 @@ +#include +#include "board.h" +#include "kernel_intern.h" + +extern void board_init(); + +__attribute__ ((constructor)) static void startup() { + /* use putchar so the linker links it in: */ + putchar('\n'); + + board_init(); + + puts("FireKernel MSP430 hardware initialization complete.\n"); + + kernel_init(); +} diff --git a/doc/doxygen/src/ukleos-footer.html b/doc/doxygen/src/ukleos-footer.html new file mode 100644 index 0000000000..73e46b97fe --- /dev/null +++ b/doc/doxygen/src/ukleos-footer.html @@ -0,0 +1,2 @@ + + diff --git a/doc/doxygen/src/ukleos-header.html b/doc/doxygen/src/ukleos-header.html new file mode 100644 index 0000000000..0f98f639d4 --- /dev/null +++ b/doc/doxygen/src/ukleos-header.html @@ -0,0 +1,11 @@ + + + + + + $title + + + + + diff --git a/doc/doxygen/src/ukleos.css b/doc/doxygen/src/ukleos.css new file mode 100644 index 0000000000..8d82f8bbb6 --- /dev/null +++ b/doc/doxygen/src/ukleos.css @@ -0,0 +1,409 @@ +BODY,H1,H2,H3,H4,H5,H6,P,CENTER,TD,TH,UL,DL,DIV { + font-family: Verdana, Arial, Helvetica, sans-serif; +} +BODY,TD { + font-size: 90%; +} +h1 { /* titel */ + text-align: left; + font-size: 140%; + background-color: #aabbbd; /*#f4f4f4; */ + padding: 0.3em 0.3 0em 0.3em; + height: 80px; + margin-top: 0; +} +h1, +h1 a, h1 a:visited { + color: #0e393f; + text-decoration: none; +} +h2 { /* section */ + font-size: 120%; +} +td h2 { /* member table captions */ + background-color: #f0f0f0; + padding: 0.1em 0 0.1em 0; +} +h3 { /* subsection */ + font-size: 100%; +} +div.agtlogo { + float: left; + position: relative; + /*bottom: 80.5em;*/ +} +div.footer { /* footer */ + font-size: x-small; + color: #333333; +} +CAPTION { font-weight: bold } +DIV.qindex { + width: 100%; + background-color: #e8eef2; + border: 1px solid #84b0c7; + text-align: center; + margin: 2px; + padding: 2px; + line-height: 140%; +} +DIV.nav { + width: 100%; + background-color: #e8eef2; + border: 1px solid #84b0c7; + text-align: center; + margin: 2px; + padding: 2px; + line-height: 140%; +} +DIV.navtab { + background-color: #e8eef2; + border: 1px solid #84b0c7; + text-align: center; + margin: 2px; + margin-right: 15px; + padding: 2px; +} +TD.navtab { + font-size: 70%; +} +a { + color: #99CC00; +} +a:visited { + color: #003366; +} +A.qindex { + text-decoration: none; + font-weight: bold; + color: #1A419D; +} +A.qindex:visited { + text-decoration: none; + font-weight: bold; + color: #1A419D +} +A.qindex:hover { + text-decoration: none; + background-color: #ddddff; +} +A.qindexHL { + text-decoration: none; + font-weight: bold; + background-color: #6666cc; + color: #ffffff; + border: 1px double #9295C2; +} +A.qindexHL:hover { + text-decoration: none; + background-color: #6666cc; + color: #ffffff; +} +A.qindexHL:visited { text-decoration: none; background-color: #6666cc; color: #ffffff } +A.el { text-decoration: none; font-weight: bold } +A.elRef { font-weight: bold } +A.code:link { text-decoration: none; font-weight: normal; color: #0000FF} +A.code:visited { text-decoration: none; font-weight: normal; color: #0000FF} +A.codeRef:link { font-weight: normal; color: #0000FF} +A.codeRef:visited { font-weight: normal; color: #0000FF} +A:hover { text-decoration: none; background-color: #ffd9b3 } +DL.el { margin-left: -1cm } +.fragment { + font-family: monospace, fixed; + font-size: 95%; +} +PRE.fragment { + border: 1px solid #CCCCCC; + background-color: #f5f5f5; + margin-top: 4px; + margin-bottom: 4px; + margin-left: 2px; + margin-right: 8px; + padding-left: 6px; + padding-right: 6px; + padding-top: 4px; + padding-bottom: 4px; +} +DIV.ah { background-color: black; font-weight: bold; color: #ffffff; margin-bottom: 3px; margin-top: 3px } + +DIV.groupHeader { + margin-left: 16px; + margin-top: 12px; + margin-bottom: 6px; + font-weight: bold; +} +DIV.groupText { margin-left: 16px; font-style: italic; font-size: 90% } +BODY { + background: white; + color: black; + margin-right: 20px; + margin-left: 20px; +} +table.styled { + border: 1px solid #d1d1d1; + border-spacing: 0; + border-collapse: collapse; +} +table.styled td, table.styled th { + background: transparent; + border: 1px solid #d1d1d1; +} +table.styled th { + background-color: #f4f4f4; + font-weight: bold; + text-align: left; +} +table.styled td { + text-align: left; + vertical-align: top; +} +TD.indexkey { + background-color: #e8eef2; + font-weight: bold; + padding-right : 10px; + padding-top : 2px; + padding-left : 10px; + padding-bottom : 2px; + margin-left : 0px; + margin-right : 0px; + margin-top : 2px; + margin-bottom : 2px; + border: 1px solid #CCCCCC; +} +TD.indexvalue { + background-color: #e8eef2; + font-style: italic; + padding-right : 10px; + padding-top : 2px; + padding-left : 10px; + padding-bottom : 2px; + margin-left : 0px; + margin-right : 0px; + margin-top : 2px; + margin-bottom : 2px; + border: 1px solid #CCCCCC; +} +TR.memlist { + background-color: #f0f0f0; +} +P.formulaDsp { text-align: center; } +IMG.formulaDsp { } +IMG.formulaInl { vertical-align: middle; } +SPAN.keyword { color: #008000 } +SPAN.keywordtype { color: #604020 } +SPAN.keywordflow { color: #e08000 } +SPAN.comment { color: #800000 } +SPAN.preprocessor { color: #806020 } +SPAN.stringliteral { color: #002080 } +SPAN.charliteral { color: #008080 } +.mdescLeft { + padding: 0px 8px 4px 8px; + font-size: 80%; + font-style: italic; + background-color: #FAFAFA; + border-top: 1px none #E0E0E0; + border-right: 1px none #E0E0E0; + border-bottom: 1px none #E0E0E0; + border-left: 1px none #E0E0E0; + margin: 0px; +} +.mdescRight { + padding: 0px 8px 4px 8px; + font-size: 80%; + font-style: italic; + background-color: #FAFAFA; + border-top: 1px none #E0E0E0; + border-right: 1px none #E0E0E0; + border-bottom: 1px none #E0E0E0; + border-left: 1px none #E0E0E0; + margin: 0px; +} +.memItemLeft { + padding: 1px 0px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: solid; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + background-color: #FAFAFA; + font-size: 80%; +} +.memItemRight { + padding: 1px 8px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: solid; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + background-color: #FAFAFA; + font-size: 80%; +} +.memTemplItemLeft { + padding: 1px 0px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: none; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + background-color: #FAFAFA; + font-size: 80%; +} +.memTemplItemRight { + padding: 1px 8px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: none; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + background-color: #FAFAFA; + font-size: 80%; +} +.memTemplParams { + padding: 1px 0px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: solid; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + color: #606060; + background-color: #FAFAFA; + font-size: 80%; +} +.search { color: #003399; + font-weight: bold; +} +FORM.search { + margin-bottom: 0px; + margin-top: 0px; +} +INPUT.search { font-size: 75%; + color: #000080; + font-weight: normal; + background-color: #e8eef2; +} +TD.tiny { font-size: 75%; +} +a { + color: #1A41A8; +} +a:visited { + color: #2A3798; +} +.dirtab { padding: 4px; + border-collapse: collapse; + border: 1px solid #84b0c7; +} +TH.dirtab { background: #e8eef2; + font-weight: bold; +} +hr.footer { + height: 1px; + border: none; + border-top: 4px solid #99CC00; +} +hr { + height: 1px; + border: none; + border-top: 1px solid #d1d1d1; +} +/* Style for detailed member documentation */ +.memtemplate { + font-size: 80%; + color: #606060; + font-weight: normal; +} +.memnav { + background-color: #e8eef2; + border: 1px solid #84b0c7; + text-align: center; + margin: 2px; + margin-right: 15px; + padding: 2px; +} +.memitem { + padding-bottom: 4px; + background-color: #eaeef4; + border: 1px solid #c5d2e4; + border-collapse: collapse; +} +.memname { + white-space: nowrap; + font-weight: bold; +} +.memdoc { + padding-left: 10px; +} +.memdoc td em { + font-family: Consolas, monospace; + text-decoration: none; +} +.memproto { + background-color: #c5d2e4; + width: 100%; + color: #333333; + border-bottom: 1px solid #84b0c7; + border-collapse: collapse; + font-weight: bold; +} +.paramkey { + text-align: right; +} +.paramtype { + white-space: nowrap; +} +.paramname { + color: #aa0000; + font-style: italic; + white-space: nowrap; +} +/* End Styling for detailed member documentation */ + +/* for the tree view */ +.ftvtree { + margin: 0.5em 0.5em 0.5em 0.5em; +} +.directory { font-size: 9pt; font-weight: bold; } +.directory h3 { margin: 0px; margin-top: 1em; font-size: 11pt; } +.directory > h3 { margin-top: 0; } +.directory p { margin: 0px; white-space: nowrap; } +.directory div { display: none; margin: 0px; } +.directory img { vertical-align: -30%; } diff --git a/doc/doxygen/ukleos.doxyfile b/doc/doxygen/ukleos.doxyfile new file mode 100644 index 0000000000..bbf20122e9 --- /dev/null +++ b/doc/doxygen/ukleos.doxyfile @@ -0,0 +1,257 @@ +# Doxyfile 1.5.8 + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- +DOXYFILE_ENCODING = UTF-8 +PROJECT_NAME = µkleos +PROJECT_NUMBER = +OUTPUT_DIRECTORY = +CREATE_SUBDIRS = NO +OUTPUT_LANGUAGE = English +BRIEF_MEMBER_DESC = YES +REPEAT_BRIEF = YES +ABBREVIATE_BRIEF = +ALWAYS_DETAILED_SEC = NO +INLINE_INHERITED_MEMB = NO +FULL_PATH_NAMES = NO +STRIP_FROM_PATH = +STRIP_FROM_INC_PATH = +SHORT_NAMES = NO +JAVADOC_AUTOBRIEF = YES +QT_AUTOBRIEF = NO +MULTILINE_CPP_IS_BRIEF = NO +INHERIT_DOCS = YES +SEPARATE_MEMBER_PAGES = NO +TAB_SIZE = 4 +ALIASES = +OPTIMIZE_OUTPUT_FOR_C = YES +OPTIMIZE_OUTPUT_JAVA = NO +OPTIMIZE_FOR_FORTRAN = NO +OPTIMIZE_OUTPUT_VHDL = NO +EXTENSION_MAPPING = +BUILTIN_STL_SUPPORT = NO +CPP_CLI_SUPPORT = NO +SIP_SUPPORT = NO +IDL_PROPERTY_SUPPORT = YES +DISTRIBUTE_GROUP_DOC = NO +SUBGROUPING = YES +TYPEDEF_HIDES_STRUCT = NO +SYMBOL_CACHE_SIZE = 0 +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- +EXTRACT_ALL = NO +EXTRACT_PRIVATE = NO +EXTRACT_STATIC = NO +EXTRACT_LOCAL_CLASSES = YES +EXTRACT_LOCAL_METHODS = NO +EXTRACT_ANON_NSPACES = NO +HIDE_UNDOC_MEMBERS = NO +HIDE_UNDOC_CLASSES = NO +HIDE_FRIEND_COMPOUNDS = NO +HIDE_IN_BODY_DOCS = NO +INTERNAL_DOCS = NO +CASE_SENSE_NAMES = YES +HIDE_SCOPE_NAMES = NO +SHOW_INCLUDE_FILES = YES +INLINE_INFO = YES +SORT_MEMBER_DOCS = YES +SORT_BRIEF_DOCS = NO +SORT_GROUP_NAMES = NO +SORT_BY_SCOPE_NAME = NO +GENERATE_TODOLIST = YES +GENERATE_TESTLIST = YES +GENERATE_BUGLIST = YES +GENERATE_DEPRECATEDLIST= YES +ENABLED_SECTIONS = +MAX_INITIALIZER_LINES = 30 +SHOW_USED_FILES = YES +SHOW_DIRECTORIES = NO +SHOW_FILES = YES +SHOW_NAMESPACES = YES +FILE_VERSION_FILTER = +LAYOUT_FILE = +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- +QUIET = NO +WARNINGS = YES +WARN_IF_UNDOCUMENTED = YES +WARN_IF_DOC_ERROR = YES +WARN_NO_PARAMDOC = NO +WARN_FORMAT = "$file:$line: $text" +WARN_LOGFILE = +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- +INPUT = ../../core ../../cpu ../../board ../../sys ../manual +INPUT_ENCODING = UTF-8 +FILE_PATTERNS = *.doc *.c *.h +RECURSIVE = YES +EXCLUDE = +EXCLUDE_SYMLINKS = NO +EXCLUDE_PATTERNS = */board/*/tools/* +EXCLUDE_SYMBOLS = +EXAMPLE_PATH = +EXAMPLE_PATTERNS = +EXAMPLE_RECURSIVE = NO +IMAGE_PATH = doxygen/ +INPUT_FILTER = +FILTER_PATTERNS = +FILTER_SOURCE_FILES = NO +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- +SOURCE_BROWSER = YES +INLINE_SOURCES = NO +STRIP_CODE_COMMENTS = YES +REFERENCED_BY_RELATION = NO +REFERENCES_RELATION = NO +REFERENCES_LINK_SOURCE = YES +USE_HTAGS = NO +VERBATIM_HEADERS = YES +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- +ALPHABETICAL_INDEX = NO +COLS_IN_ALPHA_INDEX = 5 +IGNORE_PREFIX = +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- +GENERATE_HTML = YES +HTML_OUTPUT = html +HTML_FILE_EXTENSION = .html +HTML_HEADER = src/ukleos-header.html +HTML_FOOTER = src/ukleos-footer.html +HTML_STYLESHEET = src/ukleos.css +HTML_ALIGN_MEMBERS = YES +HTML_DYNAMIC_SECTIONS = YES +GENERATE_DOCSET = NO +DOCSET_FEEDNAME = "Doxygen generated docs" +DOCSET_BUNDLE_ID = org.doxygen.Project +GENERATE_HTMLHELP = NO +CHM_FILE = +HHC_LOCATION = +GENERATE_CHI = YES # +CHM_INDEX_ENCODING = +BINARY_TOC = YES # +TOC_EXPAND = YES # +GENERATE_QHP = NO +QCH_FILE = +QHP_NAMESPACE = +QHP_VIRTUAL_FOLDER = doc +QHP_CUST_FILTER_NAME = +QHP_CUST_FILTER_ATTRS = +QHP_SECT_FILTER_ATTRS = +QHG_LOCATION = +DISABLE_INDEX = NO +ENUM_VALUES_PER_LINE = 4 +GENERATE_TREEVIEW = NO +TREEVIEW_WIDTH = 250 +FORMULA_FONTSIZE = 10 +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- +GENERATE_LATEX = YES +LATEX_OUTPUT = latex +LATEX_CMD_NAME = latex +MAKEINDEX_CMD_NAME = makeindex +COMPACT_LATEX = NO +PAPER_TYPE = a4wide +EXTRA_PACKAGES = +LATEX_HEADER = +PDF_HYPERLINKS = YES +USE_PDFLATEX = YES +LATEX_BATCHMODE = NO +LATEX_HIDE_INDICES = NO +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- +GENERATE_RTF = NO +RTF_OUTPUT = rtf +COMPACT_RTF = NO +RTF_HYPERLINKS = NO +RTF_STYLESHEET_FILE = +RTF_EXTENSIONS_FILE = +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- +GENERATE_MAN = YES +MAN_OUTPUT = man +MAN_EXTENSION = .3 +MAN_LINKS = NO +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- +GENERATE_XML = NO +XML_OUTPUT = xml +XML_SCHEMA = +XML_DTD = +XML_PROGRAMLISTING = YES +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- +GENERATE_AUTOGEN_DEF = NO +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- +GENERATE_PERLMOD = NO +PERLMOD_LATEX = NO +PERLMOD_PRETTY = YES +PERLMOD_MAKEVAR_PREFIX = +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = NO +EXPAND_ONLY_PREDEF = NO +SEARCH_INCLUDES = YES +INCLUDE_PATH = +INCLUDE_FILE_PATTERNS = +PREDEFINED = +EXPAND_AS_DEFINED = +SKIP_FUNCTION_MACROS = YES +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- +TAGFILES = +GENERATE_TAGFILE = +ALLEXTERNALS = NO +EXTERNAL_GROUPS = YES +PERL_PATH = /usr/bin/perl +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- +CLASS_DIAGRAMS = NO # +MSCGEN_PATH = +HIDE_UNDOC_RELATIONS = YES +HAVE_DOT = YES # +DOT_FONTNAME = FreeSans +DOT_FONTSIZE = 10 +DOT_FONTPATH = +CLASS_GRAPH = NO # +COLLABORATION_GRAPH = NO # +GROUP_GRAPHS = NO # +UML_LOOK = NO +TEMPLATE_RELATIONS = NO +INCLUDE_GRAPH = NO +INCLUDED_BY_GRAPH = NO +CALL_GRAPH = NO +CALLER_GRAPH = NO +GRAPHICAL_HIERARCHY = YES +DIRECTORY_GRAPH = NO # +DOT_IMAGE_FORMAT = png +DOT_PATH = +DOTFILE_DIRS = +DOT_GRAPH_MAX_NODES = 50 +MAX_DOT_GRAPH_DEPTH = 0 +DOT_TRANSPARENT = YES # +DOT_MULTI_TARGETS = NO +GENERATE_LEGEND = YES +DOT_CLEANUP = YES +#--------------------------------------------------------------------------- +# Options related to the search engine +#--------------------------------------------------------------------------- +SEARCHENGINE = NO diff --git a/drivers/Jamfile b/drivers/Jamfile new file mode 100644 index 0000000000..e0223c05a1 --- /dev/null +++ b/drivers/Jamfile @@ -0,0 +1,34 @@ +# ****************************************************************************** +# Copyright 2009, Freie Universitaet Berlin (FUB). All rights reserved. +# +# These sources were developed at the Freie Universitaet Berlin, Computer +# Systems and Telematics group (http://cst.mi.fu-berlin.de). +# ------------------------------------------------------------------------------ +# This file is part of FeuerWare. +# +# This program is free software: you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation, either version 3 of the License, or (at your option) any later +# version. +# +# FeuerWare is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with +# this program. If not, see http://www.gnu.org/licenses/ . +# ------------------------------------------------------------------------------ +# For further information and questions please use the web site +# http://scatterweb.mi.fu-berlin.de +# and the mailinglist (subscription via web site) +# scatterweb@lists.spline.inf.fu-berlin.de +# ****************************************************************************** +# $Id: Jamfile 832 2009-03-13 16:45:41Z kaspar $ + +SubDir TOP drivers ; + +Module sht11 : sht11.c : hwtimer ; + +Module ltc4150 : ltc4150.c : board_ltc4150 ; + +SubInclude TOP drivers cc110x ; diff --git a/drivers/cc110x/Jamfile b/drivers/cc110x/Jamfile new file mode 100755 index 0000000000..b96d897d9e --- /dev/null +++ b/drivers/cc110x/Jamfile @@ -0,0 +1,35 @@ +# ****************************************************************************** +# Copyright 2009, Freie Universitaet Berlin (FUB). All rights reserved. +# +# These sources were developed at the Freie Universitaet Berlin, Computer +# Systems and Telematics group (http://cst.mi.fu-berlin.de). +# ------------------------------------------------------------------------------ +# This file is part of FeuerWare. +# +# This program is free software: you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation, either version 3 of the License, or (at your option) any later +# version. +# +# FeuerWare is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with +# this program. If not, see http://www.gnu.org/licenses/ . +# ------------------------------------------------------------------------------ +# For further information and questions please use the web site +# http://scatterweb.mi.fu-berlin.de +# and the mailinglist (subscription via web site) +# scatterweb@lists.spline.inf.fu-berlin.de +# ****************************************************************************** +# $Id: Jamfile 832 2009-03-13 16:45:41Z kaspar $ + +SubDir TOP drivers cc110x ; + +HDRS += $(TOP)/drivers/cc110x ; + +Module cc110x : cc1100.c cc1100-csmaca-mac.c cc1100-defaultSettings.c + cc1100_phy.c cc1100_spi.c + : board_cc1100 swtimer protocol_multiplex gpioint ; + diff --git a/drivers/cc110x/arch_cc1100.h b/drivers/cc110x/arch_cc1100.h new file mode 100644 index 0000000000..ef61dd61c9 --- /dev/null +++ b/drivers/cc110x/arch_cc1100.h @@ -0,0 +1,50 @@ +/****************************************************************************** +Copyright 2008, Freie Universitaet Berlin (FUB). All rights reserved. + +These sources were developed at the Freie Universitaet Berlin, Computer Systems +and Telematics group (http://cst.mi.fu-berlin.de). +------------------------------------------------------------------------------- +This file is part of FeuerWare. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +FeuerWare is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see http://www.gnu.org/licenses/ . +-------------------------------------------------------------------------------- +For further information and questions please use the web site + http://scatterweb.mi.fu-berlin.de +and the mailinglist (subscription via web site) + scatterweb@lists.spline.inf.fu-berlin.de +*******************************************************************************/ + +/** + * @file + * @ingroup LPC2387 + * @brief CC1100 LPC2387 dependend functions + * + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @author Heiko Will + * @version $Revision: 1775 $ + * + * @note $Id: arch_cc1100.h 1775 2010-01-26 09:37:03Z hillebra $ + */ + +#include + +uint8_t cc1100_txrx(uint8_t c); + +void cc1100_gdo0_enable(void); +void cc1100_gdo0_disable(void); +void cc1100_gdo2_enable(void); +void cc1100_gdo2_disable(void); +void cc1100_init_interrupts(void); + +void cc1100_before_send(void); +void cc1100_after_send(void); diff --git a/drivers/cc110x/cc1100-csmaca-mac.c b/drivers/cc110x/cc1100-csmaca-mac.c new file mode 100644 index 0000000000..fab9610cc3 --- /dev/null +++ b/drivers/cc110x/cc1100-csmaca-mac.c @@ -0,0 +1,216 @@ +/****************************************************************************** +Copyright 2008, Freie Universitaet Berlin (FUB). All rights reserved. + +These sources were developed at the Freie Universitaet Berlin, Computer Systems +and Telematics group (http://cst.mi.fu-berlin.de). +------------------------------------------------------------------------------- +This file is part of FeuerWare. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +FeuerWare is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see http://www.gnu.org/licenses/ . +-------------------------------------------------------------------------------- +For further information and questions please use the web site + http://scatterweb.mi.fu-berlin.de +and the mailinglist (subscription via web site) + scatterweb@lists.spline.inf.fu-berlin.de +*******************************************************************************/ + +/** + * @file + * @ingroup dev_cc110x + * @brief ScatterWeb MSB-A2 mac-layer + * + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @author Thomas Hillebrandt + * @author Heiko Will + * @version $Revision: 2128 $ + * + * @note $Id: cc1100-csmaca-mac.c 2128 2010-05-12 12:07:59Z hillebra $ + */ + +#include +//#include +#include + +#include "cc1100.h" +#include "cc1100_phy.h" +#include "cc1100-csmaca-mac.h" +#include "protocol-multiplex.h" + +#include "hwtimer.h" + +/*---------------------------------------------------------------------------*/ + +#define COLLISION_STATE_INITIAL 1 +#define COLLISION_STATE_MEASURE 2 +#define COLLISION_STATE_KEEP 3 + +static uint32_t send_csmaca_calls = 0; +static uint32_t send_csmaca_calls_cs_timeout = 0; +static int collision_count; +static double collisions_per_sec = 0; +static int collision_state = COLLISION_STATE_INITIAL; +static uint64_t collision_measurement_start = 0; + +volatile static int cs_hwtimer_id = -1; +volatile static int cs_timeout_flag = 0; + +/*---------------------------------------------------------------------------*/ +static void cs_timeout_cb(void* ptr) +{ + cs_timeout_flag = 1; +} + +/*---------------------------------------------------------------------------*/ +int cc1100_send_csmaca(radio_address_t address, protocol_t protocol, int priority, char *payload, int payload_len) +{ + uint16_t min_window_size; + uint16_t max_window_size; + uint16_t difs; + uint16_t slottime; + + switch (priority) + { + case PRIORITY_ALARM: + min_window_size = PRIO_ALARM_MIN_WINDOW_SIZE; + max_window_size = PRIO_ALARM_MAX_WINDOW_SIZE; + difs = PRIO_ALARM_DIFS; + slottime = PRIO_ALARM_SLOTTIME; + break; + case PRIORITY_WARNING: + min_window_size = PRIO_WARN_MIN_WINDOW_SIZE; + max_window_size = PRIO_WARN_MAX_WINDOW_SIZE; + difs = PRIO_WARN_DIFS; + slottime = PRIO_WARN_SLOTTIME; + break; + default: + min_window_size = PRIO_DATA_MIN_WINDOW_SIZE; + max_window_size = PRIO_DATA_MAX_WINDOW_SIZE; + difs = PRIO_DATA_DIFS; + slottime = PRIO_DATA_SLOTTIME; + } + + // Calculate collisions per second + if (collision_state == COLLISION_STATE_INITIAL) { + collision_measurement_start = swtimer_now(); + collision_count = 0; + collisions_per_sec = 0; + collision_state = COLLISION_STATE_MEASURE; + } else if (collision_state == COLLISION_STATE_MEASURE) { + uint64_t timespan = swtimer_now() - collision_measurement_start; + if (timespan > 1000000) { + collisions_per_sec = (collision_count * 1000000) / (double) timespan; + if (collisions_per_sec > 0.5 && collisions_per_sec <= 2.2) { + collision_measurement_start = swtimer_now(); + collision_state = COLLISION_STATE_KEEP; + } else if (collisions_per_sec > 2.2) { + collision_measurement_start = swtimer_now(); + collision_state = COLLISION_STATE_KEEP; + } else { + collision_state = COLLISION_STATE_INITIAL; + } + } + } else if (collision_state == COLLISION_STATE_KEEP) { + uint64_t timespan = swtimer_now() - collision_measurement_start; + if (timespan > 5000000) { + collision_state = COLLISION_STATE_INITIAL; + } + } + + // Adjust initial window size according to collision rate + if (collisions_per_sec > 0.5 && collisions_per_sec <= 2.2) { + min_window_size *= 2; + } else if (collisions_per_sec > 2.2) { + min_window_size *= 4; + } + + uint16_t windowSize = min_window_size; // Start with window size of PRIO_XXX_MIN_WINDOW_SIZE + uint16_t backoff = 0; // Backoff between 1 and windowSize + uint32_t total; // Holds the total wait time before send try + uint32_t cs_timeout; // Current carrier sense timeout value + + if (protocol == 0) + { + return RADIO_INVALID_PARAM; // Not allowed, protocol id must be greater zero + } + + cc1100_phy_mutex_lock(); // Lock radio for exclusive access + + // Get carrier sense timeout based on overall error rate till now + send_csmaca_calls++; + int fail_percentage = (send_csmaca_calls_cs_timeout * 100) / send_csmaca_calls; + if (fail_percentage == 0) fail_percentage = 1; + cs_timeout = CARRIER_SENSE_TIMEOUT / fail_percentage; + if (cs_timeout < CARRIER_SENSE_TIMEOUT_MIN) cs_timeout = CARRIER_SENSE_TIMEOUT_MIN; + + cc1100_cs_init(); // Initialize carrier sensing + + window: + if (backoff != 0) goto cycle; // If backoff was 0 + windowSize *= 2; // ...double the current window size + if (windowSize > max_window_size) + { + windowSize = max_window_size; // This is the maximum size allowed + } + backoff = rand() % windowSize; // ...and choose new backoff + if (backoff < 0) backoff *= -1; + backoff += (uint16_t) 1; + cycle: + cs_timeout_flag = 0; // Carrier sense timeout flag + cs_hwtimer_id = hwtimer_set(cs_timeout, // Set hwtimer to set CS timeout flag + cs_timeout_cb, NULL); + while (cc1100_cs_read()) // Wait until air is free + { + if (cs_timeout_flag) + { + send_csmaca_calls_cs_timeout++; +#ifndef CSMACA_MAC_AGGRESSIVE_MODE + cc1100_phy_mutex_unlock(); + cc1100_go_after_tx(); // Go from RX to default mode + return RADIO_CS_TIMEOUT; // Return immediately +#endif +#ifdef CSMACA_MAC_AGGRESSIVE_MODE + goto send; // Send anyway +#endif + } + } + hwtimer_remove(cs_hwtimer_id); // Remove hwtimer + cc1100_cs_write_cca(1); // Air is free now + cc1100_cs_set_enabled(true); + if (cc1100_cs_read()) goto window; // GDO0 triggers on rising edge, so + // test once after interrupt is enabled + if (backoff > 0) backoff--; // Decrement backoff counter + total = slottime; // Calculate total wait time + total *= (uint32_t)backoff; // Slot vector set + total += difs; // ...and standard DIFS wait time + cs_timeout_flag = 0; // Carrier sense timeout flag + cs_hwtimer_id = hwtimer_set(total, // Set hwtimer to set CS timeout flag + cs_timeout_cb, NULL); + while (!cs_timeout_flag + || !cc1100_cs_read_cca()) // Wait until timeout is finished + { + if (cc1100_cs_read_cca() == 0) // Is the air still free? + { + hwtimer_remove(cs_hwtimer_id); + goto window; // No. Go back to new wait period. + } + } + cc1100_cs_set_enabled(false); +#ifdef CSMACA_MAC_AGGRESSIVE_MODE + send: +#endif + int res = cc1100_send(address, protocol, priority, payload, payload_len); + if (res < 0) { + collision_count++; + } + return res; +} diff --git a/drivers/cc110x/cc1100-csmaca-mac.h b/drivers/cc110x/cc1100-csmaca-mac.h new file mode 100644 index 0000000000..ecfeedc39d --- /dev/null +++ b/drivers/cc110x/cc1100-csmaca-mac.h @@ -0,0 +1,68 @@ +/****************************************************************************** +Copyright 2008, Freie Universitaet Berlin (FUB). All rights reserved. + +These sources were developed at the Freie Universitaet Berlin, Computer Systems +and Telematics group (http://cst.mi.fu-berlin.de). +------------------------------------------------------------------------------- +This file is part of FeuerWare. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +FeuerWare is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see http://www.gnu.org/licenses/ . +-------------------------------------------------------------------------------- +For further information and questions please use the web site + http://scatterweb.mi.fu-berlin.de +and the mailinglist (subscription via web site) + scatterweb@lists.spline.inf.fu-berlin.de +*******************************************************************************/ + +/** + * @file + * @ingroup dev_cc110x + * @brief ScatterWeb MSB-A2 mac-layer + * + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @author Thomas Hillebrandt + * @author Heiko Will + * @version $Revision: 1999 $ + * + * @note $Id: cc1100-csmaca-mac.h 1999 2010-03-16 15:48:18Z hillebra $ + */ + +#ifndef CC1100_CSMACA_MAC_ +#define CC1100_CSMACA_MAC_ + +#include "cc1100-interface.h" +#include "cc1100-defaultSettings.h" + +//#define CSMACA_MAC_AGGRESSIVE_MODE // MAC aggressive mode on/off switch + +#define CARRIER_SENSE_TIMEOUT (200000) // Carrier Sense timeout ~ 2 seconds +#define CARRIER_SENSE_TIMEOUT_MIN (2000) // Minimum Carrier Sense timeout ~ 20 milliseconds +#define CS_TX_SWITCH_TIME (80) // Carrier Sense to TX switch time (measured ~ 350 us) + +/** All values are in ticks (x10 us) */ +#define PRIO_ALARM_DIFS (200) // DIFS for ALARM packets, the default wait time +#define PRIO_ALARM_SLOTTIME (CS_TX_SWITCH_TIME) // Time of one additional wait slot +#define PRIO_ALARM_MIN_WINDOW_SIZE (2) // Minimum window size of backoff algorithm +#define PRIO_ALARM_MAX_WINDOW_SIZE (8) // Maximum window size of backoff algorithm + +#define PRIO_WARN_DIFS (1000) // DIFS for WARN packets, the default wait time +#define PRIO_WARN_SLOTTIME (CS_TX_SWITCH_TIME) // Time of one additional wait slot +#define PRIO_WARN_MIN_WINDOW_SIZE (2) // Minimum window size of backoff algorithm +#define PRIO_WARN_MAX_WINDOW_SIZE (16) // Maximum window size of backoff algorithm + +#define PRIO_DATA_DIFS (2500) // DIFS for normal data packets, the default wait time +#define PRIO_DATA_SLOTTIME (CS_TX_SWITCH_TIME) // Time of one additional wait slot +#define PRIO_DATA_MIN_WINDOW_SIZE (4) // Minimum window size of backoff algorithm +#define PRIO_DATA_MAX_WINDOW_SIZE (32) // Maximum window size of backoff algorithm + +#endif /*CC1100_CSMACA_MAC_*/ diff --git a/drivers/cc110x/cc1100-defaultSettings.c b/drivers/cc110x/cc1100-defaultSettings.c new file mode 100644 index 0000000000..e4561ff589 --- /dev/null +++ b/drivers/cc110x/cc1100-defaultSettings.c @@ -0,0 +1,124 @@ +/****************************************************************************** +Copyright 2008, Freie Universitaet Berlin (FUB). All rights reserved. + +These sources were developed at the Freie Universitaet Berlin, Computer Systems +and Telematics group (http://cst.mi.fu-berlin.de). +------------------------------------------------------------------------------- +This file is part of FeuerWare. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +FeuerWare is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see http://www.gnu.org/licenses/ . +-------------------------------------------------------------------------------- +For further information and questions please use the web site + http://scatterweb.mi.fu-berlin.de +and the mailinglist (subscription via web site) + scatterweb@lists.spline.inf.fu-berlin.de +*******************************************************************************/ + +/** + * @ingroup dev_cc110x + * @{ + */ + +/** + * @file + * @brief TI Chipcon CC110x default settings + * + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @author Thomas Hillebrandt + * @author Heiko Will + * @version $Revision: 2058 $ + * + * @note $Id: cc1100-defaultSettings.c 2058 2010-03-31 08:59:31Z hillebra $ + */ + +#include "cc1100-defaultSettings.h" + +/** + * Usable, non overlapping channels and corresponding frequencies + * for use with CC1100. CHANNR is the register for selecting a channel. + * + * channel number | CHANNR | frequency [MHz] + * ----------------------------------------- + * 0 | 0 | 869.525 + * 1 | 10 | 871.61 + * 2 | 20 | 873.58 ~ seems to be bad (hang-ups with this channel) + * 3 | 30 | 875.61 + * 4 | 40 | 877.58 + * 5 | 50 | 879.61 + * 6 | 60 | 881.58 + * 7 | 70 | 883.61 + * 8 | 80 | 885.58 + * 9 | 90 | 887.61 + * 10 | 100 | 889.58 + * 11 | 110 | 891.57 + * 12 | 120 | 893.58 + * 13 | 130 | 895.61 + * 14 | 140 | 897.58 + * 15 | 150 | 899.57 + * 16 | 160 | 901.57 + * 17 | 170 | 903.61 + * 18 | 180 | 905.57 + * 19 | 190 | 907.57 + * 20 | 200 | 909.57 + * 21 | 210 | 911.57 + * 22 | 220 | 913.57 + * 23 | 230 | 915.61 + * 24 | 240 | 917.61 + */ + +// 400 kbps, MSK, X-tal: 26 MHz (Chip Revision F) +char cc1100_conf[] = { + 0x06, // IOCFG2 + 0x2E, // IOCFG1 + 0x0E, // IOCFG0 + 0x0F, // FIFOTHR + 0x9B, // SYNC1 + 0xAD, // SYNC0 + 0x3D, // PKTLEN (maximum value of packet length byte = 61) + 0x06, // PKTCTRL1 + 0x45, // PKTCTRL0 (variable packet length) + 0xFF, // ADDR + CC1100_DEFAULT_CHANNR*10, // CHANNR + 0x0B, // FSCTRL1 + 0x00, // FSCTRL0 + 0x21, // FREQ2 + 0x71, // FREQ1 + 0x7A, // FREQ0 + 0x2D, // MDMCFG4 + 0xF8, // MDMCFG3 + 0x73, // MDMCFG2 + 0x42, // MDMCFG1 + 0xF8, // MDMCFG0 + 0x00, // DEVIATN + 0x07, // MCSM2 + 0x03, // MCSM1 + 0x18, // MCSM0 + 0x1D, // FOCCFG + 0x1C, // BSCFG + 0xC0, // AGCCTRL2 + 0x49, // AGCCTRL1, (old value was 0x49 -> made carrier sense less sensitive!) + // 0x47 - 7 dB above MAGN_TARGET setting + 0xB2, // AGCCTRL0 + 0x87, // WOREVT1 + 0x6B, // WOREVT0 + 0xF8, // WORCTRL + 0xB6, // FREND1 + 0x10, // FREND0 + 0xEA, // FSCAL3 + 0x2A, // FSCAL2 + 0x00, // FSCAL1 + 0x1F, // FSCAL0 + 0x00 // padding to 4 bytes +}; + +/** @} */ diff --git a/drivers/cc110x/cc1100-defaultSettings.h b/drivers/cc110x/cc1100-defaultSettings.h new file mode 100644 index 0000000000..a43ebe42cf --- /dev/null +++ b/drivers/cc110x/cc1100-defaultSettings.h @@ -0,0 +1,109 @@ +/****************************************************************************** +Copyright 2008, Freie Universitaet Berlin (FUB). All rights reserved. + +These sources were developed at the Freie Universitaet Berlin, Computer Systems +and Telematics group (http://cst.mi.fu-berlin.de). +------------------------------------------------------------------------------- +This file is part of FeuerWare. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +FeuerWare is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see http://www.gnu.org/licenses/ . +-------------------------------------------------------------------------------- +For further information and questions please use the web site + http://scatterweb.mi.fu-berlin.de +and the mailinglist (subscription via web site) + scatterweb@lists.spline.inf.fu-berlin.de +*******************************************************************************/ + +#ifndef CC1100_DEFAULTSETTINGS_H +#define CC1100_DEFAULTSETTINGS_H + +/** + * @ingroup dev_cc110x + * @{ + */ + +/** + * @file + * @brief TI Chipcon CC110x default settings + * + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @author Thomas Hillebrandt + * @author Heiko Will + * @version $Revision: 2139 $ + * + * @note $Id: cc1100-defaultSettings.h 2139 2010-05-26 08:04:04Z hillebra $ + */ + +#include "hwtimer.h" + +// returns hwtimer ticks per us +#define RTIMER_TICKS(us) HWTIMER_TICKS(us) + +#define TIMER_TICK_USEC_RES (122) + +// Default PA table index (output power) +#define PATABLE (11) + +// Watchdog cycle time in seconds, set 0 to disable watchdog +#define CC1100_WATCHDOG_PERIOD (5) + +// Number of transmission retries for unicast packets (constant RX mode) +#define TRANSMISSION_RETRIES_CRX_UC (5) + +// Number of transmission retries for unicast packets (WOR mode) +#define TRANSMISSION_RETRIES_WOR_UC (1) + +// Number of transmission retries for broadcast packets (constant RX mode) +#define TRANSMISSION_RETRIES_CRX_BC (0) + +// Number of transmission retries for broadcast packets (WOR mode) +#define TRANSMISSION_RETRIES_WOR_BC (0) + +// Time before chip goes back to RX (= stays in PWD after incoming packet) +#define WOR_TIMEOUT_1 (3200) // ~ 32 milliseconds + +// Time before chip goes back to WOR (= stays in RX after elapsed WOR_TIMEOUT_1) +#define WOR_TIMEOUT_2 (800) // ~ 8 milliseconds + +// XOSC startup + FS calibration (300 + 809 us ~ 1.38 ms) +#define FS_CAL_TIME RTIMER_TICKS(12 * TIMER_TICK_USEC_RES) + +// Manual FS calibration (721 us) +#define MANUAL_FS_CAL_TIME RTIMER_TICKS(7 * TIMER_TICK_USEC_RES) + +// Reset wait time (in reset procedure) +#define RESET_WAIT_TIME RTIMER_TICKS(4 * TIMER_TICK_USEC_RES) + +// Time chip needs to go to RX +#define IDLE_TO_RX_TIME RTIMER_TICKS(1 * TIMER_TICK_USEC_RES) + +// Time chip needs to go to RX and CS signal is ready +#define CS_READY_TIME RTIMER_TICKS(3 * TIMER_TICK_USEC_RES) + +// Default RX interval for WOR in milliseconds +#define T_RX_INTERVAL (542) + +// Time of packet interval in microseconds (at 400 kbps) +#define T_PACKET_INTERVAL (3800) + +// The size of the configuration array for CC1100 in bytes +#define CC1100_CONF_SIZE (39) + +// The default channel number (0-24) for CC1100 +#define CC1100_DEFAULT_CHANNR (0) + +// Burst retry to TX switch time (measured ~ 230 us) +#define BURST_RETRY_TX_SWITCH_TIME (23) + +/** @} */ +#endif diff --git a/drivers/cc110x/cc1100-interface.h b/drivers/cc110x/cc1100-interface.h new file mode 100644 index 0000000000..b122b5eeae --- /dev/null +++ b/drivers/cc110x/cc1100-interface.h @@ -0,0 +1,217 @@ +/****************************************************************************** +Copyright 2008, Freie Universitaet Berlin (FUB). All rights reserved. + +These sources were developed at the Freie Universitaet Berlin, Computer Systems +and Telematics group (http://cst.mi.fu-berlin.de). +------------------------------------------------------------------------------- +This file is part of FeuerWare. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +FeuerWare is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see http://www.gnu.org/licenses/ . +-------------------------------------------------------------------------------- +For further information and questions please use the web site + http://scatterweb.mi.fu-berlin.de +and the mailinglist (subscription via web site) + scatterweb@lists.spline.inf.fu-berlin.de +*******************************************************************************/ + + +/** + * @ingroup dev_cc110x + * @{ + */ + +/** + * @file + * @brief TI Chipcon CC110x public interface + * + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @author Thomas Hillebrandt + * @version $Revision: 2283 $ + * + * @note $Id: cc1100-interface.h 2283 2010-06-15 14:02:27Z hillebra $ + */ + +#ifndef CC1100INTERFACE_H_ +#define CC1100INTERFACE_H_ + +#include +#include "radio/radio.h" + +#define CC1100_BROADCAST_ADDRESS (0x00) ///< CC1100 broadcast address + +#define MAX_UID (0xFF) ///< Maximum UID of a node is 255 +#define MIN_UID (0x01) ///< Minimum UID of a node is 1 + +#define MIN_CHANNR (0) ///< Minimum channel number +#define MAX_CHANNR (24) ///< Maximum channel number + +#define MIN_OUTPUT_POWER (0) ///< Minimum output power value +#define MAX_OUTPUT_POWER (11) ///< Maximum output power value + +#define CC1100_MODE_WOR (0) ///< Usable radio mode: Wake-On-Radio +#define CC1100_MODE_CONSTANT_RX (1) ///< Usable radio mode: Constant receive + +// Define default radio mode to constant RX if no +// project specific setting is available. +#ifndef CC1100_RADIO_MODE + #define CC1100_RADIO_MODE CC1100_MODE_CONSTANT_RX +#endif + +/// CC1100 radio interface +extern const radio_t radio_cc1100; + +/** + * @brief Initialize radio layer. + * + * Initialize the radio layer, must be called before radio can be used. + */ +void cc1100_init(void); + +/** + * @brief Get the radio mode. + * + * @return Either CC1100_MODE_CONSTANT_RX or CC1100_MODE_WOR. + */ +uint8_t cc1100_get_mode(void); + +/** + * @brief Set the radio mode. + * + * Sets the radio mode with optional mode data. If the radio mode is WOR, + * the optional mode data is the RX interval in milliseconds. Must be called + * only after CC1100 is initialized. + * + * @param mode New radio mode (one of the constants defined in this file). + * @param opt_mode_data Desired RX interval in milliseconds [50..60000]. + * + * @return true if mode could be applied; false otherwise (stays in previous mode). + */ +bool cc1100_set_mode(uint8_t mode, uint16_t opt_mode_data); + +/** + * @brief Get the average transmission duration (till ACK received). + * + * @return The average transmission duration of one packet in milliseconds. + */ +int cc1100_get_avg_transmission_duration(void); + +/** + * @brief Get the radio address. + * + * @return The current address of the radio. + */ +radio_address_t cc1100_get_address(void); + +/** + * @brief Set the radio address. + * + * @param address The new radio address. + * + * @return true if address could be set; false otherwise. + */ +bool cc1100_set_address(radio_address_t address); + +/** + * @brief Get the current channel number. + * + * @return The current channel number used. + */ +uint8_t cc1100_get_channel(void); + +/** + * @brief Set the channel to use. + * + * @param channr The new channel number (between MIN_CHANNR and MAX_CHANNR) to use. + * + * @return true if channel could be set; false otherwise. + */ +bool cc1100_set_channel(uint8_t channr); + +/** + * @brief Set current output power in dBm. + * + * @param pa_idx New output power setting, valid values + * are from MIN_OUTPUT_POWER (lowest output power, -52 dBm) + * to MAX_OUTPUT_POWER (highest output power, +10 dBm). + * + * @return true if output power could be set; false otherwise. + */ +bool cc1100_set_output_power(uint8_t pa_idx); + +/** + * @brief Set a packet monitor at this layer. + * + * All incoming packets will be passed to this packet monitor before + * packet gets processed by a specific handler. The work in the monitor + * should take as less time as possible (no waiting or intense I/O). + * + * @param monitor The packet monitor or NULL if the current packet + * monitor should be removed. + * + * @return true if this layer supports packet monitoring; false otherwise. + */ +bool cc1100_set_packet_monitor(packet_monitor_t monitor); + +/** + * @brief Set a packet handler for a given protocol. + * + * @param protocol The protocol identifier (3-bit value > 0, 1 reserved for LL-ACK). + * @param handler The packet handler called if a packet of given protocol is received. + * + * @return -1 if an error occurs (e.g. handler table full) else >= 0. + */ +int cc1100_set_packet_handler(protocol_t protocol, packet_handler_t handler); + +/** + * @brief Send data to given destination address with acknowledgment. + * + * The maximum payload length are 58 bytes! + * + * @param addr The destination address. + * @param protocol The protocol identifier of the transmitted data. + * @param priority Ignored (always highest). + * @param payload The data to be send. + * @param payload_len The length of the data in bytes. + * + * @return A negative value if operation failed; if operation succeeded (ACK received) the number of transmitted bytes. + */ +int cc1100_send(radio_address_t addr, protocol_t protocol, int priority, char *payload, int payload_len); + +/** + * @brief Send data to given destination address with acknowledgment and CSMA/CA. + * + * The maximum payload length are 58 bytes! + * + * @param address The destination address. + * @param protocol The protocol identifier of the transmitted data. + * @param priority The MAC priority to send with. One of {PRIORITY_ALARM, PRIORITY_WARNING, PRIORITY_DATA}. + * @param payload The data to be send. + * @param payload_len The length of the data in bytes. + * + * @return A negative value if operation failed; if operation succeeded (ACK received) else the number of transmitted bytes. + */ +int cc1100_send_csmaca(radio_address_t address, protocol_t protocol, int priority, char *payload, int payload_len); + +/** + * @brief Print current radio configuration. + */ +void cc1100_print_config(void); + +/** + * @brief Print radio statistics. + */ +void cc1100_print_statistic(void); + +/** @} */ + +#endif /* CC1100INTERFACE_H_ */ diff --git a/drivers/cc110x/cc1100-internal.h b/drivers/cc110x/cc1100-internal.h new file mode 100755 index 0000000000..54ddabde70 --- /dev/null +++ b/drivers/cc110x/cc1100-internal.h @@ -0,0 +1,218 @@ +/****************************************************************************** +Copyright 2008, Freie Universitaet Berlin (FUB). All rights reserved. + +These sources were developed at the Freie Universitaet Berlin, Computer Systems +and Telematics group (http://cst.mi.fu-berlin.de). +------------------------------------------------------------------------------- +This file is part of FeuerWare. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +FeuerWare is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see http://www.gnu.org/licenses/ . +-------------------------------------------------------------------------------- +For further information and questions please use the web site + http://scatterweb.mi.fu-berlin.de +and the mailinglist (subscription via web site) + scatterweb@lists.spline.inf.fu-berlin.de +*******************************************************************************/ + +#ifndef CC1100_INTERNAL_H +#define CC1100_INTERNAL_H + +/** + * @ingroup dev_cc110x + * @{ + */ + +/** + * @file + * @internal + * @brief TI Chipcon CC110x internal hardware constants + * + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @author Thomas Hillebrandt + * @author Heiko Will + * @version $Revision: 1231 $ + * + * @note $Id: cc1100-internal.h 1231 2009-08-20 08:31:32Z baar $ + */ + +#define FIXED_PKTLEN (0x00) ///< Fixed length packets, length configured in PKTLEN register. +#define VARIABLE_PKTLEN (0x01) ///< Variable length packets, packet length configured by the first + ///< byte after synch word. + +/** + * @name Bitmasks for reading out status register values + * @{ + */ + +/** + * @brief Bitmask (=10000000) for reading CRC_OK. + * + * If CRC_OK == 1: CRC for received data OK (or CRC disabled). + * If CRC_OK == 0: CRC error in received data. + */ +#define CRC_OK (0x80) +/** + * @brief Bitmask (=01111111) for reading LQI_EST. + * + * The Link Quality Indicator estimates how easily a received signal can be demodulated. + */ +#define LQI_EST (0x7F) +#define I_RSSI (0x00) ///< Index 0 contains RSSI information (from optionally appended packet status bytes). +#define I_LQI (0x01) ///< Index 1 contains LQI & CRC_OK information (from optionally appended packet status bytes). +#define MARC_STATE (0x1F) ///< Bitmask (=00011111) for reading MARC_STATE in MARCSTATE status register. +#define CS (0x40) ///< Bitmask (=01000000) for reading CS (Carrier Sense) in PKTSTATUS status register. +#define PQT_REACHED (0x20) ///< Bitmask (=00100000) for reading PQT_REACHED (Preamble Quality reached) in PKTSTATUS status register. +#define CCA (0x10) ///< Bitmask (=00010000) for reading CCA (clear channel assessment) in PKTSTATUS status register. +#define SFD (0x08) ///< Bitmask (=00001000) for reading SFD (Sync word found) in PKTSTATUS status register. +#define GDO2 (0x04) ///< Bitmask (=00000100) for reading GDO2 (current value on GDO2 pin) in PKTSTATUS status register. +#define GDO1 (0x02) ///< Bitmask (=00000010) for reading GDO1 (current value on GDO1 pin) in PKTSTATUS status register. +#define GDO0 (0x01) ///< Bitmask (=00000001) for reading GDO0 (current value on GDO0 pin) in PKTSTATUS status register. +#define TXFIFO_UNDERFLOW (0x80) ///< Bitmask (=10000000) for reading TXFIFO_UNDERFLOW in TXBYTES status register. +#define BYTES_IN_TXFIFO (0x7F) ///< Bitmask (=01111111) for reading NUM_TXBYTES in TXBYTES status register. +#define RXFIFO_OVERFLOW (0x80) ///< Bitmask (=10000000) for reading RXFIFO_OVERFLOW in RXBYTES status register. +#define BYTES_IN_RXFIFO (0x7F) ///< Bitmask (=01111111) for reading NUM_RXBYTES in RXBYTES status register. +/** @} */ + +/** + * @name Bitmasks for reading out configuration register values + * @{ + */ +#define PKT_LENGTH_CONFIG (0x03) ///< Bitmask (=00000011) for reading LENGTH_CONFIG in PKTCTRL0 configuration register. +/** @} */ + +/** + * @name Definitions to support burst/single access + * @{ + */ +#define CC1100_WRITE_BURST (0x40) ///< Offset for burst write. +#define CC1100_READ_SINGLE (0x80) ///< Offset for read single byte. +#define CC1100_READ_BURST (0xC0) ///< Offset for read burst. +#define CC1100_NOBYTE (0x00) ///< No command (for reading). +/** @} */ + +/** + * @name Configuration Registers (47x) + * @{ + */ +#define CC1100_IOCFG2 (0x00) ///< GDO2 output pin configuration +#define CC1100_IOCFG1 (0x01) ///< GDO1 output pin configuration +#define CC1100_IOCFG0 (0x02) ///< GDO0 output pin configuration +#define CC1100_FIFOTHR (0x03) ///< RX FIFO and TX FIFO thresholds +#define CC1100_SYNC1 (0x04) ///< Sync word, high byte +#define CC1100_SYNC0 (0x05) ///< Sync word, low byte +#define CC1100_PKTLEN (0x06) ///< Packet length +#define CC1100_PKTCTRL1 (0x07) ///< Packet automation control +#define CC1100_PKTCTRL0 (0x08) ///< Packet automation control +#define CC1100_ADDR (0x09) ///< Device address +#define CC1100_CHANNR (0x0A) ///< Channel number +#define CC1100_FSCTRL1 (0x0B) ///< Frequency synthesizer control +#define CC1100_FSCTRL0 (0x0C) ///< Frequency synthesizer control +#define CC1100_FREQ2 (0x0D) ///< Frequency control word, high byte +#define CC1100_FREQ1 (0x0E) ///< Frequency control word, middle byte +#define CC1100_FREQ0 (0x0F) ///< Frequency control word, low byte +#define CC1100_MDMCFG4 (0x10) ///< Modem configuration +#define CC1100_MDMCFG3 (0x11) ///< Modem configuration +#define CC1100_MDMCFG2 (0x12) ///< Modem configuration +#define CC1100_MDMCFG1 (0x13) ///< Modem configuration +#define CC1100_MDMCFG0 (0x14) ///< Modem configuration +#define CC1100_DEVIATN (0x15) ///< Modem deviation setting +#define CC1100_MCSM2 (0x16) ///< Main Radio Control State Machine configuration +#define CC1100_MCSM1 (0x17) ///< Main Radio Control State Machine configuration +#define CC1100_MCSM0 (0x18) ///< Main Radio Control State Machine configuration +#define CC1100_FOCCFG (0x19) ///< Frequency Offset Compensation configuration +#define CC1100_BSCFG (0x1A) ///< Bit Synchronization configuration +#define CC1100_AGCCTRL2 (0x1B) ///< AGC control +#define CC1100_AGCCTRL1 (0x1C) ///< AGC control +#define CC1100_AGCCTRL0 (0x1D) ///< AGC control +#define CC1100_WOREVT1 (0x1E) ///< High byte Event 0 timeout +#define CC1100_WOREVT0 (0x1F) ///< Low byte Event 0 timeout +#define CC1100_WORCTRL (0x20) ///< Wake On Radio control +#define CC1100_FREND1 (0x21) ///< Front end RX configuration +#define CC1100_FREND0 (0x22) ///< Front end TX configuration +#define CC1100_FSCAL3 (0x23) ///< Frequency synthesizer calibration +#define CC1100_FSCAL2 (0x24) ///< Frequency synthesizer calibration +#define CC1100_FSCAL1 (0x25) ///< Frequency synthesizer calibration +#define CC1100_FSCAL0 (0x26) ///< Frequency synthesizer calibration +#define CC1100_RCCTRL1 (0x27) ///< RC oscillator configuration +#define CC1100_RCCTRL0 (0x28) ///< RC oscillator configuration +#define CC1100_FSTEST (0x29) ///< Frequency synthesizer calibration control +#define CC1100_PTEST (0x2A) ///< Production test +#define CC1100_AGCTEST (0x2B) ///< AGC test +#define CC1100_TEST2 (0x2C) ///< Various test settings +#define CC1100_TEST1 (0x2D) ///< Various test settings +#define CC1100_TEST0 (0x2E) ///< Various test settings +/** @} */ + +/** + * @name Strobe commands (14x) + * @{ + */ +#define CC1100_SRES (0x30) ///< Reset chip. +/** + * @brief Enable and calibrate frequency synthesizer (if MCSM0.FS_AUTOCAL=1). + * + * If in RX/TX: Go to a wait state where only the synthesizer is running (for quick RX / TX turnaround). + */ +#define CC1100_SFSTXON (0x31) +#define CC1100_SXOFF (0x32) ///< Turn off crystal oscillator. +#define CC1100_SCAL (0x33) ///< Calibrate frequency synthesizer and turn it off (enables quick start). +#define CC1100_SRX (0x34) ///< Enable RX. Perform calibration first if coming from IDLE and MCSM0.FS_AUTOCAL=1. +/** + * In IDLE state: Enable TX. Perform calibration first if MCSM0.FS_AUTOCAL=1. + * If in RX state and CCA is enabled: Only go to TX if channel is clear. + */ +#define CC1100_STX (0x35) +#define CC1100_SIDLE (0x36) ///< Exit RX / TX, turn off frequency synthesizer and exit WOR mode if applicable. +#define CC1100_SAFC (0x37) ///< Perform AFC adjustment of the frequency synthesizer +#define CC1100_SWOR (0x38) ///< Start automatic RX polling sequence (Wake-on-Radio) +#define CC1100_SPWD (0x39) ///< Enter power down mode when CSn goes high. +#define CC1100_SFRX (0x3A) ///< Flush the RX FIFO buffer (CC1100 should be in IDLE state). +#define CC1100_SFTX (0x3B) ///< Flush the TX FIFO buffer (CC1100 should be in IDLE state). +#define CC1100_SWORRST (0x3C) ///< Reset real time clock. +#define CC1100_SNOP (0x3D) ///< No operation. May be used to pad strobe commands to two bytes for simpler software. +/** @} */ + +/** + * @name Status registers (12x) + * @{ + */ +#define CC1100_PARTNUM (0x30) ///< Part number of CC1100. +#define CC1100_VERSION (0x31) ///< Current version number. +#define CC1100_FREQEST (0x32) ///< Frequency Offset Estimate. +#define CC1100_LQI (0x33) ///< Demodulator estimate for Link Quality. +#define CC1100_RSSI (0x34) ///< Received signal strength indication. +#define CC1100_MARCSTATE (0x35) ///< Control state machine state. +#define CC1100_WORTIME1 (0x36) ///< High byte of WOR timer. +#define CC1100_WORTIME0 (0x37) ///< Low byte of WOR timer. +#define CC1100_PKTSTATUS (0x38) ///< Current GDOx status and packet status. +#define CC1100_VCO_VC_DAC (0x39) ///< Current setting from PLL calibration module. +#define CC1100_TXBYTES (0x3A) ///< Underflow and number of bytes in the TX FIFO. +#define CC1100_RXBYTES (0x3B) ///< Overflow and number of bytes in the RX FIFO. +/** @} */ + +/** + * @name Multi byte registers + * @{ + */ +/** + * @brief Register for eight user selected output power settings. + * + * 3-bit FREND0.PA_POWER value selects the PATABLE entry to use. + */ +#define CC1100_PATABLE (0x3E) +#define CC1100_TXFIFO (0x3F) ///< TX FIFO: Write operations write to the TX FIFO (SB: +0x00; BURST: +0x40) +#define CC1100_RXFIFO (0x3F) ///< RX FIFO: Read operations read from the RX FIFO (SB: +0x80; BURST: +0xC0) + +/** @} */ + +#endif diff --git a/drivers/cc110x/cc1100.c b/drivers/cc110x/cc1100.c new file mode 100644 index 0000000000..5b671b3ad8 --- /dev/null +++ b/drivers/cc110x/cc1100.c @@ -0,0 +1,905 @@ +/****************************************************************************** +Copyright 2008, Freie Universitaet Berlin (FUB). All rights reserved. + +These sources were developed at the Freie Universitaet Berlin, Computer Systems +and Telematics group (http://cst.mi.fu-berlin.de). +------------------------------------------------------------------------------- +This file is part of FeuerWare. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +FeuerWare is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see http://www.gnu.org/licenses/ . +-------------------------------------------------------------------------------- +For further information and questions please use the web site + http://scatterweb.mi.fu-berlin.de +and the mailinglist (subscription via web site) + scatterweb@lists.spline.inf.fu-berlin.de +*******************************************************************************/ + +/** + * @ingroup dev_cc110x + * @{ + */ + +/** + * @file + * @internal + * @brief TI Chipcon CC110x Radio driver + * + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @author Thomas Hillebrandt + * @author Heiko Will + * @version $Revision: 2283 $ + * + * @note $Id: cc1100.c 2283 2010-06-15 14:02:27Z hillebra $ + */ + +#include +#include +#include +#include + +#include "irq.h" +#include "arch_cc1100.h" +#include "cc1100.h" +#include "cc1100_phy.h" +#include "cc1100_spi.h" +#include "cc1100-internal.h" +#include "cc1100-defaultSettings.h" + +#include "hwtimer.h" +#include "core/include/bitarithm.h" + +// TODO: cc1100 port timer +#ifdef FEUERWARE_CPU_LPC2387 +//#include "cpu/lpc2387/lpc2387-timer2.h" +#endif + +#if defined(FEUERWARE_CPU_MSP430) +#include +#elif defined(FEUERWARE_CPU_LPC2387) +#include "lpc2387.h" +#endif + +#define PACKET_LENGTH (0x3E) ///< Packet length = 62 Bytes. +#define CC1100_SYNC_WORD_TX_TIME (90000) // loop count (max. timeout ~ 15 ms) to wait for + // sync word to be transmitted (GDO2 from low to high) + +/** + * @name Virtual Radio Device methods (see vdevice_radio_methods) + * @{ + */ +static int rd_set_mode(int mode); +/** @} */ + +static void switch_to_wor(void); + +/*---------------------------------------------------------------------------*/ +// Power control data structures +/*---------------------------------------------------------------------------*/ + +static uint8_t pa_table_index = PATABLE; ///< Current PATABLE Index +static uint8_t pa_table[] = { ///< PATABLE with available output powers + 0x00, ///< -52 dBm + 0x03, ///< -30 dBm + 0x0D, ///< -20 dBm + 0x1C, ///< -15 dBm + 0x34, ///< -10 dBm + 0x57, ///< - 5 dBm + 0x3F, ///< - 1 dBm + 0x8E, ///< 0 dBm + 0x85, ///< + 5 dBm + 0xCC, ///< + 7 dBm + 0xC6, ///< + 9 dBm + 0xC3 ///< +10 dBm +}; // If PATABLE is changed in size, adjust MAX_OUTPUT_POWER definition in CC1100 interface! + +static int8_t pa_table_dBm[] = { ///< Values of the PATABLE in dBm + -52, + -30, + -20, + -15, + -10, + -5, + -1, + 0, + 5, + 7, + 9, + 10 +}; + +/*---------------------------------------------------------------------------*/ +// Main radio data structures +/*---------------------------------------------------------------------------*/ + +volatile cc1100_flags rflags; ///< Radio control flags +static uint8_t radio_address; ///< Radio address +static uint8_t radio_channel; ///< Radio channel number + +const radio_t radio_cc1100 = { ///< Radio driver API + "CC1100", + CC1100_BROADCAST_ADDRESS, + MAX_OUTPUT_POWER, + cc1100_get_avg_transmission_duration, + cc1100_get_address, + cc1100_set_address, + cc1100_set_output_power, + cc1100_set_packet_monitor, + cc1100_set_packet_handler, + cc1100_send_csmaca, + cc1100_print_statistic, + cc1100_print_config +}; + +/*---------------------------------------------------------------------------*/ +// Data structures for mode control +/*---------------------------------------------------------------------------*/ + +volatile uint8_t radio_mode; ///< Radio mode +volatile uint8_t radio_state = RADIO_UNKNOWN; ///< Radio state + +volatile cc1100_mode_callback_t cc1100_go_idle; ///< Function for going IDLE +volatile cc1100_mode_callback_t cc1100_go_receive; ///< Function for going RX +volatile cc1100_mode_callback_t cc1100_go_after_tx; ///< Function to call after TX (burst send) +volatile cc1100_mode_callback_t cc1100_setup_mode; ///< Function to set up selected mode (RX or WOR) + +volatile int wor_hwtimer_id = -1; + +/*---------------------------------------------------------------------------*/ +// Low-level hardware access +/*---------------------------------------------------------------------------*/ + +void cc1100_disable_interrupts(void) +{ + cc1100_gdo2_disable(); + cc1100_gdo0_disable(); +} + +void cc1100_gdo0_irq(void) +{ + // Air was not free -> Clear CCA flag + rflags.CAA = false; + // Disable carrier sense detection (GDO0 interrupt) + cc1100_gdo0_disable(); +} + +void cc1100_gdo2_irq(void) +{ + cc1100_phy_rx_handler(); +} + +/*---------------------------------------------------------------------------*/ +// High level CC1100 SPI functions for transferring packet out +// of RX FIFO (don't call when in WOR mode) +/*---------------------------------------------------------------------------*/ + +static bool spi_receive_packet_variable(uint8_t *rxBuffer, uint8_t length) +{ + // Needed here for statistics + extern cc1100_statistic_t cc1100_statistic; + + uint8_t status[2]; + uint8_t packetLength = 0; + + // Any bytes available in RX FIFO? + if ((cc1100_spi_read_status(CC1100_RXBYTES) & BYTES_IN_RXFIFO)) + { + // Read length byte (first byte in RX FIFO) + packetLength = cc1100_spi_read_reg(CC1100_RXFIFO); + // Read data from RX FIFO and store in rxBuffer + if (packetLength <= length) + { + // Put length byte at first position in RX Buffer + rxBuffer[0] = packetLength; + + // Read the rest of the packet + cc1100_spi_readburst_reg(CC1100_RXFIFO, (char*)rxBuffer+1, packetLength); + + // Read the 2 appended status bytes (status[0] = RSSI, status[1] = LQI) + cc1100_spi_readburst_reg(CC1100_RXFIFO, (char*)status, 2); + + // Store RSSI value of packet + rflags.RSSI = status[I_RSSI]; + + // MSB of LQI is the CRC_OK bit + rflags.CRC = (status[I_LQI] & CRC_OK) >> 7; + if (!rflags.CRC) cc1100_statistic.packets_in_crc_fail++; + + // Bit 0-6 of LQI indicates the link quality (LQI) + rflags.LQI = status[I_LQI] & LQI_EST; + + return rflags.CRC; + } + else + { + // RX FIFO get automatically flushed if return value is false + return false; + } + } + else + { + // RX FIFO get automatically flushed if return value is false + return false; + } +} + +bool cc1100_spi_receive_packet(uint8_t *rxBuffer, uint8_t length) +{ + uint8_t pkt_len_cfg = cc1100_spi_read_reg(CC1100_PKTCTRL0) & PKT_LENGTH_CONFIG; + if (pkt_len_cfg == VARIABLE_PKTLEN) + { + return spi_receive_packet_variable(rxBuffer, length); + } + // Fixed packet length not supported. + // RX FIFO get automatically flushed if return value is false + return false; +} + +/*---------------------------------------------------------------------------*/ +// CC1100 mode functionality +/*---------------------------------------------------------------------------*/ + +void cc1100_set_idle(void) { + if (radio_state == RADIO_WOR) { + // Wake up the chip from WOR/sleep + cc1100_spi_select(); + hwtimer_wait(RTIMER_TICKS(122)); + cc1100_spi_unselect(); + radio_state = RADIO_IDLE; + // XOSC startup + FS calibration (300 + 809 us ~ 1.38 ms) + hwtimer_wait(FS_CAL_TIME); + return; + } + cc1100_spi_strobe(CC1100_SIDLE); + radio_state = RADIO_IDLE; +} + +static void wakeup_from_rx(void) +{ + if (radio_state != RADIO_RX) return; + cc1100_spi_strobe(CC1100_SIDLE); + radio_state = RADIO_IDLE; +} + +static void switch_to_rx(void) +{ + radio_state = RADIO_RX; + cc1100_spi_strobe(CC1100_SRX); +} + +static void setup_rx_mode(void) +{ + // Stay in RX mode until end of packet + cc1100_spi_write_reg(CC1100_MCSM2, 0x07); + switch_to_rx(); +} + +/** + * Note: It is possible that this code is executed in an ISR! + */ +static void wakeup_from_wor(void) +{ + if (radio_state != RADIO_WOR) { + return; + } + // Wake up the chip from WOR/sleep + cc1100_spi_select(); + hwtimer_wait(RTIMER_TICKS(122)); + cc1100_spi_unselect(); + radio_state = RADIO_IDLE; + // XOSC startup + FS calibration (300 + 809 us ~ 1.38 ms) + hwtimer_wait(FS_CAL_TIME); +} + +/** + * Note: This code is executed in the hwtimer ISR! + */ +void switch_to_wor2(void) +{ + if (cc1100_get_gdo2()) return; // If incoming packet, then don't go to WOR now + cc1100_spi_strobe(CC1100_SIDLE); // Put CC1100 to IDLE + radio_state = RADIO_IDLE; // Radio state now IDLE + cc1100_spi_write_reg(CC1100_MCSM2, + cc1100_wor_config.rx_time_reg); // Configure RX_TIME (for use in WOR) + cc1100_spi_write_reg(CC1100_MCSM0, 0x18); // Turn on FS-Autocal + if (rflags.WOR_RST) { + cc1100_spi_strobe(CC1100_SWORRST); // Resets the real time clock + rflags.WOR_RST = false; + } + cc1100_spi_strobe(CC1100_SWOR); // Put radio back to sleep/WOR (must be in IDLE when this is done) + radio_state = RADIO_WOR; // Radio state now WOR +} + +/** + * Note: This code is executed in the hwtimer ISR! + */ +static void hwtimer_switch_to_wor2_wrapper(void* ptr) +{ + wor_hwtimer_id = -1; // kernel timer handler function called, clear timer id + if (rflags.TX) return; // Stability: don't allow WOR timers at this point + rflags.WOR_RST = true; + switch_to_wor2(); +} + +/** + * Note: This code is executed in the hwtimer ISR! + */ +static void switch_to_wor(void) +{ + // Any incoming packet? + if (cc1100_get_gdo2()) + { + // Then don't go to WOR now + return; + } + + // Step 1: Set chip for random interval (1..RX_INTERVAL) to power down mode + if (!rflags.MAN_WOR) + { + rflags.MAN_WOR = true; + radio_state = RADIO_WOR; + // Go to power down mode + cc1100_spi_strobe(CC1100_SIDLE); + cc1100_spi_strobe(CC1100_SPWD); + + // Set timer to do second step of manual WOR + int r = (rand() / (double)(RAND_MAX + 1.0)) * (cc1100_wor_config.rx_interval * 100.0) + 20; + wor_hwtimer_id = hwtimer_set(r, cc1100_hwtimer_go_receive_wrapper, NULL); + if (wor_hwtimer_id == -1) + { + rflags.KT_RES_ERR = true; + // No hwtimer available, go immediately to WOR mode. + // Else never receiving packets again... + rflags.MAN_WOR = false; + switch_to_wor2(); + } + } + // Step 2: Go to RX and then to WOR mode again + else + { + rflags.MAN_WOR = false; + wakeup_from_wor(); + cc1100_spi_strobe(CC1100_SRX); + hwtimer_wait(IDLE_TO_RX_TIME); + radio_state = RADIO_RX; + // Register timer to go to WOR after RX timeout + wor_hwtimer_id = hwtimer_set((cc1100_wor_config.rx_time_ms * 100 + 150), + hwtimer_switch_to_wor2_wrapper, NULL); // add 1,5 ms secure time + if (wor_hwtimer_id == -1) + { + rflags.KT_RES_ERR = true; + } + } +} + +static void setup_wor_mode(void) +{ + // Wake up from WOR (if in WOR, else no effect) + cc1100_go_idle(); + + // Make sure CC1100 is in IDLE state + cc1100_spi_strobe(CC1100_SIDLE); + + // Enable automatic initial calibration of RCosc. + // Set T_event1 ~ 1.4 ms, enough for XOSC stabilize and FS calibration before RX. + // Enable RC oscillator before starting with WOR (or else it will not wake up). + // Not using AUTO_SYNC function. + cc1100_spi_write_reg(CC1100_WORCTRL, cc1100_wor_config.wor_ctrl); + + // Set Event0 timeout (RX polling interval) + cc1100_spi_write_reg(CC1100_WOREVT1, cc1100_wor_config.wor_evt_1); + cc1100_spi_write_reg(CC1100_WOREVT0, cc1100_wor_config.wor_evt_0); + + // Set RX time in WOR mode + cc1100_spi_write_reg(CC1100_MCSM2, cc1100_wor_config.rx_time_reg); + + // Enable automatic FS calibration when going from IDLE to RX/TX/FSTXON (in between EVENT0 and EVENT1) + cc1100_spi_write_reg(CC1100_MCSM0, 0x18); + + // Put the radio to SLEEP by starting Wake-on-Radio. + cc1100_spi_strobe(CC1100_SWORRST); // Resets the real time clock + cc1100_spi_strobe(CC1100_SWOR); // Starts Wake-on-Radio + radio_state = RADIO_WOR; +} + +static void switch_to_pwd(void) +{ + cc1100_go_idle(); + cc1100_spi_strobe(CC1100_SPWD); + radio_state = RADIO_PWD; +} + +uint8_t cc1100_get_mode(void) +{ + return radio_mode; +} + +static bool cc1100_set_mode0(uint8_t mode, uint16_t opt_mode_data) +{ + int result; + switch (mode) + { + case CC1100_MODE_WOR: + // Calculate WOR settings, store result (new burst count) + result = cc1100_phy_calc_wor_settings(opt_mode_data); + // If settings can be applied, set new mode and burst count + if (result != -1) + { + radio_mode = mode; + cc1100_go_idle = wakeup_from_wor; + cc1100_go_receive = switch_to_wor; + cc1100_go_after_tx = switch_to_wor2; + cc1100_setup_mode = setup_wor_mode; + cc1100_burst_count = result; + cc1100_retransmission_count_uc = TRANSMISSION_RETRIES_WOR_UC; + cc1100_retransmission_count_bc = TRANSMISSION_RETRIES_WOR_BC; + return true; + } + break; + case CC1100_MODE_CONSTANT_RX: + radio_mode = mode; + cc1100_go_idle = wakeup_from_rx; + cc1100_go_receive = switch_to_rx; + cc1100_go_after_tx = switch_to_rx; + cc1100_setup_mode = setup_rx_mode; + cc1100_burst_count = 1; + cc1100_retransmission_count_uc = TRANSMISSION_RETRIES_CRX_UC; + cc1100_retransmission_count_bc = TRANSMISSION_RETRIES_CRX_BC; + return true; + } + return false; +} + +bool cc1100_set_mode(uint8_t mode, uint16_t opt_mode_data) +{ + // Wake up from WOR/RX (if in WOR/RX, else no effect) + cc1100_go_idle(); + + // Make sure CC1100 is in IDLE state + cc1100_spi_strobe(CC1100_SIDLE); + + // Set the new mode + bool result = cc1100_set_mode0(mode, opt_mode_data); + + // If mode change was successful (mode is valid) + if (result) + { + // Setup new mode configuration + cc1100_setup_mode(); + // Reset statistics + cc1100_reset_statistic(); + return true; + } + else + { + // Still in old mode, go to receive mode again + cc1100_go_receive(); + return false; + } +} + +char* cc1100_mode_to_text(uint8_t mode) +{ + switch (mode) + { + case CC1100_MODE_WOR: + return "Wake-On-Radio"; + case CC1100_MODE_CONSTANT_RX: + return "Constant RX"; + default: + return "unknown"; + } +} + +char* cc1100_state_to_text(uint8_t state) +{ + switch (state) + { + case RADIO_UNKNOWN: + return "Unknown"; + case RADIO_AIR_FREE_WAITING: + return "CS"; + case RADIO_WOR: + return "WOR"; + case RADIO_IDLE: + return "IDLE"; + case RADIO_SEND_BURST: + return "TX BURST"; + case RADIO_RX: + return "RX"; + case RADIO_SEND_ACK: + return "TX ACK"; + case RADIO_PWD: + return "PWD"; + default: + return "unknown"; + } +} + +void cc1100_hwtimer_go_receive_wrapper(void *ptr) +{ + // kernel timer handler function called, clear timer id + wor_hwtimer_id = -1; + // Stability: don't allow WOR timers at this point + if (rflags.TX) return; + if (radio_state == RADIO_PWD) { + // Go to RX state, listen for packets as long as WOR_TIMEOUT_2 + cc1100_spi_strobe(CC1100_SRX); + hwtimer_wait(IDLE_TO_RX_TIME); + radio_state = RADIO_RX; + // Set hwtimer to put CC1100 back to WOR after WOR_TIMEOUT_2 + wor_hwtimer_id = hwtimer_set(WOR_TIMEOUT_2, cc1100_hwtimer_go_receive_wrapper, NULL); + if (wor_hwtimer_id == -1) + { + rflags.KT_RES_ERR = true; + // No hwtimer available, go immediately to WOR mode. + // Else never receiving packets again... + rflags.MAN_WOR = false; + switch_to_wor2(); + } + } else { + cc1100_go_receive(); + } +} + +/*---------------------------------------------------------------------------*/ +// CC1100 reset functionality +/*---------------------------------------------------------------------------*/ + +static void reset(void) +{ + cc1100_go_idle(); + cc1100_spi_select(); + cc1100_spi_strobe(CC1100_SRES); + hwtimer_wait(RTIMER_TICKS(10)); +} + +static void power_up_reset(void) +{ + cc1100_spi_unselect(); + cc1100_spi_cs(); + cc1100_spi_unselect(); + hwtimer_wait(RESET_WAIT_TIME); + reset(); + radio_state = RADIO_IDLE; +} + +/*---------------------------------------------------------------------------*/ +// CC1100 low level send function +/*---------------------------------------------------------------------------*/ + +void cc1100_send_raw(uint8_t *tx_buffer, uint8_t size) +{ + volatile uint32_t abort_count; + // The number of bytes to be transmitted must be smaller + // or equal to PACKET_LENGTH (62 bytes). So the receiver + // can put the whole packet in its RX-FIFO (with appended + // packet status bytes). + if (size > PACKET_LENGTH) return; + + // Disables RX interrupt etc. + cc1100_before_send(); + + // But CC1100 in IDLE mode to flush the FIFO + cc1100_spi_strobe(CC1100_SIDLE); + // Flush TX FIFO to be sure it is empty + cc1100_spi_strobe(CC1100_SFTX); + // Write packet into TX FIFO + cc1100_spi_writeburst_reg(CC1100_TXFIFO, (char*) tx_buffer, size); + // Switch to TX mode + abort_count = 0; + unsigned int cpsr = disableIRQ(); + cc1100_spi_strobe(CC1100_STX); + // Wait for GDO2 to be set -> sync word transmitted + while (cc1100_get_gdo2() == 0) { + abort_count++; + if (abort_count > CC1100_SYNC_WORD_TX_TIME) { + // Abort waiting. CC1100 maybe in wrong mode + // e.g. sending preambles for always + puts("[CC1100 TX] fatal error\n"); + break; + } + } + restoreIRQ(cpsr); + // Wait for GDO2 to be cleared -> end of packet + while (cc1100_get_gdo2() != 0); + // Experimental - TOF Measurement + cc1100_after_send(); +} + +/*---------------------------------------------------------------------------*/ +// Various functions (mode safe - they can be called in any radio mode) +/*---------------------------------------------------------------------------*/ +uint8_t +read_register(uint8_t r) +{ + uint8_t result; + + // Save old radio state + uint8_t old_state = radio_state; + + // Wake up from WOR/RX (if in WOR/RX, else no effect) + cc1100_go_idle(); + result = cc1100_spi_read_reg(r); + // Have to put radio back to WOR/RX if old radio state + // was WOR/RX, otherwise no action is necessary + if (old_state == RADIO_WOR || old_state == RADIO_RX) { + cc1100_go_receive(); + } + + return result; +} + +static void +write_register(uint8_t r, uint8_t value) +{ + // Save old radio state + uint8_t old_state = radio_state; + + // Wake up from WOR/RX (if in WOR/RX, else no effect) + cc1100_go_idle(); + cc1100_spi_write_reg(r, value); + + // Have to put radio back to WOR/RX if old radio state + // was WOR/RX, otherwise no action is necessary + if (old_state == RADIO_WOR || old_state == RADIO_RX) { + cc1100_go_receive(); + } +} + +char* cc1100_get_output_power(char* buf) +{ + sprintf(buf, "%+i dBm", pa_table_dBm[pa_table_index]); + return buf; +} + +uint8_t cc1100_get_channel(void) +{ + return radio_channel; +} + +bool +cc1100_set_channel(uint8_t channr) +{ + if (channr > MAX_CHANNR) return false; + write_register(CC1100_CHANNR, channr*10); + radio_channel = channr; + return true; +} + +bool +cc1100_set_output_power(uint8_t pa_idx) +{ + if (pa_idx >= sizeof(pa_table)) return false; + write_register(CC1100_PATABLE, pa_table[pa_idx]); + pa_table_index = pa_idx; + return true; +} + +char* cc1100_get_marc_state(void) +{ + uint8_t state; + + // Save old radio state + uint8_t old_state = radio_state; + + // Read content of status register + state = cc1100_spi_read_status(CC1100_MARCSTATE) & MARC_STATE; + + // Make sure in IDLE state. + // Only goes to IDLE if state was RX/WOR + cc1100_go_idle(); + + // Have to put radio back to WOR/RX if old radio state + // was WOR/RX, otherwise no action is necessary + if (old_state == RADIO_WOR || old_state == RADIO_RX) { + cc1100_go_receive(); + } + + switch (state) + { + // Note: it is not possible to read back the SLEEP or XOFF state numbers + // because setting CSn low will make the chip enter the IDLE mode from the + // SLEEP (0) or XOFF (2) states. + case 1: return "IDLE"; + case 3: case 4: case 5: return "MANCAL"; + case 6: case 7: return "FS_WAKEUP"; + case 8: case 12: return "CALIBRATE"; + case 9: case 10: case 11: return "SETTLING"; + case 13: case 14: case 15: return "RX"; + case 16: return "TXRX_SETTLING"; + case 17: return "RXFIFO_OVERFLOW"; + case 18: return "FSTXON"; + case 19: case 20: return "TX"; + case 21: return "RXTX_SETTLING"; + case 22: return "TXFIFO_UNDERFLOW"; + default: return "UNKNOWN"; + } +} + +/* +static int8_t +rssi_2_dbm(uint8_t rssi) +{ + if (rssi >= 128) rssi -= 256; + rssi /= 2; + rssi -= 78; + return rssi; +}*/ + +/*---------------------------------------------------------------------------*/ +// Radio Driver API +/*---------------------------------------------------------------------------*/ +void cc1100_init(void) +{ + // Initialize SPI + cc1100_spi_init(); + + // Set default mode (with default (energy optimized) RX interval) + cc1100_set_mode0(CC1100_RADIO_MODE, T_RX_INTERVAL); + + // Load driver & reset + power_up_reset(); + + // Write configuration to configuration registers + extern char cc1100_conf[]; + cc1100_spi_writeburst_reg(0x00, cc1100_conf, CC1100_CONF_SIZE); + + // Write PATABLE (power settings) + cc1100_spi_write_reg(CC1100_PATABLE, pa_table[pa_table_index]); + + // Initialize Radio Flags + rflags.RSSI = 0x00; + rflags.LL_ACK = false; + rflags.CAA = false; + rflags.CRC = false; + rflags.SEQ = false; + rflags.MAN_WOR = false; + rflags.KT_RES_ERR = false; + rflags.TX = false; + rflags.WOR_RST = false; + + // Initialize physical layer + cc1100_phy_init(); + + // Set radio address of CC1100 + cc1100_set_address(radio_address); + + // Set default channel number + radio_channel = CC1100_DEFAULT_CHANNR; + + // Switch to desired mode (WOR or RX) + rd_set_mode(RADIO_MODE_ON); +} + +int cc1100_get_avg_transmission_duration(void) +{ + if (radio_mode == CC1100_MODE_WOR) { + // Transmission duration ~ RX interval + // Double value because of MAC delay. + return 2 * cc1100_wor_config.rx_interval; + } else { + // Transmission duration ~ 32 ms + // Double value because of MAC delay. + return 2 * 32; + } +} + +radio_address_t cc1100_get_address(void) +{ + return radio_address; +} + +bool cc1100_set_address(radio_address_t address) +{ + if (address < MIN_UID || address > MAX_UID) + { + return false; + } + + uint8_t id = (uint8_t) address; + if (radio_state != RADIO_UNKNOWN) + { + write_register(CC1100_ADDR, id); + } + + radio_address = id; + return true; +} + +static int +rd_set_mode(int mode) +{ + int result; + + // Get current radio mode + if (radio_state == RADIO_UNKNOWN || radio_state == RADIO_PWD) + { + result = RADIO_MODE_OFF; + } + else + { + result = RADIO_MODE_ON; + } + + switch (mode) + { + case RADIO_MODE_ON: + cc1100_init_interrupts(); // Enable interrupts + cc1100_setup_mode(); // Set chip to desired mode + break; + case RADIO_MODE_OFF: + cc1100_disable_interrupts(); // Disable interrupts + switch_to_pwd(); // Set chip to power down mode + break; + case RADIO_MODE_GET: + // do nothing, just return current mode + default: + // do nothing + break; + } + + // Return previous mode + return result; +} + +/*---------------------------------------------------------------------------*/ +// Carrier sense interface functions +/*---------------------------------------------------------------------------*/ + +void cc1100_cs_init(void) +{ + cc1100_go_idle(); // Wake CC1100 up from Wake-On-Radio mode + if (radio_state == RADIO_RX) // If radio in RX mode + { + cc1100_spi_strobe(CC1100_SIDLE); // Go back to IDLE for calibration + } + cc1100_spi_write_reg(CC1100_MCSM0, 0x08); // Turn off FS-Autocal + cc1100_spi_strobe(CC1100_SCAL); // Calibrate manually (721 us) + hwtimer_wait(MANUAL_FS_CAL_TIME); // Wait for calibration to finish before packet burst can start + radio_state = RADIO_AIR_FREE_WAITING; // Set status "waiting for air free" + cc1100_spi_write_reg(CC1100_MCSM2, 0x07); // Configure RX_TIME = Until end of packet (no timeout) + cc1100_spi_strobe(CC1100_SRX); // Switch to RX (88.4 us) (Carrier Sense) + hwtimer_wait(CS_READY_TIME); // Wait until CC1100 is in RX + carrier sense ready (GDO0 ready for readout -> data rate dependent!!!) +} + +void cc1100_cs_set_enabled(bool enabled) +{ + if (enabled) + { + // Enable carrier sense detection (GDO0 interrupt) + cc1100_gdo0_enable(); + } + else + { + // Disable carrier sense detection (GDO0 interrupt) + cc1100_gdo0_disable(); + } +} + +int cc1100_cs_read(void) +{ + /* GDO0 reflects CS (high: air not free, low: air free) */ + return cc1100_get_gdo0(); +} + +int cc1100_cs_read_cca(void) +{ + return rflags.CAA; +} + +void cc1100_cs_write_cca(const int cca) +{ + rflags.CAA = cca; +} +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/drivers/cc110x/cc1100.h b/drivers/cc110x/cc1100.h new file mode 100644 index 0000000000..2143e853a6 --- /dev/null +++ b/drivers/cc110x/cc1100.h @@ -0,0 +1,348 @@ +/****************************************************************************** +Copyright 2008, Freie Universitaet Berlin (FUB). All rights reserved. + +These sources were developed at the Freie Universitaet Berlin, Computer Systems +and Telematics group (http://cst.mi.fu-berlin.de). +------------------------------------------------------------------------------- +This file is part of FeuerWare. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +FeuerWare is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see http://www.gnu.org/licenses/ . +-------------------------------------------------------------------------------- +For further information and questions please use the web site + http://scatterweb.mi.fu-berlin.de +and the mailinglist (subscription via web site) + scatterweb@lists.spline.inf.fu-berlin.de +*******************************************************************************/ + +/** + * @defgroup dev_cc110x TI Chipcon CC110x radio driver + * @ingroup dev + * + *

Quick links

+ * \li \ref cc1100_packet_layer0_t MAC packet format + * + *
+ * @{ + */ + +/** + * @file + * @brief TI Chipcon CC110x radio driver + * + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @author Thomas Hillebrandt + * @author Heiko Will + * @version $Revision: 2128 $ + * + * @note $Id: cc1100.h 2128 2010-05-12 12:07:59Z hillebra $ + */ + +#ifndef CC1100_H +#define CC1100_H + +#include +#include "cc1100-interface.h" + +/** + * @name Defines used as state values for state machine + * @{ + */ +#define RADIO_UNKNOWN (0) +#define RADIO_AIR_FREE_WAITING (1) +#define RADIO_WOR (2) +#define RADIO_IDLE (3) +#define RADIO_SEND_BURST (4) +#define RADIO_RX (5) +#define RADIO_SEND_ACK (6) +#define RADIO_PWD (7) + +/** @} */ + +/** CC1100 register configuration */ +typedef struct cc1100_reg { + uint8_t IOCFG2; + uint8_t IOCFG1; + uint8_t IOCFG0; + uint8_t FIFOTHR; + uint8_t SYNC1; + uint8_t SYNC0; + uint8_t PKTLEN; + uint8_t PKTCTRL1; + uint8_t PKTCTRL0; + uint8_t ADDR; + uint8_t CHANNR; + uint8_t FSCTRL1; + uint8_t FSCTRL0; + uint8_t FREQ2; + uint8_t FREQ1; + uint8_t FREQ0; + uint8_t MDMCFG4; + uint8_t MDMCFG3; + uint8_t MDMCFG2; + uint8_t MDMCFG1; + uint8_t MDMCFG0; + uint8_t DEVIATN; + uint8_t MCSM2; + uint8_t MCSM1; + uint8_t MCSM0; + uint8_t FOCCFG; + uint8_t BSCFG; + uint8_t AGCCTRL2; + uint8_t AGCCTRL1; + uint8_t AGCCTRL0; + uint8_t WOREVT1; + uint8_t WOREVT0; + uint8_t WORCTRL; + uint8_t FREND1; + uint8_t FREND0; + uint8_t FSCAL3; + uint8_t FSCAL2; + uint8_t FSCAL1; + uint8_t FSCAL0; +} cc1100_reg_t; + +/** CC1100 radio configuration */ +typedef struct cc1100_cfg_t { + cc1100_reg_t reg_cfg; ///< CC1100 register configuration + uint8_t pa_power; ///< Output power setting +} cc1100_cfg_t; + +/** + * @brief Radio Control Flags + */ +typedef struct cc1100_flags +{ + uint32_t TOF; ///< Time of flight of the last packet and last ACK + uint32_t TCP; ///< Time to compute packet + unsigned RPS : 16; ///< Raw packets sent to transmit last packet + unsigned RTC : 8; ///< Retransmission count of last send packet + unsigned RSSI : 8; ///< The RSSI value of last received packet + unsigned RSSI_SEND : 8; ///< The RSSI value of the last send unicast packet of this node + unsigned LQI : 8; ///< The LQI value of the last received packet + unsigned LL_ACK : 1; ///< Is set if Link-Level ACK is received, otherwise 0 (reset on new burst) + unsigned CAA : 1; ///< The status of the air (1 = air free, 0 = air not free) + unsigned CRC : 1; ///< The CRC status of last received packet (1 = OK, 0 = not OK) + unsigned SEQ : 1; ///< Sequence number (toggles between 0 and 1) + unsigned MAN_WOR : 1; ///< Manual WOR set (for randomized WOR times => no synch) + unsigned KT_RES_ERR : 1; ///< A hwtimer resource error has occurred (no free timers available) + unsigned TX : 1; ///< State machine TX lock, only ACKs will be received + unsigned WOR_RST : 1; ///< Reset CC1100 real time clock (WOR) on next WOR strobe +} cc1100_flags; + +/** + * @brief Statistic interface for debugging + */ +typedef struct cc1100_statistic { + uint32_t packets_in; + uint32_t packets_in_crc_fail; + uint32_t packets_in_while_tx; + uint32_t packets_in_dups; + uint32_t packets_in_up; + uint32_t packets_out; + uint32_t packets_out_acked; + uint32_t packets_out_broadcast; + uint32_t raw_packets_out; + uint32_t raw_packets_out_acked; + uint32_t acks_send; + uint32_t rx_buffer_max; + uint32_t watch_dog_resets; +} cc1100_statistic_t; + +enum radio_mode { + RADIO_MODE_GET = -1, ///< leave mode unchanged + RADIO_MODE_OFF = 0, ///< turn radio off + RADIO_MODE_ON = 1 ///< turn radio on +}; + +enum radio_result { + RADIO_PAYLOAD_TOO_LONG = -1, ///< payload too long + RADIO_WRONG_MODE = -2, ///< operation not supported in current mode + RADIO_ADDR_OUT_OF_RANGE = -3, ///< address out of range + RADIO_OP_FAILED = -4, ///< operation failed + RADIO_CS_TIMEOUT = -5, ///< Carrier Sense timeout: air was never free + RADIO_INVALID_PARAM = -6 ///< Invalid parameters passed to radio +}; + +/* ------------------------------------------------------------------------- */ +// Variable declarations (also used in other files) +/* ------------------------------------------------------------------------- */ + +extern volatile cc1100_flags rflags; ///< Radio flags + +extern volatile uint8_t radio_mode; ///< Radio mode +extern volatile uint8_t radio_state; ///< Radio state + +/** Mode callback functions */ +typedef void (*cc1100_mode_callback_t)(void); +extern volatile cc1100_mode_callback_t cc1100_go_idle; +extern volatile cc1100_mode_callback_t cc1100_go_receive; +extern volatile cc1100_mode_callback_t cc1100_go_after_tx; +extern volatile cc1100_mode_callback_t cc1100_setup_mode; + +extern volatile int wor_hwtimer_id; ///< WOR hwtimer identifier + +/* ------------------------------------------------------------------------- */ +// CC1100 radio driver API +/* ------------------------------------------------------------------------- */ + +/** + * @brief Set chip and state machine to IDLE mode. + */ +void cc1100_set_idle(void); + +/** + * @brief Convert radio mode to textual representation. + * + * @param mode The radio mode to convert. + * + * @return Textual representation of radio mode. + */ +char* cc1100_mode_to_text(uint8_t mode); + +/** + * @brief Convert radio state to textual representation. + * + * @param mode The radio state to convert. + * + * @return Textual representation of radio state. + */ +char* cc1100_state_to_text(uint8_t state); + +/** + * @brief Convert current output power to textual representation. + * + * @return Textual representation of current output power in dBm. + */ +char* cc1100_get_output_power(char* buf); + +/** + * @brief Read out main radio control FSM state. + * + * @return Textual representation of current main radio control FSM state. + */ +char* cc1100_get_marc_state(void); + +/** + * @brief hwtimer wrapper function. + * + * This wrapper function puts the radio to receive mode. + * + * @param ptr Optional data (only to match hwtimer interface). + */ +void cc1100_hwtimer_go_receive_wrapper(void *ptr); + +/** + * @brief GDO0 interrupt handler. + */ +void cc1100_gdo0_irq(void); + +/** + * @brief GDO2 interrupt handler. + * + * @note Wakes up MCU on packet reception. + */ +void cc1100_gdo2_irq(void); + +/** + * @brief Transfer packet from CC1100 RX FIFO. + * + * Transfers a packet from CC1100 RX FIFO into a buffer. + * + * @param rxBuffer The buffer in which to transfer the packet. + * @param length The size of the buffer in which to transfer the packet. + * + * @return true if operation succeeded; false otherwise (e.g. no data + * available, buffer to small or CRC check failed). + */ +bool cc1100_spi_receive_packet(uint8_t *rxBuffer, uint8_t length); + +/** + * @brief Sends raw data. + * + * Sends the data of the given buffer. The first two bytes of the + * buffer must match the CC1100 packet format (so address interpretation + * succeeds). + *

+ * This function is not mode safe! The radio must be woke up before + * sending and has to be put back manually to receive mode. + * + * @param tx_buffer Data source buffer. + * @param size The size of the data source buffer (maximum: 62 bytes). + */ +void cc1100_send_raw(uint8_t *tx_buffer, uint8_t size); + +/** + * @name Carrier Sense interface + * @{ + */ + +/** + * @brief Initialize radio for carrier sense detection. + */ +void cc1100_cs_init(void); + +/** + * @brief Enable or disable carrier sense detections. + * + * Turns interrupts for carrier sense on or off. + * + * @param enabled true if carrier sense detection should + * be enabled; false otherwise. + */ +void cc1100_cs_set_enabled(bool enabled); + +/** + * @brief Read carrier sense signal. + * + * @return High (1) if air is not free; low (0) if air is + * currently free. + */ +int cc1100_cs_read(void); + +/** + * @brief Reads the CCA (Clear Channel Assessment) flag. + * + * The CCA flag is set by an interrupt service routine, after + * carrier sense detection is enabled. So the status of the + * carrier sense signal can be evaluated in a non blocking + * manner. + * + * @return The current value of the CCA flag (High: air is free, + * low: air is not free). + */ +int cc1100_cs_read_cca(void); + +/** + * @brief Sets the CCA flag. + * + * @param cca The new value for the CCA flag. + */ +void cc1100_cs_write_cca(const int cca); + +/** @} */ + +/** + * @name Statistic interface + * @{ + */ + +/** + * @brief Reset radio statistics. + */ +void cc1100_reset_statistic(void); + +/** @} */ + +/** @} */ + +#endif diff --git a/drivers/cc110x/cc1100_phy.c b/drivers/cc110x/cc1100_phy.c new file mode 100644 index 0000000000..036792ee2e --- /dev/null +++ b/drivers/cc110x/cc1100_phy.c @@ -0,0 +1,863 @@ +/****************************************************************************** +Copyright 2008, Freie Universitaet Berlin (FUB). All rights reserved. + +These sources were developed at the Freie Universitaet Berlin, Computer Systems +and Telematics group (http://cst.mi.fu-berlin.de). +------------------------------------------------------------------------------- +This file is part of FeuerWare. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +FeuerWare is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see http://www.gnu.org/licenses/ . +-------------------------------------------------------------------------------- +For further information and questions please use the web site + http://scatterweb.mi.fu-berlin.de +and the mailinglist (subscription via web site) + scatterweb@lists.spline.inf.fu-berlin.de +*******************************************************************************/ + +/** + * @ingroup dev_cc110x + * @{ + */ + +/** + * @file + * @internal + * @brief TI Chipcon CC110x physical radio driver + * + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @author Thomas Hillebrandt + * @author Heiko Will + * @version $Revision: 2130 $ + * + * @note $Id: cc1100_phy.c 2130 2010-05-12 13:19:07Z hillebra $ + */ +#include +#include + +#include "hwtimer.h" +#include "swtimer.h" + +#include "cc1100.h" +#include "cc1100_spi.h" +#include "cc1100_phy.h" +#include "cc1100-defaultSettings.h" + +#include "protocol-multiplex.h" + +#include "kernel.h" +#include "thread.h" +#include "mutex.h" +#include "msg.h" +#include "debug.h" + +#define MSG_POLL 12346 + +#define FLAGS_IDENTIFICATION (0x01) ///< Bit mask for reading the identification out of the flags field +#define R_FLAGS_PROTOCOL(x) ((x & 0x0E)>>1) ///< Macro for reading the protocol out of the flags field +#define W_FLAGS_PROTOCOL(x) ((x<<1) & 0x0E) ///< Macro for writing the protocol in the flags field + +/*---------------------------------------------------------------------------*/ +// RX/TX buffer data structures +/*---------------------------------------------------------------------------*/ + +typedef struct rx_buffer_t +{ + cc1100_packet_layer0_t packet; + packet_info_t info; +} rx_buffer_t; + +#define RX_BUFF_SIZE (10) ///< Size of RX queue +static volatile uint8_t rx_buffer_head; ///< RX queue head +static volatile uint8_t rx_buffer_tail; ///< RX queue tail +static volatile uint8_t rx_buffer_size; ///< RX queue size +static rx_buffer_t rx_buffer[RX_BUFF_SIZE]; ///< RX buffer +static cc1100_packet_layer0_t tx_buffer; ///< TX buffer (for one packet) + +/*---------------------------------------------------------------------------*/ +// Process/Event management data structures +/*---------------------------------------------------------------------------*/ + +#define MAX_PACKET_HANDLERS (5) +static packet_monitor_t packet_monitor; +static handler_entry_t handlers[MAX_PACKET_HANDLERS]; +static const pm_table_t handler_table; +static const char *cc1100_event_handler_name = "cc1100_event_handler"; +static mutex_t cc1100_mutex; +volatile int cc1100_mutex_pid; +static uint16_t cc1100_event_handler_pid; +static void cc1100_event_handler_function(void); +static swtimer_t cc1100_watch_dog; +static uint64_t cc1100_watch_dog_period = 0; + +/*---------------------------------------------------------------------------*/ +// Sequence number buffer management data structures +/*---------------------------------------------------------------------------*/ + +/** + * @name Sequence Buffer + * @{ + */ +#define MAX_SEQ_BUFFER_SIZE (20) ///< Maximum size of the sequence number buffer + +typedef struct +{ + uint64_t m_ticks; ///< 64-bit timestamp + uint8_t source; ///< Source address + uint8_t identification; ///< Identification (1-bit) +} seq_buffer_entry; + +/// Sequence number buffer for this layer +static seq_buffer_entry seq_buffer[MAX_SEQ_BUFFER_SIZE]; + +/// Next position to enter a new value into ::seqBuffer +static uint8_t seq_buffer_pos = 0; + +/** + * @brief Last sequence number this node has seen + * + * @note (phySrc + flags.identification) - for speedup in ISR. + */ +static volatile uint16_t last_seq_num = 0; + +/** @} */ + +/*---------------------------------------------------------------------------*/ +// WOR configuration data structures +/*---------------------------------------------------------------------------*/ + +#define EVENT0_MAX (60493) ///< Maximum RX polling interval in milliseconds +#define WOR_RES_SWITCH (1891) ///< Switching point value in milliseconds between + ///< WOR_RES = 0 and WOR_RES = 1 +#define DUTY_CYCLE_SIZE (7) ///< Length of duty cycle array + +cc1100_wor_config_t cc1100_wor_config; ///< CC1100 WOR configuration + +uint16_t cc1100_burst_count; ///< Burst count, number of packets in a burst transfer +uint8_t cc1100_retransmission_count_uc; ///< Number of retransmissions for unicast +uint8_t cc1100_retransmission_count_bc; ///< Number of retransmissions for broadcast + +const static double duty_cycle[2][DUTY_CYCLE_SIZE] = ///< Duty cycle values from AN047 +{ + {12.5, 6.25, 3.125, 1.563, 0.781, 0.391, 0.195}, + {1.95, 0.9765, 0.4883, 0.2441, 0.1221, 0.061035, 0.030518} +}; + +/*---------------------------------------------------------------------------*/ +// Data structures for statistic +/*---------------------------------------------------------------------------*/ + +cc1100_statistic_t cc1100_statistic; + +/*---------------------------------------------------------------------------*/ +// Initialization of physical layer +/*---------------------------------------------------------------------------*/ + +void cc1100_phy_init() +{ + int i; + + rx_buffer_head = 0; + rx_buffer_tail = 0; + rx_buffer_size = 0; + + // Initialize RX-Buffer (clear content) + for (i = 0; i < RX_BUFF_SIZE; i++) + { + rx_buffer->packet.length = 0; + } + + // Initialize handler table & packet monitor + packet_monitor = NULL; + pm_init_table((pm_table_t*)&handler_table, MAX_PACKET_HANDLERS, handlers); + + // Clear sequence number buffer + memset(seq_buffer, 0, sizeof(seq_buffer_entry) * MAX_SEQ_BUFFER_SIZE); + + // Initialize mutex + cc1100_mutex_pid = -1; + mutex_init(&cc1100_mutex); + + // Allocate event numbers and start cc1100 event process + cc1100_event_handler_pid = thread_create(2500, PRIORITY_CC1100, CREATE_STACKTEST, + cc1100_event_handler_function, cc1100_event_handler_name); + + // Active watchdog for the first time + if (radio_mode == CC1100_MODE_CONSTANT_RX) { + cc1100_watch_dog_period = CC1100_WATCHDOG_PERIOD; + if (cc1100_watch_dog_period != 0) { + swtimer_set_msg(&cc1100_watch_dog, 5000000L, cc1100_event_handler_pid, NULL); + } + } +} + +/*---------------------------------------------------------------------------*/ +// CC1100 mutual exclusion +/*---------------------------------------------------------------------------*/ + +void cc1100_phy_mutex_lock(void) +{ + if (fk_thread->pid != cc1100_mutex_pid) { + mutex_lock(&cc1100_mutex); + cc1100_mutex_pid = fk_thread->pid; + } +} + +void cc1100_phy_mutex_unlock(void) +{ + cc1100_mutex_pid = -1; + mutex_unlock(&cc1100_mutex, 0); +} + +/*---------------------------------------------------------------------------*/ +// Statistical functions +/*---------------------------------------------------------------------------*/ + +void cc1100_reset_statistic(void) +{ + cc1100_statistic.packets_in_up = 0; + cc1100_statistic.acks_send = 0; + cc1100_statistic.packets_out_acked = 0; + cc1100_statistic.packets_in = 0; + cc1100_statistic.packets_out = 0; + cc1100_statistic.packets_out_broadcast = 0; + cc1100_statistic.raw_packets_out_acked = 0; + cc1100_statistic.raw_packets_out = 0; + cc1100_statistic.packets_in_dups = 0; + cc1100_statistic.packets_in_crc_fail = 0; + cc1100_statistic.packets_in_while_tx = 0; + cc1100_statistic.rx_buffer_max = 0; + cc1100_statistic.watch_dog_resets = 0; +} + +void cc1100_print_statistic(void) +{ + printf("\nStatistic on CC1100 interface\n\n"); + printf("Total packets send on layer 0.5 (broadcast): %lu\n", cc1100_statistic.packets_out_broadcast); + printf("Total packets send on layer 0.5 (unicast): %lu\n", cc1100_statistic.packets_out); + printf("Total packets Acked on layer 0.5: %lu (%.2f%%)\n", cc1100_statistic.packets_out_acked, cc1100_statistic.packets_out_acked * (100.0f / (float)cc1100_statistic.packets_out)); + printf("Total packets send on layer 0: %lu\n", cc1100_statistic.raw_packets_out); + printf("Total packets send on layer 0 w. Ack on Layer 0.5: %lu (Avg. Ack after: %lu packets)\n", cc1100_statistic.raw_packets_out_acked, cc1100_statistic.raw_packets_out_acked / cc1100_statistic.packets_out_acked); + printf("Burst count on this node: %i (%.2f%%)\n", cc1100_burst_count, (100/(float)cc1100_burst_count) * (cc1100_statistic.raw_packets_out_acked / (float) cc1100_statistic.packets_out_acked)); + printf("Total packets In on layer 0: %lu\n", cc1100_statistic.packets_in); + printf("Duped packets In on layer 0: %lu\n", cc1100_statistic.packets_in_dups); + printf("Corrupted packets In on layer 0: %lu\n", cc1100_statistic.packets_in_crc_fail); + printf("Packets In on layer 0 while in TX: %lu\n", cc1100_statistic.packets_in_while_tx); + printf("Total packets In and up to layer 1: %lu (%.2f%%)\n", cc1100_statistic.packets_in_up, cc1100_statistic.packets_in_up * (100.0f / (float)cc1100_statistic.packets_in)); + printf("Total Acks send on layer 0.5: %lu\n", cc1100_statistic.acks_send); + printf("RX Buffer max: %lu (now: %u)\n", cc1100_statistic.rx_buffer_max, rx_buffer_size); + printf("State machine resets by cc1100 watchdog: %lu\n", cc1100_statistic.watch_dog_resets); +} + +void cc1100_print_config(void) +{ + char buf[8]; + printf("Current radio mode: %s\r\n", cc1100_mode_to_text(radio_mode)); + printf("Current radio state: %s\r\n", cc1100_state_to_text(radio_state)); + printf("Current MARC state: %s\r\n", cc1100_get_marc_state()); + printf("Current channel number: %u\r\n", cc1100_get_channel()); + printf("Burst count: %u packet(s)\r\n", cc1100_burst_count); + printf("Retransmissions (unicast): %u - if no ACK\r\n", cc1100_retransmission_count_uc); + printf("Retransmissions (broadcast): %u - always\r\n", cc1100_retransmission_count_bc); + printf("Output power setting: %s\r\n", cc1100_get_output_power(buf)); + if (radio_mode == CC1100_MODE_WOR) + { + printf("RX polling interval: %u ms\r\n", cc1100_wor_config.rx_interval); + printf("WOR receive time: 0x%.2X (%f ms)\r\n", cc1100_wor_config.rx_time_reg, + cc1100_wor_config.rx_time_ms); + printf("CC1100 WOREVT0 register: 0x%.2X\r\n", cc1100_wor_config.wor_evt_0); + printf("CC1100 WOREVT1 register: 0x%.2X\r\n", cc1100_wor_config.wor_evt_1); + printf("CC1100 WOR_CTRL register: 0x%.2X\r\n", cc1100_wor_config.wor_ctrl); + printf("CC1100 MAN_WOR flag: %u\r\n", rflags.MAN_WOR); + } +} + +/*---------------------------------------------------------------------------*/ +// Change of RX polling interval (T_EVENT0) +/*---------------------------------------------------------------------------*/ + +inline uint16_t iround(double d) +{ + return (uint16_t) d<0?d-.5:d+.5; +} + +int cc1100_phy_calc_wor_settings(uint16_t millis) +{ + // Get packet interval as milliseconds + double t_packet_interval = (double) ((T_PACKET_INTERVAL) / 1000.0); + + // Calculate minimal T_EVENT0: + // + // (1) t_rx_time > t_packet_interval + // (2) t_rx_time = T_EVENT0 / 2 ^ (RX_TIME + 3 + WOR_RES) + // ------------------------------------------------------ + // with RX_TIME = 0 && WOR_RES = 0 => event0_min > t_packet_interval * 8 + // + // t_packet_interval = 3.8 ms (@400kbit/s) + // + // => event0_min = Math.ceil(3.8 * 8) + 10 + uint16_t event0_min = (uint16_t)(t_packet_interval * 8) + 1 + 10; + + // Check if given value is in allowed range + if (millis < event0_min || millis > EVENT0_MAX) + { + return -1; + } + + // Time resolution for EVENT0 and other WOR parameters, + // possible values are 0 and 1 if WOR is used + uint8_t wor_res = millis < WOR_RES_SWITCH ? 0 : 1; + + // Calculate new value for EVENT0 + double tmp = (millis * 26) / (double) 750; + if (wor_res == 1) tmp /= 32; + tmp *= 1000; + uint16_t event0 = (uint16_t) iround(tmp); + + // Calculate all possible RX timeouts + int i; + double rx_timeouts[DUTY_CYCLE_SIZE]; + for (i = 0; i < DUTY_CYCLE_SIZE; i++) + { + rx_timeouts[i] = (millis * duty_cycle[wor_res][i]) / 100; + } + + // Calculate index for optimal rx_timeout (MCSM2.RX_TIME) (if possible) + int idx = -1; + for (i = DUTY_CYCLE_SIZE - 1; i >= 0; i--) + { + if (rx_timeouts[i] > t_packet_interval) + { + idx = i; + break; + } + } + + // If no index found, exit here (configuration with given value is not possible) + if (idx == -1) return -1; + + // Calculate burst count (secure burst calculation with 8 extra packets) + int burst_count = (int) iround(millis / t_packet_interval) + 8; + + // All calculations successful, now its safe to store + // final configuration values in global WOR configuration + cc1100_wor_config.rx_interval = millis; + cc1100_wor_config.wor_ctrl = (wor_res == 0) ? 0x78 : 0x79; + cc1100_wor_config.wor_evt_0 = (uint8_t) event0; + cc1100_wor_config.wor_evt_1 = (uint8_t) (event0 >> 8); + cc1100_wor_config.rx_time_reg = idx; + cc1100_wor_config.rx_time_ms = rx_timeouts[idx]; + + // If successful, return number of packets in a burst transfer + return burst_count; +} + +/*---------------------------------------------------------------------------*/ +// Sequence number buffer management +/*---------------------------------------------------------------------------*/ + +static bool contains_seq_entry(uint8_t src, uint8_t id) +{ + int i; + uint32_t cmp; + uint64_t now = swtimer_now(); + + for (i = 0; i < MAX_SEQ_BUFFER_SIZE; i++) + { + if ((seq_buffer[i].source == src) && (seq_buffer[i].identification == id)) + { + // Check if time stamp is OK + cmp = (radio_mode == CC1100_MODE_WOR) ? cc1100_wor_config.rx_interval : 16000; // constant RX ~16ms + if ((now - seq_buffer[i].m_ticks) <= cmp) + { + return true; + } + else + { + seq_buffer[i].source = 0; // Reset + } + } + } + return false; +} + +static void add_seq_entry(uint8_t src, uint8_t id) +{ + // Remove all entries with given source to avoid short time overflow + // of one bit counter (of the source node). So a valid packet would get + // lost (especially important in constant RX mode). + int i; + for (i = 0; i < MAX_SEQ_BUFFER_SIZE; i++) + { + if (seq_buffer[i].source == src) + { + seq_buffer[i].source = 0; // Reset + } + } + + // Add new entry + seq_buffer[seq_buffer_pos].source = src; + seq_buffer[seq_buffer_pos].identification = id; + seq_buffer[seq_buffer_pos].m_ticks = swtimer_now(); + + // Store 16 bit sequence number of layer 0 for speedup + last_seq_num = src; + last_seq_num <<= 8; + last_seq_num += id; + + seq_buffer_pos++; + if (seq_buffer_pos == MAX_SEQ_BUFFER_SIZE) seq_buffer_pos = 0; +} + +/*---------------------------------------------------------------------------*/ +// CC1100 physical layer send functions +/*---------------------------------------------------------------------------*/ + +static void send_link_level_ack(uint8_t dest) +{ + uint8_t oldState = radio_state; // Save old state + cc1100_packet_layer0_t ack; // Local packet, don't overwrite + + radio_state = RADIO_SEND_ACK; // Set state to "Sending ACK" + cc1100_spi_write_reg(CC1100_MCSM0, 0x08); // Turn off FS-Autocal + cc1100_spi_write_reg(CC1100_MCSM1, 0x00); // TX_OFFMODE = IDLE + ack.length = 3; // possible packet in txBuffer! + ack.address = dest; + ack.phy_src = rflags.RSSI; + ack.flags = (LAYER_1_PROTOCOL_LL_ACK << 1); + cc1100_send_raw((uint8_t*)&ack, // IDLE -> TX (88.4 us) + ack.length+1); + cc1100_spi_write_reg(CC1100_MCSM0, 0x18); // Turn on FS-Autocal + cc1100_spi_write_reg(CC1100_MCSM1, 0x03); // TX_OFFMODE = RX + radio_state = oldState; // Restore state + cc1100_statistic.acks_send++; +} + +static bool send_burst(cc1100_packet_layer0_t *packet, uint8_t retries, uint8_t rtc) +{ + int i; + radio_state = RADIO_SEND_BURST; + rflags.LL_ACK = false; + + for (i = 1; i <= cc1100_burst_count; i++) + { + /* + * Number of bytes to send is: + * length of phy payload (packet->length) + * + size of length field (1 byte) + */ + extern unsigned long hwtimer_now(void); + timer_tick_t t = hwtimer_now() + RTIMER_TICKS(T_PACKET_INTERVAL); + cc1100_send_raw((uint8_t*)packet, packet->length + 1); // RX -> TX (9.6 us) + + cc1100_statistic.raw_packets_out++; + + // Delay until predefined "send" interval has passed + timer_tick_t now = hwtimer_now(); + if (t > now) + { + hwtimer_wait(t - now); + } + + /** + * After sending the packet the CC1100 goes automatically + * into RX mode (21.5 us) (listening for an ACK). + * Do not interrupt burst if send to broadcast address (a node may + * have the broadcast address at startup and would stop the burst + * by sending an ACK). + */ + if (rflags.LL_ACK && packet->address != CC1100_BROADCAST_ADDRESS) + { + cc1100_statistic.raw_packets_out_acked += i; + break; + } + } + + // No link level ACK -> do retry if retry counter greater zero + // Note: Event broadcast packets can be sent repeatedly if in + // constant RX mode. In WOR mode it is not necessary, so + // set retry count to zero. + if (!rflags.LL_ACK && retries > 0) + { + return send_burst(packet, retries - 1, rtc + 1); + } + + // Store number of transmission retries + rflags.RTC = rtc; + rflags.RPS = rtc * cc1100_burst_count + i; + if (i > cc1100_burst_count) rflags.RPS--; + rflags.TX = false; + + // Go to mode after TX (CONST_RX -> RX, WOR -> WOR) + cc1100_go_after_tx(); + + // Burst from any other node is definitely over + last_seq_num = 0; + + if (packet->address != CC1100_BROADCAST_ADDRESS && !rflags.LL_ACK) + { + return false; + } + + return true; +} + +int cc1100_send(radio_address_t addr, protocol_t protocol, int priority, char *payload, int payload_len) +{ + bool result; + int return_code; + uint8_t address; + uint8_t retries; + + // Lock mutex, nobody else should send now + cc1100_phy_mutex_lock(); + + // TX state machine lock -> no timers (WOR), no packets (only ACKs) + rflags.TX = true; + + // Set chip to idle state + cc1100_set_idle(); + + // CC1100 radio layer only supports 8-bit addresses + address = addr; + + // Loopback not supported + if (address == cc1100_get_address()) + { + return_code = RADIO_ADDR_OUT_OF_RANGE; + goto mode_before_final; + } + + // Check address + if (address > MAX_UID) + { + return_code = RADIO_ADDR_OUT_OF_RANGE; + goto mode_before_final; + } + + // Packet too long + if (payload_len > MAX_DATA_LENGTH) + { + return_code = RADIO_PAYLOAD_TOO_LONG; + goto mode_before_final; + } + + if (radio_state == RADIO_PWD) + { + return_code = RADIO_WRONG_MODE; + goto mode_before_final; + } + + // Set number of transmission retries + retries = (address == CC1100_BROADCAST_ADDRESS) ? + cc1100_retransmission_count_bc : cc1100_retransmission_count_uc; + + memset(tx_buffer.data, 0, MAX_DATA_LENGTH); // Clean data + + tx_buffer.length = 3 + MAX_DATA_LENGTH; // 3 bytes (A&PS&F) + data length + tx_buffer.address = address; // Copy destination address + tx_buffer.flags = 0x00; // Set clean state + tx_buffer.flags = W_FLAGS_PROTOCOL(protocol); // Copy protocol identifier + tx_buffer.phy_src = (uint8_t) cc1100_get_address(); // Copy sender address + + // Set identification number of packet + tx_buffer.flags |= rflags.SEQ; // Set flags.identification (bit 0) + rflags.SEQ = !rflags.SEQ; // Toggle value of layer 0 sequence number bit + + memcpy(tx_buffer.data, payload, payload_len); // Copy data + + // Send the packet + cc1100_spi_write_reg(CC1100_MCSM0, 0x08); // Turn off FS-Autocal + result = send_burst(&tx_buffer, retries, 0); // Send raw burst + return_code = result ? payload_len : RADIO_OP_FAILED; + + // Collect statistics + if (address != CC1100_BROADCAST_ADDRESS) + { + cc1100_statistic.packets_out++; + if (result) cc1100_statistic.packets_out_acked++; + } + else cc1100_statistic.packets_out_broadcast++; + + goto final; + + mode_before_final: + rflags.TX = false; + // Definitely set secure mode (CONST_RX -> RX, WOR -> WOR) + cc1100_go_after_tx(); + + final: + // Release mutex and return + cc1100_phy_mutex_unlock(); + return return_code; +} + +/*---------------------------------------------------------------------------*/ +// RX Event Handler +/*---------------------------------------------------------------------------*/ + +bool cc1100_set_packet_monitor(packet_monitor_t monitor) +{ + packet_monitor = monitor; + return true; +} + +int cc1100_set_packet_handler(protocol_t protocol, packet_handler_t handler) +{ + if (protocol > 7) return -1; // Only 3-bit value allowed + return pm_set_handler(&handler_table, protocol, handler); +} + +static void cc1100_event_handler_function(void) +{ + msg m; + while (1) + { + if (cc1100_watch_dog_period != 0) { + swtimer_remove(&cc1100_watch_dog); + } + // Test if any resource error has occurred + if (rflags.KT_RES_ERR) + { + rflags.KT_RES_ERR = false; + // possibly do something, e.g. log error condition + } + if (m.type == MSG_TIMER) + { + uint8_t state; + if (radio_mode == CC1100_MODE_CONSTANT_RX) { + state = cc1100_spi_read_status(CC1100_MARCSTATE) & MARC_STATE; + if ((state < 13 || state > 15) && radio_state == RADIO_RX && !rflags.TX) { + cc1100_statistic.watch_dog_resets++; + if (state != 1) { + cc1100_spi_strobe(CC1100_SIDLE); + } + cc1100_spi_strobe(CC1100_SFRX); + cc1100_go_receive(); + } + } else { + // Radio mode is WOR, cannot read current MARC state, will + // always be IDLE. So do nothing here, e.g. disable watchdog. + } + } + while (rx_buffer_size > 0) + { + rx_buffer_t* packet = &rx_buffer[rx_buffer_head]; + protocol_t p = R_FLAGS_PROTOCOL(packet->packet.flags); + if (packet_monitor != NULL) packet_monitor((void*)&packet->packet.data, MAX_DATA_LENGTH, p, &packet->info); + pm_invoke(&handler_table, p, (void*)&packet->packet.data, MAX_DATA_LENGTH, &packet->info); + dINT(); + rx_buffer_size--; + rx_buffer_head++; + if (rx_buffer_head == RX_BUFF_SIZE) rx_buffer_head = 0; + eINT(); + } + dINT(); + if (rx_buffer_size == 0) + { + if (cc1100_watch_dog_period != 0) { + swtimer_set_msg(&cc1100_watch_dog, cc1100_watch_dog_period * 1000000L, + cc1100_event_handler_pid, NULL); + } + msg_receive(&m); + } + eINT(); + } +} + +/*---------------------------------------------------------------------------*/ +// CC1100 packet (RX) ISR +/*---------------------------------------------------------------------------*/ + +void cc1100_phy_rx_handler(void) +{ + msg m; + m.type = MSG_POLL; + bool dup = false; + bool res = false; + + // Possible packet received, RX -> IDLE (0.1 us) + rflags.CAA = false; + rflags.MAN_WOR = false; + cc1100_statistic.packets_in++; + + // If WOR timer set, delete it now (new one will be set at end of ISR) + if (wor_hwtimer_id != -1) + { + hwtimer_remove(wor_hwtimer_id); + wor_hwtimer_id = -1; + } + + // Transfer packet into temporary buffer position + res = cc1100_spi_receive_packet((uint8_t*)&(rx_buffer[rx_buffer_tail].packet), sizeof(cc1100_packet_layer0_t)); + + if (res) + { + // Get packet pointer and store additional data in packet info structure + cc1100_packet_layer0_t* p = &(rx_buffer[rx_buffer_tail].packet); + rx_buffer[rx_buffer_tail].info.phy_src = p->phy_src; + rx_buffer[rx_buffer_tail].info.rssi = rflags.RSSI; + rx_buffer[rx_buffer_tail].info.lqi = rflags.LQI; + rx_buffer[rx_buffer_tail].info.promiscuous = false; + + // Get protocol and id field out of flags field + uint8_t protocol = R_FLAGS_PROTOCOL(p->flags); + uint8_t identification = (p->flags & FLAGS_IDENTIFICATION); + + // If received packet was an ACK (here we must be in + // TX lock state, otherwise we don't expect an ACK) + if (protocol == LAYER_1_PROTOCOL_LL_ACK && rflags.TX) + { + // And packet was for us + if (p->address == cc1100_get_address()) + { + // Stop the burst + rflags.LL_ACK = true; + rflags.RSSI_SEND = p->phy_src; + rflags.TCP = (uint32_t)((uint16_t*)p->data)[0]; + } + return; + } + else + { + // No ACK received so TOF is unpredictable + rflags.TOF = 0; + } + + // If we are sending a burst, don't accept packets. + // Only ACKs are processed (for stopping the burst). + // Same if state machine is in TX lock. + if (radio_state == RADIO_SEND_BURST || rflags.TX) + { + cc1100_statistic.packets_in_while_tx++; + return; + } + + // If buffer is currently full -> don't check sequence numbers, send + // ACK and restore state (keep always one position free for temporary packets) + if (rx_buffer_size >= RX_BUFF_SIZE-1) goto send_ack; + + // Build 16 bit sequence number of layer 0 for fast check + uint16_t new_seq_num = p->phy_src; + new_seq_num <<= 8; + new_seq_num += identification; + + // Duplicate packet detection + dup = true; + + // If new and last sequence number are the same, then discard packet + if (last_seq_num != new_seq_num) + { + // Do a more precise check (takes more time) with larger buffer + if (!contains_seq_entry(p->phy_src, identification)) + { + // Sequence number is new, no duplicate packet + dup = false; + + // Store sequence number + add_seq_entry(p->phy_src, identification); + + // Make temporary packet in RX buffer to a "real" packet which is processed + rx_buffer_size++; + if (rx_buffer_size > cc1100_statistic.rx_buffer_max) cc1100_statistic.rx_buffer_max = rx_buffer_size; + rx_buffer_tail++; + if (rx_buffer_tail == RX_BUFF_SIZE) rx_buffer_tail = 0; + // Send empty message to wake up receiver process. + // Receiver process could already be running (triggered by previous message), + // so function would return 0 and assume the receiver is not waiting but indeed + // all is working fine. + msg_send_int(&m, cc1100_event_handler_pid); + cc1100_statistic.packets_in_up++; + } + } + + send_ack: + // If packet was send directly to us, send an ACK packet back to sender. + // But only not if the packet itself was a LL-ACK! + if (p->address == cc1100_get_address() && protocol != LAYER_1_PROTOCOL_LL_ACK) + { + send_link_level_ack(p->phy_src); + + // After LL-ACK burst is over, reset number + last_seq_num = 0; + } + + // If duplicate packet detected, clear rxBuffer position + if (dup) + { + cc1100_statistic.packets_in_dups++; + } + + // If packet interrupted this nodes send call, + // don't change anything after this point. + if (radio_state == RADIO_AIR_FREE_WAITING) + { + cc1100_spi_strobe(CC1100_SRX); + hwtimer_wait(IDLE_TO_RX_TIME); + return; + } + + // Valid packet. After a wake-up, the radio should be in IDLE. + // So put CC1100 to RX for WOR_TIMEOUT (have to manually put + // the radio back to sleep/WOR). + cc1100_spi_write_reg(CC1100_MCSM0, 0x08); // Turn off FS-Autocal + cc1100_spi_write_reg(CC1100_MCSM2, 0x07); // Configure RX_TIME (until end of packet) + if (radio_mode == CC1100_MODE_CONSTANT_RX) { + cc1100_spi_strobe(CC1100_SRX); + hwtimer_wait(IDLE_TO_RX_TIME); + radio_state = RADIO_RX; + // Return here if mode is CONSTANT_RX_MODE + return; + } else { + cc1100_spi_strobe(CC1100_SPWD); + radio_state = RADIO_PWD; + } + + // Set hwtimer to put CC1100 back to RX after WOR_TIMEOUT_1 + wor_hwtimer_id = hwtimer_set(WOR_TIMEOUT_1, cc1100_hwtimer_go_receive_wrapper, NULL); + if (wor_hwtimer_id == -1) + { + // Signal hwtimer resource error, radio stays in RX, + // so no big problem, only energy is wasted. + rflags.KT_RES_ERR = true; + } + } + else + { + // No ACK received so TOF is unpredictable + rflags.TOF = 0; + + // CRC false or RX buffer full -> clear RX FIFO in both cases + last_seq_num = 0; // Reset for correct burst detection + cc1100_spi_strobe(CC1100_SIDLE); // Switch to IDLE (should already be)... + cc1100_spi_strobe(CC1100_SFRX); // ...for flushing the RX FIFO + + // If packet interrupted this nodes send call, + // don't change anything after this point. + if (radio_state == RADIO_AIR_FREE_WAITING) + { + cc1100_spi_strobe(CC1100_SRX); + hwtimer_wait(IDLE_TO_RX_TIME); + return; + } + + // If currently sending, exit here (don't go to RX/WOR) + if (radio_state == RADIO_SEND_BURST) + { + cc1100_statistic.packets_in_while_tx++; + return; + } + + // No valid packet, so go back to RX/WOR as soon as possible + cc1100_go_receive(); + } +} diff --git a/drivers/cc110x/cc1100_phy.h b/drivers/cc110x/cc1100_phy.h new file mode 100755 index 0000000000..eb4c3530ff --- /dev/null +++ b/drivers/cc110x/cc1100_phy.h @@ -0,0 +1,156 @@ +/****************************************************************************** +Copyright 2008, Freie Universitaet Berlin (FUB). All rights reserved. + +These sources were developed at the Freie Universitaet Berlin, Computer Systems +and Telematics group (http://cst.mi.fu-berlin.de). +------------------------------------------------------------------------------- +This file is part of FeuerWare. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +FeuerWare is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see http://www.gnu.org/licenses/ . +-------------------------------------------------------------------------------- +For further information and questions please use the web site + http://scatterweb.mi.fu-berlin.de +and the mailinglist (subscription via web site) + scatterweb@lists.spline.inf.fu-berlin.de +*******************************************************************************/ + +/** + * @ingroup dev_cc110x + * @{ + */ + +/** + * @file + * @internal + * @brief TI Chipcon CC110x physical radio driver + * + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @author Thomas Hillebrandt + * @author Heiko Will + * @version $Revision: 1285 $ + * + * @note $Id: cc1100_phy.h 1285 2009-08-27 13:22:42Z hillebra $ + */ +#ifndef CC1100_PHY_H_ +#define CC1100_PHY_H_ + +#include +#include +//#include "cc1100.h" +#include "cc1100-internal.h" +#include "cc1100-interface.h" + +#define MAX_DATA_LENGTH (0x3A) ///< Maximum data length of layer 0 = 58 Bytes. + +/** + * @brief CC1100 layer 0 protocol + * + *

+---------------------------------------------------
+|        |         |         |       |            |
+| Length | Address | PhySrc  | Flags |    Data    |
+|        |         |         |       |            |
+---------------------------------------------------
+  1 byte   1 byte    1 byte   1 byte   <= 58 bytes
+
+Flags:
+		Bit | Meaning
+		--------------------
+		7:4	| -
+		3:1 | Protocol
+		  0 | Identification
+
+Notes: +\li length & address are given by CC1100 +\li Identification is increased is used to scan duplicates. It must be increased + for each new packet and kept for packet retransmissions. + */ +typedef struct __attribute__ ((packed)) cc1100_packet_layer0_t +{ + uint8_t length; ///< Length of the packet (without length byte) + uint8_t address; ///< Destination address + uint8_t phy_src; ///< Source address (physical source) + uint8_t flags; ///< Flags + uint8_t data[MAX_DATA_LENGTH]; ///< Data (high layer protocol) +} cc1100_packet_layer0_t; + +typedef struct cc1100_wor_config_t +{ + uint16_t rx_interval; ///< RX polling interval in milliseconds + float rx_time_ms; ///< WOR_RX_TIME in milliseconds + uint8_t rx_time_reg; ///< WOR_RX_TIME (CC1100 "MCSM2.RX_TIME" register value) + uint8_t wor_evt_0; ///< CC1100 WOREVT0 register value + uint8_t wor_evt_1; ///< CC1100 WOREVT1 register value + uint8_t wor_ctrl; ///< CC1100 WORCTRL register value +} cc1100_wor_config_t; + +/*---------------------------------------------------------------------------*/ +// CC1100 Wake-On-Radio configuration +/*---------------------------------------------------------------------------*/ + +extern uint16_t cc1100_burst_count; +extern uint8_t cc1100_retransmission_count_uc; +extern uint8_t cc1100_retransmission_count_bc; +extern cc1100_wor_config_t cc1100_wor_config; + +/*---------------------------------------------------------------------------*/ +// CC1100 physical radio driver API +/*---------------------------------------------------------------------------*/ + +/** + * @brief Initialize the physical radio layer. + */ +void cc1100_phy_init(void); + +/** + * Lock radio for exclusive access. If no lock could be gained, + * the current process is blocked and waits for release of lock. + * + * This function can be used by MAC for locking the radio, the + * ::cc1100_send function will automatically lock the radio. + */ +void cc1100_phy_mutex_lock(void); + +/** + * Unlock radio. Must always be called after ::cc1100_phy_mutex_lock. + * If ::cc1100_send is called, it will automatically unlock the radio + * at the end of transmission. + */ +void cc1100_phy_mutex_unlock(void); + +/** + * @brief Calculate and store Wake-On-Radio settings. + * + * Calculates WOR settings for a given RX interval in + * milliseconds and stores the values in global configuration. + *

+ * Does not change settings if not applicable. + * + * @param millis Desired RX interval in milliseconds [50..60000]. + * + * @return The burst count (number of packets in a burst transfer) + * or -1 if an error occurred (e.g. RX interval invalid). + */ +int cc1100_phy_calc_wor_settings(uint16_t millis); + +/** + * @brief Handler function for incoming packets. + * + * This handler function must be called in the receive + * interrupt service routine. + */ +void cc1100_phy_rx_handler(void); + +/** @} */ + +#endif /* CC1100_PHY_H_ */ diff --git a/drivers/cc110x/cc1100_spi.c b/drivers/cc110x/cc1100_spi.c new file mode 100644 index 0000000000..ef5206cb64 --- /dev/null +++ b/drivers/cc110x/cc1100_spi.c @@ -0,0 +1,136 @@ +/****************************************************************************** +Copyright 2008, Freie Universitaet Berlin (FUB). All rights reserved. + +These sources were developed at the Freie Universitaet Berlin, Computer Systems +and Telematics group (http://cst.mi.fu-berlin.de). +------------------------------------------------------------------------------- +This file is part of FeuerWare. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +FeuerWare is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see http://www.gnu.org/licenses/ . +-------------------------------------------------------------------------------- +For further information and questions please use the web site + http://scatterweb.mi.fu-berlin.de +and the mailinglist (subscription via web site) + scatterweb@lists.spline.inf.fu-berlin.de +*******************************************************************************/ + +/** + * @ingroup dev_cc110x + * @{ + */ + +/** + * @file + * @internal + * @brief TI Chipcon CC1100 SPI driver + * + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @author Thomas Hillebrandt + * @author Heiko Will + * @version $Revision: 1775 $ + * + * @note $Id: cc1100_spi.c 1775 2010-01-26 09:37:03Z hillebra $ + */ + +#include + +#include "irq.h" +#include "arch_cc1100.h" +#include "cc1100.h" +#include "cc1100_spi.h" +#include "cc1100-internal.h" + +/*---------------------------------------------------------------------------*/ +// CC1100 SPI access +/*---------------------------------------------------------------------------*/ + +#define NOBYTE 0xFF + +uint8_t +cc1100_spi_writeburst_reg(uint8_t addr, char *src, uint8_t count) +{ + int i = 0; + unsigned int cpsr = disableIRQ(); + cc1100_spi_select(); + cc1100_txrx(addr | CC1100_WRITE_BURST); + while (i < count) { + cc1100_txrx(src[i]); + i++; + } + cc1100_spi_unselect(); + restoreIRQ(cpsr); + return count; +} + +void +cc1100_spi_readburst_reg(uint8_t addr, char *buffer, uint8_t count) +{ + int i = 0; + unsigned int cpsr = disableIRQ(); + cc1100_spi_select(); + cc1100_txrx(addr | CC1100_READ_BURST); + while (i < count) { + buffer[i] = cc1100_txrx(NOBYTE); + i++; + } + cc1100_spi_unselect(); + restoreIRQ(cpsr); +} + +void +cc1100_spi_write_reg(uint8_t addr, uint8_t value) +{ + unsigned int cpsr = disableIRQ(); + cc1100_spi_select(); + cc1100_txrx(addr); + cc1100_txrx(value); + cc1100_spi_unselect(); + restoreIRQ(cpsr); +} + +uint8_t cc1100_spi_read_reg(uint8_t addr) +{ + uint8_t result; + unsigned int cpsr = disableIRQ(); + cc1100_spi_select(); + cc1100_txrx(addr | CC1100_READ_SINGLE); + result = cc1100_txrx(NOBYTE); + cc1100_spi_unselect(); + restoreIRQ(cpsr); + return result; +} + +uint8_t cc1100_spi_read_status(uint8_t addr) +{ + uint8_t result; + unsigned int cpsr = disableIRQ(); + cc1100_spi_select(); + cc1100_txrx(addr | CC1100_READ_BURST); + result = cc1100_txrx(NOBYTE); + cc1100_spi_unselect(); + restoreIRQ(cpsr); + return result; +} + +uint8_t cc1100_spi_strobe(uint8_t c) +{ + uint8_t result; + unsigned int cpsr = disableIRQ(); + cc1100_spi_select(); + result = cc1100_txrx(c); + cc1100_spi_unselect(); + restoreIRQ(cpsr); + return result; +} + +/** @} */ diff --git a/drivers/cc110x/cc1100_spi.h b/drivers/cc110x/cc1100_spi.h new file mode 100644 index 0000000000..736f982187 --- /dev/null +++ b/drivers/cc110x/cc1100_spi.h @@ -0,0 +1,64 @@ +/****************************************************************************** +Copyright 2008, Freie Universitaet Berlin (FUB). All rights reserved. + +These sources were developed at the Freie Universitaet Berlin, Computer Systems +and Telematics group (http://cst.mi.fu-berlin.de). +------------------------------------------------------------------------------- +This file is part of FeuerWare. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +FeuerWare is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see http://www.gnu.org/licenses/ . +-------------------------------------------------------------------------------- +For further information and questions please use the web site + http://scatterweb.mi.fu-berlin.de +and the mailinglist (subscription via web site) + scatterweb@lists.spline.inf.fu-berlin.de +*******************************************************************************/ +/** + * @ingroup dev_cc110x + * @{ + */ + +/** + * @file + * @internal + * @brief TI Chipcon CC1100 SPI driver + * + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @author Thomas Hillebrandt + * @author Heiko Will + * @version $Revision: 1775 $ + * + * @note $Id: cc1100_spi.h 1775 2010-01-26 09:37:03Z hillebra $ + */ + +#ifndef CC1100_SPI_H_ +#define CC1100_SPI_H_ + +int cc1100_get_gdo0(void); +int cc1100_get_gdo1(void); +int cc1100_get_gdo2(void); + +void cc1100_spi_init(void); +void cc1100_spi_cs(void); +void cc1100_spi_select(void); +void cc1100_spi_unselect(void); + +uint8_t cc1100_spi_writeburst_reg(uint8_t addr, char *buffer, uint8_t count); +void cc1100_spi_readburst_reg(uint8_t addr, char *buffer, uint8_t count); +void cc1100_spi_write_reg(uint8_t addr, uint8_t value); +uint8_t cc1100_spi_read_reg(uint8_t addr); +uint8_t cc1100_spi_read_status(uint8_t addr); +uint8_t cc1100_spi_strobe(uint8_t c); + +/** @} */ +#endif /* CC1100_SPI_H_ */ diff --git a/drivers/include/gpioint.h b/drivers/include/gpioint.h new file mode 100644 index 0000000000..66cf138a65 --- /dev/null +++ b/drivers/include/gpioint.h @@ -0,0 +1,96 @@ +/****************************************************************************** +Copyright 2009, Freie Universität Berlin (FUB). All rights reserved. + +These sources were developed at the Freie Universitaet Berlin, Computer Systems +and Telematics group (http://cst.mi.fu-berlin.de). +------------------------------------------------------------------------------- +This file is part of FeuerWare. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +FeuerWare is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see http://www.gnu.org/licenses/ . +-------------------------------------------------------------------------------- +For further information and questions please use the web site + http://scatterweb.mi.fu-berlin.de +and the mailinglist (subscription via web site) + scatterweb@lists.spline.inf.fu-berlin.de +*******************************************************************************/ + +#ifndef GPIOINT_H_ +#define GPIOINT_H_ + +/** + * @defgroup dev_gpioint GPIO IRQ Multiplexer + * @ingroup dev + * + * Provides an API to implement interrupt handlers on IO pins. + * + * Multiplexer and interrupt handling must be implemented platform specific. + * + * See gpioint-example.c for an example of how to use gpioint. + * + * @{ + */ + +/** + * @example gpioint-example.c + * This example shows how to setup an interrupt handler for a GPIO pin + * without using the HAL. + */ + +/** + * @file + * @brief GPIO IRQ Multiplexer interface + * + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @author Michael Baar + * @version $Revision: 1508 $ + * + * @note $Id: gpioint.h 1508 2009-10-26 15:10:02Z baar $ + */ + +#include +#include + +/* + * gpioint_flags: + * Note: - We rely on the exact values for the edges. + * - These flags are extended in hal/drivers/device-gpio.h + */ +#define GPIOINT_DISABLE 0x00 +#define GPIOINT_RISING_EDGE 0x01 ///< interrupt is generated on rising edge +#define GPIOINT_FALLING_EDGE 0x02 ///< interrupt is generated on falling edge + +/** + * @brief GPIO IRQ callback function type + * @param[in] data User defined callback data passed through gpioint_set + * @param[in] edge A combination of GPIOINT_RISING_EDGE and GPIOINT_FALLING_EDGE + */ +typedef void(*fp_irqcb)(void); + +/** + * @brief GPIO IRQ handler setup + * @param[in] port CPU specific port number (starting at 0) + * @param[in] bitmask One or more bits for which to set the handler + * @param[in] flags A combination of #GPIOINT_RISING_EDGE and #GPIOINT_FALLING_EDGE + * @param[in] callback A pointer to a handler function + * @retval true successful + * @retval false failed + * + * To enable interrupt handling for a pin flags and callback must be non-zero. To disable interrupt + * handling flags and callback shall be zero. + */ +bool gpioint_set(int port, uint32_t bitmask, int flags, fp_irqcb callback); + +void gpioint_init(void); + +/** @} */ +#endif /* GPIOINT_H_ */ diff --git a/drivers/include/ltc4150.h b/drivers/include/ltc4150.h new file mode 100644 index 0000000000..e7fbad663f --- /dev/null +++ b/drivers/include/ltc4150.h @@ -0,0 +1,14 @@ +#ifndef __LTC4150_H +#define __LTC4150_H + +#include + +void ltc4150_init(); +void ltc4150_start(); +void ltc4150_stop(); + +double ltc4150_get_current_mA(); +double ltc4150_get_total_mA(); +double ltc4150_get_avg_mA(); + +#endif /* __LTC4150_H */ diff --git a/drivers/include/ltc4150_arch.h b/drivers/include/ltc4150_arch.h new file mode 100644 index 0000000000..1a6c5c630b --- /dev/null +++ b/drivers/include/ltc4150_arch.h @@ -0,0 +1,57 @@ +/****************************************************************************** +Copyright 2008-2009, Freie Universitaet Berlin (FUB). All rights reserved. + +These sources were developed at the Freie Universitaet Berlin, Computer Systems +and Telematics group (http://cst.mi.fu-berlin.de). +------------------------------------------------------------------------------- +This file is part of FeuerWare. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +FeuerWare is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see http://www.gnu.org/licenses/ . +-------------------------------------------------------------------------------- +For further information and questions please use the web site + http://scatterweb.mi.fu-berlin.de +and the mailinglist (subscription via web site) + scatterweb@lists.spline.inf.fu-berlin.de +*******************************************************************************/ + +#ifndef __LTC4150_ARCH_H +#define __LTC4150_ARCH_H + +/** + * @defgroup ltc4150 LTC4150 Coulomb Counter + * @ingroup coulomb + * @{ + */ + +/** + * @file + * @brief LTC4150 Coulomb Counter + * + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @author Heiko Will + * @version $Revision: 1203 $ + * + * @note $Id: ltc4150_arch.h 1203 2009-07-07 10:23:18Z baar $ + */ + +#define _GFH (double)32.631375 +#define _R_SENSE (double)0.330 + +void ltc4150_disable_int(void); +void ltc4150_enable_int(void); +void ltc4150_sync_blocking(void); +void ltc4150_arch_init(void); +void ltc4150_interrupt(); + +/** @} */ +#endif /* __LTC4150_ARCH_H */ diff --git a/drivers/include/sht11.h b/drivers/include/sht11.h new file mode 100644 index 0000000000..c649f402d8 --- /dev/null +++ b/drivers/include/sht11.h @@ -0,0 +1,110 @@ +/****************************************************************************** +Copyright 2009, Freie Universitaet Berlin (FUB). All rights reserved. + +These sources were developed at the Freie Universitaet Berlin, Computer Systems +and Telematics group (http://cst.mi.fu-berlin.de). +------------------------------------------------------------------------------- +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +FeuerWare is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see http://www.gnu.org/licenses/ . +-------------------------------------------------------------------------------- +For further information and questions please use the web site + http://scatterweb.mi.fu-berlin.de +and the mailinglist (subscription via web site) + scatterweb@lists.spline.inf.fu-berlin.de +*******************************************************************************/ + +#ifndef SHT11_H_ +#define SHT11_H_ + +/** + * @defgroup sht11 Sensirion SHT11 Driver + * @ingroup dev + * @{ + */ + +/** + * @file + * @brief SHT11 Device Driver + * + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @version $Revision: 667 $ + * + * @note $Id: sht11.h 667 2009-02-19 15:06:38Z baar $ + */ + +#define SHT11_NO_ACK (0) +#define SHT11_ACK (1) + //adr command r/w +#define SHT11_STATUS_REG_W (0x06) //000 0011 0 +#define SHT11_STATUS_REG_R (0x07) //000 0011 1 +#define SHT11_MEASURE_TEMP (0x03) //000 0001 1 +#define SHT11_MEASURE_HUMI (0x05) //000 0010 1 +#define SHT11_RESET (0x1E) //000 1111 0 + +/* set measurement timeout to 1 second */ +#define SHT11_MEASURE_TIMEOUT (1000) + +/** sht11 measureable data */ +typedef struct { + /* temperature value */ + float temperature; + /* linear relative humidity */ + float relhum; + /* temperature compensated relative humidity */ + float relhum_temp; +} sht11_val_t; + +/** + * @brief SHT11 modes that can be measured + */ +typedef enum { + TEMPERATURE = 1, + HUMIDITY = 2 +} sht11_mode_t; + +/** + * @brief Initialize SHT11 ports + */ +void sht11_init(void); + +/** + * @brief Read sensor + * + * Example: + * \code struct sht11_val sht11; + * sht11_Read_Sensor(&sht11, HUMIDITY|TEMPERATURE); + * printf("%-6.2f °C %5.2f %% %5.2f %%\n", sht11.temperature, sht11.relhum, sht11.relhum_temp); \endcode + */ +uint8_t sht11_read_sensor(sht11_val_t *value, sht11_mode_t mode); + +/** + * @brief Write status register + * + * @param p_value The value to write + * + * @return 1 on success, 0 otherwise + */ +uint8_t sht11_write_status(uint8_t *p_value); + +/** + * @brief Read status register with checksum + * + * @param p_value The read value + * @param p_checksum The received checksum + * + * return 1 on success, 0 otherwise + */ +uint8_t sht11_read_status(uint8_t *p_value, uint8_t *p_checksum); + +/** @} */ +#endif /*SHT11_H_*/ + diff --git a/drivers/ltc4150.c b/drivers/ltc4150.c new file mode 100644 index 0000000000..bcc166b70b --- /dev/null +++ b/drivers/ltc4150.c @@ -0,0 +1,108 @@ +/****************************************************************************** +Copyright 2008-2009, Freie Universitaet Berlin (FUB). All rights reserved. + +These sources were developed at the Freie Universitaet Berlin, Computer Systems +and Telematics group (http://cst.mi.fu-berlin.de). +------------------------------------------------------------------------------- +This file is part of FeuerWare. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +FeuerWare is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see http://www.gnu.org/licenses/ . +-------------------------------------------------------------------------------- +For further information and questions please use the web site + http://scatterweb.mi.fu-berlin.de +and the mailinglist (subscription via web site) + scatterweb@lists.spline.inf.fu-berlin.de +*******************************************************************************/ + +/** + * @ingroup ltc4150 + * @{ + */ + +/** + * @file + * @brief LTC4150 Coulomb Counter + * + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @author Heiko Will + * @author Kaspar Schleiser + */ + +#include +#include "ltc4150_arch.h" + +static volatile unsigned long int_count; +static unsigned int last_int_time; +static unsigned int last_int_duration; +static unsigned int start_time; + +static double int_to_coulomb(int ints) { + return ((double)ints) / (_GFH * _R_SENSE); +} + +static double coulomb_to_mA(double coulomb){ + return (coulomb * 1000) / 3600; +} + +uint32_t ltc4150_get_last_int_duration_us() { + return HWTIMER_TICKS_TO_US(last_int_duration); +} + +double ltc4150_get_current_mA() { + return 1000000000/(ltc4150_get_last_int_duration_us()*(_GFH * _R_SENSE)); +} + +double ltc4150_get_total_mA() { + return coulomb_to_mA(int_to_coulomb(int_count)); +} + +double ltc4150_get_avg_mA() { + return (int_to_coulomb(int_count)*1000000000)/HWTIMER_TICKS_TO_US(last_int_time - start_time); +} + +unsigned long ltc4150_get_intcount() { + return int_count; +} + +void ltc4150_init() { + ltc4150_arch_init(); +} + +void ltc4150_start() { + ltc4150_disable_int(); + int_count = 0; + uint32_t now = hwtimer_now(); + ltc4150_sync_blocking(); + start_time = now; + last_int_time = now; + ltc4150_enable_int(); +} + +void ltc4150_stop() { + ltc4150_disable_int(); +} + +void ltc4150_interrupt() +{ + uint32_t now = hwtimer_now(); + if (now >= last_int_time) { + last_int_duration = now - last_int_time; + } else { + last_int_duration = (0-1) - last_int_time + now + 1; + } + + last_int_time = now; + int_count++; +} + +/** @} */ diff --git a/drivers/sht11.c b/drivers/sht11.c new file mode 100644 index 0000000000..b0d77e03ab --- /dev/null +++ b/drivers/sht11.c @@ -0,0 +1,345 @@ +/****************************************************************************** +Copyright 2009, Freie Universitaet Berlin (FUB). All rights reserved. + +These sources were developed at the Freie Universitaet Berlin, Computer Systems +and Telematics group (http://cst.mi.fu-berlin.de). +------------------------------------------------------------------------------- +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +FeuerWare is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see http://www.gnu.org/licenses/ . +-------------------------------------------------------------------------------- +For further information and questions please use the web site + http://scatterweb.mi.fu-berlin.de +and the mailinglist (subscription via web site) + scatterweb@lists.spline.inf.fu-berlin.de +*******************************************************************************/ + +/** + * @ingroup sht11 + * @{ + */ + +/** + * @file + * @brief SHT11 Device Driver + * + * @author Freie Universität Berlin, Computer Systems & Telematics + * @version $Revision: 2396 $ + * + * @note $Id: sht11.c 2396 2010-07-06 15:12:35Z ziegert $ + */ + +#include +#include +#include + +#include +#include +#include +#include + +/** + * @brief Perform measurement + * + * @param p_value Measured value (14 or 12 bit -> 2 bytes) + * @param p_checksum Checksum of measurement + * @param mode The requestested measurement mode: temperature or humidity + * + * @return 1 on success, 0 otherwise + */ +static uint8_t measure(uint8_t *p_value, uint8_t *p_checksum, uint8_t mode); + +/** + * @brief Write one byte + * + * @param value The value to write + * + * @return 1 for acknowledged write, 0 otherwise + */ +static uint8_t write_byte(uint8_t value); + +/** + * @brief Read ony byte + * + * @param ack Set if the data read should be acknowledged + * + * @return The read byte + */ +static uint8_t read_byte(uint8_t ack); + +/** + * @brief Communication reset + */ +static void connection_reset(void); + +/** + * @brief Send start of transmision sequence + */ +static void transmission_start(void); + +/** + * @brief Toggle the clock line + */ +static inline void clk_signal(void); + +/* mutex for exclusive measurement operation */ +mutex_t sht11_mutex; + +/*---------------------------------------------------------------------------*/ +static inline void clk_signal(void) { + SHT11_SCK_HIGH; + hwtimer_wait(SHT11_CLK_WAIT); + SHT11_SCK_LOW; + hwtimer_wait(SHT11_CLK_WAIT); +} + +/*---------------------------------------------------------------------------*/ +static uint8_t write_byte(uint8_t value) +{ + uint8_t i; + uint8_t ack; + + SHT11_DATA_OUT; + /* send value bit by bit to sht11 */ + for (i = 0; i < 8; i++) { + if (value & BIT7) { + SHT11_DATA_HIGH; + hwtimer_wait(SHT11_DATA_WAIT); + } else { + SHT11_DATA_LOW; + hwtimer_wait(SHT11_DATA_WAIT); + } + + /* trigger clock signal */ + clk_signal(); + + /* shift value to write next bit */ + value = value << 1; + } + + /* wait for ack */ + SHT11_DATA_IN; + hwtimer_wait(SHT11_CLK_WAIT); + ack = SHT11_DATA; + + clk_signal(); + + return ack; +} +/*---------------------------------------------------------------------------*/ +static uint8_t read_byte (uint8_t ack) +{ + uint8_t i; + uint8_t value = 0; + + SHT11_DATA_IN; + hwtimer_wait(SHT11_DATA_WAIT); + /* read value bit by bit */ + for (i = 0; i < 8; i++) { + value = value << 1; + SHT11_SCK_HIGH; + hwtimer_wait(SHT11_CLK_WAIT); + if (SHT11_DATA) { + /* increase data by one when DATA is high */ + value++; + } + SHT11_SCK_LOW; + hwtimer_wait(SHT11_CLK_WAIT); + } + + /* send ack if necessary */ + SHT11_DATA_OUT; + if (ack) { + SHT11_DATA_LOW; + hwtimer_wait(SHT11_DATA_WAIT); + } else { + SHT11_DATA_HIGH; + hwtimer_wait(SHT11_DATA_WAIT); + } + clk_signal(); + + /* release data line */ + SHT11_DATA_IN; + + return value; +} +/*---------------------------------------------------------------------------*/ +static void transmission_start(void) +{ + /* _____ ________ + DATA: |_______| + ___ ___ + SCK : ___| |___| |______ + */ + SHT11_DATA_OUT; + + /* set initial state */ + SHT11_DATA_HIGH; + hwtimer_wait(SHT11_DATA_WAIT); + SHT11_SCK_LOW; + hwtimer_wait(SHT11_CLK_WAIT); + + SHT11_SCK_HIGH; + hwtimer_wait(SHT11_CLK_WAIT); + + SHT11_DATA_LOW; + hwtimer_wait(SHT11_DATA_WAIT); + + SHT11_SCK_LOW; + hwtimer_wait(SHT11_CLK_WAIT); + + SHT11_SCK_HIGH; + hwtimer_wait(SHT11_CLK_WAIT); + + SHT11_DATA_HIGH; + hwtimer_wait(SHT11_DATA_WAIT); + + SHT11_SCK_LOW; + hwtimer_wait(SHT11_CLK_WAIT); +} +/*---------------------------------------------------------------------------*/ +static void connection_reset(void) +{ + /* _____________________________________________________ ____ + DATA: |_______| + _ _ _ _ _ _ _ _ _ ___ ___ + SCK : __| |__| |__| |__| |__| |__| |__| |__| |__| |______| |___| |__ + */ + uint8_t i; + SHT11_DATA_HIGH; + hwtimer_wait(SHT11_DATA_WAIT); + SHT11_SCK_LOW; + hwtimer_wait(SHT11_CLK_WAIT); + for (i = 0; i < 9; i++) { + clk_signal(); + } + transmission_start(); +} +/*---------------------------------------------------------------------------*/ +static uint8_t measure(uint8_t *p_value, uint8_t *p_checksum, uint8_t mode) +{ + uint8_t error = 0; + uint8_t ack = 1; + uint16_t i; + + transmission_start(); + error = write_byte(mode); + + hwtimer_wait(HWTIMER_MSEC); + + /* wait untile sensor has finished measurement or timeout */ + for (i = 0; (i < SHT11_MEASURE_TIMEOUT) && (!error); i++) { + ack = SHT11_DATA; + + if (!ack) { + break; + } + hwtimer_wait(HWTIMER_MSEC); + } + error += ack; + + /* read MSB */ + *(p_value + 1) = read_byte(SHT11_ACK); + /* read LSB */ + *(p_value) = read_byte(SHT11_ACK); + /* read checksum */ + *p_checksum = read_byte(SHT11_NO_ACK); + + return (!error); +} +/*---------------------------------------------------------------------------*/ +void sht11_init(void) { + mutex_init(&sht11_mutex); + SHT11_INIT; + hwtimer_wait(11 * HWTIMER_MSEC); +} +/*---------------------------------------------------------------------------*/ +uint8_t sht11_read_status(uint8_t *p_value, uint8_t *p_checksum) { + uint8_t error = 0; + + transmission_start(); + error |= write_byte(SHT11_STATUS_REG_R); + *p_value = read_byte(SHT11_ACK); + *p_checksum = read_byte(SHT11_NO_ACK); + return (!error); +} +/*---------------------------------------------------------------------------*/ +uint8_t sht11_write_status(uint8_t *p_value) { + uint8_t error = 0; + + transmission_start(); + error += write_byte(SHT11_STATUS_REG_W); + error += write_byte(*p_value); + return (!error); +} +/*---------------------------------------------------------------------------*/ +uint8_t sht11_read_sensor(sht11_val_t *value, sht11_mode_t mode) { + uint8_t error = 0; + uint8_t checksum; + uint16_t humi_int, temp_int; + + /* Temperature arithmetic where S0(T) is read value + * T = D1 + D2 * S0(T) */ + const float D1 = -39.6; + const float D2 = 0.01; + + /* Arithmetic for linear humdity where S0(RH) is read value + * HL = C1 + C2 * S0(RH) + C3 * SO(RH)^2 */ + const float C1 = -4.0; + const float C2 = +0.0405; + const float C3 = -0.0000028; + + /* Arithmetic for temperature compesated relative humdity + * HT = (T-25) * ( T1 + T2 * SO(RH) ) + HL */ + const float T1 = +0.01; + const float T2 = +0.00008; + + /* check for valid buffer */ + assert(value != NULL); + + value->temperature = 0; + value->relhum = 0; + value->relhum_temp = 0; + + mutex_lock(&sht11_mutex); + connection_reset(); + + /* measure humidity */ + if (mode & HUMIDITY) { + error += (!measure((uint8_t*) &humi_int, &checksum, SHT11_MEASURE_HUMI)); + } + /* measure temperature */ + if (mode & TEMPERATURE) { + error += (!measure((uint8_t*) &temp_int, &checksum, SHT11_MEASURE_TEMP)); + } + + /* break on error */ + if (error != 0) { + connection_reset(); + mutex_unlock(&sht11_mutex,0); + return 0; + } + + if (mode & TEMPERATURE) { + value->temperature = D1 + (D2 * ((float) temp_int)); + } + if (mode & HUMIDITY) { + value->relhum = C1 + (C2 * ((float) humi_int)) + (C3 * ((float) humi_int) * ((float) humi_int)); + + if (mode & TEMPERATURE) { + value->relhum_temp = (value->temperature - 25) * (T1 + (T2 * (float) humi_int)) + value->relhum; + } + } + mutex_unlock(&sht11_mutex,0); + return 1; +} + +/** @} */ diff --git a/projects/blinker/Jamfile b/projects/blinker/Jamfile new file mode 100644 index 0000000000..f3861a731a --- /dev/null +++ b/projects/blinker/Jamfile @@ -0,0 +1,6 @@ +SubDir TOP projects hello-world ; +# LOCATE_TARGET = $(SEARCH_SOURCE)/bin ; + +Library hello-world : main.c ; + +LinkLibraries $(BOARD).elf : hello-world ; diff --git a/projects/blinker/main.c b/projects/blinker/main.c new file mode 100644 index 0000000000..e993e0d5a5 --- /dev/null +++ b/projects/blinker/main.c @@ -0,0 +1,22 @@ +#include +#include +#include +#include "hwtimer.h" + +void wait(void) +{ /* simple delay function */ + volatile int i; /* declare i as volatile int */ + for(i = 0; i < 32000; i++); /* repeat 32000 times (nop) */ +} + +int main(void) +{ + for(;;) + { /* infinite loop */ + RED_ON; + wait(); /* call delay function */ + RED_OFF; + wait(); + } +} + diff --git a/projects/blinker/tests/hello-world b/projects/blinker/tests/hello-world new file mode 100755 index 0000000000..6f4a6ca811 --- /dev/null +++ b/projects/blinker/tests/hello-world @@ -0,0 +1,13 @@ +#!/usr/bin/expect + +set timeout 5 + +spawn board/msba2/tools/bin/pseudoterm $env(PORT) + +expect { + "Hello World!" {} + timeout { exit 1 } +} + +puts "\nTest successful!\n" + diff --git a/projects/cc110x/Jamfile b/projects/cc110x/Jamfile new file mode 100644 index 0000000000..46afa8f335 --- /dev/null +++ b/projects/cc110x/Jamfile @@ -0,0 +1,9 @@ +SubDir TOP projects cc110x ; +# LOCATE_TARGET = $(SEARCH_SOURCE)/bin ; + +Library cc110x : main.c ; + +UseModule cc110x ; +UseModule gpioint ; + +LinkLibraries $(BOARD).elf : cc110x ; diff --git a/projects/cc110x/main.c b/projects/cc110x/main.c new file mode 100644 index 0000000000..e515189602 --- /dev/null +++ b/projects/cc110x/main.c @@ -0,0 +1,83 @@ +#include +#include +#include +#include +#include + +#include "drivers/cc110x/cc1100.h" +#include "radio/radio.h" + +#include "gpioint.h" +#include "hwtimer.h" +#include "swtimer.h" + +/*---------------------------------------------------------------------------*/ + +static int message_counter = 0; +static uint32_t content; + +static void protocol_handler(void* msg, int msg_size, packet_info_t* packet_info) +{ + message_counter++; + content = *(uint32_t*) msg; + puts("."); +} + +int main(void) +{ +// minimal +#ifdef MODULE_GPIOINT + gpioint_init(); +#endif + + hwtimer_init(); + printf("hwtimer....[OK]\n"); + + // timers + swtimer_init(); + printf("swtimer....[OK]\n"); + + // Adjust hwtimer with current CPU speed + hwtimer_wait(200000); + +// benchmark_init(); + +// uint32_t speed = get_system_speed(); +// printf("System speed: %lu\n", speed); + hwtimer_init_comp(F_CPU); + printf("hwtimer fcpu....[OK]\n"); + + +#ifdef SENDER + printf("I'm Alice!\n"); + char *payload = "Hello!\n"; +#else + printf("I'm Bob!\n"); +#endif + + // radio stack + cc1100_init(); + cc1100_set_packet_handler(4, protocol_handler); + cc1100_set_channel(10); +// cc1100_set_output_power(5); + printf("cc1100..[OK]\n"); + + uint32_t i = 0; + +#ifdef SENDER + cc1100_set_address(2); + + + while(1) { + puts("."); + int result = cc1100_send_csmaca(1, 4, 2, i, sizeof(i)); + printf("%i\n", result); + } +#else + cc1100_set_address(1); + while(1) { + printf("Waiting...\n"); + hwtimer_wait(200000); + } +#endif +} diff --git a/projects/hello-world/Jamfile b/projects/hello-world/Jamfile new file mode 100644 index 0000000000..f41648d4da --- /dev/null +++ b/projects/hello-world/Jamfile @@ -0,0 +1,5 @@ +SubDir TOP projects hello-world ; + +Module hello_world : main.c ; + +UseModule hello_world ; diff --git a/projects/hello-world/main.c b/projects/hello-world/main.c new file mode 100644 index 0000000000..13f3d74890 --- /dev/null +++ b/projects/hello-world/main.c @@ -0,0 +1,12 @@ +#include +#include +#include +#include "swtimer.h" + + +int main(void) +{ + double a = 1.2; + printf("Hello world! %g\n", a); + return 0; +} diff --git a/projects/hello-world/tests/hello-world b/projects/hello-world/tests/hello-world new file mode 100755 index 0000000000..a95669338a --- /dev/null +++ b/projects/hello-world/tests/hello-world @@ -0,0 +1,18 @@ +#!/usr/bin/expect + +set timeout 5 + +spawn board/msba2/tools/bin/pseudoterm $env(PORT) + +exec jam reset + +expect { + "Hello world!" {} + timeout { + puts "\nTest not successful!\n" + exit 1 + } +} + +puts "\nTest successful!\n" + diff --git a/projects/hello-world/tests/hello-world.py b/projects/hello-world/tests/hello-world.py new file mode 100644 index 0000000000..ca58e1e56d --- /dev/null +++ b/projects/hello-world/tests/hello-world.py @@ -0,0 +1,11 @@ +import pexpect +import os +import subprocess + +child = pexpect.spawn ("board/msba2/tools/bin/pseudoterm %s" % os.environ["PORT"]) + +null = open('/dev/null', 'wb') +subprocess.call(['jam', 'reset'], stdout=null) + +child.expect ('Hello world!\r\n') +print("Test successful!") diff --git a/projects/hi_earth/Jamfile b/projects/hi_earth/Jamfile new file mode 100644 index 0000000000..dd8a116f84 --- /dev/null +++ b/projects/hi_earth/Jamfile @@ -0,0 +1,5 @@ +SubDir TOP projects hi_earth ; + +Module hi_earth : main.c ; + +UseModule hi_earth ; diff --git a/projects/hi_earth/main.c b/projects/hi_earth/main.c new file mode 100644 index 0000000000..46911bbea2 --- /dev/null +++ b/projects/hi_earth/main.c @@ -0,0 +1,53 @@ +//****************************************************************************** +// eZ430 chronos hello world +// Description: initializes lcd module and shows the string 'hi earth' on the +// lcd display becuase 'hello world' is too long +// Author: Felix Genicio +//****************************************************************************** + +#include "cc430x613x.h" +#include +#include + +void display1(void); +void display2(void); + +int main(void) +{ + lcd_init(); + + clear_display_all(); + + uint8_t i = 0; + uint16_t j; + + while(1) { + if (i) { + i = 0; + display1(); + } + else { + i = 1; + display2(); + } + for (j = 1; j != 0; j++) { + if (i) { + display_symbol(LCD_ICON_BEEPER1, SEG_ON); + } + else { + display_symbol(5, SEG_OFF); + } + } + } +} + +void display1(void) { + display_chars(LCD_SEG_L1_3_0, (uint8_t*) "HI", SEG_ON); + display_chars(LCD_SEG_L2_5_0, (uint8_t*) " EARTH", SEG_OFF); +} + +void display2(void) { + display_chars(LCD_SEG_L1_3_0, (uint8_t*) "HI", SEG_OFF); + display_chars(LCD_SEG_L2_5_0, (uint8_t*) " EARTH", SEG_ON); +} + diff --git a/projects/long_term/Jamfile b/projects/long_term/Jamfile new file mode 100644 index 0000000000..80311d08a0 --- /dev/null +++ b/projects/long_term/Jamfile @@ -0,0 +1,5 @@ +SubDir TOP projects long_term ; + +Module long_term : main.c : swtimer ; + +UseModule long_term ; diff --git a/projects/long_term/main.c b/projects/long_term/main.c new file mode 100644 index 0000000000..751b7b666e --- /dev/null +++ b/projects/long_term/main.c @@ -0,0 +1,18 @@ +#include +#include +#include +#include +#include + +int main(void) +{ + hwtimer_init(); + swtimer_init(); + uint32_t i = 0; + + while (1) { + printf("(%10lu) Still running...\n", i++); + LED_RED_TOGGLE; + swtimer_usleep(10000); + } +} diff --git a/projects/new_project.sh b/projects/new_project.sh new file mode 100644 index 0000000000..a4aba7b38b --- /dev/null +++ b/projects/new_project.sh @@ -0,0 +1,15 @@ +#!/bin/sh -u + +if [ -e ${1} ]; then + echo "Directory \"${1}\" exists. Will not overwrite." + exit 1 +fi + +echo "Creating project ${1}..." + +cp -r skel ${1} +sed -i -e "s/skel/${1}/g" ${1}/main.c +sed -i -e "s/skel/${1}/g" ${1}/Jamfile + +echo "Done." + diff --git a/projects/pingpong/Jamfile b/projects/pingpong/Jamfile new file mode 100644 index 0000000000..e2ed342b57 --- /dev/null +++ b/projects/pingpong/Jamfile @@ -0,0 +1,6 @@ +SubDir TOP projects pingpong ; +# LOCATE_TARGET = $(SEARCH_SOURCE)/bin ; + +Library pingpong : main.c ; + +LinkLibraries $(BOARD).elf : pingpong ; diff --git a/projects/pingpong/main.c b/projects/pingpong/main.c new file mode 100644 index 0000000000..daf898b88d --- /dev/null +++ b/projects/pingpong/main.c @@ -0,0 +1,33 @@ +#include +#include +#include +#include + +void second_thread(void) { + printf("second_thread starting.\n"); + msg m; + + while(1) { + msg_receive(&m); +// printf("2nd: got msg from %i\n", m.sender_pid); + m.content.value++; + msg_send(&m, m.sender_pid, true); + } +} + +int main(void) +{ + printf("Hello world!\n"); + + msg m; + + int pid = thread_create(KERNEL_CONF_STACKSIZE_MAIN, PRIORITY_MAIN-1, CREATE_WOUT_YIELD | CREATE_STACKTEST, second_thread, "pong"); + + m.content.value = 1; + + while(1) { + msg_send(&m, pid, true); + msg_receive(&m); + printf("Got msg with content %i\n", m.content.value); + } +} diff --git a/projects/pingpong/tests/hello-world b/projects/pingpong/tests/hello-world new file mode 100755 index 0000000000..6f4a6ca811 --- /dev/null +++ b/projects/pingpong/tests/hello-world @@ -0,0 +1,13 @@ +#!/usr/bin/expect + +set timeout 5 + +spawn board/msba2/tools/bin/pseudoterm $env(PORT) + +expect { + "Hello World!" {} + timeout { exit 1 } +} + +puts "\nTest successful!\n" + diff --git a/projects/pingpong_sync/Jamfile b/projects/pingpong_sync/Jamfile new file mode 100644 index 0000000000..85229b05d0 --- /dev/null +++ b/projects/pingpong_sync/Jamfile @@ -0,0 +1,6 @@ +SubDir TOP projects pingpong_sync ; +# LOCATE_TARGET = $(SEARCH_SOURCE)/bin ; + +Library pingpong_sync : main.c ; + +LinkLibraries $(BOARD).elf : pingpong_sync ; diff --git a/projects/pingpong_sync/main.c b/projects/pingpong_sync/main.c new file mode 100644 index 0000000000..739ec3acf7 --- /dev/null +++ b/projects/pingpong_sync/main.c @@ -0,0 +1,32 @@ +#include +#include +#include +#include + +void second_thread(void) { + printf("second_thread starting.\n"); + msg m; + int i = 1; + while(1) { + msg_receive(&m); +// printf("2nd: got msg from %i\n", m.sender_pid); + m.content.value++; + msg_reply(&m, &m); + } +} + +int main(void) +{ + printf("Hello world!\n"); + + msg m; + + int pid = thread_create(8192, PRIORITY_MAIN-1, CREATE_WOUT_YIELD | CREATE_STACKTEST, second_thread, "pong"); + + m.content.value = 1; + + while(1) { + msg_send_receive(&m, &m, pid); + printf("Got msg with content %i\n", m.content.value); + } +} diff --git a/projects/pingpong_sync/tests/hello-world b/projects/pingpong_sync/tests/hello-world new file mode 100755 index 0000000000..6f4a6ca811 --- /dev/null +++ b/projects/pingpong_sync/tests/hello-world @@ -0,0 +1,13 @@ +#!/usr/bin/expect + +set timeout 5 + +spawn board/msba2/tools/bin/pseudoterm $env(PORT) + +expect { + "Hello World!" {} + timeout { exit 1 } +} + +puts "\nTest successful!\n" + diff --git a/projects/simple_weather_station/Jamfile b/projects/simple_weather_station/Jamfile new file mode 100644 index 0000000000..e49a167fa2 --- /dev/null +++ b/projects/simple_weather_station/Jamfile @@ -0,0 +1,5 @@ +SubDir TOP projects simple_weather_station ; + +Module simple_weather_station : main.c : swtimer sht11 ; + +UseModule simple_weather_station ; diff --git a/projects/simple_weather_station/main.c b/projects/simple_weather_station/main.c new file mode 100644 index 0000000000..2406296534 --- /dev/null +++ b/projects/simple_weather_station/main.c @@ -0,0 +1,27 @@ +#include +#include +#include +#include +#include +#include + +int main(void) +{ + sht11_val_t sht11_val; + uint8_t success = 0; + + hwtimer_init(); + swtimer_init(); + sht11_init(); + while (1) { + success = sht11_read_sensor(&sht11_val, HUMIDITY|TEMPERATURE); + if (!success) { + printf("Error reading SHT11\n"); + } + else { + printf("%-6.2f°C %5.2f%% (%5.2f%%)\n", sht11_val.temperature, sht11_val.relhum, sht11_val.relhum_temp); + } + LED_RED_TOGGLE; + swtimer_usleep(1000 * 1000); + } +} diff --git a/projects/skel/Jamfile b/projects/skel/Jamfile new file mode 100644 index 0000000000..cf61c5db8a --- /dev/null +++ b/projects/skel/Jamfile @@ -0,0 +1,5 @@ +SubDir TOP projects skel ; + +Module skel : main.c ; + +UseModule skel ; diff --git a/projects/skel/main.c b/projects/skel/main.c new file mode 100644 index 0000000000..2aa451ee06 --- /dev/null +++ b/projects/skel/main.c @@ -0,0 +1,8 @@ +#include + +int main(void) +{ + puts("Hello world!\n"); + + while(1); +} diff --git a/projects/skel/tests/hello-world b/projects/skel/tests/hello-world new file mode 100755 index 0000000000..6f4a6ca811 --- /dev/null +++ b/projects/skel/tests/hello-world @@ -0,0 +1,13 @@ +#!/usr/bin/expect + +set timeout 5 + +spawn board/msba2/tools/bin/pseudoterm $env(PORT) + +expect { + "Hello World!" {} + timeout { exit 1 } +} + +puts "\nTest successful!\n" + diff --git a/projects/test_float/Jamfile b/projects/test_float/Jamfile new file mode 100644 index 0000000000..d55247f1e5 --- /dev/null +++ b/projects/test_float/Jamfile @@ -0,0 +1,5 @@ +SubDir TOP projects test_float ; + +Module test_float : main.c ; + +UseModule test_float ; diff --git a/projects/test_float/main.c b/projects/test_float/main.c new file mode 100644 index 0000000000..c183c13d5b --- /dev/null +++ b/projects/test_float/main.c @@ -0,0 +1,17 @@ +#include +#include +#include + +int main(void) +{ + double x = 1234567./1024., z; + while (1) { + x += 0.1; + z = x - floor(x); + if (z >= 1) { + putchar('+'); + } else { + putchar('-'); + } + } +} diff --git a/projects/test_getpid/Jamfile b/projects/test_getpid/Jamfile new file mode 100644 index 0000000000..1ae54b3928 --- /dev/null +++ b/projects/test_getpid/Jamfile @@ -0,0 +1,5 @@ +SubDir TOP projects test_getpid ; + +Module test_getpid : main.c ; + +UseModule test_getpid ; diff --git a/projects/test_getpid/main.c b/projects/test_getpid/main.c new file mode 100644 index 0000000000..3a11838329 --- /dev/null +++ b/projects/test_getpid/main.c @@ -0,0 +1,8 @@ +#include +#include + +int main(void) +{ + int pid = thread_getpid(); + printf("PID: %i\n", pid); +} diff --git a/projects/test_hwtimer/Jamfile b/projects/test_hwtimer/Jamfile new file mode 100644 index 0000000000..e9f9af9ec8 --- /dev/null +++ b/projects/test_hwtimer/Jamfile @@ -0,0 +1,5 @@ +SubDir TOP projects test_hwtimer ; + +Module test_hwtimer : main.c : hwtimer ; + +UseModule test_hwtimer ; diff --git a/projects/test_hwtimer/main.c b/projects/test_hwtimer/main.c new file mode 100644 index 0000000000..8e215d1056 --- /dev/null +++ b/projects/test_hwtimer/main.c @@ -0,0 +1,29 @@ +#include +#include +#include +#include + +void callback(void* ptr) { + puts((char*)ptr); +} + +extern uint32_t hwtimer_now(); + +int main(void) +{ + puts("hwtimer test project."); + + puts("Initializing hwtimer..."); + hwtimer_init(); + + puts("Initializing hwtimer [OK]."); + + +// while (TA0R < 20000); + + hwtimer_set(20000LU, callback, (void*)"callback1"); + hwtimer_set(50000LU, callback, (void*)"callback2"); + hwtimer_set(30000LU, callback, (void*)"callback3"); + + puts("hwtimer set."); +} diff --git a/projects/test_hwtimer/tests/test_ktimer b/projects/test_hwtimer/tests/test_ktimer new file mode 100755 index 0000000000..d391d2019b --- /dev/null +++ b/projects/test_hwtimer/tests/test_ktimer @@ -0,0 +1,29 @@ +#!/usr/bin/expect + +set timeout 5 + +spawn board/msba2/tools/bin/pseudoterm $env(PORT) +exec jam reset + +expect { + "OK" {} + timeout { exit 1 } +} + +expect { + "callback1" {} + timeout { exit 1 } +} + +expect { + "callback3" {} + timeout { exit 1 } +} + +expect { + "callback2" {} + timeout { exit 1 } +} + +puts "\nTest successful!\n" + diff --git a/projects/test_ltc4150/Jamfile b/projects/test_ltc4150/Jamfile new file mode 100644 index 0000000000..aec5fc617d --- /dev/null +++ b/projects/test_ltc4150/Jamfile @@ -0,0 +1,5 @@ +SubDir TOP projects test_ltc4150 ; + +Module test_ltc4150 : main.c : ltc4150 swtimer auto_init ; + +UseModule test_ltc4150 ; diff --git a/projects/test_ltc4150/main.c b/projects/test_ltc4150/main.c new file mode 100644 index 0000000000..9d04f73fcb --- /dev/null +++ b/projects/test_ltc4150/main.c @@ -0,0 +1,18 @@ +#include +#include +#include + +void busy_wait(unsigned int n) { + for (volatile unsigned int i = 0; i < n; i++) {} +} + +int main(void) +{ + ltc4150_start(); + while(1) { + printf("Power usage: %.4f mA (%.4f mA avg)\n", ltc4150_get_current_mA(), ltc4150_get_avg_mA()); + swtimer_usleep(100000); + } + + return 0; +} diff --git a/projects/test_periodic_sleep/Jamfile b/projects/test_periodic_sleep/Jamfile new file mode 100644 index 0000000000..b9b41cb80e --- /dev/null +++ b/projects/test_periodic_sleep/Jamfile @@ -0,0 +1,5 @@ +SubDir TOP projects test_periodic_sleep ; + +Module test_periodic_sleep : main.c : swtimer ; + +UseModule test_periodic_sleep ; diff --git a/projects/test_periodic_sleep/main.c b/projects/test_periodic_sleep/main.c new file mode 100644 index 0000000000..11733221d0 --- /dev/null +++ b/projects/test_periodic_sleep/main.c @@ -0,0 +1,26 @@ +#include +#include +#include + +#define PERIOD (1000000L) + +int main(void) +{ + hwtimer_init(); + swtimer_init(); + puts("Software timer periodic wakeup test.\n"); + + int64_t diff = 0; + int64_t before = 0; + int64_t new_period = 0; + + while(1) { + before = swtimer_now(); + new_period = PERIOD - diff ; + printf("%lli\n", new_period); + swtimer_usleep(new_period); + printf("%llu \t %lli\n", swtimer_now(), diff); + diff = (swtimer_now() - before) - PERIOD + diff + 2; + } +} + diff --git a/projects/test_periodic_sleep/tests/hello-world b/projects/test_periodic_sleep/tests/hello-world new file mode 100755 index 0000000000..6f4a6ca811 --- /dev/null +++ b/projects/test_periodic_sleep/tests/hello-world @@ -0,0 +1,13 @@ +#!/usr/bin/expect + +set timeout 5 + +spawn board/msba2/tools/bin/pseudoterm $env(PORT) + +expect { + "Hello World!" {} + timeout { exit 1 } +} + +puts "\nTest successful!\n" + diff --git a/projects/test_sleep/Jamfile b/projects/test_sleep/Jamfile new file mode 100644 index 0000000000..eee5c1fa22 --- /dev/null +++ b/projects/test_sleep/Jamfile @@ -0,0 +1,5 @@ +SubDir TOP projects test_sleep ; + +Module test_sleep : main.c : hwtimer ; + +UseModule test_sleep ; diff --git a/projects/test_sleep/main.c b/projects/test_sleep/main.c new file mode 100644 index 0000000000..32e05f90b7 --- /dev/null +++ b/projects/test_sleep/main.c @@ -0,0 +1,44 @@ +#include +#include +#include +#include + +int integer = 0; +int i = 0; + +void second_thread(void) { + printf("Woke up!\n"); + while(1) { + integer++; + printf("sleeper: running. integer=%i, i=%i.\n", integer, i); + if (integer % 100 == 0) { + printf("Going to sleep.\n"); + thread_sleep(); + } + } +} + + +int main(void) +{ + hwtimer_init(); + + printf("Hello world!\n"); + + int pid = thread_create(KERNEL_CONF_STACKSIZE_DEFAULT, PRIORITY_MAIN-1, CREATE_STACKTEST | CREATE_SLEEPING | CREATE_WOUT_YIELD, second_thread, "sleeper"); + + if (pid < 0) { + puts("Error creating second_thread! Stopping test."); + while(1); + } + + while(1) { + i++; + printf(" main: running. integer=%i, i=%i.\n", integer, i); + if (i % 100 == 0) { + printf("Waking up sleeper.\n"); + thread_wakeup(pid); + fk_yield(); + } + } +} diff --git a/projects/test_swtimer/Jamfile b/projects/test_swtimer/Jamfile new file mode 100644 index 0000000000..2a286f0861 --- /dev/null +++ b/projects/test_swtimer/Jamfile @@ -0,0 +1,5 @@ +SubDir TOP projects test_swtimer ; + +Module test_swtimer : main.c : swtimer ; + +UseModule test_swtimer ; diff --git a/projects/test_swtimer/main.c b/projects/test_swtimer/main.c new file mode 100644 index 0000000000..5932662168 --- /dev/null +++ b/projects/test_swtimer/main.c @@ -0,0 +1,63 @@ +#include +#include +#include +#include +#include + +#include + +#include "primes.h" + +#define TIMERS 20 +swtimer_t timers[TIMERS]; +int timer_hits[TIMERS]; +swtime_t timer_durations[TIMERS]; +swtime_t timer_planned_durations[TIMERS]; + +extern swtime_t swtimer_next_alarm_absolute; + +void simple_callback(void* ptr) { + int timernum = (int) ptr; + swtimer_t *t = &timers[timernum]; + timer_durations[timernum] = swtimer_now() - t->start; + timer_hits[timernum] += 1; + swtimer_set(t, t->interval); +} + +#define TIMER_FACTOR 1000L + +int main(void) +{ + hwtimer_init(); + swtimer_init(); + + printf("swtimer stress test.\n"); + + int prime = 10; + for (int i = 0; i < TIMERS; i++) { + timer_hits[i] = 0; + timers[i].action_type = SWTIMER_CALLBACK; + timers[i].action.callback.f = simple_callback; + timers[i].action.callback.ptr = (void*)i; + + swtimer_set(&timers[i], TIMER_FACTOR*primes[(prime)-1]); + timer_planned_durations[i] = TIMER_FACTOR*primes[(prime)-1]; + prime+=5; + if (prime >= 999) prime = 0; + } + + swtime_t last = 0; + unsigned int total_hits = 0; + while(1) { + swtimer_usleep(1000000L); + printf("Duration: %lu\n", swtimer_now() - last); + last = swtimer_now(); + + for (int t = 0; t < TIMERS; t++) { + total_hits += timer_hits[t]; + printf("timernum: %i \thits=%i \tduration: %8lu \tdiff=%lu\n", t, timer_hits[t], timer_durations[t], timer_durations[t] - timer_planned_durations[t]); + } + printf("-----\nTotal Hits: %u\n", total_hits); + puts(""); + } +} diff --git a/projects/test_swtimer/primes.h b/projects/test_swtimer/primes.h new file mode 100644 index 0000000000..12641138eb --- /dev/null +++ b/projects/test_swtimer/primes.h @@ -0,0 +1,80 @@ +#ifndef __PRIMES_H +#define __PRIMES_H + +const int primes[999] = {3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, +59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, +139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, +229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, +317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, +421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, +521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, +619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, +733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, +839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, +953, 967, 971, 977, 983, 991, 997, 1009, 1013, 1019, 1021, 1031, 1033, 1039, +1049, 1051, 1061, 1063, 1069, 1087, 1091, 1093, 1097, 1103, 1109, 1117, 1123, +1129, 1151, 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223, 1229, +1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291, 1297, 1301, 1303, 1307, +1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399, 1409, 1423, 1427, 1429, 1433, +1439, 1447, 1451, 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511, +1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583, 1597, 1601, 1607, +1609, 1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667, 1669, 1693, 1697, 1699, +1709, 1721, 1723, 1733, 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801, +1811, 1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889, 1901, 1907, +1913, 1931, 1933, 1949, 1951, 1973, 1979, 1987, 1993, 1997, 1999, 2003, 2011, +2017, 2027, 2029, 2039, 2053, 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111, +2113, 2129, 2131, 2137, 2141, 2143, 2153, 2161, 2179, 2203, 2207, 2213, 2221, +2237, 2239, 2243, 2251, 2267, 2269, 2273, 2281, 2287, 2293, 2297, 2309, 2311, +2333, 2339, 2341, 2347, 2351, 2357, 2371, 2377, 2381, 2383, 2389, 2393, 2399, +2411, 2417, 2423, 2437, 2441, 2447, 2459, 2467, 2473, 2477, 2503, 2521, 2531, +2539, 2543, 2549, 2551, 2557, 2579, 2591, 2593, 2609, 2617, 2621, 2633, 2647, +2657, 2659, 2663, 2671, 2677, 2683, 2687, 2689, 2693, 2699, 2707, 2711, 2713, +2719, 2729, 2731, 2741, 2749, 2753, 2767, 2777, 2789, 2791, 2797, 2801, 2803, +2819, 2833, 2837, 2843, 2851, 2857, 2861, 2879, 2887, 2897, 2903, 2909, 2917, +2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999, 3001, 3011, 3019, 3023, 3037, +3041, 3049, 3061, 3067, 3079, 3083, 3089, 3109, 3119, 3121, 3137, 3163, 3167, +3169, 3181, 3187, 3191, 3203, 3209, 3217, 3221, 3229, 3251, 3253, 3257, 3259, +3271, 3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331, 3343, 3347, 3359, 3361, +3371, 3373, 3389, 3391, 3407, 3413, 3433, 3449, 3457, 3461, 3463, 3467, 3469, +3491, 3499, 3511, 3517, 3527, 3529, 3533, 3539, 3541, 3547, 3557, 3559, 3571, +3581, 3583, 3593, 3607, 3613, 3617, 3623, 3631, 3637, 3643, 3659, 3671, 3673, +3677, 3691, 3697, 3701, 3709, 3719, 3727, 3733, 3739, 3761, 3767, 3769, 3779, +3793, 3797, 3803, 3821, 3823, 3833, 3847, 3851, 3853, 3863, 3877, 3881, 3889, +3907, 3911, 3917, 3919, 3923, 3929, 3931, 3943, 3947, 3967, 3989, 4001, 4003, +4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057, 4073, 4079, 4091, 4093, 4099, +4111, 4127, 4129, 4133, 4139, 4153, 4157, 4159, 4177, 4201, 4211, 4217, 4219, +4229, 4231, 4241, 4243, 4253, 4259, 4261, 4271, 4273, 4283, 4289, 4297, 4327, +4337, 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409, 4421, 4423, 4441, 4447, +4451, 4457, 4463, 4481, 4483, 4493, 4507, 4513, 4517, 4519, 4523, 4547, 4549, +4561, 4567, 4583, 4591, 4597, 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657, +4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751, 4759, 4783, 4787, +4789, 4793, 4799, 4801, 4813, 4817, 4831, 4861, 4871, 4877, 4889, 4903, 4909, +4919, 4931, 4933, 4937, 4943, 4951, 4957, 4967, 4969, 4973, 4987, 4993, 4999, +5003, 5009, 5011, 5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087, 5099, 5101, +5107, 5113, 5119, 5147, 5153, 5167, 5171, 5179, 5189, 5197, 5209, 5227, 5231, +5233, 5237, 5261, 5273, 5279, 5281, 5297, 5303, 5309, 5323, 5333, 5347, 5351, +5381, 5387, 5393, 5399, 5407, 5413, 5417, 5419, 5431, 5437, 5441, 5443, 5449, +5471, 5477, 5479, 5483, 5501, 5503, 5507, 5519, 5521, 5527, 5531, 5557, 5563, +5569, 5573, 5581, 5591, 5623, 5639, 5641, 5647, 5651, 5653, 5657, 5659, 5669, +5683, 5689, 5693, 5701, 5711, 5717, 5737, 5741, 5743, 5749, 5779, 5783, 5791, +5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849, 5851, 5857, 5861, 5867, 5869, +5879, 5881, 5897, 5903, 5923, 5927, 5939, 5953, 5981, 5987, 6007, 6011, 6029, +6037, 6043, 6047, 6053, 6067, 6073, 6079, 6089, 6091, 6101, 6113, 6121, 6131, +6133, 6143, 6151, 6163, 6173, 6197, 6199, 6203, 6211, 6217, 6221, 6229, 6247, +6257, 6263, 6269, 6271, 6277, 6287, 6299, 6301, 6311, 6317, 6323, 6329, 6337, +6343, 6353, 6359, 6361, 6367, 6373, 6379, 6389, 6397, 6421, 6427, 6449, 6451, +6469, 6473, 6481, 6491, 6521, 6529, 6547, 6551, 6553, 6563, 6569, 6571, 6577, +6581, 6599, 6607, 6619, 6637, 6653, 6659, 6661, 6673, 6679, 6689, 6691, 6701, +6703, 6709, 6719, 6733, 6737, 6761, 6763, 6779, 6781, 6791, 6793, 6803, 6823, +6827, 6829, 6833, 6841, 6857, 6863, 6869, 6871, 6883, 6899, 6907, 6911, 6917, +6947, 6949, 6959, 6961, 6967, 6971, 6977, 6983, 6991, 6997, 7001, 7013, 7019, +7027, 7039, 7043, 7057, 7069, 7079, 7103, 7109, 7121, 7127, 7129, 7151, 7159, +7177, 7187, 7193, 7207, 7211, 7213, 7219, 7229, 7237, 7243, 7247, 7253, 7283, +7297, 7307, 7309, 7321, 7331, 7333, 7349, 7351, 7369, 7393, 7411, 7417, 7433, +7451, 7457, 7459, 7477, 7481, 7487, 7489, 7499, 7507, 7517, 7523, 7529, 7537, +7541, 7547, 7549, 7559, 7561, 7573, 7577, 7583, 7589, 7591, 7603, 7607, 7621, +7639, 7643, 7649, 7669, 7673, 7681, 7687, 7691, 7699, 7703, 7717, 7723, 7727, +7741, 7753, 7757, 7759, 7789, 7793, 7817, 7823, 7829, 7841, 7853, 7867, 7873, +7877, 7879, 7883, 7901, 7907, 7919}; + +#endif /* __PRIMES_H */ diff --git a/projects/test_swtimer_remove/Jamfile b/projects/test_swtimer_remove/Jamfile new file mode 100644 index 0000000000..dc9af10318 --- /dev/null +++ b/projects/test_swtimer_remove/Jamfile @@ -0,0 +1,5 @@ +SubDir TOP projects test_swtimer_remove ; + +Module test_swtimer_remove : main.c : swtimer ; + +UseModule test_swtimer_remove ; diff --git a/projects/test_swtimer_remove/main.c b/projects/test_swtimer_remove/main.c new file mode 100644 index 0000000000..773265c758 --- /dev/null +++ b/projects/test_swtimer_remove/main.c @@ -0,0 +1,50 @@ +#include +#include +#include +#include + +int main(void) +{ + hwtimer_init(); + swtimer_init(); + + puts("Hello world!\n"); + + swtimer_t t; + + puts("Setting timer...\n"); + swtimer_set_wakeup(&t, 10000000L, fk_thread->pid); + puts("Small delay...\n"); + hwtimer_wait(200000); + puts("Removing timer...\n"); + swtimer_remove(&t); + puts("Done.\n"); + + swtimer_t t2; + puts("Setting timer...\n"); + swtimer_set_wakeup(&t, 10000000L, fk_thread->pid); + puts("Setting timer 2...\n"); + swtimer_set_wakeup(&t2, 50000000L, fk_thread->pid); + puts("Small delay...\n"); + hwtimer_wait(200000); + puts("Removing timer 1...\n"); + swtimer_remove(&t); + puts("Removing timer 2...\n"); + swtimer_remove(&t2); + puts("Done.\n"); + + puts("Setting timer...\n"); + swtimer_set_wakeup(&t, 10000000L, fk_thread->pid); + puts("Setting timer 2...\n"); + swtimer_set_wakeup(&t2, 50000000L, fk_thread->pid); + puts("Small delay...\n"); + hwtimer_wait(200000); + puts("Removing timer 2...\n"); + swtimer_remove(&t2); + puts("Removing timer 1...\n"); + swtimer_remove(&t); + puts("Done.\n"); + + + while(1); +} diff --git a/projects/test_swtimer_remove/tests/hello-world b/projects/test_swtimer_remove/tests/hello-world new file mode 100755 index 0000000000..6f4a6ca811 --- /dev/null +++ b/projects/test_swtimer_remove/tests/hello-world @@ -0,0 +1,13 @@ +#!/usr/bin/expect + +set timeout 5 + +spawn board/msba2/tools/bin/pseudoterm $env(PORT) + +expect { + "Hello World!" {} + timeout { exit 1 } +} + +puts "\nTest successful!\n" + diff --git a/projects/test_thread_exit/Jamfile b/projects/test_thread_exit/Jamfile new file mode 100644 index 0000000000..3f9c7e01da --- /dev/null +++ b/projects/test_thread_exit/Jamfile @@ -0,0 +1,5 @@ +SubDir TOP projects test_thread_exit ; + +Module test_thread_exit : main.c ; + +UseModule test_thread_exit ; diff --git a/projects/test_thread_exit/main.c b/projects/test_thread_exit/main.c new file mode 100644 index 0000000000..3f09c7284e --- /dev/null +++ b/projects/test_thread_exit/main.c @@ -0,0 +1,16 @@ +#include +#include +#include +#include + +void second_thread(void) { + printf("second_thread starting.\n"); + + puts("2nd: running..."); +} + +int main(void) +{ + int pid = thread_create(8192, PRIORITY_MAIN-1, CREATE_WOUT_YIELD | CREATE_STACKTEST, second_thread, "nr2"); + puts("Main thread exiting..."); +} diff --git a/projects/test_thread_exit/tests/hello-world b/projects/test_thread_exit/tests/hello-world new file mode 100755 index 0000000000..6f4a6ca811 --- /dev/null +++ b/projects/test_thread_exit/tests/hello-world @@ -0,0 +1,13 @@ +#!/usr/bin/expect + +set timeout 5 + +spawn board/msba2/tools/bin/pseudoterm $env(PORT) + +expect { + "Hello World!" {} + timeout { exit 1 } +} + +puts "\nTest successful!\n" + diff --git a/sys/Jamfile b/sys/Jamfile new file mode 100644 index 0000000000..5f49db1575 --- /dev/null +++ b/sys/Jamfile @@ -0,0 +1,33 @@ +# ****************************************************************************** +# Copyright 2009, Freie Universitaet Berlin (FUB). All rights reserved. +# +# These sources were developed at the Freie Universitaet Berlin, Computer +# Systems and Telematics group (http://cst.mi.fu-berlin.de). +# ------------------------------------------------------------------------------ +# This file is part of FeuerWare. +# +# This program is free software: you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation, either version 3 of the License, or (at your option) any later +# version. +# +# FeuerWare is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with +# this program. If not, see http://www.gnu.org/licenses/ . +# ------------------------------------------------------------------------------ +# For further information and questions please use the web site +# http://scatterweb.mi.fu-berlin.de +# and the mailinglist (subscription via web site) +# scatterweb@lists.spline.inf.fu-berlin.de +# ****************************************************************************** +# $Id$ + +SubDir TOP sys ; + +Module swtimer : swtimer.c : hwtimer ; +Module auto_init : auto_init.c ; + +SubInclude TOP sys net ; diff --git a/sys/auto_init.c b/sys/auto_init.c new file mode 100644 index 0000000000..d872c0354f --- /dev/null +++ b/sys/auto_init.c @@ -0,0 +1,36 @@ +#include +#include +#include + +#define ENABLE_DEBUG +#include + +extern void main(void); + +void auto_init(void) { +#ifdef MODULE_HWTIMER + DEBUG("Auto init hwtimer module.\n"); + hwtimer_init(); +#endif +#ifdef MODULE_SWTIMER + DEBUG("Auto init swtimer module.\n"); + swtimer_init(); +#endif +#ifdef MODULE_SHT11 + DEBUG("Auto init SHT11 module.\n"); + sht11_init(); +#endif +#ifdef MODULE_GPIOINT + DEBUG("Auto init gpioint module.\n"); + gpioint_init(); +#endif +#ifdef MODULE_CC110X + DEBUG("Auto init CC1100 module.\n"); + cc1100_init(); +#endif +#ifdef MODULE_LTC4150 + DEBUG("Auto init ltc4150 module.\n"); + ltc4150_init(); +#endif + main(); +} diff --git a/sys/include/auto_init.h b/sys/include/auto_init.h new file mode 100644 index 0000000000..c3da973b34 --- /dev/null +++ b/sys/include/auto_init.h @@ -0,0 +1,30 @@ +#ifndef AUTO_INIT_H +#define AUTO_INIT_H + +#ifdef MODULE_HWTIMER +#include +#endif + +#ifdef MODULE_SWTIMER +#include +#endif + +#ifdef MODULE_SHT11 +#include +#endif + +#ifdef MODULE_GPIOINT +#include +#endif + +#ifdef MODULE_CC110X +#include +#endif + +#ifdef MODULE_LTC4150 +#include +#endif + +void auto_init(void); + +#endif diff --git a/sys/include/ping.h b/sys/include/ping.h new file mode 100644 index 0000000000..f5ef40e1c9 --- /dev/null +++ b/sys/include/ping.h @@ -0,0 +1,25 @@ +#include "radio/radio.h" + +void init_payload(); +void ping_init(protocol_t protocol, uint8_t channr, radio_address_t addr); +void ping(radio_address_t addr, uint8_t channr); +void calc_rtt(); +void print_success(); +void print_failed(); +void gpio_n_timer_init(); +void adjust_timer(); +static void ping_handler(void *payload, int payload_size, + packet_info_t *packet_info); +static void pong_handler(void *payload, int payload_size, + packet_info_t *packet_info); +void pong(uint16_t src); + +typedef struct pong{ + int hopcount; + int ttl; + radio_address_t radio_address; +} ping_r; + +typedef struct ping_payload{ + char* payload; +} ping_payload; diff --git a/sys/include/radio/radio.h b/sys/include/radio/radio.h new file mode 100644 index 0000000000..747b9c86d0 --- /dev/null +++ b/sys/include/radio/radio.h @@ -0,0 +1,99 @@ +/****************************************************************************** +Copyright 2008-2009 , Freie Universitaet Berlin (FUB). All rights reserved. + +These sources were developed at the Freie Universitaet Berlin, Computer Systems +and Telematics group (http://cst.mi.fu-berlin.de). +------------------------------------------------------------------------------- +This file is part of FeuerWare. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +FeuerWare is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see http://www.gnu.org/licenses/ . +-------------------------------------------------------------------------------- +For further information and questions please use the web site + http://scatterweb.mi.fu-berlin.de +and the mailinglist (subscription via web site) + scatterweb@lists.spline.inf.fu-berlin.de +*******************************************************************************/ + +#ifndef RADIO_H_ +#define RADIO_H_ + +/** + * @defgroup net_datalink Data link layer + * @ingroup net + * + * @brief Defines interface of data link layers for use with micro mesh stack. + * + * @{ + */ + +/** + * @file + * @brief + * + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @author baar + * @author Thomas Hillebrandt + * @version $Revision: 1961 $ + * + * @note $Id$ + */ + +#include +#include +#include "radio/types.h" + +#ifndef FEUERWARE_CONF_NUM_RADIOS +#define FEUERWARE_CONF_NUM_RADIOS 1 +#endif + +#define L1_PROTOCOL_CATCH_ALL (0xff) ///< Catch all protocol ID + +enum layer_1_protocols +{ + LAYER_1_PROTOCOL_LL_ACK = 1, ///< Link-Level Acknowledgement (LL-ACK) + LAYER_1_PROTOCOL_MM = 2, ///< Micro Mesh network packet (MM) +}; + +/** + * Radio/MAC API. + */ +typedef struct radio { + const char* name; + const radio_address_t broadcast_address; + const uint8_t output_power_max; + /** + * @return the average transmission duration of one packet + * in milliseconds, e.g. till ACK received. + */ + int (*get_avg_transmission_duration)(void); + radio_address_t (*get_address)(void); + bool (*set_address)(radio_address_t address); + bool (*set_output_power)(uint8_t pa_idx); + bool (*set_packet_monitor)(packet_monitor_t monitor); + /** + * @return -1 if an error occurs (e.g. handler table full) else >= 0. + */ + int (*set_packet_handler)(protocol_t protocol, packet_handler_t handler); + /** + * @return A negative value if operation failed; else the number of transmitted bytes. + */ + int (*send)(radio_address_t address, protocol_t protocol, int priority, char *payload, int payload_len); + void (*print_stats)(void); + void (*print_config)(void); +} radio_t; + +extern const struct radio* feuerware_radios[FEUERWARE_CONF_NUM_RADIOS]; + +/** @} */ + +#endif /* RADIO_H_ */ diff --git a/sys/include/radio/types.h b/sys/include/radio/types.h new file mode 100644 index 0000000000..7018480f65 --- /dev/null +++ b/sys/include/radio/types.h @@ -0,0 +1,95 @@ +/****************************************************************************** +Copyright 2009, Freie Universitaet Berlin (FUB). All rights reserved. + +These sources were developed at the Freie Universitaet Berlin, Computer Systems +and Telematics group (http://cst.mi.fu-berlin.de). +------------------------------------------------------------------------------- +This file is part of FeuerWare. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +FeuerWare is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see http://www.gnu.org/licenses/ . +-------------------------------------------------------------------------------- +For further information and questions please use the web site + http://scatterweb.mi.fu-berlin.de +and the mailinglist (subscription via web site) + scatterweb@lists.spline.inf.fu-berlin.de +*******************************************************************************/ + +#ifndef COMMONTYPES_H_ +#define COMMONTYPES_H_ + +/** + * @file + * @brief Common network stack types (of all layers). + * + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @author Thomas Hillebrandt + * @version $Revision: 2061 $ + * + * @note $Id: common-types.h 2061 2010-04-01 12:13:22Z hillebra $ + */ + +#include +#include + +typedef uint8_t protocol_t; ///< Packet protocol type +typedef uint16_t radio_address_t; ///< Radio layer address type + +#define NUM_PRIORITY_LEVELS 3 ///< Number of packet transmission priorities + +/** + * @brief Packet transmission priorities of various layers. + */ +enum transmission_priorities +{ + PRIORITY_ALARM = 0, + PRIORITY_WARNING = 1, + PRIORITY_DATA = 2 +}; + +/** + * Additional packet information on a received packet. + * This struct is passed along all receive functions of + * all layers. Each layers fills in additional information. + */ +typedef struct __attribute__ ((packed)) packet_info_t +{ + uint16_t source; ///< Net layer: source + uint16_t destination; ///< Net layer: destination + radio_address_t phy_src; ///< Radio layer: source + uint8_t rssi; ///< Radio layer: RSSI + uint8_t lqi; ///< Radio layer: LQI + uint8_t ttl; ///< Net layer: TTL + uint8_t tos; ///< Net layer: TOS + bool promiscuous; ///< Radio layer: whether network interface is in promiscuous mode +} packet_info_t; + +/** + * Packet handler (receive function) of all layers. + * @param [in/out] payload Pointer to packet payload data + * @param [in] payload_size Size of the packet payload data in bytes + * @param [in/out] packet_info Cross-layer meta data + */ +typedef void (*packet_handler_t)(void* payload, int payload_size, packet_info_t* packet_info); + +/** + * Packet monitor of all layers. Normally there can be one packet + * monitor per layer (if any). The payload must not be changed! + * + * @param payload Pointer to packet payload data + * @param payload_size Size of the packet payload data in bytes + * @param protocol Protocol type of the packet payload data + * @param packet_info Cross-layer meta data + */ +typedef void (*packet_monitor_t)(void* payload, int payload_size, protocol_t protocol, packet_info_t* packet_info); + +#endif /* COMMONTYPES_H_ */ diff --git a/sys/include/swtimer.h b/sys/include/swtimer.h new file mode 100755 index 0000000000..9f7d9a9730 --- /dev/null +++ b/sys/include/swtimer.h @@ -0,0 +1,141 @@ +/** \addtogroup system + * @{ */ + +/** + * \defgroup swtimer Software Timer library + * + * The swtimer library provides functions for setting, resetting and restarting + * software timers, and for checking if a swtimer has expired. + * + * @{ + */ + +/** + * \file + * Timer library header file. + */ + +#ifndef __SWTIMER_H__ +#define __SWTIMER_H__ + +#include + +#define MSG_TIMER 12345 + +#define SWTIMER_WAKEUP 0 +#define SWTIMER_CALLBACK 1 +#define SWTIMER_MSG 2 + +#undef wakeup + +#if WORDSIZE == 32 +typedef uint64_t swtime_t; +#else +typedef uint32_t swtime_t; +#endif + +/** + * A swtimer. + * + * This structure is used for declaring a swtimer. The swtimer must be set + * with swtimer_set() before it can be used. + * + * \hideinitializer + */ +typedef struct swtimer_t { + swtime_t start; + swtime_t interval; + + struct swtimer_t *next; + + int action_type; + union { + struct { + int pid; + } wakeup; + struct { + void (*f)(void*); + void *ptr; + } callback; + struct { + unsigned int value; + int target_pid; + } msg; + } action; +} swtimer_t; + +swtime_t swtimer_now(); + +int swtimer_init(); + +/** + * @brief set swtimer interval and activate + * @param[in] t pointer to preinitialised swtimer_t + * @param[in] interval swtimer interval + */ +int swtimer_set(swtimer_t *t, swtime_t interval); + +/** + * @brief reset swtimer + * @param[in] t pointer to preinitialised swtimer_t + */ +void swtimer_reset(swtimer_t *t); + +/** + * @brief restart swtimer + * @param[in] t pointer to preinitialised swtimer_t + */ +void swtimer_restart(swtimer_t *t); + +/** + * @brief check if swtimer is expired + * @param[in] t pointer to preinitialised swtimer_t + * @return + */ +int swtimer_expired(swtimer_t *t); + +/** + * @brief will cause the calling thread to be suspended from excecution until the number of microseconds has elapsed + * @param[in] us number of microseconds + * @return 0 on success, < 0 on error + */ +int swtimer_usleep(swtime_t us); + +/** + * @brief set a swtimer with msg event handler + * @param[in] t pointer to preinitialised swtimer_t + * @param[in] interval swtimer interval + * @param[in] pid process id + * @param[in] ptr message value + * @return 0 on success, < 0 on error + */ +int swtimer_set_msg(swtimer_t *t, swtime_t interval, int pid, void *ptr); + +/** + * @brief set a swtimer with wakeup event + * @param[in] t pointer to preinitialised swtimer_t + * @param[in] pid process id + * @return 0 on success, < 0 on error + */ +int swtimer_set_wakeup(swtimer_t *t, swtime_t interval, int pid); + +/** + * @brief set a swtimer with callback function event handler + * @param[in] t pointer to preinitialised swtimer_t + * @param[in] interval swtimer interval + * @param[in] f_ptr pointer to callback function + * @return 0 on success, < 0 on error + */ +int swtimer_set_cb(swtimer_t *t, swtime_t interval, void (*f_ptr)(void *), void *ptr); + +/** + * @brief remove a swtimer + * @param[in] t pointer to preinitialised swtimer_t + * @return 0 on success, < 0 on error + */ +int swtimer_remove(swtimer_t *t); + +#endif /* __SWTIMER_H__ */ + +/** @} */ +/** @} */ diff --git a/sys/net/Jamfile b/sys/net/Jamfile new file mode 100644 index 0000000000..760992b1c1 --- /dev/null +++ b/sys/net/Jamfile @@ -0,0 +1,31 @@ +# ****************************************************************************** +# Copyright 2009, Freie Universitaet Berlin (FUB). All rights reserved. +# +# These sources were developed at the Freie Universitaet Berlin, Computer +# Systems and Telematics group (http://cst.mi.fu-berlin.de). +# ------------------------------------------------------------------------------ +# This file is part of FeuerWare. +# +# This program is free software: you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation, either version 3 of the License, or (at your option) any later +# version. +# +# FeuerWare is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with +# this program. If not, see http://www.gnu.org/licenses/ . +# ------------------------------------------------------------------------------ +# For further information and questions please use the web site +# http://scatterweb.mi.fu-berlin.de +# and the mailinglist (subscription via web site) +# scatterweb@lists.spline.inf.fu-berlin.de +# ****************************************************************************** +# $Id$ + +SubDir TOP sys net ; + +Module protocol_multiplex : protocol-multiplex.c ; + diff --git a/sys/net/protocol-multiplex.c b/sys/net/protocol-multiplex.c new file mode 100644 index 0000000000..7f3857b4ef --- /dev/null +++ b/sys/net/protocol-multiplex.c @@ -0,0 +1,145 @@ +/****************************************************************************** +Copyright 2009-2010, Freie Universitaet Berlin (FUB). All rights reserved. + +These sources were developed at the Freie Universitaet Berlin, Computer Systems +and Telematics group (http://cst.mi.fu-berlin.de). +------------------------------------------------------------------------------- +This file is part of FeuerWare. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +FeuerWare is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see http://www.gnu.org/licenses/ . +-------------------------------------------------------------------------------- +For further information and questions please use the web site + http://scatterweb.mi.fu-berlin.de +and the mailinglist (subscription via web site) + scatterweb@lists.spline.inf.fu-berlin.de +*******************************************************************************/ + +/** + * @addtogroup net_mmstack + * @{ + */ + +/** + * @file + * @internal + * @brief Protocol handler multiplexing + * + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @author Thomas Hillebrandt + * @author Heiko Will + * @author Michael Baar + * @version $Revision: 1938 $ + * + * @note $Id: protocol-multiplex.c 1938 2010-03-02 12:14:29Z baar $ + */ + +#include +#include +#include "protocol-multiplex.h" + +//#define DEBUG +#ifdef DEBUG + #include + #define PRINTF(fmt,args...) printf("pm: " fmt "\n", ##args) +#else + #define PRINTF(...) +#endif + +/*---------------------------------------------------------------------------*/ +void +pm_init_table(pm_table_t* table, uint8_t size, handler_entry_t* handler) +{ + table->size = size; + table->handler = handler; + memset(handler, 0, sizeof(handler_entry_t) * size); +} +/*---------------------------------------------------------------------------*/ +int +pm_find_handler_index(const pm_table_t* table, protocol_t protocol, unsigned int start) +{ + int i; + handler_entry_t* e = &table->handler[start]; + for(i = start; i < table->size; i++, e++) + { + if (e->protocol == protocol) + return i; + } + return -1; +} +/*---------------------------------------------------------------------------*/ +int +pm_set_handler(const pm_table_t* table, protocol_t protocol, packet_handler_t handler) +{ + // Reject illegal values + if (protocol == 0 || handler == NULL) { + PRINTF("proto %u rejected", protocol); + return -1; + } + // Check if there is already a handler for given protocol + int index = pm_find_handler_index(table, protocol, 0); + if (index >= 0) + { + // Two handlers for same protocol not allowed because only + // one gets called. This hasn't to be the last one who + // registered! + PRINTF("proto %u handler found, reset", protocol); + table->handler[index].protocol = 0; + table->handler[index].handler = NULL; + + } + // Find free position for handler (protocol value is 0) + index = pm_find_handler_index(table, 0, 0); + // Store handler if free index found + if (index >= 0) + { + PRINTF("proto %u, set", protocol); + table->handler[index].protocol = protocol; + table->handler[index].handler = handler; + } + // Return result (-1 on error or no free index) + return index; +} +/*---------------------------------------------------------------------------*/ +void +pm_remove_handler(const pm_table_t* table, protocol_t protocol, packet_handler_t handler) +{ + int i; + for (i = 0; i < table->size; i++) + { + if (table->handler[i].protocol == protocol && table->handler[i].handler == handler) + { + PRINTF("proto %u handler found, reset", protocol); + table->handler[i].protocol = 0; + table->handler[i].handler = NULL; + } + } +} +/*---------------------------------------------------------------------------*/ +int +pm_invoke(const pm_table_t* table, protocol_t protocol, void* payload, int payload_size, packet_info_t* packet_info) +{ + int index = 0; + + // Reject illegal values + if (protocol == 0) return -1; + + if ( (index = pm_find_handler_index(table, protocol, index)) != -1 ) { + PRINTF("proto %u, invoke", protocol); + table->handler[index].handler(payload, payload_size, packet_info); + } else { + PRINTF("proto %u invoke failed (no handler)", protocol); + } + return index; +} +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/sys/net/protocol-multiplex.h b/sys/net/protocol-multiplex.h new file mode 100644 index 0000000000..d48bdefc18 --- /dev/null +++ b/sys/net/protocol-multiplex.h @@ -0,0 +1,69 @@ +/****************************************************************************** +Copyright 2009, Freie Universitaet Berlin (FUB). All rights reserved. + +These sources were developed at the Freie Universitaet Berlin, Computer Systems +and Telematics group (http://cst.mi.fu-berlin.de). +------------------------------------------------------------------------------- +This file is part of FeuerWare. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +FeuerWare is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see http://www.gnu.org/licenses/ . +-------------------------------------------------------------------------------- +For further information and questions please use the web site + http://scatterweb.mi.fu-berlin.de +and the mailinglist (subscription via web site) + scatterweb@lists.spline.inf.fu-berlin.de +*******************************************************************************/ + +#ifndef PROTOCOLMULTIPLEX_H_ +#define PROTOCOLMULTIPLEX_H_ + +/** + * @addtogroup net + * @{ + */ + +/** + * @file + * @internal + * @brief Protocol handler multiplexing + * + * @author Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project + * @author Thomas Hillebrandt + * @author Heiko Will + * @author Michael Baar + * @version $Revision: 1526 $ + * + * @note $Id: protocol-multiplex.h 1526 2009-10-30 13:40:20Z hillebra $ + */ + +#include "radio/types.h" + +typedef struct { + packet_handler_t handler; + protocol_t protocol; +} handler_entry_t; + +typedef struct { + uint8_t size; + handler_entry_t* handler; +} pm_table_t; + +void pm_init_table(pm_table_t* table, uint8_t size, handler_entry_t* handler); +int pm_find_handler_index(const pm_table_t* table, protocol_t protocol, unsigned int start); +int pm_set_handler(const pm_table_t* table, protocol_t protocol, packet_handler_t handler); +void pm_remove_handler(const pm_table_t* table, protocol_t protocol, packet_handler_t handler); +int pm_invoke(const pm_table_t* table, protocol_t protocol, void* payload, int payload_size, packet_info_t* packet_info); + +/** @} */ + +#endif /* PROTOCOLMULTIPLEX_H_ */ diff --git a/sys/ping.c b/sys/ping.c new file mode 100644 index 0000000000..465c8aa3a5 --- /dev/null +++ b/sys/ping.c @@ -0,0 +1,78 @@ +#include +#include +#include +#include + +#include "drivers/cc110x/cc1100.h" +#include "lpc2387.h" + +#include "ktimer.h" +#include "swtimer.h" +#include "gpioint.h" +#include + +ping_payload *pipa; +protocol_t protocol_id = 0; +radio_address_t r_address = 0; +uint64_t start = 0; +float rtt = 0; + +void ping_handler(void *payload, int payload_size, + packet_info_t *packet_info){ + pong(packet_info->phy_src); +} + +void pong_handler(void *payload, int payload_size, + packet_info_t *packet_info){ + calc_rtt(); + print_success(); +} + +void pong(uint16_t src){ + int trans_ok = cc1100_send_csmaca(src,protocol_id,2,pipa->payload, + sizeof(pipa->payload)); + if(trans_ok < 0) + print_failed(); +} + +void ping_init(protocol_t protocol, uint8_t channr, radio_address_t addr){ + protocol_id = protocol; + r_address = addr; + cc1100_set_packet_handler(protocol, ping_handler); + cc1100_set_channel(channr); + cc1100_set_address(r_address); + init_payload(); +} + +void ping(radio_address_t addr, uint8_t channr){ + cc1100_set_packet_handler(protocol_id, pong_handler); + cc1100_set_channel(channr); + cc1100_set_address(r_address); + while(1){ + start = swtimer_now(); + int trans_ok = cc1100_send_csmaca(addr, + protocol_id,2,pipa->payload,sizeof(pipa->payload)); + if(trans_ok < 0) + print_failed(); + ktimer_wait(500000); + } +} + +void calc_rtt(){ + uint64_t end = swtimer_now(); + + rtt = ((float)end - (float)start)/1000; +} + +void print_success(void){ + printf("%s%f%s\n","time=",rtt,"ms"); +} + +void print_failed(void){ + printf("%s\n","ping failed"); +} + +void init_payload(void){ + pipa = malloc(sizeof(pipa)); + pipa->payload = NULL; +} diff --git a/sys/swtimer.c b/sys/swtimer.c new file mode 100644 index 0000000000..0faddf39bb --- /dev/null +++ b/sys/swtimer.c @@ -0,0 +1,306 @@ +/** + * + * \ingroup system + * @{ + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#define SWTIMER_OVERHEAD 80 +#define SWTIMER_SPIN_THRESHOLD 100 + +//#define ENABLE_DEBUG + +#ifdef ENABLE_DEBUG +#undef SWTIMER_OVERHEAD +#define SWTIMER_OVERHEAD 7500 +#endif + +#include + +/* workaround for buggy mspgcc signal.h */ +#undef wakeup + +static void swtimer_update_alarm(); +static void swtimer_action(swtimer_t *swtimer); +static void swtimer_trigger(void* ptr); +static void swtimer_tick(void *ptr); +static int swtimer_activate(swtimer_t *t); +static void swtimer_priolist_insert(swtimer_t *t); +static void swtimer_update_values(); + +static swtimer_t *swtimer_list = NULL; +static volatile swtime_t system_time = 0; +volatile swtime_t swtimer_next_alarm_absolute = 0; +static volatile unsigned long hwtimer_ticks_left = 0; +static volatile int hwtimer_id = -1; + +extern unsigned long hwtimer_now(void); + +int swtimer_init() { + hwtimer_set_absolute(HWTIMER_MAXTICKS, swtimer_tick, NULL); + return 0; +} + +int swtimer_set(swtimer_t *t, swtime_t interval) { + t->interval = interval; + t->next = NULL; + swtimer_activate(t); + return 0; +} + +static int swtimer_activate(swtimer_t *t) { + DEBUG("swtimer_activate. now=%lu t->interval = %lu hwtimer_ticks=%lu\n", swtimer_now(), t->interval, HWTIMER_TICKS(t->interval)); + + if (!inISR()) dINT(); + + if (t->interval <= SWTIMER_OVERHEAD) { + DEBUG("swtimer_activate: interval too short, triggering right away.\n"); + swtimer_action(t); + if (!inISR()) eINT(); + return 0; + } + + t->start = swtimer_now(); + + swtimer_priolist_insert(t); + + if (swtimer_list == t) { + swtimer_update_values(); + swtimer_update_alarm(); + } + + if (!inISR())eINT(); + + return 0; +} + +static void swtimer_update_values() { + swtimer_next_alarm_absolute = swtimer_list->start + swtimer_list->interval; + swtime_t now = swtimer_now(); + swtime_t offset = swtimer_next_alarm_absolute - now; + hwtimer_ticks_left = HWTIMER_TICKS(offset); + + if ( offset > swtimer_next_alarm_absolute ) { + DEBUG("swtimer_update_values: underflow corrected.\n"); + hwtimer_ticks_left = 0; + } else { + } + DEBUG("swtimer_update_values abs: %lu offset: %lu hwtimer_ticks_left: %lu, now=%lu, hwtimer_now=%lu\n", swtimer_next_alarm_absolute, offset, hwtimer_ticks_left, swtimer_now(), hwtimer_now()); +} + + +int swtimer_remove(swtimer_t *t) { + if ( (! swtimer_list) || (! t)) { + return -1; + } + + if ( ! inISR() ) dINT(); + if (t == swtimer_list) { + swtimer_list = t->next; + if (swtimer_list) { + swtimer_update_values(); + swtimer_update_alarm(); + } else { + swtimer_next_alarm_absolute = 0; + hwtimer_ticks_left = 0; + hwtimer_remove(hwtimer_id); + hwtimer_id = -1; + } + } else { + swtimer_t *cur = t; + while (cur) { + if (cur->next == t) { + cur->next = cur->next->next; + break; + } + cur = cur->next; + } + } + if (! inISR() ) eINT(); + return 0; +} + +swtime_t swtimer_now() { + swtime_t now = system_time; + now += HWTIMER_TICKS_TO_US(hwtimer_now()); + return now; +} + +int swtimer_set_msg(swtimer_t *t, swtime_t interval, int pid, void *ptr) { + t->action_type = SWTIMER_MSG; + t->action.msg.value = (unsigned int) ptr; + t->action.msg.target_pid = pid; + swtimer_set(t, interval); + return 0; +} + +int swtimer_set_wakeup(swtimer_t *t, swtime_t interval, int pid) { + t->action_type = SWTIMER_WAKEUP; + t->action.wakeup.pid = pid; + swtimer_set(t, interval); + return 0; +} + +int swtimer_set_cb(swtimer_t *t, swtime_t interval, void (*f_ptr)(void *), void *ptr) { + t->action_type = SWTIMER_CALLBACK; + t->action.callback.f = f_ptr; + t->action.callback.ptr = ptr; + swtimer_set(t, interval); + return 0; +} + +static void swtimer_spin(swtime_t us) { + swtime_t target = swtimer_now() + us; + while (target > swtimer_now()); +} + +int swtimer_usleep(swtime_t us) { + if (inISR()) { + swtimer_spin(us); + return 0; + } + swtimer_t t; + t.interval = us; + t.action_type = SWTIMER_WAKEUP; + t.action.wakeup.pid = thread_getpid(); + swtimer_activate(&t); + thread_sleep(); + return 0; +} + +static void swtimer_priolist_insert(swtimer_t *t) { + t->next = NULL; + if (swtimer_list == NULL) { +// DEBUG("swtimer: inserting first timer %x\n", (unsigned int)t); + swtimer_list = t; + } else { +// DEBUG("swtimer: inserting timer %x\n", (unsigned int)t); + swtime_t t_absolute = t->start + t->interval; + swtimer_t *last = NULL; + swtimer_t *cur = swtimer_list; + while (cur != NULL) { + if ( t_absolute < (cur->start + cur->interval) ) { +// DEBUG("swtimer: timer %x elapses before timer %x\n", (unsigned int) t, (unsigned int) cur); + t->next = cur; + if (last) { +// DEBUG("swtimer: setting ->next of %x to %x\n", (unsigned int) last->next, (unsigned int) t); + last->next = t; + } else { +// DEBUG("swtimer: %x is first timer now.\n", (unsigned int)t); + swtimer_list = t; + } + return; + } else { +// DEBUG("insertF\n"); + if ( cur->next ) { +// DEBUG("insertF1\n"); + last = cur; + cur = cur->next; + } else { +// DEBUG("insertF2\n"); + cur->next = t; + return; + } + } + } + } +} + + +static void swtimer_set_hwtimer(unsigned int offset) { + DEBUG("swtimer_set_hwtimer: hwtimer_now: %lu offset:%u\n", hwtimer_now(), offset); + if (hwtimer_id != -1) { + hwtimer_remove(hwtimer_id); + } + + hwtimer_id = hwtimer_set (offset, swtimer_trigger, NULL); +} + +static void swtimer_action(swtimer_t *swtimer) { + switch(swtimer->action_type) { + case SWTIMER_WAKEUP: + { + thread_wakeup(swtimer->action.wakeup.pid); + break; + } + case SWTIMER_CALLBACK: + { + swtimer->action.callback.f(swtimer->action.callback.ptr); + break; + } + case SWTIMER_MSG: + { + msg m; + m.content.value = swtimer->action.msg.value; + int result = msg_send_int(&m, swtimer->action.msg.target_pid); + if (result < 0) { + // error + } + break; + } + } +} + +static void swtimer_trigger(void* ptr) { + swtimer_t *next = swtimer_list; + swtimer_list = swtimer_list->next; + swtimer_action(next); + if (! ptr) swtimer_update_alarm(); +} + + +static void swtimer_update_alarm() { + DEBUG("swtimer_check_elapsed: Checking for elapsed timer...\n"); + + while (swtimer_list) { + swtimer_update_values(); + DEBUG("swtimer_check_elapsed: there are timers left to consider. hwtimer_ticks_left=%lu\n", hwtimer_ticks_left); + + if (hwtimer_ticks_left > HWTIMER_MAXTICKS) { + if ((long int) hwtimer_ticks_left < 0) { + printf("swtimer_update_alarm: We're late!\n"); + } + return; + } + + if (hwtimer_ticks_left < SWTIMER_SPIN_THRESHOLD) { + DEBUG("swtimer_check_elapsed: spinning..\n"); + if (hwtimer_ticks_left != 0) hwtimer_spin(hwtimer_ticks_left); + DEBUG("swtimer_check_elapsed: spinning done. shooting timer.\n"); + swtimer_trigger((void*)1); /* flag to prevent recursion */ + } else { + DEBUG("swtimer_check_elapsed: Setting hwtimer.\n"); + swtimer_set_hwtimer(hwtimer_ticks_left); + return; + } + } +} + + +static void swtimer_tick(void* offset_ptr) { + hwtimer_set_absolute(HWTIMER_MAXTICKS, swtimer_tick, NULL); + system_time += HWTIMER_TICKS_TO_US(HWTIMER_MAXTICKS); + +// DEBUG("swtimer_tick: system_time: %lu next timer: %lu ticks_left: %lu pid=%i\n", system_time, swtimer_next_alarm_absolute, hwtimer_ticks_left, thread_getpid()); + DEBUG("."); + + if (swtimer_next_alarm_absolute > 0) { + if (hwtimer_ticks_left > HWTIMER_MAXTICKS) { + hwtimer_ticks_left -= HWTIMER_MAXTICKS; + swtimer_update_alarm(); + } + } +} + + +/** @} */ diff --git a/testsuite/build_and_generate_html.sh b/testsuite/build_and_generate_html.sh new file mode 100755 index 0000000000..335cd58de4 --- /dev/null +++ b/testsuite/build_and_generate_html.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +test -f ~/.buildbot && . ~/.buildbot + +export REVISION=${1} +export ROOT=${ROOT:-.} + +${ROOT}/testsuite/svn_test_revision.sh ${REVISION} +${ROOT}/testsuite/generate_html.sh + diff --git a/testsuite/generate_html.sh b/testsuite/generate_html.sh new file mode 100755 index 0000000000..2d4b475f74 --- /dev/null +++ b/testsuite/generate_html.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +ROOT=${ROOT:-.} +TOOLROOT=${TOOLROOT:-${ROOT}} +HTMLDIR=${TOOLROOT}/tools/testsuite/html + +test -f ~/.buildbot && . ~/.buildbot + +OUTFILE=${HTMLFILE:-${HOME}/firekernel.html} +LOGDIR=${BUILDLOGS:-${HOME}/buildlogs} + +{ +cat ${HTMLDIR}/header + +for i in `ls -t $LOGDIR/*.log`; do + ${TOOLROOT}/tools/testsuite/parse_buildlog.sh $i + if [ "x${HTTPROOT}x"!="xx" ]; then + echo "
" + echo "Full build log: click here ." + fi + +done + +cat ${HTMLDIR}/footer +} > ${OUTFILE} + + diff --git a/testsuite/html/footer b/testsuite/html/footer new file mode 100644 index 0000000000..a446d53d9d --- /dev/null +++ b/testsuite/html/footer @@ -0,0 +1 @@ + diff --git a/testsuite/html/header b/testsuite/html/header new file mode 100644 index 0000000000..4d9384a397 --- /dev/null +++ b/testsuite/html/header @@ -0,0 +1,6 @@ + +

+ Feuerwhere Build Bot results +
+ + diff --git a/testsuite/parse_buildlog.sh b/testsuite/parse_buildlog.sh new file mode 100755 index 0000000000..3ce5bf53ca --- /dev/null +++ b/testsuite/parse_buildlog.sh @@ -0,0 +1,43 @@ +#!/bin/bash + +LOG=${1} + +if [ "xx${PARSELOG_ALWAYS}xx"=!"xxyxx" ]; then + if [ -f ${LOG}.parsed ]; then + cat ${LOG}.parsed + exit 0 + fi +fi + +{ +#BUILD_FAIL=`grep '\[BUILD FAILED\]' ${LOG} | wc -l` +NUM_FAIL=`grep '\[.* FAILED\]' ${LOG} | wc -l` +NUM_OK=`grep '\[TEST SUCCESSFUL\]' ${LOG} | wc -l` + +REVISION=`awk '/^Revision:/ { print $2; exit}' $LOG` +REPO=`awk '/^Repo:/ { print $2; exit}' $LOG` + + +if [ -f ${LOG}.lock ]; then + BUILD_STATUS="build in progress..." +elif (($NUM_FAIL==0)); then + BUILD_STATUS="OK" +else + BUILD_STATUS="broken!" +fi + +echo "

Revision: ${REVISION} Status: ${BUILD_STATUS}

" + +svn log --incremental -v -l 1 ${REPO}@${REVISION} | sed -e 's/$/
/' + +echo "------------------------------------------------------------------------
" + +if (($NUM_FAIL==0)); then + true +else +echo "
Failed builds/tests:
" + grep '\[.* FAILED\]' ${LOG} | uniq | sed -e 's/$/
/' +fi +} | tee ${1}.parsed + + diff --git a/testsuite/run_tests.sh b/testsuite/run_tests.sh new file mode 100755 index 0000000000..1344e604a3 --- /dev/null +++ b/testsuite/run_tests.sh @@ -0,0 +1,43 @@ +#!/bin/bash + +TOOLROOT=${TOOLROOT:-.} + +flash() { + echo "Building ${1}..." + jam -aq flash || ( echo "[BUILD FAILED] ${1}" && false ) +} + +run_tests() { + TESTDIR=projects/${1}/tests + flash ${PROJECT} || return + for tst in `ls ${TESTDIR}/`; do + echo "Project \"${1}\": Running test ${tst}..." + $TESTDIR/$tst || ( + echo + echo "[TEST FAILED] ${TESTDIR}/${tst}" + ) || echo "[TEST SUCCESSFUL] ${TESTDIR}/${tst}" + done +} + +echo +echo "Running tests..." +echo + +for i in projects/*; do + export PROJECT=`basename $i` + if [ -d projects/${PROJECT}/tests ]; then + { + echo "Testing project ${PROJECT}..." + PORT="`sh ${TOOLROOT}/tools/lock_board.sh`" + FLASHUTIL_SHELL="sh -c" + + echo "Using Target connecting to ${PORT}." + + export PORT FLASHUTIL_SHELL + run_tests ${PROJECT} + + sh ${TOOLROOT}/tools/unlock_board.sh ${PORT} + } 2>&1 + fi +done + diff --git a/testsuite/svn_test_revision.sh b/testsuite/svn_test_revision.sh new file mode 100755 index 0000000000..239ab4b199 --- /dev/null +++ b/testsuite/svn_test_revision.sh @@ -0,0 +1,46 @@ +#!/bin/bash + +. ~/.buildbot + +REPO=${REPO:-https://svn.mi.fu-berlin.de/msb/FeuerWare/trunk} +LOGDIR=${LOGDIR:-${HOME}/buildlogs} + +REVISION=${1:-HEAD} + +LOGBASE="`date +%F-%Hh-%Mm-%Ss`-r${REVISION}-test.log" + +LOGFILE="${LOGDIR}/${LOGBASE}" +TMPDIR=`mktemp -d /dev/shm/svn_test_repo.XXXXXXXXXX` + +TOOLROOT=${TOOLROOT:-.} + +if [ ! -d ${TMPDIR} ]; then exit 1; fi + +touch ${LOGFILE}.lock + +{ + echo "${0} runnning checkout/build/test cycle." + echo "Repo: ${REPO}" + echo "Revision: ${REVISION}" + echo "Temporary directory: ${TMPDIR}..." + echo "Logfilename: ${LOGBASE}" + + cd ${TMPDIR} && + + echo "Checking out..." && + svn co -q -r ${REVISION} ${REPO} && + echo "Done." && + + cd ${TMPDIR}/trunk/board/msba2/tools && make && + cd ${TMPDIR}/trunk && + bash ${TOOLROOT}/tools/testsuite/run_tests.sh + + echo + echo "Test run completed." +} 2>&1 | tee ${LOGFILE} + +rm -f ${LOGFILE}.lock +rm -f ${LOGFILE}.parsed + +rm -rf ${TMPDIR} + diff --git a/tools/testsuite/build_and_generate_html.sh b/tools/testsuite/build_and_generate_html.sh new file mode 100755 index 0000000000..a5807f42e8 --- /dev/null +++ b/tools/testsuite/build_and_generate_html.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +test -f ~/.buildbot && . ~/.buildbot + +export REVISION=${1} +export ROOT=${ROOT:-.} + +${ROOT}/tools/testsuite/svn_test_revision.sh ${REVISION} +${ROOT}/tools/testsuite/generate_html.sh + diff --git a/tools/testsuite/generate_html.sh b/tools/testsuite/generate_html.sh new file mode 100755 index 0000000000..2d4b475f74 --- /dev/null +++ b/tools/testsuite/generate_html.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +ROOT=${ROOT:-.} +TOOLROOT=${TOOLROOT:-${ROOT}} +HTMLDIR=${TOOLROOT}/tools/testsuite/html + +test -f ~/.buildbot && . ~/.buildbot + +OUTFILE=${HTMLFILE:-${HOME}/firekernel.html} +LOGDIR=${BUILDLOGS:-${HOME}/buildlogs} + +{ +cat ${HTMLDIR}/header + +for i in `ls -t $LOGDIR/*.log`; do + ${TOOLROOT}/tools/testsuite/parse_buildlog.sh $i + if [ "x${HTTPROOT}x"!="xx" ]; then + echo "
" + echo "Full build log: click here ." + fi + +done + +cat ${HTMLDIR}/footer +} > ${OUTFILE} + + diff --git a/tools/testsuite/html/footer b/tools/testsuite/html/footer new file mode 100644 index 0000000000..a446d53d9d --- /dev/null +++ b/tools/testsuite/html/footer @@ -0,0 +1 @@ + diff --git a/tools/testsuite/html/header b/tools/testsuite/html/header new file mode 100644 index 0000000000..4d9384a397 --- /dev/null +++ b/tools/testsuite/html/header @@ -0,0 +1,6 @@ + +
+ Feuerwhere Build Bot results +
+ + diff --git a/tools/testsuite/parse_buildlog.sh b/tools/testsuite/parse_buildlog.sh new file mode 100755 index 0000000000..3ce5bf53ca --- /dev/null +++ b/tools/testsuite/parse_buildlog.sh @@ -0,0 +1,43 @@ +#!/bin/bash + +LOG=${1} + +if [ "xx${PARSELOG_ALWAYS}xx"=!"xxyxx" ]; then + if [ -f ${LOG}.parsed ]; then + cat ${LOG}.parsed + exit 0 + fi +fi + +{ +#BUILD_FAIL=`grep '\[BUILD FAILED\]' ${LOG} | wc -l` +NUM_FAIL=`grep '\[.* FAILED\]' ${LOG} | wc -l` +NUM_OK=`grep '\[TEST SUCCESSFUL\]' ${LOG} | wc -l` + +REVISION=`awk '/^Revision:/ { print $2; exit}' $LOG` +REPO=`awk '/^Repo:/ { print $2; exit}' $LOG` + + +if [ -f ${LOG}.lock ]; then + BUILD_STATUS="build in progress..." +elif (($NUM_FAIL==0)); then + BUILD_STATUS="OK" +else + BUILD_STATUS="broken!" +fi + +echo "

Revision: ${REVISION} Status: ${BUILD_STATUS}

" + +svn log --incremental -v -l 1 ${REPO}@${REVISION} | sed -e 's/$/
/' + +echo "------------------------------------------------------------------------
" + +if (($NUM_FAIL==0)); then + true +else +echo "
Failed builds/tests:
" + grep '\[.* FAILED\]' ${LOG} | uniq | sed -e 's/$/
/' +fi +} | tee ${1}.parsed + + diff --git a/tools/testsuite/run_tests.sh b/tools/testsuite/run_tests.sh new file mode 100755 index 0000000000..1344e604a3 --- /dev/null +++ b/tools/testsuite/run_tests.sh @@ -0,0 +1,43 @@ +#!/bin/bash + +TOOLROOT=${TOOLROOT:-.} + +flash() { + echo "Building ${1}..." + jam -aq flash || ( echo "[BUILD FAILED] ${1}" && false ) +} + +run_tests() { + TESTDIR=projects/${1}/tests + flash ${PROJECT} || return + for tst in `ls ${TESTDIR}/`; do + echo "Project \"${1}\": Running test ${tst}..." + $TESTDIR/$tst || ( + echo + echo "[TEST FAILED] ${TESTDIR}/${tst}" + ) || echo "[TEST SUCCESSFUL] ${TESTDIR}/${tst}" + done +} + +echo +echo "Running tests..." +echo + +for i in projects/*; do + export PROJECT=`basename $i` + if [ -d projects/${PROJECT}/tests ]; then + { + echo "Testing project ${PROJECT}..." + PORT="`sh ${TOOLROOT}/tools/lock_board.sh`" + FLASHUTIL_SHELL="sh -c" + + echo "Using Target connecting to ${PORT}." + + export PORT FLASHUTIL_SHELL + run_tests ${PROJECT} + + sh ${TOOLROOT}/tools/unlock_board.sh ${PORT} + } 2>&1 + fi +done + diff --git a/tools/testsuite/svn_test_revision.sh b/tools/testsuite/svn_test_revision.sh new file mode 100755 index 0000000000..239ab4b199 --- /dev/null +++ b/tools/testsuite/svn_test_revision.sh @@ -0,0 +1,46 @@ +#!/bin/bash + +. ~/.buildbot + +REPO=${REPO:-https://svn.mi.fu-berlin.de/msb/FeuerWare/trunk} +LOGDIR=${LOGDIR:-${HOME}/buildlogs} + +REVISION=${1:-HEAD} + +LOGBASE="`date +%F-%Hh-%Mm-%Ss`-r${REVISION}-test.log" + +LOGFILE="${LOGDIR}/${LOGBASE}" +TMPDIR=`mktemp -d /dev/shm/svn_test_repo.XXXXXXXXXX` + +TOOLROOT=${TOOLROOT:-.} + +if [ ! -d ${TMPDIR} ]; then exit 1; fi + +touch ${LOGFILE}.lock + +{ + echo "${0} runnning checkout/build/test cycle." + echo "Repo: ${REPO}" + echo "Revision: ${REVISION}" + echo "Temporary directory: ${TMPDIR}..." + echo "Logfilename: ${LOGBASE}" + + cd ${TMPDIR} && + + echo "Checking out..." && + svn co -q -r ${REVISION} ${REPO} && + echo "Done." && + + cd ${TMPDIR}/trunk/board/msba2/tools && make && + cd ${TMPDIR}/trunk && + bash ${TOOLROOT}/tools/testsuite/run_tests.sh + + echo + echo "Test run completed." +} 2>&1 | tee ${LOGFILE} + +rm -f ${LOGFILE}.lock +rm -f ${LOGFILE}.parsed + +rm -rf ${TMPDIR} + diff --git a/tools/toolchains/build_gnuarm.sh b/tools/toolchains/build_gnuarm.sh new file mode 100755 index 0000000000..2151c1e21c --- /dev/null +++ b/tools/toolchains/build_gnuarm.sh @@ -0,0 +1,170 @@ +#!/bin/bash + +# directory to install compiled binaries into +PREFIX=${HOME}/gnuarm + +# directory to download source files and store intermediates +GNUARM_BUILDDIR=${GNUARM_BUILDDIR:-"/tmp/gnuarm-${USER}"} + +#GCC_VER=4.5.1 +#GCC_MD5=dc8959e31b01a65ce10d269614815054 +GCC_VER=4.3.4 +GCC_MD5=575b3220bb8e7060939c429fc8608d22 + +BINUTILS_VER=2.20.1 +BINUTILS_MD5=9cdfb9d6ec0578c166d3beae5e15c4e5 + +# 1.17.0 is a lot smaller (about 10k for arm7) +#NEWLIB_VER=1.17.0 +#NEWLIB_MD5=9c345928b4f600a211ddc5a6072f8337 + +NEWLIB_VER=1.18.0 +NEWLIB_MD5=3dae127d4aa659d72f8ea8c0ff2a7a20 + +GDB_VER=7.2 +GDB_MD5=64260e6c56979ee750a01055f16091a5 + +#uncomment to support multi-threaded compile +MAKE_THREADS=-j4 + +DOWNLOADER=wget +DOWNLOADER_OPTS="-nv -c" + +# +# Build targets +# +FILES=. + +build_binutils() { + echo "Building binutils..." + if [ ! -e .binutils_extracted ] ; then + tar -xjf ${FILES}/binutils-${BINUTILS_VER}.tar.bz2 + touch .binutils_extracted + fi + rm -rf binutils-build && mkdir -p binutils-build && cd binutils-build && + ../binutils-${BINUTILS_VER}/configure --target=arm-elf --prefix=${PREFIX} --enable-interwork --enable-multilibi --with-float=soft --with-fpu=vfp && + make ${MAKE_THREADS} all CFLAGS=-Wformat=0 && + make install && + cd ${GNUARM_BUILDDIR} +} + +build_gcc() { + echo "Building gcc..." + if [ ! -e .gcc_extracted ] ; then + tar -xjf ${FILES}/gcc-core-${GCC_VER}.tar.bz2 && + touch .gcc_extracted + fi + rm -rf gcc-build && mkdir -p gcc-build && cd gcc-build && + ../gcc-${GCC_VER}/configure --target=arm-elf --prefix=${PREFIX} --enable-interwork --enable-multilib --enable-languages="c" --with-newlib --enable-lto --disable-libssp --disable-hardfloat --with-float=soft --with-fpu=vfp --with-headers=${GNUARM_BUILDDIR}/newlib-${NEWLIB_VER}/newlib/libc/include && + + make ${MAKE_THREADS} all && + make install && + + cd ${GNUARM_BUILDDIR} +} + +extract_newlib() { + if [ ! -e .newlib_extracted ] ; then + echo -n "Extracting newlib..." + tar -xzf ${FILES}/newlib-${NEWLIB_VER}.tar.gz && + touch .newlib_extracted && + echo " Done." + fi +} + +build_newlib() { + cd ${GNUARM_BUILDDIR} && + + if [ ! -e .newlib_extracted ] ; then + extract_newlib + fi + + rm -rf newlib-build && mkdir -p newlib-build && cd newlib-build && + ../newlib-${NEWLIB_VER}/configure --target=arm-elf --prefix=${PREFIX} --enable-interwork --enable-multilib --disable-newlib-supplied-syscalls --enable-newlib-reent-small --enable-newlib-io-long-long --enable-newlib-io-float --with-float=soft --with-fpu=vfp && + #--enable-newlib-supplied-syscalls && + # options to try: --enable-newlib-reent-small + make ${MAKE_THREADS} TARGET_CFLAGS=-DREENTRANT_SYSCALLS_PROVIDED all && + make install && + + # generate zip-file to provide binary download + cd ${PREFIX}/arm-elf && + + # + # package compiled newlib for windows users. any new version must be uploaded to the + # webserver. see manual arm/toolchain/windows for paths and documentation. + # + zip -ru newlib-${NEWLIB_VER}.zip include sys-include lib/*.a lib/thumb/*.a + + cd ${GNUARM_BUILDDIR} +} + +build_gdb() { + echo "Building gdb..." + if [ ! -e .gdb_extracted ] ; then + tar -xjf ${FILES}/gdb-${GDB_VER}.tar.bz2 && + touch .gdb_extracted + fi + rm -rf gdb-build && mkdir -p gdb-build && cd gdb-build && + ../gdb-${GDB_VER}/configure --target=arm-elf --prefix=${PREFIX} --enable-interwork --enable-multilib && + + make ${MAKE_THREADS} all CFLAGS=-D_FORTIFY_SOURCE=0 && + make install && + + cd ${GNUARM_BUILDDIR} +} + +clean() { + echo "Cleaning up..." + rm -rf .gdb_extracted .newlib_extracted .gcc_extracted .binutils_extracted + rm -rf binutils-build gcc-build newlib-build gdb-build +} + +export PATH=$PATH:${PREFIX}/bin + +download() { + download_file http://ftp.gnu.org/gnu/binutils binutils-${BINUTILS_VER}.tar.bz2 ${BINUTILS_MD5} && + download_file ftp://ftp.fu-berlin.de/unix/languages/gcc/releases/gcc-${GCC_VER} gcc-core-${GCC_VER}.tar.bz2 ${GCC_MD5} && + download_file ftp://sources.redhat.com/pub/newlib newlib-${NEWLIB_VER}.tar.gz ${NEWLIB_MD5} && + download_file http://ftp.gnu.org/gnu/gdb gdb-${GDB_VER}.tar.bz2 ${GDB_MD5} +} + +download_file() { + echo "Downloading ${1}/${2}..." + ${DOWNLOADER} ${DOWNLOADER_OPTS} $1/$2 + + echo -n "Checking MD5 of " + echo "${3} ${2}" | md5sum -c - +} + +build_all() { + echo "Starting in ${GNUARM_BUILDDIR}. Installing to ${PREFIX}." + download && + build_binutils && + extract_newlib && + build_gcc && + build_newlib && + build_gdb && + + echo "Build complete." +} + +usage() { + echo "usage: ${0} build_[binutils|gcc|newlib|gdb|all]" + echo "example: ./build_gnuarm build_all" + echo "" + echo "Builds a GNU ARM toolchain. installs to HOME/gnuarm, uses /tmp/gnuarm-USER as temp." + echo "Edit to change these directories." + echo "Run like \"MAKE_THREADS=-j4 ${0} build_all\" to speed up on multicore systems." +} + +if [ -z "${1}" ]; then + usage + exit 1 +fi + +mkdir -p ${GNUARM_BUILDDIR} + +cd ${GNUARM_BUILDDIR} + +$* +