Содержание

Порядок инициализации пинов и периферии

При инициализации периферии и пинов для нее необходимо выбрать порядок, в котором происходит эта инициализация. В общем случае, логично сначала настроить блок периферии и уже затем подключить к этой периферии выводы GPIO. Таким образом, переключая пины из третьего состояния (состояния после сброса) в необходимую функцию, пины подключаются к уже настроенному источнику сигнала. Это могут быть выводы TX какого-либо блока либо RX выводы, либо что-то еще.

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

Необходимо также учесть, что режим IN/OUT в котором будет работать пин, задается самим периферийным блоком. Поэтому при настройке пина в функцию к периферийному блоку нет необходимости настраивать пин как ВЫХОД (OUT) в регистре OE. Т.е. если пин настраивается:

Исключение для RX блоков UART и SSP

Описанная выше последовательность инициализации логична и безопасна, но иногда приводит к артефактам в работе периферийных блоков. Так, при настройке UART обнаружилось, что когда UART уже настроен и происходит подключение сигналов блока UART на выводы GPIO, то UART вдруг принимает слово и его буфер FIFO_RX уже не пуст. Более того, при приеме слова выставляется запрос к каналу DMA, который вычитывает FIFO_RX. Для FIFO_RX ситуация поправима и можно вычитать буфер перед началом работы, но запрос к каналу DMA сбросить нельзя. Т.е. если канал DMA будет включен, то он сразу выполнит копирование из FIFO_RX, хотя сам FIFO_RX к тому времени уже может быть вычитан.

Происходит это потому, что для блока контроллера UART достаточно принять стартовый бит "0" на линии RX, чтобы решить, что это передача. Блок начнет сэмплировать линию и, в итоге, запишет в FIFO_RX слово, пусть, может быть, и с ошибкой в паритете. Блок UART может поймать ложный стартовый бит при переключении пина из 3-го состояния к уже настроенному блоку UART в момент задания регистра FUNC. Замечено так-же, что фиксация стартового бита происходит, когда UART настроен на достаточно большую скорость обмена. Например при скорости 115200 ложного срабатывания не происходит, а при 256000 уже наблюдается. Это говорит о том, что длительность ложного стартового бита должна быть соразмерена заданной скорости обмена по UART.

Чтобы этого избежать, необходимо сначала настроить пин в функцию UART_RX. При этом блок UART еще не настроен и состояние пина будет неопределенным. Но зато наличие броска в 0, при переключении регистра FUNC не будет воспринято за стартовый бит, поскольку блок UART еще не включен.

Поведение с реакцией на ложный стартовый бит было обнаружено в микроконтроллерах 1986ВЕ8, 1923ВК014, Электросила. В прочих микроконтроллерах, инициализация пинов при включенном блоке UART отрабатывает без ложного старта. Вероятно, это связано с различием в схеме падов (драйверов пинов) - для указанных МК настройки задаются через регистры CLR и SET.

Сдвиг бит при обмене по SPI

В случае, когда SSP является ведомым, а сигнал FSS на схеме подключен на землю, возможно повторение поведения аналогично изложенному для UART. Активный сигнал FSS активирует работу ведомого, поэтому возникновение помехи (иголки) на линии CLK может быть воспринято ведомым как сигнал CLK от мастера. Соответственно, ведомый тут же выдвигает свой первый бит. Но когда мастер начнет обмен, то выдаст, например, все 8 тактов CLK для обмена первым байтом. Ведомый один бит уже выдал, поэтому выдаст 7 бит от первого байта, и на 8-й такт от мастера выдвинет первый бит от второго байта. В итоге мастер будет постоянно получать данные, сдвинутые на 1 бит.

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

Вместо помехи на CLK может проявляться неправильная последовательность инициализации. Например SPI включился, а на линии CLK еще "0", т.к. мастер еще не включен и не вывел линию в "1" - для случая SPO=SPH=1. При этом ведомый решит, что начат обмен и выдаст первый бит.

В итоге, если наблюдается обмен со сдвигом бит, то необходимо задуматься почему ведомый ловит старт и что необходимо исправить, чтобы этого не происходило. Использование сигнала FSS в данном случае делает обмен более помехозащищенным. Даже если первое слово и будет выдано со сдвигом по какой-то причине, то последующие слова обязательно будут синхронны с FSS.