/* * UART protocol using following entities: * - message to MCU => ACK response * - event from MCU => event ACK * * Frame structure: * <STX> <DATA> <CHECKSUM> <ETX> * Where: * - STX - is start of transmission character * - ETX - end of transmission * - DATA - payload * - CHECKSUM - checksum calculated on <DATA> * * If <DATA> or <CHECKSUM> contain one of control characters, then it is * escaped using <DLE> control code. Added <DLE> does not participate in * checksum calculation.
*/ #define RAVE_SP_STX 0x02 #define RAVE_SP_ETX 0x03 #define RAVE_SP_DLE 0x10
#define RAVE_SP_MAX_DATA_SIZE 64 #define RAVE_SP_CHECKSUM_8B2C 1 #define RAVE_SP_CHECKSUM_CCITT 2 #define RAVE_SP_CHECKSUM_SIZE RAVE_SP_CHECKSUM_CCITT /* * We don't store STX, ETX and unescaped bytes, so Rx is only * DATA + CSUM
*/ #define RAVE_SP_RX_BUFFER_SIZE \
(RAVE_SP_MAX_DATA_SIZE + RAVE_SP_CHECKSUM_SIZE)
#define RAVE_SP_STX_ETX_SIZE 2 /* * For Tx we have to have space for everything, STX, EXT and * potentially stuffed DATA + CSUM data + csum
*/ #define RAVE_SP_TX_BUFFER_SIZE \
(RAVE_SP_STX_ETX_SIZE + 2 * RAVE_SP_RX_BUFFER_SIZE)
/** * enum rave_sp_deframer_state - Possible state for de-framer * * @RAVE_SP_EXPECT_SOF: Scanning input for start-of-frame marker * @RAVE_SP_EXPECT_DATA: Got start of frame marker, collecting frame * @RAVE_SP_EXPECT_ESCAPED_DATA: Got escape character, collecting escaped byte
*/ enum rave_sp_deframer_state {
RAVE_SP_EXPECT_SOF,
RAVE_SP_EXPECT_DATA,
RAVE_SP_EXPECT_ESCAPED_DATA,
};
/** * struct rave_sp_deframer - Device protocol deframer * * @state: Current state of the deframer * @data: Buffer used to collect deframed data * @length: Number of bytes de-framed so far
*/ struct rave_sp_deframer { enum rave_sp_deframer_state state; unsignedchar data[RAVE_SP_RX_BUFFER_SIZE];
size_t length;
};
/** * struct rave_sp_reply - Reply as per RAVE device protocol * * @length: Expected reply length * @data: Buffer to store reply payload in * @code: Expected reply code * @ackid: Expected reply ACK ID * @received: Successful reply reception completion
*/ struct rave_sp_reply {
size_t length; void *data;
u8 code;
u8 ackid; struct completion received;
};
/** * struct rave_sp - RAVE supervisory processor core * * @serdev: Pointer to underlying serdev * @deframer: Stored state of the protocol deframer * @ackid: ACK ID used in last reply sent to the device * @bus_lock: Lock to serialize access to the device * @reply_lock: Lock protecting @reply * @reply: Pointer to memory to store reply payload * * @variant: Device variant specific information * @event_notifier_list: Input event notification chain * * @part_number_firmware: Firmware version * @part_number_bootloader: Bootloader version
*/ struct rave_sp { struct serdev_device *serdev; struct rave_sp_deframer deframer;
atomic_t ackid; struct mutex bus_lock; struct mutex reply_lock; struct rave_sp_reply *reply;
/* * While the rest of the wire protocol is little-endian, * CCITT-16 CRC in RDU2 device is sent out in big-endian order.
*/
put_unaligned_be16(calculated, crc);
}
static u8 rave_sp_reply_code(u8 command)
{ /* * There isn't a single rule that describes command code -> * ACK code transformation, but, going through various * versions of ICDs, there appear to be three distinct groups * that can be described by simple transformation.
*/ switch (command) { case 0xA0 ... 0xBE: /* * Commands implemented by firmware found in RDU1 and * older devices all seem to obey the following rule
*/ return command + 0x20; case 0xE0 ... 0xEF: /* * Events emitted by all versions of the firmare use * least significant bit to get an ACK code
*/ return command | 0x01; default: /* * Commands implemented by firmware found in RDU2 are * similar to "old" commands, but they use slightly * different offset
*/ return command + 0x40;
}
}
switch (deframer->state) { case RAVE_SP_EXPECT_SOF: if (byte == RAVE_SP_STX)
deframer->state = RAVE_SP_EXPECT_DATA; break;
case RAVE_SP_EXPECT_DATA: /* * Treat special byte values first
*/ switch (byte) { case RAVE_SP_ETX:
rave_sp_receive_frame(sp,
deframer->data,
deframer->length); /* * Once we extracted a complete frame * out of a stream, we call it done * and proceed to bailing out while * resetting the framer to initial * state, regardless if we've consumed * all of the stream or not.
*/ goto reset_framer; case RAVE_SP_STX:
dev_warn(dev, "Bad frame: STX before ETX\n"); /* * If we encounter second "start of * the frame" marker before seeing * corresponding "end of frame", we * reset the framer and ignore both: * frame started by first SOF and * frame started by current SOF. * * NOTE: The above means that only the * frame started by third SOF, sent * after this one will have a chance * to get throught.
*/ goto reset_framer; case RAVE_SP_DLE:
deframer->state = RAVE_SP_EXPECT_ESCAPED_DATA; /* * If we encounter escape sequence we * need to skip it and collect the * byte that follows. We do it by * forcing the next iteration of the * encompassing while loop.
*/ continue;
} /* * For the rest of the bytes, that are not * speical snoflakes, we do the same thing * that we do to escaped data - collect it in * deframer buffer
*/
fallthrough;
case RAVE_SP_EXPECT_ESCAPED_DATA: if (deframer->length == sizeof(deframer->data)) {
dev_warn(dev, "Bad frame: Too long\n"); /* * If the amount of data we've * accumulated for current frame so * far starts to exceed the capacity * of deframer's buffer, there's * nothing else we can do but to * discard that data and start * assemblying a new frame again
*/ goto reset_framer;
}
deframer->data[deframer->length++] = byte;
/* * We've extracted out special byte, now we * can go back to regular data collecting
*/
deframer->state = RAVE_SP_EXPECT_DATA; break;
}
}
/* * The only way to get out of the above loop and end up here * is throught consuming all of the supplied data, so here we * report that we processed it all.
*/ return size;
reset_framer: /* * NOTE: A number of codepaths that will drop us here will do * so before consuming all 'size' bytes of the data passed by * serdev layer. We rely on the fact that serdev layer will * re-execute this handler with the remainder of the Rx bytes * once we report actual number of bytes that we processed.
*/
deframer->state = RAVE_SP_EXPECT_SOF;
deframer->length = 0;
if (command == RAVE_SP_CMD_REQ_COPPER_REV) { /* * As per RDU2 ICD 3.4.47 CMD_GET_COPPER_REV code is * different from that for RDU1 and it is set to 0x28.
*/ return 0x28;
}
return rave_sp_rdu1_cmd_translate(command);
}
staticint rave_sp_default_cmd_translate(enum rave_sp_command command)
{ /* * All of the following command codes were taken from "Table : * Communications Protocol Message Types" in section 3.3 * "MESSAGE TYPES" of Rave PIC24 ICD.
*/ switch (command) { case RAVE_SP_CMD_GET_FIRMWARE_VERSION: return 0x11; case RAVE_SP_CMD_GET_BOOTLOADER_VERSION: return 0x12; case RAVE_SP_CMD_BOOT_SOURCE: return 0x14; case RAVE_SP_CMD_SW_WDT: return 0x1C; case RAVE_SP_CMD_PET_WDT: return 0x1D; case RAVE_SP_CMD_RESET: return 0x1E; case RAVE_SP_CMD_RESET_REASON: return 0x1F; case RAVE_SP_CMD_RMB_EEPROM: return 0x20; default: return -EINVAL;
}
}
staticconstchar *devm_rave_sp_version(struct device *dev, struct rave_sp_version *version)
{ /* * NOTE: The format string below uses %02d to display u16 * intentionally for the sake of backwards compatibility with * legacy software.
*/ return devm_kasprintf(dev, GFP_KERNEL, "%02d%02d%02d.%c%c\n",
version->hardware,
le16_to_cpu(version->major),
version->minor,
version->letter[0],
version->letter[1]);
}
ret = serdev_device_set_parity(serdev, SERDEV_PARITY_NONE); if (ret) {
dev_err(dev, "Failed to set parity\n"); return ret;
}
ret = rave_sp_get_status(sp); if (ret) {
dev_warn(dev, "Failed to get firmware status: %d\n", ret);
sp->part_number_firmware = unknown;
sp->part_number_bootloader = unknown;
}
/* * Those strings already have a \n embedded, so there's no * need to have one in format string.
*/
dev_info(dev, "Firmware version: %s", sp->part_number_firmware);
dev_info(dev, "Bootloader version: %s", sp->part_number_bootloader);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.