//***************************************************************************** // (C) Automotive Lighting Reutlingen GmbH // Tuebinger Strasse 123, 72762 Reutlingen, Germany // // Automotive Lighting Reutlingen GmbH owns all the rights to this work. // This work shall not be copied, reproduced, used, modified, transferred // or its information shall not be disclosed without the prior written // authorization of Automotive Lighting Reutlingen GmbH. //***************************************************************************** //----------------------------------------------------------------------------- /// \file CddStp8899Com.c /// /// \brief Handling of Stepper-Communication via SPI - Texas Instruments TI-DRV8899 / DRV8889A /// /// \descr Handling of Stepper-Communication via SPI incl. Data-Mirror- & Error-Handling /// /// Stat-Reg-'B' - Basic-Status - comes each time 'automatically' - 1 | 1 | UVLO | CPUV | OCP | STL | TF | OL /// Stat-Reg-0 - Fault-Status - FAULT | SPI_ERROR | UVLO | CPUV | OCP | STL | TF | OL /// Stat-Reg-1 - Diag-Status-1 - OCP_LS2_B | OCP_HS2_B | OCP_LS1_B | OCP_HS1_B | OCP_LS2_A | OCP_HS2_A | OCP_LS1_A | OCP_HS1_A /// Stat-Reg-2 - Diag-Status-2 - UTW | OTW | OTS | STL_LRN_OK | STALL | RSVD | OL_B | OL_A /// /// Ctrl-Reg-1 - TRQ_DAC [3:0] | RSVD | SLEW_RATE [1:0] /// Ctrl-Reg-2 - DIS_OUT | RSVD | TOFF [1:0] | DECAY [2:0] /// Ctrl-Reg-3 - DIR | STEP | SPI_DIR | SPI_STEP | MICROSTEP_MODE [3:0] /// Ctrl-Reg-4 - CLR_FLT | LOCK [2:0] | EN_OL | OCP_MODE | OTSD_MODE | TW_REP - e.g. EN_OL: 0x31=0011.0001 | 0x39=0011.1001 /// Ctrl-Reg-5 - RSVD [1:0] | STL_LRN | EN_STL | STL_REP | OL_TIME [1:0] | EN_SR_BLANK /// Ctrl-Reg-6 - STALL_TH [7:0] /// Ctrl-Reg-7 - TRQ_COUNT [7:0] /// Ctrl-Reg-8 - RSVD | REV_ID [3:0] /// /// New Error-Debouncing /// SPI-Error and OpenLoad-Error are LATCHED errors -> in order to have any debouncing the Error-Bit has to be 'cleared': Ctrl-Reg-4 'CLR_FLT' /// /// Additional information can be found in the design description (Link: /// MDDD) /// /// \author Ott, Peter ALRT/EEG-PM2 (otp2rt) /// J. Kling ALRT-EES6 (f84304b) //----------------------------------------------------------------------------- #include #include #include #include #include #include #include <../Cfg/CddStp_RoutCfg.h> // Access to EFT-Data & IoHwAbUser-Fcts (e.g. 'CDDSTP_EftDataValid' == 'CddEft_DataValid') #ifndef UNIT_TEST // NOT Unit-Tests = 'regular' #include #include #else // Unit-Tests! uint32 CddStp_UnitTestHelper_ul1; uint32 CddStp_UnitTestHelper_ul2; boolean CddStp_UnitTestHelper_bo1; boolean CddStp_UnitTestHelper_bo2; #define CFA_CNT_STP_88XX (4u) //#include <../../Cust/Bw/Bw16/App/Bsw/Cdd/CddStp/CddStpPrj.h> #include #include tCddStp_Eft_EcuVarCfg Test_Eft_EcuVarCfg_Used[2]; // = CDDTPS92520_Eft_EcuVarCfg_Default; -- 00: not fitted | 01 : DRV8899 | 02 : DRV8889A tieDataStatus CddStp_UnitTest__EftDataStatus = tieDataStatus_Invalid; const uint8 *Test_Eft_EcuVarCfg_ucDrvType(uint8 dvcIdx) { return &Test_Eft_EcuVarCfg_Used[dvcIdx].ucType; } boolean Test_EftDataValid(void) { return CddStp_UnitTest__EftDataStatus; } #endif #ifdef CDDSTP_CFG_SIMULATION // defined in '.\Asr6\Src\Src_AL\Cust\Bw\Bw16\App\Bsw\Cdd\CddStp\CddStpPrj.h' #include #endif // CDDSTP_CFG_SIMULATION #include <8899/CddStp8899Cfg.h> #include <88XX/CddStp88XX_HalStp.h> #include <8889A/CddStp8889A_StallDetection.h> // (optional AND) dynamically Stall-Detection ONLY during referencing 'down' (= 'Ref1') #include <8899/CddStp8899Com.h> //============================================================================= // defines //============================================================================= #define CDDSTP8899_CHECKDRVDEFECT_MAX (250u) // SPI-Check-Fct is called every 1ms -> wait 4x54ms before report an SPI-Error (debouncing!) - // N.b.: Whole Schedule-Table -> takes 54ms for one full 'round' #define CDDSTP8899_VBATSDrvDefect (5500u) // [mV] VBATS < 2.5 V but 5.5 V because of 2 ms SysVolt average - DRV88XX specific #define CDDSTP8899_RegValVBATSDD (0xFFu) // control and status register value in case of VBATS < 2.5 V: SPI does not work and data is set by pull up resistances #define CDDSTP8899_SRBValVBATSDD (0x3Fu) // Basic status register value in case of VBATS < 2.5 V: SPI does not work and data is set by pull up resistances // reserved register-values #define RSVD_0 (0u) #define ST_ACTION_NONE (0u) //============================================================================= // Mirror of TI-Drv8899 / DRV8889A registers (initialization values) //============================================================================= // ctrl-register format and initialization values #if(CPU_BYTE_ORDER == LOW_BYTE_FIRST) #define TI8899_REG01 {{ CDDSTP88xx_default_SLEW_RATE, RSVD_0, CDDSTP88xx_default_TRQ_DAC }} #define TI8899_REG02 {{ CDDSTP88xx_default_DECAY, CDDSTP88xx_default_TOFF, RSVD_0, CDDSTP88xx_default_DIS_OUT }} #define TI8899_REG03 {{ CDDSTP88xx_default_MICROSTEP_MODE, CDDSTP88xx_default_SPI_STEP, CDDSTP88xx_default_SPI_DIR, CDDSTP88xx_default_STEP, CDDSTP88xx_default_DIR }} #define TI8899_REG04 {{ CDDSTP88xx_default_TW_REP, CDDSTP88xx_default_OTSD_MODE, CDDSTP88xx_default_OCP_MODE, CDDSTP88xx_default_EN_OL, CDDSTP88xx_default_LOCK, CDDSTP88xx_default_CLR_FLT }} #define TI8899_REG05 {{ CDDSTP88xx_default_EN_SR_BLANK, CDDSTP88xx_default_OL_TIME, CDDSTP88xx_default_STL_REP, CDDSTP88xx_default_EN_STL, CDDSTP88xx_default_STL_LRN, RSVD_0 }} #define TI8899_REG06 {{ CDDSTP88xx_default_STALL_TH }} #define TI8899_REG07 {{ 0 }} // Read-Only #define TI8899_REG08 {{ 0 }} // Read-Only #else #error Unsupported version of CPU_BYTE_ORDER #endif #if(CFA_CNT_STP_88XX == 1) #define INIT_TI8899(x) { x } #elif(CFA_CNT_STP_88XX == 2) #define INIT_TI8899(x) { x, x } #elif(CFA_CNT_STP_88XX == 3) #define INIT_TI8899(x) { x, x, x } #elif(CFA_CNT_STP_88XX == 4) #define INIT_TI8899(x) { x, x, x, x } #else #error Unsupported number of stepper #endif #if(CFA_CNT_STP_88XX == 4) #define DRV8889_DATAMIRROR_INIT \ { \ { /* CtrlTx */ \ INIT_TI8899(TI8899_REG01), /* aCReg1 - SLEW_RATE, RSVD_0, TRQ_DAC */ \ INIT_TI8899(TI8899_REG02), /* aCReg2 - DECAY, TOFF, RSVD_0, DIS_OUT */ \ INIT_TI8899(TI8899_REG03), /* aCReg3 - MICROSTEP_MODE, SPI_STEP, SPI_DIR, STEP, DIR */ \ INIT_TI8899(TI8899_REG04), /* aCReg4 - TW_REP, OTSD_MODE, OCP_MODE, EN_OL, LOCK, CLR_FLT */ \ INIT_TI8899(TI8899_REG05), /* aCReg5 - RSVD.STL_LRN.EN_STL.STL_REP.OL_TIME [1:0].EN_SR_BLANK */ \ INIT_TI8899(TI8899_REG06), /* aCReg6 - STALL_TH [7:0] */ \ INIT_TI8899(TI8899_REG07), /* aCReg7 - TRQ_COUNT [7:0] */ \ INIT_TI8899(TI8899_REG08) /* aCReg8 - RSVD [3:0] | REV_ID [3:0] */ \ } \ \ /* Usually: CtrlRx and StatRx and StatvRx intentionally not initialized explicitely */ \ \ , { {{{0}}}, {{{0}}}, {{{0}}}, {{{0}}}, {{{0}}}, {{{0}}}, {{{0}}}, {{{0}}} } /* Rx - Ctrl-Reg 1...8 */ \ , { {{{0}}}, {{{0}}}, {{{0}}}, {{{0}}} } /* Rx - Stat-Reg 4x */ \ , { {{{0}}}, {{{0}}}, {{{0}}}, {{{0}}} } /* Rx - Stat-v-Reg 4x */ \ } #else #error Number of stepper not supported #endif // Addr.-Byte: // B7: 0 // B6: write=0, read=1 // 5 bits of Reg.-Adr.: B5...B1 | e.g. 3=0000.0010=CtrlReg '1' // B0: don't care // #define DRV88XX_Addr(x) ((uint8) (((x) & 0x1F) << (1u))) // left-shift by '1' of B4...B0 to B5...B1 // #define DRV88XX_Addr_R(x) ((uint8) (DRV88XX_Addr(x) | 0x40)) // add '1' in B6 // #define DRV88XX_Addr_W(x) ((uint8) (DRV88XX_Addr(x))) // yet no extra handling // Registers ------------------------------------------------------------------ // typedef enum teCddStp_TI8899_RegAddr // { // CddStp_TI8899_RegAddr_FAULT_Status = 0x00, // CddStp_TI8899_RegAddr_DIAG_Status_1 = 0x01, // CddStp_TI8899_RegAddr_DIAG_Status_2 = 0x02, // CddStp_TI8899_RegAddr_CTRL1 = 0x03, // ... // } teCddStp_TI8899_RegAddr; // #define DRV88XX_SReg_FLT CddStp_TI8899_RegAddr_FAULT_Status // = 0x00 // #define DRV88XX_SReg_D1 CddStp_TI8899_RegAddr_DIAG_Status_1 // = 0x01 // #define DRV88XX_SReg_D2 CddStp_TI8899_RegAddr_DIAG_Status_2 // = 0x02 // #define DRV88XX_CREG01 CddStp_TI8899_RegAddr_CTRL1 // = 0x03 // ... // read ---------------------------------------------------------- // #define DRV88XX_arSReg_FLT DRV88XX_Addr_R(DRV88XX_SReg_FLT) // #define DRV88XX_arSReg_D1 DRV88XX_Addr_R(DRV88XX_SReg_D1) // #define DRV88XX_arSReg_D2 DRV88XX_Addr_R(DRV88XX_SReg_D2) // #define DRV88XX_arCREG01 DRV88XX_Addr_R(DRV88XX_CREG01) // ... // write ------------------------------------------------------- // #define DRV88XX_awCREG01 DRV88XX_Addr_W(DRV88XX_CREG01) // #define DRV88XX_awCREG02 DRV88XX_Addr_W(DRV88XX_CREG02) // ... #define tCddSpiL2Channel uint8 // DRV 8899 commands // TI: read/write ... S. 37 !! // addr-Byte: 0 | R/W | A4 | A3 | A2 | A1 | A0 | x // R/W: 1=read, 0=write // Example: Read e.g. SR1: '0100.0010' // SPI address for reading #define DRV8899_rSR0_ (0x40u) // 'real'-Adr 0 - Fault-Status-Reg - only READ #define DRV8899_rSR1_ (0x42u) // 'real'-Adr 1 - Diag1-Status-Reg - only READ #define DRV8899_rSR2_ (0x44u) // 'real'-Adr 2 - Diag2-Status-Reg - only READ #define DRV8899_rCR1_ (0x46u) // 'real'-Adr 3 - Ctrl-1-Reg - #define DRV8899_rCR2_ (0x48u) // 'real'-Adr 4 - Ctrl-2-Reg - #define DRV8899_rCR3_ (0x4Au) // 'real'-Adr 5 - Ctrl-3-Reg - #define DRV8899_rCR4_ (0x4Cu) // 'real'-Adr 6 - Ctrl-4-Reg - #define DRV8899_rCR5_ (0x4Eu) // 'real'-Adr 7 - Ctrl-5-Reg - #define DRV8899_rCR6_ (0x50u) // 'real'-Adr 8 - Ctrl-6-Reg - #define DRV8899_rCR7_ (0x52u) // 'real'-Adr 9 - Ctrl-7-Reg - only READ #define DRV8899_rCR8_ (0x54u) // 'real'-Adr 0x0A - Ctrl-8-Reg - only READ // SPI address for writing (no writing for Status-Reg) #define DRV8899_wCR1_ (0x06u) // 'real'-Adr 3 - Ctrl-1-Reg #define DRV8899_wCR2_ (0x08u) // 'real'-Adr 4 - Ctrl-2-Reg #define DRV8899_wCR3_ (0x0Au) // 'real'-Adr 5 - Ctrl-3-Reg #define DRV8899_wCR4_ (0x0Cu) // 'real'-Adr 6 - Ctrl-4-Reg #define DRV8899_wCR5_ (0x0Eu) // 'real'-Adr 7 - Ctrl-5-Reg #define DRV8899_wCR6_ (0x10u) // 'real'-Adr 8 - Ctrl-6-Reg // fine DRV8899_wCR7_ (0x0Cu) // 'real'-Adr 9 - only 'READ' (no 'WRITE') // fine DRV8899_wCR8_ (0x0Cu) // 'real'-Adr 0x0A - only 'READ' (no 'WRITE') #define DRV8899_Nop__ 0x00 // defines used in schedule table entries #define ST_CTRL_TX_CR1 &CddStp8899Com_DataMirror.CtrlTx.aCReg1[0].ucRaw #define ST_CTRL_TX_CR2 &CddStp8899Com_DataMirror.CtrlTx.aCReg2[0].ucRaw #define ST_CTRL_TX_CR3 &CddStp8899Com_DataMirror.CtrlTx.aCReg3[0].ucRaw #define ST_CTRL_TX_CR4 &CddStp8899Com_DataMirror.CtrlTx.aCReg4[0].ucRaw #define ST_CTRL_TX_CR5 &CddStp8899Com_DataMirror.CtrlTx.aCReg5[0].ucRaw #define ST_CTRL_TX_CR6 &CddStp8899Com_DataMirror.CtrlTx.aCReg6[0].ucRaw // fine ST_CTRL_TX_CR7 &CddStp8899Com_DataMirror.CtrlTx.aCReg7[0].ucRaw // Ctrl-Reg 7 & 8 are only 'READ' (and no 'WRITE') // fine ST_CTRL_TX_CR8 &CddStp8899Com_DataMirror.CtrlTx.aCReg8[0].ucRaw // Ctrl-Reg 7 & 8 are only 'READ' (and no 'WRITE') #define ST_CTRL_TX_ZERO CddStp8899Com_ucZero #define ST_CTRL_RX_CR1 &CddStp8899Com_DataMirror.CtrlRx.aCReg1[0].ucRaw #define ST_CTRL_RX_CR2 &CddStp8899Com_DataMirror.CtrlRx.aCReg2[0].ucRaw #define ST_CTRL_RX_CR3 &CddStp8899Com_DataMirror.CtrlRx.aCReg3[0].ucRaw #define ST_CTRL_RX_CR4 &CddStp8899Com_DataMirror.CtrlRx.aCReg4[0].ucRaw #define ST_CTRL_RX_CR5 &CddStp8899Com_DataMirror.CtrlRx.aCReg5[0].ucRaw #define ST_CTRL_RX_CR6 &CddStp8899Com_DataMirror.CtrlRx.aCReg6[0].ucRaw #define ST_CTRL_RX_CR7 &CddStp8899Com_DataMirror.CtrlRx.aCReg7[0].ucRaw #define ST_CTRL_RX_CR8 &CddStp8899Com_DataMirror.CtrlRx.aCReg8[0].ucRaw #define ST_STAT_RX_SRB &CddStp8899Com_DataMirror.StatRx.aSRegBasic[0].ucRaw // Basic-Status - comes each time 'automatically' - 1 | 1 | UVLO | CPUV | OCP | RSVD | TF | OL #define ST_STAT_RX_SR0 &CddStp8899Com_DataMirror.StatRx.aSRegFault[0].ucRaw // Fault-Status - FAULT | SPI_ERROR | UVLO | CPUV | OCP | RSVD | TF | OL #define ST_STAT_RX_SR1 &CddStp8899Com_DataMirror.StatRx.aSRegDiag1[0].ucRaw // Diag-Status-1 - OCP_LS2_B | OCP_HS2_B | OCP_LS1_B | OCP_HS1_B | OCP_LS2_A | OCP_HS2_A | OCP_LS1_A | OCP_HS1_A #define ST_STAT_RX_SR2 &CddStp8899Com_DataMirror.StatRx.aSRegDiag2[0].ucRaw // Diag-Status-2 - UTW | OTW | OTS | RSVD | OL_B | OL_A //============================================================================= // local types //============================================================================= // SPI schedule table entry typedef struct { uint8 ucNextEntry; // index of next schedule table entry uint8 ucAddr; // SPI address (combination of low and high nibble) const uint8* pucCtrlTx; // SPI control register data for transmission - offset related to 1st address of stuct uint8* pucRxDataByte; // SPI control/status register data 1 for reception - offset related to 1st address of stuct uint8* pucRxDummy; // SPI status register data 2 for reception - use instead of this: 'uint8* pucStatusBasic = ST_STAT_RX_SRB' } tCddStp8899Com_SpiSchedTable; //============================================================================= // local function prototypes //============================================================================= STATIC_AL void CddStp8899Com_SpiRx(uint16 unIx, uint16 unData); STATIC_AL uint16 CddStp8899Com_SpiTx(uint16 unIx); STATIC_AL boolean CddStp8899Com_CheckSpiComSt0(tCddSpiL2Channel SpiL2Channel); STATIC_AL void CddStp8899Com_DEBUG_Check_EnOl_DisOut(void); #ifdef CDDSTP_CFG_SIMULATION // defined in '.\Asr6\Src\Src_AL\Cust\Bw\Bw16\App\Bsw\Cdd\CddStp\CddStpPrj.h' // check simulation STATIC_AL void CddStp8899Com_Simulation_HandleSpiRxStatusBits(tCddSpiL2Channel SpiL2Channel, const boolean *pboSim_DriverDefect , const boolean *pboSim_UVLO_UnderVoltageLockout, const boolean *pboSim_CPUV_ChargePumpUndervoltage , const boolean *pboSim_OCP_OverCurrentProtection, const boolean *pboSim_OL_OpenLoad /*, const boolean *pboSim_TF_ThermalFault*/, const boolean *pboSim_OTW_OverThermalWarning , const boolean *pboSim_OTS_OverTemperatureShutdown, const boolean *pboSim_UTW_UnderTemperatureWarning); #endif // CDDSTP_CFG_SIMULATION //============================================================================= // variables //============================================================================= // usage of global definitions is allowed for inline function access only // mirror of DRV8899 / DRV8889A registers tCddStp8899Com_DataMirror CddStp8899Com_DataMirror = DRV8889_DATAMIRROR_INIT; // typedef struct { tCddStp8899Com_CtrlData CtrlTx; tCddStp8899Com_CtrlData CtrlRx; tCddStp8899Com_StatData StatRx; tCddStp8899Com_StatData StatvRx; } tCddStp8899Com_DataMirror; #if(CFA_CNT_STP_88XX == 4) uint8 CddStp8899Com_aucStReqSingle [CFA_CNT_STP_88XX] = { 0, 0, 0, 0 }; // each bit represents a requested schedule table uint8 CddStp8899Com_aucStReqOnceMore [CFA_CNT_STP_88XX] = { 0, 0, 0, 0 }; // each bit represents a requested schedule table STATIC_AL uint8 CddStp8899Com_aucActSchedTable [CFA_CNT_STP_88XX] = { (uint8)CddStp8899Com_eSt0, (uint8)CddStp8899Com_eSt0, (uint8)CddStp8899Com_eSt0, (uint8)CddStp8899Com_eSt0 }; // number of actual schedule table CddStp8899Com_eSt3 STATIC_AL uint8 CddStp8899Com_aucSchedState [CFA_CNT_STP_88XX] = { CDDSTP8899_SpiSt_StartIx0, CDDSTP8899_SpiSt_StartIx0, CDDSTP8899_SpiSt_StartIx0, CDDSTP8899_SpiSt_StartIx0 }; // index to schedule table CddStp8899Com_eSt3 // CddStp8899Com_aulRxNotification[] is used to handle RX notification functions STATIC_AL uint32 CddStp8899Com_aulRxNotification [CFA_CNT_STP_88XX] = { 0, 0, 0, 0 }; STATIC_AL uint8 CddStp8899Com_aucTrqDac_LastTx [CFA_CNT_STP_88XX] = { 0, 0, 0, 0 }; STATIC_AL uint8 CddStp8899Com_aucTrqDac_PrevTx [CFA_CNT_STP_88XX] = { 0, 0, 0, 0 }; STATIC_AL uint16 CddStp8899Com_aunTxData [CFA_CNT_STP_88XX]; // filled in fct '...SpiRx' and used in fct '...SpiTx' STATIC_AL boolean CddStp8899Com_DoClearFaultBit [CFA_CNT_STP_88XX]; // usually 'CLR_FLT' in CReg4 is '0' - only on request do WRITE ONCE a '1' STATIC_AL uint8 CddStp8899Com_aucDebouncingCtr_OL [CFA_CNT_STP_88XX]; STATIC_AL uint8 CddStp8899Com_aucDebouncingCtr_OCP [CFA_CNT_STP_88XX]; STATIC_AL uint8 CddStp8899Com_aucDebouncingCtr_SPI [CFA_CNT_STP_88XX]; // handled inside of section: 'SPI somehow NOT valid' STATIC_AL uint8 CddStp8899Com_aucDebouncingCtr_SPI2 [CFA_CNT_STP_88XX]; STATIC_AL const uint8 CddStp8899Com_ucZero [CFA_CNT_STP_88XX] = INIT_TI8899(0); // { 0, 0, 0, 0 }; #else #error Unsupported number of stepper #endif // Handle Pre-Evaluation Stall-Detection // currently not used STATIC_AL uint8 CddStp8899Com_PreEvalStallDtctn_ucSTALL_TH; STATIC_AL boolean CddStp8899Com_StallDtctn_CR7_bIsNewValue; // DEBUG #define UNTANGLE #ifdef UNTANGLE #define UNTANGLE_INCR(x) (x++); // PRQA S 3410 // warning - QAC(Prio7) Msg: 3410(Macro parameter not enclosed in ().) Depth: 0 Ref: MISRA C:2012 Rule-20.7 #define UNTANGLE_INCR_IF_NZ(x, y) {if(x>0) {y++;}} // PRQA S 3410 // warning - QAC(Prio7) Msg: 3410(Macro parameter not enclosed in ().) Depth: 0 Ref: MISRA C:2012 Rule-20.7 #define UNTANGLE_RESET(x) (x = 0); // PRQA S 3410 // warning - QAC(Prio7) Msg: 3410(Macro parameter not enclosed in ().) Depth: 0 Ref: MISRA C:2012 Rule-20.7 #define UNTANGLE_MAX(x, y) (x = UTIL_MAX(x,y)); // PRQA S 3410 // warning - QAC(Prio7) Msg: 3410(Macro parameter not enclosed in ().) Depth: 0 Ref: MISRA C:2012 Rule-20.7 typedef struct { uint32 ulRead; uint32 ulWrite; } tCddStp8899Com_DEBUG_StlLrn_Cntr; STATIC_AL volatile tCddStp8899Com_DEBUG_StlLrn_Cntr CddStp8899Com_DEBUG_StlLrn_Cntr[6+1]; // 2x Ctrl-Reg (of totally '8') are only 'READ' STATIC_AL volatile uint8 CddStp8899Com_ucDEBUG_StlLrn_Cntr__Cr5LastData; STATIC_AL volatile uint8 CddStp8899Com_ucDEBUG_SpiOkCounter; STATIC_AL volatile uint8 CddStp8899Com_ucDEBUG_BitSpiValid; // CddStp88XX_aStpState[SpiL2Channel].Bit.SpiValid STATIC_AL volatile uint8 CddStp8899Com_ucDEBUG_BitErrSpiError; // CddStp88XX_aStpState[SpiL2Channel].Bit.ErrSpiError STATIC_AL volatile uint8 CddStp8899Com_ucDEBUG_DebouncingCtr_OL_Rst; STATIC_AL volatile uint8 CddStp8899Com_ucDEBUG_DebouncingCtr_OL_Max; STATIC_AL volatile uint8 CddStp8899Com_ucDEBUG_DebouncingCtr_OL_Incr; STATIC_AL volatile uint8 CddStp8899Com_ucDEBUG_DebouncingCtr_OCP_Rst; STATIC_AL volatile uint8 CddStp8899Com_ucDEBUG_DebouncingCtr_OCP_Max; STATIC_AL volatile uint8 CddStp8899Com_ucDEBUG_DebouncingCtr_OCP_Incr; STATIC_AL volatile uint8 CddStp8899Com_ucDEBUG_DebouncingCtr_SPI_Rst; STATIC_AL volatile uint8 CddStp8899Com_ucDEBUG_DebouncingCtr_SPI_Max; STATIC_AL volatile uint8 CddStp8899Com_ucDEBUG_DebouncingCtr_SPI_Incr; STATIC_AL volatile uint8 CddStp8899Com_ucDEBUG_DebouncingCtr_SpiFaultClear; STATIC_AL volatile uint8 CddStp8899Com_ucDEBUG_DebouncingCtr_SPI2_Rst; STATIC_AL volatile uint8 CddStp8899Com_ucDEBUG_DebouncingCtr_SPI2_Max; STATIC_AL volatile uint8 CddStp8899Com_ucDEBUG_DebouncingCtr_SPI3_Max; STATIC_AL volatile uint8 CddStp8899Com_ucDEBUG_DebouncingCtr_SPI4_Rst; STATIC_AL volatile uint8 CddStp8899Com_ucDEBUG_DebouncingCtr_SPI4_Max; STATIC_AL volatile uint8 CddStp8899Com_ucDEBUG_DebouncingCtr_SPI4_Incr; STATIC_AL volatile uint32 CddStp8899Com_ulDEBUG_DebouncingCtr_ClrFlt_Sent; // count of sending the bit 'CLR_FLT' STATIC_AL volatile uint32 CddStp8899Com_ulDEBUG_SpiCheckCounter; // count of fct-call 'CddStp8899Com_CheckSpiComSt0' STATIC_AL volatile uint32 CddStp8899Com_ulDEBUG_SpiNOkCounter; // count of all 'SPI not valid due to 'Rx' == 0xFF (or SPI-HW-Error 'Bit.u1SPI_ERROR') (or due to 'Error-Simulation') STATIC_AL volatile uint32 CddStp8899Com_ulDEBUG_NotVrfyCounter; // count of all 'CtrlTx != CtrlRx of 'TRQ_DAC'' STATIC_AL volatile uint32 CddStp8899Com_ulDEBUG_DrvDfctCounter; STATIC_AL volatile tCddStp8899Com_StatReg_Basic CddStp8899Com___DEBUG_1stErrBit_Basic; STATIC_AL volatile tCddStp8899Com_StatReg_Fault CddStp8899Com___DEBUG_1stErrBit_Fault; #else #define UNTANGLE_INCR(x) #define UNTANGLE_INCR_IF_NZ(x, y) #define UNTANGLE_RESET(x) #define UNTANGLE_MAX(x, y) #endif //============================================================================= // constants //============================================================================= // SPI schedule table // one line represents one SPI transmit/receive sequence // Attention !! This table must match the CDDSTP8899_SpiSt_...-List in CddStp8899Com.h !! // tCddStp8899Com_SpiSchedTable: uint8 ucNextEntry; | uint8 ucAddr; | const uint8* pucCtrlTx; | uint8* pucRxDataByte; | uint8* pucRxDummy; STATIC_AL const tCddStp8899Com_SpiSchedTable CddStp8899Com_SpiSchedTable[CDDSTP8899_SpiSt_IxMax + 1u] = { // ucNextEntry | ucAddr | pucCtrlTx | pucRxDataByte | pucRxDummy - use instead of this: 'uint8* pucStatusBasic = ST_STAT_RX_SRB' // idx of nxt schdlTbl-Entry | SPI addr | SPI ctrl-reg-data for transm. | SPI ctrl/state-reg data 1 for reception | SPI ctrl/state-reg data 2 for reception // next TX: SPI register address (Cmd) TX: control reg. RX: ctrl/stat r. RX: status reg. table // state data byte data byte 1 data byte 2 index // jk-tbd: use 'DRV88XX_awCREG01' instead of 'DRV8899_wCR1_' & use 'ST_CTRL_TX_REG01' instead of 'ST_CTRL_TX_CR1' etc // table 0 = CddStp8899Com_eSt0 (CDDSTP8899_SpiSt_ReadWriteAll { 1u, DRV8899_wCR1_, ST_CTRL_TX_CR1, ST_STAT_RX_SR2, ST_STAT_RX_SRB }, // 0 = CDDSTP8899_SpiSt_StartIx0 { 2u, DRV8899_wCR2_, ST_CTRL_TX_CR2, ST_CTRL_RX_CR1, ST_STAT_RX_SRB }, // 1 { 3u, DRV8899_wCR1_, ST_CTRL_TX_CR1, ST_CTRL_RX_CR2, ST_STAT_RX_SRB }, // 2 { 4u, DRV8899_wCR3_, ST_CTRL_TX_CR3, ST_CTRL_RX_CR1, ST_STAT_RX_SRB }, // 3 { 5u, DRV8899_wCR1_, ST_CTRL_TX_CR1, ST_CTRL_RX_CR3, ST_STAT_RX_SRB }, // 4 { 6u, DRV8899_wCR4_, ST_CTRL_TX_CR4, ST_CTRL_RX_CR1, ST_STAT_RX_SRB }, // 5 { 7u, DRV8899_wCR1_, ST_CTRL_TX_CR1, ST_CTRL_RX_CR4, ST_STAT_RX_SRB }, // 6 { 8u, DRV8899_rSR0_, ST_CTRL_TX_ZERO, ST_CTRL_RX_CR1, ST_STAT_RX_SRB }, // 7 { 9u, DRV8899_wCR1_, ST_CTRL_TX_CR1, ST_STAT_RX_SR0, ST_STAT_RX_SRB }, // 8 { 10u, DRV8899_rSR1_, ST_CTRL_TX_ZERO, ST_CTRL_RX_CR1, ST_STAT_RX_SRB }, // 9 { 11u, DRV8899_wCR1_, ST_CTRL_TX_CR1, ST_STAT_RX_SR1, ST_STAT_RX_SRB }, // 10 { 0u, DRV8899_rSR2_, ST_CTRL_TX_ZERO, ST_CTRL_RX_CR1, ST_STAT_RX_SRB } // 11 = CDDSTP8899_SpiSt_EndIx0 }; STATIC_AL const tCddStp8899Com_SpiSchedTable CddStp8899Com_SpiSchedTable_XT[CDDSTP8899_SpiSt_IxMax_XT + 1u] = { // jk-tbd: use 'DRV88XX_awCREG01' instead of 'DRV8899_wCR1_' & use 'ST_CTRL_TX_REG01' instead of 'ST_CTRL_TX_CR1' etc // Stat-Reg-'B' - Basic-Status - comes each time 'automatically' - 1 | 1 | UVLO | CPUV | OCP | STL | TF | OL // Stat-Reg-0 - Fault-Status - FAULT | SPI_ERROR | UVLO | CPUV | OCP | STL | TF | OL // Stat-Reg-1 - Diag-Status-1 - OCP_LS2_B | OCP_HS2_B | OCP_LS1_B | OCP_HS1_B | OCP_LS2_A | OCP_HS2_A | OCP_LS1_A | OCP_HS1_A // Stat-Reg-2 - Diag-Status-2 - UTW | OTW | OTS | STL_LRN_OK | STALL | RSVD | OL_B | OL_A // // Ctrl-Reg-1 - TRQ_DAC [3:0] | RSVD | SLEW_RATE [1:0] // Ctrl-Reg-2 - DIS_OUT | RSVD | TOFF [1:0] | DECAY [2:0] // Ctrl-Reg-3 - DIR | STEP | SPI_DIR | SPI_STEP | MICROSTEP_MODE [3:0] // Ctrl-Reg-4 - CLR_FLT | LOCK [2:0] | EN_OL | OCP_MODE | OTSD_MODE | TW_REP - e.g. EN_OL: 0x31=0011.0001 | 0x39=0011.1001 // Ctrl-Reg-5 - RSVD [1:0] | STL_LRN | EN_STL | STL_REP | OL_TIME [1:0] | EN_SR_BLANK // Ctrl-Reg-6 - STALL_TH [7:0] // Ctrl-Reg-7 - TRQ_COUNT [7:0] // Ctrl-Reg-8 - RSVD | REV_ID [3:0] // old/previous Schedule-Table: 'C1' every 2nd time: C1,C2, C1,C3, C1,C4, C1,S0, C1,S1, C1,S2 -> 12 entries // // new/current Schedule-Table with new version of TI-HW-Chip (Stall-Detection) and some more registers // // what is really important (read and/or write)? // 1st is writing the actual current ('TRQ_DAC'): Ctrl-1 // 2nd NOT the FAULT-Status-Reg because the main issues are already available in BASIC-Status-Reg // 3rd keep an eye on Stall-Detection: TRQ_COUNT: Ctrl-7 // 4th the 'EN_OL' is important, too: Ctrl-4 // 5th: Really unimportant is: 'Fault', 'Diag 1&2', Ctrl-3, -6, -8 // 6th: 'Medium' important is the rest: Ctrl-2, -5 // // -> Each 3rd cycle: Ctrl-1 -> 3ms (instead of 2ms) // -> Each 3rd cycle: Toggle Ctrl-4 & Ctrl-7 -> 6ms // -> Each 3rd cycle: Medium important: Ctrl-2 & Ctrl-5 & '1 of low important' (=Flt,Dg1,Dg2,C3,C6,C8) -> 9ms / 54ms // // C1: C1,.....,C1,.....,C1,.....,C1,.....,C1,.....,C1,.....,C1,.....,C1,.....,C1,.....,C1,.....,C1,.....,C1,.....,C1,.....,C1,.....,C1,.....,C1,.....,C1,.....,C1,..... // C4 & C7: ..,C4,.....,C7,.....,C4,.....,C7,.....,C4,.....,C7,.....,C4,.....,C7,.....,C4,.....,C7,.....,C4,.....,C7,......,C4,....,C7,......,C4,....,C7,......,C4,....,C7,.. // C2 & C5 & rest: .....,C2,.....,C5,.....,xx,.....,C2,.....,C5,.....,xx,.....,C2,.....,C5,.....,xx,.....,C2,.....,C5,.....,xx,.....,C2,.....,C5,.....,xx,.....,C2,.....,C5,.....,xx // // order: C1,C4,C2,C1,C7,C5,C1,C4,Fl,C1,C7,C2,C1,C4,C5,C1,C7,D1,C1,C4,C2,C1,C7,C5,C1,C4,D2,C1,C7,C2,C1,C4,C5,C1,C7,C3,C1,C4,C2,C1,C7,C5,C1,C4,C6,C1,C7,C2,C1,C4,C5,C1,C7,C8 // idx: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 // ucNextEntry | ucAddr | pucCtrlTx | pucRxDataByte | pucRxDummy - use instead of this: 'uint8* pucStatusBasic = ST_STAT_RX_SRB' // idx of nxt schdlTbl-Entry | SPI addr | SPI ctrl-reg-data for transm. | SPI ctrl/state-reg data 1 for reception | SPI ctrl/state-reg data 2 for reception // next | TX: SPI register address (Cmd) | TX: control reg. | RX: ctrl/stat r. | RX: status reg. table // state | | data byte | data byte 1 | data byte 2 index // { 1u, DRV8899_wCR1_, ST_CTRL_TX_CR1, ST_CTRL_RX_CR8, ST_STAT_RX_SRB }, // CReg-1 - TRQ_DAC | RSVD | SLEW_RATE { 2u, DRV8899_wCR4_, ST_CTRL_TX_CR4, ST_CTRL_RX_CR1, ST_STAT_RX_SRB }, // CReg-4 - CLR_FLT | LOCK | EN_OL | OCP_MODE | OTSD_MODE | TW_REP { 3u, DRV8899_wCR2_, ST_CTRL_TX_CR2, ST_CTRL_RX_CR4, ST_STAT_RX_SRB }, // CReg-2 - DIS_OUT | RSVD | TOFF | DECAY { 4u, DRV8899_wCR1_, ST_CTRL_TX_CR1, ST_CTRL_RX_CR2, ST_STAT_RX_SRB }, // { 5u, DRV8899_rCR7_, ST_CTRL_TX_ZERO, ST_CTRL_RX_CR1, ST_STAT_RX_SRB }, // CReg-7 - TRQ_COUNT [7:0] { 6u, DRV8899_wCR5_, ST_CTRL_TX_CR5, ST_CTRL_RX_CR7, ST_STAT_RX_SRB }, // CReg-5 - RSVD | STL_LRN | EN_STL | STL_REP | OL_TIME | EN_SR_BLANK { 7u, DRV8899_wCR1_, ST_CTRL_TX_CR1, ST_CTRL_RX_CR5, ST_STAT_RX_SRB }, // { 8u, DRV8899_wCR4_, ST_CTRL_TX_CR4, ST_CTRL_RX_CR1, ST_STAT_RX_SRB }, // { 9u, DRV8899_rSR0_, ST_CTRL_TX_ZERO, ST_CTRL_RX_CR4, ST_STAT_RX_SRB }, // { 10u, DRV8899_wCR1_, ST_CTRL_TX_CR1, ST_STAT_RX_SR0, ST_STAT_RX_SRB }, // { 11u, DRV8899_rCR7_, ST_CTRL_TX_ZERO, ST_CTRL_RX_CR1, ST_STAT_RX_SRB }, // { 12u, DRV8899_wCR2_, ST_CTRL_TX_CR2, ST_CTRL_RX_CR7, ST_STAT_RX_SRB }, // { 13u, DRV8899_wCR1_, ST_CTRL_TX_CR1, ST_CTRL_RX_CR2, ST_STAT_RX_SRB }, // { 14u, DRV8899_wCR4_, ST_CTRL_TX_CR4, ST_CTRL_RX_CR1, ST_STAT_RX_SRB }, // { 15u, DRV8899_wCR5_, ST_CTRL_TX_CR5, ST_CTRL_RX_CR4, ST_STAT_RX_SRB }, // { 16u, DRV8899_wCR1_, ST_CTRL_TX_CR1, ST_CTRL_RX_CR5, ST_STAT_RX_SRB }, // { 17u, DRV8899_rCR7_, ST_CTRL_TX_ZERO, ST_CTRL_RX_CR1, ST_STAT_RX_SRB }, // { 18u, DRV8899_rSR1_, ST_CTRL_TX_ZERO, ST_CTRL_RX_CR7, ST_STAT_RX_SRB }, // { 19u, DRV8899_wCR1_, ST_CTRL_TX_CR1, ST_STAT_RX_SR1, ST_STAT_RX_SRB }, // { 20u, DRV8899_wCR4_, ST_CTRL_TX_CR4, ST_CTRL_RX_CR1, ST_STAT_RX_SRB }, // { 21u, DRV8899_wCR2_, ST_CTRL_TX_CR2, ST_CTRL_RX_CR4, ST_STAT_RX_SRB }, // { 22u, DRV8899_wCR1_, ST_CTRL_TX_CR1, ST_CTRL_RX_CR2, ST_STAT_RX_SRB }, // { 23u, DRV8899_rCR7_, ST_CTRL_TX_ZERO, ST_CTRL_RX_CR1, ST_STAT_RX_SRB }, // { 24u, DRV8899_wCR5_, ST_CTRL_TX_CR5, ST_CTRL_RX_CR7, ST_STAT_RX_SRB }, // { 25u, DRV8899_wCR1_, ST_CTRL_TX_CR1, ST_CTRL_RX_CR5, ST_STAT_RX_SRB }, // { 26u, DRV8899_wCR4_, ST_CTRL_TX_CR4, ST_CTRL_RX_CR1, ST_STAT_RX_SRB }, // { 27u, DRV8899_rSR2_, ST_CTRL_TX_ZERO, ST_CTRL_RX_CR4, ST_STAT_RX_SRB }, // { 28u, DRV8899_wCR1_, ST_CTRL_TX_CR1, ST_STAT_RX_SR2, ST_STAT_RX_SRB }, // { 29u, DRV8899_rCR7_, ST_CTRL_TX_ZERO, ST_CTRL_RX_CR1, ST_STAT_RX_SRB }, // { 30u, DRV8899_wCR2_, ST_CTRL_TX_CR2, ST_CTRL_RX_CR7, ST_STAT_RX_SRB }, // { 31u, DRV8899_wCR1_, ST_CTRL_TX_CR1, ST_CTRL_RX_CR2, ST_STAT_RX_SRB }, // { 32u, DRV8899_wCR4_, ST_CTRL_TX_CR4, ST_CTRL_RX_CR1, ST_STAT_RX_SRB }, // { 33u, DRV8899_wCR5_, ST_CTRL_TX_CR5, ST_CTRL_RX_CR4, ST_STAT_RX_SRB }, // { 34u, DRV8899_wCR1_, ST_CTRL_TX_CR1, ST_CTRL_RX_CR5, ST_STAT_RX_SRB }, // { 35u, DRV8899_rCR7_, ST_CTRL_TX_ZERO, ST_CTRL_RX_CR1, ST_STAT_RX_SRB }, // { 36u, DRV8899_wCR3_, ST_CTRL_TX_CR3, ST_CTRL_RX_CR7, ST_STAT_RX_SRB }, // { 37u, DRV8899_wCR1_, ST_CTRL_TX_CR1, ST_CTRL_RX_CR3, ST_STAT_RX_SRB }, // { 38u, DRV8899_wCR4_, ST_CTRL_TX_CR4, ST_CTRL_RX_CR1, ST_STAT_RX_SRB }, // { 39u, DRV8899_wCR2_, ST_CTRL_TX_CR2, ST_CTRL_RX_CR4, ST_STAT_RX_SRB }, // { 40u, DRV8899_wCR1_, ST_CTRL_TX_CR1, ST_CTRL_RX_CR2, ST_STAT_RX_SRB }, // { 41u, DRV8899_rCR7_, ST_CTRL_TX_ZERO, ST_CTRL_RX_CR1, ST_STAT_RX_SRB }, // { 42u, DRV8899_wCR5_, ST_CTRL_TX_CR5, ST_CTRL_RX_CR7, ST_STAT_RX_SRB }, // { 43u, DRV8899_wCR1_, ST_CTRL_TX_CR1, ST_CTRL_RX_CR5, ST_STAT_RX_SRB }, // { 44u, DRV8899_wCR4_, ST_CTRL_TX_CR4, ST_CTRL_RX_CR1, ST_STAT_RX_SRB }, // { 45u, DRV8899_rCR6_, ST_CTRL_TX_CR6, ST_CTRL_RX_CR4, ST_STAT_RX_SRB }, // CReg-6 - STALL_TH { 46u, DRV8899_wCR1_, ST_CTRL_TX_CR1, ST_CTRL_RX_CR6, ST_STAT_RX_SRB }, // { 47u, DRV8899_rCR7_, ST_CTRL_TX_ZERO, ST_CTRL_RX_CR1, ST_STAT_RX_SRB }, // { 48u, DRV8899_wCR2_, ST_CTRL_TX_CR2, ST_CTRL_RX_CR7, ST_STAT_RX_SRB }, // { 49u, DRV8899_wCR1_, ST_CTRL_TX_CR1, ST_CTRL_RX_CR2, ST_STAT_RX_SRB }, // { 50u, DRV8899_wCR4_, ST_CTRL_TX_CR4, ST_CTRL_RX_CR1, ST_STAT_RX_SRB }, // { 51u, DRV8899_wCR5_, ST_CTRL_TX_CR5, ST_CTRL_RX_CR4, ST_STAT_RX_SRB }, // { 52u, DRV8899_wCR1_, ST_CTRL_TX_CR1, ST_CTRL_RX_CR5, ST_STAT_RX_SRB }, // { 53u, DRV8899_rCR7_, ST_CTRL_TX_ZERO, ST_CTRL_RX_CR1, ST_STAT_RX_SRB }, // { 0u, DRV8899_rCR8_, ST_CTRL_TX_ZERO, ST_CTRL_RX_CR7, ST_STAT_RX_SRB } // }; static const uint8 CddStp8899Com_aucStStart[CddStp8899Com_eStMax] = { CDDSTP8899_SpiSt_StartIx0 /*, CDDSTP8899_SpiSt_StartIx1, CDDSTP8899_SpiSt_StartIx2, CDDSTP8899_SpiSt_StartIx3 */ }; typedef boolean (*tFctCheckSpiComPtr)(tCddSpiL2Channel SpiL2Channel); static const tFctCheckSpiComPtr CddStp8899Com_aucStCheckSpiComFct[CddStp8899Com_eStMax] = { CddStp8899Com_CheckSpiComSt0 /*, CddStp8899Com_CheckSpiComSt1, CddStp8899Com_CheckSpiComSt2, CddStp8899Com_CheckSpiComSt3 */ }; //============================================================================= // Public functions implementation //============================================================================= //----------------------------------------------------------------------------- /// \brief get Status-Register-Basic contents from RAM mirror (verified) /// /// \descr verified status register content is returned /// /// \param uint8 ucIx stepper index /// uint8* pucSRegBsc pointer to status register Basic content (verified) /// /// \return boolean //----------------------------------------------------------------------------- boolean CddStp8899Com_GetSRegBsc(uint8 ucIx, uint8* pucSRegBsc) { *pucSRegBsc = CddStp8899Com_DataMirror.StatvRx.aSRegBasic[ucIx].ucRaw; return TRUE; } //----------------------------------------------------------------------------- /// \brief get Status-Register-FAULT contents from RAM mirror (verified) /// /// \descr verified status register content is returned /// /// \param uint8 ucIx stepper index /// uint8* pucSRegFlt pointer to status register FAULT content (verified) /// /// \return boolean //----------------------------------------------------------------------------- boolean CddStp8899Com_GetSRegFlt(uint8 ucIx, uint8* pucSRegFlt) { *pucSRegFlt = CddStp8899Com_DataMirror.StatvRx.aSRegFault[ucIx].ucRaw; return TRUE; } //----------------------------------------------------------------------------- /// \brief get Status-Register-Diag-1 contents /// /// \descr verified status register content is returned /// /// \param uint8 ucIx stepper index /// uint8* pucSRegDiag1 pointer to status register Diag1 content (verified) /// /// \return boolean //----------------------------------------------------------------------------- boolean CddStp8899Com_GetSRegDiag1(uint8 ucIx, uint8* pucSRegDiag1) { *pucSRegDiag1 = CddStp8899Com_DataMirror.StatvRx.aSRegDiag1[ucIx].ucRaw; return TRUE; } //----------------------------------------------------------------------------- /// \brief get Status-Register-Diag-2 contents /// /// \descr verified status register content is returned /// /// \param uint8 ucIx stepper index /// uint8* pucSRegDiag2 pointer to status register Diag2 content (verified) /// /// \return boolean //----------------------------------------------------------------------------- boolean CddStp8899Com_GetSRegDiag2(uint8 ucIx, uint8* pucSRegDiag2) { *pucSRegDiag2 = CddStp8899Com_DataMirror.StatvRx.aSRegDiag2[ucIx].ucRaw; return TRUE; } //----------------------------------------------------------------------------- /// \brief get Status-Register-Diag-1 & -2 contents /// /// \descr verified status register content is returned /// /// \param uint8 ucIx stepper index /// uint8* pucSRegDiag2 pointer to status register Diag1 content (verified) /// uint8* pucSRegDiag2 pointer to status register Diag2 content (verified) /// /// \return boolean //----------------------------------------------------------------------------- boolean CddStp8899Com_GetSRegDiag12(uint8 ucIx, uint8* pucSRegDiag1, uint8* pucSRegDiag2) { *pucSRegDiag1 = CddStp8899Com_DataMirror.StatvRx.aSRegDiag1[ucIx].ucRaw; *pucSRegDiag2 = CddStp8899Com_DataMirror.StatvRx.aSRegDiag2[ucIx].ucRaw; return TRUE; } //----------------------------------------------------------------------------- /// \brief get SR1, SR2, SR6, SR7A, SR8A contents from RAM mirror (verified) /// /// \descr verified status register contents are returned /// /// \param uint8 ucIx stepper index /// uint8* aSRegFault pointer to status register FAULT content (verified) /// uint8* pucSRegDiag2 pointer to status register Diag-2 content (verified) /// /// \return boolean //----------------------------------------------------------------------------- boolean CddStp8899Com_GetSRegFltDiag2(uint8 ucIx, uint8* pucSRegFlt, uint8* pucSRegDiag2) { // usually called with var 'CddStp88XX_aSRegXXX' like 'CddStp88XX_aSRegBasic[idx]', 'CddStp88XX_aSRegFault[idx]', 'CddStp88XX_aSRegDiag1[idx]', 'CddStp88XX_aSRegDiag2[idx] *pucSRegFlt = CddStp8899Com_DataMirror.StatvRx.aSRegFault[ucIx].ucRaw; *pucSRegDiag2 = CddStp8899Com_DataMirror.StatvRx.aSRegDiag2[ucIx].ucRaw; return TRUE; } //----------------------------------------------------------------------------- /// \brief get SR1, SR2, SR6, SR7A, SR8A contents from RAM mirror (verified) /// /// \descr verified status register contents are returned /// /// \param uint8 ucIx stepper index /// uint8* aSRegBasic pointer to status register Basic content (verified) /// uint8* aSRegFault pointer to status register FAULT content (verified) /// uint8* pucSRegDiag1 pointer to status register Diag-1 content (verified) /// uint8* pucSRegDiag2 pointer to status register Diag-2 content (verified) /// /// \return boolean //----------------------------------------------------------------------------- boolean CddStp8899Com_GetSRegBscFltDiag12(uint8 ucIx, uint8* pucSRegBsc, uint8* pucSRegFlt, uint8* pucSRegDiag1, uint8* pucSRegDiag2) { // usually called with var 'CddStp88XX_aSRegXXX' like 'CddStp88XX_aSRegBasic[idx]', 'CddStp88XX_aSRegFault[idx]', 'CddStp88XX_aSRegDiag1[idx]', 'CddStp88XX_aSRegDiag2[idx] *pucSRegBsc = CddStp8899Com_DataMirror.StatvRx.aSRegBasic[ucIx].ucRaw; // jk-tbd ... Basic-Status - comes each time 'automatically' *pucSRegFlt = CddStp8899Com_DataMirror.StatvRx.aSRegFault[ucIx].ucRaw; *pucSRegDiag1 = CddStp8899Com_DataMirror.StatvRx.aSRegDiag1[ucIx].ucRaw; *pucSRegDiag2 = CddStp8899Com_DataMirror.StatvRx.aSRegDiag2[ucIx].ucRaw; return TRUE; } //----------------------------------------------------------------------------- /// \brief check SPI communication for schedule table 0 as write verify of control registers 1 and 2 and read control registers 1 and 2 /// /// \descr check communication by comparison of TX and RX data etc /// Usually called via 'CddStp8899Com_aucStCheckSpiComFct' /// /// previously: Check only once after a WHOLE Schedule-Table (ST) was done (8...50 entries & more) /// new: Check EACH received data via SPI-TX /// /// \param tCddSpiL2Channel SpiL2Channel /// /// \return (boVerifyOk && !boSpiProblem) //----------------------------------------------------------------------------- STATIC_AL boolean CddStp8899Com_CheckSpiComSt0(tCddSpiL2Channel SpiL2Channel) { boolean boVerifyOk = FALSE; boolean boSpiValid = FALSE; boolean boRxIsFF = FALSE; boolean boSim_DriverDefect = FALSE; boolean boSim_SPI_ERROR_SpiProtocolError = FALSE; boolean boSim_UVLO_UnderVoltageLockout = FALSE; boolean boSim_CPUV_ChargePumpUndervoltage = FALSE; boolean boSim_OCP_OverCurrentProtection = FALSE; boolean boSim_OL_OpenLoad = FALSE; //boolean boSim_TF_ThermalFault = FALSE; boolean boSim_OTW_OverThermalWarning = FALSE; boolean boSim_OTS_OverTemperatureShutdown = FALSE; boolean boSim_UTW_UnderTemperatureWarning = FALSE; UNTANGLE_INCR(CddStp8899Com_ulDEBUG_SpiCheckCounter) // this var will never be reset #ifndef UNIT_TEST // NOT Unit-Tests = 'regular' #ifdef UNTANGLE if ( (CddStp8899Com_DataMirror.StatRx.aSRegBasic[SpiL2Channel].ucRaw != CDDSTP8899_SRBValVBATSDD) // EACH time this is a NEW value - should be '11xx.xxxx' && (CddStp8899Com_DataMirror.StatRx.aSRegBasic[SpiL2Channel].ucRaw > 0u) // any error? && (CddStp8899Com___DEBUG_1stErrBit_Basic.ucRaw == 0u)) // not already set? { CddStp8899Com___DEBUG_1stErrBit_Basic.ucRaw = CddStp8899Com_DataMirror.StatRx.aSRegBasic[SpiL2Channel].ucRaw; // 1 | 1 | UVLO | CPUV | OCP | RSVD | TF | OL } if ( (CddStp8899Com_DataMirror.StatRx.aSRegFault[SpiL2Channel].ucRaw != CDDSTP8899_RegValVBATSDD) // EACH time this is a NEW value - should be '11xx.xxxx' && (CddStp8899Com_DataMirror.StatRx.aSRegFault[SpiL2Channel].ucRaw > 0u) // any error? && (CddStp8899Com___DEBUG_1stErrBit_Fault.ucRaw == 0u)) // not already set? { CddStp8899Com___DEBUG_1stErrBit_Fault.ucRaw = CddStp8899Com_DataMirror.StatRx.aSRegFault[SpiL2Channel].ucRaw; // FAULT | SPI_ERROR | UVLO | CPUV | OCP | RSVD | TF | OL } #endif // UNTANGLE #else // Unit-Tests! #endif #ifdef CDDSTP_CFG_SIMULATION // defined in '.\Asr6\Src\Src_AL\Cust\Bw\Bw16\App\Bsw\Cdd\CddStp\CddStpPrj.h' // check simulation - GET the 'Simulation'-Bits - yet no 'real' handling/simulation CddStp_Simulation_HandleSpiRxStatusBits(&boSim_DriverDefect, &boSim_SPI_ERROR_SpiProtocolError , &boSim_UVLO_UnderVoltageLockout , &boSim_CPUV_ChargePumpUndervoltage, &boSim_OCP_OverCurrentProtection , &boSim_OL_OpenLoad /*, &boSim_TF_ThermalFault*/ , &boSim_OTW_OverThermalWarning , &boSim_OTS_OverTemperatureShutdown, &boSim_UTW_UnderTemperatureWarning); #endif #ifdef JK_TBD /* jk-tbd */ if (0); #endif // New code: // * There is only ONE Schedule-Table (ST) // * Explicit reading of Ctrl-Registers is NEVER done // * Rx of Ctrl-Regs is always the 'previous' value (tx=5 -> rx=?, tx=5 -> rx=5, tx=5 -> rx=5, tx=8 -> rx=5, tx=3 -> rx=8, tx=y -> rx=3, ...) // * Daisy-Chain: Rx= SB3.SB2.SB1.Hdr1.Hdr2.R3.R2.R1 (SB=Status-Byte, Hdr=Header, R=register (Ctrl:'previous', Status:'current')) // * Single-Dvc: Rx= SB1.R1 (SB=Status-Byte, R=register (Ctrl:'previous', Status:'current')) // * Check: SB (='All-Time' Status-Byte): Bit 6 & 7 always '1': '11xx.xxxx' (this is NOT the FALUT-Status or any Diag-Status) // * Check: Some bits in Ctrl-Regs are always fixed and so these bits are checkable // * Check: If Daisy-Chain: Rx-Hdr has to be Tx-Hdr // if TI-HW is switched off or VBatt is too low all RX-Bits are '1' (via pullup) - check this first: if ( (CddStp8899Com_DataMirror.StatRx.aSRegBasic[SpiL2Channel].ucRaw == CDDSTP8899_SRBValVBATSDD) // EACH time this is a NEW value - should be '11xx.xxxx' || (CddStp8899Com_DataMirror.StatRx.aSRegFault[SpiL2Channel].ucRaw == CDDSTP8899_RegValVBATSDD) // N.b.: These values are usually 'outdated' (no refreshed each SPI-Cycle) || (CddStp8899Com_DataMirror.StatRx.aSRegDiag1[SpiL2Channel].ucRaw == CDDSTP8899_RegValVBATSDD) // N.b.: These values are usually 'outdated' (no refreshed each SPI-Cycle) || (CddStp8899Com_DataMirror.StatRx.aSRegDiag2[SpiL2Channel].ucRaw == CDDSTP8899_RegValVBATSDD)) // N.b.: These values are usually 'outdated' (no refreshed each SPI-Cycle) { // probably any problems with HW and/or voltage or just 'switched OFF' (i.e. '...Bit.On == 0') boRxIsFF = TRUE; } else // all Rx are ok/valid (indepentened of any error like OL, OCP, SPI, ...) { boRxIsFF = FALSE; // voltage & HW (& EMV etc) probably okay } // check simulation, too if ( (boRxIsFF == FALSE) // all Rx are ok/valid (indepentened of any error like OL, OCP, SPI, ...) && (boSim_SPI_ERROR_SpiProtocolError == FALSE)) // only about 'simulation' { // SPI-Error-Bit set? boSpiValid = CddStp8899Com_DataMirror.StatRx.aSRegFault[SpiL2Channel].Bit.u1SPI_ERROR != FALSE ? FALSE : TRUE; // inverse logic } else // some kind of problem { boSpiValid = FALSE; } // SPI-Error-Bit and all Rx are ok/valid (indepentened of any error like OL, OCP, SPI, ...) if (boSpiValid != FALSE) // SPI seems to be ok / valid { CddStp88XX_aStpState[SpiL2Channel].Bit.SpiValid = 1; // set SPI valid bit (driver is not in Sleep mode) (N.b.: in opposite to '...Bit.ErrSpiError') CddStp8899Com_ucDEBUG_BitSpiValid = 1; #ifdef UNTANGLE if (CddStp8899Com_ucDEBUG_SpiOkCounter < 200u) // max 200 (in a row) { CddStp8899Com_ucDEBUG_SpiOkCounter++; } #endif // UNTANGLE // no SPI-Error -> reset debouncing UNTANGLE_INCR_IF_NZ(CddStp8899Com_aucDebouncingCtr_SPI[SpiL2Channel], CddStp8899Com_ucDEBUG_DebouncingCtr_SPI_Rst) // PRQA S 1862 // warning - QAC(Prio7) Msg: 1862(The operands of this relational operator are of different 'essential signedness' but will both be promoted to 'signed int' for comparison.) Depth: 0 Ref: MISRA C:2012 Rule-10.4 UNTANGLE_RESET(CddStp8899Com_ucDEBUG_DebouncingCtr_SPI_Incr); CddStp8899Com_aucDebouncingCtr_SPI[SpiL2Channel] = 0; // reset - incremented inside of section: 'SPI somehow not valid' // N.b.: // If SPI is VALID there are the SAME values in Data-Mirror-StatvRx & -StatRx // If SPI is INVALID there are the DIFFERENT values in Data-Mirror-StatvRx & -StatRx // checks has been OK, copy now the raw SPI values into the verified status registers data mirror which is accessed from tasks by CddStp8899Com_GetSRegXxx1() CddStp8899Com_DataMirror.StatvRx.aSRegBasic[SpiL2Channel].ucRaw = CddStp8899Com_DataMirror.StatRx.aSRegBasic[SpiL2Channel].ucRaw; // copy verified status register value from raw SPI value CddStp8899Com_DataMirror.StatvRx.aSRegFault[SpiL2Channel].ucRaw = CddStp8899Com_DataMirror.StatRx.aSRegFault[SpiL2Channel].ucRaw; // copy verified status register value from raw SPI value CddStp8899Com_DataMirror.StatvRx.aSRegDiag1[SpiL2Channel].ucRaw = CddStp8899Com_DataMirror.StatRx.aSRegDiag1[SpiL2Channel].ucRaw; // copy verified status register value from raw SPI value CddStp8899Com_DataMirror.StatvRx.aSRegDiag2[SpiL2Channel].ucRaw = CddStp8899Com_DataMirror.StatRx.aSRegDiag2[SpiL2Channel].ucRaw; // copy verified status register value from raw SPI value // incr & check any 'latched'-OL-Error in fct 'CddStp88XX_HalStpLwr_IncOLCnt_' // New debouncing of Open-Load-Error if (CddStp8899Com_DataMirror.StatvRx.aSRegBasic[SpiL2Channel].Bit.u1OL == 1u) // HW-OL-Bit active? { static volatile uint8 CddStp8899Com_DEBUG_MaxErr_OL = 18u; // 100; // 'Cold'-Stp: 0x2A: 1v5, 0x29: 1v15, 0x28=40: 1v200 (7xTX) (9..18V) (OL_Max=0x40), 0x20=32 (6xTX) (9..18V) (OL_Max=0x35), 0x12=18 (4xTX)(OL_Max=0x25)(9..18V) if (CddStp8899Com_aucDebouncingCtr_OL[SpiL2Channel] < CddStp8899Com_DEBUG_MaxErr_OL) // N.b.: Reset-Cmd (in CReg4) is sent only every 6ms -> in order to debounce only twice it takes around 12ms { CddStp8899Com_aucDebouncingCtr_OL[SpiL2Channel]++; UNTANGLE_MAX(CddStp8899Com_ucDEBUG_DebouncingCtr_OL_Max ,CddStp8899Com_aucDebouncingCtr_OL[SpiL2Channel]) // PRQA S 400 // warning - QAC(Prio7) Msg: 400([U] 'CddStp8899Com_ucDEBUG_DebouncingCtr_OL_Max' is modified more than once between sequence points - evaluation order unspecified.) Depth: 0 Ref: MISRA C:2012 Rule-1.3, Rule-13.2; REFERENCE - ISO:C90-6.3 Expressions CddStp8899Com_DataMirror.StatvRx.aSRegBasic[SpiL2Channel].Bit.u1OL = 0; // reset Status-Reg-Basic CddStp8899Com_DataMirror.StatvRx.aSRegFault[SpiL2Channel].Bit.u1OL = 0; // reset Status-Reg-Fault if (CddStp8899Com_DoClearFaultBit[SpiL2Channel] == FALSE) // not already set? { UNTANGLE_INCR(CddStp8899Com_ucDEBUG_DebouncingCtr_OL_Incr) // this var will be reset if OL-Error is gone // reset any latched fault ('Bit.u1SPI_ERROR' or 'Bit.u1OL'): 'CLR_FLT' CddStp8899Com_DoClearFaultBit[SpiL2Channel] = TRUE; // this var wiil be reset if 'CReg4.CLR_FLT' is 'really' sent via SPI-TX } } } else // no OL-Error { UNTANGLE_INCR_IF_NZ(CddStp8899Com_aucDebouncingCtr_OL[SpiL2Channel], CddStp8899Com_ucDEBUG_DebouncingCtr_OL_Rst) // PRQA S 1862 // warning - QAC(Prio7) Msg: 1862(The operands of this relational operator are of different 'essential signedness' but will both be promoted to 'signed int' for comparison.) Depth: 0 Ref: MISRA C:2012 Rule-10.4 UNTANGLE_RESET(CddStp8899Com_ucDEBUG_DebouncingCtr_OL_Incr) CddStp8899Com_aucDebouncingCtr_OL[SpiL2Channel] = 0; // reset } // New debouncing of Over-Current-Protection-Error if (CddStp8899Com_DataMirror.StatvRx.aSRegBasic[SpiL2Channel].Bit.u1OCP == 1u) // HW-OCP-Bit active? { static volatile uint8 CddStp8899Com_DEBUG_MaxErr_OCP = 18u; // -> max=23 & 4xTX (CANoe-SC-Macro with 20ms -> max=30) if (CddStp8899Com_aucDebouncingCtr_OCP[SpiL2Channel] < CddStp8899Com_DEBUG_MaxErr_OCP) // N.b.: Reset-Cmd (in CReg4) is sent only every 6ms -> in order to debounce only twice it takes around 12ms { CddStp8899Com_aucDebouncingCtr_OCP[SpiL2Channel]++; UNTANGLE_MAX(CddStp8899Com_ucDEBUG_DebouncingCtr_OCP_Max, CddStp8899Com_aucDebouncingCtr_OCP[SpiL2Channel]) // PRQA S 400 // warning - QAC(Prio7) Msg: 400([U] 'CddStp8899Com_ucDEBUG_DebouncingCtr_OL_Max' is modified more than once between sequence points - evaluation order unspecified.) Depth: 0 Ref: MISRA C:2012 Rule-1.3, Rule-13.2; REFERENCE - ISO:C90-6.3 Expressions CddStp8899Com_DataMirror.StatvRx.aSRegBasic[SpiL2Channel].Bit.u1OCP = 0; // reset Status-Reg-Basic CddStp8899Com_DataMirror.StatvRx.aSRegFault[SpiL2Channel].Bit.u1OCP = 0; // reset Status-Reg-Fault if (CddStp8899Com_DoClearFaultBit[SpiL2Channel] == FALSE) // not already set? { UNTANGLE_INCR(CddStp8899Com_ucDEBUG_DebouncingCtr_OCP_Incr) // this var will be reset if OCP-Error is gone // reset any latched fault ('Bit.u1SPI_ERROR' or 'Bit.u1OL' or 'Bit.u1OCP'): 'CLR_FLT' CddStp8899Com_DoClearFaultBit[SpiL2Channel] = TRUE; // this var wiil be reset if 'CReg4.CLR_FLT' is 'really' sent via SPI-TX } } } else // no OCP-Error { UNTANGLE_INCR_IF_NZ(CddStp8899Com_aucDebouncingCtr_OCP[SpiL2Channel], CddStp8899Com_ucDEBUG_DebouncingCtr_OCP_Rst) // PRQA S 1862 // warning - QAC(Prio7) Msg: 1862(The operands of this relational operator are of different 'essential signedness' but will both be promoted to 'signed int' for comparison.) Depth: 0 Ref: MISRA C:2012 Rule-10.4 UNTANGLE_RESET(CddStp8899Com_ucDEBUG_DebouncingCtr_OCP_Incr) CddStp8899Com_aucDebouncingCtr_OCP[SpiL2Channel] = 0; // reset } // Stall-Detection - check Stat-Reg concerning 'Stalling-Active'-Bits CddStp8889A_StallDetection_CheckStatReg(); // Stall-Detection - new Torque-Count-Value in Ctrl-Reg-7 available? if (CddStp8899Com_StallDtctn_CR7_bIsNewValue == TRUE) { CddStp8899Com_StallDtctn_CR7_bIsNewValue = FALSE; // reset if ( (CddStp88XX_aStpState[SpiL2Channel].Bit.SpiValid != 0u) // SPI is ok? ...alternative: 'CddStp8899Com_aucDEBUG_SpiOkCounter' && (CddStp8899Com_DataMirror.CtrlRx.aCReg7[0].Bit.u8TRQ_COUNT != CDDSTP8899_RegValVBATSDD)) // maybe the bit has switched before CReg is updated { // set current TRQ-CNT and check if already 'stalling' - check if stalled - if enabled and stalled: switch of stepper (void)CddStp8889A_StallDetection_SetCurrentTrqCnt(CddStp8899Com_DataMirror.CtrlRx.aCReg7[0].Bit.u8TRQ_COUNT); } } // FLMT-4524 // Do this NOT with CURRENT values but do this with LAST VALID values // // Diag: Get raw content of 'all' TI-HW-Registers // *** jk-tbd *** do this EACH time? *** jk-tbd *** // tbd-FLM3 const aucValStp arrayStpRegValues = { // 'Rte_Type.h': 'typedef uint8 aucValStp[12];' // tbd-FLM3 CddStp8899Com_DataMirror.StatRx.aSRegBasic[0].ucRaw, CddStp8899Com_DataMirror.StatRx.aSRegFault[0].ucRaw, // tbd-FLM3 CddStp8899Com_DataMirror.StatRx.aSRegDiag1[0].ucRaw, CddStp8899Com_DataMirror.StatRx.aSRegDiag2[0].ucRaw, // tbd-FLM3 CddStp8899Com_DataMirror.CtrlRx.aCReg1[0].ucRaw, CddStp8899Com_DataMirror.CtrlRx.aCReg2[0].ucRaw, // tbd-FLM3 CddStp8899Com_DataMirror.CtrlRx.aCReg3[0].ucRaw, CddStp8899Com_DataMirror.CtrlRx.aCReg4[0].ucRaw, // tbd-FLM3 CddStp8899Com_DataMirror.CtrlRx.aCReg5[0].ucRaw, CddStp8899Com_DataMirror.CtrlRx.aCReg6[0].ucRaw, // tbd-FLM3 CddStp8899Com_DataMirror.CtrlRx.aCReg7[0].ucRaw, CddStp8899Com_DataMirror.CtrlRx.aCReg8[0].ucRaw // tbd-FLM3 }; // NOT here but a little bit below: (void)Rte_Write_ppCddStpStpRegData0_aucValStp(arrayStpRegValues); // Rte_Write_ctacCddStp_ppCddStpStpRegData0_aucValStp #ifdef CDDSTP_CFG_SIMULATION // defined in '.\Asr6\Src\Src_AL\Cust\Bw\Bw16\App\Bsw\Cdd\CddStp\CddStpPrj.h' // Simulation: Do set the bits of 'CddStp8899Com_DataMirror.StatvRx.aSRegFault' CddStp8899Com_Simulation_HandleSpiRxStatusBits(SpiL2Channel, &boSim_DriverDefect , &boSim_UVLO_UnderVoltageLockout , &boSim_CPUV_ChargePumpUndervoltage , &boSim_OCP_OverCurrentProtection , &boSim_OL_OpenLoad /*, &boSim_TF_ThermalFault*/, &boSim_OTW_OverThermalWarning , &boSim_OTS_OverTemperatureShutdown, &boSim_UTW_UnderTemperatureWarning); #endif // CDDSTP_CFG_SIMULATION // PRQA S 4397 1 // program architecture and readability - intentionally no modification of existing code - warning - QAC(Prio7) Msg: 4397(An expression which is the result of a ~ or << operation has not been cast to its essential type.) Depth: 0 Ref: MISRA C:2012 Rule-10.7 // jk-orig: if ( (CddStp8899Com_DataMirror.CtrlRx.aCReg1[SpiL2Channel].ucRaw & ~CDDSTP8899_old_Mask_MOTEN) == (CddStp8899Com_DataMirror.CtrlTx.aCReg1[SpiL2Channel].ucRaw & ~CDDSTP8899_old_Mask_MOTEN) // do not check CReg1 MOTEN bit to avoid ErrDrvDefect before UV/ErrOL/SC/Therm is detected in case of UV or error before switching driver on because of DRV8899 automatically clears MOTEN bit in this case if ( (CddStp8899Com_DataMirror.CtrlRx.aCReg1[SpiL2Channel].Bit.u4TRQ_DAC == CddStp8899Com_aucTrqDac_LastTx[SpiL2Channel]) // do not check CReg1 MOTEN bit to avoid ErrDrvDefect before UV/ErrOL/SC/Therm is detected in case of UV or error before switching driver on because of DRV8899 automatically clears MOTEN bit in this case || (CddStp8899Com_DataMirror.CtrlRx.aCReg1[SpiL2Channel].Bit.u4TRQ_DAC == CddStp8899Com_aucTrqDac_PrevTx[SpiL2Channel]) // do not check CReg1 MOTEN bit to avoid ErrDrvDefect before UV/ErrOL/SC/Therm is detected in case of UV or error before switching driver on because of DRV8899 automatically clears MOTEN bit in this case ) { UNTANGLE_INCR_IF_NZ(CddStp88XX_aucCheckDrvDefectCnt[SpiL2Channel], CddStp8899Com_ucDEBUG_DebouncingCtr_SPI_Rst) // PRQA S 1862 // warning - QAC(Prio7) Msg: 1862(The operands of this relational operator are of different 'essential signedness' but will both be promoted to 'signed int' for comparison.) Depth: 0 Ref: MISRA C:2012 Rule-10.4 CddStp88XX_aucCheckDrvDefectCnt[SpiL2Channel] = 0; // reset error-counter boVerifyOk = TRUE; // FLMT-4524 // Do this ONLY with LAST VALID values // tbd-FLM3 (void)Rte_Write_ppCddStpStpRegData0_aucValStp(arrayStpRegValues); // Rte_Write_ctacCddStp_ppCddStpStpRegData0_aucValStp } // end of 'if (DataMirror.CtrlRx.TRQ_DAC == DataMirror.CtrlTx.TRQ_DAC)' else // 'Rx' is not verified i.e.: CtrlTx.4TRQ_DAC != CtrlRx.4TRQ_DAC (occures after each change of Tx the first Rx is the old Tx date) { uint16 unDIAG_VBAT; // Vbat [mV] (void)CddStpVolt_IoHwAbUser_GetECUSupply(&unDIAG_VBAT); // get DIAG_VBAT value UNTANGLE_INCR(CddStp8899Com_ulDEBUG_NotVrfyCounter) // this var will never be reset if ( (unDIAG_VBAT >= CDDSTP8899_VBATSDrvDefect) // voltage VBATS not too low and provokes no DRV88XX specific SPI communication error ErrSpiError? && (CddStp88XX_aStpCtrl[SpiL2Channel].Bit.On == 1u) // DRV8899 driver not in sleep mode? && (CddStp8899Com_DataMirror.CtrlRx.aCReg1[SpiL2Channel].ucRaw != CDDSTP8899_RegValVBATSDD) // register value not set by pull up resistances && (CddStp8899Com_DataMirror.CtrlRx.aCReg2[SpiL2Channel].ucRaw != CDDSTP8899_RegValVBATSDD)) // register value not set by pull up resistances { CddStp88XX_aucCheckDrvDefectCnt[SpiL2Channel]++; // will be reset if: CtrlTx==CtrlRx of 'TRQ_DAC' UNTANGLE_MAX(CddStp8899Com_ucDEBUG_DebouncingCtr_SPI2_Max, CddStp88XX_aucCheckDrvDefectCnt[SpiL2Channel]) // PRQA S 400 // warning - QAC(Prio7) Msg: 400([U] 'CddStp8899Com_ucDEBUG_DebouncingCtr_OL_Max' is modified more than once between sequence points - evaluation order unspecified.) Depth: 0 Ref: MISRA C:2012 Rule-1.3, Rule-13.2; REFERENCE - ISO:C90-6.3 Expressions UNTANGLE_INCR(CddStp8899Com_ulDEBUG_DrvDfctCounter) // this var will never be reset } else // voltage VBATS too low or stepper is switched OFF { UNTANGLE_INCR_IF_NZ(CddStp88XX_aucCheckDrvDefectCnt[SpiL2Channel], CddStp8899Com_ucDEBUG_DebouncingCtr_SPI2_Rst) // PRQA S 1862 // warning - QAC(Prio7) Msg: 1862(The operands of this relational operator are of different 'essential signedness' but will both be promoted to 'signed int' for comparison.) Depth: 0 Ref: MISRA C:2012 Rule-10.4 CddStp88XX_aucCheckDrvDefectCnt[SpiL2Channel] = 0; // restart counting SPI errors // for next Kl15 not off // LED6.1 specific: Kl15 off and Led switch on supports uC but not stepper drivers! } // too many SPI-Errors? if (CddStp88XX_aucCheckDrvDefectCnt[SpiL2Channel] >= CDDSTP8899_CHECKDRVDEFECT_MAX) // Debug-Start: Up to '54' { CddStp88XX_aStpState[SpiL2Channel].Bit.ErrSpiError = 1; // set DRV8899 driver defect error bit (in opposite to '....Bit.SpiValid') CddStp8899Com_ucDEBUG_BitErrSpiError = 1; CddStp88XX_aucCheckDrvDefectCnt[SpiL2Channel] = CDDSTP8899_CHECKDRVDEFECT_MAX; // avoid overflow - because of it is sent cyclic in schedule table 0 } } // end of 'if (DataMirror.CtrlRx.TRQ_DAC == DataMirror.CtrlTx.TRQ_DAC) - else // i.e.: NOT verified - occures also because after each change of Tx the first Rx is the old Tx date' } // end of 'if (boSpiValid != FALSE)' else // SPI not valid due to 'some' (all?) 'Rx' == 0xFF or SPI-HW-Error 'Bit.u1SPI_ERROR' (or due to 'Error-Simulation') { UNTANGLE_INCR(CddStp8899Com_ulDEBUG_SpiNOkCounter) // this var will never be reset CddStp88XX_aStpState[SpiL2Channel].Bit.SpiValid = 0; // SPI not valid (driver is in Sleep mode or startup or problem) (yet NO error) (N.b.: in opposite to '...Bit.ErrSpiError') CddStp8899Com_ucDEBUG_BitSpiValid = 0; UNTANGLE_RESET(CddStp8899Com_ucDEBUG_SpiOkCounter) CddStp8899Com_DataMirror.StatvRx.aSRegBasic[SpiL2Channel].ucRaw = 0u; // reset due to invalid SPI-Values CddStp8899Com_DataMirror.StatvRx.aSRegFault[SpiL2Channel].ucRaw = 0u; // reset due to invalid SPI-Values CddStp8899Com_DataMirror.StatvRx.aSRegDiag1[SpiL2Channel].ucRaw = 0u; // reset due to invalid SPI-Values CddStp8899Com_DataMirror.StatvRx.aSRegDiag2[SpiL2Channel].ucRaw = 0u; // reset due to invalid SPI-Values if ( (CddStp88XX_aStpCtrl[SpiL2Channel].Bit.On == 1u) // DRV8899 driver NOT in sleep mode? && (CddStp8899Com_DataMirror.StatRx.aSRegFault[SpiL2Channel].ucRaw != CDDSTP8899_RegValVBATSDD)) // DRV8899 driver sends real data? { CddStp88XX_aucCheckDrvDefectCnt[SpiL2Channel]++; // will be reset if: CtrlRx==CtrlTx of 'TRQ_DAC' UNTANGLE_MAX( CddStp8899Com_ucDEBUG_DebouncingCtr_SPI3_Max, CddStp88XX_aucCheckDrvDefectCnt[SpiL2Channel]) // PRQA S 400 // warning - QAC(Prio7) Msg: 400([U] 'CddStp8899Com_ucDEBUG_DebouncingCtr_OL_Max' is modified more than once between sequence points - evaluation order unspecified.) Depth: 0 Ref: MISRA C:2012 Rule-1.3, Rule-13.2; REFERENCE - ISO:C90-6.3 Expressions UNTANGLE_INCR(CddStp8899Com_ulDEBUG_DrvDfctCounter) // this var will never be reset #ifdef CDDSTP_CFG_SIMULATION // defined in '.\Asr6\Src\Src_AL\Cust\Bw\Bw16\App\Bsw\Cdd\CddStp\CddStpPrj.h' if (boSim_SPI_ERROR_SpiProtocolError != FALSE) // only about 'simulation' { CddStp8899Com_DataMirror.StatRx.aSRegFault[SpiL2Channel].Bit.u1SPI_ERROR = 1u; } #endif // New debouncing of SPI-Error if (CddStp8899Com_DataMirror.StatRx.aSRegFault[SpiL2Channel].Bit.u1SPI_ERROR == 1u) // HW-SPI-Err-Bit active? { if (CddStp8899Com_aucDebouncingCtr_SPI2[SpiL2Channel] < CDDSTP8899_CHECKDRVDEFECT_MAX) // N.b.: Reset-Cmd (in CReg4) is sent only every 6ms -> in order to debounce only twice it takes around 12ms { CddStp8899Com_aucDebouncingCtr_SPI2[SpiL2Channel]++; UNTANGLE_MAX(CddStp8899Com_ucDEBUG_DebouncingCtr_SPI4_Max, CddStp8899Com_aucDebouncingCtr_SPI2[SpiL2Channel]) // PRQA S 400 // warning - QAC(Prio7) Msg: 400([U] 'CddStp8899Com_ucDEBUG_DebouncingCtr_OL_Max' is modified more than once between sequence points - evaluation order unspecified.) Depth: 0 Ref: MISRA C:2012 Rule-1.3, Rule-13.2; REFERENCE - ISO:C90-6.3 Expressions if (CddStp8899Com_DoClearFaultBit[SpiL2Channel] == FALSE) // not already set? { // reset any latched fault ('Bit.u1SPI_ERROR' or 'Bit.u1OL' or 'Bit.u1OCP'): 'CLR_FLT' CddStp8899Com_DoClearFaultBit[SpiL2Channel] = TRUE; // this var wiil be reset if 'CReg4.CLR_FLT' is 'really' sent via SPI-TX UNTANGLE_INCR(CddStp8899Com_ucDEBUG_DebouncingCtr_SPI4_Incr) // this var will be reset if SPI-Error is gone UNTANGLE_INCR(CddStp8899Com_ucDEBUG_DebouncingCtr_SpiFaultClear) // this var will never be reset } } // end of 'debouncing yet not max' } // end of 'DataMirror.StatRx.aSRegFault.Bit.u1SPI_ERROR == 1u' else // no SPI-Error - (probably?) comes never here { UNTANGLE_INCR_IF_NZ(CddStp8899Com_aucDebouncingCtr_SPI2[SpiL2Channel], CddStp8899Com_ucDEBUG_DebouncingCtr_SPI4_Rst) // PRQA S 1862 // warning - QAC(Prio7) Msg: 1862(The operands of this relational operator are of different 'essential signedness' but will both be promoted to 'signed int' for comparison.) Depth: 0 Ref: MISRA C:2012 Rule-10.4 UNTANGLE_RESET(CddStp8899Com_ucDEBUG_DebouncingCtr_SPI4_Incr) CddStp8899Com_aucDebouncingCtr_SPI2[SpiL2Channel] = 0; // reset - handled only 'here' inside of section: 'SPI somehow not valid' } // Check of too many SPI-Error // N.B.: Do NOT check 'CddStp8899Com_aucDebouncingCtr_SPI' because this is just a 'Sub'-Counter of 'CddStp88XX_aucCheckDrvDefectCnt' if (CddStp88XX_aucCheckDrvDefectCnt[SpiL2Channel] >= CDDSTP8899_CHECKDRVDEFECT_MAX) { CddStp88XX_aStpState[SpiL2Channel].Bit.ErrSpiError = 1; // set DRV8899 driver defect error bit (in opposite to '....Bit.SpiValid') CddStp8899Com_ucDEBUG_BitErrSpiError = 1; CddStp88XX_aucCheckDrvDefectCnt[SpiL2Channel] = CDDSTP8899_CHECKDRVDEFECT_MAX; // avoid overflow - because of it is sent cyclic in schedule table 0 } } // end of 'Bit.On == 1' } // end of 'SPI is NOT ok' // PRQA S 4558 1 // program architecture and readability - intentionally no modification of existing code - warning - QAC(Prio7) Msg: 4558(An expression of 'essentially unsigned' type (unsigned char) is being used as the left-hand operand of this logical operator (&&).) Depth: 0 Ref: MISRA C:2012 Rule-10.1 return (boVerifyOk && boSpiValid) ? TRUE : FALSE; // PRQA S 5310, 5316, 5330, 5336 1 // program architecture and readability - intentionally no modification of existing code - warning - QAC(Prio2) Msg: 5310(HIS metrics violation: 'CddStp8899Com_CheckSpiComSt0() : STPTH = 646' exceeds threshold 80 for Number of paths (STPTH).) | Msg: 5316(HIS metrics violation: 'CddStp8899Com_CheckSpiComSt0() : STCYC = 17' exceeds threshold 15 for Cyclomatic complexity (STCYC).) } #ifdef CDDSTP_CFG_SIMULATION // defined in '.\Asr6\Src\Src_AL\Cust\Bw\Bw16\App\Bsw\Cdd\CddStp\CddStpPrj.h' //----------------------------------------------------------------------------- /// \brief CddStp8899Com_Simulation_HandleSpiRxStatusBits /// /// \descr SET the 'real' bits of 'CddStp8899Com_DataMirror.StatvRx.aSRegFault' /// /// \param SpiL2Channel /// \param pboSim_DriverDefect /// \param pboSim_UVLO_UnderVoltageLockout /// \param pboSim_CPUV_ChargePumpUndervoltage /// \param pboSim_OCP_OverCurrentProtection /// \param pboSim_OL_OpenLoad /// \param pboSim_OTW_OverThermalWarning /// \param pboSim_OTS_OverTemperatureShutdown /// \param pboSim_UTW_UnderTemperatureWarning /// /// \return STATIC_AL void //----------------------------------------------------------------------------- STATIC_AL void CddStp8899Com_Simulation_HandleSpiRxStatusBits(tCddSpiL2Channel SpiL2Channel, const boolean *pboSim_DriverDefect , const boolean *pboSim_UVLO_UnderVoltageLockout, const boolean *pboSim_CPUV_ChargePumpUndervoltage , const boolean *pboSim_OCP_OverCurrentProtection, const boolean *pboSim_OL_OpenLoad /*, const boolean *pboSim_TF_ThermalFault*/, const boolean *pboSim_OTW_OverThermalWarning , const boolean *pboSim_OTS_OverTemperatureShutdown, const boolean *pboSim_UTW_UnderTemperatureWarning) { // check simulation if (CddStp_Simulation_IsSimActive() != FALSE) { // check simulation if (*pboSim_DriverDefect != FALSE) { CddStp88XX_aStpState[SpiL2Channel].Bit.ErrSpiError = 1; // set DRV8899 driver defect error bit CddStp8899Com_ucDEBUG_BitErrSpiError = 1; // CddStp8899Com_DataMirror.StatvRx.aSRegBasic[SpiL2Channel].Bit....: not available CddStp8899Com_DataMirror.StatvRx.aSRegFault[SpiL2Channel].Bit.u1FAULT = TRUE; CddStp8899Com_DataMirror.StatvRx.aSRegFault[SpiL2Channel].Bit.u1OCP = TRUE; // tbd-jk: WORKAROUND in order to simulate an error CddStp8899Com_DataMirror.StatvRx.aSRegFault[SpiL2Channel].Bit.u1OL = TRUE; // tbd-jk: WORKAROUND in order to simulate an error } else { // no need to reset: Variable 'CddStp8899Com_DataMirror' is set each time of SPI-RX } if (*pboSim_UVLO_UnderVoltageLockout != FALSE) { CddStp8899Com_DataMirror.StatvRx.aSRegBasic[SpiL2Channel].Bit.u1UVLO = TRUE; CddStp8899Com_DataMirror.StatvRx.aSRegFault[SpiL2Channel].Bit.u1UVLO = TRUE; } else { // no need to reset: Variable 'CddStp8899Com_DataMirror' is set each time of SPI-RX } if (*pboSim_CPUV_ChargePumpUndervoltage != FALSE) { CddStp8899Com_DataMirror.StatvRx.aSRegBasic[SpiL2Channel].Bit.u1CPUV = TRUE; CddStp8899Com_DataMirror.StatvRx.aSRegFault[SpiL2Channel].Bit.u1CPUV = TRUE; } else { // no need to reset: Variable 'CddStp8899Com_DataMirror' is set each time of SPI-RX } if (*pboSim_OCP_OverCurrentProtection != FALSE) { CddStp8899Com_DataMirror.StatvRx.aSRegBasic[SpiL2Channel].Bit.u1OCP = TRUE; CddStp8899Com_DataMirror.StatvRx.aSRegFault[SpiL2Channel].Bit.u1OCP = TRUE; } else { // no need to reset: Variable 'CddStp8899Com_DataMirror' is set each time of SPI-RX } if (*pboSim_OL_OpenLoad != FALSE) { CddStp8899Com_DataMirror.StatvRx.aSRegBasic[SpiL2Channel].Bit.u1OL = TRUE; CddStp8899Com_DataMirror.StatvRx.aSRegFault[SpiL2Channel].Bit.u1OL = TRUE; } else { // no need to reset: Variable 'CddStp8899Com_DataMirror' is set each time of SPI-RX } // 'TF': Logic OR of the overtemperature warning, undertemperature warning and overtemperature shutdown. // 'TF' is set in 'OTS' or 'OTW' or 'UTW' if (*pboSim_TF_ThermalFault != FALSE) // 'TF' is set in 'OTS' or 'OTW' or 'UTW' { // 'TF' is set in 'OTS' or 'OTW' or 'UTW' CddStp8899Com_DataMirror.StatvRx.aSRegBasic[SpiL2Channel].Bit.u1TF = TRUE; // 'TF' is set in 'OTS' or 'OTW' or 'UTW' CddStp8899Com_DataMirror.StatvRx.aSRegFault[SpiL2Channel].Bit.u1TF = TRUE; // Logic OR of the overtemperature warning, undertemperature warning and overtemperature shutdown. // 'TF' is set in 'OTS' or 'OTW' or 'UTW' CddStp8899Com_DataMirror.StatvRx.aSRegDiag2[SpiL2Channel].Bit.u1OTS = TRUE; // Indicates overtemperature shutdown // 'TF' is set in 'OTS' or 'OTW' or 'UTW' } // 'TF' is set in 'OTS' or 'OTW' or 'UTW' else // 'TF' is set in 'OTS' or 'OTW' or 'UTW' { // 'TF' is set in 'OTS' or 'OTW' or 'UTW' } if (*pboSim_OTS_OverTemperatureShutdown != FALSE) { CddStp8899Com_DataMirror.StatvRx.aSRegBasic[SpiL2Channel].Bit.u1TF = TRUE; CddStp8899Com_DataMirror.StatvRx.aSRegFault[SpiL2Channel].Bit.u1TF = TRUE; // Logic OR of the overtemperature warning, undertemperature warning and overtemperature shutdown. CddStp8899Com_DataMirror.StatvRx.aSRegDiag2[SpiL2Channel].Bit.u1OTS = TRUE; // Indicates overtemperature shutdown } else { // no need to reset: Variable 'CddStp8899Com_DataMirror' is set each time of SPI-RX } if (*pboSim_OTW_OverThermalWarning != FALSE) { CddStp8899Com_DataMirror.StatvRx.aSRegBasic[SpiL2Channel].Bit.u1TF = TRUE; CddStp8899Com_DataMirror.StatvRx.aSRegFault[SpiL2Channel].Bit.u1TF = TRUE; // Logic OR of the overtemperature warning, undertemperature warning and overtemperature shutdown. CddStp8899Com_DataMirror.StatvRx.aSRegDiag2[SpiL2Channel].Bit.u1OTW = TRUE; // Indicates overtemperature warning } else { // no need to reset: Variable 'CddStp8899Com_DataMirror' is set each time of SPI-RX } if (*pboSim_UTW_UnderTemperatureWarning != FALSE) { CddStp8899Com_DataMirror.StatvRx.aSRegBasic[SpiL2Channel].Bit.u1TF = TRUE; CddStp8899Com_DataMirror.StatvRx.aSRegFault[SpiL2Channel].Bit.u1TF = TRUE; // Logic OR of the overtemperature warning, undertemperature warning and overtemperature shutdown. CddStp8899Com_DataMirror.StatvRx.aSRegDiag2[SpiL2Channel].Bit.u1UTW = TRUE; // Indicates undertemperature warning } else { // no need to reset: Variable 'CddStp8899Com_DataMirror' is set each time of SPI-RX } } // end of 'if (CddStp_Simulation_IsSimActive() != FALSE)' else // no simulation is active { // no simulation is active -> no changes are done } // PRQA S 5310, 5328 1 // program architecture and readability - intentionally no modification of existing code - warning - QAC(Prio2) Msg: 5310(HIS metrics violation: 'CddStp8899Com_Simulation_HandleSpiRxStatusBits() : STPTH = 129' exceeds threshold 80 for Number of paths (STPTH).) | warning - QAC(Prio2) Msg : 5328(HIS metrics violation : 'CddStp8899Com_Simulation_HandleSpiRxStatusBits() : STPAR = 8' exceeds threshold 5 for Number of function parameters(STPAR).) } #endif // CDDSTP_CFG_SIMULATION /* //----------------------------------------------------------------------------- /// \brief check SPI communication for schedule table 1 as write verify of control registers 3...7 and read control registers 3...7 /// /// \descr check communication by comparison of TX and RX data of CR3...7 registers /// /// \param tCddSpiL2Channel SpiL2Channel /// /// \return boolean boVerifyOk //----------------------------------------------------------------------------- static boolean CddStp8899Com_CheckSpiComSt1(tCddSpiL2Channel SpiL2Channel) { boolean boVerifyOk = FALSE; uint16 unSpiCheckDrvDefectCReg1, unSpiCheckDrvDefectCReg2, unSpiCheckDrvDefectCReg3, unSpiCheckDrvDefectCReg4; unSpiCheckDrvDefectCReg1 = CddStp8899Com_DataMirror.CtrlRx.aCReg1 [SpiL2Channel]; // control register 1 RX unSpiCheckDrvDefectCReg2 = CddStp8899Com_DataMirror.CtrlRx.aCReg2 [SpiL2Channel]; // control register 2 RX unSpiCheckDrvDefectCReg3 = CddStp8899Com_DataMirror.CtrlRx.aCReg3 [SpiL2Channel]; // control register 3 RX unSpiCheckDrvDefectCReg4 = CddStp8899Com_DataMirror.CtrlRx.aCReg4 [SpiL2Channel]; // control register 4 RX // schedule table 1 writes and reads control registers 3, 4, 5, 6, 7 if ( ( unSpiCheckDrvDefectCReg1 == CddStp8899Com_DataMirror.CtrlTx.aCReg1 [SpiL2Channel]) && ( unSpiCheckDrvDefectCReg2 == CddStp8899Com_DataMirror.CtrlTx.aCReg2 [SpiL2Channel]) && ( unSpiCheckDrvDefectCReg3 == CddStp8899Com_DataMirror.CtrlTx.aCReg3 [SpiL2Channel]) && ( unSpiCheckDrvDefectCReg4 == CddStp8899Com_DataMirror.CtrlTx.aCReg4 [SpiL2Channel])) { CddStp88XX_aucCheckDrvDefectCnt[SpiL2Channel] = 0; boVerifyOk = TRUE; } else // not verified { uint16 unDIAG_VBAT; // Vbat [mV] (void)CddStpVolt_IoHwAbUser_GetECUSupply(&unDIAG_VBAT); // get DIAG_VBAT value if ( (unDIAG_VBAT >= CDDSTP8899_VBATSDrvDefect) // voltage VBATS not too low and provokes no DRV88XX specific SPI communication error ErrSpiError? && (unSpiCheckDrvDefectCReg1 != CDDSTP8899_RegValVBATSDD) // register value not set by pull up resistances && (unSpiCheckDrvDefectCReg2 != CDDSTP8899_RegValVBATSDD) // register value not set by pull up resistances && (unSpiCheckDrvDefectCReg3 != CDDSTP8899_RegValVBATSDD) // register value not set by pull up resistances && (unSpiCheckDrvDefectCReg4 != CDDSTP8899_RegValVBATSDD)) // register value not set by pull up resistances { CddStp88XX_aucCheckDrvDefectCnt[SpiL2Channel]++; } else // voltage VBATS too low // Kl15 off // LED6.1 specific: Kl15 off and Led switch on supports uC but not stepper drivers! { CddStp88XX_aucCheckDrvDefectCnt[SpiL2Channel] = 0; // restart counting SPI errors // for next Kl15 not off // LED6.1 specific: Kl15 off and Led switch on supports uC but not stepper drivers! } if (CddStp88XX_aucCheckDrvDefectCnt[SpiL2Channel] >= CDDSTP8899_CHECKDRVDEFECT_MAX) { CddStp88XX_aStpState[SpiL2Channel].Bit.ErrSpiError = 1; // set DRV8899 driver defect error bit } else // try next verify CDDSTP8899_CHECKDRVDEFECT_MAX { CddStp8899Com_StReqSingle(SpiL2Channel, CDDSTP8899_SpiSt_WriteCr34A67_ReadCr34A67); // send once more } } return boVerifyOk; } */ //----------------------------------------------------------------------------- /// \brief Called after reception of a SPI frame /// /// \descr The function reads the content of SPI Rx data provided by SPI and store data in CddStp-DataMirror. /// CB-Handling config by .\Asr6\Src\Src_AL\Cust\Bw\Bw16\App\Bsw\Cdd\CddSpi\Cfg\CddSpi_Cfg.h /// SPI-EFT-Handling: 'CddSpi_GetStpConfig' /// /// \param unIx index of stepper (up to SW-A340 = HW-B2: 3 stp) /// \param ulData : SPI Rx data (only 16 LSB valid) /// /// \return void //----------------------------------------------------------------------------- void CddStp_SpiRx(const uint16 unIx, const uint32 ulData) { if (unIx < CFA_CNT_STP_88XX) { CddStp8899Com_SpiRx(unIx, (uint16)ulData); } } //----------------------------------------------------------------------------- /// \brief Called between reception of SPI telegram and /// transmission of next SPI telegram /// /// \descr This function gets raw SPI RX data and stores the contents /// in CddStp8899Com_DataMirror. Then the function determines the /// next SPI telegram. Now the contents of the CddStp8899Com_DataMirror /// are read to start data transmission. /// /// \param uint16 unIx: index to DRV8899 chip /// uint16 unData: 16 bit raw RX data /// /// \return - //----------------------------------------------------------------------------- STATIC_AL void CddStp8899Com_SpiRx(uint16 unIx, uint16 unData) // currently called by obsolet fct 'CddStp8899_SpiRx' { // // 1st of all: // Check EFT for num of 'installed' (not just 'coded') steppers // If there is only ONE stepper, NO 'Daisy-Chain'-Handling is used // const uint8 ucNumOfSteppers_EFT = CddStp88XX_GetNumOfSteppers_EFT(); // HongQi-Hr: '1' ... BUT: Initial-ECU has TWO const tCddStp88XX_TypeOfHw eTypeOfStepper_LWR = CddStp88XX_GetTypeOfSteppers_EFT(); if ((ucNumOfSteppers_EFT == 0u) // maybe param yet not loaded || (eTypeOfStepper_LWR == CDDSTP88XX_Hw_eUnknown)) { return; } // at least ONE HW-Stepper-Chip is available else { uint8 ucSchedStateOld; uint8 ucLoByte_, ucHiByte_; // orig.: const tCddStp8899Com_SpiSchedTable* pTabEntry; static volatile const tCddStp8899Com_SpiSchedTable* pTabEntry; // jk-tbd: // static volatile tCddStp8899Com_StatReg_Basic aRegBsc_lastError [CDDSTP_8899_CNT]; // 1 | 1 | UVLO | CPUV | OCP | RSVD | TF | OL - Basic-Status-Registers - comes each time one each SPI-Response: Stat3 Stat2 Stat1 Hdr1 Hdr2 Reg3 Reg2 Reg1 // jk-tbd: static volatile uint8 aRegBsc_lastError [4]; // 1 | 1 | UVLO | CPUV | OCP | RSVD | TF | OL - Basic-Status-Registers - comes each time one each SPI-Response: Stat3 Stat2 Stat1 Hdr1 Hdr2 Reg3 Reg2 Reg1 ///// __DI(); // call from interrupt level is not possible (no counter)! ///// osDisableGlobal(); // call from interrupt level is not possible (no counter)! //Lr06 SuspendAllInterrupts(); // jk-tbd-HW-02 uint32 ulDisableIntKey; // jk-tbd-HW-02 ulDisableIntKey = __DIR(); // calculate pointer to actual schedule table entry if (eTypeOfStepper_LWR == CDDSTP88XX_Hw_e8889A) { pTabEntry = &CddStp8899Com_SpiSchedTable_XT[CddStp8899Com_aucSchedState[unIx]]; } else // should be '8899' { pTabEntry = &CddStp8899Com_SpiSchedTable[CddStp8899Com_aucSchedState[unIx]]; } // only ONE HW-Stepper-Chip if (ucNumOfSteppers_EFT == 1u) // no daisy-chain { // TX: A1 D1 -> Adr & Data // RX: S1 R1 -> Status & Report // | | // | |--> 8 Bytes // |-----> 8 Bytes // // ECU-TX: // the sdi input data word is 16 bits long and consists of the following format: // * 1 read or write bit, w (bit 14) // * 5 address bits, a (bits 13 through 9) // * 8 data bits, d (bits 7 through 0) // // sdi input data word format // b15 b14 b13 b12 b11 b10 b9 b8 b7 b6 b5 b4 b3 b2 b1 b0 // 0 w0 a4 a3 a2 a1 a0 x d7 d6 d5 d4 d3 d2 d1 d0 -> mosi: a1 d1 // // ECU-RX // the sdo output-data word is 16 bits long and the first 8 bits make up the status register (s1). // the report word (r1) is the content of the register being accessed. // for a write command (w0 = 0), the response word on the sdo pin is the data currently in the register being written to. // for a read command (w0 = 1), the response word is the data currently in the register being read. // // sdo output data word format // b15 b14 b13 b12 b11 b10 b9 b8 b7 b6 b5 b4 b3 b2 b1 b0 // 1 1 uvlo cpuv ocp rsvd tf ol d7 d6 d5 d4 d3 d2 d1 d0 -> miso: s1 r1 // | | | | | | | | // 1 1 0 0 . 0 0 0 0 = 0xC0 // only ONE stepper -> 'unIx' is always '0' if (unIx == 0u) { uint8* pucStatusBasic = ST_STAT_RX_SRB; // Basic-Status-Registers: 1 | 1 | UVLO | CPUV | OCP | RSVD | TF | OL - comes EACH time in each SPI-Response pucStatusBasic[0] = (uint8)((0x3F00u & unData) >> 8u); // e.g. 0xC123 -> take '0x01' - do NOT take the top two bits because they are always '1' in this response pTabEntry->pucRxDataByte[0] = (uint8)(0x00FFu & unData); // e.g. 0xC123 -> take '0x23' - requested register: either 'previous' Ctrl-Register or current State-Register // data is from Ctrl-Reg-7 (= TRQ_CNT) ? if (&pTabEntry->pucRxDataByte[0] == ST_CTRL_RX_CR7) { CddStp8899Com_StallDtctn_CR7_bIsNewValue = TRUE; // do not use it at once but check it 1st ... ('CddStp8889A_StallDetection_SetCurrentTrqCnt(pTabEntry->pucRxDataByte[0]); // uint8 ucTrqCnt') } // else // any other reg...: do NOT reset here } } // end of 'if (ucNumOfSteppers_EFT == 1u)' // no daisy-chain // 2 HW-Stepper-Chips else if (ucNumOfSteppers_EFT == 2u) // ECU 8.x or initial HW of HongQi-H5 { // 2-Stepper-Handling via Daisy-Chain: // // TI - DRV8899 / DRV8889A: // Send-Data: Hdr1 Hdr2 RegAdr2 RegAdr1 Dt2 Dt1 // Response-Data: Stat2 Stat1 Hdr1 Hdr2 Reg2 Reg1 // StatX?: Basic Status-Reg. - comes each time automatically // Hdr1: 1.0.n5...n0 - n=count of daisy-chain-members = '2' // // Req./Tx: // -> word-0: Hdr1 Hdr2 // -> word-1: RegAdr2 RegAdr1 // -> word-2: Dt2 Dt1 // e.g.: 0x82 0x80 0x0C 0x0C 0xE0 0xE0 // N.b.: // In SPI-Buffer 'mixed': Hdr2 Hdr1 | A1 A2 | D1 D2 // // Resp./Rx: // -> word-0: StatBsc2 StatBsc1 // -> word-1: Hdr1 Hdr2 // -> word-3: RegData2 RegData1 // // jk-TI-Daisy-Chain-Handling *#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*# // input: =2,1,0, 2,1,0, 2,1,0, .... // needed: 0,1,2, 0,1,2, ... if (unIx == 2u) { // Response-Data: Stat2 Stat1 Hdr1 Hdr2 Reg2 Reg1 // unIx=0,1,2: -----0-----,-----1---,----2---- // relevant: ^^^^^^^^^^^ // -> unIx-0 = Stat2 & Stat1 (= 2x Basic-Status-Register - comes EACH time 'automatically'!!) // jk-orig pucStatusBasic[2] = (uint8)((0x00003F00U & ulData) >> 8); // store RX data Stp-3 - do NOT take the top two bytes because they are always '1' in this response // jk-orig pucStatusBasic[1] = (uint8) (0x0000003FU & ulData); // store RX data Stp-2 - do NOT take the top two bytes because they are always '1' in this response /*static volatile*/ uint8* pucStatusBasic = ST_STAT_RX_SRB; pucStatusBasic[1] = (uint8)((0x3F00U & unData) >> 8u); // store RX data Stp-2 - do NOT take the top two bytes because they are always '1' in this response pucStatusBasic[0] = (uint8)((0x003FU & unData)); // store RX data Stp-1 - do NOT take the top two bytes because they are always '1' in this response // Basic-Status-Registers - comes each time one each SPI-Response: StsBsc2 StsBsc1 Hdr1 Hdr2 Reg2 Reg1 // 1 | 1 | UVLO | CPUV | OCP | RSVD | TF | OL (any error: 0011.1011=0x3B) // PRQA S 1861, 2214, 4542 2 // program architecture and readability - intentionally no modification of existing code - warning - QAC(Prio7) Msg: 1861(The operands of this bitwise operator are of different 'essential signedness' but will generate a result of type 'signed int'.) Depth: 0 Ref: MISRA C:2012 Rule-10.4 | warning - QAC(Prio7) Msg : 4542(A non - negative constant expression of 'essentially signed' type(signed char) is being used as the right - hand operand of this bitwise operator (&).) Depth : 0 Ref : MISRA C : 2012 Rule - 10.1 | warning - QAC(Prio7) Msg : 2214(Body of control statement is on the same line and is not enclosed within braces.) Depth : 0 Ref : MISRA C : 2012 Rule - 15.6 // jk-tbd: if ((pucStatusBasic[1] & 0x3Bu) > 0u) aRegBsc_lastError[1]/*.ucRaw*/ = pucStatusBasic[1]; // jk-tbd: if ((pucStatusBasic[0] & 0x3Bu) > 0u) aRegBsc_lastError[0]/*.ucRaw*/ = pucStatusBasic[0]; } else if (unIx == 1u) { // Response-Data: Stat2 Stat1 Hdr1 Hdr2 Reg2 Reg1 // unIx=0,1,2: -----0-----,-----1---,----2---- // relevant: ^^^^^^^^^^ // -> unIx-1 = Hdr1 & Hdr2 // yet not evaluated } else if (unIx == 0u) { // Response-Data: Stat2 Stat1 Hdr1 Hdr2 Reg2 Reg1 // unIx=0,1,2: -----0-----,-----1---,----2---- // relevant: ^^^^^^^^^ // -> unIx-2 = Reg2 Reg1 pTabEntry->pucRxDataByte[1] = (uint8)(unData >> 8u); // store RX Stp-2 in data 1 - e.g. 'ST_CTRL_RX_CR3' pTabEntry->pucRxDataByte[0] = (uint8)(unData); // store RX Stp-1 in data 1 - e.g. 'ST_CTRL_RX_CR3' } else { // MISRA / QAC - intentionally empty } } // end of '... else if (ucNumOfSteppers_EFT == 2u) ...' // 3 HW-Stepper-Chips else if (ucNumOfSteppers_EFT == 3u) // 'old' HW B2 and older { // 3-Stepper-Handling via Daisy-Chain: // // TI - DRV8899 / DRV8889A: // Send-Data: Hdr1 Hdr2 RegAdr3 RegAdr2 RegAdr1 Dt3 Dt2 Dt1 // Response-Data: Stat3 Stat2 Stat1 Hdr1 Hdr2 Reg3 Reg2 Reg1 // StatX?: Basic Status-Reg. - comes each time automatically // Hdr1: 1.0.n5...n0 - n=count of daisy-chain-members = '3' // // Req./Tx: // -> word-0: Hdr1 Hdr2 // -> word-1: RegAdr3 RegAdr2 // -> word-2: RegAdr1 Dt3 // -> word-3: Dt2 Dt1 // e.g.: 0x83 0x80 0x0C 0x0C 0x0C 0xE0 0xE0 0xE0 // N.b.: // In SPI-Buffer 'mixed': Hdr2 Hdr1 | A2 A3 | D3 A1 | D1 D2 // // Resp./Rx: // -> word-0: StatBsc3 StatBsc2 // -> word-1: StatBsc1 Hdr1 // -> word-2: Hdr2 RegData3 // -> word-3: RegData2 RegData1 // // jk-TI-Daisy-Chain-Handling *#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*# // input: =3,2,1,0, 3,2,1,0, 3,2,1,0, .... // needed: 0,1,2,3, 0,1,2,3, ... if (unIx == 3u) { // Response-Data: Stat3 Stat2 Stat1 Hdr1 Hdr2 Reg3 Reg2 Reg1 // unIx=0,1,2,3: -----0-----,-----1----,----2----,----3---- // relevant: ^^^^^^^^^^^ // -> unIx-0 = Stat3 & Stat2 (= 2x Basic-Status-Register - comes EACH time 'automatically'!!) // jk-orig pucStatusBasic[2] = (uint8)((0x00003F00U & ulData) >> 8); // store RX data Stp-3 - do NOT take the top two bytes because they are always '1' in this response // jk-orig pucStatusBasic[1] = (uint8) (0x0000003FU & ulData); // store RX data Stp-2 - do NOT take the top two bytes because they are always '1' in this response /*static volatile*/ uint8* pucStatusBasic = ST_STAT_RX_SRB; /* polyspace +2 RTE:IDP [Justified:Low] "Illegally dereferenced pointer - Reviewed - intentionally no modification of existing code" */ pucStatusBasic[2] = (uint8)((0x3F00U & unData) >> 8u); // store RX data Stp-3 - do NOT take the top two bytes because they are always '1' in this response pucStatusBasic[1] = (uint8)((0x003FU & unData)); // store RX data Stp-2 - do NOT take the top two bytes because they are always '1' in this response // Basic-Status-Registers - comes each time one each SPI-Response: StsBsc3 StsBsc2 StsBsc1 Hdr1 Hdr2 Reg3 Reg2 Reg1 // 1 | 1 | UVLO | CPUV | OCP | RSVD | TF | OL (any error: 0011.1011=0x3B) // PRQA S 1861, 2214, 4542 2 // program architecture and readability - intentionally no modification of existing code - warning - QAC(Prio7) Msg: 1861(The operands of this bitwise operator are of different 'essential signedness' but will generate a result of type 'signed int'.) Depth: 0 Ref: MISRA C:2012 Rule-10.4 | warning - QAC(Prio7) Msg : 4542(A non - negative constant expression of 'essentially signed' type(signed char) is being used as the right - hand operand of this bitwise operator (&).) Depth : 0 Ref : MISRA C : 2012 Rule - 10.1 | warning - QAC(Prio7) Msg : 2214(Body of control statement is on the same line and is not enclosed within braces.) Depth : 0 Ref : MISRA C : 2012 Rule - 15.6 // jk-tbd: if ((pucStatusBasic[2] & 0x3Bu) > 0u) aRegBsc_lastError[2]/*.ucRaw*/ = pucStatusBasic[2]; // jk-tbd: if ((pucStatusBasic[1] & 0x3Bu) > 0u) aRegBsc_lastError[1]/*.ucRaw*/ = pucStatusBasic[1]; } else if (unIx == 2u) { // Response-Data: Stat3 Stat2 Stat1 Hdr1 Hdr2 Reg3 Reg2 Reg1 // unIx=0,1,2,3: -----0-----,-----1----,----2----,----3---- // relevant: ^^^^^^^^^^ // -> unIx-1 = Stat1 & Hdr1 // jk-orig pucStatusBasic[0] = (uint8)((0x00003F00U & ulData) >> 8); // store RX data Stp-1 - do NOT take the top two bytes because they are always '1' in this response uint8* pucStatusBasic = ST_STAT_RX_SRB; pucStatusBasic[0] = (uint8)((0x3F00U & unData) >> 8u); // store RX data Stp-1 - do NOT take the top two bytes because they are always '1' in this response // Basic-Status-Registers - comes each time one each SPI-Response: StsBsc3 StsBsc2 StsBsc1 Hdr1 Hdr2 Reg3 Reg2 Reg1 // 1 | 1 | UVLO | CPUV | OCP | RSVD | TF | OL // PRQA S 1861, 2214, 4542 1 // program architecture and readability - intentionally no modification of existing code - warning - QAC(Prio7) Msg: 1861(The operands of this bitwise operator are of different 'essential signedness' but will generate a result of type 'signed int'.) Depth: 0 Ref: MISRA C:2012 Rule-10.4 | warning - QAC(Prio7) Msg : 4542(A non - negative constant expression of 'essentially signed' type(signed char) is being used as the right - hand operand of this bitwise operator (&).) Depth : 0 Ref : MISRA C : 2012 Rule - 10.1 | warning - QAC(Prio7) Msg : 2214(Body of control statement is on the same line and is not enclosed within braces.) Depth : 0 Ref : MISRA C : 2012 Rule - 15.6 // jk-tbd: if ((pucStatusBasic[0] & 0x3Bu) > 0u) aRegBsc_lastError[0]/*.ucRaw*/ = pucStatusBasic[0]; } else if (unIx == 1u) { // Response-Data: Stat3 Stat2 Stat1 Hdr1 Hdr2 Reg3 Reg2 Reg1 // unIx=0,1,2,3: -----0-----,-----1----,----2----,----3---- // relevant: ^^^^^^^^^ // -> unIx-2 = Hdr2 & Reg3 // jk-orig pTabEntry->pucRx[2] = (uint8)(ulData); // store RX data Stp-3 pTabEntry->pucRxDataByte[2] = (uint8)(unData); // store RX Stp-3 in data 1 - e.g. 'ST_CTRL_RX_CR3' } else if (unIx == 0u) { // Response-Data: Stat3 Stat2 Stat1 Hdr1 Hdr2 Reg3 Reg2 Reg1 // unIx=0,1,2,3: -----0-----,-----1----,----2----,----3---- // relevant: ^^^^^^^^^ // -> unIx-3 = Reg2 Reg1 // jk-orig pTabEntry->pucRx[1] = (uint8)(ulData >> 8); // store RX data Stp-2 // jk-orig pTabEntry->pucRx[0] = (uint8)(ulData); // store RX data Stp-1 pTabEntry->pucRxDataByte[1] = (uint8)(unData >> 8u); // store RX Stp-2 in data 1 - e.g. 'ST_CTRL_RX_CR3' pTabEntry->pucRxDataByte[0] = (uint8)(unData); // store RX Stp-1 in data 1 - e.g. 'ST_CTRL_RX_CR3' } else { // MISRA / QAC - intentionally empty } } // end of 'else if (ucNumOfSteppers_EFT == 3u)' // 'old' HW B2 and older else // ucNumOfSteppers_EFT { // num of HW-Stepper-Chips is not supported } // jk-TI-Daisy-Chain-Handling *#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*# #ifndef UNIT_TEST // NOT Unit-Tests = 'regular' #else // Unit-Tests! if (unIx > 3) // some kind of error - should never happen in real code { unIx = 0; } #endif // note: at first call unData contains dummy data // jk-orig pTabEntry->pucRxDataByte1[unIx] = UTIL_HIBYTE(unData); // store RX data 1 // jk-orig pTabEntry->pucRxDataByte2[unIx] = UTIL_LOBYTE(unData); // store RX data 2 - pucRxDummy - use instead of this: 'uint8* pucStatusBasic = ST_STAT_RX_SRB' // jk: new position (moved some lines UP) ucLoByte_ = pTabEntry->pucCtrlTx[unIx]; // get data for transmission - e.g. 'ST_CTRL_TX_CR3' = '&CddStp8899Com_DataMirror.CtrlTx.aCReg3[0].ucRaw' ucHiByte_ = pTabEntry->ucAddr; // Ctrl-Reg-1 - TRQ_DAC [3:0] | RSVD | SLEW_RATE [1:0] // Ctrl-Reg-2 - DIS_OUT | RSVD | TOFF [1:0] | DECAY [2:0] // Ctrl-Reg-3 - DIR | STEP | SPI_DIR | SPI_STEP | MICROSTEP_MODE [3:0] // Ctrl-Reg-4 - CLR_FLT | LOCK [2:0] | EN_OL | OCP_MODE | OTSD_MODE | TW_REP - e.g. EN_OL: 0x31=0011.0001 | 0x39=0011.1001 // Ctrl-Reg-5 - RSVD [1:0] | STL_LRN | EN_STL | STL_REP | OL_TIME [1:0] | EN_SR_BLANK // Ctrl-Reg-6 - STALL_TH [7:0] // Ctrl-Reg-7 - TRQ_COUNT [7:0] // Ctrl-Reg-8 - RSVD | REV_ID [3:0] // HH5: maybe later // write-request to Ctrl-Reg-1'? // HH5: maybe later if (ucHiByte_ == DRV8899_wCR1_) // TRQ_DAC [3:0] | RSVD | SLEW_RATE [1:0] // HH5: maybe later { // HH5: maybe later static uint8 ucDlyCntr; // HH5: maybe later // check if anything has changed -> do ONLY write on CHANGE // HH5: maybe later if (CddStp8899Com_DataMirror.CtrlTx.aCReg1[0].ucRaw != CddStp8899Com_DataMirror.CtrlRx.aCReg1[0].ucRaw) // HH5: maybe later { // HH5: maybe later // is this the 1st round after change? - do not write this time // HH5: maybe later if (ucDlyCntr < 1u) // HH5: maybe later { // HH5: maybe later ucDlyCntr++; // HH5: maybe later ucHiByte_ = DRV8899_rCR1_; // HH5: maybe later } // HH5: maybe later // else: counter is at least '1' -> do write once again // HH5: maybe later } // HH5: maybe later else // Tx and Rx are the same - no need to write the same content once again // HH5: maybe later { // HH5: maybe later ucDlyCntr = 0; // HH5: maybe later ucHiByte_ = DRV8899_rCR1_; // HH5: maybe later } // HH5: maybe later } // HH5: maybe later // HH5: maybe later // write-request to Ctrl-Reg-2'? // HH5: maybe later if (ucHiByte_ == DRV8899_wCR2_) // DIS_OUT | RSVD | TOFF [1:0] | DECAY [2:0] // HH5: maybe later { // HH5: maybe later // check if anything has changed -> do ONLY write on CHANGE // HH5: maybe later if (CddStp8899Com_DataMirror.CtrlTx.aCReg2[0].ucRaw == CddStp8899Com_DataMirror.CtrlRx.aCReg2[0].ucRaw) // HH5: maybe later { // HH5: maybe later ucHiByte_ = DRV8899_rCR2_; // HH5: maybe later } // HH5: maybe later } // HH5: maybe later // HH5: maybe later // write-request to Ctrl-Reg-3'? // HH5: maybe later if (ucHiByte_ == DRV8899_wCR3_) // DIR | STEP | SPI_DIR | SPI_STEP | MICROSTEP_MODE [3:0] // HH5: maybe later { // HH5: maybe later // check if anything has changed -> do ONLY write on CHANGE // HH5: maybe later if (CddStp8899Com_DataMirror.CtrlTx.aCReg3[0].ucRaw == CddStp8899Com_DataMirror.CtrlRx.aCReg3[0].ucRaw) // HH5: maybe later { // HH5: maybe later ucHiByte_ = DRV8899_rCR3_; // HH5: maybe later } // HH5: maybe later } // HH5: maybe later // HH5: maybe later // write-request to Ctrl-Reg-4 with containing bit 'CLR_FLT'? // HH5: maybe later if (ucHiByte_ == DRV8899_wCR4_) // CLR_FLT | LOCK [2:0] | EN_OL | OCP_MODE | OTSD_MODE | TW_REP - e.g. EN_OL: 0x31=0011.0001 | 0x39=0011.1001 // HH5: maybe later { // HH5: maybe later // usually 'CLR_FLT' in CReg4 is '0' - only on request do WRITE ONCE a '1' // HH5: maybe later boolean bResult = CddStp_Simulation_PreEvalStallDtctn_GetWriteClrFltOnce(); // flag will we resetted internally at once // HH5: maybe later if (bResult == TRUE) // HH5: maybe later { // HH5: maybe later ucLoByte_ |= (uint8)(1u << CDDSTP88xx_BitPos_CLR_FLT); // CLR_FLT // HH5: maybe later } // HH5: maybe later // HH5: maybe later // check if anything has changed -> do ONLY write on CHANGE // HH5: maybe later else // HH5: maybe later { // HH5: maybe later if (CddStp8899Com_DataMirror.CtrlTx.aCReg4[0].ucRaw == CddStp8899Com_DataMirror.CtrlRx.aCReg4[0].ucRaw) // HH5: maybe later { // HH5: maybe later ucHiByte_ = DRV8899_rCR4_; // HH5: maybe later } // HH5: maybe later } // HH5: maybe later } // HH5: maybe later // HH5: maybe later // HH5: maybe later // write-request to Ctrl-Reg-5 with containing bit 'STL_LRN'? // HH5: maybe later if (ucHiByte_ == DRV8899_wCR5_) // RSVD [1:0] | STL_LRN | EN_STL | STL_REP | OL_TIME [1:0] | EN_SR_BLANK // HH5: maybe later { // HH5: maybe later // usually 'STL_LRN' in CReg5 is '0' - only on request do WRITE ONCE '1' // HH5: maybe later boolean bStallLearn = CddStp_Simulation_PreEvalStallDtctn_GetWriteStlLrn(); // do now 'Stall-Learn'? // HH5: maybe later if (bStallLearn == TRUE) // HH5: maybe later { // HH5: maybe later ucLoByte_ |= (uint8)(1u << CDDSTP88xx_BitPos_STL_LRN); // STL_LRN == '0x20' // HH5: maybe later } // HH5: maybe later // HH5: maybe later // well, do NOT write Ctrl5 all the time - at least NOT during 'Stall-Learning' // HH5: maybe later static boolean CddStp8899Com_StlLrn__PrevValues_StlLrn = FALSE; // HH5: maybe later boolean bForceWriting = FALSE; // HH5: maybe later if ((bStallLearn == TRUE) && (bStallLearn != CddStp8899Com_StlLrn__PrevValues_StlLrn)) // changed to '1'? // HH5: maybe later { // HH5: maybe later bForceWriting = TRUE; // keep 'WRITE' (once) // HH5: maybe later } // HH5: maybe later CddStp8899Com_StlLrn__PrevValues_StlLrn = bStallLearn; // HH5: maybe later // HH5: maybe later // Ctrl-Reg-5 - RSVD [1:0] | STL_LRN | EN_STL | STL_REP | OL_TIME [1:0] | EN_SR_BLANK // HH5: maybe later { // HH5: maybe later boolean bHasChanged = FALSE; // HH5: maybe later // HH5: maybe later bHasChanged |= (CddStp8899Com_DataMirror.CtrlTx.aCReg5[0].Bit.u1EN_STL != CddStp8899Com_DataMirror.CtrlRx.aCReg5[0].Bit.u1EN_STL ) ? TRUE : FALSE; // changed? -> DO write // HH5: maybe later bHasChanged |= (CddStp8899Com_DataMirror.CtrlTx.aCReg5[0].Bit.u1STL_REP != CddStp8899Com_DataMirror.CtrlRx.aCReg5[0].Bit.u1STL_REP ) ? TRUE : FALSE; // changed? -> DO write // HH5: maybe later bHasChanged |= (CddStp8899Com_DataMirror.CtrlTx.aCReg5[0].Bit.u2OL_TIME != CddStp8899Com_DataMirror.CtrlRx.aCReg5[0].Bit.u2OL_TIME ) ? TRUE : FALSE; // changed? -> DO write // HH5: maybe later bHasChanged |= (CddStp8899Com_DataMirror.CtrlTx.aCReg5[0].Bit.u1EN_SR_BLANK != CddStp8899Com_DataMirror.CtrlRx.aCReg5[0].Bit.u1EN_SR_BLANK) ? TRUE : FALSE; // changed? -> DO write // HH5: maybe later // HH5: maybe later if ((bForceWriting == TRUE) ? TRUE : FALSE) // HH5: maybe later { // HH5: maybe later // do NOT change to 'read' // HH5: maybe later } // HH5: maybe later else // HH5: maybe later { // HH5: maybe later if ((bHasChanged == FALSE) ? TRUE : FALSE ) // no change? -> no writing! // HH5: maybe later { // HH5: maybe later ucHiByte_ = DRV8899_rCR5_; // change 'write' to 'read' // HH5: maybe later } // HH5: maybe later } // HH5: maybe later } // HH5: maybe later } // HH5: maybe later // HH5: maybe later // HH5: maybe later // (default) read-request to Ctrl-Reg-6? // HH5: maybe later if (ucHiByte_ == DRV8899_rCR6_) // STALL_TH [7:0] // HH5: maybe later { // HH5: maybe later // usually do READ CReg-6 - only on request do WRITE ONCE // HH5: maybe later boolean bResult = CddStp_Simulation_PreEvalStallDtctn_GetWriteCReg6Once(); // flag will we resetted internally at once // HH5: maybe later if (bResult == TRUE) // HH5: maybe later { // HH5: maybe later ucHiByte_ = DRV8899_wCR6_; // this time no reading but once a WRITE // HH5: maybe later ucLoByte_ = CddStp8899Com_PreEvalStallDtctn_ucSTALL_TH; // HH5: maybe later } // HH5: maybe later else // HH5: maybe later { // HH5: maybe later ucLoByte_ = 0; // no writing - just read // HH5: maybe later } // HH5: maybe later } // CddStp8899Com_Debug__OlErrorProblem CddStp8899Com_DEBUG_Check_EnOl_DisOut(); // Important: // // 7.4.2 Disable Mode (nSLEEP = 1, DRVOFF = 1) // The DRVOFF pin is used to enable or disable the half bridges in the device. When the DRVOFF pin is high, the output drivers are disabled in the Hi-Z state. // The DIS_OUT bit can also be used to disable the output drivers. When the DIS_OUT bit is '1', the output drivers are disabled in the Hi-Z state. DIS_OUT is OR'ed with DRVOFF pin. // // 'DRVOFF pin' == 'Rte_Call_ppaclIoHwAbUserSetLwrDrvOff0_IoHwAbUser_SetLwrDrvOff(xy)' == 'IoHwAbUser_SetLwrDrvOff(xy)' == 'IoHwAb_SetDo_0_2(xy)' == 'IoHwAb_SetDo(DioConf_DioChannel_DioChannel_0_2_ST_DRVOFF , xy)' // 'nSleep pin' == 'Rte_Call_ppaclIoHwAbUserSetLwrSleep0_IoHwAbUser_SetLwrSleep(xy)' == 'IoHwAbUser_SetLwrSleep(xy)' == 'IoHwAb_SetDo_0_1(xy)' == 'IoHwAb_SetDo(DioConf_DioChannel_DioChannel_0_1_ST_SLEEP , xy)' // // Only in fct 'CddStp88XX_CtrlFct0' // CddStp_eCtrlFct0_ModeOn: 'RTE_..._SetLwrDrvOff(FALSE) & 'RTE_..._SetLwrSleep(TRUE)' & CddStp88xx__LwrSleepAndDisable = FALSE // CddStp_eCtrlFct0_ModeOff: 'RTE_..._SetLwrDrvOff(TRUE) & 'RTE_..._SetLwrSleep(FALSE)' & CddStp88xx__LwrSleepAndDisable = TRUE // // CTRL2 - DIS_OUT // Write '1' to Hi-Z all outputs. Write '0' to enable all outputs. // OR'ed with DRVOFF pin. // To prevent false OL detection, ensure OL fault detection is disabled // by writing '0' to EN_OL bit, before making the outputs Hi-Z by writing '1' to DIS_OUT. // // The default value of the DIS_OUT bit in CTRL2 register is different in DRV8889A-Q1: '1' // // Used var for handling of bit 'EN_OL': // 'CddStp8899Com_DataMirror.CtrlTx.aCReg4[0].Bit.u1EN_OL' == 'CddStp88XX_aBitsMod[CFG_Stp_IdxVer].Bit.biDisOLDetect' // // // I.e.: // BEFORE set bit 'EN_OL' to '1' (Ctrl-4) // the TI-HW should be 'ENABLED' via 'nSleep'-Pin & 'DrvOff'-Pin & 'DIS_OUT'-Bit // // write-request to Ctrl-Reg-4 with containing bit 'EN_OL' & 'CLR_FLT'? if ( (ucHiByte_ == DRV8899_wCR4_) // CLR_FLT | LOCK [2:0] | EN_OL | OCP_MODE | OTSD_MODE | TW_REP - e.g. EN_OL: 0x31=0011.0001 | 0x39=0011.1001 || (ucHiByte_ == DRV8899_rCR4_)) // new in FLM3: Do NOR write all the time { // HW is switched off -> do NOT enable OL-Detection if (CddStp88xx__LwrSleepAndDisable == TRUE) { ucLoByte_ &= (uint8)~CDDSTP88xx_Mask_EN_OL; // CDDSTP88xx_Mask_EN_OL = 0x08u = 0000.1000 -> 1111.0111 ucHiByte_ = DRV8899_wCR4_; } // usually 'CLR_FLT' in CReg4 is '0' - only on request do WRITE ONCE a '1' e.g. reset 'Stall' or reset 'Fault-Bit' (Error-Debouncing) if (CddStp8899Com_DoClearFaultBit[unIx] == TRUE) { UNTANGLE_INCR(CddStp8899Com_ulDEBUG_DebouncingCtr_ClrFlt_Sent) // this var will never be reset CddStp8899Com_DoClearFaultBit[unIx] = FALSE; // reset at once ucLoByte_ |= (uint8)(1u << CDDSTP88xx_BitPos_CLR_FLT); // reset latched fault (e.g. SPI or OL, ... ucHiByte_ = DRV8899_wCR4_; } } if (ucHiByte_ == DRV8899_wCR1_) // next SPI-TX: Ctrl-Reg-1 with 'TRQ_DAC' { // remember values in order to compare them later with 'RX' if (CddStp8899Com_aucTrqDac_LastTx[unIx] != CddStp8899Com_DataMirror.CtrlTx.aCReg1[unIx].Bit.u4TRQ_DAC) // changed? { CddStp8899Com_aucTrqDac_PrevTx[unIx] = CddStp8899Com_aucTrqDac_LastTx[unIx]; } CddStp8899Com_aucTrqDac_LastTx[unIx] = CddStp8899Com_DataMirror.CtrlTx.aCReg1[unIx].Bit.u4TRQ_DAC; } // check RX-Data for errors via e.g. fct 'CddStp8899Com_CheckSpiComSt0' // N.b. // previously: Check only once after a WHOLE Schedule-Table (ST) was done (8...50 entries & more) // new: Check EACH received data via SPI-TX (void)CddStp8899Com_aucStCheckSpiComFct[0]((uint8)unIx); // '0': currently the one and only 1st entry in list - return (boVerifyOk && !boSpiProblem) // store schedule state for RX notification usage ucSchedStateOld = CddStp8899Com_aucSchedState[unIx]; // check whether a new write CReg0/1&2 for the actual schedule table had been requested // PRQA S 1861, 4542 2 // program architecture and readability - intentionally no modification of existing code - warning - QAC(Prio7) Msg: 1861(The operands of this bitwise operator are of different 'essential signedness' but will generate a result of type 'signed int'.) Depth: 0 Ref: MISRA C:2012 Rule-10.4 | warning - QAC(Prio7) Msg : 4542(A non - negative constant expression of 'essentially signed' type(signed char) is being used as the right - hand operand of this bitwise operator (&).) Depth : 0 Ref : MISRA C : 2012 Rule - 10.1 | warning - QAC(Prio7) Msg : 2214(Body of control statement is on the same line and is not enclosed within braces.) Depth : 0 Ref : MISRA C : 2012 Rule - 15.6 if ( ( CddStp8899Com_aucActSchedTable[unIx] == (uint8)CddStp8899Com_eSt0 ) // CddStp8899Com_eSt0='0' && ((CddStp8899Com_aucStReqOnceMore[unIx] & CDDSTP8899_SpiSt_Bit0) != 0u)) // CDDSTP8899_SpiSt_Bit0='1' { CddStp8899Com_aucStReqOnceMore [unIx] = 0; // delete all bits // CddStp8899Com_aucActSchedTable[unIx] = CddStp8899Com_eSt0; // abort actual work and restart St0 CddStp8899Com_aucSchedState[unIx] = CddStp8899Com_aucStStart[CddStp8899Com_aucActSchedTable[unIx]]; } // jk-tbd else if ( ( CddStp8899Com_aucActSchedTable[unIx] == CddStp8899Com_eSt1 ) // St1 for write CReg3&4&5&6&7? // jk-tbd && ((CddStp8899Com_aucStReqOnceMore[unIx] & CDDSTP8899_SpiSt_Bit1) != 0)) // jk-tbd { // jk-tbd CddStp8899Com_aucStReqOnceMore [unIx] = 0; // delete other bits // jk-tbd // CddStp8899Com_aucActSchedTable[unIx] = CddStp8899Com_eSt1; // abort actual work and restart St1 // jk-tbd CddStp8899Com_aucSchedState[unIx] = CddStp8899Com_aucStStart[CddStp8899Com_aucActSchedTable[unIx]]; // jk-tbd } else // standard { CddStp8899Com_aucStReqOnceMore [unIx] = 0; // delete other bits because of the schedule tables has not been active // switch to next schedule table entry CddStp8899Com_aucSchedState[unIx] = pTabEntry->ucNextEntry; if (CddStp8899Com_aucSchedState[unIx] == 0u) // actual table finished { boolean boSpiCheckResult = FALSE; const uint16 unSpiCheckIdx = CddStp8899Com_aucActSchedTable[unIx]; // mark actual table finished // tbd-jk // check 'tmp_workaround' UtilClearVarBitAtomicU8_(unSpiCheckIdx, &CddStp8899Com_aucStReqSingle[unIx]); /// tbd-jk // tbd-jk // check via e.g. fct 'CddStp8899Com_CheckSpiComSt0' // N.b. // previously: Check only once after a WHOLE Schedule-Table (ST) was done (8...50 entries & more) // new: Check EACH received data via SPI-TX // jk: outdated boSpiCheckResult = CddStp8899Com_aucStCheckSpiComFct[unSpiCheckIdx]((uint8)unIx); // return (boVerifyOk && !boSpiProblem) boSpiCheckResult = TRUE; // i.e.: (boVerifyOk && !boSpiProblem) #ifndef UNIT_TEST // NOT Unit-Tests = 'regular' #else // Unit-Tests! boSpiCheckResult = CddStp_UnitTestHelper_bo1; #endif // PRQA S 3344, 4559 2 // program architecture and readability - intentionally no modification of existing code - warning - QAC(Prio7) Msg: 3344(Controlling expression is not an 'essentially Boolean' expression.) Depth: 0 Ref: MISRA C:2012 Rule-14.4 | warning - QAC(Prio7) Msg: 4559(An expression of 'essentially unsigned' type (unsigned char) is being used as the first operand of this conditional operator (?).) Depth: 0 Ref: MISRA C:2012 Rule-10.1 if (boSpiCheckResult ? TRUE : FALSE) // verify Rx schedule 0/1 write data by comparing with Tx data and Rx schedule 2/3 read data parity check { // store bit mask for RX notification usage - only in case of verify OK CddStp8899Com_aulRxNotification[unIx] |= (((uint32) 1) << ucSchedStateOld); } else { // MISRA } #ifndef UNIT_TEST // NOT Unit-Tests = 'regular' #else // Unit-Tests! if (CddStp_UnitTestHelper_bo1 == TRUE) // no easy way to get this state { CddStp8899Com_aucStReqSingle[unIx] = CDDSTP8899_SpiSt_Bit0; } #endif // check for next schedule table request // PRQA S 1861, 4542 1 // program architecture and readability - intentionally no modification of existing code - warning - QAC(Prio7) Msg: 1861(The operands of this bitwise operator are of different 'essential signedness' but will generate a result of type 'signed int'.) Depth: 0 Ref: MISRA C:2012 Rule-10.4 | warning - QAC(Prio7) Msg : 4542(A non - negative constant expression of 'essentially signed' type(signed char) is being used as the right - hand operand of this bitwise operator (&).) Depth : 0 Ref : MISRA C : 2012 Rule - 10.1 | warning - QAC(Prio7) Msg : 2214(Body of control statement is on the same line and is not enclosed within braces.) Depth : 0 Ref : MISRA C : 2012 Rule - 15.6 if ((CddStp8899Com_aucStReqSingle[unIx] & CDDSTP8899_SpiSt_Bit0) != 0u) // - CddSpi special: CReg1, CReg2 sending in schedule table 0 is cyclic, but this special handling speeds up the sending started by code (tasks, ISRs) -> highest priority (current amplitude) { CddStp8899Com_aucActSchedTable[unIx] = (uint8)CddStp8899Com_eSt0; } // jk-tbd-Cyclic else if ((CddStp8899Com_aucStReqSingle[unIx] & CDDSTP8899_SpiSt_Bit1) != 0) // jk-tbd-Cyclic { // jk-tbd-Cyclic CddStp8899Com_aucActSchedTable[unIx] = CddStp8899Com_eSt1; // jk-tbd-Cyclic } // jk-tbd-Cyclic else if ((CddStp8899Com_aucStReqSingle[unIx] & CDDSTP8899_SpiSt_Bit2) != 0) // jk-tbd-Cyclic { // jk-tbd-Cyclic CddStp8899Com_aucActSchedTable[unIx] = CddStp8899Com_eSt2; // jk-tbd-Cyclic } // jk-tbd-Cyclic else if ((CddStp8899Com_aucStReqSingle[unIx] & CDDSTP8899_SpiSt_Bit3) != 0) // jk-tbd-Cyclic { // jk-tbd-Cyclic CddStp8899Com_aucActSchedTable[unIx] = CddStp8899Com_eSt3; // jk-tbd-Cyclic } else { CddStp8899Com_aucActSchedTable[unIx] = (uint8)CddStp8899Com_eSt0; // default table } CddStp8899Com_aucSchedState[unIx] = CddStp8899Com_aucStStart[CddStp8899Com_aucActSchedTable[unIx]]; } // calculate new pointer because index to schedule table has changed pTabEntry = &CddStp8899Com_SpiSchedTable[CddStp8899Com_aucSchedState[unIx]]; } // old position (moved some line up) ucLoByte_ = pTabEntry->pucCtrlTx[unIx]; // get data for transmission // old position (moved some line up) ucHiByte_ = pTabEntry->ucAddr; ///// __EI(); // call from interrupt level is not possible (no counter)! ///// osEnableGlobal(); // call from interrupt level is not possible (no counter)! //Lr06 ResumeAllInterrupts(); // jk-tbd-HW-02 __RIR(ulDisableIntKey); // PRQA S 4397 1 // program architecture and readability - intentionally no modification of existing code - warning - QAC(Prio7) Msg: 4397(An expression which is the result of a ~ or << operation has not been cast to its essential type.) Depth: 0 Ref: MISRA C:2012 Rule-10.7 CddStp8899Com_aunTxData[unIx] = UTIL_MAKEWORD(ucLoByte_, ucHiByte_); // low=data, high=addr } // end of 'else' // at least ONE HW-Stepper-Chip is available // PRQA S 5310, 5316, 5330, 5336 1 // // program architecture and readability - intentionally no modification of existing code - HIS metrics violation } //----------------------------------------------------------------------------- /// \brief CddStp_GetStpConfigMask /// /// \descr Provides device population footprint to CddSpi /// to handle transmissions with steppers (CddStp) /// /// \param punData: Data pointer to provide footprint // N.b.: '*punData' contains NOT number of devices BUT mask of devices /// 0000.0000 == 0 dvcs /// 0000.0001 == 1 dvcs /// 0000.0011 == 2 dvcs /// 0000.0111 == 3 dvcs /// 0000.1111 == 4 dvcs /// /// \return boolean /// TRUE : Footprint data valid /// FALSE: Footprint data invalid //----------------------------------------------------------------------------- boolean CddStp_GetStpConfigMask(uint16* punData) { uint8 ucNumOfStp = 0; return CddStp_GetStpConfig(punData, &ucNumOfStp); } //----------------------------------------------------------------------------- /// \brief CddStp_GetStpConfigMask /// /// \descr Provides device population footprint to CddSpi /// to handle transmissions with steppers (CddStp) /// /// \param punData: Data pointer to provide footprint // N.b.: '*punData' contains NOT number of devices BUT mask of devices /// 0000.0000 == 0 stepper /// 0000.0001 == 1 stepper /// 0000.0011 == 2 steppers /// 0000.0111 == 3 steppers /// 0000.1111 == 4 steppers /// /// \param pucNumOfStp: Count of steppers // N.b.: HW-Count (EFT-Data) and NOT SW-/Coding-Enabled steppers /// /// \return boolean /// TRUE : Footprint data valid /// FALSE: Footprint data invalid //----------------------------------------------------------------------------- boolean CddStp_GetStpConfig(uint16* punData, uint8* pucNumOfStp) { boolean boRetVal = FALSE; *punData = 0u; *pucNumOfStp = 0u; if (CDDSTP_EftDataValid() != FALSE) // valid 'end of line data' available? { // EFT-Data: EFT_ECUVARCFG_STEPPER_0 ... _2 // 00: not fitted // 01: DRV8899 // 02: DRV8889A for (uint8 ucDevice = 0U; ucDevice < CDDSPI_STP_MAX; ucDevice++) { uint32 ulMask = (CDDSTP_ECUVARCFG_ucDrvType(ucDevice) != 0u) ? 1u : 0u; // any type but '0'? *punData |= (uint16)(ulMask << ucDevice); // shift bit to appropriate position *pucNumOfStp += (ulMask == 0u) ? 0u : 1u; // only add if just anything is present } // if daisy chain configuration, additional element is needed (header) if ((*punData & (uint16)0x00FE) != 0u) // any bit but '0000.0001'? { *punData = (uint16)(*punData << 1u) | 1u; // shift current mask left and add '1' at the right // not here (Daisy-Chain-Header is NO real HW-Stepper): *pucNumOfStp += 1; } boRetVal = TRUE; } return boRetVal; } //----------------------------------------------------------------------------- /// \brief Called before transmission of SPI telegram /// /// \descr The function reads the content of CddStp-DataMirror /// CB-Handling config by .\Asr6\Src\Src_AL\Cust\Bw\Bw16\App\Bsw\Cdd\CddSpi\Cfg\CddSpi_Cfg.h /// SPI-EFT-Handling: 'CddSpi_GetStpConfig' /// /// \param unIx index of stepper (up to SW-A340 = HW-B2: 3 stp) /// /// \return uint32 : Tx data (16 LSB are valid) //----------------------------------------------------------------------------- uint32 CddStp_SpiTx(const uint16 unIx) { uint32 ulResult = 0; if (unIx < CFA_CNT_STP_88XX) { ulResult = CddStp8899Com_SpiTx(unIx); } return ulResult; } //----------------------------------------------------------------------------- /// \brief Called between reception of SPI telegram and /// transmission of next SPI telegram /// /// \descr This function sets raw SPI TX data. /// /// \param uint16 unIx: index to DRV8899 / DRV8889A chip /// /// \return uint16 16 bit raw TX data //----------------------------------------------------------------------------- STATIC_AL uint16 CddStp8899Com_SpiTx(uint16 unIx) { uint16 unRetValue = 0u; // // 1st of all: // Check EFT for num of 'installed' (not just 'coded') steppers // If there is only ONE stepper, NO 'Daisy-Chain'-Handling is used // const uint8 ucNumOfSteppers_EFT = CddStp88XX_GetNumOfSteppers_EFT(); if (ucNumOfSteppers_EFT == 0u) // maybe param yet not loaded { unRetValue = 0u; } // at least ONE HW-Stepper-Chip is available else { // HCM: return CddStp8899Com_aunTxData[unIx]; // low=data, high=addr // // now: // pTabEntry = &CddStp8899Com_SpiSchedTable[CddStp8899Com_aucSchedState[unIx]]; // CddStp8899Com_aunTxData[unIx] = MAKEWORD(pTabEntry->pucCtrlTx[unIx], pTabEntry->ucAddr); // low=data, high=addr static volatile uint16 unData = 0xEFEF; unData = 0; // only ONE HW-Stepper-Chip if (ucNumOfSteppers_EFT == 1u) // no daisy-chain { // the sdi input data word is 16 bits long and consists of the following format: // * 1 read or write bit, w (bit 14) // * 5 address bits, a (bits 13 through 9) // * 8 data bits, d (bits 7 through 0) // the sdo output-data word is 16 bits long and the first 8 bits make up the status register (s1). // the report word (r1) is the content of the register being accessed. // for a write command (w0 = 0), the response word on the sdo pin is the data currently in the register being written to. // for a read command (w0 = 1), the response word is the data currently in the register being read. // // sdi input data word format // b15 b14 b13 b12 b11 b10 b9 b8 b7 b6 b5 b4 b3 b2 b1 b0 // 0 w0 a4 a3 a2 a1 a0 x d7 d6 d5 d4 d3 d2 d1 d0 -> mosi: a1 d1 // // sdo output data word format // b15 b14 b13 b12 b11 b10 b9 b8 b7 b6 b5 b4 b3 b2 b1 b0 // 1 1 uvlo cpuv ocp rsvd tf ol d7 d6 d5 d4 d3 d2 d1 d0 -> miso: s1 r1 // *#*#*#*#*#*#*#*#*# TBD *#*#*#*#*#*#*#*#*# static volatile uint8 ucRegAdr; static volatile uint8 ucData; ucRegAdr = UTIL_HIBYTE(CddStp8899Com_aunTxData[0]); // low=data, high=addr ucData = UTIL_LOBYTE(CddStp8899Com_aunTxData[0]); // low=data, high=addr | idx=0,1,2 -> Reg1,Reg2,Reg3 -> idx-2 = data3 // Debug-Counter if (ucRegAdr == DRV8899_wCR1_) { CddStp8899Com_DEBUG_StlLrn_Cntr[1].ulWrite++; } if (ucRegAdr == DRV8899_rCR1_) { CddStp8899Com_DEBUG_StlLrn_Cntr[1].ulRead++; } if (ucRegAdr == DRV8899_wCR2_) { CddStp8899Com_DEBUG_StlLrn_Cntr[2].ulWrite++; } if (ucRegAdr == DRV8899_rCR2_) { CddStp8899Com_DEBUG_StlLrn_Cntr[2].ulRead++; } if (ucRegAdr == DRV8899_wCR3_) { CddStp8899Com_DEBUG_StlLrn_Cntr[3].ulWrite++; } if (ucRegAdr == DRV8899_rCR3_) { CddStp8899Com_DEBUG_StlLrn_Cntr[3].ulRead++; } if (ucRegAdr == DRV8899_wCR4_) { CddStp8899Com_DEBUG_StlLrn_Cntr[4].ulWrite++; } if (ucRegAdr == DRV8899_rCR4_) { CddStp8899Com_DEBUG_StlLrn_Cntr[4].ulRead++; } if (ucRegAdr == DRV8899_wCR5_) { CddStp8899Com_DEBUG_StlLrn_Cntr[5].ulWrite++; CddStp8899Com_ucDEBUG_StlLrn_Cntr__Cr5LastData = ucData; } if (ucRegAdr == DRV8899_rCR5_) { CddStp8899Com_DEBUG_StlLrn_Cntr[5].ulRead++; } if (ucRegAdr == DRV8899_wCR6_) { CddStp8899Com_DEBUG_StlLrn_Cntr[6].ulWrite++; } if (ucRegAdr == DRV8899_rCR6_) { CddStp8899Com_DEBUG_StlLrn_Cntr[6].ulRead++; } unData = ((uint16)((uint16)ucRegAdr << 8u) | (uint16)ucData); // RegAdrStp DataStp // *#*#*#*#*#*#*#*#*# TBD *#*#*#*#*#*#*#*#*# } // end of 'if (ucNumOfSteppers_EFT == 1u) ...' // 2 HW-Stepper-Chips else if (ucNumOfSteppers_EFT == 2u) // ECU 8.x or initial HW of HongQi-H5 { // 2-Stepper-Handling via Daisy-Chain: // Send-Data: Hdr1 Hdr2 RegAdr2 RegAdr1 Dt2 Dt1 // Hdr1: 1.0.n5...n0 - n=count of daisy-chain-members = '2' -> 0x82 // Hdr2: 1.0.Clr.x.x.x.x.x - Clr='global fault clear'=0 -> 0x80 // // Response-Data: Stat2 Stat1 Hdr1 Hdr2 Reg2 Reg1 // // Req./Tx: // -> word-0: Hdr1 Hdr2 // -> word-1: RegAdr2 RegAdr1 // -> word-2: Dt2 Dt1 // e.g.: 0x82 0x80 0x0C 0x0C 0xE0 0xE0 // // N.b.: // In SPI-Buffer 'mixed': Hdr2 Hdr1 | A1 A2 | D1 D2 // // jk-tbd // do not send/receive until basic settings are done // jk-tbd if (CddStp__DiagReq__bo_EnableSPI == FALSE) // jk-tbd { // jk-tbd return 0u; // jk-tbd } // input: =2,1,0, 2,1,0, 2,1,0, .... // needed: 0,1,2, 0,1,2, ... if (unIx == 2u) { // data: Hdr1 Hdr2 RegAdr2 RegAdr1 Dt2 Dt1 // ......^^^^^^^^^........................ // Hdr1: 1.0.n5...n0 - n=count of daisy-chain-members = '2' // Hdr2: 1.0.Clr.x.x.x.x.x - Clr='global fault clear'=0 -> 0x80 static volatile uint8 ucHdr1 = 0x82; // Header-H1: 1000.0010 = 0x82 static volatile uint8 ucHdr2 = 0x80; // Header-H2: 1000.0000 = 0x80 unData = ((uint16)((uint16)ucHdr1 << 8u) | (uint16)ucHdr2); // Hdr1 Hdr2 //unData = ((uint16)((uint16)ucHdr2 << 8u) | (uint16)ucHdr1); // Hdr1 Hdr2 } else if (unIx == 1u) { // data: Hdr1 Hdr2 RegAdr2 RegAdr1 Dt2 Dt1 // ................^^^^^^^^^^^^^^^........ static volatile uint8 ucRegAdr1; static volatile uint8 ucRegAdr2; /*uint8*/ ucRegAdr1 = UTIL_HIBYTE(CddStp8899Com_aunTxData[0]); // low=data, high=addr /*uint8*/ ucRegAdr2 = UTIL_HIBYTE(CddStp8899Com_aunTxData[1]); // low=data, high=addr unData = ((uint16)((uint16)ucRegAdr2 << 8u) | (uint16)ucRegAdr1); // RegAdrStp2 RegAdrStp1 } else if (unIx == 0u) { // data: Hdr1 Hdr2 RegAdr2 RegAdr1 Dt2 Dt1 // ................................^^^^^^^ static volatile uint8 ucData1; static volatile uint8 ucData2; /*uint8*/ ucData1 = UTIL_LOBYTE(CddStp8899Com_aunTxData[0]); // low=data, high=addr | idx=0,1,2 -> Data1,Data2,Data3 -> idx-0 = data1 /*uint8*/ ucData2 = UTIL_LOBYTE(CddStp8899Com_aunTxData[1]); // low=data, high=addr | idx=0,1,2 -> Data1,Data2,Data3 -> idx-1 = data2 unData = ((uint16)((uint16)ucData2 << 8u) | (uint16)ucData1); // DataStp2 DataStp1 } else { // MISRA / QAC - intentionally empty } } // end of '... else if (ucNumOfSteppers_EFT == 2u) ...' // 3 HW-Stepper-Chips else if (ucNumOfSteppers_EFT == 3u) // 'old' HW B2 and older { // 3-Stepper-Handling via Daisy-Chain: // Send-Data: Hdr1 Hdr2 RegAdr3 RegAdr2 RegAdr1 Dt3 Dt2 Dt1 // Hdr1: 1.0.n5...n0 - n=count of daisy-chain-members = '3' -> 0x83 // Hdr2: 1.0.Clr.x.x.x.x.x - Clr='global fault clear'=0 -> 0x80 // // Response-Data: Stat3 Stat2 Stat1 Hdr1 Hdr2 Reg3 Reg2 Reg1 // // Tx: // -> unIx=0: Hdr1 Hdr2 // -> unIx=1: RegAdr3 RegAdr2 // -> unIx=2: RegAdr1 Dt3 // -> unIx=3: Dt2 Dt1 // // e.g.: 0x83 0x80 0x0C 0x0C 0x0C 0xE0 0xE0 0xE0 // // N.b.: // In SPI-Buffer: Hdr2 Hdr1 | A2 A3 | D3 A1 | D1 D2 // // jk-tbd // do not send/receive until basic settings are done // jk-tbd if (CddStp__DiagReq__bo_EnableSPI == FALSE) // jk-tbd { // jk-tbd return 0u; // jk-tbd } // input: =3,2,1,0, 3,2,1,0, 3,2,1,0, .... // needed: 0,1,2,3, 0,1,2,3, ... if (unIx == 3u) { // data: Hdr1 Hdr2 RegAdr3 RegAdr2 RegAdr1 Dt3 Dt2 Dt1 // Hdr1: 1.0.n5...n0 - n=count of daisy-chain-members = '3' // Hdr2: 1.0.Clr.x.x.x.x.x - Clr='global fault clear'=0 -> 0x80 static volatile uint8 ucHdr1 = 0x83; // Header-H1: 1000.0011 = 0x83 static volatile uint8 ucHdr2 = 0x80; // Header-H2: 1000.0000 = 0x80 unData = ((uint16)((uint16)ucHdr1 << 8u) | (uint16)ucHdr2); // Hdr1 Hdr2 } else if (unIx == 2u) { // data: Hdr1 Hdr2 RegAdr3 RegAdr2 RegAdr1 Dt3 Dt2 Dt1 // jk-orig uint8 ucRegAdr2 = pTabEntry->ucRegAddrMODIFIED; // jk-orig uint8 ucRegAdr3 = pTabEntry->ucRegAddrMODIFIED; static volatile uint8 ucRegAdr2; static volatile uint8 ucRegAdr3; /*uint8*/ ucRegAdr2 = UTIL_HIBYTE(CddStp8899Com_aunTxData[unIx]); // low=data, high=addr /*uint8*/ ucRegAdr3 = UTIL_HIBYTE(CddStp8899Com_aunTxData[unIx]); // low=data, high=addr unData = ((uint16)((uint16)ucRegAdr3 << 8u) | (uint16)ucRegAdr2); // RegAdrStp3 RegAdrStp2 } else if (unIx == 1u) { // data: Hdr1 Hdr2 RegAdr3 RegAdr2 RegAdr1 Dt3 Dt2 Dt1 // jk-orig uint8 ucRegAdr1 = pTabEntry->ucRegAddrMODIFIED; // jk-orig uint8 ucData3 = pTabEntry->pucTx[2]; // idx=0,1,2 -> Reg1,Reg2,Reg3 -> idx-2 = data3 static volatile uint8 ucRegAdr1; static volatile uint8 ucData3 ; /*uint8*/ ucRegAdr1 = UTIL_HIBYTE(CddStp8899Com_aunTxData[unIx]); // low=data, high=addr /*uint8*/ ucData3 = UTIL_LOBYTE(CddStp8899Com_aunTxData[2]); // low=data, high=addr | idx=0,1,2 -> Reg1,Reg2,Reg3 -> idx-2 = data3 unData = ((uint16)((uint16)ucRegAdr1 << 8u) | (uint16)ucData3); // RegAdrStp1 DataStp3 } else if (unIx == 0u) { // data: Hdr1 Hdr2 RegAdr3 RegAdr2 RegAdr1 Dt3 Dt2 Dt1 // jk-orig uint8 ucData1 = pTabEntry->pucTx[0]; // idx=0,1,2 -> Data1,Data2,Data3 -> idx-0 = data1 // jk-orig uint8 ucData2 = pTabEntry->pucTx[1]; // idx=0,1,2 -> Data1,Data2,Data3 -> idx-1 = data2 static volatile uint8 ucData1; static volatile uint8 ucData2; /*uint8*/ ucData1 = UTIL_LOBYTE(CddStp8899Com_aunTxData[0]); // low=data, high=addr | idx=0,1,2 -> Data1,Data2,Data3 -> idx-0 = data1 /*uint8*/ ucData2 = UTIL_LOBYTE(CddStp8899Com_aunTxData[1]); // low=data, high=addr | idx=0,1,2 -> Data1,Data2,Data3 -> idx-1 = data2 unData = ((uint16)((uint16)ucData2 << 8u) | (uint16)ucData1); // DataStp2 DataStp1 } else { // MISRA / QAC - intentionally empty } } // end of '... else if (ucNumOfSteppers_EFT == 3u) ...' else // ucNumOfSteppers_EFT { // num of HW-Stepper-Chips is not supported } // jk-orig if(unIx == (CFA_CNT_STP_88XX - 1u)) // is last instance? (e.g. unIx=2 -> 2 == 4-1=3) // jk-orig { // jk-orig // switch to next schedule table entry for next transmission // jk-orig CddStp88X9_ucSchedIx_Tx = pTabEntry->ucNextEntry; // jk-orig } // get SPI register address and contents of control register for next SPI frame // update parity bit according to control register data unRetValue = unData; // CddStp88X9_ConcatTxData(pTabEntry->unAddr, pTabEntry->punTx[unIx]); } // end of 'if (ucNumOfSteppers_EFT == 0u) ... else ...' return unRetValue; // PRQA S 5310, 5316, 5330, 5336 1 // // program architecture and readability - intentionally no modification of existing code - HIS metrics violation } //----------------------------------------------------------------------------- /// \brief CddStp8899Com_PreEvalStallDtctn /// /// \descr Handle Pre-Evaluation Stall-Detection /// Usually called via 'CddStp88XX_Cycle0' /// /// \param - /// /// \return void //----------------------------------------------------------------------------- void CddStp8899Com_PreEvalStallDtctn(void) { if (CddStp_Simulation_IsSimActive() == TRUE) { tCddStp_Simulation_PreEvalStallDtctn_CtrlReg controlRegisters; CddStp_Simulation_PreEvalStallDtctn_GetControlRegs(&controlRegisters); // CddStp8899Com_DataMirror.CtrlTx.aCReg5->Bit.u1STL_LRN = controlRegisters.bStallDtctn_STL_LRN; // Write '1' to learn stall count for stall detection. This bit automatically returns to '0' when the stall learning process is complete. CddStp8899Com_DataMirror.CtrlTx.aCReg5->Bit.u1STL_REP = controlRegisters.bStallDtctn_STL_REP; // 0b = Stall detection i s not reported on nFAULT | 1b = Stall detection is reported on nFAULT CddStp8899Com_DataMirror.CtrlTx.aCReg5->Bit.u1EN_STL = controlRegisters.bStallDtctn_EN_STL; // 0b = Stall detection is disabled | 1b = Stall detection is enabled // CddStp8899Com_DataMirror.CtrlTx.aCReg6->Bit.u8STALL_TH = controlRegisters.ucStallDtctn_STALL_TH; // 0...255 counts ('DRV8899_wCR6_cr6' / 'DRV8899_rCR6_' / 'CddStp_Simulation_PreEvalStallDtctn_GetWriteCReg6Once()') // currently not used CddStp8899Com_PreEvalStallDtctn_ucSTALL_TH = controlRegisters.ucStallDtctn_STALL_TH; // 0...255 counts ('DRV8899_wCR6_cr6' / 'DRV8899_rCR6_' / 'CddStp_Simulation_PreEvalStallDtctn_GetWriteCReg6Once()') } } // Stall-Detection-DEBUG-Handling typedef struct { boolean bState_EnOl; boolean bState_DisOut; // tbd: CddStp88XX_aBitsMod[CFG_Stp_IdxVer].Bit.biDisOLDetect // tbd: CddStp88XX_HalStp_BitsLwr.Bit.biMotEn uint8 ucSpiOkCounter; tFTimer ftTime; uint8 ucNextEntry; // index of next schedule table entry uint8 ucAddr; // SPI address (combination of low and high nibble) - e.g. 'DRV8899_wCR3_' } tCddStp8899Com_DebugOlErrorProblem; #define cDebugSize 10u static volatile tCddStp8899Com_DebugOlErrorProblem CddStp8899Com_Debug__OlErrorProblem[cDebugSize]; static volatile uint8 CddStp8899Com_Debug__ucIdx = 0; static volatile boolean CddStp8899Com_Debug__bSomeKindOfError = FALSE; //----------------------------------------------------------------------------- /// \brief CddStp8899Com_DEBUG_Check_EnOl_DisOut /// /// \descr /// /// \param - /// /// \return void //----------------------------------------------------------------------------- STATIC_AL void CddStp8899Com_DEBUG_Check_EnOl_DisOut(void) { static volatile boolean CddStp8899Com_Debug__bStateOld_EnOl = FALSE; static volatile boolean CddStp8899Com_Debug__bStateOld_DisOut = FALSE; static volatile uint8 CddStp8899Com_Debug__ucStateOld_SpiOkCounter = 0; // PRQA S 3415 2 // program architecture and readability - intentionally no modification of existing code - warning - QAC(Prio7) Msg: 3415(Right hand operand of '&&' or '||' is an expression with possible side effects.) Depth: 0 Ref: MISRA C:2012 Rule-13.5; REFERENCE - ISO:C90-5,1,2,3 Program Execution if ( (CddStp8899Com_Debug__bStateOld_EnOl != CddStp8899Com_DataMirror.CtrlTx.aCReg4[0].Bit.u1EN_OL) // changed? || (CddStp8899Com_Debug__bStateOld_DisOut != CddStp8899Com_DataMirror.CtrlTx.aCReg2[0].Bit.u1DIS_OUT) // changed? || (CddStp8899Com_Debug__ucStateOld_SpiOkCounter > CddStp8899Com_ucDEBUG_SpiOkCounter) // reset to '0'? ) { CddStp8899Com_Debug__OlErrorProblem[CddStp8899Com_Debug__ucIdx].bState_EnOl = CddStp8899Com_DataMirror.CtrlTx.aCReg4[0].Bit.u1EN_OL; // set via fct 'CddStp88XX_HalStpLwr_SendCReg4' | 'CddStp8899Com_SetCReg4' CddStp8899Com_Debug__OlErrorProblem[CddStp8899Com_Debug__ucIdx].bState_DisOut = CddStp8899Com_DataMirror.CtrlTx.aCReg2[0].Bit.u1DIS_OUT; // requested via fct 'CddStp8899Com_GetCRegRxMotEn' CddStp8899Com_Debug__OlErrorProblem[CddStp8899Com_Debug__ucIdx].ucSpiOkCounter = CddStp8899Com_ucDEBUG_SpiOkCounter; CddStp8899Com_Debug__OlErrorProblem[CddStp8899Com_Debug__ucIdx].ucAddr = CddStp8899Com_SpiSchedTable_XT[CddStp8899Com_aucSchedState[0]].ucAddr; // e.g. 'DRV8899_wCR1_' = 0x06 = 'real'-Adr 3) CddStp8899Com_Debug__OlErrorProblem[CddStp8899Com_Debug__ucIdx].ucNextEntry = CddStp8899Com_SpiSchedTable_XT[CddStp8899Com_aucSchedState[0]].ucNextEntry; // index of next schedule table entry CddStp8899Com_Debug__OlErrorProblem[CddStp8899Com_Debug__ucIdx].ftTime = TimerGetTick(); // PRQA S 400 1 // program architecture and readability - intentionally no modification of existing code - warning - QAC(Prio7) Msg: 400([U] 'CddStp8899Com_Debug__ucIdx' is modified more than once between sequence points - evaluation order unspecified.) Depth: 0 Ref: MISRA C:2012 Rule-1.3, Rule-13.2; REFERENCE - ISO:C90-6.3 Expressions CddStp8899Com_Debug__ucIdx = (CddStp8899Com_Debug__ucIdx + 1u) % cDebugSize; } CddStp8899Com_Debug__bStateOld_EnOl = CddStp8899Com_DataMirror.CtrlTx.aCReg4[0].Bit.u1EN_OL; // depends on 'CddStp88__LwrDisableOlDetection', too CddStp8899Com_Debug__bStateOld_DisOut = CddStp8899Com_DataMirror.CtrlTx.aCReg2[0].Bit.u1DIS_OUT; CddStp8899Com_Debug__ucStateOld_SpiOkCounter = CddStp8899Com_ucDEBUG_SpiOkCounter; if ((CddStp88XX_aeState[0] == CddStp88XX_eStateErr) || (CddStp88XX_aStpState[0].Bit.ErrSpiError == 1u)) // '9' OR SPI-Error reported by Stp-Drv-HW (previously called 'ErrDrvDefect': driver defect error) { CddStp8899Com_Debug__bSomeKindOfError = TRUE; } else { CddStp8899Com_Debug__bSomeKindOfError = FALSE; } } //EOF