Skip to content
Snippets Groups Projects
Commit 8fab06df authored by Sergi Hernandez's avatar Sergi Hernandez
Browse files

Tested the basic read/write operation.

TO DO:
  - implement and test the reception filters.
  - implement and test the data request operation
Added examples for the basic read/write operation.
parent 08b8efa7
No related branches found
No related tags found
No related merge requests found
#include "can.h"
#include "commexceptions.h"
#include <string.h>
#include <iostream>
#include <math.h>
#include <errno.h>
CCAN::CCAN(const std::string &comm_id) : CComm(comm_id)
{
this->can_socket_fd=-1;
this->req_can_id=-1;
// initialize the thread attributes
this->thread_server=CThreadServer::instance();
this->can_thread_id=comm_id + "_can_thread";
this->thread_server->create_thread(this->can_thread_id);
this->thread_server->attach_thread(this->can_thread_id,this->can_thread,this);
// initialize the event atributes
this->event_server=CEventServer::instance();
this->new_frame_event_id=comm_id + "_new_frame_event_id";
this->event_server->create_event(this->new_frame_event_id);
this->frame_error_event_id=comm_id + "_frame_error_event_id";
this->event_server->create_event(this->frame_error_event_id);
this->data_requested_event_id=comm_id + "_data_requested_event_id";
this->event_server->create_event(this->data_requested_event_id);
this->finish_can_thread_event_id=comm_id + "_finish_can_thread_event_id";
this->event_server->create_event(this->finish_can_thread_event_id);
}
void CCAN::hard_open(void *comm_dev)
{
std::string *can_dev=(std::string *)comm_dev;
struct sockaddr_can addr;
struct ifreq ifr;
if ((this->can_socket_fd = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0)
{
/* handle exceptions */
throw CCommException(_HERE_,"impossible to create the socket-CAN",this->get_id());
}
addr.can_family = AF_CAN;
std::cout << *can_dev << std::endl;
strcpy(ifr.ifr_name, can_dev->c_str());
ioctl(this->can_socket_fd, SIOCGIFINDEX, &ifr);
addr.can_ifindex = ifr.ifr_ifindex;
if (bind(this->can_socket_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
{
/* handle exceptions */
throw CCommException(_HERE_,"impossible to connect the socket-CAN",this->get_id());
}
}
void CCAN::hard_config(void *config)
{
/* do nothing */
// start the can thread
this->thread_server->start_thread(this->can_thread_id);
}
int CCAN::hard_read(unsigned char *data, int len)
{
int num_read=0;
if(this->can_socket_fd!=-1)
{
if((num_read=::read(this->can_socket_fd,data,len))==-1)
{
/* handle exceptions */
throw CCommException(_HERE_,"Error while reading from the socket.",this->comm_id);
}
}
else
{
/* handle exceptions */
throw CCommException(_HERE_,"The socket-CAN has not been properly opened.",this->comm_id);
}
return num_read;
}
......@@ -26,28 +81,239 @@ int CCAN::hard_write(unsigned char *data, int len)
{
int num_write=0;
if(this->can_socket_fd!=-1)
{
if((num_write=::write(this->can_socket_fd,data,len))==-1)
{
/* handle exceptions */
throw CCommException(_HERE_,"Error while writing to the socket.",this->comm_id);
}
}
else
{
/* handle exceptions */
throw CCommException(_HERE_,"The socket-CAN has not been properly opened.",this->comm_id);
}
return num_write;
}
int CCAN::hard_get_num_data(void)
{
unsigned char data[1024];
int num;
if(this->can_socket_fd!=-1)
{
if((num=recv(this->can_socket_fd,data,1024,MSG_PEEK))==-1)
// if(ioctl(this->can_socket_fd,FIONREAD,&num)==-1)
{
std::cout << errno << std::endl;
/* handle exceptions */
throw CCommException(_HERE_,"Error while getting the number of bytes available from the socket.",this->comm_id);
}
}
else
{
/* handle exceptions */
throw CCommException(_HERE_,"The socket-CAN has not been properly opened.",this->comm_id);
}
return num;
}
int CCAN::hard_wait_comm_event(void)
{
fd_set receive_set,error_set;
int max_fd,wait_result=0;
max_fd=this->can_socket_fd+1;
FD_ZERO(&receive_set);
FD_SET(this->can_socket_fd,&receive_set);
FD_ZERO(&error_set);
FD_SET(this->can_socket_fd,&error_set);
wait_result=select(max_fd,&receive_set,NULL,&error_set,NULL);
if(wait_result==-1)
{
/* handle exceptions */
throw CCommException(_HERE_,"Error while waiting for socket events",this->comm_id);
}
else
{
if(FD_ISSET(this->can_socket_fd,&receive_set))/* data has been received */
return 1;
if(FD_ISSET(this->can_socket_fd,&error_set))
return 2;
}
return -1;
}
void CCAN::hard_close(void)
{
// close the can device
if(this->can_socket_fd!=-1)
::close(this->can_socket_fd);
// free all the resources
if(this->finish_can_thread_event_id!="")
{
this->event_server->set_event(this->finish_can_thread_event_id);
this->thread_server->end_thread(this->can_thread_id);
this->thread_server->detach_thread(this->can_thread_id);
this->thread_server->delete_thread(this->can_thread_id);
this->can_thread_id="";
this->event_server->delete_event(this->finish_can_thread_event_id);
this->finish_can_thread_event_id="";
}
if(this->new_frame_event_id!="")
{
this->event_server->delete_event(this->new_frame_event_id);
this->new_frame_event_id="";
}
if(this->frame_error_event_id!="")
{
this->event_server->delete_event(this->frame_error_event_id);
this->frame_error_event_id="";
}
if(this->data_requested_event_id!="")
{
this->event_server->delete_event(this->data_requested_event_id);
this->data_requested_event_id="";
}
}
void *CCAN::can_thread(void *param)
{
static struct can_frame new_frame;
std::list<std::string> events;
CCAN *can=(CCAN *)param;
unsigned int event_id,num;
bool end=false;
events.push_back(can->finish_can_thread_event_id);
events.push_back(can->get_rx_event_id());
while(!end)
{
event_id=can->event_server->wait_first(events);
if(event_id==0)
end=true;
else
{
can->can_access.enter();
// process the incomming data
num=can->get_num_data();
while(num>=sizeof(struct can_frame))// there is a whole frame in the input buffer
{
can->read((unsigned char *)&new_frame,sizeof(struct can_frame));
if(new_frame.can_id&CAN_RTR_FLAG)
{
// save the requested can_id
can->req_can_id=new_frame.can_id;
// activate the event
can->event_server->set_event(can->data_requested_event_id);
}
else
{
//puch the new frame into the queue
can->rx_frames.push(new_frame);
// activate the event
can->event_server->set_event(can->new_frame_event_id);
}
num-=sizeof(struct can_frame);
}
can->can_access.exit();
}
}
pthread_exit(NULL);
}
CCAN::~CCAN()
void CCAN::open(const std::string &can_dev)
{
CComm::open((void *)&can_dev);
this->config();
}
std::string CCAN::get_new_frame_event_id(void)
{
return this->new_frame_event_id;
}
std::string CCAN::get_frame_error_event_id(void)
{
return this->frame_error_event_id;
}
std::string CCAN::get_data_requested_event_id(void)
{
return this->data_requested_event_id;
}
unsigned int CCAN::get_requested_can_id(void)
{
return this->req_can_id;
}
void CCAN::write_frame(unsigned int can_id, unsigned char *data, int len)
{
int num_frames=ceil((double)len/8.0),i,j;
struct can_frame frame;
// check the identifier format
if((can_id&(~CAN_SFF_MASK))!=0)// it's an extended identifier
can_id=can_id|CAN_EFF_FLAG;
for(i=0;i<num_frames;i++)
{
// generate all the frames
frame.can_id=can_id;
if((len-8*i)<8)
frame.can_dlc=len-8*i;
else
frame.can_dlc=8;
for(j=0;j<frame.can_dlc;j++)
frame.data[j]=data[i*8+j];
// send the frames
this->write((unsigned char *)&frame,sizeof(struct can_frame));
}
}
void CCAN::read_frame(unsigned int *can_id, unsigned char *data, int *len)
{
struct can_frame frame;
int i=0;
this->can_access.enter();
if(!this->rx_frames.empty())
{
frame=this->rx_frames.front();
this->rx_frames.pop();
*can_id=frame.can_id;
*len=frame.can_dlc;
for(i=0;i<frame.can_dlc;i++)
data[i]=frame.data[i];
}
else
{
/* handle exceptions */
}
this->can_access.exit();
}
void CCAN::add_id_filter(unsigned short int start_id, unsigned short int end_id)
{
}
void CCAN::clear_id_filters(void)
{
}
CCAN::~CCAN()
{
// close the can device
if(this->can_socket_fd!=-1)
this->close();
}
......@@ -4,14 +4,41 @@
#include "comm.h"
#include "mutex.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/uio.h>
#include <net/if.h>
#include <linux/can.h>
#include <linux/can/bcm.h>
#include "threadserver.h"
#include "eventserver.h"
#include <queue>
/**
* \brief CAN driver
*
*/
class CCAN : public CComm
class CCAN : protected CComm
{
private:
// can device identifier
int can_socket_fd;
unsigned int req_can_id;
// thread attributes
CThreadServer *thread_server;
std::string can_thread_id;
// event attributes
CEventServer *event_server;
std::string new_frame_event_id;// public event
std::string frame_error_event_id;// public event
std::string data_requested_event_id;// public event
std::string finish_can_thread_event_id;// private event
// intranal received frame buffer
std::queue<struct can_frame> rx_frames;
CMutex can_access;
protected:
/**
* \brief Function to actually open the device
......@@ -147,6 +174,10 @@ class CCAN : public CComm
* exception class defined by the inherited class.
*/
virtual void hard_close(void);
/**
* \brief
*/
static void *can_thread(void *param);
public:
/**
* \brief default constructor
......@@ -160,6 +191,42 @@ class CCAN : public CComm
* class.
*/
CCAN(const std::string &comm_id);
/**
* \brief
*/
void open(const std::string &can_dev);
/**
* \brief
*/
std::string get_new_frame_event_id(void);
/**
* \brief
*/
std::string get_frame_error_event_id(void);
/**
* \brief
*/
std::string get_data_requested_event_id(void);
/**
* \brief
*/
unsigned int get_requested_can_id(void);
/**
* \brief
*/
void write_frame(unsigned int can_id, unsigned char *data, int len);
/**
* \brief
*/
void read_frame(unsigned int *can_id, unsigned char *data, int *len);
/**
* \brief
*/
void add_id_filter(unsigned short int start_id, unsigned short int end_id=-1);
/**
* \brief
*/
void clear_id_filters(void);
/**
* \brief Destructor
*
......
......@@ -4,6 +4,18 @@ ADD_EXECUTABLE(test_rs232 test_rs232.cpp)
# edit the following line to add the necessary libraries
TARGET_LINK_LIBRARIES(test_rs232 ${IRIUTILS_LIBRARY} comm pthread)
# edit the following line to add the source code for the example and the name of the executable
ADD_EXECUTABLE(test_can test_can.cpp)
# edit the following line to add the necessary libraries
TARGET_LINK_LIBRARIES(test_can ${IRIUTILS_LIBRARY} comm pthread)
# edit the following line to add the source code for the example and the name of the executable
ADD_EXECUTABLE(test_can_rx test_can_rx.cpp)
# edit the following line to add the necessary libraries
TARGET_LINK_LIBRARIES(test_can_rx ${IRIUTILS_LIBRARY} comm pthread)
IF(BUILD_FTDI)
ADD_EXECUTABLE(test_ftdi test_ftdi.cpp)
......
#include "eventserver.h"
#include "threadserver.h"
#include "commexceptions.h"
#include "can.h"
#include <stdio.h>
#include <unistd.h>
#include <string>
#include <iostream>
#include <linux/can/raw.h>
#include <linux/can.h>
const std::string can_dev="can0";
/**
* \example test_can.cpp
*
*/
int main(int argc,char *argv[])
{
CCAN can_port("can_port");
unsigned char data[10];
int i=0;
try{
can_port.open(can_dev);
data[0]=0x01;
data[1]=0x02;
data[2]=0x03;
data[3]=0x04;
data[4]=0x05;
data[5]=0x06;
data[6]=0x07;
data[7]=0x08;
data[8]=0x09;
data[9]=0x0A;
for(i=0;i<5;i++)
{
can_port.write_frame(0x200,data,10);
sleep(1);
}
}catch(CCommException &e){
std::cout << e.what() << std::endl;
}
}
#include "eventserver.h"
#include "threadserver.h"
#include "commexceptions.h"
#include "can.h"
#include <stdio.h>
#include <unistd.h>
#include <string>
#include <iostream>
#include <linux/can/raw.h>
#include <linux/can.h>
const std::string can_dev="can1";
/**
* \example test_can.cpp
*
*/
int main(int argc,char *argv[])
{
CEventServer *event_server=CEventServer::instance();
std::list<std::string> events;
CCAN can_port("can_port");
unsigned char data[8];
unsigned int can_id;
int i=0,len;
events.push_back(can_port.get_new_frame_event_id());
try{
can_port.open(can_dev);
while(1)
{
event_server->wait_all(events);
can_port.read_frame(&can_id,data,&len);
std::cout << "can id: 0x" << std::hex << can_id << std::endl;
std::cout << "length: " << len << std::endl;
std::cout << "data: ";
for(i=0;i<len;i++)
std::cout << "0x" << std::hex << (int)data[i];
std::cout << std::endl;
}
}catch(CCommException &e){
std::cout << e.what() << std::endl;
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment