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

Мне нужно переслать по SPI пакет данных 4K при помощи DMA.

Если произошла смена таска DMA умеет продолжить после того как вернулся таск? Или ему не важна смена таска?

 

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


Ссылка на сообщение
Поделиться на другие сайты
Мне нужно переслать по SPI пакет данных 4K при помощи DMA.

Если произошла смена таска DMA умеет продолжить после того как вернулся таск? Или ему не важна смена таска?

Он о Ваших тасках не знает ровно ничего. Вы ему команду долбить дали - он и долбит. Что в этот момент делает процессор - ему до лампочки :laughing:

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


Ссылка на сообщение
Поделиться на другие сайты
Он о Ваших тасках не знает ровно ничего. Вы ему команду долбить дали - он и долбит. Что в этот момент делает процессор - ему до лампочки :laughing:

 

спасибо. заодно спрошу такой вопрос - кто управляет пином слейв селект? в примерах я не нашел привязки DMA к этому пину. я также не нашел где в коде происходит управление этим пином.

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


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

*Попытка соединиться с межгалактическим сервером телепатов...*

*Не успешно. Соединение разорвано.*

Процессор/МК какой хоть? Если STM32 то ручками либо аппаратным таймером. Смотрите референс на свой МК.

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


Ссылка на сообщение
Поделиться на другие сайты
Если произошла смена таска DMA умеет продолжить после того как вернулся таск? Или ему не важна смена таска?

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

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


Ссылка на сообщение
Поделиться на другие сайты
Если произошла смена таска DMA умеет продолжить после того как вернулся таск? Или ему не важна смена таска?

DMA не зависит от операционной системы, которая по-сути таже программа. И если при смене таска шедулер не пишет в DMA (а я ещё не слышал о таком), то всё будет работать нормально. Правда, учитывая, что у вас многозадачная система, вам следует построить драйвер DMA таким образом, чтобы исключить к нему множественный неконтролируемый доступ. Другими словами обложить мьютексами, либо создать очереди заданий, либо драйвер DMA должен выдавать первый свободный от транзакции канал. Вариантов реализации может быть множество. Я это дело до рабочего состояния пили около 2х недель. У меня две шины SPI из разных задач через DMA общаются с кучей слейвов. CS дёргается программно.

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


Ссылка на сообщение
Поделиться на другие сайты
Arlleex и haker_fox раскажите подробней как вы синхронизируете ChipSelect с DMA. Пару лет назад нужно было это сделать на STM32. Я не придумал как это сделать и оставил SPI на прерываниях.

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


Ссылка на сообщение
Поделиться на другие сайты
Arlleex и haker_fox раскажите подробней как вы синхронизируете ChipSelect с DMA. Пару лет назад нужно было это сделать на STM32. Я не придумал как это сделать и оставил SPI на прерываниях.

Вот в этой теме воевал с STM32.

Идея следующая. Смотрим картинку.

Используем один аппаратный таймер. Один канал сравнения настраиваем на переключение ножки по событию сравнения (для этого CS должен быть заведен на аппаратный вывод OC микроконтроллера), а также на формирование запроса DMA по этому сравнению, а второй канал сравнения просто будет формировать сигналы для DMA.

Допустим, теперь, хотим начать принимать много данных от АЦП (у меня задача была именно такая). У него только MISO, CLK, CS. То есть придется отправлять пустые данные и принимать уже нужные отсчеты.

Для этого настраиваю период пересчета таймера, например, на 45мкс, время срабатывания первого канала сравнения 5мкс, второго - 10мкс (на рисунке момент времени 1).

Через 5мкс таймер аппаратно опустит CS в 0, активизируя подчиненное устройство (момент времени 2). В этот же момент DMA, получив сигнал сравнения от таймера, осуществляет пересылку числа 40 в регистр сравнения первого канала. В момент времени 3 таймер досчитал до значения сравнения канала 2, и по этому событию DMA отправляет очередной пустой байт/слово в SPI. В момент времени 4 срабатывает DMA на прием по SPI, который складывает принятые данные в кольцевой буфер. Как только буфер заполнится - мне выдается прерывание, а DMA продолжает молотить. В момент времени 5 таймер досчитал до 40, и здесь снова аппаратно переключается ножка CS, а DMA отправляет в регистр сравнения первого канала снова число 5. И так до бесконечности.

Получается, что автомат построен по чисто аппаратному таймеру и DMA, а с программной точки зрения это выглядит прозрачно, как будто кто-то толкает SPI и принимает от него данные :rolleyes:

Сделано, конечно, все равно через одно место, если так подумать... Но за неимением другого варианта, приходится изобретать разные механизмы. В других МК с этим было бы куда проще.

