嵌入式系统内核镜像相关(十五)

发布于:2025-07-22 ⋅ 阅读:(19) ⋅ 点赞:(0)


前言

本篇接着补充移植的例子。


十四、网卡驱动(移植成功)

14.1 移植的程序

这一篇没啥难度,直接照搬alinx程序即可。

驱动模块如下:

/** ===================================================== **
 *Author : ALINX Electronic Technology (Shanghai) Co., Ltd.
 *Website: http://www.alinx.com
 *Address: Room 202, building 18, 
           No.518 xinbrick Road, 
           Songjiang District, Shanghai
 *Created: 2020-3-2 
 *Version: 1.0
 ** ===================================================== **/

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/fcntl.h>
#include <linux/ioport.h>
#include <linux/in.h>
#include <linux/skbuff.h>
#include <linux/string.h>
#include <linux/init.h>
#include <linux/bitops.h>
#include <linux/ip.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <asm/io.h>
#include <asm/irq.h>

/* 定义一个net_device结构体变量 */
static struct net_device *ax_net_dev;

/* 模拟接收, 构造一个虚拟的sk_buff上报, 并更新统计信息 */
static void ax_net_rx(struct sk_buff *skb, struct net_device *dev)
{
	unsigned char *type;
	struct iphdr *ih;
	__be32 *saddr, *daddr, tmp;
	unsigned char	tmp_dev_addr[ETH_ALEN];
	struct ethhdr *ethhdr;
	
	struct sk_buff *rx_skb;

    /* 交换接受和发送方的mac地址 */
	ethhdr = (struct ethhdr *)skb->data;
	memcpy(tmp_dev_addr, ethhdr->h_dest, ETH_ALEN);
	memcpy(ethhdr->h_dest, ethhdr->h_source, ETH_ALEN);
	memcpy(ethhdr->h_source, tmp_dev_addr, ETH_ALEN);
  
    /* 交换接受和发送方的ip地址 */
	ih = (struct iphdr *)(skb->data + sizeof(struct ethhdr));
	saddr = &ih->saddr;
	daddr = &ih->daddr;

	tmp = *saddr;
	*saddr = *daddr;
	*daddr = tmp;
    
	type = skb->data + sizeof(struct ethhdr) + sizeof(struct iphdr);
	/* 修改类型, 0表示reply */
    *type = 0;
	
	ih->check = 0;
	ih->check = ip_fast_csum((unsigned char *)ih,ih->ihl);
	
    /* 构造sk_buff */
	rx_skb = dev_alloc_skb(skb->len + 2);
	skb_reserve(rx_skb, 2);
	memcpy(skb_put(rx_skb, skb->len), skb->data, skb->len);

	rx_skb->dev = dev;
	rx_skb->protocol = eth_type_trans(rx_skb, dev);
	rx_skb->ip_summed = CHECKSUM_UNNECESSARY;
	dev->stats.rx_packets++;
	dev->stats.rx_bytes += skb->len;

    /* 提交sk_buff */
	netif_rx(rx_skb);
}

static netdev_tx_t ax_net_tx(struct sk_buff *skb, struct net_device *dev)
{
	static int cnt = 0;
    
    /* 停止上层数据下传队列 */
	netif_stop_queue(dev);
    /* 模拟接收, 以达到一个完成的发送接收过程 */
	ax_net_rx(skb, dev);
    /* 释放skb */
	dev_kfree_skb (skb);
    /* 发送完成, 恢复上层数据下传队列 */
	netif_wake_queue(dev);
    /* 更新统计信息 */
	dev->stats.tx_packets++;
	dev->stats.tx_bytes += skb->len;
	
	return NETDEV_TX_OK;
}

/* 网卡设备操作函数集 */
static const struct net_device_ops ax_netdev_ops = 
{
	.ndo_start_xmit = ax_net_tx,
};

/* 驱动入口函数 */
static int __init ax_net_init(void)
{
    /* 分配net_device结构体 */
	ax_net_dev = alloc_netdev(0, "ax_net%d", NET_NAME_UNKNOWN, ether_setup);
    /* 设置操作函数集 */
	ax_net_dev->netdev_ops = &ax_netdev_ops;

    /* 设置MAC地址 */
    ax_net_dev->dev_addr[0] = 0x0A;
    ax_net_dev->dev_addr[1] = 0x0B;
    ax_net_dev->dev_addr[2] = 0x0C;
    ax_net_dev->dev_addr[3] = 0x0D;
    ax_net_dev->dev_addr[4] = 0x0E;
    ax_net_dev->dev_addr[5] = 0x0F;
    /* 设置ping功能 */
	ax_net_dev->flags     |= IFF_NOARP;
	ax_net_dev->features  |= NETIF_F_CSUM_MASK;	
    /* 注册网卡驱动 */
	register_netdev(ax_net_dev);
	
	return 0;
}

/* 驱动出口函数 */
static void __exit ax_net_exit(void)
{
	unregister_netdev(ax_net_dev);
	free_netdev(ax_net_dev);
}

module_init(ax_net_init);
module_exit(ax_net_exit);

/* 驱动描述信息 */  
MODULE_AUTHOR("Alinx"); 
MODULE_ALIAS("net card test");  
MODULE_DESCRIPTION("NET CARD driver");  
MODULE_VERSION("v1.0");  
MODULE_LICENSE("GPL"); 

参照以下在主机端完成驱动编译:

dention@ubuntu:~/petalinux_proj/test_peta/proj_peta$ source /opt/pkg/petalinux/settings.sh 
PetaLinux environment set to '/opt/pkg/petalinux'
WARNING: /bin/sh is not bash! 
bash is PetaLinux recommended shell. Please set your default shell to bash.
INFO: Checking free disk space
INFO: Checking installed tools
INFO: Checking installed development libraries
INFO: Checking network and other services
WARNING: No tftp server found - please refer to "PetaLinux SDK Installation Guide" for its impact and solution
dention@ubuntu:~/petalinux_proj/test_peta/proj_peta$ source /tools/Xilinx/Vivado/2019.1/s
scripts/        settings64.csh  settings64.sh   src/            strategies/     
dention@ubuntu:~/petalinux_proj/test_peta/proj_peta$ source /tools/Xilinx/Vivado/2019.1/settings64.sh 
dention@ubuntu:~/petalinux_proj/test_peta/proj_peta$ ls
build  components  config.project  images  project-spec
dention@ubuntu:~/petalinux_proj/test_peta/proj_peta$ petalinux-create -t modules --name ax-netcard-drv
INFO: Create modules: ax-netcard-drv
INFO: New modules successfully created in /home/dention/petalinux_proj/test_peta/proj_peta/project-spec/meta-user/recipes-modules/ax-netcard-drv
dention@ubuntu:~/petalinux_proj/test_peta/proj_peta$ petalinux-config -c rootfs
[INFO] sourcing bitbake
[INFO] generating plnxtool conf
[INFO] generating meta-plnx-generated layer
[INFO] generating user layers
[INFO] generating machine configuration
[INFO] configuring: rootfs
[INFO] generating kconfig for Rootfs
[INFO] menuconfig rootfs


*** End of the configuration.
*** Execute 'make' to start the build or try 'make help'.

[INFO] generating petalinux-user-image.bb
[INFO] successfully configured rootfs
dention@ubuntu:~/petalinux_proj/test_peta/proj_peta$ petalinux-build 
[INFO] building project
[INFO] sourcing bitbake
[INFO] generating user layers
INFO: bitbake petalinux-user-image
Loading cache: 100% |############################################################################################################| Time: 0:00:03
Loaded 3813 entries from dependency cache.
Parsing recipes: 100% |##########################################################################################################| Time: 0:00:09
Parsing of 2779 .bb files complete (2778 cached, 1 parsed). 3814 targets, 163 skipped, 0 masked, 0 errors.
NOTE: Resolving any missing task queue dependencies
Initialising tasks: 100% |#######################################################################################################| Time: 0:00:06
Checking sstate mirror object availability: 100% |###############################################################################| Time: 0:00:30
Sstate summary: Wanted 120 Found 12 Missed 216 Current 767 (10% match, 87% complete)
NOTE: Executing SetScene Tasks
NOTE: Executing RunQueue Tasks
NOTE: Tasks Summary: Attempted 3199 tasks of which 3153 didn't need to be rerun and all succeeded.
INFO: Copying Images from deploy to images
NOTE: Failed to copy built images to tftp dir:  /tftpboot
[INFO] successfully built project
dention@ubuntu:~/petalinux_proj/test_peta/proj_peta$ find ./ -name "ax-netcard-drv.ko"
./build/tmp/sysroots-components/plnx_zynq7/ax-netcard-drv/lib/modules/4.19.0-xilinx-v2019.1/extra/ax-netcard-drv.ko

随后移植到开发板上!

14.2 移植的结果

移植的结果如下:

root@proj_peta:~# ifconfig
eth0      Link encap:Ethernet  HWaddr 00:0A:35:00:1E:53
          inet6 addr: fe80::20a:35ff:fe00:1e53/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:17 errors:0 dropped:0 overruns:0 frame:0
          TX packets:21 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:1408 (1.3 KiB)  TX bytes:4642 (4.5 KiB)
          Interrupt:29 Base address:0xb000

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

root@proj_peta:~# ifconfig eth0 192.168.137.2 up
root@proj_peta:~# ifconfig
eth0      Link encap:Ethernet  HWaddr 00:0A:35:00:1E:53
          inet addr:192.168.137.2  Bcast:192.168.137.255  Mask:255.255.255.0
          inet6 addr: fe80::20a:35ff:fe00:1e53/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:17 errors:0 dropped:0 overruns:0 frame:0
          TX packets:28 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:1408 (1.3 KiB)  TX bytes:6792 (6.6 KiB)
          Interrupt:29 Base address:0xb000

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

root@proj_peta:~# ls
ax-netcard-drv.ko
root@proj_peta:~# insmod ./ax-netcard-drv.ko
ax_netcard_drv: loading out-of-tree module taints kernel.
ax_net0: mixed HW and IP checksum settings.
root@proj_peta:~# ls /sys/class/net/
ax_net0  can0     eth0     lo       sit0
root@proj_peta:~# ifconfig
eth0      Link encap:Ethernet  HWaddr 00:0A:35:00:1E:53
          inet addr:192.168.137.2  Bcast:192.168.137.255  Mask:255.255.255.0
          inet6 addr: fe80::20a:35ff:fe00:1e53/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:166 errors:0 dropped:0 overruns:0 frame:0
          TX packets:291 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:15954 (15.5 KiB)  TX bytes:43070 (42.0 KiB)
          Interrupt:29 Base address:0xb000

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

root@proj_peta:~# ls /sys/class/net/
ax_net0  can0     eth0     lo       sit0
root@proj_peta:~# ifconfig ax_net0 3.3.3.3
root@proj_peta:~# ping 3.3.3.4
PING 3.3.3.4 (3.3.3.4): 56 data bytes
64 bytes from 3.3.3.4: seq=0 ttl=64 time=0.138 ms
64 bytes from 3.3.3.4: seq=1 ttl=64 time=0.098 ms
64 bytes from 3.3.3.4: seq=2 ttl=64 time=0.079 ms
64 bytes from 3.3.3.4: seq=3 ttl=64 time=0.077 ms
64 bytes from 3.3.3.4: seq=4 ttl=64 time=0.082 ms
64 bytes from 3.3.3.4: seq=5 ttl=64 time=0.075 ms
64 bytes from 3.3.3.4: seq=6 ttl=64 time=0.073 ms
64 bytes from 3.3.3.4: seq=7 ttl=64 time=0.072 ms
64 bytes from 3.3.3.4: seq=8 ttl=64 time=0.070 ms
^C
--- 3.3.3.4 ping statistics ---
9 packets transmitted, 9 packets received, 0% packet loss
round-trip min/avg/max = 0.070/0.084/0.138 ms
root@proj_peta:~# ifconfig
ax_net0   Link encap:Ethernet  HWaddr 0A:0B:0C:0D:0E:0F
          inet addr:3.3.3.3  Bcast:3.255.255.255  Mask:255.0.0.0
          inet6 addr: fe80::80b:cff:fe0d:e0f/64 Scope:Link
          UP BROADCAST RUNNING NOARP MULTICAST  MTU:1500  Metric:1
          RX packets:23 errors:0 dropped:0 overruns:0 frame:0
          TX packets:23 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:3336 (3.2 KiB)  TX bytes:3336 (3.2 KiB)

eth0      Link encap:Ethernet  HWaddr 00:0A:35:00:1E:53
          inet addr:192.168.137.2  Bcast:192.168.137.255  Mask:255.255.255.0
          inet6 addr: fe80::20a:35ff:fe00:1e53/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:166 errors:0 dropped:0 overruns:0 frame:0
          TX packets:303 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:15954 (15.5 KiB)  TX bytes:46660 (45.5 KiB)
          Interrupt:29 Base address:0xb000

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

root@proj_peta:~#

十五、AMP通信(裸机成功)

15.1 硬件开发

PS的配置如下,主要关心UART是否是接到ARM侧的引脚!
在这里插入图片描述

15.2 裸机测试

建立2个项目,分别是amp_selfamp2_self
在这里插入图片描述
随后amp_self中的cpu0.c如下:

#include "xparameters.h"
#include "xscugic.h"
#include "xil_printf.h"
#include "xil_exception.h"
#include "xil_mmu.h"
#include "stdio.h"

//宏定义
#define INTC_DEVICE_ID	     XPAR_SCUGIC_SINGLE_DEVICE_ID //中断ID
#define SHARE_BASE           0xffff0000                   //共享OCM首地址
#define CPU1_START_ADDR      0xfffffff0                   //CPU1开始地址
#define CPU1_START_MEM       0x10000000                   //CPU1程序开始地址

#define SOFT_INTR_ID_TO_CPU0 0   //软件中断号 0 ,范围:0~15
#define SOFT_INTR_ID_TO_CPU1 1   //软件中断号 1 ,范围:0~15
#define CPU1_ID              2


#define sev()                __asm__("sev")

//函数声明
void start_cpu1();
void cpu0_intr_init(XScuGic *intc_ptr);
void soft_intr_handler(void *CallbackRef);

//全局变量
XScuGic Intc;                    //中断控制器驱动程序实例
int inter_flag = 0;
int test_data;

//CPU0 main函数
int main()
{

	Xil_SetTlbAttributes(SHARE_BASE,0x14de2);    //禁用OCM的Cache属性

	//启动CPU1
	start_cpu1();
	//CPU0中断初始化
	cpu0_intr_init(&Intc);
	while(1){
		if(inter_flag == 0){
			xil_printf("This is CPU0,Please input the numbers\r\n");
			scanf("%d",&test_data);
			xil_printf("You input number is %d\r\n",test_data);
			//向共享的地址中写入输入的数据
			Xil_Out8(SHARE_BASE,test_data);
			//给CPU1触发中断
			XScuGic_SoftwareIntr(&Intc,SOFT_INTR_ID_TO_CPU1,CPU1_ID);
			inter_flag = 1;
		}
	}
	return 0 ;
}

