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 */
解決済! 解決策の投稿を見る。
Hi,
Does this: int_io_dev_ptr->DEV_PUTC(int_io_dev_ptr, c);
call the function: void _kuart_int_putc().
The function waits TX-register to be empty:
while (!(sci_ptr->S1 & UART_S1_TDRE_MASK)) {
/* Wait while buffer is full */
} /* Endwhile */
Prevents/blocks other interrupts to be served during this time.
How about, if you increase a global variable in unexpected int routine and check and print
that variable in main task of you system.
~Mark
Hi,
Does this: int_io_dev_ptr->DEV_PUTC(int_io_dev_ptr, c);
call the function: void _kuart_int_putc().
The function waits TX-register to be empty:
while (!(sci_ptr->S1 & UART_S1_TDRE_MASK)) {
/* Wait while buffer is full */
} /* Endwhile */
Prevents/blocks other interrupts to be served during this time.
How about, if you increase a global variable in unexpected int routine and check and print
that variable in main task of you system.
~Mark
Hi Mark,
You're right, the function called by int_io_dev_ptr->DEV_PUTC() polls the TX register before sending a character.
For MCF52259, this function is _mcf52xx_uart_serial_int_putc() defined in mqx/source/io/serial/int/serl_int_mcf52xx.c (this is set when calling _io_serial_int_install() in mqx/source/io/serial/int/serl_int.c to install the driver)
But this is not worse than doing this when using the polled UART driver. The purpose here is just to have the same functionality than with the polled UART driver.
OK, other interrupts are lost when printing characters from the ISR, but it's OK for me because the purpose is not to use prinf() in the ISRs used by the drivers (which would not be a good idea), but to display fatal exceptions (data access error, code corruption, ...) or unhandled ISRs (that should never occur).
On my system, I added a reset at the end of the int_unx.c to reset the board when such a problem occur, so I don't care about loosing interrupts. The more important to me is to know the task, the type of error, and the address in code at which the porblem occured.
There's probably a simplier solution without the extra variable _io_serial_int_write_force_polled_mode, but I have not tested it yet.
Use
if (_mqx_kernel_data->IN_ISR) {
instead of
if (_io_serial_int_write_force_polled_mode) {
or cleaner but longer :
KERNEL_DATA_STRUCT_PTR kernel_data;
_GET_KERNEL_DATA(kernel_data);
if (kernel_data->IN_ISR) {