So I tried to power up codec (CS4272) together with my F401 board. After a lot of tweaking I got I2S to work and send data, but there were gaps. Upon further investigation it looks like HAL_I2SEx_TransmitReceive_IT doesn't return until it sends all of it's data.
for(int i=0;;i++)
{
for(int j=0;j<256;j++)
data[2*j]=16843009*(i%256);
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,1);
HAL_I2SEx_TransmitReceive_IT(&hi2s2,(uint16_t*)data,(uint16_t*)ret,128);
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,0);
//printf("dupa: %d\r\n",i);
}
Here is main loop from my test code. The rest is just cubeMX output. Logic analyser shows that I2S activity is only when C13 is HIGH. Why is so? How can it be fixed?
Here's is logic analyser trace of signals. On top there's C13 and I2S below. top C13, under data, LRCLk and SCLK respectively
As you can see the I2S transmit doesn't return until it's done. And no, C13 is not CS for codec but simply debug utility to track why I2S transmission executes so slowly
1 Answer 1
The calls ending with IT start a transfer that happens in the background and calls the transfer complete callback when done. Obviously, since you call it in a for loop, it starts one transfer and the HAL is busy, so further calls to it will fail until done or timeout elapses. You don't check the return value which would tell you it failed. Start a new transfer in the callback or use DMA with double or ring buffer.
HAL_I2SEx_TransmitReceive_IT
does return almost immediately. All it does is set up and start the interrupt-driven transfer. As such, your PC13 will only be high for a very brief period of time. \$\endgroup\$HAL_GPIO_WritePin()
calls, and useHAL_I2SEx_TransmitReceive()
(the non-interrupt version) instead. \$\endgroup\$Transmit_Receive_IT
doesn't return until it's done \$\endgroup\$