Tertanam Karat. Pengembangan untuk prosesor Cortex-M3 menggunakan papan debug STM32F103C8T6 (Black Pill)

Halo! Saya ingin memperkenalkan Anda dengan proyek Embedded Rust . Hal ini memungkinkan kita untuk menggunakan bahasa pemrograman Rust untuk pengembangan untuk platform tertanam (Embedded Linux / RTOS / Bare Metal).


Pada artikel ini, kami akan mempertimbangkan komponen yang diperlukan untuk memulai pengembangan untuk mikroprosesor Cortex-M3. Setelah itu kita akan menulis contoh sederhana - berkedip LED built-in.

Untuk melakukan ini, kita memerlukan papan debug Cina STM32F103C8T6 atau Black Pill yang terjangkau dan murah (karena warna hitam dan ukuran kecil). Ada juga versi papan berwarna biru - Pil Biru. Saya tidak merekomendasikannya, karena saya dengar ada resistor yang salah, yang menyebabkan masalah saat menggunakan port USB. Perbedaan kedua dari Pill Hitam dalam pengaturan pin (kesimpulan). Tetapi lebih lanjut tentang itu nanti.

Kami juga akan membutuhkan programmer untuk papan debug STM32. Pada artikel ini, kita akan menggunakan programmer ST-Link V2 Cina yang murah dan terjangkau.


Versi Kompiler Karat


Untuk memulai, Anda perlu memastikan versi kompiler Anda adalah 1,31 atau lebih baru. Anda dapat memeriksa versi kompiler Anda dengan memasukkan perintah:

> rustc --version

Pemasangan Komponen


Sekarang kita dapat mulai menginstal komponen yang diperlukan.

GNU Arm Embedded Toolchain


Kami akan membutuhkan debugger untuk chip ARM - arm-none-eabi-gdb. Luncurkan penginstal dan ikuti instruksi. Di akhir instalasi, pastikan untuk memeriksa opsi " Tambahkan path ke variabel lingkungan ".

Tautan unduhan

Setelah instalasi, Anda dapat memeriksa apakah semuanya beres dengan memasukkan yang berikut di baris perintah:

> arm-none-eabi-gdb -v

Jika semuanya beres, maka Anda akan melihat versi komponen yang diinstal.

ST-Link Driver


Mari beralih ke menginstal driver untuk programmer ST-Link.

Ikuti instruksi penginstal dan pastikan Anda menginstal versi driver yang benar ( enam puluh empat bit atau tiga puluh dua bit ), tergantung pada kedalaman bit sistem operasi Anda.

Tautan untuk mengunduh

ST-Link Tools


Langkah selanjutnya adalah menginstal alat yang diperlukan untuk firmware - ST-Link Tools. Unduh arsip dan unzip ke tempat yang nyaman, Anda juga perlu menentukan path ke subfolder bin ( stlink-1.3.0 \ bin ) dalam variabel lingkungan " PATH ".

Tautan untuk mengunduh

binutils kargo


Akhirnya, instal paket kargo-binutils, ini dilakukan oleh dua perintah di konsol.

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

Ini menyelesaikan pemasangan komponen.

Membuat dan mengatur proyek


Untuk melanjutkan, kita perlu membuat proyek baru dengan nama " stm32f103c8t6 ". Biarkan saya mengingatkan Anda, ini dilakukan oleh perintah:

> cargo new stm32f103c8t6

Ketergantungan dan Optimasi Proyek


Hubungkan perpustakaan yang diperlukan di file 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 #  

Anda juga dapat melihat bahwa, di akhir file, optimasi kode telah diaktifkan.

Pustaka cortex-m-rt mengharuskan kita membuat file di direktori root proyek, itu harus disebut " memory.x ". Ini menunjukkan berapa banyak memori yang dimiliki perangkat kita dan alamatnya:

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

Menetapkan platform target dan tujuan kompilasi default


Kita perlu mengatur platform target untuk kompiler, ini dilakukan dengan perintah:

> rustup target add thumbv7m-none-eabi

Setelah itu, buat folder " .cargo " di direktori root dan file " config " di dalamnya .

Isi file konfigurasi :

[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

Di dalamnya, kami mengidentifikasi tujuan kompilasi default, ini memungkinkan kami untuk mengkompilasi kode kami ke file ARM .elf dengan perintah sederhana dan akrab:

> cargo build --release

Contoh


Untuk memastikan itu berfungsi, pertimbangkan contoh paling sederhana - mengedipkan LED.

Isi file 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();
    }
}

Di baris pertama, menggunakan atribut - #![deny(unsafe_code)], kami menghapus kemungkinan menggunakan kode yang tidak aman.

Di baris kedua, kita menempatkan atribut #![no_std], itu diperlukan, karena kita membuat aplikasi untuk besi kosong, dan perpustakaan standar membutuhkan sistem operasi.

