Elektroda.pl
Elektroda.pl
X

Search our partners

Find the latest content on electronic components. Datasheets.com
Elektroda.pl
Please add exception to AdBlock for elektroda.pl.
If you watch the ads, you support portal and users.

[Atmega128] [Bascom] - Obsługa błędów I2C przy zapisie do eeprom

rj1307 14 Nov 2013 15:05 1902 7
  • #1
    rj1307
    Level 15  
    Witam, mam sterownik który co kilka minut zapisuje w pamięci AT24c1024 jeden z 4 parametrów, są to 3 wartości typu Byte oraz jedna typu Word. Niestety raz na 1-2 dni występuje problem z zapisem, "zacina" się komunikacja i sterownik najczęściej zostaje zresetowany przez watchdog'a, jeśli wyłączę watchdoga sterownik przestaje reagować. Na magistrali jest jeszcze PCF8583 z którego co 1s odczytuję dane, oraz 3xADS1110 które odczytuję po kolei co 5s. Wszystko robię w pętli głównej, w przerwaniu ustawiam tylko znaczniki.
    Korzystam ze sprzętowego TWI, rezystory podciągające mają po 2k2.
    Konfiguracja TWI:
    Code: basic4gl
    Log in, to see the code


    W ten sposób wychwycam moment, gdzie występuje błąd.

    Code: basic4gl
    Log in, to see the code




    W momencie wystąpienia błędu, terminal zgłasza:

    Code:
    i2cwbyte adresl   TWSR=38
    
    i2cwbyte T1_eeprom   TWSR=F8
    8:15:30:Bład zapisu historii T1


    lub

    Code:
    i2cwbyte Odczyt_sg_l  TWSR=38
    
    12:3:40:Bład zapisu historii Sg_l


    Rejestr TWSR powinien mieć wartość 28 a ma 38, czyli brak potwierdzenia.
    W jaki sposób, po wykryciu tego błędu, mogę przywrócić poprawny stan magistrali TWI, bez resetu sterownika?
  • Helpful post
    #2
    cavendish
    Level 17  
    Skoro program utyka w jakimś miejscu to znaczy że czekasz w pollingu na stan, który się nie pojawia. Po pierwsze dodałbym time out, który przerwie pętlę oczekiwania zanim układ zostanie zresetowany przez watchdog. Dodatkowo w przypadku wystąpienia takiego timeoutu trzeba by obsłużyć jakoś błąd magistrali:
    [Atmega128] [Bascom] - Obsługa błędów I2C przy zapisie do eeprom

    Błąd w tym przypadku to arbitration lost. Skoro na magistrali nie ma innego mastera to należałoby wysłać ponowny warunek startu.
  • #3
    rj1307
    Level 15  
    cavendish wrote:
    Skoro program utyka w jakimś miejscu to znaczy że czekasz w pollingu na stan, który się nie pojawia. Po pierwsze dodałbym time out, który przerwie pętlę oczekiwania zanim układ zostanie zresetowany przez watchdog.

    Zapis nie jest w pętli, struktura programu wygląda tak:
    Code: basic4gl
    Log in, to see the code


    cavendish wrote:
    Skoro na magistrali nie ma innego mastera to należałoby wysłać ponowny warunek startu.

    Nie mam innego mastera, czy wystarczy dopisać zwykłe
    Code: basic4gl
    Log in, to see the code

    czy trzeba dłubać w rejestrach?
  • #4
    cavendish
    Level 17  
    Niestety co do programu w bascomie jak i samych bibliotek dostępnych w tym środowisku nie jestem w stanie się wypowiedzieć ale recepta na powtórzony start jest generalnie prosta:
    [Atmega128] [Bascom] - Obsługa błędów I2C przy zapisie do eeprom

    Żeby przetestować na szybko czy to działa (nie czekając kilku dni aby stwierdzić, że firmware się nie wiesza) dorobiłbym sobie jakieś zwieranie linii SDA. Arbitration lost jest wykrywane w sytuacji gdy master wysyła jakieś dane a linia SDA w momentach gdy master wystawia stan wysoki pozostaje w stanie niskim.
  • #5
    rj1307
    Level 15  
    Czyli jednak dłubanie w rejestrach :)
    Co do testowania - mam jeszcze wolne piny w m128, podłączę jeden pod SDA i programowo mogę ściągnąć szynę do stanu niskiego.
    W dokumentacji jest napisane:
    Quote:
    Z przypadkiem specjalnym mamy do czynienia gdy nowy warunek START pojawi się pomiędzy warunkami START i STOP. Tego typu warunek nosi nazwę REPEATED START i jest wykorzystywany gdy master życzy sobie zainicjować nowy transfer bez porzucania sterowania nad magistralą. Po REPEATED START magistralę uważa się za zajętą dopóki nie pojawi się następny STOP.
    Po warunku REPEATED START (stan $10) TWI może uzyskać dostęp do tego samego urządzenia slave lub do nowego urządzenia slave bez generacji warunku STOP. REPEATED START aktywuje urządzenie master aby przełączać między urządzeniami slave, tryb MT i MR bez utraty sterowania na magistrali.

    Trochę nie rozumiem - po REPEATED START mam wygenerować STOP i ponowić całą procedurę zapisu
    Code: basic4gl
    Log in, to see the code

    czy tylko od momentu wystąpienia błędu?
    Code: basic4gl
    Log in, to see the code
  • #6
    rj1307
    Level 15  
    Rozwiązanie okazało się proste - wystarczy wyzerować rejestr TWCR, dzięki za pomoc.
  • #7
    cavendish
    Level 17  
    Są rzeczywiście sytuacje, gdzie hardware'owe i2c/twi potrafi się zawiesić. Nie jestem specem od AVR niemniej kiedyś bawiłem się w atmega interfejsem TWI. Wykonywałem losowe zwarcia linii SDA zarówno w trakcie transmisji jak i gdy linia jest wolna. Czasem gdy rozwierałem linię SDA ona zamiast podciągnąć się do 5V pozostawała na 0V a w rejestrze statusowym pojawiały się czasem (nie było to regułą) statusy różne od 0xF8 - np. 0x08 - "a start condition has been transmitted". Nie zgłaszało się przy tym żadne przerwanie gdzie znajdowała się potencjalnie obsługa błędów. Wydaje mi się, że są tam jakieś luki w działaniu tego sprzętowego kontrolera, nie uwzględniające pewnych scenariuszy zdarzeń na magistrali. Dlatego w sterowniku i2c na avrki używam procedury:

    Code: c
    Log in, to see the code


    Jeśli zleciłem jakąś transmisję to mam założony time out po którym jeśli magistrala nie zostaje zwolniona resetuję sprzętowe i2c na sposób taki jak opisałeś. Gdyby to nie pomogło to po drugim timeout'cie mówię "nie ma takiego bicia" i kończę imprezę przerywając egzekucję programu poprzez watchdog reset.
  • #8
    rj1307
    Level 15  
    Co ciekawe, błąd TWI pojawia się tylko przy zapisie do AT24c1024, co ciekawsze - po wystąpieniu błędu i zresetowaniu TWI w atmedze pamięć ta dalej trwa w "zawieszeniu", wystarczy jednak odczytać inny układ na magistrali (np. odczytać czas z PCF8583) i pamięć wraca do życia. Prawdopodobnie robi to warunek STOP.