复旦微ZYNQ 四核使用_zynq block unlock_寒听雪落的博客-程序员宅基地

技术标签: fpga开发  ZYNQ:FPGA_AXI_ARM  

一,procise步骤

二,IAR步骤:四个ARM CONTEX A7

1,新建hello word工程,并将代码,并将iar工程复制四份,修改四个工程的 cstartup.s 文件

2,修改初始化代码,fsbl 里边已经将 DDR 等硬件初始化好了,注释掉app 中的初始化
代码,避免重复是初始化。

3,修改 icf 文件,四个 app 程序的运行空间不能冲突,分别为如下:

SDK0:

/*-Memory Regions-*/
define symbol __ICFEDIT_region_RAM_start__ = 0x00100000;
define symbol __ICFEDIT_region_RAM_end__   = 0x1FFFFFF;
define symbol __AXI_DDR_START = 0x00100000;
define symbol __AXI_DDR_END = 0x3FFFFFFF;

SDK1:

define symbol __ICFEDIT_region_RAM_start__ = 0x2000000;
define symbol __ICFEDIT_region_RAM_end__   = 0x2FFFFFF;

SDK2:

/*-Memory Regions-*/
define symbol __ICFEDIT_region_RAM_start__ = 0x3000000;
define symbol __ICFEDIT_region_RAM_end__   = 0x3FFFFFF;

SDK3:

define symbol __ICFEDIT_region_RAM_start__ = 0x4000000;
define symbol __ICFEDIT_region_RAM_end__   = 0x4FFFFFF;

4,打包boot.bin文件,boot.bin 文件由fsbl+bit+app0+app1+app2+app3组成,注意修改destination CPU和cstartup.s文件一致。

 

5,测试时需要接上开发板的两个串口,由于测试时两个 cpu 共用一个uart,因此 helloworld
程序中将打印时间设置的不一样以区分确认不同核的代码确实跑起来了。

6,CPU0-CPU1都运行的串口代码

#include <stdio.h>
#include "platform.h"
#include "fmsh_common.h"
#include "ps_init.h"
#include "fmsh_print.h"
#include "fmsh_ps_parameters.h"
int main()
{
    init_platform();
    
   /* FMSH_WriteReg(FPS_SLCR_BASEADDR, 0x008, 0xDF0D767BU);   //unlock
    FMSH_WriteReg(FPS_SLCR_BASEADDR, 0x838, 0xf);
    //Open USER_LVL_SHFTR_EN_A and USER_LVL_SHFTR_EN_5
    FMSH_WriteReg(FPS_SLCR_BASEADDR, 0x004, 0xDF0D767BU);  //lock*/
    while(1)
    {
      fmsh_print("Hello World! cpux\n\r");
      delay_ms(100);
    }
}

三,多核间数据共享IAR代码解析

filetomem:用于将文件拷贝到指定的内存地址处。
amp:将裸机程序所在的内存地址写入指定 CPU 核的程序入口地址寄存器。
app_cpu2.bin:每隔 1 秒产生一次心跳,用于 softuart 监测;接收led 程序发来的信息,实现指定 led 灯的开关;实现串口中断,接收输入串口的信息。

#include <stdio.h>
#include "platform.h"
#include "fmsh_common.h"
#include "ps_init.h"
#include "fmsh_print.h"
#include "intrinsics.h"
#include "cache.h"
//#include "fmsh_ttc_public.h"  
#include "fmsh_gic.h"
#include "fmsh_gic_hw.h"
#include "spin_lock.h"
#include "ttc.h"

/* 测试一小部分数据,主要是针对一些共享flag变量的场景,测试时,需要CPU0和CPU1的宏定义同时改为1*/
#define  TEST_SEVERAL_VIRIABLES                 0
/* 1表示开启更多的调试信息;0表示关闭调试信息 */
#define  DEBUG_AMP_INFO                       0
#define  DEBUG_AMP(flag,...) \
do { \
  if(flag) \
    fmsh_print(__VA_ARGS__); \
}while(0)


