Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: STM32F4 I2S Slave Receive DMA
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Мусатов Константин
Пытаюсь задействовать SPI3/I2S3 в slave режиме с обработкой через DMA.

Принимать через I2S удается в режиме программного поллинга
Код
  while(1){
    while( (SPI3->SR & SPI_I2S_FLAG_RXNE) == 0 );
    SPDiffRxBuffer[TimeRXPointer][0] = (long)SPI3->DR;
    if( ++TimeRXPointer >= SPDIFF_BUF_LEN ) TimeRXPointer = 0;
  }

Т.е. сам I2S приемник работает
Пытаюсь добавить код что бы сделать прием через DMA
CODE
static void I2S_DMA_Init( void )
{
DMA_InitTypeDef DMA_InitStruct;
NVIC_InitTypeDef NVIC_InitStructure;

DMA_DeInit( DMA1_Stream2 );

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);

DMA_InitStruct.DMA_Channel = DMA_Channel_2;
DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)&(SPI3->DR);
DMA_InitStruct.DMA_Memory0BaseAddr = (uint32_t)SPDiffRxBuffer;
DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralToMemory;
DMA_InitStruct.DMA_BufferSize = SPDIFF_BUF_LEN * 4;
DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStruct.DMA_Mode = DMA_Mode_Circular;
DMA_InitStruct.DMA_Priority = DMA_Priority_High;
DMA_InitStruct.DMA_FIFOMode = DMA_FIFOMode_Enable;
DMA_InitStruct.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
DMA_InitStruct.DMA_MemoryBurst = DMA_MemoryBurst_INC4;
DMA_InitStruct.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
while( DMA_GetCmdStatus( DMA1_Stream2 ) == ENABLE );
DMA_Init( DMA1_Stream2, &DMA_InitStruct );

DMA_ITConfig( DMA1_Stream2, DMA_IT_TC, ENABLE );

DMA_Cmd( DMA1_Stream2, ENABLE );

SPI_I2S_DMACmd( SPI3, SPI_I2S_DMAReq_Rx, ENABLE);

NVIC_InitStructure.NVIC_IRQChannel = DMA1_Stream2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}

и
Код
void DMA1_Stream2_IRQHandler( void )
{
  LEDOn( LED1 );
  LEDOff( LED1 );
}

Прерывание не вызывается, буфер не заполняется. При этом флаг RXNE поднимается и можно опять же работать с опросом.
Пробовал работать через DMA1 Channel3 Stream0 - результат такой же, отрицательный.
Пробовал без прерывания, буфер все равно не заполняется.
Что я делаю не правильно?
Можно принимать и через прерывание от I2S, но это неудобно, поскольку контроллер принимает только 16 бит и выходит 4 прерывания на семпл. Очень хочется задействовать Fifo в DMA для сбора по два 32 битных слова и передачей полного семпла за раз.
Tolyaha
Цитата(Мусатов Константин @ Nov 25 2012, 22:30) *
Пробовал работать через DMA1 Channel3 Stream0 - результат такой же, отрицательный.

А если попробовать DMA1 Channel0 Stream0
Мусатов Константин
Попробовал DMA1 Channel0 Stream0 - чуда не произошло. Наверно, как часто для STM, что-то недостаточно задокументировано и надо докапываться.
AHTOXA
Не знаю, как с I2S, но для работы SPI по DMA нужно задействовать два канала DMA - один на передачу, второй - на приём.
Мусатов Константин
Цитата(AHTOXA @ Nov 26 2012, 21:15) *
Не знаю, как с I2S, но для работы SPI по DMA нужно задействовать два канала DMA - один на передачу, второй - на приём.

Да, если надо и то и другое. Но мне надо только принимать.
AHTOXA
Нет. В любом случае. В SPI нельзя принять, не передав.

--
Вернее, как раз для приёма нужно задействовать оба DMA. Для передачи достаточно одного.
Мусатов Константин
Цитата(AHTOXA @ Nov 27 2012, 00:36) *
Нет. В любом случае. В SPI нельзя принять, не передав.

--
Вернее, как раз для приёма нужно задействовать оба DMA. Для передачи достаточно одного.

Это наверно в мастер режиме, поскольку клок генерится только при передаче в мастере. Правда, это носится к самому SPI, а не к DMA.
Но у меня реально прием есть и бит RXNE выставляется. Пока не могу понять, почему этот бит не вызывает запроса DMA.
Мусатов Константин
Все же удалось запустить DMA прием. И правильный оказался канал SPI3_RX - DMA1 Channel_0 Stream_0 Ошибка еще была в последовательности вызова. Сделал дополнение по опубликованной эррате о синхронизации I2S в slave с необходимостью дождаться уровня 1 у WS перед включением модуля. Выяснилось неудобство в том, что 16 битные слова в 32 битной паре переставлены: первым приходит старшее слово, а кладется оно в младшую часть. Получается, что после такого приема надо переставлять слова для обработки, а потом перед отправкой опять переставлять. Думаю не делать длинный приемный буфер, делать прерывание по каждому принятому семплу и перекладывать слова в нормальный буфер.
Всем спасибо!
Vladislav_Minsk
Поскольку в данной теме обсуждается I2S, решил не создавать новую тему...
Попробовал запустить у себя I2S2 в режиме мастер-приёмник... Но столкнулся с непонятными значениями клока...
PLL_I2S настроил на выходную 40 МГц... Через MCO2 проверил, всё точно... Но дальше, возникли вопросы...
Тактовая на выходе почему-то где-то успевает делиться ещё на 2...
Вот значения регистров делителей самого модуля I2S...
/* I2S2 configuration */
SPI2->I2SCFGR = 0x0B01; // I2S2 configuration
SPI2->I2SPR = 0x0004; // I2S2 clock mode
SPI2->I2SCFGR |= (1<<10); // I2S2 On
Из схемы в документации настроил делители как показано во второй строчке... При таком раскладе должно быть на выходе 10 МГц...
Но там почему-то 5 Мгц... Откуда ещё один делитель на два...?

Цитата(Vladislav_Minsk @ Dec 4 2012, 10:14) *
Поскольку в данной теме обсуждается I2S, решил не создавать новую тему...
Попробовал запустить у себя I2S2 в режиме мастер-приёмник... Но столкнулся с непонятными значениями клока...
PLL_I2S настроил на выходную 40 МГц... Через MCO2 проверил, всё точно... Но дальше, возникли вопросы...
Тактовая на выходе почему-то где-то успевает делиться ещё на 2...
Вот значения регистров делителей самого модуля I2S...
/* I2S2 configuration */
SPI2->I2SCFGR = 0x0B01; // I2S2 configuration
SPI2->I2SPR = 0x0004; // I2S2 clock mode
SPI2->I2SCFGR |= (1<<10); // I2S2 On
Из схемы в документации настроил делители как показано во второй строчке... При таком раскладе должно быть на выходе 10 МГц...
Но там почему-то 5 Мгц... Откуда ещё один делитель на два...?

Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.