View previous topic :: View next topic |
Author |
Message |
huwemajor
Joined: 06 Sep 2004 Posts: 5 Location: Southampton, UK
|
Help with interrupts |
Posted: Mon Sep 06, 2004 4:24 am |
|
|
I need to run a fairly long section of code on an interrupt. I know this is bad practice but i do not need to observe anything else once this interrupt is activated.
Just trying to call my 'longish' function from within the interrupt causes an 'out of rom' message. I'm using a 16f877 which is only 20% full.
Any help would be much appreciated |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Mon Sep 06, 2004 5:27 am |
|
|
Which compiler version are you using? The release notes for v3.209 mention a fix for large ROM chips. |
|
|
Haplo
Joined: 06 Sep 2003 Posts: 659 Location: Sydney, Australia
|
|
Posted: Mon Sep 06, 2004 5:44 am |
|
|
Meanwhile, try putting the big code in a separate function, and call that function from inside your ISR. Don't forget to put the line
#SEPARATE
Before your function so it won't get implemented inline. |
|
|
huwemajor
Joined: 06 Sep 2004 Posts: 5 Location: Southampton, UK
|
|
Posted: Mon Sep 06, 2004 10:15 am |
|
|
Right i have tried using #separate to no avail. The code i am calling is a function anyway, like you suggested.
The problem is due to having a delay in the function, again i realise this is bad practice. Any further ideas would be much appreciated, I'll also update my compiler and see if that helps. |
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Mon Sep 06, 2004 2:23 pm |
|
|
Set a flag and handle it in the main loop. If the function is too big then break it up. printf's are a hog. |
|
|
huwemajor
Joined: 06 Sep 2004 Posts: 5 Location: Southampton, UK
|
|
Posted: Mon Sep 06, 2004 3:19 pm |
|
|
Ok i have tried using the downloaded demo software which says it works with my PIC, the 16F877. This didn't help the matter.
But one thing that confuses me is that the ROM usage is on 81% without the interrupt, but is then full with the interrupt. I am obviously being stupid but, why does it take over 19% of the ROM to store the program counter value and jump to a section of code that gets used elsewhere and jump back again after that.
I would have thought that would be a simple task for a PIC. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Sep 06, 2004 4:01 pm |
|
|
Quote: |
I have tried using the downloaded demo software which says it works with my PIC, the 16F877 |
On the CCS Demo page, it says: There is a 2K program size limit.
http://www.ccsinfo.com/demo.shtml
Quote: |
But one thing that confuses me is that the ROM usage is on 81% without
the interrupt, but is then full with the interrupt |
19% of 2048 = 389 ROM words (approx.) remaining.
When you put in the isr, the compiler will add 50+ lines of ASM code
just to create the interrupt dispatcher. I suspect that you have some
lengthy code in the isr, which uses up the rest of the ROM words. |
|
|
huwemajor
Joined: 06 Sep 2004 Posts: 5 Location: Southampton, UK
|
|
Posted: Mon Sep 06, 2004 4:45 pm |
|
|
Sorry i don't think its that. I have also tried compiling with the full version of CCs and the exact same thing happens.
And anyway its at 81% if i leave in the interrupt routine but just remove the function call within the ISR |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Sep 06, 2004 5:29 pm |
|
|
Post the C source code for the isr. If some of the variables used
in the isr are globals, then show the declarations for them too. |
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Mon Sep 06, 2004 7:22 pm |
|
|
If you don't call the function then the compiler will not include it! I am pretty sure that it is because of the demo software. |
|
|
Haplo
Joined: 06 Sep 2003 Posts: 659 Location: Sydney, Australia
|
|
Posted: Mon Sep 06, 2004 7:46 pm |
|
|
One thing comes to mind: As PCM Programmer calculated, you probably have about 390 words free. The ISR overhead is about 60 words, so that leaves you with 330 words.
Since you are using PIC16F877, you must be getting the error message "Out of ROM, a segment is too large". You may have 330 words free, but it is probably broken down between different segments. CCS can't implement a function across two segments, so if you have a big function, you'll need to have at least one segment with big enough free space to hold that function. You can see the amount of free memory in each segment in the .STA (statistics) file. Here is an example:
Quote: |
Segment Used Free
--------- ---- ----
00000-00003 4 0
00004-00034 49 0
00035-007FF 1994 1
00800-00FFF 2030 18
01000-017FF 2006 42
01800-01826 39 0
01827-0182F 0 9
01830-01890 92 5
01891-01BFE 674 204
01BFF-01C08 2 8
01C09-01FFF 605 410
|
As you can see this program has more than 650 words available, but any functions bigger than 410 bytes will cause 'Out of ROM error'. That is probably the culprit in your case.
To work around this problem, use #separate to manually place all (or at least enough of) the functions in your code until you get a segment with free space big enough. It is doable, just takes a bit of time. The information in the .SYM and .STA file are very handy in doing this.
And one more thing, if you are using ICD, the compiler adds a little program at the end of the program memory. In this case you will not have 390 words free, even if the compiler reports so. |
|
|
bdavis
Joined: 31 May 2004 Posts: 86 Location: Colorado Springs, CO
|
|
Posted: Mon Sep 06, 2004 10:30 pm |
|
|
If you don't need to do/observe anything else once in the interrupt, then you may want to consider polling for the interrupt and eliminating the interrupt handler altogether... |
|
|
Haplo
Joined: 06 Sep 2003 Posts: 659 Location: Sydney, Australia
|
|
Posted: Tue Sep 07, 2004 4:35 am |
|
|
Correction to my previous post: What I meant was use #separate and #org to manually place the functions in the memory. If you look at the example I posted, I had done the same to fit a big code in PIC16F877 memory. That is why there are so many segments in it. |
|
|
huwemajor
Joined: 06 Sep 2004 Posts: 5 Location: Southampton, UK
|
|
Posted: Tue Sep 07, 2004 5:08 am |
|
|
Thanks Haplo, PCM Programmer suggested that last night and fixed it for me.
It now all works.
Thanks to everyone else as well. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Sep 07, 2004 12:07 pm |
|
|
The solution that I suggested in response to a PM, was to take 3 lines
of floating point calculations that were in main(), and move them into
a function of their own. Then call that function from main().
His main() function was large, and by putting the floating point code
in its own function, this allowed the compiler to partition the functions
into the 4 ROM segments successfully.
I recommended against using #separate because then you have to
watch the .LST file to see if you have exceeded the 8 stack levels
available in the 16F877.
To demonstrate this, the test program shown below uses #separate in
several chained function calls, and it uses 9 stack levels. No compiler
warning is given. This is stated in the manual.
Code: | CCS PCM C Compiler, Version 3.209, xxxxx 07-Sep-04 11:04
Filename: C:\PICC\TEST\test.LST
ROM used: 53 words (1%)
Largest free fragment is 2048
RAM used: 5 (3%) at main() level
6 (3%) worst case
Stack: 9 locations |
Code: | #include <16F877.H>
#fuses XT, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock = 4000000)
//=======================
#separate
void func9(void)
{
char c;
c = 0x55;
}
//----------------------
#separate
void func8(void)
{
func9();
}
//----------------------
#separate
void func7(void)
{
func8();
}
//----------------------
#separate
void func6(void)
{
func7();
}
//----------------------
#separate
void func5(void)
{
func6();
}
//----------------------
#separate
void func4(void)
{
func5();
}
//----------------------
#separate
void func3(void)
{
func4();
}
//----------------------
#separate
void func2(void)
{
func3();
}
//----------------------
#separate
void func1(void)
{
func2();
}
//==================
void main()
{
func1();
while(1);
} |
|
|
|
|