//启动CPU1,用于固化程序
void start_cpu1()
{
	Xil_Out32(CPU1_START_ADDR, CPU1_START_MEM);
	dmb();
	sev();
}

//CPU0中断初始化
void cpu0_intr_init(XScuGic *intc_ptr)
{
	//初始化中断控制器
	XScuGic_Config *intc_cfg_ptr;
	intc_cfg_ptr = XScuGic_LookupConfig(INTC_DEVICE_ID);
    XScuGic_CfgInitialize(intc_ptr, intc_cfg_ptr,
    		intc_cfg_ptr->CpuBaseAddress);
    //设置并打开中断异常处理功能
    Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
    		(Xil_ExceptionHandler)XScuGic_InterruptHandler, intc_ptr);
    Xil_ExceptionEnable();

    XScuGic_Connect(intc_ptr, SOFT_INTR_ID_TO_CPU0,
          (Xil_ExceptionHandler)soft_intr_handler, (void *)intc_ptr);

    XScuGic_Enable(intc_ptr, SOFT_INTR_ID_TO_CPU0); //CPU0软件中断
}

//软件中断函数
void soft_intr_handler(void *CallbackRef)
{
	xil_printf("This is A9  CPU0,Soft Interrupt from A9 CPU1\r\n");
	xil_printf("\r\n");
	inter_flag = 0;
}

lscript.ld如下:

/*******************************************************************/
/*                                                                 */
/* This file is automatically generated by linker script generator.*/
/*                                                                 */
/* Version: 2019.1                                                 */
/*                                                                 */
/* Copyright (c) 2010-2016 Xilinx, Inc.  All rights reserved.      */
/*                                                                 */
/* Description : Cortex-A9 Linker Script                           */
/*                                                                 */
/*******************************************************************/

_STACK_SIZE = DEFINED(_STACK_SIZE) ? _STACK_SIZE : 0x2000;
_HEAP_SIZE = DEFINED(_HEAP_SIZE) ? _HEAP_SIZE : 0x2000;

_ABORT_STACK_SIZE = DEFINED(_ABORT_STACK_SIZE) ? _ABORT_STACK_SIZE : 1024;
_SUPERVISOR_STACK_SIZE = DEFINED(_SUPERVISOR_STACK_SIZE) ? _SUPERVISOR_STACK_SIZE : 2048;
_IRQ_STACK_SIZE = DEFINED(_IRQ_STACK_SIZE) ? _IRQ_STACK_SIZE : 1024;
_FIQ_STACK_SIZE = DEFINED(_FIQ_STACK_SIZE) ? _FIQ_STACK_SIZE : 1024;
_UNDEF_STACK_SIZE = DEFINED(_UNDEF_STACK_SIZE) ? _UNDEF_STACK_SIZE : 1024;

/* Define Memories in the system */

MEMORY
{
   ps7_ddr_0 : ORIGIN = 0x100000, LENGTH = 0x1FF00000
   ps7_qspi_linear_0 : ORIGIN = 0xFC000000, LENGTH = 0x1000000
   ps7_ram_0 : ORIGIN = 0x0, LENGTH = 0x30000
   ps7_ram_1 : ORIGIN = 0xFFFF0000, LENGTH = 0xFE00
}

/* Specify the default entry point to the program */

ENTRY(_vector_table)

/* Define the sections, and where they are mapped in memory */

