Ucom/Uftdi Thru-put
User Tomdean
tomdean at speakeasy.org
Tue Aug 30 17:47:44 GMT 2005
Sorry this is long, I have attached the code at the bottom.
ucom_read.c is the FreeBSD code. UMP2_send.c is the AVR code.
# kldload ucom
# kldload uftdi
power up UMP2 and AVR
In dmesg, I see
ucom0: FTDI USB HS Serial Converter, rev 1.10/2.00, addr 2
With a scope, on the USB_DATA+ line, I see groups of 3 uSec activity,
every 1 mSec. Within the groups, I see 100 nSec pulses, or a 10 mBit
rate.
# ./ucom_read
With a scope, on the USB_DATA+ line, I see activity every 1 mSec.
But, the AVR has groups of activity every 2 mSEC! Just before the 52
uSec of activity caused by the AVR, I see a 3 uSec group of activity.
So, the USB bus has its normal 3 uSec activity every 1 mSec overlayed
by 52 uSec of AVR activity every 2 mSec. So, ucom_read only gets the
USB bus every 2 msec.
The AVR send loop takes 0.9 to 1.1 uSec. These happen in bursts of 74
uSec every 2 mSec. The AVR waits for the UMP2 TX ready signal most of
the time.
>From looking at the USB_DATA+ line and the UMP2 *TXE signal, the *TXE
signal is not true until the buffer is empty. The doc states 'If this
signal is log.1, the buffer is full'.
10 mSec --+---------+---------+---------+---------
USB --1---------123-------1---------123------
*TXE ---------------4-------------------4-----
1 - 3 uSec USB activity from FreeBSD
2 - 10 uSec gap
3 - 52 uSec USB activity from the UMP2
4 - 72 uSec activity on the *TXE line, high otherwise.
The nominal return from the FreeBSD read is 62 bytes. The UMP2 has a
FT8U245BM chip, which has a 384 byte transmit buffer.
The output from ucom_read,
Read 1000060 bytes in 32.242824 seconds in chuncks of 62 bytes
This is a thruput of 31017 bytes/second.
Does FreeBSD only request 64 bytes from the UMP2????
tomdean
=== ucom_read =========================================================
/*
* asus-read.c - read ucom0, doing time measurements
*
* $Id$
*/
#include <stdio.h>
#include <termios.h> /* termios settings */
#include <fcntl.h> /* open */
#include <sys/types.h> /* read */
#include <sys/uio.h> /* read */
#include <unistd.h> /* read */
#include <sys/time.h> /* time */
#define USB_BUF_SIZE 20000
#define BYTES_TO_READ 1000000
/*
* Set up ucom's state
*/
void ucomsetup (int fd) {
struct termios termios;
tcgetattr (fd, &termios);
/* input modes */
termios.c_iflag = (IGNBRK);
/* local modes */
termios.c_lflag = 0;
/* common modes */
termios.c_cflag = (CLOCAL|HUPCL|CREAD|CS8); /* no parity */
/* since the UMP2 is a USB to parallel device, speed is meaningless */
if (0) termios.c_ispeed = termios.c_ospeed = B9600;
if (0) termios.c_ispeed = termios.c_ospeed = B38400;
if (0) termios.c_ispeed = termios.c_ospeed = B115200;
if (0) termios.c_ispeed = termios.c_ospeed = B230400;
if (0) termios.c_ispeed = termios.c_ospeed = B921600;
tcsetattr (fd, TCSANOW, &termios);
return;
}
/*
* main
*/
int main(int argc, char **argv) {
int fd; /* file descriptor */
int numRead;
size_t bytes;
uint8_t *buf[USB_BUF_SIZE];
struct timeval start, stop;
struct timezone tz;
long sec, usec;
double elapsed, mb_sec, nsec;
if ((fd = open("/dev/ucom0", O_RDONLY)) < 0) {
perror("Open /dev/ucom0");
return -1;
}
/* need to do this */
ucomsetup(fd);
numRead = 0;
/*
* get the start time
*/
gettimeofday(&start, &tz);
/*
* read a large number of bytes and keep track of time
*/
while (numRead < BYTES_TO_READ) {
bytes = read(fd, buf, USB_BUF_SIZE);
if (0) printf("Read %d bytes\n", bytes);
numRead += bytes;
}
/*
* get the end time
*/
gettimeofday(&stop, &tz);
/*
* calculate the time, etc.
*/
sec = stop.tv_sec - start.tv_sec;
if (sec < 0) sec++;
usec = stop.tv_usec - start.tv_usec;
if (usec < 0) {
sec--;
usec += 1000000L;
}
elapsed = (double)sec + ((double) usec)/1000000.0;
printf("Read %d bytes in %f seconds in chuncks of %d bytes\n",
numRead, elapsed, bytes);
close(fd);
return 0;
}
== UMP2_send ========================================================
/*
* UMP2-send.c - provide loopback for the UMP2 module
*
* Connections
* PORTA
* <7> UMP2 RD# =0 to read data
* <6> UMP2 WR =1 to write data
* <5> UMP2 TXE# =0 TX is available to accept data
* <4> UMP2 RXF# =0 RX has data available
* <3> UMP2 PWE# =0 if device is configured via USB
* <2>
* <1>
* <0>
* PORTB LEDs
* <7> Init OK
* <6>
* <5>
* <4>
* <3> Wait Tx ready
* <2> Wait Rx data
* <1> Writing data to UMP2
* <0> Reading data from UMP2
* PORTC
* <7:0> UMP2 data
*
* $Id$
*/
#include <avr/io.h> /* io definitions like PORTB, etc */
#include <libasus.h> /* prototypes */
#include <avr/interrupt.h> /* cli */
#include <stdint.h> /* uint8_t, etc */
/* led 0 is the first led, or bit 0 */
/* PORTB is at 0x18 */
#define LED_PORT 0x18
#define LED_ON(n) asm("cbi %0,%1"::"i"(LED_PORT),"i"(n))
#define LED_OFF(n) asm("sbi %0,%1"::"i"(LED_PORT),"i"(n));
/*
* UMP2 bit definitions
*/
#define UMP2_CTL PORTA
#define UMP2_CTL_PIN PINA
#define UMP2_RD 7
#define UMP2_WR 6
#define UMP2_TXE 5
#define UMP2_RXF 4
#define UMP2_PWE 3
#define UMP2_DATA PORTC
#define SET_READ DDRC=0x00
#define SET_WRITE DDRC=0xff
int main() {
uint8_t c;
uint8_t r;
asm("cli");
DDRA = (1<<UMP2_RD) | (1<<UMP2_WR);
DDRB=0xff; /* all output */
DDRC=0x00; /* all input */
PORTC=0x00; /* make sure no pullups */
/* ser UMP2_RD high */
PORTA |= (1<<UMP2_RD);
/* pull up the low signals */
PORTA |= (1<<UMP2_TXE) |(1<<UMP2_RXF) |(1<<UMP2_PWE);
PORTB = 0xff; /* all led's off */
serial_init();
/*
* set the UART baud rate
*/
UBRRL = 8; /* 115.2k at 16.0000Mhz */
PORTB = 0; /* all led's on */
if (0) r = serial_recv(); /* get in sync */
PORTB = 0xff; /* all led's off */
LED_ON(7);
LED_OFF(7);
c = 'a';
/* set the data port direction to out */
SET_WRITE;
while(1) {
/* visual output and scope trigger */
LED_ON(0);
/* Write data to UMP2 */
while (UMP2_CTL_PIN & (1<<UMP2_TXE)) ;
/* WR up */
UMP2_CTL |= (1<<UMP2_WR);
/* present data */
UMP2_DATA = c;
/* WR down */
UMP2_CTL &= ~(1<<UMP2_WR);
/* the loop is done */
LED_OFF(0);
}
return 0;
}
More information about the freebsd-usb
mailing list