Results 1 to 10 of 15
Hello,
I am having the following problem. The following code works fine on my P.C. Ubuntu x64, and on a jetway mini-itx board with an atom processor. The problem is, ...
- 04-06-2011 #1Just Joined!
- Join Date
- Sep 2010
- Location
- Montgomery, AL
- Posts
- 27
[SOLVED] ioctl TIOCMGET call doesn't detect TIOCM_CTS
Hello,
I am having the following problem. The following code works fine on my P.C. Ubuntu x64, and on a jetway mini-itx board with an atom processor. The problem is, the same code doesn't work on the intel equivalent of the jetway board. I thought the maybe, I didn't have the port configured right, so I turned on Hardware Flow control and also tried turning on the modem bits I needed with TIOCMBIS. Neither worked. Here is the code. There are two threads, one of them, respsponding to the client, and using the RTS and DTR pins to power two relays. The other, manages listening to CTS and DSR for input. Here is the class with the first thread.
here is the second, handling the inputCode:/* * DigitalIOCore.cpp * * Created on: Nov 1, 2010 * Author: jonathan */ #include "DigitalIOCore.h" #include "DeviceInfo.h" #include "NetworkSettings.h" #include "ClientSocket.h" #include "SocketException.h" int currentBitState; DigitalIOCore::DigitalIOCore() : status(0), set_bits1(0), set_bits2(0) { //Grab the DeviceInfo from config file; DeviceInfo device; if((fd = open(device.getIOPort().c_str(), O_RDWR | O_NDELAY)) >= 0) { PWaitAndSignal m(port_mutex); input_engine = new DigitalInputEngine(&port_mutex, fd); input_engine->input1_received.connect(sigc::mem_fun(this, &DigitalIOCore::FireInput1)); input_engine->input2_received.connect(sigc::mem_fun(this, &DigitalIOCore::FireInput2)); input_engine->input3_received.connect(sigc::mem_fun(this, &DigitalIOCore::FireInput3)); } if(fd >= 0) input_engine->Resume(); } DigitalIOCore::~DigitalIOCore() { input_engine->end_thread = true; input_engine->Terminate(); delete input_engine; close(fd); } bool DigitalIOCore::Output1(bool on_off) { if(on_off) { //set the bits to TIOCM_DTR and include TIOCM_RTS if it is on so not to undo Output2 if it is running set_bits1 = TIOCM_DTR; currentBitState = set_bits1 | set_bits2; //hold the semaphore for as short a time as possible since the input thread will need this serial port as well. PWaitAndSignal m(port_mutex); int test = ioctl(fd, TIOCMSET, ¤tBitState); ioctl(fd, TIOCMGET, &status); return status & TIOCM_DTR; } else { //set the bits back to TIOCM_DTR being off, but do not undo TIOCM_RTS if it is on. set_bits1 = 0; currentBitState = set_bits1 | set_bits2; //hold the semaphore for as short a time as possible since the input thread will need this serial port as well. PWaitAndSignal m(port_mutex); ioctl(fd, TIOCMSET, ¤tBitState); ioctl(fd, TIOCMGET, &status); return ~(status & TIOCM_DTR); } } bool DigitalIOCore::Output2(bool on_off) { if(on_off) { //set the bits to TIOCM_RTS and include TIOCM_DTS if it is on so not to undo Output1 if it is running set_bits2 = TIOCM_RTS; currentBitState = set_bits1 | set_bits2; //hold the semaphore for as short a time as possible since the input thread will need this serial port as well. PWaitAndSignal m(port_mutex); ioctl(fd, TIOCMSET, ¤tBitState); ioctl(fd, TIOCMGET, &status); return status & TIOCM_RTS; } else { //set the bits back to TIOCM_RTS being off, but do not undo TIOCM_DTS if it is on. set_bits2 = 0; currentBitState = set_bits1 | set_bits2; //hold the semaphore for as short a time as possible since the input thread will need this serial port as well. PWaitAndSignal m(port_mutex); ioctl(fd, TIOCMSET, ¤tBitState); ioctl(fd, TIOCMGET, &status); return ~(status & TIOCM_RTS); } } void DigitalIOCore::FireInput1() { NetworkSettings network; vector<string> devicesToRemove; for(list<string>::iterator iter = clients.begin(); iter != clients.end(); iter++) { //we need to handle the case where a registered client goes offline. In that case the client will be removed from the list. try { ClientSocket sock(*iter, 35100); sock << network.getIPv4Address() + "&0&"; } catch(SocketException ex) { devicesToRemove.push_back(*iter); } } for(vector<string>::iterator iter = devicesToRemove.begin(); iter != devicesToRemove.end(); iter++) { clients.remove(*iter); } } void DigitalIOCore::FireInput2() { NetworkSettings network; vector<string> devicesToRemove; for(list<string>::iterator iter = clients.begin(); iter != clients.end(); iter++) { //we need to handle the case where a registered client goes offline. In that case the client will be removed from the list. try { ClientSocket sock(*iter, 35100); sock << network.getIPv4Address() + "&1&"; } catch(SocketException ex) { devicesToRemove.push_back(*iter); } } for(vector<string>::iterator iter = devicesToRemove.begin(); iter != devicesToRemove.end(); iter++) { clients.remove(*iter); } } void DigitalIOCore::FireInput3() { NetworkSettings network; vector<string> devicesToRemove; //we need to handle the case where a registered client goes offline. In that case the client will be removed from the list. for(list<string>::iterator iter = clients.begin(); iter != clients.end(); iter++) { try { ClientSocket sock(*iter, 35100); sock << network.getIPv4Address() + "&2&"; } catch(SocketException ex) { devicesToRemove.push_back(*iter); } } for(vector<string>::iterator iter = devicesToRemove.begin(); iter != devicesToRemove.end(); iter++) { clients.remove(*iter); } } void DigitalIOCore::RegisterClientForInput(string ipAddress) { clients.push_back(ipAddress); } void DigitalIOCore::RemoveClientFromInput(string ipAddress) { clients.remove(ipAddress); }
Code:/* * DigitalInputEngine.cpp * * Created on: Nov 1, 2010 * Author: jonathan */ #include "DigitalInputEngine.h" DigitalInputEngine::DigitalInputEngine(PMutex* port_mutex, int fd) : PThread (1000, AutoDeleteThread, HighestPriority, "DigitalInputEngine"), end_thread(false) { mutex = port_mutex; serial = fd; if(DEBUG) { std::cout << "Input Engine constructed.\n"; } } DigitalInputEngine::~DigitalInputEngine() { } void DigitalInputEngine::Main() { int temp = 0; ioctl(serial, TIOCMSET, &temp); if(DEBUG) std::cout << "Serial set to 0\n"; while(!end_thread) { if(DEBUG) std::cout << "Iteration of Thread Called\n"; int bytes = 0; if(serial >= 0) { //hold the semaphore for as short a time as possible since, since the output thread will need this serial port as well. PWaitAndSignal m(*mutex); //send 127 because this will ensure a constant positive voltage since all bits will be high. //The tx pin is being used for source voltage. //we will not be using the tx pin for source any more, so this has been commented out. //char data[] = {127, 127, 127, 127, 127, 127, 127, 127}; //int test = write(serial, data , 8); ioctl(serial, TIOCMGET, &bytes); if(DEBUG) std::cout << "Data written out and read on serial port\n"; } if((bytes & TIOCM_CTS) && (bytes & TIOCM_DSR)) { if(DEBUG) std::cout << "Input 3 fired\n"; input3_received.emit(); this->Sleep(100); } else if (bytes & TIOCM_CTS) { if(DEBUG) std::cout << "Input 1 fired\n"; input1_received.emit(); this->Sleep(100); } else if (bytes & TIOCM_DSR) { if(DEBUG) std::cout << "Input 2 fired\n"; input2_received.emit(); this->Sleep(100); } else { //give the other thread time to grab the semaphore this->Sleep(5); } } }
As I said, this works perfectly on all boards I have tested except for the intel board. I have already tried adding
int sigs = TIOCM_RTS | TIOCM_DTR | TIOCM_CTS | TIOCM_DSR;
ioctl(fd, TIOCMBIS, &sigs);
struct termios options;
tcgetattr(fd, &options);
options.c_cflag |= CRTSCTS;
tcsetattr(fd, TCSANOW, &options);
after the open call, and it didn't help.
Thanks for your help!Last edited by JHenson; 04-06-2011 at 06:40 PM.
- 04-06-2011 #2Just Joined!
- Join Date
- Sep 2010
- Location
- Montgomery, AL
- Posts
- 27
oh yeah, and the mini-itx boards are running a version of Crunch Bang that I stripped down to run as an embeded system.
- 04-06-2011 #3Just Joined!
- Join Date
- Sep 2010
- Location
- Montgomery, AL
- Posts
- 27
woops! I forgot to mention the actual problem. When I put +12v dc from the source voltage onto the CTS pin it does not set the pin to high. This does work however on the DSR pin. I only have this problem on the Intel board.
- 04-06-2011 #4Linux Guru
- Join Date
- Apr 2009
- Location
- I can be found either 40 miles west of Chicago, or in a galaxy far, far away.
- Posts
- 8,974
Please! When you post code, DO put it inside code blocks! Like this:
here is the second, handling the inputCode:/* * DigitalIOCore.cpp * * Created on: Nov 1, 2010 * Author: jonathan */ #include "DigitalIOCore.h" #include "DeviceInfo.h" #include "NetworkSettings.h" #include "ClientSocket.h" #include "SocketException.h" int currentBitState; DigitalIOCore::DigitalIOCore() : status(0), set_bits1(0), set_bits2(0) { //Grab the DeviceInfo from config file; DeviceInfo device; if((fd = open(device.getIOPort().c_str(), O_RDWR | O_NDELAY)) >= 0) { PWaitAndSignal m(port_mutex); input_engine = new DigitalInputEngine(&port_mutex, fd); input_engine->input1_received.connect(sigc::mem_fun(this, &DigitalIOCore::FireInput1)); input_engine->input2_received.connect(sigc::mem_fun(this, &DigitalIOCore::FireInput2)); input_engine->input3_received.connect(sigc::mem_fun(this, &DigitalIOCore::FireInput3)); } if(fd >= 0) input_engine->Resume(); } DigitalIOCore::~DigitalIOCore() { input_engine->end_thread = true; input_engine->Terminate(); delete input_engine; close(fd); } bool DigitalIOCore::Output1(bool on_off) { if(on_off) { //set the bits to TIOCM_DTR and include TIOCM_RTS if it is on so not to undo Output2 if it is running set_bits1 = TIOCM_DTR; currentBitState = set_bits1 | set_bits2; //hold the semaphore for as short a time as possible since the input thread will need this serial port as well. PWaitAndSignal m(port_mutex); int test = ioctl(fd, TIOCMSET, ¤tBitState); ioctl(fd, TIOCMGET, &status); return status & TIOCM_DTR; } else { //set the bits back to TIOCM_DTR being off, but do not undo TIOCM_RTS if it is on. set_bits1 = 0; currentBitState = set_bits1 | set_bits2; //hold the semaphore for as short a time as possible since the input thread will need this serial port as well. PWaitAndSignal m(port_mutex); ioctl(fd, TIOCMSET, ¤tBitState); ioctl(fd, TIOCMGET, &status); return ~(status & TIOCM_DTR); } } bool DigitalIOCore::Output2(bool on_off) { if(on_off) { //set the bits to TIOCM_RTS and include TIOCM_DTS if it is on so not to undo Output1 if it is running set_bits2 = TIOCM_RTS; currentBitState = set_bits1 | set_bits2; //hold the semaphore for as short a time as possible since the input thread will need this serial port as well. PWaitAndSignal m(port_mutex); ioctl(fd, TIOCMSET, ¤tBitState); ioctl(fd, TIOCMGET, &status); return status & TIOCM_RTS; } else { //set the bits back to TIOCM_RTS being off, but do not undo TIOCM_DTS if it is on. set_bits2 = 0; currentBitState = set_bits1 | set_bits2; //hold the semaphore for as short a time as possible since the input thread will need this serial port as well. PWaitAndSignal m(port_mutex); ioctl(fd, TIOCMSET, ¤tBitState); ioctl(fd, TIOCMGET, &status); return ~(status & TIOCM_RTS); } } void DigitalIOCore::FireInput1() { NetworkSettings network; vector<string> devicesToRemove; for(list<string>::iterator iter = clients.begin(); iter != clients.end(); iter++) { //we need to handle the case where a registered client goes offline. In that case the client will be removed from the list. try { ClientSocket sock(*iter, 35100); sock << network.getIPv4Address() + "&0&"; } catch(SocketException ex) { devicesToRemove.push_back(*iter); } } for(vector<string>::iterator iter = devicesToRemove.begin(); iter != devicesToRemove.end(); iter++) { clients.remove(*iter); } } void DigitalIOCore::FireInput2() { NetworkSettings network; vector<string> devicesToRemove; for(list<string>::iterator iter = clients.begin(); iter != clients.end(); iter++) { //we need to handle the case where a registered client goes offline. In that case the client will be removed from the list. try { ClientSocket sock(*iter, 35100); sock << network.getIPv4Address() + "&1&"; } catch(SocketException ex) { devicesToRemove.push_back(*iter); } } for(vector<string>::iterator iter = devicesToRemove.begin(); iter != devicesToRemove.end(); iter++) { clients.remove(*iter); } } void DigitalIOCore::FireInput3() { NetworkSettings network; vector<string> devicesToRemove; //we need to handle the case where a registered client goes offline. In that case the client will be removed from the list. for(list<string>::iterator iter = clients.begin(); iter != clients.end(); iter++) { try { ClientSocket sock(*iter, 35100); sock << network.getIPv4Address() + "&2&"; } catch(SocketException ex) { devicesToRemove.push_back(*iter); } } for(vector<string>::iterator iter = devicesToRemove.begin(); iter != devicesToRemove.end(); iter++) { clients.remove(*iter); } } void DigitalIOCore::RegisterClientForInput(string ipAddress) { clients.push_back(ipAddress); } void DigitalIOCore::RemoveClientFromInput(string ipAddress) { clients.remove(ipAddress); }
That will keep the indents, and avoid turning some symbol sets into smileys.Code:/* * DigitalInputEngine.cpp * * Created on: Nov 1, 2010 * Author: jonathan */ #include "DigitalInputEngine.h" DigitalInputEngine::DigitalInputEngine(PMutex* port_mutex, int fd) : PThread (1000, AutoDeleteThread, HighestPriority, "DigitalInputEngine"), end_thread(false) { mutex = port_mutex; serial = fd; if(DEBUG) { std::cout << "Input Engine constructed.\n"; } } DigitalInputEngine::~DigitalInputEngine() { } void DigitalInputEngine::Main() { int temp = 0; ioctl(serial, TIOCMSET, &temp); if(DEBUG) std::cout << "Serial set to 0\n"; while(!end_thread) { if(DEBUG) std::cout << "Iteration of Thread Called\n"; int bytes = 0; if(serial >= 0) { //hold the semaphore for as short a time as possible since, since the output thread will need this serial port as well. PWaitAndSignal m(*mutex); //send 127 because this will ensure a constant positive voltage since all bits will be high. //The tx pin is being used for source voltage. //we will not be using the tx pin for source any more, so this has been commented out. //char data[] = {127, 127, 127, 127, 127, 127, 127, 127}; //int test = write(serial, data , 8); ioctl(serial, TIOCMGET, &bytes); if(DEBUG) std::cout << "Data written out and read on serial port\n"; } if((bytes & TIOCM_CTS) && (bytes & TIOCM_DSR)) { if(DEBUG) std::cout << "Input 3 fired\n"; input3_received.emit(); this->Sleep(100); } else if (bytes & TIOCM_CTS) { if(DEBUG) std::cout << "Input 1 fired\n"; input1_received.emit(); this->Sleep(100); } else if (bytes & TIOCM_DSR) { if(DEBUG) std::cout << "Input 2 fired\n"; input2_received.emit(); this->Sleep(100); } else { //give the other thread time to grab the semaphore this->Sleep(5); } } }Sometimes, real fast is almost as good as real time.
Just remember, Semper Gumbi - always be flexible!
- 04-06-2011 #5Just Joined!
- Join Date
- Sep 2010
- Location
- Montgomery, AL
- Posts
- 27
Thanks, I was wondering how to do that.
- 04-06-2011 #6Linux Guru
- Join Date
- Apr 2009
- Location
- I can be found either 40 miles west of Chicago, or in a galaxy far, far away.
- Posts
- 8,974
Anyway, regarding your problem. Have you considered that it is possible that the Intel board is not supporting hardware flow control on that port? Or that there is some sort of low-level configuration option (i/o instructions) to enable it. Anyway, I have seen boards where there is no hw flow control, just transmit, receive, and ground. What does the Intel web site say about the board? The specs should be there I would think.
Sometimes, real fast is almost as good as real time.
Just remember, Semper Gumbi - always be flexible!
- 04-06-2011 #7Linux Guru
- Join Date
- Apr 2009
- Location
- I can be found either 40 miles west of Chicago, or in a galaxy far, far away.
- Posts
- 8,974
Sometimes, real fast is almost as good as real time.
Just remember, Semper Gumbi - always be flexible!
- 04-06-2011 #8Just Joined!
- Join Date
- Sep 2010
- Location
- Montgomery, AL
- Posts
- 27
I will work on getting the specs. It is certainly possible that it does not support hardware flow control, though I would think that would kill my DSR pin as well. The fact that my other modem bits are working confuses me, since I would think that no hardware control would kill those off as well. As to whether or not there are some i/o instructions I can set, that is largely the reason I posted this here instead of the hardware and peripherals section--I don't know and I am hoping that that is my problem.
Thanks for the swift reply and form posting help.
- 04-06-2011 #9Just Joined!
- Join Date
- Sep 2010
- Location
- Montgomery, AL
- Posts
- 27
correction. RTS is the other hardware flow control bit, and it does work. However, I am turning it on as an output and not listening for an outside voltage to set it to high. DSR is not related to Hardware Flow control, so that doesn't prove anything.
Question, if hardware flow control is not supported on this board, would I still be able to set RTS to high from my code? I know for certain it works, as I am driving a relay with it and I just tested it.
- 04-06-2011 #10Linux Guru
- Join Date
- Apr 2009
- Location
- I can be found either 40 miles west of Chicago, or in a galaxy far, far away.
- Posts
- 8,974
Probably not. It may be that there is a problem with the port/board. Ok. Digging back into my brain (I haven't done RS-232 bit twiddling for a looong time), here is something. DSR is actually part of the DTE/DCE RS-232 flow control standard protocols. The DSR line is used by DCE equipment to indicate to the DTE that the DCE is ready to receive data. The RTS line is used by the DTE equipment to tell the DCE to get ready to receive data. So, it may be that in your case, that the port is a DTE only, and not a DCE device. DTE flow control lines are DTR and RTS. DCE flow control lines are DSR and CTS. I don't think that you need to fiddle with the ring indicator and carrier detect lines and such.
Sometimes, real fast is almost as good as real time.
Just remember, Semper Gumbi - always be flexible!



