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

 
 
> 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
Ответов (1 - 9)
SasaVitebsk
сообщение Apr 12 2017, 20:12
Сообщение #2


Гуру
******

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



Цитата(jeka @ Apr 12 2017, 22:07) *
4DMA генерирует прерывания как положено, с той же частотой и вовремя, т.е. как и без WFI.4

DMA не сам ведь генерирует прерывания. DMA вообще сам по себе работать не будет - его ADC пинает по готовности. Отсюда вывод, что АЦП работает.
Соответственно в настройках DMA и ADC я не вижу смысла копаться. Надо разбираться как RAM работает в режиме сна. Там чего почитать
Go to the top of the page
 
+Quote Post
jeka
сообщение Apr 12 2017, 20:42
Сообщение #3


Administrator
***

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



Это понятно. Я к тому что контроллер DMA корректно работает с адресацией и прерываниями (именно DMA же определяет заполненность буфера), но не пишет в память. В документации про упоминание особенностей работы периферии АЦП или DMA в sleep режиме ничего интересного не нашел.

Про sleep режим указано, что он лишь останавливает клоки процессора, но вся остальная периферия (в т.ч. и память) продолжают штатно работать. В разделе памяти про спячку тоже ничего нет.

Ура, нашел в чем проблема sm.gif

Есть такой бит - "sram interface clock enable during sleep mode".
Включил, все заработало.
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Apr 13 2017, 05:15
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 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
Сообщение #5


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

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



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

Мои изыскания показывают, что особо сэкономить на остановке только тактовой процессора не получается.
Куда выгодней ее просто снижать.
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Apr 17 2017, 06:33
Сообщение #6


Гуру
******

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



Цитата(Alechek @ Apr 14 2017, 19:29) *
Мои изыскания показывают, что особо сэкономить на остановке только тактовой процессора не получается.
Куда выгодней ее просто снижать.

Интересно. А как же изыскания Atmel, к примеру. Которые рекомендуют прямо противоположное. То есть быстро проснуться выполнить кусочек и заснуть глубоким сном. ))
Я не экспериментировал. На это надо пол жизни потратить, но делал пару устройств малого потребления на MSP430. Последнее устройство вообще непонятно себя ведёт. Потребление намного выше , чем заявленное. Перерыл всё. Проект факультативный, поэтому тратить на него кучу времени не могу. Но, было бы любопытно сделать аналогичный проект на st32l0.
Go to the top of the page
 
+Quote Post
Alechek
сообщение Apr 17 2017, 09:21
Сообщение #7


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

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



Цитата(SasaVitebsk @ Apr 17 2017, 11:33) *
Интересно. А как же изыскания Atmel, к примеру. Которые рекомендуют прямо противоположное. То есть быстро проснуться выполнить кусочек и заснуть глубоким сном. ))
...
Но, было бы любопытно сделать аналогичный проект на st32l0.

Глубоким сном - да! Но если нужна работающая периферия, глубоким сном тут и не пахнет. Фишка, видимо, в том, что хоть ядро проца и стоит, но всякие NVIC работают, и жрут просто дофига!
C STM32L сказка, там многое что можно напрямую от генератора запитать, а общую тактовую снизить.
С STM32F0x0 хуже, там только UART может работать от генератора.
Go to the top of the page
 
+Quote Post
jcxz
сообщение Apr 19 2017, 18:17
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(Alechek @ Apr 17 2017, 11:21) *
Глубоким сном - да! Но если нужна работающая периферия, глубоким сном тут и не пахнет. Фишка, видимо, в том, что хоть ядро проца и стоит, но всякие NVIC работают, и жрут просто дофига!

Мои изыскания на этой ниве (но с LPC1758) дали похожий результат: я выяснил, что если выключить всю периферию, а также PLL, выключить кварц, затактироваться от внутреннего RC, и ещё включить после него максимальный делитель, так что тактовая проца составляет десятки кГц, то в таком режиме МК потребляет почти как в самом глубоком сне. И ещё и ОЗУ при этом остаётся целым.
Правда один таймер я оставлял работать. Для побудки.
Go to the top of the page
 
+Quote Post
Kabdim
сообщение Apr 20 2017, 08:07
Сообщение #9


Знающий
****

Группа: Свой
Сообщений: 558
Регистрация: 26-11-14
Из: Зеленоград
Пользователь №: 83 842



А время пробудки не замеряли в том и в др. случае?
Go to the top of the page
 
+Quote Post
jcxz
сообщение Apr 20 2017, 09:00
Сообщение #10


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(Kabdim @ Apr 20 2017, 10:07) *
А время пробудки не замеряли в том и в др. случае?

У меня устройство в таком режиме (ожидания) периодически ложилось спать, потом просыпалось, включало периферию, опрашивало её несколько мсек (определяло нажатость кнопки, наличие подключения USB-хоста, ставило CTS Bluetooth-модулю, чтобы он мог выплюнуть накопленные за время сна данные), и, если можно оставаться в режиме ожидания, укладывалось спать опять. Этот период был == 300мсек. Для такого периода время просыпания не играет роли.
Да там собственно оно должно быть быстрым: процессор выполняет WFI (на малой тактовой), таймер генерит сигнал прерывания (но входа в ISR нет), процессор переходит на след. команду после WFI и сразу сбрасывает делитель своей тактовой в 1 (до этого был выставлен максимум ==256), и дальнейшее выполнение уже должно идти на полной частоте IRC (4МГц если склероз не изменяет). Соответственно когда проц спит у него тактовая ~15.6кГц. По потреблению это почти то же самое, что глубокий сон.
Go to the top of the page
 
+Quote Post

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

 


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


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