⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mutlihdlc.c

📁 该程序是MPC860的SCC2用作HDLC模式的驱动程序。供大家参考。
💻 C
📖 第 1 页 / 共 3 页
字号:
/* includes */
#include "copyright_wrs.h"
#include "vxWorks.h"
#include "stdio.h" 
#include "ioLib.h"
#include "intLib.h"
#include "errno.h"
#include  "ifLib.h"
#include  "sysLib.h"
#include "taskLib.h"
#include "msgQLib.h"
#include "iv.h"
#include "drv/intrCtl/ppc860Intr.h"
#include "drv/multi/ppc860Siu.h"
#include "drv/multi/ppc860Cpm.h"
#include "drv/sio/ppc860Sio.h"
#include "mutlichannel.h"
#include "arch/ppc/vxPpcLib.h"
#include "iosLib.h"
#include "sysLib.h"


#include "MAILBOX.h"

#define MAX_MSG_NUM         32
#define MAX_MSG_LENGTH      600
#define DPRAM_PORT_OFFSET   0x0002      /*右口邮箱偏移量*/

extern SEM_ID MboxPrcTaskSemId;	/*mailboxDs21354_Isr释放的信号量,通知DPRAM里有新邮件*/

#define M_HDLC_PASS     0x17


u_char      mhdlcTxBuffer[]=" i one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen";


u_char multibuf[1024] = {0};
UINT16 multilen = 0;
/*#include "ds21354.c"*/
UINT8 totTs ;
UINT16 dl, hdlcTxLen ;
UINT32 chReset[32] = {0};

extern UINT32 rxCorrectTotal[32] ;

/*HDLC收消息队列*/
extern MSG_Q_ID mutliChannelHdlcMsgQId;  
extern MSG_Q_ID mutliChannelHdlcMsgQId1;  
#define PURE_HDLC_FRAME
/* defines */
int    mutliHdlcOpen (PPC860SCCHDLC_CHAN *, u_char*,int); 
int    mutliHdlcRead (PPC860SCCHDLC_CHAN *, u_char*, int) ;
int    mutliHdlcWrite (PPC860SCCHDLC_CHAN *, u_char*, int) ;
LOCAL  STATUS mutliHdlcIoctl (PPC860SCCHDLC_CHAN *, int, int) ;
void   mutliHdlcStartup(void);

/************************************************************************* 
* mutli_channel HDLC Interrupt - interrupt service routine 
* 
* Most drivers have routines that handle interrupts from the devices 
* serviced by the driver. These routines are connected to the interrupts 
* by calling intConnect (usually in xxDrv above). They can receive a 
* single argument, specified in the call to intConnect (see intLib). 
*/ 
void   mutliHdlcInterrupt (PPC860SCCHDLC_CHAN *); 

STATUS mutliHdlcDrv(void);
STATUS mutliHdlcDevCreate(PPC860SCCHDLC_CHAN *,u_char*,FAST int);
void   QMC_GlobalInit(void);
void   QMC_ChannelInit(void);
void   QMC_InitBDs(void);
void   mutliChannelHdlcInit(void);
void   sccMutliHdlcInit(void);


void   mutliChannelHdlcStartup(void);
int    mutliChannelHdlcWrite(u_char*,int);

UINT16 *IntCQ=(UINT16*)(0x01ff8000);        /* interrupt circle queue for QMC*/
int    mutliHdlcDrvNum=0;
PPC860SCCHDLC_CHAN   mutliHdlcChan; /*mutli-channel hdlc struct*/
UINT8   *qmcTxBuffer=(UINT8*)(0x1fe0000);/*32k*/
UINT8   *qmcRxBuffer=(UINT8*)(0x1fe8000);/*32k*/ 
BDRINGS *bdbase=(BDRINGS*)(0x01ff0000);/**/
R_HDLC_FRAME *rHdlcFrame=(R_HDLC_FRAME*)(0x01ffa000);
/* forward declarations */




/*  driver function table */
/*  打开一个多通道HDLC设备 */
/* 
 参数:1、PPC860SCCHDLC_CHAN *pchan:此设备的数据结构,是联系驱动程序和I/O设备的纽带,所有
            的调用都要通过此结构体来完成用户需要。
          2、char * remainder:保留参数,没有使用,因此必须为0
          3、 int mode:打开模式,没有使用,必须为0
    返回值:设备数据结构的值 
*/

