Не блокирующий SPI DMA - Добавлен обратный вызов к функциям SPI DMA (DMASEND, DMATRANSFER...)

victor_pv
Вторник 21 февраля 2017 г. 20:05
ОБНОВЛЯТЬ:
Рабочий код в этом посте и объяснение, как изменить SDFAT, чтобы использовать его в следующем посте после этого:
http: // www.STM32duino.com/viewtopic.PHP ... = 60#P30306

============================================================================= ====


Это то, что Роджер предложил несколько раз, и, похоже, это имеет смысл.

В настоящее время функции DMA TX/RX, которые мы добавили в блок библиотеки SPI до тех пор, пока передача DMA не будет завершена или не будет.
Это изменение добавит 2 функции в библиотеку SPI, аналогично библиотеке Arduino Official I2S:
Congratulations, you have installed the STM32duino bootloader See https://github.com/rogerclarkmelbourne/STM32duino-bootloader For more information about Arduino on STM32 and http://www.stm32duino.com

Rogerclark
Вторник 21 февраля 2017 г. 8:34 вечера
Виктор

Вероятно, это стоит PM'ing @StevStrong, если он не видит эту ветку, так как он недавно проделал большую работу в SPI.

Я думаю, что у меня есть один ожидающий пиар от Stev, но, похоже, он замедляет SPI, поэтому я еще не поступил на него. Но это может быть необходимо, поскольку содержит исправления ошибок.

Я думаю, что существует общая проблема с обратными вызовами в классах C ++, так как доступ к адресам статических функций можно.
Так что это должно быть общим ISR для всех случаев.

Другие API, с которыми я работаю, позвольте вам передать указатель на функцию обратного вызова, в трансферную функцию. Что мне кажется логичным.

victor_pv
Вт 21 февраля 2017 г. 8:50 вечера
Rogerclark написал:Виктор

Вероятно, это стоит PM'ing @StevStrong, если он не видит эту ветку, так как он недавно проделал большую работу в SPI.

Я думаю, что у меня есть один ожидающий пиар от Stev, но, похоже, он замедляет SPI, поэтому я еще не поступил на него. Но это может быть необходимо, поскольку содержит исправления ошибок.

Я думаю, что существует общая проблема с обратными вызовами в классах C ++, так как доступ к адресам статических функций можно.
Так что это должно быть общим ISR для всех случаев.

Другие API, с которыми я работаю, позвольте вам передать указатель на функцию обратного вызова, в трансферную функцию. Что мне кажется логичным.

Rogerclark
Вт 21 февраля 2017 г. 20:56
Привет, Виктор

Я не тестировал последний пиар @stevstrongs, но предыдущий был медленнее, чем то, что у нас было раньше :-(

Re: один ISR на канал SPI

Мне звучит нормально.


Спасибо

Роджер

Стивестронг
Вт 21 февраля 2017 г. 9:14 вечера
Пытаясь оптимизировать ILI9486 LIB, я уже внедрил неблокирующий DMA с обратным вызовом в конце работы. Это включало короткий ISR в конце задания, который называется функция CB, если он установлен пользователем в ISR.
К сожалению, DMA очень сильно замедляет процессор, поэтому в конце, включая Ovehead to. Я проверил его с помощью графического теста Adafruit. Вы можете следовать результатам этой ветки.
Моя версия была разработана, чтобы зарезервировать соответствующий канал DMA (я думаю, канал 3) только для SPI. Тем не менее, я не был доволен результатом.

victor_pv
Вт 21 февраля 2017 г., 21:32
Стивестронг написал:Пытаясь оптимизировать ILI9486 LIB, я уже внедрил неблокирующий DMA с обратным вызовом в конце работы. Это включало короткий ISR в конце задания, который называется функция CB, если он установлен пользователем в ISR.
К сожалению, DMA очень сильно замедляет процессор, поэтому в конце, включая Ovehead to. Я проверил его с помощью графического теста Adafruit. Вы можете следовать результатам этой ветки.
Моя версия была разработана, чтобы зарезервировать соответствующий канал DMA (я думаю, канал 3) только для SPI. Тем не менее, я не был доволен результатом.

Стивестронг
Вт 21 февраля 2017 г. 22:00
Конечно, это зависит от приложения.
Дисплей LIB также частично писал большие блоки, однако общий усиление скорости не достигнут.
Еще раз, процессор сильно замедляется из -за DMA, работающего на фоне.
Не понимаю меня неправильно, я вижу теоретическое преимущество, поэтому я также проверил это. Тем не менее, результаты не убедили меня.

Поскольку у меня нет никакого другого приложения, в котором сохраненное время будет играть большую роль, чем на дисплее, я сдался, чтобы подтолкнуть его в репо.
Но не стесняйтесь, чтобы он бежал. Если вы думаете, что это могло бы помочь, я мог бы поделиться своей местной версией.

victor_pv
Ср 22 февраля 2017 г. 1:02
Стивестронг написал:Конечно, это зависит от приложения.
Дисплей LIB также частично писал большие блоки, однако общий усиление скорости не достигнут.
Еще раз, процессор сильно замедляется из -за DMA, работающего на фоне.
Не понимаю меня неправильно, я вижу теоретическое преимущество, поэтому я также проверил это. Тем не менее, результаты не убедили меня.

Поскольку у меня нет никакого другого приложения, в котором сохраненное время будет играть большую роль, чем на дисплее, я сдался, чтобы подтолкнуть его в репо.
Но не стесняйтесь, чтобы он бежал. Если вы думаете, что это могло бы помочь, я мог бы поделиться своей местной версией.

Стивестронг
Ср 22 февраля 2017 г. 9:50 утра
Пожалуйста, проверьте мои комментарии, размещенные здесь: https: // github.com/rogerclarkmelbourne/ ... -277516813

Racemaniac
Ср 22 февраля 2017 г. 10:20
Стивестронг написал:Конечно, это зависит от приложения.
Дисплей LIB также частично писал большие блоки, однако общий усиление скорости не достигнут.
Еще раз, процессор сильно замедляется из -за DMA, работающего на фоне.
Не понимаю меня неправильно, я вижу теоретическое преимущество, поэтому я также проверил это. Тем не менее, результаты не убедили меня.

Поскольку у меня нет никакого другого приложения, в котором сохраненное время будет играть большую роль, чем на дисплее, я сдался, чтобы подтолкнуть его в репо.
Но не стесняйтесь, чтобы он бежал. Если вы думаете, что это могло бы помочь, я мог бы поделиться своей местной версией.

Стивестронг
Ср 22 февраля 2017 г. 11:39
и как DMA может не дать ускорение, даже если процессор замедляется? Ваш перевод займет столь же длинное, как и с блокирующей передачей, и даже если процессор замедлится, по крайней мере, он может выполнить некоторую работу во время передачи. Вы забыли накладные расходы, чтобы настроить DMA перед каждой транзакцией. И если вы реализуете обратный вызов в конце работы, это также займет время и полностью заблокирует процессор от других задач.
Таким образом, в зависимости от скоростной скорости SPI, накладные расходы вместе с постобработкой могут занять время, необходимое для передачи, скажем, 25 байтов.
Поэтому, если вы переводите 20 байт без DMA, это быстрее, чем передавать его с помощью DMA.

Следовательно, опять же, выбрать соответствующую стратегию сильно зависит от приложения.
Если вы всегда пишете блоки по 256 байтов или более, и у вас есть много задач, которые нужно выполнить между последовательными записями блоков (не только для того, чтобы дождаться предыдущей работы SPI), то использование DMA, безусловно, является хорошим подходом. В противном случае он может быть медленнее, чем версия без DMA.

Racemaniac
Ср 22 февраля 2017 г. 12:06
Стивестронг написал:и как DMA может не дать ускорение, даже если процессор замедляется? Ваш перевод займет столь же длинное, как и с блокирующей передачей, и даже если процессор замедлится, по крайней мере, он может выполнить некоторую работу во время передачи. Вы забыли накладные расходы, чтобы настроить DMA перед каждой транзакцией. И если вы реализуете обратный вызов в конце работы, это также займет время и полностью заблокирует процессор от других задач.
Таким образом, в зависимости от скоростной скорости SPI, накладные расходы вместе с постобработкой могут занять время, необходимое для передачи, скажем, 25 байтов.
Поэтому, если вы переводите 20 байт без DMA, это быстрее, чем передавать его с помощью DMA.

Следовательно, опять же, выбрать соответствующую стратегию сильно зависит от приложения.
Если вы всегда пишете блоки по 256 байтов или более, и у вас есть много задач, которые нужно выполнить между последовательными записями блоков (не только для того, чтобы дождаться предыдущей работы SPI), то использование DMA, безусловно, является хорошим подходом. В противном случае он может быть медленнее, чем версия без DMA.

Стивестронг
Ср 22 февраля 2017 г. 15:06
Выдержка из RM0008: 13.3 функциональное описание DMA
Контроллер DMA выполняет прямую передачу памяти, делясь системной шиной с
Cortex®-M3 Core. Запрос DMA может остановить доступ в системную шину для системной шины
Циклы шины, когда процессор и DMA нацелены на одно и то же пункт назначения (память или
периферийный)
. Матрица автобусов реализует расписание круглых робина, тем самым обеспечивая по крайней мере половину
пропускной способности системной шины (как для памяти, так и для периферийных) для ЦП.
Таким образом, процессор может быть замедлен до половины его скорости. Чем выше часы SPI, тем хуже ситуация для процессора, если выполняет много доступа к памяти.

Racemaniac
Ср 22 февраля 2017 г. 15:28
Стивестронг написал:Выдержка из RM0008: 13.3 функциональное описание DMA
Контроллер DMA выполняет прямую передачу памяти, делясь системной шиной с
Cortex®-M3 Core. Запрос DMA может остановить доступ в системную шину для системной шины
Циклы шины, когда процессор и DMA нацелены на одно и то же пункт назначения (память или
периферийный)
. Матрица автобусов реализует расписание круглых робина, тем самым обеспечивая по крайней мере половину
пропускной способности системной шины (как для памяти, так и для периферийных) для ЦП.
Таким образом, процессор может быть замедлен до половины его скорости. Чем выше часы SPI, тем хуже ситуация для процессора, если выполняет много доступа к памяти.

victor_pv
Ср 22 февраля 2017 г. 16:17
Стивестронг написал:Пожалуйста, проверьте мои комментарии, размещенные здесь: https: // github.com/rogerclarkmelbourne/ ... -277516813

victor_pv
Ср 22 февраля 2017 г. 16:31
Реданьяк написал:Стивестронг написал:Выдержка из RM0008: 13.3 функциональное описание DMA
Контроллер DMA выполняет прямую передачу памяти, делясь системной шиной с
Cortex®-M3 Core. Запрос DMA может остановить доступ в системную шину для системной шины
Циклы шины, когда процессор и DMA нацелены на одно и то же пункт назначения (память или
периферийный)
. Матрица автобусов реализует расписание круглых робина, тем самым обеспечивая по крайней мере половину
пропускной способности системной шины (как для памяти, так и для периферийных) для ЦП.
Таким образом, процессор может быть замедлен до половины его скорости. Чем выше часы SPI, тем хуже ситуация для процессора, если выполняет много доступа к памяти.

Racemaniac
Ср 22 февраля 2017 г., 19:28
victor_pv написал:Реданьяк написал:Стивестронг написал:Выдержка из RM0008:

Таким образом, процессор может быть замедлен до половины его скорости. Чем выше часы SPI, тем хуже ситуация для процессора, если выполняет много доступа к памяти.

victor_pv
Ср 22 февраля 2017 г., 19:51
Реданьяк написал:
действительно :). Было бы неплохо иметь возможность настроить, что вы не будете повторно использовать канал DMA для чего -то другого и получить более дешевую настройку DMA (вероятно, наиболее часто используйте, поскольку DMA в любом случае вряд ли используется ^^)

