kostya-m 0 25 ноября, 2012 Опубликовано 25 ноября, 2012 (изменено) · Жалоба Пытаюсь задействовать 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 битных слова и передачей полного семпла за раз. Изменено 26 ноября, 2012 пользователем IgorKossak [codebox] для длинного кода!!! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Tolyaha 1 26 ноября, 2012 Опубликовано 26 ноября, 2012 · Жалоба Пробовал работать через DMA1 Channel3 Stream0 - результат такой же, отрицательный. А если попробовать DMA1 Channel0 Stream0 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
kostya-m 0 26 ноября, 2012 Опубликовано 26 ноября, 2012 · Жалоба Попробовал DMA1 Channel0 Stream0 - чуда не произошло. Наверно, как часто для STM, что-то недостаточно задокументировано и надо докапываться. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 15 26 ноября, 2012 Опубликовано 26 ноября, 2012 · Жалоба Не знаю, как с I2S, но для работы SPI по DMA нужно задействовать два канала DMA - один на передачу, второй - на приём. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
kostya-m 0 26 ноября, 2012 Опубликовано 26 ноября, 2012 · Жалоба Не знаю, как с I2S, но для работы SPI по DMA нужно задействовать два канала DMA - один на передачу, второй - на приём. Да, если надо и то и другое. Но мне надо только принимать. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 15 26 ноября, 2012 Опубликовано 26 ноября, 2012 · Жалоба Нет. В любом случае. В SPI нельзя принять, не передав. -- Вернее, как раз для приёма нужно задействовать оба DMA. Для передачи достаточно одного. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
kostya-m 0 26 ноября, 2012 Опубликовано 26 ноября, 2012 · Жалоба Нет. В любом случае. В SPI нельзя принять, не передав. -- Вернее, как раз для приёма нужно задействовать оба DMA. Для передачи достаточно одного. Это наверно в мастер режиме, поскольку клок генерится только при передаче в мастере. Правда, это носится к самому SPI, а не к DMA. Но у меня реально прием есть и бит RXNE выставляется. Пока не могу понять, почему этот бит не вызывает запроса DMA. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
kostya-m 0 28 ноября, 2012 Опубликовано 28 ноября, 2012 · Жалоба Все же удалось запустить DMA прием. И правильный оказался канал SPI3_RX - DMA1 Channel_0 Stream_0 Ошибка еще была в последовательности вызова. Сделал дополнение по опубликованной эррате о синхронизации I2S в slave с необходимостью дождаться уровня 1 у WS перед включением модуля. Выяснилось неудобство в том, что 16 битные слова в 32 битной паре переставлены: первым приходит старшее слово, а кладется оно в младшую часть. Получается, что после такого приема надо переставлять слова для обработки, а потом перед отправкой опять переставлять. Думаю не делать длинный приемный буфер, делать прерывание по каждому принятому семплу и перекладывать слова в нормальный буфер. Всем спасибо! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
graf_vladislav 0 4 декабря, 2012 Опубликовано 4 декабря, 2012 · Жалоба Поскольку в данной теме обсуждается 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 Мгц... Откуда ещё один делитель на два...? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться