AnsweredAssumed Answered

Make printf work in ISRs with interrupt driven UART driver

Question asked by gilles buloz on Nov 4, 2011
Latest reply on Nov 5, 2011 by gilles buloz

I use interrupt driven UART driver ("ittya:") on my project and wanted to have unexpected exception beeing displayed.

 

First, in the mqx/source/bsp/<myboard>/init_bsp.c, I added 

   _int_install_unexpected_isr();

to set the default handler for unexpected ISRs; this is  _int_unexpected_isr() defined in mqx/source/psp/coldfire/int_unx.c

But as said in this file " This default I/O must NOT be an interrupt drive I/O channel"

 

However, with a very small change to the UART driver this works fine. The trick is : when printf is called from an ISR, send the characters directly to the UART.

For this, just edit

mqx/source/io/serial/int/serl_int.c

to add the following lines at the beginning of _io_serial_int_putc_internal()  (just after /* End CR 388 */) :

   if (_io_serial_int_write_force_polled_mode) {
       /* directly write to UART, bypassing normal interrupt driven code */
       int_io_dev_ptr->DEV_PUTC(int_io_dev_ptr, c);
       return;
   }

Then add to mqx/source/fio/io_util.c :

boolean _io_serial_int_write_force_polled_mode = FALSE;

 

And to mqx/source/include/fio.h

extern boolean _io_serial_int_write_force_polled_mode;

 

Then in mqx/source/psp/coldfire/int_unx.c, before first printf() add :

   _io_serial_int_write_force_polled_mode = TRUE; /* force polled UART mode (needed when called from ISR) */

and after last printf() :

   _io_serial_int_write_force_polled_mode = FALSE; /* no more force polled mode */

You can also force the output to be written to the default serial port instead of the current stdout (useful if the terminal of the task producing the exception is not a serial port; a telnet session for example); for this declare :

   pointer stdout_orig;
then before first printf :

   _io_serial_int_write_force_polled_mode = TRUE; /* force polled UART mode (needed when called from ISR) */
   stdout_orig = td_ptr->STDOUT_STREAM;
   td_ptr->STDOUT_STREAM = kernel_data->PROCESSOR_STDOUT; /* force printf output on default console */
and after last one :

   td_ptr->STDOUT_STREAM = stdout_orig; /* restore stdout */
   _io_serial_int_write_force_polled_mode = FALSE; /* no more force polled mode */

Outcomes