Open drf5n opened 2 years ago
Here's a demo of using Timer1's TIMER1_COMPA_vect
and TIMER1_OVF_vect
in WGM=4 CTC(TOP=OCR1A) mode:
https://wokwi.com/projects/328669448533705299
It seems to be working fine in the test sketch:
...but grbl, grbl-Mega, and grbl-Mega-5X all still appear hang in Wokwi but not in silicon.
Thanks for reporting @drf5n!
It's probably best to recompile grbl inside Wokwi (so we have the ELF file), then debug it using GDB to figure out where exactly it hangs.
The AVR timers are super complex, so we'll need to narrow this down to a minimal test case, similar to what you did in #119
it looks like I can compile it inside Wokwi, and "F1 / Start Web GDB Session (debug build)" and set a breakpoint liketbreak st_wake_up
... but it looks very complex.
Is there a Wokwi simulation interface running attached to the GDB? I'm not sure how to trigger the error without interacting with the serial interface.
The grbl event loop code continues to run as expected, but the background stepping/motion planning software that uses the AVR timers and interrupts might be where things are going wrong.
I'm not familiar enough with the code to trim it down into a minimal case.
When you start a GDB session, the Wokwi interface should continue to function in the browser tab where you started the simulation from. You can see an example here:
https://youtu.be/YUUHw-bU9yk?t=434 (Starting at 7:14)
You are right.
It is really amazing to be able to singlestep the simulated Arduino and type p TCNT1
to see the counter tick up.
I poked at this a little more, and I think the difference is on CTC mode when OCR1A = 0.
Per Pg 100 of https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-7810-Automotive-Microcontrollers-ATmega328P_Datasheet.pdf
And in a Wokwi: (Note that pin 9/OC1A isn't toggling as expected when OCR1A = 0, and is toggling when OCR1A=1)
https://wokwi.com/projects/360749451904483329
Fixing this should make grbl run on Wokwi:
https://wokwi.com/projects/328163210406396500
versus debugging in
Maybe in line 705 here?
if (((prevValue < ocrA || overflow ) && value >= ocrA) || (prevValue < ocrA && overflow)) {
If OCR1A == 0 in CTC mode, then TCNT1 won't not be zero*, value == prevValue, so overflow == False, prevValue will never be < ocrA, and all the if conditions are false.
Maybe it needs another case like this completely untested:
if (((prevValue < ocrA || overflow ) && value >= ocrA) || (prevValue < ocrA && overflow) || (ocrA == 0 && value == 0) {
Or will timerUpdated() even be called on a 0->0 transition?
Here's an example with an oscilloscope:
https://wokwi.com/projects/361352450358452225
Every 10 seconds, the top trace should toggle between a 3906.25Hz and 7812.50Hz, 50% PWM, but the output goes flat for the 7812.50Hz case because when TOP=0, the simulation won't toggle the output pin.
This output shows the timer1 registers, the expected toggle frequency on OC1A (pin9) and som random samples of TCNT1 during operation:
TCCR1A=0b1010000;
TCCR1B=0b1101;
TIMSK1=0b0;
OCR1A=0;
F_OC1A = fclk/(2*N*(1+OCR1A))=7812.50Hz per page 101 of ATmega48A-PA-88A-PA-168A-PA-328-P-DS-DS40002061A.pdf
https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-7810-Automotive-Microcontrollers-ATmega328P_Datasheet.pdf
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
10000004us Setting OCR1A = 0x1
TCCR1A=0b1010000;
TCCR1B=0b1101;
TIMSK1=0b0;
OCR1A=1;
F_OC1A = fclk/(2*N*(1+OCR1A))=3906.25Hz per page 101 of ATmega48A-PA-88A-PA-168A-PA-328-P-DS-DS40002061A.pdf
https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-7810-Automotive-Microcontrollers-ATmega328P_Datasheet.pdf
0 0 1 0 1 0 1 1 1 0 1 0 1 0 0 1 0 0 0 0 1 1 1 1 0 0 0 0 1 0 0 1 0 1 0 1 0 0 0 1 1 1 0 0 1
Thanks for the example! I'll have to find a time to sit down and look into it more thoroughly. From a quick look, your suggested fix might work - but we'd also need to create a minimal test case, similar to the ones in this file so we can be sure we fixed the issue and also that it won't come back when we make additional changes to the code in the future.
So something like:
https://github.com/wokwi/avr8js/blob/320007df8d652755ecbf424fd0128c2ef98862de/src/peripherals/timer.spec.ts#L306-L321 but reworked for timer1 and OCR1A=0
it('should reset the counter in CTC mode if it equals to OCR1A equals 0 (issue #122)', () => {
const cpu = new CPU(new Uint16Array(0x1000));
new AVRTimer(cpu, timer0Config);
cpu.writeData(TCNT1, 0x0);
cpu.writeData(OCR1A, 0x0);
cpu.writeData(TCCR1A, WGM12); // WGM: CTC TOP=OCR1A
cpu.writeData(TCCR1B, CS10); // Set prescaler to 1
cpu.cycles = 1;
cpu.tick();
cpu.cycles = 3;
cpu.tick();
const tcnt = cpu.readData(TCNT1);
expect(tcnt).toEqual(0);
expect(cpu.pc).toEqual(0);
expect(cpu.cycles).toEqual(3);
});
...but tuned properly. I just hacked the writes and am unclear on the cycles and ticks.
It also: 'should set the OCF1A flag...'
expect(cpu.data[TIFR1] & (OCF1A ).toEqual(OCF1A);
I was trying to make the Grbl CNC software (https://github.com/gnea/grbl-Mega) work with some steppers in a couple sketches like https://wokwi.com/projects/328566930816369236 or the Uno like https://wokwi.com/projects/328163210406396500
In the Description/README.md file on https://wokwi.com/projects/328566930816369236 I wrote this:
The grbl released hex file https://github.com/gnea/grbl/releases/download/v1.1h.20190825/grbl_v1.1h.20190825.hex from https://github.com/gnea/grbl/releases on a simulated Uno exhibits the same blocked behavior.
I think the
TIMER1_COMPA_vect
in stepper.h may not be triggering, but I'm not sure how to diagnose it. Do you have a test setup for timer modes that I could play with to see if can duplicate the problem with a simpler demo?