Естественно, в моей схеме таймер и модуль SPI должны быть одновременно доступны в одном модуле DMA (я имею ввиду то, что DMA должен быть физически подключен и к таймеру и к SPI, что накладывает небольшие ограничения на вариации Timer<->SPI).

 

sdf.gif

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


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

Можно чуть иначе. Начало передачи определяется командой или таймером. В этот момент ставится CS и запускается таймер на фиксированное время - слейву на подготовку данных к передаче и запуска своего DMA на прием/передачу. По истечении таймера (прерывание) мастер запускает свой DMA на прием/передачу и разрешает прерывание по завершению приема по DMA. По этому прерыванию он снимает CS - цикл передачи завершен.

 

Слейв по переднему фронту CS (прерывание по ноге) готовит данные, запускает свой DMA на прием/передачу и разрешает прерывание завершения приема DMA. По этому прерыванию обрабатывает полученные данные.

 

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

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


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

я не понимаю. а почему нельзя опустить CS - запустить DMA - а в прерывании по окончанию транзакции DMA поднять CS.

 

 

*Попытка соединиться с межгалактическим сервером телепатов...*

*Не успешно. Соединение разорвано.*

Процессор/МК какой хоть? Если STM32 то ручками либо аппаратным таймером. Смотрите референс на свой МК.

я работаю с Кинетис.

K20_SPI_MSTR_DMA.zip

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


Ссылка на сообщение
Поделиться на другие сайты
Arlleex и haker_fox раскажите подробней как вы синхронизируете ChipSelect с DMA.

Я работаю с микросхемой АЦП ADS131E04. Поскольку частота сбора данных довольно большая (8 кГц ), то на шине висит только одно АЦП, больше шина ничем не занята. CS дёргается программно, в начале посылки, и с небольшой задержкой (она необходима) после посылки устанавливается в 1. Задержку подобрал банальным for( volatile...). Кривовато, но работает надёжно.

Вторая шина (микроконтроллера LPC4337) также использует программное дёргание CS, коих аж целых 7 (три АЦП более медленные, две флешки, sd-карта и жк-дисплечик). Т.е. просто и в лоб дёргаю ножки CS по таблице, в зависимости от того, к какому слейву обращаемся.

 

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

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


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

Это в случае, если подчиненное устройство допускает одну фазу CS для многих байт данных. Но многие (почти все) АЦП/ЦАП, работающие по SPI, должны дергать CS каждый байт/слово. А если это делать в прерываниях, это равносильно ручному дерганию (в прерывании все равно присутствует код переключения ножки). Это не есть комильфо, ведь цель не достигнута получается (от программного руления ножкой не избавились). В моем же случае все делается автоматически - главное успевай данные обрабатывать. Я оцифровывал на 10кГц, соответственно при программном управлении CS в прерывании мне надо было бы входить в прерывание 20 000 раз в секунду. Для меня, даже несмотря на 180МГц работающий CPU, это видится неприемлимым (не хочу насиловать МК такими частотами прерываний, особенно если от этого можно гибко увильнуть).

 

я не понимаю. а почему нельзя опустить CS - запустить DMA - а в прерывании по окончанию транзакции DMA поднять CS.

Я причину описал выше. Многим подчиненным смена CS жизненно важна для каждого передаваемого единичного объекта данных (байт, полуслово, слово и т.д.).

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


Ссылка на сообщение
Поделиться на другие сайты
Это в случае, если подчиненное устройство допускает одну фазу CS для многих байт данных. Но многие (почти все) АЦП/ЦАП, работающие по SPI, должны дергать CS каждый байт/слово.

У spi есть два режима cs - Motorola и TI режим, и я их постоянно путаю.

Один из них может активировать cs, но не может его снять - предназначен для работы с потоком.

Второй дёргает ногу cs с каждой 4-16 битной одноразовой передачей данных. Размер данных задаётся отдельно.

 

Меня другое волнует, они уже давно придумали fifo буфер и ещё кучу полезностей, но отчего-то размер данных ограничен в 16 бит...

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


Ссылка на сообщение
Поделиться на другие сайты
Меня другое волнует, они уже давно придумали fifo буфер и ещё кучу полезностей, но отчего-то размер данных ограничен в 16 бит...

Ну если свет клином сошёлся на STM32, то вероятно да. :laughing:

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


Ссылка на сообщение
Поделиться на другие сайты
Я причину описал выше. Многим подчиненным смена CS жизненно важна для каждого передаваемого единичного объекта данных (байт, полуслово, слово и т.д.).

 

STM32F0xx так умеет. Взводите бит NSSP в регистре SPI_CR2. Сбрасывает NSS в ноль перед началом передачи, и устанавливает а 1 после ее окончания без каких либо программных вмешательств. В том числе и в DMA режиме.

Изменено пользователем nanorobot

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


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

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

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

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

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

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

Войти

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

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