cancel
Showing results for 
Search instead for 
Did you mean: 

Can't work on CubeIDE, but can work on MDK

SourFish
Associate II

I want to use ThreadX and a Command-Line called letter-shell with CubeIDE, used a uart lib(lwrb) but changed it to HAL, but it will crash when send an costum command. Send string is "func 123 "hello word"".

SourFish_0-1723475584804.png

Here are a few of the ways I've tried: 

First, it works well without ThreadX when using CubeIDE, still used a uart lib(lwrb) but changed it to HAL. Here is the repository(link).

SourFish_2-1723476204199.png

Second, I tried porting the program to MDK, everything is same but compiler. The project of CubeIDE and MDK are both in this repository(link). 

Third, I increased the heap and stack when using CubeIDE and ThreadX, it does not work.

/* Entry Point */
ENTRY(Reset_Handler)

/* Highest address of the user mode stack */
_estack = ORIGIN(RAM) + LENGTH(RAM);    /* end of RAM */
/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 0x800;      /* required amount of heap  */
_Min_Stack_Size = 0x1000; /* required amount of stack */

 

It's very strange, the question is not letter-shell, because it works well when not using ThreadX. I was bothered by this issue for more than two weeks.

 

Hopes for your reply.

BR

1 ACCEPTED SOLUTION

Accepted Solutions

Find why.....

The stack of my task has been set to small, I set it to 512.

 

I think the reason why it could execute on MDK is that MDK has Micro lib, printf in MDK will not use much stack.

View solution in original post

6 REPLIES 6
Pavel A.
Evangelist III

I tried porting the program to MDK, everything is same but compiler. 

Compiler AND runtime library that Just Works.

Now you see why MDK is worth the money ))  Losing two weeks is a pity.

 

Andrew Neil
Evangelist III

@SourFish wrote:

I want to use ThreadX and a Command-Line called letter-shell with CubeIDE, used a uart lib(lwrb) but changed it to HAL, but it will crash when send an costum command. .


So what have you done to debug that crash?

See the Posting Tips for some hints on debugging:

https://community.st.com/t5/community-guidelines/how-to-write-your-question-to-maximize-your-chances-to-find-a/tac-p/708193

 

>> I was bothered by this issue for more than two weeks.

So blindly changing the stack/heap wasn't driven by an understanding if they even related to the issue?

You're going to have to up your debug / explanation game, I'm not even clear what the failure is from the screen shots.

Use the debugger, understand where it's failing, where it's stuck or stopped, and the state / condition of the USART peripheral.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
SourFish
Associate II

@Tesla DeLorean @Andrew Neil @Pavel A. 

Sorry for missing some key information. Here are some additions.

The board is NUCLEO-G474RE.

The logic of my code is as follows:

VOID shellThread(ULONG id)
{
    (void)id;
    char c;

    /* usart ringbuff initialization */
    lwrb_init(&tx_ringbuf, tx_ringbuf_array, sizeof(tx_ringbuf_array));
    lwrb_init(&rx_ringbuf, rx_ringbuf_array, sizeof(rx_ringbuf_array));

    uart_init(&huart2);
    rtt_init();

    userShellInit(&shell);

    while (1)
    {
        {
            if (lwrb_read(&rx_ringbuf, &c, 1))
                shellHandler(&shell, c);

            // if (SEGGER_RTT_Read(0, &c, 1))
            //     shellHandler(&shell, c);
            tx_thread_sleep(10);
        }
    }
}

The above code is the only one task that I created, specifically using the letter-shell to handle characters.

void uart_init(UART_HandleTypeDef *huart)
{
    /* dma receive config */
    HAL_UART_Receive_DMA(huart, recv_buf, RECV_SIZE);
    __HAL_DMA_ENABLE_IT(huart->hdmarx, DMA_IT_HT);
    __HAL_DMA_ENABLE_IT(huart->hdmarx, DMA_IT_TC);
    HAL_DMA_RegisterCallback(huart->hdmarx, HAL_DMA_XFER_HALFCPLT_CB_ID, dma_recv_HT);
    HAL_DMA_RegisterCallback(huart->hdmarx, HAL_DMA_XFER_CPLT_CB_ID, dma_recv_TC);

    /* usart config */
    __HAL_UART_ENABLE_IT(huart, UART_IT_IDLE);
}

static void uart_rx_check(DMA_HandleTypeDef *hdma)
{
    static size_t old_pos;
    size_t pos;

    /* Calculate current position in buffer and check for new data available */
    pos = ARRAY_LEN(recv_buf) - __HAL_DMA_GET_COUNTER(hdma);
    if (pos > ARRAY_LEN(recv_buf)) // 数组越界保护,因为DMA COUNTER会返回错误的数值
        pos = ARRAY_LEN(recv_buf);

    if (pos != old_pos)
    {
        /* Check change in received data */
        if (pos > old_pos)
        {
            /* Current position is over previous one */
            lwrb_write(&rx_ringbuf, &recv_buf[old_pos], pos - old_pos);
        }
        else
        {
            lwrb_write(&rx_ringbuf, &recv_buf[old_pos], ARRAY_LEN(recv_buf) - old_pos);
            if (pos > 0)
            {
                lwrb_write(&rx_ringbuf, &recv_buf[0], pos);
            }
        }
        old_pos = pos; /* Save current position as old for next transfers */
    }
}

static void dma_recv_HT(struct __DMA_HandleTypeDef *hdma)
{
    uart_rx_check(hdma);
}

static void dma_recv_TC(struct __DMA_HandleTypeDef *hdma)
{
    uart_rx_check(hdma);
}

void HAL_UARTEx_IdleCallback(UART_HandleTypeDef *huart)
{
    if (__HAL_UART_GET_FLAG(huart, UART_FLAG_IDLE) != RESET)
    {
        __HAL_UART_CLEAR_IDLEFLAG(huart);
        uart_rx_check(huart->hdmarx);
    }
}

In the uart_init(&huart2); , I enabled DMA_IT_HT, DMA_IT_TC, and UART_IT_IDLE, any interrupt will write the data to the ringbuff rx_ringbuf. Then, the task will get a char from the ringbuff rx_ringbuf and use letter-shell to handle it.

int shellFunc(int argc, char *argv[])
{
    HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);
    // rtt_printf("%dparameter(s)\r\n", argc);
    uart_printf(&huart2, "%dparameter(s)\r\n", argc);
    for (unsigned char i = 0; i < argc; i++)
    {
        // rtt_printf("%s\r\n", (char *)argv[i]);
        uart_printf(&huart2, "%s\r\n", (char *)argv[i]);
    }

    return 0;
}
SHELL_EXPORT_CMD(
    SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN),
    func, shellFunc, test);

If letter-shell matched the correct command, a specific function will be executed. In this specific function I printf the 

parameter that I input.

 

The code without ThreadX differs from the above by simply replacing the task with the main function:

void app_main(void)
{
    char c;

    lwrb_init(&tx_ringbuf, tx_ringbuf_array, sizeof(tx_ringbuf_array));
    lwrb_init(&rx_ringbuf, rx_ringbuf_array, sizeof(rx_ringbuf_array));

    uart_init(&huart2);
    rtt_init();

    userShellInit(&shell);

    for (;;)
    {
        if (lwrb_read(&rx_ringbuf, &c, 1))
        {
            shellHandler(&shell, c);
        }
        HAL_Delay(10);
    }
}

 

 

Here's how I debugged:

SourFish_0-1723548646687.pngSourFish_1-1723548658756.png

SourFish_2-1723548743078.png

Break points in the loop of the task, the costume command function, the common execution part of the UART interrupt. 

Start project.

SourFish_3-1723549415396.png

Send "func 123 "hello word"" from PC, the ringbuff rx_ringbuf is written correct data.

SourFish_4-1723549681509.png

The letter-shell got the correct data from the ringbuff rx_ringbuf.

SourFish_5-1723549804042.png

The costume command function has been executed, as the first picture see.

SourFish_7-1723550037994.png

 

However, even the break point in the task still exist, it won't stop. The task can't be executed again.

SourFish_8-1723550155808.png

But UART interrupt still works, it could write correct data into the ringbuff.

SourFish_9-1723550389558.png

 

I tried to switch UART to SEGGER RTT, it's still the same phenomenon. The command still could be executed just once, then the task will not be executed again. 

 

Hopes for your reply again.

BR

 

 

 

 

 

Pavel A.
Evangelist III

The command still could be executed just once, then the task will not be executed again. 

Break in debugger while the program "does nothing". Does it spin in some error handler? (while(1)....)

Find why.....

The stack of my task has been set to small, I set it to 512.

 

I think the reason why it could execute on MDK is that MDK has Micro lib, printf in MDK will not use much stack.