Перейти к содержанию
    

stm32f030. некорректно работает DMA в sleep mode (решено)

Несколько раундов борьбы с косяком, пока безуспешно. Суть следующая:

Оцифровываю данные так: АЦП -> DMA -> прерывание half transfer и full transfer.

Если процессор всегда в активном режиме, все работает прекрасно.

Но как только в холостой основной цикл добавляю остановку процессора (WFI), то начинает твориться следующее:

 

DMA генерирует прерывания как положено, с той же частотой и вовремя, т.е. как и без WFI. Но как только активирую WFI, то в RAM, куда DMA должна сохранять результат оцифровки, данные не записываются.

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

При этом все счетчики контроллера DMA работают корректно, что в sleep mode, что без него, т.е. нужный канал АЦП записывается всегда по нужному адресу. Счетчики DMA считывал в обработчике DMA, и делаю вывод что прерывания DMA вызываются вовремя (без задержек).

 

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

Слабо верится что такой косяк до ST до сих пор не дошел.

 

 

Куски кода:

  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
[codebox] для длинного кода. [code]-для короткого!!!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

4DMA генерирует прерывания как положено, с той же частотой и вовремя, т.е. как и без WFI.4

DMA не сам ведь генерирует прерывания. DMA вообще сам по себе работать не будет - его ADC пинает по готовности. Отсюда вывод, что АЦП работает.

Соответственно в настройках DMA и ADC я не вижу смысла копаться. Надо разбираться как RAM работает в режиме сна. Там чего почитать

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

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

 

Ура, нашел в чем проблема :)

 

Есть такой бит - "sram interface clock enable during sleep mode".

Включил, все заработало.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ожидаемо.))

Я об этом и писал.

Вот только такой сон, наверное не сильно от бодрствования будет отличаться по потреблению ))

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ожидаемо.))

Я об этом и писал.

Вот только такой сон, наверное не сильно от бодрствования будет отличаться по потреблению ))

Мои изыскания показывают, что особо сэкономить на остановке только тактовой процессора не получается.

Куда выгодней ее просто снижать.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Мои изыскания показывают, что особо сэкономить на остановке только тактовой процессора не получается.

Куда выгодней ее просто снижать.

Интересно. А как же изыскания Atmel, к примеру. Которые рекомендуют прямо противоположное. То есть быстро проснуться выполнить кусочек и заснуть глубоким сном. ))

Я не экспериментировал. На это надо пол жизни потратить, но делал пару устройств малого потребления на MSP430. Последнее устройство вообще непонятно себя ведёт. Потребление намного выше , чем заявленное. Перерыл всё. Проект факультативный, поэтому тратить на него кучу времени не могу. Но, было бы любопытно сделать аналогичный проект на st32l0.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Интересно. А как же изыскания Atmel, к примеру. Которые рекомендуют прямо противоположное. То есть быстро проснуться выполнить кусочек и заснуть глубоким сном. ))

...

Но, было бы любопытно сделать аналогичный проект на st32l0.

Глубоким сном - да! Но если нужна работающая периферия, глубоким сном тут и не пахнет. Фишка, видимо, в том, что хоть ядро проца и стоит, но всякие NVIC работают, и жрут просто дофига!

C STM32L сказка, там многое что можно напрямую от генератора запитать, а общую тактовую снизить.

С STM32F0x0 хуже, там только UART может работать от генератора.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Глубоким сном - да! Но если нужна работающая периферия, глубоким сном тут и не пахнет. Фишка, видимо, в том, что хоть ядро проца и стоит, но всякие NVIC работают, и жрут просто дофига!

Мои изыскания на этой ниве (но с LPC1758) дали похожий результат: я выяснил, что если выключить всю периферию, а также PLL, выключить кварц, затактироваться от внутреннего RC, и ещё включить после него максимальный делитель, так что тактовая проца составляет десятки кГц, то в таком режиме МК потребляет почти как в самом глубоком сне. И ещё и ОЗУ при этом остаётся целым.

Правда один таймер я оставлял работать. Для побудки.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А время пробудки не замеряли в том и в др. случае?

У меня устройство в таком режиме (ожидания) периодически ложилось спать, потом просыпалось, включало периферию, опрашивало её несколько мсек (определяло нажатость кнопки, наличие подключения USB-хоста, ставило CTS Bluetooth-модулю, чтобы он мог выплюнуть накопленные за время сна данные), и, если можно оставаться в режиме ожидания, укладывалось спать опять. Этот период был == 300мсек. Для такого периода время просыпания не играет роли.

Да там собственно оно должно быть быстрым: процессор выполняет WFI (на малой тактовой), таймер генерит сигнал прерывания (но входа в ISR нет), процессор переходит на след. команду после WFI и сразу сбрасывает делитель своей тактовой в 1 (до этого был выставлен максимум ==256), и дальнейшее выполнение уже должно идти на полной частоте IRC (4МГц если склероз не изменяет). Соответственно когда проц спит у него тактовая ~15.6кГц. По потреблению это почти то же самое, что глубокий сон.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...