mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
feat(twai): support legacy twai(can) driver for esp32p4
This commit is contained in:
parent
4ea0538a88
commit
d9d6f5a17a
@ -1,5 +1,5 @@
|
|||||||
| Supported Targets | ESP32 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S2 | ESP32-S3 |
|
| Supported Targets | ESP32 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
|
||||||
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- |
|
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- |
|
||||||
|
|
||||||
# Enable Socket CAN Device with bitrate 250Kbps
|
# Enable Socket CAN Device with bitrate 250Kbps
|
||||||
|
|
||||||
|
@ -1,38 +1,25 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "unity.h"
|
#include "unity.h"
|
||||||
#include "unity_test_runner.h"
|
#include "unity_test_utils.h"
|
||||||
#include "esp_heap_caps.h"
|
#include "esp_heap_caps.h"
|
||||||
|
|
||||||
// Some resources are lazy allocated in the TWAI driver, the threshold is left for that case
|
// Some resources are lazy allocated in the TWAI driver, the threshold is left for that case
|
||||||
#define TEST_MEMORY_LEAK_THRESHOLD (-200)
|
#define TEST_MEMORY_LEAK_THRESHOLD (200)
|
||||||
|
|
||||||
static size_t before_free_8bit;
|
|
||||||
static size_t before_free_32bit;
|
|
||||||
|
|
||||||
static void check_leak(size_t before_free, size_t after_free, const char *type)
|
|
||||||
{
|
|
||||||
ssize_t delta = after_free - before_free;
|
|
||||||
printf("MALLOC_CAP_%s: Before %u bytes free, After %u bytes free (delta %d)\n", type, before_free, after_free, delta);
|
|
||||||
TEST_ASSERT_MESSAGE(delta >= TEST_MEMORY_LEAK_THRESHOLD, "memory leak");
|
|
||||||
}
|
|
||||||
|
|
||||||
void setUp(void)
|
void setUp(void)
|
||||||
{
|
{
|
||||||
before_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT);
|
unity_utils_record_free_mem();
|
||||||
before_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void tearDown(void)
|
void tearDown(void)
|
||||||
{
|
{
|
||||||
size_t after_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT);
|
esp_reent_cleanup(); //clean up some of the newlib's lazy allocations
|
||||||
size_t after_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT);
|
unity_utils_evaluate_leaks_direct(TEST_MEMORY_LEAK_THRESHOLD);
|
||||||
check_leak(before_free_8bit, after_free_8bit, "8BIT");
|
|
||||||
check_leak(before_free_32bit, after_free_32bit, "32BIT");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void app_main(void)
|
void app_main(void)
|
||||||
@ -42,10 +29,10 @@ void app_main(void)
|
|||||||
// | | \ \ /\ / / _ \ | | | |/ _ \/ __| __|
|
// | | \ \ /\ / / _ \ | | | |/ _ \/ __| __|
|
||||||
// | | \ V V / ___ \ | | | | __/\__ \ |_
|
// | | \ V V / ___ \ | | | | __/\__ \ |_
|
||||||
// |_| \_/\_/_/ \_\___| |_|\___||___/\__|
|
// |_| \_/\_/_/ \_\___| |_|\___||___/\__|
|
||||||
printf(" _______ ___ ___ _____ _\r\n");
|
printf(" _______ ___ ___ _____ _\n");
|
||||||
printf("|_ _\\ \\ / / \\ |_ _| |_ _|__ ___| |_\r\n");
|
printf("|_ _\\ \\ / / \\ |_ _| |_ _|__ ___| |_\n");
|
||||||
printf(" | | \\ \\ /\\ / / _ \\ | | | |/ _ \\/ __| __|\r\n");
|
printf(" | | \\ \\ /\\ / / _ \\ | | | |/ _ \\/ __| __|\n");
|
||||||
printf(" | | \\ V V / ___ \\ | | | | __/\\__ \\ |_\r\n");
|
printf(" | | \\ V V / ___ \\ | | | | __/\\__ \\ |_\n");
|
||||||
printf(" |_| \\_/\\_/_/ \\_\\___| |_|\\___||___/\\__|\r\n");
|
printf(" |_| \\_/\\_/_/ \\_\\___| |_|\\___||___/\\__|\n");
|
||||||
unity_run_menu();
|
unity_run_menu();
|
||||||
}
|
}
|
||||||
|
@ -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
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@ -14,7 +14,7 @@
|
|||||||
#include "unity_test_utils.h"
|
#include "unity_test_utils.h"
|
||||||
#include "driver/twai.h"
|
#include "driver/twai.h"
|
||||||
#include "soc/soc_caps.h"
|
#include "soc/soc_caps.h"
|
||||||
#include "esp_attr.h"
|
#include "esp_log.h"
|
||||||
|
|
||||||
#if CONFIG_TWAI_ISR_IN_IRAM
|
#if CONFIG_TWAI_ISR_IN_IRAM
|
||||||
static void IRAM_ATTR test_delay_post_cache_disable(void *args)
|
static void IRAM_ATTR test_delay_post_cache_disable(void *args)
|
||||||
@ -37,7 +37,7 @@ TEST_CASE("twai_listen_only", "[twai]")
|
|||||||
TEST_ESP_OK(twai_start());
|
TEST_ESP_OK(twai_start());
|
||||||
|
|
||||||
#if CONFIG_TWAI_ISR_IN_IRAM
|
#if CONFIG_TWAI_ISR_IN_IRAM
|
||||||
printf("disable flash cache and check if we can still receive the frame\r\n");
|
printf("disable flash cache and check if we can still receive the frame\n");
|
||||||
for (int i = 0; i < 100; i++) {
|
for (int i = 0; i < 100; i++) {
|
||||||
unity_utils_run_cache_disable_stub(test_delay_post_cache_disable, NULL);
|
unity_utils_run_cache_disable_stub(test_delay_post_cache_disable, NULL);
|
||||||
}
|
}
|
||||||
@ -48,9 +48,8 @@ TEST_CASE("twai_listen_only", "[twai]")
|
|||||||
TEST_ESP_OK(twai_receive(&rx_msg, portMAX_DELAY));
|
TEST_ESP_OK(twai_receive(&rx_msg, portMAX_DELAY));
|
||||||
|
|
||||||
TEST_ASSERT_EQUAL(0x123, rx_msg.identifier);
|
TEST_ASSERT_EQUAL(0x123, rx_msg.identifier);
|
||||||
for (int i = 0; i < rx_msg.data_length_code; i++) {
|
ESP_LOG_BUFFER_HEX("rx", rx_msg.data, rx_msg.data_length_code);
|
||||||
TEST_ASSERT_EQUAL_HEX8(expected_data[i], rx_msg.data[i]);
|
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_data, rx_msg.data, rx_msg.data_length_code);
|
||||||
}
|
|
||||||
|
|
||||||
TEST_ESP_OK(twai_stop());
|
TEST_ESP_OK(twai_stop());
|
||||||
TEST_ESP_OK(twai_driver_uninstall());
|
TEST_ESP_OK(twai_driver_uninstall());
|
||||||
@ -58,11 +57,13 @@ TEST_CASE("twai_listen_only", "[twai]")
|
|||||||
|
|
||||||
TEST_CASE("twai_remote_request", "[twai]")
|
TEST_CASE("twai_remote_request", "[twai]")
|
||||||
{
|
{
|
||||||
|
twai_handle_t bus_handle;
|
||||||
twai_timing_config_t t_config = TWAI_TIMING_CONFIG_250KBITS();
|
twai_timing_config_t t_config = TWAI_TIMING_CONFIG_250KBITS();
|
||||||
twai_filter_config_t f_config = TWAI_FILTER_CONFIG_ACCEPT_ALL();
|
twai_filter_config_t f_config = TWAI_FILTER_CONFIG_ACCEPT_ALL();
|
||||||
twai_general_config_t g_config = TWAI_GENERAL_CONFIG_DEFAULT(0, 2, TWAI_MODE_NORMAL);
|
twai_general_config_t g_config = TWAI_GENERAL_CONFIG_DEFAULT(0, 2, TWAI_MODE_NORMAL);
|
||||||
TEST_ESP_OK(twai_driver_install(&g_config, &t_config, &f_config));
|
g_config.controller_id = 2;
|
||||||
TEST_ESP_OK(twai_start());
|
TEST_ESP_OK(twai_driver_install_v2(&g_config, &t_config, &f_config, &bus_handle));
|
||||||
|
TEST_ESP_OK(twai_start_v2(bus_handle));
|
||||||
|
|
||||||
twai_message_t req_msg = {
|
twai_message_t req_msg = {
|
||||||
.identifier = 0x6688,
|
.identifier = 0x6688,
|
||||||
@ -70,16 +71,17 @@ TEST_CASE("twai_remote_request", "[twai]")
|
|||||||
.rtr = true, // remote request
|
.rtr = true, // remote request
|
||||||
.extd = true,// extended ID
|
.extd = true,// extended ID
|
||||||
};
|
};
|
||||||
TEST_ESP_OK(twai_transmit(&req_msg, portMAX_DELAY));
|
TEST_ESP_OK(twai_transmit_v2(bus_handle, &req_msg, portMAX_DELAY));
|
||||||
|
ESP_LOGI("TWAI", "send remote frame");
|
||||||
|
|
||||||
uint8_t expected_data[8] = {0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80};
|
uint8_t expected_data[8] = {0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80};
|
||||||
twai_message_t res_msg;
|
twai_message_t res_msg;
|
||||||
TEST_ESP_OK(twai_receive(&res_msg, portMAX_DELAY));
|
TEST_ESP_OK(twai_receive_v2(bus_handle, &res_msg, portMAX_DELAY));
|
||||||
|
ESP_LOGI("TWAI", "receive with id %lx\n", res_msg.identifier);
|
||||||
TEST_ASSERT_EQUAL(0x6688, res_msg.identifier);
|
TEST_ASSERT_EQUAL(0x6688, res_msg.identifier);
|
||||||
for (int i = 0; i < 8; i++) {
|
ESP_LOG_BUFFER_HEX("rx", res_msg.data, res_msg.data_length_code);
|
||||||
TEST_ASSERT_EQUAL_HEX8(expected_data[i], res_msg.data[i]);
|
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_data, res_msg.data, res_msg.data_length_code);
|
||||||
}
|
|
||||||
|
|
||||||
TEST_ESP_OK(twai_stop());
|
TEST_ESP_OK(twai_stop_v2(bus_handle));
|
||||||
TEST_ESP_OK(twai_driver_uninstall());
|
TEST_ESP_OK(twai_driver_uninstall_v2(bus_handle));
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
# SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
|
||||||
# SPDX-License-Identifier: CC0-1.0
|
# SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
@ -15,6 +15,7 @@ from pytest_embedded import Dut
|
|||||||
@pytest.mark.esp32h2
|
@pytest.mark.esp32h2
|
||||||
@pytest.mark.esp32s2
|
@pytest.mark.esp32s2
|
||||||
@pytest.mark.esp32s3
|
@pytest.mark.esp32s3
|
||||||
|
@pytest.mark.esp32p4
|
||||||
@pytest.mark.generic
|
@pytest.mark.generic
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
'config',
|
'config',
|
||||||
@ -41,6 +42,7 @@ def fixture_create_socket_can() -> Bus:
|
|||||||
@pytest.mark.esp32h2
|
@pytest.mark.esp32h2
|
||||||
@pytest.mark.esp32s2
|
@pytest.mark.esp32s2
|
||||||
@pytest.mark.esp32s3
|
@pytest.mark.esp32s3
|
||||||
|
@pytest.mark.esp32p4
|
||||||
@pytest.mark.skip(reason='Runner not set up yet')
|
@pytest.mark.skip(reason='Runner not set up yet')
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
'config',
|
'config',
|
||||||
@ -73,6 +75,7 @@ def test_twai_listen_only(dut: Dut, socket_can: Bus) -> None:
|
|||||||
@pytest.mark.esp32h2
|
@pytest.mark.esp32h2
|
||||||
@pytest.mark.esp32s2
|
@pytest.mark.esp32s2
|
||||||
@pytest.mark.esp32s3
|
@pytest.mark.esp32s3
|
||||||
|
@pytest.mark.esp32p4
|
||||||
@pytest.mark.skip(reason='Runner not set up yet')
|
@pytest.mark.skip(reason='Runner not set up yet')
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
'config',
|
'config',
|
||||||
@ -101,5 +104,6 @@ def test_twai_remote_request(dut: Dut, socket_can: Bus) -> None:
|
|||||||
data=[0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80],
|
data=[0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80],
|
||||||
)
|
)
|
||||||
socket_can.send(reply, timeout=0.2)
|
socket_can.send(reply, timeout=0.2)
|
||||||
|
print('send', reply)
|
||||||
|
|
||||||
dut.expect_unity_test_output()
|
dut.expect_unity_test_output()
|
||||||
|
@ -58,6 +58,12 @@
|
|||||||
#define TWAI_RCC_ATOMIC()
|
#define TWAI_RCC_ATOMIC()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if SOC_PERIPH_CLK_CTRL_SHARED
|
||||||
|
#define TWAI_PERI_ATOMIC() PERIPH_RCC_ATOMIC()
|
||||||
|
#else
|
||||||
|
#define TWAI_PERI_ATOMIC()
|
||||||
|
#endif
|
||||||
|
|
||||||
/* ------------------ Typedefs, structures, and variables ------------------- */
|
/* ------------------ Typedefs, structures, and variables ------------------- */
|
||||||
|
|
||||||
//Control structure for TWAI driver
|
//Control structure for TWAI driver
|
||||||
@ -453,6 +459,11 @@ esp_err_t twai_driver_install_v2(const twai_general_config_t *g_config, const tw
|
|||||||
twai_ll_enable_bus_clock(controller_id, true);
|
twai_ll_enable_bus_clock(controller_id, true);
|
||||||
twai_ll_reset_register(controller_id);
|
twai_ll_reset_register(controller_id);
|
||||||
}
|
}
|
||||||
|
TWAI_PERI_ATOMIC() {
|
||||||
|
//Enable functional clock
|
||||||
|
twai_ll_set_clock_source(p_twai_obj->controller_id, clk_src);
|
||||||
|
twai_ll_enable_clock(p_twai_obj->controller_id, true);
|
||||||
|
}
|
||||||
|
|
||||||
//Initialize TWAI HAL layer
|
//Initialize TWAI HAL layer
|
||||||
twai_hal_config_t hal_config = {
|
twai_hal_config_t hal_config = {
|
||||||
@ -514,6 +525,9 @@ esp_err_t twai_driver_uninstall_v2(twai_handle_t handle)
|
|||||||
|
|
||||||
//Clear registers by reading
|
//Clear registers by reading
|
||||||
twai_hal_deinit(&p_twai_obj->hal);
|
twai_hal_deinit(&p_twai_obj->hal);
|
||||||
|
TWAI_PERI_ATOMIC() {
|
||||||
|
twai_ll_enable_clock(controller_id, false);
|
||||||
|
}
|
||||||
TWAI_RCC_ATOMIC() {
|
TWAI_RCC_ATOMIC() {
|
||||||
twai_ll_enable_bus_clock(controller_id, false);
|
twai_ll_enable_bus_clock(controller_id, false);
|
||||||
}
|
}
|
||||||
|
@ -194,25 +194,25 @@ static inline void twai_ll_reset_register(int group_id)
|
|||||||
/**
|
/**
|
||||||
* @brief Enable TWAI module clock
|
* @brief Enable TWAI module clock
|
||||||
*
|
*
|
||||||
* @param hw Start address of the TWAI registers
|
* @param group_id Group ID
|
||||||
* @param en true to enable, false to disable
|
* @param en true to enable, false to disable
|
||||||
*/
|
*/
|
||||||
__attribute__((always_inline))
|
__attribute__((always_inline))
|
||||||
static inline void twai_ll_enable_clock(twai_dev_t *hw, bool en)
|
static inline void twai_ll_enable_clock(int group_id, bool en)
|
||||||
{
|
{
|
||||||
(void)hw;
|
(void)group_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Set clock source for TWAI module
|
* @brief Set clock source for TWAI module
|
||||||
*
|
*
|
||||||
* @param hw Start address of the TWAI registers
|
* @param group_id Group ID
|
||||||
* @param clk_src Clock source
|
* @param clk_src Clock source
|
||||||
*/
|
*/
|
||||||
__attribute__((always_inline))
|
__attribute__((always_inline))
|
||||||
static inline void twai_ll_set_clock_source(twai_dev_t *hw, twai_clock_source_t clk_src)
|
static inline void twai_ll_set_clock_source(int group_id, twai_clock_source_t clk_src)
|
||||||
{
|
{
|
||||||
(void)hw;
|
(void)group_id;
|
||||||
HAL_ASSERT(clk_src == TWAI_CLK_SRC_APB);
|
HAL_ASSERT(clk_src == TWAI_CLK_SRC_APB);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,25 +124,25 @@ static inline void twai_ll_reset_register(int group_id)
|
|||||||
/**
|
/**
|
||||||
* @brief Enable TWAI module clock
|
* @brief Enable TWAI module clock
|
||||||
*
|
*
|
||||||
* @param hw Start address of the TWAI registers
|
* @param group_id Group ID
|
||||||
* @param en true to enable, false to disable
|
* @param en true to enable, false to disable
|
||||||
*/
|
*/
|
||||||
__attribute__((always_inline))
|
__attribute__((always_inline))
|
||||||
static inline void twai_ll_enable_clock(twai_dev_t *hw, bool en)
|
static inline void twai_ll_enable_clock(int group_id, bool en)
|
||||||
{
|
{
|
||||||
(void)hw;
|
(void)group_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Set clock source for TWAI module
|
* @brief Set clock source for TWAI module
|
||||||
*
|
*
|
||||||
* @param hw Start address of the TWAI registers
|
* @param group_id Group ID
|
||||||
* @param clk_src Clock source
|
* @param clk_src Clock source
|
||||||
*/
|
*/
|
||||||
__attribute__((always_inline))
|
__attribute__((always_inline))
|
||||||
static inline void twai_ll_set_clock_source(twai_dev_t *hw, twai_clock_source_t clk_src)
|
static inline void twai_ll_set_clock_source(int group_id, twai_clock_source_t clk_src)
|
||||||
{
|
{
|
||||||
(void)hw;
|
(void)group_id;
|
||||||
HAL_ASSERT(clk_src == TWAI_CLK_SRC_APB);
|
HAL_ASSERT(clk_src == TWAI_CLK_SRC_APB);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,13 +123,13 @@ static inline void twai_ll_reset_register(int group_id)
|
|||||||
/**
|
/**
|
||||||
* @brief Enable TWAI module clock
|
* @brief Enable TWAI module clock
|
||||||
*
|
*
|
||||||
* @param hw Start address of the TWAI registers
|
* @param group_id Group ID
|
||||||
* @param en true to enable, false to disable
|
* @param en true to enable, false to disable
|
||||||
*/
|
*/
|
||||||
__attribute__((always_inline))
|
__attribute__((always_inline))
|
||||||
static inline void twai_ll_enable_clock(twai_dev_t *hw, bool en)
|
static inline void twai_ll_enable_clock(int group_id, bool en)
|
||||||
{
|
{
|
||||||
if (hw == &TWAI0) {
|
if (group_id == 0) {
|
||||||
PCR.twai0_func_clk_conf.twai0_func_clk_en = en;
|
PCR.twai0_func_clk_conf.twai0_func_clk_en = en;
|
||||||
} else {
|
} else {
|
||||||
PCR.twai1_func_clk_conf.twai1_func_clk_en = en;
|
PCR.twai1_func_clk_conf.twai1_func_clk_en = en;
|
||||||
@ -139,11 +139,11 @@ static inline void twai_ll_enable_clock(twai_dev_t *hw, bool en)
|
|||||||
/**
|
/**
|
||||||
* @brief Set clock source for TWAI module
|
* @brief Set clock source for TWAI module
|
||||||
*
|
*
|
||||||
* @param hw Start address of the TWAI registers
|
* @param group_id Group ID
|
||||||
* @param clk_src Clock source
|
* @param clk_src Clock source
|
||||||
*/
|
*/
|
||||||
__attribute__((always_inline))
|
__attribute__((always_inline))
|
||||||
static inline void twai_ll_set_clock_source(twai_dev_t *hw, twai_clock_source_t clk_src)
|
static inline void twai_ll_set_clock_source(int group_id, twai_clock_source_t clk_src)
|
||||||
{
|
{
|
||||||
uint32_t clk_id = 0;
|
uint32_t clk_id = 0;
|
||||||
bool valid = true;
|
bool valid = true;
|
||||||
@ -158,7 +158,7 @@ static inline void twai_ll_set_clock_source(twai_dev_t *hw, twai_clock_source_t
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (valid) {
|
if (valid) {
|
||||||
if (hw == &TWAI0) {
|
if (group_id == 0) {
|
||||||
PCR.twai0_func_clk_conf.twai0_func_clk_sel = clk_id;
|
PCR.twai0_func_clk_conf.twai0_func_clk_sel = clk_id;
|
||||||
} else {
|
} else {
|
||||||
PCR.twai1_func_clk_conf.twai1_func_clk_sel = clk_id;
|
PCR.twai1_func_clk_conf.twai1_func_clk_sel = clk_id;
|
||||||
|
@ -116,24 +116,26 @@ static inline void twai_ll_reset_register(int group_id)
|
|||||||
/**
|
/**
|
||||||
* @brief Enable TWAI module clock
|
* @brief Enable TWAI module clock
|
||||||
*
|
*
|
||||||
* @param hw Start address of the TWAI registers
|
* @param group_id Group ID
|
||||||
* @param en true to enable, false to disable
|
* @param en true to enable, false to disable
|
||||||
*/
|
*/
|
||||||
__attribute__((always_inline))
|
__attribute__((always_inline))
|
||||||
static inline void twai_ll_enable_clock(twai_dev_t *hw, bool en)
|
static inline void twai_ll_enable_clock(int group_id, bool en)
|
||||||
{
|
{
|
||||||
|
(void)group_id;
|
||||||
PCR.twai0_func_clk_conf.twai0_func_clk_en = en;
|
PCR.twai0_func_clk_conf.twai0_func_clk_en = en;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Set clock source for TWAI module
|
* @brief Set clock source for TWAI module
|
||||||
*
|
*
|
||||||
* @param hw Start address of the TWAI registers
|
* @param group_id Group ID
|
||||||
* @param clk_src Clock source
|
* @param clk_src Clock source
|
||||||
*/
|
*/
|
||||||
__attribute__((always_inline))
|
__attribute__((always_inline))
|
||||||
static inline void twai_ll_set_clock_source(twai_dev_t *hw, twai_clock_source_t clk_src)
|
static inline void twai_ll_set_clock_source(int group_id, twai_clock_source_t clk_src)
|
||||||
{
|
{
|
||||||
|
(void)group_id;
|
||||||
switch (clk_src) {
|
switch (clk_src) {
|
||||||
case TWAI_CLK_SRC_DEFAULT:
|
case TWAI_CLK_SRC_DEFAULT:
|
||||||
PCR.twai0_func_clk_conf.twai0_func_clk_sel = 0;
|
PCR.twai0_func_clk_conf.twai0_func_clk_sel = 0;
|
||||||
|
@ -38,12 +38,6 @@ static inline uint32_t periph_ll_get_clk_en_mask(periph_module_t periph)
|
|||||||
return HP_SYS_CLKRST_REG_I2C1_APB_CLK_EN;
|
return HP_SYS_CLKRST_REG_I2C1_APB_CLK_EN;
|
||||||
case PERIPH_LCD_MODULE:
|
case PERIPH_LCD_MODULE:
|
||||||
return HP_SYS_CLKRST_REG_LCD_CLK_EN;
|
return HP_SYS_CLKRST_REG_LCD_CLK_EN;
|
||||||
case PERIPH_TWAI0_MODULE:
|
|
||||||
return HP_SYS_CLKRST_REG_TWAI0_CLK_EN;
|
|
||||||
case PERIPH_TWAI1_MODULE:
|
|
||||||
return HP_SYS_CLKRST_REG_TWAI1_CLK_EN;
|
|
||||||
case PERIPH_TWAI2_MODULE:
|
|
||||||
return HP_SYS_CLKRST_REG_TWAI2_CLK_EN;
|
|
||||||
case PERIPH_I3C_MODULE:
|
case PERIPH_I3C_MODULE:
|
||||||
return HP_SYS_CLKRST_REG_I3C_MST_CLK_EN;
|
return HP_SYS_CLKRST_REG_I3C_MST_CLK_EN;
|
||||||
case PERIPH_CAM_MODULE:
|
case PERIPH_CAM_MODULE:
|
||||||
@ -109,12 +103,6 @@ static inline uint32_t periph_ll_get_rst_en_mask(periph_module_t periph, bool en
|
|||||||
return HP_SYS_CLKRST_REG_RST_EN_I2C0;
|
return HP_SYS_CLKRST_REG_RST_EN_I2C0;
|
||||||
case PERIPH_I2C1_MODULE:
|
case PERIPH_I2C1_MODULE:
|
||||||
return HP_SYS_CLKRST_REG_RST_EN_I2C1;
|
return HP_SYS_CLKRST_REG_RST_EN_I2C1;
|
||||||
case PERIPH_TWAI0_MODULE:
|
|
||||||
return HP_SYS_CLKRST_REG_RST_EN_CAN0;
|
|
||||||
case PERIPH_TWAI1_MODULE:
|
|
||||||
return HP_SYS_CLKRST_REG_RST_EN_CAN1;
|
|
||||||
case PERIPH_TWAI2_MODULE:
|
|
||||||
return HP_SYS_CLKRST_REG_RST_EN_CAN2;
|
|
||||||
case PERIPH_LCD_MODULE:
|
case PERIPH_LCD_MODULE:
|
||||||
return HP_SYS_CLKRST_REG_RST_EN_LCDCAM;
|
return HP_SYS_CLKRST_REG_RST_EN_LCDCAM;
|
||||||
case PERIPH_SARADC_MODULE:
|
case PERIPH_SARADC_MODULE:
|
||||||
@ -174,9 +162,6 @@ static inline uint32_t periph_ll_get_clk_en_reg(periph_module_t periph)
|
|||||||
return HP_SYS_CLKRST_SOC_CLK_CTRL2_REG;
|
return HP_SYS_CLKRST_SOC_CLK_CTRL2_REG;
|
||||||
case PERIPH_LCD_MODULE:
|
case PERIPH_LCD_MODULE:
|
||||||
return HP_SYS_CLKRST_PERI_CLK_CTRL110_REG;
|
return HP_SYS_CLKRST_PERI_CLK_CTRL110_REG;
|
||||||
case PERIPH_TWAI0_MODULE:
|
|
||||||
case PERIPH_TWAI1_MODULE:
|
|
||||||
case PERIPH_TWAI2_MODULE:
|
|
||||||
return HP_SYS_CLKRST_PERI_CLK_CTRL116_REG;
|
return HP_SYS_CLKRST_PERI_CLK_CTRL116_REG;
|
||||||
case PERIPH_I3C_MODULE:
|
case PERIPH_I3C_MODULE:
|
||||||
case PERIPH_CAM_MODULE:
|
case PERIPH_CAM_MODULE:
|
||||||
@ -221,9 +206,6 @@ static inline uint32_t periph_ll_get_rst_en_reg(periph_module_t periph)
|
|||||||
case PERIPH_I2C0_MODULE:
|
case PERIPH_I2C0_MODULE:
|
||||||
case PERIPH_I2C1_MODULE:
|
case PERIPH_I2C1_MODULE:
|
||||||
return HP_SYS_CLKRST_HP_RST_EN1_REG;
|
return HP_SYS_CLKRST_HP_RST_EN1_REG;
|
||||||
case PERIPH_TWAI0_MODULE:
|
|
||||||
case PERIPH_TWAI1_MODULE:
|
|
||||||
case PERIPH_TWAI2_MODULE:
|
|
||||||
case PERIPH_CAM_MODULE:
|
case PERIPH_CAM_MODULE:
|
||||||
case PERIPH_SARADC_MODULE:
|
case PERIPH_SARADC_MODULE:
|
||||||
case PERIPH_AES_MODULE:
|
case PERIPH_AES_MODULE:
|
||||||
|
816
components/hal/esp32p4/include/hal/twai_ll.h
Normal file
816
components/hal/esp32p4/include/hal/twai_ll.h
Normal file
@ -0,0 +1,816 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* NOTICE
|
||||||
|
* The ll is not public api, don't use in application code.
|
||||||
|
* See readme.md in hal/include/hal/readme.md
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
// The Lowlevel layer for TWAI
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "esp_assert.h"
|
||||||
|
#include "hal/misc.h"
|
||||||
|
#include "hal/assert.h"
|
||||||
|
#include "hal/twai_types.h"
|
||||||
|
#include "soc/twai_struct.h"
|
||||||
|
#include "soc/hp_sys_clkrst_struct.h"
|
||||||
|
|
||||||
|
#define TWAI_LL_GET_HW(controller_id) ((controller_id == 0) ? (&TWAI0) : \
|
||||||
|
(controller_id == 1) ? (&TWAI1) : \
|
||||||
|
(&TWAI2))
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ------------------------- Defines and Typedefs --------------------------- */
|
||||||
|
|
||||||
|
#define TWAI_LL_STATUS_RBS (0x1 << 0) //Receive Buffer Status
|
||||||
|
#define TWAI_LL_STATUS_DOS (0x1 << 1) //Data Overrun Status
|
||||||
|
#define TWAI_LL_STATUS_TBS (0x1 << 2) //Transmit Buffer Status
|
||||||
|
#define TWAI_LL_STATUS_TCS (0x1 << 3) //Transmission Complete Status
|
||||||
|
#define TWAI_LL_STATUS_RS (0x1 << 4) //Receive Status
|
||||||
|
#define TWAI_LL_STATUS_TS (0x1 << 5) //Transmit Status
|
||||||
|
#define TWAI_LL_STATUS_ES (0x1 << 6) //Error Status
|
||||||
|
#define TWAI_LL_STATUS_BS (0x1 << 7) //Bus Status
|
||||||
|
#define TWAI_LL_STATUS_MS (0x1 << 8) //Miss Status
|
||||||
|
|
||||||
|
#define TWAI_LL_INTR_RI (0x1 << 0) //Receive Interrupt
|
||||||
|
#define TWAI_LL_INTR_TI (0x1 << 1) //Transmit Interrupt
|
||||||
|
#define TWAI_LL_INTR_EI (0x1 << 2) //Error Interrupt
|
||||||
|
//Data overrun interrupt not supported in SW due to HW peculiarities
|
||||||
|
#define TWAI_LL_INTR_EPI (0x1 << 5) //Error Passive Interrupt
|
||||||
|
#define TWAI_LL_INTR_ALI (0x1 << 6) //Arbitration Lost Interrupt
|
||||||
|
#define TWAI_LL_INTR_BEI (0x1 << 7) //Bus Error Interrupt
|
||||||
|
#define TWAI_LL_INTR_BISI (0x1 << 8) //Bus Idle Status Interrupt
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The following frame structure has an NEARLY identical bit field layout to
|
||||||
|
* each byte of the TX buffer. This allows for formatting and parsing frames to
|
||||||
|
* be done outside of time critical regions (i.e., ISRs). All the ISR needs to
|
||||||
|
* do is to copy byte by byte to/from the TX/RX buffer. The two reserved bits in
|
||||||
|
* TX buffer are used in the frame structure to store the self_reception and
|
||||||
|
* single_shot flags which in turn indicate the type of transmission to execute.
|
||||||
|
*/
|
||||||
|
typedef union {
|
||||||
|
struct {
|
||||||
|
struct {
|
||||||
|
uint8_t dlc: 4; //Data length code (0 to 8) of the frame
|
||||||
|
uint8_t self_reception: 1; //This frame should be transmitted using self reception command
|
||||||
|
uint8_t single_shot: 1; //This frame should be transmitted using single shot command
|
||||||
|
uint8_t rtr: 1; //This frame is a remote transmission request
|
||||||
|
uint8_t frame_format: 1; //Format of the frame (1 = extended, 0 = standard)
|
||||||
|
};
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
uint8_t id[2]; //11 bit standard frame identifier
|
||||||
|
uint8_t data[8]; //Data bytes (0 to 8)
|
||||||
|
uint8_t reserved8[2];
|
||||||
|
} standard;
|
||||||
|
struct {
|
||||||
|
uint8_t id[4]; //29 bit extended frame identifier
|
||||||
|
uint8_t data[8]; //Data bytes (0 to 8)
|
||||||
|
} extended;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
uint8_t bytes[13];
|
||||||
|
} __attribute__((packed)) twai_ll_frame_buffer_t;
|
||||||
|
|
||||||
|
ESP_STATIC_ASSERT(sizeof(twai_ll_frame_buffer_t) == 13, "TX/RX buffer type should be 13 bytes");
|
||||||
|
|
||||||
|
/* ---------------------------- Reset and Clock Control ------------------------------ */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Enable the bus clock for twai module
|
||||||
|
*
|
||||||
|
* @param group_id Group ID
|
||||||
|
* @param enable true to enable, false to disable
|
||||||
|
*/
|
||||||
|
static inline void twai_ll_enable_bus_clock(int group_id, bool enable)
|
||||||
|
{
|
||||||
|
switch (group_id)
|
||||||
|
{
|
||||||
|
case 0: HP_SYS_CLKRST.soc_clk_ctrl2.reg_twai0_apb_clk_en = enable; break;
|
||||||
|
case 1: HP_SYS_CLKRST.soc_clk_ctrl2.reg_twai1_apb_clk_en = enable; break;
|
||||||
|
case 2: HP_SYS_CLKRST.soc_clk_ctrl2.reg_twai2_apb_clk_en = enable; break;
|
||||||
|
default: HAL_ASSERT(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// use a macro to wrap the function, force the caller to use it in a critical section
|
||||||
|
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
|
||||||
|
#define twai_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; twai_ll_enable_bus_clock(__VA_ARGS__)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reset the twai module
|
||||||
|
*
|
||||||
|
* @param group_id Group ID
|
||||||
|
*/
|
||||||
|
static inline void twai_ll_reset_register(int group_id)
|
||||||
|
{
|
||||||
|
switch (group_id)
|
||||||
|
{
|
||||||
|
case 0: HP_SYS_CLKRST.hp_rst_en1.reg_rst_en_twai0 = 1;
|
||||||
|
HP_SYS_CLKRST.hp_rst_en1.reg_rst_en_twai0 = 0;
|
||||||
|
break;
|
||||||
|
case 1: HP_SYS_CLKRST.hp_rst_en1.reg_rst_en_twai1 = 1;
|
||||||
|
HP_SYS_CLKRST.hp_rst_en1.reg_rst_en_twai1 = 0;
|
||||||
|
break;
|
||||||
|
case 2: HP_SYS_CLKRST.hp_rst_en1.reg_rst_en_twai2 = 1;
|
||||||
|
HP_SYS_CLKRST.hp_rst_en1.reg_rst_en_twai2 = 0;
|
||||||
|
break;
|
||||||
|
default: HAL_ASSERT(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// use a macro to wrap the function, force the caller to use it in a critical section
|
||||||
|
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
|
||||||
|
#define twai_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; twai_ll_reset_register(__VA_ARGS__)
|
||||||
|
|
||||||
|
/* ---------------------------- Peripheral Control Register ----------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Enable TWAI module clock
|
||||||
|
*
|
||||||
|
* @param group_id Group ID
|
||||||
|
* @param en true to enable, false to disable
|
||||||
|
*/
|
||||||
|
__attribute__((always_inline))
|
||||||
|
static inline void twai_ll_enable_clock(int group_id, bool en)
|
||||||
|
{
|
||||||
|
switch (group_id) {
|
||||||
|
case 0: HP_SYS_CLKRST.peri_clk_ctrl115.reg_twai0_clk_en = en; break;
|
||||||
|
case 1: HP_SYS_CLKRST.peri_clk_ctrl115.reg_twai1_clk_en = en; break;
|
||||||
|
case 2: HP_SYS_CLKRST.peri_clk_ctrl115.reg_twai2_clk_en = en; break;
|
||||||
|
default: HAL_ASSERT(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// use a macro to wrap the function, force the caller to use it in a critical section
|
||||||
|
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
|
||||||
|
#define twai_ll_enable_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; twai_ll_enable_clock(__VA_ARGS__)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set clock source for TWAI module
|
||||||
|
*
|
||||||
|
* @param group_id Group ID
|
||||||
|
* @param clk_src Clock source
|
||||||
|
*/
|
||||||
|
__attribute__((always_inline))
|
||||||
|
static inline void twai_ll_set_clock_source(int group_id, twai_clock_source_t clk_src)
|
||||||
|
{
|
||||||
|
uint32_t clk_id = 0;
|
||||||
|
|
||||||
|
switch (clk_src) {
|
||||||
|
case TWAI_CLK_SRC_XTAL: clk_id = 0; break;
|
||||||
|
#if SOC_CLK_TREE_SUPPORTED
|
||||||
|
case TWAI_CLK_SRC_RC_FAST: clk_id = 1; break;
|
||||||
|
#endif
|
||||||
|
default: HAL_ASSERT(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (group_id) {
|
||||||
|
case 0: HP_SYS_CLKRST.peri_clk_ctrl115.reg_twai0_clk_src_sel = clk_id; break;
|
||||||
|
case 1: HP_SYS_CLKRST.peri_clk_ctrl115.reg_twai1_clk_src_sel = clk_id; break;
|
||||||
|
case 2: HP_SYS_CLKRST.peri_clk_ctrl115.reg_twai2_clk_src_sel = clk_id; break;
|
||||||
|
default: HAL_ASSERT(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// use a macro to wrap the function, force the caller to use it in a critical section
|
||||||
|
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
|
||||||
|
#define twai_ll_set_clock_source(...) (void)__DECLARE_RCC_ATOMIC_ENV; twai_ll_set_clock_source(__VA_ARGS__)
|
||||||
|
|
||||||
|
/* ---------------------------- Mode Register ------------------------------- */
|
||||||
|
/**
|
||||||
|
* @brief Enter reset mode
|
||||||
|
*
|
||||||
|
* When in reset mode, the TWAI controller is effectively disconnected from the
|
||||||
|
* TWAI bus and will not participate in any bus activates. Reset mode is required
|
||||||
|
* in order to write the majority of configuration registers.
|
||||||
|
*
|
||||||
|
* @param hw Start address of the TWAI registers
|
||||||
|
*
|
||||||
|
* @note Reset mode is automatically entered on BUS OFF condition
|
||||||
|
*/
|
||||||
|
__attribute__((always_inline))
|
||||||
|
static inline void twai_ll_enter_reset_mode(twai_dev_t *hw)
|
||||||
|
{
|
||||||
|
hw->mode.reset_mode = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Exit reset mode
|
||||||
|
*
|
||||||
|
* When not in reset mode, the TWAI controller will take part in bus activities
|
||||||
|
* (e.g., send/receive/acknowledge messages and error frames) depending on the
|
||||||
|
* operating mode.
|
||||||
|
*
|
||||||
|
* @param hw Start address of the TWAI registers
|
||||||
|
*
|
||||||
|
* @note Reset mode must be exit to initiate BUS OFF recovery
|
||||||
|
*/
|
||||||
|
__attribute__((always_inline))
|
||||||
|
static inline void twai_ll_exit_reset_mode(twai_dev_t *hw)
|
||||||
|
{
|
||||||
|
hw->mode.reset_mode = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Check if in reset mode
|
||||||
|
* @param hw Start address of the TWAI registers
|
||||||
|
* @return true if in reset mode
|
||||||
|
*/
|
||||||
|
__attribute__((always_inline))
|
||||||
|
static inline bool twai_ll_is_in_reset_mode(twai_dev_t *hw)
|
||||||
|
{
|
||||||
|
return hw->mode.reset_mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set operating mode of TWAI controller
|
||||||
|
*
|
||||||
|
* @param hw Start address of the TWAI registers
|
||||||
|
* @param mode Operating mode
|
||||||
|
*
|
||||||
|
* @note Must be called in reset mode
|
||||||
|
*/
|
||||||
|
__attribute__((always_inline))
|
||||||
|
static inline void twai_ll_set_mode(twai_dev_t *hw, twai_mode_t mode)
|
||||||
|
{
|
||||||
|
if (mode == TWAI_MODE_NORMAL) { //Normal Operating mode
|
||||||
|
hw->mode.listen_only_mode = 0;
|
||||||
|
hw->mode.self_test_mode = 0;
|
||||||
|
} else if (mode == TWAI_MODE_NO_ACK) { //Self Test Mode (No Ack)
|
||||||
|
hw->mode.listen_only_mode = 0;
|
||||||
|
hw->mode.self_test_mode = 1;
|
||||||
|
} else if (mode == TWAI_MODE_LISTEN_ONLY) { //Listen Only Mode
|
||||||
|
hw->mode.listen_only_mode = 1;
|
||||||
|
hw->mode.self_test_mode = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------- Command Register ----------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set TX command
|
||||||
|
*
|
||||||
|
* Setting the TX command will cause the TWAI controller to attempt to transmit
|
||||||
|
* the frame stored in the TX buffer. The TX buffer will be occupied (i.e.,
|
||||||
|
* locked) until TX completes.
|
||||||
|
*
|
||||||
|
* @param hw Start address of the TWAI registers
|
||||||
|
*
|
||||||
|
* @note Transmit commands should be called last (i.e., after handling buffer
|
||||||
|
* release and clear data overrun) in order to prevent the other commands
|
||||||
|
* overwriting this latched TX bit with 0.
|
||||||
|
*/
|
||||||
|
__attribute__((always_inline))
|
||||||
|
static inline void twai_ll_set_cmd_tx(twai_dev_t *hw)
|
||||||
|
{
|
||||||
|
hw->cmd.tx_request = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set single shot TX command
|
||||||
|
*
|
||||||
|
* Similar to setting TX command, but the TWAI controller will not automatically
|
||||||
|
* retry transmission upon an error (e.g., due to an acknowledgement error).
|
||||||
|
*
|
||||||
|
* @param hw Start address of the TWAI registers
|
||||||
|
*
|
||||||
|
* @note Transmit commands should be called last (i.e., after handling buffer
|
||||||
|
* release and clear data overrun) in order to prevent the other commands
|
||||||
|
* overwriting this latched TX bit with 0.
|
||||||
|
*/
|
||||||
|
__attribute__((always_inline))
|
||||||
|
static inline void twai_ll_set_cmd_tx_single_shot(twai_dev_t *hw)
|
||||||
|
{
|
||||||
|
hw->cmd.val = 0x03; //Set cmd.tx_request and cmd.abort_tx simultaneously for single shot transmitting request
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Aborts TX
|
||||||
|
*
|
||||||
|
* Frames awaiting TX will be aborted. Frames already being TX are not aborted.
|
||||||
|
* Transmission Complete Status bit is automatically set to 1.
|
||||||
|
* Similar to setting TX command, but the TWAI controller will not automatically
|
||||||
|
* retry transmission upon an error (e.g., due to acknowledge error).
|
||||||
|
*
|
||||||
|
* @param hw Start address of the TWAI registers
|
||||||
|
*
|
||||||
|
* @note Transmit commands should be called last (i.e., after handling buffer
|
||||||
|
* release and clear data overrun) in order to prevent the other commands
|
||||||
|
* overwriting this latched TX bit with 0.
|
||||||
|
*/
|
||||||
|
__attribute__((always_inline))
|
||||||
|
static inline void twai_ll_set_cmd_abort_tx(twai_dev_t *hw)
|
||||||
|
{
|
||||||
|
hw->cmd.abort_tx = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Release RX buffer
|
||||||
|
*
|
||||||
|
* Rotates RX buffer to the next frame in the RX FIFO.
|
||||||
|
*
|
||||||
|
* @param hw Start address of the TWAI registers
|
||||||
|
*/
|
||||||
|
__attribute__((always_inline))
|
||||||
|
static inline void twai_ll_set_cmd_release_rx_buffer(twai_dev_t *hw)
|
||||||
|
{
|
||||||
|
hw->cmd.release_buffer = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Clear data overrun
|
||||||
|
*
|
||||||
|
* Clears the data overrun status bit
|
||||||
|
*
|
||||||
|
* @param hw Start address of the TWAI registers
|
||||||
|
*/
|
||||||
|
__attribute__((always_inline))
|
||||||
|
static inline void twai_ll_set_cmd_clear_data_overrun(twai_dev_t *hw)
|
||||||
|
{
|
||||||
|
hw->cmd.clear_data_overrun = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set self reception single shot command
|
||||||
|
*
|
||||||
|
* Similar to setting TX command, but the TWAI controller also simultaneously
|
||||||
|
* receive the transmitted frame and is generally used for self testing
|
||||||
|
* purposes. The TWAI controller will not ACK the received message, so consider
|
||||||
|
* using the NO_ACK operating mode.
|
||||||
|
*
|
||||||
|
* @param hw Start address of the TWAI registers
|
||||||
|
*
|
||||||
|
* @note Transmit commands should be called last (i.e., after handling buffer
|
||||||
|
* release and clear data overrun) in order to prevent the other commands
|
||||||
|
* overwriting this latched TX bit with 0.
|
||||||
|
*/
|
||||||
|
__attribute__((always_inline))
|
||||||
|
static inline void twai_ll_set_cmd_self_rx_request(twai_dev_t *hw)
|
||||||
|
{
|
||||||
|
hw->cmd.self_rx_request = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set self reception request command
|
||||||
|
*
|
||||||
|
* Similar to setting the self reception request, but the TWAI controller will
|
||||||
|
* not automatically retry transmission upon an error (e.g., due to and
|
||||||
|
* acknowledgement error).
|
||||||
|
*
|
||||||
|
* @param hw Start address of the TWAI registers
|
||||||
|
*
|
||||||
|
* @note Transmit commands should be called last (i.e., after handling buffer
|
||||||
|
* release and clear data overrun) in order to prevent the other commands
|
||||||
|
* overwriting this latched TX bit with 0.
|
||||||
|
*/
|
||||||
|
__attribute__((always_inline))
|
||||||
|
static inline void twai_ll_set_cmd_self_rx_single_shot(twai_dev_t *hw)
|
||||||
|
{
|
||||||
|
hw->cmd.val = 0x12; //Set cmd.self_rx_request and cmd.abort_tx simultaneously for single shot self reception request
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------- Status Register ------------------------------ */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get all status bits
|
||||||
|
*
|
||||||
|
* @param hw Start address of the TWAI registers
|
||||||
|
* @return Status bits
|
||||||
|
*/
|
||||||
|
__attribute__((always_inline))
|
||||||
|
static inline uint32_t twai_ll_get_status(twai_dev_t *hw)
|
||||||
|
{
|
||||||
|
return hw->status.val;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Check if RX FIFO overrun status bit is set
|
||||||
|
*
|
||||||
|
* @param hw Start address of the TWAI registers
|
||||||
|
* @return Overrun status bit
|
||||||
|
*/
|
||||||
|
__attribute__((always_inline))
|
||||||
|
static inline bool twai_ll_is_fifo_overrun(twai_dev_t *hw)
|
||||||
|
{
|
||||||
|
return hw->status.status_overrun;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Check if previously TX was successful
|
||||||
|
*
|
||||||
|
* @param hw Start address of the TWAI registers
|
||||||
|
* @return Whether previous TX was successful
|
||||||
|
*/
|
||||||
|
__attribute__((always_inline))
|
||||||
|
static inline bool twai_ll_is_last_tx_successful(twai_dev_t *hw)
|
||||||
|
{
|
||||||
|
return hw->status.status_transmission_complete;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------- Interrupt Register ---------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get currently set interrupts
|
||||||
|
*
|
||||||
|
* Reading the interrupt registers will automatically clear all interrupts
|
||||||
|
* except for the Receive Interrupt.
|
||||||
|
*
|
||||||
|
* @param hw Start address of the TWAI registers
|
||||||
|
* @return Bit mask of set interrupts
|
||||||
|
*/
|
||||||
|
__attribute__((always_inline))
|
||||||
|
static inline uint32_t twai_ll_get_and_clear_intrs(twai_dev_t *hw)
|
||||||
|
{
|
||||||
|
return hw->interrupt_st.val;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------------- Interrupt Enable Register ------------------------ */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set which interrupts are enabled
|
||||||
|
*
|
||||||
|
* @param hw Start address of the TWAI registers
|
||||||
|
* @param Bit mask of interrupts to enable
|
||||||
|
*
|
||||||
|
* @note Must be called in reset mode
|
||||||
|
*/
|
||||||
|
__attribute__((always_inline))
|
||||||
|
static inline void twai_ll_set_enabled_intrs(twai_dev_t *hw, uint32_t intr_mask)
|
||||||
|
{
|
||||||
|
hw->interrupt_ena.val = intr_mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------ Bus Timing Registers --------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Check if the brp value valid
|
||||||
|
*
|
||||||
|
* @param brp Bit rate prescaler value
|
||||||
|
* @return true or False
|
||||||
|
*/
|
||||||
|
__attribute__((always_inline))
|
||||||
|
static inline bool twai_ll_check_brp_validation(uint32_t brp)
|
||||||
|
{
|
||||||
|
bool valid = (brp >= SOC_TWAI_BRP_MIN) && (brp <= SOC_TWAI_BRP_MAX);
|
||||||
|
// should be an even number
|
||||||
|
valid = valid && !(brp & 0x01);
|
||||||
|
return valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set bus timing
|
||||||
|
*
|
||||||
|
* @param hw Start address of the TWAI registers
|
||||||
|
* @param brp Baud Rate Prescaler
|
||||||
|
* @param sjw Synchronization Jump Width
|
||||||
|
* @param tseg1 Timing Segment 1
|
||||||
|
* @param tseg2 Timing Segment 2
|
||||||
|
* @param triple_sampling Triple Sampling enable/disable
|
||||||
|
*
|
||||||
|
* @note Must be called in reset mode
|
||||||
|
* @note ESP32C6 brp can be any even number between 2 to 32768
|
||||||
|
*/
|
||||||
|
__attribute__((always_inline))
|
||||||
|
static inline void twai_ll_set_bus_timing(twai_dev_t *hw, uint32_t brp, uint32_t sjw, uint32_t tseg1, uint32_t tseg2, bool triple_sampling)
|
||||||
|
{
|
||||||
|
hw->bus_timing_0.baud_presc = (brp / 2) - 1;
|
||||||
|
hw->bus_timing_0.sync_jump_width = sjw - 1;
|
||||||
|
hw->bus_timing_1.time_segment1 = tseg1 - 1;
|
||||||
|
hw->bus_timing_1.time_segment2 = tseg2 - 1;
|
||||||
|
hw->bus_timing_1.time_sampling = triple_sampling;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------------------- ALC Register ------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Clear Arbitration Lost Capture Register
|
||||||
|
*
|
||||||
|
* Reading the ALC register rearms the Arbitration Lost Interrupt
|
||||||
|
*
|
||||||
|
* @param hw Start address of the TWAI registers
|
||||||
|
*/
|
||||||
|
__attribute__((always_inline))
|
||||||
|
static inline void twai_ll_clear_arb_lost_cap(twai_dev_t *hw)
|
||||||
|
{
|
||||||
|
(void)hw->arb_lost_cap.val;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------------------- ECC Register ------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Clear Error Code Capture register
|
||||||
|
*
|
||||||
|
* Reading the ECC register rearms the Bus Error Interrupt
|
||||||
|
*
|
||||||
|
* @param hw Start address of the TWAI registers
|
||||||
|
*/
|
||||||
|
__attribute__((always_inline))
|
||||||
|
static inline void twai_ll_clear_err_code_cap(twai_dev_t *hw)
|
||||||
|
{
|
||||||
|
(void)hw->err_code_cap.val;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------------------- EWL Register ------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set Error Warning Limit
|
||||||
|
*
|
||||||
|
* @param hw Start address of the TWAI registers
|
||||||
|
* @param ewl Error Warning Limit
|
||||||
|
*
|
||||||
|
* @note Must be called in reset mode
|
||||||
|
*/
|
||||||
|
__attribute__((always_inline))
|
||||||
|
static inline void twai_ll_set_err_warn_lim(twai_dev_t *hw, uint32_t ewl)
|
||||||
|
{
|
||||||
|
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->err_warning_limit, err_warning_limit, ewl);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get Error Warning Limit
|
||||||
|
*
|
||||||
|
* @param hw Start address of the TWAI registers
|
||||||
|
* @return Error Warning Limit
|
||||||
|
*/
|
||||||
|
__attribute__((always_inline))
|
||||||
|
static inline uint32_t twai_ll_get_err_warn_lim(twai_dev_t *hw)
|
||||||
|
{
|
||||||
|
return hw->err_warning_limit.val;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------ RX Error Count Register ------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get RX Error Counter
|
||||||
|
*
|
||||||
|
* @param hw Start address of the TWAI registers
|
||||||
|
* @return REC value
|
||||||
|
*
|
||||||
|
* @note REC is not frozen in reset mode. Listen only mode will freeze it. A BUS
|
||||||
|
* OFF condition automatically sets the REC to 0.
|
||||||
|
*/
|
||||||
|
__attribute__((always_inline))
|
||||||
|
static inline uint32_t twai_ll_get_rec(twai_dev_t *hw)
|
||||||
|
{
|
||||||
|
return hw->rx_err_cnt.val;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set RX Error Counter
|
||||||
|
*
|
||||||
|
* @param hw Start address of the TWAI registers
|
||||||
|
* @param rec REC value
|
||||||
|
*
|
||||||
|
* @note Must be called in reset mode
|
||||||
|
*/
|
||||||
|
__attribute__((always_inline))
|
||||||
|
static inline void twai_ll_set_rec(twai_dev_t *hw, uint32_t rec)
|
||||||
|
{
|
||||||
|
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->rx_err_cnt, rx_err_cnt, rec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------ TX Error Count Register ------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get TX Error Counter
|
||||||
|
*
|
||||||
|
* @param hw Start address of the TWAI registers
|
||||||
|
* @return TEC value
|
||||||
|
*
|
||||||
|
* @note A BUS OFF condition will automatically set this to 128
|
||||||
|
*/
|
||||||
|
__attribute__((always_inline))
|
||||||
|
static inline uint32_t twai_ll_get_tec(twai_dev_t *hw)
|
||||||
|
{
|
||||||
|
return hw->tx_err_cnt.val;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set TX Error Counter
|
||||||
|
*
|
||||||
|
* @param hw Start address of the TWAI registers
|
||||||
|
* @param tec TEC value
|
||||||
|
*
|
||||||
|
* @note Must be called in reset mode
|
||||||
|
*/
|
||||||
|
__attribute__((always_inline))
|
||||||
|
static inline void twai_ll_set_tec(twai_dev_t *hw, uint32_t tec)
|
||||||
|
{
|
||||||
|
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->tx_err_cnt, tx_err_cnt, tec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------- Acceptance Filter Registers ----------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set Acceptance Filter
|
||||||
|
* @param hw Start address of the TWAI registers
|
||||||
|
* @param code Acceptance Code
|
||||||
|
* @param mask Acceptance Mask
|
||||||
|
* @param single_filter Whether to enable single filter mode
|
||||||
|
*
|
||||||
|
* @note Must be called in reset mode
|
||||||
|
*/
|
||||||
|
__attribute__((always_inline))
|
||||||
|
static inline void twai_ll_set_acc_filter(twai_dev_t *hw, uint32_t code, uint32_t mask, bool single_filter)
|
||||||
|
{
|
||||||
|
uint32_t code_swapped = HAL_SWAP32(code);
|
||||||
|
uint32_t mask_swapped = HAL_SWAP32(mask);
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->acceptance_filter.acr[i], byte, ((code_swapped >> (i * 8)) & 0xFF));
|
||||||
|
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->acceptance_filter.amr[i], byte, ((mask_swapped >> (i * 8)) & 0xFF));
|
||||||
|
}
|
||||||
|
hw->mode.acceptance_filter_mode = single_filter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------- TX/RX Buffer Registers ------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Copy a formatted TWAI frame into TX buffer for transmission
|
||||||
|
*
|
||||||
|
* @param hw Start address of the TWAI registers
|
||||||
|
* @param tx_frame Pointer to formatted frame
|
||||||
|
*
|
||||||
|
* @note Call twai_ll_format_frame_buffer() to format a frame
|
||||||
|
*/
|
||||||
|
__attribute__((always_inline))
|
||||||
|
static inline void twai_ll_set_tx_buffer(twai_dev_t *hw, twai_ll_frame_buffer_t *tx_frame)
|
||||||
|
{
|
||||||
|
//Copy formatted frame into TX buffer
|
||||||
|
for (int i = 0; i < 13; i++) {
|
||||||
|
hw->tx_rx_buffer[i].val = tx_frame->bytes[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Copy a received frame from the RX buffer for parsing
|
||||||
|
*
|
||||||
|
* @param hw Start address of the TWAI registers
|
||||||
|
* @param rx_frame Pointer to store formatted frame
|
||||||
|
*
|
||||||
|
* @note Call twai_ll_parse_frame_buffer() to parse the formatted frame
|
||||||
|
*/
|
||||||
|
__attribute__((always_inline))
|
||||||
|
static inline void twai_ll_get_rx_buffer(twai_dev_t *hw, twai_ll_frame_buffer_t *rx_frame)
|
||||||
|
{
|
||||||
|
//Copy RX buffer registers into frame
|
||||||
|
for (int i = 0; i < 13; i++) {
|
||||||
|
rx_frame->bytes[i] = HAL_FORCE_READ_U32_REG_FIELD(hw->tx_rx_buffer[i], byte);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Format contents of a TWAI frame into layout of TX Buffer
|
||||||
|
*
|
||||||
|
* This function encodes a message into a frame structure. The frame structure
|
||||||
|
* has an identical layout to the TX buffer, allowing the frame structure to be
|
||||||
|
* directly copied into TX buffer.
|
||||||
|
*
|
||||||
|
* @param[in] 11bit or 29bit ID
|
||||||
|
* @param[in] dlc Data length code
|
||||||
|
* @param[in] data Pointer to an 8 byte array containing data. NULL if no data
|
||||||
|
* @param[in] format Type of TWAI frame
|
||||||
|
* @param[in] single_shot Frame will not be retransmitted on failure
|
||||||
|
* @param[in] self_rx Frame will also be simultaneously received
|
||||||
|
* @param[out] tx_frame Pointer to store formatted frame
|
||||||
|
*/
|
||||||
|
__attribute__((always_inline))
|
||||||
|
static inline void twai_ll_format_frame_buffer(uint32_t id, uint8_t dlc, const uint8_t *data, uint32_t flags, twai_ll_frame_buffer_t *tx_frame)
|
||||||
|
{
|
||||||
|
bool is_extd = flags & TWAI_MSG_FLAG_EXTD;
|
||||||
|
bool is_rtr = flags & TWAI_MSG_FLAG_RTR;
|
||||||
|
|
||||||
|
//Set frame information
|
||||||
|
tx_frame->dlc = dlc;
|
||||||
|
tx_frame->frame_format = is_extd;
|
||||||
|
tx_frame->rtr = is_rtr;
|
||||||
|
tx_frame->self_reception = (flags & TWAI_MSG_FLAG_SELF) ? 1 : 0;
|
||||||
|
tx_frame->single_shot = (flags & TWAI_MSG_FLAG_SS) ? 1 : 0;
|
||||||
|
|
||||||
|
//Set ID. The ID registers are big endian and left aligned, therefore a bswap will be required
|
||||||
|
if (is_extd) {
|
||||||
|
uint32_t id_temp = HAL_SWAP32((id & TWAI_EXTD_ID_MASK) << 3); //((id << 3) >> 8*(3-i))
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
tx_frame->extended.id[i] = (id_temp >> (8 * i)) & 0xFF;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
uint32_t id_temp = HAL_SWAP16((id & TWAI_STD_ID_MASK) << 5); //((id << 5) >> 8*(1-i))
|
||||||
|
for (int i = 0; i < 2; i++) {
|
||||||
|
tx_frame->standard.id[i] = (id_temp >> (8 * i)) & 0xFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *data_buffer = (is_extd) ? tx_frame->extended.data : tx_frame->standard.data;
|
||||||
|
if (!is_rtr) { //Only copy data if the frame is a data frame (i.e not a remote frame)
|
||||||
|
for (int i = 0; (i < dlc) && (i < TWAI_FRAME_MAX_DLC); i++) {
|
||||||
|
data_buffer[i] = data[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Parse formatted TWAI frame (RX Buffer Layout) into its constituent contents
|
||||||
|
*
|
||||||
|
* @param[in] rx_frame Pointer to formatted frame
|
||||||
|
* @param[out] id 11 or 29bit ID
|
||||||
|
* @param[out] dlc Data length code
|
||||||
|
* @param[out] data Data. Left over bytes set to 0.
|
||||||
|
* @param[out] format Type of TWAI frame
|
||||||
|
*/
|
||||||
|
__attribute__((always_inline))
|
||||||
|
static inline void twai_ll_parse_frame_buffer(twai_ll_frame_buffer_t *rx_frame, uint32_t *id, uint8_t *dlc, uint8_t *data, uint32_t *flags)
|
||||||
|
{
|
||||||
|
//Copy frame information
|
||||||
|
*dlc = rx_frame->dlc;
|
||||||
|
uint32_t flags_temp = 0;
|
||||||
|
flags_temp |= (rx_frame->frame_format) ? TWAI_MSG_FLAG_EXTD : 0;
|
||||||
|
flags_temp |= (rx_frame->rtr) ? TWAI_MSG_FLAG_RTR : 0;
|
||||||
|
flags_temp |= (rx_frame->dlc > TWAI_FRAME_MAX_DLC) ? TWAI_MSG_FLAG_DLC_NON_COMP : 0;
|
||||||
|
*flags = flags_temp;
|
||||||
|
|
||||||
|
//Copy ID. The ID registers are big endian and left aligned, therefore a bswap will be required
|
||||||
|
if (rx_frame->frame_format) {
|
||||||
|
uint32_t id_temp = 0;
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
id_temp |= rx_frame->extended.id[i] << (8 * i);
|
||||||
|
}
|
||||||
|
id_temp = HAL_SWAP32(id_temp) >> 3; //((byte[i] << 8*(3-i)) >> 3)
|
||||||
|
*id = id_temp & TWAI_EXTD_ID_MASK;
|
||||||
|
} else {
|
||||||
|
uint32_t id_temp = 0;
|
||||||
|
for (int i = 0; i < 2; i++) {
|
||||||
|
id_temp |= rx_frame->standard.id[i] << (8 * i);
|
||||||
|
}
|
||||||
|
id_temp = HAL_SWAP16(id_temp) >> 5; //((byte[i] << 8*(1-i)) >> 5)
|
||||||
|
*id = id_temp & TWAI_STD_ID_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *data_buffer = (rx_frame->frame_format) ? rx_frame->extended.data : rx_frame->standard.data;
|
||||||
|
//Only copy data if the frame is a data frame (i.e. not a remote frame)
|
||||||
|
int data_length = (rx_frame->rtr) ? 0 : ((rx_frame->dlc > TWAI_FRAME_MAX_DLC) ? TWAI_FRAME_MAX_DLC : rx_frame->dlc);
|
||||||
|
for (int i = 0; i < data_length; i++) {
|
||||||
|
data[i] = data_buffer[i];
|
||||||
|
}
|
||||||
|
//Set remaining bytes of data to 0
|
||||||
|
for (int i = data_length; i < TWAI_FRAME_MAX_DLC; i++) {
|
||||||
|
data[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------------- RX Message Count Register ------------------------ */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get RX Message Counter
|
||||||
|
*
|
||||||
|
* @param hw Start address of the TWAI registers
|
||||||
|
* @return RX Message Counter
|
||||||
|
*/
|
||||||
|
__attribute__((always_inline))
|
||||||
|
static inline uint32_t twai_ll_get_rx_msg_count(twai_dev_t *hw)
|
||||||
|
{
|
||||||
|
return hw->rx_message_counter.val;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------- Clock Divider Register ------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set CLKOUT Divider and enable/disable
|
||||||
|
*
|
||||||
|
* Configure CLKOUT. CLKOUT is a pre-scaled version of peripheral source clock. Divider can be
|
||||||
|
* 1, or any even number from 2 to 490. Set the divider to 0 to disable CLKOUT.
|
||||||
|
*
|
||||||
|
* @param hw Start address of the TWAI registers
|
||||||
|
* @param divider Divider for CLKOUT (any even number from 2 to 490). Set to 0 to disable CLKOUT
|
||||||
|
*/
|
||||||
|
__attribute__((always_inline))
|
||||||
|
static inline void twai_ll_set_clkout(twai_dev_t *hw, uint32_t divider)
|
||||||
|
{
|
||||||
|
if (divider >= 2 && divider <= 490) {
|
||||||
|
hw->clock_divider.clock_off = 0;
|
||||||
|
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clock_divider, cd, (divider / 2) - 1);
|
||||||
|
} else if (divider == 1) {
|
||||||
|
//Setting the divider reg to max value (255) means a divider of 1
|
||||||
|
hw->clock_divider.clock_off = 0;
|
||||||
|
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clock_divider, cd, 255);
|
||||||
|
} else {
|
||||||
|
hw->clock_divider.clock_off = 1;
|
||||||
|
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clock_divider, cd, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
@ -127,25 +127,25 @@ static inline void twai_ll_reset_register(int group_id)
|
|||||||
/**
|
/**
|
||||||
* @brief Enable TWAI module clock
|
* @brief Enable TWAI module clock
|
||||||
*
|
*
|
||||||
* @param hw Start address of the TWAI registers
|
* @param group_id Group ID
|
||||||
* @param en true to enable, false to disable
|
* @param en true to enable, false to disable
|
||||||
*/
|
*/
|
||||||
__attribute__((always_inline))
|
__attribute__((always_inline))
|
||||||
static inline void twai_ll_enable_clock(twai_dev_t *hw, bool en)
|
static inline void twai_ll_enable_clock(int group_id, bool en)
|
||||||
{
|
{
|
||||||
(void)hw;
|
(void)group_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Set clock source for TWAI module
|
* @brief Set clock source for TWAI module
|
||||||
*
|
*
|
||||||
* @param hw Start address of the TWAI registers
|
* @param group_id Group ID
|
||||||
* @param clk_src Clock source
|
* @param clk_src Clock source
|
||||||
*/
|
*/
|
||||||
__attribute__((always_inline))
|
__attribute__((always_inline))
|
||||||
static inline void twai_ll_set_clock_source(twai_dev_t *hw, twai_clock_source_t clk_src)
|
static inline void twai_ll_set_clock_source(int group_id, twai_clock_source_t clk_src)
|
||||||
{
|
{
|
||||||
(void)hw;
|
(void)group_id;
|
||||||
HAL_ASSERT(clk_src == TWAI_CLK_SRC_APB);
|
HAL_ASSERT(clk_src == TWAI_CLK_SRC_APB);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,25 +124,25 @@ static inline void twai_ll_reset_register(int group_id)
|
|||||||
/**
|
/**
|
||||||
* @brief Enable TWAI module clock
|
* @brief Enable TWAI module clock
|
||||||
*
|
*
|
||||||
* @param hw Start address of the TWAI registers
|
* @param group_id Group ID
|
||||||
* @param en true to enable, false to disable
|
* @param en true to enable, false to disable
|
||||||
*/
|
*/
|
||||||
__attribute__((always_inline))
|
__attribute__((always_inline))
|
||||||
static inline void twai_ll_enable_clock(twai_dev_t *hw, bool en)
|
static inline void twai_ll_enable_clock(int group_id, bool en)
|
||||||
{
|
{
|
||||||
(void)hw;
|
(void)group_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Set clock source for TWAI module
|
* @brief Set clock source for TWAI module
|
||||||
*
|
*
|
||||||
* @param hw Start address of the TWAI registers
|
* @param group_id Group ID
|
||||||
* @param clk_src Clock source
|
* @param clk_src Clock source
|
||||||
*/
|
*/
|
||||||
__attribute__((always_inline))
|
__attribute__((always_inline))
|
||||||
static inline void twai_ll_set_clock_source(twai_dev_t *hw, twai_clock_source_t clk_src)
|
static inline void twai_ll_set_clock_source(int group_id, twai_clock_source_t clk_src)
|
||||||
{
|
{
|
||||||
(void)hw;
|
(void)group_id;
|
||||||
HAL_ASSERT(clk_src == TWAI_CLK_SRC_APB);
|
HAL_ASSERT(clk_src == TWAI_CLK_SRC_APB);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@ -23,8 +23,6 @@ bool twai_hal_init(twai_hal_context_t *hal_ctx, const twai_hal_config_t *config)
|
|||||||
hal_ctx->dev = TWAI_LL_GET_HW(config->controller_id);
|
hal_ctx->dev = TWAI_LL_GET_HW(config->controller_id);
|
||||||
hal_ctx->state_flags = 0;
|
hal_ctx->state_flags = 0;
|
||||||
hal_ctx->clock_source_hz = config->clock_source_hz;
|
hal_ctx->clock_source_hz = config->clock_source_hz;
|
||||||
//Enable functional clock
|
|
||||||
twai_ll_enable_clock(hal_ctx->dev, true);
|
|
||||||
//Initialize TWAI controller, and set default values to registers
|
//Initialize TWAI controller, and set default values to registers
|
||||||
twai_ll_enter_reset_mode(hal_ctx->dev);
|
twai_ll_enter_reset_mode(hal_ctx->dev);
|
||||||
if (!twai_ll_is_in_reset_mode(hal_ctx->dev)) { //Must enter reset mode to write to config registers
|
if (!twai_ll_is_in_reset_mode(hal_ctx->dev)) { //Must enter reset mode to write to config registers
|
||||||
@ -48,8 +46,6 @@ void twai_hal_deinit(twai_hal_context_t *hal_ctx)
|
|||||||
twai_ll_set_enabled_intrs(hal_ctx->dev, 0);
|
twai_ll_set_enabled_intrs(hal_ctx->dev, 0);
|
||||||
twai_ll_clear_arb_lost_cap(hal_ctx->dev);
|
twai_ll_clear_arb_lost_cap(hal_ctx->dev);
|
||||||
twai_ll_clear_err_code_cap(hal_ctx->dev);
|
twai_ll_clear_err_code_cap(hal_ctx->dev);
|
||||||
//Disable functional clock
|
|
||||||
twai_ll_enable_clock(hal_ctx->dev, false);
|
|
||||||
hal_ctx->dev = NULL;
|
hal_ctx->dev = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,14 +58,6 @@ void twai_hal_configure(twai_hal_context_t *hal_ctx, const twai_timing_config_t
|
|||||||
brp = hal_ctx->clock_source_hz / t_config->quanta_resolution_hz;
|
brp = hal_ctx->clock_source_hz / t_config->quanta_resolution_hz;
|
||||||
}
|
}
|
||||||
|
|
||||||
// set clock source
|
|
||||||
twai_clock_source_t clk_src = t_config->clk_src;
|
|
||||||
//for backward compatible, zero value means default a default clock source
|
|
||||||
if (t_config->clk_src == 0) {
|
|
||||||
clk_src = TWAI_CLK_SRC_DEFAULT;
|
|
||||||
}
|
|
||||||
twai_ll_set_clock_source(hal_ctx->dev, clk_src);
|
|
||||||
|
|
||||||
//Configure bus timing, acceptance filter, CLKOUT, and interrupts
|
//Configure bus timing, acceptance filter, CLKOUT, and interrupts
|
||||||
twai_ll_set_bus_timing(hal_ctx->dev, brp, t_config->sjw, t_config->tseg_1, t_config->tseg_2, t_config->triple_sampling);
|
twai_ll_set_bus_timing(hal_ctx->dev, brp, t_config->sjw, t_config->tseg_1, t_config->tseg_2, t_config->triple_sampling);
|
||||||
twai_ll_set_acc_filter(hal_ctx->dev, f_config->acceptance_code, f_config->acceptance_mask, f_config->single_filter);
|
twai_ll_set_acc_filter(hal_ctx->dev, f_config->acceptance_code, f_config->acceptance_mask, f_config->single_filter);
|
||||||
|
@ -35,6 +35,10 @@ config SOC_MCPWM_SUPPORTED
|
|||||||
bool
|
bool
|
||||||
default y
|
default y
|
||||||
|
|
||||||
|
config SOC_TWAI_SUPPORTED
|
||||||
|
bool
|
||||||
|
default y
|
||||||
|
|
||||||
config SOC_ETM_SUPPORTED
|
config SOC_ETM_SUPPORTED
|
||||||
bool
|
bool
|
||||||
default y
|
default y
|
||||||
@ -1009,7 +1013,7 @@ config SOC_MWDT_SUPPORT_XTAL
|
|||||||
|
|
||||||
config SOC_TWAI_CONTROLLER_NUM
|
config SOC_TWAI_CONTROLLER_NUM
|
||||||
int
|
int
|
||||||
default 2
|
default 3
|
||||||
|
|
||||||
config SOC_TWAI_CLK_SUPPORT_XTAL
|
config SOC_TWAI_CLK_SUPPORT_XTAL
|
||||||
bool
|
bool
|
||||||
|
@ -464,6 +464,21 @@ typedef enum {
|
|||||||
} soc_periph_ana_cmpr_clk_src_t;
|
} soc_periph_ana_cmpr_clk_src_t;
|
||||||
|
|
||||||
//////////////////////////////////////////////////TWAI//////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////TWAI//////////////////////////////////////////////////////////////////
|
||||||
|
/**
|
||||||
|
* @brief Array initializer for all supported clock sources of TWAI
|
||||||
|
*/
|
||||||
|
#define SOC_TWAI_CLKS {SOC_MOD_CLK_XTAL, SOC_MOD_CLK_RC_FAST}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief TWAI clock source
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
TWAI_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL, /*!< Select XTAL as the source clock */
|
||||||
|
#if SOC_CLK_TREE_SUPPORTED
|
||||||
|
TWAI_CLK_SRC_RC_FAST = SOC_MOD_CLK_RC_FAST /*!< Select RC_FAST as the source clock */
|
||||||
|
#endif
|
||||||
|
TWAI_CLK_SRC_DEFAULT = SOC_MOD_CLK_XTAL, /*!< Select XTAL as the default clock choice */
|
||||||
|
} soc_periph_twai_clk_src_t;
|
||||||
|
|
||||||
//////////////////////////////////////////////////ADC///////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////ADC///////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@ -159,18 +159,18 @@
|
|||||||
#define UART4_SLP_CLK_PAD_IN_IDX 78
|
#define UART4_SLP_CLK_PAD_IN_IDX 78
|
||||||
#define GPIO_SD6_OUT_IDX 78
|
#define GPIO_SD6_OUT_IDX 78
|
||||||
#define GPIO_SD7_OUT_IDX 79
|
#define GPIO_SD7_OUT_IDX 79
|
||||||
#define CAN0_RX_PAD_IN_IDX 80
|
#define TWAI0_RX_PAD_IN_IDX 80
|
||||||
#define CAN0_TX_PAD_OUT_IDX 80
|
#define TWAI0_TX_PAD_OUT_IDX 80
|
||||||
#define CAN0_BUS_OFF_ON_PAD_OUT_IDX 81
|
#define TWAI0_BUS_OFF_ON_PAD_OUT_IDX 81
|
||||||
#define CAN0_CLKOUT_PAD_OUT_IDX 82
|
#define TWAI0_CLKOUT_PAD_OUT_IDX 82
|
||||||
#define CAN1_RX_PAD_IN_IDX 83
|
#define TWAI1_RX_PAD_IN_IDX 83
|
||||||
#define CAN1_TX_PAD_OUT_IDX 83
|
#define TWAI1_TX_PAD_OUT_IDX 83
|
||||||
#define CAN1_BUS_OFF_ON_PAD_OUT_IDX 84
|
#define TWAI1_BUS_OFF_ON_PAD_OUT_IDX 84
|
||||||
#define CAN1_CLKOUT_PAD_OUT_IDX 85
|
#define TWAI1_CLKOUT_PAD_OUT_IDX 85
|
||||||
#define CAN2_RX_PAD_IN_IDX 86
|
#define TWAI2_RX_PAD_IN_IDX 86
|
||||||
#define CAN2_TX_PAD_OUT_IDX 86
|
#define TWAI2_TX_PAD_OUT_IDX 86
|
||||||
#define CAN2_BUS_OFF_ON_PAD_OUT_IDX 87
|
#define TWAI2_BUS_OFF_ON_PAD_OUT_IDX 87
|
||||||
#define CAN2_CLKOUT_PAD_OUT_IDX 88
|
#define TWAI2_CLKOUT_PAD_OUT_IDX 88
|
||||||
#define PWM0_SYNC0_PAD_IN_IDX 89
|
#define PWM0_SYNC0_PAD_IN_IDX 89
|
||||||
#define PWM0_CH0_A_PAD_OUT_IDX 89
|
#define PWM0_CH0_A_PAD_OUT_IDX 89
|
||||||
#define PWM0_SYNC1_PAD_IN_IDX 90
|
#define PWM0_SYNC1_PAD_IN_IDX 90
|
||||||
|
@ -3473,27 +3473,27 @@ extern "C" {
|
|||||||
#define HP_SYS_CLKRST_REG_RST_EN_PWM1_M (HP_SYS_CLKRST_REG_RST_EN_PWM1_V << HP_SYS_CLKRST_REG_RST_EN_PWM1_S)
|
#define HP_SYS_CLKRST_REG_RST_EN_PWM1_M (HP_SYS_CLKRST_REG_RST_EN_PWM1_V << HP_SYS_CLKRST_REG_RST_EN_PWM1_S)
|
||||||
#define HP_SYS_CLKRST_REG_RST_EN_PWM1_V 0x00000001U
|
#define HP_SYS_CLKRST_REG_RST_EN_PWM1_V 0x00000001U
|
||||||
#define HP_SYS_CLKRST_REG_RST_EN_PWM1_S 25
|
#define HP_SYS_CLKRST_REG_RST_EN_PWM1_S 25
|
||||||
/** HP_SYS_CLKRST_REG_RST_EN_CAN0 : R/W; bitpos: [26]; default: 0;
|
/** HP_SYS_CLKRST_REG_RST_EN_TWAI0 : R/W; bitpos: [26]; default: 0;
|
||||||
* Reserved
|
* Reserved
|
||||||
*/
|
*/
|
||||||
#define HP_SYS_CLKRST_REG_RST_EN_CAN0 (BIT(26))
|
#define HP_SYS_CLKRST_REG_RST_EN_TWAI0 (BIT(26))
|
||||||
#define HP_SYS_CLKRST_REG_RST_EN_CAN0_M (HP_SYS_CLKRST_REG_RST_EN_CAN0_V << HP_SYS_CLKRST_REG_RST_EN_CAN0_S)
|
#define HP_SYS_CLKRST_REG_RST_EN_TWAI0_M (HP_SYS_CLKRST_REG_RST_EN_TWAI0_V << HP_SYS_CLKRST_REG_RST_EN_TWAI0_S)
|
||||||
#define HP_SYS_CLKRST_REG_RST_EN_CAN0_V 0x00000001U
|
#define HP_SYS_CLKRST_REG_RST_EN_TWAI0_V 0x00000001U
|
||||||
#define HP_SYS_CLKRST_REG_RST_EN_CAN0_S 26
|
#define HP_SYS_CLKRST_REG_RST_EN_TWAI0_S 26
|
||||||
/** HP_SYS_CLKRST_REG_RST_EN_CAN1 : R/W; bitpos: [27]; default: 0;
|
/** HP_SYS_CLKRST_REG_RST_EN_TWAI1 : R/W; bitpos: [27]; default: 0;
|
||||||
* Reserved
|
* Reserved
|
||||||
*/
|
*/
|
||||||
#define HP_SYS_CLKRST_REG_RST_EN_CAN1 (BIT(27))
|
#define HP_SYS_CLKRST_REG_RST_EN_TWAI1 (BIT(27))
|
||||||
#define HP_SYS_CLKRST_REG_RST_EN_CAN1_M (HP_SYS_CLKRST_REG_RST_EN_CAN1_V << HP_SYS_CLKRST_REG_RST_EN_CAN1_S)
|
#define HP_SYS_CLKRST_REG_RST_EN_TWAI1_M (HP_SYS_CLKRST_REG_RST_EN_TWAI1_V << HP_SYS_CLKRST_REG_RST_EN_TWAI1_S)
|
||||||
#define HP_SYS_CLKRST_REG_RST_EN_CAN1_V 0x00000001U
|
#define HP_SYS_CLKRST_REG_RST_EN_TWAI1_V 0x00000001U
|
||||||
#define HP_SYS_CLKRST_REG_RST_EN_CAN1_S 27
|
#define HP_SYS_CLKRST_REG_RST_EN_TWAI1_S 27
|
||||||
/** HP_SYS_CLKRST_REG_RST_EN_CAN2 : R/W; bitpos: [28]; default: 0;
|
/** HP_SYS_CLKRST_REG_RST_EN_TWAI2 : R/W; bitpos: [28]; default: 0;
|
||||||
* Reserved
|
* Reserved
|
||||||
*/
|
*/
|
||||||
#define HP_SYS_CLKRST_REG_RST_EN_CAN2 (BIT(28))
|
#define HP_SYS_CLKRST_REG_RST_EN_TWAI2 (BIT(28))
|
||||||
#define HP_SYS_CLKRST_REG_RST_EN_CAN2_M (HP_SYS_CLKRST_REG_RST_EN_CAN2_V << HP_SYS_CLKRST_REG_RST_EN_CAN2_S)
|
#define HP_SYS_CLKRST_REG_RST_EN_TWAI2_M (HP_SYS_CLKRST_REG_RST_EN_TWAI2_V << HP_SYS_CLKRST_REG_RST_EN_TWAI2_S)
|
||||||
#define HP_SYS_CLKRST_REG_RST_EN_CAN2_V 0x00000001U
|
#define HP_SYS_CLKRST_REG_RST_EN_TWAI2_V 0x00000001U
|
||||||
#define HP_SYS_CLKRST_REG_RST_EN_CAN2_S 28
|
#define HP_SYS_CLKRST_REG_RST_EN_TWAI2_S 28
|
||||||
/** HP_SYS_CLKRST_REG_RST_EN_LEDC : R/W; bitpos: [29]; default: 0;
|
/** HP_SYS_CLKRST_REG_RST_EN_LEDC : R/W; bitpos: [29]; default: 0;
|
||||||
* Reserved
|
* Reserved
|
||||||
*/
|
*/
|
||||||
@ -3971,27 +3971,27 @@ extern "C" {
|
|||||||
#define HP_SYS_CLKRST_REG_FORCE_NORST_PWM1_M (HP_SYS_CLKRST_REG_FORCE_NORST_PWM1_V << HP_SYS_CLKRST_REG_FORCE_NORST_PWM1_S)
|
#define HP_SYS_CLKRST_REG_FORCE_NORST_PWM1_M (HP_SYS_CLKRST_REG_FORCE_NORST_PWM1_V << HP_SYS_CLKRST_REG_FORCE_NORST_PWM1_S)
|
||||||
#define HP_SYS_CLKRST_REG_FORCE_NORST_PWM1_V 0x00000001U
|
#define HP_SYS_CLKRST_REG_FORCE_NORST_PWM1_V 0x00000001U
|
||||||
#define HP_SYS_CLKRST_REG_FORCE_NORST_PWM1_S 5
|
#define HP_SYS_CLKRST_REG_FORCE_NORST_PWM1_S 5
|
||||||
/** HP_SYS_CLKRST_REG_FORCE_NORST_CAN0 : R/W; bitpos: [6]; default: 0;
|
/** HP_SYS_CLKRST_REG_FORCE_NORST_TWAI0 : R/W; bitpos: [6]; default: 0;
|
||||||
* Reserved
|
* Reserved
|
||||||
*/
|
*/
|
||||||
#define HP_SYS_CLKRST_REG_FORCE_NORST_CAN0 (BIT(6))
|
#define HP_SYS_CLKRST_REG_FORCE_NORST_TWAI0 (BIT(6))
|
||||||
#define HP_SYS_CLKRST_REG_FORCE_NORST_CAN0_M (HP_SYS_CLKRST_REG_FORCE_NORST_CAN0_V << HP_SYS_CLKRST_REG_FORCE_NORST_CAN0_S)
|
#define HP_SYS_CLKRST_REG_FORCE_NORST_TWAI0_M (HP_SYS_CLKRST_REG_FORCE_NORST_TWAI0_V << HP_SYS_CLKRST_REG_FORCE_NORST_TWAI0_S)
|
||||||
#define HP_SYS_CLKRST_REG_FORCE_NORST_CAN0_V 0x00000001U
|
#define HP_SYS_CLKRST_REG_FORCE_NORST_TWAI0_V 0x00000001U
|
||||||
#define HP_SYS_CLKRST_REG_FORCE_NORST_CAN0_S 6
|
#define HP_SYS_CLKRST_REG_FORCE_NORST_TWAI0_S 6
|
||||||
/** HP_SYS_CLKRST_REG_FORCE_NORST_CAN1 : R/W; bitpos: [7]; default: 0;
|
/** HP_SYS_CLKRST_REG_FORCE_NORST_TWAI1 : R/W; bitpos: [7]; default: 0;
|
||||||
* Reserved
|
* Reserved
|
||||||
*/
|
*/
|
||||||
#define HP_SYS_CLKRST_REG_FORCE_NORST_CAN1 (BIT(7))
|
#define HP_SYS_CLKRST_REG_FORCE_NORST_TWAI1 (BIT(7))
|
||||||
#define HP_SYS_CLKRST_REG_FORCE_NORST_CAN1_M (HP_SYS_CLKRST_REG_FORCE_NORST_CAN1_V << HP_SYS_CLKRST_REG_FORCE_NORST_CAN1_S)
|
#define HP_SYS_CLKRST_REG_FORCE_NORST_TWAI1_M (HP_SYS_CLKRST_REG_FORCE_NORST_TWAI1_V << HP_SYS_CLKRST_REG_FORCE_NORST_TWAI1_S)
|
||||||
#define HP_SYS_CLKRST_REG_FORCE_NORST_CAN1_V 0x00000001U
|
#define HP_SYS_CLKRST_REG_FORCE_NORST_TWAI1_V 0x00000001U
|
||||||
#define HP_SYS_CLKRST_REG_FORCE_NORST_CAN1_S 7
|
#define HP_SYS_CLKRST_REG_FORCE_NORST_TWAI1_S 7
|
||||||
/** HP_SYS_CLKRST_REG_FORCE_NORST_CAN2 : R/W; bitpos: [8]; default: 0;
|
/** HP_SYS_CLKRST_REG_FORCE_NORST_TWAI2 : R/W; bitpos: [8]; default: 0;
|
||||||
* Reserved
|
* Reserved
|
||||||
*/
|
*/
|
||||||
#define HP_SYS_CLKRST_REG_FORCE_NORST_CAN2 (BIT(8))
|
#define HP_SYS_CLKRST_REG_FORCE_NORST_TWAI2 (BIT(8))
|
||||||
#define HP_SYS_CLKRST_REG_FORCE_NORST_CAN2_M (HP_SYS_CLKRST_REG_FORCE_NORST_CAN2_V << HP_SYS_CLKRST_REG_FORCE_NORST_CAN2_S)
|
#define HP_SYS_CLKRST_REG_FORCE_NORST_TWAI2_M (HP_SYS_CLKRST_REG_FORCE_NORST_TWAI2_V << HP_SYS_CLKRST_REG_FORCE_NORST_TWAI2_S)
|
||||||
#define HP_SYS_CLKRST_REG_FORCE_NORST_CAN2_V 0x00000001U
|
#define HP_SYS_CLKRST_REG_FORCE_NORST_TWAI2_V 0x00000001U
|
||||||
#define HP_SYS_CLKRST_REG_FORCE_NORST_CAN2_S 8
|
#define HP_SYS_CLKRST_REG_FORCE_NORST_TWAI2_S 8
|
||||||
/** HP_SYS_CLKRST_REG_FORCE_NORST_LEDC : R/W; bitpos: [9]; default: 0;
|
/** HP_SYS_CLKRST_REG_FORCE_NORST_LEDC : R/W; bitpos: [9]; default: 0;
|
||||||
* Reserved
|
* Reserved
|
||||||
*/
|
*/
|
||||||
|
@ -2350,18 +2350,18 @@ typedef union {
|
|||||||
* Reserved
|
* Reserved
|
||||||
*/
|
*/
|
||||||
uint32_t reg_rst_en_pwm1:1;
|
uint32_t reg_rst_en_pwm1:1;
|
||||||
/** reg_rst_en_can0 : R/W; bitpos: [26]; default: 0;
|
/** reg_rst_en_twai0 : R/W; bitpos: [26]; default: 0;
|
||||||
* Reserved
|
* Reserved
|
||||||
*/
|
*/
|
||||||
uint32_t reg_rst_en_can0:1;
|
uint32_t reg_rst_en_twai0:1;
|
||||||
/** reg_rst_en_can1 : R/W; bitpos: [27]; default: 0;
|
/** reg_rst_en_twai1 : R/W; bitpos: [27]; default: 0;
|
||||||
* Reserved
|
* Reserved
|
||||||
*/
|
*/
|
||||||
uint32_t reg_rst_en_can1:1;
|
uint32_t reg_rst_en_twai1:1;
|
||||||
/** reg_rst_en_can2 : R/W; bitpos: [28]; default: 0;
|
/** reg_rst_en_twai2 : R/W; bitpos: [28]; default: 0;
|
||||||
* Reserved
|
* Reserved
|
||||||
*/
|
*/
|
||||||
uint32_t reg_rst_en_can2:1;
|
uint32_t reg_rst_en_twai2:1;
|
||||||
/** reg_rst_en_ledc : R/W; bitpos: [29]; default: 0;
|
/** reg_rst_en_ledc : R/W; bitpos: [29]; default: 0;
|
||||||
* Reserved
|
* Reserved
|
||||||
*/
|
*/
|
||||||
@ -2656,18 +2656,18 @@ typedef union {
|
|||||||
* Reserved
|
* Reserved
|
||||||
*/
|
*/
|
||||||
uint32_t reg_force_norst_pwm1:1;
|
uint32_t reg_force_norst_pwm1:1;
|
||||||
/** reg_force_norst_can0 : R/W; bitpos: [6]; default: 0;
|
/** reg_force_norst_twai0 : R/W; bitpos: [6]; default: 0;
|
||||||
* Reserved
|
* Reserved
|
||||||
*/
|
*/
|
||||||
uint32_t reg_force_norst_can0:1;
|
uint32_t reg_force_norst_twai0:1;
|
||||||
/** reg_force_norst_can1 : R/W; bitpos: [7]; default: 0;
|
/** reg_force_norst_twai1 : R/W; bitpos: [7]; default: 0;
|
||||||
* Reserved
|
* Reserved
|
||||||
*/
|
*/
|
||||||
uint32_t reg_force_norst_can1:1;
|
uint32_t reg_force_norst_twai1:1;
|
||||||
/** reg_force_norst_can2 : R/W; bitpos: [8]; default: 0;
|
/** reg_force_norst_twai2 : R/W; bitpos: [8]; default: 0;
|
||||||
* Reserved
|
* Reserved
|
||||||
*/
|
*/
|
||||||
uint32_t reg_force_norst_can2:1;
|
uint32_t reg_force_norst_twai2:1;
|
||||||
/** reg_force_norst_ledc : R/W; bitpos: [9]; default: 0;
|
/** reg_force_norst_ledc : R/W; bitpos: [9]; default: 0;
|
||||||
* Reserved
|
* Reserved
|
||||||
*/
|
*/
|
||||||
|
@ -55,9 +55,9 @@ typedef enum {
|
|||||||
ETS_ADC_INTR_SOURCE,
|
ETS_ADC_INTR_SOURCE,
|
||||||
ETS_PWM0_INTR_SOURCE,
|
ETS_PWM0_INTR_SOURCE,
|
||||||
ETS_PWM1_INTR_SOURCE,
|
ETS_PWM1_INTR_SOURCE,
|
||||||
ETS_CAN0_INTR_SOURCE,
|
ETS_TWAI0_INTR_SOURCE,
|
||||||
ETS_CAN1_INTR_SOURCE,
|
ETS_TWAI1_INTR_SOURCE,
|
||||||
ETS_CAN2_INTR_SOURCE,
|
ETS_TWAI2_INTR_SOURCE,
|
||||||
ETS_RMT_INTR_SOURCE,
|
ETS_RMT_INTR_SOURCE,
|
||||||
ETS_I2C0_INTR_SOURCE,
|
ETS_I2C0_INTR_SOURCE,
|
||||||
ETS_I2C1_INTR_SOURCE,
|
ETS_I2C1_INTR_SOURCE,
|
||||||
|
@ -35,7 +35,7 @@
|
|||||||
#define SOC_GPTIMER_SUPPORTED 1
|
#define SOC_GPTIMER_SUPPORTED 1
|
||||||
#define SOC_PCNT_SUPPORTED 1
|
#define SOC_PCNT_SUPPORTED 1
|
||||||
#define SOC_MCPWM_SUPPORTED 1
|
#define SOC_MCPWM_SUPPORTED 1
|
||||||
// #define SOC_TWAI_SUPPORTED 1 //TODO: IDF-7470
|
#define SOC_TWAI_SUPPORTED 1
|
||||||
#define SOC_ETM_SUPPORTED 1
|
#define SOC_ETM_SUPPORTED 1
|
||||||
#define SOC_PARLIO_SUPPORTED 1 //TODO: IDF-7471
|
#define SOC_PARLIO_SUPPORTED 1 //TODO: IDF-7471
|
||||||
#define SOC_ASYNC_MEMCPY_SUPPORTED 1
|
#define SOC_ASYNC_MEMCPY_SUPPORTED 1
|
||||||
@ -458,7 +458,7 @@
|
|||||||
#define SOC_MWDT_SUPPORT_XTAL (1)
|
#define SOC_MWDT_SUPPORT_XTAL (1)
|
||||||
|
|
||||||
/*-------------------------- TWAI CAPS ---------------------------------------*/
|
/*-------------------------- TWAI CAPS ---------------------------------------*/
|
||||||
#define SOC_TWAI_CONTROLLER_NUM 2
|
#define SOC_TWAI_CONTROLLER_NUM 3
|
||||||
#define SOC_TWAI_CLK_SUPPORT_XTAL 1
|
#define SOC_TWAI_CLK_SUPPORT_XTAL 1
|
||||||
#define SOC_TWAI_BRP_MIN 2
|
#define SOC_TWAI_BRP_MIN 2
|
||||||
#define SOC_TWAI_BRP_MAX 32768
|
#define SOC_TWAI_BRP_MAX 32768
|
||||||
|
@ -434,7 +434,7 @@ typedef union {
|
|||||||
uint32_t reserved_9:23;
|
uint32_t reserved_9:23;
|
||||||
};
|
};
|
||||||
uint32_t val;
|
uint32_t val;
|
||||||
} twai_interrupt_reg_t;
|
} twai_interrupt_status_reg_t;
|
||||||
|
|
||||||
/** Type of interrupt_enable register
|
/** Type of interrupt_enable register
|
||||||
* Interrupt enable register.
|
* Interrupt enable register.
|
||||||
@ -493,214 +493,43 @@ typedef union {
|
|||||||
|
|
||||||
|
|
||||||
/** Group: Data Registers */
|
/** Group: Data Registers */
|
||||||
/** Type of data_0 register
|
/** Type of buffer register
|
||||||
* Data register 0.
|
* TX RX Buffer.
|
||||||
*/
|
*/
|
||||||
typedef union {
|
typedef union {
|
||||||
struct {
|
struct {
|
||||||
/** data_0 : R/W; bitpos: [7:0]; default: 0;
|
/** byte : R/W; bitpos: [7:0]; default: 0;
|
||||||
* In reset mode, it is acceptance code register 0 with R/W Permission. In operation
|
* In reset mode, it is acceptance code register 0 with R/W Permission. In operation
|
||||||
* mode, when software initiate write operation, it is tx data register 0 and when
|
* mode, when software initiate write operation, it is tx data register 0 and when
|
||||||
* software initiate read operation, it is rx data register 0.
|
* software initiate read operation, it is rx data register 0.
|
||||||
*/
|
*/
|
||||||
uint32_t data_0:8;
|
uint32_t byte:8;
|
||||||
uint32_t reserved_8:24;
|
uint32_t reserved_8:24;
|
||||||
};
|
};
|
||||||
uint32_t val;
|
uint32_t val;
|
||||||
} twai_data_0_reg_t;
|
} twai_tx_rx_buffer_reg_t;
|
||||||
|
|
||||||
/** Type of data_1 register
|
|
||||||
* Data register 1.
|
|
||||||
*/
|
|
||||||
typedef union {
|
|
||||||
struct {
|
|
||||||
/** data_1 : R/W; bitpos: [7:0]; default: 0;
|
|
||||||
* In reset mode, it is acceptance code register 1 with R/W Permission. In operation
|
|
||||||
* mode, when software initiate write operation, it is tx data register 1 and when
|
|
||||||
* software initiate read operation, it is rx data register 1.
|
|
||||||
*/
|
|
||||||
uint32_t data_1:8;
|
|
||||||
uint32_t reserved_8:24;
|
|
||||||
};
|
|
||||||
uint32_t val;
|
|
||||||
} twai_data_1_reg_t;
|
|
||||||
|
|
||||||
/** Type of data_2 register
|
|
||||||
* Data register 2.
|
|
||||||
*/
|
|
||||||
typedef union {
|
|
||||||
struct {
|
|
||||||
/** data_2 : R/W; bitpos: [7:0]; default: 0;
|
|
||||||
* In reset mode, it is acceptance code register 2 with R/W Permission. In operation
|
|
||||||
* mode, when software initiate write operation, it is tx data register 2 and when
|
|
||||||
* software initiate read operation, it is rx data register 2.
|
|
||||||
*/
|
|
||||||
uint32_t data_2:8;
|
|
||||||
uint32_t reserved_8:24;
|
|
||||||
};
|
|
||||||
uint32_t val;
|
|
||||||
} twai_data_2_reg_t;
|
|
||||||
|
|
||||||
/** Type of data_3 register
|
|
||||||
* Data register 3.
|
|
||||||
*/
|
|
||||||
typedef union {
|
|
||||||
struct {
|
|
||||||
/** data_3 : R/W; bitpos: [7:0]; default: 0;
|
|
||||||
* In reset mode, it is acceptance code register 3 with R/W Permission. In operation
|
|
||||||
* mode, when software initiate write operation, it is tx data register 3 and when
|
|
||||||
* software initiate read operation, it is rx data register 3.
|
|
||||||
*/
|
|
||||||
uint32_t data_3:8;
|
|
||||||
uint32_t reserved_8:24;
|
|
||||||
};
|
|
||||||
uint32_t val;
|
|
||||||
} twai_data_3_reg_t;
|
|
||||||
|
|
||||||
/** Type of data_4 register
|
|
||||||
* Data register 4.
|
|
||||||
*/
|
|
||||||
typedef union {
|
|
||||||
struct {
|
|
||||||
/** data_4 : R/W; bitpos: [7:0]; default: 0;
|
|
||||||
* In reset mode, it is acceptance mask register 0 with R/W Permission. In operation
|
|
||||||
* mode, when software initiate write operation, it is tx data register 4 and when
|
|
||||||
* software initiate read operation, it is rx data register 4.
|
|
||||||
*/
|
|
||||||
uint32_t data_4:8;
|
|
||||||
uint32_t reserved_8:24;
|
|
||||||
};
|
|
||||||
uint32_t val;
|
|
||||||
} twai_data_4_reg_t;
|
|
||||||
|
|
||||||
/** Type of data_5 register
|
|
||||||
* Data register 5.
|
|
||||||
*/
|
|
||||||
typedef union {
|
|
||||||
struct {
|
|
||||||
/** data_5 : R/W; bitpos: [7:0]; default: 0;
|
|
||||||
* In reset mode, it is acceptance mask register 1 with R/W Permission. In operation
|
|
||||||
* mode, when software initiate write operation, it is tx data register 5 and when
|
|
||||||
* software initiate read operation, it is rx data register 5.
|
|
||||||
*/
|
|
||||||
uint32_t data_5:8;
|
|
||||||
uint32_t reserved_8:24;
|
|
||||||
};
|
|
||||||
uint32_t val;
|
|
||||||
} twai_data_5_reg_t;
|
|
||||||
|
|
||||||
/** Type of data_6 register
|
|
||||||
* Data register 6.
|
|
||||||
*/
|
|
||||||
typedef union {
|
|
||||||
struct {
|
|
||||||
/** data_6 : R/W; bitpos: [7:0]; default: 0;
|
|
||||||
* In reset mode, it is acceptance mask register 2 with R/W Permission. In operation
|
|
||||||
* mode, when software initiate write operation, it is tx data register 6 and when
|
|
||||||
* software initiate read operation, it is rx data register 6.
|
|
||||||
*/
|
|
||||||
uint32_t data_6:8;
|
|
||||||
uint32_t reserved_8:24;
|
|
||||||
};
|
|
||||||
uint32_t val;
|
|
||||||
} twai_data_6_reg_t;
|
|
||||||
|
|
||||||
/** Type of data_7 register
|
|
||||||
* Data register 7.
|
|
||||||
*/
|
|
||||||
typedef union {
|
|
||||||
struct {
|
|
||||||
/** data_7 : R/W; bitpos: [7:0]; default: 0;
|
|
||||||
* In reset mode, it is acceptance mask register 3 with R/W Permission. In operation
|
|
||||||
* mode, when software initiate write operation, it is tx data register 7 and when
|
|
||||||
* software initiate read operation, it is rx data register 7.
|
|
||||||
*/
|
|
||||||
uint32_t data_7:8;
|
|
||||||
uint32_t reserved_8:24;
|
|
||||||
};
|
|
||||||
uint32_t val;
|
|
||||||
} twai_data_7_reg_t;
|
|
||||||
|
|
||||||
/** Type of data_8 register
|
|
||||||
* Data register 8.
|
|
||||||
*/
|
|
||||||
typedef union {
|
|
||||||
struct {
|
|
||||||
/** data_8 : R/W; bitpos: [7:0]; default: 0;
|
|
||||||
* In reset mode, reserved with RO. In operation mode, when software initiate write
|
|
||||||
* operation, it is tx data register 8 and when software initiate read operation, it
|
|
||||||
* is rx data register 8.
|
|
||||||
*/
|
|
||||||
uint32_t data_8:8;
|
|
||||||
uint32_t reserved_8:24;
|
|
||||||
};
|
|
||||||
uint32_t val;
|
|
||||||
} twai_data_8_reg_t;
|
|
||||||
|
|
||||||
/** Type of data_9 register
|
|
||||||
* Data register 9.
|
|
||||||
*/
|
|
||||||
typedef union {
|
|
||||||
struct {
|
|
||||||
/** data_9 : R/W; bitpos: [7:0]; default: 0;
|
|
||||||
* In reset mode, reserved with RO. In operation mode, when software initiate write
|
|
||||||
* operation, it is tx data register 9 and when software initiate read operation, it
|
|
||||||
* is rx data register 9.
|
|
||||||
*/
|
|
||||||
uint32_t data_9:8;
|
|
||||||
uint32_t reserved_8:24;
|
|
||||||
};
|
|
||||||
uint32_t val;
|
|
||||||
} twai_data_9_reg_t;
|
|
||||||
|
|
||||||
/** Type of data_10 register
|
|
||||||
* Data register 10.
|
|
||||||
*/
|
|
||||||
typedef union {
|
|
||||||
struct {
|
|
||||||
/** data_10 : R/W; bitpos: [7:0]; default: 0;
|
|
||||||
* In reset mode, reserved with RO. In operation mode, when software initiate write
|
|
||||||
* operation, it is tx data register 10 and when software initiate read operation, it
|
|
||||||
* is rx data register 10.
|
|
||||||
*/
|
|
||||||
uint32_t data_10:8;
|
|
||||||
uint32_t reserved_8:24;
|
|
||||||
};
|
|
||||||
uint32_t val;
|
|
||||||
} twai_data_10_reg_t;
|
|
||||||
|
|
||||||
/** Type of data_11 register
|
|
||||||
* Data register 11.
|
|
||||||
*/
|
|
||||||
typedef union {
|
|
||||||
struct {
|
|
||||||
/** data_11 : R/W; bitpos: [7:0]; default: 0;
|
|
||||||
* In reset mode, reserved with RO. In operation mode, when software initiate write
|
|
||||||
* operation, it is tx data register 11 and when software initiate read operation, it
|
|
||||||
* is rx data register 11.
|
|
||||||
*/
|
|
||||||
uint32_t data_11:8;
|
|
||||||
uint32_t reserved_8:24;
|
|
||||||
};
|
|
||||||
uint32_t val;
|
|
||||||
} twai_data_11_reg_t;
|
|
||||||
|
|
||||||
/** Type of data_12 register
|
|
||||||
* Data register 12.
|
|
||||||
*/
|
|
||||||
typedef union {
|
|
||||||
struct {
|
|
||||||
/** data_12 : R/W; bitpos: [7:0]; default: 0;
|
|
||||||
* In reset mode, reserved with RO. In operation mode, when software initiate write
|
|
||||||
* operation, it is tx data register 12 and when software initiate read operation, it
|
|
||||||
* is rx data register 12.
|
|
||||||
*/
|
|
||||||
uint32_t data_12:8;
|
|
||||||
uint32_t reserved_8:24;
|
|
||||||
};
|
|
||||||
uint32_t val;
|
|
||||||
} twai_data_12_reg_t;
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
uint32_t byte: 8; /* ACRx[7:0] Acceptance Code */
|
||||||
|
uint32_t reserved8: 24; /* Internal Reserved */
|
||||||
|
};
|
||||||
|
uint32_t val;
|
||||||
|
} acr[4];
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
uint32_t byte: 8; /* AMRx[7:0] Acceptance Mask */
|
||||||
|
uint32_t reserved8: 24; /* Internal Reserved */
|
||||||
|
};
|
||||||
|
uint32_t val;
|
||||||
|
} amr[4];
|
||||||
|
uint32_t reserved_60;
|
||||||
|
uint32_t reserved_64;
|
||||||
|
uint32_t reserved_68;
|
||||||
|
uint32_t reserved_6c;
|
||||||
|
uint32_t reserved_70;
|
||||||
|
} acceptance_filter_reg_t;
|
||||||
|
|
||||||
/** Group: Timestamp Register */
|
/** Group: Timestamp Register */
|
||||||
/** Type of timestamp_data register
|
/** Type of timestamp_data register
|
||||||
@ -749,8 +578,8 @@ typedef struct {
|
|||||||
volatile twai_mode_reg_t mode;
|
volatile twai_mode_reg_t mode;
|
||||||
volatile twai_cmd_reg_t cmd;
|
volatile twai_cmd_reg_t cmd;
|
||||||
volatile twai_status_reg_t status;
|
volatile twai_status_reg_t status;
|
||||||
volatile twai_interrupt_reg_t interrupt;
|
volatile twai_interrupt_status_reg_t interrupt_st;
|
||||||
volatile twai_interrupt_enable_reg_t interrupt_enable;
|
volatile twai_interrupt_enable_reg_t interrupt_ena;
|
||||||
uint32_t reserved_014;
|
uint32_t reserved_014;
|
||||||
volatile twai_bus_timing_0_reg_t bus_timing_0;
|
volatile twai_bus_timing_0_reg_t bus_timing_0;
|
||||||
volatile twai_bus_timing_1_reg_t bus_timing_1;
|
volatile twai_bus_timing_1_reg_t bus_timing_1;
|
||||||
@ -760,19 +589,10 @@ typedef struct {
|
|||||||
volatile twai_err_warning_limit_reg_t err_warning_limit;
|
volatile twai_err_warning_limit_reg_t err_warning_limit;
|
||||||
volatile twai_rx_err_cnt_reg_t rx_err_cnt;
|
volatile twai_rx_err_cnt_reg_t rx_err_cnt;
|
||||||
volatile twai_tx_err_cnt_reg_t tx_err_cnt;
|
volatile twai_tx_err_cnt_reg_t tx_err_cnt;
|
||||||
volatile twai_data_0_reg_t data_0;
|
volatile union {
|
||||||
volatile twai_data_1_reg_t data_1;
|
acceptance_filter_reg_t acceptance_filter;
|
||||||
volatile twai_data_2_reg_t data_2;
|
twai_tx_rx_buffer_reg_t tx_rx_buffer[13];
|
||||||
volatile twai_data_3_reg_t data_3;
|
};
|
||||||
volatile twai_data_4_reg_t data_4;
|
|
||||||
volatile twai_data_5_reg_t data_5;
|
|
||||||
volatile twai_data_6_reg_t data_6;
|
|
||||||
volatile twai_data_7_reg_t data_7;
|
|
||||||
volatile twai_data_8_reg_t data_8;
|
|
||||||
volatile twai_data_9_reg_t data_9;
|
|
||||||
volatile twai_data_10_reg_t data_10;
|
|
||||||
volatile twai_data_11_reg_t data_11;
|
|
||||||
volatile twai_data_12_reg_t data_12;
|
|
||||||
volatile twai_rx_message_counter_reg_t rx_message_counter;
|
volatile twai_rx_message_counter_reg_t rx_message_counter;
|
||||||
uint32_t reserved_078;
|
uint32_t reserved_078;
|
||||||
volatile twai_clock_divider_reg_t clock_divider;
|
volatile twai_clock_divider_reg_t clock_divider;
|
||||||
@ -786,6 +606,9 @@ typedef struct {
|
|||||||
volatile twai_timestamp_cfg_reg_t timestamp_cfg;
|
volatile twai_timestamp_cfg_reg_t timestamp_cfg;
|
||||||
} twai_dev_t;
|
} twai_dev_t;
|
||||||
|
|
||||||
|
extern twai_dev_t TWAI0;
|
||||||
|
extern twai_dev_t TWAI1;
|
||||||
|
extern twai_dev_t TWAI2;
|
||||||
|
|
||||||
#ifndef __cplusplus
|
#ifndef __cplusplus
|
||||||
_Static_assert(sizeof(twai_dev_t) == 0xa0, "Invalid size of twai_dev_t structure");
|
_Static_assert(sizeof(twai_dev_t) == 0xa0, "Invalid size of twai_dev_t structure");
|
||||||
|
@ -47,9 +47,9 @@ const char *const esp_isr_names[] = {
|
|||||||
[ETS_ADC_INTR_SOURCE] = "ADC",
|
[ETS_ADC_INTR_SOURCE] = "ADC",
|
||||||
[ETS_PWM0_INTR_SOURCE] = "PWM0",
|
[ETS_PWM0_INTR_SOURCE] = "PWM0",
|
||||||
[ETS_PWM1_INTR_SOURCE] = "PWM1",
|
[ETS_PWM1_INTR_SOURCE] = "PWM1",
|
||||||
[ETS_CAN0_INTR_SOURCE] = "CAN0",
|
[ETS_TWAI0_INTR_SOURCE] = "TWAI0",
|
||||||
[ETS_CAN1_INTR_SOURCE] = "CAN1",
|
[ETS_TWAI1_INTR_SOURCE] = "TWAI1",
|
||||||
[ETS_CAN2_INTR_SOURCE] = "CAN2",
|
[ETS_TWAI2_INTR_SOURCE] = "TWAI2",
|
||||||
[ETS_RMT_INTR_SOURCE] = "RMT",
|
[ETS_RMT_INTR_SOURCE] = "RMT",
|
||||||
[ETS_I2C0_INTR_SOURCE] = "I2C0",
|
[ETS_I2C0_INTR_SOURCE] = "I2C0",
|
||||||
[ETS_I2C1_INTR_SOURCE] = "I2C1",
|
[ETS_I2C1_INTR_SOURCE] = "I2C1",
|
||||||
|
@ -8,5 +8,33 @@
|
|||||||
#include "soc/gpio_sig_map.h"
|
#include "soc/gpio_sig_map.h"
|
||||||
|
|
||||||
const twai_controller_signal_conn_t twai_controller_periph_signals = {
|
const twai_controller_signal_conn_t twai_controller_periph_signals = {
|
||||||
|
.controllers = {
|
||||||
|
[0] = {
|
||||||
|
.module = PERIPH_TWAI0_MODULE,
|
||||||
|
.irq_id = ETS_TWAI0_INTR_SOURCE,
|
||||||
|
.tx_sig = TWAI0_TX_PAD_OUT_IDX,
|
||||||
|
.rx_sig = TWAI0_RX_PAD_IN_IDX,
|
||||||
|
.bus_off_sig = TWAI0_BUS_OFF_ON_PAD_OUT_IDX,
|
||||||
|
.clk_out_sig = TWAI0_CLKOUT_PAD_OUT_IDX,
|
||||||
|
.stand_by_sig = TWAI0_STANDBY_PAD_OUT_IDX,
|
||||||
|
},
|
||||||
|
[1] = {
|
||||||
|
.module = PERIPH_TWAI1_MODULE,
|
||||||
|
.irq_id = ETS_TWAI1_INTR_SOURCE,
|
||||||
|
.tx_sig = TWAI1_TX_PAD_OUT_IDX,
|
||||||
|
.rx_sig = TWAI1_RX_PAD_IN_IDX,
|
||||||
|
.bus_off_sig = TWAI1_BUS_OFF_ON_PAD_OUT_IDX,
|
||||||
|
.clk_out_sig = TWAI1_CLKOUT_PAD_OUT_IDX,
|
||||||
|
.stand_by_sig = TWAI1_STANDBY_PAD_OUT_IDX,
|
||||||
|
},
|
||||||
|
[2] = {
|
||||||
|
.module = PERIPH_TWAI2_MODULE,
|
||||||
|
.irq_id = ETS_TWAI2_INTR_SOURCE,
|
||||||
|
.tx_sig = TWAI2_TX_PAD_OUT_IDX,
|
||||||
|
.rx_sig = TWAI2_RX_PAD_IN_IDX,
|
||||||
|
.bus_off_sig = TWAI2_BUS_OFF_ON_PAD_OUT_IDX,
|
||||||
|
.clk_out_sig = TWAI2_CLKOUT_PAD_OUT_IDX,
|
||||||
|
.stand_by_sig = TWAI2_STANDBY_PAD_OUT_IDX,
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
@ -82,7 +82,6 @@ api-reference/peripherals/gpio/esp32p4.inc
|
|||||||
api-reference/peripherals/adc_continuous.rst
|
api-reference/peripherals/adc_continuous.rst
|
||||||
api-reference/peripherals/adc_oneshot.rst
|
api-reference/peripherals/adc_oneshot.rst
|
||||||
api-reference/peripherals/usb_host.rst
|
api-reference/peripherals/usb_host.rst
|
||||||
api-reference/peripherals/twai.rst
|
|
||||||
api-reference/peripherals/usb_host/usb_host_notes_arch.rst
|
api-reference/peripherals/usb_host/usb_host_notes_arch.rst
|
||||||
api-reference/peripherals/usb_host/usb_host_notes_index.rst
|
api-reference/peripherals/usb_host/usb_host_notes_index.rst
|
||||||
api-reference/peripherals/usb_host/usb_host_notes_dwc_otg.rst
|
api-reference/peripherals/usb_host/usb_host_notes_dwc_otg.rst
|
||||||
|
@ -164,7 +164,7 @@ The operating bit rate of the TWAI driver is configured using the :cpp:type:`twa
|
|||||||
2. **Timing Segment 1** consists of 1 to 16 time quanta before sample point
|
2. **Timing Segment 1** consists of 1 to 16 time quanta before sample point
|
||||||
3. **Timing Segment 2** consists of 1 to 8 time quanta after sample point
|
3. **Timing Segment 2** consists of 1 to 8 time quanta after sample point
|
||||||
|
|
||||||
{IDF_TARGET_MAX_BRP:default="128", esp32="128", esp32s2="32768", esp32s3="16384", esp32c3="16384", esp32c6="32768", esp32h2="32768"}
|
{IDF_TARGET_MAX_BRP:default="32768", esp32="128", esp32s3="16384", esp32c3="16384"}
|
||||||
|
|
||||||
The **Baudrate Prescaler** is used to determine the period of each time quantum by dividing the TWAI controller's source clock. On the {IDF_TARGET_NAME}, the ``brp`` can be **any even number from 2 to {IDF_TARGET_MAX_BRP}**. Alternatively, you can decide the resolution of each quantum, by setting :cpp:member:`twai_timing_config_t::quanta_resolution_hz` to a non-zero value. In this way, the driver can calculate the underlying ``brp`` value for you. It is useful when you set different clock sources but want the bitrate to keep the same.
|
The **Baudrate Prescaler** is used to determine the period of each time quantum by dividing the TWAI controller's source clock. On the {IDF_TARGET_NAME}, the ``brp`` can be **any even number from 2 to {IDF_TARGET_MAX_BRP}**. Alternatively, you can decide the resolution of each quantum, by setting :cpp:member:`twai_timing_config_t::quanta_resolution_hz` to a non-zero value. In this way, the driver can calculate the underlying ``brp`` value for you. It is useful when you set different clock sources but want the bitrate to keep the same.
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
| Supported Targets | ESP32 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S2 | ESP32-S3 |
|
| Supported Targets | ESP32 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
|
||||||
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- |
|
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- |
|
||||||
|
|
||||||
# TWAI Alert and Recovery Example
|
# TWAI Alert and Recovery Example
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2010-2023 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: CC0-1.0
|
* SPDX-License-Identifier: CC0-1.0
|
||||||
*/
|
*/
|
||||||
@ -26,7 +26,7 @@
|
|||||||
#include "driver/twai.h"
|
#include "driver/twai.h"
|
||||||
#include "esp_rom_gpio.h"
|
#include "esp_rom_gpio.h"
|
||||||
#include "esp_rom_sys.h"
|
#include "esp_rom_sys.h"
|
||||||
#include "soc/gpio_sig_map.h" // For GPIO matrix signal index
|
#include "soc/twai_periph.h" // For GPIO matrix signal index
|
||||||
|
|
||||||
/* --------------------- Definitions and static variables ------------------ */
|
/* --------------------- Definitions and static variables ------------------ */
|
||||||
//Example Configuration
|
//Example Configuration
|
||||||
@ -38,12 +38,6 @@
|
|||||||
#define ERR_PERIOD_US 80 //Approximate time for two bits at 25KBPS
|
#define ERR_PERIOD_US 80 //Approximate time for two bits at 25KBPS
|
||||||
#define EXAMPLE_TAG "TWAI Alert and Recovery"
|
#define EXAMPLE_TAG "TWAI Alert and Recovery"
|
||||||
|
|
||||||
#if CONFIG_IDF_TARGET_ESP32C6
|
|
||||||
#define TWAI_TX_SIGNAL_IDX TWAI0_TX_IDX
|
|
||||||
#else
|
|
||||||
#define TWAI_TX_SIGNAL_IDX TWAI_TX_IDX
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static const twai_filter_config_t f_config = TWAI_FILTER_CONFIG_ACCEPT_ALL();
|
static const twai_filter_config_t f_config = TWAI_FILTER_CONFIG_ACCEPT_ALL();
|
||||||
static const twai_timing_config_t t_config = TWAI_TIMING_CONFIG_25KBITS();
|
static const twai_timing_config_t t_config = TWAI_TIMING_CONFIG_25KBITS();
|
||||||
static const twai_general_config_t g_config = TWAI_GENERAL_CONFIG_DEFAULT(TX_GPIO_NUM, RX_GPIO_NUM, TWAI_MODE_NO_ACK);
|
static const twai_general_config_t g_config = TWAI_GENERAL_CONFIG_DEFAULT(TX_GPIO_NUM, RX_GPIO_NUM, TWAI_MODE_NO_ACK);
|
||||||
@ -54,15 +48,15 @@ static SemaphoreHandle_t ctrl_task_sem;
|
|||||||
static bool trigger_tx_error = false;
|
static bool trigger_tx_error = false;
|
||||||
|
|
||||||
/* --------------------------- Tasks and Functions -------------------------- */
|
/* --------------------------- Tasks and Functions -------------------------- */
|
||||||
|
extern const twai_controller_signal_conn_t twai_controller_periph_signals;
|
||||||
static void invert_tx_bits(bool enable)
|
static void invert_tx_bits(bool enable)
|
||||||
{
|
{
|
||||||
if (enable) {
|
if (enable) {
|
||||||
//Inverts output of TX to trigger errors
|
//Inverts output of TX to trigger errors
|
||||||
esp_rom_gpio_connect_out_signal(TX_GPIO_NUM, TWAI_TX_SIGNAL_IDX, true, false);
|
esp_rom_gpio_connect_out_signal(TX_GPIO_NUM, twai_controller_periph_signals.controllers[0].tx_sig, true, false);
|
||||||
} else {
|
} else {
|
||||||
//Returns TX to default settings
|
//Returns TX to default settings
|
||||||
esp_rom_gpio_connect_out_signal(TX_GPIO_NUM, TWAI_TX_SIGNAL_IDX, false, false);
|
esp_rom_gpio_connect_out_signal(TX_GPIO_NUM, twai_controller_periph_signals.controllers[0].tx_sig, false, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
| Supported Targets | ESP32 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S2 | ESP32-S3 |
|
| Supported Targets | ESP32 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
|
||||||
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- |
|
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- |
|
||||||
|
|
||||||
# TWAI Network Example
|
# TWAI Network Example
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
| Supported Targets | ESP32 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S2 | ESP32-S3 |
|
| Supported Targets | ESP32 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
|
||||||
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- |
|
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- |
|
||||||
|
|
||||||
# TWAI Self Test Example
|
# TWAI Self Test Example
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user