cancel
Showing results for 
Search instead for 
Did you mean: 

SAI block settings

z1060
Associate II
Posted on May 22, 2015 at 11:33

Hi,

help me please

to set up

the SAI

correctly.

I need a

mode

I2S standart, 32-bit frame, 24-bit data.

I

configured

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.

1 REPLY 1
michaeljulius9
Associate II
Posted on October 22, 2015 at 06:21

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...