目录

前言

1.BSP工程说明

第一步:创建BSP工程,选择硬件平台、cpu核和支持的OS

第二步:BSP工程设置

(1)版本+库文件选择

(2)standalone配置

(3)drivers支持

(4)编译选项

2.sdk_repo的作用

(1)STDOUT_REDIR 宏定义

(2)boot.S

(2.1)CPU1内存分配(必须)

(2.2)启动地址重映射:_boot(非必须)

(2.3)AMP模式禁用L2 cache(必须)

(3)asm_vectors.S(非必须)

(4)xtime_l.c修改(必须)

3.总结归纳

4.附录




前言

前面一篇文章基本上讲解了Zynq的AMP模式的开发流程,需要结合Vivado、SDK和Petalinux三个软件。在开发过程中还需要注意一些问题:sdk_repo的使用、设备树的定义、uboot启动参数、内核映像文件类型等等,这里首先说明sdk_repo的使用问题。


首先,在SDK中开发用户应用程序时,需要有2个工程文件:用户应用程序工程+BSP工程。

其中,BSP工程为应用程序工程提供板级支持,BSP工程中封装了板卡所有底层硬件的原理描述和函数操作,用户不需要详细了解板卡底层的设计原理,只需要直接使用BSP提供的API接口函数即可对硬件进行相应操作。

版本说明:

本人安装的开发软件均是2017.4版本,软件自带的sdk源码版本为:standalone_v6_5;

官方资料xapp1078_2014.04下载中,提供的sdk_repo源码版本为:standalone_v4_299;



1.BSP工程说明

注意:这里并没有将BSP配置成AMP模式,只是简单介绍BSP工程的创建流程。


第一步:创建BSP工程,选择硬件平台、cpu核和支持的OS

第二步:BSP工程设置

(1)版本+库文件选择

在安装SDK软件时,standalone文件自动包含在安装包中,默认的版本已确定,除非使用用户的standalone。

库文件可以根据用户需要自行选择,如openamp库。

(2)standalone配置

主要是需要配置系统所使用的输入输出接口:一般选择uart0或uart1。

zynq_fsbl_bsp:当创建fsbl工程时的bsp工程师,才会选择有效。

(3)drivers支持

以下显示是bsp提供的驱动支持,用于应用程序对底层硬件的访问和操作。

(4)编译选项

程序从创建到生产可执行文件需要历经:预处理、编译、汇编、连接。

archiver:linux系统下交叉编译工具中的库管理器。

compiler:linux系统下交叉编译工具中的集成编译工具。

compiler flag:gcc编译标志

extra compiler flag:gcc附加编译标志

归纳:由创建到生成BSP工程的过程中,用户需要根据自己的使用要求进行合理修改,前提是需要理解配置选项的具体作用。


2.sdk_repo的作用

在基于官方文档:《xapp1078-amp-linux-bare-metal.pdf》进行AMP模式开发中,必须要使用到官方提供的sdk_repo文件。针对AMP模式,sdk_repo中对一些启动文件进行了必要的修改,下面进行详细说明:

修改设计内容:(参考1078官方资料下的《Vivado instructions.txt》)

standalone BSP.Note: The standalone v4.2 BSP was modified as follows: - armcc/_sys_write.c, gcc/write.c, printc, xil_printf.c: These changes add a new define 'STDOUT_REDIR'that prevents the removal of calls to outbyte() if STDOUT_BASEADDRESS is not defined- armcc/boot.S, gcc/boot.S: These changes remove remapping of virtual address 0x20000000 to physicaladdress 0x00000000, configures address 0x00000000-0x2fffffff to be unavailable, and disables sharingand L2 cache on address 0x30000000-0x3fffffff. The startup code was also modified to allow redirectingcpu0 or cpu1 to a different starting address (This redirecting ability is not used for xapp1078).- xtime_l.c: The change to this file prevents re-initializing the global timer.- asm_vectors.S: Two extra vectors are added at the end of the vector table and are used by the boot.Sredirecting code. (This redirecting ability is not used for xapp1078).

(1)STDOUT_REDIR 宏定义

在armcc/_sys_write.c, gcc/write.c, printc, xil_printf.c中,所有涉及到print打印函数的地方,都增加了对应的宏定义,如:

#if defined STDOUT_BASEADDRESS || STDOUT_REDIRoutbyte( *lp++);
#endif

原因:1078提供的AMP设计中,双核通信过程:cpu1会通过xil_printf()函数将打印消息发送给cpu0,cpu0再通过系统uart1将打印消息发送给显示器。

在1078的bsp设置中,Select Overview->standalone and change stdin and stdout to None,没有定义输入输出端设备,即没有STDOUT_BASEADDRESS 宏。为了避免xil_printf()无效,才有了STDOUT_REDIR 宏定义。

(我的配置:在vivado中使能uart0:使用EMIO引脚,使能uart1:使用ps侧标准IO;在cpu1的bsp配置中使用uart0;

因此,不需要定义STDOUT_REDIR,demo也可以正常运行)


(2)boot.S

(2.1)CPU1内存分配(必须)

作用:限定cpu1的裸机程序不可访问低内存空间(保留给linux系统专用)

第一:将虚拟地址0x20000000重新映射到物理地址0x00000000 部分的代码注释(注意:sdk软件自带的standalone不会有这段代码,可忽略此步,这段代码可能是xilinx以前增加的)

第二:将地址0x00000000-0x2fffffff(768M)配置为不可用。注意:这里配置的DDR是1G,因此cpu1运行裸机程序的情况下,配置低768M给cpu0使用,cpu1只是用高256M。如果DDR是512M,分为模式应该是:384M+128M。

第三:设置0x30000000-0x3fffffff仅作为CPU1的内部使用。如果DDR是512M,因该是高128M。

注意:关于MMU的原理和相关描述符的具体含义请参考《 嵌入式系统Linux内核开发实战指南ARM平台.pdf》中的第4章节(这里讲的描述符可能不是arm最新架构的,比如没有标志位s,此时参考下文:MMU配置和使用)

//第一步:注释代码
//  /* In case of AMP, map virtual address 0x20000000 to 0x00000000  and mark it as non-cacheable */
//#if USE_AMP==1
//  ldr r3, =0x1ff         /* 512 entries to cover 512MB DDR */
//  ldr r0, =TblBase           /* MMU Table address in memory */
//  add r0, r0, #0x800          /* Address of entry in MMU table, for 0x20000000 */
//  ldr r2, =0x0c02            /* S=b0 TEX=b000 AP=b11, Domain=b0, C=b0, B=b0 */
//mmu_loop:
//  str r2, [r0]            /* write the entry to MMU table */
//  add r0, r0, #0x4            /* next entry in the table */
//  add r2, r2, #0x100000       /* next section */
//  subs    r3, r3, #1
//  bge mmu_loop            /* loop till 512MB is covered */
//#endif/* In case of AMP, mark address 0x00000000 - 0x2fffffff DDR as unassigned/reserved *//* and address 0x30000000 - 0x3fffffff DDR as inner cached only */#if USE_AMP==1//第二步:保留低768M(如果DDR是512M,可将768M修改为384M,cpu0也可以正常运行系统)ldr  r3, =0x2ff           /* 768 entries to cover 768MB DDR */ldr   r0, =TblBase           /* MMU Table address in memory */ldr    r2, =0x0000              /* S=b0 TEX=b000 AP=b00, Domain=b0, C=b0, B=b0 */
mmu_loop:str    r2, [r0]                /* write the entry to MMU table */add   r0, r0, #0x4            /* next entry in the table */add    r2, r2, #0x100000   /* next section */subs  r3, r3, #1bge   mmu_loop                /* loop till 768MB is covered *///第三步:设置高256M专为CPU1使用(如果DDR是512M,这里的256M需修改为128M)ldr    r3, =0x0ff           /* 256 entries to cover 256MB DDR */movw r2, #0x4de6        /* S=b0 TEX=b100 AP=b11, Domain=b1111, C=b0, B=b1 *///注意:CB为01:表示cpu1的MMU设置为了分段地址管理,不支持cache但支持buffer;mmu域是15;保护标志位为0;访问权限为11:可读可写;在ARMv5以上版本处理器中有定义,如果TEX等于1,表示系统支持写时分配cache,这里没有分配cache;s为0:表示此内存不共享!movt r2, #0x3000      /* S=b0, Section start for address 0x30000000 */
mmu_loop1:str   r2, [r0]                /* write the entry to MMU table */add   r0, r0, #0x4            /* next entry in the table */add    r2, r2, #0x100000   /* next section */subs  r3, r3, #1bge   mmu_loop1               /* loop till 256MB is covered */
#endif

(2.2)启动地址重映射:_boot(非必须)

(注意:这个功能在1078上用不上,可不增加这一段)

