ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Пятница
29 марта
767351
Sl (07.07.2017 19:38, просмотров: 8618)
Добрый день. stm32f746IG + IAR 8.11 + ST-link. Помогите разобраться с проблемой DMA2. Не получается запустить ADC1 -> DMA2. Уже несколько дней бьюсь. Не раз читал reference manual (RM0385), AN4031 (Application note Using the STM32F2, STM32F4 and STM32F7 Series DMA controller), Errata. Пытаюсь запустить самый простой вариант - преобразования 5-ми регулярных каналов. ADC1 -> DMA2_Stream_4_Channel0 -> U16Dma2DataADC1[]. Причем: - Все это раньше успешно делал для Stm32f107  - в stm32f746IG уже успешно работает связка DMA2 -> USART1 - после инициализации ADC1 и DMA2 удается успешно перебросить данные АЦП ТОЛЬКО ОДИН раз! Попытка еще раз запустить ADC1 -> DMA2 не “проходит”, пока не сброшу процессор. Т.е. я вижу, что преобразования в ADC1 завершились ADC1->SR.EOC = 1, но DMA2_Stream4 не “запустилось” DMA2_Stream4->CR.EN=1 и DMA2_Stream4->NDTR = 5 (не уменьшилось до нуля). Все прерывания запрещены. Между первым запуском и последующим запуском ADC1 -> DMA2 пауза 100 mks. Пытался размещать массив для ADC1 как в SRAM1, так и в SRAM2, так и в DTCM RAM. Результат одинаково неуспешный. Команда U16Dma2DataADC1[0]++; работает. Т.е. массив в расположен в SRAM. Перед повторным запуском флаги прерывания используемого потока сбрасываю с помощью DMA2->LIFCR и DMA2->HIFCR. В подпрограмме повторного запуска есть лишние “телодвижения”. Но это уже от безысходности . Конечно, тактирование ADC1 и DMA2 разрешено. Все входы ADC1,2,3 определены как аналоговые. Очень большое подозрение, что где то устанавливается или флаг ошибки или еще какое то запрещение работы DMA2. Но, я этого не вижу.  ADCCLK = PCLK2/4 = 27000000 volatile uint16_t U16Dma2DataADC1[16]; // ADC1. // *********************************************************************** Подпрограмма инициализации ADC1 для работы с DMA. void SInitContinueChannelDMA_ADC1(void) { // ADCPRE[1:0] = 1. ADCCLK = 108Mhz/4 = 27 Mhz. ADC->CCR = 0x00010000; // 12 bit. Enable Scan mode. ADC1->CR1 =((ADC_12bit<<ADCx_CR1_RES) | (ADC_CR1_SCAN * 1)); #define ADCx_CR2_DMA_init ((ADC_CR2_ALIGN * 0) | \ (ADC_CR2_EOCS * 0) | \ (ADC_CR2_DMA * 1) | \ (ADC_CR2_CONT * 0) | \ (ADC_CR2_ADON * 1)) ADC1->CR2 = ADCx_CR2_DMA_init; #define ADCx_SR_init 0x00000000 ADC1->SR = ADCx_SR_init; ADC1->SMPR1 = 0x00000000; ADC1->SMPR2 = 0x00000000; ADC1->HTR = 0x00000FFF; ADC1->LTR = 0x00000000; // Будет запущено 5 каналов. #define ADC1_SQR1_init ((5<<20) | 0x00000000) #define ADC1_SQR2_init 0x00000000 #define ADC1_SQR3_init ((0 <<25) | (Uin3 <<20) | (Uin2 <<15) | (Uin1 <<10) | (Iin2 <<5) | (Iin1 << 0)) ADC1->SQR1 = ADC1_SQR1_init; ADC1->SQR2 = ADC1_SQR2_init; ADC1->SQR3 = ADC1_SQR3_init; ADC1->JSQR = 0x00000000; ADC1->DR; // Empty read. ADC->CDR; // Empty read. } // *********************************************************************** Подпрограмма инициализации DMA для работы с ADC1. void SInitDMA2_f74x_75x(void) { // Сбрасываю все флаги прерываний всех потоков. #define DMA_LIFCR_all_clear (uint32_t)(0x0F7D0F7D) // DMA all interrupt flags clear. DMA2->LIFCR = DMA_LIFCR_all_clear; #define DMA_HIFCR_all_clear (uint32_t)(0x0F7D0F7D) // DMA all interrupt flags clear. DMA2->HIFCR = DMA_HIFCR_all_clear; ADC1->CR2 |= ADC_CR2_DMA; // Запрещаю работу DMA2_Stream4. LSStream4Disable: DMA2_Stream4->CR &= ~DMA_SxCR_EN; if((DMA2_Stream4->CR & DMA_SxCR_EN) != 0) goto LSStream4Disable; // Адрес источника. DMA2_Stream4->PAR = (uint32_t)&ADC1->DR; // 0x4001.2000 + 0x004C. // Адрес первого элемента массива. DMA2_Stream4->M0AR = (uint32_t)&U16Dma2DataADC1[0x00]; // Количество пересылаемых 16битных значений. DMA2_Stream4->NDTR = 5; // 0 - Chanel. - (0<<DMA_SxCR_Chanel) // memory single transfer. - (DMASingleTransfer<<DMA_SxCR_MBurstConfig) // peripheral single transfer. - (DMASingleTransfer<<DMA_SxCR_PBurstConfig) // запрещаем работу с двойным буффером - (DMA_SxCR_DBM * 0) // Высокий приоритет - DMAHighPrioritet. // Периферийный адрес НЕ увеличивается исходя из записанного в PSIZE - PINCOS=0. // Память передает 16-bits(DMA_Data16 << DMA_SxCR_MemSize), а периферия принимает 16-bits(DMA_Data16 << DMA_SxCR_PerphSize). // Адрес памяти увиличивается (DMA_SxCR_MINC*1), а адрес периферии не увеличивается (DMA_SxCR_PINC*0). // Circular mode disabled. (DMA_SxCR_CIRC*0). // Peripheral-to-Memory. (DMA_Peripheral_memory << DMA_SxCR__DIR). // Peripheral flow controller no use. (DMA_SxCR_PFCTRL*0). // DMA Transfer complete interrupt enable. (DMA_SxCR_TCIE*1). #define DMA2_Stream4_CR_DMA_ADC1_init ((0<<DMA_SxCR_Chanel) | \ (DMASingleTransfer<<DMA_SxCR_MBurstConfig) | \ (DMASingleTransfer<<DMA_SxCR_PBurstConfig) | \ (DMA_SxCR_DBM * 0) | \ (DMAHighPrioritet << DMA_SxCR_Prioritet) | \ (DMA_SxCR_PINCOS * 0) | \ (DMA_Data16 << DMA_SxCR_MemSize) | (DMA_Data16 << DMA_SxCR_PerphSize) | \ (DMA_SxCR_MINC*1) | (DMA_SxCR_PINC*0) | \ (DMA_SxCR_CIRC*0) | \ (DMA_Peripheral_memory << DMA_SxCR__DIR) | \ (DMA_SxCR_PFCTRL*0) | \ (DMA_SxCR_TCIE*1)) DMA2_Stream4->CR = DMA2_Stream4_CR_DMA_ADC1_init; // Direct mode enabled. DMA2_Stream4->FCR &= ~ ((uint32_t)(DMA_SxFCR_DMDIS)); } // *********************************************************************** Подпрограмма первого старта ADC1 -> DMA2_Stream_4_Channel0 -> U16Dma2DataADC1[]. void SStartDMA_ADC1(void) { DMA2_Stream4->CR |= DMA_SxCR_EN; ADC1->SR &= ~ADC_SR_STRT; // 0x00000010. Clear Regular channel Start flag. ADC1->CR2 |= ADC_CR2_SWSTART; //0x40000000. Start Conversion of regular channels. } // *********************************************************************** Подпрограмма второго и последующих стартов ADC1 -> DMA2_Stream_4_Channel0 -> U16Dma2DataADC1[]. void SReStartDMA_ADC1(void) { LSReStream4Disable: DMA2_Stream4->CR &= ~DMA_SxCR_EN; if((DMA2_Stream4->CR & DMA_SxCR_EN) != 0) goto LSReStream4Disable; register uint32_t RegPRIMASKGFAB124_tmp; RegPRIMASKGFAB124_tmp = __get_PRIMASK(); __disable_irq(); // сбрасываю перед повторным запуском все флаги прерывания для используемого потока. DMA2->HIFCR = DMA_HIFCR_AllStream4_clear; // 0x0000003D. // Адрес источника. DMA2_Stream4->PAR = (uint32_t)&ADC1->DR; // 0x4001.2000 + 0x004C. // Адрес первого элемента массива. DMA2_Stream4->M0AR = (uint32_t)&U16Dma2DataADC1[0x00]; // Количество пересылаемых 16битных значений. DMA2_Stream4->NDTR = 5; DMA2_Stream4->CR |= DMA_SxCR_EN; ADC1->DR; // Empty read. ADC->CDR; // Empty read. ADC1->SR &= ~ADC_SR_STRT; // 0x00000010. Clear Regular channel Start flag. ADC1->CR2 |= ADC_CR2_SWSTART; //0x40000000. Start Conversion of regular channels. __set_PRIMASK(RegPRIMASKGFAB124_tmp); } // ***********************************************************************