Инструменты пользователя

Инструменты сайта


stm32:vsmilandr

STM32 vs Milandr

Некоторые неочевидные отличия в реализации блоков периферии микроконтроллеров.

SPI: Пересылка отдельных байт

В МК STM32F7хх блок SPI содержит FIFO TX и RX на 32 бита, доступ к которому осуществляется через регистр DR. Размер слова SPI может составлять от 4 до 16-ти бит. Оказалось, что запись в регистр DR добавляет в FIFO_TX сразу 16 бит, даже если размер слова настроен на количество бит ⇐ 8. При этом в регистре SR выставляется флаг что буфер FIFO_TX на половину занят. Чтобы записать / считать через регистр DR отдельный байт из FIFO_TX/FIF_RX необходимо чтобы компилятор сформировал байтные STRB/LDRB инструкции к регистру DR. Если инструкции будут словные STR/LDR, то запись и чтение будут происходить по 16-ть бит, т.е. равны максимальному размеру слова.

Итого, для чтения и записи необходимы два вида функций - для слов больше 8 бит и для слов меньше 8 бит:

// for spi_word > 8 bits
__STATIC_INLINE void     NT_SPI_Send(SPI_TypeDef *SPIx, uint8_t value) { SPIx->DR = value; }
__STATIC_INLINE uint16_t NT_SPI_Read(SPI_TypeDef *SPIx)                { return SPIx->DR; }

// for spi_word <= 8 bits
__STATIC_INLINE void    NT_SPI_Send8(SPI_TypeDef *SPIx, uint8_t value) {*(__IO uint8_t*)(&SPIx->DR) = value; }
__STATIC_INLINE uint8_t NT_SPI_Read8(SPI_TypeDef *SPIx)    { return  *(__IO uint8_t*)(&SPIx->DR); }

В STM32F3/STM32F4 обычно нет FIFO у SPI, а размер слова может быть только либо 8, либо 16 бит. Но судя по коду HAL при посылке отдельного байта так-же требуется приведение регистра DR к байтному обращению.

В SPI блоках микроконтроллеров Миландр это работает не так. Обращение к регистру DR приводит к тому, что в блок записывается слово заданной размерности.

В МК от Миландр SPI имеет FIFO на 16-ть слов, и если размер слова настроен, скажем, в 5 бит, то записав в DR шестнадцать байт FIFO заполнится полностью. Т.е. размер слова в FIFO равно максимально возможному - т.е. 16 бит, но из каждого слова FIFO в линию уходит только количество бит равное размеру слова SPI. Размер слова здесь тоже регулируется от 4 и до 16 (в некоторых МК и до 32 бит).

Т.е. в данных микроконтроллерах нужны только функции NT_SPI_Send() / NT_SPI_Read(), вариации для байтных обращений не нужны.

В МК STM32F7хх чтобы принять отдельный байт (или слово меньшей битности) по SPI необходимо установить в регистре CR2 бит FRXTH (FIFO_Rx reception threshold).

  • Если FRXTH = 0, то флаг RXNE (есть принятое слово и его надо считать) устанавливается при заполнении FIFO_Rx на половину - т.е. при принятых 16-ти битах. При байтной пересылке это два целых слова, а если мы ждем только одно слово, то выставления флага мы не дождемся.
  • Если FRXTH = 0, то флаг RXNE выставляется при заполнении FIFO_Rx на четверть - т.е. 8-мь бит. Выставление флага RXNE будет говорит о необходимости вычитать один байт.

SPI Slave: Прием данных на высокой скорости, NSS(CS)

Столкнулся с тем, что STM32F765 в режиме SPI Slave не принимает данные от ПЛИС при частоте SCK выше порядка 6MHz. Хотя по даташиту связь по SPI должна работать вплоть до 54МГц.

При пересылке по SPI ПЛИС формирует сигналы CS(FSS), SCK, MOSI и принимает от STM32 сигнал по MISO. При формировании сигналов линия CS опускается в 0 раньше первого переключения тактового SCK на длительность полупериода SCK, что казалось стандартным решением. Но оказалось, что для STM32F765 необходимо чтобы это время составляло 2 периода SCK. Скорее всего это время необходимо, чтобы микроконтроллер успел активировать управление пином MISO. Т.к. без активного выбора по CS блок SPI видимо удерживает MISO в 3-м состоянии.

Поскольку я использовал режим SPI_MODE = 1, то дерганье CS как FSS (Frame Sync Signal) мне не нужно. (В режимах SPI_MODE = 0 и SPI_MODE = 3 блок SPI должен выставлять первый бит на MISO при опускании CS в 0 при начале посылки, т.е. еще до первого переключения SCK. Т.к. по первому переключению SCK этот первый бит уже должен быть сэмплирован.)

Выставив постоянный уровень CS = 0 в ПЛИС при рестарте связка по SPI сразу заработала на ожидаемой частоте 25МГц.

В микроконтроллерах Миландр с максимальной частотой обмена все несколько хуже. Максимальная частота обмена для приема в режиме SPI Slave определяется как pclk / 12. Т.е. если частота SPI_Clock составит максимальную для некоторых микроконтроллеров 144МГц, то максимальная частота обмена SPI может быть 144 / 12 = 12 MHz. Максимальная частота обмена в режиме мастера составляет pclk / 4.

  • Миландр: В режиме мастера сигнал FSS(CS) формируется аппаратно для каждого слова.
  • В STM32 сигнал CS опускается в 0 при включении блока SPI в регистре CR1 битом SPE, и поднимается в 1 при выключении блока тем же битом.
stm32/vsmilandr.txt · Последнее изменение: 2023/06/20 11:37 — vasco