izmit escort escort ankara adana escort

 FAQ •  Search •  Register •  Login 

All times are UTC + 1 hour [ DST ]




Post new topic Reply to topic  [ 4 posts ] 
Author Message
 Post subject: problem with SAMA5D35 running AT91 linux and uart in RS485
PostPosted: Tue Apr 11, 2017 8:46 am 
Offline

Joined: Thu Sep 15, 2016 10:07 am
Posts: 12
Hej

Since last November(2016) I try to use the usart1 in RS485 mode. Every time when I was sending a byte(tx) the receive buffer(rx) is filled with a byte.

There some fixes for the kernel but it seems, that they are not affecting my problem.

My system:
- HW: SAMA5D35-CM
- OS: Linux 4.4.57-01287-g55bb80b (AT91 Linux)

I am using Yocto + meta-atmel to build my custom linux. At yocto I am on the yocto morty branch.

I am using an lightly modified dts:
Code:
usart1: serial@f0020000 {
   pinctrl-0 = <&pinctrl_usart1 &pinctrl_usart1_rts_cts>;
   linux,rs485-enabled-at-boot-time;
   rs485-rts-delay = <0 20>;
   status = "okay";
};


My RS485 test is very simple:
1st) open UART in "O_RDWR" mode
2nd) set tty:
Code:
struct termios tty;

memset (&tty, 0, sizeof tty);

// get old cfg
tcgetattr ( pSP->fd, &tty );
savetty = tty;

// set Baud Rate
cfsetospeed (&tty, B9600);
cfsetispeed (&tty, B9600); // set input speed = output speed

cfmakeraw(&tty);

tty.c_cc[VMIN] = 1;
tty.c_cc[VTIME] = 10;

tty.c_cflag &= ~CSTOPB;
tty.c_cflag &= ~CRTSCTS;    /* no HW flow control? */
tty.c_cflag |= CLOCAL | CREAD;

// Flush Port, then applies attributes
tcflush(fd, TCIFLUSH );
tcsetattr (fd, TCSANOW, &tty );

3rd) enable RS485
Code:
struct serial_rs485 rs485conf;

memset(&rs485conf, 0, sizeof(struct serial_rs485));

ioctl (fd, TIOCGRS485, &rs485conf);

// enable RS485 mode
// set logical level for RTS pin equal to 1 when sending
rs485conf.flags |= SER_RS485_ENABLED | SER_RS485_RTS_ON_SEND;

// Set rts delay before send, if needed:
rs485conf.delay_rts_before_send = 0;

// Set rts delay after send, if needed:
rs485conf.delay_rts_after_send = 20;

ioctl (fd, TIOCSRS485, &rs485conf);

4th) start a posix-thread which is reading from the rs485
Code:
static void * helper_serialPortThreadFunc(void * argument) {
   int * pfd = (TSerialPort *) argument;

   char rxB[drxBufferSize];
   char * szRes;
   size_t am;

   printf("[%s] i/o polling thread is created", __FUNCTION__);

   for (;;) {
      am = read(*pfd, rxB, drxBufferSize);
      rxB[am]=0;
      printf("[%s] rx: %s", __FUNCTION__, rxB);
   }
   pthread_exit(NULL);
}

static int helper_startSerialPort(int * pfd) {
   char szDummy[100];
   if (pthread_create(&gth, NULL, &helper_serialPortThreadFunc, pfd)) {
      return -1;
   }
   sprintf(szDummy, "i/o thread for rs232/rs485 with fid=%i", *pfd);
   pthread_setname_np(gth, szDummy);
   return 0;
}

5th) write to rs485
Code:
static void helper_writeSerialPort(int * pfd, void * pD, size_t nBytes) {
   printf("[%s] start write", __FUNCTION__);
   nBytes = write(*pfd, pD, nBytes);
   printf("[%s] %u Bytes written", __FUNCTION__, (unsigned int)nBytes);
}


Every time I write some bytes to the tx at the rx are bytes generated. Their value is 0. They are generated after the write call is finished.

Any ideas?


Top
 Profile  
Reply with quote  
 Post subject: Re: problem with SAMA5D35 running AT91 linux and uart in RS4
PostPosted: Wed Apr 12, 2017 9:13 pm 
Offline

Joined: Thu Apr 19, 2007 10:15 pm
Posts: 1478
Location: USA
Stefan J wrote:
My RS485 test is very simple:
It's too simple. The return codes from syscalls are not checked, so any errors will be silently ignored.

Stefan J wrote:
Every time I write some bytes to the tx at the rx are bytes generated.
Since cfmakeraw() has already disabled the termios echo, this is not a software issue, but rather a hardware issue.
You haven't described the RS-485 implementation on your board.

Stefan J wrote:
Their value is 0.
Have you verified that you're not transmitting nulls? You make no mention of any other transmit or receive capability/sucess.

FYI the Linux man page for termios mentions that
Quote:
If neither IGNPAR nor PARMRK is set, read a character with a parity error or framing error as \0.
IGNPAR is typically clear by default, and cfmakeraw() clears PARMRK, so that would satisfy the conditions for this receive conversion.

Regards


Top
 Profile  
Reply with quote  
 Post subject: Re: problem with SAMA5D35 running AT91 linux and uart in RS4
PostPosted: Thu Apr 13, 2017 9:57 am 
Offline

Joined: Thu Sep 15, 2016 10:07 am
Posts: 12
I list my code to produce this error. Maybe it helps to reproduce the error.

1st cpp-File "testApp.cpp":
Code:
#include <string.h>
#include <strings.h>
#include <errno.h>
#include <stdbool.h>
#include <stdio.h>

#include <termios.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/signal.h>
#include <fcntl.h>
#include <signal.h>

#include <linux/serial.h>
#include <sys/ioctl.h>

#include <pthread.h>
#include <semaphore.h>
#include <ctype.h>

#define drxBufferSize (1024)

typedef enum eAppErrorCodes {
   eAppErrorCode_none = 0,
   eAppErrorCode_readConf,
   eAppErrorCode_setUART,
   eAppErrorCode_getRS485,
   eAppErrorCode_setRS485,
   eAppErrorCode_AppArgUnknown,
   eAppErrorCode_openBSPfile,
   eAppErrorCode_openFailed,
   eAppErrorCode_ThreadCreateFailed,
} TAppErrorCode;

typedef struct SSerialConfig {
   const char * szDeviceName;
   int sek4pinInit;

   speed_t baudrate;
   tcflag_t bits;
   tcflag_t stopBits;
   tcflag_t parity;

   int rs485enabled;
   __u32 delay_rts_before_send;
   __u32 delay_rts_after_send;
} TSerialConfig;

typedef struct SSerialPort{
   int   fd; //!< the file handle
   bool rs485enabled; //!< flag if the rs485 interface is used
   pthread_t th; //!< the thread handle
   struct termios  savetty;
} TSerialPort;

typedef struct SApp {
   TSerialConfig cfg;
   sem_t exitSem;
} TApp;

TApp gApp;

// ----------------
// baud rate
// ----------------

//! type for associating the baudrate with the pedefined ones
typedef struct SBaudrateConvEle {
   const int br;   //!< baud rate
   const speed_t ibr; //!< interface baud rate ident
} TBaudrateConvEle;

