diff --git a/components/driver/test/esp32/test_i2c.c b/components/driver/test/esp32/test_i2c.c new file mode 100644 index 000000000..75eec14d7 --- /dev/null +++ b/components/driver/test/esp32/test_i2c.c @@ -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 +#include +#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 /*! +#include +#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); diff --git a/components/driver/test/esp32/test_spi_param.c b/components/driver/test/esp32/test_spi_param.c new file mode 100644 index 000000000..b055cf96c --- /dev/null +++ b/components/driver/test/esp32/test_spi_param.c @@ -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]") \ No newline at end of file diff --git a/components/driver/test/esp32/test_spi_sio.c b/components/driver/test/esp32/test_spi_sio.c new file mode 100644 index 000000000..cf6107ea0 --- /dev/null +++ b/components/driver/test/esp32/test_spi_sio.c @@ -0,0 +1,143 @@ +/* + Tests for the spi sio mode +*/ + +#include +#include +#include +#include +#include +#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); \ No newline at end of file diff --git a/components/driver/test/test_i2c.c b/components/driver/test/test_i2c.c index bde591cb3..d26d45861 100644 --- a/components/driver/test/test_i2c.c +++ b/components/driver/test/test_i2c.c @@ -62,19 +62,6 @@ static esp_err_t i2c_master_write_slave(i2c_port_t i2c_num, uint8_t *data_wr, si 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) { 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()); } -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 bool test_read_func; diff --git a/components/driver/test/test_spi_param.c b/components/driver/test/test_spi_param.c index d1bfd1209..68fdc936b 100644 --- a/components/driver/test/test_spi_param.c +++ b/components/driver/test/test_spi_param.c @@ -429,551 +429,3 @@ static spitest_param_set_t 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]") diff --git a/components/driver/test/test_spi_sio.c b/components/driver/test/test_spi_sio.c index bba47097b..a203021d0 100644 --- a/components/driver/test/test_spi_sio.c +++ b/components/driver/test/test_spi_sio.c @@ -103,120 +103,3 @@ TEST_CASE("local test sio", "[spi]") spi_slave_free(TEST_SLAVE_HOST); 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); diff --git a/components/driver/test/test_uart.c b/components/driver/test/test_uart.c index 019604403..3283b9f6f 100644 --- a/components/driver/test/test_uart.c +++ b/components/driver/test/test_uart.c @@ -26,83 +26,6 @@ // 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 -}; - static void uart_config(uint32_t baud_rate, bool use_ref_tick) { uart_config_t uart_config = { @@ -203,177 +126,3 @@ TEST_CASE("test uart tx data with break", "[uart]") free(psend); 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); - diff --git a/components/esp_wifi/test/esp32/test_wifi.c b/components/esp_wifi/test/esp32/test_wifi.c new file mode 100644 index 000000000..5e601f322 --- /dev/null +++ b/components/esp_wifi/test/esp32/test_wifi.c @@ -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); \ No newline at end of file diff --git a/components/esp_wifi/test/test_wifi.c b/components/esp_wifi/test/test_wifi.c index 08996d9de..df6908e39 100644 --- a/components/esp_wifi/test/test_wifi.c +++ b/components/esp_wifi/test/test_wifi.c @@ -110,7 +110,7 @@ TEST_CASE("wifi stop and deinit","[wifi]") .password = DEFAULT_PWD }, }; - + //init nvs ESP_LOGI(TAG, EMPH_STR("nvs_flash_init")); esp_err_t r = nvs_flash_init(); @@ -118,7 +118,7 @@ TEST_CASE("wifi stop and deinit","[wifi]") ESP_LOGI(TAG, EMPH_STR("no free pages or nvs version mismatch, erase..")); TEST_ESP_OK(nvs_flash_erase()); r = nvs_flash_init(); - } + } TEST_ESP_OK(r); //init tcpip ESP_LOGI(TAG, EMPH_STR("tcpip_adapter_init")); @@ -126,7 +126,7 @@ TEST_CASE("wifi stop and deinit","[wifi]") //init event loop ESP_LOGI(TAG, EMPH_STR("esp_event_loop_init")); TEST_ESP_OK(esp_event_loop_init(event_handler, NULL)); - + ESP_LOGI(TAG, "test wifi init & deinit..."); test_wifi_init_deinit(&cfg, &wifi_config); ESP_LOGI(TAG, "wifi init & deinit seem to be OK."); @@ -140,175 +140,4 @@ TEST_CASE("wifi stop and deinit","[wifi]") ESP_LOGI(TAG, "test passed..."); 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); +} \ No newline at end of file diff --git a/tools/ci/config/target-test.yml b/tools/ci/config/target-test.yml index 368f207ac..bf9193f44 100644 --- a/tools/ci/config/target-test.yml +++ b/tools/ci/config/target-test.yml @@ -419,41 +419,6 @@ UT_031: - 7.2.2 - 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: extends: .test_template artifacts: