A debugging method and system for lightweight embedded systems
By receiving and parsing command strings ending with special characters in a lightweight embedded system, and executing the corresponding functions or system commands, the problem of cumbersome debugging steps in existing technologies is solved, and a fast and flexible debugging method is realized.
Patent Information
- Authority / Receiving Office
- CN · China
- Patent Type
- Patents(China)
- Current Assignee / Owner
- Filing Date
- 2022-12-12
- Publication Date
- 2026-04-03
AI Technical Summary
Existing lightweight embedded systems lack effective debugging methods, resulting in complicated and inefficient debugging steps, and making debugging impossible in harsh environments.
It receives command strings terminated by special characters via serial port or network port, parses and extracts function names and parameter information, matches them against a pre-registered list of function names, and executes the corresponding function or system command. It supports the special command function generalFuc to jump to the entry address of the function to be executed, enabling fast debugging.
It improves debugging efficiency, enhances the applicability and flexibility of debugging, and enables fast and effective debugging in various environments without the need to modify and compile the code.
Smart Images

Figure CN116126690B_ABST
Abstract
Description
Technical Field
[0001] This invention relates to the field of embedded systems, and more particularly to a debugging method and system for lightweight embedded systems. Background Technology
[0002] Computer hardware is controlled by the operating system kernel. Due to security, complexity, and cumbersome reasons, users cannot directly access the kernel (nor is it necessary). A "proxy" layer needs to be added between the user and the kernel. This means receiving user operations (clicking icons, entering commands) through a graphical interface and command line, performing simple processing, and then passing it to the kernel. This simplifies user operations and ensures kernel security.
[0003] Embedded systems include systems based on Linux or WinCE kernels. These systems have large kernels and comprehensive functions, but their real-time performance is not high. Therefore, lightweight embedded systems also exist. Lightweight embedded systems are embedded software that runs on an RTOS (UCOS, BIOS, etc.) or a simple foreground / background system, rather than running on a Linux system. In these systems, there is often no supporting debugging system or the debugging system has limited applicability (only applicable to a single RTOS). During the development or field testing of embedded software, it is often necessary to view various variables in real time, or export data within a specific range of memory or file data stored in flash memory for subsequent analysis, or execute specific debugging functions, etc. In such cases, it is often necessary to add print statements or debugging statements to the source code, recompile, and then run to observe. This is not only cumbersome and wastes a lot of compilation and running time, but also destroys the context in which the problem occurred, which is not conducive to the localization of sporadic problems. In some specific harsh environments (such as when the board is installed in the whole machine and cannot be removed separately, or when the emulator has poor contact due to violent shaking), it is even impossible to mount the emulator for downloading operations. Summary of the Invention
[0004] The technical problem to be solved by the present invention is to provide a debugging method and system for lightweight embedded systems, which supports common hardware interfaces, enables fast and effective debugging, and has wide applicability.
[0005] To solve the above-mentioned technical problems, the technical solution adopted by the present invention is as follows:
[0006] A debugging method for lightweight embedded systems includes the following steps:
[0007] S1) Receive a command string terminated by a special character via serial port or network port, break the frame according to the special character, and obtain the current instruction;
[0008] S2) Parse and extract the function name and parameter information from the current instruction, and match the function name and parameter information against a pre-registered list of function names. If a match is found, proceed to step S3; otherwise, proceed to step S4.
[0009] S3) If the function name is not a special command function, jump to the corresponding function entry address, process the corresponding parameters, execute the function, and jump to step S5); If the function name is a special command function, jump to the special command function entry address, obtain the entry address information of the function to be executed after the function name, process the corresponding parameters, jump to the entry address of the function to be executed, execute the function, and jump to step S5);
[0010] S4) If the function name is not a system command, terminate the parsing and return an error message, then proceed to step S5); If the function name is a system command, execute the corresponding system function, then proceed to step S5).
[0011] S5) Return to step S1) until no more command strings are received.
[0012] Furthermore, the format of the special command function is generalFuc(void(*fuc)(), char *format, a1,..., a N ), where void(*fuc)() is the entry address of the function to be executed found in the map file, and the string pointed to by char*format contains the number and type information of the parameters of the function to be executed. This string consists of conversion specifiers, a1,..., a N It is a variable parameter.
[0013] Furthermore, when the function name in step S3) is a special command function, the corresponding parameter processing includes the following steps: obtaining the value of the current variable parameter based on the address of the current variable parameter and saving it; traversing the format string, analyzing the type of the current variable parameter and recording the type information of the current variable parameter; obtaining the memory occupied by the current variable parameter based on the type of the current variable parameter; and adding the address of the current variable parameter to the memory occupied by the current variable parameter to obtain the address of the next variable parameter.
[0014] Furthermore, in step S2), the parameters include one or more of the following: unsigned integer, signed integer, 32-bit floating point, string, and function pointer.
[0015] Furthermore, in step S4), the system commands include one or more of the following: help commands, function list printing commands, and decimal / hexadecimal conversion commands for displaying number types.
[0016] This invention also proposes a lightweight embedded system, including an external interface and a mini-shell module. The mini-shell module connects to a PC via the external interface, which is either a network port or a serial port. The mini-shell module is configured to perform the following steps:
[0017] Receive command strings that end with special characters via serial port or network port, break frames according to the special characters, and obtain the current instruction;
[0018] Parse and extract the function name and parameter information from the current instruction, and match the function name and parameter information with a pre-registered list of function names;
[0019] If a matching result exists, and the function name is a special command function, jump to the entry address of the special command function, obtain the entry address information of the function to be executed after the function name, process the corresponding parameters, and then jump to the entry address of the function to be executed to execute the function; if no matching result exists, and the function name is a system command, execute the corresponding system function.
[0020] Furthermore, the mini-shell module is also configured to perform the following steps:
[0021] If a matching result exists and the function name is not a special command function, jump to the corresponding function entry address, process the corresponding parameters, and execute the function; if no matching result exists and the function name is not a system command, terminate the parsing and return an error message.
[0022] Compared with the prior art, the present invention has the following advantages:
[0023] This invention receives command strings terminated by special characters via serial port or network port. It can then fragment the command into frames based on these special characters to obtain a complete instruction. After parsing and extracting the function name and parameters from the instruction, if the function name exists in a pre-registered list of function names or is a system command, the corresponding parameters are processed for use in subsequent processes. The function name list includes special command functions, which can be configured with the entry address information of all functions. Furthermore, for special command functions, execution can jump to the entry address of the actual function to be executed, thus avoiding the need to modify and recompile code for unregistered functions and effectively improving debugging efficiency. Attached Figure Description
[0024] Figure 1 This is a schematic diagram of the framework of a lightweight embedded system according to an embodiment of the present invention.
[0025] Figure 2 This is a functional flowchart of the mini-shell module in an embodiment of the present invention.
[0026] Figure 3 This is a flowchart illustrating the workflow of a specific command function in an embodiment of the present invention.
[0027] Figure 4 This is a flowchart of the method in an embodiment of the present invention. Detailed Implementation
[0028] The present invention will be further described below with reference to the accompanying drawings and specific preferred embodiments, but this does not limit the scope of protection of the present invention.
[0029] Example 1
[0030] This embodiment proposes a lightweight embedded system, such as Figure 1 As shown, the system includes an external interface and a mini-shell module. The mini-shell module connects to the PC via the external interface. For this lightweight embedded system, the physical basis for data transmission is a serial port or Ethernet port. When using a serial port, the PC's control software is a commonly used serial port debugging assistant, such as SSCOM or XCOM. The PC interacts with the lightweight embedded system by sending strings. After the PC sends a command, the mini-shell module parses the received command characters and then calls the corresponding user function from the user function list. It can also transmit data back to the PC for subsequent analysis.
[0031] In this embodiment, after the mini-shell module receives command information with a special ending symbol through a serial port or network port, it breaks the frame according to the special ending symbol and temporarily stores the valid information in memory. The valid information is then passed as input parameters to the command parsing function. The command parsing function parses out the function name, parameter value, and number of parameters contained in the received command and compares them with the registry stored in memory beforehand. If the function name parsed from the received command exists in the registry, the function is executed once. If it does not exist in the registry, the received command is considered invalid.
[0032] In this embodiment, the commands are divided into two main categories:
[0033] The first type is function name commands. The user inputs the name of the function to be run and its parameters. The mini-shell is responsible for parsing and executing the function once. Allowed input parameters include unsigned integers, signed integers, 32-bit floating-point numbers, strings, and function pointers. The mini-shell currently does not verify the type of the input parameters; this is the user's responsibility. For parameters that are pointers (except for string pointers), the specific address must be entered. Additionally, there is a special command in the function name commands: `generalFuc`, which corresponds to `generalFuc(void(*fuc)(), char *format, a1,..., a` in the user's function list. N This command can execute any function in an embedded system, offering great flexibility.
[0034] The second category is system commands, which mainly include help commands, commands to print function lists, commands to display decimal / hexadecimal conversion of numbers, etc.
[0035] Apart from system commands, all other instructions, after being parsed, jump to the entry address of the function to be executed and wait for the corresponding function to be executed.
[0036] like Figure 2 As shown, the mini-shell module is configured to perform the following steps:
[0037] 1. Receive command strings ending with special characters via serial port or network port, break frames based on the special characters, and obtain the current instruction; specifically, the user sends a command string via serial port debugging assistant, ending with a special character. The mini-shell module interrupts the reception of data from the serial port peripheral and uses the ending character as the basis for breaking frames. It stores a complete instruction received into a temporary array and passes it to the parsing module for parsing.
[0038] 2. Parse and extract the function name and parameter information from the current instruction, and match the function name and parameter information with a pre-registered list of function names. The list of function names includes the names of registered functions and their corresponding function entry addresses. Specifically, the parsing module first extracts the function name and the number of parameters from the received instruction, and then compares the extracted function name with the pre-registered list of function names one by one to determine whether the function the user wants to execute has been registered.
[0039] 3. If a matching result exists, and the function name is a special command function `generalFuc`, jump to the special command function entry address according to the function entry address corresponding to the function name in the function name list and execute the special command function: obtain the entry address information of the function to be executed after the function name, process the corresponding parameters, and then jump to the entry address of the function to be executed to execute the function; if a matching result exists, and the function name is not a special command function, jump to the corresponding function entry address according to the function name in the function name list, process the corresponding parameters, and then execute the function; parameter processing includes: extracting the parameter information after the function name in the input command one by one, determining the type, converting the string to the real type, storing, and generating several auxiliary prompts for use in subsequent processes;
[0040] 4. If no matching result exists and the function name is a system command, execute the corresponding system function; if no matching result exists and the function name is not a system command, terminate the parsing and return an error message.
[0041] In this embodiment, the mini-shell module actually obtains the actual memory address of the function to be executed by parsing the input command and directly jumps to that address to execute the function, thereby achieving the debugging purpose. This execution method means that theoretically, as long as the address of any function is known, and this address information is added to the command and parsed by the module, the function can be executed (not all functions are allowed to be executed, such as functions in the RTOS kernel). This enhances the coverage of executable functions of this module. When a function needs to be executed but is not added to the registry, the address of the function to be executed can be input through the special command `generalFuc` to achieve the purpose of executing the function, skipping the steps of modifying code, compiling, and downloading.
[0042] The generalFuc command is explained in detail below:
[0043] Since the instruction functions registered in the function name list are basic functionalities required during debugging, such as reading and writing memory data, reading and writing specific global variable values, and reading file data, as the debugging process deepens or application requirements change, it is very likely that other functions will need to be executed for verification and observation. These functions have highly variable forms, with uncertain numbers and types of parameters, making it difficult to have a definite form. In such cases, the usual solution is to modify the code, add the information of the new functions to be executed to the registry, recompile and download it to the target device, and continue debugging, which leads to low efficiency. To solve this problem, a special command function is introduced: generalFuc(void(*fuc)(), char *format, a1,..., a NThe flexibility of this function lies in the fact that as long as the entry address of the function to be executed is known, and the parameters are entered in a style similar to that of the printf function, the function can be executed once. Furthermore, a project's map file contains the entry address information of all functions in that project, so theoretically, any function can be executed by searching through the map file. This greatly enhances the adaptability of this component.
[0044] Special command function (generalFuc(void(*fuc)(), char *format, a1, ..., a) N The command actually jumps to the entry address of the function to be executed twice. The first jump is to the registered function `generalFuc` itself. Registration means mapping the address of the function to be executed to its name. This way, when the function name is parsed from the command line, the entry point can be found, thus enabling the jump. This process is consistent with other ordinary commands. The second jump occurs when the `generalFuc` function is executed. This jump is to the actual function entry point that the user needs to execute. This entry point address information is obtained from the first parameter of `generalFuc`. Therefore, it can be seen that the special instruction contains the entry point address information needed for both jumps. The first required information is the function name `generalFuc`, which can be obtained by looking up the function name list. The second required information is the first parameter. The parameter list of this function can be divided into two categories. The first category is the first two parameters, which provide all the necessary information for the function to be executed. Among them, "void(*fuc)()" is the entry point address of the function to be executed found from `map`. The string pointed to by "char *format" contains information such as the number and types of parameters of the function to be executed. This string consists of conversion specifiers, in the form of "%d, %d, %f". The second type is for variable parameters "a1,..., a N The variable parameter is used to input the specific parameters of the function to be executed. Since the type and number of parameters of the function to be executed are unknown, variable parameters are used to deal with this situation.
[0045] The parsing and execution process of the `generalFuc` command is consistent with other commands. However, because it has variable arguments, it needs to use a series of macros provided by the `stdarg.h` header file in the C standard library to handle variable arguments. The basic principle is to obtain the address of each variable argument in sequence, starting from the fixed parameter closest to the first variable argument, based on the characteristics of parameter pushing onto the stack. The macros are defined as follows:
[0046] typedef char * va_list;
[0047] #define _INTSIZEOF(n)( (sizeof(n) + sizeof(int) - 1)&~(sizeof(int) -1) )
[0048] #define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) )
[0049] #define va_arg(ap,t)( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
[0050] #define va_end(ap)( ap = (va_list)0 )
[0051] The `_INTSIZEOF(n)` macro is for systems where memory addresses need to be aligned; it should be aligned with `sizeof(int)`. Generally, `sizeof(int)` = 4, meaning the memory address of the parameter is a multiple of 4. For example, if `sizeof(n)` is between 1 and 4, then `_INTSIZEOF(n)` = 4; if `sizeof(n)` is between 5 and 8, then `_INTSIZEOF(n)` = 8.
[0052] In order to obtain each variable parameter sequentially from the fixed parameters, va_start and va_arg make full use of the following two points:
[0053] 1. In C, when a function is called, the last parameter is first pushed onto the stack.
[0054] 2. In embedded hardware platforms, memory allocation proceeds from high-address memory to low-address memory.
[0055] The memory layout diagram of the stack is as follows:
[0056] ***High-level address***
[0057] The Nth variable parameter
[0058] ...
[0059] The second variable parameter
[0060] The first variable parameter? ap
[0061] Fixed parameters? v
[0062] ***Low address***
[0063] As seen above, `v` is the memory address of the fixed parameter. After calling `va_start`, `ap` points to the first variable parameter. This macro increments the memory address of `v` by the size of `v`, thus obtaining the address of the first variable parameter. Next, we can imagine that if we can determine the type of this variable parameter, we know how much memory it occupies; similarly, we can obtain the address of the next variable parameter. Looking at `va_arg`, it first makes `ap` point to the next variable parameter, then subtracts the size of the current variable parameter to get its memory address, performs a type conversion, and returns its value. To determine the type of each variable parameter, there are two approaches: either use default types, or include enough information in the fixed parameters for the program to determine the type of each variable parameter. In this approach, `generalFuc` allows the program to determine the type of each variable parameter by analyzing the `format` string. The final macro, `va_end`, causes `ap` to no longer point to a valid memory address.
[0064] like Figure 3 As shown, the specific workflow for processing parameters of generalFuc is as follows:
[0065] Calling va_start(ap, format) makes ap point to the first variable argument.
[0066] 2. Check each `format` parameter individually to see if it is a conversion specifier. If it is, call `va_arg(ap, type)`, where `type` is the parameter type obtained from the conversion specifier. This process retrieves each parameter value from the stack sequentially and stores and records the type information.
[0067] 3. After traversing the entire format, call va_end(ap) to make ap no longer point to a valid memory address.
[0068] 4. Execute the function based on the entry address, number of parameters, type, and other information of the function to be executed.
[0069] In this embodiment, the mini-shell module is a flexible interactive component. Through common hardware interfaces such as serial ports or Ethernet ports, field engineers can quickly and reliably send commands to the system to execute several pre-written debugging functions. It also has the capability to export real-time or historical data stored in RAM or the file system to a PC for subsequent analysis. The generalFuc command in the function name list theoretically has the ability to execute any function. This gives field personnel a great deal of freedom and effectively improves debugging efficiency.
[0070] Example 2
[0071] Based on the lightweight embedded system of Embodiment 1, this embodiment proposes a debugging method for lightweight embedded systems, such as... Figure 4 As shown, it includes the following steps:
[0072] S1) Receive a command string terminated by a special character via serial port or network port, break the frame according to the special character, and obtain the current instruction;
[0073] S2) Parse and extract the function name and parameter information from the current instruction. The parameter information includes the parameter value and the number of parameters. Match the function name and parameter information with a pre-registered list of function names. If a match is found, proceed to step S3; otherwise, proceed to step S4.
[0074] S3) If the function name is not a special command function, jump to the corresponding function entry address according to the function name in the function name list, process the corresponding parameters, execute the function, and jump to step S5); If the function name is a special command function, jump to the special command function entry address according to the function name in the function name list, obtain the entry address information of the function to be executed after the function name, process the corresponding parameters, jump to the entry address of the function to be executed, and execute the function, and jump to step S5);
[0075] S4) If the function name is not a system command, terminate the parsing and return an error message, then proceed to step S5); If the function name is a system command, execute the corresponding system function, then proceed to step S5).
[0076] S5) Return to step S1) until no more command strings are received.
[0077] In step S2 of this embodiment, the parameters include one or more of the following: unsigned integer, signed integer, 32-bit floating point, string, and function pointer.
[0078] In step S3) of this embodiment, the format of the special command function is generalFuc(void(*fuc)(), char *format, ...), where void(*fuc)() is the entry address of the function to be executed found from the map file, the string pointed to by char*format contains the number and type information of the parameters of the function to be executed, and this string is composed of conversion specifiers, ... represents variable parameters. In addition, when the function name in step S3) is a special command function, the corresponding parameter processing includes the following steps: obtaining the value of the current variable parameter according to the address of the current variable parameter and saving it, traversing the format string, analyzing the type of the current variable parameter and recording the type information of the current variable parameter, obtaining the memory occupied by the current variable parameter according to the type of the current variable parameter, and adding the address of the current variable parameter to the memory occupied by the current variable parameter to obtain the address of the next variable parameter.
[0079] In step S4 of this embodiment, the system commands include one or more of the following: help command, print function list command, and display decimal / hexadecimal conversion command for number types.
[0080] The method in this embodiment has the following advantages:
[0081] 1. Independent of any kernel, making it easy to port and use;
[0082] 2. It has low hardware requirements; a common serial port is sufficient.
[0083] 3. It can cover the basic needs of technicians in the R&D and debugging process when there is no simulator or the on-site environment does not allow the use of simulators, thereby improving the speed of problem location;
[0084] 4. It is easy to extend; commands can be extended simply by modifying the code of special command functions.
[0085] The above description is merely a preferred embodiment of the present invention and is not intended to limit the invention in any way. Although the present invention has been disclosed above with reference to preferred embodiments, it is not intended to limit the invention. Therefore, any simple modifications, equivalent changes, and alterations made to the above embodiments based on the technical essence of the present invention without departing from the scope of the present invention should fall within the protection scope of the present invention.
Claims
1. A debugging method for lightweight embedded systems, characterized in that, Includes the following steps: S1) Receive a command string terminated by a special character via serial port or network port, break the frame according to the special character, and obtain the current instruction; S2) Parse and extract the function name and parameter information from the current instruction, and match the function name and parameter information against a pre-registered list of function names. If a match is found, proceed to step S3; otherwise, proceed to step S4. S3) If the function name is not a special command function, jump to the corresponding function entry address, process the corresponding parameters, execute the function, and jump to step S5); If the function name is a special command function, jump to the special command function entry address, obtain the entry address information and parameter information of the function to be executed after the function name, process the corresponding parameters, jump to the entry address of the function to be executed, execute the function, and jump to step S5); The format of the special command function is generalFuc(void(*fuc)(), char *format, a1,..., a N ), where void(*fuc)() is the entry address of the function to be executed found in the map file, and the string pointed to by char *format contains the number and type information of the parameters of the function to be executed. This string consists of conversion specifiers, a1,..., a N These are variable arguments, which are the actual parameters required by the function to be executed. S4) If the function name is not a system command, terminate the parsing and return an error message, then proceed to step S5); If the function name is a system command, execute the corresponding system function, then proceed to step S5). S5) Return to step S1) until no more command strings are received.
2. The debugging method for lightweight embedded systems according to claim 1, characterized in that, When the function name mentioned in step S3 is a special command function, the corresponding parameter processing includes the following steps: obtain the value of the current variable parameter based on the address of the current variable parameter and save it; traverse the format string, analyze the type of the current variable parameter and record the type information of the current variable parameter; obtain the memory occupied by the current variable parameter based on the type of the current variable parameter; and add the address of the current variable parameter to the memory occupied by the current variable parameter to obtain the address of the next variable parameter.
3. The debugging method for lightweight embedded systems according to claim 1, characterized in that, In step S2), the parameters include one or more of the following: unsigned integer, signed integer, 32-bit floating point, string, and function pointer.
4. The debugging method for lightweight embedded systems according to claim 1, characterized in that, In step S4), the system commands include one or more of the following: help command, print function list command, and display decimal / hexadecimal conversion command for number types.
5. A lightweight embedded system, characterized in that, This includes an external interface and a mini-shell module. The mini-shell module connects to the PC via the external interface, which can be a network port or a serial port. The mini-shell module is configured to perform the following steps: Receive command strings that end with special characters via serial port or network port, break frames according to the special characters, and obtain the current instruction; Parse and extract the function name and parameter information from the current instruction, and match the function name and parameter information with a pre-registered list of function names; If a matching result exists, and the function name is a special command function, jump to the entry address of the special command function, obtain the entry address information and parameter information of the function to be executed after the function name, process the corresponding parameters, and then jump to the entry address of the function to be executed to execute the function; if no matching result exists, and the function name is a system command, execute the corresponding system function; the format of the special command function is generalFuc(void(*fuc)(), char *format, a1,...,a1,...). N ), where void(*fuc)() is the entry address of the function to be executed found in the map file, and the string pointed to by char *format contains the number and type information of the parameters of the function to be executed. This string consists of conversion specifiers, a1,..., a N These are variable arguments, which are the actual parameters required by the function to be executed.
6. The lightweight embedded system according to claim 5, characterized in that, The mini-shell module is also configured to perform the following steps: If a matching result exists and the function name is not a special command function, jump to the corresponding function entry address, process the corresponding parameters, and execute the function; if no matching result exists and the function name is not a system command, terminate the parsing and return an error message.
Citation Information
Patent Citations
Function information acquisition method, computing device and storage medium
CN114168489A
Identifying program units in an operating environment in a computer
EP0336552A2