SECTIONS
{
.text : {
   KEEP (*(.vectors))
   *(.boot)
   *(.text)
   *(.text.*)
   *(.gnu.linkonce.t.*)
   *(.plt)
   *(.gnu_warning)
   *(.gcc_execpt_table)
   *(.glue_7)
   *(.glue_7t)
   *(.vfp11_veneer)
   *(.ARM.extab)
   *(.gnu.linkonce.armextab.*)
} > ps7_ddr_0

.init : {
   KEEP (*(.init))
} > ps7_ddr_0

.fini : {
   KEEP (*(.fini))
} > ps7_ddr_0

.rodata : {
   __rodata_start = .;
   *(.rodata)
   *(.rodata.*)
   *(.gnu.linkonce.r.*)
   __rodata_end = .;
} > ps7_ddr_0

.rodata1 : {
   __rodata1_start = .;
   *(.rodata1)
   *(.rodata1.*)
   __rodata1_end = .;
} > ps7_ddr_0

.sdata2 : {
   __sdata2_start = .;
   *(.sdata2)
   *(.sdata2.*)
   *(.gnu.linkonce.s2.*)
   __sdata2_end = .;
} > ps7_ddr_0

.sbss2 : {
   __sbss2_start = .;
   *(.sbss2)
   *(.sbss2.*)
   *(.gnu.linkonce.sb2.*)
   __sbss2_end = .;
} > ps7_ddr_0

.data : {
   __data_start = .;
   *(.data)
   *(.data.*)
   *(.gnu.linkonce.d.*)
   *(.jcr)
   *(.got)
   *(.got.plt)
   __data_end = .;
} > ps7_ddr_0

.data1 : {
   __data1_start = .;
   *(.data1)
   *(.data1.*)
   __data1_end = .;
} > ps7_ddr_0

.got : {
   *(.got)
} > ps7_ddr_0

.ctors : {
   __CTOR_LIST__ = .;
   ___CTORS_LIST___ = .;
   KEEP (*crtbegin.o(.ctors))
   KEEP (*(EXCLUDE_FILE(*crtend.o) .ctors))
   KEEP (*(SORT(.ctors.*)))
   KEEP (*(.ctors))
   __CTOR_END__ = .;
   ___CTORS_END___ = .;
} > ps7_ddr_0

.dtors : {
   __DTOR_LIST__ = .;
   ___DTORS_LIST___ = .;
   KEEP (*crtbegin.o(.dtors))
   KEEP (*(EXCLUDE_FILE(*crtend.o) .dtors))
   KEEP (*(SORT(.dtors.*)))
   KEEP (*(.dtors))
   __DTOR_END__ = .;
   ___DTORS_END___ = .;
} > ps7_ddr_0

.fixup : {
   __fixup_start = .;
   *(.fixup)
   __fixup_end = .;
} > ps7_ddr_0

.eh_frame : {
   *(.eh_frame)
} > ps7_ddr_0

.eh_framehdr : {
   __eh_framehdr_start = .;
   *(.eh_framehdr)
   __eh_framehdr_end = .;
} > ps7_ddr_0

.gcc_except_table : {
   *(.gcc_except_table)
} > ps7_ddr_0

.mmu_tbl (ALIGN(16384)) : {
   __mmu_tbl_start = .;
   *(.mmu_tbl)
   __mmu_tbl_end = .;
} > ps7_ddr_0

.ARM.exidx : {
   __exidx_start = .;
   *(.ARM.exidx*)
   *(.gnu.linkonce.armexidix.*.*)
   __exidx_end = .;
} > ps7_ddr_0

.preinit_array : {
   __preinit_array_start = .;
   KEEP (*(SORT(.preinit_array.*)))
   KEEP (*(.preinit_array))
   __preinit_array_end = .;
} > ps7_ddr_0

.init_array : {
   __init_array_start = .;
   KEEP (*(SORT(.init_array.*)))
   KEEP (*(.init_array))
   __init_array_end = .;
} > ps7_ddr_0

.fini_array : {
   __fini_array_start = .;
   KEEP (*(SORT(.fini_array.*)))
   KEEP (*(.fini_array))
   __fini_array_end = .;
} > ps7_ddr_0

.ARM.attributes : {
   __ARM.attributes_start = .;
   *(.ARM.attributes)
   __ARM.attributes_end = .;
} > ps7_ddr_0

.sdata : {
   __sdata_start = .;
   *(.sdata)
   *(.sdata.*)
   *(.gnu.linkonce.s.*)
   __sdata_end = .;
} > ps7_ddr_0

.sbss (NOLOAD) : {
   __sbss_start = .;
   *(.sbss)
   *(.sbss.*)
   *(.gnu.linkonce.sb.*)
   __sbss_end = .;
} > ps7_ddr_0

.tdata : {
   __tdata_start = .;
   *(.tdata)
   *(.tdata.*)
   *(.gnu.linkonce.td.*)
   __tdata_end = .;
} > ps7_ddr_0

.tbss : {
   __tbss_start = .;
   *(.tbss)
   *(.tbss.*)
   *(.gnu.linkonce.tb.*)
   __tbss_end = .;
} > ps7_ddr_0

.bss (NOLOAD) : {
   __bss_start = .;
   *(.bss)
   *(.bss.*)
   *(.gnu.linkonce.b.*)
   *(COMMON)
   __bss_end = .;
} > ps7_ddr_0

_SDA_BASE_ = __sdata_start + ((__sbss_end - __sdata_start) / 2 );

_SDA2_BASE_ = __sdata2_start + ((__sbss2_end - __sdata2_start) / 2 );

/* Generate Stack and Heap definitions */

.heap (NOLOAD) : {
   . = ALIGN(16);
   _heap = .;
   HeapBase = .;
   _heap_start = .;
   . += _HEAP_SIZE;
   _heap_end = .;
   HeapLimit = .;
} > ps7_ddr_0

.stack (NOLOAD) : {
   . = ALIGN(16);
   _stack_end = .;
   . += _STACK_SIZE;
   . = ALIGN(16);
   _stack = .;
   __stack = _stack;
   . = ALIGN(16);
   _irq_stack_end = .;
   . += _IRQ_STACK_SIZE;
   . = ALIGN(16);
   __irq_stack = .;
   _supervisor_stack_end = .;
   . += _SUPERVISOR_STACK_SIZE;
   . = ALIGN(16);
   __supervisor_stack = .;
   _abort_stack_end = .;
   . += _ABORT_STACK_SIZE;
   . = ALIGN(16);
   __abort_stack = .;
   _fiq_stack_end = .;
   . += _FIQ_STACK_SIZE;
   . = ALIGN(16);
   __fiq_stack = .;
   _undef_stack_end = .;
   . += _UNDEF_STACK_SIZE;
   . = ALIGN(16);
   __undef_stack = .;
} > ps7_ddr_0

_end = .;
}

amp2_self中的cpu1.c如下:

