logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

[stm32] STM32F103RB – zawieszanie I2C przy aktywnych przerwaniach input capture z timerów

pawwik 11 Gru 2010 11:53 4130 9
REKLAMA
  • #1 8853738
    pawwik
    Poziom 11  
    Posty: 74
    Pomógł: 1
    Mój problem polega na tym że komunikacja z 2 czujnikami na i2c przebiega poprawnie dopóki nie odpalę przerwań od input capture z timerów.

    Komunikacja zawiesza się w losowo wybranych momentach, raz po 20 sekundach raz po 10 minutach. Gdy wyłączę przerwania to chodzi bez blednie. Mój procesor to stm32F103rb. Próbowałem już 3 sposobów na odczyt z i2c - DMA, przerwania o najwyższym priorytecie i bez przerwań. Nic to nie zmienia. Sprawdzałem także rożne prędkości i2c - to samo. Komunikacja wywala sie w różnych miejscach - przy sprawdzaniu bitu SB czy to ADDR. Po wystąpieniu problemu z ADDR można zrestartować i2c i chodzi dalej ale po zawieszeniu SB już tylko reset zasilania ratuje sytuacje. I bardzo ważne, nie korzytam z bilbiotek od ST tylko z definów i paru funkcji z biblioteki libopenstm32.

    Męczę się z tym już nie wiem ile. Zna ktoś jakieś rozwiązanie ?
  • REKLAMA
  • #3 8853776
    pawwik
    Poziom 11  
    Posty: 74
    Pomógł: 1
    aktualnie mam kod do DMA:
    konfiguracja i2c
    
    gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_ALTFN_OPENDRAIN,GPIO_I2C1_SCL | GPIO_I2C1_SDA);
    
    	I2C_CR1(I2C1) |= I2C_CR1_SWRST;
    	I2C_CR1(I2C1) &= ~I2C_CR1_SWRST;
    
    	i2c_peripheral_disable(I2C1);
    	i2c_set_clock_frequency(I2C1, I2C_CR2_FREQ_36MHZ);
    	i2c_set_fast_mode(I2C1);
    	i2c_set_ccr(I2C1, 0x1e);
    	i2c_set_trise(I2C1, 0x0A);
    	i2c_set_own_7bit_slave_address(I2C1, 0x32);
    	I2C1_CR2 |= I2C_CR2_DMAEN | I2C_CR2_LAST;
    	I2C_CR1(I2C1) |= I2C_CR1_ACK;
    	i2c_peripheral_enable(I2C1);
    


    konfiguracja dma
    
    	DMA1_CPAR7 = 0x40005410;
    	DMA1_CMAR7 =(u32) &bufor_i2c;
    	DMA1_CNDTR7 =10;
    	DMA1_CCR7 &=~DMA_CCR7_DIR;
    	DMA1_CCR7 |= DMA_CCR7_MINC;
    	DMA1_CCR7 |= DMA_CCR7_EN;
    


    procedura odczytu z i2c

    I2C_CR1(i2c) |= I2C_CR1_ACK;
    	i2c_send_start(i2c);
    
    	timeout = 0xFFFF;
    	while (!(I2C_SR1(i2c) & I2C_SR1_SB))		{
            if (timeout-- == 0)return 1;
    	}
    
    	i2c_send_7bit_address(i2c,itg3200, I2C_WRITE);
    	timeout = 0xFFFF;
    	while (!(I2C_SR1(i2c) & I2C_SR1_ADDR))	{
            if (timeout-- == 0)return 2;
    	}
    
    
    	reg32 = I2C_SR2(i2c);
    
    	i2c_send_data(i2c, 0x1B);
    	timeout = 0xFFFF;
    	while (!(I2C_SR1(i2c) & (I2C_SR1_BTF|I2C_SR1_TxE)))	{
            if (timeout-- == 0)return 3;
    	}
    	i2c_send_start(i2c);
    	timeout = 0xFFFF;
    	//while (!((I2C_SR1(i2c) & I2C_SR1_SB)& (I2C_SR2(i2c) & (I2C_SR2_MSL | I2C_SR2_BUSY))))	{
    	while (!(I2C_SR1(i2c) & I2C_SR1_SB))	{
            if (timeout-- == 0)return 4;
    	}
    
    	i2c_send_7bit_address(i2c,itg3200, I2C_READ);
    	timeout = 0xFFFF;
    	while (!(I2C_SR1(i2c) & I2C_SR1_ADDR))	{
            if (timeout-- == 0)return 5;
    	}
    	reg32 = I2C_SR2(i2c);
    
    
    	timeout = 0xFFFF;
    	while (!((DMA1_ISR & DMA_ISR_TCIF7)==DMA_ISR_TCIF7))	{
            if (timeout-- == 0)return 6;
    	}
    
    	DMA1_CCR7 &= ~DMA_CCR1_EN;
    
    	DMA1_IFCR |= DMA_IFCR_CTCIF7;
    
    
    	I2C1_CR1 |= I2C_CR1_STOP;
    	timeout = 0xFFFF;
    	while ((I2C1_CR1&I2C_CR1_STOP) ==I2C_CR1_STOP)	{
            if (timeout-- == 0)return 7;
    	}
    
  • REKLAMA
  • REKLAMA
  • #5 8853812
    pawwik
    Poziom 11  
    Posty: 74
    Pomógł: 1
    zegary itp włączone, bo jak mówiłem wszystko chodzi i odczytuje ładnie aż do pewnego momentu gdzie się wiesza. Funkcja odczytu znajduje się w przerwaniu od systicka, a przerwania od timerów maja niższy priorytet wiec nie powinny się wcinać w komunikacje. Jednak jak je wyłączę to chodzi bezbłędnie.
  • #6 8853884
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    Zwiększ rozmiar stosów, bo przerwania mogą po prostu przepełniać stos. No i jeśli ich nie potrzebujesz, to wyłącz możliwość przerwań zagnieżdżonych.

    4\/3!!
  • #7 8853986
    pawwik
    Poziom 11  
    Posty: 74
    Pomógł: 1
    hardkorowo ustawione

    __main_stack_size = 4096;
    __process_stack_size = 4096;


    nie pomaga. Jedyne co poprawia to wylaczenie timerow.

    konfuguracja timerow
    
    	 TIM2_CCMR2 |= TIM_CCMR2_CC3S_IN_TI2| TIM_CCMR2_CC4S_IN_TI2;
    
    	 TIM2_DIER |= TIM_DIER_CC4IE | TIM_DIER_CC3IE;
    	 TIM2_CCMR1 |= TIM_CCMR1_IC1F_CK_INT_N_8 |  TIM_CCMR1_IC2F_CK_INT_N_8;
    	 TIM2_CCMR1 |=  TIM_CCMR1_OC2M_PWM1 | TIM_CCMR1_OC2PE ; //Konfiguracja wyjsc
    	 TIM2_CCER |=TIM_CCER_CC3E|TIM_CCER_CC4E;
    	 TIM_CR1(TIM2) |= TIM_CR1_ARPE; //enable i enable autoreload
    	 TIM_PSC(TIM2) |= 72; //preskaler
    	 TIM_ARR(TIM2)=20000;//autoreload
    	 
    	 TIM_CR1(TIM2) |= TIM_CR1_CEN ;
    
    
    
    	 //TIMER 3
    	 TIM3_DIER |= TIM_DIER_CC1IE | TIM_DIER_CC2IE;
    	 TIM2_CCMR2 |= TIM_CCMR2_IC3F_CK_INT_N_8 |  TIM_CCMR2_IC4F_CK_INT_N_8;
    	 TIM3_CCMR1 |= TIM_CCMR1_CC2S_IN_TI2 | TIM_CCMR1_CC1S_IN_TI2;
    	 TIM3_CCMR2 |=  TIM_CCMR2_OC4M_PWM1  | TIM_CCMR2_OC3M_PWM1 | TIM_CCMR2_OC4PE | TIM_CCMR2_OC3PE;
    	 TIM3_CCER |= TIM_CCER_CC4E | TIM_CCER_CC3E| TIM_CCER_CC2E| TIM_CCER_CC1E;
    	 TIM3_CR1 |= TIM_CR1_ARPE;
    	 TIM3_PSC |= 72; //preskaler
    	 TIM3_ARR = 20000;//autoreload
    
    	 TIM3_CR1 |= TIM_CR1_CEN;
    
    
    
    	 //TIMER4
    	 TIM4_CCMR2 |=  TIM_CCMR2_OC4M_PWM1  | TIM_CCMR2_OC3M_PWM1 | TIM_CCMR2_OC4PE | TIM_CCMR2_OC3PE;
    	 TIM4_CCER |= TIM_CCER_CC4E | TIM_CCER_CC3E;
    	 TIM4_CR1 |= TIM_CR1_ARPE;
    	 TIM4_PSC |= 72; //preskaler
    	 TIM4_ARR=20000;//autoreload
    
    	 TIM4_CR1 |= TIM_CR1_CEN;



    i przerwanie od niego
    u32 reg32;
    
    	reg32=TIM3_SR;
    
    	if ((reg32 &TIM_DIER_CC1IE)==TIM_DIER_CC1IE){
    		TIM3_SR &= ~( TIM_DIER_CC1IE );
    		if (kanal_3_flaga==0){
    			kanal_3_flaga=1;
    			kanal_3_start=TIM3_CCR1;
    			TIM3_CCER |= TIM_CCER_CC1P;//ustaw na zbocze opadajace
    		}else{
    			kanal_3_flaga=0;
    			kanal_3_koniec=TIM3_CCR1;
    			if (kanal_3_koniec>kanal_3_start){
    				kanal_3=kanal_3_koniec-kanal_3_start;
    			}
    			else{
    				kanal_3=(20000-kanal_3_start)+kanal_3_koniec;
    			}
    			TIM3_CCER &=~TIM_CCER_CC1P;//ustaw na zbocze opadajace
    		}
    
    	}
    	if ((reg32 &TIM_DIER_CC2IE)==TIM_DIER_CC2IE){
    		TIM3_SR &= ~( TIM_DIER_CC2IE );
    		if (kanal_4_flaga==0){
    			kanal_4_flaga=1;
    			kanal_4_start=TIM3_CCR2;
    			TIM3_CCER |= TIM_CCER_CC2P;//ustaw na zbocze opadajace
    		}else{
    			kanal_4_flaga=0;
    			kanal_4_koniec=TIM3_CCR2;
    			if (kanal_4_koniec>kanal_4_start){
    				kanal_4=kanal_4_koniec-kanal_4_start;
    			}
    			else {
    				kanal_4=(20000-kanal_4_start)+kanal_4_koniec;
    			}
    			TIM3_CCER &=~TIM_CCER_CC2P;//ustaw na zbocze opadajace
    		}
    
    	}





    wylaczenie przerwan od timerow tez sytuacji nie rozwiazauje, pomaga jedynie ich calkowite wylaczenie...
  • REKLAMA
  • #8 8854067
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    Jeśli przerwanie obsługujące I2C trwa długo, to może po prostu timery dostają jakiegoś overflow (or sth) i wiesza się tak naprawdę gdzie indziej? Masz JTAGa?

    4\/3!!
  • #9 8854076
    pawwik
    Poziom 11  
    Posty: 74
    Pomógł: 1
    no wlasnie nie mam JTAGa i z kazda chwila coraz bardziej tego zaluje :P
  • #10 9504058
    ciastek4
    Poziom 14  
    Posty: 118
    Pomógł: 4
    Witaj,

    Popatrz sobie do datasheeta. Są tam informacje, kiedy pewne instrukcje nie powinny być przerwane przez przerwanie.Chodzi mi o takie wzmianki jak:
    EV6: ADDR=1, cleared by reading SR1 register followed by reading SR2...
    Może to powoduje usterkę. Zobacz sobie notę aplikacyjną: an2824 i odszukaj miejsca gdzie powinny być wyłączone przerwania.

    Jeżeli natomiast udało Ci się rozwiązać problem to podziel się z nami rozwiązaniem.

Podsumowanie tematu

✨ Użytkownik zgłasza problem z komunikacją I2C w mikrokontrolerze STM32F103RB, która zawiesza się po uruchomieniu przerwań od timerów. Komunikacja działa poprawnie, gdy przerwania są wyłączone, co sugeruje konflikt między przerwaniami a operacjami I2C. Użytkownik próbował różnych metod, w tym DMA i zmiany priorytetów przerwań, ale problem nadal występuje. Inni uczestnicy dyskusji sugerują sprawdzenie konfiguracji zegarów, zwiększenie rozmiaru stosów oraz analizę dokumentacji technicznej, aby zidentyfikować potencjalne problemy z przerwaniami. Wskazano również na możliwość, że długotrwałe przerwania mogą prowadzić do przepełnienia timerów.
Wygenerowane przez model językowy.
REKLAMA