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

 
 
> stm32f030. некорректно работает DMA в sleep mode (решено)
jeka
сообщение Apr 12 2017, 19:07
Сообщение #1


Administrator
***

Группа: Свой
Сообщений: 400
Регистрация: 10-05-04
Пользователь №: 1



Несколько раундов борьбы с косяком, пока безуспешно. Суть следующая:
Оцифровываю данные так: АЦП -> DMA -> прерывание half transfer и full transfer.
Если процессор всегда в активном режиме, все работает прекрасно.
Но как только в холостой основной цикл добавляю остановку процессора (WFI), то начинает твориться следующее:

DMA генерирует прерывания как положено, с той же частотой и вовремя, т.е. как и без WFI. Но как только активирую WFI, то в RAM, куда DMA должна сохранять результат оцифровки, данные не записываются.
Точнее, экспериментально определено, что в буфере DMA обновляется только та часть данных, которая оцифровалась в моменты времени, когда процессор был в активном режиме (т.е. вертелся в обработчиках прерываний). Определил это добавлением холостого цикла в конце обработчика прерываний. И от величины задержки зависит, какие значения запишутся в RAM.
При этом все счетчики контроллера DMA работают корректно, что в sleep mode, что без него, т.е. нужный канал АЦП записывается всегда по нужному адресу. Счетчики DMA считывал в обработчике DMA, и делаю вывод что прерывания DMA вызываются вовремя (без задержек).

Вероятно, я что-то упустил в настройках или еще где, но по работе DMA в sleep mode ничего интересного не нашел. В errata также ничего полезного нет.
Слабо верится что такой косяк до ST до сих пор не дошел.


Куски кода:
CODE
ADC1->CFGR1=ADC_CFGR1_AWDSGL|ADC_CFGR1_CONT|ADC_CFGR1_DMACFG|ADC_CFGR1_DMAEN;
ADC1->CFGR2=ADC_CFGR2_CKMODE_0;

ADC1->CHSELR=0x02FF|ADC_CHSELR_CHSEL16;
ADC1->SMPR=6;// скоростью оцифровки также игрался
ADC->CCR|=ADC_CCR_TSEN;

// ADC DMA
DMA1_Channel1->CCR&=~DMA_CCR_EN;
DMA1_Channel1->CCR=DMA_CCR_PL_0*3 | DMA_CCR_MSIZE_0 | DMA_CCR_PSIZE_0 | DMA_CCR_MINC | DMA_CCR_CIRC | DMA_CCR_HTIE | DMA_CCR_TCIE | DMA_CCR_TEIE;
DMA1_Channel1->CNDTR=20;
DMA1_Channel1->CPAR=(uint32_t)&(ADC1->DR);
DMA1_Channel1->CMAR=(uint32_t)&adcbuf;
DMA1_Channel1->CCR|=DMA_CCR_EN;

...

ADC1->CR=ADC_CR_ADSTART;


---------------- Основной цикл:
...
__enable_irq();

while (1) {
__WFI();// WFI cause DMA fill error in ADC bufer
};

------------------ И обработчик:

// Для фиксации позиции буфера DMA при обработке.
volatile int bp1, bp2;
volatile int bp1a, bp2a;

__irq void DMA1_Channel1_IRQHandler() {
int di=DMA1->ISR;

if (di & DMA_ISR_TEIF1) {
DMA1->IFCR=DMA_IFCR_CTEIF1;
}

if (di & DMA_ISR_HTIF1) {// нечетный вызов (первая половина буфера готова)
bp1=DMA1_Channel1->CNDTR;
DMA1->IFCR=DMA_IFCR_CHTIF1;
adc_new_data(&adcbuf[0]);
bp1a=DMA1_Channel1->CNDTR;
tc_cnt1++;
}

if (di & DMA_ISR_TCIF1) {// четный вызов (вторая половина буфера готова)
bp2=DMA1_Channel1->CNDTR;// Зафиксируем позицию DMA перед съемом данных
DMA1->IFCR=DMA_IFCR_CTCIF1;
adc_new_data(&adcbuf[1]);
bp2a=DMA1_Channel1->CNDTR;// Зафиксируем позицию DMA после съема данных
tc_cnt2++;
}

//for (int i=0; i<80; i++) __NOP();// Цикл, который влияет на количество байт, которые обновляются в буфере DMA
//(соответственно, появляется больше правильных выборок от начала буфера и от середины буфера)

}


Сообщение отредактировал IgorKossak - Apr 13 2017, 09:16
Причина редактирования: [codebox] для длинного кода. [code]-для короткого!!!
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
SasaVitebsk
сообщение Apr 13 2017, 05:15
Сообщение #2


Гуру
******

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



Ожидаемо.))
Я об этом и писал.
Вот только такой сон, наверное не сильно от бодрствования будет отличаться по потреблению ))
Go to the top of the page
 
+Quote Post
Alechek
сообщение Apr 14 2017, 16:29
Сообщение #3


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

Группа: Свой
Сообщений: 1 241
Регистрация: 15-11-05
Из: Челябинск
Пользователь №: 10 882



Цитата(SasaVitebsk @ Apr 13 2017, 10:15) *
Ожидаемо.))
Я об этом и писал.
Вот только такой сон, наверное не сильно от бодрствования будет отличаться по потреблению ))

Мои изыскания показывают, что особо сэкономить на остановке только тактовой процессора не получается.
Куда выгодней ее просто снижать.
Go to the top of the page
 
+Quote Post



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

 


RSS Текстовая версия Сейчас: 19th August 2025 - 19:14
Рейтинг@Mail.ru


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