|
|
View previous topic :: View next topic |
Author |
Message |
[email protected]
Joined: 05 Nov 2003 Posts: 23
|
Out of ROM error, but plenty of space left in the page? |
Posted: Thu Apr 09, 2009 12:24 am |
|
|
I have a program I'm writing where I have my ISR defined as an #int_global so that I can make it leaner than CCS typically does. I've found that I get the "Out of ROM" error as soon as this grows past 0x0048 or so. When the ISR compiles, it uses addresses 0004-0048, when I add another case and a simple assign I get:
Out of ROM...
seg 00004-00045, 0042 left, need 004E
Huh? since when is a page only 0x87 bytes? (a page in this part is 0xFF bytes.) I've tried putting in #SEPARATE in front of this ISR and functions that follow and it doesn't help. I know that the compiler needs to put INLINE functions completely within a page boundary, but I don't enforce INLINE anywhere. My ISR isn't all that big either, but any other function with this simple switch in it would compile fine - The ISR is the one that the compiler appears to be complaining about.
Has anyone else seen this peculiarity before?
If this can't be fixed I'm going to have to poll my SPI clock instead of using the ISR, which would be a pity and be more troublesome in "book keeping".
I'm using PCM 3.242.
thanks,
DLC _________________ --
------------------------------------
Dennis Clark [email protected]
http://www.techtoystoday.com
------------------------------------ |
|
|
Ttelmah Guest
|
|
Posted: Thu Apr 09, 2009 4:08 am |
|
|
What chip?.
Best Wishes |
|
|
Guest
|
|
Posted: Thu Apr 09, 2009 8:27 am |
|
|
Ttelmah wrote: | What chip?.
Best Wishes |
16F630 - I wouldn't think that it mattered, but you're correct, it could.
DLC |
|
|
Ttelmah Guest
|
|
Posted: Thu Apr 09, 2009 9:55 am |
|
|
OK.
Have you got the line *=16 in your device setup?.
Otherwise the chip will only use the bottom bank of the ROM.
Second comment, how small can you make the 'main'?.
Problem exists, that the compiler will normally want to fit the main into the bottom page. I'd suspect that what is actually happening, is that the 'main' is actually '0xBA' in size, and because it is written in one piece, can't be split up, not leaving enough space for the interrupt handler.
Best Wishes |
|
|
n-squared
Joined: 03 Oct 2006 Posts: 99
|
|
Posted: Thu Apr 09, 2009 10:08 am |
|
|
In addition to Ttelmah's comment about the size of main, please note that the PCM compiler tends to put functions that are called only once into the calling function to save on call stack's limited space (only 8 deep). This will make the main function bigger than you expect.
To make the functions separate from main(), place a #separate directive above the function declaration.
Best regards
Noam _________________ Every solution has a problem. |
|
|
Guest
|
|
Posted: Thu Apr 09, 2009 10:57 pm |
|
|
Ttelmah wrote: | OK.
Have you got the line *=16 in your device setup?.
Otherwise the chip will only use the bottom bank of the ROM.
Second comment, how small can you make the 'main'?.
Problem exists, that the compiler will normally want to fit the main into the bottom page. I'd suspect that what is actually happening, is that the 'main' is actually '0xBA' in size, and because it is written in one piece, can't be split up, not leaving enough space for the interrupt handler.
Best Wishes |
??? *=16? Hmm, I'm not sure just what good that will do, but hey, I'm puzzled so I'm go. Main is pretty darn small right now since it is little more than a while loop with a couple of function calls. Since the 16F630 only has 1K of ROM, I doubt that making the addresses 16 bit vs. 14 bit will have any effect, but hey, I'll try it.
I have two small functions (init and a SONAR ping) along with the main and the ISR. The whole bloody thing fits into 512 bytes, so I'm pretty baffled with this error.
... I tried the *=16, no effect on the issue, not even the numbers changed. Bummer.
Thanks for the help though, that suggestion could be useful in other parts.
DLC |
|
|
[email protected]
Joined: 05 Nov 2003 Posts: 23
|
|
Posted: Thu Apr 09, 2009 11:03 pm |
|
|
n-squared wrote: | In addition to Ttelmah's comment about the size of main, please note that the PCM compiler tends to put functions that are called only once into the calling function to save on call stack's limited space (only 8 deep). This will make the main function bigger than you expect.
To make the functions separate from main(), place a #separate directive above the function declaration.
Best regards
Noam |
Thanks. I put #SEPARATE before _every_ function to try this out and nothing changed. There is some other pathological activity going on here that I don't grok. The list file (when it compiled) seemed very logical. I've been using CCS for 10 years and I've never had this issue before.
Still working on it - I'm going to try "org"ing the ISR elsewhere in memory to see if that helps.
thanks all,
DLC _________________ --
------------------------------------
Dennis Clark [email protected]
http://www.techtoystoday.com
------------------------------------ |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Apr 09, 2009 11:20 pm |
|
|
Post the smallest possible program that shows the problem, but that
also compiles with no errors. Then show in comments the line that
if added, causes the error. |
|
|
[email protected]
Joined: 05 Nov 2003 Posts: 23
|
|
Posted: Fri Apr 10, 2009 12:06 am |
|
|
PCM programmer wrote: | Post the smallest possible program that shows the problem, but that
also compiles with no errors. Then show in comments the line that
if added, causes the error. |
You got it. BTW, if I use #int_ext instead of #int_global, it will compile, but the ISR is WAY bigger than it needs to be in this case.
Here is my code, trimmed to useless, but showing the compile error:
Code: |
#include <16F630.h>
#fuses HS,NOWDT,MCLR,NOPROTECT,NOBROWNOUT
#use delay(clock=10000000)
#use rs232(baud=9600, xmit=PIN_C1, rcv=PIN_C2, INVERT) //software UART
#use FAST_IO(C)
#use FAST_IO(A)
#define myAddr 0x10 //This should be stored in EEPROM and be configurable
//But I ran out of time for a full implementation.
#define PWR PIN_C3
#define ECHO PIN_C4
#define SINIT PIN_C5
#define SDA PIN_C0
#define SCK PIN_A2
#define ATRIS 0x04 //data direction for TRIS A
#define CTRIS 0x14 //data direction for TRIS C C0 output
#define RSPI 0x15 //turn C0 to input
#define S_IDLE 0 // waiting for any clock
#define S_ADDRCMD 1 //Address and command input state
#define S_DOUT 2 //Sending data out
#define S_DIN 3 //Pulling in 16 bits of data
#define S_READY 4 //There is a command ready
int cmdIn = 0; //Most recent command received
#locate cmdIn = 0x5c //Keep it in common memory for ISR use
int bCount = 0; //bit coming in or going out
#locate bCount = 0x5b //Kept in register memory for fast access in ISR
long dataIn = 0;
#locate dataIn = 0x59 //Should I ever take 16 bits of data in...
int spiState = 0; //state machine variable for communications
#locate spiState = 0x58
int addrIn = 0; //incoming address target
#locate addrIn = 0x57
long dataOut = 0; //16 bit data to send back
int save_w;
#locate save_w=0x5f
int save_status;
#locate save_status=0x5e
int save_FSR;
#locate save_FSR=0x5d
/*
* Give me direct access to several SFR's that I want to deal with.
*/
#byte INTCON = 0x0B
#byte FSR = 0x04
#byte status = 0x03
#byte TRISC = 0x87
#int_global
void isr(void)
{
#asm
//store current state of processor
MOVWF save_w
SWAPF status,W
MOVWF save_status
SWAPF FSR,W
MOVWF save_FSR
BCF status,5 //Set to page 0 for SFR's
BCF status,6
#endasm
switch (spiState)
{
// Uncomment these next two lines and it won't compile. (DLC)
// case S_IDLE: //Kick start the state machine
// spiState = S_ADDRCMD; //and move right to the next state
case S_ADDRCMD:
if (bCount <8) //We are getting the target address
{
shift_left(&addrIn,1,SDA); //Get the current data value
}
else if(bCount < 16) //Now getting the command
{
shift_left(&cmdIn,1,SDA);
if ((addrIn == myAddr) && ((cmdIn & 0x80) == 0))
{
set_tris_C(CTRIS); //Make SDA an output now
spiState = S_DOUT; //next state is data going out
}
else
{
spiState = S_DIN; //next state is 16 bits data in
}
}
break;
case S_DOUT: //Next 16 bits go out
output_bit(SDA,shift_right(&dataOut,2,0));
break;
case S_DIN: //Next 16 bits come in
shift_left(&dataIn,1,SDA);
break;
}
bCount++;
//increment the bit count
#asm
// clear INT flag and restore processor and return from interrupt
BCF INTCON,1
SWAPF save_FSR,W
MOVWF FSR
SWAPF save_status,W
MOVWF status
SWAPF save_w,F
SWAPF save_w,W
#endasm
}
void init(void)
{
set_tris_C(RSPI); //SDA is an input
set_tris_A(ATRIS);
enable_interrupts(INT_EXT); //enable external INT (SCK line)
enable_interrupts(GLOBAL); //turn on the interrupts
}
int16 ping(void)
{
int16 temp; //holder for 16 bit time
return (temp/92); //148us/1.6us = 92.5, return inches
}
void main(void)
{
int16 x;
init();
delay_ms(2000);
while(1)
{
output_high(PIN_C0);
x = ping(); //Get SONAR reading
}
}
|
This compiles, pull out the noted commented lines in the ISR and it won't. When compiled this code uses 18% of the ROM space.
thanks,
DLC _________________ --
------------------------------------
Dennis Clark [email protected]
http://www.techtoystoday.com
------------------------------------ |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Apr 10, 2009 1:16 am |
|
|
If you add a default case, it compiles:
Quote: | case S_DIN: //Next 16 bits come in
shift_left(&dataIn,1,SDA);
break;
default:
} |
|
|
|
dbotkin
Joined: 08 Sep 2003 Posts: 197 Location: Omaha NE USA
|
|
Posted: Fri Apr 10, 2009 7:30 am |
|
|
I've seen that happen myself, just a couple of days ago (version 4.087, 18F4620). I had a switch statement that caused an "Out of ROM" error until I added a default case. Nothing else, just default: at the end, and it worked fine. |
|
|
[email protected]
Joined: 05 Nov 2003 Posts: 23
|
|
Posted: Fri Apr 10, 2009 8:40 am |
|
|
PCM programmer wrote: | If you add a default case, it compiles:
Quote: | case S_DIN: //Next 16 bits come in
shift_left(&dataIn,1,SDA);
break;
default:
} |
|
Thanks - I don't think that I'd ever have found that one. I don't have unbounded switch blocks so I rarely use "default" in them, there would be no point to it in a state machine. I'll mark that one down in my toolbox. I do this all the time in other routines, I wonder what makes it so special in an ISR.
Thanks for the pointer!
DLC _________________ --
------------------------------------
Dennis Clark [email protected]
http://www.techtoystoday.com
------------------------------------ |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Apr 10, 2009 1:33 pm |
|
|
The way I found it was this:
First I tried relocating main() to high memory (0x300 range) with an
#org statement. That didn't fix it.
Then I moved your sub-routines to below main() and put function
prototypes above main(), in attempt to re-arrange partitioning of ROM.
That didn't help.
Then I tried commenting out all your #locate statements, because I
thought maybe the compiler didn't like you taking away it's preferred
area for variables. That didn't work.
Then I just started chopping out sections of your code. I removed your
sub-routines init() and ping(). I removed all the code in main() except
a while(1) statement. That didn't help.
Then I started removing blocks of code from your isr. I deleted all the
ASM code. I still got the error. Then I removed most of the case code,
while still keeping the case statements in place. It still failed.
At that point, there wasn't much left. I recalled earlier threads by
Ttelmah, where he had remarked on how the compiler creates different
code based on the number of cases, and also whether or not there is
a default case present. So I said "Hmmm, what if I add a default case ?"
So the basic strategy is to cut the code down until I find the line that's
causing the problem, or until the code is so small that it's evident
what the problem is, and it can solved almost by inspection. |
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Fri Apr 10, 2009 1:46 pm |
|
|
Do you see anything reasonable in this behaviour? Or is it just a bug, continued since V3.xx of the compiler? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Apr 10, 2009 1:49 pm |
|
|
Probably the latter (a bug). |
|
|
|
|
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
|