TWAI: bringup for S3 and C3

This commit is contained in:
Marius Vikhammer 2021-01-14 10:44:59 +08:00
parent 19d92ef6b2
commit 0713e93b8f
18 changed files with 341 additions and 191 deletions

View File

@ -19,6 +19,7 @@ set(srcs
"spi_slave.c"
"spi_bus_lock.c"
"timer.c"
"twai.c"
"uart.c")
set(includes "include" "${target}/include")
@ -32,7 +33,6 @@ if(${target} STREQUAL "esp32")
"sdmmc_host.c"
"sdmmc_transaction.c"
"touch_sensor_common.c"
"twai.c"
"esp32/touch_sensor.c"
"esp32/adc.c"
"esp32/dac.c")
@ -45,7 +45,6 @@ if(IDF_TARGET STREQUAL "esp32s2")
"dedic_gpio.c"
"spi_slave_hd.c"
"touch_sensor_common.c"
"twai.c"
"esp32s2/rtc_tempsensor.c"
"esp32s2/touch_sensor.c"
"esp32s2/adc.c"
@ -61,7 +60,6 @@ if(${target} STREQUAL "esp32s3")
"gdma.c"
"spi_slave_hd.c"
"touch_sensor_common.c"
"twai.c"
)
endif()

View File

@ -24,6 +24,7 @@ PROVIDE ( TIMERG1 = 0x60020000 );
PROVIDE ( GPSPI2 = 0x60024000 );
PROVIDE ( GPSPI3 = 0x60025000 );
PROVIDE ( SYSCON = 0x60026000 );
PROVIDE ( TWAI = 0x6002B000 );
PROVIDE ( GPSPI4 = 0x60037000 );
PROVIDE ( APB_SARADC = 0x60040000 );
PROVIDE ( GDMA = 0x6003F000 );

View File

@ -26,6 +26,7 @@ PROVIDE ( GPSPI2 = 0x60024000 );
PROVIDE ( GPSPI3 = 0x60025000 );
PROVIDE ( SYSCON = 0x60026000 );
PROVIDE ( I2C1 = 0x60027000 );
PROVIDE ( TWAI = 0x6002B000 );
PROVIDE ( GPSPI4 = 0x60037000 );
PROVIDE ( GDMA = 0x6003F000 );
PROVIDE ( UART2 = 0x60010000 );

View File

@ -28,7 +28,9 @@ if(NOT BOOTLOADER_BUILD)
"soc_hal.c"
"interrupt_controller_hal.c"
"sha_hal.c"
"aes_hal.c")
"aes_hal.c"
"twai_hal.c"
"twai_hal_iram.c")
if(${target} STREQUAL "esp32")
list(APPEND srcs
@ -38,8 +40,6 @@ if(NOT BOOTLOADER_BUILD)
"pcnt_hal.c"
"sdio_slave_hal.c"
"touch_sensor_hal.c"
"twai_hal.c"
"twai_hal_iram.c"
"esp32/adc_hal.c"
"esp32/brownout_hal.c"
"esp32/interrupt_descriptor_table.c"
@ -57,8 +57,6 @@ if(NOT BOOTLOADER_BUILD)
"spi_flash_hal_gpspi.c"
"spi_slave_hd_hal.c"
"touch_sensor_hal.c"
"twai_hal.c"
"twai_hal_iram.c"
"esp32s2/adc_hal.c"
"esp32s2/brownout_hal.c"
"esp32s2/cp_dma_hal.c"
@ -78,8 +76,6 @@ if(NOT BOOTLOADER_BUILD)
"spi_flash_hal_gpspi.c"
"spi_slave_hd_hal.c"
"touch_sensor_hal.c"
"twai_hal.c"
"twai_hal_iram.c"
"esp32s3/brownout_hal.c"
"esp32s3/interrupt_descriptor_table.c"
"esp32s3/systimer_hal.c"

View File

@ -1,4 +1,4 @@
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
// Copyright 2021 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@ -15,7 +15,7 @@
/*******************************************************************************
* NOTICE
* The ll is not public api, don't use in application code.
* See readme.md in soc/include/hal/readme.md
* See readme.md in hal/include/hal/readme.md
******************************************************************************/
// The Lowlevel layer for TWAI
@ -33,22 +33,22 @@ extern "C" {
/* ------------------------- Defines and Typedefs --------------------------- */
#define TWAI_LL_STATUS_RBS (0x1 << 0)
#define TWAI_LL_STATUS_DOS (0x1 << 1)
#define TWAI_LL_STATUS_TBS (0x1 << 2)
#define TWAI_LL_STATUS_TCS (0x1 << 3)
#define TWAI_LL_STATUS_RS (0x1 << 4)
#define TWAI_LL_STATUS_TS (0x1 << 5)
#define TWAI_LL_STATUS_ES (0x1 << 6)
#define TWAI_LL_STATUS_BS (0x1 << 7)
#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_INTR_RI (0x1 << 0)
#define TWAI_LL_INTR_TI (0x1 << 1)
#define TWAI_LL_INTR_EI (0x1 << 2)
#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)
#define TWAI_LL_INTR_ALI (0x1 << 6)
#define TWAI_LL_INTR_BEI (0x1 << 7)
#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
/*
* The following frame structure has an NEARLY identical bit field layout to
@ -82,6 +82,8 @@ typedef union {
uint8_t bytes[13];
} __attribute__((packed)) twai_ll_frame_buffer_t;
_Static_assert(sizeof(twai_ll_frame_buffer_t) == 13, "TX/RX buffer type should be 13 bytes");
/* ---------------------------- Mode Register ------------------------------- */
/**
@ -92,14 +94,12 @@ typedef union {
* in order to write the majority of configuration registers.
*
* @param hw Start address of the TWAI registers
* @return true if reset mode was entered successfully
*
* @note Reset mode is automatically entered on BUS OFF condition
*/
static inline bool twai_ll_enter_reset_mode(twai_dev_t *hw)
static inline void twai_ll_enter_reset_mode(twai_dev_t *hw)
{
hw->mode_reg.rm = 1;
return hw->mode_reg.rm;
}
/**
@ -110,14 +110,12 @@ static inline bool twai_ll_enter_reset_mode(twai_dev_t *hw)
* operating mode.
*
* @param hw Start address of the TWAI registers
* @return true if reset mode was exit successfully
*
* @note Reset mode must be exit to initiate BUS OFF recovery
*/
static inline bool twai_ll_exit_reset_mode(twai_dev_t *hw)
static inline void twai_ll_exit_reset_mode(twai_dev_t *hw)
{
hw->mode_reg.rm = 0;
return !(hw->mode_reg.rm);
}
/**
@ -186,7 +184,7 @@ static inline void twai_ll_set_cmd_tx(twai_dev_t *hw)
*/
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
hw->command_reg.val = 0x03; //Set command_reg.tr and command_reg.at simultaneously for single shot transmittion request
}
/**
@ -266,7 +264,7 @@ static inline void twai_ll_set_cmd_self_rx_request(twai_dev_t *hw)
*/
static inline void twai_ll_set_cmd_self_rx_single_shot(twai_dev_t *hw)
{
hw->command_reg.val = 0x12;
hw->command_reg.val = 0x12; //Set command_reg.srr and command_reg.at simultaneously for single shot self reception request
}
/* --------------------------- Status Register ------------------------------ */
@ -304,8 +302,6 @@ static inline bool twai_ll_is_last_tx_successful(twai_dev_t *hw)
return hw->status_reg.tcs;
}
//Todo: Add stand alone status bit check functions when necessary
/* -------------------------- Interrupt Register ---------------------------- */
/**
@ -334,12 +330,7 @@ static inline uint32_t twai_ll_get_and_clear_intrs(twai_dev_t *hw)
*/
static inline void twai_ll_set_enabled_intrs(twai_dev_t *hw, uint32_t intr_mask)
{
#ifdef TWAI_BRP_DIV_SUPPORTED
//ESP32 Rev 2 has brp div. Need to mask when setting
hw->interrupt_enable_reg.val = (hw->interrupt_enable_reg.val & 0x10) | intr_mask;
#else
hw->interrupt_enable_reg.val = intr_mask;
#endif
}
/* ------------------------ Bus Timing Registers --------------------------- */
@ -355,18 +346,10 @@ static inline void twai_ll_set_enabled_intrs(twai_dev_t *hw, uint32_t intr_mask)
* @param triple_sampling Triple Sampling enable/disable
*
* @note Must be called in reset mode
* @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.
* @note ESP32C3 brp can be any even number between 2 to 32768
*/
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)
{
#ifdef TWAI_BRP_DIV_SUPPORTED
if (brp > TWAI_BRP_DIV_THRESH) {
//Need to set brp_div bit
hw->interrupt_enable_reg.brp_div = 1;
brp /= 2;
}
#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;
@ -386,7 +369,6 @@ static inline void twai_ll_set_bus_timing(twai_dev_t *hw, uint32_t brp, uint32_t
static inline void twai_ll_clear_arb_lost_cap(twai_dev_t *hw)
{
(void)hw->arbitration_lost_captue_reg.val;
//Todo: Decode ALC register
}
/* ----------------------------- ECC Register ------------------------------- */
@ -401,7 +383,6 @@ static inline void twai_ll_clear_arb_lost_cap(twai_dev_t *hw)
static inline void twai_ll_clear_err_code_cap(twai_dev_t *hw)
{
(void)hw->error_code_capture_reg.val;
//Todo: Decode error code capture
}
/* ----------------------------- EWL Register ------------------------------- */
@ -546,7 +527,11 @@ static inline void twai_ll_get_rx_buffer(twai_dev_t *hw, twai_ll_frame_buffer_t
/**
* @brief Format contents of a TWAI frame into layout of TX Buffer
*
* @param[in] id 11 or 29bit ID
* 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
@ -557,9 +542,6 @@ static inline void twai_ll_get_rx_buffer(twai_dev_t *hw, twai_ll_frame_buffer_t
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)
{
/* 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. */
bool is_extd = flags & TWAI_MSG_FLAG_EXTD;
bool is_rtr = flags & TWAI_MSG_FLAG_RTR;
@ -570,7 +552,7 @@ static inline void twai_ll_format_frame_buffer(uint32_t id, uint8_t dlc, const u
tx_frame->self_reception = (flags & TWAI_MSG_FLAG_SELF) ? 1 : 0;
tx_frame->single_shot = (flags & TWAI_MSG_FLAG_SS) ? 1 : 0;
//Set ID
//Set ID. The ID registers are big endian and left aligned, therefore a bswap will be required
if (is_extd) {
uint32_t id_temp = __builtin_bswap32((id & TWAI_EXTD_ID_MASK) << 3); //((id << 3) >> 8*(3-i))
for (int i = 0; i < 4; i++) {
@ -583,9 +565,8 @@ static inline void twai_ll_format_frame_buffer(uint32_t id, uint8_t dlc, const u
}
}
//Set Data
uint8_t *data_buffer = (is_extd) ? tx_frame->extended.data : tx_frame->standard.data;
if (!is_rtr) {
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];
}
@ -593,7 +574,7 @@ static inline void twai_ll_format_frame_buffer(uint32_t id, uint8_t dlc, const u
}
/**
* @brief Parse formatted TWAI frame (RX Buffer Layout) into its contents
* @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
@ -604,8 +585,6 @@ static inline void twai_ll_format_frame_buffer(uint32_t id, uint8_t dlc, const u
static inline void twai_ll_prase_frame_buffer(twai_ll_frame_buffer_t *rx_frame, uint32_t *id, uint8_t *dlc,
uint8_t *data, uint32_t *flags)
{
//This function decodes a frame structure into it's constituent components.
//Copy frame information
*dlc = rx_frame->dlc;
uint32_t flags_temp = 0;
@ -614,7 +593,7 @@ static inline void twai_ll_prase_frame_buffer(twai_ll_frame_buffer_t *rx_frame,
flags_temp |= (rx_frame->dlc > TWAI_FRAME_MAX_DLC) ? TWAI_MSG_FLAG_DLC_NON_COMP : 0;
*flags = flags_temp;
//Copy ID
//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++) {
@ -631,8 +610,8 @@ static inline void twai_ll_prase_frame_buffer(twai_ll_frame_buffer_t *rx_frame,
*id = id_temp & TWAI_STD_ID_MASK;
}
//Copy data
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];
@ -661,43 +640,27 @@ static inline uint32_t twai_ll_get_rx_msg_count(twai_dev_t *hw)
/**
* @brief Set CLKOUT Divider and enable/disable
*
* Configure CLKOUT. CLKOUT is a pre-scaled version of APB CLK. 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. Set to 0 to disable CLKOUT
* @param divider Divider for CLKOUT (any even number from 2 to 490). Set to 0 to disable CLKOUT
*/
static inline void twai_ll_set_clkout(twai_dev_t *hw, uint32_t divider)
{
/* Configure CLKOUT. CLKOUT is a pre-scaled version of APB CLK. Divider can be
1, or any even number from 2 to 14. Set to out of range value (0) to disable
CLKOUT. */
if (divider >= 2 && divider <= 14) {
TWAI.clock_divider_reg.co = 0;
TWAI.clock_divider_reg.cd = (divider / 2) - 1;
if (divider >= 2 && divider <= 490) {
hw->clock_divider_reg.co = 0;
hw->clock_divider_reg.cd = (divider / 2) - 1;
} else if (divider == 1) {
TWAI.clock_divider_reg.co = 0;
TWAI.clock_divider_reg.cd = 7;
//Setting the divider reg to max value (255) means a divider of 1
hw->clock_divider_reg.co = 0;
hw->clock_divider_reg.cd = 255;
} else {
TWAI.clock_divider_reg.co = 1;
TWAI.clock_divider_reg.cd = 0;
hw->clock_divider_reg.co = 1;
hw->clock_divider_reg.cd = 0;
}
}
/**
* @brief Set register address mapping to extended mode
*
* Extended mode register address mapping consists of more registers and extra
* features.
*
* @param hw Start address of the TWAI registers
*
* @note Must be called before setting any configuration
* @note Must be called in reset mode
*/
static inline void twai_ll_enable_extended_reg_layout(twai_dev_t *hw)
{
hw->clock_divider_reg.cm = 1;
}
#ifdef __cplusplus
}
#endif

View File

@ -30,26 +30,25 @@ extern "C" {
#include <stdbool.h>
#include "hal/twai_types.h"
#include "soc/twai_periph.h"
#include "soc/soc_caps.h"
/* ------------------------- Defines and Typedefs --------------------------- */
#define TWAI_LL_STATUS_RBS (0x1 << 0)
#define TWAI_LL_STATUS_DOS (0x1 << 1)
#define TWAI_LL_STATUS_TBS (0x1 << 2)
#define TWAI_LL_STATUS_TCS (0x1 << 3)
#define TWAI_LL_STATUS_RS (0x1 << 4)
#define TWAI_LL_STATUS_TS (0x1 << 5)
#define TWAI_LL_STATUS_ES (0x1 << 6)
#define TWAI_LL_STATUS_BS (0x1 << 7)
#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_INTR_RI (0x1 << 0)
#define TWAI_LL_INTR_TI (0x1 << 1)
#define TWAI_LL_INTR_EI (0x1 << 2)
#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)
#define TWAI_LL_INTR_ALI (0x1 << 6)
#define TWAI_LL_INTR_BEI (0x1 << 7)
#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
/*
* The following frame structure has an NEARLY identical bit field layout to
@ -95,14 +94,12 @@ _Static_assert(sizeof(twai_ll_frame_buffer_t) == 13, "TX/RX buffer type should b
* in order to write the majority of configuration registers.
*
* @param hw Start address of the TWAI registers
* @return true if reset mode was entered successfully
*
* @note Reset mode is automatically entered on BUS OFF condition
*/
static inline bool twai_ll_enter_reset_mode(twai_dev_t *hw)
static inline void twai_ll_enter_reset_mode(twai_dev_t *hw)
{
hw->mode_reg.rm = 1;
return hw->mode_reg.rm;
}
/**
@ -113,14 +110,12 @@ static inline bool twai_ll_enter_reset_mode(twai_dev_t *hw)
* operating mode.
*
* @param hw Start address of the TWAI registers
* @return true if reset mode was exit successfully
*
* @note Reset mode must be exit to initiate BUS OFF recovery
*/
static inline bool twai_ll_exit_reset_mode(twai_dev_t *hw)
static inline void twai_ll_exit_reset_mode(twai_dev_t *hw)
{
hw->mode_reg.rm = 0;
return !(hw->mode_reg.rm);
}
/**
@ -189,7 +184,7 @@ static inline void twai_ll_set_cmd_tx(twai_dev_t *hw)
*/
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
hw->command_reg.val = 0x03; //Set command_reg.tr and command_reg.at simultaneously for single shot transmittion request
}
/**
@ -269,7 +264,7 @@ static inline void twai_ll_set_cmd_self_rx_request(twai_dev_t *hw)
*/
static inline void twai_ll_set_cmd_self_rx_single_shot(twai_dev_t *hw)
{
hw->command_reg.val = 0x12;
hw->command_reg.val = 0x12; //Set command_reg.srr and command_reg.at simultaneously for single shot self reception request
}
/* --------------------------- Status Register ------------------------------ */
@ -307,8 +302,6 @@ static inline bool twai_ll_is_last_tx_successful(twai_dev_t *hw)
return hw->status_reg.tcs;
}
//Todo: Add stand alone status bit check functions when necessary
/* -------------------------- Interrupt Register ---------------------------- */
/**
@ -337,12 +330,7 @@ static inline uint32_t twai_ll_get_and_clear_intrs(twai_dev_t *hw)
*/
static inline void twai_ll_set_enabled_intrs(twai_dev_t *hw, uint32_t intr_mask)
{
#ifdef TWAI_BRP_DIV_SUPPORTED
//ESP32 Rev 2 has brp div. Need to mask when setting
hw->interrupt_enable_reg.val = (hw->interrupt_enable_reg.val & 0x10) | intr_mask;
#else
hw->interrupt_enable_reg.val = intr_mask;
#endif
}
/* ------------------------ Bus Timing Registers --------------------------- */
@ -358,18 +346,10 @@ static inline void twai_ll_set_enabled_intrs(twai_dev_t *hw, uint32_t intr_mask)
* @param triple_sampling Triple Sampling enable/disable
*
* @note Must be called in reset mode
* @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.
* @note ESP32S3 brp can be any even number between 2 to 32768
*/
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)
{
#ifdef TWAI_BRP_DIV_SUPPORTED
if (brp > SOC_TWAI_BRP_DIV_THRESH) {
//Need to set brp_div bit
hw->interrupt_enable_reg.brp_div = 1;
brp /= 2;
}
#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;
@ -389,7 +369,6 @@ static inline void twai_ll_set_bus_timing(twai_dev_t *hw, uint32_t brp, uint32_t
static inline void twai_ll_clear_arb_lost_cap(twai_dev_t *hw)
{
(void)hw->arbitration_lost_captue_reg.val;
//Todo: Decode ALC register
}
/* ----------------------------- ECC Register ------------------------------- */
@ -404,7 +383,6 @@ static inline void twai_ll_clear_arb_lost_cap(twai_dev_t *hw)
static inline void twai_ll_clear_err_code_cap(twai_dev_t *hw)
{
(void)hw->error_code_capture_reg.val;
//Todo: Decode error code capture
}
/* ----------------------------- EWL Register ------------------------------- */
@ -588,7 +566,7 @@ static inline void twai_ll_format_frame_buffer(uint32_t id, uint8_t dlc, const u
}
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 RTR)
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];
}
@ -663,42 +641,26 @@ static inline uint32_t twai_ll_get_rx_msg_count(twai_dev_t *hw)
* @brief Set CLKOUT Divider and enable/disable
*
* Configure CLKOUT. CLKOUT is a pre-scaled version of APB CLK. Divider can be
* 1, or any even number from 2 to 14. Set the divider to 0 to disable CLKOUT.
* 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. Set to 0 to disable CLKOUT
* @param divider Divider for CLKOUT (any even number from 2 to 490). Set to 0 to disable CLKOUT
*/
static inline void twai_ll_set_clkout(twai_dev_t *hw, uint32_t divider)
{
if (divider >= 2 && divider <= 14) {
if (divider >= 2 && divider <= 490) {
hw->clock_divider_reg.co = 0;
hw->clock_divider_reg.cd = (divider / 2) - 1;
} else if (divider == 1) {
//Setting the divider reg to max value (7) means a divider of 1
//Setting the divider reg to max value (255) means a divider of 1
hw->clock_divider_reg.co = 0;
hw->clock_divider_reg.cd = 7;
hw->clock_divider_reg.cd = 255;
} else {
hw->clock_divider_reg.co = 1;
hw->clock_divider_reg.cd = 0;
}
}
/**
* @brief Set register address mapping to extended mode
*
* Extended mode register address mapping consists of more registers and extra
* features.
*
* @param hw Start address of the TWAI registers
*
* @note Must be called before setting any configuration
* @note Must be called in reset mode
*/
static inline void twai_ll_enable_extended_reg_layout(twai_dev_t *hw)
{
hw->clock_divider_reg.cd = 1;
}
#ifdef __cplusplus
}
#endif

View File

@ -5,8 +5,10 @@
#pragma once
#define SOC_CPU_CORES_NUM 1
#define SOC_GDMA_SUPPORTED 1
#define SOC_CPU_CORES_NUM 1
#define SOC_GDMA_SUPPORTED 1
#define SOC_TWAI_SUPPORTED 1
// There are 3 DMA channels on ESP32-C3
// Attention: These fixed DMA channels are temporarily workaround before we have a centralized DMA controller API to help alloc the channel dynamically
@ -46,6 +48,9 @@
/*-------------------------- TOUCH SENSOR CAPS -------------------------------*/
#define SOC_TOUCH_SENSOR_NUM (0) /*! No touch sensors on ESP32-C3 */
/*-------------------------- TWAI CAPS ---------------------------------------*/
#define SOC_TWAI_BRP_MIN 2
#define SOC_TWAI_BRP_MAX 32768
#define SOC_ADC_CHANNEL_NUM(PERIPH_NUM) ((PERIPH_NUM==0)? 5 : 1)
#define SOC_ADC_MAX_CHANNEL_NUM (10)

View File

@ -0,0 +1,208 @@
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
/* ---------------------------- Register Layout ------------------------------ */
/* The TWAI peripheral's registers are 8bits, however the ESP32-C3 can only access
* peripheral registers every 32bits. Therefore each TWAI register is mapped to
* the least significant byte of every 32bits.
*/
typedef volatile struct twai_dev_s {
//Configuration and Control Registers
union {
struct {
uint32_t rm: 1; /* MOD.0 Reset Mode */
uint32_t lom: 1; /* MOD.1 Listen Only Mode */
uint32_t stm: 1; /* MOD.2 Self Test Mode */
uint32_t afm: 1; /* MOD.3 Acceptance Filter Mode */
uint32_t reserved28: 28; /* Internal Reserved. MOD.4 Sleep Mode not supported */
};
uint32_t val;
} mode_reg; /* Address 0 */
union {
struct {
uint32_t tr: 1; /* CMR.0 Transmission Request */
uint32_t at: 1; /* CMR.1 Abort Transmission */
uint32_t rrb: 1; /* CMR.2 Release Receive Buffer */
uint32_t cdo: 1; /* CMR.3 Clear Data Overrun */
uint32_t srr: 1; /* CMR.4 Self Reception Request */
uint32_t reserved27: 27; /* Internal Reserved */
};
uint32_t val;
} command_reg; /* Address 1 */
union {
struct {
uint32_t rbs: 1; /* SR.0 Receive Buffer Status */
uint32_t dos: 1; /* SR.1 Data Overrun Status */
uint32_t tbs: 1; /* SR.2 Transmit Buffer Status */
uint32_t tcs: 1; /* SR.3 Transmission Complete Status */
uint32_t rs: 1; /* SR.4 Receive Status */
uint32_t ts: 1; /* SR.5 Transmit Status */
uint32_t es: 1; /* SR.6 Error Status */
uint32_t bs: 1; /* SR.7 Bus Status */
uint32_t ms: 1; /* SR.8 Miss Status */
uint32_t reserved23: 23; /* Internal Reserved */
};
uint32_t val;
} status_reg; /* Address 2 */
union {
struct {
uint32_t ri: 1; /* IR.0 Receive Interrupt */
uint32_t ti: 1; /* IR.1 Transmit Interrupt */
uint32_t ei: 1; /* IR.2 Error Interrupt */
uint32_t reserved2: 2; /* Internal Reserved (Data Overrun interrupt and Wake-up not supported) */
uint32_t epi: 1; /* IR.5 Error Passive Interrupt */
uint32_t ali: 1; /* IR.6 Arbitration Lost Interrupt */
uint32_t bei: 1; /* IR.7 Bus Error Interrupt */
uint32_t reserved24: 24; /* Internal Reserved */
};
uint32_t val;
} interrupt_reg; /* Address 3 */
union {
struct {
uint32_t rie: 1; /* IER.0 Receive Interrupt Enable */
uint32_t tie: 1; /* IER.1 Transmit Interrupt Enable */
uint32_t eie: 1; /* IER.2 Error Interrupt Enable */
uint32_t reserved2: 2; /* Internal Reserved (Data Overrun interrupt and Wake-up not supported) */
uint32_t epie: 1; /* IER.5 Error Passive Interrupt Enable */
uint32_t alie: 1; /* IER.6 Arbitration Lost Interrupt Enable */
uint32_t beie: 1; /* IER.7 Bus Error Interrupt Enable */
uint32_t reserved24: 24; /* Internal Reserved */
};
uint32_t val;
} interrupt_enable_reg; /* Address 4 */
uint32_t reserved_05; /* Address 5 */
union {
struct {
uint32_t brp: 14; /* BTR0[13:0] Baud Rate Prescaler */
uint32_t sjw: 2; /* BTR0[15:14] Synchronization Jump Width*/
uint32_t reserved16: 16; /* Internal Reserved */
};
uint32_t val;
} bus_timing_0_reg; /* Address 6 */
union {
struct {
uint32_t tseg1: 4; /* BTR1[3:0] Timing Segment 1 */
uint32_t tseg2: 3; /* BTR1[6:4] Timing Segment 2 */
uint32_t sam: 1; /* BTR1.7 Sampling*/
uint32_t reserved24: 24; /* Internal Reserved */
};
uint32_t val;
} bus_timing_1_reg; /* Address 7 */
uint32_t reserved_08; /* Address 8 (Output control not supported) */
uint32_t reserved_09; /* Address 9 (Test Register not supported) */
uint32_t reserved_10; /* Address 10 */
//Capture and Counter Registers
union {
struct {
uint32_t alc: 5; /* ALC[4:0] Arbitration lost capture */
uint32_t reserved27: 27; /* Internal Reserved */
};
uint32_t val;
} arbitration_lost_captue_reg; /* Address 11 */
union {
struct {
uint32_t seg: 5; /* ECC[4:0] Error Code Segment 0 to 5 */
uint32_t dir: 1; /* ECC.5 Error Direction (TX/RX) */
uint32_t errc: 2; /* ECC[7:6] Error Code */
uint32_t reserved24: 24; /* Internal Reserved */
};
uint32_t val;
} error_code_capture_reg; /* Address 12 */
union {
struct {
uint32_t ewl: 8; /* EWL[7:0] Error Warning Limit */
uint32_t reserved24: 24; /* Internal Reserved */
};
uint32_t val;
} error_warning_limit_reg; /* EWLR[7:0] Error Warning Limit: Address 13 */
union {
struct {
uint32_t rxerr: 8; /* RXERR[7:0] Receive Error Counter */
uint32_t reserved24: 24; /* Internal Reserved */
};
uint32_t val;
} rx_error_counter_reg; /* Address 12 */
union {
struct {
uint32_t txerr: 8; /* TXERR[7:0] Receive Error Counter */
uint32_t reserved24: 24; /* Internal Reserved */
};
uint32_t val;
} tx_error_counter_reg; /* Address 15 */
//Shared Registers (TX Buff/RX Buff/Acc Filter)
union {
struct {
union {
struct {
uint32_t byte: 8; /* ACRx[7:0] Acceptance Code */
uint32_t reserved24: 24; /* Internal Reserved */
};
uint32_t val;
} acr[4];
union {
struct {
uint32_t byte: 8; /* AMRx[7:0] Acceptance Mask */
uint32_t reserved24: 24; /* Internal Reserved */
};
uint32_t val;
} amr[4];
uint32_t reserved32[5];
} acceptance_filter;
union {
struct {
uint32_t byte: 8;
uint32_t reserved24: 24;
};
uint32_t val;
} tx_rx_buffer[13];
}; /* Address 16-28 TX/RX Buffer and Acc Filter*/;
//Misc Registers
union {
struct {
uint32_t rmc: 7; /* RMC[6:0] RX Message Counter */
uint32_t reserved25: 25; /* Internal Reserved */
};
uint32_t val;
} rx_message_counter_reg; /* Address 29 */
uint32_t reserved_30; /* Address 30 (RX Buffer Start Address not supported) */
union {
struct {
uint32_t cd: 8; /* CDR[7:0] CLKOUT frequency selector based of fOSC */
uint32_t co: 1; /* CDR.8 CLKOUT enable/disable */
uint32_t reserved24: 23; /* Internal Reserved */
};
uint32_t val;
} clock_divider_reg; /* Address 31 */
} twai_dev_t;
_Static_assert(sizeof(twai_dev_t) == 128, "TWAI registers should be 32 * 4 bytes");
extern twai_dev_t TWAI;
#ifdef __cplusplus
}
#endif

View File

@ -22,7 +22,7 @@ extern "C" {
/* ---------------------------- Register Layout ------------------------------ */
/* The TWAI peripheral's registers are 8bits, however the ESP32 can only access
/* The TWAI peripheral's registers are 8bits, however the ESP32-S2 can only access
* peripheral registers every 32bits. Therefore each TWAI register is mapped to
* the least significant byte of every 32bits.
*/

View File

@ -22,7 +22,7 @@ extern "C" {
/* ---------------------------- Register Layout ------------------------------ */
/* The TWAI peripheral's registers are 8bits, however the ESP32 can only access
/* The TWAI peripheral's registers are 8bits, however the ESP32-S3 can only access
* peripheral registers every 32bits. Therefore each TWAI register is mapped to
* the least significant byte of every 32bits.
*/
@ -61,7 +61,7 @@ typedef volatile struct twai_dev_s {
uint32_t es: 1; /* SR.6 Error Status */
uint32_t bs: 1; /* SR.7 Bus Status */
uint32_t ms: 1; /* SR.8 Miss Status */
uint32_t reserved24: 23; /* Internal Reserved */
uint32_t reserved23: 23; /* Internal Reserved */
};
uint32_t val;
} status_reg; /* Address 2 */

View File

@ -14,7 +14,7 @@ Note: If you don't have an external transceiver, this example can still be run b
### Configure the project
* Set the target of the build (where `{IDF_TARGET}` stands for the target chip such as `eszp32` or `esp32s2`).
* Set the target of the build (where `{IDF_TARGET}` stands for the target chip such as `esp32`, `esp32s2`, `esp32s2` or `esp32c3`).
* Then run `menuconfig` to configure the example.
```
@ -25,6 +25,8 @@ idf.py menuconfig
* Under `Example Configuration`, configure the pin assignments using the options `TX GPIO Number` and `RX GPIO Number` according to how the target was connected to the transceiver. By default, `TX GPIO Number` and `RX GPIO Number` are set to the following values:
* On the ESP32, `TX GPIO Number` and `RX GPIO Number` default to `21` and `22` respectively
* On the ESP32-S2, `TX GPIO Number` and `RX GPIO Number` default to `20` and `21` respectively
* On the ESP32-S3, `TX GPIO Number` and `RX GPIO Number` default to `20` and `21` respectively
* On the ESP32-C3, `TX GPIO Number` and `RX GPIO Number` default to `2` and `3` respectively
### Build and Flash

View File

@ -2,7 +2,8 @@ menu "Example Configuration"
config EXAMPLE_TX_GPIO_NUM
int "TX GPIO number"
default 20 if IDF_TARGET_ESP32S2
default 2 if IDF_TARGET_ESP32C3
default 20 if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
default 21 if IDF_TARGET_ESP32
help
This option selects the GPIO pin used for the TX signal. Connect the
@ -10,7 +11,8 @@ menu "Example Configuration"
config EXAMPLE_RX_GPIO_NUM
int "RX GPIO number"
default 21 if IDF_TARGET_ESP32S2
default 3 if IDF_TARGET_ESP32C3
default 21 if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
default 22 if IDF_TARGET_ESP32
help
This option selects the GPIO pin used for the RX signal. Connect the

View File

@ -2,7 +2,7 @@
(See the README.md file in the upper level 'examples' directory for more information about examples.)
This example demonstrates how to use the TWAI driver to program a target (ESP32 or ESP32-S2) as a TWAI node, and have the two nodes (Network Master and Network Slave) communicate on a TWAI network. The Listen Only node is optional and acts as a network monitor meaning that it only receives messages and does not influence the bus in any way (i.e. doesn't not acknowledge or send error frames).
This example demonstrates how to use the TWAI driver to program a target (ESP32, ESP32-S2, ESP32-S3 or ESP32-C3) as a TWAI node, and have the two nodes (Network Master and Network Slave) communicate on a TWAI network. The Listen Only node is optional and acts as a network monitor meaning that it only receives messages and does not influence the bus in any way (i.e. doesn't not acknowledge or send error frames).
Note that concept of master/slave in this example refers to which node initiates
and stops the transfer of a stream of data messages.
@ -55,6 +55,8 @@ idf.py menuconfig
* Under `Example Configuration`, configure the pin assignments using the options `TX GPIO Number` and `RX GPIO Number` according to how the target was connected to the transceiver. By default, `TX GPIO Number` and `RX GPIO Number` are set to the following values:
* On the ESP32, `TX GPIO Number` and `RX GPIO Number` default to `21` and `22` respectively
* On the ESP32-S2, `TX GPIO Number` and `RX GPIO Number` default to `20` and `21` respectively
* On the ESP32-S3, `TX GPIO Number` and `RX GPIO Number` default to `20` and `21` respectively
* On the ESP32-C3, `TX GPIO Number` and `RX GPIO Number` default to `2` and `3` respectively
### Build and Flash

View File

@ -2,7 +2,8 @@ menu "Example Configuration"
config EXAMPLE_TX_GPIO_NUM
int "TX GPIO number"
default 20 if IDF_TARGET_ESP32S2
default 2 if IDF_TARGET_ESP32C3
default 20 if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
default 21 if IDF_TARGET_ESP32
help
This option selects the GPIO pin used for the TX signal. Connect the
@ -10,7 +11,8 @@ menu "Example Configuration"
config EXAMPLE_RX_GPIO_NUM
int "RX GPIO number"
default 21 if IDF_TARGET_ESP32S2
default 3 if IDF_TARGET_ESP32C3
default 21 if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
default 22 if IDF_TARGET_ESP32
help
This option selects the GPIO pin used for the RX signal. Connect the

View File

@ -2,7 +2,8 @@ menu "Example Configuration"
config EXAMPLE_TX_GPIO_NUM
int "TX GPIO number"
default 20 if IDF_TARGET_ESP32S2
default 2 if IDF_TARGET_ESP32C3
default 20 if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
default 21 if IDF_TARGET_ESP32
help
This option selects the GPIO pin used for the TX signal. Connect the
@ -10,7 +11,8 @@ menu "Example Configuration"
config EXAMPLE_RX_GPIO_NUM
int "RX GPIO number"
default 21 if IDF_TARGET_ESP32S2
default 3 if IDF_TARGET_ESP32C3
default 21 if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
default 22 if IDF_TARGET_ESP32
help
This option selects the GPIO pin used for the RX signal. Connect the

View File

@ -2,7 +2,8 @@ menu "Example Configuration"
config EXAMPLE_TX_GPIO_NUM
int "TX GPIO number"
default 20 if IDF_TARGET_ESP32S2
default 2 if IDF_TARGET_ESP32C3
default 20 if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
default 21 if IDF_TARGET_ESP32
help
This option selects the GPIO pin used for the TX signal. Connect the
@ -10,7 +11,8 @@ menu "Example Configuration"
config EXAMPLE_RX_GPIO_NUM
int "RX GPIO number"
default 21 if IDF_TARGET_ESP32S2
default 3 if IDF_TARGET_ESP32C3
default 21 if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
default 22 if IDF_TARGET_ESP32
help
This option selects the GPIO pin used for the RX signal. Connect the

View File

@ -2,7 +2,7 @@
(See the README.md file in the upper level 'examples' directory for more information about examples.)
The TWAI Self Test Example demonstrates how a node can transmit TWAI messages to itself using the TWAI driver's "No Acknowledgement" mode and Self Reception Requests. The Self Test Example can be run as a simple test to determine whether a target (ESP32 or ESP32-S2) is properly connected to a working external transceiver.
The TWAI Self Test Example demonstrates how a node can transmit TWAI messages to itself using the TWAI driver's "No Acknowledgement" mode and Self Reception Requests. The Self Test Example can be run as a simple test to determine whether a target (ESP32, ESP32-S2, ESP32-S3 or ESP32-C3) is properly connected to a working external transceiver.
## How to use example
@ -25,6 +25,8 @@ idf.py menuconfig
* Under `Example Configuration`, configure the pin assignments using the options `TX GPIO Number` and `RX GPIO Number` according to how the target was connected to the transceiver. By default, `TX GPIO Number` and `RX GPIO Number` are set to the following values:
* On the ESP32, `TX GPIO Number` and `RX GPIO Number` default to `21` and `22` respectively
* On the ESP32-S2, `TX GPIO Number` and `RX GPIO Number` default to `20` and `21` respectively
* On the ESP32-S3, `TX GPIO Number` and `RX GPIO Number` default to `20` and `21` respectively
* On the ESP32-C3, `TX GPIO Number` and `RX GPIO Number` default to `2` and `3` respectively
### Build and Flash

View File

@ -2,7 +2,8 @@ menu "Example Configuration"
config EXAMPLE_TX_GPIO_NUM
int "TX GPIO number"
default 20 if IDF_TARGET_ESP32S2
default 2 if IDF_TARGET_ESP32C3
default 20 if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
default 21 if IDF_TARGET_ESP32
help
This option selects the GPIO pin used for the TX signal. Connect the
@ -10,7 +11,8 @@ menu "Example Configuration"
config EXAMPLE_RX_GPIO_NUM
int "RX GPIO number"
default 21 if IDF_TARGET_ESP32S2
default 3 if IDF_TARGET_ESP32C3
default 21 if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
default 22 if IDF_TARGET_ESP32
help
This option selects the GPIO pin used for the RX signal. Connect the