Home/Support/Support Forum/Has anyone got the CAN Example on the ConnectCore6 working reliably?
Welcome to Digi Forum, where you can ask questions and receive answers from other members of the community.

Has anyone got the CAN Example on the ConnectCore6 working reliably?

0 votes
When trying the CAN Bus sample application for sending data I get the error message:

write() returned with errors, No buffer space available

Has anyone else seen this, if so is there a workaround?
asked Feb 3, 2015 in Linux by david.lockyer New to the Community (15 points)

Please log in or register to answer this question.

1 Answer

0 votes
Hi David,
I have not checked the sample application but This works for me:

data definition:
//CAN
struct ifreq S_can_ifr;
struct sockaddr_can S_can_addr;
struct can_frame S_can_frame;
int i16_can_socket;
struct can_filter S_can_rx_filter[5];

Initialization routine:
void vfn_Init_CAN()
{
// Preconfigurar can0 en boot de SBC
//ip link set can0 type can bitrate 500000
//ifconfig can0 up
//bit-rate can only be modified when the device is down
//If you type "ifconfig can0" you can see if it is up or down
//The open() callback should return a 0 in case of success or any nonzero value
//in case of failure. The close() callback (which is void) must always succeed.

// The socketCAN version can be retrieved like that:
// # cat /proc/net/can/version
// The socketCAN statistics can be retrieved like that:
// # cat /proc/net/can/stats

memset(&S_can_ifr, 0x0, sizeof(S_can_ifr));
memset(&S_can_addr, 0x0, sizeof(S_can_addr));
memset(&S_can_frame, 0x0, sizeof(S_can_frame));

// open CAN_RAW socket
i16_can_socket = socket(PF_CAN, SOCK_RAW, CAN_RAW);

// convert interface sting "can0" into interface index
strcpy(S_can_ifr.ifr_name, "can0");
ioctl(i16_can_socket, SIOCGIFINDEX, &S_can_ifr);
// setup address for bind
S_can_addr.can_ifindex = S_can_ifr.ifr_ifindex;
S_can_addr.can_family = PF_CAN;

// set baud rate
//S_can_ifr.ifr_ifru.ifru_ivalue = 500000;
//ioctl(i16_can_socket, SIOCSCANBAUDRATE, &S_can_ifr);

S_can_rx_filter[0].can_id = 0x229;
S_can_rx_filter[0].can_mask = CAN_SFF_MASK;
S_can_rx_filter[1].can_id = 0x230;
S_can_rx_filter[1].can_mask = CAN_SFF_MASK;
S_can_rx_filter[2].can_id = 0x231;
S_can_rx_filter[2].can_mask = CAN_SFF_MASK;
S_can_rx_filter[3].can_id = 0x234;
S_can_rx_filter[3].can_mask = CAN_SFF_MASK;
S_can_rx_filter[4].can_id = 0x235;
S_can_rx_filter[4].can_mask = CAN_SFF_MASK;

setsockopt(i16_can_socket, SOL_CAN_RAW, CAN_RAW_FILTER, &S_can_rx_filter, sizeof(S_can_rx_filter));
//To disable the reception of CAN frames on the selected CAN_RAW socket:
//setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0);
//To set the filters to zero filters is quite obsolete as not read
//data causes the raw socket to discard the received CAN frames. But
//having this 'send only' use-case we may remove the receive list in the
//Kernel to save a little (really a very little!) CPU usage.

// bind socket to the can0 interface
bind(i16_can_socket, (struct sockaddr *)&S_can_addr, sizeof(S_can_addr));
}

void vfn_End_CAN()
{
close(i16_can_socket);
}

I work with two threads: CAN_TX and CAN_RX:

void * vfn_CAN_TX()
{
//while (ui8_sys_state==SM_RUNNING)
//for(ui8_j=0;ui8_j<10;ui8_j++)
while (ui8_sys_state==SM_RUNNING)
{
i16_rtc_fd=open("/dev/rtc",O_RDONLY);
ret_val=rtc_time_read(i16_rtc_fd, &rtc_tm);
close(i16_rtc_fd);
printf("%d-%d-%d, %02d:%02d:%02d\n", rtc_tm.tm_mday, rtc_tm.tm_mon+1, rtc_tm.tm_year+1900, rtc_tm.tm_hour, rtc_tm.tm_min, rtc_tm.tm_sec);
//fprintf(ptr_file_txt,"%d; %d; %d-%d-%d; %02d:%02d:%02d\n", ui8_j, ui8_j+10, rtc_tm.tm_mday, rtc_tm.tm_mon+1, rtc_tm.tm_year+1900, rtc_tm.tm_hour, rtc_tm.tm_min, rtc_tm.tm_sec);
//fprintf(ptr_file_json,"[%d, %d]",1999+ui8_j,ui8_j/2);
//if (ui8_j<9)
//{
//fprintf(ptr_file_json,", ");
//}

// first fill, then send the CAN frame
S_can_frame.can_id = 0x215;
S_can_frame.can_dlc = 8;
S_can_frame.data[0]=(char)rtc_tm.tm_mday;
S_can_frame.data[1]=(char)(rtc_tm.tm_mon+1);
S_can_frame.data[2]=(char)(rtc_tm.tm_year+1900-2000);
S_can_frame.data[3]=(char)rtc_tm.tm_hour;
S_can_frame.data[4]=(char)rtc_tm.tm_min;
S_can_frame.data[5]=(char)rtc_tm.tm_sec;
S_can_frame.data[6]=0;
S_can_frame.data[7]=0;
write(i16_can_socket,&S_can_frame,sizeof(S_can_frame));

//usleep(250000); //0.25s
sleep(1);
}
}

void * vfn_CAN_RX()
{
//for(ui8_k=0;ui8_k<20;ui8_k++)
//while (ui8_sys_state==SM_RUNNING)
while (ui8_sys_state==SM_RUNNING)
{
// Read messages from the CAN bus
// Filters set at S_can_rx_filter
read(i16_can_socket,&S_can_frame,sizeof(S_can_frame));
switch(S_can_frame.can_id)
{
case 0x235: //RTC_DATA_CFG
{
// tm->tm_mday = 26; //26
// tm->tm_mon = 2 -1; //feb
// tm->tm_year = 2010 -1900; //2010
// tm->tm_hour = 7;
// tm->tm_min = 33;
// tm->tm_sec = 55;

printf("CAN ID 0x235 -> RTC_DATA_CFG\n");

// read configuration data
rtc_tm.tm_mday=S_can_frame.data[0];
rtc_tm.tm_mon=S_can_frame.data[1]-1;
rtc_tm.tm_year=2000+S_can_frame.data[2]-1900;
rtc_tm.tm_hour=S_can_frame.data[3];
rtc_tm.tm_min=S_can_frame.data[4];
rtc_tm.tm_sec=S_can_frame.data[5];

i16_rtc_fd=open("/dev/rtc",O_RDONLY);
rtc_time_set(i16_rtc_fd, &rtc_tm);
close(i16_rtc_fd);
}
break;
case 0x234: //STOP
{
printf("CAN ID 0x234 -> STOP\n");
ui8_sys_state=SM_STOP;
}
break;
default:
{
// Any other id which is defined in S_can_rx_filter
//printf("ID%X\n",S_can_frame.can_id);
}
break;
}
sleep(1);
}
}

Good luck!
alvaro
answered Feb 5, 2015 by almarto New to the Community (3 points)
...