int mutliHdlcOpen  
  (
  PPC860SCCHDLC_CHAN *pSioChan, 
  u_char * remainder, 
  int mode
  )
{ 
    /* serial devices should have no file name part */ 
    if (remainder[0] != 0) 
        return (ERROR); 
    else 
        return ((int) pSioChan); 
} 



/*
多通道HDLC设备写函数(指定通道号)
参数:1、PPC860SCCHDLC_CHAN *pchan:此设备的数据结构,是联系驱动程序和I/O设备的纽带,所有
          的调用都要通过此结构体来完成用户需要。
     2、char *buffer: 等待写如入的数据指针,因为程序需要区分该数据是写往哪一路HDLC,所以上层程序需要指
                     明要写入的HDLC链路号,从0到31,buffer[0]被指定为链路号标识。
     3、int dataLen:  写数据长度,每次写入的数据长度不能超过HDLC链路规定的最大帧长度,因为一次写操作只
                     能写入一个HDLC帧,我们规定的最大帧长度为1500个字节,因此该参数必须小于1496,4个字
                     节CRC校验空间保留。
     注意:长度大小不包括buffer[0]在内
 返回值:1、OK,数据发送成功
        2、EAGAIN,数据发送失败
*/
int mutliHdlcWrite( PPC860SCCHDLC_CHAN *pSioChan, u_char *buffer, int dataLen )
{
    PPC860SCCHDLC_CHAN *    pChan = pSioChan;
    int i,j;
    int channelNum;
    int activeTxBd;
    UINT16 *tempAddr;
       
    channelNum=buffer[0];
    activeTxBd=pChan->hdlc.txBdNext[channelNum];
    
    tempAddr=(UINT16*)(0xff002000+0x02+channelNum*64);
    i=0;
    while((i<=20000)&&(bdbase[channelNum].TxBd[activeTxBd].bd_cstatus&BD_TX_READY_BIT)) 
    {
        i++;
    }
    /*如果该通道有未发送的帧,等待1000个循环*/
    
    if (bdbase[channelNum].TxBd[activeTxBd].bd_cstatus &BD_TX_READY_BIT)
    {
        return(EAGAIN);
    }
    /*如果还有未发送的帧,返回错误*/
    
    if(dataLen>MAX_HDLC_FRAME)
    {
        return(EAGAIN);   
    }
    /*太大的帧,不发送*/
        
    for( i=1,j=1; i<=dataLen; i++,j++ )
    {
        bdbase[channelNum].TxBd[activeTxBd].bd_addr[j-1] =(u_char)buffer[i];
    }
    bdbase[channelNum].TxBd[activeTxBd].bd_length =dataLen;
    /*数据长度*/
    bdbase[channelNum].TxBd[activeTxBd].bd_cstatus|=BD_TX_READY_BIT|0x0800;
    /*打开发送位,开始发送*/
                
    *tempAddr|=0x0100;
                
    pChan->hdlc.txBdNext[channelNum]= (activeTxBd + 1) % pChan->hdlc.txBdNum;
    /*指向下一个BD*/
    return(OK);
}
  
  
  
 
/*
  多通道HDLC设备读函数(向指定通道读)
  参数:1、PPC860SCCHDLC_CHAN *pchan:此设备的数据结构,是联系驱动程序和I/O设备的纽带,所有
            的调用都要通过此结构体来完成用户需要。
       2、char *buffer: 等待读入的数据指针,因为程序需要区分该数据是写往哪一路HDLC,所以上层
                        程序需要指明要写入的HDLC链路号,从0到31,buffer[0]被指定为链路号标
                        识。
       3、int dataLen:  读数据长度,每次读入的数据长度不能超过HDLC链路规定的最大帧长度,因为
                        一次读操作只能读入一个HDLC帧,我们规定的最大帧长度为1500个字节,因此
                        该参数必须小于1496,4个字节的CRC校验空间保留。
       注意:长度大小不包括buffer[0]在内
 返回值:OK,数据读取成功
        EAGAIN,数据读取失败
*/ 
int mutliHdlcRead 
  (
  PPC860SCCHDLC_CHAN *pChan ,
  u_char *buffer ,
  int  dataLen 
  )
{
    int i=0,j=0, activeRxBd,lastFrameBd;
    int channelNum;
    
    channelNum=buffer[0];
    
    if((channelNum>=MAXLOGCHAN)|(channelNum<0))
        return(EAGAIN);
      
    activeRxBd=pChan->hdlc.rxBdNext[channelNum];
    lastFrameBd=activeRxBd;
                    
    if (bdbase[channelNum].RxBd[activeRxBd].bd_cstatus &BD_RX_EMPTY_BIT)
        return(EAGAIN);
    /*接收缓冲为空,返回错误*/
    
    if (bdbase[channelNum].RxBd[activeRxBd].bd_cstatus &0x003c)
        return(EAGAIN);
    /*有出现LG,NO,AB,CR错误,返回*/
    
    while(!(bdbase[channelNum].RxBd[lastFrameBd].bd_cstatus&0x0800))
    {
        lastFrameBd=(lastFrameBd+1)%(pChan->hdlc.rxBdNum);
        if ( (bdbase[channelNum].RxBd[lastFrameBd].bd_cstatus & 0x803c)|(i>1000) )
        {
            while(activeRxBd==lastFrameBd)    
            {
                bdbase[channelNum].RxBd[activeRxBd].bd_cstatus |= BD_RX_EMPTY_BIT;
                activeRxBd=(activeRxBd+1)%(pChan->hdlc.rxBdNum);
            }/*将上面的缓冲区置空标志*/
            return(EAGAIN);
        }
        i++;
        /*循环1000次,找不到一帧的最后缓冲区标志,返回错误*/
    }
        
    dataLen = bdbase[channelNum].RxBd[lastFrameBd].bd_length;
    
    if(dataLen>MAX_HDLC_FRAME)
    {
        dataLen=0;
        while(activeRxBd==lastFrameBd)    
        {
            bdbase[channelNum].RxBd[activeRxBd].bd_cstatus|=
            BD_RX_EMPTY_BIT;
            activeRxBd=(activeRxBd+1)%(pChan->hdlc.rxBdNum);
        }/*将上面的缓冲区置空标志*/
      
        return(EAGAIN);
    }
    /*太大的帧,不接受,置dataLen=0*/
    
    
    for(i=1,j=1;i<dataLen;i++,j++)
    {
        buffer[i]=(u_char)bdbase[channelNum].RxBd[activeRxBd].bd_addr[j-1];
      
        if(j>bdbase[channelNum].RxBd[activeRxBd].bd_length) /*缓冲区读完*/
        {
            bdbase[channelNum].RxBd[activeRxBd].bd_cstatus|=BD_RX_EMPTY_BIT;
                  /*置缓冲区为空*/  
            activeRxBd=(activeRxBd+1)%(pChan->hdlc.rxBdNum);
            /*下一个BD*/
            j=1;
        }
    }
    
    bdbase[channelNum].RxBd[activeRxBd].bd_cstatus|=BD_RX_EMPTY_BIT;
    /*置缓冲区为空*/
    if(activeRxBd==lastFrameBd)
    {
        pChan->hdlc.rxBdNext[channelNum] = (activeRxBd + 1) % pChan->hdlc.rxBdNum;
    }   
    else
    {
        pChan->hdlc.rxBdNext[channelNum] = (lastFrameBd + 1) % pChan->hdlc.rxBdNum;
    }       
    
    return(OK);
}




  
/*I/O控制函数,目前暂时没有功能可以使用,可以根据需要增加*/
/*
  参数:1、PPC860SCCHDLC_CHAN *pchan:此设备的数据结构,是联系驱动程序和I/O设备的纽带,所有
            的调用都要通过此结构体来完成用户需要。
       2、int request:要求代码
       3、int arg:   参数
  返回值:多通道HDLC工作模式改变
       1、正确 
       2、出错:返回系统错误代码
*/
LOCAL STATUS mutliHdlcIoctl
    (
    PPC860SCCHDLC_CHAN *    pChan,      /* device to control */
    int         request,            /* request code */
    int         arg             /* some argument */
    )
{
    STATUS  status = OK;
    
    switch(request)
    {
        case(SIO_MODE_SET):
            return(ENOSYS);
            break;
        default:
            status = ENOSYS;
    }
    return(status);
}



 /*
  多通道中断处理函数,本函数只处理多通道HDLC的某一路收到一个完整的HDLC帧,将收到的帧保存在缓冲区里
  然后向消息队列中发送一条消息,通知上层应用程序处理
   参数:1、PPC860SCCHDLC_CHAN *pchan:此设备的数据结构,是联系驱动程序和I/O设备的纽带,所有
            的调用都要通过此结构体来完成用户需要。
    返回值:无
 */
//UINT32 rxChReset[32] = {0} ;
void mutliHdlcInterrupt 
 (
   PPC860SCCHDLC_CHAN * pSioChan
 )
{      
    PPC860SCCHDLC_CHAN *    pChan = pSioChan;
    UINT16 *curIntCQPtr; 
    int exitFlag,lastBdFlag;
    UINT16 scceReg;
    UINT16 channelNum;
    UINT16 i,j, rxLen, temp;
    int activeRxBd, lastFrameBd;
       
    exitFlag=0;
    lastBdFlag=OK;
    scceReg=*(UINT16*)MPC860_SCCE2(vxImmrGet()); 
    *MPC860_SCCE2(vxImmrGet())=0x000f;
    curIntCQPtr=IntCQ;
    i=0;
    j=0;

    if(!scceReg&0x0004)
    {
        *MPC860_CISR(vxImmrGet())|=CISR_SCC2;
        /*清中断*/
        return;
        /*没有GINT中断,退出*/ 
        /*几乎屏蔽其他所有的中断*/
    }
    
    while(!exitFlag)
    {            
        if((*curIntCQPtr)&QMC_ITE_V)   /*V有效?*/
        {         
            channelNum=((*curIntCQPtr)&QMC_ITE_CN);
            channelNum=(channelNum>>6);
            /*获得通道号*/
            activeRxBd=pChan->hdlc.rxBdNext[channelNum];
            lastFrameBd=activeRxBd;

            if((*curIntCQPtr)&QMC_ITE_RXF)  /*收到一个帧*/
            {     
                rHdlcFrame->frameLen=
                bdbase[channelNum].RxBd[lastFrameBd].bd_length;
                /*帧的长度*/
                rHdlcFrame->channelNum=channelNum;
                rHdlcFrame->buffer[0]=channelNum;

                /*通道号*/
                   
                /* 读取帧的内容 */
                for(i=1,j=0;i<=rHdlcFrame->frameLen;i++,j++)
                {  
                    rHdlcFrame->buffer[i]=                                            	 	
	                (u_char)bdbase[channelNum].RxBd[activeRxBd].bd_addr[j];              
	            }
			
                rHdlcFrame->frameLen=rHdlcFrame->frameLen-2;	

                bdbase[channelNum].RxBd[activeRxBd].bd_cstatus |= BD_RX_EMPTY_BIT;
                /*置缓冲区为空*/
                  
                pChan->hdlc.rxBdNext[channelNum] = (activeRxBd + 1) % pChan->hdlc.rxBdNum;

                rxLen = (UINT)rHdlcFrame->frameLen ;
                for( i=1; i<rxLen; i++ )
                {
                    if( rHdlcFrame->buffer[i] != i )
                    {               
                        for( j=0; j<rxLen; j++ )
                        {
                            if( j%20 == 0 )
                                logMsg( "\n",0,0,0,0,0,0 ) ;
                            logMsg( "%2x ", rHdlcFrame->buffer[j],0,0,0,0,0 ) ;
                        }
                        i = 0x1000 ;
                    }
                }
                
                if(( i < 0x1000 ) && ( rxLen == hdlcTxLen ))
                    rxCorrectTotal[rHdlcFrame->buffer[0]] = rxCorrectTotal[rHdlcFrame->buffer[0]] + 1 ;
/*                msgQSend(mutliChannelHdlcMsgQId1,
                         rHdlcFrame->buffer,
                         (UINT)rHdlcFrame->frameLen,
                         0, MSG_PRI_NORMAL); */
                /*向上层队列发送消息*/
            } /*(*curIntCQPtr)&QMC_ITE_RXF*/  
        }/* if((*curIntCQPtr)&QMC_ITE_V)*/   

        if((*curIntCQPtr)&QMC_ITE_W)         /*中断表最后一个??*/
        {  
            exitFlag=1;
            /*最后一个,退出*/
            (*curIntCQPtr)&=(QMC_ITE_CLEAR | QMC_ITE_W);
            /*清*/
            curIntCQPtr=IntCQ;
        }
        else
        {
            (*curIntCQPtr)&=QMC_ITE_CLEAR;
            curIntCQPtr++;      /*中断表下一个*/
        }
    }
          
    *MPC860_CISR(vxImmrGet())|=CISR_SCC2;
    /*清中断*/
    
        /*读取32通道RxBD状态*/
//    for( i=0; i<MAXLOGCHAN; i++ )
//    {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -