cancel
Showing results for 
Search instead for 
Did you mean: 

HAL_CAN_Transmit timeout error

Armani.Pejman
Associate II
Posted on November 14, 2015 at 11:22

Hello, I'm trying to communicate with a STM32f4x9 EVAL board and a STM32F429-Discovery board via CAN Bus,

I am using MCP2551 transceiver IC for Discovery board, I know that CAN1 is being used by LCD and CAN2 is used by USB OTG. So I de-soldered the C53 (4k7 uf) capacitor of Discovery board (according to a video on

https://www.youtube.com/watch?v=4fYoXGiIdDs

), I have tested everything, wirings, HAL configs for CAN, etc.. But I'm getting timeout when I call the HAL_CAN_Transmit function. I am using pure STMCube examples (STM32F4x9_EVAL\Examples\CAN\CAN_Networking), I re-configured the same example for Discovery board, using CAN2 instead of CAN1. Here is my wiring schematic: 0690X000006035cQAA.jpg I did not touch the Eval example, but here is my code for Discovery board:

bool CANWorker::init_HAL_CAN()
{
// Placed in MCP file:
GPIO_InitTypeDef GPIO_InitStruct;
/*##-1- Enable peripherals and GPIO Clocks #################################*/
/* CAN2 Periph clock enable */
CANx_CLK_ENABLE();
/* Enable GPIO clock ****************************************/
CANx_GPIO_CLK_ENABLE();
/*##-2- Configure peripheral GPIO ##########################################*/ 
/* CAN2 TX GPIO pin configuration */
GPIO_InitStruct.Pin = CANx_TX_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FAST;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Alternate = CANx_TX_AF;
HAL_GPIO_Init(CANx_TX_GPIO_PORT, &GPIO_InitStruct);
/* CAN2 RX GPIO pin configuration */
GPIO_InitStruct.Pin = CANx_RX_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FAST;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Alternate = CANx_RX_AF;
HAL_GPIO_Init(CANx_TX_GPIO_PORT, &GPIO_InitStruct);
/*##-3- Configure the NVIC #################################################*/
/* NVIC configuration for CAN2 Reception complete interrupt */
HAL_NVIC_SetPriority(CANx_RX_IRQn, 1, 0);
HAL_NVIC_EnableIRQ(CANx_RX_IRQn);
CAN_FilterConfTypeDef sFilterConfig;
static CanTxMsgTypeDef TxMessage;
static CanRxMsgTypeDef RxMessage;
/*##-1- Configure the CAN peripheral #######################################*/
_canHandle.Instance = CAN2;
_canHandle.pTxMsg = &TxMessage;
_canHandle.pRxMsg = &RxMessage;
_canHandle.Init.TTCM = DISABLE;
_canHandle.Init.ABOM = DISABLE;
_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;
_canHandle.Init.BS1 = CAN_BS1_6TQ;
_canHandle.Init.BS2 = CAN_BS2_8TQ;
_canHandle.Init.Prescaler = 2;
if(HAL_CAN_Init(&_canHandle) != HAL_OK)
{
/* Initialization Error */
Error_Handler();
return false;
}
/*##-2- Configure the CAN Filter ###########################################*/
sFilterConfig.FilterNumber = 14;
sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
sFilterConfig.FilterIdHigh = 0x0000;
sFilterConfig.FilterIdLow = 0x0000;
sFilterConfig.FilterMaskIdHigh = 0x0000;
sFilterConfig.FilterMaskIdLow = 0x0000;
sFilterConfig.FilterFIFOAssignment = 0;
sFilterConfig.FilterActivation = ENABLE;
sFilterConfig.BankNumber = 14;
if(HAL_CAN_ConfigFilter(&_canHandle, &sFilterConfig) != HAL_OK)
{
/* Filter configuration Error */
Error_Handler();
return false;
}
/*##-3- Configure Transmission process #####################################*/
_canHandle.pTxMsg->StdId = 0x321;
_canHandle.pTxMsg->ExtId = 0x01;
_canHandle.pTxMsg->RTR = CAN_RTR_DATA;
_canHandle.pTxMsg->IDE = CAN_ID_STD;
_canHandle.pTxMsg->DLC = 2;
return true;
}

void HAL_CAN_RxCpltCallback(CAN_HandleTypeDef* CanHandle)
{
if ((CanHandle->pRxMsg->StdId == 0x321)&&(CanHandle->pRxMsg->IDE == CAN_ID_STD) && (CanHandle->pRxMsg->DLC == 2))
{
LED_Display(CanHandle->pRxMsg->Data[0]);
ubKeyNumber = CanHandle->pRxMsg->Data[0];
}
/* Receive */
if(HAL_CAN_Receive_IT(CanHandle, CAN_FIFO0) != HAL_OK)
{
/* Reception Error */
//Error_Handler();
}
}

CANWorker::CANWorker ()
{
init_HAL_CAN();
BSP_PB_Init(BUTTON_KEY, BUTTON_MODE_GPIO);
/*##-2- Start the Reception process and enable reception interrupt #########*/
if(HAL_CAN_Receive_IT(&_canHandle, CAN_FIFO0) != HAL_OK)
{
/* Reception Error */
Error_Handler();
}
/* Infinite loop */
while(1)
{
while(BSP_PB_GetState(BUTTON_KEY) == KEY_PRESSED)
{
if(ubKeyNumber == 0x4) 
{
ubKeyNumber = 0x00;
}
else
{
LED_Display(++ubKeyNumber);
/* Set the data to be transmitted */
_canHandle.pTxMsg->Data[0] = ubKeyNumber;
_canHandle.pTxMsg->Data[1] = 0xAD;
/*##-3- Start the Transmission process ###############################*/
if(HAL_CAN_Transmit(&_canHandle, 1000) != HAL_OK)
{
/* Transmition Error */
Error_Handler();
}
HAL_Delay(10);
while(BSP_PB_GetState(BUTTON_KEY) != KEY_NOT_PRESSED)
{
}
}
}
}
}

But the ''HAL_CAN_Transmit'' returns timeout, waiting for TransmitMailbox to be sent (Following codes are from : stm32f4xx_hal_can.c

/* Check End of transmission flag */
while(!(__HAL_CAN_TRANSMIT_STATUS(hcan, transmitmailbox)))
{
/* Check for the Timeout */
if(Timeout != HAL_MAX_DELAY)
{
if((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout))
{
hcan->State = HAL_CAN_STATE_TIMEOUT;
/* Process unlocked */
__HAL_UNLOCK(hcan);
return HAL_TIMEOUT;
}
}
}

What am I doing wrong? It's not because I use a MCP2551 and the EVAL board is using HVD230 transceiver instead, right? It seems that the other not does not ACK the sent frame, am I right? What causes this? #transmission #stm32 #stm32f4 #can #can #error #timeout #can-timeout
24 REPLIES 24
T J
Lead
Posted on December 28, 2017 at 01:56

Yes, I had trouble too...

did you know that the ABOM bit must be set.   /*!< Enable or disable the automatic bus-off management.

in the L95616 datasheet, page 5, the RXO pin is definitively going to your STM32 Rx pin...

You must make sure any tranmission stdID is always different from any other source. otherwise the canbus will go into an error state and then you must power cycle your whole network to clear it.

I used port pins to set a different 'ID' for each board, then they use different stdID in the frame.

The issue is that the canbus hardware checks it has the buscontrol as it transmits the stdID, after that, if two devices are using the same stdID then both will succeed past the stdID part of the frame, then if the data is not exactly the same from both transmitters, the canbus will go into fault. Then you must power cycle your whole network to clear it. (there is an error flag for that. Eventually, your code should be able to recover from a bus failed state)

If you can transmit ok onto the canbus, then you can receive it on the dongle ?

T J
Lead
Posted on December 28, 2017 at 02:13

PA12 is the Tx pin... page 40 of the data sheet.

Posted on December 28, 2017 at 01:13

Thanks.  I'm using the same code as the eval.  I've looked and I have no idea where the CAN 'ID' is set.  I don't see it in any of the code so maybe it comes from some hardware jumper or something.  So, I would say the the two boards, and maybe even the dongle have the same ID. 

I thought the transmitted packet would go to all devices on the bus and that the StdID mask would tell the receiving device(s) if they want to receive the packet.  I haven't changed the StdID of the packet (0x321).  I've setup the dongle to send a 0x321 packet across the CAN bus and the waveform is identical whether the dongle generates or the Nucleo board generates.  The documentation on the Ginkgo USB-CAN Interface adapter and software is horrible so it may not be setup correctly to display anything it sees on the CAN bus...

Another thing I'm not clear on (the short list is what I'm clear on!) is the nomenclature of the transceiver chip (L9616) and Nucleo board.  When there is a signal on the CAN bus, the RX0 pin on the L9616 has the decoded TTL level signal.  I would have thought that signal should be routed to the RX pin for the Nucleo board (PA12 in my case).  That doesn't work.  It must be routed to PA11 (CANx_TX_PIN).  Maybe CANx_TX_PIN means the pin for incoming data from a CAN transmission.  It's just backwards from what I would think which is that the TX pin should have the outgoing data to be transmitted, not the incoming data...  So, the RXO line from the transceiver goes to the CAN_TX_PIN and the TX0 line from the transceiver goes to the CAN_RX_PIN on the STM32f303.

I've been working on this thing for days now and I'm not sure I'm much closer than when I started...  Maybe we bite the bullet and buy eval boards that have working peripherals and samples..

Thanks for your suggestions.

Posted on December 28, 2017 at 20:23

Thanks Nick.  What data sheet do you have?  I have RM0316. Is there a better one?  Anyway, that's my error.  I took the Eval sample sources and changed PD0 and PD1 to PA12 and PA11 respectively.  I reversed them.  So, I changed them in the header file, rebuilt and reflashed and the performance is the same as it was. 

I still don't know how to set the CAN bus ID.  I haven't found it in docs.   Is it a hardware setting on the Nucleo boards?  I must say the documentation leaves much to be desired...

FLASH:  I was wrong.  I am now getting a CAN receive interrupt!  And I'm receiving the data that I am transmitting from the USB dongle.  I still haven't received anything on the dongle from my Nucleo board.  Nor have I received anything on the Nucleo from the other Nucleo.  I suspect that's the CAN ID issue we're working on.  How do I set the CAN ID?

Maybe there is a light at the end of the tunnel (that isn't a train!).

T J
Lead
Posted on December 28, 2017 at 21:34

Sorry for the confusion...it takes a while for the understanding to click into place.

it is a message ID.

the higher priority messages are automatically sent first by negotiation across the 'CAN-BUS'

so you must make your messages unique or you will put the bus into an error state.

so I set an address on each board separately, only used a message ID unique to that address.

all the problems stopped after that.

Don't forget, nothing will work while the 'bus' is in that error state, you will need to power cycle all connected devices to be sure its cleared.

Posted on December 28, 2017 at 20:37

Data Sheet != Reference Manual

For former describes specific parts, pins and performance, the latter describes more interior functionality across a family of parts

http://www.st.com/content/ccc/resource/technical/document/datasheet/f2/1f/e1/41/ef/59/4d/50/DM00058181.pdf/files/DM00058181.pdf/jcr:content/translations/en.DM00058181.pdf

 

PA11 CAN_RX

PA12 CAN_TX

RM0316 is for the STM32F303 parts, for the F4 parts you'll want RM0090 and the appropriate Data Sheets

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on December 28, 2017 at 21:22

Thanks Clive.  Do you know how to set the CAN device address on a Nucleo board??

Posted on December 28, 2017 at 21:30

It is not board specific. The Filter defines the Message ID which are pulled off the wire. These can describe one ID, a range or selection of them, or all of them. You need to stop thinking of this as a MAC or IP address.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on December 29, 2017 at 00:11

 ,

 ,

Ok. , I think I'm starting to get my mind right... ,  , I can understand the concept of only 1 device accepting certain packets and no 2 devices may accept the same packet ID. , So we use filters to do this. , For testing, I want the board to only , accept StdMsgID = 0x320 . , So I set the mask and ID both to 0x320 and now I don't recieve the incoming message. ,  ,I set the ID to 0x320 and the mask to 0x1fffffff and still don't get the packet. , When the mask and ID are both 0x0000 , the packet is received and its StdID is 0x320. ,  ,Is there any documentation on the filter ID/Mask implementation?

 , ,

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

 ,

sFilterConfig.FilterNumber = 0,

 ,

sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK,

 ,

sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT,

 ,

sFilterConfig.FilterIdHigh = 0x0000,

 ,

sFilterConfig.FilterIdLow = 0x320, ,  ,  ,  ,  , // works with , 0x0000

 ,

sFilterConfig.FilterIdLow = 0x0000,

 ,

sFilterConfig.FilterMaskIdHigh = 0x1fff, ,  ,// works with 0x0000

 ,

sFilterConfig.FilterMaskIdLow = 0xffff, ,  , // works with 0x0000

 ,

sFilterConfig.FilterFIFOAssignment = 0,

 ,

sFilterConfig.FilterActivation = ENABLE,

 ,

sFilterConfig.BankNumber = 14,

 ,

Thanks

Posted on December 29, 2017 at 00:19

sFilterConfig.FilterIdLow = 0x0320 << 5;    

sFilterConfig.FilterIdLow = 0;

sFilterConfig.FilterMaskIdHigh = 0x7ff << 5; 

sFilterConfig.FilterMaskIdLow = 0;
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..