#OMAPL多核異構通訊驅動AD9833-Notify組件demophp
OMAPL多核通訊有三個主要機制,Notify,MessageQ,RegionShare;這裏主要利用了Notify機制進行通訊控制。html
簡單的說,ARM跑一個界面上面有一些按鈕,DSP負責驅動AD9833產生正弦、方波和三角波,寫入頻率信息。這個實驗結構是一個經典的單向的傳輸結構,由用戶觸發ARM跑的界面上的按鈕,發出消息通知DSP,DSP控制AD9833產生波形,寫入頻率字等信息。ios
那麼ARM的Linux端首選Qt,DSP端的程序使用SYSLINK/BIOS實施操做系統,IPC通信組件使用Notify。api
視頻預覽:app
<iframe height=498 width=510 src='http://player.youku.com/embed/XMzY1MjUwNDI0OA==' frameborder=0 'allowfullscreen'></iframe>ide
幾個文件,arm,dsp,run,shared,還有makefile文件,makefile文件本身要會修改。函數
DSP端程序對於用戶來說ad9833_dev.c ad9833_server.c main.c 三個主要的文件,post
環境搭建正確以後,最核心的就是這三個東西,對還有個makefile要配置正確。我在環境調試的時間花的比開發時間多的多,最重要的就是要環境配置正確,庫啊,路徑啊,這類的。ui
咱們這裏給出接口函數目錄,具體實現不給出:this
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_server裏面運行。 AD9833這塊就很少說了,咱們主要來講多核通訊這塊的知識。
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( ¶ms ); params.mode = Semaphore_Mode_COUNTING; Semaphore_construct(&server->sem_obj,0,¶ms); 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; } } }
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程序,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.