ZYNQ的AMP模式下,重启CPU1后的引导

ZYNQ的AMP模式下,一种可以在线调试的重启CPU1的方法

问题背景

ZYNQ的AMP模式开发中,常常会需要对CPU1进行software Reset ,reset之后的引导是一个比较麻烦的问题。

按照官方手册的介绍,software Reset之后,CPU1会跳到0x00地址处执行。正常工作的情况下,0x00处加载的是FSBL的代码,由BSP中的boot.s来实现CPU ID的识别和代码跳转。当需要XSDK通过JTAG在线调试时,FSBL并不会加载,此时0x00处的代码未知,若对CPU1执行Reset,将无法正确实现跳转。

解决思路

按照XAPP1079的处理方式,在POR复位整个系统时,bootrom会使CPU1进入WFE状态,不断检查0xFFFFFFF0处的值是否为0,若不为0则跳转到该值指示的地址执行。所以此时只需向0xFFFFFFF0写入CPU1的代码起始地址并发送sev即可实现CPU1的重新引导。
遗憾的是,Software Reset会使CPU1直接从0x00处执行,并不会走bootrom进入WFE状态。所以思路是模仿bootrom的这一套流程,在Reset CPU1之前,通过用户代码向0x00等区域写入跳转代码,实现重启后进入WFE状态的功能。

具体办法

//重启CPU1之前执行,为进入WFE做准备
void CPU1_WfePre() {
    //向0xFFFFFF00起始的地址写入WFE指令
    Xil_Out32(0xFFFFFF00, 0xe3e0000f);
    Xil_Out32(0xFFFFFF04, 0xe3a01000);
    Xil_Out32(0xFFFFFF08, 0xe5801000);
    Xil_Out32(0xFFFFFF0C, 0xe320f002);
    Xil_Out32(0xFFFFFF10, 0xe5902000);
    Xil_Out32(0xFFFFFF14, 0xe1520001);
    Xil_Out32(0xFFFFFF18, 0x0afffffb);
    Xil_Out32(0xFFFFFF1C, 0xe1a0f002);
    
    //向0x00写入跳转代码指向0xFFFFFF00  
    Xil_Out32(0x00000000, 0xe3e0f0ff);
    
    //清0xFFFFFFF0
    Xil_Out32(0xFFFFFFF0, 0x00000000);
    
    dmb();
}

其中,向0xFFFFFF00处写入数据对应的指令为:

ffffff00:   mvn     r0, #15
ffffff04:   mov     r1, #0
ffffff08:   str     r1, [r0]
ffffff0c:   wfe
ffffff10:   ldr     r2, [r0]
ffffff14:   cmp     r2, r1
ffffff18:   beq     -20     ; addr=0xffffff0c
ffffff1c:   mov     pc, r2

可见实际就是由这段代码实现的检查0xFFFFFFF0的内容并跳转

重启CPU1的代码,参考XAPP1079即可

{
    	/*
    	 *  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 CPU0
    	//    2. A9_CLKSTOP1 = 1 to stop clock to CPU0
    	//    3. A9_RST1 = 0 to release reset to CPU0
    	//    4. A9_CLKSTOP1 = 0 to restart clock to CPU0

    	/* 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);
    }

参考:What is the state of CPU1 after a software reset through SLCR.A9_CPU_RST_CTRL

文档共60页。主要向初学者提供了Zynq开发的技术方向,针对不同应用给出了基本的参考文档;同时对Zynq双核AMP加载方式做了详细描述,对Zynq的fsbl启动流程做了简单介绍。章节如下: Zynq User Guide 1 介绍 4 2 快速上手指南 4 3 多核开发教程 4 3.1 AMP开发说明 6 3.1.1 快速生成amp工程 6 3.1.2 Generating Boot File 8 3.1.3 烧写程序 9 3.1.4 启动 10 3.1.5 调试 10 3.1.6 总结 11 3.2 SMP开发说明 11 4 ZC706启动代码分析 11 4.1 启动代码 12 4.2 FSBL流程(FOR AMP) 13 4.3 CPU0启动CPU1流程 14 5 程序在线烧写方案及流程 14 5.1 程序烧写需求 14 5.2 提出该需求的原因 14 5.3 程序烧写方案 14 5.3.1 BOOT.BIN组成 14 5.3.2 BOOT.BIN生成方法 15 5.4 FSBL.BIN和APP.BIN等的生成 15 5.5 制作*BIN及烧写的具体步骤 15 5.5.1 制作*bin流程 15 5.5.2 BOOT.bin制作过程 15 5.5.3 FSBL.bin和APP.bin等的生成过程 22 5.6 烧写BOOT.BIN步骤 26 5.6.1 通过SDK工具烧写步骤 26 5.6.2 通过上位机烧写软件的烧写步骤 29 5.6.3 通过串口调试助手烧写步骤 29 6 Zynq Qspi控制器 30 6.1 基本特性 30 6.2 I/O接口 31 6.3 QSPI控制器模式 33 6.3.1 I/O模式 33 6.3.2 线性地址(linear address)模式 33 6.3.3 传统(legacy)SPI模式 34 6.4 QSPI 例程 34 6.5 QSPI控制器支持访问32MB方法 35 6.5.1 Bank地址寄存器(Bank address register) 35 6.5.2 扩展地址模式(Extended address mode) 35 6.5.3 使用新写命令(New commands) 35 6.6 QSPI FLASH选择 35 6.7 作为BOOT器件考虑 35 7 µC/OS系统启动指南 36 7.1 INTRODUCTION 36 7.1.1 Software Requirements 36 7.1.2 Hardware Requirements 36 7.2 HARDWARE DESIGN 37 7.2.1 Step 1. Invoke the Vivado IDE and Create a project 37 7.2.2 Step 2. Create an IP Integrator Design 39 7.2.3 Step 3. Add and setup the Zynq processor system IP block 39 7.2.4 Step 4. Customize the Zynq block for our design 41 7.2.5 Step 5. Add the soft peripherals 45 7.2.6 Step 6. Generate HDL Design Files 47 7.2.7 Step 7. Synthesis, Implement and Generate Bitstream 48 7.3 SOFTWARE DESIGN 49 7.3.1 Step 1. Installation of the µC/OS Repository 49 7.3.2 Step 2. Generate the µC/OS BSP 50 7.3.3 Step 3. Build and Debug the Demonstration Project 54 7.3.4 Step 4. Program the AXI Timer 0 with the ucos_axitimer Driver 55 7.3.5 Step 5. Program the AXI Timer 1 with the Xilinx tmrctr Driver 58 7.4 CONCLUSION 59 8 Linux系统启动指南 59
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值