Selanjutnya adalah atribut #![no_main]yang memberitahu kompiler bahwa kita tidak menggunakan fungsi default default dengan vektor argumen dan tipe pengembalian. Ini tidak masuk akal, karena kita tidak memiliki sistem operasi atau runtime lain yang memanggil fungsi dan memproses nilai kembali.

Setelah atribut, kami pasang modul yang diperlukan ke dalam ruang lingkup.

Ini diikuti oleh fungsi, dalam kasus kami, karena kebiasaan, kami menyebutnya -main(). Ini adalah titik masuk ke program, ditentukan oleh atribut #[entry].

Di dalam fungsi utama, kami membuat pegangan ke objek periferal yang "memiliki" semua perangkat periferal.

Setelah itu, kita dapat mengatur pin yang bertanggung jawab untuk LED yang terpasang di papan ke output. Karena dalam kasus saya ini adalah papan Pill Hitam , LED di dalamnya terhubung ke pin B12 . Jika Anda memiliki papan Blue Pill , maka pin C13 bertanggung jawab untuk LED bawaan . Oleh karena itu, kami menetapkan pin B12 sebagai output push-pull dan menetapkannya ke variabel led.

Sekarang kita dapat mengatur waktu pemicu acara pembaruan untuk penghitung waktu sistem, dan menyimpannya dalam variabeltimer. Dalam contoh kita, waktu ini adalah satu detik.

Kemudian, dalam loop tanpa akhir, kita dapat menggambarkan logika program kita. Sangat sederhana, pertama-tama timermemblokir eksekusi program hingga waktu yang ditentukan di dalamnya telah berlalu. Langkah selanjutnya adalah mengatur pin LED bawaan ke tinggi , sehingga menyala. Setelah itu, eksekusi program kembali diblokir oleh penghitung waktu yang sama, selama satu detik. Dan pin LED diatur ke rendah , karena itu padam. Selanjutnya, program ini diulang secara siklis.

Kompilasi


Sekarang kita telah mengetahui kode program dan logika, kita dapat mengkompilasinya menjadi file .elf dengan perintah:

> cargo build --release

Format ini tidak hanya berisi kode biner, tetapi juga beberapa header dan banyak lagi. Ini berguna ketika file diluncurkan oleh perangkat lunak lain, seperti sistem operasi atau bootloader.

Tetapi, untuk menjalankan program pada bare metal, kita tidak perlu file .elf , tetapi file .bin . File .bin adalah gambar perangkat lunak yang dapat ditulis byte ke dalam memori mikrokontroler. File .elf dapat dikonversi ke file .bin menggunakan perintah:

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

Sekarang file biner kami siap untuk firmware.

Koneksi


Kami akan mem-flash board menggunakan programmer ST-Link V2. Untuk melakukan ini, Anda harus terlebih dahulu menghubungkannya ke papan tulis.

Pada kasus programmer ada pengaturan pin konektor. Anda perlu memperhatikan potongan di konektor, itu juga ditampilkan pada diagram, yang memungkinkan Anda untuk memahami cara membuat koneksi.

Hubungkan pin 3.3V dan GND programmer dengan pin yang sesuai di papan tulis. Ping SWDIO terhubung untuk menyematkan DIO , dan menyematkan SWCLK untuk menyematkan CLK .

Setelah menghubungkan papan ke pemrogram, kita dapat menghubungkan ST-Link ke komputer.

Perhatian!Sebelum menghubungkan, lepaskan semua sumber daya lain dari papan, jika ada, jika tidak dapat merusak papan atau komputer.

Sekarang kita dapat memeriksa koneksi:

> st-info --descr

Di konsol, kita akan melihat garis " perangkat kepadatan menengah F1 ".

Firmware


Secara opsional, sebelum berkedip, Anda dapat menghapus memori papan jika ada sesuatu yang tertulis di dalamnya:

> st-flash erase

Akhirnya, kita dapat memulai firmware:

> st-flash write stm32f1.bin 0x8000000

Jika semuanya dilakukan dengan benar, Anda akan melihat LED yang berkedip. Selamat!

Kesimpulan


Jadi, untuk mem-flash board, Anda harus menggunakan set perintah yang dimasukkan secara berurutan:

> 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

Untuk menyederhanakan hidup kita, kita dapat membuat file .bat dengan perintah ini dan menjalankannya dari konsol.

Dari penulis


Jika Anda tertarik dengan panduan ini, selamat datang di saluran YouTube saya .
Juga, baru-baru ini, saya memulai saluran Telegram di mana saya menerbitkan berbagai terjemahan buku pedoman dan buku, berita, humor, dan hal-hal lain yang berkaitan dengan bahasa pemrograman Rust. Di sana Anda dapat menemukan tautan ke beberapa ruang obrolan untuk mengajukan pertanyaan dan mendapatkan bantuan, mengirimkan proyek, atau hanya mengobrol dengan orang yang berpikiran sama.

Terimakasih atas perhatiannya!

All Articles