Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Пауза между байтами в SPI DMA, STM32F4xx
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Страницы: 1, 2
Rash
Приветствую.
Может кто нибудь подсказать возможно ли сделать паузу между байтами в SPI при использовании DMA, STM32F4xx? например совместно с каким либо таймером. А то многие медленные мс требуют паузы между байтами несколько сотен нсек и для работы с ними по DMA приходится понижать частоту до 1-2 МГц, хотя сами они держат до 8 МГц при побайтовом вычитывании. Мк STM32F4xx.
scifi
Таймеры вполне способны генерировать запросы DMA с нужным интервалом и в нужном числе.
Rash
а примера случаем нет такого для настройки?
adnega
Цитата(Rash @ Sep 19 2013, 11:25) *
А то многие медленные мс требуют паузы между байтами несколько сотен нсек.

Это какие, например?
DmitryM
Цитата(adnega @ Sep 19 2013, 12:15) *
Это какие, например?

например CMX608/CMX618/CMX638
tNXT Inter-Byte time 200 – – ns

Не пойму причем тут таймер, если Вы передаете через DMA. Таймером можно запустить передачу, но не вставить паузу между байтами в пакете. Это работа модуля SPI - поддержка защитных интервалов между байтами, пакетами и пр.
Rash
одна из микр это CMX618 имено эти 200 нсек и нужно сделать.
но насколько я понял поддержку защитных интервалов между байтами при использовании DMA не сделаешь?
Или есть варианты?
adnega
Цитата(DmitryM @ Sep 19 2013, 17:30) *
например CMX608/CMX618/CMX638
tNXT Inter-Byte time 200 – – ns

Если внимательно посмотреть картинку, то tNXT расстояние между двумя соседними ФРОНТАМИ тактового сигнала.
При этом на максимальной частоте tNXT = tCK, т.е. никакой дополнительной задержки вставлять не нужно.
Rash
это зависимости на какой частоте запустить SPI. При частотах > 4МГц, этого значения не будет хватать.
adnega, Вопрос не в том как обойти какие либо ограничения, а в том возможно ли сделать поддержку защитных интервалов между байтами при использовании DMA
megajohn
Цитата(Rash @ Sep 19 2013, 17:36) *
Или есть варианты?


там от фронта последнего бита N байта до первого бита N+1 должно быть не менее 200нс, а это 5МГц тактовой
я бы сделал 4МГц и не парился
DmitryM
Цитата(adnega @ Sep 19 2013, 17:48) *
Если внимательно посмотреть картинку, то tNXT расстояние между двумя соседними ФРОНТАМИ тактового сигнала.
При этом на максимальной частоте tNXT = tCK, т.е. никакой дополнительной задержки вставлять не нужно.

Нужно как минимум один такт клока, а SPI может передавать байты сплошным потоком бит без всякой задержки.
adnega
Цитата(Rash @ Sep 19 2013, 17:52) *
это зависимости на какой частоте запустить SPI. При частотах > 4МГц, этого значения не будет хватать.
adnega, Вопрос не в том как обойти какие либо ограничения, а в том возможно ли сделать поддержку защитных интервалов между байтами при использовании DMA

С помощью таймера, SPI, DMA и какой-то матери конечно можно сделать.
Но тут вопрос в другом: интерфейс SPI настолько "дубовый", что делать какие-либо задержки между байтами,
это на мой взгляд нарушение основной его идеологии. Пока не видел ни одного устройства (и которые Вы
привели в пример тоже к ним относятся), которым бы требовалась задержка ежду байтами.
Чисто формально можно называть такие интерфейсы не SPI, а например C-Bus, но в SPI никаких задержек не требуется.
Если один интерфейс для управляемый светодиодных лент, где пауза соответствует защелкиванию данных, но между
байтами поток непрерывный.

Так как будем интерфейс называть?

Цитата(DmitryM @ Sep 19 2013, 17:55) *
Нужно как минимум один такт клока, а SPI может передавать байты сплошным потоком бит без всякой задержки.

Повторяю, задержка не нужна - посмотрите внимательно, что такое tNXT по диаграмме (а не по переводу с английского).

Добавлю: тут недавно обсуждали DMA + SPI на STM. Картина не такая уж и радужная. Гарантировать интервал в 200нс с помощью DMA, таймеров
и прочего, по-моему, не получится. Относитесь к DMA как сущности, которая может быстро и без участия CPU передать БОЛЬШОЙ кусок данных.
Как только речь заходит о единичных транзакциях начинаются проблемы. Время между DMA-запросом и DMA-транзакцией далеко не ноль, "но это
еще пол беды, вся беда в том, что" это время не постоянно.
DmitryM
Цитата(adnega @ Sep 19 2013, 18:22) *
Повторяю, задержка не нужна - посмотрите внимательно, что такое tNXT по диаграмме (а не по переводу с английского).

Задержка нужна, проверено на собственно опыте, иначе мсх (в моем случае CMX638) не дает верные данные. Да можно понизить частоту клока и тем самым выдержать эти несчастные 200нс. В моем случа все решалось просто, у атмела sam7s все это умеет делать модуль SPI, задал параметры и все. В случае с стм32 этого сделать нельзя при работе через DMA, а поллингом как-то некузяво, итак есть чем заниматься. Здесь по-моему только снижением частоты клока.
ЗЫ. Разработчики мсх специально указали Inter-Byte time, могли бы вообще не указывать, tCK сказали, что не меньше такого то и все, ан нет, указали, обратили внимание.
Rash
adnega, Задержка байтами в SPI нужна конечно меньше чем tNXT расстояние между двумя соседними ФРОНТАМИ, но если посылать SCK постоянно (при использовании DMA) например с частотой 5МГц, то время tNXT уже не уложиться в требуемые 200 нсек, и часть данных изказиться. Но если Читать данные без DMA с проверкой флагов состояния SPI, на всё тех же 5 МГц, то все данные будут правильные, т.к. есть время на выполнение ассемблерных инструкций и всё укладывается в 200 нсек. Проверено лог. анализатором. Есть ещё и другие микросхемы для которых это время должно быть > 250 нсек.
Также в SPI есть чёткие предделители частоты. И получается большой шаг между выбором частоты SCK.
В результате при использовании DMA для таких микр. получается время вычитывания будет в несколько раз > если это сделать по прерываниям или с ожиданием флагов.

А теперь давайте по существу вопроса. Я просил рассказать какие есть возможности сделать задержку между байтами (если они есть), а не разъяснить как работать с какой либо микрой. Я таких возможностей пока не нашёл.
DmitryM
Цитата(Rash @ Sep 19 2013, 18:42) *
А теперь давайте по существу вопроса. Я просил рассказать какие есть возможности сделать задержку между байтами (если они есть), а не разъяснить как работать с какой либо микрой. Я таких возможностей пока не нашёл.

В STM32F4 при SPI c DMA этого сделать нельзя, по крайней мере я смотрел STM32F407. В SAM7S как я уже писал выше - можно.
adnega
Цитата(Rash @ Sep 19 2013, 18:42) *
А теперь давайте по существу вопроса. Я просил рассказать какие есть возможности сделать задержку между байтами (если они есть), а не разъяснить как работать с какой либо микрой. Я таких возможностей пока не нашёл.

У STM я таких возможностей не видел.

Добавлю: сейчас посмотрел на STM32F3xx (у них SPI другой)
Цитата
SPI special features
26.4.1 NSS pulse mode
This mode is activated by the NSSP bit in the SPIx_CR1 register and it takes effect only if
the SPI interface is configured as Motorola SPI master with capture on the first edge
(SPIx_CR1 CPHA = 0). When activated, an NSS pulse is generated between two
consecutive data frame transfers when NSS stays at high level for the duration of one clock
period at least. This mode allows the slave to latch data. NSSP pulse mode is designed for
applications with a single master-slave pair.


На картинке таки вставляет один пробел в SCK, но не знаю будет ли работать с DMA.
Могу как-нить попробовать, или F3 для Вас не вариант.
adnega
Попробовал. Получилось))
Правда, на STM32F303 (с новым SPI).

