hiroki_abe
@hiroki_abe

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

HAL_FDCAN_AddMessageToTxFifoQ関数でFIFOバッファにセットしたデータが出力されないことがある

解決したいこと

CPU:「STM32H723ZGT6」を使用してCAN通信処理を実装しています。
CANデータの送信処理としてHAL_FDCAN_AddMessageToTxFifoQ関数を使用しています。
この関数でCAN出力データをFIFOバッファにセット~送信していますが正常に送信されないことがあります。
この原因を突き止めたいと考えております。

分かっていること

この問題は必ず再現するわけではなく何度かCAN通信していると起きます。

ソースコード

void CanSendProc(void)
{
	int	i;
	int	box;
	uint32_t canid;
	uint32_t Tickstart;
	uint8_t sendbuf[32];
	
	// 送信間隔を300usec以上空ける
	if( gTimer.can_interval ){
		set_led( ECU_LED, FALSE );
		return;
	}
	
	if( gCan.sgptr == gCan.ssptr ){
		set_led( ECU_LED, FALSE );
		return;
	}

	FDCAN_TxHeaderTypeDef txheader;

	if( !HAL_FDCAN_GetTxFifoFreeLevel(&hfdcan1) ){

		txheader.Identifier = gCan.send[gCan.sgptr].canid;
		txheader.IdType = FDCAN_STANDARD_ID;
		txheader.TxFrameType = FDCAN_DATA_FRAME;

		switch(gCan.send[gCan.sgptr].len){
		case  0: txheader.DataLength = FDCAN_DLC_BYTES_0; break;
		case  1: txheader.DataLength = FDCAN_DLC_BYTES_1; break;
		case  2: txheader.DataLength = FDCAN_DLC_BYTES_2; break;
		case  3: txheader.DataLength = FDCAN_DLC_BYTES_3; break;
		case  4: txheader.DataLength = FDCAN_DLC_BYTES_4; break;
		case  5: txheader.DataLength = FDCAN_DLC_BYTES_5; break;
		case  6: txheader.DataLength = FDCAN_DLC_BYTES_6; break;
		case  7: txheader.DataLength = FDCAN_DLC_BYTES_7; break;
		case  8:
		case  9:
		case 10:
		case 11: txheader.DataLength = FDCAN_DLC_BYTES_8; break;
		case 12:
		case 13:
		case 14:
		case 15: txheader.DataLength = FDCAN_DLC_BYTES_12; break;
		case 16:
		case 17:
		case 18:
		case 19: txheader.DataLength = FDCAN_DLC_BYTES_16; break;
		case 20:
		case 21:
		case 22:
		case 23: txheader.DataLength = FDCAN_DLC_BYTES_20; break;
		case 24:
		case 25:
		case 26:
		case 27:
		case 28:
		case 29:
		case 30:
		case 31: txheader.DataLength = FDCAN_DLC_BYTES_24; break;
		case 32:
		case 33:
		case 34:
		case 35:
		case 36:
		case 37:
		case 38:
		case 39:
		case 40:
		case 41:
		case 42:
		case 43:
		case 44:
		case 45:
		case 46:
		case 47: txheader.DataLength = FDCAN_DLC_BYTES_32; break;
		case 48:
		case 49:
		case 50:
		case 51:
		case 52:
		case 53:
		case 54:
		case 55:
		case 56:
		case 57:
		case 58:
		case 59:
		case 60:
		case 61:
		case 62:
		case 63: txheader.DataLength = FDCAN_DLC_BYTES_48; break;
		default:
			txheader.DataLength = FDCAN_DLC_BYTES_64;
			break;
		}

		txheader.ErrorStateIndicator = FDCAN_ESI_ACTIVE;
		txheader.BitRateSwitch = FDCAN_BRS_OFF;
		if( gIO.dsw & 0x01 ){
			txheader.FDFormat = FDCAN_CLASSIC_CAN;
		}else {
			txheader.FDFormat = FDCAN_FD_CAN;
		}
		txheader.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
		txheader.MessageMarker = 0;

		set_led( ECU_LED, TRUE );

		for(i=0;i<(sizeof(sendbuf)/sizeof(sendbuf[0]));i++){
			sendbuf[i] = 0;
		}
		memcpy(sendbuf, gCan.send[gCan.sgptr].buf, sizeof(gCan.send[gCan.sgptr].buf));

		if(!get_relay(CAN_RL)){
			sci_printf(COM_SCI, "get_relay CAN_RL OFF!!!\r\n");
		}

		Tickstart = HAL_GetTick();

		if (HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &txheader, sendbuf) != HAL_OK){
			sci_printf(COM_SCI, "NOT HAL OK)\r\n");
			Error_Handler();
		}

		/* Check transmission occurred before timeout */
		while(HAL_FDCAN_IsTxBufferMessagePending(&hfdcan1, FDCAN_TX_BUFFER0) != 0)
		{
			if((HAL_GetTick() - Tickstart) > 1000)	// 1000msec
			{
				sci_printf(COM_SCI, "Send NG!!!!!\r\n");
			}
		}

		if( ++gCan.sgptr >= 256 ) gCan.sgptr = 0;
	}
}

ソースについて

以下部分で出力データをFIFOバッファにセット~送信しています。
エラーにはなっておらず正常終了しています。

		if (HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &txheader, sendbuf) != HAL_OK){
			sci_printf(COM_SCI, "NOT HAL OK)\r\n");
			Error_Handler();
		}

FIFOバッファにデータが残っていないかを以下でチェックしています。
このループは抜けているためFIFOバッファに残っているわけではないと考えています。

		/* Check transmission occurred before timeout */
		while(HAL_FDCAN_IsTxBufferMessagePending(&hfdcan1, FDCAN_TX_BUFFER0) != 0)
		{
			if((HAL_GetTick() - Tickstart) > 1000)	// 1000msec
			{
				sci_printf(COM_SCI, "Send NG!!!!!\r\n");
			}
		}

原因として何が考えられるかを知りたく、
お力をお借りできますと幸いです。よろしくお願いいたします。

0

1Answer

提示された CODE 部分に問題があると仮定すれば、sendbufのサイズが小さいのではないでしょうか?

つまり、
sizeof(gCan.send[gCan.sgptr].buf) が 32 以上と推測します。

uint8_t sendbuf[32]; の 32を gCan.send[gCan.sgptr].buf と同じサイズにするのはどうでしょう?

0Like

Comments

  1. @hiroki_abe

    Questioner

    @YearCentury
    ご回答いただきありがとうございます。
    サイズを改めて確認しました。

    gCan.send[gCan.sgptr].bufは以下で定義しておりましたので同じサイズでした。

    uint8_t buf[32];
    

    また、念の為以下デバッグ文を追加しそれぞれのサイズを確認しましたが
    sizeof sendbuf(32) buf(32)で取れたので同じサイズで認識されていました。

    sci_printf(COM_SCI, "sizeof sendbuf(%d) buf(%d)\r\n", sizeof(sendbuf), sizeof(gCan.send[gCan.sgptr].buf));
    

    恐縮ですが他に考えられる点がございましたらご教示いただけますと幸いです。
    よろしくお願いいたします。

  2. では転送されるデーター長はどこで決定されるのでしょう。

    if (HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &txheader, sendbuf) != HAL_OK){
    			sci_printf(COM_SCI, "NOT HAL OK)\r\n");
    			Error_Handler();
    		}
    

    たぶん、txheader.DataLength と思うのですが、そうだとすると、これが32以上になっている可能性があると思いますがどうでしょう。

Your answer might help someone💌