Linux: Solution de contournement de bogue I2C Broadcom.

Créé le 20 mars 2013  ·  73Commentaires  ·  Source: raspberrypi/linux

Le Broadcom BCM2835 a un bogue (matériel) dans le module I2C.

Le BCM implémente mal le "clock stretching":

Au lieu d'assurer un "hightime" minimum pour l'horloge, le BCM laisse fonctionner l'horloge I2C en interne, et quand il est temps de retourner l'horloge à nouveau, il vérifie si l'horloge est devenue haute ou non, et si elle est basse, il fait un "tronçon d'horloge". Cependant, si juste dans les quelques nanosecondes avant cette vérification, l'esclave libère le signal d'horloge indiquant qu'il est prêt pour une nouvelle horloge, l'impulsion d'horloge peut devenir aussi courte que 40ns. (c'est le plus bas que je puisse mesurer, et c'est bien sûr assez rare). Avec une horloge I2C de 100 kHz (10 microsecondes), les «mauvais» moments pour libérer l'horloge sont espacés de 5 microsecondes.

Mes esclaves nécessitent une impulsion d'horloge d'au moins 500 ns. (ce qui devrait être un facteur dix plus court que ce que le maître devrait générer lorsqu'il est configuré pour un fonctionnement à 100 kHz).

C'est un bug matériel auquel nous ne pouvons pas faire grand-chose pour le moment. (Astuce pour les gars du matériel: au lieu d'implémenter l'étirement de l'horloge de cette manière: inhibez le comptage du compteur CLOCKDIV tant que l'horloge reste basse. Cela allongera probablement l'horloge de quelques horloges rapides à chaque cycle, mais la conformité aux normes s'améliorera considérablement ).

Lorsque cela se produit, le BCM envoie un octet, avec une première impulsion d'horloge très courte. L'esclave ne voit alors pas la première impulsion d'horloge, donc quand à la fin de cet octet il est temps d'acquitter cet octet, l'esclave attend toujours le 8ème bit. Le BCM interprète cela comme un "NAK" et abandonne le transfert I2C. Cependant, à ce moment-là, l'esclave voit sa 8ème impulsion d'horloge et émet un "ACK" (tire la ligne SDA vers le bas). Cela signifie à son tour que le BCM ne peut pas émettre une condition "START" appropriée pour le prochain transfert.

Solution logicielle suggérée pour réduire l'impact de ce bogue matériel: Lorsqu'un transfert est interrompu en raison d'un "NAK" pour un octet, émettez un seul cycle d'horloge supplémentaire avant l'arrêt pour synchroniser l'esclave. Cela doit probablement être fait dans un logiciel.

Cela se produit uniquement dans le "chemin d'erreur" lorsque l'esclave n'acquiert pas d'octet. Il est peut-être préférable de ne faire cela que si ce n'est PAS le premier octet d'un transfert, car le bogue ne peut pas se produire sur le premier octet d'un transfert.

Ce correctif logiciel appartient-il au pilote? Oui. C'est un pilote pour un matériel qui a un bogue. Il est du devoir du pilote de faire fonctionner ce matériel de buggy le mieux possible.

Bug

Commentaire le plus utile

Salut hmf2015,
Ce n'est pas un forum. Ceci est un bug tracker. Cette liste de commentaires traite d'un bogue qui n'est pas lié à vos problèmes. Veuillez discuter de votre problème avec un forum ou un service d'assistance approprié. Encore une fois, nous apprécions votre question: "Peut-être que c'est la même chose? Peut-être que ma description aide à résoudre ce bogue?" mais maintenant nous savons avec certitude que ce que vous voyez n'a aucun rapport, veuillez ne pas «polluer» davantage cette discussion.

Tous les 73 commentaires

Si une solution de contournement dans le pilote permet de mieux fonctionner pour la majorité des utilisateurs, assurez-vous qu'elle doit être incluse.
Avez-vous un patch approprié?

Non pas encore.

1) Je n'ai pas encore exploré le pilote I2C. Il y a environ un an, j'avais l'intention de l'écrire moi-même, mais avant de m'y mettre, quelqu'un d'autre l'avait écrit. Donc, quelqu'un qui connaît déjà ce pilote pourrait être mieux équipé pour le faire dans le cadre d'un projet de cinq minutes. Il me faudrait au moins plusieurs heures pour connaître le chauffeur.
2) Il est avantageux d'en discuter d'abord si vous (et peut-être d'autres) convenez qu'un correctif / solution de contournement est justifié.
3) Je voulais juste documenter cela comme un "todo" que nous ne devons pas oublier ....
4) Peut-être que quelqu'un suggérerait une solution de contournement différente.

Parlant de solutions de contournement: La solution de contournement pourrait également être déclenchée par la ligne SDA toujours faible lorsque nous essayons d'initier une nouvelle transaction. C'est clairement une situation "problématique".

Le cas «ça va mal» peut être rare pour les cas «normaux». De nombreuses personnes auront un module hardware-i2c sur le bus I2C. À l'époque où I2C a été inventé, le «10us» était peut-être un délai «très court» pour que certaines puces gèrent les demandes, donc un allongement de l'horloge était nécessaire. De nos jours, toute implémentation matérielle I2C devrait être capable de gérer le «I2C rapide» encore plus rapidement.

Cela se combine avec la façon dont les gars d'atmosphère ont implémenté leurs modules asynchrones. Au lieu de faire fonctionner le module sur l'horloge externe (esclave i2c ou esclave SPI), le module fonctionne toujours sur l'horloge du processeur. Et il synchronise tous les signaux entrants en les faisant passer à travers un tas de filpflops. Bonne conception matérielle. L'alternative est meilleure IMHO: exécutez le module hors de l'horloge externe, et synchronisez lorsque les données passent à l'autre domaine d'horloge (cpu-). Cela permettrait par exemple au module SPI de fonctionner à 20 MHz, même si le processeur ne tourne qu'à 8.

En tous cas. Assez de décousu matériel.

Solution de contournement suggérée: émettez un cycle d'horloge supplémentaire lorsque, au début d'une transaction, la ligne SDA est toujours faible. (il devrait commencer haut pour pouvoir émettre une condition de «démarrage»).

Premièrement, je connais peu I2C. J'ai parlé à Gert et à d'autres de solutions de contournement.

Il existe deux problèmes connus avec I2C:

  1. Le problème d'étirement de l'horloge que vous avez décrit
  2. Problème avec la machine d'état I2C lors du redémarrage

Pour 1, l'opinion de Gert est qu'il n'y a pas de solution de contournement infaillible.
Si l'esclave I2C ne prend pas en charge l'étirement d'horloge, tout va bien.
Si l'horloge I2C s'étire d'une quantité limitée, abaisser la fréquence d'horloge I2C peut éviter le problème
Passer à un pilote un peu percutant pour les esclaves qui ne tombent pas dans les cas précédents est une solution de contournement sûre.

Je ne sais pas si votre proposition fonctionnera. Je serais intéressé de savoir si cela réduit le problème ou le résout complètement.

Gert dit qu'il a une description du bogue qu'il essaiera de libérer.

Pour 2, dans le pilote GPU I2C, nous avons du code qui contournait un problème avec la machine à états:

/***********************************************************
 * Name: i2c_actual_read
 *
 * Arguments:
 *       const I2C_PERIPH_SETUP_T *periph_setup,
         const uint32_t sub_address,
         const uint32_t data_to_read_in_bytes,
         void *data
 *
 * Description: Routine to actually transfer data to the I2C peripheral
 *
 * Returns: int == 0 is success, all other values are failures
 *
 ***********************************************************/
static int32_t i2c_actual_read(  const I2C_PERIPH_SETUP_T *periph_setup,
                                 const I2C_USER_T *user,
                                 const uint32_t sub_address,
                                 const uint32_t read_nbytes,
                                 void *data,
                                 const int using_interrupt)
{
   int32_t rc = -1; /* Fail by default */
   int32_t status = 0;
   int32_t nbytes;

   uint32_t sub;
   uint8_t* read_data = (uint8_t*)data;
   uint32_t data_read = 0;

   if( NULL != periph_setup && NULL != data ) {

      // confirm that the latch is held for this transaction
      assert( i2c_state.periph_latch[ periph_setup->port ] != rtos_latch_unlocked() );

      // -> START
      // -> Slave device address | WRITE
      // <- Ack
      // -> Sub address
      // <- Ack
      // -> Sub address
      // <- Ack
      // -> ReSTART
      // -> Slave device address | READ
      // <- Ack
      // <- Data[0]
      // -> Ack
      // <- Data[1]
      // -> nAck
      // -> STOP

      I2CC_x( periph_setup->port )     = I2CC_EN | I2CC_CLEAR; /* Enable I2C and clear FIFO */
      I2CS_x( periph_setup->port )     = I2CS_ERR | I2CS_DONE | I2CS_CLKT; /* clear ERROR and DONE bits */
      I2CA_x( periph_setup->port )     = periph_setup->device_address;

      sub = sub_address;
      nbytes = periph_setup->sub_address_size_in_bytes;

      if( 0 == nbytes ) {
         /* No subaddress to send - just issue the read */
      } else {
         /*
           See i2c.v: The I2C peripheral samples the values for rw_bit and xfer_count in the IDLE state if start is set.

           We want to generate a ReSTART not a STOP at the end of the TX phase. In order to do that we must
           ensure the state machine goes RACK1 -> RACK2 -> SRSTRT1 (not RACK1 -> RACK2 -> SSTOP1). 

           So, in the RACK2 state when (TX) xfer_count==0 we must therefore have already set, ready to be sampled:
           READ ; rw_bit     <= I2CC bit 0   -- must be "read"
           ST;    start      <= I2CC bit 7   -- must be "Go" in order to not issue STOP
           DLEN;  xfer_count <= I2CDLEN      -- must be equal to our read amount

           The plan to do this is:
           1. Start the sub-add]ress write, but don't let it finish (keep xfer_count > 0)
           2. Populate READ, DLEN and ST in preparation for ReSTART read sequence
           3. Let TX finish (write the rest of the data)
           4. Read back data as it arrives

         */
         assert( nbytes <= 16 );
         I2CDLEN_x( periph_setup->port )  = nbytes;
         I2CC_x( periph_setup->port )    |= I2CC_EN | I2CC_START; /* Begin, latch the WRITE and TX xfer_count values */

         /* Wait for us to leave the idle state */
         while( 0 == ( I2CS_x(periph_setup->port) & (I2CS_TA|I2CS_ERR) ) ) {
            _nop();
         }
      }

      /* Now we can set up the parameters for the read - they don't get considered until the TX xfer_count==0 */
      I2CDLEN_x( periph_setup->port )  = read_nbytes;
      I2CC_x( periph_setup->port )     |= I2CC_EN | I2CC_START | I2CC_READ;

      /* Let the TX complete by providing the sub-address */
      while( nbytes-- ) {
         I2CFIFO_x( periph_setup->port ) = sub & 0xFF; /* No need to check FIFO fullness as sub-address <= 16 bytes long */
         sub >>= 8;
      }

      /* We now care that the transmit portion has completed; the FIFO is shared and we mustn't read out
         any of the data we were planning on writing to the slave! */

      /* Wait for peripheral to get to IDLE or one of the two RX states - this way we *know* TX has completed or hit an error */
      {
         uint32_t state;
         bool_t state_transition_complete;
         bool_t error_detected;
         do { 
            state = (I2CS_x( periph_setup->port ) & 0xf0000000) >> 28;
            state_transition_complete = ((state == 0) || (state == 4) || (state == 5));
            error_detected = (I2CS_x(periph_setup->port) & (I2CS_ERR | I2CS_CLKT)) != 0;
         } while(!state_transition_complete && !error_detected);

         if (error_detected) {
            /* Clean up, and disable I2C */
            I2CC_x( periph_setup->port ) &= ~(I2CC_INTD | I2CC_INTR);
            I2CC_x( periph_setup->port ) &= ~(I2CC_START | I2CC_READ);
            I2CS_x( periph_setup->port ) = I2CS_CLKT | I2CS_ERR | I2CS_DONE;
            I2CC_x( periph_setup->port ) |= I2CC_CLEAR;
            I2CC_x( periph_setup->port ) = 0;
            return -1;
         }
      }

      if (using_interrupt)
      {
         /* Wait for interrupt to complete. */
         i2c_state.active_buffer[periph_setup->port] = data;
         i2c_state.active_buffer_length[periph_setup->port] = read_nbytes;
         i2c_state.active_buffer_offset[periph_setup->port] = 0;
         i2c_state.pending_transfer[periph_setup->port] = I2C_PENDING_TRANSFER_READ;
         RTOS_LATCH_T latch = rtos_latch_locked();
         i2c_state.pending_latch[periph_setup->port] = &latch;

         /* Enable interrupt. */
         I2CC_x( periph_setup->port ) |= I2CC_INTD | I2CC_INTR;

         rtos_latch_get (&latch);

         i2c_state.pending_latch[periph_setup->port] = NULL;
         data_read = i2c_state.active_buffer_offset[periph_setup->port];

         rc = (data_read == read_nbytes) ? 0 : -1;
      }
      else
      {
         uint32_t time_now = 0;

         /* Loop until we've read all our data or failed. */
         while( 0 == ( I2CS_x(periph_setup->port) & (I2CS_TA|I2CS_ERR|I2CS_DONE) ) ) {
            _nop();
         }

         /* Wait for some data to arrive - we should wait, at most, I2C_TIMEOUT_IN_USECS for data to arrive every time we start waiting */
         time_now = i2c_state.systimer_driver->get_time_in_usecs( i2c_state.systimer_handle );
         while( ((i2c_state.systimer_driver->get_time_in_usecs( i2c_state.systimer_handle ) - time_now) < I2C_TIMEOUT_IN_USECS)
                && ( data_read < read_nbytes )
                && !(I2CS_x( periph_setup->port ) & I2CS_ERR) ) 
         {
            if (I2CS_x( periph_setup->port ) & I2CS_RXD) 
            {
               read_data[ data_read ] = I2CFIFO_x( periph_setup->port );
               data_read++;
               time_now = i2c_state.systimer_driver->get_time_in_usecs( i2c_state.systimer_handle  );
            }
         }

         if( (data_read != read_nbytes) /* Did we read all the data we asked for? */
             || ( (read_nbytes - data_read) != I2CDLEN_x( periph_setup->port ) ) /* Has DLEN decremented? */
             || ( 0 != (I2CS_x( periph_setup->port ) & I2CS_ERR) ) ) { /* Are there any errors? */
            rc = -1;
         } else {
            while( I2CS_DONE != (I2CS_x(periph_setup->port) & I2CS_DONE) ); /* Wait for the peripheral */
            rc = 0;
         }
      }

      /* Clean up, and disable I2C */
      I2CC_x( periph_setup->port ) &= ~(I2CC_INTD | I2CC_INTR);
      if(I2CS_x( periph_setup->port ) & I2CS_ERR) {
         //Wait for it to be idle
         while(I2CS_x( periph_setup->port ) & I2CS_TA)
            _nop();
      }
      I2CS_x( periph_setup->port ) = I2CS_ERR | I2CS_DONE;
      //Finally disable the I2C
      I2CC_x( periph_setup->port ) = 0x0;
   }

   if( !user->skip_asserts ) {
      assert( rc >= 0 );
      _nop();
   }

   return rc;
}      

Je ne sais pas si les gens rencontrent ce problème, mais le collage peut être utile si vous l'êtes.

Il n'est pas possible d'éradiquer complètement ce bogue matériel.

Lorsque cela se produit, le maître et l'esclave ne sont pas d'accord sur le nombre de cycles d'horloge. Par conséquent, les données, telles qu'interprétées par l'esclave et les données comme le maître (= raspberry pi = pilote / application) voulues diffèrent. Vous pourriez écrire quelque part une valeur complètement fausse dans un registre. Très ennuyeux.

Ma solution de contournement suggérée ferait au moins fonctionner la prochaine transaction. L'impact serait divisé par deux: une seule transaction bâclée au lieu de deux. Cela n'éliminerait pas le problème.

Si l'esclave I2C ne prend pas en charge l'étirement d'horloge, tout va bien.

Si l'esclave I2C ne nécessite pas d'étirement d'horloge ...

Si l'horloge I2C s'étire d'une quantité limitée, abaisser la fréquence d'horloge I2C peut éviter le problème

Oui. J'ai 10 appareils «sur le terrain» à un seul endroit. Apparemment, la fréquence d'horloge (horloge RC) de trois des modules est différente de telle sorte qu'ils finissent par "fini" avec l'horloge s'étirant exactement au mauvais moment. La réduction de la fréquence d'horloge a résolu les problèmes de ces modules.