И я все еще задаюсь вопросом о том, что приносит в нем одновременно одновременно :). Я действительно собираюсь попробовать, когда у меня будет время, очень приятно знать :).

Любые предложения о том, что справиться с этим с? Просто христон?

victor_pv
Чт 23 февраля 2017 г., 2:51
Реданьяк написал: действительно :). Было бы неплохо иметь возможность настроить, что вы не будете повторно использовать канал DMA для чего -то другого и получить более дешевую настройку DMA (вероятно, наиболее часто используйте, поскольку DMA в любом случае вряд ли используется ^^)

Racemaniac
Чт 23 февраля 2017 г. 8:31
victor_pv написал:Реданьяк написал: действительно :). Было бы неплохо иметь возможность настроить, что вы не будете повторно использовать канал DMA для чего -то другого и получить более дешевую настройку DMA (вероятно, наиболее часто используйте, поскольку DMA в любом случае вряд ли используется ^^)

Стивестронг
Чт 23 февраля 2017 г. 8:36 утра
В моем коде я инициализировал DMA Once (dmasEndinit ()), затем я только что обновил количество данных для передачи и указателя в dmasendbuffer () и включил DMA, чтобы накладные расходы могли быть минимальными.
Я опубликую свою версию здесь вечером.

Racemaniac
Чт 23 февраля 2017 г. 8:51 утра
Стивестронг написал:В моем коде я инициализировал DMA Once (dmasEndinit ()), затем я только что обновил количество данных для передачи и указателя в dmasendbuffer () и включил DMA, чтобы накладные расходы могли быть минимальными.
Я опубликую свою версию здесь вечером.

victor_pv
Чт 23 февраля 2017 г. 15:47
Реданьяк написал:victor_pv написал:Реданьяк написал: действительно :). Было бы неплохо иметь возможность настроить, что вы не будете повторно использовать канал DMA для чего -то другого и получить более дешевую настройку DMA (вероятно, наиболее часто используйте, поскольку DMA в любом случае вряд ли используется ^^)

Racemaniac
Чт 23 февраля 2017 г. 15:55
тьфу, этот вечный компромисс между производительностью и удобством для использования рамки ^^ '
действительно нет серебряной пули или «лучшего» решения >_<. Я все равно хотел бы, чтобы дешевые функции настройки при напряжении использования DMA, но для использования в рамках, полная установка действительно является более безопасным выбором.

Стивестронг
Чт 23 февраля 2017 г. 18:09
Я думаю, что мы могли бы зарезервировать использование DMA в каналах 2-5 для SPI1 и 2 (как RX, так и TX), Пользователь настраивается. Другие каналы будут всегда бесплатными для других целей.
Я прикрепляю свою местную версию SPI.CPP, где я начал реализовать двойной перевод DMA: при отправке одного буфера другой буфер заполняется. Когда первый отправляется, в ISR проверяется, содержит ли другой буфер данных для отправки или нет. Если да, DMA снова будет настроена автоматически. Пока что план, но часть ISR еще не кодирована.
Интересные функции начинаются с строки 479, обусловленных SPI_USE_DMA DEFINE.
Надеюсь, вы сможете получить от этого некоторые идеи.

