针对多核CPU0无法唤醒CPU1的问题,结合提供的代码片段,以下是完整的解决方案:
启动地址寄存器偏移错误
cpuboot_membase + 4 * cpu 计算出的地址为 0x070005C8(当 cpu=1)。修正建议:
// 修改前
writel((uint32_t)(secondary_cpu_start), cpuboot_membase + 4 * cpu);
// 修改后(假设手册要求固定偏移0x04)
writel((uint32_t)(secondary_cpu_start), cpuboot_membase + 0x04); // 固定偏移复位控制寄存器操作错误
reg | (1 << cpu) 可能不正确:~)而非置位。修正建议:
// 方案1:尝试清除复位位(常见设计)
writel(reg & ~(1 << cpu), cpuxcfg_membase);
// 方案2:确认硬件文档中的位操作逻辑
// 例如:若文档要求写1解除复位,则用 OR 操作;若写0解除,则用 AND 取反缺失内存屏障指令
writel(reg | (1 << cpu), cpuxcfg_membase);
// 插入数据同步屏障
__asm__ volatile("dsb sy");
__asm__ volatile("isb");次级CPU启动代码未初始化
secondary_cpu_start 已正确实现: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();
}添加启动延迟
// 解除复位后添加微秒级延时
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++); // 延时等待
}secondary_cpu_start。
重要提示:以上偏移量和位操作需以芯片手册为准(如全志T113-S3手册)。若问题仍未解决,请重点核查复位控制寄存器的具体位定义及电源管理单元(PMU)配置。
举报
更多回帖