My application is HTTP+SAI scenario. When I run the SAI alone, there is no problem. However, when I open the HTTP and send messages to the board, the callback of the SAI does not enter.
1.SAI captures the play using EDMA and uses the semaphore in the callback to synchronize the task so that it runs alone without a problem.
NVIC_SetPriority(DMA1_DMA17_IRQn, 2);//Set the priority to 2, otherwise the semaphore cannot be used
static void rx_callback(I2S_Type *base, sai_edma_handle_t *handle, status_t status, void *userData)
{
portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
if (kStatus_SAI_RxError == status)
{
/* Handle the error. */
}
else
{
emptyBlock--;
xSemaphoreGiveFromISR(xSemaphoreSai, &xHigherPriorityTaskWoken);
portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}
}
static void tx_callback(I2S_Type *base, sai_edma_handle_t *handle, status_t status, void *userData)
{
if (kStatus_SAI_TxError == status)
{
/* Handle the error. */
}
else
{
emptyBlock++;
}
}
...
...
...
void sai_task()
{
while (1)
{
if(emptyBlock > 0)
{
xfer.data = Buffer + rx_index * BUFFER_SIZE;
xfer.dataSize = BUFFER_SIZE;
if (kStatus_Success == SAI_TransferReceiveEDMA(DEMO_SAI, &rxHandle, &xfer))
{
rx_index++;
}
if (rx_index == BUFFER_NUMBER)
{
rx_index = 0U;
}
}
if(emptyBlock < BUFFER_NUMBER)
{
xSemaphoreTake(xSemaphoreSai, portMAX_DELAY);
xfer.data = Buffer + tx_index * BUFFER_SIZE;
xfer.dataSize = BUFFER_SIZE;
if (kStatus_Success == SAI_TransferSendEDMA(DEMO_SAI, &txHandle, &xfer))
{
tx_index++;
}
if (tx_index == BUFFER_NUMBER)
{
tx_index = 0U;
}
}
}
}
2.Add http service and send test data to board,Have a probability of causing rx_callback/tx_callback no call. I suspect it has something to do with semaphore
Hi,@jingpan
The block is because xSemaphoreTake(xSemaphoreSai, portMAX_DELAY);
If you set a timeout, When refreshing http, an error occurs causing SAI_TransferSendEDMA to return 1904,Cause audio distortion
Hi @jarman_zhou ,
Do you mean ISR is keeping receiving data but xSemaphoreTake() can't get semaphore?
Regards,
Jing
Hi,@jingpan
No, the block is because portMAX_DELAY is set.Setting a specific value will work.
However, if there is any other interruption, it will cause the audio data to become abnormal
Hi @jarman_zhou ,
If xSemaphoreTake() doesn't get semaphore, it will return errQUEUE_EMPTY. But you do not care about it because (emptyBlock < BUFFER_NUMBER). It will still copy data and process. The delay is useless here because new data is received. But if (emptyBlock < BUFFER_NUMBER) while queue still empty, something is wrong.
Regards,
Hi,@jingpan
The way it's written in the example, when I write if(emptyBlock < BUFFER_NUMBER), when processing data after sending, the ring buffer pointing to has been received to change, resulting in data distortion, how to avoid this problem?