OMAPL多核异构通信驱动AD9833-Notify组件demo

OMAPL多核通信有三个主要机制,Notify,MessageQ,RegionShare;这里主要利用了Notify机制进行通信控制。

要做一个什么实验?

简单的说,ARM跑一个界面上面有一些按钮,DSP负责驱动AD9833产生正弦、方波和三角波,写入频率信息。这个实验结构是一个经典的单向的传输结构,由用户触发ARM跑的界面上的按钮,发出消息通知DSP,DSP控制AD9833产生波形,写入频率字等信息。

那么ARM的Linux端首选Qt,DSP端的程序使用SYSLINK/BIOS实施操作系统,IPC通讯组件使用Notify。

视频预览:

多核通信工程目录结构



几个文件,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的驱动,按照手册进行编辑,然后封装成这个样子,这里一定需要有的函数是:

  • ad9833_dev_new()
  • ad9833_dev_destroy()

这两个函数需要在ad9833_server里面运行。

AD9833这块就不多说了,我们主要来说多核通信这块的知识。

IPC之Notify机制-ad9833_server.c

结构体建立

ad9833_server结构体的建立:

typedef struct ad9833_server_t {
// 3个id
uint8_t host_id;
uint8_t line_id;
uint8_t event_id;
// 连接状态
bool connected;
bool quit;
// 信号量的机制
Semaphore_Struct sem_obj;
Semaphore_Handle sem;
uint32_t payload;
// 底层设备,ad9833_dev.c的驱动结构体
AD9833 *dev;
} AD9833_SERVER ;

*** 3个ID**

host id: 在BIOS里面有设定

line_id,event_id: 在shared文件夹内有个SystemCfg.h里面定义了这两个ID

/* ti.ipc.Notify system configuration */
#define SystemCfg_LineId 0
#define SystemCfg_EventId 7

*** 信号量**

l提供对共享资源的的互斥访问,最多直接64个独立的信号量,信号量请求方式

——直接方式

——间接方式

——混合方式

l不分大小端

l信号量的原子操作

l锁存模式(信号量被使用时)

l排队等待信号量

l获取信号量时产生中断

l支持信号量状态检测

l错误检测和错误中断

通过以上阅读就可以知道信号量是做什么的了。

*** 底层设备**

需要通过server结构体的实例化对AD9833实行操控。

服务函数

Notify必不可少的几个函数:

  • 事件注册函数:static void ad9833_server_on_event(**uint16_t proc_id, uint16_t line_id, uint32_t event_id, UArg arg, uint32_t payloa**)
  • 事件销毁函数:void ad9833_server_destroy(AD9833_SERVER *server)
  • 运行函数: void ad9833_server_run(AD9833_SERVER *server)
  • 命令接收函数: static uint32_t ad9833_server_wait_command(AD9833_SERVER *server)
  • 命令执行函数:static void ad9833_server_handle_command(AD9833_SERVER *server, uint32_t cmd)

基本上有了这些函数之后,就可以完成对于Notify服务函数的处理:

Ad9833Server	*ad9833_server_new( uint16_t host_id, uint16_t line_id, uint32_t event_id )
{
Ad9833Server *server = ( Ad9833Server * )calloc(1,sizeof( Ad9833Server ));
server->host_id = host_id;
server->line_id = line_id;
server->event_id = event_id;
server->quit = false;
server->connected = false; server->dev = ad9833_dev_new();
Semaphore_Params params;
Semaphore_Params_init( &params );
params.mode = Semaphore_Mode_COUNTING;
Semaphore_construct(&server->sem_obj,0,&params);
server->sem = Semaphore_handle(&server->sem_obj); if( Notify_registerEvent( \
server->host_id, \
server->line_id, \
server->event_id, \
ad9833_server_start_event, \
(UArg)server ) < 0 ) {
printf( "fail to register event in %d:%d(line:event)", server->line_id, server->event_id );
} return server;
}

static void ad9833_server_start_event( uint16_t proc_id, uint16_t line_id, uint32_t event_id, UArg arg, uint32_t payload )
{
Ad9833Server *server = (Ad9833Server *)arg; Notify_disableEvent( server->host_id, server->line_id, server->event_id );
//ASSERT( server->payload == APP_CMD_NULL );
server->payload = payload;
Semaphore_post( server->sem );
}

void ad9833_server_destroy( Ad9833Server *self )
{
if( !self ) return;
Notify_unregisterEvent( self->host_id, self->line_id, self->event_id, ad9833_server_start_event, (UArg)self );
Semaphore_destruct(&self->sem_obj);
ad9833_dev_destroy(self->dev);
free(self); }

