Zynq启动CPU1的步骤(寄存器A9_CPU_RST_CTRLS)

本文详细介绍了如何使用Zynq AMP架构中的CPU0来启动CPU1的过程。主要内容包括设置CPU1的捕获地址、复位和时钟控制等关键步骤,并提供了具体的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近要用到Zynq的AMP,看了xapp1079,关于CPU0启动CPU1的介绍还是比较细腻的,摘录之。

SDK中的代码:

print("CPU0: writing startaddress for cpu1\n\r");

    {
    	/*
    	 *  Reset and start CPU1
    	 *  - Application for cpu1 exists at 0x00000000 per cpu1 linkerscript
    	 *
    	 */
		#include "xil_misc_psreset_api.h"
		#include "xil_io.h"

    	#define A9_CPU_RST_CTRL		(XSLCR_BASEADDR + 0x244)
		#define A9_RST1_MASK 		0x00000002
		#define A9_CLKSTOP1_MASK	0x00000020
		#define CPU1_CATCH			0x00000024

		#define XSLCR_LOCK_ADDR		(XSLCR_BASEADDR + 0x4)
		#define XSLCR_LOCK_CODE		0x0000767B

    	u32 RegVal;


    	/*
    	 * Setup cpu1 catch address with starting address of app_cpu1. The FSBL initialized the vector table at 0x00000000
    	 * using a boot.S that checks for cpu number and jumps to the address stored at the
    	 * end of the vector table in cpu0_catch and cpu1_catch entries.
    	 * Note: Cache has been disabled at the beginning of main(). Otherwise
		 * a cache flush would have to be issued after this write
    	 */
    	Xil_Out32(CPU1_CATCH, APP_CPU1_ADDR);


    	/* Unlock the slcr register access lock */
    	Xil_Out32(XSLCR_UNLOCK_ADDR, XSLCR_UNLOCK_CODE);

    	//    the user must stop the associated clock, de-assert the reset, and then restart the clock. During a
    	//    system or POR reset, hardware automatically takes care of this. Therefore, a CPU cannot run the code
    	//    that applies the software reset to itself. This reset needs to be applied by the other CPU or through
    	//    JTAG or PL. Assuming the user wants to reset CPU1, the user must to set the following fields in the
    	//    slcr.A9_CPU_RST_CTRL (address 0xF8000244) register in the order listed:
    	//    1. A9_RST1 = 1 to assert reset to CPU1
    	//    2. A9_CLKSTOP1 = 1 to stop clock to CPU1
    	//    3. A9_RST1 = 0 to release reset to CPU1
    	//    4. A9_CLKSTOP1 = 0 to restart clock to CPU1

    	/* Assert and deassert cpu1 reset and clkstop using above sequence*/
    	RegVal = 	Xil_In32(A9_CPU_RST_CTRL);
    	RegVal |= A9_RST1_MASK;
    	Xil_Out32(A9_CPU_RST_CTRL, RegVal);
    	RegVal |= A9_CLKSTOP1_MASK;
    	Xil_Out32(A9_CPU_RST_CTRL, RegVal);
    	RegVal &= ~A9_RST1_MASK;
		Xil_Out32(A9_CPU_RST_CTRL, RegVal);
    	RegVal &= ~A9_CLKSTOP1_MASK;
		Xil_Out32(A9_CPU_RST_CTRL, RegVal);

    	/* lock the slcr register access */
    	Xil_Out32(XSLCR_LOCK_ADDR, XSLCR_LOCK_CODE);

    }

上述着重注意两部分:

其一为Xil_Out32(CPU1_CATCH, APP_CPU1_ADDR);这句中CPU1_CATCH宏定义为0x24,看代码中注释即可明白,其实这个0x24是在boot.s的汇编中起作用。跳到boot.s:

#include "xparameters.h"
#include "xil_errata.h"

.globl MMUTable
.global _prestart
.global _boot
.global __stack
.global __irq_stack
.global __supervisor_stack
.global __abort_stack
.global __fiq_stack
.global __undef_stack
.global _vector_table

.globl _cpu0_catch
.globl _cpu1_catch
.globl OKToRun
.globl EndlessLoop0
按理说应该对应.globl _cpu1_catch才对,而且boot.s中下面的执行代码也的确用到了这个量,不过怎么数.globl _cpu1_catch也是0x2C,这个疑问留待以后吧。


其二是启动CPU1的部分:

RegVal = 	Xil_In32(A9_CPU_RST_CTRL);
    	RegVal |= A9_RST1_MASK;
    	Xil_Out32(A9_CPU_RST_CTRL, RegVal);
    	RegVal |= A9_CLKSTOP1_MASK;
    	Xil_Out32(A9_CPU_RST_CTRL, RegVal);
    	RegVal &= ~A9_RST1_MASK;
		Xil_Out32(A9_CPU_RST_CTRL, RegVal);
    	RegVal &= ~A9_CLKSTOP1_MASK;
		Xil_Out32(A9_CPU_RST_CTRL, RegVal);

这部分的注释也说的很明白,要想启动一个CPU,首先不能自己去启动自己,其次按步骤走即可:

1、停止与该CPU相关联的时钟;

2、禁能该CPU的复位;

3、重启该CPU的时钟;

上述代码也分别是做这三件事的。




评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值