//! global table containing baudrates
const TBaudrateConvEle gBRC [] = {
   {.br = 50,.ibr = B50},
   {.br = 75,.ibr = B75},
   {.br = 110,.ibr = B110},
   {.br = 134,.ibr = B134},
   {.br = 150,.ibr = B150},
   {.br = 200,.ibr = B200},
   {.br = 300,.ibr = B300},
   {.br = 600,.ibr = B600},
   {.br = 1200,.ibr = B1200},
   {.br = 1800,.ibr = B1800},
   {.br = 2400,.ibr = B2400},
   {.br = 4800,.ibr = B4800},
   {.br = 9600,.ibr = B9600},
   {.br = 19200,.ibr = B19200},
   {.br = 38400,.ibr = B38400},
   {.br = 57600,.ibr = B57600},
   {.br = 115200,.ibr = B115200},
   {.br = 230400,.ibr = B230400},
   {.br = 460800,.ibr = B460800},
   {.br = 500000,.ibr = B500000},
   {.br = 576000,.ibr = B576000},
   {.br = 921600,.ibr = B921600},
   {.br = 1000000,.ibr = B1000000},
   {.br = 1152000,.ibr = B1152000},
   {.br = 1500000,.ibr = B1500000},
   {.br = 2000000,.ibr = B2000000},
   {.br = 2500000,.ibr = B2500000},
   {.br = 3000000,.ibr = B3000000},
   {.br = 3500000,.ibr = B3500000},
   {.br = 4000000,.ibr = B4000000}
};

//! returns the terminos baud rate
speed_t helper_getBaudrate (int br) {
   unsigned int i;
   for (i = 0; i < sizeof(gBRC)/sizeof(const TBaudrateConvEle); i++) {
      if (gBRC[i].br == br) return gBRC[i].ibr;
   }
   return B0;
}

// ----------------
// parity
// ----------------
typedef struct SparityAsso {
   const tcflag_t pa;
   const char * szParName;
} TparityAsso;

const TparityAsso gCParAsso [] = {
   {.pa=0 , .szParName="no"},
   {.pa=PARENB | PARODD , .szParName="odd"},
   {.pa=PARENB , .szParName="even"},
};

//! helper to get the numeric expression of a parity string
tcflag_t helper_getParityFromString(const char * szPar) {
   unsigned int i;
   for (i = 0; i < sizeof(gCParAsso)/sizeof(const TparityAsso); i++) {
      if (!strcasecmp(gCParAsso[i].szParName, szPar)) return gCParAsso[i].pa;
   }
   return 0;
}

// ----------------
// data bits
// ----------------
typedef struct SdatabitsAsso {
   const tcflag_t idb; //!< data interface bits
   const int db; //!< numeric expression
} TdatabitsAsso;

const TdatabitsAsso gCdatabitsAsso [] = {
   {.idb = CS5, .db = 5},
   {.idb = CS6, .db = 6},
   {.idb = CS7, .db = 7},
   {.idb = CS8, .db = 8},
};

//! helper to get the databits
static tcflag_t helper_getDatabits(const int db) {
   unsigned int i;
   for (i = 0; i < sizeof(gCdatabitsAsso)/sizeof(const TdatabitsAsso); i++) {
      if (db == gCdatabitsAsso[i].db) return gCdatabitsAsso[i].idb;
   }
   return 0;
}

static TAppErrorCode helper_setUart (TSerialPort * pSP, TSerialConfig * pCfg) {
   struct termios tty;

   memset (&tty, 0, sizeof tty);

   // get old cfg
   if ( tcgetattr ( pSP->fd, &tty ) != 0 ) {
      fprintf(stderr, "[%s] getting UART attributes failed with: %s\n", __FUNCTION__ , strerror(errno));
      return eAppErrorCode_setUART;
   }

   pSP->savetty = tty;

   // set Baud Rate
   if (-1 == cfsetospeed (&tty, pCfg->baudrate)) {
      fprintf(stderr, "[%s] cfsetospeed failed with: %s\n", __FUNCTION__ , strerror(errno));
      return TAppErrorCode::eAppErrorCode_setUART;
   }
   if (-1 == cfsetispeed (&tty, pCfg->baudrate)) {
      fprintf(stderr, "[%s] cfsetispeed failed with: %s\n", __FUNCTION__ , strerror(errno));
      return TAppErrorCode::eAppErrorCode_setUART;
   }

   cfmakeraw(&tty);

   tty.c_cc[VMIN] = 1;
   tty.c_cc[VTIME] = 10;

   tty.c_cflag &= ~CSTOPB;
   tty.c_cflag &= ~CRTSCTS;    /* no HW flow control? */
   tty.c_cflag |= CLOCAL | CREAD;

   // Flush Port, then applies attributes
   tcflush( pSP->fd, TCIFLUSH );
   if ( tcsetattr ( pSP->fd, TCSANOW, &tty ) != 0) {
      fprintf(stderr, "[%s] set UART attributes failed with: %s\n", __FUNCTION__ , strerror(errno));
      return eAppErrorCode_setUART;
   }
   return eAppErrorCode_none;
}

