• Uncategorized

About c : Concurrency-thread-read-write-different-UART-linux-C-Programming

Question Detail

I try to read and write data by two different UART.
I create two thread to comunicate with theese UARTs. Every thread use diffent UART

Some Time, when I write data to UART, write function return with all byte whiuout error, but elettrical port not send all byte.

If I comment second thread, I haven’t this error.

Why? Somebody know the problem?

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <errno.h>
#include <fcntl.h> 
#include <string.h>
#include <termios.h>
#include <unistd.h>
#include <stdint.h>
#include "log4c.h"
#include <pthread.h>
pthread_t threadId[2];          /*!< Array di pthread_t. In presenza di micro, vengono avviati 2 thread, uno per ogni micro per la generazione del crc*/
/** \struct parameters
   * \brief Struttura contenente i parametri scambiati con il thread che calcola il crc
   */
struct parameters {
    uint8_t* Buffer; /*!< Puntatore al buffer contenente i dati di cui calcolare il crc   */
    uint32_t length; /*!< Lunghezza in byte del buffer contenente i dati   */
    uint32_t crc;    /*!< Contiene il valore del crc calcolato dal micro   */
    uint8_t microNumber; /*!< Valore numerico che identifica il micro: 1->micro1, 2->micro2   */
    
};
int fdMicroFirst; /*!<Memorizza l'identificativo numerico del microcontrollore 1 */
int fdMicroSecond; /*!<Memorizza l'identificativo numerico del microcontrollore 2 */


/*
 * 
 */
int setInterfaceAttribs(int speed, int parity, int fd) {
    struct termios tty;
    if (tcgetattr(fd, &tty) != 0) {
        printf("error %d from tcgetattr", errno);
        return -1;
    }

    cfsetospeed(&tty, speed);
    cfsetispeed(&tty, speed);

    tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8; // 8-bit chars
    // disable IGNBRK for mismatched speed tests; otherwise receive break
    // as \000 chars
    tty.c_iflag &= ~IGNBRK; // disable break processing
    tty.c_lflag = 0; // no signaling chars, no echo,
    // no canonical processing
    tty.c_oflag = 0; // no remapping, no delays
    
    tty.c_iflag &= ~(IXON | IXOFF | IXANY | INLCR | ICRNL); // shut off xon/xoff ctrl
    //INLCR | ICRNL in questo modo viene disabilitata la conversione da Carriege return (CR) a new line(NL) e viceversa.
    //Se non vengono disabilitate queste due configurazioni 0x0d viene letto come 0x0a
    tty.c_cflag |= (CLOCAL | CREAD); // ignore modem controls,
    // enable reading
    tty.c_cflag &= ~(PARENB | PARODD); // shut off parity
    tty.c_cflag |= parity;
    tty.c_cflag &= ~CSTOPB;
    tty.c_cflag &= ~CRTSCTS;

    if (tcsetattr(fd, TCSANOW, &tty) != 0) {
        printf("error %d from tcsetattr", errno);
        return -1;
    }
    return 0;
}

void setBlocking(int should_block, int fd) {
    struct termios tty;
    memset(&tty, 0, sizeof tty);
    if (tcgetattr(fd, &tty) != 0) {
        printf("error %d from tggetattr", errno);
        return;
    }

    tty.c_cc[VMIN] = should_block ? 4 : 0;
    tty.c_cc[VTIME] = 2.5; // 0.5 seconds read timeout era impostato a 5

    if (tcsetattr(fd, TCSANOW, &tty) != 0)
        printf("error %d setting term attributes", errno);
}

int openSerialCommunication(char *portname, int speed, int microNumber) {
    int retVal = -1;
    int fd = open(portname, O_RDWR | O_NOCTTY | O_SYNC);
    if (fd < 0) {
        printf("error %d opening %s: %s", errno, portname, strerror(errno));
        return -1;
    }
    if (speed == 115200) {
        speed = B115200;
    } else if (speed == 460800) {
        speed = B460800;
    } else if (speed == 921600) {
        speed = B921600;
    }
    if (microNumber == 1) {
        fdMicroFirst = fd;
        //retVal = setInterfaceAttribs(B115200, 0, fdMicroFirst); // set speed to 115,200 bps, 8n1 (no parity)


        retVal = setInterfaceAttribs(speed, 0, fdMicroFirst); // set speed to 115,200 bps, 8n1 (no parity)
        //retVal = setInterfaceAttribs(B460800, 0, fdMicroFirst); // set speed to 115,200 bps, 8n1 (no parity)
        setBlocking(0, fdMicroFirst); // set no blocking
        if (tcflush(fdMicroFirst, TCOFLUSH) != 0) {
            printf("Errore flush Output Buffer Micro %d\n", microNumber);
        }
    } else if (microNumber == 2) {
        fdMicroSecond = fd;
        //retVal = setInterfaceAttribs(B115200, 0, fdMicroSecond); // set speed to 115,200 bps, 8n1 (no parity)
        retVal = setInterfaceAttribs(speed, 0, fdMicroSecond); // set speed to 115,200 bps, 8n1 (no parity)
        setBlocking(0, fdMicroSecond); // set no blocking
        if (tcflush(fdMicroSecond, TCOFLUSH) != 0) {
            printf("Errore flush Output Buffer Micro %d\n", microNumber);
        }
    }

    return retVal;
}
void closeSerialCommunication() {
    if (fdMicroFirst != -1) {
        close(fdMicroFirst);
    }
    if (fdMicroSecond != -1) {
        close(fdMicroSecond);
    }
}
uint32_t calculateCrc(uint8_t* buffer, uint16_t bufferLengthCrc, int microNumber) {
    
       
    uint8_t write_buffer[1100];
    uint32_t crc = 0;
    int fdMicro = -1;
    uint8_t readBuffer [4] = {0x00, 0x00, 0x00, 0x00};
    int numB = 0;
    int n = 0;
    int nTemp;
    uint8_t crcBuffer [4] = {0x00, 0x00, 0x00, 0x00};
    int counter = 0;
    struct timespec startTime, stopTime;
    uint16_t dimBufferTosend = 0;
    uint16_t numnByteSent = 0;

    if (microNumber == 1) {

        fdMicro = fdMicroFirst;
    } else if (microNumber == 2) {
        fdMicro = fdMicroSecond;
    }
     
    //I primi due byte che vengono inviati alla seriale rappresentano il numero di byte 
    //che costituiscono il dato inviato

    if (bufferLengthCrc <= 0xFFFF) {
        write_buffer[0] = (bufferLengthCrc & 0xFF00) >> 8;
        write_buffer[1] = (bufferLengthCrc & 0x00FF);
        //printf("UART Write Buffer: %x %x\n",write_buffer[0],write_buffer[1]);
        for (int i = 0; i < bufferLengthCrc; i++) {
            write_buffer[i + 2] = buffer[i];
            //printf("Write Buffer: %x ", write_buffer[i + 2]);

            /*
                        printf("Write Buffer: %x \n",write_buffer[i + 2]);
             */
        }
        
            
        printf("Flushing Micro %d with fd: %d\n", microNumber, fdMicro);
        if (tcflush(fdMicro, TCOFLUSH) != 0) {
            printf("Errore flush Output Buffer Micro %d\n", microNumber);
        }
        
        dimBufferTosend = bufferLengthCrc + 2;
        numnByteSent = 0;
        numB = 1;
        while (numnByteSent < dimBufferTosend && numB > 0) {
            numB = write(fdMicro, write_buffer + numnByteSent, dimBufferTosend - numnByteSent);
            
            
            numnByteSent = numnByteSent + numB;
            printf("Byte scritti su Micro %d:%d\n", microNumber, numnByteSent);
            
            printf( "Byte rimanenti da scrivere su Micro %d:%d\n", microNumber, dimBufferTosend - numnByteSent);


        }
        if (numnByteSent >= dimBufferTosend) {
            //printf("UART Buffer: \n");
            //clock_gettime(CLOCK_REALTIME, &startTime);
            while (n < 4) {
                nTemp = read(fdMicro, readBuffer, sizeof readBuffer); // read up to 100 characters if ready to read
                //printf("ntemp:%d ",nTemp);

                if (nTemp != 0 && nTemp != -1) {
                    int j = 0;
                    for (int k = n; k < n + nTemp; k++) {
                        crcBuffer[k] = readBuffer[j];
                        printf(" 0x%x 0x%x ", crcBuffer[k], readBuffer[j]);
                        j++;
                    }
                    printf("UART Buffer Response Micro %d: \n", microNumber);
                    n = n + nTemp;


                } else {
                    if (counter == 3) {
                        n = 4;
                        for (int i = 0; i < bufferLengthCrc + 2; i++) {
                           //printf("Write Buffer: %x ", write_buffer[i]);

                        }
                        printf("CRC Ricevuto: 0x%x 0x%x 0x%x 0x%x\n", crcBuffer[0], crcBuffer[1], crcBuffer[2], crcBuffer[3]);
                        printf( "Risposta CRC da MICRO %d non pervenuta\n", microNumber);
                        while (1) {
                            usleep(1000);
                        }

                    } else {
                        counter = counter + 1;
                    }
                }
            }
        }
        
        
        printf("CRC Ricevuto: 0x%x 0x%x 0x%x 0x%x\n", crcBuffer[0], crcBuffer[1], crcBuffer[2], crcBuffer[3]);

        crc = (crcBuffer[0] << 24)+(crcBuffer[1] << 16)+(crcBuffer[2] << 8)+(crcBuffer[3]);

    }

    return crc;

}

///Thread calcolo  CRC
void *
crcCalcThread(void *_args) {
    printf("crccalcthread\n");
    /* Cast the arguments to the usable struct type */
    struct parameters *args = (struct parameters *) _args;

    /* Place the result into the struct itself (on the heap) */
    
    args->crc = calculateCrc(args->Buffer, args->length, args->microNumber);
    printf("after  crccalcthread\n");
    return 0;
    //pthread_exit(NULL);
}

int main(int argc, char** argv) {
    
    
    
    uint8_t Buffer[1100];
    uint32_t crc32pol1;
    uint32_t crc32pol2;
    //int retValInitMutex=pthread_mutex_init(&(lockWrite), NULL);
    
    
    openSerialCommunication("/dev/ttySTM4",115200,1);
    openSerialCommunication("/dev/ttySTM3",115200,2);
    
    while(1)
    {
       
        for (int i = 0; i < 1024; i++) {
            Buffer[i] = 0x03;
            //printf("Write Buffer: %x ", write_buffer[i + 2]);

        }
        struct parameters *argsFirstMicro = calloc(sizeof (struct parameters), 1);
        argsFirstMicro->Buffer = Buffer;
        argsFirstMicro->length = 1024;
        argsFirstMicro->microNumber = 1;

        int err = pthread_create(&(threadId[0]), NULL, &crcCalcThread, argsFirstMicro);
        if (err != 0)
            printf("can't create thread :[%s]\n", strerror(err));
        else
            printf("crcCalcThread created successfully!\n");

        //MICRO 2
        /*crc32pol2 = crc32(Buffer, (packetLength + slPDU_SAFETY_CODE_NUM_BYTE+ paddingNum), CRC32_POLY_CH2_INV);
        log4c_category_log(slcat, LOG4C_PRIORITY_DEBUG, "CRC2 NO MICRO:%x\n", crc32pol2);
        printf("CRC2 NO MICRO:%x", crc32pol2);*/
        struct parameters *argsSecondMicro = calloc(sizeof (struct parameters), 1);
        argsSecondMicro->Buffer = Buffer;
        argsSecondMicro->length = 1024;
        argsSecondMicro->microNumber = 2;
        
        err = pthread_create(&(threadId[1]), NULL, &crcCalcThread, argsSecondMicro);
        if (err != 0)
            printf( "can't create thread :[%s]\n", strerror(err));
        else
            printf("crcCalcThread created successfully!\n");
        pthread_join(threadId[0], NULL);
        
        pthread_join(threadId[1], NULL);

        crc32pol1 = argsFirstMicro->crc;
        /*
                 Clean up the struct instance 
         */
        free(argsFirstMicro);
        argsFirstMicro = NULL;
        crc32pol2 = argsSecondMicro->crc;
        // Clean up the struct instance 
        free(argsSecondMicro);
        argsSecondMicro = NULL;
        usleep(4);
    }
    
        
    return (EXIT_SUCCESS);
    
}

Question Answer

No answer for now.

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.