📄 can_hw.c
字号:
msg->len = ((U8)(CANData >> 16)) & 0x0F;
/* Read CAN message identifier */
msg->id = ptrcan->CANRID;
/* Read the data if received message was DATA FRAME */
if (msg->type == DATA_FRAME) {
/* Read first 4 data bytes */
CANAddr = (U32 *) &msg->data[0];
*CANAddr++ = ptrcan->CANRDA;
/* Read second 4 data bytes */
*CANAddr = ptrcan->CANRDB;
}
}
/*--------------------------- CAN_hw_set ------------------------------------
* Set a message that will automatically be sent as an answer to the REMOTE
* FRAME message, as this functionality is not enabled by hardware this
* function is not implemented
*
* Parameter: ctrl: Ignored
* msg: Pointer to CAN message to be set
*
* Return: CAN_ERROR: Error code
*---------------------------------------------------------------------------*/
CAN_ERROR CAN_hw_set (U32 ctrl, CAN_msg *msg) {
return CAN_NOT_IMPLEMENTED_ERROR;
}
/*--------------------------- CAN_hw_rx_object ------------------------------
*
* Enable reception of messages, on specified controller with specified
* identifier, by setting acceptance filter
*
* Parameter: ctrl: Index of the hardware CAN controller (1 .. x)
* ch: Ignored for LPC2xxx
* id: CAN message identifier
* CAN_FORMAT: Format of CAN identifier (standard or extended)
*
* Return: CAN_ERROR: Error code
*---------------------------------------------------------------------------*/
CAN_ERROR CAN_hw_rx_object (U32 ctrl, U32 ch, U32 id, CAN_FORMAT format) {
U32 ctrl0 = ctrl-1; /* Controller index 0 .. x-1 */
static S16 CAN_std_cnt = 0;
static S16 CAN_ext_cnt = 0;
regCAN_AF *ptrcan_af = (regCAN_AF *) CAN_AF_BASE;
regCAN_AFRAM *ptrcan_afram = (regCAN_AFRAM *) CAN_AFRAM_BASE;
U32 buf0, buf1;
S16 cnt1, cnt2, bound1;
/* Acceptance Filter Memory full */
if ((((CAN_std_cnt + 1) >> 1) + CAN_ext_cnt) >= 512)
return CAN_OBJECTS_FULL_ERROR;
/* Setup Acceptance Filter Configuration
Acceptance Filter Mode Register = Off */
ptrcan_af->AFMR = 0x00000001;
if (format == STANDARD_FORMAT) { /* Add mask for standard identifiers */
id |= ctrl0 << 13; /* Add controller number */
id &= 0x0000F7FF; /* Mask out 16-bits of ID */
/* Move all remaining extended mask entries one place up
if new entry will increase standard ID filters list */
if ((CAN_std_cnt & 0x0001) == 0 && CAN_ext_cnt != 0) {
cnt1 = (CAN_std_cnt >> 1);
bound1 = CAN_ext_cnt;
buf0 = ptrcan_afram->mask[cnt1];
while (bound1--) {
cnt1++;
buf1 = ptrcan_afram->mask[cnt1];
ptrcan_afram->mask[cnt1] = buf0;
buf0 = buf1;
}
}
if (CAN_std_cnt == 0) { /* For entering first ID */
ptrcan_afram->mask[0] = 0x0000FFFF | (id << 16);
} else if (CAN_std_cnt == 1) { /* For entering second ID */
if ((ptrcan_afram->mask[0] >> 16) > id)
ptrcan_afram->mask[0] = (ptrcan_afram->mask[0] >> 16) | (id << 16);
else
ptrcan_afram->mask[0] = (ptrcan_afram->mask[0] & 0xFFFF0000) | id;
} else {
/* Find where to insert new ID */
cnt1 = 0;
cnt2 = CAN_std_cnt;
bound1 = (CAN_std_cnt - 1) >> 1;
while (cnt1 <= bound1) { /* Loop through standard existing IDs */
if ((ptrcan_afram->mask[cnt1] >> 16) > id) {
cnt2 = cnt1 * 2;
break;
}
if ((ptrcan_afram->mask[cnt1] & 0x0000FFFF) > id) {
cnt2 = cnt1 * 2 + 1;
break;
}
cnt1++; /* cnt1 = U32 where to insert new ID */
} /* cnt2 = U16 where to insert new ID */
if (cnt1 > bound1) { /* Adding ID as last entry */
if ((CAN_std_cnt & 0x0001) == 0)/* Even number of IDs exists */
ptrcan_afram->mask[cnt1] = 0x0000FFFF | (id << 16);
else /* Odd number of IDs exists */
ptrcan_afram->mask[cnt1] = (ptrcan_afram->mask[cnt1] & 0xFFFF0000) | id;
} else {
buf0 = ptrcan_afram->mask[cnt1];/* Remember current entry */
if ((cnt2 & 0x0001) == 0) /* Insert new mask to even address */
buf1 = (id << 16) | (buf0 >> 16);
else /* Insert new mask to odd address */
buf1 = (buf0 & 0xFFFF0000) | id;
ptrcan_afram->mask[cnt1] = buf1;/* Insert mask */
bound1 = CAN_std_cnt >> 1;
/* Move all remaining standard mask entries one place up */
while (cnt1 < bound1) {
cnt1++;
buf1 = ptrcan_afram->mask[cnt1];
ptrcan_afram->mask[cnt1] = (buf1 >> 16) | (buf0 << 16);
buf0 = buf1;
}
if ((CAN_std_cnt & 0x0001) == 0)/* Even number of IDs exists */
ptrcan_afram->mask[cnt1] = (ptrcan_afram->mask[cnt1] & 0xFFFF0000) | (0x0000FFFF);
}
}
CAN_std_cnt++;
} else { /* Add mask for extended identifiers */
id |= (ctrl0) << 29; /* Add controller number */
cnt1 = ((CAN_std_cnt + 1) >> 1);
cnt2 = 0;
while (cnt2 < CAN_ext_cnt) { /* Loop through extended existing masks*/
if (ptrcan_afram->mask[cnt1] > id)
break;
cnt1++; /* cnt1 = U32 where to insert new mask */
cnt2++;
}
buf0 = ptrcan_afram->mask[cnt1]; /* Remember current entry */
ptrcan_afram->mask[cnt1] = id; /* Insert mask */
CAN_ext_cnt++;
bound1 = CAN_ext_cnt - 1;
/* Move all remaining extended mask entries one place up */
while (cnt2 < bound1) {
cnt1++;
cnt2++;
buf1 = ptrcan_afram->mask[cnt1];
ptrcan_afram->mask[cnt1] = buf0;
buf0 = buf1;
}
}
/* Calculate std ID start address (buf0) and ext ID start address (buf1) */
buf0 = ((CAN_std_cnt + 1) >> 1) << 2;
buf1 = buf0 + (CAN_ext_cnt << 2);
/* Setup acceptance filter pointers */
ptrcan_af->SFF_sa = 0;
ptrcan_af->SFF_GRP_sa = buf0;
ptrcan_af->EFF_sa = buf0;
ptrcan_af->EFF_GRP_sa = buf1;
ptrcan_af->ENDofTable = buf1;
ptrcan_af->AFMR = 0x00000000; /* Use acceptance filter */
return CAN_OK;
}
/*--------------------------- CAN_hw_tx_object ------------------------------
*
* This function has no usage on LPC2xxx, and so it does nothing
*
* Parameter: ctrl: Index of the hardware CAN controller (1 .. x)
* ch: Ignored for LPC2xxx
* id: CAN message identifier
* CAN_FORMAT: Format of CAN identifier (standard or extended)
*
* Return: CAN_ERROR: Error code
*---------------------------------------------------------------------------*/
CAN_ERROR CAN_hw_tx_object (U32 ctrl, U32 ch, CAN_FORMAT format) {
return CAN_OK;
}
/************************* Interrupt Functions *******************************/
/*--------------------------- CAN_ISR ---------------------------------------
*
* CAN receive and transmit interrupt function for all controllers
* Reads message from hardware registers and puts it into receive mailboxes
* If there are messages in mailbox for transmit it writes it to hardware
* and starts the transmission
*
* Parameter: none
*
* Return: none
*---------------------------------------------------------------------------*/
static void CAN_ISR (void) __irq {
CAN_msg *ptrmsg;
U32 temp;
/* If message is received and if mailbox isn't full read message from
hardware and send it to message queue */
#if USE_CAN_CTRL1 == 1
if (CAN1GSR & 0x01) {
if (os_mbx_check (MBX_rx_ctrl[0]) > 0) {
ptrmsg = _alloc_box (CAN_mpool);
CAN_hw_rd (1, ptrmsg);
CAN1CMR = 0x04; /* Release receive buffer */
isr_mbx_send (MBX_rx_ctrl[0], ptrmsg);
}
}
#endif
#if USE_CAN_CTRL2 == 1
if (CAN2GSR & 0x01) {
if (os_mbx_check (MBX_rx_ctrl[1]) > 0) {
ptrmsg = _alloc_box (CAN_mpool);
CAN_hw_rd (2, ptrmsg);
CAN2CMR = 0x04; /* Release receive buffer */
isr_mbx_send (MBX_rx_ctrl[1], ptrmsg);
}
}
#endif
/* If there is message in mailbox ready for send, and if transmission
hardware is ready, read the message from mailbox and send it */
#if USE_CAN_CTRL1 == 1
if (CAN1GSR & (1 << 3)) {
if (isr_mbx_receive (MBX_tx_ctrl[0], (void **)&ptrmsg) != OS_R_OK) {
CAN_hw_wr (1, ptrmsg);
_free_box(CAN_mpool, ptrmsg);
} else {
isr_sem_send(wr_sem[0]); /* Return a token back to semaphore */
}
}
#endif
#if USE_CAN_CTRL2 == 1
if (CAN2GSR & (1 << 3)) {
if (isr_mbx_receive (MBX_tx_ctrl[1], (void **)&ptrmsg) != OS_R_OK) {
CAN_hw_wr (2, ptrmsg);
_free_box(CAN_mpool, ptrmsg);
} else {
isr_sem_send(wr_sem[1]); /* Return a token back to semaphore */
}
}
#endif
/* Read from interrupt register to acknowledge interrupt */
#if USE_CAN_CTRL1 == 1
temp = ptrCAN1->CANICR;
#endif
#if USE_CAN_CTRL2 == 1
temp = ptrCAN2->CANICR;
#endif
VICVectAddr = 0xFFFFFFFF; /* Acknowledge Interrupt */
}
/*----------------------------------------------------------------------------
* end of file
*---------------------------------------------------------------------------*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -