lpcmanager

Parents 24d3d28deee7
Children 4fff1de58ab4
Enhanced code generation of MC9 busses, allowing nesting code given by LPCcomponsed. Added RS485 bus scanning logic and serial communication. Added (non working) control of RS485 transceiver through RTS
  • +370 -44
    LPCBus.py
  • --- a/LPCBus.py Tue Dec 09 17:27:37 2014 +0100
    +++ b/LPCBus.py Wed Dec 10 18:32:59 2014 +0100
    @@ -80,8 +80,6 @@
    /* LPCBus confnode functions */
    int __init_%(location_str)s(int argc,char **argv)
    {
    - %(buffer_init)s
    - %(init_code)s
    %(bus_init_code)s
    return 0;
    }
    @@ -94,12 +92,10 @@
    void __retrieve_%(location_str)s(void)
    {
    %(bus_retrieve_code)s
    -%(retrieve_code)s
    }
    void __publish_%(location_str)s(void)
    {
    -%(publish_code)s
    %(bus_publish_code)s
    }
    """}
    @@ -140,25 +136,26 @@
    /* XXX TODO #include "smarteh.h" */
    """,
    - "buffer_init":"""
    + "init":"""
    +#define DEVICEFILENAME "rightbus"
    +
    bzero(&rightReadBuf, sizeof(rightReadBuf_t));
    bzero(&rightWriteBuf, sizeof(rightWriteBuf_t));
    bzero(&rightI2CMod, sizeof(rightI2CMod_t));
    -""",
    - "init":"""
    -#define DEVICEFILENAME "rightbus"
    +
    +%(init_code)s
    int err;
    rightbusfd = rt_dev_open( DEVICEFILENAME, 0);
    if (rightbusfd < 0) {
    - printf("can't open %s rtdm device, %s\\n", DEVICEFILENAME,
    + printf("can't open %%s rtdm device, %%s\\n", DEVICEFILENAME,
    strerror(-rightbusfd));
    return rightbusfd;
    }
    err = rt_dev_ioctl(rightbusfd, RTSMT_RTIOC_INIT, &rightI2CMod);
    if (err) {
    - printf("error while RTSMT_RTIOC_INIT, %s\\n",
    + printf("error while RTSMT_RTIOC_INIT, %%s\\n",
    strerror(-err));
    rt_dev_close(rightbusfd);
    return err;
    @@ -166,8 +163,10 @@
    """,
    "retrieve":"""
    rt_dev_ioctl(rightbusfd, RTSMT_RTIOC_READ, &rightReadBuf);
    +%(retrieve_code)s
    """,
    "publish":"""
    +%(publish_code)s
    rt_dev_ioctl(rightbusfd, RTSMT_RTIOC_WRITE, &rightWriteBuf);
    """,
    "cleanup":"""
    @@ -181,22 +180,96 @@
    (initialized by Composer) */
    unsigned char onBoardDev[MAX_ONBOARD_DEVICES][2];
    """,
    - "buffer_init":"""
    + "init":"""
    bzero(&onBoardDev, sizeof(onBoardDev));
    -""",
    - "init":"""
    +%(init_code)s
    """,
    - "retrieve":"""
    -""",
    - "publish":"""
    -""",
    - "cleanup":"""
    -""",
    + "retrieve":"%(retrieve_code)s",
    + "publish":"%(publish_code)s",
    + "cleanup":"",
    },
    "MC9:Devices": {
    "decl" : """
    +#include <stdio.h>
    +#include <termios.h>
    +#include <unistd.h>
    +#include <sys/ioctl.h>
    +#include <fcntl.h>
    +#include <sys/select.h>
    +
    #include <native/task.h>
    #include <native/mutex.h>
    +#include <native/timer.h>
    +
    +static struct termios oldterminfo;
    +
    +void closeserial(int fd)
    +{
    + tcsetattr(fd, TCSANOW, &oldterminfo);
    + if (close(fd) < 0)
    + perror("closeserial()");
    +}
    +
    +int setRTS(int fd)
    +{
    + int bit = TIOCM_RTS;
    + if (ioctl(fd, TIOCMBIS, &bit) == -1) {
    + perror("setRTS(): TIOCMGET");
    + return 0;
    + }
    + return 1;
    +}
    +
    +int clearRTS(int fd)
    +{
    + int bit = TIOCM_RTS;
    + if (ioctl(fd, TIOCMBIC, &bit) == -1) {
    + perror("clearRTS(): TIOCMGET");
    + return 0;
    + }
    + return 1;
    +}
    +
    +int openserial(char *devicename)
    +{
    + int fd;
    + struct termios attr;
    + speed_t baud = B115200; /* baud rate */
    +
    + if ((fd = open(devicename, O_RDWR)) == -1) {
    + perror("openserial(): open()");
    + return 0;
    + }
    + if (tcgetattr(fd, &oldterminfo) == -1) {
    + perror("openserial(): tcgetattr()");
    + return 0;
    + }
    + attr = oldterminfo;
    + attr.c_oflag = 0;
    +
    + // attr.c_cflag |= CRTSCTS | CLOCAL;
    + attr.c_cflag |= CLOCAL;
    + attr.c_cflag &= ~CRTSCTS;
    + attr.c_cflag &= ~PARENB; /* no parity */
    + attr.c_cflag &= ~CSTOPB; /* 1 stop bit */
    + attr.c_cflag &= ~CSIZE;
    + attr.c_cflag |= CS8 ; /* 8 bits */
    +
    + cfsetospeed(&attr, baud); /* baud rate */
    + if (tcflush(fd, TCIOFLUSH) == -1) {
    + perror("openserial(): tcflush()");
    + return 0;
    + }
    + if (tcsetattr(fd, TCSANOW, &attr) == -1) {
    + perror("initserial(): tcsetattr()");
    + return 0;
    + }
    +
    + /* Turn to write mode*/
    + setRTS(fd);
    +
    + return fd;
    +}
    typedef struct /* Type definition for timers for right modules */
    {
    @@ -204,6 +277,7 @@
    RTIME actValue; /* Actual timer value */
    RTIME toValue; /* Timeout value - initialized at startup */
    } commTimer;
    +
    #define TIM_DISABLED 0
    #define TIM_EN_RUNNING 1
    #define TIM_EN_EXPIRED 2
    @@ -226,7 +300,7 @@
    uartDevReadBuf_t uartDevReadBufB;
    uartDevReadBuf_t *uartDevReadBuf_drv;
    uartDevReadBuf_t *uartDevReadBuf_plc;
    -/* MC8 compatibility crap */
    +/* MC8 compatibility */
    #define uartDevReadBuf (*uartDevReadBuf_drv)
    /* Buffers for writing data to UART port devices */
    @@ -235,19 +309,28 @@
    uartDevWriteBuf_t uartDevWriteBufB;
    uartDevWriteBuf_t *uartDevWriteBuf_drv;
    uartDevWriteBuf_t *uartDevWriteBuf_plc;
    -/* MC8 compatibility crap */
    +/* MC8 compatibility */
    #define uartDevWriteBuf (*uartDevWriteBuf_drv)
    int uartDevWriteBuf_plc_state;
    int uartDevReadBuf_plc_state;
    +/* Function interface definition for modules on UART (RS485) bus */
    +typedef void (*uartPortFunct)(char*, char*, char);
    +/* Table describing module positions on UART (RS485) bus (parsed from Composer data) */
    +uartPortFunct uartPortDevices[MAX_UART_DEVICES] = {NULL};
    +/* Table of timers (one for each position) */
    +static commTimer uartPortTim[MAX_UART_DEVICES];
    +
    static RT_TASK UART_task;
    static RT_MUTEX UART_WriteMutex;
    static RT_MUTEX UART_ReadMutex;
    void UART_task_proc(void *arg)
    {
    + int i;
    while (rt_task_sleep_until(TM_INFINITE) == -EINTR){
    + printf("Hellllo world\\n");
    if(!rt_mutex_acquire(&UART_WriteMutex, TM_INFINITE )){
    if(uartDevWriteBuf_plc_state == FULL){
    uartDevWriteBuf_t *uartDevWriteBuf_tmp;
    @@ -259,9 +342,44 @@
    rt_mutex_release(&UART_WriteMutex);
    }
    - /* XXX use data from uartDevWriteBuf_drv */
    + /* Scan all positions for attached UART port modules */
    + for(i=0;i<MAX_UART_DEVICES;i++)
    + {
    + RTIME now = rt_timer_read();
    + /* Timers for right modules */
    + if(uartPortTim[i].status != TIM_DISABLED)
    + {
    + if(now - uartPortTim[i].actValue < uartPortTim[i].toValue)
    + {
    + uartPortTim[i].status = TIM_EN_RUNNING;
    + }
    + else
    + uartPortTim[i].status = TIM_EN_EXPIRED;
    + }
    + if(uartPortDevices[i] != NULL)
    + {
    + // Check timer status
    + if((uartPortTim[i].status == TIM_DISABLED)
    + || (uartPortTim[i].status == TIM_EN_EXPIRED))
    + {
    + // Communicate with device
    + (*uartPortDevices[i])(
    + &uartDevReadBuf[i][0],
    + &uartDevWriteBuf[i][0],
    + uartDev[i][1]);
    - /* XXX write data to uartDevReadBuf_drv */
    + // If timer is enabled, reset it's value,
    + // otherwise keep it disabled
    + if(uartPortTim[i].status != TIM_DISABLED)
    + {
    + uartPortTim[i].actValue = now;
    + uartPortTim[i].status = TIM_EN_RUNNING;
    + }
    + else /* Keep timer disabled */
    + uartPortTim[i].status = TIM_DISABLED;
    + }
    + }
    + }
    if(!rt_mutex_acquire(&UART_ReadMutex, TM_INFINITE )){
    if(uartDevReadBuf_plc_state == EMPTY){
    @@ -275,8 +393,203 @@
    }
    }
    }
    +
    +/**************************************************************************//**
    +* Calculate checksum of a buffer
    +* @param [in] buffer Pointer to buffer
    +* @return Checksum values on buffer locations 23 & 24
    +******************************************************************************/
    +void Checksum(unsigned char *buffer)
    +{
    + unsigned char i=0, j=0;
    + unsigned char checksum1=0, checksum2=0;
    + unsigned char checksum1Temp=0;
    + for(i=0;i<45;i++)
    + {
    + checksum1Temp=buffer[i];
    + for(j=0;j<8;j++) // Compute number of '1' of whole buff.
    + {
    + if((checksum1Temp & 0x01)>0)
    + checksum1++;
    + checksum1Temp = checksum1Temp >> 1;
    + }
    + checksum2 = checksum2 ^ buffer[i]; // Compute XOR of whole buffer
    + }
    + buffer[45] = checksum2; // Write number of '1' to buffer
    + buffer[46] = checksum1; // Write XOR to buffer
    +}
    +/**************************************************************************//**
    +* Check if checksum values of received buffer are valid
    +* @param [in] buffer Pointer to buffer
    +* @return TRUE if valid, otherwise FALSE
    +******************************************************************************/
    +unsigned char ChecksumValid(unsigned char *buffer)
    +{
    + unsigned char i=0, j=0;
    + unsigned char checksum1=0, checksum2=0;
    + unsigned char checksum1Temp=0;
    + for(i=0;i<45;i++)
    + {
    + checksum1Temp = buffer[i];
    + for(j=0;j<8;j++) // Compute number of '1' of whole buff.
    + {
    + if((checksum1Temp & 0x01)>0)
    + checksum1++;
    + checksum1Temp = checksum1Temp >> 1; // Compute XOR of whole buffer
    + }
    + checksum2 = checksum2^buffer[i];
    + }
    + if((checksum2==buffer[45]) && (checksum1==buffer[46])) // Check if computed checksums are the same as those in buffer (=> no error)
    + return TRUE;
    + else
    + return FALSE;
    +}
    +
    +static int UART_fd;
    +
    +/*************************************************************************//**
    +* Support for UART modules
    +* @param [in] readBuf Pointer to read buffer (for previously polled UART device!)
    +* @param [out] writeBuf Pointer to write buffer (for current device)
    +* @param [in] address UART device address
    +* @return None
    +*****************************************************************************/
    +void UARTDevice(char* readBuf, char* writeBuf, char address)
    +{
    + fd_set set;
    + struct timeval timeout;
    + int rv;
    +
    + // writeBuf[45] = address;
    + writeBuf[45] = 2;
    + char tmp[UART_BUFSIZE];
    + Checksum((unsigned char*)writeBuf+1);
    +
    + writeBuf[0] = 'S';
    + //{
    + // int i;
    + // for (i=0; i<UART_BUFSIZE; i++){
    + // printf("|%%c:%%d", writeBuf[i], writeBuf[i]);
    + // }
    + // printf("\\n");
    + //}
    + //rt_task_sleep(rt_timer_ns2ticks(500000));
    +
    + if(write(UART_fd, writeBuf, UART_BUFSIZE) != UART_BUFSIZE){
    + goto UARTDevfail;
    + }
    +
    + FD_ZERO(&set); /* clear the set */
    + FD_SET(UART_fd, &set); /* add our file descriptor to the set */
    +
    + timeout.tv_sec = 0;
    + timeout.tv_usec = 50000;
    +
    + /* Turn to listen mode*/
    + clearRTS(UART_fd);
    +
    + rv = select(UART_fd + 1, &set, NULL, NULL, &timeout);
    + if(rv == -1)
    + perror("select"); /* an error accured */
    + else if(rv == 0)
    + printf("timeout"); /* a timeout occured */
    + else if(read(UART_fd, tmp, UART_BUFSIZE) == UART_BUFSIZE){
    + memcpy(readBuf,tmp,UART_BUFSIZE);
    + return;
    + }
    +
    + /* Turn to transmit mode*/
    + setRTS(UART_fd);
    +
    + UARTDevfail:
    + tcflush(UART_fd, TCIOFLUSH);
    +}
    +
    +/* Macro to transform milliseconds to xenomai ticks */
    +#define msTOxn(ms) rt_timer_ns2ticks(1000000L*ms)
    +
    +void InitUartPortDevices(void)
    +{
    + unsigned char i=0;
    +
    + for(i=0;i<MAX_UART_DEVICES;i++)
    + {
    + switch(uartDev[i][1])
    + {
    + case(130): /* P01, P02, P01V, P02V */
    + case(132):
    + case(134):
    + case(136):
    + case(138): /* CA1 */
    + case(140):
    + case(142):
    + case(144):
    + case(154): /* CR1 */
    + case(156):
    + case(158):
    + case(160):
    + case(162): /* IR1V */
    + case(164):
    + case(166):
    + case(168):
    + case(186): /* TH1V */
    + case(188):
    + case(190):
    + case(192):
    + uartPortDevices[i] = &UARTDevice;
    + uartPortTim[i].toValue = msTOxn(200); /* 200ms */
    + uartPortTim[i].status = TIM_EN_RUNNING;
    + break;
    + case(146): /* CH1 */
    + case(148):
    + case(150):
    + case(152):
    + uartPortDevices[i] = &UARTDevice;
    + uartPortTim[i].toValue = msTOxn(600); /* 600ms */
    + uartPortTim[i].status = TIM_EN_RUNNING;
    + break;
    + case(170): /* ID1, ID2, ID3 */
    + case(172):
    + case(174):
    + case(176):
    + uartPortDevices[i] = &UARTDevice;
    + uartPortTim[i].toValue = msTOxn(400); /* 400ms */
    + uartPortTim[i].status = TIM_EN_RUNNING;
    + break;
    + case(194): /* DP1V */
    + case(196):
    + case(198):
    + case(200):
    + case(202): /* DP2V */
    + case(204):
    + case(206):
    + case(208):
    + case(210): /* DT1V */
    + case(212):
    + case(214):
    + case(216):
    + case(218): /* DU1V */
    + case(220):
    + case(222):
    + case(224):
    + uartPortDevices[i] = &UARTDevice;
    + uartPortTim[i].toValue = msTOxn(400); /* 400ms */
    + uartPortTim[i].status = TIM_EN_RUNNING;
    + break;
    +
    + default:
    + uartPortDevices[i] = NULL; /* "Empty" or unknown module */
    + uartPortTim[i].status = TIM_DISABLED;
    + break;
    + }
    + }
    +}
    +
    """,
    - "buffer_init":"""
    + "init":"""
    +int err;
    +char *serialdev = "/dev/ttyAPP1";
    +
    uartDevWriteBuf_plc_state = EMPTY;
    uartDevReadBuf_plc_state = EMPTY;
    bzero(&uartDev, sizeof(uartDev));
    @@ -290,9 +603,8 @@
    bzero(&uartDevWriteBufB, sizeof(uartDevWriteBuf_t));
    uartDevWriteBuf_drv = &uartDevWriteBufA;
    uartDevWriteBuf_plc = &uartDevWriteBufB;
    -""",
    - "init":"""
    -int err;
    +
    +%(init_code)s
    if((err = rt_mutex_create (&UART_WriteMutex, "UART_WriteMutex")))
    return err;
    @@ -300,6 +612,16 @@
    if((err = rt_mutex_create (&UART_ReadMutex, "UART_ReadMutex")))
    return err;
    +
    +UART_fd = openserial(serialdev);
    +
    +if (!UART_fd) {
    + fprintf(stderr, "Error while initializing %%s.\\n", serialdev);
    + return 1;
    +}
    +
    +InitUartPortDevices();
    +
    if((err = rt_task_create(&UART_task, "UART_task", 0, 50, T_JOINABLE)))
    return err;
    @@ -319,7 +641,7 @@
    if(prevstate == FULL){
    - /* XXX use uartDevReadBuf_plc */
    +%(retrieve_code)s
    /* unlock plc buffer */
    uartDevReadBuf_plc_state = EMPTY;
    @@ -337,7 +659,7 @@
    rt_mutex_release(&UART_WriteMutex);
    - /* XXX use uartDevWriteBuf_plc */
    +%(publish_code)s
    /* unlock plc buffer */
    uartDevWriteBuf_plc_state = FULL;
    @@ -349,6 +671,7 @@
    "cleanup":"""
    rt_task_delete(&UART_task);
    rt_task_join(&UART_task);
    +closeserial(UART_fd);
    rt_mutex_delete(&UART_WriteMutex);
    rt_mutex_delete(&UART_ReadMutex);
    """,
    @@ -541,27 +864,12 @@
    # define a unique name for the generated C file
    location_str = "_".join(map(str, current_location))
    - BusName = LPCarch + ":" + self.BaseParams.getName()
    -
    - bcode = bus_code.get(BusName,{"decl":"",
    - "buffer_init":"",
    - "init":"",
    - "retrieve":"",
    - "publish":"",
    - "cleanup":"",
    - })
    code_str = {"location_str": location_str,
    "var_decl": "",
    "declare_code": "",
    "init_code": "",
    "retrieve_code": "",
    "publish_code": "",
    - "bus_decl":bcode["decl"],
    - "buffer_init": bcode["buffer_init"],
    - "bus_init_code": bcode["init"],
    - "bus_cleanup_code": bcode["cleanup"],
    - "bus_retrieve_code": bcode["retrieve"],
    - "bus_publish_code": bcode["publish"],
    }
    for module in GetModuleChildren(self):
    @@ -609,6 +917,24 @@
    if var["Publish"] != "":
    code_str["publish_code"] += " " + var["Publish"] % ("*" + var["location"]) + "\n"
    + BusName = LPCarch + ":" + self.BaseParams.getName()
    +
    +
    + def bcode(section):
    + return bus_code.get(BusName,{"decl":"",
    + "init":"%(init_code)s",
    + "retrieve":"%(retrieve_code)s",
    + "publish":"%(publish_code)s",
    + "cleanup":"",
    + })[section] % code_str
    + code_str.update({
    + "bus_decl":bcode("decl"),
    + "bus_init_code": bcode("init"),
    + "bus_cleanup_code": bcode("cleanup"),
    + "bus_retrieve_code": bcode("retrieve"),
    + "bus_publish_code": bcode("publish"),
    + })
    +
    if LPCarch not in bus_template_code:
    raise Exception, "Unknown arch %s. Please use %s"%(
    LPCarch,repr(bus_template_code.keys()))