الصدأ مضمن. تطوير معالجات Cortex-M3 باستخدام لوحة التصحيح STM32F103C8T6 (الحبة السوداء)

مرحبا! أريد أن أقدم لكم مشروع Rust Embedded . يسمح لنا باستخدام لغة البرمجة Rust للتطوير للمنصات المضمنة (Embedded Linux / RTOS / Bare Metal).


في هذه المقالة ، سننظر في المكونات الضرورية لبدء تطوير المعالجات الدقيقة Cortex-M3. بعد ذلك ، سنكتب مثالًا بسيطًا - يومض مؤشر LED المدمج.

للقيام بذلك ، نحتاج إلى لوحة تصحيح صينية بأسعار معقولة ورخيصة STM32F103C8T6 أو حبوب سوداء (بسبب اللون الأسود والحجم الصغير). هناك أيضًا نسخة من اللوحة باللون الأزرق - Blue Pill. لا أوصي به ، لأنني سمعت أنه يحتوي على المقاوم الخطأ ، مما يسبب مشاكل عند استخدام منفذ USB. اختلافه الثاني عن الحبة السوداء في ترتيب الدبابيس (الاستنتاجات). ولكن أكثر عن ذلك لاحقا.

سنحتاج أيضًا إلى مبرمج لألواح تصحيح الأخطاء STM32. في هذه المقالة ، سوف نستخدم مبرمج ST-Link V2 الصيني الرخيص والميسور التكلفة.


إصدار مترجم الصدأ


للبدء ، تحتاج إلى التأكد من أن إصدار المترجم الخاص بك هو 1.31 أو أحدث. يمكنك التحقق من إصدار المترجم الخاص بك عن طريق إدخال الأمر:

> rustc --version

تثبيت المكون


الآن يمكننا البدء في تثبيت المكونات الضرورية.

ذراع غنو المضمنة


سنحتاج إلى مصحح أخطاء لرقائق ARM - arm-none-eabi-gdb. قم بتشغيل المثبت واتبع التعليمات. في نهاية التثبيت ، تأكد من تحديد الخيار " إضافة مسار إلى متغير البيئة ".

رابط التحميل

بعد التثبيت ، يمكنك التحقق مما إذا كان كل شيء على ما يرام بإدخال ما يلي في سطر الأوامر:

> arm-none-eabi-gdb -v

إذا كان كل شيء على ما يرام ، فسترى إصدار المكون المثبت.

برنامج تشغيل ST-Link


دعنا ننتقل إلى تثبيت برنامج التشغيل لمبرمج ST-Link.

اتبع تعليمات المثبت وتأكد من تثبيت الإصدار الصحيح ( أربعة وستين أو اثنين وثلاثين بت ) من برنامج التشغيل اعتمادًا على عمق البت لنظام التشغيل الخاص بك.

رابط التحميل

أدوات ST-Link


الخطوة التالية هي تثبيت الأدوات اللازمة للبرنامج الثابت - أدوات ST-Link. قم بتنزيل الأرشيف وفك ضغطه إلى أي مكان مناسب ، وتحتاج أيضًا إلى تحديد المسار إلى مجلد bin الفرعي ( stlink-1.3.0 \ bin ) في متغير البيئة " PATH ".

رابط التحميل

حاويات الشحن


أخيرًا ، قم بتثبيت حزمة binutils للشحن ، ويتم ذلك بواسطة أمرين في وحدة التحكم.

> cargo install cargo-binutils
> rustup component add llvm-tools-preview

هذا يكمل تركيب المكونات.

إنشاء وإنشاء مشروع


للمتابعة ، نحتاج إلى إنشاء مشروع جديد باسم " stm32f103c8t6 ". دعني أذكرك ، يتم ذلك عن طريق الأمر:

> cargo new stm32f103c8t6

تبعيات المشروع والتحسين


قم بتوصيل المكتبات الضرورية في ملف Cargo.toml :

[package]
name = "stm32f103c8t6"
version = "0.1.0"
authors = ["Nick"]
edition = "2018"

#      Cortex-M3
[dependencies]
cortex-m = "*"
cortex-m-rt = "*"
cortex-m-semihosting = "*"
panic-halt = "*"
nb = "0.1.2"
embedded-hal = "0.2.3"

#       stm32f1
[dependencies.stm32f1xx-hal]
version = "0.5.2"
features = ["stm32f100", "rt"]

#   `cargo fix`!
[[bin]]
name = "stm32f103c8t6"
test = false
bench = false

#   
[profile.release]
codegen-units = 1 #  
debug = true #  ,     Flash 
lto = true #  

