Author Topic: UART hang on receive in default interrupt handler  (Read 11338 times)

Offline akorud

  • Newbie
  • *
  • Posts: 31
    • View Profile
UART hang on receive in default interrupt handler
« on: May 29, 2008, 02:38:18 PM »
Hi, I'm trying to use second UART (first is working like a charm) and found out strange behavior:
UART is opened:
Code: [Select]
tInterfaceParameters.Channel = 1;
tInterfaceParameters.ucSpeed = SERIAL_BAUD_9600; // 9600 baud rate
tInterfaceParameters.Rx_tx_sizes.RxQueueSize = RX_BUFFER_SIZE;      // input buffer size
tInterfaceParameters.Rx_tx_sizes.TxQueueSize = TX_BUFFER_SIZE;      // output buffer size
tInterfaceParameters.Task_to_wake = OWN_TASK;                
tInterfaceParameters.usConfig = (CHAR_8 | NO_PARITY | ONE_STOP | NO_HANDSHAKE | CHAR_MODE);

if (InternalUARTPortID = fnOpen( TYPE_TTY, FOR_I_O, &tInterfaceParameters )) {
        fnDriver( InternalUARTPortID, ( TX_ON | RX_ON ), 0 );                  // enable rx and tx
}
send some data:
Code: [Select]
if (fnWrite(InternalUARTPortID, &req, sizeof(req)) != sizeof(req)) {
//fail
}
which works fine and I can confirm data sending with osciloscope. Then as soon as data comes to this serial port execution flow jumps to
Code: [Select]
// default interrupt handler - and undefined interrupts will arrive here
//
static __interrupt__ void undef_int(void)
{
    while (1) {}                                                         // wait here and analyse with debugger....
}
and application is reseted by watchdog.
Any ideas what I'm doing wrong?

Thanks in advance,
Andriy Korud

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3236
    • View Profile
    • uTasker
Re: UART hang on receive in default interrupt handler
« Reply #1 on: May 29, 2008, 04:08:36 PM »
Hi Andriy

I suspect two things:

1. If you have the define SERIAL_SUPPORT_DMA active you should pass the parameter tInterfaceParameters.ucDMAConfig = 0;
This could cause strange things when left uninitialised but probably not an exception.

2. More likely - you haven't enough heap available for the extra UART buffer space defined (I assume you are opening an 'additional' UART and not just 'changing' its UART number).

If you look in fnOpenTTY() in Tty_drv.c you will see that the UART requires memory for its transmit control block and for its receive control block. Each block then has its own data queue defined by the sizes you pass (RX_BUFFER_SIZE and TX_BUFFER_SIZE) .
First the tx buffer block is allocated, followed by the rx block.
Assuming you are demaining a little more memory than the heap has (increase in config.h using define OUR_HEAP_SIZE) the tx block will be possible and so tx work OK, but the rx block allocation will fail. This will only be noticed when something is received and the receiver tries to put the received characcter into the (non-existent) buffer.

Since a null pointer (returned by uMalloc() on failure) will be pointing to FLASH in most chips it doesn't necessarily cause a crash immediately but only then when a pointer goes off into non-existend memory or a write is attempted to a pointer pointing to FLASH.

If you run the project in the uTasker simulator a uMalloc() failure will result in an immediate exception which is then easier to find.

To quickly confirm this, set break points on the null return in uMalloc() and uMallocAlign(). Also monitor the heap use before opening the UART (using fnHeapAvailable() and fnHeapFree()) - is there enough left for the buffers? - and then increase the heap define to make the additional memory possible.

However also always monitor stack use using fnStackFree() to ensure that the additional heap requirements doesn't conflict with stack memory use. If it gets critical (limited by chip's physical memory) then you may have to optimise some buffers sizes to save a little space.


Regards

Mark

Offline akorud

  • Newbie
  • *
  • Posts: 31
    • View Profile
Re: UART hang on receive in default interrupt handler
« Reply #2 on: May 29, 2008, 04:22:12 PM »
Hi Andriy

I suspect two things:

1. If you have the define SERIAL_SUPPORT_DMA active you should pass the parameter tInterfaceParameters.ucDMAConfig = 0;
This could cause strange things when left uninitialised but probably not an exception.

Thanks, that was the problem - now everything works fine.
And another question about serial port - what if flow control is turned off (both RTS_CTS and XON_XOFF) and data comes to serial port faster than application is able to read them - they will be silently discarded? Or something worse can happen?

Regards,
Andriy

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3236
    • View Profile
    • uTasker
Re: UART hang on receive in default interrupt handler
« Reply #3 on: May 29, 2008, 09:05:54 PM »
Hi Andriy

If you are not using DMA on the UARTs you could remove the define SERIAL_SUPPORT_DMA.

If there's no more input buffer space, following characters will indeed be 'silently discarded'.

Regards

Mark


Offline akorud

  • Newbie
  • *
  • Posts: 31
    • View Profile
Re: UART hang on receive in default interrupt handler
« Reply #4 on: May 30, 2008, 09:12:59 AM »
Hi Andriy

If you are not using DMA on the UARTs you could remove the define SERIAL_SUPPORT_DMA.

Hi, thanks for the tips. I wonder what are the benefits of using DMA for serial transfers?

Andriy

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3236
    • View Profile
    • uTasker
Re: UART hang on receive in default interrupt handler
« Reply #5 on: May 30, 2008, 10:47:30 AM »
Hi Andriy

I would generally use DMA on transmission (as long as you don't need flow control - flow control presently doesn't work in conjunction with DMA) since it means that the CPU doesn't need to handle an interrupt for each transmitted character. If you, for example, activate TX DMA on a debug output and a string of 1000 bytes is sent, it can be handled with just one interrupt (at the end of the complete transmission). Without DMA support it will have to handle 1000 interrupts, which means that the CPU gets disturbed much more. Whether this is actually noticable is another question...

DMA on reception is another matter since this requires a fixed amount of characters to be received in each frame, which is not practical for a lot of uses. If a protocol always sends 100 bytes this would means that the receiver would only have to handle the DMA interrupt to say that the 100 bytes have arrived. Another possibility (which is supported) is to work in break mode. In this mode the receiver can receive a large and variable amount of data using DMA (no CPU interrupts) until it receives a break condition ('0' on the line for about 10 baud intervals). This will then interrupt the processor which can handle the rx input as a frame.

Not all processors support DMA on the UARTs but the Coldfire does and this support is included. Note however that the Coldfire has 4 DMA controllers. If all 3 UARTs are used in TX DMA mode 3 of these are assigned (additional ones would be required for rx channels) - generally one DMA channel is used by uMemcpy()/uMemset() to speed up these routines, which then would allocate all available channels. Other processor types (such as SAM7X) have a DMA channel assigned for every peripheral: the DMA channels are however dedicated and not as flexible as in the Coldfire - for example they can not be used for memory<->memory transfers, which are useful to accelerate uMemcpy()/uMemset().

Regards

Mark