في
المقال الأخير ، درسنا نظرية إدارة ألف الأشياء الصغيرة في مجمع Redd ، ولكن من أجل عدم تضخيم الحجم ، قمنا بتأجيل هذه الممارسة في المرة القادمة. لقد حان الوقت لإجراء تجارب عملية. سيتمكن أولئك الذين لا يستخدمون Redd complex أيضًا من العثور على معرفة مفيدة في هذه المقالة ، وهي منهجية إرسال أوامر Vendor إلى محركات أقراص USB من نظام Linux ، لأن وحدة التحكم STM32 في المجمع ، كما ذُكر سابقًا ، تؤدي وظيفة قارئ SD ، أي القيادة.

تصنيف محرك بواسطة أنظمة القيادة
عند العمل مع محركات الأقراص ، يجب التمييز بين الواجهة الفعلية ونظام الأوامر. على وجه الخصوص ، محركات الأقراص CD / DVD / BD وغيرها من البصريات. تقليديًا ، يتصلون بكبل SATA (IDE سابقًا). لكن على وجه التحديد ، يتم تشغيل أوامر PACKET فقط أثناء التشغيل ، حيث يتم وضع أوامر البيانات المشفرة بمبدأ مختلف تمامًا في كتلة البيانات (سنكتشف قريبًا أيًا منها). لذلك ، سنتحدث الآن ليس عن الأسلاك ، ولكن عن الفرق التي تعمل فيها. أعرف ثلاثة أنظمة أوامر شائعة للعمل مع محركات الأقراص.
- MMC. ومن المفهوم من قبل بطاقات SD. بصراحة ، بالنسبة لي هذا هو نظام القيادة الأكثر غموضا. يبدو أن كيفية إرسالها واضحة ، لكن كيفية إدارة محرك الأقراص دون قراءة الوثيقة التي تحتوي على الكثير من الرسوم البيانية الانتقالية - أنا مرتبك دائمًا. لحسن الحظ ، هذا اليوم لا يزعجنا ، لأنه على الرغم من أننا نعمل مع بطاقة SD ، فإن وحدة التحكم STM32 في وضع "الصندوق الأسود" تعمل معها.
- ATA. في البداية ، ركضت هذه الأوامر على ناقل IDE ، ثم على SATA. نظام قيادة رائع ، لكن اليوم نذكر أيضًا أنه موجود.
- SCSI. يستخدم نظام القيادة هذا على مجموعة واسعة من الأجهزة. النظر في استخدامه في محركات الأقراص. هناك اليوم ، تعمل أوامر SCSI في المقام الأول على أسلاك ناقل SAS (بالمناسبة ، حتى SSDs مع واجهة SAS أصبحت الآن). ومن الغريب أن محركات الأقراص الضوئية المتصلة فعلياً بحافلة SATA تعمل أيضًا من خلال أوامر SCSI. على ناقل USB عند العمل وفقًا لمعيار Mass Storage Device ، تذهب الأوامر أيضًا بتنسيق SCSI. يتم توصيل متحكم STM32 بمجمع Redd عبر ناقل USB ، وهذا هو ، في حالتنا ، الأوامر تسير على الطريق التالي:

من الكمبيوتر إلى وحدة التحكم ، عبر USB ، تكون الأوامر بتنسيق SCSI. تقوم وحدة التحكم بترجمة الأوامر وفقًا لقاعدة MMC وترسلها عبر ناقل SDIO. لكن علينا أن نكتب برنامجًا للكمبيوتر الشخصي ، بحيث تتركنا الفرق بتنسيق SCSI. يتم إعدادهم بواسطة برنامج تشغيل جهاز Mass Storage Device ، والذي نتواصل معه من خلال برنامج تشغيل نظام الملفات. هل يمكن مزج الطلبات مع الأجهزة الأخرى لهذه الطلبات؟ هيا بنا
SCSI تفاصيل نظام القيادة
إذا تعاملت مع الأمر بشكل رسمي ، فسيكون وصف معيار SCSI متاحًا على t10.org ، لكننا سنكون واقعيين. لا أحد سوف يقرأها طواعية. بتعبير أدق ، ليس هو نفسه ، ولكن مستنداتهم: توجد كومة كاملة من المستندات المفتوحة وجبل من المستندات المغلقة. فقط هناك حاجة ماسة تجعلك تزج نفسك في اللغة المعقدة التي يكتب بها المعيار (هذا ، بالمناسبة ، ينطبق على معيار ATA على t13.org). من الأسهل بكثير قراءة الوثائق لمحركات الأقراص الحقيقية. هو مكتوب بلغة أكثر حيوية ، ويتم قطع أجزاء افتراضية ولكن لم تستخدم حقا للخروج منه. أثناء إعداد المقالة ، صادفت مستندًا جديدًا إلى حد ما (2016) من
الدليل المرجعي لأوامر SCSI الخاص بـ Seagate (الرابط المباشر
www.seagate.com/files/staticfiles/support/docs/manual/Interface٪20manuals/100293068j.pdf) ، كما هو الحال دائمًا ، لا أعرف كم من الوقت ستعيش). أعتقد أنه إذا أراد شخص ما إتقان نظام الأوامر هذا ، فعليه البدء بهذا المستند. نتذكر فقط أن قارئات SD تنفذ مجموعة فرعية أصغر من الأوامر من هذا الوصف.
يتحدث لفترة وجيزة جدًا ، يتم إرسال وحدة قيادة بطول يتراوح من 6 إلى 16 بايت إلى محرك الأقراص. يمكن توصيل كتلة البيانات بكتلة الأوامر إما من جهاز الكمبيوتر إلى محرك الأقراص ، أو من محرك الأقراص إلى جهاز الكمبيوتر (يسمح معيار SCSI أيضًا بالتبادل ثنائي الاتجاه ، ولكن بالنسبة لجهاز التخزين كبير السعة عبر USB ، يُسمح بلوك واحد فقط ، مما يعني أن الاتجاه واحد فقط). في كتلة التعليمات ، البايت الأول هو دائمًا رمز الأمر. البايتات المتبقية هي وسائطه. يتم وصف قواعد ملء الوسيطات حصريًا بتفاصيل تنفيذ الأمر.

في البداية قمت بإدخال الكثير من الأمثلة في المقالة ، لكنني أدركت بعد ذلك أنها تجعل القراءة صعبة. لذلك ، أقترح على الجميع مقارنة حقول الأمر READ CAPACITY (10) من الجدول 119 من مستند Seigate وحقول الأمر READ (10) من الجدول 97 لنفس المستند (انظر الرابط أعلاه). الذين لم يجدوا أي اتصال - لا تشعر بالقلق. هذا ما أردت أن أظهره. بالإضافة إلى حقل "أمر" في صفر بايت ، فإن الغرض من جميع الحقول يعتمد فقط على تفاصيل أمر معين. تحتاج دائمًا إلى فتح المستند ودراسة الغرض من الحقول المتبقية فيه.
لذلك:
- للتواصل مع محرك الأقراص ، يجب عليك تشكيل كتلة أوامر بطول يتراوح من 6 إلى 16 بايت (حسب تنسيق الأمر ، تتم الإشارة إلى الرقم الدقيق في الوثائق الخاصة به).
- الأهم هو صفر بايت من الكتلة: هو الذي يحدد رمز الأوامر.
- لا تحتوي على بايت كتلة المتبقية غرض واضح. لفهم كيفية ملؤها ، يجب عليك فتح الوثائق لفريق معين.
- يمكن ربط مجموعة من البيانات التي يمكن نقلها من أو إلى محرك أقراص بأمر.
في الواقع ، هذا كل شيء. لقد تعلمنا قواعد إصدار أوامر SCSI. الآن يمكننا تقديمها ، سيكون هناك وثائق عليها. ولكن كيف نفعل ذلك على مستوى نظام التشغيل؟
أوامر SCSI Linux
البحث عن الجهاز المستهدف
لإصدار الأوامر ، افتح جهاز القرص. دعنا نجد اسمه. للقيام بذلك ، سنذهب بنفس الطريقة تمامًا كما في
المقالة حول المنافذ التسلسلية . دعونا نرى قائمة "الملفات" في دليل
/ dev (تذكر أنه على أجهزة Linux تظهر أيضًا كملفات ويتم عرض قائمتها بنفس
الأمر ls ).
اليوم ننتبه إلى
قرص الدليل الظاهري:

نحن ننظر إلى محتوياته:

مجموعة مألوفة من الدلائل المتداخلة! نحن نحاول النظر في الدليل
الفرعي ، باستخدام مفتاح التبديل
-l للأمر ls ، المألوف لنا بالفعل من المقالة على المنافذ التسلسلية:

الكلمات البارزة تتحدث عن نفسها. هذا هو محرك يحتوي على بطاقة SD الداخلية لمجمع Redd. ! ممتاز الآن نعلم أن الجهاز
MIR_Redd_Internal_SD يتوافق مع الجهاز
/ dev / sdb و / dev / sdb1 . الشخص الذي لا يحتوي على الرقم هو محرك الأقراص نفسه ، وسنعمل معه ، والرقم هو نظام الملفات الموجود على الوسائط المدرجة فيه. من حيث العمل مع بطاقة SD ، يعد
/ dev / sdb هو القارئ ، و
/ dev / sdb1 هو نظام الملفات الموجود على البطاقة.
وظيفة نظام التشغيل لإصدار الأوامر
عادة ، في أي نظام تشغيل ، تتم جميع الأشياء غير القياسية مع الأجهزة من خلال الطلبات المباشرة إلى برنامج التشغيل. في نظام Linux ، تتوفر وظيفة
ioctl () لإرسال هذه الطلبات. حالتنا ليست استثناء. كوسيطة ، نقوم بتمرير طلب SG_IO الموضح في ملف الرأس
sg.h. يوصف أيضًا هيكل
sg_io_hdr_t الذي يحتوي على معلمات الطلب. لن أعطي الهيكل الكامل ، حيث لن يتم ملء جميع حقوله. سأقدم فقط أهمها:
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) */
لا معنى لوصف تلك الحقول الموثقة جيدًا في التعليقات (
واجهة_التعريف ، dxfer_direction ، المهلة ). المقالة تنمو بالفعل.
يحتوي الحقل
cmd_len على عدد البايتات في كتلة الأوامر ،
ويحتوي cmdp على مؤشر لهذه الكتلة. لا يمكنك الاستغناء عن أمر ، لذا يجب أن يكون عدد البايتات غير صفري (من 6 إلى 16).
البيانات اختيارية. إذا كانت كذلك ، فسيتم تحديد طول المخزن المؤقت المحدد في حقل
dxfer_len ، ويتم تحديد مؤشر له في حقل
dxferp . يمكن لمحرك الأقراص نقل بيانات أقل فعليًا من حجم المخزن المؤقت المحدد. يتم تحديد اتجاه الإرسال في مجال
dxfer_direction . قيم أجهزة التخزين ذات السعة الكبيرة USB هي:
SG_DXFER_NONE ، SG_DXFER_TO_DEV ، SG_DXFER_FROM_DEV . يوجد شيء آخر في ملف الرأس ، لكن معيار Mass Storage Device لا يسمح بتطبيقه فعليًا.
يمكنك أيضًا طلب إرجاع رمز الخطأ الموسّع (
SENSE ). ما يمكن العثور عليه في مستند Segate ، القسم 2.4. يشار إلى طول المخزن المؤقت المخصص في الحقل
mx_sb_len ،
ويشار إلى المؤشر إلى المخزن المؤقت نفسه في حقل
sbp .
كما ترون ، يتم ملء كل ما تحدثت عنه أعلاه في هذا الهيكل (بالإضافة إلى أنه يمكنك الحصول على معلومات موسعة حول الخطأ). اقرأ المزيد حول العمل مع طلب
SG_IO هنا:
sg.danny.cz/sg/sg_io.htmlنرسل أمر قياسي إلى محرك الأقراص
حسنًا ، اكتشفنا تنسيق الأمر ، اكتشفنا أي جهاز لإرساله إليه ، اكتشفنا الوظيفة التي يجب الاتصال بها. دعونا نحاول إرسال بعض الأوامر القياسية إلى الجهاز لدينا. فليكن هذا الأمر هو الحصول على اسم محرك الأقراص. هذه هي الطريقة الموصوفة في مستند Sigeyt:

