SpenceKonde / ATTinyCore

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

T84A Serial.read #769

Open JohnOH opened 1 year ago

JohnOH commented 1 year ago

I am having problems using Serial.read. I am expecting to accept serial input on the PA2 pin, I beleive this is faciltated by built in SoftwareSerial code. This is the demo code: `void setup() { delay(10000); 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);

}

void loop() { // put your main code here, to run repeatedly: if (Serial.available()) { byte c = Serial.read(); delay (60); Serial.print(c, HEX); } } My output looks like this: 21:47:33.197 -> raw text 21:47:33.197 -> F() macro 21:47:33.197 -> 001DFD929329FD`

after inputting "AAAAAAA"

A possibly associated problem occurs when attempting to compile a much larger sketch that includes: if (Serial.available()) handleInput(Serial.read()); The compile fails with the following: `In file included from /Users/johare/Documents/Arduino/hardware/ATTinyCore/avr/cores/tiny/Arduino.h:247:0, from /Users/johare/Documents/Arduino/hardware/ATTinyCore/avr/cores/tiny/wiring_private.h:35, from /Users/johare/Documents/Arduino/hardware/ATTinyCore/avr/cores/tiny/wiring_digital.c:11: /Users/johare/Documents/Arduino/hardware/ATTinyCore/avr/variants/tinyx4_legacy/pins_arduino.h:295:9: note: #pragma message: This is the COUNTERCLOCKWISE pin mapping - make sure you're using the pinout diagram with the pins in counter clockwise order

pragma message("This is the COUNTERCLOCKWISE pin mapping - make sure you're using the pinout diagram with the pins in counter clockwise order")

     ^~~~~~~

/var/folders/6c/gxr4fz9s0_1cfcfnq7b8fmr40000gp/T//cc3VfWPh.s: Assembler messages: /var/folders/6c/gxr4fz9s0_1cfcfnq7b8fmr40000gp/T//cc3VfWPh.s:2353: 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. `

If I remove the Serial.read line the compile succeeds, I now think this is the same issue I reported earlier under #672 since the assembly code in my sketch has been totally removed.

JohnOH commented 1 year ago

I now understand that the compilation error: "Assembler messages: /var/folders/6c/gxr4fz9s0_1cfcfnq7b8fmr40000gp/T//cc3VfWPh.s:2353: Error: register r24, r26, r28 or r30 required lto-wrapper: fatal error:" relates to code size.

After extensive slimming of the code I am down to 5338 bytes and the compile message is gone. Sketch uses 5338 bytes (65%) of program storage space. Maximum is 8192 bytes. Global variables use 324 bytes (63%) of dynamic memory, leaving 188 bytes for local variables. Maximum is 512 bytes.

However I still have the problem with Serial.read. The input characters become radically corrupted. There must be an issue in the RXD interrupt handling somewhere.

JohnOH commented 1 year ago

With the workaround for delayMicroseconds in place the problem with Serial.read remains. Character are corrupted or missed.

SpenceKonde commented 1 year ago

Oh god damn it goes away under some circumstances?

The error itself, normally comes from from inline assembly that is improperly specifying constraints such that the opperand for an instruction that only works on register pairs in the top 4 register pairs (the pre-X register and the 3 pointers) is not one of those registers, because the 'w' constraint was not used to specify which working register to use, and sometimes the compiler will pick one that is not valid. But while those files are the only ones in this core with inline asm, that should only be possible if I used an instruction limited to the top 4 register pairs. But I think that's just adiw and sbiw, which I don't happen to use...

It would be nice if you could get a representation of the asm it was generating that was human readable, but you can't get that with LTO, and you probably won't get the same behavior without LTO. Your code doesn't have any inline assembly in it does it? And you haven't altered the software serial library to change the buffer size to something not a power of two or something? (don't do that - the implementation of the ring buffer only works with lengths a power of 2 in size).

Can you share a hex file exported using the ATTinyCore 2.0.0-dev version (the old version uses a very different version of the tinySoftSerial with it's own horrific bugs) and the source that produced it, which manifests the issue wherein it compiles, but returns wrong results from Serial.read()?

JohnOH commented 1 year ago

SerialPrint.ino.hex.zip

JohnOH commented 1 year ago

The active code is in /Arduino/hardware/ATTinyCore/avr/cores/tiny/TinySoftwareSerial.cpp although there is also a SoftwareSerial at Arduino/hardware/ATTinyCore/avr/libraries/SoftwareSerial/SoftwareSerial.cpp in the core.

No suprises, the issue is in the interrupt code. The interrupt is happening correctly and values can be passed through the ring buffer fine through to the calling code. There appears to be an issue with when to actually sample the bit value in the serial stream. Was the code developed on an 8Khz processor? The code does pick up a variable value used in the timing calculation from: Serial._delayCount // (66@9k6 14@38k4) on an @8Mhz - not sure which code that comes from.

The code appears too late in beginning sampling hence the 8Mhz processor question.

Dr Azzy, reference your earlier questions: My code does not have any asm. I haven't changed the size of any buffers. The code was used exactly as supplied in the core.

JohnOH commented 1 year ago

I have not made any progress on this other than to use "No line ending" if using the Serial Monitor built into the Arduino package. When using other endings then at least two characters arrive in short order at the ISR.