mirror of
https://gitee.com/beecue/fastbee.git
synced 2025-12-20 01:45:55 +08:00
添加智能灯固件代码
This commit is contained in:
@@ -0,0 +1,184 @@
|
||||
# TWAI Network Example
|
||||
|
||||
(See the README.md file in the upper level 'examples' directory for more information about examples.)
|
||||
|
||||
This example demonstrates how to use the TWAI driver to program a target (ESP32 or ESP32-S2) as a TWAI node, and have the two nodes (Network Master and Network Slave) communicate on a TWAI network. The Listen Only node is optional and acts as a network monitor meaning that it only receives messages and does not influence the bus in any way (i.e. doesn't not acknowledge or send error frames).
|
||||
|
||||
Note that concept of master/slave in this example refers to which node initiates
|
||||
and stops the transfer of a stream of data messages.
|
||||
|
||||
## How to use example
|
||||
|
||||
### Hardware Required
|
||||
|
||||
This example requires at least two targets (e.g., an ESP32 or ESP32-S2) to act as the Network Master and Network Slave. The third target (Listen Only) is optional. Each target must be connected to an external transceiver (e.g., a SN65HVD23X transceiver). The transceivers must then be interconnected to form a TWAI network.
|
||||
|
||||
The following diagram illustrates an example network:
|
||||
|
||||
```
|
||||
---------- ---------- --------------
|
||||
| Master | | Slave | | Listen Only |
|
||||
| | | | | |
|
||||
| TX RX | | TX RX | | TX RX |
|
||||
---------- ---------- --------------
|
||||
| | | | | |
|
||||
| | | | | |
|
||||
---------- ---------- ----------
|
||||
| D R | | D R | | D R |
|
||||
| | | | | |
|
||||
| VP230 | | VP230 | | VP230 |
|
||||
| | | | | |
|
||||
| H L | | H L | | H L |
|
||||
---------- ---------- ----------
|
||||
| | | | | |
|
||||
| | | | | |
|
||||
|--x------|-----x------|-----x------|--| H
|
||||
| | |
|
||||
|---------x------------x------------x--| L
|
||||
|
||||
```
|
||||
|
||||
Note: If you don't have an external transceiver, you can still run the [TWAI Self Test example](../twai_self_test/README.md)
|
||||
|
||||
### Configure the project
|
||||
|
||||
For each node in the TWAI network (i.e., Master, Slave, Listen Only)...
|
||||
|
||||
* Set the target of the build (where `{IDF_TARGET}` stands for the target chip such as `eszp32` or `esp32s2`).
|
||||
* Then run `menuconfig` to configure the example.
|
||||
|
||||
```
|
||||
idf.py set-target {IDF_TARGET}
|
||||
idf.py menuconfig
|
||||
```
|
||||
|
||||
* Under `Example Configuration`, configure the pin assignments using the options `TX GPIO Number` and `RX GPIO Number` according to how the target was connected to the transceiver. By default, `TX GPIO Number` and `RX GPIO Number` are set to the following values:
|
||||
* On the ESP32, `TX GPIO Number` and `RX GPIO Number` default to `21` and `22` respectively
|
||||
* On the ESP32-S2, `TX GPIO Number` and `RX GPIO Number` default to `20` and `21` respectively
|
||||
|
||||
|
||||
### Build and Flash
|
||||
|
||||
For each node, build the project and flash it to the board, then run monitor tool to view serial output:
|
||||
|
||||
```
|
||||
idf.py -p PORT flash monitor
|
||||
```
|
||||
|
||||
(Replace PORT with the name of the serial port to use.)
|
||||
|
||||
(To exit the serial monitor, type ``Ctrl-]``.)
|
||||
|
||||
See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects.
|
||||
|
||||
## Example Output
|
||||
|
||||
Network Master
|
||||
```
|
||||
I (345) TWAI Master: Driver installed
|
||||
I (345) TWAI Master: Driver started
|
||||
I (345) TWAI Master: Transmitting ping
|
||||
I (3105) TWAI Master: Transmitted start command
|
||||
I (3105) TWAI Master: Received data value 339
|
||||
...
|
||||
I (5545) TWAI Master: Received data value 584
|
||||
I (5545) TWAI Master: Transmitted stop command
|
||||
I (5595) TWAI Master: Driver stopped
|
||||
I (6595) TWAI Master: Driver started
|
||||
I (6595) TWAI Master: Transmitting ping
|
||||
I (7095) TWAI Master: Transmitted start command
|
||||
I (7095) TWAI Master: Received data value 738
|
||||
...
|
||||
I (9535) TWAI Master: Received data value 983
|
||||
I (9535) TWAI Master: Transmitted stop command
|
||||
I (9585) TWAI Master: Driver stopped
|
||||
I (10585) TWAI Master: Driver started
|
||||
I (10585) TWAI Master: Transmitting ping
|
||||
I (11085) TWAI Master: Transmitted start command
|
||||
I (11085) TWAI Master: Received data value 1137
|
||||
...
|
||||
I (13525) TWAI Master: Received data value 1382
|
||||
I (13525) TWAI Master: Transmitted stop command
|
||||
I (13575) TWAI Master: Driver stopped
|
||||
I (14575) TWAI Master: Driver uninstalled
|
||||
```
|
||||
|
||||
Network Slave
|
||||
```
|
||||
Slave starting in 3
|
||||
Slave starting in 2
|
||||
Slave starting in 1
|
||||
I (6322) TWAI Slave: Driver installed
|
||||
I (6322) TWAI Slave: Driver started
|
||||
I (6462) TWAI Slave: Transmitted ping response
|
||||
I (6712) TWAI Slave: Start transmitting data
|
||||
I (6712) TWAI Slave: Transmitted data value 339
|
||||
...
|
||||
I (9162) TWAI Slave: Transmitted data value 584
|
||||
I (9212) TWAI Slave: Transmitted stop response
|
||||
I (9312) TWAI Slave: Driver stopped
|
||||
I (10312) TWAI Slave: Driver started
|
||||
I (10452) TWAI Slave: Transmitted ping response
|
||||
I (10702) TWAI Slave: Start transmitting data
|
||||
I (10702) TWAI Slave: Transmitted data value 738
|
||||
...
|
||||
I (13152) TWAI Slave: Transmitted data value 983
|
||||
I (13202) TWAI Slave: Transmitted stop response
|
||||
I (13302) TWAI Slave: Driver stopped
|
||||
I (14302) TWAI Slave: Driver started
|
||||
I (14442) TWAI Slave: Transmitted ping response
|
||||
I (14692) TWAI Slave: Start transmitting data
|
||||
I (14692) TWAI Slave: Transmitted data value 1137
|
||||
...
|
||||
I (17142) TWAI Slave: Transmitted data value 1382
|
||||
I (17192) TWAI Slave: Transmitted stop response
|
||||
I (17292) TWAI Slave: Driver stopped
|
||||
I (18292) TWAI Slave: Driver uninstalled
|
||||
```
|
||||
|
||||
Network Listen Only
|
||||
```
|
||||
I (326) TWAI Listen Only: Driver installed
|
||||
I (326) TWAI Listen Only: Driver started
|
||||
I (366) TWAI Listen Only: Received master ping
|
||||
...
|
||||
I (1866) TWAI Listen Only: Received master ping
|
||||
I (1866) TWAI Listen Only: Received slave ping response
|
||||
I (2116) TWAI Listen Only: Received master start command
|
||||
I (2116) TWAI Listen Only: Received data value 329
|
||||
...
|
||||
I (4566) TWAI Listen Only: Received data value 574
|
||||
I (4566) TWAI Listen Only: Received master stop command
|
||||
I (4606) TWAI Listen Only: Received slave stop response
|
||||
I (5606) TWAI Listen Only: Received master ping
|
||||
I (5856) TWAI Listen Only: Received master ping
|
||||
I (5856) TWAI Listen Only: Received slave ping response
|
||||
I (6106) TWAI Listen Only: Received master start command
|
||||
I (6106) TWAI Listen Only: Received data value 728
|
||||
...
|
||||
I (8556) TWAI Listen Only: Received data value 973
|
||||
I (8556) TWAI Listen Only: Received master stop command
|
||||
I (8596) TWAI Listen Only: Received slave stop response
|
||||
I (9596) TWAI Listen Only: Received master ping
|
||||
I (9846) TWAI Listen Only: Received master ping
|
||||
I (9846) TWAI Listen Only: Received slave ping response
|
||||
I (10096) TWAI Listen Only: Received master start command
|
||||
I (10096) TWAI Listen Only: Received data value 1127
|
||||
...
|
||||
I (12546) TWAI Listen Only: Received data value 1372
|
||||
I (12546) TWAI Listen Only: Received master stop command
|
||||
I (12586) TWAI Listen Only: Received slave stop response
|
||||
I (12586) TWAI Listen Only: Driver stopped
|
||||
I (12586) TWAI Listen Only: Driver uninstalled
|
||||
|
||||
```
|
||||
|
||||
## Example Breakdown
|
||||
|
||||
The communication between the Network Master and Network Slave execute the following steps over multiple iterations:
|
||||
|
||||
1. Both master and slave go through install and start their TWAI drivers independently.
|
||||
2. The master repeatedly sends **PING** messages until it receives a **PING_RESP** (ping response message) from the slave. The slave will only send a **PING_RESP** message when it receives a **PING** message from the master.
|
||||
3. Once the master has received the **PING_RESP** from the slave, it will send a **START_CMD** message to the slave.
|
||||
4. Upon receiving the **START_CMD** message, the slave will start transmitting **DATA** messages until the master sends a **STOP_CMD**. The master will send the **STOP_CMD** after receiving N **DATA** messages from the slave (N = 50 by default).
|
||||
5. When the slave receives the **STOP_CMD**, it will confirm that it has stopped by sending a **STOP_RESP** message to the master.
|
||||
@@ -0,0 +1,74 @@
|
||||
# Need Python 3 string formatting functions
|
||||
from __future__ import print_function
|
||||
|
||||
from threading import Thread
|
||||
|
||||
import ttfw_idf
|
||||
|
||||
# Define tuple of strings to expect for each DUT.
|
||||
master_expect = ("TWAI Master: Driver installed", "TWAI Master: Driver uninstalled")
|
||||
slave_expect = ("TWAI Slave: Driver installed", "TWAI Slave: Driver uninstalled")
|
||||
listen_only_expect = ("TWAI Listen Only: Driver installed", "TWAI Listen Only: Driver uninstalled")
|
||||
|
||||
|
||||
def dut_thread_callback(**kwargs):
|
||||
# Parse keyword arguments
|
||||
dut = kwargs['dut'] # Get DUT from kwargs
|
||||
expected = kwargs['expected']
|
||||
result = kwargs['result'] # Get result[out] from kwargs. MUST be of mutable type e.g. list
|
||||
|
||||
# Must reset again as flashing during start_app will reset multiple times, causing unexpected results
|
||||
dut.reset()
|
||||
|
||||
for string in expected:
|
||||
dut.expect(string, 20)
|
||||
|
||||
# Mark thread has run to completion without any exceptions
|
||||
result[0] = True
|
||||
|
||||
|
||||
@ttfw_idf.idf_example_test(env_tag='Example_TWAI2')
|
||||
def test_twai_network_example(env, extra_data):
|
||||
|
||||
# Get device under test. "dut1", "dut2", and "dut3" must be properly defined in EnvConfig
|
||||
dut_master = env.get_dut("dut1", "examples/peripherals/twai/twai_network/twai_network_master",
|
||||
dut_class=ttfw_idf.ESP32DUT)
|
||||
dut_slave = env.get_dut("dut2", "examples/peripherals/twai/twai_network/twai_network_slave",
|
||||
dut_class=ttfw_idf.ESP32DUT)
|
||||
dut_listen_only = env.get_dut("dut3", "examples/peripherals/twai/twai_network/twai_network_listen_only",
|
||||
dut_class=ttfw_idf.ESP32DUT)
|
||||
|
||||
# Flash app onto each DUT, each DUT is reset again at the start of each thread
|
||||
dut_master.start_app()
|
||||
dut_slave.start_app()
|
||||
dut_listen_only.start_app()
|
||||
|
||||
# Create dict of keyword arguments for each dut
|
||||
results = [[False], [False], [False]]
|
||||
master_kwargs = {"dut": dut_master, "result": results[0], "expected": master_expect}
|
||||
slave_kwargs = {"dut": dut_slave, "result": results[1], "expected": slave_expect}
|
||||
listen_only_kwargs = {"dut": dut_listen_only, "result": results[2], "expected": listen_only_expect}
|
||||
|
||||
# Create thread for each dut
|
||||
dut_master_thread = Thread(target=dut_thread_callback, name="Master Thread", kwargs=master_kwargs)
|
||||
dut_slave_thread = Thread(target=dut_thread_callback, name="Slave Thread", kwargs=slave_kwargs)
|
||||
dut_listen_only_thread = Thread(target=dut_thread_callback, name="Listen Only Thread", kwargs=listen_only_kwargs)
|
||||
|
||||
# Start each thread
|
||||
dut_listen_only_thread.start()
|
||||
dut_master_thread.start()
|
||||
dut_slave_thread.start()
|
||||
|
||||
# Wait for threads to complete
|
||||
dut_listen_only_thread.join()
|
||||
dut_master_thread.join()
|
||||
dut_slave_thread.join()
|
||||
|
||||
# check each thread ran to completion
|
||||
for result in results:
|
||||
if result[0] is not True:
|
||||
raise Exception("One or more threads did not run successfully")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
test_twai_network_example()
|
||||
@@ -0,0 +1,6 @@
|
||||
# The following lines of boilerplate have to be in your project's CMakeLists
|
||||
# in this exact order for cmake to work correctly
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(twai_network_listen_only)
|
||||
@@ -0,0 +1,9 @@
|
||||
#
|
||||
# This is a project Makefile. It is assumed the directory this Makefile resides in is a
|
||||
# project subdirectory.
|
||||
#
|
||||
|
||||
PROJECT_NAME := twai_network_listen_only
|
||||
|
||||
include $(IDF_PATH)/make/project.mk
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
idf_component_register(SRCS "twai_network_example_listen_only_main.c"
|
||||
INCLUDE_DIRS ".")
|
||||
@@ -0,0 +1,19 @@
|
||||
menu "Example Configuration"
|
||||
|
||||
config EXAMPLE_TX_GPIO_NUM
|
||||
int "TX GPIO number"
|
||||
default 20 if IDF_TARGET_ESP32S2
|
||||
default 21 if IDF_TARGET_ESP32
|
||||
help
|
||||
This option selects the GPIO pin used for the TX signal. Connect the
|
||||
TX signal to your transceiver.
|
||||
|
||||
config EXAMPLE_RX_GPIO_NUM
|
||||
int "RX GPIO number"
|
||||
default 21 if IDF_TARGET_ESP32S2
|
||||
default 22 if IDF_TARGET_ESP32
|
||||
help
|
||||
This option selects the GPIO pin used for the RX signal. Connect the
|
||||
RX signal to your transceiver.
|
||||
|
||||
endmenu
|
||||
@@ -0,0 +1,4 @@
|
||||
#
|
||||
# Main Makefile. This is basically the same as a component makefile.
|
||||
#
|
||||
# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)
|
||||
@@ -0,0 +1,123 @@
|
||||
/* TWAI Network Listen Only 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 Listen Only node in a TWAI network. The
|
||||
* Listen Only node will not take part in any TWAI bus activity (no acknowledgments
|
||||
* and no error frames). This example will execute multiple iterations, with each
|
||||
* iteration the Listen Only node will do the following:
|
||||
* 1) Listen for ping and ping response
|
||||
* 2) Listen for start command
|
||||
* 3) Listen for data messages
|
||||
* 4) Listen for stop and stop response
|
||||
*/
|
||||
#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"
|
||||
|
||||
/* --------------------- Definitions and static variables ------------------ */
|
||||
//Example Configuration
|
||||
#define NO_OF_ITERS 3
|
||||
#define RX_TASK_PRIO 9
|
||||
#define TX_GPIO_NUM CONFIG_EXAMPLE_TX_GPIO_NUM
|
||||
#define RX_GPIO_NUM CONFIG_EXAMPLE_RX_GPIO_NUM
|
||||
#define EXAMPLE_TAG "TWAI Listen Only"
|
||||
|
||||
#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
|
||||
|
||||
static const twai_filter_config_t f_config = TWAI_FILTER_CONFIG_ACCEPT_ALL();
|
||||
static const twai_timing_config_t t_config = TWAI_TIMING_CONFIG_25KBITS();
|
||||
//Set TX queue length to 0 due to listen only mode
|
||||
static const twai_general_config_t g_config = {.mode = TWAI_MODE_LISTEN_ONLY,
|
||||
.tx_io = TX_GPIO_NUM, .rx_io = RX_GPIO_NUM,
|
||||
.clkout_io = TWAI_IO_UNUSED, .bus_off_io = TWAI_IO_UNUSED,
|
||||
.tx_queue_len = 0, .rx_queue_len = 5,
|
||||
.alerts_enabled = TWAI_ALERT_NONE,
|
||||
.clkout_divider = 0};
|
||||
|
||||
static SemaphoreHandle_t rx_sem;
|
||||
|
||||
/* --------------------------- Tasks and Functions -------------------------- */
|
||||
|
||||
static void twai_receive_task(void *arg)
|
||||
{
|
||||
xSemaphoreTake(rx_sem, portMAX_DELAY);
|
||||
bool start_cmd = false;
|
||||
bool stop_resp = false;
|
||||
uint32_t iterations = 0;
|
||||
|
||||
while (iterations < NO_OF_ITERS) {
|
||||
twai_message_t rx_msg;
|
||||
twai_receive(&rx_msg, portMAX_DELAY);
|
||||
if (rx_msg.identifier == ID_MASTER_PING) {
|
||||
ESP_LOGI(EXAMPLE_TAG, "Received master ping");
|
||||
} else if (rx_msg.identifier == ID_SLAVE_PING_RESP) {
|
||||
ESP_LOGI(EXAMPLE_TAG, "Received slave ping response");
|
||||
} else if (rx_msg.identifier == ID_MASTER_START_CMD) {
|
||||
ESP_LOGI(EXAMPLE_TAG, "Received master start command");
|
||||
start_cmd = true;
|
||||
} else if (rx_msg.identifier == ID_SLAVE_DATA) {
|
||||
uint32_t data = 0;
|
||||
for (int i = 0; i < rx_msg.data_length_code; i++) {
|
||||
data |= (rx_msg.data[i] << (i * 8));
|
||||
}
|
||||
ESP_LOGI(EXAMPLE_TAG, "Received data value %d", data);
|
||||
} else if (rx_msg.identifier == ID_MASTER_STOP_CMD) {
|
||||
ESP_LOGI(EXAMPLE_TAG, "Received master stop command");
|
||||
} else if (rx_msg.identifier == ID_SLAVE_STOP_RESP) {
|
||||
ESP_LOGI(EXAMPLE_TAG, "Received slave stop response");
|
||||
stop_resp = true;
|
||||
}
|
||||
if (start_cmd && stop_resp) {
|
||||
//Each iteration is complete after a start command and stop response is received
|
||||
iterations++;
|
||||
start_cmd = 0;
|
||||
stop_resp = 0;
|
||||
}
|
||||
}
|
||||
|
||||
xSemaphoreGive(rx_sem);
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
rx_sem = xSemaphoreCreateBinary();
|
||||
xTaskCreatePinnedToCore(twai_receive_task, "TWAI_rx", 4096, NULL, RX_TASK_PRIO, NULL, tskNO_AFFINITY);
|
||||
|
||||
//Install and start TWAI driver
|
||||
ESP_ERROR_CHECK(twai_driver_install(&g_config, &t_config, &f_config));
|
||||
ESP_LOGI(EXAMPLE_TAG, "Driver installed");
|
||||
ESP_ERROR_CHECK(twai_start());
|
||||
ESP_LOGI(EXAMPLE_TAG, "Driver started");
|
||||
|
||||
xSemaphoreGive(rx_sem); //Start RX task
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
xSemaphoreTake(rx_sem, portMAX_DELAY); //Wait for RX task to complete
|
||||
|
||||
//Stop and uninstall TWAI driver
|
||||
ESP_ERROR_CHECK(twai_stop());
|
||||
ESP_LOGI(EXAMPLE_TAG, "Driver stopped");
|
||||
ESP_ERROR_CHECK(twai_driver_uninstall());
|
||||
ESP_LOGI(EXAMPLE_TAG, "Driver uninstalled");
|
||||
|
||||
//Cleanup
|
||||
vSemaphoreDelete(rx_sem);
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
# The following lines of boilerplate have to be in your project's CMakeLists
|
||||
# in this exact order for cmake to work correctly
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(twai_network_master)
|
||||
@@ -0,0 +1,9 @@
|
||||
#
|
||||
# This is a project Makefile. It is assumed the directory this Makefile resides in is a
|
||||
# project subdirectory.
|
||||
#
|
||||
|
||||
PROJECT_NAME := twai_network_master
|
||||
|
||||
include $(IDF_PATH)/make/project.mk
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
idf_component_register(SRCS "twai_network_example_master_main.c"
|
||||
INCLUDE_DIRS ".")
|
||||
@@ -0,0 +1,19 @@
|
||||
menu "Example Configuration"
|
||||
|
||||
config EXAMPLE_TX_GPIO_NUM
|
||||
int "TX GPIO number"
|
||||
default 20 if IDF_TARGET_ESP32S2
|
||||
default 21 if IDF_TARGET_ESP32
|
||||
help
|
||||
This option selects the GPIO pin used for the TX signal. Connect the
|
||||
TX signal to your transceiver.
|
||||
|
||||
config EXAMPLE_RX_GPIO_NUM
|
||||
int "RX GPIO number"
|
||||
default 21 if IDF_TARGET_ESP32S2
|
||||
default 22 if IDF_TARGET_ESP32
|
||||
help
|
||||
This option selects the GPIO pin used for the RX signal. Connect the
|
||||
RX signal to your transceiver.
|
||||
|
||||
endmenu
|
||||
@@ -0,0 +1,4 @@
|
||||
#
|
||||
# Main Makefile. This is basically the same as a component makefile.
|
||||
#
|
||||
# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)
|
||||
@@ -0,0 +1,237 @@
|
||||
/* TWAI Network Master 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 master node in a TWAI network. The master
|
||||
* node is responsible for initiating and stopping the transfer of data messages.
|
||||
* The example will execute multiple iterations, with each iteration the master
|
||||
* node will do the following:
|
||||
* 1) Start the TWAI driver
|
||||
* 2) Repeatedly send ping messages until a ping response from slave is received
|
||||
* 3) Send start command to slave and receive data messages from slave
|
||||
* 4) Send stop command to slave and wait for stop response from slave
|
||||
* 5) 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"
|
||||
|
||||
/* --------------------- Definitions and static variables ------------------ */
|
||||
//Example Configuration
|
||||
#define PING_PERIOD_MS 250
|
||||
#define NO_OF_DATA_MSGS 50
|
||||
#define NO_OF_ITERS 3
|
||||
#define ITER_DELAY_MS 1000
|
||||
#define RX_TASK_PRIO 8
|
||||
#define TX_TASK_PRIO 9
|
||||
#define CTRL_TSK_PRIO 10
|
||||
#define TX_GPIO_NUM CONFIG_EXAMPLE_TX_GPIO_NUM
|
||||
#define RX_GPIO_NUM CONFIG_EXAMPLE_RX_GPIO_NUM
|
||||
#define EXAMPLE_TAG "TWAI Master"
|
||||
|
||||
#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_PINGS,
|
||||
TX_SEND_START_CMD,
|
||||
TX_SEND_STOP_CMD,
|
||||
TX_TASK_EXIT,
|
||||
} tx_task_action_t;
|
||||
|
||||
typedef enum {
|
||||
RX_RECEIVE_PING_RESP,
|
||||
RX_RECEIVE_DATA,
|
||||
RX_RECEIVE_STOP_RESP,
|
||||
RX_TASK_EXIT,
|
||||
} rx_task_action_t;
|
||||
|
||||
static const twai_timing_config_t t_config = TWAI_TIMING_CONFIG_25KBITS();
|
||||
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_message = {.identifier = ID_MASTER_PING, .data_length_code = 0,
|
||||
.ss = 1, .data = {0, 0 , 0 , 0 ,0 ,0 ,0 ,0}};
|
||||
static const twai_message_t start_message = {.identifier = ID_MASTER_START_CMD, .data_length_code = 0,
|
||||
.data = {0, 0 , 0 , 0 ,0 ,0 ,0 ,0}};
|
||||
static const twai_message_t stop_message = {.identifier = ID_MASTER_STOP_CMD, .data_length_code = 0,
|
||||
.data = {0, 0 , 0 , 0 ,0 ,0 ,0 ,0}};
|
||||
|
||||
static QueueHandle_t tx_task_queue;
|
||||
static QueueHandle_t rx_task_queue;
|
||||
static SemaphoreHandle_t stop_ping_sem;
|
||||
static SemaphoreHandle_t ctrl_task_sem;
|
||||
static SemaphoreHandle_t done_sem;
|
||||
|
||||
/* --------------------------- Tasks and Functions -------------------------- */
|
||||
|
||||
static void twai_receive_task(void *arg)
|
||||
{
|
||||
while (1) {
|
||||
rx_task_action_t action;
|
||||
xQueueReceive(rx_task_queue, &action, portMAX_DELAY);
|
||||
|
||||
if (action == RX_RECEIVE_PING_RESP) {
|
||||
//Listen for ping response from slave
|
||||
while (1) {
|
||||
twai_message_t rx_msg;
|
||||
twai_receive(&rx_msg, portMAX_DELAY);
|
||||
if (rx_msg.identifier == ID_SLAVE_PING_RESP) {
|
||||
xSemaphoreGive(stop_ping_sem);
|
||||
xSemaphoreGive(ctrl_task_sem);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (action == RX_RECEIVE_DATA) {
|
||||
//Receive data messages from slave
|
||||
uint32_t data_msgs_rec = 0;
|
||||
while (data_msgs_rec < NO_OF_DATA_MSGS) {
|
||||
twai_message_t rx_msg;
|
||||
twai_receive(&rx_msg, portMAX_DELAY);
|
||||
if (rx_msg.identifier == ID_SLAVE_DATA) {
|
||||
uint32_t data = 0;
|
||||
for (int i = 0; i < rx_msg.data_length_code; i++) {
|
||||
data |= (rx_msg.data[i] << (i * 8));
|
||||
}
|
||||
ESP_LOGI(EXAMPLE_TAG, "Received data value %d", data);
|
||||
data_msgs_rec ++;
|
||||
}
|
||||
}
|
||||
xSemaphoreGive(ctrl_task_sem);
|
||||
} else if (action == RX_RECEIVE_STOP_RESP) {
|
||||
//Listen for stop response from slave
|
||||
while (1) {
|
||||
twai_message_t rx_msg;
|
||||
twai_receive(&rx_msg, portMAX_DELAY);
|
||||
if (rx_msg.identifier == ID_SLAVE_STOP_RESP) {
|
||||
xSemaphoreGive(ctrl_task_sem);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (action == RX_TASK_EXIT) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
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_PINGS) {
|
||||
//Repeatedly transmit pings
|
||||
ESP_LOGI(EXAMPLE_TAG, "Transmitting ping");
|
||||
while (xSemaphoreTake(stop_ping_sem, 0) != pdTRUE) {
|
||||
twai_transmit(&ping_message, portMAX_DELAY);
|
||||
vTaskDelay(pdMS_TO_TICKS(PING_PERIOD_MS));
|
||||
}
|
||||
} else if (action == TX_SEND_START_CMD) {
|
||||
//Transmit start command to slave
|
||||
twai_transmit(&start_message, portMAX_DELAY);
|
||||
ESP_LOGI(EXAMPLE_TAG, "Transmitted start command");
|
||||
} else if (action == TX_SEND_STOP_CMD) {
|
||||
//Transmit stop command to slave
|
||||
twai_transmit(&stop_message, portMAX_DELAY);
|
||||
ESP_LOGI(EXAMPLE_TAG, "Transmitted stop command");
|
||||
} 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");
|
||||
|
||||
//Start transmitting pings, and listen for ping response
|
||||
tx_action = TX_SEND_PINGS;
|
||||
rx_action = RX_RECEIVE_PING_RESP;
|
||||
xQueueSend(tx_task_queue, &tx_action, portMAX_DELAY);
|
||||
xQueueSend(rx_task_queue, &rx_action, portMAX_DELAY);
|
||||
|
||||
//Send Start command to slave, and receive data messages
|
||||
xSemaphoreTake(ctrl_task_sem, portMAX_DELAY);
|
||||
tx_action = TX_SEND_START_CMD;
|
||||
rx_action = RX_RECEIVE_DATA;
|
||||
xQueueSend(tx_task_queue, &tx_action, portMAX_DELAY);
|
||||
xQueueSend(rx_task_queue, &rx_action, portMAX_DELAY);
|
||||
|
||||
//Send Stop command to slave when enough data messages have been received. Wait for stop response
|
||||
xSemaphoreTake(ctrl_task_sem, portMAX_DELAY);
|
||||
tx_action = TX_SEND_STOP_CMD;
|
||||
rx_action = RX_RECEIVE_STOP_RESP;
|
||||
xQueueSend(tx_task_queue, &tx_action, portMAX_DELAY);
|
||||
xQueueSend(rx_task_queue, &rx_action, portMAX_DELAY);
|
||||
|
||||
xSemaphoreTake(ctrl_task_sem, portMAX_DELAY);
|
||||
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 app_main(void)
|
||||
{
|
||||
//Create tasks, queues, and semaphores
|
||||
rx_task_queue = xQueueCreate(1, sizeof(rx_task_action_t));
|
||||
tx_task_queue = xQueueCreate(1, sizeof(tx_task_action_t));
|
||||
ctrl_task_sem = xSemaphoreCreateBinary();
|
||||
stop_ping_sem = xSemaphoreCreateBinary();
|
||||
done_sem = xSemaphoreCreateBinary();
|
||||
xTaskCreatePinnedToCore(twai_receive_task, "TWAI_rx", 4096, NULL, RX_TASK_PRIO, NULL, tskNO_AFFINITY);
|
||||
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
|
||||
ESP_ERROR_CHECK(twai_driver_install(&g_config, &t_config, &f_config));
|
||||
ESP_LOGI(EXAMPLE_TAG, "Driver installed");
|
||||
|
||||
xSemaphoreGive(ctrl_task_sem); //Start control task
|
||||
xSemaphoreTake(done_sem, portMAX_DELAY); //Wait for completion
|
||||
|
||||
//Uninstall TWAI driver
|
||||
ESP_ERROR_CHECK(twai_driver_uninstall());
|
||||
ESP_LOGI(EXAMPLE_TAG, "Driver uninstalled");
|
||||
|
||||
//Cleanup
|
||||
vQueueDelete(rx_task_queue);
|
||||
vQueueDelete(tx_task_queue);
|
||||
vSemaphoreDelete(ctrl_task_sem);
|
||||
vSemaphoreDelete(stop_ping_sem);
|
||||
vSemaphoreDelete(done_sem);
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
# The following lines of boilerplate have to be in your project's CMakeLists
|
||||
# in this exact order for cmake to work correctly
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(twai_network_slave)
|
||||
@@ -0,0 +1,9 @@
|
||||
#
|
||||
# This is a project Makefile. It is assumed the directory this Makefile resides in is a
|
||||
# project subdirectory.
|
||||
#
|
||||
|
||||
PROJECT_NAME := twai_network_slave
|
||||
|
||||
include $(IDF_PATH)/make/project.mk
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
idf_component_register(SRCS "twai_network_example_slave_main.c"
|
||||
INCLUDE_DIRS ".")
|
||||
@@ -0,0 +1,19 @@
|
||||
menu "Example Configuration"
|
||||
|
||||
config EXAMPLE_TX_GPIO_NUM
|
||||
int "TX GPIO number"
|
||||
default 20 if IDF_TARGET_ESP32S2
|
||||
default 21 if IDF_TARGET_ESP32
|
||||
help
|
||||
This option selects the GPIO pin used for the TX signal. Connect the
|
||||
TX signal to your transceiver.
|
||||
|
||||
config EXAMPLE_RX_GPIO_NUM
|
||||
int "RX GPIO number"
|
||||
default 21 if IDF_TARGET_ESP32S2
|
||||
default 22 if IDF_TARGET_ESP32
|
||||
help
|
||||
This option selects the GPIO pin used for the RX signal. Connect the
|
||||
RX signal to your transceiver.
|
||||
|
||||
endmenu
|
||||
@@ -0,0 +1,4 @@
|
||||
#
|
||||
# Main Makefile. This is basically the same as a component makefile.
|
||||
#
|
||||
# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)
|
||||
@@ -0,0 +1,264 @@
|
||||
/* 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"
|
||||
|
||||
/* --------------------- 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 8 //Receiving task priority
|
||||
#define TX_TASK_PRIO 9 //Sending task priority
|
||||
#define CTRL_TSK_PRIO 10 //Control task priority
|
||||
#define TX_GPIO_NUM CONFIG_EXAMPLE_TX_GPIO_NUM
|
||||
#define RX_GPIO_NUM CONFIG_EXAMPLE_RX_GPIO_NUM
|
||||
#define EXAMPLE_TAG "TWAI Slave"
|
||||
|
||||
#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_general_config_t g_config = TWAI_GENERAL_CONFIG_DEFAULT(TX_GPIO_NUM, RX_GPIO_NUM, TWAI_MODE_NORMAL);
|
||||
static const twai_timing_config_t t_config = TWAI_TIMING_CONFIG_25KBITS();
|
||||
static const twai_filter_config_t f_config = TWAI_FILTER_CONFIG_ACCEPT_ALL();
|
||||
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
|
||||
static twai_message_t data_message = {.identifier = ID_SLAVE_DATA, .data_length_code = 4,
|
||||
.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)
|
||||
{
|
||||
while (1) {
|
||||
rx_task_action_t action;
|
||||
xQueueReceive(rx_task_queue, &action, portMAX_DELAY);
|
||||
if (action == RX_RECEIVE_PING) {
|
||||
//Listen for pings from master
|
||||
twai_message_t rx_msg;
|
||||
while (1) {
|
||||
twai_receive(&rx_msg, portMAX_DELAY);
|
||||
if (rx_msg.identifier == ID_MASTER_PING) {
|
||||
xSemaphoreGive(ctrl_task_sem);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (action == RX_RECEIVE_START_CMD) {
|
||||
//Listen for start command from master
|
||||
twai_message_t rx_msg;
|
||||
while (1) {
|
||||
twai_receive(&rx_msg, portMAX_DELAY);
|
||||
if (rx_msg.identifier == ID_MASTER_START_CMD) {
|
||||
xSemaphoreGive(ctrl_task_sem);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (action == RX_RECEIVE_STOP_CMD) {
|
||||
//Listen for stop command from master
|
||||
twai_message_t rx_msg;
|
||||
while (1) {
|
||||
twai_receive(&rx_msg, portMAX_DELAY);
|
||||
if (rx_msg.identifier == ID_MASTER_STOP_CMD) {
|
||||
xSemaphoreGive(stop_data_sem);
|
||||
xSemaphoreGive(ctrl_task_sem);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (action == RX_TASK_EXIT) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
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 app_main(void)
|
||||
{
|
||||
//Add short delay to allow master it to initialize first
|
||||
for (int i = 3; i > 0; i--) {
|
||||
printf("Slave starting in %d\n", i);
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
}
|
||||
|
||||
|
||||
//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();;
|
||||
xTaskCreatePinnedToCore(twai_receive_task, "TWAI_rx", 4096, NULL, RX_TASK_PRIO, NULL, tskNO_AFFINITY);
|
||||
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));
|
||||
ESP_LOGI(EXAMPLE_TAG, "Driver installed");
|
||||
|
||||
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);
|
||||
}
|
||||
Reference in New Issue
Block a user