QSerialPort is in use before application starts - c++

I am developing an application for Apalis iMX6 with Qt C++ in Linux and I've added this application into the startup by means of profile.d
this code must set ttymxc1 into RS485 mode like below:
int enableRS485(){
struct serial_rs485 rs485conf;
int fd = open ("/dev/ttymxc1", O_RDWR);
if (fd < 0) {
printf("Error: Can't open: /dev/ttymxc1 %d\n",fd);
return fd;
}
rs485conf.flags |= SER_RS485_ENABLED;
rs485conf.flags &= ~(SER_RS485_RTS_ON_SEND);
rs485conf.flags |= SER_RS485_RTS_AFTER_SEND;
rs485conf.flags |= SER_RS485_RX_DURING_TX;
err = ioctl (fd, TIOCSRS485, &rs485conf);
if (err < 0) {
printf("Error: TIOCSRS485 ioctl not supported.\n");
return err;
}
err = close (fd);
if (err < 0) {
printf("Error: Can't close: /dev/ttyLP1 %d\n",err);
return err;
}
return 0;
}
this function is working as well and has no problem. but when I try to open the serial port sometimes during startup application couldn't get this serial port and QSerialPortInfo shows me ttymxc1 is in use. my initiation of the serial port is like below:
void SerialClass::initSerial()
{
m_serialPort = new QSerialPort();
enableRS485();
sleep(1);
m_serialPort->setPortName("/dev/ttymxc1");
m_serialPort->setFlowControl(QSerialPort::NoFlowControl);
m_serialPort->setBaudRate(9600);
m_serialPort->setRequestToSend(false);
bool res = m_serialPort->open(QIODevice::ReadWrite);
}
"QSerialPort::errorOccured" signal will emit with value "PermissionError"
but mysteriously "ls -l /proc/[0-9]/fd/ |grep /dev/ttymxc1" shows me ttymxc1 is in used by my application.
there is no application that works with serial port and my application is just for one time run.
Is there any idea?
Thanks

You need to call close() on m_serialPort when you close your application. Otherwise your serial port will keep in-use state.

I've found a new remedy, so I want to share it here.
in SerialClass constructor I've added initSerial(), in this way application at the beginning of starting, will open the ttymxc1.
There is no more problem with such a solution.
I don't have such an issue with Raspberry Pi (Raspberry Pi3 + Qt 5.6 + Raspbian). But Toradex Apalis is in another way.
Would you please tell me why?

Related

freeDiameter based server cannot read received buffer

