Skip to content

Let's code a Linux Driver - 24: Accessing memory mapped IOs from a Platform Device Driver

شرح عملي لكتابة تعريف جهاز مؤقت ARM في نظام لينكس على راسبيري باي مع توضيح الوصول إلى وحدات الإدخال والإخراج المخططة في الذاكرة.

Key Takeaways

  • كتابة تعريف جهاز منصة يتطلب فهم العناوين الفيزيائية للوصول إلى وحدات الإدخال والإخراج.
  • معرفة خريطة العناوين الخاصة بالشرائح ضرورية لتحديد مواقع السجلات.
  • تراكب شجرة الأجهزة (Device Tree Overlay) هو أداة مهمة لإضافة الأجهزة إلى نظام لينكس.
  • يمكن استخدام تعريفات مخصصة لأجهزة غير مدعومة افتراضياً في النظام.
  • تجربة التعريف على أجهزة راسبيري باي من الإصدار 1 إلى 4 ممكنة باستخدام نفس النهج.

What the video covers

  • مقدمة حول كتابة تعريف جهاز مدمج في نظام لينكس لشريحة SoC.
  • استعراض شرائح Broadcom المستخدمة في راسبيري باي من الإصدار 1 إلى 4.
  • تحديد ملحق مؤقت ARM لم يتم تحميل تعريف له افتراضياً.
  • شرح سجلات المؤقت وكيفية التحكم به من خلال تعريف لينكس.
  • مناقشة خريطة العناوين الفيزيائية المعقدة في راسبيري باي للوصول إلى السجلات.
  • حساب العنوان الفيزيائي الصحيح للوصول إلى مؤقت ARM عبر خريطة العناوين.
  • إعداد ملفات برنامج التعريف: كود C، تراكب شجرة الأجهزة، وملف البناء.
  • تعديل تراكب شجرة الأجهزة لتحديد الجهاز والعنوان الفيزيائي وحجم الذاكرة.
  • تنفيذ دوال برنامج التعريف لتعيين الذاكرة والتحكم في المؤقت.
  • اختبار تراكب شجرة الأجهزة وتشغيل المؤقت والتحقق من عمله.

Answers

Questions about this video

لماذا نحتاج إلى كتابة تعريف جديد لمؤقت ARM في راسبيري باي؟

لأن المؤقت ARM المستخدم لا يتم تحميل تعريف له افتراضياً في نظام لينكس، مما يستدعي كتابة تعريف خاص للتحكم به.

كيف يمكن تحديد العنوان الفيزيائي للوصول إلى سجلات المؤقت؟

يتم حساب العنوان الفيزيائي عبر طرح العنوان الأساسي للملحق من العنوان الموثق ثم إضافته إلى عنوان الأجهزة الطرفية الرئيسية في خريطة العناوين الخاصة بالمعالج.

ما هو دور تراكب شجرة الأجهزة (Device Tree Overlay) في تعريف الأجهزة؟

يستخدم تراكب شجرة الأجهزة لإضافة الجهاز إلى نظام لينكس وتحديد خصائصه مثل العنوان الفيزيائي وحجم الذاكرة وسلسلة التوافق.

Full Transcript — Download SRT & Markdown

00:00
Speaker A
أهلاً بكم في حلقة جديدة من دروس تعريفات نظام لينكس. اليوم، سأريكم كيف يمكننا كتابة تعريف لقطعة أجهزة مدمجة داخل نظامنا على شريحة (SoC). ولذلك، يجب أن أوضح لكم كيف يمكننا الوصول إلى وحدات الإدخال والإخراج المخططة في الذاكرة من تعريف
00:18
Speaker A
لينكس. إذًا، متى ستحتاج إلى ما سأعرضه لك اليوم؟ حسناً، ستحتاج إليه إذا كان لديك شريحة جديدة تحتوي على أجهزة لا يوجد لها تعريف مكتوب مسبقاً، أو إذا كنت تعمل مع مصفوفات البوابات المنطقية القابلة للبرمجة (FPGA) ولديك قطعة أجهزة خاصة
00:35
Speaker A
بك مدمجة فيها، وتحتاج أيضاً إلى كتابة تعريف لها. ولكن، حتى وإن لم تكن لديك حالات الاستخدام هذه، فسيكون هذا مفيداً أيضاً إذا أردت فهم التعريفات المكتوبة للملحقات في الأنظمة الموجودة على وحدات (SoM). والتحدي الأول هو العثور على ملحق
00:54
Speaker A
يمكننا كتابة تعريف له. حسناً، أنا أقوم بدروسي على جهاز راسبيري باي. لذا، دعونا نلقي نظرة على الملحقات المتاحة في الشرائح المستخدمة في راسبيري باي. وبناءً على ذلك، سنلقي نظرة على دليل ملحقات ARM لشرائح Broadcom المستخدمة في راسبيري
01:12
Speaker A
باي. هذه الشريحة هنا، BCM2711، هي الشريحة المستخدمة في راسبيري باي 4. ولكن عند الاطلاع على هذه الوثائق، اكتشفت أن جميع الشرائح المستخدمة في إصدارات راسبيري باي الأقدم تشترك في نفس الملحقات الموجودة في الإصدارات الأحدث.
01:33
Speaker A
بالطبع، تمت إضافة بعض الملحقات، لكن الملحقات الأساسية كانت دائماً متشابهة تقريباً بدءاً من الشريحة المستخدمة في راسبيري باي 1 وحتى شريحة راسبيري باي 4.
01:45
Speaker A
لذا، ما سأعرضه لكم اليوم، ستتمكنون من متابعته على الأجهزة من راسبيري باي 1 إلى راسبيري باي 4. أما بالنسبة لجهاز راسبيري باي 5 أو الشريحة المستخدمة فيه، فلم أجد وثيقة ملحقات خاصة به بعد.
01:58
Speaker A
لذا، إذا كانت متاحة لديكم، سأكون ممتناً لو أرسلتم لي الرابط، وربما يمكنني تحديث هذا الفيديو ليعمل أيضاً على راسبيري باي 5. تخبرك هذه الوثيقة بشكل أساسي عن جميع قطع الأجهزة أو الملحقات المختلفة المدمجة في شريحة Broadcom. لدينا بعض الملحقات
02:20
Speaker A
الإضافية. لدينا وحدة تحكم DMA، ومقاطعات، وتعديل عرض النبضة (PWM)، و SPI، و UART، وما إلى ذلك. لكن، بالنسبة لمعظم الملحقات، هناك تعريفات محملة ومتاحة بالفعل. ومع ذلك، وجدت ملحقاً واحداً لا يتم تحميل أي تعريف له افتراضياً. وهذا الملحق هو هذا المؤقت
02:42
Speaker A
هنا. إذن، لدينا هنا مؤقت لجانب الـ ARM. هذا مؤقت ARM يعتمد على ARM SP804، لكنه يختلف في عدة جوانب عن مؤقت SP804 القياسي. بشكل أساسي، لدينا هنا مؤقت أو عداد يعمل بحرية بسعة 16 أو 32 بت. وبالنسبة لهذا الجهاز الطرفي،
03:06
Speaker A
لا يتم تحميل أي تعريف له بشكل افتراضي. لذا، دعونا نكتب التعريف الخاص بنا له. إذن، كيف يعمل مؤقت ARM هذا؟ حسناً، يمكنك رؤية السجلات المتاحة للتحكم في المؤقت هنا بالأسفل. وبالنسبة لنا، تعتبر هذه السجلات الأربعة أو الثلاثة هي المهمة فقط. في سجل
03:28
Speaker A
التحكم، يمكننا ضبط المؤقت وتفعيله أو تعطيله. يوفر لنا سجل القيمة القيمة الحالية للمؤقت. وفي سجل التحميل، يمكننا تعيين قيمة البداية التي سيبدأ المؤقت بالعد التنازلي منها. وبما أنه مؤقت يعمل بحرية، فعندما ينتهي، سيقوم بتحميل القيمة من سجل التحميل مجدداً والبدء من جديد.
03:57
Speaker A
والهدف من فيديو اليوم هو كتابة تعريف يصل إلى هذه السجلات، ويبدأ المؤقت، ويتحقق من أنه يعمل. حسناً، ولكن كيف يمكننا الوصول إلى هذه السجلات؟ ببساطة، يحتاج معالجك فقط إلى الوصول إلى عنوان فيزيائي، ومن ثم سيصل إلى هذه السجلات هنا.
04:20
Speaker A
ولدينا هنا إزاحة ضمن قاعدة السجل، ويمكننا رؤية أن العنوان الأساسي لسجل مؤقت ARM هو 7E00B000 بالنظام الست عشري. وفي العديد من أنظمة الرقائق (System-on-a-Module)، سيكون هذا هو العنوان الفيزيائي الذي يجب أن يصل إليه نواة المعالج للوصول إلى هذه السجلات. لكن
04:43
Speaker A
للأسف، في جهاز Raspberry Pi، الأمر أكثر تعقيداً قليلاً. وهذا يقودنا إلى خريطة العناوين الخاصة بـ Raspberry Pi. أساسياً، على رقاقة Broadcom الموجودة في Raspberry Pi، لدينا ثلاثة مناظر مختلفة للعناوين. هنا، لدينا منظر رئيسي قديم بسعة 32 بت لخريطة العناوين.
05:04
Speaker A
ويقع مؤقت ARM الخاص بنا في مكان ما بين هذا العنوان وذاك العنوان. أي في مكان ما ضمن فئة الأجهزة الطرفية الرئيسية هنا. حسناً، ولكن بالطبع تدعم الرقاقة نفسها منظر عناوين أكبر. لدينا خريطة عناوين بسعة 35 بت، وفي خريطة العناوين هذه، تقع
05:24
Speaker A
الأجهزة الطرفية الرئيسية هنا. ولجعل الأمر أكثر تعقيداً، يمتلك معالج ARM أيضاً منظوره الخاص للعناوين. هنا، تبدأ الأجهزة الطرفية الرئيسية عند هذه القيمة. إذن، كيف نحصل على العنوان الفيزيائي للمعالج للوصول إلى سجلات مؤقت ARM؟ حسناً، لذلك علينا القيام بعملية حسابية
05:50
Speaker A
بسيطة. حسناً، دعني أشغل بايثون هنا لمعرفة العنوان. حسناً، سجل قاعدة مؤقت ARM كان هذا العنوان. لا، هذا هو العنوان الخطأ.
06:02
Speaker A
كان هذا العنوان هنا، حسناً؟ وقد رأيناه في مكان ما في هذه الملحقات الرئيسية. إذاً، دعنا نجد الإزاحة داخل هذه الملحقات الرئيسية.
06:14
Speaker A
للقيام بذلك، ما علينا فعله هو أخذ قيمة مؤقت ARM وطرح... أمم، هذه القيمة هنا. إذاً، يجب أن تكون هذه هي الإزاحة داخل الملحقات الرئيسية، ومن ثم علينا فقط أخذ هذه الإزاحة وإضافتها إلى هذه القيمة هنا للملحقات الرئيسية. إذاً، لنقم بذلك. مهم.
06:44
Speaker A
كإزاحة مضافاً إليها هذه القيمة هنا. وإذا ألقيت نظرة عليه، سنحصل على هذا السجل المادي. والمشكلة هي أن هذا السجل المادي يختلف أيضاً بين إصدارات الرقائق المختلفة المستخدمة في راسمبيري باي، لكن بالنسبة لراسمبيري باي 1 إلى 4، أنا أعرف
07:04
Speaker A
هذا العنوان. سأضعه في ملف القراءة (readme) على جيت هاب، لذا يمكنك... نعم، سيكون هذا العنوان متاحاً لديك على جميع أجهزة راسمبيري باي. حسناً، إذاً هذا هنا هو العنوان الأساسي، وللوصول إلى... أمم نعم، سجل التحميل للمؤقت، علينا إضافة الإزاحة 400. إذاً، بالنسبة لسجل التحميل السجل، سنجد
07:31
Speaker A
العنوان النهائي مضافاً إليه الإزاحة 400 بالنظام الست عشري. حسناً، لقد ارتكبت خطأ مطبعياً، لكن لا يهم. إذاً، هذا هنا هو العنوان الذي يمكننا خلفه العثور على سجل التحميل. حسناً، يكفي هذا القدر من المقدمة.
07:50
Speaker A
الآن، دعنا نبدأ في تنفيذ برنامج تعريف لهذا. حسناً، إذاً لنقم بتنفيذ برنامج التعريف. كما ترون، أنا متصل بالفعل براسمبيري باي الخاص بي عبر SSH، ودعوني أنتقل إلى مجلد دروس تعريفات لينكس الخاص بي. دعنا نرى. سأختار الدرس رقم 16 كنموذج
08:10
Speaker A
لبرنامج التعريف الخاص بي اليوم، وسأسميه DTM MIO. دعوني أنتقل إلى هذا المجلد، ولنلقِ نظرة على ما بداخله. ملف devdriver.c هو الكود المصدري بلغة C لبرنامج التعريف الخاص بنا. ملف overlay.dts هو تراكب لشجرة الأجهزة (device tree overlay) يضيف الجهاز إلى
08:28
Speaker A
النظام. ملف makefile سيقوم ببناء كل من برنامج التعريف وتراكب شجرة الأجهزة، وسيعطيك ملف readme المزيد من المعلومات إذا كنت تشاهد هذا داخل مستودع جيت هاب أو كودبيرج الخاص بي. حسناً، لنقم ببعض عمليات إعادة التسمية. سأعيد تسمية devdriver الخاص بي إلى timer.c، وسأعيد تسمية overlay.dts
08:51
Speaker A
إلى Raspberry Pi 4 timer.dts. وبالنسبة للأجيال الأخرى من راسمبيري باي، سأقوم بإنشاء تراكب شجرة أجهزة خاص، وسأخبرك في ملف readme أي واحد يجب أن تستخدمه لكل إصدار من إصدارات راسمبيري باي. حسنًا، علينا الآن تعديل ملف المايكفايل قليلاً وتغيير الاسم إلى my_timer.o. سيكون هذا هو RP4.
09:21
Speaker A
أمم، المؤقت هنا في الأسفل أيضاً. هنا في الأسفل أيضاً. وهنا أيضاً. حسناً. هذا كل ما يخص ملف المايكفايل، والآن لنقم بتحرير تراكب شجرة الجهاز الخاص بنا. هنا لدينا تراكب بسيط لشجرة الجهاز يضيف جهازي إلى المسار الجذري لشجرة الجهاز. سأقوم بتغيير
09:43
Speaker A
هذا قليلاً. أول شيء سأغيره هو إعادة تسمية الجهاز إلى my_timer. وبعد علامة "at"، سأحدد العنوان المادي للجهاز، وهو FE00B400. يجب علي أيضاً تغيير سلسلة التوافق إلى arm. My_timer، حيث arm هو المورّد، و my_timer هو اسم الجهاز.
10:15
Speaker A
الحالة "okay" تعني أنه يعمل، وهذا يفعّل الجهاز. وهنا سأضيف خاصية أخرى وهي خاصية reg. تخبر خاصية reg الجهاز بالعنوان الذي يمكن من خلاله الوصول إلى العتاد. لكن قبل ملء خاصية reg، يجب أن نحدد قيمتين إضافيتين.
10:40
Speaker A
هنا علينا تحديد قيمتين. الأولى هي عدد خلايا العنوان، وسأضبطها على اثنين. والثانية هي عدد خلايا الحجم، وسأضبطها على واحد. لأن خاصية reg هذه تحتوي على بعض خلايا العنوان وبعض خلايا الحجم. وهذان المتغيران يحددان عدد الخلايا المستخدمة لتحديد العنوان. هنا أستخدم كلمتين بحجم 32-
11:13
Speaker A
بت، أي كلمة واحدة بحجم 64-بت. ولتحديد مقدار السجلات التي يستخدمها هذا العتاد، سأستخدم قيمة عدد خلايا الحجم وهي واحد، مما يعني كلمة واحدة بحجم 32-بت. حسناً، الآن يمكنني تحديد العنوان. أولاً، يجب أن أحدد الـ 32-بت الأعلى ثم الـ 32-بت الأدنى، وهي FE00B400.
11:44
Speaker A
حسناً، وبالنسبة للحجم، يمكنني استخدام كلمة واحدة بحجم 32-بت. وعندما نلقي نظرة هنا، آخر سجل ينتهي عند العنوان 23، لذا دعنا نجعله أكبر قليلاً ونقول إن الحجم هنا هو 40 بالنظام الست عشري، وهذا مقبول. جيد.
12:07
Speaker A
إذن، يجب أن يكون هذا هو تراكب شجرة الجهاز الخاص بنا. دعونا نتحقق مما إذا كنا قادرين على تجميعه.
12:18
Speaker A
حسناً، نحصل على بعض التحذيرات، لكن بشكل عام يجب أن يعمل. جيد. الآن، يمكننا البدء في تنفيذ المشغل (driver).
12:33
Speaker A
ولذلك، سأستخدم هذا القالب لمشغل منصة "مرحباً بالعالم". إذن، أول شيء نراه هنا أو الخطوات التي يجب عليك القيام بها عند كتابة برنامج تشغيل جهاز لنظام لينكس هي أولاً تسمية الأجهزة المتوافقة مع البرنامج، وهو ما يتم هنا. ثم، عليك تنفيذ
12:49
Speaker A
دالة الف
13:05
Speaker A
هيكل تعريف البرنامج ( driver's struct). وأخيراً وليس آخراً، يجب عليك تسجيل البرنامج في نظام التشغيل، وهنا يمكننا استخدام ماكرو "module platform driver" مباشرة. حسناً. سأقوم ببعض التعديلات التجميلية البسيطة. أولاً، سأقوم بإعادة تسمية "my dev" إلى "my timer". هذا مجرد إجراء
13:31
Speaker A
تجميلي. وهنا بالطبع، يجب علي تغيير السلسلة النصية المتوافقة. ومن المهم جداً أن تتطابق هذه السلسلة مع السلسلة التي استخدمناها في تراكب شجرة الجهاز (device tree overlay). لذا، يجب ضبط هذه السلسلة على "my timer" الخاصة بنا. سأقوم بنسخ هذا هنا للتأكد
13:56
Speaker A
من أنها مطابقة تماماً . حسناً. جيد. ثم سأحتاج إلى ملف ترويسة (header file ) إضافي. سأحتاج إلى، أم، ملف "linux io.h" ثم سأقوم بتعريف متغيرين عامين. الأول من نوع هيكل المورد (struct resource) يصف المورد أو خاصية " reg" في تراكب شجرة
14:26
Speaker A
الجهاز الخاص بنا. والثاني سيكون مؤشراً يشير إلى ذاكرة الإدخال والإخراج (IO memory). لهذا السبب أحدد هذا هنا وسأسميه "hopper registers". حسناً. والآن في دالة الفحص، سأحاول تعيين ثم الوصول إلى سجلات العتاد هذه.
14:52
Speaker A
حسناً. إذن، سأضبط المورد على "platform get resource". وهنا أريد قراءة خاصية "reg" من مدخل شجرة الجهاز الخاص بي. المعامل الأول هو مؤشر إلى جهاز المنصة الخاص بي. التالي هو نوع المورد الذي أريد تعيينه. وهنا هو "IO resource mem". يمكنني أيضاً استخدام هذا لتعيين
15:18
Speaker A
مقاطعة (interrupt)، على سبيل المثال، عندها سيكون "IO resource interrupt". والمعامل الأخير هو رقم خاصية "reg" التي أريد تعيينها، وهنا سأقوم بتعيين الأولى، أي صفر. من الممكن أن يحتوي الجهاز على عدة مدخلات "reg". لكن في هذه الحالة يمكنك زيادة هذا المعامل الأخير
15:41
Speaker A
هنا، ولكننا هنا لدينا واحد فقط. حسناً، دعنا نتحقق مما إذا كان هذا قد أعاد مؤشراً فارغاً ، لأنه في هذه الحالة حدث خطأ، وسأطبع رسالة خطأ "تعذر تعيين المورد" أو "الحصول على المورد" سيكون أفضل.
16:07
Speaker A
وسأقوم بإرجاع خطأ "لا يوجد جهاز". حسناً. ولكن إذا نجح هذا، فستصبح البيانات من خاصية reg موجودة الآن في مؤشر هيكل المورد هذا ويمكننا طباعتها.
16:26
Speaker A
أمم إذًا، هنا سأقوم بطباعة عنوان البدء للمورد، والذي يتم تخزينه في حقل البداية (start field). و باستخدام دالة حجم المورد (resource size)، سأستعيد حجم المورد. حسناً. إذًا، لقد قرأنا للتو خاصية reg هذه من شجرة الأجهزة ، لكننا لم نقم بتعيينها بعد على مؤشر
17:05
Speaker A
سجل الأجهزة الخاص بنا . هذا ما يجب علي فعله بالدالة التالية. وهنا سأستخدم دالة ioremap.
17:14
Speaker A
إذًا، المعامل الأول هو مؤشر الجهاز الذي نريد إجراء ioremap له. المعامل التالي هو بداية المورد الذي نريد تعيينه. والمعامل الأخير هو حجم المورد الذي نريد تعيينه.
17:31
Speaker A
وأجل، مرة أخرى، إذا أعاد هذا مؤشراً فارغاً (null pointer) حسناً ، هنا ليس لدي شيء، إذاً حدث خطأ. ويجب علي طباعة رسالة خطأ. إذًا ، خطأ: تعذر تعيين المورد هذه المرة.
17:51
Speaker A
حسناً. ولكن إذا نجح هذا، يمكننا الآن الوصول إلى هذا المؤشر مباشرة وسنصل حينها إلى الأجهزة. إذاً، ما الذي أريد فعله حقاً؟ أول شيء أريد القيام به هو ضبط الحمل (load) على FFFF. ثم يجب علي تفعيل المؤقت هنا في
18:09
Speaker A
سجل التحكم هذا. لذا، يمكنك رؤية أنه من خلال البت رقم سبعة يمكننا تفعيل المؤقت.
18:17
Speaker A
وبعد ذلك أريد قراءة سجل القيمة للحصول على قيمة العداد الحالية. إذًا، لنفعل ذلك. أول شيء هنا هو أننا سنقوم بضبط سجل التحميل.
18:39
Speaker A
حسناً. بعد ذلك، لنقم بتفعيل المؤقت. بما أن هذه قيمة 32 بت، يجب علي زيادة هذا المؤشر بمقدار اثنين للوصول إلى سجل التحكم. وهنا، لنقم فقط بضبط البت رقم سبعة، وهو بت التفعيل. إذًا، البت رقم سبعة يقوم بتفعيل المؤقت. ثم، لنقم بطباعة القيمة
19:14
Speaker A
الحالية للمؤقت مرتين. هنا الإزاحة (offset) هي زائد واحد، ولنقم بذلك مرتين حتى نتمكن من رؤية المؤقت وهو يعد تنازلياً. وفي الأسفل هنا في دالة الحذف (remove function)، كل ما سأفعله هو تعطيل المؤقت مرة أخرى . هنا يجب علي مسح هذا البت. إذًا، هنا هو
20:03
Speaker A
تفعيل المؤقت وهنا قراءة المؤقت مرتين. حسناً. إذًا، ينبغي أن يكون هذا، أجل، لنقم بتغيير هذا البرنامج التشغيلي أيضاً لمؤقت RP arm. حسناً. حسناً، سأحاول تجميع هذا ولنرى عدد الأخطاء التي ارتكبتها. أجل، لدي خطأ مطبعي هنا. أوه . يتوقع تنسيق عدد صحيح
20:41
Speaker A
. المورد T. حسناً. أجل. حسناً، هنا يجب أن يكون هناك R. ولنقم بتغيير التنسيق هنا أيضاً. لنرى ما إذا كانت الأخطاء قد اختفت . نعم، اختفت الأخطاء.
21:08
Speaker A
جيد. الآن سأقوم بفتح نافذة ثانية هنا. جيد. وهنا سأقوم فقط بمتابعة سجل نواة لينكس. وأول شيء سأفعله هنا هو تطبيق تراكب شجرة الجهاز الخاص بي. حسناً، لقد نجح هذا. ولنتحقق مما إذا كان بإمكاننا رؤيته تحت مسار شجرة جهاز مؤقت السجل الخاص
21:37
Speaker A
بي. نعم، هنا يمكننا رؤية العناوين التي تم تعيينها والحجم الذي تم تخصيصه. والآن يمكننا محاولة تحميل برنامج التشغيل الخاص بنا. وما يمكننا رؤيته هنا هو أن عملية الربط قد نجحت. لدينا مورد هنا يبدأ بهذا العنوان بحجم 64 بايت كما حددنا في خاصية السجل الخاصة
22:08
Speaker A
بنا، وهنا نقوم بقراءة السجل مرتين. حسناً، يبدو أن المؤقت سيزداد ، لكنه مؤقت تنازلي.
22:20
Speaker A
لذا هنا القيمة عادت والتفت وبدأت من جديد عند f f f f. لهذا السبب يبدو الأمر هكذا.
22:27
Speaker A
لاحقاً معك سأقوم بتقليل التردد أيضاً. وعندما نقوم بإزالة الوحدة مرة أخرى، يجب أن يتوقف المؤقت. وهذا كل شيء بشكل أساسي.
22:41
Speaker A
رائع. هذه هي طريقة الوصول إلى مدخلات ومخرجات الذاكرة المعنونة في برنامج تشغيل لينكس. آمل أن تكونوا قد استمتعتم بالفيديو وتعلمتم شيئاً. في حال أردتم دعم عملي، يمكنكم شراء قهوة لي عبر buymeacoffee.com/learnforlinux. شكراً للمشاهدة وإلى اللقاء.
Topics:تعريفات لينكسراسبيري بايمؤقت ARMوحدات الإدخال والإخراجخريطة العناوينتراكب شجرة الأجهزةبرمجة تعريفات الأجهزةSystem on Chipبرمجة لينكستعريف منصة

Get More with the SozAI App

Transcribe recordings, audio files, and YouTube videos — with AI summaries, speaker detection, and unlimited transcriptions.

Or transcribe another YouTube video here →