i have a problem closing the serial port using boost (1.58) asio on a linux (xubuntu 16.04) system. The problem is, the close operation never returns. The code below is my test program on linux host. Everything works fine as long as the arduino (micro) calls its read function. But if i have a blank ino file with just the serial port opened (it doesnt send nor receive) i can not close the port on linux host. Furthermore if sending to arduino the write call will block as the writebuffer(?) is full. ( sometimes after 200 bytes sent, sometimes after 300 bytes sent).
I set off the flow control on linux side and i read arduino has no flow control at all.
So i can not explain why this is happening.
#include <boost/asio/serial_port.hpp>
#include <boost/asio.hpp>
#include <iostream>
#include <iomanip>
#include <deque>
#include <thread>
#include <mutex>
using namespace boost;
class SerialDeviceAsyncExample
{
public:
SerialDeviceAsyncExample();
~SerialDeviceAsyncExample();
bool open(std::string device, unsigned long baudrate);
void close();
void start_reading();
void stop_reading();
int write(const char* buffer, int length);
bool read(uint8_t& c);
private:
std::thread _thread;
void _thread_func();
bool _running;
std::deque<uint8_t> _buffer;
std::mutex _buffer_mutex;
private:
asio::io_service _io;
asio::serial_port _port;
uint8_t _read();
};
SerialDeviceAsyncExample::SerialDeviceAsyncExample() : _running(true), _port(_io){}
SerialDeviceAsyncExample::~SerialDeviceAsyncExample(){}
bool SerialDeviceAsyncExample::open(std::string device, unsigned long baudrate)
{
boost::asio::serial_port_base::baud_rate
BAUD( baudrate) ;
boost::asio::serial_port_base::character_size
C_SIZE( 8 );
boost::asio::serial_port_base::flow_control
FLOW( boost::asio::serial_port_base::flow_control::none );
boost::asio::serial_port_base::parity
PARITY( boost::asio::serial_port_base::parity::even );
boost::asio::serial_port_base::stop_bits
STOP( boost::asio::serial_port_base::stop_bits::one );
try{
_port.open(device);
_port.set_option(C_SIZE);
_port.set_option(FLOW);
_port.set_option(PARITY);
_port.set_option(STOP);
_port.set_option(BAUD);
}catch(boost::exception& ex){
return false;
}
return true;
}
void SerialDeviceAsyncExample::close()
{
_port.close();
}
void SerialDeviceAsyncExample::start_reading()
{
_running = true;
_thread = std::thread(&SerialDeviceAsyncExample::_thread_func, this);
}
void SerialDeviceAsyncExample::stop_reading()
{
_running = false;
_thread.join();
_buffer.clear();
}
int SerialDeviceAsyncExample::write(const char* buffer, int length)
{
int written = _port.write_some(boost::asio::buffer(buffer, length));
return written;
}
bool SerialDeviceAsyncExample::read(uint8_t& c)
{
_buffer_mutex.lock();
if(_buffer.size() > 0){
c = _buffer.front();
_buffer.pop_front();
}else{
_buffer_mutex.unlock();
return false;
}
_buffer_mutex.unlock();
return true;
}
void SerialDeviceAsyncExample::_thread_func()
{
while(_running)
{
uint8_t c = _read();
_buffer_mutex.lock();
_buffer.push_back(c);
_buffer_mutex.unlock();
}
}
uint8_t SerialDeviceAsyncExample::_read()
{
uint8_t c = 0;
// loops as long until a char arrives at serial device or threadfunc is canceled
for(;_running == true;){
try{
asio::read(_port, asio::buffer(&c,1));
break;
}catch(boost::exception& e){
}
}
return c;
}
int main(int argc, char** argv)
{
SerialDeviceAsyncExample com;
std::string device = "/dev/ttyACM0";
if(!com.open(device, 115200)){
std::cout << "No Device at port " << device << std::endl;
return -1;
}
std::cout << "Press enter to start reading." << std::endl;
std::cin.ignore();
com.start_reading();
std::cout << "Now reading into a software buffer." << std::endl;
std::string input;
std::cout << "Enter a string you want to send via serial port." << std::endl;
std::cout << "Enter 'quit' to quit the loop" << std::endl;
std::cout << "Enter 'fetch' to fetch all read bytes in the software buffer" << std::endl;
while(true){
std::cout << "Command: " ; std::cin >> input;
if(input.compare(std::string("fetch")) == 0){
uint8_t c;
std::cout << "Buffer: ";
while (com.read(c)){
// print each char in hex format
//std::cout << "0x" << std::setfill('0') << std::setw(2) << std::hex << static_cast<int>(c) << " " << std::dec;
std::cout << c;
}
std::cout << std::endl;
continue;
}
if(input.compare(std::string("quit")) == 0){
break;
}
com.write(input.c_str(), input.size());
}
std::cout << "Stop reading." << std::endl;
com.stop_reading();
return 0;
}
The blank ino file
void setup() {
Serial.begin(115200);
}
void loop() {
//while(Serial.available()){char c = Serial.read();Serial.write(c);};
}
Aucun commentaire:
Enregistrer un commentaire