void ad9833_server_run( Ad9833Server *self )
{
//ASSERT(self);
printf( "ad9833_server running...\n" );
while( ! self->quit ){
uint32_t cmd = ad9833_server_wait_command( self );
ad9833_server_handle_command( self, cmd );
} printf( "ad9833 server is stopped!\n" ); }

static uint32_t ad9833_server_wait_command( Ad9833Server *self )
{
Semaphore_pend( self->sem, BIOS_WAIT_FOREVER );
uint32_t cmd = self->payload;
self->payload = APP_CMD_NULL;
Notify_enableEvent( self->host_id, self->line_id, self->event_id ); return cmd;
}
static uint32_t	ad9833_server_wait_command( Ad9833Server *self )
{
Semaphore_pend( self->sem, BIOS_WAIT_FOREVER );
uint32_t cmd = self->payload;
self->payload = APP_CMD_NULL;
Notify_enableEvent( self->host_id, self->line_id, self->event_id ); return cmd;
}

static void ad9833_server_handle_command( Ad9833Server *self, uint32_t cmd )
{
if( !self->connected && cmd != APP_CMD_CONNECTED ) {
printf( "disconnect client \n" );
}
switch( cmd ) { case APP_CMD_CONNECTED:
//ASSERT(! self->connected);
//LOG_DEBUG("led client had connected");
self->connected = true;
break; case APP_CMD_DISCONNECTED:
//ASSERT( self->connected ); self->connected = false;
self->quit = true; break; case APP_CMD_SETSINE: self->dev->set_wave_type( self->dev, SIN ); break; case APP_CMD_SETSEQ: self->dev->set_wave_type( self->dev, SQU ); break; case APP_CMD_SETTRI: self->dev->set_wave_type( self->dev, TRI ); break; case APP_CMD_SETFREQ_UP: self->dev->set_wave_freq( self->dev, current_freq += 10 );
if( current_freq > 50000 ) {
current_freq = 50000;
}
break; case APP_CMD_SETPHASE_UP: self->dev->set_wave_phase( self->dev, current_phase += 1 );
if( current_phase > 360 ) {
current_phase = 360;
} break; case APP_CMD_SETFREQ_DOWN: self->dev->set_wave_freq( self->dev, current_freq -= 10 );
if( current_freq < 10 ) {
current_freq = 10;
} break;
case APP_CMD_SETPHASE_DOWN: self->dev->set_wave_phase( self->dev, current_phase -= 1 );
if( current_phase < 1 ) {
current_phase = 0;
}
}
}

SYSBIOS启动服务

AD9833	*ad9833_handle;

Int main()
{
Task_Handle task;
Error_Block eb;
System_printf("enter main()\n");
Error_init(&eb);
ad9833_handle = ad9833_dev_new();
task = Task_create(taskFxn, NULL, &eb);
if (task == NULL) {
System_printf("Task_create() failed!\n");
BIOS_exit(0);
} BIOS_start(); /* does not return */
return(0);
} Void taskFxn(UArg a0, UArg a1)
{
System_printf("enter taskFxn()\n");
printf("Hello sysbios.\n");
ad9833_handle->set_wave_para( ad9833_handle, 5000, 0, SIN ); Task_sleep(1500);
ad9833_handle->set_wave_type( ad9833_handle, SQU );
Task_sleep(1500);
ad9833_handle->set_wave_type( ad9833_handle, TRI );
Task_sleep(1500);
ad9833_handle->set_wave_freq( ad9833_handle, 1000.0f );
System_printf("exit taskFxn()\n");
}

到此我们就完成了对于多核通信的Notify DSP端程序。

ARM端Qt程序

在ARM端有Qt程序,Qt主程序中对syslink的初始化,需要注册几个事件:

    SysLink_setup();
this->m_slave_id = MultiProc_getId("DSP"); if( Ipc_control(this->m_slave_id, Ipc_CONTROLCMD_LOADCALLBACK, NULL ) < 0) {
LOG_ERROR("load callback failed");
} if( Ipc_control(this->m_slave_id, Ipc_CONTROLCMD_STARTCALLBACK, NULL ) < 0 ) {
LOG_ERROR("start callback failed");
} m_dev = new ad9833_client( this->m_slave_id, SystemCfg_LineId, SystemCfg_EventId );
if( ! this->m_dev->connect() ) {
LOG_ERROR("failed to connect to led server");
}else {
LOG_DEBUG("connect to led server");
}

需要建立服务函数:

#include "ad9833_client.h"
#include "ti/syslink/Std.h"
#include "ti/ipc/Notify.h"
#include "unistd.h"
#include "log.h" ad9833_client::ad9833_client(uint16_t slave_id, uint16_t line_id, uint16_t event_id )
: m_slave_id(slave_id),m_line_id(line_id),m_event_id(event_id)
{ } ad9833_client::~ad9833_client() { } bool ad9833_client::connect() {
int status; do {
LOG_DEBUG("try to connect!\n");
status = Notify_sendEvent( this->m_slave_id, \
this->m_line_id, \
this->m_event_id, \
APP_CMD_CONNECTED, \
TRUE );
if( status != Notify_E_EVTNOTREGISTERED ) {
usleep(100);
}
}while( status == Notify_E_EVTNOTREGISTERED ); if( status != Notify_S_SUCCESS ) {
LOG_ERROR("failed to send connect command\n");
return false;
} LOG_DEBUG("send connected command");
return true;
} bool ad9833_client::send_cmd( uint16_t cmd )
{
int status = Notify_sendEvent( this->m_slave_id, \
this->m_line_id, \
this->m_event_id, \
cmd, \
TRUE);
if( status < 0 ) {
LOG_DEBUG("fail to send command: %d", cmd);
return false;
}
LOG_DEBUG("send command: %d", cmd);
return true;
} bool ad9833_client::disconnect()
{
LOG_DEBUG("disconnect with server");
return this->send_cmd(APP_CMD_DISCONNECTED);
} bool ad9833_client::set_freq_down()
{
LOG_DEBUG("set freq down with server");
return this->send_cmd(APP_CMD_SETFREQ_DOWN);
} bool ad9833_client::set_freq_up()
{
LOG_DEBUG("set freq up with server");
return this->send_cmd(APP_CMD_SETFREQ_UP);
} bool ad9833_client::set_phase_down()
{
LOG_DEBUG("set phase down with server");
return this->send_cmd(APP_CMD_SETPHASE_DOWN);
} bool ad9833_client::set_phase_up()
{
LOG_DEBUG("set phase up with server");
return this->send_cmd(APP_CMD_SETPHASE_UP);
}
bool ad9833_client::set_wave_type(WAVE_TYPE type)
{
if( type == SIN ) {
LOG_DEBUG("set wave type is sine");
this->send_cmd( APP_CMD_SETSINE );
}else if( type == SQU ) {
LOG_DEBUG("set wave type is squ");
this->send_cmd( APP_CMD_SETSEQ );
}else {
LOG_DEBUG("set wave type is tri");
this->send_cmd( APP_CMD_SETTRI );
}
}
#ifndef AD9833_CLIENT_H
#define AD9833_CLIENT_H
#include "stdint.h"
#include "app_common.h" typedef enum wave_type_t { SIN=0,SQU,TRI } WAVE_TYPE; class ad9833_client
{
public:
explicit ad9833_client( uint16_t slave_id, uint16_t line_id, uint16_t event_id );
~ad9833_client(); bool connect();
bool disconnect(); bool set_wave_type( WAVE_TYPE type );
bool set_freq_up();
bool set_freq_down();
bool set_phase_up();
bool set_phase_down(); private: bool send_cmd( uint16_t cmd ); private: uint16_t m_slave_id;
uint16_t m_line_id;
uint16_t m_event_id; }; #endif // AD9833_CLIENT_H

源程序: 链接: https://pan.baidu.com/s/1sxjQaalhhtNcIBGKPlnxmg 密码: ya8g

参考文献

[1] ti/wiki, IPC Users Guide/Notify Module, 19 July 2014, at 13:36

[2] ti/wiki, IPC API-Notify.h File Reference 3.40.00.06, 2015

[3] ti/wiki, SysLink UserGuide/Notify, 24 July 2014, at 09:26.

OMAPL多核异构通信驱动AD9833波形发生器-Notify组件的更多相关文章

  1. 基于OMAPL138的Linux字符驱动_GPIO驱动AD9833(一)之miscdevice和ioctl

    基于OMAPL138的Linux字符驱动_GPIO驱动AD9833(一)之miscdevice和ioctl 0. 导语 在嵌入式的道路上寻寻觅觅很久,进入嵌入式这个行业也有几年的时间了,从2011年后 ...

  2. DSP+ARM多核异构开发环境SYSLINK搭建OMAPL138

    DSP+ARM多核异构开发环境搭建OMAPL138 注意: 环境为Ubuntu 12.04 只能是这个环境.我甚至在Ubuntu16.04上面安装了VMware,然后,在装了一个Ubuntu 12.0 ...

  3. STM32 基DMA的DAC波形发生器

    DAC是STM32系列的一个基本外设,可以将数字信号转化成模拟信号,这次我将使用DAC来输出一个特定波形. 首先确定工作方法,由于我目前在做的简易示波器在输出波形的同时还需要显示输入信号,所以不能占用 ...

  4. 基于OMAPL138的字符驱动_GPIO驱动AD9833(三)之中断申请IRQ

    基于OMAPL138的字符驱动_GPIO驱动AD9833(三)之中断申请IRQ 0. 导语 学习进入到了下一个阶段,还是以AD9833为例,这次学习是向设备申请中断,实现触发,在未来很多场景,比如做用 ...

  5. 基于OMAPL138的Linux字符驱动_GPIO驱动AD9833(二)之cdev与read、write

    基于OMAPL138的Linux字符驱动_GPIO驱动AD9833(二)之cdev与read.write 0. 导语 在上一篇博客里面,基于OMAPL138的字符驱动_GPIO驱动AD9833(一)之 ...

  6. 基于FPGA的DDS任意波形发生器设计

    一.简介       DDS技术最初是作为频率合成技术提出的,由于其易于控制,相位连续,输出频率稳定度高,分辨率高, 频率转换速度快等优点,现在被广泛应用于任意波形发生器(AWG).基于DDS技术的任 ...

  7. AI异构通信:重压下的突围,华为P50系列的卓越体验

    撰文 |懂懂 编辑 | 秦言 来源:懂懂笔记 "华为不会让消费者失望."华为消费者业务CEO余承东在P50系列发布会上如是说. 今年4月美国对华为第四轮制裁以来,华为终端产品无缘5 ...

  8. (DDS)正弦波形发生器——幅值、频率、相位可调(二)

    (DDS)正弦波形发生器--幅值.频率.相位可调(二) 主要关于调相方面 一.项目任务: 设计一个幅值.频率.相位均可调的正弦波发生器. 频率每次增加10kHz 相位每次增加 PI/2 幅值每次增加两 ...

  9. (DDS)正弦波形发生器——幅值、频率、相位可调(一)

    (DDS)正弦波形发生器--幅值.频率.相位可调 一.项目任务: 设计一个幅值.频率.相位均可调的正弦波发生器. 频率每次增加1kHz. 相位每次增加 2*PI/256 幅值每次增加两倍 二.文章内容 ...

随机推荐

  1. To find names containing exactly five characters, use “^”and “$”to match the beginning and end of the name, and five instances of “.”in between: mysql

    To find names containing exactly five characters, use “^”and “$”to match the beginning and end of th ...

  2. C/S与B/S架构的区别和优缺点

    C/S 架构的概念 C/S是Client/Server,即客户端/服务器端架构,一种典型的两层架构. 客户端包含一个或多个在用户的电脑上运行的程序 服务器端有两种,一种是数据库服务器端,客户端通过数据 ...

  3. 30分钟LINQ教程 【转载】

    原文地址:http://www.cnblogs.com/liulun/archive/2013/02/26/2909985.html 在说LINQ之前必须先说说几个重要的C#语言特性 一:与LINQ有 ...

  4. PHP程序员应当如何保持与时俱进?

    记得之前在某个论坛上看到别人说php程序员土,作为一名php程序员内心当然是不乐意的.不过别人这么说也不是完全没有道理,其实他说php程序员土应该指的就是php程序员不懂得与时俱进. 当然,这也不全是 ...

  5. 环境变量PATH超长问题[转]

    症状回放: 最近安装一个Delphi的控件,结果,在安装之后启动Delphi时出现了找不到相关文件的错误.一开始以为是Delphi内的Library路径没有添加,查看,一切正常.再次启动Delphi, ...

  6. 【java开发系列】—— java输入输出流

    前言 任何语言输入输出流都是很重要的部分,比如从一个文件读入内容,进行分析,或者输出到另一个文件等等,都需要文件流的操作.这里简单介绍下reader,wirter,inputstream,output ...

  7. 高效实时的网络会议数据传输库—UDT

    在视频会议系统的研发当中,我们的音.视频数据必须要有相应的可靠性作为保障,因为视频会议系统是一个实时性非常强的系统,如果其数据在网络不太好的情况下,有可能会出现丢包.数据延迟.数据堵塞等现象,出现这些 ...

  8. bootstrap-multiselect.js如何动态更新select里的数据

    在使用jQuery的bootstrap-multiselect插件时可能会遇到一个问题 就是想要动态的去更新select里的数据 比如我们要使一个id=select的选择框实现多选 那么先用ajax获 ...

  9. 去掉video视频播放器下的下载按钮

    去掉video视频播放器下的下载按钮: video::-internal-media-controls-download-button { display:none; } video::-webkit ...

  10. spring boot Unable to find a @SpringBootConfiguration, you need to use @ContextConfiguration

    java.lang.IllegalStateException: Unable to find a @SpringBootConfiguration, you need to use @Context ...