CAN Bus Receive without Interrupt

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
keenansoe
Level 3
Level 3
25 sign-ins 5 questions asked 10 replies posted

Hello,

As I have mentioned before, I am trying to create an abstraction layer for the CAN bus in C++ on an XMC700 family device.

I want to use this application in an RTOS and in other device families I am used to creating an RTOS thread for querying the hardware CAN receive buffers and putting them onto an RTOS queue.

The challenge I have is that the only CAN receive examples use an interrupt-driven call back which requires a globally scoped named function. This is very challenging as I can link directly to a class function's name without declaring that function as static and eliminating a lot of the benefit of the code reuse across the different CAN bus devices on the chip.

Is there a way or examples of how I can write a function to check the receive buffer of the CAN hw and extract any new messages in a polling fashion that would align better with the RTOS?

0 Likes
1 Solution
sujatapatil
Moderator
Moderator
Moderator
50 solutions authored 10 likes received 100 sign-ins

Hi Keenasoe,

Polling code looks fine but it assumes only one CAN packet is received and index is always pointing  to 0 while accessing FIFO top while calling Cy_CANFD_ExtractMsgFromRXBuffer   .  You need to consider FIFO size programmed and increment in for loop for SIZE and call function Cy_CANFD_ExtractMsgFromRXBuffer and store it in local buffer.

Thanks

Sujata

 

View solution in original post

0 Likes
7 Replies
keenansoe
Level 3
Level 3
25 sign-ins 5 questions asked 10 replies posted

@Pradeep_PN you've been helpful with replies before. Perhaps you have a strategy here?

0 Likes
keenansoe
Level 3
Level 3
25 sign-ins 5 questions asked 10 replies posted

It seems like I should be able to use the function Cy_CANFD_GetFIFOTop() as shown in the docs.

However, I am not sure if that is possible if the interrupts are not running or if I still need the interrupt to be configured?

 

https://infineon.github.io/mtb-pdl-cat1/pdl_api_reference_manual/html/group__group__canfd__functions...

0 Likes
keenansoe
Level 3
Level 3
25 sign-ins 5 questions asked 10 replies posted

I started from the can example on github and attempted to use the GetFIFOTop() function, but it didn't seem to work.

However, I was able to use this code that seemed to function properly using the CAN FIFO0. Does this method seem correct? It uses the  Cy_CANFD_ExtractMsgFromRXBuffer method.

 

for(;;)
    {

		/* The members of the rxBuffer structure */
		cy_stc_canfd_r0_t  r0RxBuffer; /* The R0 register structure of the RX buffer element */
		cy_stc_canfd_r1_t  r1RxBuffer; /* The R1 register structure of the RX buffer element */
		uint32_t           rxData[CY_CANFD_DATA_ELEMENTS_MAX]; /* The array to store RX data */

		cy_stc_canfd_rx_buffer_t rxBuffer =
		{
			/* .r0_f         */ &r0RxBuffer,
			/* .r1_f         */ &r1RxBuffer,
			/* .data_area_f  */ rxData
		};

		bool rxFIFOMsg = true;
		uint8_t msgBufOrRxFIFONum = 0;

		uint8_t canfd_data_buffer[8];


		// Check if there is a message in the buffer
		uint32_t status;
		status = Cy_CANFD_GetInterruptStatus(CANFD_HW, CAN_HW_CHANNEL);
		if (0 != (status & CY_CANFD_RX_FIFO_0_NEW_MESSAGE ))
		{
			/* Process the received message */

			if( CY_CANFD_SUCCESS == (Cy_CANFD_ExtractMsgFromRXBuffer(CANFD_HW, CAN_HW_CHANNEL,
                                         rxFIFOMsg, msgBufOrRxFIFONum,
                                         &rxBuffer, &canfd_context)) )
			{
				int canfd_dlc = r1RxBuffer.dlc;
				int canfd_id  = r0RxBuffer.id;

				memcpy(canfd_data_buffer, rxBuffer.data_area_f, canfd_dlc);

				// Message Received
				printf("%d bytes received from Node-%d with identifier %d\r\n\r\n",
																		canfd_dlc,
																		canfd_id,
																		canfd_id);

				for (uint8_t msg_idx = 0; msg_idx < canfd_dlc ; msg_idx++)
				{
					printf(" %d ", canfd_data_buffer[msg_idx]);
				}
				printf("\r\n\r\n");

				uint32_t status =  (CY_CANFD_RX_FIFO_0_NEW_MESSAGE);
				Cy_CANFD_ClearInterrupt(CANFD_HW, CAN_HW_CHANNEL, status);
			}
			else
			{
				// Handle Error
			}
		}

 

 

 

0 Likes
sujatapatil
Moderator
Moderator
Moderator
50 solutions authored 10 likes received 100 sign-ins

Hello,

You can use IPC mechanism like message queues or pipes ,and also  shared memory for your requirement. RTOS provides APIs for this . 

 

Thanks 

Sujata

0 Likes
keenansoe
Level 3
Level 3
25 sign-ins 5 questions asked 10 replies posted

Thank you @sujatapatil for the response. Yes I understand, but could you take a look at my code snippit I posted above? Curious if that is a "correct" approach for polling the CAN bus?

0 Likes
sujatapatil
Moderator
Moderator
Moderator
50 solutions authored 10 likes received 100 sign-ins

Hi Keenasoe,

Polling code looks fine but it assumes only one CAN packet is received and index is always pointing  to 0 while accessing FIFO top while calling Cy_CANFD_ExtractMsgFromRXBuffer   .  You need to consider FIFO size programmed and increment in for loop for SIZE and call function Cy_CANFD_ExtractMsgFromRXBuffer and store it in local buffer.

Thanks

Sujata

 

0 Likes
keenansoe
Level 3
Level 3
25 sign-ins 5 questions asked 10 replies posted

Thanks for the reply, but I am not quite sure I understand. Wouldn't the index always be zero if I am using the FIFO behavior?

Perhaps if you could show an example, I might understand better.

0 Likes