RT-Thread论坛
直播中

陈伟

8年用户 1572经验值
私信 关注
[问答]

smp t113-s3 A7 多核cpu0 无法唤醒cpu1 核怎么解决?


  • void rt_hw_secondary_cpu_up(void)
  • {
  •     uint32_t cpuboot_membase = 0x070005c4;
  •     uint32_t cpuxcfg_membase = 0x09010000;
  •     uint32_t cpu, reg;

  •     cpu = 1;
  •     /* Set CPU boot address */
  •     writel((uint32_t)(secondary_cpu_start), cpuboot_membase + 4 * cpu);

  •     /* Deassert the CPU core in reset */
  •     reg = readl(cpuxcfg_membase);
  •     writel(reg | (1 << cpu), cpuxcfg_membase);

  •     __asm__ volatile ("dsb":::"memory");
  •     rt_hw_ipi_send(0, 1 << 1);

  • }


想通过rt_hw_secondary_cpu_up 唤醒CPU1核, CPU1核的地址确认:

  • The Soft Entry Address Register of CPU0 is 0x070005C4.
  • The Soft Entry Address Register of CPU1 is 0x070005C8.


但是secondary_cpu_start没有被的执行过,rt_hw_ipi_send(0, 1 << 1) 这个参考的A9的唤醒方式

回帖(1)

安立路

2025-10-24 17:58:35

针对多核CPU0无法唤醒CPU1的问题,结合提供的代码片段,以下是完整的解决方案:


原因分析及解决方案:




  1. 启动地址寄存器偏移错误  



    • 代码中 cpuboot_membase + 4 * cpu 计算出的地址为 0x070005C8(当 cpu=1)。

    • 验证硬件手册:确认CPU1的启动地址寄存器偏移量是否正确(部分硬件可能使用固定偏移而非动态计算)。


    • 修正建议:  


      // 修改前
      writel((uint32_t)(secondary_cpu_start), cpuboot_membase + 4 * cpu);

      // 修改后(假设手册要求固定偏移0x04)
      writel((uint32_t)(secondary_cpu_start), cpuboot_membase + 0x04); // 固定偏移





  2. 复位控制寄存器操作错误  



    • 复位解除操作 reg | (1 << cpu) 可能不正确:

      • 位方向问题:硬件可能要求清除位(~)而非置位。

      • 位偏移错误:某些芯片的复位控制位是反向逻辑(如:0表示解除复位)。



    • 修正建议:  


      // 方案1:尝试清除复位位(常见设计)
      writel(reg & ~(1 << cpu), cpuxcfg_membase);

      // 方案2:确认硬件文档中的位操作逻辑
      // 例如:若文档要求写1解除复位,则用 OR 操作;若写0解除,则用 AND 取反





  3. 缺失内存屏障指令  



    • 寄存器操作后需插入屏障确保执行顺序。

    • 修正建议:  
      writel(reg | (1 << cpu), cpuxcfg_membase);
      // 插入数据同步屏障
      __asm__ volatile("dsb sy");
      __asm__ volatile("isb");




  4. 次级CPU启动代码未初始化  



    • 确保 secondary_cpu_start 已正确实现:

      • 包含核心初始化(MMU、缓存、栈指针)。

      • 通知操作系统核心已启动。


    • 示例代码:  
      void secondary_cpu_start(void) {
      // 初始化核心硬件
      rt_hw_vector_init();
      rt_hw_spin_lock(&_cpus_lock);
      // 设置栈指针
      __asm__ volatile("mov sp, %0" : : "r"(core1_stack_base));
      // 跳转到操作系统入口
      rt_system_scheduler_start();
      }




  5. 添加启动延迟  



    • 解除复位后增加短暂延时:  
      // 解除复位后添加微秒级延时
      for (volatile int i = 0; i < 1000; i++);




完整修正代码:


void rt_hw_secondary_cpu_up(void) {
    uint32_t cpuboot_membase = 0x070005c4;
    uint32_t cpuxcfg_membase = 0x09010000;
    uint32_t cpu = 1;

    // 1. 设置启动地址(修正固定偏移)
    writel((uint32_t)(secondary_cpu_start), cpuboot_membase + 0x04); // 固定偏移0x04

    // 2. 内存屏障确保写入完成
    __asm__ volatile("dsb st");
    __asm__ volatile("isb");

    // 3. 解除复位(注意位操作逻辑!)
    uint32_t reg = readl(cpuxcfg_membase);
    // 假设文档要求写0解除复位
    writel(reg & ~(1 << cpu), cpuxcfg_membase); // 或根据手册调整

    // 4. 屏障+延时
    __asm__ volatile("dsb sy");
    __asm__ volatile("isb");
    for (volatile int i = 0; i < 1000; i++); // 延时等待
}

其他关键检查项:



  1. 硬件配置

    • 确认CPU时钟和电源已使能(查看PMU寄存器)。

    • 验证AXI总线互连配置是否允许CPU1访问内存。


  2. 固件协作

    • 检查BootROM是否已释放CPU1(部分芯片需ATF固件处理)。


  3. 调试手段

    • 通过JTAG查看CPU1 PC寄存器是否跳转到 secondary_cpu_start

    • 在启动地址处添加死循环,用示波器检测信号变化。




重要提示:以上偏移量和位操作需以芯片手册为准(如全志T113-S3手册)。若问题仍未解决,请重点核查复位控制寄存器的具体位定义及电源管理单元(PMU)配置。


举报

更多回帖

发帖
×
20
完善资料,
赚取积分