View previous topic :: View next topic |
Author |
Message |
Bryan
Joined: 23 Apr 2005 Posts: 73
|
Global variables access issues |
Posted: Tue Oct 10, 2006 9:47 pm |
|
|
I increment a global count variable in an ISR, and then print the result after the calculations are performed using the UART and this works correctly - I get what was expected. Unfortunately, when I try to access this variable in a function which is called in my main loop later on, it is not accessed period when I try to call it in a for loop inside this function. Do I need to disable the ISR where the global variable is incremented? Are there access issues with global variables that I am unaware of? Any help would be greatly appreciated! By the way I am using a PIC18F2580. |
|
|
asmallri
Joined: 12 Aug 2004 Posts: 1634 Location: Perth, Australia
|
|
Posted: Tue Oct 10, 2006 10:13 pm |
|
|
It depends. If the variable is a byte or a bit no, anything else yes. _________________ Regards, Andrew
http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!! |
|
|
Bryan
Joined: 23 Apr 2005 Posts: 73
|
|
Posted: Tue Oct 10, 2006 10:48 pm |
|
|
Could you be more specific? The variable I am incrementing is an int, but I am also having trouble accessing an array that is a global which is filled in in the ISR. I use my incrementing variable to fill in the array elements sequentially like the code below:
Code: |
#device HIGH_INTS = TRUE
bitpos = 0;
data[88];
#int_ccp1 fast
void ccp_int()
{
data[bitpos] = CCP_1;
bitpos++;
}
|
I also used the preprocessor directive to set the compiler to be able to use high priority interrupts for the fast keyword and this helped significantly. Any ideas why when I try to access my array and bitpos in a function that is called within main, it cannot read them? |
|
|
asmallri
Joined: 12 Aug 2004 Posts: 1634 Location: Perth, Australia
|
|
Posted: Tue Oct 10, 2006 11:57 pm |
|
|
There are 1 to 3 possible problems. It depends on your compiler version and you PIC rev.
1. Some versions of CCS save the interrupt context for the fast handler, some do not. There are pros and cons either way. For the sort of low latency critical high priority interrupts I usually use, the compiler is very inefficient and would prevent my code form operating correctly. For example I have two full duplex software UARTS running at 115Kbps which would not be possible with the compiler saving the context. Depending on the compiler version, the fast directive no only sets the interrupt as a high priority interrupt but also results in the fast return option being used where the PIC restores the BSR, WREG and STATUS registers from the shadow registers.
2. Some 18F series PIC (most) are broken with their fast interrupt handling. This is because the shadow registers for WREG, STATUS and BSR, may hold the incorrect entry if a movff instruction operating on any of the non shadowed versions of these registers was interrupted mid step. The result is the shadow versions are not correct and therefore when returning form interrupt the processor status was corrupted. So if you happen to have one of these PICs and the compiler does not have the context for you then your application can crash and burn. The work around is to save these registers yourself (using movff instructions) and exit the handler via your own _asm RETFIE 0 _endasm instruction.
3. In your example you use an array data[] inside the handler. Now the compiler might be using the FSR0 registers to do this but if the compiler is not saving the context, then these registers are being corrupted. Therefore, depending on point 1, you may also need to save the FSR registers. It is easy to tell just dump the listing. The compiler can (and often does) generate rather convoluted (inefficient and using more registers) for dealing with arrays. So, if your compiler version does not save context, here is a cleanish work around: inside the FAST interrupt handler
Code: |
// save FSR 0
IH_FSR0L = FSR0L; // the complier will use movff
IH_FSR0H = FSR0H; // the compiler will use movff
_asm
lfsr 0, data
movff bitpos, WREG // deliberate use of movff
movff CCP_1, PLUSW0
_endasm
FSR0L = IH_FSR0L;
FSR0H = IH_FSR0H;
|
What type of variables are data and bitpos? _________________ Regards, Andrew
http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!! |
|
|
Bryan
Joined: 23 Apr 2005 Posts: 73
|
|
Posted: Wed Oct 11, 2006 12:38 am |
|
|
Thanks for the help! My bitpos is a simple int and the array data is an array of longs. The weird part with this is that if I read either bitpos or the various data locations in the array in main, everything seems to be consistent and ok. If I try to access either of these from a function that is defined outside of main and called within main, I run into problems.
Another strange problem I have is that when I try to disable my ccp interrupt after I have collected all of the data from the incoming signal (I am doing signal reading) I no longer get anything. This is strange because I know my disabling is happening after the data has come in and I have verified this. Any ideas why this might be the case? |
|
|
asmallri
Joined: 12 Aug 2004 Posts: 1634 Location: Perth, Australia
|
|
Posted: Wed Oct 11, 2006 12:51 am |
|
|
Bryan wrote: | and the array data is an array of longs |
This is why you need to disable interrupts in main.
Quote: | Another strange problem I have is that when I try to disable my ccp interrupt after I have collected all of the data from the incoming signal (I am doing signal reading) I no longer get anything. |
I don't understand what you mean. You disabled the interrupt because you don't want it anymore but now you are no longer getting it? How would you get it if it is disabled? _________________ Regards, Andrew
http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!! |
|
|
Bryan
Joined: 23 Apr 2005 Posts: 73
|
|
Posted: Wed Oct 11, 2006 2:26 am |
|
|
I disable the interrupt AFTER I collect the data.
The only reason I thought this would be needed was because when I print out my array, I am only expecting 49 pieces of data, but the array was still getting data even in the positions that weren't supposed to be filled (Since it is sized as 88 wide I checked all 88 and 50-88 are filled with junk data seemingly random numbers). Now that you have mentioned the shadow register corruption it would make sense that this is why the array is getting all the junk data in it.
What do you mean by: Quote: | This is why you need to disable interrupts in main. |
I think you might be using a different compiler than I because the _asm and _endasm directives don't work - I need to use #asm and #endasm to get it to compile. |
|
|
asmallri
Joined: 12 Aug 2004 Posts: 1634 Location: Perth, Australia
|
|
Posted: Wed Oct 11, 2006 2:40 am |
|
|
Bryan wrote: | I disable the interrupt AFTER I collect the data.
The only reason I thought this would be needed was because when I print out my array, I am only expecting 49 pieces of data, but the array was still getting data even in the positions that weren't supposed to be filled (Since it is sized as 88 wide I checked all 88 and 50-88 are filled with junk data seemingly random numbers). |
If you have not prevoulsy initialized these location then they would contain junk anyway.
Quote: | I think you might be using a different compiler than I because the _asm and _endasm directives don't work - I need to use #asm and #endasm to get it to compile. |
I do use different compilers, the C18 and the CCS and in one the _asm is the correct one and in the CCS its the #asm. I just forgot which one is which :-) _________________ Regards, Andrew
http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!! |
|
|
Bryan
Joined: 23 Apr 2005 Posts: 73
|
|
Posted: Wed Oct 11, 2006 3:00 am |
|
|
Could you please describe in more detail what your ASM code does from a couple posts back as I am not familiar with some of the instructions you are using. Namely these lines:
Code: |
lfsr 0, data
movff bitpos, WREG // deliberate use of movff
movff CCP_1, PLUSW0
|
Is movff bitpos, WREG loading the value of WREG into bitpos? I have no clue what the lfsr instruction is doing, or what PLUSW0 is. Thanks for all of your help! |
|
|
asmallri
Joined: 12 Aug 2004 Posts: 1634 Location: Perth, Australia
|
|
Posted: Wed Oct 11, 2006 3:15 am |
|
|
Code: |
lfsr 0, data // load the FSR0 with the address in RAM of the data array
movff bitpos, WREG // get the vaule of BITPOS into the WREG (work register)
movff CCP_1, PLUSW0 // load the variable CCP_1 with the contents of the address data (in the FSR0) plus the offset held in WREG
|
this is equivalent to:
Code: | data[bitpos] = CCP_1; |
The difference you know explicitly what registers are used, what functions are called, and what you have to save in a handler that does not save context automatically.
My future in assembler was talked about and planned, but I gave it up for C and the CCS band. _________________ Regards, Andrew
http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!! |
|
|
treitmey
Joined: 23 Jan 2004 Posts: 1094 Location: Appleton,WI USA
|
|
Posted: Wed Oct 11, 2006 8:23 am |
|
|
a poet as well ! |
|
|
|