ZYNQ MPSOC 软件无线电开发[软件部分(2)] - 在Petalinux工程中添加驱动程序与自启动脚本

ZYNQ MPSOC 软件无线电开发[软件部分(2)] -在Petalinux工程中添加驱动与自启动脚本

ZYNQ MPSOC 软件无线电开发[软件部分(1)] - 导出Vivado硬件设计并构建基本的Petalinux工程

接上一章,现在已经完成了基本工程的创建,硬件上是Alinx AXU3EGB开发板,PL端连接了AD9238和AD9767。

从该部分往下,大部分内容都可以在Xilinx的官方Petalinux Userguide里找到,而且恰好有官方简中
PetaLinux 工具文档参考指南 (ug1144)

1. 添加自启动脚本

进入Petalinux工程目录,创建一个apps,命名autostart,–enable是启用该apps

petalinux-create -t apps --template install --name autostart --enable
INFO: Create apps: autostart
INFO: New apps successfully created in /home/xlnxdev-2020-1/peta_prj/adda_probtest/petalinux/project-spec/meta-user/recipes-apps/autostart
INFO: Enabling created component...
INFO: sourcing build environment
INFO: silentconfig rootfs
INFO: autostart has been enabled

上面的输出告诉了我们apps的路径,打开文件

~/peta_prj/adda_probtest/petalinux/project-spec/meta-user/recipes-apps/autostart/files/autostart

修改为

#!/bin/sh

echo "Simple applecations autostart"

USERHOOK_SD0=/media/sd-mmcblk0p1/autostart.sh
USERHOOK_SD1=/media/sd-mmcblk1p1/autostart.sh

if [ -f $USERHOOK_SD0 ]; then 
    sh $USERHOOK_SD0 & 
fi 

if [ -f $USERHOOK_SD1 ]; then 
    sh $USERHOOK_SD1 & 
fi

该脚本会被编译到Petalinux中,自动查找SD卡(sd-mmcblk1)或者板载emmc(sd-mmcblk0)第一分区的autostart.sh并执行。

现在打开

~/peta_prj/adda_probtest/petalinux/project-spec/meta-user/recipes-apps/autostart/autostart.bb

修改为

#
# This file is the autostart recipe.
#

SUMMARY = "Simple autostart application"
SECTION = "PETALINUX/apps"
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"

SRC_URI = "file://autostart \
	"

S = "${WORKDIR}"

inherit update-rc.d 
INITSCRIPT_NAME = "autostart" 
INITSCRIPT_PARAMS = "start 99 5 ."

do_install() {
   
	     install -d ${
   D}/${
   sysconfdir}/init.d
	     install -m 0755 ${
   S}/autostart ${
   D}/${
   sysconfdir}/init.d/autostart
}

RDEPENDS_${
   PN}_append += "bash"

功能是复制autostart到根文件系统 init.d,然后添加 0755 权限。 至于INITSCRIPT_PARAMS的内容可以参考其他博客,主要是控制启动顺序和权限。RDEPENDS_${PN}_append += "bash"是指该脚本依赖bash。

特别指出RDEPENDS_${PN}_append,如果你用的是新版的Petalinux,这部分需要修改成RDEPENDS:${PN}:append = "bash",新的yocto bitbake对override语法有改动。参考https://docs.yoctoproject.org/migration-guides/migration-3.4.html或者ug1144

2. 添加驱动程序

执行命令

petalinux-create -t modules -n ad9767 --enable

刚才的自启动脚本是apps,对于驱动程序一类使用modules。

INFO: Create modules: ad9767
INFO: New modules successfully created in /home/xlnxdev-2020-1/peta_prj/adda_probtest/petalinux/project-spec/meta-user/recipes-modules/ad9767
INFO: Enabling created component...
INFO: sourcing build environment
INFO: silentconfig rootfs
INFO: ad9767 has been enabled

打开生成的.c文件

~/peta_prj/adda_probtest/petalinux/project-spec/meta-user/recipes-modules/ad9767/files/ad9767.c

写入以下驱动程序源码

#include <asm/uaccess.h>
#include <linux/dma/xilinx_dma.h>
#include <linux/cdev.h>
#include <linux/dma-mapping.h>
#include <linux/dmaengine.h>
#include <linux/err.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/of_address.h>
#include <linux/platform_device.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/delay.h>

#define MODULE_NAME "axi_dac9767_dma"
#define AXI_ADC_MINOR_START 0
#define AXI_ADC_MINOR_COUNT 16
#define AXI_ADC_CALLBACK_TIMEOUTMSEC 200
#define SUCCESS 0
#define FAILURE -1
#define MAX_BUF_COUNT 8
/* IOCTL defines */
#define AXI_ADC_IOCTL_BASE 'W'
#define AXI_ADC_SET_SAMPLE_NUM _IO(AXI_ADC_IOCTL_BASE, 0)
#define AXI_ADC_SET_DMA_LEN_BYTES _IO(AXI_ADC_IOCTL_BASE, 1)
#define AXI_ADC_DMA_INIT _IO(AXI_ADC_IOCTL_BASE, 2)
#define AXI_ADC_DMA_START _IO(AXI_ADC_IOCTL_BASE, 3)
#define AXI_ADC_DMA_DEINIT _IO(AXI_ADC_IOCTL_BASE, 4)
#define AXI_ADC_DMA_CYCLIC_SEND _IO(AXI_ADC_IOCTL_BASE, 5)
#define AXI_ADC_DMA_CYCLIC_STOP _IO(AXI_ADC_IOCTL_BASE, 6)

struct axi_adc_dev
{
   
	struct mutex mutex;
	struct platform_device *pdev;
	/* ADC Hardware device constants */
	void *adc_virtaddr;
	/* DMA stuff */
	struct dma_chan *tx_chan;
	dma_cookie_t tx_cookie;
	struct completion tx_cmp;
	unsigned long tx_tmo;
	int bd_cnt;
	struct scatterlist *tx_sg;
	/*DMA address of buffer */
	dma_addr_t *dma_dsts;
	u8 **dsts;
	int adc_sample_num;
	int dma_len_bytes;
	size_t cyclic_len;
};

/*ADC channel name */
static const char adc_channels[][20] =
	{
   
		{
   "dac0"},
		{
   "dac1"},
		{
   "dac2"},
		{
   "dac3"},
		{
   "dac4"},
		{
   "dac5"},
		{
   "dac6"},
		{
   "dac7"},
		{
   "dac8"},
		{
   "dac9"},
		{
   "dac10"},
		{
   "dac11"},
		{
   "dac12"},
		{
   "dac13"},
		{
   "dac14"},
		{
   "dac15"},
};

static struct axi_adc_dev *axi_adc_dev[16];
static int dev_index = 0;
static dev_t devno;
static struct cdev adc_cdev;
static struct class *axi_adc_class;
static void dma_slave_tx_callback(void *completion)
{
   
	complete(completion);
}

/* File operations */
int axi_adc_dma_open(struct inode *inode, struct file *filp)
{
   
	unsigned int mn;
	mn = iminor(inode);
	/*Assign minor number for later reference */
	filp->private_data = (void *)mn;

	return SUCCESS;
}

int axi_adc_dma_release(struct inode *inode, struct file *filp)
{
   
	return SUCCESS;
}

ssize_t axi_adc_dma_write(struct file *filep, const char __user *buf,
						  size_t count, loff_t *f_pos)
{
   
	int minor = 0;
	/* Query minor number.
	 * @To be extended for multiple channel support
	 */
	minor = (int)filep->private_data;
	axi_adc_dev[minor]->cyclic_len = count;

	/* Validation for read size */
	if (count > axi_adc_dev[minor]->dma_len_bytes)
	{
   
		axi_adc_dev[minor]->cyclic_len = axi_adc_dev[minor]->dma_len_bytes;
	}

	copy_from_user(axi_adc_dev[minor]->dsts[0], buf, axi_adc_dev[minor]->cyclic_len);
	return count;
}

/* IOCTL calls provide interface to configure ,start and stop
   DMA engine */
static long axi_adc_dma_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
   
	enum dma_ctrl_flags flags;
	enum dma_status status;
	int ret = 0;
	int i;
	int minor = (int)file->private_data;
	struct dma_device *tx_dev 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值