Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: I2S full duplex dma
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
nicks80
Проблема в следующем.
Имеется кодек UDA1344 в связке с stm32f407vet6
Данные читаются по I2S из кодека в память и потом выдаются в кодек обратно по I2S с помощью DMA.
Все работает как часы но на объекте раз в день или два. происходит сбой. результатом такого сбоя является сильный шум из кодека.
Как я понял такой шум появляется если самому дотронутся до линии CK I2S. которая отвечает за очередность передачи битов.
Печально что восстановления не происходит при переходе 1 в 0 или наоборот 0 в 1 линии WS(LR CH). То есть получается что данные так и идут перемешанными битами соответственно и програмно никак это не отследишь.
Но оно и понятно если бит(помеха) лишний проскочил то все уже съехало а dma все шлет и шлет. какими средствами справляться хз.
_4afc_
Если сбой не отражается в статусных регистрах stm32f407vet6 - то никак. Ну разве что оценивать уровень шума - и перезапускать кодек.

Вообще такая картина со всеми синхронными интерфейсами в МК и ЦСП. Поэтому я перешел на ПЛИС и сам пишу блоки синхронного приёма/передачи.
OVladimir
Не знаю, поможет или нет, но похожую проблему пришлось решать несколько лет назад на STM32F103Rx + GSM modem (несколько разных модемов). I2S в МК в режиме Slave, длинный WA, передаёт в модем голосовую запись, иногда происходит рассинхронизация в итоге слышен шум....
Идея в том, что по прерыванию TXE проверяется уровень на WS линии тупо при помощи GPIO (в этом МК IDR всегда отображает картину на входе независимо от выбранной функции). Если прерывание происходит на середине слова, это легко можно определить проверив уровень WS(должен быть высокий, а он низкий и наоборот), то делаем переинициализацию модуля I2S. В моём случае метод сработал без каких-либо заметных для ушей помех.
nicks80
Цитата(OVladimir @ Sep 9 2016, 17:48) *
Не знаю, поможет или нет, но похожую проблему пришлось решать несколько лет назад на STM32F103Rx + GSM modem (несколько разных модемов). I2S в МК в режиме Slave, длинный WA, передаёт в модем голосовую запись, иногда происходит рассинхронизация в итоге слышен шум....
Идея в том, что по прерыванию TXE проверяется уровень на WS линии тупо при помощи GPIO (в этом МК IDR всегда отображает картину на входе независимо от выбранной функции). Если прерывание происходит на середине слова, это легко можно определить проверив уровень WS(должен быть высокий, а он низкий и наоборот), то делаем переинициализацию модуля I2S. В моём случае метод сработал без каких-либо заметных для ушей помех.

.идея понятна но как на протяжении 16 бит отследить состояние ноги WS.
у меня к томуже все через DMA.
проблема серьезная с этим WS и рассинхронизацией. у меня длинна дорожки 20мм. и при прикосании даже проводником 10см происходит сбой.
попробовал через постоянную составляющую сигнала тоже не прокатило.(хотя по идее должно сработать)
OVladimir
Я использовал только TXE прерывание для проверки рассинхронизации I2S, этого оказалось достаточно. А DMA или не DMA, по-моему, не имеет никакого значения, ведь глючит модуль I2S, странно, что инженеры ST до сих пор не исправили.. Кстати, загляните в Errat'у тоже.
nicks80
Цитата(OVladimir @ Sep 11 2016, 13:25) *
Я использовал только TXE прерывание для проверки рассинхронизации I2S, этого оказалось достаточно. А DMA или не DMA, по-моему, не имеет никакого значения, ведь глючит модуль I2S, странно, что инженеры ST до сих пор не исправили.. Кстати, загляните в Errat'у тоже.

А можете подетальный или часть кода привести. а то я не понимаю как опрашивать в нужный момент на протяжении 16 бит.
aaarrr
Случаи разные: у OVladimir'а МК ведомый, а у вас - кодек.
По-моему, нужно:
1. Разобраться с целостностью сигналов (в любом случае)
2. Заменить кодек на что-нибудь более современное
nicks80
Цитата(aaarrr @ Sep 11 2016, 13:52) *
Случаи разные: у OVladimir'а МК ведомый, а у вас - кодек.
По-моему, нужно:
1. Разобраться с целостностью сигналов (в любом случае)
2. Заменить кодек на что-нибудь более современное