/* share ddr is at the high ddr address 768MB for some variable usage
*/
#define   SHARED_DDR_ADDRESS    (0x30000000)

/* ahb sarm(128KB) used for shared flag with device memory*/
#define SHARED_OCM_MEMORY_BASE   (0xe1fe0000)
#define SHARED_GIC_SPIN_LOCK     (0xe1fe0040)

#define SHARED_TEST_SEMAPHORE    (0xe1fe0080)


/* Define a data memory space which is visible to both CPUs, the DDR is okay since a large amount of data could be written. */
#define SHARED_DDR_MEMORY_BASE   (0x04000000)
#define SHARED_DDR_MEMORY_SIZE_128KB    (0x20000)
#define SHARED_DDR_MEMORY_SIZE_1MB      (0x100000)

/* Declare a value stored in OCM space which is visible to both CPUs. */
#define SEMAPHORE_VALUE      (*(volatile unsigned long *)(SHARED_OCM_MEMORY_BASE))
#define GIC_SPIN_LOCK        ((arch_spinlock_t *)(SHARED_GIC_SPIN_LOCK))


#define TEST_SEMAPHORE_VALUE (*(volatile unsigned long *)(SHARED_TEST_SEMAPHORE))


/* Declare a memory space where both CPUs can store their data sets. */
#define DESTINATION_ARRAY    (SHARED_DDR_MEMORY_BASE)

/* Define a data set for CPU0 to operate on. */
static char cpu0_data_128KB[SHARED_DDR_MEMORY_SIZE_128KB];


ttc_user_dev_t ttc0_timer1=
{
    .device_id              = FPAR_TTCPS_0_DEVICE_ID,
	.irq_no			= TIMER0_1_INT_ID,
        .irq_priority           = 0xa8,
	.timer_no		= timer1,

	.ttc_cnt		= 0,
	
	.delay_cnt		= TTC0_0_FREQ*10, /* 10 Seconds */
	.IntcPtr		= &IntcInstance,
	/* shared spin lock */
	.gic_spin_lock	        = GIC_SPIN_LOCK,
	/* cpu0 */
	.map_cpu_no		= 0x1 << 0
};

/* ttc0的timer1初始化 */
int ttc0_timer1_use_interrupt(void)
{
  ttc_user_dev_t *ttc_dev_ptr = &ttc0_timer1;
  gic_common_init(ttc_dev_ptr);
  FTtcPs_ttc_timer_init(ttc_dev_ptr);
  /* 即使某个cpu提前退出锁,产生了中断,中断处理流程里比如读中断号寄存器,
   * 写ack寄存器之类的操作和设置对应中断的触发模式寄存器,优先级寄存器并不冲突 ,
   * 没有并发即可
   */
  FTtcPs_ttc_timer_enable(ttc_dev_ptr, FMSH_set);
  return 0;
}

/* large block data for share */
int data_copy_to_cpu1 (u8 *data, u32 size)
{
  int index;
  volatile char* data_destination = (volatile  char *) DESTINATION_ARRAY;
  /* Copy the data set to the shared memory destination. */
  for (index = 0; index < size; index++)
  {
      data_destination[index] = data[index];
  }
  return index;
}

int semaphore_cpu0_init()
{
  /* Only CPU0 should be responsible for initializing the semaphore. */
  SEMAPHORE_VALUE = 0;
  return 0;
}

int semaphore_cpu0_signal()
{
  SEMAPHORE_VALUE = 1;
  return 0;
}

int semaphore_cpu0_wait()
{
  while (SEMAPHORE_VALUE == 1);
  return 0;
}

// several memory location shared flag variable
void core0_test(volatile unsigned int *flag)
{
  /* cortex-A7的scu会窥探store buffer 
   * armv7 TRM里说multi-core copy架构上not amtomic
   * 实际CPU设计实现时muti-core copy是atomic的,armv8已经是
   * 在架构上muti-core copy atomic的了,而read-modify-write不是原子的
   * 这样同一地址MESI的话应该可以保证多核的一致性,仅考虑单个变量就不需要内存屏障了
   * 这个测试例子比较特殊,反汇编看得话,写-读,以及读-写前后都有寄存器依赖,读到的值和要写的值都放到R1寄存器了,
   * 所以执行odder应该也是program order
   * 请参考配套的文档。
   */
  *flag = 0x11111111;

  //smp_rmb();

  /* 共cpu0和cpu1共享flag变量
   */
  while(*flag != 0x22222222);
  /* 这里应该是控制依赖的 */
  *flag = 0x33333333;
  //smp_rmb();
  while(*flag != 0x44444444);
  /* 和后面的指令隔离 */
 // smp_mb();
}

static void init_data_cpu0_pattern(u8 * data, u32 size)
{
  u32 i;
  if(!data || !size) 
    return;
  /* 初始化数据偏移0x5 */
  for(i = 0; i< size; i++)
    data[i] = (u8)(i + 0x5);
}

static void dump_cpu0_data(u8 * data, u32 size)
{
  u32 i;
  for(i = 0; i< size; i++)
  {
    fmsh_print("%x ", data[i]);
    if((i+1)%16 == 0)
      fmsh_print("\n\r");
  }
  fmsh_print("\n\r");
}

static int check_data_cpu1_pattern(u8 * data, u32 size)
{
  u32 i;
  int failed = 0;
  
  if(!data || !size) 
    return -1;
  for(i = 0; i< size; i++)
    if( data[i] != ( (u8)(i+0xa) ) )
    {
      failed++;
      fmsh_print("%d: %x-%x\n\r",i, data[i], (u8)(i+0x5));
    }
  
  return failed;
}

/* cpu0和cpu1的这个同名函数是一对测试例程,同时改成main可以进行测试
 */
int global_variable_observation_main()
{
    /* fsbl has called ps_init */
    init_platform();
 
    invalidate_icache_all();
    icache_enable();
    
    /* 使能d-cache时,会设置cpu core的smp bit,默认的DDR页表已经满足shareable,WBWA 
     * 使能过程中,会无效L1,L2 d-cache。
     */
    dcache_enable();
   
    
    fmsh_print("CPU 0 set the shared global variable...\n\r");
    
    
    SEMAPHORE_VALUE = 0;
    
    while(1)      
    {

      while(FUartPs_isRxFifoEmpty(&g_UART));
      /* 串口终端里按按键c执行全局变量修改,也可以自动发送c字符 */
      if(FUartPs_read(&g_UART)=='c')
      {
        SEMAPHORE_VALUE += 1;
        smp_mb();
        TEST_SEMAPHORE_VALUE = 1;      
      }
    }
    
}


/* 本demo是基于scu保证多个cpu core共享内存的一致性,即遵循MESI cache一致性原则
 * 没有考虑dma的场景
 */