...
...
.globl _cpu0_catch
.globl _cpu1_catch
.globl OKToRun
.globl EndlessLoop0
...
..._boot:        //复位中断向量,系统复位后代码从这里启动/* Test which processor is running and jump to the catch address */mrc p15,0,r1,c0,c0,5and r1, r1, #0xfcmp r1, #0bne   NotCpu0               //如果不是cpu0,则跳转到NotCpu0处继续判断ldr r0, =_cpu0_catch      //如果是CPU0,则准备跳转到_cpu0_catch处b cpuxCont
NotCpu0:                    //如果不是cpu0cmp   r1, #1              bne EndlessLoop0        //如果也不是cpu1,则跳转到endlessloop0ldr  r0, =_cpu1_catch    //如果是cpu1,则准备跳转到_cpu1_catch处b cpuxCont
EndlessLoop0:wfe                     //等待唤醒信号b  EndlessLoop0    /* Jump to address pointed to by cpux_catch */
cpuxCont:ldr lr, [r0]bx lr                //执行跳转OKToRun:mrc     p15, 0, r0, c0, c0, 0       /* Get the revision */and     r5, r0, #0x00f00000 and     r6, r0, #0x0000000forr     r6, r6, r5, lsr #20-4
...
...

但是,standalone_v6_5中也有类似的一段,如下:

作用:从下面的汇编来看,如果实际加载中测到的CPU_ID和配置的CPU_ID如果不同,BSP将无法启动。

......
.set SLCRCPURSTReg,     (0xF8000000 + 0x244)           /*(XPS_SYS_CTRL_BASEADDR + A9_CPU_RST_CTRL_OFFSET)*/
.set EFUSEStaus,        (0xF800D000 + 0x10)            /*(XPS_EFUSE_BASEADDR + EFUSE_STATUS_OFFSET)*/
......_prestart:
_boot:#if XPAR_CPU_ID==0            //如果bsp中设置的是CPU0,则只有cpu0会启动,cpu1无法启动!/* only allow cpu0 through */mrc    p15,0,r1,c0,c0,5and r1, r1, #0xfcmp r1, #0beq   CheckEFUSEEndlessLoop0:wfeb EndlessLoop0CheckEFUSE:ldr r0,=EFUSEStausldr r1,[r0]                             /* Read eFuse setting */ands r1,r1,#0x80                        /* Check whether device is having single core */beq OKToRun/* single core device, reset cpu1 */ldr     r0,=SLCRUnlockReg               /* Load SLCR base address base + unlock register */ldr     r1,=SLCRUnlockKey               /* set unlock key */str     r1, [r0]                        /* Unlock SLCR */ldr r0,=SLCRCPURSTRegldr r1,[r0]                             /* Read CPU Software Reset Control register */orr r1,r1,#0x22str r1,[r0]                             /* Reset CPU1 */ldr  r0,=SLCRlockReg            /* Load SLCR base address base + lock register */ldr   r1,=SLCRlockKey                /* set lock key */str   r1, [r0]                /* lock SLCR */#elif XPAR_CPU_ID==1        //如果bsp中设置的是CPU1,则只有cpu1会启动,cpu0无法启动!/* only allow cpu1 through */mrc p15,0,r1,c0,c0,5and r1, r1, #0xfcmp r1, #1beq   CheckEFUSE1b        EndlessLoop1CheckEFUSE1:ldr r0,=EFUSEStausldr r1,[r0]                             /* Read eFuse setting */ands r1,r1,#0x80                        /* Check whether device is having single core */beq OKToRunEndlessLoop1:wfeb EndlessLoop1
#endif

(2.3)AMP模式禁用L2 cache(必须)

作用:如果是AMP模式,cpu1就需要禁用L2 cache;(这段代码两个sdk源码均有,不需要用户添加)

原因参考《Zynq的AMP开发注意事项之禁用L2 cache》

/* For AMP, assume running on CPU1. Don't initialize L2 Cache (up to Linux) */
#if USE_AMP!=1ldr  r0,=L2CCCrtl           /* Load L2CC base address base + control register */mov    r1, #0              /* force the disable bit */str  r1, [r0]            /* disable the L2 Caches */ldr  r0,=L2CCAuxCrtl            /* Load L2CC base address base + Aux control register */ldr    r1,[r0]             /* read the register */ldr  r2,=L2CCAuxControl     /* set the default bits */orr   r1,r1,r2str r1, [r0]            /* store the Aux Control Register */ldr r0,=L2CCTAGLatReg      /* Load L2CC base address base + TAG Latency address */ldr r1,=L2CCTAGLatency     /* set the latencies for the TAG*/str   r1, [r0]            /* store the TAG Latency register Register */ldr    r0,=L2CCDataLatReg     /* Load L2CC base address base + Data Latency address */ldr    r1,=L2CCDataLatency        /* set the latencies for the Data*/str  r1, [r0]            /* store the Data Latency register Register */ldr   r0,=L2CCWay            /* Load L2CC base address base + way register*/ldr r2, =0xFFFFstr r2, [r0]            /* force invalidate */ldr   r0,=L2CCSync           /* need to poll 0x730, PSS_L2CC_CACHE_SYNC_OFFSET *//* Load L2CC base address base + sync register*/
......