Код
void init_SPI2(void)
{
    SPI2->CR1 =
            (1 << SPI_CR1_SSM)
        | (1 << SPI_CR1_SSI)
        | (0 << SPI_CR1_SPE)
        | (2 << SPI_CR1_BR)
        | (1 << SPI_CR1_MSTR);

    SPI2->CR2 =
            (1 << SPI_CR2_SSOE)
        | (7 << SPI_CR2_DS)
        | (0 << SPI_CR2_FRF)
        | (1 << SPI_CR2_NSSP)          // ВСТАВИТЬ ПАУЗЫ
        | (0 << SPI_CR2_TXDMAEN);

    SPI2->CR1 =
            (1 << SPI_CR1_SSM)
        | (1 << SPI_CR1_SSI)
        | (1 << SPI_CR1_SPE)
        | (2 << SPI_CR1_BR)
        | (1 << SPI_CR1_MSTR);
}

Передача:
        SPI2->CR2 =
                (1 << SPI_CR2_SSOE)
            | (7 << SPI_CR2_DS)
            | (0 << SPI_CR2_FRF)
            | (1 << SPI_CR2_NSSP)
            | (0 << SPI_CR2_TXDMAEN);

        DMA1_Channel5->CCR =
                (DMA_PL_HIGH << DMA_CCR_PL)
            | (DMA_SIZE_BYTE << DMA_CCR_MSIZE)
            | (DMA_SIZE_BYTE << DMA_CCR_PSIZE)
            |    (1 << DMA_CCR_DIR)
            | (1 << DMA_CCR_MINC)
            | (0 << DMA_CCR_EN);

        DMA1_Channel5->CPAR = (DWORD)&SPI2->DR8;
        DMA1_Channel5->CMAR = (DWORD)&val;
        DMA1_Channel5->CNDTR = 8;

        DMA1->IFCR = (0x0F << 16);

        DMA1_Channel5->CCR =
                (DMA_PL_HIGH << DMA_CCR_PL)
            | (DMA_SIZE_BYTE << DMA_CCR_MSIZE)
            | (DMA_SIZE_BYTE << DMA_CCR_PSIZE)
            |    (1 << DMA_CCR_DIR)
            | (1 << DMA_CCR_MINC)
            | (1 << DMA_CCR_EN);

        SPI2->CR2 =
                (1 << SPI_CR2_SSOE)
            | (7 << SPI_CR2_DS)
            | (0 << SPI_CR2_FRF)
            | (1 << SPI_CR2_NSSP)
            | (1 << SPI_CR2_TXDMAEN);


Частота SPI 72Мгц/8/2 = 4.5МГц.
Пауза между битами 540нс.
DmitryM
Цитата(adnega @ Sep 19 2013, 23:45) *
Попробовал. Получилось))

Это не вариант. Снятие nSS означает завершение транзакции, а не паузу между "байтами"!!!!
adnega
Цитата(DmitryM @ Sep 20 2013, 00:00) *
Это не вариант. Снятие nSS означает завершение транзакции, а не паузу между "байтами"!!!!

Дык, NSS-ом в STM обычно софтово машут.
DmitryM
Цитата(adnega @ Sep 20 2013, 00:01) *
Дык, NSS-ом в STM обычно софтово машут.

А, я все больше по старинке (FPGA) на железку полагаюсь wink.gif Нафига лишний боян. машет nSS, ну и пусть машет.
А топикпастреру, следуюший алгоритмтм, но без DMA: послал, узнал что отправилось, взвел таймер, по истечению таймера запустил на один байт и т.д.
adnega
Цитата(DmitryM @ Sep 20 2013, 00:07) *
А, я все больше по старинке (FPGA) на железку полагаюсь wink.gif Нафига лишний боян.

)) Сравнили.
В МК чем-то нужно жертвовать. Из всех зол, это меньшее. Но ТС вряд ли подойдет, т.к. семейство другое...

