2020-12-03 9:30 AM - last edited on 2024-07-03 3:23 AM by Andrew Neil
Hey,
I am using a STM32F7676vit6 Controller an try to set up a SAI connection to my audio CODEC now my problem is that the CODEC has two Serial outputs and one serial input. So i configured:
SAI1A to be the transmitting master SAI1B is a synchronous Slave which is configured to be in sync with SAI1A. SAI2B is also configured a synchronous Slave and configured to be in sync with SAI1A. I also use DMA on all three channels.
Now i receive data on SAI1B and but not on SAI2B (SAI1A works fine). Only wired thing is that after txCpltCallback the SCK and FS do not stop....
I really don't know what to try anymore please help ;).
I use CubeIDE my sai.c file looks like:
/* Includes ------------------------------------------------------------------*/
#include "sai.h"
#include "gpio.h"
#include "dma.h"
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
SAI_HandleTypeDef hsai_BlockA1;
SAI_HandleTypeDef hsai_BlockB1;
SAI_HandleTypeDef hsai_BlockB2;
DMA_HandleTypeDef hdma_sai1_a;
DMA_HandleTypeDef hdma_sai1_b;
DMA_HandleTypeDef hdma_sai2_b;
/* SAI1 init function */
void MX_SAI1_Init(void)
{
hsai_BlockA1.Instance = SAI1_Block_A;
hsai_BlockA1.Init.AudioMode = SAI_MODEMASTER_TX;
hsai_BlockA1.Init.Synchro = SAI_ASYNCHRONOUS;
hsai_BlockA1.Init.OutputDrive = SAI_OUTPUTDRIVE_DISABLE;
hsai_BlockA1.Init.NoDivider = SAI_MASTERDIVIDER_ENABLE;
hsai_BlockA1.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_EMPTY;
hsai_BlockA1.Init.AudioFrequency = SAI_AUDIO_FREQUENCY_192K;
hsai_BlockA1.Init.SynchroExt = SAI_SYNCEXT_DISABLE;
hsai_BlockA1.Init.MonoStereoMode = SAI_STEREOMODE;
hsai_BlockA1.Init.CompandingMode = SAI_NOCOMPANDING;
hsai_BlockA1.Init.TriState = SAI_OUTPUT_NOTRELEASED;
if (HAL_SAI_InitProtocol(&hsai_BlockA1, SAI_I2S_LSBJUSTIFIED, SAI_PROTOCOL_DATASIZE_32BIT, 2) != HAL_OK)
{
Error_Handler();
}
hsai_BlockB1.Instance = SAI1_Block_B;
hsai_BlockB1.Init.AudioMode = SAI_MODESLAVE_RX;
hsai_BlockB1.Init.Synchro = SAI_SYNCHRONOUS;
hsai_BlockB1.Init.OutputDrive = SAI_OUTPUTDRIVE_DISABLE;
hsai_BlockB1.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_EMPTY;
hsai_BlockB1.Init.SynchroExt = SAI_SYNCEXT_DISABLE;
hsai_BlockB1.Init.MonoStereoMode = SAI_STEREOMODE;
hsai_BlockB1.Init.CompandingMode = SAI_NOCOMPANDING;
hsai_BlockB1.Init.TriState = SAI_OUTPUT_NOTRELEASED;
if (HAL_SAI_InitProtocol(&hsai_BlockB1, SAI_I2S_STANDARD, SAI_PROTOCOL_DATASIZE_32BIT, 2) != HAL_OK)
{
Error_Handler();
}
}
/* SAI2 init function */
void MX_SAI2_Init(void)
{
hsai_BlockB2.Instance = SAI2_Block_B;
hsai_BlockB2.Init.AudioMode = SAI_MODESLAVE_RX;
hsai_BlockB2.Init.Synchro = SAI_SYNCHRONOUS_EXT_SAI1;
hsai_BlockB2.Init.OutputDrive = SAI_OUTPUTDRIVE_DISABLE;
hsai_BlockB2.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_EMPTY;
hsai_BlockB2.Init.MonoStereoMode = SAI_STEREOMODE;
hsai_BlockB2.Init.CompandingMode = SAI_NOCOMPANDING;
hsai_BlockB2.Init.TriState = SAI_OUTPUT_NOTRELEASED;
if (HAL_SAI_InitProtocol(&hsai_BlockB2, SAI_I2S_STANDARD, SAI_PROTOCOL_DATASIZE_32BIT, 2) != HAL_OK)
{
Error_Handler();
}
}
static uint32_t SAI1_client =0;
static uint32_t SAI2_client =0;
void HAL_SAI_MspInit(SAI_HandleTypeDef* hsai)
{
GPIO_InitTypeDef GPIO_InitStruct;
/* SAI1 */
if(hsai->Instance==SAI1_Block_A)
{
/* SAI1 clock enable */
if (SAI1_client == 0)
{
__HAL_RCC_SAI1_CLK_ENABLE();
}
SAI1_client ++;
/**SAI1_A_Block_A GPIO Configuration
PE4 ------> SAI1_FS_A
PE5 ------> SAI1_SCK_A
PE6 ------> SAI1_SD_A
*/
GPIO_InitStruct.Pin = SAI1A_FS_Pin|SAI1A_SCK_Pin|SAI1A_DAC_SDATA_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF6_SAI1;
HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
/* Peripheral DMA init*/
hdma_sai1_a.Instance = DMA2_Stream1;
hdma_sai1_a.Init.Channel = DMA_CHANNEL_0;
hdma_sai1_a.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_sai1_a.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_sai1_a.Init.MemInc = DMA_MINC_ENABLE;
hdma_sai1_a.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
hdma_sai1_a.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
hdma_sai1_a.Init.Mode = DMA_NORMAL;
hdma_sai1_a.Init.Priority = DMA_PRIORITY_LOW;
hdma_sai1_a.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
if (HAL_DMA_Init(&hdma_sai1_a) != HAL_OK)
{
Error_Handler();
}
/* Several peripheral DMA handle pointers point to the same DMA handle.
Be aware that there is only one stream to perform all the requested DMAs. */
__HAL_LINKDMA(hsai,hdmarx,hdma_sai1_a);
__HAL_LINKDMA(hsai,hdmatx,hdma_sai1_a);
}
if(hsai->Instance==SAI1_Block_B)
{
/* SAI1 clock enable */
if (SAI1_client == 0)
{
__HAL_RCC_SAI1_CLK_ENABLE();
}
SAI1_client ++;
/**SAI1_B_Block_B GPIO Configuration
PE3 ------> SAI1_SD_B
*/
GPIO_InitStruct.Pin = GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF6_SAI1;
HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
/* Peripheral DMA init*/
hdma_sai1_b.Instance = DMA2_Stream5;
hdma_sai1_b.Init.Channel = DMA_CHANNEL_0;
hdma_sai1_b.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_sai1_b.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_sai1_b.Init.MemInc = DMA_MINC_ENABLE;
hdma_sai1_b.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
hdma_sai1_b.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
hdma_sai1_b.Init.Mode = DMA_NORMAL;
hdma_sai1_b.Init.Priority = DMA_PRIORITY_LOW;
hdma_sai1_b.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
if (HAL_DMA_Init(&hdma_sai1_b) != HAL_OK)
{
Error_Handler();
}
/* Several peripheral DMA handle pointers point to the same DMA handle.
Be aware that there is only one stream to perform all the requested DMAs. */
__HAL_LINKDMA(hsai,hdmarx,hdma_sai1_b);
__HAL_LINKDMA(hsai,hdmatx,hdma_sai1_b);
}
/* SAI2 */
if(hsai->Instance==SAI2_Block_B)
{
/* SAI2 clock enable */
if (SAI2_client == 0)
{
__HAL_RCC_SAI2_CLK_ENABLE();
}
SAI2_client ++;
/**SAI2_B_Block_B GPIO Configuration
PA0/WKUP ------> SAI2_SD_B
*/
GPIO_InitStruct.Pin = GPIO_PIN_0;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF10_SAI2;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* Peripheral DMA init*/
hdma_sai2_b.Instance = DMA2_Stream6;
hdma_sai2_b.Init.Channel = DMA_CHANNEL_3;
hdma_sai2_b.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_sai2_b.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_sai2_b.Init.MemInc = DMA_MINC_ENABLE;
hdma_sai2_b.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
hdma_sai2_b.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
hdma_sai2_b.Init.Mode = DMA_NORMAL;
hdma_sai2_b.Init.Priority = DMA_PRIORITY_LOW;
hdma_sai2_b.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
if (HAL_DMA_Init(&hdma_sai2_b) != HAL_OK)
{
Error_Handler();
}
/* Several peripheral DMA handle pointers point to the same DMA handle.
Be aware that there is only one stream to perform all the requested DMAs. */
__HAL_LINKDMA(hsai,hdmarx,hdma_sai2_b);
__HAL_LINKDMA(hsai,hdmatx,hdma_sai2_b);
}
}
void HAL_SAI_MspDeInit(SAI_HandleTypeDef* hsai)
{
/* SAI1 */
if(hsai->Instance==SAI1_Block_A)
{
SAI1_client --;
if (SAI1_client == 0)
{
/* Peripheral clock disable */
__HAL_RCC_SAI1_CLK_DISABLE();
}
/**SAI1_A_Block_A GPIO Configuration
PE4 ------> SAI1_FS_A
PE5 ------> SAI1_SCK_A
PE6 ------> SAI1_SD_A
*/
HAL_GPIO_DeInit(GPIOE, SAI1A_FS_Pin|SAI1A_SCK_Pin|SAI1A_DAC_SDATA_Pin);
HAL_DMA_DeInit(hsai->hdmarx);
HAL_DMA_DeInit(hsai->hdmatx);
}
if(hsai->Instance==SAI1_Block_B)
{
SAI1_client --;
if (SAI1_client == 0)
{
/* Peripheral clock disable */
__HAL_RCC_SAI1_CLK_DISABLE();
}
/**SAI1_B_Block_B GPIO Configuration
PE3 ------> SAI1_SD_B
*/
HAL_GPIO_DeInit(GPIOE, GPIO_PIN_3);
HAL_DMA_DeInit(hsai->hdmarx);
HAL_DMA_DeInit(hsai->hdmatx);
}
/* SAI2 */
if(hsai->Instance==SAI2_Block_B)
{
SAI2_client --;
if (SAI2_client == 0)
{
/* Peripheral clock disable */
__HAL_RCC_SAI2_CLK_DISABLE();
}
/**SAI2_B_Block_B GPIO Configuration
PA0/WKUP ------> SAI2_SD_B
*/
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_0);
HAL_DMA_DeInit(hsai->hdmarx);
HAL_DMA_DeInit(hsai->hdmatx);
}
}
To make sure that every thing works in sync i first start both receiving Block and than the Transmitting one like:
HAL_SAI_Receive_DMA(&hsai_BlockB1, (uint8_t*) &meas->BufferADC23[0], BufferSize); //ADC 01 HAL_SAI_Receive_DMA(&hsai_BlockB2, (uint8_t*) &meas->BufferADC01[0], BufferSize); //ADC 23 HAL_SAI_Transmit_DMA(&hsai_BlockA1, (uint8_t*) &LookupTable[0], LookupTableSize); //DAC 01
I am very grateful for any help
Solved! Go to Solution.
2020-12-04 3:43 AM
Hey,
I have found the root cause i think:
It seams that even if I configure the "External Synchro Out" Signal in the STM32CubeIDE that the init function, does not care about it.
Remains unchanged! To me that looks clearly like a bug from the STM32CubeIDE.
hsai_BlockA1.Init.SynchroExt = SAI_SYNCEXT_DISABLE;
/* SAI1 init function */
void MX_SAI1_Init(void)
{
hsai_BlockA1.Instance = SAI1_Block_A;
hsai_BlockA1.Init.AudioMode = SAI_MODEMASTER_TX;
hsai_BlockA1.Init.Synchro = SAI_ASYNCHRONOUS;
hsai_BlockA1.Init.OutputDrive = SAI_OUTPUTDRIVE_DISABLE;
hsai_BlockA1.Init.NoDivider = SAI_MASTERDIVIDER_ENABLE;
hsai_BlockA1.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_EMPTY;
hsai_BlockA1.Init.AudioFrequency = SAI_AUDIO_FREQUENCY_192K;
hsai_BlockA1.Init.SynchroExt = SAI_SYNCEXT_DISABLE;
hsai_BlockA1.Init.MonoStereoMode = SAI_STEREOMODE;
hsai_BlockA1.Init.CompandingMode = SAI_NOCOMPANDING;
hsai_BlockA1.Init.TriState = SAI_OUTPUT_NOTRELEASED;
if (HAL_SAI_InitProtocol(&hsai_BlockA1, SAI_I2S_LSBJUSTIFIED, SAI_PROTOCOL_DATASIZE_32BIT, 2) != HAL_OK)
{
Error_Handler();
}
hsai_BlockB1.Instance = SAI1_Block_B;
hsai_BlockB1.Init.AudioMode = SAI_MODESLAVE_RX;
hsai_BlockB1.Init.Synchro = SAI_SYNCHRONOUS;
hsai_BlockB1.Init.OutputDrive = SAI_OUTPUTDRIVE_DISABLE;
hsai_BlockB1.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_EMPTY;
hsai_BlockB1.Init.SynchroExt = SAI_SYNCEXT_DISABLE;
hsai_BlockB1.Init.MonoStereoMode = SAI_STEREOMODE;
hsai_BlockB1.Init.CompandingMode = SAI_NOCOMPANDING;
hsai_BlockB1.Init.TriState = SAI_OUTPUT_NOTRELEASED;
if (HAL_SAI_InitProtocol(&hsai_BlockB1, SAI_I2S_STANDARD, SAI_PROTOCOL_DATASIZE_32BIT, 2) != HAL_OK)
{
Error_Handler();
}To fix that and enable the first block SAI1 to output the external sync signal, it is necessary to manually configure both sub-Blocks of the SAI1:
hsai_BlockA1.Init.SynchroExt = SAI_SYNCEXT_OUTBLOCKA_ENABLE;
hsai_BlockB1.Init.SynchroExt = SAI_SYNCEXT_OUTBLOCKA_ENABLE;I hope that i can help others which might run into similar problems.
Cheers,
Luca
2020-12-04 3:43 AM
Hey,
I have found the root cause i think:
It seams that even if I configure the "External Synchro Out" Signal in the STM32CubeIDE that the init function, does not care about it.
Remains unchanged! To me that looks clearly like a bug from the STM32CubeIDE.
hsai_BlockA1.Init.SynchroExt = SAI_SYNCEXT_DISABLE;
/* SAI1 init function */
void MX_SAI1_Init(void)
{
hsai_BlockA1.Instance = SAI1_Block_A;
hsai_BlockA1.Init.AudioMode = SAI_MODEMASTER_TX;
hsai_BlockA1.Init.Synchro = SAI_ASYNCHRONOUS;
hsai_BlockA1.Init.OutputDrive = SAI_OUTPUTDRIVE_DISABLE;
hsai_BlockA1.Init.NoDivider = SAI_MASTERDIVIDER_ENABLE;
hsai_BlockA1.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_EMPTY;
hsai_BlockA1.Init.AudioFrequency = SAI_AUDIO_FREQUENCY_192K;
hsai_BlockA1.Init.SynchroExt = SAI_SYNCEXT_DISABLE;
hsai_BlockA1.Init.MonoStereoMode = SAI_STEREOMODE;
hsai_BlockA1.Init.CompandingMode = SAI_NOCOMPANDING;
hsai_BlockA1.Init.TriState = SAI_OUTPUT_NOTRELEASED;
if (HAL_SAI_InitProtocol(&hsai_BlockA1, SAI_I2S_LSBJUSTIFIED, SAI_PROTOCOL_DATASIZE_32BIT, 2) != HAL_OK)
{
Error_Handler();
}
hsai_BlockB1.Instance = SAI1_Block_B;
hsai_BlockB1.Init.AudioMode = SAI_MODESLAVE_RX;
hsai_BlockB1.Init.Synchro = SAI_SYNCHRONOUS;
hsai_BlockB1.Init.OutputDrive = SAI_OUTPUTDRIVE_DISABLE;
hsai_BlockB1.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_EMPTY;
hsai_BlockB1.Init.SynchroExt = SAI_SYNCEXT_DISABLE;
hsai_BlockB1.Init.MonoStereoMode = SAI_STEREOMODE;
hsai_BlockB1.Init.CompandingMode = SAI_NOCOMPANDING;
hsai_BlockB1.Init.TriState = SAI_OUTPUT_NOTRELEASED;
if (HAL_SAI_InitProtocol(&hsai_BlockB1, SAI_I2S_STANDARD, SAI_PROTOCOL_DATASIZE_32BIT, 2) != HAL_OK)
{
Error_Handler();
}To fix that and enable the first block SAI1 to output the external sync signal, it is necessary to manually configure both sub-Blocks of the SAI1:
hsai_BlockA1.Init.SynchroExt = SAI_SYNCEXT_OUTBLOCKA_ENABLE;
hsai_BlockB1.Init.SynchroExt = SAI_SYNCEXT_OUTBLOCKA_ENABLE;I hope that i can help others which might run into similar problems.
Cheers,
Luca
2024-03-22 3:35 AM - edited 2024-06-14 1:10 AM
glad that you found it!
@LFrei.2 wrote:I hope that i can help others which might run into similar problems.
The best way to do that is to Mark the Solution - then people will see that the thread is "Solved".
Also, please try to keep the title brief.
2024-06-13 10:17 PM
Hi Luca @LFrei.2
Thank you so much for posting the solution of the problem. I don't know how many days of my life would be wasted without your solution. I am writing the 4 years later and ST still has not solved the problem in CubeMX.
Thanks and wish you many happy day!
2024-07-03 6:14 AM
Hi @Duddie ,
Checking on my side using STM32CubeMX 6.11.1, I see that following lines are properly generated:
hsai_BlockA1.Init.SynchroExt = SAI_SYNCEXT_OUTBLOCKA_ENABLE;
hsai_BlockB1.Init.SynchroExt = SAI_SYNCEXT_OUTBLOCKA_ENABLE;
To have these lines generated, I need to:
I'm not sure that this is really an STM32CubeMX or STM32CubeIDE issue requiring fix.
-Amel
To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
We’re moving the ST Community to a new platform to give you a better and more reliable community experience.