Closed atanisoft closed 2 years ago
@Dazza0 I've rewritten my code to directly leverage the new TWAI APIs. Unfortunately, I still see the same problem with RX not firing. I added an LM358 to the TX and RX pins to visually indicate activity and I can see there is activity on both TX and RX now but the RX event doesn't appear to be firing. Any updates or things I can try to help resolve this?
@Dazza0 I've tested the TWAI code I linked to above on the ESP32 on latest IDF master with no issues. I'm at a loss as to what is missing on the ESP32-S2 side.
For both the ESP32 and ESP32-S2 I've used SN65HVD230 with this circuit to visualize the TX/RX activity:
It appears that even though the frames are visually confirmed as being sent by the SN65HVD230 to the ESP32-S2 it would appear the ESP32-S2 is not processing them.
@atanisoft I've just tested the ESP32-S2 by porting over the can.h
and can_types.h
and haven't been able to recreate this issue. Could you share a snippet of your mapping header file and also you application code?
@Dazza0 let me share a private repo with you that contains a version of it and instructions on how to test it with that code. I haven't been able to receive with the code using only the new TWAI API on the S2 but it works on the esp32.
@Dazza0 you should have received an invite to the repo and I've added some notes in the readme which explain how to connect the ESP32-S2 and what sort of data to send to it (very basic frames really)
@atanisoft The invite I received doesn't seem to work.
@Dazza0 if you can send me an email I'll send you a zip file if the project.
Is it possibly an issue with using pins 41 (rx), 42 (tx)? I have no issues with tx but rx doesn't seem to be firing even though the transceiver shows activity on rx.
@Dazza0 I tested using the arduino-esp32 esp32s2 branch (uses v4.3-dev-907-g6c17e3a64-dirty) and it somewhat works. I'll be digging through the diffs further.
latest code seems to work correctly...
@Dazza0 I'm circling back to this with the latest IDF v4.4 (master cf457d412) and I'm seeing consistent failure with my S2 Saola WROVER:
09:12:34.212 -> ESP-ROM:esp32s2-rc4-20191025
09:12:34.212 -> Build:Oct 25 2019
09:12:34.212 -> rst:0x1 (POWERON),boot:0x8 (SPI_FAST_FLASH_BOOT)
09:12:34.212 -> SPIWP:0xee
09:12:34.212 -> mode:DIO, clock div:1
09:12:34.245 -> load:0x3ffe6100,len:0x4b0
09:12:34.245 -> load:0x4004c000,len:0xa6c
09:12:34.245 -> load:0x40050000,len:0x25c0
09:12:34.245 -> entry 0x4004c198
09:12:34.576 -> [SoC] reset reason:1 - power on reset
09:12:34.576 -> [SoC] model:ESP32-S2,rev:0,cores:1,flash:No,WiFi:Yes,BLE:No,BT:No
09:12:34.576 -> [SoC] Heap: 207.92kB / 281.12Kb
09:12:34.576 -> [SoC] PSRAM: 2045.63kB / 2048.00Kb
09:12:34.576 -> [SoC] App running from: app0
As you can see it is an early rev0 board, I'm wondering if possibly this specific board has a broken TWAI peripheral? It works fine for TX but never for RX.
I have apparently the same issue here. My (simple example) Rx /Tx code is working well on a ESP32, but when compiled for ESP32-s2 (in arduino-esp32-2.0.2rc1, based on esp-idf4..4) , only TX is working and no RX event is firing...
The acceptance filter is supposed to be configured for letting all frames in.
On the same board a circuitpython script is able to both receive and transmit so I am pretty sure it is not the HW (furthermore, frames from the other node are acknowledged and no error is raised on transmission, which means the twai controller is properly seeing what happens on the bus)
@atanisoft have you solved your issue ?
@brice-fr I have not found a workable solution as of now, I'm using IDF v4.3 release branch for esp32, esp32-c3 and esp32-s2. The code works on all three for TX but RX doesn't seem to ever trigger on the esp32-s2.
Since you have seen circuit python working for this, it would be good to see the diff of what is being used there compared to IDF. It could be a bug in the HAL-LL code for the esp32-s2.
@atanisoft there is indeed some hint in the adafruit canio/twai driver https://github.com/adafruit/circuitpython/blob/main/ports/esp32s2/common-hal/canio/Listener.c#L47
It is pointing to this issue : https://github.com/espressif/esp-idf/issues/6020 (thanks to @jepler for pointing this in the first time)
I can not recompile easily the esp-idf library that is used in esp32-arduino but I have somehow duplicated the twai driver in my project and just adding "attribute((optimize("O0")))" in the prototype of the filter setting function in twai_ll.h actually allows to solve this issue:
static inline void __attribute__((optimize("O0"))) twaie_ll_set_acc_filter(twaie_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);
for (int i = 0; i < 4; i++) {
hw->acceptance_filter.acr[i].byte = ((code_swapped >> (i * 8)) & 0xFF);
hw->acceptance_filter.amr[i].byte = ((mask_swapped >> (i * 8)) & 0xFF);
}
hw->mode_reg.afm = single_filter;
}
Reworking the struct as @Dazza0 planned might also do the trick but meanwhile this solution seems the most easy and effective
@brice-fr wow, such a simple fix possibly. I'll give it a test with my hardware setup and if it works can submit a PR for @Dazza0 to review.
Most probably replacing the ".byte" (x2) by ".val“ would have also worked as this is what is done with the TX buffers. Gone to work right now but I can try that this evening...
[edit] ... and I can confirm this version also works:
`static inline void twaie_ll_set_acc_filter(twaie_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);
for (int i = 0; i < 4; i++) {
hw->acceptance_filter.acr[i].val = ((code_swapped >> (i * 8)) & 0xFF);
hw->acceptance_filter.amr[i].val = ((mask_swapped >> (i * 8)) & 0xFF);
}
hw->mode_reg.afm = single_filter;
}`
@brice-fr I'm seeing some other issues with the patched method. But I do see the RX ISR event firing so that is some progress. I suspect it may be a few other 8-bit accesses causing the issues.
Just ran into this myself and was stumped why the identical code on an ESP32 failed on an ESP32-S2 for receive. Googling online there were others with the same problem that eventually led me here. I haven't been able to get my own twai driver working for some reason as brice-fr was. Hopefully this is figured out soon as in the Espressif Arduino forum, they were asking for feedback on bugs as looking to release 2.0.0
PTAL at commit 2e0ffbd543abc0226f0dbd2f725eb891235abe02. The commit should prevent s8
access on all peripherals.
Thank you!
@Dazza0 Seeing some issues with the updates when used in C++ code:
esp-idf-master/components/hal/platform_port/include/hal/misc.h:35:18: error: ambiguous overload for 'operator=' (operand types are 'volatile twai_dev_s::<unnamed union>' and 'volatile twai_dev_s::<unnamed union>')
(base_reg) = temp_reg; \
^~~~~~~~
esp-idf-master/components/hal/esp32s2/include/hal/twai_ll.h:663:9: note: in expansion of macro 'HAL_FORCE_MODIFY_U32_REG_FIELD'
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clock_divider_reg, cd, 0);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from esp-idf-master/components/soc/include/soc/twai_periph.h:24,
from esp-idf-master/components/hal/esp32s2/include/hal/twai_ll.h:33,
from esp-idf-master/components/hal/include/hal/twai_hal.h:31,
from ../components/OpenMRNIDF/src/freertos_drivers/esp32/Esp32HardwareTwai.cpp:64:
esp-idf-master/components/soc/esp32s2/include/soc/twai_struct.h:198:11: note: candidate: 'constexpr twai_dev_s::<unnamed union>& twai_dev_s::<unnamed union>::operator=(const twai_dev_s::<unnamed union>&)' <near match>
union {
^
esp-idf-master/components/soc/esp32s2/include/soc/twai_struct.h:198:11: note: conversion of argument 1 would be ill-formed:
In file included from esp-idf-master/components/hal/esp32s2/include/hal/twai_ll.h:31,
from esp-idf-master/components/hal/include/hal/twai_hal.h:31,
from ../components/OpenMRNIDF/src/freertos_drivers/esp32/Esp32HardwareTwai.cpp:64:
esp-idf-master/components/hal/platform_port/include/hal/misc.h:35:18: error: binding reference of type 'const twai_dev_s::<unnamed union>&' to 'volatile twai_dev_s::<unnamed union>' discards qualifiers
(base_reg) = temp_reg; \
^~~~~~~~
esp-idf-master/components/hal/esp32s2/include/hal/twai_ll.h:663:9: note: in expansion of macro 'HAL_FORCE_MODIFY_U32_REG_FIELD'
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clock_divider_reg, cd, 0);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Any ideas? Esp32HardwareTwai.cpp can be found here. I'm not using driver/twai.c due to overriding the ISR and exposing as a VFS.
EDIT: This is seen for ESP32-C3 and ESP32 as well.
@Dazza0 A simpler example of the failure is likely as simple as:
main.cpp
#include <hal/twai_hal.h>
extern "C" void app_main() {}
Likely other HAL header files would reproduce this as well since the new macros are used quite extensively.
This seems to be a behavior difference of C vs C++ related to the typeof
operator.
@atanisoft Seems like there are two separate issues when C++ tries to use the macros provided in hal/misc.h
typeof()
on a union{}
register somehow discards its volatile
qualifier. Not sure why.typeof(base_reg) temp_reg = (base_reg);
will invoke a non-existent copy constructor.Try replacing the macros in hal/misc.h
with the following and see if the issues is resolved
#define HAL_FORCE_MODIFY_U32_REG_FIELD(base_reg, reg_field, field_val) \
{ \
uint32_t temp_val = base_reg.val; \
typeof(base_reg) temp_reg; \
temp_reg.val = temp_val; \
temp_reg.reg_field = (field_val); \
(base_reg).val = temp_reg.val; \
}
#define HAL_FORCE_READ_U32_REG_FIELD(base_reg, reg_field) ({ \
uint32_t temp_val = base_reg.val; \
typeof(base_reg) temp_reg; \
temp_reg.val = temp_val; \
temp_reg.reg_field; \
})
@Dazza0 Compilation seems to be successful with the updated macros, will test with this on: ESP32, ESP32-S2, ESP32-C3 and report back.
@Dazza0 I've confirmed that using the above macros the linked Esp32HardwareTwai.cpp code works for the ESP32-S2. I'll continue testing over the weekend but so far it looks good.
@Dazza0 Can this HAL fix be backported to IDF v4.3?
@atanisoft Technically this will need to be back-ported all the way back to v4.2 since this was the first version where ESP32-S2 was supported, so v4.3 should also have this backport. But I want to double check if this bug is present in all of our compiler versions (given that the source of this bug is due to the -fstrict-volatile-bitfields
not working).
I can confirm it is broken in v4.3 at least, which also uses the same gcc as master is today.
@Dazza0 Any timeline for the fix being backported to IDF v4.3?
@atanisoft MR for v4.3 backport is current review
Thanks @Dazza0 I'll run it through validations in a bit
@Dazza0, I am also facing the Rx issue with ESP32 (ESP-WROOM-32) while Tx is working perfectly. I am using the MCP2515 module as my CAN transceiver.
I tried ESP-IDF v5 as well as v4.4.4, neither of which seem to work.
I saw a YouTube video with someone who used a similar code, and it was working perfectly for him (YouTube Video: link: https://youtu.be/bxzWuIqfn9Y).
This is my code:
#include "driver/gpio.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "stdio.h"
#include "stdlib.h"
#include "driver/twai.h"
void twai_setup_and_install(){
//Initialize configuration structures using macro initializers
twai_general_config_t g_config = {
.mode = TWAI_MODE_NORMAL,
.tx_io = GPIO_NUM_5,
.rx_io = GPIO_NUM_4,
.clkout_io = TWAI_IO_UNUSED,
.bus_off_io = TWAI_IO_UNUSED,
.tx_queue_len = 5,
.rx_queue_len = 5,
.alerts_enabled = TWAI_ALERT_NONE,
.clkout_divider = 0
};
twai_timing_config_t t_config = TWAI_TIMING_CONFIG_500KBITS();
twai_filter_config_t f_config = TWAI_FILTER_CONFIG_ACCEPT_ALL();
// Install TWAI driver
if (twai_driver_install(&g_config, &t_config, &f_config) == ESP_OK) {
printf("Driver installed\n");
} else {
printf("Failed to install driver\n");
return;
}
// Start TWAI driver
if (twai_start() == ESP_OK) {
printf("Driver started\n");
} else {
printf("Failed to start driver\n");
return;
}
}
void new_message(twai_message_t *message, uint32_t id, uint8_t dlc, uint8_t *data)
{
message->flags = TWAI_MSG_FLAG_NONE;
message->identifier = id;
message->data_length_code = dlc;
for (int i = 0; i < dlc; i++) {
message->data[i] = data[i];
}
printf("Message created\nID: %ld DLC: %d Data:\t", message->identifier, message->data_length_code);
for (int i = 0; i < message->data_length_code; i++) {
printf("%d\t", message->data[i]);
}
printf("\n");
}
void transmit_message(twai_message_t *message)
{
if (twai_transmit(message, pdMS_TO_TICKS(1000)) == ESP_OK) {
printf("Message queued for transmission\n");
} else {
printf("Failed to send message\n");
}
}
void receive_message(twai_message_t *message)
{
if (twai_receive(message, pdMS_TO_TICKS(1000)) == ESP_OK) {
printf("Message received:\n");
printf("ID: %ld DLC: %d Data:\t", message->identifier, message->data_length_code);
for (int i = 0; i < message->data_length_code; i++) {
(message->extd)?printf("Extended ID"):printf("Standard ID");
printf("%d\t", message->data[i]);
}
} else {
printf("Failed to receive message\n");
}
}
void app_main()
{
twai_setup_and_install();
twai_message_t message;
twai_message_t message1;
// Set the data to send
uint8_t data[8] = {rand() % 255, rand() % 255, rand() % 255,
rand() % 255, rand() % 255, rand() % 255, rand() % 255, rand() % 255};
while(true){
// Create a new message
new_message(&message, 0x123, 8, data);
// Transmit the message to a queue
transmit_message(&message);
// Receive the message from the queue
receive_message(&message1);
// Wait for 1 second
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
}
@brice-fr @eloebl @atanisoft @jepler
If anyone can help me, it would be really appreciated!
Regards,
Awaiting reply ASAP
@Dazza0, I am also facing the Rx issue with ESP32 (ESP-WROOM-32) while Tx is working perfectly. I am using the MCP2515 module as my CAN transceiver.
I tried ESP-IDF v5 as well as v4.4.4, neither of which seem to work.
I saw a YouTube video with someone who used a similar code, and it was working perfectly for him (YouTube Video: link: https://youtu.be/bxzWuIqfn9Y).
This is my code:
#include "driver/gpio.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "stdio.h" #include "stdlib.h" #include "driver/twai.h" void twai_setup_and_install(){ //Initialize configuration structures using macro initializers twai_general_config_t g_config = { .mode = TWAI_MODE_NORMAL, .tx_io = GPIO_NUM_5, .rx_io = GPIO_NUM_4, .clkout_io = TWAI_IO_UNUSED, .bus_off_io = TWAI_IO_UNUSED, .tx_queue_len = 5, .rx_queue_len = 5, .alerts_enabled = TWAI_ALERT_NONE, .clkout_divider = 0 }; twai_timing_config_t t_config = TWAI_TIMING_CONFIG_500KBITS(); twai_filter_config_t f_config = TWAI_FILTER_CONFIG_ACCEPT_ALL(); // Install TWAI driver if (twai_driver_install(&g_config, &t_config, &f_config) == ESP_OK) { printf("Driver installed\n"); } else { printf("Failed to install driver\n"); return; } // Start TWAI driver if (twai_start() == ESP_OK) { printf("Driver started\n"); } else { printf("Failed to start driver\n"); return; } } void new_message(twai_message_t *message, uint32_t id, uint8_t dlc, uint8_t *data) { message->flags = TWAI_MSG_FLAG_NONE; message->identifier = id; message->data_length_code = dlc; for (int i = 0; i < dlc; i++) { message->data[i] = data[i]; } printf("Message created\nID: %ld DLC: %d Data:\t", message->identifier, message->data_length_code); for (int i = 0; i < message->data_length_code; i++) { printf("%d\t", message->data[i]); } printf("\n"); } void transmit_message(twai_message_t *message) { if (twai_transmit(message, pdMS_TO_TICKS(1000)) == ESP_OK) { printf("Message queued for transmission\n"); } else { printf("Failed to send message\n"); } } void receive_message(twai_message_t *message) { if (twai_receive(message, pdMS_TO_TICKS(1000)) == ESP_OK) { printf("Message received:\n"); printf("ID: %ld DLC: %d Data:\t", message->identifier, message->data_length_code); for (int i = 0; i < message->data_length_code; i++) { (message->extd)?printf("Extended ID"):printf("Standard ID"); printf("%d\t", message->data[i]); } } else { printf("Failed to receive message\n"); } } void app_main() { twai_setup_and_install(); twai_message_t message; twai_message_t message1; // Set the data to send uint8_t data[8] = {rand() % 255, rand() % 255, rand() % 255, rand() % 255, rand() % 255, rand() % 255, rand() % 255, rand() % 255}; while(true){ // Create a new message new_message(&message, 0x123, 8, data); // Transmit the message to a queue transmit_message(&message); // Receive the message from the queue receive_message(&message1); // Wait for 1 second vTaskDelay(1000 / portTICK_PERIOD_MS); } }
@brice-fr @eloebl @atanisoft @jepler
If anyone can help me, it would be really appreciated!
Regards,
Awaiting reply ASAP
@Kunaalkk1 Hi, I'm currently working with the same board and the same code, but it also doesn't work... have you figured it out in the meantime?
Just Recover from BUS OFF state - here is example
void drv_can_check_bus_off_and_recover(void) { twai_status_info_t status_info; esp_err_t twai_err = twai_get_status_info(&status_info);
if(twai_err == ESP_OK)
{
ESP_LOGI(TAG, "twai_status : %s",
(status_info.state == TWAI_STATE_STOPPED)? "TWAI_STATE_STOPPED" :
(status_info.state == TWAI_STATE_RUNNING)? "TWAI_STATE_RUNNING" :
(status_info.state == TWAI_STATE_BUS_OFF)? "TWAI_STATE_BUS_OFF" :
(status_info.state == TWAI_STATE_RECOVERING)? "TWAI_STATE_RECOVERING" : "TWAI_STATE_UNKNOWN"
);
if (status_info.state == TWAI_STATE_BUS_OFF)
{
if(twai_initiate_recovery() == ESP_OK)
{
ESP_LOGW(TAG, "twai_initiate_recovery");
}
else
{
ESP_LOGE(TAG, "twai_initiate_recovery failure");
}
}
else
if (status_info.state == TWAI_STATE_STOPPED)
{
if(twai_start() == ESP_OK)
{
ESP_LOGW(TAG, "twai_start");
}
else
{
ESP_LOGE(TAG, "twai_start failure");
}
}
}
}
Environment
git describe --tags
to find it): master (latest)xtensa-esp32-elf-gcc --version
to find it): 8.2.0r2Problem Description
The TWAI driver does not trigger RX events when running at 125kbps (pins rx: 36, tx: 37) with accept all filter.
Expected Behavior
Actual Behavior
Steps to reproduce
After fixing https://github.com/espressif/esp-idf/issues/5603 mappings (minimum needed for my old code):
I was able to compile my old code (https://github.com/openmrn/OpenMRNLite/tree/master/examples/ESP32IOBoard). I can see the frames being transmitted by the S2 to the other devices on the network but the S2 never raises an RX event.
I added
to https://github.com/espressif/esp-idf/blob/master/components/soc/src/hal/twai_hal.c#L91 in order to confirm the RX event was never raised: