Skip to content

Commit

Permalink
Merge branch 'feature/2nd_twai_on_c6' into 'master'
Browse files Browse the repository at this point in the history
twai: support multiple TWAI controller

See merge request espressif/esp-idf!23713
  • Loading branch information
suda-morris committed Oct 13, 2023
2 parents 3620037 + 2ae3d4d commit d4dbacf
Show file tree
Hide file tree
Showing 6 changed files with 625 additions and 251 deletions.
72 changes: 1 addition & 71 deletions components/driver/Kconfig
Expand Up @@ -124,77 +124,7 @@ menu "Driver Configurations"

endmenu # SPI Configuration

menu "TWAI Configuration"
depends on SOC_TWAI_SUPPORTED

config TWAI_ISR_IN_IRAM
bool "Place TWAI ISR function into IRAM"
default n
help
Place the TWAI ISR in to IRAM. This will allow the ISR to avoid
cache misses, and also be able to run whilst the cache is disabled
(such as when writing to SPI Flash).
Note that if this option is enabled:
- Users should also set the ESP_INTR_FLAG_IRAM in the driver
configuration structure when installing the driver (see docs for
specifics).
- Alert logging (i.e., setting of the TWAI_ALERT_AND_LOG flag)
will have no effect.

config TWAI_ERRATA_FIX_BUS_OFF_REC
bool "Add SW workaround for REC change during bus-off"
depends on IDF_TARGET_ESP32
default y
help
When the bus-off condition is reached, the REC should be reset to 0 and frozen (via LOM) by the
driver's ISR. However on the ESP32, there is an edge case where the REC will increase before the
driver's ISR can respond in time (e.g., due to the rapid occurrence of bus errors), thus causing the
REC to be non-zero after bus-off. A non-zero REC can prevent bus-off recovery as the bus-off recovery
condition is that both TEC and REC become 0. Enabling this option will add a workaround in the driver
to forcibly reset REC to zero on reaching bus-off.

config TWAI_ERRATA_FIX_TX_INTR_LOST
bool "Add SW workaround for TX interrupt lost errata"
depends on IDF_TARGET_ESP32
default y
help
On the ESP32, when a transmit interrupt occurs, and interrupt register is read on the same APB clock
cycle, the transmit interrupt could be lost. Enabling this option will add a workaround that checks the
transmit buffer status bit to recover any lost transmit interrupt.

config TWAI_ERRATA_FIX_RX_FRAME_INVALID
bool "Add SW workaround for invalid RX frame errata"
depends on IDF_TARGET_ESP32
default y
help
On the ESP32, when receiving a data or remote frame, if a bus error occurs in the data or CRC field,
the data of the next received frame could be invalid. Enabling this option will add a workaround that
will reset the peripheral on detection of this errata condition. Note that if a frame is transmitted on
the bus whilst the reset is ongoing, the message will not be receive by the peripheral sent on the bus
during the reset, the message will be lost.

config TWAI_ERRATA_FIX_RX_FIFO_CORRUPT
bool "Add SW workaround for RX FIFO corruption errata"
depends on IDF_TARGET_ESP32
default y
help
On the ESP32, when the RX FIFO overruns and the RX message counter maxes out at 64 messages, the entire
RX FIFO is no longer recoverable. Enabling this option will add a workaround that resets the peripheral
on detection of this errata condition. Note that if a frame is being sent on the bus during the reset
bus during the reset, the message will be lost.

config TWAI_ERRATA_FIX_LISTEN_ONLY_DOM
bool "Add SW workaround for listen only transmits dominant bit errata"
depends on IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32C3
default y
help
When in the listen only mode, the TWAI controller must not influence the TWAI bus (i.e., must not send
any dominant bits). However, while in listen only mode on the ESP32/ESP32-S2/ESP32-S3/ESP32-C3, the
TWAI controller will still transmit dominant bits when it detects an error (i.e., as part of an active
error frame). Enabling this option will add a workaround that forces the TWAI controller into an error
passive state on initialization, thus preventing any dominant bits from being sent.

endmenu # TWAI Configuration
orsource "./twai/Kconfig.twai"

menu "Temperature sensor Configuration"
depends on SOC_TEMP_SENSOR_SUPPORTED
Expand Down
37 changes: 25 additions & 12 deletions components/driver/test_apps/twai/main/test_twai_loop_back.c
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
Expand Down Expand Up @@ -86,32 +86,45 @@ TEST_CASE("twai_mode_std_no_ack_25kbps", "[twai-loop-back]")

TEST_CASE("twai_mode_ext_no_ack_250kbps", "[twai-loop-back]")
{
twai_handle_t twai_buses[SOC_TWAI_CONTROLLER_NUM] = {0};
twai_timing_config_t t_config = TWAI_TIMING_CONFIG_250KBITS();
twai_filter_config_t f_config = TWAI_FILTER_CONFIG_ACCEPT_ALL();
// bind the TX and RX to the same GPIO to act like a loopback
twai_general_config_t g_config = TWAI_GENERAL_CONFIG_DEFAULT(0, 0, TWAI_MODE_NO_ACK);
printf("install twai driver\r\n");
TEST_ESP_OK(twai_driver_install(&g_config, &t_config, &f_config));
TEST_ESP_OK(twai_start());

twai_message_t tx_msg = {
.identifier = 0x12345,
.data_length_code = 6,
.data = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66},
.self = true, // Transmitted message will also received by the same node
.extd = true, // Extended Frame Format (29bit ID)
};

printf("install twai driver\r\n");
for (int i = 0; i < SOC_TWAI_CONTROLLER_NUM; i++) {
g_config.controller_id = i;
g_config.tx_io = i;
g_config.rx_io = i;
TEST_ESP_OK(twai_driver_install_v2(&g_config, &t_config, &f_config, &twai_buses[i]));
TEST_ESP_OK(twai_start_v2(twai_buses[i]));
}

printf("transmit message\r\n");
TEST_ESP_OK(twai_transmit(&tx_msg, pdMS_TO_TICKS(1000)));
for (int i = 0; i < SOC_TWAI_CONTROLLER_NUM; i++) {
TEST_ESP_OK(twai_transmit_v2(twai_buses[i], &tx_msg, pdMS_TO_TICKS(1000)));
}

printf("receive message\r\n");
twai_message_t rx_msg;
TEST_ESP_OK(twai_receive(&rx_msg, pdMS_TO_TICKS(1000)));
TEST_ASSERT_TRUE(rx_msg.data_length_code == 6);
for (int i = 0; i < 6; i++) {
TEST_ASSERT_EQUAL(tx_msg.data[i], rx_msg.data[i]);
for (int i = 0; i < SOC_TWAI_CONTROLLER_NUM; i++) {
TEST_ESP_OK(twai_receive_v2(twai_buses[i], &rx_msg, pdMS_TO_TICKS(1000)));
TEST_ASSERT_TRUE(rx_msg.data_length_code == 6);
for (int i = 0; i < 6; i++) {
TEST_ASSERT_EQUAL(tx_msg.data[i], rx_msg.data[i]);
}
}

TEST_ESP_OK(twai_stop());
TEST_ESP_OK(twai_driver_uninstall());
for (int i = 0; i < SOC_TWAI_CONTROLLER_NUM; i++) {
TEST_ESP_OK(twai_stop_v2(twai_buses[i]));
TEST_ESP_OK(twai_driver_uninstall_v2(twai_buses[i]));
}
}
71 changes: 71 additions & 0 deletions components/driver/twai/Kconfig.twai
@@ -0,0 +1,71 @@
menu "TWAI Configuration"
depends on SOC_TWAI_SUPPORTED

config TWAI_ISR_IN_IRAM
bool "Place TWAI ISR function into IRAM"
default n
help
Place the TWAI ISR in to IRAM. This will allow the ISR to avoid
cache misses, and also be able to run whilst the cache is disabled
(such as when writing to SPI Flash).
Note that if this option is enabled:
- Users should also set the ESP_INTR_FLAG_IRAM in the driver
configuration structure when installing the driver (see docs for
specifics).
- Alert logging (i.e., setting of the TWAI_ALERT_AND_LOG flag)
will have no effect.

config TWAI_ERRATA_FIX_BUS_OFF_REC
bool "Add SW workaround for REC change during bus-off"
depends on IDF_TARGET_ESP32
default y
help
When the bus-off condition is reached, the REC should be reset to 0 and frozen (via LOM) by the
driver's ISR. However on the ESP32, there is an edge case where the REC will increase before the
driver's ISR can respond in time (e.g., due to the rapid occurrence of bus errors), thus causing the
REC to be non-zero after bus-off. A non-zero REC can prevent bus-off recovery as the bus-off recovery
condition is that both TEC and REC become 0. Enabling this option will add a workaround in the driver
to forcibly reset REC to zero on reaching bus-off.

config TWAI_ERRATA_FIX_TX_INTR_LOST
bool "Add SW workaround for TX interrupt lost errata"
depends on IDF_TARGET_ESP32
default y
help
On the ESP32, when a transmit interrupt occurs, and interrupt register is read on the same APB clock
cycle, the transmit interrupt could be lost. Enabling this option will add a workaround that checks the
transmit buffer status bit to recover any lost transmit interrupt.

config TWAI_ERRATA_FIX_RX_FRAME_INVALID
bool "Add SW workaround for invalid RX frame errata"
depends on IDF_TARGET_ESP32
default y
help
On the ESP32, when receiving a data or remote frame, if a bus error occurs in the data or CRC field,
the data of the next received frame could be invalid. Enabling this option will add a workaround that
will reset the peripheral on detection of this errata condition. Note that if a frame is transmitted on
the bus whilst the reset is ongoing, the message will not be receive by the peripheral sent on the bus
during the reset, the message will be lost.

config TWAI_ERRATA_FIX_RX_FIFO_CORRUPT
bool "Add SW workaround for RX FIFO corruption errata"
depends on IDF_TARGET_ESP32
default y
help
On the ESP32, when the RX FIFO overruns and the RX message counter maxes out at 64 messages, the entire
RX FIFO is no longer recoverable. Enabling this option will add a workaround that resets the peripheral
on detection of this errata condition. Note that if a frame is being sent on the bus during the reset
bus during the reset, the message will be lost.

config TWAI_ERRATA_FIX_LISTEN_ONLY_DOM
bool "Add SW workaround for listen only transmits dominant bit errata"
depends on IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32C3
default y
help
When in the listen only mode, the TWAI controller must not influence the TWAI bus (i.e., must not send
any dominant bits). However, while in listen only mode on the ESP32/ESP32-S2/ESP32-S3/ESP32-C3, the
TWAI controller will still transmit dominant bits when it detects an error (i.e., as part of an active
error frame). Enabling this option will add a workaround that forces the TWAI controller into an error
passive state on initialization, thus preventing any dominant bits from being sent.

endmenu # TWAI Configuration

0 comments on commit d4dbacf

Please sign in to comment.