OMAPL多核异构通信驱动AD9833Notify组件demo

OMAPL多核通信有三个主要机制,Notify,MessageQ,RegionShare;这里主要利用了Notify机制进行通信控制。 要做一个什么实验?简单的说,ARM跑一个界面上面有一些按钮,DSP负责驱动AD9833产生正弦、方波和三角波,写入频率信息。这个实验结构是一个经典的单向的传输结构,由用户触发ARM跑的界面上的按钮,发出消息通知DSP,DSP控制AD9833产生波形,写入频率字等信息。 那么ARM的Linux端首选Qt,DSP端的程序使用SYSLINK/BIOS实施操作系统,IPC通讯组件使用Notify。 视频预览: <iframe height=498 width=510 src='http://player.youku.com/embed...' frameborder=0 'allowfullscreen'></iframe> 多核通信工程目录结构几个文件,arm,dsp,run,shared,还有makefile文件,makefile文件自己要会修改。 DSP端程序 DSP端程序对于用户来讲ad9833_dev.c ad9833_server.c main.c 三个主要的文件, ad9833_dev.c 为AD9833底层驱动,负责写时序,写参数的ad9833_server.c 相当于以太网scoket通信因子,负责进行多核通信和调用dev中的api的main.c 为dspbios启动,初始化操作。环境搭建正确之后,最核心的就是这三个东西,对还有个makefile要配置正确。我在环境调试的时间花的比开发时间多的多,最重要的就是要环境配置正确,库啊,路径啊,这类的。 AD9833底层驱动-ad9833_dev.c我们这里给出接口函数目录,具体实现不给出: enum ad9833_wavetype_t{ SIN,SQU,TRI};struct ad9833_hw_t { uint16 clk; uint16 sdi; uint16 fsy;};// AD9833结构体表述typedef struct ad9833_t { struct ad9833_hw_t hw; struct ad9833_t *self; enum ad9833_wavetype_t wave_type; u16 delay; void (*write_reg)( struct ad9833_t *self, u16 reg_value); void (*init_device)( struct ad9833_t *self ); void (*set_wave_freq)( struct ad9833_t *self , float freqs_data); void (*set_wave_type)( struct ad9833_t *self, enum ad9833_wavetype_t wave_type ); void (*set_wave_phase)( struct ad9833_t *self, u16 phase ); void (*set_wave_para)( struct ad9833_t *self, u32 freqs_data, u16 phase, enum ad9833_wavetype_t wave_type );} AD9833;// 函数列表void ad9833_set_para( struct ad9833_t *self,u32 freqs_data, u16 phase, enum ad9833_wavetype_t wave_type );void ad9833_device_init( struct ad9833_t *self );void ad9833_write_reg( struct ad9833_t *self, uint16_t data );void ad9833_delay( struct ad9833_t *self );void ad9833_gpio_init( void );void ad9833_set_wave_type( struct ad9833_t *self, enum ad9833_wavetype_t wave_type );void ad9833_set_phase( struct ad9833_t *self, uint16_t phase );void ad9833_set_freq( struct ad9833_t *self, float freq );void ad9833_dev_destroy( AD9833 *dev );void ad9833_dev_new();AD9833的驱动,按照手册进行编辑,然后封装成这个样子,这里一定需要有的函数是: ...

November 4, 2019 · 5 min · jiezi

基于OMAPL138的字符驱动GPIO驱动AD9833三之中断申请IRQ

0. 导语学习进入到了下一个阶段,还是以AD9833为例,这次学习是向设备申请中断,实现触发,在未来很多场景,比如做用户级的SPI传输完毕数据之后,怎么知道从设备要发数据呢,则需要一个IO信号通知主设备来读从设备的数据,那么就需要一个外部的IO中断信号,所以呢,对于中断的处理十分重要,本demo实现这样的一个功能增加一个GPIO口,这个GPIO口接的是一个按键,通过触发信号,进入中断服务函数,在中断服务函数内改变AD9833的波形。以此达到学习实验目的。 之前的代码都是一样的,在这里尽量剥离AD9833驱动和Linux的代码模板,只写中断相关相关程序。 效果演示视频: https://v.youku.com/v_show/id... 1. 前篇导读:基于OMAPL138的字符驱动_GPIO驱动AD9833(一)之ioctl基于OMAPL138的Linux字符驱动_GPIO驱动AD9833(二)之cdev与read、writeLinux GPIO键盘驱动开发记录_OMAPL138原理图: 2. 申请中断准备首先需要两个头文件:#include <linux/interrupt.h>#include <linux/irq.h>IO口配置准备在此次使用中断中,主要用的是GPIO口,我们使用电平跳变使之进入到中断处理程序中,所以作为IO口,需要配置IO口的方向为输入方向。我的OMAPL138中给的IO口操作使用GPIO_TO_PIN这个宏函数进行,在IO口操作上每个平台都会给定自己的寻IO口的方法,然后使用linux通用gpio_direction_output进行设定该GPIO口为输入方向,如上面的原理图,本demo的驱动使用的GPIO6[1],所以as follow:gpio_direction_output( GPIO_TO_PIN(6, 1) , 0 ); 硬件中断号IRQ我参考了很多文献,也找了很多书籍,对于硬件中断号码从哪里得到一笔带过,也没有具体说明,不过,经过一下午的努力,我找到了查找中断号码的方法。使用gpio_to_irq这个函数方法可以得到irq。我之前找到手册,看到了手册里面说GPIO6 BANK的IRQ为48号,我尝试加载到内核里面,每次初始化的时候都告诉我中断申请失败,这个号看来不是datasheet给定的48号,在Linux内核里面对于硬件IRQ又进行了重新映射。 中断事件在内核中断申请的时候,需要指定中断事件是什么,边沿信号,高电平触发,低电平触发,在irq.h里面定义了: IRQ_TYPE_NONE = 0x00000000, IRQ_TYPE_EDGE_RISING = 0x00000001, IRQ_TYPE_EDGE_FALLING = 0x00000002, IRQ_TYPE_EDGE_BOTH = (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING), IRQ_TYPE_LEVEL_HIGH = 0x00000004, IRQ_TYPE_LEVEL_LOW = 0x00000008, IRQ_TYPE_LEVEL_MASK = (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH), IRQ_TYPE_SENSE_MASK = 0x0000000f 我们需要指定这个事件。 中断的名字这个使用#cat /proc/interrupts 查看当前内核中断资源的时候就可以看到你指定注册的名字。 中断服务程序这个我们自己定一个函数就可以,然后一会儿使用中断申请的时候将数据传输进去就好。我们在中断服务函数里面进行按键进行波形切换: static int key_count = 0;static irqreturn_t ad9833_press_intHandle( int irq, void *dev_id ){ printk( DRV_NAME "\t press trigger!\n" ); if( key_count == 0 ) { ad9833->set_wave_type( ad9833, SIN ); printk( DRV_NAME "\tSet wave is SIN.\n" ); }else if( key_count == 2 ) { ad9833->set_wave_type( ad9833, TRI ); printk( DRV_NAME "\tSet wave is TRI.\n" ); }else if( key_count == 4 ) { ad9833->set_wave_type( ad9833, SQU ); printk( DRV_NAME "\tSet wave is SQU.\n" ); } key_count ++; if( key_count >= 5 ) key_count = 0; return IRQ_RETVAL( IRQ_HANDLED );}3. 申请中断准备使用request_irq函数就好,我们在初始化函数里面,申请irq。在申请irq前,为了更好的管理中断函数,我们定义了一个结构体,专门进行irq配置。 ...

November 4, 2019 · 2 min · jiezi