1 /*
2  * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 #ifndef _TEST_COMMON_SPI_H_
7 #define _TEST_COMMON_SPI_H_
8 
9 #include <esp_types.h>
10 #include "driver/spi_master.h"
11 #include "freertos/FreeRTOS.h"
12 #include "freertos/ringbuf.h"
13 #include "freertos/task.h"
14 #include "unity.h"
15 #include "test_utils.h"
16 #include <string.h>
17 #include "param_test.h"
18 #include "soc/io_mux_reg.h"
19 #include "sdkconfig.h"
20 #include "soc/spi_periph.h"
21 
22 // All the tests using the header should use this definition as much as possible,
23 // so that the working host can be changed easily in the future.
24 #if CONFIG_IDF_TARGET_ESP32
25 #define TEST_SPI_HOST           SPI2_HOST
26 #define TEST_SLAVE_HOST         SPI3_HOST
27 
28 #define PIN_NUM_MISO            SPI2_IOMUX_PIN_NUM_MISO
29 #define PIN_NUM_MOSI            SPI2_IOMUX_PIN_NUM_MOSI
30 #define PIN_NUM_CLK             SPI2_IOMUX_PIN_NUM_CLK
31 #define PIN_NUM_CS              SPI2_IOMUX_PIN_NUM_CS
32 #define PIN_NUM_WP              SPI2_IOMUX_PIN_NUM_WP
33 #define PIN_NUM_HD              SPI2_IOMUX_PIN_NUM_HD
34 
35 #define MASTER_IOMUX_PIN_MISO   SPI2_IOMUX_PIN_NUM_MISO
36 #define MASTER_IOMUX_PIN_MOSI   SPI2_IOMUX_PIN_NUM_MOSI
37 #define MASTER_IOMUX_PIN_SCLK   SPI2_IOMUX_PIN_NUM_CLK
38 #define MASTER_IOMUX_PIN_CS     SPI2_IOMUX_PIN_NUM_CS
39 #define MASTER_IOMUX_PIN_WP     SPI2_IOMUX_PIN_NUM_WP
40 #define MASTER_IOMUX_PIN_HD     SPI2_IOMUX_PIN_NUM_HD
41 
42 #define SLAVE_IOMUX_PIN_MISO    SPI3_IOMUX_PIN_NUM_MISO
43 #define SLAVE_IOMUX_PIN_MOSI    SPI3_IOMUX_PIN_NUM_MOSI
44 #define SLAVE_IOMUX_PIN_SCLK    SPI3_IOMUX_PIN_NUM_CLK
45 #define SLAVE_IOMUX_PIN_CS      SPI3_IOMUX_PIN_NUM_CS
46 #define SLAVE_IOMUX_PIN_WP      SPI3_IOMUX_PIN_NUM_WP
47 #define SLAVE_IOMUX_PIN_HD      SPI3_IOMUX_PIN_NUM_HD
48 
49 #define UNCONNECTED_PIN         27
50 #define INPUT_ONLY_PIN          34
51 #define GPIO_DELAY              (12.5*2)
52 #define ESP_SPI_SLAVE_TV        (12.5*3.5)
53 #define WIRE_DELAY              12.5
54 
55 #elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
56 #define TEST_SPI_HOST           SPI2_HOST
57 #define TEST_SLAVE_HOST         SPI3_HOST
58 
59 #define PIN_NUM_MISO            SPI2_IOMUX_PIN_NUM_MISO
60 #define PIN_NUM_MOSI            SPI2_IOMUX_PIN_NUM_MOSI
61 #define PIN_NUM_CLK             SPI2_IOMUX_PIN_NUM_CLK
62 #define PIN_NUM_CS              SPI2_IOMUX_PIN_NUM_CS
63 #define PIN_NUM_WP              SPI2_IOMUX_PIN_NUM_WP
64 #define PIN_NUM_HD              SPI2_IOMUX_PIN_NUM_HD
65 
66 #define MASTER_IOMUX_PIN_MISO   SPI2_IOMUX_PIN_NUM_MISO
67 #define MASTER_IOMUX_PIN_MOSI   SPI2_IOMUX_PIN_NUM_MOSI
68 #define MASTER_IOMUX_PIN_SCLK   SPI2_IOMUX_PIN_NUM_CLK
69 #define MASTER_IOMUX_PIN_CS     SPI2_IOMUX_PIN_NUM_CS
70 #define MASTER_IOMUX_PIN_WP     SPI2_IOMUX_PIN_NUM_WP
71 #define MASTER_IOMUX_PIN_HD     SPI2_IOMUX_PIN_NUM_HD
72 
73 #define SLAVE_IOMUX_PIN_MISO    -1
74 #define SLAVE_IOMUX_PIN_MOSI    -1
75 #define SLAVE_IOMUX_PIN_SCLK    -1
76 #define SLAVE_IOMUX_PIN_CS      -1
77 #define SLAVE_IOMUX_PIN_NUM_WP  -1
78 #define SLAVE_IOMUX_PIN_NUM_HD  -1
79 
80 #define UNCONNECTED_PIN         41
81 #define INPUT_ONLY_PIN          46
82 #define GPIO_DELAY              0
83 #define ESP_SPI_SLAVE_TV        0
84 #define WIRE_DELAY              12.5
85 
86 #elif CONFIG_IDF_TARGET_ESP32C3
87 //NOTE: On esp32c3, there is only 1 GPSPI controller, so master-slave test on single board should be disabled
88 #define TEST_SPI_HOST           SPI2_HOST
89 #define TEST_SLAVE_HOST         SPI2_HOST
90 
91 #define PIN_NUM_MISO            SPI2_IOMUX_PIN_NUM_MISO
92 #define PIN_NUM_MOSI            SPI2_IOMUX_PIN_NUM_MOSI
93 #define PIN_NUM_CLK             SPI2_IOMUX_PIN_NUM_CLK
94 #define PIN_NUM_CS              SPI2_IOMUX_PIN_NUM_CS
95 #define PIN_NUM_WP              SPI2_IOMUX_PIN_NUM_WP
96 #define PIN_NUM_HD              SPI2_IOMUX_PIN_NUM_HD
97 
98 #define SLAVE_IOMUX_PIN_MISO    SPI2_IOMUX_PIN_NUM_MISO
99 #define SLAVE_IOMUX_PIN_MOSI    SPI2_IOMUX_PIN_NUM_MOSI
100 #define SLAVE_IOMUX_PIN_SCLK    SPI2_IOMUX_PIN_NUM_CLK
101 #define SLAVE_IOMUX_PIN_CS      SPI2_IOMUX_PIN_NUM_CS
102 
103 #define MASTER_IOMUX_PIN_MISO   SPI2_IOMUX_PIN_NUM_MISO
104 #define MASTER_IOMUX_PIN_MOSI   SPI2_IOMUX_PIN_NUM_MOSI
105 #define MASTER_IOMUX_PIN_SCLK   SPI2_IOMUX_PIN_NUM_CLK
106 #define MASTER_IOMUX_PIN_CS     SPI2_IOMUX_PIN_NUM_CS
107 
108 #define GPIO_DELAY              0
109 #define ESP_SPI_SLAVE_TV        0
110 #define WIRE_DELAY              12.5
111 #endif
112 
113 #define GET_DMA_CHAN(HOST)      (HOST)
114 
115 #define TEST_DMA_CHAN_MASTER    GET_DMA_CHAN(TEST_SPI_HOST)
116 #define TEST_DMA_CHAN_SLAVE     GET_DMA_CHAN(TEST_SLAVE_HOST)
117 
118 
119 #define FUNC_SPI    1
120 #define FUNC_GPIO   PIN_FUNC_GPIO
121 
122 //Delay information
123 #define TV_INT_CONNECT_GPIO     (ESP_SPI_SLAVE_TV+GPIO_DELAY)
124 #define TV_INT_CONNECT          (ESP_SPI_SLAVE_TV)
125 //when connecting to another board, the delay is usually increased by 12.5ns
126 #define TV_WITH_ESP_SLAVE_GPIO  (TV_INT_CONNECT_GPIO+WIRE_DELAY)
127 #define TV_WITH_ESP_SLAVE       (TV_INT_CONNECT+WIRE_DELAY)
128 
129 //currently ESP32 slave only supports up to 20MHz, but 40MHz on the same board
130 #define ESP_SPI_SLAVE_MAX_FREQ      SPI_MASTER_FREQ_20M
131 #define ESP_SPI_SLAVE_MAX_FREQ_SYNC SPI_MASTER_FREQ_40M
132 
133 #define MAX_TEST_SIZE   16  ///< in this test we run several transactions, this is the maximum trans that can be run
134 #define PSET_NAME_LEN   30  ///< length of each param set name
135 
136 //test low frequency, high frequency until freq limit for worst case (both GPIO)
137 #define TEST_FREQ_DEFAULT(){    \
138         1*1000*1000,            \
139         SPI_MASTER_FREQ_8M ,    \
140         SPI_MASTER_FREQ_9M ,    \
141         SPI_MASTER_FREQ_10M,    \
142         SPI_MASTER_FREQ_11M,    \
143         SPI_MASTER_FREQ_13M,    \
144         SPI_MASTER_FREQ_16M,    \
145         SPI_MASTER_FREQ_20M,    \
146         SPI_MASTER_FREQ_26M,    \
147         SPI_MASTER_FREQ_40M,    \
148         SPI_MASTER_FREQ_80M,    \
149         0,\
150     }
151 
152 //default bus config for tests
153 #define SPI_BUS_TEST_DEFAULT_CONFIG() {\
154         .miso_io_num=PIN_NUM_MISO, \
155         .mosi_io_num=PIN_NUM_MOSI,\
156         .sclk_io_num=PIN_NUM_CLK,\
157         .quadwp_io_num=-1,\
158         .quadhd_io_num=-1\
159     }
160 
161 //default device config for master devices
162 #define SPI_DEVICE_TEST_DEFAULT_CONFIG()    {\
163         .clock_speed_hz=10*1000*1000,\
164         .mode=0,\
165         .spics_io_num=PIN_NUM_CS,\
166         .queue_size=16,\
167         .pre_cb=NULL,  \
168         .cs_ena_pretrans = 0,\
169         .cs_ena_posttrans = 0,\
170         .input_delay_ns = 62.5,\
171     }
172 
173 //default device config for slave devices
174 #define SPI_SLAVE_TEST_DEFAULT_CONFIG() {\
175         .mode=0,\
176         .spics_io_num=PIN_NUM_CS,\
177         .queue_size=3,\
178         .flags=0,\
179     }
180 
181 typedef enum {
182     FULL_DUPLEX = 0,
183     HALF_DUPLEX_MISO = 1,
184     HALF_DUPLEX_MOSI = 2,
185 } spi_dup_t;
186 
187 /*-------- slave task related stuff -----------*/
188 typedef struct {
189     uint32_t len;
190     uint8_t* tx_start;
191     uint8_t data[1];
192 } slave_rxdata_t;
193 
194 typedef struct {
195     uint32_t len;
196     const uint8_t *start;
197 } slave_txdata_t;
198 
199 typedef struct {
200     spi_host_device_t spi;
201     RingbufHandle_t data_received;
202     QueueHandle_t data_to_send;
203 } spi_slave_task_context_t;
204 
205 // test data for master and slave
206 extern uint8_t spitest_master_send[];
207 extern uint8_t spitest_slave_send[];
208 
209 //tags for master and slave app
210 extern const char MASTER_TAG[];
211 extern const char SLAVE_TAG[];
212 
213 //parameter set definition
214 typedef struct {
215     const char pset_name[PSET_NAME_LEN];
216     /*The test work till the frequency below,
217      *set the frequency to higher and remove checks in the driver to know how fast the system can run.
218      */
219     const int *freq_list;     // list of tested frequency, terminated by 0
220     int freq_limit;     //freq larger (not equal) than this will be ignored
221     spi_dup_t dup;
222     int mode;
223     bool length_aligned;
224     int test_size;
225 
226     int master_limit;   // the master disable dummy bits and discard readings over this freq
227     bool master_iomux;
228     int master_dma_chan;
229 
230     bool slave_iomux;
231     int slave_dma_chan;
232     int slave_tv_ns;
233     bool slave_unaligned_addr;
234 } spitest_param_set_t;
235 
236 //context definition for the parameterized test
237 typedef struct {
238     uint8_t master_rxbuf[480];
239     spi_transaction_t master_trans[MAX_TEST_SIZE];
240     TaskHandle_t handle_slave;
241     spi_slave_task_context_t slave_context;
242     slave_txdata_t slave_trans[MAX_TEST_SIZE];
243 } spitest_context_t;
244 
245 // fill default value of spitest_param_set_t
246 void spitest_def_param(void* arg);
247 
248 // functions for slave task
249 esp_err_t init_slave_context(spi_slave_task_context_t *context);
250 void deinit_slave_context(spi_slave_task_context_t *context);
251 void spitest_slave_task(void* arg);
252 
253 //called by slave, pull-up all pins used by slave
254 void slave_pull_up(const spi_bus_config_t* cfg, int spics_io_num);
255 
256 // to access data of pre-defined transactions.
257 void spitest_init_transactions(const spitest_param_set_t *cfg, spitest_context_t* context);
258 
259 // print data from a transaction
260 void spitest_master_print_data(spi_transaction_t *t, int rxlength);
261 void spitest_slave_print_data(slave_rxdata_t *t, bool print_rxdata);
262 // Check whether master and slave data match
263 esp_err_t spitest_check_data(int len, spi_transaction_t *master_t, slave_rxdata_t *slave_t, bool check_master_data, bool check_slave_len, bool check_slave_data);
264 
265 #define spitest_cmp_or_dump(expected, actual, len) ({\
266     int r = memcmp(expected, actual, len);\
267     if (r != 0) {\
268         ESP_LOG_BUFFER_HEXDUMP("expected", expected, len, ESP_LOG_INFO);\
269         ESP_LOG_BUFFER_HEXDUMP("actual", actual, len, ESP_LOG_WARN);\
270         TEST_ASSERT_EQUAL_HEX8_ARRAY(expected, actual, len);\
271     }\
272     r;\
273 })
274 
get_trans_len(spi_dup_t dup,spi_transaction_t * master_t)275 static inline int get_trans_len(spi_dup_t dup, spi_transaction_t *master_t)
276 {
277     if (dup!=HALF_DUPLEX_MISO) {
278         return master_t->length;
279     } else {
280         return master_t->rxlength;
281     }
282 }
283 //remove device from bus and free the bus
284 void master_free_device_bus(spi_device_handle_t spi);
285 
286 //use this function to fix the output source when assign multiple funcitons to a same pin
287 void spitest_gpio_output_sel(uint32_t gpio_num, int func, uint32_t signal_idx);
288 
289 //use this function to fix the input source when assign multiple funcitons to a same pin
290 void spitest_gpio_input_sel(uint32_t gpio_num, int func, uint32_t signal_idx);
291 
292 //Note this cs_num is the ID of the connected devices' ID, e.g. if 2 devices are connected to the bus,
293 //then the cs_num of the 1st and 2nd devices are 0 and 1 respectively.
294 void same_pin_func_sel(spi_bus_config_t bus, spi_device_interface_config_t dev, uint8_t cs_num);
295 
296 /**
297  * This function is used to get tx_buffer used in dual-board test
298  */
299 void get_tx_buffer(uint32_t seed, uint8_t *master_send_buf, uint8_t *slave_send_buf, int send_buf_size);
300 #endif  //_TEST_COMMON_SPI_H_
301