One 、FinSH Transplantation and use of
FinSH The problem of unresponsive component input
- The phenomenon : When open finsh After component , The console will print the corresponding information , The following figure says yes :
\ | /
- RT - Thread Operating System
/ | \ 3.1.5 build Jul 6 2022
2006 - 2020 Copyright by rt-thread team
do components initialization.
initialize rti_board_end:0 done
initialize finsh_system_init:0 done
RT-Thread Start......
msh >
But when entering carriage return or anything , No response . Of course, there are two possibilities for this phenomenon , One possibility is that the corresponding configuration is not turned on normally , The second is that the function receiving characters is not implemented , See the following for details
- FinSH Component in rtconfig.h Configuration in , As shown below :
/* --------------------------------- RT-Thread Kernel part --------------------------------- */
/* Represents the maximum length of the name of the kernel object , If the maximum length of the object name in the code is greater than the length defined by the macro ,
* The extra part will be cut off .*/
#define RT_NAME_MAX 8
/* Set the number of aligned bytes when aligning bytes . Regular use ALIGN(RT_ALIGN_SIZE) Do byte alignment .*/
#define RT_ALIGN_SIZE 4
/* Define the priority level of system threads ; Usually use RT_THREAD_PRIORITY_MAX-1 Define the priority of idle threads */
#define RT_THREAD_PRIORITY_MAX 32
/* Define the clock beat , by 100 It means 100 individual tick Per second , One tick by 10ms */
#define RT_TICK_PER_SECOND 1000
/* Check whether the stack overflows , If not defined, close */
#define RT_USING_OVERFLOW_CHECK
/* Define the macro to open debug Pattern , If not defined, close */
#define RT_DEBUG
/* Turn on debug Mode time : The macro is defined as 0 Indicates that the initialization information of the print component is closed , Defined as 1 When, it means that */
#define RT_DEBUG_INIT 1
/* Turn on debug Mode time : The macro is defined as 0 Indicates that the print thread switching information is turned off , Defined as 1 When, it means that */
#define RT_DEBUG_THREAD 0
/* Defining this macro indicates the use of the hook function , If not defined, close */
//#define RT_USING_HOOK
/* Defines the stack size of idle threads */
#define IDLE_THREAD_STACK_SIZE 1024
FinSH transplant
FinSH There are three ways to use components , as follows :
adopt rt_hw_console_getchar() Function to get console data
FinSH Threads are used mainly through rt_hw_console_getchar() function , Get the data entered by the console , See my previous notes for details ,STM32 transplant RT-Thread The standard version of the FinSH Components .Through the peripheral drive Data flow (stm32_getc function ) Get console data
The specific implementation method is shown in UART Transplantation of peripherals , Later, I will also post my migration process , If you need it, you can see my notes later .Through the peripheral drive Interrupt mode Get console data
The way of interruption includes DMA To get console data .
Be careful : The second and third methods are actually through RT-Thread Obtained by the peripheral driver in , Here, why will I Data flow and interruption Explain separately , Because a new problem will be introduced between them , See the following process for details
Two 、 The device is empty
The phenomenon :msh >(dev != RT_NULL) assertion failed at function:rt_device_read, line number:320
reason : This phenomenon is mainly caused when registering the device , Only when registering the device did I go back to the data stream , As shown below :
/* Configure serial port device */ result = rt_hw_serial_register(&uart_obj[i].serial, uart_obj[i].config->name, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_INT_TX , NULL);
The corresponding configuration macros are as follows :
#define RT_DEVICE_FLAG_RDONLY 0x001 /* read-only */ #define RT_DEVICE_FLAG_WRONLY 0x002 /* Just write */ #define RT_DEVICE_FLAG_RDWR 0x003 /* Reading and writing */ #define RT_DEVICE_FLAG_REMOVABLE 0x004 /* Removable */ #define RT_DEVICE_FLAG_STANDALONE 0x008 /* Independent */ #define RT_DEVICE_FLAG_SUSPENDED 0x020 /* Hang up */ #define RT_DEVICE_FLAG_STREAM 0x040 /* Flow mode */ #define RT_DEVICE_FLAG_INT_RX 0x100 /* Interrupt reception */ #define RT_DEVICE_FLAG_DMA_RX 0x200 /* DMA receive */ #define RT_DEVICE_FLAG_INT_TX 0x400 /* Interrupt sending */ #define RT_DEVICE_FLAG_DMA_TX 0x800 /* DMA send out */
Serious thinking partners will have a question , Why register data reception as Flow mode It will cause the device to be empty , It can be guessed that somewhere it caused the loss of equipment , We will find the code in shell.c In file , The device is opened by interruption , As shown in the figure below :
Now the reason has been found , There are two solutions , As shown below :
terms of settlement
When the device will be registered , Register the device by interrupting reception
take shell.c Change the sending mode in the file to the stream mode , Only need to RT_DEVICE_FLAG_INT_RX shielding , As shown below :
void finsh_set_device(const char *device_name) { rt_device_t dev = RT_NULL; RT_ASSERT(shell != RT_NULL); dev = rt_device_find(device_name); if (dev == RT_NULL) { rt_kprintf("finsh: can not find device: %s\n", device_name); return; } /* check whether it's a same device */ if (dev == shell->device) return; /* open this device and set the new device in finsh shell */ if (rt_device_open(dev, RT_DEVICE_OFLAG_RDWR | // RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_STREAM) == RT_EOK) { if (shell->device != RT_NULL) { /* close old finsh device */ rt_device_close(shell->device); rt_device_set_rx_indicate(shell->device, RT_NULL); } /* clear line buffer before switch to new device */ memset(shell->line, 0, sizeof(shell->line)); shell->line_curpos = shell->line_position = 0; shell->device = dev; rt_device_set_rx_indicate(dev, finsh_rx_ind); } }
** Be careful :** After changing to stream mode , You will find a strange phenomenon , When you use debug mode , Can receive instructions normally , But in normal operation , There is no response , Don't panic when you encounter such a phenomenon , So let's look down .
3、 ... and 、FinSH Stuck problem
The phenomenon :FinSH Thread stuck , The obvious discovery is , When using debug mode , Can receive instructions normally , But in normal operation , There is no response .
reason : After in-depth analysis , Will be in shell.c In the document finsh_getchar Function to see the use of semaphores , As shown in the figure below :
Now the reason has been found , Then we just need to release the semaphore at the appropriate time , Then we are looking to see if there is a function of signal release , Next we will find that in shell.c In file finsh_rx_ind Function is to release semaphore , As shown in the figure :
Then the new problem comes again , How to call this function , Because in shell.h There is no definition of this function in the file , Don't be afraid we'll keep looking , Last in shell.c In the document finsh_set_device Function , The function pointer that releases the semaphore will be placed in rt_device In the structure , As shown in the figure below :
Then the problem becomes simple , The solution is as follows
terms of settlement : We already know how to release semaphores , So all you need to do is Data receiving function (stm32_getc) in , After data reception , Just release the semaphore , As shown below :
/** * Receive a character data */ static int stm32_getc(struct rt_serial_device *serial) { int ch; struct stm32_uart *uart; RT_ASSERT(serial != RT_NULL); uart = rt_container_of(serial, struct stm32_uart, serial); ch = -1; if (USART_GetFlagStatus(uart->handle.Instance, USART_FLAG_RXNE) != RESET) { #if defined(SOC_SERIES_STM32L4) || defined(SOC_SERIES_STM32F7) || defined(SOC_SERIES_STM32F0) \ || defined(SOC_SERIES_STM32L0) || defined(SOC_SERIES_STM32G0) || defined(SOC_SERIES_STM32H7) \ || defined(SOC_SERIES_STM32G4) ch = uart->handle.Instance->RDR & 0xff; #else // ch = (uint16_t)uart->handle.Instance->DR & (uint16_t)0x00ff; ch = (char)USART_ReceiveData(uart->handle.Instance); #endif } /* Call the device to receive data callback , Release semaphore */ uart->serial.parent.rx_indicate(&serial->parent, 0); return ch; }
Four 、 test
After solving the problem , Enter enter on the console and respond accordingly , As shown in the figure below :