У меня контроллеры работают круглогодично в шкафу где куча частотников по десяткам киловатт. кодек сбивается и это факт. может думаю кондер с резистором повесить на сигнальных данных. а вообще все входы защищены и сбивается именно от помех. какой кодек не поставь сбивается именно в камне прием да и времени нет.
aaarrr
Давайте уточним: сбивается только прием, передача остается нормальной? Можете схему включения привести?
jcxz
Завести сигнал клока параллельно на любой таймерный вход в счётном режиме и подсчитывать число переходов 0->1 и 1->0 за время кадра по этому таймеру. Если получено недопустимое число - реинит I2S.

2ТС: Вы ищете сочуствие или всё-таки совет?? Если 2ое, то чтобы получить осмысленные и полезные советы, следует приводить подробное и внятное описание проблемы. Сюда следует отнести: схемы включения, диаграммы сигналов и т.п. Ибо здесь не форум телепатов.
nicks80
Цитата(aaarrr @ Sep 11 2016, 15:16) *
Давайте уточним: сбивается только прием, передача остается нормальной? Можете схему включения привести?

Передача сбиваться не может в кодеке по перепадам WS производится сброс счетчика битов. сбивается именно прием. ожидал что будет присутствовать постоянная составляющая в сигнале принимаемом но как оказалось сдвиг битов не изменяет ее.


Цитата(nicks80 @ Sep 11 2016, 15:50) *
Передача сбиваться не может в кодеке по перепадам WS производится сброс счетчика битов. сбивается именно прием. ожидал что будет присутствовать постоянная составляющая в сигнале принимаемом но как оказалось сдвиг битов не изменяет ее. и яэто вижу по данным которые принял i2s проца.

aaarrr
Цитата(nicks80 @ Sep 11 2016, 14:52) *
сбивается именно прием

На прием используется отдельный I2S?
nicks80
Цитата(jcxz @ Sep 11 2016, 15:29) *
Завести сигнал клока параллельно на любой таймерный вход в счётном режиме и подсчитывать число переходов 0->1 и 1->0 за время кадра по этому таймеру. Если получено недопустимое число - реинит I2S.

2ТС: Вы ищете сочуствие или всё-таки совет?? Если 2ое, то чтобы получить осмысленные и полезные советы, следует приводить подробное и внятное описание проблемы. Сюда следует отнести: схемы включения, диаграммы сигналов и т.п. Ибо здесь не форум телепатов.

1й вариант отпадает т.к. непонятно как помеха поведет себя по отношению к этим двум ногам. понятно что процессор выдает клоки нормальные. наверно здесь лучше таймер завести по перепаду WS и сравнивать допустим через 1024 отсчета границы сигнала WS.

схема включения стандартная


Цитата(aaarrr @ Sep 11 2016, 16:00) *
На прием используется отдельный I2S?

нет, все одним I2S2 принимается и передается.

CODE
/// Peripheral DMA init
hdma_i2s2_ext_rx.Instance = DMA1_Stream3;
hdma_i2s2_ext_rx.Init.Channel = DMA_CHANNEL_3;
hdma_i2s2_ext_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_i2s2_ext_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_i2s2_ext_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_i2s2_ext_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
hdma_i2s2_ext_rx.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
hdma_i2s2_ext_rx.Init.Mode = DMA_CIRCULAR;
hdma_i2s2_ext_rx.Init.Priority = DMA_PRIORITY_HIGH;
hdma_i2s2_ext_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;//ENABLE;
hdma_i2s2_ext_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_HALFFULL;
hdma_i2s2_ext_rx.Init.MemBurst = DMA_MBURST_SINGLE;
hdma_i2s2_ext_rx.Init.PeriphBurst = DMA_PBURST_SINGLE;
HAL_DMA_Init(&hdma_i2s2_ext_rx);

__HAL_LINKDMA(hi2s,hdmarx,hdma_i2s2_ext_rx);

hdma_i2s2_ext_tx.Instance = DMA1_Stream4;
hdma_i2s2_ext_tx.Init.Channel = DMA_CHANNEL_0;
hdma_i2s2_ext_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_i2s2_ext_tx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_i2s2_ext_tx.Init.MemInc = DMA_MINC_ENABLE;
hdma_i2s2_ext_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
hdma_i2s2_ext_tx.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
hdma_i2s2_ext_tx.Init.Mode = DMA_CIRCULAR;
hdma_i2s2_ext_tx.Init.Priority = DMA_PRIORITY_HIGH;
hdma_i2s2_ext_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;//ENABLE;
hdma_i2s2_ext_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_HALFFULL;
hdma_i2s2_ext_tx.Init.MemBurst = DMA_MBURST_SINGLE;
hdma_i2s2_ext_tx.Init.PeriphBurst = DMA_PBURST_SINGLE;
HAL_DMA_Init(&hdma_i2s2_ext_tx);

