mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-02 03:00:34 +03:00
feat(driver_twai): support rx frame timestamp for all chips
Closes https://github.com/espressif/esp-idf/issues/4527
This commit is contained in:
@@ -6,7 +6,7 @@ endif()
|
||||
|
||||
set(srcs "esp_twai.c")
|
||||
set(public_include "include")
|
||||
set(priv_req esp_driver_gpio esp_pm)
|
||||
set(priv_req esp_driver_gpio esp_pm esp_timer)
|
||||
|
||||
if(CONFIG_SOC_TWAI_SUPPORTED)
|
||||
list(APPEND srcs "esp_twai_onchip.c")
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "esp_timer.h"
|
||||
#include "esp_twai.h"
|
||||
#include "esp_twai_onchip.h"
|
||||
#include "esp_private/twai_interface.h"
|
||||
@@ -68,10 +69,12 @@ typedef struct {
|
||||
uint64_t gpio_reserved;
|
||||
twai_hal_context_t *hal;
|
||||
intr_handle_t intr_hdl;
|
||||
intr_handle_t timer_intr_hdl;
|
||||
QueueHandle_t tx_mount_queue;
|
||||
EventGroupHandle_t event_group;
|
||||
twai_clock_source_t curr_clk_src;
|
||||
uint32_t src_freq_hz;
|
||||
uint32_t timestamp_freq_hz;
|
||||
uint32_t valid_fd_timing;
|
||||
twai_event_callbacks_t cbs;
|
||||
void *user_data;
|
||||
@@ -87,7 +90,8 @@ typedef struct {
|
||||
} twai_onchip_ctx_t;
|
||||
|
||||
typedef struct twai_platform_s {
|
||||
_lock_t mutex;
|
||||
_lock_t ctrlr_mutex;
|
||||
_lock_t intr_mutex;
|
||||
twai_onchip_ctx_t *nodes[SOC_TWAI_CONTROLLER_NUM];
|
||||
} twai_platform_t;
|
||||
static twai_platform_t s_platform;
|
||||
@@ -95,7 +99,7 @@ static twai_platform_t s_platform;
|
||||
static int _ctrlr_acquire(twai_onchip_ctx_t *node)
|
||||
{
|
||||
int ctrlr_id = -1;
|
||||
_lock_acquire(&s_platform.mutex);
|
||||
_lock_acquire(&s_platform.ctrlr_mutex);
|
||||
// Check if there is a controller available for use
|
||||
for (int i = 0; i < SOC_TWAI_CONTROLLER_NUM; i++) {
|
||||
if (s_platform.nodes[i] == NULL) {
|
||||
@@ -105,7 +109,7 @@ static int _ctrlr_acquire(twai_onchip_ctx_t *node)
|
||||
break;
|
||||
}
|
||||
}
|
||||
_lock_release(&s_platform.mutex);
|
||||
_lock_release(&s_platform.ctrlr_mutex);
|
||||
|
||||
// Return the controller index or -1
|
||||
return ctrlr_id;
|
||||
@@ -113,11 +117,11 @@ static int _ctrlr_acquire(twai_onchip_ctx_t *node)
|
||||
|
||||
static void _ctrlr_release(int ctrlr_id)
|
||||
{
|
||||
_lock_acquire(&s_platform.mutex);
|
||||
_lock_acquire(&s_platform.ctrlr_mutex);
|
||||
assert(s_platform.nodes[ctrlr_id]);
|
||||
// Clear the node object from the controller slot
|
||||
s_platform.nodes[ctrlr_id] = NULL;
|
||||
_lock_release(&s_platform.mutex);
|
||||
_lock_release(&s_platform.ctrlr_mutex);
|
||||
}
|
||||
|
||||
static esp_err_t _node_config_io(twai_onchip_ctx_t *node, const twai_onchip_node_config_t *node_config)
|
||||
@@ -311,6 +315,9 @@ static void _node_destroy(twai_onchip_ctx_t *twai_ctx)
|
||||
if (twai_ctx->intr_hdl) {
|
||||
esp_intr_free(twai_ctx->intr_hdl);
|
||||
}
|
||||
if (twai_ctx->timer_intr_hdl) {
|
||||
esp_intr_free(twai_ctx->timer_intr_hdl);
|
||||
}
|
||||
if (twai_ctx->tx_mount_queue) {
|
||||
vQueueDeleteWithCaps(twai_ctx->tx_mount_queue);
|
||||
}
|
||||
@@ -423,6 +430,18 @@ static esp_err_t _node_calc_set_bit_timing(twai_node_handle_t node, const twai_t
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
//convert microseconds to timestamp units
|
||||
__attribute__((always_inline))
|
||||
static inline uint64_t _time_us_to_timestamp(uint64_t time_us, uint32_t resolution)
|
||||
{
|
||||
if (resolution > 1000000) {
|
||||
return time_us * (resolution / 1000000);
|
||||
} else if (resolution > 0) {
|
||||
return time_us / (1000000 / resolution);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------- Node Control -------------------------------------------------- */
|
||||
|
||||
static esp_err_t _node_enable(twai_node_handle_t node)
|
||||
@@ -437,7 +456,12 @@ static esp_err_t _node_enable(twai_node_handle_t node)
|
||||
}
|
||||
#endif //CONFIG_PM_ENABLE
|
||||
twai_hal_start(twai_ctx->hal);
|
||||
|
||||
#if SOC_TWAI_SUPPORT_TIMESTAMP
|
||||
if (twai_ctx->timestamp_freq_hz) {
|
||||
twai_hal_timer_start_with(twai_ctx->hal, _time_us_to_timestamp(esp_timer_get_time(), twai_ctx->timestamp_freq_hz));
|
||||
ESP_RETURN_ON_ERROR(esp_intr_enable(twai_ctx->timer_intr_hdl), TAG, "enable timer interrupt failed");
|
||||
}
|
||||
#endif
|
||||
twai_error_state_t hw_state = twai_hal_get_err_state(twai_ctx->hal);
|
||||
atomic_store(&twai_ctx->state, hw_state);
|
||||
// continuing the transaction if there be
|
||||
@@ -453,6 +477,12 @@ static esp_err_t _node_disable(twai_node_handle_t node)
|
||||
twai_onchip_ctx_t *twai_ctx = __containerof(node, twai_onchip_ctx_t, api_base);
|
||||
ESP_RETURN_ON_FALSE(atomic_load(&twai_ctx->state) != TWAI_ERROR_BUS_OFF, ESP_ERR_INVALID_STATE, TAG, "node already disabled");
|
||||
|
||||
#if SOC_TWAI_SUPPORT_TIMESTAMP
|
||||
if (twai_ctx->timestamp_freq_hz) {
|
||||
twai_hal_timer_stop(twai_ctx->hal);
|
||||
ESP_RETURN_ON_ERROR(esp_intr_disable(twai_ctx->timer_intr_hdl), TAG, "disable timer interrupt failed");
|
||||
}
|
||||
#endif
|
||||
ESP_RETURN_ON_ERROR(esp_intr_disable(twai_ctx->intr_hdl), TAG, "disable interrupt failed");
|
||||
atomic_store(&twai_ctx->state, TWAI_ERROR_BUS_OFF);
|
||||
twai_hal_stop(twai_ctx->hal);
|
||||
@@ -619,7 +649,11 @@ static esp_err_t _node_parse_rx(twai_node_handle_t node, twai_frame_t *rx_frame)
|
||||
ESP_RETURN_ON_FALSE_ISR(atomic_load(&twai_ctx->rx_isr), ESP_ERR_INVALID_STATE, TAG, "rx can only called in `rx_done` callback");
|
||||
assert(xPortInIsrContext() && "should always in rx_done callback");
|
||||
|
||||
twai_hal_parse_frame(&twai_ctx->rcv_buff, &rx_frame->header, rx_frame->buffer, rx_frame->buffer_len);
|
||||
twai_hal_parse_frame(twai_ctx->hal, &twai_ctx->rcv_buff, &rx_frame->header, rx_frame->buffer, rx_frame->buffer_len);
|
||||
if (twai_ctx->timestamp_freq_hz && !rx_frame->header.timestamp) {
|
||||
// if timestamp not updated by hardware, use the esp_timer timestamp to calculate the timestamp
|
||||
rx_frame->header.timestamp = _time_us_to_timestamp(esp_timer_get_time(), twai_ctx->timestamp_freq_hz);
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@@ -639,6 +673,8 @@ esp_err_t twai_new_node_onchip(const twai_onchip_node_config_t *node_config, twa
|
||||
ESP_GOTO_ON_FALSE(ctrlr_id != -1, ESP_ERR_NOT_FOUND, err, TAG, "Controller not available");
|
||||
node->ctrlr_id = ctrlr_id;
|
||||
node->hal = (twai_hal_context_t *)(node + 1); //hal context is place at end of driver context
|
||||
node->curr_clk_src = node_config->clk_src ? node_config->clk_src : TWAI_CLK_SRC_DEFAULT;
|
||||
ESP_GOTO_ON_ERROR(esp_clk_tree_src_get_freq_hz(node->curr_clk_src, ESP_CLK_TREE_SRC_FREQ_PRECISION_APPROX, &node->src_freq_hz), err, TAG, "get clock source frequency failed");
|
||||
|
||||
// state is in bus_off before enabled
|
||||
atomic_store(&node->state, TWAI_ERROR_BUS_OFF);
|
||||
@@ -647,22 +683,39 @@ esp_err_t twai_new_node_onchip(const twai_onchip_node_config_t *node_config, twa
|
||||
ESP_GOTO_ON_FALSE((node->tx_mount_queue && node->event_group) || node_config->flags.enable_listen_only, ESP_ERR_NO_MEM, err, TAG, "no_mem");
|
||||
uint32_t intr_flags = TWAI_INTR_ALLOC_FLAGS;
|
||||
intr_flags |= (node_config->intr_priority > 0) ? BIT(node_config->intr_priority) : ESP_INTR_FLAG_LOWMED;
|
||||
_lock_acquire(&s_platform.intr_mutex); // lock to prevent twai_intr and timer_intr registered to different cpu then triggered at the same time
|
||||
ESP_GOTO_ON_ERROR(esp_intr_alloc(twai_controller_periph_signals.controllers[ctrlr_id].irq_id, intr_flags, _node_isr_main, (void *)node, &node->intr_hdl),
|
||||
err, TAG, "Alloc interrupt failed");
|
||||
|
||||
if (node_config->timestamp_resolution_hz) {
|
||||
#if SOC_TWAI_SUPPORT_TIMESTAMP
|
||||
ESP_GOTO_ON_FALSE((node_config->timestamp_resolution_hz >= (node->src_freq_hz / TWAI_LL_TIMER_DIV_MAX)) && (node_config->timestamp_resolution_hz <= node->src_freq_hz), \
|
||||
ESP_ERR_INVALID_ARG, err, TAG, "Timestamp resolution range [%d, %d]", node->src_freq_hz / TWAI_LL_TIMER_DIV_MAX, node->src_freq_hz);
|
||||
uint32_t real_timer_freq = node->src_freq_hz / (node->src_freq_hz / node_config->timestamp_resolution_hz);
|
||||
if (real_timer_freq != node_config->timestamp_resolution_hz) {
|
||||
ESP_LOGW(TAG, "timestamp resolution loss, adjust to %dHz", real_timer_freq);
|
||||
}
|
||||
// deal timer interrupt in same `_node_isr_main` handler and check timer event first
|
||||
// to avoid race condition if two hardware interrupts are triggered at the same time
|
||||
ESP_GOTO_ON_ERROR(esp_intr_alloc(twai_controller_periph_signals.controllers[ctrlr_id].timer_irq_id, intr_flags, _node_isr_main, (void *)node, &node->timer_intr_hdl),
|
||||
err, TAG, "Alloc timer interrupt failed");
|
||||
#else
|
||||
ESP_GOTO_ON_FALSE(node_config->timestamp_resolution_hz <= 1000000, ESP_ERR_INVALID_ARG, err, TAG, "Timestamp resolution is at most 1MHz");
|
||||
#endif
|
||||
node->timestamp_freq_hz = node_config->timestamp_resolution_hz;
|
||||
}
|
||||
_lock_release(&s_platform.intr_mutex);
|
||||
|
||||
#if CONFIG_PM_ENABLE
|
||||
#if SOC_TWAI_CLK_SUPPORT_APB
|
||||
// DFS can change APB frequency. So add lock to prevent sleep and APB freq from changing
|
||||
ESP_GOTO_ON_ERROR(esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, twai_periph_signals[ctrlr_id].module_name, &node->pm_lock), err, TAG, "init power manager failed");
|
||||
ESP_GOTO_ON_ERROR(esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, twai_controller_periph_signals.controllers[ctrlr_id].module_name, &node->pm_lock), err, TAG, "init power manager failed");
|
||||
#else // XTAL
|
||||
// XTAL freq can be closed in light sleep, so we need to create a lock to prevent light sleep
|
||||
ESP_GOTO_ON_ERROR(esp_pm_lock_create(ESP_PM_NO_LIGHT_SLEEP, 0, twai_periph_signals[ctrlr_id].module_name, &node->pm_lock), err, TAG, "init power manager failed");
|
||||
ESP_GOTO_ON_ERROR(esp_pm_lock_create(ESP_PM_NO_LIGHT_SLEEP, 0, twai_controller_periph_signals.controllers[ctrlr_id].module_name, &node->pm_lock), err, TAG, "init power manager failed");
|
||||
#endif //SOC_TWAI_CLK_SUPPORT_APB
|
||||
#endif //CONFIG_PM_ENABLE
|
||||
|
||||
node->curr_clk_src = node_config->clk_src ? node_config->clk_src : TWAI_CLK_SRC_DEFAULT;
|
||||
esp_clk_tree_src_get_freq_hz(node->curr_clk_src, ESP_CLK_TREE_SRC_FREQ_PRECISION_APPROX, &node->src_freq_hz);
|
||||
|
||||
// Set clock source, enable bus clock and reset controller
|
||||
ESP_RETURN_ON_ERROR(esp_clk_tree_enable_src(node->curr_clk_src, true), TAG, "enable clock source failed");
|
||||
ESP_LOGD(TAG, "set clock source to %d, freq: %ld Hz", node->curr_clk_src, node->src_freq_hz);
|
||||
@@ -674,6 +727,7 @@ esp_err_t twai_new_node_onchip(const twai_onchip_node_config_t *node_config, twa
|
||||
.controller_id = node->ctrlr_id,
|
||||
.intr_mask = TWAI_LL_DRIVER_INTERRUPTS,
|
||||
.clock_source_hz = node->src_freq_hz,
|
||||
.timer_freq = node->timestamp_freq_hz,
|
||||
.retry_cnt = node_config->fail_retry_cnt,
|
||||
.no_receive_rtr = node_config->flags.no_receive_rtr,
|
||||
.enable_listen_only = node_config->flags.enable_listen_only,
|
||||
@@ -705,6 +759,7 @@ esp_err_t twai_new_node_onchip(const twai_onchip_node_config_t *node_config, twa
|
||||
return ESP_OK;
|
||||
err:
|
||||
if (node) {
|
||||
_lock_release(&s_platform.intr_mutex);
|
||||
_node_destroy(node);
|
||||
}
|
||||
return ret;
|
||||
|
||||
@@ -26,6 +26,7 @@ typedef struct {
|
||||
twai_clock_source_t clk_src; /**< Optional, clock source, remain 0 to using TWAI_CLK_SRC_DEFAULT by default */
|
||||
twai_timing_basic_config_t bit_timing; /**< Timing configuration for classic twai and FD arbitration stage */
|
||||
twai_timing_basic_config_t data_timing; /**< Optional, timing configuration for FD data stage */
|
||||
uint32_t timestamp_resolution_hz; /**< Timebase frequency (in Hz), used for recording the timestamp of RX frame, set 0 to disable the timestamp feature */
|
||||
int8_t fail_retry_cnt; /**< Hardware retry limit if failed, range [-1:15], -1 for re-trans forever */
|
||||
uint32_t tx_queue_depth; /**< Depth of the transmit queue */
|
||||
int intr_priority; /**< Interrupt priority, [0:3] */
|
||||
|
||||
@@ -10,6 +10,6 @@ endif()
|
||||
|
||||
idf_component_register(
|
||||
SRCS ${srcs}
|
||||
PRIV_REQUIRES esp_driver_twai esp_timer esp_driver_uart
|
||||
PRIV_REQUIRES esp_driver_twai esp_timer esp_driver_uart esp_driver_gpio
|
||||
WHOLE_ARCHIVE
|
||||
)
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#include "esp_heap_caps.h"
|
||||
|
||||
// lazy install of mutex and pm_lock occupied memorys
|
||||
#define LEAKS (300)
|
||||
#define LEAKS (400)
|
||||
|
||||
void setUp(void)
|
||||
{
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -12,12 +12,13 @@
|
||||
#include "test_utils.h"
|
||||
#include "esp_attr.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_timer.h"
|
||||
#include "esp_heap_caps.h"
|
||||
#include "esp_clk_tree.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "esp_twai.h"
|
||||
#include "esp_twai_onchip.h"
|
||||
#include "hal/twai_periph.h"
|
||||
#include "soc/twai_periph.h"
|
||||
#include "esp_private/gpio.h"
|
||||
#include "soc/gpio_sig_map.h"
|
||||
#include "driver/uart.h" // for baudrate detection
|
||||
@@ -621,9 +622,9 @@ TEST_CASE("test arb lost and stuff err", "[twai]")
|
||||
if (tx_frame.header.id < 0x7F0 - 2) { // trigger error after 2 frames
|
||||
printf("trigger arb lost now!\n");
|
||||
esp_rom_delay_us(5 * (1000000 / node_config.bit_timing.bitrate)); // trigger error at 30 bits after frame start
|
||||
gpio_matrix_output(TEST_TX_GPIO, SIG_GPIO_OUT_IDX, false, false);
|
||||
esp_rom_gpio_connect_out_signal(TEST_TX_GPIO, twai_controller_periph_signals.controllers[0].tx_sig, false, false);
|
||||
esp_rom_delay_us(2 * (1000000 / node_config.bit_timing.bitrate)); // trigger error for 2 bits
|
||||
gpio_matrix_output(TEST_TX_GPIO, twai_periph_signals[0].tx_sig, false, false);
|
||||
esp_rom_gpio_connect_out_signal(TEST_TX_GPIO, twai_controller_periph_signals.controllers[0].tx_sig, false, false);
|
||||
}
|
||||
vTaskDelay(pdMS_TO_TICKS(1000)); // some time for hardware report errors
|
||||
twai_node_get_info(node_hdl, &node_status, NULL);
|
||||
@@ -804,7 +805,7 @@ static IRAM_ATTR bool test_dlc_range_cb(twai_node_handle_t handle, const twai_rx
|
||||
{
|
||||
twai_frame_t *rx_frame = (twai_frame_t *)user_ctx;
|
||||
if (ESP_OK == twai_node_receive_from_isr(handle, rx_frame)) {
|
||||
esp_rom_printf(DRAM_STR("RX len %d %s\n"), rx_frame->header.dlc, rx_frame->buffer);
|
||||
ESP_EARLY_LOGI("RX", "timestamp %llu frame %x [%d] %s", rx_frame->header.timestamp, rx_frame->header.id, rx_frame->header.dlc, rx_frame->buffer);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -850,6 +851,7 @@ TEST_CASE("twai dlc range test", "[twai]")
|
||||
TEST_ASSERT_EQUAL(len % 9, rx_frame.header.dlc);
|
||||
memset(rx_buffer, 0, sizeof(rx_buffer));
|
||||
}
|
||||
TEST_ASSERT_EQUAL(0, rx_frame.header.timestamp); // timestamp should be 0 if not enabled
|
||||
|
||||
tx_frame.buffer_len = 9;
|
||||
tx_frame.header.dlc = 0;
|
||||
@@ -862,3 +864,72 @@ TEST_CASE("twai dlc range test", "[twai]")
|
||||
TEST_ESP_OK(twai_node_disable(node_hdl));
|
||||
TEST_ESP_OK(twai_node_delete(node_hdl));
|
||||
}
|
||||
|
||||
#define MS_TO_TWAI_TICK(time_ms, resolution) ((time_ms) * (resolution / 1000))
|
||||
TEST_CASE("twai rx timestamp", "[twai]")
|
||||
{
|
||||
twai_node_handle_t node_hdl;
|
||||
twai_onchip_node_config_t node_config = {};
|
||||
node_config.io_cfg.tx = TEST_TX_GPIO;
|
||||
node_config.io_cfg.rx = TEST_TX_GPIO; // Using same pin for test without transceiver
|
||||
node_config.io_cfg.quanta_clk_out = GPIO_NUM_NC;
|
||||
node_config.io_cfg.bus_off_indicator = GPIO_NUM_NC;
|
||||
node_config.bit_timing.bitrate = 800000;
|
||||
node_config.tx_queue_depth = TEST_FRAME_NUM;
|
||||
node_config.flags.enable_loopback = true;
|
||||
node_config.flags.enable_self_test = true;
|
||||
|
||||
bool hw_timer = false;
|
||||
#if SOC_TWAI_SUPPORT_TIMESTAMP
|
||||
hw_timer = true;
|
||||
#endif
|
||||
for (uint32_t resolution = 1000; resolution <= 10000000; resolution *= 100) {
|
||||
node_config.timestamp_resolution_hz = resolution;
|
||||
printf("\nTesting resolution %ld\n", resolution);
|
||||
if (((resolution < 2000) && hw_timer) || ((resolution > 1000000) && !hw_timer)) {
|
||||
TEST_ESP_ERR(twai_new_node_onchip(&node_config, &node_hdl), ESP_ERR_INVALID_ARG);
|
||||
continue;
|
||||
}
|
||||
TEST_ESP_OK(twai_new_node_onchip(&node_config, &node_hdl));
|
||||
|
||||
uint8_t rx_buffer[TWAI_FRAME_MAX_LEN] = {0};
|
||||
twai_frame_t rx_frame = {};
|
||||
rx_frame.buffer = rx_buffer;
|
||||
rx_frame.buffer_len = sizeof(rx_buffer);
|
||||
|
||||
twai_event_callbacks_t user_cbs = {};
|
||||
user_cbs.on_rx_done = test_dlc_range_cb;
|
||||
TEST_ESP_OK(twai_node_register_event_callbacks(node_hdl, &user_cbs, &rx_frame));
|
||||
TEST_ESP_OK(twai_node_enable(node_hdl));
|
||||
|
||||
twai_frame_t tx_frame = {};
|
||||
tx_frame.buffer = (uint8_t *)"hi time";
|
||||
tx_frame.buffer_len = strlen((const char *)tx_frame.buffer);
|
||||
uint64_t time_now, time_last = MS_TO_TWAI_TICK(esp_timer_get_time() / 1000, resolution);
|
||||
for (int i = 1; i < 10; i++) {
|
||||
tx_frame.header.id = i;
|
||||
printf("\nwaiting %dms (%ld ticks) ...\n", i * 100, MS_TO_TWAI_TICK(i * 100, resolution));
|
||||
esp_rom_delay_us(i * 100 * 1000);
|
||||
TEST_ESP_OK(twai_node_transmit(node_hdl, &tx_frame, 100));
|
||||
TEST_ESP_OK(twai_node_transmit_wait_all_done(node_hdl, 100));
|
||||
|
||||
time_now = MS_TO_TWAI_TICK(esp_timer_get_time() / 1000, resolution);
|
||||
printf("esp tick now %llu, diff %llu\n", time_now, time_now - rx_frame.header.timestamp);
|
||||
TEST_ASSERT_INT32_WITHIN(MAX(resolution / 100, 5), time_now, rx_frame.header.timestamp);
|
||||
TEST_ASSERT_INT32_WITHIN(MAX(resolution / 100, 5), rx_frame.header.timestamp - time_last, MS_TO_TWAI_TICK(i * 100, resolution));
|
||||
time_last = rx_frame.header.timestamp;
|
||||
}
|
||||
|
||||
printf("\n==============================================\n");
|
||||
printf("Test timestamp still alive during node disable/enable (%ld ticks)\n", MS_TO_TWAI_TICK(1000, resolution));
|
||||
TEST_ESP_OK(twai_node_disable(node_hdl));
|
||||
esp_rom_delay_us(1000 * 1000);
|
||||
TEST_ESP_OK(twai_node_enable(node_hdl));
|
||||
TEST_ESP_OK(twai_node_transmit(node_hdl, &tx_frame, 100));
|
||||
TEST_ESP_OK(twai_node_transmit_wait_all_done(node_hdl, 100));
|
||||
TEST_ASSERT_INT32_WITHIN(MAX(resolution / 100, 5), rx_frame.header.timestamp - time_last, MS_TO_TWAI_TICK(1000, resolution));
|
||||
|
||||
TEST_ESP_OK(twai_node_disable(node_hdl));
|
||||
TEST_ESP_OK(twai_node_delete(node_hdl));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user