Олли
Пт 24 февраля 2017 г. 16:15
Дополнительную ссылку можно найти в http: // www.Эмблоки.орг/вики/учебные пособия: ... _disco: SPI. Я включил скриншоты логического анализатора, чтобы показать, как 3 SPI -устройства общаются одновременно с использованием DMA для массовой обработки.

Это основано на принципе, что запросы на передачу SPI не блокируются. Это означает, что запросы помещаются в очередь. При получении запроса из очереди выполняются следующие действия
- Адрес устройства отправляется с использованием опроса
- Номер регистра отправляется с использованием опроса
- Один или два DMA настраиваются в зависимости от того, читая, писать или одновременно прочитать и написать
- Прерывание установлено для завершения DMA
- Как только прерывание получено, «обратный вызов» выполняется, и следующий перевод запускается

Этот код демонстрирует, как скорость и другие настройки SPI могут быть изменены для разных устройств и как регистры конфигурации SPI изменяются только при необходимости.

Этот код демонстрирует, как строка команды/данных DATA DATA.

Ура, Олли

Стивестронг
Пт 24 февраля 2017 г. 16:48
Олли написал:Этот код демонстрирует, как строка команды/данных DATA DATA.
Ура, Олли

Mrburnette
Сб 25 февраля 2017 г. 15:56
.... думать вслух.... Нет ответа ....

Кто -нибудь посмотрел на то, что Пол Стоффреген делает вокруг Teensy 3.1/3.2 ?

Rogerclark
Сб 25 февраля 2017 г. 8:24
Mrburnette написал:.... думать вслух.... Нет ответа ....

Кто -нибудь посмотрел на то, что Пол Стоффреген делает вокруг Teensy 3.1/3.2 ?

victor_pv
Сб 25 февраля 2017 г. 22:51
Из того, что я нашел, они не интегрировали никаких функций DMA в нормальную библиотеку SPI.
Есть другая библиотека, DMASPI, которая обладает возможностями DMA:

https: // github.com/crteensy/dmaspi

Это работает, аналогично тому, над чем работал Стив, он передает очередь с серией свойств (буферный указатель, размер и PIN -объект для управления CS), затем обслуживает эти передачи в порядке.

Не уверен, что все, что стоит усилий, как тестировал Стив, для небольших переводов не улучшает производительность из -за всех накладных расходов, и библиотеки, использующие его.

Rogerclark
Солнце 26 февраля 2017 г. 12:40
Я полностью согласен.

Не стоит добавлять этот уровень сложности, так как вряд ли кто -нибудь будет использовать его.

victor_pv
Солнце 26 февраля 2017 г. 1:23
Первый выстрел в разделении настройки передачи DMA и стрельбы по передаче.
В основном я только что отделил код, который ранее находился в DMASEND в двух частях, DMASENSEDSET настроил передачу, за исключением длины и включил канал. Затем вы называете DmasenDrepeat (мне не очень нравится это имя, но не могу думать о других подходящих, которые мне нравятся) с длиной передачи, и который устанавливает регистр DMACNDTR, который необходимо перезагрузить для новой передачи, и и и позволяет канал. Если функция обратного вызова была установлена ​​ранее, не блокирует и не возвращает 0 для успеха. Если функция обратного вызова не была установлена, она будет блокировать.
SPI.DMASEND имеет точно такую ​​же функциональность, что и раньше, поэтому любой использующий код не должен ломаться каким -либо образом, но теперь он использует другие 2 функции для выполнения работы.

Таким образом, если вы хотите отправить несколько байтов с того же буферного указателя, вы только вызовите SPI.dmasendrepeat с 1 параметром, количество байтов для отправки, все остальное остается таким же, как и последняя передача, поэтому вам нужно только заполнить буфер и уволить передачу.

Что вы думаете, ребята? Это до сих пор не реализует внутренний буфер, который тестировал Стивен.

РЕДАКТИРОВАТЬ: Я понимаю, что может быть хорошо добавить чеки, чтобы подтвердить, существует ли уже в процессе передачи, прежде чем изменить настройки. Это зависит, если мы предпочитаем такую ​​маленькую накладную расходы для безопасности.

// the setup function runs once when you press reset or power the board void setup() { // initialize digital pin PB1 as an output. pinMode(PC13, OUTPUT); } // the loop function runs over and over again forever void loop() { digitalWrite(PC13, HIGH); // turn the LED on (HIGH is the voltage level) delay(100); // wait for a second digitalWrite(PC13, LOW); // turn the LED off by making the voltage LOW delay(300); // wait for a second }

Rogerclark
Солнце 26 февраля 2017 г. 2:34
Спасибо, Виктор

Отбор блокировки / не блокировки через аргумент обратного вызова, который не нулевой, - это то, что скандинавские полуфинации делают в их SDK / API, поэтому, если он достаточно для них, я думаю, что это достаточно для нас.

Также

dmasendrepeat () кажется мне префектно -хорошим именем, как его описательное и краткое

Стивестронг
Солнце 26 февраля 2017 г. 7:04
Пока это хорошо.
Это должно быть не блокировать, если не нулевая функция CB передается в качестве параметра.
Я бы действительно склонен зарезервировать каналы DMA для SPI, если он настроен пользователем, чтобы удалить верхнюю часть вызова DMASEND/SET каждый раз, если изменяются только указатель буфера и его длина. Таким образом, можно быстро переключиться между двумя буферами, один заполняется, пока предыдущий отправляется.
Я думаю, что он вряд ли будет использовать тот же канал DMA для других целей, если кто-то использует DMA для SPI, что означает, что SPI постоянно работает, а затем с DMA, как приложения, связанные с дисплеем.

Олли
Солнце 26 февраля 2017 г. 16:07
Если/когда вы готовитесь к порту архитектуры F1XX в F4XX/F7XX/H7XX, управление ассигнованиями DMA должно быть решено. При наличии нескольких альтернативных потоков DMA, доступных для периферийных устройств и большего количества периферийных устройств, требующих DMA, видимость этой матрицы отображения важна. В долгосрочной перспективе он не будет работать, если периферические библиотеки предполагают, что для них доступны определенные потоки DMA.

Нам либо нужно иметь по запросу/выпуск потока DMA DMA, либо статическое распределение с обнаружением конфликтов.

Стивестронг
Солнце 26 февраля 2017 г. 16:25
Олли написал:Если/когда вы готовитесь к порту архитектуры F1XX в F4XX/F7XX/H7XX, управление ассигнованиями DMA должно быть решено. При наличии нескольких альтернативных потоков DMA, доступных для периферийных устройств и большего количества периферийных устройств, требующих DMA, видимость этой матрицы отображения важна. В долгосрочной перспективе он не будет работать, если периферические библиотеки предполагают, что для них доступны определенные потоки DMA.

Нам либо нужно иметь по запросу/выпуск потока DMA DMA, либо статическое распределение с обнаружением конфликтов.

victor_pv
Солнце 26 февраля 2017 г. 16:30
Как вы, ребята, предлагаете управлять распределением каналов DMA?
Насколько я знаю в настоящее время, ядро ​​не хранит никаких данных о том, какие каналы включены и для того, что периферийно, я думаю, потребуется дополнительная библиотека, которая сохраняет эти данные и управляет распределением и выпуском каналов.

О порте F4, я думаю, что первое усилие, которое мы, вероятно, должны попробовать, - это перейти на API «Трубки», который добавил Leaflabs для управления потоками F4 DMA. Я не использовал его в F1, но я видел код, использующий его, поэтому, вероятно, работает.

Теперь я придерживаюсь мнения об изменении вещей по одному, когда они уже работают, поэтому ничего не сломать.
Лично я закончу с тем, что начал. Я добавлю еще одну функцию, чтобы покрыть изменение адреса источника и длины одновременно, как предложил Стив, это поможет управлять двойным буферизацией.

Если кто -то может начать работать над кодом, который управляет бронированием каналов DMA, мы можем работать параллельно. Как только я закончу с дополнительными функциями, и они работают, я постараюсь понять, смогу ли я работать с трубками, чтобы это было для F4.

РЕДАКТИРОВАТЬ: Одним из способов может быть попытка создать какую -то таблицу, подобную PIN_MAP ONE, который отображает каналы DMA с периферийными устройствами, которые могут их использовать, и добавить ломти.

Rogerclark
Солнце 26 февраля 2017 г. 9:00 вечера
Потребуется ли много места для хранения бронирования ? эн.глин. Нужно ли просто хранить что -то для каждого канала DMA E.глин. зарезервировано или нужно хранить структуру на канал ?

Есть ли способ прочитать информацию с аппаратного обеспечения. Из того, что я помню, можно было эффективно анализировать регистры DMA, чтобы выяснить довольно много информации об их установке.

victor_pv
Пн 27 февраля 2017 г. 1:36
Rogerclark написал:Потребуется ли много места для хранения бронирования ? эн.глин. Нужно ли просто хранить что -то для каждого канала DMA E.глин. зарезервировано или нужно хранить структуру на канал ?

Есть ли способ прочитать информацию с аппаратного обеспечения. Из того, что я помню, можно было эффективно анализировать регистры DMA, чтобы выяснить довольно много информации об их установке.

Олли
Пн 27 февраля 2017 г., 4:41
Я согласен, что у нас будет много лун, прежде чем мы будем использовать Arduino IDE для серьезных или полуразмерных программ F4/F7/H7. В этой границе разработчики должны знать о возможностях и ограничениях различных периферических автобусов и каналов DMA в них.

Я предлагаю, чтобы мы использовали терминологию STM для этих концепций. В этом смысле нам нужно определить, что их только мало Каналы DMA и у каждого из них есть несколько потоки. Потоки в разных каналах могут быть активными одновременно, но для потоков в канале только один может быть активным в любой момент времени.

victor_pv
Пн 27 февраля 2017 г., 17:14
Олли написал:Я согласен, что у нас будет много лун, прежде чем мы будем использовать Arduino IDE для серьезных или полуразмерных программ F4/F7/H7. В этой границе разработчики должны знать о возможностях и ограничениях различных периферических автобусов и каналов DMA в них.

Я предлагаю, чтобы мы использовали терминологию STM для этих концепций. В этом смысле нам нужно определить, что их только мало Каналы DMA и у каждого из них есть несколько потоки. Потоки в разных каналах могут быть активными одновременно, но для потоков в канале только один может быть активным в любой момент времени.

Олли
Пн 27 февраля 2017 г., 17:50
Извините, теперь у меня есть нога во рту. F1 и другие MCU STM имеют одно и то же имя для контроллеров в периферийных автобусах. Итак, вот краткое изложение для F4/F7/H7
1) контроллеры DMA имеют несколько потоков
2) Потоки имеют несколько каналов
3) Каналы потока жестко подключены к периферийным устройствам
- Конфигурация потока выбирает одно из устройств

victor_pv
Пн 27 февраля 2017 г., 19:21
Олли написал:Извините, теперь у меня есть нога во рту. F1 и другие MCU STM имеют одно и то же имя для контроллеров в периферийных автобусах. Итак, вот краткое изложение для F4/F7/H7
1) контроллеры DMA имеют несколько потоков
2) Потоки имеют несколько каналов
3) Каналы потока жестко подключены к периферийным устройствам
- Конфигурация потока выбирает одно из устройств

Racemaniac
Вт 28 февраля 2017 г. 8:09 утра
victor_pv написал:Из того, что я нашел, они не интегрировали никаких функций DMA в нормальную библиотеку SPI.
Есть другая библиотека, DMASPI, которая обладает возможностями DMA:

https: // github.com/crteensy/dmaspi

Это работает, аналогично тому, над чем работал Стив, он передает очередь с серией свойств (буферный указатель, размер и PIN -объект для управления CS), затем обслуживает эти передачи в порядке.

Не уверен, что все, что стоит усилий, как тестировал Стив, для небольших переводов не улучшает производительность из -за всех накладных расходов, и библиотеки, использующие его.

victor_pv
Вт 28 февраля 2017 г. 13:37
Реданьяк написал:victor_pv написал:Из того, что я нашел, они не интегрировали никаких функций DMA в нормальную библиотеку SPI.
Есть другая библиотека, DMASPI, которая обладает возможностями DMA:

https: // github.com/crteensy/dmaspi

Это работает, аналогично тому, над чем работал Стив, он передает очередь с серией свойств (буферный указатель, размер и PIN -объект для управления CS), затем обслуживает эти передачи в порядке.

Не уверен, что все, что стоит усилий, как тестировал Стив, для небольших переводов не улучшает производительность из -за всех накладных расходов, и библиотеки, использующие его.

Racemaniac
Вт 28 февраля 2017 г. 13:48
victor_pv написал:Реданьяк написал:victor_pv написал:Из того, что я нашел, они не интегрировали никаких функций DMA в нормальную библиотеку SPI.
Есть другая библиотека, DMASPI, которая обладает возможностями DMA:

https: // github.com/crteensy/dmaspi

Это работает, аналогично тому, над чем работал Стив, он передает очередь с серией свойств (буферный указатель, размер и PIN -объект для управления CS), затем обслуживает эти передачи в порядке.

Не уверен, что все, что стоит усилий, как тестировал Стив, для небольших переводов не улучшает производительность из -за всех накладных расходов, и библиотеки, использующие его.

victor_pv
Пн, 06 марта 2017 г., 19:50
Кажется, что у меня сейчас рабочая версия, которая позволяет:
-Установить функции обратного вызова, которые будут вызваны при завершении передачи DMA. В случае, если обратные вызовы устанавливаются dmamesend, а dmatransfer не блокируют.
-Разрешить устанавливать все настройки, связанные с DMA, одной функцией (включение контроллера DMA, установить адрес передачи, назначение, размер данных и т. Д.), А затем вторую функцию для перезагрузки размер передачи DMA, который необходимо перезагрузить, прежде чем снова включить канал , поскольку значение не сохраняется в конце передачи. Таким образом, если адрес буфера, сторона данных, используется повторно, необходимо вызывать только вторую функцию.

Я протестировал обратный вызов с библиотекой SDFAT и с дисплеем ILI SPI. Теперь странная вещь:
При использовании SDFAT на скорости SPI DIV/2 и использования обратных вызовов, что -то DMA RX никогда не завершается, и оставляет 1 или 2 байта в ожидании.
Итак, я хочу получить 512bytes. Для этого DMA RX установлен на 512 байтов, DR считывается, если установлен RXN.
После того, как каждый байт выйдет, можно выйти, и контроллер DMA считывает его от DR, хранит его в буфере RX и уменьшает количество запросов RX DMA в ожидании.

