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

    

LPC4347 + DMA + перепрограммирование регистра сравнения таймера

Добрый день, коллеги! Поздравляю нас с новой версией портала!

Теперь по делу. Мне необходимо запускать опрос данных с АЦП на шине SPI каждый 2 мкс. Нужно опросить 8 каналов. Т.е. это занимает 15 мкс. Затем выдерживается пауза 35 мкс, и снова опрашиваются 8 каналов. Т.е. каналы опрашиваются фреймами, которые повторяются каждые 50 мкс. Я настроил один канал DMA для передачи через SPI, один для приёма, и один - для перепрограммирования регистра сравнения таймера MR1. Самое интересное, что таймер не сбрасывается (хотя в регистре настройки таймера явно установлен бит Reset on Match) по событию сравнения, дёргает однократно DMA, и считает себе дальше. Следовательно оставшиеся 7 каналов АЦП не опрашиваются. Если через DMA не перепрограммировать MR0, то таймер сбрасывается. Пока задачу решил следующим образом. Я настраиваю MR0 на 50 мкс со сбросом. А DMA записывает MR1 следующими значениями: 2, 4, 6, 8 и т.д. Т.е. получается таймер тикает, и каждые две мкс формирует событие сравнения на канале 1, которое дёргает DMA, а тот, в свою очередь опрашивает АЦП. Затем, когда таймер дотикает до MR0, который записывается однократно вручную, сбрасывается, и цикл повторяется. Так всё работает прекрасно. Вопрос: почему может не сбрасываться таймер, если его MR1 программирует DMA? В документации об этом ни слова. Может быть событие сравнения генерируется на такт раньше, чем сброс таймера (т.е. они не синхронны)? А к этому времени, DMA уже успел перепрограммировать MR1? В общем небольшая неоднозначность, которую бы хотелось прояснить для себя. Возможно, это особенность конкретного чипа. Но в целом всё очень красиво получается: АЦП опрашивается МК по-сути без участия процессорного ядра. Только прерывание после прохода DMA по связному списку вызывается, чтобы обновить свои регистры.

Возможно написал немного сумбурно, если будет необходимо, отвечу на дополнительные вопросы.

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


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

Как я понял - проблема у Вас возникает из-за записи DMA-каналом значения в регистр MRx таймера? А зачем что-то обновлять в MRx если прерывания нужны с фиксированным периодом? Пускай он себе и генерит с фиксированным периодом события к DMA. И не надо трогать MRx.

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

 

PS: А с новой версией не поздравлять нужно, а выражать соболезнования - пока что в ней столько багов, что пользоваться трудно. :(

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


Ссылка на сообщение
Поделиться на другие сайты
8 hours ago, jcxz said:

И не надо трогать MRx.

В том-то и дело, что транзакции на шине нужны с таким интервалом: 2, 2, 2, 2, 2, 2, 2, 35 мкс. Т.е. мы опрашиваем 8 каналом АЦП каждые 2 мкс, затем ждём 35 мкс, и повторяем всё сначала. Вот я и решил, что мне проще перепрограммировать MR.

8 hours ago, jcxz said:

2 мкс - слишком малое время.

Гм... я подумал, что проц, работающий на 180 МГц справится...

8 hours ago, jcxz said:

с новой версией не поздравлять нужно, а выражать соболезнования - пока что в ней столько багов, что пользоваться трудно. :(

Да, использовать её я бы сказал очень сложно. Но всё же решил найти каплю позитива)))

 

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


Ссылка на сообщение
Поделиться на другие сайты
5 часов назад, haker_fox сказал:

В том-то и дело, что транзакции на шине нужны с таким интервалом: 2, 2, 2, 2, 2, 2, 2, 35 мкс. Т.е. мы опрашиваем 8 каналом АЦП каждые 2 мкс, затем ждём 35 мкс, и повторяем всё сначала. Вот я и решил, что мне проще перепрограммировать MR.

