반응형
#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 |