Кто-нибудь имел дело с SAI в СТМ? Хочу настроить в режиме I2S, но что-то он у меня вообще никак не работает, настраиваю так:
Код
rccEnableAPB2(1 << 23, false); // 23rd bit- SAI2 periph.
SAI2->GCR = 0;
SAI2_Block_A->CR1 = SAI_xCR1_NODIV |
SAI_xCR1_CKSTR |
(4 << 5); // 16 bit data size
SAI2_Block_A->CR2 = (2 << 0); // 1/2 FIFO threshold
SAI2_Block_A->FRCR = SAI_xFRCR_FSOFF |
SAI_xFRCR_FSDEF |
(24 << 8) | // FS active time
(49 << 0); // 2.4MHz / 48kHz = 50 (FS rate)
SAI2_Block_A->SLOTR = (3 << 16) | // Slot 0 and 1 enabled
((2 - 1) << 8) | // 2 Slots
SAI_xSLOTR_SLOTSZ_1;
SAI2_Block_A->CR1 |= SAI_xCR1_SAIEN; // Enable block
// wm8994_Init(0x34 >> 1, OUTPUT_DEVICE_BOTH, 50, AUDIO_FREQUENCY_48K);
// wm8994_SetMute(0x34 >> 1, AUDIO_MUTE_OFF);
while(true) {
// k = (SAI2_Block_A->SR & SAI_xSR_FLVL) >> 16;
if(SAI2_Block_A->SR & SAI_xSR_FREQ)
SAI2_Block_A->DR = i++;
}
SAI2->GCR = 0;
SAI2_Block_A->CR1 = SAI_xCR1_NODIV |
SAI_xCR1_CKSTR |
(4 << 5); // 16 bit data size
SAI2_Block_A->CR2 = (2 << 0); // 1/2 FIFO threshold
SAI2_Block_A->FRCR = SAI_xFRCR_FSOFF |
SAI_xFRCR_FSDEF |
(24 << 8) | // FS active time
(49 << 0); // 2.4MHz / 48kHz = 50 (FS rate)
SAI2_Block_A->SLOTR = (3 << 16) | // Slot 0 and 1 enabled
((2 - 1) << 8) | // 2 Slots
SAI_xSLOTR_SLOTSZ_1;
SAI2_Block_A->CR1 |= SAI_xCR1_SAIEN; // Enable block
// wm8994_Init(0x34 >> 1, OUTPUT_DEVICE_BOTH, 50, AUDIO_FREQUENCY_48K);
// wm8994_SetMute(0x34 >> 1, AUDIO_MUTE_OFF);
while(true) {
// k = (SAI2_Block_A->SR & SAI_xSR_FLVL) >> 16;
if(SAI2_Block_A->SR & SAI_xSR_FREQ)
SAI2_Block_A->DR = i++;
}
Тактирование блока SAI - от PLL 2.4MHz. В цикле фифо заполняется и новых запросов не шлет. Содержимое статусного регистра не меняется:
Цитата
Fields in ASR of peripheral SAI2:
FLVL: 3 FIFO level threshold
LFSDET: 0 Late frame synchronization detection
AFSDET: 0 Anticipated frame synchronization detection
CNRDY: 0 Codec not ready
FREQ: 0 FIFO request
WCKCFG: 0 Wrong clock configuration flag. This bit is read only.
MUTEDET: 0 Mute detection
OVRUDR: 0 Overrun / underrun
FLVL: 3 FIFO level threshold
LFSDET: 0 Late frame synchronization detection
AFSDET: 0 Anticipated frame synchronization detection
CNRDY: 0 Codec not ready
FREQ: 0 FIFO request
WCKCFG: 0 Wrong clock configuration flag. This bit is read only.
MUTEDET: 0 Mute detection
OVRUDR: 0 Overrun / underrun
Ощущение, что клок на фифо не приходит. Все усугубляется тем, что осциллом в линии не ткнуться - на плате (F7 disco) чип - БГА.
Пробовал настроить то же самое через функции HAL - так же не работает (при попытке послать что-нибудь - вылетает тайм аут).
---
Было тактирование от PLLSAI, затактировал от PLLI2S xfcnjnjq 49.143. Взял функцию инициализации из примеров Куба:
Код
static void SAIx_Out_Init(void) {
rccEnableAPB2(1 << 23, false);
/* Initialize the haudio_out_sai Instance parameter */
haudio_out_sai.Instance = SAI2_Block_A;
/* Disable SAI peripheral to allow access to SAI internal registers */
__HAL_SAI_DISABLE(&haudio_out_sai);
/* Configure SAI_Block_x
LSBFirst: Disabled
DataSize: 16 */
haudio_out_sai.Init.AudioFrequency = SAI_AUDIO_FREQUENCY_48K;
haudio_out_sai.Init.AudioMode = SAI_MODEMASTER_TX;
haudio_out_sai.Init.NoDivider = SAI_MASTERDIVIDER_ENABLED;
haudio_out_sai.Init.Protocol = SAI_FREE_PROTOCOL;
haudio_out_sai.Init.DataSize = SAI_DATASIZE_16;
haudio_out_sai.Init.FirstBit = SAI_FIRSTBIT_MSB;
haudio_out_sai.Init.ClockStrobing = SAI_CLOCKSTROBING_RISINGEDGE;
haudio_out_sai.Init.Synchro = SAI_ASYNCHRONOUS;
haudio_out_sai.Init.OutputDrive = SAI_OUTPUTDRIVE_ENABLED;
haudio_out_sai.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_1QF;
/* Configure SAI_Block_x Frame
Frame Length: 64
Frame active Length: 32
FS Definition: Start frame + Channel Side identification
FS Polarity: FS active Low
FS Offset: FS asserted one bit before the first bit of slot 0 */
haudio_out_sai.FrameInit.FrameLength = 64;
haudio_out_sai.FrameInit.ActiveFrameLength = 32;
haudio_out_sai.FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION;
haudio_out_sai.FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW;
haudio_out_sai.FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT;
/* Configure SAI Block_x Slot
Slot First Bit Offset: 0
Slot Size : 16
Slot Number: 4
Slot Active: All slot actives */
haudio_out_sai.SlotInit.FirstBitOffset = 0;
haudio_out_sai.SlotInit.SlotSize = SAI_SLOTSIZE_DATASIZE;
haudio_out_sai.SlotInit.SlotNumber = 4;
haudio_out_sai.SlotInit.SlotActive = SAI_SLOTACTIVE_ALL;
HAL_SAI_Init(&haudio_out_sai);
/* Enable SAI peripheral to generate MCLK */
__HAL_SAI_ENABLE(&haudio_out_sai);
}
rccEnableAPB2(1 << 23, false);
/* Initialize the haudio_out_sai Instance parameter */
haudio_out_sai.Instance = SAI2_Block_A;
/* Disable SAI peripheral to allow access to SAI internal registers */
__HAL_SAI_DISABLE(&haudio_out_sai);
/* Configure SAI_Block_x
LSBFirst: Disabled
DataSize: 16 */
haudio_out_sai.Init.AudioFrequency = SAI_AUDIO_FREQUENCY_48K;
haudio_out_sai.Init.AudioMode = SAI_MODEMASTER_TX;
haudio_out_sai.Init.NoDivider = SAI_MASTERDIVIDER_ENABLED;
haudio_out_sai.Init.Protocol = SAI_FREE_PROTOCOL;
haudio_out_sai.Init.DataSize = SAI_DATASIZE_16;
haudio_out_sai.Init.FirstBit = SAI_FIRSTBIT_MSB;
haudio_out_sai.Init.ClockStrobing = SAI_CLOCKSTROBING_RISINGEDGE;
haudio_out_sai.Init.Synchro = SAI_ASYNCHRONOUS;
haudio_out_sai.Init.OutputDrive = SAI_OUTPUTDRIVE_ENABLED;
haudio_out_sai.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_1QF;
/* Configure SAI_Block_x Frame
Frame Length: 64
Frame active Length: 32
FS Definition: Start frame + Channel Side identification
FS Polarity: FS active Low
FS Offset: FS asserted one bit before the first bit of slot 0 */
haudio_out_sai.FrameInit.FrameLength = 64;
haudio_out_sai.FrameInit.ActiveFrameLength = 32;
haudio_out_sai.FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION;
haudio_out_sai.FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW;
haudio_out_sai.FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT;
/* Configure SAI Block_x Slot
Slot First Bit Offset: 0
Slot Size : 16
Slot Number: 4
Slot Active: All slot actives */
haudio_out_sai.SlotInit.FirstBitOffset = 0;
haudio_out_sai.SlotInit.SlotSize = SAI_SLOTSIZE_DATASIZE;
haudio_out_sai.SlotInit.SlotNumber = 4;
haudio_out_sai.SlotInit.SlotActive = SAI_SLOTACTIVE_ALL;
HAL_SAI_Init(&haudio_out_sai);
/* Enable SAI peripheral to generate MCLK */
__HAL_SAI_ENABLE(&haudio_out_sai);
}
Тоже не работает. HAL_SAI_Init вызывает функцию, вычисляющую текущую частоту тактирования блока - и она правильная. В gdb все регистры, относящиеся к тактированию тоже правильно заполнены. Чудеса какие-то.