// See serial_packet.h for documentation on this function. status_t serial_packet_read(const peripheral_descriptor_t * self, uint8_t ** packet, uint32_t * packetLength, packet_type_t packetType) { if (!packet || !packetLength) { debug_printf("Error: invalid packet\r\n"); return kStatus_InvalidArgument; } *packetLength = 0; status_t status; g_serialContext.isBackToBackWrite = false; // Send ACK if needed. status = send_deferred_ack(); if (status != kStatus_Success) { return status; } framing_data_packet_t framingPacket; bool isPacketOk; do { // Clear the packet data area so unsent parameters default to zero. memset(g_serialContext.data, 0, sizeof(g_serialContext.data)); // Receive the framing data packet. isPacketOk = true; status_t status = read_data_packet(&framingPacket, g_serialContext.data, packetType); if (status != kStatus_Success) { // No packet available. *packetLength = 0; return status; } // Verify crc. uint16_t calculated_crc = calculate_framing_crc16(&framingPacket, g_serialContext.data); if (framingPacket.crc16 != calculated_crc) { debug_printf("Error: invalid crc 0x%x, expected 0x%x\r\n", framingPacket.crc16, calculated_crc); isPacketOk = false; } // Send Nak if necessary. if (!isPacketOk) { serial_packet_send_sync(kFramingPacketType_Nak); } } while (!isPacketOk); // Indicate an ACK must be sent. g_serialContext.isAckNeeded = true; // Set caller's data buffer and length *packet = g_serialContext.data; *packetLength = framingPacket.length; return kStatus_Success; }
// See serial_packet.h for documentation on this function. status_t serial_packet_write(const peripheral_descriptor_t *self, const uint8_t *packet, uint32_t byteCount, packet_type_t packetType) { if (!packet || (byteCount > kOutgoingPacketBufferSize)) { debug_printf("Error: invalid packet or packet size %d\r\n", byteCount); return kStatus_InvalidArgument; } // Send ACK if needed. status_t status = send_deferred_ack(); if (status != kStatus_Success) { return status; } // Back-to-back writes require delay for receiver to enter peripheral read routine. if (g_serialContext.isBackToBackWrite) { g_serialContext.isBackToBackWrite = false; #if defined(BOOTLOADER_HOST) host_delay(100); #endif } // Initialize the framing data packet. serial_framing_packet_t *framingPacket = &g_serialContext.framingPacket; framingPacket->dataPacket.header.startByte = kFramingPacketStartByte; framingPacket->dataPacket.header.packetType = kFramingPacketType_Command; if (packetType != kPacketType_Command) { framingPacket->dataPacket.header.packetType = kFramingPacketType_Data; } framingPacket->dataPacket.length = (uint16_t)byteCount; // Copy the caller's data buffer into the framing packet. if (byteCount) { memcpy(framingPacket->data, packet, byteCount); } // Calculate and set the framing packet crc. framingPacket->dataPacket.crc16 = calculate_framing_crc16(&framingPacket->dataPacket, (uint8_t *)framingPacket->data); #if defined(TEST_NAK) ++framingPacket->dataPacket.crc16; #endif // TEST_NAK // Send the framing data packet. status = write_data((uint8_t *)framingPacket, sizeof(framing_data_packet_t) + byteCount); if (status != kStatus_Success) { return status; } return wait_for_ack_packet(); }
// See serial_packet.h for documentation on this function. status_t serial_packet_finalize(const peripheral_descriptor_t * self) { return send_deferred_ack(); }