summaryrefslogtreecommitdiffstats
path: root/firmware
diff options
context:
space:
mode:
authorcpldcpu <cpldcpu@gmail.com>2013-11-04 13:57:24 +0100
committercpldcpu <cpldcpu@gmail.com>2013-11-04 13:57:24 +0100
commit0a4f48c2cbcf20f93fc9531b3f57974cb4b6364d (patch)
tree2a831c2c1ec1f8ac21427bf87c2955eae391d171 /firmware
parentd7360925c1170acbc3a7b98c50e48350ac80fbc7 (diff)
downloadmicronucleus-0a4f48c2cbcf20f93fc9531b3f57974cb4b6364d.tar.gz
micronucleus-0a4f48c2cbcf20f93fc9531b3f57974cb4b6364d.tar.bz2
micronucleus-0a4f48c2cbcf20f93fc9531b3f57974cb4b6364d.zip
source code clean up
Diffstat (limited to 'firmware')
-rw-r--r--firmware/Makefile11
-rw-r--r--firmware/bootloaderconfig.h2
-rw-r--r--firmware/libs-device/osccal.h35
-rw-r--r--firmware/libs-device/osccalASM.S228
-rw-r--r--firmware/libs-device/osccalASM.obin0 -> 1708 bytes
-rw-r--r--firmware/usbconfig.h7
-rw-r--r--firmware/usbdrv/usbdrvasm.S195
7 files changed, 251 insertions, 227 deletions
diff --git a/firmware/Makefile b/firmware/Makefile
index 2d6f357..2f539b6 100644
--- a/firmware/Makefile
+++ b/firmware/Makefile
@@ -24,7 +24,7 @@ LOCKOPT = -U lock:w:0x2f:m
# - for the size of your device (8kb = 1024 * 8 = 8192) subtract above value 2124... = 6068
# - How many pages in is that? 6068 / 64 (tiny85 page size in bytes) = 94.8125
# - round that down to 94 - our new bootloader address is 94 * 64 = 6016, in hex = 1780
-BOOTLOADER_ADDRESS = 1780
+BOOTLOADER_ADDRESS = 1840
PROGRAMMER = -c USBasp
# PROGRAMMER contains AVRDUDE options to address your programmer
@@ -148,13 +148,12 @@ CC = avr-gcc
# Options:
DEFINES = -DBOOTLOADER_ADDRESS=0x$(BOOTLOADER_ADDRESS) #-DDEBUG_LEVEL=2
# Remove the -fno-* options when you use gcc 3, it does not understand them
-#
-CFLAGS = -g2 -ffunction-sections -fdata-sections -fpack-struct -Wall -Os -fno-inline-small-functions -fno-move-loop-invariants -fno-tree-scev-cprop -I. -Ilibs-device -mmcu=$(DEVICE) -DF_CPU=$(F_CPU) $(DEFINES)
+#
+CFLAGS = -g2 -ffunction-sections -fdata-sections -fpack-struct -Wall -Os -fno-inline-small-functions -fno-move-loop-invariants -fno-tree-scev-cprop -I. -Ilibs-device -mmcu=$(DEVICE) -DF_CPU=$(F_CPU) $(DEFINES)
LDFLAGS = -Wl,--relax,--gc-sections -Wl,--section-start=.text=$(BOOTLOADER_ADDRESS),-Map=main.map
OBJECTS = usbdrv/usbdrvasm.o usbdrv/oddebug.o main.o
-OBJECTS += libs-device/osccal.o
-
+OBJECTS += libs-device/osccalASM.o
# symbolic targets:
all: main.hex
@@ -172,7 +171,7 @@ all: main.hex
$(CC) $(CFLAGS) -S $< -o $@
flash: all
- $(AVRDUDE) -U flash:w:main.hex:i
+ $(AVRDUDE) -U flash:w:main.hex:i -B 10
readflash:
$(AVRDUDE) -U flash:r:read.hex:i
diff --git a/firmware/bootloaderconfig.h b/firmware/bootloaderconfig.h
index d78a614..641a9e0 100644
--- a/firmware/bootloaderconfig.h
+++ b/firmware/bootloaderconfig.h
@@ -222,7 +222,7 @@ these macros are defined, the boot loader uses them.
// LED will turn on when output=low and act as external pull up otherwise
// button shorts to GND
-// #define NANITE
+//#define NANITE
#define NANITE_CTRLPIN PB5
diff --git a/firmware/libs-device/osccal.h b/firmware/libs-device/osccal.h
index bfc5530..af37a43 100644
--- a/firmware/libs-device/osccal.h
+++ b/firmware/libs-device/osccal.h
@@ -1,10 +1,10 @@
/* Name: osccal.h
* Author: Christian Starkjohann
* Creation Date: 2008-04-10
+ * Changes 2013-11-04 cpldcpu@gmail.com
* Tabsize: 4
* Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
- * This Revision: $Id: osccal.h 762 2009-08-12 17:10:30Z cs $
*/
/*
@@ -14,31 +14,18 @@ oscillator so that the CPU runs at F_CPU (F_CPU is a macro which must be
defined when the module is compiled, best passed in the compiler command
line). The time reference is the USB frame clock of 1 kHz available
immediately after a USB RESET condition. Timing is done by counting CPU
-cycles, so all interrupts must be disabled while the calibration runs. For
-low level timing measurements, usbMeasureFrameLength() is called. This
-function must be enabled in usbconfig.h by defining
-USB_CFG_HAVE_MEASURE_FRAME_LENGTH to 1. It is recommended to call
-calibrateOscillator() from the reset hook in usbconfig.h:
-*/
+cycles, so all interrupts must be disabled while the calibration runs.
+The size optimized assembler implementation includes its own implementation
+of usbMeasureFrameLength. Therefore USB_CFG_HAVE_MEASURE_FRAME_LENGTH should
+be set to 0 to avoid including unused code sections. It is recommended to call
+calibrateOscillatorASM() from the reset hook in usbconfig.h by including osccal.h:
-#ifndef __ASSEMBLER__
-//extern void calibrateOscillator(void);
-extern void calibrateOscillatorASM(void);
-#endif
-//#define USB_RESET_HOOK(resetStarts) if(!resetStarts){ calibrateOscillator(); }
-#define USB_RESET_HOOK(resetStarts) if(!resetStarts){ calibrateOscillatorASM(); }
+#include "osccal.h"
-/*
This routine is an alternative to the continuous synchronization described
in osctune.h.
-Algorithm used:
-calibrateOscillator() first does a binary search in the OSCCAL register for
-the best matching oscillator frequency. Then it does a next neighbor search
-to find the value with the lowest clock rate deviation. It is guaranteed to
-find the best match among neighboring values, but for version 5 oscillators
-(which have a discontinuous relationship between OSCCAL and frequency) a
-better match might be available in another OSCCAL region.
+Algorithm used: See osccalASM.x
Limitations:
This calibration algorithm may try OSCCAL values of up to 192 even if the
@@ -54,7 +41,11 @@ deviation! All other frequency modules require at least 0.2% precision.
#ifndef __OSCCAL_H_INCLUDED__
#define __OSCCAL_H_INCLUDED__
-//void calibrateOscillator(void);
+#ifndef __ASSEMBLER__
+ void calibrateOscillatorASM(void);
+# define USB_RESET_HOOK(resetStarts) if(!resetStarts){ calibrateOscillatorASM();}
+# define USB_CFG_HAVE_MEASURE_FRAME_LENGTH 0
+#endif
/* This function calibrates the RC oscillator so that the CPU runs at F_CPU.
* It MUST be called immediately after the end of a USB RESET condition!
* Disable all interrupts during the call!
diff --git a/firmware/libs-device/osccalASM.S b/firmware/libs-device/osccalASM.S
new file mode 100644
index 0000000..9a317f1
--- /dev/null
+++ b/firmware/libs-device/osccalASM.S
@@ -0,0 +1,228 @@
+/* Name: osccalASM.S
+ * Author: cpldcpu@gmail.com
+ * Creation Date: 2013-11-3
+ * Tabsize: 4
+ * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
+ */
+
+/* Calibrate the RC oscillator. Our timing reference is the Start Of Frame
+ * signal (a single SE0 bit) repeating every millisecond immediately after
+ * a USB RESET.
+ *
+ *
+ * Benefits:
+ * - Codesize reduced by 90 bytes.
+ * - Improved robustness due to removing timeout from frame length measurement and
+ * inserted NOP after OSCCAL writes.
+ *
+ * Changes:
+ * - The new routine performs a combined binary and neighborhood search
+ * in a single loop.
+ * Note that the neighborhood search is necessary due to the quasi-monotonic
+ * nature of OSCCAL. (See Atmel application note AVR054).
+ * - Inserted NOP after writes to OSCCAL to avoid CPU errors during oscillator
+ * stabilization.
+ * - Implemented new routine to measure frame time "usbMeasureFrameLengthDecreasing".
+ * This routine takes the target time as a parameter and returns the deviation.
+ * - usbMeasureFrameLengthDecreasing measures in multiples of 5 cycles and is thus
+ * slighly more accurate.
+ * - usbMeasureFrameLengthDecreasing does not support time out anymore. The original
+ * implementation returned zero in case of time out, which would have caused the old
+ * calibrateOscillator() implementation to increase OSSCAL to 255, effictively
+ * overclocking and most likely crashing the CPU. The new implementation will enter
+ * an infinite loop when no USB activity is encountered. The user program should
+ * use the watchdog to escape from situations like this.
+ *
+ * This routine will work both on controllers with and without split OSCCAL range.
+ * The first trial value is 128 which is the lowest value of the upper OSCCAL range
+ * on Attiny85 and will effectively limit the search to the upper range, unless the
+ * RC oscillator frequency is unusually high. Under normal operation, the highest
+ * tested frequency setting is 192. This corresponds to ~20 Mhz core frequency and
+ * is still within spec for a 5V device.
+ */
+
+
+#define __SFR_OFFSET 0 /* used by avr-libc's register definitions */
+#include "./usbdrv/usbdrv.h" /* for common defs */
+
+#ifdef __IAR_SYSTEMS_ASM__
+/* Register assignments for usbMeasureFrameLengthDecreasing on IAR cc */
+/* Calling conventions on IAR:
+ * First parameter passed in r16/r17, second in r18/r19 and so on.
+ * Callee must preserve r4-r15, r24-r29 (r28/r29 is frame pointer)
+ * Result is passed in r16/r17
+ * In case of the "tiny" memory model, pointers are only 8 bit with no
+ * padding. We therefore pass argument 1 as "16 bit unsigned".
+ */
+
+//Untested
+
+# define i r20
+# define opV r19
+# define opD r18
+# define try r21
+# define stp r22
+
+# define cnt16L r30
+# define cnt16H r31
+
+
+#else /* __IAR_SYSTEMS_ASM__ */
+/* Register assignments for usbMeasureFrameLength on gcc */
+/* Calling conventions on gcc:
+ * First parameter passed in r24/r25, second in r22/23 and so on.
+ * Callee must preserve r1-r17, r28/r29
+ * Result is passed in r24/r25
+ */
+
+# define i r20
+# define opV r19
+# define opD r18
+# define try r27
+# define stp r26
+# define cnt16L r24
+# define cnt16H r25
+#endif
+# define cnt16 cnt16L
+
+; extern void calibrateOscillatorASM(void);
+
+.global calibrateOscillatorASM
+calibrateOscillatorASM:
+
+ cli
+ ldi opD, 255
+
+ ldi try, 128 ; calibration start value
+ ldi stp, 64 ; initial step width
+ ldi i, 10 ; 10 iterations
+
+usbCOloop:
+
+ out OSCCAL, try
+ nop
+
+ ; Delay values = F_CPU * 999e-6 / 5 + 0.5
+
+#if (F_CPU == 16500000)
+ ldi cnt16L, lo8(3297)
+ ldi cnt16H, hi8(3297)
+#elif (F_CPU == 12800000)
+ ldi cnt16L, lo8(2557)
+ ldi cnt16H, hi8(2557)
+#else
+ #error "calibrateOscillatorASM: no delayvalues defined for this F_CPU setting"
+#endif
+
+usbCOWaitStrobe: ; first wait for D- == 0 (idle strobe)
+ sbic USBIN, USBMINUS ;
+ rjmp usbCOWaitStrobe ;
+usbCOWaitIdle: ; then wait until idle again
+ sbis USBIN, USBMINUS ;1 wait for D- == 1
+ rjmp usbCOWaitIdle ;2
+usbCOWaitLoop:
+ sbiw cnt16,1 ;[0] [5]
+ sbic USBIN, USBMINUS ;[2]
+ rjmp usbCOWaitLoop ;[3]
+
+ sbrs cnt16H, 7 ;delay overflow?
+ rjmp usbCOclocktoolow
+ sub try, stp
+ neg cnt16L
+ rjmp usbCOclocktoohigh
+usbCOclocktoolow:
+ add try, stp
+usbCOclocktoohigh:
+ lsr stp
+ brne usbCOnoneighborhoodsearch
+ cp opD, cnt16L
+ brcs usbCOnoimprovement
+ in opV, OSCCAL
+ mov opD, cnt16L
+usbCOnoimprovement:
+ ldi stp, 1
+usbCOnoneighborhoodsearch:
+ subi i, 1
+ brne usbCOloop
+
+ out OSCCAL, opV
+ nop
+ sei
+ ret
+
+#undef i
+#undef opV
+#undef opD
+#undef try
+#undef stp
+#undef cnt16
+#undef cnt16L
+#undef cnt16H
+
+/* ------------------------------------------------------------------------- */
+/* ------ Original C Implementation of improved calibrateOscillator -------- */
+/* ---------------------- for Reference only ----------------------------- */
+/* ------------------------------------------------------------------------- */
+
+#if 0
+void calibrateOscillator(void)
+{
+ uchar step, trialValue, optimumValue;
+ int x, targetValue;
+ uchar optimumDev;
+ uchar i,xl;
+
+ targetValue = (unsigned)((double)F_CPU * 999e-6 / 5.0 + 0.5); /* Time is measured in multiples of 5 cycles. Target is 0.999µs */
+ optimumDev = 0xff;
+ // optimumValue = OSCCAL;
+ step=64;
+ trialValue = 128;
+
+ cli(); // disable interrupts
+
+ /*
+ Performs seven iterations of a binary search (stepwidth decreasing9
+ with three additional steps of a neighborhood search (step=1, trialvalue will oscillate around target value to find optimum)
+ */
+
+ for(i=0; i<10; i++){
+ OSCCAL = trialValue;
+ asm volatile(" NOP");
+
+ x = usbMeasureFrameLengthDecreasing(targetValue);
+
+ if(x < 0) /* frequency too high */
+ {
+ trialValue -= step;
+ xl=(uchar)-x;
+ }
+ else /* frequency too low */
+ {
+ trialValue += step;
+ xl=(uchar)x;
+ }
+
+ /*
+ Halve stepwidth to perform binary search. At step=1 the mode changes to neighbourhood search.
+ Once the neighbourhood search stage is reached, x will be smaller than +-255, hence more code can be
+ saved by only working with the lower 8 bits.
+ */
+
+ step >>= 1;
+
+ if (step==0) // Enter neighborhood search mode
+ {
+ step=1;
+ if(xl <= optimumDev){
+ optimumDev = xl;
+ optimumValue = OSCCAL;
+ }
+ }
+ }
+
+ OSCCAL = optimumValue;
+ asm volatile(" NOP");
+
+ sei(); // enable interrupts
+}
+#endif \ No newline at end of file
diff --git a/firmware/libs-device/osccalASM.o b/firmware/libs-device/osccalASM.o
new file mode 100644
index 0000000..1dac9d8
--- /dev/null
+++ b/firmware/libs-device/osccalASM.o
Binary files differ
diff --git a/firmware/usbconfig.h b/firmware/usbconfig.h
index 55707cb..bba210d 100644
--- a/firmware/usbconfig.h
+++ b/firmware/usbconfig.h
@@ -158,11 +158,10 @@
* for each control- and out-endpoint to check for duplicate packets.
*/
//#if USB_CFG_CLOCK_KHZ==16500
-#define USB_CFG_HAVE_MEASURE_FRAME_LENGTH 1
+
+
#include "osccal.h"
-//#else
-//#define USB_CFG_HAVE_MEASURE_FRAME_LENGTH 0
-//#endif
+
/* define this macro to 1 if you want the function usbMeasureFrameLength()
* compiled in. This function can be used to calibrate the AVR's RC oscillator.
*/
diff --git a/firmware/usbdrv/usbdrvasm.S b/firmware/usbdrv/usbdrvasm.S
index 29c634a..32ce8ef 100644
--- a/firmware/usbdrv/usbdrvasm.S
+++ b/firmware/usbdrv/usbdrvasm.S
@@ -282,7 +282,7 @@ usbCrc16Append:
#undef scratch
-#if USB_CFG_HAVE_MEASURE_FRAME_LENGTHx
+#if USB_CFG_HAVE_MEASURE_FRAME_LENGTH
#ifdef __IAR_SYSTEMS_ASM__
/* Register assignments for usbMeasureFrameLength on IAR cc */
/* Calling conventions on IAR:
@@ -355,199 +355,6 @@ usbMFTimeout:
#endif /* USB_CFG_HAVE_MEASURE_FRAME_LENGTH */
-
-#if USB_CFG_HAVE_MEASURE_FRAME_LENGTHx
-#ifdef __IAR_SYSTEMS_ASM__
-/* Register assignments for usbMeasureFrameLengthDecreasing on IAR cc */
-/* Calling conventions on IAR:
- * First parameter passed in r16/r17, second in r18/r19 and so on.
- * Callee must preserve r4-r15, r24-r29 (r28/r29 is frame pointer)
- * Result is passed in r16/r17
- * In case of the "tiny" memory model, pointers are only 8 bit with no
- * padding. We therefore pass argument 1 as "16 bit unsigned".
- */
-# define resL r16
-# define resH r17
-# define cnt16L r30
-# define cnt16H r31
-# define cntH r18
-
-#else /* __IAR_SYSTEMS_ASM__ */
-/* Register assignments for usbMeasureFrameLength on gcc */
-/* Calling conventions on gcc:
- * First parameter passed in r24/r25, second in r22/23 and so on.
- * Callee must preserve r1-r17, r28/r29
- * Result is passed in r24/r25
- */
-# define resL r24
-# define resH r25
-# define cnt16L r24
-# define cnt16H r25
-# define cntH r26
-#endif
-# define cnt16 cnt16L
-
-; extern int usbMeasurePacketLengthDecreasing(int);
-; input: timer start value
-; return: counts down time between two idle strobes in multiples of 5 CPU clocks
-.global usbMeasureFrameLengthDecreasing
-usbMeasureFrameLengthDecreasing:
-
-#if resL != cnt16L
- mov cnt16L, resL
- mov cnt16H, resH
-#endif
-
-usbDFWaitStrobe: ; first wait for D- == 0 (idle strobe)
- sbic USBIN, USBMINUS ;
- rjmp usbDFWaitStrobe ;
-usbDFWaitIdle: ; then wait until idle again
- sbis USBIN, USBMINUS ;1 wait for D- == 1
- rjmp usbDFWaitIdle ;2
-usbDFWaitLoop:
- sbiw cnt16,1 ;[0] [5]
- sbic USBIN, USBMINUS ;[2]
- rjmp usbDFWaitLoop ;[3]
-
-#if resL != cnt16L
- mov resL, cnt16L
- mov resH, cnt16H
-#endif
- ret
-
-#undef resL
-#undef resH
-#undef cnt16
-#undef cnt16L
-#undef cnt16H
-#undef cntH
-
-#endif /* USB_CFG_HAVE_MEASURE_FRAME_LENGTH */
-
-
-
-#if USB_CFG_HAVE_MEASURE_FRAME_LENGTH
-#ifdef __IAR_SYSTEMS_ASM__
-/* Register assignments for usbMeasureFrameLengthDecreasing on IAR cc */
-/* Calling conventions on IAR:
- * First parameter passed in r16/r17, second in r18/r19 and so on.
- * Callee must preserve r4-r15, r24-r29 (r28/r29 is frame pointer)
- * Result is passed in r16/r17
- * In case of the "tiny" memory model, pointers are only 8 bit with no
- * padding. We therefore pass argument 1 as "16 bit unsigned".
- */
-
-# define resL r16
-# define resH r17
-# define cnt16L r30
-# define cnt16H r31
-# define cntH r18
-
-#else /* __IAR_SYSTEMS_ASM__ */
-/* Register assignments for usbMeasureFrameLength on gcc */
-/* Calling conventions on gcc:
- * First parameter passed in r24/r25, second in r22/23 and so on.
- * Callee must preserve r1-r17, r28/r29
- * Result is passed in r24/r25
- */
-
-# define i r20
-# define opV r19
-# define opD r18
-# define try r27
-# define stp r26
-# define cnt16L r24
-# define cnt16H r25
-#endif
-# define cnt16 cnt16L
-
-; extern void calibrateOscillatorASM(void);
-
-.global calibrateOscillatorASM
-calibrateOscillatorASM:
-
- cli
- ldi i, 10 ; 10 iterations
-
- ldi opD, 255
-
- ldi try, 128 ; calibration start value
- ldi stp, 64 ; initial step width
-
-usbCOloop:
-
- out OSCCAL, try
- nop
-
- ; Delay values = F_CPU * 999e-6 / 5 + 0.5
-
-#if (F_CPU == 16500000)
- ldi cnt16L, lo8(3297)
- ldi cnt16H, hi8(3297)
-#define usbok
-#endif
-
-#if (F_CPU == 12800000)
- ldi cnt16L, lo8(2557)
- ldi cnt16H, hi8(2557)
-#define usbok
-#endif
-
-#ifndef usbok
- #error "calibrateOscillatorASM: no delayvalues defined for this F_CPU setting"
-#endif
-#undef usbok
-
-usbCOWaitStrobe: ; first wait for D- == 0 (idle strobe)
- sbic USBIN, USBMINUS ;
- rjmp usbCOWaitStrobe ;
-usbCOWaitIdle: ; then wait until idle again
- sbis USBIN, USBMINUS ;1 wait for D- == 1
- rjmp usbCOWaitIdle ;2
-usbCOWaitLoop:
- sbiw cnt16,1 ;[0] [5]
- sbic USBIN, USBMINUS ;[2]
- rjmp usbCOWaitLoop ;[3]
-
- sbrs cnt16H, 7 ;delay overflow?
- rjmp usbCOclocktoolow
- sub try, stp
- neg cnt16L
- rjmp usbCOclocktoohigh
-usbCOclocktoolow:
- add try, stp
-usbCOclocktoohigh:
- lsr stp
- brne usbCOstepnotzero
- cp opD, cnt16L
- brcs usbCOnoimprovement
- in opV, OSCCAL
- mov opD, cnt16L
-usbCOnoimprovement:
- ldi stp, 1
-usbCOstepnotzero:
- subi i, 1
- brne usbCOloop
-
- out OSCCAL, opV
- nop
- sei
- ret
-
-#undef i
-#undef opV
-#undef opD
-#undef try
-#undef stp
-#undef cnt16
-#undef cnt16L
-#undef cnt16H
-
-
-#endif /* USB_CFG_HAVE_MEASURE_FRAME_LENGTH */
-
-
-
;----------------------------------------------------------------------------
; Now include the clock rate specific code
;----------------------------------------------------------------------------