__HAL_LINKDMA(hi2s,hdmatx,hdma_i2s2_ext_tx);


.............
hi2s2.Instance = SPI2;
hi2s2.Init.Mode = I2S_MODE_MASTER_TX;
hi2s2.Init.Standard = I2S_STANDARD_PHILIPS;
hi2s2.Init.DataFormat = I2S_DATAFORMAT_16B;//I2S_DATAFORMAT_16B;
hi2s2.Init.MCLKOutput = I2S_MCLKOUTPUT_ENABLE;
hi2s2.Init.AudioFreq = g_nI2SFreq[nSR];
hi2s2.Init.CPOL = I2S_CPOL_LOW;

hi2s2.Init.ClockSource = I2S_CLOCK_PLL;
hi2s2.Init.FullDuplexMode = I2S_FULLDUPLEXMODE_ENABLE;

RCC_PeriphCLKInitTypeDef PeriphClkInitStruct;
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_I2S;
PeriphClkInitStruct.PLLI2S.PLLI2SN = g_nI2SPLLN[nSR];
PeriphClkInitStruct.PLLI2S.PLLI2SR = g_nI2SPLLR[nSR];
HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);


HAL_I2S_Init(&hi2s2);
HAL_I2SEx_TransmitReceive_DMA(&hi2s2,(unsigned short*)i2s2_DelayBuf,(unsigned short*)i2s2_DelayBuf,(nDelay* ( 1<<nFFT ))*I2S2_DELAY_BUFFCHANNELS);

MX_TIM7_Init(g_nI2S_SR[nSR],1<<nFFT);

g_nI2S2_nFFT = nFFT;
g_nI2S2_DelayBufCmpl = 0;

g_nI2S2_nSR = nSR;


я наверно совсем заблудился. Если мастер процессор и он выдает сигналы WS. то получается кодек неверные данные выдает я же его тактирую.
jcxz
Цитата(nicks80 @ Sep 11 2016, 18:42) *
я наверно совсем заблудился. Если мастер процессор и он выдает сигналы WS. то получается кодек неверные данные выдает я же его тактирую.

Вообще-то мой совет касался случая если у Вас мастер - кодек. Если у Вас мастер - МК и как Вы утверждаете:
Цитата(nicks80 @ Sep 11 2016, 17:52) *
Передача сбиваться не может в кодеке по перепадам WS производится сброс счетчика битов.

по WS - сбрасывается битовая машина состояний, то ни приём ни передача не могут сбиваться, так как в кодеке они сбрасываются по WS, а МК по определению не может сбиваться, так как сам и генерит и WS и CLK. Значит ошибка у Вас где-то в другом.
Источник WS же у Вас МК?

Пока, судя по симптомам, всё выглядит как будто сбивается кол-во CLK во фрейме, фиксируемое кодеком. Т.е. - он не сбрасывает счётчик битов при изменении WS.
Кол-во клоков во фрейме WS передаёте равным числу битов или клоков больше чем бит?
Управление/конфигурирование кодека идёт по тому же каналу I2S что и данные? (вроде не вижу отдельных шин)
Genadi Zawidowski
Судя по схеме, кодек в режиме конфигурирования пинами стоит.
nicks80
Цитата(Genadi Zawidowski @ Sep 11 2016, 20:06) *
Судя по схеме, кодек в режиме конфигурирования пинами стоит.

да конфигурирую пинами.
я пробовал математически сдвиг отловить не по шуму. думал даже в сигнал примешивать высокочастотный и смотреть гармоники так как у меня там ффт крутится. но все отлавливается еще проще как выяснилось.
Я включил таймер. и смотрю количество тиков в периоде между заполнениями буферов. Это значение меняется +-1. А при сбое прыгает до 20-30 процентов а то и более. отлавливается все четко.
Видать клоки проскакивают. Но странно ведь при переходе WS должны биты опять синхронизироватся. Наверно связка DMA и I2S это не отслеживает.
jcxz
Цитата(nicks80 @ Sep 12 2016, 00:04) *
но все отлавливается еще проще как выяснилось.
Я включил таймер. и смотрю количество тиков в периоде между заполнениями буферов. Это значение меняется +-1. А при сбое прыгает до 20-30 процентов а то и более. отлавливается все четко.
Видать клоки проскакивают. Но странно ведь при переходе WS должны биты опять синхронизироватся. Наверно связка DMA и I2S это не отслеживает.

