SpenceKonde/DxCore

millis/micros timer disabled wedges DD part

xxxajk opened this issue · 10 comments

xxxajk commented

Compile with timers disabled, and the MCU wedges.
Happens on 64DD14 part, probably happens on others.
Something isn't happy :-)

void setup() {
        pinMode(PIN_PC3, OUTPUT);
}

void loop() {
        digitalWrite(PIN_PC3, LOW);
        delay(100);
        digitalWrite(PIN_PC3, HIGH);
        delay(100);
}

Are you on Arduino IDE or PIO/etc?

Most PIO errors come from PIO's imperfect emulation of arduino, specifically the stuff in boards.txt that creates submenus - on PIO, you aren;t forced to select something from every menu, even if it's just leaving the default. But on PIO, people just don't specify menus where they want the default, and that has caused tons of problems lately. It has always done this, but suddenly people are noticing for some reason, and I've been having to go back and modify boards.txt to assign all default values as board defaults, instead of putting it in the menu section, and only have parameters be passed on non-default selections.

Hmm... The asm listing doesn't contain anything obviously ugly, and excludes some possibilities.

No interrupts should be happening, and I don't think any are. So what's going on? On previous versions of DxCore, you could get bizzare broken behavior on PIO by omitting menu selections, because PIO does not assign any default value to the menu (which is a cant-happen in the Arduino IDE - but not a cant-happen in arduino-cli (!!!).

void loop() {
        digitalWrite(PIN_PC3, LOW);
 1e2:	80 e0       	ldi	r24, 0x00	; 0 //<---------------- The rjmp at the end points here
 1e4:	74 df       	rcall	.-280    	; 0xce <digitalWrite.constprop.3>
_delay_ms():
c:\arduino-1.8.13_azd5test\hardware\tools\avr\avr\include\util/delay.h:187
	#else
		//round up by default
		__ticks_dc = (uint32_t)(ceil(fabs(__tmp)));
	#endif

	__builtin_avr_delay_cycles(__ticks_dc);
 1e6:	2f ef       	ldi	r18, 0xFF	; 255
 1e8:	82 e5       	ldi	r24, 0x52	; 82
 1ea:	97 e0       	ldi	r25, 0x07	; 7
 1ec:	21 50       	subi	r18, 0x01	; 1
 1ee:	80 40       	sbci	r24, 0x00	; 0
 1f0:	90 40       	sbci	r25, 0x00	; 0
 1f2:	e1 f7       	brne	.-8      	; 0x1ec <main+0xd4>
 1f4:	00 c0       	rjmp	.+0      	; 0x1f6 <main+0xde>
 1f6:	00 00       	nop
loop():
C:\Users\Spence\Documents\Arduino\sketch_sep28a/sketch_sep28a.ino:8
        delay(100);
        digitalWrite(PIN_PC3, HIGH);
 1f8:	81 e0       	ldi	r24, 0x01	; 1
 1fa:	69 df       	rcall	.-302    	; 0xce <digitalWrite.constprop.3>
_delay_ms():
c:\arduino-1.8.13_azd5test\hardware\tools\avr\avr\include\util/delay.h:187
 1fc:	2f ef       	ldi	r18, 0xFF	; 255
 1fe:	82 e5       	ldi	r24, 0x52	; 82
 200:	97 e0       	ldi	r25, 0x07	; 7
 202:	21 50       	subi	r18, 0x01	; 1
 204:	80 40       	sbci	r24, 0x00	; 0
 206:	90 40       	sbci	r25, 0x00	; 0
 208:	e1 f7       	brne	.-8      	; 0x202 <main+0xea>
 20a:	00 c0       	rjmp	.+0      	; 0x20c <main+0xf4>
 20c:	00 00       	nop
 20e:	e9 cf       	rjmp	.-46     	; 0x1e2 <main+0xca> // This RJMP goes up to the place marked above, this is the loop()

Perfectly innocuous looking.

Is that what the section of assembly listing near loop comes out looking like for you?

xxxajk commented

Using the Arduino builder via GNU Make, which is essentially identical to using the IDE directly.
Not sure what the culprit is, but latest test shows that blinking does indeed work...
...HOWEVER serial doesn't.

Here's the new sketch

void setup() {
        pinMode(PIN_PC3, OUTPUT);
        Serial.begin(115200);
        delay(1000);
        Serial.println("Output, and not wedged"); // nothing prints even if you swap the lines above.
}

void loop() {
        digitalWrite(PIN_PC3, LOW);
        delay(100);
        digitalWrite(PIN_PC3, HIGH);
        delay(100);
        Serial.println("Output, and not wedged"); // nothing prints
}

Hi! I'm not sure, what I should see, but my bare metal AVR64DD32 shows:

19:01:57.759 -> Startup, and not wedged
19:01:57.958 -> Output, and not wedged
19:01:58.157 -> Output, and not wedged
19:01:58.357 -> Output, and not wedged
...

on the serial monitor and PC3 pulses with 5Hz [16MHz internal, Optiboot and millis selected on TCB1 (selected because of "14pin"), Arduino1.8.19 on 64bit Linux Mint]. Yes, I changed Output to Startup in the setup() :-)

xxxajk commented

With Optiboot it bootloops, due to crash...
DD14 pulses PD6 when it reboots.
There will be no serial output when you select disable millis/mircos (bootloop).
Set it to Disabled delay only, see what happens.
On bare metal you don't get anything printed or any activity on PC3 either.
Not sure if it's wedged, or resetting in a loop but the only way to actually tell that would be using optiboot.

Yapp, confirmed. When I disable the timer, nothing happens after uploading. Also after changing to "No Bootloader" the same. No pulses, no serial output.

This is weird as fuck, man.

It's bloody obvious in the asm what the problem is: Every callback that we provide, when compiled with millis disabled, compiles to a call to 0x0000 " 0x950E 0000 or 0e 94 00 00 in the byte order it is in in the flash. It's declared weak. I can use other weakly defined functions and choose to override or not override them. But not these functions. it's a weak symbol so you can override it, but for some reason, I can't seem to make it both function correctly as a weak function (allowing it to be overridden, and using the included weak definition if it's called when it's not defined), and not get rendered as a call to 0 when millis is disabled, and I'm still pondering why.

It seems like weak definitions weren't working properly, and calls to those functions instead of compile errors were turned into runtime ones, "handled" the same way every other unrecoverable error is - calling (or jumping) to 0, triggering a bootloop, because that's how we call the startuip callbacks

xxxajk commented

Next bug :-D, unless you managed to fix it while fixing this one ;-)