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

Реально достижимая скорость по SPI

Тема была навеяна $ilent, но она была закрыта прежде, чем я успел в ней поучаствовать :-).

 

Интересует, прежде всего, потенциально достижимая скорость как в аппаратном исполнении, так и в программном.

 

Какие требования в "железном" исполнении? Необходимо передать по SPI nByte байт из буфера txBuffer (ОЗУ МК) и одновременно принять массив байт такой же длины в rxBuffer (ОЗУ МК). Моя программа выполняется за 8МЦ, т.е. ровно один такт на 1 бит. Интересно, можно ли добиться большего? Что скажут эксперты?

 

Программа $ilent работает в полудуплексе, следовательно можно снизить требования к программной реализации SPI, а именно, необходимо программно формировать только биты данных и синхронизацию на передачу ИЛИ принимать биты данных по положительным фронтам импульсов синхронизации на прием. Моя программа передает один байт за 36МЦ, т.е. за 4,5 такта на 1 бит. Как добиться большего?

 

Народ, не воспринимайте топик слишком сурово, это мой первый на этом сайте...

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


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

А что значит программа выполняется за 8МЦ? Передает все nByte за 8 маш. циклов или я неправильно понял?

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


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

Ничего не понял. Толи у меня башка уже не варит толи одно из двух.

GM повторите 2 раза и помедленнее. :)

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


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

Может вы имели ввиду не мегагерцы а такты?

т.е программа выполняется за 36 тактов ( 4.5 такта на бит)

 

1 такт на бит не получить аппаратно мин прескалер равен 2 и получится 2 такта на бит

пограммно теоретически максимум можно получить тоже 2 такта на бит, но только для отправки и отправлять например константу т.е тупо 16 раз записать в порт (не используя SBI CBI)

примерно так

  LDI R16, 1; pin0 - CLK=1
  LDI R17, 0; pin0 - CLK=0 

  OUT PORTA, R16; bit 7
  OUT PORTA, R17

  OUT PORTA, R16; bit 6
  OUT PORTA, R17

; и т.д нужное число бит

 

но ценность этого кода сомнительна

 

можно так, но уже 3 такта на бит

 

  LDI R17, 0

  LDI R16, 1 | ((val>>6) & 2); pin0 - CLK=1 pin1 - MOSI=bit 7
  OUT PORTA, R16; bit 7
  OUT PORTA, R17

  LDI R16, 1 | ((val>>5) & 2); pin0 - CLK=1 pin1 - MOSI=bit 6
  OUT PORTA, R16; bit 7
  OUT PORTA, R17

; и т.д нужное число бит

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


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

Ничего не понял. Толи у меня башка уже не варит толи одно из двух.

GM повторите 2 раза и помедленнее. :)

 

Прошу прощения за непонятки(:-). Это я, наверное, туплю. Устал, через неделю ухожу в отпуск. Тем не менее, повторяю.

 

В АВР есть аппаратный SPI. С его помощью надо передать и принять некое количество байт максимально быстро. Т.е. нужна программа, которая в основном цикле выполняет следующее

 

1) взять байт из буфера 1, сдвинуть указатель,

2) отправить его в регистр SPDR на передачу,

3) прочитать из SPDR принятый по SPI байт,

4) записать принятый байт в буфер 2, сдвинуть указатель,

5) повторить п.п.1-4 для заданного количества байт.

 

Мною написана программа, основной цикл которой выполняется за 8 тактов процессора.

(Не хочу публиковать преждевременно. чтобы не смущать народ). Меня интересует, можно ли сделать еще быстрее или это предел?

 

Ну и тоже самое для упрощенного програмного варианта, т.е. программное формирование импульсов синхронизации и бит данных только на передачу. Такая программа тоже написана. Цикл на передачу занимает 36 тактов процессора.

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


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

Может вы имели ввиду не мегагерцы а такты? т.е программа выполняется за 36 тактов ( 4.5 такта на бит)

МЦ - это сокращение слов Машинный Цикл. Я думал, это общепринято.

 

1 такт на бит не получить аппаратно мин прескалер равен 2 и получится 2 такта на бит

Я в курсе, что максимальная частота клока равна половине тактовой. Скажем для тактовой частоты процессора в 10 МГц, можно получить 5 Мгц частоту сихронизации для SPI, тогда для передачи одного бита требуется 0,2 мкс, т.е. 2 МЦ(машинных цикла или такта), а для передачи байта потребуется 8*0,2=1,6 мкс или 16 МЦ. Все это делается аппаратно, но моя программа сохраняет принятый байт и передает новый байт за 8МЦ, остальные 8МЦ она простаивает. Если бы был второй SPI, можно было бы успеть и его обработать(:-). А так машина тратит 1 такт своего машинного времени на передачу/прием одного бита, ну и работает вхолостую половину времени.

 

пограммно теоретически максимум можно получить тоже 2 такта на бит, но только для отправки и отправлять например константу т.е тупо 16 раз записать в порт (не используя SBI CBI)

Нет, это не интересно. Надо именно произвольные байты гонять туда-сюда.

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


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

А какие ограничения на использование регистров? Обязательно два буфера? Можно ли использовать прерывание SPI?

2) отправить его в регистр SPDR на передачу,

3) прочитать из SPDR принятый по SPI байт,

хм, а не наоборот?

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

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


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

А какие ограничения на использование регистров? Обязательно два буфера? Можно ли использовать прерывание SPI?

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

 

2) отправить его в регистр SPDR на передачу,

3) прочитать из SPDR принятый по SPI байт,

хм, а не наоборот?

Запись в регистр SPDR инициирует передачу по SPI. После окончания последовательной передачи 8-ми бит можно прочитать принятый байт из регистра SPDR. Можно сначала читать из регистра SPDR, а потом писать в регистр SPDR. Главное, чтобы было четкое понимание, что передается и что принимается.

 

Что-то эксперты тяжело раскачиваются...не хотят делиться секретами мастерства(:-).

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


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

2) отправить его в регистр SPDR на передачу,

3) прочитать из SPDR принятый по SPI байт,

хм, а не наоборот?

А что вы собственно читать из SPDR собрались до записи в него? Результат предыдущего сдвига?

Принцип работы SPI - кольцевой регистр сдвига, пока мастер не инициировал передачу, слэйв ничего сам не отдаст. Поэтому все правильно - сначала пишем в SPDR, потом читаем.

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


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

2) отправить его в регистр SPDR на передачу,

3) прочитать из SPDR принятый по SPI байт,

хм, а не наоборот?

А что вы собственно читать из SPDR собрались до записи в него? Результат предыдущего сдвига?

Принцип работы SPI - кольцевой регистр сдвига, пока мастер не инициировал передачу, слэйв ничего сам не отдаст. Поэтому все правильно - сначала пишем в SPDR, потом читаем.

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

 

Поскольку эксперты не хотят делиться своими тайными приемами и трюками(:-), публикую первый вариант программы для аппаратного скоростного SPI, передача идет на предельно достижимой скорости fCLK/2, fCLK-тактовая частота процессора, один байт передается за 16 машинных циклов (МЦ). Регистровая пара Х указывает на начало передающего буфера, пара Y указывает на байт ПЕРЕД приемным буфером, txByte, rxByte - верхние регистры, скажем r16, r17.

spiLoop:   <nop x 8 раз или другая задача на 8МЦ>
               ld      txByte,X+    ;подготавливаем байт на передачу
               in      rxByte,SPDR  ;читаем принятый байт (первый байт-фиктивный)
               out     SPDR,txByte  ;запускаем байт на передачу
               st      Y+,rxByte    ;сохраняем принятый байт в приемном буфере
               rjmp    spiLoop      ;повторяем цикл

 

Как вы видите, ничего страшного и сложного. Ну вот, весь огонь принимаю на себя(:-).

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


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

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

