258 lines
8.8 KiB
C
258 lines
8.8 KiB
C
|
/* TWAI Network Slave Example
|
||
|
|
||
|
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||
|
|
||
|
Unless required by applicable law or agreed to in writing, this
|
||
|
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||
|
CONDITIONS OF ANY KIND, either express or implied.
|
||
|
*/
|
||
|
|
||
|
/*
|
||
|
* The following example demonstrates a slave node in a TWAI network. The slave
|
||
|
* node is responsible for sending data messages to the master. The example will
|
||
|
* execute multiple iterations, with each iteration the slave node will do the
|
||
|
* following:
|
||
|
* 1) Start the TWAI driver
|
||
|
* 2) Listen for ping messages from master, and send ping response
|
||
|
* 3) Listen for start command from master
|
||
|
* 4) Send data messages to master and listen for stop command
|
||
|
* 5) Send stop response to master
|
||
|
* 6) Stop the TWAI driver
|
||
|
*/
|
||
|
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include "freertos/FreeRTOS.h"
|
||
|
#include "freertos/task.h"
|
||
|
#include "freertos/queue.h"
|
||
|
#include "freertos/semphr.h"
|
||
|
#include "esp_err.h"
|
||
|
#include "esp_log.h"
|
||
|
#include "driver/twai.h"
|
||
|
|
||
|
#include "can_network.h"
|
||
|
|
||
|
/* --------------------- Definitions and static variables ------------------ */
|
||
|
// Example Configuration
|
||
|
#define DATA_PERIOD_MS 50
|
||
|
#define NO_OF_ITERS 3
|
||
|
#define ITER_DELAY_MS 1000
|
||
|
#define RX_TASK_PRIO 41 // Receiving task priority
|
||
|
#define TX_TASK_PRIO 42 // Sending task priority
|
||
|
#define CTRL_TSK_PRIO 10 // Control task priority
|
||
|
#define TX_GPIO_NUM 14
|
||
|
#define RX_GPIO_NUM 21
|
||
|
#define TAG "CAN"
|
||
|
|
||
|
#define ID_MASTER_STOP_CMD 0x0A0
|
||
|
#define ID_MASTER_START_CMD 0x0A1
|
||
|
#define ID_MASTER_PING 0x0A2
|
||
|
#define ID_SLAVE_STOP_RESP 0x0B0
|
||
|
#define ID_SLAVE_DATA 0x0B1
|
||
|
#define ID_SLAVE_PING_RESP 0x0B2
|
||
|
|
||
|
typedef enum
|
||
|
{
|
||
|
TX_SEND_PING_RESP,
|
||
|
TX_SEND_DATA,
|
||
|
TX_SEND_STOP_RESP,
|
||
|
TX_TASK_EXIT,
|
||
|
} tx_task_action_t;
|
||
|
|
||
|
typedef enum
|
||
|
{
|
||
|
RX_RECEIVE_PING,
|
||
|
RX_RECEIVE_START_CMD,
|
||
|
RX_RECEIVE_STOP_CMD,
|
||
|
RX_TASK_EXIT,
|
||
|
} rx_task_action_t;
|
||
|
|
||
|
|
||
|
|
||
|
static const twai_timing_config_t t_config = TWAI_TIMING_CONFIG_250KBITS();
|
||
|
static const twai_filter_config_t f_config = TWAI_FILTER_CONFIG_ACCEPT_ALL();
|
||
|
static const twai_general_config_t g_config = TWAI_GENERAL_CONFIG_DEFAULT(TX_GPIO_NUM, RX_GPIO_NUM, TWAI_MODE_NORMAL);
|
||
|
|
||
|
// static const twai_message_t ping_resp = {.identifier = ID_SLAVE_PING_RESP, .data_length_code = 0, .data = {0, 0, 0, 0, 0, 0, 0, 0}};
|
||
|
// static const twai_message_t stop_resp = {.identifier = ID_SLAVE_STOP_RESP, .data_length_code = 0, .data = {0, 0, 0, 0, 0, 0, 0, 0}};
|
||
|
// Data bytes of data message will be initialized in the transmit task
|
||
|
// twai_message_t data_message = {.identifier = ID_SLAVE_DATA, .data_length_code = 8, .data = {0, 0, 0, 0, 0, 0, 0, 0}};
|
||
|
|
||
|
// static QueueHandle_t tx_task_queue;
|
||
|
// static QueueHandle_t rx_task_queue;
|
||
|
// static SemaphoreHandle_t ctrl_task_sem;
|
||
|
// static SemaphoreHandle_t stop_data_sem;
|
||
|
// static SemaphoreHandle_t done_sem;
|
||
|
|
||
|
/* --------------------------- Tasks and Functions -------------------------- */
|
||
|
|
||
|
static void twai_receive_task(void *arg)
|
||
|
{
|
||
|
twai_message_t rx_msg;
|
||
|
int i;
|
||
|
while (1)
|
||
|
{
|
||
|
char msg_data_str[32];
|
||
|
int index = 0;
|
||
|
esp_err_t err = twai_receive(&rx_msg, portMAX_DELAY);
|
||
|
if (err == ESP_OK)
|
||
|
{
|
||
|
for (i = 0; i < rx_msg.data_length_code; i++)
|
||
|
{
|
||
|
index += sprintf(&msg_data_str[i], "%02x ", rx_msg.data[i]);
|
||
|
}
|
||
|
ESP_LOGI(TAG, "recive msg id=%x,len=%d,data=[%s]", rx_msg.identifier, rx_msg.data_length_code, msg_data_str);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// static void twai_transmit_task(void *arg)
|
||
|
// {
|
||
|
// while (1)
|
||
|
// {
|
||
|
// tx_task_action_t action;
|
||
|
// xQueueReceive(tx_task_queue, &action, portMAX_DELAY);
|
||
|
|
||
|
// if (action == TX_SEND_PING_RESP)
|
||
|
// {
|
||
|
// // Transmit ping response to master
|
||
|
// twai_transmit(&ping_resp, portMAX_DELAY);
|
||
|
// ESP_LOGI(EXAMPLE_TAG, "Transmitted ping response");
|
||
|
// xSemaphoreGive(ctrl_task_sem);
|
||
|
// }
|
||
|
// else if (action == TX_SEND_DATA)
|
||
|
// {
|
||
|
// // Transmit data messages until stop command is received
|
||
|
// ESP_LOGI(EXAMPLE_TAG, "Start transmitting data");
|
||
|
// while (1)
|
||
|
// {
|
||
|
// // FreeRTOS tick count used to simulate sensor data
|
||
|
// uint32_t sensor_data = xTaskGetTickCount();
|
||
|
// for (int i = 0; i < 4; i++)
|
||
|
// {
|
||
|
// data_message.data[i] = (sensor_data >> (i * 8)) & 0xFF;
|
||
|
// }
|
||
|
// twai_transmit(&data_message, portMAX_DELAY);
|
||
|
// ESP_LOGI(EXAMPLE_TAG, "Transmitted data value %d", sensor_data);
|
||
|
// vTaskDelay(pdMS_TO_TICKS(DATA_PERIOD_MS));
|
||
|
// if (xSemaphoreTake(stop_data_sem, 0) == pdTRUE)
|
||
|
// {
|
||
|
// break;
|
||
|
// }
|
||
|
// }
|
||
|
// }
|
||
|
// else if (action == TX_SEND_STOP_RESP)
|
||
|
// {
|
||
|
// // Transmit stop response to master
|
||
|
// twai_transmit(&stop_resp, portMAX_DELAY);
|
||
|
// ESP_LOGI(EXAMPLE_TAG, "Transmitted stop response");
|
||
|
// xSemaphoreGive(ctrl_task_sem);
|
||
|
// }
|
||
|
// else if (action == TX_TASK_EXIT)
|
||
|
// {
|
||
|
// break;
|
||
|
// }
|
||
|
// }
|
||
|
// vTaskDelete(NULL);
|
||
|
// }
|
||
|
|
||
|
// static void twai_control_task(void *arg)
|
||
|
// {
|
||
|
// xSemaphoreTake(ctrl_task_sem, portMAX_DELAY);
|
||
|
// tx_task_action_t tx_action;
|
||
|
// rx_task_action_t rx_action;
|
||
|
|
||
|
// for (int iter = 0; iter < NO_OF_ITERS; iter++)
|
||
|
// {
|
||
|
// ESP_ERROR_CHECK(twai_start());
|
||
|
// ESP_LOGI(EXAMPLE_TAG, "Driver started");
|
||
|
|
||
|
// // Listen of pings from master
|
||
|
// rx_action = RX_RECEIVE_PING;
|
||
|
// xQueueSend(rx_task_queue, &rx_action, portMAX_DELAY);
|
||
|
// xSemaphoreTake(ctrl_task_sem, portMAX_DELAY);
|
||
|
|
||
|
// // Send ping response
|
||
|
// tx_action = TX_SEND_PING_RESP;
|
||
|
// xQueueSend(tx_task_queue, &tx_action, portMAX_DELAY);
|
||
|
// xSemaphoreTake(ctrl_task_sem, portMAX_DELAY);
|
||
|
|
||
|
// // Listen for start command
|
||
|
// rx_action = RX_RECEIVE_START_CMD;
|
||
|
// xQueueSend(rx_task_queue, &rx_action, portMAX_DELAY);
|
||
|
// xSemaphoreTake(ctrl_task_sem, portMAX_DELAY);
|
||
|
|
||
|
// // Start sending data messages and listen for stop command
|
||
|
// tx_action = TX_SEND_DATA;
|
||
|
// rx_action = RX_RECEIVE_STOP_CMD;
|
||
|
// xQueueSend(tx_task_queue, &tx_action, portMAX_DELAY);
|
||
|
// xQueueSend(rx_task_queue, &rx_action, portMAX_DELAY);
|
||
|
// xSemaphoreTake(ctrl_task_sem, portMAX_DELAY);
|
||
|
|
||
|
// // Send stop response
|
||
|
// tx_action = TX_SEND_STOP_RESP;
|
||
|
// xQueueSend(tx_task_queue, &tx_action, portMAX_DELAY);
|
||
|
// xSemaphoreTake(ctrl_task_sem, portMAX_DELAY);
|
||
|
|
||
|
// // Wait for bus to become free
|
||
|
// twai_status_info_t status_info;
|
||
|
// twai_get_status_info(&status_info);
|
||
|
// while (status_info.msgs_to_tx > 0)
|
||
|
// {
|
||
|
// vTaskDelay(pdMS_TO_TICKS(100));
|
||
|
// twai_get_status_info(&status_info);
|
||
|
// }
|
||
|
|
||
|
// ESP_ERROR_CHECK(twai_stop());
|
||
|
// ESP_LOGI(EXAMPLE_TAG, "Driver stopped");
|
||
|
// vTaskDelay(pdMS_TO_TICKS(ITER_DELAY_MS));
|
||
|
// }
|
||
|
|
||
|
// // Stop TX and RX tasks
|
||
|
// tx_action = TX_TASK_EXIT;
|
||
|
// rx_action = RX_TASK_EXIT;
|
||
|
// xQueueSend(tx_task_queue, &tx_action, portMAX_DELAY);
|
||
|
// xQueueSend(rx_task_queue, &rx_action, portMAX_DELAY);
|
||
|
|
||
|
// // Delete Control task
|
||
|
// xSemaphoreGive(done_sem);
|
||
|
// vTaskDelete(NULL);
|
||
|
// }
|
||
|
|
||
|
|
||
|
void can_init(void)
|
||
|
{
|
||
|
// Add short delay to allow master it to initialize first
|
||
|
|
||
|
// Create semaphores and tasks
|
||
|
// tx_task_queue = xQueueCreate(1, sizeof(tx_task_action_t));
|
||
|
// rx_task_queue = xQueueCreate(1, sizeof(rx_task_action_t));
|
||
|
// ctrl_task_sem = xSemaphoreCreateBinary();
|
||
|
// stop_data_sem = xSemaphoreCreateBinary();;
|
||
|
// done_sem = xSemaphoreCreateBinary();;
|
||
|
ESP_ERROR_CHECK(twai_driver_install(&g_config, &t_config, &f_config));
|
||
|
ESP_LOGI(TAG, "Driver installed");
|
||
|
|
||
|
xTaskCreatePinnedToCore(twai_receive_task, "CAN_rx", 1024, NULL, RX_TASK_PRIO, NULL, tskNO_AFFINITY);
|
||
|
twai_start();
|
||
|
// xTaskCreatePinnedToCore(twai_transmit_task, "TWAI_tx", 4096, NULL, TX_TASK_PRIO, NULL, tskNO_AFFINITY);
|
||
|
// xTaskCreatePinnedToCore(twai_control_task, "TWAI_ctrl", 4096, NULL, CTRL_TSK_PRIO, NULL, tskNO_AFFINITY);
|
||
|
|
||
|
// Install TWAI driver, trigger tasks to start
|
||
|
// ESP_ERROR_CHECK(twai_driver_install(&g_config, &t_config, &f_config));
|
||
|
|
||
|
// xSemaphoreGive(ctrl_task_sem); // Start Control task
|
||
|
// xSemaphoreTake(done_sem, portMAX_DELAY); // Wait for tasks to complete
|
||
|
|
||
|
// //Uninstall TWAI driver
|
||
|
// ESP_ERROR_CHECK(twai_driver_uninstall());
|
||
|
// ESP_LOGI(EXAMPLE_TAG, "Driver uninstalled");
|
||
|
|
||
|
// //Cleanup
|
||
|
// vSemaphoreDelete(ctrl_task_sem);
|
||
|
// vSemaphoreDelete(stop_data_sem);
|
||
|
// vSemaphoreDelete(done_sem);
|
||
|
// vQueueDelete(tx_task_queue);
|
||
|
// vQueueDelete(rx_task_queue);
|
||
|
}
|