cancel
Showing results for 
Search instead for 
Did you mean: 

An exception occurred after using HAL_UART_Transmit_DMA with HAL_UART_AbortReceive.

YutinhLin
Associate II

Chip model: STM32H723VGTx
Both the RX and TX buffers are allocated in the D2 domain.

1.CubMx settings are correct.
2.HAL_UART_Transmit_DMA runs normally on the first run.

However, after running HAL_UART_AbortReceive, HAL_UART_Transmit_DMA fails.

Tracing the HAL_UART_Transmit_DMA function:
The huart->gState value is always 0x33.

7 REPLIES 7
Saket_Om
ST Employee

Hello @YutinhLin 

Why you are calling HAL_UART_AbortReceive() after a transmit operation?

If your intention is to abort an ongoing transmission, you should use HAL_UART_AbortTransmit() instead.

 

 

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.
Saket_Om

I use `INFO.RX.count=CO_UART_BUF_LENGTH-(__HAL_DMA_GET_COUNTER(CO_INFO.channel->hdmarx));` to calculate the data index,
and I need to reset the index to 0 each time.

So I tried using `HAL_UART_AbortTransmit()`, but it didn't work.
Then I tried using `HAL_UART_AbortReceive()`, and it worked.

Hello @YutinhLin 

You should investigate why HAL_UART_AbortTransmit() is not working. 

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.
Saket_Om
TDK
Super User

Duplicate:

STM32H723VGTx DMA TX reboot use fail - STMicroelectronics Community

 

If you're using HAL functions, you need to abide by their rules. Calling HAL_UART_AbortReceive to abort a transmit still makes no sense.

If you feel a post has answered your question, please click "Accept as Solution".

This is a very strange phenomenon, but you don't see it as a problem.

Okay, I tried using HAL_UART_AbortTransmit() to stop the DMA transfer, but the same HAL_UART_Transmit_DMA() didn't work.

The error code for huart->gState changes to 0x32.

This is my call enable and disable function :
void CO_DMA_CRL(FunctionalState state)
{
if(state==DISABLE)
{
if(HAL_OK==HAL_UART_AbortReceive(CO_INFO.channel))
CO_INFO.dma_status=DISABLE;
if(HAL_OK==HAL_UART_AbortTransmit(CO_INFO.channel))
CO_INFO.dma_status=DISABLE;
}
else
{
CO_INFO.RX.data = (uint8_t *)co_dma_rx_data;
if(HAL_OK==HAL_UARTEx_ReceiveToIdle_DMA(CO_INFO.channel,(uint8_t*)CO_INFO.RX.data,CO_UART_BUF_LENGTH))
CO_INFO.dma_status=ENABLE;
}
}

Then I tried adding reinitialization:
MX_DMA_Init();
MX_BDMA_Init();
The error code for huart->gState became 0x33.

The HAL library was originally intended to be easy for developers to use.
Furthermore, why do the TX settings of DMA interact with the RX settings?

My initial use case was that I needed to reset the receive index to 0 each time.
As I mentioned in another post,When TX calls DMA, does the state not automatically return to IDLE after data transfer is complete?

The problem is that when using the HAL library, DMA TX fails to function properly after using HAL_UART_AbortReceive(), and re-executing MX_DMA_Init() and MX_BDMA_Init() also fails.
Do you mean I should abandon the HAL library and study the specs myself to achieve my desired development goals?

If you provide the actual code being used that replicates the problem, I will check it out.

Break it down into a few different HAL_* calls that illustrates the issue, like I did in your other thread with code that works. Not just function names, but actual code.

If you feel a post has answered your question, please click "Accept as Solution".

This is my execution function.
I don't know what other code you need.

