|
|
View previous topic :: View next topic |
Author |
Message |
miketwo
Joined: 04 Aug 2010 Posts: 24
|
PCD: Help from someone who knows assembly? |
Posted: Tue Sep 28, 2010 5:03 pm |
|
|
My program was going through reboots for no apparent reason, and after a LOT of debugging I was able to narrow it down to a single line.
Code: | Y->Omega_LV_ECI_LV_y = -Compute_Omega_LV_ECI_LV_41_1; |
If I changed that to
Code: | Y->Omega_LV_ECI_LV_y = -1.0 * Compute_Omega_LV_ECI_LV_41_1; |
No more reboots!
This problem really confuses me, so I copied down the disassembly listings. But I'm a real novice at assembly, and can't find the error, so I'm hoping someone can interpret the following for me.
Assembly Code for the WORKING version:
Code: |
3490:
Y->Omega_LV_ECI_LV_y = -1.0 * Compute_Omega_LV_ECI_LV_41_1; // mra: wtf?! this is the problem?
06496 822730 mov.w 0x44e6,0x0000
06498 200044 mov.w #0x4,0x0008
0649A 420280 add.w 0x0008,0x0000,0x000a
0649C 200000 mov.w #0x0,0x0000
0649E 2BF801 mov.w #0xbf80,0x0002
064A0 8227C2 mov.w 0x44f8,0x0004
064A2 8227D3 mov.w 0x44fa,0x0006
064A4 023B9C call 0x003b9c
064A8 200004 mov.w #0x0,0x0008
064AA 781AB4 mov.w [0x0008++],[0x000a++]
064AC 781AB4 mov.w [0x0008++],[0x000a++]
|
Assembly Code for the BROKEN version:
Code: |
3489:
Y->Omega_LV_ECI_LV_y = -Compute_Omega_LV_ECI_LV_41_1; // mra: wtf?! this is the problem?
06496 822730 mov.w 0x44e6,0x0000
06498 200044 mov.w #0x4,0x0008
0649A 420280 add.w 0x0008,0x0000,0x000a
0649C 244F84 mov.w #0x44f8,0x0008
0649E 781AB4 mov.w [0x0008++],[0x000a++]
064A0 781AB4 mov.w [0x0008++],[0x000a++]
064A2 A2F016 btg [0x000c],#15
|
Additional info that might be helpful:
The RHS of the equation is a float.
The LHS is a struct with 3 floats that was passed by reference into the function.
The assignment is to the middle (2nd) float of the 3 in the struct.
Any help is greatly appreciated! |
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Wed Sep 29, 2010 4:08 am |
|
|
I can't see a reason for reboot at first sight, although I doubt, that the negation is performed correctly. Can you post a short, complete example code, that demonstrates the error?
P.S.: Please tell also your PCD version. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Wed Sep 29, 2010 8:00 am |
|
|
Obvious other question, is 'how is Compute_Omega_LV_ECI_LV_41_1 declared'?.
In the 'working' version, you have a -1, on the right of the equation. This will force signed arithmetic to be used. If Compute_Omega_LV_ECI_LV_41_1 is 'unsigned', then the crash may be the compiler trying to negate an unsigned number.
Best Wishes |
|
|
miketwo
Joined: 04 Aug 2010 Posts: 24
|
|
Posted: Wed Sep 29, 2010 1:54 pm |
|
|
Thanks for the responses guys. PCD version is 4.111, the PIC is a 24FJ256GA110.
FvM, you are correct -- the negation does not happen correctly. I think this leads to a math-error-induced reboot in another section of my program.
I can't get the reboot to occur in my test program, but I definitely was able to duplicate the failure in negation. The failure to negate happens on the assignment to a passed struct -- the last one in the test.
Code: | // Device
#include <24FJ256GA110.h>
#pragma case // Makes all code case-sensitive
#use delay(clock=32MHZ,internal=8M) // Tells compiler what the clock speed is
// UART
#pin_select U1TX = PIN_F3
#pin_select U1RX = PIN_F2
#use rs232(baud=9600, UART1, BITS=8, STREAM=COM_A, ERRORS)
// Dependencies
#include <string.h> // Standard string lib
#include <stdlib.h> // Standard lib
// Declarations
struct f_s
{
float a;
float b;
float c;
};
// Negative Float assignment test
void Test11(struct f_s * f_ptr)
{
float b,c;
struct f_s f_local;
b=2.46245e3;
disable_interrupts(INTR_GLOBAL);
fprintf(COM_A,"\r\nNegative Float test:");
fprintf(COM_A,"\r\nOriginal float (all others should be negative):\t %f",b);
c=-b;
fprintf(COM_A,"\r\nAssigned to auto float (c=-b;):\t\t\t %f",c);
f_local.b=-b;
fprintf(COM_A,"\r\nAssigned to local struct (f_local.b=-b;):\t %f",f_local.b);
f_ptr->b=-1.0 * b;
fprintf(COM_A,"\r\nAssigned to struct ptr v1: (f_ptr->b=-1.0 * b;): %f",f_ptr->b);
f_ptr->b=-b;
fprintf(COM_A,"\r\nAssigned to struct ptr v2: (f_ptr->b=-b;):\t %f",f_ptr->b);
return;
}
//==============================================
// MAIN
//==============================================
void main()
{
struct f_s floatstruct;
// Setup Port
setup_uart(9600, COM_A);
delay_ms(100); // give it a second to work out the port setup
// Run Test
Test11(&floatstruct); // Negative Float Test
getch();
}
|
Floats. They're a bad a idea. I wish I could avoid them. |
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Wed Sep 29, 2010 2:00 pm |
|
|
I was also able to reproduce the generated code of your example in the meantime. It's still identical with most recent PCD V4.112
Code: | typedef struct
{
float f1,f2,f3;
} FSTRUCT, *PFSTRUCT;
FSTRUCT fs;
PFSTRUCT pfs;
float f;
pfs = &fs;
f = -25.123456;
pfs->f2 = -f;
pfs->f2 = -1.0*f; |
The problem is in this instruction
At first sight, I doubted correctly that it doesn't negate the float variable. Because 0x000c (WREG6) is never set inside the calculation, the result of the bit set is unpredictable and will cause an address error trap in two cases:
- WREG6 is holding an odd number
- WREG6 is not pointing to a valid data address
At best, it's "only" corrupting the application data!
This operation would correctly negate a float value
|
|
|
miketwo
Joined: 04 Aug 2010 Posts: 24
|
|
Posted: Wed Sep 29, 2010 2:15 pm |
|
|
Thanks so much FvM, especially for the descriptions of what conditions would cause a reboot. That explains why it would run for a little while "correctly."
I just submitted a bug report. Hopefully they'll address this immediately, because it's a pretty basic operation. |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|