يرجى ملاحظة أنه وفقًا لإيديولوجية SCSI ، يتم ملء جميع الحقول الموجودة في الأوامر القياسية بترميز Big Endian ، أي أعلى بايت للأمام. لذلك ، نحن نملأ الحقل بطول المخزن المؤقت ليس بالتنسيق "0x80 ، 0x00" ، ولكن على العكس - "0x00 ، 0x80". ولكن هذا في الأوامر القياسية. في كل شيء غير قياسي ، يمكنك دائمًا الرجوع إلى الوصف. في الواقع ، فقط رمز الأمر (
12H ) والطول الذي يتعين علينا ملء. سنطلب صفحة صفرية ، أما الحقول المتبقية فهي إما محفوظة أو قديمة أو الافتراضي إلى صفر. لذلك املأهم جميعًا بالأصفار.
نصنع برنامجًا يعطي هذا الأمر: #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; }
كيفية تشغيل مثل هذه البرامج على جهاز Redd بعيد ، لقد ناقشنا بالفعل في أحد
المقالات السابقة . صحيح ، عند بدء تشغيله لأول مرة ، تلقيت على الفور خطأ أثناء استدعاء الدالة
open () . اتضح أن المستخدم بشكل افتراضي ليس لديه حقوق كافية لفتح أجهزة القرص. من أنا متخصص في Linux ، كتبت عدة مرات ، لكنني تمكنت من العثور على هذه الشبكة لحل هذه المشكلة ، يمكنك تغيير حقوق الوصول إلى الجهاز عن طريق إصدار الأمر:
سودو شمود 666 / ديف / SDBومع ذلك ، لاحظ مدرب رئيسي (وهو متخصص كبير في نظام التشغيل) لاحقًا أن الحل صالح حتى يتم إعادة تشغيل نظام التشغيل. للحصول على الحقوق بالتأكيد ، تحتاج إلى إضافة المستخدم إلى مجموعة
الأقراص .
أيًا من هذين المسارين نذهب ، ولكن بعد أن
نجح كل شيء ، ضع نقطة توقف على السطر
(s_fd) ؛ وفحص النتائج بحلول الوقت الذي يتم فيه تحقيقه في بيئة التطوير (نظرًا لأن البرنامج لا يستغرق يومًا واحدًا ، مما يعني أنه ليس لدينا وقت لقضاء الوقت والجهد في إدراج المخططين إذا كانت بيئة التطوير يمكنها إظهار كل شيء لنا). قيمة
الدقة هي صفر. لذلك عمل الفريق دون أخطاء.

ما جاء إلى المخزن المؤقت؟ عندما أدخلت كلمة
البيانات في عنوان التفريغ ، أخبروني أنهم لا يستطيعون حساب القيمة ، وكان عليّ إدخال
البيانات &؛ . إنه أمر غريب ، لأن
البيانات هي مؤشر ، عند تصحيح الأخطاء تحت Windows ، يعمل كل شيء ، لكنني لاحظت هذه الحقيقة فقط ، إنها تعمل كما يلي: انظر إلى النتيجة التي تم الحصول عليها مثل هذا:

