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

txISR PCD

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



Joined: 02 Feb 2010
Posts: 368

View user's profile Send private message

txISR PCD
PostPosted: Wed Jan 29, 2025 8:53 am     Reply with quote

Hello,

I'm trying to run "ex_stisr_pcd" but not success.

Code:



#include <33EP512MU810.h>
#device ICSP=1
#use delay(crystal=8MHz)

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES CKSFSM                   //Clock Switching is enabled, fail Safe clock monitor is enabled
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOJTAG                   //JTAG disabled


#define PER_EN PIN_D5

#define PER_ON() output_high(PER_EN)
#define PER_OFF() output_low(PER_EN)

/* HW UART1 */
#pin_select U1RX=PIN_E1         // Rx Com1.
#pin_select U1TX=PIN_E0         // Tx Com1.   

#use rs232(UART1,baud=9600)


#define T_BUFFER_SIZE 64
byte t_buffer[T_BUFFER_SIZE];
byte t_next_in = 0;
byte t_next_out = 0;


#int_tbe
void serial_isr() {

   if(t_next_in!=t_next_out)
   {
      putc(t_buffer[t_next_out]);
      t_next_out=(t_next_out+1) % T_BUFFER_SIZE;
   }
   disable_interrupts(INT_TBE);
}

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

   restart=t_next_in==t_next_out;
   t_buffer[t_next_in]=c;
   ni=(t_next_in+1) % T_BUFFER_SIZE;
   while(ni==t_next_out);
   t_next_in=ni;
   if(restart)
      U1TXIF = 1;
}

void main() {
     
   delay_ms(100);
   
   PER_ON();
   
   enable_interrupts(INT_TBE);
   enable_interrupts(GLOBAL);

   printf(bputc,"\r\n\Running...\r\n");

   do {
      delay_ms(2000);
      printf(bputc,"This is buffered data\r\n");
   } while (TRUE);
}


dsPic doesn't transmit anything!

CCS c v.5.115
Best Regards,
temtronic



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

View user's profile Send private message

PostPosted: Wed Jan 29, 2025 9:09 am     Reply with quote

Hmmm..
does it transmit if you just do a normal 'print to comport' ?
do those PPS pins connect to UART or I/O pins ?
does the PC terminal program work ? loopback checked OK ?
any chance TX-->TXD, RX-->RXD ?

Always wondered if anyone did a test to see IF using a TXISR is faster and by how much ?
kmp84



Joined: 02 Feb 2010
Posts: 368

View user's profile Send private message

PostPosted: Wed Jan 29, 2025 9:45 am     Reply with quote

temtronic wrote:
Hmmm..
does it transmit if you just do a normal 'print to comport' ?
do those PPS pins connect to UART or I/O pins ?
does the PC terminal program work ? loopback checked OK ?
any chance TX-->TXD, RX-->RXD ?

Always wondered if anyone did a test to see IF using a TXISR is faster and by how much ?


Normal printf function working, no problem. Just ISR doesn't fire!

Best Regards,
Ttelmah



Joined: 11 Mar 2010
Posts: 19649

View user's profile Send private message

PostPosted: Wed Jan 29, 2025 10:49 am     Reply with quote

Aargh.....

Does the example really have this?.

disable_interrupts(INT_TBE);

Never going to work. It'll send _one_ character.

The point is you want to only disable the interrupt if the buffer is empty.

So:
Code:

#int_tbe
void serial_isr(void)
{
   if(t_next_in!=t_next_out)
   {
      putc(t_buffer[t_next_out]);
      t_next_out=(t_next_out+1) % T_BUFFER_SIZE;
   }
   else
      disable_interrupts(INT_TBE);
}


I did point this out to CCS about three years ago.

My own buffers, which are a bit more 'universal', are:
Code:

//Buffer tests and handling
unsigned int8 btempU1RX,btempU1TX;
#define SIBUFF (64) //buffer sizes
typedef struct {
   unsigned int8 in;
   unsigned int8 out;
   unsigned int8 buff[SIBUFF];
} buffer;

