Import independent seat firmware source without build artifacts
This commit is contained in:
@@ -0,0 +1,306 @@
|
||||
/* Included into the generated main_cm0plus.c for the eight Android-controlled
|
||||
* direction-test images. It intentionally lives in the same translation unit
|
||||
* so it can reuse the proven static motor safety/event implementation without
|
||||
* changing the bundled third_party reference source. */
|
||||
|
||||
static bool otaInteractiveDriverInitOk;
|
||||
static bool otaInteractiveFinalized = true;
|
||||
|
||||
static void OtaInteractive_ClearResult(void)
|
||||
{
|
||||
simpleDirectionResult.risingEdges = 0ul;
|
||||
simpleDirectionResult.totalEdges = 0ul;
|
||||
simpleDirectionResult.activeMs = 0ul;
|
||||
simpleDirectionResult.safetyWindowPulses = 0ul;
|
||||
simpleDirectionResult.driverStatus = 0u;
|
||||
simpleDirectionResult.driverFaults = 0u;
|
||||
simpleDirectionResult.finalHallLevel = 0u;
|
||||
simpleDirectionResult.stopReason =
|
||||
SIMPLE_DIRECTION_STOP_REASON_NOT_STARTED;
|
||||
simpleDirectionResult.armed = false;
|
||||
simpleDirectionResult.prepared = false;
|
||||
simpleDirectionResult.timingValid = false;
|
||||
simpleDirectionResult.diagnosticsValid = false;
|
||||
simpleDirectionRunActive = false;
|
||||
simpleDirectionRunComplete = false;
|
||||
}
|
||||
|
||||
static void OtaInteractive_Finalize(void)
|
||||
{
|
||||
uint8_t driverStatus = 0u;
|
||||
bool statusReadOk;
|
||||
bool stopOk;
|
||||
|
||||
if((false == simpleDirectionRunComplete) ||
|
||||
(false != otaInteractiveFinalized))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Motor_ServiceAll();
|
||||
statusReadOk = Drv8718_ReadRegRaw(DRV8718_REG_IC_STAT1,
|
||||
&driverStatus);
|
||||
if(false != statusReadOk)
|
||||
{
|
||||
simpleDirectionResult.driverStatus = driverStatus;
|
||||
simpleDirectionResult.driverFaults =
|
||||
(uint16_t)(driverStatus & DRV8718_IC_STAT1_ALERT_MASK);
|
||||
}
|
||||
stopOk = (MOTOR_API_SUCCESS ==
|
||||
Motor_StopMode((motor_mode_t)MOTOR_AUTOMATED_TEST_MODE));
|
||||
if(false != stopOk)
|
||||
{
|
||||
stopOk = Motor_WaitForCoastToSettle(
|
||||
(motor_mode_t)MOTOR_AUTOMATED_TEST_MODE);
|
||||
}
|
||||
simpleDirectionResult.diagnosticsValid = statusReadOk && stopOk;
|
||||
SimpleDirectionTest_ImmediateAllOff();
|
||||
(void)OtaSeat_SavePersistentState();
|
||||
otaInteractiveFinalized = true;
|
||||
}
|
||||
|
||||
static void OtaInteractive_Stop(void)
|
||||
{
|
||||
uint32_t savedIntrStatus;
|
||||
|
||||
if(false != simpleDirectionRunActive)
|
||||
{
|
||||
savedIntrStatus = Cy_SysLib_EnterCriticalSection();
|
||||
Motor_RequestEventFromIsr(MOTOR_AUTOMATED_TEST_MODE,
|
||||
MOTOR_EVENT_ABORTED);
|
||||
Cy_SysLib_ExitCriticalSection(savedIntrStatus);
|
||||
}
|
||||
if((false == simpleDirectionRunComplete) &&
|
||||
(false == otaInteractiveFinalized))
|
||||
{
|
||||
SimpleDirectionTest_ImmediateAllOff();
|
||||
SimpleDirectionTest_CaptureStopFromIsr(
|
||||
(uint32_t)(hallTimebaseTicks - simpleDirectionStartTicks),
|
||||
Hall_ReadLevel(MOTOR_AUTOMATED_TEST_MODE),
|
||||
SIMPLE_DIRECTION_STOP_REASON_ABORTED,
|
||||
motorRuntime[MOTOR_AUTOMATED_TEST_MODE].recentWindowPulses);
|
||||
}
|
||||
OtaInteractive_Finalize();
|
||||
}
|
||||
|
||||
static bool OtaInteractive_Start(void)
|
||||
{
|
||||
if((false != simpleDirectionRunActive) ||
|
||||
(false != driverFaultLatched))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
OtaInteractive_ClearResult();
|
||||
simpleDirectionResult.armed = true;
|
||||
simpleDirectionResult.prepared =
|
||||
SimpleDirectionTest_Prepare(otaInteractiveDriverInitOk);
|
||||
if(false == simpleDirectionResult.prepared)
|
||||
{
|
||||
simpleDirectionResult.prepared = false;
|
||||
SimpleDirectionTest_ImmediateAllOff();
|
||||
return false;
|
||||
}
|
||||
|
||||
/* OtaInteractiveTest_Run() and every completed/stopped test use
|
||||
* SimpleDirectionTest_ImmediateAllOff(), which asserts the external
|
||||
* DRVOFF pin. The original one-shot direction test never starts again
|
||||
* after that call, but an interactive OTA image must explicitly release
|
||||
* DRVOFF before each new TEST_START. Without this transition the SPI
|
||||
* bridge/PWM setup succeeds while the DRV8718 power outputs remain
|
||||
* hardware-disabled (IC_STAT1 still reads 0x80 and Hall stays at zero). */
|
||||
Cy_GPIO_Clr(DRV_DRVOFF_PORT, DRV_DRVOFF_PIN);
|
||||
Cy_SysTick_DelayInUs(100ul);
|
||||
if(false == SimpleDirectionTest_Start())
|
||||
{
|
||||
simpleDirectionResult.prepared = false;
|
||||
SimpleDirectionTest_ImmediateAllOff();
|
||||
return false;
|
||||
}
|
||||
otaInteractiveFinalized = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static uint32_t OtaInteractive_StateValue(void)
|
||||
{
|
||||
uint32_t value =
|
||||
((uint32_t)simpleDirectionResult.stopReason <<
|
||||
OTA_TEST_STATE_STOP_REASON_SHIFT) |
|
||||
((uint32_t)MOTOR_AUTOMATED_TEST_MODE <<
|
||||
OTA_TEST_STATE_MODE_SHIFT) |
|
||||
((uint32_t)MOTOR_AUTOMATED_TEST_DIRECTION <<
|
||||
OTA_TEST_STATE_DIRECTION_SHIFT);
|
||||
|
||||
if(false != simpleDirectionRunActive)
|
||||
{
|
||||
value |= OTA_TEST_STATE_ACTIVE;
|
||||
}
|
||||
if(false != simpleDirectionRunComplete)
|
||||
{
|
||||
value |= OTA_TEST_STATE_COMPLETE;
|
||||
}
|
||||
if(false != driverFaultLatched)
|
||||
{
|
||||
value |= OTA_TEST_STATE_DRIVER_FAULT;
|
||||
}
|
||||
if(false != simpleDirectionResult.prepared)
|
||||
{
|
||||
value |= OTA_TEST_STATE_PREPARED;
|
||||
}
|
||||
if(false != simpleDirectionResult.timingValid)
|
||||
{
|
||||
value |= OTA_TEST_STATE_TIMING_VALID;
|
||||
}
|
||||
if(false != simpleDirectionResult.diagnosticsValid)
|
||||
{
|
||||
value |= OTA_TEST_STATE_DIAGNOSTICS_VALID;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
static uint32_t OtaInteractive_InfoValue(uint8_t selector)
|
||||
{
|
||||
switch((ota_test_info_selector_t)selector)
|
||||
{
|
||||
case OTA_TEST_INFO_STATE:
|
||||
return OtaInteractive_StateValue();
|
||||
case OTA_TEST_INFO_RISING_EDGES:
|
||||
return simpleDirectionResult.risingEdges;
|
||||
case OTA_TEST_INFO_TOTAL_EDGES:
|
||||
return simpleDirectionResult.totalEdges;
|
||||
case OTA_TEST_INFO_ACTIVE_MS:
|
||||
return simpleDirectionResult.activeMs;
|
||||
case OTA_TEST_INFO_SAFETY_WINDOW_PULSES:
|
||||
return simpleDirectionResult.safetyWindowPulses;
|
||||
case OTA_TEST_INFO_DRIVER_DIAGNOSTICS:
|
||||
return ((uint32_t)simpleDirectionResult.driverFaults << 16u) |
|
||||
(uint32_t)simpleDirectionResult.driverStatus;
|
||||
default:
|
||||
return 0ul;
|
||||
}
|
||||
}
|
||||
|
||||
static void OtaInteractive_Respond(const ota_can_control_frame_t *frame,
|
||||
ota_status_t status,
|
||||
uint32_t value)
|
||||
{
|
||||
(void)OtaCan_QueueResponse(frame->data[1], frame->data[2],
|
||||
(uint8_t)status, value);
|
||||
}
|
||||
|
||||
static void OtaInteractive_EnterBootloader(
|
||||
const ota_can_control_frame_t *frame)
|
||||
{
|
||||
uint32_t waitMs;
|
||||
|
||||
OtaInteractive_Stop();
|
||||
(void)OtaSeat_SavePersistentState();
|
||||
OtaInteractive_Respond(frame, OTA_STATUS_OK,
|
||||
OtaInteractive_StateValue());
|
||||
for(waitMs = 0ul; waitMs < 100ul; waitMs++)
|
||||
{
|
||||
OtaCan_Service();
|
||||
if(false != OtaCan_TxIdle())
|
||||
{
|
||||
break;
|
||||
}
|
||||
Cy_SysTick_DelayInUs(1000ul);
|
||||
}
|
||||
SimpleDirectionTest_ImmediateAllOff();
|
||||
Ota_EnterBootloader();
|
||||
}
|
||||
|
||||
static void OtaInteractive_HandleControl(
|
||||
const ota_can_control_frame_t *frame)
|
||||
{
|
||||
uint8_t opcode = frame->data[2];
|
||||
|
||||
if(frame->data[0] != OTA_CONTROL_MAGIC)
|
||||
{
|
||||
OtaInteractive_Respond(frame, OTA_STATUS_BAD_MAGIC, 0ul);
|
||||
return;
|
||||
}
|
||||
|
||||
if(false != OtaSeat_HandleInfoControl(frame))
|
||||
{
|
||||
return;
|
||||
}
|
||||
switch((ota_opcode_t)opcode)
|
||||
{
|
||||
case OTA_OPCODE_TEST_INFO:
|
||||
if(frame->data[3] > OTA_TEST_INFO_DRIVER_DIAGNOSTICS)
|
||||
{
|
||||
OtaInteractive_Respond(frame, OTA_STATUS_BAD_ARGUMENT,
|
||||
frame->data[3]);
|
||||
}
|
||||
else
|
||||
{
|
||||
OtaInteractive_Respond(
|
||||
frame, OTA_STATUS_OK,
|
||||
OtaInteractive_InfoValue(frame->data[3]));
|
||||
}
|
||||
break;
|
||||
case OTA_OPCODE_TEST_START:
|
||||
if(false != OtaInteractive_Start())
|
||||
{
|
||||
OtaInteractive_Respond(frame, OTA_STATUS_OK,
|
||||
OtaInteractive_StateValue());
|
||||
}
|
||||
else
|
||||
{
|
||||
OtaInteractive_Respond(frame, OTA_STATUS_BAD_STATE,
|
||||
OtaInteractive_StateValue());
|
||||
}
|
||||
break;
|
||||
case OTA_OPCODE_TEST_STOP:
|
||||
OtaInteractive_Stop();
|
||||
OtaInteractive_Respond(frame, OTA_STATUS_OK,
|
||||
OtaInteractive_StateValue());
|
||||
break;
|
||||
case OTA_OPCODE_ENTER_BOOTLOADER:
|
||||
OtaInteractive_EnterBootloader(frame);
|
||||
break;
|
||||
default:
|
||||
OtaInteractive_Respond(frame, OTA_STATUS_BAD_OPCODE, opcode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int OtaInteractiveTest_Run(bool driverInitOk)
|
||||
{
|
||||
ota_can_control_frame_t frame;
|
||||
|
||||
/* Keep the original one-shot runner linked for source-level parity; the
|
||||
* interactive build intentionally dispatches through this loop instead. */
|
||||
(void)SimpleDirectionTest_Run;
|
||||
otaInteractiveDriverInitOk = driverInitOk;
|
||||
OtaInteractive_ClearResult();
|
||||
OtaSeat_RestorePersistentState();
|
||||
SimpleDirectionTest_ImmediateAllOff();
|
||||
OtaCan_DebugStart();
|
||||
if(false == OtaCan_Init())
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
SimpleDirectionTest_ImmediateAllOff();
|
||||
}
|
||||
}
|
||||
|
||||
for(;;)
|
||||
{
|
||||
Motor_ServiceAll();
|
||||
OtaCan_Service();
|
||||
|
||||
if((false != simpleDirectionRunComplete) &&
|
||||
(false == otaInteractiveFinalized))
|
||||
{
|
||||
OtaInteractive_Finalize();
|
||||
}
|
||||
while(false != OtaCan_PopControl(&frame))
|
||||
{
|
||||
OtaInteractive_HandleControl(&frame);
|
||||
OtaCan_Service();
|
||||
}
|
||||
__WFI();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user