🕵️ SicherheitslückenWhat continuous operational resilience looks like under DORA(09.09.2026 um 17:53 Uhr)
🔧 AI Nachrichten OpenAI seeks tougher AI rules. CIOs may feel the ripple effects(10.09.2026 um 12:11 Uhr)
🔧 AI Nachrichten Mistral valued at €21bn after €3bn Series D funding round(08.09.2026 um 10:19 Uhr)
🪟 Windows TippsWindows XP's Cursor Indicator Is Getting a Windows 11 Refresh(25.08.2026 um 13:00 Uhr)
🕵️ SicherheitslückenWhat continuous operational resilience looks like under DORA(09.09.2026 um 17:53 Uhr)
🔧 AI Nachrichten OpenAI seeks tougher AI rules. CIOs may feel the ripple effects(10.09.2026 um 12:11 Uhr)
🔧 AI Nachrichten Mistral valued at €21bn after €3bn Series D funding round(08.09.2026 um 10:19 Uhr)
🪟 Windows TippsWindows XP's Cursor Indicator Is Getting a Windows 11 Refresh(25.08.2026 um 13:00 Uhr)

🔧 Programmierung 🕛 vor 1 Jahr 7 Min Lesezeit
0

Self-Aligning Dish in Rust: Setup

↗ Quelle (dev.to)
🗣️ Stimme:
📑 Inhaltsübersicht

In this section, we will lay the software setup for the project.






Table of contents:




  • Requirements


  • Implementation


    • Minimum Program

    • Linker File & Configuration

    • Critical Section






  • Results









Requirements




  • Raspberry Pi Pico board

  • USB Cable type 2.0








Implementation



We begin by creating a new project in our machines.




CODE
cargo new self-aligning-sat-dish











Minimum Program



Navigate to src/main.rs and replace the contents of the main.rs file with the following:




CODE
#![no_std]
#![no_main]

use panic_halt as _;
use cortex_m_rt::entry;

#[link_section = ".boot2"]
#[used]
pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER_W25Q080;

#[entry]
fn main() -> ! {
loop {}
}






The above code is the minimum embedded program for the RP2040 microcontroller.



The #![no_std] part is an attribute that tells the compiler that we'll not be using the bloated Rust std library since embedded devices are usually resource constrained. The core library will be used instead.



#![no_main] says the entry point into the program will be directly after the #[entry] attribute and not the std library's main function.

 

We'll need to import a number of crates to build this code: panic_halt defines actions to be performed in case of a panic (in this case the program should halt), cortex_m_rt provides the #[entry] attribute, and rp2040_boot2 is a second-stage bootloader for the RP2040 microcontroller.

 

These crates are added as dependencies to our project via the Cargo.toml file, as shown below:




CODE
panic-halt = "0.2.0"
cortex-m-rt = "0.7.3"
rp2040-boot2 = "0.3.0"











Linker Script and Configuration



Next we'll add the linker script which gives the compiler the memory layout of the microcontroller we'll be using. This information is important for the cross-compilation of our code.



Create a memory.x file in our project (at the same level as src) with the following content:




CODE
MEMORY {
BOOT2 : ORIGIN = 0x10000000, LENGTH = 0x100
FLASH : ORIGIN = 0x10000100, LENGTH = 2048K - 0x100
RAM : ORIGIN = 0x20000000, LENGTH = 256K
}

EXTERN(BOOT2_FIRMWARE)

SECTIONS {
/* ### Boot loader */
.boot2 ORIGIN(BOOT2) :
{
KEEP(*(.boot2));
} > BOOT2
} INSERT BEFORE .text






Create a file .cargo and in it add the toml file config.toml. This provides further configuration for our particular target device.




CODE
[target.thumbv6m-none-eabi]
runner = "elf2uf2-rs -d"

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

[build]
target = "thumbv6m-none-eabi"






The target will change depending on the processor architecture of the device one's application is designed to run on. The RP2040's architecture is thumbv6m-none-eabi




NB You will need to download and set up the crate.



Most HALs, such as the rp2040-hal, have it already baked in. In our case, however, we'll need to manually implement it since the rp2040-pac crate has no critical section implementation which is crucial for ensuring safe access to application data without data races.



In the /src folder of your project, make another directory with the name drivers.




CODE
 mkdir drivers






Copy the below code in a file named critical_section_rp2040.rs




CODE
use rp2040_pac as pac;
use core::sync::atomic::{AtomicU8, Ordering};

struct RpSpinlockCs;
critical_section::custom_impl!(RpSpinlockCs);

/// Marker value to indicate no-one has the lock.
///
/// Initialising `LOCK_OWNER` to 0 means cheaper static initialisation so it's the best choice
const LOCK_UNOWNED: u8 = 0;

/// Indicates which core owns the lock so that we can call critical_section recursively.
///
/// 0 = no one has the lock, 1 = core0 has the lock, 2 = core1 has the lock
static LOCK_OWNER: AtomicU8 = AtomicU8::new(LOCK_UNOWNED);

/// Marker value to indicate that we already owned the lock when we started the `critical_section`.
///
/// Since we can't take the spinlock when we already have it, we need some other way to keep track of `critical_section` ownership.
/// `critical_section` provides a token for communicating between `acquire` and `release` so we use that.
/// If we're the outermost call to `critical_section` we use the values 0 and 1 to indicate we should release the spinlock and set the interrupts back to disabled and enabled, respectively.
/// The value 2 indicates that we aren't the outermost call, and should not release the spinlock or re-enable interrupts in `release`
const LOCK_ALREADY_OWNED: u8 = 2;

