1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2026-01-01 01:41:18 +01:00

ecp/esp32: changes in periph_can for ESP-IDF v4.4

This commit is contained in:
Gunar Schorcht 2022-02-26 18:58:21 +01:00
parent 24162af90a
commit 587e007a31
2 changed files with 65 additions and 62 deletions

View File

@ -38,6 +38,7 @@ INCLUDES += -I$(ESP32_SDK_DIR)/components/esp_rom/include/$(CPU)
INCLUDES += -I$(ESP32_SDK_DIR)/components/esp_timer/include
INCLUDES += -I$(ESP32_SDK_DIR)/components/hal/$(CPU)/include
INCLUDES += -I$(ESP32_SDK_DIR)/components/hal/include
INCLUDES += -I$(ESP32_SDK_DIR)/components/hal/platform_port/include
INCLUDES += -I$(ESP32_SDK_DIR)/components/heap/include
INCLUDES += -I$(ESP32_SDK_DIR)/components/log/include
INCLUDES += -I$(ESP32_SDK_DIR)/components/newlib/platform_include

View File

@ -36,14 +36,20 @@
#include "periph/can.h"
#include "periph/gpio.h"
#include "soc/can_struct.h"
#include "hal/twai_ll.h"
#include "soc/gpio_sig_map.h"
#include "soc/gpio_struct.h"
#include "soc/twai_struct.h"
#include "soc/soc.h"
#include "xtensa/xtensa_api.h"
#define ENABLE_DEBUG 0
#include "debug.h"
#define CAN TWAI
/** Common ESP CAN definitions */
#define ESP_CAN_INTR_MASK (0xffU) /* interrupts handled by ESP CAN */
#define ESP_CAN_CLOCK APB_CLK_FREQ /* controller main clock */
@ -337,10 +343,10 @@ static int _esp_can_set(candev_t *candev, canopt_t opt, void *value, size_t valu
return -EOVERFLOW;
}
if (opt == CANOPT_TEC) {
CAN.tx_error_counter_reg.byte = *((uint16_t*)value);
CAN.tx_error_counter_reg.txerr = *((uint16_t*)value);
}
else {
CAN.rx_error_counter_reg.byte = *((uint16_t*)value);
CAN.rx_error_counter_reg.rxerr = *((uint16_t*)value);
}
res = sizeof(uint16_t);
break;
@ -408,10 +414,10 @@ static int _esp_can_get(candev_t *candev, canopt_t opt, void *value, size_t max_
}
if (opt == CANOPT_TEC) {
*((uint16_t *)value) = CAN.tx_error_counter_reg.byte;
*((uint16_t *)value) = CAN.tx_error_counter_reg.txerr;
}
else {
*((uint16_t *)value) = CAN.rx_error_counter_reg.byte;
*((uint16_t *)value) = CAN.rx_error_counter_reg.rxerr;
}
res = sizeof(uint16_t);
@ -532,8 +538,8 @@ static void _esp_can_set_reset_mode(void)
{
DEBUG("%s\n", __func__);
while (CAN.mode_reg.reset != 1) {
CAN.mode_reg.reset = 1;
while (CAN.mode_reg.rm != 1) {
CAN.mode_reg.rm = 1;
}
}
@ -541,8 +547,8 @@ static void _esp_can_set_operating_mode(void)
{
DEBUG("%s\n", __func__);
while (CAN.mode_reg.reset != 0) {
CAN.mode_reg.reset = 0;
while (CAN.mode_reg.rm != 0) {
CAN.mode_reg.rm = 0;
}
}
@ -558,33 +564,33 @@ static int _esp_can_config(can_t *dev)
_esp_can_set_reset_mode();
/* configuration is done in listen only mode */
CAN.mode_reg.self_test = 0;
CAN.mode_reg.listen_only = 1;
CAN.mode_reg.stm = 0;
CAN.mode_reg.lom = 1;
/* Use SJA1000 PeliCAN mode and registers layout */
CAN.clock_divider_reg.can_mode = 1;
CAN.clock_divider_reg.cm = 1;
#ifndef ESP_CAN_CLK_OUT
CAN.clock_divider_reg.clock_off = 1;
CAN.clock_divider_reg.clock_divider = 0;
CAN.clock_divider_reg.co = 1;
CAN.clock_divider_reg.cd = 0;
#else
uint32_t clk_out_div = ESP_CAN_CLK_OUT_DIV / 2 - 1;
clk_out_div = (clk_out_div < 7) ? clk_out_div : 7;
CAN.clock_divider_reg.clock_off = 0;
CAN.clock_divider_reg.clock_divider = clk_out_div;
CAN.clock_divider_reg.co = 0;
CAN.clock_divider_reg.cd = clk_out_div;
#endif
/* set error counter values and warning limits */
CAN.error_warning_limit_reg.byte = ESP_CAN_ERROR_WARNING_LIMIT;
CAN.tx_error_counter_reg.byte = 0;
CAN.rx_error_counter_reg.byte = 0;
CAN.error_warning_limit_reg.ewl = ESP_CAN_ERROR_WARNING_LIMIT;
CAN.tx_error_counter_reg.txerr = 0;
CAN.rx_error_counter_reg.rxerr = 0;
/* accept all CAN messages, filtering is done by software */
CAN.mode_reg.acceptance_filter = 0; /* single filter */
CAN.acceptance_filter.mask_reg[0].byte = 0xff; /* all bits masked */
CAN.acceptance_filter.mask_reg[1].byte = 0xff;
CAN.acceptance_filter.mask_reg[2].byte = 0xff;
CAN.acceptance_filter.mask_reg[3].byte = 0xff;
CAN.mode_reg.afm = 0; /* single filter */
CAN.acceptance_filter.amr[0].byte = 0xff; /* all bits masked */
CAN.acceptance_filter.amr[1].byte = 0xff;
CAN.acceptance_filter.amr[2].byte = 0xff;
CAN.acceptance_filter.amr[3].byte = 0xff;
/* clear interrupt status register by read and enable all interrupts */
uint32_t tmp = CAN.interrupt_reg.val; (void)tmp;
@ -652,7 +658,7 @@ static void _esp_can_init_pins(can_t *dev)
/* Init TX pin */
gpio_init(dev->tx_pin, GPIO_OUT);
gpio_set_pin_usage(dev->tx_pin, _CAN);
GPIO.func_out_sel_cfg[dev->tx_pin].func_sel = CAN_TX_IDX;
GPIO.func_out_sel_cfg[dev->tx_pin].func_sel = TWAI_TX_IDX;
/* Init RX pin */
gpio_init(dev->rx_pin, GPIO_IN);
@ -665,14 +671,14 @@ static void _esp_can_init_pins(can_t *dev)
/* Init CLK_OUT pin (optional) if defined */
gpio_init(dev->clk_out_pin, GPIO_OD);
gpio_set_pin_usage(dev->clk_out_pin, _CAN);
GPIO.func_out_sel_cfg[dev->clk_out_pin].func_sel = CAN_CLKOUT_IDX;
GPIO.func_out_sel_cfg[dev->clk_out_pin].func_sel = TWAI_CLKOUT_IDX;
#endif
/* Init BUS_ON_OFF pin pin (optional) if defined */
#ifdef ESP_CAN_BUS_ON_OFF
gpio_init(dev->bus_on_of_pin, GPIO_OD);
gpio_set_pin_usage(dev->bus_on_of_pin, _CAN);
GPIO.func_out_sel_cfg[dev->bus_on_of_pin].func_sel = CAN_BUS_OFF_ON_IDX;
GPIO.func_out_sel_cfg[dev->bus_on_of_pin].func_sel = TWAI_BUS_OFF_ON_IDX;
#endif
}
@ -695,8 +701,8 @@ static int _esp_can_set_mode(can_t *dev, canopt_state_t state)
_esp_can_power_up(dev);
/* set the new mode (has to be done in reset mode) */
_esp_can_set_reset_mode();
CAN.mode_reg.self_test = 0;
CAN.mode_reg.listen_only = 1;
CAN.mode_reg.stm = 0;
CAN.mode_reg.lom = 1;
_esp_can_set_operating_mode ();
break;
@ -715,8 +721,8 @@ static int _esp_can_set_mode(can_t *dev, canopt_state_t state)
_esp_can_power_up(dev);
/* set the new mode (has to be done in reset mode) */
_esp_can_set_reset_mode();
CAN.mode_reg.self_test = 0;
CAN.mode_reg.listen_only = 0;
CAN.mode_reg.stm = 0;
CAN.mode_reg.lom = 0;
_esp_can_set_operating_mode ();
break;
@ -740,29 +746,29 @@ static void IRAM_ATTR _esp_can_intr_handler(void *arg)
critical_enter();
/* read the registers to clear them */
can_status_reg_t sta_reg = CAN.status_reg;
can_intr_reg_t int_reg = CAN.interrupt_reg;
uint32_t sta_reg = CAN.status_reg.val;
uint32_t int_reg = CAN.interrupt_reg.val;
DEBUG("%s int=%08x sta=%08x\n", __func__, int_reg.val, sta_reg.val);
DEBUG("%s int=%08x sta=%08x\n", __func__, int_reg, sta_reg);
/* Wake-Up Interrupt (not supported by ESP32) */
if (int_reg.reserved1) {
if (int_reg & BIT(4)) {
DEBUG("%s wake-up interrupt\n", __func__);
dev->events |= ESP_CAN_EVENT_WAKE_UP;
}
/* Arbitration Lost Interrupt */
if (int_reg.arb_lost) {
if (int_reg & TWAI_LL_INTR_ALI) {
DEBUG("%s arbitration lost interrupt\n", __func__);
/* can only happen during transmission, handle it as error in single shot transmission */
dev->events |= ESP_CAN_EVENT_TX_ERROR;
}
/* bus or error status has changed, handle this first */
if (int_reg.err_warn) {
if (int_reg & TWAI_LL_INTR_EI) {
/* BUS_OFF state condition */
if (sta_reg.error && sta_reg.bus) {
if ((sta_reg & TWAI_LL_STATUS_ES) && (sta_reg & TWAI_LL_STATUS_BS)) {
DEBUG("%s bus-off state interrupt\n", __func__);
/* switch to listen only mode to freeze the RX error counter */
_esp_can_set_mode (dev, CANOPT_STATE_LISTEN_ONLY);
@ -771,7 +777,7 @@ static void IRAM_ATTR _esp_can_intr_handler(void *arg)
}
/* ERROR_WARNING state condition, RX/TX error counter are > 96 */
else if (sta_reg.error && !sta_reg.bus) {
else if ((sta_reg & TWAI_LL_STATUS_ES) && !(sta_reg & TWAI_LL_STATUS_BS)) {
DEBUG("%s error warning interrupt\n", __func__);
/* save the event */
dev->events |= ESP_CAN_EVENT_ERROR_WARNING;
@ -779,13 +785,13 @@ static void IRAM_ATTR _esp_can_intr_handler(void *arg)
}
/* enter to / return from ERROR_PASSIVE state */
if (int_reg.err_passive) {
if (int_reg & TWAI_LL_INTR_EPI) {
/* enter to the ERROR_PASSIVE state when one of the error counters is >= 128 */
if (CAN.tx_error_counter_reg.byte >= ESP_CAN_ERROR_PASSIVE_LIMIT ||
CAN.rx_error_counter_reg.byte >= ESP_CAN_ERROR_PASSIVE_LIMIT) {
if (CAN.tx_error_counter_reg.txerr >= ESP_CAN_ERROR_PASSIVE_LIMIT ||
CAN.rx_error_counter_reg.rxerr >= ESP_CAN_ERROR_PASSIVE_LIMIT) {
DEBUG("%s error passive interrupt %d %d\n", __func__,
CAN.tx_error_counter_reg.byte,
CAN.rx_error_counter_reg.byte);
CAN.tx_error_counter_reg.txerr,
CAN.rx_error_counter_reg.rxerr);
/* save the event */
dev->events |= ESP_CAN_EVENT_ERROR_PASSIVE;
}
@ -796,23 +802,23 @@ static void IRAM_ATTR _esp_can_intr_handler(void *arg)
* in ECC register (see SJA1000 Data sheet, Table 20 and 21)
*/
if (int_reg.bus_err) {
can_err_code_cap_reg_t ecc = CAN.error_code_capture_reg;
if (int_reg & TWAI_LL_INTR_BEI) {
/* save the event */
DEBUG("%s bus error interrupt, ecc=%08x\n", __func__, ecc.val);
dev->events |= ecc.direction ? ESP_CAN_EVENT_RX_ERROR
: ESP_CAN_EVENT_TX_ERROR;
DEBUG("%s bus error interrupt, ecc=%08x\n", __func__,
CAN.error_code_capture_reg.val);
dev->events |= CAN.error_code_capture_reg.dir ? ESP_CAN_EVENT_RX_ERROR
: ESP_CAN_EVENT_TX_ERROR;
}
/* TX buffer becomes free */
if (int_reg.tx) {
if (int_reg & TWAI_LL_INTR_TI) {
DEBUG("%s transmit interrupt\n", __func__);
/* save the event */
dev->events |= ESP_CAN_EVENT_TX_CONFIRMATION;
}
/* RX buffer has one or more frames */
if (int_reg.rx) {
if (int_reg & TWAI_LL_INTR_RI) {
/* get the number of messages in receive buffer */
uint32_t msg_cnt = CAN.rx_message_counter_reg.val;
@ -885,7 +891,7 @@ static void IRAM_ATTR _esp_can_intr_handler(void *arg)
}
/* data overrun interrupts are not handled */
if (int_reg.data_overrun) {
if (int_reg & BIT(3)) {
DEBUG("%s data overrun interrupt\n", __func__);
/* we use rx error since there is no separate overrun error */
dev->events |= ESP_CAN_EVENT_RX_INDICATION;
@ -913,25 +919,21 @@ static void _esp_can_set_bittiming(can_t *dev)
timing->prop_seg, timing->phase_seg1, timing->phase_seg2,
timing->sjw);
can_bus_tim_0_reg_t reg_0;
can_bus_tim_1_reg_t reg_1;
_esp_can_set_reset_mode();
/* Again cppcheck gets off rails due to missing concept of union (see
* explanation above), so we suppress false unreadVariable here */
/* cppcheck-suppress unreadVariable */
reg_0.baud_rate_prescaler = (timing->brp / 2) - 1;
CAN.bus_timing_0_reg.brp = (timing->brp / 2) - 1;
/* cppcheck-suppress unreadVariable */
reg_0.sync_jump_width = timing->sjw - 1;
CAN.bus_timing_0_reg.sjw = timing->sjw - 1;
/* cppcheck-suppress unreadVariable */
reg_1.time_seg_1 = (timing->prop_seg + timing->phase_seg1) - 1;
CAN.bus_timing_1_reg.tseg1 = (timing->prop_seg + timing->phase_seg1) - 1;
/* cppcheck-suppress unreadVariable */
reg_1.time_seg_2 = timing->phase_seg2 - 1;
CAN.bus_timing_1_reg.tseg2 = timing->phase_seg2 - 1;
/* cppcheck-suppress unreadVariable */
reg_1.sampling = 0;
CAN.bus_timing_1_reg.sam = 0;
_esp_can_set_reset_mode();
CAN.bus_timing_0_reg.val = reg_0.val;
CAN.bus_timing_1_reg.val = reg_1.val;
_esp_can_set_operating_mode();
}