Jump to content

    

Алгоритм передачи данных по SPI

Подскажите надежный вариант передачи  данных по SPI. 

Задача такая надо сделать прием/ передачу данных с stm32f4(мастер) в stm32f0(slave).

Слейв это "аналог расширителя USART",  он принимает потоки данных по одним USART(2 шт) и параллельно выдает потоки данные по другим USART(2шт), вот по spi надо считать принятые данные и закинуть новые.

В железе между процессорами по мимом основных выводов SPI(MISO,...) заложенные ещё 2 вывода RD  RW(это походу лишнее).

Так что по получению одного пакета данных slave может выдать сигнал мастеру на чтение данных, только как мастеру узнать сколько надо прочитать данных 1 пакет данных(с 1 usat 1 КБ )? Или 2 пакета(с двух usart 2кб)?

Подумываю сделать регистр принятых данных в slave и после того как был выставлен лог 1 на линии RD сначала одним запросом прочитать "регистр" сколько данных надо принять,  и другим запросом считать все данные. (А если данные прийдут после считывания регистра?) 

Теперь по поводу самого SPI как, правильнее все настроить? В прошлом проект использовал такой алгоритм. 

1) Ожидаем прерывание 1->0 по CS(настраиваем SPI, так как только через reset spi очищаться буффер в stm32f0)

1.1) Включаем прерывание по CS из 0->1 (выключаем SPI)

2) Принимаем шапку через прерывания(вытаскиваем размер данных)

3) Настраиваем DMA по количеству данных

4) после завершения передачи spi и dma выключиться сам см пункт 1.1

Но как то выглядит замудренно, можно проще? 

 

 

Share this post


Link to post
Share on other sites

Что-то у вас каша какая-то.

Данные передаются только в одну сторону или во все? какие USART(синхронные или асинхронные) и куда передают данные? И сколько всего USART? Если синхронные, насколько синхронно надо всё делать? И не очень понятно это потоки данных или всё-таки зависимые блоки данных?

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

Share this post


Link to post
Share on other sites
6 hours ago, pokk said:

. . .  (А если данные прийдут после считывания регистра?)  . . .

У должен быть регистр статуса и состояния FIFO слейва для каждого канала. "Новые" данные должны спокойно-независимо приходить в приемный кольцевой байтовый буфер (если он не переполнен). Данные (массив структур) в FIFO могут содержать указатели на начала пакетов во входном кольцевом буфере, длину и разные флаги (например результат проверки CRC пакета).

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

 

 

Share this post


Link to post
Share on other sites
7 hours ago, HardEgor said:

Данные передаются только в одну сторону или во все? какие USART(синхронные или асинхронные) и куда передают данные? И сколько всего USART?

Всего USART пока 4, данные передаются в обе стороны, это настраивает пользователь, может бы как 4 на передачу в slave так и 4 на прием из slave, так же разные комбинации (2 передача 2 прием), это все конфигурируеться в мастере. Планирую сделать по измению конфигурации отправлять блок конфигурации slave.

8 hours ago, HardEgor said:

И не очень понятно это потоки данных или всё-таки зависимые блоки данных?

Поток представляет собой идущие друз за другом блоки данных размером 1 кб.

7 hours ago, k155la3 said:

У должен быть регистр статуса и состояния FIFO слейва для каждого канала. "Новые" данные должны спокойно-независимо приходить в приемный кольцевой байтовый буфер (если он не переполнен)

Да тут планировал сделать кольцевой буфер на каждый поток  и по приему блока данных увеличивать счетчик блоков в буфере. И после приема каждого блока данных запускать процедуру формирование приемного пакета, примерно с таким алгоритмом:

1) Пройтись по всем буферам и выявить которые надо передавать(счетчик блоков >0)

2) Скопировать блок данных в передающий массив SPI c пометкой с какого буфера он был извлечен

3) Посчитать размер получившегося массива занести его в регистр

4) Выставить сигнал мастеру на забор данных (сигнал по линии RD)

 

7 hours ago, k155la3 said:

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

Это да полезная штука благодарю. 

 

 

 

 

 

Share this post


Link to post
Share on other sites
44 минуты назад, pokk сказал:

Всего USART пока 4, данные передаются в обе стороны, это настраивает пользователь, может бы как 4 на передачу в slave так и 4 на прием из slave, так же разные комбинации (2 передача 2 прием), это все конфигурируеться в мастере. Планирую сделать по измению конфигурации отправлять блок конфигурации slave.

Поток представляет собой идущие друз за другом блоки данных размером 1 кб.

master and slave - это имеются ввиду SPI?

Т.е. :

 - каждый USART либо приемник, либо передатчик или все они могут быть приемопередатчиками?

 - USART могут иметь разные скорости? Макс. скорость одного USART?

 - максимум  4 приемника или 4 передатчика или любая комбинация, так?

 - при передаче через SPI к блоку 1кб надо добавлять номера USART (+1 байт)

 - по SPI передается пакет конфигурации

Share this post


Link to post
Share on other sites
1 hour ago, HardEgor said:

master and slave - это имеются ввиду SPI? 

Да про spi

1 hour ago, HardEgor said:

- каждый USART либо приемник, либо передатчик или все они могут быть приемопередатчиками?

Да

 

1 hour ago, HardEgor said:

 - USART могут иметь разные скорости? Макс. скорость одного USART? 

Скорость у всех одинакова. Скорости SPI хватает с 3х кратным запасом что бы все принимать/передавать.  

 

1 hour ago, HardEgor said:

 - максимум  4 приемника или 4 передатчика или любая комбинация, так?

Все верно

1 hour ago, HardEgor said:

- при передаче через SPI к блоку 1кб надо добавлять номера USART (+1 байт)

Да, для того что бы по максимум нагрузить SPI и не дробить DMA  на более мелкие посылки, решил объединить по максимум в одну большую посылку(все потоки, которые принялись), по этому и добавляю номер потока к данным.

 

Edited by pokk

Share this post


Link to post
Share on other sites
2 hours ago, pokk said:

. . . 2) Скопировать блок данных в передающий массив SPI c пометкой с какого буфера он был извлечен

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

 

 

 

Share this post


Link to post
Share on other sites
1 minute ago, k155la3 said:

Если блоки данных фиксированного

Да блоки фиксированного размера, всегда пытался так делать, и вечно получал грабли,  то чего то не хватает что ещё что нибудь, в данном случае, не получиться все  принятые данные с несколько потоков объединить(хотя может это и не актуально).

Share this post


Link to post
Share on other sites
1 minute ago, pokk said:

Да блоки фиксированного размера, . . .

в slave, при приеме блока (пакета) из канала, целостность пакета проверяется (CRC, заголовок итп) ? 

RAM сколько ?  (под буферизацию, если 4 канала)

В каждом канале - буфер на 3 пакета максимальной длины. IN_Channl1[3]

IN_Channl1[0] - то что "льется" по приему из канала в данный момент

IN_Channl1[1] - принято, проверено, передано мастеру на обработку. (ждет своей "участи"-приговора от мастера)

IN_Channl1[2] - предыдущий принятый (и проверенный мастером) пакет, который должен быть "оттранслирован" (передается сейчас) далее на другой USART-TX.

Указатель буфера USART-TX установлен на IN_Channl1[2].  Данные из IN_Channl1[2] сейчас в процессе передачи по USART-TX Channl2.

(например это "транзитный" пакет, который мастеру вообще не интересен)

"Передающих" буферов нет вообще, их роль выполняет приемный буфер. (если конечено, не требуется обработка или формирование с нуля ответного пакета) 

 Это "к сведению", может Вам подойдет.

 

 

Share this post


Link to post
Share on other sites
1 час назад, pokk сказал:

Скорость у всех одинакова. Скорости SPI хватает с 3х кратным запасом что бы все принимать/передавать.  

Т.е. если все 4 UART работают и на прием и на передачу с трекратным запасом?

Тогда всё элементарно - полная загрузка, это когда данные идут на полной скорости по всем UART, тогда:

В 1кб блоках данных делаем флаг: 0-нет данных, 1...4  - данные соответств. UART

Синхронно передаём данные блоками 1Кб по MOSI и MISO. slave выдает master'у индикатор READY готовности к передачи.

Т.е. тупо молотим во все стороны по SPI на полной скорости. Загрузка процессора будет только на прерываниях DMA.

1. Одновременно оба процессора готовят данные, настраивают DMA c обеих сторон

2. когда master готов, он проверяет READY(флаг готовности slave)

3. Если READY встал, то master запускает передачу

4. По окончанию передачи в обеих процессорах вызываются прерывания, slave сбрасывает READY  и переходим к п.1

5. проверяем флаг блока данных  - если ноль, то ничего с ним не делаем. Если другое число - обрабатываем.

 

Это будет работать в любой конфигурации UART.

 

p.s. Мда, смотрю на QuadSPI в H7 пишу всё это.... а в F0-то обычный SPI...

 

Но принцип не изменится - рассчитывайте алгоритм на полную загрузку SPI.

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this