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

📄 at91sio.c

📁 vwworks 在 at91rm9200上的bsp配置
💻 C
📖 第 1 页 / 共 2 页
字号:
    AT91_SIO_CHAN * pChan = (AT91_SIO_CHAN *)pSioChan;

    status = OK;    /* preset to return OK */

    switch (request)
        {
        case SIO_BAUD_SET:
            /*
             * Set the baud rate. Return EIO for an invalid baud rate, or
             * OK on success.
             *
             * Calculate the baud rate divisor: it must be non-zero and must
             * fit in a 16-bit register.
             */

            brd = pChan->xtal / (16 * arg);

            if (brd & ~0xFFFF)
                {
                status = EIO;       /* baud rate out of range */
                break;
                }


            AT91_USART_REG_WRITE (pChan, AT91_US_BRGR, brd);

            pChan->baudRate = arg;

            break;


        case SIO_BAUD_GET:

            /* Get the baud rate and return OK */

            *(int *)arg = pChan->baudRate;
            break;


        case SIO_MODE_SET:
            /*
             * Set the mode (e.g., to interrupt or polled). Return OK
             * or EIO for an unknown or unsupported mode.
             */

            if ((arg != SIO_MODE_POLL) && (arg != SIO_MODE_INT))
                {
                status = EIO;
                break;
                }

            oldlevel = intLock ();

            if (arg == SIO_MODE_INT)
                {
                /* Enable appropriate interrupt */

                if (pChan->isUsart)
                    {
                    intEnable (pChan->level);
                    }
                else
                    {
                    sysPeripheralIntEnable(pChan->level);
                    }
                }
            else
                {
                /* Disable the interrupt */
                if (pChan->isUsart)
                    {
                    intDisable (pChan->level);
                    }
                else
                    {
                    sysPeripheralIntDisable(pChan->level);
                    }
                }

            pChan->channelMode = arg;

            intUnlock (oldlevel);
            break;


        case SIO_MODE_GET:

            /* Get the current mode and return OK */

            *(int *)arg = pChan->channelMode;
            break;


        case SIO_AVAIL_MODES_GET:

            /* Get the available modes and return OK */

            *(int *)arg = SIO_MODE_INT | SIO_MODE_POLL;
            break;


        case SIO_HW_OPTS_SET:

            /*
             * Optional command to set the hardware options (as defined
             * in sioLib.h).
             * Return OK, or ENOSYS if this command is not implemented.
             * Note: several hardware options are specified at once.
             * This routine should set as many as it can and then return
             * OK. The SIO_HW_OPTS_GET is used to find out which options
             * were actually set.
             */

        case SIO_HW_OPTS_GET:

            /*
             * Optional command to get the hardware options (as defined
             * in sioLib.h). Return OK or ENOSYS if this command is not
             * implemented.  Note: if this command is unimplemented, it
             * will be assumed that the driver options are CREAD | CS8
             * (e.g., eight data bits, one stop bit, no parity, ints enabled).
             */

        default:
            status = ENOSYS;
        }

    return status;

    }

/*******************************************************************************
*
* at91SioInt - handle an interrupt
*
* This routine handles interrupts from the USART.
*
* RETURNS: N/A
*/

