SpenceKonde / ATTinyCore

Arduino core for ATtiny 1634, 828, x313, x4, x41, x5, x61, x7 and x8
Other
1.53k stars 302 forks source link

Compiler problems with delayMicroseconds #770

Closed JohnOH closed 1 year ago

JohnOH commented 1 year ago

I have a problem with delayMicroseconds. The sketch below shows two example code lines demonstrating success and the second demonstrating the failure.

void setup() { delay(10000); ookPulse(375, 1125); Serial.setTxBit(PIN3); // https://github.com/SpenceKonde/ATTinyCore/search?q=T84+tx Serial.begin(38400); Serial.println("raw text"); Serial.println(F("F() macro")); Serial.printHex(EEDR); Serial.println(); byte one = 1; Serial.println(one); Serial.println(!one); Serial.println(!!one); } void loop() { // put your main code here, to run repeatedly: if (Serial.available()) { byte c = Serial.read(); delay (60); Serial.print(c, HEX); } } static void ookPulse(int on, int off) {// delayMicroseconds(on + 150); // delayMicroseconds(on + 150); // This will compile delayMicroseconds(off - 200); // This will not compile }

I think the problem is an old one dating back at least to #672 the compiler messages are as follow:

/private/var/folders/6c/gxr4fz9s0_1cfcfnq7b8fmr40000gp/T/AppTranslocation/FF74FF7C-65DA-4311-BB33-D08BCBDE3CA9/d/Arduino.app/Contents/Java/arduino-builder -dump-prefs -logger=machine -hardware /private/var/folders/6c/gxr4fz9s0_1cfcfnq7b8fmr40000gp/T/AppTranslocation/FF74FF7C-65DA-4311-BB33-D08BCBDE3CA9/d/Arduino.app/Contents/Java/hardware -hardware /Users/johare/Library/Arduino15/packages -hardware /Users/johare/Documents/Arduino/hardware -tools /private/var/folders/6c/gxr4fz9s0_1cfcfnq7b8fmr40000gp/T/AppTranslocation/FF74FF7C-65DA-4311-BB33-D08BCBDE3CA9/d/Arduino.app/Contents/Java/tools-builder -tools /private/var/folders/6c/gxr4fz9s0_1cfcfnq7b8fmr40000gp/T/AppTranslocation/FF74FF7C-65DA-4311-BB33-D08BCBDE3CA9/d/Arduino.app/Contents/Java/hardware/tools/avr -tools /Users/johare/Library/Arduino15/packages -built-in-libraries /private/var/folders/6c/gxr4fz9s0_1cfcfnq7b8fmr40000gp/T/AppTranslocation/FF74FF7C-65DA-4311-BB33-D08BCBDE3CA9/d/Arduino.app/Contents/Java/libraries -libraries /Users/johare/Documents/Arduino/libraries -fqbn=ATTinyCore:avr:attinyx4:optimization=debug,chip=84,clock=internal_8m,pinmap=ccw,eesave=aenable,softserial=enable,bod=1v8,millis=enabled -ide-version=10813 -build-path /var/folders/6c/gxr4fz9s0_1cfcfnq7b8fmr40000gp/T/arduino_build_441856 -warnings=default -build-cache /var/folders/6c/gxr4fz9s0_1cfcfnq7b8fmr40000gp/T/arduino_cache_274995 -prefs=build.warn_data_percentage=75 -verbose /Users/johare/Documents/Arduino/libraries/jeelib/examples/Ports/SerialPrint/SerialPrint.ino /private/var/folders/6c/gxr4fz9s0_1cfcfnq7b8fmr40000gp/T/AppTranslocation/FF74FF7C-65DA-4311-BB33-D08BCBDE3CA9/d/Arduino.app/Contents/Java/arduino-builder -compile -logger=machine -hardware /private/var/folders/6c/gxr4fz9s0_1cfcfnq7b8fmr40000gp/T/AppTranslocation/FF74FF7C-65DA-4311-BB33-D08BCBDE3CA9/d/Arduino.app/Contents/Java/hardware -hardware /Users/johare/Library/Arduino15/packages -hardware /Users/johare/Documents/Arduino/hardware -tools /private/var/folders/6c/gxr4fz9s0_1cfcfnq7b8fmr40000gp/T/AppTranslocation/FF74FF7C-65DA-4311-BB33-D08BCBDE3CA9/d/Arduino.app/Contents/Java/tools-builder -tools /private/var/folders/6c/gxr4fz9s0_1cfcfnq7b8fmr40000gp/T/AppTranslocation/FF74FF7C-65DA-4311-BB33-D08BCBDE3CA9/d/Arduino.app/Contents/Java/hardware/tools/avr -tools /Users/johare/Library/Arduino15/packages -built-in-libraries /private/var/folders/6c/gxr4fz9s0_1cfcfnq7b8fmr40000gp/T/AppTranslocation/FF74FF7C-65DA-4311-BB33-D08BCBDE3CA9/d/Arduino.app/Contents/Java/libraries -libraries /Users/johare/Documents/Arduino/libraries -fqbn=ATTinyCore:avr:attinyx4:optimization=debug,chip=84,clock=internal_8m,pinmap=ccw,eesave=aenable,softserial=enable,bod=1v8,millis=enabled -ide-version=10813 -build-path /var/folders/6c/gxr4fz9s0_1cfcfnq7b8fmr40000gp/T/arduino_build_441856 -warnings=default -build-cache /var/folders/6c/gxr4fz9s0_1cfcfnq7b8fmr40000gp/T/arduino_cache_274995 -prefs=build.warn_data_percentage=75 -verbose /Users/johare/Documents/Arduino/libraries/jeelib/examples/Ports/SerialPrint/SerialPrint.ino Using board 'attinyx4' from platform in folder: /Users/johare/Documents/Arduino/hardware/ATTinyCore/avr Using core 'tiny' from platform in folder: /Users/johare/Documents/Arduino/hardware/ATTinyCore/avr Detecting libraries used... /Users/johare/Library/Arduino15/packages/DxCore/tools/avr-gcc/7.3.0-atmel3.6.1-azduino6/bin/avr-g++ -c -g -Og -Wall -std=gnu++17 -fpermissive -Wno-sized-deallocation -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -flto -mrelax -w -x c++ -E -CC -mmcu=attiny84 -DF_CPU=8000000UL -DCLOCK_SOURCE=0 -DARDUINO=10813 -DARDUINO=10813 -DARDUINO_AVR_ATTINYX4 -DARDUINO_ARCH_AVR "-DATTINYCORE=\"2.0.0-dev\"" -DATTINYCORE_MAJOR=2UL -DATTINYCORE_MINOR=0UL -DATTINYCORE_PATCH=0UL -DATTINYCORE_RELEASED=0 -I/Users/johare/Documents/Arduino/hardware/ATTinyCore/avr/cores/tiny -I/Users/johare/Documents/Arduino/hardware/ATTinyCore/avr/variants/tinyx4_legacy /var/folders/6c/gxr4fz9s0_1cfcfnq7b8fmr40000gp/T/arduino_build_441856/sketch/SerialPrint.ino.cpp -o /dev/null -DARDUINO_LIB_DISCOVERY_PHASE Generating function prototypes... /Users/johare/Library/Arduino15/packages/DxCore/tools/avr-gcc/7.3.0-atmel3.6.1-azduino6/bin/avr-g++ -c -g -Og -Wall -std=gnu++17 -fpermissive -Wno-sized-deallocation -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -flto -mrelax -w -x c++ -E -CC -mmcu=attiny84 -DF_CPU=8000000UL -DCLOCK_SOURCE=0 -DARDUINO=10813 -DARDUINO=10813 -DARDUINO_AVR_ATTINYX4 -DARDUINO_ARCH_AVR "-DATTINYCORE=\"2.0.0-dev\"" -DATTINYCORE_MAJOR=2UL -DATTINYCORE_MINOR=0UL -DATTINYCORE_PATCH=0UL -DATTINYCORE_RELEASED=0 -I/Users/johare/Documents/Arduino/hardware/ATTinyCore/avr/cores/tiny -I/Users/johare/Documents/Arduino/hardware/ATTinyCore/avr/variants/tinyx4_legacy /var/folders/6c/gxr4fz9s0_1cfcfnq7b8fmr40000gp/T/arduino_build_441856/sketch/SerialPrint.ino.cpp -o /var/folders/6c/gxr4fz9s0_1cfcfnq7b8fmr40000gp/T/arduino_build_441856/preproc/ctags_target_for_gcc_minus_e.cpp -DARDUINO_LIB_DISCOVERY_PHASE /private/var/folders/6c/gxr4fz9s0_1cfcfnq7b8fmr40000gp/T/AppTranslocation/FF74FF7C-65DA-4311-BB33-D08BCBDE3CA9/d/Arduino.app/Contents/Java/tools-builder/ctags/5.8-arduino11/ctags -u --language-force=c++ -f - --c++-kinds=svpf --fields=KSTtzns --line-directives /var/folders/6c/gxr4fz9s0_1cfcfnq7b8fmr40000gp/T/arduino_build_441856/preproc/ctags_target_for_gcc_minus_e.cpp Compiling sketch... /Users/johare/Library/Arduino15/packages/DxCore/tools/avr-gcc/7.3.0-atmel3.6.1-azduino6/bin/avr-g++ -c -g -Og -Wall -std=gnu++17 -fpermissive -Wno-sized-deallocation -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -MMD -flto -mrelax -mmcu=attiny84 -DF_CPU=8000000UL -DCLOCK_SOURCE=0 -DARDUINO=10813 -DARDUINO=10813 -DARDUINO_AVR_ATTINYX4 -DARDUINO_ARCH_AVR "-DATTINYCORE=\"2.0.0-dev\"" -DATTINYCORE_MAJOR=2UL -DATTINYCORE_MINOR=0UL -DATTINYCORE_PATCH=0UL -DATTINYCORE_RELEASED=0 -I/Users/johare/Documents/Arduino/hardware/ATTinyCore/avr/cores/tiny -I/Users/johare/Documents/Arduino/hardware/ATTinyCore/avr/variants/tinyx4_legacy /var/folders/6c/gxr4fz9s0_1cfcfnq7b8fmr40000gp/T/arduino_build_441856/sketch/SerialPrint.ino.cpp -o /var/folders/6c/gxr4fz9s0_1cfcfnq7b8fmr40000gp/T/arduino_build_441856/sketch/SerialPrint.ino.cpp.o Compiling libraries... Compiling core... Using precompiled core: /var/folders/6c/gxr4fz9s0_1cfcfnq7b8fmr40000gp/T/arduino_cache_274995/core/core_ed9085a3233578fb723bee24e24e048a.a Linking everything together... /Users/johare/Library/Arduino15/packages/DxCore/tools/avr-gcc/7.3.0-atmel3.6.1-azduino6/bin/avr-gcc -Wall -Os -g -flto -fuse-linker-plugin -Wl,--gc-sections -mrelax -mmcu=attiny84 -o /var/folders/6c/gxr4fz9s0_1cfcfnq7b8fmr40000gp/T/arduino_build_441856/SerialPrint.ino.elf /var/folders/6c/gxr4fz9s0_1cfcfnq7b8fmr40000gp/T/arduino_build_441856/sketch/SerialPrint.ino.cpp.o /var/folders/6c/gxr4fz9s0_1cfcfnq7b8fmr40000gp/T/arduino_build_441856/../arduino_cache_274995/core/core_ed9085a3233578fb723bee24e24e048a.a -L/var/folders/6c/gxr4fz9s0_1cfcfnq7b8fmr40000gp/T/arduino_build_441856 -lm /var/folders/6c/gxr4fz9s0_1cfcfnq7b8fmr40000gp/T//cc0zTHM3.s: Assembler messages: /var/folders/6c/gxr4fz9s0_1cfcfnq7b8fmr40000gp/T//cc0zTHM3.s:1937: Error: register r24, r26, r28 or r30 required lto-wrapper: fatal error: /Users/johare/Library/Arduino15/packages/DxCore/tools/avr-gcc/7.3.0-atmel3.6.1-azduino6/bin/avr-gcc returned 1 exit status compilation terminated. /Users/johare/Library/Arduino15/packages/DxCore/tools/avr-gcc/7.3.0-atmel3.6.1-azduino6/bin/../lib/gcc/avr/7.3.0/../../../../avr/bin/ld: error: lto-wrapper failed collect2: error: ld returned 1 exit status exit status 1 Error compiling for board ATtiny84/44/24 (No Bootloader).

I don't know yet where the source code for delayMicroseconds is located. Any pointers will be greatfully received.

JohnOH commented 1 year ago

delayMicroseconds is commented out in ATTinyCore/avr/cores/tiny/wiring.c

There is a version in Arduino.h as follows:

static inline void delayMicroseconds(uint16_t us) { // if us is a compile-time constant result is accurate to 1 cycle if (__builtin_constant_p(us)) { _delay_us(us); return; }

// when us is not known at compile time, delay is accurate to +/- 2us
// plus an overhead of 3 CPU cycles
const float fMHz = (F_CPU/1000000.0);
// subtract two for rounding before dividing by 4
us -= 2;
delay4us:
    // delay 4us per loop, less 4 cycles for overhead
    _delay_us(4.0 - (4.0 / fMHz));
    asm volatile ("sbiw %[us], 4" : [us]"+d"(us));
asm goto( "brpl %l[delay4us]" :::: delay4us);

}

JohnOH commented 1 year ago

The issue appears to be in these lines from ATTinyCore/avr/cores/tiny/Arduino.h:

asm volatile ("sbiw %[us], 4" : [us]"+d"(us)); asm goto( "brpl %l[delay4us]" :::: delay4us);

It will be a while before I understand assembly.

JohnOH commented 1 year ago

There is nothing new in the world, the links below have seen the problem before and the proposed solution is to replace the problem sbiw line with the following:

asm volatile ("sbiw %[us], 1" : [us]"+w"(us));

It appears to work, Dr Azzy is this a call for you?

https://github.com/nerdralph/ArduinoShrink/issues/12 https://github.com/MCUdude/MicroCore/issues/136

SpenceKonde commented 1 year ago

Yeah, that would be it. The offending code was originally written by Ralph over on ArduinoShrink, when he grudgingly added support for non-constant arguments to his implementation of delayMicroseconds.

I think the main reason I used that one was that unlike on my other cores (which essentially do it the traditional way, albeit with a slower loop depending on operating speed if that improves performance (by making the delay loop an even divisor of the , here we support wacky UART frequencies. Modern AVRs have no need of UART crystals, because the baud rate calculation error is reduced to 0.77% absolute worst case by the fractional baud generator, and negligible in typical conditions. Absolute worst case on the baud rate generator of the classic AVRs is like 33% or something crazy in that area under contrived operating parameters (an unreasonably high and pessimally chosen baud rate) and is often in excess of 1% under non-contrived parameters; hence, it was not felt to be acceptable for ATTinyCore to not support use of UART crystals - I mean the original point of me getting the 841s working with arduino was because I wanted dual UART on an AVR and didn't want to pay for whatever the smallest atmega with 2 usarts was. Cause you need one for debug and one to talk to an external device with, and Software Serial Sucks (SoftwareSerial in particular is bad, but any software serial implementation (including the one you're having issues with in the other issue) will always suck - there isn't really a way to make one that is anything better than barely tolerable.)

JohnOH commented 1 year ago

I used to use the code below to do serial on the T84, I am pleased to see builtin Serial included in your core. Just need to get it working now.

if TINY

// Serial support (output only) for Tiny supported by TinyDebugSerial // http://www.ernstc.dk/arduino/tinycom.html // 9600, 38400, or 115200 // hardware\jeelabs\avr\cores\tiny\TinyDebugSerial.h Modified to // moveTinyDebugSerial from PB0 to PA3 to match the Jeenode Micro V3 PCB layout // Connect Tiny84 PA3 to USB-BUB RXD for serial output from sketch. // Jeenode AIO2 // // With thanks for the inspiration by 2006 David A. Mellis and his AFSoftSerial // code. All right reserved. // Connect Tiny84 PA2 to USB-BUB TXD for serial input to sketch. // Jeenode DIO2 // 9600 or 38400 at present.

if SERIAL_BAUD == 9600

define BITDELAY 54 // 9k6 @ 8MHz, 19k2 @16MHz

endif

if SERIAL_BAUD == 38400

define BITDELAY 11 // 38k4 @ 8MHz, 76k8 @16MHz

endif

define _receivePin 8

static int _bitDelay; static char _receive_buffer; static byte _receive_buffer_index;

static void showString (PGM_P s); // forward declaration

ISR (PCINT0_vect) { char i, d = 0; if (digitalRead(_receivePin)) // PA2 = Jeenode DIO2 return; // not ready! whackDelay(_bitDelay - 8); for (i=0; i<8; i++) { whackDelay(_bitDelay2 - 6); // digitalread takes some time if (digitalRead(_receivePin)) // PA2 = Jeenode DIO2 d |= (1 << i); } whackDelay(_bitDelay2); if (_receive_buffer_index) return; _receive_buffer = d; // save data _receive_buffer_index = 1; // got a byte }

// TODO: replace with code from the std avr libc library: // http://www.nongnu.org/avr-libc/user-manual/group__util__delay__basic.html void whackDelay (word delay) { byte tmp=0;

asm volatile("sbiw      %0, 0x01 \n\t"
             "ldi %1, 0xFF \n\t"
             "cpi %A0, 0xFF \n\t"
             "cpc %B0, %1 \n\t"
             "brne .-10 \n\t"
             : "+r" (delay), "+a" (tmp)
             : "0" (delay)
             );

}

static byte inChar () { byte d; if (! _receive_buffer_index) return -1; d = _receive_buffer; // grab first and only byte _receive_buffer_index = 0; return d; }

endif