twai: bringup on esp32c6

This commit is contained in:
morris
2022-10-19 17:40:32 +08:00
parent 6828c011d9
commit a25123f703
35 changed files with 1521 additions and 261 deletions

View File

@@ -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;