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

[SOLVED] Uart Lagging 4 Characters PIC24FJ64GA202-I/SP RS232

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
JamesW



Joined: 23 Apr 2007
Posts: 91
Location: Rochester, England

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

[SOLVED] Uart Lagging 4 Characters PIC24FJ64GA202-I/SP RS232
PostPosted: Wed Mar 08, 2017 4:51 am     Reply with quote

Hi Folks,

I am seeing something really strange on a new project where I am using PIC24FJ64GA202-I/SP.

I am getting a receive interrupt on every character, however the character that is retrieved from uart is lagging 4 characters from what is entered.

For example if I send 12345 from power up, the data I receive on my VT100 terminal is (code below, the NI and NO are positions of the head and tail of the buffer in the isr):

NI:0 NO:0
NI:0 NO:0
NI:0 NO:0
[00]0 NO:0
[00]1 NO:1
ΓΏ[ff] NO:2
1[31] NO:3
NI:4 NO:4
NI:4 NO:4
NI:4 NO:4

So on the first character when I press '1', the ISR obtains a 0x00 from the uart, when I press '2' I also get 0x00, when I press '3' I get 0xFF, when I press '4' I get the '1' and so forth. Every incoming character from that point, returns the character that entered the uart 3 characters previously.

I know this PIC has a 4 byte FIFO, and it almost seems like that this is being used, but not handled by the normal CCS RS232 code.

Can anyone point me in the right direction of what I am missing please?

I have defined the uart as normal with :

Code:

/* UART DEFINITIONS - DEBUG */
#pin_select U2TX=PIN_B1
#pin_select U2RX=PIN_B14
#use rs232(UART2, baud=38400, errors, stream=DEBUG_PORT)


My ISR is pretty much the CCS example of how to handle serial interrupts (which I've used for years and years without a problem).

Code:

 void DRV_VT100_UartInt()
 {
   UI_8 t;
   
   DEBUG_buffer[DEBUG_next_in]=fgetc(DEBUG_PORT);
   t = DEBUG_next_in;

   if (++DEBUG_next_in == DEBUG_BUFFER_SIZE)
   {
       DEBUG_next_in = 0;
   }

   if(DEBUG_next_in==DEBUG_next_out)
   {
     /* BUFFER FULL */
     DEBUG_next_in=t;
   }
 }


And my main loop has been cut down to the absolute minimum, just to try and resolve this

Code:

   while (TRUE)
   {
       LoopCount++;
      if (LoopCount >= 70000)
      {
         fprintf(DEBUG_PORT, "\r NI:%u NO:%u", DEBUG_next_in, DEBUG_next_out);
         LoopCount= 0;
     
      }
     
      if (_DEBUG_kbhit)
      {
         /* READ IN THE SENT BYTE AND SAVE IT IN THE BUFFER */
         NewChar = Debug_bgetc();
         
         ConsoleGotoXY(1,25);
         fprintf(DEBUG_PORT,"%c[%02x]",NewChar,NewChar);
      }
   }



Any suggestions would be gratefully received.

Thanks

James


Last edited by JamesW on Wed Mar 08, 2017 9:38 am; edited 1 time in total
temtronic



Joined: 01 Jul 2010
Posts: 9226
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Wed Mar 08, 2017 6:09 am     Reply with quote

Sure sounds like a 'buffer' problem but I don't use that PIC..sigh too mny PICs ,too little time.
What REALLY impresses me is that you've got a working VT100 terminal !! I used to fix them in my 'day job',40 YEARS ago...like 2/3rds of my lifetime.
Sad thing is I got rid of all my DEC stuff 2 decades ago....kinda wish I'd kept the ASR33 though.
Jay
JamesW



Joined: 23 Apr 2007
Posts: 91
Location: Rochester, England

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

PostPosted: Wed Mar 08, 2017 6:12 am     Reply with quote

Well - hyperterminal in VT100 mode actually.

It still has its place, and is incredibly useful debugging, displaying, and changing stuff cheaply when you don't have a display.

Cheers

James
Ttelmah



Joined: 11 Mar 2010
Posts: 19515

View user's profile Send private message

PostPosted: Wed Mar 08, 2017 9:11 am     Reply with quote

Add the following to the interrupt handler:
Code:

void DRV_VT100_UartInt(void)
{
   UI_8 t;
   do
   {
      DEBUG_buffer[DEBUG_next_in]=fgetc(DEBUG_PORT);
      t = DEBUG_next_in;

      if (++DEBUG_next_in == DEBUG_BUFFER_SIZE)
      {
         DEBUG_next_in = 0;
      }

      if(DEBUG_next_in==DEBUG_next_out)
      {
          /* BUFFER FULL */
          DEBUG_next_in=t;
      }
   } while (kbhit(DEBUG_PORT));
}


What is happening is that the UART is receiving some zeros as garbage during the boot. So has four zeros in it's hardware buffer, when you start the interrupt. Each time you get an interrupt, since you only retrieve one character, you never catch up at all.
So it interrupts straight away when you enable it, and you then get a zero. A character arrives, triggering the interrupt again, but you then retrieve the 'old' zero that is already there. etc. etc..

On PIC's with larger buffers it is always worth looping if there is more than one character waiting (as shown). The other thing to do is to flush the buffer before enabling the interrupt. So:

Code:

   while (kbhit(DEBUG_PORT))
      dummy=fgetc(DEBUG_PORT);
   clear_interrupts(INT_RDAxxxx); //for this UART
   enable_interrupts(INT_RDAxxxx);


This is worth doing even on standard PIC's, where it is common to find one garbage character on boot.
JamesW



Joined: 23 Apr 2007
Posts: 91
Location: Rochester, England

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

PostPosted: Wed Mar 08, 2017 9:37 am     Reply with quote

Problem solved.

We thought that was what it must be what the problem was, but couldn't see any mention in the help files as to how uarts with FIFO's need to be handled.

So that's how you clear the buffer!

Thanks for that - it had us completely stumped, we were hunting through the datasheet looking for a register setting we could check.

Crate of virtual internet beer heading your way!

James
Ttelmah



Joined: 11 Mar 2010
Posts: 19515

View user's profile Send private message

PostPosted: Wed Mar 08, 2017 11:46 am     Reply with quote

It has been mentioned here before, but not for quite a while. Unfortunately the CCS examples don't really cover this.

Glad you have it sorted. Also more efficient anyway, if something delays the serial ISR being serviced, it'll now grab all characters that are waiting. Smile
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
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