static TAppErrorCode helper_setRS485(int rs485ID, TSerialConfig * pCfg) {
   struct serial_rs485 rs485conf;

   memset(&rs485conf, 0, sizeof(struct serial_rs485));

   if (ioctl (rs485ID, TIOCGRS485, &rs485conf) < 0) {
      fprintf(stderr, "[%s] get rs485 attributes failed with: %s\n", __FUNCTION__ , strerror(errno));
      return eAppErrorCode_getRS485;
   }

   // enable RS485 mode
   // set logical level for RTS pin equal to 1 when sending
   rs485conf.flags |= SER_RS485_ENABLED | SER_RS485_RTS_ON_SEND;

   // Set rts delay before send, if needed:
   rs485conf.delay_rts_before_send = pCfg->delay_rts_before_send;

   // Set rts delay after send, if needed:
   rs485conf.delay_rts_after_send = pCfg->delay_rts_after_send;

   if (ioctl (rs485ID, TIOCSRS485, &rs485conf) < 0) {
      fprintf(stderr, "[%s] set rs485 attributes failed with: %s\n", __FUNCTION__ , strerror(errno));
      return eAppErrorCode_setRS485;
   }
   return eAppErrorCode_none;
}

static TAppErrorCode helper_openSerialPort(TSerialPort * pSP, TSerialConfig * pCfg) {
   TAppErrorCode e;


   printf("[%s] try to open %s\n", __FUNCTION__, pCfg->szDeviceName);

   memset(pSP, 0, sizeof(TSerialPort));

   // open uart port in blocking mode
   pSP->fd = open (pCfg->szDeviceName, O_RDWR);
   if (pSP->fd < 0) {
      fprintf(stderr, "[%s] open %s failed with: %s\n", __FUNCTION__,pCfg->szDeviceName , strerror(errno));
      pSP->fd = -1;
      return eAppErrorCode_openFailed;
   }
   printf("[%s] fid=%i\n", __FUNCTION__, pSP->fd);

   // setup port
   printf( "[%s] set UART parameter ...\n", __FUNCTION__);
   if (eAppErrorCode_none != (e = helper_setUart(pSP, pCfg))) {
      return e;
   }

   // enable rs485 if wanted
   if (pCfg->rs485enabled == 1) {
      printf( "[%s] set RS485 parameter ...\n", __FUNCTION__);
      if (eAppErrorCode_none != (e = helper_setRS485(pSP->fd, pCfg))) {
         return e;
      }
   } else {
      printf( "[%s] RS485 is disabled in configuration\n", __FUNCTION__);
   }

   pSP->rs485enabled = pCfg->rs485enabled == 1 ? true : false;
   return eAppErrorCode_none;
}

static void helper_closeSerialPort(TSerialPort * pSP) {
   printf( "[%s] close fid=%i\n", __FUNCTION__, pSP->fd);

   if (pSP->fd != -1) {
      tcsetattr ( pSP->fd, TCSANOW, &pSP->savetty );
      close(pSP->fd);
   }
   pSP->fd = -1;
}

static void * helper_serialPortThreadFunc(void * argument) {
   TSerialPort * pSP = (TSerialPort *) argument;

   char rxB[drxBufferSize];
   size_t am;
   size_t i;

   printf( "[%s] i/o polling thread is created\n", __FUNCTION__);

   for (;;) {
      am = read(pSP->fd, rxB, drxBufferSize);
      printf( "[%s] rx: ", __FUNCTION__);
      for (i = 0; i < am; i++) {
         if (isprint(rxB[i])) {
            printf( "%c", rxB[i]);
         } else {
            printf( "0x%X", (int)rxB[i]);
         }
      }
      printf( "\n");
   }
   pthread_exit(NULL);
}


