hi,I write an algorithm running in cortex M0. It has some floating point multiplication.But the program always resets when encounter a floating point multiplication.And the code showed below:
for (k = 0; k < 4; k++) { tmpx = dbuffer[0] * a[k + 1]; dbuffer[k + 1] = dbuffer[k + 1] - tmpx; }
dbuffer[] and a[] are float array. tmpx is a float variable. When I debug the program, the M0 resets at line "tmpx = dbuffer[0] * a[k + 1];" .And the value of dbuffer[0] is 1429983,a[k+1] is 0.00974910986. I have tested this multiplication in a new project.And the code goes well and result is right.The test code is like below:
float a = 1429983; float b = 0.00974910986; float c; c = a* b;
So, I know M0 use softVFP. I have seen asm code such as __aeabi_fmul corresponding to my code. Could anybody tell me what's wrong with my code? Thank you very much.
I suggest that you single step through the assembly instructions of the source line and post these assembly instructions along with the instruction causes the reset to this forum.
Information like the register values of the related registers would help too.
Thank you for your reply. When I step into the assembly code,the code runs well and the cpu never reset.It's so weird. But when debug in C code, then reset again. below is the assembly code:
28: { 29: float a1; 30: float tmp1,tmp2; 31: int k; 32: float dbuffer[5]; 33: int j; 0x00028FFC B5FF PUSH {r0-r7,lr} 0x00028FFE B087 SUB sp,sp,#0x1C 0x00029000 4607 MOV r7,r0 0x00029002 460E MOV r6,r1 34: a1 = a[0]; 35: // if ((!((!rtIsInf(a[0])) && (!rtIsNaN(a[0])))) || (a[0] == 0.0) || (!(a[0] !=1.0))) 36: if (1) 37: { 0x00029004 6830 LDR r0,[r6,#0x00] 0x00029006 9006 STR r0,[sp,#0x18] 38: a1 = a[0]; 39: } else { 40: for (k = 0; k < 5; k++) { 41: b[k] /= a1; 42: } 43: 44: for (k = 0; k < 4; k++) { 45: a[k + 1] /= a1; 46: } 47: 48: a[0] = 1.0; 49: } 50: 0x00029008 6830 LDR r0,[r6,#0x00] 0x0002900A 9006 STR r0,[sp,#0x18] 51: for (k = 0; k < 4; k++) { 0x0002900C 2400 MOVS r4,#0x00 0x0002900E E007 B 0x00029020 52: dbuffer[k + 1] = zi[k]; 53: } 54: 0x00029010 00A1 LSLS r1,r4,#2 0x00029012 980A LDR r0,[sp,#0x28] 0x00029014 5841 LDR r1,[r0,r1] 0x00029016 1C60 ADDS r0,r4,#1 0x00029018 0080 LSLS r0,r0,#2 0x0002901A AA01 ADD r2,sp,#0x04 0x0002901C 5011 STR r1,[r2,r0] 0x0002901E 1C64 ADDS r4,r4,#1 0x00029020 2C04 CMP r4,#0x04 0x00029022 DBF5 BLT 0x00029010 55: for (j = 0; j < 424; j++) { 0x00029024 2500 MOVS r5,#0x00 0x00029026 E043 B 0x000290B0 56: for (k = 0; k < 4; k++) { 0x00029028 2400 MOVS r4,#0x00 0x0002902A E007 B 0x0002903C 57: dbuffer[k] = dbuffer[k + 1]; 58: } 0x0002902C 1C60 ADDS r0,r4,#1 0x0002902E 0080 LSLS r0,r0,#2 0x00029030 A901 ADD r1,sp,#0x04 0x00029032 5808 LDR r0,[r1,r0] 0x00029034 00A1 LSLS r1,r4,#2 0x00029036 AA01 ADD r2,sp,#0x04 0x00029038 5050 STR r0,[r2,r1] 0x0002903A 1C64 ADDS r4,r4,#1 0x0002903C 2C04 CMP r4,#0x04 0x0002903E DBF5 BLT 0x0002902C 59: dbuffer[4] = 0.0; 0x00029040 2000 MOVS r0,#0x00 0x00029042 9005 STR r0,[sp,#0x14] 60: for (k = 0; k < 5; k++) { 0x00029044 2400 MOVS r4,#0x00 0x00029046 E013 B 0x00029070 61: tmpx = x[j] * b[k]; 0x00029048 00A2 LSLS r2,r4,#2 0x0002904A 58B9 LDR r1,[r7,r2] 0x0002904C 00AB LSLS r3,r5,#2 0x0002904E 9A09 LDR r2,[sp,#0x24] 0x00029050 58D0 LDR r0,[r2,r3] 0x00029052 F7EDF976 BL.W __aeabi_fmul (0x00016342) 0x00029056 4919 LDR r1,[pc,#100] ; @0x000290BC 0x00029058 6008 STR r0,[r1,#0x00] 62: dbuffer[k] = dbuffer[k] +tmpx; 63: 64: } 0x0002905A 00A1 LSLS r1,r4,#2 0x0002905C AA01 ADD r2,sp,#0x04 0x0002905E 5850 LDR r0,[r2,r1] 0x00029060 4916 LDR r1,[pc,#88] ; @0x000290BC 0x00029062 6809 LDR r1,[r1,#0x00] 0x00029064 F7EDF914 BL.W __aeabi_fadd (0x00016290) 0x00029068 00A1 LSLS r1,r4,#2 0x0002906A AA01 ADD r2,sp,#0x04 0x0002906C 5050 STR r0,[r2,r1] 60: for (k = 0; k < 5; k++) { 61: tmpx = x[j] * b[k]; 62: dbuffer[k] = dbuffer[k] +tmpx; 63: 64: } 0x0002906E 1C64 ADDS r4,r4,#1 0x00029070 2C05 CMP r4,#0x05 0x00029072 DBE9 BLT 0x00029048 65: for (k = 0; k < 4; k++) { 0x00029074 2400 MOVS r4,#0x00 0x00029076 E014 B 0x000290A2 66: tmpx = dbuffer[0] * a[k + 1]; 0x00029078 1C62 ADDS r2,r4,#1 0x0002907A 0092 LSLS r2,r2,#2 0x0002907C 58B1 LDR r1,[r6,r2] 0x0002907E 9801 LDR r0,[sp,#0x04] 0x00029080 F7EDF95F BL.W __aeabi_fmul (0x00016342) 0x00029084 490D LDR r1,[pc,#52] ; @0x000290BC 0x00029086 6008 STR r0,[r1,#0x00] 67: dbuffer[k + 1] = dbuffer[k + 1] - tmpx; 68: } 69: 0x00029088 1C61 ADDS r1,r4,#1 0x0002908A 0089 LSLS r1,r1,#2 0x0002908C AA01 ADD r2,sp,#0x04 0x0002908E 5850 LDR r0,[r2,r1] 0x00029090 490A LDR r1,[pc,#40] ; @0x000290BC 0x00029092 6809 LDR r1,[r1,#0x00] 0x00029094 F7EDF94D BL.W __aeabi_fsub (0x00016332) 0x00029098 1C61 ADDS r1,r4,#1 0x0002909A 0089 LSLS r1,r1,#2 0x0002909C AA01 ADD r2,sp,#0x04 0x0002909E 5050 STR r0,[r2,r1] 0x000290A0 1C64 ADDS r4,r4,#1 0x000290A2 2C04 CMP r4,#0x04 0x000290A4 DBE8 BLT 0x00029078 70: y[j] = dbuffer[0]; 71: } 0x000290A6 00AA LSLS r2,r5,#2 0x000290A8 9901 LDR r1,[sp,#0x04] 0x000290AA 9810 LDR r0,[sp,#0x40] 0x000290AC 5081 STR r1,[r0,r2]
.
and the whole c function.
void filter(float b[5], float a[5], const float x[424], const float zi[4], float y[424]) { float a1; float tmp1,tmp2; int k; float dbuffer[5]; int j; a1 = a[0]; // if ((!((!rtIsInf(a[0])) && (!rtIsNaN(a[0])))) || (a[0] == 0.0) || (!(a[0] !=1.0))) if (1) { a1 = a[0]; } else { for (k = 0; k < 5; k++) { b[k] /= a1; } for (k = 0; k < 4; k++) { a[k + 1] /= a1; } a[0] = 1.0; } for (k = 0; k < 4; k++) { dbuffer[k + 1] = zi[k]; } for (j = 0; j < 424; j++) { for (k = 0; k < 4; k++) { dbuffer[k] = dbuffer[k + 1]; } dbuffer[4] = 0.0; for (k = 0; k < 5; k++) { tmpx = x[j] * b[k];//reset here!!!! dbuffer[k] = dbuffer[k] +tmpx; } for (k = 0; k < 4; k++) { tmpx = dbuffer[0] * a[k + 1]; dbuffer[k + 1] = dbuffer[k + 1] - tmpx; } y[j] = dbuffer[0]; } }
Because it doesn't reset when step into assembly.Which register should I post? Thanks again.
I would rule out that the floating point code itself causes the reset.
What about interrupts in your system? Did you check for stack overflows?
The default stack, in startup_arch.s is usually very small. If you hold your arrays in local/auto variables it's going to break unless you make the stack sufficiently large.
Does it end up in the Hard Fault Handler?
Thank you,Reinhard,I resize the stack size and cut my code to 100 point filter.Then the program runs well.So,it's obviously caused by stack overflow.
hi,Westonsupermare,Thank you for reply.It's indeed caused by stack overflow. By the way, I'd like to ask another question:How can I know the program ends up in the Hard Fault Handler?
If you stop the debugger you could observe where it's stuck, often a while(1) loop.
You can break-point the handler. You can have the handler output status/diagnostic information on the serial port.
This may help you further: http://www.keil.com/appnotes/docs/apnt_209.asp
community.arm.com/.../17345