#include "LinCP.h" #include "cmsis_os.h" #define LIN_SYNC_BYTE (0x55) #define PID_MAX (0x3F) //63 (6 bit ID: 0 ~ 63) static u8 LIN_PID_TABLE[PID_MAX + 1]; #define LINCP_COMM_TIMEOUT (300) //ms 100 #define LINCP_COMM_CHECK_PERIOD (5) //ms typedef union _LIN_ID_Field { u8 value; struct { u8 b0:1; u8 b1:1; u8 b2:1; u8 b3:1; u8 b4:1; u8 b5:1; u8 p0:1; u8 p1:1; }; } __attribute__((__packed__)) LIN_ID_Field, *PLIN_ID_Field; void LIN_CreatePidTable(void) { LIN_ID_Field x; for (u8 i = 0; i <= PID_MAX; i++) { x.value = i; x.p0 = (x.b0 ^ x.b1 ^ x.b2 ^ x.b4); x.p1 = (x.b1 ^ x.b3 ^ x.b4 ^ x.b5) ^ 1; LIN_PID_TABLE[i] = x.value; #ifdef DEBUG_LIN_CP XP("PID[%02d] %02X "BYTE_TO_BINARY_PATTERN" %s", i, LIN_PID_TABLE[i], BYTE_TO_BINARY(LIN_PID_TABLE[i]), (i % 4 == 3 ? "\r\n" : "")); #endif } } u8 LIN_CalcCheckSum(u8 id, u8 *data, u8 len) { #ifdef LIN_VER_2X u32 Sum = LIN_PID_TABLE[id]; #else u32 Sum = 0; #endif for (int i = 0; i < len; i++) { Sum += data[i]; if (0xFF < Sum) { Sum = (Sum & 0xFF) + 1; } } return (u8)(~Sum & 0xFF); } void LIN_FlowTx(PLinCP p, HTK_BOOL bTx, HTK_BOOL bRx) { if (p == NULL) return; if (bTx == HTK_TRUE && bRx == HTK_TRUE) bRx = HTK_FALSE; if (bTx) { //Disable RX p->m_bRx = HTK_FALSE; LL_USART_DisableIT_RXNE(p->m_USART); LL_USART_DisableIT_LBD(p->m_USART); LL_USART_DisableIT_ERROR(p->m_USART); p->m_RxLen = 0; //Enable TX LL_USART_DisableDirectionRx(p->m_USART); LL_USART_EnableIT_TXE(p->m_USART); p->m_bTx = HTK_TRUE; } else //Rx { p->m_bTx = HTK_FALSE; //Disable TX LL_USART_DisableIT_TXE(p->m_USART); LL_USART_EnableDirectionRx(p->m_USART); if (!bRx) { //Disable RX p->m_bRx = HTK_FALSE; LL_USART_DisableIT_RXNE(p->m_USART); LL_USART_DisableIT_LBD(p->m_USART); LL_USART_DisableIT_ERROR(p->m_USART); } else { //Enable RX LL_USART_EnableIT_RXNE(p->m_USART); LL_USART_EnableIT_LBD(p->m_USART); LL_USART_EnableIT_ERROR(p->m_USART); p->m_bRx = HTK_TRUE; } p->m_RxLen = 0; } //#ifdef DEBUG_LIN_CP // XP("\r\n", bTx ? "TX" : "RX", p->m_bTx, p->m_bRx); //#endif } //void LIN_SetTx(PLinCP p, HTK_BOOL bEnable) //{ // if (bEnable) // { // LL_USART_DisableDirectionRx(p->m_USART); // LL_USART_EnableIT_TXE(p->m_USART); // } // else // { // LL_USART_DisableIT_TXE(p->m_USART); // LL_USART_EnableDirectionRx(p->m_USART); // } //} //void LIN_SetRx(PLinCP p, HTK_BOOL bEnable) //{ // if (bEnable) // { // LL_USART_EnableIT_RXNE(p->m_USART); // LL_USART_EnableIT_LBD(p->m_USART); // LL_USART_EnableIT_ERROR(p->m_USART); // } // else // { // LL_USART_DisableIT_RXNE(p->m_USART); // LL_USART_DisableIT_LBD(p->m_USART); // LL_USART_DisableIT_ERROR(p->m_USART); // } //} void LIN_Init(PLinCP p, USART_TypeDef* usart) { if (p == NULL) return; LIN_CreatePidTable(); p->m_USART = usart; #ifdef FUNC_LIN_MASTER LIN_FlowTx(p, HTK_FALSE, HTK_FALSE); #else #endif } HTK_BOOL LIN_TxHeader(PLinCP p, u8 id) { if (p == NULL) return HTK_FALSE; //osDelay(10); memset(p->m_TxBuf, 0, sizeof(p->m_TxBuf)); memset(p->m_RxBuf, 0, sizeof(p->m_RxBuf)); p->m_TxBuf[0] = LIN_SYNC_BYTE; p->m_TxBuf[1] = LIN_PID_TABLE[id]; p->m_TxIdx = 0; p->m_TxLen = 2; LIN_FlowTx(p, HTK_TRUE, HTK_FALSE); #ifdef DEBUG_LIN_CP XP("LIN-TX(H): PID(%02X) ID(%02X)\r\n", p->m_TxBuf[1], id); #endif u32 BegTick = HAL_GetTick(); do { osDelay(LINCP_COMM_CHECK_PERIOD); if (HTK_IsTimeout(BegTick, LINCP_COMM_TIMEOUT)) { p->m_bTxTimeout = HTK_TRUE; p->m_nTxNG++; #ifdef DEBUG_LIN_CP XP("LIN-TX(H): PID(%02X) ID(%02X) ... TxTimeout(%d)!\r\n", p->m_TxBuf[1], id, p->m_nTxNG); #endif return HTK_FALSE; } } while(p->m_TxLen != 0); p->m_bTxTimeout = HTK_FALSE; p->m_nTxOK++; int DataIndex = 1; //0: 0xF0 BegTick = HAL_GetTick(); do { osDelay(LINCP_COMM_CHECK_PERIOD); if (p->m_RxLen == 10 && p->m_RxBuf[0] == 0xF0) { DataIndex = 1; break; } else if (p->m_RxLen == 9 && p->m_RxBuf[0] != 0xF0) { DataIndex = 0; break; } if (HTK_IsTimeout(BegTick, LINCP_COMM_TIMEOUT)) { p->m_bRxTimeout = HTK_TRUE; p->m_nRxNG++; #ifdef DEBUG_LIN_CP XP("LIN-TX(H): PID(%02X) ID(%02X) ... RxTimeout(%d)! (RxLen = %d)\r\n", p->m_TxBuf[1], id, p->m_nRxNG, p->m_RxLen); XP("[0]%02X [1]%02X [2]%02X [3]%02X [4]%02X [5]%02X [6]%02X [7]%02X [8]%02X [9]%02X [10]%02X Len = %d\r\n", p->m_RxBuf[0], p->m_RxBuf[1], p->m_RxBuf[2], p->m_RxBuf[3], p->m_RxBuf[4], p->m_RxBuf[5], p->m_RxBuf[6], p->m_RxBuf[7], p->m_RxBuf[8], p->m_RxBuf[9], p->m_RxBuf[10], p->m_RxLen); #endif return HTK_FALSE; } } while (1); //while (p->m_RxLen != 10); p->m_bRxTimeout = HTK_FALSE; p->m_nRxOK++; LIN_FlowTx(p, HTK_FALSE, HTK_FALSE); if (!p->m_bTxTimeout && !p->m_bRxTimeout) { HTK_BOOL bChecksum = (LIN_CalcCheckSum(id, &p->m_RxBuf[DataIndex], 8) == p->m_RxBuf[DataIndex + 8]); #ifdef DEBUG_LIN_CP XP("LIN-RX(D): PID(%02X) ID(%02X) {%02X, %02X, %02X, %02X, %02X, %02X, %02X, %02X} [%02X%s] <%d, %d>\r\n", p->m_TxBuf[1], id, p->m_RxBuf[DataIndex + 0], p->m_RxBuf[DataIndex + 1], p->m_RxBuf[DataIndex + 2], p->m_RxBuf[DataIndex + 3], p->m_RxBuf[DataIndex + 4], p->m_RxBuf[DataIndex + 5], p->m_RxBuf[DataIndex + 6], p->m_RxBuf[DataIndex + 7], p->m_RxBuf[DataIndex + 8], (bChecksum ? "" : " [NG]"), p->m_nTxOK, p->m_nRxOK); #endif return bChecksum; } else { return HTK_FALSE; } } HTK_BOOL LIN_TxHeaderData(PLinCP p, u8 id, void* Data, u8 DataLen) { if (p == NULL) return HTK_FALSE; //osDelay(10); memset(p->m_TxBuf, 0, sizeof(p->m_TxBuf)); memset(p->m_RxBuf, 0, sizeof(p->m_RxBuf)); p->m_TxBuf[0] = LIN_SYNC_BYTE; p->m_TxBuf[1] = LIN_PID_TABLE[id]; DataLen = HTK_GET_VAL_MIN(DataLen, 8); memcpy(&p->m_TxBuf[2], Data, DataLen); p->m_TxBuf[2 + DataLen] = LIN_CalcCheckSum(id, &p->m_TxBuf[2], DataLen); p->m_TxIdx = 0; p->m_TxLen = 2 + DataLen + 1; LIN_FlowTx(p, HTK_TRUE, HTK_FALSE); u32 BegTick = HAL_GetTick(); do { osDelay(LINCP_COMM_CHECK_PERIOD); if (HTK_IsTimeout(BegTick, LINCP_COMM_TIMEOUT)) { p->m_bTxTimeout = HTK_TRUE; p->m_nTxNG++; #ifdef DEBUG_LIN_CP XP("LIN-TX(A): PID(%02X) ID(%02X) ... TxTimeout(%d)!\r\n", p->m_TxBuf[1], id, p->m_nTxNG); #endif return HTK_FALSE; } } while(p->m_TxLen != 0); p->m_bTxTimeout = HTK_FALSE; p->m_nTxOK++; #ifdef DEBUG_LIN_CP XP("LIN-TX(A): PID(%02X) ID(%02X) {%02X, %02X, %02X, %02X, %02X, %02X, %02X, %02X} [%02X] <%d, %d>\r\n", p->m_TxBuf[1], id, p->m_TxBuf[2], p->m_TxBuf[3], p->m_TxBuf[4], p->m_TxBuf[5], p->m_TxBuf[6], p->m_TxBuf[7], p->m_TxBuf[8], p->m_TxBuf[9], p->m_TxBuf[10], p->m_nTxOK, p->m_nRxOK); #endif return HTK_TRUE; } void LIN_Display(PLinCP p) { if (p == NULL) return; XP("-----------------------[ LIN-CP ]------------------------\r\n"); XP("TxOK: %d, TxNG: %d, SUM: %d\r\n", p->m_nTxOK, p->m_nTxNG, p->m_nTxOK + p->m_nTxNG); XP("RxOK: %d, RxNG: %d, SUM: %d\r\n", p->m_nRxOK, p->m_nRxNG, p->m_nRxOK + p->m_nRxNG); XP("---------------------------------------------------------\r\n"); } void LIN_IRQ_Proc(PLinCP p) { if (p == NULL) return; #ifdef FUNC_LIN_MASTER // if (p->m_bTx) // { // LIN_IRQ_Master_ProcTx(p); // } // else if (p->m_bRx) // { // LIN_IRQ_Master_ProcRx(p); // } LIN_IRQ_Master_ProcTx(p); LIN_IRQ_Master_ProcRx(p); #else // if (p->m_bTx) // { // LIN_IRQ_Slave_ProcTx(p); // } // // if (p->m_bRx) // { // LIN_IRQ_Slave_ProcRx(p); // } #endif } #ifdef FUNC_LIN_MASTER void LIN_IRQ_Master_ProcTx(PLinCP p) { if (p == NULL) return; if (LL_USART_IsActiveFlag_TXE(p->m_USART)) { if (p->m_TxIdx == 0 && p->m_TxLen == 0) return; if (p->m_TxIdx < p->m_TxLen) { if (p->m_TxIdx == 0) { LL_USART_RequestBreakSending(p->m_USART); } LL_USART_TransmitData8(p->m_USART, p->m_TxBuf[p->m_TxIdx++]); } else { p->m_TxLen = 0; p->m_TxIdx = 0; LIN_FlowTx(p, HTK_FALSE, HTK_TRUE); } } } void LIN_IRQ_Master_ProcRx(PLinCP p) { if (p == NULL) return; if (LL_USART_IsActiveFlag_LBD(p->m_USART)) { LL_USART_ClearFlag_LBD(p->m_USART); p->m_RxLen = 0; } // else if ( // LL_USART_IsActiveFlag_FE(p->m_USART) || // LL_USART_IsActiveFlag_ORE(p->m_USART) || // LL_USART_IsActiveFlag_NE(p->m_USART)) // { // u8 Data = LL_USART_ReceiveData8(p->m_USART); // XP("Data = %02X\r\n", Data); // } else if (LL_USART_IsActiveFlag_FE(p->m_USART)) { u8 Data = LL_USART_ReceiveData8(p->m_USART); XP("#LIN_ProcRx_Flag_FE = %02X\r\n", Data); } else if (LL_USART_IsActiveFlag_ORE(p->m_USART)) { u8 Data = LL_USART_ReceiveData8(p->m_USART); XP("#LIN_ProcRx_Flag_ORE = %02X\r\n", Data); } else if (LL_USART_IsActiveFlag_NE(p->m_USART)) { u8 Data = LL_USART_ReceiveData8(p->m_USART); XP("#LIN_ProcRx_Flag_NE = %02X\r\n", Data); } else if (LL_USART_IsActiveFlag_RXNE(p->m_USART)) { p->m_RxBuf[p->m_RxLen++] = LL_USART_ReceiveData8(p->m_USART); // if (p->m_RxLen == 10) // { // LIN_FlowTx(p, HTK_FALSE, HTK_FALSE); // } // if (LIN_BUF_MAX <= p->m_RxLen) // { // if (p->m_RxBuf[0] == LIN_SYNC_BYTE) // { // u8 id = p->m_RxBuf[1] & PID_MAX; // // if (p->m_RxBuf[1] == LIN_PID_TABLE[id]) // { // if (LIN_CalcCheckSum(id, &p->m_RxBuf[2], 8) == p->m_RxBuf[10]) // { //#ifdef DEBUG_LIN_CP // XP("LIN-RX : PID(%02X) ID(%02X) {%02X, %02X, %02X, %02X, %02X, %02X, %02X, %02X} [%02X]\r\n", // p->m_RxBuf[1], id, // p->m_RxBuf[2], p->m_RxBuf[3], p->m_RxBuf[4], p->m_RxBuf[5], // p->m_RxBuf[6], p->m_RxBuf[7], p->m_RxBuf[8], p->m_RxBuf[9], // p->m_RxBuf[10]); //#endif // LIN_SetRx(p, HTK_FALSE); // p->m_bRx = HTK_FALSE; // } // else // { // // } // } // else // { // // } // } // else // { // // } // // p->m_RxLen = 0; // } } else { } } #else //FUNC_LIN_MASTER #endif //FUNC_LIN_MASTER