cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F7 HAL CAN Receive interrupt only once

Rob Ashworth_2
Associate II
Posted on January 25, 2017 at 20:33

I seem to have an issue with receiving CAN messages.  It is set up on an interrupt, but the interrupt only seems to fire once, and when I receive the 2nd message, nothing happens.  There seems to be very little on setting up the NVIC using the HAL library with CAN.  Can anyone see anything obvious wrong with the configuration etc.  Can transmits OK.

Hardware Is the STM32F7 DISCO board.

HAL Libraries are the latest V1.5

CAN Config:

//Initialize the CAN bus settings

void

CAN_Init

(

void

)

{

HAL_CAN_MspInit

(

&

CanHandle

)

;

}

void

CAN_Config

(

void

)

{

char

MyString

[

20

]

;

CAN_FilterConfTypeDef

sFilterConfig

;

//HAL_CAN_DeInit(&CanHandle);

/*##-1- Configure the CAN peripheral #######################################*/

CanHandle

.

Instance

=

CANx

;

//Calculation is CANCLK/(BRP*(BS1+BS2+1)) = 50/5*(7+2+1) = 1

CanHandle

.

Init

.

TTCM

=

DISABLE

;

CanHandle

.

Init

.

ABOM

=

ENABLE

;

CanHandle

.

Init

.

AWUM

=

DISABLE

;

CanHandle

.

Init

.

NART

=

DISABLE

;

CanHandle

.

Init

.

RFLM

=

DISABLE

;

CanHandle

.

Init

.

TXFP

=

DISABLE

;

CanHandle

.

Init

.

Mode

=

CAN_MODE_NORMAL

;

CanHandle

.

Init

.

SJW

=

CAN_SJW_1TQ

;

//1MBit

CanHandle

.

Init

.

BS1

=

CAN_BS1_7TQ

;

//Aim for between 70% & 85% Bit sampling point

CanHandle

.

Init

.

BS2

=

CAN_BS2_2TQ

;

//

CanHandle

.

Init

.

Prescaler

=

5

;

//2;//?

/*##-3- Configure Transmission process #####################################*/

CanHandle

.

pTxMsg

->

StdId

=

0x64

;

CanHandle

.

pTxMsg

->

ExtId

=

0x01

;

CanHandle

.

pTxMsg

->

RTR

=

CAN_RTR_DATA

;

CanHandle

.

pTxMsg

->

IDE

=

CAN_ID_STD

;

CanHandle

.

pTxMsg

->

DLC

=

8

;

if

(

HAL_CAN_Init

(

&

CanHandle

)

!=

HAL_OK

)

{

/* Initialization Error */

// Error_Handler();

}

/*##-2- Configure the CAN Filter ###########################################*/

sFilterConfig

.

FilterNumber

=

0

;

sFilterConfig

.

FilterMode

=

CAN_FILTERMODE_IDMASK

;

sFilterConfig

.

FilterScale

=

CAN_FILTERSCALE_32BIT

;

sFilterConfig

.

FilterIdHigh

=

0x0000

;

sFilterConfig

.

FilterIdLow

=

0x0000

;

sFilterConfig

.

FilterMaskIdHigh

=

0x0000

;

sFilterConfig

.

FilterMaskIdLow

=

0x0000

;

sFilterConfig

.

FilterFIFOAssignment

=

CAN_FIFO0

;

sFilterConfig

.

FilterActivation

=

ENABLE

;

sFilterConfig

.

BankNumber

=

14

;

//Set up the CAN Receive buffer and enable it

HAL_CAN_Receive_IT

(

&

CanHandle

,

CAN_FIFO0

)

;

if

(

HAL_CAN_ConfigFilter

(

&

CanHandle

,

&

sFilterConfig

)

!=

HAL_OK

)

{

/* Filter configuration Error */

// Error_Handler();

}

HAL_NVIC_SetPriority

(

CANx_RX0_IRQn

,

2

,

0

)

;

HAL_NVIC_EnableIRQ

(

CANx_RX0_IRQn

)

;

HAL_NVIC_SetPriority

(

CANx_RX1_IRQn

,

2

,

0

)

;

HAL_NVIC_EnableIRQ

(

CANx_RX1_IRQn

)

;

}

Then in the Interupt handler:

void

CAN1_RX0_IRQHandler

(

void

)

{

HAL_CAN_IRQHandler

(

&

CanHandle

)

;

// __HAL_CAN_CLEAR_FLAG(&CanHandle,CAN_IT_FMP0);

}

void

CAN1_RX1_IRQHandler

(

void

)

{

HAL_CAN_IRQHandler

(

&

CanHandle

)

;

//__HAL_CAN_CLEAR_FLAG(&CanHandle,CAN_IT_FMP0);

}

Then the code which handles what happens when the interrupt is triggered - This only get triggered on the reception of the first message.  Subsequent message are ignored....!!

void

HAL_CAN_RxCpltCallback

(

CAN_HandleTypeDef

*

RxCANHandle

)

{

uint8_t

CANData

[

8

]

;

char

DebugStr

[

20

]

;

//send debug message

CAN_TAG320_TxDataMerge

.

CAN_TAG_TxMsg

.

StdId

=

0x65

;

HAL_CAN_Transmit_IT

(

&

CanHandle

)

;

BSP_LCD_SetTextColor

(

LCD_COLOR_GREEN

)

;

BSP_LCD_SetFont

(

&

Font12

)

;

sprintf

(

DebugStr

,

'CAN Message Received %d'

,

nCANMessage

)

;

BSP_LCD_DisplayStringAt

(

200

,

195

,

(

uint8_t

*

)

DebugStr

,

LEFT_MODE

)

;

CANData

[

0

]

=

RxCANHandle

->

pRxMsg

->

Data

[

0

]

;

nCANMessage

++;

//increment the message count

}

9 REPLIES 9
Amel NASRI
ST Employee
Posted on January 26, 2017 at 10:08

Hi,

Is the CAN IQ Handler managed correctly in the stm32f7xx_it.c file?

You may refer to the CAN examples available in the Cube package (as STM32Cube_FW_F7_V1.6.0\Projects\STM32F769I_EVAL\Examples\CAN\CAN_Networking) to compare your own configuration & code with the one in the example.

There is no update in CAN driver for the new package version, you can wheck differences between pboth package versions in the Release_Notes.html file.

-Amel

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

Rob Ashworth_2
Associate II
Posted on January 26, 2017 at 11:46

Hi Amel, thank, all sorted now.  In the time it took me to download the latest libraries, I saw that I was using both CANRX0 & RX1 interrupt.  After removing RX1 reference, it all sprang into life!  When I get time I will look a little more in depth at what was going on...

HAL_NVIC_SetPriority

(

CANx_RX_IRQn

,

1

,

0

)

;

HAL_NVIC_EnableIRQ

(

CANx_RX_IRQn

)

;

// HAL_NVIC_SetPriority(CANx_RX1_IRQn, 1, 0);

// HAL_NVIC_EnableIRQ(CANx_RX1_IRQn);

Posted on April 03, 2017 at 15:53

Hello Rob, I'm having the exact same problem as you, I've already removed the RX1 reference, but the problem persists. Did you change anything else?

Thank you.
Tiago Malheiro
Associate II
Posted on May 13, 2017 at 16:31

Hi Rob,

It seems that CAN_Receive_IT() in stm32f7xx_hal_can.c disables reception interrupt upon message reception.

in your void HAL_CAN_RxCpltCallback(CAN_HandleTypeDef *CanHandle), you need to submit again the IT reception request:

void HAL_CAN_RxCpltCallback(CAN_HandleTypeDef *CanHandle)

{

 if (HAL_CAN_Receive_IT(CanHandle, 0) != HAL_OK)

  {

    /* Reception Error */

    Error_Handler();

  } 

}
David Horch
Associate
Posted on June 13, 2017 at 18:51

Hey,

You should avoid using HAL functions like HAL_CAN_Transmit_* or HAL_CAN_Receive_* inside the ISR. It might fail due to the internal locking process, although it might be very unlikely to happen. Let's assume that another instance of your program already locked CAN successfully (e.q. in the main thread/loop) and before it resets the locking state the ISR executes. The invoked HAL function will try to take the lock within the ISR, fails and will return HAL_BUSY without actually doing something.

There is a second point I saw in your code:

/*##-3- Configure Transmission process #####################################*/

CanHandle

.

pTxMsg

->

StdId

=

0x64

;

CanHandle

.

pTxMsg

->

ExtId

=

0x01

;

CanHandle

.

pTxMsg

->

RTR

=

CAN_RTR_DATA

;

CanHandle

.

pTxMsg

->

IDE

=

CAN_ID_STD

;

CanHandle

.

pTxMsg

->

DLC

=

8

;

Please check that CanHandle.pTxMsg actually points to a valid address before assigning values to the struct fields. At least withevery HAL implementations that I worked with (F1, F3, F4) you first have to assign

CanHandle.pTxMsg to an allocated memory location. For example use a statically allocated buffer:

static CanTxMsgTypeDef transmitBuffer;
/* schnipp */
CanHandle.pTxMsg = &transmitBuffer;�?�?�?�?�?�?�?�?�?

Good luck!

Joerg Wagner
Senior III
Posted on June 14, 2017 at 14:48

I have the same issue: the interrupt is called only once.

CanTx/RxMsgTypeDef is used to provide memory, nothing else than CAN is used in the application to test it properly.

In the HAL_CAN_RxCpltCallback function is the call of:

HAL_CAN_Receive_IT(CanHandle, CAN_FIFO0);

at the end of the function, but the result is always HAL_BUSY

It works when I execute

__HAL_UNLOCK(CanHandle);

before, but this should not be the final solution?

Posted on June 15, 2017 at 10:13

Joerg,

notice that there is a bug in HAL CAN V1.7 in that exact function: HAL_CAN_Receive_IT.

You need to edit the file stm32f7xx_hal_can.c and place __HAL_UNLOCK(hcan) near the end of that function:

 __HAL_CAN_ENABLE_IT(hcan, CAN_IT_EWG |
 CAN_IT_EPV |
 CAN_IT_BOF |
 CAN_IT_LEC |
 CAN_IT_ERR |
 CAN_IT_TME);
 
 /* Process unlocked */
 __HAL_UNLOCK(hcan);
 if(FIFONumber == CAN_FIFO0)
 {
 /* Enable FIFO 0 overrun and message pending Interrupt */
 __HAL_CAN_ENABLE_IT(hcan, CAN_IT_FOV0 | CAN_IT_FMP0);
 }
 else
 {
 /* Enable FIFO 1 overrun and message pending Interrupt */
 __HAL_CAN_ENABLE_IT(hcan, CAN_IT_FOV1 | CAN_IT_FMP1);
 }
 /* Return function status */
 return HAL_OK;
}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

Furthermore, as David mention, you need to ensure no other thread/ISR is locking the resource.

best,

Posted on June 15, 2017 at 11:09

Thank you so much. I felt like an idiot not able to use CAN properly.

Posted on August 24, 2017 at 09:36

Thanks Tiago,

I was migration F4 to F7.

But, CAN was not working.

CAN's HAL handler is HAL_BUSY.

So, I was compare between stm32f7xx_hal_can.c and stm32f4xx_hal_can.c.

Different point is only it in stm32f7xx_hal_can.c.

I was convinced of it by your favor.