[domestic MCU transplantation] transplant RT thread to domestic chip fm33lc026

Time:2022-1-2

This article was originally released by RT thread forum user @jiao96:https://club.rt-thread.org/ask/article/3020.html

abstract

Due to the needs of the project, Fudan micro fm33lc026 single chip microcomputer is used and RT is transplanted_ Thread system. Just in time for RT the official [domestic MCU transplantation] activity, take part in it on the way.

Chip parameters:

Hardware describe
CPU Cortex-M0
Dominant frequency 64MHz
SRAM 24KB
Flash 128KB

Main steps of migration:
1. Project construction
2. Add Fudan micro official library
3. Board level initialization
4. Connect serial port driver

Development tools:
Keil5, env tools, scons

Engineering construction

The chip is arm cortex M0 core, which can be modified by other BSPs of M0 core.
Because STM32 is often used and the adaptation is good, stm32f072 st nucleus is used for modification.

Copy stm32f072 st nucleus to the BSP directory and rename it fm33lc026.
[domestic MCU transplantation] transplant RT thread to domestic chip fm33lc026

Move the libraries of STM32 together to the new project directory.
[domestic MCU transplantation] transplant RT thread to domestic chip fm33lc026

Only keil5’s project was carried out, and other useless items were deleted.
[domestic MCU transplantation] transplant RT thread to domestic chip fm33lc026

Modify keil5 project.
The project project is generated by the tool through the template template, so to modify the model, you only need to modify the template Uvprojx will do.

Open template uvprojx

The modified chip model is fm33lc02x, and most of the rest will be modified automatically according to the selected chip.
[domestic MCU transplantation] transplant RT thread to domestic chip fm33lc026

Then enter linker, load the file separately and modify it.
[domestic MCU transplantation] transplant RT thread to domestic chip fm33lc026

After modifying the template, you need to use the template to generate the project. Because the project is copied from STM32, some relative paths will change, and there will be problems with the script. Please modify it first.

Modify fm33lc026 the sconstruct file in the folder, open the text document, and change the path here to the path shown in the figure.
[domestic MCU transplantation] transplant RT thread to domestic chip fm33lc026

Modify the kconfig file in fm33lc026 folder as follows.
[domestic MCU transplantation] transplant RT thread to domestic chip fm33lc026

After modification, through the env tool, menuconfig, aha, report an error.
[domestic MCU transplantation] transplant RT thread to domestic chip fm33lc026

According to the error message, you also need to modify the path of Libraries under board / kconfig.
[domestic MCU transplantation] transplant RT thread to domestic chip fm33lc026

After modification, menuconfig is opened. Now it is still the configuration of the original project. Next, you need to continue to modify, exit, generate the keil5 project, open the project, all configurations are normal, the file path can be found, and the project is built.
[domestic MCU transplantation] transplant RT thread to domestic chip fm33lc026

###Add Fudan micro official library

Next, add the official library function of Fudan micro fm33lc0xx to the path.
The original official Hal Library of STM32 needs to be replaced.
The library functions and driver files of STM32 are in the \ libraries folder, which is the folder we copied to the project just now.
We just need to enter the \ libraries folder, add the official library function folder, and modify the script to add it by ourselves.

