#ifndef OTA_PROTOCOL_H #define OTA_PROTOCOL_H #include /* Classic CAN, 500 kbit/s, standard identifiers, DLC 8. */ #define OTA_CAN_CONTROL_ID (0x6A0ul) #define OTA_CAN_DATA_ID (0x6A1ul) #define OTA_CAN_RESPONSE_ID (0x6A2ul) #define OTA_CONTROL_MAGIC (0xC7u) #define OTA_DATA_MAGIC (0xD7u) #define OTA_RESPONSE_MAGIC (0x7Cu) #define OTA_BOOTLOADER_MAJOR (1u) #define OTA_BOOTLOADER_MINOR (0u) #define OTA_BOOT_WAIT_MS (2000ul) /* Control frame: magic, sequence, opcode, selector/flags, uint32 LE argument. */ typedef enum { OTA_OPCODE_PING = 0x01u, OTA_OPCODE_INFO = 0x02u, OTA_OPCODE_BEGIN_SIZE = 0x10u, OTA_OPCODE_BEGIN_CRC32 = 0x11u, OTA_OPCODE_ROW_BEGIN = 0x20u, OTA_OPCODE_ROW_COMMIT = 0x21u, OTA_OPCODE_END = 0x30u, OTA_OPCODE_ABORT = 0x31u, OTA_OPCODE_BOOT = 0x40u, /* Runtime motor-test application commands. The Bootloader deliberately * rejects these opcodes; the application deliberately rejects the flash * opcodes, so the Android client can identify the active side safely. */ OTA_OPCODE_TEST_INFO = 0x50u, OTA_OPCODE_TEST_START = 0x51u, OTA_OPCODE_TEST_STOP = 0x52u, OTA_OPCODE_ENTER_BOOTLOADER = 0x53u, /* Shared four-axis seat telemetry. Calibration and homing are accepted * only by the dedicated calibration application image. */ OTA_OPCODE_SEAT_INFO = 0x60u, OTA_OPCODE_SEAT_CALIBRATE = 0x61u, OTA_OPCODE_SEAT_HOME = 0x62u, OTA_OPCODE_SEAT_STOP = 0x63u, /* Interactive position control used by the cockpit HMI. MOVE carries a * board-axis selector and a 0..1000 target. All four axes may move at * once; HEARTBEAT renews one axis lease (or every active lease with the * all-axes selector) without changing any target. */ OTA_OPCODE_SEAT_MOVE = 0x64u, OTA_OPCODE_SEAT_HEARTBEAT = 0x65u, /* Board-owned, time-bounded comfort motions. START selector chooses the * pattern and argument carries duration seconds; STOP remains the common * OTA_OPCODE_SEAT_STOP command. */ OTA_OPCODE_SEAT_DYNAMIC_START = 0x66u, /* Absolute move with explicit PWM. Argument layout is target permille in * bits 0..15, duty percent in bits 16..23 and zero in bits 24..31. */ OTA_OPCODE_SEAT_MOVE_WITH_DUTY = 0x67u } ota_opcode_t; typedef enum { OTA_STATUS_OK = 0x00u, OTA_STATUS_BAD_MAGIC = 0x01u, OTA_STATUS_BAD_OPCODE = 0x02u, OTA_STATUS_BAD_STATE = 0x03u, OTA_STATUS_BAD_ARGUMENT = 0x04u, OTA_STATUS_FLASH_ERROR = 0x05u, OTA_STATUS_ROW_INCOMPLETE = 0x06u, OTA_STATUS_ROW_CRC_MISMATCH = 0x07u, OTA_STATUS_IMAGE_CRC_MISMATCH = 0x08u, OTA_STATUS_INVALID_VECTOR = 0x09u, OTA_STATUS_NO_VALID_APP = 0x0Au, OTA_STATUS_ALREADY_COMMITTED = 0x0Bu, OTA_STATUS_RX_OVERFLOW = 0x0Cu, OTA_STATUS_BUS_OFF = 0x0Du, OTA_STATUS_DATA_CONFLICT = 0x0Eu } ota_status_t; typedef enum { OTA_INFO_BOOT_VERSION = 0u, OTA_INFO_STATE = 1u, OTA_INFO_APPLICATION_BASE = 2u, OTA_INFO_APPLICATION_LIMIT = 3u, OTA_INFO_APPLICATION_SIZE = 4u, OTA_INFO_APPLICATION_CRC32 = 5u, OTA_INFO_NEXT_ROW = 6u, OTA_INFO_LAST_ERROR = 7u } ota_info_selector_t; typedef enum { OTA_STATE_IDLE = 0u, OTA_STATE_HAVE_SIZE, OTA_STATE_READY, OTA_STATE_RECEIVING_ROW, OTA_STATE_COMPLETE, OTA_STATE_ERROR } ota_state_t; typedef enum { OTA_TEST_INFO_STATE = 0u, OTA_TEST_INFO_RISING_EDGES, OTA_TEST_INFO_TOTAL_EDGES, OTA_TEST_INFO_ACTIVE_MS, OTA_TEST_INFO_SAFETY_WINDOW_PULSES, OTA_TEST_INFO_DRIVER_DIAGNOSTICS, OTA_TEST_INFO_CALIBRATION_HALL } ota_test_info_selector_t; typedef enum { OTA_SEAT_INFO_JOB = 0u, OTA_SEAT_INFO_AXIS0_POSITION_RANGE = 1u, OTA_SEAT_INFO_AXIS1_POSITION_RANGE = 2u, OTA_SEAT_INFO_AXIS2_POSITION_RANGE = 3u, OTA_SEAT_INFO_AXIS3_POSITION_RANGE = 4u, OTA_SEAT_INFO_AXIS0_FLAGS = 5u, OTA_SEAT_INFO_AXIS1_FLAGS = 6u, OTA_SEAT_INFO_AXIS2_FLAGS = 7u, OTA_SEAT_INFO_AXIS3_FLAGS = 8u, OTA_SEAT_INFO_AXIS0_PHYSICAL_X100 = 9u, OTA_SEAT_INFO_AXIS1_PHYSICAL_X100 = 10u, OTA_SEAT_INFO_AXIS2_PHYSICAL_X100 = 11u, OTA_SEAT_INFO_AXIS3_PHYSICAL_X100 = 12u, OTA_SEAT_INFO_STORAGE = 13u, OTA_SEAT_INFO_RUNTIME_KIND = 14u } ota_seat_info_selector_t; typedef enum { OTA_SEAT_JOB_NONE = 0u, OTA_SEAT_JOB_CALIBRATE = 1u, OTA_SEAT_JOB_HOME = 2u, OTA_SEAT_JOB_MOVE = 3u, OTA_SEAT_JOB_DYNAMIC = 4u } ota_seat_job_type_t; typedef enum { OTA_SEAT_PHASE_IDLE = 0u, OTA_SEAT_PHASE_FIND_NEAR = 1u, OTA_SEAT_PHASE_FIND_FAR = 2u, OTA_SEAT_PHASE_RETURN_NEAR = 3u, OTA_SEAT_PHASE_SAVE = 4u, OTA_SEAT_PHASE_COMPLETE = 5u, OTA_SEAT_PHASE_FAILED = 6u, OTA_SEAT_PHASE_MOVING = 7u, OTA_SEAT_PHASE_STOPPED = 8u, OTA_SEAT_PHASE_DYNAMIC = 9u } ota_seat_job_phase_t; typedef enum { OTA_SEAT_DYNAMIC_CRADLE = 1u, OTA_SEAT_DYNAMIC_ROCKING_HORSE = 2u } ota_seat_dynamic_mode_t; #define OTA_SEAT_JOB_ACTIVE (1ul << 0u) #define OTA_SEAT_JOB_COMPLETE (1ul << 1u) #define OTA_SEAT_JOB_SUCCESS (1ul << 2u) #define OTA_SEAT_JOB_STORAGE_OK (1ul << 3u) #define OTA_SEAT_JOB_TYPE_SHIFT (4u) #define OTA_SEAT_JOB_PHASE_SHIFT (8u) #define OTA_SEAT_JOB_AXIS_SHIFT (12u) #define OTA_SEAT_JOB_ERROR_SHIFT (16u) #define OTA_SEAT_JOB_PROGRESS_SHIFT (24u) #define OTA_SEAT_JOB_AXIS_MULTIPLE (0x0Fu) #define OTA_SEAT_AXIS_ALL (0xFFu) #define OTA_SEAT_AXIS_VALID (1ul << 0u) #define OTA_SEAT_AXIS_MOVING (1ul << 1u) #define OTA_SEAT_AXIS_CALIBRATING (1ul << 2u) #define OTA_SEAT_AXIS_DRIVER_FAULT (1ul << 3u) #define OTA_SEAT_AXIS_PERSISTED (1ul << 4u) #define OTA_SEAT_AXIS_DIRECTION_SHIFT (8u) #define OTA_SEAT_AXIS_EVENT_SHIFT (16u) #define OTA_SEAT_RUNTIME_FBL (0x46424C31ul) /* "FBL1" */ #define OTA_SEAT_RUNTIME_CALIBRATION (0x43414C31ul) /* "CAL1" */ #define OTA_SEAT_RUNTIME_SELF_COMPOSE (0x44495931ul) /* "DIY1" */ #define OTA_SEAT_RUNTIME_DUAL_PROTOCOL (0x44554131ul) /* "DUA1" */ #define OTA_TEST_STATE_ACTIVE (1ul << 0u) #define OTA_TEST_STATE_COMPLETE (1ul << 1u) #define OTA_TEST_STATE_DRIVER_FAULT (1ul << 2u) #define OTA_TEST_STATE_PREPARED (1ul << 3u) #define OTA_TEST_STATE_TIMING_VALID (1ul << 4u) #define OTA_TEST_STATE_DIAGNOSTICS_VALID (1ul << 5u) #define OTA_TEST_STATE_STOP_REASON_SHIFT (8u) #define OTA_TEST_STATE_MODE_SHIFT (16u) #define OTA_TEST_STATE_DIRECTION_SHIFT (20u) /* Application -> bootloader handoff through backup-domain registers. */ #define OTA_BOOT_REQUEST_MAGIC (0x424F4F54ul) /* "BOOT" */ #define OTA_BOOT_REQUEST_MAGIC_INVERSE (~OTA_BOOT_REQUEST_MAGIC) #endif /* OTA_PROTOCOL_H */