Все работает нормально, если я не использую обратные вызовы, и просто блокируйте, пока RX не будет завершен. Это также работает нормально, если я установил порт на 18 МБ (Div/4) при использовании обратных вызовов.
Но если я использую обратные вызовы и устанавливаю порт на скорость Div/2, то иногда RX никогда не завершается. Буфер TX все отправлено, а 1 или 2 байта все еще ожидают в RX. Поскольку TX завершен, он больше не производит часы, и RX никогда не получит последние байты в.

Я запустил его через отладчик, и иногда он правильно заполняет несколько передач, прежде чем сбой, но каждый раз представляет собой различное количество передачи. Иногда идет дольше, некоторые для более коротких.
Я попытался установить приоритет RX DMA для очень высокого и TX до среднего, в случае, если контроллер DMA обслуживает TX, в то время как RX находился на рассмотрении, что перезаписывало бы реестр DR и потеряет байт RX, но это не помогло.

Помимо установки обратного вызова для полного события Transfer, настройка DMA точно такая же, будь то блокировка или нет, поэтому я не могу понять, что происходит, кроме, возможно, даже при блокировании переводов не всегда завершается, но, поскольку есть Проверка тайм -аута, иногда перевод только прекращается на тайм -аут, а не потому, что RX фактически завершен.

Мне нужно проверить эту теорию, удалив тайм -аут, но у кого -нибудь возникает какая -либо проблема при получении данных с библиотекой SDFAT и скоростью порта MAX SPI при использовании DMA или заметил какую -либо коррупцию в чтении данных?

Стивестронг
Пн, 06 марта 2017 г., 8:30 вечера
Я думаю, что это нормально, что байты RX еще должны быть получены, когда TX готовы, так как TXE приходит раньше, чем RXNE. Это означает, что TXE установлен до получения последнего байта.
Вы ждете в функции обратного вызова TX End, чтобы не TXE и BSY?

victor_pv
Пн, 06 марта 2017 г. 22:11
Стивестронг написал:Я думаю, что это нормально, что байты RX еще должны быть получены, когда TX готовы, так как TXE приходит раньше, чем RXNE. Это означает, что TXE установлен до получения последнего байта.
Вы ждете в функции обратного вызова TX End, чтобы не TXE и BSY?

Стивестронг
Вт
Итак, вы запускаете оба порта SPI в режиме DMA...
Вы можете попытаться позволить только части RX в режиме DMA, часть TX в «нормальном» режиме, чтобы увидеть, все еще потеряны RX байты.

victor_pv
Вт. Март 07, 2017 1:52
Стивестронг написал:Итак, вы запускаете оба порта SPI в режиме DMA...
Вы можете попытаться позволить только части RX в режиме DMA, часть TX в «нормальном» режиме, чтобы увидеть, все еще потеряны RX байты.

Стивестронг
Вт
Я думаю, что обратный вызов не должен иметь никакого влияния на результат теста, если вы ждете флага TXE и BSY в конце TX ISR.
При проверке рисунков 246 и 247 перекрывают разрыв на один бит (2 часа APB1) между RXNE и TXE, должен дать приоритет каналу RX, если установлен на самый высокий приоритет (11), пожалуйста, проверьте, что вы правильно установили приоритеты. DMA для TX может быть установлен на самый низкий приоритет (00).

Кроме того, вместо тайм -аута вы можете проверить значение регистра DMA_CNDTRX, чтобы определить, есть ли еще байты, которые будут получены, когда закончится TX.

Сбой ли при использовании только SPI_1 как TX, так и RX DMA с 36 МГц часами (SPI2 не работает)?

