//*****************************************************************************
// (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