buffer U1RX,U1TX; //declare these for every buffer you want.

#define incin(buff) ((buff.in==(SIBUFF-1))?0:buff.in+1)
#define incout(buff) ((buff.out==(SIBUFF-1))?0:buff.out+1)
#define isempty(buff) (buff.in==buff.out)
#define hasdata(buff) (buff.in!=buff.out)
#define isfull(buff) ((incin(buff)==buff.out)
#define tobuff(bname,c) { bname.buff[bname.in]=c;\
   bname.in=incin(bname);\
   if (bname.in==bname.out) bname.out=incout(bname);\
   }
#define frombuff(bname) (btemp##bname=bname.buff[bname.out],\
   bname.out=incout(bname), \
   btemp##bname)
#define clrbuff(buff) buff.in=buff.out=0

#define bkbhit(BUFF) hasdata(BUFF)
#define bgetc(BUFF) frombuff(BUFF);

void U1putc(int chr)
{
   clear_interrupt(INT_TBE);
   tobuff(U1TX,chr);
   enable_interrupts(INT_TBE);
}

#INT_RDA
void uart1rx(void)
{
   unsigned int8 temp;
   while (kbhit(U1STREAM)) {
      temp=getc();
      tobuff(U1RX, temp);
   };
}

#INT_TBE
void uart1tx(void)
{
   unsigned int8 temp;
   temp=bgetc(U1TX);
   fputc(temp,U1STREAM);
   if (isempty(U1TX))
      disable_interrupts(INT_TBE);
}


These allow you to just add more buffers for different serials by adding 'buffer' declarations for them, and you handle them inside the interrupts
rather like streams, just using the buffer names to say when buffer you
are talking to.

I do also though always use ERROR interrupts for the serials. The 'ERRORS'
declaration on PIC24 and up does not work. So I use an error interrupt to
handle the errors:
Code:

///UART ERROR HANDLING
#word U1STA=getenv("SFR:U1STA")
#word U2STA=getenv("SFR:U2STA")
#word U3STA=getenv("SFR:U3STA")
#word U4STA=getenv("SFR:U4STA")
#BIT UTXEN1=U1STA.10
#BIT UTXEN2=U2STA.10
#BIT UTXEN3=U3STA.10
#BIT UTXEN4=U4STA.10
#word U1MODE=getenv("SFR:U1MODE")
#word U2MODE=getenv("SFR:U2MODE")
#word U3MODE=getenv("SFR:U3MODE")
#word U4MODE=getenv("SFR:U4MODE")
#bit UARTEN1=U1MODE.15
#bit UARTEN2=U2MODE.15
#bit UARTEN3=U3MODE.15
#bit UARTEN4=U4MODE.15
#bit OERR1=U1STA.1
#bit FERR1=U1STA.2
#bit PERR1=U1STA.3
#bit OERR2=U2STA.1
#bit FERR2=U2STA.2
#bit PERR2=U2STA.3
#bit OERR3=U3STA.1
#bit FERR3=U3STA.2
#bit PERR3=U3STA.3
#bit OERR4=U4STA.1
#bit FERR4=U4STA.2
#bit PERR4=U4STA.3
#word U1RXREG=getenv("SFR:U1RXREG")
#word U2RXREG=getenv("SFR:U2RXREG")
#word U3RXREG=getenv("SFR:U3RXREG")
#word U4RXREG=getenv("SFR:U4RXREG")

#define CAT(x,y) x##y
#define CAT3(x,y,z) x##y##z

#define HASH_LIT #
#define HASH() HASH_LIT

#define EFUNCTION(x) void CAT(errorint, x) (void) { \
static int16 eword; \
if (CAT(OERR,x)) { CAT(OERR,x) = 0; return; } \
if (CAT(PERR,x)) { eword=CAT3(U,x,RXREG); } \
if (CAT(FERR,x)) { eword=CAT3(U,x,RXREG); } \
}
//Builds an interrupt handler to cope with UART errors.
//For parity and framing, throw the byte with the error.

