Forum: Mikrocontroller und Digitale Elektronik STM32F446 Problem mit I2CSlave SDA


von I2CSlave (Gast)


Angehängte Dateien:

Lesenswert?

Hi,
Ich habe ein Problem mit dem FMPI2C des STM32F446.
Der STM ist als I2C slave (NOSTRETCH = 1) an einen anderen µC (RL78) 
angeschlossen. Scheiben vom RL78 zum STM geht.
Beim Lesen gibt es in Abhängigkeit von den vom STM gesendeten Daten ein 
Problem mit der Freigabe der SDA-Leitung.
Im TXIS Interrupt wird das nächste zu sendene Byte eingestellt (da ich 
nicht weiß wieviele Daten vom RL78 abgeholt werden, muss ich das TXDR 
immer befüllen, auch wenn der RL78 kurz darauf ein Stop senden kann).
Ist das bit7 = 1 (Bild I2CSlave_8a.png) und der RL78 möchte die 
Transmission abbrechen, wird das Stop korrekt erzeugt und ich bekomme 
einen Interrupt mit STOPF).
Ist dagegen bit7 = 0 (Bild I2CSlave_4a.png) scheitert das Ausgeben der 
Stop-Sequenz.
Offensichtlich gibt der STM das Bit7 des nächsten Datenbytes schon auf 
den Bus, wodurch die SDA-Leitung auf 0 gehalten wird (ist Bit7 = 1, dann 
stört es SDA nicht). Der STM gibt irgendwann die Leitung durch die in 
Folge gesendeten SCL Takte wieder frei. Diese Takte gehören aber 
eigentlich zur nächsten Transmission (nächste I2C-Adresse), welche 
dadurch verloren geht.

In den Abbildung im RM0390-Reference manual kann man nicht sehen, wann 
der STM die Ausgabe des nächsten Datenbits beginnt.

Ist jemanden so etwas schon mal vorgekommen und kann einen Tipp geben?

Anbei meine STM Interrupt Routine:
Da ist jetzt auch jede Menge Müll drin, um das Problem zu lösen.

Beste Grüße,
Tom
1
void I2CScheduler::EV_IRQHandler_FMPI2C()
2
{
3
  static bool prefilled = false;
4
    bool Ackn=true;
5
    uint8_t sentdata = 0xaa;
6
    uint8_t recdata = 0xaa;
7
    uint16_t stages = prefilled? 0x8000:0x0;
8
9
    if (64 <= IsrBufferIdx) {
10
      IsrBufferIdx = 0;
11
    }
12
    ITFlags   = READ_REG(fmpi2c.Instance->ISR);
13
14
    if (ITFlags & (FMPI2C_FLAG_STOPF | FMPI2C_ISR_NACKF)) {
15
      stages |= 0x1000;
16
        __HAL_FMPI2C_CLEAR_FLAG(&fmpi2c,FMPI2C_FLAG_STOPF | FMPI2C_ISR_NACKF);
17
         I2C_Slave_STOPF();
18
         if (nullptr != pActiveSlave) {
19
             pActiveSlave->HandleI2cEvent(II2CSlave::eStopReceived, m_Address, 0U);
20
         }
21
         pActiveSlave = nullptr;
22
    }
23
24
    if (ITFlags & FMPI2C_FLAG_TCR) {
25
      stages |= 0x2000;
26
        fmpi2c.Instance->CR2 |= 1 << FMPI2C_CR2_NBYTES_Pos;
27
    }
28
29
    if (ITFlags & FMPI2C_FLAG_ADDR) {
30
      stages |= 0x04;
31
        __HAL_FMPI2C_CLEAR_FLAG(&fmpi2c,FMPI2C_FLAG_ADDR);
32
        m_Address = (ITFlags & FMPI2C_ISR_ADDCODE_Msk) >> FMPI2C_ISR_ADDCODE_Pos;
33
        recdata = m_Address;
34
        pActiveSlave = nullptr;
35
      uint16_t stages;
36
      datacount = 2;
37
      prefilled = false;
38
        for (uint8_t i = 0; cMaxSlaves > i; ++i) {
39
            if ( m_Address == Slaves[i].Address) {
40
                pActiveSlave = Slaves[i].pSlave;
41
            }
42
        }
43
        if (nullptr != pActiveSlave) {
44
            Ackn = pActiveSlave->HandleI2cEvent(II2CSlave::eCheckAddress, m_Address, 0U);
45
            Ackn = true;
46
        if (Ackn) {
47
        if(ITFlags & FMPI2C_ISR_DIR) {
48
            stages |= 0x08;
49
           m_I2cState = eTransmit;
50
           if (1 || !prefilled) {
51
             //fmpi2c.Instance->ISR |= FMPI2C_FLAG_TXE;
52
             //__HAL_FMPI2C_CLEAR_FLAG(&fmpi2c, FMPI2C_FLAG_TXE);
53
             __HAL_FMPI2C_ENABLE_IT(&fmpi2c, FMPI2C_IT_TXI );
54
             uint8_t SendData = 0;//pActiveSlave->HandleI2cEvent(II2CSlave::eByteToSend, m_Address, 0U);
55
             SendData = 0x80 | DataGen();
56
             fmpi2c.Instance->TXDR = SendData;
57
             sentdata = SendData;
58
           }
59
        }
60
        else {
61
            stages |= 0x10;
62
           m_I2cState = eReceive;
63
           __HAL_FMPI2C_ENABLE_IT(&fmpi2c, FMPI2C_IT_RXI);
64
             (void)READ_REG(fmpi2c.Instance->RXDR);  // clear rx
65
        }
66
        }
67
       else {
68
          stages |= 0x20;
69
         __HAL_FMPI2C_GENERATE_NACK(&fmpi2c);
70
       }
71
       }
72
       else {
73
           __HAL_FMPI2C_GENERATE_NACK(&fmpi2c);
74
       }
75
    }
76
77
    if (ITFlags & FMPI2C_FLAG_RXNE) {
78
      stages |= 0x40;
79
        uint8_t RecData = READ_REG(fmpi2c.Instance->RXDR);
80
        recdata = RecData;
81
        //if (eReceive == m_I2cState) {
82
        if (nullptr != pActiveSlave) {
83
            Ackn = 1; //pActiveSlave->HandleI2cEvent(II2CSlave::eByteReceived, m_Address, RecData);
84
         // prefill data
85
            prefilled = true;
86
       uint8_t SendData = 0;//pActiveSlave->HandleI2cEvent(II2CSlave::eByteToSend, m_Address, 0U);
87
       SendData = 0x40 | DataGen();
88
       sentdata = SendData;
89
       fmpi2c.Instance->TXDR = SendData;
90
            if (!Ackn) {
91
              __HAL_FMPI2C_GENERATE_NACK(&fmpi2c);
92
            }
93
        }
94
    }
95
    if (ITFlags & (FMPI2C_FLAG_TXIS)) {
96
        uint8_t SendData = 0;
97
//        --datacount;
98
        if (datacount) {
99
      if (eTransmit == m_I2cState) {
100
        if (nullptr != pActiveSlave) {
101
          stages |= 0x82;
102
          //SendData = pActiveSlave->HandleI2cEvent(II2CSlave::eByteToSend, m_Address, 0U);
103
          SendData = DataGen();
104
          fmpi2c.Instance->TXDR = SendData;
105
          sentdata = SendData;
106
        }
107
        else {
108
          stages |= 0x81;
109
          fmpi2c.Instance->TXDR = 0xC0 | DataGen();
110
        }
111
      }
112
      else {
113
        stages |= 0x80;
114
        fmpi2c.Instance->TXDR = 0xB3;
115
      }
116
        }
117
        else {
118
          fmpi2c.Instance->TXDR = 0x12;
119
        }
120
    }
121
122
    if (ITFlags & FMPI2C_ISR_NACKF) {
123
      stages |= 0x100;
124
        __HAL_FMPI2C_CLEAR_FLAG(&fmpi2c, FMPI2C_ISR_NACKF);
125
    }
126
    if (ITFlags & FMPI2C_FLAG_BERR) {
127
      stages |= 0x200;
128
        __HAL_FMPI2C_CLEAR_FLAG(&fmpi2c, FMPI2C_FLAG_BERR);
129
    }
130
    if (ITFlags & FMPI2C_FLAG_ARLO) {
131
      stages |= 0x400;
132
        __HAL_FMPI2C_CLEAR_FLAG(&fmpi2c, FMPI2C_FLAG_ARLO);
133
    }
134
    if (ITFlags & FMPI2C_FLAG_OVR) {
135
      stages |= 0x800;
136
        __HAL_FMPI2C_CLEAR_FLAG(&fmpi2c, FMPI2C_FLAG_OVR);
137
    }
138
    IsrBuffer[IsrBufferIdx].Isr  = ITFlags;
139
    IsrBuffer[IsrBufferIdx].Data = sentdata;
140
    IsrBuffer[IsrBufferIdx].stages = stages;
141
    IsrBuffer[IsrBufferIdx].Rec = recdata;
142
    ++IsrBufferIdx;
143
    // SMBus only: FMPI2C_FLAG_PECERR, FMPI2C_FLAG_TIMEOUT, FMPI2C_FLAG_ALERT
144
}

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.