هذا صحيح ، لقد أعادوا اسم ومراجعة محرك الأقراص لنا. يمكن العثور على مزيد من المعلومات حول تنسيق الهيكل الناتج في مستند Segate (القسم 3.6.2 ، الجدول 59). لم يتم تعبئة المخزن المؤقت
للمعنى ، لكن وصف IOCTL للطلب يقول أنه يتم ملؤه فقط عند حدوث خطأ بإرجاع شيء ما في هذا المخزن المؤقت. حرفيًا:
البيانات المنطقية (تُستخدم فقط عندما يكون "الحالة" هو CHECK CONDITION أو (driver_status & DRIVER_SENSE) صحيحًا) .
تنسيق القيادة المخصص لمحرك الأقراص SD Redd الداخلي
الآن وبعد أن درسنا فقط الوصف الجاف للمعيار ، ولكن أيضًا جربنا كل شيء في الممارسة ، بعد أن واجهنا كتلة الأوامر ، يمكننا بالفعل عرض تنسيق الأوامر الذي يمكنك من خلاله استدعاء الوظائف غير القياسية التي "يتم وميضها" إلى وحدة التحكم STM32 على اللوحة المعقدة. لقد حددت رمز الأمر من بداية مجموعة أوامر
Vendor Specific . إنه يساوي 0xC0. بشكل تقليدي ، في أوصاف أوامر SCSI ، اكتب
C0h . طول الأمر هو دائما 10 بايت. شكل الفريق موحد ويعرض في الجدول أدناه.
كما ترون ، يتم تقديم الحجج في تدوين Little Endian. سيتيح لك ذلك وصف الأمر في شكل بنية والوصول إلى حقولها مباشرةً ، دون اللجوء إلى وظيفة التقليب البايت. مشاكل المحاذاة (الكلمات المزدوجة في الهيكل لها إزاحات لا تتعدى أربعة) على x86 و x64 البنيات لا يستحق كل هذا العناء.
يتم وصف رموز الأوامر الفرعية بواسطة التعداد التالي:
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 };
يمكن تقسيمها إلى مجموعات.
تبديل الأجهزة إلى أوضاع داخلية وخارجية
يعمل
الأمران subCmdSdEnable و
subCmdSpiFlashEnable على تبديل بطاقة SD وفلاش SPI على التوالي. تقوم المعلمة
arg1 بتمرير إحدى القيم التالية:
enum enableMode { enableModeToPC = 0, enableModeOutside };
بشكل افتراضي ، يتم توصيل كلا الجهازين بجهاز كمبيوتر.
تبديل السلطة
يتطلب بروتوكول SDIO الكثير من المعالجة أثناء التهيئة. من المفيد في بعض الأحيان إعادة تعيين بطاقة SD إلى حالتها الأولية (على سبيل المثال ، عند تحويل خطوطها إلى موصل خارجي). للقيام بذلك ، قم بإيقاف تشغيله ، ثم قم بتشغيله. يمكن القيام بذلك باستخدام
الأمر subCmdSdPower . في الوسيطة
arg1 ، يتم تمرير إحدى القيم التالية: 0 - power off ، 1 - power on. تذكر أن تعطي وقتًا لتفريغ المكثفات على خط الطاقة.
بعد تشغيل الطاقة ، يجب إعادة تهيئة البطاقة ، إذا كانت متصلة بالكمبيوتر. للقيام بذلك ، استخدم الأمر
subCmdSdReinit (لا يحتوي على وسيطات).
العمل مع محرك أقراص فلاش SPI
إذا كانت بطاقة SD متصلة بالنظام كمحرك أقراص كامل ، فإن شريحة الوصول في الإصدار الحالي محدودة للغاية. يمكنك الوصول إلى الصفحات الفردية فقط (256 بايت) وصفحة واحدة فقط في كل مرة. إن مقدار الذاكرة في الدائرة المصغرة هو أنه حتى عند العمل على الصفحة ، فإن العملية لن تستغرق الكثير من الوقت على أي حال ، ولكن هذا النهج يبسط إلى حد كبير "البرامج الثابتة" للمراقب الدقيق.
يقرأ الأمر
subCmdSpiFlashReadPage الصفحة. يتم تحديد العنوان في المعلمة arg1 ، وعدد الصفحات المراد إرسالها في المعلمة arg2. ولكن في الإصدار الحالي ، يجب أن يكون عدد الصفحات مساويًا لصفحة واحدة. سيعود الأمر 256 بايت من البيانات.
لها
نسخة متطابقة لها هو الأمر
subCmdSpiFlashWritePage . تمتلئ الحجج لها في نفس المبدأ. اتجاه نقل البيانات إلى الجهاز.
خصوصية ذاكرة الفلاش هي أنه لا يمكن استبدال البتات المفردة إلا بتات صفرية أثناء التسجيل. لإعادتها إلى قيمة واحدة ، يجب أن تمحى الصفحات. يوجد أمر
subCmdSpiFlashErasePage لهذا
الغرض . صحيح ، نظرًا لميزات الدائرة المصغرة المستخدمة ، فهي ليست صفحة واحدة يتم تعيينها في المعلمة
arg1 التي تم محوها ، بل كتلة 4 كيلوبايت تحتوي عليها.
إدارة تتابع الحالة الصلبة
يحتوي المجمع على ستة مرحل الحالة الصلبة. هناك ثلاثة فرق لإدارتها.
subCmdRelaysSet - يحدد قيمة جميع المرحلات الستة في وقت واحد. في المعلمة
arg1 ، يتم تمرير قيمة ، كل جزء منها يتوافق مع مرحلته الخاصة (صفر بت - مرحل مع الفهرس 0 ، أول بت مع الفهرس 1 ، إلخ). تقوم قيمة البتة الواحدة بإغلاق التتابع ، وتؤدي قيمة الصفر إلى فتحه.
طريقة التشغيل هذه جيدة عندما تعمل جميع المرحلات كمجموعة واحدة. إذا كانت تعمل بشكل مستقل عن بعضها البعض ، فمع هذا النهج ، يتعين عليك بدء تشغيل متغير مؤقت يقوم بتخزين قيمة حالة كل المرحلات. في حالة التحكم في المرحلات المختلفة بواسطة برامج مختلفة ، تصبح مشكلة تخزين القيمة الإجمالية شديدة للغاية. في هذه الحالة ، يمكنك استخدام أمرين آخرين:
subCmdRelaysOn - يمكّن المرحلات المحددة بواسطة القناع. سيتم تمكين تلك المرحلات التي تتوافق مع وحدات البت في وسيطة
arg1 . ستحتفظ المرحلات التي تتوافق مع الأصفار الموجودة في القناع بحالتها الحالية.
سيقوم الأمر
subCmdRelaysOff الذي يعكسه بإيقاف تشغيل المرحلات المحددة بواسطة قناع. سيتم إيقاف تشغيل تلك المرحلات التي تتوافق مع البتات الفردية في الوسيطة
arg1 . ستحتفظ المرحلات التي تتوافق مع الأصفار الموجودة في القناع بحالتها الحالية.
إعادة تعيين وحدات تحكم FTDI و Maxim
لإرسال إشارات إعادة
التعيين إلى دوائر FTDI و Maxim الدقيقة ، فإن مجموعة الأوامر
subCmdFT4222_1_Reset و
subCmdFT4222_2_Retet و
subCmdFT4222_3_Reset و
subCmdFT4232_Reset و
subCmdFT4232_Reset و
subCmdFT4232_Reset و
subCmd من أسمائهم يمكنك أن ترى أي رقائق تتحكم فيها عن طريق إعادة تعيين الإشارات. جسور FT4222 ، كما ذكرنا سابقًا ، جسرين في الدائرة (مؤشراتها 1 و 2) ، وجسر FT4222 آخر ينقل البيانات إلى شريحة MAX3421 ، والتي سننظر فيها في المقالة التالية.
تقوم المعلمة
arg1 بتمرير إحدى القيم التالية:
enum ResetState { resetStateActive =0, resetStateNormalOperation };
افتراضيًا ، تكون جميع الجسور في حالة عمل طبيعية. كما ذكرنا
سابقًا في مقال سابق ، نحن لسنا متأكدين مما إذا كانت هذه الوظيفة مطلوبة ، ولكن عندما لا يكون هناك وصول مباشر إلى الجهاز ، فمن الأفضل أن تكون قادرًا على إعادة ضبط كل شيء وكل شيء عن بُعد.
تبديل خطوط التكوين لرقائق FT4222
تحتوي رقائق FT4222 على أربعة أوضاع. من غير المحتمل أن يحتاج أي شخص إلى وضع غير "00" ، ولكن إذا كنت بحاجة إليه فجأة ، فيمكنك استخدام
subCmdFT4222_1_Cfg و
subCmdFT4222_2_Cfg وأوامر subCmdFT4222_3_Cfg للتبديل للشرائح الأولى والثانية والثالثة. يتم تعيين قيمة الأسطر CFG0 و CFG1 في البتاتين الأدنى للمعلمة
arg1 .
خبرة عملية في إصدار الأوامر إلى وحدة التحكم STM32
لاختبار المواد النظرية التي تم الحصول عليها في الممارسة العملية ، سنحاول تبديل بطاقة SD. للقيام بذلك ، قم بإصدار الأمر
subCmdSdEnable برمز 0x00 باستخدام الوسيطة
enableModeOutside مع الرمز 0x01. غرامة. نعيد كتابة البرنامج من التجربة السابقة على النحو التالي.
البرنامج المعاد كتابته: #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; }
قمنا بتغيير طول الأمر إلى عشر بايت وإزالة كتلة البيانات. حسنًا ، قاموا بتدوين رمز الأمر باستخدام الوسائط ، كما هو مطلوب. خلاف ذلك ، كل شيء لا يزال هو نفسه. نبدأ ... و ... لا شيء يعمل. ترجع الدالة
ioctl () خطأ. السبب موصوف في
مستند أمر
SG_IO . الحقيقة هي أننا نعطي الأمر البائع المحدد
C0h ،
ويقال ما يلي عنهم حرفيا:
يحتاج أي أمر SCSI آخر (شفرة تشغيل) لم يرد ذكره لبرنامج تشغيل sg إلى O_RDWR. يحتاج أي أمر SCSI آخر (شفرة تشغيل) لم يتم ذكره لطبقة الكتلة SG_IO ioctl إلى مستخدم لديه قدرة CAP_SYS_RAWIO.
كما أوضح لي الرئيس (أنا فقط أقوم برواية كلماته) ، يتم تعيين قيم
القدرات إلى ملف قابل للتنفيذ. لهذا السبب ، كان علي أن أتتبع من بيئة التطوير عن طريق تسجيل الدخول
كجذر . ليس الحل الأفضل ، لكن على الأقل شيء ما. في الواقع ، على نظام Windows ، يتطلب طلب
IOCTL_SCSI_PASS_THROUGH_DIRECT أيضًا حقوق المسؤول. ربما في التعليقات سيقدم شخص ما النصيحة حول كيفية حل مشكلة التتبع دون مثل هذه الخطوات الجذرية ، لكن يمكنك تشغيل البرنامج المكتوب بالفعل بدون
جذر ، إذا قمت بتسجيل
القدرات الصحيحة
لذلك . في غضون ذلك ، قم بتغيير اسم المستخدم في بيئة التطوير وتعيين نقطة توقف على السطر:
int res = ioctl(s_fd, SG_IO, &header;);
وقبل الاتصال بوظيفة
ioctl () ، ننظر إلى قائمة أجهزة التخزين:

