View previous topic :: View next topic |
Author |
Message |
raljones
Joined: 11 Aug 2005 Posts: 11
|
Crash when code size exceeds 32k |
Posted: Thu Aug 11, 2005 3:11 pm |
|
|
I'm using a 18F8720 devce, which has 128k of code space.
My code recently grew to bigger than 32k, 25%, and it quit running.
It still mostly runs, until it tries to execute code near the end of the program, then it crashes.
If I chop out peices to get it under 32k it starts working again.
I'm prety sure there is no obscure bug in the code I cut out, as it was working before I hit the 32k wall, it I can get it working by removing different sections of code, as long as I can get it under 32k.
Code: |
#include <18F8720.h>
#device *=16 // this makes no difference to the problem
#include <string.h>
#include <stdlib.h>
#include <stddef.h>
#include <math.h>
#define ICD=TRUE
#define RAMSIZE 3840
#define STACKSIZE 31
#define EEPROMSIZE 1024
#define FLASHSIZE (128 * 1024)
#define ERAMSIZE (128 * 1024) // external 128K x 8 SRAM
#define ERAM 0x20000 // Start address of extarnal RAM
#use i2c(master, scl=PIN_C3, sda=PIN_C4, slow)
#use delay(clock=25000000)
#use rs232(stream=com1,baud=9600,parity=N,xmit=tx1,rcv=rx1,enable=ser1en1)
//External com port - switch selectable for RS232, RS485 & Ethernet
#use rs232(stream=com2,baud=9600,parity=N,xmit=tx2,rcv=rx2,enable=ser1en2)
// Internal RS485 com port for talking to bench
#fuses HS,NOWDT,NOPROTECT,NOLVP,DEBUG,EMCU // EMCU fuse enables external RAM access
|
I have an external 128k SRAM.
It's address space starts at 128k, after code.
It's working fine.
Any idea what I am doing wrong?
Thanks |
|
|
raljones
Joined: 11 Aug 2005 Posts: 11
|
compiler version |
Posted: Thu Aug 11, 2005 3:48 pm |
|
|
I should mention that I've compiled it on version 3.207 & 3.224. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
|
raljones
Joined: 11 Aug 2005 Posts: 11
|
optimization level |
Posted: Thu Aug 11, 2005 6:26 pm |
|
|
Thanks for the tip, but I'm afraid it didn't help.
At least not with compiler Version 3.207
Here are my results:
no #opt 33130 bytes (25%) crash
#opt 0 42222 bytes (32%) not run at all
#opt 1 41956 bytes (32%) not run at all
#opt 2 41956 bytes (32%) not run at all
#opt 3 41956 bytes (32%) not run at all
#opt 4 41956 bytes (32%) not run at all
#opt 5 41956 bytes (32%) not run at all
#opt 6 41746 bytes (32%) not run at all
#opt 7 38442 bytes (29%) not run at all
#opt 8 36880 bytes (28%) just starts to run
#opt 9 33130 bytes (25%) crash - same as no #opt statement
I'm not sure what this means, but too much opt does not seem to be the problem.
But I'll try compiler Version 3.224 tomorrow anyway, just in case.
Any other suggestions?
Thanks |
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Thu Aug 11, 2005 7:12 pm |
|
|
What rev is the silicon? If its A3 I wouldn't trust it. I've had tons of them bad. All doing wierd stuff. Sometimes just changing a line of code would make things better. A4's work just fine. Supposely, the bad ones are supposed to work below 4MHz but I never confirmed this. I just swapped them out with the later rev. |
|
|
raljones
Joined: 11 Aug 2005 Posts: 11
|
silicon revision |
Posted: Fri Aug 12, 2005 11:03 am |
|
|
When the IDC connects to the chip it says:
Target Device PIC18F8720 found, revision = 0x4
Does that make it an A3 or A4?
BTW, it's running at 25MHz. |
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Fri Aug 12, 2005 12:36 pm |
|
|
I'm guessing that would be an a4. My version of MPLAB (7.20) displays the revision as a4 instead of 0x4. Can you run it slower as a test? |
|
|
raljones
Joined: 11 Aug 2005 Posts: 11
|
Clock speed |
Posted: Fri Aug 12, 2005 5:42 pm |
|
|
I'll try running it slower.
I have to get my hands on a slower oscillator. |
|
|
raljones
Joined: 11 Aug 2005 Posts: 11
|
|
Posted: Mon Aug 15, 2005 1:26 pm |
|
|
No, running it slower (4MHz) didn't help.
I also tried another Motherboard to make sure it isn't just one bad chip, but it fails on the other card as well.
Anybody got any more suggestions? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Aug 15, 2005 1:34 pm |
|
|
Change the source code so that you can cause the error by adding
one line of code -- such as delay_cycles(1), which translates to a NOP.
Then compile it with and without that line, and then compare the .LST
files. Also perhaps step through the code in the area that crosses
the 32KB boundary. |
|
|
raljones
Joined: 11 Aug 2005 Posts: 11
|
Code size |
Posted: Mon Aug 15, 2005 6:45 pm |
|
|
If I chop out code until it works,
then add NOPs ( delay_cycles(1) ) until it fails,
the largest file size that works says
ROM used: 32190 bytes (25%).
Not exactly 32768 for some reason.
Adding one or two more NOPs causes it to hang,
adding a third produces the characteristic restarting behavior.
Of course if I want to single step it I have to include the debugger, which changes the behavior. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Aug 15, 2005 7:37 pm |
|
|
Can you look at the .LST files for the working version and the failed
version, and see if adding the NOPs caused a function to be shoved
over the 32KB boundary ? In the working version, are all functions
allocated below that boundary ? |
|
|
raljones
Joined: 11 Aug 2005 Posts: 11
|
NOP details |
Posted: Tue Aug 16, 2005 4:20 pm |
|
|
Alright, I can single step it. With disassembly on interesting things can be seen.
I had been putting the NOPs at the beginning of main().
If I move the NOPs to the very end of main(), after the closing brace of the infinite loop:
Code: |
main()
{
..
while(1)
{
..
}
delay_cycles(1);
..
delay_cycles(1);
}
|
it won't crash no matter how many NOPs there are.
However, if the NOPs are at the very end of the infinite loop:
Code: |
main()
{
..
while(1)
{
..
delay_cycles(1);
..
delay_cycles(1);
}
}
|
it is sensitive to how many there are.
An interesting thing to note is that the compiler inserts a sleep instruction right after the closing brace of main(), I guess to halt the program if it finishes and exits main(). This sleep instruction is visible in disassembly.
If the last NOP is at address 07DBA, so the BRA at the end of the loop is at 07DBE and the SLEEP at 07DC0 it runs fine.
07DBA 0000 NOP
07DBC 0105 MOVLB 0x5
07DBE D4A3 BRA 0x7706
07DC0 0003 SLEEP
But if the last NOP is at address 07DBC, so the BRA at the end of the loop is at 07DC0 and the SLEEP at 07DC2, it does not take the BRA and hangs at the SLEEP.
07DBA 0000 NOP
07DBC 0000 NOP
07DBE 0105 MOVLB 0x5
07DC0 D4A3 BRA 0x7706
07DC2 0003 SLEEP
Why is it doing this? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Aug 16, 2005 4:36 pm |
|
|
Quote: |
But if the last NOP is at address 07DBC, so the BRA at the end of
the loop is at 07DC0 and the SLEEP at 07DC2, it does not take the BRA and hangs at the SLEEP |
What debugger and what IDE are you using ? What versions ?
Does this failure (to take the BRA) occur only in single-step
debugging ? Does it occur if you tell the debugger to "run" ?
Does it occur when the PIC is running it as a standalone program ?
(ie., no debugger) |
|
|
raljones
Joined: 11 Aug 2005 Posts: 11
|
debugger |
Posted: Tue Aug 16, 2005 5:16 pm |
|
|
Debugger info
MPLAB ICD 2 Version 01.20.00.00
Firmware ICD2
Firmware Type 18F
Firmware Version 02.00.05.00
Bootloader Version 01.01.01.00
Debug Exec Version (none given)
If I hit RUN, it hangs, but won't tell me where it is hung when I stop it.
Without the debugger, it hangs, but there is no way to see where. |
|
|
|