A discussion group for the PICMicro microcontroller. Also called the Microchip PIC, this list is dedicated to the use and abuse of this fine, simple, microcontroller. Close to topic posts are welcome, ie. general electronics.
|
*Pounding headache* Greetings everyone, So heres my stumper of a question... I am using multiple banks of memory (16 bit pointer) in a Pic16f877. I am recieving data serially via interrupt (rda) and heres what i am finding: When a buffer fills up in one bank, the streaming data does not flow over into the next bank correctly (I suspect that the interrupt may have had something happen to it, ie disabled, when transfering the pointer from one bank/page to another). Lets say i have just two partitions of data, one in bank 2, the other in bank 3. Heres how my data would look: Bank 2 would have all the memory fill in correctly and appear exactly as it should. Bank 3 would miss recording data for a while, and then it would eventually start recording data just as bank 2 did. Eg, This is sent: "ABCDEFGHIJKLMNOPQRSTUVWXYZ" Buffer_A is present in bank 2, size 10 Buffer_B is present in bank 3, size 30 Buffer_A contents: "ABCDEFGHIJ" Buffer_B contents: "QTUVWXYZ" Also notice that there is some missing stuff between Q and T... this also happens for some messed up reason. As far as i can tell, my buffer should and has no reason not to work, my rda interrupt also has no reason not to operate.... I thought i might be running into a time-to-service problem so I went from 11059200 to 20000000 Hz... no difference!? If you know the secret code to tell the pic, or have experienced wierd voo-doo things like this... heres my real code below, and here is the symbol map: buffer2 02A-04A : Bank 0 overbuf 0A0-0DF : Bank 1 buffer 110-16F : Bank 3 #int_RDA // Recieved data available void TCP_RX_isr() { if( (RCREG==Xoff) || (RCREG==Xon)) { if( RCREG==Xoff) // Stop sending, Xoff was recieved { bit_clear( TCP_flags, Send_ok); // No more sending T1CON.TMR1ON=0; set_timer1(0); fprintf(DBUG, "\r\n\ GOT Xoff\r\n"); } if( RCREG==Xon) { bit_set( TCP_flags, Send_ok); // Sending now allowed T1CON.TMR1on=0; set_timer1(0); fprintf(DBUG, "\r\n\ GOT Xon\r\n"); TCP_TX_isr(); // call to continue } } else put_in_buffer(); } void Put_in_buffer() { if( BufPtr<Buffer_size) { Buffer[BufPtr]=RCREG; } else if(( BufPtr >= (Buffer_size)) && ( BufPtr < 128)) { Buffer2[BufPtr-Buffer_size]=RCREG; } if(BufPtr==127) { bit_set(TCP_flags, Non_data); TXREG=Xoff; PIE1.TXIE=1; TXSTA.TXEN=1; bit_set(TCP_flags, Sent_Xoff); bit_set( Buffer_flags, Buffull); // Buffer is now full } if( BufPtr>=(128)) { bit_set( Buffer_flags, Overflow ); OverBuf[BufPtr-128]=RCREG; } BufPtr++; } |
|
|
|
At 05:05 PM 10/01/05, sirtiffguy wrote: >So heres my stumper of a question... I am using multiple banks of >memory (16 bit pointer) in a Pic16f877. I am recieving data >serially via interrupt (rda) and heres what i am finding: When a >buffer fills up in one bank, the streaming data does not flow over >into the next bank correctly (I suspect that the interrupt may have I've deleted your original post, others can refer to the archives. I have done something similar with an F876 and F628. I had no problems with buffer overruns despite receiving data from a Nokia phone at 115,200 baud. However, I didn't split the primary receive buffer. My secondary buffer was split. I used a state machine concept. Therefore the main code was constantly raking around transferring data from the primary buffer to the larger banked secondary buffer and simultaneously processing the secondary buffer on the fly. I would suggest that you don't make calls to subroutines from within your interrupt service routine. I'll copy snippets of my code below complete with my original comments, some of which may not be relevant to your application. BTW, do you really need to bother with the XON/XOFF handshaking code you've implemented? Good luck figuring this stuff out, some of my code macros and bit variable macros are not shown here. The important point to note is that the isr itself is minimal, it has more comments than code. #define FIFOSIZE 0x30 // experiment with this value volatile BYTE fifo[FIFOSIZE]; volatile BYTE fifoin; volatile BYTE fifoout; BYTE frametype; BYTE framesize; BYTE framenum; BYTE frameseq; BYTE frameptr; BYTE framectr; BYTE framestate; // machine state getframe() // int mode = 0; #define FRAME0SIZE 14 // experiment with these values #define FRAME1SIZE 31 #define FRAME2SIZE 32 #define FRAME3SIZE 32 #define FRAME0MAX FRAME0SIZE #define FRAME1MAX FRAME1SIZE + FRAME0MAX #define FRAME2MAX FRAME2SIZE + FRAME1MAX #define FRAMEMAX FRAME3SIZE + FRAME2MAX BYTE framedat0[FRAME0SIZE]; bank1 BYTE framedat1[FRAME1SIZE]; bank1 BYTE framedat2[FRAME2SIZE]; bank2 BYTE framedat3[FRAME3SIZE]; void interrupt isr(void) { // SCI (Serial Communications Receiver) interrupt while(RCIF) { // set when SCI receive register is loaded if (OERR) { CREN = 0; // clear the overrun error CREN = 1; } // we don't need to check framing error because it will be // cleared, if set, when RCREG is read fifo[fifoin++] = RCREG; if (fifoin == FIFOSIZE) fifoin = 0; if (fifoin != fifoout) b_fifoloaded = 1; // if the buffer catches up to itself, too bad, we will // eventually get a checksum or other error and do a reset #endif } // somewhere within mainloop BYTE c; while(b_fifoloaded) { di(); c = fifo[fifoout++]; if (fifoout == FIFOSIZE) fifoout = 0; if (fifoin == fifoout) b_fifoloaded = 0; ei(); switch(whatever) { case 0xFF // cases as required case 0 case 1 case 6: // N61MODE_DATA: collect frame data // check for buffer oveflow if ((framectr && frameptr >= FRAMEMAX) || (!framectr && b_frameodd && frameptr >= FRAMEMAX + 5) || (!framectr && !b_frameodd && frameptr >= FRAMEMAX + 4)) b_frameignore = 1; // if appropriate, store byte in ganged buffer if (framectr && !b_frameignore) { if (frameptr >= FRAME2MAX) framedat3[frameptr - FRAME2MAX] = c; else if (frameptr >= FRAME1MAX) framedat2[frameptr - FRAME1MAX] = c; else if (frameptr >= FRAME0MAX) framedat1[frameptr - FRAME0MAX] = c; else framedat0[frameptr] = c; } frameptr++; Case 22 ..etc // all the above is within the b_fifoloaded loop. |