CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

HIGH_INTS = TRUE
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
jseidmann



Joined: 04 Nov 2004
Posts: 67

View user's profile Send private message Send e-mail

HIGH_INTS = TRUE
PostPosted: Tue Feb 21, 2006 4:24 pm     Reply with quote

I am currently using the PCWH version 3.190 and I am considering upgrading to the newest compiler version, specifically to get access to the '#DEVICE HIGH_INTS = TRUE' command.

The reason is because I want to be able to have my INT_RDA a higher priority. I am having some problems with my RS-485 and believe that having a hardware interrupt (this is what HIGH_INTS does, no?) will help me out.

My question is: do I understand this correctly? Is that what HIGH_INTS does? If so, how do I implement it? Do I just add that one line? Do I need to add anything else?

Any comments are appreciated,

thanks
treitmey



Joined: 23 Jan 2004
Posts: 1094
Location: Appleton,WI USA

View user's profile Send private message Visit poster's website

PostPosted: Tue Feb 21, 2006 4:52 pm     Reply with quote

HIGH_INTS are beyond my scope.
They have to do with the stack and a high int breaking out of a low int.

BUT

Have you tried #priority?
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Tue Feb 21, 2006 5:56 pm     Reply with quote

Quote:
The reason is because I want to be able to have my INT_RDA a higher priority. I am having some problems with my RS-485 and believe that having a hardware interrupt (this is what HIGH_INTS does, no?) will help me out.
I'm not sure I understand this question correctly, it implies you are currently not using any hardware interrupts at all. Is that true?

From the readme.txt of v3.241:
Quote:
PIC18 interrupts now allow the HIGH option to mark an interrupt as high priority.
A summary of the different kinds of PIC18 interupts:
#INT_xxxx
Normal (low priority) interrupt. Compiler saves/restores key registers.
This interrupt will not interrupt any interrupt in progress.
#INT_xxxx FAST
High priority interrupt. Compiler DOES NOT save/restore key registers.
This interrupt will interrupt any normal interrupt in progress.
Only one is allowed in a program.
#INT_xxxx HIGH
High priority interrupt. Compiler saves/restores key registers.
This interrupt will interrupt any normal interrupt in progress.
#INT_GLOBAL
Compiler generates no interrupt code. User function is located
at address 8 for user interrupt handling.

All these options are available in v3.190 except for the HIGH keyword.

The PIC18 processor has two levels of hardware interrupts: normal and high priority. Normal interrupts are easy to implement using the #INT_xxx keywords. If you want to be able to interrupt an already active interrupt than you need to code that as an High priority interrupt.
The high priority interrupts can be used in v3.190 using the FAST keyword but you as the programmer will have to take care of saving and restoring all used registers. The new HIGH keyword takes this burden out of your hands but at the cost of saving all registers, not just the few you are actually using. Still, the HIGH keyword is usefull when you want a quick and sure implementation of an interrupt that can interrupt a lower priority interrupt.

Using the High priority interrupts caused many people headaches because they forgot to save a register. If you don't need the quality of an interrupt being interrupted by another interrupt then have a look at the easier to implement #priority keyword as Treitmey already pointed to.
jseidmann



Joined: 04 Nov 2004
Posts: 67

View user's profile Send private message Send e-mail

PostPosted: Wed Feb 22, 2006 7:40 am     Reply with quote

To clear a few things up, here is my situation:

I am using a PIC18F252 on a fairly intensive data acquisition product. When this product is 'off' so to speak, that its only collecting some data, then the RS-485 works flawlessly for 72 hours (thats how long I ran a test for).

If I turn on all of the data acquisition capabilities, it 'drop's' some RS-485 commands. It drops roughly 25 commands an hour (running at 19200 baud).

The interrupts are never disabled at any time. Ever. My question is that since the RS-485 interrupt should ALWAYS be interrupting any routine that the main program is in, I should never be having this RS-485 problem, but for some reason this problem is happening.

I am currently using 2 interrupts, the INT_RDA, and the TIMER2 interrupt which executes every 1/2 a millisecond. INT_RDA has been made a higher priority on the #PRIORITY with no improvement in the RS-485 performance. I feel that perhaps by using the HIGH_INTS = TRUE and making the RDA a #INT_RDA HIGH will improve this. Does that make sense? I tried making the #INT_RDA FAST, but the data acquisition process that used the TIMER2 interrupt did not work at all.

I am certainly up for any suggestions, but remember I am using compiler 3.190

Thanks!
MikeValencia



Joined: 04 Aug 2004
Posts: 238
Location: Chicago

View user's profile Send private message Send e-mail Yahoo Messenger

PostPosted: Wed Feb 22, 2006 8:21 am     Reply with quote

I use

#priority EXT,TIMER3

in my code. Also, instead of using high priority interrupts (since the syntax overwhelms me!), i do the following:

Say i'm in the TIMER3 isr, then I check if the EXT interrupt flag is set. So I just call the function called by my INT_EXT isr. This way i avoid the latency of exiting the current isr, and then re-entering the pending isr.

There is still some latency, which depends on how soon you check for the pending interrupt flag while still in the current interrupt, but it is significantly reduced.
jseidmann



Joined: 04 Nov 2004
Posts: 67

View user's profile Send private message Send e-mail

PostPosted: Wed Feb 22, 2006 8:31 am     Reply with quote

How do I check if the interrupt flag is set as you suggest?
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Wed Feb 22, 2006 8:48 am     Reply with quote

Another optimization that often is overlooked in the int_rda handling is that you can check for more characters to be waiting. The hardware UART can buffer up to three characters and you can read all of them in a loop instead of only reading a single character.

Code:
unsigned char RCREG;
#locate RCREG=0x0FAE

unsigned char RCSTA;
#locate RCSTA=0x0FAB

struct {
unsigned char RX9D:1;
unsigned char OERR:1;
unsigned char FERR:1;
unsigned char ADDEN:1;
unsigned char CREN:1;
unsigned char SREN:1;
unsigned char RX9:1;
unsigned char SPEN:1;
} RCSTAbits;
#locate RCSTAbits=0x0FAB

//-----------------------------------------------------------------------------
// Received data interrupt
//-----------------------------------------------------------------------------
#int_rda
void Rx_Isr(void)
{
  char NewChar;
 
  do
  {
    // Read the character from the UART buffer.
    // Remember that even if OERR, was asserted, the data buffers
    // will be full, and you must read the character, or the
    // error will re-assert almost immediately...
    NewChar = RCREG;

    // Check for errors
    if (RCSTAbits.OERR)
    {
      // Clear overrun error bit
      RCSTAbits.CREN=0;
      RCSTAbits.CREN=1;
      // Optional: add a global error flag for error detection.
    }

    SaveToRxCircularbuffer(NewChar);
  } while (kbhit());  // while (character is waiting);
}
MikeValencia



Joined: 04 Aug 2004
Posts: 238
Location: Chicago

View user's profile Send private message Send e-mail Yahoo Messenger

PostPosted: Wed Feb 22, 2006 12:42 pm     Reply with quote

jseidmann wrote:
How do I check if the interrupt flag is set as you suggest?


