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