Open the \ libraries folder and look at the file structure first.
[external chain picture transfer failed. The source station may have anti-theft chain mechanism. It is recommended to save the picture and upload it directly (img-2ohyyqcx-1631071758745)(https://oss-club.rt-thread.or…)]

Delete all Hal libraries of STM32 and find the official fm33lc0xx_ FL_ Driver library, copy it in. Meanwhile, fm33lc0xx kernel related files are also copied in. The new directory structure is as follows. Keep the driver file. The low-level driver needs to be connected to the kernel driver layer. It can be modified in the original STM32.
[domestic MCU transplantation] transplant RT thread to domestic chip fm33lc026

Modify kconfig
[domestic MCU transplantation] transplant RT thread to domestic chip fm33lc026

Go to the next folder and continue to modify kconfig.

The files in FM are configured by kconfig in board, and only S startup file. Configure it in the next section.

First in fm33lc0xx_ FL_ Driver folder.
FM33LC0xx_ FL_ Driver corresponds to stm32_ Hal library, copy a copy of stm32_ Sconscript of Hal to fm33lc0xx_ FL_ Under the driver directory, modify it.
Copy BSP \ STM32 \ libraries \ stm32f0xx_ Sconscript in Hal to fm33lc0xx_ FL_ Driver directory. Open.
[domestic MCU transplantation] transplant RT thread to domestic chip fm33lc026

Replace with the following:
[domestic MCU transplantation] transplant RT thread to domestic chip fm33lc026

Enter Hal_ Drivers folder.

Because I only adapt to the serial driver and delete useless files. Delete as shown in the figure below.
[domestic MCU transplantation] transplant RT thread to domestic chip fm33lc026

Config folder
[domestic MCU transplantation] transplant RT thread to domestic chip fm33lc026

When you modify sconscript, you add DRV according to the macro definition_ XXX. C to the project.
Emmmm, forget it. Don’t modify it. Add the driver in the future. At most, the generated project can’t find the corresponding drv# c. Basically no impact.
Use env to generate a project and report an error. Find the error location according to the error information.
[the external chain picture transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the picture and upload it directly (img-xvzapi6j-1631071758753)(https://oss-club.rt-thread.or…)]

Open the error file. The official library path has been modified in this step and needs to be modified again.
[domestic MCU transplantation] transplant RT thread to domestic chip fm33lc026

Regenerate the project successfully, open the project and add the library file successfully.
[domestic MCU transplantation] transplant RT thread to domestic chip fm33lc026

Board level initialization

Relevant library functions have been added successfully. Next, let the MCU run and enter the system.
You can see the startup processRT_ Thread official document。 Borrow a picture here.
[domestic MCU transplantation] transplant RT thread to domestic chip fm33lc026

To be modified are S startup file, RT_ hw_ board_ Init() function.

After adding the official library file, open keil5 project and you will find S startup file is still stm32f072. Here, we need to modify it.

Open the board folder, open sconscript, and modify the startup file path as follows.
[domestic MCU transplantation] transplant RT thread to domestic chip fm33lc026

There is also a kconfig file, which has nothing to do with startup. You can also modify it on the way. It is mainly the configuration menu of MCU equipment in menuconfig, which is modified to what we need.
[domestic MCU transplantation] transplant RT thread to domestic chip fm33lc026

Enter the project board folder and delete the cubemx folder of STM32.
Delete linker_ Scripts distributed loading file (distributed loading related has been configured at the front. If it is necessary to load the file, it is recommended not to delete it, and change the file content to fm33lc0xx).
OK..
Enter Env, open menuconfig, and find that the graphical configuration of the serial port is OK.
[domestic MCU transplantation] transplant RT thread to domestic chip fm33lc026

Exit menuconfig, generate the project, open the project, find that all files have been added, and then modify the code.
[domestic MCU transplantation] transplant RT thread to domestic chip fm33lc026

Perform RT_ hw_ board_ Modification of related functions in init().
Change it directly. Check the source code for specific relevant information. The code has been merged into RT_ Thread main branch.

Open DRV_ common. c. Modify relevant.
[domestic MCU transplantation] transplant RT thread to domestic chip fm33lc026

Open board c
[domestic MCU transplantation] transplant RT thread to domestic chip fm33lc026

Board level initialization is completed. The compilation of this part of the project will still report errors, because the code related to serial port driver is STM32. The docking of the driving part is described in the next part.

Docking serial driver

For equipment, refer toOfficial equipment documentation
Continue to reference a figure.
[domestic MCU transplantation] transplant RT thread to domestic chip fm33lc026

Corresponding to project:
[domestic MCU transplantation] transplant RT thread to domestic chip fm33lc026

In short, it is to write a socket layer to socket the official library functions to RT_ Within the device management layer of thread. You only need to modify the device driver framework layer, and the corresponding project is the relevant code in drivers in keil5.
Open the drivers group and find the serial port programs we want to modify, which are DRV_ usart. c,drv_ usart. h,uart_ config. h。 At the same time, for the initialization of the serial port pin, imitate the BSP package of STM32, take it out separately and put it on the board C.

The first is DRV_ usart. H file, which defines the serial port configuration structure and serial port device structure. Delete the original STM32 and modify it as follows:
Serial port configuration structure, some parts that need to be configured separately are pulled out.

/* config class */
struct _uart_config
{
    const char *name;
    void *InitTypeDef;
    IRQn_Type irq_type;
    uint32_t clockSrc;
};

Serial port structure, general, part that does not need to be modified.

/* uart dirver class */
struct _uart
{
    FL_UART_InitTypeDef  handle;
    struct _uart_config *config;
    rt_uint16_t uart_dma_flag;
    struct rt_serial_device serial;
};

drv_ usart. C file defines the serial port instance, serial port operation method function and serial port registration function. Amend as follows:
Serial port instance, according to rtconfig Configure the macro definition in H.

enum
{
#ifdef BSP_USING_UART0
    UART0_INDEX,
#endif
#ifdef BSP_USING_UART1
    UART1_INDEX,
#endif
#ifdef BSP_USING_UART4
    UART4_INDEX,
#endif
#ifdef BSP_USING_UART5
    UART5_INDEX,
#endif
#ifdef BSP_USING_LPUART0
    LPUART0_INDEX,
#endif
#ifdef BSP_USING_LPUART1
    LPUART1_INDEX,
#endif
};

static struct _uart_config uart_config[] =
{
#ifdef BSP_USING_UART0
    UART0_CONFIG,
#endif
#ifdef BSP_USING_UART1
    UART1_CONFIG,
#endif
#ifdef BSP_USING_UART4
    UART4_CONFIG,
#endif
#ifdef BSP_USING_UART5
    UART5_CONFIG,
#endif
#ifdef BSP_USING_LPUART0
    LPUART0_CONFIG,
#endif
#ifdef BSP_USING_LPUART1
    LPUART1_CONFIG,
#endif
};

The operation methods and functions of the serial port are not listed in detail here. You need to modify the functions in these structures.

static const struct rt_uart_ops _uart_ops =
{
    .configure = uart_configure,
    .control = uart_control,
    .putc = uart_putc,
    .getc = uart_getc,
    .dma_transmit = 0
};

The serial port registration function registers the serial port device to the device management layer.

int rt_hw_usart_init(void)
{
    rt_size_t obj_num = sizeof(uart_obj) / sizeof(struct _uart);
    struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
    rt_err_t result = 0;

    for (int i = 0; i < obj_num; i++)
    {
        /* init UART object */
        uart_obj[i].config = &uart_config[i];
        uart_obj[i].serial.ops    = &_uart_ops;
        uart_obj[i].serial.config = config;

        /* register UART device */
        result = rt_hw_serial_register(&uart_obj[i].serial, uart_obj[i].config->name,
                                       RT_DEVICE_FLAG_RDWR
                                       | RT_DEVICE_FLAG_INT_RX
                                       | RT_DEVICE_FLAG_INT_TX
                                       | uart_obj[i].uart_dma_flag
                                       , NULL);
        RT_ASSERT(result == RT_EOK);
    }

    return result;
}

uart_ config. H file, in DRV_ config. H contains, to assign values to the serial port configuration structure, you need to fill in the corresponding serial port interrupt vector address, etc.:

#if defined(BSP_USING_UART0)
#ifndef UART0_CONFIG
#define UART0_CONFIG                                                \
    {                                                               \
        .name = "uart0",                                            \
        .InitTypeDef = UART0,                                       \
        .irq_type = UART0_IRQn,                                    \
        .clockSrc = FL_RCC_UART0_CLK_SOURCE_APB1CLK,                \
    }
#endif /* UART0_CONFIG */
#endif /* BSP_USING_UART0 */

#if defined(BSP_USING_UART1)
#ifndef UART1_CONFIG
#define UART1_CONFIG                                                \
    {                                                               \
        .name = "uart1",                                            \
        .InitTypeDef = UART1,                                       \
        .irq_type = UART1_IRQn,                                    \
        .clockSrc = FL_RCC_UART1_CLK_SOURCE_APB1CLK,               \
    }
#endif /* UART1_CONFIG */
#endif /* BSP_USING_UART1 */

board. C into the serial pin initialization, and some other hardware on the underlying configuration.

FL_ErrorStatus FL_UART_GPIO_Init(UART_Type *UARTx)
{
    FL_ErrorStatus status = FL_FAIL;
    FL_GPIO_InitTypeDef    GPIO_InitStruct;
    if (UARTx ==  UART0)
    {
        GPIO_InitStruct.pin = FL_GPIO_PIN_13;
        GPIO_InitStruct.mode = FL_GPIO_MODE_DIGITAL;
        GPIO_InitStruct.outputType = FL_GPIO_OUTPUT_PUSHPULL;
        GPIO_InitStruct.pull = FL_DISABLE;
        GPIO_InitStruct.remapPin = FL_DISABLE;

        status = FL_GPIO_Init(GPIOA, &GPIO_InitStruct);

        GPIO_InitStruct.pin = FL_GPIO_PIN_14;
        GPIO_InitStruct.mode = FL_GPIO_MODE_DIGITAL;
        GPIO_InitStruct.outputType = FL_GPIO_OUTPUT_PUSHPULL;
        GPIO_InitStruct.pull = FL_DISABLE;
        GPIO_InitStruct.remapPin = FL_DISABLE;

        status = FL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    }
    else if (UARTx ==  UART1)
    {
        GPIO_InitStruct.pin = FL_GPIO_PIN_13;
        GPIO_InitStruct.mode = FL_GPIO_MODE_DIGITAL;
        GPIO_InitStruct.outputType = FL_GPIO_OUTPUT_PUSHPULL;
        GPIO_InitStruct.pull = FL_DISABLE;
        GPIO_InitStruct.remapPin = FL_DISABLE;

        status = FL_GPIO_Init(GPIOB, &GPIO_InitStruct);

        GPIO_InitStruct.pin = FL_GPIO_PIN_14;
        GPIO_InitStruct.mode = FL_GPIO_MODE_DIGITAL;
        GPIO_InitStruct.outputType = FL_GPIO_OUTPUT_PUSHPULL;
        GPIO_InitStruct.pull = FL_DISABLE;
        GPIO_InitStruct.remapPin = FL_DISABLE;

        status = FL_GPIO_Init(GPIOB, &GPIO_InitStruct);
    }
    else if (UARTx ==  UART4)
    {
        GPIO_InitStruct.pin = FL_GPIO_PIN_0;
        GPIO_InitStruct.mode = FL_GPIO_MODE_DIGITAL;
        GPIO_InitStruct.outputType = FL_GPIO_OUTPUT_PUSHPULL;
        GPIO_InitStruct.pull = FL_DISABLE;
        GPIO_InitStruct.remapPin = FL_DISABLE;

        status = FL_GPIO_Init(GPIOA, &GPIO_InitStruct);

        GPIO_InitStruct.pin = FL_GPIO_PIN_1;
        GPIO_InitStruct.mode = FL_GPIO_MODE_DIGITAL;
        GPIO_InitStruct.outputType = FL_GPIO_OUTPUT_PUSHPULL;
        GPIO_InitStruct.pull = FL_DISABLE;
        GPIO_InitStruct.remapPin = FL_DISABLE;

        status = FL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    }
    return status;
}

After modification, configure the serial port to the console, compile and download, and use it normally.

Light up

Finally, light the light in the main function

int main(void)
{
    FL_GPIO_InitTypeDef GPIO_InitStruct = {0};

    FL_GPIO_SetOutputPin(GPIOD, FL_GPIO_PIN_4);
    GPIO_InitStruct.pin = FL_GPIO_PIN_4;
    GPIO_InitStruct.mode = FL_GPIO_MODE_OUTPUT;
    GPIO_InitStruct.outputType = FL_GPIO_OUTPUT_PUSHPULL;
    GPIO_InitStruct.pull = FL_DISABLE;
    FL_GPIO_Init(GPIOD, &GPIO_InitStruct);
    while (1)
    {
        FL_GPIO_SetOutputPin(GPIOD, FL_GPIO_PIN_4);
        rt_thread_mdelay(500);
        FL_GPIO_ResetOutputPin(GPIOD, FL_GPIO_PIN_4);
        rt_thread_mdelay(500);
    }

}

complete.

summary

No summary, write technical documents for the first time, welcome to learn and communicate.

[domestic MCU transplantation] transplant RT thread to domestic chip fm33lc026

Recently, the shortage of chips has opened, setting off a new wave of domestic substitution. RT thread launched a domestic MCU transplantation contribution activity and invited developers to participate!
Event details:The rise of national tide! RT thread domestic MCU transplantation contribution activity started!