-
Notifications
You must be signed in to change notification settings - Fork 113
feat(esp_isotp): add ISO-TP protocol component's echo example (IEC-376) #568
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
Open
eternal-echo
wants to merge
2
commits into
espressif:master
Choose a base branch
from
eternal-echo:features/isotp-doc-echo
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
# For more information about build system see | ||
# https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html | ||
# The following five lines of boilerplate have to be in your project's | ||
# CMakeLists in this exact order for cmake to work correctly | ||
cmake_minimum_required(VERSION 3.16) | ||
|
||
include($ENV{IDF_PATH}/tools/cmake/project.cmake) | ||
|
||
project(esp_isotp_echo_example) |
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,55 @@ | ||
# ISO-TP Echo Example | ||
|
||
Simple ISO-TP echo service: receives data and sends it back. Supports single-frame and multi-frame transfers. | ||
|
||
## How to Use Example | ||
|
||
### Hardware Required | ||
|
||
* An ESP32 development board | ||
* A transceiver (e.g., TJA1050) | ||
* An USB cable for power supply and programming | ||
|
||
### Configuration | ||
|
||
Use `idf.py menuconfig` to configure the example: | ||
|
||
- **ISO-TP Echo Configuration → TWAI Basic Configuration**: | ||
- TX GPIO Number (default: GPIO 5) | ||
- RX GPIO Number (default: GPIO 4) | ||
- TWAI Bitrate (default: 500000) | ||
|
||
- **ISO-TP Echo Configuration → ISO-TP Configuration**: | ||
- TX/RX Message IDs (default: 0x7E0/0x7E8) | ||
- Buffer sizes | ||
|
||
Connect the ESP32 to a CAN transceiver and the CAN bus. | ||
|
||
### Build and Flash | ||
|
||
Run `idf.py -p PORT flash monitor` to build, flash and monitor the project. | ||
|
||
(To exit the serial monitor, type ``Ctrl-]``.) | ||
|
||
See the [Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html) for full steps to configure and use ESP-IDF to build projects. | ||
|
||
### Example Output | ||
|
||
Once the application is running, you will see the following output: | ||
|
||
``` | ||
I (xxx) isotp_echo: ISO-TP Echo Demo started | ||
I (xxx) isotp_echo: ISO-TP echo example's TX ID: 0x7E0, RX ID: 0x7E8 | ||
``` | ||
|
||
To test the echo functionality, you can use a tool like `can-utils` on a Linux machine connected to the same CAN bus: | ||
|
||
```bash | ||
# Send a message and wait for the echo (using default IDs from Kconfig) | ||
candump -tA -e -c -a vcan0 & | ||
(isotprecv -s 0x7E0 -d 0x7E8 vcan0 | hexdump -C) & (echo 11 22 33 44 55 66 DE AD BE EF | isotpsend -s 0x7E0 -d 0x7E8 vcan0) | ||
``` | ||
|
||
## Troubleshooting | ||
|
||
For any technical queries, please open an [issue](https://github.com/espressif/idf-extra-components/issues) on GitHub. We will get back to you soon. |
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,42 @@ | ||
# SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD | ||
# SPDX-License-Identifier: Unlicense OR CC0-1.0 | ||
|
||
import pytest | ||
import subprocess | ||
import logging | ||
|
||
|
||
@pytest.fixture(autouse=True, scope='session') | ||
def setup_vcan_interface(): | ||
"""Ensure vcan0 interface is available for QEMU CAN testing.""" | ||
created_interface = False | ||
|
||
try: | ||
# Check if vcan0 exists | ||
result = subprocess.run(['ip', 'link', 'show', 'vcan0'], | ||
capture_output=True, text=True, check=False) | ||
if result.returncode != 0: | ||
logging.info("Creating vcan0 interface...") | ||
# Try creating vcan0 interface | ||
subprocess.run(['sudo', 'ip', 'link', 'add', 'dev', 'vcan0', 'type', 'vcan'], | ||
capture_output=True, text=True, check=False) | ||
created_interface = True | ||
|
||
# Ensure it's up | ||
subprocess.run(['sudo', 'ip', 'link', 'set', 'up', 'vcan0'], | ||
capture_output=True, text=True, check=False) | ||
logging.info("vcan0 interface ready") | ||
|
||
except Exception as e: | ||
logging.warning(f"Could not setup vcan0: {e}. QEMU will handle CAN interface setup.") | ||
|
||
yield # Test execution happens here | ||
|
||
# Cleanup: Remove vcan0 interface if we created it | ||
if created_interface: | ||
try: | ||
subprocess.run(['sudo', 'ip', 'link', 'delete', 'vcan0'], | ||
capture_output=True, text=True, check=False) | ||
logging.info("vcan0 interface cleaned up") | ||
except Exception as e: | ||
logging.warning(f"Could not cleanup vcan0: {e}") |
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,2 @@ | ||
idf_component_register(SRCS "isotp_echo_main.c" | ||
INCLUDE_DIRS ".") |
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,91 @@ | ||
menu "ISO-TP Echo Configuration" | ||
menu "TWAI Basic Configuration" | ||
config EXAMPLE_TX_GPIO_NUM | ||
int "TX GPIO Number" | ||
default 5 | ||
range 0 48 | ||
help | ||
GPIO pin number for TWAI transmission. | ||
|
||
config EXAMPLE_RX_GPIO_NUM | ||
int "RX GPIO Number" | ||
default 4 | ||
range 0 48 | ||
help | ||
GPIO pin number for TWAI reception. | ||
|
||
config EXAMPLE_BITRATE | ||
int "TWAI Bitrate" | ||
default 500000 | ||
range 25000 1000000 | ||
help | ||
TWAI bitrate in bits per second. | ||
Common values: 125000, 250000, 500000, 1000000 | ||
|
||
config EXAMPLE_TWAI_TX_QUEUE_DEPTH | ||
int "TWAI TX Queue Length" | ||
default 16 | ||
range 1 64 | ||
help | ||
Length of the TWAI transmit queue. | ||
|
||
endmenu | ||
|
||
menu "ISO-TP Configuration" | ||
config EXAMPLE_ISOTP_TX_ID | ||
hex "TX Message ID" | ||
default 0x7E8 | ||
help | ||
TWAI ID for transmitting ISO-TP messages. | ||
|
||
config EXAMPLE_ISOTP_RX_ID | ||
hex "RX Message ID" | ||
default 0x7E0 | ||
help | ||
TWAI ID for receiving ISO-TP messages. | ||
|
||
config EXAMPLE_ISOTP_TX_BUFFER_SIZE | ||
int "ISO-TP TX Buffer Size" | ||
default 4096 | ||
range 256 8192 | ||
help | ||
Size of the ISO-TP transmission buffer. | ||
|
||
config EXAMPLE_ISOTP_RX_BUFFER_SIZE | ||
int "ISO-TP RX Buffer Size" | ||
default 4096 | ||
range 256 8192 | ||
help | ||
Size of the ISO-TP reception buffer. | ||
|
||
config EXAMPLE_ISOTP_TX_FRAME_POOL_SIZE | ||
int "ISO-TP TX Frame Pool Size" | ||
default 8 | ||
range 1 32 | ||
help | ||
Number of TX frames in the ISO-TP transmission pool. | ||
endmenu | ||
|
||
menu "Task Configuration" | ||
config EXAMPLE_ECHO_TASK_STACK_SIZE | ||
int "Task Stack Size" | ||
default 4096 | ||
range 2048 32768 | ||
help | ||
Stack size for the echo task. | ||
|
||
config EXAMPLE_ECHO_TASK_PRIORITY | ||
int "Task Priority" | ||
default 10 | ||
range 1 25 | ||
help | ||
FreeRTOS priority for the echo task. | ||
|
||
config EXAMPLE_ECHO_POLL_DELAY_MS | ||
int "Poll Interval (ms)" | ||
default 1 | ||
range 1 100 | ||
help | ||
Delay between consecutive ISO-TP protocol polls. | ||
endmenu | ||
endmenu |
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,4 @@ | ||
## IDF Component Manager Manifest File | ||
dependencies: | ||
esp_isotp: | ||
override_path: '../../../' |
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,130 @@ | ||
/* | ||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD | ||
* | ||
* SPDX-License-Identifier: Unlicense OR CC0-1.0 | ||
*/ | ||
|
||
#include <stdio.h> | ||
#include "freertos/FreeRTOS.h" | ||
#include "freertos/task.h" | ||
#include "esp_log.h" | ||
#include "esp_check.h" | ||
#include "esp_twai.h" | ||
#include "esp_twai_onchip.h" | ||
#include "esp_isotp.h" | ||
|
||
static const char *TAG = "isotp_echo"; | ||
|
||
// Global variables for cleanup | ||
static esp_isotp_handle_t g_isotp_handle = NULL; | ||
static twai_node_handle_t g_twai_node = NULL; | ||
static esp_err_t isotp_echo_init(void); | ||
static esp_err_t isotp_echo_deinit(void); | ||
|
||
static void on_tx_done(esp_isotp_handle_t handle, uint32_t tx_size, void *user_arg) | ||
{ | ||
ESP_EARLY_LOGI(TAG, "TX complete: %lu bytes", (unsigned long)tx_size); | ||
} | ||
|
||
static void on_rx_done(esp_isotp_handle_t handle, const uint8_t *data, uint32_t size, void *user_arg) | ||
{ | ||
ESP_EARLY_LOGI(TAG, "RX complete: %lu bytes, echoing back...", (unsigned long)size); | ||
|
||
// Check handle validity using ESP-IDF standard macro for ISR context | ||
ESP_RETURN_VOID_ON_FALSE_ISR(handle, TAG, "Echo send failed: invalid handle"); | ||
|
||
// Echo back the received data immediately (ISR-safe API) | ||
esp_err_t err = esp_isotp_send(handle, data, size); | ||
if (unlikely(err != ESP_OK && err != ESP_ERR_NOT_FINISHED)) { | ||
ESP_EARLY_LOGE(TAG, "Echo send failed: %s", esp_err_to_name(err)); | ||
} | ||
|
||
} | ||
|
||
void app_main(void) | ||
{ | ||
ESP_LOGI(TAG, "ISO-TP Echo Demo started"); | ||
|
||
// Initialize the ISO-TP echo example | ||
ESP_ERROR_CHECK(isotp_echo_init()); | ||
|
||
// Main task will just sleep, the echo_task handles the ISO-TP communication | ||
while (1) { | ||
vTaskDelay(pdMS_TO_TICKS(10000)); | ||
} | ||
|
||
// Deinitialize the ISO-TP echo example | ||
isotp_echo_deinit(); | ||
} | ||
|
||
static void echo_task(void *arg) | ||
{ | ||
esp_isotp_handle_t isotp_handle = (esp_isotp_handle_t)arg; | ||
|
||
ESP_LOGI(TAG, "ISO-TP Echo task started"); | ||
|
||
while (1) { | ||
// Poll ISO-TP protocol state machine (timeouts, consecutive frames, etc.) | ||
ESP_ERROR_CHECK(esp_isotp_poll(isotp_handle)); | ||
|
||
// Small delay to ensure accurate STmin timing and prevent 100% CPU usage | ||
vTaskDelay(pdMS_TO_TICKS(CONFIG_EXAMPLE_ECHO_POLL_DELAY_MS)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The configuration symbol CONFIG_EXAMPLE_ECHO_POLL_DELAY_MS is used but not defined in the provided Kconfig file. This should reference CONFIG_EXAMPLE_ECHO_POLL_DELAY_MS which is defined in Kconfig.projbuild. Copilot uses AI. Check for mistakes. Positive FeedbackNegative Feedback |
||
} | ||
|
||
ESP_LOGI(TAG, "ISO-TP Echo task finished"); | ||
vTaskDelete(NULL); | ||
} | ||
|
||
static esp_err_t isotp_echo_init(void) | ||
{ | ||
twai_onchip_node_config_t twai_cfg = { | ||
.io_cfg = { | ||
.tx = CONFIG_EXAMPLE_TX_GPIO_NUM, | ||
.rx = CONFIG_EXAMPLE_RX_GPIO_NUM, | ||
}, | ||
.bit_timing.bitrate = CONFIG_EXAMPLE_BITRATE, | ||
.tx_queue_depth = CONFIG_EXAMPLE_TWAI_TX_QUEUE_DEPTH, | ||
.intr_priority = 0, | ||
}; | ||
|
||
ESP_ERROR_CHECK(twai_new_node_onchip(&twai_cfg, &g_twai_node)); | ||
|
||
esp_isotp_config_t isotp_cfg = { | ||
.tx_id = CONFIG_EXAMPLE_ISOTP_TX_ID, | ||
.rx_id = CONFIG_EXAMPLE_ISOTP_RX_ID, | ||
.tx_buffer_size = CONFIG_EXAMPLE_ISOTP_TX_BUFFER_SIZE, | ||
.rx_buffer_size = CONFIG_EXAMPLE_ISOTP_RX_BUFFER_SIZE, | ||
.tx_frame_pool_size = CONFIG_EXAMPLE_ISOTP_TX_FRAME_POOL_SIZE, | ||
.rx_callback = on_rx_done, | ||
.tx_callback = on_tx_done, | ||
.callback_arg = NULL, | ||
}; | ||
|
||
ESP_ERROR_CHECK(esp_isotp_new_transport(g_twai_node, &isotp_cfg, &g_isotp_handle)); | ||
|
||
// Create echo task | ||
BaseType_t task_ret = xTaskCreate(echo_task, "isotp_echo", CONFIG_EXAMPLE_ECHO_TASK_STACK_SIZE, | ||
g_isotp_handle, CONFIG_EXAMPLE_ECHO_TASK_PRIORITY, NULL); | ||
ESP_RETURN_ON_FALSE(task_ret == pdPASS, ESP_FAIL, TAG, "Failed to create echo task"); | ||
|
||
ESP_LOGI(TAG, "ISO-TP echo example's TX ID: 0x%X, RX ID: 0x%X", | ||
CONFIG_EXAMPLE_ISOTP_TX_ID, CONFIG_EXAMPLE_ISOTP_RX_ID); | ||
|
||
return ESP_OK; | ||
} | ||
|
||
static esp_err_t isotp_echo_deinit(void) | ||
{ | ||
ESP_RETURN_ON_FALSE(g_isotp_handle != NULL, ESP_OK, TAG, "ISO-TP echo example is not initialized"); | ||
|
||
esp_isotp_delete(g_isotp_handle); | ||
g_isotp_handle = NULL; | ||
|
||
if (g_twai_node) { | ||
twai_node_delete(g_twai_node); | ||
g_twai_node = NULL; | ||
} | ||
|
||
ESP_LOGI(TAG, "ISO-TP echo example deinitialized"); | ||
return ESP_OK; | ||
} |
Oops, something went wrong.
Oops, something went wrong.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.