как Вам уже сказали, Вы элементарноь не понимаете элементарнейший принцип работы SPI :-(

Могу это еще раз подтвердить.

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


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

Поскольку эксперты не хотят делиться своими тайными приемами и трюками(:-), публикую первый вариант программы для аппаратного скоростного SPI, передача идет на предельно достижимой скорости fCLK/2, fCLK-тактовая частота процессора, один байт передается за 16 машинных циклов (МЦ). Регистровая пара Х указывает на начало передающего буфера, пара Y указывает на байт ПЕРЕД приемным буфером, txByte, rxByte - верхние регистры, скажем r16, r17.

spiLoop:   <nop x 8 раз или другая задача на 8МЦ>
               ld      txByte,X+;подготавливаем байт на передачу
               in      rxByte,SPDR ;читаем принятый байт (первый байт-фиктивный)
               out     SPDR,txByte ;запускаем байт на передачу
               st      Y+,rxByte;сохраняем принятый байт в приемном буфере
               rjmp    spiLoop     ;повторяем цикл

 

Как вы видите, ничего страшного и сложного. Ну вот, весь огонь принимаю на себя(:-).

В вашем примере отсутствует проверка готовности буферов приемника и передатчика. Нельзя записывать байт в буфер SPI до того как он освободится и/или не имеет смысла читать байт до того как он запишется в буфер SPI.

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


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

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

как Вам уже сказали, Вы элементарноь не понимаете элементарнейший принцип работы SPI :-(

Могу это еще раз подтвердить.

Ой, кто это(:-)? Кто же мне это сказал, и когда? Чего я там элементарного не понимаю? Всё я понимаю(:-). Но, учтите, задача стоит - достичь максимально возможной скорости передачи по SPI. Приведите внятное видение вами данной проблемы.

 

Подтверждать не надо, надо доказывать, цифрами, программками, ссылками на документы...А так написать, я считаю, это просто гнилой наезд.

 

Поскольку эксперты не хотят делиться своими тайными приемами и трюками(:-), публикую первый вариант программы для аппаратного скоростного SPI, передача идет на предельно достижимой скорости fCLK/2, fCLK-тактовая частота процессора, один байт передается за 16 машинных циклов (МЦ). Регистровая пара Х указывает на начало передающего буфера, пара Y указывает на байт ПЕРЕД приемным буфером, txByte, rxByte - верхние регистры, скажем r16, r17.

spiLoop:   <nop x 8 раз или другая задача на 8МЦ>
               ld      txByte,X+;подготавливаем байт на передачу
               in      rxByte,SPDR;читаем принятый байт (первый байт-фиктивный)
               out     SPDR,txByte;запускаем байт на передачу
               st      Y+,rxByte;сохраняем принятый байт в приемном буфере
               rjmp    spiLoop    ;повторяем цикл

 

Как вы видите, ничего страшного и сложного. Ну вот, весь огонь принимаю на себя(:-).

В вашем примере отсутствует проверка готовности буферов приемника и передатчика. Нельзя записывать байт в буфер SPI до того как он освободится и/или не имеет смысла читать байт до того как он запишется в буфер SPI.

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

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


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

Интересный подход. А остальная программа в момент приёма/передачи пакета ничего неделает.

:)

PC.

Вафли ловит.

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


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

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

Имеет значение. Читать ДО записи нечего, а делать из-за этого буфер на 1 байт больше не имеет никакого смысла. Читать немедленно после записи тоже абсурдно. Зачем изобретать грабли? Порядок работы с SPI описан почти в каждом даташите АВРки имеющей такой модуль:

- пишем байт в SPDR;

- ждем установку SPIF в SPSR (это говорит нам о том, что процесс передачи байта мастера и приема байта слэйва завершен);

- читаем SPDR.

 

В вашем коде нет ожидания флага SPIF, поэтому может возникнуть коллизия (запись в SPDR во время передачи), о чем сигнализирует флаг WCOL регистра SPSR, или вы прочтете недостоверные данные. Еще раз повторюсь - SPI это по сути кольцевой 16 разрядный сдвиговый регистр, 8 бит - регистр мастера, 8 бит регистр слэйва. Сдвиг на один бит регистра мастера влечет за собой сдвиг на один бит регистра слэйва (каждый сдвиг тактируется SCK).

И никаких тайных приемов и трюков....

 

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

Вы привели фрагмент программы которая правильно работать не будет. Не обижайтесь, просто посмотрите в любом даташите диаграмму "SPI Master-slave Interconnection" и вам все сразу станет понятно.

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


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

Присоединяйтесь к обсуждению

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

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...