Berlatih dalam bekerja dengan ban khusus dari kompleks Redd

Dalam artikel terakhir, kami memeriksa teori mengelola ribuan hal kecil di kompleks Redd, tetapi agar tidak menambah volume, kami menunda praktik di waktu berikutnya. Waktunya telah tiba untuk melakukan eksperimen praktis. Mereka yang tidak menggunakan kompleks Redd juga akan dapat menemukan pengetahuan yang berguna dalam artikel ini, yaitu, metodologi untuk mengirim perintah Vendor ke drive USB dari Linux, karena, sebagaimana telah disebutkan, pengontrol STM32 di kompleks melakukan fungsi pembaca SD, yaitu, berkendara.




Drive klasifikasi dengan sistem perintah


Saat bekerja dengan drive, Anda harus membedakan antara antarmuka fisik dan sistem perintah. Khususnya, drive CD / DVD / BD dan optik lainnya. Secara tradisional, mereka terhubung ke kabel SATA (sebelumnya IDE). Tetapi secara khusus pada kawat ini, hanya perintah PACKET yang dijalankan selama operasi, di blok data yang perintahnya disandikan sesuai dengan prinsip yang sama sekali berbeda ditempatkan (kita akan segera mengetahui yang mana). Oleh karena itu, sekarang kita tidak akan berbicara banyak tentang kabel, tetapi tentang tim yang menjalankannya. Saya tahu tiga sistem perintah umum untuk bekerja dengan drive.

  • MMC Ini dipahami oleh kartu SD. Jujur saja, bagi saya ini adalah sistem komando yang paling misterius. Cara mengirimkannya, tampaknya, jelas, tetapi cara mengelola drive tanpa hati-hati membaca dokumen yang mengandung banyak grafik transisi - Saya selalu bingung. Untungnya, ini tidak mengganggu kita hari ini, karena meskipun kita bekerja dengan kartu SD, pengendali STM32 dalam mode "kotak hitam" bekerja dengannya.
  • ATA Awalnya, perintah-perintah ini dijalankan pada bus IDE, kemudian pada SATA. Sistem komando yang luar biasa, tetapi hari ini kami juga hanya menyebutkan bahwa itu ada.
  • SCSI Sistem perintah ini digunakan pada berbagai perangkat. Pertimbangkan penggunaannya dalam drive. Di sana, hari ini tim SCSI menjalankan, pertama-tama, di sepanjang kabel bus SAS (omong-omong, bahkan SSD dengan antarmuka SAS kini sedang populer). Anehnya, drive optis yang terhubung secara fisik ke bus SATA juga berfungsi melalui perintah SCSI. Di bus USB saat bekerja sesuai dengan standar Mass Storage Device, perintah juga masuk dalam format SCSI. Mikrokontroler STM32 terhubung ke kompleks Redd melalui bus USB, yaitu, dalam kasus kami, perintah mengikuti jalur berikut:



Dari PC ke controller, melalui USB, perintahnya dalam format SCSI. Pengontrol mentranskode perintah sesuai dengan aturan MMC dan mengirimkannya melalui bus SDIO. Tetapi kita harus menulis sebuah program untuk PC, sehingga tim meninggalkan kita dalam format SCSI. Mereka disiapkan oleh driver perangkat Mass Storage Device, yang kami berkomunikasi dengan melalui driver sistem file. Apakah mungkin untuk menggabungkan permintaan dengan perangkat lain untuk permintaan ini? Mari kita perbaiki.

Detail Sistem Perintah SCSI


