diff --git a/ptxdist/local_src/common/hw/tle82353sa.cpp b/ptxdist/local_src/common/hw/tle82353sa.cpp index 35720a9..44ba8d9 100644 --- a/ptxdist/local_src/common/hw/tle82353sa.cpp +++ b/ptxdist/local_src/common/hw/tle82353sa.cpp @@ -151,6 +151,19 @@ bool TLE82353SA::readRegister(int hdl, unsigned char adr, unsigned long &value) return bRet; } +bool TLE82353SA::readICVersion(int hdl, unsigned long &value) +{ + bool bRet; + unsigned long regvalue; + + bRet = readRegister(hdl, REGISTER_ICVID, regvalue); + if (bRet) + { + value = TLE82353SA_GET_IC_VERSION(regvalue); + } + return bRet; +} + bool TLE82353SA::initTLE( int hdl, unsigned long clkDividervalue, bool includeClkDivider, bool resetDiagRegister ) { diff --git a/ptxdist/local_src/common/hw/tle82353sa.h b/ptxdist/local_src/common/hw/tle82353sa.h index 4b0ea77..1da9929 100644 --- a/ptxdist/local_src/common/hw/tle82353sa.h +++ b/ptxdist/local_src/common/hw/tle82353sa.h @@ -59,6 +59,10 @@ TLE82353SA */ #define TLE82353SA_MASKED_RESET_VALUE 0x00C10000 #define TLE82353SA_IC_VERSION_MASK 0x0000FF00 +#define TLE82353SA_IC_VERSION_SHIFT (8) + +#define TLE82353SA_GET_IC_VERSION(regval) \ + (((regval) & TLE82353SA_IC_VERSION_MASK) >> TLE82353SA_IC_VERSION_SHIFT) #define TLE82353SA_RESET_VALUE_OK(regval) \ (((regval) & ~TLE82353SA_IC_VERSION_MASK) == TLE82353SA_MASKED_RESET_VALUE) @@ -123,6 +127,14 @@ public: static bool readRegister( int hdl, unsigned char adr, unsigned long &value ); /** + * @brief readICVersion get IC version (see TLE82453 Data Sheet (Rev 1.0, 2015-03-27), page 53) from hardware + * @param hdl ready opened filehandle to SPIDEV file + * @param value Reference to where the result should be stored + * @return true on sucess + */ + static bool readICVersion( int hdl, unsigned long &value ); + + /** * @brief initTLE initialize the tle * @param hdl ready opened filehandle to SPIDEV file * @return true on success diff --git a/ptxdist/local_src/ecu-control/ecutle.cpp b/ptxdist/local_src/ecu-control/ecutle.cpp index 814af70..c8d192e 100644 --- a/ptxdist/local_src/ecu-control/ecutle.cpp +++ b/ptxdist/local_src/ecu-control/ecutle.cpp @@ -43,6 +43,121 @@ /* here: Defines */ /*****************************************************************************/ +#define WORKAROUND_TLE82353SA_C11_FUNCTION_CHANGE 1 + +/*****************************************************************************/ +/* here: Utility functions */ +/*****************************************************************************/ + +static +bool fixUpTLEReg(int tle_fd, unsigned long adr, unsigned long& value) +{ +#if WORKAROUND_TLE82353SA_C11_FUNCTION_CHANGE +/* + * Workaround for a functional change in the TLE82353SA between chip version + * B13 and chip version C11. + * + * In version C11 the "Current FB" value (bits 23:12) of registers 0x40, 0x41 + * and 0x41 needs to be multiplied by factor 2 compared to the older chip + * version B13. + * + * Fortunately the chip version can be extracted (at the cost of extra SPI bus + * traffic, if not cached "somewhere") and used to distinguish between both + * versions. + * + * ** Test sequence: + * -- snip -- + * # activate hardware safety (must run (="toggle") in the background + * # during the whole test!) + * ecu-control --safety wdt 800000 & + * # enable TLE + * ecu-control --io wdo 46 0 + * # enable power + * ecu-control --io wao 1 800 + * + * # after that it should be possible to read the power value back via + * ecu-control --tle read 0x40 + * -- snip -- + * + * Expected value should be around "0x0018c0f8". + * + */ + bool retval = false; + unsigned long tle_version = 0xDEADBEEF; + + switch(adr) + { + case 0x40: + case 0x41: + case 0x42: + if (!TLE82353SA::readICVersion(tle_fd, tle_version)) + { + (void)fprintf(stderr, "WARNING: EcuTle::readRegister: could not read TLE version, ucAdr=%x\n", (int)adr); + return false; + } + + switch(tle_version) + { + case 4: /* B13 step = 00000100 */ + retval = true; + break; + case 6: /* C11 step = 00000110 */ + { +#define TLE_CURRENT_FB_MASK (0x00FFF000UL) +#define TLE_CURRENT_FB_SHIFT (12) + unsigned long tmpval; + /* + * fetch bits 12-23 (counting from 0) for "Current FB" and + * move them to the lower bits... + */ + tmpval = (value & TLE_CURRENT_FB_MASK) >> TLE_CURRENT_FB_SHIFT; + + /* + * ... then multiply the value by 2 (and complain if + * the result gets too large to fit into 12 bits; + * pow(2,12)-1==0xFFF) ... + */ + tmpval *= 2; + if (tmpval > 0xFFF) + { + (void)fprintf(stderr, "fixUpTLEReg: value cutoff at 0xFFF %lx\n", tmpval); + tmpval = 0xFFF; + retval = false; + } + else + { + retval = true; + } + + /* + * ... and then shift the bits back into their place and into + * the value we wish to return. + */ + value &= ~TLE_CURRENT_FB_MASK; + value |= (tmpval << TLE_CURRENT_FB_SHIFT) & TLE_CURRENT_FB_MASK; + } + break; + default: + (void)fprintf(stderr, "EcuTle::readRegister: unknown TLE version %lx, no fixup done, ucAdr=%x, value=%lx\n", + tle_version, + (int)adr, + (unsigned long)value); + retval = false; + break; + } + break; + default: + retval = true; + break; + } + + return retval; +#else + return true; +#endif /* WORKAROUND_TLE82353SA_C11_FUNCTION_CHANGE */ +} + + /*****************************************************************************/ /* here: Classes */ /*****************************************************************************/ @@ -97,7 +212,10 @@ int EcuTle::execute_special(int iChannel, unsigned long& ulValue) /* initialized before */ ok = TLE82353SA::readRegister( fd, ucCmd, ulValue); if( ok ){ - iRet = RETCODE_OK; + if (fixUpTLEReg(fd, ucCmd, ulValue)) + iRet = RETCODE_OK; + else + iRet = RETCODE_FAIL; } else{ iRet = RETCODE_FAIL; @@ -223,7 +341,10 @@ int EcuTle::readRegister(const ECuParameter ¶meters, unsigned long& value) unsigned char ucAdr = (unsigned char)adr; ok = TLE82353SA::readRegister( fd, ucAdr, value); if( ok ){ - iRet = RETCODE_OK; + if (fixUpTLEReg(fd, ucAdr, value)) + iRet = RETCODE_OK; + else + iRet = RETCODE_FAIL; } else{ iRet = RETCODE_FAIL;