1 /*
2  * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 #include "sdkconfig.h"
7 
8 #if CONFIG_IDF_TARGET_ESP32
9 
10 #include <stdio.h>
11 
12 #include "esp_types.h"
13 #include "freertos/FreeRTOS.h"
14 #include "freertos/task.h"
15 #include "freertos/semphr.h"
16 #include "freertos/queue.h"
17 #include "freertos/xtensa_api.h"
18 #include "unity.h"
19 #include "soc/uart_periph.h"
20 #include "soc/dport_reg.h"
21 #include "hal/gpio_hal.h"
22 #include "driver/gpio.h"
23 
24 
25 /*
26 This test tests the 'fast' peripherial bus at 0x3ff40000. This bus is connected directly to the core, and as such
27 can receive 'speculative' reads, that is, reads that may or may not actually be executed in the code flow. This
28 may mess with any FIFOs mapped in the region: if a byte gets dropped due to a missed speculative read, the fifo
29 may advance to the next byte anyway.
30 
31 This code tests reading/writing from the UART1 FIFO, using both cores. For this to work, it's required that the
32 UARTs RX and TX lines are connected.
33 */
34 
35 
36 void test_fastbus_cp(int fifo_addr, unsigned char *buf, int len, int *dummy);
37 
38 static volatile int state = 0;
39 static volatile int xor = 0;
40 static unsigned char res[128];
41 
tskOne(void * pvParameters)42 static void tskOne(void *pvParameters)
43 {
44     int run = 0, err = 0;
45     int x;
46     int ct[256];
47     volatile int w;
48     int dummy;
49     while (1) {
50         state = 1;
51         for (x = 0; x < 64; x++) {
52             WRITE_PERI_REG(UART_FIFO_REG(1), x ^ xor);
53         }
54         for (w = 0; w < (1 << 14); w++); //delay
55         state = 2;
56         test_fastbus_cp(UART_FIFO_REG(1), &res[0], 64, &dummy);
57         for (w = 0; w < (1 << 10); w++);    //delay
58         for (x = 0; x < 255; x++) {
59             ct[x] = 0;    //zero ctrs
60         }
61         for (x = 0; x < 128; x++) {
62             ct[(int)res[x]^xor]++;    //count values
63         }
64         for (x = 0; x < 255; x++) {         //check counts
65             if (ct[x] != (x < 128 ? 1 : 0)) {
66                 //Disregard first few loops; there may be crap in the fifo.
67                 if (run > 2) {
68                     err++;
69                     printf("Error! Received value %d %d times!\n", x, ct[x]);
70                 }
71             }
72         }
73         run++;
74         if ((run & 255) == 0) {
75             printf("Loop %d errct %d\n", run, err);
76         }
77         xor = (xor + 1) & 0xff;
78     }
79 }
80 
81 #define FB2ADDR 0x40098000
82 
tskTwo(void * pvParameters)83 static void tskTwo(void *pvParameters)
84 {
85     int x;
86     int dummy;
87     int *p = (int *)FB2ADDR;
88     int *s = (int *)test_fastbus_cp;
89     for (x = 0; x < 100; x++) {
90         *p++ = *s++;
91     }
92     void (*test_fastbus_cp2)(int fifo_addr, unsigned char * buf, int len, int * dummy) = (void *)FB2ADDR;
93 
94 
95     while (1) {
96         while (state != 1) ;
97         for (x = 64; x < 128; x++) {
98             WRITE_PERI_REG(UART_FIFO_REG(1), x ^ xor);
99         }
100         while (state != 2);
101         test_fastbus_cp2(UART_FIFO_REG(1), &res[64], 64, &dummy);
102     }
103 }
104 
105 
106 // TODO: split this thing into separate orthogonal tests
107 TEST_CASE("Fast I/O bus test", "[hw][ignore]")
108 {
109     int i;
110     if ((REG_UART_BASE(0) >> 16) != 0x3ff4) {
111         printf("Error! Uart base isn't on fast bus.\n");
112         TEST_ASSERT(0);
113     }
114 
115     gpio_pullup_dis(10);
116     gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_SD_DATA2_U, FUNC_SD_DATA2_U1RXD);
117     gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_SD_DATA3_U, FUNC_SD_DATA3_U1TXD);
118 
119     int reg_val = (1 << UART_RXFIFO_FULL_THRHD_S);
120     WRITE_PERI_REG(UART_CONF1_REG(1), reg_val);
121     WRITE_PERI_REG(UART_CLKDIV_REG(1), 0x30); //semi-random
122 //  CLEAR_PERI_REG_MASK(UART_INT_ENA_REG(1), UART_TXFIFO_EMPTY_INT_ENA|UART_RXFIFO_TOUT_INT_ENA);
123 
124     TaskHandle_t th[2];
125     printf("Creating tasks\n");
126     xTaskCreatePinnedToCore(tskOne  , "tskone"  , 2048, NULL, 3, &th[0], 0);
127     xTaskCreatePinnedToCore(tskTwo  , "tsktwo"  , 2048, NULL, 3, &th[1], 1);
128 
129     // Let stuff run for 20s
130     while (1) {
131         vTaskDelay(20000 / portTICK_PERIOD_MS);
132     }
133 
134     //Shut down all the tasks
135     for (i = 0; i < 2; i++) {
136         vTaskDelete(th[i]);
137     }
138     xt_ints_off(1 << ETS_UART0_INUM);
139 }
140 
141 #endif // CONFIG_IDF_TARGET_ESP32
142