Skip to content

ESP-IDF CAN controller driver not working for transmit: invalid_state error #3921

@Civilduino

Description

@Civilduino

Hardware:

Board: Wemos LOLIN D32 Pro
CAN Bus Transceiver: SN65HVD230

Software

PLATFORM: Espressif 32 1.12.0 > WEMOS LOLIN D32 PRO
HARDWARE: ESP32 240MHz, 320KB RAM, 4MB Flash
PACKAGES:
-- framework-arduinoespressif32 3.10004.200129 (1.0.4)
-- tool-esptoolpy 1.20600.0 (2.6.0)
-- toolchain-xtensa32 2.50200.80 (5.2.0)
Dependency Graph
--Ticker 1.1

RAM: [ ] 4.5% (used 14796 bytes from 327680 bytes)
Flash: [== ] 20.8% (used 272229 bytes from 1310720 bytes)

IDE name: Platformio.io Core 4.3.1, Home 3.1.1 using Visual Code IDE
Flash Frequency: default
PSRAM enabled: yes
Upload Speed: 460800
Computer OS: Mac OSX

Description:

I am trying to use the ESP-IDF driver for the CAN controller in my CAN BUS application. I am getting an error when trying to transmit a CAN data frame or RTR. The error appears when trying to send the second CAN data frame. However, the first frame seems to be corrupted as well when I look at it with a digital analyser directly at the Tx pin.

Why does the CAN controller enters an "invalid_state" and then it goes "bus-off"?

How exactly I need to use this API? if I were to only receive CAN frames my approach seems to work.

or can it be a hardware issue as described here (from page 16) https://esp32.com/viewtopic.php?t=380&start=170 ?

Sketch:

#include <Arduino.h>
#include <driver/can.h>
#include <driver/gpio.h>

#include <Ticker.h>

// Global objects
Ticker canBusTimer;

// Global variables
uint8_t canBusFLAG = 0;

// Prototype functions
void CAN_begin(void);
void CAN_receive(void);
void CAN_transmit_RTR(uint32_t id);
void CAN_transmit_stdData(uint32_t id, uint8_t len, uint8_t *data);

void can_flag(void);

void setup()
{
  CAN_begin();
  delay(1000);
  canBusTimer.attach_ms(1000, can_flag);
}

void loop()
{
  if (canBusFLAG == 1)
  {
    uint8_t canData[1] = {1};
    CAN_transmit_stdData(0x003, 1, canData);
    canBusFLAG = 0;
    CAN_receive();
  }
}

// FUNCTIONS
void can_flag(void)
{
  canBusFLAG = 1;
}

void CAN_begin(void)
{
  //Initialize configuration structures using macro initializers (changed GPIO type in esp idf library)
  can_general_config_t g_config = CAN_GENERAL_CONFIG_DEFAULT(GPIO_NUM_22, GPIO_NUM_23, CAN_MODE_NO_ACK);
  can_timing_config_t t_config = CAN_TIMING_CONFIG_25KBITS();
  can_filter_config_t f_config = CAN_FILTER_CONFIG_ACCEPT_ALL();

  //Install CAN driver
  if (can_driver_install(&g_config, &t_config, &f_config) == ESP_OK)
    printf("Driver installed\n");
  else
  {
    printf("Failed to install driver\n");
    return;
  }

  //Start CAN driver
  if (can_start() == ESP_OK)
    printf("Driver started\n");
  else
  {
    printf("Failed to start driver\n");
    return;
  }
}

void CAN_receive(void)
{
  can_status_info_t can_status;
  can_message_t message;

  //Check for received messages
  can_get_status_info(&can_status);
  if (can_status.msgs_to_rx >= 1)
  {
    if (can_receive(&message, pdMS_TO_TICKS(10)) == ESP_OK)
      printf("Message received\n");
    else
    {
      printf("Failed to receive message\n");
      return;
    }

    //Process received message
    printf("ID is %d\n", message.identifier);
    for (int i = 0; i < message.data_length_code; i++)
    {
      printf("Data byte %d = %d\n", i, message.data[i]);
    }
  }
}

void CAN_transmit_stdData(uint32_t id, uint8_t len, uint8_t *data)
{
  //Configure message to transmit
  can_message_t message;
  message.flags = CAN_MSG_FLAG_SELF;
  message.identifier = id;
  message.data_length_code = len;
  message.data[0] = 1;
  // for (uint8_t i = 0; i < len; i++)
  // {
  //     message.data[i] = 1;
  // }

  can_status_info_t info;
  can_get_status_info(&info);

  if (info.state == CAN_STATE_RUNNING)
    printf("CAN running\n");
  else if (info.state == CAN_STATE_STOPPED)
    printf("CAN stopped\n");
  else if (info.state == CAN_STATE_RECOVERING)
    printf("CAN recovering\n");
  else if (info.state == CAN_STATE_BUS_OFF)
    printf("CAN bus-off\n");

  ESP_ERROR_CHECK_WITHOUT_ABORT(can_transmit(&message, pdMS_TO_TICKS(100)));

  // //Queue message for transmission
  // if (can_transmit(&message, pdMS_TO_TICKS(100)) == ESP_OK)
  //     printf("Message queued for transmission\n");
  // else
  //     printf("Failed to queue message for transmission\n");
}

void CAN_transmit_RTR(uint32_t id)
{
  //Configure message to transmit
  can_message_t message;
  message.flags = CAN_MSG_FLAG_RTR;
  message.identifier = id;
  message.data_length_code = 0;

  //Queue message for transmission
  ESP_ERROR_CHECK_WITHOUT_ABORT(can_transmit(&message, pdMS_TO_TICKS(100)));
}

Debug Messages:

ESP_ERROR_CHECK_WITHOUT_ABORT failed: esp_err_t 0x103 (ESP_ERR_INVALID_STATE) at 0x4008d8df
file: "src/main.cpp" line 122
func: void CAN_transmit_stdData(uint32_t, uint8_t, uint8_t*)
expression: can_transmit(&message, pdMS_TO_TICKS(100))

Platformio configuration

[env:lolin_d32_pro]
platform = espressif32
board = lolin_d32_pro
framework = arduino
upload_port = /dev/tty.wchusbserial1410
monitor_speed = 115200

; debug_tool = esp-prog
; debug_init_break = tbreak setup
; monitor_filters = log2file, esp32_exception_decoder
build_flags =
    -DBOARD_HAS_PSRAM
    -mfix-esp32-psram-cache-issue
    -DCORE_DEBUG_LEVEL=4

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions