mirror of
https://github.com/espressif/esp-modbus.git
synced 2026-08-03 20:24:09 +02:00
Test common library with new DUT synch functionality
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
cmake_minimum_required(VERSION 3.22)
|
||||
idf_component_register(SRCS "test_common.c"
|
||||
INCLUDE_DIRS "include"
|
||||
REQUIRES unity)
|
||||
REQUIRES unity esp_timer)
|
||||
|
||||
set(EXTRA_COMPONENT_DIRS)
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2018-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2018-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -15,6 +15,11 @@
|
||||
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#define TEST_TASK_PRIO_MASTER (CONFIG_MB_TEST_MASTER_TASK_PRIO)
|
||||
#define TEST_TASK_PRIO_SLAVE (CONFIG_MB_TEST_SLAVE_TASK_PRIO)
|
||||
#define TEST_TASK_STACK_SIZE (5120)
|
||||
|
||||
|
||||
#define STR(fieldname) ((const char *)(fieldname))
|
||||
#define OPTS(min_val, max_val, step_val) \
|
||||
{ \
|
||||
@@ -23,7 +28,7 @@
|
||||
|
||||
// Enumeration of modbus slave addresses accessed by master device
|
||||
enum {
|
||||
MB_DEVICE_ADDR1 = 1,
|
||||
MB_DEVICE_ADDR1 = 01,
|
||||
MB_DEVICE_ADDR2 = 200
|
||||
};
|
||||
|
||||
@@ -44,6 +49,12 @@ enum {
|
||||
TEST_REG_VAL4 = 0x4444
|
||||
};
|
||||
|
||||
// Enumeration of task notification
|
||||
enum {
|
||||
TASK_START = 1,
|
||||
TASK_STOP = 2
|
||||
};
|
||||
|
||||
typedef struct task_entry_s {
|
||||
TaskHandle_t task_handle;
|
||||
SemaphoreHandle_t task_sema_handle;
|
||||
@@ -87,12 +98,17 @@ esp_err_t test_common_write_modbus_parameter(void *handle, uint16_t cid, uint16_
|
||||
* @brief The test helper functions to work with test tasks
|
||||
*
|
||||
*/
|
||||
void test_common_task_notify_start(TaskHandle_t task_handle, uint32_t value);
|
||||
void test_common_task_notify_start_and_stop(TaskHandle_t task_handle, uint32_t value);
|
||||
void test_common_task_start(TaskHandle_t task_handle, uint32_t value);
|
||||
int test_common_task_start_all(uint32_t value);
|
||||
uint32_t test_common_task_wait_start_and_stop(TickType_t timeout_ticks);
|
||||
int test_common_task_start_all();
|
||||
bool test_common_task_wait_done(TaskHandle_t task_handle, TickType_t timeout_ticks);
|
||||
bool test_common_task_wait_done_delete(TaskHandle_t task_handle, TickType_t task_timeout_ticks);
|
||||
int test_common_task_wait_done_delete_all(TickType_t task_timeout_tick);
|
||||
void test_common_task_delete(TaskHandle_t task_handle);
|
||||
void test_common_task_delete_all();
|
||||
int test_common_task_delete_all();
|
||||
void *test_common_task_get_instance(TaskHandle_t task_handle);
|
||||
void test_task_add_entry(TaskHandle_t task_handle, void *pinst);
|
||||
void test_common_task_notify_done(TaskHandle_t task_handle);
|
||||
void test_common_task_destroy_and_notify_done_all();
|
||||
bool test_common_wait_check_destroy_message(char *message, uint32_t timeout_ms);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2018-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2018-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "mb_common.h"
|
||||
#include "mbc_slave.h"
|
||||
#include "mbc_master.h"
|
||||
#include "esp_timer.h" // for esp_timer_get_time()
|
||||
|
||||
#include "test_common.h"
|
||||
#include "esp_heap_caps.h"
|
||||
@@ -21,9 +22,6 @@
|
||||
#include "esp_heap_trace.h"
|
||||
#endif
|
||||
|
||||
#define TEST_TASK_PRIO_MASTER (CONFIG_MB_TEST_MASTER_TASK_PRIO)
|
||||
#define TEST_TASK_PRIO_SLAVE (CONFIG_MB_TEST_SLAVE_TASK_PRIO)
|
||||
#define TEST_TASK_STACK_SIZE (5120)
|
||||
#define TEST_TASK_CYCLE_COUNTER (CONFIG_MB_TEST_COMM_CYCLE_COUNTER)
|
||||
#define TEST_BUSY_TASK_PRIO (20)
|
||||
|
||||
@@ -42,8 +40,11 @@
|
||||
#define TEST_NOTIF_SIZE (20)
|
||||
#define TEST_ALLOW_PROC_FAIL (5) // percentage of allowed failures due to desynchronization
|
||||
#define TEST_TASK_TICK_TIME (50 / portTICK_PERIOD_MS)
|
||||
#define TEST_DESTROY_MESSAGE_TOUT (500)
|
||||
#define TEST_NOTIFY_DONE_TOUT (200 / portTICK_PERIOD_MS)
|
||||
|
||||
#define TAG "TEST_COMMON"
|
||||
#define MSG_DESTROY "Destroy instances\n\0"
|
||||
|
||||
typedef enum {
|
||||
RT_HOLDING_RD,
|
||||
@@ -109,18 +110,18 @@ static bool task_wait_done_and_remove(task_entry_t *task_entry, TickType_t tout_
|
||||
if ((xSemaphoreTake(task_entry->task_sema_handle, tout_ticks) == pdTRUE)) {
|
||||
ESP_LOGI(TAG, "Test task 0x%" PRIx32 ", done successfully.", (uint32_t)task_entry->task_handle);
|
||||
is_done = true;
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Could not complete task 0x%" PRIx32 " after timeout, force kill the task.",
|
||||
(uint32_t)task_entry->task_handle);
|
||||
is_done = false;
|
||||
task_entry_remove(task_entry);
|
||||
}
|
||||
// Else statement removed from here.
|
||||
//This is a workaround on how to handle the finishing of tasks without increasing timeout of
|
||||
//test_common_task_wait_done_delete_all() and task_wait_done_and_remove()
|
||||
|
||||
vTaskDelay(1); // Let the lower priority task to suspend or delete itself
|
||||
task_entry_remove(task_entry);
|
||||
}
|
||||
return (is_done);
|
||||
}
|
||||
|
||||
static void test_task_add_entry(TaskHandle_t task_handle, void *inst)
|
||||
void test_task_add_entry(TaskHandle_t task_handle, void *inst)
|
||||
{
|
||||
TEST_ASSERT_TRUE(task_handle);
|
||||
task_entry_t *new_entry = (task_entry_t *) calloc(1, sizeof(task_entry_t));
|
||||
@@ -154,7 +155,42 @@ static task_entry_t *test_task_find_entry(TaskHandle_t task_handle)
|
||||
return pfound;
|
||||
}
|
||||
|
||||
static void test_common_task_notify_done(TaskHandle_t task_handle)
|
||||
void test_common_task_notify_stop_all()
|
||||
{
|
||||
task_entry_t *it = NULL;
|
||||
if (LIST_EMPTY(&s_task_list)) {
|
||||
return;
|
||||
}
|
||||
|
||||
LIST_FOREACH(it, &s_task_list, entries) {
|
||||
ESP_LOGD(TAG, "Notify task stop, inst: %p.", it->task_handle);
|
||||
test_common_task_notify_start_and_stop(it->task_handle, TASK_STOP);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
bool test_common_wait_check_destroy_message(char *message, uint32_t timeout_ms)
|
||||
{
|
||||
/* Read line from console, non-blocking function, timeout in ms */
|
||||
|
||||
char buffer[64] = {0}; //fixed size buffer to store the input from stdin
|
||||
|
||||
ESP_LOGD(TAG, "Waiting for destroy message: \"%s\" (timeout: %lu ms)", message, timeout_ms);
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(timeout_ms));
|
||||
if (fgets(buffer, sizeof(buffer), stdin) != NULL) {
|
||||
ESP_LOGD(TAG, "%s: received: %s", __func__, buffer);
|
||||
}
|
||||
|
||||
if (strcmp(buffer, message) == 0) {
|
||||
ESP_LOGD(TAG, "Destroy message matched, notifying to destroy instances.");
|
||||
return true;
|
||||
}
|
||||
ESP_LOGD(TAG, "Timeout waiting for destroy message.");
|
||||
return false;
|
||||
}
|
||||
|
||||
void test_common_task_notify_done(TaskHandle_t task_handle)
|
||||
{
|
||||
task_entry_t *it = test_task_find_entry(task_handle);
|
||||
if (it) {
|
||||
@@ -180,10 +216,10 @@ static void test_busy_task(void *phandle)
|
||||
void test_common_task_start(TaskHandle_t task_handle, uint32_t value)
|
||||
{
|
||||
// Directly notify the task waiting to start loop
|
||||
test_common_task_notify_start(task_handle, value);
|
||||
test_common_task_notify_start_and_stop(task_handle, value);
|
||||
}
|
||||
|
||||
int test_common_task_start_all(uint32_t value)
|
||||
int test_common_task_start_all()
|
||||
{
|
||||
task_entry_t *it = NULL;
|
||||
if (LIST_EMPTY(&s_task_list)) {
|
||||
@@ -191,7 +227,7 @@ int test_common_task_start_all(uint32_t value)
|
||||
}
|
||||
int task_count = 0;
|
||||
LIST_FOREACH(it, &s_task_list, entries) {
|
||||
test_common_task_notify_start(it->task_handle, value);
|
||||
test_common_task_notify_start_and_stop(it->task_handle, TASK_START);
|
||||
task_count++;
|
||||
}
|
||||
return task_count;
|
||||
@@ -216,13 +252,32 @@ int test_common_task_wait_done_delete_all(TickType_t task_timeout_tick)
|
||||
{
|
||||
task_entry_t *it, *ptmp = NULL;
|
||||
int task_count = 0;
|
||||
int64_t start_time = esp_timer_get_time(); //getting the reference system time to compare
|
||||
|
||||
if (LIST_EMPTY(&s_task_list)) {
|
||||
return 0;
|
||||
}
|
||||
LIST_FOREACH_SAFE(it, &s_task_list, entries, ptmp) {
|
||||
task_wait_done_and_remove(it, task_timeout_tick);
|
||||
task_count++;
|
||||
|
||||
while ((esp_timer_get_time() - start_time) <= (task_timeout_tick * portTICK_PERIOD_MS * 1000)) {
|
||||
|
||||
if (LIST_EMPTY(&s_task_list)) {
|
||||
return task_count;
|
||||
}
|
||||
|
||||
if (test_common_wait_check_destroy_message(MSG_DESTROY, TEST_DESTROY_MESSAGE_TOUT)) {
|
||||
test_common_task_notify_stop_all();
|
||||
}
|
||||
|
||||
LIST_FOREACH_SAFE(it, &s_task_list, entries, ptmp) {
|
||||
if (task_wait_done_and_remove(it, TEST_NOTIFY_DONE_TOUT)) {
|
||||
task_count++;
|
||||
}
|
||||
}
|
||||
|
||||
vTaskDelay(TEST_TASK_TICK_TIME);
|
||||
|
||||
}
|
||||
task_count = test_common_task_delete_all();
|
||||
return task_count;
|
||||
}
|
||||
|
||||
@@ -234,12 +289,15 @@ void test_common_task_delete(TaskHandle_t task_handle)
|
||||
}
|
||||
}
|
||||
|
||||
void test_common_task_delete_all()
|
||||
int test_common_task_delete_all()
|
||||
{
|
||||
task_entry_t *it = NULL;
|
||||
int task_count = 0;
|
||||
while ((it = LIST_FIRST(&s_task_list))) {
|
||||
task_entry_remove(it);
|
||||
task_count++;
|
||||
}
|
||||
return task_count;
|
||||
}
|
||||
|
||||
void *test_common_task_get_instance(TaskHandle_t task_handle)
|
||||
@@ -305,7 +363,7 @@ void test_common_stop()
|
||||
CONFIG_MB_TEST_LEAK_WARN_LEVEL, CONFIG_MB_TEST_LEAK_CRITICAL_LEVEL);
|
||||
}
|
||||
|
||||
static uint32_t test_common_task_wait_start(TickType_t timeout_ticks)
|
||||
uint32_t test_common_task_wait_start_and_stop(TickType_t timeout_ticks)
|
||||
{
|
||||
static uint32_t notify_value = 0;
|
||||
|
||||
@@ -317,9 +375,10 @@ static uint32_t test_common_task_wait_start(TickType_t timeout_ticks)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void test_common_task_notify_start(TaskHandle_t task_handle, uint32_t value)
|
||||
void test_common_task_notify_start_and_stop(TaskHandle_t task_handle, uint32_t value)
|
||||
{
|
||||
ESP_LOGD(TAG, "Notify task start 0x%" PRIx32, (uint32_t)task_handle);
|
||||
char *task_state = (value == TASK_START) ? "start" : "stop";
|
||||
ESP_LOGD(TAG, "Notify task %s 0x%" PRIx32, task_state, (uint32_t)task_handle);
|
||||
TEST_ASSERT_EQUAL_INT(xTaskNotify(task_handle, value, eSetValueWithOverwrite), pdTRUE);
|
||||
}
|
||||
|
||||
@@ -419,7 +478,7 @@ static void test_master_task(void *arg)
|
||||
uint16_t cycle_counter = 0;
|
||||
|
||||
// Wait task start notification during timeout
|
||||
test_common_task_wait_start(TEST_TASK_START_TIMEOUT);
|
||||
test_common_task_wait_start_and_stop(TEST_TASK_START_TIMEOUT);
|
||||
|
||||
holding_registers[CID_DEV_REG0] = TEST_REG_VAL1;
|
||||
holding_registers[CID_DEV_REG1] = TEST_REG_VAL2;
|
||||
@@ -485,7 +544,7 @@ static void test_slave_task(void *arg)
|
||||
mbs_controller_iface_t *pctrl_obj = ((mbs_controller_iface_t *)mbs_handle);
|
||||
mb_param_info_t reg_info; // keeps the Modbus registers access information
|
||||
|
||||
test_common_task_wait_start(TEST_TASK_START_TIMEOUT);
|
||||
test_common_task_wait_start_and_stop(TEST_TASK_START_TIMEOUT);
|
||||
|
||||
while (1) {
|
||||
// Get parameter information from parameter queue
|
||||
@@ -513,6 +572,7 @@ static void test_slave_task(void *arg)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Destroy slave, inst: %p.", mbs_handle);
|
||||
TEST_ESP_OK(mbc_slave_delete(mbs_handle));
|
||||
ESP_LOGD(TAG, "Notify task done, inst: %p.", xTaskGetCurrentTaskHandle());
|
||||
@@ -544,6 +604,7 @@ void test_common_slave_setup_start(void *mbs_handle)
|
||||
reg_area.size = coil_registers_counter;
|
||||
TEST_ESP_OK(mbc_slave_set_descriptor(mbs_handle, reg_area));
|
||||
TEST_ESP_OK(mbc_slave_start(mbs_handle));
|
||||
|
||||
}
|
||||
|
||||
#if (CONFIG_FMB_COMM_MODE_RTU_EN || CONFIG_FMB_COMM_MODE_ASCII_EN)
|
||||
|
||||
Reference in New Issue
Block a user