void modbus_send_package(uint8_t dev_addr, uint8_t fun_id, uint8_t reg, uint16_t reg_count, uint16_t *send_data)
{
    uint16_t crc=0;
    uint16_t data_tmp;
    uint8_t  send_len=0;

    CO_INFO.send_func_id    = fun_id;
    CO_INFO.read_start_reg  = reg;
    CO_INFO.read_reg_count  = reg_count;
    CO_INFO.send_data       = send_data[0];

    co_dma_tx_data[0]=dev_addr;
    co_dma_tx_data[1]=fun_id;
    if(fun_id == MODBUS_FUN_ID_READ_INFO)//read holding register
    {
        co_dma_tx_data[2]=(reg>>8)&0xFF;       //start register address High byte
        co_dma_tx_data[3]=reg&0xFF;            //start register address Low byte
        co_dma_tx_data[4]=(reg_count>>8)&0xFF; //register read count High byte
        co_dma_tx_data[5]=reg_count&0xFF;      //register read count Low byte
        crc=MODBUS_CRC16(co_dma_tx_data,6);
        co_dma_tx_data[6]=(crc>>8)&0xFF;       //crc Low byte
        co_dma_tx_data[7]=crc&0xFF;            //crc High byte
        send_len=8;
    }
    else if(fun_id == MODBUS_FUN_ID_WRITE_SINGLE)   //write single register
    {
        co_dma_tx_data[2]=(reg>>8)&0xFF;       //register address High byte
        co_dma_tx_data[3]=reg&0xFF;            //register address Low byte
        data_tmp=send_data[0];
        co_dma_tx_data[4]=(data_tmp>>8)&0xFF;  //write data High byte
        co_dma_tx_data[5]=data_tmp&0xFF;       //write data Low byte
        crc=MODBUS_CRC16(co_dma_tx_data,6);
        co_dma_tx_data[6]=(crc>>8)&0xFF;       //crc Low byte
        co_dma_tx_data[7]=crc&0xFF;            //crc High byte
        send_len=8;
    }
    else if(fun_id == MODBUS_FUN_ID_WRITE_MULTI)   //write multiple register
    {
        co_dma_tx_data[2]=(reg>>8)&0xFF;       //start register address High byte
        co_dma_tx_data[3]=reg&0xFF;            //start register address Low byte
        co_dma_tx_data[4]=(reg_count>>8)&0xFF; //register write count High byte
        co_dma_tx_data[5]=reg_count&0xFF;      //register write count Low byte
        co_dma_tx_data[6]=reg_count*2;         //byte count
        for(uint16_t i=0;i<reg_count;i++)
        {
            data_tmp=send_data[i];
            co_dma_tx_data[7+i*2]=(data_tmp>>8)&0xFF;  //write data High byte
            co_dma_tx_data[8+i*2]=data_tmp&0xFF;       //write data Low byte
        }
        crc=MODBUS_CRC16(co_dma_tx_data,7+reg_count*2);
        co_dma_tx_data[7+reg_count*2]=(crc>>8)&0xFF;   //crc Low byte
        co_dma_tx_data[8+reg_count*2]=crc&0xFF;        //crc High byte
        send_len=9+reg_count*2;
    }
    else
    {
        CO_INFO.send_func_id=0;
        CO_INFO.read_start_reg=0;
        CO_INFO.read_reg_count=0;
        CO_INFO.send_data = 0;
        return;
    }

    if(HAL_OK != HAL_UART_Transmit_DMA(CO_INFO.channel, co_dma_tx_data, send_len))
    {
        DEBUG_PRINT("CO MODULE SEND DATA ERROR!!\r\n");
    }
}

void CO_DMA_CRL(FunctionalState state)
{
    if(state==DISABLE)
    {
        if(HAL_OK==HAL_UART_AbortReceive(CO_INFO.channel))
            CO_INFO.dma_status=DISABLE;
        if(HAL_OK==HAL_UART_AbortTransmit(CO_INFO.channel))
            CO_INFO.dma_status=DISABLE;
    }
    else
    {
        CO_INFO.RX.data = (uint8_t *)co_dma_rx_data;
        if(HAL_OK==HAL_UARTEx_ReceiveToIdle_DMA(CO_INFO.channel,(uint8_t*)CO_INFO.RX.data,CO_UART_BUF_LENGTH))
            CO_INFO.dma_status=ENABLE;
    }
}

modbus_send_package(MODBUS_DEVICE_ID, MODBUS_FUN_ID_READ_INFO, REG_CO_VERSION, 1, NULL);
CO_DMA_CRL(DISABLE);
CO_DMA_CRL(ENABLE);
modbus_send_package(MODBUS_DEVICE_ID, MODBUS_FUN_ID_READ_INFO, REG_CO_VERSION, 1, NULL);