ci: disable UTs for esp32s2beta without runners
This commit is contained in:
parent
c22965b22c
commit
eb158e9a22
12 changed files with 1572 additions and 1393 deletions
356
components/driver/test/esp32/test_i2c.c
Normal file
356
components/driver/test/esp32/test_i2c.c
Normal file
|
@ -0,0 +1,356 @@
|
||||||
|
/**
|
||||||
|
* test environment UT_T2_I2C:
|
||||||
|
* please prepare two ESP32-WROVER-KIT board.
|
||||||
|
* Then connect GPIO18 and GPIO18, GPIO19 and GPIO19 between these two boards.
|
||||||
|
*/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "unity.h"
|
||||||
|
#include "test_utils.h"
|
||||||
|
#include "unity_config.h"
|
||||||
|
#include "driver/i2c.h"
|
||||||
|
#include "esp_attr.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "soc/gpio_periph.h"
|
||||||
|
#include "soc/i2c_periph.h"
|
||||||
|
#include "esp_system.h"
|
||||||
|
#include "driver/pcnt.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define DATA_LENGTH 512 /*!<Data buffer length for test buffer*/
|
||||||
|
#define RW_TEST_LENGTH 129 /*!<Data length for r/w test, any value from 0-DATA_LENGTH*/
|
||||||
|
#define DELAY_TIME_BETWEEN_ITEMS_MS 1234 /*!< delay time between different test items */
|
||||||
|
|
||||||
|
#define I2C_SLAVE_SCL_IO 19 /*!<gpio number for i2c slave clock */
|
||||||
|
#define I2C_SLAVE_SDA_IO 18 /*!<gpio number for i2c slave data */
|
||||||
|
#define I2C_SLAVE_NUM I2C_NUM_0 /*!<I2C port number for slave dev */
|
||||||
|
#define I2C_SLAVE_TX_BUF_LEN (2*DATA_LENGTH) /*!<I2C slave tx buffer size */
|
||||||
|
#define I2C_SLAVE_RX_BUF_LEN (2*DATA_LENGTH) /*!<I2C slave rx buffer size */
|
||||||
|
|
||||||
|
#define I2C_MASTER_SCL_IO 19 /*!< gpio number for I2C master clock */
|
||||||
|
#define I2C_MASTER_SDA_IO 18 /*!< gpio number for I2C master data */
|
||||||
|
#define I2C_MASTER_NUM I2C_NUM_1 /*!< I2C port number for master dev */
|
||||||
|
#define I2C_MASTER_TX_BUF_DISABLE 0 /*!< I2C master do not need buffer */
|
||||||
|
#define I2C_MASTER_RX_BUF_DISABLE 0 /*!< I2C master do not need buffer */
|
||||||
|
#define I2C_MASTER_FREQ_HZ 100000 /*!< I2C master clock frequency */
|
||||||
|
|
||||||
|
#define ESP_SLAVE_ADDR 0x28 /*!< ESP32 slave address, you can set any 7bit value */
|
||||||
|
#define WRITE_BIT I2C_MASTER_WRITE /*!< I2C master write */
|
||||||
|
#define READ_BIT I2C_MASTER_READ /*!< I2C master read */
|
||||||
|
#define ACK_CHECK_EN 0x1 /*!< I2C master will check ack from slave*/
|
||||||
|
#define ACK_CHECK_DIS 0x0 /*!< I2C master will not check ack from slave */
|
||||||
|
#define ACK_VAL 0x0 /*!< I2C ack value */
|
||||||
|
#define NACK_VAL 0x1 /*!< I2C nack value */
|
||||||
|
|
||||||
|
#define PULSE_IO 19
|
||||||
|
#define PCNT_INPUT_IO 4
|
||||||
|
#define PCNT_CTRL_FLOATING_IO 5
|
||||||
|
#define HIGHEST_LIMIT 10000
|
||||||
|
#define LOWEST_LIMIT -10000
|
||||||
|
|
||||||
|
|
||||||
|
static esp_err_t i2c_master_write_slave(i2c_port_t i2c_num, uint8_t *data_wr, size_t size)
|
||||||
|
{
|
||||||
|
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
||||||
|
i2c_master_start(cmd);
|
||||||
|
TEST_ESP_OK(i2c_master_write_byte(cmd, ( ESP_SLAVE_ADDR << 1 ) | WRITE_BIT, ACK_CHECK_EN));
|
||||||
|
TEST_ESP_OK(i2c_master_write(cmd, data_wr, size, ACK_CHECK_EN));
|
||||||
|
TEST_ESP_OK(i2c_master_stop(cmd));
|
||||||
|
esp_err_t ret = i2c_master_cmd_begin(i2c_num, cmd, 5000 / portTICK_RATE_MS);
|
||||||
|
i2c_cmd_link_delete(cmd);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static i2c_config_t i2c_master_init(void)
|
||||||
|
{
|
||||||
|
i2c_config_t conf_master = {
|
||||||
|
.mode = I2C_MODE_MASTER,
|
||||||
|
.sda_pullup_en = GPIO_PULLUP_ENABLE,
|
||||||
|
.scl_pullup_en = GPIO_PULLUP_ENABLE,
|
||||||
|
.master.clk_speed = I2C_MASTER_FREQ_HZ,
|
||||||
|
.sda_io_num = I2C_MASTER_SDA_IO,
|
||||||
|
.scl_io_num = I2C_MASTER_SCL_IO,
|
||||||
|
};
|
||||||
|
return conf_master;
|
||||||
|
}
|
||||||
|
|
||||||
|
// print the reading buffer
|
||||||
|
static void disp_buf(uint8_t *buf, int len)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
printf("%02x ", buf[i]);
|
||||||
|
if (( i + 1 ) % 16 == 0) {
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static i2c_config_t i2c_slave_init(void)
|
||||||
|
{
|
||||||
|
i2c_config_t conf_slave = {
|
||||||
|
.mode = I2C_MODE_SLAVE,
|
||||||
|
.sda_io_num = I2C_SLAVE_SDA_IO,
|
||||||
|
.scl_io_num = I2C_SLAVE_SCL_IO,
|
||||||
|
.sda_pullup_en = GPIO_PULLUP_ENABLE,
|
||||||
|
.scl_pullup_en = GPIO_PULLUP_ENABLE,
|
||||||
|
.slave.addr_10bit_en = 0,
|
||||||
|
.slave.slave_addr = ESP_SLAVE_ADDR,
|
||||||
|
};
|
||||||
|
return conf_slave;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void i2c_master_write_test(void)
|
||||||
|
{
|
||||||
|
uint8_t *data_wr = (uint8_t *) malloc(DATA_LENGTH);
|
||||||
|
int i;
|
||||||
|
|
||||||
|
i2c_config_t conf_master = i2c_master_init();
|
||||||
|
TEST_ESP_OK(i2c_param_config(I2C_MASTER_NUM, &conf_master));
|
||||||
|
|
||||||
|
TEST_ESP_OK(i2c_driver_install(I2C_MASTER_NUM, I2C_MODE_MASTER,
|
||||||
|
I2C_MASTER_RX_BUF_DISABLE,
|
||||||
|
I2C_MASTER_TX_BUF_DISABLE, 0));
|
||||||
|
unity_wait_for_signal("i2c slave init finish");
|
||||||
|
|
||||||
|
unity_send_signal("master write");
|
||||||
|
for (i = 0; i < DATA_LENGTH / 2; i++) {
|
||||||
|
data_wr[i] = i;
|
||||||
|
}
|
||||||
|
i2c_master_write_slave(I2C_MASTER_NUM, data_wr, DATA_LENGTH / 2);
|
||||||
|
disp_buf(data_wr, i + 1);
|
||||||
|
free(data_wr);
|
||||||
|
unity_wait_for_signal("ready to delete");
|
||||||
|
TEST_ESP_OK(i2c_driver_delete(I2C_MASTER_NUM));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void i2c_slave_read_test(void)
|
||||||
|
{
|
||||||
|
uint8_t *data_rd = (uint8_t *) malloc(DATA_LENGTH);
|
||||||
|
int size_rd = 0;
|
||||||
|
int len = 0;
|
||||||
|
|
||||||
|
i2c_config_t conf_slave = i2c_slave_init();
|
||||||
|
TEST_ESP_OK(i2c_param_config( I2C_SLAVE_NUM, &conf_slave));
|
||||||
|
TEST_ESP_OK(i2c_driver_install(I2C_SLAVE_NUM, I2C_MODE_SLAVE,
|
||||||
|
I2C_SLAVE_RX_BUF_LEN,
|
||||||
|
I2C_SLAVE_TX_BUF_LEN, 0));
|
||||||
|
unity_send_signal("i2c slave init finish");
|
||||||
|
|
||||||
|
unity_wait_for_signal("master write");
|
||||||
|
while (1) {
|
||||||
|
len = i2c_slave_read_buffer( I2C_SLAVE_NUM, data_rd + size_rd, DATA_LENGTH, 10000 / portTICK_RATE_MS);
|
||||||
|
if (len == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
size_rd += len;
|
||||||
|
}
|
||||||
|
disp_buf(data_rd, size_rd);
|
||||||
|
for (int i = 0; i < size_rd; i++) {
|
||||||
|
TEST_ASSERT(data_rd[i] == i);
|
||||||
|
}
|
||||||
|
free(data_rd);
|
||||||
|
unity_send_signal("ready to delete");
|
||||||
|
TEST_ESP_OK(i2c_driver_delete(I2C_SLAVE_NUM));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE_MULTIPLE_DEVICES("I2C master write slave test", "[i2c][test_env=UT_T2_I2C][timeout=150]", i2c_master_write_test, i2c_slave_read_test);
|
||||||
|
|
||||||
|
static void master_read_slave_test(void)
|
||||||
|
{
|
||||||
|
uint8_t *data_rd = (uint8_t *) malloc(DATA_LENGTH);
|
||||||
|
memset(data_rd, 0, DATA_LENGTH);
|
||||||
|
i2c_config_t conf_master = i2c_master_init();
|
||||||
|
TEST_ESP_OK(i2c_param_config(I2C_MASTER_NUM, &conf_master));
|
||||||
|
TEST_ESP_OK(i2c_driver_install(I2C_MASTER_NUM, I2C_MODE_MASTER,
|
||||||
|
I2C_MASTER_RX_BUF_DISABLE,
|
||||||
|
I2C_MASTER_TX_BUF_DISABLE, 0));
|
||||||
|
unity_wait_for_signal("i2c slave init finish");
|
||||||
|
|
||||||
|
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
||||||
|
i2c_master_start(cmd);
|
||||||
|
i2c_master_write_byte(cmd, ( ESP_SLAVE_ADDR << 1 ) | READ_BIT, ACK_CHECK_EN);
|
||||||
|
|
||||||
|
unity_send_signal("slave write");
|
||||||
|
unity_wait_for_signal("master read");
|
||||||
|
i2c_master_read(cmd, data_rd, RW_TEST_LENGTH-1, ACK_VAL);
|
||||||
|
i2c_master_read_byte(cmd, data_rd + RW_TEST_LENGTH-1, NACK_VAL);
|
||||||
|
i2c_master_stop(cmd);
|
||||||
|
i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 5000 / portTICK_RATE_MS);
|
||||||
|
i2c_cmd_link_delete(cmd);
|
||||||
|
vTaskDelay(100 / portTICK_RATE_MS);
|
||||||
|
for (int i = 0; i < RW_TEST_LENGTH; i++) {
|
||||||
|
printf("%d\n", data_rd[i]);
|
||||||
|
TEST_ASSERT(data_rd[i]==i);
|
||||||
|
}
|
||||||
|
free(data_rd);
|
||||||
|
unity_send_signal("ready to delete");
|
||||||
|
i2c_driver_delete(I2C_MASTER_NUM);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void slave_write_buffer_test(void)
|
||||||
|
{
|
||||||
|
uint8_t *data_wr = (uint8_t *) malloc(DATA_LENGTH);
|
||||||
|
int size_rd;
|
||||||
|
|
||||||
|
i2c_config_t conf_slave = i2c_slave_init();
|
||||||
|
TEST_ESP_OK(i2c_param_config( I2C_SLAVE_NUM, &conf_slave));
|
||||||
|
TEST_ESP_OK(i2c_driver_install(I2C_SLAVE_NUM, I2C_MODE_SLAVE,
|
||||||
|
I2C_SLAVE_RX_BUF_LEN,
|
||||||
|
I2C_SLAVE_TX_BUF_LEN, 0));
|
||||||
|
unity_send_signal("i2c slave init finish");
|
||||||
|
|
||||||
|
unity_wait_for_signal("slave write");
|
||||||
|
for (int i = 0; i < DATA_LENGTH / 2; i++) {
|
||||||
|
data_wr[i] = i;
|
||||||
|
}
|
||||||
|
size_rd = i2c_slave_write_buffer(I2C_SLAVE_NUM, data_wr, RW_TEST_LENGTH, 2000 / portTICK_RATE_MS);
|
||||||
|
disp_buf(data_wr, size_rd);
|
||||||
|
unity_send_signal("master read");
|
||||||
|
unity_wait_for_signal("ready to delete");
|
||||||
|
free(data_wr);
|
||||||
|
i2c_driver_delete(I2C_SLAVE_NUM);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST_CASE_MULTIPLE_DEVICES("I2C master read slave test", "[i2c][test_env=UT_T2_I2C][timeout=150]", master_read_slave_test, slave_write_buffer_test);
|
||||||
|
|
||||||
|
static void i2c_master_write_read_test(void)
|
||||||
|
{
|
||||||
|
uint8_t *data_rd = (uint8_t *) malloc(DATA_LENGTH);
|
||||||
|
memset(data_rd, 0, DATA_LENGTH);
|
||||||
|
uint8_t *data_wr = (uint8_t *) malloc(DATA_LENGTH);
|
||||||
|
|
||||||
|
i2c_config_t conf_master = i2c_master_init();
|
||||||
|
TEST_ESP_OK(i2c_param_config(I2C_MASTER_NUM, &conf_master));
|
||||||
|
TEST_ESP_OK(i2c_driver_install(I2C_MASTER_NUM, I2C_MODE_MASTER,
|
||||||
|
I2C_MASTER_RX_BUF_DISABLE,
|
||||||
|
I2C_MASTER_TX_BUF_DISABLE, 0));
|
||||||
|
unity_wait_for_signal("i2c slave init finish");
|
||||||
|
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
||||||
|
i2c_master_start(cmd);
|
||||||
|
i2c_master_write_byte(cmd, ( ESP_SLAVE_ADDR << 1 ) | READ_BIT, ACK_CHECK_EN);
|
||||||
|
|
||||||
|
unity_send_signal("slave write");
|
||||||
|
unity_wait_for_signal("master read and write");
|
||||||
|
i2c_master_read(cmd, data_rd, RW_TEST_LENGTH, ACK_VAL);
|
||||||
|
i2c_master_read_byte(cmd, data_rd + RW_TEST_LENGTH, NACK_VAL);
|
||||||
|
i2c_master_stop(cmd);
|
||||||
|
i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 5000 / portTICK_RATE_MS);
|
||||||
|
i2c_cmd_link_delete(cmd);
|
||||||
|
vTaskDelay(100 / portTICK_RATE_MS);
|
||||||
|
disp_buf(data_rd, RW_TEST_LENGTH);
|
||||||
|
for (int i = 0; i < RW_TEST_LENGTH; i++) {
|
||||||
|
TEST_ASSERT(data_rd[i] == i/2);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < DATA_LENGTH; i++) {
|
||||||
|
data_wr[i] = i % 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
vTaskDelay(100 / portTICK_RATE_MS);
|
||||||
|
i2c_master_write_slave(I2C_MASTER_NUM, data_wr, RW_TEST_LENGTH);
|
||||||
|
free(data_wr);
|
||||||
|
free(data_rd);
|
||||||
|
unity_send_signal("slave read");
|
||||||
|
unity_wait_for_signal("ready to delete");
|
||||||
|
i2c_driver_delete(I2C_MASTER_NUM);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void i2c_slave_read_write_test(void)
|
||||||
|
{
|
||||||
|
uint8_t *data_rd = (uint8_t *) malloc(DATA_LENGTH);
|
||||||
|
memset(data_rd, 0, DATA_LENGTH);
|
||||||
|
uint8_t *data_wr = (uint8_t *) malloc(DATA_LENGTH);
|
||||||
|
int size_rd;
|
||||||
|
|
||||||
|
i2c_config_t conf_slave = i2c_slave_init();
|
||||||
|
TEST_ESP_OK(i2c_param_config( I2C_SLAVE_NUM, &conf_slave));
|
||||||
|
TEST_ESP_OK(i2c_driver_install(I2C_SLAVE_NUM, I2C_MODE_SLAVE,
|
||||||
|
I2C_SLAVE_RX_BUF_LEN,
|
||||||
|
I2C_SLAVE_TX_BUF_LEN, 0));
|
||||||
|
unity_send_signal("i2c slave init finish");
|
||||||
|
unity_wait_for_signal("slave write");
|
||||||
|
|
||||||
|
for (int i = 0; i < DATA_LENGTH / 2; i++) {
|
||||||
|
data_wr[i] = i/2;
|
||||||
|
}
|
||||||
|
size_rd = i2c_slave_write_buffer(I2C_SLAVE_NUM, data_wr, RW_TEST_LENGTH, 2000 / portTICK_RATE_MS);
|
||||||
|
disp_buf(data_wr, size_rd);
|
||||||
|
unity_send_signal("master read and write");
|
||||||
|
unity_wait_for_signal("slave read");
|
||||||
|
size_rd = i2c_slave_read_buffer( I2C_SLAVE_NUM, data_rd, RW_TEST_LENGTH, 1000 / portTICK_RATE_MS);
|
||||||
|
printf("slave read data is:\n");
|
||||||
|
disp_buf(data_rd, size_rd);
|
||||||
|
for (int i = 0; i < RW_TEST_LENGTH; i++) {
|
||||||
|
TEST_ASSERT(data_rd[i] == i % 3);
|
||||||
|
}
|
||||||
|
free(data_wr);
|
||||||
|
free(data_rd);
|
||||||
|
unity_send_signal("ready to delete");
|
||||||
|
i2c_driver_delete(I2C_SLAVE_NUM);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE_MULTIPLE_DEVICES("I2C read and write test", "[i2c][test_env=UT_T2_I2C][timeout=150]", i2c_master_write_read_test, i2c_slave_read_write_test);
|
||||||
|
|
||||||
|
static void i2c_master_repeat_write(void)
|
||||||
|
{
|
||||||
|
uint8_t *data_wr = (uint8_t *) malloc(DATA_LENGTH);
|
||||||
|
int times = 3;
|
||||||
|
|
||||||
|
i2c_config_t conf_master = i2c_master_init();
|
||||||
|
TEST_ESP_OK(i2c_param_config(I2C_MASTER_NUM, &conf_master));
|
||||||
|
|
||||||
|
TEST_ESP_OK(i2c_driver_install(I2C_MASTER_NUM, I2C_MODE_MASTER,
|
||||||
|
I2C_MASTER_RX_BUF_DISABLE,
|
||||||
|
I2C_MASTER_TX_BUF_DISABLE, 0));
|
||||||
|
unity_wait_for_signal("i2c slave init finish");
|
||||||
|
|
||||||
|
for (int j = 0; j < times; j++) {
|
||||||
|
for (int i = 0; i < DATA_LENGTH; i++) {
|
||||||
|
data_wr[i] = j + i;
|
||||||
|
}
|
||||||
|
i2c_master_write_slave(I2C_MASTER_NUM, data_wr, RW_TEST_LENGTH);
|
||||||
|
disp_buf(data_wr, RW_TEST_LENGTH);
|
||||||
|
}
|
||||||
|
free(data_wr);
|
||||||
|
unity_send_signal("master write");
|
||||||
|
unity_wait_for_signal("ready to delete");
|
||||||
|
i2c_driver_delete(I2C_MASTER_NUM);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void i2c_slave_repeat_read(void)
|
||||||
|
{
|
||||||
|
int size_rd = 0;
|
||||||
|
int times = 3;
|
||||||
|
uint8_t *data_rd = (uint8_t *) malloc(DATA_LENGTH * 3);
|
||||||
|
|
||||||
|
i2c_config_t conf_slave = i2c_slave_init();
|
||||||
|
TEST_ESP_OK(i2c_param_config( I2C_SLAVE_NUM, &conf_slave));
|
||||||
|
TEST_ESP_OK(i2c_driver_install(I2C_SLAVE_NUM, I2C_MODE_SLAVE,
|
||||||
|
I2C_SLAVE_RX_BUF_LEN,
|
||||||
|
I2C_SLAVE_TX_BUF_LEN, 0));
|
||||||
|
unity_send_signal("i2c slave init finish");
|
||||||
|
unity_wait_for_signal("master write");
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
int len = i2c_slave_read_buffer( I2C_SLAVE_NUM, data_rd + size_rd, RW_TEST_LENGTH * 3, 10000 / portTICK_RATE_MS);
|
||||||
|
if (len == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
size_rd += len;
|
||||||
|
}
|
||||||
|
disp_buf(data_rd, size_rd);
|
||||||
|
for (int j = 0; j < times; j++) {
|
||||||
|
for (int i = 0; i < RW_TEST_LENGTH; i++) {
|
||||||
|
printf("data: %d, %d\n", data_rd[j * RW_TEST_LENGTH + i], (i % 129 + j));
|
||||||
|
TEST_ASSERT(data_rd[j * RW_TEST_LENGTH + i] == (i % 129 + j));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(data_rd);
|
||||||
|
unity_send_signal("ready to delete");
|
||||||
|
i2c_driver_delete(I2C_SLAVE_NUM);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE_MULTIPLE_DEVICES("I2C repeat write test", "[i2c][test_env=UT_T2_I2C][timeout=150]", i2c_master_repeat_write, i2c_slave_repeat_read);
|
281
components/driver/test/esp32/test_rs485.c
Normal file
281
components/driver/test/esp32/test_rs485.c
Normal file
|
@ -0,0 +1,281 @@
|
||||||
|
/* This file is from test_uart.c, but mainly about RS485 */
|
||||||
|
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include "unity.h"
|
||||||
|
#include "test_utils.h" // unity_send_signal
|
||||||
|
#include "driver/uart.h" // for the uart driver access
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "esp_system.h" // for uint32_t esp_random()
|
||||||
|
|
||||||
|
#define UART_TAG "Uart"
|
||||||
|
#define UART_NUM1 (UART_NUM_1)
|
||||||
|
#define BUF_SIZE (100)
|
||||||
|
#define UART1_RX_PIN (22)
|
||||||
|
#define UART1_TX_PIN (23)
|
||||||
|
#define UART_BAUD_11520 (11520)
|
||||||
|
#define UART_BAUD_115200 (115200)
|
||||||
|
#define TOLERANCE (0.02) //baud rate error tolerance 2%.
|
||||||
|
|
||||||
|
#define UART_TOLERANCE_CHECK(val, uper_limit, lower_limit) ( (val) <= (uper_limit) && (val) >= (lower_limit) )
|
||||||
|
|
||||||
|
// RTS for RS485 Half-Duplex Mode manages DE/~RE
|
||||||
|
#define UART1_RTS_PIN (18)
|
||||||
|
|
||||||
|
// Number of packets to be send during test
|
||||||
|
#define PACKETS_NUMBER (10)
|
||||||
|
|
||||||
|
// Wait timeout for uart driver
|
||||||
|
#define PACKET_READ_TICS (1000 / portTICK_RATE_MS)
|
||||||
|
|
||||||
|
// The table for fast CRC16 calculation
|
||||||
|
static const uint8_t crc_hi[] = {
|
||||||
|
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
|
||||||
|
0x00, 0xC1, 0x81,
|
||||||
|
0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81,
|
||||||
|
0x40, 0x01, 0xC0,
|
||||||
|
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1,
|
||||||
|
0x81, 0x40, 0x01,
|
||||||
|
0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01,
|
||||||
|
0xC0, 0x80, 0x41,
|
||||||
|
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
|
||||||
|
0x00, 0xC1, 0x81,
|
||||||
|
0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80,
|
||||||
|
0x41, 0x01, 0xC0,
|
||||||
|
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
|
||||||
|
0x80, 0x41, 0x01,
|
||||||
|
0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00,
|
||||||
|
0xC1, 0x81, 0x40,
|
||||||
|
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
|
||||||
|
0x00, 0xC1, 0x81,
|
||||||
|
0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
|
||||||
|
0x40, 0x01, 0xC0,
|
||||||
|
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1,
|
||||||
|
0x81, 0x40, 0x01,
|
||||||
|
0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01,
|
||||||
|
0xC0, 0x80, 0x41,
|
||||||
|
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
|
||||||
|
0x00, 0xC1, 0x81,
|
||||||
|
0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
|
||||||
|
0x40, 0x01, 0xC0,
|
||||||
|
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
|
||||||
|
0x80, 0x41, 0x01,
|
||||||
|
0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01,
|
||||||
|
0xC0, 0x80, 0x41,
|
||||||
|
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
|
||||||
|
0x00, 0xC1, 0x81,
|
||||||
|
0x40
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint8_t crc_low[] = {
|
||||||
|
0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7,
|
||||||
|
0x05, 0xC5, 0xC4,
|
||||||
|
0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB,
|
||||||
|
0x0B, 0xC9, 0x09,
|
||||||
|
0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE,
|
||||||
|
0xDF, 0x1F, 0xDD,
|
||||||
|
0x1D, 0x1C, 0xDC, 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2,
|
||||||
|
0x12, 0x13, 0xD3,
|
||||||
|
0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32,
|
||||||
|
0x36, 0xF6, 0xF7,
|
||||||
|
0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E,
|
||||||
|
0xFE, 0xFA, 0x3A,
|
||||||
|
0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B,
|
||||||
|
0x2A, 0xEA, 0xEE,
|
||||||
|
0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27,
|
||||||
|
0xE7, 0xE6, 0x26,
|
||||||
|
0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1,
|
||||||
|
0x63, 0xA3, 0xA2,
|
||||||
|
0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD,
|
||||||
|
0x6D, 0xAF, 0x6F,
|
||||||
|
0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8,
|
||||||
|
0xB9, 0x79, 0xBB,
|
||||||
|
0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4,
|
||||||
|
0x74, 0x75, 0xB5,
|
||||||
|
0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0,
|
||||||
|
0x50, 0x90, 0x91,
|
||||||
|
0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94,
|
||||||
|
0x54, 0x9C, 0x5C,
|
||||||
|
0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59,
|
||||||
|
0x58, 0x98, 0x88,
|
||||||
|
0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D,
|
||||||
|
0x4D, 0x4C, 0x8C,
|
||||||
|
0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83,
|
||||||
|
0x41, 0x81, 0x80,
|
||||||
|
0x40
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Calculate buffer checksum using tables
|
||||||
|
// The checksum CRC16 algorithm is specific
|
||||||
|
// for Modbus standard and uses polynomial value = 0xA001
|
||||||
|
static uint16_t get_buffer_crc16( uint8_t * frame_ptr, uint16_t length )
|
||||||
|
{
|
||||||
|
TEST_ASSERT( frame_ptr != NULL);
|
||||||
|
|
||||||
|
uint8_t crc_hi_byte = 0xFF;
|
||||||
|
uint8_t crc_low_byte = 0xFF;
|
||||||
|
int index;
|
||||||
|
|
||||||
|
while ( length-- )
|
||||||
|
{
|
||||||
|
index = crc_low_byte ^ *(frame_ptr++);
|
||||||
|
crc_low_byte = crc_hi_byte ^ crc_hi[index];
|
||||||
|
crc_hi_byte = crc_low[index];
|
||||||
|
}
|
||||||
|
return ((crc_hi_byte << 8) | crc_low_byte);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fill the buffer with random numbers and apply CRC16 at the end
|
||||||
|
static uint16_t buffer_fill_random(uint8_t *buffer, size_t length)
|
||||||
|
{
|
||||||
|
TEST_ASSERT( buffer != NULL);
|
||||||
|
// Packet is too short
|
||||||
|
if (length < 4) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < length; i += 4) {
|
||||||
|
uint32_t random = esp_random();
|
||||||
|
memcpy(buffer + i, &random, MIN(length - i, 4));
|
||||||
|
}
|
||||||
|
// Get checksum of the buffer
|
||||||
|
uint16_t crc = get_buffer_crc16((uint8_t*)buffer, (length - 2));
|
||||||
|
// Apply checksum bytes into packet
|
||||||
|
buffer[length - 2] = (uint8_t)(crc & 0xFF); // Set Low byte CRC
|
||||||
|
buffer[length - 1] = (uint8_t)(crc >> 8); // Set High byte CRC
|
||||||
|
return crc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rs485_init(void)
|
||||||
|
{
|
||||||
|
uart_config_t uart_config = {
|
||||||
|
.baud_rate = UART_BAUD_115200,
|
||||||
|
.data_bits = UART_DATA_8_BITS,
|
||||||
|
.parity = UART_PARITY_DISABLE,
|
||||||
|
.stop_bits = UART_STOP_BITS_1,
|
||||||
|
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
|
||||||
|
.rx_flow_ctrl_thresh = 122,
|
||||||
|
};
|
||||||
|
printf("RS485 port initialization...\r\n");
|
||||||
|
// Configure UART1 parameters
|
||||||
|
uart_param_config(UART_NUM1, &uart_config);
|
||||||
|
// Set UART1 pins(TX: IO4, RX: I05, RTS: IO18, CTS: IO19)
|
||||||
|
uart_set_pin(UART_NUM1, UART1_TX_PIN, UART1_RX_PIN, UART1_RTS_PIN, UART_PIN_NO_CHANGE);
|
||||||
|
// Install UART driver (we don't need an event queue here)
|
||||||
|
uart_driver_install(UART_NUM1, BUF_SIZE * 2, 0, 0, NULL, 0);
|
||||||
|
// Setup rs485 half duplex mode
|
||||||
|
//uart_set_rs485_hd_mode(uart_num, true);
|
||||||
|
uart_set_mode(UART_NUM1, UART_MODE_RS485_HALF_DUPLEX);
|
||||||
|
}
|
||||||
|
|
||||||
|
static esp_err_t print_packet_data(const char *str, uint8_t *buffer, uint16_t buffer_size)
|
||||||
|
{
|
||||||
|
TEST_ASSERT( buffer != NULL);
|
||||||
|
TEST_ASSERT( str != NULL);
|
||||||
|
|
||||||
|
// Calculate the checksum of the buffer
|
||||||
|
uint16_t crc16_calc = get_buffer_crc16(buffer, (buffer_size - 2));
|
||||||
|
uint16_t crc16_in = ((uint16_t)(buffer[buffer_size - 1]) << 8) | buffer[buffer_size - 2];
|
||||||
|
const char* state_str = (crc16_in != crc16_calc) ? "incorrect " : "correct ";
|
||||||
|
// Print an array of data
|
||||||
|
printf("%s%s RS485 packet = [ ", str, state_str);
|
||||||
|
for (int i = 0; i < buffer_size; i++) {
|
||||||
|
printf("0x%.2X ", (uint8_t)buffer[i]);
|
||||||
|
}
|
||||||
|
printf(" ]\r\n");
|
||||||
|
printf("crc_in = 0x%.4X\r\n", (uint16_t)crc16_in);
|
||||||
|
printf("crc_calc = 0x%.4X\r\n", (uint16_t)crc16_calc);
|
||||||
|
esp_err_t result = (crc16_in != crc16_calc) ? ESP_ERR_INVALID_CRC : ESP_OK;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Slave test case for multi device
|
||||||
|
static void rs485_slave(void)
|
||||||
|
{
|
||||||
|
rs485_init();
|
||||||
|
uint8_t* slave_data = (uint8_t*) malloc(BUF_SIZE);
|
||||||
|
uint16_t err_count = 0, good_count = 0;
|
||||||
|
printf("Start recieve loop.\r\n");
|
||||||
|
unity_send_signal("Slave_ready");
|
||||||
|
unity_wait_for_signal("Master_started");
|
||||||
|
for(int pack_count = 0; pack_count < PACKETS_NUMBER; pack_count++) {
|
||||||
|
//Read slave_data from UART
|
||||||
|
int len = uart_read_bytes(UART_NUM1, slave_data, BUF_SIZE, (PACKET_READ_TICS * 2));
|
||||||
|
//Write slave_data back to UART
|
||||||
|
if (len > 2) {
|
||||||
|
esp_err_t status = print_packet_data("Received ", slave_data, len);
|
||||||
|
|
||||||
|
// If received packet is correct then send it back
|
||||||
|
if (status == ESP_OK) {
|
||||||
|
uart_write_bytes(UART_NUM1, (char*)slave_data, len);
|
||||||
|
good_count++;
|
||||||
|
} else {
|
||||||
|
printf("Incorrect packet received.\r\n");
|
||||||
|
err_count++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
printf("Incorrect data packet[%d] received.\r\n", pack_count);
|
||||||
|
err_count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("Test completed. Received packets = %d, errors = %d\r\n", good_count, err_count);
|
||||||
|
// Wait for packet to be sent
|
||||||
|
uart_wait_tx_done(UART_NUM1, PACKET_READ_TICS);
|
||||||
|
free(slave_data);
|
||||||
|
uart_driver_delete(UART_NUM1);
|
||||||
|
TEST_ASSERT(err_count < 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Master test of multi device test case.
|
||||||
|
// It forms packet with random data, apply generated CRC16 and sends to slave.
|
||||||
|
// If response recieved correctly from slave means RS485 channel works.
|
||||||
|
static void rs485_master(void)
|
||||||
|
{
|
||||||
|
uint16_t err_count = 0, good_count = 0;
|
||||||
|
rs485_init();
|
||||||
|
uint8_t* master_buffer = (uint8_t*) malloc(BUF_SIZE);
|
||||||
|
uint8_t* slave_buffer = (uint8_t*) malloc(BUF_SIZE);
|
||||||
|
// The master test case should be synchronized with slave
|
||||||
|
unity_wait_for_signal("Slave_ready");
|
||||||
|
unity_send_signal("Master_started");
|
||||||
|
printf("Start recieve loop.\r\n");
|
||||||
|
for(int i = 0; i < PACKETS_NUMBER; i++) {
|
||||||
|
// Form random buffer with CRC16
|
||||||
|
buffer_fill_random(master_buffer, BUF_SIZE);
|
||||||
|
// Print created packet for debugging
|
||||||
|
esp_err_t status = print_packet_data("Send ", master_buffer, BUF_SIZE);
|
||||||
|
TEST_ASSERT(status == ESP_OK);
|
||||||
|
uart_write_bytes(UART_NUM1, (char*)master_buffer, BUF_SIZE);
|
||||||
|
// Read translated packet from slave
|
||||||
|
int len = uart_read_bytes(UART_NUM1, slave_buffer, BUF_SIZE, (PACKET_READ_TICS * 2));
|
||||||
|
// Check if the received packet is too short
|
||||||
|
if (len > 2) {
|
||||||
|
// Print received packet and check checksum
|
||||||
|
esp_err_t status = print_packet_data("Received ", slave_buffer, len);
|
||||||
|
if (status == ESP_OK) {
|
||||||
|
good_count++;
|
||||||
|
printf("Received: %d\r\n", good_count);
|
||||||
|
} else {
|
||||||
|
err_count++;
|
||||||
|
printf("Errors: %d\r\n", err_count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
printf("Incorrect answer from slave.\r\n");
|
||||||
|
err_count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Free the buffer and delete driver at the end
|
||||||
|
free(master_buffer);
|
||||||
|
uart_driver_delete(UART_NUM1);
|
||||||
|
TEST_ASSERT(err_count <= 1);
|
||||||
|
printf("Test completed. Received packets = %d, errors = %d\r\n", (uint16_t)good_count, (uint16_t)err_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This multi devices test case verifies RS485 mode of the uart driver and checks
|
||||||
|
* correctness of RS485 interface channel communication. It requires
|
||||||
|
* RS485 bus driver hardware to be connected to boards.
|
||||||
|
*/
|
||||||
|
TEST_CASE_MULTIPLE_DEVICES("RS485 half duplex uart multiple devices test.", "[driver_RS485][test_env=UT_T2_RS485]", rs485_master, rs485_slave);
|
555
components/driver/test/esp32/test_spi_param.c
Normal file
555
components/driver/test/esp32/test_spi_param.c
Normal file
|
@ -0,0 +1,555 @@
|
||||||
|
#include "test/test_common_spi.h"
|
||||||
|
#include "driver/spi_master.h"
|
||||||
|
#include "driver/spi_slave.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "soc/spi_periph.h"
|
||||||
|
#include "test/test_common_spi.h"
|
||||||
|
|
||||||
|
|
||||||
|
/********************************************************************************
|
||||||
|
* Test By Master & Slave (2 boards)
|
||||||
|
*
|
||||||
|
* Wiring:
|
||||||
|
* | Master | Slave |
|
||||||
|
* | ------ | ----- |
|
||||||
|
* | 12 | 19 |
|
||||||
|
* | 13 | 23 |
|
||||||
|
* | 14 | 18 |
|
||||||
|
* | 15 | 5 |
|
||||||
|
* | GND | GND |
|
||||||
|
*
|
||||||
|
********************************************************************************/
|
||||||
|
static void test_master_init(void** context);
|
||||||
|
static void test_master_deinit(void* context);
|
||||||
|
static void test_master_loop(const void *test_cfg, void* context);
|
||||||
|
|
||||||
|
static const ptest_func_t master_test_func = {
|
||||||
|
.pre_test = test_master_init,
|
||||||
|
.post_test = test_master_deinit,
|
||||||
|
.loop = test_master_loop,
|
||||||
|
.def_param = spitest_def_param,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void test_slave_init(void** context);
|
||||||
|
static void test_slave_deinit(void* context);
|
||||||
|
static void test_slave_loop(const void *test_cfg, void* context);
|
||||||
|
|
||||||
|
static const ptest_func_t slave_test_func = {
|
||||||
|
.pre_test = test_slave_init,
|
||||||
|
.post_test = test_slave_deinit,
|
||||||
|
.loop = test_slave_loop,
|
||||||
|
.def_param = spitest_def_param,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define TEST_SPI_MASTER_SLAVE(name, param_group, extra_tag) \
|
||||||
|
PARAM_GROUP_DECLARE(name, param_group) \
|
||||||
|
TEST_MASTER_SLAVE(name, param_group, "[spi_ms][test_env=Example_SPI_Multi_device][timeout=120]"#extra_tag, &master_test_func, &slave_test_func)
|
||||||
|
|
||||||
|
/************ Master Code ***********************************************/
|
||||||
|
static void test_master_init(void** arg)
|
||||||
|
{
|
||||||
|
TEST_ASSERT(*arg==NULL);
|
||||||
|
*arg = malloc(sizeof(spitest_context_t));
|
||||||
|
spitest_context_t* context = *arg;
|
||||||
|
TEST_ASSERT(context!=NULL);
|
||||||
|
context->slave_context = (spi_slave_task_context_t){};
|
||||||
|
esp_err_t err = init_slave_context(&context->slave_context);
|
||||||
|
TEST_ASSERT(err == ESP_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_master_deinit(void* arg)
|
||||||
|
{
|
||||||
|
spitest_context_t* context = (spitest_context_t*)arg;
|
||||||
|
deinit_slave_context(&context->slave_context);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_master_start(spi_device_handle_t *spi, int freq, const spitest_param_set_t* pset, spitest_context_t* context)
|
||||||
|
{
|
||||||
|
//master config
|
||||||
|
spi_bus_config_t buspset=SPI_BUS_TEST_DEFAULT_CONFIG();
|
||||||
|
buspset.miso_io_num = spi_periph_signal[HSPI_HOST].spiq_iomux_pin;
|
||||||
|
buspset.mosi_io_num = spi_periph_signal[HSPI_HOST].spid_iomux_pin;
|
||||||
|
buspset.sclk_io_num = spi_periph_signal[HSPI_HOST].spiclk_iomux_pin;
|
||||||
|
//this does nothing, but avoid the driver from using native pins
|
||||||
|
if (!pset->master_iomux) buspset.quadhd_io_num = spi_periph_signal[VSPI_HOST].spiq_iomux_pin;
|
||||||
|
spi_device_interface_config_t devpset=SPI_DEVICE_TEST_DEFAULT_CONFIG();
|
||||||
|
devpset.spics_io_num = spi_periph_signal[HSPI_HOST].spics0_iomux_pin;
|
||||||
|
devpset.mode = pset->mode;
|
||||||
|
const int cs_pretrans_max = 15;
|
||||||
|
if (pset->dup==HALF_DUPLEX_MISO) {
|
||||||
|
devpset.cs_ena_pretrans = cs_pretrans_max;
|
||||||
|
devpset.flags |= SPI_DEVICE_HALFDUPLEX;
|
||||||
|
} else if (pset->dup == HALF_DUPLEX_MOSI) {
|
||||||
|
devpset.cs_ena_pretrans = cs_pretrans_max;
|
||||||
|
devpset.flags |= SPI_DEVICE_NO_DUMMY;
|
||||||
|
} else {
|
||||||
|
devpset.cs_ena_pretrans = cs_pretrans_max;//20;
|
||||||
|
}
|
||||||
|
const int cs_posttrans_max = 15;
|
||||||
|
devpset.cs_ena_posttrans = cs_posttrans_max;
|
||||||
|
devpset.input_delay_ns = pset->slave_tv_ns;
|
||||||
|
devpset.clock_speed_hz = freq;
|
||||||
|
if (pset->master_limit != 0 && freq > pset->master_limit) devpset.flags |= SPI_DEVICE_NO_DUMMY;
|
||||||
|
TEST_ESP_OK(spi_bus_initialize(TEST_SPI_HOST, &buspset, pset->master_dma_chan));
|
||||||
|
TEST_ESP_OK(spi_bus_add_device(TEST_SPI_HOST, &devpset, spi));
|
||||||
|
|
||||||
|
//prepare data for the slave
|
||||||
|
for (int i = 0; i < pset->test_size; i ++) {
|
||||||
|
/* in the single board, the data is send to the slave task, then to the driver.
|
||||||
|
* However, in this test we don't know the data received by the slave.
|
||||||
|
* So we send to the return queue of the slave directly.
|
||||||
|
*/
|
||||||
|
//xQueueSend( slave_context.data_to_send, &slave_txdata[i], portMAX_DELAY );
|
||||||
|
|
||||||
|
uint8_t slave_buffer[320+8];
|
||||||
|
int length;
|
||||||
|
if (pset->dup!=HALF_DUPLEX_MISO) {
|
||||||
|
length = context->master_trans[i].length;
|
||||||
|
} else {
|
||||||
|
length = context->master_trans[i].rxlength;
|
||||||
|
}
|
||||||
|
uint32_t* ptr = (uint32_t*)slave_buffer;
|
||||||
|
ptr[0] = length;
|
||||||
|
ptr[1] = (uint32_t)context->slave_trans[i].start;
|
||||||
|
if (context->master_trans[i].tx_buffer!=NULL) {
|
||||||
|
memcpy(ptr+2, context->master_trans[i].tx_buffer, (context->master_trans[i].length+7)/8);
|
||||||
|
}
|
||||||
|
//Send to return queue directly
|
||||||
|
xRingbufferSend(context->slave_context.data_received, slave_buffer, 8+(length+7)/8, portMAX_DELAY);
|
||||||
|
}
|
||||||
|
memset(context->master_rxbuf, 0x66, sizeof(context->master_rxbuf));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_master_loop(const void *arg1, void* arg2)
|
||||||
|
{
|
||||||
|
const spitest_param_set_t *test_cfg = (spitest_param_set_t*)arg1;
|
||||||
|
spitest_context_t* context = (spitest_context_t*)arg2;
|
||||||
|
spi_device_handle_t spi;
|
||||||
|
spitest_init_transactions(test_cfg, context);
|
||||||
|
const int *timing_speed_array = test_cfg->freq_list;
|
||||||
|
|
||||||
|
ESP_LOGI(MASTER_TAG, "****************** %s ***************", test_cfg->pset_name);
|
||||||
|
for (int i=0; ; i++ ) {
|
||||||
|
const int freq = timing_speed_array[i];
|
||||||
|
if (freq==0) break;
|
||||||
|
if (test_cfg->freq_limit && freq > test_cfg->freq_limit) break;
|
||||||
|
|
||||||
|
ESP_LOGI(MASTER_TAG, "==============> %dk", freq/1000);
|
||||||
|
test_master_start(&spi, freq, test_cfg, context);
|
||||||
|
|
||||||
|
unity_wait_for_signal("slave ready");
|
||||||
|
|
||||||
|
for( int j= 0; j < test_cfg->test_size; j ++ ) {
|
||||||
|
//wait for both master and slave end
|
||||||
|
ESP_LOGI( MASTER_TAG, "=> test%d", j );
|
||||||
|
//send master tx data
|
||||||
|
vTaskDelay(20);
|
||||||
|
|
||||||
|
spi_transaction_t *t = &context->master_trans[j];
|
||||||
|
TEST_ESP_OK (spi_device_transmit(spi, t) );
|
||||||
|
int len = get_trans_len(test_cfg->dup, t);
|
||||||
|
spitest_master_print_data(t, len);
|
||||||
|
|
||||||
|
size_t rcv_len;
|
||||||
|
slave_rxdata_t *rcv_data = xRingbufferReceive( context->slave_context.data_received, &rcv_len, portMAX_DELAY );
|
||||||
|
spitest_slave_print_data(rcv_data, false);
|
||||||
|
|
||||||
|
//check result
|
||||||
|
bool check_master_data = (test_cfg->dup != HALF_DUPLEX_MOSI &&
|
||||||
|
(test_cfg->master_limit == 0 || freq <= test_cfg->master_limit));
|
||||||
|
const bool check_slave_data = false;
|
||||||
|
const bool check_len = false;
|
||||||
|
if (!check_master_data) {
|
||||||
|
ESP_LOGI(MASTER_TAG, "skip data check due to duplex mode or freq.");
|
||||||
|
} else {
|
||||||
|
TEST_ESP_OK(spitest_check_data(len, t, rcv_data, check_master_data,
|
||||||
|
check_len, check_slave_data));
|
||||||
|
}
|
||||||
|
//clean
|
||||||
|
vRingbufferReturnItem( context->slave_context.data_received, rcv_data );
|
||||||
|
}
|
||||||
|
master_free_device_bus(spi);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/************ Slave Code ***********************************************/
|
||||||
|
static void test_slave_init(void** arg)
|
||||||
|
{
|
||||||
|
TEST_ASSERT(*arg==NULL);
|
||||||
|
*arg = malloc(sizeof(spitest_context_t));
|
||||||
|
spitest_context_t* context = (spitest_context_t*)*arg;
|
||||||
|
TEST_ASSERT(context!=NULL);
|
||||||
|
context->slave_context = (spi_slave_task_context_t){};
|
||||||
|
esp_err_t err = init_slave_context( &context->slave_context );
|
||||||
|
TEST_ASSERT( err == ESP_OK );
|
||||||
|
|
||||||
|
xTaskCreate( spitest_slave_task, "spi_slave", 4096, &context->slave_context, 0, &context->handle_slave);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_slave_deinit(void* arg)
|
||||||
|
{
|
||||||
|
spitest_context_t* context = (spitest_context_t*)arg;
|
||||||
|
vTaskDelete( context->handle_slave );
|
||||||
|
context->handle_slave = 0;
|
||||||
|
|
||||||
|
deinit_slave_context(&context->slave_context);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void timing_slave_start(int speed, const spitest_param_set_t* pset, spitest_context_t *context)
|
||||||
|
{
|
||||||
|
//slave config
|
||||||
|
spi_bus_config_t slv_buscfg=SPI_BUS_TEST_DEFAULT_CONFIG();
|
||||||
|
slv_buscfg.miso_io_num = spi_periph_signal[VSPI_HOST].spiq_iomux_pin;
|
||||||
|
slv_buscfg.mosi_io_num = spi_periph_signal[VSPI_HOST].spid_iomux_pin;
|
||||||
|
slv_buscfg.sclk_io_num = spi_periph_signal[VSPI_HOST].spiclk_iomux_pin;
|
||||||
|
//this does nothing, but avoid the driver from using native pins
|
||||||
|
if (!pset->slave_iomux) slv_buscfg.quadhd_io_num = spi_periph_signal[HSPI_HOST].spiclk_iomux_pin;
|
||||||
|
spi_slave_interface_config_t slvcfg=SPI_SLAVE_TEST_DEFAULT_CONFIG();
|
||||||
|
slvcfg.spics_io_num = spi_periph_signal[VSPI_HOST].spics0_iomux_pin;
|
||||||
|
slvcfg.mode = pset->mode;
|
||||||
|
//Enable pull-ups on SPI lines so we don't detect rogue pulses when no master is connected.
|
||||||
|
slave_pull_up(&slv_buscfg, slvcfg.spics_io_num);
|
||||||
|
|
||||||
|
TEST_ESP_OK(spi_slave_initialize(TEST_SLAVE_HOST, &slv_buscfg, &slvcfg, pset->slave_dma_chan));
|
||||||
|
|
||||||
|
//prepare data for the master
|
||||||
|
for (int i = 0; i < pset->test_size; i++) {
|
||||||
|
if (pset->dup==FULL_DUPLEX) {
|
||||||
|
memcpy(context->master_trans[i].rx_buffer, context->slave_trans[i].start, (context->master_trans[i].length+7)/8);
|
||||||
|
} else if (pset->dup==HALF_DUPLEX_MISO) {
|
||||||
|
memcpy(context->master_trans[i].rx_buffer, context->slave_trans[i].start, (context->master_trans[i].rxlength+7)/8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_slave_loop(const void *arg1, void* arg2)
|
||||||
|
{
|
||||||
|
const spitest_param_set_t *pset = (spitest_param_set_t*)arg1;
|
||||||
|
spitest_context_t* context = (spitest_context_t*)arg2;
|
||||||
|
ESP_LOGI(SLAVE_TAG, "****************** %s ***************", pset->pset_name);
|
||||||
|
spitest_init_transactions(pset, context);
|
||||||
|
|
||||||
|
const int *timing_speed_array = pset->freq_list;
|
||||||
|
for (int i=0; ; i++ ) {
|
||||||
|
const int freq = timing_speed_array[i];
|
||||||
|
if (freq==0) break;
|
||||||
|
if (pset->freq_limit != 0 && freq > pset->freq_limit) break;
|
||||||
|
|
||||||
|
ESP_LOGI(MASTER_TAG, "==============> %dk", timing_speed_array[i]/1000);
|
||||||
|
//Initialize SPI slave interface
|
||||||
|
timing_slave_start(freq, pset, context);
|
||||||
|
|
||||||
|
//prepare slave tx data
|
||||||
|
for (int i = 0; i < pset->test_size; i ++) {
|
||||||
|
xQueueSend( context->slave_context.data_to_send, &context->slave_trans[i], portMAX_DELAY );
|
||||||
|
//memcpy(context->master_trans[i].rx_buffer, context->slave_trans[i].start, (context->master_trans[i].length+7)/8);
|
||||||
|
}
|
||||||
|
|
||||||
|
vTaskDelay(50/portTICK_PERIOD_MS);
|
||||||
|
unity_send_signal("slave ready");
|
||||||
|
|
||||||
|
for( int i= 0; i < pset->test_size; i ++ ) {
|
||||||
|
//wait for both master and slave end
|
||||||
|
ESP_LOGI( MASTER_TAG, "===== test%d =====", i );
|
||||||
|
//send master tx data
|
||||||
|
vTaskDelay(20);
|
||||||
|
|
||||||
|
spi_transaction_t *t = &context->master_trans[i];
|
||||||
|
int len = get_trans_len(pset->dup, t);
|
||||||
|
spitest_master_print_data(t, FULL_DUPLEX);
|
||||||
|
|
||||||
|
size_t rcv_len;
|
||||||
|
slave_rxdata_t *rcv_data = xRingbufferReceive( context->slave_context.data_received, &rcv_len, portMAX_DELAY );
|
||||||
|
spitest_slave_print_data(rcv_data, true);
|
||||||
|
|
||||||
|
//check result
|
||||||
|
const bool check_master_data = false;
|
||||||
|
bool check_slave_data = (pset->dup!=HALF_DUPLEX_MISO);
|
||||||
|
const bool check_len = true;
|
||||||
|
TEST_ESP_OK(spitest_check_data(len, t, rcv_data, check_master_data, check_len, check_slave_data));
|
||||||
|
//clean
|
||||||
|
vRingbufferReturnItem( context->slave_context.data_received, rcv_data );
|
||||||
|
}
|
||||||
|
TEST_ASSERT(spi_slave_free(TEST_SLAVE_HOST) == ESP_OK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/************ Timing Test ***********************************************/
|
||||||
|
static spitest_param_set_t timing_conf[] = {
|
||||||
|
{ .pset_name = "FULL_DUP, BOTH IOMUX",
|
||||||
|
.freq_limit = ESP_SPI_SLAVE_MAX_FREQ,
|
||||||
|
.master_limit = SPI_MASTER_FREQ_16M,
|
||||||
|
.dup = FULL_DUPLEX,
|
||||||
|
.master_iomux= true,
|
||||||
|
.slave_iomux = true,
|
||||||
|
.slave_tv_ns = TV_WITH_ESP_SLAVE,
|
||||||
|
},
|
||||||
|
{ .pset_name = "FULL_DUP, MASTER IOMUX",
|
||||||
|
.freq_limit = ESP_SPI_SLAVE_MAX_FREQ,
|
||||||
|
.master_limit = SPI_MASTER_FREQ_11M,
|
||||||
|
.dup = FULL_DUPLEX,
|
||||||
|
.master_iomux = true,
|
||||||
|
.slave_iomux = false,
|
||||||
|
.slave_tv_ns = TV_WITH_ESP_SLAVE_GPIO,
|
||||||
|
},
|
||||||
|
{ .pset_name = "FULL_DUP, SLAVE IOMUX",
|
||||||
|
.freq_limit = ESP_SPI_SLAVE_MAX_FREQ,
|
||||||
|
.master_limit = SPI_MASTER_FREQ_11M,
|
||||||
|
.dup = FULL_DUPLEX,
|
||||||
|
.master_iomux = false,
|
||||||
|
.slave_iomux = true,
|
||||||
|
.slave_tv_ns = TV_WITH_ESP_SLAVE,
|
||||||
|
},
|
||||||
|
{ .pset_name = "FULL_DUP, BOTH GPIO",
|
||||||
|
.freq_limit = ESP_SPI_SLAVE_MAX_FREQ,
|
||||||
|
.master_limit = SPI_MASTER_FREQ_9M,
|
||||||
|
.dup = FULL_DUPLEX,
|
||||||
|
.master_iomux = false,
|
||||||
|
.slave_iomux = false,
|
||||||
|
.slave_tv_ns = TV_WITH_ESP_SLAVE_GPIO,
|
||||||
|
},
|
||||||
|
{ .pset_name = "MOSI_DUP, BOTH IOMUX",
|
||||||
|
.freq_limit = ESP_SPI_SLAVE_MAX_FREQ,
|
||||||
|
.dup = HALF_DUPLEX_MOSI,
|
||||||
|
.master_iomux= true,
|
||||||
|
.slave_iomux = true,
|
||||||
|
.slave_tv_ns = TV_WITH_ESP_SLAVE,
|
||||||
|
},
|
||||||
|
{ .pset_name = "MOSI_DUP, MASTER IOMUX",
|
||||||
|
.freq_limit = ESP_SPI_SLAVE_MAX_FREQ,
|
||||||
|
.dup = HALF_DUPLEX_MOSI,
|
||||||
|
.master_iomux= true,
|
||||||
|
.slave_iomux = false,
|
||||||
|
.slave_tv_ns = TV_WITH_ESP_SLAVE_GPIO,
|
||||||
|
},
|
||||||
|
{ .pset_name = "MOSI_DUP, SLAVE IOMUX",
|
||||||
|
.freq_limit = ESP_SPI_SLAVE_MAX_FREQ,
|
||||||
|
.dup = HALF_DUPLEX_MOSI,
|
||||||
|
.master_iomux= false,
|
||||||
|
.slave_iomux = true,
|
||||||
|
.slave_tv_ns = TV_WITH_ESP_SLAVE,
|
||||||
|
},
|
||||||
|
{ .pset_name = "MOSI_DUP, BOTH GPIO",
|
||||||
|
.freq_limit = ESP_SPI_SLAVE_MAX_FREQ,
|
||||||
|
.dup = HALF_DUPLEX_MOSI,
|
||||||
|
.master_iomux= false,
|
||||||
|
.slave_iomux = false,
|
||||||
|
.slave_tv_ns = TV_WITH_ESP_SLAVE_GPIO,
|
||||||
|
},
|
||||||
|
{ .pset_name = "MISO_DUP, BOTH IOMUX",
|
||||||
|
.freq_limit = ESP_SPI_SLAVE_MAX_FREQ,
|
||||||
|
.dup = HALF_DUPLEX_MISO,
|
||||||
|
.master_iomux = true,
|
||||||
|
.slave_iomux = true,
|
||||||
|
.slave_tv_ns = TV_WITH_ESP_SLAVE,
|
||||||
|
},
|
||||||
|
{ .pset_name = "MISO_DUP, MASTER IOMUX",
|
||||||
|
.freq_limit = ESP_SPI_SLAVE_MAX_FREQ,
|
||||||
|
.dup = HALF_DUPLEX_MISO,
|
||||||
|
.master_iomux = true,
|
||||||
|
.slave_iomux = false,
|
||||||
|
.slave_tv_ns = TV_WITH_ESP_SLAVE_GPIO,
|
||||||
|
},
|
||||||
|
{ .pset_name = "MISO_DUP, SLAVE IOMUX",
|
||||||
|
.freq_limit = ESP_SPI_SLAVE_MAX_FREQ,
|
||||||
|
.dup = HALF_DUPLEX_MISO,
|
||||||
|
.master_iomux = false,
|
||||||
|
.slave_iomux = true,
|
||||||
|
.slave_tv_ns = TV_WITH_ESP_SLAVE,
|
||||||
|
},
|
||||||
|
{ .pset_name = "MISO_DUP, BOTH GPIO",
|
||||||
|
.freq_limit = ESP_SPI_SLAVE_MAX_FREQ,
|
||||||
|
.dup = HALF_DUPLEX_MISO,
|
||||||
|
.master_iomux = false,
|
||||||
|
.slave_iomux = false,
|
||||||
|
.slave_tv_ns = TV_WITH_ESP_SLAVE_GPIO,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
TEST_SPI_MASTER_SLAVE(TIMING, timing_conf, "")
|
||||||
|
|
||||||
|
/************ Mode Test ***********************************************/
|
||||||
|
#define FREQ_LIMIT_MODE SPI_MASTER_FREQ_16M
|
||||||
|
//Set to this input delay so that the master will read with delay until 7M
|
||||||
|
#define DELAY_HCLK_UNTIL_7M 12.5*3
|
||||||
|
|
||||||
|
static int test_freq_mode_ms[]={
|
||||||
|
100*1000,
|
||||||
|
6*1000*1000,
|
||||||
|
7*1000*1000,
|
||||||
|
SPI_MASTER_FREQ_8M, //maximum freq MISO stable before next latch edge
|
||||||
|
SPI_MASTER_FREQ_9M, //maximum freq MISO stable before next latch edge
|
||||||
|
SPI_MASTER_FREQ_10M,
|
||||||
|
SPI_MASTER_FREQ_11M,
|
||||||
|
SPI_MASTER_FREQ_13M,
|
||||||
|
SPI_MASTER_FREQ_16M,
|
||||||
|
SPI_MASTER_FREQ_20M,
|
||||||
|
0,
|
||||||
|
};
|
||||||
|
static int test_freq_20M_only[]={
|
||||||
|
SPI_MASTER_FREQ_20M,
|
||||||
|
0,
|
||||||
|
};
|
||||||
|
|
||||||
|
spitest_param_set_t mode_conf[] = {
|
||||||
|
//non-DMA tests
|
||||||
|
{ .pset_name = "mode 0, no DMA",
|
||||||
|
.freq_list = test_freq_mode_ms,
|
||||||
|
.master_limit = FREQ_LIMIT_MODE,
|
||||||
|
.dup = FULL_DUPLEX,
|
||||||
|
.master_iomux= true,
|
||||||
|
.slave_iomux = true,
|
||||||
|
.slave_tv_ns = TV_WITH_ESP_SLAVE,
|
||||||
|
.mode = 0,
|
||||||
|
},
|
||||||
|
{ .pset_name = "mode 1, no DMA",
|
||||||
|
.freq_list = test_freq_mode_ms,
|
||||||
|
.master_limit = FREQ_LIMIT_MODE,
|
||||||
|
.dup = FULL_DUPLEX,
|
||||||
|
.master_iomux= true,
|
||||||
|
.slave_iomux = true,
|
||||||
|
.slave_tv_ns = TV_WITH_ESP_SLAVE,
|
||||||
|
.mode = 1,
|
||||||
|
},
|
||||||
|
{ .pset_name = "mode 2, no DMA",
|
||||||
|
.freq_list = test_freq_mode_ms,
|
||||||
|
.master_limit = FREQ_LIMIT_MODE,
|
||||||
|
.dup = FULL_DUPLEX,
|
||||||
|
.master_iomux= true,
|
||||||
|
.slave_iomux = true,
|
||||||
|
.slave_tv_ns = TV_WITH_ESP_SLAVE,
|
||||||
|
.mode = 2,
|
||||||
|
},
|
||||||
|
{ .pset_name = "mode 3, no DMA",
|
||||||
|
.freq_list = test_freq_mode_ms,
|
||||||
|
.master_limit = FREQ_LIMIT_MODE,
|
||||||
|
.dup = FULL_DUPLEX,
|
||||||
|
.master_iomux= true,
|
||||||
|
.slave_iomux = true,
|
||||||
|
.slave_tv_ns = TV_WITH_ESP_SLAVE,
|
||||||
|
.mode = 3,
|
||||||
|
},
|
||||||
|
//the master can only read to 16MHz, use half-duplex mode to read at 20.
|
||||||
|
{ .pset_name = "mode 0, no DMA, 20M",
|
||||||
|
.freq_list = test_freq_20M_only,
|
||||||
|
.dup = HALF_DUPLEX_MISO,
|
||||||
|
.master_iomux= true,
|
||||||
|
.slave_iomux = true,
|
||||||
|
.slave_tv_ns = TV_WITH_ESP_SLAVE,
|
||||||
|
.mode = 0,
|
||||||
|
},
|
||||||
|
{ .pset_name = "mode 1, no DMA, 20M",
|
||||||
|
.freq_list = test_freq_20M_only,
|
||||||
|
.dup = HALF_DUPLEX_MISO,
|
||||||
|
.master_iomux= true,
|
||||||
|
.slave_iomux = true,
|
||||||
|
.slave_tv_ns = TV_WITH_ESP_SLAVE,
|
||||||
|
.mode = 1,
|
||||||
|
},
|
||||||
|
{ .pset_name = "mode 2, no DMA, 20M",
|
||||||
|
.freq_list = test_freq_20M_only,
|
||||||
|
.dup = HALF_DUPLEX_MISO,
|
||||||
|
.master_iomux= true,
|
||||||
|
.slave_iomux = true,
|
||||||
|
.slave_tv_ns = TV_WITH_ESP_SLAVE,
|
||||||
|
.mode = 2,
|
||||||
|
},
|
||||||
|
{ .pset_name = "mode 3, no DMA, 20M",
|
||||||
|
.freq_list = test_freq_20M_only,
|
||||||
|
.dup = HALF_DUPLEX_MISO,
|
||||||
|
.master_iomux= true,
|
||||||
|
.slave_iomux = true,
|
||||||
|
.slave_tv_ns = TV_WITH_ESP_SLAVE,
|
||||||
|
.mode = 3,
|
||||||
|
},
|
||||||
|
//DMA tests
|
||||||
|
{ .pset_name = "mode 0, DMA",
|
||||||
|
.freq_list = test_freq_mode_ms,
|
||||||
|
.master_limit = FREQ_LIMIT_MODE,
|
||||||
|
.dup = FULL_DUPLEX,
|
||||||
|
.master_iomux= true,
|
||||||
|
.slave_iomux = true,
|
||||||
|
.slave_tv_ns = DELAY_HCLK_UNTIL_7M,
|
||||||
|
.mode = 0,
|
||||||
|
.master_dma_chan = 1,
|
||||||
|
.slave_dma_chan = 1,
|
||||||
|
.length_aligned = true,
|
||||||
|
},
|
||||||
|
{ .pset_name = "mode 1, DMA",
|
||||||
|
.freq_list = test_freq_mode_ms,
|
||||||
|
.master_limit = FREQ_LIMIT_MODE,
|
||||||
|
.dup = FULL_DUPLEX,
|
||||||
|
.master_iomux= true,
|
||||||
|
.slave_iomux = true,
|
||||||
|
.slave_tv_ns = TV_WITH_ESP_SLAVE,
|
||||||
|
.mode = 1,
|
||||||
|
.master_dma_chan = 1,
|
||||||
|
.slave_dma_chan = 1,
|
||||||
|
.length_aligned = true,
|
||||||
|
},
|
||||||
|
{ .pset_name = "mode 2, DMA",
|
||||||
|
.freq_list = test_freq_mode_ms,
|
||||||
|
.master_limit = FREQ_LIMIT_MODE,
|
||||||
|
.dup = FULL_DUPLEX,
|
||||||
|
.master_iomux= true,
|
||||||
|
.slave_iomux = true,
|
||||||
|
.slave_tv_ns = DELAY_HCLK_UNTIL_7M,
|
||||||
|
.mode = 2,
|
||||||
|
.master_dma_chan = 1,
|
||||||
|
.slave_dma_chan = 1,
|
||||||
|
.length_aligned = true,
|
||||||
|
},
|
||||||
|
{ .pset_name = "mode 3, DMA",
|
||||||
|
.freq_list = test_freq_mode_ms,
|
||||||
|
.master_limit = FREQ_LIMIT_MODE,
|
||||||
|
.dup = FULL_DUPLEX,
|
||||||
|
.master_iomux= true,
|
||||||
|
.slave_iomux = true,
|
||||||
|
.slave_tv_ns = TV_WITH_ESP_SLAVE,
|
||||||
|
.mode = 3,
|
||||||
|
.master_dma_chan = 1,
|
||||||
|
.slave_dma_chan = 1,
|
||||||
|
.length_aligned = true,
|
||||||
|
},
|
||||||
|
//the master can only read to 16MHz, use half-duplex mode to read at 20.
|
||||||
|
{ .pset_name = "mode 0, DMA, 20M",
|
||||||
|
.freq_list = test_freq_20M_only,
|
||||||
|
.dup = HALF_DUPLEX_MISO,
|
||||||
|
.master_iomux= true,
|
||||||
|
.slave_iomux = true,
|
||||||
|
.slave_tv_ns = TV_WITH_ESP_SLAVE,
|
||||||
|
.mode = 0,
|
||||||
|
.master_dma_chan = 1,
|
||||||
|
.slave_dma_chan = 1,
|
||||||
|
},
|
||||||
|
{ .pset_name = "mode 1, DMA, 20M",
|
||||||
|
.freq_list = test_freq_20M_only,
|
||||||
|
.dup = HALF_DUPLEX_MISO,
|
||||||
|
.master_iomux= true,
|
||||||
|
.slave_iomux = true,
|
||||||
|
.slave_tv_ns = TV_WITH_ESP_SLAVE,
|
||||||
|
.mode = 1,
|
||||||
|
.master_dma_chan = 1,
|
||||||
|
.slave_dma_chan = 1,
|
||||||
|
},
|
||||||
|
{ .pset_name = "mode 2, DMA, 20M",
|
||||||
|
.freq_list = test_freq_20M_only,
|
||||||
|
.dup = HALF_DUPLEX_MISO,
|
||||||
|
.master_iomux= true,
|
||||||
|
.slave_iomux = true,
|
||||||
|
.slave_tv_ns = TV_WITH_ESP_SLAVE,
|
||||||
|
.mode = 2,
|
||||||
|
.master_dma_chan = 1,
|
||||||
|
.slave_dma_chan = 1,
|
||||||
|
},
|
||||||
|
{ .pset_name = "mode 3, DMA, 20M",
|
||||||
|
.freq_list = test_freq_20M_only,
|
||||||
|
.dup = HALF_DUPLEX_MISO,
|
||||||
|
.master_iomux= true,
|
||||||
|
.slave_iomux = true,
|
||||||
|
.slave_tv_ns = TV_WITH_ESP_SLAVE,
|
||||||
|
.mode = 3,
|
||||||
|
.master_dma_chan = 1,
|
||||||
|
.slave_dma_chan = 1,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
TEST_SPI_MASTER_SLAVE(MODE, mode_conf, "[ignore]")
|
143
components/driver/test/esp32/test_spi_sio.c
Normal file
143
components/driver/test/esp32/test_spi_sio.c
Normal file
|
@ -0,0 +1,143 @@
|
||||||
|
/*
|
||||||
|
Tests for the spi sio mode
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <esp_types.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/task.h"
|
||||||
|
#include "freertos/semphr.h"
|
||||||
|
#include "freertos/queue.h"
|
||||||
|
#include "freertos/xtensa_api.h"
|
||||||
|
#include "unity.h"
|
||||||
|
#include "driver/spi_master.h"
|
||||||
|
#include "driver/spi_slave.h"
|
||||||
|
#include "esp_heap_caps.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "soc/spi_periph.h"
|
||||||
|
#include "test_utils.h"
|
||||||
|
#include "test/test_common_spi.h"
|
||||||
|
#include "soc/gpio_periph.h"
|
||||||
|
#include "sdkconfig.h"
|
||||||
|
#include "hal/spi_ll.h"
|
||||||
|
|
||||||
|
|
||||||
|
/********************************************************************************
|
||||||
|
* Test SIO Master & Slave
|
||||||
|
********************************************************************************/
|
||||||
|
//if test_mosi is false, test on miso of slave, otherwise test on mosi of slave
|
||||||
|
static void test_sio_master_round(bool test_mosi)
|
||||||
|
{
|
||||||
|
spi_device_handle_t spi;
|
||||||
|
WORD_ALIGNED_ATTR uint8_t rx_buffer[320];
|
||||||
|
|
||||||
|
if (test_mosi) {
|
||||||
|
ESP_LOGI(MASTER_TAG, "======== TEST MOSI ===========");
|
||||||
|
} else {
|
||||||
|
ESP_LOGI(MASTER_TAG, "======== TEST MISO ===========");
|
||||||
|
}
|
||||||
|
|
||||||
|
spi_bus_config_t bus_cfg = SPI_BUS_TEST_DEFAULT_CONFIG();
|
||||||
|
if (!test_mosi) bus_cfg.mosi_io_num = bus_cfg.miso_io_num;
|
||||||
|
bus_cfg.miso_io_num = -1;
|
||||||
|
TEST_ESP_OK(spi_bus_initialize(TEST_SPI_HOST, &bus_cfg, 0));
|
||||||
|
|
||||||
|
spi_device_interface_config_t dev_cfg = SPI_DEVICE_TEST_DEFAULT_CONFIG();
|
||||||
|
dev_cfg.flags = SPI_DEVICE_HALFDUPLEX | SPI_DEVICE_3WIRE;
|
||||||
|
dev_cfg.clock_speed_hz = 1*1000*1000;
|
||||||
|
TEST_ESP_OK(spi_bus_add_device(TEST_SPI_HOST, &dev_cfg, &spi));
|
||||||
|
|
||||||
|
for (int i = 0; i < 8; i ++) {
|
||||||
|
int tlen = i*2+1;
|
||||||
|
int rlen = 9-i;
|
||||||
|
spi_transaction_t t = {
|
||||||
|
.length = tlen*8,
|
||||||
|
.tx_buffer = spitest_master_send+i,
|
||||||
|
.rxlength = rlen*8,
|
||||||
|
.rx_buffer = rx_buffer+i,
|
||||||
|
};
|
||||||
|
memset(rx_buffer, 0x66, sizeof(rx_buffer));
|
||||||
|
|
||||||
|
//get signal
|
||||||
|
unity_wait_for_signal("slave ready");
|
||||||
|
|
||||||
|
TEST_ESP_OK(spi_device_transmit(spi, &t));
|
||||||
|
uint8_t* exp_ptr = spitest_slave_send+i;
|
||||||
|
ESP_LOG_BUFFER_HEXDUMP("master tx", t.tx_buffer, tlen, ESP_LOG_INFO);
|
||||||
|
ESP_LOG_BUFFER_HEXDUMP("exp tx", exp_ptr, rlen, ESP_LOG_INFO);
|
||||||
|
ESP_LOG_BUFFER_HEXDUMP("master rx", t.rx_buffer, rlen, ESP_LOG_INFO);
|
||||||
|
if (!test_mosi) {
|
||||||
|
TEST_ASSERT_EQUAL_HEX8_ARRAY(exp_ptr+tlen, t.rx_buffer, rlen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
master_free_device_bus(spi);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sio_master(void)
|
||||||
|
{
|
||||||
|
test_sio_master_round(true);
|
||||||
|
unity_send_signal("master ready");
|
||||||
|
test_sio_master_round(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sio_slave_round(bool test_mosi)
|
||||||
|
{
|
||||||
|
WORD_ALIGNED_ATTR uint8_t rx_buffer[320];
|
||||||
|
|
||||||
|
if (test_mosi) {
|
||||||
|
ESP_LOGI(SLAVE_TAG, "======== TEST MOSI ===========");
|
||||||
|
} else {
|
||||||
|
ESP_LOGI(SLAVE_TAG, "======== TEST MISO ===========");
|
||||||
|
}
|
||||||
|
|
||||||
|
spi_bus_config_t bus_cfg = SPI_BUS_TEST_DEFAULT_CONFIG();
|
||||||
|
bus_cfg.mosi_io_num = spi_periph_signal[TEST_SLAVE_HOST].spid_iomux_pin;
|
||||||
|
bus_cfg.miso_io_num = spi_periph_signal[TEST_SLAVE_HOST].spiq_iomux_pin;
|
||||||
|
bus_cfg.sclk_io_num = spi_periph_signal[TEST_SLAVE_HOST].spiclk_iomux_pin;
|
||||||
|
|
||||||
|
spi_slave_interface_config_t slv_cfg = SPI_SLAVE_TEST_DEFAULT_CONFIG();
|
||||||
|
slv_cfg.spics_io_num = spi_periph_signal[TEST_SLAVE_HOST].spics0_iomux_pin;
|
||||||
|
TEST_ESP_OK(spi_slave_initialize(TEST_SLAVE_HOST, &bus_cfg, &slv_cfg, 0));
|
||||||
|
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
int tlen = 9-i;
|
||||||
|
int rlen = i*2+1;
|
||||||
|
spi_slave_transaction_t t = {
|
||||||
|
.length = (tlen+rlen)*8,
|
||||||
|
.tx_buffer = spitest_slave_send+i,
|
||||||
|
.rx_buffer = rx_buffer,
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_ESP_OK(spi_slave_queue_trans(TEST_SLAVE_HOST, &t, portMAX_DELAY));
|
||||||
|
|
||||||
|
ESP_LOG_BUFFER_HEXDUMP("slave tx", t.tx_buffer, tlen+rlen, ESP_LOG_INFO);
|
||||||
|
|
||||||
|
//send signal_idx
|
||||||
|
unity_send_signal("slave ready");
|
||||||
|
|
||||||
|
uint8_t *exp_ptr = spitest_master_send+i;
|
||||||
|
spi_slave_transaction_t* ret_t;
|
||||||
|
TEST_ESP_OK(spi_slave_get_trans_result(TEST_SLAVE_HOST, &ret_t, portMAX_DELAY));
|
||||||
|
|
||||||
|
ESP_LOG_BUFFER_HEXDUMP("exp tx", exp_ptr, tlen+rlen, ESP_LOG_INFO);
|
||||||
|
ESP_LOG_BUFFER_HEXDUMP("slave rx", t.rx_buffer, tlen+rlen, ESP_LOG_INFO);
|
||||||
|
if (test_mosi) {
|
||||||
|
TEST_ASSERT_EQUAL_HEX8_ARRAY(exp_ptr, t.rx_buffer, rlen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
spi_slave_free(TEST_SLAVE_HOST);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sio_slave(void)
|
||||||
|
{
|
||||||
|
test_sio_slave_round(true);
|
||||||
|
unity_wait_for_signal("master ready");
|
||||||
|
test_sio_slave_round(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE_MULTIPLE_DEVICES("sio mode", "[spi][test_env=Example_SPI_Multi_device]", test_sio_master, test_sio_slave);
|
|
@ -62,19 +62,6 @@ static esp_err_t i2c_master_write_slave(i2c_port_t i2c_num, uint8_t *data_wr, si
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// print the reading buffer
|
|
||||||
static void disp_buf(uint8_t *buf, int len)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < len; i++) {
|
|
||||||
printf("%02x ", buf[i]);
|
|
||||||
if (( i + 1 ) % 16 == 0) {
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
static i2c_config_t i2c_master_init(void)
|
static i2c_config_t i2c_master_init(void)
|
||||||
{
|
{
|
||||||
i2c_config_t conf_master = {
|
i2c_config_t conf_master = {
|
||||||
|
@ -252,260 +239,6 @@ TEST_CASE("I2C driver memory leaking check", "[i2c]")
|
||||||
TEST_ASSERT_INT_WITHIN(100, size, esp_get_free_heap_size());
|
TEST_ASSERT_INT_WITHIN(100, size, esp_get_free_heap_size());
|
||||||
}
|
}
|
||||||
|
|
||||||
static void i2c_master_write_test(void)
|
|
||||||
{
|
|
||||||
uint8_t *data_wr = (uint8_t *) malloc(DATA_LENGTH);
|
|
||||||
int i;
|
|
||||||
|
|
||||||
i2c_config_t conf_master = i2c_master_init();
|
|
||||||
TEST_ESP_OK(i2c_param_config(I2C_MASTER_NUM, &conf_master));
|
|
||||||
|
|
||||||
TEST_ESP_OK(i2c_driver_install(I2C_MASTER_NUM, I2C_MODE_MASTER,
|
|
||||||
I2C_MASTER_RX_BUF_DISABLE,
|
|
||||||
I2C_MASTER_TX_BUF_DISABLE, 0));
|
|
||||||
unity_wait_for_signal("i2c slave init finish");
|
|
||||||
|
|
||||||
unity_send_signal("master write");
|
|
||||||
for (i = 0; i < DATA_LENGTH / 2; i++) {
|
|
||||||
data_wr[i] = i;
|
|
||||||
}
|
|
||||||
i2c_master_write_slave(I2C_MASTER_NUM, data_wr, DATA_LENGTH / 2);
|
|
||||||
disp_buf(data_wr, i + 1);
|
|
||||||
free(data_wr);
|
|
||||||
unity_wait_for_signal("ready to delete");
|
|
||||||
TEST_ESP_OK(i2c_driver_delete(I2C_MASTER_NUM));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void i2c_slave_read_test(void)
|
|
||||||
{
|
|
||||||
uint8_t *data_rd = (uint8_t *) malloc(DATA_LENGTH);
|
|
||||||
int size_rd = 0;
|
|
||||||
int len = 0;
|
|
||||||
|
|
||||||
i2c_config_t conf_slave = i2c_slave_init();
|
|
||||||
TEST_ESP_OK(i2c_param_config( I2C_SLAVE_NUM, &conf_slave));
|
|
||||||
TEST_ESP_OK(i2c_driver_install(I2C_SLAVE_NUM, I2C_MODE_SLAVE,
|
|
||||||
I2C_SLAVE_RX_BUF_LEN,
|
|
||||||
I2C_SLAVE_TX_BUF_LEN, 0));
|
|
||||||
unity_send_signal("i2c slave init finish");
|
|
||||||
|
|
||||||
unity_wait_for_signal("master write");
|
|
||||||
while (1) {
|
|
||||||
len = i2c_slave_read_buffer( I2C_SLAVE_NUM, data_rd + size_rd, DATA_LENGTH, 10000 / portTICK_RATE_MS);
|
|
||||||
if (len == 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
size_rd += len;
|
|
||||||
}
|
|
||||||
disp_buf(data_rd, size_rd);
|
|
||||||
for (int i = 0; i < size_rd; i++) {
|
|
||||||
TEST_ASSERT(data_rd[i] == i);
|
|
||||||
}
|
|
||||||
free(data_rd);
|
|
||||||
unity_send_signal("ready to delete");
|
|
||||||
TEST_ESP_OK(i2c_driver_delete(I2C_SLAVE_NUM));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE_MULTIPLE_DEVICES("I2C master write slave test", "[i2c][test_env=UT_T2_I2C][timeout=150]", i2c_master_write_test, i2c_slave_read_test);
|
|
||||||
|
|
||||||
static void master_read_slave_test(void)
|
|
||||||
{
|
|
||||||
uint8_t *data_rd = (uint8_t *) malloc(DATA_LENGTH);
|
|
||||||
memset(data_rd, 0, DATA_LENGTH);
|
|
||||||
i2c_config_t conf_master = i2c_master_init();
|
|
||||||
TEST_ESP_OK(i2c_param_config(I2C_MASTER_NUM, &conf_master));
|
|
||||||
TEST_ESP_OK(i2c_driver_install(I2C_MASTER_NUM, I2C_MODE_MASTER,
|
|
||||||
I2C_MASTER_RX_BUF_DISABLE,
|
|
||||||
I2C_MASTER_TX_BUF_DISABLE, 0));
|
|
||||||
unity_wait_for_signal("i2c slave init finish");
|
|
||||||
|
|
||||||
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
|
||||||
i2c_master_start(cmd);
|
|
||||||
i2c_master_write_byte(cmd, ( ESP_SLAVE_ADDR << 1 ) | READ_BIT, ACK_CHECK_EN);
|
|
||||||
|
|
||||||
unity_send_signal("slave write");
|
|
||||||
unity_wait_for_signal("master read");
|
|
||||||
i2c_master_read(cmd, data_rd, RW_TEST_LENGTH-1, ACK_VAL);
|
|
||||||
i2c_master_read_byte(cmd, data_rd + RW_TEST_LENGTH-1, NACK_VAL);
|
|
||||||
i2c_master_stop(cmd);
|
|
||||||
i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 5000 / portTICK_RATE_MS);
|
|
||||||
i2c_cmd_link_delete(cmd);
|
|
||||||
vTaskDelay(100 / portTICK_RATE_MS);
|
|
||||||
for (int i = 0; i < RW_TEST_LENGTH; i++) {
|
|
||||||
printf("%d\n", data_rd[i]);
|
|
||||||
TEST_ASSERT(data_rd[i]==i);
|
|
||||||
}
|
|
||||||
free(data_rd);
|
|
||||||
unity_send_signal("ready to delete");
|
|
||||||
i2c_driver_delete(I2C_MASTER_NUM);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void slave_write_buffer_test(void)
|
|
||||||
{
|
|
||||||
uint8_t *data_wr = (uint8_t *) malloc(DATA_LENGTH);
|
|
||||||
int size_rd;
|
|
||||||
|
|
||||||
i2c_config_t conf_slave = i2c_slave_init();
|
|
||||||
TEST_ESP_OK(i2c_param_config( I2C_SLAVE_NUM, &conf_slave));
|
|
||||||
TEST_ESP_OK(i2c_driver_install(I2C_SLAVE_NUM, I2C_MODE_SLAVE,
|
|
||||||
I2C_SLAVE_RX_BUF_LEN,
|
|
||||||
I2C_SLAVE_TX_BUF_LEN, 0));
|
|
||||||
unity_send_signal("i2c slave init finish");
|
|
||||||
|
|
||||||
unity_wait_for_signal("slave write");
|
|
||||||
for (int i = 0; i < DATA_LENGTH / 2; i++) {
|
|
||||||
data_wr[i] = i;
|
|
||||||
}
|
|
||||||
size_rd = i2c_slave_write_buffer(I2C_SLAVE_NUM, data_wr, RW_TEST_LENGTH, 2000 / portTICK_RATE_MS);
|
|
||||||
disp_buf(data_wr, size_rd);
|
|
||||||
unity_send_signal("master read");
|
|
||||||
unity_wait_for_signal("ready to delete");
|
|
||||||
free(data_wr);
|
|
||||||
i2c_driver_delete(I2C_SLAVE_NUM);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
TEST_CASE_MULTIPLE_DEVICES("I2C master read slave test", "[i2c][test_env=UT_T2_I2C][timeout=150]", master_read_slave_test, slave_write_buffer_test);
|
|
||||||
|
|
||||||
static void i2c_master_write_read_test(void)
|
|
||||||
{
|
|
||||||
uint8_t *data_rd = (uint8_t *) malloc(DATA_LENGTH);
|
|
||||||
memset(data_rd, 0, DATA_LENGTH);
|
|
||||||
uint8_t *data_wr = (uint8_t *) malloc(DATA_LENGTH);
|
|
||||||
|
|
||||||
i2c_config_t conf_master = i2c_master_init();
|
|
||||||
TEST_ESP_OK(i2c_param_config(I2C_MASTER_NUM, &conf_master));
|
|
||||||
TEST_ESP_OK(i2c_driver_install(I2C_MASTER_NUM, I2C_MODE_MASTER,
|
|
||||||
I2C_MASTER_RX_BUF_DISABLE,
|
|
||||||
I2C_MASTER_TX_BUF_DISABLE, 0));
|
|
||||||
unity_wait_for_signal("i2c slave init finish");
|
|
||||||
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
|
||||||
i2c_master_start(cmd);
|
|
||||||
i2c_master_write_byte(cmd, ( ESP_SLAVE_ADDR << 1 ) | READ_BIT, ACK_CHECK_EN);
|
|
||||||
|
|
||||||
unity_send_signal("slave write");
|
|
||||||
unity_wait_for_signal("master read and write");
|
|
||||||
i2c_master_read(cmd, data_rd, RW_TEST_LENGTH, ACK_VAL);
|
|
||||||
i2c_master_read_byte(cmd, data_rd + RW_TEST_LENGTH, NACK_VAL);
|
|
||||||
i2c_master_stop(cmd);
|
|
||||||
i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 5000 / portTICK_RATE_MS);
|
|
||||||
i2c_cmd_link_delete(cmd);
|
|
||||||
vTaskDelay(100 / portTICK_RATE_MS);
|
|
||||||
disp_buf(data_rd, RW_TEST_LENGTH);
|
|
||||||
for (int i = 0; i < RW_TEST_LENGTH; i++) {
|
|
||||||
TEST_ASSERT(data_rd[i] == i/2);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < DATA_LENGTH; i++) {
|
|
||||||
data_wr[i] = i % 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
vTaskDelay(100 / portTICK_RATE_MS);
|
|
||||||
i2c_master_write_slave(I2C_MASTER_NUM, data_wr, RW_TEST_LENGTH);
|
|
||||||
free(data_wr);
|
|
||||||
free(data_rd);
|
|
||||||
unity_send_signal("slave read");
|
|
||||||
unity_wait_for_signal("ready to delete");
|
|
||||||
i2c_driver_delete(I2C_MASTER_NUM);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void i2c_slave_read_write_test(void)
|
|
||||||
{
|
|
||||||
uint8_t *data_rd = (uint8_t *) malloc(DATA_LENGTH);
|
|
||||||
memset(data_rd, 0, DATA_LENGTH);
|
|
||||||
uint8_t *data_wr = (uint8_t *) malloc(DATA_LENGTH);
|
|
||||||
int size_rd;
|
|
||||||
|
|
||||||
i2c_config_t conf_slave = i2c_slave_init();
|
|
||||||
TEST_ESP_OK(i2c_param_config( I2C_SLAVE_NUM, &conf_slave));
|
|
||||||
TEST_ESP_OK(i2c_driver_install(I2C_SLAVE_NUM, I2C_MODE_SLAVE,
|
|
||||||
I2C_SLAVE_RX_BUF_LEN,
|
|
||||||
I2C_SLAVE_TX_BUF_LEN, 0));
|
|
||||||
unity_send_signal("i2c slave init finish");
|
|
||||||
unity_wait_for_signal("slave write");
|
|
||||||
|
|
||||||
for (int i = 0; i < DATA_LENGTH / 2; i++) {
|
|
||||||
data_wr[i] = i/2;
|
|
||||||
}
|
|
||||||
size_rd = i2c_slave_write_buffer(I2C_SLAVE_NUM, data_wr, RW_TEST_LENGTH, 2000 / portTICK_RATE_MS);
|
|
||||||
disp_buf(data_wr, size_rd);
|
|
||||||
unity_send_signal("master read and write");
|
|
||||||
unity_wait_for_signal("slave read");
|
|
||||||
size_rd = i2c_slave_read_buffer( I2C_SLAVE_NUM, data_rd, RW_TEST_LENGTH, 1000 / portTICK_RATE_MS);
|
|
||||||
printf("slave read data is:\n");
|
|
||||||
disp_buf(data_rd, size_rd);
|
|
||||||
for (int i = 0; i < RW_TEST_LENGTH; i++) {
|
|
||||||
TEST_ASSERT(data_rd[i] == i % 3);
|
|
||||||
}
|
|
||||||
free(data_wr);
|
|
||||||
free(data_rd);
|
|
||||||
unity_send_signal("ready to delete");
|
|
||||||
i2c_driver_delete(I2C_SLAVE_NUM);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE_MULTIPLE_DEVICES("I2C read and write test", "[i2c][test_env=UT_T2_I2C][timeout=150]", i2c_master_write_read_test, i2c_slave_read_write_test);
|
|
||||||
|
|
||||||
static void i2c_master_repeat_write(void)
|
|
||||||
{
|
|
||||||
uint8_t *data_wr = (uint8_t *) malloc(DATA_LENGTH);
|
|
||||||
int times = 3;
|
|
||||||
|
|
||||||
i2c_config_t conf_master = i2c_master_init();
|
|
||||||
TEST_ESP_OK(i2c_param_config(I2C_MASTER_NUM, &conf_master));
|
|
||||||
|
|
||||||
TEST_ESP_OK(i2c_driver_install(I2C_MASTER_NUM, I2C_MODE_MASTER,
|
|
||||||
I2C_MASTER_RX_BUF_DISABLE,
|
|
||||||
I2C_MASTER_TX_BUF_DISABLE, 0));
|
|
||||||
unity_wait_for_signal("i2c slave init finish");
|
|
||||||
|
|
||||||
for (int j = 0; j < times; j++) {
|
|
||||||
for (int i = 0; i < DATA_LENGTH; i++) {
|
|
||||||
data_wr[i] = j + i;
|
|
||||||
}
|
|
||||||
i2c_master_write_slave(I2C_MASTER_NUM, data_wr, RW_TEST_LENGTH);
|
|
||||||
disp_buf(data_wr, RW_TEST_LENGTH);
|
|
||||||
}
|
|
||||||
free(data_wr);
|
|
||||||
unity_send_signal("master write");
|
|
||||||
unity_wait_for_signal("ready to delete");
|
|
||||||
i2c_driver_delete(I2C_MASTER_NUM);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void i2c_slave_repeat_read(void)
|
|
||||||
{
|
|
||||||
int size_rd = 0;
|
|
||||||
int times = 3;
|
|
||||||
uint8_t *data_rd = (uint8_t *) malloc(DATA_LENGTH * 3);
|
|
||||||
|
|
||||||
i2c_config_t conf_slave = i2c_slave_init();
|
|
||||||
TEST_ESP_OK(i2c_param_config( I2C_SLAVE_NUM, &conf_slave));
|
|
||||||
TEST_ESP_OK(i2c_driver_install(I2C_SLAVE_NUM, I2C_MODE_SLAVE,
|
|
||||||
I2C_SLAVE_RX_BUF_LEN,
|
|
||||||
I2C_SLAVE_TX_BUF_LEN, 0));
|
|
||||||
unity_send_signal("i2c slave init finish");
|
|
||||||
unity_wait_for_signal("master write");
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
int len = i2c_slave_read_buffer( I2C_SLAVE_NUM, data_rd + size_rd, RW_TEST_LENGTH * 3, 10000 / portTICK_RATE_MS);
|
|
||||||
if (len == 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
size_rd += len;
|
|
||||||
}
|
|
||||||
disp_buf(data_rd, size_rd);
|
|
||||||
for (int j = 0; j < times; j++) {
|
|
||||||
for (int i = 0; i < RW_TEST_LENGTH; i++) {
|
|
||||||
printf("data: %d, %d\n", data_rd[j * RW_TEST_LENGTH + i], (i % 129 + j));
|
|
||||||
TEST_ASSERT(data_rd[j * RW_TEST_LENGTH + i] == (i % 129 + j));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
free(data_rd);
|
|
||||||
unity_send_signal("ready to delete");
|
|
||||||
i2c_driver_delete(I2C_SLAVE_NUM);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE_MULTIPLE_DEVICES("I2C repeat write test", "[i2c][test_env=UT_T2_I2C][timeout=150]", i2c_master_repeat_write, i2c_slave_repeat_read);
|
|
||||||
|
|
||||||
static volatile bool exit_flag;
|
static volatile bool exit_flag;
|
||||||
static bool test_read_func;
|
static bool test_read_func;
|
||||||
|
|
||||||
|
|
|
@ -429,551 +429,3 @@ static spitest_param_set_t mode_pgroup[] = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
TEST_SPI_LOCAL(MODE, mode_pgroup)
|
TEST_SPI_LOCAL(MODE, mode_pgroup)
|
||||||
|
|
||||||
/********************************************************************************
|
|
||||||
* Test By Master & Slave (2 boards)
|
|
||||||
*
|
|
||||||
* Wiring:
|
|
||||||
* | Master | Slave |
|
|
||||||
* | ------ | ----- |
|
|
||||||
* | 12 | 19 |
|
|
||||||
* | 13 | 23 |
|
|
||||||
* | 14 | 18 |
|
|
||||||
* | 15 | 5 |
|
|
||||||
* | GND | GND |
|
|
||||||
*
|
|
||||||
********************************************************************************/
|
|
||||||
static void test_master_init(void** context);
|
|
||||||
static void test_master_deinit(void* context);
|
|
||||||
static void test_master_loop(const void *test_cfg, void* context);
|
|
||||||
|
|
||||||
static const ptest_func_t master_test_func = {
|
|
||||||
.pre_test = test_master_init,
|
|
||||||
.post_test = test_master_deinit,
|
|
||||||
.loop = test_master_loop,
|
|
||||||
.def_param = spitest_def_param,
|
|
||||||
};
|
|
||||||
|
|
||||||
static void test_slave_init(void** context);
|
|
||||||
static void test_slave_deinit(void* context);
|
|
||||||
static void test_slave_loop(const void *test_cfg, void* context);
|
|
||||||
|
|
||||||
static const ptest_func_t slave_test_func = {
|
|
||||||
.pre_test = test_slave_init,
|
|
||||||
.post_test = test_slave_deinit,
|
|
||||||
.loop = test_slave_loop,
|
|
||||||
.def_param = spitest_def_param,
|
|
||||||
};
|
|
||||||
|
|
||||||
#define TEST_SPI_MASTER_SLAVE(name, param_group, extra_tag) \
|
|
||||||
PARAM_GROUP_DECLARE(name, param_group) \
|
|
||||||
TEST_MASTER_SLAVE(name, param_group, "[spi_ms][test_env=Example_SPI_Multi_device][timeout=120]"#extra_tag, &master_test_func, &slave_test_func)
|
|
||||||
|
|
||||||
/************ Master Code ***********************************************/
|
|
||||||
static void test_master_init(void** arg)
|
|
||||||
{
|
|
||||||
TEST_ASSERT(*arg==NULL);
|
|
||||||
*arg = malloc(sizeof(spitest_context_t));
|
|
||||||
spitest_context_t* context = *arg;
|
|
||||||
TEST_ASSERT(context!=NULL);
|
|
||||||
context->slave_context = (spi_slave_task_context_t){};
|
|
||||||
esp_err_t err = init_slave_context(&context->slave_context);
|
|
||||||
TEST_ASSERT(err == ESP_OK);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_master_deinit(void* arg)
|
|
||||||
{
|
|
||||||
spitest_context_t* context = (spitest_context_t*)arg;
|
|
||||||
deinit_slave_context(&context->slave_context);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_master_start(spi_device_handle_t *spi, int freq, const spitest_param_set_t* pset, spitest_context_t* context)
|
|
||||||
{
|
|
||||||
//master config
|
|
||||||
spi_bus_config_t buspset=SPI_BUS_TEST_DEFAULT_CONFIG();
|
|
||||||
buspset.miso_io_num = spi_periph_signal[HSPI_HOST].spiq_iomux_pin;
|
|
||||||
buspset.mosi_io_num = spi_periph_signal[HSPI_HOST].spid_iomux_pin;
|
|
||||||
buspset.sclk_io_num = spi_periph_signal[HSPI_HOST].spiclk_iomux_pin;
|
|
||||||
//this does nothing, but avoid the driver from using native pins
|
|
||||||
if (!pset->master_iomux) buspset.quadhd_io_num = spi_periph_signal[VSPI_HOST].spiq_iomux_pin;
|
|
||||||
spi_device_interface_config_t devpset=SPI_DEVICE_TEST_DEFAULT_CONFIG();
|
|
||||||
devpset.spics_io_num = spi_periph_signal[HSPI_HOST].spics0_iomux_pin;
|
|
||||||
devpset.mode = pset->mode;
|
|
||||||
const int cs_pretrans_max = 15;
|
|
||||||
if (pset->dup==HALF_DUPLEX_MISO) {
|
|
||||||
devpset.cs_ena_pretrans = cs_pretrans_max;
|
|
||||||
devpset.flags |= SPI_DEVICE_HALFDUPLEX;
|
|
||||||
} else if (pset->dup == HALF_DUPLEX_MOSI) {
|
|
||||||
devpset.cs_ena_pretrans = cs_pretrans_max;
|
|
||||||
devpset.flags |= SPI_DEVICE_NO_DUMMY;
|
|
||||||
} else {
|
|
||||||
devpset.cs_ena_pretrans = cs_pretrans_max;//20;
|
|
||||||
}
|
|
||||||
const int cs_posttrans_max = 15;
|
|
||||||
devpset.cs_ena_posttrans = cs_posttrans_max;
|
|
||||||
devpset.input_delay_ns = pset->slave_tv_ns;
|
|
||||||
devpset.clock_speed_hz = freq;
|
|
||||||
if (pset->master_limit != 0 && freq > pset->master_limit) devpset.flags |= SPI_DEVICE_NO_DUMMY;
|
|
||||||
TEST_ESP_OK(spi_bus_initialize(TEST_SPI_HOST, &buspset, pset->master_dma_chan));
|
|
||||||
TEST_ESP_OK(spi_bus_add_device(TEST_SPI_HOST, &devpset, spi));
|
|
||||||
|
|
||||||
//prepare data for the slave
|
|
||||||
for (int i = 0; i < pset->test_size; i ++) {
|
|
||||||
/* in the single board, the data is send to the slave task, then to the driver.
|
|
||||||
* However, in this test we don't know the data received by the slave.
|
|
||||||
* So we send to the return queue of the slave directly.
|
|
||||||
*/
|
|
||||||
//xQueueSend( slave_context.data_to_send, &slave_txdata[i], portMAX_DELAY );
|
|
||||||
|
|
||||||
uint8_t slave_buffer[320+8];
|
|
||||||
int length;
|
|
||||||
if (pset->dup!=HALF_DUPLEX_MISO) {
|
|
||||||
length = context->master_trans[i].length;
|
|
||||||
} else {
|
|
||||||
length = context->master_trans[i].rxlength;
|
|
||||||
}
|
|
||||||
uint32_t* ptr = (uint32_t*)slave_buffer;
|
|
||||||
ptr[0] = length;
|
|
||||||
ptr[1] = (uint32_t)context->slave_trans[i].start;
|
|
||||||
if (context->master_trans[i].tx_buffer!=NULL) {
|
|
||||||
memcpy(ptr+2, context->master_trans[i].tx_buffer, (context->master_trans[i].length+7)/8);
|
|
||||||
}
|
|
||||||
//Send to return queue directly
|
|
||||||
xRingbufferSend(context->slave_context.data_received, slave_buffer, 8+(length+7)/8, portMAX_DELAY);
|
|
||||||
}
|
|
||||||
memset(context->master_rxbuf, 0x66, sizeof(context->master_rxbuf));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_master_loop(const void *arg1, void* arg2)
|
|
||||||
{
|
|
||||||
const spitest_param_set_t *test_cfg = (spitest_param_set_t*)arg1;
|
|
||||||
spitest_context_t* context = (spitest_context_t*)arg2;
|
|
||||||
spi_device_handle_t spi;
|
|
||||||
spitest_init_transactions(test_cfg, context);
|
|
||||||
const int *timing_speed_array = test_cfg->freq_list;
|
|
||||||
|
|
||||||
ESP_LOGI(MASTER_TAG, "****************** %s ***************", test_cfg->pset_name);
|
|
||||||
for (int i=0; ; i++ ) {
|
|
||||||
const int freq = timing_speed_array[i];
|
|
||||||
if (freq==0) break;
|
|
||||||
if (test_cfg->freq_limit && freq > test_cfg->freq_limit) break;
|
|
||||||
|
|
||||||
ESP_LOGI(MASTER_TAG, "==============> %dk", freq/1000);
|
|
||||||
test_master_start(&spi, freq, test_cfg, context);
|
|
||||||
|
|
||||||
unity_wait_for_signal("slave ready");
|
|
||||||
|
|
||||||
for( int j= 0; j < test_cfg->test_size; j ++ ) {
|
|
||||||
//wait for both master and slave end
|
|
||||||
ESP_LOGI( MASTER_TAG, "=> test%d", j );
|
|
||||||
//send master tx data
|
|
||||||
vTaskDelay(20);
|
|
||||||
|
|
||||||
spi_transaction_t *t = &context->master_trans[j];
|
|
||||||
TEST_ESP_OK (spi_device_transmit(spi, t) );
|
|
||||||
int len = get_trans_len(test_cfg->dup, t);
|
|
||||||
spitest_master_print_data(t, len);
|
|
||||||
|
|
||||||
size_t rcv_len;
|
|
||||||
slave_rxdata_t *rcv_data = xRingbufferReceive( context->slave_context.data_received, &rcv_len, portMAX_DELAY );
|
|
||||||
spitest_slave_print_data(rcv_data, false);
|
|
||||||
|
|
||||||
//check result
|
|
||||||
bool check_master_data = (test_cfg->dup != HALF_DUPLEX_MOSI &&
|
|
||||||
(test_cfg->master_limit == 0 || freq <= test_cfg->master_limit));
|
|
||||||
const bool check_slave_data = false;
|
|
||||||
const bool check_len = false;
|
|
||||||
if (!check_master_data) {
|
|
||||||
ESP_LOGI(MASTER_TAG, "skip data check due to duplex mode or freq.");
|
|
||||||
} else {
|
|
||||||
TEST_ESP_OK(spitest_check_data(len, t, rcv_data, check_master_data,
|
|
||||||
check_len, check_slave_data));
|
|
||||||
}
|
|
||||||
//clean
|
|
||||||
vRingbufferReturnItem( context->slave_context.data_received, rcv_data );
|
|
||||||
}
|
|
||||||
master_free_device_bus(spi);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/************ Slave Code ***********************************************/
|
|
||||||
static void test_slave_init(void** arg)
|
|
||||||
{
|
|
||||||
TEST_ASSERT(*arg==NULL);
|
|
||||||
*arg = malloc(sizeof(spitest_context_t));
|
|
||||||
spitest_context_t* context = (spitest_context_t*)*arg;
|
|
||||||
TEST_ASSERT(context!=NULL);
|
|
||||||
context->slave_context = (spi_slave_task_context_t){};
|
|
||||||
esp_err_t err = init_slave_context( &context->slave_context );
|
|
||||||
TEST_ASSERT( err == ESP_OK );
|
|
||||||
|
|
||||||
xTaskCreate( spitest_slave_task, "spi_slave", 4096, &context->slave_context, 0, &context->handle_slave);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_slave_deinit(void* arg)
|
|
||||||
{
|
|
||||||
spitest_context_t* context = (spitest_context_t*)arg;
|
|
||||||
vTaskDelete( context->handle_slave );
|
|
||||||
context->handle_slave = 0;
|
|
||||||
|
|
||||||
deinit_slave_context(&context->slave_context);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void timing_slave_start(int speed, const spitest_param_set_t* pset, spitest_context_t *context)
|
|
||||||
{
|
|
||||||
//slave config
|
|
||||||
spi_bus_config_t slv_buscfg=SPI_BUS_TEST_DEFAULT_CONFIG();
|
|
||||||
slv_buscfg.miso_io_num = spi_periph_signal[VSPI_HOST].spiq_iomux_pin;
|
|
||||||
slv_buscfg.mosi_io_num = spi_periph_signal[VSPI_HOST].spid_iomux_pin;
|
|
||||||
slv_buscfg.sclk_io_num = spi_periph_signal[VSPI_HOST].spiclk_iomux_pin;
|
|
||||||
//this does nothing, but avoid the driver from using native pins
|
|
||||||
if (!pset->slave_iomux) slv_buscfg.quadhd_io_num = spi_periph_signal[HSPI_HOST].spiclk_iomux_pin;
|
|
||||||
spi_slave_interface_config_t slvcfg=SPI_SLAVE_TEST_DEFAULT_CONFIG();
|
|
||||||
slvcfg.spics_io_num = spi_periph_signal[VSPI_HOST].spics0_iomux_pin;
|
|
||||||
slvcfg.mode = pset->mode;
|
|
||||||
//Enable pull-ups on SPI lines so we don't detect rogue pulses when no master is connected.
|
|
||||||
slave_pull_up(&slv_buscfg, slvcfg.spics_io_num);
|
|
||||||
|
|
||||||
TEST_ESP_OK(spi_slave_initialize(TEST_SLAVE_HOST, &slv_buscfg, &slvcfg, pset->slave_dma_chan));
|
|
||||||
|
|
||||||
//prepare data for the master
|
|
||||||
for (int i = 0; i < pset->test_size; i++) {
|
|
||||||
if (pset->dup==FULL_DUPLEX) {
|
|
||||||
memcpy(context->master_trans[i].rx_buffer, context->slave_trans[i].start, (context->master_trans[i].length+7)/8);
|
|
||||||
} else if (pset->dup==HALF_DUPLEX_MISO) {
|
|
||||||
memcpy(context->master_trans[i].rx_buffer, context->slave_trans[i].start, (context->master_trans[i].rxlength+7)/8);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_slave_loop(const void *arg1, void* arg2)
|
|
||||||
{
|
|
||||||
const spitest_param_set_t *pset = (spitest_param_set_t*)arg1;
|
|
||||||
spitest_context_t* context = (spitest_context_t*)arg2;
|
|
||||||
ESP_LOGI(SLAVE_TAG, "****************** %s ***************", pset->pset_name);
|
|
||||||
spitest_init_transactions(pset, context);
|
|
||||||
|
|
||||||
const int *timing_speed_array = pset->freq_list;
|
|
||||||
for (int i=0; ; i++ ) {
|
|
||||||
const int freq = timing_speed_array[i];
|
|
||||||
if (freq==0) break;
|
|
||||||
if (pset->freq_limit != 0 && freq > pset->freq_limit) break;
|
|
||||||
|
|
||||||
ESP_LOGI(MASTER_TAG, "==============> %dk", timing_speed_array[i]/1000);
|
|
||||||
//Initialize SPI slave interface
|
|
||||||
timing_slave_start(freq, pset, context);
|
|
||||||
|
|
||||||
//prepare slave tx data
|
|
||||||
for (int i = 0; i < pset->test_size; i ++) {
|
|
||||||
xQueueSend( context->slave_context.data_to_send, &context->slave_trans[i], portMAX_DELAY );
|
|
||||||
//memcpy(context->master_trans[i].rx_buffer, context->slave_trans[i].start, (context->master_trans[i].length+7)/8);
|
|
||||||
}
|
|
||||||
|
|
||||||
vTaskDelay(50/portTICK_PERIOD_MS);
|
|
||||||
unity_send_signal("slave ready");
|
|
||||||
|
|
||||||
for( int i= 0; i < pset->test_size; i ++ ) {
|
|
||||||
//wait for both master and slave end
|
|
||||||
ESP_LOGI( MASTER_TAG, "===== test%d =====", i );
|
|
||||||
//send master tx data
|
|
||||||
vTaskDelay(20);
|
|
||||||
|
|
||||||
spi_transaction_t *t = &context->master_trans[i];
|
|
||||||
int len = get_trans_len(pset->dup, t);
|
|
||||||
spitest_master_print_data(t, FULL_DUPLEX);
|
|
||||||
|
|
||||||
size_t rcv_len;
|
|
||||||
slave_rxdata_t *rcv_data = xRingbufferReceive( context->slave_context.data_received, &rcv_len, portMAX_DELAY );
|
|
||||||
spitest_slave_print_data(rcv_data, true);
|
|
||||||
|
|
||||||
//check result
|
|
||||||
const bool check_master_data = false;
|
|
||||||
bool check_slave_data = (pset->dup!=HALF_DUPLEX_MISO);
|
|
||||||
const bool check_len = true;
|
|
||||||
TEST_ESP_OK(spitest_check_data(len, t, rcv_data, check_master_data, check_len, check_slave_data));
|
|
||||||
//clean
|
|
||||||
vRingbufferReturnItem( context->slave_context.data_received, rcv_data );
|
|
||||||
}
|
|
||||||
TEST_ASSERT(spi_slave_free(TEST_SLAVE_HOST) == ESP_OK);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/************ Timing Test ***********************************************/
|
|
||||||
static spitest_param_set_t timing_conf[] = {
|
|
||||||
{ .pset_name = "FULL_DUP, BOTH IOMUX",
|
|
||||||
.freq_limit = ESP_SPI_SLAVE_MAX_FREQ,
|
|
||||||
.master_limit = SPI_MASTER_FREQ_16M,
|
|
||||||
.dup = FULL_DUPLEX,
|
|
||||||
.master_iomux= true,
|
|
||||||
.slave_iomux = true,
|
|
||||||
.slave_tv_ns = TV_WITH_ESP_SLAVE,
|
|
||||||
},
|
|
||||||
{ .pset_name = "FULL_DUP, MASTER IOMUX",
|
|
||||||
.freq_limit = ESP_SPI_SLAVE_MAX_FREQ,
|
|
||||||
.master_limit = SPI_MASTER_FREQ_11M,
|
|
||||||
.dup = FULL_DUPLEX,
|
|
||||||
.master_iomux = true,
|
|
||||||
.slave_iomux = false,
|
|
||||||
.slave_tv_ns = TV_WITH_ESP_SLAVE_GPIO,
|
|
||||||
},
|
|
||||||
{ .pset_name = "FULL_DUP, SLAVE IOMUX",
|
|
||||||
.freq_limit = ESP_SPI_SLAVE_MAX_FREQ,
|
|
||||||
.master_limit = SPI_MASTER_FREQ_11M,
|
|
||||||
.dup = FULL_DUPLEX,
|
|
||||||
.master_iomux = false,
|
|
||||||
.slave_iomux = true,
|
|
||||||
.slave_tv_ns = TV_WITH_ESP_SLAVE,
|
|
||||||
},
|
|
||||||
{ .pset_name = "FULL_DUP, BOTH GPIO",
|
|
||||||
.freq_limit = ESP_SPI_SLAVE_MAX_FREQ,
|
|
||||||
.master_limit = SPI_MASTER_FREQ_9M,
|
|
||||||
.dup = FULL_DUPLEX,
|
|
||||||
.master_iomux = false,
|
|
||||||
.slave_iomux = false,
|
|
||||||
.slave_tv_ns = TV_WITH_ESP_SLAVE_GPIO,
|
|
||||||
},
|
|
||||||
{ .pset_name = "MOSI_DUP, BOTH IOMUX",
|
|
||||||
.freq_limit = ESP_SPI_SLAVE_MAX_FREQ,
|
|
||||||
.dup = HALF_DUPLEX_MOSI,
|
|
||||||
.master_iomux= true,
|
|
||||||
.slave_iomux = true,
|
|
||||||
.slave_tv_ns = TV_WITH_ESP_SLAVE,
|
|
||||||
},
|
|
||||||
{ .pset_name = "MOSI_DUP, MASTER IOMUX",
|
|
||||||
.freq_limit = ESP_SPI_SLAVE_MAX_FREQ,
|
|
||||||
.dup = HALF_DUPLEX_MOSI,
|
|
||||||
.master_iomux= true,
|
|
||||||
.slave_iomux = false,
|
|
||||||
.slave_tv_ns = TV_WITH_ESP_SLAVE_GPIO,
|
|
||||||
},
|
|
||||||
{ .pset_name = "MOSI_DUP, SLAVE IOMUX",
|
|
||||||
.freq_limit = ESP_SPI_SLAVE_MAX_FREQ,
|
|
||||||
.dup = HALF_DUPLEX_MOSI,
|
|
||||||
.master_iomux= false,
|
|
||||||
.slave_iomux = true,
|
|
||||||
.slave_tv_ns = TV_WITH_ESP_SLAVE,
|
|
||||||
},
|
|
||||||
{ .pset_name = "MOSI_DUP, BOTH GPIO",
|
|
||||||
.freq_limit = ESP_SPI_SLAVE_MAX_FREQ,
|
|
||||||
.dup = HALF_DUPLEX_MOSI,
|
|
||||||
.master_iomux= false,
|
|
||||||
.slave_iomux = false,
|
|
||||||
.slave_tv_ns = TV_WITH_ESP_SLAVE_GPIO,
|
|
||||||
},
|
|
||||||
{ .pset_name = "MISO_DUP, BOTH IOMUX",
|
|
||||||
.freq_limit = ESP_SPI_SLAVE_MAX_FREQ,
|
|
||||||
.dup = HALF_DUPLEX_MISO,
|
|
||||||
.master_iomux = true,
|
|
||||||
.slave_iomux = true,
|
|
||||||
.slave_tv_ns = TV_WITH_ESP_SLAVE,
|
|
||||||
},
|
|
||||||
{ .pset_name = "MISO_DUP, MASTER IOMUX",
|
|
||||||
.freq_limit = ESP_SPI_SLAVE_MAX_FREQ,
|
|
||||||
.dup = HALF_DUPLEX_MISO,
|
|
||||||
.master_iomux = true,
|
|
||||||
.slave_iomux = false,
|
|
||||||
.slave_tv_ns = TV_WITH_ESP_SLAVE_GPIO,
|
|
||||||
},
|
|
||||||
{ .pset_name = "MISO_DUP, SLAVE IOMUX",
|
|
||||||
.freq_limit = ESP_SPI_SLAVE_MAX_FREQ,
|
|
||||||
.dup = HALF_DUPLEX_MISO,
|
|
||||||
.master_iomux = false,
|
|
||||||
.slave_iomux = true,
|
|
||||||
.slave_tv_ns = TV_WITH_ESP_SLAVE,
|
|
||||||
},
|
|
||||||
{ .pset_name = "MISO_DUP, BOTH GPIO",
|
|
||||||
.freq_limit = ESP_SPI_SLAVE_MAX_FREQ,
|
|
||||||
.dup = HALF_DUPLEX_MISO,
|
|
||||||
.master_iomux = false,
|
|
||||||
.slave_iomux = false,
|
|
||||||
.slave_tv_ns = TV_WITH_ESP_SLAVE_GPIO,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
TEST_SPI_MASTER_SLAVE(TIMING, timing_conf, "")
|
|
||||||
|
|
||||||
/************ Mode Test ***********************************************/
|
|
||||||
#define FREQ_LIMIT_MODE SPI_MASTER_FREQ_16M
|
|
||||||
//Set to this input delay so that the master will read with delay until 7M
|
|
||||||
#define DELAY_HCLK_UNTIL_7M 12.5*3
|
|
||||||
|
|
||||||
static int test_freq_mode_ms[]={
|
|
||||||
100*1000,
|
|
||||||
6*1000*1000,
|
|
||||||
7*1000*1000,
|
|
||||||
SPI_MASTER_FREQ_8M, //maximum freq MISO stable before next latch edge
|
|
||||||
SPI_MASTER_FREQ_9M, //maximum freq MISO stable before next latch edge
|
|
||||||
SPI_MASTER_FREQ_10M,
|
|
||||||
SPI_MASTER_FREQ_11M,
|
|
||||||
SPI_MASTER_FREQ_13M,
|
|
||||||
SPI_MASTER_FREQ_16M,
|
|
||||||
SPI_MASTER_FREQ_20M,
|
|
||||||
0,
|
|
||||||
};
|
|
||||||
static int test_freq_20M_only[]={
|
|
||||||
SPI_MASTER_FREQ_20M,
|
|
||||||
0,
|
|
||||||
};
|
|
||||||
|
|
||||||
spitest_param_set_t mode_conf[] = {
|
|
||||||
//non-DMA tests
|
|
||||||
{ .pset_name = "mode 0, no DMA",
|
|
||||||
.freq_list = test_freq_mode_ms,
|
|
||||||
.master_limit = FREQ_LIMIT_MODE,
|
|
||||||
.dup = FULL_DUPLEX,
|
|
||||||
.master_iomux= true,
|
|
||||||
.slave_iomux = true,
|
|
||||||
.slave_tv_ns = TV_WITH_ESP_SLAVE,
|
|
||||||
.mode = 0,
|
|
||||||
},
|
|
||||||
{ .pset_name = "mode 1, no DMA",
|
|
||||||
.freq_list = test_freq_mode_ms,
|
|
||||||
.master_limit = FREQ_LIMIT_MODE,
|
|
||||||
.dup = FULL_DUPLEX,
|
|
||||||
.master_iomux= true,
|
|
||||||
.slave_iomux = true,
|
|
||||||
.slave_tv_ns = TV_WITH_ESP_SLAVE,
|
|
||||||
.mode = 1,
|
|
||||||
},
|
|
||||||
{ .pset_name = "mode 2, no DMA",
|
|
||||||
.freq_list = test_freq_mode_ms,
|
|
||||||
.master_limit = FREQ_LIMIT_MODE,
|
|
||||||
.dup = FULL_DUPLEX,
|
|
||||||
.master_iomux= true,
|
|
||||||
.slave_iomux = true,
|
|
||||||
.slave_tv_ns = TV_WITH_ESP_SLAVE,
|
|
||||||
.mode = 2,
|
|
||||||
},
|
|
||||||
{ .pset_name = "mode 3, no DMA",
|
|
||||||
.freq_list = test_freq_mode_ms,
|
|
||||||
.master_limit = FREQ_LIMIT_MODE,
|
|
||||||
.dup = FULL_DUPLEX,
|
|
||||||
.master_iomux= true,
|
|
||||||
.slave_iomux = true,
|
|
||||||
.slave_tv_ns = TV_WITH_ESP_SLAVE,
|
|
||||||
.mode = 3,
|
|
||||||
},
|
|
||||||
//the master can only read to 16MHz, use half-duplex mode to read at 20.
|
|
||||||
{ .pset_name = "mode 0, no DMA, 20M",
|
|
||||||
.freq_list = test_freq_20M_only,
|
|
||||||
.dup = HALF_DUPLEX_MISO,
|
|
||||||
.master_iomux= true,
|
|
||||||
.slave_iomux = true,
|
|
||||||
.slave_tv_ns = TV_WITH_ESP_SLAVE,
|
|
||||||
.mode = 0,
|
|
||||||
},
|
|
||||||
{ .pset_name = "mode 1, no DMA, 20M",
|
|
||||||
.freq_list = test_freq_20M_only,
|
|
||||||
.dup = HALF_DUPLEX_MISO,
|
|
||||||
.master_iomux= true,
|
|
||||||
.slave_iomux = true,
|
|
||||||
.slave_tv_ns = TV_WITH_ESP_SLAVE,
|
|
||||||
.mode = 1,
|
|
||||||
},
|
|
||||||
{ .pset_name = "mode 2, no DMA, 20M",
|
|
||||||
.freq_list = test_freq_20M_only,
|
|
||||||
.dup = HALF_DUPLEX_MISO,
|
|
||||||
.master_iomux= true,
|
|
||||||
.slave_iomux = true,
|
|
||||||
.slave_tv_ns = TV_WITH_ESP_SLAVE,
|
|
||||||
.mode = 2,
|
|
||||||
},
|
|
||||||
{ .pset_name = "mode 3, no DMA, 20M",
|
|
||||||
.freq_list = test_freq_20M_only,
|
|
||||||
.dup = HALF_DUPLEX_MISO,
|
|
||||||
.master_iomux= true,
|
|
||||||
.slave_iomux = true,
|
|
||||||
.slave_tv_ns = TV_WITH_ESP_SLAVE,
|
|
||||||
.mode = 3,
|
|
||||||
},
|
|
||||||
//DMA tests
|
|
||||||
{ .pset_name = "mode 0, DMA",
|
|
||||||
.freq_list = test_freq_mode_ms,
|
|
||||||
.master_limit = FREQ_LIMIT_MODE,
|
|
||||||
.dup = FULL_DUPLEX,
|
|
||||||
.master_iomux= true,
|
|
||||||
.slave_iomux = true,
|
|
||||||
.slave_tv_ns = DELAY_HCLK_UNTIL_7M,
|
|
||||||
.mode = 0,
|
|
||||||
.master_dma_chan = 1,
|
|
||||||
.slave_dma_chan = 1,
|
|
||||||
.length_aligned = true,
|
|
||||||
},
|
|
||||||
{ .pset_name = "mode 1, DMA",
|
|
||||||
.freq_list = test_freq_mode_ms,
|
|
||||||
.master_limit = FREQ_LIMIT_MODE,
|
|
||||||
.dup = FULL_DUPLEX,
|
|
||||||
.master_iomux= true,
|
|
||||||
.slave_iomux = true,
|
|
||||||
.slave_tv_ns = TV_WITH_ESP_SLAVE,
|
|
||||||
.mode = 1,
|
|
||||||
.master_dma_chan = 1,
|
|
||||||
.slave_dma_chan = 1,
|
|
||||||
.length_aligned = true,
|
|
||||||
},
|
|
||||||
{ .pset_name = "mode 2, DMA",
|
|
||||||
.freq_list = test_freq_mode_ms,
|
|
||||||
.master_limit = FREQ_LIMIT_MODE,
|
|
||||||
.dup = FULL_DUPLEX,
|
|
||||||
.master_iomux= true,
|
|
||||||
.slave_iomux = true,
|
|
||||||
.slave_tv_ns = DELAY_HCLK_UNTIL_7M,
|
|
||||||
.mode = 2,
|
|
||||||
.master_dma_chan = 1,
|
|
||||||
.slave_dma_chan = 1,
|
|
||||||
.length_aligned = true,
|
|
||||||
},
|
|
||||||
{ .pset_name = "mode 3, DMA",
|
|
||||||
.freq_list = test_freq_mode_ms,
|
|
||||||
.master_limit = FREQ_LIMIT_MODE,
|
|
||||||
.dup = FULL_DUPLEX,
|
|
||||||
.master_iomux= true,
|
|
||||||
.slave_iomux = true,
|
|
||||||
.slave_tv_ns = TV_WITH_ESP_SLAVE,
|
|
||||||
.mode = 3,
|
|
||||||
.master_dma_chan = 1,
|
|
||||||
.slave_dma_chan = 1,
|
|
||||||
.length_aligned = true,
|
|
||||||
},
|
|
||||||
//the master can only read to 16MHz, use half-duplex mode to read at 20.
|
|
||||||
{ .pset_name = "mode 0, DMA, 20M",
|
|
||||||
.freq_list = test_freq_20M_only,
|
|
||||||
.dup = HALF_DUPLEX_MISO,
|
|
||||||
.master_iomux= true,
|
|
||||||
.slave_iomux = true,
|
|
||||||
.slave_tv_ns = TV_WITH_ESP_SLAVE,
|
|
||||||
.mode = 0,
|
|
||||||
.master_dma_chan = 1,
|
|
||||||
.slave_dma_chan = 1,
|
|
||||||
},
|
|
||||||
{ .pset_name = "mode 1, DMA, 20M",
|
|
||||||
.freq_list = test_freq_20M_only,
|
|
||||||
.dup = HALF_DUPLEX_MISO,
|
|
||||||
.master_iomux= true,
|
|
||||||
.slave_iomux = true,
|
|
||||||
.slave_tv_ns = TV_WITH_ESP_SLAVE,
|
|
||||||
.mode = 1,
|
|
||||||
.master_dma_chan = 1,
|
|
||||||
.slave_dma_chan = 1,
|
|
||||||
},
|
|
||||||
{ .pset_name = "mode 2, DMA, 20M",
|
|
||||||
.freq_list = test_freq_20M_only,
|
|
||||||
.dup = HALF_DUPLEX_MISO,
|
|
||||||
.master_iomux= true,
|
|
||||||
.slave_iomux = true,
|
|
||||||
.slave_tv_ns = TV_WITH_ESP_SLAVE,
|
|
||||||
.mode = 2,
|
|
||||||
.master_dma_chan = 1,
|
|
||||||
.slave_dma_chan = 1,
|
|
||||||
},
|
|
||||||
{ .pset_name = "mode 3, DMA, 20M",
|
|
||||||
.freq_list = test_freq_20M_only,
|
|
||||||
.dup = HALF_DUPLEX_MISO,
|
|
||||||
.master_iomux= true,
|
|
||||||
.slave_iomux = true,
|
|
||||||
.slave_tv_ns = TV_WITH_ESP_SLAVE,
|
|
||||||
.mode = 3,
|
|
||||||
.master_dma_chan = 1,
|
|
||||||
.slave_dma_chan = 1,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
TEST_SPI_MASTER_SLAVE(MODE, mode_conf, "[ignore]")
|
|
||||||
|
|
|
@ -103,120 +103,3 @@ TEST_CASE("local test sio", "[spi]")
|
||||||
spi_slave_free(TEST_SLAVE_HOST);
|
spi_slave_free(TEST_SLAVE_HOST);
|
||||||
master_free_device_bus(spi);
|
master_free_device_bus(spi);
|
||||||
}
|
}
|
||||||
|
|
||||||
/********************************************************************************
|
|
||||||
* Test SIO Master & Slave
|
|
||||||
********************************************************************************/
|
|
||||||
//if test_mosi is false, test on miso of slave, otherwise test on mosi of slave
|
|
||||||
void test_sio_master_round(bool test_mosi)
|
|
||||||
{
|
|
||||||
spi_device_handle_t spi;
|
|
||||||
WORD_ALIGNED_ATTR uint8_t rx_buffer[320];
|
|
||||||
|
|
||||||
if (test_mosi) {
|
|
||||||
ESP_LOGI(MASTER_TAG, "======== TEST MOSI ===========");
|
|
||||||
} else {
|
|
||||||
ESP_LOGI(MASTER_TAG, "======== TEST MISO ===========");
|
|
||||||
}
|
|
||||||
|
|
||||||
spi_bus_config_t bus_cfg = SPI_BUS_TEST_DEFAULT_CONFIG();
|
|
||||||
if (!test_mosi) bus_cfg.mosi_io_num = bus_cfg.miso_io_num;
|
|
||||||
bus_cfg.miso_io_num = -1;
|
|
||||||
TEST_ESP_OK(spi_bus_initialize(TEST_SPI_HOST, &bus_cfg, 0));
|
|
||||||
|
|
||||||
spi_device_interface_config_t dev_cfg = SPI_DEVICE_TEST_DEFAULT_CONFIG();
|
|
||||||
dev_cfg.flags = SPI_DEVICE_HALFDUPLEX | SPI_DEVICE_3WIRE;
|
|
||||||
dev_cfg.clock_speed_hz = 1*1000*1000;
|
|
||||||
TEST_ESP_OK(spi_bus_add_device(TEST_SPI_HOST, &dev_cfg, &spi));
|
|
||||||
|
|
||||||
for (int i = 0; i < 8; i ++) {
|
|
||||||
int tlen = i*2+1;
|
|
||||||
int rlen = 9-i;
|
|
||||||
spi_transaction_t t = {
|
|
||||||
.length = tlen*8,
|
|
||||||
.tx_buffer = spitest_master_send+i,
|
|
||||||
.rxlength = rlen*8,
|
|
||||||
.rx_buffer = rx_buffer+i,
|
|
||||||
};
|
|
||||||
memset(rx_buffer, 0x66, sizeof(rx_buffer));
|
|
||||||
|
|
||||||
//get signal
|
|
||||||
unity_wait_for_signal("slave ready");
|
|
||||||
|
|
||||||
TEST_ESP_OK(spi_device_transmit(spi, &t));
|
|
||||||
uint8_t* exp_ptr = spitest_slave_send+i;
|
|
||||||
ESP_LOG_BUFFER_HEXDUMP("master tx", t.tx_buffer, tlen, ESP_LOG_INFO);
|
|
||||||
ESP_LOG_BUFFER_HEXDUMP("exp tx", exp_ptr, rlen, ESP_LOG_INFO);
|
|
||||||
ESP_LOG_BUFFER_HEXDUMP("master rx", t.rx_buffer, rlen, ESP_LOG_INFO);
|
|
||||||
if (!test_mosi) {
|
|
||||||
TEST_ASSERT_EQUAL_HEX8_ARRAY(exp_ptr+tlen, t.rx_buffer, rlen);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
master_free_device_bus(spi);
|
|
||||||
}
|
|
||||||
|
|
||||||
void test_sio_master(void)
|
|
||||||
{
|
|
||||||
test_sio_master_round(true);
|
|
||||||
unity_send_signal("master ready");
|
|
||||||
test_sio_master_round(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void test_sio_slave_round(bool test_mosi)
|
|
||||||
{
|
|
||||||
WORD_ALIGNED_ATTR uint8_t rx_buffer[320];
|
|
||||||
|
|
||||||
if (test_mosi) {
|
|
||||||
ESP_LOGI(SLAVE_TAG, "======== TEST MOSI ===========");
|
|
||||||
} else {
|
|
||||||
ESP_LOGI(SLAVE_TAG, "======== TEST MISO ===========");
|
|
||||||
}
|
|
||||||
|
|
||||||
spi_bus_config_t bus_cfg = SPI_BUS_TEST_DEFAULT_CONFIG();
|
|
||||||
bus_cfg.mosi_io_num = spi_periph_signal[TEST_SLAVE_HOST].spid_iomux_pin;
|
|
||||||
bus_cfg.miso_io_num = spi_periph_signal[TEST_SLAVE_HOST].spiq_iomux_pin;
|
|
||||||
bus_cfg.sclk_io_num = spi_periph_signal[TEST_SLAVE_HOST].spiclk_iomux_pin;
|
|
||||||
|
|
||||||
spi_slave_interface_config_t slv_cfg = SPI_SLAVE_TEST_DEFAULT_CONFIG();
|
|
||||||
slv_cfg.spics_io_num = spi_periph_signal[TEST_SLAVE_HOST].spics0_iomux_pin;
|
|
||||||
TEST_ESP_OK(spi_slave_initialize(TEST_SLAVE_HOST, &bus_cfg, &slv_cfg, 0));
|
|
||||||
|
|
||||||
for (int i = 0; i < 8; i++) {
|
|
||||||
int tlen = 9-i;
|
|
||||||
int rlen = i*2+1;
|
|
||||||
spi_slave_transaction_t t = {
|
|
||||||
.length = (tlen+rlen)*8,
|
|
||||||
.tx_buffer = spitest_slave_send+i,
|
|
||||||
.rx_buffer = rx_buffer,
|
|
||||||
};
|
|
||||||
|
|
||||||
TEST_ESP_OK(spi_slave_queue_trans(TEST_SLAVE_HOST, &t, portMAX_DELAY));
|
|
||||||
|
|
||||||
ESP_LOG_BUFFER_HEXDUMP("slave tx", t.tx_buffer, tlen+rlen, ESP_LOG_INFO);
|
|
||||||
|
|
||||||
//send signal_idx
|
|
||||||
unity_send_signal("slave ready");
|
|
||||||
|
|
||||||
uint8_t *exp_ptr = spitest_master_send+i;
|
|
||||||
spi_slave_transaction_t* ret_t;
|
|
||||||
TEST_ESP_OK(spi_slave_get_trans_result(TEST_SLAVE_HOST, &ret_t, portMAX_DELAY));
|
|
||||||
|
|
||||||
ESP_LOG_BUFFER_HEXDUMP("exp tx", exp_ptr, tlen+rlen, ESP_LOG_INFO);
|
|
||||||
ESP_LOG_BUFFER_HEXDUMP("slave rx", t.rx_buffer, tlen+rlen, ESP_LOG_INFO);
|
|
||||||
if (test_mosi) {
|
|
||||||
TEST_ASSERT_EQUAL_HEX8_ARRAY(exp_ptr, t.rx_buffer, rlen);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
spi_slave_free(TEST_SLAVE_HOST);
|
|
||||||
}
|
|
||||||
|
|
||||||
void test_sio_slave(void)
|
|
||||||
{
|
|
||||||
test_sio_slave_round(true);
|
|
||||||
unity_wait_for_signal("master ready");
|
|
||||||
test_sio_slave_round(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE_MULTIPLE_DEVICES("sio mode", "[spi][test_env=Example_SPI_Multi_device]", test_sio_master, test_sio_slave);
|
|
||||||
|
|
|
@ -26,83 +26,6 @@
|
||||||
// Wait timeout for uart driver
|
// Wait timeout for uart driver
|
||||||
#define PACKET_READ_TICS (1000 / portTICK_RATE_MS)
|
#define PACKET_READ_TICS (1000 / portTICK_RATE_MS)
|
||||||
|
|
||||||
// The table for fast CRC16 calculation
|
|
||||||
static const uint8_t crc_hi[] = {
|
|
||||||
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
|
|
||||||
0x00, 0xC1, 0x81,
|
|
||||||
0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81,
|
|
||||||
0x40, 0x01, 0xC0,
|
|
||||||
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1,
|
|
||||||
0x81, 0x40, 0x01,
|
|
||||||
0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01,
|
|
||||||
0xC0, 0x80, 0x41,
|
|
||||||
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
|
|
||||||
0x00, 0xC1, 0x81,
|
|
||||||
0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80,
|
|
||||||
0x41, 0x01, 0xC0,
|
|
||||||
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
|
|
||||||
0x80, 0x41, 0x01,
|
|
||||||
0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00,
|
|
||||||
0xC1, 0x81, 0x40,
|
|
||||||
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
|
|
||||||
0x00, 0xC1, 0x81,
|
|
||||||
0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
|
|
||||||
0x40, 0x01, 0xC0,
|
|
||||||
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1,
|
|
||||||
0x81, 0x40, 0x01,
|
|
||||||
0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01,
|
|
||||||
0xC0, 0x80, 0x41,
|
|
||||||
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
|
|
||||||
0x00, 0xC1, 0x81,
|
|
||||||
0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
|
|
||||||
0x40, 0x01, 0xC0,
|
|
||||||
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
|
|
||||||
0x80, 0x41, 0x01,
|
|
||||||
0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01,
|
|
||||||
0xC0, 0x80, 0x41,
|
|
||||||
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
|
|
||||||
0x00, 0xC1, 0x81,
|
|
||||||
0x40
|
|
||||||
};
|
|
||||||
|
|
||||||
static const uint8_t crc_low[] = {
|
|
||||||
0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7,
|
|
||||||
0x05, 0xC5, 0xC4,
|
|
||||||
0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB,
|
|
||||||
0x0B, 0xC9, 0x09,
|
|
||||||
0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE,
|
|
||||||
0xDF, 0x1F, 0xDD,
|
|
||||||
0x1D, 0x1C, 0xDC, 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2,
|
|
||||||
0x12, 0x13, 0xD3,
|
|
||||||
0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32,
|
|
||||||
0x36, 0xF6, 0xF7,
|
|
||||||
0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E,
|
|
||||||
0xFE, 0xFA, 0x3A,
|
|
||||||
0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B,
|
|
||||||
0x2A, 0xEA, 0xEE,
|
|
||||||
0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27,
|
|
||||||
0xE7, 0xE6, 0x26,
|
|
||||||
0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1,
|
|
||||||
0x63, 0xA3, 0xA2,
|
|
||||||
0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD,
|
|
||||||
0x6D, 0xAF, 0x6F,
|
|
||||||
0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8,
|
|
||||||
0xB9, 0x79, 0xBB,
|
|
||||||
0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4,
|
|
||||||
0x74, 0x75, 0xB5,
|
|
||||||
0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0,
|
|
||||||
0x50, 0x90, 0x91,
|
|
||||||
0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94,
|
|
||||||
0x54, 0x9C, 0x5C,
|
|
||||||
0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59,
|
|
||||||
0x58, 0x98, 0x88,
|
|
||||||
0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D,
|
|
||||||
0x4D, 0x4C, 0x8C,
|
|
||||||
0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83,
|
|
||||||
0x41, 0x81, 0x80,
|
|
||||||
0x40
|
|
||||||
};
|
|
||||||
|
|
||||||
static void uart_config(uint32_t baud_rate, bool use_ref_tick)
|
static void uart_config(uint32_t baud_rate, bool use_ref_tick)
|
||||||
{
|
{
|
||||||
uart_config_t uart_config = {
|
uart_config_t uart_config = {
|
||||||
|
@ -203,177 +126,3 @@ TEST_CASE("test uart tx data with break", "[uart]")
|
||||||
free(psend);
|
free(psend);
|
||||||
uart_driver_delete(UART_NUM1);
|
uart_driver_delete(UART_NUM1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate buffer checksum using tables
|
|
||||||
// The checksum CRC16 algorithm is specific
|
|
||||||
// for Modbus standard and uses polynomial value = 0xA001
|
|
||||||
static uint16_t get_buffer_crc16( uint8_t * frame_ptr, uint16_t length )
|
|
||||||
{
|
|
||||||
TEST_ASSERT( frame_ptr != NULL);
|
|
||||||
|
|
||||||
uint8_t crc_hi_byte = 0xFF;
|
|
||||||
uint8_t crc_low_byte = 0xFF;
|
|
||||||
int index;
|
|
||||||
|
|
||||||
while ( length-- )
|
|
||||||
{
|
|
||||||
index = crc_low_byte ^ *(frame_ptr++);
|
|
||||||
crc_low_byte = crc_hi_byte ^ crc_hi[index];
|
|
||||||
crc_hi_byte = crc_low[index];
|
|
||||||
}
|
|
||||||
return ((crc_hi_byte << 8) | crc_low_byte);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fill the buffer with random numbers and apply CRC16 at the end
|
|
||||||
static uint16_t buffer_fill_random(uint8_t *buffer, size_t length)
|
|
||||||
{
|
|
||||||
TEST_ASSERT( buffer != NULL);
|
|
||||||
// Packet is too short
|
|
||||||
if (length < 4) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
for (int i = 0; i < length; i += 4) {
|
|
||||||
uint32_t random = esp_random();
|
|
||||||
memcpy(buffer + i, &random, MIN(length - i, 4));
|
|
||||||
}
|
|
||||||
// Get checksum of the buffer
|
|
||||||
uint16_t crc = get_buffer_crc16((uint8_t*)buffer, (length - 2));
|
|
||||||
// Apply checksum bytes into packet
|
|
||||||
buffer[length - 2] = (uint8_t)(crc & 0xFF); // Set Low byte CRC
|
|
||||||
buffer[length - 1] = (uint8_t)(crc >> 8); // Set High byte CRC
|
|
||||||
return crc;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void rs485_init(void)
|
|
||||||
{
|
|
||||||
uart_config_t uart_config = {
|
|
||||||
.baud_rate = UART_BAUD_115200,
|
|
||||||
.data_bits = UART_DATA_8_BITS,
|
|
||||||
.parity = UART_PARITY_DISABLE,
|
|
||||||
.stop_bits = UART_STOP_BITS_1,
|
|
||||||
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
|
|
||||||
.rx_flow_ctrl_thresh = 122,
|
|
||||||
};
|
|
||||||
printf("RS485 port initialization...\r\n");
|
|
||||||
// Configure UART1 parameters
|
|
||||||
uart_param_config(UART_NUM1, &uart_config);
|
|
||||||
// Set UART1 pins(TX: IO4, RX: I05, RTS: IO18, CTS: IO19)
|
|
||||||
uart_set_pin(UART_NUM1, UART1_TX_PIN, UART1_RX_PIN, UART1_RTS_PIN, UART_PIN_NO_CHANGE);
|
|
||||||
// Install UART driver (we don't need an event queue here)
|
|
||||||
uart_driver_install(UART_NUM1, BUF_SIZE * 2, 0, 0, NULL, 0);
|
|
||||||
// Setup rs485 half duplex mode
|
|
||||||
//uart_set_rs485_hd_mode(uart_num, true);
|
|
||||||
uart_set_mode(UART_NUM1, UART_MODE_RS485_HALF_DUPLEX);
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t print_packet_data(const char *str, uint8_t *buffer, uint16_t buffer_size)
|
|
||||||
{
|
|
||||||
TEST_ASSERT( buffer != NULL);
|
|
||||||
TEST_ASSERT( str != NULL);
|
|
||||||
|
|
||||||
// Calculate the checksum of the buffer
|
|
||||||
uint16_t crc16_calc = get_buffer_crc16(buffer, (buffer_size - 2));
|
|
||||||
uint16_t crc16_in = ((uint16_t)(buffer[buffer_size - 1]) << 8) | buffer[buffer_size - 2];
|
|
||||||
const char* state_str = (crc16_in != crc16_calc) ? "incorrect " : "correct ";
|
|
||||||
// Print an array of data
|
|
||||||
printf("%s%s RS485 packet = [ ", str, state_str);
|
|
||||||
for (int i = 0; i < buffer_size; i++) {
|
|
||||||
printf("0x%.2X ", (uint8_t)buffer[i]);
|
|
||||||
}
|
|
||||||
printf(" ]\r\n");
|
|
||||||
printf("crc_in = 0x%.4X\r\n", (uint16_t)crc16_in);
|
|
||||||
printf("crc_calc = 0x%.4X\r\n", (uint16_t)crc16_calc);
|
|
||||||
esp_err_t result = (crc16_in != crc16_calc) ? ESP_ERR_INVALID_CRC : ESP_OK;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Slave test case for multi device
|
|
||||||
static void rs485_slave(void)
|
|
||||||
{
|
|
||||||
rs485_init();
|
|
||||||
uint8_t* slave_data = (uint8_t*) malloc(BUF_SIZE);
|
|
||||||
uint16_t err_count = 0, good_count = 0;
|
|
||||||
printf("Start recieve loop.\r\n");
|
|
||||||
unity_send_signal("Slave_ready");
|
|
||||||
unity_wait_for_signal("Master_started");
|
|
||||||
for(int pack_count = 0; pack_count < PACKETS_NUMBER; pack_count++) {
|
|
||||||
//Read slave_data from UART
|
|
||||||
int len = uart_read_bytes(UART_NUM1, slave_data, BUF_SIZE, (PACKET_READ_TICS * 2));
|
|
||||||
//Write slave_data back to UART
|
|
||||||
if (len > 2) {
|
|
||||||
esp_err_t status = print_packet_data("Received ", slave_data, len);
|
|
||||||
|
|
||||||
// If received packet is correct then send it back
|
|
||||||
if (status == ESP_OK) {
|
|
||||||
uart_write_bytes(UART_NUM1, (char*)slave_data, len);
|
|
||||||
good_count++;
|
|
||||||
} else {
|
|
||||||
printf("Incorrect packet received.\r\n");
|
|
||||||
err_count++;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
printf("Incorrect data packet[%d] received.\r\n", pack_count);
|
|
||||||
err_count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
printf("Test completed. Received packets = %d, errors = %d\r\n", good_count, err_count);
|
|
||||||
// Wait for packet to be sent
|
|
||||||
uart_wait_tx_done(UART_NUM1, PACKET_READ_TICS);
|
|
||||||
free(slave_data);
|
|
||||||
uart_driver_delete(UART_NUM1);
|
|
||||||
TEST_ASSERT(err_count < 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Master test of multi device test case.
|
|
||||||
// It forms packet with random data, apply generated CRC16 and sends to slave.
|
|
||||||
// If response recieved correctly from slave means RS485 channel works.
|
|
||||||
static void rs485_master(void)
|
|
||||||
{
|
|
||||||
uint16_t err_count = 0, good_count = 0;
|
|
||||||
rs485_init();
|
|
||||||
uint8_t* master_buffer = (uint8_t*) malloc(BUF_SIZE);
|
|
||||||
uint8_t* slave_buffer = (uint8_t*) malloc(BUF_SIZE);
|
|
||||||
// The master test case should be synchronized with slave
|
|
||||||
unity_wait_for_signal("Slave_ready");
|
|
||||||
unity_send_signal("Master_started");
|
|
||||||
printf("Start recieve loop.\r\n");
|
|
||||||
for(int i = 0; i < PACKETS_NUMBER; i++) {
|
|
||||||
// Form random buffer with CRC16
|
|
||||||
buffer_fill_random(master_buffer, BUF_SIZE);
|
|
||||||
// Print created packet for debugging
|
|
||||||
esp_err_t status = print_packet_data("Send ", master_buffer, BUF_SIZE);
|
|
||||||
TEST_ASSERT(status == ESP_OK);
|
|
||||||
uart_write_bytes(UART_NUM1, (char*)master_buffer, BUF_SIZE);
|
|
||||||
// Read translated packet from slave
|
|
||||||
int len = uart_read_bytes(UART_NUM1, slave_buffer, BUF_SIZE, (PACKET_READ_TICS * 2));
|
|
||||||
// Check if the received packet is too short
|
|
||||||
if (len > 2) {
|
|
||||||
// Print received packet and check checksum
|
|
||||||
esp_err_t status = print_packet_data("Received ", slave_buffer, len);
|
|
||||||
if (status == ESP_OK) {
|
|
||||||
good_count++;
|
|
||||||
printf("Received: %d\r\n", good_count);
|
|
||||||
} else {
|
|
||||||
err_count++;
|
|
||||||
printf("Errors: %d\r\n", err_count);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
printf("Incorrect answer from slave.\r\n");
|
|
||||||
err_count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Free the buffer and delete driver at the end
|
|
||||||
free(master_buffer);
|
|
||||||
uart_driver_delete(UART_NUM1);
|
|
||||||
TEST_ASSERT(err_count <= 1);
|
|
||||||
printf("Test completed. Received packets = %d, errors = %d\r\n", (uint16_t)good_count, (uint16_t)err_count);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This multi devices test case verifies RS485 mode of the uart driver and checks
|
|
||||||
* correctness of RS485 interface channel communication. It requires
|
|
||||||
* RS485 bus driver hardware to be connected to boards.
|
|
||||||
*/
|
|
||||||
TEST_CASE_MULTIPLE_DEVICES("RS485 half duplex uart multiple devices test.", "[driver_RS485][test_env=UT_T2_RS485]", rs485_master, rs485_slave);
|
|
||||||
|
|
||||||
|
|
233
components/esp_wifi/test/esp32/test_wifi.c
Normal file
233
components/esp_wifi/test/esp32/test_wifi.c
Normal file
|
@ -0,0 +1,233 @@
|
||||||
|
/*
|
||||||
|
Tests for the Wi-Fi
|
||||||
|
*/
|
||||||
|
#include "string.h"
|
||||||
|
#include "esp_system.h"
|
||||||
|
#include "unity.h"
|
||||||
|
#include "esp_system.h"
|
||||||
|
#include "esp_event_loop.h"
|
||||||
|
#include "esp_wifi.h"
|
||||||
|
#include "esp_wifi_types.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "nvs_flash.h"
|
||||||
|
#include "test_utils.h"
|
||||||
|
#include "freertos/task.h"
|
||||||
|
#include "freertos/event_groups.h"
|
||||||
|
|
||||||
|
static const char* TAG = "test_wifi";
|
||||||
|
|
||||||
|
#define DEFAULT_SSID "TEST_SSID"
|
||||||
|
#define DEFAULT_PWD "TEST_PASS"
|
||||||
|
|
||||||
|
#define GOT_IP_EVENT 0x00000001
|
||||||
|
#define DISCONNECT_EVENT 0x00000002
|
||||||
|
|
||||||
|
#define EVENT_HANDLER_FLAG_DO_NOT_AUTO_RECONNECT 0x00000001
|
||||||
|
|
||||||
|
static uint32_t wifi_event_handler_flag;
|
||||||
|
|
||||||
|
static EventGroupHandle_t wifi_events;
|
||||||
|
|
||||||
|
static esp_err_t event_handler(void *ctx, system_event_t *event)
|
||||||
|
{
|
||||||
|
printf("ev_handle_called.\n");
|
||||||
|
switch(event->event_id) {
|
||||||
|
case SYSTEM_EVENT_STA_START:
|
||||||
|
ESP_LOGI(TAG, "SYSTEM_EVENT_STA_START");
|
||||||
|
//do not actually connect in test case
|
||||||
|
//;
|
||||||
|
break;
|
||||||
|
case SYSTEM_EVENT_STA_GOT_IP:
|
||||||
|
ESP_LOGI(TAG, "SYSTEM_EVENT_STA_GOT_IP");
|
||||||
|
ESP_LOGI(TAG, "got ip:%s\n",
|
||||||
|
ip4addr_ntoa(&event->event_info.got_ip.ip_info.ip));
|
||||||
|
if (wifi_events) {
|
||||||
|
xEventGroupSetBits(wifi_events, GOT_IP_EVENT);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SYSTEM_EVENT_STA_DISCONNECTED:
|
||||||
|
ESP_LOGI(TAG, "SYSTEM_EVENT_STA_DISCONNECTED");
|
||||||
|
if (! (EVENT_HANDLER_FLAG_DO_NOT_AUTO_RECONNECT & wifi_event_handler_flag) ) {
|
||||||
|
TEST_ESP_OK(esp_wifi_connect());
|
||||||
|
}
|
||||||
|
if (wifi_events) {
|
||||||
|
xEventGroupSetBits(wifi_events, DISCONNECT_EVENT);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void start_wifi_as_softap(void)
|
||||||
|
{
|
||||||
|
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
|
||||||
|
cfg.nvs_enable = false;
|
||||||
|
|
||||||
|
wifi_config_t w_config = {
|
||||||
|
.ap.ssid = DEFAULT_SSID,
|
||||||
|
.ap.password = DEFAULT_PWD,
|
||||||
|
.ap.ssid_len = 0,
|
||||||
|
.ap.channel = 1,
|
||||||
|
.ap.authmode = WIFI_AUTH_WPA2_PSK,
|
||||||
|
.ap.ssid_hidden = false,
|
||||||
|
.ap.max_connection = 4,
|
||||||
|
.ap.beacon_interval = 100,
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_ESP_OK(esp_event_loop_init(event_handler, NULL));
|
||||||
|
|
||||||
|
// can't deinit event loop, need to reset leak check
|
||||||
|
unity_reset_leak_checks();
|
||||||
|
|
||||||
|
if (wifi_events == NULL) {
|
||||||
|
wifi_events = xEventGroupCreate();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_ESP_OK(esp_wifi_init(&cfg));
|
||||||
|
TEST_ESP_OK(esp_wifi_set_mode(WIFI_MODE_AP));
|
||||||
|
TEST_ESP_OK(esp_wifi_set_config(WIFI_IF_AP, &w_config));
|
||||||
|
TEST_ESP_OK(esp_wifi_start());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void start_wifi_as_sta(void)
|
||||||
|
{
|
||||||
|
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
|
||||||
|
cfg.nvs_enable = false;
|
||||||
|
|
||||||
|
// do not auto connect
|
||||||
|
wifi_event_handler_flag |= EVENT_HANDLER_FLAG_DO_NOT_AUTO_RECONNECT;
|
||||||
|
TEST_ESP_OK(esp_event_loop_init(event_handler, NULL));
|
||||||
|
|
||||||
|
// can't deinit event loop, need to reset leak check
|
||||||
|
unity_reset_leak_checks();
|
||||||
|
|
||||||
|
if (wifi_events == NULL) {
|
||||||
|
wifi_events = xEventGroupCreate();
|
||||||
|
} else {
|
||||||
|
xEventGroupClearBits(wifi_events, 0x00ffffff);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_ESP_OK(esp_wifi_init(&cfg));
|
||||||
|
TEST_ESP_OK(esp_wifi_set_mode(WIFI_MODE_STA));
|
||||||
|
TEST_ESP_OK(esp_wifi_start());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void stop_wifi(void)
|
||||||
|
{
|
||||||
|
printf("stop wifi\n");
|
||||||
|
TEST_ESP_OK(esp_wifi_stop());
|
||||||
|
TEST_ESP_OK(esp_wifi_deinit());
|
||||||
|
if (wifi_events) {
|
||||||
|
vEventGroupDelete(wifi_events);
|
||||||
|
wifi_events = NULL;
|
||||||
|
}
|
||||||
|
vTaskDelay(1000/portTICK_PERIOD_MS);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void receive_ds2ds_packet(void)
|
||||||
|
{
|
||||||
|
test_case_uses_tcpip();
|
||||||
|
start_wifi_as_softap();
|
||||||
|
unity_wait_for_signal("sender ready");
|
||||||
|
unity_send_signal("receiver ready");
|
||||||
|
|
||||||
|
// wait for sender to send packets
|
||||||
|
vTaskDelay(1000/portTICK_PERIOD_MS);
|
||||||
|
stop_wifi();
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char ds2ds_pdu[] = {
|
||||||
|
0x48, 0x03, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xE8, 0x65, 0xD4, 0xCB, 0x74, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0x60, 0x94, 0xE8, 0x65, 0xD4, 0xCB, 0x74, 0x1C, 0x26, 0xB9,
|
||||||
|
0x0D, 0x02, 0x7D, 0x13, 0x00, 0x00, 0x01, 0xE8, 0x65, 0xD4, 0xCB, 0x74,
|
||||||
|
0x1C, 0x00, 0x00, 0x26, 0xB9, 0x00, 0x00, 0x00, 0x00
|
||||||
|
};
|
||||||
|
|
||||||
|
static void send_ds2ds_packet(void)
|
||||||
|
{
|
||||||
|
test_case_uses_tcpip();
|
||||||
|
start_wifi_as_softap();
|
||||||
|
unity_send_signal("sender ready");
|
||||||
|
unity_wait_for_signal("receiver ready");
|
||||||
|
|
||||||
|
// send packet 20 times to make sure receiver will get this packet
|
||||||
|
for (uint16_t i = 0; i < 20; i++) {
|
||||||
|
esp_wifi_80211_tx(ESP_IF_WIFI_AP, ds2ds_pdu, sizeof(ds2ds_pdu), true);
|
||||||
|
vTaskDelay(50 / portTICK_PERIOD_MS);
|
||||||
|
}
|
||||||
|
stop_wifi();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE_MULTIPLE_DEVICES("receive ds2ds packet without exception", "[wifi][test_env=UT_T2_1]", receive_ds2ds_packet, send_ds2ds_packet);
|
||||||
|
|
||||||
|
static void wifi_connect_by_bssid(uint8_t *bssid)
|
||||||
|
{
|
||||||
|
EventBits_t bits;
|
||||||
|
|
||||||
|
wifi_config_t w_config = {
|
||||||
|
.sta.ssid = DEFAULT_SSID,
|
||||||
|
.sta.password = DEFAULT_PWD,
|
||||||
|
.sta.bssid_set = true,
|
||||||
|
};
|
||||||
|
|
||||||
|
memcpy(w_config.sta.bssid, bssid, 6);
|
||||||
|
|
||||||
|
TEST_ESP_OK(esp_wifi_set_config(WIFI_IF_STA, &w_config));
|
||||||
|
TEST_ESP_OK(esp_wifi_connect());
|
||||||
|
bits = xEventGroupWaitBits(wifi_events, GOT_IP_EVENT, 1, 0, 5000/portTICK_RATE_MS);
|
||||||
|
TEST_ASSERT(bits == GOT_IP_EVENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_wifi_connection_sta(void)
|
||||||
|
{
|
||||||
|
char mac_str[19];
|
||||||
|
uint8_t mac[6];
|
||||||
|
EventBits_t bits;
|
||||||
|
|
||||||
|
test_case_uses_tcpip();
|
||||||
|
|
||||||
|
start_wifi_as_sta();
|
||||||
|
|
||||||
|
unity_wait_for_signal_param("SoftAP mac", mac_str, 19);
|
||||||
|
|
||||||
|
TEST_ASSERT_TRUE(unity_util_convert_mac_from_string(mac_str, mac));
|
||||||
|
|
||||||
|
wifi_connect_by_bssid(mac);
|
||||||
|
|
||||||
|
unity_send_signal("STA connected");
|
||||||
|
|
||||||
|
bits = xEventGroupWaitBits(wifi_events, DISCONNECT_EVENT, 1, 0, 60000 / portTICK_RATE_MS);
|
||||||
|
// disconnect event not triggered
|
||||||
|
printf("wait finish\n");
|
||||||
|
TEST_ASSERT(bits == 0);
|
||||||
|
|
||||||
|
stop_wifi();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_wifi_connection_softap(void)
|
||||||
|
{
|
||||||
|
char mac_str[19] = {0};
|
||||||
|
uint8_t mac[6];
|
||||||
|
|
||||||
|
test_case_uses_tcpip();
|
||||||
|
|
||||||
|
start_wifi_as_softap();
|
||||||
|
|
||||||
|
TEST_ESP_OK(esp_wifi_get_mac(ESP_IF_WIFI_AP, mac));
|
||||||
|
sprintf(mac_str, MACSTR, MAC2STR(mac));
|
||||||
|
|
||||||
|
unity_send_signal_param("SoftAP mac", mac_str);
|
||||||
|
|
||||||
|
unity_wait_for_signal("STA connected");
|
||||||
|
|
||||||
|
vTaskDelay(60000 / portTICK_PERIOD_MS);
|
||||||
|
|
||||||
|
stop_wifi();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE_MULTIPLE_DEVICES("test wifi retain connection for 60s", "[wifi][test_env=UT_T2_1][timeout=90]", test_wifi_connection_sta, test_wifi_connection_softap);
|
|
@ -141,174 +141,3 @@ TEST_CASE("wifi stop and deinit","[wifi]")
|
||||||
|
|
||||||
TEST_IGNORE_MESSAGE("this test case is ignored due to the critical memory leak of tcpip_adapter and event_loop.");
|
TEST_IGNORE_MESSAGE("this test case is ignored due to the critical memory leak of tcpip_adapter and event_loop.");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void start_wifi_as_softap(void)
|
|
||||||
{
|
|
||||||
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
|
|
||||||
cfg.nvs_enable = false;
|
|
||||||
|
|
||||||
wifi_config_t w_config = {
|
|
||||||
.ap.ssid = DEFAULT_SSID,
|
|
||||||
.ap.password = DEFAULT_PWD,
|
|
||||||
.ap.ssid_len = 0,
|
|
||||||
.ap.channel = 1,
|
|
||||||
.ap.authmode = WIFI_AUTH_WPA2_PSK,
|
|
||||||
.ap.ssid_hidden = false,
|
|
||||||
.ap.max_connection = 4,
|
|
||||||
.ap.beacon_interval = 100,
|
|
||||||
};
|
|
||||||
|
|
||||||
TEST_ESP_OK(esp_event_loop_init(event_handler, NULL));
|
|
||||||
|
|
||||||
// can't deinit event loop, need to reset leak check
|
|
||||||
unity_reset_leak_checks();
|
|
||||||
|
|
||||||
if (wifi_events == NULL) {
|
|
||||||
wifi_events = xEventGroupCreate();
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_ESP_OK(esp_wifi_init(&cfg));
|
|
||||||
TEST_ESP_OK(esp_wifi_set_mode(WIFI_MODE_AP));
|
|
||||||
TEST_ESP_OK(esp_wifi_set_config(WIFI_IF_AP, &w_config));
|
|
||||||
TEST_ESP_OK(esp_wifi_start());
|
|
||||||
}
|
|
||||||
|
|
||||||
static void start_wifi_as_sta(void)
|
|
||||||
{
|
|
||||||
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
|
|
||||||
cfg.nvs_enable = false;
|
|
||||||
|
|
||||||
// do not auto connect
|
|
||||||
wifi_event_handler_flag |= EVENT_HANDLER_FLAG_DO_NOT_AUTO_RECONNECT;
|
|
||||||
TEST_ESP_OK(esp_event_loop_init(event_handler, NULL));
|
|
||||||
|
|
||||||
// can't deinit event loop, need to reset leak check
|
|
||||||
unity_reset_leak_checks();
|
|
||||||
|
|
||||||
if (wifi_events == NULL) {
|
|
||||||
wifi_events = xEventGroupCreate();
|
|
||||||
} else {
|
|
||||||
xEventGroupClearBits(wifi_events, 0x00ffffff);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_ESP_OK(esp_wifi_init(&cfg));
|
|
||||||
TEST_ESP_OK(esp_wifi_set_mode(WIFI_MODE_STA));
|
|
||||||
TEST_ESP_OK(esp_wifi_start());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static void stop_wifi(void)
|
|
||||||
{
|
|
||||||
printf("stop wifi\n");
|
|
||||||
TEST_ESP_OK(esp_wifi_stop());
|
|
||||||
TEST_ESP_OK(esp_wifi_deinit());
|
|
||||||
if (wifi_events) {
|
|
||||||
vEventGroupDelete(wifi_events);
|
|
||||||
wifi_events = NULL;
|
|
||||||
}
|
|
||||||
vTaskDelay(1000/portTICK_PERIOD_MS);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void receive_ds2ds_packet(void)
|
|
||||||
{
|
|
||||||
test_case_uses_tcpip();
|
|
||||||
start_wifi_as_softap();
|
|
||||||
unity_wait_for_signal("sender ready");
|
|
||||||
unity_send_signal("receiver ready");
|
|
||||||
|
|
||||||
// wait for sender to send packets
|
|
||||||
vTaskDelay(1000/portTICK_PERIOD_MS);
|
|
||||||
stop_wifi();
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char ds2ds_pdu[] = {
|
|
||||||
0x48, 0x03, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
|
||||||
0xE8, 0x65, 0xD4, 0xCB, 0x74, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
|
||||||
0x60, 0x94, 0xE8, 0x65, 0xD4, 0xCB, 0x74, 0x1C, 0x26, 0xB9,
|
|
||||||
0x0D, 0x02, 0x7D, 0x13, 0x00, 0x00, 0x01, 0xE8, 0x65, 0xD4, 0xCB, 0x74,
|
|
||||||
0x1C, 0x00, 0x00, 0x26, 0xB9, 0x00, 0x00, 0x00, 0x00
|
|
||||||
};
|
|
||||||
|
|
||||||
static void send_ds2ds_packet(void)
|
|
||||||
{
|
|
||||||
test_case_uses_tcpip();
|
|
||||||
start_wifi_as_softap();
|
|
||||||
unity_send_signal("sender ready");
|
|
||||||
unity_wait_for_signal("receiver ready");
|
|
||||||
|
|
||||||
// send packet 20 times to make sure receiver will get this packet
|
|
||||||
for (uint16_t i = 0; i < 20; i++) {
|
|
||||||
esp_wifi_80211_tx(ESP_IF_WIFI_AP, ds2ds_pdu, sizeof(ds2ds_pdu), true);
|
|
||||||
vTaskDelay(50 / portTICK_PERIOD_MS);
|
|
||||||
}
|
|
||||||
stop_wifi();
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE_MULTIPLE_DEVICES("receive ds2ds packet without exception", "[wifi][test_env=UT_T2_1]", receive_ds2ds_packet, send_ds2ds_packet);
|
|
||||||
|
|
||||||
static void wifi_connect_by_bssid(uint8_t *bssid)
|
|
||||||
{
|
|
||||||
EventBits_t bits;
|
|
||||||
|
|
||||||
wifi_config_t w_config = {
|
|
||||||
.sta.ssid = DEFAULT_SSID,
|
|
||||||
.sta.password = DEFAULT_PWD,
|
|
||||||
.sta.bssid_set = true,
|
|
||||||
};
|
|
||||||
|
|
||||||
memcpy(w_config.sta.bssid, bssid, 6);
|
|
||||||
|
|
||||||
TEST_ESP_OK(esp_wifi_set_config(WIFI_IF_STA, &w_config));
|
|
||||||
TEST_ESP_OK(esp_wifi_connect());
|
|
||||||
bits = xEventGroupWaitBits(wifi_events, GOT_IP_EVENT, 1, 0, 5000/portTICK_RATE_MS);
|
|
||||||
TEST_ASSERT(bits == GOT_IP_EVENT);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_wifi_connection_sta(void)
|
|
||||||
{
|
|
||||||
char mac_str[19];
|
|
||||||
uint8_t mac[6];
|
|
||||||
EventBits_t bits;
|
|
||||||
|
|
||||||
test_case_uses_tcpip();
|
|
||||||
|
|
||||||
start_wifi_as_sta();
|
|
||||||
|
|
||||||
unity_wait_for_signal_param("SoftAP mac", mac_str, 19);
|
|
||||||
|
|
||||||
TEST_ASSERT_TRUE(unity_util_convert_mac_from_string(mac_str, mac));
|
|
||||||
|
|
||||||
wifi_connect_by_bssid(mac);
|
|
||||||
|
|
||||||
unity_send_signal("STA connected");
|
|
||||||
|
|
||||||
bits = xEventGroupWaitBits(wifi_events, DISCONNECT_EVENT, 1, 0, 60000 / portTICK_RATE_MS);
|
|
||||||
// disconnect event not triggered
|
|
||||||
printf("wait finish\n");
|
|
||||||
TEST_ASSERT(bits == 0);
|
|
||||||
|
|
||||||
stop_wifi();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_wifi_connection_softap(void)
|
|
||||||
{
|
|
||||||
char mac_str[19] = {0};
|
|
||||||
uint8_t mac[6];
|
|
||||||
|
|
||||||
test_case_uses_tcpip();
|
|
||||||
|
|
||||||
start_wifi_as_softap();
|
|
||||||
|
|
||||||
TEST_ESP_OK(esp_wifi_get_mac(ESP_IF_WIFI_AP, mac));
|
|
||||||
sprintf(mac_str, MACSTR, MAC2STR(mac));
|
|
||||||
|
|
||||||
unity_send_signal_param("SoftAP mac", mac_str);
|
|
||||||
|
|
||||||
unity_wait_for_signal("STA connected");
|
|
||||||
|
|
||||||
vTaskDelay(60000 / portTICK_PERIOD_MS);
|
|
||||||
|
|
||||||
stop_wifi();
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE_MULTIPLE_DEVICES("test wifi retain connection for 60s", "[wifi][test_env=UT_T2_1][timeout=90]", test_wifi_connection_sta, test_wifi_connection_softap);
|
|
||||||
|
|
|
@ -419,41 +419,6 @@ UT_031:
|
||||||
- 7.2.2
|
- 7.2.2
|
||||||
- UT_T1_1
|
- UT_T1_1
|
||||||
|
|
||||||
UT_032:
|
|
||||||
extends: .unit_test_template
|
|
||||||
parallel: 3
|
|
||||||
tags:
|
|
||||||
- 7.2.2
|
|
||||||
- UT_T2_1
|
|
||||||
|
|
||||||
UT_033:
|
|
||||||
extends: .unit_test_template
|
|
||||||
parallel: 4
|
|
||||||
tags:
|
|
||||||
- 7.2.2
|
|
||||||
- Example_SPI_Multi_device
|
|
||||||
|
|
||||||
UT_034:
|
|
||||||
extends: .unit_test_template
|
|
||||||
parallel: 4
|
|
||||||
tags:
|
|
||||||
- 7.2.2
|
|
||||||
- UT_T1_RMT
|
|
||||||
|
|
||||||
UT_035:
|
|
||||||
extends: .unit_test_template
|
|
||||||
parallel: 4
|
|
||||||
tags:
|
|
||||||
- 7.2.2
|
|
||||||
- UT_T2_I2C
|
|
||||||
|
|
||||||
UT_036:
|
|
||||||
extends: .unit_test_template
|
|
||||||
parallel: 4
|
|
||||||
tags:
|
|
||||||
- 7.2.2
|
|
||||||
- UT_T2_RS485
|
|
||||||
|
|
||||||
nvs_compatible_test:
|
nvs_compatible_test:
|
||||||
extends: .test_template
|
extends: .test_template
|
||||||
artifacts:
|
artifacts:
|
||||||
|
|
Loading…
Reference in a new issue