mirror of
https://github.com/espressif/esp-idf.git
synced 2025-11-22 03:13:45 +00:00
twai: bringup on esp32c6
This commit is contained in:
@@ -14,18 +14,24 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "hal/misc.h"
|
||||
#include "hal/assert.h"
|
||||
#include "hal/twai_types.h"
|
||||
#include "soc/twai_periph.h"
|
||||
#include "soc/twai_struct.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
|
||||
|
||||
/* ------------------------- Defines and Typedefs --------------------------- */
|
||||
|
||||
#define TWAI_LL_STATUS_RBS (0x1 << 0) //Receive Buffer Status
|
||||
@@ -143,6 +149,33 @@ typedef enum {
|
||||
} twai_ll_err_seg_t;
|
||||
#endif
|
||||
|
||||
/* ---------------------------- Peripheral Control Register ----------------- */
|
||||
|
||||
/**
|
||||
* @brief Enable TWAI module clock
|
||||
*
|
||||
* @param hw Start address of the TWAI registers
|
||||
* @param en true to enable, false to disable
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline void twai_ll_enable_clock(twai_dev_t *hw, bool en)
|
||||
{
|
||||
(void)hw;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set clock source for TWAI module
|
||||
*
|
||||
* @param hw Start address of the TWAI registers
|
||||
* @param clk_src Clock source
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline void twai_ll_set_clock_source(twai_dev_t *hw, twai_clock_source_t clk_src)
|
||||
{
|
||||
(void)hw;
|
||||
HAL_ASSERT(clk_src == TWAI_CLK_SRC_APB);
|
||||
}
|
||||
|
||||
/* ---------------------------- Mode Register ------------------------------- */
|
||||
|
||||
/**
|
||||
@@ -156,6 +189,7 @@ typedef enum {
|
||||
*
|
||||
* @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_reg.rm = 1;
|
||||
@@ -172,6 +206,7 @@ static inline void twai_ll_enter_reset_mode(twai_dev_t *hw)
|
||||
*
|
||||
* @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_reg.rm = 0;
|
||||
@@ -182,6 +217,7 @@ static inline void twai_ll_exit_reset_mode(twai_dev_t *hw)
|
||||
* @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_reg.rm;
|
||||
@@ -195,6 +231,7 @@ 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)
|
||||
{
|
||||
if (mode == TWAI_MODE_NORMAL) { //Normal Operating mode
|
||||
@@ -224,6 +261,7 @@ static inline void twai_ll_set_mode(twai_dev_t *hw, twai_mode_t mode)
|
||||
* 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->command_reg.tr = 1;
|
||||
@@ -241,6 +279,7 @@ static inline void twai_ll_set_cmd_tx(twai_dev_t *hw)
|
||||
* 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->command_reg.val = 0x03; //Writing to TR and AT simultaneously
|
||||
@@ -260,6 +299,7 @@ static inline void twai_ll_set_cmd_tx_single_shot(twai_dev_t *hw)
|
||||
* 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->command_reg.at = 1;
|
||||
@@ -272,6 +312,7 @@ static inline void twai_ll_set_cmd_abort_tx(twai_dev_t *hw)
|
||||
*
|
||||
* @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->command_reg.rrb = 1;
|
||||
@@ -284,6 +325,7 @@ static inline void twai_ll_set_cmd_release_rx_buffer(twai_dev_t *hw)
|
||||
*
|
||||
* @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->command_reg.cdo = 1;
|
||||
@@ -303,6 +345,7 @@ static inline void twai_ll_set_cmd_clear_data_overrun(twai_dev_t *hw)
|
||||
* 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->command_reg.srr = 1;
|
||||
@@ -321,6 +364,7 @@ static inline void twai_ll_set_cmd_self_rx_request(twai_dev_t *hw)
|
||||
* 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->command_reg.val = 0x12;
|
||||
@@ -334,6 +378,7 @@ static inline void twai_ll_set_cmd_self_rx_single_shot(twai_dev_t *hw)
|
||||
* @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_reg.val;
|
||||
@@ -345,6 +390,7 @@ static inline uint32_t twai_ll_get_status(twai_dev_t *hw)
|
||||
* @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;
|
||||
@@ -356,6 +402,7 @@ static inline bool twai_ll_is_fifo_overrun(twai_dev_t *hw)
|
||||
* @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;
|
||||
@@ -372,6 +419,7 @@ static inline bool twai_ll_is_last_tx_successful(twai_dev_t *hw)
|
||||
* @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_reg.val;
|
||||
@@ -387,6 +435,7 @@ static inline uint32_t twai_ll_get_and_clear_intrs(twai_dev_t *hw)
|
||||
*
|
||||
* @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)
|
||||
{
|
||||
#if SOC_TWAI_BRP_DIV_SUPPORTED
|
||||
@@ -399,6 +448,25 @@ static inline void twai_ll_set_enabled_intrs(twai_dev_t *hw, uint32_t 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);
|
||||
if (brp > TWAI_LL_BRP_DIV_THRESH) {
|
||||
// should be multiple of 4
|
||||
valid = valid && !(brp & 0x03);
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set bus timing
|
||||
*
|
||||
@@ -413,10 +481,11 @@ static inline void twai_ll_set_enabled_intrs(twai_dev_t *hw, uint32_t intr_mask)
|
||||
* @note ESP32 rev 2 or later can support a x2 brp by setting a brp_div bit,
|
||||
* allowing the brp to go from a maximum of 128 to 256.
|
||||
*/
|
||||
__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 > SOC_TWAI_BRP_DIV_THRESH) {
|
||||
if (brp > TWAI_LL_BRP_DIV_THRESH) {
|
||||
//Need to set brp_div bit
|
||||
hw->interrupt_enable_reg.brp_div = 1;
|
||||
brp /= 2;
|
||||
@@ -440,6 +509,7 @@ static inline void twai_ll_set_bus_timing(twai_dev_t *hw, uint32_t brp, uint32_t
|
||||
*
|
||||
* @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->arbitration_lost_captue_reg.val;
|
||||
@@ -454,6 +524,7 @@ static inline void twai_ll_clear_arb_lost_cap(twai_dev_t *hw)
|
||||
*
|
||||
* @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;
|
||||
@@ -482,6 +553,7 @@ static inline void twai_ll_parse_err_code_cap(twai_dev_t *hw,
|
||||
*
|
||||
* @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->error_warning_limit_reg, ewl, ewl);
|
||||
@@ -493,6 +565,7 @@ static inline void twai_ll_set_err_warn_lim(twai_dev_t *hw, uint32_t ewl)
|
||||
* @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->error_warning_limit_reg.val;
|
||||
@@ -509,6 +582,7 @@ static inline uint32_t twai_ll_get_err_warn_lim(twai_dev_t *hw)
|
||||
* @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_error_counter_reg.val;
|
||||
@@ -522,6 +596,7 @@ static inline uint32_t twai_ll_get_rec(twai_dev_t *hw)
|
||||
*
|
||||
* @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_error_counter_reg, rxerr, rec);
|
||||
@@ -537,6 +612,7 @@ static inline void twai_ll_set_rec(twai_dev_t *hw, uint32_t rec)
|
||||
*
|
||||
* @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_error_counter_reg.val;
|
||||
@@ -550,6 +626,7 @@ static inline uint32_t twai_ll_get_tec(twai_dev_t *hw)
|
||||
*
|
||||
* @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_error_counter_reg, txerr, tec);
|
||||
@@ -566,7 +643,8 @@ static inline void twai_ll_set_tec(twai_dev_t *hw, uint32_t tec)
|
||||
*
|
||||
* @note Must be called in reset mode
|
||||
*/
|
||||
static inline void twai_ll_set_acc_filter(twai_dev_t* hw, uint32_t code, uint32_t mask, bool single_filter)
|
||||
__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);
|
||||
@@ -587,6 +665,7 @@ static inline void twai_ll_set_acc_filter(twai_dev_t* hw, uint32_t code, uint32_
|
||||
*
|
||||
* @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
|
||||
@@ -603,6 +682,7 @@ static inline void twai_ll_set_tx_buffer(twai_dev_t *hw, twai_ll_frame_buffer_t
|
||||
*
|
||||
* @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
|
||||
@@ -626,6 +706,7 @@ static inline void twai_ll_get_rx_buffer(twai_dev_t *hw, twai_ll_frame_buffer_t
|
||||
* @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)
|
||||
{
|
||||
@@ -669,6 +750,7 @@ static inline void twai_ll_format_frame_buffer(uint32_t id, uint8_t dlc, const u
|
||||
* @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)
|
||||
{
|
||||
@@ -717,6 +799,7 @@ static inline void twai_ll_parse_frame_buffer(twai_ll_frame_buffer_t *rx_frame,
|
||||
* @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_reg.val;
|
||||
@@ -733,6 +816,7 @@ static inline uint32_t twai_ll_get_rx_msg_count(twai_dev_t *hw)
|
||||
* @param hw Start address of the TWAI registers
|
||||
* @param divider Divider for CLKOUT. 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 <= 14) {
|
||||
@@ -759,6 +843,7 @@ static inline void twai_ll_set_clkout(twai_dev_t *hw, uint32_t divider)
|
||||
* @note Must be called before setting any configuration
|
||||
* @note Must be called in reset mode
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline void twai_ll_enable_extended_reg_layout(twai_dev_t *hw)
|
||||
{
|
||||
hw->clock_divider_reg.cm = 1;
|
||||
@@ -779,6 +864,7 @@ static inline void twai_ll_enable_extended_reg_layout(twai_dev_t *hw)
|
||||
* @note Some registers are cleared on entering reset mode so must be saved
|
||||
* separate from this function.
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline void twai_ll_save_reg(twai_dev_t *hw, twai_ll_reg_save_t *reg_save)
|
||||
{
|
||||
reg_save->mode_reg = (uint8_t) hw->mode_reg.val;
|
||||
@@ -806,6 +892,7 @@ static inline void twai_ll_save_reg(twai_dev_t *hw, twai_ll_reg_save_t *reg_save
|
||||
* @note Must be called in reset mode so that config registers become accessible
|
||||
* @note Some registers are read only thus cannot be restored
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline void twai_ll_restore_reg(twai_dev_t *hw, twai_ll_reg_save_t *reg_save)
|
||||
{
|
||||
hw->mode_reg.val = reg_save->mode_reg;
|
||||
|
||||
Reference in New Issue
Block a user