当前位置:网站首页>Problems encountered in using RT thread component fish

Problems encountered in using RT thread component fish

2022-07-06 19:10:00 Pouring rookie

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 :

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

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

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

  1. When the device will be registered , Register the device by interrupting reception

  2. 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 :

原网站

版权声明
本文为[Pouring rookie]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/187/202207061113320507.html

随机推荐