Если нет, то это ясно, что расовая кондиционер/ограничение аппаратного обеспечения (матрица шины, системную шину AHB и два моста до периферических шин APB1 и APB2, как указано на рисунке 2), которые не могут обрабатывать так много данных (DMA и CPU<->Запросы на передачу оперативной памяти в течение короткого периода переноса одного байта при 36 МГц, так как SPI_1 обслуживается на APB2 и SPI_2 на APB1.

В качестве альтернативы вы можете проверить, что происходит при установлении состояния ожидания вспышки до 1 (процессор при 72 МГц) или до 3.

Кроме того, вы можете отслеживать флаги ошибок MODF и OVR SPI (включите эти IRQS?и/или teif of dma.

РЕДАКТИРОВАТЬ
Не могли бы вы указать более подробную информацию о том, как именно вы тестируете? Вы читаете блоки 512 байтов на SPI 1 от SD -карты и читайте блоки (сколько байтов?) с дисплея ILI неоднократно? Вы используете более старую SDFAT LIB или более новый, SDFAT Beta? Я мог бы проверить параллельно, если вы поделитесь кодом тестирования.

victor_pv
Вт, март 07, 2017, 16:58
Стивестронг написал:Я думаю, что обратный вызов не должен иметь никакого влияния на результат теста, если вы ждете флага TXE и BSY в конце TX ISR.
При проверке рисунков 246 и 247 перекрывают разрыв на один бит (2 часа APB1) между RXNE и TXE, должен дать приоритет каналу RX, если установлен на самый высокий приоритет (11), пожалуйста, проверьте, что вы правильно установили приоритеты. DMA для TX может быть установлен на самый низкий приоритет (00).

Кроме того, вместо тайм -аута вы можете проверить значение регистра DMA_CNDTRX, чтобы определить, есть ли еще байты, которые будут получены, когда закончится TX.

Сбой ли при использовании только SPI_1 как TX, так и RX DMA с 36 МГц часами (SPI2 не работает)?

Если нет, то это ясно, что расовая кондиционер/ограничение аппаратного обеспечения (матрица шины, системную шину AHB и два моста до периферических шин APB1 и APB2, как указано на рисунке 2), которые не могут обрабатывать так много данных (DMA и CPU<->Запросы на передачу оперативной памяти в течение короткого периода переноса одного байта при 36 МГц, так как SPI_1 обслуживается на APB2 и SPI_2 на APB1.

В качестве альтернативы вы можете проверить, что происходит при установлении состояния ожидания вспышки до 1 (процессор при 72 МГц) или до 3.

Кроме того, вы можете отслеживать флаги ошибок MODF и OVR SPI (включите эти IRQS?и/или teif of dma.

РЕДАКТИРОВАТЬ
Не могли бы вы указать более подробную информацию о том, как именно вы тестируете? Вы читаете блоки 512 байтов на SPI 1 от SD -карты и читайте блоки (сколько байтов?) с дисплея ILI неоднократно? Вы используете более старую SDFAT LIB или более новый, SDFAT Beta? Я мог бы проверить параллельно, если вы поделитесь кодом тестирования.

Стивестронг
Вт
Я не думаю, что регистр SPI_DR для TX и RX будет смешивать, оборудование должно обрабатывать правильный способ потока данных данных TX и RX в SPI_DR. Я думаю, что это скорее вопрос ограничения на внутренние шины данных.

Тем не менее, вы не пытались запустить TX и RX DMA на SPI 1 с 36 МГц и Пусть SPI 2 отключен/неактивен. Это даст нам больше информации.

victor_pv
Вт
Стивестронг написал:Я не думаю, что регистр SPI_DR для TX и RX будет смешивать, оборудование должно обрабатывать правильный способ потока данных данных TX и RX в SPI_DR. Я думаю, что это скорее вопрос ограничения на внутренние шины данных.

Тем не менее, вы не пытались запустить TX и RX DMA на SPI 1 с 36 МГц и Пусть SPI 2 отключен/неактивен. Это даст нам больше информации.

Стивестронг
Ср. 08, 2017 10:10
Виктор, как вы адаптировали LIB SDFAT, чтобы справиться с функциональностью обратного вызова?
Потому что, насколько я знаю, SDFAT использует в настоящее время передачи SPI в виде блокировки.

victor_pv
Ср. 08 марта 2017 г. 15:18
Стивестронг написал:Виктор, как вы адаптировали LIB SDFAT, чтобы справиться с функциональностью обратного вызова?
Потому что, насколько я знаю, SDFAT использует в настоящее время передачи SPI в виде блокировки.

victor_pv
Солнце 12 марта 2017 г. 18:03
Я сделал несколько тестов сегодня с другой платой, с чипом F103RCT6.
Я соединил MISO с MOSI в SPI1 и неоднократно отправлялся и получал с DMA в 2 буфера. Затем сравните контент.
Все шло хорошо, когда я использовал SPI1, с обратным вызовом или без него.
Затем я также начал использовать SPI2 (SPI2 без DMA), и проблемы начинаются. Некоторые биты не получены правильно, и изменяет 0 на 1 в последнем бите некоторых переведенных байтов.

Sketch Run переносит в петле и сравнивает результат в конце. Если есть ошибка, она останавливается и ждать ввода пользователя, затем может повторить. Если нет ошибки, он повторяет петлю без остановки. Когда случаются ошибки, они случаются каждые несколько проходов, но не каждый. Ошибки также случаются на разных байтах, не всегда одинаковые.

РЕДАКТИРОВАТЬ: Я повторил тот же тест с использованием SPI2 с DMA, а также установил SPI1 на Div4 Speed. Это результаты:

Div2 скорость на SPI1:
SPI1 в одиночку без обратного вызова: ОК
SPI1 наедине с обратным вызовом: ОК
SPI1 с обратным вызовом, в параллельном SPI2 без DMA: ошибки
SPI1 с обратным вызовом, в параллельном SPI2 с DMA: ошибки

Div4 скорость на SPI1:
SPI1 с обратным вызовом, в параллельном SPI2 без DMA: OK
SPI1 с обратным вызовом, в параллельном SPI2 с DMA: OK

Похоже, что ошибки случаются только тогда, когда SPI1 и SPI2 работают одновременно, а SPI1 работает на уровне 36 МГц (над спецификациями).
Я постараюсь опубликовать весь свой код на GitHub. Я остановлюсь с этими тестами здесь, так как у него начались проблемы, когда я начал писать обратный вызов, и не знал, была ли проблема в этом. Я убежден, что теперь у кода обратного вызовов нет проблем, но единственная проблема была из -за использования оба порта SPI полностью параллельно, что было разрешено только с помощью обратных вызовов для сигнала конца передачи.

Заключение для меня: SPI1 не является надежным при работе при 36 МГц, особенно при использовании другого порта SPI одновременно. Вероятно, в порядке только для отправки данных, или когда используется в отдельности, или не критический прием.

Рик Кимбалл
Солнце 12 марта 2017 г., 19:46
Может быть, вы могли бы попробовать приспособиться относительный приоритет прерываний?

victor_pv
Солнце 12 марта 2017 г. 22:42
Рик Кимбалл написал:Может быть, вы могли бы попробовать приспособиться относительный приоритет прерываний?

victor_pv
Пт 23 июня 2017 г., 19:21
Воскресение этого потока, чтобы добавить код.

Я тщательно протестировал функции, и единственная проблема, которую я когда -либо обнаружил, была при использовании SPI1 на 36 Мбит с DMA, как опубликовано выше. Я проверил проблему, независимо от того, используя обратный вызов или нет.
Теперь версия, которую я публикую, не та, которую я проверил. Мне пришлось переделать его, чтобы добавить последние изменения от Роджера, и мне нужно было повторно его, но я публикую его, чтобы все больше людей могли его проверить.
Эта версия не использует DMATUBES, хотя у меня есть другая версия, которую я написал для поддержки F4, но Стив работает больше всего в F4, а его ядро ​​не использует трубки DMA, поэтому я не вижу точка, используя это.
Я постараюсь проверить это, как только смогу, и отправлюсь обратно, если кто -то найдет какую -либо проблему, дайте мне знать.
SPI.молния
(10.42 киб) скачано 14 раз

Стивестронг
Пт 23 июня 2017 г. 8:34 вечера
Привет, Виктор,
Сначала попытайтесь построить: int ledPin = BOARD_LED_PIN; // LED connected to digital pin D13 // pin D1 for piezo output // the setup() method runs once when the sketch starts void setup() { pinMode(ledPin, OUTPUT); //turn on the led, just so that i know it is 'alive' digitalWrite(ledPin, HIGH); pinMode(D1, OUTPUT); } //the loop() method runs over and over again, //as long as maple has power void loop() { int i, hz, t; for(hz = 0; hz < 4500; hz+= 100) { t = 1000000 / hz; //beep for 1/3 sec for(i=0;i

Стивестронг
Пт 23 июня 2017 г., 8:50 вечера
Внесли некоторые необходимые изменения, чтобы иметь возможность построить его.
Я не проверял новые функции, только старые (оригинальные) DMA, они, кажется, работают.

victor_pv
SAT 24 июня 2017 г. 9:02 вечера
[Стивестронг - Пт 23 июня 2017 г. 8:50 вечера] - Внесли некоторые необходимые изменения, чтобы иметь возможность построить его.
Я не проверял новые функции, только старые (оригинальные) DMA, они, кажется, работают.
Спасибо, Стив, я только что закончил собирать его и нашел аналогичные ошибки и тоже исправил их.
Я загружаю новый. Это почти те же изменения, которые вы должны были сделать, за исключением перевода и отправки, я изменил его на void *, а не на Uint8 *, который я использовал раньше (мой оригинальный код был основан на более старой версии ядра).

Я также не использовал typedef для указателей функций, но я вижу, что вы сделали. Я предполагаю, что вы добавили, чтобы прояснить код прочитанным, но вы считаете необходимым и на самом деле не затрудняет чтение кода, чтобы проверить, что такое этот тип? или вы использовали его по какой -то другой причине?

Вот новая версия, которая собирает правильную. Как я сказал довольно близко к Стиву, за исключением этих различий. Мне все еще нужно проверить, запустив мой предыдущий тестовый эскиз с ним, который использует обратные вызовы. У меня нет кода для проверки новой асинхронной функции, я надеюсь, что я не сломал ее.
SPI.молния
(10.44 киб) скачано 19 раз

victor_pv
Вт 27 июня 2017 г. 3:35 утра
Я только что проверил с помощью своего тестового эскиза и могу успешно использовать обратные вызовы как с SPI1, так и SPI2 с кодом в посте выше, который основан на последних последних.

Для моего теста я использовал свой старый тестовый код WAV Player, он использует Freertos 900. DMA запускает 3 периферийных устройства, SPI1, SPI2 и таймер для получения выходного сигнала.
Я изменил SDFAT, поэтому он установил функцию обратного вызова, и после DMASEND или DMATRANSFER он устанавливает задачу для блокировки до выпуска ISR, к изменению RTOS в следующую задачу и занимает процессор до тех пор, пока не закончится передача SPI DMA. ISR приводит к новому контексту переключения на выход, а RTOS возвращается к задаче, которая читала из SDCARD.
Я тоже проверил его с дисплеем, но просто представляет джиттер, так как задача отображения записывает только несколько байтов за раз, и все контекст -переключение просто тратит впустую любое время ЦП, которое можно использовать для чего -либо еще. Таким образом, на дисплее он работает, но не обеспечивает никакой прироста производительности.

Это мои изменения в SDSPISTM32F1.Файл CPP в библиотеке SDFAT на случай, если кто -то заинтересован в тестировании:
Сначала включайте RTO (9.0 в моем случае должен работать с 8.2.1 тоже): Serial.end();

Даниэфф
Вт 27 июня 2017 г., 4:42
Вместо всего этого, разве этого не будет достаточно, чтобы добавить `hirlw ()` к циклу, который ждет, пока DMA закончится? Это сделает для вас переключатель контекста во время ожидания.

victor_pv
Ср 28 июня 2017 г., 3:11
[Даниэфф - Вт 27 июня 2017 г. 4:42] - Вместо всего этого, разве этого не будет достаточно, чтобы добавить `hirlw ()` к циклу, который ждет, пока DMA закончится? Это сделает для вас переключатель контекста во время ожидания.

Даниэль, я не уверен, что понимаю твое предложение, так что поправьте меня, если я ошибаюсь, но вы предлагаете использовать Freertos Taskyield (), это правильно?
Это не сработает по двум причинам.
1.- Он выполняет доход только в том случае, если задача с более высоким приоритетом ожидает выполнения. Если задача, выполняющая доступ к SDFAT в данный момент, является самой высокой, готовой к выполнению, она не будет уступать и продолжать работать, поэтому вы фактически не выполняете другую задачу для выполнения, пока DMA продолжается.
2.- Если мы просто уступим, это вернется к этой задаче в тот момент, который не синхронизируется с передачей DMA, нам все равно нужно знать, будет ли DMA завершен, прежде чем продолжить с кодом SDFAT. Если вы не используете какой -то семафор и не проверьте его, или вы должны опросить контроллер DMA, чтобы проверить, сделано ли это. Первый случай - это именно то, что реализовано, только с уведомлениями о задачах, которые, согласно документам Freertos, стоят меньше циклов и оперативной памяти, чем семафор. Если мы сделали второй случай, опросите контроллер DMA, то мы тратим циклы просто опросы. У нас уже есть это в библиотеке, когда мы работаем в режиме блокировки.

Используя уведомление о задаче, мы достигаем 2 вещей. Сначала задача будет выполнять следующую, чтобы запустить, даже если доступные являются более низким приоритетом. И во -вторых, как только функция обратного вызовов вызвана потому, что передача DMA закончится, она запрашивает урожайность RTOS. Если выполнение задачи имеет тот же или более низкий приоритет, она перейдет в SDFAT, который был заблокирован. Если выполнение задачи в настоящее время будет более высоким приоритетом, то она будет отмечать это как готовое к запуску и будет работать в следующий раз, когда сможет в соответствии с приоритетами и т. Д.

Если вы имели в виду с доходностью () - это что -то еще, пожалуйста, дайте мне знать. Я знаю, что в библиотеке SDFAT есть некоторые функции урожайности (), но я понял, что это должно было поместить процессор в режим сна до следующего прерывания, и в этом случае он не выполнит другую задачу.

Наконец, это просто пример использования, потому что у меня был этот эскиз Freertos, но не нужно использовать какие -либо RTO, поскольку обратный вызов объявляется кодом пользователя, который он может быть использован для установки переменной, изменить уровень PIN -кода и т. Д.

Rogerclark
Пн, 3 июля 2017 г. 5:53 утра
Виктор

SPI Zip, кажется, работает для меня нормально, но я не использую обратные вызовы.

Я использовал код с тестовым стендом камеры OV7670, и это было хорошо.

Но это не включает в себя dmasendasync

Я могу вручную объединить эту новую функцию в вашем коде, а затем проверить свою локальную копию обратно в GitHub, но она не будет такой чистой, как вы втягиваете новейшую репо в jathub Repo, а затем отправляете пиар на основе изменений.

Так что, если вы хотите это сделать, я объединяю пиар как можно скорее.глин. завтра

Спасибо

Роджер

Пса. Как вы можете видеть из моего PM, я объединил вас другие PR

victor_pv
Пн 10 июля 2017 г. 15:33
[Rogerclark - Пн, 3 июля 2017 г. 5:53 утра] - Виктор

SPI Zip, кажется, работает для меня нормально, но я не использую обратные вызовы.

Я использовал код с тестовым стендом камеры OV7670, и это было хорошо.

Но это не включает в себя dmasendasync

Я могу вручную объединить эту новую функцию в вашем коде, а затем проверить свою локальную копию обратно в GitHub, но она не будет такой чистой, как вы втягиваете новейшую репо в jathub Repo, а затем отправляете пиар на основе изменений.

Так что, если вы хотите это сделать, я объединяю пиар как можно скорее.глин. завтра

Спасибо

Роджер

Пса. Как вы можете видеть из моего PM, я объединил вас другие PR
Моя версия была переделана, принимая вашу последнюю.
Я отправлю пиар с этими 2 файлами.

Rogerclark
Пн 10 июля 2017 г. 22:00
Спасибо

Стивестронг
Пн 31 июля 2017 г. 11:37
Я только что увидел в недавно добавленном коде SPI, кажется, что есть 3 вызовы DMA_SET_TRANSFER (), хотя обычно должно быть только один, с адаптированными флагами в качестве входных данных, в зависимости от бита MINC:
https: // github.com/rogerclarkmelbourne/ ... я.CPP#L399

Я бы изменил это так: #include void setup() { Serial.end(); USBComposite.setProductId(0x27db); USBComposite.setVendorId(0x16c0); USBHID_begin_with_serial(HID_KEYBOARD); Keyboard.begin(); // useful to detect host capslock state and LEDs delay(1000); } void loop() { Keyboard.println("Hello world"); delay(10000); }

victor_pv
Пн 31 июля 2017 г. 12:31
[Стивестронг - Пн 31 июля 2017 г. 11:37] - https: // github.com/rogerclarkmelbourne/ ... я.CPP#L399

Я бы изменил это так: Start...done. Tstart =0 Tfinish=1740 Duration=1740

Стивестронг
Пн 31 июля 2017 г. 12:36
[victor_pv - Пн 31 июля 2017 г. 12:31]] - Не могли бы вы указать на линии, на которые вы ссылаетесь?
Эти две строки Перейти на строку 420.
Имеет смысл очистить их до запуска какого -либо дальнейшего запроса.
И было бы неплохо, чтобы они читали их после перевода Чтобы проверить верхний уровень программного обеспечения, были ли установлены какие -либо флаги ошибок или нет.

victor_pv
Пн 31 июля 2017 г. 12:49
[Стивестронг - Пн 31 июля 2017 г. 12:36] -
[victor_pv - Пн 31 июля 2017 г. 12:31]] - Не могли бы вы указать на линии, на которые вы ссылаетесь?
Эти две строки Перейти на строку 420.
Имеет смысл очистить их до запуска какого -либо дальнейшего запроса.
И было бы неплохо, чтобы они читали их после перевода Чтобы проверить верхний уровень программного обеспечения, были ли установлены какие -либо флаги ошибок или нет.
Проблема была бы в такой ситуации, как это:
Вы управляете Dmatransfer. (Биты ISR не очищены)
Вы делаете что -то с этим каналом DMA и включаете запросы IRQ. Поскольку запрос на прерывание все еще установлен, я думаю, что прерывание сразу же запустит.

Я считаю, что именно так они работают из того, что я помню из справочного руководства.

Стивестронг
Пн 31 июля 2017 г. 12:55
Виктор, это выдержка из справочного руководства F4 в отношении битов статуса DMA. Страница 326, Глава 10.4: #include #include USBHID HID; HIDKeyboard Keyboard(HID); HIDJoystick Joystick(HID); HIDMouse Mouse(HID); void setup() { USBHID.begin(HID_KEYBOARD_MOUSE_JOYSTICK); while (!usb_is_connected(USBLIB) || !usb_is_configured(USBLIB)) delay(100); Keyboard.println("Hello world!"); } void loop() { Joystick.X(0); Joystick.Y(0); digitalWrite(PB12, 0); delay(500); Joystick.X(1023); Joystick.Y(1023); delay(500); digitalWrite(PB12, 1); }

victor_pv
Пн 31 июля 2017 г. 15:52
Хорошо, давайте переместим его, прежде чем включить DMA и повторно.
Не уверен, почему я бы переместил их туда, не могу вспомнить конкретную причину, чтобы мы могли проверить и подтвердить, что все это хорошо, если я столкнулся с проблемой, которая заставила меня переместить их.

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

РЕДАКТИРОВАТЬ:
Просто примечание, при использовании ISRS с DMA, основной обработчик DMA IRQ очищает их, сразу после вызова пользователя DMA Handler:
https: // github.com/rogerclarkmelbourne/ ... ван.H#L45
Поэтому при использовании обратных вызовов они будут очищены в конце передачи, но если обработчик кода пользователя хочет их проверить, это можно сделать, так как они еще не очищены, но по возвращению.

Rogerclark
Пн 31 июля 2017 г. 22:30
Ребята

Пока вы смотрите на материал SPI DMA, я вижу, что эскиз камеры OV7670, который будет использовать ILI9341 в качестве высокоскоростной оперативной памяти для хранения изображения..

Выиграет от функции, которая прочитает DMA, но ему не все равно, что передается.

На данный момент лучшим способом сделать это было бы использовать Dmatransfer и, возможно, указать буфер TX на какую -то арбитатную флэш -ную (как в этом случае я не знаю, имеет ли это значение то, что отправлено, хотя мне нужно было Двойная проверка....)

Но в идеале что -то вроде DMASEND, которое получает только и, возможно, посылает определенное значение (передано на функцию)

Я не уверен, насколько сложно было бы написать что -то подобное, но я предполагаю, что это будет модифицированная копия dmasend

victor_pv
Вторник 01 августа 2017 г. 2:40
Я вижу 3 возможных способа сделать это:
1.-Мы добавляем функцию Dmaread, которая просто посылает FF неоднократно и читает в буфер.
2.-Мы модифицируем DMATRANSFER для обнаружения нулевого значения в отправке Баффера, и если это так, он неоднократно отправляет FF, пока он читает в буфер приема.
3.-Мы добавляем переменную MINC, как мы делали для DMASEND. В случае, если MINC равен 0, он не увеличивает буфер для канала TX и поэтому посылает первый байт повторно.

Преимущество на варианте 3 заключается в том, что он позволяет отправлять произвольное значение. Вариант 2 просто добавляет чек в dmatransfer, поэтому должен держать код немного короче, если в одном эскизе используются как нормальная передача, так и передача с нулевым буфером, но должны иметь небольшое влияние на производительность от чека. Не должно быть много для dmatransfer, хотя.

И Option1 имеет преимущество более близкого напоминания текущего SPI.читать(&Функция BUF, N), принимая те же параметры и работая одинаково, за исключением использования DMA, но не так гибко, как вариант 3.

Мы также могли бы выполнить полную новую функцию, которая работает иначе, чем текущие DMA One, и Read (), и вместо этого потребуется как значение для неоднократно, так и буфер приема для чтения данных. Что -то вроде: const uint32 leftSwitch = PA1; const uint32 rightSwitch = PA2; const uint32 upSwitch = PA3; const uint32 downSwitch = PA4; const bool switchActive = 1; // 1 if microswitch is connected to VCC and pulled down ... void setup() { ... Joystick.setManualReportMode(true); } void loop() { if (digitalRead(leftSwitch) == switchActive) Joystick.X(0); else if (digitalRead(rightSwitch) == switchActive) Joystick.X(1023); else Joystick.X(512); if (digitalRead(upSwitch) == switchActive) Joystick.Y(0); else if (digitalRead(downSwitch) == switchActive) Joystick.Y(1023); else Joystick.Y(512); Joystick.send(); }

Rogerclark
Вторник 01 августа 2017 г. 5:19 утра
Спасибо, Виктор

Я думаю, что нам понадобился бы способ многократно отправлять любые данные, так как я не уверен, что такие устройства, как ILI9341.
Я подозреваю, что ILI9341 не должен заботиться о том, что их отправляют, когда данные читаются, но мне нужно подтвердить это, и его безопаснее иметь возможность указать байт, который отправляется при чтении.

Таким образом, вариант, который использует MINC, выглядит так, как будто это может быть лучшим решением

Стивестронг
Вторник 01 августа 2017 г. 7:31
Я бы выбрал комбинацию 2) и 3), имея оба преимущества, с действительно минимальными накладными расходами, увеличивая размер кода лишь минимально.

victor_pv
Вторник 01 августа 2017 г. 15:54
Проверка кода, выглядит так, как будто мы забыли функцию dmatransfer, уже может отправлять FF неоднократно, если передача == null.
Текущий dmatransfer:
#include "USBComposite.h" // https://github.com/arpruss/USBHID_stm32f1 #define LED_BUILTIN PA1 // change to match your board ; PB12 for some black pills ; PC13 for blue/red pill const uint32 leftSwitch = PA7; const uint32 rightSwitch = PA6; const uint32 upSwitch = PA5; const uint32 downSwitch = PA4; const uint32 fireSwitch = PA3; const bool switchActive = 1; // 1 if microswitch is connected to VCC and pulled down USBHID HID; HIDJoystick Joystick(HID); void setup() { pinMode(LED_BUILTIN, OUTPUT); pinMode(PA7, INPUT_PULLDOWN); pinMode(PA6, INPUT_PULLDOWN); pinMode(PA5, INPUT_PULLDOWN); pinMode(PA4, INPUT_PULLDOWN); pinMode(PA3, INPUT_PULLDOWN); USBComposite.setProductId(0xE004); USBComposite.setProductString("MapleGameportToUSB"); HID.begin(HID_JOYSTICK); digitalWrite(LED_BUILTIN, 1); adc_set_sample_rate(ADC1, ADC_SMPR_13_5); // ADC_SMPR_13_5, ADC_SMPR_1_5 Joystick.setManualReportMode(true); } void loop() { if (digitalRead(leftSwitch) == switchActive) Joystick.X(0); else if (digitalRead(rightSwitch) == switchActive) Joystick.X(1023); else Joystick.X(512); if (digitalRead(upSwitch) == switchActive) Joystick.Y(0); else if (digitalRead(downSwitch) == switchActive) Joystick.Y(1023); else Joystick.Y(512); if (digitalRead(fireSwitch) == switchActive) Joystick.button(1,true); else Joystick.button(1,false); Joystick.send(); }

victor_pv
Вторник 01 августа 2017 г. 15:58
[Rogerclark - Пн 31 июля 2017 г. 22:30] - Выиграет от функции, которая прочитает DMA, но ему не все равно, что передается.
Роджер см. Мой пост выше. Функция DMATRANSFER уже может сделать это, если параметр передачи передачи. В этом случае он отправляет FF при получении в буфер RX.
Мы добавим функцию MINC, чтобы отправленное значение можно выбрать пользователем с переменной.

Rogerclark
Вторник 01 августа 2017 г., 21:26
Спасибо, Виктор

Мне нужно будет проверить это, когда у меня будет время, на дисплее ILI9341