unsafe impl critical_section::Impl for RpSpinlockCs {
unsafe fn acquire() -> u8 {
RpSpinlockCs::acquire()
}

unsafe fn release(token: u8) {
RpSpinlockCs::release(token);
}
}

impl RpSpinlockCs {
unsafe fn acquire() -> u8 {
// Store the initial interrupt state and current core id in stack variables
let interrupts_active = cortex_m::register::primask::read().is_active();
// We reserved 0 as our `LOCK_UNOWNED` value, so add 1 to core_id so we get 1 for core0, 2 for core1.
// let core = crate::Sio::core() as u8 + 1_u8;
let core = (*pac::SIO::ptr()).cpuid.read().bits() as u8 + 1_u8;
// Do we already own the spinlock?
if LOCK_OWNER.load(Ordering::Acquire) == core {
// We already own the lock, so we must have called acquire within a critical_section.
// Return the magic inner-loop value so that we know not to re-enable interrupts in release()
LOCK_ALREADY_OWNED
} else {
// Spin until we get the lock
loop {
// Need to disable interrupts to ensure that we will not deadlock
// if an interrupt enters critical_section::Impl after we acquire the lock
cortex_m::interrupt::disable();
// Ensure the compiler doesn't re-order accesses and violate safety here
core::sync::atomic::compiler_fence(Ordering::SeqCst);
// Read the spinlock reserved for `critical_section`
let spinlock31 = &(*pac::SIO::ptr()).spinlock[31];
let lock = spinlock31.read().bits();
if lock > 0 {
// We just acquired the lock.
// 1. Forget it, so we don't immediately unlock
#[allow(forgetting_copy_types)]
//core::mem::forget(lock);
// 2. Store which core we are so we can tell if we're called recursively
LOCK_OWNER.store(core, Ordering::Relaxed);
break;
}
// We didn't get the lock, enable interrupts if they were enabled before we started
if interrupts_active {
cortex_m::interrupt::enable();
}
}
// If we broke out of the loop we have just acquired the lock
// As the outermost loop, we want to return the interrupt status to restore later
interrupts_active as _
}
}

unsafe fn release(token: u8) {
// Did we already own the lock at the start of the `critical_section`?
if token != LOCK_ALREADY_OWNED {
// No, it wasn't owned at the start of this `critical_section`, so this core no longer owns it.
// Set `LOCK_OWNER` back to `LOCK_UNOWNED` to ensure the next critical section tries to obtain the spinlock instead
LOCK_OWNER.store(LOCK_UNOWNED, Ordering::Relaxed);
// Ensure the compiler doesn't re-order accesses and violate safety here
core::sync::atomic::compiler_fence(Ordering::SeqCst);
// Release the spinlock to allow others to enter critical_section again
let spinlock31 = &(*pac::SIO::ptr()).spinlock[31];
spinlock31.write_with_zero(|b| b.bits(1));
// Re-enable interrupts if they were enabled when we first called acquire()
// We only do this on the outermost `critical_section` to ensure interrupts stay disabled
// for the whole time that we have the lock
if token != 0 {
cortex_m::interrupt::enable();
}
}
}
}






The code above is a slight edit of the critical implementation from the rp2040-hal crate.



Create another rust file mod.rs inside drivers that will bring critical_section_rp2040 into scope.




CODE
vi mod.rs






Copy the following into the file.




CODE
pub mod critical_section_rp2040;






Our program tree up to this point should be as shown below.




CODE
├── Cargo.toml
├── memory.x
└── src
├── drivers
│   ├── critical_section_rp2040.rs
│   └── mod.rs
└── main.rs











Results



We can now build our minimal RP2040 program.




CODE
cargo build






The program should compile and build without issue.



Now flash the program by running the code while the Raspberry Pi Pico is plugged in via USB to the computer.




CODE
cargo run







NB ❗ The Pico will need to be in flash mode. This is achieved by plugging the USB into the computer while the button on the Pico is pressed. Otherwise it will simply run the last program flashed into it.




Our minimal program should flash into the Pico successfully.



In the next part of the, series we'll blink the indication LED on the Pico board.

Vollständiger Original-Bericht
Ausführliche Details, Code-Beispiele & Hersteller-Stellungnahme auf dev.to.
↗ Original-Artikel auf dev.to lesen
Wie bewertest du diesen Beitrag?
1 Klick Feedback
Teilen mit Netzwerk & Team:

Community-Analysen & Experten-Meinungen 0

Verfasse deine eigene Analyse, teile Workarounds oder diskutiere diesen Vorfall im Blog.
Noch keine Community-Analyse verfasst. Markiere einen Textabschnitt oder klicke oben auf Eigene Analyse verfassen“!
Community Pulse: Relevanz-Einschätzung
1 Klick Experten-Votum
🔴 Akute Relevanz 0%
🟡 In Evaluierung 0%
🟢 Keine Auswirkung 0%
Spannende Innovation 0%
Verwandte Story-Cluster & Quellen (Vektor-KI)
Port 8095 Engine
1 Quelle
Sam Altman calls GPT-6 Astra rollout ‘messy’ as enterprise users wait for access
1 Quelle
Swiss government explores replacing Microsoft 365 with open-source software
1 Quelle
What continuous operational resilience looks like under DORA
Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten Self-Aligning Dish in Rust: Setup

Thematisch verwandte Begriffe: SelfAligning, Dish, Rust, Setup · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...