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 + -
显示快捷键?