As we all know, Linux development is very convenient, because there are many open source libraries that can be used through simple installation, and real-time operating systems like Free RTOS mostly only provide system kernel functions. However, RT-Thread provides a set of general device frameworks and transplants many common component functions, such as console, file system, network protocol stack, etc., and can be developed through simple configuration, providing users with a very good solution reference.
FinSH Console
FinSH is the command line component of RT-Thread, which provides a set of operation interfaces for users to call in the command line, mainly used for debugging or viewing system information.
FinSH supports two input modes: traditional command line mode and C language interpreter mode.
RT-Thread shell commands:
version - show RT-Thread version information
list_thread - list threads
list_sem - list semaphore in system
list_event - list event in system
list_mutex - list mutex in system
list_mailbox - list mail box in system
list_msgqueue - list message queue in system
list_timer - list timer in system
list_device - list device in system
exit - return to RT-Thread shell mode.
help - RT-Thread shell help.
ps - List threads in the system.
time - Execute command with time.
free - Show the memory usage in the system.
Here is a list of field information returned after entering common commands, which helps developers understand the returned information content.
In addition to the commands that come with FinSH, FinSH also provides multiple macro interfaces to export custom commands. The exported commands can be executed directly in FinSH.
Virtual File System
DFS is a virtual file system component provided by RT-Thread. Its full name is Device File System, which is a device virtual file system. The name of the file system uses a style similar to UNIX files and folders. The directory structure is shown in the following figure:
DFS Architecture
The main features of the RT-Thread DFS component are:
-
Provides a unified POSIX file and directory operation interface for applications: read, write, poll/select, etc.
-
It supports multiple types of file systems, such as FatFS, RomFS, DevFS, etc., and provides management of common files, device files, and network file descriptors.
-
Supports various types of storage devices, such as SD Card, SPI Flash, Nand Flash, etc.
The hierarchical architecture of DFS is shown in the figure below, which is mainly divided into POSIX interface layer, virtual file system layer and device abstraction layer.
Mount Management
The initialization process of the file system is generally divided into the following steps:
-
Initializes the DFS components.
-
Initialize a file system of a specific type.
-
Create a block device on the storage.
-
Format a block device.
-
Mount the block device to the DFS directory.
-
When a file system is no longer in use, it can be unmounted.
// Register the file system
int dfs_register(const struct dfs_filesystem_ops *ops);
//Format the file system
int dfs_mkfs(const char * fs_name, const char * device_name);
// Mount the file system
int dfs_mount(const char *device_name,
const char *path,
const char *filesystemtype,
unsigned long rwflag,
const void *data);
// Unmount the file system
int dfs_unmount(const char *specialfile);
File Management
Related functions for operating files. File operations are generally based on file descriptors fd, as shown in the following figure:
Catalog Management
Functions frequently used in directory management. Operations on directories are generally based on directory addresses, as shown in the following figure:
netdev network card
Netdev (network interface device) is a network interface device, also known as a network card. Every device used for network connection can be registered as a network card. In order to adapt to more types of network cards and avoid the system's dependence on a single network card, the RT-Thread system provides a netdev component for network card management and control.
The initialization and registration of the network card is based on the protocol cluster type, so each network card corresponds to a unique protocol cluster type. The creation of the socket descriptor is based on the netdev network card, so each created socket corresponds to a unique network card. The relationship between the protocol cluster, network card and socket is shown in the following figure:
Network card structure object parameter introduction:
/* Network card structure object*/
struct netdev
{
rt_slist_t list; /* Network card list*/
char name[RT_NAME_MAX]; /* Network card name*/
ip_addr_t ip_addr; /* IP address*/
ip_addr_t netmask; /* Subnet mask address*/
ip_addr_t gw; /* Gateway address*/
ip_addr_t dns_servers[NETDEV_DNS_SERVERS_NUM]; /* DNS server address*/
uint8_t hwaddr_len; /* Hardware address length*/
uint8_t hwaddr[NETDEV_HWADDR_MAX_LEN]; /* Hardware address*/
uint16_t flags; /* NIC status bit*/
uint16_t mtu; /* Maximum transmission unit of the network card*/
const struct netdev_ops *ops; /* Network card operation callback function*/
netdev_callback_fn status_callback; /* Network card status change callback*/
netdev_callback_fn addr_callback; /* Network card address change callback*/
#ifdef RT_USING_SAL
void *sal_user_data; /* Parameter data related to the protocol cluster in the network card*/
#endif /* RT_USING_SAL */
void *user_data; /* Reserved user data*/
};
How to use
//Register network card
int netdev_register(struct netdev *netdev, const char *name, void *user_data);
//Deregister the network card
int netdev_unregister(struct netdev *netdev);
// Get the first matching network card object by status
struct netdev *netdev_get_first_by_flags(uint16_t flags);
// Get the first network card object of the specified protocol cluster type
struct netdev *netdev_get_by_family(int family);
// Get the network card object by IP address
struct netdev *netdev_get_by_ipaddr(ip_addr_t *ip_addr);
// Get the network card object by name
struct netdev *netdev_get_by_name(const char *name);
// Set the default network card
void netdev_set_default(struct netdev *netdev);
// Set the network card up/down status
int netdev_set_up(struct netdev *netdev);
int netdev_set_down(struct netdev *netdev);
// Set the DHCP function status of the network card
int netdev_dhcp_enabled(struct netdev *netdev, rt_bool_t is_enabled);
// Set the network card address information
/* Set the network card IP address */
int netdev_set_ipaddr(struct netdev *netdev, const ip_addr_t *ipaddr);
/* Set the network card gateway address */
int netdev_set_gw(struct netdev *netdev, const ip_addr_t *gw);
/* Set the network card subnet mask address*/
int netdev_set_netmask(struct netdev *netdev, const ip_addr_t *netmask);
// Set the network card DNS server address
int netdev_set_dns_server(struct netdev *netdev, uint8_t dns_num, const ip_addr_t *dns_server);
// Set the network card callback function
typedef void (*netdev_callback_fn )(struct netdev *netdev, enum netdev_cb_type type);
void netdev_set_status_callback(struct netdev *netdev, netdev_callback_fn status_callback);
// Set the callback function called when the network card address information changes
void netdev_set_addr_callback(struct netdev *netdev, netdev_callback_fn addr_callback);
// Get network card information
#define netdev_is_up(netdev)
#define netdev_is_link_up(netdev)
#define netdev_is_internet_up(netdev)
#define netdev_is_dhcp_enable(netdev)
SAL Socket Abstraction Layer
In order to adapt to more types of network protocol stacks and avoid the system's dependence on a single network protocol stack, the RT-Thread system provides a set of SAL (Socket Abstraction Layer) components, which completes the abstraction of different network protocol stacks or network implementation interfaces and provides a set of standard BSD Socket APIs to the upper layer.
The network framework structure of RT-Thread is as follows:
SAL TLS encrypted transmission function
The usage process is as follows:
-
Configure and enable support for any network protocol stack (such as lwIP protocol stack);
-
Configure and enable the MbedTLS package (currently only supports MbedTLS type encryption);
-
Configure and enable SAL_TLS function support
AT Commands
In order to facilitate users to use AT commands and simply adapt to different AT modules, RT-Thread provides AT components for AT device connection and data communication. The implementation of AT components includes two parts: client and server.
AT component resource usage:
-
AT Client function: 4.6K ROM and 2.0K RAM;
-
AT Server function: 4.0K ROM and 2.5K RAM;
-
AT CLI functionality: 1.5K ROM, almost no RAM used.
ulog log
ulog is a very concise and easy-to-use C/C++ log component. The first letter u stands for μ, which means micro. It can achieve the minimum resource usage of ROM<1K and RAM<0.2K . ulog is not only small in size, but also has very comprehensive functions. Its design concept refers to another C/C++ open source log library: EasyLogger (elog for short), and has made many improvements in functions and performance. The main features are as follows:
-
The backends for log output are diversified and can support backend forms such as serial port, network, file, flash memory, etc.
-
Log output is designed to be thread-safe and supports asynchronous output mode.
-
The log system is highly reliable and can still be used in complex environments such as ISR interrupts and Hardfault.
-
The log supports setting the output level during runtime/compilation.
-
Log content supports global filtering by keywords and tags.
-
API and log format are compatible with Linux syslog.
-
Supports dumping debug data into the log in hex format.
-
Compatible with rtdbg (RTT's early log header file) and EasyLogger's log output API.
Ulog log component architecture diagram:
utest test framework
utest (unit test) is a unit test framework developed by RT-Thread. The original intention of designing utest is to facilitate RT-Thread developers to use a unified framework interface to write test programs to achieve the purpose of unit testing, coverage testing and integration testing.
Dynamic Modules
In traditional desktop operating systems, user space and kernel space are separate. Applications run in user space, while kernel and kernel modules run in kernel space. Kernel modules can be dynamically loaded and deleted to extend kernel functions. dlmodule
RT-Thread is a software component that provides a dynamic module loading mechanism in kernel space.
POSIX interface
POSIX Threads is referred to as Pthreads. POSIX is the abbreviation of "Portable Operating System Interface". POSIX is a set of standards developed by the IEEE Computer Society to improve the compatibility of different operating systems and the portability of applications.
Power Management
RT-Thread's PM component adopts a layered design concept, separating the architecture and chip-related parts, and extracting the common parts as the core. While providing a common interface to the upper layer, it also makes it easier for the underlying driver to adapt to the component.
Summarize:
RT-Thread provides a relatively complete set of peripheral components, giving users a wide range of choices to consider actual application needs, reducing the user's workload of porting the underlying device development, and allowing users to spend more time on application implementation and stability testing.
This content is originally created by EEWORLD forum user ID.LODA . If you want to reprint or use it for commercial purposes, you must obtain the author's consent and indicate the source