int main()
{

    u32 round = 0;
    
    
    /* fsbl has called ps_init */
    init_platform();

 
    invalidate_icache_all();
    icache_enable();
    
    /* 使能d-cache时,会设置cpu core的smp bit,默认的DDR页表已经满足shareable,WBWA 
     * 使能过程中,会无效L1,L2 d-cache。
     */
    dcache_enable();

    
    /* xapp1079的同步变量说明:
     * 可以直接修改mmu_table.S对应ahb sram的属性,psoc没有提供API,可以移植过来 
     * Disable caching on shared OCM data by setting the appropriate TLB
     * attributes for the shared data space in OCM.
     * 可参考ARMV7 TRM文档,《汇总文档\裸跑相关补充文档\arm官方文档\arm_arm_ARMv7-A_ARMv7-R_DDI0406_2007.pdf》
     * S=b1  共享
     * TEX=b100  
     * AP=b11              manager不做权限检查
     * Domain=b1111
     * C=b0
     * B=b0
     * 页表属性:L1和L2 d-cache设定为non-cacheable,shareable,normal memory
     */
//    Xil_SetTlbAttributes(0xE1Fe0000,0x14de2);           // S=b1 TEX=b100 AP=b11, Domain=b1111, C=b0, B=b0

/* 保留的示例代码,本demo利用fsbl自动启动两个app,请参考
 * 《汇总文档\裸跑相关补充文档\amp\amp_bare_metal_ddr-v1.0.pdf》
 */
#if 0
    FMSH_WriteReg(0xE0026008, 0x0, 0xDF0D767B);//解锁 SLCR 寄存器
    FMSH_WriteReg(0xE0026440, 0x0, 0x02004100);//写入 Helloword 运行的起始地址到该寄存器中。
    FMSH_WriteReg(0xE0026004, 0x0, 0xDF0D767B);//解锁 SLCR 寄存器
    asm("sev"); //通过指令唤醒 CPU1。
#endif    
    
    fmsh_print("CPU 0 will print after for a little long delay!waiting...\n\r");
    
    init_data_cpu0_pattern((u8 *)cpu0_data_128KB, SHARED_DDR_MEMORY_SIZE_128KB);
    
    /* 这里的同步变量已经改成normal cache-able的属性了 
     * non-cacheable的normal memory,甚至device memory和normal memory在一起,
     * 内存序也不保证的。
     */
    semaphore_cpu0_init();

    
    /* 即使某个cpu提前退出锁,产生了中断,中断处理流程里比如读中断号寄存器,
       写ack寄存器之类的操作和设置触发,优先级寄存器不冲突 ,没有并发
     */
    ttc0_timer1_use_interrupt();
   
    while(1)
    {      
/* 针对一些地址的单个共享flag变量的场景 */
#if TEST_SEVERAL_VIRIABLES
      u32 i;
      
      for(i = 0; i < 0x100000; i +=32)
    	core0_test((volatile unsigned int *)(SHARED_DDR_ADDRESS + i));

      core0_test((volatile unsigned int *)SHARED_DDR_ADDRESS+0x10000);
      core0_test((volatile unsigned int *)SHARED_DDR_ADDRESS+0x20000);
      core0_test((volatile unsigned int *)SHARED_DDR_ADDRESS+0x30000);
      
      if(round && ((round % 200) == 0) )
         fmsh_print("CPU 0 finished %u round\n\r", round);
      
      round++;

/* 连续通信数据区缓冲区测试 */
#else  
      int fail = 1;
      
      /* 开始测试一段连续数据 */
      if(round && ((round % 200) == 0) )
        fmsh_print("CPU0: has run %u round start!\n\r", round);
      
      /* cpu0写128KB cpu0 pattern数据到共享数据区 */
      data_copy_to_cpu1((u8 *)cpu0_data_128KB, SHARED_DDR_MEMORY_SIZE_128KB);
      
      DEBUG_AMP(DEBUG_AMP_INFO, "CPU0 write 128KB data!\n\r");
      
      //dump_cpu0_data((u8 *)DESTINATION_ARRAY, SHARED_DDR_MEMORY_SIZE_128KB);
      
      /* 在ahb sram里的信号量改成cache-able时,可能normal memory时cpu乱序执行的问题,
       * 特别是两片内存地址没有关系的情况,所以应该需要把内存屏障开了比较安全
       * 实际上cache一致性的问题在关掉L2 cache后,一致性问题是在共享DDR级别,速度很慢
       * 就是状态变到S,或者M变到E,scu需要刷L1 cache到DDR,而不是L2 cache
       * 而使能了L2 cache的话,一致性问题是L2 cache,就完全脱离了DDR了
       * 另外根据并行编程里的场景,全局变量赋值,其他cpu可能看不到完整的值,
       * 另外即使normal memory和device memory的内存不重叠时,也有可能会乱序。
       */
      smp_wmb();
       
      /* 通知CPU1校验 */
      semaphore_cpu0_signal();
      /* 等待CPU1校验结束,并更新1MB数据过来 */
      semaphore_cpu0_wait();
      
      DEBUG_AMP(DEBUG_AMP_INFO, "CPU0 will check 1MB data!\n\r");
      
      smp_rmb();
      
      /* 获取了CPU1的通知,cpu0开始检查cpu1写的1MB共享数据 */
      fail = check_data_cpu1_pattern((u8 *)DESTINATION_ARRAY, SHARED_DDR_MEMORY_SIZE_1MB);
      if(fail)
      {
        fmsh_print("CPU0 check cpu1 written data failed!\n\r");
        break;
      }
      else
        DEBUG_AMP(DEBUG_AMP_INFO, "CPU0 check 1MB ok!\n\r");
      
      if(round && ((round % 200) == 0) )
        fmsh_print("CPU0: has run %u round end!\n\r", round);
      
      round++;
      
#endif

    }
}

 

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/wangjie36/article/details/119110701

