examples/modbus: Add Reg Coil support and use it to control USERLEDs

This commit is contained in:
Alan C. Assis 2021-04-18 16:39:50 -03:00 committed by Xiang Xiao
parent f7880bcca9
commit 0146e88001
2 changed files with 130 additions and 1 deletions

View File

@ -50,4 +50,15 @@ config EXAMPLES_MODBUS_REG_HOLDING_NREGS
int "Number of holding registers"
default 130
config EXAMPLES_MODBUS_REG_COILS_START
int "Coils registers start address"
default 3000
config EXAMPLES_MODBUS_REG_COILS_NREGS
int "Number of coils registers"
default 32
config EXAMPLES_MODBUS_REG_COILS_USERLEDS
bool "Enable Reg Coils to control USERLEDs"
depends on USERLED
endif

View File

@ -71,6 +71,14 @@
#include "modbus/mb.h"
#include "modbus/mbport.h"
#ifdef CONFIG_EXAMPLES_MODBUS_REG_COILS_USERLEDS
# include <sys/types.h>
# include <sys/stat.h>
# include <fcntl.h>
# include <sys/ioctl.h>
# include <nuttx/leds/userled.h>
#endif
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
@ -108,6 +116,10 @@
# define CONFIG_EXAMPLES_MODBUS_REG_HOLDING_NREGS 130
#endif
#ifdef CONFIG_EXAMPLES_MODBUS_REG_COILS_USERLEDS
# define CONFIG_USERLEDS_DEVPATH "/dev/userleds"
#endif
/****************************************************************************
* Private Types
****************************************************************************/
@ -124,6 +136,10 @@ struct modbus_state_s
enum modbus_threadstate_e threadstate;
uint16_t reginput[CONFIG_EXAMPLES_MODBUS_REG_INPUT_NREGS];
uint16_t regholding[CONFIG_EXAMPLES_MODBUS_REG_HOLDING_NREGS];
uint16_t regcoils[CONFIG_EXAMPLES_MODBUS_REG_COILS_NREGS];
#ifdef CONFIG_EXAMPLES_MODBUS_REG_COILS_USERLEDS
int fd_leds;
#endif
pthread_t threadid;
pthread_mutex_t lock;
volatile bool quit;
@ -260,6 +276,12 @@ static void *modbus_pollthread(void *pvarg)
{
eMBErrorCode mberr;
int ret;
#ifdef CONFIG_EXAMPLES_MODBUS_REG_COILS_USERLEDS
int i;
userled_set_t ledbit;
userled_set_t ledset = 0;
userled_set_t supported;
#endif
/* Initialize the modbus */
@ -273,6 +295,33 @@ static void *modbus_pollthread(void *pvarg)
srand(time(NULL));
/* Open the USERLED device */
#ifdef CONFIG_EXAMPLES_MODBUS_REG_COILS_USERLEDS
printf("Opening %s\n", CONFIG_USERLEDS_DEVPATH);
g_modbus.fd_leds = open(CONFIG_USERLEDS_DEVPATH, O_WRONLY);
if (g_modbus.fd_leds < 0)
{
int errcode = errno;
printf("ERROR: Failed to open %s: %d\n",
CONFIG_USERLEDS_DEVPATH, errcode);
goto stop_modbus_exit;
}
/* Get the set of LEDs supported */
ret = ioctl(g_modbus.fd_leds, ULEDIOC_SUPPORTED,
(unsigned long)((uintptr_t)&supported));
if (ret < 0)
{
int errcode = errno;
printf("ERROR: ioctl(ULEDIOC_SUPPORTED) failed: %d\n",
errcode);
close(g_modbus.fd_leds);
goto stop_modbus_exit;
}
#endif
/* Then loop until we are commanded to shutdown */
do
@ -288,9 +337,35 @@ static void *modbus_pollthread(void *pvarg)
/* Generate some random input */
g_modbus.reginput[0] = (uint16_t)rand();
/* If Reg Coils controls USERLEDs, update it! */
#ifdef CONFIG_EXAMPLES_MODBUS_REG_COILS_USERLEDS
ledset = 0;
for (i = 0; i < CONFIG_EXAMPLES_MODBUS_REG_COILS_NREGS && i < 32; i++)
{
ledbit = g_modbus.regcoils[i] << i;
ledset |= ledbit & supported;
}
ret = ioctl(g_modbus.fd_leds, ULEDIOC_SETALL, ledset);
if (ret < 0)
{
int errcode = errno;
printf("ERROR: ioctl(ULEDIOC_SUPPORTED) failed: %d\n",
errcode);
close(g_modbus.fd_leds);
goto stop_modbus_exit;
}
#endif
}
while (g_modbus.threadstate != SHUTDOWN);
#ifdef CONFIG_EXAMPLES_MODBUS_REG_COILS_USERLEDS
stop_modbus_exit:
#endif
/* Disable */
eMBDisable();
@ -539,7 +614,50 @@ eMBErrorCode eMBRegHoldingCB(uint8_t *buffer, uint16_t address, uint16_t nregs,
eMBErrorCode eMBRegCoilsCB(uint8_t *buffer, uint16_t address, uint16_t ncoils,
eMBRegisterMode mode)
{
return MB_ENOREG;
eMBErrorCode mberr = MB_ENOERR;
int index;
if ((address >= CONFIG_EXAMPLES_MODBUS_REG_COILS_START) &&
(address + ncoils <=
CONFIG_EXAMPLES_MODBUS_REG_COILS_START +
CONFIG_EXAMPLES_MODBUS_REG_COILS_NREGS))
{
index = (int)(address - CONFIG_EXAMPLES_MODBUS_REG_COILS_START);
switch (mode)
{
/* Pass current register values to the protocol stack. */
case MB_REG_READ:
while (ncoils > 0)
{
*buffer++ = (uint8_t)(g_modbus.regcoils[index] & 0xff);
*buffer++ = (uint8_t)(g_modbus.regcoils[index] >> 8);
index++;
ncoils--;
}
break;
/* Update current register values with new values from the
* protocol stack.
*/
case MB_REG_WRITE:
while (ncoils > 0)
{
g_modbus.regcoils[index] = *buffer++;
g_modbus.regcoils[index] |= *buffer++ << 8;
index++;
ncoils--;
}
break;
}
}
else
{
mberr = MB_ENOREG;
}
return mberr;
}
/****************************************************************************