А зачем каждые 2 мкс? Что за АЦП такое, что не позволяет считать единым блоком эти 7 слов, а требует их с периодом именно 2 мкс? Это действительно так нужно?

Почему нельзя запрограммировать SCLK на частоту == число_бит/2e-6 Гц и считать данные из АЦП единым блоком, а потом сделать паузу до следующего блока? Сами преобразования в АЦП что-ли тактируются от SCLK и поэтому выбор частоты ограничен?

Но даже если так, то в Вашем МК есть SGPIO, который позволяет сделать что угодно с времянкой сигналов последовательного канала. Если там какие-то хитрые требования, то можно сделать на нём.

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


Ссылка на сообщение
Поделиться на другие сайты
4 minutes ago, jcxz said:

А зачем каждые 2 мкс? Что за АЦП такое, что не позволяет считать единым блоком эти 7 слов, а требует их с периодом именно 2 мкс? Это действительно так нужно?

ADS8638. Там для запуска преобразования каждого канала необоходимо ронять CS в лог. 0. Поэтому разом считать невозможно.

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


Ссылка на сообщение
Поделиться на другие сайты
6 minutes ago, jcxz said:

Но даже если так, то в Вашем МК есть SGPIO, который позволяет сделать что угодно с времянкой сигналов последовательного канала. Если там какие-то хитрые требования, то можно сделать на нём.

SGPIO заняты другой периферией. А кидать кучу волосни просто сейчас не хочется. Вот и пробую решить задачу, используя DMA. Кстати, а как вы посчитали, что 2 мкс - это мало?

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


Ссылка на сообщение
Поделиться на другие сайты
5 часов назад, haker_fox сказал:

Гм... я подумал, что проц, работающий на 180 МГц справится...

А при чём частота проца? Да хоть на ГГц бы работал - один фиг. Если у Вас тактирование работы АЦП (его преобразования идут от частоты посылок по SPI), то привязав их к работе DMA, сразу получаете джиттер в сэмплировании АЦП. И уже ни о какой времянке снятого сигнала говорить не приходится.

И какая частота проца тут совсем никак не зависит. Зависит от того: с каким регионом памяти он в данный момент работает, от плотности этой работы (скомпилили с бОльшей оптимизацией и начало глючить, или вышла новая версия компилятора, который по другому стал строить код - и такой код перестаёт работать). И у Вас только этот один канал работает по DMA? А других нет? А если они ещё будут конкурировать за шину? А одна только перезагрузка регистров управления DMA, при переключении на следующий блок связного списка уже потребует много тактов. А если это по времени совпало с другим каналом DMA - и у него такая же перезагрузка в этот момент случилась?

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


Ссылка на сообщение
Поделиться на другие сайты
10 минут назад, haker_fox сказал:

SGPIO заняты другой периферией. А кидать кучу волосни просто сейчас не хочется. Вот и пробую решить задачу, используя DMA. Кстати, а как вы посчитали, что 2 мкс - это мало?

Вы же сами написали, что преобразования АЦП запускаются стартом передачи слова по SPI. Соответственно любая задержка. Решил например CPU в этот момент с этого региона памяти считать данные командой LDM {R0-R11} - получите задержку в 12 тактов! А если в этот же момент ещё и другой канал DMA выполняет перегрузку след. блока связного списка? Тогда сюда ещё приплюсуется N тактов. А если 2 DMA-канала свои связные списки перегружают?....  ;)

Т.е. - в Вашей реализации вообще нельзя говорить о какой-то частоте преобразований АЦП. Сейчас она одна, через секунду другая, после добавления каких-то частей кода и перекомпиляции - 3-я.

 

PS: Такую задачу нужно решать или на другом МК, где можно выставить времянку отправки слов в самом SPI. Или на LPC43xx - через SGPIO например.

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

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


Ссылка на сообщение
Поделиться на другие сайты
7 minutes ago, jcxz said:

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

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

