Unable to receive CAN messages between two STM32FI-Discovery Boards
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2020-03-29 9:39 AM
I'm trying to communicate over CAN using the HAL_CAN library between two STM32F boards. Specifically the issue seems to be in receiving messages. Following the documentation:
==============================================================================
##### How to use this driver #####
[..]
(#) Initialize the CAN low level resources by implementing the HAL_CAN_MspInit():
(++) Enable the CAN interface clock using __HAL_RCC_CANx_CLK_ENABLE()
(++) Configure CAN pins
(+++) Enable the clock for the CAN GPIOs
(+++) Configure CAN pins as alternate function open-drain
(++) In case of using interrupts (e.g. HAL_CAN_ActivateNotification())
(+++) Configure the CAN interrupt priority using
HAL_NVIC_SetPriority()
(+++) Enable the CAN IRQ handler using HAL_NVIC_EnableIRQ()
(+++) In CAN IRQ handler, call HAL_CAN_IRQHandler()
(#) Initialize the CAN peripheral using HAL_CAN_Init() function. This
function resorts to HAL_CAN_MspInit() for low-level initialization.
(#) Configure the reception filters using the following configuration
functions:
(++) HAL_CAN_ConfigFilter()
(#) Start the CAN module using HAL_CAN_Start() function. At this level
the node is active on the bus: it receive messages, and can send
messages.
(#) To manage messages transmission, the following Tx control functions
can be used:
(++) HAL_CAN_AddTxMessage() to request transmission of a new
message.
(++) HAL_CAN_AbortTxRequest() to abort transmission of a pending
message.
(++) HAL_CAN_GetTxMailboxesFreeLevel() to get the number of free Tx
mailboxes.
(++) HAL_CAN_IsTxMessagePending() to check if a message is pending
in a Tx mailbox.
(++) HAL_CAN_GetTxTimestamp() to get the timestamp of Tx message
sent, if time triggered communication mode is enabled.
(#) When a message is received into the CAN Rx FIFOs, it can be retrieved
using the HAL_CAN_GetRxMessage() function. The function
HAL_CAN_GetRxFifoFillLevel() allows to know how many Rx message are
stored in the Rx Fifo.
(#) Calling the HAL_CAN_Stop() function stops the CAN module.
(#) The deinitialization is achieved with HAL_CAN_DeInit() function.
*** Polling mode operation ***
==============================
[..]
(#) Reception:
(++) Monitor reception of message using HAL_CAN_GetRxFifoFillLevel()
until at least one message is received.
(++) Then get the message using HAL_CAN_GetRxMessage().
(#) Transmission:
(++) Monitor the Tx mailboxes availability until at least one Tx
mailbox is free, using HAL_CAN_GetTxMailboxesFreeLevel().
(++) Then request transmission of a message using
HAL_CAN_AddTxMessage().
*** Interrupt mode operation ***
================================
[..]
(#) Notifications are activated using HAL_CAN_ActivateNotification()
function. Then, the process can be controlled through the
available user callbacks: HAL_CAN_xxxCallback(), using same APIs
HAL_CAN_GetRxMessage() and HAL_CAN_AddTxMessage().
(#) Notifications can be deactivated using
HAL_CAN_DeactivateNotification() function.
(#) Special care should be taken for CAN_IT_RX_FIFO0_MSG_PENDING and
CAN_IT_RX_FIFO1_MSG_PENDING notifications. These notifications trig
the callbacks HAL_CAN_RxFIFO0MsgPendingCallback() and
HAL_CAN_RxFIFO1MsgPendingCallback(). User has two possible options
here.
(++) Directly get the Rx message in the callback, using
HAL_CAN_GetRxMessage().
(++) Or deactivate the notification in the callback without
getting the Rx message. The Rx message can then be got later
using HAL_CAN_GetRxMessage(). Once the Rx message have been
read, the notification can be activated again.
- I'm calling HAL_CAN_Init, which in turns calls HAL_CAN_MspInit setting the clock, enabling the gpios and configuring the can pins as alternate function open drain. As I'm using interrupts it also sets the receive interrupt as:
HAL_NVIC_SetPriority(CAN1_RX0_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(CAN1_RX0_IRQn);
2. Reception filters are being set as follows using HAL_CAN_ConfigFilter(), and no error is returned:
sFilterConfig.FilterFIFOAssignment = CAN_FILTER_FIFO0;
sFilterConfig.FilterIdHigh = 0;
sFilterConfig.FilterIdLow = 0;
sFilterConfig.FilterMaskIdHigh = 0;
sFilterConfig.FilterMaskIdLow = 0;
sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
sFilterConfig.FilterActivation = ENABLE;
sFilterConfig.FilterBank = 0;
sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
sFilterConfig.SlaveStartFilterBank = 14;
HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig)
3. HAL_CAN_Start is called and no error is returned:
HAL_CAN_Start(&hcan1)
4. Using an interrupt triggered by pressing the blue pushbutton a message is sent:
void EXTI0_IRQHandler(void)
{
/* USER CODE BEGIN EXTI0_IRQn 0 */
for(int n=0;n<1000000;n++);
if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_SET) {
a++;
if(HAL_CAN_GetTxMailboxesFreeLevel(&hcan1)){
if(HAL_CAN_AddTxMessage(&hcan1, &pHeader, &a, &TxMailbox)==HAL_OK){
if(HAL_GPIO_ReadPin(GPIOG, GPIO_PIN_6) == GPIO_PIN_SET){
HAL_GPIO_WritePin(GPIOG, GPIO_PIN_6, GPIO_PIN_RESET);
} else{
HAL_GPIO_WritePin(GPIOG, GPIO_PIN_6, GPIO_PIN_SET);
}
}
}
}
5. I've verified the message is pending as the following returns a positive value:
HAL_CAN_IsTxMessagePending(&hcan1, TxMailbox)
6. However the following interrupt that should be triggered when a messaged is available to be received is never triggered:
void CAN1_RX0_IRQHandler(void)
{
/* USER CODE BEGIN CAN1_RX0_IRQn 0 */
/* USER CODE END CAN1_RX0_IRQn 0 */
HAL_CAN_IRQHandler(&hcan1);
/* USER CODE BEGIN CAN1_RX0_IRQn 1 */
HAL_CAN_GetRxMessage(&hcan1, CAN_RX_FIFO0, &pRxHeader, &r);
HAL_GPIO_WritePin(GPIOK, GPIO_PIN_3, GPIO_PIN_RESET);
/* USER CODE END CAN1_RX0_IRQn 1 */
}
Other notes:
- Have verified the transceivers being used are both receiving 3.3V
Any help would be greatly appreciated, Rus
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2020-03-29 12:38 PM
Probably wouldn't be doing a whole lot of block operations in an interrupt/callback that might exclude other things in the system from running.
Check NVIC group settings and preempt priority levels.
Won't the HAL_CAN_IRQHandler() run callbacks, clear interrupt, etc?
Might want to look at the HAL EVAL board CAN examples rather than CubeMX output.
Up vote any posts that you find helpful, it shows what's working..
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2020-03-29 12:54 PM
Hi Clive1,
Thanks for the response. Looking at the HAL Eval Board CAN examples:
They initiate their `HAL_CAN_AddTxMessage` within their main loop, is that what you're suggesting when you say not to "do whole lot of block operations in an interrupt/callback that might exclude other things in the system from running" ?
In regards to your second point "Won't the HAL_CAN_IRQHandler() run callbacks, clear interrupt, etc?". The documentation states:
(#) Special care should be taken for CAN_IT_RX_FIFO0_MSG_PENDING and
CAN_IT_RX_FIFO1_MSG_PENDING notifications. These notifications trig
the callbacks HAL_CAN_RxFIFO0MsgPendingCallback() and
HAL_CAN_RxFIFO1MsgPendingCallback(). User has two possible options
here.
(++) Directly get the Rx message in the callback, using
HAL_CAN_GetRxMessage().
(++) Or deactivate the notification in the callback without
getting the Rx message. The Rx message can then be got later
using HAL_CAN_GetRxMessage(). Once the Rx message have been
read, the notification can be activated again.
Again looking at the HAL EVAL Board CAN examples within stm32f4xx_it.c, they have the following interrupt:
/******************************************************************************/
/* STM32F4xx Peripherals Interrupt Handlers */
/* Add here the Interrupt Handler for the used peripheral(s) (PPP), for the */
/* available peripheral interrupt handler's name please refer to the startup */
/* file (startup_stm32f4xx.s). */
/******************************************************************************/
/**
* @brief This function handles CAN1 RX0 interrupt request.
* @param None
* @retval None
*/
void CANx_RX_IRQHandler(void)
{
HAL_CAN_IRQHandler(&CanHandle);
}
While as the function description states looking at startup_stm32f4xx.s yields the following options for possible interrupts:
DCD CAN1_TX_IRQHandler ; CAN1 TX
DCD CAN1_RX0_IRQHandler ; CAN1 RX0
DCD CAN1_RX1_IRQHandler ; CAN1 RX1
DCD CAN1_SCE_IRQHandler ; CAN1 SCE
Which makes sense as in the main.h they are stating:
#define CANx_RX_IRQHandler CAN1_RX0_IRQHandler
Therefore their receive interrupt is the same as mine, while the main difference is that they are sending in their main loop. I can test this and provide further results.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2020-03-29 2:23 PM
Update:
I've replicated the HAL EVAL board CAN Example (https://github.com/STMicroelectronics/STM32CubeF4/tree/master/Projects/STM324xG_EVAL/Examples/CAN/CAN_Networking)
However I'm still in the same position, that being able to send messages and know that a message is pending via:
HAL_CAN_IsTxMessagePending
While still not receiving any messages. Something strange about the linked github example above is that I don't see anywhere where they use:
HAL_CAN_RegisterCallback
to actually register the HAL_CAN_RxFifo0MsgPendingCallback, therefore I'm equally confused as to how this is a working example
