mirror of
https://github.com/espressif/esp-idf.git
synced 2025-09-21 00:30:34 +00:00
feat(driver_twai): support legacy targets in new driver
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -18,23 +18,31 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include "esp_assert.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "hal/misc.h"
|
||||
#include "hal/assert.h"
|
||||
#include "hal/twai_types.h"
|
||||
#include "hal/efuse_hal.h"
|
||||
#include "soc/chip_revision.h"
|
||||
#include "soc/twai_periph.h"
|
||||
#include "soc/twai_struct.h"
|
||||
#include "soc/dport_reg.h"
|
||||
|
||||
#define TWAI_LL_GET_HW(controller_id) ((controller_id == 0) ? (&TWAI) : NULL)
|
||||
|
||||
#define TWAI_LL_BRP_DIV_THRESH 128
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
static uint32_t twai_ll_get_brp_max(void);
|
||||
/* ------------------------- Defines and Typedefs --------------------------- */
|
||||
#define TWAI_LL_BRP_MIN 2
|
||||
#define TWAI_LL_BRP_MAX twai_ll_get_brp_max() // max brp of esp32 is depends on chip version
|
||||
#define TWAI_LL_TSEG1_MIN 1
|
||||
#define TWAI_LL_TSEG2_MIN 1
|
||||
#define TWAI_LL_TSEG1_MAX 16 //the max register value
|
||||
#define TWAI_LL_TSEG2_MAX 8
|
||||
#define TWAI_LL_SJW_MAX 4
|
||||
|
||||
#define TWAI_LL_STATUS_RBS (0x1 << 0) //Receive Buffer Status
|
||||
#define TWAI_LL_STATUS_DOS (0x1 << 1) //Data Overrun Status
|
||||
@@ -53,6 +61,9 @@ extern "C" {
|
||||
#define TWAI_LL_INTR_ALI (0x1 << 6) //Arbitration Lost Interrupt
|
||||
#define TWAI_LL_INTR_BEI (0x1 << 7) //Bus Error Interrupt
|
||||
|
||||
#define TWAI_LL_DRIVER_INTERRUPTS (TWAI_LL_INTR_RI | TWAI_LL_INTR_TI | TWAI_LL_INTR_EI | \
|
||||
TWAI_LL_INTR_EPI | TWAI_LL_INTR_ALI | TWAI_LL_INTR_BEI)
|
||||
|
||||
/*
|
||||
* 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
|
||||
@@ -61,7 +72,7 @@ extern "C" {
|
||||
* 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 {
|
||||
typedef union twai_ll_frame_buffer_t {
|
||||
struct {
|
||||
struct {
|
||||
uint8_t dlc: 4; //Data length code (0 to 8) of the frame
|
||||
@@ -87,7 +98,6 @@ typedef union {
|
||||
|
||||
ESP_STATIC_ASSERT(sizeof(twai_ll_frame_buffer_t) == 13, "TX/RX buffer type should be 13 bytes");
|
||||
|
||||
#if defined(CONFIG_TWAI_ERRATA_FIX_RX_FRAME_INVALID) || defined(CONFIG_TWAI_ERRATA_FIX_RX_FIFO_CORRUPT)
|
||||
/**
|
||||
* Some errata workarounds will require a hardware reset of the peripheral. Thus
|
||||
* certain registers must be saved before the reset, and then restored after the
|
||||
@@ -105,9 +115,7 @@ typedef struct {
|
||||
uint8_t tx_error_counter_reg;
|
||||
uint8_t clock_divider_reg;
|
||||
} __attribute__((packed)) twai_ll_reg_save_t;
|
||||
#endif //defined(CONFIG_TWAI_ERRATA_FIX_RX_FRAME_INVALID) || defined(CONFIG_TWAI_ERRATA_FIX_RX_FIFO_CORRUPT)
|
||||
|
||||
#ifdef CONFIG_TWAI_ERRATA_FIX_RX_FRAME_INVALID
|
||||
typedef enum {
|
||||
TWAI_LL_ERR_BIT = 0,
|
||||
TWAI_LL_ERR_FORM,
|
||||
@@ -123,7 +131,7 @@ typedef enum {
|
||||
} twai_ll_err_dir_t;
|
||||
|
||||
typedef enum {
|
||||
TWAI_LL_ERR_SEG_SOF = 0,
|
||||
TWAI_LL_ERR_SEG_SOF = 3,
|
||||
TWAI_LL_ERR_SEG_ID_28_21 = 2,
|
||||
TWAI_LL_ERR_SEG_SRTR = 4,
|
||||
TWAI_LL_ERR_SEG_IDE = 5,
|
||||
@@ -149,7 +157,6 @@ typedef enum {
|
||||
TWAI_LL_ERR_SEG_OVRLD_FLAG = 28,
|
||||
TWAI_LL_ERR_SEG_MAX = 29,
|
||||
} twai_ll_err_seg_t;
|
||||
#endif
|
||||
|
||||
/* ---------------------------- Reset and Clock Control ------------------------------ */
|
||||
|
||||
@@ -272,18 +279,10 @@ static inline bool twai_ll_is_in_reset_mode(twai_dev_t *hw)
|
||||
* @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)
|
||||
static inline void twai_ll_set_mode(twai_dev_t *hw, bool listen_only, bool no_ack, bool loopback)
|
||||
{
|
||||
if (mode == TWAI_MODE_NORMAL) { //Normal Operating mode
|
||||
hw->mode_reg.lom = 0;
|
||||
hw->mode_reg.stm = 0;
|
||||
} else if (mode == TWAI_MODE_NO_ACK) { //Self Test Mode (No Ack)
|
||||
hw->mode_reg.lom = 0;
|
||||
hw->mode_reg.stm = 1;
|
||||
} else if (mode == TWAI_MODE_LISTEN_ONLY) { //Listen Only Mode
|
||||
hw->mode_reg.lom = 1;
|
||||
hw->mode_reg.stm = 0;
|
||||
}
|
||||
hw->mode_reg.lom = listen_only;
|
||||
hw->mode_reg.stm = no_ack;
|
||||
}
|
||||
|
||||
/* --------------------------- Command Register ----------------------------- */
|
||||
@@ -424,30 +423,6 @@ static inline uint32_t twai_ll_get_status(twai_dev_t *hw)
|
||||
return hw->status_reg.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_reg.dos;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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_reg.tcs;
|
||||
}
|
||||
|
||||
/* -------------------------- Interrupt Register ---------------------------- */
|
||||
|
||||
/**
|
||||
@@ -478,16 +453,27 @@ static inline uint32_t twai_ll_get_and_clear_intrs(twai_dev_t *hw)
|
||||
__attribute__((always_inline))
|
||||
static inline void twai_ll_set_enabled_intrs(twai_dev_t *hw, uint32_t intr_mask)
|
||||
{
|
||||
#if SOC_TWAI_BRP_DIV_SUPPORTED
|
||||
//ESP32 Rev 2 or later has brp div field. Need to mask it out
|
||||
hw->interrupt_enable_reg.val = (hw->interrupt_enable_reg.val & 0x10) | intr_mask;
|
||||
#else
|
||||
hw->interrupt_enable_reg.val = intr_mask;
|
||||
#endif
|
||||
if (ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 200)) {
|
||||
//ESP32 Rev 2 or later has brp div field. Need to mask it out
|
||||
hw->interrupt_enable_reg.val = (hw->interrupt_enable_reg.val & 0x10) | intr_mask;
|
||||
} else {
|
||||
hw->interrupt_enable_reg.val = intr_mask;
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------ Bus Timing Registers --------------------------- */
|
||||
|
||||
/**
|
||||
* @brief Get the hardware bitrate prediv max value
|
||||
*
|
||||
* @return Max brp value
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline uint32_t twai_ll_get_brp_max(void)
|
||||
{
|
||||
return ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 200) ? 256 : 128;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if the brp value valid
|
||||
*
|
||||
@@ -497,7 +483,7 @@ static inline void twai_ll_set_enabled_intrs(twai_dev_t *hw, uint32_t intr_mask)
|
||||
__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);
|
||||
bool valid = (brp >= TWAI_LL_BRP_MIN) && (brp <= TWAI_LL_BRP_MAX);
|
||||
// should be an even number
|
||||
valid = valid && !(brp & 0x01);
|
||||
if (brp > TWAI_LL_BRP_DIV_THRESH) {
|
||||
@@ -524,15 +510,15 @@ static inline bool twai_ll_check_brp_validation(uint32_t brp)
|
||||
__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)
|
||||
{
|
||||
#if SOC_TWAI_BRP_DIV_SUPPORTED
|
||||
if (brp > TWAI_LL_BRP_DIV_THRESH) {
|
||||
//Need to set brp_div bit
|
||||
hw->interrupt_enable_reg.brp_div = 1;
|
||||
brp /= 2;
|
||||
} else {
|
||||
hw->interrupt_enable_reg.brp_div = 0;
|
||||
if (ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 200)) {
|
||||
if (brp > TWAI_LL_BRP_DIV_THRESH) {
|
||||
//Need to set brp_div bit
|
||||
hw->interrupt_enable_reg.brp_div = 1;
|
||||
brp /= 2;
|
||||
} else {
|
||||
hw->interrupt_enable_reg.brp_div = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
hw->bus_timing_0_reg.brp = (brp / 2) - 1;
|
||||
hw->bus_timing_0_reg.sjw = sjw - 1;
|
||||
hw->bus_timing_1_reg.tseg1 = tseg1 - 1;
|
||||
@@ -558,30 +544,20 @@ static inline void twai_ll_clear_arb_lost_cap(twai_dev_t *hw)
|
||||
/* ----------------------------- ECC Register ------------------------------- */
|
||||
|
||||
/**
|
||||
* @brief Clear Error Code Capture register
|
||||
* @brief Parse 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->error_code_capture_reg.val;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_TWAI_ERRATA_FIX_RX_FRAME_INVALID
|
||||
static inline void twai_ll_parse_err_code_cap(twai_dev_t *hw,
|
||||
twai_ll_err_type_t *type,
|
||||
twai_ll_err_dir_t *dir,
|
||||
twai_ll_err_seg_t *seg)
|
||||
static inline void twai_ll_parse_err_code_cap(twai_dev_t *hw, twai_ll_err_type_t *type, twai_ll_err_dir_t *dir, twai_ll_err_seg_t *seg)
|
||||
{
|
||||
uint32_t ecc = hw->error_code_capture_reg.val;
|
||||
*type = (twai_ll_err_type_t) ((ecc >> 6) & 0x3);
|
||||
*dir = (twai_ll_err_dir_t) ((ecc >> 5) & 0x1);
|
||||
*seg = (twai_ll_err_seg_t) (ecc & 0x1F);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* ----------------------------- EWL Register ------------------------------- */
|
||||
|
||||
@@ -781,6 +757,18 @@ static inline void twai_ll_format_frame_buffer(uint32_t id, uint8_t dlc, const u
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if the message in twai_ll_frame_buffer is extend id format or not
|
||||
*
|
||||
* @param rx_frame The rx_frame in twai_ll_frame_buffer_t type
|
||||
* @return true if the message is extend id format, false if not
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline bool twai_ll_frame_is_ext_format(twai_ll_frame_buffer_t *rx_frame)
|
||||
{
|
||||
return rx_frame->frame_format;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Parse formatted TWAI frame (RX Buffer Layout) into its constituent contents
|
||||
*
|
||||
@@ -792,7 +780,7 @@ static inline void twai_ll_format_frame_buffer(uint32_t id, uint8_t dlc, const u
|
||||
*/
|
||||
__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)
|
||||
uint8_t *data, uint32_t buf_sz, uint32_t *flags)
|
||||
{
|
||||
//Copy frame information
|
||||
*dlc = rx_frame->dlc;
|
||||
@@ -822,13 +810,10 @@ static inline void twai_ll_parse_frame_buffer(twai_ll_frame_buffer_t *rx_frame,
|
||||
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);
|
||||
data_length = (data_length < buf_sz) ? data_length : buf_sz;
|
||||
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 ------------------------ */
|
||||
@@ -891,7 +876,6 @@ static inline void twai_ll_enable_extended_reg_layout(twai_dev_t *hw)
|
||||
|
||||
/* ------------------------- Register Save/Restore -------------------------- */
|
||||
|
||||
#if defined(CONFIG_TWAI_ERRATA_FIX_RX_FRAME_INVALID) || defined(CONFIG_TWAI_ERRATA_FIX_RX_FIFO_CORRUPT)
|
||||
/**
|
||||
* @brief Saves the current values of the TWAI controller's registers
|
||||
*
|
||||
@@ -948,7 +932,6 @@ static inline void twai_ll_restore_reg(twai_dev_t *hw, twai_ll_reg_save_t *reg_s
|
||||
hw->tx_error_counter_reg.val = reg_save->tx_error_counter_reg;
|
||||
hw->clock_divider_reg.val = reg_save->clock_divider_reg;
|
||||
}
|
||||
#endif //defined(CONFIG_TWAI_ERRATA_FIX_RX_FRAME_INVALID) || defined(CONFIG_TWAI_ERRATA_FIX_RX_FIFO_CORRUPT)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
Reference in New Issue
Block a user