Process that can sleep waiting for a tty driver protocol RX - c

My aim is to have a user space linux process that sleep while a tty uart based driver is receiving a message.
The protocol is a very simple (bad) stream of data that starts with a break signal followed by 513 bytes.
So far I modified the freescale's tty uart driver interrupt to receive the message.
static int DMX_RX(struct imx_port *sport)
{
struct tty_port *port = &sport->port.state->port;
tty_flip_buffer_push(port);
struct uart_state *state = sport->port.state;
if (sport->port.flags & UPF_SAK)
do_SAK(state->port.tty);
return 0;
}
static irqreturn_t imx_rxint(int irq, void *dev_id)
{
struct imx_port *sport = dev_id;
unsigned int rx, flg, ignored = 0;
struct tty_port *port = &sport->port.state->port;
unsigned long flags, temp;
spin_lock_irqsave(&sport->port.lock, flags);
while (readl(sport->port.membase + USR2) & USR2_RDR)
{
flg = TTY_NORMAL;
sport->port.icount.rx++;
rx = readl(sport->port.membase + URXD0);
temp = readl(sport->port.membase + USR2);
if (temp & USR2_BRCD)
{
writel(USR2_BRCD, sport->port.membase + USR2);
// Break received then push the message to userspace
DMX_RX(sport);
}
else
{
// Byte received then put it in the flip buffer
tty_insert_flip_char(port, rx, flg);
}
.....
// other stuff
.....
out:
spin_unlock_irqrestore(&sport->port.lock, flags);
return IRQ_HANDLED;
}
Then I implemented a simple process on linux user space as below:
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <linux/termios.h>
#include <sched.h>
int ioctl(int d, int request, ...);
#define MAX_DATA_LOG 1000
int main(int argc, char *argv[])
{
struct termios2 t;
int fd,baud;
char buf[513];
fd = open("/dev/ttyDMXc4", O_RDONLY | O_NOCTTY | O_NDELAY);
baud = 250000;
if (ioctl(fd, TCGETS2, &t))
{
perror("TCGETS2");
return 3;
}
t.c_cflag &= ~CBAUD;
t.c_cflag |= BOTHER;
t.c_cflag |= CSTOPB;
t.c_ospeed = baud;
t.c_lflag &= ~(ICANON | ISIG | IEXTEN | ECHO);
/* Noncanonical mode, disable signals, extended
input processing, and echoing */
t.c_iflag &= ~(BRKINT | ICRNL | IGNBRK | IGNCR | INLCR |
INPCK | ISTRIP | IXON | PARMRK);
/* Disable special handling of CR, NL, and BREAK.
No 8th-bit stripping or parity error handling.
Disable START/STOP output flow control. */
t.c_oflag &= ~OPOST; /* Disable all output processing */
if (ioctl(fd, TCSETS2, &t))
{
perror("TCSETS2");
return 4;
}
if (ioctl(fd, TCGETS2, &t))
{
perror("TCGETS2");
return 5;
}
printf("actual speed reported %d\n", t.c_ospeed);
typedef struct {
unsigned long time;
unsigned int res;
}stuct_appo;
int ret = 1;
int res;
int i;
fd_set read_fds;
struct timeval tv;
int data_log_idx=1;
stuct_appo data_log[MAX_DATA_LOG];
struct timespec now;
while (1)
{
tv.tv_sec = 1;
tv.tv_usec = 0;
FD_ZERO(&read_fds);
FD_SET(fd, &read_fds);
ret = select (fd+1, &read_fds, NULL, NULL, &tv);
if (ret > 0)
{
res = read (fd, buf, 513);
if (res > 0)
{
clock_gettime(0, &now);
data_log[data_log_idx].time = now.tv_nsec;
data_log[data_log_idx].res = res;
data_log_idx = (data_log_idx % MAX_DATA_LOG) + 1;
}
}
else
{
int i;
printf("TIMEOUT %d!!!\n", ret);
for (i=1; i<data_log_idx; i++)
printf("%lu\n", data_log[i].time);
for (i=1; i<data_log_idx; i++)
printf("%d\n", data_log[i].res);
}
}
return 0;
}
As you can see the select has a 1 sec of timeout.
I start my process and after receiving some messages I stop the sender and the process printout timings and received char.
What I can see is that sometimes (very often) select return and the read: eg 69 bytes.
At the end all 513 bytes are read, but shared on 2 or 3 read, eg: 154 and 359 bytes.
I'm sure that driver push data of split buffer each 513 bytes, so my doubt is:
Is select awaking at the wrong time when the flip buffer is not pushed?
Is the read function that can read less that the whole buffer even if I specified 513 in the third parameter?

Related

Reading arduino serial in linux using C

I want to read serial from arduino. I use this code :
#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 */
#include <sys/ioctl.h>
int main(){
char data[1024];
char dev[] = "/dev/ttyACM1";
int fd = open(dev, O_RDWR | O_NOCTTY | O_NDELAY);
fcntl(fd, F_SETFL, FNDELAY);
struct termios options;
tcgetattr(fd, &options);
cfsetispeed(&options, B9600);
cfsetospeed(&options, B9600);
options.c_cflag |= CS8;
options.c_cflag |= CS8;
options.c_cflag &= ~CRTSCTS;
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
tcsetattr(fd, TCSANOW, &options);
ioctl(fd, TCFLSH, 2);
while(1){
read(fd, data, sizeof(data));
printf(data);
}
//write(fd, data, sizeof(data));
}
My arduino runs very simple sketch :
int x;
void setup() {
Serial.begin(9600);
}
void loop() {
Serial.println("DO YOU HEAR ME ??");
delay(1000);
}
and output of this combinatin is that :
??OU HEAR ME ??
DO YOU HEAR ME ??
DO YOU HEAR ME ??
A¹­þ
??OU HEAR ME ??
DO YOU HEAR ME ??
DO YOU HEAR ME ??
A¹­þ
??OU HEAR ME ??
DO YOU HEAR ME ??
DO YOU HEAR ME ??
My question is how to make order out of chaos. I found that this issue occurs when buffer ends and new one begins(bigger buffer less junk data) but I can't have a infinite buffer. Also there is a lot of junk when it reads for the first time.. Is there a way to sync it or something ?
(Also I am not native English sorry for any mistakes.)
I found answer to my own problem. I used this time c++ to organize it in class (very poor one because it doesn't handle any errors and doesn't use c++ in the most..) Here is the code :
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <strings.h>
#include <cstring>
#include <iostream>
//Here I define some vars
#define BAUDRATE B9600
#define MODEMDEVICE "/dev/ttyACM0"
#define _POSIX_SOURCE 1
class serial{
public:
serial(){
fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY );
if (fd <0) {perror(MODEMDEVICE); exit(-1); }
// Improvement No. 1 I save old setting and clean the new one
tcgetattr(fd,&oldtio);
bzero(&newtio, sizeof(newtio));
// Here I set all the flags to vars at once
newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;
newtio.c_iflag = IGNPAR | ICRNL;
newtio.c_oflag = 0;
newtio.c_lflag = ICANON;
//here I set some new flags..
newtio.c_cc[VINTR] = 0; /* Ctrl-c */
newtio.c_cc[VQUIT] = 0; /* Ctrl-\ */
newtio.c_cc[VERASE] = 0; /* del */
newtio.c_cc[VKILL] = 0; /* # */
newtio.c_cc[VEOF] = 4; /* Ctrl-d */
newtio.c_cc[VTIME] = 0; /* inter-character timer unused */
newtio.c_cc[VMIN] = 1; /* blocking read until 1 character arrives */
newtio.c_cc[VSWTC] = 0; /* '\0' */
newtio.c_cc[VSTART] = 0; /* Ctrl-q */
newtio.c_cc[VSTOP] = 0; /* Ctrl-s */
newtio.c_cc[VSUSP] = 0; /* Ctrl-z */
newtio.c_cc[VEOL] = 0; /* '\0' */
newtio.c_cc[VREPRINT] = 0; /* Ctrl-r */
newtio.c_cc[VDISCARD] = 0; /* Ctrl-u */
newtio.c_cc[VWERASE] = 0; /* Ctrl-w */
newtio.c_cc[VLNEXT] = 0; /* Ctrl-v */
newtio.c_cc[VEOL2] = 0; /* '\0' */
// and I finally save the settings
tcflush(fd, TCIFLUSH);
tcsetattr(fd,TCSANOW,&newtio);
}
~serial(){
close(fd);
}
std::string sread(){
res = read(fd,buf,255);
buf[res]=0;
return buf;
}
void swrite(const char* input){
write(fd,input,std::strlen(input));
}
private:
int fd,c,res;
struct termios oldtio,newtio;
char buf[255];
};
int main(){
serial s;
s.swrite("Light");
std::string buf = s.sread();
std::cout << buf;
}
This is more of a ripoff from "Serial programming HOW TO" : http://tldp.org/HOWTO/Serial-Programming-HOWTO/ (form the example code..)
And here is the new poor arduino code :
int x;
String buff;
int lpin = A0;
int tpin = A1;
int data;
void setup() {
Serial.begin(9600);
pinMode(lpin,INPUT);
pinMode(tpin,INPUT);
}
void loop() {
if(Serial.available() == 1)
{
buff = Serial.readString();
if(buff == "Light"){
data = analogRead(lpin);
Serial.print(data);
Serial.print("\n");
}else if(buff == "Temp"){
data = analogRead(tpin);
Serial.print(data);
Serial.print("\n");
}else{
Serial.print("Something went wrong !");
Serial.print("\n");
}
}
delay(1);
}

Read UART continuously without blocking host application

I have been searching around and reading the documentation, but I am at the point where I need a little help. The use case is relatively simple, but the implementation is where I am stuck.
On one end is a wireless Xbee radio. This radio transmits a signal every 300ms. The payload of this signal consists of button states and joystick positions.
On the receiving end is a Linux based SBC running Ubuntu with an Xbee attached. For the sake of this post, I have combined the following into one single file and added a main for readability:
This code is based off the Serial programming Guide
#include <stdio.h>
#include <stdlib.h>
#include <linux/ioctl.h>
#include <fcntl.h>
#include <termios.h>
#include <sys/signal.h>
#include <sys/types.h>
#include <unistd.h>
#include "XbeeReceiver.h"
#define FALSE 0
#define TRUE 1
volatile int STOP = FALSE;
void signal_handler_IO(int status);
int wait_flag = TRUE;
int fileDescriptor = -1;
/* Constants */
const char *DEFAULT_PORT = "/dev/ttyTHS1";
const int DEFAULT_BAUD = B115200;
/* Prototypes */
struct N64_DTO queryController(int fd);
void init(const char *port, const int baud);
void setTermConfig(int fd, const int baud);
void signal_handler_IO(int status);
int openUART(const char *port);
void init(const char *port, const int baud) {
fileDescriptor = openUART(port ? port : DEFAULT_PORT);
setTermConfig(fileDescriptor, baud ? baud : DEFAULT_BAUD);
while (STOP == FALSE) {
if (wait_flag == FALSE) {
struct N64_DTO controller = queryController(fileDescriptor);
printf("\n\n\n Y Joystick:: %i \n", (signed char) controller.y);
printf("X Joystick:: %i \n", (signed char) controller.x);
/* I am supposed to set STOP to TRUE for this loop to stop, however I always want to read from the controller,
which is why this is now blocking */
wait_flag = TRUE;
}
}
}
struct N64_DTO queryController(int fd) {
struct N64_DTO controller;
int byteCount = read(fd, (char *) &controller, sizeof(struct N64_DTO));
if (byteCount == -1) {
printf("I'll handle this error later on");
exit(1);
}
return controller;
}
void signal_handler_IO(int status) {
printf("received SIGIO signal.\n");
wait_flag = FALSE;
}
void setTermConfig(int fd, const int baud) {
struct sigaction saio;
saio.sa_handler = signal_handler_IO;
sigemptyset(&saio.sa_mask);
sigaddset(&saio.sa_mask, SIGINT);
saio.sa_flags = 0;
saio.sa_restorer = NULL;
sigaction(SIGIO, &saio, NULL);
fcntl(fd, F_SETOWN, getpid());
fcntl(fd, F_SETFL, FASYNC);
struct termios toptions;
tcgetattr(fd, &toptions);
cfsetspeed(&toptions, baud);
/* man termios for individual definitions */
toptions.c_cflag &= ~PARENB;
toptions.c_cflag &= ~CSTOPB;
toptions.c_cflag &= ~CSIZE;
toptions.c_cflag |= CS8;
toptions.c_cflag &= ~CRTSCTS;
toptions.c_cflag |= CREAD | CLOCAL;
toptions.c_iflag &= ~(IXON | IXOFF | IXANY);
toptions.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
toptions.c_oflag &= ~OPOST;
toptions.c_cc[VMIN] = sizeof(struct N64_DTO);
toptions.c_cc[VTIME] = 0;
tcsetattr(fd, TCSANOW, &toptions);
tcflush(fd, TCIFLUSH);
}
int openUART(const char *port) {
return open(port, O_RDWR | O_NOCTTY | O_NONBLOCK);
}
int main(int argc, char *argv[]) {
int i;
init("/dev/ttyTHS1", 115200);
for (i = 0; i < 10; i++) {
printf("This loop never prints..");
}
return 0;
}
Although it needs more refactoring, this code works and gives me the expected output. However, now that I have the output, I would like to do something with it, i.e send as input to a motor controller etc. The problem is, due to the frequency of reads(300ms) the program is ultimately blocking any other routines from executing.
I went back to the drawing board a few weeks ago and started down a few different paths. I explored threading, signal handlers, leveraging poll/select API, and the possibility of creating a dedicates kernel module. Last week, for a different reason, I put the controller up on a scope and setup triggers for the rising edge of the signal. That’s when it hit me. What I want is an event driven model where the OS notifies me when a signal is detected on a particular serial port. I figured I would reach out and see if someone has experience in this area that would be willing to steer me in the right direction. I have been at this issue for a week and still have not made any progress. In the end, the goal is to continuously receive serial data from the port without blocking other parts of my applications(driving motors, moving servos).

Serial communication on Linux with flow control enabled - bad behaviour

I wrote common functions in order to manage serial ports, based on the following structure:
typedef struct
{
int PHandle;
unsigned int Port;
unsigned int BaudRate;
unsigned char Parity;
unsigned char FlowControl;
char Device[MAX_SIZE];
} Tst_SPort;
I am calling these functions (see below) in another file in order to test an RS232 serial port. The flow control needs to be enabled.
int iInit(Tst_SPort *port, const char *device, int baudRate, unsigned char parity, unsigned char flowControl)
{
strncpy(port->Device, device, MAX_SIZE);
port->PHandle = iOpen(port);
port->Port = -1;
port->BaudRate = baudRate;
port->Parity = parity;
port->FlowControl = flowControl;
if(port->PHandle > 0)
{
setuart(port, port->BaudRate);
}
return port->PHandle;
}
int iOpen(Tst_SPort *port)
{
port->PHandle = open(port->Device, O_RDWR | O_NOCTTY);
if(port->PHandle < 0)
{
perror("open:");
return (-1);
}
return (port->PHandle);
}
void setuart(Tst_SPort *port, int baudRate)
{
struct termios opt, optCmp;
struct serial_struct info;
if(port->PHandle > 0)
{
bzero(&opt, sizeof(opt));
bzero(&optCmp, sizeof(optCmp));
if(ioctl(port->PHandle, TIOCGSERIAL, &info) == 0)
port->Port = info.port;
fcntl(port->PHandle, F_SETFL, O_NONBLOCK);
if (tcgetattr(port->PHandle, &opt) < 0)
perror("tcgetattr Get:");
if(baudRate > 0)
{
cfsetospeed (&opt, baudRate);
cfsetispeed (&opt, baudRate);
}
opt.c_iflag = IGNPAR;
opt.c_oflag &= ~OPOST
opt.c_oflag &= ~ONLCR;
opt.c_lflag = 0;
opt.c_cflag |= (CLOCAL | CREAD);
opt.c_cflag &= ~(PARENB | PARODD);
opt.c_cflag |= port->Parity;
opt.c_cflag &= ~CSTOPB;
opt.c_cflag &= ~CSIZE;
opt.c_cflag |= CS8;
if(!port->FlowControl)
opt.c_cflag &= ~CRTSCTS;
else
opt.c_cflag |= CRTSCTS;
opt.c_cc[VMIN] = 0;
opt.c_cc[VTIME] = 50;
if(tcsetattr(opt->PHandle, TCSANOW, &opt) < 0)
perror("tcgetattr Update :");
if (tcgetattr(opt->PHandle, &optCmp) < 0)
perror("tcgetattr Read:");
/* Compare */
if (memcmp((void *)&opt, (void *)&optCmp, sizeof(opt)) != 0)
printf("Conf failed");
tcflush(port->PHandle, TCIFLUSH);
}
}
int iRead(Tst_SPort *port, char *buffer, unsigned long buffLength)
{
struct timeval tv;
fd_set recv;
int s32Read = 0;
int s32Offset = 0;
int s32SRes = 0;
tv.tv_sec = 0;
tv.tv_usec = 100000; /* 100ms */
if ((port) && (port->PHandle > 0))
{
while (s32Offset < buffLength)
{
FD_ZERO(&recv);
FD_SET(port->PHandle, &recv);
s32SRes = select(port->PHandle + 1, &recv, NULL, NULL, &tv);
if ((s32SRes == -1) && (errno == EINTR))
{
continue;
}
else if(s32SRes > 0)
{
if (FD_ISSET(port->PHandle, &recv))
{
s32Read = read(port->PHandle, buffer + s32Offset, buffLength - s32Offset);
if(s32Read > 0)
{
tv.tv_sec = 0;
tv.tv_usec = 5000;
s32Offset += s32Read;
continue;
}
}
}
break;
}
}
return s32Offset;
}
int iClose(Tst_SPort *port)
{
return (close(port->Phandle));
}
In order to validate the implementation, the pinouts Tx and Rx have been connected together, idem for CTS and RTS. Everything works fine, the message sent can be read correctly. In addition, when Tx is disconnected from the Rx nothing is reading as expected.
But when the CTS is unplugged from the RTS the test blocks after the port closing step (~20 seconds).
However, if the function setuart() is called with flowControl == 0, the test does not block and returns the exepected error code without delay.
I probably understood something wrongly especially in port configuration. Is it the good way to do ?
The problem you are facing is a correct behaviour.
Leaving CTS unconnected with flow control enabled, means DTE (AKA PC) cannot send data to DCE (slave device).
When you try to write to the UART output buffer it, probably, is full and application temporarily stops running and waits until some buffer space becomes available.