Кол-во тиков должно быть +-0, а если у Вас и при нормальной работе +-1, то и при сбое так же может быть. И тогда ничего не отловите.
И испытывать надо не пальцем, а с генератора импульсы подавать. Чтобы какой-то вменяемый и повторяемый результат получить.
Вобщем - так ничего у Вас и не отлавливается...
_4afc_
Цитата(nicks80 @ Sep 11 2016, 22:04) *
Но странно ведь при переходе WS должны биты опять синхронизироватся.


Не должны - а хотелось бы. Факт автоматической байтовой ресинхронизации с каждым WS описан в даташите?
Если - нет, то после синхронизации по первому WS - потом просто считаются такты, и на WS уже не смотрят.

Была такая же проблема у двух Atmel связанных по I2S - решил перейдя на USART.

Точно также в BF561 при приёме видеокадра - тупо считаются линии и точки. При сбое на тактовой - изображение съезжает и не исправляется с новым кадром. При этом никакие статусы не меняются. Единственный вариант - каждый кадр успевать инитить заново блок приёма видеоданных.

Кстати, у вас на линии WS резистор есть последовательный?
nicks80
Цитата(jcxz @ Sep 12 2016, 07:57) *
Кол-во тиков должно быть +-0, а если у Вас и при нормальной работе +-1, то и при сбое так же может быть. И тогда ничего не отловите.
И испытывать надо не пальцем, а с генератора импульсы подавать. Чтобы какой-то вменяемый и повторяемый результат получить.
Вобщем - так ничего у Вас и не отлавливается...

Если период даже при условии что где-то прибавилось и столько же убавилось равен. То рассинхронизации не будет на следующей порции данных.
Я сейчас уменьшил буфер до 64 отсчетов. сделал прерывание с наивысшим приоритетом. и таймером до изменения бита могу отловить. Другой вариант это сравнивать встроенной ацепешкой данные на входе и выходе.
Странно почему такой чуствительный этот тракт. входы выходе сделаны через резисторы с диодами и все ровно сбоит время от времени. на столе сутками стоит и все ок. через пару дней надо 3 контроллера времени мало.


Цитата(jcxz @ Sep 12 2016, 07:57) *
Кол-во тиков должно быть +-0, а если у Вас и при нормальной работе +-1, то и при сбое так же может быть. И тогда ничего не отловите.
И испытывать надо не пальцем, а с генератора импульсы подавать. Чтобы какой-то вменяемый и повторяемый результат получить.
Вобщем - так ничего у Вас и не отлавливается...

Если период даже при условии что где-то прибавилось и столько же убавилось равен. То рассинхронизации не будет на следующей порции данных.
Я сейчас уменьшил буфер до 64 отсчетов. сделал прерывание с наивысшим приоритетом. и таймером до изменения бита могу отловить. Другой вариант это сравнивать встроенной ацепешкой данные на входе и выходе.
Странно почему такой чуствительный этот тракт. входы выходе сделаны через резисторы с диодами и все ровно сбоит время от времени. на столе сутками стоит и все ок. через пару дней надо 3 контроллера времени мало.


Цитата(_4afc_ @ Sep 12 2016, 11:32) *
Не должны - а хотелось бы. Факт автоматической байтовой ресинхронизации с каждым WS описан в даташите?
Если - нет, то после синхронизации по первому WS - потом просто считаются такты, и на WS уже не смотрят.

Была такая же проблема у двух Atmel связанных по I2S - решил перейдя на USART.

Точно также в BF561 при приёме видеокадра - тупо считаются линии и точки. При сбое на тактовой - изображение съезжает и не исправляется с новым кадром. При этом никакие статусы не меняются. Единственный вариант - каждый кадр успевать инитить заново блок приёма видеоданных.

Кстати, у вас на линии WS резистор есть последовательный?

резистора нет. планирую от мастера поставит RC фильтр к слейву.
nicks80
Что только не предпринимал оказывалось костылями. В итоге пожертвовал процессорным временем и сделал на 2х таймерах с прерыванием. работает как часы.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.