Si le délai d'étirement de l'horloge n'est PAS fixe, mais, disons, varie de plus de 5 microsecondes, il y a une chance plus ou moins statistique de rencontrer le problème. Dans mon cas, l'esclave nécessite 0,25 microsecondes de largeur d'horloge. Ainsi, l'étirement de l'horloge se termine dans les 5% du temps menant au moment de changement d'horloge pour le BCM, puis les choses tournent mal. Donc, dans ce cas, environ 1 transfert sur 20 tournerait mal. (les spécifications indiquent min 250ns pour une impulsion d'horloge. En fait, cela ne signifie pas qu'elle ne sera pas vue si elle est plus courte. Je pense que les chances qu'elle soit vue vont linéairement de 100% à> 250ns à 0% à < 125 ns.)

J'ai passé hier à étirer la période d'étirement de l'horloge de manière à ce qu'elle tombe autour de 2,5 microsecondes dans la fenêtre d'opportunité de 5 microsecondes. Si je visais le début de la fenêtre et que mon horloge RC tourne un peu vite, je frapperais le "0" qui déclenche le bogue. Si je vise 5, même chose. Alors maintenant, je vise au milieu, loin des mauvais endroits. Mais changez l'horloge I2C à 80 kHz, et BAM, je vise bien le point sensible ... (et si cela ne se produit pas avec 80 kHz, cela se produira avec une valeur entre 80 et 100).

Voici la description par Gert du bogue I2C:
https://dl.dropbox.com/u/3669512/2835_I2C%20interface.pdf

Haha! J'ai instrumenté ma carte de test exactement de la même manière. J'ai coupé la trace SCL et y ai monté un connecteur de cavalier de 0,1 ". Sans mesurer, il y a un cavalier normal là-bas, ou un connecteur femelle avec une résistance de 100 ohms quand je suis.

Je ne pense pas que cela se produit uniquement à la première horloge. Cela signifierait que je pourrais contourner le problème en NE PAS étirer du tout l'horloge (comme le font probablement la plupart des puces I2C matérielles), ou en faisant durer au moins un cycle complet.

J'ai instrumenté mon code esclave i2c de telle manière que je puisse faire changer l'étirement de l'horloge par incréments de 0,5 microseconde. Je peux lui commander de changer le tronçon d'horloge à XXX sur I2C, puis cela fonctionne comme ça pendant 50 millisecondes avant de revenir aux valeurs par défaut. (au cas où cela ne fonctionnerait pas, nous devons le faire fonctionner à nouveau. De cette façon, je peux analyser rapidement toute une gamme de valeurs pour ces paramètres, tout en surveillant les lignes SDA et SCL avec un analyseur logique. Envoi d'un "use delay XXX", puis l'envoi d'une piqûre prend 25 millisecondes. Ensuite, l'incrémentation d'un compteur dans le script et l'envoi du "prochain délai" prend environ 100 ms au script shell. Je peux donc scanner 100 valeurs possibles en 10 secondes environ.

J'AI vu le bogue se produire sur des retards plus longs. Donc la théorie: "ça n'arrive que sur le premier" n'est pas correcte.

Quant au gestionnaire d'interruptions "super efficace": Oui, je peux le faire aussi. La chose est: la fonction d'étirement de l'horloge me permet de mettre le code "gérer cet octet" dans la routine d'interruption et de ne pas m'inquiéter que cela prenne quelques microsecondes ou quelques millisecondes. En théorie, l'étirement de l'horloge fera en sorte que le maître attend que je finisse de traiter cet octet avant de continuer avec le suivant. Ce plan est totalement anéanti avec le bogue du 2835. Je fais maintenant simplement arrêter l'étirement de l'horloge, puis j'espère finir de gérer l'octet dans les 70 microsecondes qui suivent.

Je dois "compter le cycle" pour viser le milieu de la demi-horloge de 5 microsecondes pour que je libère l'étirement de l'horloge. Si je visais le début (pour provoquer une période d'horloge haute de 4,9 microsecondes), l'horloge de mon esclave pourrait fonctionner quelques pour cent plus vite et provoquer le déclenchement du bogue un demi-cycle plus tôt. Donc, les deux extrémités du cycle de la demi-horloge sont dangereuses, je dois viser un cycle d'horloge court mais suffisamment valide.

Le changement dans le module est simple à mon humble avis: lorsque SCL est "entraîné haut" (c'est-à-dire pas du tout entraîné), arrêtez l'horloge maître du module I2C. Cela a pour effet secondaire d'autoriser des bus I2C beaucoup plus longs car l'étirement automatique de l'horloge se produit lorsque la capacité du bus est supérieure aux spécifications.

Merci d'essayer d'aider, iz8mbw, mais cela n'a rien à voir avec ce bogue (matériel).

J'ai mesuré mon horloge I2C et elle sort à 100 kHz, ce que le pilote pense qu'elle devrait être. Le pilote a un objet "source d'horloge" qu'il interroge pour la fréquence et il l'utilise. Je n'ai pas encore instrumenté mon pilote pour imprimer la fréquence.

Juste pour information pour les personnes qui veulent VOIR le bogue en action, j'ai une «preuve» sous la forme d'un vidage d'analyse logique.
Hmm je peux joindre des images, mais pas le vidage binaire LA. Celui-ci est ici: http://prive.bitwizard.nl/LA_with_bug_scan_50_to_100_microseconds_delay.bin.gz

Dans l'image LA_with_bug_shot1.png vous verrez la courte rafale d'activité: "set delay to XXX" puis une petite rafale qui essaie d'écrire environ 10 octets, mais elle est annulée à cause d'un NACK. Sur la droite, vous voyez un paquet de 10 octets approprié. La ligne SDA reste faible jusqu'à la prochaine rafale qui est mal alignée (tous les bits sont décalés, et dans mon esclave le compteur "xth-byte-in-packet" n'a pas été réinitialisé par la condition de démarrage inexistante au début de ce paquet .

Dans l'image LA_with_bug_shot2.png, j'ai zoomé sur la section où se produit l'impulsion courte. C'est la plus longue impulsion que j'ai vue mal: 290ns. (ci-dessus fiche technique-spec pour l'Atmel!)
LA_with_bug_shot1
LA_with_bug_shot2

Oh alors c'est de là que ça vient!

J'ai un projet que j'essaie de contrôler avec I2C à partir d'un Raspberry Pi et je suis honnêtement sur le point d'abandonner et de passer à un beagleboard ou de faire parler le Pi à un FPGA via SPI qui fait ensuite les choses I2C .

J'ai un tableau dans le courrier qui devrait pouvoir le faire (livraison prévue: demain). Connecteur SPI, connecteur I2C. Ce serait un bon projet à essayer avec ce conseil. Envoyez-moi un e-mail si vous souhaitez être tenu informé.

Situation actuelle: je vois un comportement compatible avec celui de Gert: "seul le premier cycle peut mal tourner" lorsque l'esclave est un ATMEGA, et je vois le bogue en pleine force lorsque l'esclave est l'un de mes ATTINY.

Voici les retards que j'ai testés:
i2c_delays_atmega
et l'impulsion SCL la plus courte observée pendant cette session de test était de 4,5 microsecondes.

Maintenant en test avec l'esclave attiny, les délais testés pour l'ACK sont:
i2c_delays_attiny

et la largeur d'impulsion minimale est de 41ns (ma résolution de mesure):
i2c_delays_attiny2

Ah. Trouvé! Il semble que l'horloge s'étendant avant l'ACK d'un octet soit "dangereux" mais l'étirement de l'horloge APRÈS l'ACK est ok .....

Moi et d'autres sommes certainement confrontés au problème des départs répétés. J'ai un hack de l'espace utilisateur sur http://cpansearch.perl.org/src/MDOOTSON/HiPi-0.26/BCM2835.xs dans proc hipi_i2c_read_register_rs. Cela semble fonctionner pour les utilisateurs qui ont déclaré avoir essayé ou incorporé le code C (bien que ce ne soit que 5 personnes), même si je n'avais pas compris correctement comment déterminer que l'étape TX était terminée. Je suppose que j'ai besoin d'apprendre à compiler les modules du noyau et à exécuter les tests existants contre le code ci-dessus.

Ne pourrions-nous pas simplement forcer le noyau à ignorer le matériel I2C et à utiliser l'I2C basé sur GPIO bitbangé sur les mêmes broches? Je pense que la surcharge pour cela serait plus acceptable que les bogues du matériel lui-même.

Quels frais généraux vous attendez-vous? Le pilote actuel utilise par défaut une horloge de 100 kHz. Ainsi, la lecture de 10 octets à partir d'un capteur d'interface i2c prend environ 1 ms. Si vous bitbang, vous risquez de générer des cycles de processeur tout ce temps ...

Ma préférence serait que le pilote prenne éventuellement en charge le bitbanging i2c via un paramètre de module (ou peut-être un module séparé si cela est plus pratique).

De nombreux périphériques n'utilisent pas d'étirement d'horloge (ou d'étirement d'horloge d'une quantité limitée afin de pouvoir fonctionner correctement à vitesse réduite), le pilote I2C matériel est donc toujours préférable dans ces cas.

Le noyau lui-même a un pilote pour I2C bitbanged sur les broches GPIO, ce pilote a une surcharge beaucoup plus faible que le bitbangging depuis l'espace utilisateur et expose la même API que les pilotes I2C matériels. Ma suggestion serait de compiler à la fois ce pilote et le pilote matériel I2C en tant que modules, puis de charger le pilote matériel par défaut.

@Ferroin
Utilisez-vous le pilote I2C bitbanged sur Pi?
Quelles options .config avez-vous ajoutées pour le construire? Des correctifs source?
Que faites-vous pour choisir le pilote à utiliser (modprobe? Different / dev / devices?)

Je n'ai pas utilisé le pilote sur le Pi, mais j'ai un ami qui l'utilise avec succès sur un BeagleBoard.
L'option de configuration est I2C_GPIO.
Si cela et le pilote Broadcom étaient configurés en tant que modules, le choix du pilote serait aussi simple que de charger le module du noyau.
Le module GPIO a besoin de paramètres pour lui dire quels GPIO utiliser comme SDA et SCL, je ne sais pas quels sont les paramètres, mais sur la base de la source pas très bien documentée dans dirvers / i2c / bus / i2c-gpio.c, il semble que les paramètres appropriés sont 'sda = X scl = Y' où X et Y sont les broches que vous devez utiliser.

Le module i2c-gpio lui-même ne fournit aucun moyen de lui passer des paramètres. Vous avez donc besoin d'un autre module qui enregistre les données de la plate-forme et configure au moins le numéro de bus, les broches SDA et SCL. J'ai écrit une preuve de concept d'un tel module et cela a même fonctionné sur les broches 0 et 1 mais sans i2c-bcm2708 chargé (pcf8574 a été détecté par i2cdetect, j'ai pu piloter des LED avec le module gpio-pcf857x). Mais ensuite, j'ai brûlé mon pcf8574 en changeant les broches (et je n'ai pas d'autres puces i2c pour le moment), donc je ne pouvais pas vraiment le tester. Voici le code

@kadamsi
La création de paramètres de module sda_pin / scl_pin peut être utile. Comme le ferait une pull request.
Quelqu'un peut-il confirmer que cela fonctionne pour eux?

C'est moins trivial qu'il n'y paraît: il s'attend à recevoir une structure de données de plate-forme complètement.

D'un autre côté, la plate-forme ne dicte pas les GPIO que vous allez utiliser aujourd'hui, donc faire le travail pour changer cela semble raisonnable. (normalement, les données de la plate-forme spécifient: "Comment / cet / ordinateur est-il câblé".)

@popcornmix
Je prévois de les rendre configurables, je n'avais tout simplement pas assez de temps hier. J'aimerais aussi qu'il puisse créer plus d'un bus à la fois. Peut-être de manière dynamique, comme les fichiers GPIOS export et unexport sysfs (mais je ne suis pas sûr qu'il soit possible d'annuler proprement l'exportation d'un tel bus)? Oh, et j'ai trouvé un autre pcf8574 et j'ai pu confirmer qu'il fonctionnait bien également sur différentes broches GPIO lorsque des résistances pullup externes sont utilisées. Malheureusement, je n'ai pas d'appareils I²C plus sophistiqués à tester. Alors êtes-vous intéressé à fournir un tel module dans l'arborescence du noyau par défaut?

@kadamski
Je n'ai pas de configuration pour tester des modules comme celui-ci. Cependant, toutes les fonctionnalités matérielles fournies par la puce (comme I2C) devraient avoir des pilotes de noyau pour permettre à plus de personnes de les utiliser. Si le matériel I2C a des bogues qui empêcheront les gens d'utiliser certains périphériques, alors une alternative bitbanging en vaut la peine.

Donc, si vous produisez un nouveau pilote qui semble inoffensif pour les personnes qui ne l'utilisent pas (c'est-à-dire construit en tant que module, et ne fait rien tant qu'il n'est pas chargé) et qu'il y a des preuves (c'est-à-dire des rapports d'utilisateurs confirmant) qu'il fonctionne correctement, alors je suis heureux d'accepter un PR.

Le matériel a-t-il été corrigé sur BCM2837 (dans RPi 3)?

Ma conjecture est: non. Mais je n'ai probablement pas le temps de tester cela aujourd'hui.

BCM2837 I2C est inchangé.

C'est malheureux, mais merci pour l'info.

c'est très ennuyeux.

Je suis d'accord. Quelqu'un a-t-il un lien vers l'errata BCM2837, ou similaire, indiquant que le problème existe toujours? Ce serait pratique lorsque nous devons transmettre les nouvelles. Ou @ P33M , peut-être pouvez-vous être cité comme faisant autorité si vous travaillez pour Broadcom?

Il fait autorité, mais ne travaille pas pour Broadcom.

C'est bon. Mais j'ai déjà cherché sur Google, et à part le fait que P33M soit M33P ailleurs, j'ai du mal à trouver une pièce d'identité que je peux utilement transmettre. Ce qui est bien, mais cela signifie qu'il n'est pas une bonne source à citer. :-) Un lien d'errata serait donc pratique.

@ P33M fonctionne pour Raspberry Pi. Vous pouvez traiter ce qu'il dit comme faisant autorité.

Je ne pense pas qu'il y ait une liste d'errata, devrait probablement l'être. Je l'ai laissé
pour confirmer son identité, ou pas!

Le 15 mars 2016 à 14h30, RalphCorderoy [email protected] a écrit:

C'est bon. Mais j'ai déjà googlé, et à part P33M étant M33P
ailleurs, lutte pour trouver une pièce d'identité que je puisse utilement transmettre. Ce qui est bien,
mais signifie qu'il n'est pas une bonne source à citer. :-) Donc, un lien d'errata serait
pratique.

-
Vous recevez ceci parce que vous avez commenté.
Répondez directement à cet e-mail ou affichez-le sur GitHub:
https://github.com/raspberrypi/linux/issues/254#issuecomment -196845789

@RalphCorderoy Je suis un employé de Raspberry Pi (trading) Ltd. Ma réponse fait autorité.

@ P33M , Ta, ça ira. Désolé pour les tracas.

Cela affecte un projet sur lequel je travaille. Heureusement, j'ai un contrôle complet sur le micrologiciel du périphérique esclave et j'ai pu ajouter une solution de contournement consistant à ajouter un délai supplémentaire d'une demi-période (allongement de l'horloge) dans mes réponses, ce qui évite le mauvais comportement.

Une bonne analyse du problème peut être trouvée sur advamation.com .

Ce matériel est-il défectueux dans l'implémentation I2C de Broadcom ou y a-t-il des ajustements du noyau possibles pour que le matériel se comporte correctement?

Je viens de m'abonner à ce problème car je l'ai également rencontré avec un produit que je développe
qui utilise i2c entre un AVR et Pi. Maintenant, j'ai besoin de le repenser.
Quelqu'un a-t-il utilisé une forme fiable de frappe de bits i2c?

@ mwilliams03 , vous pourriez être intéressé par ce projet , dans lequel j'ai réussi à établir une communication I2C 100 kHz et 400 kHz entre un Raspberry Pi et un AVR. Je ne suis pas un bit-banging, mais plutôt en utilisant le support matériel I2C et en insérant des retards à des points clés. Il s'est avéré que l'AVR est suffisamment lent pour qu'à 400 kHz, aucun délai supplémentaire ne soit nécessaire.

En particulier, voici des informations sur les problèmes I2C . Notez également que le module TWI de l'AVR a un problème empêchant les lectures rapides .

merci @ pdg137 , je l'ai essayé et du premier coup, j'ai obtenu 1,2 million de lectures sans erreur et toujours en cours.

@rewolff semble que ce problème a été résolu. Si tel est le cas, veuillez fermer ce problème.

Et maintenant .... ajoutez un sélecteur de niveau et 40cm de rallonge .. Est-ce que ça marche alors? Il y a de fortes chances que cela cause suffisamment de retard sur le côté "haut" des formes d'onde, et tout d'un coup, le bogue se reproduit.

Autant que je sache, Broadcom et les employés pensent toujours que ce bogue est limité aux 5 PREMIÈRES microsecondes (en fait une demi-heure) après le dernier bit d'un octet. alors juste ajouter 10 microsecondes reportera les choses à deux demi-horloges et il ne devrait y avoir aucun problème. Dans mes tests, je trouve de «mauvais» moments pour arrêter l'horloge qui s'étire toutes les 5 microsecondes.

En raison de la symétrie entre SPI et I2C, il est plus facile dans mon code AVR si le prochain octet de données est "calculé" dans l'interruption "données suivantes" .... (j'expose une interface où la poursuite de la lecture est autorisée, donc un tampon de 16 octets ne suffit pas toujours.).

Je ne suis pas convaincu.

Je rencontre des problèmes avec SMBus entre un Respberry Pi et un ATMEGA 324PA - pourraient-ils être liés à ce problème? https://stackoverflow.com/questions/39274784/talking-smbus-between-raspberr-pi-and-atmega-324pa-avr-not-clock-stretching

Autant que je sache, Broadcom et les employés pensent toujours que ce bogue est limité aux 5 PREMIÈRES microsecondes (en fait une demi-heure) après le dernier bit d'un octet.

@rewolff : Je devrais être d'accord avec les employés de Broadcom. Dans mes tests, avec un Raspberry Pi 3 et un I2C 100 kHz (qui ralentit à 62 kHz lorsque le CPU est étranglé), j'obtiens des résultats similaires à l'

L'animation semble sonore. Cependant, cela ne correspond pas à mon expérience. Peut-être que je devrais organiser un test. Cela peut prendre un certain temps. Il est occupé avec d'autres choses.

Mais si c'était le cas, un simple "usleep (10)" dans ma routine d'interruption (avec un étirement de l'horloge matérielle) ferait normalement l'affaire et empêcherait les choses de se bloquer. Je suis presque sûr que ce n'était pas le cas. :-(

@rewolff : Sur le Raspberry Pi 3, j'ai vu le CPU être étranglé à 600 MHz, résultant en une vitesse I2C par défaut de 62 kHz. Vous devriez donc dormir pendant 17 microsecondes dans l'ISR de votre esclave si l'ISR commence sur le front descendant de SCL. Ou si vous pensez que le processeur pourrait être réduit à moins de 600 MHz, dormez plus longtemps.

Serait-il possible d'inclure le module i2c-gpio-param de @kadamski dans le noyau Raspberry Pi? Je peux confirmer que cette approche semble fonctionner assez bien pour mon application (logiciel AVR esclave I2C) et il est quelque peu fastidieux d'installer les en-têtes requis pour le noyau framboise, donc l'avoir disponible serait génial.

Ce serait également une bonne solution de contournement pour résoudre le bogue HW sous-jacent à tout ce problème.

@onnokort Vous voulez dire comme la superposition i2c-gpio présente dans les noyaux actuels depuis novembre 2015? https://github.com/raspberrypi/linux/blob/rpi-4.4.y/arch/arm/boot/dts/overlays/i2c-gpio-overlay.dts
Depuis le README pour les superpositions:

Name:   i2c-gpio
Info:   Adds support for software i2c controller on gpio pins
Load:   dtoverlay=i2c-gpio,<param>=<val>
Params: i2c_gpio_sda            GPIO used for I2C data (default "23")

        i2c_gpio_scl            GPIO used for I2C clock (default "24")

        i2c_gpio_delay_us       Clock delay in microseconds
                                (default "2" = ~100kHz)

@ 6by9 : Génial, merci, j'ai appris quelque chose de nouveau aujourd'hui. Je n'ai pas encore testé cela, mais oui, cela ressemble exactement à ce que je cherchais (et trouvé dans i2c-gpio-param).

@popcornmix @ 6by9 Cela peut-il être fermé? Cela fait très longtemps, et le truc dt param de ma lecture semble être une option décente.

La solution de contournement recommandée pour les périphériques qui ne fonctionnent certainement pas bien avec notre matériel I2C consiste à utiliser la superposition i2c-gpio, qui bitbash les broches.

Sinon, l'étirement de l'horloge dans la phase ACK d'adresse est pris en charge par le pilote en amont.

Bonjour à tous, j'ai testé aujourd'hui le BNO055 dans le boîtier GY-955 d'Asie de l'Est qui se comporte très mal à 100_000 Hz avec un Pi 2B (BMC2835). Pour les tests, j'ai changé la fréquence du bus I2C de 50_000 à 400_000 Hz et j'ai trouvé des problèmes à 100_000 Hz, mais pour 50_000, 85_000, 115_000 et 125_000Hz le code d'Adafruit (Adafruit_Python_BNO055) fonctionne assez bien avec la connexion I2C, 150_000 Hz semble trop rapide pour le BNO055, ça marche mais les valeurs sont parfois fausses. J'avoue, je n'ai pas testé la fréquence avec un oscilloscope, je n'ai lu que le fichier / sys / class / i2c-adapter / i2c-1 / of_node / clock-frequency, donc une certaine incertitude est laissée ouverte. Maintenant, je commence à implémenter une interface complète avec le BNO055 dans ADA.
Facit: Le bug matériel dans la gestion du BMC I2C n'apparaît qu'à 100_000 Hz, il doit être confirmé.

Juste pour info, le bogue matériel se produit lorsque le périphérique esclave fait un étirement d'horloge et libère la ligne SCL après 0,9 à 0,999 périodes d'horloge I2C. La ligne commencera à monter, et le matériel pi dira: Oh, il n'a pas fait d'étirement d'horloge afin que je puisse fournir la prochaine impulsion d'horloge en tirant à nouveau la ligne d'horloge vers le bas.

Le bogue se produit lorsque le temps restant dans la période d'horloge est suffisant pour que la ligne clk passe le seuil "HIGH" pour la framboise mais pas pour les périphériques esclaves OU lorsque l'esclave a un filtrage de bruit et considère un haut pendant <x% de la cycle d'horloge I2C normal un pépin.

Cela ne se produit pas "seulement à 100 kHz", mais également à de nombreuses autres fréquences, sauf que le temps de réponse du dispositif esclave doit alors être une valeur différente.

Supposons que l'horloge est de 100 kHz, donc un cycle normal serait 5us haut et 5us bas. Supposons maintenant qu'à t = 0, le pi commence le dernier cycle d'horloge en tirant la ligne d'horloge vers le bas. À t = 5us, le pi libère le signal d'horloge, mais l'esclave est toujours occupé et maintient l'horloge à un niveau bas. À t = 9us, l'esclave est terminé et libère le signal d'horloge. À t = 10us, le pi regardera le signal d'horloge et pensera: Ok, pas d'étirement d'horloge, alors continuez, et il ramène le signal d'horloge à un niveau bas. Le signal d'horloge n'a maintenant été élevé que pendant 1us (un peu moins en raison de la capacité et de la constante de temps des résistances pullup) et pourrait ne pas être vu par l'esclave. Maintenant, un autre appareil ne devient pas prêt après 9 microsecondes, mais après 10,5. Maintenant, à 100 kHz, le pi verra "toujours faible, l'horloge s'étire, attendez encore 5 microsecondes. Maintenant, nous aurons une impulsion d'horloge de 4,5 microsecondes et les choses fonctionneront. Mais exécutez cet appareil à 90 kHz, et il a des problèmes. Maintenant, le pi regardera 11 microsecondes depuis le début, et le signal d'horloge aura été élevé pendant moins d'une microseconde -> Problèmes.

Les personnes qui s'en plaignent ne sont PAS celles qui ont ces autres appareils. Ceux-ci fonctionnent à la valeur par défaut de 100 kHz. Mais le bogue est toujours très réel et se produirait sur ces appareils simplement à d'autres vitesses de bus que les appareils que vous et moi avons.

Merci pour la réponse, cela explique très bien, pourquoi j'ai obtenu un transfert fiable aux fréquences que j'ai choisies:
à 100_000 Hz les problèmes se posent dans la période de 9 à 9,99 µsec
à 85_000 Hz, les problèmes commencent à 1_000_000 / 85_000 * .9 = 10,59 µsec> 9,99 sec, donc l'étirement d'horloge est ignoré je suppose, pour toutes les fréquences inférieures à 85_000 Hz, le point de départ des problèmes est supérieur à 10,59 µsec .
à 115_000 Hz, le cycle de bus est 1_000_000 / 125_000 = 8,7 µs <9 µs, donc l'étirement de l'horloge est détecté correctement, pour toutes les fréquences supérieures à 115_000 Hz, le cycle de bus est inférieur à 8,7 µs.
Ainsi, quand j'ai des problèmes, je peux calculer la fréquence dont j'ai besoin.
(J'ai lu les informations sur http://www.advamation.com/knowhow/raspberrypi/rpi-i2c-bug.html,
il a été noté 0,5 au lieu de 0,9 d'une période).

Bien. Cela dépend de ce que votre esclave détecte comme un signal d'horloge valide. Et combien de retard le RC sur votre bus introduit. Dans mon cas, l'AVR que j'utilise en tant qu'esclave considère les impulsions de moins de deux cycles d'horloge comme un problème. Avec une horloge RC interne de 8 MHz (+/- 10% !!!), l'impulsion doit être d'au moins 250 ns pour être détectée. Les spécifications I2C nécessitent 5 microsecondes, il y a donc un facteur de 20 "marge" entre ce qui est officiellement requis et ce qui ne fonctionne plus.

Au début, je pensais augmenter le tronçon d'horloge dans mon esclave produit un peu pour dire 12us. Cela fonctionne jusqu'à ce que la capacité du bus ajoute suffisamment de retard pour provoquer à nouveau un problème. Il est donc très difficile de contourner le problème. Gênant de devoir dire à vos clients de ne pas utiliser le i2c 100kHz standard.

Désolé, mais il me fallait un peu de temps pour écrire une implémentation complète et un scénario de test.
Je vous remercie pour toutes les informations que vous m'avez données, elles ont été très utiles.
Mon scénario de test est constitué de 2 MEMS (BNO055 emballé comme GY-055, MPU9255 emballé comme MPU-9250/6500, registre WHO_AM_I dit MPU9255) et 1 extension GPIO PCF 8574 (emballé PCF 8574).
L'horloge I2C au Pi (2b) a été réglée à 125 kHz, vérifiée en lisant / sys / class / i2c-adapter / i2c-1 / of_node / clock-frequency.
Mon code s'exécute 100 fois en lisant les données du MEMS et en écrivant des données pour PCF avec un délai de 0,1 sec.
Résultat:

  • L'initialisation du MEMS a réussi.
  • La lecture des données MEMS sur le bus I2C a été réussie sur tous les cycles.
  • L'écriture des données sur le PCF via le bus I2C a été réussie sur tous les cycles.

Par conséquent, le MEMS et le PCF acceptent une horloge supérieure à la norme 100 kHz.
Dans un environnement plus ancien, la communication avec l'AVR se fait via une ligne série, dans ma deuxième, la communication se fera via USB, mais ce n'est pas fini, en fait, j'ai trébuché sur les problèmes de bus I2C causés par le BNO055, mais je pense pour mon environnement, j'ai trouvé une solution de contournement pour un Pi 2b et j'espère que cela fonctionnera aussi avec un Pi 3, c'est le prochain test. Et puis je dois intégrer 2 autres MEMS, 1 VL53L0X et 1 BME280, j'espère que cela fonctionnera avec la nouvelle fréquence et que la capacité du bus acceptera tous ces éléments.

Je joue avec ce problème maintenant sur un RPi 3 Model B + et je vois des résultats différents de ceux décrits dans l'article Advamation. Le silicium n'a pas été revu récemment, n'est-ce pas?

La version courte est que les choses semblent fonctionner si je m'étire à read-preACK, write-preACK ou write-postACK; le seul moment où j'ai besoin de m'assurer de m'étirer longtemps ou pas du tout est read-postACK. Cependant, j'ai encore besoin de nettoyer mon expérience avant de pouvoir dire quoi que ce soit de certain.

Tout d'abord, une note sur la terminologie. L'article d'Advamation dit:

Ainsi, I2C avec le Raspberry Pi ne fonctionne que si
l'esclave n'utilise pas du tout d'étirement d'horloge, ou
l'esclave n'étend l'horloge qu'à la fin / directement après une phase I2C-read-ACK (après lecture ACK / NACK), mais ensuite de plus de 0,5 période d'horloge.

Le terme "phase I2C-lecture-ACK" semble quelque peu ambigu. S'il s'agit d'une commande de lecture I2C (c'est-à-dire que le bit R / W̅ de post-adresse est positionné), l'esclave écrirait le bit A̅C̅K,, ne le lirait pas, contrairement à la parenthèse. Quand je dis "read-postACK" ici, je veux dire que le bit R / W̅ a été placé juste après l'adresse (et vraisemblablement pas changé par le protocole comme le fait SMBus), donc l'esclave vient d'écrire sa réponse A̅C̅K..

Comme cela a été suggéré ici, il semble que si le RPi détecte que SCL est maintenu bas par un esclave, il retardera son horloge SCL interne d'un demi-cycle (5 μS). Le bogue est déclenché si l'esclave maintient SCL bas pendant _ presque_ un demi-cycle. Si cela se produit, alors le RPi laissera toujours SCL monter, puis le tirera vers le bas immédiatement après lorsque son horloge SCL se déclenchera. Cela se traduit par une impulsion d'horloge runt, que certains appareils peuvent voir comme une impulsion tandis que d'autres ne le font pas. (Pour référence: la spécification I2C implique un temps SCL élevé nominal de 5 μS et établit un temps minimum de 4,0 μS à 100 kHz, qui est la vitesse par défaut de l'interface I2C du RPi.)

Dans mes expériences, dans les phases read-preACK, write-preACK et write-postACK, le RPi garantirait que le temps maximum SCL élevé qu'il permettrait était de 4 μS environ. Il semblait disposé à repousser son horloge SCL dans ces phases. Je soupçonne que le RPi a échantillonné la ligne SCL peu de temps après l'avoir libérée, et si SCL était encore faible, il repoussait son horloge SCL d'une demi-phase.

Cependant, dans la phase de lecture postACK, j'ai vu que le RPi émettrait des horloges runt (<4 μS, souvent 2 μS ou moins) si la ligne SCL était maintenue basse pendant environ 6 à 9 μS. Je soupçonne que dans cette phase, les ingénieurs de Broadcom suivent un chemin différent qui tente de réduire la probabilité qu'ils devront retarder une demi-phase sur une ligne à haute capacité. Malheureusement - comme nous l'avons vu - cela ne suffit pas.

Par conséquent, mon code actuel doit étirer SCL au-delà d'un demi-cycle dans la phase de lecture-postACK des lectures qui peuvent prendre un certain temps (comme les conversions ADC). Si je ne parviens pas à

Les tests actuels que j'exécute utilisent un PIC16F1619 comme périphérique esclave. Le périphérique esclave utilise une boucle pour étirer l'horloge dans les commandes de lecture et d'écriture, à la fois pré et postACK. La longueur de cette boucle plus la surcharge varie de 3 μS (moins que le temps pendant lequel le RPi maintient le SCL bas) à 90 μS par incréments de 0,35 μS. J'ai un programme Python sur le RPi qui va différer les valeurs de deux registres, puis les relire et affirmer que les valeurs de relecture sont correctes. Les valeurs utilisées

Piquan,
Broadcom a minimisé cela en proclamant que ce problème ne se produit que lors du tout premier tronçon d'horloge. Je ne pense pas que ce soit le cas. Vous devriez pouvoir le vérifier. Advamation semble suivre les déclarations de Broadcom.

@rewolff Eh bien, il y a peut-être quelque chose dans leur interprétation. Si, par «premier tronçon d'horloge», ils signifient «la première fois dans une étape donnée que SCL est étiré par plus d'une translation d'horloge» alors leur description est exacte: si vous étirez de plus d'un cycle d'horloge, alors oui: en tout phases, si vous étirez par> 0,5 cycle, vous êtes en bonne forme. Du moins, dans les vagues expériences que j'ai faites jusqu'à présent; des expériences plus précises sont encore à venir.

Je suis heureux de mener de meilleures expériences pour démontrer quand l'I2C du RPi peut et ne peut pas gérer les étirements d'horloge, et obtenir des repros que BCM peut envoyer aux ingénieurs.

Malheureusement, il y a un très important régime de silicium dont ils auraient besoin pour résoudre ce problème; ils n'ont pas besoin de cocher l'horloge du diviseur SCL lorsque SCL est maintenu bas (par une source interne ou externe). Cela nécessitera probablement un changement au niveau du silicium, ce qui est coûteux; la plupart des ECO sont au niveau du métal, ce qui est… enfin, pas bon marché, mais bien moins cher que le silicium.

Mon objectif principal ici est de caractériser les types d'esclaves qui fonctionneraient et ne fonctionneraient pas avec le RPi, avec quelques preuves expérimentales.

Il semble que nous ayons besoin de données plus solides, telles que des scénarios de repro, pour convaincre Broadcom de repenser le contrôleur I2C. Même avec des données solides, les ingénieurs devront convaincre la direction qu'il vaut la peine de réviser le silicium pour la prochaine révision.

Cela dit, je consacrerai du temps à la conception de scénarios reproductibles afin que les ingénieurs de BCM puissent clairement voir et tester le problème. Je vais cependant dépendre des membres de la communauté ici pour communiquer mes conclusions à Broadcom; Je n'ai pas de chaîne pour eux.

Je devrais clarifier quelque chose à propos de mon commentaire précédent pour la communauté, sur les changements silicium vs métal.

Vous savez comment, si vous obtenez une carte de SparkFun ou d'Adafruit, elle a souvent des traces que vous pouvez couper ou souder ensemble pour changer son comportement? La plupart des cartes I2C ont des traces que vous pouvez modifier pour changer l'adresse, activer ou désactiver les résistances de rappel, etc.

Les concepteurs de Microchip font la même chose. Ils peuvent apporter de nombreux changements aux couches métalliques d'une micropuce, afin de ne pas avoir à changer les couches de silicium. C'est parce que changer les couches de silicium est difficile et coûteux (comme changer la puce sur une carte), tandis que les couches métalliques sont beaucoup plus faciles à changer (comme changer les traces sur une carte).

De nombreux changements utiles peuvent être apportés aux couches métalliques, car les concepteurs réfléchissent à l'avance et établissent des connexions métalliques (cavaliers, essentiellement) qui modifient le comportement d'une puce.

Mais s'il y a un changement qu'ils n'ont pas prévu et ne peuvent pas comprendre comment faire en redirigeant les traces dans la puce, ils doivent alors changer le silicium. Le silicium a besoin de beaucoup plus de planification, de vérification et de masquage, il est donc difficile de changer.

De nombreuses entreprises, si elles ont une couche de silicium «assez bonne», l'utiliseront le plus longtemps possible. Ils réutiliseront certaines parties de la couche de silicium dans plusieurs révisions de la puce.

Je soupçonne que c'est là que BCM en est: ils ont besoin de bonnes preuves que ce bogue ne peut pas être corrigé dans les pilotes ou le métal avant de pouvoir justifier la réingénierie de cette partie de la couche de silicium à partir de zéro.

Il est extrêmement improbable qu'il y ait un retour du silicium existant juste pour résoudre ce problème (vous avez 1 million de dollars de réserve?). Les futures puces pourraient bien avoir un correctif, qui sait.

Le mercredi 05 septembre 2018 à 02:13:19 -0700, Joel Ray Holveck a écrit:

Il semble que nous ayons besoin de données plus solides, telles que des scénarios de repro, pour
convaincre Broadcom de repenser le contrôleur I2C. Même avec
des données solides, les ingénieurs devront convaincre la direction que
cela vaut la peine de réviser le silicium pour la prochaine révision.

Ils ont déjà eu six ans et 3 révisions de silicium où ils
ont démontré leur décision: "ne réparera pas".

si vous vous étirez d'un cycle> 0,5, vous êtes en forme.

Je ne pense pas. Chaque fois que vous relâchez CLK dans le "juste avant le
Broadcom regarde à nouveau "période de temps, vous obtenez des impulsions courtes. Je peux facilement
retarder la libération du signal d'horloge de 5 microsecondes inutiles pour
être toujours en dehors du cycle 0,5. Mais ça n'a pas marché.

Le mercredi 05 septembre 2018 à 02:28:53 -0700, James Hughes a écrit:

Il est extrêmement improbable qu'il y ait une réaction de la
silicium existant juste pour résoudre ce problème (vous avez 1 million de dollars de réserve?). Avenir
les puces peuvent bien avoir la solution.

J'en doute. Nous sommes passés du BCM2835 avec bug CONNU au BCM2836 avec
le même bug sur le BCM2837 avec exactement le même bug sur le BCM2837B0.

Maintenant, pourquoi pensez-vous que la prochaine révision sera différente?

BCM a un marché cible: les téléphones et les clés TV pour ces puces. Dans
leur marché cible, personne ne fait de logiciel-I2C à usage général
microcontrôleurs comme les AVR et les PIC. ils ne vont PAS résoudre ce problème.

Il est dommage que cet effort d’enquête soit nécessaire, aussi formidable soit-il. Quand j'ai demandé auparavant un erratum qui couvre cela, on pensait qu'il n'y en avait pas. Cela a-t-il changé et il y a une URL? Idéalement, Broadcom aiderait la communauté en décrivant précisément le défaut et quand il se produit, des solutions de contournement ou des évaluations de composants compatibles seraient plus faciles à élaborer en toute confiance. Même dans la mesure de l'extrait de HDL pertinent s'ils ne veulent pas essayer de traduire cela avec précision en une description.

La suggestion d'arrêter le diviseur d'horloge demi-bit lorsque vous autorisez l'étirement d'horloge est bonne. Cela marcherait.

Le problème avec cela est qu'une partie du module I2C devrait alors fonctionner à "pleine vitesse d'horloge". Maintenant, le module I2C est un bon module de faible puissance car il ne fonctionne normalement pas plus vite que 200 kHz.

La raison principale de mon message était ce que j'ai dit au début de mon message d'origine :

Je joue avec ce problème maintenant sur un RPi 3 Model B + et je vois des résultats différents de ceux décrits dans l'article Advamation. Le silicium n'a pas été revu récemment, n'est-ce pas?

Si nous avons eu des changements significatifs sur le matériel ou le pilote I2C après la rédaction d'Advamation 2013 et que la communauté sait comment ils peuvent affecter ce bogue, alors je devrais apporter les modifications appropriées à mes expériences.

Je sais que le problème fondamental est dans le matériel, mais pour autant que je sache, quelqu'un peut avoir trouvé par expérience que changer un registre apparemment sans rapport dans le pilote modifie en fait le comportement de ce bogue. Je n'ai pas non plus confirmé que le BCM2837 avait le même module I2C que le RPi 2 (la dernière fois que j'ai pu trouver la confirmation définitive que le matériel I2C était inchangé depuis que ce problème a été signalé pour la première fois). Je n'ai pas non plus trouvé d'informations sur l'un des steppings BCM283x; pour tout ce que je sais, il aurait pu y avoir un changement de métal à l'ère BCM2836.

Je ne suis pas intéressé à dénigrer Broadcom, à spéculer sur la façon dont ils pourraient changer les futures révisions, ou quelque chose du genre.

Mon objectif principal ici est de documenter clairement le comportement actuel; il semble que cela ait changé avec le temps. J'ai un objectif secondaire de permettre aux futurs utilisateurs de reproduire mes expériences pour voir si les résultats sont toujours valides, ou d'apporter des améliorations ou de tester d'autres conditions. J'ai un autre objectif secondaire: permettre aux ingénieurs de Broadcom de reproduire facilement les tests s'ils le souhaitent. Ces deux éléments signifient que je dois publier mes expériences, ce qui aide aussi: à cause de mon propre orgueil , si je publie mes expériences, je serai plus poussé à les rendre rigoureuses.

Mon plan expérimental actuel est d'utiliser un PIC16F1619 comme implémentation esclave; il est assez rapide et polyvalent pour faire des expériences d'étirement d'horloge, assez facile à utiliser et assez courant pour que d'autres expérimentateurs puissent reproduire mes résultats. Si les résultats sont ambigus, je pourrais aussi construire une expérience avec un FPGA. Je verrai peut-être si je peux obtenir une granularité raisonnable en utilisant un autre Raspberry Pi dans une configuration peu gourmande en tant qu'esclave, mais je suppose que j'aurai besoin de quelque chose sans un système d'exploitation complet pour faire des tests en temps réel.

Pour aborder quelques autres choses qui ont été soulevées:

Désolé que mon message original soit incomplet; J'ai accidentellement posté un premier brouillon. Je vais le laisser tel quel, car les modifications que j'ai apportées sont assez mineures.

Je ne revendique pas d'originalité sur l'idée d'arrêter le diviseur d'horloge alors que SCL était maintenu bas extérieurement. J'ai lu ça ailleurs, mais je ne me souviens pas où; Je pensais que c'était de Gert van Loo dans le fil d'étirement d'horloge I2C sur raspberrypi.org , mais je ne peux pas le trouver maintenant, donc j'ai dû le voir ailleurs. Je ne suis pas convaincu que cela changerait le profil de puissance de manière significative,

Le bloc I2C HW n'a pas été corrigé / changé, et il est peu probable qu'il le soit, dans le bcm2835 / 6/7 car cela nécessiterait des répétitions de la puce qui est tout simplement beaucoup trop chère.

Je ne sais pas qui sont Advamation, mais ils ne sont pas accordés au groupe RPF (T), donc je ne peux pas garantir l'exactitude des articles.

Bonjour à tous, j'ai un phénomène très étrange sur mes Pi 2B et 3, j'essaie d'expliquer:
quand j'ai commencé à implémenter le BNO055 fin juin, j'ai utilisé un ancien Raspbian (je n'ai pas maintenant la version) et j'ai eu beaucoup d'adresses I2C invalides en utilisant i2cdetect. Pour cela j'ai regardé sur le net et j'ai trouvé ce forum avec de bonnes informations. Pour cela j'ai changé la fréquence I2C comme décrit ci-dessus et tous les fantômes disparaissent et je peux travailler. Mi-août, j'ai mis à jour Raspbian vers je pense que raspbi-dev 4.14.62-v7 + et le système est devenu un peu instable, mais je peux travailler. De la mise à jour à la mise à jour, le système est devenu plus instable, ont noté des fuites sur la carte SD. Par conséquent, j'ai réinstallé Raspbian via NOOBS (Linux raspbi-dev 4.14.62-v7 + # 1134 SMP mar 14 août 17:10:10 BST 2018 armv7l) et j'ai oublié de régler la fréquence I2C mais aucun fantôme n'est apparu. D'accord, je n'utilise pas de microkontroller sur le bus, seulement des extensions MEMS et GPIO, mais je pense qu'il existe une solution de contournement dans le code i2c de Raspbian. De plus, je pense que les fuites détectées proviennent d'une mise à niveau imparfaite, j'utilise la même carte et aucune fuite n'est détectée.

@ hmf2015 Ce problème concerne un problème I2C très spécifique. Les problèmes avec la carte SD ne sont pas causés par ce problème I2C. Si votre carte SD ne fonctionne pas correctement, vous devriez essayer une nouvelle carte SD. Certaines cartes ne sont pas bonnes et cessent de fonctionner rapidement. Ma carte SD a cessé de fonctionner le mois dernier et j'ai dû la remplacer.

Habituellement, les fantômes I2C ne sont pas à cause de ce problème. Ils surviennent le plus souvent parce que:

  • Vous n'avez pas une bonne alimentation électrique. J'aime celui-ci .
  • Vos câbles sont trop longs. I2C ne fonctionne pas bien avec des câbles de plus de 1 m.
  • Vos câbles ont un couplage capacitif. Si vous avez les broches I2C (SCL et SDA) torsadées ensemble, cela peut poser un problème. Parfois, les gens utilisent des câbles à paires torsadées (comme des câbles Ethernet) qui tordent les broches I2C, et cela pose des problèmes. Si vous devez utiliser des câbles à paires torsadées, torsadez SCL avec Vss (masse) et SDA avec Vdd (3,3 V). Regardez la spécification I2C dans la section 7.5.
  • Votre appareil I2C a 5V. Le Raspberry Pi effectue des E / S à 3,3 V. Si les tensions sont différentes, cela peut poser des problèmes. (Le BNO055 a besoin de 3,3 V, donc si vous l'utilisez avec 5 V, vous avez un problème.)

J'ai dit que nous parlions d'un problème particulier. Certains périphériques peuvent créer des fantômes à cause de ce problème, mais peu de périphériques. Si les appareils créent des fantômes à cause de ce problème, ils ne produisent pas beaucoup de fantômes. Je pense que votre problème est différent.

Je ne sais pas ce que vous voulez dire quand vous dites que vous avez "noté des fuites sur la carte SD". C'est un problème important, mais ce n'est pas un problème dont nous parlons dans le numéro de cette page Web. Cette conversation concerne un bug particulier. Ce bogue n'affecte pas les cartes SD.

Je ne pense pas que le récent Raspbian ait changé le fonctionnement d'I2C. Nous pensons que Raspbian ne peut pas corriger ce bogue. Nous avons peut-être tort. Merci de nous en parler.

Si vous ne nous communiquez ces informations que pour nous aider, nous vous en remercions. Si vous nous donnez ces informations pour demander de l'aide, vous voudrez peut-être demander sur les forums Raspberry Pi . Les forums parlent de beaucoup de choses, comme I2C, les cartes SD, les extendeurs GPIO et bien d'autres choses. Les choses que vous voyez peuvent être les mêmes dont nous parlons, mais elles peuvent être différentes. Les personnes présentes sur les forums peuvent vous aider à connaître les problèmes que vous rencontrez.

Merci de nous avoir communiqué ces informations!

Merci pour la réponse, mais le problème de la carte SD a été produit par l'O / S, j'ai vérifié la carte sur mon hôte (Unix), et c'était ok, et maintenant le même cad fonctionne parfaitement après une nouvelle installation.
Les fantômes sur le bus I2C disparaissent à une fréquence plus élevée et maintenant, après la réinstallation, ils n'apparaissent pas, problèmes R / C et réflexions que je peux, je pense, exclure. Je connais les problèmes de 3,3 V, mais le niveau minimal 1 est inférieur.
Le boîtier BNO055 dispose d'un régulateur de tension.
Je pensais aussi que les problèmes d'I2C seraient les mêmes qu'avant, mais ce n'est pas le cas, pour le moment je n'ai pas le temps (et l'intérêt) de regarder dans le code source de Raspbian pour détecter les différences, ça m'intéresse sur un environnement de travail.
La liste des éléments doit seulement montrer que je travaille dans un environnement Andoid (avec un vrai Unix) comme le supporte BCM, pas avec un microcontrôleur ce que je connecte via une ligne série ou USB depuis que je suis paresseux. Dans votre environnement, les conditions sont plus restrictives que les miennes, donc je ne peux pas dire si vos problèmes diminuent, mais j'espère.

Salut hmf2015,
Ce n'est pas un forum. Ceci est un bug tracker. Cette liste de commentaires traite d'un bogue qui n'est pas lié à vos problèmes. Veuillez discuter de votre problème avec un forum ou un service d'assistance approprié. Encore une fois, nous apprécions votre question: "Peut-être que c'est la même chose? Peut-être que ma description aide à résoudre ce bogue?" mais maintenant nous savons avec certitude que ce que vous voyez n'a aucun rapport, veuillez ne pas «polluer» davantage cette discussion.

@popcornmix
salut, il y a longtemps, vous avez mentionné un problème avec la machine d'état I2C lors du redémarrage et posté du code concernant ce problème.
Je ne suis pas sûr de ce que vous vouliez dire, mais j'ai un problème avec le codec WM8731 connecté à I2C.
Après 2-3 redémarrages, le bus I2C raccroche complètement. i2cdetect n'affiche aucune information sauf la 1ère ligne et raccroche aussi. La seule façon de récupérer est le cycle de mise hors / sous tension.
Cela ressemble-t-il à un problème que vous avez mentionné?
J'utilise le noyau principal 4.19.

@ sergey-suloev Quand i2cdetect ne continue pas à scanner après 8 ou 16 adresses, je dirais que cela n'a aucun rapport avec ce problème. Le problème survient lorsque les appareils effectuent un étirement d'horloge pour indiquer qu'ils ne sont pas encore prêts pour le prochain cycle d'horloge. Lorsque I2C a été conçu il y a près de 40 ans, cela aurait pu être également envisageable pour les implémentations matérielles. Mais de nos jours, le matériel est toujours prêt à temps pour gérer le prochain cycle d'horloge, car 10 microsecondes sont des siècles pour quelque chose d'implémenté dans le matériel.

Cette page vous a été utile?
0 / 5 - 0 notes