Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: f4 - SPI + DMA
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
diwil
Здравствуйте.
Я скрещиваю DMA с SPI1 следующим образом:
Код
    SPI1->CR2 = 0;
    SPI1->CR1 &= ~SPI_CR1_SPE;
    SPI1->CR1 |= SPI_CR1_LSBFIRST | SPI_CR1_DFF;
    SPI1->CRCPR = 10;    
    
    DMA2_Stream2->CR = 0x06022d1f - 1;
    DMA2_Stream2->NDTR = 0x800;
    DMA2_Stream2->M0AR = (uint32_t)spirx;
    DMA2_Stream2->PAR = 0x4001300c;
    
    DMA2_Stream3->CR = 0x06022d5f - 1;
    DMA2_Stream3->NDTR = 0x800;
    DMA2_Stream3->M0AR = (uint32_t)spitx;
    DMA2_Stream3->PAR = 0x4001300c;
    
    DMA2_Stream2->CR |=  DMA_SxCR_EN;
    DMA2_Stream3->CR |=  DMA_SxCR_EN;
    
    SPI1->CR2 |= SPI_CR2_RXDMAEN;
    SPI1->CR2 |= SPI_CR2_TXDMAEN;    
    SPI1->CR1 |= SPI_CR1_SPE;


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

Я тупо вызываю код выше еще раз, когда мастер хочет начать передачу (я этот момент тоже знаю).
Так вот с буфером от мастера (spirx) все хорошо, а spitx съезжает на 1 слово!

Я заметил, что после ресета регистр DMA2_Stream3->NDTR становится не 0x800, а 0x7ff после выполнения строки
SPI1->CR2 |= SPI_CR2_TXDMAEN

т.е. как я понимаю, DMA переписывает 1 слово из памяти в сдвиговый регистр SPI.

а вот если делать переинициализацию, то такого не происходит - т.е. после
SPI1->CR2 |= SPI_CR2_TXDMAEN
значение DMA2_Stream3->NDTR не изменяется.

Вопрос -
как мне переинициализировать DMA правильно?
Golikov A.
у DMA обычно еще есть фифо, потому вам надо дождаться того что оно пусто.
Алгоритм обычно запаузить ДМА, дождаться завершения работы и опустошения фифо, выключить ДМА. перенастроить включить ДМА.

Иногда ДМА неправильно реагирует на оставшийся взведенным бит в регистре приема SPI, нвдо после выключения ДМА вычитать бит из SPI, а потом включить ДМА обратно.

Процедура включения и выключения ДМА обычно описана в мануале на проц, вы не указали точно какой он у вас...
diwil
Цитата(Golikov A. @ Jul 23 2015, 15:34) *
у DMA обычно еще есть фифо, потому вам надо дождаться того что оно пусто.
Алгоритм обычно запаузить ДМА, дождаться завершения работы и опустошения фифо, выключить ДМА. перенастроить включить ДМА.

Иногда ДМА неправильно реагирует на оставшийся взведенным бит в регистре приема SPI, нвдо после выключения ДМА вычитать бит из SPI, а потом включить ДМА обратно.

Процедура включения и выключения ДМА обычно описана в мануале на проц, вы не указали точно какой он у вас, это что-то вроде LPC да?


stm32f405rgt6

все правильно делал, за исключение да, бит TXE должен быть взведен при переинициализации ДМА.
В этом проце, как я понимаю этого руками сделать нельзя.
Поэтому в слэйве все сложно оказалось. Сработало так:

когда мастер хочет завершить передачу, надо дождаться окончания передачи байта от слэйва к мастеру, остановить ДМА, убедиться, что SPI передал все (TXE == 1) и только потом просиьт мастера прекращать передачу.
Golikov A.
в LPC тоже были проблемы с выходным буфером
Пришлось мастеру дать предписание перед началом обмена вычитать пустой байт, чтобы буфер сбросился, и только потом запускать нормальный обмен с запуском ДМА.

Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.