I2S Input DMA setup

dawime
Posts: 6
Joined: Sat Aug 13, 2022 7:35 pm

I2S Input DMA setup

Postby dawime » Sun Mar 19, 2023 10:41 pm

Hello - I am trying to interface a mems I2C microphone to I2S0 - I have verified that the device is clocking and outputing data - The idea is to setup DMA buffers, to trigger an interrupt when DMA is complete, from the DMA ISR signal a task that will read out the last buffer, process it and notify other consumers for that data.

My problem seems to be that the DMA ISR is not getting set. I checked that the semaphores are setup properly, but I can't quite figure it out. Here is the code:
  1.  
  2. static int16_t dma_buf[DMA_BUF_COUNT][DMA_BUF_LEN];
  3. static int buf_ptr = 0;
  4. SemaphoreHandle_t i2s_dma_sem;
  5. static intr_handle_t i2s_isr_ret_handle;
  6.  
  7. void IRAM_ATTR i2s_isr_handler(void *arg)
  8. {
  9.     BaseType_t xHigherPriorityTaskWoken = pdFALSE;
  10.  
  11.     xSemaphoreGiveFromISR(i2s_dma_sem, &xHigherPriorityTaskWoken);
  12.     if (xHigherPriorityTaskWoken) {
  13.         portYIELD_FROM_ISR();
  14.     }
  15. }
  16.  
  17.  
  18. void mic_task(void *arg)
  19. {
  20.     size_t bytesRead;
  21.     color_t sample_colors[6] = { red, green, blue, yellow, purple, silver };
  22.     printf("mic_task enabled\n\r");
  23.     while (1)
  24.     {
  25.         if (xSemaphoreTake(i2s_dma_sem, portMAX_DELAY) == pdTRUE) {
  26.             // Process the data in dma_buf[buf_ptr]
  27.             // ...
  28.             i2s_read(I2S_NUM, (void *)&dma_buf[buf_ptr], DMA_BUF_LEN * sizeof(int16_t), &bytesRead, 0);
  29.             buf_ptr = (buf_ptr + 1) % DMA_BUF_COUNT;
  30.             printf("Read %d bytes",bytesRead);
  31.            
  32.             // Signal the main application that new data is available
  33.             // ...
  34.         }
  35.     }
  36. }
  37.  
  38. void mic_init()
  39. {
  40.     i2s_config_t i2s_config = {
  41.         .mode = I2S_MODE_MASTER | I2S_MODE_RX,
  42.         .sample_rate = 44100,
  43.         .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
  44.         .channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
  45.         .communication_format = I2S_COMM_FORMAT_I2S_MSB,
  46.         .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
  47.         .dma_buf_count = DMA_BUF_COUNT,
  48.         .dma_buf_len = DMA_BUF_LEN,
  49.         .use_apll = false,
  50.         .tx_desc_auto_clear = false,
  51.         .fixed_mclk = 0,
  52.        
  53.  
  54.     };
  55.     i2s_driver_install(I2S_NUM, &i2s_config, 0, NULL);
  56.     i2s_set_clk(I2S_NUM, 44100, I2S_BITS_PER_SAMPLE_16BIT, I2S_CHANNEL_MONO);
  57.     i2s_pin_config_t pin_config = {
  58.         .mck_io_num = I2S_PIN_NO_CHANGE,
  59.         .bck_io_num = 3,
  60.         .ws_io_num = I2S_PIN_NO_CHANGE,
  61.         .data_out_num = I2S_PIN_NO_CHANGE,
  62.         .data_in_num = 8
  63.     };
  64.     i2s_set_pin(I2S_NUM, &pin_config);
  65.     i2s_zero_dma_buffer(I2S_NUM);
  66.    
  67.     i2s_dma_sem = xSemaphoreCreateBinary();
  68.     esp_err_t err =esp_intr_alloc(ETS_I2S0_INTR_SOURCE, ESP_INTR_FLAG_LEVEL1 | ESP_INTR_FLAG_IRAM, i2s_isr_handler, NULL, &i2s_isr_ret_handle);
  69.     if (err != ESP_OK)
  70.         ESP_LOGE(TAG, "Error esp_intr_alloc %s", esp_err_to_name(err));
  71.  
  72.    
  73.     err = esp_intr_enable(i2s_isr_ret_handle);
  74.     ESP_LOGI(TAG, "INTERRUPT Enable:      %d ", err);
  75.     xTaskCreate(mic_task, "mic_task", 4096, NULL, 5, NULL);
  76.  
  77. }
Any ideas why i2s_isr_handler does not get called? Both esp_intr_alloc() and esp_intr_enable() return ESP_OK.

Thank you

ESP_Sprite
Posts: 9764
Joined: Thu Nov 26, 2015 4:08 am

Re: I2S Input DMA setup

Postby ESP_Sprite » Mon Mar 20, 2023 12:38 am

You cannot use both the driver as well as install your own ISR, and in your particular case, you don't need to. i2s_read() already suspends the calling task until the i2s peripheral has data available (that's why the driver needs the interrupt, it uses that to unblock the task calling i2s_read).

dawime
Posts: 6
Joined: Sat Aug 13, 2022 7:35 pm

Re: I2S Input DMA setup

Postby dawime » Mon Mar 20, 2023 2:36 pm

Thank you - I couldn't locate any documentation on it, but it makes sense. If the read will be blocking already, then I can forgo my interrupt and just running it on my thread directly.

Who is online

Users browsing this forum: Google [Bot] and 164 guests