void at91SioInt
    (
    AT91_SIO_CHAN *	pChan   /* ptr to AT91_SIO_CHAN describing this chan */
    )
    {
#ifndef AT91_USE_PDC
    UINT32  ch;     /* Possible char to be in/output */
#endif
    UINT32  status;     /* Status from USART */
    UINT32  imr;        /* interrupt mask register */
#ifdef AT91_USE_PDC
    UINT8 * ptr;
    int     count;
#endif


    /* read status register and mask register */

    AT91_USART_REG_READ (pChan, AT91_US_CSR, status);
    AT91_USART_REG_READ (pChan, AT91_US_IMR, imr);

#ifndef AT91_USE_PDC
    if (status & AT91_US_RXRDY)        /* data? */
        {
        AT91_USART_REG_READ (pChan, AT91_US_RHR, ch);      /* read character */
        (*pChan->putRcvChar) (pChan->putRcvArg, (char)ch); /* pass it on */
        }
#else /* AT91_USE_PDC */
    if (status & AT91_US_TIMEOUT)
        {
        /* restart timeout */
        if (pChan->isUsart)
            {
            AT91_USART_REG_WRITE (pChan, AT91_US_CR, AT91_US_STTTO);
            }
        }

    /*
     * Read the Receiver Peripheral Data Controller count. It was originally
     * set to the size of the receive buffer.
     */

    AT91_USART_REG_READ (pChan, AT91_US_RCR, count);

    while (count < AT91_RXBUFF_SIZE)
        {
        /*
         * then characters have been received into the buffer - setup
         * PDC to use the other swing-buffer whilst we deal with this
         * one.
         */
        AT91_USART_REG_WRITE (pChan, AT91_US_RCR, 0);   /* stop Rx PDC */

        /* reset ptr to beginning of new buffer  */
        if (pChan->buffInUse == 0)
            {
            ptr = &pChan->rxBuffA[0];   /* ptr to beginning of Rx buffer */
            AT91_USART_REG_WRITE (pChan, AT91_US_RPR, (UINT32)(pChan->rxBuffB));
            pChan->buffInUse = 1;
            }
        else
            {
            ptr = &pChan->rxBuffB[0];   /* ptr to beginning of Rx buffer */
            AT91_USART_REG_WRITE (pChan, AT91_US_RPR, (UINT32)(pChan->rxBuffA));
            pChan->buffInUse = 0;
            }

        /* reset count to size of buffer and restart timeout  */
        AT91_USART_REG_WRITE (pChan, AT91_US_RCR, AT91_RXBUFF_SIZE);

        if (pChan->isUsart)
            {
            AT91_USART_REG_WRITE (pChan, AT91_US_CR, AT91_US_STTTO);
            }

        /* read chars from buffer and pass on to installed callback rtn */
        while (count < AT91_RXBUFF_SIZE)
            {
            /* while there are chars in buffer we have not yet passed on */
            (*pChan->putRcvChar) (pChan->putRcvArg, *ptr++); /* pass it on */
            count++;
            }

        /* reread PDC Rx count */
        AT91_USART_REG_READ (pChan, AT91_US_RCR, count);
        } /* endwhile */
#endif /* AT91_USE_PDC */

#ifndef AT91_USE_PDC
    /*
     * There is a THR and the Tx Shift Register, so we may be able to push
     * two characters into the USART.
     */
    status &= imr;

    if (status & AT91_US_TXRDY)  /* if THR is empty */
        {
        if (((*pChan->getTxChar) (pChan->getTxArg, &ch)) != ERROR)
            {
            AT91_USART_REG_WRITE(pChan, AT91_US_THR, ch);   /* tx char */
            }
        else /* no more chars to send - disable transmitter interrupts */
            {
            AT91_USART_REG_WRITE (pChan, AT91_US_IDR, AT91_US_TXRDY);
            }
        }
#else /* AT91_USE_PDC */
    
    /* ENDTX interrupt => Tx is required */
    if (status & AT91_US_ENDTX)    
        {
        count = 0;

        ptr = pChan->txBuff; /* ptr to beginning of Tx buffer */

        do
            {
            if ((*pChan->getTxChar) (pChan->getTxArg, ptr++) == ERROR)
                {
                break;
                }
            
            count++;
            }
        while (count < AT91_TXBUFF_SIZE);

        /* If nothing more to transmit, so disable ENDTX interrupt */
        if (count == 0)
            {
            AT91_USART_REG_WRITE (pChan, AT91_US_IDR, AT91_US_ENDTX);
            }
        else
            {
            /* reset ptr to beginning of buffer and count to size of buffer */
            AT91_USART_REG_WRITE (pChan, AT91_US_TPR, (UINT32)(pChan->txBuff));
            AT91_USART_REG_WRITE (pChan, AT91_US_TCR, count);
            }
        } /* endif ENDTX was enabled */
#endif /* AT91_USE_PDC */
    }

/*******************************************************************************
*
* at91SioTxStartup - transmitter startup routine
*
* Call interrupt level char output routine and enable interrupt
*
* RETURNS: OK on success, ENOSYS if the device is polled-only, or
* EIO on hardware error.
*/

LOCAL int at91SioTxStartup
    (
    SIO_CHAN *	pSioChan	/* ptr to SIO_CHAN describing this channel */
    )
    {
    AT91_SIO_CHAN * pChan = (AT91_SIO_CHAN *)pSioChan;

    if (pChan->channelMode == SIO_MODE_INT)
        {
        /* Enable Transmitter interrupts */

#ifndef AT91_USE_PDC
        AT91_USART_REG_WRITE (pChan, AT91_US_IER, AT91_US_TXRDY);
#else
        AT91_USART_REG_WRITE (pChan, AT91_US_IER, AT91_US_ENDTX);
#endif
        return OK;
        }
    else
        return ENOSYS;
    }

/******************************************************************************
*
* at91SioPollOutput - output a character in polled mode.
*
* RETURNS: OK if a character arrived, EIO on device error, EAGAIN
* if the output buffer is full, ENOSYS if the device is interrupt-only.
*/

LOCAL int at91SioPollOutput
    (
    SIO_CHAN *	pSioChan,	/* ptr to SIO_CHAN describing this channel */
    char	    outChar 	/* char to output */
    )
    {
    AT91_SIO_CHAN * pChan = (AT91_SIO_CHAN *)pSioChan;
    UINT32 pollStatus;

    AT91_USART_REG_READ (pChan, AT91_US_CSR, pollStatus);

    /* is the transmitter ready to accept a character? */

    if ((pollStatus & AT91_US_TXRDY) == 0)
        return EAGAIN;


    /* write out the character */

    AT91_USART_REG_WRITE (pChan, AT91_US_THR, outChar); /* transmit character */

    return OK;
    }

/******************************************************************************
*
* at91SioPollInput - poll the device for input.
*
* RETURNS: OK if a character arrived, EIO on device error, EAGAIN
* if the input buffer is empty, ENOSYS if the device is interrupt-only.
*/

LOCAL int at91SioPollInput
    (
    SIO_CHAN *  pSioChan,   /* ptr to SIO_CHAN describing this channel */
    char *  thisChar    /* pointer to where to return character */
    )
    {
    AT91_SIO_CHAN * pChan = (AT91_SIO_CHAN *)pSioChan;
    UINT32 pollStatus;

    AT91_USART_REG_READ (pChan, AT91_US_CSR, pollStatus);

    if ((pollStatus & AT91_US_RXRDY) == 0)
        return EAGAIN;


    /* got a character */

    AT91_USART_REG_READ (pChan, AT91_US_RHR, *thisChar);

    return OK;
    }

/******************************************************************************
*
* at91SioCallbackInstall - install ISR callbacks to get/put chars.
*
* This routine installs interrupt callbacks for transmitting characters
* and receiving characters.
*
* RETURNS: OK on success, or ENOSYS for an unsupported callback type.
*
*/

LOCAL int at91SioCallbackInstall
    (
    SIO_CHAN *  pSioChan,   /* ptr to SIO_CHAN describing this channel */
    int     callbackType,   /* type of callback */
    STATUS  (*callback)(),  /* callback */
    void *  callbackArg     /* parameter to callback */
    
    )
    {
    AT91_SIO_CHAN * pChan = (AT91_SIO_CHAN *)pSioChan;

    switch (callbackType)
        {
        case SIO_CALLBACK_GET_TX_CHAR:
            pChan->getTxChar = callback;
            pChan->getTxArg  = callbackArg;
            return OK;

        case SIO_CALLBACK_PUT_RCV_CHAR:
            pChan->putRcvChar = callback;
            pChan->putRcvArg  = callbackArg;
            return OK;

        default:
            return ENOSYS;
        }
    }

#endif /* INCLUDE_SERIAL */

⌨️ 快捷键说明

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