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

📄 serial.c

📁 一个开源的Modbus协议栈
💻 C
📖 第 1 页 / 共 2 页
字号:
                error = ERR_MEM;
            }
            else if( dev->rx_sem == ( xSemaphoreHandle ) 0 )
            {
                error = ERR_MEM;
            }
            else
            {
                /* UART parameter correct and hardware device available. */
                UART_OnOffConfig( dev->UARTx, ENABLE );
                UART_FifoConfig( dev->UARTx, ENABLE );
                UART_FifoReset( dev->UARTx, UART_RxFIFO );
                UART_FifoReset( dev->UARTx, UART_TxFIFO );
                UART_LoopBackConfig( dev->UARTx, DISABLE );
                UART_Config( dev->UARTx, baudrate, eUARTParity, eUARTStopBits, eUARTMode );
                UART_TimeOutPeriodConfig( dev->UARTx, 0xFF );
                UART_ItConfig( dev->UARTx, UART_RxBufFull, ENABLE );
                UART_RxConfig( dev->UARTx, ENABLE );

                /* Device is now ready for use. */
                dev->ready = 1;
            }

            if( error != ERR_OK )
            {
                sio_close( dev );
            }
            vPortExitCritical(  );
        }
    }
    else
    {
        error = ERR_VAL;
    }
    return error == ERR_OK ? ( void * )dev : SIO_FD_NULL;
}

sio_fd_t
sio_open( u8_t devnr )
{
    return sio_open_new( devnr, DEFAULT_BAUDRATE, DEFAULT_DATABITS,
                         DEFAULT_STOPBITS, DEFAULT_PARITY );
}

void
sio_send_noisr( u8_t data, sio_fd_t fd )
{
    serdev_t       *dev = fd;

    if( dev->ready )
    {
        UART_ByteSend( dev->UARTx, &data );
    }
}

u32_t
sio_write_noisr( sio_fd_t fd, u8_t * buf, u32_t size )
{
    u32_t           left = size;
    u8_t            send;
    serdev_t       *dev = fd;

    if( dev->ready )
    {
        left = size;
        while( left > 0 )
        {
            send = size % 256;
            UART_DataSend( dev->UARTx, ( u8 * ) buf, ( u8 ) send );
            left -= send;
        }
    }
    return size - left;
}

void
sio_send( u8_t data, sio_fd_t fd )
{
    while( sio_write( fd, &data, 1 ) != 1 );
}

u8_t
sio_recv( sio_fd_t fd )
{
    u8_t            data;
    serdev_t       *dev = fd;

    if( dev->ready )
    {
        while( sio_read( fd, &data, 1 ) != 1 );
    }
    else
    {
        LWIP_ASSERT( "sio_recv: dev->ready != 0 ", dev->ready != 0 );
        data = '\0';
    }
    return data;
}

u32_t
sio_read( sio_fd_t fd, u8_t * buf, u32_t size )
{
    u32_t           ch_left = size;
    u32_t           ch_received = 0;
    volatile serdev_t *dev = fd;

    if( dev->ready )
    {
        dev->abort = 0;
        while( ch_left && !dev->abort )
        {
            vPortEnterCritical(  );
            while( ( dev->rx_buf_cnt > 0 ) && ( ch_left > 0 ) )
            {
                /* Fetch character from the ring buffer. */
                *buf++ = dev->rx_buf[dev->rx_buf_rdpos];
                dev->rx_buf_rdpos = ( dev->rx_buf_rdpos + 1 ) % DEFAULT_RX_BUFSIZE;
                dev->rx_buf_cnt--;
                /* Count character received and left for read. */
                ch_left--;
                ch_received++;
            }
            vPortExitCritical(  );
            /* If we want more data block on the semaphore and wait until
             * something happens.
             */
            if( ch_left )
            {
                if( xSemaphoreTake( dev->rx_sem, MS_TO_TICKS( DEFAULT_READTIMEOUT_MS ) ) ==
                    pdFALSE )
                {
                    /* A timeout. Abort the read and return the characters 
                     * received so far. 
                     */
                    dev->abort = 1;
                }
            }
        }
    }
    return ch_received;
}

u32_t
sio_write( sio_fd_t fd, u8_t * buf, u32_t size )
{
    u32_t           ch_left;

    volatile serdev_t *dev = fd;

    if( dev->ready )
    {
        ch_left = size;
        while( ch_left > 0 )
        {
            vPortEnterCritical(  );
            while( ( dev->tx_buf_cnt < DEFAULT_TX_BUFSIZE ) && ( ch_left > 0 ) )
            {
                dev->tx_buf[dev->tx_buf_wrpos] = *buf++;
                dev->tx_buf_wrpos = ( dev->tx_buf_wrpos + 1 ) % DEFAULT_TX_BUFSIZE;
                dev->tx_buf_cnt++;
                ch_left--;
            }
            /* Enable transmit FIFO empty interrupts and block. */
            UART_ItConfig( dev->UARTx, UART_TxHalfEmpty, ENABLE );
            vPortExitCritical(  );

            /* Not all characters sent within one write. Block on a semaphore
             * which is triggered when the buffer is empty again.
             */
            if( ch_left != 0 )
            {
                while( xSemaphoreTake( dev->tx_sem, portMAX_DELAY ) != pdTRUE );
            }
        }
    }
    return size;
}

void
sio_read_abort( sio_fd_t fd )
{
    volatile serdev_t *dev = fd;

    dev->abort = 1;
}

void
sio_serial_isr( UART_TypeDef * UARTx, u8_t * need_ctx_switch )
{
    int             i;
    u16             status;
    volatile serdev_t *dev = SIO_FD_NULL;

    portBASE_TYPE   rx_woken = pdFALSE;
    portBASE_TYPE   tx_woken = pdFALSE;

    for( i = 0; i < UART_DEVICES_MAX; i++ )
    {
        if( devices[i].ready && ( devices[i].UARTx == UARTx ) )
        {
            dev = &devices[i];
            break;
        }
    }
    if( dev != SIO_FD_NULL )
    {
        status = UART_FlagStatus( dev->UARTx );

        /* If there are characters in the UART fifo place them into the 
         * ring buffer. In case the buffer is filled half or the requested
         * number of bytes has been read wakeup the receiver.
         */
        if( status & UART_RxBufFull )
        {
            do
            {
                /* Store the character in the ring buffer and advance write
                 * position. */
                dev->rx_buf[dev->rx_buf_wrpos] = dev->UARTx->RxBUFR;
                dev->rx_buf_wrpos = ( dev->rx_buf_wrpos + 1 ) % DEFAULT_RX_BUFSIZE;

                /* Increment the receiver buffer counter. Check for a buffer
                 * overrun. In that case we have overwritten a old character.
                 * Therefore we have to advance the read position. Note that
                 * in this error case we must not increment the read counter
                 * because an old character was lost.
                 */
                if( dev->rx_buf_cnt >= DEFAULT_RX_BUFSIZE )
                {
                    /* LWIP_ASSERT( "sio_serial_isr: receiver buffer overflow", 0 ); */
                    dev->rx_buf_rdpos = ( dev->rx_buf_rdpos + 1 ) % DEFAULT_RX_BUFSIZE;
                }
                else
                {
                    dev->rx_buf_cnt++;
                }

                /* Get the new status from the UART. */
                status = UART_FlagStatus( dev->UARTx );
            }
            while( status & UART_RxBufFull );

            /* Wakeup receiver if buffer is starting to fill. */
            if( dev->rx_buf_cnt > ( DEFAULT_RX_BUFSIZE / 2 ) )
            {
                rx_woken = xSemaphoreGiveFromISR( dev->rx_sem, rx_woken );
            }
        }

        /* Check if we must send characters. */
        if( ( dev->tx_buf_cnt > 0 ) && ( status & UART_TxHalfEmpty ) )
        {
            do
            {
                /* Fetch character from the ring buffer and place them into
                 * the FIFO. */
                dev->UARTx->TxBUFR = dev->tx_buf[dev->tx_buf_rdpos];
                dev->tx_buf_rdpos = ( dev->tx_buf_rdpos + 1 ) % DEFAULT_TX_BUFSIZE;
                dev->tx_buf_cnt--;

                /* Get the new status from the UART. */
                status = UART_FlagStatus( dev->UARTx );
            }
            while( ( dev->tx_buf_cnt > 0 ) && ( status & UART_TxHalfEmpty ) );

            if( dev->tx_buf_cnt == 0 )
            {
                tx_woken = xSemaphoreGiveFromISR( dev->tx_sem, tx_woken );
                UART_ItConfig( dev->UARTx, UART_TxHalfEmpty, DISABLE );
            }
        }

        if( tx_woken || rx_woken )
        {
            *need_ctx_switch = 1;
        }
    }
}


void
sio_uart0_irq( void )
{
    /* Save context to stack. */
    portENTER_SWITCHING_ISR(  );

    static u8_t     need_ctx_switch;

    sio_serial_isr( UART0, &need_ctx_switch );

    /* End the interrupt in the EIC. */
    EIC->IPR |= 1 << EIC_CurrentIRQChannelValue(  );

    /* End the ISR. */
    portEXIT_SWITCHING_ISR( need_ctx_switch ? pdTRUE : pdFALSE );
}

void
sio_uart1_irq( void )
{
    /* Save context to stack. */
    portENTER_SWITCHING_ISR(  );

    static u8_t     need_ctx_switch;

    sio_serial_isr( UART1, &need_ctx_switch );

    /* End the interrupt in the EIC. */
    EIC->IPR |= 1 << EIC_CurrentIRQChannelValue(  );

    /* End the ISR. */
    portEXIT_SWITCHING_ISR( need_ctx_switch ? pdTRUE : pdFALSE );
}

⌨️ 快捷键说明

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