#include "xparameters.h"
#include "xscugic.h"
#include "xil_printf.h"
#include "xil_exception.h"
#include "xil_mmu.h"
#include "stdio.h"

//宏定义
#define INTC_DEVICE_ID	     XPAR_SCUGIC_SINGLE_DEVICE_ID //中断ID
#define SHARE_BASE  	     0xffff0000                   //共享OCM首地址
#define SOFT_INTR_ID_TO_CPU0 0                            //软件中断号 0 ,范围:0~15
#define SOFT_INTR_ID_TO_CPU1 1                            //软件中断号 1 ,范围:0~15
#define CPU0_ID              1                            //CPU1 ID,0bxxxxxxx1指向CPU0


//函数声明
void cpu1_intr_init(XScuGic *intc_ptr);
void soft_intr_handler(void *CallbackRef);

//全局变量
XScuGic Intc;               //中断控制器驱动程序实例
int soft_intr_flag = 0;
int test_data;

//CPU1 main函数
int main()
{

	Xil_SetTlbAttributes(SHARE_BASE,0x14de2);    //禁用OCM的Cache属性

	//CPU1中断初始化
	cpu1_intr_init(&Intc);

	while(1){
		if(soft_intr_flag){
			test_data = Xil_In8(SHARE_BASE);     //从共享OCM中读出数据
			xil_printf("CUP1 Received data is %d\r\n",test_data) ;
			//给给CPU0触发中断
			XScuGic_SoftwareIntr(&Intc,SOFT_INTR_ID_TO_CPU0,CPU0_ID);
			soft_intr_flag = 0;
		}
	}
	return 0 ;
}

//CPU1中断初始化
void cpu1_intr_init(XScuGic *intc_ptr)
{
	//初始化中断控制器
	XScuGic_Config *intc_cfg_ptr;
	intc_cfg_ptr = XScuGic_LookupConfig(INTC_DEVICE_ID);
    XScuGic_CfgInitialize(intc_ptr, intc_cfg_ptr,
    		intc_cfg_ptr->CpuBaseAddress);
    //设置并打开中断异常处理功能
    Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
    		(Xil_ExceptionHandler)XScuGic_InterruptHandler, intc_ptr);
    Xil_ExceptionEnable();

    XScuGic_Connect(intc_ptr, SOFT_INTR_ID_TO_CPU1,
          (Xil_ExceptionHandler)soft_intr_handler, (void *)intc_ptr);

    XScuGic_Enable(intc_ptr, SOFT_INTR_ID_TO_CPU1); //CPU1软件中断
}

//软件中断函数
void soft_intr_handler(void *CallbackRef)
{
	xil_printf("This is A9  CUP1,Soft Interrupt from  A9 CPU0\r\n") ;
	soft_intr_flag = 1;
}

lscript.ld如下:

/*******************************************************************/
/*                                                                 */
/* This file is automatically generated by linker script generator.*/
/*                                                                 */
/* Version: 2018.3                                                 */
/*                                                                 */
/* Copyright (c) 2010-2016 Xilinx, Inc.  All rights reserved.      */
/*                                                                 */
/* Description : Cortex-A9 Linker Script                           */
/*                                                                 */
/*******************************************************************/

_STACK_SIZE = DEFINED(_STACK_SIZE) ? _STACK_SIZE : 0x2000;
_HEAP_SIZE = DEFINED(_HEAP_SIZE) ? _HEAP_SIZE : 0x2000;

_ABORT_STACK_SIZE = DEFINED(_ABORT_STACK_SIZE) ? _ABORT_STACK_SIZE : 1024;
_SUPERVISOR_STACK_SIZE = DEFINED(_SUPERVISOR_STACK_SIZE) ? _SUPERVISOR_STACK_SIZE : 2048;
_IRQ_STACK_SIZE = DEFINED(_IRQ_STACK_SIZE) ? _IRQ_STACK_SIZE : 1024;
_FIQ_STACK_SIZE = DEFINED(_FIQ_STACK_SIZE) ? _FIQ_STACK_SIZE : 1024;
_UNDEF_STACK_SIZE = DEFINED(_UNDEF_STACK_SIZE) ? _UNDEF_STACK_SIZE : 1024;

/* Define Memories in the system */

MEMORY
{
   ps7_ddr_0 : ORIGIN = 0x10000000 , LENGTH = 0x1FF00000
   ps7_qspi_linear_0 : ORIGIN = 0xFC000000, LENGTH = 0x1000000
   ps7_ram_0 : ORIGIN = 0x0, LENGTH = 0x30000
   ps7_ram_1 : ORIGIN = 0xFFFF0000, LENGTH = 0xFE00
}

/* Specify the default entry point to the program */

ENTRY(_vector_table)

/* Define the sections, and where they are mapped in memory */

