Skip to content

Commit

Permalink
Add global HSEM object and shared memory sample (#6)
Browse files Browse the repository at this point in the history
* Core0 controls blink freq of Core1

* Minor code clean-up
  • Loading branch information
taunusflieger authored Apr 30, 2024
1 parent e5a7978 commit cf9e1f4
Show file tree
Hide file tree
Showing 12 changed files with 212 additions and 46 deletions.
5 changes: 5 additions & 0 deletions .zed/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@
"allTargets": false,
"targets": "thumbv7em-none-eabihf"
},
"linkedProjects": [
"./core0/Cargo.toml",
"./core1/Cargo.toml",
"./stm32h7hal-ext/Cargo.toml"
],
"inlayHints": {
"maxLength": null,
"lifetimeElisionHints": {
Expand Down
37 changes: 37 additions & 0 deletions .zed/tasks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Static tasks configuration.
[
{
"label": "Build Core 0",
"command": "cargo build",
//"args": ["build"],
// Env overrides for the command, will be appended to the terminal's environment from the settings.
// "env": { "foo": "bar" },
// Current working directory to spawn the command into, defaults to current project root.
"cwd": "$ZED_WORKTREE_ROOT/core0",
// Whether to use a new terminal tab or reuse the existing one to spawn the process, defaults to `false`.
"use_new_terminal": false,
// Whether to allow multiple instances of the same task to be run, or rather wait for the existing ones to finish, defaults to `false`.
"allow_concurrent_runs": false
// What to do with the terminal pane and tab, after the command was started:
// * `always` — always show the terminal pane, add and focus the corresponding task's tab in it (default)
// * `never` — avoid changing current terminal pane focus, but still add/reuse the task's tab there
//"reveal": "always"
},
{
"label": "Build Core 1",
"command": "cargo build",
//"args": ["build"],
// Env overrides for the command, will be appended to the terminal's environment from the settings.
// "env": { "foo": "bar" },
// Current working directory to spawn the command into, defaults to current project root.
"cwd": "$ZED_WORKTREE_ROOT/core1",
// Whether to use a new terminal tab or reuse the existing one to spawn the process, defaults to `false`.
"use_new_terminal": false,
// Whether to allow multiple instances of the same task to be run, or rather wait for the existing ones to finish, defaults to `false`.
"allow_concurrent_runs": false
// What to do with the terminal pane and tab, after the command was started:
// * `always` — always show the terminal pane, add and focus the corresponding task's tab in it (default)
// * `never` — avoid changing current terminal pane focus, but still add/reuse the task's tab there
//"reveal": "always"
}
]
29 changes: 17 additions & 12 deletions core0/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions core0/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ embedded-storage = "0.3.1"
static_cell = "2"
chrono = { version = "^0.4", default-features = false }
stm32h7hal-ext = { version = "0.1.0", path = "../stm32h7hal-ext" }
shared = { version = "0.1.0", path = "../shared" }

# [patch."https://github.com/esrlabs/embassy"]
# embassy-stm32 = { path = "../../embassy/embassy-stm32" }
# embassy-sync = { path = "../../embassy/embassy-sync" }
Expand Down
4 changes: 2 additions & 2 deletions core0/memory.x
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ SECTIONS {
*(.sram3 .sram3.*);
. = ALIGN(4);
} > SRAM3
.sram4 (NOLOAD) : ALIGN(4) {
*(.sram4 .sram4.*);
.shared (NOLOAD) : ALIGN(4) {
*(.sram4 .sram4.* .shared .shared.*);
. = ALIGN(4);
} > SRAM4
.bsram (NOLOAD) : ALIGN(4) {
Expand Down
70 changes: 62 additions & 8 deletions core0/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#![no_std]
#![no_main]

#![feature(sync_unsafe_cell)]
use core::cell::SyncUnsafeCell;
use cortex_m::peripheral::NVIC;
use defmt::*;
use embassy_executor::Spawner;
Expand All @@ -9,20 +10,32 @@ use hal::{
bind_interrupts,
gpio::{Level, Output, Speed},
hsem::{HardwareSemaphore, InterruptHandler},
peripherals, Config,
peripherals::{self, HSEM},
Config,
};
use {
defmt_rtt as _, embassy_stm32 as hal, panic_probe as _, shared as _, stm32h7hal_ext as hal_ext,
};
use {defmt_rtt as _, embassy_stm32 as hal, panic_probe as _, stm32h7hal_ext as hal_ext};

bind_interrupts!(
struct Irqs {
HSEM1 => InterruptHandler<peripherals::HSEM>;
}
);

// SAFETY: This is safe because all access to the HSEM registers are atomic
static HSEM_INSTANCE: SyncUnsafeCell<Option<HardwareSemaphore<'static, HSEM>>> =
SyncUnsafeCell::new(None);

#[embassy_executor::main]
async fn main(_spawner: Spawner) {
info!("Core0: STM32H755 Embassy HSEM Test.");

unsafe {
for i in 0..10 {
shared::MAILBOX[i] = 0;
}
}
// Wait for Core1 to be finished with its init
// tasks and in Stop mode
hal_ext::wait_for_core1();
Expand Down Expand Up @@ -68,29 +81,35 @@ async fn main(_spawner: Spawner) {
let mut led_green = Output::new(p.PB0, Level::Low, Speed::Low);
let mut led_red = Output::new(p.PB14, Level::Low, Speed::Low);

let mut hsem = HardwareSemaphore::new(p.HSEM, Irqs);
let hsem = HardwareSemaphore::new(p.HSEM, Irqs);

// initialize global HSEM instance
unsafe { *HSEM_INSTANCE.get() = Some(hsem) };

unsafe { NVIC::unmask(embassy_stm32::pac::Interrupt::HSEM1) };
// Take the semaphore for waking Core1 (CM4)
if let Err(_err) = hsem.one_step_lock(0) {
if !get_global_hsem().one_step_lock(0) {
info!("Error taking semaphore 0");
} else {
info!("Semaphore 0 taken");
}

let mut core_1_blink_delay = 500;
set_core1_blink_delay(core_1_blink_delay).await;

// Wake Core1 (CM4)
hsem.unlock(0, 0);
get_global_hsem().unlock(0, 0);
info!("Core1 (CM4) woken");
led_green.set_high();
Timer::after_millis(250).await;
led_green.set_low();

info!("Waiting for Sem 1");
let _ = hsem.wait_unlocked(1).await;
let _ = get_global_hsem().wait_unlocked(1).await;
led_green.set_high();
led_red.set_high();
info!("Waiting for Sem 2");
let _ = hsem.wait_unlocked(2).await;
let _ = get_global_hsem().wait_unlocked(2).await;
led_red.set_low();
led_green.set_low();

Expand All @@ -102,5 +121,40 @@ async fn main(_spawner: Spawner) {
led_red.set_high();
Timer::after_millis(500).await;
led_red.set_low();
info!("Set Core 1 blink delay {}", core_1_blink_delay);
set_core1_blink_delay(core_1_blink_delay).await;
if core_1_blink_delay < 100 {
core_1_blink_delay = 500;
}
core_1_blink_delay -= 50;
}
}

async fn set_core1_blink_delay(freq: u32) {
let mut retry = 10;
while !get_global_hsem().lock(5).await && retry > 0 {
Timer::after_micros(50).await;
retry -= 1;
}
if retry > 0 {
//let mut mailbox = *shared::MAILBOX.get() as [u32; 10];
unsafe {
shared::MAILBOX[0] = freq;
};

get_global_hsem().unlock(5, 0);
} else {
// Core1 has asquired the semaphore and is
// not releasing it - crashed?
defmt::panic!("Failed to asquire semaphore 1");
}
}

fn get_global_hsem() -> &'static mut HardwareSemaphore<'static, HSEM> {
unsafe {
match *HSEM_INSTANCE.get() {
Some(ref mut obj) => obj,
None => defmt::panic!("HardwareSemaphore was not initialized"),
}
}
}
Loading

0 comments on commit cf9e1f4

Please sign in to comment.