can_wizard/main/can.c

104 lines
3.5 KiB
C
Raw Normal View History

2023-11-22 11:48:03 +00:00
#include "can.h"
#include "esp_log.h"
#include "freertos/projdefs.h"
2023-11-22 11:48:03 +00:00
#include "sdkconfig.h"
#include <stddef.h>
2023-11-22 11:48:03 +00:00
#include <stdio.h>
2023-11-24 05:30:27 +00:00
#include <string.h>
#include "freertos/ringbuf.h"
#include "xvprintf.h"
2023-11-25 08:01:19 +00:00
bool is_error_passive = false;
2023-11-26 05:34:12 +00:00
SemaphoreHandle_t can_mutex;
volatile can_status_t curr_can_state = { 0 };
2023-11-26 05:34:12 +00:00
static can_status_t get_can_state() {
can_status_t result;
twai_status_info_t status = { 0 };
2023-11-25 08:01:19 +00:00
esp_err_t res = twai_get_status_info(&status);
if (res != ESP_OK) {
result.state = CAN_NOT_INSTALLED;
return result;
}
result.msgs_to_rx = status.msgs_to_rx;
result.msgs_to_tx = status.msgs_to_tx;
result.arb_lost_count = status.arb_lost_count;
result.bus_error_count = status.bus_error_count;
result.tx_error_counter = status.tx_error_counter;
result.rx_error_counter = status.rx_error_counter;
result.tx_failed_count = status.tx_failed_count;
result.rx_missed_count = status.rx_missed_count;
result.rx_overrun_count = status.rx_overrun_count;
2023-11-25 08:01:19 +00:00
switch (status.state) {
case TWAI_STATE_STOPPED:
result.state = CAN_STOPPED;
break;
2023-11-25 08:01:19 +00:00
case TWAI_STATE_BUS_OFF:
result.state = CAN_BUF_OFF;
break;
2023-11-25 08:01:19 +00:00
case TWAI_STATE_RECOVERING:
result.state = CAN_RECOVERING;
break;
2023-11-25 08:01:19 +00:00
default:
if (is_error_passive) result.state = CAN_ERROR_PASSIVE;
else result.state = CAN_ERROR_ACTIVE;
break;
2023-11-25 08:01:19 +00:00
}
return result;
2023-11-25 08:01:19 +00:00
}
void can_msg_to_str(twai_message_t *can_msg, char *start_str, char *out_str) {
char byte_str[3];
out_str[0] = '\0';
sprintf(out_str, "%scan frame: ID: %08X dlc: %d ", start_str, (int) can_msg->identifier, can_msg->data_length_code);
if (can_msg->data_length_code == 0) {
strcat(out_str, "(no data)");
} else {
strcat(out_str, "data: ");
for (int i = 0; i < can_msg->data_length_code; i++) {
sprintf(byte_str, "%02X", can_msg->data[i]);
strcat(out_str, byte_str);
}
}
}
// TODO: add software filtering
2023-11-22 11:48:03 +00:00
void can_task(void* arg) {
static const TickType_t can_task_timeout = pdMS_TO_TICKS(10);
2023-11-28 05:55:08 +00:00
uint32_t alerts = 0;
2023-11-26 05:34:12 +00:00
can_mutex = xSemaphoreCreateMutex();
2023-11-22 11:48:03 +00:00
twai_message_t rx_msg;
char data_bytes_str[70];
2023-11-22 11:48:03 +00:00
for (;;) { // A Task shall never return or exit.
2023-11-28 05:55:08 +00:00
if (twai_read_alerts(&alerts, 0) == ESP_OK) {
2023-11-28 06:51:44 +00:00
if (alerts & TWAI_ALERT_ERR_ACTIVE) {
is_error_passive = false;
}
if (alerts & TWAI_ALERT_ERR_PASS) {
is_error_passive = true;
}
if (alerts & TWAI_ALERT_BUS_ERROR) {
print_w_clr_time("CAN error!", LOG_COLOR_RED, false);
2023-11-28 06:51:44 +00:00
}
2023-11-28 05:55:08 +00:00
if (alerts & TWAI_ALERT_BUS_OFF) {
print_w_clr_time("CAN went bus-off!", LOG_COLOR_RED, false);
2023-11-28 05:55:08 +00:00
// ESP_ERROR_CHECK(twai_initiate_recovery());
}
if (alerts & TWAI_ALERT_BUS_RECOVERED) {
print_w_clr_time("CAN recovered!", LOG_COLOR_BLUE, false);
2023-11-28 05:55:08 +00:00
// ESP_ERROR_CHECK(twai_start());
}
}
2023-11-28 06:51:44 +00:00
curr_can_state = get_can_state();
2023-11-28 05:55:08 +00:00
if (xSemaphoreTake(can_mutex, 0) == pdTRUE) {
2023-11-28 06:51:44 +00:00
while (twai_receive(&rx_msg, 0) == ESP_OK) {
can_msg_to_str(&rx_msg, "recv ", data_bytes_str);
print_w_clr_time(data_bytes_str, LOG_COLOR_BLUE, false);
2023-11-28 05:55:08 +00:00
}
xSemaphoreGive(can_mutex);
2023-11-28 06:51:44 +00:00
}
vTaskDelay(can_task_timeout);
2023-11-22 11:48:03 +00:00
}
}