前言
终于腾出手来整理最后升级的1553应用了,作为最底层最需要稳定和安全的保障,对于裸板开发的从0-1,操作系统下的改进几乎相当于1-50了,当然核心思想还是对寄存器的配置以及对内存空间的划分,只是更需要考虑到操作系统调度,操作系统的反应能力以及单一测试工程和最后整体应用中存在差异的情况:
印象里比较深刻的比如裸板的中断及反应能力远远大于操作系统,需要在上层应用中通过对寄存器进行不同于常规的特殊配置来规避过多的消息处理,也就是比如有个流程需要将数据分别存进5-12的子地址,正常来说每个子地址都会收到中断分别取读取收到的数据,但是数据过大时难免出现丢包操作系统处理不过来等情况,那么就可以修改寄存器屏蔽掉6-12的中断消息,在收到5的消息中断后休眠一段时间直接读取剩下全部子地址收到的消息,大大降低了处理的负荷;
还有高频率的消息包本可以轮询处理,但是面对庞大的工程业务,尤其在某个线程中在不断地while1拉片选信号的时候,中断自然变成了更好的选择(虽然处理效率确实没有轮询快,但是就可以通过第一种情况来进行规避了)
甚至还有不是很合常理的,基本的读写数据在面对实际应用中高频海量的消息时都会出现读写错误,可以由FPGA修改读写时序来解决,同样的,也可以通过上层应用来进行规避,毕竟再差的读写时序,大不了多读几次做判断筛选呗,总会有解决办法的:
结合第一二种情况,应用层的驱动肯定是满足不了要求了,需要直接在驱动层直接编写好模块,然后应用层在采取异步通知的机制,就可以合理恰当的解决:
字符设备驱动简介
字符设备是 Linux 驱动中最基本的一类设备驱动,字符设备就是一个一个字节,按照字节流进行读写操作的设备,读写数据是分先后顺序的。比如我们最常见的 LED、按键、 IIC、SPI, LCD 等等都是字符设备,这些设备的驱动就叫做字符设备驱动。在详细的学习字符设备驱动架构之前,我们先来简单的了解一下Linux 下的应用程序是如何调用驱动程序的, Linux 应用程序对驱动程序的调用如下图所示:
在 Linux 中一切皆为文件,驱动加载成功以后会在“ /dev”目录下生成一个相应的文件,应用程序通过对这个名为“ /dev/xxx” (xxx 是具体的驱动文件名字)的文件进行相应的操作即可实现对硬件的操作。比如现在有个叫做/dev/rt1553 的驱动文件,此文件是 rt1553 的驱动文件。应用程序使用 open 函数来打开文件/dev/rt1553,使用完成以后使用 close 函数关闭/dev/led 这个文件。 open 和 close 就是打开和关闭 led 驱动的函数,如果要点亮或关闭rt1553,那么就使用 write 函数来操作,也就是向此驱动写入数据,这个数据就是要关闭还是要打开 rt1553 的控制参数。如果要获取rt1553的状态,就用 read 函数从驱动中读取相应的状态。
应用程序运行在用户空间,而 Linux 驱动属于内核的一部分,因此驱动运行于内核空间。当我们在用户空间想要实现对内核的操作,比如使用 open 函数打开/dev/rt1553 这个驱动,因为用户空间不能直接对内核进行操作,因此必须使用一个叫做“系统调用”的方法来实现从用户空间陷入到内核空间,这样才能实现对底层驱动的操作。 open、 close、 write 和read 等这些函数是有 C 库提供的,在 Linux 系统中,系统调用作为 C 库的一部分。当我们调用 open 函数的时候流程如下图所示
其中关于 C 库以及如何通过系统调用陷入到内核空间这个我们不用去管,我们重点关注的是应用程序和具体的驱动,应用程序使用到的函数在具体驱动程序中都有与之对应的函数,比如应用程序中调用了 open 这个函数,那么在驱动程序中也得有一个名为 open 的函数。每一个系统调用,在驱动中都有与之对应的一个驱动函数,在 Linux 内核文件include/linux/fs.h 中有个叫做 file_operations 的结构体,此结构体就是 Linux 内核驱动操作函数集合,内容如下所示:
常用函数结构体
1692 struct file_operations { 1693 struct module *owner; 1694 loff_t (*llseek) (struct file *, loff_t, int); 1695 ssize_t (*read) (struct file *, char __user *, size_t, loff_t *); 1696 ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *); 1697 ssize_t (*read_iter) (struct kiocb *, struct iov_iter *); 1698 ssize_t (*write_iter) (struct kiocb *, struct iov_iter *); 1699 int (*iterate) (struct file *, struct dir_context *); 1700 int (*iterate_shared) (struct file *, struct dir_context *); 1701 unsigned int (*poll) (struct file *, struct poll_table_struct *); 1702 long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); 1703 long (*compat_ioctl) (struct file *, unsigned int, unsigned long); 1704 int (*mmap) (struct file *, struct vm_area_struct *); 1705 int (*open) (struct inode *, struct file *); 1706 int (*flush) (struct file *, fl_owner_t id); 1707 int (*release) (struct inode *, struct file *); 1708 int (*fsync) (struct file *, loff_t, loff_t, int datasync); 1709 int (*fasync) (int, struct file *, int); 1710 int (*lock) (struct file *, int, struct file_lock *); 1711 ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int); 1712 unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); 1713 int (*check_flags)(int); 1714 int (*flock) (struct file *, int, struct file_lock *); 1715 ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int); 1716 ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int); 1717 int (*setlease)(struct file *, long, struct file_lock **, void **); 1718 long (*fallocate)(struct file *file, int mode, loff_t offset, 1719 loff_t len); 1720 void (*show_fdinfo)(struct seq_file *m, struct file *f); 1721 #ifndef CONFIG_MMU 1722 unsigned (*mmap_capabilities)(struct file *); 1723 #endif 1724 ssize_t (*copy_file_range)(struct file *, loff_t, struct file *, 1725 loff_t, size_t, unsigned int); 1726 int (*clone_file_range)(struct file *, loff_t, struct file *, loff_t, 1727 u64); 1728 ssize_t (*dedupe_file_range)(struct file *, u64, u64, struct file *, 1729 u64); 1730 } __randomize_layout;
简单介绍一下 file_operation 结构体中比较重要的、常用的函数:
第 1693 行, owner 拥有该结构体的模块的指针,一般设置为 THIS_MODULE。
第 1694 行, llseek 函数用于修改文件当前的读写位置。
第 1695 行, read 函数用于读取设备文件。
第 1696 行, write 函数用于向设备文件写入(发送)数据。
第 1701 行, poll 是个轮询函数,用于查询设备是否可以进行非阻塞的读写。
第 1702 行, unlocked_ioctl 函数提供对于设备的控制功能,与应用程序中的 ioctl 函数对应。
第 1703 行, compat_ioctl 函数与 unlocked_ioctl 函数功能一样,区别在于在 64 位系统上, 32 位的应用程序调用将会使用此函数。在 32 位的系统上运行 32 位的应用程序调用的是unlocked_ioctl。
第 1704 行, mmap 函数用于将设备的内存映射到进程空间中(也就是用户空间),一般帧缓冲设备会使用此函数,比如 LCD 驱动的显存,将帧缓冲(LCD 显存)映射到用户空间中以后应用程序就可以直接操作显存了,这样就不用在用户空间和内核空间之间来回复制。
第 1705 行, open 函数用于打开设备文件。
第 1707 行, release 函数用于释放(关闭)设备文件,与应用程序中的 close 函数对应。
第 1709 行, fsync 函数用于刷新待处理的数据,用于将缓冲区中的数据刷新到磁盘中。
第 1605 行, fasync 函数与 fsync 函数的功能类似,只是 fasync 是异步刷新待处理的数据。在字符设备驱动开发中最常用的就是上面这些函数,关于其他的函数大家可以查阅相关文档。我们在字符设备驱动开发中最主要的工作就是实现上面这些函数,不一定全部都要实现,但是像 open、 release、 write、 read 等都是需要实现的,当然了,具体需要实现哪些函数还是要看具体的驱动要求
printk函数
通常来说printk 来输出信息,而不是 printf。 因为在 Linux 内核中没有 printf 这个函数。 printk 相当于 printf的孪生兄妹, printf 运行在用户态, printk 运行在内核态。在内核中想要向控制台输出或显示一些内容,必须使用 printk 这个函数。不同之处在于, printk 可以根据日志级别对消息进行分类,一共有 8 个消息级别,这 8 个消息级别定义在文件include/linux/kern_levels.h 里面,定义如下:
#define KERN_SOH "\001" /* ASCII Start Of Header */ #define KERN_SOH_ASCII '\001' #define KERN_EMERG KERN_SOH "0" /* system is unusable */ #define KERN_ALERT KERN_SOH "1" /* action must be taken immediately */ #define KERN_CRIT KERN_SOH "2" /* critical conditions */ #define KERN_ERR KERN_SOH "3" /* error conditions */ #define KERN_WARNING KERN_SOH "4" /* warning conditions */ #define KERN_NOTICE KERN_SOH "5" /* normal but significant condition */ #define KERN_INFO KERN_SOH "6" /* informational */ #define KERN_DEBUG KERN_SOH "7" /* debug-level messages */
一共定义了 8 个级别,其中 0 的优先级最高, 7 的优先级最低。如果要设置消息级别,参考如下示例:
printk(KERN_EMERG "gsmi: Log Shutdown Reason\n");
上述代码就是设置“ gsmi: Log Shutdown Reason\n”这行消息的级别为 KERN_EMERG。在具体的消息前面加上 KERN_EMERG 就可以将这条消息的级别设置为 KERN_EMERG。如果使用printk 的时候不显式的设置消息级别,那么 printk 将会采用默认级别
CONFIG_MESSAGE_LOGLEVEL_DEFAULT,
CONFIG_MESSAGE_LOGLEVEL_DEFAULT 默认为 4。
在 include/linux/printk.h 中有个宏 CONSOLE_LOGLEVEL_DEFAULT,定义如下:
/* * Default used to be hard-coded at 7, we're now allowing it to be set from * kernel config. */ #define CONSOLE_LOGLEVEL_DEFAULT CONFIG_CONSOLE_LOGLEVEL_DEFAULT
ONSOLE_LOGLEVEL_DEFAULT 控制着哪些级别的消息可以显示在控制台上, 从注释可知此宏默认为 7,意味着只有优先级高于 7 的消息才能显示在控制台上。这个就是 printk 和 printf 的最大区别,可以通过消息级别来决定哪些消息可以显示在控制台上。默认消息级别为 4, 4 的级别比 7 高,所示直接使用 printk 输出的信息是可以显示在控制台上的。
参数 filp 有个叫做 private_data 的成员变量, private_data 是个 void 指针,一般在驱动中将 private_data 指向设备结构体,设备结构体会存放设备的一些属性。
RT_read 函数,应用程序调用 read 函数从设备中读取数据的时候,此函数会执行。参数 buf 是用户空间的内存,读取到的数据存储在 buf 中,参数 cnt 是要读取的字节数,参数 offt 是相对于文件首地址的偏移。 kerneldata 里面保存着用户空间要读取的数据,先将 kerneldata 数组中的数据拷贝到读缓冲区 readbuf 中,通过函数 copy_to_user 函数将 readbuf 中的数据复制到参数 buf 中。因为内核空间不能直接操作用户空间的内存,因此需要借助 copy_to_user 函数来完成内核空间的数据到用户空间的复制。 copy_to_user 函数原型如下:
static inline long copy_to_user(void __user *to, const void *from, unsigned long n)
参数 to 表示目的,参数 from 表示源,参数 n 表示要复制的数据长度。如果复制成功,返回值为 0,如果复制失败则返回负数。
RT_write 函数,应用程序调用 write 函数向设备写数据的时候此函数就会执行。参数 buf 就是应用程序要写入设备的数据,也是用户空间的内存,参数 cnt是要写入的数据长度,参数 offt 是相对文件首地址的偏移。第 75 行通过函数copy_from_user 将 buf 中的数据复制到写缓冲区 writebuf 中,因为用户空间内存不能直接访问内核空间的内存,所以需要借助函数 copy_from_user 将用户空间的数据复制到writebuf 这个内核空间中。
RT_release 函数,应用程序调用 close 关闭设备文件的时候此函数会执行,一般会在此函数里面执行一些释放操作。如果在 open 函数中设置了 filp 的private_data 成员变量指向设备结构体,那么在 release 函数最终就要释放掉。
新建 RT 的设备文件操作结构体 RT_fops,初始化RT_fops。
驱动入口函数 RT_init,第 118 行调用函数 register_chrdev 来注册字符设备。
驱动出口函数 RT_exit,第 134 行调用函数 unregister_chrdev来注销字符设备。
通过 module_init 和 module_exit 这两个函数来指定驱动的入口和出口函数。
添加 LICENSE 和作者信息
open 函数
open 函数原型如下:
int open(const char *pathname, int flags)
open 函数参数含义如下:
pathname:要打开的设备或者文件名。
flags: 文件打开模式,以下三种模式必选其一:
O_RDONLY 只读模式
O_WRONLY 只写模式
O_RDWR 读写模式
因为我们要对 chrdevbase 这个设备进行读写操作,所以选择 O_RDWR。除了上述三种模式以外还有其他的可选模式,通过逻辑或来选择多种模式:
O_APPEND 每次写操作都写入文件的末尾
O_CREAT 如果指定文件不存在,则创建这个文件
O_EXCL 如果要创建的文件已存在,则返回 -1,并且修改 errno 的值
O_TRUNC 如果文件存在,并且以只写/读写方式打开,则清空文件全部内容
O_NOCTTY 如果路径名指向终端设备,不要把这个设备用作控制终端。
O_NONBLOCK 如果路径名指向 FIFO/块文件/字符文件,则把文件的打开和后继 I/O 设置为非阻塞
DSYNC 等待物理 I/O 结束后再 write。在不影响读取新写入的数据的前提下,不等待文件属性更新。
O_RSYNC read 等待所有写入同一区域的写操作完成后再进行。
O_SYNC 等待物理 I/O 结束后再 write,包括更新文件属性的 I/O
返回值:如果文件打开成功的话返回文件的文件描述符。
在 Linux中输入“ man 2 open”即可查看 open 函数的详细内容,如下图所示:
OPEN(2) Linux Programmer's Manual OPEN(2) NAME open, openat, creat - open and possibly create a file SYNOPSIS #include <sys/types.h>#include <sys/stat.h>#include <fcntl.h> int open(const char *pathname, int flags); int open(const char *pathname, int flags, mode t mode); int creat(const char *pathname, mode t mode); int openat(int dirfd, const char *pathname, int flags); int openat(int dirfd, const char *pathname, int flags, mode t mode): Feature Test Macro Requirements for glibc (see feature test macros(7)): openat(): Since glibc 2.10: Manual page open(2) line 1 (press h for help or q to quit) Hx--1024
read 函数
read 函数原型如下:
ssize_t read(int fd, void *buf, size_t count)
read 函数参数含义如下:
fd:要读取的文件描述符,读取文件之前要先用 open 函数打开文件, open 函数打开文件成功以后会得到文件描述符。
buf: 数据读取到此 buf 中。
count: 要读取的数据长度,也就是字节数。
返回值: 读取成功的话返回读取到的字节数;如果返回 0 表示读取到了文件末尾;如果返回负值,表示读取失败。在 Ubuntu 中输入“ man 2 read”命令即可查看 read 函数的详细内容
write 函数
write 函数原型如下:
ssize_t write(int fd, const void *buf, size_t count);
write 函数参数含义如下:
fd:要进行写操作的文件描述符,写文件之前要先用 open 函数打开文件, open 函数打开文件成功以后会得到文件描述符。
buf: 要写入的数据。
count: 要写入的数据长度,也就是字节数。
返回值: 写入成功的话返回写入的字节数;如果返回 0 表示没有写入任何数据;如果返回负值,表示写入失败。在 Ubuntu 中输入“ man 2 write”命令即可查看 write 函数的详细内容
close 函数
close 函数原型如下:
int close(int fd);
close 函数参数含义如下:
fd:要关闭的文件描述符。
返回值: 0 表示关闭成功,负值表示关闭失败。在 Ubuntu 中输入“ man 2 close”命令即可查看 close 函数的详细内容。
demo
参考前面章节字符型设备驱动模块的编写,直接给出LHB155304的模块编写源码吧,涉及到的重要函数在后面再次补充:
1553drv.c
/* 1553drv.c - The simplest kernel module. * Copyright (C) 2013 - 2016 Xilinx, Inc * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see <http://www.gnu.org/licenses/>. */ #include <linux/kernel.h> #include <linux/init.h> #include <linux/module.h> #include <linux/slab.h> #include <linux/io.h> #include <linux/interrupt.h> #include <linux/of_address.h> #include <linux/of_device.h> #include <linux/of_platform.h> #include <linux/miscdevice.h> #include <linux/types.h> #include <asm/uaccess.h> #include <linux/uaccess.h> #include <linux/fcntl.h> #include <linux/fs.h> #include "1553drv.h" /* Standard module information, edit as appropriate */ MODULE_LICENSE("GPL"); MODULE_AUTHOR ("Xin.han"); MODULE_DESCRIPTION ("1553drv - loadable module template generated by petalinux-create -t modules"); #define DRIVER_NAME "1553drv" /* Simple example of how to receive command line parameters to your module. Delete if you don't need them */ // unsigned myint = 0xdeadbeef; // char *mystr = "default"; // module_param(myint, int, S_IRUGO); // module_param(mystr, charp, S_IRUGO); struct RT_local { int irq; unsigned long mem_start; unsigned long mem_end; void __iomem *base_addr; }; //static struct fasync_struct *RT_async; struct fasync_struct *RT_async; static int RT_read(struct file *filp, char __user *buf, size_t cnt, loff_t *offt) { copy_to_user(buf,&(rt1553B_BUMSG),cnt); //printk("*************command is %d*****************\n",command); //printk("*************command is 0x%x*****************\n",command); return 0; } static int RT_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { switch (cmd) { case DISABLE_SUBADDR_IRQ: printk("************* disable sunaddr irq*****************\n"); fastenable(); break; case ENABLE_SUBADDR_IRQ: printk("************* enable subaddr irq*****************\n"); fastenable(); break; default: break; } return 0; } static int RT_fasync_ops (int fd, struct file *filp, int on) { return fasync_helper(fd, filp, on, &RT_async); } static int RT_release(struct inode *inode, struct file *filp) { return RT_fasync_ops(-1, filp, 0); } static struct file_operations RT_fops = { .read=RT_read, // .unlocked_ioctl=RT_ioctl, .fasync = RT_fasync_ops, .release = RT_release, }; static struct miscdevice RT_misc = { .minor = MISC_DYNAMIC_MINOR, .name = DRIVER_NAME, .fops = &RT_fops, }; static irqreturn_t RT_irq(int irq, void *lp) { rt1553B_handle(); //printk("1553drv interrupt\n"); return IRQ_HANDLED; } static int RT_probe(struct platform_device *pdev) { struct resource *r_irq; /* Interrupt resources */ struct resource *r_mem; /* IO mem resources */ struct device *dev = &pdev->dev; struct RT_local *lp = NULL; int rc = 0; dev_info(dev, "Device Tree Probing\n"); /* Get iospace for the device */ r_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!r_mem) { dev_err(dev, "invalid address\n"); return -ENODEV; } // dev_info(dev, "platform_get_resource success\n"); lp = (struct RT_local *) kmalloc(sizeof(struct RT_local), GFP_KERNEL); if (!lp) { dev_err(dev, "Cound not allocate 1553drv device\n"); return -ENOMEM; } // dev_info(dev,"kmalloc success\n"); dev_set_drvdata(dev, lp); lp->mem_start = r_mem->start; lp->mem_end = r_mem->end; if (!request_mem_region(lp->mem_start, lp->mem_end - lp->mem_start + 1, DRIVER_NAME)) { dev_err(dev, "Couldn't lock memory region at %p\n", (void *)lp->mem_start); rc = -EBUSY; goto error1; } // dev_info(dev,"request_mem_region success\n"); lp->base_addr = ioremap(lp->mem_start, lp->mem_end - lp->mem_start + 1); if (!lp->base_addr) { dev_err(dev, "1553drv: Could not allocate iomem\n"); rc = -EIO; goto error2; } // dev_info(dev,"ioremap success\n"); rt1553B_addrmap_base=lp->base_addr; rt1553init(); dev_info(dev,"1553init success\n"); misc_register(&RT_misc); // dev_info(dev,"RT_MISC success\n"); /* Get IRQ for the device */ r_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (!r_irq) { dev_info(dev, "no IRQ found\n"); dev_info(dev, "1553drv at 0x%08x mapped to 0x%08x\n", (unsigned int __force)lp->mem_start, (unsigned int __force)lp->base_addr); return 0; } // dev_info(dev," IRQ platform_get_resource success\n"); lp->irq = r_irq->start; //rc = request_irq(lp->irq, &RT_irq, 0, DRIVER_NAME, lp); rc = request_irq(lp->irq, &RT_irq, IRQF_TRIGGER_HIGH, DRIVER_NAME, lp); if (rc) { dev_err(dev, "testmodule: Could not allocate interrupt %d.\n", lp->irq); goto error3; } // dev_info(dev," IRQ platform_get_resource success\n"); dev_info(dev,"1553drv at 0x%08x mapped to 0x%08x, irq=%d\n", (unsigned int __force)lp->mem_start, (unsigned int __force)lp->base_addr, lp->irq); return 0; error3: free_irq(lp->irq, lp); error2: release_mem_region(lp->mem_start, lp->mem_end - lp->mem_start + 1); error1: kfree(lp); dev_set_drvdata(dev, NULL); return rc; } static int RT_remove(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct RT_local *lp = dev_get_drvdata(dev); free_irq(lp->irq, lp); iounmap(lp->base_addr); iounmap(rt1553B_BRAMmap_base); release_mem_region(lp->mem_start, lp->mem_end - lp->mem_start + 1); kfree(lp); dev_set_drvdata(dev, NULL); return 0; } // #ifdef CONFIG_OF // static struct of_device_id RT_of_match[] = { // { .compatible = "vendor,1553drv", }, // { /* end of list */ }, // }; // MODULE_DEVICE_TABLE(of, RT_of_match); // #else // # define RT_of_match // #endif static struct of_device_id RT_of_match[] = { { .compatible = "xlnx,test2-1.0"}, { /* end of list */ }, }; static struct platform_driver RT_driver = { .driver = { .name = DRIVER_NAME, .owner = THIS_MODULE, .of_match_table = RT_of_match, }, .probe = RT_probe, .remove = RT_remove, }; static int __init RT_init(void) { printk("<1>Hello module world.\n"); //printk("<1>Module parameters were (0x%08x) and \"%s\"\n", myint, // mystr); return platform_driver_register(&RT_driver); } static void __exit RT_exit(void) { platform_driver_unregister(&RT_driver); printk(KERN_ALERT "Goodbye module world.\n"); } module_init(RT_init); module_exit(RT_exit);
1553drv.h
#ifndef __1553DRV_H_ #define __1553DRV_H_ #include <linux/rtmutex.h> #include <linux/string.h> #define BUINTMASK 0x0 //reg0 #define BUCFG1 0x1 #define BUCFG2 0x2 #define BURST 0x3 #define BUCMDSTACKPOINT 0x3 #define BURTSUBADDRCTRL 0x4 #define BUTIMETAG 0x5 #define BUINTSTATUS 0x6 #define BUCFG3 0x7 #define BUCFG4 0x8 #define BUCFG5 0x9 #define BURTDATASTACKADDR 0xa #define BUBCFRAMETIME 0xb #define BUBCTIMEREMAIN 0xc #define BURTLASTCMD 0xd #define BURTSTATUSWORD 0xe #define BURTBITWORD 0xf #define BUTSTMODE0 0x10 #define BUTSTMODE1 0x11 #define BUTSTMODE2 0x12 #define BUTSTMODE3 0x13 #define BUTSTMODE4 0x14 #define BUTSTMODE5 0x15 #define BUTSTMODE6 0x16 #define BUTSTMODE7 0x17 //reg17 #define BUMSGDATANUM 0x20 //1553 message data size 32 #define BUCHANNELA 0x0 #define BUCHANNELB 0x1 #define BURX 0x0 #define BUTX 0x1 #define ERR1 0x0 #define ERR3 0x1 #define ERR 0x2 #define OK 0x0 #define INTMASK 0x0 #define BUM400 0x400 //data block 13 #define BUM800 0x800 //data block 37 #define BUZERO 0x0 //#define BUMSGDATANUM 0x40 //1553 message data size 32 word #define BUMSGDATANUM 0x20 #define BUSUBADDR0 0x0 #define BUSUBADDR31 0x20 //1553 subaddress 31 #define BUMSGBUFSIZE 0x40 //1553 message buffer size 64 #define BUEOMINT 0x1 // #define BUMSGBUFBGN 0x0 //1553 message buffer begin 0 #define BusCheckRespAddr 1 //subaddress #define SelfCheckAndUpdateCtrlRespAddr 3 #define StatusCheckAndUpdateDataGroupRespAddr 4 #define UpdateBlock1Addr 5 #define UpdateBlock2Addr 6 #define EndecryptRespAndUpdateBlock3Addr 7 #define UpdateBlock4Addr 8 #define DdChannelSetRespAndUpdateBlock5Addr 9 #define UpdateBlock6Addr 10 #define UpdateBlock7Addr 11 #define UpdateBlock8Addr 12 #define TransBookRespAddr 15 #define DjChannelSetSyRespsSetAddr 22 #define DxChannelSetRespAddr 21 #define ForwardDataG2Addr 24 #define DjChannelSetRespSelfCheckAddr 26 #define DISABLE_SUBADDR_IRQ 0x4200 #define ENABLE_SUBADDR_IRQ 0x0 typedef struct { unsigned int channelAB; unsigned int blockStatusWord; unsigned int timeTagWord; unsigned int dataBlockPointer; unsigned int commandWord; unsigned int remoteTerminalAddr; unsigned int tr; unsigned int subAddModeCode; unsigned int dataCntModeCode; //unsigned char data[BUMSGDATANUM]; unsigned int data[BUMSGDATANUM]; }BUMSGIFM; extern BUMSGIFM rt1553B_BUMSG; extern unsigned int commandWord[8]; #define XPAR_BRAM_0_BASEADDR 0x40000000 //mem ctrl baseaddr #define MEM_BASEADDR 0x43c00000 extern void *rt1553B_BRAMmap_base; //mem ctrl baseaddr extern void *rt1553B_addrmap_base; extern struct fasync_struct *RT_async; //extern unsigned int command; void Xil_Out32(unsigned int *Addr, unsigned int Value); unsigned int *Xil_In32(unsigned int *Addr); #define RT_WriteReg(BaseAddress, RegOffset, Data) \ Xil_Out32((BaseAddress) + (RegOffset), (Data)) #define RT_ReadReg(BaseAddress, RegOffset) \ Xil_In32((BaseAddress) + (RegOffset)) #define MEM_Write(BaseAddress, RegOffset, Data) \ Xil_Out32((BaseAddress) + (RegOffset), (Data)) #define MEM_Read(BaseAddress, RegOffset)\ Xil_In32((BaseAddress) + (RegOffset)) void *BRAM_mmap(void); int init_reg(void); int init_mem(void); int init_rcv(void); int init_send(void); int start_RT(void); int rt1553init(void); void fastenable(void); void fastdisable(void); unsigned int rt1553B_handle(void); #endif
1553init.c
#include <linux/kernel.h> #include <linux/init.h> #include <linux/module.h> #include <linux/slab.h> #include <linux/io.h> #include <linux/interrupt.h> #include <linux/of_address.h> #include <linux/of_device.h> #include <linux/of_platform.h> #include<linux/delay.h> #include <linux/fcntl.h> #include <linux/fs.h> #include "1553drv.h" void *rt1553B_BRAMmap_base; //mem ctrl baseaddr void *rt1553B_addrmap_base; //unsigned int command; BUMSGIFM rt1553B_BUMSG;//消息 unsigned int commandWord[8]={0}; void Xil_Out32(unsigned int * Addr, unsigned int Value) { volatile unsigned int *LocalAddr = (volatile unsigned int *)Addr; *LocalAddr = Value; } unsigned int * Xil_In32(unsigned int * Addr) { return *(volatile unsigned int *) Addr; } void Delay(void) { unsigned int n =1000; while(n--); } // unsigned int MEM_Read(unsigned int BaseAddress,unsigned int RegOffset) // { // unsigned int temp[3]= {0}; // temp[0] = Xil_In32((BaseAddress) + (RegOffset)); // Delay(); // temp[1] = Xil_In32((BaseAddress) + (RegOffset)); // Delay(); // temp[2] = Xil_In32((BaseAddress) + (RegOffset)); // if(temp[0] == temp[1]) // { // return temp[0]; // } // else if(temp[0] == temp[2] ) // { // return temp[0]; // } // else if(temp[1] == temp[2]) // { // return temp[1]; // } // else // { // return 0xFFFF; // } // } void * BRAM_mmap(void) { rt1553B_BRAMmap_base=ioremap(XPAR_BRAM_0_BASEADDR,0x10000); return rt1553B_BRAMmap_base; } // void * addr_mmap(void) // { // rt1553B_addrmap_base=ioremap(MEM_BASEADDR,0x1000000); // return rt1553B_addrmap_base; // } int init_reg() { printk("befdre init reg \n"); Xil_Out32(rt1553B_BRAMmap_base + 68, 0); //fangwen reg ssleep(10); // printk("bram CS success\n"); RT_WriteReg(rt1553B_addrmap_base, (0x03) * 4, 0x0001); //软件复位 LHB155304, // printk("write reg success\n"); RT_WriteReg(rt1553B_addrmap_base, (0x07) * 4, 0x8000); /*配置寄存器#3 的增强模式位置位(因为忙表、增强方式指令处理、 增强中断处理等功能必须在增强模式下才能有效)*/ // red = RT_ReadReg(rt1553B_addrmap_base, (0x07) * 4); // printk("R07 is 0x%x\n", red); //RT_WriteReg(rt1553B_addrmap_base, 0x00, 0x0037); RT_WriteReg(rt1553B_addrmap_base, 0x00, 0x0037); /*初始化中断屏蔽寄存器:使能 RT 子地址控制字中断、 RT 循环缓冲回 卷中断、 RT 方式指令中断和格式错误中断*/ //0013,0037 RT_WriteReg(rt1553B_addrmap_base, (0x02) * 4, 0xB83B); /*初始化配置寄存器#2:使能增强中断、忙表、接收子地址双缓冲、覆 写无效数据字、增强 RT 存储管理和广播数据分离存放*/ //803A,B80B*/ RT_WriteReg(rt1553B_addrmap_base, (0x07) * 4, 0x801D); /*初始化配置寄存器#3:增强模式、禁止非法和忙时接收数据、使能增强 方式指令处理、使能 RT 故障显示*/ //809D,801Dbit7非法禁止 RT_WriteReg(rt1553B_addrmap_base, (0x08) * 4, 0x2008); /*初始化配置寄存器#4:使能方式指令忽略忙位和 RT 地址锁存*/ //2008,2000bit3保留 RT_WriteReg(rt1553B_addrmap_base, (0x09) * 4, 0x0A00); /*初始化配置寄存器#5:选择 16MHz 时钟、使能 GAP 检查*/ //0800,0100bit15时钟选择bit11保留 return 0; } int init_mem() { int i; Xil_Out32(rt1553B_BRAMmap_base + 68, 1); //fangwen mem ssleep(10); for (i = 0; i < 256; i++) { MEM_Write(rt1553B_addrmap_base, (0x000 + i) * 4, 0000); //块状态字单元清零 } //设置堆栈指针 MEM_Write(rt1553B_addrmap_base, (0x0100) * 4, 0000); //初始化区域 A 指令堆栈指针为‘0 /*初始化方式指令中断*/ MEM_Write(rt1553B_addrmap_base, (0x0108) * 4, 0x0000); //接收方式指令 0‐15 不产生中断 MEM_Write(rt1553B_addrmap_base, (0x0109) * 4, 0x0002); //接收方式指令中断:带字同步方式指令中断使能 // mem = MEM_Read(rt1553B_addrmap_base,(0x109)*4); // printk("mem the address at %x data is :0X %x \n\r" ,rt1553B_addrmap_base+(0x109)*4, mem); MEM_Write(rt1553B_addrmap_base, (0x010A) * 4, 0x010A); //发送方式指令中断:无字同步、复位 RT 和自检指令中断使能 MEM_Write(rt1553B_addrmap_base, (0x010B) * 4, 0x0000); //发送方式指令 16‐31 不产生中断 // MEM_Write(rt1553B_addrmap_base, (0x010C) * 4, 0x0000); //广播接收方式指令 0‐15 不产生中断 // MEM_Write(rt1553B_addrmap_base, (0x010D) * 4, 0x0000); //广播接收方式指令中断:带字同步方式指令中断使能 // MEM_Write(rt1553B_addrmap_base, (0x010E) * 4, 0x010A); //广播发送方式指令中断:无字同步、复位 RT 和自检指令中断使能 // MEM_Write(rt1553B_addrmap_base, (0x010F) * 4, 0x0000); //广播发送方式指令 16‐31 不产生中断 /*初始化方式指令数据字*/ MEM_Write(rt1553B_addrmap_base, (0x0111) * 4, 0x0000); //为同步方式指令接收数据保留,清零 MEM_Write(rt1553B_addrmap_base, (0x0120) * 4, 0x1234); //发送矢量字方式指令的数据 return 0; } int init_rcv() { Xil_Out32(rt1553B_BRAMmap_base + 68, 1); //fangwen mem ssleep(10); MEM_Write(rt1553B_addrmap_base, (0x0141) * 4, 0x0400); //接收子地址 1 的数据指针 ssleep(10); MEM_Write(rt1553B_addrmap_base, (0x0143) * 4, 0x0440); //接收子地址 3 的数据指针 ssleep(10); MEM_Write(rt1553B_addrmap_base, (0x0144) * 4, 0x0480); //接收子地址 4 的数据指针 ssleep(10); MEM_Write(rt1553B_addrmap_base, (0x0145) * 4, 0x04c0); //接收子地址 5 的数据指针 ssleep(10); MEM_Write(rt1553B_addrmap_base, (0x0146) * 4, 0x0500); //接收子地址 6 的数据指针 // //ssleep(10); MEM_Write(rt1553B_addrmap_base, (0x0147) * 4, 0x0540); //接收子地址 7 的数据指针 // //ssleep(10); MEM_Write(rt1553B_addrmap_base, (0x0148) * 4, 0x0580); //接收子地址 8 的数据指针 ssleep(10); MEM_Write(rt1553B_addrmap_base, (0x0149) * 4, 0x05C0); //接收子地址 9 的数据指针 ssleep(10); MEM_Write(rt1553B_addrmap_base, (0x014A) * 4, 0x0600); //接收子地址 10 的数据指针 // //ssleep(10); MEM_Write(rt1553B_addrmap_base, (0x014B) * 4, 0x0640); //接收子地址 11 的数据指针 // //ssleep(10); MEM_Write(rt1553B_addrmap_base, (0x014C) * 4, 0x0680); //接收子地址 12 的数据指针 // ssleep(10); MEM_Write(rt1553B_addrmap_base, (0x014E) * 4, 0x06C0); //接收子地址 14 的数据指针 ssleep(10); MEM_Write(rt1553B_addrmap_base, (0x014F) * 4, 0x0700); //接收子地址 15 的数据指针 // //ssleep(10); MEM_Write(rt1553B_addrmap_base, (0x0150) * 4, 0x0740); //接收子地址 16 的数据指针 // //ssleep(10); MEM_Write(rt1553B_addrmap_base, (0x0151) * 4, 0x0780); //接收子地址 17 的数据指针 // //ssleep(10); MEM_Write(rt1553B_addrmap_base, (0x0152) * 4, 0x07C0); //接收子地址 18 的数据指针 ssleep(10); MEM_Write(rt1553B_addrmap_base, (0x0153) * 4, 0x0800); //接收子地址 19 的数据指针 // //ssleep(10); MEM_Write(rt1553B_addrmap_base, (0x0155) * 4, 0x0840); //接收子地址 21 的数据指针 ssleep(10); MEM_Write(rt1553B_addrmap_base, (0x0156) * 4, 0x0880); //接收子地址 22 的数据指针 MEM_Write(rt1553B_addrmap_base, (0x0157) * 4, 0x08C0); //接收子地址 23 的数据指针 MEM_Write(rt1553B_addrmap_base, (0x0158) * 4, 0x0900); //接收子地址 24 的数据指针 // //ssleep(10); MEM_Write(rt1553B_addrmap_base, (0x015A) * 4, 0x0940); //接收子地址 26 的数据指针 ssleep(10); MEM_Write(rt1553B_addrmap_base, (0x015E) * 4, 0x0980); //接收子地址 30 的数据指针 注意:子地址 30 的发送、接收和广播数据指针都被指定为 0480 ssleep(10); return 0; } int init_send() { Xil_Out32(rt1553B_BRAMmap_base + 68, 1); //fangwen mem //msleep(1); MEM_Write(rt1553B_addrmap_base, (0x0161) * 4, 0x0400); //发送子地址 1 的数据指针 ssleep(10); MEM_Write(rt1553B_addrmap_base, (0x0163) * 4, 0x0440); //发送子地址 3 的数据指针 ssleep(10); MEM_Write(rt1553B_addrmap_base, (0x0164) * 4, 0x0480); //发送子地址 4 的数据指针 ssleep(10); MEM_Write(rt1553B_addrmap_base, (0x0165) * 4, 0x04c0); //发送子地址 5 的数据指针 // //ssleep(10); MEM_Write(rt1553B_addrmap_base, (0x0166) * 4, 0x0500); //发送子地址 6 的数据指针 // //ssleep(10); MEM_Write(rt1553B_addrmap_base, (0x0167) * 4, 0x0540); //发送子地址 7 的数据指针 ssleep(10); MEM_Write(rt1553B_addrmap_base, (0x0168) * 4, 0x0580); //发送子地址 8 的数据指针 // //ssleep(10); MEM_Write(rt1553B_addrmap_base, (0x0169) * 4, 0x05C0); //发送子地址 9 的数据指针 // //ssleep(10); MEM_Write(rt1553B_addrmap_base, (0x016A) * 4, 0x0600); //发送子地址 10 的数据指针 ssleep(10); MEM_Write(rt1553B_addrmap_base, (0x016B) * 4, 0x0640); //发送子地址 11 的数据指针 ssleep(10); MEM_Write(rt1553B_addrmap_base, (0x016C) * 4, 0x0680); //发送子地址 12 的数据指针 ssleep(10); MEM_Write(rt1553B_addrmap_base, (0x016E) * 4, 0x06C0); //发送子地址 14 的数据指针 // //ssleep(10); MEM_Write(rt1553B_addrmap_base, (0x016F) * 4, 0x0700); //发送子地址 15 的数据指针 ssleep(10); MEM_Write(rt1553B_addrmap_base, (0x0170) * 4, 0x0740); //发送子地址 16 的数据指针 ssleep(10); MEM_Write(rt1553B_addrmap_base, (0x0171) * 4, 0x0780); //发送子地址 17 的数据指针 // //ssleep(10); MEM_Write(rt1553B_addrmap_base, (0x0172) * 4, 0x07C0); //发送子地址 18 的数据指针 // //ssleep(10); MEM_Write(rt1553B_addrmap_base, (0x0173) * 4, 0x0800); //发送子地址 19 的数据指针 // //ssleep(10); MEM_Write(rt1553B_addrmap_base, (0x0175) * 4, 0x0840); //发送子地址 21 的数据指针 MEM_Write(rt1553B_addrmap_base, (0x0176) * 4, 0x0880); //发送子地址 22 的数据指针 MEM_Write(rt1553B_addrmap_base, (0x0177) * 4, 0x08C0); //发送子地址 23 的数据指针 // //ssleep(10); MEM_Write(rt1553B_addrmap_base, (0x0178) * 4, 0x0900); //发送子地址 24 的数据指针 ssleep(10); MEM_Write(rt1553B_addrmap_base, (0x017A) * 4, 0x0940); //发送子地址 26 的数据指针 // //ssleep(10); MEM_Write(rt1553B_addrmap_base, (0x017E) * 4, 0x0980); //发送子地址 30 的数据指针 // //ssleep(10); return 0; } int start_RT(void) { Xil_Out32(rt1553B_BRAMmap_base + 68, 0); //fangwen reg ssleep(10); /*初始化配置寄存器#1,启动 RT */ RT_WriteReg(rt1553B_addrmap_base, (0x01) * 4, 0x8F80); /*选择 RT 模式, RT 状态字的动态总线控制、忙、服务请求、子地址故 障标记和 RT 故障标记位设置为‘ 0’。*/ } // void fastenable(void) // { // Xil_Out32(rt1553B_BRAMmap_base + 68, 0); // RT_WriteReg(rt1553B_addrmap_base, 0x00, 0x0010); // Xil_Out32(rt1553B_BRAMmap_base + 68, 1); // MEM_Write(rt1553B_addrmap_base, (0x01A3) * 4, 0x4200); //子地址 3:所有消息类型使用单消息管理机制,tr产生中断 // MEM_Write(rt1553B_addrmap_base, (0x01A4) * 4, 0x4200); //子地址 4:所有消息类型使用单消息管理机制,tr生中断 // MEM_Write(rt1553B_addrmap_base, (0x01A5) * 4, 0x4200); //子地址 5:所有消息类型使用单消息管理机制,tr产生中断 // MEM_Write(rt1553B_addrmap_base, (0x01A6) * 4, 0x0000); //子地址 6:所有消息类型使用单消息管理机制,不产生中断 // MEM_Write(rt1553B_addrmap_base, (0x01A7) * 4, 0x0000); //子地址 7:所有消息类型使用单消息管理机制,不产生中断 // MEM_Write(rt1553B_addrmap_base, (0x01A8) * 4, 0x0000); //子地址 8:所有消息类型使用单消息管理机制,不产生中断 // MEM_Write(rt1553B_addrmap_base, (0x01A9) * 4, 0x0000); //子地址 9:所有消息类型使用单消息管理机制,不产生中断 // MEM_Write(rt1553B_addrmap_base, (0x01AA) * 4, 0x0000); //子地址 10:所有消息类型使用单消息管理机制,不产生中断 // MEM_Write(rt1553B_addrmap_base, (0x01AB) * 4, 0x0000); //子地址 11:所有消息类型使用单消息管理机制,不产生中断 // MEM_Write(rt1553B_addrmap_base, (0x01AC) * 4, 0x0000); //子地址 12:所有消息类型使用单消息管理机制,不产生中断 // } // void fastdisable(void) // { // Xil_Out32(rt1553B_BRAMmap_base + 68, 0); // RT_WriteReg(rt1553B_addrmap_base, 0x00, 0x0037); // Xil_Out32(rt1553B_BRAMmap_base + 68, 1); // MEM_Write(rt1553B_addrmap_base, (0x01A3) * 4, 0x0000); //子地址 3:所有消息类型使用单消息管理机制,不产生中断 // MEM_Write(rt1553B_addrmap_base, (0x01A4) * 4, 0x0000); //子地址 4:所有消息类型使用单消息管理机制,不产生中断 // MEM_Write(rt1553B_addrmap_base, (0x01A5) * 4, 0x0000); //子地址 5:所有消息类型使用单消息管理机制,不产生中断 // MEM_Write(rt1553B_addrmap_base, (0x01A6) * 4, 0x0000); //子地址 6:所有消息类型使用单消息管理机制,不产生中断 // MEM_Write(rt1553B_addrmap_base, (0x01A7) * 4, 0x0000); //子地址 7:所有消息类型使用单消息管理机制,不产生中断 // MEM_Write(rt1553B_addrmap_base, (0x01A8) * 4, 0x0000); //子地址 8:所有消息类型使用单消息管理机制,不产生中断 // MEM_Write(rt1553B_addrmap_base, (0x01A9) * 4, 0x0000); //子地址 9:所有消息类型使用单消息管理机制,不产生中断 // MEM_Write(rt1553B_addrmap_base, (0x01AA) * 4, 0x0000); //子地址 10:所有消息类型使用单消息管理机制,不产生中断 // MEM_Write(rt1553B_addrmap_base, (0x01AB) * 4, 0x0000); //子地址 11:所有消息类型使用单消息管理机制,不产生中断 // MEM_Write(rt1553B_addrmap_base, (0x01AC) * 4, 0x0000); //子地址 12:所有消息类型使用单消息管理机制,不产生中断 // } int rt1553init() { int i; BRAM_mmap(); // printk("mmap success!"); //addr_mmap(); init_reg(); init_mem(); init_rcv(); init_send(); /*初始化RT查询表*/ // printk("send rcv mem reg init success!"); //ma MEM_Write(rt1553B_addrmap_base, (0x0181) * 4, 0x0400); //广播接收子地址 1 的数据指针 MEM_Write(rt1553B_addrmap_base, (0x0187) * 4, 0x0C00); //广播接收子地址 7 的数据指针 MEM_Write(rt1553B_addrmap_base, (0x0193) * 4, 0x04A0); //广播接收子地址 19的数据指针 MEM_Write(rt1553B_addrmap_base, (0x019E) * 4, 0x0980); //广播接收子地址 30的数据指针 //初始化 RT 子地址控制字 没有使用的子地址控制字单元应当清零,这里没有给出 MEM_Write(rt1553B_addrmap_base, (0x01A1) * 4, 0x0000); //子地址 1:所有消息类型使用单消息管理机制,不产生中断 MEM_Write(rt1553B_addrmap_base, (0x01A3) * 4, 0x0000); //子地址 3:所有消息类型使用单消息管理机制,不产生中断 MEM_Write(rt1553B_addrmap_base, (0x01A4) * 4, 0x0000); //子地址 4:所有消息类型使用单消息管理机制,不产生中断 MEM_Write(rt1553B_addrmap_base, (0x01A5) * 4, 0x0000); //子地址 5:所有消息类型使用单消息管理机制,不产生中断 MEM_Write(rt1553B_addrmap_base, (0x01A6) * 4, 0x0000); //子地址 6:所有消息类型使用单消息管理机制,不产生中断 MEM_Write(rt1553B_addrmap_base, (0x01A7) * 4, 0x0000); //子地址 7:所有消息类型使用单消息管理机制,不产生中断 MEM_Write(rt1553B_addrmap_base, (0x01A8) * 4, 0x0000); //子地址 8:所有消息类型使用单消息管理机制,不产生中断 MEM_Write(rt1553B_addrmap_base, (0x01A9) * 4, 0x0000); //子地址 9:所有消息类型使用单消息管理机制,不产生中断 MEM_Write(rt1553B_addrmap_base, (0x01AA) * 4, 0x0000); //子地址 10:所有消息类型使用单消息管理机制,不产生中断 MEM_Write(rt1553B_addrmap_base, (0x01AB) * 4, 0x0000); //子地址 11:所有消息类型使用单消息管理机制,不产生中断 MEM_Write(rt1553B_addrmap_base, (0x01AC) * 4, 0x0000); //子地址 12:所有消息类型使用单消息管理机制,不产生中断 MEM_Write(rt1553B_addrmap_base, (0x01AE) * 4, 0x0000); //子地址 14:所有消息类型使用单消息管理机制,不产生中断 MEM_Write(rt1553B_addrmap_base, (0x01AF) * 4, 0x0000); //子地址 15:所有消息类型使用单消息管理机制,不产生中断 MEM_Write(rt1553B_addrmap_base, (0x01B0) * 4, 0x0000); //子地址 16:所有消息类型使用单消息管理机制,不产生中断 MEM_Write(rt1553B_addrmap_base, (0x01B1) * 4, 0x0000); //子地址 17:所有消息类型使用单消息管理机制,不产生中断 MEM_Write(rt1553B_addrmap_base, (0x01B2) * 4, 0x0000); //子地址 18:所有消息类型使用单消息管理机制,不产生中断 MEM_Write(rt1553B_addrmap_base, (0x01B3) * 4, 0x0000); //子地址 19:所有消息类型使用单消息管理机制,不产生中断 MEM_Write(rt1553B_addrmap_base, (0x01B5) * 4, 0x0000); //子地址 21:所有消息类型使用单消息管理机制,不产生中断 MEM_Write(rt1553B_addrmap_base, (0x01B6) * 4, 0x0000); //子地址 22:所有消息类型使用单消息管理机制,不产生中断 MEM_Write(rt1553B_addrmap_base, (0x01B7) * 4, 0x0000); //子地址 23:所有消息类型使用单消息管理机制,不产生中断 MEM_Write(rt1553B_addrmap_base, (0x01B8) * 4, 0x0000); //子地址 24:所有消息类型使用单消息管理机制,不产生中断 MEM_Write(rt1553B_addrmap_base, (0x01BA) * 4, 0x0000); //子地址 26:所有消息类型使用单消息管理机制,不产生中断 MEM_Write(rt1553B_addrmap_base, (0x01BE) * 4, 0x0000); //子地址 30:所有消息类型使用单消息管理机制,不产生中断 //初始化忙表(所有子地址初始化为不忙) for ( i = 0; i < 8; i++) { MEM_Write(rt1553B_addrmap_base, (0x0240 + i) * 4, 0000); } //初始化非法表 //广播接收字地址 MEM_Write(rt1553B_addrmap_base, (0x0300) * 4, 0xFFFF); //子地址 0,广播接收方式指令设置 MEM_Write(rt1553B_addrmap_base, (0x0301) * 4, 0xFFFD); //子地址 0,广播接收方式指令设置:只有带字同步指令被指定为合法 MEM_Write(rt1553B_addrmap_base, (0x0301) * 4, 0000); //广播接收子地址 7 合法 MEM_Write(rt1553B_addrmap_base, (0x0302) * 4, 0000); for (i = 0; i < 12; i++) { MEM_Write(rt1553B_addrmap_base, (0x0304 + i) * 4, 0X0000); //广播接收子地址 1‐广播接收子地址 16 非法 } MEM_Write(rt1553B_addrmap_base, (0x030E) * 4, 0000); //广播接收子地址 7 合法 MEM_Write(rt1553B_addrmap_base, (0x030F) * 4, 0000); for (i = 0; i < 22; i++) { MEM_Write(rt1553B_addrmap_base, (0x0310 + i) * 4, 0X0000); //广播接收子地址 8‐广播接收子地址 18 非法 } MEM_Write(rt1553B_addrmap_base, (0x0326) * 4, 0000); //广播接收子地址 19 合法 MEM_Write(rt1553B_addrmap_base, (0x0327) * 4, 0000); for (i = 0; i < 18; i++) { MEM_Write(rt1553B_addrmap_base, (0x0328 + i) * 4, 0X0000); //广播接收子地址 20‐广播接收子地址 129 非法 } MEM_Write(rt1553B_addrmap_base, (0x033A) * 4, 0000); //广播接收子地址 29 合法 MEM_Write(rt1553B_addrmap_base, (0x033B) * 4, 0000); MEM_Write(rt1553B_addrmap_base, (0x033C) * 4, 0000); //广播接收子地址 30 合法 MEM_Write(rt1553B_addrmap_base, (0x033D) * 4, 0000); MEM_Write(rt1553B_addrmap_base, (0x033E) * 4, 0xFFFF); //广播接收方式指令设置 MEM_Write(rt1553B_addrmap_base, (0x033F) * 4, 0xFFFD); //子地址 31,广播接收方式指令设置:只有同步方式指令合法 /*广播发送子地址*/ MEM_Write(rt1553B_addrmap_base, (0x0340) * 4, 0xFE05); //子地址 0,广播发送方式指令设置 MEM_Write(rt1553B_addrmap_base, (0x0341) * 4, 0xFFFF); /*子地址 0,广播发送方式指令设置:无字同步、启动自检、发送器 切断、忽略发送器切断、禁止故障标记位、忽略故障禁止标记和复位 RT 方式指令合法*/ /*( M0342‐037D 单元无需配置)*/ MEM_Write(rt1553B_addrmap_base, (0x037E) * 4, 0xFE05); //子地址 31,广播发送方式指令设置: MEM_Write(rt1553B_addrmap_base, (0x037F) * 4, 0xFFFF); /*子地址 31,广播发送方式指令设置:无字同步、启动自检、发送器 切断、忽略发送器切断、禁止故障标记位、忽略故障禁止标记和复位 RT 方式指令合法*/ /*;非广播接收子地址*/ MEM_Write(rt1553B_addrmap_base, (0x0380) * 4, 0xFFFF); //子地址 0,非广播接收方式指令设置 MEM_Write(rt1553B_addrmap_base, (0x0381) * 4, 0xFFFD); //子地址 0,非广播接收方式指令设置,只有带字同步方式指令设置为合法 for (i = 0; i < 12; i++) { MEM_Write(rt1553B_addrmap_base, (0x0382 + i) * 4, 0X0000); //广播接收子地址 1‐广播接收子地址 16 非法 } MEM_Write(rt1553B_addrmap_base, (0x038E) * 4, 0000); //接收子地址 7 合法 MEM_Write(rt1553B_addrmap_base, (0x038F) * 4, 0000); for (i = 0; i < 22; i++) { MEM_Write(rt1553B_addrmap_base, (0x0390 + i) * 4, 0X0000); //非广播接收子地址 8‐非广播接收子地址 18 非法 } MEM_Write(rt1553B_addrmap_base, (0x03A6) * 4, 0000); //非广播接收子地址 19 合法 MEM_Write(rt1553B_addrmap_base, (0x03A7) * 4, 0000); for (i = 0; i < 18; i++) { MEM_Write(rt1553B_addrmap_base, (0x03A8 + i) * 4, 0X0000); //非广播接收子地址 20‐非广播接收子地址 29 非法 } MEM_Write(rt1553B_addrmap_base, (0x03BA) * 4, 0000); //非广播接收子地址 30 合法 MEM_Write(rt1553B_addrmap_base, (0x03BB) * 4, 0000); MEM_Write(rt1553B_addrmap_base, (0x03BC) * 4, 0000); //非广播接收子地址 30 合法 MEM_Write(rt1553B_addrmap_base, (0x03BD) * 4, 0000); MEM_Write(rt1553B_addrmap_base, (0x03BE) * 4, 0xFFFF); //子地址 31,非广播接收方式指令设置: MEM_Write(rt1553B_addrmap_base, (0x03BF) * 4, 0xFFFD); //子地址 31,非广播接收方式指令设置:只有无字同步方式指令合法 /*非广播发送子地址*/ MEM_Write(rt1553B_addrmap_base, (0x03C0) * 4, 0xFE00); //子地址 0,非广播发送方式指令设 MEM_Write(rt1553B_addrmap_base, (0x03C1) * 4, 0xFFF2); /*子地址 0,非广播发送方式指令设置:动态总线控制、无字同步、 发送状态字、启动自检、发送器切断、忽略发送器切断、禁止终端故障标记、忽略禁止 终端故障标记、复位 RT、发送矢量字、发送上一指令字和发送 BIT 字合法*/ MEM_Write(rt1553B_addrmap_base, (0x03C2) * 4, 0000); //非广播发送子地址 1 合法 MEM_Write(rt1553B_addrmap_base, (0x03C3) * 4, 0000); for (i = 0; i < 54; i++) { MEM_Write(rt1553B_addrmap_base, (0x03C4 + i) * 4, 0X0000); //非广播接收子地址 20‐非广播接收子地址 29 非法 } MEM_Write(rt1553B_addrmap_base, (0x03FA) * 4, 0000); //非广播发送子地址 30 合法 MEM_Write(rt1553B_addrmap_base, (0x03FB) * 4, 0000); MEM_Write(rt1553B_addrmap_base, (0x03FC) * 4, 0000); //非广播发送子地址 30 合法 MEM_Write(rt1553B_addrmap_base, (0x03FD) * 4, 0000); MEM_Write(rt1553B_addrmap_base, (0x03FE) * 4, 0xFE00); //子地址 31,非广播发送方式指令设置 MEM_Write(rt1553B_addrmap_base, (0x03FF) * 4, 0xFFF2); /*子地址 31,非广播发送方式指令设置:动态总线控制、无字同步、 发送状态字、启动自检、发送器切断、忽略发送器切断、禁止终端故障标记、忽略禁止 终端故障标记、复位 RT、发送矢量字、发送上一指令字和发送 BIT 字合法 */ /*初始化各个子地址的数据块*/ /*初始化子地址 1 的发送数据字*/ for (i = 0; i < 32; i++) { MEM_Write(rt1553B_addrmap_base, (0x400+ i) * 4, 0x0001); } start_RT(); } unsigned int rt1553B_handle() { int Status; int i = 0; unsigned int red; //dujicunqi unsigned int temp, temp1; unsigned int tempVar = 0; int blk; memset(&rt1553B_BUMSG,0,sizeof(rt1553B_BUMSG)); Xil_Out32(rt1553B_BRAMmap_base + 68, 0); //fangwen reg //sslep(10); red = RT_ReadReg(rt1553B_addrmap_base, (BUINTSTATUS)*4); //printk("*****************INT stat is 0x%x**************************\n",red); tempVar = red & BUEOMINT; //读中断状态寄存器,判断现在状态 //tempVar = *(unsigned int *)(BUREG |BUINTSTATUS) & BUEOMINT;//(bit 0 = 1表示消息结束) //printk("tempVar is 0x%x\r\n",tempVar); if (tempVar == BUEOMINT) { //temp1=BUREG | BUCFG1;//配置寄存器#1 temp = RT_ReadReg(rt1553B_addrmap_base, (BUCFG1)*4); // //temp = *(unsigned int *) (temp1); //printk("cfg1 is 0x%x\r\n", temp); rt1553B_BUMSG.channelAB = (temp >> 13) & 0x1; //判断当前工作区域// //printk("channelAB is 0x%x\r\n", rt1553B_BUMSG.channelAB); // /***************************************堆栈四个单元分别读写***********************************************************/ blk = RT_ReadReg(rt1553B_addrmap_base, (BUCMDSTACKPOINT)*4); Xil_Out32(rt1553B_BRAMmap_base + 68, 1); //fangwen reg rt1553B_BUMSG.blockStatusWord = MEM_Read(rt1553B_addrmap_base, blk * 4); //printk("blockStatusWord is 0x%x\r\n", rt1553B_BUMSG.blockStatusWord); rt1553B_BUMSG.timeTagWord = MEM_Read(rt1553B_addrmap_base, (blk + 1) * 4); // //printk("timeTagWord status is 0x%x\r\n", rt1553B_BUMSG.timeTagWord); rt1553B_BUMSG.dataBlockPointer = MEM_Read(rt1553B_addrmap_base, (blk + 2) * 4); //printk("data block pointer is 0x%x\r\n", rt1553B_BUMSG.dataBlockPointer); // Xil_Out32(rt1553B_BRAMmap_base + 68, 0); //fangwen reg // rt1553B_BUMSG.commandWord = MEM_Read(rt1553B_addrmap_base, (BURTLASTCMD)*4); rt1553B_BUMSG.commandWord = MEM_Read(rt1553B_addrmap_base, (blk + 3) * 4); //printk("receive commandword is 0x%x\r\n", rt1553B_BUMSG.commandWord); /***********************************************************************************************/ rt1553B_BUMSG.remoteTerminalAddr = (rt1553B_BUMSG.commandWord >> 11) & 0x1f; //远程终端地址 rt1553B_BUMSG.tr = (rt1553B_BUMSG.commandWord >> 10) & 0x01; //(=0收=1发) rt1553B_BUMSG.subAddModeCode = (rt1553B_BUMSG.commandWord >> 5) & 0x1f; //字地址/方式指令 rt1553B_BUMSG.dataCntModeCode = (rt1553B_BUMSG.commandWord) & 0x1f; //数据字指令/方式指令 // //printk("*******handle is 0x%x***********************************\n",command); if (RT_async) { kill_fasync(&RT_async, SIGIO, POLL_IN); } return 0; } rt1553B_BUMSG.commandWord=-1; if (RT_async) { kill_fasync(&RT_async, SIGIO, POLL_IN); } return 0; }
这样一个完整的模块就编好了,重要函数的讲解在后面会逐步完善