天天看點

VxWorks BSP學習筆記_序列槽驅動1.     序列槽驅動

VxWorks BSP學習筆記(基于SBC8349E)

1.     序列槽驅動

1.1   串行驅動程式的重要結構

以下結構指出了驅動程式函數的入口點  ../target/h/sioLib.h

Typedef struct sio_drv_funcs          

{

    int     (*ioctl)

        (

        SIO_CHAN * pSioChan,

        int    cmd,

        void *     arg

        );

    int     (*txStartup)

        (

        SIO_CHAN * pSioChan

        );

    int     (*callbackInstall)

        (

        SIO_CHAN * pSioChan,

        int    callbackType,

        STATUS     (*callback)(void *, ...),

        void *     callbackArg

        );

    int     (*pollInput)

        (

        SIO_CHAN * pSioChan,

        char *     inChar

        );

    int     (*pollOutput)

        (

        SIO_CHAN * pSioChan,

        char       outChar

        );

}SIO_DRV_FUNCS;

typedef struct sio_chan           

    {

    SIO_DRV_FUNCS * pDrvFuncs;

} SIO_CHAN;

在串行裝置的驅動程式中,必須有一個包含指向SIO_DRV_FUNCS指針的結構(XX_CHAN),這個結構可以包含裝置的其他資訊以及提供給高層協定的回調函數。以16550為例:

../target/h/drv/sio/ns16552Sio.h

typedef  struct  

    {

    SIO_DRV_FUNCS *     pDrvFuncs;     

    STATUS      (*getTxChar) ();  

    STATUS      (*putRcvChar) ();

    void *      getTxArg;

    void *      putRcvArg;

    UINT8   *regs;    

    UINT8   level;    

    UINT8   ier;      

    UINT8   lcr;      

    UINT8   mcr;      

    UINT16      channelMode;  

    UINT16      regDelta; 

    int         baudRate;

    UINT32      xtal;          

    UINT32  options;  

} NS16550_CHAN;

1.2   串行驅動程式的初始化函數

串行裝置驅動程式的初始化函數應該包含下面的内容:

1)  包含一個指向xx_DRV結構的指針;

2)  初始化xx_CHAN;

3)  初始化驅動程式必要的内容;

4)  重新設定晶片

../target/src/drv/sio/ns16550Sio.c

#ifdef INCLUDE_TTY_DEV

static SIO_DRV_FUNCS ns16550SioDrvFuncs =

    {

    (int (*)()) ns16550Ioctl,

    (int (*)()) ns16550TxStartup,

    (int (*)()) ns16550CallbackInstall,

    (int (*)()) ns16550PollInput,

    (int (*)(SIO_CHAN *,char))ns16550PollOutput

    };

#else 

static SIO_DRV_FUNCS ns16550SioDrvFuncs =

    {

    (int (*)()) NULL,

    (int (*)()) NULL,

    (int (*)()) NULL,

    (int (*)()) ns16550PollInput,

    (int (*)(SIO_CHAN *,char))ns16550PollOutput

    };

#endif 

void ns16550DevInit

    (

        NS16550_CHAN * pChan

    )

    {

    int oldlevel = intLock ();

    pChan->pDrvFuncs    = &ns16550SioDrvFuncs;

    pChan->getTxChar    = ns16550DummyCallback;

    pChan->putRcvChar   = ns16550DummyCallback;

    pChan->channelMode  = 0;   

    pChan->options      = (CLOCAL | CREAD | CS8);

    pChan->mcr     = MCR_OUT2;

    ns16550InitChannel (pChan);

    intUnlock (oldlevel);

}

1.3   回調安裝函數以及驅動各函數的實作

SIO_DRV_FUNCS結構中的各函數的實作

1.4   串行裝置的安裝

1.4.1          串行裝置的初始化

sysDuartHwInit(),由usrInit()函數調用,初始化了驅動程式相關的xx_CHAN結構。調用了xxDevInit()函數初始化硬體,設定中斷未連接配接标志。該函數在核心初始化之前完成。使用16550晶片的例子:

void sysDuartHwInit (void)

    {

    int i;

    eumbbar_base = (char *)CCSBAR;

    for (i = 0; i < N_DUART_CHANNELS; i++)

        {

    ns16550Chan[i].regs        = (UINT8 *)devDuartParas[i].baseAdrs;

    ns16550Chan[i].level    = devDuartParas[i].intLevel;

    ns16550Chan[i].channelMode = SIO_MODE_INT;

    ns16550Chan[i].regDelta    = devDuartParas[i].regSpace;

    ns16550Chan[i].baudRate     = DUART_BAUD;

    ns16550Chan[i].xtal     = sysClkFreqGet();

    ns16550DevInit (&ns16550Chan[i]);

        }

    if (ns16550Chan[0].channelMode == SIO_MODE_INT)

    {

        eumbbar_base[UDCR1] = 0x01; 

        eumbbar_base[ULCR1] = 0x80; 

        eumbbar_base[UAFR1] = 0x00;

        eumbbar_base[UDMB1] = 0x03; 

    eumbbar_base[UDLB1] = 0x64; 

    eumbbar_base[ULCR1] = 0x03; 

    eumbbar_base[UMCR1] = 0x02; 

    eumbbar_base[UIER1] = 0x03; 

    }

    if (ns16550Chan[1].channelMode == SIO_MODE_INT)

    {

        eumbbar_base[UDCR2] = 0x01; 

        eumbbar_base[ULCR2] = 0x80; 

        eumbbar_base[UAFR2] = 0x00;

        eumbbar_base[UDMB2] = 0x01; 

    eumbbar_base[UDLB2] = 0xB2; 

    eumbbar_base[ULCR2] = 0x03; 

    eumbbar_base[UMCR2] = 0x02; 

    eumbbar_base[UIER2] = 0x03; 

    }

}

1.4.2          安裝串行裝置的ISR

sysDuartHwInit2()由usrRoot任務中的sysClkConnnect()函數調用,安裝了裝置的中斷服務程式。這個函數在系統初始化之後執行,此時系統已經可以執行中斷連接配接了。

void sysSerialHwInit2 (void)

    {

    int i;

    for (i = 0; i < N_DUART_CHANNELS; i++)

        {

        (void) intConnect ((VOIDFUNCPTR *)((int)devDuartParas[i].vector),

                           (VOIDFUNCPTR)ns16550Int, (int)&ns16550Chan[i] );

        intEnable (devDuartParas[i].vector);

        }

}

1.4.3          串行裝置描述符與通道号的轉換

sysSerialChanGet()的作用是将串行裝置通道的索引轉換為該通道的裝置描述符。通常目标機代理會使用這個函數以獲得通道的指針,usrRoot()任務也會用到該函數。

SIO_CHAN * sysSerialChanGet

    (

    int channel        

    )

    {

    if ( (channel < 0) ||

         (channel >= (int)NELEMENTS(sysSerialSioChans)) )

    return (SIO_CHAN *) ERROR;

    return sysSerialSioChans[channel];

    }

繼續閱讀