I am having problems generating serial port (RI and TI) interrupts in an application that I have. I have two functions being running with Round Robin disabled. Both functions send signals to each other when the tasks need to switch. I've gone through the threads, and tried to follow the instructions given when other people had similar problems, but none of that is working for me. I am also using Timer 2 for Uart 0, and timer 1 for uart 1. Interrupt for both UARTs are enabled. I can only set the priorities for both interrupts as high. I tried doing this but it didn't seem to help. Any ideas, thoughts or suggestions?
Take a look to the example C:\Keil\c51\RtxTiny2\Examples\Traffic. In the SERIAL.C module there is an implementation of an interrupt driver serial interface that uses RTX Tiny as scheduler. Reinhard
I am using that file, and I'm still having problems with it.
You should not use identical function (putchar or printf) and identical variables and buffers of exchange for different tasks, It is necessary to use different functions putchar (puchar_to_uart_0, puchar_to_uart_1) for different UARTS. I modified SERIAL.C from example Traffic for Silabs C8051F12x with two UARTS:
/******************************************************************************/ /* */ /* SERIAL.C: Interrupt Controlled Serial Interface for RTX-51 tiny */ /* */ /******************************************************************************/ /* */ /* Modified for Silabs C8051F12x with two UARTs and SFR paging */ /* */ /* Last changes: 10 November 2005 */ /******************************************************************************/ #include <include.h> #define CTRL_Q 0x11 /* Control+Q character code */ #define CTRL_S 0x13 /* Control+S character code */ #define DEL 0x7F #define BACKSPACE 0x08 #define CR 0x0D #define LF 0x0A #define ESC 0x1B /* ESCAPE character code */ #define OLEN 32 /* size of serial transmission buffer */ data uchar ostart_0; /* transmission buffer start index */ data uchar oend_0; /* transmission buffer end index */ data uchar ostart_1; /* transmission buffer start index */ data uchar oend_1; /* transmission buffer end index */ char idata outbuf_0[OLEN]; /* storage for transmission buffer */ char idata outbuf_1[OLEN]; /* storage for transmission buffer */ data uchar otask_0 = 0xff; /* task number of output task */ data uchar otask_1 = 0xff; /* task number of output task */ #define ILEN 32 /* size of serial receiving buffer */ data uchar istart_0; /* receiving buffer start index */ data uchar iend_0; /* receiving buffer end index */ data uchar istart_1; /* receiving buffer start index */ data uchar iend_1; /* receiving buffer end index */ char idata inbuf_0[ILEN]; /* storage for receiving buffer */ char idata inbuf_1[ILEN]; /* storage for receiving buffer */ data uchar itask_0 = 0xff; /* task number of output task */ data uchar itask_1 = 0xff; /* task number of output task */ bool sendfull_0; /* flag: marks transmit buffer full */ bool sendactive_0; /* flag: marks transmitter active */ bool sendfull_1; /* flag: marks transmit buffer full */ bool sendactive_1; /* flag: marks transmitter active */ bool put_to_uart_0; /* redirector for putchar & printf */ //************************************************************************** // Function prototype //************************************************************************** void putchar_to_uart_0 (char c); // send char to UART_0 void putchar_to_uart_1 (char c); // send char to UART_1 char putchar (char c); // common puchar for printf void getline_0 (uchar *line, uchar n); // get line from UART_0 void getline_1 (uchar *line, uchar n); // get line from UART_0
//************************************************************************** // Send to UART_0 //************************************************************************** void putchar_to_uart_0 (char c) { char SFRPAGE_SAVE = SFRPAGE; // Save Current SFR page SFRPAGE = UART0_PAGE; if (c == '\n') { while (sendfull_0) { // wait for transmission buffer empty otask_0 = os_running_task_id (); /* set output task number */ os_wait (K_SIG, 0, 0); /* RTX-51 call: wait for signal */ otask_0 = 0xff; /* clear output task number */ } if (!sendactive_0) { // if transmitter not active sendactive_0 = 1; // transfer the first character direct SBUF0 = CR; // to SBUF to start transmission } else { // otherwize: outbuf_0[oend_0++ & (OLEN-1)] = CR; // transfer char to transmission buffer if (((oend_0 ^ ostart_0) & (OLEN-1)) == 0) sendfull_0 = 1; } } while (sendfull_0) { // wait for transmission buffer empty otask_0 = os_running_task_id (); /* set output task number */ os_wait (K_SIG, 0, 0); /* RTX-51 call: wait for signal */ otask_0 = 0xff; /* clear output task number */ } if (!sendactive_0) { // if transmitter not active sendactive_0 = 1; // transfer the first character direct SBUF0 = c; // to SBUF to start transmission } else { // otherwize: outbuf_0[oend_0++ & (OLEN-1)] = c; // transfer char to transmission buffer // set flag if buffer is full if (((oend_0 ^ ostart_0) & (OLEN-1)) == 0) sendfull_0 = 1; } SFRPAGE = SFRPAGE_SAVE; // Restore current SFR page } //************************************************************************** // Send to UART_1 //************************************************************************** void putchar_to_uart_1 (char c) { char SFRPAGE_SAVE = SFRPAGE; // Save Current SFR page SFRPAGE = UART1_PAGE; if (c == '\n') { while (sendfull_1) { // wait for transmission buffer empty otask_1 = os_running_task_id (); /* set output task number */ os_wait (K_SIG, 0, 0); /* RTX-51 call: wait for signal */ otask_1 = 0xff; /* clear output task number */ } if (!sendactive_1) { // if transmitter not active sendactive_1 = 1; // transfer the first character direct SBUF1 = CR; // to SBUF to start transmission } else { // otherwize: outbuf_1[oend_1++ & (OLEN-1)] = CR; // transfer char to transmission buffer if (((oend_1 ^ ostart_1) & (OLEN-1)) == 0) sendfull_1 = 1; } } while (sendfull_1) { // wait for transmission buffer empty otask_1 = os_running_task_id (); /* set output task number */ os_wait (K_SIG, 0, 0); /* RTX-51 call: wait for signal */ otask_1 = 0xff; /* clear output task number */ } if (!sendactive_1) { // if transmitter not active sendactive_1 = 1; // transfer the first character direct SBUF1 = c; // to SBUF to start transmission } else { // otherwize: outbuf_1[oend_1++ & (OLEN-1)] = c; // transfer char to transmission buffer // set flag if buffer is full if (((oend_1 ^ ostart_1) & (OLEN-1)) == 0) sendfull_1 = 1; } SFRPAGE = SFRPAGE_SAVE; // Restore current SFR page } /******************************************************************************/ /* putchar: interrupt controlled putchar function */ /******************************************************************************/ char putchar (char c) { if (put_to_uart_0) { putchar_to_uart_0 (c); // Send to UART0 } else { putchar_to_uart_1 (c); // Send to UART1 } return (c); // return character: ANSI requirement }
/******************************************************************************/ /* serial_0: serial receiver / transmitter interrupt */ /******************************************************************************/ void serial_0 (void) interrupt 4 { if (RI0) { // if receiver interrupt RI0 = 0; // clear interrupt request flag inbuf_0[iend_0++ & (ILEN-1)] = SBUF0; // read character if (itask_0 != 0xFF) isr_send_signal (itask_0); } if (TI0) { // if transmitter interrupt TI0 = 0; // clear interrupt request flag if (ostart_0 != oend_0) { // if characters in buffer and SBUF0 = outbuf_0[ostart_0++ & (OLEN-1)]; // transmit character sendfull_0 = 0; // clear 'sendfull' flag // if task waiting: signal ready if (otask_0 != 0xFF) isr_send_signal (otask_0); } else { sendactive_0 = 0; // if all transmitted clear 'sendactive' } } } /******************************************************************************/ /* serial_1: serial receiver / transmitter interrupt */ /******************************************************************************/ void serial_1 (void) interrupt 20 { if (RI1) { // if receiver interrupt RI1 = 0; // clear interrupt request flag inbuf_1[iend_1++ & (ILEN-1)] = SBUF1; // read character if (itask_1 != 0xFF) isr_send_signal (itask_1); } if (TI1) { // if transmitter interrupt TI1 = 0; // clear interrupt request flag if (ostart_1 != oend_1) { // if characters in buffer and SBUF1 = outbuf_1[ostart_1++ & (OLEN-1)]; /* transmit character */ sendfull_1 = 0; // clear 'sendfull' flag // if task waiting: signal ready if (otask_1 != 0xFF) isr_send_signal (otask_1); } else { sendactive_1 = 0; // if all transmitted clear 'sendactive' } } } /***************************/ /* Line Editor from UART_0 */ /***************************/ void getline_0 (uchar *line, uchar n) { uchar cnt = 0; uchar c; do { while (iend_0 == istart_0) { itask_0 = os_running_task_id (); /* set input task number */ os_wait (K_SIG, 0, 0); /* RTX-51 call: wait for signal */ itask_0 = 0xff; /* clear input task number */ } if ((c = inbuf_0[istart_0++ & (ILEN-1)]) == CR) c = LF; // read character *line = c; line++; /* increment line pointer */ cnt++; /* and count */ } while (cnt < n - 1 && c != LF); /* check limit and line feed */ *line = 0; } /***************************/ /* Line Editor from UART_1 */ /***************************/ void getline_1 (uchar *line, uchar n) { uchar cnt = 0; uchar c; do { while (iend_1 == istart_1) { itask_1 = os_running_task_id (); /* set input task number */ os_wait (K_SIG, 0, 0); /* RTX-51 call: wait for signal */ itask_1 = 0xff; /* clear input task number */ } if ((c = inbuf_1[istart_1++ & (ILEN-1)]) == CR) c = LF; // read character *line = c; line++; /* increment line pointer */ cnt++; /* and count */ } while (cnt < n - 1 && c != LF); /* check limit and line feed */ *line = 0; }
I've tried the suggestions. I am using pretty much the same code you put up. My problem is that it appears that my interrupts are not working. The TI_0 and RI_0 interrupts are not interrupting the OS. Furthermore, when I look at the RTX tiny task list, once the task 0 (init) task finishes running and exits, I notice that the system timer doesn't count down anymore, but I know that Timer 0 is still running. Its as if all interrupts are disabled, but when you look at the interrupt peripheral tool, EA is enabled. My interrupts are not working. My Conf_Tny file is almost identical to the file from Traffic. Any ideas? Thanks
Try C:\Keil\c51\RtxTiny2\Examples\Traffic Try to test Traffic in initial variant - without changes. Probably it is necessary to renominate pin for led. This example excellently works. If it not works then you have troubles with hardware.
RTX51Tiny should be using Timer1, not your UART function. Are you attempting to run two UARTS? If so, look again at the 'Traffic' example running a single UART with Xmit and Receive and RTX51Tiny. Get the example running and then just duplicate the serail functions for the second UART. If you are attempting to run two UARTs, use timer2 for both UARTs unless you are attempting to run at two different baud rates.
No. RTX51-Tiny uses Timer0 only - Timer1 is free. Timer1 can be used only in RTX51-Full.
RTX tiny uses timer 0. Yes I am running at two different speeds. This is why I'm using Timer 1 for UART 1 and Timer 2 for UART 0. The problem is that the microcontroller is not interrupting. It appears as if the interrupt priorities are screwed up, but I'm not exactly sure where and how they get modified or how to fix it.
Maybe the existing dead-lock posibility( or function) in rtx-tiny serial rutine in trafic example does your problems. Program hangs when 1'st char is arrived (empty inbuf) and ISR processed this char after the
while(iend == istart)
Your right of course. Timer 0 is the correct timer. I don't know what I was thinking at the time. I apologize for clouding the issue. Bradford
All the interrupts enabled have a priority of 0. I know that can't be right. Somehow somewhere the priority is screwed up, and I don't know what screws it up.