PS. На большом отрезке любопытно наблюдать динамику в ST.
Как переделали AFIO в новых процах (большое за это спасибо), в новых SPI поддерживаются посылки от 4 до 16 бит
(и паузы вставлять можно), появились 32-битные таймеры и т.п. Но на мой взгляд плохо, что переделали RTC (навороченный календарь
вместо счетчика секунд), плохо что вынесли GPIO из bit-band региона((
DmitryM
Цитата(adnega @ Sep 20 2013, 00:25) *
в новых SPI поддерживаются посылки от 4 до 16 бит (и паузы вставлять можно)

Как? Именно об этом спрашивает Rash.
ЗЫ. Легко это сделал на SAM7
adnega
Цитата(DmitryM @ Sep 20 2013, 00:32) *
Как? Именно об этом спрашивает Rash.
ЗЫ. Легко это сделал на SAM7

Дык, ответ в сообщении 16.
DmitryM
Цитата(adnega @ Sep 20 2013, 00:58) *
Дык, ответ в сообщении 16.

Опять? nSS нельзя снимать.
adnega
Цитата(DmitryM @ Sep 20 2013, 01:03) *
Опять? nSS нельзя снимать.

По второму кругу. Не используйте аппаратное управление NSS и будет Вам счастье.
Не понимаю, что мешает опустить NSS перед передачей и поднять когда все закончится?
Более того, когда будете подключать SD-карту по SPI при чтении сектора данные идут не сразу,
нужно засылать FF пока не придет ответ со статусом, затем с помощью DMA можно прочитать
сразу сектор. В таких случаях только софтовое управление NSS или я чего-то упустил в этой жизни...
DmitryM
Цитата(adnega @ Sep 20 2013, 02:30) *
В таких случаях только софтовое управление NSS или я чего-то упустил в этой жизни...

Ой-ёй.
bb-offtopic.gif ИМХО, то что можно/нужно сделать аппаратно - нужно делать аппаратно. Незачем программе считать задержки после выставления nSS и перед началом тактирования. Там где нельзя - приходится делать программно.
FF для SD карты формируем по прерыванию TXRDY, а потом читаем с помощью DMA. Ногодрыг вещь конечно хорошая, но занимает процессорное время. Зачем?
HHIMERA
Вы хоть понимаете о чём идёт речь??? rolleyes.gif
Rash
NSS и так программный, ибо в STM аппаратный он вроде только для slave режима. Переключать его внутри посылки думаю не правильно, поэтому F3 не вариант. Да и F4 заложен на дальнейшее макс. использование его возможностей, т.к. цена этого мк в данной случае не жмёт. Вот если бы возможно было бы сделать отправку каждого байт в SPI по тайм-ауту таймера и всё это без использование ресурсов мк, был бы реально мощный SPI в STM (даже пусть ещё таймер один забрался, всё равно их куча ещё). А так получается мощные и быстрые контролеры должны по старинке то ли через прерывания, то ли по ожиданию флагов читать данные из периферии по SPI.
HHIMERA
Цитата(Rash @ Sep 20 2013, 09:59) *
Вот если бы возможно было бы сделать отправку каждого байт в SPI по тайм-ауту таймера и всё это без использование ресурсов мк, был бы реально мощный SPI в STM (даже пусть ещё таймер один забрался, всё равно их куча ещё).

Ещё во втором посте вам выдали самое ценное... идею, реализацию...
Потрудитесь хоть немножко поработать головой и руками... там текста... несколько строчек... ничего особенного...
Настраиваете таймер, настраиваете ДМА... Запускаете ДМА, запускаете таймер...
DmitryM
Цитата(HHIMERA @ Sep 20 2013, 11:34) *
Ещё во втором посте вам выдали самое ценное... идею, реализацию...
Потрудитесь хоть немножко поработать головой и руками... там текста... несколько строчек... ничего особенного...
Настраиваете таймер, настраиваете ДМА... Запускаете ДМА, запускаете таймер...

DMA на один байт? А зачем он тогда нужен?
HHIMERA
Цитата(DmitryM @ Sep 20 2013, 10:41) *
DMA на один байт? А зачем он тогда нужен?

Ысчо разз!!!
Вы точно в теме??? rolleyes.gif
scifi
Цитата(Rash @ Sep 20 2013, 10:59) *
Вот если бы возможно было бы сделать отправку каждого байт в SPI по тайм-ауту таймера и всё это без использование ресурсов мк, был бы реально мощный SPI в STM (даже пусть ещё таймер один забрался, всё равно их куча ещё).

Вы вообще читаете ответы на ваши вопросы? Я именно такой вариант и предложил с самого начала. И да, ничего невозможного в этом нет.
Rash
не разобрался я как через таймер DMA запускать. Понял пока, что как то через триггерный режим.
scifi
Цитата(Rash @ Sep 20 2013, 12:13) *
не разобрался я как через таймер DMA запускать. Понял пока, что как то через триггерный режим.

Ну так разбирайтесь. Я запускал, работает в соответствии с мануалом.
adnega
Цитата(Rash @ Sep 20 2013, 12:13) *
не разобрался я как через таймер DMA запускать. Понял пока, что как то через триггерный режим.

Все просто: DMA натравливаете на буфер памяти и на SPI->DR.
Но выбираете канал, который управляется событием по таймеру, а не канал для SPI_TX.
Настраиваете таймер с нужной частотой, разрешаете ему генерировать DMA-запросы.
Если CPU у Вас работает на 168МГц, то ничего страшного. Если частота ниже, то будут
неприятности связанные с тем, что между DMA-запросом и DMA-транзакцией проходит от 12 тактов.

Позже попробую, покажу в чем может быть затык.
Какая частота CPU (168МГц), шины для SPI (168/2)?
Номер SPI (SPI2)?
Какая частота у SPI_SCK (5.25МГц = 168/32)?
Какая задержка tNXT (250нс)?
Какая длина посылки?
Какой таймер свободен?
Rash
* частота CPU = 168МГц
* Номер - SPI2, SPI3
* частота у SPI_SCK подбирается автоматом при настройке (определяется предделитель в зависимости от частоты шины), минимальная от максимально заданной.
* задержка tNXT 200нс и 250нс
* длина посылки - от 20 до 100 байт
* занят только TIM7, но не принципиально
scifi
Цитата(adnega @ Sep 20 2013, 12:34) *
Настраиваете таймер с нужной частотой, разрешаете ему генерировать DMA-запросы.

Ну да, а чтобы запросы не генерировались бесконечно, нужен второй таймер, чтобы всё это в нужный момент остановилось, причём сделать можно без прерываний и вообще вмешательств процессора: запустил и забыл.
Update:
Пардон, DMA и сам умеет останавливаться после заданного числа посылок.
adnega
Цитата(scifi @ Sep 20 2013, 12:46) *
Ну да, а чтобы запросы не генерировались бесконечно, нужен второй таймер, чтобы всё это в нужный момент остановилось, причём сделать можно без прерываний и вообще вмешательств процессора: запустил и забыл.
Update:
Пардон, DMA и сам умеет останавливаться после заданного числа посылок.

Все хитрее, по прерыванию DMA_TC разрешаем прерывание от TIM.
В прерывании от TIM считаем, что последний байт передан полностью, можно взводить NSS и запрещать TIM.

Нужна только передача, как я понял?
DmitryM
Цитата(HHIMERA @ Sep 20 2013, 11:51) *
Ысчо разз!!!
Вы точно в теме??? rolleyes.gif

Точно. По моему мы разговариваем на разных языках wink.gif
1. Можно запустить ДМА по таймеру, но нельзя приостановить передачу после каждого байта для выдержки inter-byte time. Т.е. как только SPI TXE будет выставлен, ДМА загрузит новый байт (если есть) и SPI продолжит непрерывную передачу.
2. Можно использовать Single Mode DMA, но смысл? Это ничем не будет отличаться от записи в SPI DR.
Rash
Цитата
Нужна только передача, как я понял?

нужна и передача, и приём. Только прерывания от таймера, это задействование процессорного времени
scifi
Цитата(adnega @ Sep 20 2013, 12:51) *
Все хитрее, по прерыванию DMA_TC разрешаем прерывание от TIM.
В прерывании от TIM считаем, что последний байт передан полностью, можно взводить NSS и запрещать TIM.

Можно ещё хитрее: сигнал NSS вырабатывать на аппаратном выходе таймера. Эти таймеры можно каскадировать самым причудливым образом. Но по возможности надо избегать, иначе голова закружится :-)
HHIMERA
Цитата(adnega @ Sep 20 2013, 11:51) *
Все хитрее, по прерыванию DMA_TC разрешаем прерывание от TIM.

Не нужны там никакие прерывания... думайте...

Цитата(DmitryM @ Sep 20 2013, 11:54) *
По моему мы разговариваем на разных языках wink.gif

Похоже... вы пытаетесь мне что-то объяснить/доказать... а мне не нужно... у меня всё давно работает...

Цитата(scifi @ Sep 20 2013, 11:55) *
Эти таймеры можно каскадировать самым причудливым образом. Но по возможности надо избегать, иначе голова закружится :-)

