Skip to content

第十六周工作总结

本周完成的功能

本周成功实现了JH7110双核系统之间的双向核间通信:

  • embassy_preempt → StarryOS:hart0定时发送IPI到hart1,StarryOS成功接收并记录
  • StarryOS → embassy_preempt:在StarryOS中执行 echo 1 > /dev/ipi 可触发hart0中断

第一部分:实现Hart间通信基础机制

本周在embassy_preempt和StarryOS中分别实现了hart0和hart1之间的双向通信机制。

工作目的

为JH7110的多核配置实现完整的核间通信(IPI, Inter-Processor Interrupt)机制:

  • hart0 (M态): embassy_preempt RTOS
  • hart1 (S态): StarryOS

工作成果

1. 简单Hart同步标志结构体

example/src/bin/console.rs 中实现了共享内存同步机制:

目前暂时将HartSyncFlags放在0xc8000000

rust
#[repr(C)]
pub struct HartSyncFlags {
    pub magic_number: u16,
    /// Hart1 上的 OS 是否已经启动
    pub hart1_os_ready: AtomicBool,
    /// Hart0 是否发送了 IPI
    pub hart0_ipi_sent: AtomicBool,
}

2. Machine Software Interrupt 处理

interrupt.rs 中添加了MSIP中断处理:

rust
riscv_irq::M_SOFT => {
    os_log!(trace, "[IRQ] MSIP");
    let msip: *mut usize = 0x02000000 as *mut usize;
    core::ptr::write_volatile(msip, 0);
}

MSIP寄存器地址

  • Hart0: 0x02000000
  • Hart1: 0x02000004

3. 任务7 - 定时IPI测试

添加了异步任务测试hart间通信:

rust
async fn task7(_args: *mut c_void) {
    let hart_sync = get_hart_sync();
    loop {
        task_log!(info, "hello");
        Timer::after_ticks(16_000_000).await;
        if hart_sync.is_hart1_ready() {
            hart_sync.set_ipi_sent();
            // 触发hart1的MSIP
            let msip_hart1: *mut u32 = 0x0200_0004 as *mut u32;
            core::ptr::write_volatile(msip_hart1, 1);
        }
    }
}

4. 启用Machine Software Interrupt

platform.rs 中启用MSIP:

rust
unsafe {
    riscv::register::mstatus::set_mie();
    riscv::register::mie::set_msoft();  // 新增
    // ...
}

第二部分:StarryOS端IPI设备实现

在StarryOS中实现了完整的IPI字符设备,支持与hart0的核间通信。

1. IPI字符设备 (kernel/src/pseudofs/dev/ipi.rs)

功能

  • 写设备:通过SBI调用发送IPI到hart0
  • 读设备:获取接收到的IPI事件消息
  • IRQ处理:注册软件中断处理函数

核心实现

rust
/// IPI Character Device
pub struct IpiDevice;

impl DeviceOps for IpiDevice {
    fn write_at(&self, buf: &[u8], _offset: u64) -> VfsResult<usize> {
        // 通过SBI调用发送IPI到hart0
        send_ipi_to_hart0()?;
        Ok(buf.len())
    }

    fn read_at(&self, buf: &mut [u8], _offset: u64) -> VfsResult<usize> {
        // 读取IPI消息队列
        let mut messages = IPI_MESSAGES.lock();
        // ...
    }
}

2. Hart同步机制

与embassy_preempt使用相同的共享内存结构体:

rust
#[repr(C)]
pub struct HartSyncFlags {
    pub magic_number: u16,
    pub hart1_os_ready: AtomicBool,
    pub hart0_ipi_sent: AtomicBool,
}

设备初始化时自动标记hart1 OS已就绪:

rust
fn mark_hart1_os_ready() {
    let sync = get_hart_sync();
    sync.hart1_os_ready.store(true, Ordering::Release);
}

3. 设备注册

/dev/ipi 创建字符设备:

rust
root.add(
    "ipi",
    Device::new(
        fs.clone(),
        NodeType::CharacterDevice,
        DeviceId::new(10, 200),
        Arc::new(ipi::IpiDevice::new()),
    ),
);

第三部分:修复上下文切换mepc错误

本周修复了上下文切换时 mepc 寄存器会被错误设置的问题。

问题描述

在中断处理完成后进行上下文切换时,mepc (Machine Exception Program Counter) 的值不正确,导致程序跳转到错误的地址。


第四部分:构建系统更新

升级了Rust工具链并优化了构建配置:

  • Rust版本更新nightly-2025-11-05nightly-2026-03-15
  • 添加StarryOS构建环境:增加 riscv64-unknown-linux-musl 交叉编译支持

第五部分:中断处理重构

interrupt.rs 中进行了代码重构:

  • RISC-V中断编号常量化:新增 riscv_irq 模块
  • PLIC中断处理改进:支持多个挂起中断的循环处理
  • 中断处理函数表:分离 RISC-V 中断和 PLIC 外部中断的处理

下一步计划

  1. 独立的Hart通信库:将 HartSyncFlags 抽取为独立库,供embassy_preempt和StarryOS共同调用
  2. 消息队列功能:在共享库中实现环形缓冲区消息队列
  3. 中断驱动接收:IPI中断触发时自动调用消息接收处理