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);
}