Это дело привычки... зато какая сила!!! STM'у респект!!!
adnega
Цитата(Rash @ Sep 20 2013, 12:54) *
нужна и передача, и приём. Только прерывания от таймера, это задействование процессорного времени

Всего на посылку будет возникать два прерывания: одно от DMA, второе от таймера.
Песле посылки очередного байта прерывания не будет. Прерывание нужно только в самом конце
- освободить NSS сразу после передачи последнего байта.

Хотя, если делать прием, то завершение посылки можно настроить по второму DMA_TC, настроеному на события SPI_RX.
Прерывания от таймера в таком случае не понадобится.
Rash
Цитата(adnega @ Sep 20 2013, 12:05) *
Всего на посылку будет возникать два прерывания: одно от DMA, второе от таймера.
Песле посылки очередного байта прерывания не будет. Прерывание нужно только в самом конце
- освободить NSS сразу после передачи последнего байта.

Хотя, если делать прием, то завершение посылки можно настроить по второму DMA_TC, настроеному на события SPI_RX.
Прерывания от таймера в таком случае не понадобится.

NSS я и освобождаю в прерывании по DMA.
DmitryM
Цитата(HHIMERA @ Sep 20 2013, 13:04) *
а мне не нужно... у меня всё давно работает...

у меня тоже, но не на СТМ и без использования таймеров, на голом SPI.


