Browse Source

Don't use strerror in apps/modbus; Add CONFIG_MB_TERMIOS to enable/suppress use of termios.h interfaces

git-svn-id: https://nuttx.svn.sourceforge.net/svnroot/nuttx/trunk@4968 7fd9a85b-ad96-42d3-883c-3090e2eb8679
sbg
patacongo 13 years ago
parent
commit
ad37fa6505
  1. 6
      apps/ChangeLog.txt
  2. 9
      apps/modbus/Kconfig
  3. 4
      apps/modbus/README.txt
  4. 30
      apps/modbus/nuttx/portother.c
  5. 84
      apps/modbus/nuttx/portserial.c

6
apps/ChangeLog.txt

@ -255,5 +255,7 @@ @@ -255,5 +255,7 @@
has been added to the NuttX apps/ source tree.
* apps/examples/modbus: A port of the freemodbus-v1.5.0 "demo"
program that will be used to verify the FreeModBus port
* apps/modbus: Don't use strerror(). It is just too big.
* apps/modbus: Add CONFIG_MB_TERMIOS. If the driver doesn't support
termios ioctls, then don't bother trying to configure the baud, parity
etc.

9
apps/modbus/Kconfig

@ -24,6 +24,15 @@ config MB_TCP_ENABLED @@ -24,6 +24,15 @@ config MB_TCP_ENABLED
depends on MODBUS
default y
config MB_TERMIOS
bool "Driver TERMIOS supported"
depends on MB_ASCII_ENABLED || MB_RTU_ENABLED
default n
---help---
Serial driver supports termios.h interfaces (tcsetattr, tcflush, etc.).
If this is not defined, then the terminal settings (baud, parity, etc).
are not configurable at runtime; serial streams will not be flushed when closed.
config MB_ASCII_TIMEOUT_SEC
int "Character timeout"
depends on MB_ASCII_ENABLED

4
apps/modbus/README.txt

@ -60,6 +60,10 @@ The NuttX-named configuration options that are available include: @@ -60,6 +60,10 @@ The NuttX-named configuration options that are available include:
CONFIG_MB_ASCII_ENABLED - Modbus ASCII support
CONFIG_MB_RTU_ENABLED - Modbus RTU support
CONFIG_MB_TCP_ENABLED - Modbus TCP support
CONFIG_MB_TERMIOS - Serial driver supports termios.h interfaces (tcsetattr,
tcflush, etc.). If this is not defined, then the terminal settings (baud,
parity, etc.) are not configurable at runtime; serial streams will not be
flushed when closed.
CONFIG_MB_ASCII_TIMEOUT_SEC - Character timeout value for Modbus ASCII. The
character timeout value is not fixed for Modbus ASCII and is therefore
a configuration option. It should be set to the maximum expected delay

30
apps/modbus/nuttx/portother.c

