
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
/*
* Can_Driver.c
*
* Created on: 2021. 8. 3.
* Author: KimJeongWoo
*/
#include <CommonLib.h>
sCanMsg CanaTxMbox1;
sCanMsg CanaTxMbox2;
sCanMsg CanbTxMbox;
sCanMsg CanaRxMbox[32];
sCanMsg CanbRxMbox[32];
unsigned int TerminalResSet = 0xff;
void InitCan()
{
// InitCanGpio();
CAN_initModule(CANA_BASE);
CAN_initModule(CANB_BASE);
CAN_setBitRate(CANA_BASE, DEVICE_SYSCLK_FREQ, 500000, 16);
CAN_setBitRate(CANB_BASE, DEVICE_SYSCLK_FREQ, 500000, 16);
CAN_enableGlobalInterrupt(CANA_BASE, CAN_GLOBAL_INT_CANINT0);
CAN_enableGlobalInterrupt(CANB_BASE, CAN_GLOBAL_INT_CANINT0);
CAN_enableInterrupt(CANA_BASE, CAN_INT_IE0);
CAN_enableInterrupt(CANB_BASE, CAN_INT_IE0);
//송신용
// CAN_setupMessageObject(CANA_BASE, 32, 0x000 + CanBe_TxId_Offset, CAN_MSG_FRAME_STD, CAN_MSG_OBJ_TYPE_TX, 0x7FF, CAN_MSG_OBJ_USE_ID_FILTER, 8);
// CAN_setupMessageObject(CANA_BASE, 31, 0x01F + CanBe_TxId_Offset, CAN_MSG_FRAME_STD, CAN_MSG_OBJ_TYPE_TX, 0x7F0, CAN_MSG_OBJ_USE_ID_FILTER, 8);
//수신용
// CAN_setupMessageObject(CANA_BASE, 1, 0x000 + CanBe_RxId_Offset, CAN_MSG_FRAME_STD, CAN_MSG_OBJ_TYPE_RX, 0x7FF, (CAN_MSG_OBJ_RX_INT_ENABLE | CAN_MSG_OBJ_USE_ID_FILTER), 0);
// CAN_setupMessageObject(CANA_BASE, 2, 0x01F + CanBe_RxId_Offset, CAN_MSG_FRAME_STD, CAN_MSG_OBJ_TYPE_RX, 0x7F0, (CAN_MSG_OBJ_RX_INT_ENABLE | CAN_MSG_OBJ_USE_ID_FILTER), 0);
CAN_startModule(CANA_BASE);
CAN_startModule(CANB_BASE);
}
int FlagCanReset = 0;
/*
bp_16 LEC:3; // 2:0 Last Error Code
bp_16 TxOk:1; // 3 Transmission status
bp_16 RxOk:1; // 4 Reception status
bp_16 EPass:1; // 5 Error Passive State
bp_16 EWarn:1; // 6 Warning State
bp_16 BOff:1; // 7 Bus-Off State
bp_16 PER:1; // 8 Parity Error Detected
*/
void CanErrorReset()
{
if ((CanaRegs.CAN_ES.bit.BOff == 1) || (CanaRegs.CAN_ES.bit.PER == 1))
{
CAN_startModule(CANA_BASE);
}
if ((CanbRegs.CAN_ES.bit.BOff == 1) || (CanbRegs.CAN_ES.bit.PER == 1))
{
CAN_startModule(CANB_BASE);
}
if (FlagCanReset == 1)
{
InitCan();
FlagCanReset = 0;
}
}
//todo 일단은 std만.. 나중에 고칠 것
//ID 변경가능, DLC 변경 가능, Std 모드
void CanTxMsg(uint32_t base, uint32_t objID, sCanMsg *Msg)
{
uint32_t msgCtrl = 0U;
uint32_t arbReg = 0U;
HWREG_BP(base + CAN_O_IF1CMD) = ((uint32_t) CAN_IF1CMD_CONTROL | (objID & CAN_IF1CMD_MSG_NUM_M));
while ((HWREGH(base + CAN_O_IF1CMD) & CAN_IF1CMD_BUSY) == CAN_IF1CMD_BUSY);
msgCtrl = HWREGH(base + CAN_O_IF1MCTL);
arbReg = HWREGH(base + CAN_O_IF1ARB);
// 데이터 길이 업데이트
msgCtrl &= ~CAN_IF1MCTL_DLC_M;
msgCtrl |= (Msg->Lenth & CAN_IF1MCTL_DLC_M);
HWREG_BP(base + CAN_O_IF1MCTL) = msgCtrl;
//ID 업데이트 Id std.
arbReg |= ((Msg->Id << CAN_IF1ARB_STD_ID_S) & CAN_IF1ARB_STD_ID_M) | CAN_IF1ARB_MSGVAL | CAN_IF1ARB_DIR;
HWREG_BP(base + CAN_O_IF1ARB) = arbReg;
HWREG_BP(base + CAN_O_IF1CMD) = (CAN_IF1CMD_CONTROL | CAN_IF1CMD_DIR | (objID & CAN_IF1CMD_MSG_NUM_M));
uint16_t Cnt = 0;
uint16_t idx = 0;
uint32_t dataReg = 0;
//Data 주소위치
dataReg = (base + CAN_O_IF1DATA);
//16bit 처리를 위한 인덱스 카운트 생성, 데이터길이가 홀수일 때 + 1
Cnt = ((Msg->Lenth * 0.5) + (Msg->Lenth % 2));
//MassageRam 영역에 데이터 쓰기
for (idx = 0U; idx < Cnt; idx++)
{
//HWREGH는16bit, HWREGB는 8bit
HWREGH(dataReg) = Msg->Data.U16.Word[idx];
dataReg = dataReg + 2;
}
// Set Data to be transferred from IF
if (Msg->Lenth > 0U)
{
msgCtrl = CAN_IF1CMD_DATA_B | CAN_IF1CMD_DATA_A;
}
else
{
msgCtrl = 0U;
}
HWREG_BP(base + CAN_O_IF1CMD) = (msgCtrl | (uint32_t) CAN_IF1CMD_DIR | CAN_IF1CMD_ARB | (uint32_t) CAN_IF1CMD_TXRQST | (objID & CAN_IF1CMD_MSG_NUM_M));
}
bool CanRxMsg(uint32_t base, uint32_t objID, sCanMsg *Msg)
{
bool status;
uint16_t msgCtrl = 0U;
uint32_t idx;
uint32_t dataReg;
HWREG_BP(base + CAN_O_IF2CMD) = ((uint32_t) CAN_IF2CMD_DATA_A
| (uint32_t) CAN_IF2CMD_DATA_B
| (uint32_t) CAN_IF2CMD_CONTROL
| (objID & CAN_IF2CMD_MSG_NUM_M)
| (uint32_t) CAN_IF2CMD_ARB);
while ((HWREGH(base + CAN_O_IF2CMD) & CAN_IF2CMD_BUSY) == CAN_IF2CMD_BUSY);
msgCtrl = HWREGH(base + CAN_O_IF2MCTL);
Msg->Lenth = (msgCtrl & CAN_IF2MCTL_DLC_M);
if ((msgCtrl & CAN_IF2MCTL_NEWDAT) == CAN_IF2MCTL_NEWDAT)
{
uint16_t Cnt;
Cnt = ((Msg->Lenth * 0.5) + (Msg->Lenth % 2));
dataReg = (base + CAN_O_IF2DATA);
for(idx = 0; idx < Cnt; idx++)
{
Msg->Data.U16.Word[idx] = HWREGH(dataReg);
dataReg = dataReg + 2;
}
status = true;
//
// Now clear out the new data flag
//
HWREG_BP(base + CAN_O_IF2CMD) = ((uint32_t) CAN_IF2CMD_TXRQST | (objID & CAN_IF2CMD_MSG_NUM_M));
//
// Wait for busy bit to clear
//
while ((HWREGH(base + CAN_O_IF2CMD) & CAN_IF2CMD_BUSY) == CAN_IF2CMD_BUSY);
}
else
{
status = false;
}
if (status == true)
{
if ((HWREG_BP(base + CAN_O_IF2ARB) & CAN_IF2ARB_XTD) != 0U)
{
*Msg->frameType = CAN_MSG_FRAME_EXT;
Msg->Id = ((HWREG_BP(base + CAN_O_IF2ARB)) & CAN_IF2ARB_ID_M);
}
else
{
*Msg->frameType = CAN_MSG_FRAME_STD;
Msg->Id = (((HWREG_BP(base + CAN_O_IF2ARB)) & CAN_IF2ARB_STD_ID_M) >> CAN_IF2ARB_STD_ID_S);
}
Msg->Cnt++; //정상적인 수신일 경우 카운트
}
return (status);
}