Т.е., я правильно понял, что даже если таймер запускает канал DMA-SPI (по линии burst request), то такая схема может работать ненадёжно?

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


Ссылка на сообщение
Поделиться на другие сайты
5 минут назад, haker_fox сказал:

Т.е., я правильно понял, что даже если таймер запускает канал DMA-SPI (по линии burst request), то такая схема может работать ненадёжно?

Конечно. Ведь DMA работает по общей шине с CPU и другими DMA-каналами. Значит джиттер его пересылок всё равно будет. Даже если назначить ему наивысший приоритет. К тому же в LPC43xx насколько помню приоритет DMA нельзя назначить выше чем у CPU?

Но даже если бы и было можно, один фиг. Сами подумайте: вот пинает таймер сейчас DMA, а в это время шина занята - например CPU читает по этой шине длинной командой (LDM)? Или в этот момент другой DMA-канал (даже менее приоритетный), перегружает свой LLI-блок? Или выполняет burst-пересылку? Такая транзакция не прервётся, этот канал будет ждать освобождение шины.

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


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

Кстати, а по самому первому вопросу, кто-нибудь может дать комментарий? Я имею в виду, почему таймер генерит по сравнению транзакцию ПДП, но не сбрасывается? Особенности SoC?

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


Ссылка на сообщение
Поделиться на другие сайты
1 minute ago, jcxz said:

Такая транзакция не прервётся, этот канал будет ждать освобождение шины.

В принципе, мне джиттер между каналами не нормирован по ТЗ. Самое главное - выдавать сэмплы по 8 каналам каждые 50 мкс. Т.е. пока этот вопрос я могу оставить полуоткрытым. 50 мкс, полагаю, должно хватить, чтобы всё устаканилось.

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


Ссылка на сообщение
Поделиться на другие сайты
3 минуты назад, haker_fox сказал:

В принципе, мне джиттер между каналами не нормирован по ТЗ. Самое главное - выдавать сэмплы по 8 каналам каждые 50 мкс. Т.е. пока этот вопрос я могу оставить полуоткрытым. 50 мкс, полагаю, должно хватить, чтобы всё устаканилось.

50 мкс тоже будут с джиттером  ;)

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


Ссылка на сообщение
Поделиться на другие сайты
5 минут назад, haker_fox сказал:

Кстати, а по самому первому вопросу, кто-нибудь может дать комментарий? Я имею в виду, почему таймер генерит по сравнению транзакцию ПДП, но не сбрасывается? Особенности SoC?

Возможно баг в периферии. Делал такое когда-то на LPC17xx, но уже не помню особенностей.

Попробуйте разрешить прерывание вместе с reset-ом. Даже не нужно его обрабатывать или разрешать в NVIC, достаточно установить битик в MCR.

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


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

1) Кстати - пришёл на ум ещё вариант как можно работать через SPI. Читать даташит на ADS8638 лень - там в исходящем из МК канале SPI передаётся какая-то инфа в неё? Или только чтение?

Если нет, то можно сигнал CS формировать передаваемым через MOSI словом. Тогда весь блок из 7 слов можно DMA-каналом сразу закинуть в FIFO SPI и избавиться от джиттера 2 мкс совсем.  ;)

 

2) Ещё лучше и совсем без джиттера и по 2 мкс и по 50 мкс: формировать сигналы SCLK и CS таймером, а SPI МК перевести в слэйв-режим, принимать эти сигналы как внешние и выплёвывать данные из FIFO SPI. FIFO SPI заполнять штатным образом - от запросов SPI-FIFO к DMA.

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


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

Для публикации сообщений создайте учётную запись или авторизуйтесь

Вы должны быть пользователем, чтобы оставить комментарий

Создать учетную запись

Зарегистрируйте новую учётную запись в нашем сообществе. Это очень просто!

Регистрация нового пользователя

Войти

Уже есть аккаунт? Войти в систему.

Войти
Авторизация