From a1a11ed4888bfd84f2215321489b25944404b6ab Mon Sep 17 00:00:00 2001 From: cpldcpu Date: Sun, 5 Jan 2014 12:09:34 +0100 Subject: firmware: first working version with polled usb --- firmware/osccalASM.S | 70 ++++++++++++++++++++++++++++++---------------------- 1 file changed, 40 insertions(+), 30 deletions(-) (limited to 'firmware/osccalASM.S') diff --git a/firmware/osccalASM.S b/firmware/osccalASM.S index c0c8803..9c3b45a 100644 --- a/firmware/osccalASM.S +++ b/firmware/osccalASM.S @@ -1,6 +1,8 @@ -/* Name: osccalASM.S +/* Name: osccalASM.S v1.1 * Author: cpldcpu@gmail.com * Creation Date: 2013-11-3 + * Update : 2014-01-4 + * * Tabsize: 4 * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) */ @@ -11,28 +13,34 @@ * * * Benefits: - * - Codesize reduced by 90 bytes. + * - Codesize reduced by 90 bytes. * - Improved robustness due to removing timeout from frame length measurement and - * inserted NOP after OSCCAL writes. + * 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 + * - 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 + * 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 + * an infinite loop when no USB activity is encountered. The user program should * use the watchdog to escape from situations like this. - * + * Update 2014-01-4 + * - Added an initial sync-state, which will discard the first delay measurement. + * This allows to call this routine before or during the SE0 bus reset without + * corrupting OSCCAL. + * - Removed CLI/SEI to allow more flexibility. + * + * * 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 @@ -90,20 +98,19 @@ .global calibrateOscillatorASM calibrateOscillatorASM: -; cli - ldi opD, 255 + ldi opD, 255 - ldi try, 128 ; calibration start value - ldi stp, 64 ; initial step width - ldi i, 10 ; 10 iterations + ldi try, 128 ; calibration start value + ldi stp, 0 ; initial step width=0 for sync phase (first delay is discarded) + ldi i, 11 ; 11 iterations (1x sync, 7x binary search, 3x neighbourhood) usbCOloop: - out OSCCAL, try - nop + out OSCCAL, try + nop - ; Delay values = F_CPU * 999e-6 / 5 + 0.5 - + ; Delay values = F_CPU * 999e-6 / 5 + 0.5 + #if (F_CPU == 16500000) ldi cnt16L, lo8(3297) ldi cnt16H, hi8(3297) @@ -115,9 +122,9 @@ usbCOloop: ldi cnt16H, hi8(2398) #elif (F_CPU == 16000000) ldi cnt16L, lo8(3197) - ldi cnt16H, hi8(3197) + ldi cnt16H, hi8(3197) #else - #error "calibrateOscillatorASM: no delayvalues defined for this F_CPU setting" + #error "calibrateOscillatorASM: no delayvalues defined for this F_CPU setting" #endif usbCOWaitStrobe: ; first wait for D- == 0 (idle strobe) @@ -139,21 +146,26 @@ usbCOWaitLoop: usbCOclocktoolow: add try, stp usbCOclocktoohigh: - lsr stp - brne usbCOnoneighborhoodsearch + lsr stp ; stp = 0 in first iteration (sync) + ; stp = 2^x (x=0..6) during binary search, + ; stp = 1 during neighbourhood search + + brne usbCObinarysearch + ldi stp, 64 ; stp=64 to initiate binary search. + ; If we are in neighbourhood search (c=1), it is changed to 1 below + brcc usbCObinarysearch cp opD, cnt16L brcs usbCOnoimprovement in opV, OSCCAL mov opD, cnt16L usbCOnoimprovement: - ldi stp, 1 -usbCOnoneighborhoodsearch: + ldi stp, 1 ; stp=1 to continue with neighbourhood search +usbCObinarysearch: subi i, 1 brne usbCOloop out OSCCAL, opV nop -; sei ret #undef i @@ -227,8 +239,6 @@ void calibrateOscillator(void) } OSCCAL = optimumValue; - asm volatile(" NOP"); - - sei(); // enable interrupts + asm volatile(" NOP"); } #endif \ No newline at end of file -- cgit v1.2.3