반응형
#include "Driver_USART.h"
#include "xmodem_lib.h"
#include "crc.h"

#define PACKET_SIZE 128

extern ARM_DRIVER_USART Driver_USART0;
static ARM_DRIVER_USART *USARTdrv = &Driver_USART0;

static const uint8_t SOH = 0x01;
static const uint8_t EOT = 0x04;
static const uint8_t ACK = 0x06;
static const uint8_t NAK = 0x15;

#ifdef XMODEM_CRC16
static uint8_t rx_buffer[PACKET_SIZE + 5]; // SOH, Block, ~Block, Data[128], CRC[2]
static const uint8_t SELC = 0x43;
#else
static uint8_t rx_buffer[PACKET_SIZE + 4]; // SOH, Block, ~Block, Data[128], checksum
#endif

void USART_Callback(uint32_t event) {
    // Handle USART events here
}

void XMODEM_Init(void) {
    USARTdrv->Initialize(USART_Callback);
    USARTdrv->PowerControl(ARM_POWER_FULL);
    USARTdrv->Control(ARM_USART_MODE_ASYNCHRONOUS |
                      ARM_USART_DATA_BITS_8 |
                      ARM_USART_PARITY_NONE |
                      ARM_USART_STOP_BITS_1 |
                      ARM_USART_FLOW_CONTROL_NONE, 115200);
    USARTdrv->Control(ARM_USART_CONTROL_RX, 0);
}

unsigned short crc16_ccitt( const void *buf, int len )
{
	unsigned short crc = 0;
	while( len-- ) {
		int i;
		crc ^= *(char *)buf++ << 8;
		for( i = 0; i < 8; ++i ) {
			if( crc & 0x8000 )
				crc = (crc << 1) ^ 0x1021;
			else
				crc = crc << 1;
		}
	}
	return crc;
}

uint8_t calculate_checksum(const uint8_t *data, uint16_t length) {
    uint8_t checksum = 0;
    while (length--) {
        checksum += *data++;
    }
    return checksum;
}

int XMODEM_Receive(uint8_t *data, uint32_t length) {
    uint8_t block_number = 1, started = 0;
    uint32_t received = 0, timeout = 0;
    uint32_t count;

    //Clear RXFIFO
    while (USARTdrv->GetRxCount() > 0) {
        uint8_t dummy;
        USARTdrv->Receive(&dummy, 1);
    }

#ifdef XMODEM_CRC16
    USARTdrv->Send(&SELC, 1);
#else
    USARTdrv->Send(&ACK, 1);
#endif
    
    while (received < length) {
        memset(rx_buffer, 0x0, sizeof(rx_buffer));
        USARTdrv->Receive(rx_buffer, sizeof(rx_buffer));
        count = USARTdrv->GetRxCount();
        if((!started) && (count > 0))
            started = 1;
        // Wait for data reception to complete
        // Implement timeout handling here

        if (rx_buffer[0] == SOH && rx_buffer[1] == block_number && rx_buffer[2] == (uint8_t)~block_number) {
#ifdef XMODEM_CRC16
            uint16_t crc_received = (rx_buffer[PACKET_SIZE + 3] << 8) | rx_buffer[PACKET_SIZE + 4];
            uint16_t crc_calculated = crc16_ccitt(&rx_buffer[3], PACKET_SIZE);
            if (crc_received == crc_calculated) {
#else
            uint8_t checksum_received = rx_buffer[PACKET_SIZE + 3];
            uint8_t checksum_calculated = calculate_checksum(&rx_buffer[3], PACKET_SIZE);
            if (checksum_received == checksum_calculated) {
#endif
                memcpy(&data[received], &rx_buffer[3], PACKET_SIZE);
                received += PACKET_SIZE;
                started = 1;
                block_number++;
                USARTdrv->Send(&ACK, 1);
                timeout = 0;
            } else {
                if(block_number == 1)
                    USARTdrv->Send(&SELC, 1);
                else
                    USARTdrv->Send(&NAK, 1);
            }
        } else if (rx_buffer[0] == EOT) {
            USARTdrv->Send(&ACK, 1);
            break;
        } else {
            //Clear Read Buffer For Packet align
            if(count > 0) {
                do {
                    USARTdrv->Receive(rx_buffer, sizeof(rx_buffer));
                } while (USARTdrv->GetRxCount());
            }
#ifdef XMODEM_CRC16
            if(block_number == 1)
                    USARTdrv->Send(&SELC, 1);
            else
#endif
                USARTdrv->Send(&NAK, 1);
            
            if(started && timeout > 15) {
                block_number = 1;
                received = 0;
                started = 0;
                timeout = 0;
            } else if (started) {
                timeout++;
            }
        }
    }

    return received;
}
반응형

'Programming Language > C&C++' 카테고리의 다른 글

CRC16/32 & Checksum C언어 코드  (0) 2024.11.14
[C++] STL 및 Container 종류  (0) 2021.08.25

+ Recent posts