Hello. I'm writing a program for an NE64 board, which reads a series of data over the SCI1 port, and then transmits them over the Ethernet port. Pretty much it's done and works, but due to the amount of data collected on every reading, I have to send out 10-15 packets every time. My problem is that, when the function for UDP transmission is executed, some of the data received on the serial port are skipped and lost. I understand that in order to overcome this I need to implement an Interrupt function for the SCI1 port. I've tried this, but my code gets stuck in an infinite loop when the SCI reading in functions takes place ( SCI1in(); ). <TR> <TH>main.c</TH> //*********************************** #include "RXFIFO.H" #include "sci.h" #include "MC9S12NE64.h" //...and all other required files/libraries extern void SCI1_isr_handler (void); #pragma CODE_SEG BANKED interrupt void SCI1Interrupt (void) { SCI1_isr_handler(); } #pragma CODE_SEG DEFAULT .... <TR> <TR> <TH>RxFifo.c</TH> //************************************ #include "RxFifo.h" /* Number of characters in the Fifo the FIFO is full when it has FifoSize-1 characters */ char static volatile *RxPutPt; /* Pointer of where to put next */ char static volatile *RxGetPt; /* Pointer of where to get next */ /* FIFO is empty if PutPt=GetPt */ /* FIFO is full if PutPt+1=GetPt */ char static RxFifo[RXFIFOSIZE]; /* The statically allocated fifo data */ /*----------RxFifo_Init Initialize fifo to be empty Inputs: none Outputs: none */ void RxFifo_Init(void){unsigned char SaveCCR; /* save previous interrupt enable */ asm tpa asm staa SaveCCR asm sei /* make atomic */ RxPutPt=RxGetPt=&RxFifo[0]; /* Empty when PutPt=GetPt */ asm ldaa SaveCCR asm tap /* end critical section */ } /*---------RxFifo_Put Enter one character into the fifo Inputs: 8-bit data Outputs: true if data is properly saved Since this is called by interrupt handlers no sei,cli*/ int RxFifo_Put(char data){ char volatile *tempPt; tempPt = RxPutPt; *(tempPt) = data; /* try to Put data into fifo */ tempPt++; if(tempPt == &RxFifo[RXFIFOSIZE]){ /* need to wrap?*/ tempPt = &RxFifo[0]; } if(tempPt == RxGetPt){ return(0); /* Failed, fifo was full */ } else{ RxPutPt = tempPt; /* Success, so update pointer */ return(1); } } /*-----------------------RxFifo_Get---------------------------- Remove one character from the fifo Inputs: pointer to place to save 8-bit data Outputs: true if data is valid */ int RxFifo_Get(char *datapt){ if(RxPutPt == RxGetPt){ return(0); /* Empty if PutPt=GetPt */ } else{ *datapt = *(RxGetPt); RxGetPt++; if(RxGetPt == &RxFifo[RXFIFOSIZE]){ RxGetPt = &RxFifo[0]; } return(1); } } </TR> <TR> <TH>sci.c</TH> //************************************ #include <stdio.h> #include "ne64debug.h" #include "MC9S12NE64.h" #include "sci.h" #include "RXFIFO.H" unsigned short RxHistogram[RXFIFOSIZE]; // collected before put void SCI1Init(void){ //Debugt("Initializing my SCI1 function\r\n"); #define ECLK 25000000 //< this is BUSCLK #define BAUD_RATE 9600 PTG_PTG2 = 0; #define BAUD_DIV ECLK/16/BAUD_RATE SCI1BD= BAUD_DIV; SCI1CR1= 0; SCI1CR2= SCI1CR2_TE_MASK | SCI1CR2_RE_MASK | SCI1CR2_RIE; RxFifo_Init(); asm cli } //------SCI1 interrupt handler interrupt void SCI1_isr_handler(void){ if(SCI1SR1 & SCI1SR1_RDRF_MASK){ RxHistogram[RxFifo_Size()]++; RxFifo_Put(SCI1DRL); // clears RDRF } } //-----Start of SCI1In // Wait for new serial port input, return ASCII code for key typed char SCI1In(void){ char letter; while (RxFifo_Get(&letter) == 0){ PTG_PTG0 = 0; //<FONT FACE="Times New Roman" SIZE="+2" COLOR="#FF0000"> Where my code stucks</FONT> }; PTG_PTG0 = 1; return(letter); } </TR> My program is based on the Freescale's Connector_App, so similar initilizations take place. I'm new at this, and I had a really hard time finding information and examples using SCI Rx interrupts. Can somebody indicate me what i'm doing wrong please? Your help will be trully appreciated. Thank you