Receive extra null byte when using serial port

I'm writing a program for serial port data transmission on Linux, but find that every time the sender opens the port, the receiver gets an extra null byte '\x00'.
Here's the code of sender:
#include <unistd.h>
#include <termios.h>
#include <fcntl.h>
int main(int argc, char* argv[]) {
int fd_com_ = open("/dev/ttyAM0", O_RDWR | O_NOCTTY | O_NONBLOCK);
struct termios attrs_;
attrs_.c_iflag = IGNBRK;
attrs_.c_oflag = 0;
attrs_.c_cflag = (CLOCAL | CREAD);
attrs_.c_cflag |= CS8;
attrs_.c_lflag = 0;
attrs_.c_cc[VMIN] = 0;
attrs_.c_cc[VTIME] = 0;
cfsetspeed(&attrs_, B115200);
tcsetattr(fd_com_, TCSANOW, &attrs_);
const char *s = "abcd";
write(fd_com_, s, 4);
sleep(1);
write(fd_com_, s, 4);
sleep(1);
close(fd_com_);
fd_com_ = open("/dev/ttyAM0", O_RDWR | O_NOCTTY | O_NONBLOCK);
write(fd_com_, s, 4);
return 0;
}
The receiver has the same configuration, but receives "\x00abcdabcd\x00abcd". How to fix this problem so the receiver could get "abcdabcdabcd"?
Update:
The code of receiver:
#include <stdio.h>
#include <unistd.h>
#include <termios.h>
#include <fcntl.h>
int main(int argc, char* argv[]) {
int fd_com_ = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NONBLOCK);
struct termios attrs_;
attrs_.c_iflag = IGNBRK;
attrs_.c_oflag = 0;
attrs_.c_cflag = (CLOCAL | CREAD);
attrs_.c_cflag |= CS8;
attrs_.c_lflag = 0;
attrs_.c_cc[VMIN] = 0;
attrs_.c_cc[VTIME] = 0;
cfsetspeed(&attrs_, B115200);
tcsetattr(fd_com_, TCSANOW, &attrs_);
char buf[100];
ssize_t sz;
while(1) {
sz = read(fd_com_, buf, 100);
if (sz > 0) {
for (ssize_t i=0; i<sz; i++) {
printf("%02hhx\n", buf[i]);
}
}
sleep(1);
}
return 0;
}
Please check in your ARM board's documentation how the ARM's UART is hooked up and how it is configured in hardware and by your platform driver.
From what you describe, I would suppose that when opening the UART port on the ARM, the physical UART (i.e., the hardware peripheral module within the ARM or maybe an externally wired UART chip) is enabled or restored from some unknown idle state to the proper -12 Volt idle state of RS232. This transistion may be enough for your PC's UART to recognize a start bit and receive a bogus character.
You may want to check the serial line using an oscilloscope to see what happens when actually opening the port.
the initial \x0 is the indication that a parity or framing error occurred.
this error occurs because the termios fields are not being setup properly.
so the initial line high/low status and number of start/stop bits and parity
are not being setup properly.
you might read: http://man7.org/linux/man-pages/man3/termios.3.html
which discusses each of the fields and their contents and meaning.
(The linked page is way too long to post here)

