博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
OMAPL多核异构通信驱动AD9833波形发生器-Notify组件
阅读量:5234 次
发布时间:2019-06-14

本文共 12086 字,大约阅读时间需要 40 分钟。

OMAPL多核异构通信驱动AD9833-Notify组件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='' frameborder=0 'allowfullscreen'>

多核通信工程目录结构

810200-20180608132745322-521475425.png

几个文件,arm,dsp,run,shared,还有makefile文件,makefile文件自己要会修改。

DSP端程序

810200-20180608133818631-742840630.png

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

源程序: 链接: 密码: ya8g

参考文献

[1] ti/wiki, , 19 July 2014, at 13:36

[2] ti/wiki, , 2015
[3] ti/wiki, , 24 July 2014, at 09:26.

转载于:https://www.cnblogs.com/sigma0/p/9155134.html

你可能感兴趣的文章
监控工具之---Prometheus 安装详解(三)
查看>>
不错的MVC文章
查看>>
IOS Google语音识别更新啦!!!
查看>>
[置顶] Linux终端中使用上一命令减少键盘输入
查看>>
BootScrap
查看>>
路冉的JavaScript学习笔记-2015年1月23日
查看>>
Mysql出现(10061)错误提示的暴力解决办法
查看>>
2018-2019-2 网络对抗技术 20165202 Exp3 免杀原理与实践
查看>>
Swift - 异步加载各网站的favicon图标,并在单元格中显示
查看>>
【Python学习笔记】1.基础知识
查看>>
梦断代码阅读笔记02
查看>>
selenium学习中遇到的问题
查看>>
大数据学习之一——了解简单概念
查看>>
Lintcode: Partition Array
查看>>
[Linux]PHP-FPM与NGINX的两种通讯方式
查看>>
Java实现二分查找
查看>>
[LintCode] 462 Total Occurrence of Target
查看>>
架构图-模型
查看>>
黑马程序员_Java基础枚举类型
查看>>
UIImage 和 iOS 图片压缩UIImage / UIImageVIew
查看>>