lpcmanager

Smarteh 485: slave address of RX buffer must match the address of sent TX buffer in order to be accepted. If reception is not successful data is not copied to beremiz buffer (memcpy()).
#include <native/task.h>
#include <native/mutex.h>
#include <native/timer.h>
#include <unistd.h>
#include <fcntl.h>
#include <rtdm/rtdm.h>
#include "beremiz.h"
/*------------------------- GPIO -------------------------------------*/
/* from armadeus/target/packages/as_devices/c/as_gpio* */
//#ifdef DEBUG
# define ERROR(fmt, ...) printf(fmt, ##__VA_ARGS__)
//#else
//# define ERROR(fmt, ...) /*fmt, ##__VA_ARGS__*/
//#endif
struct gpio_device {
int port_num;
int pin_file; /* pin file for 2.6.29 interface*/
};
struct gpio_device *RTU_GPIO_dev;
#if defined MC9 || defined GOT
struct gpio_device *RUN_LED_dev;
#endif /* MC9/GOT */
#ifdef MC9
struct gpio_device *CAN0_EN_dev;
struct gpio_device *CAN1_EN_dev;
#endif /* MC9 */
static int write_file_bool(int fd, int value)
{
int ret;
ret = write(fd, value?"1":"0", 1);
if (ret < 0) {
ERROR("write error\n");
return ret;
}
if (lseek(fd, 0, SEEK_SET) < 0) {
ERROR("lseek error\n");
return ret;
}
return ret;
}
#define BUFF_SIZE 256
static int gpio_set_pin_value(struct gpio_device *aDev, int aValue)
{
int pin_file = aDev->pin_file;
int retval;
retval = write_file_bool(pin_file, aValue);
if (retval < 0) {
ERROR("Can't write value\n");
close(pin_file);
return -1;
}
return aValue;
}
static struct gpio_device *gpio_open(int aGpioNum)
{
struct gpio_device *dev;
int pin_file;
int export_file;
int gpio_dir_fd;
int retval;
char buf[BUFF_SIZE];
int ret = 0;
export_file = open("/sys/class/gpio/export", O_WRONLY);
if (export_file < 0) {
ERROR("Can't open /sys/class/gpio/export\nBe sure that gpiolib is under your kernel\n");
return NULL;
}
snprintf(buf, BUFF_SIZE, "%%d", aGpioNum);
retval = write(export_file, buf, strlen(buf));
close(export_file);
if (retval < 0) {
ERROR("/sys/class/gpio/export can't be written\n");
return NULL;
}
snprintf(buf, BUFF_SIZE, "/sys/class/gpio/gpio%%d/direction", aGpioNum);
gpio_dir_fd = open(buf, O_WRONLY);
if (gpio_dir_fd < 0) {
ERROR("Can't open gpio%%d direction\n", aGpioNum);
return NULL;
}
ret = write(gpio_dir_fd, "out", 3);
close(gpio_dir_fd);
if (ret < 0){
ERROR("Error writing direction\n");
return NULL;
}
snprintf(buf, BUFF_SIZE, "/sys/class/gpio/gpio%%d/value", aGpioNum);
pin_file = open(buf, O_RDWR);
if (pin_file < 0) {
ERROR("Can't export gpio number %%d\n", aGpioNum);
return NULL;
}
dev = malloc(sizeof(struct gpio_device));
if (dev == NULL) {
ERROR("Can't allocate gpio_device structure\n");
close(pin_file);
return NULL;
}
dev->port_num = aGpioNum;
dev->pin_file = pin_file;
gpio_set_pin_value(dev, 1);
return dev;
}
static int gpio_close(struct gpio_device *aDev)
{
int unexport_file;
char buf[BUFF_SIZE];
int retval;
if(aDev == NULL){
ERROR("device is NULL\n");
return -1;
}
unexport_file = open("/sys/class/gpio/unexport", O_WRONLY);
if (unexport_file < 0) {
ERROR("Can't open /sys/class/gpio/unexport\nBe sure that gpiolib is under your kernel\n");
return -1;
}
snprintf(buf, BUFF_SIZE, "%%d", aDev->port_num);
retval = write(unexport_file, buf, strlen(buf));
close(unexport_file);
if (retval < 0) {
ERROR("/sys/class/gpio/unexport can't be written\n");
return -1;
}
close(aDev->pin_file);
return 0;
}
#define REG_DISCRETE_START 0 /**< Input discrete start address */
#define REG_DISCRETE_NREGS 1024 /**< 1024 bits (type: single bit, Read only) */
#define REG_COILS_START 0 /**< Coils start address */
#define REG_COILS_NREGS 1024 /**< 1024 bits (type: single bit, Read/Write) */
#define REG_INPUT_START 0 /**< Input registers start address */
#define REG_INPUT_NREGS 1024 /**< 1024 words (type: 16-bit word, Read only) */
#define REG_HOLDING_START 0 /**< Holding registers start address */
#define REG_HOLDING_NREGS 1024 /**< 1024 words (type: 16-bit word, Read/Write) */
#define MAX_MOD_RTU_DEVICES 16
typedef struct _mbRtuRdHoldingRegs {
unsigned int use;
unsigned short startAddr;
unsigned char length;
short* buffer;
} mbRtuRdHoldingRegs;
typedef struct _mbRtuRdDiscInputs {
unsigned int use;
unsigned short startAddr;
unsigned short length;
char* buffer;
// unsigned short* buffer;
} mbRtuRdDiscInputs;
typedef struct _mbRtuRdCoils {
unsigned int use;
unsigned short startAddr;
unsigned short length;
char* buffer;
} mbRtuRdCoils;
typedef struct _mbRtuWrSingleCoil {
unsigned int use;
unsigned short startAddr;
char* buffer;
} mbRtuWrSingleCoil;
typedef struct _mbRtuWrCoils {
unsigned int use;
unsigned short startAddr;
unsigned short length;
char* buffer;
} mbRtuWrCoils;
typedef struct _mbRtuRdInputRegs {
unsigned int use;
unsigned short startAddr;
unsigned char length;
short* buffer;
} mbRtuRdInputRegs;
typedef struct _mbRtuWrSingleReg {
unsigned int use;
unsigned short startAddr;
short* buffer;
} mbRtuWrSingleReg;
typedef struct _mbRtuWrMultiRegs {
unsigned int use;
unsigned short startAddr;
unsigned char length;
short* buffer;
} mbRtuWrMultiRegs;
typedef struct _mbRtuSlaveConfig {
unsigned char slaveAddr;
mbRtuRdDiscInputs rdDiscInputs;
mbRtuRdCoils rdCoils;
mbRtuWrSingleCoil wrSingleCoil;
mbRtuWrCoils wrCoils;
mbRtuRdInputRegs rdInputRegs;
mbRtuRdHoldingRegs rdHoldingRegs;
mbRtuWrSingleReg wrSingleReg;
mbRtuWrMultiRegs wrMultiRegs;
} mbRtuSlaveConfig;
typedef enum
{
MB_PAR_ODD = 0, /**< ODD parity. */
MB_PAR_EVEN = 1, /**< Even parity. */
MB_PAR_NONE = 2 /**< No parity. */
} eMBSerialParity;
mbRtuSlaveConfig mbRtuSlaveDev[MAX_MOD_RTU_DEVICES];/**< Tables containing information about connected Modbus network devices (initialized by Composer) */
commTimer mbRtuDevTim[MAX_MOD_RTU_DEVICES]; /**< Table of timers (one for each position) */
short usRegInputValue[REG_INPUT_NREGS]; /**< Array of Modbus input registers */
short usRegHoldingValue[REG_HOLDING_NREGS]; /**< Array of Modbus holding registers */
char ubCoilValue[REG_COILS_NREGS/8]; /**< Array of Modbus coils (8 coils per byte) */
char ubRegDiscreteValue[REG_DISCRETE_NREGS/8]; /**< Array of Modbus discrete inputs (8 inputs per byte) */
unsigned long mbBaudRate = 115200; /**< Modbus baud-rate setting: 9600, 19200, 38400, 57600, 115200 */
eMBSerialParity mbParity = MB_PAR_NONE; /**< Modbus parity setting: odd, even, none */
/* prototypes for functions defined in shared library */
int mbmrtu_init(unsigned long ulBaudRate, eMBSerialParity eParity);
void mbmrtu_BusUpdate(int);
int mbmrtu_cleanup(void);
static RT_TASK RTU_UART_task;
static RT_TASK RTU_task;
static RT_MUTEX RTU_BuffMutex;
void LockMBRTUBuffer(void){
while ( rt_mutex_acquire(&RTU_BuffMutex, TM_INFINITE ) == -EINTR);
}
void UnLockMBRTUBuffer(void){
rt_mutex_release(&RTU_BuffMutex);
}
typedef struct {
void*(*RTU_UART_task_proc)(void *);
void* xSerHdl;
} MB_xeno_task_adaptor_t;
static MB_xeno_task_adaptor_t MB_xeno_task_adaptor_data;
void MB_xeno_task_adaptor(void* param)
{
MB_xeno_task_adaptor_t *d = param;
d->RTU_UART_task_proc(d->xSerHdl);
}
int CreateMBRTUSerialTask(
void*(*RTU_UART_task_proc)(void *),
void* param)
{
int err;
MB_xeno_task_adaptor_data.RTU_UART_task_proc = RTU_UART_task_proc;
MB_xeno_task_adaptor_data.xSerHdl = param;
if((err = rt_task_start(&RTU_UART_task,
MB_xeno_task_adaptor,
&MB_xeno_task_adaptor_data)) != 0)
return err;
return 0;
}
#define nsTOus(ns) (ns/1000L)
#define nsTOms(ns) (ns/1000000L)
#define INVALID_RTU_ADDR 255 /* Used when no Modbus RTU slave device is present */
static void mbmrtu_BusUpdate_proc(void *param){
uint64_t actTime;
while (rt_task_sleep_until(TM_INFINITE) == -EINTR){
int i;
for(i=0;i<MAX_MOD_RTU_DEVICES;i++)
{
if(mbRtuSlaveDev[i].slaveAddr != INVALID_RTU_ADDR)
{
if(mbRtuDevTim[i].status != TIM_DISABLED)
{
actTime = (uint64_t)nsTOms(rt_timer_read());
mbRtuDevTim[i].actValue += actTime - mbRtuDevTim[i].oldTime;
mbRtuDevTim[i].oldTime = actTime;
if(mbRtuDevTim[i].actValue < mbRtuDevTim[i].toValue)
mbRtuDevTim[i].status = TIM_EN_RUNNING;
else
mbRtuDevTim[i].status = TIM_EN_EXPIRED;
}
/* Check if communication depends on timer - if it does, check timer status */
if((mbRtuDevTim[i].status == TIM_DISABLED) || (mbRtuDevTim[i].status == TIM_EN_EXPIRED))
{
mbmrtu_BusUpdate(i);
/* If timer is enabled, reset it's value, otherwise keep it disabled */
if(mbRtuDevTim[i].status != TIM_DISABLED)
{
mbRtuDevTim[i].actValue = 0; /* Reset timer value */
mbRtuDevTim[i].status = TIM_EN_RUNNING;
}
else /* Keep timer disabled */
mbRtuDevTim[i].status = TIM_DISABLED;
}
}
}
}
}
RTIME now;
void TransmitMode(void){
gpio_set_pin_value(RTU_GPIO_dev, 1);
now = rt_timer_read();
}
void RecieveMode(int us){
while(rt_task_sleep_until(
now + rt_timer_ns2ticks(1000LL*us)
) == -EINTR);
gpio_set_pin_value(RTU_GPIO_dev, 0);
}
#ifdef GOT
#define MAX_ONBOARD_DEVICES 2
#define ONBOARD_READ_BUFSIZE 30
#define ONBOARD_WRITE_BUFSIZE 30
typedef char onBoardReadBuf_t[MAX_ONBOARD_DEVICES][ONBOARD_READ_BUFSIZE];
typedef char onBoardWriteBuf_t[MAX_ONBOARD_DEVICES][ONBOARD_WRITE_BUFSIZE];
typedef char onBoardDev_t[MAX_ONBOARD_DEVICES][2];
typedef struct {
onBoardDev_t onBoardDev;
unsigned long long common_ticktime__;
} onBoardBusInit_t;
#define RTIOC_TYPE_SMT_ONBOARD RTDM_CLASS_EXPERIMENTAL
#define RTSMT_ONBOARD_RTIOC_INIT _IOR(RTIOC_TYPE_SMT_ONBOARD, 0x00, onBoardBusInit_t)
#define RTSMT_ONBOARD_RTIOC_READ _IOR(RTIOC_TYPE_SMT_ONBOARD, 0x01, onBoardReadBuf_t)
#define RTSMT_ONBOARD_RTIOC_WRITE _IOR(RTIOC_TYPE_SMT_ONBOARD, 0x02, onBoardWriteBuf_t)
static onBoardReadBuf_t onBoardReadBuf;
static onBoardWriteBuf_t onBoardWriteBuf;
static onBoardBusInit_t onBoardBusInit;
static int onboardbusfd = -1;
#endif /* GOT */