PS. Собственно все сводится к уменьшению частоты SPI, а отчего запускать ДМА - от таймера или от SPI без разницы.
Golikov A.
ДМА посылающий 1 байт не тоже самое что самому положить этот байт в СПИ.

В случае руками
таймер генерит прерывание
вы реагируете на прерывание и прерываете программу
попадаете в обработчик
там кладете байт в СПИ
выходите

В Случае ДМА
таймер генерит прерывание
но обработчик прерывания не вызывается и вы не прерываете программу
ДМА сам по сигналу кладет байт в СПИ

Согласитесь что во втором варианте ресурсы процессора, основной программы не трогаются, она не останавливается.


Дальше если таймер щелкает постоянно генеря прерывания(на которые мы не реагируем, они для ДМА) то и ДМА будет запускаться периодически с заданными задержками. Подобрав время равное (длина посылки байта + пауза), получается выдержать паузу между байтами. Есть проблема со стартом ДМА, так что задержка должна быть чуть больше.

А ДМА как я понимаю послав один байт перенастраивается на следующий, и таким образом происходит посылка группы байт через ДМА, но критерий посылки следующего байта не готовность буфера, а таймер.
adnega
Цитата(Golikov A. @ Sep 20 2013, 13:46) *
А ДМА как я понимаю послав один байт перенастраивается на следующий, и таким образом происходит посылка группы байт через ДМА, но критерий посылки следующего байта не готовность буфера, а таймер.

Именно!
DmitryM
Цитата(Golikov A. @ Sep 20 2013, 13:46) *

Да, Вы правы, в таком варианте будет работать. Придется конечно поизвращаться со стартом транзакции, но это не сложно.
adnega
Ну собственно работа SPI с TIM и DMA.
Обращаю внимание на последнюю картинку. Желтый фронт - событие таймера (считай запуск DMA), но сама посылка начинается значительно позже. И время не стабильно. Поэтому зазор tNXT плавает приблизительно от 170нс до 290нс. И я об этом с самого начала предупреждал. Так сойдет?
Rash
плавая пауза между байтами думаю не проблема, главное что бы минимальная пауза была регулируемая в понятных приделах
Golikov A.
ну это понятно ДМА то надо дождаться свободной шины, но гарантированный минимум спокойно получится... это в разы лучше чем полингом тупить...
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.