cancel
Showing results for 
Search instead for 
Did you mean: 

CAN message reception without callbacks

Timo Wedde-Ramola
Associate
Posted on May 24, 2018 at 15:52

Hi All,

I am currently developing an application using CAN1 with CMSIS driver on a STM32F413 controller. As the reception of CAN messages is not so time critical like other parts in the application, I wanted to poll manually for new messages by calling MessageRead(). The Callback functions are NULL.

Now, after the third reception of my message, the CAN controller does not stop 'receiving' the message until I entirely power off my hardware and restart.

When I register an ObjectEvent callback and do a MessageRead() in there, everything works as expected, but I wanted to avoid having interrupts in my program flow. I get, that obviously it has to do with the RFOM register, but don't see, what is the difference between trying to read a message cyclic or read it after I have been informed about a new reception.

In the CMSIS documentation there is written the callbacks may be NULL. But is it intended at all to receive messages when no callbacks are registered? Or am I 'forced' to use the callbacks when I don't want to dismiss incoming messages?

Many thanks in advance,

Timo

3 REPLIES 3
T J
Lead
Posted on May 25, 2018 at 02:26

I guess you are over running the buffers and going into an error state.

I made a table of 64 entries to catch all the frames.

char canRxString[1024];
uint16_t canRxMsgID [64];// to catch any size
uint8_t canRxMsgLength [64];
uint32_t canRxMsgBottomWord [64];
uint32_t canRxMsgTopWord[64];
char canRxHaveSegmentID [64];
char canTxString[1024];
uint16_t canTxMsgID[64];
uint8_t canTxMsgLength[64];
uint32_t canTxMsgBottomWord [64];
uint32_t canTxMsgTopWord[64];

in the HAL CAN CALLBACK;
I use this code to steal the frame before HAL can see it, thereby leaving HAL enabled.

/**
* @brief This function handles CAN1 RX0 interrupts.
*/
void CAN1_RX0_IRQHandler(void)
{
 /* USER CODE BEGIN CAN1_RX0_IRQn 0 */
 checkCanRxFifos();
 /* USER CODE END CAN1_RX0_IRQn 0 */
 HAL_CAN_IRQHandler(&hcan1);
 /* USER CODE BEGIN CAN1_RX0_IRQn 1 */
 /* USER CODE END CAN1_RX0_IRQn 1 */
}
/**
* @brief This function handles CAN1 RX1 interrupt.
*/
void CAN1_RX1_IRQHandler(void)
{
 /* USER CODE BEGIN CAN1_RX1_IRQn 0 */
 checkCanRxFifos();
 /* USER CODE END CAN1_RX1_IRQn 0 */
 HAL_CAN_IRQHandler(&hcan1);
 /* USER CODE BEGIN CAN1_RX1_IRQn 1 */
 /* USER CODE END CAN1_RX1_IRQn 1 */
}

 
void checkCanRxFifos(void) {
 
 int readCanBytecount;
 
 char canFifo1FullFlag = CAN1->RF1R & CAN_RF1R_FMP1;
 if (canFifo1FullFlag) {
 {
 readCanBytecount = (CAN1->sFIFOMailBox[1].RDTR & 0x0f); 
 canRxMsgBottomWord[canRxMsgIN] = CAN1->sFIFOMailBox[1].RDLR; // load all eight bytes in 2 cycles
 canRxMsgTopWord [canRxMsgIN] = CAN1->sFIFOMailBox[1].RDHR;
 canRxMsgID[canRxMsgIN] = CAN1->sFIFOMailBox[1].RIR >> 21;
 CAN1->RF1R |= CAN_RF1R_RFOM1; // release FIFO 
 canRxMsgLength[canRxMsgIN] = readCanBytecount; 
 ++canRxMsgIN &= 0x3F; // 64 entries only
 canRxMsgTableEMPTY = false;
 if (canRxMsgIN == canRxMsgOUT) canRxMsgTableFULL = true;
 }
 CAN1->IER |= CAN_IER_FMPIE1; // (11) Set FIFO1 message pending IT enable 
 }
 char canFifo0FullFlag = CAN1->RF0R & CAN_RF0R_FMP0;
 if (canFifo0FullFlag) {
 {
 readCanBytecount = (CAN1->sFIFOMailBox[0].RDTR & 0x0f); 
 canRxMsgBottomWord[canRxMsgIN] = CAN1->sFIFOMailBox[0].RDLR;
 canRxMsgTopWord[canRxMsgIN] = CAN1->sFIFOMailBox[0].RDHR;


 uint32_t canRxmsgID = CAN1->sFIFOMailBox[0].RIR >> 21;
 CAN1->RF0R |= CAN_RF0R_RFOM0; // release FIFO 
 if (canRxMsgTableFULL) { 
 canRxMsgTableOverflow = true; // now dump new frame...
 }
 else {
 canRxMsgID[canRxMsgIN] = canRxmsgID;
 canRxMsgLength[canRxMsgIN] = readCanBytecount; 
 ++canRxMsgIN &= 0x3F; // 16 entries only
 canRxMsgTableEMPTY = false;
 if (canRxMsgIN == canRxMsgOUT)
 canRxMsgTableFULL = true;
 }
 
 //length = sprintf(string + length,'%08X, %08X :W',canFifoBuf.d32[0],canFifoBuf.d32[1]); 
 // for( int i = 0; i < readCanBytecount; i++){
 // 
 // canRxBuffer[canRxpointerIN++] = canFifoBuf.d8[i]; 
 // canRxpointerIN &= 0xFF;
 // if (canRxpointerIN == canRxpointerOUT ) CanRxbufferOverrun = true;
 // //length += sprintf(string + length,'%02X, ',canFifoBuf.d8[i]);
 // }
 //sprintf(string + length -2,'

'); // remove 2 bytes, the last comma and space
 //canFifo0FullFlag = CAN1->RF0R & CAN_RF0R_FMP0;
 }
 CAN1->IER |= CAN_IER_FMPIE0; // (11) Set FIFO1 message pending IT enable 
 }
 // if (length >0) puts(string);
}

�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

Timo Wedde-Ramola
Associate
Posted on May 28, 2018 at 08:37

Hi and many thanks for the detailed answer.

I will take a closer look on it asap and see where it brings me. Nevertheless, it is still utilizing interrupts which I wanted to avoid. I thought, there maybe would be a way to poll the messages manually on a regular time base. But maybe the drivers simply aren't intended to be used this way.

Posted on May 28, 2018 at 11:14

Yes, this code under interrupt, fills a Can-frame-buffer[64], that's 64 frames before you must service the buffer, to be sure that you never miss a frame.

In a different process, you can poll the buffer full/empty/length, at any time.