اتصل بـ
ioctl () وانظر إلى القائمة مرة أخرى:

بقي الجهاز
/ dev / sdb (تحدث تقريبًا ، هذا هو قارئ بطاقة SD نفسه) ، و
/ dev / sdb1 اختفى. يتوافق هذا الجهاز مع نظام الملفات على الوسائط. الناقل مفصول عن الكمبيوتر - لم يعد مرئيًا. نواصل البحث عن المفقودين. بعد استدعاء وظيفة
ioctl () الثانية ، ننظر مرة أخرى إلى قائمة الأجهزة:

يتم إعادة توصيل بطاقة SD بالنظام ، لذا فإن
/ dev / sdb1 عادت إلى مكانها. في الواقع ، لقد تعلمنا كيفية إصدار أوامر محددة للبائع وإدارة جهاز يستند إلى متحكم STM32 في مجمع Redd. سيتم ترك الأوامر الأخرى للقراء للدراسة المستقلة. يمكنك التحكم في تشغيل بعضها بطريقة مماثلة. إذا
دخلت بعض شرائح
ftdi في حالة إعادة
التعيين ، فسيختفي الجهاز المقابل من النظام. سيتعين التحكم في تشغيل التتابع والتحكم في أرجل التكوين بواسطة أدوات القياس. حسنًا ، يمكنك التحقق من العمل باستخدام محرك أقراص فلاش عن طريق كتابة الصفحات مع التحكم في القراءة اللاحق.
استنتاج
درسنا موضوعين كبيرين لا يرتبطان بـ FPGAs في مجمع Redd. بقي الثالث - العمل مع رقاقة MAX3421 ، والذي يسمح بتنفيذ أجهزة USB 2.0 FS. في الواقع ، هناك مضيفين أيضًا ، لكن هناك الكثير من المضيفين واللوحة الأم. سوف تسمح وظيفة الجهاز للمجمع بالتظاهر بأنه محرك أقراص USB محمول (لإرسال تحديثات "البرامج الثابتة") ولوحة مفاتيح USB (للتحكم في الوحدات الخارجية) ، إلخ. سننظر في هذا الموضوع في المقال التالي.