Unexpected behavior related to write() function

This program is intended to read a byte from the console (cygwin on windows XP) and write it to the serial port (in order to communicate from a PC to an AVR). Then it should read data from the serial port. The AVR is set up to send data periodically, which works as it should (confirmed with Hyper Terminal). The program below works as it should, but when the line that writes data to the serial port is commented out, the program does not read either. In fact, it does not execute the lines before the (commented out) "write (fd, datatemp, 1);" either.
Why does the program seemingly not execute as intended when the write operation is not included?
#include "serialport.h"
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <stdlib.h>
#include <strings.h>
#include <stdio.h>
/* baudrate settings are defined in <asm/termbits.h>, which is
* included by <termios.h> */
#ifndef BAUDRATE
#define BAUDRATE B2400
#endif
#define _POSIX_SOURCE 1 /* POSIX compliant source */
#define BUFLEN 4
static int fd, c, res;
static struct termios oldtio, newtio;
static char *device;
int serial_init(char *modemdevice)
{
/*
* Open modem device for reading and writing and not as controlling tty
* because we don't want to get killed if linenoise sends CTRL-C.
**/
device = modemdevice;
fd = open (device, O_RDWR | O_NOCTTY | O_NDELAY);
//fd = open (device, O_RDWR | O_NOCTTY );
//fcntl(fd, F_SETFL, 0);
if (fd < 0)
{
perror (device);
exit(-1);
}
tcgetattr (fd, &oldtio); /* save current serial port settings */
bzero (&newtio, sizeof (newtio)); /* clear struct for new port settings */
/*
*BAUDRATE: Set bps rate. You could also use cfsetispeed and cfsetospeed.
*CRTSCTS : output hardware flow control (only used if the cable has
*all necessary lines. )
*CS8 : 8n1 (8bit,no parity,1 stopbit)
*CLOCAL : local connection, no modem contol
*CREAD : enable receiving characters
**/
newtio.c_cflag = BAUDRATE | CS8 | CLOCAL | CREAD;
/*
*IGNPAR : ignore bytes with parity errors
*ICRNL : map CR to NL (otherwise a CR input on the other computer
* will not terminate input)
* otherwise make device raw (no other input processing)
**/
newtio.c_iflag = IGNPAR | ICRNL;
/*
* Map NL to CR NL in output.
* */
#if 0
newtio.c_oflag = ONLCR;
#else
newtio.c_oflag = 0;
#endif
/*
* ICANON : enable canonical input
* disable all echo functionality, and don't send signals to calling program
**/
#if 1
newtio.c_lflag = ICANON;
#else
newtio.c_lflag = 0;
#endif
/*
* initialize all control characters
* default values can be found in /usr/include/termios.h, and are given
* in the comments, but we don't need them here
* */
newtio.c_cc[VINTR] = 0; /* Ctrl-c */
newtio.c_cc[VQUIT] = 0; /* Ctrl-\ */
newtio.c_cc[VERASE] = 0; /* del */
newtio.c_cc[VKILL] = 0; /* # */
newtio.c_cc[VEOF] = 4; /* Ctrl-d */
newtio.c_cc[VTIME] = 0; /* inter-character timer unused */
newtio.c_cc[VMIN] = 1; /* blocking read until 1 character arrives */
newtio.c_cc[VSWTC] = 0; /* '\0' */
newtio.c_cc[VSTART] = 0; /* Ctrl-q */
newtio.c_cc[VSTOP] = 0; /* Ctrl-s */
newtio.c_cc[VSUSP] = 0; /* Ctrl-z */
newtio.c_cc[VEOL] = 0; /* '\0' */
newtio.c_cc[VREPRINT] = 0; /* Ctrl-r */
newtio.c_cc[VDISCARD] = 0; /* Ctrl-u */
newtio.c_cc[VWERASE] = 0; /* Ctrl-w */
newtio.c_cc[VLNEXT] = 0; /* Ctrl-v */
newtio.c_cc[VEOL2] = 0; /* '\0' */
/*
* now clean the modem line and activate the settings for the port
**/
tcflush (fd, TCIFLUSH);
tcsetattr (fd, TCSANOW, &newtio);
/*
* terminal settings done, return file descriptor
**/
return fd;
}
void serial_cleanup(int ifd){
if(ifd != fd) {
fprintf(stderr, "WARNING! file descriptor != the one returned by serial_init()\n");
}
/* restore the old port settings */
tcsetattr (ifd, TCSANOW, &oldtio);
}
void main(void) {
int fd = serial_init("/dev/ttyS0");
//while(1)
//{
printf("Enter a dutycycle: ");
unsigned char buffer[BUFLEN] = {0};
fgets(buffer, BUFLEN, stdin);
uint8_t data = atoi(buffer);
unsigned char datatemp[1] = {(unsigned char) data};
printf("hen");
write (fd, datatemp, 1);
int n = 0;
unsigned char inbuffer[2] = {0};
int temp = -1;
//printf("%ld", temp);
while (temp <= 0)
{
//printf("%ld", temp);
temp = read(fd, inbuffer, 1);
}
printf("%u", (uint8_t) inbuffer[0]);
//}
serial_cleanup(fd);
}
Try looking at fflush() function.
Maybe
fflush(NULL)
or even
fflush(stdout)
will help in your case. Its worth experimenting by flushing before and/or after outputting to console.

Resources