I have tried to set up a server with a specific IP address and Port number by freeDiameter libraries. In other side, there is a client that sends a string message via freeDiameter libraries successfully; I checked it out in Wireshark.
So, here is the problem; when I start listening from the server side, it has no problem until a client sends a connection request; if you look at the below code, "fd_cnx_serv_accept(listener)" is listening to a socket named "listener" which is bind to a specific IP address and Port number.
uint8_t * rcv_buf;
size_t rcv_size;
struct cnxctx * listener_side = NULL;
int ret;
listener_side = fd_cnx_serv_accept(listener);
ret = fd_cnx_start_clear(listener_side, 0);
if(ret != 0){
std::cout<<side<<" is unable to accept connections."<<std::endl;
return -1;
}
ret = fd_cnx_receive(listener_side, NULL, &rcv_buf, &rcv_size);
if(ret == 0){
std::cout<<"Message received."<<std::endl;
listener_side = NULL;
free(rcv_buf);
}
The program works fine until it gets a client request; when "fd_cnx_serv_accept" accept the client side, the program tries to receive the message by "fd_cnx_receive"; but the program stops and shows the error "Segmentation fault (core dumped)". Then, I test the program by gdb and it shows that it is something wrong with the line 309 of "hook.c". Here is the image of the error which is shown by gdb.
Error Screenshot
transcript
multi-thre Thread 0x7fffff72a77 In: fd_hook_call
[New Thread 0x7fffff72a7700 (LWP 1612914)
Thread 2 "server" received signal SIGSEGEV, Segmentation Fault
[Switching to Thread 0x7fffff72a7700 (LWP 1612914)
--Type <RET> for more, q to quit, c to continue without paging --c
0x00007ffff7f2cefc in fd_hook_call (type=HOOD_DATA_RECEIVED, msg=0x0, peer=0x0, other=0x7ffff72a6be0, pmdl=0x7ffff0000ba8 at /root/projects/start_cnx_free/third-party/libfdcore/hooks.c:309
It is good to mention that I am trying to write a c++ program.
How can I solve this problem ?
I solved this problem myself. I forgot to use fd_hooks_init() at the begining of my program to initialize necessary libraries and objects.
Here is the modified code:
/* Initialize the library -- must come first since it initializes the debug facility */
int ret = fd_libproto_init();
if (ret != 0) {
fprintf(stderr, "Unable to initialize libfdproto: %s\n", strerror(ret));
return ret;
}
ret = fd_hooks_init();
if(ret != 0){
std::cout<<"Unable to initialize the hooks."<<std::endl;
return ret;
}
/* Initialize the config with default values */
memset(&g_conf, 0, sizeof(struct fd_config));
fd_g_config = &g_conf;
ret = fd_conf_init();
if (ret != 0) {
printf("Unable to initialize the config with default values.");
return ret;
}
/* Add definitions of the base protocol */
ret = fd_dict_base_protocol(fd_g_config->cnf_dict);
if (ret != 0) {
printf("Unable to add definitions of the base protocol.");
return ret;
}

How to set low latency in serial port open by QSerialPort

I have already developed an application and it performs serial communication with sensors.
For an unknown reason, my received data is slow with QT C++ Framework.
I have tested the sample code (https://www.pjrc.com/tmp/host_software/receive_test.c). I received data in the appropriate time with this sample code.
Here i found that low latency mode is set ASYNC_LOW_LATENCY.
I have read (https://doc.qt.io/qt-5/qserialport.html) but didn't get any idea about how to set low latency with QSerialPort
Q1: Please give a sample code in qt c++ with QSerialPort on how to set low latency.
Please don't suggest writing c code inside qt c++ this is not the right approach to solve this probleam.
QSerialPort *pUsbSerialPort;
pUsbSerialPort = new QSerialPort();
if(IS_VALID_OBJ(pUsbSerialPort))
{
pUsbSerialPort->setPortName(sSerialPort);
pUsbSerialPort->setBaudRate(BaudRate);
pUsbSerialPort->setDataBits(QSerialPort::Data8);
pUsbSerialPort->setParity(QSerialPort::NoParity);
pUsbSerialPort->setStopBits(QSerialPort::OneStop);
pUsbSerialPort->setFlowControl(QSerialPort::NoFlowControl);
if(pUsbSerialPort->open(QIODevice::ReadWrite))
{
connect(pUsbSerialPort, &QSerialPort::readyRead,this , &Laser::LaserReadyRead);
PRINT_INFO("Serial port successfully initialized" + sSerialPort);
bIsServeropen = true;
}
else
{
PRINT_INFO("Serial port initialization failed" + sSerialPort);
return;
}
}
else
{
PRINT_INFO(" Failed to assign memory to pUsbSerialPort" + sSerialPort);
return;
}
The descriptor is the Handle of the QSerialPort:
#include <sys/ioctl.h>
#include <linux/serial.h>
// ...
pUsbSerialPort->open(QIODevice::ReadOnly);
int fd = pUsbSerialPort->handle();
struct serial_struct kernel_serial_settings;
::ioctl(fd, TIOCGSERIAL, &kernel_serial_settings);
kernel_serial_settings.flags |= ASYNC_LOW_LATENCY;
::ioctl(fd, TIOCSSERIAL, &kernel_serial_settings);

Trying to communicate with DMC20xx through USB interface NET2888

I am trying to communicate with a galil motion controler DMC2070 through its USB interface.
The USB interface of the DMC2070 is made with a NET2888 chip but it is not supported by windows 7 or 10.
I currently load the winusb driver and try to communicate with it with libusb-1.0 (statically linked 32bit version) and compile with mingw32-gcc under windows 10 (64bit).
I managed to claim the interface but could not send or receive messages.
Here is my test program :
#include <cstring>
#include <stdio.h>
#include "libusb/libusb.h"
int main(){
char entry;
libusb_context *context = nullptr;
int status, nwrite;
unsigned char buffer[64] = "TP\0";
libusb_device_handle *handle = nullptr;
printf("start usb test (y/n) ?");
scanf("%c", &entry);
if(entry=='n') return 0;
libusb_init(&context);
handle = libusb_open_device_with_vid_pid(context, 0x06B3, 0x07D1);
if(handle){
printf("Device %04x:%04x opened with success\n",0x06B3,0x07D1);
}
else {
libusb_exit(nullptr);
printf("device %04x:%04x not found\n",0x06B3,0x07D1);
system("pause");
return 1;
}
libusb_set_auto_detach_kernel_driver(handle, 1);
status = libusb_claim_interface(handle,0);
if(status!=0){
libusb_close(handle);
libusb_exit(nullptr);
fprintf(stderr, "usb_claim_interface error %d\n", status);
system("pause");
return 2;
}
printf("Interface claimed successfully\n");
status = libusb_bulk_transfer(handle, USB_ENDPOINT_OUT,
buffer, 64, &nwrite, TIMEOUT);
if(status==0) printf("send %d bytes to device\n", nwrite);
else printf("error %d, writing to device\n", status);
libusb_release_interface(handle,0);
libusb_close(handle);
libusb_exit(nullptr);
system("pause");
return 0;
}
Here is the resulting output :
start usb test (y/n) ?y
Device 06b3:07d1 opened with success
Interface claimed successfully
error -5, writing to device
Error -5 corresponds to LIBUSB_ERROR_NOT_FOUND which means "Entity not found".
I am not used to deal with USB interface directly, and hope someone with far more experience could enlighten my path.
I am thinking about installing a vm with windows xp and try reverse the driver.
you have to set the configuration before claim interface.

Simplest IPC from one Linux app to another in C++ on raspberry pi

I need the simplest most reliable IPC method from one C++ app running on the RPi to another app.
All I'm trying to do is send a string message of 40 characters from one app to another
The first app is running as a service on boot, the other app is started at a later time and is frequently exited and restarted for debugging
The frequent debugging for the second app is whats causing problems with the IPCs I've tried so far
I've tried about 3 different methods and here is where they failed:
File FIFO, the problem is one program hangs while the other program is writing to the file
Shared memory: cannot initialize on one thread and read from another thread. Also frequent exiting while debugging causing GDB crashes with the following GDB command is taking too long to complete -stack-list-frames --thread 1
UDP socket with localhost - same issue as above, plus improper exits block the socket, forcing me to reboot device
Non blocking pipe - not getting any messages on the receiving process
What else can I try? I dont want to get the DBus library, seems too complex for this application.
Any simple server and client code or a link to it would be helpful
Here is my non-blockign pipe code, that doesnt work for me,
I assume its because I dont have a reference to the pipe from one app to the other
Code sourced from here: https://www.geeksforgeeks.org/non-blocking-io-with-pipes-in-c/
char* msg1 = "hello";
char* msg2 = "bye !!";
int p[2], i;
bool InitClient()
{
// error checking for pipe
if(pipe(p) < 0)
exit(1);
// error checking for fcntl
if(fcntl(p[0], F_SETFL, O_NONBLOCK) < 0)
exit(2);
//Read
int nread;
char buf[MSGSIZE];
// write link
close(p[1]);
while (1) {
// read call if return -1 then pipe is
// empty because of fcntl
nread = read(p[0], buf, MSGSIZE);
switch (nread) {
case -1:
// case -1 means pipe is empty and errono
// set EAGAIN
if(errno == EAGAIN) {
printf("(pipe empty)\n");
sleep(1);
break;
}
default:
// text read
// by default return no. of bytes
// which read call read at that time
printf("MSG = % s\n", buf);
}
}
return true;
}
bool InitServer()
{
// error checking for pipe
if(pipe(p) < 0)
exit(1);
// error checking for fcntl
if(fcntl(p[0], F_SETFL, O_NONBLOCK) < 0)
exit(2);
//Write
// read link
close(p[0]);
// write 3 times "hello" in 3 second interval
for(i = 0 ; i < 3000000000 ; i++) {
write(p[0], msg1, MSGSIZE);
sleep(3);
}
// write "bye" one times
write(p[0], msg2, MSGSIZE);
return true;
}
Please consider ZeroMQ
https://zeromq.org/
It is lightweight and has wrapper for all major programming languages.

Unable to use windows.h ReadFile correctly on COM port. WriteFile seems to work fine

I am trying to use the windows.h library to communicate through RS232 with a device (SCPI communication). I have looked at several tutorials and guides on how to set this up and think my code should work correctly. I am able to send data to the device using WriteFile. However, I am not able to receive any data using ReadFile (ReadFile generates no errors but the buffer size is 0). Here is my code:
#include <stdio.h>
#include <windows.h>
void main ()
{
// CreateFile
HANDLE rs232 = CreateFileA ("\\\\.\\COM1", GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
if (rs232 == INVALID_HANDLE_VALUE)
{
printf ("fail CreateFile: %d\n", GetLastError ()); system ("pause"); return;
}
// Get & Set CommState
DCB port_configuration;
int err = GetCommState (rs232, &port_configuration);
if (err <= 0)
{
printf ("fail GetCommState: %d\n", GetLastError ()); CloseHandle (rs232); system ("pause"); return;
}
port_configuration.BaudRate = 19200;
port_configuration.ByteSize = 8;
port_configuration.Parity = 0;
port_configuration.StopBits = 0;
port_configuration.DCBlength = sizeof (port_configuration);
err = SetCommState (rs232, &port_configuration);
if (err <= 0)
{
printf ("fail SetCommState\n"); CloseHandle (rs232); system ("pause"); return;
}
// SetCommTimeouts
COMMTIMEOUTS timeout_configuration;
timeout_configuration.ReadIntervalTimeout = 1;// MAXDWORD;
timeout_configuration.ReadTotalTimeoutMultiplier = 1;// 0;
timeout_configuration.ReadTotalTimeoutConstant = 1;// 0;
timeout_configuration.WriteTotalTimeoutMultiplier = 1;// 0;
timeout_configuration.WriteTotalTimeoutConstant = 1;// 0;
err = SetCommTimeouts (rs232, &timeout_configuration);
if (err <= 0)
{
printf ("fail SetCommTimeouts: %d\n", GetLastError ()); CloseHandle (rs232); system ("pause"); return;
}
// WriteFile
DWORD buffer_size_w;
char buffer_w[128] = "*IDN?\n";
err = WriteFile (rs232, buffer_w, strlen (buffer_w), &buffer_size_w, 0);
if (err <= 0)
{
printf ("fail WriteFile: %d\n", GetLastError ()); CloseHandle (rs232); system ("pause"); return;
}
printf ("written %d characters: %s\n", buffer_size_w, buffer_w);
// ReadFile
for (int x = 0; x < 10; ++x)
{
DWORD buffer_size_r;
char buffer_r[128] = {0};
err = ReadFile (rs232, buffer_r, 128, &buffer_size_r, 0);
if (err <= 0)
{
printf ("fail ReadFile: %d\n", GetLastError ()); Sleep (250); continue;
}
printf ("read %d characters: %s\n", buffer_size_r, buffer_r);
Sleep (250);
}
CloseHandle (rs232);
system ("pause");
}
Here is some more information about my setup:
I am using Windows 7 x64 and Microsoft Visual Studio 2013
The project is compiled as a Win32 Console
I use a FTDI Chipi-X USB to COM port converter cable
I have tried connecting with a Newport Motion Controller and a Thorlabs Piezo Controller
Here are the things I have tried so far:
Update the drivers of the Chipi-X VCOM
Change the COMMTIMEOUTS to various different values as seen in guides online
Using a HyperTerminal I am able to fully communicate back and forth with the device. If I use my own program to send commands that request something of the device, such as "*IDN?\n", my own ReadFile would thus return nothing. However, when I connect the HyperTerminal again I can press ENTER to receive the requested information.
Change the buffer sizes using SetupComm()
Change the ReadFile buffer size to 1 byte at a time
Implement the OVERLAPPED method as explained in this guide: https://msdn.microsoft.com/en-us/library/ff802693.aspx. It gave exactly the same problem as the non-overlapped code above: The windows functions would not generate errors but the read buffer would stay empty.
I tried communicating with a different device, this was interesting: Again I was able to fully communicate back and forth using the HyperTerminal. Whenever I used my own program to send, I would always receive the exact string I sent back using ReadFile. And again the actual requested information could be retrieved by reconnecting the HyperTerminal.
It seems to me there is some problem with buffers but I don't know what. I am also not sure if it is expectable that the HyperTerminal is able to pick up requested information that was requested several seconds earlier through a different COM port connection. Presumably the problem is related to my coding since the HyperTerminal works fine, but I cannot seem to find what is wrong with my code if I compare it with other code I find online.
Can someone help me out here?
EDIT:
I have created a new CLR/C++ test application using the following example: https://msdn.microsoft.com/en-us/library/system.io.ports.serialport(v=vs.110).aspx. This again gives the exact same problem of not being able to receive requests.
I have tried a Roline USB to RS232 cable: HyperTerminal works and my programming does not. The underlying hardware or drivers are likely not the problem here.
I solved the issue:
I forgot to send the carriage return (\r) at the end of my commands. Apparently the devices I was testing with both were waiting for the combination \r\n before actually parsing the request.
Somehow by using the hyperterminal I would be able to append the \r\n to the current COM port output buffer and get results delayed like that.