Jika Anda mendekati masalah ini secara formal, maka deskripsi standar SCSI tersedia di t10.org, tetapi kami akan realistis. Tidak ada yang akan membacanya dengan sukarela. Lebih tepatnya, bukan miliknya, tetapi milik mereka: ada setumpuk dokumen terbuka dan segunung dokumen tertutup. Hanya kebutuhan ekstrem yang akan membuat Anda membenamkan diri dalam bahasa rumit yang menjadi standar penulisan ini (ini, omong-omong, berlaku untuk standar ATA di t13.org). Jauh lebih mudah untuk membaca dokumentasi untuk drive nyata. Itu ditulis dalam bahasa yang lebih hidup, dan bagian hipotetis tetapi tidak benar-benar digunakan dipotong dari itu. Dalam mempersiapkan artikel, saya menemukan dokumen (2016) yang agak baru dari Seagate's Commands Reference Manual Manual (tautan langsung www.seagate.com/files/staticfiles/support/docs/manual/Interface%20manuals/100293068j.pdf tetapi, seperti biasa, Saya tidak tahu berapa lama dia akan hidup). Saya pikir jika seseorang ingin menguasai sistem perintah ini, ia harus mulai dengan dokumen ini. Kami hanya ingat bahwa pembaca SD menerapkan subset perintah yang bahkan lebih kecil dari deskripsi itu.

Secara singkat, unit perintah dengan panjang 6 hingga 16 byte dikirim ke drive. Blok data dapat dilampirkan ke blok perintah baik dari PC ke drive, atau dari drive ke PC (standar SCSI juga memungkinkan pertukaran dua arah, tetapi untuk Mass Storage Device via USB hanya satu blok yang diizinkan, yang berarti bahwa arahnya hanya satu). Dalam blok instruksi, byte pertama selalu merupakan kode perintah. Byte yang tersisa adalah argumennya. Aturan untuk mengisi argumen dijelaskan secara eksklusif oleh rincian implementasi perintah.



Pada awalnya saya memasukkan banyak contoh ke dalam artikel, tetapi kemudian saya menyadari bahwa mereka membuat sulit membaca. Oleh karena itu, saya menyarankan semua orang untuk membandingkan bidang perintah READ CAPACITY (10) dari tabel 119 dari dokumen Seigate dan bidang-bidang perintah READ (10) dari tabel 97 dari dokumen yang sama (lihat tautan di atas). Siapa yang tidak menemukan koneksi - jangan khawatir. Itulah yang ingin saya tunjukkan. Selain bidang "perintah" dalam byte nol, tujuan semua bidang hanya bergantung pada spesifikasi perintah tertentu. Anda selalu perlu membuka dokumen dan mempelajari tujuan dari bidang yang tersisa di dalamnya.

Jadi:

  • Untuk berkomunikasi dengan drive, Anda harus membentuk blok perintah dengan panjang 6 hingga 16 byte (tergantung pada format perintah, angka yang tepat ditunjukkan dalam dokumentasi untuk itu).
  • Yang paling penting adalah byte nol dari blok: dialah yang menetapkan kode perintah.
  • Bytes blok yang tersisa tidak memiliki tujuan yang jelas. Untuk memahami cara mengisinya, Anda harus membuka dokumentasi untuk tim tertentu.
  • Blok data yang dapat ditransfer ke atau dari drive dapat dilampirkan ke perintah.

Sebenarnya itu saja. Kami mempelajari aturan untuk mengeluarkan perintah SCSI. Sekarang kita bisa mengirimkannya, akan ada dokumentasi tentang mereka. Tetapi bagaimana melakukannya di tingkat sistem operasi?

Perintah Linux SCSI


Cari perangkat target


Untuk mengeluarkan perintah, buka perangkat disk. Ayo cari namanya. Untuk melakukan ini, kita akan pergi dengan cara yang persis sama seperti pada artikel tentang port serial . Mari kita lihat daftar "file" di direktori / dev (ingat bahwa pada perangkat Linux juga ditampilkan sebagai file dan daftar mereka ditampilkan dengan perintah ls yang sama).

Hari ini kami memperhatikan disk direktori virtual:



Kami melihat isinya:



Kumpulan direktori bersarang yang familier! Kami mencoba untuk mempertimbangkan direktori by-id , menggunakan –l switch dari perintah ls , yang sudah akrab bagi kami dari artikel di port serial:



Kata-kata yang disorot berbicara sendiri. Ini adalah drive yang berisi kartu SD internal kompleks Redd. Hebat! Sekarang kita tahu bahwa perangkat MIR_Redd_Internal_SD sesuai dengan perangkat / dev / sdb dan / dev / sdb1 . Yang tanpa nomor adalah drive itu sendiri, kami akan bekerja dengannya, dan dengan nomor itu adalah sistem file yang terletak pada media yang dimasukkan ke dalamnya. Dalam hal bekerja dengan kartu SD, / dev / sdb adalah pembaca, dan / dev / sdb1 adalah sistem file pada kartu yang dimasukkan ke dalamnya.

Fungsi sistem operasi untuk mengeluarkan perintah


Biasanya, dalam OS apa pun, semua hal non-standar dengan perangkat dilakukan melalui permintaan langsung ke pengemudi. Di Linux, fungsi ioctl () tersedia untuk mengirim permintaan tersebut. Kasus kami tidak terkecuali. Sebagai argumen, kami meneruskan permintaan SG_IO yang dijelaskan dalam file header sg.h. Struktur sg_io_hdr_t yang berisi parameter permintaan juga dijelaskan di sana. Saya tidak akan memberikan struktur penuh, karena tidak semua bidangnya harus diisi. Saya hanya akan memberikan yang paling penting di antara mereka:

