📄 serial.c
字号:
/*
* FreeModbus Libary: STR71/lwIP Port serial driver.
* Copyright (C) 2006 Christian Walter <wolti@sil.at>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* File: $Id: serial.c,v 1.4 2006/09/04 20:38:50 wolti Exp $
*/
/* ----------------------- Platform includes --------------------------------*/
#include "uart.h"
#include "eic.h"
#include "gpio.h"
/* ----------------------- lwIP includes ------------------------------------*/
#include "lwip/opt.h"
#include "lwip/sys.h"
#include "lwip/sio.h"
#include "lwip/err.h"
/* ----------------------- FreeRTOS includes --------------------------------*/
#include "task.h"
#include "semphr.h"
/* ----------------------- Project includes ---------------------------------*/
#include "serial.h"
/* ----------------------- Defines ------------------------------------------*/
#define UART0_DEV ( UART0 )
#define UART0_RX_PORT ( GPIO0 )
#define UART0_RX_PIN ( 8 )
#define UART0_TX_PORT ( GPIO0 )
#define UART0_TX_PIN ( 9 )
#define UART0_IRQ_CH ( UART0_IRQChannel )
#define UART0_IRQ_PRIORITY ( 1 )
#define UART1_DEV ( UART1 )
#define UART1_RX_PORT ( GPIO0 )
#define UART1_RX_PIN ( 10 )
#define UART1_TX_PORT ( GPIO0 )
#define UART1_TX_PIN ( 11 )
#define UART1_IRQ_CH ( UART1_IRQChannel )
#define UART1_IRQ_PRIORITY ( 1 )
#define UART_DEVICES_MAX ( 2 )
#define DEFAULT_BAUDRATE ( 38400 )
#define DEFAULT_DATABITS ( 8 )
#define DEFAULT_STOPBITS ( 1 )
#define DEFAULT_PARITY ( SIO_PAR_NONE )
#define DEFAULT_TX_BUFSIZE ( 64 )
#define DEFAULT_RX_BUFSIZE ( 64 )
#define DEFAULT_READTIMEOUT_MS ( 10 )
#define SIO_RESET_STATE( dev ) do { \
( dev )->ready = 0; \
( dev )->abort = 0; \
( dev )->UARTx = NULL; \
( dev )->rx_buf_rdpos = ( dev )->rx_buf_wrpos = 0; \
( dev )->rx_sem = SYS_SEM_NULL; \
( dev )->tx_buf_rdpos = ( dev )->tx_buf_wrpos = 0; \
( dev )->tx_sem = SYS_SEM_NULL; \
} while( 0 )
#define MS_TO_TICKS( ms ) \
( portTickType )( ( portTickType ) ( ms ) / portTICK_RATE_MS )
/* ----------------------- Type definitions ---------------------------------*/
typedef struct
{
u8_t ready;
u8_t abort;
u8_t rx_buf[DEFAULT_RX_BUFSIZE];
u8_t rx_buf_rdpos;
u8_t rx_buf_wrpos;
u8_t rx_buf_cnt;
xSemaphoreHandle rx_sem;
u8_t tx_buf[DEFAULT_TX_BUFSIZE];
u8_t tx_buf_rdpos;
u8_t tx_buf_wrpos;
u8_t tx_buf_cnt;
xSemaphoreHandle tx_sem;
UART_TypeDef *UARTx;
} serdev_t;
/* ----------------------- Prototypes ---------------------------------------*/
void sio_uart0_irq( void ) __attribute__ ( ( naked ) );
void sio_uart1_irq( void ) __attribute__ ( ( naked ) );
/* ----------------------- Static functions ---------------------------------*/
static err_t sio_open_low_level( u8_t devnr, serdev_t * dev );
static err_t sio_close_low_level( u8_t devnr, serdev_t * dev );
/* ----------------------- Static variables ---------------------------------*/
static u8_t initialized = FALSE;
static volatile serdev_t devices[UART_DEVICES_MAX];
/* ----------------------- Start implementation -----------------------------*/
err_t
sio_open_low_level( u8_t devnr, serdev_t * dev )
{
err_t error = ERR_OK;
if( devnr == 0 )
{
/* Return value. */
dev->UARTx = UART0;
/* Reset the UART. */
UART_Init( dev->UARTx );
/* Configure the GPIO pints for the UART device. */
GPIO_Config( UART0_TX_PORT, 1 << UART0_TX_PIN, GPIO_AF_PP );
GPIO_Config( UART0_RX_PORT, 1 << UART0_RX_PIN, GPIO_IN_TRI_CMOS );
/* Configure the IEC for the UART interrupts. */
EIC_IRQChannelPriorityConfig( UART0_IRQ_CH, UART0_IRQ_PRIORITY );
EIC_IRQChannelConfig( UART0_IRQ_CH, ENABLE );
}
else if( devnr == 1 )
{
/* Return value. */
dev->UARTx = UART1;
/* Reset the UART. */
UART_Init( dev->UARTx );
/* Configure the GPIO pints for the UART device. */
GPIO_Config( UART1_TX_PORT, 1 << UART1_TX_PIN, GPIO_AF_PP );
GPIO_Config( UART1_RX_PORT, 1 << UART1_RX_PIN, GPIO_IN_TRI_TTL );
/* Configure the EIC for the UART interrupts. */
EIC_IRQChannelPriorityConfig( UART1_IRQ_CH, UART1_IRQ_PRIORITY );
EIC_IRQChannelConfig( UART1_IRQ_CH, ENABLE );
}
else
{
error = ERR_IF;
}
return error;
}
err_t
sio_close_low_level( u8_t devnr, serdev_t * dev )
{
err_t error = ERR_OK;
if( devnr == 0 )
{
UART_Init( dev->UARTx );
/* Disable the GPIO pints for the UART device. */
GPIO_Config( UART0_TX_PORT, 1 << UART1_TX_PIN, GPIO_IN_TRI_TTL );
GPIO_Config( UART0_RX_PORT, 1 << UART1_RX_PIN, GPIO_IN_TRI_TTL );
/* Disable the UART interrupts in the EIC. */
EIC_IRQChannelConfig( UART0_IRQ_CH, DISABLE );
}
else if( devnr == 1 )
{
UART_Init( dev->UARTx );
/* Disable the GPIO pints for the UART device. */
GPIO_Config( UART1_TX_PORT, 1 << UART1_TX_PIN, GPIO_IN_TRI_TTL );
GPIO_Config( UART1_RX_PORT, 1 << UART1_RX_PIN, GPIO_IN_TRI_TTL );
/* Disable the UART interrupts in the EIC. */
EIC_IRQChannelConfig( UART1_IRQ_CH, DISABLE );
}
else
{
error = ERR_IF;
}
return error;
}
err_t
sio_close( serdev_t * dev )
{
int i;
err_t error = ERR_VAL;
for( i = 0; i < UART_DEVICES_MAX; i++ )
{
if( &devices[i] == dev )
{
break;
}
}
if( i < UART_DEVICES_MAX )
{
vPortEnterCritical( );
error = sio_close_low_level( i, dev );
vPortExitCritical( );
if( dev->tx_sem != ( xSemaphoreHandle ) 0 )
{
vQueueDelete( dev->tx_sem );
}
if( dev->rx_sem != ( xSemaphoreHandle ) 0 )
{
vQueueDelete( dev->tx_sem );
}
SIO_RESET_STATE( dev );
}
return error;
}
sio_fd_t
sio_open_new( u8_t devnr, u32_t baudrate, u8_t databits, sio_stop_t stopbits, sio_parity_t parity )
{
int i;
err_t error = ERR_OK;
serdev_t *dev;
UARTParity_TypeDef eUARTParity = UART_NO_PARITY;
UARTMode_TypeDef eUARTMode = UARTM_8D;
UARTStopBits_TypeDef eUARTStopBits;
if( !initialized )
{
for( i = 0; i < UART_DEVICES_MAX; i++ )
{
SIO_RESET_STATE( &devices[i] );
}
initialized = 1;
}
/* Check if devicename is valid and not in use. */
if( ( devnr < UART_DEVICES_MAX ) && ( devices[devnr].ready == 0 ) )
{
dev = ( serdev_t * ) & devices[devnr];
switch ( parity )
{
case SIO_PAR_EVEN:
eUARTParity = UART_EVEN_PARITY;
break;
case SIO_PAR_ODD:
eUARTParity = UART_ODD_PARITY;
break;
case SIO_PAR_NONE:
eUARTParity = UART_NO_PARITY;
break;
default:
error = ERR_VAL;
}
switch ( databits )
{
case 7:
if( parity != SIO_PAR_NONE )
{
eUARTMode = UARTM_7D_P;
}
break;
case 8:
eUARTMode = parity == SIO_PAR_NONE ? UARTM_8D : UARTM_8D_P;
break;
default:
error = ERR_VAL;
}
switch ( stopbits )
{
case SIO_STOP_0_5:
eUARTStopBits = UART_0_5_StopBits;
break;
case SIO_STOP_1:
eUARTStopBits = UART_1_StopBits;
break;
case SIO_STOP_1_5:
eUARTStopBits = UART_1_5_StopBits;
break;
case SIO_STOP_2:
eUARTStopBits = UART_2_StopBits;
break;
default:
error = ERR_VAL;
}
if( error == ERR_OK )
{
SIO_RESET_STATE( dev );
vSemaphoreCreateBinary( dev->rx_sem );
vSemaphoreCreateBinary( dev->tx_sem );
vPortEnterCritical( );
if( ( error = sio_open_low_level( devnr, dev ) ) != ERR_OK )
{
/* Hardware interface does not exist. */
}
else if( dev->tx_sem == ( xSemaphoreHandle ) 0 )
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -