Перейти к содержанию
    

STM32F4 I2S Slave Receive DMA

Пытаюсь задействовать 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

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 битных слова и передачей полного семпла за раз.

Изменено пользователем IgorKossak
[codebox] для длинного кода!!!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Пробовал работать через DMA1 Channel3 Stream0 - результат такой же, отрицательный.

А если попробовать DMA1 Channel0 Stream0

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Попробовал DMA1 Channel0 Stream0 - чуда не произошло. Наверно, как часто для STM, что-то недостаточно задокументировано и надо докапываться.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Не знаю, как с I2S, но для работы SPI по DMA нужно задействовать два канала DMA - один на передачу, второй - на приём.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Не знаю, как с I2S, но для работы SPI по DMA нужно задействовать два канала DMA - один на передачу, второй - на приём.

Да, если надо и то и другое. Но мне надо только принимать.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

--

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

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

--

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

Это наверно в мастер режиме, поскольку клок генерится только при передаче в мастере. Правда, это носится к самому SPI, а не к DMA.

Но у меня реально прием есть и бит RXNE выставляется. Пока не могу понять, почему этот бит не вызывает запроса DMA.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Все же удалось запустить DMA прием. И правильный оказался канал SPI3_RX - DMA1 Channel_0 Stream_0 Ошибка еще была в последовательности вызова. Сделал дополнение по опубликованной эррате о синхронизации I2S в slave с необходимостью дождаться уровня 1 у WS перед включением модуля. Выяснилось неудобство в том, что 16 битные слова в 32 битной паре переставлены: первым приходит старшее слово, а кладется оно в младшую часть. Получается, что после такого приема надо переставлять слова для обработки, а потом перед отправкой опять переставлять. Думаю не делать длинный приемный буфер, делать прерывание по каждому принятому семплу и перекладывать слова в нормальный буфер.

Всем спасибо!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Поскольку в данной теме обсуждается 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 Мгц... Откуда ещё один делитель на два...?

 

Поскольку в данной теме обсуждается 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 Мгц... Откуда ещё один делитель на два...?

post-73054-1354605163_thumb.jpg

post-73054-1354605516_thumb.jpg

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...