static TAppErrorCode helper_startSerialPort(TSerialPort * pSP) {
   char szDummy[100];
   printf( "[%s] create RX handler thread\n", __FUNCTION__);
   if (pthread_create(&pSP->th, NULL, &helper_serialPortThreadFunc, pSP)) {
      fprintf(stderr, "[%s] creating thread failed\n", __FUNCTION__);
      return eAppErrorCode_ThreadCreateFailed;
   }
   sprintf(szDummy, "i/o thread for rs232/rs485 with fid=%i\n", pSP->fd);
   pthread_setname_np(pSP->th, szDummy);
   return eAppErrorCode_none;
}

static void helper_stopSerialPort(TSerialPort * pSP) {
   printf( "[%s] stop RX handler thread\n", __FUNCTION__);
   pthread_cancel(pSP->th);
   pthread_join(pSP->th, NULL);
}

static void helper_writeSerialPort(TSerialPort * pSP, void * pD, size_t nBytes) {
   printf( "[%s] start write\n", __FUNCTION__);
   nBytes = write(pSP->fd, pD, nBytes);
   printf( "[%s] %u Bytes written\n", __FUNCTION__, (unsigned int)nBytes);
}

static void * helper_stdinThreadFunc(void * argument) {
   TSerialPort * pSP = (TSerialPort *) argument;
   char line[1024];

   fprintf(stdout, "Program started. Enter chars and press enter to send.\n");
   fflush(stdout);

   for (;;) {
      fgets (line, sizeof(line), stdin);
      helper_writeSerialPort(pSP, line, strlen(line));
   }
}


void sig_handler(int sig) {
   printf( "[%s] signal=%i\n", __FUNCTION__, sig);
    switch(sig)
    {
        case SIGHUP:
        case SIGINT:
        case SIGKILL:
        case SIGTERM:
           printf( "[%s] exit signal\n", __FUNCTION__);
           sem_post(&gApp.exitSem);
           break;
        case SIGSTOP:
           printf( "[%s] stop signal\n", __FUNCTION__);

           break;
        case SIGCONT:
           printf( "[%s] resume signal\n", __FUNCTION__);

           break;
        case SIGUSR1:
           printf( "[%s] reinit signal\n", __FUNCTION__);

         break;
        default:
           printf( "[%s] unknown signal\n", __FUNCTION__);
    }

}

typedef struct SSignalHandlerAsso {
   const int sig;
   const __sighandler_t handler;
} TSignalHandlerAsso;

const TSignalHandlerAsso gUnixSignalMap [] = {
   {.sig=SIGUSR1, .handler=sig_handler},
   {.sig=SIGHUP, .handler=sig_handler},
   {.sig=SIGINT, .handler=sig_handler},
   {.sig=SIGKILL, .handler=sig_handler},
   {.sig=SIGTERM, .handler=sig_handler},
   {.sig=SIGSTOP, .handler=sig_handler},
   {.sig=SIGCONT, .handler=sig_handler}
};


int main(int argc, char* argv[]) {
   (void)(argc);
   (void)(argv);

   unsigned int i;
   TSerialPort sp;
   pthread_t stdinTh;

   // init logging
    printf("start RS485 test");

    // set up app
    memset(&gApp, 0, sizeof(TApp));
    sem_init(&gApp.exitSem, 0, 0);
    gApp.cfg.szDeviceName = "/dev/ttyS2";
    gApp.cfg.baudrate = helper_getBaudrate(9600);
    gApp.cfg.parity = helper_getParityFromString("no");
    gApp.cfg.bits = helper_getDatabits(8);
    gApp.cfg.stopBits = 0;

    gApp.cfg.rs485enabled = 1;
    gApp.cfg.delay_rts_after_send = 20;
    gApp.cfg.delay_rts_before_send = 0;

    memset(&sp, 0, sizeof(TSerialPort));

   // install signal handlers
    for (i = 0; i < sizeof(gUnixSignalMap)/sizeof(const TSignalHandlerAsso); i++) {
      signal(gUnixSignalMap[i].sig, gUnixSignalMap[i].handler);
    }


   if (eAppErrorCode_none != helper_openSerialPort(&sp, &gApp.cfg)){
      goto exit;
   }

   if (eAppErrorCode_none != helper_startSerialPort(&sp)){
      goto exit;
   }

   pthread_create(&stdinTh, NULL, &helper_stdinThreadFunc, &sp);
   pthread_setname_np(stdinTh, "stdin rx thread");

   sem_wait(&gApp.exitSem);
   // IV. exit
   printf("closes RS485 test");

exit:
   helper_stopSerialPort(&sp);
   helper_closeSerialPort(&sp);

   sem_close(&gApp.exitSem);
    return 0;

}


