I am working an a serial communication project where two applications server and client will send to each other messages.
For example client send a string command server receives this and after processing response with a value. One example of that is : client AT+REG1 server value.
If client sends the message AT+REG1=value then the server must inform his system that the value of current register1 which client needs has changed.
In order to achieve this I keep a stack where at the beginning of the program I am pushing into stack a default value for register1 and if server detect this message AT+REG1= pops the old value and push the new into stack.
Currently if client sends the message AT+REG1, server must response with the new value and not with the old one that I push it by default in the beginning. All the stuff in pop push and generally at stack operations are going right.
My problem is, when I start with AT+REG1, client receives the default value but when I start with AT+REG1=5 (server must change the value from the stack and replace it with the new "5") I am not getting any response. At this point I have to mention that in terminal I am seeing the changes in the stack (with printf for example at AT+REG1=5 , he pops the old and push the new) but I cannot have the result.
The problem that I noticed when trying to print the value that pops out from stack terminal says that it is of type int DESPITE that am not using or creating integers, all the values are in char form.
SERVER.C
//data structures
typedef enum operation{
insert,
read_reg,
info
}Operation;
typedef struct request{
Operation operation;
char old_value1[SIZE];
char old_value2[SIZE];
int flag; //flag to know which register is
int counter1;
int counter2;
}Request;
Request c1;
Request c2;
//Prototype Functions
Request *parse_request(char *buffer);
void process_request(int fd);
int isEmpty(char *stack);
int isFull(char *stack);
void push(char num,char *stack);
char pop(char *stack);
char *stack1,*stack2;
int top1=-1,top2=-1;
char t1,t2;
int main(int argc , char * argv[]){
int fd; //file descriptor of the port
char *port; // port name
struct termios tty; //connection manager
stack1=(char*)malloc(STACK_SIZE*sizeof(char));
stack2=(char*)malloc(STACK_SIZE*sizeof(char));
if(argc < 1){
printf("You have to enter a specific tty file to open\n");
exit(1);
}
//Opening port .
port =argv[1];
fd=open(port,O_RDWR|O_NOCTTY| O_NONBLOCK);
if(fd==-1){
perror(port);
exit(1);
}
printf("[+] port opened succesfully!\n");
if(tcgetattr(fd,&tty)!=0){
printf("tcgetattr : %s \n",strerror(errno));
}
//BAUD RATE SETTINGS (read and write speed)
cfsetospeed(&tty,B115200);
cfsetispeed(&tty,B115200);
cfmakeraw(&tty);
// Settings for control modes
tty.c_cflag &= ~PARENB; // Clear the parity bit for the serial communication
tty.c_cflag &= ~CSTOPB; // Using only one stop bit in this communication
tty.c_cflag |= CS8; // Set 8 bits per byte in transmittion
tty.c_cflag &= ~CRTSCTS; // Disable the RTS/CTS flow control
tty.c_cflag |= CREAD | CLOCAL; // Setting clocal up ("1") .Usefull for reading data
tty.c_lflag &= ~ICANON; // Setting on the non-canonical mode
tty.c_lflag &= ~ISIG; // Disable the INTR - QUIT - SUSP characters
tty.c_iflag &= ~IGNPAR;
//Blocking read operation and setting maximum timeout 1 second
tty.c_cc[VTIME]=1;
tty.c_cc[VMIN] =0;
//Setting the options
tcsetattr(fd,TCSANOW,&tty);
//setting first values for each register!
push('0',stack1);
push('1',stack2);
c1.counter1=0;
c2.counter2=0;
printf("[+] Connection starting !\n");
while(1){
process_request(fd);
}
}
Request *parse_request(char *buffer){
char *token=NULL;
char *take[3];
int i=0,num;
Request *rep=NULL;
if(!buffer)
return NULL;
rep=(Request*)malloc(sizeof(Request));
memset(rep->old_value1,0,SIZE);
memset(rep->old_value2,0,SIZE);
if(strcmp(buffer,"AT+REG1")==0) {
rep->operation=read_reg;
rep->flag=1;
}else if(strcmp(buffer,"AT+REG2")==0){
rep->operation=read_reg;
rep->flag=2;
}else if(strcmp(buffer,"AT+REG2")!=0 || strcmp(buffer,"AT+REG1")!=0){
token=strtok(buffer,"=");
while(token!=NULL){
take[i]=token;
token=strtok(NULL," ");
i++;
}
if(strcmp(take[0],"AT+REG1")==0 && strcmp(take[1],"?")==0){
rep->operation=info;
rep->flag=1;
}else if(strcmp(take[0],"AT+REG2")==0 && strcmp(take[1],"?")==0){
rep->operation=info;
rep->flag=2;
}else if(strcmp(take[0],"AT+REG1")==0 && take[1]!=NULL){
rep->operation=insert;
rep->flag=1;
//Scanning for errors
if(atoi(take[1])>16535 || atoi(take[1])<0)
return rep=NULL;
char rev;
if(!isEmpty(stack1)){
//take the old value from the stack and save it
rep->old_value1[c1.counter1]=pop(stack1);
c1.counter1++;
int num=atoi(take[1]);
rev= num;
push(rev,stack1);
}else{
//push the new value into the stack
int num=atoi(take[1]);
rev= num;
push(rev,stack1);
}
}else if(strcmp(take[0],"AT+REG2")==0 && take[1]!=NULL){
rep->operation=insert;
rep->flag=2;
//Scanning for errors
if(atoi(take[1])>3 || atoi(take[1])<1)
return rep=NULL;
char rev;
if(!isEmpty(stack2)){
rep->old_value2[c2.counter2]=pop(stack2);
c2.counter2++;
int num=atoi(take[1]);
rev=num;
push(rev,stack2);
}else{
int num=atoi(take[1]);
rev=num;
push(rev,stack2);
}
}else{
free(rep);
return(NULL);
}
}else{
free(rep);
return(NULL);
}
return rep;
}
void process_request(int fd){
fd_set readfd;
int status;
char *str;
char buffer[SIZE];
int read_num=0;
char *str1;
struct flock fl;
struct timeval timeout;
Request *request;
fl.l_type = F_RDLCK; /* read lock */
fl.l_whence = SEEK_SET; /* beginning of file */
fl.l_start = 0; /* offset from l_whence */
fl.l_len = 0; /* length, 0 = to EOF */
fl.l_pid = getpid(); /* PID */
//Clean buffer
memset(buffer,0,SIZE);
FD_ZERO(&readfd);
FD_SET(fd,&readfd);
timeout.tv_sec=100;
timeout.tv_usec=0;
status=select(40,&readfd,NULL,NULL,&timeout);
if(status==0){ //no data is receiving !
printf("Cannot receive data from client\n");
printf("\tTime Out\n");
exit(1);
}
//read from file descriptor
read_num=read(fd,buffer,sizeof(buffer));
if(read_num<0)perror("Error in reading\n");
if(read_num){
fcntl(fd, F_SETLKW, &fl); // set lock
str1=strdup(buffer);
request = parse_request(str1);
if(request){
switch(request->operation){
case info:
if(request->flag==1){
write(fd,"0-16535\n",20);
}else if(request->flag==2){
write(fd,"1|2|3\n",40);
}
break;
case read_reg:
if(request->flag==1){
//HERE IS THE PROBLEM!!!
t1=pop(stack1);
printf("%s\n",t1); // it understand this as int why ?
write(fd,&t1,5);
//---------------
}else if(request->flag==2){
t2=pop(stack2);
write(fd,&t2,sizeof(t2));
}
break;
case insert:
if(request==NULL)
write(fd,"INVINPUT\n",20);
write(fd,"OK\n",5);
break;
default:
printf("Something went wrong\n");
break;
}
if(request)
free(request);
}
}
fl.l_type = F_UNLCK;
fcntl(fd, F_SETLK, &fl); // unset lock
}
int isEmpty(char *stack){
if(stack==stack1){
if(top1==-1)
return 1;
return 0;
}else if(stack==stack2){
if(top2==-1)
return 1;
return 0;
}
}
int isFull(char *stack){
if(stack==stack1){
if(top1==STACK_SIZE)
return 1;
return 0;
}else if(stack==stack2){
if(top2==STACK_SIZE)
return 1;
return 0;
}
}
void push(char num,char *stack){
if(stack==stack1){
if(!isFull(stack1)){
printf("Eisagogh\n");
top1++;
//*(stack+top1)=num;
stack1[top1]=num;
}else{
printf("Error , push at stack1\n");
}
}else if(stack==stack2){
if(!isFull(stack2)){
top2++;
*(stack2+top2)=num;
}else
printf("Error , push at stack2\n");
}
}
char pop(char *stack){
char str_num;
if(stack==stack1){
if(!isEmpty(stack)){
printf("Eksagogh\n");
str_num=*(stack+top1);
top1--;
return str_num;
}else
printf("Error in pop item from stack1\n");
}else if(stack==stack2){
printf("me vlepeis edo ?\n");
if(!isEmpty(stack)){
str_num=*(stack+top2);
top2--;
return str_num;
}else
printf("Error in pop item from stack2\n");
}
}
Running :
CLIENT
AT+REG1=5
writing AT+REG1=5 command
Response:OK
AT+REG1
writing AT+REG1 command
Responce :
SERVER
[+] port opened succesfully!
push //it is the default value that I insert into the stack
[+] Connection starting !
pop // pops out the default value
push // seems that inserting the value 5 that client asked
pop // and now that pop is for writing to serial port in order client reads it (HERE IS THE PROBLEM) this is the point where I mention in the code that I have problem terminal seeing it as integer and not as char , go check this at process_requst function in server above.
If client sends although AT+REG1 he response the default value where server pops out from stack and send it in the point where the problem is . Please if anyone can help i would appreciate.
Related
In this case of the project that am working on , am receiving a message and i want to send a response by writing a message to the file descriptor.But the problem is that the write function returns Segmentation Fault and i dont know why. For example i receive a message going to the right case and send response by writing to a file when i use write it shows that the message went to the destination but after that returns segmentation fault.If instead of write use a printf it works and doesnt show segmentation fault .Can any one help me with that ?
typedef enum operation{
insert,
read_reg,
info,
error
}Operation;
typedef struct request{
Operation operation;
int ID;
int counter;
}Request;
int **regs;
fd=open(port,O_RDWR|O_NOCTTY);
if(fd==-1){
perror(port);
exit(1);
}
regs=(int **)malloc(2*sizeof(int*));
if(regs==NULL){
printf("Cant create data base for registers\n");
exit(1);
}
for(int i=1;i<=2;i++){
regs[i]=(int*)malloc(SIZE*sizeof(int));
if(regs[i]==NULL){
exit(1);
}
}
regs[1][0]=1;
regs[2][0]=3;
char str[12];
char buffer[255];
while(1){
//Clean buffer
memset(buffer,0,SIZE);
FD_ZERO(&readfd);
FD_SET(fd,&readfd);
timeout.tv_sec=100;
timeout.tv_usec=0;
status=select(40,&readfd,NULL,NULL,&timeout);
if(status==0){
printf("Cannot receive data from client\n");
printf("\tTime Out\n");
exit(1);
}
read_num=read(fd,buffer,sizeof(buffer));
if(read_num<0) perror("Error in reading file descriptor\n");
if(read_num>0){
//while(1){
fl.l_type = F_RDLCK; /* read lock */
fl.l_whence = SEEK_SET; /* beginning of file */
fl.l_start = 0; /* offset from l_whence */
fl.l_len = 0; /* length, 0 = to EOF */
fl.l_pid = getpid(); /* PID */
fcntl(fd, F_SETLKW, &fl);
request=parse_request(buffer);
if(request){
switch(request->operation){
case info:
write(fd,"OK\n",1);
break;
case read_reg:
write(fd,"OK\n",1);
printf("prepei na diabaso reg\n");
break;
case insert:
printf("edo vazo timi\n");
write(fd,"OK\n",1);
break;
case error:
printf("prepei na petakso error\n");
write(fd,"OK\n",1);
break;
}
printf("prepei na me deis meta apo kathe break\n");
}
printf("kai edw prepei na me deis \n");
fl.l_type = F_UNLCK;
fcntl(fd, F_SETLK, &fl); // unset lock
//}
}
printf("edw ?\n");
}
parse_request is a function that splits the message and determines information about it.
Request *parse_request(char *buffer){
char *token=NULL,*value=NULL;
Request *rep=NULL;
char string_split[4];
int i=0;
rep=(Request*)malloc(sizeof(Request));
rep->counter=0;
token=strtok(buffer,"=");
//extract value
value=strtok(NULL,"=");
token=strtok(token,"+");
//extract register
token=strtok(NULL,"+");
//Set up registers ID
rep->ID=atoi(&token[strlen(token)-1]);
//Set up operation type
if(!value){
rep->operation=read_reg;
//printf("Operation :read\n");
}else{
if(strcmp(value,"?")==0){
rep->operation=info;
//printf("Operation :info\n");
}else{
//check if number is valid
if(isValid(value,rep)==1){
rep->operation=insert;
//printf("Operation :insert\n");
//printf("am gonna insert value:%d\n",atoi(value));
regs[rep->ID][rep->counter++]=atoi(value);
printf("%d\n",regs[rep->ID][rep->counter++]=atoi(value));
}else{
rep->operation=error;
//printf("Operation :error\n");
}
}
}
return rep;
}
regarding a buffer that contains:
AT+<REG>=<VALUE>
the first call to strtok() replaces the + with a NUL byte.
A second call to strtok() does not find a + in the buffer, so continues to search through memory until some 'random' + is encountered.
Now you have a pointer token pointing to memory that your program should not access.
Then the program tries to output the memory at that 'invalid' 'token' pointer. The result is a seq fault event.
I'm new here.
I'm trying receive data from UART which is from Xbee.
The sample code below is allow me to check the API frame.
But what I need is make these to be a useful array.
How should i make this into a complete array?
The result shows what i need but they are independent.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h> //Used for UART
#include <fcntl.h> //Used for UART
#include <termios.h> //Used for UART
int main(int argc, char const *argv[])
{
//-------------------------
//----- SETUP USART 0 -----
//-------------------------
//At bootup, pins 8 and 10 are already set to UART0_TXD, UART0_RXD (ie the alt0 function) respectively
int uart0_filestream = -1;
//OPEN THE UART
//The flags (defined in fcntl.h):
// Access modes (use 1 of these):
// O_RDONLY - Open for reading only.
// O_RDWR - Open for reading and writing.
// O_WRONLY - Open for writing only.
//
// O_NDELAY / O_NONBLOCK (same function) - Enables nonblocking mode. When set read requests on the file can return immediately with a failure status
// if there is no input immediately available (instead of blocking). Likewise, write requests can also return
// immediately with a failure status if the output can't be written immediately.
//
// O_NOCTTY - When set and path identifies a terminal device, open() shall not cause the terminal device to become the controlling terminal for the process.
uart0_filestream = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY); //Open in non blocking read/write mode
if (uart0_filestream == -1)
{
//ERROR - CAN'T OPEN SERIAL PORT
printf("Error - Unable to open UART. Ensure it is not in use by another application\n");
}
struct termios options;
tcgetattr(uart0_filestream, &options);
options.c_cflag = B9600 | CS8 | CLOCAL | CREAD; //<Set baud rate
options.c_iflag = IGNPAR;
options.c_oflag = 0;
options.c_lflag = 0;
tcflush(uart0_filestream, TCIFLUSH);
tcsetattr(uart0_filestream, TCSANOW, &options);
//----- TX BYTES -----
unsigned char tx_buffer[20];
unsigned char *p_tx_buffer;
p_tx_buffer = &tx_buffer[0];
*p_tx_buffer++ = 'H';
*p_tx_buffer++ = 'e';
*p_tx_buffer++ = 'l';
*p_tx_buffer++ = 'l';
*p_tx_buffer++ = 'o';
if (uart0_filestream != -1)
{
int count = write(uart0_filestream, &tx_buffer[0], (p_tx_buffer - &tx_buffer[0]));
//Filestream, bytes to write, number of bytes to write
if (count < 0)
{
printf("UART TX error\n");
}
}
char r[100];
while(1){
//----- CHECK FOR ANY RX BYTES -----
if (uart0_filestream != -1)
{
//printf("OK");
// Read up to 255 characters from the port if they are there
unsigned char rx_buffer[256];
int rx_length = read(uart0_filestream, (void*)rx_buffer, 255); //Filestream, buffer to store in, number of bytes to read (max)
if (rx_length < 0)
{
//An error occured (will occur if there are no bytes)
}
else if (rx_length == 0)
{
//No data waiting
}
else
{
//Bytes received
rx_buffer[rx_length] = '\0';
printf("%i bytes read : %s\n", rx_length, rx_buffer);
//printf("%d\n",rx_buffer[0]);
}
}
}
return 0;
}
I am trying to write a function that reads a chunk of data sent through UART. I am using Raspbian Jessie running on a RaspberryPi model B but I wanted to use this C code (with any necessary revisions) on openwrt. So far, this is what I wrote.
Header:
#ifndef __UART_LIB__
#define __UART_LIB__
#include <stdlib.h> //Errors, etc
#include <unistd.h> //Used for UART
#include <fcntl.h> //Used for UART
#include <termios.h> //Used for UART
#include <sys/types.h> //These includes are for timeout
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/select.h> //
#include <sys/ioctl.h>
#define BITS_PER_PACKAGE_ 11
#define WAIT_PROLONGATION_CONSTANT_ 1.1f
//Some values used by default, left for the user to change if needed
unsigned int BAUD_ ;
unsigned int NUM_BITS_ ;
char *UART_PATH_ ;
unsigned int MAX_SIZE_ ;
unsigned int OPEN_FLAG_ ;
time_t TIMEOUT_SEC_ ;
suseconds_t TIMEOUT_USEC_ ;
struct timeval WAIT_CONSTANT_ ;
int open_conf_UART_() ;
int read_UART_(int uart_filestream, char** dest, int max_len) ;
#endif
.c file:
#include "uartlib.h"
unsigned int BAUD_ = B115200 ;
unsigned int NUM_BITS_ = CS8 ;
char *UART_PATH_ = "/dev/ttyAMA0" ;
unsigned int MAX_SIZE_ = 128 ;
unsigned int OPEN_FLAG_ = O_RDWR ;
time_t TIMEOUT_SEC_ = 5 ;
suseconds_t TIMEOUT_USEC_ = 0 ;
int open_conf_UART_()
{
int indicator, old_fl;
int uart_filestream ;
struct termios options ;
// Opening the port in a read/write mode
uart_filestream = open(UART_PATH_, OPEN_FLAG_ | O_NOCTTY );
if (uart_filestream < 0)
{
// Unable to open the serial port, so produce an error and halt
return -1;
}
// Configuring the options for UART
// Retrieve the options and modify them.
indicator = tcgetattr(uart_filestream, &options);
if(indicator < 0)
{
// Unable to get the attributes
close(uart_filestream);
return -1;
}
// I found a question on stackoverlow where the answer said that VTIME and VMIN will be ignored unless I
// switch the FNDELAY flag off
old_fl = fcntl(uart_filestream, F_GETFL);
if(old_fl < 0)
{
return -1;
}
old_fl &= ~FNDELAY;
fcntl(uart_filestream, old_fl);
//Setting the options
options.c_cflag = CRTSCTS | BAUD_ | NUM_BITS_ | CLOCAL | CREAD ;
options.c_iflag = 0;
options.c_oflag = 0;
options.c_lflag = 0;
//I want the uart to wait 1/10 of a second between bytes at most
options.c_cc[VTIME] = 1;
options.c_cc[VMIN] = 0;
// Flushing the file stream (the input and the output area)
indicator = tcflush(uart_filestream, TCIOFLUSH);
if(indicator < 0)
{
// Unable to flush
close(uart_filestream);
return -1;
}
// Setting the options for the file stream.
indicator = tcsetattr(uart_filestream, TCSANOW, &options);
if(indicator < 0)
{
// Unable to set the attributes
close(uart_filestream);
return -1;
}
return uart_filestream;
}
int read_UART_(int uart_filestream, char** dest, int max_len)
{
int indicator;
int buffer_length;
indicator = tcflush(uart_filestream, TCIFLUSH);
if(indicator < 0)
{
// Unable to flush
return -1;
}
//Do the actual reading
buffer_length = read(uart_filestream, (void*)(*dest), max_len);
if(indicator < 0)
{
return -1;
}
else
{
// Returning number of read bytes
return buffer_length;
}
// Both branches of the if statement above have return, so this will not be reached
}
So, when I try to read more than 8 bytes, the message gets truncated to 8 bytes.
As I read, setting VTIME to a certain value allows the time interval between two bytes to be at most that long.
I am not certain what is going on but I suspect that the read() call reads the buffer before the receiving of the data is complete.
My wish is to read a chunk of data of undefined size. I also used select() with a timeout before the read to make sure the program won't block entirely.
I read a lot of forum topics, stackoverflow questions, guides, etc. on this topic and none seem to help me with my solution.
So, can anyone explain what is going on here? Is it possible to do what I want?
Note that I removed some of the code (I also wrote a function that writes to a UART port) so here might be some redundant includes, global variables, etc.
So, I solved my problem. I still can't flush (when the system is freshly booted up and there was a signal before I turned my program on, there is some old content in the buffer, as it seems to me).
I used this assumption: The package will arrive in smaller bursts and they will be separated by TIMEOUT_BYTE_ amount of time. If that expires, I assume that the package is over.
Also, I have a timeout for initial waiting for the data but I reckon that is situational.
Header file:
#ifndef UART_LIB_
#define UART_LIB_
#include <stdlib.h> //Errors, etc
#include <unistd.h> //Used for UART
#include <fcntl.h> //Used for UART
#include <termios.h> //Used for UART
#include <sys/types.h> //These includes are for timeout
#include <sys/select.h> //Used for select(), etc
//Some values used by default, left for the user to change if needed
//Used to set up the baud rate
unsigned int BAUD_ ;
//Used to indicate number of bits in one backage
unsigned int NUM_BITS_ ;
//Path to the UART device
char *UART_PATH_ ;
//Flag for opening the device
unsigned int OPEN_FLAG_ ;
//Timeout for answer from the other side
time_t TIMEOUT_SEC_ ;
suseconds_t TIMEOUT_USEC_ ;
//Time interval between two bursts of data inside the package
suseconds_t TIMEOUT_BYTE_ ;
int open_conf_UART_(void) ;
int read_UART_(int uart_filestream, char* dest, int max_len) ;
#endif
Source file:
#include <errno.h>
#include "uartlib.h"
unsigned int BAUD_ = B38400 ;
unsigned int NUM_BITS_ = CS8 ;
char *UART_PATH_ = "/dev/ttyAMA0" ;
unsigned int OPEN_FLAG_ = O_RDWR ;
time_t TIMEOUT_SEC_ = 2 ;
suseconds_t TIMEOUT_USEC_ = 0 ;
// This needs to be finely tuned
suseconds_t TIMEOUT_BYTE_ = 5000;
int open_conf_UART_()
{
// Variable section
int indicator;
int uart_filestream ;
struct termios options ;
// Opening the port in a read/write mode
uart_filestream = open(UART_PATH_, OPEN_FLAG_ | O_NOCTTY | O_NONBLOCK);
if (uart_filestream < 0)
{
// Unable to open the serial port, so produce an error and halt
return -1;
}
// Configuring the options for UART
// Flushing the file stream (the input and the output area)
indicator = tcflush(uart_filestream, TCIOFLUSH);
if(indicator < 0)
{
// Unable to flush
close(uart_filestream);
return -1;
}
// Retrieve the options and modify them.
indicator = tcgetattr(uart_filestream, &options);
if(indicator < 0)
{
// Unable to get the attributes
close(uart_filestream);
return -1;
}
// Setting the options
cfmakeraw(&options);
options.c_cflag |= BAUD_ | NUM_BITS_ | CREAD;
// Setting the options for the file stream.
indicator = tcsetattr(uart_filestream, TCSANOW, &options);
if(indicator < 0)
{
// Unable to set the attributes
close(uart_filestream);
return -1;
}
return uart_filestream;
}
int read_UART_(int uart_filestream, char* dest, int max_len)
{
// Variable section
int indicator;
int buffer_length;
char *tmp_dest;
fd_set set;
struct timeval timeout, init_timeout;
while(1)
{
// Reseting the set and inserting the uart_filestream in it
FD_ZERO(&set);
FD_SET(uart_filestream, &set);
// Setting the time for initial contact
init_timeout.tv_sec = TIMEOUT_SEC_ ;
init_timeout.tv_usec = TIMEOUT_USEC_ ;
// Waiting for the first contact. If this times out, we assume no contact.
indicator = select(uart_filestream + 1, &set, NULL, NULL, &init_timeout);
if(indicator < 0)
{
if(errno == EINTR)
{
// Try again
continue;
}
return -1;
}
else if(indicator == 0)
{ // Timeout has occurred
return -2;
}
else
{
break;
}
}
// This section means that there is something to be read in the file descriptor
buffer_length = 0 ;
tmp_dest = dest ;
// The first select is redundant but it is easier to loop this way.
while(buffer_length < max_len)
{
// select changes the timeval structure so it is reset here
timeout.tv_sec = 0;
timeout.tv_usec = TIMEOUT_BYTE_;
// Reinitialize the sets for reading
FD_ZERO(&set);
FD_SET(uart_filestream, &set);
// Wait for the file descriptor to be available or for timeout
indicator = select(uart_filestream+1, &set, NULL, NULL, &timeout);
if(indicator < 0)
{
if(errno == EINTR)
{
// Try again
continue;
}
// This indicates an error
return -1;
}
else if(indicator == 0)
{
// This indicates a timeout; We assume that the transmission is over once first timeout is reached
return buffer_length;
}
// There's been a select that didn't time out before this read
indicator = read(uart_filestream, (void*)tmp_dest, max_len - buffer_length);
if(indicator < 0)
{
if(errno == EINTR)
{
// If the call was interrupted, try again
continue;
}
// If it was any other condition, the read is corrupt.
return -1;
}
else if(indicator == 0)
{
// If, somehow, EOF was reached
break;
}
// Change the necessary values
buffer_length += indicator ;
tmp_dest += indicator;
}
// Both branches of the if statement above have return, so this will not be reached
// but a warning is generated
return buffer_length;
}
void flush_buffer_UART_(int uart_filestream)
{
char c;
while(read(uart_filestream, &c, 1) > 0);
}
I know it is not the topic here, but if someone knows how to solve the flush issue, please respond.
Also, any constructive criticism is very welcome.
P.S. I also have a write_UART() function but I did not deem necessary to post it as it represented no problem (measured with an oscilloscope and later, tried with echo. Echo wouldn't be able to give me the same message).
EDIT: Flush has been introduced and then merged with the source file. Still haven't figured out is it working or not.
I am writing the data to /dev/ttyO3 in my application .The write is succeeded but not visible int he cat /dev/ttyO3.
ttyO3 is the device name for the uart4 instance of omap4460 pandaboard.
Edit 1:But some pulses are showing up when I probe through CRO.
How should I change my code to enable the software loop back?ie(I want the same pulse to be seen at rx pin without shorting Tx-Rx)
#define DEVICE "/dev/ttyO3"
int main()
{
int fd;
int write_fd1;
struct termios options;
fd = open(DEVICE,O_RDWR);
if(fd < 0)
printf("unable to open the device\n");
else
printf("device opened %d \n",fd);
tcgetattr(fd,&options);
cfsetospeed(&options,B300);
cfsetispeed(&options,B300);
tcsetattr(fd,TCSANOW,&options);
tcgetattr(fd,&options);
if((cfgetospeed(&options) != B300) || (cfgetispeed(&options)!= B300));
{
printf("Baud rate not set");
}
while(1)
{
write_fd1 = write(fd,"a",2) ;
printf("write_fd %d \n",write_fd1);
}
close(fd);
return 0;
}
I use a GSM/GPRS module called SIM340DZ, and use AT commands to be able manage the module.
I am able to send a UDP packet to a remote computer at a specific port from the GPRS module. Now, I would like to transfer a UDP packet from computer to the GPRS unit. But, the GPRS unit has a private IP address (e.g. 10.46.123.25), and the access point name (APN) is internet.tele2.se
Could anyone please explain how I can send a UDP data from a (linux) computer to the GPRS unit? What information do I need to know and how can I find it out?
Additionally, if you have experience in AT commands, I would also appreciate if you could explain me what command sequence do I need to use to configure the module on UDP listening mode?
For the ones who needs to deal with similar system, I am posting the code that you can send UDP packets to a destinated port and IPaddress through the serial port by using AT commands. Explanations are included as comment on the code:
int Serial_Close(int *fd);
int Serial_Send(int *fd, char *string);
int Serial_Open(int* fd, char *serial_Name, speed_t baudrate);
int main(int argc, char** argv)
{
int fd;
Serial_Open(&fd, "/dev/ttyAPP0", B115200); //open the UART interface with 115200 boundrate, 8 1 N
if(tcflush(fd, TCIOFLUSH) != 0)
{
exit(1); //error
fprintf(stderr, "tcflush error\n");
}
Serial_Send(&fd, "ATE0\r\n"); //ATE0 = echo mode(ATE) is off (0)
sleep(1);
Serial_Send(&fd, "AT+CGATT=1\r\n");
sleep(1);
Serial_Send(&fd, "AT+AT+CSTT=\"internet.tele2.se\"\r\n"); //here you define the name the APN
sleep(1);
Serial_Send(&fd, "AT+CIICR\r\n");
sleep(1);
Serial_Send(&fd, "AT+cipstart=\"UDP\",\"85.1.2.3\",\"20000\"\r\n"); //85.1.2.3 is the destination IP address, 20000 is the destination Port number
sleep(1);
Serial_Send(&fd, "AT+CIPSEND=5\r\n");
sleep(1);
Serial_Send(&fd, "12345\r\n"); //12345 is the message
sleep(1);
Serial_Send(&fd, "AT+CIPSHUT\r\n");
sleep(1);
Serial_Close(&fd);
return 0;
}
int Serial_Open(int* fd, char *serial_Name, speed_t baudrate)
{
struct termios serCfg;
memset(&serCfg, 0, sizeof(serCfg));
if((*fd = open(serial_Name, O_RDWR)) < 0)
return -1;
else
if(tcgetattr(*fd, &serCfg) != 0)
return -1;
cfsetispeed(&serCfg, baudrate);
cfsetospeed(&serCfg, baudrate);
cfmakeraw(&serCfg);
if(tcsetattr(*fd, TCSANOW, &serCfg) != 0)
return -1;
return 0;
}
int Serial_Send(int *fd, char *string)
{
int len;
char *buffer;
int bytes_sent;
len = strlen(string);
if(len > 255)
return -1;
buffer = (char*)malloc((len+1)*sizeof(char));
if(buffer == NULL)
return -1;
strcpy(buffer, string);
buffer[len] = 0;
bytes_sent = write(*fd, buffer, strlen(buffer));
if(bytes_sent < 0)
{
close (*fd);
return -1;
}
else
{
free(buffer);
return 0;
}
}
int Serial_Close(int *fd)
{
if(close (*fd) < 0)
return -1;
else
return 0;
}
I hope it helps to someone.