أيضا ، يمكنك أن ترى أنه في نهاية الملف ، تم تمكين تحسين التعليمات البرمجية.

تتطلب مكتبة cortex-m-rt إنشاء ملف في الدليل الجذر للمشروع ، يجب أن يطلق عليه " memory.x ". يشير إلى مقدار الذاكرة التي يمتلكها الجهاز وعنوانه:

MEMORY
{
 FLASH : ORIGIN = 0x08000000, LENGTH = 64K
 RAM : ORIGIN = 0x20000000, LENGTH = 20K
}

تحديد النظام الأساسي الهدف وأهداف التجميع الافتراضية


من الضروري تعيين النظام الأساسي الهدف للمترجم ، ويتم ذلك عن طريق الأمر:

> rustup target add thumbv7m-none-eabi

بعد ذلك ، قم بإنشاء مجلد " cargo " في الدليل الجذر وملف " config " فيه .

محتويات ملف التكوين :

[target.thumbv7m-none-eabi]

[target.'cfg(all(target_arch = "arm", target_os = "none"))']

rustflags = ["-C", "link-arg=-Tlink.x"]

[build]
target = "thumbv7m-none-eabi"  # Cortex-M3

حددنا فيه هدف الترجمة الافتراضي ، وهذا يسمح لنا بتجميع التعليمات البرمجية في ملف ARM .elf بأمر بسيط ومألوف:

> cargo build --release

مثال


للتأكد من أنه يعمل ، خذ بعين الاعتبار أبسط مثال - يومض LED.

محتويات ملف main.rs :

#![deny(unsafe_code)]
#![no_std]
#![no_main]

use panic_halt as _;

use nb::block;

use stm32f1xx_hal::{
    prelude::*,
    pac,
    timer::Timer,
};
use cortex_m_rt::entry;
use embedded_hal::digital::v2::OutputPin;

//   .
#[entry]
fn main() -> ! {
    
    //     
    let cp = cortex_m::Peripherals::take().unwrap();
    let dp = pac::Peripherals::take().unwrap();
    let mut flash = dp.FLASH.constrain();
    let mut rcc = dp.RCC.constrain();

    let clocks = rcc.cfgr.freeze(&mut flash.acr);
    let mut gpiob = dp.GPIOB.split(&mut rcc.apb2);

    //   b12   .
    //  "crh"      .
    //   0-7,    "crl".
    let mut led = gpiob.pb12.into_push_pull_output(&mut gpiob.crh);
    //        .
    let mut timer = Timer::syst(cp.SYST, &clocks)
    .start_count_down(1.hz());

    //     
    //    .
    loop {
        block!(timer.wait()).unwrap();
        led.set_high().unwrap();
        block!(timer.wait()).unwrap();
        led.set_low().unwrap();
    }
}

في السطر الأول ، باستخدام السمة - #![deny(unsafe_code)]، نزيل إمكانية استخدام رمز غير آمن.

في السطر الثاني ، قمنا بوضع السمة #![no_std]، وهي مطلوبة ، لأننا نقوم بإنشاء تطبيق للحديد المجرد ، وتحتاج المكتبة القياسية إلى نظام تشغيل.

بعد ذلك تأتي السمة #![no_main]التي تخبر المترجم أننا لا نستخدم الوظيفة الافتراضية الافتراضية مع متجه الوسيطة ونوع الإرجاع. هذا ليس له معنى ، حيث ليس لدينا نظام تشغيل أو وقت تشغيل آخر يستدعي الوظيفة ويعالج القيمة المرتجعة.

بعد السمات ، نقوم بتوصيل الوحدات الضرورية في النطاق.

ويتبع ذلك وظيفة ، في حالتنا ، بدافع العادة ، نسميها -main(). هذه هي نقطة الدخول إلى البرنامج ، يتم تحديدها من خلال السمة #[entry].

داخل الوظيفة الرئيسية ، نقوم بإنشاء مقبض لكائن طرفي "يمتلك" جميع الأجهزة الطرفية.

بعد ذلك ، يمكننا تعيين الدبوس المسؤول عن LED المدمج في اللوحة للإخراج. نظرًا لأنه في حالتي عبارة عن لوحة Black Pill ، فإن LED الموجود بها متصل بالطرف B12 . إذا كان لديك لوحة Blue Pill ، فإن دبوس C13 مسؤول عن LED المدمج . لذلك ، قمنا بتعيين طرف B12 كمخرج دفع وسحبه إلى متغير led.

الآن يمكننا ضبط وقت بدء حدث التحديث لمؤقت النظام ، وحفظه في متغيرtimer. في مثالنا ، هذه المرة ثانية واحدة.

بعد ذلك ، في حلقة لا نهائية ، يمكننا وصف منطق برنامجنا. الأمر بسيط للغاية ، أولاً timerيمنع تنفيذ البرنامج حتى انقضاء الوقت المحدد فيه. والخطوة التالية هي ضبط دبوس LED المدمج على ارتفاع ، بحيث يضيء. بعد ذلك ، يتم حظر تنفيذ البرنامج مرة أخرى بواسطة نفس المؤقت لمدة ثانية واحدة. ويتم تعيين دبوس LED إلى منخفض ، وبالتالي يخرج. علاوة على ذلك ، يتم تكرار البرنامج بشكل دوري.

التحويل البرمجي


الآن بعد أن اكتشفنا رمز البرنامج والمنطق ، يمكننا تجميعه في ملف .elf باستخدام الأمر:

> cargo build --release

لا يحتوي هذا التنسيق على رمز ثنائي فحسب ، بل يحتوي أيضًا على بعض الرؤوس والمزيد. يفيد ذلك عندما يتم تشغيل الملف بواسطة برنامج آخر ، مثل نظام التشغيل أو أداة تحميل التشغيل.

ولكن ، لتشغيل البرنامج على المعدن ، لا نحتاج إلى ملف .elf ، ولكن ملف .bin . ملف .bin هو صورة برنامج يمكن كتابتها بايت في ذاكرة وحدة التحكم الدقيقة. و .elf ملف يمكن تحويلها إلى . بن ملف باستخدام الأمر:

> cargo objcopy --bin stm32f103c8t6 --target thumbv7m-none-eabi --release -- -O binary stm32f103c8t6.bin

الآن ملفنا الثنائي جاهز للبرامج الثابتة.

الإتصال


سنومض اللوح باستخدام مبرمج ST-Link V2. للقيام بذلك ، يجب عليك أولاً توصيله باللوحة.

في حالة المبرمج يوجد ترتيب دبوس للموصل. تحتاج إلى الانتباه إلى الانقطاع في الموصل ، كما يتم عرضه على الرسم التخطيطي ، مما يسمح لك بفهم كيفية إجراء الاتصال.

قم بتوصيل دبابيس المبرمج 3.3V و GND بالدبابيس المقابلة على اللوحة. يتم توصيل Ping SWDIO لتثبيت DIO ، ودفع SWCLK لتثبيت CLK .

بعد توصيل اللوحة بالمبرمج ، يمكننا توصيل ST-Link بالكمبيوتر.

انتباه!قبل التوصيل ، افصل جميع مصادر الطاقة الأخرى عن اللوحة ، إن وجدت ، وإلا فقد تتسبب في تلف اللوحة أو الكمبيوتر.

الآن يمكننا التحقق من الاتصال:

> st-info --descr

في وحدة التحكم ، يجب أن نرى السطر " جهاز متوسط ​​الكثافة F1 ".

البرامج الثابتة


اختياريًا ، قبل الوميض ، يمكنك مسح ذاكرة اللوحة إذا كان هناك شيء مكتوب عليها:

> st-flash erase

أخيرًا ، يمكننا تشغيل البرنامج الثابت:

> st-flash write stm32f1.bin 0x8000000

إذا تم كل شيء بشكل صحيح ، يجب أن ترى ضوء LED وامض. تهانينا!

استنتاج


لذلك ، لتحديث اللوحة ، يجب عليك استخدام هذه المجموعة من الأوامر التي تم إدخالها بالتسلسل:

> cargo build --release
> cargo objcopy --bin stm32f103c8t6 --target thumbv7m-none-eabi --release -- -O binary stm32f103c8t6.bin
> st-flash erase
> st-flash write stm32f1.bin 0x8000000

لتبسيط حياتنا ، يمكننا إنشاء ملف .bat بهذه الأوامر وتشغيله من وحدة التحكم.

من المؤلف


إذا كنت مهتمًا بهذه الأدلة ، فمرحباً بك في قناة YouTube الخاصة بي .
أيضًا ، بدأت مؤخرًا قناة Telegram حيث أنشر ترجمات مختلفة من الكتيبات والكتب والأخبار والمرح وغيرها من الأشياء المتعلقة بلغة البرمجة Rust. هناك يمكنك العثور على روابط إلى العديد من غرف الدردشة من أجل طرح أسئلتك والحصول على المساعدة أو إرسال مشاريعك أو مجرد الدردشة مع الأشخاص ذوي التفكير المماثل.

شكرا للانتباه!

All Articles