#include "communication.h" #define INTC XScuGic #define COMM_UART_DEVICE_ID XPAR_PS7_UART_0_DEVICE_ID #define COMM_INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID #define COMM_UART_INT_IRQ_ID XPAR_PS7_UART_0_INTR//XPAR_XUARTPS_0_INTR #define BAUD_RATE 921600 // Maximum number of bytes to be received within our loop time, // plus the maximum packet size that might be carried over from the last call, // plus 128 for a little buffer // (bit/s) * (seconds) / (10 bits / byte for UART) #define PACKET_HEADER_SIZE 7 #define UART_BUF_SIZE (((BAUD_RATE * (DESIRED_USEC_PER_LOOP / 1000) / 1000) / 10) + MAX_PACKET_SIZE + 128) //#define INTERRUPT_BENCHMARK // Declaration of interrupt handler void Handler(void *CallBackRef, u32 Event, unsigned int EventData); u8 packet[MAX_PACKET_SIZE]; int bytes_recv = 0; int try_receive_packet(struct UARTDriver *uart) { int attempts = 0; while (attempts++ < MAX_PACKET_SIZE) { // Find start of packet if (bytes_recv == 0) { if (uart->read(uart, &packet[bytes_recv])) return -1; // uart empty if (packet[bytes_recv] != 0xBE) { continue; // keep looking } bytes_recv = 1; } // receive length bytes while (bytes_recv < PACKET_HEADER_SIZE) { if (uart->read(uart, &packet[bytes_recv])) return -1; // uart empty bytes_recv += 1; } // Check if incoming packet is nonsensically large unsigned short length = (packet[6] << 8 | packet[5]) + PACKET_HEADER_SIZE; if (length >= MAX_PACKET_SIZE) { bytes_recv = 0; continue; // abort packet and start over } // Receive rest of packet while (bytes_recv < length) { if (uart->read(uart, &packet[bytes_recv])) return -1; // uart empty bytes_recv += 1; } // Receive checksum and compare if (bytes_recv < length + 1) { if (uart->read(uart, &packet[bytes_recv])) return -1; // uart empty unsigned char calculated_checksum = 0; int i; for(i = 0; i < length; i++) { calculated_checksum ^= packet[i]; } if (calculated_checksum != packet[bytes_recv]) { bytes_recv = 0; continue; // abort packet and start over } bytes_recv += 1; } // Packet ready return 0; } // Try again later return -1; } int process_packet(modular_structs_t *structs) { struct metadata meta; // parse metadata meta.begin_char = packet[0]; meta.msg_type = packet[2] << 8 | packet[1]; meta.msg_id = packet[4] << 8 | packet[3]; meta.data_len = packet[6] << 8 | packet[5]; // Call appropriate function for packet command_cb* func_ptr = MessageTypes[meta.msg_type].functionPtr; if (meta.msg_type < MAX_TYPE_ID && func_ptr) { (* func_ptr)(structs,&meta,&packet[PACKET_HEADER_SIZE], meta.data_len); } // Done processing packets, reset state bytes_recv = 0; return 0; } void process_received(modular_structs_t *structs) { // Parse as many packets as possible struct UARTDriver *uart = structs->hardware_struct.comm.uart; while (!try_receive_packet(uart)) { process_packet(structs); } } int send_data(struct UARTDriver *uart, u16 type_id, u16 msg_id, u8* data, size_t size) { //---------------------------------------------------------------------------------------------- // index|| 0 | 1 | 2 | 3 & 4 | 5 & 6 | 7+ | end | //---------------------------------------------------------------------------------------------| // msg param|| beg char | msg type | msg id | data len (bytes) | data | checksum | //-------------------------------------------------------------------------------------------- | // bytes|| 1 | 2 | 2 | 2 | var | 1 | //---------------------------------------------------------------------------------------------- unsigned char formattedHeader[PACKET_HEADER_SIZE]; // Begin Char: formattedHeader[0] = BEGIN_CHAR; // Msg type 2 bytes: formattedHeader[1] = type_id & 0x000000ff; formattedHeader[2] = (type_id >> 8) & 0x000000ff; // Msg id 2 bytes formattedHeader[3] = msg_id & 0x000000ff; formattedHeader[4] = (msg_id >> 8) & 0x000000ff; // Data length and data - bytes 5&6 for len, 7+ for data formattedHeader[5] = size & 0x000000ff; formattedHeader[6] = (size >> 8) & 0x000000ff; // Compute checksum unsigned char packet_checksum = 0; int i; for(i = 0; i < PACKET_HEADER_SIZE; i++) { packet_checksum ^= formattedHeader[i]; uart->write(uart, formattedHeader[i]); } for (i = 0; i < size; i++) { packet_checksum ^= data[i]; uart->write(uart, data[i]); } uart->write(uart, packet_checksum); return 0; }