I have a C18 interrupt routine that I wish to convert to assembly codes in an attempt to reduce latency in some high frequency counting situation (Variable gl_pulse_cnt seems to reach its limit at about 30,000 counts with the C18 codes). Here's snippets of the codes :
Code:
unsigned long int gl_pulse_cnt=0;
#pragma code low_vector=0x18
void low_vector (void)
{
_asm GOTO isr_low _endasm
}
#pragma interruptlow isr_low
void isr_low(void)
{
gl_pulse_cnt++;
PIR1bits.CCP1IF=0; //clear interrupt flag
}
What is the assembly code equivalent of the 2-liner C18 codes within the "isr_low" routine? Would also like to insert this assembly code directly into the "low_vector" routine, within the _asm and _endasm block to reduce latency due to function calling. Is this workable?
Luckily, you only have to save the BSR register to still use that code. Plus loose the fast off the return and restore the BSR at the end of the ISR. Check the datasheet.
Alternatively, a 1 second interrupt should not get higher priority - don't use the fast return stack on that interrupt.
not a very competent assembly language & MCU programmer myself, I tinker with Mike's codes to put them into the _asm _endasm construct that I am slightly more familiar with.
I've gone thru the datasheet and modify the incfsz, bcf and retfie commands based on the syntax expected. Unfortunately it is not working! . The codes compiled well but the program does not return anything unlike the pure C18 codes.
Any advise on how I should correct the above? You have to assume I am an absolute newbie in assembly and mixing it with C18. btw, I am using 18f1220.
Instead of the piece of code in C (I am not conversant in C), could show here the correct/complete flow diagram of what you want to accomplish? I could be dead wrong but "translating" (whatever that could mean here) seems prone to create an unintended effect.
Would also like to insert this assembly code directly into the "low_vector" routine, within the _asm and _endasm block to reduce latency due to function calling
Have you taken a look at the asm output of C18 for those two instructions? It's pretty hard to beat... 17 instruction cycles total, including the intr overhead.
Also, I meant to point out that not only is the ASM code you've inserted longer than what C18 produces, you can't just do a 'retfie 0' at the end as this skips restoring the intr context that was saved as part of the intr vectoring.
You could leave that instruction out and let the isr_low() perform the proper exit, but you're still better off with the original C code.
What you're doing won't speed up anything. I guess the biggest overhead of your interrupt routine is the prolog and epilog inserted by C compiler to save/restore context. You code doesn't remove any of it.
You can look at the listing from C18 which shows its assembly. I suggest you look at it, or, perhaps, post it here.
If you're building a frequency counter a popular method was using Timer0. You can go beyond the FOSC with that method, Google 16F84 frequency counter for examples.
I posted this as a continuation of another of your threads.
Here's a 50MHz counter using the ancient 16F84. Crystal frequency needs to be accurate but doesn't need to be that fast. A TCXO would get the accuracy up.
If I were doing a frequency counter I'd use a PIC with a "Gated Timer", it can start / stop the timer based on an external input.