智能推荐

训练yolov5中遇到的问题_yolov5卡在扫描训练集_努力读研的小小明的博客-程序员宅基地

环境问题是大家遇到最多的问题,用cmd运行pip list查看所用环境是否正确在这里建议大家使用:python3.7torch1.6.0+gpu(如果没有gpu就直接torch1.6.0)torchvision0.7.0+gpu(同上)cuda10.2问题出的最多的就是numpy,这个不要单独装,他是和torch相关联的,如果版本对应不上可能会报错,我这里使用的是numpy1.19.5**一旦发现报错首先看环境对不对!!!**环境不对改代码也是白搭这是我的环境..._yolov5卡在扫描训练集

c语言中输出最大公约数和最小公倍数,c语言求最大公约数和最小公倍数(转)..._潘球球的博客-程序员宅基地

最大公约数与最小公倍数的求解是很多初学C的人所面临的一道问题。当然这道问题并不难解答,也有很多人已经写过相关的博客,我在此书写此篇博客,一是为了让自己能够夯实基础,另外就是希望能够帮到和我一样的初学者。当然,在写这篇博客之前,我已经做过相关资料的调查,可能读者会发现此篇博客会与其他人的博客有所重复,但是,我保证绝未抄袭。好了,进入正题!问题:请从键盘上输入两个数值 x,y,请用C语言求出这两个数值..._输出最大公约数和最小公倍数

WEB APP、HYBRID APP与NATIVE APP的设计差异_daisy_Hawen的博客-程序员宅基地

一、Web App、Hybrid App、Native App 纵向对比首先,我们来看看什么是 Web App、Hybrid App、 Native App。Web APPWeb App 指采用Html5语言写出的App,不需要下载安装。类似于现在所说的轻应用。生存在浏览器中的应用,基本上可以说是触屏版的网页应用。优点(1)开发成本低, (2)更新快, (3)更新无需通知用户,不需要手动升级

Freertos-互斥量的基本使用_创建2个发送任务:每个任务发送10的字符。 使用互斥量:可以看到任务1、任务2打印的_小阳先生的宝库的博客-程序员宅基地

刚创建的互斥量可以被成功"take"“take"互斥量成功的任务,被称为"holder”,只能由它"give"互斥量;别的任务"give"不成功。在 ISR 中不能使用互斥量。本程序创建 2 个发送任务:故意发送大量的字符。 可以做 2 个实验:使用互斥量:可以看到任务 1、任务 2 打印的字符串没有混杂在一起。不使用互斥量:任务 1、任务 2 打印的字符串混杂在一起。main函数/* 互斥量句柄 */SemaphoreHandle_t xMutex;int main( void )._创建2个发送任务:每个任务发送10的字符。 使用互斥量:可以看到任务1、任务2打印的

4.9 文件描述符FileDescriptor_兴趣使然的程序猿的博客-程序员宅基地

4.9 FileDescriptor Instances of the file descriptor class serve as an opaque handle to the underlying machine-specific structure representing an open file, an open socket, or another source or sink of bytes.The

7-9 删数问题 (10 分)(思路加详解)_删数问题 有一个长度为n(n <= 240)的正整数,从中取出k(k < n)个数,使剩余的数保持_天天向上的菜鸡杰!!的博客-程序员宅基地

