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

Data sent slowly with circular buffer

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



Joined: 22 Jan 2018
Posts: 34
Location: North of France

View user's profile Send private message

Data sent slowly with circular buffer
PostPosted: Thu Sep 20, 2018 12:12 am     Reply with quote

Hello to all

I encounter a strange problem. When i use the circular transmit buffer, i don't understand why sometimes my data string are sent on the UART very slowly.
Code:

void bputc2(char c)
{                             
   short restart2;
   int ni2;                   

   restart2=t_next_in2==t_next_out2;
   t_buffer2[t_next_in2]=c;
   ni2=(t_next_in2+1) % T_BUFFER2_SIZE;   
   while(ni2==t_next_out2);
   {t_next_in2=ni2
     } 
 
   if(restart2)
    { enable_interrupts(int_tbe2);
     }
}


#INT_TBE2
void  TBE2_isr(void)
{
Flag_Int_TBE2=1;             

Stop_WS2812_Stream=1;   
 
      if(t_next_in2!=t_next_out2) //   
   {
      putc(t_buffer[t_next_out]);
      fputc(t_buffer2[t_next_out2],PORT2);
      t_next_out2=(t_next_out2+1) % BUFFER2_SIZE;   
      if(t_next_in2==t_next_out2)
      {
      disable_interrupts(int_tbe2);
      Flag_Int_TBE2=0;                                               
      } 




//Main.c
//Code executed at startup, not in the While(1)
delay_ms(1000);
printf(bputc2,"+++");
delay_ms(200);
printf(bputc2,"R1=9F7F7F\r");
delay_ms(200);
printf(bputc2,"R2=9F7F7F\r");
delay_ms(200);
printf(bputc2,"R3=9F7F7F\r");


when i replace printf(bputc2,"R3=9F7F7F\r");
with fprintf(PORT2,"R3=9F7F7F\r");

data are sent immediatly with no delay!
FYI, i need small delay between each transmission.

Have a great day!

Manu
_________________
CCS + ICD3 + PIC18F46K80
Ttelmah



Joined: 11 Mar 2010
Posts: 19520

View user's profile Send private message

PostPosted: Thu Sep 20, 2018 1:23 am     Reply with quote

There are several 'extreme oddities' in your posted code.....

First:

restart2=t_next_in2==t_next_out2;

This will make 'restart2', TRUE, if t_next_in2 is equal to t_next_out2, so potentially if the buffer is empty.

This then is used at the end of the routine, to enable interrupts. Possibly fair enough.

However if the buffer overflows:
while(ni2==t_next_out2);
{t_next_in2=ni2
}

Nothing is done. Look carefully. All that is executed is the ';' not the bracketed reset operation that you probably want to execute....

Wrong.... :(

So this means the first line could return TRUE if the buffer overflows as well, since the buffer is not being reset in this condition. Ugh.

Then the actual ISR only sends data if there is something in the buffer (fair enough), but if there is nothing in the buffer the interrupt is left enabled (since the test for buffer being empty is inside the test for it not being empty), so there is potentially a hang with the interrupt being continuously called. Again a major problem... :(

You need a radical re-think of how your buffer handling is being done. Sad
Manu59114



Joined: 22 Jan 2018
Posts: 34
Location: North of France

View user's profile Send private message

PostPosted: Thu Sep 20, 2018 4:00 am     Reply with quote

Thanks Ttelmah

I will re write my code! But i need to understand a part of this code.
Code:

void bputc(char c) {
  #if defined(__PCD__)
   #bit U1TXIF = getenv("BIT:U1TXIF")
  #endif
   short restart;
   int ni;

restart=t_next_in==t_next_out; // At the beguinning, Restart == 1
t_buffer[t_next_in]=c; // send C in the Array at t_next_in
ni=(t_next_in+1) % T_BUFFER_SIZE; // ni ==0
while(ni==t_next_out); // This line is not understand...


Is it not an infinite loop?
Which part of the code will be executed if the condition is True or if the condition is false?
Code:

   t_next_in=ni;
   if(restart)
     #if defined(__PCD__)
      U1TXIF = 1;
     #else
      enable_interrupts(int_tbe);
     #endif
}

Many Thanks to all for help me!

Manu
_________________
CCS + ICD3 + PIC18F46K80
Ttelmah



Joined: 11 Mar 2010
Posts: 19520

View user's profile Send private message

PostPosted: Thu Sep 20, 2018 4:13 am     Reply with quote

No. Remember that 't_next_out' is updated in the interrupt.

So this will stop, if the buffer would be full after the data is added, until the interrupt sends one character.

It sounds as if you are using someone else's code, with some typing errors to make it not work correctly. Why not use ex_stisr.c which is in the compiler examples. This is correct.
Ttelmah



Joined: 11 Mar 2010
Posts: 19520

View user's profile Send private message

PostPosted: Thu Sep 20, 2018 4:38 am     Reply with quote

Just thinking. There is another issue that applies to the code, that you may not realise. The buffer size in this code (and in the CCS example), _must_ be a 'binary multiple'. So 8, 16, 32, 64 bytes. If you use a size like (say) 20 bytes, it'll result in extreme inefficiency in the code as posted. Very important to understand.
jeremiah



Joined: 20 Jul 2010
Posts: 1349

View user's profile Send private message

PostPosted: Fri Sep 28, 2018 12:50 pm     Reply with quote

Just to explain the why a binary multiple (power of 2) size is faster:

The code uses the modulus operator, "%" to bound the buffer. This operation normally takes a division operation, which can be extremely slow. Even chips with hardware divide typically take 18 instruction cycles for atomic sized divisions. However, taking the modulus of a value using a binary multiple (power of 2) number, x % 256 for example, can be done without division using just an AND operation, which is normally just a single instruction cycle for atomic sized operations.

To show with the above example:

(x % 256) is equivalent to (x AND 255)

but

(x % 255) cannot be converted to an AND and must use division.
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