Пуск SPI трансивера на STM32

от автора

Пролог

SPI это цифровой, последовательный, относительно высокоскоростной, полнодуплексный, синхронный физический интерфейс передачи данных в пределах одной электронной платы PCB. Этот интерфейс служит для обмена данными между микросхемами в пределах одной электронной платы. Ранее в эпоху ARV микроконтроллеров интерфейс SPI и вовсе использовался для пере прошивки микроконтроллеров вместо SWD, как сейчас. По SPI обычно подключают внешние ASIC-и. Это могут быть ADC, акселерометры, дисплеи, DAC, Flash память, CAN трансиверы и прочее. SPI много надежнее, чем его собрат I2C. I2C может зависать, в то время в как SPI просто нечему зависать.

При разработке электроники практически на всех платах нужно передавать данные по интерфейсу SPI.

Во всех микроконтроллерах заложен аппаратный SPI трансивер. Трансивер — это прибор, который может отправлять и принимать бинарные массивы. Полный дуплекс — это когда передача и прием происходят одновременно.

Постановка задачи
Настроить SPI2 трансивер на работу в режиме DMA. Сделать функцию передачи данных в режиме полного дуплекса. В качестве отладочной платы использовать учебно-тренировочную электронную плату JZ-F407VET6. Выбрать GPIO пины PB10, PC2, PC3.

Pin

MCU pin

GPIO

Dir

SCK

47

PB10

out

MISO

17

PC2

in

MOSI

5

PC3

out

Реализация

Настройка SPI передачи данных — это комплекс мер. Надо настроить регистры тактирования, GPIO, SPI, DMA и прерывания.

Настроить тактирование (clock)

—Подать тактирование на используемые GPIO пины.
—Подать тактирование на SPI трансивер.
—Подать тактирование на DMA.

Активировать прерывания (NVIC)
1—Активировать прерывания глобально на уровне процессорного ядра.
2—Определить приоритет прерывания SPI. В случае с SPI2 NVIC номер равен 36
3—Активировать прерывания для каналов DMA (14 и 15).

Поток

IRQn

DMA

stream

channel

SPI2_TX

15

DMA1

stream_4

channel_0

SPI2_RX

14

DMA1

stream_3

channel_0

4—Определить функции обработчики прерываний для DMA каналов. Тут важный момент. Как сделать так, чтобы и отправка по SPI2 и прием по SPI2 работали в режиме DMA одновременно (полный дуплекс режим)? Ведь у них один и тот же корневой DMA: DMA1. У каждого DMA потока должен быть свой собственный и отдельный экземпляр структуры DMA_HandleTypeDef. Для каждого потока надо вызывать DMA_Init для каждого экземпляра потока. Даже вопреки тому, что они ссылаются на один DMA1.

5—Определить функцию обработчик прерываний для SPI.

Активировать GPIO

—Надо физически подключить SPI блок к GPIO пинам микроконтроллера. Для этого надо сконфигурировать 3 GPIO пина на альтернативную функцию SPI2. Переключить внутренний мультиплексор.

Pin

MCU pin

GPIO

Dir

PinMux

Pull

Connector

SCK

47

PB10

out

5

air

P3.5

MISO

17

PC2

in

5

up

P3.7

MOSI

5

PC3

out

5

up

P3.6

Активировать SPI

1—Подать тактирование на SPI трансивер.
2—Активировать прерывание для конкретного SPI трансивера
3—написать обработчик прерывания для SPI
4—Задать приоритет SPI прерывания
5—Выбрать роль трансивера: master или slave.
6—Задать битовую скорость.
7—Задать фазу тактирования.
8—Задать размер сдвигового регистра: 8 бит или 16 бит.
9—Задать порядок передачи бит.
10—Задать событие захвата бита: положительный перепад или отрицательный перепад.

Активировать DMA

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

Надо подать тактирование на DMA c которым будет работать SPI. В моем случает это DMA1

Активировать DMA каналы
—Выбрать Номер DMA, поток и канал на конкретный экземпляр поток передачи. Это указано в спецификации на микроконтроллер.

Поток

IRQn

DMA

stream

channel

SPI2_TX

15

DMA1

stream_4

channel_0

SPI2_RX

14

DMA1

stream_3

channel_0

—Активировать канал DMA ассоциированный с SPI отправкой
Ассоциировать SPI трансивер с DMA каналом отправки

__HAL_LINKDMA(&Node->handle,hdmatx,(DmaCh->dma_h));

—Активировать канал DMA ассоциированный с SPI приёмом
Ассоциировать SPI трансивер с потоком DMA отправки.

  __HAL_LINKDMA(&Node->handle,hdmarx,DmaCh->dma_h);

—Активировать два прерывания DMA для работы SPI в режиме DMA.

Поток

IRQn

DMA_stream

SPI2_TX

15

DMA1_stream_4

SPI2_RX

14

DMA1_stream_3

—Назначить разный приоритет всем каналам DMA.
—настроить источник канала: адрес, выравнивание, инкремент.
—настроить приемник канала: адрес, выравнивание, инкремент.
—Указать сколько байт будем передавать по DMA.

Опрос SPI трансивера

Когда SPI уже сконфигурирован, то можно периодически вычитывать статусный регистр и следить за здоровьем SPI трансивера. Так можно выявить события аварий и принять меры. Например пере инициализировать SPI-трансивер.

Комбинаторика такова, что у SPI драйвера помимо init должно быть еще минимум 9 функций.

operation

move mode

move mode

move mode

operation

polling

interrupts

DMA

read

spi_read_polling

spi_read_interrupt

spi_read_dma

write

spi_write_polling

spi_write_interrupt

spi_write_dma

write_read

spi_write_read_polling

spi_write_read_interrupt

spi_write_read_dma

Модульное тестирование SPI трансивера

Я подготовил набор модульных тестов для верификации SPI трансивера

Механизм

тип теста

Название теста

CLI команда пуска теста

polling

write

spi1_write_polling

tr spi1_write_polling

polling

read

spi1_read_polling

tr spi1_read_polling

polling

write_read

spi1_write_read_polling

tr spi1_write_read_polling

interrupt

write

spi1_write_interrupt

tr spi1_write_interrupt

interrupt

read

spi1_read_interrupt

tr spi1_read_interrupt

read

spi1_miso

tr spi1_miso

interrupt

write_read

spi1_write_read_interrupt

tr spi1_write_read_interrupt

dma

write

spi1_write_dma

tr spi1_write_dma

dma

read

spi1_read_dma

tr spi1_read_dma

dma

write_read

spi1_write_read_dma

tr spi1_write_read_dma

Тестирование приёма по SPI

Тест SPI приёма может быть таким:
1—Отключить провод от SPI пинв MISO .
2—Установить на пине MISO Pull Up.
3—Прочитать байт по SPI.
4—В приёмном регистре должно быть 0xFF.
5—Установить на пине MISO Pull Down.
6—Прочитать байт по SPI.
7—В приёмном регистре должно быть 0x00.

Если так, то тест пройден. Если нет, то приём по SPI не работает.

Тестирование отправки по SPI

1—В обработчике прерываний по окончании отправки увеличивать счетчик отправленных байт.
2—Запустить SPI отправку
3—Подождать прерывания окончания отправки
4—Убедиться что счетчик отправленных байт увеличился на нужное значение.

Если прерывание произошло, то тест пройден. Если прерывания не было, то интерфейс не работает.

Тестирование полнодуплексной операции по SPI
—Можно взять проводную перемычку, соединить пин MOSI и MISO, выполнить полно дуплексную запись-чтение и проверить, что микроконтроллер принял то же самое, что и отправил. Если массив совпал, значит тест пройден.

Тест DMA
Что касается модульного теста DMA, то тут можно просто реализовать функцию memcpy() на основе DMA и прогнать её для всех свободных потоков. Если массив прописался по новому адресу и совпал по значению байт в байт, значит тест пройден.

Итог

Удалость научиться отправлять и принимать массивы по интерфейсу SPI на микроконтроллерах семейства STM32F4x во всех трёх режимах: опрос, прерывания и DMA. Как видите запуск SPI это достаточно громоздкая работа. Надо было настроить CLK, GPIO, NVIC, SPI и DMA. Зато теперь это открывает прямую дорогу для подключения к микроконтроллеру всяческих внешних ASICов: SPI NAND-Flash памяти, микросхем с ADC, RF трансиверы, CAN-трансиверы, SD карты, акселерометры и прочее.

Словарь

Сокращение

Расшифровка

PCB

printed circuit board

ASIC

application-specific integrated circuit

DMA

Direct Memory Access

MCU

microcontroller unit

SPI

Serial Peripheral Interface

MISO

Master In Slave Out

MOSI

Master Out Slave In

Ссылки

При наличии работающего SPI трансивера можно смело подключать к микроконтроллеру разнообразное периферийное оборудование: Flash память, джойстики, SD карты памяти, генераторы сигналов, акселерометры и прочее.

Текст

URL

SPI-NOR Flash на примере MX25R6435F

https://habr.com/ru/articles/731604/

Подключение PlayStation2 Джойстика к Микроконтроллеру (или Переходник между человеком и компьютером)

https://habr.com/ru/articles/959628/

Подключение SD карты по SPI (Капсула памяти)

https://habr.com/ru/articles/974076/

Пульт от «Dendy» в любительских конструкциях

https://habr.com/ru/articles/191936/

Обзор генератора сигналов AD9833

https://habr.com/ru/articles/733776/

Обзор учебно-тренировочной платы JZ-F407VET6 (или электронная парта)

https://habr.com/ru/articles/988494/

Обзор Акселерометра LIS3DH

https://habr.com/ru/articles/851180/

Serial Peripheral Interface

https://ru.wikipedia.org/wiki/Serial_Peripheral_Interface

Вопросы

1—На шине SPI 2 разных чипа. На оба подали CS-0 вольт и начали читать. Что произойдет: Сгорит/не сгорит/другое?

ссылка на оригинал статьи https://habr.com/ru/articles/1043452/