|
DAC + DMA в STM32F2xx |
|
|
|
Feb 22 2012, 07:58
|
Знающий
   
Группа: Участник
Сообщений: 998
Регистрация: 27-08-08
Пользователь №: 39 850

|
Цитата(scifi @ Feb 22 2012, 11:44)  Что-то не сходится: 120000 Гц * 16 бит = 1.92 Мбит/с. У меня гонял данные с частотой 20 МГц из буфера в памяти на GPIO (внешний DAC). Если умножить на 16 бит, то это 320 Мбит/с. Виноват. Еще * на 48 каналов - 120 000*16*48 = 92.16 Мбит/сек Надеюсь stm32 справится. Цитата Вот с DMA: Спасибо. Попробую.
Сообщение отредактировал Acvarif - Feb 22 2012, 08:02
|
|
|
|
|
Feb 22 2012, 08:39
|
Знающий
   
Группа: Участник
Сообщений: 998
Регистрация: 27-08-08
Пользователь №: 39 850

|
Цитата(scifi @ Feb 22 2012, 12:34)  Я думаю, собрать данные удастся. А вот прокачать 92 Мбит/с на ПК - нетривиальная задача. Даже не всякий ПК справится. Внутренней памяти МК хватает на буферизацию всего нескольких миллисекунд. Я думаю, не всякий сетевой стек потянят: нужно будет оптимизировать под задачу. Возможно, следует сразу отказаться от TCP и делать на UDP. Ну конечно UDP. Уже проверялось UDP + LwIP. Вроде тянет 95. Буду пытаться сделать качели - пока первая половина буфера заполняется, другая передается. DMA вроде так позволяет (прерывания по заполнению пол.. всего буфера).
|
|
|
|
|
Mar 4 2012, 11:33
|
Участник

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

|
Цитата(scifi @ Feb 22 2012, 11:23)  Конечно заработает. И не такое работало. Предвидя дальнейшие вопросы, даю подсказку: таймеры могут формировать запросы DMA по событию Capture, которое может вызываться фронтом на входе таймера. И вообще таймеры в STM32 весьма мощные и позволяют творить чудеса. При условии, что не запутаетесь и правильно их запрограммируете.
Вопрос не имеет смысла и вскрывает глубинное непонимание принципа работы DMA. Номер стрима определяет выбор источников сигнала запроса DMA. Он не определяет адрес источника и приёмника данных. Добрый день всем! Мучаюсь с обратной задачей. Из памяти вывести поток данных на параллельный порт с помощью DMA. Конструкция TIM6 + DMA1 Stream1 Channel7 формирует Event. DMA начинает выводить полуслово в порт E ( GPIOE_ODR) после первой же попытки (видно, что DMA_S1NDTR декрементировался) все заканчивается с флагом Stream 1 transfer error interrupt. Прямой вывод данных в GPIOE_ODR из тела программы при этом дает отличный результат! В чем грабли?
|
|
|
|
|
Mar 4 2012, 13:31
|
Участник

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

|
Цитата(Sekat @ Mar 4 2012, 15:33)  В чем грабли? Подробности к проблеме из предыдущего поста. 1. Процессор - STM32F407 . 2. Инициализация GPIO для вывода в порт Е: Код RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE); GPIO_InitStructure.GPIO_Pin = 0xffff; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOE, &GPIO_InitStructure); 3. Инициализация таймера TIM6: Код TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure); TIM_TimeBaseStructure.TIM_Period = 0x200; TIM_TimeBaseStructure.TIM_Prescaler = 0; TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM6, &TIM_TimeBaseStructure);
TIM_Cmd(TIM6, ENABLE); 3. Инициализация DMA: Код RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1 , ENABLE); DMA_DeInit(DMA1_Stream1); DMA_InitTypeDef DMA_InitStructure; DMA_InitStructure.DMA_Channel = DMA_Channel_7; DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t) GPIOE_ODR; DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&Sine12bit; DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral; DMA_InitStructure.DMA_BufferSize = 32; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; DMA_InitStructure.DMA_Priority = DMA_Priority_High; DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull; DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; DMA_Init(DMA1_Stream1, &DMA_InitStructure); DMA_Cmd(DMA1_Stream1, ENABLE); TIM_DMACmd(TIM6, TIM_DMA_Update, ENABLE); Этот код слегка переделанный пример от IAR вывода во внутренний DAC. 4. Что удивительно. Если подставить вместо GPIOE_ODR например адрес встроенного DAC, то DMA начинает пересылать данные без ошибки. 5. Что примечательно. Если реверсировать передачу данных (поменять направление - от порта в память, естественно память разместить в RAM), результат тот же - ошибка передачи DMA! Пункты 4 и 5 внушают пессимизм. Неужели обращение DMA к параллельному порту в STM32F посредством DMA невозможно? Надеюсь все же, что это мои грабли
Сообщение отредактировал Sekat - Mar 4 2012, 13:34
|
|
|
|
|
Mar 6 2012, 06:15
|
Участник

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

|
Цитата(Sekat @ Mar 4 2012, 17:31)  4. Что удивительно. Если подставить вместо GPIOE_ODR например адрес встроенного DAC, то DMA начинает пересылать данные без ошибки. 5. Что примечательно. Если реверсировать передачу данных (поменять направление - от порта в память, естественно память разместить в RAM), результат тот же - ошибка передачи DMA!
Пункты 4 и 5 внушают пессимизм. Неужели обращение DMA к параллельному порту в STM32F посредством DMA невозможно?
Надеюсь все же, что это мои грабли Пока нет обсуждения, продолжаю излагать хронологию борьбы с проблемой. По пунктам 4,5 выяснилось, что в этой ситуации вся периферия с адресами < 0x40010000 работает без ошибок, в частности и встроенный DAC. Ага, подумал я. И поменял DMA2 на DMA1, таймер6 на таймер8. Заработало с GPIO. Сколько не искал ссылок на эти ограничения в "RM0090 Reference manual" так и не смог найти. Видимо плохо искал, что не мудрено - легко заблудиться в почти полутора тысячах страниц. Как бы то ни было - теперь работает с параллельным выводом в GPIO. Однако борюсь со следующей проблемой; - ко всей этой конструкции хочу прикрутить FIFO с Burst. Возможно ли в принципе учинить такое для параллельного порта? Пока что картина следующая. Фифо с берстом работают исправно по таймеру, пересылая заданную пачку байтов. Однако в параллельный порт эта вся пачка пересылается очень быстро - похоже, что с максимально возможной скоростью шины, а вовсе не по EVENT таймера. Хотелось бы, что бы данные пересылались в параллельный порт по EVENTу, а буфер фифо обновлялся бы берстом по мере необходимости. Как такое сделать???
|
|
|
|
|
Mar 6 2012, 12:03
|
Участник

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

|
Цитата(Flexz @ Mar 6 2012, 10:28)  По неработающей периферии - посмотрите раздел "2.1 System architecture". У DMA1 не упоминается периферийная шина и на схеме он не соединен с AHB-периферией, вероятно, причина в этом.
А фифо как настраиваете? там же отдельно есть настроки Memory burst и Peripheral burst. Да, действительно, согласно этому разделу DMA2 peripheral bus есть, а такой же для DMA1 нет. Однако, заработало то у меня именно с DMA1. К тому же DMA2 замечательно работает с адресами меньше 0x40010000 - есть пример от IAR с DAC. Не проверял работу DMA1 с адресами <0x40010000, но не удивлюсь, если окажется, что не работает. Такое своеобразное разделение между двумя DMA по адресному пространству. Однако обнаружить эти особенности в каких-либо руководствах не удалось. Настройки фифо и бёрст достаточно тривиальны, здесь сложно сильно ошибиться: Код DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable; DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full; DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_INC8; DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_INC8; Настораживает то, что GPIO нет специальных настроек разрешения работы с DMA, как например есть у другой периферии.
Сообщение отредактировал Sekat - Mar 6 2012, 12:05
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|