zynq的linux管理了软中断吗,ZYNQ笔记(5):软中断实现核间通信

ZYNQ包括一个 FPGA 和两个 ARM,多个 ARM 核心相对独立的运行不同的任务,每个核心可能运行不同的操作系统或裸机程序,但是有一个主要核心,用来控制整个系统以及其他从核心的允许。因此我们可以在 CPU0 和 CPU1 中独立跑不同的应用程序,发挥双核的非对称性架构的优势和性能。

从软件的角度来看,多核处理器的运行模式主要有三种:

① AMP(非对称多进程):多个核心相对独立的运行不同的任务,每个核心可能运行不同的操作系统或裸机程序,但是有一个主要核心,用来控制整个系统以及其它从核心的运行。

② SMP(对称多进程):一个操作系统同等的管理各个内核,例如 PC 机。

③ BMP(受约束多进程):与 SMP 类似,但开发者可以指定将某个任务仅在某个指定内核上执行默认情况下。

裸机程序 ZYNQ 仅运行一个 CPU,这里主要讲解 AMP 模式下,两个 CPU 同时运行的裸机程序开发方法。

一、核间中断原理(软中断SGI)

253d702cb33d8aa424973a103f7ee908.png

1944ac67dbc7087ca80f76b58f394a49.png

软中断的 ID 都是从0到15,并且都是上升沿触发,主要用于核间中断或者 CPU 自己中断自己。

中断函数如下:

XScuGic_SoftwareIntr(&InterruptController,   //指向GIC指针

INTC_CPU0,//需要中断的CPU ID

XSCUGIC_SPI_CPU0_MASK); //使能该CPU会接受中断

二、ARM启动过程

1.ARM 里有个 ROM,存储了一段程序,ROM起来后从 SD 卡读取数据2.启动 FSBL(First Boot Loader)第一启动项(有模板)3.加载 bit(FPGA配置程序),同时加载 elf(ARM应用程序),如果是操作系统则 elf 替换成 uBoot

三、搭建软件 CPU0 和 CPU1 非对称环境

1.创建 amp_fsbl 用于生成烧写镜像的时候加载 core0 和 core1的代码。

①启动 Vivado,创建 ZYNQ,勾选  SD卡 和 UART 即可,并加载 SDK 开发环境

②进到 SDK ,点击 File --- New --- Application Project,命名为 amp_fsbl 并选择 CPU0

1af6f79766ddb827ebb0401bc9bc0314.png

③选择 FSBL,finish

cf16b377b51e340663435ede9e49f557.png

④修改 main.c 函数来启动 core1,需要两个步骤,首先把 CPU1 应用程序地址写入到 0xfffffff0地址中,这是启动 CPU1 命令的地址,然后执行 sev 指令加载 CPU1 应用程序。具体参考 UG585 的启动代码章节。

在 main.c 函数的 main 函数上方插入这段代码:

1 #define sev() __asm__("sev")

2 #define CPU1STARTADR 0xFFFFFFF0

3 #define CPU1STARTMEM 0x2000000

4

5 void StartCpu1(void)6 {7 #if 1

8 fsbl_printf(DEBUG_GENERAL,"FSBL: Write the address of the application for CPU 1 to 0xFFFFFFF0\n\r");9 Xil_Out32(CPU1STARTADR, CPU1STARTMEM);10 dmb(); //waits until write has finished

11 fsbl_printf(DEBUG_GENERAL,"FSBL: Execute the SEV instruction to cause CPU 1 to wake up and jump to the application\n\r");12 sev();13 #endif

14 }

在 main.c 函数的 load镜像位置加入代码: StartCpu1();

6cc4d06935b745128080bad24706ecc6.png

2.创建 app_cpu0 应用程序

①重新创建一个新的 File --- New --- Application Project,命名为 app_cpu0,这时选择的是 CPU0

8f8e44739702b4580475e429240ec1fc.png

②选择 helloworld 模板即可

4d2b0a96903c34074389c6d5cc7ac053.png

③将 helloworld.c 改名为 mian.c,并且用如下代码替换掉内容

1 #include

2 #include "platform.h"

3 #include "xil_printf.h"

4

5 #define COMM_VAL (*(volatile unsigned long *)(0xFFFF0000)) //无优化无符号长整形地址转成指针

6

7 intmain()8 {9 COMM_VAL=0;10

11 //Disable cache on OCM

12 Xil_SetTlbAttributes(0xFFFF0000,0x14de2);13 while(1)14 {15 print("Hello World cpu0 \n\r");16 COMM_VAL =1;17 while(COMM_VAL == 1)18 {19 }20 }21 return 0;22 }

该指针指向的地址为片上存储的共享内存(OCM)。可以指定这里面的任意一个地址。定义的指针变量如下所示: #define COMM_VAL (*(volatile unsigned long *)(0x00020000)) 该变量CPU0和CPU1都可以在里面读写数据,可以达到CPU0和CPU1的数据交互。OCM的地址如下图所示。

3ea8669d614d5020e80d84c6d8f2285d.png

6ec2b8e02662c64d149cc776f00152ba.png

④打开 Scr 目录中的文件 lscript.ld,点击下方的 Source 做如下修改:CPU0 的代码空间改为 1E00000

9f4511984ad12044929eeec7ad13e5b6.png

CPU1运行程序的地址改为fsbl里面指定的起始地址。后面为长度,有一点需要注意:CPU0的起始地址加上CPU0的长度之后不能超过CPU1的起始地址。也就是两个CPU占用的DDR的地址不能重叠。若程序很大,则CPU0需要的LENGTH就大,因此CPU1的起始地址数值就大。DDR地址范围如下所示:

a6cfcbe4a6bffdf4e1a0614f66872fe8.png

3.创建 app_cpu1 应用程序

①重新创建一个新的 File --- New --- Application Project,命名为 app_cpu1,这时选择的是 CPU1

9170691c676c90752602d623b71ad714.png

②选择 helloworld 模板即可

a7cd0314dbd270786fabb1faf4e4c036.png

③将 helloworld.c 改名为 mian.c,并且用如下代码替换掉内容

1 #include

2 #include "platform.h"

3 #include "xil_printf.h"

4

5 #define COMM_VAL (*(volatile unsigned long *)(0xFFFF0000))

6 intmain()7 {8 //Disable cache on OCM

9 Xil_SetTlbAttributes(0xFFFF0000,0x14de2);10 while(1)11 {12 while(COMM_VAL == 0)13 {14 }15 print("Hello World cpu1 \n\r");16 sleep(2);17 COMM_VAL=0;18 }19 return 0;20 }

④打开 Scr 目录中的文件 lscript.ld 点击下方的 Source 做如下修改起始地址改为 0x2000000 长度 0x1F00000

8c39f35fd1e1f43ad6b30740e6aa2098.png

4.增加编译选项(设置 CPU1 的BSP setting 为 AMP 模式)

app_cpu1_bps --- 右键 --- Board Suport Package Setting,点击 driver --- ps7_cortexa9_0,添加指令

28a211225b00f6cc6cb22e91c7b94a2f.png

5.让双核跑起来

①点击 app_cpu0 --- 右键 --- Debug As --- Debug Configurations...

cfd8c276687073f6f7232e0a9ee63e64.png

② 点击选项卡的 Application,勾选 0 和 1,然后点击 Debug,yes

1539a78b03aa6f6f733b9ddd3506bee5.png

③默认停到第一行,连接好串口,选择APU --- ARM --- #0,单步慢慢走可以看到有信息打印出,#2也是一样的。如果让 #0 和 #1 都一直执行,则串口会一直交替打印。

e1d7335734296a87478b74383104dac6.png

四、软中断的注册和使用

84b309b41bedb095752700a81e0185e1.png

参考资料:

[1]V3学院FPGA教程

[2]何宾, 张艳辉. Xilinx Zynq-7000嵌入式系统设计与实现[M]. 电子工业出版社, 2016.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值