Files
seat-firmware/firmware/application/ota_seat_runtime.inc
T

245 lines
7.6 KiB
C++

/* Shared board-authoritative position/range state for every OTA application.
* This file is included after the motor implementation so it can snapshot and
* restore the proven per-axis runtime without changing the bundled source. */
static bool otaSeatStateLoaded;
static bool otaSeatLastSaveOk;
static uint32_t otaSeatPersistedMask;
static uint32_t otaSeatStateSequence;
static bool otaSeatJobActive;
static bool otaSeatJobComplete;
static bool otaSeatJobSuccess;
static ota_seat_job_type_t otaSeatJobType = OTA_SEAT_JOB_NONE;
static ota_seat_job_phase_t otaSeatJobPhase = OTA_SEAT_PHASE_IDLE;
static uint8_t otaSeatJobAxis = 0x0Fu;
static uint8_t otaSeatJobError;
static uint8_t otaSeatJobProgress;
static bool OtaSeat_SavePersistentState(void);
static uint32_t OtaSeat_RuntimeKind(void)
{
#if (MOTOR_OTA_CALIBRATION != 0u)
return OTA_SEAT_RUNTIME_CALIBRATION;
#elif (MOTOR_OTA_SELF_COMPOSE != 0u)
return OTA_SEAT_RUNTIME_DUAL_PROTOCOL;
#else
return OTA_SEAT_RUNTIME_FBL;
#endif
}
static void OtaSeat_RestorePersistentState(void)
{
ota_seat_state_data_t stored;
uint32_t axis;
uint32_t savedIntrStatus;
bool normalizePersistentState = false;
otaSeatStateLoaded = OtaSeatState_Load(&stored);
otaSeatLastSaveOk = otaSeatStateLoaded;
otaSeatPersistedMask = 0ul;
otaSeatStateSequence = 0ul;
if(false == otaSeatStateLoaded)
{
return;
}
savedIntrStatus = Cy_SysLib_EnterCriticalSection();
otaSeatStateSequence = stored.sequence;
otaSeatPersistedMask = 0ul;
for(axis = 0ul; axis < MOTOR_PROFILE_COUNT; axis++)
{
uint32_t defaultRange = motorProfiles[axis].defaultMaxHallCount;
motorRuntime[axis].maxHallCount = defaultRange;
if((stored.validMask & (1ul << axis)) != 0ul)
{
uint32_t position = stored.position[axis];
/* The Base owns all four physical Hall ranges. Persistent storage
* remembers position only and can never override a Base range. */
if(stored.range[axis] != defaultRange)
{
normalizePersistentState = true;
}
if(position > defaultRange)
{
position = defaultRange;
normalizePersistentState = true;
}
motorRuntime[axis].positionHallCount = position;
motorRuntime[axis].positionValid = true;
otaSeatPersistedMask |= 1ul << axis;
}
}
Cy_SysLib_ExitCriticalSection(savedIntrStatus);
if(false != normalizePersistentState)
{
(void)OtaSeat_SavePersistentState();
}
}
static bool OtaSeat_SavePersistentState(void)
{
ota_seat_state_data_t state;
uint32_t axis;
uint32_t savedIntrStatus;
state.sequence = otaSeatStateSequence + 1ul;
state.validMask = 0ul;
savedIntrStatus = Cy_SysLib_EnterCriticalSection();
for(axis = 0ul; axis < MOTOR_PROFILE_COUNT; axis++)
{
uint32_t range = motorProfiles[axis].defaultMaxHallCount;
uint32_t position = motorRuntime[axis].positionHallCount;
motorRuntime[axis].maxHallCount = range;
if(position > range)
{
position = range;
}
state.range[axis] = range;
state.position[axis] = position;
if(false != motorRuntime[axis].positionValid)
{
state.validMask |= 1ul << axis;
}
}
Cy_SysLib_ExitCriticalSection(savedIntrStatus);
otaSeatLastSaveOk = OtaSeatState_Save(&state);
if(false != otaSeatLastSaveOk)
{
otaSeatStateLoaded = true;
otaSeatStateSequence = state.sequence;
otaSeatPersistedMask = state.validMask;
}
return otaSeatLastSaveOk;
}
static uint32_t OtaSeat_JobStateValue(void)
{
uint32_t value =
((uint32_t)otaSeatJobType << OTA_SEAT_JOB_TYPE_SHIFT) |
((uint32_t)otaSeatJobPhase << OTA_SEAT_JOB_PHASE_SHIFT) |
((uint32_t)otaSeatJobAxis << OTA_SEAT_JOB_AXIS_SHIFT) |
((uint32_t)otaSeatJobError << OTA_SEAT_JOB_ERROR_SHIFT) |
((uint32_t)otaSeatJobProgress << OTA_SEAT_JOB_PROGRESS_SHIFT);
if(false != otaSeatJobActive) value |= OTA_SEAT_JOB_ACTIVE;
if(false != otaSeatJobComplete) value |= OTA_SEAT_JOB_COMPLETE;
if(false != otaSeatJobSuccess) value |= OTA_SEAT_JOB_SUCCESS;
if(false != otaSeatLastSaveOk) value |= OTA_SEAT_JOB_STORAGE_OK;
return value;
}
static uint32_t OtaSeat_AxisPositionRangeValue(uint32_t axis)
{
uint32_t position;
uint32_t range;
uint32_t savedIntrStatus;
savedIntrStatus = Cy_SysLib_EnterCriticalSection();
position = motorRuntime[axis].positionHallCount;
range = motorRuntime[axis].maxHallCount;
Cy_SysLib_ExitCriticalSection(savedIntrStatus);
if(position > 65535ul) position = 65535ul;
if(range > 65535ul) range = 65535ul;
return (range << 16u) | position;
}
static uint32_t OtaSeat_AxisFlagsValue(uint32_t axis)
{
uint32_t value;
uint32_t savedIntrStatus;
savedIntrStatus = Cy_SysLib_EnterCriticalSection();
value = ((uint32_t)motorRuntime[axis].direction <<
OTA_SEAT_AXIS_DIRECTION_SHIFT) |
((uint32_t)motorRuntime[axis].lastEvent <<
OTA_SEAT_AXIS_EVENT_SHIFT);
if(false != motorRuntime[axis].positionValid)
{
value |= OTA_SEAT_AXIS_VALID;
}
if((motorRuntime[axis].direction != MOTOR_DIRECTION_STOPPED) ||
(false != motorRuntime[axis].startPending))
{
value |= OTA_SEAT_AXIS_MOVING;
}
if(false != motorRuntime[axis].calibrating)
{
value |= OTA_SEAT_AXIS_CALIBRATING;
}
Cy_SysLib_ExitCriticalSection(savedIntrStatus);
if(false != driverFaultLatched) value |= OTA_SEAT_AXIS_DRIVER_FAULT;
if((otaSeatPersistedMask & (1ul << axis)) != 0ul)
{
value |= OTA_SEAT_AXIS_PERSISTED;
}
return value;
}
static uint32_t OtaSeat_InfoValue(uint8_t selector)
{
uint32_t axis;
if(selector == OTA_SEAT_INFO_JOB)
{
return OtaSeat_JobStateValue();
}
if((selector >= OTA_SEAT_INFO_AXIS0_POSITION_RANGE) &&
(selector <= OTA_SEAT_INFO_AXIS3_POSITION_RANGE))
{
axis = (uint32_t)(selector - OTA_SEAT_INFO_AXIS0_POSITION_RANGE);
return OtaSeat_AxisPositionRangeValue(axis);
}
if((selector >= OTA_SEAT_INFO_AXIS0_FLAGS) &&
(selector <= OTA_SEAT_INFO_AXIS3_FLAGS))
{
axis = (uint32_t)(selector - OTA_SEAT_INFO_AXIS0_FLAGS);
return OtaSeat_AxisFlagsValue(axis);
}
if((selector >= OTA_SEAT_INFO_AXIS0_PHYSICAL_X100) &&
(selector <= OTA_SEAT_INFO_AXIS3_PHYSICAL_X100))
{
axis = (uint32_t)(selector - OTA_SEAT_INFO_AXIS0_PHYSICAL_X100);
return motorProfiles[axis].maxPhysicalValueX100;
}
if(selector == OTA_SEAT_INFO_STORAGE)
{
return (otaSeatPersistedMask & 0x0Ful) |
((false != otaSeatStateLoaded) ? (1ul << 8u) : 0ul) |
((false != otaSeatLastSaveOk) ? (1ul << 9u) : 0ul) |
((otaSeatStateSequence & 0xFFFFul) << 16u);
}
if(selector == OTA_SEAT_INFO_RUNTIME_KIND)
{
return OtaSeat_RuntimeKind();
}
return 0ul;
}
static bool OtaSeat_HandleInfoControl(const ota_can_control_frame_t *frame)
{
uint8_t selector;
if(frame->data[2] != OTA_OPCODE_SEAT_INFO)
{
return false;
}
selector = frame->data[3];
if(selector > OTA_SEAT_INFO_RUNTIME_KIND)
{
(void)OtaCan_QueueResponse(frame->data[1], frame->data[2],
OTA_STATUS_BAD_ARGUMENT, selector);
}
else
{
(void)OtaCan_QueueResponse(frame->data[1], frame->data[2],
OTA_STATUS_OK,
OtaSeat_InfoValue(selector));
}
return true;
}