Author Topic: Serial Port  (Read 8306 times)

Offline neil

  • Sr. Member
  • ****
  • Posts: 438
    • View Profile
Serial Port
« on: August 02, 2007, 03:56:39 PM »
Hi,
  I have a serial port configured as UART_TX_DMA for sending.  How do I know when all the data is sent? Just so the applicaiton can send another block known that the previous wont be overwritten before being sent.

Regards
Neil
« Last Edit: August 02, 2007, 03:59:26 PM by neil »

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3234
    • View Profile
    • uTasker
Re: Serial Port
« Reply #1 on: August 03, 2007, 09:52:16 PM »
Hi Neil

I don't know whether this is specific to the fact that you are using DMA on transmission or not so I will give some details.

1. When using the UART for transmission there is no difference at the interface level when using it in interrupt driven or DMA mode.

2. The interface is realised as a queue. The user passes data to the driver as a buffer (with length). The contents are copied to the UART's output buffer, which has the size as defined when opening the interface:

TTYTABLE tInterfaceParameters;                                       // table for passing information to driver
...
tInterfaceParameters.Rx_tx_sizes.TxQueueSize = TX_BUFFER_SIZE;       // output buffer size
...
SerialPortID = fnOpen( TYPE_TTY, ucDriverMode, &tInterfaceParameters );

NOTE: The buffer space is taken from the uMalloc heap so the heap size (MY_HEAP_SIZE in config.h) may have to be increased to satisfy the new requirement.

3. Assuming that the transmitter is not busy, the transmission of the block will be started - either first character in interrupt driven mode or transmission of the block in DMA mode.
Note that the buffer is circular and in DMA mode not all of the block will be transmitted in one DMA transfer sequence if there is a wrap around. Instead the first transfer will be up to the end of the buffer and a second transfer will start afterward from the begining of the buffer.

4. If a transfer is already in progress the buffer is filled but the present transfer is not changed. In interrupt mode it simply means that there are more characters waiting to be sent and these will be transmitted as soon as previously waiting ones have been completely transmitted. In DMA mode the present block transfer will always be completed and then a second transfer will be started with a new block length determined by the amount of characters waiting in the buffer - again if this involves a wrap in the circular buffer the block transfer will be up to the end of the buffer and a subsequent one will then start at the beginning again.

5. If the user tries to copy more characters than there is space in the buffer, the ones which won't fit are simply discarded (theys will be lost). The user can check (if the data is very important - rather than debug type data) to see whether there is enough space to accept the buffer by calling the write with a zero pointer as follows:
if (!fnWrite(SerialPortID, 0, MAX_MENU_LINE)) {
    // complete message can not be accepted at the moment
}
Take a look in debug.c in the demo project which uses this method to halt the display of a menu until the TX_FREE interrupt event is returned to inform that the buffer has space again. In the demo project the output buffer is set to about 250 bytes
to ensure that the menu can not be sent in one go and thus to illustrate how this control can be used!

If there is however adequate RAM available, the user should try to dimension the tx buffer so that it will accept all message in normal use. When used as debug output a size of 250 bytes is usually not adequate - 1k to 4k is more practical (if the memory is available and can be afforded!!).

Note that for string output the function fnDebugMsg("Hello World!"); is a practical alternative to fnWrite(SerialPortID, "Hello World!", uStrlen("Hello World!")); It sends the string (after counting its length) to DebugHandle. If the project wants to use a particular UART for debug data simply set DebugHandle = SerialPortID;
Note that if DebugHandle is left as default NETWORK_HANDLE the data (string) will be sent via the routine fnNetworkTx(). In the demo project this sends debug output to an open Telnet connection. The use of UART and TELNET are thus more or less interchangeable. ALso the flow contro methoid is the same - see the discussion on using TCP in teh uTasker project and buffered TCP!

Regards

Mark