Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: STM32F407 Непонятки с SAI
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Tarbal
Вроде как есть два I2S и 2 SAI и I2S и SAI это разные устройства. Мне надо 16 каналов PCM и SAI это позволяет. Но вот засада: читаю документацию и никак не могу найти к каким ножкам оно подключено. Это скорее всего не I2S ибо I2S имеет другие регистры причем одни и те же что и SPI. Кто-нибудь использовал SAI в STM32F407 или STM32F405?
Genadi Zawidowski
В STM32F407/STM32F405 контроллера SAI нет. совсем.
http://www.st.com/st-web-ui/static/active/.../DM00037051.pdf
В 429, 446, 746 и вариациях.
alag57
Цитата(Tarbal @ Nov 2 2015, 23:46) *
Вроде как есть два I2S и 2 SAI и I2S и SAI это разные устройства. Мне надо 16 каналов PCM и SAI это позволяет. Но вот засада: читаю документацию и никак не могу найти к каким ножкам оно подключено. Это скорее всего не I2S ибо I2S имеет другие регистры причем одни и те же что и SPI. Кто-нибудь использовал SAI в STM32F407 или STM32F405?

Serial audio interface (SAI) RM0090
914/1718 DocID018909 Rev 8
29 Serial audio interface (SAI)
This section applies to the STM32F42xxx and STM32F43xxx family.
перевод: SAI нет в 407.
Tarbal
Спасибо за подсказку. В Юзер Референс Мануал описано что есть. Вот я и ищу, а найти не могу. И STM32CubeMX ( http://www.st.com/web/catalog/tools/FM147/...42?sc=stm32cube ) тоже ничего не видит. А вот для указанных вами процессоров сразу показала.

Значит мой дискавери борд не годится для экспериментов.
Genadi Zawidowski
Как раз в DM00037051.pdf даже слова такого нет...
платы с 429 даже раздавали бесплатно на многих мероприятиях.
ig_z
QUOTE (Tarbal @ Nov 3 2015, 04:39) *
Значит мой дискавери борд не годится для экспериментов.

Слегка офтоп. Если у вас есть LPC с SGPIO модулем, то можно получить похожий функционал.
В сети бродит описание такого проекта.
Tarbal
Цитата(ig_z @ Nov 3 2015, 17:34) *
Слегка офтоп. Если у вас есть LPC с SGPIO модулем, то можно получить похожий функционал.
В сети бродит описание такого проекта.


Спасибо. В моем случае надо будет купить подходящий борд ибо LPC с SGPIO модулем у меня тоже нет sm.gif
alexandermas
sgpio в lpc полная порнография, хотя сами процы вполне ничего хоть и не без багов. что касается самого i2s я сам сейчас нахожусь в процессе спрыгивания с lpc4357 в пользу stm32f7xx. и только потому что несмог путью прикрутить плиску к 43хх, в которой как раз похожий многоканальный i2s и реализован. а вот в 32f7хх есть qspi с ddr обменом в обе стороны. sgpio в 43xx полусофтварный и если пользовать его то получается что часть мощности самого проца уходит на вывод данных
ig_z
QUOTE (alexandermas @ Nov 4 2015, 12:42) *
sgpio в lpc полная порнография


Что значит "полная порнография"? Можно плиз подробнее и более техническими терминами обрисовать ситуацию.

QUOTE (alexandermas @ Nov 4 2015, 12:42) *
я сам сейчас нахожусь в процессе спрыгивания с lpc4357 в пользу stm32f7xx. и только потому что несмог путью прикрутить плиску к 43хх
в которой как раз похожий многоканальный i2s и реализован.


Что такое "похожий многоканальный i2s"? В LPC есть I2S и SGPIO. Судя по описанию, на последнем можно делать всевозможные серийные синхронные / асинхронные шины и заниматься ногодрыжеством. Для этого он и задумывался, и как любое универсальное решение обладает избыточностью. У меня руки до него еще не дошли, если у вас есть конкретная информация об отрицательных свойствах этого модуля, поделитесь информацией, это будет всем интересно

QUOTE (alexandermas @ Nov 4 2015, 12:42) *
sgpio в 43xx полусофтварный и если пользовать его то получается что часть мощности самого проца уходит на вывод данных

В чем заключается полусофтварность?
Ну и как бы для юсб аудио интерфейса особо то и заниматься нечем.
Например взять LPC17. Если бы DMA было бы поумнее ( что то типа 2D) или I2S модуль оптимальнее спроектирован, то весь аудио стрим для некоторых режимов мог бы передаваться без участия CPU.

alexandermas
Цитата(ig_z @ Nov 4 2015, 18:25) *
Что значит "полная порнография"? Можно плиз подробнее и более техническими терминами обрисовать ситуацию.



Что такое "похожий многоканальный i2s"? В LPC есть I2S и SGPIO. Судя по описанию, на последнем можно делать всевозможные серийные синхронные / асинхронные шины и заниматься ногодрыжеством. Для этого он и задумывался, и как любое универсальное решение обладает избыточностью. У меня руки до него еще не дошли, если у вас есть конкретная информация об отрицательных свойствах этого модуля, поделитесь информацией, это будет всем интересно


В чем заключается полусофтварность?
Ну и как бы для юсб аудио интерфейса особо то и заниматься нечем.
Например взять LPC17. Если бы DMA было бы поумнее ( что то типа 2D) или I2S модуль оптимальнее спроектирован, то весь аудио стрим для некоторых режимов мог бы передаваться без участия CPU.

Начну с конца.... Для юсб аудио, не спорю, заниматься действительно нечем, но вот когда распаковываешь .ape или многоканальный .flac то мегагерцы становятся совсем не лишними. полусофтварность заключается в том что приходится соотв. образом подготавливать буфера для вывода, лить их по дма без участия ядра тоже не выходит (приходится проверять опустошение) это про sgpio. что касается i2s лично мне для моего проекта 2 набортных i2s мало, да и заставить их синхронно работать я не представляю как. С дма (касается lpc43xx, у 17хх вроде все нормально) тоже аппаратный косяк - при работе со связанными списками наблюдается выпадение 1 семпла из каждых 2-3 блоков по 4090 семплов, (тоже не особо удобно, т.к. фреймы в lossless форматов обычно 4096 семплов или больше) при работе на набортный i2s. плюс ко всему если вы делаете действительно высококлассную аудио систему, напомню что сами порты вывода (те к которым посредством матриц подключается встроенная переферия) тактируются совсем не от того клока что сам i2s. поэтому имеем резкое увеличение джиттера как результат(проверено опытным путем). Далее в своих мытарствах решил уйти на плис, подумал что от вышеописаных трудностей уйду... Прицепил плис, на тот момент по spi, все вроде ничего, и играло лучше чем с набортного, но только на 2х каналах, для большего невытянул spi по скорости(максимум выжал 50м/бит). решил повесить плис на EMC а вот тут была действительно засада, изза встроенных неотключаемых буферов на шине emc (даже флаг гады сделали, но нерабочий) если писать по 1 адресу я еще как то мог, то вот последовательное чтение по 1 адресу стабатывало только 1 раз, на второй логика emc считала что данные не изменились и выдавала результат из буфера. сейчас в плис находится 8 однотипных контроллеров которые я могу по своему усмотрению конфигурировать и настраивать выводя некоторые каналы хоть по i2s в разных форматах, хоть по spdif. Обмен с камнем планирую сделать по qspi.
Tarbal
Кто-нибудь использовал SAI На STM32F429 или похожем?
Никак не могу получить выходную тактовую частоту в режиме мастера. Иметь подсказку в виде содержимого регистров было бы полезно.
Genadi Zawidowski
А какие регистры интересуют?
Вот тут https://188.134.5.254/browser/hfreceiver/tr...recodecs.c#L924 инициализация, имейте в виду - в описании SAI_xCR1_MCKDIV_0 и остальных у ST ошибка в значении (я использую исправленную версию).
Tarbal
Цитата(Genadi Zawidowski @ Nov 7 2015, 21:21) *
А какие регистры интересуют?
Вот тут https://188.134.5.254/browser/hfreceiver/tr...recodecs.c#L924 инициализация, имейте в виду - в описании SAI_xCR1_MCKDIV_0 и остальных у ST ошибка в значении (я использую исправленную версию).

Спасибо посмотрю.
Меня интересуют регистры SAI. Просто значения.

Про ошибку не очень понял. Можно поподробнее пожалуйста?

Спасибо вам Генадий,
Нашел уже, что APB clock не разрешен для SAI, но пока не помогло. Буду искать дальше. Код у вас с любовью написан -- красиво.
Genadi Zawidowski
Вот подробности:




Вот выдача:
Код
hardware_sai1_master_fullduplex_initialize: 2 SAI1 MCKDIV=14, ARMSAIMCLK=12288000, PLLI2S_FREQ_OUT=172032000
SAI1_Block_A->CR1:      007202E0
SAI1_Block_A->CR2:      00000000
SAI1_Block_A->FRCR:     00011F3F
SAI1_Block_A->SLOTR:    00030180
SAI1_Block_A->IMR:      00000000
SAI1_Block_A->SR:       00000008
SAI1_Block_B->CR1:      007206E3
SAI1_Block_B->CR2:      00000000
SAI1_Block_B->FRCR:     00011F3F
SAI1_Block_B->SLOTR:    00030180
SAI1_Block_B->IMR:      00000000
SAI1_Block_B->SR:       00000000

Вот код:
Код
static void pp(const SAI_Block_TypeDef * dev, const char * label)
{
    debug_printf_P(PSTR("%s->%s:\t%08lX\n"), label, "CR1", dev->CR1);
    debug_printf_P(PSTR("%s->%s:\t%08lX\n"), label, "CR2", dev->CR2);
    debug_printf_P(PSTR("%s->%s:\t%08lX\n"), label, "FRCR", dev->FRCR);
    debug_printf_P(PSTR("%s->%s:\t%08lX\n"), label, "SLOTR", dev->SLOTR);
    debug_printf_P(PSTR("%s->%s:\t%08lX\n"), label, "IMR", dev->IMR);
    debug_printf_P(PSTR("%s->%s:\t%08lX\n"), label, "SR", dev->SR);
}


В данном варианте тактируется от PLL, так что там ещё и I2SPLL задействовано в RCC (смотрите функцию hardware_sai_clock_selection, для WITHSAICLOCKFROMI2S
Tarbal
Спасибо, уже дышит.
Насколько я понял клок не разрешался из-за моих ляпов -- куб не при чем, а модули надо было разрешить после всех инициализаций:

__HAL_SAI_ENABLE(&hsai_BlockA1);
__HAL_SAI_ENABLE(&hsai_BlockB1);
Genadi Zawidowski
Цитата(Tarbal @ Nov 8 2015, 04:47) *
Спасибо, уже дышит.

Ну и хорошо...
Tarbal
Цитата(Genadi Zawidowski @ Nov 8 2015, 15:10) *
Ну и хорошо...

Но вопросы не кончились.

Отчего-то нет фрейм сигнала. Насколько я понимаю если DMA подключено, то железке уже пофиг, что я не считываю из DMA. Хотя прерывания от DMA тоже не возникает.
Хотя то, что я не записываю ничего может быть и проблема. Надо еще с DMA разобраться.

В первый раз надо готовить буфер и активировать DMA или достаточно сделать все в обработчике прерывания и он сразу вызовет прерывание, когда все готово и прерывание разрешено? Другими словами по какому условию вызывается прерывание:
- передача завершена
- передача не обработана (как буфер пуст в UART)

FIFO и DMA как я понимаю разные устройства. FIFO встроено в SAI, а DMA отдельный модуль. При передаче DMA берет данные из области памяти и запихивает в FIFO. На этом обо всем можно забыть до следующей транзакции -- работает железо.
Genadi Zawidowski
Посмотрите как я делаю... первый буфер подставляется DMA ещё при инициализации.
Tarbal
Цитата(Genadi Zawidowski @ Nov 8 2015, 18:10) *
Посмотрите как я делаю... первый буфер подставляется DMA ещё при инициализации.

__DSB(); это что?


Это?
http://infocenter.arm.com/help/index.jsp?t...ar01s02s04.html
Tarbal
Добавил старт ПДП (DMA) и все начало работать. Появился сигнал синхронизации фрейма. Спасибо Генадий за помощь.
Сейчас соединю дату с выхода SAIA со входом SAIB и попробую скопировать буфер через SAI.
Теперь еще USB прикрутить надо будет, но понемногу концепция куба становится понятной и с каждым шагом легче использовать.
Tarbal
Наконец дошел до организации потока данных через SAI. Сделал по простому. Оба DMA (в оба направления) с кольцевыми буферами. В прерывании конца передачи DMA читаю принятый буфер и заполняю буфер на передачу при помощи memcpy(). Поскольку оба канала синхронны, то полагаю, что оба копирования могу делать в одном и том же обработчике прерывания. Но судя по результату я чего-то не понимаю. Может нужны какие-то процедуры, о которых я не подозреваю? Подскажите люди добрые.
Tarbal
Решил несколько проблем. Осталась по видимому одна. Отчего-то нет синхронизации положения в данных буфере со слотом PCM.
У меня 16 слотов. Сначала я использовал циклический буфер DMA, но теперь перезапускаю прием и передачу в соответствующем прерывании каждый раз. Разнес прерывания на окончание приема и окончание передачи.
Может что-то надо переустановить в DMA?

Кажется понял. Надо из кеша выдувать данные в железо сразу после записи. На чтение вроде нет такой проблемы. Или я неправ?

Нашел, что и на чтение надо тоже произвести обмен с кэшем. Осталось найти как.
Genadi Zawidowski
В stm32f429 нет data cache, который было бы нужно как-то пинать.
В Вашем случае, возможно надо double buffer использовать ("качели") - у Вас будет время на обработку одного буфера, пока другой заполняется.
В случае же циклического такой возможности нет.
Tarbal
Цитата(Genadi Zawidowski @ Mar 2 2016, 02:26) *
В stm32f429 нет data cache, который было бы нужно как-то пинать.
В Вашем случае, возможно надо double buffer использовать ("качели") - у Вас будет время на обработку одного буфера, пока другой заполняется.
В случае же циклического такой возможности нет.


Спасибо. Я примерно так и сделал. На циклическом буфере двойной длины делаю прерывания на половине передачи и на полной. Качели и получаются.
Оказывается FIFO надо включать sm.gif. Разрешил FIFO (неважно на половине или на полном ставить порог слвания) и все заработало, но отчего-то строб сигнал фрейма FS приходитса на первый (старший) бит последнего байта фрейма. Вот преодолеваю. Поскольку надо мне все равно делать транспонирование при копировании между USB и PCM, пока вставлю в матрицу преобразования символа сдвиг для коррекции, а дальше посмотрим.

Причем сдвиг имеет место быть и при передаче без DMA.
Tarbal
Цитата(Tarbal @ Mar 2 2016, 18:53) *
Спасибо. Я примерно так и сделал. На циклическом буфере двойной длины делаю прерывания на половине передачи и на полной. Качели и получаются.
Оказывается FIFO надо включать sm.gif. Разрешил FIFO (неважно на половине или на полном ставить порог слвания) и все заработало, но отчего-то строб сигнал фрейма FS приходитса на первый (старший) бит последнего байта фрейма. Вот преодолеваю. Поскольку надо мне все равно делать транспонирование при копировании между USB и PCM, пока вставлю в матрицу преобразования символа сдвиг для коррекции, а дальше посмотрим.

Причем сдвиг имеет место быть и при передаче без DMA.


Не доволен результатом. Иногда попадает на ошибку DMA. и срывается синхронизация. Буду копать дальше.

Генадий, у меня одна проблема, которую я не могу никак понять.
Я использую все 16 слотов интерфейса.
Отчего-то импульс синхронизации не на первом бите (старшем) нулевого слота, а на первом бите последнего слота предыдущего фрейма.
Могу конечно в буфере подвинуть, но мне такое делать стыдно.

У вас нет никаких идей насчет этого?
Заранее спасибо.
Genadi Zawidowski
Цитата(Tarbal @ Mar 3 2016, 09:05) *
Не доволен результатом. Иногда попадает на ошибку DMA. и срывается синхронизация. Буду копать дальше.

Генадий, у меня одна проблема, которую я не могу никак понять.
Я использую все 16 слотов интерфейса.
Отчего-то импульс синхронизации не на первом бите (старшем) нулевого слота, а на первом бите последнего слота предыдущего фрейма.
Могу конечно в буфере подвинуть, но мне такое делать стыдно.

У вас нет никаких идей насчет этого?
Заранее спасибо.

а на первом бите последнего слота предыдущего фрейма - это I2S, смотрите 29.7.4 Frame synchronization offset
Tarbal
Цитата(Genadi Zawidowski @ Mar 3 2016, 17:28) *
а на первом бите последнего слота предыдущего фрейма - это I2S, смотрите 29.7.4 Frame synchronization offset

Спасибо.
Посмотрел. Это сдвиг на один бит, а у меня сдвиг на байт. Причем я пробовал посылать без DMA. Не помогло. Точно также.
Genadi Zawidowski
А Вы в референс мануал вообще заглядывали?
Tarbal
Цитата(Genadi Zawidowski @ Mar 3 2016, 22:54) *
А Вы в референс мануал вообще заглядывали?


Заглядывал.
Tarbal
Разобрался что происходит, но не было времени разобраться (вернее проверить как надо знаю sm.gif ) как грамотно решить проблему. Жесткий график проекта не давал продохнуть.
При старте SAI думает, что в FIFO уже есть один байт. Это и вызывает сдвиг. По хорошему перед вызовом функции куба передачи через DMA надо промыть (flush) FIFO, но не было времени проверять.
Allregia
Коллеги, просветите по поводу этого SAI - пытаюсь перелезть на него с обычного I2S (который в SPI).
Непонятнки с семплрейтом, получается что при внешнем клоке 512фс, можно получить на выходе только 48 и 96, при вкл. делителе, и 384 при выключенном? Т.е. 192 получить вообще не получается, а 384 вроде как оверспек (для L4).
В I2S на F4 это без проблем.
Genadi Zawidowski
Цитата(Allregia @ Apr 30 2016, 16:43) *
Коллеги, просветите по поводу этого SAI - пытаюсь перелезть на него с обычного I2S (который в SPI).
Непонятнки с семплрейтом, получается что при внешнем клоке 512фс, можно получить на выходе только 48 и 96, при вкл. делителе, и 384 при выключенном? Т.е. 192 получить вообще не получается, а 384 вроде как оверспек (для L4).
В I2S на F4 это без проблем.


Убедитесь, что в вашей версии заголовочных файлов значения битов, определяющих делитель, соответствуют документации (в старых версиях была ошибка).
Allregia
Версии 2-х месячной давности годятся?
Но вообще, я вручную пишу в делитель 1 для 48 и 0 для 96, при NoDiv=0, соотв. деление на 2 и на 1.
Что надо записать, чтобы получить 192?
Genadi Zawidowski
Должно быть так:
Код
#define  SAI_xCR1_MCKDIV                  ((uint32_t)0x00F00000)        /*!<MCKDIV[3:0] (Master ClocK Divider)  */
#define  SAI_xCR1_MCKDIV_0                ((uint32_t)0x00100000)        /*!<Bit 0  */
#define  SAI_xCR1_MCKDIV_1                ((uint32_t)0x00200000)        /*!<Bit 1  */
#define  SAI_xCR1_MCKDIV_2                ((uint32_t)0x00400000)        /*!<Bit 2  */
#define  SAI_xCR1_MCKDIV_3                ((uint32_t)0x00800000)        /*!<Bit 3  */


Цитата
RM0090, SAI xConfiguration register 1 (SAI_xCR1) (chapter 29.17.1).
MCKDIV[3:0] value description:

0000: Divides by 1 the master clock input.
Otherwise, The Master clock frequency is calculated accordingly to the following formula:
MCLK_x = SAI_CK_x / (MCKDIV[3:0] * 2)


Меньше уже не сделать...
А какая частота (и откуда берется) и какой формат?
Allregia
Цитата(Genadi Zawidowski @ May 1 2016, 01:48) *
Меньше уже не сделать...


В том-то и дело!
Непонятно, зачем они вместо I2S в SPI сделали это SAI, с кучей дополнительных возможностей, но допустили при этом такие досадные элементарные промахи!
Я теперь даже не знаю как быть в одном из проектов. Попытаюсь поставить туда Ф4, на нем все работает, но не уверен что получится, все было расчитано под Л4.

Цитата
А какая частота (и откуда берется) и какой формат?


Я писал выше - клок 512фс, т.е 24.576мгц. Формат - самый стандартный I2S, bclk/lrclk=64.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.