一:题目有一个长度为n(n <= 240)的正整数,从中取出k(k < n)个数,使剩余的数保持原来的次序不变,求这个正整数经过删数之后最小是多少。输入格式:n和k输出格式:一个数字,表示这个正整数经过删数之后的最小值。输入样例:178543 4结尾无空行输出样例:13二:思路思路:1.首先贪心的策略是每次最优,那么结果就是最优的2.那么这道题我们可以每次删除序列中 升序的结尾,重复上述操作k次,这样的话我们就能可以这个结果的最优解了解释:因为在一串数中,我们_删数问题 有一个长度为n(n <= 240)的正整数,从中取出k(k < n)个数,使剩余的数保持

随便推点

VC++定制状态栏的方法_rsjrj的博客-程序员宅基地

在String Table中加入一个新ID:ID_INDICATOR_COIN,Caption为“硬币数量”。2、 在MainFrm.cpp中的静态数组indicator中将上面的ID加入:static UINT indicators[] ={ ID_SEPARATOR, //// status line indicator ID

Linux 防火墙及防火墙规则_linux 防火墙 服务规则_LKmnbZ的博客-程序员宅基地

防火墙的分类包过滤型防火墙 工作在OSI参考模型的网络层 它根据数据包头源地址、目的地址、端口号和协议类型 等标志确定是否允许数据包通过代理型防火墙主要工作在OSI的应用层 代理服务在确认客户端连接请求有效后接管代理 代为向服 务器发出连接请求代理型防火墙可以允许或拒绝特定的应用程序或服务,还可以实施数据流监控、过滤、 记录和报告功能代理服务器通常有高速缓存功能代..._linux 防火墙 服务规则

requests和re库爬取淘宝商品信息_酷不酷炫的博客-程序员宅基地

这次还是静态网页但是是比较复杂的淘宝,我在直接请求时发现我得到的结果并不是网页response的text的结果,以为是不能直接请求,结果在看大佬的博客时发现他爬取的有结果,然后我试着把他的代码复制下来输出了他的response的text信息发现和我一样,所以之后正则时都是在开发者工具中直接观察的,包括商品名称价格和付款人数。这个可能太麻烦而且不好提取信息,今天安装Chromedriver出现了问题...

python27安装pycrypto报 unable to find vcvarsall.bat错误解决办法_空城雀的博客-程序员宅基地

在安装RF第三方库SSHLibrary时,需要依赖pycrypto,因为我没有使用pip,是手动下载安装的,所以需要手动安装pycrypto,我是安装的pycrypto2.2版本。安装过程中,报如下错误:error: Unable to find vcvarsall.bat问题很直观,没有找到vcvarsall.bat,需要安装VS C++ 。直接上解决办法:1.根据下面链接中提供的下载...

cx_Oracle.DatabaseError: DPI-1047: Cannot locate a 64-bit Oracle Client library: “The specified modu_cx_0racle.databaseerror:dpi-1047: cannot locate a6_郎家岭伯爵的博客-程序员宅基地

报错cx_Oracle.DatabaseError: DPI-1047: Cannot locate a 64-bit Oracle Client library: "The specified module could not be found". See https://oracle.github.io/odpi/doc/installation.html#windows for help解决方法1、下载instant-client 64位2、解压instant-client,将其下所有dll_cx_0racle.databaseerror:dpi-1047: cannot locate a64- bit oracle

JAVA调用DLL/SO动态库干货攻略(上)(jna篇)_java调用dll .so .dylib_sky_鸡蛋的博客-程序员宅基地

JAVA调用DLL/SO动态库干货攻略(上)(jna篇)首先,动态链接库windows下是.dll文件,linux下是.so文件。.dll文件要被调用的话需要确保其有导出函数,.so文件函数只有隐藏和不隐藏,所以默认相当于全部导出。如果遇到只提供一个导出函数用来生成实例的话,需要自己做一层封装再将实例下的函数导出供jna调用。第一步,需要jna的jar包,以下为maven依赖:net.ja..._java调用dll .so .dylib

推荐文章

热门文章

相关标签