I am writing an ISR routine to process incoming characters on a MC9S08 from another serial device. The device sends the characters with no idle time between the bytes. In one example the device responds to a specific command with 3 bytes "OK<CR>". I find that I can only recieve the first character and then I get an overRun error. I feel that either my ISR is incorrect OR my clocks are not configured correctly. My init and ISR are as follows...
...
/* configure SCI2 interrupt mode */
/* SCI2C1: LOOPS=0,SCISWAI=0,Rsrc=0,M=0,WAKE=0,ILT=0,PE=0,PT=0 */
SCI2C1 = 0x00; /* Configure the SCI */
/* SCI2C3: R8=0,T8=0,TXDIR=0,TXINV=0,ORIE=0,NEIE=0,FEIE=0,PEIE=0 */
SCI2C3 = 0x00; /* Disable error interrupts */
/* SCI2S2: LBKDIF=0,RXEDGIF=0,??=0,RXINV=0,RWUID=0,BRK13=0,LBKDE=0,RAF=0 */
SCI2S2 = 0x00;
/* SCI2C2: TIE=0,TCIE=0,RIE=0,ILIE=0,TE=0,RE=0,RWU=0,SBK=0 */
SCI2C2 = 0x00; /* Disable all interrupts */
SCI2BD = UART_BAUD_9600;
/* SCI2C3: ORIE=0,NEIE=0,FEIE=0,PEIE=0 */
SCI2C3 |= 0x00; /* disable error interrupts */
SCI2C2 |= ( SCI2C2_TE_MASK | SCI2C2_RE_MASK | SCI2C2_RIE_MASK); /* Enable transmitter, Enable receiver, Enable receiver interrupt */
asm CLI;
}
#pragma TRAP_PROC
void vSci2Rx(void){
//mask this isr
SCI2C2 &= ~(SCI2C2_RIE_MASK);
while(SCI2S1 & SCI1S1_RDRF_MASK){
//read the char into buf
ucSci2RcvBuf[iSci2Index++] = SCI2D;
if(iSci2Index > 7){
iSci2Index = 0;
}
}
//unmask isr
SCI2C2 |= (SCI2C2_RIE_MASK);
}
Any ideas on how I can get better thru-put for this part?
thanks
rich
Thanks for your replies.
The posted isr was actually a second iteration of my original routine to try to improve thru-put. As you can imagine, it didn't work. Here is what I've been using w/ most success and most posts indicate that this is the right way to do it...feel free to comment...
#pragma TRAP_PROC
void vSci2Rx(void){
char cStatus;
cStatus = SCI2S1;
//read the char into buf
ucSci2RcvBuf[iSci2Index++] = SCI2D;
if(iSci2Index > 7){
iSci2Index = 0;
}
if(cStatus & SCI1S1_OR_MASK){
while(1);//overrun here
}
}
With this isr, I get the first character and then overrun on the second.
If it isn't the isr, maybe clocks? My current target clock is around 2% of the actuall running freq. This allows me to init SCI1 and verify that I can send characters from hyperterminal to MC9S08 (it echos them back). Still trouble w/ SCI2. Other than SCI1 and SCI2, no other interrupt sources are enabled.
any other ideas?
thanks
rich
Hello Rich,
Mr. Freez wrote:If it isn't the isr, maybe clocks? My current target clock is around 2% of the actuall running freq. This allows me to init SCI1 and verify that I can send characters from hyperterminal to MC9S08 (it echos them back). Still trouble w/ SCI2. Other than SCI1 and SCI2, no other interrupt sources are enabled.
If this is what I think it means, you have reduced the number of bus cycles available to service the interrupt routine by a factor of 50, so an overrun condition is probably inevitable at the baud rate you have chosen. If you have a bus clock in the region of 100 kHz this would mean that the ISR processing should be completed within 100 bus cycles, a questionable limit.
If you have the two SCI modules operative, an additional factor would be that the processing of the ISR for one module can delay the processing of the ISR for the other module by up to the full ISR processing period.
I would suggest a bus frequency of at least 1 MHz, and more if two SCI modules are in operation, unless you wish to operate with a much lower baud rate than 9600.
Regards,
Mac
Thanks for this suggestion. Will try.
rich
Hi Rich,
Not sure about your idea of locking into an infinite loop within the ISR on overrun!
When it goes into error how many characters do you have in your buffer , or what valur is your index?
If you send just 1 byte does it look good?
Is the flag reset?
Try a dummy SCID read before you start.
Yes...that would be bad. I though I had commented that out. I had put that there to allow me to set a breakpoint to see which character was getting the overrun error. Turns out it is the first character.
At this point, the issue is that I overrun when I recieve characters from the ASIC serial device. If I hold this serial device in RESET and then send the characters from my pc, I get all characters just fine with no overrun.
Superimposing scope traces of the two bitstreams shows a slight timing difference between the ASIC and pc data (from hyperterminal).
I am currently waiting for info from the designers of this device as to how they are clocking the bits.
Thanks for your replies!
rich
It's not working because you don't clear the interrupt status flag (RDRF), and until RDRF it's set no interrupt can be triggered. Read on the datasheet how to do that.
And is useless to wait (with the while) that RDRF become set, seen that if you are in the interrupt routine is because RDRF is already set (it's this flag that triggers the ISR).
Bye Jack
Hello Rich,
Firstly I would say that your disabling of the receiver interrupts is unnecessary as all interrupts are automatically disabled by the setting of the I bit in CCR.
Jack's comment is valid in that your test is already effectively carried out by the interrupt itself.
i.e. You would not be in the interrupt code unless the flag was set already. However the test you are doing should actually satisfy the flag resetting requirements and so I am not sure that this is the cause of the problem. It is more normal to use the required read of the S1 register to look at the lower 4 bits for errors.
How are you actually detecting the overrun condition?