- Ini adalah catatan pembuatan perangkat keras yang menambahkan kemampuan kirim-terima Ethernet 10BASE-T ke komputer logika diskret yang dibuat tanpa CPU komersial atau chip jaringan khusus
- Di atas adapter lapisan fisik 10BASE-T↔SPI yang dibuat sebelumnya, ditambahkan modul lapisan MAC untuk dihubungkan ke homebrew computer, dan pemancar serta penerima disusun dalam arsitektur full-duplex yang independen
- Penerima mengubah data SPI menjadi byte dan menyimpannya ke SRAM 2 kB, lalu memeriksa 6 byte pertama di perangkat keras agar hanya menerima
FE:FA:F6:F2:EE:EAatau MAC broadcast - Untuk menyederhanakan rangkaian, pemancar menyerahkan pembuatan FCS dan penyiapan preamble ke perangkat lunak, dan hanya mendukung frame dengan panjang tetap 1024 byte
- Bahkan dibuat compiler C yang mampu mengompilasi uIP 1.0 untuk menjalankan aplikasi jaringan, dengan hasil rata-rata ping 85 ms dan unduhan file statis HTTP sekitar 2.6 kB/s
Menambahkan Ethernet ke komputer logika diskret
- Sebagai kelanjutan dari upaya membangun sistem komputer lengkap dengan komponen logika diskret, dibuat adapter Ethernet yang mampu menjalankan aplikasi jaringan
- Sebelumnya telah dibuat adapter lapisan fisik yang mengubah sinyal Ethernet 10BASE-T menjadi SPI dan sebaliknya, dan saat itu pengujian operasi menggunakan mikrokontroler STM32
- Inti dari pekerjaan kali ini adalah modul lapisan MAC untuk menghubungkan adapter tersebut ke homebrew computer
- Adapter ini berarsitektur full-duplex, dan bagian pemancar serta penerima bekerja independen satu sama lain
Penerima: menyimpan data SPI ke buffer frame
- Penerima mengubah data serial SPI menjadi data paralel per byte dan mengekstrak clock byte
- Alamat MAC tujuan diperiksa pada 6 byte pertama, dan frame yang tidak memenuhi kriteria akan ditolak
- Byte yang diterima ditulis ke buffer SRAM 6116 2 kB
- Saat frame selesai, penerima dinonaktifkan dan tidak akan menerima frame tambahan sampai diaktifkan kembali
- Pencacah byte tetap mempertahankan nilainya setelah berhenti agar CPU dapat membaca panjang data yang diterima
- FCS tidak diperiksa di perangkat keras
-
Pengumpulan data dan akses buffer
- Data serial SPI masuk ke shift register
U32, danU30sertaU31masing-masing menghitung bit dan byte - D flip-flop
U29Bmembuat sinyal tulis SRAMrecv_buf_we, dan sinyal ini sesaat menjadi rendah setiap 8 bit data masuk - Byte yang diterima ditulis ke SRAM 6116
U20 U13,U16,U18membentuk multiplexer alamat untuk memilih pencacah byte atau bus alamat sistem sebagai input alamat SRAMU21berperan sebagai buffer tri-state yang mengirim byte yang diterima ke RAM- Agar CPU bisa mengakses data dan panjang data terima, RAM dan pencacah byte dihubungkan ke bus data sistem
U25menghubungkan RAM penerima ke bus data sistem- Setelah frame selesai, nilai pencacah byte dipertahankan pada bus
recv_byte_cnt U26,U27mengirim nilai ini ke bus data sistem saat ada permintaan baca alamat tertentu- Separuh sisa dari
U27membentuk register status baca-saja 2-bit untuk mengecek status penerima dan pemancar
- Data serial SPI masuk ke shift register
Penyaringan alamat MAC di perangkat keras
- Setelah menganalisis lalu lintas Ethernet, terlihat bahwa frame biasanya masuk dalam kelompok kecil berisi 3–4 buah yang dipisahkan jeda singkat, dan bahkan dalam kelompok yang sama pun alamat MAC tujuan sering berbeda
- Komputer mungkin tidak cukup cepat untuk melakukan penyaringan MAC di perangkat lunak lalu mengaktifkan kembali penerima, sehingga dibutuhkan penyaringan MAC di perangkat keras
- Metode menyimpan alamat MAC kustom lalu membandingkannya dengan 6 byte pertama dianggap terlalu rumit dan dikesampingkan
- Alamat MAC dengan pengulangan byte tunggal juga memungkinkan, tetapi akhirnya dipilih pembuatan alamat MAC sebagai fungsi dari indeks byte
- bit 0 tetap 0
- bit 1 tetap 1
- bit 2~4 adalah nilai terbalik dari indeks byte
- bit 5~7 tetap 1
- Alamat MAC yang dihasilkan dengan aturan ini adalah
FE:FA:F6:F2:EE:EA - Agar ARP berfungsi, MAC broadcast
FF:FF:FF:FF:FF:FFjuga diterima U33membandingkan apakah bit data 0 dan bit 2~4 sesuai dengan nilai yang diinginkan, dan keluaranU34Amenjadi tinggi saat bit-bit tersebut cocokU35Amengimplementasikan pemeriksaan MAC broadcast, dan keluarannya menjadi tinggi jika bit 0 dan bit 2~4 semuanya 1- Kedua sinyal digabung dengan diode OR menggunakan
D7danR6, danU35Bmemeriksa apakah semua bit sisanya bernilai 1 - Hasil validitas satu byte diakumulasikan di
U10A- Saat tidak menerima frame, sinyal incoming SPI slave select
ssrendah danU10Adiatur ke 1 - Selama penerimaan frame, nilainya diperbarui untuk setiap byte yang diterima
- Jika alamat MAC tujuan sesuai kriteria, nilai
U10Atetap tinggi - Saat alamat byte mencapai 5, nilai akhirnya dilatch ke
U36B, dan jika alamat tujuan tidak cocok maka penerimaan frame diblokir
- Saat tidak menerima frame, sinyal incoming SPI slave select
Pemancar: menyederhanakan rangkaian dengan frame panjang tetap
- Seperti pada penerima, pemancar juga tidak mengimplementasikan pembuatan FCS di perangkat keras dan menanganinya di perangkat lunak
- Untuk mengurangi rangkaian, pemancar hanya mendukung frame dengan panjang tetap
- Panjang frame dipilih 1024 byte, nilai yang mendekati MTU umum 1500 byte
- Preamble yang dibutuhkan 10BASE-T terdiri dari beberapa
0x55dan diakhiri0xD5, dan perangkat lunak harus memuatnya bersama data ke dalam 1024 byte ini - Panjang frame tetap tidak memengaruhi protokol lapisan atas
- Protokol lapisan atas mengenkode ukuran paket di header
- Tidak bergantung pada panjang frame Ethernet sebenarnya
-
Alur data transmisi
- Data kirim disimpan di SRAM
- Clock 20 MHz masuk ke pencacah 4-bit, dan keluaran overflow digunakan sebagai clock byte
- Menulis nilai ke lokasi memori write-only tertentu akan mengaktifkan pencacah dan memulai transmisi frame
- Data byte paralel diserialkan melalui shift register
- Sama seperti penerima,
U12menghitung bit danU14menghitung byte - Clock 20 MHz berasal dari osilator terintegrasi, dan tidak digunakan langsung melainkan minimal dibagi 2 terlebih dahulu
- Cara ini memastikan duty cycle osilator tidak memengaruhi sinyal keluaran
-
RAM, shift register, dan timing
- Seperti pada penerima, tiga multiplexer 74HC157 digunakan untuk memilih input alamat RAM
U22 U23digunakan untuk memuat data ke RAMU24berfungsi sebagai penyimpanan sementara untuk byte yang sedang dikirim- Pencacah byte 74HC4040 adalah ripple counter sehingga stabilisasinya lambat
U24menyediakan keluaran yang stabil saat keluaran RAM belum valid- Data masuk ke shift register
U28dan digeser per bit - Ada bug perangkat keras yang salah menghubungkan urutan bit dari RAM ke shift register, sehingga harus diakali di perangkat lunak dengan menukar bit
MOSIdanSCKharus disinkronkan secara tepat untuk menghasilkan sinyal 10BASE-T yang baikU11AdanU8Bmenangani sinkronisasi initx_cnt0adalah bit 0 dari pencacah bit, yaitu sinyal hasil pembagian dua dari 20 MHz yang dipakai sebagai clockU11Amengubah keluaran sesuai sinyal iniU8Bmenunda clock agar sesuai dengan delay yang dibuatU11A- D latch lebih kompleks daripada gerbang AND sederhana dan memiliki delay sekitar 5 ns lebih besar, sehingga digunakan 74LV74A yang lebih cepat
- 74LV74A adalah satu-satunya chip keluarga cepat di papan ini
- Seperti pada penerima, tiga multiplexer 74HC157 digunakan untuk memilih input alamat RAM
Antarmuka CPU dan pemetaan memori
- Dari sudut pandang pemrogram, adapter Ethernet terlihat sebagai antarmuka yang dipetakan ke memori
- Dua buffer frame dipetakan ke
0xF000 - Ada dua register baca-saja
- Register status 8-bit di
0xFB00memiliki flagRX_FULLdanTX_BUSY RX_FULLmenunjukkan status penerimaan frame selesaiTX_BUSYmenunjukkan status sedang mengirim frame- Register 16-bit di
0xFB02menyimpan panjang data terima
- Register status 8-bit di
- Operasi tulis digunakan sebagai perintah kontrol
- Menulis nilai apa pun ke
0xFB00akan mengaktifkan kembali penerima - Menulis nilai apa pun ke
0xFB01akan memulai transmisi
- Menulis nilai apa pun ke
- Karena CPU tidak mendukung interupsi, tidak ada interupsi
- Semua alamat terkait dimulai dengan
Fyang berarti 4 bit teratas bernilai 1, dan kondisi ini diperiksa olehU2A - Alamat buffer mengharuskan bit 11 bernilai 0, dan ini diperiksa oleh
U1D,D2,R2,U1E - Alamat register mengharuskan digit heksadesimal kedua bernilai
Byaitu1011, danU1BsertaU2Bmemverifikasinya - Decoder
U4A,U4Bdigunakan untuk memilih fungsi individual - Dua LED menunjukkan akses ke buffer atau register
Pemrograman dan performa
- Ingin ada dukungan jaringan, tetapi tidak ingin mengimplementasikan sendiri stack TCP/IP dan juga kurang nyaman menulis assembly, sehingga dibuat compiler C
- Compiler ini sudah cukup matang untuk mengompilasi uIP 1.0, pustaka TCP/IP kecil
- Kepadatan kode CPU sangat rendah, tetapi uIP muat di RAM dan masih menyisakan ruang untuk aplikasi nyata
- Performa jaringan memang rendah, tetapi ini adalah hasil yang dicapai tanpa CPU komersial atau chip khusus
- Rata-rata RTT ping: 85 ms
- Kecepatan unduh server HTTP: 2.6 kB/s
- Server HTTP menyajikan file statis dari kartu SD
- Model, berkas skematik, dan gambar PCB tersedia di repositori GitHub
1 komentar
Komentar Hacker News
Karya yang keren, terima kasih sudah berbagi. Stack trace proses penalaran-nya terutama bagus, dan secara edukatif sangat baik karena banyak hal diuraikan dari prinsip pertama atau dicoba dijelaskan dari sudut pandang pemula.
Walau tidak praktis untuk jaringan nyata, menurut saya ini bukan sekadar main-main sederhana. Di era ketika backdoor ditemukan di chip jaringan yang terlalu kompleks, ke depan mungkin akan muncul pembaca yang lebih serius atau motivasi proyek seperti ini.
Ini dibuat untuk komputer yang sepenuhnya kustom, jadi dengan sendirinya jauh lebih mengesankan; belum lagi bagian “jadi saya membuat compiler C”. Meski begitu, saya jadi penasaran seperti apa implementasi minimal kartu Ethernet untuk PC “umum”.
Sepertinya banyak bagiannya akan mirip, dan checksum mungkin bisa diproses oleh CPU PC. Koneksinya perlu serial mentah atau, lebih praktis, USB; pada akhirnya sepertinya harus memakai driver “sungguhan” atau menyerahkannya ke user space untuk diproses.
Saat melihat hal-hal serupa, saya sempat berpikir kalau perangkat mengimplementasikan https://en.wikipedia.org/wiki/USB_communications_device_clas..., mungkin bisa “langsung jalan” tanpa driver sendiri, tetapi itu tampaknya kurang cocok dengan memproses semua checksum di sisi host.
Saat mencari, saya juga menemukan https://en.wikipedia.org/wiki/Ethernet_over_USB, dan mungkin maksudnya kita bisa membuat adaptor yang hanya mengubah koneksi fisik menjadi USB lalu membiarkan komputer menangani sisanya.
Mungkin perangkat USB gaya FTDI bisa dibujuk untuk melakukan bit-banging 10base2 Ethernet. Caranya hanya mengimplementasikan sisi “PHY” yang mengubah lalu lintas kabel menjadi bitstream bersih dan menyelaraskan awal frame, lalu PC menangani semua sisanya di software.
Untuk sisi USB, CDC-NCM sendiri tidak sulit diimplementasikan pada MCU mana pun, tetapi implementasi USB HS PHY pada praktiknya membutuhkan hardware ASIC.
Dengan USB HS ULPI PHY seharga 0,30 dolar, USB CDC-NCM kemungkinan bisa diimplementasikan di FPGA dengan cukup mudah.
Di bagian akhir ada tautan ke compiler C yang dibuat untuk proyek ini: https://github.com/imihajlow/ccpu-cc
Sepertinya ada linker dan libc juga. Saya tidak benar-benar tahu seberapa kompleks desain hardwarenya, tetapi hebat sekali bisa membuat dan menempelkan compiler C ringan seperti itu.
Sangat mengesankan. Saya ingin mencoba proyek seperti ini sendiri, dan saya jadi menghormati semangat serta jam kerja tak terhitung yang dibutuhkan untuk memahami sistem lalu sampai membuatnya.
Saya tidak terlalu berharap pensiun, tetapi mungkin sekitar saat itulah saya akan menghabiskan waktu untuk proyek hardware dan software seperti ini.
Jadi ini lebih baik daripada Etherlink 3c501, atau lebih buruk? :-D
https://mirror.math.princeton.edu/pub/oldlinux/Linux.old/net...
Kalau ingatan saya benar, paket baru yang masuk dari jaringan bisa menimpa buffer yang hendak dibaca CPU. Saya memakainya di Linux selama beberapa waktu, dan performanya benar-benar buruk.
Mengejutkan betapa banyak hal yang disembunyikan dari pandangan kita oleh pembaruan driver dan firmware.
Punya saya lebih baik karena buffernya ada dua :) Meski begitu, frame yang diterima tetap hanya disimpan satu.
Bagian “meski panjang frame dibuat tetap, protokol di atasnya tidak terpengaruh, karena protokol tingkat atas mengodekan ukuran paket di header dan tidak bergantung pada panjang frame Ethernet sebenarnya” menarik.
Baru-baru ini saya membuat packet decoder, dan di setiap layer saya secara eksplisit memverifikasi apakah panjang dari layer bawah sesuai. Untuk IP, di decoder saya panjang datagram IP harus persis cocok dengan panjang frame Ethernet dan panjang header link-layer.
Itu bukan karena ingin terlalu teliti, melainkan untuk mendeteksi frame pendek; belakangan saya juga memutuskan untuk menganggap frame panjang sebagai error. Penulis memakai uIP, tetapi saya penasaran bagaimana Linux atau OS modern lain menanganinya. Saya juga jadi penasaran apakah sudah dilakukan pengujian interoperabilitas.
Jika aplikasi tidak melihat data L2, stack IP Linux akan mengabaikannya begitu saja.
Secara fisik jauh lebih kecil daripada set kartu SSI Ethernet pertama DEC: https://i.ebayimg.com/images/g/NEYAAOSw-mZlg0lZ/s-l1600.jpg
Papan DEC DEUNA panjangnya lebih dari 1 kaki, tetapi fungsinya juga jauh lebih banyak. DEUNA adalah NIC “sungguhan”, punya antrean kirim/terima, menanganinya secara mandiri, dan juga melakukan DMA. Tentu saja di atas kartunya juga ada PDP-11 sendiri untuk menjalankannya.
Keren sekali. Saya penasaran butuh berapa lama.
Ini menunjukkan betapa mudahnya menanam backdoor di dalam chip yang terhubung ke port jaringan.
Di mata kuliah Communication Systems Engineering, saya mengimplementasikan pemrosesan sinyal Ethernet, lalu mengimplementasikan stack TCP/IP termasuk ARP dan switching dalam assembler Motorola 68k QUIC.
Itu 18 bulan terpanjang dalam hidup saya.