Skip to content

Commit

Permalink
can: add test app based on conn_can
Browse files Browse the repository at this point in the history
  • Loading branch information
Vincent Dupont committed Aug 31, 2016
1 parent d72f830 commit 18ad903
Show file tree
Hide file tree
Showing 3 changed files with 303 additions and 0 deletions.
22 changes: 22 additions & 0 deletions tests/conn_can/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
export APPLICATION = can
include ../Makefile.tests_common

OS:=$(shell uname)

CFLAGS += -DDEVELHELP
CFLAGS += -DLOG_LEVEL=LOG_ALL
CFLAGS_OPT = -O0

USEMODULE += shell
USEMODULE += can
USEMODULE += shell_commands
USEMODULE += ps
USEMODULE += xtimer

ifeq ($(BOARD),native)
ifeq ($(OS),Linux)
USEMODULE += can_linux
endif
endif

include $(RIOTBASE)/Makefile.include
31 changes: 31 additions & 0 deletions tests/conn_can/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
tests/conn_can
================
Demo application for the CAN stack with conn_can interface.


Native prerequisites
============

The native can_conf.h file defines two virtual can ifaces to be used.
Before running this test on native, you should create those:

```
sudo modprobe vcan
sudo ip link add dev vcan0 type vcan
sudo ip link add dev vcan1 type vcan
sudo ip link set vcan0 up
sudo ip link set vcan1 up
```

Usage
=====

Add a can_conf.h file to boards/<board>/include which defines the can
devices to use.
Build, flash and start the application:
```
export BOARD=your_board
make
make flash
make term
```
250 changes: 250 additions & 0 deletions tests/conn_can/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,250 @@
/*
* Copyright (C) 2016 OTA keys S.A.
*/

/**
* @ingroup main
* @{
*
* @file
* @brief main
*
* @author Vincent Dupont <vincent@otakeys.com>
*
* @}
*/
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <inttypes.h>

#include "shell.h"
#include "board.h"
#include "periph/gpio.h"
#include "thread.h"

#include "can/can.h"
#include "can/conn_can.h"

#define THREAD_STACKSIZE (THREAD_STACKSIZE_MAIN)
#define RECEIVE_THREAD_MSG_QUEUE_SIZE (8)

#include "timex.h"
#define TEST_CONN_CAN_RECV_TIMEOUT (10 * SEC_IN_USEC)

static char thread_stack[THREAD_STACKSIZE];
kernel_pid_t receive_pid;

static int _send(int argc, char **argv)
{
if (argc < 5) {
puts("Send: Not enough arguments\n");
return 1;
}
struct can_frame frame;
int ifnum = strtol(argv[2], NULL, 0);

frame.can_id = strtoul(argv[3], NULL, 0);
frame.can_dlc = strtol(argv[4], NULL, 0);
if (argc < 5 + frame.can_dlc) {
puts("Not enough arguments\n");
return 1;
}
for (int i = 0; i < frame.can_dlc; i++) {
frame.data[i] = strtol(argv[5 + i], NULL, 0);
}
conn_can_t conn;
conn_can_create(&conn, NULL, 0, ifnum, CONN_CAN_RAW, 0);
int ret = conn_can_send(&conn, &frame, sizeof(frame), 0);
if (ret < 0) {
puts("Error when trying to send\n");
}
conn_can_close(&conn);
return 0;
}

static int _receive(int argc, char **argv)
{
if (argc < 4) {
puts("Not enough arguments\n");
return 1;
}
int res;
int ifnum = strtol(argv[2], NULL, 0);
int filt_num = strtol(argv[3], NULL, 0);
if (argc < 4 + filt_num) {
puts("Not enough arguments\n");
return 1;
}
struct can_filter filters[filt_num];
for (int i = 0; i < filt_num; i++) {
filters[i].can_id = strtoul(argv[4 + i], NULL, 0);
filters[i].can_mask = 0xffffffff;
}
msg_t msg, reply;
can_opt_t opt;
opt.data = filters;
opt.data_len = filt_num * sizeof(filters[0]);
opt.context = ifnum;
msg.type = CAN_MSG_SET;
msg.content.ptr = &opt;
res = msg_send_receive(&msg, &reply, receive_pid);
if (res < 0 || (int)reply.content.value < 0) {
puts("Error when setting filters\n");
return 1;
}
return 0;
}

static int _stop_receive(int argc, char **argv)
{
(void) argc;
(void) argv;
msg_t msg;
msg.type = 0x1234;
msg_send(&msg, receive_pid);
return 0;
}