typedef struct sg_io_hdr { int interface_id; /* [i] 'S' for SCSI generic (required) */ int dxfer_direction; /* [i] data transfer direction */ unsigned char cmd_len; /* [i] SCSI command length ( <= 16 bytes) */ unsigned char mx_sb_len; /* [i] max length to write to sbp */ unsigned short int iovec_count; /* [i] 0 implies no scatter gather */ unsigned int dxfer_len; /* [i] byte count of data transfer */ void * dxferp; /* [i], [*io] points to data transfer memory or scatter gather list */ unsigned char * cmdp; /* [i], [*i] points to command to perform */ unsigned char * sbp; /* [i], [*o] points to sense_buffer memory */ unsigned int timeout; /* [i] MAX_UINT->no timeout (unit: millisec) */ 

Tidak masuk akal untuk menggambarkan bidang-bidang yang didokumentasikan dengan baik dalam komentar ( interface_id, dxfer_direction, timeout ). Artikel sudah berkembang.

Bidang cmd_len berisi jumlah byte di blok perintah, dan cmdp berisi pointer ke blok ini. Anda tidak dapat melakukannya tanpa perintah, sehingga jumlah byte harus nol (dari 6 hingga 16).

Data bersifat opsional. Jika ya, maka panjang buffer yang dipilih ditentukan dalam bidang dxfer_len , dan penunjuknya ditentukan dalam bidang dxferp . Drive secara fisik dapat mentransfer lebih sedikit data daripada ukuran buffer yang ditentukan. Arah transmisi ditentukan dalam bidang dxfer_direction . Nilai Perangkat Mass Storage USB yang valid adalah: SG_DXFER_NONE, SG_DXFER_TO_DEV, SG_DXFER_FROM_DEV . Ada satu hal lagi dalam file header, tetapi standar Mass Storage Device tidak memungkinkan untuk mengimplementasikannya secara fisik.

Anda juga dapat meminta pengembalian kode kesalahan yang diperluas ( SENSE ). Apa itu dapat ditemukan di dokumen Segate, bagian 2.4. Panjang buffer yang dialokasikan ditunjukkan di bidang mx_sb_len , dan pointer ke buffer itu sendiri ditunjukkan di bidang sbp .

Seperti yang Anda lihat, semua yang saya bicarakan di atas terisi dalam struktur ini (ditambah Anda dapat memperoleh informasi tambahan tentang kesalahan). Baca lebih lanjut tentang bekerja dengan permintaan SG_IO di sini: sg.danny.cz/sg/sg_io.html

Kami mengirim perintah standar ke drive


Kami menemukan format perintah, kami mencari tahu perangkat mana yang akan dikirim, kami menemukan fungsi untuk menelepon. Mari kita coba mengirim beberapa perintah standar ke perangkat kita. Biarkan ini menjadi perintah untuk mendapatkan nama drive. Ini adalah bagaimana itu dijelaskan dalam dokumen Sigeyt:



Harap dicatat bahwa menurut ideologi-SCSI, semua bidang dalam perintah standar diisi dengan notasi Big Endian, yaitu byte maju ke depan. Oleh karena itu, kami mengisi bidang dengan panjang buffer tidak dalam format "0x80, 0x00", tetapi sebaliknya - "0x00, 0x80". Tapi ini dalam perintah standar. Dalam non-standar semuanya mungkin, Anda harus selalu berkonsultasi dengan deskripsi. Sebenarnya, hanya kode perintah ( 12 jam ) dan panjang yang harus kita isi. Kami akan meminta halaman nol, dan bidang lainnya dicadangkan, atau kedaluwarsa, atau default ke nol. Jadi isi semuanya dengan nol.

Kami membuat program yang memberikan perintah ini:
 #include <cstdio> #include <stdint.h> #include <string.h> #include <fcntl.h> // open #include <unistd.h> // close #include <sys/ioctl.h> #include <scsi/scsi.h> #include <scsi/sg.h> int main() { printf("hello from SdAccessTest!\n"); int s_fd = open("/dev/sdb", O_NONBLOCK | O_RDWR); if (s_fd < 0) { printf("Cannot open file\n"); return -1; } sg_io_hdr_t header; memset(&header;, 0, sizeof(header)); uint8_t cmd12h[] = { 0x12,0x00,0x00,0x00,0x80,0x00}; uint8_t data[0x80]; uint8_t sense[0x80]; header.interface_id = 'S'; //  'S' //  header.cmd_len = sizeof(cmd12h); header.cmdp = cmd12h; //  header.dxfer_len = sizeof(data); header.dxferp = data; header.dxfer_direction = SG_DXFER_TO_FROM_DEV; //     header.mx_sb_len = sizeof(sense); header.sbp = sense; // header.timeout = 100; // 100  int res = ioctl(s_fd, SG_IO, &header;); close(s_fd); return 0; } 



Bagaimana menjalankan program tersebut pada perangkat Redd jarak jauh, kita telah membahas di salah satu artikel sebelumnya . Benar, memulainya untuk pertama kalinya, saya segera menerima kesalahan memanggil fungsi open () . Ternyata pengguna secara default tidak memiliki hak yang cukup untuk membuka perangkat disk. Yang mana dari saya adalah spesialis Linux, saya menulis berkali-kali, tetapi pada jaringan saya berhasil menemukan bahwa untuk mengatasi masalah ini, Anda dapat mengubah hak akses ke perangkat dengan mengeluarkan perintah:

sudo chmod 666 / dev / sdb

Namun, bos saya (dan dia adalah spesialis hebat dalam OS ini) kemudian mencatat bahwa solusinya valid sampai sistem operasi di-boot ulang. Untuk mendapatkan hak pasti, Anda perlu menambahkan pengguna ke grup disk .

Mana pun dari dua jalur ini yang kita tuju, tetapi setelah semuanya berhasil, letakkan breakpoint pada baris tutup (s_fd); dan periksa hasilnya pada saat itu dicapai dalam lingkungan pengembangan (karena program ini bahkan bukan satu hari, yang berarti bahwa kita tidak punya waktu untuk menghabiskan waktu dan upaya memasukkan pembuat peta, jika lingkungan pengembangan dapat menunjukkan kepada kita segalanya). Nilai res adalah nol. Jadi tim bekerja tanpa kesalahan.



Apa yang datang ke buffer? Ketika saya memasukkan kata data di alamat untuk dump, mereka mengatakan kepada saya bahwa mereka tidak dapat menghitung nilainya, saya harus memasukkan & data; . Aneh, karena data adalah pointer, ketika debugging di Windows semuanya berfungsi, tapi saya perhatikan fakta ini, kerjanya seperti ini: lihat hasil yang didapat seperti ini:



Itu benar, mereka mengembalikan nama dan revisi drive kepada kami. Informasi lebih lanjut tentang format struktur yang dihasilkan dapat ditemukan dalam dokumen Segate (bagian 3.6.2, tabel 59). Buffer indra tidak mengisi, tetapi deskripsi IOCTL dari permintaan mengatakan bahwa itu diisi hanya ketika kesalahan terjadi yang mengembalikan sesuatu di buffer ini. Secara harfiah: Sense data (hanya digunakan ketika 'status' adalah PERIKSA KONDISI atau (driver_status & DRIVER_SENSE) adalah benar) .

Format Perintah Kustom untuk Redd Internal SD Drive


Sekarang kita tidak hanya mempelajari deskripsi kering dari standar, tetapi juga mencoba segala sesuatu dalam praktik, setelah mengalami apa itu command block, kita sudah dapat menunjukkan format perintah yang dengannya Anda dapat memanggil fungsi-fungsi non-standar yang "di-flash" ke pengontrol STM32 pada papan kompleks. Saya memilih kode perintah dari awal rentang spesifik Vendor dari perintah. Itu sama dengan 0xC0. Secara tradisional, dalam deskripsi perintah SCSI, tulis C0h . Panjang perintah selalu 10 byte. Format tim disatukan dan disajikan dalam tabel di bawah ini.

ByteJanji temu
0Kode Perintah C0h
1Kode Sub-Perintah
2Argumen arg1. Diatur dalam notasi Little Endian (forward byte rendah)
3
4
5
6Argumen arg2. Diatur dalam notasi Little Endian (forward byte rendah)
7
8
9

Seperti yang Anda lihat, argumen diberikan dalam notasi Little Endian. Ini akan memungkinkan Anda untuk menggambarkan perintah dalam bentuk struktur dan mengakses bidangnya secara langsung, tanpa menggunakan fungsi permutasi byte. Masalah perataan (kata-kata dobel dalam struktur memiliki offset yang bukan kelipatan empat) pada arsitektur x86 dan x64 tidak sepadan.

Kode sub-perintah dijelaskan oleh enumerasi berikut:
 enum vendorSubCommands { subCmdSdEnable = 0, // 00 Switch SD card to PC or Outside subCmdSdPower, // 01 Switch Power of SD card On/Off subCmdSdReinit, // 02 Reinitialize SD card (for example, after Power Cycle) subCmdSpiFlashEnable, // 03 Switch SPI Flash to PC or Outside subCmdSpiFlashWritePage, // 04 Write Page to SPI Flash subCmdSpiFlashReadPage, // 05 Read Page from SPI Flash subCmdSpiFlashErasePage,// 06 Erase Pages on SPI Flash (4K block) subCmdRelaysOn, // 07 Switch relays On by mask subCmdRelaysOff, // 08 Switch relays off by mask subCmdRelaysSet, // 09 Set state of all relays by data subCmdFT4222_1_Reset, // 0A Activate Reset State or switch chip to normal mode subCmdFT4222_2_Reset, // 0B Activate Reset State or switch chip to normal mode subCmdFT4222_3_Reset, // 0C Activate Reset State or switch chip to normal mode subCmdFT4232_Reset, // 0D Activate Reset State or switch chip to normal mode subCmdFT2232_Reset, // 0E Activate Reset State or switch chip to normal mode subCmdMAX3421_Reset, // 0F Activate Reset State or switch chip to normal mode subCmdFT4222_1_Cfg, // 10 Write to CFG pins of FT4222_1 subCmdFT4222_2_Cfg, // 11 Write to CFG pins of FT4222_2 subCmdFT4222_3_Cfg, // 12 Write to CFG pins of FT4222_3 }; 

Mereka dapat dibagi menjadi beberapa kelompok.

Berpindah perangkat ke mode internal dan eksternal


Perintah subCmdSdEnable dan subCmdSpiFlashEnable masing-masing mengganti kartu SD dan flash SPI. Parameter arg1 melewati salah satu nilai berikut:

 enum enableMode { enableModeToPC = 0, enableModeOutside }; 

Secara default, kedua perangkat terhubung ke PC.

Peralihan daya


Protokol SDIO membutuhkan cukup banyak manipulasi selama inisialisasi. Kadang-kadang berguna untuk mengatur ulang kartu SD ke keadaan awal (misalnya, ketika mengganti jalurnya ke konektor eksternal). Untuk melakukan ini, matikan, lalu nyalakan daya. Ini dapat dilakukan dengan menggunakan perintah subCmdSdPower . Dalam argumen arg1, salah satu dari nilai berikut ini diteruskan: 0 - matikan, 1 - matikan. Ingatlah untuk memberikan waktu untuk melepaskan kapasitor pada saluran listrik.

Setelah menyalakan daya, kartu, jika terhubung ke PC, harus diinisialisasi ulang. Untuk melakukan ini, gunakan perintah subCmdSdReinit (tidak memiliki argumen).

Bekerja dengan SPI flash drive


Jika kartu SD terhubung ke sistem sebagai drive penuh, chip akses dalam versi saat ini sangat terbatas. Anda hanya dapat mengakses halaman individualnya (256 byte) dan hanya satu per satu. Jumlah memori dalam rangkaian mikro sedemikian rupa sehingga bahkan ketika bekerja di halaman, prosesnya tidak akan memakan banyak waktu, tetapi pendekatan ini sangat menyederhanakan "firmware" dari mikrokontroler.

Perintah subCmdSpiFlashReadPage membaca halaman. Alamatnya ditentukan dalam parameter arg1, jumlah halaman yang akan dikirim dalam parameter arg2. Tetapi dalam versi saat ini, jumlah halaman harus sama dengan satu. Perintah akan mengembalikan 256 byte data.

Dicerminkan baginya adalah perintah subCmdSpiFlashWritePage . Argumen untuknya diisi oleh prinsip yang sama. Arah transfer data adalah ke perangkat.

Kekhasan memori flash adalah bahwa hanya bit tunggal yang dapat diganti dengan nol bit selama perekaman. Untuk mengembalikannya ke nilai tunggal, halaman harus dihapus. Ada perintah subCmdSpiFlashErasePage untuk ini . Benar, karena fitur dari sirkuit mikro yang digunakan, itu bukan halaman tunggal yang diatur dalam parameter arg1 yang dihapus, tetapi blok 4 kilobyte yang mengandungnya.

Manajemen Relay Solid State


Kompleks ini memiliki enam relai keadaan padat. Ada tiga tim untuk mengelolanya.

subCmdRelaysSet - menetapkan nilai keenam relay secara bersamaan. Dalam parameter arg1, nilai dilewatkan, setiap bit yang sesuai dengan relay sendiri (nol bit - relay dengan indeks 0, bit pertama dengan indeks 1, dll). Nilai bit tunggal menutup relai, nilai nol menyebabkannya terbuka.

Metode operasi ini bagus ketika semua relay bekerja sebagai satu kelompok. Jika mereka bekerja secara independen satu sama lain, dengan pendekatan ini Anda harus memulai variabel penyangga yang menyimpan nilai keadaan semua relay. Jika relay yang berbeda dikendalikan oleh program yang berbeda, masalah penyimpanan nilai agregat menjadi sangat akut. Dalam hal ini, Anda dapat menggunakan dua perintah lain:

subCmdRelaysOn - memungkinkan relay terpilih dengan mask. Relai yang sesuai dengan bit unit dalam argumen arg1 akan diaktifkan. Relay yang sesuai dengan nol di topeng akan mempertahankan statusnya saat ini.

Perintah subCmdRelaysOff yang mencerminkan perintah itu akan mematikan relai yang dipilih oleh mask. Relai yang sesuai dengan bit tunggal dalam argumen arg1 akan dimatikan. Relay yang sesuai dengan nol di topeng akan mempertahankan statusnya saat ini.

Setel ulang pengontrol FTDI dan Maxim


Untuk mengirim sinyal reset ke sirkuit mikro FTDI dan Maxim, kelompok perintah subCmdFT4222_1_Reset , subCmdFT4222_2_Reset , subCmdFT4222_3_Reset , subCmdFT4232_Reset , subCmdFT2232_Reset , subCmdFT2232_Reset , dan subCmdMA_21 digunakan . Dari namanya, Anda dapat melihat chip mana yang mereka kontrol dengan mengatur ulang sinyal. Jembatan FT4222, seperti yang kita bahas sebelumnya, adalah dua di sirkuit (indeksnya 1 dan 2), jembatan FT4222 lainnya mentransfer data ke chip MAX3421, yang akan kita bahas dalam artikel berikutnya.

Parameter arg1 melewati salah satu nilai berikut:

 enum ResetState { resetStateActive =0, resetStateNormalOperation }; 

Secara default, semua jembatan dalam kondisi kerja normal. Seperti yang sudah disebutkan dalam artikel sebelumnya , kami sendiri tidak yakin apakah fungsi ini diperlukan, tetapi ketika tidak ada akses langsung ke perangkat, lebih baik untuk mengatur ulang semuanya dari jarak jauh.

Berpindah jalur konfigurasi chip FT4222


Chip FT4222 memiliki empat mode. Tidak mungkin ada orang yang memerlukan mode selain "00", tetapi jika Anda tiba-tiba membutuhkannya, Anda dapat menggunakan subCmdFT4222_1_Cfg , subCmdFT4222_2_Cfg, dan perintah subCmdFT4222_3_Cfg untuk beralih untuk chip pertama, kedua, dan ketiga. Nilai garis CFG0 dan CFG1 diatur dalam dua bit lebih rendah dari parameter arg1 .

Pengalaman praktis dalam mengeluarkan perintah ke pengontrol STM32


Untuk menguji materi teoretis yang diperoleh dalam praktik, kami akan mencoba untuk mematikan kartu SD. Untuk melakukan ini, keluarkan perintah subCmdSdEnable dengan kode 0x00 dengan argumen enableModeOutside dengan kode 0x01. Bagus Kami menulis ulang program dari pengalaman masa lalu sebagai berikut.

Program ditulis ulang:
 #include <cstdio> #include <stdint.h> #include <string.h> #include <fcntl.h> // open #include <unistd.h> // close #include <sys/ioctl.h> #include <scsi/scsi.h> #include <scsi/sg.h> int main() { printf("hello from SdAccessTest!\n"); int s_fd = open("/dev/sdb", O_NONBLOCK | O_RDWR); if (s_fd < 0) { printf("Cannot open file\n"); return -1; } sg_io_hdr_t header; memset(&header;, 0, sizeof(header)); uint8_t cmdSdToOutside[] = { 0xC0,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; uint8_t cmdSdToPC[] = { 0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; uint8_t sense[32]; memset(sense, 0, sizeof(sense)); header.interface_id = 'S'; //  'S' //  header.cmd_len = sizeof(cmdSdToOutside); header.cmdp = cmdSdToOutside; //  ( ) header.dxfer_len = 0; header.dxferp = 0; header.dxfer_direction = SG_DXFER_NONE; //     header.mx_sb_len = sizeof(sense); header.sbp = sense; // header.timeout = 100; // 100  int res = ioctl(s_fd, SG_IO, &header;); //   header.cmdp = cmdSdToPC; res = ioctl(s_fd, SG_IO, &header;); close(s_fd); return 0; } 


Kami mengubah panjang perintah menjadi sepuluh byte dan menghapus blok data. Yah, mereka menuliskan kode perintah dengan argumen, sesuai kebutuhan. Kalau tidak, semuanya tetap sama. Kita mulai ... Dan ... Tidak ada yang berhasil. Fungsi ioctl () mengembalikan kesalahan. Alasannya dijelaskan dalam dokumen perintah SG_IO . Faktanya adalah bahwa kita memberikan perintah Vendor Specific C0h , dan berikut ini dikatakan tentang mereka secara harfiah:
Perintah SCSI (opcode) lainnya yang tidak disebutkan untuk driver sg membutuhkan O_RDWR. Perintah SCSI (opcode) lainnya yang tidak disebutkan untuk lapisan blok SG_IO ioctl membutuhkan pengguna dengan kemampuan CAP_SYS_RAWIO.

Seperti yang dijelaskan bos kepada saya (saya hanya menceritakan kembali kata-katanya), nilai kapabilitas ditugaskan ke file yang dapat dieksekusi. Untuk alasan ini, saya harus melacak dari lingkungan pengembangan dengan masuk sebagai root . Bukan solusi terbaik, tetapi setidaknya sesuatu. Bahkan, pada Windows, permintaan IOCTL_SCSI_PASS_THROUGH_DIRECT juga memerlukan hak administrator. Mungkin di komentar seseorang akan memberikan saran tentang cara mengatasi masalah penelusuran tanpa langkah drastis seperti itu, tetapi Anda dapat menjalankan program yang sudah ditulis tanpa root , jika Anda mendaftarkan kemampuan yang benar untuk itu . Sementara itu, ubah nama pengguna di lingkungan pengembangan dan atur breakpoint di telepon:

 int res = ioctl(s_fd, SG_IO, &header;); 

dan sebelum memanggil fungsi ioctl () , kita melihat daftar perangkat penyimpanan:



Panggil ioctl () dan lihat daftar lagi:



Perangkat / dev / sdb tetap (secara kasar, ini adalah pembaca kartu SD itu sendiri), dan / dev / sdb1 menghilang. Perangkat ini sesuai dengan sistem file di media. Pembawa terputus dari komputer - tidak lagi terlihat. Kami terus melacak. Setelah memanggil fungsi ioctl () kedua, kami kembali melihat daftar perangkat:



Kartu SD dihubungkan kembali ke sistem, sehingga / dev / sdb1 kembali ke tempatnya. Sebenarnya, kami belajar cara mengeluarkan perintah khusus vendor dan mengelola perangkat berbasis mikrokontroler STM32 di kompleks Redd. Perintah lain akan diserahkan kepada pembaca untuk belajar mandiri. Anda dapat mengontrol operasi beberapa dari mereka dengan cara yang sama. Jika beberapa chip ftdi masuk ke kondisi reset, perangkat yang sesuai akan menghilang dari sistem. Pengoperasian relai dan kontrol kaki konfigurasi harus dikontrol dengan alat ukur. Nah, Anda dapat memeriksa pekerjaan dengan flash drive dengan menulis halaman dengan kontrol bacaan berikutnya.

Kesimpulan


Kami memeriksa dua topik besar yang tidak terkait dengan FPGA di kompleks Redd. Yang ketiga tetap - bekerja dengan chip MAX3421, yang memungkinkan implementasi perangkat USB 2.0 FS. Sebenarnya, ada host juga, tetapi ada banyak host dan motherboard. Fungsionalitas perangkat akan memungkinkan kompleks untuk berpura-pura menjadi USB flash drive (untuk mengirim pembaruan "firmware"), keyboard USB (untuk mengontrol unit eksternal), dll. Kami akan mempertimbangkan topik ini di artikel selanjutnya.

Source: https://habr.com/ru/post/id484706/


All Articles