Skocz do zawartości

[STM32][C] i2c zawieszanie programu


mike660

Pomocna odpowiedź

Cześć!

Zrobiłem sobie ekspander wejść oraz osobny ekspander wyjść na MCP23017, komunikacja i2c.

Ogólnie wszystko działa ale pojawia się od czasu do czasu problem że po wysłaniu ramki do MCP program się całkowicie zawiesza. 

Przeanalizowałem kod razem z debuggerem i wygląda to tak że program wychodzi z funkcji HAL_I2C_Master_Transmit ( zwraca HAL_BUSY lub HAL_ERROR ) i dopiero potem następuje zwis i nie wiem co w tym momencie procesor robi.

Jest ktoś w stanie nakierunkować mnie gdzie szukać problemu ?

Na początek chciałbym aby po błędzie i2c STM dalej normalnie funkcjonował, w późniejszym etapie chciałbym wyeliminować problem wysyłania.

Ekspander wejść i wyjść działają na osobnych liniach i2c.

Całość generowana za pomocą CubeMx

Ewentualnie może pomogła by zmiana biblioteki do obsługi i2c ?

Edytowano przez mike660
Link do komentarza
Share on other sites

Dokladnie to błędu szukaj w krzemie STMa - ta magistrala w tych procesorach tak ma, ale pod HALem jakoś to działa. Pokaż kod i sprawdź stany rejestru SR od I2C - jak rozwiniesz SFR to masz tam rózne flagi BUSY, ACK itp. W Attolicu, CubeIDE i innych Eclipso podobnych masz okienko SFR w debugu - podgląd rejestrów (Jak nie ma w to poszukaj w View gdzieś).

 

Przed włączeniem I2C możesz spróbować zresetować magistralę I2C - tak procedura jest opisana w Erracie procka.

	I2Cx->CR1 |= I2C_CR1_SWRST; //Software reset 1
	I2Cx->CR1 &= ~ I2C_CR1_SWRST; //Software reset 0

 

zamiast I2Cx wstawiasz IC21 albo I2C2 itd zależnie którego używasz.

Handlery są w pliku stm32fxxxx_it.c (gdzie x to numer rodziny itp), ale jakbyś był w Handlerze to by Ci tam debug wskakiwał po wciśnięciu pauzy.

 

Najważniejsze to kod - dla programisty ważniejsze niż opis słowny, bez tego to możemy wróżyć tutaj przez rok.

Edytowano przez ps19
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

Wszystkie rejestry w debuggerze po zawieszeniu się są równe 0

No więc kod

Uruchomienie i2c standardowe z CubeMx

void MX_I2C3_Init(void)
{

  hi2c3.Instance = I2C3;
  hi2c3.Init.ClockSpeed = 10000;
  hi2c3.Init.DutyCycle = I2C_DUTYCYCLE_2;
  hi2c3.Init.OwnAddress1 = 0;
  hi2c3.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
  hi2c3.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
  hi2c3.Init.OwnAddress2 = 0;
  hi2c3.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
  hi2c3.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
  if (HAL_I2C_Init(&hi2c3) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure Analogue filter 
  */
  if (HAL_I2CEx_ConfigAnalogFilter(&hi2c3, I2C_ANALOGFILTER_ENABLE) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure Digital filter 
  */
  if (HAL_I2CEx_ConfigDigitalFilter(&hi2c3, 0) != HAL_OK)
  {
    Error_Handler();
  }

}

 

Do testów zrobiłem sobie w pętli zmianę stanów pinów :

while (1) {

	HAL_GPIO_TogglePin(LD1_GPIO_Port, LD1_Pin);
	MCP23017_toggle_pin(&hi2c3, 1,1);
	HAL_Delay(1000);
	MCP23017_toggle_pin(&hi2c3, 1,0);
	HAL_Delay(1000);
}

 

i funkcja tooglePin

void MCP23017_toggle_pin(I2C_HandleTypeDef *hi2c, uint8_t pin, uint8_t v) {

	uint8_t data[2];

	data[0] = out_str.port;    // Adres rejestru IODIRA
  
	if(v==1)
		data[1] = 0xFF;   
	else
		data[1] = 0x00;
  
	HAL_I2C_Master_Transmit(hi2c, out_str.mcp + 1, data, 2, 20);

	

}

 

Program działa różnie, najczęściej 2- 3 przejścia pętli i koniec...

Link do komentarza
Share on other sites

Proponuję zacząć od początku, czyli jaki mikrokontroler, która wersja CubeMX. Wbrew pozorom różne błędy pojawiają się w oprogramowaniu dla różnych modeli z rodziny STM32, w każdej wersji Cube niektóre są poprawiane, a pojawiają się nowe. Więc może zamiast zgadywać warto ustalić o czym piszemy.

Druga sprawa to "wygląda to tak że program wychodzi z funkcji HAL_I2C_Master_Transmit ( zwraca HAL_BUSY lub HAL_ERROR ) i dopiero potem następuje zwis i nie wiem co w tym momencie procesor robi." - możesz to nieco rozwinąć? Piszesz że używasz debuggera, a później nie wiesz co procesor robi - czyli nie możesz zatrzymać wykonywania, nastąpił reset, program jest w miejscu gdzie się nie spodziewałeś czy o co chodzi? Przy okazji warto sprawdzić czy nie jest winne to co pojawia się w programie po wywołaniu HAL_I2C_Master_Transmit - może wstaw tam nieskończoną pętlę i zobacz czy wtedy wszystko działa. Bo może błąd jest w zupełnie innym miejscu kodu?

Edit: pisaliśmy w tej samej chwili - w każdym razie warto ustalić o którym modelu mikrokontrolera piszemy. Natomiast odnośnie zawieszenia - wygląda jakby wykonywany był reset, stąd następne pytania: czy używasz watchdoga, z jakiej płytki korzystasz?

Edytowano przez Elvis
Link do komentarza
Share on other sites

(edytowany)

Płytka Nucleo F429, CubeMx 1.3

Nie używam watchdoga.  W pętli głównej oprócz HAL_I2C_Master_Transmit jest mruganie diodą wbudowaną w płykę. Po błędzie przestaje mrugać.

 

Podczas dalszego debugowania odkryłem że program zatrzymuje się na funkcji i trwa w pętli nieskończonej

static HAL_StatusTypeDef I2C_WaitOnFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Flag, FlagStatus Status, uint32_t Timeout, uint32_t Tickstart)
{
  /* Wait until flag is set */
  while (__HAL_I2C_GET_FLAG(hi2c, Flag) == Status)
  {
    /* Check for the Timeout */
    if (Timeout != HAL_MAX_DELAY)
    {
      if (((HAL_GetTick() - Tickstart) > Timeout) || (Timeout == 0U))
      {
        hi2c->PreviousState     = I2C_STATE_NONE;
        hi2c->State             = HAL_I2C_STATE_READY;
        hi2c->Mode              = HAL_I2C_MODE_NONE;
        hi2c->ErrorCode         |= HAL_I2C_ERROR_TIMEOUT;

        /* Process Unlocked */
        __HAL_UNLOCK(hi2c);

        return HAL_ERROR;
      }
    }
  }
  return HAL_OK;
}

 

Edytowano przez mike660
Dalsze debugowanie
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.