-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Tests/candev: Initial version with native support #13360
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| include ../Makefile.tests_common | ||
|
|
||
| USEMODULE += shell | ||
| USEMODULE += can | ||
| USEMODULE += isrpipe | ||
|
|
||
| # define the CAN driver you want to use here | ||
| CAN_DRIVER ?= native | ||
|
|
||
| ifeq ($(CAN_DRIVER), PERIPH_CAN) | ||
| # periph_can modules/variables go here | ||
|
|
||
| else ifeq ($(CAN_DRIVER), CAN_NATIVE) | ||
| # can_native modules/variables go here | ||
|
|
||
| endif | ||
|
|
||
| CFLAGS += -DCAN_DRIVER_$(CAN_DRIVER) | ||
|
|
||
| include $(RIOTBASE)/Makefile.include |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| FEATURES_BLACKLIST += arch_msp430 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,109 @@ | ||
| # Candev abstraction test | ||
|
|
||
| ## About | ||
|
|
||
| This application is a test for using the candev abstraction directly. | ||
| Use this if you want to use a single CAN driver and thus don't need the CAN-DLL layer. | ||
|
|
||
| Native prerequisites | ||
| ============ | ||
| For using the can stack on top of socketCAN, available for linux, you need: | ||
| - socketCAN (part of kernel starting from 2.6.25) | ||
| - install the 32bit version of libsocketcan: | ||
|
|
||
| if you're on a 64bit system: | ||
| ``` | ||
| sudo dpkg --add-architecture i386 | ||
| sudo apt-get update | ||
| sudo apt-get install libsocketcan-dev:i386 | ||
| ``` | ||
| On 32 bit you can just do the following: | ||
| ``` | ||
| sudo apt-get install libsocketcan-dev | ||
| ``` | ||
|
|
||
| Alternatively, you can compile from source: | ||
|
|
||
| ``` | ||
| wget http://www.pengutronix.de/software/libsocketcan/download/libsocketcan-0.0.10.tar.bz2 | ||
| $ sudo tar xvjf libsocketcan-0.0.10.tar.bz2 | ||
|
|
||
| $ sudo rm -rf libsocketcan-0.0.10.tar.bz2 | ||
|
|
||
| $ sudo cd libsocketcan-0.0.10 | ||
|
|
||
| $ sudo ./configure | ||
|
|
||
| compile in 32bits | ||
|
|
||
| ./configure --build=i686-pc-linux-gnu "CFLAGS=-m32" "CXXFLAG | ||
|
|
||
| $ sudo make | ||
|
|
||
| $ sudo make install | ||
|
|
||
| sudo ldconfig /usr/local/lib | ||
| ``` | ||
|
|
||
| The default native configuration 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 | ||
|
|
||
| ### Sending | ||
|
|
||
| Messages can be sent over the CAN-bus through the `send` command. Optionally, up to 8 bytes can be passed as arguments (in decimal form). If no arguments are passed it will default to sending AB CD EF (hex). | ||
|
|
||
| ``` | ||
| send <bytes> | ||
| ``` | ||
|
|
||
| When running the app native on linux, the sent bytes can be seen by scanning the CANbus with candump: | ||
|
|
||
| ``` | ||
| $ candump vcan0 | ||
| ``` | ||
|
|
||
| ### Receiving | ||
|
|
||
| The test-app is always listening for incoming CAN messages. They will be stored asynchronously in a buffer and can be requested by means of the `receive` command. Optionally, an argument n can be passed to receive n messages in a row. | ||
|
|
||
| ``` | ||
| receive <n> | ||
| ``` | ||
|
|
||
| If more messages are requested than are available in the buffer, the receive function will block until new data is available. | ||
|
|
||
| When running the app native on linux, data can be sent with `cansend`: | ||
|
|
||
| ``` | ||
| $ cansend <interface> <can_id>:<hexbytes> | ||
| ``` | ||
|
|
||
| e.g.: | ||
|
|
||
| ``` | ||
| $ cansend vcan0 001:1234ABCD | ||
| ``` | ||
|
|
||
| An alternative is to use `cangen` to generate a number of random can messages: | ||
|
|
||
| ``` | ||
| $ cangen <interface> -v -n <n> | ||
| ``` | ||
|
|
||
| e.g.: | ||
|
|
||
| ``` | ||
| $ cangen vcan0 -v -n 5 | ||
| ``` | ||
|
|
||
| will send 5 can messages to vcan0 with verbose output. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,214 @@ | ||
| /* | ||
| * Copyright (C) 2020 Nalys | ||
| * | ||
| * This file is subject to the terms and conditions of the GNU Lesser | ||
| * General Public License v2.1. See the file LICENSE in the top level | ||
| * directory for more details. | ||
| */ | ||
|
|
||
| /** | ||
| * @ingroup tests | ||
| * @{ | ||
| * | ||
| * @file | ||
| * @brief Test application for the candev abstraction | ||
| * | ||
| * @author Toon Stegen <tstegen@nalys-group.com> | ||
| * @author Wouter Symons <wsymons@nalys-group.com> | ||
| * | ||
| * @} | ||
| */ | ||
|
|
||
| #define ENABLE_DEBUG (0) | ||
|
|
||
| #include <debug.h> | ||
| #include <errno.h> | ||
| #include <stdio.h> | ||
| #include <stdlib.h> | ||
| #include <string.h> | ||
| #include <isrpipe.h> | ||
| #include "shell.h" | ||
| #include "can/device.h" | ||
|
|
||
| #ifdef BOARD_NATIVE | ||
|
|
||
| #include <candev_linux.h> | ||
|
|
||
| static candev_linux_t linux_dev; | ||
|
|
||
| #else | ||
| /* add other candev drivers here */ | ||
| #endif | ||
|
|
||
| #define RX_RINGBUFFER_SIZE 128 /* Needs to be a power of 2! */ | ||
| static isrpipe_t rxbuf; | ||
| static uint8_t rx_ringbuf[RX_RINGBUFFER_SIZE]; | ||
|
|
||
| static candev_t *candev = NULL; | ||
|
|
||
| static int _send(int argc, char **argv) | ||
| { | ||
| int ret = 0; | ||
|
|
||
| struct can_frame frame = { | ||
| .can_id = 1, | ||
| .can_dlc = 3, | ||
| .data[0] = 0xAB, | ||
| .data[1] = 0xCD, | ||
| .data[2] = 0xEF, | ||
| }; | ||
|
|
||
| if (argc > 1) { | ||
| if (argc > 1 + CAN_MAX_DLEN) { | ||
| printf("Could not send. Maximum CAN-bytes: %d\n", CAN_MAX_DLEN); | ||
| return -1; | ||
| } | ||
| for (int i = 1; i < argc; i++) { | ||
| frame.data[i - 1] = atoi(argv[i]); | ||
| } | ||
| frame.can_dlc = argc - 1; | ||
| } | ||
|
|
||
| ret = candev->driver->send(candev, &frame); | ||
| if (ret < 0) { | ||
| puts("Failed to send CAN-message!"); | ||
| } | ||
| else { | ||
| DEBUG("sent using mailbox: %d\n", ret); | ||
| } | ||
|
|
||
| return 0; | ||
| } | ||
|
|
||
| static int _receive(int argc, char **argv) | ||
| { | ||
| uint8_t buf[CAN_MAX_DLEN]; | ||
| int n = 1; | ||
|
|
||
| if (argc > 1) { | ||
| n = strtol(argv[1], NULL, 10); | ||
| if (n < 1) { | ||
| puts("Usage: receive <number>"); | ||
| return -1; | ||
| } | ||
| } | ||
|
|
||
| for (int i = 0; i < n; i++) { | ||
| uint32_t can_id = 0; | ||
| uint8_t can_dlc = 0; | ||
|
|
||
| puts("Reading from Rxbuf..."); | ||
| isrpipe_read(&rxbuf, buf, 4); /* can-id */ | ||
| can_id = ((uint32_t)buf[0] << 24) | | ||
| ((uint32_t)buf[1] << 16) | | ||
| ((uint32_t)buf[2] << 8) | | ||
| ((uint32_t)buf[3]); | ||
| isrpipe_read(&rxbuf, buf, 1); /* can-dlc */ | ||
| can_dlc = buf[0]; | ||
| isrpipe_read(&rxbuf, buf, can_dlc); /* data */ | ||
|
|
||
| printf("id: %" PRIx32 " dlc: %" PRIx8 " Data: \n", can_id, can_dlc); | ||
| for (int i = 0; i < can_dlc; i++) { | ||
| printf("0x%X ", buf[i]); | ||
| } | ||
| puts(""); | ||
| } | ||
|
|
||
| return 0; | ||
| } | ||
|
|
||
| static const shell_command_t shell_commands[] = { | ||
| { "send", "send some data", _send }, | ||
| { "receive", "receive some data", _receive }, | ||
| { NULL, NULL, NULL } | ||
| }; | ||
|
|
||
| static void _can_event_callback(candev_t *dev, candev_event_t event, void *arg) | ||
| { | ||
| (void)arg; | ||
| struct can_frame *frame; | ||
|
|
||
| switch (event) { | ||
| case CANDEV_EVENT_ISR: | ||
| DEBUG("_can_event: CANDEV_EVENT_ISR\n"); | ||
| dev->driver->isr(candev); | ||
| break; | ||
| case CANDEV_EVENT_WAKE_UP: | ||
| DEBUG("_can_event: CANDEV_EVENT_WAKE_UP\n"); | ||
| break; | ||
| case CANDEV_EVENT_TX_CONFIRMATION: | ||
| DEBUG("_can_event: CANDEV_EVENT_TX_CONFIRMATION\n"); | ||
| break; | ||
| case CANDEV_EVENT_TX_ERROR: | ||
| DEBUG("_can_event: CANDEV_EVENT_TX_ERROR\n"); | ||
| break; | ||
| case CANDEV_EVENT_RX_INDICATION: | ||
| DEBUG("_can_event: CANDEV_EVENT_RX_INDICATION\n"); | ||
|
|
||
| frame = (struct can_frame *)arg; | ||
|
|
||
| DEBUG("\tid: %" PRIx32 " dlc: %" PRIx8 " Data: \n\t", frame->can_id, | ||
| frame->can_dlc); | ||
| for (uint8_t i = 0; i < frame->can_dlc; i++) { | ||
| DEBUG("0x%X ", frame->data[i]); | ||
| } | ||
| DEBUG(" "); | ||
|
|
||
| /* Store in buffer until user requests the data */ | ||
| isrpipe_write_one(&rxbuf, | ||
| (uint8_t)((frame->can_id & 0x1FFFFFFF) >> 24)); | ||
| isrpipe_write_one(&rxbuf, | ||
| (uint8_t)((frame->can_id & 0xFF0000) >> 16)); | ||
| isrpipe_write_one(&rxbuf, (uint8_t)((frame->can_id & 0xFF00) >> 8)); | ||
| isrpipe_write_one(&rxbuf, (uint8_t)((frame->can_id & 0xFF))); | ||
|
|
||
| isrpipe_write_one(&rxbuf, frame->can_dlc); | ||
| for (uint8_t i = 0; i < frame->can_dlc; i++) { | ||
| isrpipe_write_one(&rxbuf, frame->data[i]); | ||
| } | ||
|
|
||
| break; | ||
| case CANDEV_EVENT_RX_ERROR: | ||
| DEBUG("_can_event: CANDEV_EVENT_RX_ERROR\n"); | ||
| break; | ||
| case CANDEV_EVENT_BUS_OFF: | ||
| dev->state = CAN_STATE_BUS_OFF; | ||
| break; | ||
| case CANDEV_EVENT_ERROR_PASSIVE: | ||
| dev->state = CAN_STATE_ERROR_PASSIVE; | ||
| break; | ||
| case CANDEV_EVENT_ERROR_WARNING: | ||
| dev->state = CAN_STATE_ERROR_WARNING; | ||
| break; | ||
| default: | ||
| DEBUG("_can_event: unknown event\n"); | ||
| break; | ||
| } | ||
| } | ||
|
|
||
| int main(void) | ||
| { | ||
|
|
||
| puts("candev test application\n"); | ||
|
|
||
| isrpipe_init(&rxbuf, (uint8_t *)rx_ringbuf, sizeof(rx_ringbuf)); | ||
| #ifdef BOARD_NATIVE | ||
| puts("Initializing Linux Can device"); | ||
| candev_linux_init( &linux_dev, &(candev_linux_conf[0])); /* vcan0 */ | ||
| candev = (candev_t *)&linux_dev; | ||
| #else | ||
| /* add initialization for other candev drivers here */ | ||
| #endif | ||
|
|
||
| assert(candev); | ||
|
|
||
| candev->event_callback = _can_event_callback; | ||
| candev->isr_arg = NULL; | ||
|
|
||
| candev->driver->init(candev); | ||
|
|
||
| char line_buf[SHELL_DEFAULT_BUFSIZE]; | ||
| shell_run(shell_commands, line_buf, SHELL_DEFAULT_BUFSIZE); | ||
|
|
||
| return 0; | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.