cancel
Showing results for 
Search instead for 
Did you mean: 

HAL_CAN_AddTxMessage never transmits

juliancarneiro
Associate

I have a simple CAN test where the CAN1 Peripheral on the STM32F446RE board is initialized using STM32CubeMX (Prescaler = 16, TimeSeg1/TimeSeg2/SyncJumpWidth = 1TQ, Mode = Normal, all parameters are DISABLED except for AutoRetransmission = ENABLE). A CAN_TxHeaderTypeDef struct is created (StdId is within the range of 0-0x7FF, ExtId = 0, IDE = CAN_ID_STD, DLC = 8, RTR = CAN_RTR_DATA, TransmitGlobalTime is DISABLED) called module. a buffer is created that just holds [0, 1, 2, 3, 4, 5, 6, 7] (8 bytes). hcan1 is initialized and started using MX_CAN1_Init and HAL_CAN_Start. Then it loops over

HAL_CAN_AddTxMessage(&hcan1, &module, buffer1, (uint32_t*)CAN_TX_MAILBOX0);
while(HAL_CAN_GetTxMailboxesFreeLevel(&hcan1) == 0U);

It passes over those 3 times and on the third time, it hangs in the while since the mailboxes never get cleared. I'm really not sure what I should do instead to fix this.

EDIT: PROBLEM IS FIXED

There was an update where the HAL Cube RetransmissionDisable field stayed as named but is actually Enable in the new code implementation. Changing that field results in the mailboxes no longer holding on to messages.

1 REPLY 1
T J
Lead

maybe you can glean an answer from this working code:

I initialised from the cube and HAL is running, but not using HAL to transmit. :(

I call the StdID or ExtID the MessageID

I only look at MsgIDs in the ranges 0x400 - 0x5FF   and  0x600-0x6FF  
 
This is my Startup init code:
 
char canRxString            [1024];
uint16_t canRxMsgID         [64];
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 HAL void CAN_Config() {
:
.
.
.
 
    //##-2- Configure the CAN Filter ###########################################
    sFilterConfig.FilterNumber 					= 0;
    sFilterConfig.FilterMode   					= CAN_FILTERMODE_IDMASK;
    sFilterConfig.FilterScale  					= CAN_FILTERSCALE_32BIT;
    sFilterConfig.FilterIdHigh 					= 0x400 << 5;  //11-bit ID in top bits
    sFilterConfig.FilterIdLow  					= 0x0000;
    sFilterConfig.FilterMaskIdHigh	  	        = 0x600 << 5; 	// resolves as 0x0400 - 0x05FF
    sFilterConfig.FilterMaskIdLow				= 0x0000;
    sFilterConfig.FilterFIFOAssignment	        = 0;
    sFilterConfig.FilterActivation	            = ENABLE;
    sFilterConfig.BankNumber 	    			= 0;
 
    if (HAL_CAN_ConfigFilter(&hcan, &sFilterConfig) != HAL_OK)
    {
        // Filter configuration Error 
        _Error_Handler(__FILE__, __LINE__);
        char string[38];
 
        sprintf( string, "Can Filter configuration Error\n\r");
        puts1( string);
    }
	
 
    //##-2- Configure the 2nd CAN Filter ###########################################
    sFilterConfig.FilterNumber 			= 1;
    sFilterConfig.FilterMode   			= CAN_FILTERMODE_IDMASK;
    sFilterConfig.FilterScale  			= CAN_FILTERSCALE_32BIT;
    sFilterConfig.FilterIdHigh 			= 0x600 << 5;  //11-bit ID in top bits		// command channel
    sFilterConfig.FilterIdLow  			= 0x0000;
    sFilterConfig.FilterMaskIdHigh		= 0x700 << 5; 	// resolves as 0x0600 - 0x06FF
    sFilterConfig.FilterMaskIdLow		= 0x0000;
    sFilterConfig.FilterFIFOAssignment	= 1;
    sFilterConfig.FilterActivation		= ENABLE;
    sFilterConfig.BankNumber 			= 1;
 
    if (HAL_CAN_ConfigFilter(&hcan, &sFilterConfig) != HAL_OK)
    {
        // Filter configuration Error 
        _Error_Handler(__FILE__, __LINE__);
        char string[38];
        sprintf( string, "Can Filter configuration Error\n\r");
       puts1( string);
    }
 
 
 
after HAL Can init code:
 
void initCairoCan(void) {
    CAN_Config();
    canRxpointerIN = 0;
    canRxMsgIN  = 0;
    canRxMsgOUT = 0;
    canRxMsgTableEMPTY = true;
    canRxMsgTableFULL = false;            
 
    for (int i = 0; i < 16; i++)
        IOCanMsgFlag[i] = false;
 
			
	
    __HAL_CAN_ENABLE_IT(&hcan, CAN_IT_FMP1);
    __HAL_CAN_ENABLE_IT(&hcan, CAN_IT_FMP0);
		
    canTxMsgIN  = 0;
    canTxMsgOUT = 0;
    canTxMsgTableEMPTY 		= true;
    canTxMsgTableFULL 		= false;
    canTxMsgTableOverflow = false;
    canTxMsgOverrun = false;
    blockCanTx = false;
 
}
 
I edited the interrupt code :
void CEC_CAN_IRQHandler(void) {
    /* USER CODE BEGIN CEC_CAN_IRQn 0 */
    CAN_IRQFlag = true;
    checkCanRxFifos();
    /* USER CODE END CEC_CAN_IRQn 0 */
    HAL_CAN_IRQHandler(&hcan);
    /* USER CODE BEGIN CEC_CAN_IRQn 1 */
 
    /* USER CODE END CEC_CAN_IRQn 1 */
}
 
 
void checkCanRxFifos(void) {
	
    int readCanBytecount;
	
    char canFifo1FullFlag = CAN->RF1R & CAN_RF1R_FMP1;
    if (canFifo1FullFlag) {
        {
            readCanBytecount = (CAN->sFIFOMailBox[1].RDTR & 0x0f);	
 
            canRxMsgBottomWord[canRxMsgIN]	= CAN->sFIFOMailBox[1].RDLR;
            canRxMsgTopWord[canRxMsgIN]	= CAN->sFIFOMailBox[1].RDHR;
 
            canRxMsgID[canRxMsgIN] = CAN->sFIFOMailBox[1].RIR >> 21;
            CAN->RF1R |= CAN_RF1R_RFOM1;   						// release FIFO 
 
            canRxMsgLength[canRxMsgIN] =	readCanBytecount;  
 
            canRxMsgIN++;
            canRxMsgIN &= 0x3F;   	// 64 entries only
            canRxMsgTableEMPTY = false;
            if (canRxMsgIN == canRxMsgOUT) canRxMsgTableFULL = true;
        }
        CAN->IER |= CAN_IER_FMPIE1;  		  				  // (11)		Set FIFO1 message pending IT enable 
    }
                     
    char canFifo0FullFlag = CAN->RF0R & CAN_RF0R_FMP0;
    if (canFifo0FullFlag) {
        {
            readCanBytecount 		= (CAN->sFIFOMailBox[0].RDTR & 0x0f);	
 
            canRxMsgBottomWord[canRxMsgIN]	= CAN->sFIFOMailBox[0].RDLR;
            canRxMsgTopWord[canRxMsgIN]	= CAN->sFIFOMailBox[0].RDHR;
 
            uint32_t canRxmsgID =  CAN->sFIFOMailBox[0].RIR >> 21;
            CAN->RF0R |= CAN_RF0R_RFOM0;  						// release FIFO 
 
            if(canRxMsgTableFULL) {	
                canRxMsgTableOverflow = true;   // now dump new frame...
            }else {
                canRxMsgID[canRxMsgIN] = canRxmsgID;
                canRxMsgLength[canRxMsgIN] = readCanBytecount;  	
                canRxMsgIN++;
                canRxMsgIN &= 0x3F;  	// 64 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,"\n\r");		// remove 2 bytes, the last comma and space
            
        }
        CAN->IER |= CAN_IER_FMPIE0;  		// (11)		Set FIFO1 message pending IT enable 
    }
    //			if (length >0)  puts(string);
 
}
inside my foreground process I call DoCan, which only checks all new RXframes before it leaves.
 
 
void DoCan(void) {
    char string[1024];
    int length = 0;
    if (canRxMsgTableOverflow) {
        canRxMsgTableOverflow = false;
        sprintf(string, "CanFlags Table has Overflowed, new frames are being dumped\n\r");   // now dump new frame...
        puts1(string);
    }
    if (canRxMsgTableFULL) {
        canRxMsgTableFULL = false;
        sprintf(string, "CanFlags Table is Full, probably missing frames now\n\r");
        puts1(string);
    }
			
    if (checkCanRxSensorFreshDataCompleted())   
        showCanSensorADCArray();
    if (haveCanString)
        showCanString();
 
           			
    while (!canRxMsgTableEMPTY) {
        int canRxMsgBytecount = canRxMsgLength[canRxMsgOUT];
					
        int16_t dataChannel 	= canRxMsgID[canRxMsgOUT];
        canRxCmdFifoBuf.d32[0] 	= canRxMsgBottomWord[canRxMsgOUT];
        canRxCmdFifoBuf.d32[1] 	= canRxMsgTopWord[canRxMsgOUT];
 
        // zero data within RxCanFrameBuffer to make sure we only use valid data, but not necessary
        canRxMsgID[canRxMsgOUT] = 0; 
        canRxMsgBottomWord[canRxMsgOUT] = 0;
        canRxMsgTopWord[canRxMsgOUT] = 0;
        canRxMsgLength[canRxMsgOUT] = 0;				
 
        /*	if (dataChannel == 0x418) 
        		while(1);
        	if (dataChannel == 0x408) 
        		while(1);
        */
        canRxMsgTableFULL = false;
        canRxMsgOUT++;
        canRxMsgOUT &= 0x3f;  		// only 16 messages
        if(canRxMsgOUT == canRxMsgIN) canRxMsgTableEMPTY = true;
			.
			.
			.
			.
		process frame here
 
 
 
 
the transmit function
if ((CAN->TSR & CAN_TSR_TME0) == CAN_TSR_TME0) // (1) 
{
 
    CAN->sTxMailBox[0].TDTR = canTxMsgLength[canTxMsgOUT];      // (2) length
    CAN->sTxMailBox[0].TDLR = canTxMsgBottomWord[canTxMsgOUT]; // (3) 4bytes
    CAN->sTxMailBox[0].TDHR = canTxMsgTopWord[canTxMsgOUT];   // (3) 4bytes
    CAN->sTxMailBox[0].TIR  = ((uint32_t)canTxMsgID[canTxMsgOUT] << 21 | CAN_TI0R_TXRQ); // (4)  // send it now if the line is idle
 
 
}
 
if ((CAN->TSR & CAN_TSR_TME1) == CAN_TSR_TME1) // (1) 
     {
if ((CAN->TSR & CAN_TSR_TME2) == CAN_TSR_TME2) // (1) 
     {
 
 
 
void CAN1_RX0_IRQHandler(void)
{
  /* USER CODE BEGIN CAN1_RX0_IRQn 0 */
    //CAN_Rx0_IRQFlag = true;
    //CAN_IRQFlag = true;
    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 */
//    CAN_Rx1_IRQFlag = true;
//    CAN_IRQFlag = true;
    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 */
}