📄 drv_can.c
字号:
* @return Status E_OK if tranfer initiated
* E_OS_STATE otherwise
**********************************************************************/
StatusType CopyFrameBuffer2Hard(pTXBUF_t pTxbuf)
{
StatusType returned_type;
unsigned char foo;
returned_type = E_OS_STATE;
CAN_current_message = CAN_deqMsg();
if (CAN_current_message == NULL)
return(returned_type);
#ifdef __EXT29BITS__
pTxbuf->EIDL = CAN_current_message->CANID;
pTxbuf->EIDH = CAN_current_message->CANID >> 8;
pTxbuf->SIDL = (CAN_current_message->CANID >> 16) & 0x03;
foo = (CAN_current_message->CANID >> 13) & 0xE0;
foo = foo | 0x08;
pTxbuf->SIDL = pTxbuf->SIDL + foo;
pTxbuf->SIDH = CAN_current_message->CANID >> 21;
#else
#ifdef __STD11BITS__
pTxbuf->SIDL = CAN_current_message->CANID << 5;
pTxbuf->SIDH = CAN_current_message->CANID >> 3;
#else
#error "you should define 11 or 29 bits for CANID !"
#endif
#endif
pTxbuf->DLC = CAN_current_message->length & 0x0F;
pTxbuf->DATA[0] = CAN_current_message->data[0];
pTxbuf->DATA[1] = CAN_current_message->data[1];
pTxbuf->DATA[2] = CAN_current_message->data[2];
pTxbuf->DATA[3] = CAN_current_message->data[3];
pTxbuf->DATA[4] = CAN_current_message->data[4];
pTxbuf->DATA[5] = CAN_current_message->data[5];
pTxbuf->DATA[6] = CAN_current_message->data[6];
pTxbuf->DATA[7] = CAN_current_message->data[7];
CAN_current_message->state = CAN_MSG_SENT;
SetEvent(CAN_current_message->CallerID, CAN_QUEUE_EMPTY);
SET_TXREQ(pTxbuf);
returned_type = E_OK;
return(returned_type);
}
/**********************************************************************
* Enqueue a client packet object into the RS task queue.
*
* Once placed in queue, client must not modify the data
* otherwise unpredictable results. To safely change the object,
* dequeue, modify, re-enqueue.
*
* The code in mainly executed in critical region [SuspendAllInterrupt]
* because many tasks can call this function at the same time and break
* the FIFO list.
*
* Returns 1 if successfull, 0 if message could not be enqueued
**********************************************************************/
StatusType CAN_enqMsg(CAN_message_tRef toEnqueue)
{
CAN_message_tRef CAN_list_itor;
if (toEnqueue != NULL)
{
SuspendOSInterrupts();
if (CAN_list_head == NULL)
CAN_list_head = toEnqueue;
else
{
CAN_list_itor = CAN_list_head;
while (CAN_list_itor->next != NULL)
CAN_list_itor = CAN_list_itor->next;
CAN_list_itor->next = toEnqueue;
}
toEnqueue->next = NULL;
toEnqueue->CallerID = id_tsk_run;
toEnqueue->state = CAN_FULL;
CAN_list_count++;
ResumeOSInterrupts();
return E_OK;
}
else
return E_OS_STATE;
}
/**********************************************************************
* Dequeue a client message from the RS task queue.
*
*
*********************************************************************/
CAN_message_tRef CAN_deqMsg(void)
{
CAN_message_tRef CAN_list_itor;
SuspendOSInterrupts();
CAN_list_itor = NULL;
if (CAN_list_head != NULL)
{
CAN_list_itor = CAN_list_head;
CAN_list_head = CAN_list_head->next;
CAN_list_count--;
}
ResumeOSInterrupts();
return CAN_list_itor;
}
/**********************************************************************
* Called by the CAN driver task.
* Check the RXFUL bit of the both RX CAN hardware buffers.
* If at least one message is store in hardware then this function
* tries to tranfer the data from hardware to dedicated structure
* (structure created by other tasks).
*
* @param void
* @return Status Always return E_OK
**********************************************************************/
StatusType ReadCANBuffer(void)
{
if (PIR3bits.RXB0IF == 1)
{
CANCONbits.WIN2 = 1;
CANCONbits.WIN1 = 1;
CANCONbits.WIN0 = 0;
if (CopyHard2FrameBuffer() == E_OK)
{
RXB0CONbits.RXFUL = 0;
PIR3bits.RXB0IF = 0;
PIE3bits.RXB0IE = 1;
}
}
if (PIR3bits.RXB1IF == 1)
{
CANCONbits.WIN2 = 1;
CANCONbits.WIN1 = 0;
CANCONbits.WIN0 = 1;
if (CopyHard2FrameBuffer() == E_OK)
{
RXB0CONbits.RXFUL = 0;
PIR3bits.RXB1IF = 0;
PIE3bits.RXB1IE = 1;
}
}
return(E_OK);
}
/**********************************************************************
* Enqueue a client packet object into the RS task queue.
*
* Once placed in queue, client must not modify the data
* otherwise unpredictable results. To safely change the object,
* dequeue, modify, re-enqueue.
*
* The code in mainly executed in critical region [SuspendAllInterrupt]
* because many tasks can call this function at the same time and break
* the FIFO list.
*
* Returns 1 if successfull, 0 if message could not be enqueued
**********************************************************************/
StatusType CAN_RCV_Register(CAN_message_tRef toEnqueue)
{
CAN_message_tRef CAN_list_itor;
if (toEnqueue != NULL)
{
SuspendOSInterrupts();
if (CAN_list_head_rcv == NULL)
CAN_list_head_rcv = toEnqueue;
else
{
CAN_list_itor = CAN_list_head_rcv;
while (CAN_list_itor->next != NULL)
CAN_list_itor = CAN_list_itor->next;
CAN_list_itor->next = toEnqueue;
}
toEnqueue->next = NULL;
toEnqueue->CallerID = id_tsk_run;
CAN_list_count_rcv++;
ResumeOSInterrupts();
return E_OK;
}
else
return E_OS_STATE;
}
/**********************************************************************
* Parse the entier RX message list to find any task waiting for the
* received message ID.
* Once a such taks is found we post an event to the waiting task
* to tell its software buffer is full and we break.
* The event is used if the task want to wait for a particular message
* ID without overloading the CPU by a pooling method.
*
* @param type IN Number of the hardware buffer
* @return Status E_OK if tranfer initiated
* E_OS_STATE otherwise
**********************************************************************/
StatusType CopyHard2FrameBuffer(void)
{
StatusType returned_type;
unsigned long ID_received;
CAN_message_tRef CAN_list_itor;
returned_type = E_OK;
if (CAN_list_head_rcv != NULL)
{
CAN_list_itor = CAN_list_head_rcv;
do
{
#ifdef __NOFILTER__
if (1)
#else
#ifdef __EXT29BITS__
ID_received = 0;
ID_received += (unsigned long)(RXB0EIDL);
ID_received += (unsigned long)(RXB0EIDH) << 8;
ID_received += (unsigned long)(RXB0SIDL & 0x03) << 16;
ID_received += (unsigned long)(RXB0SIDL & 0xE0) << 13;
ID_received += (unsigned long)(RXB0SIDH & 0xFF) << 21;
#else
#ifdef __STD11BITS__
ID_received = 0;
ID_received += (unsigned long)(RXB0SIDL) >> 5;
ID_received += (unsigned long)(RXB0SIDH) << 3;
#else
#error "you should define 11 or 29 bits for CANID !"
#endif
#endif
if (CAN_list_itor->CANID == ID_received)
#endif
{
if (CAN_list_itor->state == CAN_FREE)
{
CAN_list_itor->data[0] = RXB0D0;
CAN_list_itor->data[1] = RXB0D1;
CAN_list_itor->data[2] = RXB0D2;
CAN_list_itor->data[3] = RXB0D3;
CAN_list_itor->data[4] = RXB0D4;
CAN_list_itor->data[5] = RXB0D5;
CAN_list_itor->data[6] = RXB0D6;
CAN_list_itor->data[7] = RXB0D7;
CAN_list_itor->length = RXB0DLC & 0x0F;
CAN_list_itor->state = CAN_FULL;
SetEvent(CAN_list_itor->CallerID, CAN_QUEUE_FULL);
}
else
returned_type = E_OS_STATE;
}
CAN_list_itor = CAN_list_itor->next;
}
while (CAN_list_itor != NULL);
}
return(returned_type);
}
/**********************************************************************
* ISR of the CAN driver.
*
* For each interrupt we disable the IE first to avoid any infinite loop
* and we clear the IF in the dedicated function (Read or Write CAN mess).
* Indeed we have to clear the IT when the message has been properly
* accessed and is no more used. The IF lets the peripheral accept a new
* message.
* If 3 frames arrive at the same time, the two first are stored in the
* RCV buffers and the third is discarded (temporary overload bus).
*
* @return void
**********************************************************************/
void CAN_INT(void)
{
if (PIR3 & 0x03)
{
if (PIR3bits.RXB0IF)
PIE3bits.RXB0IE = 0;
if (PIR3bits.RXB1IF)
PIE3bits.RXB1IE = 0;
SetEvent(CAN_DRV_ID, CAN_RCV_MSG);
};
if (PIR3 & 0x1C)
{
if (PIR3bits.TXB0IF)
PIE3bits.TXB0IE = 0;
if (PIR3bits.TXB1IF)
PIE3bits.TXB1IE = 0;
if (PIR3bits.TXB2IF)
PIE3bits.TXB2IE = 0;
SetEvent(CAN_DRV_ID, CAN_NEW_MSG);
}
if (PIR3 & 0xE0)
{
if (PIR3bits.WAKIF)
PIR3bits.WAKIF = 0;
if (PIR3bits.ERRIF)
{
COMSTATbits.RXB0OVFL = 0;
COMSTATbits.RXB1OVFL = 0;
PIR3bits.ERRIF = 0;
}
if (PIR3bits.IRXIF)
PIR3bits.IRXIF = 0;
SetEvent(CAN_DRV_ID, CAN_ERR_MSG);
}
}
/* End of File : drv_can.c */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -