File transfer over UART

Hello, benedict,

I am also confused about how to write logic to end of the first file and the start of the second file. Please share any output on it.

Ok without know details you have several options.

  1. Use a proper file transfer protocol e.g YModem/ZModem These have checksums to make sure the data is correct and handle multiple files as part of the protocol. ZModem has a resume feature for interrupted transfers. These protocols were designed to solve the problem of sending files over a serial connection.

  2. Don’t use Terraterm to send the files. Write your own software where you have control of the output and can send extra control information. But here you are just going to implement your own file transfer protocol. It could be simpler than Y/Zmodem but you will need to develop and test it and maintain the Windows software.

  3. A very crude alternative is to use select() to look for data on the COM port. You will need to read a byte at a time. With select() you can specify a timeout value if no data has arrived. At 9600 baud a byte arrives very roughly every 1ms. So if you set the timeout to something like 500ms you could say that the file has finished and get ready for the next if select() times out. This only works if the file sending has a large enough delay between files though. If a user is manually sending 1 file at a time this would work. However if multiple files are selected together and then sent from Terraterm that won’t work. Also how do you handle the user sending the wrong file by mistake, or the connection being broken/ Terraterm crashing or being closed mid transfer ?

Hello benedict,

In the future, Teraterm is going to be replaced by LPC2478. We have one product that is based on the LPC2478 MCU, and we are going to attach a beaglebone to it. LPC2478 and Beaglebone are communicating with each other using the UART communication protocol. We need to transfer some files from Beaglebone to LPC2478 and from LPC2478 to Beaglebone as well.

On LPC2478, not sufficient space is available to implement z/y modem; hence, we are trying to receive data byte by byte and store it in beaglebone.

I have done it by using Zmodem, which means writing source code to store received files from TeraTerm in Beaglebone using Zmodem.

Regards,
Avinash.

Ok so then you are going to need to implement your own simple file transfer protocol.

If the files are simple ASCII text it is easier, but you mentioned special characters before.

I would drop trying to send files with Terraterm, if that is not the end goal. Either use a second Beagle, a LPC2478 or anything with a serial port to test.

Your receiving loops will probably need to read a byte at a time. If not sending binary files use low value ASCII codes as control codes, there are plenty excluding newline and carriage return. If you need to send binary files then you will have to use something like base64 encoding the files to send them.

Use a control byte to signify the start of transmission.

In fact if you look at the ASCII codes, codes 1 -4 are

  1. start of heading (send before filename )
  2. start of text (send after sending filename, but before file data)
  3. end of text ( send after a file has been sent , go back to step 1 if more files)
  4. end of transmission (send once all data is sent)

Hello @benedict.hewson, I tried to store each file in beaglebone but all content stored in first file that i given in arrary, in remaining other files does not store any data.

  1. Windows side code to transmit 6 files
    import serial
    import time

Open the serial port for communication

ser = serial.Serial(‘COM3’, 9600) # COM port and baud rate

List of file names to send

file_names = [“DIA_ID.TXT”, “OP_REC.TXT”, “DIA_REC.TXT”, “PAT_REC.TXT”, “JAR_REC.TXT”, “PRO_REC.TXT”]

Send files one by one

for file_name in file_names:
try:
with open(f"C:/Users/HP/OneDrive/Desktop/DRS_Database/{file_name}“, “rb”) as file:
print(f"Sending {file_name}…”)
file_data = file.read()
ser.write(file_data)
time.sleep(1) # Add a delay to allow time for the BeagleBone to process the data
print(f"{file_name} sent successfully.“)
except FileNotFoundError:
print(f"File {file_name} not found.”)

Close the serial port

ser.close()

image

  1. Beaglebone side c code to receive and store files

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <termios.h>
#include <unistd.h>

#define UART_PORT “/dev/ttyS1”
#define BAUD_RATE B9600
#define UART_BUFFER_SIZE 8192

void receiveAndStoreFilesOverUART(const char *folderPath, const char *filenames, int numFiles) {
int uart_fd = open(UART_PORT, O_RDWR | O_NOCTTY);
struct termios uart_config;

if (uart_fd < 0) {
    perror("Error opening UART port");
    return;
}

// Configure UART settings
 if (tcgetattr(uart_fd, &uart_config) < 0) {
    perror("Error getting UART configuration");
    close(uart_fd);
    return;
}

// Set baud rate to 9600
cfsetispeed(&uart_config, B9600);
cfsetospeed(&uart_config, B9600);

// Set data format to 8N1 (8 data bits, no parity, 1 stop bit)
uart_config.c_cflag &= ~PARENB;
uart_config.c_cflag &= ~CSTOPB;
uart_config.c_cflag &= ~CSIZE;
uart_config.c_cflag |= CS8;

// Disable hardware flow control
uart_config.c_cflag &= ~CRTSCTS;
// Enable receiver and local mode
uart_config.c_cflag |= CREAD | CLOCAL;
// Set input mode to non-canonical and disable echo
uart_config.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);

// Set the minimum number of characters for non-canonical read
uart_config.c_cc[VMIN] = 1;

// Set the timeout in deciseconds for non-canonical read
uart_config.c_cc[VTIME] = 0;

// Apply UART configuration
if (tcsetattr(uart_fd, TCSANOW, &uart_config) < 0) {
    perror("Error setting UART configuration");
    close(uart_fd);
    return;
}

for (int i = 0; i < numFiles; i++) {
    char filePath[256];
    snprintf(filePath, sizeof(filePath), "%s%s", folderPath, filenames[i]);
    FILE *file = fopen(filePath, "wb");

    if (file == NULL) {
        perror("Error opening file for writing");
        continue;
    }

    char buffer[UART_BUFFER_SIZE];
    ssize_t bytesRead;
    int stopFlag = 0;

    while (!stopFlag) {
        bytesRead = read(uart_fd, buffer, sizeof(buffer));

        if (bytesRead < 0) {
            perror("Error reading from UART");
            break;
        }

if (bytesRead == 0) {
// No data received, continue reading
continue;
}

        // Write the received data to the file
        fwrite(buffer, 1, bytesRead, file);

        // Check for end of file marker or delimiter
        if (strstr(buffer, "EOF") != NULL) {
            printf("End of file marker found for %s\n", filenames[i]);
            break;
        }
    }

    fclose(file);
}

close(uart_fd);

}

int main(void) {
const char *storageFolderPath = “/home/debian/NEW/”;
const char *filenames = {
“OP_REC.TXT”,
“PAT_REC.TXT”,
“JAR_REC.TXT”,
“DIA_ID.TXT”,
“DIA_REC.TXT”,
“PRO_REC.TXT”
};
int numFiles = sizeof(filenames) / sizeof(filenames[0]);

receiveAndStoreFilesOverUART(storageFolderPath, filenames, numFiles);

return 0;

}

All files content is stored in OP_REC.TXT file.

please help me to resolve it.

Thanks,
Avinash

ok I am not going to write this for you, but here is some rough pseudo code.

This will send as many files as you need in any order as the filename is sent before the data, so the beagle will know what file it is getting.

This only works if your file does not include bytes 0x01-0x04 in its data. If it does then you would need to base64 encode the files before sending them, and then decode them on the beagle.

Of course you will also need to add some buffer overflow checks for filename.

I am sure if you study the pseudo code below you will get the idea.

Sending.



for f in filenames
{   
   sendbyte(0x01)
   sendfilename()
   sendbyte(0x02)
   sendfiledata()
   sendbyte(0x03)
   
}

sendbyte(0x04)


all done.

-----------------------
Receiving part



state = idle
finished = false


while !finished
{   
   byte = readbyte()

      
   switch(state)
      
      idle:
         if byte == 0x01
            state = filename
         if byte == 0x04
            finished = true
               
         break;
      
      filename:
         if byte == 0x02 
            !!! add 0 to filename buffer if sending machine doesn't send one.
            open/create filename.
            state = data
         else if byte == 0x04
            finished = true
         else
            add byte to filename buffer
         
         break
         
      data:
         if byte == 0x03   // data finished.
            // if using buffer make sure to write any saved data before closing the file
            close file
            state = idle
         else if byte == 0x04
            // if using buffer make sure to write any saved data before closing the file
            close file
            finished = true
         else
            write byte to file
            // you could buffer up more than 1 byte here to save on writes and increase performance
            
         break
      
}

2 Likes

Hello @benedict.hewson I tried, but I wasn’t able to do it. If possible, can you please make changes or edits to my code? still facing the same issue.

Thanks,
Avinash

Ok I will help some more, but still not going to write the software for you. The best way to learn is by doing, not copying.

Firstly lets take the Windows Python code.

Firstly when inserting code on this forum please make sure it is all in a preformatted text block.
This not only makes it easier to read, it is vital with Python code as white space is important.

So taking you initial Python code from above.

Does it follow the pseudo code I wrote ?
Are you sending the filename and file data separated by the control bytes ?

1 Like

Hello @benedict.hewson, Thank you for your patience, yes i am following your pseudo code for transmitting and receiving side as well.

  1. Windows Side code
import serial
import time

def send_file(serial_port, file_name):
    try:
        # Send start marker (0x01)
        serial_port.write(bytes([0x01]))

        # Send filename marker (0x02)
        serial_port.write(bytes([0x02]))

        # Send filename length as a single byte
        serial_port.write(bytes([len(file_name)]))

        # Send filename
        serial_port.write(file_name.encode())

        # Open the file for reading
        with open(f"C:/Users/HP/OneDrive/Desktop/DRS_Database/{file_name}", "rb") as file:
            # Send data marker (0x03)
            serial_port.write(bytes([0x03]))

            # Send file data
            file_data = file.read()
            serial_port.write(file_data)

        print(f"{file_name} sent successfully.")
    except FileNotFoundError:
        print(f"File {file_name} not found.")

def send_files(serial_port, filenames):
    for file_name in filenames:
        send_file(serial_port, file_name)
        time.sleep(1)  # Add a delay to allow time for the BeagleBone to process the data

    # Send finish marker (0x04)
    serial_port.write(bytes([0x04]))

# Open the serial port for communication
ser = serial.Serial('COM11', 9600)  # COM port and baud rate

# List of file names to send
file_names = ["DIA_ID.TXT", "OP_REC.TXT", "DIA_REC.TXT", "PAT_REC.TXT", "JAR_REC.TXT", "PRO_REC.TXT"]

# Send files
send_files(ser, file_names)

# Close the serial port
ser.close()

Output-
image

Receiving(Beaglebone) side code-

#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>  
#include <fcntl.h>  
#include <termios.h>  
#include <unistd.h>  
#define UART_PORT "/dev/ttyS1"  
#define BAUD_RATE B9600  
#define UART_BUFFER_SIZE 8192  
enum State {  
    IDLE,  
    FILENAME,  
    DATA  
};  
char readByte(int uart_fd) {  
    char byte;  
    ssize_t bytesRead = read(uart_fd, &byte, 1);  
    if (bytesRead < 0) {  
        perror("Error reading from UART");  
        exit(EXIT_FAILURE);  
    }  
    return byte;  
}  
void receiveAndStoreFilesOverUART(const char *folderPath, const char *filenames[], int numFiles) {  
    int uart_fd = open(UART_PORT, O_RDWR | O_NOCTTY);  
    struct termios uart_config;  
    if (uart_fd < 0) {  
        perror("Error opening UART port");  
        exit(EXIT_FAILURE);  
    }  
    // Configure UART settings  
    if (tcgetattr(uart_fd, &uart_config) < 0) {  
        perror("Error getting UART configuration");  
        close(uart_fd);  
        exit(EXIT_FAILURE);  
    }  
    cfsetispeed(&uart_config, B9600);  
    cfsetospeed(&uart_config, B9600);  
    uart_config.c_cflag &= ~PARENB;  
    uart_config.c_cflag &= ~CSTOPB;  
    uart_config.c_cflag &= ~CSIZE;  
    uart_config.c_cflag |= CS8;  
    uart_config.c_cflag &= ~CRTSCTS;  
    uart_config.c_cflag |= CREAD | CLOCAL;  
    uart_config.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);  
    uart_config.c_cc[VMIN] = 1;  
    uart_config.c_cc[VTIME] = 0;  
    if (tcsetattr(uart_fd, TCSANOW, &uart_config) < 0) {  
        perror("Error setting UART configuration");  
        close(uart_fd);  
        exit(EXIT_FAILURE);  
    }  
    enum State state = IDLE;  
    int finished = 0;  
    char filenameBuffer[256];  
    FILE *file = NULL;  
    while (!finished) {  
        char byte = readByte(uart_fd);  
        switch (state) {  
            case IDLE:  
                if (byte == 0x02)  
                    state = FILENAME;  
                if (byte == 0x04)  
                    finished = 1;  
                break;  
            case FILENAME:  
                if (byte == 0x03) {  
                    filenameBuffer[0] = '\0'; // Add null terminator  
                    snprintf(filenameBuffer, sizeof(filenameBuffer), "%s%s", folderPath, filenameBuffer);  
                    file = fopen(filenameBuffer, "wb");  
                    if (file == NULL) {  
                        perror("Error opening file");  
                        finished = 1;  
                    } else {  
                        state = DATA;  
                    }  
                } else if (byte == 0x04) {  
                    finished = 1;  
                } else {  
                    strncat(filenameBuffer, &byte, 1);  
                }  
                break;  
            case DATA:  
                if (byte == 0x01) {  
                    if (file != NULL) {  
                        fclose(file);  
                        file = NULL;  
                    }  
                    state = IDLE;  
                } else if (byte == 0x04) {  
                    if (file != NULL) {  
                        fclose(file);  
                        file = NULL;  
                    }  
                    finished = 1;  
                } else {  
                    if (file != NULL) {  
                        fwrite(&byte, 1, 1, file);  
                    }  
                }  
                break;  
        }  
    }  
    close(uart_fd);  
}  
int main(void) {  
    const char *storageFolderPath = "/home/debian/NEW/";  
    const char *filenames[] = {  
        "OP_REC.TXT",  
        "PAT_REC.TXT",  
        "JAR_REC.TXT",  
        "DIA_ID.TXT",  
        "DIA_REC.TXT",  
        "PRO_REC.TXT"  
    };  
    int numFiles = sizeof(filenames) / sizeof(filenames[0]);  
    receiveAndStoreFilesOverUART(storageFolderPath, filenames, numFiles);  
    return 0;  
} 
in above code we need to add this logic char filePath[256];  
        snprintf(filePath, sizeof(filePath), "%s%s", folderPath, filenames[i]);  
        FILE *file = fopen(filePath, "wb");  
        if (file == NULL) {  
            perror("Error opening file for writing");  
            continue;  
        }

but the receiving side code not open file for write, recently shared code receive and store data in first file of array.

Ok, lets start with the Python.

You are close.
You should send the filename after sending 0x01 byte and before sending 0x02 byte.
I would not bother sending the filename length. It complicates things and you are not checking for it in your C code.

The 0x02 byte tells the receiving code that the file data will come next.

You should be sending the 0x03 byte after you have sent the file data.
This byte tells the receiving code that you have finished sending the file data.

Now for your C code.

You are close. However -

filenameBuffer[0] = '\0'; // Add null terminator 

This is not adding a null terminator, you are basically setting filenameBuffer to “”.
As you are using strncat to append the bytes to the file name, you don’t need to do this. strncat will always null terminate the destination string.

Depending on how much trust you have in the incoming data, you should be checking the length of filenameBuffer before appending the byte to make sure you don’t overwrite your buffer.

Also prior to opening the file you are pre-pending the path to this same buffer, so even if the filename fits in the buffer, by the time you add the path to it, you might not have enough room.
You should be checking the return value from snprintf to make sure the output has not been truncated.
Again this will depend on if you trust the incoming data.

In your DATA case, you should be looking for 0x03 to mark the end of the file, not 0x01

Otherwise it looks close.

Hello @benedict.hewson, I have updated sending side code(Windows) to send 6 files please check it is correct or not?

import serial
import time

def send_file(serial_port, file_name):
    try:
        # Send start marker (0x01)
        serial_port.write(bytes([0x01]))

        # Send filename
        serial_port.write(file_name.encode())

        # Send filename marker (0x02)
        serial_port.write(bytes([0x02]))

        # Open the file for reading
        with open(f"C:/Users/HP/OneDrive/Desktop/DRS_Database/{file_name}", "rb") as file:
            # Send file data marker (0x03)
            serial_port.write(bytes([0x03]))

            # Send file data
            file_data = file.read()
            serial_port.write(file_data)

        # Send finish marker (0x04)
        serial_port.write(bytes([0x04]))

        print(f"{file_name} sent successfully.")
    except FileNotFoundError:
        print(f"File {file_name} not found.")

def send_files(serial_port, filenames):
    for file_name in filenames:
        send_file(serial_port, file_name)
        time.sleep(1)  # Add a delay to allow time for the BeagleBone to process the data

# Open the serial port for communication
ser = serial.Serial('COM11', 9600)  # COM port and baud rate

# List of file names to send
file_names = ["DIA_ID.TXT", "OP_REC.TXT", "DIA_REC.TXT", "PAT_REC.TXT", "JAR_REC.TXT", "PRO_REC.TXT"]

# Send files
send_files(ser, file_names)

# Close the serial port
ser.close()

Still facing issue with beaglebone side c code. I will update in some time.

Thanks,
Avinash.

You still have an issue with your C code.
I would suggest when you fail to open the file, instead of just printing a message “Error opening file for writing” also print out the filename you are trying to open !

Maybe you will see what is going wrong.

EDIT: I also just noted in your Python code, you are sending 0x04 after each file. You should only send 0x04 after all files have been sent.

Hello @benedict.hewson, I have updated python code as per suggestions, but i am facing file opening issue on receiving side(beaglebone). Please have a look on code,

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <termios.h>
#include <unistd.h>

#define UART_PORT "/dev/ttyS1"
#define BAUD_RATE B9600
#define UART_BUFFER_SIZE 8192

enum State {
    IDLE,
    FILENAME,
    DATA
};

char readByte(int uart_fd) {
    char byte;
    ssize_t bytesRead = read(uart_fd, &byte, 1);

    if (bytesRead < 0) {
        perror("Error reading from UART");
        exit(EXIT_FAILURE);
    }

    return byte;
}

void receiveAndStoreFilesOverUART(const char *folderPath, const char *filenames[], int numFiles) {
    int uart_fd = open(UART_PORT, O_RDWR | O_NOCTTY);

    if (uart_fd < 0) {
        perror("Error opening UART port");
        exit(EXIT_FAILURE);
    }

    struct termios uart_config;
 if (tcgetattr(uart_fd, &uart_config) < 0) {
        perror("Error getting UART configuration");
        close(uart_fd);
        exit(EXIT_FAILURE);
    }

    cfsetispeed(&uart_config, BAUD_RATE);
    cfsetospeed(&uart_config, BAUD_RATE);

    uart_config.c_cflag &= ~PARENB;
    uart_config.c_cflag &= ~CSTOPB;
    uart_config.c_cflag &= ~CSIZE;
    uart_config.c_cflag |= CS8;

    uart_config.c_cflag &= ~CRTSCTS;
    uart_config.c_cflag |= CREAD | CLOCAL;

    uart_config.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);

    uart_config.c_cc[VMIN] = 1;
    uart_config.c_cc[VTIME] = 0;

    if (tcsetattr(uart_fd, TCSANOW, &uart_config) < 0) {
        perror("Error setting UART configuration");
        close(uart_fd);
        exit(EXIT_FAILURE);
    }

 enum State state = IDLE;
    int finished = 0;
    char filenameBuffer[256];
    FILE *file = NULL;

    while (!finished) {
        char byte = readByte(uart_fd);

        switch (state) {
            case IDLE:
                if (byte == 0x02) {
 state = FILENAME;
                    printf("Entering FILENAME state\n");
                }
                if (byte == 0x04) {
                    finished = 1;
                    printf("Finished receiving\n");
                }
                break;

        // Inside the FILENAME case
case FILENAME:
    if (byte == 0x03) {
        filenameBuffer[0] = '\0'; // Add null terminator
        printf("Entering DATA state\n");
        printf("Attempting to open file: %s\n", filenameBuffer); // Add this line for debugging
        file = fopen(filenameBuffer, "wb");
        if (file == NULL) {
            perror("Error opening file");
            printf("Failed to open file: %s\n", filenameBuffer);
            finished = 1;
        } else {
            state = DATA;
        }
    } else if (byte == 0x04) {
        finished = 1;
    } else {
        // Append the byte to the filenameBuffer
        int len = strlen(filenameBuffer);
        if (len < sizeof(filenameBuffer) - 1) {
            filenameBuffer[len] = byte;
            filenameBuffer[len + 1] = '\0';  // Add null terminator
        } else {
            printf("Filename buffer overflow!\n");
            finished = 1;
        }
        printf("Appending byte to filenameBuffer: %c\n", byte);
        printf("Filename received: %s\n", filenameBuffer);
    }
    break;
   case DATA:
                if (byte == 0x03) { // Data finished
                    if (file != NULL) {
                        fclose(file);
                        file = NULL;
                        printf("File closed\n");
                    }
                    state = IDLE;
                    printf("Entering IDLE state\n");
                } else if (byte == 0x04) {
                    if (file != NULL) {
                        fclose(file);
                        file = NULL;
                        printf("File closed\n");
                    }
                    finished = 1;
                    printf("Finished receiving\n");
                } else {
                    if (file != NULL) {
                        fwrite(&byte, 1, 1, file);
                    }
                }
                break;
        }
    }

    close(uart_fd);
}

int main(void) {
    const char *storageFolderPath = "/home/debian/NEW/";
    const char *filenames[] = {
        "OP_REC.TXT",
        "PAT_REC.TXT",
        "JAR_REC.TXT",
        "DIA_ID.TXT",
        "DIA_REC.TXT",
        "PRO_REC.TXT"
    };
 int numFiles = sizeof(filenames) / sizeof(filenames[0]);
    receiveAndStoreFilesOverUART(storageFolderPath, filenames, numFiles);
    return 0;
}

Thank you,
Avinash.

OUTPUT -
image

Ok you are pretty close. You didn’t show what the output you getting on the BBB.

My guess is you are not seeing any filenames?

you have this bit of code

            case FILENAME:
                if (byte == 0x03) {
                    filenameBuffer[0] = '\0'; // Add null terminator
                    printf("Entering DATA state\n");
                    printf("Attempting to open file: %s\n", filenameBuffer); // Add this line for debugging

You do realise the by setting filenameBuffer[0] to 0 you are truncating the string to 0 characters ?

Now if you remove this line the following bit of code will probably work.

However you are always appending characters to the filenameBuffer and never clearing it for the next file.

I suggest as you want to include the file path, that you try the following

            case IDLE:
                if (byte == 0x02) {
                    state = FILENAME;
                    strcpy(filenameBuffer,folderPath);   // init buffer to folder where file is to be created.
                    printf("Entering FILENAME state\n");
                }

Hello @benedict.hewson, All file data is stored in one folder: /home/debian/NEW. No separate files are stored. Output of c code
image

The content of files that I send from my Windows PC using a Python script is stored in a folder. It does not generate separate files.

Please help me to do this.

Thanks,
Avinash.

Hello @benedict.hewson, data is not storing in 6 files separately. stores in folder only in random.

Please have a look once.

what is the C code currently ?

Hello @benedict.hewson, thanks for you support, i will share code please take a look on it.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <termios.h>
#include <unistd.h>

#define UART_PORT "/dev/ttyS1"
#define BAUD_RATE B9600
#define UART_BUFFER_SIZE 8192

enum State {
    IDLE,
    FILENAME,
    DATA
};

char readByte(int uart_fd) {
    char byte;
    ssize_t bytesRead = read(uart_fd, &byte, 1);

    if (bytesRead < 0) {
        perror("Error reading from UART");
        exit(EXIT_FAILURE);
    }

    return byte;
}

void receiveAndStoreFilesOverUART(const char *folderPath, const char *filenames[], int numFiles) {
    int uart_fd = open(UART_PORT, O_RDWR | O_NOCTTY);

    if (uart_fd < 0) {
        perror("Error opening UART port");
        exit(EXIT_FAILURE);
    }

    struct termios uart_config;
 if (tcgetattr(uart_fd, &uart_config) < 0) {
        perror("Error getting UART configuration");
        close(uart_fd);
        exit(EXIT_FAILURE);
    }

    cfsetispeed(&uart_config, B9600);
    cfsetospeed(&uart_config, B9600);
    uart_config.c_cflag &= ~PARENB;
    uart_config.c_cflag &= ~CSTOPB;
    uart_config.c_cflag &= ~CSIZE;
    uart_config.c_cflag |= CS8;
    uart_config.c_cflag &= ~CRTSCTS;
    uart_config.c_cflag |= CREAD | CLOCAL;
    uart_config.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
    uart_config.c_cc[VMIN] = 1;
    uart_config.c_cc[VTIME] = 0;

    if (tcsetattr(uart_fd, TCSANOW, &uart_config) < 0) {
        perror("Error setting UART configuration");
        close(uart_fd);
        exit(EXIT_FAILURE);
    }

    enum State state = IDLE;
    int finished = 0;
    char filenameBuffer[256];
    FILE *file = NULL;

    while (!finished) {
        char byte = readByte(uart_fd);

        switch (state) {
 case IDLE:
    if (byte == 0x01) {
        state = FILENAME;
//        filenameBuffer[0] = '\0'; // Reset the filename buffer
        strcpy(filenameBuffer,folderPath);
        printf("Entering FILENAME state\n");
    } else if (byte == 0x04) {
        finished = 1;
        printf("Entering IDLE state\n");
    }
    break;


            case FILENAME:
                if (byte == 0x02) {
                    state = DATA;
                    printf("Entering DATA state\n");
                } else if (byte == 0x04) {
                    finished = 1;
                    printf("Entering IDLE state\n");
                } else {
                    strncat(filenameBuffer, &byte, 1);
                }
                break;

            case DATA:
                if (byte == 0x03) {
                            if (file != NULL) {
                        fclose(file);
                        printf("File closed\n");
                        file = NULL;
                    }
                    state = IDLE;
                } else if (byte == 0x04) {
                    if (file != NULL) {
                        fclose(file);
                        printf("File closed\n");
                        file = NULL;
 }
                    finished = 1;
                    printf("Finished receiving\n");
                } else {
                    if (file == NULL) {
                        file = fopen(filenameBuffer, "wb");
                        if (file == NULL) {
                            perror("Error opening file");
                            finished = 1;
                        }
                    }
                    fwrite(&byte, 1, 1, file);
                }
                break;
        }
    }

    close(uart_fd);
}

int main(void) {
    const char *storageFolderPath = "/home/debian/NEW/";
    const char *filenames[] = {
        "OP_REC.TXT",
        "PAT_REC.TXT",
        "JAR_REC.TXT",
        "DIA_ID.TXT",
        "DIA_REC.TXT",
        "PRO_REC.TXT"
    };
    int numFiles = sizeof(filenames) / sizeof(filenames[0]);

    receiveAndStoreFilesOverUART(storageFolderPath, filenames, numFiles);

    return 0;
}

Thanks,
Avinash.

Ok don’t think there is anything wrong with the C code. It works for me, at least with my test files.

Either it is your python code, or the files you are sending.

I suggest creating a few small test files and send those.

If you want to debug a little mode I would suggest the following

char byte = readByte(uart_fd);
printf("%02x ",(unsigned int)byte);

You can at least then see what bytes you are reading in. It will help you see where you are going wrong.

Thank you @benedict.hewson, I will share python code with you. Please take a look on it.

import serial
import time

def send_file(serial_port, file_name):
    try:
        # Send start marker (0x01)
        serial_port.write(bytes([0x01]))

        # Send filename
        serial_port.write(file_name.encode())

        # Send filename marker (0x02)
        serial_port.write(bytes([0x02]))

        # Open the file for reading
        with open(f"C:/Users/HP/OneDrive/Desktop/DRS_Database/{file_name}", "rb") as file:
            # Send file data marker (0x03)
            serial_port.write(bytes([0x03]))

            # Send file data
            file_data = file.read()
            serial_port.write(file_data)

        print(f"{file_name} sent successfully.")
    except FileNotFoundError:
        print(f"File {file_name} not found.")

def send_files(serial_port, filenames):
    for file_name in filenames:
        send_file(serial_port, file_name)
        time.sleep(1)  # Add a delay to allow time for the BeagleBone to process the data

    # Send finish marker (0x04) after all files are sent
    serial_port.write(bytes([0x04]))

# Open the serial port for communication
ser = serial.Serial('COM11', 9600)  # COM port and baud rate

# List of file names to send
file_names = ["DIA_ID.TXT", "OP_REC.TXT", "DIA_REC.TXT", "PAT_REC.TXT", "JAR_REC.TXT", "PRO_REC.TXT"]

# Send files
send_files(ser, file_names)

# Close the serial port
ser.close()