libftdi Archives

Subject: Re: Re: opening device given its serial and hardware flow control

From: frrrt_ <frrrt_@xxxxxxxxxxxxx>
To: libftdi@xxxxxxxxxxxxxxxxxxxxxxx
Date: Sun, 22 Feb 2009 19:47:19 +0100
After some investigation...some answers and some more questions
See attached readwrite.c for reference

Cheers,
Luca


Problem #1: opening device given its serial

Basically the function ftdi_usb_open_desc expects the Fixed Serial Number of the device one wants to open. By running simple.c from the examples folder in libftdi-0.15 I was mislead into thinking that the FTDIChip-ID of R type chips was the serial number expected by ftdi_usb_open_desc. The Fixed Serial Number of a device can be found by running MPROG utility on Windows.

Can somebody explain what's the point of having a function called ftdi_read_chipid? From my understanding it is specific for FTDI 232R devices only but it doesn't check it is being called upon a 232R device, and it calculates a number, the chipid, which is not related to the true Fixed Serial Number..
Obviously I'm not criticizing, just trying to understand...


Problem #2: hardware flow control, in other words the RTS handshaking signal misbehaves after setting hardware flow control.

Sounds like FTDI device never sets RTS to GND (logic 0) even though ReaderThread continues to read FTDI RX buffer by repeatedly calling function ftdi_read_data. Under this circumstance the FTDI RX hardware FIFO buffer should be empty or nearly empty, hence the FTDI chip should automatically lower RTS to GND (logic 0).

Can somebody sugget a way of debugging this issue? Function ftdi_setflowctrl returns 0 to indicate correct operation.
I am starting to think it may be a hardware bug in the FTDI 232R chip???
Help please!




FTDI documentation reports the following:

*. RTS# and CTS# are by factory setting active low (hence the reason for character #) unless eeprom of FTDI chip has been set to the contrary. I checked my FTDI device is configured with factory settings.

*. RTS# is an output from FTDI device that controls flow of data into FTDI RX pin
    0: whatever device attached to FDTI device can transmit
    1: whatever device attached to FDTI device should stop transmitting

*. CTS# is an input to FTDI device that controls the flow of data out of FTDI TX pin
    0: FTDI device can send data
    1: FTDI device cannot send data


The unexpected behavior I observe can be summarized as follows:

*. Either I connect RTS and CTS together or leave them floating, this program reads 0s for about 5 seconds
   then I get following error:
write: rv=-110, error=usb bulk write failed, errno=Resource temporarily unavailable (11) close: rv=0, error=usb bulk write failed, errno=Resource temporarily unavailable (11)

*. If I manually connect CTS to GND (logic 0) then everything works and I receive the random numbers - good because it shows that if I manually assert CTS then the WriterThread can do its job.

*. The same misbehavior happens regardles I set bitbang ON or OFF.




Thomas Jarosch wrote:
Hi Luca,

On Wednesday, 11. February 2009 09:36:27 Thomas Jarosch wrote:
   1. Cant open specific FTDI device with serial D44F6D5
      tried with        ftdi_usb_open_desc(&ctx, vendor, device, NULL,
"D44F6D5");
      and also with     ftdi_usb_open_desc(&ctx, vendor, device,
"TTL232R-3V3", "D44F6D5");

     If I am logged in as root
      init: OK
      open: rv=-3, error=device not found, errno=Inappropriate ioctl for
device (25)

     If I am logged in as a user
      init: OK
     open: rv=-3, error=device not found, errno=Operation not permitted (1)

I took a quick look at ftdi_usb_open_desc() and to me the code seems fine.
You might want to add debug output in there to see
if it walks the USB device list correctly.

   2. Can't get to use handshaking signals RTS and CTS (hardware flow)
       Either I connect RTS and CTS together or leave them floating, it
reads 0 for about 5 seconds
       then I get following error: (basically it times out after so many
write attempts)

      write: rv=-110, error=usb bulk write failed, errno=Resource
temporarily unavailable (11)
      close: rv=0, error=usb bulk write failed, errno=Resource
temporarily unavailable (11)

      If I manually connect CTS to GND then everything works and I
receive the random numbers. Sounds like FTDI device never
     sets RTS(ready to send) to GND. I don't understand this because,
from what I have gathered
     googling hardware flow control, CTS line should be high (+3.3V) for
source device to begin transmission

     The same happens regardless I set bitbang ON or OFF

As I'm not really into the details of RS232, I guess this is best left to somebody else to answer. We use the FTDI chips for bitbanging only.

Cheers,
Thomas


--
libftdi - see http://www.intra2net.com/en/developer/libftdi for details.
To unsubscribe send a mail to libftdi+unsubscribe@xxxxxxxxxxxxxxxxxxxxxxx




--
libftdi - see http://www.intra2net.com/en/developer/libftdi for details.
To unsubscribe send a mail to libftdi+unsubscribe@xxxxxxxxxxxxxxxxxxxxxxx   
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
// published by the Free Software Foundation.
//
// Example of pthread read and pthread write inspired by 
//
//   sertest.c     Copyright (c) 2006 Dave Hylands     <dhylands@xxxxxxxxx>
//   testusb.c     Copyright (c) 06/2004 by Wolfgang Wieser
//
// This program is meant to be run on a FTDI device with RX connected to TX and 
// CTS connected to RTS (hardware flow control)
//
//    ________
//            |
//        TX  |---> 
//            |     | 
//        RX  |<---
//            |
//            |
//       RTS  |--->
//            |     |
//       CTS  |<---
//            |
//    ________|
//
//  From my understanding of RS232 gathered from internet and books the 
following should happen:
//
//    RTS goes high whenever the device is ready to receive
//  
//    CTS high allows device to begin transmission
//
//---------------------------------------------------------------------------------
//
// USAGE
// go to directory 
// /home/duffyduck/new_ftdi_driver/my_example2
//
// compile with the following
// gcc -O readwrite.c -o readwrite /usr/local/lib/libftdi.a -W -Wall -Wformat 
/usr/lib/libusb.a -pthread
//
//---------------------------------------------------------------------------------
//
//   PROBLEMS SEEN SO FAR
//
//
//
//   1. Cant open specific FTDI device with serial D44F6D5         
//       tried with        ftdi_usb_open_desc(&ctx, vendor, device, NULL, 
"D44F6D5");
//       and also with     ftdi_usb_open_desc(&ctx, vendor, device, 
"TTL232R-3V3", "D44F6D5");
//
//      If I am logged in as root
//      init: OK
//      open: rv=-3, error=device not found, errno=Inappropriate ioctl for 
device (25)
//
//      If I am logged in as a user
//      init: OK
//      open: rv=-3, error=device not found, errno=Operation not permitted (1)
//
//
//
//   2. Can't get to use handshaking signals RTS and CTS (hardware flow)
// Either I connect RTS and CTS together or leave them floating, it reads 0 for 
about 5 seconds 
// then I get following error
// write: rv=-110, error=usb bulk write failed, errno=Resource temporarily 
unavailable (11)
// close: rv=0, error=usb bulk write failed, errno=Resource temporarily 
unavailable (11)
//
// If I manually connect CTS to GND then everything works and I receive the 
random numbers. Sounds like FTDI device never
// sets RTS(ready to send) to GND. I don't understand this because, from what I 
have gathered 
// googling hardware flow control, CTS line should be high (+3.3V) for source 
device to begin trasmission
//
// The same happens regardles I set bitbang ON or OFF







#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/unistd.h>
#include <pthread.h>
#include <getopt.h>
//#include <termios.h>


//testusb
#include "ftdi.h"
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
//#include <sys/time.h>
//#include <time.h>


struct ftdi_context ctx;


static void Error(const char *where,int rv,struct ftdi_context *ctx,int doclose)
{
        if(rv)
        {
                fprintf(stderr,"%s: rv=%d, error=%s, errno=%s (%d)\n",
                        where,rv,ctx->error_str,strerror(errno),errno);
                if(doclose)
                {
                        rv=ftdi_usb_close(ctx);
                        fprintf(stderr,"close: rv=%d, error=%s, errno=%s 
(%d)\n",
                                rv,ctx->error_str,strerror(errno),errno);
                }
                ftdi_deinit(ctx);
                exit(1);
        }
        else
                fprintf(stderr,"%s: OK\n",where);
}







////////////////////////////////////////////////////////////
//
//   Thread which processes the incoming serial data.
//

void *ReaderThread(  )
{


   int rv;

   int i;
   const int bufsize = 32;
   unsigned char buf[bufsize];

   printf("\nEntered ReaderThread  \n");

   while ( 1 ) 
   {
      rv=ftdi_read_data(&ctx,buf,bufsize);
      if(rv<0) Error("read",rv,&ctx,1);
      else
      {
         printf("%3d: ",rv);
         for(i=0; i<rv; i++)
            printf("%02x%s",buf[i],i%8==7 ? i%16==15 ? "\n     " : "  " : " ");
      }
      printf("\n"); fflush(stdout);
   }

   return 0;

} // ReaderThread




////////////////////////////////////////////////////////////
//
//   Thread which writes serial data.
//

void *WriterThread(  )
{


   int rv;

   int i;
   const int bufsize = 16;
   unsigned char buf[bufsize];

   printf("\nEntered WriterThread  \n");



   //Fill TX buffer with some stuff
   for (i=0; i<bufsize; i++) {
      //buf[i] = 'c';
      // buf[i] = i;
      buf[i] = random();
   }



   while ( 1 ) 
   {

      //Fill TX buffer with some stuff
      for (i=0; i<bufsize; i++) {
         // buf[i] = 'c';
         // buf[i] = i;
         buf[i] = random();
      }



      rv=ftdi_write_data(&ctx,buf,bufsize);
      if(rv<0) Error("write",rv,&ctx,1);
   }

   return 0;

} // WriterThread





////////////////////////////////////////////////////////////
//
//   Main
//

int main() {


   
   int rv;
   int vendor=0x0403;
   int device=0x6001;

   int rc;


   pthread_t   readerThreadId;


   


   // Initialize
   rv=ftdi_init(&ctx);
   Error("init",rv,&ctx,0);


   // Open FTDI device with serial D44F6D5
   //rv=ftdi_usb_open_desc(&ctx, vendor, device, NULL , "D44F6D5");
   //rv=ftdi_usb_open_desc(&ctx, vendor, device, NULL , NULL);
   //rv=ftdi_usb_open_desc(&ctx, vendor, device, "TTL232R-3V3", "NULL");
   rv=ftdi_usb_open(&ctx,vendor,device);
   Error("open",rv,&ctx,0);


   // Reset
   rv=ftdi_usb_reset(&ctx);
   Error("reset",rv,&ctx,1);


   // Disable bitbang: will need the handshake lines connected or nothing will 
happen (short RTS and CTS)
   // Comment read in testusb.c 
   //...With bitbang mode disabled, hence you need to use the handshake 
signals. Otherwise, sending 
   // will stop with timeout and receiving will continuously read chunks of 
length 0

   rv=ftdi_disable_bitbang(&ctx);
   Error("bitbang(off)",rv,&ctx,1);


   // Set baudrate to 115200
   rv=ftdi_set_baudrate(&ctx,115200);
   Error("baudrate",rv,&ctx,1);


   // Set hardware flow control
   rv=ftdi_setflowctrl(&ctx,SIO_RTS_CTS_HS);
   //rv=ftdi_setflowctrl(&ctx,SIO_XON_XOFF_HS);
   Error("hardware_flow_control",rv,&ctx,1);



    // Read out FTDIChip-ID of R type chips
    if (ctx.type == TYPE_R) {
        unsigned int chipid;
        printf("ftdi_read_chipid: %d\n", ftdi_read_chipid(&ctx, &chipid));
        printf("FTDI chipid: %X\n", chipid);
    }



   //Kick off read thread
   rc = pthread_create( &readerThreadId, NULL, ReaderThread, NULL );
   if ( rc != 0 ) {
      fprintf( stderr, "Error creating ReaderThread: %s\n", strerror( rc ));
      exit( 7 );
   }

   printf("\nInside main function after kicking off ReaderThread \n");



   //Kick off write thread
   rc = pthread_create( &readerThreadId, NULL, WriterThread, NULL );
   if ( rc != 0 ) {
      fprintf( stderr, "Error creating WriterThread: %s\n", strerror( rc ));
      exit( 7 );
   }

   printf("\nInside main function after kicking off WriterThread \n");







   //for(i=0; i<10; i++) {
      //sleep(1);
   //}


   //keep main alive
   while ( 1 ) {
   }

}








Current Thread