Hello
I am developping a complex application with stepper motors, usb driver, syntax analyze on an AT90USB board.
My application is running quite well but ......
I found a bug which appends sometimes depending of the activity of the board and I was "lucky" to discover that the bug was a data memory corruption (always in the same memory area but not the same bytes)
After 4 complete days isolating the minimum code which generates the bug at least one time per minute, I can resume it to you like this :
My application use the "Stepper-Motor in UserMode" driver, so I define my own StepperIOS function.
(I have found a lot of weeks ago that the parameter (CW: boolean) of the userdevice is not correct and is always set to false because the caller of StepperIOS tests the wrong bit of _StepFlags variable, but I didn't took time to report you the bug, sorry !)
After some days of tests I isolated the problem : sometimes, the frame pointer Y is not a valid frame pointer when the value CW is pushed on the frame before the call. So the value CW (which is always $00 like I told you above) is WRITTEN SOMEWHERE in the memory, I leave you imagine what is happening after and when .....
So by patching the result .hex file
LDS _ACCA, _StepFlags;
ANDI _ACCA, 004h
ST -Y, _ACCA
CALL EchoTPXUDefinitions.StepperIOS
by
LDS _ACCA, _StepFlags;
ANDI _ACCA, 004h
NOP
CALL EchoTPXUDefinitions.StepperIOS
the application is WELL RUNNING FOR HOURS. Without the patch the bug appears before less than 10 seconds !!!!!
This is the tip of the iceberg but doesn't explain why it is happening so I didn't stop my investigations and I found something very very deep in the scheduler :
To use the stepper motor very smoothly, I declare the scheduler as this :
Scheduler = iData, interruptible;
In this case the compiler creates this code :
SYSTEM.$INTERRUPT_TIMER0:
.......
CALL EchoTPXUDefinitions.onSysTick
LDI _ACCA, 1 SHLB IntFlag
OR Flags, _ACCA
SEI
so the whole following scheduler code accepts extra interruptions and it is fine for the stepper motor driver.
BUT.....
when the scheduler has to make a task change, it uses this part of code
SYSTEM.SwitchProcess:
CALL SYSTEM.SavePrcsRegs
...........
SYSTEM.SwitchProcess_T:
......
.DEB $_CurProcess
CALL SYSTEM.RestorePrcsRegs
and this is done with the interruptions enabled BUT the procedure "RestorePrcsRegs" is not protected from interruption.
Effectively the "RestorePrcsRegs" code is the following :
SYSTEM.RestorePrcsRegs:
LDD _FPTRHI, Z+9
LDD _FRAMEPTR, Z+8
LDD _ACCA, Z+11
......
So you can see that if an interrupt occurs between these 2 lines
LDD _FPTRHI, Z+9
LDD _FRAMEPTR, Z+8
the frame pointer which will be used in the interrupt service routine is no AVAILABLE
Fortunately (or unfortunately, otherwise I would have seen it before) all my interrupt service routines of my others applications (without stepper motor) are not using frame variables and so the problem was hidden.
Actually, I have only two solutions :
A) remove the "interrupt" key word on the scheduler declaration,
but the stepper motor will not work well and the steps generation might be heratic.
B) patch the hex file to remove the frame push of the CW variable before the StepperIOS call.
but it is very heavy to do this each time I compile the application !!!
So, Rolf, could you change the scheduler code to protect the SYSTEM.RestorePrcsRegs from interrupts !!
(and possibly change also the call of StepperIOS by testing the correct bit)
Thank you for reading me until the end
Gerard
I am developping a complex application with stepper motors, usb driver, syntax analyze on an AT90USB board.
My application is running quite well but ......
I found a bug which appends sometimes depending of the activity of the board and I was "lucky" to discover that the bug was a data memory corruption (always in the same memory area but not the same bytes)
After 4 complete days isolating the minimum code which generates the bug at least one time per minute, I can resume it to you like this :
My application use the "Stepper-Motor in UserMode" driver, so I define my own StepperIOS function.
(I have found a lot of weeks ago that the parameter (CW: boolean) of the userdevice is not correct and is always set to false because the caller of StepperIOS tests the wrong bit of _StepFlags variable, but I didn't took time to report you the bug, sorry !)
After some days of tests I isolated the problem : sometimes, the frame pointer Y is not a valid frame pointer when the value CW is pushed on the frame before the call. So the value CW (which is always $00 like I told you above) is WRITTEN SOMEWHERE in the memory, I leave you imagine what is happening after and when .....
So by patching the result .hex file
LDS _ACCA, _StepFlags;
ANDI _ACCA, 004h
ST -Y, _ACCA
CALL EchoTPXUDefinitions.StepperIOS
by
LDS _ACCA, _StepFlags;
ANDI _ACCA, 004h
NOP
CALL EchoTPXUDefinitions.StepperIOS
the application is WELL RUNNING FOR HOURS. Without the patch the bug appears before less than 10 seconds !!!!!
This is the tip of the iceberg but doesn't explain why it is happening so I didn't stop my investigations and I found something very very deep in the scheduler :
To use the stepper motor very smoothly, I declare the scheduler as this :
Scheduler = iData, interruptible;
In this case the compiler creates this code :
SYSTEM.$INTERRUPT_TIMER0:
.......
CALL EchoTPXUDefinitions.onSysTick
LDI _ACCA, 1 SHLB IntFlag
OR Flags, _ACCA
SEI
so the whole following scheduler code accepts extra interruptions and it is fine for the stepper motor driver.
BUT.....
when the scheduler has to make a task change, it uses this part of code
SYSTEM.SwitchProcess:
CALL SYSTEM.SavePrcsRegs
...........
SYSTEM.SwitchProcess_T:
......
.DEB $_CurProcess
CALL SYSTEM.RestorePrcsRegs
and this is done with the interruptions enabled BUT the procedure "RestorePrcsRegs" is not protected from interruption.
Effectively the "RestorePrcsRegs" code is the following :
SYSTEM.RestorePrcsRegs:
LDD _FPTRHI, Z+9
LDD _FRAMEPTR, Z+8
LDD _ACCA, Z+11
......
So you can see that if an interrupt occurs between these 2 lines
LDD _FPTRHI, Z+9
LDD _FRAMEPTR, Z+8
the frame pointer which will be used in the interrupt service routine is no AVAILABLE
Fortunately (or unfortunately, otherwise I would have seen it before) all my interrupt service routines of my others applications (without stepper motor) are not using frame variables and so the problem was hidden.
Actually, I have only two solutions :
A) remove the "interrupt" key word on the scheduler declaration,
but the stepper motor will not work well and the steps generation might be heratic.
B) patch the hex file to remove the frame push of the CW variable before the StepperIOS call.
but it is very heavy to do this each time I compile the application !!!
So, Rolf, could you change the scheduler code to protect the SYSTEM.RestorePrcsRegs from interrupts !!
(and possibly change also the call of StepperIOS by testing the correct bit)
Thank you for reading me until the end
Gerard