serial.c

来自「freemodbus-v1-1-1-0.zip v1.1.1版本的代码 支持多」· C语言 代码 · 共 628 行 · 第 1/2 页

C
628
字号
                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_tsio_open( u8_t devnr ){    return sio_open_new( devnr, DEFAULT_BAUDRATE, DEFAULT_DATABITS,                         DEFAULT_STOPBITS, DEFAULT_PARITY );}voidsio_send_noisr( u8_t data, sio_fd_t fd ){    serdev_t       *dev = fd;    if( dev->ready )    {        UART_ByteSend( dev->UARTx, &data );    }}u32_tsio_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;}voidsio_send( u8_t data, sio_fd_t fd ){    while( sio_write( fd, &data, 1 ) != 1 );}u8_tsio_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_tsio_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_tsio_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;}voidsio_read_abort( sio_fd_t fd ){    volatile serdev_t *dev = fd;    dev->abort = 1;}voidsio_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;        }    }}voidsio_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 );}voidsio_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 + =
减小字号Ctrl + -
显示快捷键?