2024-08-12 08:39 AM
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"".
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).
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
Solved! Go to Solution.
2024-08-14 06:11 AM
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.
2024-08-12 08:49 AM - edited 2024-08-12 08:50 AM
> 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.
2024-08-12 09:14 AM
@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:
2024-08-12 09:45 AM
>> 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.
2024-08-13 05:05 AM
@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
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:
Break points in the loop of the task, the costume command function, the common execution part of the UART interrupt.
Start project.
Send "func 123 "hello word"" from PC, the ringbuff rx_ringbuf is written correct data.
The letter-shell got the correct data from the ringbuff rx_ringbuf.
The costume command function has been executed, as the first picture see.
However, even the break point in the task still exist, it won't stop. The task can't be executed again.
But UART interrupt still works, it could write correct data into the ringbuff.
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
2024-08-13 07:12 AM
> 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)....)
2024-08-14 06:11 AM
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.