Import independent seat firmware source without build artifacts
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Host regression tests against the real v40 CAN dispatch function; no hardware motion."""
|
||||
from pathlib import Path
|
||||
import subprocess, tempfile
|
||||
root=Path(__file__).resolve().parents[2]
|
||||
source=(root/'firmware/application/seat_demo_compat.inc').read_text()
|
||||
start=source.index('void SeatDemoCompat_Service(void)')
|
||||
end=source.index('\nvoid SeatDemoCompat_ReleaseAxisForNative',start)
|
||||
service=source[start:end]
|
||||
preamble=r'''
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include "ota_can.h"
|
||||
#include "seat_legacy_version_query.h"
|
||||
#define SEAT_DEMO_CAN_COMMAND_ID 0x300
|
||||
#define SEAT_DEMO_OPCODE_STOP_ALL 9
|
||||
#define MOTOR_DIRECTION_STOPPED 0
|
||||
#define SEAT_DEMO_ACK_STOP_ALL_ACCEPTED 1
|
||||
#define SEAT_DEMO_REJECT_NONE 0
|
||||
typedef struct { unsigned opcode,motor,direction,sequence; } seat_demo_command_t;
|
||||
static bool seatDemoInitialized=true,seatDemoCalibrationWorker,seatDemoStopAllFromIsr;
|
||||
static unsigned seatDemoServiceDepth,seatDemoStopAllSequenceFromIsr;
|
||||
static bool seatDemoLastSequenceValid,seatDemoLastCommandValid;
|
||||
static unsigned seatDemoSequenceReference=123;
|
||||
static seat_demo_command_t seatDemoLastCommand;
|
||||
static ota_can_frame_t frames[512];
|
||||
static unsigned frameCount,frameNext,commandCount,thermalFrames,txCount,ackCount;
|
||||
static unsigned dynamicCalls,taskCalls,dispatchCalls,thermalCalls,feedbackCalls;
|
||||
static unsigned commands[512];
|
||||
static uint32_t Cy_SysLib_EnterCriticalSection(void){return 0;}
|
||||
static void Cy_SysLib_ExitCriticalSection(uint32_t s){(void)s;}
|
||||
void OtaCan_Service(void){}
|
||||
bool OtaCan_PopFrame(ota_can_frame_t *frame){if(frameNext==frameCount)return false;*frame=frames[frameNext++];return true;}
|
||||
bool OtaCan_QueueFrame(uint32_t id,const uint8_t data[8]){(void)id;(void)data;txCount++;return true;}
|
||||
static void SeatDemoCompat_StopNativeOwnersForAll(void){}
|
||||
static void SeatDemoCompat_StopAllInternal(uint16_t s){(void)s;}
|
||||
static void SeatDemoCompat_SetResponse(unsigned a,unsigned b,seat_demo_command_t *c){(void)a;(void)b;(void)c;ackCount++;}
|
||||
static void SeatDemoCompat_HandleCommand(const ota_can_frame_t *f){commands[commandCount++]=f->data[0];seatDemoSequenceReference=f->data[2]|((unsigned)f->data[3]<<8);}
|
||||
static void SeatDemoThermal_HandleFrame(const ota_can_frame_t *f){(void)f;thermalFrames++;}
|
||||
static void SeatDemoDynamic_Service(void){dynamicCalls++;}
|
||||
static void SeatDemoCompat_ServiceTasks(void){taskCalls++;}
|
||||
static void SeatDemoCompat_ServiceDispatcher(void){dispatchCalls++;}
|
||||
static void SeatDemoThermal_Service(void){thermalCalls++;}
|
||||
static void SeatDemoCompat_ServiceFeedback(void){feedbackCalls++;}
|
||||
'''
|
||||
tests=r'''
|
||||
int main(void){
|
||||
ota_can_frame_t q={.identifier=0x300,.dlc=8,.data={0x10,0x10,0,0,0,0,0,0}};
|
||||
assert(!SeatDemo_IsLegacyVersionQuery(NULL));
|
||||
for(unsigned i=0;i<65536;i++){q.data[2]=i;q.data[3]=i>>8;assert(SeatDemo_IsLegacyVersionQuery(&q));}
|
||||
for(unsigned opcode=0;opcode<256;opcode++){q.data[0]=opcode;assert(SeatDemo_IsLegacyVersionQuery(&q)==(opcode==0x10));}
|
||||
q.data[0]=0x10;
|
||||
for(unsigned i=4;i<8;i++){q.data[i]=1;assert(!SeatDemo_IsLegacyVersionQuery(&q));q.data[i]=0;}
|
||||
q.identifier=0x6a0;assert(!SeatDemo_IsLegacyVersionQuery(&q));q.identifier=0x300;
|
||||
q.dlc=7;assert(!SeatDemo_IsLegacyVersionQuery(&q));q.dlc=8;
|
||||
q.data[1]=0;assert(!SeatDemo_IsLegacyVersionQuery(&q));q.data[1]=0x10;
|
||||
for(unsigned i=0;i<200;i++)frames[frameCount++]=q;
|
||||
SeatDemoCompat_Service();
|
||||
assert(commandCount==0&&txCount==0&&ackCount==0&&seatDemoSequenceReference==123);
|
||||
assert(dynamicCalls==1&&taskCalls==1&&dispatchCalls==1&&thermalCalls==1&&feedbackCalls==1);
|
||||
assert(seatDemoServiceDepth==0);
|
||||
frameNext=frameCount=0;
|
||||
unsigned ops[]={1,3,9,0x0c,0x0e,0x0f};
|
||||
for(unsigned i=0;i<sizeof(ops)/sizeof(*ops);i++){
|
||||
frames[frameCount++]=q;
|
||||
ota_can_frame_t command=q;command.data[0]=ops[i];command.data[2]=i+1;command.data[3]=0;
|
||||
frames[frameCount++]=command;
|
||||
}
|
||||
ota_can_frame_t thermal=q;thermal.identifier=0x29e;frames[frameCount++]=thermal;
|
||||
SeatDemoCompat_Service();
|
||||
assert(commandCount==6&&thermalFrames==1&&seatDemoSequenceReference==6&&txCount==0);
|
||||
for(unsigned i=0;i<6;i++)assert(commands[i]==ops[i]);
|
||||
assert(dynamicCalls==2&&taskCalls==2&&dispatchCalls==2&&thermalCalls==2&&feedbackCalls==2);
|
||||
puts("PASS: 65536 legacy query sequences ignored; no query TX/ACK/sequence changes; mixed motion/STOP/dynamic/thermal frames retain routing and feedback service");
|
||||
}
|
||||
'''
|
||||
with tempfile.TemporaryDirectory(prefix='n7-v40-query-') as tmp:
|
||||
c=Path(tmp)/'test.c';exe=Path(tmp)/'test'
|
||||
c.write_text(preamble+service+tests)
|
||||
subprocess.run(['gcc','-std=c11','-Wall','-Wextra','-Werror','-I'+str(root/'firmware/bootloader/src'),'-I'+str(root/'firmware/application'),str(c),'-o',str(exe)],check=True)
|
||||
subprocess.run([str(exe)],check=True)
|
||||
Reference in New Issue
Block a user