//***************************************************************************** // (C) Automotive Lighting China // // 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 China. //***************************************************************************** // ---------------------------------------------------------------------------- /// \file Protocol_Flexwire.c /// /// \author f24301c [mailto:walker.lv@marelli.com] /// /// \date 06.21.2024 /// /// \brief FlexWire protocol implementation /// // ---------------------------------------------------------------------------- /****************************************************************************** ** Includes ** ******************************************************************************/ #include "Protocol_Flexwire.h" #include #include #include #include "../Cfg/CddTps929x_PBcfg.h" #include "../Cfg/CddTps929x_Protocol_PBcfg.h" #include "../Common/Tps929xType.h" #include /******************************************************************************* ** Private Macro Definitions ** *******************************************************************************/ #if (UUE_TRANSACTION_PROFILE == STD_ON) #define CONSTRUCT_TCB(channel, address, primitive) \ { \ channel, \ address, \ (uint8)primitive, \ FALSE, \ 0, \ UUE_TRANSACTION_RETRY_THRESHOLD, \ UUE_TRANSACTION_DELAY, \ UUE_TRANSACTION_TIMEOUT, \ TransactionError_NoError, \ TransactionState_RequestReady, \ 0, 0, 0, 0 \ } #else #define CONSTRUCT_TCB(channel, address, primitive) \ { \ channel, \ address, \ primitive, \ FALSE, \ 0, \ UUE_TRANSACTION_RETRY_THRESHOLD, \ UUE_TRANSACTION_DELAY, \ UUE_TRANSACTION_TIMEOUT, \ TransactionError_NoError, \ TransactionState_RequestReady, \ } #endif // (UUE_TRANSACTION_PROFILE == STD_ON) /******************************************************************************* ** Private Variable Declarations ** *******************************************************************************/ static const uint8 flexWire_Tps929_crcArray[256] = { 0x00u,0x5eu,0xbcu,0xe2u,0x61u,0x3fu,0xddu,0x83u,0xc2u,0x9cu,0x7eu,0x20u,0xa3u,0xfdu,0x1fu,0x41u, 0x9du,0xc3u,0x21u,0x7fu,0xfcu,0xa2u,0x40u,0x1eu,0x5fu,0x01u,0xe3u,0xbdu,0x3eu,0x60u,0x82u,0xdcu, 0x23u,0x7du,0x9fu,0xc1u,0x42u,0x1cu,0xfeu,0xa0u,0xe1u,0xbfu,0x5du,0x03u,0x80u,0xdeu,0x3cu,0x62u, 0xbeu,0xe0u,0x02u,0x5cu,0xdfu,0x81u,0x63u,0x3du,0x7cu,0x22u,0xc0u,0x9eu,0x1du,0x43u,0xa1u,0xffu, 0x46u,0x18u,0xfau,0xa4u,0x27u,0x79u,0x9bu,0xc5u,0x84u,0xdau,0x38u,0x66u,0xe5u,0xbbu,0x59u,0x07u, 0xdbu,0x85u,0x67u,0x39u,0xbau,0xe4u,0x06u,0x58u,0x19u,0x47u,0xa5u,0xfbu,0x78u,0x26u,0xc4u,0x9au, 0x65u,0x3bu,0xd9u,0x87u,0x04u,0x5au,0xb8u,0xe6u,0xa7u,0xf9u,0x1bu,0x45u,0xc6u,0x98u,0x7au,0x24u, 0xf8u,0xa6u,0x44u,0x1au,0x99u,0xc7u,0x25u,0x7bu,0x3au,0x64u,0x86u,0xd8u,0x5bu,0x05u,0xe7u,0xb9u, 0x8cu,0xd2u,0x30u,0x6eu,0xedu,0xb3u,0x51u,0x0fu,0x4eu,0x10u,0xf2u,0xacu,0x2fu,0x71u,0x93u,0xcdu, 0x11u,0x4fu,0xadu,0xf3u,0x70u,0x2eu,0xccu,0x92u,0xd3u,0x8du,0x6fu,0x31u,0xb2u,0xecu,0x0eu,0x50u, 0xafu,0xf1u,0x13u,0x4du,0xceu,0x90u,0x72u,0x2cu,0x6du,0x33u,0xd1u,0x8fu,0x0cu,0x52u,0xb0u,0xeeu, 0x32u,0x6cu,0x8eu,0xd0u,0x53u,0x0du,0xefu,0xb1u,0xf0u,0xaeu,0x4cu,0x12u,0x91u,0xcfu,0x2du,0x73u, 0xcau,0x94u,0x76u,0x28u,0xabu,0xf5u,0x17u,0x49u,0x08u,0x56u,0xb4u,0xeau,0x69u,0x37u,0xd5u,0x8bu, 0x57u,0x09u,0xebu,0xb5u,0x36u,0x68u,0x8au,0xd4u,0x95u,0xcbu,0x29u,0x77u,0xf4u,0xaau,0x48u,0x16u, 0xe9u,0xb7u,0x55u,0x0bu,0x88u,0xd6u,0x34u,0x6au,0x2bu,0x75u,0x97u,0xc9u,0x4au,0x14u,0xf6u,0xa8u, 0x74u,0x2au,0xc8u,0x96u,0x15u,0x4bu,0xa9u,0xf7u,0xb6u,0xe8u,0x0au,0x54u,0xd7u,0x89u,0x6bu,0x35u }; /******************************************************************************* ** Public Variable Declarations ** *******************************************************************************/ /******************************************************************************* ** Private Function Declarations ** *******************************************************************************/ static void flexwireTransactionCallback(ProtocolBuf_t* pThis); /******************************************************************************* ** Public Function Declarations ** *******************************************************************************/ //----------------------------------------------------------------------------- /// \brief Crc8 calculation per Tps929240 spec /// /// \descr serialize primitive into a ProtocolBuf_t which in turn enqueue into /// one of uartEng channel /// /// \param stream: data to be calculated. /// len: len of data to be calculated /// /// \return crc8 result //----------------------------------------------------------------------------- uint8 FlexWire_Tps929240_CRC(uint8* stream, uint8 len) { uint8 k; uint8 remainder; uint8 tempData; remainder = 0xFF; // CRC initial value for (k = 0; k < len; k++) { tempData = remainder ^ stream[k]; remainder = flexWire_Tps929_crcArray[tempData]; } // we have to reverse the final remainder to get the CRC value, for example, // if final remainder = 0010 1100, we need to reverse it to 0011 0100 remainder = ((remainder & 0x80) >> 7) + ((remainder & 0x40) >> 5) + ((remainder & 0x20) >> 3) + ((remainder & 0x10) >> 1) + ((remainder & 0x08) << 1) + ((remainder & 0x04) << 3) + ((remainder & 0x02) << 5) + ((remainder & 0x01) << 7); return remainder; } //----------------------------------------------------------------------------- /// \brief fetch global pdu response buffer and associated description /// /// \descr locate global pdu response buffer by uart channel and device address /// if founded /// /// \param channel: uartEng channel index to carry payload /// address: register to access /// primitive: primitive of response buffer /// response: description of the response buffer, out parameter, could be NULL /// /// \return device object index within device_Tps929240_Instances[]. return 0xFF if not /// found /// //----------------------------------------------------------------------------- uint8 FlexWire_GetGlobalResponse(uint8 channel, uint8 address, PrimitiveResponseBuf_Tps929x_t** response) { uint8 found = FALSE; uint8 idx; for (idx = 0; idx < device_Tps929240_number; idx++) { const DeviceCfg_Tps929x_t* const deviceInfo = device_Tps929240_Instances[idx].config; if ((deviceInfo->address == address) && (deviceInfo->channel == channel)) { if (response) { *response = device_Tps929240_Instances[idx].primitiveResp; } else { // only get idx } found = TRUE; break; } } if (!found) { idx = 0xff; } return idx; } //----------------------------------------------------------------------------- /// \brief callback function when transaction is done /// /// \descr pdu response buffer point to device global response buffer. update /// primitive response state, dirty flag from pdu->tcb /// the callback is invoked from ISR context, so do not run heavy load /// task. pdu is allocated in CddUartEng.channel.queue, would be invalid /// after the callback. so this is the only window to access pdu. /// /// \param pdu :pointer to a instance of ProtocolBuf_t, which contains /// everything needed to handle pdu /// /// \return none //----------------------------------------------------------------------------- static void flexwireTransactionCallback(ProtocolBuf_t* pdu) { UUE_ASSERT(pdu != (ProtocolBuf_t*)NULL_PTR); TransactionControl_t* tcb = &pdu->tcb; UUE_ASSERT(tcb->transactionState == TransactionState_ResponseReady); if (tcb->transactionState == TransactionState_ResponseReady) { if (tcb->broadcasting) { // ignore transaction error in case of broadcasting // RATIONALE: a broadcasting request has no response. if any bus error existing during // broadcasting, it will also be detected by non-broadcasting request. if // not a bus error, there would be no way to identify which slave goes wrong, // and also no way to confirm slave accepts or reject request. } else { // none broadcasting transaction PrimitiveResponseBuf_Tps929x_t* response = (PrimitiveResponseBuf_Tps929x_t*)NULL_PTR; if (FlexWire_GetGlobalResponse(tcb->channel, tcb->address, &response) != 0xFF) { // copy only important stuff only, the rest would be handle in Tps929 period runnable response->primitiveRespDesc[tcb->primitive].transactionErr = tcb->errorState; response->primitiveRespDesc[tcb->primitive].dirtyFlag = TRUE; // marks response need to be process // DO NOT check crc in ISR } else { UUE_ASSERT(0); // configuration error // just ignore this when assert disabled } } } else { UUE_ASSERT(0); // transaction state incorrect, do nothing } } //----------------------------------------------------------------------------- /// \brief create a protocol PDU from inputs /// /// \descr serialize primitive into a ProtocolBuf_t which in turn enqueue into /// one of uartEng channel /// /// \param channel: uartEng channel index to carry payload /// address: register to access /// broadcasting: broadcasting mode or end2end communication /// primitive: primitive to be execute /// request: primitive specified data to be send /// requestLen: size of request /// /// \return none //----------------------------------------------------------------------------- #pragma warning 589 // W589: pointer assumed to be nonzero - test removed UUE_ErrorType FlexWire_Ser(uint8 channel, uint8 address, uint8 broadcasting, Primitive_Tps929x_t primitive, uint8* request, uint8 requestLen) { UUE_ErrorType retVal = E_UUE_NO_ERROR; if ((address >= TPS929240_MAX_DEVICE_PER_CHANNEL) || (channel >= UUE_MAX_UART_CHANNEL) || (primitive >= Prim_Tps929x_NUMBER) || (requestLen > 24)) { retVal = E_UUE_BAD_PARAMETER; } else { //if (channel != 4) return retVal; // construct a general ProtocolBuf_t pdu, only tcb part ProtocolBuf_t pdu = { CONSTRUCT_TCB(channel, address, primitive), }; pdu.tcb.broadcasting = broadcasting; // setup request buffer and len uint8* requestBuf = pdu.reqPduBuffer; // clear buffer? requestBuf[0] = FLEXWIRE_SYNC; // byte 0: sync requestBuf[1] = (flexWireCfg[primitive].readWrite) | // byte 1: control (broadcasting ? FLEXWIRE_BROADCASTING : FLEXWIRE_NON_BROADCASTING) | (flexWireCfg[primitive].protocolDataLen) | ((uint8)(address & 0x0f)); requestBuf[2] = flexWireCfg[primitive].regAddr; // byte 2: register start address // pdu payload assembling if (request && requestLen) { UUE_ASSERT(flexWireCfg[primitive].readWrite == FLEXWIRE_WRITE_MODE); memcpy(&requestBuf[3], request, requestLen); } // update Crc in last byte // last byte, Crc requestBuf[flexWireCfg[primitive].requestLen - 1] = FlexWire_Tps929240_CRC(&requestBuf[1], flexWireCfg[primitive].requestLen - 2); pdu.reqPduLength = flexWireCfg[primitive].requestLen; //setup response buffer if necessary (non-broadcasting) if (broadcasting) { pdu.resPduBuffer = (uint8*)NULL_PTR; pdu.resPduLength = 0; } else { PrimitiveResponseBuf_Tps929x_t* response = (PrimitiveResponseBuf_Tps929x_t*)NULL_PTR; if (FlexWire_GetGlobalResponse(channel, address, &response) != 0xFF) { pdu.resPduLength = TPS929X_GET_PRIMITIVE_RESPBUFLEN(response, primitive); pdu.resPduBuffer = TPS929X_GET_PRIMITIVE_RESPBUF(response, primitive); UUE_ASSERT(pdu.resPduBuffer != 0); } else { retVal = E_UUE_TPS929_RESPBUFF_NOT_FOUND; } } if (retVal == E_UUE_NO_ERROR) { // setup transaction callback pdu.transactionNotifyCallback = flexwireTransactionCallback; // all set and check, good to go retVal = CddUartEng_AddPud(&pdu); } else { // return previous error code } } return retVal; } #pragma warning restore //----------------------------------------------------------------------------- /// \brief second version of FlexWire_Ser /// /// \descr a wrapper of FlexWire_Ser, support common register read write /// /// \param channel: uartEng channel index to carry payload /// address: register to access /// regAddr: which register to be access /// broadcasting: broadcasting mode or end2end communication /// primitive: primitive to be execute /// request: primitive specified data to be send /// requestLen: size of request /// /// \return none //----------------------------------------------------------------------------- UUE_ErrorType FlexWire_Ser2(uint8 channel, uint8 address, uint8 regAddr, uint8 broadcasting, Primitive_Tps929x_t primitive, uint8* request, uint8 requestLen) { UUE_ErrorType retVal = E_UUE_NO_ERROR; if (primitive >= Prim_Tps929x_NUMBER) { retVal = E_UUE_BAD_PARAMETER; } else { // NOTENOTE: it is not a good implementation. update regAddr of flexWireCfg primitive // change every device's behavior, it is ok but not a good idea. flexWireCfg[primitive].regAddr = regAddr; retVal = FlexWire_Ser(channel, address, broadcasting, primitive, request, requestLen); } return retVal; }