RE: Fast Read/Write To Serial Port
"Kelly Smith" <[email protected]>
| Newsgroups | gmane.comp.hardware.microcontrollers.tini |
|---|---|
| Message-ID | <[email protected]> |
Dear Jonathan - This code from Systronix ( a slight "hack" to add SIO
hardware handshaking), works fine for me at any baud rate (including
115,200), with both BlackBox and HyperTerminal.
Look it over... Its using serial4, but easily changed to do the other
"supported RS-232 ports for either a DalSemi DSTINIm400 or Systronix
TStik400, and TINI SDK 1,12. Use "/* blah, blah */ to commented out the code
just above " // Whoops! No control lines are available.", if you
don't want the hardware handshake.
Best regards, Kelly Smith
package com.systronix.TStik.App.Notes;
import java.io.IOException;
import java.io.OutputStream;
import java.io.InputStream;
import javax.comm.SerialPort;
import javax.comm.SerialPortEvent;
import javax.comm.CommPortIdentifier;
import com.dalsemi.system.*;
/**
* Simple SerialEcho example, using javaxcomm.<br>
* This program receives serial data on any Systronix TStikJStamp/JStik/SaJe
com port
* RXD line, echos it back out the same com port TXD line, and prints the
hex value
* and ASCII character to System.out. This is a good basic serial I/O test
program,
* using serial4 RTS/CTS hardware handshake. <br>
* <hr>
*
* <b>Serial cables:</b>
* <hr>
* <b>Details:</b><br>
* This class implements SerialPortEventListener in
* order to receive the DataAvailable event.
* <hr>
* <B>Using this example</B>
* Change baud rate or com port values in {@link #initializeSerialPort}
* <br>
* <hr>
*
* @author Kelly Smith. Added (1) RTS/CTS control section, (2) accept baud
rate from
* the command line, and renamed to Serial4,
* on December 27, 2003.
* @version 1.6
*
* @author B Boyes
* @version 1.5 testing serial 4 support on Tstik.
* version 1.0 initial version
* <ul>
* <li>1.0 2002 Sep 30 bboyes
* </ul>
*/
public class Serial4 implements javax.comm.SerialPortEventListener
{
/** reference to the serial input stream */
protected InputStream inStream;
/** reference to the serial output stream */
protected OutputStream outStream;
/** Javax.comm will call this method whenever a Data Available event
occurs
* On serial ports without hardware flow control this is the only event
supported.
*
* @param ev this is the serial event - it tells us what kind of
* event occurred. Currently DATA_AVAILABLE is the only supported event
on serial
* ports without flow control.
*/
public void serialEvent(SerialPortEvent ev)
{
// Display incoming ASCII values if true.
boolean displayASCII = true;
// "Holding byte" for recieved ASCII value.
byte rcvVal;
// Is any serial input data available?
if (ev.getEventType() != SerialPortEvent.DATA_AVAILABLE)
System.out.println("Bad event " + ev.getEventType());
try
{
while (inStream.available() > 0)
{
// Get the received value.
rcvVal = (byte) inStream.read(); // blocking call
// Echo the recieved value back out to sender.
outStream.write(rcvVal);
if (displayASCII)
{
System.out.println("0x" + Integer.toHexString(rcvVal & 0xFF) + " " +
(char) rcvVal);
}
}
} catch (IOException e) {
System.out.println("IOException caught");
}
} // End serialEvent
/** Method to initialize the serial port and set up the
* input and output streams - this is where you change the baud rate
* and com port. If it is unable aquire the serial port, the program will
exit.
*
* It demonstrates serial input and output streams using javax.comm.
* It also registers this class as
* a listener for the data available events with Javax.comm.
*
* No parameters, but edit the source code here to change com port and baud
rate.
* <br>
* On JStamp, SaJe and JStik, the onboard serial ports are "com1" and
"com2".
* With SaJe, "com3" is available on the SBX2 expansion board.
* <br>
* On TINI the uarts are serial0, serial1, serial2 and serial3.
*
* @return nothing if successful. Uses System.exit to bail out brutally
* if unable to properly configure. For JStamp, SaJe and/or JStik there's
* really no place to which we can exit so this will in turn result in
* an aJile Charade runtime exception.
*/
public void initializeSerialPort(String portName, int baudRate)
{
SerialPort sp;
CommPortIdentifier commPortId;
try
{
commPortId =
CommPortIdentifier.getPortIdentifier(portName);
if (!commPortId.isCurrentlyOwned())
{
if (commPortId.getPortType() == CommPortIdentifier.PORT_SERIAL)
{
try
{
// Open the serial port. The name is unimportant,
// The second (timeout) parameter is unimplemented
sp = (SerialPort) commPortId.open("Serial4 Test", 0);
// Set the baud rate, using the command line parameter.
sp
.setSerialPortParams(
baudRate,
javax.comm.SerialPort.DATABITS_8,
javax.comm.SerialPort.STOPBITS_1,
javax.comm.SerialPort.PARITY_NONE);
// Enable RTS/CTS Flow Control for serial port 4 only, if DS80C400.
// NOTE: Only serial0 or serial1 or serial4 can have RTS/CTS flow control
// enabled at a time.
if ( TINIOS.getCPU() == TINIOS.DS80C400 )
{
TINIOS.setSerial(TINIOS.SERIAL_SET_RTSCTS_FLOW_CONTROL, 1, false);
TINIOS.setSerial(TINIOS.SERIAL_SET_RTSCTS_FLOW_CONTROL, 0, false);
TINIOS.setSerial(TINIOS.SERIAL_SET_RTSCTS_FLOW_CONTROL, 4, true);
// Enable RTSCTS flow control
sp.setFlowControlMode(sp.FLOWCONTROL_RTSCTS_IN |
sp.FLOWCONTROL_RTSCTS_OUT);
}
// Whoops! No control lines are available.
else
{
// Indicate failure and exit, killing the JVM.
System.out.println("The host controller is not a DSTINIm400 or TStik400");
System.out.println("Exiting...");
System.exit(1);
}
// Register for notification of data changes
try
{
sp.addEventListener(this);
} catch (Exception tml) {
System.out.println("addEventListener error " + tml.toString());
System.exit(1);
}
sp.notifyOnDataAvailable(true);
// Get output and input streams
outStream = sp.getOutputStream();
inStream = sp.getInputStream();
outStream.write("Hello World".getBytes());
} catch (javax.comm.UnsupportedCommOperationException ucoe)
{
System.out.println("Error: UnsupportedCommOperationException");
System.exit(1);
} catch (javax.comm.PortInUseException piue) {
System.out.println("Error: PortInUseException");
System.exit(1);
} catch (java.io.IOException ioe) {
System.out.println("Error: IOException");
System.exit(1);
} // end catch block
} else {
System.out.println("Error: comm port is not a serial port");
System.exit(1);
} // End if port is serial
} // End if port is not owned
} catch (javax.comm.NoSuchPortException nsp) {
System.out.println("NoSuchPortException");
System.exit(1);
}
} // End initializeSerialPort
/**
* Instantiate our class and then wait in this thread.
* All the action then occurs in the serial event handler.
*/
public static void main(String[] args)
{
if (args.length != 1) {
System.out.println("Usage: java Serial4.tini baudrate");
System.exit(1);
}
Serial4 mEcho4 = new Serial4();
mEcho4.initializeSerialPort("serial4", Integer.parseInt(args[0]));
System.out.println("Serial Port Echo Using Events Example bab 1.6");
mEcho4.blockThread();
} // End of main
/**
* Method to block a thread
* This lets the main routine do nothing.
* Serial events will then be received and handled
*/
public synchronized void blockThread()
{
try
{
wait();
} catch (InterruptedException ie)
{
System.out.println("block thread exception: " + ie.toString());
ie.printStackTrace();
}
} // End of synchronized
} // End of class Serial4
-----Original Message-----
From: tini-admin-6tN4nzCoH/[email protected] [mailto:[email protected]]On Behalf Of
Jonathan Sharret
Sent: Thursday, January 15, 2004 1:00 PM
To: [email protected]
Subject: [TINI]Fast Read/Write To Serial Port
Hi
My company just bought the DSTINIs400/DSTINIm400 kit. Ive set up the
TINI system running SDK 1.12.
Im trying to run a simple loopback program on the serial port. Using a
straight-through cable from my PCs COM1 to TINIs serial0 Id like TINI
to transmit back everything it receives. Im using the Comm APIs
blackbox program to test out my TINI program. I would think that this
would be a relatively simple operation and would not tax the system
(after all, max serial port speed is 115,200 bps and the system runs at
70 MHz. However, at any baud rate above 19,200 bps there is significant
byte loss (roughly half are lost). I would like to get this application
working at 115,200. I get byte loss even when I increase the input
buffer size. Ive tried using RTS/CTS but for some reason nothing
transfers when I use that setting. However, I dont want to use flow
control so its a moot point.
The main problem seems to be transmitting and not receiving. Ive tried
every combination of putting the receiver and transmitter in the same or
separate threads to no avail. When I just have a receiver running I
always receive the correct number of bytes. However the second a
transmitter is added the receiver no longer receives properly. It seems
that the process waits for the transmitter to finish before receiving
again. This happens regardless of whether the receiver and transmitter
are in separate threads. This doesnt seem to make sense to me since I
would think the separate threads would prevent the write from blocking
the read and vise versa. Using javax.comms read and write together at
115,200 results in the read method always returning 1 byte. Only at
19,200 does it work properly. I decided to try the NativeComms read
and write methods and although it actually grabs large chunks of data
now the receiver still drops about half the bytes. Im trying to read
blocks of data at a time so Im not byte-banging. Heres the receivers
code.
Using NativeComm:
import java.io.*;
import java.util.*;
import java.lang.*;
import com.dalsemi.comm.*;
public class SerialReceiver implements Runnable {
private byte[] buffer = null;
private int avail = 0;
private int amtReceived = 0;
private int total = 0;
private int portHandleRx;
private int portHandleTx;
public SerialReceiver(SerialConnection owner) {
portHandleRx = NativeComm.open(NativeComm.PORT_SERIAL0,
NativeComm.STREAM_STDIN);
portHandleTx = NativeComm.open(NativeComm.PORT_SERIAL0,
NativeComm.STREAM_STDOUT);
}
public void run() {
while (true) {
avail = NativeComm.available(portHandleRx);
if (buffer == null || buffer.length < avail)
buffer = new byte[avail];
amtReceived = NativeComm.read(portHandleRx, buffer, 100, true);
if (avail > 0) {
System.out.println("amtAvail: " + avail);
}
if (amtReceived > 0) {
System.out.println("amtRx: " + amtReceived);
NativeComm.write(portHandleTx,buffer,0,amtReceived);
total += amtReceived;
System.out.write(buffer,0,amtReceived);
System.out.println("Rcv: " + total);
}
}
}
}
The javax.comm version is essentially the same. Can someone explain to
me what Im doing wrong here?
Thanks,
Jonathan
_______________________________________________
TINI mailing list
TINI-6tN4nzCoH/[email protected]
To UNSUBSCRIBE, edit your profile, or see list archives:
http://lists.dalsemi.com/mailman/listinfo/tini
_______________________________________________
TINI mailing list
TINI-6tN4nzCoH/[email protected]
To UNSUBSCRIBE, edit your profile, or see list archives:
http://lists.dalsemi.com/mailman/listinfo/tini