|
|
View previous topic :: View next topic |
Author |
Message |
notbad
Joined: 10 Jan 2013 Posts: 68
|
Second instance of printf function? |
Posted: Sun Jun 01, 2014 1:16 am |
|
|
Hi
As you know, there is a solution for stopping the compiler from disabling interrupts for delay functions(here) but I couldn't find one for printf.
I tried:
Code: |
#use rs232(BAUD=9600,UART1,ERRORS)
#int_xxx
void xxx_ISR(void)
{
printf("a");
}
#use rs232(BAUD=9600,UART1,ERRORS)
void main()
{
printf("b");
} |
and:
Code: |
#use rs232(stream=isr,BAUD=9600,UART1,ERRORS)
#use rs232(stream=maincode,BAUD=9600,UART1,ERRORS)
#int_xxx
void xxx_ISR(void)
{
fprintf(isr,"a");
}
#use rs232(BAUD=9600,UART1,ERRORS)
void main()
{
fprintf(maincode,"b");
} |
My CCS version is 4.130. |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Sun Jun 01, 2014 1:56 am |
|
|
1) Why do you even want to printf in an ISR?
2) Exactly what do you want to happen?
Mike |
|
|
notbad
Joined: 10 Jan 2013 Posts: 68
|
|
Posted: Sun Jun 01, 2014 2:41 am |
|
|
Thanks Mike
The Interrupt is simply an INT_TIMER2 and counts a timeout variable and if code is stuck somewhere (in an external eeprom routine) it prints something and halts(while(true);) right there in the isr. I know this is not good practice but I was hoping to find a way to do it this way. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19554
|
|
Posted: Sun Jun 01, 2014 2:53 am |
|
|
If you must print in an ISR, then don't!....
Use interrupt driven buffered routines instead.
This lets the characters actually transmit when there is space in the UART to take them, and allows the interrupt to just update data to the buffer.
Code: |
#define T_BUFFER_SIZE 64
byte t_buffer[T_BUFFER_SIZE];
byte t_next_in = 0;
byte t_next_out = 0;
#define INC_PTR(x) if (++x == T_BUFFER_SIZE) x=0
#int_tbe
void serial_isr() {
if(t_next_in!=t_next_out)
{
putc(t_buffer[t_next_out]);
INC_PTR(t_next_out);
}
else
disable_interrupts(int_tbe);
}
#bit GIE=getenv("BIT:GIE")
void bputc(char c) {
//buffered putc to call in the main code.
int1 GINT;
GINT=GIE;
disable_interrupts(GLOBAL);
t_buffer[t_next_in]=c;
INC_PTR(t_next_in);
if (t_next_in==t_next_out);
INC_PTR(t_next_out);
if (GINT)
enable_interrupts(GLOBAL); //interrupts will be re-enabled
//if they were enabled when the routine was called - not otherwise.
enable_interrupts(int_tbe);
}
void int_bputc(char c)
{
//Buffered putc to call inside the interrupt
t_buffer[t_next_in]=c;
INC_PTR(t_next_in);
if (t_next_in==t_next_out);
INC_PTR(t_next_out);
enable_interrupts(int_tbe);
}
|
Then call int_bputc for your printing in the interrupt, and bputc for the prints outside.
Key differences here is that unlike the CCS bputc, these will throw away characters if the buffer gets full, rather than waiting. If the buffer is larger than any message you might send, this is not a problem. They will also work efficiently for non binary buffer sizes. Because interrupts are disabled in the bputc version, they won't interfere with one another, except insofar as data could be inserted by the interrupt routine in the middle of a message being generated in the main code. If you don't want this to happen, then just disable_interrupts(GLOBAL) before calling the bputc, and re-enable it afterwards. This way the message from 'main' will always be unbroken. Since it only takes uSec to add a message to the buffer, this is generally OK. |
|
|
notbad
Joined: 10 Jan 2013 Posts: 68
|
|
Posted: Sun Jun 01, 2014 6:33 am |
|
|
Hi Ttelmah. Thanks.
I tested your code and it works goodly. I disabled GIE after buffer is all out. |
|
|
|
|
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
|