diff options
Diffstat (limited to 'libre/linux-libre-firmware/0002-Add-firmware-for-the-ATUSB-IEEE-802.15.4-USB-Adapter.patch')
-rw-r--r-- | libre/linux-libre-firmware/0002-Add-firmware-for-the-ATUSB-IEEE-802.15.4-USB-Adapter.patch | 4893 |
1 files changed, 0 insertions, 4893 deletions
diff --git a/libre/linux-libre-firmware/0002-Add-firmware-for-the-ATUSB-IEEE-802.15.4-USB-Adapter.patch b/libre/linux-libre-firmware/0002-Add-firmware-for-the-ATUSB-IEEE-802.15.4-USB-Adapter.patch deleted file mode 100644 index aa4cb07dc..000000000 --- a/libre/linux-libre-firmware/0002-Add-firmware-for-the-ATUSB-IEEE-802.15.4-USB-Adapter.patch +++ /dev/null @@ -1,4893 +0,0 @@ -From dd4bc9ff49b9a7075e579fdd62fd930d27a9a7df Mon Sep 17 00:00:00 2001 -From: Jason Self <j@jxself.org> -Date: Thu, 4 Jul 2019 15:55:48 -0700 -Subject: [PATCH 2/8] Add firmware for the ATUSB IEEE 802.15.4 USB Adapter - -http://shop.sysmocom.de/products/atusb/ ---- - INSTALL | 20 +- - Makefile | 6 +- - WHENCE | 12 ++ - atusb/Makefile | 236 +++++++++++++++++++++ - atusb/README | 94 +++++++++ - atusb/an/README | 25 +++ - atusb/an/dec.py | 127 ++++++++++++ - atusb/an/get.py | 31 +++ - atusb/an/plot | 12 ++ - atusb/atusb.c | 63 ++++++ - atusb/board.c | 120 +++++++++++ - atusb/board.h | 95 +++++++++ - atusb/board_app.c | 173 ++++++++++++++++ - atusb/board_atusb.c | 162 +++++++++++++++ - atusb/board_atusb.h | 48 +++++ - atusb/board_hulusb.c | 179 ++++++++++++++++ - atusb/board_hulusb.h | 66 ++++++ - atusb/board_rzusb.c | 169 +++++++++++++++ - atusb/board_rzusb.h | 48 +++++ - atusb/boot.c | 77 +++++++ - atusb/descr.c | 104 ++++++++++ - atusb/ep0.c | 338 ++++++++++++++++++++++++++++++ - atusb/flash.c | 97 +++++++++ - atusb/include/at86rf230.h | 402 ++++++++++++++++++++++++++++++++++++ - atusb/include/atusb/atusb.h | 97 +++++++++ - atusb/include/atusb/ep0.h | 64 ++++++ - atusb/mac.c | 250 ++++++++++++++++++++++ - atusb/mac.h | 26 +++ - atusb/sernum.c | 47 +++++ - atusb/sernum.h | 37 ++++ - atusb/spi.c | 51 +++++ - atusb/spi.h | 30 +++ - atusb/uart.c | 64 ++++++ - atusb/uart.h | 25 +++ - atusb/usb/atu2.c | 247 ++++++++++++++++++++++ - atusb/usb/dfu.c | 260 +++++++++++++++++++++++ - atusb/usb/dfu.h | 119 +++++++++++ - atusb/usb/dfu_common.c | 101 +++++++++ - atusb/usb/usb.c | 181 ++++++++++++++++ - atusb/usb/usb.h | 189 +++++++++++++++++ - atusb/version.h | 23 +++ - 42 files changed, 4512 insertions(+), 3 deletions(-) - create mode 100644 atusb/Makefile - create mode 100644 atusb/README - create mode 100644 atusb/an/README - create mode 100755 atusb/an/dec.py - create mode 100755 atusb/an/get.py - create mode 100755 atusb/an/plot - create mode 100644 atusb/atusb.c - create mode 100644 atusb/board.c - create mode 100644 atusb/board.h - create mode 100644 atusb/board_app.c - create mode 100644 atusb/board_atusb.c - create mode 100644 atusb/board_atusb.h - create mode 100644 atusb/board_hulusb.c - create mode 100644 atusb/board_hulusb.h - create mode 100644 atusb/board_rzusb.c - create mode 100644 atusb/board_rzusb.h - create mode 100644 atusb/boot.c - create mode 100644 atusb/descr.c - create mode 100644 atusb/ep0.c - create mode 100644 atusb/flash.c - create mode 100644 atusb/include/at86rf230.h - create mode 100644 atusb/include/atusb/atusb.h - create mode 100644 atusb/include/atusb/ep0.h - create mode 100644 atusb/mac.c - create mode 100644 atusb/mac.h - create mode 100644 atusb/sernum.c - create mode 100644 atusb/sernum.h - create mode 100644 atusb/spi.c - create mode 100644 atusb/spi.h - create mode 100644 atusb/uart.c - create mode 100644 atusb/uart.h - create mode 100644 atusb/usb/atu2.c - create mode 100644 atusb/usb/dfu.c - create mode 100644 atusb/usb/dfu.h - create mode 100644 atusb/usb/dfu_common.c - create mode 100644 atusb/usb/usb.c - create mode 100644 atusb/usb/usb.h - create mode 100644 atusb/version.h - -diff --git a/INSTALL b/INSTALL -index 74c5cfd..7fb1116 100644 ---- a/INSTALL -+++ b/INSTALL -@@ -16,6 +16,8 @@ In order to build everything you will need the following on the host - system: - - * A C/C++ compiler, like GCC -+ * AVR-GCC -+ * Standard C library for AVR-GCC - * Cmake - * GNU Bison/YACC - * GNU Flex -@@ -32,13 +34,27 @@ system: - - On GNU/Linux distros that use apt you can install these with: - -- apt install binutils-arm-linux-gnueabi binutils-arm-none-eabi bison \ -- cmake flex g++ gcc gcc-arm-linux-gnueabi gcc-arm-none-eabi gperf make wget -+ apt install avr-gcc avr-libc binutils-arm-linux-gnueabi \ -+ binutils-arm-none-eabi bison cmake flex g++ gcc \ -+ gcc-arm-linux-gnueabi gcc-arm-none-eabi gperf make wget - - CARL9170 Firmware Configuration -+------------------------------- - When building the carl9170 firmware you will be prompted with - configuration questions. - -+atusb: Firmware for the ATUSB IEEE 802.15.4 USB Adapter -+------------------------------------------------------- -+ -+To flash the firmware you need dfu-util on the host. Issue -+ -+ make dfu -+ -+right after plugging the device into the USB port while the red led is -+still on. -+ -+Refer to the included README file for more information. -+ - Licensing - --------- - -diff --git a/Makefile b/Makefile -index 21d16fb..8474b30 100644 ---- a/Makefile -+++ b/Makefile -@@ -17,7 +17,7 @@ shell=/bin/sh - prefix=/lib/firmware - install_program=install - --.PHONY: all test clean install a56 as31 aica ath9k_htc_toolchain ath9k_htc av7110 b43-tools carl9170fw-toolchain carl9170fw cis-tools cis dsp56k ihex2fw isci keyspan_pda openfwwf usbdux -+.PHONY: all test clean install a56 as31 aica ath9k_htc_toolchain ath9k_htc atusb av7110 b43-tools carl9170fw-toolchain carl9170fw cis-tools cis dsp56k ihex2fw isci keyspan_pda openfwwf usbdux - - all: aica ath9k_htc av7110 carl9170fw cis dsp56k isci keyspan_pda openfwwf usbdux - -@@ -36,6 +36,9 @@ ath9k_htc_toolchain: - ath9k_htc: ath9k_htc_toolchain - cd ath9k_htc && $(MAKE) -C target_firmware - -+atusb: -+ cd atusb && $(MAKE) -+ - av7110: - cd av7110 && $(MAKE) - -@@ -81,6 +84,7 @@ clean: - if [ -a as31/Makefile ]; then cd as31 && $(MAKE) clean; fi; - cd ath9k_htc && $(MAKE) toolchain-clean - cd ath9k_htc && $(MAKE) -C target_firmware clean -+ cd atusb && $(MAKE) clean - cd av7110 && $(MAKE) clean - cd carl9170fw/toolchain && $(MAKE) clean - if [ -a carl9170fw/Makefile ]; then cd carl9170fw && $(MAKE) clean; fi; -diff --git a/WHENCE b/WHENCE -index 2932155..756de43 100644 ---- a/WHENCE -+++ b/WHENCE -@@ -112,6 +112,18 @@ From https://github.com/qca/open-ath9k-htc-firmware - - -------------------------------------------------------------------------- - -+atusb: Firmware for the ATUSB IEEE 802.15.4 USB Adapter -+http://shop.sysmocom.de/products/atusb/ -+ -+From http://projects.qi-hardware.com/index.php/p/ben-wpan/source/tree/master/atusb/fw -+ -+License: GPL-2.0-or-later -+ -+Version: Based on commit 805db6ebf5d80692158acadf88e239da9d3e67af -+dated September 13 2017 -+ -+-------------------------------------------------------------------------- -+ - Driver: b43 - OpenFWWF -- Free firmware for some Broadcom 43xx series WLAN chips - - License: GPLv2 -diff --git a/atusb/Makefile b/atusb/Makefile -new file mode 100644 -index 0000000..c79cb26 ---- /dev/null -+++ b/atusb/Makefile -@@ -0,0 +1,236 @@ -+# -+# Makefile - Makefile of the ATUSB firmware -+# -+# Written 2010-2011, 2013 by Werner Almesberger -+# Copyright 2010-2011, 2013 by Werner Almesberger -+# -+# 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. -+# -+ -+SHELL = /bin/bash -+ -+NAME = atusb -+DEBUG = false -+ -+CFLAGS = -g -mmcu=$(CHIP) -DBOOT_ADDR=$(BOOT_ADDR) \ -+ -Wall -Wextra -Wshadow -Werror -Wno-unused-parameter \ -+ -Wmissing-prototypes -Wmissing-declarations -Wstrict-prototypes -+ -+ifeq ($(DEBUG),true) -+CFLAGS += -DDEBUG -+endif -+ -+ifeq ($(NAME),rzusb) -+CHIP=at90usb1287 -+CFLAGS += -DRZUSB -DAT86RF230 -+else ifeq ($(NAME),hulusb) -+CHIP=at90usb1287 -+CFLAGS += -DHULUSB -DAT86RF212 -+else -+CHIP=atmega32u2 -+CFLAGS += -DATUSB -DAT86RF231 -+endif -+HOST=jlime -+BOOT_ADDR=0x7000 -+ -+AVR_PREFIX = $(BIN_PATH) avr- -+CC = $(AVR_PREFIX)gcc -+OBJCOPY = $(AVR_PREFIX)objcopy -+#OBJDUMP = $(AVR_PREFIX)objdump -+SIZE = $(AVR_PREFIX)size -+ -+# BCD notion is 0xJJMM with JJ being major and MM being minor. Thus 0x0020 is -+# version 0.2 */ -+USB_BCD_VERSION = 0030 -+USB_VENDOR_ID = 20b7 -+USB_PRODUCT_ID = 1540 -+USB_ID = $(USB_VENDOR_ID):$(USB_PRODUCT_ID) -+ -+OBJS = atusb.o board.o board_app.o sernum.o spi.o descr.o ep0.o \ -+ dfu_common.o usb.o app-atu2.o mac.o -+BOOT_OBJS = boot.o board.o sernum.o spi.o flash.o dfu.o \ -+ dfu_common.o usb.o boot-atu2.o -+ -+ifeq ($(DEBUG),true) -+OBJS += uart.o -+endif -+ -+ifeq ($(NAME),rzusb) -+OBJS += board_rzusb.o -+BOOT_OBJS += board_rzusb.o -+else ifeq ($(NAME),hulusb) -+OBJS += board_hulusb.o -+BOOT_OBJS += board_hulusb.o -+else -+OBJS += board_atusb.o -+BOOT_OBJS += board_atusb.o -+endif -+ -+ -+vpath %.c usb/ -+ -+CFLAGS += -Iinclude -Iusb -I. -+ -+# ----- Verbosity control ----------------------------------------------------- -+ -+CC_normal := $(CC) -+BUILD_normal := -+DEPEND_normal := $(CPP) $(CFLAGS) -MM -MG -+ -+CC_quiet = @echo " CC " $@ && $(CC_normal) -+BUILD_quiet = @echo " BUILD " $@ && $(BUILD_normal) -+DEPEND_quiet = @$(DEPEND_normal) -+ -+ifeq ($(V),1) -+ CC = $(CC_normal) -+ BUILD = $(BUILD_normal) -+ DEPEND = $(DEPEND_normal) -+else -+ CC = $(CC_quiet) -+ BUILD = $(BUILD_quiet) -+ DEPEND = $(DEPEND_quiet) -+endif -+ -+# ----- Rules ----------------------------------------------------------------- -+ -+.PHONY: all clean upload prog dfu update version.c bindist -+.PHONY: prog-app prog-read on off reset -+ -+all: $(NAME).bin boot.hex -+ -+$(NAME).elf: $(OBJS) -+ $(MAKE) version.o -+ $(CC) $(CFLAGS) -o $@ $(OBJS) version.o -+ $(SIZE) $@ -+ -+boot.elf: $(BOOT_OBJS) -+ $(CC) $(CFLAGS) -o $@ $(BOOT_OBJS) \ -+ -Wl,--section-start=.text=$(BOOT_ADDR) -+ $(SIZE) $@ -+ -+%.bin: %.elf -+ $(BUILD) $(OBJCOPY) -j .text -j .data -O binary $< $@ -+ @echo "build #`cat .version`, `ls -l $@`" -+ -+%.dfu: %.bin -+ cp $(NAME).bin $(NAME).dfu -+ dfu-suffix -a $(NAME).dfu -d 0x$(USB_BCD_VERSION) \ -+ -p 0x$(USB_PRODUCT_ID) -v 0x$(USB_VENDOR_ID) -+ -+%.hex: %.elf -+ $(BUILD) $(OBJCOPY) -j .text -j .data -O ihex $< $@ -+ @echo "Size: `$(SIZE) -A boot.hex | sed '/Total */s///p;d'` B" -+ -+# ----- Cleanup --------------------------------------------------------------- -+ -+clean: -+ rm -f $(NAME).bin $(NAME).elf $(NAME).dfu -+ rm -f $(OBJS) $(OBJS:.o=.d) -+ rm -f boot.hex boot.elf -+ rm -f $(BOOT_OBJS) $(BOOT_OBJS:.o=.d) -+ rm -f version.c version.d version.o -+ -+# ----- Build version --------------------------------------------------------- -+ -+version.c: -+ @if [ -f .version ]; then \ -+ v=`cat .version`; \ -+ expr $$v + 1 >.version; \ -+ else \ -+ echo 0 >.version; \ -+ fi -+ @[ -s .version ] || echo 0 >.version -+ @echo '/* MACHINE-GENERATED. DO NOT EDIT ! */' >version.c -+ @echo '#include "version.h"' >>version.c -+ @echo "const char *build_date = \"`date`\";" >>version.c -+ @echo "const uint16_t build_number = `cat .version`;" \ -+ >>version.c -+ -+# ----- Dependencies ---------------------------------------------------------- -+ -+MKDEP = \ -+ $(DEPEND) $< | \ -+ sed \ -+ -e 's|^$(basename $(notdir $<)).o:|$@:|' \ -+ -e '/^\(.*:\)\? */{p;s///;s/ *\\\?$$/ /;s/ */:\n/g;H;}' \ -+ -e '$${g;p;}' \ -+ -e d >$(basename $@).d; \ -+ [ "$${PIPESTATUS[*]}" = "0 0" ] || \ -+ { rm -f $(basename $@).d; exit 1; } -+ -+%.o: %.c -+ $(CC) $(CFLAGS) -Os -c $< -+ $(MKDEP) -+ -+-include $(OBJS:.o=.d) -+ -+# ----- Object file variants -------------------------------------------------- -+ -+app-%.o: usb/%.c -+ $(CC) $(CFLAGS) -Os -o $@ -c $< -+ $(MKDEP) -+ -+boot-%.o: usb/%.c -+ $(CC) $(CFLAGS) -DBOOT_LOADER -Os -o $@ -c $< -+ $(MKDEP) -+ -+# ----- Distribution ---------------------------------------------------------- -+ -+BINDIST_BASE=http://downloads.qi-hardware.com/people/werner/wpan/bindist -+ATUSB_BIN_NAME=atusb-`git rev-parse HEAD | cut -c 1-7`.bin -+ -+bindist: -+ qippl atusb.bin wpan/bindist/$(ATUSB_BIN_NAME) -+ @echo $(BINDIST_BASE)/$(ATUSB_BIN_NAME) -+ @echo md5sum: `md5sum atusb.bin | sed 's/ .*//'` -+ @echo atrf-id: \ -+ `sed '/.*number = \(.*\);/s//#\1/p;d' version.c` \ -+ `sed '/.*date = "\(.*\)";/s//\1/p;d' version.c` -+ -+# ----- Programming and device control ---------------------------------------- -+ -+upload: $(NAME).bin boot.hex -+ scp $(NAME).bin boot.hex $(HOST): -+ -+# lfuse: external clock, slow start-up -+# hfuse: 4 kB boot loader, reset into boot loader -+# lock: allow everything but SPM to the boot loader -+# Note: when trying to program 0xef, we get back 0x2f, failing -+# verification. So we just program 0x2f. -+ -+prog-app: -+ ssh $(HOST) avrdude -F -p $(CHIP) -c nanonote_atusb -e \ -+ -U flash:w:atusb.bin:r \ -+ -U lfuse:w:0x60:m -+ -+prog: -+ ssh $(HOST) avrdude -F -p $(CHIP) -c nanonote_atusb -e \ -+ -U flash:w:boot.hex:i \ -+ -U lfuse:w:0x60:m \ -+ -U hfuse:w:0xd8:m \ -+ -U lock:w:0x2f:m -+ -+prog-read: -+ ssh $(HOST) avrdude -F -p $(CHIP) -c nanonote_atusb \ -+ -U flash:r:mcu.bin:r -+ -+dfu: $(NAME).dfu -+ dfu-util -d $(USB_ID) -D $(NAME).dfu -+ -+update: $(NAME).bin -+ -atrf-reset -a -+ usbwait -r -i 0.01 -t 5 $(USB_ID) -+ $(MAKE) dfu -+ -+on: -+ ssh $(HOST) poke 0x10010318 4 -+ -+off: -+ ssh $(HOST) poke 0x10010314 4 -+ -+reset: -+ ssh $(HOST) poke 0x10010318 2048 -+ ssh $(HOST) poke 0x10010314 2048 -diff --git a/atusb/README b/atusb/README -new file mode 100644 -index 0000000..99ceb22 ---- /dev/null -+++ b/atusb/README -@@ -0,0 +1,94 @@ -+Requires a very recent toolchain, because ATmega32U2 is relatively new. -+ -+- Building: -+ -+ make -+ -+- Uploading the firmware to a Ben (for flashing with the atusb-pgm cable): -+ -+ make HOST=<hostname> upload -+ -+ Example: -+ -+ make HOST=ben upload -+ -+ HOST defaults to "jlime". -+ -+- Flashing the boot loader: -+ -+ Prerequisite: avrdude on the Ben. -+ -+ Disconnect the atusb board from USB. Insert the atusb-pgm connector into -+ the Ben. Place the atusb-pgm adapter on the exposed contact pads of the -+ atusb board and push it down. Then run -+ -+ make prog -+ -+ This takes about 30 seconds. If the programming fails with an error -+ message like "Yikes! Invalid device signature.", verify that the -+ atusb-pgm board is properly connected and placed, then try again. -+ -+- Uploading the application: -+ -+ Prerequisite: dfu-util installed on the PC. -+ -+ Insert atusb into the PC, then run -+ -+ make dfu -+ -+ Note: since the boot loader resets the USB bus after timing out, -+ this operation can fail with a message like "No DFU capable USB device -+ found". Just retry, and it will eventually get through. -+ -+ -+HULUSB notes: -+------------- -+To prepare and flash the firmware on a HULUSB device some additional steps are -+needed; -+ -+avr-objcopy -O ihex -R .signature -R .fuse -R .eeprom hulusb.elf hulusb.hex -+dfu-programmer at90usb1287 flash hulusb.hex -+dfu-programmer at90usb1287 reset -+ -+-------------------------- -+ -+Making the toolchain: -+ -+# patches according to -+# http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&p=789527 -+ -+# some gcc prerequisites -+ -+apt-get remove avr-libc gcc-avr binutils-avr -+apt-get install libmpfr-dev libmpc-dev -+ -+# binutils -+ -+wget http://ftp.gnu.org/gnu/binutils/binutils-2.21.tar.bz2 -+tar xfj binutils-2.21.tar.bz2 -+cd binutils-2.21 -+./configure --target=avr --disable-nls -+make -+make install -+ -+# gcc -+ -+wget http://ftpmirror.gnu.org/gcc/gcc-4.5.2/gcc-4.5.2.tar.bz2 -+wget -O gcc_452_avr.patch http://gcc.gnu.org/bugzilla/attachment.cgi?id=23050 -+tar xfj gcc-4.5.2.tar.bz2 -+cd gcc-4.5.2 -+patch -p1 -s <../gcc_452_avr.patch -+mkdir obj-avr -+cd obj-avr -+../configure --target=avr --enable-languages=c \ -+ --disable-nls --disable-libssp --with-dwarf2 -+make -+make install -+ -+wget http://download.savannah.gnu.org/releases/avr-libc/avr-libc-1.7.1.tar.bz2 -+tar xfj avr-libc-1.7.1.tar.bz2 -+cd avr-libc-1.7.1 -+./bootstrap # the automake at the end takes a while -+./configure --build=`./config.guess` --host=avr -+make -+make install -diff --git a/atusb/an/README b/atusb/an/README -new file mode 100644 -index 0000000..8e0d2fc ---- /dev/null -+++ b/atusb/an/README -@@ -0,0 +1,25 @@ -+workflow: -+ -+- connect zprobe (note: it currently inverts because it didn't have any -+ other chips around. this may change later.) -+ -+- capture the USB signals at an interesting moment with a sample rate of -+ 50 MSa/s -+ -+- zoom into the frame(s) of interest -+ -+- download the data with -+ ./get.py -+ -+- decode with -+ ./dec.py -+ -+ For manual decoding, set the coders to D+ and D- (we need D- for SE0 -+ and SE1 detection), then click on a rising clock edge left of the -+ packet and move the cursor to the right. -+ -+- if there are problems with the clock, the analog signal and digital -+ signals derived from it can be examined after running dec.py with -+ ./plot -+ -+ (Note that the digital zprobe hides any analog anomalies.) -diff --git a/atusb/an/dec.py b/atusb/an/dec.py -new file mode 100755 -index 0000000..8534857 ---- /dev/null -+++ b/atusb/an/dec.py -@@ -0,0 +1,127 @@ -+#!/usr/bin/python -+ -+from tmc.wave import * -+from tmc.dxplore import dxplore -+from tmc.decode import d_usb_stream -+ -+ -+# -+# Clock recovery: we assume that each change in the wave is triggered by a -+# clock edge. We know the clock's nominal period and resynchronize on each -+# edge. Additionally, we can obtain a list of times when a timing violation -+# has occurred. -+# -+# Note that the timing violations logic doesn't make much sense in its present -+# form, since it mainly measures noise (particularly if we're digitizing slow -+# edges) and not clock drift. -+# -+# A more useful metric would be accumulated error from some point of reference -+# or at least the timing of same edges, to eliminate (generally harmless) time -+# offsets introduced by digitizing. -+# -+# So it would probably make more sense for "recover" not to check for timing -+# violations at all, and leave this to more specialized functions. -+# -+def recover(self, period, min = None, max = None, t0 = None): -+ if t0 is None: -+ t0 = self.data[0] -+ v = not self.initial -+ res = [] -+ violations = [] -+ for t in self.data: -+ v = not v -+ if t <= t0: -+ continue -+ n = 0 -+ while t0 < t-period/2: -+ res.append(t0) -+ t0 += period -+ n += 1 -+ if min is not None: -+ if t0-t > n*min: -+ violations.append(t) -+ if max is not None: -+ if t-t0 > n*max: -+ violations.append(t) -+ t0 = t -+ return res, violations -+ -+ -+# -+# Load the analog waves saved by get.py -+# -+wv = waves() -+wv.load("_wv") -+ -+# -+# Digitize the waves and save the result. -+# -+dp = wv[0].digitize(1.5, 1.8) -+dm = wv[1].digitize(1.5, 1.8) -+wv = waves(dp, dm, dp-dm) -+wv.save("_dig") -+ -+# -+# Also record the differential signal. -+# -+wd = wv[1]-wv[0] -+dd = wd.digitize(-0.5, 0.5) -+wd.save("_diff") -+ -+# -+# Run clock recovery on D+/D-. We only need one, but check both to be sure. -+# -+#p = 1/1.5e6 -+p = 1/12e6 -+dp_t, viol = recover(dp, p, p*0.9, p*1.1) -+print viol -+dm_t, viol = recover(dm, p, p*.9, p*1.1, t0 = dp.data[0]) -+print viol -+ -+# -+# Shift the clock by half a period, add a few periods to get steady state and -+# SE0s (if any), and then sample the data lines. -+# -+clk = map(lambda t: t+p/2, dp_t) -+clk.extend((clk[-1]+p, clk[-1]+2*p, clk[-1]+3*p)) -+dp_bv = dp.get(clk) -+dm_bv = dm.get(clk) -+ -+# -+# Save a wave with the recovered clock to make it easier to find the bits in -+# analog graphs. -+# -+dd.data = dp_t; -+dd.save("_clk") -+ -+# -+# For decoding, we need a fake bit clock. We generate it by doubling each data -+# bit and generating a L->H transition during this bit. -+# -+dpd = [] -+dmd = [] -+dck = [] -+ -+# err, silly, seems that we've mixed up D+ and D- all over the place :-) -+print d_usb_stream(dm_bv[:], dp_bv[:]) -+ -+for v in dp_bv: -+ dpd.append(v) -+ dpd.append(v) -+ dck.append(0) -+ dck.append(1) -+ -+for v in dm_bv: -+ dmd.append(v) -+ dmd.append(v) -+ -+# -+# Display the reconstructed digital signal. Note that the absolute time is only -+# correct at the beginning and that relative time is only accurate over -+# intervals in which no significant clock resynchronization has occurred. -+# -+# In fact, dxplore should probably have an option to either turn off time -+# entirely or to display a user-provided time axis. The latter may be a bit -+# tricky to implement. -+# -+dxplore((dmd, dpd, dck), 0, p/2, labels = ("D+", "D-", "CLK")) -diff --git a/atusb/an/get.py b/atusb/an/get.py -new file mode 100755 -index 0000000..685e00f ---- /dev/null -+++ b/atusb/an/get.py -@@ -0,0 +1,31 @@ -+#!/usr/bin/python -+ -+from tmc.scope import rigol_ds1000c -+ -+#-800, +1600 -+s = rigol_ds1000c() -+#s.debug = False -+ -+pos = s.hor.pos -+scale = s.hor.scale -+t0 = pos-scale*s.div_hor/2 -+t1 = pos+scale*s.div_hor/2 -+print t0, t1 -+ -+#zoom = 10 -+#step = scale/s.samples_per_div/zoom -+#print step -+step = 4e-9 -+step = 2e-9 -+ -+w = s.wave((s.ch[0], s.ch[1]), start = t0, end = t1, step = step) -+w[0] = 3.3-w[0] -+w[1] = 3.3-w[1] -+ -+s.hor.pos = pos -+s.hor.scale = scale -+ -+w[0].label = "D+"; -+w[1].label = "D-"; -+ -+w.save("_wv") -diff --git a/atusb/an/plot b/atusb/an/plot -new file mode 100755 -index 0000000..1dea789 ---- /dev/null -+++ b/atusb/an/plot -@@ -0,0 +1,12 @@ -+#!/bin/sh -+# -+# Plot output of "dec" -+# -+gnuplot -persist <<EOF -+set style data lines -+plot "_wv" using 1:(\$2-4), \ -+ "_dig" using 1:(\$2*3.3-4) lw 2, \ -+ "_wv" using 1:3, \ -+ "_dig" using 1:(\$3*3.3) lw 2, \ -+ "_clk" using 1:(\$2+1) lt 7 -+EOF -diff --git a/atusb/atusb.c b/atusb/atusb.c -new file mode 100644 -index 0000000..28faf40 ---- /dev/null -+++ b/atusb/atusb.c -@@ -0,0 +1,63 @@ -+/* -+ * fw/atusb.c - ATUSB initialization and main loop -+ * -+ * Written 2008-2011 by Werner Almesberger -+ * Copyright 2008-2011 Werner Almesberger -+ * -+ * 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. -+ */ -+ -+ -+#include <stdint.h> -+ -+#include <avr/io.h> -+#include <avr/sleep.h> -+#include <avr/interrupt.h> -+ -+#include "usb.h" -+ -+#include "board.h" -+#include "sernum.h" -+#include "spi.h" -+#include "atusb/ep0.h" -+ -+#ifdef DEBUG -+#include "uart.h" -+#endif -+ -+ -+int main(void) -+{ -+ board_init(); -+ board_app_init(); -+ reset_rf(); -+ -+ user_get_descriptor = sernum_get_descr; -+ -+ /* now we should be at 8 MHz */ -+ -+#ifdef DEBUG -+ uart_init(); -+ static FILE atben_stdout = FDEV_SETUP_STREAM(uart_write_char, NULL, -+ _FDEV_SETUP_WRITE); -+ stdout = &atben_stdout; -+#endif -+ -+ usb_init(); -+ ep0_init(); -+#ifdef ATUSB -+ timer_init(); -+ -+ /* move interrupt vectors to 0 */ -+ MCUCR = 1 << IVCE; -+ MCUCR = 0; -+#endif -+ -+ sei(); -+ -+ while (1) -+ sleep_mode(); -+} -diff --git a/atusb/board.c b/atusb/board.c -new file mode 100644 -index 0000000..c3b8d26 ---- /dev/null -+++ b/atusb/board.c -@@ -0,0 +1,120 @@ -+/* -+ * fw/board.c - Board-specific functions (for boot loader and application) -+ * -+ * Written 2011, 2013 by Werner Almesberger -+ * Copyright 2011, 2013 Werner Almesberger -+ * -+ * 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. -+ */ -+ -+ -+#include <stdbool.h> -+#include <stdint.h> -+ -+#include <avr/io.h> -+#include <avr/interrupt.h> -+#include <avr/boot.h> -+ -+#define F_CPU 8000000UL -+#include <util/delay.h> -+ -+#include "usb.h" -+#include "at86rf230.h" -+#include "board.h" -+#include "spi.h" -+ -+ -+uint8_t board_sernum[42] = { 42, USB_DT_STRING }; -+ -+/* ----- Register access --------------------------------------------------- */ -+ -+void change_state(uint8_t new) -+{ -+ while ((reg_read(REG_TRX_STATUS) & TRX_STATUS_MASK) == -+ TRX_STATUS_TRANSITION); -+ reg_write(REG_TRX_STATE, new); -+} -+ -+ -+uint8_t reg_read(uint8_t reg) -+{ -+ uint8_t value; -+ -+ spi_begin(); -+ spi_send(AT86RF230_REG_READ | reg); -+ value = spi_recv(); -+ spi_end(); -+ -+ return value; -+} -+ -+ -+uint8_t subreg_read(uint8_t address, uint8_t mask, uint8_t position) -+{ -+ /* Read current register value and mask out subregister. */ -+ uint8_t register_value = reg_read(address); -+ register_value &= mask; -+ register_value >>= position; /* Align subregister value. */ -+ -+ return register_value; -+} -+ -+ -+void reg_write(uint8_t reg, uint8_t value) -+{ -+ spi_begin(); -+ spi_send(AT86RF230_REG_WRITE | reg); -+ spi_send(value); -+ spi_end(); -+} -+ -+ -+void subreg_write(uint8_t address, uint8_t mask, uint8_t position, uint8_t value) -+{ -+ /* Read current register value and mask area outside the subregister. */ -+ uint8_t register_value = reg_read(address); -+ register_value &= ~mask; -+ -+ /* Start preparing the new subregister value. shift in place and mask. */ -+ value <<= position; -+ value &= mask; -+ -+ value |= register_value; /* Set the new subregister value. */ -+ -+ /* Write the modified register value. */ -+ reg_write(address, value); -+} -+ -+ -+void panic(void) -+{ -+ cli(); -+ while (1) { -+ SET(LED); -+ _delay_ms(100); -+ CLR(LED); -+ _delay_ms(100); -+ } -+} -+ -+ -+static char hex(uint8_t nibble) -+{ -+ return nibble < 10 ? '0'+nibble : 'a'+nibble-10; -+} -+ -+ -+void get_sernum(void) -+{ -+ uint8_t sig; -+ uint8_t i; -+ -+ for (i = 0; i != 10; i++) { -+ sig = boot_signature_byte_get(i+0xe); -+ board_sernum[(i << 2)+2] = hex(sig >> 4); -+ board_sernum[(i << 2)+4] = hex(sig & 0xf); -+ } -+} -diff --git a/atusb/board.h b/atusb/board.h -new file mode 100644 -index 0000000..dbcd410 ---- /dev/null -+++ b/atusb/board.h -@@ -0,0 +1,95 @@ -+/* -+ * fw/board.h - Board-specific functions and definitions -+ * -+ * Written 2008-2011, 2013, 2013 by Werner Almesberger -+ * Copyright 2008-2011, 2013, 2013 Werner Almesberger -+ * -+ * 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. -+ */ -+ -+#ifndef BOARD_H -+#define BOARD_H -+ -+#include <stdbool.h> -+#include <stdint.h> -+ -+#include <atusb/atusb.h> -+ -+#ifdef ATUSB -+#include "board_atusb.h" -+#endif -+#ifdef RZUSB -+#include "board_rzusb.h" -+#endif -+#ifdef HULUSB -+#include "board_hulusb.h" -+#endif -+ -+#define SET_2(p, b) PORT##p |= 1 << (b) -+#define CLR_2(p, b) PORT##p &= ~(1 << (b)) -+#define IN_2(p, b) DDR##p &= ~(1 << (b)) -+#define OUT_2(p, b) DDR##p |= 1 << (b) -+#define PIN_2(p, b) ((PIN##p >> (b)) & 1) -+ -+#define SET_1(p, b) SET_2(p, b) -+#define CLR_1(p, b) CLR_2(p, b) -+#define IN_1(p, b) IN_2(p, b) -+#define OUT_1(p, b) OUT_2(p, b) -+#define PIN_1(p, b) PIN_2(p, b) -+ -+#define SET(n) SET_1(n##_PORT, n##_BIT) -+#define CLR(n) CLR_1(n##_PORT, n##_BIT) -+#define IN(n) IN_1(n##_PORT, n##_BIT) -+#define OUT(n) OUT_1(n##_PORT, n##_BIT) -+#define PIN(n) PIN_1(n##_PORT, n##_BIT) -+ -+ -+#define USB_VENDOR ATUSB_VENDOR_ID -+#define USB_PRODUCT ATUSB_PRODUCT_ID -+ -+#define DFU_USB_VENDOR USB_VENDOR -+#define DFU_USB_PRODUCT USB_PRODUCT -+ -+ -+#define BOARD_MAX_mA 40 -+ -+#ifdef BOOT_LOADER -+#define NUM_EPS 1 -+#else -+#define NUM_EPS 2 -+#endif -+ -+#define HAS_BOARD_SERNUM -+ -+extern uint8_t board_sernum[42]; -+extern uint8_t irq_serial; -+ -+ -+void reset_rf(void); -+void reset_cpu(void); -+uint8_t read_irq(void); -+void slp_tr(void); -+ -+void led(bool on); -+void panic(void); -+ -+uint64_t timer_read(void); -+void timer_init(void); -+ -+bool gpio(uint8_t port, uint8_t data, uint8_t dir, uint8_t mask, uint8_t *res); -+void gpio_cleanup(void); -+ -+void get_sernum(void); -+ -+void board_app_init(void); -+ -+uint8_t reg_read(uint8_t reg); -+uint8_t subreg_read(uint8_t address, uint8_t mask, uint8_t position); -+void reg_write(uint8_t reg, uint8_t value); -+void subreg_write(uint8_t address, uint8_t mask, uint8_t position, uint8_t value); -+void change_state(uint8_t new); -+ -+#endif /* !BOARD_H */ -diff --git a/atusb/board_app.c b/atusb/board_app.c -new file mode 100644 -index 0000000..1fa9bf4 ---- /dev/null -+++ b/atusb/board_app.c -@@ -0,0 +1,173 @@ -+/* -+ * fw/board_app.c - Board-specific functions (for the application) -+ * -+ * Written 2011, 2013 by Werner Almesberger -+ * Copyright 2011, 2013 Werner Almesberger -+ * -+ * 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. -+ */ -+ -+ -+#include <stddef.h> -+#include <stdbool.h> -+#include <stdint.h> -+ -+#include <avr/io.h> -+#include <avr/interrupt.h> -+ -+#define F_CPU 8000000UL -+#include <util/delay.h> -+ -+#include "usb.h" -+#include "at86rf230.h" -+#include "spi.h" -+#include "mac.h" -+#include "board.h" -+ -+ -+static volatile uint32_t timer_h = 0; /* 2^(16+32) / 8 MHz = ~1.1 years */ -+ -+ -+void reset_cpu(void) -+{ -+ WDTCSR = 1 << WDE; -+} -+ -+ -+uint8_t read_irq(void) -+{ -+ return PIN(IRQ_RF); -+} -+ -+ -+void slp_tr(void) -+{ -+ SET(SLP_TR); -+ CLR(SLP_TR); -+} -+ -+ -+ISR(TIMER1_OVF_vect) -+{ -+ timer_h++; -+} -+ -+ -+uint64_t timer_read(void) -+{ -+ uint32_t high; -+ uint8_t low, mid; -+ -+ do { -+ if (TIFR1 & (1 << TOV1)) { -+ TIFR1 = 1 << TOV1; -+ timer_h++; -+ } -+ high = timer_h; -+ low = TCNT1L; -+ mid = TCNT1H; -+ } -+ while (TIFR1 & (1 << TOV1)); -+ -+ /* -+ * We need all these casts because the intermediate results are handled -+ * as if they were signed and thus get sign-expanded. Sounds wrong-ish. -+ */ -+ return (uint64_t) high << 16 | (uint64_t) mid << 8 | (uint64_t) low; -+} -+ -+ -+void timer_init(void) -+{ -+ /* configure timer 1 as a free-running CLK counter */ -+ -+ TCCR1A = 0; -+ TCCR1B = 1 << CS10; -+ -+ /* enable timer overflow interrupt */ -+ -+ TIMSK1 = 1 << TOIE1; -+} -+ -+ -+bool gpio(uint8_t port, uint8_t data, uint8_t dir, uint8_t mask, uint8_t *res) -+{ -+ EIMSK = 0; /* recover INT_RF to ATUSB_GPIO_CLEANUP or an MCU reset */ -+ -+ switch (port) { -+ case 1: -+ DDRB = (DDRB & ~mask) | dir; -+ PORTB = (PORTB & ~mask) | data; -+ break; -+ case 2: -+ DDRC = (DDRC & ~mask) | dir; -+ PORTC = (PORTC & ~mask) | data; -+ break; -+ case 3: -+ DDRD = (DDRD & ~mask) | dir; -+ PORTD = (PORTD & ~mask) | data; -+ break; -+ default: -+ return 0; -+ } -+ -+ /* disable the UART so that we can meddle with these pins as well. */ -+ spi_off(); -+ _delay_ms(1); -+ -+ switch (port) { -+ case 1: -+ res[0] = PINB; -+ res[1] = PORTB; -+ res[2] = DDRB; -+ break; -+ case 2: -+ res[0] = PINC; -+ res[1] = PORTC; -+ res[2] = DDRC; -+ break; -+ case 3: -+ res[0] = PIND; -+ res[1] = PORTD; -+ res[2] = DDRD; -+ break; -+ } -+ -+ return 1; -+} -+ -+ -+void gpio_cleanup(void) -+{ -+ EIMSK = 1 << 0; -+} -+ -+ -+static void done(void *user) -+{ -+ led(0); -+} -+ -+ -+uint8_t irq_serial; -+ -+#if defined(ATUSB) || defined(HULUSB) -+ISR(INT0_vect) -+#endif -+#ifdef RZUSB -+ISR(TIMER1_CAPT_vect) -+#endif -+{ -+ if (mac_irq) { -+ if (mac_irq()) -+ return; -+ } -+ if (eps[1].state == EP_IDLE) { -+ led(1); -+ irq_serial = (irq_serial+1) | 0x80; -+ usb_send(&eps[1], &irq_serial, 1, done, NULL); -+ } -+} -diff --git a/atusb/board_atusb.c b/atusb/board_atusb.c -new file mode 100644 -index 0000000..a02fb7f ---- /dev/null -+++ b/atusb/board_atusb.c -@@ -0,0 +1,162 @@ -+/* -+ * fw/board_atusb.c - ATUSB Board-specific functions (for boot loader and application) -+ * -+ * Written 2016 by Stefan Schmidt -+ * Copyright 2016 Stefan Schmidt -+ * -+ * 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. -+ */ -+ -+ -+#include <stdbool.h> -+#include <stdint.h> -+ -+#include <avr/io.h> -+#include <avr/interrupt.h> -+#include <avr/boot.h> -+ -+#define F_CPU 8000000UL -+#include <util/delay.h> -+ -+#include "usb.h" -+#include "at86rf230.h" -+#include "board.h" -+#include "spi.h" -+#include "usb/usb.h" -+ -+static bool spi_initialized = 0; -+ -+void reset_rf(void) -+{ -+ /* set up all the outputs; default port value is 0 */ -+ -+ DDRB = 0; -+ DDRC = 0; -+ DDRD = 0; -+ PORTB = 0; -+ PORTC = 0; -+ PORTD = 0; -+ -+ OUT(LED); -+ OUT(nRST_RF); /* this also resets the transceiver */ -+ OUT(SLP_TR); -+ -+ spi_init(); -+ -+ /* AT86RF231 data sheet, 12.4.13, reset pulse width: 625 ns (min) */ -+ -+ CLR(nRST_RF); -+ _delay_us(2); -+ SET(nRST_RF); -+ -+ /* 12.4.14: SPI access latency after reset: 625 ns (min) */ -+ -+ _delay_us(2); -+ -+ /* we must restore TRX_CTRL_0 after each reset (9.6.4) */ -+ -+ set_clkm(); -+} -+ -+void led(bool on) -+{ -+ if (on) -+ SET(LED); -+ else -+ CLR(LED); -+} -+ -+void set_clkm(void) -+{ -+ /* switch CLKM to 8 MHz */ -+ -+ /* -+ * @@@ Note: Atmel advise against changing the external clock in -+ * mid-flight. We should therefore switch to the RC clock first, then -+ * crank up the external clock, and finally switch back to the external -+ * clock. The clock switching procedure is described in the ATmega32U2 -+ * data sheet in secton 8.2.2. -+ */ -+ spi_begin(); -+ spi_send(AT86RF230_REG_WRITE | REG_TRX_CTRL_0); -+ spi_send(CLKM_CTRL_8MHz); -+ spi_end(); -+} -+ -+void board_init(void) -+{ -+ /* Disable the watchdog timer */ -+ -+ MCUSR = 0; /* Remove override */ -+ WDTCSR |= 1 << WDCE; /* Enable change */ -+ WDTCSR = 1 << WDCE; /* Disable watchdog while still enabling -+ change */ -+ -+ CLKPR = 1 << CLKPCE; -+ /* We start with a 1 MHz/8 clock. Disable the prescaler. */ -+ CLKPR = 0; -+ -+ get_sernum(); -+} -+ -+void spi_begin(void) -+{ -+ if (!spi_initialized) -+ spi_init(); -+ CLR(nSS); -+} -+ -+void spi_off(void) -+{ -+ spi_initialized = 0; -+ UCSR1B = 0; -+} -+ -+void spi_init(void) -+{ -+ SET(nSS); -+ OUT(SCLK); -+ OUT(MOSI); -+ OUT(nSS); -+ IN(MISO); -+ -+ UBRR1 = 0; /* set bit rate to zero to begin */ -+ UCSR1C = 1 << UMSEL11 | 1 << UMSEL10; -+ /* set MSPI, MSB first, SPI data mode 0 */ -+ UCSR1B = 1 << RXEN1 | 1 << TXEN1; -+ /* enable receiver and transmitter */ -+ UBRR1 = 0; /* reconfirm the bit rate */ -+ -+ spi_initialized = 1; -+} -+ -+void usb_init(void) -+{ -+ USBCON |= 1 << FRZCLK; /* freeze the clock */ -+ -+ /* enable the PLL and wait for it to lock */ -+ PLLCSR &= ~(1 << PLLP2 | 1 << PLLP1 | 1 << PLLP0); -+ PLLCSR |= 1 << PLLE; -+ while (!(PLLCSR & (1 << PLOCK))); -+ -+ USBCON &= ~(1 << USBE); /* reset the controller */ -+ USBCON |= 1 << USBE; -+ -+ USBCON &= ~(1 << FRZCLK); /* thaw the clock */ -+ -+ UDCON &= ~(1 << DETACH); /* attach the pull-up */ -+ UDIEN = 1 << EORSTE; /* enable device interrupts */ -+// UDCON |= 1 << RSTCPU; /* reset CPU on bus reset */ -+ -+ ep_init(); -+} -+ -+void board_app_init(void) -+{ -+ /* enable INT0, trigger on rising edge */ -+ EICRA = 1 << ISC01 | 1 << ISC00; -+ EIMSK = 1 << 0; -+} -diff --git a/atusb/board_atusb.h b/atusb/board_atusb.h -new file mode 100644 -index 0000000..e5974c7 ---- /dev/null -+++ b/atusb/board_atusb.h -@@ -0,0 +1,48 @@ -+/* -+ * fw/board_atusb.h - ATUSB Board-specific functions and definitions -+ * -+ * Written 2016 by Stefan Schmidt -+ * Copyright 2016 Stefan Schmidt -+ * -+ * 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. -+ */ -+ -+#ifndef BOARD_ATUSB_H -+#define BOARD_ATUSB_H -+ -+#include <stdbool.h> -+#include <stdint.h> -+ -+#define LED_PORT B -+#define LED_BIT 6 -+#define nRST_RF_PORT C -+#define nRST_RF_BIT 7 -+#define SLP_TR_PORT B -+#define SLP_TR_BIT 4 -+ -+#define SCLK_PORT D -+#define SCLK_BIT 5 -+#define MOSI_PORT D -+#define MOSI_BIT 3 -+ -+#define MISO_PORT D -+#define MISO_BIT 2 -+#define nSS_PORT D -+#define nSS_BIT 1 -+#define IRQ_RF_PORT D -+#define IRQ_RF_BIT 0 -+ -+#define SPI_WAIT_DONE() while (!(UCSR1A & 1 << RXC1)) -+#define SPI_DATA UDR1 -+ -+void set_clkm(void); -+void board_init(void); -+ -+void spi_begin(void); -+void spi_off(void); -+void spi_init(void); -+ -+#endif /* !BOARD_H */ -diff --git a/atusb/board_hulusb.c b/atusb/board_hulusb.c -new file mode 100644 -index 0000000..084714e ---- /dev/null -+++ b/atusb/board_hulusb.c -@@ -0,0 +1,179 @@ -+/* -+ * fw/board_hulusb.c - Busware HUL Board-specific functions (for boot loader and application) -+ * -+ * Written 2017 by Filzmaier Josef -+ * Based on fw/board_rzusb written and Copyright 2016 Stefan Schmidt -+ * -+ * 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. -+ */ -+ -+ -+#include <stdbool.h> -+#include <stdint.h> -+ -+#include <avr/io.h> -+#include <avr/interrupt.h> -+#include <avr/boot.h> -+ -+#define F_CPU 8000000UL -+#include <util/delay.h> -+ -+#include "usb.h" -+#include "at86rf230.h" -+#include "board.h" -+#include "spi.h" -+#include "usb/usb.h" -+ -+static bool spi_initialized = 0; -+ -+void reset_rf(void) -+{ -+ /* set up all the outputs; default port value is 0 */ -+ -+ DDRB = 0; -+ DDRC = 0; -+ DDRD = 0; -+ PORTB = 0; -+ PORTC = 0; -+ PORTD = 0; -+ -+ OUT(LED_RED); -+ OUT(LED_GREEN); -+ SET(LED_RED); /* Leds are active low on HULUSB board */ -+ CLR(LED_GREEN); /* Green Led indicates the dongle is running */ -+ OUT(nRST_RF); /* this also resets the transceiver */ -+ OUT(SLP_TR); -+ -+ spi_init(); -+ -+ /* AT86RF212 data sheet, Appendix B, p166 Power-On Reset procedure */ -+ /*-----------------------------------------------------------------*/ -+ CLR(SLP_TR); -+ SET(nRST_RF); -+ SET(nSS); -+ _delay_us(400); -+ -+ CLR(nRST_RF); -+ _delay_us(2); -+ SET(nRST_RF); -+ -+ /* 5.1.4.5: Wait t10: 625 ns (min) */ -+ -+ _delay_us(2); -+ -+ reg_write(REG_TRX_CTRL_0, 0x19); -+ -+ change_state(TRX_CMD_FORCE_TRX_OFF); -+ /*-----------------------------------------------------------------*/ -+ -+ /* we must restore TRX_CTRL_0 after each reset (7.7.4) */ -+ -+ set_clkm(); -+} -+ -+void led_red(bool on) { -+ if (on) -+ CLR(LED_RED); -+ else -+ SET(LED_RED); -+} -+ -+void led_green(bool on) { -+ if (on) -+ CLR(LED_GREEN); -+ else -+ SET(LED_GREEN); -+} -+ -+void led(bool on) -+{ -+ led_red(on); -+} -+ -+void set_clkm(void) -+{ -+ /* CLKM is not connected on BUSWARE HUL and therefore it is running in -+ * async mode. */ -+ reg_write(REG_TRX_CTRL_0, 0x00); -+ -+ /* TX_AUTO_CRC_ON, default disabled */ -+ subreg_write(SR_TX_AUTO_CRC_ON, 1); -+} -+ -+void board_init(void) -+{ -+ /* Disable the watchdog timer */ -+ -+ MCUSR = 0; /* Remove override */ -+ WDTCSR |= 1 << WDCE; /* Enable change */ -+ WDTCSR = 1 << WDCE; /* Disable watchdog while still enabling -+ change */ -+ -+ CLKPR = 1 << CLKPCE; -+ /* We start with a 16 MHz/8 clock. Put the prescaler to 2. */ -+ CLKPR = 1 << CLKPS0; -+ -+ get_sernum(); -+} -+ -+void spi_begin(void) -+{ -+ if (!spi_initialized) -+ spi_init(); -+ CLR(nSS); -+} -+ -+void spi_off(void) -+{ -+ spi_initialized = 0; -+ SPCR &= ~(1 << SPE); -+} -+ -+void spi_init(void) -+{ -+ SET(nSS); -+ OUT(SCLK); -+ OUT(MOSI); -+ OUT(nSS); -+ IN(MISO); -+ -+ SPCR = (1 << SPE) | (1 << MSTR); -+ SPSR = (1 << SPI2X); -+ -+ spi_initialized = 1; -+} -+ -+void usb_init(void) -+{ -+ USBCON |= 1 << FRZCLK; /* freeze the clock */ -+ -+ /* enable the PLL and wait for it to lock */ -+ /* TODO sheet page 50 For Atmel AT90USB128x only. Do not use with Atmel AT90USB64x. */ -+ /* FOR 8 XTAL Mhz only!!! */ -+ PLLCSR = ((1 << PLLP1) | (1 << PLLP0)); -+ PLLCSR |= 1 << PLLE; -+ while (!(PLLCSR & (1 << PLOCK))); -+ -+ UHWCON |= (1 << UVREGE); -+ -+ USBCON &= ~((1 << USBE) | (1 << OTGPADE)); /* reset the controller */ -+ USBCON |= ((1 << USBE) | (1 << OTGPADE)); -+ -+ USBCON &= ~(1 << FRZCLK); /* thaw the clock */ -+ -+ UDCON &= ~(1 << DETACH); /* attach the pull-up */ -+ UDIEN = 1 << EORSTE; /* enable device interrupts */ -+ // UDCON |= 1 << RSTCPU; /* reset CPU on bus reset */ -+ -+ ep_init(); -+} -+ -+void board_app_init(void) -+{ -+ /* enable INT0, trigger on rising edge */ -+ EICRA = 1 << ISC01 | 1 << ISC00; -+ EIMSK = 1 << INT0; -+} -diff --git a/atusb/board_hulusb.h b/atusb/board_hulusb.h -new file mode 100644 -index 0000000..a1dadf0 ---- /dev/null -+++ b/atusb/board_hulusb.h -@@ -0,0 +1,66 @@ -+/* -+ * fw/board_hulusb.h - Busware HUL Board-specific functions (for boot loader and application) -+ * -+ * Written 2017 by Filzmaier Josef -+ * Based on fw/board_rzusb written and Copyright 2016 Stefan Schmidt -+ * -+ * 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. -+ */ -+ -+#ifndef BOARD_HULUSB_H -+#define BOARD_HULUSB_H -+ -+#include <stdbool.h> -+#include <stdint.h> -+ -+#define LED_RED_PORT A -+#define LED_GREEN_PORT A -+#define LED_RED_BIT 3 -+#define LED_GREEN_BIT 4 -+#define LED_PORT LED_RED_PORT -+#define LED_BIT LED_RED_BIT -+ -+#define nRST_RF_PORT B -+#define nRST_RF_BIT 5 -+#define SLP_TR_PORT B -+#define SLP_TR_BIT 4 -+ -+#define SCLK_PORT B -+#define SCLK_BIT 1 -+#define MOSI_PORT B -+#define MOSI_BIT 2 -+ -+#define MISO_PORT B -+#define MISO_BIT 3 -+#define nSS_PORT B -+#define nSS_BIT 0 -+#define IRQ_RF_PORT D -+#define IRQ_RF_BIT 4 -+ -+#define SR_TX_AUTO_CRC_ON 0x04, 0x20, 5 -+#define SR_CHANNEL 0x08, 0x1f, 0 -+ -+#define RG_CC_CTRL_1 (0x14) -+ -+#define SPI_WAIT_DONE() while ((SPSR & (1 << SPIF)) == 0) -+#define SPI_DATA SPDR -+ -+void set_clkm(void); -+void board_init(void); -+ -+void led_red(bool on); -+void led_green(bool on); -+ -+void spi_begin(void); -+void spi_off(void); -+void spi_init(void); -+ -+#ifdef DEBUG -+void printStatus(void); -+#define PRINT_STATUS() printStatus() -+#endif -+ -+#endif /* !BOARD_HULUSB_H */ -diff --git a/atusb/board_rzusb.c b/atusb/board_rzusb.c -new file mode 100644 -index 0000000..e83d6fa ---- /dev/null -+++ b/atusb/board_rzusb.c -@@ -0,0 +1,169 @@ -+/* -+ * fw/board_rzusb.c - RZUSB Board-specific functions (for boot loader and application) -+ * -+ * Written 2016 by Stefan Schmidt -+ * Copyright 2016 Stefan Schmidt -+ * -+ * 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. -+ */ -+ -+ -+#include <stdbool.h> -+#include <stdint.h> -+ -+#include <avr/io.h> -+#include <avr/interrupt.h> -+#include <avr/boot.h> -+ -+#define F_CPU 8000000UL -+#include <util/delay.h> -+ -+#include "usb.h" -+#include "at86rf230.h" -+#include "board.h" -+#include "spi.h" -+#include "usb/usb.h" -+ -+static bool spi_initialized = 0; -+ -+void reset_rf(void) -+{ -+ /* set up all the outputs; default port value is 0 */ -+ -+ DDRB = 0; -+ DDRC = 0; -+ DDRD = 0; -+ PORTB = 0; -+ PORTC = 0; -+ PORTD = 0; -+ -+ OUT(LED); -+ OUT(nRST_RF); /* this also resets the transceiver */ -+ OUT(SLP_TR); -+ -+ spi_init(); -+ -+ /* AT86RF231 data sheet, 12.4.13, reset pulse width: 625 ns (min) */ -+ -+ CLR(nRST_RF); -+ _delay_us(2); -+ SET(nRST_RF); -+ -+ /* 12.4.14: SPI access latency after reset: 625 ns (min) */ -+ -+ _delay_us(2); -+ -+ /* we must restore TRX_CTRL_0 after each reset (9.6.4) */ -+ -+ set_clkm(); -+} -+ -+void led(bool on) -+{ -+ if (on) -+ SET(LED); -+ else -+ CLR(LED); -+} -+ -+void set_clkm(void) -+{ -+ /* switch CLKM to 8 MHz */ -+ -+ /* -+ * @@@ Note: Atmel advise against changing the external clock in -+ * mid-flight. We should therefore switch to the RC clock first, then -+ * crank up the external clock, and finally switch back to the external -+ * clock. The clock switching procedure is described in the ATmega32U2 -+ * data sheet in secton 8.2.2. -+ */ -+ spi_begin(); -+ spi_send(AT86RF230_REG_WRITE | REG_TRX_CTRL_0); -+ spi_send(0x10); -+ spi_end(); -+ -+ /* TX_AUTO_CRC_ON, default disabled */ -+ spi_begin(); -+ spi_send(AT86RF230_REG_WRITE | 0x05); -+ spi_send(0x80); -+ spi_end(); -+} -+ -+void board_init(void) -+{ -+ /* Disable the watchdog timer */ -+ -+ MCUSR = 0; /* Remove override */ -+ WDTCSR |= 1 << WDCE; /* Enable change */ -+ WDTCSR = 1 << WDCE; /* Disable watchdog while still enabling -+ change */ -+ -+ CLKPR = 1 << CLKPCE; -+ /* We start with a 16 MHz/8 clock. Put the prescaler to 2. */ -+ CLKPR = 1 << CLKPS0; -+ -+ get_sernum(); -+} -+ -+void spi_begin(void) -+{ -+ if (!spi_initialized) -+ spi_init(); -+ CLR(nSS); -+} -+ -+void spi_off(void) -+{ -+ spi_initialized = 0; -+ SPCR &= ~(1 << SPE); -+} -+ -+void spi_init(void) -+{ -+ SET(nSS); -+ OUT(SCLK); -+ OUT(MOSI); -+ OUT(nSS); -+ IN(MISO); -+ -+ SPCR = (1 << SPE) | (1 << MSTR); -+ SPSR = (1 << SPI2X); -+ -+ spi_initialized = 1; -+} -+ -+void usb_init(void) -+{ -+ USBCON |= 1 << FRZCLK; /* freeze the clock */ -+ -+ /* enable the PLL and wait for it to lock */ -+ /* TODO sheet page 50 For Atmel AT90USB128x only. Do not use with Atmel AT90USB64x. */ -+ /* FOR 8 XTAL Mhz only!!! */ -+ PLLCSR = ((1 << PLLP1) | (1 << PLLP0)); -+ PLLCSR |= 1 << PLLE; -+ while (!(PLLCSR & (1 << PLOCK))); -+ -+ UHWCON |= (1 << UVREGE); -+ -+ USBCON &= ~((1 << USBE) | (1 << OTGPADE)); /* reset the controller */ -+ USBCON |= ((1 << USBE) | (1 << OTGPADE)); -+ -+ USBCON &= ~(1 << FRZCLK); /* thaw the clock */ -+ -+ UDCON &= ~(1 << DETACH); /* attach the pull-up */ -+ UDIEN = 1 << EORSTE; /* enable device interrupts */ -+// UDCON |= 1 << RSTCPU; /* reset CPU on bus reset */ -+ -+ ep_init(); -+} -+ -+void board_app_init(void) -+{ -+ /* enable timer input capture 1, trigger on rising edge */ -+ TCCR1B = (1 << ICES1); -+ TIFR1 = (1 << ICF1); -+ TIMSK1 = (1 << ICIE1); -+} -diff --git a/atusb/board_rzusb.h b/atusb/board_rzusb.h -new file mode 100644 -index 0000000..c2e518f ---- /dev/null -+++ b/atusb/board_rzusb.h -@@ -0,0 +1,48 @@ -+/* -+ * fw/board_rzusb.h - RZUSB Board-specific functions and definitions -+ * -+ * Written 2016 by Stefan Schmidt -+ * Copyright 2016 Stefan Schmidt -+ * -+ * 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. -+ */ -+ -+#ifndef BOARD_RZUSB_H -+#define BOARD_RZUSB_H -+ -+#include <stdbool.h> -+#include <stdint.h> -+ -+#define LED_PORT D -+#define LED_BIT 7 -+#define nRST_RF_PORT B -+#define nRST_RF_BIT 5 -+#define SLP_TR_PORT B -+#define SLP_TR_BIT 4 -+ -+#define SCLK_PORT B -+#define SCLK_BIT 1 -+#define MOSI_PORT B -+#define MOSI_BIT 2 -+ -+#define MISO_PORT B -+#define MISO_BIT 3 -+#define nSS_PORT B -+#define nSS_BIT 0 -+#define IRQ_RF_PORT D -+#define IRQ_RF_BIT 4 -+ -+#define SPI_WAIT_DONE() while ((SPSR & (1 << SPIF)) == 0) -+#define SPI_DATA SPDR -+ -+void set_clkm(void); -+void board_init(void); -+ -+void spi_begin(void); -+void spi_off(void); -+void spi_init(void); -+ -+#endif /* !BOARD_H */ -diff --git a/atusb/boot.c b/atusb/boot.c -new file mode 100644 -index 0000000..6826ac6 ---- /dev/null -+++ b/atusb/boot.c -@@ -0,0 +1,77 @@ -+/* -+ * fw/boot.c - DFU boot loader for ATUSB -+ * -+ * Written 2008-2011 by Werner Almesberger -+ * Copyright 2008-2011 Werner Almesberger -+ * -+ * 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. -+ */ -+ -+ -+#include <stdint.h> -+ -+#include <avr/io.h> -+#include <avr/interrupt.h> -+#include <avr/pgmspace.h> -+ -+#define F_CPU 8000000UL -+#include <util/delay.h> -+ -+#include "usb.h" -+#include "dfu.h" -+ -+#include "board.h" -+#include "spi.h" -+#include "atusb/ep0.h" -+ -+ -+#define MS_TO_LOOPS(ms) ((uint32_t) (ms)*335) -+ -+ -+static void (*run_payload)(void) = 0; -+ -+ -+int main(void) -+{ -+ /* -+ * pgm_read_byte gets cached and there doesn't seem to be any other -+ * way to dissuade gcc from doing this. -+ */ -+ volatile int zero = 0; -+ uint32_t loop = 0; -+ -+ board_init(); -+ reset_rf(); -+ -+ /* now we should be at 8 MHz */ -+ -+ usb_init(); -+ dfu_init(); -+ -+ /* move interrupt vectors to the boot loader */ -+ MCUCR = 1 << IVCE; -+ MCUCR = 1 << IVSEL; -+ -+ sei(); -+ -+ led(1); -+ -+ while (loop != MS_TO_LOOPS(2500)) { -+ if (dfu.state == dfuIDLE && pgm_read_byte(zero) != 0xff) -+ loop++; -+ else -+ loop = 0; -+ } -+ -+ led(0); -+ -+ cli(); -+ -+ usb_reset(); -+ run_payload(); -+ -+ while (1); /* not reached */ -+} -diff --git a/atusb/descr.c b/atusb/descr.c -new file mode 100644 -index 0000000..f96b0ee ---- /dev/null -+++ b/atusb/descr.c -@@ -0,0 +1,104 @@ -+/* -+ * fw/descr.c - USB descriptors -+ * -+ * Written 2008-2011, 2014 by Werner Almesberger -+ * Copyright 2008-2011, 2014 Werner Almesberger -+ * -+ * 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. -+ */ -+ -+ -+#include "usb.h" -+#include "dfu.h" -+#include "board.h" -+ -+ -+#define LE(x) ((uint16_t) (x) & 0xff), ((uint16_t) (x) >> 8) -+ -+/* -+ * Device descriptor -+ */ -+ -+const uint8_t device_descriptor[18] = { -+ 18, /* bLength */ -+ USB_DT_DEVICE, /* bDescriptorType */ -+ LE(0x200), /* bcdUSB */ -+ USB_CLASS_VENDOR_SPEC, /* bDeviceClass */ -+ 0x00, /* bDeviceSubClass */ -+ 0x00, /* bDeviceProtocol */ -+ EP0_SIZE, /* bMaxPacketSize */ -+ LE(USB_VENDOR), /* idVendor */ -+ LE(USB_PRODUCT), /* idProduct */ -+ LE(0x0001), /* bcdDevice */ -+ 0, /* iManufacturer */ -+ 0, /* iProduct */ -+#ifdef HAS_BOARD_SERNUM -+ 1, /* iSerialNumber */ -+#else -+ 0, /* iSerialNumber */ -+#endif -+ 1 /* bNumConfigurations */ -+}; -+ -+ -+/* -+ * Our configuration -+ * -+ * We're always bus-powered. -+ */ -+ -+const uint8_t config_descriptor[] = { -+ 9, /* bLength */ -+ USB_DT_CONFIG, /* bDescriptorType */ -+#if 0 -+ LE(9+9+7+7), /* wTotalLength */ -+#else -+ LE(9+9+7+9), /* wTotalLength */ -+#endif -+ 2, /* bNumInterfaces */ -+ 1, /* bConfigurationValue (> 0 !) */ -+ 0, /* iConfiguration */ -+ USB_ATTR_BUS_POWERED, /* bmAttributes */ -+ ((BOARD_MAX_mA)+1)/2, /* bMaxPower */ -+ -+ /* Interface #0 */ -+ -+ 9, /* bLength */ -+ USB_DT_INTERFACE, /* bDescriptorType */ -+ 0, /* bInterfaceNumber */ -+ 0, /* bAlternateSetting */ -+ 1, /* bNumEndpoints */ -+ USB_CLASS_VENDOR_SPEC, /* bInterfaceClass */ -+ 0, /* bInterfaceSubClass */ -+ 0, /* bInterfaceProtocol */ -+ 0, /* iInterface */ -+ -+#if 0 -+ /* EP OUT */ -+ -+ 7, /* bLength */ -+ USB_DT_ENDPOINT, /* bDescriptorType */ -+ 0x01, /* bEndPointAddress */ -+ 0x02, /* bmAttributes (bulk) */ -+ LE(EP1_SIZE), /* wMaxPacketSize */ -+ 0, /* bInterval */ -+#endif -+ -+#if 1 -+ /* EP IN */ -+ -+ 7, /* bLength */ -+ USB_DT_ENDPOINT, /* bDescriptorType */ -+ 0x81, /* bEndPointAddress */ -+ 0x02, /* bmAttributes (bulk) */ -+ LE(EP1_SIZE), /* wMaxPacketSize */ -+ 0, /* bInterval */ -+#endif -+ -+ /* Interface #1 */ -+ -+ DFU_ITF_DESCR(1, 0, dfu_proto_runtime, 0) -+}; -diff --git a/atusb/ep0.c b/atusb/ep0.c -new file mode 100644 -index 0000000..fa43f3b ---- /dev/null -+++ b/atusb/ep0.c -@@ -0,0 +1,338 @@ -+/* -+ * fw/ep0.c - EP0 extension protocol -+ * -+ * Written 2008-2011, 2013 by Werner Almesberger -+ * Copyright 2008-2011, 2013 Werner Almesberger -+ * Copyright 2015-2016 Stefan Schmidt -+ * -+ * 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. -+ */ -+ -+ -+#include <stdbool.h> -+#include <stdint.h> -+#include <string.h> -+ -+#include <avr/io.h> -+#include <avr/eeprom.h> -+ -+#define F_CPU 8000000UL -+#include <util/delay.h> -+ -+#ifndef NULL -+#define NULL 0 -+#endif -+ -+#include "usb.h" -+#include "dfu.h" -+ -+#include "at86rf230.h" -+#include "atusb/ep0.h" -+#include "version.h" -+#include "board.h" -+#include "sernum.h" -+#include "spi.h" -+#include "mac.h" -+ -+#ifdef ATUSB -+#define HW_TYPE ATUSB_HW_TYPE_110131 -+#endif -+ -+#ifdef RZUSB -+#define HW_TYPE ATUSB_HW_TYPE_RZUSB -+#endif -+ -+#ifdef HULUSB -+#define HW_TYPE ATUSB_HW_TYPE_HULUSB -+#endif -+ -+#ifdef DEBUG -+#include "uart.h" -+#include <stdio.h> -+#define debug(FORMAT,args...) printf(FORMAT,##args) -+#define error(FORMAT,args...) printf(FORMAT,##args) -+#else -+#define debug(...) -+#define error(...) -+#endif -+ -+ -+static const uint8_t id[] = { EP0ATUSB_MAJOR, EP0ATUSB_MINOR, HW_TYPE }; -+static uint8_t buf[MAX_PSDU+3]; /* command, PHDR, and LQI */ -+static uint8_t size; -+ -+ -+static void do_eeprom_write(void *user) -+{ -+ int i; -+ -+ for (i = 0; i < size; i++) -+ eeprom_update_byte((uint8_t*)i, buf[i]); -+} -+ -+static void do_buf_write(void *user) -+{ -+ uint8_t i; -+ -+ spi_begin(); -+ for (i = 0; i != size; i++) -+ spi_send(buf[i]); -+ spi_end(); -+} -+ -+ -+#define BUILD_OFFSET 7 /* '#' plus "65535" plus ' ' */ -+ -+ -+static bool my_setup(const struct setup_request *setup) -+{ -+ uint16_t req = setup->bmRequestType | setup->bRequest << 8; -+ unsigned tmp; -+ uint8_t i; -+ uint64_t tmp64; -+ -+ switch (req) { -+ case ATUSB_FROM_DEV(ATUSB_ID): -+ debug("ATUSB_ID\n"); -+ if (setup->wLength > 3) -+ return 0; -+ usb_send(&eps[0], id, setup->wLength, NULL, NULL); -+ return 1; -+ case ATUSB_FROM_DEV(ATUSB_BUILD): -+ debug("ATUSB_BUILD\n"); -+ tmp = build_number; -+ for (i = BUILD_OFFSET-2; tmp; i--) { -+ buf[i] = (tmp % 10)+'0'; -+ tmp /= 10; -+ } -+ buf[i] = '#'; -+ buf[BUILD_OFFSET-1] = ' '; -+ for (size = 0; build_date[size]; size++) -+ buf[BUILD_OFFSET+size] = build_date[size]; -+ size += BUILD_OFFSET-i; -+ if (size > setup->wLength) -+ return 0; -+ usb_send(&eps[0], buf+i, size, NULL, NULL); -+ return 1; -+ -+ case ATUSB_TO_DEV(ATUSB_RESET): -+ debug("ATUSB_RESET\n"); -+ reset_cpu(); -+ while (1); -+ -+ case ATUSB_TO_DEV(ATUSB_RF_RESET): -+ debug("ATUSB_RF_RESET\n"); -+ reset_rf(); -+ mac_reset(); -+ //ep_send_zlp(EP_CTRL); -+ return 1; -+ -+ case ATUSB_FROM_DEV(ATUSB_POLL_INT): -+ debug("ATUSB_POLL_INT\n"); -+ if (setup->wLength < 1) -+ return 0; -+ *buf = read_irq(); -+ usb_send(&eps[0], buf, 1, NULL, NULL); -+ return 1; -+ -+ case ATUSB_FROM_DEV(ATUSB_TIMER): -+ debug("ATUSB_TIMER\n"); -+ size = setup->wLength; -+ if (size > sizeof(tmp64)) -+ size = sizeof(tmp64); -+ tmp64 = timer_read(); -+ memcpy(buf, &tmp64, sizeof(tmp64)); -+ usb_send(&eps[0], buf, size, NULL, NULL); -+ return 1; -+ -+ case ATUSB_FROM_DEV(ATUSB_GPIO): -+ debug("ATUSB_GPIO\n"); -+ if (setup->wLength < 3) -+ return 0; -+ if (!gpio(setup->wIndex, setup->wValue, setup->wValue >> 8, -+ setup->wIndex >> 8, buf)) -+ return 0; -+ usb_send(&eps[0], buf, 3, NULL, NULL); -+ return 1; -+ case ATUSB_TO_DEV(ATUSB_GPIO_CLEANUP): -+ gpio_cleanup(); -+ return 1; -+ -+ case ATUSB_TO_DEV(ATUSB_SLP_TR): -+ debug("ATUSB_SLP_TR\n"); -+ slp_tr(); -+ return 1; -+ -+ case ATUSB_TO_DEV(ATUSB_REG_WRITE): -+ debug("ATUSB_REG_WRITE\n"); -+ spi_begin(); -+ spi_send(AT86RF230_REG_WRITE | setup->wIndex); -+ spi_send(setup->wValue); -+ spi_end(); -+ //ep_send_zlp(EP_CTRL); -+ return 1; -+ case ATUSB_FROM_DEV(ATUSB_REG_READ): -+ debug("ATUSB_REG_READ\n"); -+ spi_begin(); -+ spi_send(AT86RF230_REG_READ | setup->wIndex); -+ *buf = spi_recv(); -+ spi_end(); -+ usb_send(&eps[0], buf, 1, NULL, NULL); -+ return 1; -+ -+ case ATUSB_TO_DEV(ATUSB_BUF_WRITE): -+ debug("ATUSB_BUF_WRITE\n"); -+ if (setup->wLength < 1) -+ return 0; -+ if (setup->wLength > MAX_PSDU) -+ return 0; -+ buf[0] = AT86RF230_BUF_WRITE; -+ buf[1] = setup->wLength; -+ size = setup->wLength+2; -+ usb_recv(&eps[0], buf+2, setup->wLength, do_buf_write, NULL); -+ return 1; -+ case ATUSB_FROM_DEV(ATUSB_BUF_READ): -+ debug("ATUSB_BUF_READ\n"); -+ if (setup->wLength < 2) /* PHR+LQI */ -+ return 0; -+ if (setup->wLength > MAX_PSDU+2) /* PHR+PSDU+LQI */ -+ return 0; -+ spi_begin(); -+ spi_send(AT86RF230_BUF_READ); -+ size = spi_recv(); -+ if (size >= setup->wLength) -+ size = setup->wLength-1; -+ for (i = 0; i != size+1; i++) -+ buf[i] = spi_recv(); -+ spi_end(); -+ usb_send(&eps[0], buf, size+1, NULL, NULL); -+ return 1; -+ -+ case ATUSB_TO_DEV(ATUSB_SRAM_WRITE): -+ debug("ATUSB_SRAM_WRITE\n"); -+ if (setup->wIndex > SRAM_SIZE) -+ return 0; -+ if (setup->wIndex+setup->wLength > SRAM_SIZE) -+ return 0; -+ buf[0] = AT86RF230_SRAM_WRITE; -+ buf[1] = setup->wIndex; -+ size = setup->wLength+2; -+ usb_recv(&eps[0], buf+2, setup->wLength, do_buf_write, NULL); -+ return 1; -+ case ATUSB_FROM_DEV(ATUSB_SRAM_READ): -+ debug("ATUSB_SRAM_READ\n"); -+ if (setup->wIndex > SRAM_SIZE) -+ return 0; -+ if (setup->wIndex+setup->wLength > SRAM_SIZE) -+ return 0; -+ spi_begin(); -+ spi_send(AT86RF230_SRAM_READ); -+ spi_send(setup->wIndex); -+ for (i = 0; i != setup->wLength; i++) -+ buf[i] = spi_recv(); -+ spi_end(); -+ usb_send(&eps[0], buf, setup->wLength, NULL, NULL); -+ return 1; -+ -+ case ATUSB_TO_DEV(ATUSB_SPI_WRITE): -+ size = setup->wLength+2; -+ if (size > sizeof(buf)) -+ return 0; -+ buf[0] = setup->wValue; -+ buf[1] = setup->wIndex; -+ if (setup->wLength) -+ usb_recv(&eps[0], buf+2, setup->wLength, -+ do_buf_write, NULL); -+ else -+ do_buf_write(NULL); -+ return 1; -+ case ATUSB_FROM_DEV(ATUSB_SPI_WRITE2_SYNC): -+ spi_begin(); -+ spi_send(setup->wValue); -+ spi_send(setup->wIndex); -+ spi_end(); -+ buf[0] = irq_serial; -+ if (setup->wLength) -+ usb_send(&eps[0], buf, 1, NULL, NULL); -+ return 1; -+ -+ case ATUSB_FROM_DEV(ATUSB_SPI_READ1): -+ case ATUSB_FROM_DEV(ATUSB_SPI_READ2): -+ spi_begin(); -+ spi_send(setup->wValue); -+ if (req == ATUSB_FROM_DEV(ATUSB_SPI_READ2)) -+ spi_send(setup->wIndex); -+ for (i = 0; i != setup->wLength; i++) -+ buf[i] = spi_recv(); -+ spi_end(); -+ usb_send(&eps[0], buf, setup->wLength, NULL, NULL); -+ return 1; -+ -+ case ATUSB_TO_DEV(ATUSB_RX_MODE): -+ return mac_rx(setup->wValue); -+ case ATUSB_TO_DEV(ATUSB_TX): -+ return mac_tx(setup->wValue, setup->wIndex, setup->wLength); -+ case ATUSB_TO_DEV(ATUSB_EUI64_WRITE): -+ debug("ATUSB_EUI64_WRITE\n"); -+ usb_recv(&eps[0], buf, setup->wLength, do_eeprom_write, NULL); -+ _delay_ms(100); -+ reset_cpu(); -+ return 1; -+ -+ case ATUSB_FROM_DEV(ATUSB_EUI64_READ): -+ debug("ATUSB_EUI64_READ\n"); -+ eeprom_read_block(buf, (const void*)0, 8); -+ usb_send(&eps[0], buf, 8, NULL, NULL); -+ return 1; -+ -+ default: -+ error("Unrecognized SETUP: 0x%02x 0x%02x ...\n", -+ setup->bmRequestType, setup->bRequest); -+ return 0; -+ } -+} -+ -+ -+static bool my_dfu_setup(const struct setup_request *setup) -+{ -+ switch (setup->bmRequestType | setup->bRequest << 8) { -+ case DFU_TO_DEV(DFU_DETACH): -+ /* @@@ should use wTimeout */ -+ dfu.state = appDETACH; -+ return 1; -+ default: -+ return dfu_setup_common(setup); -+ } -+} -+ -+ -+static void my_set_interface(int nth) -+{ -+ if (nth) { -+ user_setup = my_dfu_setup; -+ user_get_descriptor = dfu_my_descr; -+ dfu.state = appIDLE; -+ } else { -+ user_setup = my_setup; -+ user_get_descriptor = sernum_get_descr; -+ } -+} -+ -+ -+static void my_reset(void) -+{ -+ if (dfu.state == appDETACH) -+ reset_cpu(); -+} -+ -+ -+void ep0_init(void) -+{ -+ user_setup = my_setup; -+ user_set_interface = my_set_interface; -+ my_set_interface(0); -+ user_reset = my_reset; -+} -diff --git a/atusb/flash.c b/atusb/flash.c -new file mode 100644 -index 0000000..1f8e59d ---- /dev/null -+++ b/atusb/flash.c -@@ -0,0 +1,97 @@ -+/* -+ * fw/flash.c - Board-specific flash functions -+ * -+ * Written 2011, 2013-2015 by Werner Almesberger -+ * Copyright 2011, 2013-2015 Werner Almesberger -+ * -+ * 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. -+ */ -+ -+ -+#include <stdbool.h> -+#include <stdint.h> -+ -+#include <avr/boot.h> -+#include <avr/pgmspace.h> -+ -+#include "dfu.h" -+#include "board.h" -+ -+ -+static uint32_t payload; -+ -+ -+static void flash_start(void) -+{ -+ payload = 0; -+} -+ -+ -+static bool flash_can_write(uint16_t size) -+{ -+ return payload+size <= BOOT_ADDR; -+} -+ -+ -+static void flash_write(const uint8_t *buf, uint16_t size) -+{ -+ static uint8_t last; -+ const uint8_t *p; -+ -+ for (p = buf; p != buf+size; p++) { -+ if (!(payload & (SPM_PAGESIZE-1))) { -+ boot_page_erase(payload); -+ boot_spm_busy_wait(); -+ } -+ -+ if (payload & 1) -+ boot_page_fill(payload, last | (*p << 8)); -+ else -+ last = *p; -+ payload++; -+ -+ if (!(payload & (SPM_PAGESIZE-1))) { -+ boot_page_write(payload-SPM_PAGESIZE); -+ boot_spm_busy_wait(); -+ } -+ } -+} -+ -+ -+static void flash_end_write(void) -+{ -+ if (payload & (SPM_PAGESIZE-1)) { -+ boot_page_write(payload & ~(SPM_PAGESIZE-1)); -+ boot_spm_busy_wait(); -+ } -+ boot_rww_enable(); -+} -+ -+ -+static uint16_t flash_read(uint8_t *buf, uint16_t size) -+{ -+ uint16_t got = 0; -+ -+ while (size && payload != (uint32_t) FLASHEND+1) { -+ *buf++ = pgm_read_byte(payload); -+ payload++; -+ size--; -+ got++; -+ } -+ return got; -+} -+ -+ -+static const struct dfu_flash_ops flash_ops = { -+ .start = flash_start, -+ .can_write = flash_can_write, -+ .write = flash_write, -+ .end_write = flash_end_write, -+ .read = flash_read, -+}; -+ -+ -+const struct dfu_flash_ops *dfu_flash_ops = &flash_ops; -diff --git a/atusb/include/at86rf230.h b/atusb/include/at86rf230.h -new file mode 100644 -index 0000000..4c3ae22 ---- /dev/null -+++ b/atusb/include/at86rf230.h -@@ -0,0 +1,402 @@ -+/* -+ * include/at86rf230.h - AT86RF230/AT86RF231 protocol and register definitions -+ * -+ * Written 2008-2011 by Werner Almesberger -+ * Copyright 2008-2011 Werner Almesberger -+ * -+ * 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. -+ */ -+ -+ -+#ifndef AT86RF230_H -+#define AT86RF230_H -+ -+enum { -+ AT86RF230_REG_WRITE = 0xc0, /* 11... */ -+ AT86RF230_REG_READ = 0x80, /* 10... */ -+ AT86RF230_BUF_WRITE = 0x60, /* 011... */ -+ AT86RF230_BUF_READ = 0x20, /* 001... */ -+ AT86RF230_SRAM_WRITE = 0x40, /* 010... */ -+ AT86RF230_SRAM_READ = 0x00 /* 000... */ -+}; -+ -+#define MAX_PSDU 127 /* octets, see AT86RF230 manual section 8.1 */ -+#define SRAM_SIZE 128 -+ -+ -+/* --- Registers ----------------------------------------------------------- */ -+ -+enum { -+ REG_TRX_STATUS = 0x01, -+ REG_TRX_STATE = 0x02, -+ REG_TRX_CTRL_0 = 0x03, -+ -+ REG_TRX_CTRL_1 = 0x04, /* 231 only */ -+ -+ REG_PHY_TX_PWR = 0x05, -+ REG_PHY_RSSI = 0x06, -+ REG_PHY_ED_LEVEL = 0x07, -+ REG_PHY_CC_CCA = 0x08, -+ REG_CCA_THRES = 0x09, -+ -+ REG_RX_CTRL = 0x0a, /* 231 only */ -+ REG_SFD_VALUE = 0x0b, /* 231 only */ -+ REG_TRX_CTRL_2 = 0x0c, /* 231 only */ -+ REG_ANT_DIV = 0x0d, /* 231 only */ -+ -+ REG_IRQ_MASK = 0x0e, -+ REG_IRQ_STATUS = 0x0f, -+ REG_VREG_CTRL = 0x10, -+ REG_BATMON = 0x11, -+ REG_XOSC_CTRL = 0x12, -+ -+ REG_RX_SYN = 0x15, /* 231 only */ -+ REG_XAH_CTRL_1 = 0x17, /* 231 only */ -+ REG_FTN_CTRL = 0x18, /* 231 only */ -+ -+ REG_PLL_CF = 0x1a, -+ REL_PLL_DCU = 0x1b, -+ REG_PART_NUM = 0x1c, -+ REG_VERSION_NUM = 0x1d, -+ REG_MAN_ID_0 = 0x1e, -+ REG_MAN_ID_1 = 0x1f, -+ REG_SHORT_ADDR_0 = 0x20, -+ REG_SHORT_ADDR_1 = 0x21, -+ REG_PAN_ID_0 = 0x22, -+ REG_PAN_ID_1 = 0x23, -+ REG_IEEE_ADDR_0 = 0x24, -+ REG_IEEE_ADDR_1 = 0x25, -+ REG_IEEE_ADDR_2 = 0x26, -+ REG_IEEE_ADDR_3 = 0x27, -+ REG_IEEE_ADDR_4 = 0x28, -+ REG_IEEE_ADDR_5 = 0x29, -+ REG_IEEE_ADDR_6 = 0x2a, -+ REG_IEEE_ADDR_7 = 0x2b, -+ -+ REG_XAH_CTRL_0 = 0x2c, /* XAH_CTRL in 230 */ -+ REG_CSMA_SEED_0 = 0x2d, -+ REG_CSMA_SEED_1 = 0x2e, -+ REG_CSMA_BE = 0x2f, /* 231 only */ -+ -+ REG_CONT_TX_0 = 0x36, -+ REG_CONT_TX_1 = 0x3d, /* 230 only */ -+}; -+ -+/* --- TRX_STATUS --- ------------------------------------------------------ */ -+ -+#define CCA_DONE (1 << 7) -+#define CCA_STATUS (1 << 6) -+ -+#define TRX_STATUS_SHIFT 0 -+#define TRX_STATUS_MASK 0x1f -+ -+enum { -+ TRX_STATUS_P_ON = 0x00, /* reset default */ -+ TRX_STATUS_BUSY_RX = 0x01, -+ TRX_STATUS_BUSY_TX = 0x02, -+ TRX_STATUS_RX_ON = 0x06, -+ TRX_STATUS_TRX_OFF = 0x08, -+ TRX_STATUS_PLL_ON = 0x09, -+ TRX_STATUS_SLEEP = 0x0f, -+ TRX_STATUS_BUSY_RX_AACK = 0x11, -+ TRX_STATUS_BUSY_TX_ARET = 0x12, -+ TRX_STATUS_RX_AACK_ON = 0x16, -+ TRX_STATUS_TX_ARET_ON = 0x19, -+ TRX_STATUS_RX_ON_NOCLK = 0x1c, -+ TRX_STATUS_RX_AACK_ON_NOCLK = 0x1d, -+ TRX_STATUS_BUSY_RX_AACK_NOCLK = 0x1e, -+ TRX_STATUS_TRANSITION = 0x1f /* ..._IN_PROGRESS */ -+}; -+ -+/* --- TRX_STATE ----------------------------------------------------------- */ -+ -+#define TRAC_STATUS_SHIFT 5 -+#define TRAC_STATUS_MASK 7 -+ -+enum { -+ TRAC_STATUS_SUCCESS = 0, /* reset default */ -+ TRAC_STATUS_SUCCESS_DATA_PENDING = 1, -+ TRAC_STATUS_SUCCESS_WAIT_FOR_ACK = 2, /* 231 only */ -+ TRAC_STATUS_CHANNEL_ACCESS_FAILURE = 3, -+ TRAC_STATUS_NO_ACK = 5, -+ TRAC_STATUS_INVALID = 7 -+}; -+ -+#define TRX_CMD_SHIFT 0 -+#define TRX_CMD_MASK 0x1f -+ -+enum { -+ TRX_CMD_NOP = 0x00, /* reset default */ -+ TRX_CMD_TX_START = 0x02, -+ TRX_CMD_FORCE_TRX_OFF = 0x03, -+ TRX_CMD_FORCE_PLL_ON = 0x04, /* 231 only */ -+ TRX_CMD_RX_ON = 0x06, -+ TRX_CMD_TRX_OFF = 0x08, -+ TRX_CMD_PLL_ON = 0x09, -+ TRX_CMD_RX_AACK_ON = 0x16, -+ TRX_CMD_TX_ARET_ON = 0x19, -+}; -+ -+/* --- TRX_CTRL_0 ---------------------------------------------------------- */ -+ -+#define PAD_IO_SHIFT 6 -+#define PAD_IO_MASK 3 -+ -+enum { -+ PAD_IO_2mA, /* reset default */ -+ PAD_IO_4mA, -+ PAD_IO_6mA, -+ PAD_IO_8mA -+}; -+ -+#define PAD_IO_CLKM_SHIFT 4 -+#define PAD_IO_CLKM_MASK 3 -+ -+enum { -+ PAD_IO_CLKM_2mA, -+ PAD_IO_CLKM_4mA, /* reset default */ -+ PAD_IO_CLKM_5mA, -+ PAD_IO_CLKM_8mA, -+}; -+ -+#define CLKM_SHA_SEL (1 << 3) -+ -+#define CLKM_CTRL_SHIFT 0 -+#define CLKM_CTRL_MASK 7 -+ -+enum { -+ CLKM_CTRL_OFF = 0, -+ CLKM_CTRL_1MHz = 1, /* reset default */ -+ CLKM_CTRL_2MHz = 2, -+ CLKM_CTRL_4MHz = 3, -+ CLKM_CTRL_8MHz = 4, -+ CLKM_CTRL_16MHz = 5 -+}; -+ -+/* --- TRX_CTRL_1 (231 only) ----------------------------------------------- */ -+ -+#define PA_EXT_EN (1 << 7) -+#define IRQ_2_EXT_EN (1 << 6) -+#define TX_AUTO_CRC_ON (1 << 5) /* 231 location */ -+#define RX_BL_CTRL (1 << 4) -+ -+#define SPI_CMD_MODE_SHIFT 2 -+#define SPI_CMD_MODE_MASK 3 -+ -+enum { -+ SPI_CMD_MODE_EMPTY = 0, /* reset default */ -+ SPI_CMD_MODE_TRX_STATUS = 1, -+ SPI_CMD_MODE_PHY_RSSI = 2, -+ SPI_CMD_MODE_IRQ_STATUS = 3, -+}; -+ -+#define IRQ_MASK_MODE (1 << 1) -+#define IRQ_POLARITY (1 << 0) -+ -+/* --- PHY_TX_PWR ---------------------------------------------------------- */ -+ -+#define TX_AUTO_CRC_ON_230 (1 << 7) /* 230 location */ -+ -+#define PA_BUF_LT_SHIFT 6 -+#define PA_BUF_LT_MASK 3 -+ -+#define PA_LT_SHIFT 4 -+#define PA_LT_MASK 3 -+ -+#define TX_PWR_SHIFT 0 -+#define TX_PWR_MASK 0x0f -+ -+/* --- PHY_RSSI ------------------------------------------------------------ */ -+ -+#define RX_CRC_VALID (1 << 7) -+ -+#define RND_VALUE_SHIFT 5 /* 231 only */ -+#define RND_VALUE_MASK 3 -+ -+#define RSSI_SHIFT 0 -+#define RSSI_MASK 0x1f -+ -+/* --- PHY_CC_CCA ---------------------------------------------------------- */ -+ -+#define CCA_REQUEST (1 << 7) -+ -+#define CCA_MODE_SHIFT 5 -+#define CCA_MODE_MASK 3 -+ -+enum { -+ CCA_MODE_CARRIER_OR_ENERGY = 0, /* 231 only */ -+ CCA_MODE_ENERGY = 1, /* reset default */ -+ CCA_MODE_CARRIER = 2, -+ CCA_MODE_CARRIER_AND_ENERGY = 3 -+}; -+ -+#define CHANNEL_SHIFT 0 -+#define CHANNEL_MASK 0x1f -+ -+/* --- CCA_THRES ----------------------------------------------------------- */ -+ -+#define CCA_ED_THRES_SHIFT 0 -+#define CCA_ED_THRES_MASK 0x0f -+ -+/* --- RX_CTRL (231 only) -------------------------------------------------- */ -+ -+#define PDT_THRES_SHIFT 0 -+#define PDT_THRES_MASK 0x0f -+ -+enum { -+ PDT_THRES_DEFAULT = 0x07, /* reset default */ -+ PDT_THRES_DIVERSITY = 0x03, -+}; -+ -+/* --- TRX_CTRL_2 (231 only) ----------------------------------------------- */ -+ -+#define RX_SAFE_MODE (1 << 7) -+ -+#define OQPSK_DATA_RATE_SHIFT 0 -+#define OQPSK_DATA_RATE_MASK 3 -+ -+enum { -+ OQPSK_DATA_RATE_250 = 0, /* reset default */ -+ OQPSK_DATA_RATE_500 = 1, -+ OQPSK_DATA_RATE_1000 = 2, -+ OQPSK_DATA_RATE_2000 = 3 -+}; -+ -+/* --- ANT_DIV (231 only) -------------------------------------------------- */ -+ -+#define ANT_SEL (1 << 7) -+#define ANT_DIV_EN (1 << 3) -+#define ANT_EXT_SW_EN (1 << 2) -+ -+#define ANT_CTRL_SHIFT 0 -+#define ANT_CTRL_MASK 3 -+ -+enum { -+ ANT_CTRL_ANT_0 = 1, -+ ANT_CTRL_ANT_1 = 2, -+ ANT_CTRL_NODIV = 3, /* reset default */ -+}; -+ -+/* --- IRQ_MASK/IRQ_STATUS ------------------------------------------------- */ -+ -+enum { -+ IRQ_PLL_LOCK = 1 << 0, -+ IRQ_PLL_UNLOCK = 1 << 1, -+ IRQ_RX_START = 1 << 2, -+ IRQ_TRX_END = 1 << 3, -+ IRQ_CCA_ED_DONE = 1 << 4, /* 231 only */ -+ IRQ_AMI = 1 << 5, /* 231 only */ -+ IRQ_TRX_UR = 1 << 6, -+ IRQ_BAT_LOW = 1 << 7 -+}; -+ -+/* --- VREG_CTRL ----------------------------------------------------------- */ -+ -+#define AVREG_EXT (1 << 7) -+#define AVDD_OK (1 << 6) -+#define DVREG_EXT (1 << 3) -+#define DVDD_OK (1 << 2) -+ -+/* --- BATMON -------------------------------------------------------------- */ -+ -+#define BATMON_OK (1 << 5) -+#define BATMON_HR (1 << 4) -+ -+#define BATMON_VTH_SHIFT 0 -+#define BATMON_VTH_MASK 0x0f -+ -+/* --- XOSC_CTRL ----------------------------------------------------------- */ -+ -+#define XTAL_MODE_SHIFT 4 -+#define XTAL_MODE_MASK 0x0f -+ -+enum { -+ XTAL_MODE_OFF = 0x0, /* 230 only */ -+ XTAL_MODE_EXT = 0x4, -+ XTAL_MODE_INT = 0xf /* reset default */ -+}; -+ -+#define XTAL_TRIM_SHIFT 4 -+#define XTAL_TRIM_MASK 0x0f -+ -+/* --- RX_SYN (231 only) --------------------------------------------------- */ -+ -+#define RX_PDT_DIS (1 << 7) -+ -+#define RX_PDT_LEVEL_SHIFT 0 -+#define RX_PDT_LEVEL_MASK 0xf -+ -+/* --- XAH_CTRL_1 (231 only) ----------------------------------------------- */ -+ -+#define AACK_FLTR_RES_FT (1 << 5) -+#define AACK_UPLD_RES_FT (1 << 4) -+#define AACK_ACK_TIME (1 << 2) -+#define AACK_PROM_MODE (1 << 1) -+ -+/* --- FTN_CTRL (231 only) ------------------------------------------------- */ -+ -+#define FTN_START (1 << 7) -+ -+/* --- PLL_CF -------------------------------------------------------------- */ -+ -+#define PLL_CF_START (1 << 7) -+ -+/* --- PLL_DCU ------------------------------------------------------------- */ -+ -+#define PLL_DCU_START (1 << 7) -+ -+/* --- XAH_CTRL_0 (XAH_CTRL in 230) ---------------------------------------- */ -+ -+#define MAX_FRAME_RETRIES_SHIFT 4 -+#define MAX_FRAME_RETRIES_MASK 0x0f -+ -+#define MAX_CSMA_RETRIES_SHIFT 1 -+#define MAX_CSMA_RETRIES_MASK 0x07 -+ -+#define SLOTTED_OPERATION (1 << 0) /* 231 only */ -+ -+/* --- CSMA_SEED_1 --------------------------------------------------------- */ -+ -+#define MIN_BE_SHIFT_230 6 /* 230 location */ -+#define MIN_BE_MASK_230 3 -+ -+#define AACK_FVN_MODE_SHIFT 6 /* 231 only */ -+#define AACK_FVN_MODE_MASK 3 -+ -+enum { -+ AACK_FVN_MODE_0 = 0, -+ AACK_FVN_MODE_01 = 1, /* reset default */ -+ AACK_FVN_MODE_012 = 2, -+ AACK_FVN_MODE_ANY = 3 -+}; -+ -+#define AACK_SET_PD (1 << 5) -+#define AACK_DIS_ACK (1 << 4) /* 231 only */ -+#define I_AM_COORD (1 << 3) -+ -+#define CSMA_SEED_1_SHIFT 0 -+#define CSMA_SEED_1_MASK 7 -+ -+/* --- CSMA_BE ------------------------------------------------------------- */ -+ -+#define MAX_BE_SHIFT 4 -+#define MAX_BE_MASK 0x0f -+ -+#define MIN_BE_SHIFT 0 /* 231 location */ -+#define MIN_BE_MASK 0x0f -+ -+/* --- REG_CONT_TX_0 ------------------------------------------------------- */ -+ -+#define CONT_TX_MAGIC 0x0f -+ -+/* --- REG_CONT_TX_1 (230 only) -------------------------------------------- */ -+ -+#define CONT_TX_MOD 0x00 /* modulated */ -+#define CONT_TX_M2M 0x10 /* f_CH-2 MHz */ -+#define CONT_TX_M500K 0x80 /* f_CH-0.5 MHz */ -+#define CONT_TX_P500K 0xc0 /* f_CH+0.5 MHz */ -+ -+#endif /* !AT86RF230_H */ -diff --git a/atusb/include/atusb/atusb.h b/atusb/include/atusb/atusb.h -new file mode 100644 -index 0000000..555d14b ---- /dev/null -+++ b/atusb/include/atusb/atusb.h -@@ -0,0 +1,97 @@ -+/* -+ * atusb.h - Definitions shared between kernel and ATUSB firmware -+ * -+ * Written 2013 by Werner Almesberger <werner@almesberger.net> -+ * -+ * 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, version 2, or -+ * (at your option) any later version. -+ * -+ * This file should be identical for kernel and firmware. -+ * Kernel: drivers/net/ieee802154/atusb.h -+ * Firmware: ben-wpan/atusb/fw/include/atusb/atusb.h -+ */ -+ -+#ifndef _ATUSB_H -+#define _ATUSB_H -+ -+#define ATUSB_VENDOR_ID 0x20b7 /* Qi Hardware*/ -+#define ATUSB_PRODUCT_ID 0x1540 /* 802.15.4, device 0 */ -+ /* -- - - */ -+ -+#define ATUSB_BUILD_SIZE 256 /* maximum build version/date message length */ -+ -+/* Commands to our device. Make sure this is synced with the firmware */ -+enum atusb_requests { -+ ATUSB_ID = 0x00, /* system status/control grp */ -+ ATUSB_BUILD, -+ ATUSB_RESET, -+ ATUSB_RF_RESET = 0x10, /* debug/test group */ -+ ATUSB_POLL_INT, -+ ATUSB_TEST, /* atusb-sil only */ -+ ATUSB_TIMER, -+ ATUSB_GPIO, -+ ATUSB_SLP_TR, -+ ATUSB_GPIO_CLEANUP, -+ ATUSB_REG_WRITE = 0x20, /* transceiver group */ -+ ATUSB_REG_READ, -+ ATUSB_BUF_WRITE, -+ ATUSB_BUF_READ, -+ ATUSB_SRAM_WRITE, -+ ATUSB_SRAM_READ, -+ ATUSB_SPI_WRITE = 0x30, /* SPI group */ -+ ATUSB_SPI_READ1, -+ ATUSB_SPI_READ2, -+ ATUSB_SPI_WRITE2_SYNC, -+ ATUSB_RX_MODE = 0x40, /* HardMAC group */ -+ ATUSB_TX, -+ ATUSB_EUI64_WRITE = 0x50, /* Parameter in EEPROM grp */ -+ ATUSB_EUI64_READ, -+}; -+ -+enum { -+ ATUSB_HW_TYPE_100813, /* 2010-08-13 */ -+ ATUSB_HW_TYPE_101216, /* 2010-12-16 */ -+ ATUSB_HW_TYPE_110131, /* 2011-01-31, ATmega32U2-based */ -+ ATUSB_HW_TYPE_RZUSB, /* Atmel Raven USB dongle with at86rf230 */ -+ ATUSB_HW_TYPE_HULUSB, /* Busware HUL USB dongle with at86rf212 */ -+}; -+ -+/* -+ * Direction bRequest wValue wIndex wLength -+ * -+ * ->host ATUSB_ID - - 3 -+ * ->host ATUSB_BUILD - - #bytes -+ * host-> ATUSB_RESET - - 0 -+ * -+ * host-> ATUSB_RF_RESET - - 0 -+ * ->host ATUSB_POLL_INT - - 1 -+ * host-> ATUSB_TEST - - 0 -+ * ->host ATUSB_TIMER - - #bytes (6) -+ * ->host ATUSB_GPIO dir+data mask+p# 3 -+ * host-> ATUSB_SLP_TR - - 0 -+ * host-> ATUSB_GPIO_CLEANUP - - 0 -+ * -+ * host-> ATUSB_REG_WRITE value addr 0 -+ * ->host ATUSB_REG_READ - addr 1 -+ * host-> ATUSB_BUF_WRITE - - #bytes -+ * ->host ATUSB_BUF_READ - - #bytes -+ * host-> ATUSB_SRAM_WRITE - addr #bytes -+ * ->host ATUSB_SRAM_READ - addr #bytes -+ * -+ * host-> ATUSB_SPI_WRITE byte0 byte1 #bytes -+ * ->host ATUSB_SPI_READ1 byte0 - #bytes -+ * ->host ATUSB_SPI_READ2 byte0 byte1 #bytes -+ * ->host ATUSB_SPI_WRITE2_SYNC byte0 byte1 0/1 -+ * -+ * host-> ATUSB_RX_MODE on - 0 -+ * host-> ATUSB_TX flags ack_seq #bytes -+ * host-> ATUSB_EUI64_WRITE - - #bytes (8) -+ * ->host ATUSB_EUI64_READ - - #bytes (8) -+ */ -+ -+#define ATUSB_REQ_FROM_DEV (USB_TYPE_VENDOR | USB_DIR_IN) -+#define ATUSB_REQ_TO_DEV (USB_TYPE_VENDOR | USB_DIR_OUT) -+ -+#endif /* !_ATUSB_H */ -diff --git a/atusb/include/atusb/ep0.h b/atusb/include/atusb/ep0.h -new file mode 100644 -index 0000000..7777345 ---- /dev/null -+++ b/atusb/include/atusb/ep0.h -@@ -0,0 +1,64 @@ -+/* -+ * include/atusb/ep0.h - EP0 extension protocol -+ * -+ * Written 2008-2011, 2013 by Werner Almesberger -+ * Copyright 2008-2011, 2013 Werner Almesberger -+ * -+ * 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. -+ */ -+ -+ -+#ifndef EP0_H -+#define EP0_H -+ -+#include <atusb/atusb.h> -+ -+ -+/* -+ * EP0 protocol: -+ * -+ * 0.0 initial release -+ * 0.1 addition of ATUSB_TEST -+ * 0.2 First public release -+ * 0.3 ATUSB_EUI64_READ/WRITE for permanent EUI64 handling -+ * Support to run the firmware on Atmel Raven USB dongles -+ * Remove FCS frame check from firmware and leave it to the driver -+ * Use extended operation mode for TX for automatic ACK handling -+ */ -+ -+#define EP0ATUSB_MAJOR 0 /* EP0 protocol, major revision */ -+#define EP0ATUSB_MINOR 3 /* EP0 protocol, minor revision */ -+ -+ -+/* -+ * bmRequestType: -+ * -+ * D7 D6..5 D4...0 -+ * | | | -+ * direction (0 = host->dev) -+ * type (2 = vendor) -+ * recipient (0 = device) -+ */ -+ -+#ifndef USB_TYPE_VENDOR -+#define USB_TYPE_VENDOR 0x40 -+#endif -+ -+#ifndef USB_DIR_IN -+#define USB_DIR_IN 0x80 -+#endif -+ -+#ifndef USB_DIR_OUT -+#define USB_DIR_OUT 0x00 -+#endif -+ -+#define ATUSB_FROM_DEV(req) (ATUSB_REQ_FROM_DEV | (req) << 8) -+#define ATUSB_TO_DEV(req) (ATUSB_REQ_TO_DEV | (req) << 8) -+ -+ -+void ep0_init(void); -+ -+#endif /* !EP0_H */ -diff --git a/atusb/mac.c b/atusb/mac.c -new file mode 100644 -index 0000000..835002c ---- /dev/null -+++ b/atusb/mac.c -@@ -0,0 +1,250 @@ -+/* -+ * fw/mac.c - HardMAC functions -+ * -+ * Written 2011, 2013 by Werner Almesberger -+ * Copyright 2011, 2013 Werner Almesberger -+ * -+ * 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. -+ */ -+ -+#include <stddef.h> -+#include <stdbool.h> -+#include <stdint.h> -+ -+#include "usb.h" -+ -+#include "at86rf230.h" -+#include "spi.h" -+#include "board.h" -+#include "mac.h" -+ -+#define RX_BUFS 3 -+ -+ -+bool (*mac_irq)(void) = NULL; -+ -+ -+static uint8_t rx_buf[RX_BUFS][MAX_PSDU+2]; /* PHDR+payload+LQ */ -+static uint8_t tx_buf[MAX_PSDU]; -+static uint8_t tx_size = 0; -+static bool txing = 0; -+static bool queued_tx_ack = 0; -+static uint8_t next_seq, this_seq, queued_seq; -+ -+ -+/* ----- Receive buffer management ----------------------------------------- */ -+ -+ -+static uint8_t rx_in = 0, rx_out = 0; -+ -+ -+static inline void next_buf(uint8_t *index) -+{ -+ *index = (*index+1) % RX_BUFS; -+} -+ -+ -+/* ----- Interrupt handling ------------------------------------------------ */ -+ -+ -+static void rx_done(void *user); -+static void tx_ack_done(void *user); -+ -+ -+static void usb_next(void) -+{ -+ const uint8_t *buf; -+ -+ if (rx_in != rx_out) { -+ buf = rx_buf[rx_out]; -+ led(1); -+ usb_send(&eps[1], buf, buf[0]+2, rx_done, NULL); -+ } -+ -+ if (queued_tx_ack) { -+ usb_send(&eps[1], &queued_seq, 1, tx_ack_done, NULL); -+ queued_tx_ack = 0; -+ } -+} -+ -+ -+static void tx_ack_done(void *user) -+{ -+ usb_next(); -+} -+ -+static void rx_done(void *user) -+{ -+ led(0); -+ next_buf(&rx_out); -+ usb_next(); -+#ifdef AT86RF230 -+ /* slap at86rf230 - reduce fragmentation issue */ -+ change_state(TRX_STATUS_RX_AACK_ON); -+#endif -+} -+ -+ -+static void receive_frame(void) -+{ -+ uint8_t size; -+ uint8_t *buf; -+ -+ spi_begin(); -+ spi_io(AT86RF230_BUF_READ); -+ -+ size = spi_recv(); -+ if (!size || (size & 0x80)) { -+ spi_end(); -+ return; -+ } -+ -+ buf = rx_buf[rx_in]; -+ spi_recv_block(buf+1, size+1); -+ spi_end(); -+ -+ buf[0] = size; -+ next_buf(&rx_in); -+ -+ if (eps[1].state == EP_IDLE) -+ usb_next(); -+} -+ -+ -+static bool handle_irq(void) -+{ -+ uint8_t irq; -+ -+ irq = reg_read(REG_IRQ_STATUS); -+ if (!(irq & IRQ_TRX_END)) -+ return 1; -+ -+ if (txing) { -+ if (eps[1].state == EP_IDLE) { -+ usb_send(&eps[1], &this_seq, 1, tx_ack_done, NULL); -+ } else { -+ queued_tx_ack = 1; -+ queued_seq = this_seq; -+ } -+ txing = 0; -+ return 1; -+ } -+ -+ /* likely */ -+ if (eps[1].state == EP_IDLE || rx_in != rx_out) -+ receive_frame(); -+ -+ return 1; -+} -+ -+ -+/* ----- TX/RX ------------------------------------------------------------- */ -+ -+ -+bool mac_rx(int on) -+{ -+ if (on) { -+ mac_irq = handle_irq; -+ reg_read(REG_IRQ_STATUS); -+ change_state(TRX_CMD_RX_AACK_ON); -+ } else { -+ mac_irq = NULL; -+ change_state(TRX_CMD_FORCE_TRX_OFF); -+ txing = 0; -+ } -+ return 1; -+} -+ -+ -+static void do_tx(void *user) -+{ -+ uint16_t timeout = 0xffff; -+ uint8_t status; -+ uint8_t i; -+ -+ /* -+ * If we time out here, the host driver will time out waiting for the -+ * TRX_END acknowledgement. -+ */ -+ do { -+ if (!--timeout) -+ return; -+ status = reg_read(REG_TRX_STATUS) & TRX_STATUS_MASK; -+ } -+ while (status != TRX_STATUS_RX_ON && status != TRX_STATUS_RX_AACK_ON); -+ -+#ifdef AT86RF231 -+ /* -+ * We use TRX_CMD_FORCE_PLL_ON instead of TRX_CMD_PLL_ON because a new -+ * reception may have begun while we were still working on the previous -+ * one. -+ */ -+ reg_write(REG_TRX_STATE, TRX_CMD_FORCE_PLL_ON); -+#endif -+#ifdef AT86RF230 -+ /* -+ * at86rf230 doesn't support force change, nevetherless this works -+ * somehow -+ */ -+ reg_write(REG_TRX_STATE, TRX_CMD_PLL_ON); -+#endif -+#ifdef AT86RF212 -+ /* -+ * We use TRX_CMD_FORCE_PLL_ON instead of TRX_CMD_PLL_ON because a new -+ * reception may have begun while we were still working on the previous -+ * one. -+ */ -+ reg_write(REG_TRX_STATE, TRX_CMD_FORCE_PLL_ON); -+#endif -+ -+ handle_irq(); -+ -+ spi_begin(); -+ spi_send(AT86RF230_BUF_WRITE); -+ spi_send(tx_size+2); /* CRC */ -+ for (i = 0; i != tx_size; i++) -+ spi_send(tx_buf[i]); -+ spi_end(); -+ -+ change_state(TRX_STATUS_TX_ARET_ON); -+ -+ slp_tr(); -+ -+ txing = 1; -+ this_seq = next_seq; -+ -+ /* -+ * Wait until we reach BUSY_TX_ARET, so that we command the transition to -+ * RX_AACK_ON which will be executed upon TX completion. -+ */ -+ change_state(TRX_CMD_PLL_ON); -+ change_state(TRX_CMD_RX_AACK_ON); -+} -+ -+ -+bool mac_tx(uint16_t flags, uint8_t seq, uint16_t len) -+{ -+ if (len > MAX_PSDU) -+ return 0; -+ tx_size = len; -+ next_seq = seq; -+ usb_recv(&eps[0], tx_buf, len, do_tx, NULL); -+ return 1; -+} -+ -+ -+void mac_reset(void) -+{ -+ mac_irq = NULL; -+ txing = 0; -+ queued_tx_ack = 0; -+ rx_in = rx_out = 0; -+ next_seq = this_seq = queued_seq = 0; -+ -+ /* enable CRC and PHY_RSSI (with RX_CRC_VALID) in SPI status return */ -+ reg_write(REG_TRX_CTRL_1, -+ TX_AUTO_CRC_ON | SPI_CMD_MODE_PHY_RSSI << SPI_CMD_MODE_SHIFT); -+} -diff --git a/atusb/mac.h b/atusb/mac.h -new file mode 100644 -index 0000000..f3c92fb ---- /dev/null -+++ b/atusb/mac.h -@@ -0,0 +1,26 @@ -+/* -+ * fw/mac.h - HardMAC functions -+ * -+ * Written 2011, 2013 by Werner Almesberger -+ * Copyright 2011, 2013 Werner Almesberger -+ * -+ * 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. -+ */ -+ -+#ifndef MAC_H -+#define MAC_H -+ -+#include <stdbool.h> -+#include <stdint.h> -+ -+ -+extern bool (*mac_irq)(void); -+ -+bool mac_rx(int on); -+bool mac_tx(uint16_t flags, uint8_t seq, uint16_t len); -+void mac_reset(void); -+ -+#endif /* !MAC_H */ -diff --git a/atusb/sernum.c b/atusb/sernum.c -new file mode 100644 -index 0000000..41e434c ---- /dev/null -+++ b/atusb/sernum.c -@@ -0,0 +1,47 @@ -+/* -+ * fw/sernum.c - ATUSB serial number -+ * -+ * Written 2008-2011, 2013 by Werner Almesberger -+ * Copyright 2008-2011, 2013 Werner Almesberger -+ * -+ * 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. -+ */ -+ -+ -+#include <stdbool.h> -+#include <stdint.h> -+ -+#include "usb.h" -+ -+#include "board.h" -+#include "sernum.h" -+ -+ -+static const uint8_t string_descriptor_0[] = { -+ 4, /* blength */ -+ USB_DT_STRING, /* bDescriptorType */ -+ LE(USB_LANGID_ENGLISH_US) /* wLANGID[0] */ -+}; -+ -+ -+bool sernum_get_descr(uint8_t type, uint8_t index, const uint8_t **reply, -+ uint8_t *size) -+{ -+ if (type != USB_DT_STRING) -+ return 0; -+ switch (index) { -+ case 0: -+ *reply = string_descriptor_0; -+ *size = sizeof(string_descriptor_0); -+ return 1; -+ case 1: -+ *reply = board_sernum; -+ *size = sizeof(board_sernum); -+ return 1; -+ default: -+ return 0; -+ } -+} -diff --git a/atusb/sernum.h b/atusb/sernum.h -new file mode 100644 -index 0000000..31a8e27 ---- /dev/null -+++ b/atusb/sernum.h -@@ -0,0 +1,37 @@ -+/* -+ * fw/sernum.h - ATUSB serial number -+ * -+ * Written 2011, 2013 by Werner Almesberger -+ * Copyright 2011, 2013 Werner Almesberger -+ * -+ * 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. -+ */ -+ -+#ifndef SERNUM_H -+#define SERNUM_H -+ -+#include <stdbool.h> -+#include <stdint.h> -+ -+#include "board.h" -+ -+ -+#ifdef HAS_BOARD_SERNUM -+ -+bool sernum_get_descr(uint8_t type, uint8_t index, const uint8_t **reply, -+ uint8_t *size); -+ -+#else /* HAS_BOARD_SERNUM */ -+ -+static inline bool sernum_get_descr(uint8_t type, uint8_t index, -+ const uint8_t **reply, uint8_t *size) -+{ -+ return 0; -+} -+ -+#endif /* !HAS_BOARD_SERNUM */ -+ -+#endif /* !SERNUM_H */ -diff --git a/atusb/spi.c b/atusb/spi.c -new file mode 100644 -index 0000000..3fa5715 ---- /dev/null -+++ b/atusb/spi.c -@@ -0,0 +1,51 @@ -+/* -+ * fw/spi.c - ATmega8 family SPI I/O -+ * -+ * Written 2011, 2013 by Werner Almesberger -+ * Copyright 2011, 2013 Werner Almesberger -+ * -+ * 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. -+ */ -+ -+ -+#include <stdbool.h> -+#include <stdint.h> -+ -+#include <avr/io.h> -+ -+#include "board.h" -+#include "spi.h" -+ -+ -+uint8_t spi_io(uint8_t v) -+{ -+// while (!(UCSR1A & 1 << UDRE1)); -+ SPI_DATA = v; -+ SPI_WAIT_DONE(); -+ return SPI_DATA; -+} -+ -+ -+void spi_end(void) -+{ -+// while (!(UCSR1A & 1 << TXC1)); -+ SET(nSS); -+} -+ -+ -+void spi_recv_block(uint8_t *buf, uint8_t n) -+{ -+ if (!n) -+ return; -+ SPI_DATA = 0; -+ while (--n) { -+ SPI_WAIT_DONE(); -+ *buf++ = SPI_DATA; -+ SPI_DATA = 0; -+ } -+ SPI_WAIT_DONE(); -+ *buf++ = SPI_DATA; -+} -diff --git a/atusb/spi.h b/atusb/spi.h -new file mode 100644 -index 0000000..6e04f4e ---- /dev/null -+++ b/atusb/spi.h -@@ -0,0 +1,30 @@ -+/* -+ * fw/spi.h - ATmega8 family SPI I/O -+ * -+ * Written 2011, 2013 by Werner Almesberger -+ * Copyright 2011, 2013 Werner Almesberger -+ * -+ * 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. -+ */ -+ -+#ifndef SPI_H -+#define SPI_H -+ -+#include <stdint.h> -+ -+ -+void spi_begin(void); -+uint8_t spi_io(uint8_t v); -+void spi_end(void); -+void spi_off(void); -+void spi_init(void); -+ -+#define spi_send(v) (void) spi_io(v) -+#define spi_recv(v) spi_io(0) -+ -+void spi_recv_block(uint8_t *buf, uint8_t n); -+ -+#endif /* !SPI_H */ -diff --git a/atusb/uart.c b/atusb/uart.c -new file mode 100644 -index 0000000..44bec27 ---- /dev/null -+++ b/atusb/uart.c -@@ -0,0 +1,64 @@ -+/* -+ * fw/uart.h - Functions needed for debugging over uart -+ * -+ * Code adapted from http://www.roboternetz.de/wissen/index.php/UART_mit_avr-gcc -+ * and http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial -+ * -+ * Published under the Creative Commons Share-Alike licence -+ * https://creativecommons.org/licenses/by-sa/2.0/de/ -+ * -+ * S. Salewski 2007 -+ * -+ * Adapted by -+ * Josef Filzmaier 2017 -+ */ -+ -+#include <avr/io.h> -+#include "uart.h" -+ -+#define USART_BAUD 38400UL -+#define F_CPU 8000000UL -+ -+#define Wait_USART_Ready() while (!(UCSR1A & (1<<UDRE1))) -+#define UART_UBRR (F_CPU/(16L*USART_BAUD)-1) -+ -+// initialize USART, 8N1 mode -+void -+uart_init(void) -+{ -+/* TODO: Find a working configuration for uart for the atmega32u2 */ -+#if CHIP == at90usb1287 -+ CLKPR = (1 << CLKPCE); -+ CLKPR = 0; // clock prescaler == 0, so we have 16 MHz mpu frequency -+ UBRR1 = UART_UBRR; -+ UCSR1C = (1 << UCSZ10) | (1 << UCSZ11); -+ UCSR1B = (1 << TXEN1); -+ do -+ { -+ UDR1; -+ } -+ while (UCSR1A & (1 << RXC1)); -+#endif -+ -+} -+ -+int uart_write_char(char c, FILE* stream) -+{ -+ if (c == '\n'){ -+ uart_new_line(); -+ } -+ else { -+ Wait_USART_Ready(); -+ UDR1 = c; -+ } -+ return 0; -+} -+ -+void -+uart_new_line(void) -+{ -+ Wait_USART_Ready(); -+ UDR1 = '\r'; -+ Wait_USART_Ready(); -+ UDR1 = '\n'; -+} -diff --git a/atusb/uart.h b/atusb/uart.h -new file mode 100644 -index 0000000..4810f9c ---- /dev/null -+++ b/atusb/uart.h -@@ -0,0 +1,25 @@ -+/* -+ * fw/uart.h - Functions needed for debugging over uart -+ * -+ * Code adapted from http://www.roboternetz.de/wissen/index.php/UART_mit_avr-gcc -+ * and http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial -+ * -+ * Published under the Creative Commons Share-Alike licence -+ * https://creativecommons.org/licenses/by-sa/2.0/de/ -+ * -+ * S. Salewski 2007 -+ * -+ * Adapted by -+ * Josef Filzmaier 2017 -+ */ -+ -+#ifndef UART_H_ -+#define UART_H_ -+ -+#include <stdio.h> -+ -+void uart_init(void); -+int uart_write_char(char c, FILE* stream); -+void uart_new_line(void); -+ -+#endif /* UART_H_ */ -diff --git a/atusb/usb/atu2.c b/atusb/usb/atu2.c -new file mode 100644 -index 0000000..98158bf ---- /dev/null -+++ b/atusb/usb/atu2.c -@@ -0,0 +1,247 @@ -+/* -+ * fw/usb/atu2.c - Chip-specific driver for Atmel ATxxxU2 USB chips -+ * -+ * Written 2008-2011, 2013-2014 by Werner Almesberger -+ * Copyright 2008-2011, 2013-2014 Werner Almesberger -+ * -+ * 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. -+ */ -+ -+/* -+ * Known issues: -+ * - no suspend/resume -+ * - we don't call back after failed transmissions, -+ * - we don't reset the EP buffer after failed receptions -+ * - enumeration often encounters an error -71 (from which it recovers) -+ */ -+ -+#include <stdbool.h> -+#include <stdint.h> -+ -+#define F_CPU 8000000UL -+#include <util/delay.h> -+ -+#include <avr/io.h> -+#include <avr/interrupt.h> -+#include "usb.h" -+#include "board.h" -+ -+ -+#ifndef NULL -+#define NULL 0 -+#endif -+ -+#if 1 -+#define BUG_ON(cond) do { if (cond) panic(); } while (0) -+#else -+#define BUG_ON(cond) -+#endif -+ -+ -+struct ep_descr eps[NUM_EPS]; -+ -+ -+static uint16_t usb_read_word(void) -+{ -+ uint8_t low; -+ -+ low = UEDATX; -+ return low | UEDATX << 8; -+} -+ -+ -+static void enable_addr(void *user) -+{ -+ while (!(UEINTX & (1 << TXINI))); -+ UDADDR |= 1 << ADDEN; -+} -+ -+ -+void set_addr(uint8_t addr) -+{ -+ UDADDR = addr; -+ usb_send(&eps[0], NULL, 0, enable_addr, NULL); -+} -+ -+ -+void usb_ep_change(struct ep_descr *ep) -+{ -+ if (ep->state == EP_TX) { -+ UENUM = ep-eps; -+ UEIENX |= 1 << TXINE; -+ } -+} -+ -+ -+static bool ep_setup(void) -+{ -+ struct setup_request setup; -+ -+ BUG_ON(UEBCLX < 8); -+ -+ setup.bmRequestType = UEDATX; -+ setup.bRequest = UEDATX; -+ setup.wValue = usb_read_word(); -+ setup.wIndex = usb_read_word(); -+ setup.wLength = usb_read_word(); -+ -+ if (!handle_setup(&setup)) -+ return 0; -+ if (!(setup.bmRequestType & 0x80) && eps[0].state == EP_IDLE) -+ usb_send(&eps[0], NULL, 0, NULL, NULL); -+ return 1; -+} -+ -+ -+static bool ep_rx(struct ep_descr *ep) -+{ -+ uint8_t size; -+ -+ size = UEBCLX; -+ if (size > ep->end-ep->buf) -+ return 0; -+ while (size--) -+ *ep->buf++ = UEDATX; -+ if (ep->buf == ep->end) { -+ ep->state = EP_IDLE; -+ if (ep->callback) -+ ep->callback(ep->user); -+// if (ep == &eps[0]) -+ usb_send(ep, NULL, 0, NULL, NULL); -+ } -+ return 1; -+} -+ -+ -+static void ep_tx(struct ep_descr *ep) -+{ -+ uint8_t size = ep->end-ep->buf; -+ uint8_t left; -+ -+ if (size > ep->size) -+ size = ep->size; -+ for (left = size; left; left--) -+ UEDATX = *ep->buf++; -+ if (size == ep->size) -+ return; -+ ep->state = EP_IDLE; -+} -+ -+ -+static void handle_ep(int n) -+{ -+ struct ep_descr *ep = eps+n; -+ uint8_t mask; -+ -+ UENUM = n; -+ if (UEINTX & (1 << RXSTPI)) { -+ /* @@@ EP_RX. EP_TX: cancel */ -+ ep->state = EP_IDLE; -+ if (!ep_setup()) -+ goto stall; -+ UEINTX = ~(1 << RXSTPI); -+ } -+ if (UEINTX & (1 << RXOUTI)) { -+ /* @@ EP_TX: cancel */ -+ if (ep->state != EP_RX) -+ goto stall; -+ if (!ep_rx(ep)) -+ goto stall; -+ /* @@@ gcc 4.5.2 wants this cast */ -+ UEINTX = (uint8_t) ~(1 << RXOUTI | 1 << FIFOCON); -+ } -+ if (UEINTX & (1 << STALLEDI)) { -+ ep->state = EP_IDLE; -+ UEINTX = ~(1 << STALLEDI); -+ } -+ if (UEINTX & (1 << TXINI)) { -+ /* @@ EP_RX: cancel (?) */ -+ if (ep->state == EP_TX) { -+ ep_tx(ep); -+ mask = 1 << TXINI; -+ if (n) -+ mask |= 1 << FIFOCON; -+ UEINTX = ~mask; -+ if (ep->state == EP_IDLE && ep->callback) -+ ep->callback(ep->user); -+ } else { -+ UEIENX &= ~(1 << TXINE); -+ } -+ } -+ return; -+ -+stall: -+ UEINTX = ~(1 << RXSTPI | 1 << RXOUTI | 1 << STALLEDI); -+ ep->state = EP_IDLE; -+ UECONX |= 1 << STALLRQ; -+} -+ -+ -+void ep_init(void) -+{ -+ UENUM = 0; -+ UECONX = (1 << RSTDT) | (1 << EPEN); /* enable */ -+ UECFG0X = 0; /* control, direction is ignored */ -+ UECFG1X = 3 << EPSIZE0; /* 64 bytes */ -+ UECFG1X |= 1 << ALLOC; -+ -+ while (!(UESTA0X & (1 << CFGOK))); -+ -+ UEIENX = -+ (1 << RXSTPE) | (1 << RXOUTE) | (1 << STALLEDE) | (1 << TXINE); -+ -+ eps[0].state = EP_IDLE; -+ eps[0].size = 64; -+ -+#ifndef BOOT_LOADER -+ -+ UENUM = 1; -+ UECONX = (1 << RSTDT) | (1 << EPEN); /* enable */ -+ UECFG0X = (1 << EPTYPE1) | (1 << EPDIR); /* bulk IN */ -+ UECFG1X = 3 << EPSIZE0; /* 64 bytes */ -+ UECFG1X |= 1 << ALLOC; -+ -+ while (!(UESTA0X & (1 << CFGOK))); -+ -+ UEIENX = (1 << STALLEDE) | (1 << TXINE); -+ -+ eps[1].state = EP_IDLE; -+ eps[1].size = 64; -+ -+#endif -+} -+ -+ -+ISR(USB_GEN_vect) -+{ -+ uint8_t flags; -+ -+ flags = UDINT; -+ if (flags & (1 << EORSTI)) { -+ if (user_reset) -+ user_reset(); -+ ep_init(); -+ UDINT = ~(1 << EORSTI); -+ } -+} -+ -+ -+ISR(USB_COM_vect) -+{ -+ uint8_t flags, i; -+ -+ flags = UEINT; -+ for (i = 0; i != NUM_EPS; i++) -+ if (flags & (1 << i)) -+ handle_ep(i); -+} -+ -+ -+void usb_reset(void) -+{ -+ UDCON |= 1 << DETACH; /* detach the pull-up */ -+ _delay_ms(1); -+} -diff --git a/atusb/usb/dfu.c b/atusb/usb/dfu.c -new file mode 100644 -index 0000000..c84a28d ---- /dev/null -+++ b/atusb/usb/dfu.c -@@ -0,0 +1,260 @@ -+/* -+ * boot/dfu.c - DFU protocol engine -+ * -+ * Written 2008-2011, 2013-2015 by Werner Almesberger -+ * Copyright 2008-2011, 2013-2015 Werner Almesberger -+ * -+ * 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. -+ */ -+ -+/* -+ * http://www.usb.org/developers/devclass_docs/DFU_1.1.pdf -+ */ -+ -+/* -+ * A few, erm, shortcuts: -+ * -+ * - we don't bother with the app* states since DFU is all this firmware does -+ * - after DFU_DNLOAD, we just block until things are written, so we never -+ * enter dfuDNLOAD_SYNC or dfuDNBUSY -+ * - no dfuMANIFEST_SYNC, dfuMANIFEST, or dfuMANIFEST_WAIT_RESET -+ * - to keep our buffers small, we only accept EP0-sized blocks -+ */ -+ -+ -+#include <stdbool.h> -+#include <stdint.h> -+ -+#include "usb.h" -+#include "dfu.h" -+ -+#include "board.h" -+ -+ -+#ifndef NULL -+#define NULL 0 -+#endif -+ -+#define debug(...) -+#define error(...) -+ -+ -+#ifndef DFU_ALT_SETTINGS -+#define DFU_ALT_SETTINGS 1 -+#endif -+ -+#ifndef DFU_ALT_NAME_0_IDX -+#define DFU_ALT_NAME_0_IDX 0 -+#endif -+ -+#ifndef DFU_ALT_NAME_1_IDX -+#define DFU_ALT_NAME_1_IDX 0 -+#endif -+ -+#ifndef DFU_ALT_NAME_2_IDX -+#define DFU_ALT_NAME_2_IDX 0 -+#endif -+ -+ -+const uint8_t device_descriptor[] = { -+ 18, /* bLength */ -+ USB_DT_DEVICE, /* bDescriptorType */ -+ LE(0x100), /* bcdUSB */ -+ USB_CLASS_APP_SPEC, /* bDeviceClass */ -+ 0x00, /* bDeviceSubClass (per interface) */ -+ 0x00, /* bDeviceProtocol (per interface) */ -+ EP0_SIZE, /* bMaxPacketSize */ -+ LE(DFU_USB_VENDOR), /* idVendor */ -+ LE(DFU_USB_PRODUCT), /* idProduct */ -+ LE(0x0001), /* bcdDevice */ -+ 0, /* iManufacturer */ -+ 0, /* iProduct */ -+#ifdef HAS_BOARD_SERNUM -+ 1, /* iSerialNumber */ -+#else -+ 0, /* iSerialNumber */ -+#endif -+ 1 /* bNumConfigurations */ -+}; -+ -+ -+const uint8_t config_descriptor[] = { -+ 9, /* bLength */ -+ USB_DT_CONFIG, /* bDescriptorType */ -+ LE(9+9*DFU_ALT_SETTINGS), /* wTotalLength */ -+ 1, /* bNumInterfaces */ -+ 1, /* bConfigurationValue (> 0 !) */ -+ 0, /* iConfiguration */ -+// USB_ATTR_SELF_POWERED | USB_ATTR_BUS_POWERED, -+ USB_ATTR_BUS_POWERED, /* bmAttributes */ -+ ((BOARD_MAX_mA)+1)/2, /* bMaxPower */ -+ -+ /* Interface #0 */ -+ -+ DFU_ITF_DESCR(0, 0, dfu_proto_dfu, DFU_ALT_NAME_0_IDX) -+#if DFU_ALT_SETTINGS > 1 -+ DFU_ITF_DESCR(0, 1, dfu_proto_dfu, DFU_ALT_NAME_1_IDX) -+#endif -+#if DFU_ALT_SETTINGS > 2 -+ DFU_ITF_DESCR(0, 2, dfu_proto_dfu, DFU_ALT_NAME_2_IDX) -+#endif -+}; -+ -+ -+static uint16_t next_block = 0; -+static bool did_download; -+ -+ -+static uint8_t buf[EP0_SIZE]; -+ -+ -+static void block_write(void *user) -+{ -+ uint16_t *size = user; -+ -+ dfu_flash_ops->write(buf, *size); -+} -+ -+ -+static bool block_receive(uint16_t length) -+{ -+ static uint16_t size; -+ -+ if (!dfu_flash_ops->can_write(length)) { -+ dfu.state = dfuERROR; -+ dfu.status = errADDRESS; -+ return 0; -+ } -+ if (length > EP0_SIZE) { -+ dfu.state = dfuERROR; -+ dfu.status = errUNKNOWN; -+ return 0; -+ } -+ size = length; -+ usb_recv(&eps[0], buf, size, block_write, &size); -+ return 1; -+} -+ -+ -+static bool block_transmit(uint16_t length) -+{ -+ uint16_t got; -+ -+ if (length > EP0_SIZE) { -+ dfu.state = dfuERROR; -+ dfu.status = errUNKNOWN; -+ return 1; -+ } -+ got = dfu_flash_ops->read(buf, length); -+ if (got < length) { -+ length = got; -+ dfu.state = dfuIDLE; -+ } -+ usb_send(&eps[0], buf, length, NULL, NULL); -+ return 1; -+} -+ -+ -+static bool my_setup(const struct setup_request *setup) -+{ -+ bool ok; -+ -+ switch (setup->bmRequestType | setup->bRequest << 8) { -+ case DFU_TO_DEV(DFU_DETACH): -+ debug("DFU_DETACH\n"); -+ /* -+ * The DFU spec says thay this is sent in protocol 1 only. -+ * However, dfu-util also sends it to get out of DFU mode, -+ * so we just don't make a fuss and ignore it. -+ */ -+ return 1; -+ case DFU_TO_DEV(DFU_DNLOAD): -+ debug("DFU_DNLOAD\n"); -+ if (dfu.state == dfuIDLE) { -+ next_block = setup->wValue; -+ dfu_flash_ops->start(); -+ } -+ else if (dfu.state != dfuDNLOAD_IDLE) { -+ error("bad state\n"); -+ return 0; -+ } -+ if (dfu.state != dfuIDLE && setup->wValue == next_block-1) { -+ debug("retransmisson\n"); -+ return 1; -+ } -+ if (setup->wValue != next_block) { -+ debug("bad block (%d vs. %d)\n", -+ setup->wValue, next_block); -+ dfu.state = dfuERROR; -+ dfu.status = errUNKNOWN; -+ return 1; -+ } -+ if (!setup->wLength) { -+ debug("DONE\n"); -+ dfu_flash_ops->end_write(); -+ dfu.state = dfuIDLE; -+ did_download = 1; -+ return 1; -+ } -+ ok = block_receive(setup->wLength); -+ next_block++; -+ dfu.state = dfuDNLOAD_IDLE; -+ return ok; -+ case DFU_FROM_DEV(DFU_UPLOAD): -+ debug("DFU_UPLOAD\n"); -+ if (dfu.state == dfuIDLE) { -+ next_block = setup->wValue; -+ dfu_flash_ops->start(); -+ } -+ else if (dfu.state != dfuUPLOAD_IDLE) -+ return 0; -+ if (dfu.state != dfuIDLE && setup->wValue == next_block-1) { -+ debug("retransmisson\n"); -+ /* @@@ try harder */ -+ dfu.state = dfuERROR; -+ dfu.status = errUNKNOWN; -+ return 1; -+ } -+ if (setup->wValue != next_block) { -+ debug("bad block (%d vs. %d)\n", -+ setup->wValue, next_block); -+ dfu.state = dfuERROR; -+ dfu.status = errUNKNOWN; -+ return 1; -+ } -+ ok = block_transmit(setup->wLength); -+ next_block++; -+ dfu.state = dfuUPLOAD_IDLE; -+ return ok; -+ case DFU_TO_DEV(DFU_ABORT): -+ debug("DFU_ABORT\n"); -+ dfu.state = dfuIDLE; -+ dfu.status = OK; -+ return 1; -+ default: -+ return dfu_setup_common(setup); -+ } -+} -+ -+ -+static void my_reset(void) -+{ -+#if 0 -+ /* @@@ not nice -- think about where this should go */ -+ extern void run_payload(void); -+ -+ if (did_download) -+ run_payload(); -+#endif -+} -+ -+ -+void dfu_init(void) -+{ -+ user_setup = my_setup; -+ user_get_descriptor = dfu_my_descr; -+ user_reset = my_reset; -+} -diff --git a/atusb/usb/dfu.h b/atusb/usb/dfu.h -new file mode 100644 -index 0000000..bc35bbc ---- /dev/null -+++ b/atusb/usb/dfu.h -@@ -0,0 +1,119 @@ -+/* -+ * boot/dfu.h - DFU protocol constants and data structures -+ * -+ * Written 2008, 2011, 2013-2015 by Werner Almesberger -+ * Copyright 2008, 2011, 2013-2015 Werner Almesberger -+ * -+ * 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. -+ */ -+ -+ -+#ifndef DFU_H -+#define DFU_H -+ -+#include <stdbool.h> -+#include <stdint.h> -+ -+#include "usb.h" -+ -+ -+enum dfu_request { -+ DFU_DETACH, -+ DFU_DNLOAD, -+ DFU_UPLOAD, -+ DFU_GETSTATUS, -+ DFU_CLRSTATUS, -+ DFU_GETSTATE, -+ DFU_ABORT, -+}; -+ -+ -+enum dfu_status { -+ OK, -+ errTARGET, -+ errFILE, -+ errWRITE, -+ errERASE, -+ errCHECK_ERASED, -+ errPROG, -+ errVERIFY, -+ errADDRESS, -+ errNOTDONE, -+ errFIRMWARE, -+ errVENDOR, -+ errUSBR, -+ errPOR, -+ errUNKNOWN, -+ errSTALLEDPKT, -+}; -+ -+ -+enum dfu_state { -+ appIDLE, -+ appDETACH, -+ dfuIDLE, -+ dfuDNLOAD_SYNC, -+ dfuDNBUSY, -+ dfuDNLOAD_IDLE, -+ dfuMANIFEST_SYNC, -+ dfuMANIFEST, -+ dfuMANIFEST_WAIT_RESET, -+ dfuUPLOAD_IDLE, -+ dfuERROR -+}; -+ -+enum dfu_itf_proto { -+ dfu_proto_runtime = 1, /* Runtime protocol */ -+ dfu_proto_dfu = 2, /* DFU mode protocol */ -+}; -+ -+ -+#define DFU_DT_FUNCTIONAL 0x21 /* DFU FUNCTIONAL descriptor type */ -+ -+ -+#define DFU_TO_DEV(req) (0x21 | (req) << 8) -+#define DFU_FROM_DEV(req) (0xa1 | (req) << 8) -+ -+ -+struct dfu { -+ uint8_t status; /* bStatus */ -+ uint8_t toL, toM, toH; /* bwPollTimeout */ -+ uint8_t state; /* bState */ -+ uint8_t iString; -+}; -+ -+ -+#define DFU_ITF_DESCR(itf, alt, proto, idx) \ -+ 9, /* bLength */ \ -+ USB_DT_INTERFACE, /* bDescriptorType */ \ -+ (itf), /* bInterfaceNumber */ \ -+ (alt), /* bAlternateSetting */ \ -+ 0, /* bNumEndpoints */ \ -+ 0xfe, /* bInterfaceClass (application specific) */ \ -+ 0x01, /* bInterfaceSubClass (device fw upgrade) */ \ -+ (proto), /* bInterfaceProtocol (dfu_proto_*) */ \ -+ (idx), /* iInterface */ -+ -+ -+struct dfu_flash_ops { -+ void (*start)(void); -+ bool (*can_write)(uint16_t size); -+ void (*write)(const uint8_t *buf, uint16_t size); -+ void (*end_write)(void); -+ uint16_t (*read)(uint8_t *buf, uint16_t size); -+}; -+ -+extern struct dfu dfu; -+extern const struct dfu_flash_ops *dfu_flash_ops; -+ -+ -+bool dfu_setup_common(const struct setup_request *setup); -+bool dfu_my_descr(uint8_t type, uint8_t index, const uint8_t **reply, -+ uint8_t *size); -+ -+void dfu_init(void); -+ -+#endif /* !DFU_H */ -diff --git a/atusb/usb/dfu_common.c b/atusb/usb/dfu_common.c -new file mode 100644 -index 0000000..9b6feef ---- /dev/null -+++ b/atusb/usb/dfu_common.c -@@ -0,0 +1,101 @@ -+/* -+ * boot/dfu_common.c - DFU protocol engine parts common to App/DFU -+ * -+ * Written 2008-2011, 2013-2014 by Werner Almesberger -+ * Copyright 2008-2011, 2013-2014 Werner Almesberger -+ * -+ * 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. -+ */ -+ -+/* -+ * http://www.usb.org/developers/devclass_docs/DFU_1.1.pdf -+ */ -+ -+/* -+ * A few, erm, shortcuts: -+ * -+ * - we don't bother with the app* states since DFU is all this firmware does -+ * - after DFU_DNLOAD, we just block until things are written, so we never -+ * enter dfuDNLOAD_SYNC or dfuDNBUSY -+ * - no dfuMANIFEST_SYNC, dfuMANIFEST, or dfuMANIFEST_WAIT_RESET -+ * - to keep our buffers small, we only accept EP0-sized blocks -+ */ -+ -+ -+#include <stdbool.h> -+#include <stdint.h> -+ -+#include "usb.h" -+#include "dfu.h" -+ -+#include "board.h" -+#include "../sernum.h" -+ -+ -+#ifndef NULL -+#define NULL 0 -+#endif -+ -+#define debug(...) -+#define error(...) -+ -+ -+static const uint8_t functional_descriptor[] = { -+ 9, /* bLength */ -+ DFU_DT_FUNCTIONAL, /* bDescriptorType */ -+ 0xf, /* bmAttributes (claim omnipotence :-) */ -+ LE(0xffff), /* wDetachTimeOut (we're very patient) */ -+ LE(EP0_SIZE), /* wTransferSize */ -+ LE(0x101), /* bcdDFUVersion */ -+}; -+ -+ -+/* -+ * The worst-case activity would be flashing a one page and erasing another -+ * one, would should take less than 10 ms. A 100 ms timeout ought to be plenty. -+ */ -+ -+struct dfu dfu = { -+ OK, /* bStatus */ -+ LE(100), 0, /* bwPollTimeout, 100 ms */ -+ dfuIDLE, /* bState */ -+ 0, /* iString */ -+}; -+ -+ -+bool dfu_setup_common(const struct setup_request *setup) -+{ -+ switch (setup->bmRequestType | setup->bRequest << 8) { -+ case DFU_FROM_DEV(DFU_GETSTATUS): -+ debug("DFU_GETSTATUS\n"); -+ usb_send(&eps[0], (uint8_t *) &dfu, sizeof(dfu), NULL, NULL); -+ return 1; -+ case DFU_TO_DEV(DFU_CLRSTATUS): -+ debug("DFU_CLRSTATUS\n"); -+ dfu.state = dfuIDLE; -+ dfu.status = OK; -+ return 1; -+ case DFU_FROM_DEV(DFU_GETSTATE): -+ debug("DFU_GETSTATE\n"); -+ usb_send(&eps[0], &dfu.state, 1, NULL, NULL); -+ return 1; -+ default: -+ error("DFU rt %x, rq%x ?\n", -+ setup->bmRequestType, setup->bRequest); -+ return 0; -+ } -+} -+ -+ -+bool dfu_my_descr(uint8_t type, uint8_t index, const uint8_t **reply, -+ uint8_t *size) -+{ -+ if (type != DFU_DT_FUNCTIONAL) -+ return sernum_get_descr(type, index, reply, size); -+ *reply = functional_descriptor; -+ *size = sizeof(functional_descriptor); -+ return 1; -+} -diff --git a/atusb/usb/usb.c b/atusb/usb/usb.c -new file mode 100644 -index 0000000..543d8c2 ---- /dev/null -+++ b/atusb/usb/usb.c -@@ -0,0 +1,181 @@ -+/* -+ * fw/usb/usb.c - USB hardware setup and standard device requests -+ * -+ * Written 2008-2011, 2013, 2015 by Werner Almesberger -+ * Copyright 2008-2011, 2013, 2015 Werner Almesberger -+ * -+ * 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. -+ */ -+ -+/* -+ * Known issues: -+ * - no suspend/resume -+ * - should support EP clearing and stalling -+ */ -+ -+#include <stdbool.h> -+#include <stdint.h> -+ -+#include "usb.h" -+#include "board.h" -+ -+ -+#ifndef NULL -+#define NULL 0 -+#endif -+ -+#if 1 -+extern void panic(void); -+#define BUG_ON(cond) do { if (cond) panic(); } while (0) -+#else -+#define BUG_ON(cond) -+#endif -+ -+bool (*user_setup)(const struct setup_request *setup); -+void (*user_set_interface)(int nth); -+bool (*user_get_descriptor)(uint8_t type, uint8_t index, -+ const uint8_t **reply, uint8_t *size); -+void (*user_reset)(void); -+ -+ -+void usb_io(struct ep_descr *ep, enum ep_state state, uint8_t *buf, -+ uint8_t size, void (*callback)(void *user), void *user) -+{ -+ BUG_ON(ep->state); -+ ep->state = state; -+ ep->buf = buf; -+ ep->end = buf+size; -+ ep->callback = callback; -+ ep->user = user; -+ usb_ep_change(ep); -+} -+ -+ -+static bool get_descriptor(uint8_t type, uint8_t index, uint16_t length) -+{ -+ const uint8_t *reply; -+ uint8_t size; -+ -+ switch (type) { -+ case USB_DT_DEVICE: -+ reply = device_descriptor; -+ size = reply[0]; -+ break; -+ case USB_DT_CONFIG: -+ if (index) -+ return 0; -+ reply = config_descriptor; -+ size = reply[2]; -+ break; -+ default: -+ if (!user_get_descriptor) -+ return 0; -+ if (!user_get_descriptor(type, index, &reply, &size)) -+ return 0; -+ } -+ if (length < size) -+ size = length; -+ usb_send(&eps[0], reply, size, NULL, NULL); -+ return 1; -+} -+ -+ -+bool handle_setup(const struct setup_request *setup) -+{ -+ switch (setup->bmRequestType | setup->bRequest << 8) { -+ -+ /* -+ * Device request -+ * -+ * See http://www.beyondlogic.org/usbnutshell/usb6.htm -+ */ -+ -+ case FROM_DEVICE(GET_STATUS): -+ if (setup->wLength != 2) -+ return 0; -+ usb_send(&eps[0], "\000", 2, NULL, NULL); -+ break; -+ case TO_DEVICE(CLEAR_FEATURE): -+ break; -+ case TO_DEVICE(SET_FEATURE): -+ return 0; -+ case TO_DEVICE(SET_ADDRESS): -+ set_addr(setup->wValue); -+ break; -+ case FROM_DEVICE(GET_DESCRIPTOR): -+ case FROM_INTERFACE(GET_DESCRIPTOR): -+ if (!get_descriptor(setup->wValue >> 8, setup->wValue, -+ setup->wLength)) -+ return 0; -+ break; -+ case TO_DEVICE(SET_DESCRIPTOR): -+ return 0; -+ case FROM_DEVICE(GET_CONFIGURATION): -+ usb_send(&eps[0], "", 1, NULL, NULL); -+ break; -+ case TO_DEVICE(SET_CONFIGURATION): -+ if (setup->wValue != config_descriptor[5]) -+ return 0; -+ break; -+ -+ /* -+ * Interface request -+ */ -+ -+ case FROM_INTERFACE(GET_STATUS): -+ return 0; -+ case TO_INTERFACE(CLEAR_FEATURE): -+ return 0; -+ case TO_INTERFACE(SET_FEATURE): -+ return 0; -+ case FROM_INTERFACE(GET_INTERFACE): -+ return 0; -+ case TO_INTERFACE(SET_INTERFACE): -+ { -+ const uint8_t *interface_descriptor = -+ config_descriptor+9; -+ const uint8_t *p; -+ int i; -+ -+ i = 0; -+ for (p = interface_descriptor; -+ p != config_descriptor+config_descriptor[2]; -+ p += p[0]) { -+ if (p[1] != USB_DT_INTERFACE) -+ continue; -+ if (p[2] == setup->wIndex && -+ p[3] == setup->wValue) { -+ if (user_set_interface) -+ user_set_interface(i); -+ return 1; -+ } -+ i++; -+ } -+ return 0; -+ } -+ break; -+ -+ /* -+ * Endpoint request -+ */ -+ -+ case FROM_ENDPOINT(GET_STATUS): -+ return 0; -+ case TO_ENDPOINT(CLEAR_FEATURE): -+ return 0; -+ case TO_ENDPOINT(SET_FEATURE): -+ return 0; -+ case FROM_ENDPOINT(SYNCH_FRAME): -+ return 0; -+ -+ default: -+ if (user_setup) -+ return user_setup(setup); -+ return 0; -+ } -+ -+ return 1; -+} -diff --git a/atusb/usb/usb.h b/atusb/usb/usb.h -new file mode 100644 -index 0000000..cb40f9e ---- /dev/null -+++ b/atusb/usb/usb.h -@@ -0,0 +1,189 @@ -+/* -+ * fw/usb//usb.h - USB hardware setup and standard device requests -+ * -+ * Written 2008, 2009, 2011, 2013, 2015 by Werner Almesberger -+ * Copyright 2008, 2009, 2011, 2013, 2015 Werner Almesberger -+ * -+ * 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. -+ */ -+ -+ -+#ifndef USB_H -+#define USB_H -+ -+ -+#include <stdbool.h> -+#include <stdint.h> -+ -+ -+/* -+ * Packet identifier types -+ */ -+ -+#define PID_OUT 0x1 -+#define PID_IN 0x9 -+#define PID_SOF 0x5 -+#define PID_SETUP 0xd -+#define PID_DATA0 0x3 -+#define PID_DATA1 0xb -+#define PID_ACK 0x2 -+#define PID_NAK 0xa -+#define PID_STALL 0xe -+ -+/* -+ * Descriptor types -+ * -+ * Reuse libusb naming scheme (/usr/include/usb.h) -+ */ -+ -+#define USB_DT_DEVICE 1 -+#define USB_DT_CONFIG 2 -+#define USB_DT_STRING 3 -+#define USB_DT_INTERFACE 4 -+#define USB_DT_ENDPOINT 5 -+ -+/* -+ * Device classes -+ * -+ * Reuse libusb naming scheme (/usr/include/usb.h) -+ */ -+ -+#define USB_CLASS_PER_INTERFACE 0 -+#define USB_CLASS_COMM 2 -+#define USB_CLASS_HID 3 -+#define USB_CLASS_MASS_STORAGE 8 -+#define USB_CLASS_HUB 9 -+#define USB_CLASS_DATA 10 -+#define USB_CLASS_APP_SPEC 0xfe -+#define USB_CLASS_VENDOR_SPEC 0xff -+ -+/* -+ * Configuration attributes -+ */ -+ -+#define USB_ATTR_BUS_POWERED 0x80 -+#define USB_ATTR_SELF_POWERED 0x40 -+#define USB_ATTR_REMOTE_WAKEUP 0x20 -+ -+/* -+ * Endpoint type -+ */ -+ -+#define USB_ENDPOINT_TYPE_CONTROL 0 -+#define USB_ENDPOINT_TYPE_ISOCHRONOUS 1 -+#define USB_ENDPOINT_TYPE_BULK 2 -+#define USB_ENDPOINT_TYPE_INTERRUPT 3 -+ -+/* -+ * Setup request types -+ */ -+ -+#define TO_DEVICE(req) (0x00 | (req) << 8) -+#define FROM_DEVICE(req) (0x80 | (req) << 8) -+#define TO_INTERFACE(req) (0x01 | (req) << 8) -+#define FROM_INTERFACE(req) (0x81 | (req) << 8) -+#define TO_ENDPOINT(req) (0x02 | (req) << 8) -+#define FROM_ENDPOINT(req) (0x82 | (req) << 8) -+ -+/* -+ * Setup requests -+ */ -+ -+#define GET_STATUS 0x00 -+#define CLEAR_FEATURE 0x01 -+#define SET_FEATURE 0x03 -+#define SET_ADDRESS 0x05 -+#define GET_DESCRIPTOR 0x06 -+#define SET_DESCRIPTOR 0x07 -+#define GET_CONFIGURATION 0x08 -+#define SET_CONFIGURATION 0x09 -+#define GET_INTERFACE 0x0a -+#define SET_INTERFACE 0x0b -+#define SYNCH_FRAME 0x0c -+ -+/* -+ * USB Language ID codes -+ * -+ * http://www.usb.org/developers/docs/USB_LANGIDs.pdf -+ */ -+ -+#define USB_LANGID_ENGLISH_US 0x409 -+ -+ -+/* -+ * Odd. sdcc seems to think "x" assumes the size of the destination, i.e., -+ * uint8_t. Hence the cast. -+ */ -+ -+#define LE(x) ((uint16_t) (x) & 0xff), ((uint16_t) (x) >> 8) -+ -+#define LO(x) (((uint8_t *) &(x))[0]) -+#define HI(x) (((uint8_t *) &(x))[1]) -+ -+ -+#ifdef LOW_SPEED -+#define EP0_SIZE 8 -+#else -+#define EP0_SIZE 64 -+#endif -+ -+#define EP1_SIZE 64 /* simplify */ -+ -+ -+enum ep_state { -+ EP_IDLE, -+ EP_RX, -+ EP_TX, -+ EP_STALL, -+}; -+ -+struct ep_descr { -+ enum ep_state state; -+ uint8_t *buf; -+ uint8_t *end; -+ uint8_t size; -+ void (*callback)(void *user); -+ void *user; -+}; -+ -+struct setup_request { -+ uint8_t bmRequestType; -+ uint8_t bRequest; -+ uint16_t wValue; -+ uint16_t wIndex; -+ uint16_t wLength; -+}; -+ -+ -+extern const uint8_t device_descriptor[]; -+extern const uint8_t config_descriptor[]; -+extern struct ep_descr eps[]; -+ -+extern bool (*user_setup)(const struct setup_request *setup); -+extern void (*user_set_interface)(int nth); -+extern bool (*user_get_descriptor)(uint8_t type, uint8_t index, -+ const uint8_t **reply, uint8_t *size); -+extern void (*user_reset)(void); -+ -+ -+#define usb_left(ep) ((ep)->end-(ep)->buf) -+#define usb_send(ep, buf, size, callback, user) \ -+ usb_io(ep, EP_TX, (void *) buf, size, callback, user) -+#define usb_recv(ep, buf, size, callback, user) \ -+ usb_io(ep, EP_RX, buf, size, callback, user) -+ -+void usb_io(struct ep_descr *ep, enum ep_state state, uint8_t *buf, -+ uint8_t size, void (*callback)(void *user), void *user); -+ -+bool handle_setup(const struct setup_request *setup); -+void set_addr(uint8_t addr); -+void usb_ep_change(struct ep_descr *ep); -+void usb_reset(void); -+void usb_init(void); -+ -+void ep_init(void); -+ -+#endif /* !USB_H */ -diff --git a/atusb/version.h b/atusb/version.h -new file mode 100644 -index 0000000..8fd6a2c ---- /dev/null -+++ b/atusb/version.h -@@ -0,0 +1,23 @@ -+/* -+ * fw/version.h - Automatically generated version string -+ * -+ * Written 2008, 2011 by Werner Almesberger -+ * Copyright 2008, 2011 Werner Almesberger -+ * -+ * 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. -+ */ -+ -+ -+#ifndef VERSION_H -+#define VERSION_H -+ -+#include <stdint.h> -+ -+ -+extern const char *build_date; -+extern const uint16_t build_number; -+ -+#endif /* !VERSION_H */ --- -2.26.0 - |