Skocz do zawartości

STM32G431 :: ADC+Timer i zapętlone przerwanie DMA.


Majk32

Pomocna odpowiedź

Cześć,

 

próbuję się uporać z nadaktywnym przerwaniem z DMA. Konfiguracja następująca:

ADC1 pracuje w prostej konfiguracji samplując sobie jeden kanał. Wyzwalanie ADC1 robi timer TIM2:

 hadc1.Instance = ADC1;
  hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
  hadc1.Init.Resolution = ADC_RESOLUTION_12B;
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc1.Init.GainCompensation = 0;
  hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
  hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
  hadc1.Init.LowPowerAutoWait = DISABLE;
  hadc1.Init.ContinuousConvMode = DISABLE;
  hadc1.Init.NbrOfConversion = 1;
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIG_T2_TRGO;
  hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
  hadc1.Init.DMAContinuousRequests = ENABLE;
  hadc1.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;
  hadc1.Init.OversamplingMode = DISABLE;

Dalej, DMA:

  DMA1_Channel1->CPAR = (uint32_t) &ADC1->DR;					// Peripheral address
  DMA1_Channel1->CMAR = (uint32_t) array[0];					// Memory address
  DMA1_Channel1->CNDTR = 32;									// number of samples
  DMA1_Channel1->CCR |= DMA_CCR_EN | DMA_CCR_TCIE | DMA_PRIORITY_MEDIUM | // [EN, TCIE, PL] DMA Enable, xfer complete interrupt enabled
      DMA_PDATAALIGN_HALFWORD | DMA_MDATAALIGN_HALFWORD |		// [PSIZE, MSIZE] P-Data & M-Data size: 16-bit
  	  DMA_PERIPH_TO_MEMORY |
	  DMA_PINC_DISABLE | DMA_MINC_ENABLE;						// [PINC, MINC] addr increments

  DMAMUX1_Channel0->CCR |= DMA_REQUEST_ADC1;

  ADC1->CFGR |= ADC_CFGR_DMAEN;

I obsługa przerwania DMA: Kasuję wszystkie flagi przerwań DMA, deaktywuję TIM2:

void DMA1_Channel1_IRQHandler(void){

	DMA_HandleTypeDef *hdma = &hdma_adc1;

	hdma->DmaBaseAddress->IFCR = ((uint32_t)DMA_ISR_HTIF1 << (hdma->ChannelIndex & 0x1FU));
	hdma->DmaBaseAddress->IFCR = ((uint32_t)DMA_ISR_TCIF1 << (hdma->ChannelIndex & 0x1FU));
	hdma->DmaBaseAddress->IFCR = ((uint32_t)DMA_ISR_GIF1 << (hdma->ChannelIndex & 0x1FU));

	HAL_TIM_Base_Stop(&htim2);
	return;
}

I teraz, zgodnie z DMA/CNDTR do tablicy trafia 32 odczytów ADC, potem odpalane jest IRQ z DMA, timer staje, tablica odczytów ADC nie jest dalej nadpisywana. OK.

Problem pojawia się, że IRQ od DMA, pomimo wykasowania flag przerwań cały czas się odpala. Flagi HTIF1, TCIF1 oraz GIF1 nadal się świecą.

Potrzebuję zatrzymać odpalanie tego przerwania po zatrzymaniu TIM2. Docelowo, TIM2 będzie triggerowany sygnałem z zewnątrz, powodując "odpalenie" zbierania serii próbek. Czyli taki zewnętrzny sygnał SYNC. Ponieważ będzie to dość krytyczna czasowo operacja, nie mogę sobie pozwolić na wyłączanie DMA w przerwaniach, deaktywację ADC itp - chciałbym, żeby to działało hardwareowo i jedyną rolą przerwania będzie poinformowanie, że dane czekają już w buforze i podmiana bufora na kolejny.
 

  • Lubię! 1
Link do komentarza
Share on other sites

Zajrzałem na szybko do Reference Manual rodział 11 (bo temat DMA też mnie wkrótce będzie interesował) i widzę pierwsze primo, że enablowanie/disablowanie przerwań DMA odbywa się raczej poprzez rejestr DMA_CCR...   ?

O ile pamiętam rejestry ICFR służą do skasowania bieżącego sygnału przerwania, dzięki czemu hardware wie, że software ten sygnał skonsumował, natomiast nie służą do wyłączenia generowania przerwań przez źródło.

Link do komentarza
Share on other sites

(edytowany)
2 godziny temu, ReniferRudolf napisał:

Zajrzałem na szybko do Reference Manual rodział 11 (bo temat DMA też mnie wkrótce będzie interesował) i widzę pierwsze primo, że enablowanie/disablowanie przerwań DMA odbywa się raczej poprzez rejestr DMA_CCR...   ?

O ile pamiętam rejestry ICFR służą do skasowania bieżącego sygnału przerwania, dzięki czemu hardware wie, że software ten sygnał skonsumował, natomiast nie służą do wyłączenia generowania przerwań przez źródło.

Tak, wiem - ale ja nie chcę tych przerwań disablować. Za pierwszym razem (po zebraniu i przesłaniu do RAM 32-ch próbek) obsłużyłem przerwanie DMA, i w nim zatrzymałem timer TIM2, co jest równoznaczne z zatrzymaniem ADC, bo nie będzie wyzwalane ze stojącego timera. Czyli kolejne próbki się nie pojawiają, bo ADC stoi. Skoro nie ma ukończonych konwersji, to według tego jak to rozumiem - nie ma kolejnego requestu na transfer. Tymczasem IRQ od DMA odpala cały czas w pętli, pomimo, że ADC stoi i pomimo skasowania flag DMA. Co ciekawe, DMA odpala to przerwania transferu POMIMO tego, że do RAM nie trafiają nowe dane - więc przyczyną chyba nie jest "koniec transferu" - bo gdyby tak było toby faktycznie nadpisywał stare próbki.

A ja chcę docelowo, żeby po obsłużeniu tego przerwania system sobie czekał, aż załączę timer znowu, który odpali mi ADC - i po skończeniu konwersji przez przetwornik znów nastąpi wyzwolenie dla DMA, celem przesłania zmierzonej próbki do bufora.

Co jeszcze ciekawe, po skasowaniu flag DMA, nadal mają one wartość "1".

Capture.JPG

Edytowano przez Majk32
Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

Treker
Ta treść została wynagrodzona przez moderatora!

Majk32 otrzymał odznakę: "Odkrywca (podanie odp. na własne pytanie)"

Problem rozwiązany - procedura kasowania flag DMA z HAL nie działała. Napisanie od podstaw "po swojemu" załatwiło temat.

	DMA1_Channel1->CCR &= ~DMA_CCR_EN;							// stop DMA
	uint32_t *ifcr = DMA1_BASE + 4;
	*(ifcr) = DMA_IFCR_CHTIF1 | DMA_IFCR_CTCIF1 | DMA_IFCR_CTEIF1;

 

  • Lubię! 2
Link do komentarza
Share on other sites

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.