Где DMA хранит значения АЦП в STM32?

Я включил передачу периферийных устройств DMA в память для ADC1 в CubeMX и сгенерировал код. Однако я не понимаю, куда будут записываться данные из АЦП? Должен ли я явно определять переменную для хранения этих данных? Как я могу получить данные в ISR канала 1 DMA?


person sixter    schedule 08.03.2019    source источник
comment
Чтобы настроить DMA, вы должны указать ему адрес и эффективный (с точки зрения размера слова и количества слов) размер буфера памяти, надеюсь, в допустимом месте в ОЗУ. Данные попадут туда. Только у вас есть код, поэтому только вы знаете, где он находится.   -  person Chris Stratton    schedule 08.03.2019
comment
DMA обозначает прямой адрес памяти. Это означает, что АЦП будет писать прямо в адрес памяти, который вы ему предоставили. Итак, сначала uint16_t adcvalues[10];, затем настройте DMA для записи 10 значений в указатель adcvalues, дождитесь завершения, затем вы читаете значения только из adcvalues.   -  person KamilCuk    schedule 08.03.2019
comment
Примечание. Буферы DMA должны всегда объявляться как volatile, иначе вы можете получить всевозможные странные ошибки оптимизации. Вы также должны учитывать возможность повторного входа между оборудованием DMA и вашим приложением.   -  person Lundin    schedule 08.03.2019


Ответы (4)


DMA не управляет памятью и не выбирает действительный адрес для установки данных. Вообще говоря, DMA позволяет передавать данные без использования ЦП, но не более того.


Микроконтроллеры STM32 обеспечивают передачу от:

  • память в память
  • память на периферийное устройство
  • периферийное устройство в память

Во всех из них разработчики должны знать о своей цели, чтобы настроить (помимо DMA) места источника и назначения, такие как адрес периферийных устройств, резервная память (и какой тип памяти) и т. Д.


В вашем конкретном случае (отметьте RM, AN, docs и т. Д. периферийное устройство в память) переносятся:

  • Источник: периферийное устройство АЦП, разработчик должен знать, где находится периферийное устройство АЦП, и настроить (помимо АЦП) DMA на основе параметров АЦП в качестве источника информации.
  • Назначение: память, разработчик должен зарезервировать кучу памяти (куча / стек / глобальная / и т. Д.) И настроить DMA в соответствии с уже выделенным пространством памяти. При этом DMA позволит вам устанавливать значения по-разному (в зависимости от устройства), например, непрерывный кольцевой буфер, один цикл, буфер для пинг-понга (stm32 использует термин «двойной кольцевой буфер») и т. Д.
  • Конфигурация DMA и ADC: существует огромное количество факторов, которые для простоты я не буду включать, обычно упрощенные производителем HAL (использовать его вам).
person Jose    schedule 08.03.2019
comment
Хотя выполнение DMA по адресу в стеке не принципиально невозможно сделать правильно, выполнение этого в любом месте ниже, скажем, main () - потенциально плохая идея, так как вы должны быть уверены, что код не вернется, аннулируя этот кадр стека перед прямой доступ к памяти сделан. - person Chris Stratton; 08.03.2019
comment
Хотя я согласен с комментарием Лундина относительно изменчивости, я не согласен с этим, когда существуют ограничения или ограниченные ресурсы. Зарезервировать кучу ОЗУ только для DMA не всегда возможно, хотя, правда, это должен быть первый вариант. - person Jose; 11.03.2019

Вы указываете драйверу HAL DMA ADC, куда поместить образцы данных при запуске преобразования:

volatile uint32_t adcBuffer[SAMPLE_COUNT]; 
HAL_ADC_Start_DMA( &hadc, 
                   adcBuffer, 
                   SAMPLE_COUNT ); 

Обратите внимание, что некоторые части STM32 имеют SRAM, разделенную на несколько шин, причем одна секция намного меньше, чем другие. Резервирование этого раздела для буферов DMA дает преимущества в производительности, так как это снижает конкуренцию на шине с помощью обычных программных выборок данных. Таким образом, вы можете настроить свой сценарий компоновщика для создания разделов и явного размещения буферов DMA в одном, исключая размещение в них данных приложения.

person Clifford    schedule 08.03.2019

Если вы посмотрите документы и примеры HAL, вы найдете пример того, как использовать ADC с DMA.

Суммируя :

Чтобы начать преобразование, вы используете функцию:

HAL_StatusTypeDef HAL_ADC_Start_DMA(ADC_HandleTypeDef* hadc, uint32_t* pData, uint32_t Length);

Где pData - ваша переменная / массив, куда DMA должен поместить данные.

person theSealion    schedule 08.03.2019

DMA и uC ничего не знают о переменных. Периферийное устройство DMA имеет два регистра конфигурации, в которых вы храните периферийный адрес и адрес памяти. Если вы начнете с чтения документации uC вместо HAL, все сразу станет ясно

person 0___________    schedule 08.03.2019