2015-05-22 02:33 AM
Hi,
help me please
to set up
the SAI
correctly.
I need a
mode
I2S standart, 32-bit frame, 24-bit data. Iconfigured
my code: hsai_BlockA1.Instance = SAI1_Block_A; hsai_BlockA1.Init.Protocol = SAI_FREE_PROTOCOL; hsai_BlockA1.Init.AudioMode = SAI_MODEMASTER_TX; hsai_BlockA1.Init.DataSize = SAI_DATASIZE_24; hsai_BlockA1.Init.FirstBit = SAI_FIRSTBIT_MSB; hsai_BlockA1.Init.ClockStrobing = SAI_CLOCKSTROBING_RISINGEDGE; hsai_BlockA1.Init.Synchro = SAI_ASYNCHRONOUS; hsai_BlockA1.Init.OutputDrive = SAI_OUTPUTDRIVE_ENABLED; hsai_BlockA1.Init.NoDivider = SAI_MASTERDIVIDER_ENABLED; hsai_BlockA1.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_EMPTY; hsai_BlockA1.Init.ClockSource = SAI_CLKSOURCE_PLLI2S; hsai_BlockA1.Init.AudioFrequency = SAI_AUDIO_FREQUENCY_48K; hsai_BlockA1.FrameInit.FrameLength = 64; hsai_BlockA1.FrameInit.ActiveFrameLength = 32; hsai_BlockA1.FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION; hsai_BlockA1.FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW; hsai_BlockA1.FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT;//SAI_FS_FIRSTBIT hsai_BlockA1.SlotInit.FirstBitOffset = 0; hsai_BlockA1.SlotInit.SlotSize = SAI_SLOTSIZE_32B; hsai_BlockA1.SlotInit.SlotNumber = 2; hsai_BlockA1.SlotInit.SlotActive = 0xFFFF0000; HAL_SAI_Init(&hsai_BlockA1);However, these
are not perceived
correctly.
2015-10-21 09:21 PM
My question is most likely related to this. Has anyone got a 24-bit or 32-bit I2S transmitter working using the SAI peripheral?
Scenario
I have setup my project on a STM32756G-Eval board and used STM32CubeMX 4.10.1 with STM32F7 firmware package version 1.1.0 to generate my HAL libraries. I’m using DMA to loop through a buffer of “audio data� and pass this into SAI1 peripheral. I selected a low audio frequency or 16kHz (also tried 192kHz) and my I2S_CKIN is 216MHz. The source code auto generated is:
/* 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_ENABLED;
hsai_BlockA1.Init.NoDivider = SAI_MASTERDIVIDER_ENABLED;
hsai_BlockA1.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_EMPTY;
hsai_BlockA1.Init.AudioFrequency = SAI_AUDIO_FREQUENCY_16K;
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;
HAL_SAI_InitProtocol(&hsai_BlockA1, SAI_I2S_STANDARD, SAI_PROTOCOL_DATASIZE_16BIT, 2);
}
And:
void HAL_SAI_MspInit(SAI_HandleTypeDef* hsai)
{
GPIO_InitTypeDef GPIO_InitStruct;
/* SAI1 */
if(hsai->Instance==SAI1_Block_A)
{
/* Peripheral clock enable */
if (SAI1_client == 0)
{
__SAI1_CLK_ENABLE();
/* Peripheral interrupt init*/
HAL_NVIC_SetPriority(SAI1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(SAI1_IRQn);
}
SAI1_client ++;
/**SAI1_A_Block_A GPIO Configuration
PE4 ------> SAI1_FS_A
PE2 ------> SAI1_MCLK_A
PE5 ------> SAI1_SCK_A
PE6 ------> SAI1_SD_A
*/
GPIO_InitStruct.Pin = GPIO_PIN_4|GPIO_PIN_2|GPIO_PIN_5|GPIO_PIN_6;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_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_HALFWORD;
hdma_sai1_a.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
hdma_sai1_a.Init.Mode = DMA_CIRCULAR;
hdma_sai1_a.Init.Priority = DMA_PRIORITY_LOW;
hdma_sai1_a.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
hdma_sai1_a.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
hdma_sai1_a.Init.MemBurst = DMA_MBURST_SINGLE;
hdma_sai1_a.Init.PeriphBurst = DMA_PBURST_SINGLE;
HAL_DMA_Init(&hdma_sai1_a);
/* 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);
}
}
And my test app simply does:
{
static constexpr int DATA_SIZE = 1024;
uint16_t data[DATA_SIZE];
HAL_SAI_Transmit_DMA(&hsai_BlockA1, (uint8_t*) &data[0], DATA_SIZE);
while(1);
}
Problem
When I use SAI_PROTOCOL_DATASIZE_16BIT, everything seems to work fine when I check the lines on a scope; but using SAI_PROTOCOL_DATASIZE_24BIT or SAI_PROTOCOL_DATASIZE_32BIT I get nothing at all out any of the lines. Although it shouldn't really matter, I did also change the DMA to write words instead of half-words when using 24 and 32-bit output. I also that I tried using the blocking funcion HAL_SAI_Transmit() instead of the DMA version and it had the same problem (worked for 16 but not for 24 or 32-bit). (NOTE: There are some bugs in the HAL_SAI_Transmit() that I guess I can post as issues somewhere (?))
Help
Am I doing something wrong? Has anyone had success with this peripheral at these rates? It seems that I'm either doing something wrong in my setup or there are bugs in the HAL library or silicon...