Linux: Solusi bug I2C Broadcom.

Dibuat pada 20 Mar 2013  ·  73Komentar  ·  Sumber: raspberrypi/linux

Broadcom BCM2835 memiliki bug (perangkat keras) di modul I2C.

BCM mengimplementasikan "clock stretching" dengan cara yang buruk:

Alih-alih memastikan "waktu tunggu" minimum untuk jam, BCM membiarkan jam I2C berjalan secara internal, dan ketika waktunya untuk membalik jam lagi, ia memeriksa apakah jam telah menjadi tinggi atau tidak, dan jika rendah, itu melakukan "peregangan jam". Namun jika hanya dalam beberapa nanodetik sebelum pemeriksaan ini budak melepaskan sinyal jam yang menunjukkan siap untuk jam baru, pulsa jam mungkin menjadi sesingkat 40ns. (itu paling rendah yang bisa saya ukur, dan tentu saja itu sangat jarang). Dengan jam I2C 100kHz (10 mikrodetik), momen "buruk" untuk melepaskan jam berjarak 5 mikrodetik.

Budak saya membutuhkan pulsa clock minimal 500ns. (yang harus menjadi faktor sepuluh lebih pendek dari yang seharusnya dihasilkan master ketika dikonfigurasi untuk operasi 100kHz).

Itu adalah bug perangkat keras yang tidak dapat kami lakukan saat ini. (Tip untuk orang-orang perangkat keras: alih-alih menerapkan peregangan jam dengan cara ini: hentikan penghitungan penghitung CLOCKDIV saat jam tetap rendah. Ini mungkin akan memperpanjang beberapa jam cepat pada setiap siklus, tetapi kesesuaian standar akan meningkat secara substansial ).

Ketika ini terjadi, BCM akan mengirim byte, dengan pulsa clock pertama yang sangat singkat. Slave kemudian tidak melihat pulsa clock pertama, jadi ketika pada akhir byte itu waktunya untuk ACK byte itu, slave masih menunggu bit ke-8. BCM menafsirkan ini sebagai "NAK" dan membatalkan transfer I2C. Namun pada saat itu budak melihat pulsa clock ke-8 dan mengeluarkan "ACK" (Menarik garis SDA rendah). Ini pada gilirannya berarti bahwa BCM tidak dapat mengeluarkan kondisi "MULAI" yang sesuai untuk transfer berikutnya.

Solusi perangkat lunak yang disarankan untuk mengurangi dampak bug perangkat keras ini: Ketika transfer dibatalkan karena "NAK" untuk satu byte, keluarkan satu siklus jam ekstra sebelum STOP untuk menyinkronkan budak. Ini mungkin harus dilakukan dalam perangkat lunak.

Ini hanya terjadi di "jalur kesalahan" jika budak tidak memberi ACK satu byte. Mungkin yang terbaik adalah melakukan ini hanya jika BUKAN byte pertama dalam transfer, karena bug tidak dapat terjadi pada byte pertama transfer.

Apakah perbaikan perangkat lunak ini milik pengemudi? Iya. Ini adalah driver untuk perangkat keras yang memiliki bug. Adalah tugas pengemudi untuk membuat perangkat keras buggy ini bekerja sebaik mungkin.

Bug

Komentar yang paling membantu

Halo hmf2015,
Ini bukan forum. Ini adalah pelacak bug. Daftar komentar ini membahas bug yang tidak terkait dengan masalah Anda. Silakan diskusikan masalah Anda dengan forum atau helpdesk yang sesuai. Sekali lagi, kami menghargai pertanyaan Anda: "Mungkin sama? Mungkin deskripsi saya membantu mengatasi bug itu?" tapi sekarang kami tahu pasti bahwa apa yang Anda lihat tidak ada hubungannya, mohon jangan "mencemari" diskusi ini lebih lanjut.

Semua 73 komentar

Jika solusi dalam driver membuatnya bekerja lebih baik untuk sebagian besar pengguna, maka itu harus disertakan.
Apakah Anda memiliki tambalan yang cocok?

Tidak, belum.

1) Saya belum mempelajari driver I2C. Sekitar setahun yang lalu, saya memiliki rencana untuk menulisnya sendiri tetapi sebelum saya melakukannya, orang lain telah menulisnya. Jadi seseorang yang sudah mengetahui pengemudi ini mungkin lebih siap untuk melakukan ini sebagai proyek lima menit. Perlu waktu setidaknya beberapa jam untuk mengenal pengemudi itu.
2) Membahasnya terlebih dahulu jika Anda (dan mungkin orang lain) setuju bahwa perbaikan / solusi diperlukan.
3) Saya hanya ingin mendokumentasikan ini sebagai "rencana" yang tidak boleh kita lupakan ....
4) Mungkin seseorang akan menyarankan solusi lain.

Berbicara tentang solusi: Solusi tersebut juga dapat dipicu oleh garis SDA yang masih rendah saat kami mencoba untuk memulai transaksi baru. Itu jelas merupakan situasi "masalah".

Kasus "tidak beres" mungkin jarang terjadi untuk kasus "normal". Banyak orang akan memiliki modul hardware-i2c pada bus I2C. Kembali ketika I2C ditemukan, "10us" mungkin merupakan jangka waktu yang "sangat singkat" bagi beberapa chip untuk menangani permintaan, jadi peregangan jam diperlukan. Saat ini setiap implementasi perangkat keras I2C harus dapat menangani "I2C cepat" hingga lebih cepat.

Ini digabungkan dengan cara atmel mengimplementasikan modul asinkron mereka. Alih-alih menjalankan modul pada jam yang disediakan secara eksternal (i2c-slave atau SPI-slave), modul masih berjalan pada jam prosesor. Dan itu menyinkronkan semua sinyal yang masuk dengan melewatkannya melalui sekelompok filpflop. Desain perangkat keras yang bagus. Alternatifnya adalah IMHO lebih baik: jalankan modul dari jam eksternal, dan sinkronkan saat data lolos ke domain jam (cpu-) lainnya. Ini misalnya akan memungkinkan modul SPI berfungsi pada 20MHz, meskipun CPU hanya berjalan pada 8.

Bagaimanapun. Perangkat keras yang cukup bertele-tele.

Solusi yang disarankan: Keluarkan siklus jam tambahan ketika di awal transaksi garis SDA masih rendah. (harus dimulai dari awal yang tinggi untuk dapat mengeluarkan kondisi "mulai").

Pertama, saya tahu sedikit tentang I2C. Saya telah berbicara dengan Gert dan orang lain tentang solusi.

Ada dua masalah dengan I2C yang diketahui:

  1. Masalah peregangan jam yang telah Anda jelaskan
  2. Masalah dengan mesin status I2C saat melakukan restart

Untuk 1, menurut Gert, tidak ada solusi yang sangat mudah.
Jika budak I2C tidak mendukung peregangan jam, Anda baik-baik saja.
Jika jam I2C membentang dengan jumlah yang dibatasi, maka menurunkan frekuensi jam I2C dapat menghindari masalah
Beralih ke driver yang sedikit membenturkan untuk budak yang tidak jatuh dalam kasus sebelumnya adalah solusi yang aman.

Saya tidak tahu apakah proposal Anda akan berhasil. Saya tertarik untuk mendengar apakah ini mengurangi masalah, atau memperbaikinya sepenuhnya.

Gert mengatakan dia memiliki deskripsi bug yang akan dia coba dan dibebaskan.

Untuk 2, di driver GPU I2C kami memiliki beberapa kode yang mengatasi masalah dengan mesin negara:

/***********************************************************
 * 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;
}      

Saya tidak yakin apakah orang-orang mengalami masalah ini, tetapi tempel dapat membantu jika Anda.

Tidak mungkin sepenuhnya memberantas bug perangkat keras ini.

Ketika itu terjadi, master dan slave tidak setuju pada jumlah siklus clock. Oleh karena itu, data, yang diinterpretasikan oleh slave dan data sebagai master (= raspberry pi = driver / aplikasi) yang dimaksudkan berbeda. Anda mungkin menulis nilai yang sepenuhnya palsu di register di suatu tempat. Sangat menyebalkan.

Solusi yang saya sarankan setidaknya akan menyebabkan transaksi berikutnya berfungsi. Dampaknya akan berkurang setengahnya: hanya satu transaksi yang gagal, bukan dua. Itu tidak akan menghilangkan masalah.

Jika budak I2C tidak mendukung peregangan jam, Anda baik-baik saja.

Jika budak I2C tidak membutuhkan peregangan jam ....

Jika jam I2C membentang dengan jumlah yang dibatasi, maka menurunkan frekuensi jam I2C dapat menghindari masalah

Iya. Saya memiliki 10 perangkat "di lapangan" di satu lokasi. Rupanya frekuensi clock (jam RC) dari tiga modul berbeda sedemikian rupa sehingga mereka akhirnya "selesai" dengan jam yang meregang tepat pada saat yang salah. Mengurangi frekuensi clock memperbaiki masalah untuk modul tersebut.

Jika penundaan peregangan jam TIDAK tetap, tetapi, katakanlah, bervariasi lebih dari 5 mikrodetik, ada kemungkinan statistik yang lebih atau kurang untuk mencapai masalah. Dalam kasus saya, slave membutuhkan lebar clock 0,25 mikrodetik. Jadi peregangan jam berakhir di 5% dari waktu menjelang jam perubahan momen untuk BCM, maka ada yang salah. Jadi, dalam kasus ini, sekitar 1 dari 20 transfer akan salah. (spesifikasi mengatakan min 250ns untuk clock pulse. Itu sebenarnya tidak berarti bahwa itu tidak akan terlihat jika lebih pendek. Saya pikir kemungkinan itu terlihat berjalan secara linier dari 100% pada> 250ns menjadi 0% pada < 125ns.)

Saya telah menghabiskan kemarin untuk meregangkan periode peregangan jam sedemikian rupa sehingga akan jatuh di sekitar tanda 2,5 mikrodetik dalam jendela peluang 5 mikrodetik. Jika saya bertujuan untuk memulai jendela dan jam RC saya berjalan agak cepat, saya akan menekan "0" yang memicu bug. Jika saya bertujuan untuk 5, hal yang sama. Jadi sekarang saya membidik di tengah, jauh dari tempat yang buruk. Tapi ubah jam I2C menjadi 80kHz, dan BAM, saya bertujuan tepat untuk titik sensitif ... (dan jika itu tidak terjadi dengan 80kHz, itu akan terjadi dengan nilai antara 80 dan 100).

Berikut penjelasan Gert tentang bug I2C:
https://dl.dropbox.com/u/3669512/2835_I2C%20interface.pdf

Ha ha! Saya telah menginstrumentasi papan tes saya dengan cara yang persis sama. Saya telah memotong jejak SCL dan memasang konektor jumper 0,1 "di sana. Meskipun tidak mengukur, ada jumper normal di sana, atau konektor wanita dengan resistor 100 ohm saat saya menggunakannya.

Saya tidak berpikir itu hanya terjadi pada jam pertama. Itu berarti saya dapat mengatasi masalah dengan BUKAN peregangan jam sama sekali (seperti yang mungkin dilakukan sebagian besar chip I2C perangkat keras), atau dengan menyebabkan peregangan jam berlangsung setidaknya satu siklus penuh.

Saya telah menginstrumentasi kode budak i2c saya sedemikian rupa sehingga saya dapat menyebabkan peregangan jam berubah dengan kenaikan 0,5 mikrodetik. Saya dapat memerintahkannya untuk mengubah peregangan jam ke XXX melalui I2C dan kemudian bekerja seperti itu selama 50 milidetik sebelum mengubah kembali ke nilai default. (jika tidak berhasil, kami memerlukannya berfungsi lagi. Dengan cara ini saya dapat dengan cepat memindai seluruh rentang nilai untuk pengaturan ini, sambil memantau garis SDA dan SCL dengan penganalisis logika. Mengirim "gunakan penundaan XXX" dan kemudian mengirim sengatan membutuhkan waktu 25 milidetik. Kemudian menaikkan penghitung dalam skrip dan mengirim "penundaan berikutnya" membutuhkan skrip shell sekitar 100 md. Jadi saya dapat memindai 100 kemungkinan nilai dalam waktu sekitar 10 detik.

SAYA TELAH melihat bug terjadi pada penundaan yang lebih lama. Jadi teori: "itu hanya terjadi pada yang pertama" tidaklah benar.

Mengenai penangan interupsi "super efisien": Ya, saya juga bisa melakukannya. Masalahnya adalah: Fitur peregangan jam memungkinkan saya untuk meletakkan kode "menangani byte ini" dalam rutinitas interupsi dan tidak khawatir tentang hal itu membutuhkan beberapa mikrodetik atau beberapa milidetik. Secara teori, clock stretching akan memastikan bahwa master menunggu saya menyelesaikan penanganan byte ini sebelum melanjutkan dengan byte berikutnya. Rencana itu benar-benar rusak dengan bug di 2835. Saya sekarang hanya menghentikan peregangan jam, dan kemudian berharap untuk menyelesaikan penanganan byte dalam 70 mikrodetik berikutnya.

Saya harus "menghitung siklus" untuk mengarahkan ke tengah dari setengah jam 5 mikrodetik agar saya melepaskan jam peregangan. Jika saya bertujuan untuk memulai (menyebabkan periode tinggi jam 4,9 mikrodetik), jam pada budak saya mungkin berjalan beberapa persen lebih cepat dan menyebabkan bug memicu setengah siklus lebih awal. Jadi kedua ujung siklus setengah jam itu berbahaya, saya harus membidik siklus jam yang pendek tapi cukup valid.

Perubahan modul IMHO sederhana: Ketika SCL "didorong tinggi" (yaitu tidak didorong sama sekali), hentikan jam master modul I2C. Ini memiliki efek samping yang memungkinkan bus I2C lebih lama karena peregangan jam otomatis terjadi ketika kapasitansi bus di atas spesifikasi.

Terima kasih telah mencoba membantu, iz8mbw, tetapi itu tidak ada hubungannya dengan bug (perangkat keras) ini.

Saya telah mengukur jam I2C saya dan hasilnya 100kHz yang menurut pengemudi seharusnya demikian. Sopir memiliki objek "sumber jam" yang menanyakan frekuensi dan menggunakannya. Saya belum menginstrumentasi driver saya untuk mencetak frekuensi.

Sekadar informasi bagi orang-orang yang ingin MELIHAT bug beraksi, saya punya beberapa "bukti" dalam bentuk logika analsyer dump.
Hmm saya bisa melampirkan gambar, tapi tidak biner LA dump. Yang itu ada di sini: http://prive.bitwizard.nl/LA_with_bug_scan_50_to_100_microseconds_delay.bin.gz

Dalam gambar LA_with_bug_shot1.png Anda akan melihat ledakan singkat aktivitas: "setel penundaan ke XXX" lalu semburan kecil yang mencoba untuk menulis sekitar 10 byte, tetapi dibatalkan karena NACK. Di sebelah kanan Anda melihat paket 10-byte yang tepat. Garis SDA tetap rendah sampai ledakan berikutnya yang tidak sejajar (semua bit digeser, dan pada budak saya penghitung "xth-byte-in-packet" belum diatur ulang oleh kondisi awal yang tidak ada pada awal paket itu .

Pada gambar LA_with_bug_shot2.png saya telah memperbesar ke bagian di mana pulsa pendek terjadi. Ini denyut nadi terpanjang yang pernah saya lihat salah: 290ns. (di atas spesifikasi lembar data untuk Atmel!)
LA_with_bug_shot1
LA_with_bug_shot2

Oh jadi dari situlah asalnya!

Saya punya proyek yang saya coba kendalikan dengan I2C dari raspberry pi dan sejujurnya saya hampir menyerah dan beralih ke beagleboard atau meminta Pi berbicara ke FPGA melalui SPI yang kemudian melakukan hal-hal I2C .

Saya memiliki papan di pos yang seharusnya dapat melakukan itu (pengiriman yang diharapkan: besok). Konektor SPI, konektor I2C. Akan menjadi proyek yang bagus untuk dicoba dengan papan itu. Kirimi saya email jika Anda ingin terus diinformasikan.

Situasi saat ini: Saya melihat perilaku yang kompatibel dengan Gert's: "hanya siklus pertama yang bisa salah" jika slave adalah ATMEGA, dan saya melihat bug dengan kekuatan penuh saat slave adalah salah satu ATTINY saya.

Berikut penundaan yang saya uji:
i2c_delays_atmega
dan denyut SCL terpendek yang diamati selama sesi tes ini adalah 4,5 mikrodetik.

Sekarang pengujian dengan attiny slave, penundaan yang diuji untuk ACK adalah:
i2c_delays_attiny

dan lebar pulsa minimum adalah 41ns (resolusi pengukuran saya):
i2c_delays_attiny2

Ah. Menemukannya! Tampaknya jam peregangan sebelum ACK byte "berbahaya" tetapi jam peregangan SETELAH ACK ok .....

Saya dan yang lainnya pasti mengalami masalah start berulang. Saya memiliki hack userspace di http://cpansearch.perl.org/src/MDOOTSON/HiPi-0.26/BCM2835.xs di proc hipi_i2c_read_register_rs. Ini tampaknya berfungsi untuk pengguna yang telah melaporkan mencobanya atau memasukkan kode C (meskipun itu hanya 5 orang), meskipun saya tidak tahu dengan benar cara menentukan bahwa tahap TX telah selesai. Saya kira saya perlu belajar mengkompilasi modul kernel dan menjalankan tes yang ada terhadap kode di atas.

Tidak bisakah kita memaksa kernel untuk mengabaikan perangkat keras I2C dan menggunakan I2C berbasis GPIO bitbang pada pin yang sama? Saya pikir biaya overhead untuk itu akan lebih dapat diterima daripada bug di perangkat keras itu sendiri.

Overhead apa yang Anda harapkan? Driver saat ini secara default menggunakan clock 100kHz. Jadi membaca 10 byte dari sensor intertial i2c membutuhkan waktu sekitar 1ms. Jika Anda melakukan bitbang, kemungkinan besar Anda akan mengaduk siklus CPU sepanjang waktu ....

Preferensi saya adalah driver untuk secara opsional mendukung bitbanging i2c melalui parameter modul (atau mungkin modul terpisah jika itu lebih nyaman).

Banyak perangkat tidak menggunakan peregangan jam (atau rentang jam dengan jumlah yang dibatasi sehingga dapat bekerja dengan benar pada kecepatan yang lebih rendah), sehingga driver I2C perangkat keras masih lebih disukai dalam kasus tersebut.

Kernel itu sendiri memiliki driver untuk bitbang I2C pada pin GPIO, driver ini memiliki overhead yang jauh lebih rendah daripada bitbangging dari userspace, dan mengekspos API yang sama dengan driver I2C perangkat keras. Saran saya adalah mengkompilasi driver itu dan driver I2C perangkat keras sebagai modul, lalu memuat driver perangkat keras secara default.

@Tokopedia
Apakah Anda menggunakan driver I2C bitbanged di Pi?
Opsi .config apa yang telah Anda tambahkan untuk membuatnya? Ada patch sumber?
Apa yang Anda lakukan untuk memilih driver yang akan digunakan (modprobe? Different / dev / devices?)

Belum menggunakan driver di Pi, tapi saya punya teman yang berhasil menggunakannya di BeagleBoard.
Opsi konfigurasinya adalah I2C_GPIO.
Jika keduanya dan driver broadcom dikonfigurasi sebagai modul, memilih driver akan semudah memuat modul kernel.
Modul GPIO memang membutuhkan parameter untuk memberi tahu GPIO mana yang akan digunakan sebagai SDA dan SCL, saya tidak tahu apa parameternya, tetapi berdasarkan sumber yang tidak terdokumentasi dengan baik di dirvers / i2c / busses / i2c-gpio.c, Sepertinya parameter yang tepat adalah 'sda = X scl = Y' di mana X dan Y adalah pin yang ingin Anda gunakan.

Modul i2c-gpio sendiri tidak menyediakan cara apapun untuk mengirimkan parameter ke sana. Jadi, Anda memerlukan modul lain yang mendaftarkan data platform dan mengkonfigurasi setidaknya nomor bus, pin SDA dan SCL. Saya telah menulis bukti konsep modul semacam itu dan bahkan bekerja pada pin 0 dan 1 tetapi tanpa memuat i2c-bcm2708 (pcf8574 terdeteksi oleh i2cdetect, saya dapat menggerakkan beberapa LED dengan modul gpio-pcf857x). Tapi kemudian saya membakar pcf8574 saya ketika mengganti pin (dan saya tidak memiliki chip i2c lain sekarang) jadi saya tidak bisa benar-benar mengujinya. Ini kodenya

@jamur_kejang
Membuat parameter modul sda_pin / scl_pin mungkin berguna. Seperti halnya permintaan tarik.
Adakah yang bisa memastikan ini bekerja untuk mereka?

Itu tidak sepele dari kelihatannya: Ia mengharapkan untuk diteruskan struktur data platform secara keseluruhan.

Di sisi lain, platform tidak menentukan GPIO mana yang akan Anda gunakan hari ini, jadi melakukan pekerjaan untuk mengubahnya memang terdengar masuk akal. (biasanya data platform menentukan: "Bagaimana / ini / komputer terhubung".)

@tokopedia
Saya berencana untuk membuatnya dapat dikonfigurasi, saya hanya tidak punya cukup waktu kemarin. Saya juga ingin dapat membuat lebih dari satu bus dalam satu waktu. Mungkin dengan cara yang dinamis, seperti file GPIOS export dan unexport sysfs (tapi saya tidak yakin apakah mungkin untuk membatalkan ekspor bus tersebut dengan rapi)? Oh, dan saya menemukan pcf8574 lain dan dapat memastikan bahwa itu bekerja dengan baik juga pada pin GPIO yang berbeda ketika resistor pullup eksternal digunakan. Sayangnya, saya tidak memiliki perangkat I²C yang lebih canggih untuk diuji. Jadi, apakah Anda tertarik untuk menyediakan modul seperti itu di pohon kernel default?

@tokopedia
Saya tidak memiliki pengaturan untuk menguji modul seperti ini. Namun fitur hardware apapun yang disediakan chip (seperti I2C) harus memiliki driver kernel agar lebih banyak orang dapat menggunakannya. Jika perangkat keras I2C memiliki bug yang akan menghentikan orang menggunakan periferal tertentu, maka suara alternatif bitbanging bermanfaat.

Jadi, jika Anda menghasilkan driver baru yang tampak tidak berbahaya bagi orang yang tidak menggunakannya (yaitu dibangun sebagai modul, dan tidak apa-apa sampai dimuat), dan ada beberapa bukti (yaitu beberapa laporan pengguna yang mengonfirmasi) berfungsi dengan benar, maka saya Saya senang menerima PR.

Apakah HW sudah diperbaiki pada BCM2837 (dalam RPi 3)?

Dugaan saya: tidak. Tapi saya mungkin tidak punya waktu untuk menguji hari ini.

BCM2837 I2C tidak berubah.

Itu sangat disayangkan, tapi terima kasih atas informasinya.

itu sangat menjengkelkan.

Saya setuju. Apakah ada yang punya link ke BCM2837 errata, atau serupa, yang menyatakan masalah masih ada? Akan berguna ketika kita harus menyampaikan berita. Atau @ P33M , mungkin Anda bisa dikutip sebagai berwibawa jika Anda bekerja untuk Broadcom?

Dia berwibawa, meskipun tidak bekerja untuk Broadcom.

Itu bagus. Tapi saya sudah mencari di Google, dan selain P33M menjadi M33P di tempat lain, berjuang untuk menemukan ID yang bisa saya teruskan. Tidak apa-apa, tapi berarti dia bukan sumber kutipan yang bagus. :-) Jadi link erata akan berguna.

@ P33M berfungsi untuk Raspberry Pi. Anda dapat memperlakukan apa yang dia katakan sebagai berwibawa.

Saya rasa tidak ada daftar errata, mungkin seharusnya ada. Saya telah meninggalkan dia
untuk mengkonfirmasi identitasnya, atau tidak!

Pada 15 Maret 2016 pukul 14:30, RalphCorderoy [email protected] menulis:

Itu bagus. Tapi saya sudah mencari Google, dan selain P33M adalah M33P
di tempat lain, berjuang untuk menemukan ID yang bisa saya teruskan. Yang mana baik,
tapi berarti dia bukan sumber kutipan yang bagus. :-) Jadi link erata akan menjadi
berguna.

-
Anda menerima ini karena Anda berkomentar.
Balas email ini secara langsung atau lihat di GitHub:
https://github.com/raspberrypi/linux/issues/254#issuecomment -196845789

@RalphCorderoy Saya adalah karyawan Raspberry Pi (perdagangan) Ltd. Jawaban saya berwibawa.

@ P33M , Ta, itu sudah cukup. Maaf merepotkan.

Ini memengaruhi proyek yang sedang saya kerjakan. Untungnya, saya memiliki kendali penuh atas firmware perangkat budak dan saya dapat menambahkan solusi untuk menambahkan penundaan setengah periode tambahan (peregangan jam) dalam tanggapan saya yang melewatkan perilaku buruk.

Analisis masalah yang baik dapat ditemukan di advamation.com .

Apakah perangkat keras ini buruk dalam implementasi I2C Broadcom atau adakah perubahan kernel yang mungkin dilakukan agar perangkat keras berfungsi dengan benar?

Saya baru saja berlangganan masalah ini karena saya juga mengalami ini dengan produk yang saya kembangkan
yang menggunakan i2c antara AVR dan Pi. Sekarang saya perlu memikirkannya kembali.
Adakah yang menggunakan bentuk bit i2c yang dapat diandalkan?

@ mwilliams03 , Anda mungkin tertarik dengan proyek ini , di mana saya berhasil membangun komunikasi I2C 100 kHz dan 400 kHz antara Raspberry Pi dan AVR. Saya tidak menggigit-gigit, tetapi menggunakan dukungan perangkat keras I2C dan memasukkan penundaan pada poin-poin penting. AVR ternyata cukup lambat sehingga pada 400 kHz tidak diperlukan penundaan tambahan.

Secara khusus, berikut adalah informasi tentang masalah I2C . Perhatikan juga bahwa modul TWI AVR memiliki masalah yang mencegah pembacaan cepat .

terima kasih @ pdg137 , saya mencobanya dan pada

@rewolff sepertinya masalah ini telah diselesaikan. Jika itu masalahnya, tutup masalah ini.

Dan sekarang .... tambahkan shifter level dan kabel ekstensi 40cm .. Lalu apakah berfungsi? Kemungkinan hal ini menyebabkan penundaan yang cukup pada sisi "atas" dari bentuk gelombang, dan tiba-tiba, bug menyerang lagi.

Sejauh yang saya tahu, broadcom dan karyawan masih berpikir bahwa bug ini terbatas pada 5 mikrodetik PERTAMA (sebenarnya setengah jam) setelah bit terakhir byte. kemudian hanya menambahkan 10 mikrodetik akan membawa semuanya ke dua setengah jam lebih jauh dan seharusnya tidak ada masalah. Dalam pengujian saya, saya menemukan momen "buruk" untuk menghentikan jam yang meregang setiap 5 mikrodetik.

Karena simetri antara SPI dan I2C, lebih mudah dalam kode AVR saya jika databyte berikutnya "dihitung" dalam interupsi "data berikutnya" .... (Saya mengekspos sebuah antarmuka di mana melanjutkan membaca diperbolehkan, jadi buffer 16 byte tidak selalu cukup.).

Saya tidak yakin.

Saya mengalami masalah dengan SMBus antara Respberry Pi dan ATMEGA 324PA - mungkinkah ini terkait dengan masalah ini? https://stackoverflow.com/questions/39274784/talking-smbus-between-raspberr-pi-and-atmega-324pa-avr-not-clock-stretching

Sejauh yang saya tahu, broadcom dan karyawan masih berpikir bahwa bug ini terbatas pada 5 mikrodetik PERTAMA (sebenarnya setengah jam) setelah bit terakhir byte.

@rewolff : Saya harus setuju dengan karyawan Broadcom. Dalam pengujian saya, dengan Raspberry Pi 3 dan 100 kHz I2C (yang melambat hingga 62 kHz saat CPU dicekik), saya mendapatkan hasil yang mirip dengan animasi dari advamation.com . Apakah Anda mendapatkan hasil eksperimental yang berbeda dari animasi tersebut, atau apakah animasinya tidak cukup untuk meyakinkan Anda?

Animasinya sepertinya terdengar. Namun hal tersebut tidak sejalan dengan pengalaman saya. Mungkin saya harus menyiapkan tes. Mungkin butuh waktu. Sibuk dengan hal lain.

Tetapi jika ini masalahnya, cukup "usleep (10)" dalam rutinitas interupsi saya (dengan peregangan jam perangkat keras) biasanya akan melakukan trik dan membuat segalanya tidak terkunci. Saya cukup yakin bahwa bukan itu masalahnya. :-(

@rewolff : Pada Raspberry Pi 3, saya telah melihat CPU dicekik hingga 600 MHz, menghasilkan kecepatan I2C default 62 kHz. Jadi Anda harus tidur selama 17 mikrodetik di ISR ​​budak Anda jika ISR dimulai di tepi jatuh SCL. Atau jika menurut Anda CPU mungkin akan terhambat hingga di bawah 600 MHz, tidur lebih lama.

Apakah mungkin untuk menyertakan modul i2c-gpio-param

Ini juga akan menjadi solusi yang baik untuk mengatasi bug HW yang mendasari seluruh masalah ini.

Maksudmu, i-gio overlay yang ada di kernel saat ini sejak Nov 2015? https://github.com/raspberrypi/linux/blob/rpi-4.4.y/arch/arm/boot/dts/overlays/i2c-gpio-overlay.dts
Dari README untuk hamparan:

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 : Luar biasa, terima kasih, saya belajar sesuatu yang baru hari ini. Saya belum menguji ini, tapi, ya, ini terlihat persis seperti yang saya cari (dan ditemukan di i2c-gpio-param).

@popcornmix @ 6by9 Bisakah ini ditutup? Berada di sekitar waktu yang lama, dan hal-hal penting dari bacaan saya tampaknya menjadi pilihan yang layak.

Solusi yang disarankan untuk perangkat yang pasti tidak bekerja dengan baik dengan perangkat keras I2C kami adalah dengan menggunakan hamparan i2c-gpio, yang merupakan pin bitbash.

Jika tidak, peregangan jam dalam fase ACK alamat didukung oleh driver upstream.

Dear all, hari ini saya telah menguji BNO055 dalam paket GY-955 dari Asia Timur yang berperilaku sangat buruk pada 100_000 Hz dengan Pi 2B (BMC2835). Untuk tes saya telah mengubah frekuensi bus I2C dari 50_000 menjadi 400_000 Hz dan saya menemukan masalah pada 100_000 Hz, tetapi untuk 50_000, 85_000, 115_000 dan 125_000Hz kode dari Adafruit (Adafruit_Python_BNO055) berfungsi dengan baik dengan koneksi I2C, 150_000 Hz tampaknya terlalu cepat untuk BNO055, ia berfungsi tetapi nilainya terkadang salah. Saya akui, saya tidak menguji frekuensi dengan osiloskop, saya hanya membaca file / sys / class / i2c-adapter / i2c-1 / of_node / clock-frequency, oleh karena itu beberapa ketidakpastian dibiarkan terbuka. Sekarang saya mulai menerapkan antarmuka lengkap ke BNO055 di ADA.
Facit: Bug hardware dalam penanganan BMC I2C hanya muncul pada 100_000 Hz, harus dikonfirmasi.

Sekadar diketahui, Bug perangkat keras terjadi ketika perangkat budak melakukan peregangan jam dan melepaskan garis SCL setelah periode jam 0,9 hingga 0,999 I2C. Garis akan mulai naik, dan perangkat keras pi akan berkata: Oh, dia tidak melakukan peregangan jam jadi saya bisa memberikan pulsa jam berikutnya dengan menarik garis jam rendah lagi.

Bug terjadi ketika waktu yang tersisa dalam periode jam cukup bagi baris CLK untuk melewati ambang batas "TINGGI" untuk raspberry tetapi tidak untuk perangkat budak ATAU ketika budak memiliki penyaringan kebisingan dan menganggap tinggi selama <x% dari siklus jam I2C normal kesalahan.

Ini tidak "hanya terjadi pada 100kHz", tetapi juga pada banyak frekuensi lain, kecuali bahwa waktu respons perangkat pendukung harus memiliki nilai yang berbeda.

Misalkan clocknya 100kHz, jadi siklus normal akan menjadi 5us high dan 5us low. Sekarang misalkan pada t = 0 pi memulai siklus clock terakhir dengan menarik garis clock rendah. Pada t = 5us pi melepaskan sinyal clock, tetapi slave masih sibuk dan membuat clock tetap rendah. Pada t = 9us slave selesai dan melepaskan sinyal clock. Pada t = 10us pi akan melihat sinyal clock, dan berpikir: Ok, tidak ada clock yang meregang, jadi lanjutkan, dan ia akan menarik sinyal clock rendah lagi. Sinyal clock sekarang hanya tinggi untuk 1us (sedikit lebih sedikit karena kapasitansi dan konstanta waktu resistor pullup) dan mungkin tidak terlihat oleh budak. Sekarang perangkat yang berbeda tidak menjadi siap setelah 9 mikrodetik, tetapi setelah 10,5. Sekarang pada 100kHz, pi akan melihat "masih rendah, clock stretching, tunggu 5 mikrodetik lagi. Sekarang kita akan mendapatkan pulsa clock 4,5 mikrodetik dan semuanya akan berfungsi. Tapi jalankan perangkat ini pada 90kHz, dan itu mendapat masalah. Sekarang pi akan melihat 11 mikrodetik dari awal, dan sinyal clock akan tinggi kurang dari satu mikrodetik -> Masalah.

Orang yang mengeluh tentang hal ini BUKAN orang yang memiliki perangkat lain tersebut. Mereka bekerja pada 100kHz default. Tetapi bug tersebut masih sangat nyata dan akan terjadi pada perangkat tersebut hanya pada kecepatan bus selain perangkat yang Anda dan saya miliki.

Terima kasih atas tanggapannya, ini menjelaskan dengan sangat baik, mengapa saya mendapat transfer yang andal pada frekuensi yang saya pilih:
pada 100_000 Hz masalah meningkat dalam periode 9 hingga 9.99 µsec
pada 85_000 Hz masalah dimulai pada 1_000_000 / 85_000 * .9 = 10,59 µsec> 9,99 detik, oleh karena itu peregangan jam diabaikan Saya berasumsi, untuk semua frekuensi kurang dari 85_000 Hz titik awal masalah lebih tinggi dari 10,59 µsec .
pada 115_000 Hz siklus bus adalah 1_000_000 / 125_000 = 8,7 µsec <9 µsec, oleh karena itu clock stretcing dideteksi dengan benar, untuk semua frekuensi yang lebih tinggi dari 115_000 Hz siklus bus kurang dari 8,7 µsec.
Jadi ketika saya memiliki masalah, saya dapat menghitung frekuensi yang saya butuhkan.
(Saya membaca informasi di http://www.advamation.com/knowhow/raspberrypi/rpi-i2c-bug.html,
ada catatan 0,5 bukan 0,9 titik).

Baik. Itu tergantung pada apa yang dideteksi budak Anda sebagai sinyal clock yang valid. Dan berapa lama penundaan RC di bus Anda. Dalam kasus saya, AVR yang saya gunakan sebagai budak menganggap pulsa kurang dari dua siklus jam menjadi kesalahan. Dengan clock RC internal 8MHz (+/- 10% !!!), pulsa harus setidaknya 250ns agar dapat dideteksi. Spesifikasi I2C membutuhkan 5 mikrodetik, jadi ada faktor 20 "margin" antara apa yang secara resmi diperlukan dan yang tidak lagi berfungsi.

Pada awalnya saya pikir saya akan meningkatkan peregangan jam di budak saya menghasilkan sedikit untuk mengatakan 12us. Itu berfungsi sampai kapasitansi bus menambahkan penundaan yang cukup untuk menyebabkan masalah lagi. Jadi sangat sulit untuk menyiasatinya. Menjengkelkan harus memberi tahu klien Anda untuk tidak menggunakan i2c 100kHz standar.

Maaf, tapi saya butuh waktu untuk menulis skenario implementasi dan pengujian penuh.
Saya berterima kasih atas semua informasi yang Anda berikan kepada saya, itu sangat membantu.
Skenario pengujian saya dibangun dengan 2 MEMS (BNO055 dikemas sebagai GY-055, MPU9255 dikemas sebagai MPU-9250/6500, register WHO_AM_I mengatakan MPU9255) dan 1 GPIO extender PCF 8574 (paket PCF 8574).
Jam I2C di Pi (2b) diatur ke 125 kHz, diverifikasi dengan membaca / sys / class / i2c-adapter / i2c-1 / of_node / clock-frequency.
Kode saya berjalan 100 kali membaca data dari MEMS dan menulis data untuk PCF dengan penundaan 0,1 detik.
Hasil:

  • Inisialisasi MEMS berhasil.
  • Membaca dari data MEMS melalui bus I2C berhasil di semua siklus.
  • Menulis data ke PCF melalui bus I2C berhasil di semua siklus.

Oleh karena itu MEMS dan PCF menerima clock yang lebih tinggi dari standar 100 kHz.
Di lingkungan yang lebih tua komunikasi ke AVR dilakukan melalui jalur serial, di yang kedua komunikasi akan dilakukan melalui USB, tetapi belum selesai, sebenarnya saya tersandung masalah bus I2C yang disebabkan oleh BNO055, tetapi saya pikir untuk lingkungan saya, saya menemukan solusi untuk Pi 2b dan saya berharap ini akan bekerja dengan Pi 3 juga, itulah tes berikutnya. Dan kemudian saya harus mengintegrasikan 2 MEMS lainnya, 1 VL53L0X dan 1 BME280, saya harap ini akan berfungsi dengan frekuensi baru dan kapasitansi bus menerima semua elemen ini.

Saya bermain dengan masalah ini sekarang pada RPi 3 Model B +, dan saya melihat hasil yang berbeda dari yang dijelaskan artikel Advamation. Silikon tidak dicabut baru-baru ini, bukan?

Versi singkatnya adalah, segala sesuatunya tampaknya berfungsi jika saya melakukan peregangan pada read-preACK, write-preACK, atau write-postACK; satu-satunya waktu yang saya perlukan untuk melakukan peregangan baik panjang atau tidak sama sekali adalah read-postACK. Saya masih perlu membersihkan eksperimen saya sebelum saya dapat mengatakan sesuatu yang pasti.

Pertama, catatan tentang terminologi. Artikel Advamation mengatakan:

Jadi, I2C dengan Raspberry Pi hanya berfungsi jika
budak tidak menggunakan peregangan jam sama sekali, atau
budak meregangkan jam hanya di akhir / langsung setelah fase-baca-ACK-I2C (setelah membaca ACK / NACK), tetapi kemudian dengan lebih dari 0,5 periode jam.

Istilah "I2C-read-ACK-phase" tampaknya agak ambigu. Jika ini adalah perintah baca I2C (mis., Bit R / W̅ alamat-pos disetel), slave akan menulis bit A̅C̅K̅, bukan membacanya, berlawanan dengan tanda kurung. Ketika saya mengatakan "read-postACK" di sini, maksud saya bit R / W̅ disetel tepat setelah alamat (dan mungkin tidak diubah oleh protokol seperti yang dilakukan SMBus), jadi budak baru saja menulis respon A̅C̅K̅-nya.

Seperti yang telah diisyaratkan di sini, tampaknya jika RPi merasakan bahwa SCL ditahan rendah oleh seorang budak, itu akan menunda jam SCL internalnya sebanyak satu setengah siklus (5μS). Bug dipicu jika slave menahan SCL rendah selama _almost_ satu setengah siklus. Jika itu terjadi, maka RPi akan tetap membiarkan SCL naik, dan kemudian menariknya ke bawah segera setelah jam SCL-nya terpicu. Ini menghasilkan pulsa clock runt, yang mungkin dilihat beberapa perangkat sebagai pulsa sementara perangkat lainnya tidak. (Untuk referensi: spesifikasi I2C menyiratkan waktu tinggi SCL nominal 5μS, dan menetapkan waktu minimum 4.0μS pada 100kHz, yang merupakan kecepatan default antarmuka I2C RPi.)

Dalam eksperimen saya, dalam fase read-preACK, write-preACK, dan write-postACK, RPi akan memastikan bahwa waktu tinggi SCL maksimum yang diizinkan adalah 4μS atau lebih. Tampaknya bersedia untuk mendorong jam SCL-nya kembali ke fase tersebut. Saya menduga bahwa RPi mengambil sampel garis SCL tak lama setelah itu melepaskannya, dan jika SCL masih rendah, itu mendorong jam SCL mundur setengah fase.

Namun, dalam fase read-postACK, saya melihat bahwa RPi akan memancarkan runt clock (<4μS, seringkali 2μS atau kurang) jika garis SCL dipertahankan rendah selama sekitar 6-9μS. Saya menduga bahwa dalam fase ini, para insinyur Broadcom mengikuti jalur berbeda yang mencoba mengurangi kemungkinan mereka harus menunda setengah fase pada jalur kapasitansi tinggi. Sayangnya - seperti yang telah kita lihat - gagal.

Oleh karena itu, kode saya saat ini perlu meregangkan SCL melebihi siklus ½ dalam fase baca-postACK pembacaan yang mungkin memakan waktu cukup lama (seperti konversi ADC). Jika saya gagal

Pengujian saat ini yang saya jalankan menggunakan PIC16F1619 sebagai perangkat budak. Perangkat slave menggunakan perulangan untuk meregangkan jam di kedua perintah baca dan tulis, baik pra dan pasca. Panjang loop ditambah overhead bervariasi dari 3μS (kurang dari waktu RPi menahan SCL rendah) hingga 90μS dalam peningkatan 0,35μS. Saya memiliki program Python pada RPi yang akan membedakan nilai ke dua register, kemudian membacanya kembali, dan menegaskan bahwa nilai read-back sudah benar. Nilai-nilai yang digunakan

Piquan,
Broadcom telah meremehkan ini dengan menyatakan bahwa masalah ini hanya terjadi pada peregangan jam pertama. Saya tidak berpikir bahwa ini masalahnya. Anda harus bisa memverifikasi itu. Advamation tampaknya mengikuti pernyataan broadcom.

@rewolff Nah, mungkin ada sesuatu untuk interpretasi mereka. Jika, dengan "peregangan jam pertama" yang mereka maksud adalah "pertama kali dalam tahap tertentu bahwa SCL diregangkan oleh lebih dari satu terjemahan jam" maka deskripsi mereka akurat: jika Anda meregang lebih dari satu siklus jam, maka ya: secara keseluruhan fase, jika Anda meregang dengan> .5 siklus, Anda dalam kondisi yang baik. Setidaknya, dalam eksperimen samar yang telah saya lakukan sejauh ini; eksperimen yang lebih tepat belum datang.

Saya senang melakukan beberapa eksperimen yang lebih baik untuk mendemonstrasikan kapan I2C RPi dapat dan tidak dapat menangani peregangan jam, dan mendapatkan repro yang dapat dikirim BCM kepada para insinyur.

Sayangnya, ada putaran silikon yang sangat signifikan yang mereka perlukan untuk memperbaiki masalah ini; mereka tidak perlu mencentang jam pembagi SCL saat SCL ditahan rendah (oleh sumber internal atau eksternal). Itu mungkin akan membutuhkan perubahan tingkat silikon, yang mahal; kebanyakan ECO memiliki level logam, yang… yah, tidak murah, tetapi jauh lebih murah daripada silikon.

Tujuan utama saya di sini adalah untuk mengkarakterisasi jenis budak yang akan dan tidak akan bekerja dengan RPi, dengan beberapa bukti eksperimental.

Sepertinya kita membutuhkan lebih banyak data yang solid, seperti skenario repro, untuk meyakinkan Broadcom untuk merekayasa ulang pengontrol I2C. Bahkan dengan data yang solid, para insinyur harus meyakinkan manajemen bahwa perlu merevisi silikon untuk revisi berikutnya.

Karena itu, saya akan meluangkan waktu untuk merancang skenario yang dapat direproduksi sehingga insinyur BCM dapat dengan jelas melihat dan menguji masalahnya. Saya akan bergantung pada anggota komunitas di sini untuk mengkomunikasikan temuan saya ke Broadcom; Saya tidak memiliki saluran ke mereka.

Saya harus mengklarifikasi sesuatu tentang komentar saya sebelumnya kepada komunitas, tentang perubahan silikon vs logam.

Anda tahu bagaimana, jika Anda mendapatkan papan dari SparkFun atau Adafruit, seringkali ada jejak yang dapat Anda potong atau solder bersama untuk mengubah perilakunya? Kebanyakan papan I2C memiliki jejak yang dapat Anda ubah untuk mengubah alamat, mengaktifkan atau menonaktifkan resistor pull-up, dll.

Desainer microchip melakukan hal yang sama. Ada banyak perubahan yang bisa mereka lakukan pada lapisan logam microchip, jadi mereka tidak perlu mengganti lapisan silikon. Itu karena mengganti lapisan silikon itu sulit dan mahal (seperti mengganti chip di papan), sementara lapisan logam jauh lebih mudah untuk diubah (seperti mengubah jejak di papan).

Banyak perubahan yang berguna dapat dilakukan pada lapisan logam, karena desainer berpikir ke depan dan membuat sambungan logam (jumper, pada dasarnya) yang mengubah perilaku chip.

Tetapi jika ada perubahan yang tidak mereka rencanakan, dan tidak tahu bagaimana membuatnya dengan mengubah jejak jejak di dalam chip, maka mereka harus mengganti silikon. Silikon membutuhkan lebih banyak perencanaan, verifikasi, dan penyamaran, jadi sulit untuk diubah.

Banyak perusahaan, jika mereka memiliki lapisan silikon yang "cukup baik", akan menggunakannya selama mungkin. Mereka akan menggunakan kembali beberapa bagian lapisan silikon dalam beberapa revisi chip.

Saya menduga di situlah BCM berada: mereka membutuhkan bukti yang baik bahwa bug ini tidak dapat diperbaiki pada driver atau logam sebelum mereka dapat membenarkan rekayasa ulang bagian lapisan silikon ini dari awal.

Sangat tidak mungkin bahwa akan ada respin dari silikon yang ada hanya untuk memperbaiki masalah ini (mendapat $ 1 juta cadangan?). Chip masa depan mungkin memiliki perbaikan, siapa tahu.

Pada Rabu, 05 Sep 2018 pukul 02:13:19 -0700, Joel Ray Holveck menulis:

Sepertinya kita membutuhkan data yang lebih solid, seperti skenario repro, untuk
meyakinkan Broadcom untuk merekayasa ulang pengontrol I2C. Bahkan dengan
data solid, para insinyur harus meyakinkan manajemen itu
ada baiknya merevisi silikon untuk revisi berikutnya.

Mereka sudah memiliki enam tahun dan 3 revisi silikon di mana mereka
telah menunjukkan keputusan mereka: "tidak akan diperbaiki".

jika Anda melakukan peregangan dengan> 0,5 siklus, Anda dalam kondisi yang baik.

Saya kira tidak. Setiap kali Anda melepaskan CLK di "tepat sebelum
broadcom melihat lagi "periode waktu, Anda mendapatkan pulsa pendek. Saya bisa dengan mudah
tunda pelepasan sinyal clock dengan mengatakan 5 mikrodetik yang tidak berguna
selalu keluar dari siklus 0,5. Tapi itu tidak berhasil.

Pada Rabu, 05 Sep 2018 pukul 02:28:53 -0700, James Hughes menulis:

Sangat tidak mungkin bahwa akan ada respin dari
silikon yang ada hanya untuk memperbaiki masalah ini (mendapat $ 1 juta cadangan?). Masa depan
chip mungkin bisa memperbaikinya.

Aku meragukan itu. Kami beralih dari BCM2835 dengan bug DIKENAL ke BCM2836 dengan
bug yang sama ke BCM2837 dengan bug yang sama persis dengan BCM2837B0.

Sekarang mengapa menurut Anda revisi berikutnya akan berbeda?

BCM memiliki target pasar: Ponsel dan TV-stick untuk chip ini. Di
target pasar mereka tidak ada yang melakukan software-I2C untuk tujuan umum
mikrokontroler seperti AVR dan PIC. mereka TIDAK akan memperbaiki ini.

Sayang sekali upaya investigasi ini diperlukan, meskipun demikian hebatnya. Ketika saya bertanya sebelumnya untuk erratum yang menutupi ini, saya pikir tidak ada. Apakah sekarang sudah berubah dan ada URL? Idealnya, Broadcom akan membantu komunitas dengan mendeskripsikan kesalahan secara tepat dan ketika itu terjadi sehingga penyelesaian atau evaluasi komponen yang kompatibel akan lebih mudah dikerjakan dengan percaya diri. Bahkan sampai cuplikan HDL yang relevan tidak mau berusaha menerjemahkannya secara akurat ke dalam deskripsi.

Saran untuk menghentikan pembagi setengah-bit-jam saat mengizinkan peregangan jam adalah bagus. Itu akan berhasil.

Masalahnya adalah bahwa bagian dari modul I2C kemudian perlu dijalankan pada "kecepatan clock penuh". Sekarang modul I2C adalah modul berdaya rendah yang bagus karena biasanya berjalan tidak lebih cepat dari 200kHz.

Alasan utama posting saya adalah apa yang saya katakan di awal posting asli saya:

Saya bermain dengan masalah ini sekarang pada RPi 3 Model B +, dan saya melihat hasil yang berbeda dari yang dijelaskan artikel Advamation. Silikon tidak dicabut baru-baru ini, bukan?

Jika kami mengalami perubahan signifikan pada perangkat keras atau driver I2C setelah penulisan Advamation 2013 , dan komunitas tahu bagaimana hal itu dapat memengaruhi bug ini, maka saya harus membuat perubahan yang sesuai pada eksperimen saya.

Saya tahu masalah mendasar ada di perangkat keras, tetapi untuk semua yang saya tahu, seseorang mungkin telah menemukan melalui percobaan bahwa mengubah register yang tampaknya tidak terkait di driver sebenarnya mengubah perilaku bug ini. Saya juga belum mengonfirmasi bahwa BCM2837 memiliki modul I2C yang sama dengan RPi 2 (terakhir kali saya dapat menemukan konfirmasi pasti bahwa perangkat keras I2C tidak berubah sejak masalah ini pertama kali dilaporkan). Saya juga belum menemukan informasi apapun tentang stepping BCM283x manapun; yang saya tahu, mungkin saja ada perubahan logam di era BCM2836.

Saya tidak tertarik untuk menolak Broadcom, berspekulasi bagaimana mereka dapat mengubah revisi di masa mendatang, atau semacamnya.

Tujuan utama saya di sini adalah mendokumentasikan dengan jelas perilaku saat ini; sepertinya itu berubah seiring waktu. Saya memiliki tujuan sekunder untuk memungkinkan pengguna di masa mendatang mereproduksi eksperimen saya untuk melihat apakah hasilnya masih valid, atau untuk melakukan perbaikan atau menguji kondisi lain. Saya memiliki tujuan sekunder lain untuk memungkinkan teknisi Broadcom mereproduksi pengujian dengan mudah jika mereka mau. Keduanya berarti saya perlu memublikasikan eksperimen saya, yang juga membantu: karena keangkuhan saya sendiri, jika saya memublikasikan eksperimen saya, saya akan lebih terdorong untuk membuatnya lebih teliti.

Rencana eksperimental saya saat ini adalah menggunakan PIC16F1619 sebagai implementasi budak; cukup cepat dan serbaguna untuk melakukan eksperimen peregangan jam, cukup mudah untuk dikerjakan, dan cukup umum sehingga peneliti lain dapat mereproduksi hasil saya. Jika hasilnya ambigu, saya mungkin juga membuat eksperimen dengan FPGA. Saya mungkin melihat apakah saya bisa mendapatkan perincian yang masuk akal menggunakan Raspberry Pi lain dalam konfigurasi bit-bashing sebagai budak, tetapi saya curiga saya akan memerlukan sesuatu tanpa seluruh OS untuk melakukan pengujian waktu nyata.

Untuk mengatasi beberapa hal lain yang muncul:

Maaf posting asli saya tidak lengkap; Saya tidak sengaja memposting draf awal. Saya akan membiarkannya apa adanya, karena perubahan yang saya buat cukup kecil.

Saya tidak mengklaim orisinalitas pada gagasan menghentikan pembagi jam sementara SCL secara eksternal ditahan rendah. Saya membacanya di tempat lain, tapi tidak ingat di mana; Saya pikir itu dari Gert van Loo di thread peregangan jam I2C di raspberrypi.org , tetapi saya tidak dapat menemukannya sekarang, jadi saya pasti pernah melihatnya di tempat lain. Saya tidak yakin itu akan mengubah profil kekuatan secara signifikan,

Blok I2C HW belum diperbaiki / diubah, dan tidak mungkin, di bcm2835 / 6/7 karena itu akan membutuhkan respins dari chip yang terlalu mahal.

Saya tidak tahu siapa Advamasi itu, tapi mereka belum terealisasi ke kelompok RPF (T), jadi saya tidak bisa menjamin keakuratan artikelnya.

Dear all, saya mendapat fenomena yang sangat aneh di Pi 2B dan 3 saya, saya coba jelaskan:
ketika saya mulai menerapkan BNO055 akhir Juni, saya menggunakan Raspbian yang lebih tua (saya tidak sekarang versinya) dan saya mendapat banyak alamat I2C yang tidak valid menggunakan i2cdetect. Untuk itu saya mencari di internet dan saya menemukan forum ini dengan informasi yang bagus. Untuk itu saya ubah frekuensi I2C seperti yang dijelaskan di atas dan semua hantu lenyap dan saya bisa bekerja. Pertengahan Agustus saya mengupgrade Raspbian menjadi raspbi-dev 4.14.62-v7 + dan sistem menjadi sedikit tidak stabil, tetapi saya dapat bekerja. Dari update hingga update sistem menjadi lebih tidak stabil, mencatat kebocoran pada sd card. Oleh karena itu saya menginstal ulang Raspbian melalui NOOBS (Linux raspbi-dev 4.14.62-v7 + # 1134 SMP Sel 14 Agustus 17:10:10 BST 2018 armv7l) dan saya lupa mengatur frekuensi I2C tetapi tidak ada hantu yang muncul. Oke saya tidak menggunakan mikrokontroler di bus, hanya extender MEMS dan GPIO, tapi saya merasa ada solusi untuk kode i2c Raspbian. Selanjutnya saya pikir kebocoran yang terdeteksi berasal dari peningkatan yang tidak sempurna, saya menggunakan kartu yang sama dan tidak ada kebocoran yang terdeteksi.

@ hmf2015 Masalah ini adalah tentang masalah I2C yang sangat spesifik. Masalah dengan kartu SD bukan disebabkan oleh masalah I2C ini. Jika kartu SD Anda tidak berfungsi dengan benar, Anda harus mencoba kartu SD baru. Beberapa kartu tidak bagus, dan berhenti bekerja dengan cepat. Kartu SD saya berhenti berfungsi bulan lalu, dan saya harus menggantinya.

Biasanya hantu I2C bukan karena masalah ini. Mereka paling sering terjadi karena:

  • Anda tidak memiliki catu daya yang baik. Saya suka yang ini .
  • Kabel Anda terlalu panjang. I2C tidak bekerja dengan baik dengan kabel yang lebih panjang dari 1m.
  • Kabel Anda memiliki kopling kapasitif. Jika Anda memiliki pin I2C (SCL dan SDA) yang dipelintir bersama, itu dapat menimbulkan masalah. Terkadang, orang menggunakan kabel twisted-pair (seperti kabel Ethernet) yang memutar pin I2C, dan itu menimbulkan masalah. Jika Anda harus menggunakan kabel twisted-pair, maka putar SCL dengan Vss (ground) dan SDA dengan Vdd (3.3V). Lihat spesifikasi I2C di bagian 7.5.
  • Perangkat I2C Anda memiliki 5V. Raspberry Pi melakukan I / O pada 3.3V. Jika voltase berbeda, itu bisa menimbulkan masalah. (BNO055 membutuhkan 3,3V, jadi jika Anda menggunakannya dengan 5V, Anda mengalami masalah.)

Saya mengatakan bahwa kita sedang membicarakan masalah tertentu. Beberapa perangkat mungkin membuat hantu karena masalah ini, tetapi tidak banyak perangkat. Jika perangkat membuat hantu karena masalah ini, perangkat tersebut tidak membuat banyak hantu. Saya pikir masalah Anda berbeda.

Saya tidak mengerti apa yang Anda maksud ketika Anda mengatakan bahwa Anda "mencatat kebocoran pada kartu sd". Itu masalah yang penting, tapi itu bukan masalah yang kita bicarakan dalam masalah halaman web ini. Percakapan ini tentang bug tertentu. Bug itu tidak memengaruhi kartu SD.

Saya tidak berpikir bahwa Raspbian baru-baru ini mengubah cara kerja I2C. Menurut kami, Raspbian tidak dapat memperbaiki bug ini. Kami mungkin salah. Terima kasih telah memberi tahu kami tentang ini.

Jika Anda hanya memberi tahu kami informasi ini untuk membantu kami, kami berterima kasih. Jika Anda memberi tahu kami informasi ini untuk meminta bantuan, Anda mungkin ingin bertanya di forum Raspberry Pi . Forum membicarakan banyak hal, seperti I2C, kartu SD, perluasan GPIO, dan banyak lagi. Hal-hal yang Anda lihat mungkin sama dengan yang sedang kita bicarakan, tetapi mungkin berbeda. Orang-orang di forum dapat membantu Anda mengetahui masalah yang Anda hadapi.

Terima kasih telah memberi tahu kami informasi ini!

Terima kasih atas jawabannya, tetapi masalah kartu sd dihasilkan oleh O / S, saya memeriksa kartu pada host (Unix) saya, dan itu baik-baik saja, dan sekarang cad yang sama berfungsi sempurna setelah instalasi baru.
Hantu di bus I2C menghilang dengan frekuensi yang lebih tinggi dan sekarang setelah penginstalan ulang mereka tidak muncul, masalah R / C dan refleksi yang saya pikir dapat saya kecualikan. Saya tahu masalah 3.3V, tetapi level minimal 1 kurang.
Paket BNO055 memiliki pengatur tegangan.
Saya juga berpikir bahwa masalah I2C akan sama seperti sebelumnya, tetapi ternyata tidak, saat ini saya belum memiliki waktu (dan minat) untuk melihat kode sumber Raspbian untuk mendeteksi perbedaannya, saya tertarik di lingkungan kerja.
Daftar elemen seharusnya hanya menunjukkan, bahwa saya bekerja di lingkungan Andoid (dengan Unix asli) karena BCM mendukung, bukan dengan mikrokontroler yang saya pasang melalui jalur serial atau USB karena saya malas. Di lingkungan Anda kondisinya lebih membatasi daripada saya, jadi saya tidak bisa mengatakan apakah masalah Anda berkurang, tapi saya harap.

Halo hmf2015,
Ini bukan forum. Ini adalah pelacak bug. Daftar komentar ini membahas bug yang tidak terkait dengan masalah Anda. Silakan diskusikan masalah Anda dengan forum atau helpdesk yang sesuai. Sekali lagi, kami menghargai pertanyaan Anda: "Mungkin sama? Mungkin deskripsi saya membantu mengatasi bug itu?" tapi sekarang kami tahu pasti bahwa apa yang Anda lihat tidak ada hubungannya, mohon jangan "mencemari" diskusi ini lebih lanjut.

@tokopedia
hai, lama Anda telah menyebutkan masalah dengan mesin negara I2C selama restart dan memposting beberapa kode mengenai masalah ini.
Saya tidak yakin apa yang Anda maksud tetapi saya memiliki masalah dengan codec WM8731 yang terhubung ke I2C.
Setelah 2-3 kali restart, bus I2C menutup sepenuhnya. i2cdetect tidak menampilkan info apa pun kecuali baris pertama dan juga menutup telepon. Satu-satunya cara untuk memulihkan adalah power down / up cycle.
Apakah ini terlihat seperti masalah yang Anda sebutkan?
Saya menggunakan kernel 4.19 mainine.

@ sergey-suloev Jika i2cdetect tidak melanjutkan pemindaian setelah 8 atau 16 alamat, menurut saya ini tidak ada hubungannya dengan masalah ini. Masalah muncul ketika perangkat melakukan peregangan jam untuk menunjukkan bahwa mereka belum siap untuk siklus jam berikutnya. Ketika I2C dirancang hampir 40 tahun yang lalu, hal itu mungkin bisa dibayangkan untuk implementasi perangkat keras juga. Namun saat ini, perangkat keras selalu siap pada waktunya untuk menangani siklus jam berikutnya karena 10 mikrodetik adalah usia waktu untuk sesuatu yang diimplementasikan dalam perangkat keras.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat