Formula returning wrong answer
Posted: Thu Jul 21, 2011 12:53 pm
I am getting random errors in my formula; could it be to do with this error message?
Serious Warning: Possible sw stack corruption, function '__div_16_16' called by more than one asynchronous thread (main/Task, interrupt, interrupt low)
div_16_1_0004 appears in my CASM file in these places:
A long maths formula within TMR0 interrupt
Various formulae outside interrupt
In Flowcode’s LCD routine
Is it corrupting because the interrupt takes over half way through the __div_16_16 routine and picks up the wrong intermediate results? I can understand how that explanation, if true, would cause the value returned by the interrupt to be wrong but less clear how that would corrupt the formulae outside the interrupt, as the formula inside would complete before returning to outside.
Assuming that division in the formulae is the problem, solutions I can think of are:-
1) I note that when I divide by 2 rather than say 20 __div_16_1_00004 lines are not present. So if I converted my interrupt formula into divisors that were all 2, 4, 8, 16, etc. numbers would it avoid ever needing to use __div_16_16? I am only dividing to shorten the value so that Integer1 * Integer2 does not exceed 32k. Thus /16 or /32 is as good as /20 for this. Can I /16 to avoid __div_16_1_00004 lines or does it have to be /2/2/2/2 instead?
2) Similar to 1) is to in C Code:
Convert integers to binary
Shift byte in lower registers to right by a few places to loose the least significant bits, i.e. effectively dividing by 2, 4, 8, 16, etc. Also shift part of upper one to lower one.
Convert back to decimal.
But no idea how to write that in C.
3) Turn off/on the interrupts before/after every division outside the interrupt, but hard to do in your LCD routine. Also it upsets my timing.
4) Make the formula run quicker so that there is less chance of them clashing in time. I can cope with occasional errors but there are far too many at the moment. If I divide by 2, 4, 8, 16 instead of 3, 5, 20, etc. do the formulae execute much faster? Also I’d have to do the same thing in your LCD routine which is probably impossible.
5) Work in the 32bit realm when doing the interrupt formula, so do not need to divide the 2 integers to shorten them, and then somehow convert the most significant bits back to 16bits without doing a division.
The solution for the interrupt should be the one that executes fastest.
I also call __mul_16s_16 in the interrupt to multiply 2 integers, but not currently outside it. If I were to call it outside I assume I’d have similar error problems, but the above neat solution 1) is not going to help me as the 2 integers to be multiplied are continuously varying and so not 2, 4, 8, 16, etc. Is that correct
Serious Warning: Possible sw stack corruption, function '__div_16_16' called by more than one asynchronous thread (main/Task, interrupt, interrupt low)
div_16_1_0004 appears in my CASM file in these places:
A long maths formula within TMR0 interrupt
Various formulae outside interrupt
In Flowcode’s LCD routine
Is it corrupting because the interrupt takes over half way through the __div_16_16 routine and picks up the wrong intermediate results? I can understand how that explanation, if true, would cause the value returned by the interrupt to be wrong but less clear how that would corrupt the formulae outside the interrupt, as the formula inside would complete before returning to outside.
Assuming that division in the formulae is the problem, solutions I can think of are:-
1) I note that when I divide by 2 rather than say 20 __div_16_1_00004 lines are not present. So if I converted my interrupt formula into divisors that were all 2, 4, 8, 16, etc. numbers would it avoid ever needing to use __div_16_16? I am only dividing to shorten the value so that Integer1 * Integer2 does not exceed 32k. Thus /16 or /32 is as good as /20 for this. Can I /16 to avoid __div_16_1_00004 lines or does it have to be /2/2/2/2 instead?
2) Similar to 1) is to in C Code:
Convert integers to binary
Shift byte in lower registers to right by a few places to loose the least significant bits, i.e. effectively dividing by 2, 4, 8, 16, etc. Also shift part of upper one to lower one.
Convert back to decimal.
But no idea how to write that in C.
3) Turn off/on the interrupts before/after every division outside the interrupt, but hard to do in your LCD routine. Also it upsets my timing.
4) Make the formula run quicker so that there is less chance of them clashing in time. I can cope with occasional errors but there are far too many at the moment. If I divide by 2, 4, 8, 16 instead of 3, 5, 20, etc. do the formulae execute much faster? Also I’d have to do the same thing in your LCD routine which is probably impossible.
5) Work in the 32bit realm when doing the interrupt formula, so do not need to divide the 2 integers to shorten them, and then somehow convert the most significant bits back to 16bits without doing a division.
The solution for the interrupt should be the one that executes fastest.
I also call __mul_16s_16 in the interrupt to multiply 2 integers, but not currently outside it. If I were to call it outside I assume I’d have similar error problems, but the above neat solution 1) is not going to help me as the 2 integers to be multiplied are continuously varying and so not 2, 4, 8, 16, etc. Is that correct