Binary serial port read missing bytes in c - c

I am sending binary data from an arduino to a serial port where this code is running.
Using cutecom in hex mode can clearly read what I expect on that serial port. As shown below.
00000000: 24 04 85 ab 47 43 04 04 24 04 85 ab 47 43 04 04
00000010: 24 04 85 ab 47 43 04 04 24 04 85 ab 47 43 04 04
No problems up to here. I don't believe I need to give the arduino code.
I am trying to read the same thing with c. However the code below only prints this:
24 85 ab 47 43 24 85 ab 47 43 24 85 ab 47 43
For some reasons it is skipping the 04. Any ideas?
#include <stdio.h>
#include <fcntl.h> /* File Control Definitions */
#include <termios.h> /* POSIX Terminal Control Definitions */
#include <unistd.h> /* UNIX Standard Definitions */
#include <errno.h> /* ERROR Number Definitions */
#include <signal.h>
#include <string.h>
#include <stdint.h>
int open_serial(char *port, int baud);
void main(void)
{
int tty = open_serial("/dev/ttyUSB0", B115200);
uint8_t buff[256]; /* Buffer to store the data received */
int n; /* Number of bytes read by the read() system call */
while (1) {
n = read(tty, &buff, sizeof buff);
if (n > 0){
//printf("-%d-\n ", n);
for(int i=0;i<n;i++){
printf("%02x ", buff[i]);
}
fflush(stdout);
}
}
}
int open_serial(char *port, int baud)
{
int fd = open( port, O_RDWR | O_NOCTTY);
if(fd == -1) /* Error Checking */
printf("\n Error! in Opening tty ");
struct termios SerialPortSettings; /* Create the structure */
tcgetattr(fd, &SerialPortSettings); /* Get the current attributes of the Serial port */
/* Setting the Baud rate */
cfsetispeed(&SerialPortSettings,B115200); /* Set Read Speed as 115200 */
cfsetospeed(&SerialPortSettings,B115200); /* Set Write Speed as 115200 */
/* 8N1 Mode */
SerialPortSettings.c_cflag &= ~PARENB; /* Disables the Parity Enable bit(PARENB),So No Parity */
SerialPortSettings.c_cflag &= ~CSTOPB; /* CSTOPB = 2 Stop bits,here it is cleared so 1 Stop bit */
SerialPortSettings.c_cflag &= ~CSIZE; /* Clears the mask for setting the data size */
SerialPortSettings.c_cflag |= CS8; /* Set the data bits = 8 */
SerialPortSettings.c_cflag &= ~CRTSCTS; /* No Hardware flow Control */
SerialPortSettings.c_cflag |= CREAD | CLOCAL; /* Enable receiver,Ignore Modem Control lines */
SerialPortSettings.c_iflag &= ~(IXON | IXOFF | IXANY); /* Disable XON/XOFF flow control both i/p and o/p */
SerialPortSettings.c_iflag &= ~(ICANON | ECHO | ECHOE | ISIG); /* Non Cannonical mode */
SerialPortSettings.c_oflag &= ~OPOST;/*No Output Processing*/
/* Setting Time outs */
SerialPortSettings.c_cc[VMIN] = 10; /* Read at least 10 characters */
SerialPortSettings.c_cc[VTIME] = 0; /* Wait indefinetly */
if((tcsetattr(fd,TCSANOW,&SerialPortSettings)) != 0) /* Set the attributes to the termios structure*/
printf("\n ERROR ! in Setting attributes");
else
printf("\n BaudRate = 115200 StopBits = 1 Parity = none\n");
/*------------------------------- Read data from serial port -----------------------------*/
tcflush(fd, TCIFLUSH); /* Discards old data in the rx buffer */
return fd;
}

I am sending binary data from an arduino to a serial port where this code is running.
Transmission of binary data necessitates that the POSIX serial terminal be configured for non-canonical (aka raw) mode.
For some reasons it is skipping the 04. Any ideas?
Consistent loss of data that have values in the range of ASCII control characters (i.e. 0x00 through 0x1F) almost always indicates improper termios configuration.
Since the data loss seems to be on the reception side, the first thing to verify is the proper specification of non-canonical input mode.
Your code has
SerialPortSettings.c_iflag &= ~(ICANON | ECHO | ECHOE | ISIG); /* Non Cannonical mode */
The attributes on the right-hand side of the assignment all belong to the c_lflag of the termios structure, rather than the c_iflag that is coded.
So presumably the default mode of the serial terminal is canonical mode, and your program fails to reconfigure to non-canonical input mode because of this typo.
Your workaround of augmenting your code with a cfmakeraw() call is not ideal.
The use of cfmakeraw() is convenient for avoiding mistakes like the one you have.
But the buggy statement should be corrected, or even better the operations that are made redundant by the cfmakeraw() call can be removed.
cfmakeraw() sets the terminal to something like the "raw" mode of the old
Version 7 terminal driver: input is available character by character, echoing is
disabled, and all special processing of terminal input and output characters is
disabled. The terminal attributes are set as follows:
termios_p->c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP
| INLCR | IGNCR | ICRNL | IXON);
termios_p->c_oflag &= ~OPOST;
termios_p->c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
termios_p->c_cflag &= ~(CSIZE | PARENB);
termios_p->c_cflag |= CS8;
BTW your code does use the recommended/preferred method of calling tcgetattr(), and then setting/modifying the terminal attributes using Boolean operations. The suggestion of using a "clean struc" is not considered portable.
ADDENDUM
The origin of this c_iflag and ICANON bug seems to be this serial port tutorial from xanthium.in. The author was notified back in 2016 of the bug, but has not bothered to fix it.

Got it to work adding
cfmakeraw(&SerialPortSettings);
just above the tcsetattr function call.

Related

Data from serial port only displayed when cable is unplugged

I am trying to read data from serial port sent by RS232 module using :
A USB - SERIAL converter
A C program and the lib TERMIOS (Which worked perfectly ; I can read and send data in real time).
A Linux environment
Now, I'm trying to do the exact same thing but using directly the serial port of my device and not the USB port.
With the same configuration (except I change the device from tty USB0 to tty mxc2 and using a RS232 cable only not the USB - SERIAL converter). I can't get the data but when I unplug the RS232 cable, all the data I try to read is received and printed to the terminal.
I also tried to use stty directly to read (thinking it was a C problem) but I get the same result (I unplug the RS232 cable & the data is read)
I can not explain why there is a delta between using USB - RS232 converter and using only RS232 cable.
//configuration of TERMIOS :
tty.c_cflag |= (CLOCAL | CREAD); /* ignore modem controls */
tty.c_cflag &= ~CSIZE;
tty.c_cflag |= CS8; /* 8-bit characters */
tty.c_cflag &= ~PARENB; /* no parity bit */
tty.c_cflag &= ~(CSTOPB | CRTSCTS); /* only need 1 stop bit & no hardware flowcontrol */
/* setup for non-canonical mode */
tty.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
tty.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
tty.c_oflag &= ~OPOST;
tty.c_cc[VMIN] = 0;
tty.c_cc[VTIME] = 0;
//trying to read with termios :
retlen = read(fd,&tmp_buff,1);
if (retlen > 0)
printf("%02x\n",tmp_buff);
here are some result and output from terminal that may help :
When the cable is plugged the data are not displayed
root#2021ufv6zgzg:~# ./main.exe
When the cable is unplugged the data are displayed
root#2021ufv6zgzg:~# ./main.exe
00
fe
00
fe
00
fe
00
fe
Same goes with only stty, data displayed when I unplug the cable :
od -x < /dev/ttymxc2
0003260 fe00 fe00 fe00 fe00 fe00 fe00 fe00 fe00
Thank you very much for your help. Even though you can not find the solution, i'd really like to know the differences between using tty USB0 and tty mxc2.

Linux Reading Data from UART