static int _get_filter(int argc, char **argv)
{
if (argc < 3) {
puts("Not enough arguments\n");
return 1;
}
int res;
int ifnum = strtol(argv[2], NULL, 0);
struct can_filter filters[32];
can_opt_t opt;
opt.data = (void *)filters;
opt.data_len = sizeof(filters);
opt.opt = CANOPT_RX_FILTERS;
res = raw_can_get_can_opt(ifnum, &opt);
if (res < 0) {
puts("Error when reading filters\n");
}
else if (res == 0) {
puts("No filter set\n");
}
else {
for (unsigned int i = 0; i < res / sizeof(filters[0]); i++) {
printf("Filter %d: 0x%" PRIx32"\n", i, filters[i].can_id);
printf("Mask %d: 0x%" PRIx32"\n", i, filters[i].can_mask);
}
}
return 0;
}

static int _set_bitrate(int argc, char **argv)
{
if (argc < 4) {
puts("Not enough argument\n");
return 1;
}

int ifnum = strtol(argv[2], NULL, 0);
uint32_t bitrate = strtoul(argv[3], NULL, 0);

// Unable to find a function to set bitrate
printf("Function not implemented. Bitrate (%"PRIu32") of Interface num: %d is still equal to its default value\n", bitrate, ifnum);

// convertion bitrate to bit timing ????
return 0; // return = raw_can_set_can_opt(ifnum, CAN_MSG_SET, bitrate_into_bittiming)
}

static int _can_handler(int argc, char **argv)
{
if (argc < 2) {
puts("can send ifnum id len [B1 [B2 [B3 [B4 [B5 [B6 [B7 [B8]]]]]]]]\n");
puts("can recv ifnum nb_id id1 [id2..id16]\n");
puts("can get_filter ifnum\n");
puts("can set_bitrate ifnum bitrate\n");
return 1;
}
else if (strncmp(argv[1], "send", 4) == 0) {
return _send(argc, argv);
}
else if (strncmp(argv[1], "recv", 4) == 0) {
return _receive(argc, argv);
}
else if (strncmp(argv[1], "stop_recv", 9) == 0) {
return _stop_receive(argc, argv);
}
else if (strncmp(argv[1], "get_filter", 10) == 0) {
return _get_filter(argc, argv);
}
else if (strncmp(argv[1], "set_bitrate", 11) == 0) {
return _set_bitrate(argc, argv);
}
else {
printf("unknown command: %s\n", argv[1]);
return 1;
}
}

static void *_receive_thread(void *args)
{
(void) args;
struct can_frame frame;
msg_t msg, msg_queue[RECEIVE_THREAD_MSG_QUEUE_SIZE];

/* setup the device layers message queue */
msg_init_queue(msg_queue, RECEIVE_THREAD_MSG_QUEUE_SIZE);

while (1) {
msg_receive(&msg);
switch (msg.type) {
case CAN_MSG_SET:
{
int ret;
msg_t reply;
conn_can_t conn;
can_opt_t *opt = msg.content.ptr;
ret = conn_can_create(&conn, opt->data, opt->data_len, opt->context, CONN_CAN_RAW, 0);
reply.type = msg.type;
reply.content.value = ret;
msg_reply(&msg, &reply);
while ((ret = conn_can_recv(&conn, &frame, sizeof(struct can_frame), TEST_CONN_CAN_RECV_TIMEOUT)) == sizeof(struct can_frame)) {
printf("Frame received 0x%" PRIx32 " dlc: 0x%02x data:", frame.can_id, frame.can_dlc);
for (int i = 0; i < frame.can_dlc; i++) {
printf(" 0x%02x", frame.data[i]);
}
printf("\n");
}
printf("recv terminated: ret=%d\n", ret);
conn_can_close(&conn);
}
break;

case 0x1234:
puts("_receive_thread: stop receiving\n");
break;

default:
puts("_receive_thread: received unknown message\n");
break;
}
}

return NULL;
}

static const shell_command_t _commands[] = {
{"can", "CAN functions", _can_handler},
{ NULL, NULL, NULL},
};

int main(void)
{
char line_buf[SHELL_DEFAULT_BUFSIZE];

msg_t msg_queue[8];
msg_init_queue(msg_queue, 8);

receive_pid = thread_create(thread_stack, THREAD_STACKSIZE, THREAD_PRIORITY_MAIN - 1,
0, _receive_thread, NULL, "receive_thread");

shell_run(_commands, line_buf, SHELL_DEFAULT_BUFSIZE);

return 0;
}

0 comments on commit 18ad903

Please sign in to comment.