1 /*
2  * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /*
8  Tests for the dac device driver on ESP32-S2 only
9 */
10 #include "sdkconfig.h"
11 #if CONFIG_IDF_TARGET_ESP32S2
12 
13 #include "esp_system.h"
14 #include "esp_intr_alloc.h"
15 #include "freertos/FreeRTOS.h"
16 #include "freertos/task.h"
17 #include "freertos/queue.h"
18 #include "driver/adc.h"
19 #include "driver/rtc_io.h"
20 #include "driver/gpio.h"
21 #include "unity.h"
22 #include "esp_system.h"
23 #include "esp_event.h"
24 #include "esp_wifi.h"
25 #include "esp_log.h"
26 #include "nvs_flash.h"
27 #include "test_utils.h"
28 #include "soc/soc.h"
29 #include "soc/spi_reg.h"
30 #include "soc/adc_periph.h"
31 #include "soc/dac_periph.h"
32 #include "soc/spi_periph.h"
33 #include "test/test_common_adc.h"
34 #include "driver/dac.h"
35 #include "soc/system_reg.h"
36 #include "esp32s2/rom/lldesc.h"
37 #include "test/test_adc_dac_dma.h"
38 
39 static const char *TAG = "test_adc";
40 
41 #define PLATFORM_SELECT            (1)  //0: pxp; 1: chip
42 #if (PLATFORM_SELECT == 0)              //PXP platform
43 #include "soc/syscon_reg.h"
44 #define SET_BREAK_POINT(flag) REG_WRITE(SYSCON_DATE_REG, flag)
45 //PXP clk is slower.
46 #define SYS_DELAY_TIME_MOM    (1/40)
47 #define RTC_SLOW_CLK_FLAG     1     // Slow clock is 32KHz.
test_pxp_deinit_io(void)48 static void test_pxp_deinit_io(void)
49 {
50     for (int i = 0; i < 22; i++) {
51         rtc_gpio_init(i);
52     }
53 }
54 #else
55 //PXP clk is slower.
56 #define SET_BREAK_POINT(flag)
57 #define SYS_DELAY_TIME_MOM    (1)
58 #define RTC_SLOW_CLK_FLAG     0     // Slow clock is 32KHz.
59 #endif
60 
61 #define SAR_SIMPLE_NUM  512  // Set out number of enabled unit.
62 
63 typedef struct dma_msg {
64     uint32_t int_msk;
65     uint8_t *data;
66     uint32_t data_len;
67 } dac_dma_event_t;
68 
69 static QueueHandle_t que_dac = NULL;
70 static uint8_t link_buf[2][SAR_SIMPLE_NUM*2] = {0};
71 static lldesc_t dma1 = {0};
72 static lldesc_t dma2 = {0};
73 
74 /*******************************************/
75 /**           DAC-DMA INIT CODE            */
76 /*******************************************/
77 
78 /**
79  * DMA liner initialization and start.
80  * @param is_loop
81  *     - true: The two dma linked lists are connected end to end, with no end mark (eof).
82  *     - false: The two dma linked lists are connected end to end, with end mark (eof).
83  * @param int_mask DMA interrupt types.
84  */
dac_dma_linker_init(bool is_alter,bool is_loop)85 uint32_t dac_dma_linker_init(bool is_alter, bool is_loop)
86 {
87     /* The DAC output is a sawtooth wave. */
88     if (is_alter) {
89         for(int i=0; i<SAR_SIMPLE_NUM*2; i++) {
90             if(i%2){
91                 link_buf[0][i] = i%256;
92             }else{
93                 link_buf[0][i] = 256-i%256;
94             }
95             if(i%2){
96                 link_buf[1][i] = i%256;
97             }else{
98                 link_buf[1][i] = 256-i%256;
99             }
100         }
101     } else {
102         for(int i=0; i<SAR_SIMPLE_NUM; i++) {
103             link_buf[0][i] = i%256;
104             link_buf[1][i] = i%256;
105         }
106     }
107     dma1 = (lldesc_t) {
108         .size = (is_alter) ? SAR_SIMPLE_NUM*2 : SAR_SIMPLE_NUM,
109         .length = (is_alter) ? SAR_SIMPLE_NUM*2 : SAR_SIMPLE_NUM,
110         .eof = 0,
111         .owner = 1,
112         .buf = &link_buf[0][0],
113         .qe.stqe_next = &dma2,
114     };
115     dma2 = (lldesc_t) {
116         .size = (is_alter) ? SAR_SIMPLE_NUM*2 : SAR_SIMPLE_NUM,
117         .length = (is_alter) ? SAR_SIMPLE_NUM*2 : SAR_SIMPLE_NUM,
118         .owner = 1,
119         .buf = &link_buf[1][0],
120     };
121     if (is_loop) {
122         dma2.eof = 0;
123         dma2.qe.stqe_next = &dma1;
124     } else {
125         dma2.eof = 1;
126         dma2.qe.stqe_next = NULL;
127     }
128     return (uint32_t)&dma1;
129 }
130 
131 /** ADC-DMA ISR handler. */
dac_dma_isr(void * arg)132 static IRAM_ATTR void dac_dma_isr(void * arg)
133 {
134     uint32_t int_st = REG_READ(SPI_DMA_INT_ST_REG(3));
135     int task_awoken = pdFALSE;
136     dac_dma_event_t adc_evt;
137     adc_evt.int_msk = int_st;
138     REG_WRITE(SPI_DMA_INT_CLR_REG(3), int_st);
139     xQueueSendFromISR(que_dac, &adc_evt, &task_awoken);
140     ESP_EARLY_LOGV(TAG, "int msk%x, raw%x", int_st, REG_READ(SPI_DMA_INT_RAW_REG(3)));
141 
142     if (task_awoken == pdTRUE) {
143         portYIELD_FROM_ISR();
144     }
145 }
146 
147 /**
148  * Testcase: Check the interrupt types of DAC-DMA.
149  */
test_dac_dig_dma_intr_check(dac_digi_convert_mode_t mode)150 void test_dac_dig_dma_intr_check(dac_digi_convert_mode_t mode)
151 {
152     ESP_LOGI(TAG, "  >> %s - dac mode %d<<  ", __func__, mode);
153 
154     dac_dma_event_t evt;
155 
156     dac_digi_init();
157     const dac_digi_config_t cfg = {
158         .mode = mode,
159         .interval = 100,
160         .dig_clk.use_apll = false,  // APB clk
161         .dig_clk.div_num = 79,
162         .dig_clk.div_b = 1,
163         .dig_clk.div_a = 0,
164     };
165     dac_digi_controller_config(&cfg);
166     dac_output_enable(DAC_CHANNEL_1);
167     dac_output_enable(DAC_CHANNEL_2);
168 
169     /* DAC-DMA linker init */
170     if (que_dac == NULL) {
171         que_dac = xQueueCreate(5, sizeof(dac_dma_event_t));
172     } else {
173         xQueueReset(que_dac);
174     }
175     uint32_t int_mask = SPI_OUT_DONE_INT_ENA | SPI_OUT_EOF_INT_ENA | SPI_OUT_TOTAL_EOF_INT_ENA;
176     uint32_t dma_addr = dac_dma_linker_init(mode, false);
177     adc_dac_dma_isr_register(dac_dma_isr, NULL, int_mask);
178     adc_dac_dma_linker_start(DMA_ONLY_DAC_OUTLINK, (void *)dma_addr, int_mask);
179 
180     /* ADC-DMA start output */
181     dac_digi_start();
182 
183     /* Check interrupt type */
184     while (int_mask) {
185         TEST_ASSERT_EQUAL( xQueueReceive(que_dac, &evt, 2000 / portTICK_RATE_MS), pdTRUE );
186         ESP_LOGI(TAG, "DAC-DMA intr type 0x%x", evt.int_msk);
187         if (evt.int_msk & int_mask) {
188             int_mask &= (~evt.int_msk);
189         }
190     }
191 
192     ESP_LOGI(TAG, "DAC-DMA intr test over");
193     adc_dac_dma_linker_deinit();
194     adc_dac_dma_isr_deregister(dac_dma_isr, NULL);
195     TEST_ESP_OK( dac_digi_deinit() );
196 }
197 
198 TEST_CASE("DAC-DMA interrupt test", "[dac]")
199 {
200     test_dac_dig_dma_intr_check(DAC_CONV_NORMAL);
201     test_dac_dig_dma_intr_check(DAC_CONV_ALTER);
202 }
203 
204 /*******************************************/
205 /**           SPI DMA INIT CODE            */
206 /*******************************************/
207 
208 #include "sys/queue.h"
209 static bool adc_dac_dma_isr_flag = false;
210 
211 /*---------------------------------------------------------------
212                         INTERRUPT HANDLER
213 ---------------------------------------------------------------*/
214 
215 typedef struct adc_dac_dma_isr_handler_ {
216     uint32_t mask;
217     intr_handler_t handler;
218     void* handler_arg;
219     SLIST_ENTRY(adc_dac_dma_isr_handler_) next;
220 } adc_dac_dma_isr_handler_t;
221 
222 static SLIST_HEAD(adc_dac_dma_isr_handler_list_, adc_dac_dma_isr_handler_) s_adc_dac_dma_isr_handler_list =
223         SLIST_HEAD_INITIALIZER(s_adc_dac_dma_isr_handler_list);
224 portMUX_TYPE s_isr_handler_list_lock = portMUX_INITIALIZER_UNLOCKED;
225 static intr_handle_t s_adc_dac_dma_isr_handle;
226 
adc_dac_dma_isr_default(void * arg)227 static IRAM_ATTR void adc_dac_dma_isr_default(void* arg)
228 {
229     uint32_t status = REG_READ(SPI_DMA_INT_ST_REG(3));
230     adc_dac_dma_isr_handler_t* it;
231     portENTER_CRITICAL_ISR(&s_isr_handler_list_lock);
232     SLIST_FOREACH(it, &s_adc_dac_dma_isr_handler_list, next) {
233         if (it->mask & status) {
234             portEXIT_CRITICAL_ISR(&s_isr_handler_list_lock);
235             (*it->handler)(it->handler_arg);
236             portENTER_CRITICAL_ISR(&s_isr_handler_list_lock);
237         }
238     }
239     portEXIT_CRITICAL_ISR(&s_isr_handler_list_lock);
240     REG_WRITE(SPI_DMA_INT_CLR_REG(3), status);
241 }
242 
adc_dac_dma_isr_ensure_installed(void)243 static esp_err_t adc_dac_dma_isr_ensure_installed(void)
244 {
245     esp_err_t err = ESP_OK;
246     portENTER_CRITICAL(&s_isr_handler_list_lock);
247     if (s_adc_dac_dma_isr_handle) {
248         goto out;
249     }
250     REG_WRITE(SPI_DMA_INT_ENA_REG(3), 0);
251     REG_WRITE(SPI_DMA_INT_CLR_REG(3), UINT32_MAX);
252     err = esp_intr_alloc(ETS_SPI3_DMA_INTR_SOURCE, 0, &adc_dac_dma_isr_default, NULL, &s_adc_dac_dma_isr_handle);
253     if (err != ESP_OK) {
254         goto out;
255     }
256 
257 out:
258     portEXIT_CRITICAL(&s_isr_handler_list_lock);
259     return err;
260 }
261 
adc_dac_dma_isr_register(intr_handler_t handler,void * handler_arg,uint32_t intr_mask)262 esp_err_t adc_dac_dma_isr_register(intr_handler_t handler, void* handler_arg, uint32_t intr_mask)
263 {
264     esp_err_t err = adc_dac_dma_isr_ensure_installed();
265     if (err != ESP_OK) {
266         return err;
267     }
268 
269     adc_dac_dma_isr_handler_t* item = malloc(sizeof(*item));
270     if (item == NULL) {
271         return ESP_ERR_NO_MEM;
272     }
273     item->handler = handler;
274     item->handler_arg = handler_arg;
275     item->mask = intr_mask;
276     portENTER_CRITICAL(&s_isr_handler_list_lock);
277     SLIST_INSERT_HEAD(&s_adc_dac_dma_isr_handler_list, item, next);
278     portEXIT_CRITICAL(&s_isr_handler_list_lock);
279     return ESP_OK;
280 }
281 
adc_dac_dma_isr_deregister(intr_handler_t handler,void * handler_arg)282 esp_err_t adc_dac_dma_isr_deregister(intr_handler_t handler, void* handler_arg)
283 {
284     adc_dac_dma_isr_handler_t* it;
285     adc_dac_dma_isr_handler_t* prev = NULL;
286     bool found = false;
287     portENTER_CRITICAL(&s_isr_handler_list_lock);
288     SLIST_FOREACH(it, &s_adc_dac_dma_isr_handler_list, next) {
289         if (it->handler == handler && it->handler_arg == handler_arg) {
290             if (it == SLIST_FIRST(&s_adc_dac_dma_isr_handler_list)) {
291                 SLIST_REMOVE_HEAD(&s_adc_dac_dma_isr_handler_list, next);
292             } else {
293                 SLIST_REMOVE_AFTER(prev, next);
294             }
295             found = true;
296             free(it);
297             break;
298         }
299         prev = it;
300     }
301     portEXIT_CRITICAL(&s_isr_handler_list_lock);
302     return found ? ESP_OK : ESP_ERR_INVALID_STATE;
303 }
304 
adc_dac_dma_linker_start(spi_dma_link_type_t type,void * dma_addr,uint32_t int_msk)305 void adc_dac_dma_linker_start(spi_dma_link_type_t type, void *dma_addr, uint32_t int_msk)
306 {
307     REG_SET_BIT(DPORT_PERIP_CLK_EN_REG, DPORT_APB_SARADC_CLK_EN_M);
308     REG_SET_BIT(DPORT_PERIP_CLK_EN_REG, DPORT_SPI3_DMA_CLK_EN_M);
309     REG_SET_BIT(DPORT_PERIP_CLK_EN_REG, DPORT_SPI3_CLK_EN);
310     REG_CLR_BIT(DPORT_PERIP_RST_EN_REG, DPORT_SPI3_DMA_RST_M);
311     REG_CLR_BIT(DPORT_PERIP_RST_EN_REG, DPORT_SPI3_RST_M);
312     REG_WRITE(SPI_DMA_INT_CLR_REG(3), 0xFFFFFFFF);
313     REG_WRITE(SPI_DMA_INT_ENA_REG(3), int_msk | REG_READ(SPI_DMA_INT_ENA_REG(3)));
314     if (type & DMA_ONLY_ADC_INLINK) {
315         REG_SET_BIT(SPI_DMA_IN_LINK_REG(3), SPI_INLINK_STOP);
316         REG_CLR_BIT(SPI_DMA_IN_LINK_REG(3), SPI_INLINK_START);
317         SET_PERI_REG_BITS(SPI_DMA_IN_LINK_REG(3), SPI_INLINK_ADDR, (uint32_t)dma_addr, 0);
318         REG_SET_BIT(SPI_DMA_CONF_REG(3), SPI_IN_RST);
319         REG_CLR_BIT(SPI_DMA_CONF_REG(3), SPI_IN_RST);
320         REG_CLR_BIT(SPI_DMA_IN_LINK_REG(3), SPI_INLINK_STOP);
321         REG_SET_BIT(SPI_DMA_IN_LINK_REG(3), SPI_INLINK_START);
322     }
323     if (type & DMA_ONLY_DAC_OUTLINK) {
324         REG_SET_BIT(SPI_DMA_OUT_LINK_REG(3), SPI_OUTLINK_STOP);
325         REG_CLR_BIT(SPI_DMA_OUT_LINK_REG(3), SPI_OUTLINK_START);
326         SET_PERI_REG_BITS(SPI_DMA_OUT_LINK_REG(3), SPI_OUTLINK_ADDR, (uint32_t)dma_addr, 0);
327         REG_SET_BIT(SPI_DMA_CONF_REG(3), SPI_OUT_RST);
328         REG_CLR_BIT(SPI_DMA_CONF_REG(3), SPI_OUT_RST);
329         REG_CLR_BIT(SPI_DMA_OUT_LINK_REG(3), SPI_OUTLINK_STOP);
330         REG_SET_BIT(SPI_DMA_OUT_LINK_REG(3), SPI_OUTLINK_START);
331     }
332 }
333 
adc_dac_dma_linker_stop(spi_dma_link_type_t type)334 void adc_dac_dma_linker_stop(spi_dma_link_type_t type)
335 {
336     if (type & DMA_ONLY_ADC_INLINK) {
337         REG_SET_BIT(SPI_DMA_IN_LINK_REG(3), SPI_INLINK_STOP);
338         REG_CLR_BIT(SPI_DMA_IN_LINK_REG(3), SPI_INLINK_START);
339     }
340     if (type & DMA_ONLY_DAC_OUTLINK) {
341         REG_SET_BIT(SPI_DMA_OUT_LINK_REG(3), SPI_OUTLINK_STOP);
342         REG_CLR_BIT(SPI_DMA_OUT_LINK_REG(3), SPI_OUTLINK_START);
343     }
344 }
345 
adc_dac_dma_linker_deinit(void)346 void adc_dac_dma_linker_deinit(void)
347 {
348     adc_dac_dma_linker_stop(DMA_BOTH_ADC_DAC);
349     REG_WRITE(SPI_DMA_INT_CLR_REG(3), 0xFFFFFFFF);
350     REG_WRITE(SPI_DMA_INT_ENA_REG(3), 0);
351     adc_dac_dma_isr_flag = false;
352 }
353 
354 /*******************************************/
355 /**           SPI DMA INIT CODE END        */
356 /*******************************************/
357 
358 #endif // CONFIG_IDF_TARGET_ESP32S2
359