@ -22,6 +22,7 @@ @@ -22,6 +22,7 @@
*/
/* ----------------------- Standard includes --------------------------------*/
#include <nuttx/config.h>
#include <stdio.h>
#include <stdlib.h>
@ -33,32 +34,33 @@ @@ -33,32 +34,33 @@
#include "port.h"
/* ----------------------- Modbus includes ----------------------------------*/
#include <apps/modbus/mb.h>
#include <apps/modbus/mbport.h>
/* ----------------------- Defines ------------------------------------------*/
#define NELEMS(x) (sizeof((x))/sizeof((x)[0]))
/* ----------------------- Static variables ---------------------------------*/
static FILE *fLogFile = NULL;
static eMBPortLogLevel eLevelMax = MB_LOG_DEBUG;
static pthread_mutex_t xLock = PTHREAD_MUTEX_INITIALIZER;
/* ----------------------- Start implementation -----------------------------*/
void
vMBPortLogLevel( eMBPortLogLevel eNewLevelMax )
void vMBPortLogLevel(eMBPortLogLevel eNewLevelMax)
{
eLevelMax = eNewLevelMax;
}
void
vMBPortLogFile( FILE * fNewLogFile )
void vMBPortLogFile(FILE * fNewLogFile)
{
fLogFile = fNewLogFile;
}
void
vMBPortLog( eMBPortLogLevel eLevel, const char * szModule, const char * szFmt, ... )
void vMBPortLog(eMBPortLogLevel eLevel, const char * szModule, const char * szFmt, ...)
{
char szBuf[512];
int i;
@ -85,20 +87,20 @@ vMBPortLog( eMBPortLogLevel eLevel, const char * szModule, const char * szFmt, . @@ -85,20 +87,20 @@ vMBPortLog( eMBPortLogLevel eLevel, const char * szModule, const char * szFmt, .
}
}
void
vMBPortEnterCritical( void )
void vMBPortEnterCritical(void)
{
if( pthread_mutex_lock( &xLock ) != 0 )
int ret = pthread_mutex_lock(&xLock);
if (ret != 0)
{
vMBPortLog( MB_LOG_ERROR, "OTHER", "Locking primitive failed: %s\n", strerror( errno ) );
vMBPortLog(MB_LOG_ERROR, "OTHER", "Locking primitive failed: %d\n", ret);
}
}
void
vMBPortExitCritical( void )
void vMBPortExitCritical(void)
{
if( pthread_mutex_unlock( &xLock ) != 0 )
int ret = pthread_mutex_unlock(&xLock);
if (ret != 0)
{
vMBPortLog( MB_LOG_ERROR, "OTHER", "Locking primitive failed: %s\n", strerror( errno ) );
vMBPortLog(MB_LOG_ERROR, "OTHER", "Locking primitive failed: %d\n", ret);
}
}

84
apps/modbus/nuttx/portserial.c

@ -22,6 +22,7 @@ @@ -22,6 +22,7 @@
*/
/* ----------------------- Standard includes --------------------------------*/
#include <nuttx/config.h>
#include <stdio.h>
#include <stdlib.h>
@ -31,17 +32,22 @@ @@ -31,17 +32,22 @@
#include <sys/stat.h>
#include <sys/select.h>
#include <fcntl.h>
#include <termios.h>
#include <unistd.h>
#include <assert.h>
#ifdef CONFIG_MB_TERMIOS
# include <termios.h>
#endif
#include "port.h"
/* ----------------------- Modbus includes ----------------------------------*/
#include <apps/modbus/mb.h>
#include <apps/modbus/mbport.h>
/* ----------------------- Defines -----------------------------------------*/
#ifdef CONFIG_MB_ASCII_ENABLED
#define BUF_SIZE 513 /* must hold a complete ASCII frame. */
#else
@ -49,6 +55,7 @@ @@ -49,6 +55,7 @@
#endif
/* ----------------------- Static variables ---------------------------------*/
static int iSerialFd = -1;
static bool bRxEnabled;
static bool bTxEnabled;
@ -58,22 +65,28 @@ static uint8_t ucBuffer[BUF_SIZE]; @@ -58,22 +65,28 @@ static uint8_t ucBuffer[BUF_SIZE];
static int uiRxBufferPos;
static int uiTxBufferPos;
#ifdef CONFIG_MB_TERMIOS
static struct termios xOldTIO;
#endif
/* ----------------------- Function prototypes ------------------------------*/
static bool prvbMBPortSerialRead(uint8_t *pucBuffer, uint16_t usNBytes, uint16_t *usNBytesRead);
static bool prvbMBPortSerialWrite(uint8_t *pucBuffer, uint16_t usNBytes);
/* ----------------------- Begin implementation -----------------------------*/
void
vMBPortSerialEnable( bool bEnableRx, bool bEnableTx )
void vMBPortSerialEnable(bool bEnableRx, bool bEnableTx)
{
/* it is not allowed that both receiver and transmitter are enabled. */
ASSERT(!bEnableRx || !bEnableTx);
if (bEnableRx)
{
#ifdef CONFIG_MB_TERMIOS
(void)tcflush(iSerialFd, TCIFLUSH);
#endif
uiRxBufferPos = 0;
bRxEnabled = true;
}
@ -81,6 +94,7 @@ vMBPortSerialEnable( bool bEnableRx, bool bEnableTx ) @@ -81,6 +94,7 @@ vMBPortSerialEnable( bool bEnableRx, bool bEnableTx )
{
bRxEnabled = false;
}
if (bEnableTx)
{
bTxEnabled = true;
@ -92,26 +106,30 @@ vMBPortSerialEnable( bool bEnableRx, bool bEnableTx ) @@ -92,26 +106,30 @@ vMBPortSerialEnable( bool bEnableRx, bool bEnableTx )
}
}
bool
xMBPortSerialInit( uint8_t ucPort, uint32_t ulBaudRate, uint8_t ucDataBits, eMBParity eParity )
bool xMBPortSerialInit(uint8_t ucPort, uint32_t ulBaudRate,
uint8_t ucDataBits, eMBParity eParity)
{
char szDevice[16];
bool bStatus = true;
#ifdef CONFIG_MB_TERMIOS
struct termios xNewTIO;
speed_t xNewSpeed;
#endif
snprintf(szDevice, 16, "/dev/ttyS%d", ucPort);
if ((iSerialFd = open(szDevice, O_RDWR | O_NOCTTY)) < 0)
{
vMBPortLog( MB_LOG_ERROR, "SER-INIT", "Can't open serial port %s: %s\n", szDevice,
strerror( errno ) );
vMBPortLog(MB_LOG_ERROR, "SER-INIT", "Can't open serial port %s: %d\n",
szDevice, errno);
}
#ifdef CONFIG_MB_TERMIOS
else if (tcgetattr(iSerialFd, &xOldTIO) != 0)
{
vMBPortLog( MB_LOG_ERROR, "SER-INIT", "Can't get settings from port %s: %s\n", szDevice,
strerror( errno ) );
vMBPortLog(MB_LOG_ERROR, "SER-INIT", "Can't get settings from port %s: %d\n",
szDevice, errno);
}
else
{
@ -132,6 +150,7 @@ xMBPortSerialInit( uint8_t ucPort, uint32_t ulBaudRate, uint8_t ucDataBits, eMBP @@ -132,6 +150,7 @@ xMBPortSerialInit( uint8_t ucPort, uint32_t ulBaudRate, uint8_t ucDataBits, eMBP
default:
bStatus = false;
}
switch (ucDataBits)
{
case 8:
@ -143,6 +162,7 @@ xMBPortSerialInit( uint8_t ucPort, uint32_t ulBaudRate, uint8_t ucDataBits, eMBP @@ -143,6 +162,7 @@ xMBPortSerialInit( uint8_t ucPort, uint32_t ulBaudRate, uint8_t ucDataBits, eMBP
default:
bStatus = false;
}
switch (ulBaudRate)
{
case 9600:
@ -163,22 +183,23 @@ xMBPortSerialInit( uint8_t ucPort, uint32_t ulBaudRate, uint8_t ucDataBits, eMBP @@ -163,22 +183,23 @@ xMBPortSerialInit( uint8_t ucPort, uint32_t ulBaudRate, uint8_t ucDataBits, eMBP
default:
bStatus = false;
}
if (bStatus)
{
if (cfsetispeed(&xNewTIO, xNewSpeed) != 0)
{
vMBPortLog( MB_LOG_ERROR, "SER-INIT", "Can't set baud rate %ld for port %s: %s\n",
ulBaudRate, strerror( errno ) );
vMBPortLog(MB_LOG_ERROR, "SER-INIT", "Can't set baud rate %ld for port %s: %d\n",
ulBaudRate, errno);
}
else if (cfsetospeed(&xNewTIO, xNewSpeed) != 0)
{
vMBPortLog( MB_LOG_ERROR, "SER-INIT", "Can't set baud rate %ld for port %s: %s\n",
ulBaudRate, szDevice, strerror( errno ) );
vMBPortLog(MB_LOG_ERROR, "SER-INIT", "Can't set baud rate %ld for port %s: %d\n",
ulBaudRate, szDevice, errno);
}
else if (tcsetattr(iSerialFd, TCSANOW, &xNewTIO) != 0)
{
vMBPortLog( MB_LOG_ERROR, "SER-INIT", "Can't set settings for port %s: %s\n",
szDevice, strerror( errno ) );
vMBPortLog(MB_LOG_ERROR, "SER-INIT", "Can't set settings for port %s: %d\n",
szDevice, errno);
}
else
{
@ -187,11 +208,12 @@ xMBPortSerialInit( uint8_t ucPort, uint32_t ulBaudRate, uint8_t ucDataBits, eMBP @@ -187,11 +208,12 @@ xMBPortSerialInit( uint8_t ucPort, uint32_t ulBaudRate, uint8_t ucDataBits, eMBP
}
}
}
#endif
return bStatus;
}
bool
xMBPortSerialSetTimeout( uint32_t ulNewTimeoutMs )
bool xMBPortSerialSetTimeout(uint32_t ulNewTimeoutMs)
{
if (ulNewTimeoutMs > 0)
{
@ -201,22 +223,23 @@ xMBPortSerialSetTimeout( uint32_t ulNewTimeoutMs ) @@ -201,22 +223,23 @@ xMBPortSerialSetTimeout( uint32_t ulNewTimeoutMs )
{
ulTimeoutMs = 1;
}
return true;
}
void
vMBPortClose( void )
void vMBPortClose(void)
{
if (iSerialFd != -1)
{
#ifdef CONFIG_MB_TERMIOS
(void)tcsetattr(iSerialFd, TCSANOW, &xOldTIO);
#endif
(void)close(iSerialFd);
iSerialFd = -1;
}
}
bool
prvbMBPortSerialRead( uint8_t * pucBuffer, uint16_t usNBytes, uint16_t * usNBytesRead )
bool prvbMBPortSerialRead(uint8_t *pucBuffer, uint16_t usNBytes, uint16_t *usNBytesRead)
{
bool bResult = true;
ssize_t res;
@ -229,7 +252,9 @@ prvbMBPortSerialRead( uint8_t * pucBuffer, uint16_t usNBytes, uint16_t * usNByte @@ -229,7 +252,9 @@ prvbMBPortSerialRead( uint8_t * pucBuffer, uint16_t usNBytes, uint16_t * usNByte
FD_SET(iSerialFd, &rfds);
/* Wait until character received or timeout. Recover in case of an
* interrupted read system call. */
* interrupted read system call.
*/
do
{
if (select(iSerialFd + 1, &rfds, NULL, NULL, &tv) == -1)
@ -257,12 +282,12 @@ prvbMBPortSerialRead( uint8_t * pucBuffer, uint16_t usNBytes, uint16_t * usNByte @@ -257,12 +282,12 @@ prvbMBPortSerialRead( uint8_t * pucBuffer, uint16_t usNBytes, uint16_t * usNByte
break;
}
}
while(bResult == true);
return bResult;
}
bool
prvbMBPortSerialWrite( uint8_t * pucBuffer, uint16_t usNBytes )
bool prvbMBPortSerialWrite(uint8_t *pucBuffer, uint16_t usNBytes)
{
ssize_t res;
size_t left = (size_t) usNBytes;
@ -276,12 +301,15 @@ prvbMBPortSerialWrite( uint8_t * pucBuffer, uint16_t usNBytes ) @@ -276,12 +301,15 @@ prvbMBPortSerialWrite( uint8_t * pucBuffer, uint16_t usNBytes )
{
break;
}
/* call write again because of interrupted system call. */
continue;
}
done += res;
left -= res;
}
return left == 0 ? true : false;
}
@ -313,8 +341,8 @@ xMBPortSerialPoll( ) @@ -313,8 +341,8 @@ xMBPortSerialPoll( )
}
else
{
vMBPortLog( MB_LOG_ERROR, "SER-POLL", "read failed on serial device: %s\n",
strerror( errno ) );
vMBPortLog(MB_LOG_ERROR, "SER-POLL", "read failed on serial device: %d\n",
errno);
bStatus = false;
}
}
@ -327,8 +355,8 @@ xMBPortSerialPoll( ) @@ -327,8 +355,8 @@ xMBPortSerialPoll( )
}
if (!prvbMBPortSerialWrite(&ucBuffer[0], uiTxBufferPos))
{
vMBPortLog( MB_LOG_ERROR, "SER-POLL", "write failed on serial device: %s\n",
strerror( errno ) );
vMBPortLog(MB_LOG_ERROR, "SER-POLL", "write failed on serial device: %d\n",
errno);
bStatus = false;
}
}

Loading…
Cancel
Save