I want to read data from UART, i followed this tutorial, the write function works as expected, however i'am getting problem with the read function :
This is the uart_init function:
void uart_init()
{
printf("\n +----------------------------------+");
printf("\n | Serial Port Write |");
printf("\n +----------------------------------+");
/*------------------------------- Opening the Serial Port -------------------------------*/
fd = open("/dev/ttyUSB0",O_RDWR | O_NOCTTY| O_SYNC); /* !!blocks the read */
/* O_RDWR Read/Write access to serial port */
/* O_NOCTTY - No terminal will control the process */
/* O_NDELAY -Non Blocking Mode,Does not care about- */
/* -the status of DCD line,Open() returns immediatly */
if(fd == -1) /* Error Checking */
printf("\n Error! in Opening ttyUSB0 ");
else
printf("\n ttyUSB0 Opened Successfully ");
/*---------- Setting the Attributes of the serial port using termios structure --------- */
struct termios SerialPortSettings; /* Create the structure */
tcgetattr(fd, &SerialPortSettings); /* Get the current attributes of the Serial port */
cfsetispeed(&SerialPortSettings,B19200); /* Set Read Speed as 19200 */
cfsetospeed(&SerialPortSettings,B19200); /* Set Write Speed as 19200 */
SerialPortSettings.c_cflag &= ~PARENB; /* Disables the Parity Enable bit(PARENB),So No Parity */
SerialPortSettings.c_cflag &= ~CSTOPB; /* CSTOPB = 2 Stop bits,here it is cleared so 1 Stop bit */
SerialPortSettings.c_cflag &= ~CSIZE; /* Clears the mask for setting the data size */
SerialPortSettings.c_cflag |= CS8; /* Set the data bits = 8 */
SerialPortSettings.c_cflag &= ~CRTSCTS; /* No Hardware flow Control */
SerialPortSettings.c_cflag |= CREAD | CLOCAL; /* Enable receiver,Ignore Modem Control lines */
SerialPortSettings.c_iflag &= ~(IXON | IXOFF | IXANY); /* Disable XON/XOFF flow control both i/p and o/p */
SerialPortSettings.c_iflag &= ~(ICANON | ECHO | ECHOE | ISIG); /* Non Cannonical mode */
SerialPortSettings.c_oflag &= ~OPOST;/*No Output Processing*/
/* Setting Time outs */
SerialPortSettings.c_cc[VMIN] = 10; /* Read at least 10 characters */
SerialPortSettings.c_cc[VTIME] = 0; /* Wait indefinetly */
if((tcsetattr(fd,TCSANOW,&SerialPortSettings)) != 0) /* Set the attributes to the termios structure*/
printf("\n ERROR ! in Setting attributes");
else
printf("\n BaudRate = 19200 \n StopBits = 1 \n Parity = none");
}
the receive function :
void uart_receive()
{
char read_buffer[32]; /* Buffer to store the data received */
int bytes_read = 0; /* Number of bytes read by the read() system call */
int i = 0;
bytes_read = read(fd,&read_buffer,10); /* Read the data */
printf("\n\n Bytes Rxed %d", bytes_read); /* Print the number of bytes read */
printf("\n\n ");
for(i=0;i<bytes_read;i++) /*printing only the received characters*/
printf("%c",read_buffer[i]);
printf("\n +----------------------------------+\n\n\n");
}
the main function :
void main(void)
{
uart_init();
/*------------------------------- Write data to serial port -----------------------------*/
//uart_write_commande(write_buffer); //Write function works well
uart_receive();
close(fd);/* Close the Serial port */
}
I execute the program and wait for data bytes to be received in UART, i send data using UART but the read function keeps blocked.
I'am using a Virtual machine with Ubunutu 14.04 on it, and i'am not sure that using an emulated UART can cause problems during reception.
Your program is hanging in the read() syscall because it is blocked waiting for a line-termination character.
You tried to configure the port for non-canonical mode with the statement
SerialPortSettings.c_iflag &= ~(ICANON | ECHO | ECHOE | ISIG); /* Non Cannonical mode
but that operation is on the wrong termios element.
The ICANON attribute is part of the lflag element (and not the iflag). (This error originates from the tutorial you referenced!)
Therefore your program is performing blocking canonical reads.
There's a convenient termios function for configuring non-canonical mode:
cfmakeraw() sets the terminal to something like the "raw" mode of the old
Version 7 terminal driver: input is available character by
character, echoing is disabled, and all special processing of
terminal input and output characters is disabled. The terminal
attributes are set as follows:
termios_p->c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP
| INLCR | IGNCR | ICRNL | IXON);
termios_p->c_oflag &= ~OPOST;
termios_p->c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
termios_p->c_cflag &= ~(CSIZE | PARENB);
termios_p->c_cflag |= CS8;
There's an error in the read function
bytes_read = read(fd,&read_buffer,10); /* Read the data
should be
bytes_read = read(fd,read_buffer,10); /* Read the data
Your read() function may be blocked, for whatever reason. Here is a discussion on reading from a serial port, including code for blocked/unblocked settings.
It may also be possible that there is no data being transferred, leading to nothing being read. Without having access to the hardware setup, it is difficult to go further without very specific information about what you are seeing.
Also, in addition to passing the read_buffer correctly (another answer), there are at least two additional things that may improve:
1) check the return of read before using it:
bytes_read = read(fd,&read_buffer,10); /* Read the data*/
if(bytes_read > 0)
{
...
}
2) Change:
for(i=0;i<bytes_read;i++) /*printing only the received characters*/
printf("%c",read_buffer[i]);
To:
//after successful read:
read_buffer[bytes_read]=0;//place null termination after last character read.
printf("%s",read_buffer);//note format specifier
This will print the number of characters read, without the loop.

Program hangs when setting serial port parameters

In my program a connection is opened with serial port that recieves 10-byte packages with set frequency (usually 100 Hz). However i have run into the following problem: sometimes (but not always) when i am closing connection, the program hangs.
In the following code i do not specify constants; at runtime connection parameters (baud rate, parity...) are determined from command line. In practice, connection is usually opened with baud rate 230400, no parity, 8-bit character size and 1 stop bit.
This is how i am opening serial port:
struct termios config;
LOGPRINT("Will operate on device \'%s\'\n", pconfig->device);
LOGPRINT("Opening serial device\n");
int flag = O_RDWR | O_NOCTTY | ASYNC_LOW_LATENCY;
// pconfig contains some necessary information to set connection parameters
// async == false for connectin that causes problems
int fd = open(pconfig->device, async? flag | O_NONBLOCK: flag);
if(fd == -1)
{ /* skipped error handling */ }
LOGPRINT("Retrieving terminal attributes\n");
if(!!tcgetattr(fd, &config))
{ /* skipped error handling */ }
else
{
// backup old configuration for restoring it on exit
if(poldconfig != NULL)
memcpy(poldconfig, &config, sizeof(struct termios));
LOGPRINT("Setting terminal attributes\n");
set_attribs(fd, &config, pconfig);
}
...
int set_attribs(const int fd, struct termios* pterm, const struct serial_config* pconfig)
{
// set baud rate
// baud_rates contains integers of actual rates
LOGPRINT("Setting baud rate to %d.\n", baud_rates[pconfig->baud_rate_index]);
// change to raw mode
LOGPRINT("Setting terminal to raw mode\n");
pterm->c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR
| IGNCR | ICRNL | IXON);
pterm->c_oflag &= OPOST;
pterm->c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
// baud_bits contains actual pre-defined baud rate flags
cfsetispeed(pterm, baud_bits[pconfig->baud_rate_index]);
cfsetospeed(pterm, baud_bits[pconfig->baud_rate_index]);
LOGPRINT("Set character size, parity and stop bit flags.\n");
// set character size
pterm->c_cflag &= ~CSIZE;
pterm->c_cflag |= pconfig->csize_flag;
// set parity
pterm->c_cflag &= ~(PARENB | PARODD);
pterm->c_cflag |= pconfig->parity_flag;
// set stopbits
pterm->c_cflag &= ~CSTOPB;
pterm->c_cflag |= pconfig->stopbits_flag;
// enable reading; ignore control lines
pterm->c_cflag |= CREAD | CLOCAL;
LOGPRINT("Flush terminal.\n");
// flush terminal
tcflush(fd, TCIOFLUSH);
LOGPRINT("Apply parameters.\n");
return tcsetattr(fd, TCSANOW, pterm);
}
For valid reasons, i needed to force serial device driver to use 1-byte buffer for incoming/outgoing data, which i have set using this function:
int set_port_type(int fd, int ptype)
{
struct serial_struct temp;
int res = ioctl(fd, TIOCGSERIAL, &temp);
if(!!res)
{ /* stipped error handling */ }
temp.type = ptype;
res = ioctl(fd, TIOCSSERIAL, &temp);
if(!!res)
{ /* stipped error handling */ }
return res;
}
with ptype = PORT_UNKNOWN or ptype = PORT_16450.
When finished with serial port, i perform the following operations:
Flush it
Set its type back to 16550A
Restore its settigns to saved ones
Close it
From time to time it causes the program to hang and stop responding to any external stimulus. It forces me to suspend the program and then reboot system, as it never releases file descriptors it holds.
What can i do to ensure that does not happen? Even if settings are not restored, the program needs to close on its own - maybe with error code.
Operating system i am using is TinyCore Linux. No other user program is being run an the same time as my program.
IMportant clarification. Serial device i am working with is actually NPort 5232 - asyncronous RS-422/485 - Ethernet communicator (description from vendor. Consequently, serial devices i am working with are virtual, which enables me to try and change their type / size of internal buffer.

How to recieve data on serial port synchronously?

I have the following set up: a computer that runs Linux (TCL) and device that sends packets of fixed length (10 bytes) with fixed frequency (100 Hz).
On computer, i have that serial port open, and i am trying to read incoming data. However, instead of recieving it in 10-byte chunks all the time, lesser amounts of data are being read, and i am forced to reassemble them back.
My goal is to send a responce for each packet once it arrives, preserving intervals between packets as much as possible.
This is how i open the serial port:
int fd = open(device_name, O_RDWR | O_NOCTTY | O_NONBLOCK);
if(fd == -1)
{
LOGPRINT("Failed to open terminal file.\nError #%d (%s)\n",
errno, strerror(errno));
return fd;
}
LOGPRINT("Setting terminal attributes\n");
struct termios config;
struct termios *pterm = &config;
// set baud rate
LOGPRINT("Setting baud rate to %d.\n", baud_rates[baud_rate_index]);
// change to raw mode
LOGPRINT("Setting terminal to raw mode\n");
pterm->c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR
| IGNCR | ICRNL | IXON);
pterm->c_oflag &= OPOST;
pterm->c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
cfsetispeed(pterm, baud_bits[pconfig->baud_rate_index]);
cfsetospeed(pterm, baud_bits[pconfig->baud_rate_index]);
LOGPRINT("Set character size, parity and stop bit flags.\n");
// set character size
pterm->c_cflag &= ~CSIZE;
pterm->c_cflag |= csize_flag;
// set parity
pterm->c_cflag &= ~(PARENB | PARODD);
pterm->c_cflag |= parity_flag;
// set stopbits
pterm->c_cflag &= ~CSTOPB;
pterm->c_cflag |= stopbits_flag;
// enable reading; ignore control lines
pterm->c_cflag |= CREAD | CLOCAL;
// disable flow control
pterm->c_cc[VMIN] = 1;
pterm->c_cc[VTIME] = 0;
LOGPRINT("Flush terminal.\n");
// flush terminal
tcflush(fd, TCIOFLUSH);
LOGPRINT("Apply parameters.\n");
return WRAPSYSCALL(tcsetattr(fd, TCSANOW, pterm));
Additionally i set the following on file descriptor with fnctl:
int flags = fcntl(fd, F_GETFL);
fcntl(fd, F_SETFL, flags | FASYNC | O_DIRECT);
I am reading from file descriptor in a cycle with select() call on file descriptor set containing fd, then reading all bytes avaiable (requesting number of bytes much bigger then 10).
What should i change to ensure incoming data are processed as they come properly, in timely manner?
If your program does nothing else than waiting for bytes and answering, then you can try using blocking file operations. Remove O_NONBLOCK flag from your open function call, and after setting the port just do a read(fd, buffer, 10). The function will return after it reads exactly 10 bytes (or an error happens or signal arrives).
However, bear in mind that you read operation can start in the middle of packet transmission, so for example you can get last x bytes of n-th packet and first 10-x of packet n+1.

Sending files over serial port

I need some help sending a file over a serial connection. I have two RS232 to USB cables, and I am testing out my code by using one to send data, and the other to receive it. I have them both physically connected to each other.
So I wrote some code adapted from a few sources, and I can successfully transfer a series of characters. One program receives the data, the other sends it. I have these two open in two separate terminals. Find the two blocks of code below:
serialout.c
#include <stdio.h> /* Standard input/output definitions */
#include <string.h> /* String function definitions */
#include <unistd.h> /* UNIX standard function definitions */
#include <fcntl.h> /* File control definitions */
#include <errno.h> /* Error number definitions */
#include <termios.h> /* POSIX terminal control definitions */
int main()
{
//writing
int writeport = open_port("/dev/ttyUSB0");
char str[] = "hello how are you?";
int n = write(writeport, str, strlen(str));
if (n < 0)
fputs("write() of bytes failed!\n", stderr);
//closing ports
close(writeport);
}
int open_port(char str[])
{
int fd = open(str, O_RDWR | O_NOCTTY | O_NONBLOCK); // ?? NDELAY or NONBLOCK?
if (fd == -1)
{
perror("open_port: Unable to open /dev/ttyS0 - ");
}
else
fcntl(fd, F_SETFL, 0);
struct termios options;
tcgetattr(fd, &options); //this gets the current options set for the port
// setting the options
cfsetispeed(&options, B9600); //input baudrate
cfsetospeed(&options, B9600); // output baudrate
options.c_cflag |= (CLOCAL | CREAD); // ?? enable receicer and set local mode
//options.c_cflag &= ~CSIZE; /* mask the character size bits */
options.c_cflag |= CS8; /* select 8 data bits */
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // choosing raw input
options.c_iflag &= ~INPCK; // disable parity check
options.c_iflag &= ~(IXON | IXOFF | IXANY); // disable software flow control
options.c_oflag |= OPOST; // ?? choosing processed output
options.c_cc[VMIN] = 0; // Wait until x bytes read (blocks!)
options.c_cc[VTIME] = 0; // Wait x * 0.1s for input (unblocks!)
// settings for no parity bit
options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB;
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8;
tcsetattr(fd, TCSANOW, &options); //set the new options ... TCSANOW specifies all option changes to occur immediately
return (fd);
}
serialin.c
#include <stdio.h> /* Standard input/output definitions */
#include <string.h> /* String function definitions */
#include <unistd.h> /* UNIX standard function definitions */
#include <fcntl.h> /* File control definitions */
#include <errno.h> /* Error number definitions */
#include <termios.h> /* POSIX terminal control definitions */
int main()
{
//reading
int readport = open_port("/dev/ttyUSB1");
//trying to read one character at a time
char buff;
int n = 1;
while (n > 0)
{
n = read(readport, &buff, 1);
printf("%c", buff, buff);
}
printf("\n");
//closing ports
close(readport);
}
int open_port(char str[])
{
int fd = open(str, O_RDWR | O_NOCTTY | O_NONBLOCK); // ?? NDELAY or NONBLOCK?
if (fd == -1)
{
perror("open_port: Unable to open /dev/ttyS0 - ");
}
else
fcntl(fd, F_SETFL, 0);
struct termios options;
tcgetattr(fd, &options); //this gets the current options set for the port
// setting the options
cfsetispeed(&options, B9600); //input baudrate
cfsetospeed(&options, B9600); // output baudrate
options.c_cflag |= (CLOCAL | CREAD); // ?? enable receicer and set local mode
//options.c_cflag &= ~CSIZE; /* mask the character size bits */
options.c_cflag |= CS8; /* select 8 data bits */
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // choosing raw input
options.c_iflag &= ~INPCK; // disable parity check
options.c_iflag &= ~(IXON | IXOFF | IXANY); // disable software flow control
options.c_oflag |= OPOST; // ?? choosing processed output
options.c_cc[VMIN] = 0; // Wait until x bytes read (blocks!)
options.c_cc[VTIME] = 0; // Wait x * 0.1s for input (unblocks!)
// settings for no parity bit
options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB;
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8;
tcsetattr(fd, TCSANOW, &options); //set the new options ... TCSANOW specifies all option changes to occur immediately
return (fd);
}
So what I'd like to do is send a file. For example, a jpeg file. Is there some way to convert it to bytecode and reassemble it as a jpeg? I have searched around but have found little relevant information unfortunately - maybe I'm searching the wrong terms.
Even better would be to send the files after they are zipped. Ultimately, I am using gzip to zip jpeg files, then send them over the serial connection. Thanks everyone!
If you want to transfer files, you should break the file up into chunks, and use a checksum on each chunk; then verify the checksums as you rejoin the chunks on the other side.
This is not a new problem. Others have solved it for you. You should get an existing reliable file-transfer program and run it over the serial link.
The top choice would be rsync. That is GPL, so the license may keep you from using it if you are doing proprietary work.
Another good choice would be XMODEM (or YMODEM or ZMODEM). I found a C implementation of XMODEM with a BSD license, so you can use this for sure. This is also smaller and simpler than rsync.
http://www.menie.org/georges/embedded/#xmodem
http://en.wikipedia.org/wiki/XMODEM
I was also going to suggest Z-Modem or X-Modem for file transferring. But what you've got to understand is that there's nothing special about files. As far as the transferring computer and receiving terminal are concerned, the file being sent is just a stream of binary data, no matter if it's a jpeg image, a compressed file or just a text file.
All you've got to do is write the incoming stream into a file an make sure it has the right extension so it can be properly handled.
The transfer protocols mentioned above only add layers to ensure the whole file is being sent and that it is not corrupted, but you can dismiss them on a first instance to understand the concept.

Resources