Help needed with SCI interrupts (HC12)
Started by ●June 27, 2007
Reply by ●June 27, 20072007-06-27
On Jun 27, 1:23 pm, ryufr...@hotmail.com wrote:> I understand that in order to overcome this I need to implement an > Interrupt function for the SCI1 port. > I've tried this, but my code gets stuck in an infinite loop when the > SCI reading in functions takes place ( SCI1in(); ).So which exact instructions is it looping on? Are there actually characters in the RF fifo? If you put a breakpoint in the ISR, is it triggering and storing characters to the FIFO? One general note: your memory section pragmas look a little suspicious. You need to be sure that everything that runs as a result of the interrupt is in the non-banked memory section - both the ISR routine, and anything it calls . If you don't it will likely work fine until your program grows to the size where bank switching is required, at which point it will start failing in very odd ways.> RxFifo_Put(SCI1DRL); // clears RDRFI'd be tempted to copy SCI1DRL into a volatile temporary variable so I could see with the debugger that it's actually getting read, and then call the routine using that.
Reply by ●June 28, 20072007-06-28
Hi, and thank you for your quick reply. I attempted to write in HTML formatting, to indicate some problems, but I forgot that this is not supported here. Anyway here is my feedback to your help:> > I understand that in order to overcome this I need to implement an > > Interrupt function for the SCI1 port. > > I've tried this, but my code gets stuck in an infinite loop when the > > SCI reading in functions takes place ( SCI1in(); ). > > So which exact instructions is it looping on?I inspected closer my code by adding some Debugging checkpoints, and my code loops 3-4 times in the SCI1in() function at the " while (RxFifo_Get(&letter) == 0){ };" loop when SCI1in is manually called. Then it just crashes or something.> Are there actually characters in the RF fifo? > > If you put a breakpoint in the ISR, is it triggering and storing > characters to the FIFO?I checked and it appears that the ISR is not reached before program crashes (SCI1In reached). So i guess my mistake is at a lower level, something to do with my interrupt implimentation mayb.e> One general note: your memory section pragmas look a little > suspicious. You need to be sure that everything that runs as a result > of the interrupt is in the non-banked memory section - both the ISR > routine, and anything it calls . If you don't it will likely work > fine until your program grows to the size where bank switching is > required, at which point it will start failing in very odd ways.I`m not really sure what to do with this. Any suggestions are more than welcome> > RxFifo_Put(SCI1DRL); // clears RDRF > > I'd be tempted to copy SCI1DRL into a volatile temporary variable so I > could see with the debugger that it's actually getting read, and then > call the routine using that.The 3-4 readings taken before the program crashes show SCI1DRL as 0, even though I`m transmitting to the board`s SCI1 port. I googled around a lot the past days to find SCI communication examples with interrupts to familiarize with. But I didn`t have much luck with it. If you have anything in mind please let me know. Thank you
Reply by ●June 28, 20072007-06-28
On Jun 28, 5:11 am, ryufr...@hotmail.com wrote:> I checked and it appears that the ISR is not reached before program > crashes (SCI1In reached). So i guess my mistake is at a lower level, > something to do with my interrupt implimentation mayb.ePlease describe what you mean by crashes. For example, does it jump to an arbitrary address outside of the program and thus trigger the software trap debugging interrupt? What is your debuger and target connection?> > One general note: your memory section pragmas look a little > > suspicious. You need to be sure that everything that runs as a result > > of the interrupt is in the non-banked memory section - both the ISR > > routine, and anything it calls . If you don't it will likely work > > fine until your program grows to the size where bank switching is > > required, at which point it will start failing in very odd ways. > > I`m not really sure what to do with this. Any suggestions are more > than welcomeYou need to have a non-banked memory section in your linker .prm file (assuming codewarrior) which will not be banked switch and thus always reliably there when an interrupt occurs, and you need to put your interrupt service routine and anything that it might call in that section. If you are using the .prm from the connector app, this section is called NON_BANKED so you would precede your ISR and anything it uses with a #pragma CODE_SEG NON_BANKED and follow it with a #pragma CODE_SEG DEFAULT Also make sure that you are getting the address of the ISR correctly loaded into the vector table. In the connector app, vectors.c does that and would need to reference your ISR.
Reply by ●June 28, 20072007-06-28
On Jun 28, 2:58 pm, cs_post...@hotmail.com wrote:> Please describe what you mean by crashes. For example, does it jump > to an arbitrary address outside of the program and thus trigger the > software trap debugging interrupt?I`m sorry for my ignorance, but how can I check this?> What is your debuger and target connection?I`m using Serial Monitor debugger, and Monitor as Target in Codewarrior IDE 5.7. Sorry for not referring to these information earlier.> You need to have a non-banked memory section in your linker .prm file > (assuming codewarrior) which will not be banked switch and thus always > reliably there when an interrupt occurs, and you need to put your > interrupt service routine and anything that it might call in that > section. > > If you are using the .prm from the connector app, this section is > called NON_BANKED > so you would precede your ISR and anything it uses with a > > #pragma CODE_SEG NON_BANKED > > and follow it with a > > #pragma CODE_SEG DEFAULTThis is my case.. #pragma CODE_SEG NON_BANKED interrupt void SCI1Interrupt (void) { SCI1_isr_handler(); } #pragma CODE_SEG DEFAULT> Also make sure that you are getting the address of the ISR correctly > loaded into the vector table. In the connector app, vectors.c does > that and would need to reference your ISR.in Vectors.c ------------------------- ... SCI1Interrupt, /* 38 Default (unused) interrupt */ .... I believe SCI1 is supposed to be Interrupt Vector No. 21. But how do I clarify that my specific interrupt is triggered by that? Thank you for your support so far.
Reply by ●June 28, 20072007-06-28
On Jun 28, 10:43 am, ryufr...@hotmail.com wrote:> > Please describe what you mean by crashes. For example, does it jump > > to an arbitrary address outside of the program and thus trigger the > > software trap debugging interrupt? > > > I`m sorry for my ignorance, but how can I check this?How is it that you determine that the program has "crashed"? What exactly do you mean by "crashed" ?> I believe SCI1 is supposed to be Interrupt Vector No. 21. But how do I > clarify that my specific interrupt is triggered by that?- Put a breakpoint in the ISR to see if it is ever reached - Examine memory at location 0xFF80 and you should see the vector table. Check that the address of your handler appears at the right location in it. (You may want to examine the linker map file too, it shows you a lot)
Reply by ●June 28, 20072007-06-28
On Jun 28, 4:54 pm, cs_post...@hotmail.com wrote:> On Jun 28, 10:43 am, ryufr...@hotmail.com wrote: > > > > Please describe what you mean by crashes. For example, does it jump > > > to an arbitrary address outside of the program and thus trigger the > > > software trap debugging interrupt? > > > I`m sorry for my ignorance, but how can I check this? > > How is it that you determine that the program has "crashed"? > What exactly do you mean by "crashed" ?When the board reaches the point to call the SCI1in function to read in data over the RS232 link, any further functions taking place at that time freeze (Ethernet protocols` initialization etc).> > I believe SCI1 is supposed to be Interrupt Vector No. 21. But how do I > > clarify that my specific interrupt is triggered by that? > > - Put a breakpoint in the ISR to see if it is ever reachedI tried to set various checkpoint to see where the code reaches... and the ISR doesn`t appear to be called> - Examine memory at location 0xFF80 and you should see the vector > table. Check that the address of your handler appears at the right > location in it. (You may want to examine the linker map file too, it > shows you a lot)In the linker map file i found that my interrupt is on the wrong address i think. Name Addr hSize dSize Ref Section SCI1Interrupt 506D 5 5 1 NON_BANKED>From the MC9S12NE64`s datasheets:Vector No Vector Address Name Source 21 $FFD4, $FFD5 Vsci1 SCI1 This is getting more confusing to me minute by minute :/ Thanks again for your help
Reply by ●June 28, 20072007-06-28
On Jun 28, 11:49 am, ryufr...@hotmail.com wrote:> On Jun 28, 4:54 pm, cs_post...@hotmail.com wrote: > > > On Jun 28, 10:43 am, ryufr...@hotmail.com wrote:> > What exactly do you mean by "crashed" ? > > When the board reaches the point to call the SCI1in function to read > in data over the RS232 link, any further functions taking place at > that time freeze (Ethernet protocols` initialization etc).But what is the processor doing? Frozen? Executing from unprogrammed memory? Or stuck in a loop within your program? If it's stuck in a loop, determine which instructions are actually being executed - I think you posted something before that included a function call within the loop.> > - Examine memory at location 0xFF80 and you should see the vector > > table. Check that the address of your handler appears at the right > > location in it. (You may want to examine the linker map file too, it > > shows you a lot) > > In the linker map file i found that my interrupt is on the wrong > address i think. > > Name Addr hSize dSize Ref Section > SCI1Interrupt 506D 5 5 1 NON_BANKED > > >From the MC9S12NE64`s datasheets: > > Vector No Vector Address Name Source > 21 $FFD4, $FFD5 Vsci1 SCI1The 16 bit value at $FFD4 should contain the address of your ISR, which according to the map file would be $506D. Use the memory window in the debugger to examine it. But it's probably okay. You should also make sure that interrupts are enable (assembler instructions SEI and CLI or whatever, can't remember which is which), that the SCI RX interrupt bit is enabled (use the debugger to examine the memory mapped SCI register), and that the port module is leaving the relevant IO pins for SCI and not making GPIO's out of them. Another thing you could try: make your program periodically call the ISR, so that in effect you are polling the serial port (and leave out the time consuming UDP calls). Does it work then?
Reply by ●June 30, 20072007-06-30
Hi. Sorry for the late reply. I took some time to play around with my code and discover various flaws thanks to your help. My biggest mistake was that my ISR function was in the wrong place in vectors.c. Using the file MC9S12NE64.h and the board`s manual i figured out the correct position. Now everything in the program appears to function as it should... apart from the SCI1 interrupt that skips several readings. For example I'm inputting to SCI1 "1234567890" and it reads "1470". The SCI1 status register 1 returns OverRun bit as 1. (I'm checking the value of SCI1DRL right after the ISR occurs). So this means that for some reason it misses those characters. Tomorrow I will sit down and struggle to find what can be wrong with it. If you have any more suggestions they are more than welcome :) Thank you for all your help so far.
Reply by ●June 30, 20072007-06-30
Yeyyy!!! Who said that "Information is power"? My problem was caused by the various DEBUGOUT functions I set in my code in order to monitor its progress in hyperterminal and locate where it stops etc. As long as it works fine, there is no need anymore to know the details within ;) They were causing delays to everything else! I never tought of that, and I didn`t expect the board to be so sensitive with such delays :/ Anyway, now the initial part is ok. I can receive some basic information over the serial port, and trying to make the whole thing work together (UDP sending and interrupted SCI1). When this works more or less my objective will be met. So far I can notice that various other interrupts take place while SCI1 interrupt is active, coming from broadcast packets on the Ethernet port. I haven`t done much testing yet of the whole program, but in case this causes me any problems, is there a way to increase the SCI1 interrupt`s priority over the others? Thanks