2nd Makefile "CMakeLists.txt" for x-compile:
Code:
cmake_minimum_required (VERSION 3.0)
# module name
set(PrjName testApp)

project (${PrjName})
# module version
set(PCK_MAJOR 1)
set(PCK_MINOR 0)
set(PCK_REVISION 0)

set(${PrjName}_VERSION_MAJOR 1)
set(${PrjName}_VERSION_MINOR 0)
set(${PrjName}_VERSION_REVISION 0)
set(${PrjName}_SOVERSION 1)

# the libs goes into BASE_LIBS
set(USR_LIBS "")

# --- lib rt ---
find_library (LIB_RT rt)

# --- Lib pthread ---
find_library (LIB_PTHREAD pthread)
list(APPEND USR_LIBS ${LIB_PTHREAD})


set(${PrjName}_SCL
    ${CMAKE_CURRENT_SOURCE_DIR}/src/testApp.cpp
)

# SEK4ethCheck build
add_executable(${PrjName} ${${PrjName}_SCL})

set_target_properties(${PrjName} PROPERTIES
    LINKER_LANGUAGE CXX
    VERSION "${${PrjName}_VERSION_MAJOR}.${${PrjName}_VERSION_MINOR}.${${PrjName}_VERSION_REVISION}"
    SOVERSION ${${PrjName}_SOVERSION}
)

target_link_libraries(${PrjName}
    ${LIB_RT}
    ${LIB_PTHREAD}
)

target_compile_options(${PrjName} PUBLIC -D_GNU_SOURCE)


3rd Console print:
Code:
root@sama5d3xek:~# /tmp/testApp-1.0.0
start RS485 test[helper_openSerialPort] try to open /dev/ttyS2
[helper_openSerialPort] fid=3
[helper_openSerialPort] set UART parameter ...
[helper_openSerialPort] set RS485 parameter ...
[helper_startSerialPort] create RX handler thread
Program started. Enter chars and press enter to send.
[helper_serialPortThreadFunc] i/o polling thread is created
hello
[helper_writeSerialPort] start write
[helper_writeSerialPort] 6 Bytes written
[helper_serialPortThreadFunc] rx: 0x0
[helper_serialPortThreadFunc] rx: 0x0
[helper_serialPortThreadFunc] rx: 0x0
[helper_serialPortThreadFunc] rx: 0x0
[helper_serialPortThreadFunc] rx: 0x0
[helper_serialPortThreadFunc] rx: 0x0


Hope this helps!


Top
 Profile  
Reply with quote  
 Post subject: Re: problem with SAMA5D35 running AT91 linux and uart in RS4
PostPosted: Fri Apr 14, 2017 8:51 pm 
Offline

Joined: Thu Apr 19, 2007 10:15 pm
Posts: 1478
Location: USA
Stefan J wrote:
I list my code to produce this error. Maybe it helps to reproduce the error.
...
Hope this helps!
No, it doesn't. I don't have your board(s), so how could I reproduce what is a hardware issue?

Regards


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 4 posts ] 

All times are UTC + 1 hour [ DST ]


Who is online

Users browsing this forum: Google [Bot] and 2 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: