реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> STM32F4 ACD->DMA->USART, Как правильно настроить DMA?
Haamu
сообщение Dec 20 2013, 10:31
Сообщение #1


Частый гость
**

Группа: Участник
Сообщений: 90
Регистрация: 12-12-13
Пользователь №: 79 587



Ситуация такая... Оцифровываю несколько датчиков и через DMA сохраняю их показания в памяти. После записи энного количества показаний хочу передать их опять же через DMA по USART на компьютер, для дальнейшей обработки. Первую половину цепочки настроил, данный записываются в память. А вот передать их не получается. Подозреваю, что проблема где-то в настройках DMA.
Вот так я настраиваю DMA на передачу данных:
Код
    DMA_InitTypeDef DMA_InitStruct;
    DMA_InitStruct.DMA_Channel = DMA_Channel_4;
    DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)&(USART1->DR);
    DMA_InitStruct.DMA_Memory0BaseAddr = (uint32_t)&sensors_data;
    DMA_InitStruct.DMA_DIR = DMA_DIR_MemoryToPeripheral;
    DMA_InitStruct.DMA_BufferSize = 30000;    //Size of data in uint32_t sencors_data[]
    DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;
    DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
    DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
    DMA_InitStruct.DMA_Mode = DMA_Mode_Normal;
    DMA_InitStruct.DMA_Priority = DMA_Priority_High;
    DMA_InitStruct.DMA_FIFOMode = DMA_FIFOMode_Enable;
    DMA_InitStruct.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
    DMA_InitStruct.DMA_MemoryBurst = DMA_MemoryBurst_Single;
    DMA_InitStruct.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
    DMA_Init(DMA2_Stream7, &DMA_InitStruct);
    USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE);
    USART_Cmd(USART1, ENABLE);


Сомневаюсь в парвильности этих параметров:
Код
DMA_InitStruct.DMA_BufferSize = 30000;
DMA_InitStruct.DMA_Mode = DMA_Mode_Normal;
DMA_InitStruct.DMA_FIFOMode = DMA_FIFOMode_Enable;
DMA_InitStruct.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
DMA_InitStruct.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStruct.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;

Если у меня передаваемый массив состоит из 30000 16-битных значений, а передаю я его по одному байту, правильно ли я указал размер буфера?
Я так понимаю, что при передаче HalfWord -> Byte без FIFO не обойтись. На что влияет его размер (FIFOThreshold)?
Как правильно выбрать DMA_Mode? Что значат режим Circular и режим Normal?
И что такое MemoryBurst и PeripheralBurst?

И еще один момент. Как я понимаю, после команды
Код
DMA_Cmd(DMA2_Stream7, ENABLE);

DMA сразу начинает передачу. Это так?
В дебагере заметил, что при запуске этой команды в регистре DMA_S7CR устанавливается бит EN, но на следуещем же такте он сбрасывается. Почему?
Go to the top of the page
 
+Quote Post
Falkon_99
сообщение Dec 20 2013, 13:12
Сообщение #2


Частый гость
**

Группа: Участник
Сообщений: 169
Регистрация: 26-03-12
Из: Харьков
Пользователь №: 71 010



прочитайте тут, большинство вопросов отсеится

Сообщение отредактировал Falkon_99 - Dec 20 2013, 13:13
Go to the top of the page
 
+Quote Post
Haamu
сообщение Dec 20 2013, 17:00
Сообщение #3


Частый гость
**

Группа: Участник
Сообщений: 90
Регистрация: 12-12-13
Пользователь №: 79 587



Цитата(Falkon_99 @ Dec 20 2013, 17:12) *
прочитайте тут, большинство вопросов отсеится

В том то и дело, что уже читал, но осталось непонимание. Хороший сайт, спасибо автору. Но в этой статье, как и в большинстве других есть указания, что и как настраивается, но не объясняется почему именно так.

Кстати, по поводу моего кода. Когда проверил работу уже на железе, а не в дебагере, оказалось что всё работает. Видимо как-то не туда смотрел в дебагере. Единственный момент, который следует исправить - это размер буфера. Так как я отправляю 30000 HalfWord'ов по одному байту, то таких байт, а соответсвенно и запросов к DMA должно быть в два раза больше.

