Created Fri, 05 Aug 2011 05:51:46 +0000 by ron.dunn
Fri, 05 Aug 2011 05:51:46 +0000
What is the maximum baud rate supported for the HardwareSerial ports on Max32?
Ron.
Fri, 05 Aug 2011 10:40:56 +0000
What is the maximum baud rate supported for the HardwareSerial ports on Max32?
Look here: http://www.chipkit.org/forum/viewtopic.php?f=7&t=213 1.25 - 1.5Mbps, depending on your clock setting and the real limiting factor is the FTDI chip, not PIC32. It's worth noting that very few terminal programs, belonging to the age when the computers were powered by coal furnaces, are ready to accept such baudrates.
Fri, 05 Aug 2011 11:21:07 +0000
Hmmmm. I wonder where I'm going wrong ...
I have a program on my PC that writes bytes to the serial port, opened at 115200. The program opens a port using the Windows CreateFile() function, then stuffs bytes down it in a loop using the WriteFile() function. Here are the two relevant snippets:
for (long i=0; i<1000000L; ++i) {
serial.Write ((byte) 1);
}
serial.Write ((byte) 0);
bool Serial::Write (byte b) {
DWORD countSent = 0;
if (WriteFile (port,&b,1,&countSent,0)) return (true);
return false;
}
A program on the Max32 reads bytes from the serial port as fast as it can, and when it receives a special character reports back the number read. Here's the Max32 code:
long count = 0L;
void setup () {
Serial.begin (115200L);
Serial.println ("Waiting ...");
}
void loop () {
if (Serial.available()) {
int ch = Serial.read ();
++count;
if (ch == 0) {
Serial.print ("Count=");
Serial.println (count);
count = 0;
}
}
}
The fastest I can make this work is to transfer 1,000,000 bytes in around 4 minutes. That works out to around 4,500 characters per second.
That looks just wrong, probably around half what I thought I should be getting. Increasing the baud rate doesn't work, either.
Oh well, back to the keyboard.
Fri, 05 Aug 2011 13:11:01 +0000
Did you try to verify the data you're receiving? How exactly do you open the port? Did you try to send data the other way around (just so it might be easier to verify)?
I've found this my junkbin, it could serve as an example of windows serial port setup. I know that it works, although I'm not sure if it's the best way. Look below line 61. http://code.google.com/p/svofski/source/browse/src/avr/bootloader/avr/mega_bootloader/pc_sw_5/win_unix_port_vXXX/serial.c
Fri, 05 Aug 2011 13:37:32 +0000
The code for opening the port is basically the same as that you linked:
bool Serial::Begin(char *portName,long baudRate) {
DCB dcb;
port = CreateFile(portName,(GENERIC_READ | GENERIC_WRITE),0,NULL,OPEN_EXISTING,FILE_FLAG_NO_BUFFERING,NULL);
if (port == INVALID_HANDLE_VALUE) return (false);
if (!GetCommState(port, &dcb)) return (false);
dcb.BaudRate=baudRate;
dcb.ByteSize=8;
dcb.StopBits=ONESTOPBIT;
dcb.Parity=NOPARITY;
if (!SetCommState(port, &dcb)) return (false);
return (true);
}
I've verified the data being written from the PC and received at the Max32, it is correct. I tested by writing cascades of 1-8-1 repeatedly, and validating that sequence at the receiving end. I've also tried the port buffered and unbuffered. Same result.
Data gets written back successfully as well.
I can't help thinking I've missed something obvious. I'll sleep on it tonight and see what occurs to me in the morning.
Fri, 05 Aug 2011 15:49:47 +0000
Well, everything looks normal to me then. What if you tried to write in larger chunks on Windows? On chipKit it's all pretty simple, but I'm not sure how these things are handled in Windows. It's normal to expect some unnecessary overhead when doing I/O byte-by-byte.
Fri, 05 Aug 2011 21:09:05 +0000
Keep in mind that when you are going through the FTDI USB serial converter, the baud rate that you set in the UART on the Max32 is the baud rate between PIC32 and the FTDI chip. The actual data transfer rate is going to be governed by the USB interface.
The FTDI FT232R is a full speed device. It has a 256 byte transmit buffer. Data from the PC will be sent in 256 byte (or smaller chunks). The way full speed USB bus scheduling works, if the host tries to send a packet to a device, and the device doesn't accept it immediatly, the host waits several milliseconds before trying to send it again.
All of these things will limit the maximum data throughput you can get. If there were no USB overhead at all, 115,200 baud is about 11000 characters per second. You're getting a bit better than a third of that. I would have thought you would be able to get a bit faster than that.
Gene Apperson Digilent
Fri, 05 Aug 2011 23:02:56 +0000
Thanks for the input so far.
I re-compiled the device program for an Arduino Mega and got exactly the same results.That suggests (a) the problem is in the host PC, or (b) the problem is in the Arduino library code.
The host code was compiled using MinGW. I think I'll try an alternative compiler, or maybe even an alternative language. I've got a Python environment on this machine, so I might replicate the program there and see what happens.
Sat, 06 Aug 2011 06:56:20 +0000
Solved (I think).
I was writing a USB packet for each character. Bundling my data into 10,000 character blocks and writing one block at a time increased my throughput to the expected level.
Here's a snippet that shows the change:
byte buf[10000];
for (int outer=0; outer<100; ++outer) {
// Write buffer to serial port. IN EARLIER POST
// THIS WAS A LOOP SENDING ONE BYTE AT A TIME.
memset (buf,1,sizeof(buf));
serial.Write (buf,sizeof(buf));
// Send feedback request and wait for response.
serial.Write ((byte) 13);
Sleep (20);
// Print time and response to console.
time (&t);
ts = localtime (&t);
printf ("(%02d:%02d:%02d) %d: ",ts->tm_hour,ts->tm_min,ts->tm_sec,outer);
while (serial.Available()) putchar ((char) serial.Read());
}
Another lesson learned!