SECTIONS
{
.text : {
   KEEP (*(.vectors))
   *(.boot)
   *(.text)
   *(.text.*)
   *(.gnu.linkonce.t.*)
   *(.plt)
   *(.gnu_warning)
   *(.gcc_execpt_table)
   *(.glue_7)
   *(.glue_7t)
   *(.vfp11_veneer)
   *(.ARM.extab)
   *(.gnu.linkonce.armextab.*)
} > ps7_ddr_0

.init : {
   KEEP (*(.init))
} > ps7_ddr_0

.fini : {
   KEEP (*(.fini))
} > ps7_ddr_0

.rodata : {
   __rodata_start = .;
   *(.rodata)
   *(.rodata.*)
   *(.gnu.linkonce.r.*)
   __rodata_end = .;
} > ps7_ddr_0

.rodata1 : {
   __rodata1_start = .;
   *(.rodata1)
   *(.rodata1.*)
   __rodata1_end = .;
} > ps7_ddr_0

.sdata2 : {
   __sdata2_start = .;
   *(.sdata2)
   *(.sdata2.*)
   *(.gnu.linkonce.s2.*)
   __sdata2_end = .;
} > ps7_ddr_0

.sbss2 : {
   __sbss2_start = .;
   *(.sbss2)
   *(.sbss2.*)
   *(.gnu.linkonce.sb2.*)
   __sbss2_end = .;
} > ps7_ddr_0

.data : {
   __data_start = .;
   *(.data)
   *(.data.*)
   *(.gnu.linkonce.d.*)
   *(.jcr)
   *(.got)
   *(.got.plt)
   __data_end = .;
} > ps7_ddr_0

.data1 : {
   __data1_start = .;
   *(.data1)
   *(.data1.*)
   __data1_end = .;
} > ps7_ddr_0

.got : {
   *(.got)
} > ps7_ddr_0

.ctors : {
   __CTOR_LIST__ = .;
   ___CTORS_LIST___ = .;
   KEEP (*crtbegin.o(.ctors))
   KEEP (*(EXCLUDE_FILE(*crtend.o) .ctors))
   KEEP (*(SORT(.ctors.*)))
   KEEP (*(.ctors))
   __CTOR_END__ = .;
   ___CTORS_END___ = .;
} > ps7_ddr_0

.dtors : {
   __DTOR_LIST__ = .;
   ___DTORS_LIST___ = .;
   KEEP (*crtbegin.o(.dtors))
   KEEP (*(EXCLUDE_FILE(*crtend.o) .dtors))
   KEEP (*(SORT(.dtors.*)))
   KEEP (*(.dtors))
   __DTOR_END__ = .;
   ___DTORS_END___ = .;
} > ps7_ddr_0

.fixup : {
   __fixup_start = .;
   *(.fixup)
   __fixup_end = .;
} > ps7_ddr_0

.eh_frame : {
   *(.eh_frame)
} > ps7_ddr_0

.eh_framehdr : {
   __eh_framehdr_start = .;
   *(.eh_framehdr)
   __eh_framehdr_end = .;
} > ps7_ddr_0

.gcc_except_table : {
   *(.gcc_except_table)
} > ps7_ddr_0

.mmu_tbl (ALIGN(16384)) : {
   __mmu_tbl_start = .;
   *(.mmu_tbl)
   __mmu_tbl_end = .;
} > ps7_ddr_0

.ARM.exidx : {
   __exidx_start = .;
   *(.ARM.exidx*)
   *(.gnu.linkonce.armexidix.*.*)
   __exidx_end = .;
} > ps7_ddr_0

.preinit_array : {
   __preinit_array_start = .;
   KEEP (*(SORT(.preinit_array.*)))
   KEEP (*(.preinit_array))
   __preinit_array_end = .;
} > ps7_ddr_0

.init_array : {
   __init_array_start = .;
   KEEP (*(SORT(.init_array.*)))
   KEEP (*(.init_array))
   __init_array_end = .;
} > ps7_ddr_0

.fini_array : {
   __fini_array_start = .;
   KEEP (*(SORT(.fini_array.*)))
   KEEP (*(.fini_array))
   __fini_array_end = .;
} > ps7_ddr_0

.ARM.attributes : {
   __ARM.attributes_start = .;
   *(.ARM.attributes)
   __ARM.attributes_end = .;
} > ps7_ddr_0

.sdata : {
   __sdata_start = .;
   *(.sdata)
   *(.sdata.*)
   *(.gnu.linkonce.s.*)
   __sdata_end = .;
} > ps7_ddr_0

.sbss (NOLOAD) : {
   __sbss_start = .;
   *(.sbss)
   *(.sbss.*)
   *(.gnu.linkonce.sb.*)
   __sbss_end = .;
} > ps7_ddr_0

.tdata : {
   __tdata_start = .;
   *(.tdata)
   *(.tdata.*)
   *(.gnu.linkonce.td.*)
   __tdata_end = .;
} > ps7_ddr_0

.tbss : {
   __tbss_start = .;
   *(.tbss)
   *(.tbss.*)
   *(.gnu.linkonce.tb.*)
   __tbss_end = .;
} > ps7_ddr_0

.bss (NOLOAD) : {
   __bss_start = .;
   *(.bss)
   *(.bss.*)
   *(.gnu.linkonce.b.*)
   *(COMMON)
   __bss_end = .;
} > ps7_ddr_0

_SDA_BASE_ = __sdata_start + ((__sbss_end - __sdata_start) / 2 );

_SDA2_BASE_ = __sdata2_start + ((__sbss2_end - __sdata2_start) / 2 );

/* Generate Stack and Heap definitions */

.heap (NOLOAD) : {
   . = ALIGN(16);
   _heap = .;
   HeapBase = .;
   _heap_start = .;
   . += _HEAP_SIZE;
   _heap_end = .;
   HeapLimit = .;
} > ps7_ddr_0

.stack (NOLOAD) : {
   . = ALIGN(16);
   _stack_end = .;
   . += _STACK_SIZE;
   . = ALIGN(16);
   _stack = .;
   __stack = _stack;
   . = ALIGN(16);
   _irq_stack_end = .;
   . += _IRQ_STACK_SIZE;
   . = ALIGN(16);
   __irq_stack = .;
   _supervisor_stack_end = .;
   . += _SUPERVISOR_STACK_SIZE;
   . = ALIGN(16);
   __supervisor_stack = .;
   _abort_stack_end = .;
   . += _ABORT_STACK_SIZE;
   . = ALIGN(16);
   __abort_stack = .;
   _fiq_stack_end = .;
   . += _FIQ_STACK_SIZE;
   . = ALIGN(16);
   __fiq_stack = .;
   _undef_stack_end = .;
   . += _UNDEF_STACK_SIZE;
   . = ALIGN(16);
   __undef_stack = .;
} > ps7_ddr_0

_end = .;
}

注意俩lscript.ld的差异只在于基地址!

随后需要的配置如下:

在这里插入图片描述

修改成如下:

-mcpu=cortex-a9 -mfpu=vfpv3 -mfloat-abi=hard -nostartfiles -g -Wall -Wextra -DUSE_AMP=1

运行前如下配置:

在这里插入图片描述
在这里插入图片描述

裸机测试效果如下:
在这里插入图片描述
结果符合预期!

15.3 驱动开发的例子

看到野火STM32可以使用异构多核通信的驱动开发教程,想着试试,但后来发现arm不支持,看下grep的结果:

dention@ubuntu:~/petalinux_proj/test_peta/proj_peta$ grep -rl "ipcc" ./
./images/linux/System.map.linux
./images/linux/vmlinux
./build/tmp/work-shared/plnx-zynq7/kernel-source/Documentation/devicetree/bindings/mailbox/stm32-ipcc.txt
./build/tmp/work-shared/plnx-zynq7/kernel-source/.git/index
./build/tmp/work-shared/plnx-zynq7/kernel-source/drivers/gpu/drm/amd/include/asic_reg/gca/gfx_8_0_sh_mask.h
./build/tmp/work-shared/plnx-zynq7/kernel-source/drivers/gpu/drm/amd/include/asic_reg/gca/gfx_7_2_sh_mask.h
./build/tmp/work-shared/plnx-zynq7/kernel-source/drivers/gpu/drm/amd/include/asic_reg/gca/gfx_6_0_sh_mask.h
./build/tmp/work-shared/plnx-zynq7/kernel-source/drivers/gpu/drm/amd/include/asic_reg/gca/gfx_8_1_sh_mask.h
./build/tmp/work-shared/plnx-zynq7/kernel-source/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.h
./build/tmp/work-shared/plnx-zynq7/kernel-source/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.h
./build/tmp/work-shared/plnx-zynq7/kernel-source/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.h
./build/tmp/work-shared/plnx-zynq7/kernel-source/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.h
./build/tmp/work-shared/plnx-zynq7/kernel-source/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.h
./build/tmp/work-shared/plnx-zynq7/kernel-source/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.h
./build/tmp/work-shared/plnx-zynq7/kernel-source/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.h
./build/tmp/work-shared/plnx-zynq7/kernel-source/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.h
./build/tmp/work-shared/plnx-zynq7/kernel-source/drivers/mailbox/Makefile
./build/tmp/work-shared/plnx-zynq7/kernel-source/drivers/mailbox/stm32-ipcc.c
./build/tmp/work-shared/plnx-zynq7/kernel-source/drivers/clk/clk-stm32mp1.c
./build/tmp/work-shared/plnx-zynq7/kernel-source/ipc/msg.c
./build/tmp/work-shared/plnx-zynq7/kernel-source/ipc/util.h
./build/tmp/work-shared/plnx-zynq7/kernel-source/ipc/shm.c
./build/tmp/work-shared/plnx-zynq7/kernel-source/ipc/util.c
./build/tmp/work-shared/plnx-zynq7/kernel-source/ipc/sem.c
./build/tmp/work-shared/plnx-zynq7/kernel-build-artifacts/System.map-4.19.0-xilinx-v2019.1
./build/tmp/sysroots-components/cortexa9t2hf-neon/perl/usr/lib/perl/5.24.4/CORE/embed.h
./build/tmp/sysroots-components/cortexa9t2hf-neon/perl/usr/lib/perl/5.24.4/CORE/proto.h

还是挺无奈的!不过算是一次记录,万一将来需要!

用了将近三周的时间,总算把alinx野火的知识讲解部分整理完了!

接下来得回头把中断处理一下了!


总结

补充了网卡驱动异构多核裸机开发的例子。


网站公告

今日签到

点亮在社区的每一天
去签到