(3)asm_vectors.S(非必须)

在向量表的末尾添加了两个额外的向量,由boot.s中的重定向代码使用。

.globl _boot
.globl _vector_table
.globl _cpu0_catch
.globl _cpu1_catch
.globl OKToRun
.globl EndlessLoop0.globl FIQInterrupt
.globl IRQInterrupt
.globl SWInterrupt
.globl DataAbortInterrupt
.globl PrefetchAbortInterrupt.globl IRQHandler
.globl prof_pc.section .vectors
_vector_table:B _bootB  UndefinedB  SVCHandlerB PrefetchAbortHandlerB   DataAbortHandlerNOP /* Placeholder for address exception vector*/B  IRQHandlerB FIQHandler#if XPAR_CPU_ID==0        //如果bsp中设置的是CPU0
_cpu0_catch:              //则:cpu0可以运行
.word   OKToRun         /* fixed addr for caught cpu- */
_cpu1_catch:              //cpu1会跳转到等待wfe循环中
.word   EndlessLoop0    /* fixed addr for caught cpu- */#elif XPAR_CPU_ID==1       //如果bsp中设置的是cpu1,则cpu启动与上述相反
_cpu0_catch:
.word   EndlessLoop0
_cpu1_catch:
.word   OKToRun
#endifIRQHandler:                   /* IRQ vector handler */stmdb   sp!,{r0-r3,r12,lr}      /* state save from compiled code*/
#ifdef __ARM_NEON__vpush {d0-d7}vpush {d16-d31}vmrs r1, FPSCRpush {r1}vmrs r1, FPEXCpush {r1}
#endif......

(4)xtime_l.c修改(必须)

作用:在AMP模式下,global全局定时器肯定会在CPU0的系统中完成初始化,因此避免CPU1启动或是运行过程中CPU1重启时,将global全局定时器reset!

void XTime_SetTime(XTime Xtime)
{#ifdef USE_AMPif(Xil_In32(GLOBAL_TMR_BASEADDR + GTIMER_CONTROL_OFFSET) && 0x1) {//Timer is already enabled so don't reset itreturn;}
#endif/* Disable Global Timer */Xil_Out32(GLOBAL_TMR_BASEADDR + GTIMER_CONTROL_OFFSET, 0x0);/* Updating Global Timer Counter Register */Xil_Out32(GLOBAL_TMR_BASEADDR + GTIMER_COUNTER_LOWER_OFFSET, (u32)Xtime);Xil_Out32(GLOBAL_TMR_BASEADDR + GTIMER_COUNTER_UPPER_OFFSET,(u32)(Xtime>>32));/* Enable Global Timer */Xil_Out32(GLOBAL_TMR_BASEADDR + GTIMER_CONTROL_OFFSET, 0x1);
}

3.总结归纳

(1)首先,1078文件中提供的sdk_repo并不是必须的,在经过理解之后,我们已经知道需要修改哪些必须的内容,并可以直接在standalone_v6_5源码上进行修改,依然能够完成AMP模式验证。

(2)注意:如果需要使用standalone_v4_299,除了在新建BSP工程前导入sdk_repo外,还需要在BSP配置选项中:OS version——>4.2版本,默认是6.5(软件自带);但是使用4.2版本源码会出现很多报错的情况,因此需要用户谨慎使用。

(3)本人建议:直接使用6.5版本,并在此基础上进行相应修改。

有问题交流请联系,qq:1030843709 泊叶

4.附录

xilinx官网关于SDK的详细使用介绍:

https://china.xilinx.com/search/site-keyword-search.html#q=sdk&firstQueryCause=omniboxFromLink&firstQueryMeta={%22partialQueries%22:%22%22%20,%20%22suggestionRanking%22:3%20,%20%22suggestions%22:%22zynq%207000%20qspi%3Bug1157%3Bug1144%3Bsdk%3Bcallbackref%22%20,%20%22partialQuery%22:%22undefined%22%20,%20%22JSUIVersion%22:%222.4382.16%3B2.4382.16%22}

Zynq的AMP开发注意事项之sdk_repo相关推荐

  1. Zynq的AMP开发注意事项之禁用L2 cache

    前言 Zynq的AMP模式在开发过程中,cpu1应用程序的bsp工程的boot.s中,禁用了L2 cache.在这里,阐述一下原因: 博客主体参考自下文,并在此基础上进行适当修改 https://bl ...

  2. hls fifo_【正点原子FPGA连载】第一章HLS简介--领航者ZYNQ之HLS 开发指南

    1)摘自[正点原子]领航者ZYNQ之HLS 开发指南 2)平台购买地址:https://item.taobao.com/item.htm?&id=606160108761 3)全套实验源码+手 ...

  3. input自适应_【正点原子FPGA连载】第十一章基于OV5640的自适应二值化实验-领航者ZYNQ之HLS 开发指南...

    1)摘自[正点原子]领航者ZYNQ之HLS 开发指南 2)平台购买地址:https://item.taobao.com/item.htm?&id=606160108761 3)全套实验源码+手 ...

  4. PHP 接口开发注意事项

    PHP 接口开发注意事项 PHP 接口开发注意事项 预先定义接口流程和逻辑,确认需求 在开发前首先确定流程,复杂的接口可以绘制流程图,并确保流程与需求一致: 使用统一的变量定义 无论是SDK还是Ser ...

  5. 分布式系统开发注意点_分布式系统开发注意事项

    分布式系统开发注意点 开发分布式软件系统时,要考虑许多因素. 如果您甚至不知道第一句话中我在说什么,那么让我为您提供一些见解,示例以及有关分布式系统的实例. 总览 分布式系统是指多个物理硬件设备与单独 ...

  6. 分布式系统开发注意事项

    开发分布式软件系统时,要考虑许多因素. 如果您甚至不知道第一句话中我在说什么,那么让我为您提供一些见解,示例以及有关分布式系统的实例. 总览 分布式系统是指多个物理硬件设备与单独的离散用户交互并通过这 ...

  7. 嵌入式软件开发注意事项一

    嵌入式软件开发注意事项一 1.首先对测试板进行各方面硬件性能的测试:电源测试,时钟测试等等.要确保硬件最基本的几个性能是正常的,否则后面真的无法进行软件的开发,因为如果你没有确保硬件的正确性,那么后面 ...

  8. cups源码下载 linux_【正点原子FPGA连载】第九章Linux显示设备的使用-领航者ZYNQ之linux开发指南...

    1)实验平台:正点原子领航者ZYNQ开发板 2)平台购买地址:https://item.taobao.com/item.htm?&id=606160108761 3)全套实验源码+手册+视频下 ...

  9. WP7开发平台介绍及开发注意事项【WP7学习札记之二】

    Windows Phone是一个由微软制作并发行的触控操作模式行动操作系统,它的前身是Windows Mobile系统,但却与之完全不同. WP7系统架构: Windows Phone 7基于Wind ...

最新文章

  1. Hadoop集群的基本操作(三:HBase的基本操作)
  2. python 连接mysql数据库
  3. 2021年春季学期-信号与系统-第十五次作业参考答案-第七小题参考答案
  4. DDD:用 “四色原型” 进行 “聚合设计”
  5. ajax带来的主要问题有哪些,ajax面试题
  6. uni-app实现传值路径乱码的问题
  7. P1518 两只塔姆沃斯牛 The Tamworth Two(简单的搜索题)
  8. 前端学习(1811):前端调试之css装饰cursor练习
  9. 定时更换超级连接的代码
  10. javascript高级程序设计第二章知识点提炼
  11. PHP可以通过什么组件上传大文件
  12. 基于地理距离的省际空间权重矩阵
  13. 锻造互联网青铜时代 (转)
  14. 【雷丰阳-谷粒商城 】课程概述
  15. 使用appium进行app自动化测试时遇到AppActivity设置正确但报Connect Appium Server Fail.A new session could not be created
  16. SSM框架实战详细教程(十四)贯穿项目实战之三层架构
  17. 单调栈(C/C++)
  18. 使用变量时,单引号、双引号、反向单引号的区别
  19. PHP-邮件发送接口
  20. 飞秋下载2010正式版 飞秋下载

热门文章

  1. 分布式事务之最终一致的Mq实现
  2. Python-OpenCV 处理视频(一)(二): 输入输出 视频处理
  3. Python-OpenCV 处理图像(二)(三):滤镜和图像运算 图像像素点操作
  4. OpenCV系列(三):Mat详解
  5. Vim 实用技术,第 3 部分: 定制 Vim
  6. 20321关系数据库理论基础
  7. Nginx安装echo模块
  8. 同步文件,不需要密码
  9. Tomcat一些小事
  10. 信息安全系统设计基础第二次实验