Today, I would like to share an open-source, lightweight framework designed specifically for embedded systems.
https://gitee.com/MacRsh/mr-library
Introduction to mr-library
MR framework is a lightweight framework designed specifically for embedded systems. It fully considers the resource and performance needs of embedded systems. By providing standardized device management interfaces, it greatly simplifies the difficulty of embedded application development and helps developers quickly build embedded applications.
The framework provides standardized interfaces for opening (open), closing (close), controlling (ioctl), reading (read), writing (write), etc. It decouples the application from the underlying hardware drivers. Applications do not need to understand the implementation details of the drivers.
When hardware changes, only the underlying drivers need to be adapted, and the application can seamlessly migrate to the new hardware. This greatly improves the reusability of the software and the scalability to new hardware.

Key Features
-
Standardized device access interfaces -
Decoupling application and driver development -
Simplifying the development of underlying drivers and applications -
Lightweight and easy to use, low resource consumption -
Modular design, decoupled and independently developed parts, extremely low hardware migration costs -
Supports use in bare-metal environments and operating system environments
Main Components
-
Device framework: provides standardized device access interfaces -
Memory management: dynamic memory management -
Tools: common data structures such as linked lists, queues, balanced trees, etc. -
Various functional components
Standardized Device Interface
All operations on the device can be implemented through the following interfaces:
| Interface | Description |
|---|---|
| mr_dev_register | Register device |
| mr_dev_open | Open device |
| mr_dev_close | Close device |
| mr_dev_ioctl | Control device |
| mr_dev_read | Read data from device |
| mr_dev_write | Write data to device |
Example:
struct mr_spi_dev spi_dev;
int main(void)
{
/* Register SPI10 device (CS active low) to SPI1 bus */
mr_spi_dev_register(&spi_dev, "spi1/spi10", 0, MR_SPI_CS_ACTIVE_LOW);
/* Open SPI10 device under SPI1 bus */
int ds = mr_dev_open("spi1/spi10", MR_OFLAG_RDWR);
/* Send data */
uint8_t wr_buf[] = {0x01, 0x02, 0x03, 0x04};
mr_dev_write(ds, wr_buf, sizeof(wr_buf));
/* Receive data */
uint8_t rd_buf[4] = {0};
mr_dev_read(ds, rd_buf, sizeof(rd_buf));
/* Close device */
mr_dev_close(ds);
}
Configuration Tool
MR provides a Kconfig visual configuration tool, allowing developers to configure without needing to delve into the source code.
Kconfig will automatically generate a configuration options interface based on the configuration file. Developers can easily select the functional components to enable and set related parameters through simple operations.


By modifying parameters, quickly trim the required functions. After configuration, the configuration file is automatically generated through a Python script.
Directory Structure
| Name | Description |
|---|---|
| bsp | Board Support Package |
| components | Components |
| device | Device files |
| document | Documentation |
| driver | Driver files |
| include | Library header files |
| source | Library source files |
| Kconfig | Configuration files |
| kconfig.py | Automatic configuration script |
| LICENSE | License |
Getting Started
Configuring the Kconfig Environment
Note: Kconfig is not mandatory, but recommended (installation and configuration are very quick, and subsequent tutorials will also use Kconfig as an example).
-
Verify whether the system has the Python environment installed. Run
python --versionin the command line to check the Python version (sinceKconfigdepends onpython, please installpythonif it is not present). -
Use the following command in the command line to install
Kconfig:python -m pip install windows-curses python -m pip install kconfiglib -
Run
menuconfig -hin the command line to verify whether the installation was successful.
Importing the Framework into the Project
-
Download the latest version of the source code from
GiteeorGithubrepository to your local. -
Import the source code into the directory where your project is located. For example, in the STM32 project:

Project Directory -
If the chip you are using has been adapted for
BSP, please refer to the configuration tutorial in the correspondingBSPto complete theBSPconfiguration. -
Remove unnecessary files from the
bsp,document,moduledirectories (ifGITis not needed, you can also remove the.gitfile). After completion, the directory structure is as follows:
Project Directory 1 -
Add the files to the IDE (most IDEs can automatically recognize the files under the project path, so this step is not necessary). For example, in
keil:
Project Directory Keil Add all files under the
source,device, anddriverdirectories.
Configuring Menu Options
-
Open the command line tool in the
mr-librarydirectory and runmenuconfigto configure the menu.
Project Directory 2 Note: When adding the corresponding chip driver,
Device configureandDriver configurewill be displayed. ForDriver configure, please refer to the tutorial underBSP. -
Select
Device configureand press enter to enter the menu, and configure the functions as needed.
Project Directory 3 -
After configuration is complete, press
Qto exit the menu configuration interface, and pressYto save the configuration.
Generating Configuration Files
-
Open the command line tool in the mr-librarydirectory and runpython kconfig.pyto automatically generate the configuration filemr_config.h.
Adding Include Paths
-
Add the include path of
mr-libraryin the compiler, for example, inkeil:
Project Directory 4 -
Configure automatic initialization (GCC environment), find the linking script file with the suffix
.ldunder your project (usuallylink.ld), and add the following code to the script file: Note: If you are in an environment likekeilthat can automatically generate linking scripts, please skip this step./* mr-library auto init */ . = ALIGN(4); _mr_auto_init_start = .; KEEP(*(SORT(.auto_init*))) _mr_auto_init_end = .;Example:

Project Directory 5 -
Configure GNU syntax. If you are using a non-
GCCcompiler, please enable GNU syntax. For example, inkeil:AC5:
Project Directory 6 AC6:

Project Directory 7 -
Include
#include "include/mr_lib.h"in your project. -
Add the
mr_auto_init();automatic initialization function in themainfunction.
Let’s Turn on the Light
#include "include/mr_lib.h"
/* Define LED pin (PC13)*/
#define LED_PIN_NUMBER 45
int main(void)
{
/* Automatic initialization */
mr_auto_init();
/* Open PIN device */
int ds = mr_dev_open("pin", MR_OFLAG_RDWR);
/* Set to LED pin */
mr_dev_ioctl(ds, MR_CTL_PIN_SET_NUMBER, mr_make_local(int, LED_PIN_NUMBER));
/* Set LED pin to push-pull output mode */
mr_dev_ioctl(ds, MR_CTL_PIN_SET_MODE, mr_make_local(int, MR_PIN_MODE_OUTPUT));
while(1)
{
/* Light up LED */
mr_dev_write(ds, mr_make_local(uint8_t, MR_PIN_HIGH_LEVEL), sizeof(uint8_t));
mr_delay_ms(500);
mr_dev_write(ds, mr_make_local(uint8_t, MR_PIN_LOW_LEVEL), sizeof(uint8_t));
mr_delay_ms(500);
}
}
Hello World
#include "include/mr_lib.h"
int main(void)
{
/* Automatic initialization */
mr_auto_init();
/* Open Serial-1 device */
int ds = mr_dev_open("serial1", MR_OFLAG_RDWR);
/* Output Hello World */
mr_dev_write(ds, "Hello World\r\n", sizeof("Hello World\r\n"));
while(1);
}
This article is sourced from the internet, freely conveying knowledge, and the copyright belongs to the original author. If there are any copyright issues, please contact me for removal.
