It is said that RT thread OS developed by Chinese people has been for some time and has not been tried. After all, learning a new platform takes a lot of time and energy. The main purpose of testing RT thread this time is to use its dynamic library function. Now the Cortex-M series Arm processor is very powerful. However, because Cortex-M does not have a memory manager. The program lacks relocation function. Therefore, it is difficult to implement a shared library (lib.so) similar to linux OS ). The shared library is very important for the function expansion of the system. For example, in the controller, the function blocks need to be imported dynamically. If there is no shared library function, the newly added program library must be recompiled and downloaded together with the kernel and OS. It is more troublesome to add and update the function blocks remotely. Therefore, the shared library is very important for the embedded software controlling the device of
Getting to know RT thread
The RT thread Studio development environment is very convenient
RT thread has provided an integrated development environment RT thread studio. It is very convenient to use. In order to reduce the trouble of setting at the beginning, I purchased an Art PI development board. Developing a flashing program is very fast and smooth.
Dependency of RT thread
RT thread uses ST link as the program download tool. It needs to download and install STlink. At the same time, Python 2.7 needs to be installed
msh of RT thread
Different from other embedded OS, RT thread provides a command tool similar to Linux shell, formerly called msh. It is linked to PC through USB on the development board. You can use a serial port software. It used to be called Finsh. I don't know why it's not called shell directly?
ENV tool that can't get rid of RT thread
In the past, RT thread was developed using ENV tool. At present, it seems that the ENV tool is still indispensable for developing dynamic modules. It is used under windows cmd. Right click in the relevant directory and select conEMU Here to enter.
Make complaints about
Maybe it's some historical baggage. Some concepts, naming and usage of RT thread are a little strange, which is different from linux or other development environments. It's a little confusing for beginners. As I pointed out, when developing software, you should be very careful in naming and terminology. Try to conform to social semantics (that is, people's habits).
Another problem with RT thread is that there is a common problem with software developed by Chinese people. It is not the poor technology of the software itself, but the poor community. It is difficult to find answers to problems on the Internet. On the Internet, except for the original documents, there are few questions to answer, discuss with each other and share experience. Most articles are forwarded to each other or their own learning notes, Or the training teacher's copy. What you say is the same. If you make mistakes in one place, many places are wrong. This is the biggest confusion in using domestic software.
Using dynamic modules
Main reference [STM32H750] play art PI (VIII) -- add dynamic module This blog post doesn't seem to have encountered too many problems.
Source code from rtthread-apps It includes two programs, one is the library lib and the other is the main program hello
lib.c
#include <stdio.h> int lib_func(void) { printf("hello world from RTT::dynamic library!\n"); return 0; } int add_func(int a, int b) { return (a + b); }
main.c in the hello directory
#include <stdio.h> #include <dlfcn.h> #include <rtthread.h> #define APP_PATH "/sdcard/lib.so" typedef int (*add_func_t)(int, int); typedef void (*lib_func_t)(void); int dlmodule_sample(void) { void* handle; lib_func_t lib_function; add_func_t add_function; handle = dlopen(APP_PATH,RTLD_LAZY); if(!handle) { printf("dlopen %s failed!\n",APP_PATH); return -1; } lib_function = (lib_func_t)dlsym(handle,"lib_func"); if(!lib_function) { printf("dlsym %p failed!\n",handle); return -1; } lib_function(); add_function = (add_func_t)dlsym(handle,"add_func"); if(!add_function) { printf("dlsym %p failed!\n",handle); return -1; } printf("add_function result is:%d\n",add_function(3,4)); dlclose(handle); return 0; } MSH_CMD_EXPORT(dlmodule_sample, dlmodule sample); int main(void) { printf("rt-thread dynamic module Test!\n"); return 0; }
By careful comparison, we have made a little change.
The original #define APP_PATH "/lib.so" is changed to
# define APP_PATH "/sdcard/lib.so". Maybe you can set it somewhere and use / lib.so.
Besides, I don't know why
MSH_CMD_EXPORT(dlmodule_sample, dlmodule sample); It doesn't work. This statement can transform the dlmount_sample program into a msh command. Run the program under msh. I later called dlmount_sample program directly in main.
Compiled commands
set RTT_ROOT=C:\RT-ThreadStudio\workspace\art_pi_module\rt-thread set BSP_ROOT=C:\RT-ThreadStudio\workspace\art_pi_module scons --target=ua -s scons --lib=lib scons --app=hello
Further testing
[STM32H750] play art PI (VIII) -- add dynamic module This is the end of the article, but there seems to be some things to do to really use dynamic modules
Calling lib.so Library in studio project file
This seems relatively simple. Copy dlmount_sample to the main of the project.
/* * Copyright (c) 2006-2020, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2020-09-02 RT-Thread first version */ #include <rtthread.h> #include <rtdevice.h> #include "drv_common.h" #include <stdio.h> #include <dlfcn.h> #define LED_PIN GET_PIN(I, 8) #define APP_PATH "/sdcard/lib.so" typedef int (*add_func_t)(int, int); typedef void (*lib_func_t)(void); int dlmodule_sample(void) { void* handle; lib_func_t lib_function; add_func_t add_function; handle = dlopen(APP_PATH,RTLD_LAZY); if(!handle) { printf("dlopen %s failed!\n",APP_PATH); return -1; } lib_function = (lib_func_t)dlsym(handle,"lib_func"); if(!lib_function) { printf("dlsym %p failed!\n",handle); return -1; } lib_function(); //add function add_function = (add_func_t)dlsym(handle,"add_func"); if(!add_function) { printf("dlsym %p failed!\n",handle); return -1; } printf("add_function result is:%d\n",add_function(3,4)); dlclose(handle); return 0; } int main(void) { rt_uint32_t count = 1; printf("rt-thread dynamic module Test!\n"); rt_thread_mdelay(500); dlmodule_sample(); rt_pin_mode(LED_PIN, PIN_MODE_OUTPUT); while(count++) { rt_thread_mdelay(500); rt_pin_write(LED_PIN, PIN_HIGH); rt_thread_mdelay(500); rt_pin_write(LED_PIN, PIN_LOW); } return RT_EOK; } #include "stm32h7xx.h" static int vtor_config(void) { /* Vector Table Relocation in Internal QSPI_FLASH */ SCB->VTOR = QSPI_BASE; return 0; } INIT_BOARD_EXPORT(vtor_config);
The only problem here is that when the main thread is run, the sdcard cannot be found when the lib.so file is opened at the beginning of mount sdcard. Therefore, I added one before calling dlmount_sample
rt_thread_mdelay(500);
Ensure that the sdcard mount is successful.
lib calls external functions
How to call back the main function in the lib program. Here we use the C language callback method. It is feasible after testing.
lib.c
#include <stdio.h> int lib_func(void) { printf("hello world from RTT::dynamic library!\n"); return 0; } int add_func(int a, int b) { return (a + b); } int handle(int y, int (*Callback)(int)){ printf("Entering Handle Function. \n"); Callback(y); printf("Leaving Handle Function. \n"); return 0; }
dlmodule_sample subroutine
#include <rtdevice.h> #include "drv_common.h" #include <stdio.h> #include <dlfcn.h> #define LED_PIN GET_PIN(I, 8) #define APP_PATH "/sdcard/lib.so" typedef int (*add_func_t)(int, int); typedef void (*lib_func_t)(void); typedef void (*handle_func_t)(int,int (*Callback)(int)); int Callback(int x) // Callback Function 1 { printf("Hello, this is Callback_1: x = %d ", x); return 0; } int dlmodule_sample(void) { void* handle; lib_func_t lib_function; add_func_t add_function; handle_func_t handle_function; handle = dlopen(APP_PATH,RTLD_LAZY); if(!handle) { printf("dlopen %s failed!\n",APP_PATH); return -1; } lib_function = (lib_func_t)dlsym(handle,"lib_func"); if(!lib_function) { printf("dlsym %p failed!\n",handle); return -1; } lib_function(); //add function add_function = (add_func_t)dlsym(handle,"add_func"); if(!add_function) { printf("dlsym %p failed!\n",handle); return -1; } printf("add_function result is:%d\n",add_function(3,4)); // callback handle_function = (handle_func_t)dlsym(handle,"handle"); if(!handle_function) { printf("dlsym %p failed!\n",handle); return -1; } handle_function(100,&Callback); dlclose(handle); return 0; }
Conclusion
Completed the preliminary test of RT thread OS external module call. External module call is very useful for embedded programs, perhaps because the external module function of RT thread makes me fall in love with RT thread.