Code:

    if (PIC_INTCON & PIC_INTCON_INT01F)
    {
...


I just check the particular interrupt flag bit in the INTCON register. The snippet above shows me checking if the external interrupt flag bit (RB0) is set.
Ttelmah
Guest







PostPosted: Thu Feb 23, 2006 3:23 am     Reply with quote

As a comment, it is probably more efficient, to just declare the flag with a #bit declaration.So (for a PIC18):
Code:

#byte INTCON = 0xFF2
#bit EXT0IF = INTCON.1


Then do your test as:
Code:

do {
   //Remember _you_ must clear this flag
   EXT0IF=0;
   //Receive code here

}while (EXT0IF);


If declared like this, the compiler just does a bit test (one instruction), while with the '&', it probably does generate the extra logic this entails (the latest optimisers may be good enough to not do this though...).
Declare the interrupt with the 'NOCLEAR' option, sice you are taking over control of the interrupt flag.

Best Wishes
MikeValencia



Joined: 04 Aug 2004
Posts: 238
Location: Chicago

View user's profile Send private message Send e-mail Yahoo Messenger

PostPosted: Thu Feb 23, 2006 8:49 am     Reply with quote

[code]
.................... if (PIC_INTCON & PIC_INTCON_INT01F)
03A4: BTFSS FF2.1
03A6: BRA 03B4
[/code

Actually the generated assembly is optimized with a one-line btfss statement. I totally agree though that using #bit to declare it is more readable and use-able. I remember in my past job that it irked some people maintaining my code that all my code looks like cryptic logical operations.
asmallri



Joined: 12 Aug 2004
Posts: 1635
Location: Perth, Australia

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Thu Feb 23, 2006 9:29 am     Reply with quote

Quote:
The interrupts are never disabled at any time. Ever.


Are you sure? The compiler will disable interrupts itself under certain conditions.

[quote] I am using a PIC18F252 on a fairly intensive data acquisition product. When this product is 'off' so to speak, that its only collecting some data, then the RS-485 works flawlessly for 72 hours (thats how long I ran a test for).

If I turn on all of the data acquisition capabilities, it 'drop's' some RS-485 commands. It drops roughly 25 commands an hour (running at 19200 baud). [quote]

On one of my data acquisition systems based on a PIC18F252, I run a RS485 software UART at 56K, a RS232 SW FDX uart at 115200, and a HW FDX UART at 115200. The RS485 traffic rate in normal operation is 18,000 packets per hour without packet loss.

From your description, it sounds like you are spending too long in some other interrupt handler causing characters to be missed or the compiler is disabling interrupts in the main body of code.
_________________
Regards, Andrew

http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!!
EdWaugh



Joined: 07 Dec 2004
Posts: 127
Location: Southampton, UK

View user's profile Send private message

cheers
PostPosted: Tue Aug 01, 2006 6:50 am     Reply with quote

Hi,

Just wanted to say cheers to ckielstra for his great tip on the hardware buffer being 3 bytes long, by reading all present instead of just one I fixed my code.

cheers

ed
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

Re: cheers
PostPosted: Tue Aug 01, 2006 7:28 am     Reply with quote

EdWaugh wrote:
Just wanted to say cheers to ckielstra for his great tip on the hardware buffer being 3 bytes long, by reading all present instead of just one I fixed my code.
You're welcome. Very Happy
EdWaugh



Joined: 07 Dec 2004
Posts: 127
Location: Southampton, UK

View user's profile Send private message

actually...
PostPosted: Tue Aug 01, 2006 8:01 am     Reply with quote

Hi,

My code is much better now with the previous suggestions but I've noticed a little bit of occasional data corruption. This wasn't present during some testing I did just transfering bytes from one serial port to another using my circular buffers but is now when I add the rest of my code.

Basically I have a rs232 device that throws a string at me at 8Hz. I use a high priority rda interrupt to read as many chars as are available and test OERR like ckielstra suggests. This just chucks these into a circular buffer.

There is also a 40Hz timed interrupt that amongst other (fast) things checks the circular buffer and once a full sentence is received writes it to the mmc card buffer using:

Code:
printf(mmc_add_to_buffer, "%s", str_compass);


I'm guessing its a problem at the char receive level still, I'm gonna have a play around but as this seemed fairly well trodden ground I thought I would see if anyone had any suggestions. The errors are a few chars in length and occur intermitantly.

cheers

ed
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Tue Aug 01, 2006 11:55 am     Reply with quote

Use the error-flags of the UART to figure out if it is a framing error or an buffer overrun error.

In case of framing error the problem is most likely a timing error between the clock speed of the sender and receiver. Only about 5% total error margin for sender and receiver together is allowed. Some PC's are known to be terrible inaccurate.

In case of an overrun error you know you are reading too slow. Do you have other interrupts active? Also note that some of the compiler inbuilt functions will disable all interrupts, think of functions like memcpy and a software UART.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
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