Home arrow Support arrow Forums

Luminary Micro Forums

taudas

Fresh Boarder

2006/11/26 22:25

how to listen to uart_out on linux?

i've got uart_out.c running using openocd on debian host.
where is that data going? i mean, how do i read that data stream on the usb-connected host?

login or register to reply

magnuslundinse

Gold Boarder

2006/11/27 13:37

Re:how to listen to uart_out on linux?

This is for the ev-lm3s811 board

The simple (and incomplete) answer is to load the ftdi_sio module with parameters vendor=0x0403 product=0xbcd9.

As root, remove and reload the module, or put this in an init script:
/sbin/rmmod ftdi_sio
/sbin/modprobe ftdi_sio vendor=0x0403 product=0xbcd9

Check the result with dmesg, you will see that two USB serial ports are added, corresponding to portA and port B of the ftdi2232 chip on the eval board. The second one, port B, is connected to the Uart on the LM3S811 chip.
I use ckermit to connect (assuming the second USB serial port is /dev/ttyUSB1 )

kermit -C "set line /dev/ttyUSB1,set speed 115200,set modem type none,set flow none,set carrier-watch off,connect"
Push the reset button and watch the greeting :)


The problem is that the JTAG port is now seen as a serial port and cannot be used by other tools (such as OpenOCD) without unloading the ftdi_sio driver module or disconnecting interface 0 from the serial driver (see below).

Two solutions are now possible:
Unload ftdi_sio, start OpenOCD to claim interface 0, then load (modprobe) ftdi_sio. The serial device is now probably /dev/ttyUSB0 since port A is already in use by openocd and not loaded by the serail driver. When there is a USB bus reset this probably has to be redone.

Method two is to write a small utitlity that opens the ft2232 device with libusb and then releases interface 0 with the usb_detach_kernel_driver_np call.

Yes it is a bit of a hassle, but handling ftdi drivers under windows is also a pain.

login or register to reply

saa

Fresh Boarder

2007/05/08 05:56

Re:how to listen to uart_out on linux?

On OS X, I ended up writing an application that used the FTDI D2XX library to send and receive data from the UART. I think it should work on Linux with minimal changes. I was thinking of working this into the openocd daemon so you could telnet to a local port to get to the port, but wasn't sure if that would be considered a good thing.

Feel free to hack/slash/copy/ship this code in whatever manner you like.

Code:

  #include <pthread.h> #include <signal.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <termios.h> #include <unistd.h> #include <sys/errno.h> #include <sys/stat.h> #include <sys/types.h> #include <sys/uio.h> #include <ftd2xx.h> // Seems like this sort of stuff should have been provided by FTDI static const char *ft_errors[] = {     [FT_OK] = "Success",     [FT_INVALID_HANDLE] = "Invalid device handle",     [FT_DEVICE_NOT_FOUND] = "Device not found",     [FT_DEVICE_NOT_OPENED] = "Device not opened",     [FT_IO_ERROR] = "Input/output error",     [FT_INSUFFICIENT_RESOURCES] = "Insufficient resources",     [FT_INVALID_PARAMETER] = "Invalid parameter",     [FT_INVALID_BAUD_RATE] = "Invalid baud rate",     [FT_DEVICE_NOT_OPENED_FOR_ERASE] = "Device not opened for erase",     [FT_DEVICE_NOT_OPENED_FOR_WRITE] = "Device not opened for write",     [FT_FAILED_TO_WRITE_DEVICE] = "Failed to write device",     [FT_EEPROM_READ_FAILED] = "EEPROM read failed",     [FT_EEPROM_WRITE_FAILED] = "EEPROM write failed",     [FT_EEPROM_ERASE_FAILED] = "EEPROM erase failed",     [FT_EEPROM_NOT_PRESENT] = "EEPROM not present",     [FT_EEPROM_NOT_PROGRAMMED] = "EEPROM not programmed",     [FT_INVALID_ARGS] = "Invalid argument",     [FT_NOT_SUPPORTED] = "Not supported",     [FT_OTHER_ERROR] = "Other error" }; static const int num_ft_errors sizeof(ft_errors) / sizeof(ft_errors[FT_OK]); static const char *ft_strerror(FT_STATUS ft_status) {     if (ft_status 0        // Should be impossible because it is unsigned     || ft_status >= num_ft_errors     || !ft_errors[ft_status])     {     return "Unknown error";     }     return ft_errors[ft_status]; } static void ft_error_exit(const char *strFT_STATUS ft_status) {     if (str && *str)     fprintf(stderr"%s: %sn"strft_strerror(ft_status));     else     fprintf(stderr"%sn"ft_strerror(ft_status));     exit(1); } static void std_error_exit(const char *str) {     perror(str);     exit(1); } static void pthread_error_exit(const char *strint err) {     if (str && *str)     fprintf(stderr"%s: %sn"strstrerror(err));     else     fprintf(stderr"%sn"strerror(err));     exit(1); } static FT_HANDLE ft_handle; // Registered with atexit() static void cleanup_ft_handle(void) {     (void)FT_Close(ft_handle); } static struct termios saved_termios; // Registered with atexit() static void cleanup_termios(void) {     if (tcsetattr(STDIN_FILENOTCSAFLUSH TCSASOFT, &saved_termios))     std_error_exit("tcsetattr restore"); } // Reader thread function static void *reader_func(void *arg) {     FT_STATUS ft_status;     EVENT_HANDLE eh;     DWORD chars_in_q;     char buf[1024];     int pterr;     if ((pterr pthread_mutex_init(&eh.eMutexNULL)))     pthread_error_exit("pthread_mutex_init"pterr);     if ((pterr pthread_cond_init(&eh.eCondVarNULL)))     pthread_error_exit("pthread_cond_init"pterr);     if ((ft_status FT_SetEventNotification(ft_handleFT_EVENT_RXCHAR,                          (PVOID)&eh)) != FT_OK)     ft_error_exit("FT_SetEventNotification"ft_status);     for (;;)     {     if ((pterr pthread_mutex_lock(&eh.eMutex)))         pthread_error_exit("pthread_mutex_lock"pterr);     if ((ft_status FT_GetQueueStatus(ft_handle, &chars_in_q)) != FT_OK)         ft_error_exit("FT_GetQueueStatus"ft_status);     if (chars_in_q == 0)     {         if ((pterr pthread_cond_wait(&eh.eCondVar, &eh.eMutex)))         pthread_error_exit("pthread_cond_wait"pterr);         if ((ft_status FT_GetQueueStatus(ft_handle,                            &chars_in_q)) != FT_OK)         ft_error_exit("FT_GetQueueStatus"ft_status);     }     if ((pterr pthread_mutex_unlock(&eh.eMutex)))         pthread_error_exit("pthread_mutex_unlock"pterr);     while (chars_in_q)     {         DWORD len_to_readlen_read;         ssize_t len_written;         len_to_read = (chars_in_q sizeof(buf)) ? sizeof(buf) : chars_in_q;         // Read from the Evaluation Board         if ((ft_status FT_Read(ft_handle, (LPVOID)buf,                      len_to_read, &len_read)) != FT_OK)         ft_error_exit("FT_Read"ft_status);         if (!len_read)         {         fprintf(stderr"FT_Read returned no data.n");         exit(1);         }         while (len_read)         {         // Write to stdout         len_written write(STDOUT_FILENObuflen_read);         if (len_written == -1)             std_error_exit("fwrite");         len_read -= len_written;         }         chars_in_q -= len_read;     }     }     return NULL; } // Writer thread function static void *writer_func(void *arg) {     char buf[1024];     ssize_t len_read;     FT_STATUS ft_status;     DWORD len_written;     do     {     len_read read(STDIN_FILENObufsizeof(buf));     switch (len_read) {     case 0:         // EOF         break;     case -1:         // Error         std_error_exit("fread");         break;     default:         // Got some bytes.         if ((ft_status FT_Write(ft_handle, (LPVOID)buf,                       len_read, &len_written)) != FT_OK)         ft_error_exit("FT_Write"ft_status);         if (len_read != len_written)         {         fprintf(stderr"FT_Write did not write all the data.n");         exit(1);         }         break;     }     } while (len_read);     return NULL; } // Main event int main(int argcchar **argv) {     FT_STATUS ft_status;     // Add the VID/PID for the Luminary Micro LM3S811 Evaluation Board     if ((ft_status FT_SetVIDPID(0x04030xBCD9)) != FT_OK)     ft_error_exit("FT_SetVIDPID"ft_status);     // Open up the second port of the Luminary board.  The first port is JTAG.     if ((ft_status FT_OpenEx("LM3S811 Evaluation Board B",                 FT_OPEN_BY_DESCRIPTION, &ft_handle)) != FT_OK)     ft_error_exit("FT_OpenEx"ft_status);     // Ensure the handle gets closed per FTDI's D2XX OS X release notes     if (atexit(cleanup_ft_handle))     std_error_exit("atexit");     // 115200, 8N1, no flow control     if ((ft_status FT_SetBaudRate(ft_handle115200)) != FT_OK)     ft_error_exit("FT_SetBaudRate"ft_status);     if ((ft_status FT_SetDataCharacteristics(ft_handle,                            FT_BITS_8,                            FT_STOP_BITS_1,                            FT_PARITY_NONE)) != FT_OK)     ft_error_exit("FT_SetDataCharacteristics"ft_status);     if ((ft_status FT_SetFlowControl(ft_handle,                        FT_FLOW_NONE00)) != FT_OK)     ft_error_exit("FT_SetFlowControl"ft_status);     // Flush the FTDI's buffers     if ((ft_status FT_Purge(ft_handleFT_PURGE_RX FT_PURGE_TX)) != FT_OK)     ft_error_exit("FT_Purge"ft_status);     // Turn off buffering on stdout     (void)setvbuf(stdoutNULL_IONBF0);     // If stdin and stdout refer to the same tty, set the tty to raw     struct stat stdin_sbstdout_sb;     if (fstat(STDIN_FILENO, &stdin_sb))     std_error_exit("fstat stdin");     if (fstat(STDOUT_FILENO, &stdout_sb))     std_error_exit("fstat stdout");     if ((stdin_sb.st_mode S_IFCHR)     && stdin_sb.st_ino == stdout_sb.st_ino     && stdin_sb.st_dev == stdout_sb.st_dev)     {     if (!tcgetattr(STDIN_FILENO, &saved_termios))     {         if (atexit(cleanup_termios))         std_error_exit("atexit");         struct termios tios saved_termios;         cfmakeraw(&tios);         tios.c_lflag |= ISIG;         tios.c_cc[VINTR] = '03';        // ^c for now         tios.c_cc[VQUIT] = _POSIX_VDISABLE;         tios.c_cc[VSUSP] = _POSIX_VDISABLE;         tios.c_cc[VMIN] = 1;         tios.c_cc[VTIME] = 0;         if (tcsetattr(STDIN_FILENOTCSANOW TCSASOFT, &tios))         std_error_exit("tcsetattr stdin");     }     else if (errno != ENODEV)         std_error_exit("tcgetattr stdin");     }     // Mask all allowed signals because after we kick off our     // reader and writer threads, we'll just wait for the signals.     sigset_t sig_set;     (void)sigfillset(&sig_set);     int pterr;     if ((pterr pthread_sigmask(SIG_BLOCK, &sig_setNULL)))     pthread_error_exit("pthread_sigmask"pterr);     // Create reader and writer threads.     pthread_attr_t ptattr;     if ((pterr pthread_attr_init(&ptattr)))     pthread_error_exit("pthread_attr_init"pterr);     if ((pterr pthread_attr_setdetachstate(&ptattr,                          PTHREAD_CREATE_DETACHED)))     pthread_error_exit("pthread_attr_setdetachstate"pterr);     pthread_t reader_idwriter_id;     if ((pterr pthread_create(&reader_id, &ptattrreader_funcNULL)))     pthread_error_exit("pthread_create reader"pterr);     if ((pterr pthread_create(&writer_id, &ptattrwriter_funcNULL)))     pthread_error_exit("pthread_create writer"pterr);     // Now wait for a signal to terminate us     int caught_sig;     if (sigwait(&sig_set, &caught_sig))     std_error_exit("sigwait");     exit(0); } 

login or register to reply