STM32L552 I2S DMA and CDC continuous transfer problem
I have an ADC connected to my MCU using I2S. MCU configured in I2S master receive mode. MCU supplying the ADC with 12MHZ MCLK. MCU sampling freq is 48 KHZ(Actual is 46.875 KHZ), Number of slots are 4, Data size is 16bits and I2S standard protocol. Using the Peripheral to Memory DMA in Normal mode, Half word data width, Medium priority.
DMA receive size is 188. Since the data size is half word, I am expecting 376 bytes. I choose this size to time 1 msec data.
HAL_SAI_Receive_DMA(&hsai_BlockB2, (uint8_t *)&i2s_adc_dma_data.sai_dma_data_buf[0], I2S_DMA_RX_SIZE);
I am sending the DMA data directly to PC through CDC. CDC Tx buff si
I2S Half complete callback:
usb_ret = CDC_Transmit_FS((uint8_t*)&i2s_adc_dma_data.sai_dma_data_buf[0], I2S_DMA_RX_SIZE);
I2S full complete callback:
usb_ret = CDC_Transmit_FS((uint8_t*)&i2s_adc_dma_data.sai_dma_data_buf[I2S_DMA_RX_SIZE], I2S_DMA_RX_SIZE);
My application requires continuous streaming of the ADC data to PC for 10 to 20 seconds. But I am not able to stream roughly more than 100 msec without loosing the DMA data. I am trying to find a way to sync the I2S DMA and USB CDC. Is it the host's problem that disturbing the transfer? If yes, what are the other options I have here?
void HAL_SAI_RxCpltCallback(SAI_HandleTypeDef *hsai)
{
uint8_t usb_ret;
if(i2s_adc_dma_data.start_i2s != false) {
HAL_SAI_Receive_DMA(&hsai_BlockB2, (uint8_t *)&i2s_adc_dma_data.sai_dma_data_buf[0], I2S_DMA_RX_SIZE);
//memcpy(&i2s_adc_dma_data.sai_data_buf_app[I2S_DMA_RX_SIZE], &i2s_adc_dma_data.sai_dma_data_buf[I2S_DMA_RX_SIZE], I2S_DMA_RX_SIZE);
//i2s_adc_dma_data.cdc_error = true;
if(cdc_status != TX_EVENT_INPROGRESS) {
usb_ret = CDC_Transmit_FS((uint8_t*)&i2s_adc_dma_data.sai_dma_data_buf[I2S_DMA_RX_SIZE], I2S_DMA_RX_SIZE);
i2s_adc_dma_data.cdc_error = false;
if (USBD_OK == usb_ret)
{
cdc_status = TX_EVENT_INPROGRESS;
}
else if(usb_ret != USBD_BUSY)
{
log_info("USB TX error. Stopping DMA");
HAL_SAI_Abort(&hsai_BlockB2);
i2s_adc_dma_data.cdc_error = true;
}
}
else if(cdc_status == TX_EVENT_INPROGRESS){ //Last transfer is still pending
log_info("Prev USB TX pending. Stopping DMA");
HAL_SAI_Abort(&hsai_BlockB2);
i2s_adc_dma_data.cdc_error = true;
}
}
}
void HAL_SAI_RxHalfCpltCallback(SAI_HandleTypeDef *hsai)
{
uint8_t usb_ret;
//memcpy(&i2s_adc_dma_data.sai_data_buf_app[0], &i2s_adc_dma_data.sai_dma_data_buf[0], I2S_DMA_RX_SIZE);
if(i2s_adc_dma_data.start_i2s != false && cdc_status != TX_EVENT_INPROGRESS) {
usb_ret = CDC_Transmit_FS((uint8_t*)&i2s_adc_dma_data.sai_dma_data_buf[0], I2S_DMA_RX_SIZE);
i2s_adc_dma_data.cdc_error = false;
if (USBD_OK == usb_ret)
{
cdc_status = TX_EVENT_INPROGRESS;
}
else if(usb_ret != USBD_BUSY)
{
log_info("USB TX error. Stopping DMA");
HAL_SAI_Abort(&hsai_BlockB2);
i2s_adc_dma_data.cdc_error = true;
}
}
else if(cdc_status == TX_EVENT_INPROGRESS){ //Last transfer is still pending
log_info("Prev USB TX pending. Stopping DMA");
HAL_SAI_Abort(&hsai_BlockB2);
i2s_adc_dma_data.cdc_error = true;
}
}