#INT_UART1E LEVEL=5
EFUNCTION(1)

#INT_UART2E LEVEL=5
EFUNCTION(2)

#INT_UART3E LEVEL=5
EFUNCTION(3)

#INT_UART4E LEVEL=5
EFUNCTION(4)
//REM these out for UARTs the chip does not have



These then require the corresponding error interrupts are enabled.
These throw a byte when necessary to clear an error, and clear the
interrupt flags when this is needed.

With these buffers and error handling, I have had zero UART problems
on chips running all four UARTs at really high rates.
dyeatman



Joined: 06 Sep 2003
Posts: 1946
Location: Norman, OK

View user's profile Send private message

PostPosted: Wed Jan 29, 2025 1:01 pm     Reply with quote

Yep, the latest version compiler is still missing the else in the example...
_________________
Google and Forum Search are some of your best tools!!!!
kmp84



Joined: 02 Feb 2010
Posts: 368

View user's profile Send private message

PostPosted: Thu Jan 30, 2025 7:00 am     Reply with quote

Hi,

The problem are not only missing 'else' statement. With adding else statement still doesn't work.
Ttelmah



Joined: 11 Mar 2010
Posts: 19649

View user's profile Send private message

PostPosted: Thu Jan 30, 2025 12:25 pm     Reply with quote

OK. Look at Jay's questions. Have you verified the chip will transmit without
using the interrupt?.
kmp84



Joined: 02 Feb 2010
Posts: 368

View user's profile Send private message

PostPosted: Fri Jan 31, 2025 4:57 am     Reply with quote

Hi mr.Tt,

I said yes at second post. Smile

Best Regards,
Ttelmah



Joined: 11 Mar 2010
Posts: 19649

View user's profile Send private message

PostPosted: Fri Jan 31, 2025 10:18 am     Reply with quote

OK. Lets try some routines based on the way do it. It is very worrying
that their routines have faults I pointed out a long time ago.
Looking at it, the problem is that they enable the transmit interrupt at the
start. This means the transmit routine will be immediately called and
this will then disable the interrupts.

Code:

#include <33EP512MU810.h>
#device ICSP=1
#use delay(crystal=8MHz)

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES CKSFSM                   //Clock Switching is enabled, fail Safe clock monitor is enabled
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOJTAG                   //JTAG disabled


#define PER_EN PIN_D5

#define PER_ON() output_high(PER_EN)
#define PER_OFF() output_low(PER_EN)

/* HW UART1 */
#pin_select U1RX=PIN_E1         // Rx Com1.
#pin_select U1TX=PIN_E0         // Tx Com1.   

#use rs232(UART1,baud=9600)


#define T_BUFFER_SIZE 64
byte t_buffer[T_BUFFER_SIZE];
byte t_next_in = 0;
byte t_next_out = 0;


#int_tbe
void serial_isr()
{
   putc(t_buffer[t_next_out]);
   t_next_out++;
   if (t_next_out>=T_BUFFER_SIZE)
      t_next_out=0;
   if (t_next_out==t_next_in)
      disable_interrupts(INT_TBE);
}

//This puts a character to send to the TX buffer.
void bputc(uint16_t chr)
{
   //interrupt driven TX
   short rest; //flag to restart TX
   disable_interrupts(INT_TBE);
   rest=(t_next_in==t_next_out); //if buffer was empty
   tbuff[t_next_in++]=chr;
   if (t_next_in>=T_BUFFER_SIZE)
      t_next_in=0;
   if(rest)
      U1TXIF = 1;  //force interrupt to trigger
   enable_interrupts(INT_TBE); ??this is where the interrupt gets enabled.
   while(t_next_in==t_next_out) //This is buffer full
      delay_cycles(4);//wait if buffer full for a character to send.
}

void main() {
     
   delay_ms(100);
   
   PER_ON();
   //do not enable the TX interrupt here.
   enable_interrupts(GLOBAL);

   printf(bputc,"\r\n\Running...\r\n");

   do {
      delay_ms(2000);
      printf(bputc,"This is buffered data\r\n");
   } while (TRUE);
}


This should work. Sorry I did not spot their stupidity with the interrupt
enable before. It was so long ago, that I forgot how bad this was.
Mine also handles using non binary buffer sizes, and will stop and
wait if the buffer gets full.
temtronic



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

View user's profile Send private message

PostPosted: Fri Jan 31, 2025 10:40 am     Reply with quote

You're forgiven.....
One day you head will explode with all the tidBITS of PIC info inside !!
That will be a very,very sad day !!
kmp84



Joined: 02 Feb 2010
Posts: 368

View user's profile Send private message

PostPosted: Fri Jan 31, 2025 11:17 am     Reply with quote

Hi mr.'Tt',
Yes, now example working!
There is many identical problems like this and 'sd card' example also. They present from the beginning of the ccs compiler and still not corrected! Smile

But this will not be CCS if not present! Smile

Working Example Code:
Code:


#include <33EP512MU810.h>
#device ICSP=1
#use delay(crystal=8MHz)

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES CKSFSM                   //Clock Switching is enabled, fail Safe clock monitor is enabled
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOJTAG                   //JTAG disabled


#define PER_EN PIN_D5

#define PER_ON() output_high(PER_EN)
#define PER_OFF() output_low(PER_EN)

/* HW UART1 */
#pin_select U1RX=PIN_E1         // Rx Com1.
#pin_select U1TX=PIN_E0         // Tx Com1.   

#use rs232(UART1,baud=9600)


#define T_BUFFER_SIZE 64
byte t_buffer[T_BUFFER_SIZE];
byte t_next_in = 0;
byte t_next_out = 0;


#int_tbe
void serial_isr()
{
   putc(t_buffer[t_next_out]);
   t_next_out++;
   if (t_next_out>=T_BUFFER_SIZE)
      t_next_out=0;
   if (t_next_out==t_next_in)
      disable_interrupts(INT_TBE);
}

//This puts a character to send to the TX buffer.
void bputc(unsigned int16 chr)
{
   #bit U1TXIF = getenv("BIT:U1TXIF")
   //interrupt driven TX
   short rest; //flag to restart TX
   disable_interrupts(INT_TBE);
   rest=(t_next_in==t_next_out); //if buffer was empty
   t_buffer[t_next_in++]=chr;
   if (t_next_in>=T_BUFFER_SIZE)
      t_next_in=0;
   if(rest)
      U1TXIF = 1;  //force interrupt to trigger
   enable_interrupts(INT_TBE); //??this is where the interrupt gets enabled.
   while(t_next_in==t_next_out) //This is buffer full
      delay_cycles(4);//wait if buffer full for a character to send.
}

void main() {
     
   delay_ms(100);
   
   PER_ON();
   //do not enable the TX interrupt here.
   enable_interrupts(GLOBAL);

   printf(bputc,"\r\n\Running...\r\n");

   do {
      delay_ms(2000);
      printf(bputc,"This is buffered data\r\n");
   } while (TRUE);
}



Best Regards!
Ttelmah



Joined: 11 Mar 2010
Posts: 19649

View user's profile Send private message

PostPosted: Fri Jan 31, 2025 12:50 pm     Reply with quote

I have pointed it out to CCS again. Touch wood, this time they update their
examples.
Think I'lll add this thread to the 'known faults' page.
I think I'll stick my versions in the code library.

The SD card code does actually work. Problem is, only with old sub 2GB
SD;s formatted FAT16, and without an MBR. They have never done properly
updated examples that suit modern cards. The same really on the TCP/IP
stack as well. Ten years ago, their examples were good. Now they are
becoming annoying at times.

The code library is becoming more and more important as fixes like this
get added.
Ttelmah



Joined: 11 Mar 2010
Posts: 19649

View user's profile Send private message

PostPosted: Sat Feb 01, 2025 12:16 pm     Reply with quote

CCS have replied that the IsR example will be fixed in the next release.
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