Сообщение отредактировал Haamu - Dec 20 2013, 17:03
Go to the top of the page
 
+Quote Post
Haamu
сообщение Dec 21 2013, 12:15
Сообщение #4


Частый гость
**

Группа: Участник
Сообщений: 90
Регистрация: 12-12-13
Пользователь №: 79 587



И все-же...
Код
DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStruct.DMA_FIFOMode = DMA_FIFOMode_Enable;
DMA_InitStruct.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
DMA_InitStruct.DMA_MemoryBurst = ???????
DMA_InitStruct.DMA_PeripheralBurst = ???????

Какими доолжны быть последние два параметра при таких вот настройках DMA? Есть кто-нибудь, кто разобрался в параметрах Burst?
Go to the top of the page
 
+Quote Post
HardEgor
сообщение Dec 21 2013, 16:09
Сообщение #5


Гуру
******

Группа: Свой
Сообщений: 2 223
Регистрация: 3-03-06
Из: Tomsk
Пользователь №: 14 925



Цитата(Haamu @ Dec 21 2013, 19:15) *
DMA_InitStruct.DMA_MemoryBurst = ???????
DMA_InitStruct.DMA_PeripheralBurst = ???????[/code]
Какими доолжны быть последние два параметра при таких вот настройках DMA? Есть кто-нибудь, кто разобрался в параметрах Burst?

Эхх... кто-бы знал, у меня для STM32F105 в настройках таких параметрок к сожалению нет.
Вы бы уж написали какой конкретно процессор используете.
Go to the top of the page
 
+Quote Post
esaulenka
сообщение Dec 21 2013, 22:19
Сообщение #6


Профессионал
*****

Группа: Свой
Сообщений: 1 032
Регистрация: 13-03-08
Из: Маськва
Пользователь №: 35 877



Burst mode - режим, когда за раз передаётся сразу несколько байт (или не байт, смотря на какую "ширину" настроено DMA). В данном случае он не нужен.

А контроллер указан в заголовке темы (не полностью, но для понимания вопроса достаточно ;-) )


--------------------
Тут обсуждается творческий порыв, а не соответствие каким-либо стандартам ©
Go to the top of the page
 
+Quote Post
Haamu
сообщение Dec 23 2013, 05:10
Сообщение #7


Частый гость
**

Группа: Участник
Сообщений: 90
Регистрация: 12-12-13
Пользователь №: 79 587



У меня STM32F407VG. На сколько я понял в STM32F10x в контроллере DMA вообще FIFO буфера нет, поэтому и Burst режима тоже нет. Хотя, как же тогда передаются данные разного размера (в памяте и в периферии)?..

Цитата(esaulenka @ Dec 22 2013, 02:19) *
Burst mode - режим, когда за раз передаётся сразу несколько байт (или не байт, смотря на какую "ширину" настроено DMA). В данном случае он не нужен.

Вас не затруднит пояснить, в каких случаях он нужен и как им пользоваться?
Правильно я понял, что для разных размеров данных в памяти и периферии без FIFO не обойтись?

Я решил проблемму в лоб, без использования FIFO. Просто указал, что в памяти массив состоит из байтов и отключил FIFO. Передаю по одному байту, а наверху уже собираю в полуслова. Но ведь так поидее не правильно...
Еще сбивает с толку, что при отладке в CoIDE сразу посли запуска DMA появляется флаг FIFO error. При том, если не ошибаюсь, и при отключенном FIFO он выскакивает. Не пойму, это глюк в настройках DMA или в CoIDE...
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Dec 23 2013, 05:33
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



На сколько я сейчас бегло глянул fifo используется если оба устройства находятся на одной шине AHB. То есть скорее всего для быстрых устройств, чтобы разгрузить шину и не затормаживать процессор. Использовать может та периферия, которая поддерживает такой обмен данными.
DMA - это не совсем процессор, поэтому вы вряд ли корректно увидите отладчиком что-то. Да и зачем?
Какая-то тенденция нехорошая, чуть ли не по шагам рассмотреть деятельность процессора. Одно время ряд спецов говорило, что вообще надо отказаться от отладчика. Я тогда не понимал зачем. Теперь вижу.
Смотрите отладчиком только ключевые моменты. Правильность передачи буфера, к примеру. Например остановится по прерыванию, завершения передачи DMA и проверить правильность выполнения. Иначе зароетесь, и толком ничего не увидите, а будет только сумбур в голове, ИМХО.
Go to the top of the page
 
+Quote Post
Haamu
сообщение Dec 23 2013, 06:19
Сообщение #9


Частый гость
**

Группа: Участник
Сообщений: 90
Регистрация: 12-12-13
Пользователь №: 79 587



Цитата(SasaVitebsk @ Dec 23 2013, 09:33) *
Какая-то тенденция нехорошая, чуть ли не по шагам рассмотреть деятельность процессора. Одно время ряд спецов говорило, что вообще надо отказаться от отладчика. Я тогда не понимал зачем. Теперь вижу.
Смотрите отладчиком только ключевые моменты. Правильность передачи буфера, к примеру. Например остановится по прерыванию, завершения передачи DMA и проверить правильность выполнения. Иначе зароетесь, и толком ничего не увидите, а будет только сумбур в голове, ИМХО.


Может Вы и правы на счет того, что не стоит каждый шаг отслеживать. Я так пол дня убил на эксперименты с настройками ДМА и отслеживанием его работы в отладчике, пока на проверел на железе, оказалось все работает прекрасно. Так же было, когда с USART разбирался. Всё не мог понять, почему у меня регистр данных пустой, пока не увидел, что на самом деле всё работает.
Я до STM32 c отладчиками не работал. AVRки в симуляторе гонял. Видимо в том и отличие отладчика от симулятора в том, что в симуляторе всё пошагово выполняется, а в отладчике только программа останавливается, а периферия, которая на автомате работает, продолжает выполнять свои действия.
Go to the top of the page
 
+Quote Post
HardEgor
сообщение Dec 27 2013, 04:13
Сообщение #10


Гуру
******

Группа: Свой
Сообщений: 2 223
Регистрация: 3-03-06
Из: Tomsk
Пользователь №: 14 925



Да, читайте Reference Manual - в DMA burst нужен для того, кто имеет у буфера FIFO: "Supports incremental burst transfers of 4, 8 or 16 beats. The size of the burst is
software-configurable, usually equal to half the FIFO size of the peripheral"

Т.е. например USART передает информацию побайтово, если нет FIFO, то DMA кладёт в буфер USART за каждую операцию только 1 байт, потом ждет окончания его передачи, кладёт следующий байт и т.д. Когда у буфера USART есть FIFO - тогда, DMA за одну операцию может сложить туда сразу несколько байт(в половину буфера), что разгружает шину.

FIFO error - это или неправильная настройка DMA или ошибки в работе DMA, почитай Reference Manual там описано когда она возникает.

Цитата(Haamu @ Dec 23 2013, 12:10) *
Правильно я понял, что для разных размеров данных в памяти и периферии без FIFO не обойтись?

Нет, DMA без разницы какой размер данных лежит в памяти, он просто читает указанное количество байт(DMA_InitStruct.DMA_Memory0BaseAddr) начиная с указанного адреса(DMA_InitStruct.DMA_Memory0BaseAddr) из памяти и передает их в буфер приемника, или наоборот.
Количество передаваемых байт в каждом чтении должны совпадать с размером буфера приемника! Но если буфер приемника имеет FIFO, тогда они могут не совпадать:
"Independent source and destination transfer width (byte, half-word, word): when the data widths of the source and destination are not equal, the DMA automatically packs/unpacks the necessary transfers to optimize the bandwidth. This feature is only available in FIFO mode"

Цитата(Haamu @ Dec 23 2013, 12:10) *
Я решил проблемму в лоб, без использования FIFO. Просто указал, что в памяти массив состоит из байтов и отключил FIFO. Передаю по одному байту, а наверху уже собираю в полуслова. Но ведь так поидее не правильно...

А так все и делают, ведь USART передает данные побайтово.
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 25th July 2025 - 02:56
Рейтинг@Mail.ru


Страница сгенерированна за 0.02029 секунд с 7
ELECTRONIX ©2004-2016