本帖最后由 _Prtemly 于 2025-4-28 14:41 编辑

1. 准备工作

1.1 硬件准备

  • ME32G030AC8T6开发板一张。
  • 调试器(如J-Link、ST-Link等)
  • 必要的连接线缆,ME32G030的开发板一端就是标准20p的简牛插座,和J-Link直接对插即可,如图:

Snipaste_2025-04-28_14-04-16.png

1.2 软件准备

2. 创建基础工程


  • 在开发环境中创建一个新的工程,或者直接copy一份sdk的测试工程也可以。
  • 添加必要的lib库文件。

3. 添加RT-Thread Nano到工程

3.1 复制RT-Thread Nano文件

将RT-Thread Nano的以下目录复制到你的工程目录中:

rtthread-nano/
  • ├── include
  • ├── libcpu
  • ├── src
  • └── components
  • 复制代码

    3.2 添加文件到工程

    在开发环境中添加以下文件到工程:

    • rtthread-nano/src/*.c
    • rtthread-nano/libcpu/arm/cortex-m0/*.c

    3.3 包含头文件路径

    添加以下头文件路径到工程设置:

    • rtthread-nano/include
    • rtthread-nano/libcpu/arm/cortex-m0

    配置好的工程目录如下图:

    Snipaste_2025-04-28_14-11-53.png

    4. 配置RT-Thread Nano

    4.1 修改rtconfig.h创建或修改rtconfig.h文件,

    配置RT-Thread Nano的基本参数:

    #pragma once

    #define RT_THREAD_PRIORITY_MAX  8
    #define RT_TICK_PER_SECOND  1000
    #define RT_ALIGN_SIZE   4
    #define RT_NAME_MAX    8
    #define RT_USING_COMPONENTS_INIT
    #define RT_USING_USER_MAIN
    #define RT_MAIN_THREAD_STACK_SIZE     512

    // <e>Software timers Configuration
    // <i> Enables user timers
    #define RT_USING_TIMER_SOFT         0
    #if RT_USING_TIMER_SOFT == 0
        #undef RT_USING_TIMER_SOFT
    #endif
    // <o>The priority level of timer thread <0-31>
    //  <i>Default: 4
    #define RT_TIMER_THREAD_PRIO        4
    // <o>The stack size of timer thread <0-8192>
    //  <i>Default: 512
    #define RT_TIMER_THREAD_STACK_SIZE  512
    // </e>

    #define RT_TIMER_THREAD_PRIO        4
    #define RT_TIMER_THREAD_STACK_SIZE  512

    // <c1>Using Semaphore
    //  <i>Using Semaphore
    #define RT_USING_SEMAPHORE
    // </c>
    // <c1>Using Mutex
    //  <i>Using Mutex
    //#define RT_USING_MUTEX
    // </c>
    // <c1>Using Event
    //  <i>Using Event
    //#define RT_USING_EVENT
    // </c>
    // <c1>Using MailBox
    //  <i>Using MailBox
    #define RT_USING_MAILBOX
    // </c>
    // <c1>Using Message Queue
    //  <i>Using Message Queue
    //#define RT_USING_MESSAGEQUEUE
    // </c>
    // </h>

    // <h>Memory Management Configuration
    // <c1>Memory Pool Management
    //  <i>Memory Pool Management
    //#define RT_USING_MEMPOOL
    // </c>
    // <c1>Dynamic Heap Management(Algorithm: small memory )
    //  <i>Dynamic Heap Management
    #define RT_USING_HEAP
    #define RT_USING_SMALL_MEM
    // </c>
    // <c1>using tiny size of memory
    //  <i>using tiny size of memory
    //#define RT_USING_TINY_SIZE
    // </c>
    // </h>

    // <h>Console Configuration
    // <c1>Using console
    //  <i>Using console
    #define RT_USING_CONSOLE
    // </c>
    // <o>the buffer size of console <1-1024>
    //  <i>the buffer size of console
    //  <i>Default: 128  (128Byte)
    #define RT_CONSOLEBUF_SIZE          128
    // </h>


    4.2 板级硬件配置

    board.c中配置内存堆:

    #include "me32g030.h"

  • extern void SystemCoreClockUpdate (void);

  • #if defined(RT_USING_USER_MAIN) && defined(RT_USING_HEAP)
  • #ifdef __ICCARM__
  • // Use *.icf ram symbal, to avoid hardcode.
  • extern char __ICFEDIT_region_IRAM1_end__;
  • #define MCU_SRAM_END            &__ICFEDIT_region_IRAM1_end__
  • #else
  • // 根据自己的MCU不同修改
  • #define MCU_SRAM_SIZE           8
  • // 根据自己的MCU不同修改
  • #define MCU_SRAM_END            (0x10000000 + MCU_SRAM_SIZE * 1024)
  • #endif

  • #ifdef __ICCARM__
  • #pragma section="HEAP"
  • #define HEAP_BEGIN    (__segment_end("HEAP"))
  • #else
  • extern int Image$RW_IRAM1$ZI$Limit;
  • #define HEAP_BEGIN    (&Image$RW_IRAM1$ZI$Limit)
  • #endif
  • #define HEAP_END                MCU_SRAM_END

  • RT_WEAK void *rt_heap_begin_get(void)
  • {
  •     return (void*)HEAP_BEGIN;
  • }

  • RT_WEAK void *rt_heap_end_get(void)
  • {
  •     return (void *)HEAP_END;
  • }
  • #endif
  • 复制代码


    配置systick中断函数:

    void rt_os_tick_callback(void)
  • {
  •     rt_interrupt_enter();   
  •     rt_tick_increase();   
  •     rt_interrupt_leave();
  • }

  • void SysTick_Handler(void)
  • {
  •     rt_os_tick_callback();
  • }

  • void rt_hw_board_init(void)
  • {
  •     SystemCoreClockUpdate();
  •     SysTick_Config(SystemCoreClock / RT_TICK_PER_SECOND);
  •    
  • #ifdef RT_USING_COMPONENTS_INIT
  •     rt_components_board_init();
  • #endif

  • #if defined(RT_USING_USER_MAIN) && defined(RT_USING_HEAP)
  •     rt_system_heap_init(rt_heap_begin_get(), rt_heap_end_get());
  • #endif
  • }
  • 复制代码


    配置日志串口初始化及日志输出函数:

    <pre><font size="3">#ifdef RT_USING_CONSOLE
  • #include "me32g030_uart.h"
  • #include "me32g030_ioconfig.h"

  • static int uart_init(void)
  • {
  •     PA2_INIT(PA2_UART1_TX);
  •     PA3_INIT(PA3_UART1_RX);
  •     UART_Open(UART1,115200,UART_NO_PARITY,UART_TRIGGER_LEVEL_1_BYTE);
  •     return 0;
  • }
  • INIT_BOARD_EXPORT(uart_init);

  • void rt_hw_console_output(const char *str)
  • {
  •     rt_enter_critical();
  •     while( *str != '\0')
  •     {
  •       if(*str == '\n')
  •       {
  •        while (!(UART1->LSR_b.THRE));
  •         UART1->THR = '\r';
  •       }
  •       while(!(UART1->LSR_b.THRE));
  •        UART1->THR = *str++;
  •     }
  •     rt_exit_critical();
  • }

  • #endif</font></pre>
  • 复制代码

    6. 创建示例应用

    6.1 修改main函数

    我们这里只开了一个点灯的任务:

    #include "demo.h"

  • int main(void)
  • {
  •     rt_thread_t _task_serial = rt_thread_create("demo", task_led, RT_NULL, 1024, 0, 10);
  •    
  •     if(_task_serial != RT_NULL)
  •         rt_thread_startup(_task_serial);
  • }
  • 复制代码

    其中点灯任务代码如下:

    void task_led(void *args)
  • {
  •    //Set PB12 as gpio
  •   PB12_INIT(PB12_GPIO);
  •   //Set PB12 as output
  •   PB->DIR_b.DIR12  = 0x1;

  •   while(1)
  •   {
  •     //toggle PB12
  •     // PB->NOT_b.NOT12 = 1;
  •      PB->SET_b.SET12 = 1;
  •      rt_kprintf("led on!\r\n");
  •     rt_thread_mdelay(1000);
  •     PB->CLR_b.CLR12 = 1;
  •     rt_kprintf("led off!\r\n");
  •     rt_thread_mdelay(1000);
  •   }
  • }
  • 复制代码

    7. 编译与调试

    • 编译工程,确保没有错误
    • 连接调试器,下载程序到目标板
    • 通过串口调试工具查看输出,确认RT-Thread正常运行

    Snipaste_2025-04-28_14-31-33.png

    同时可以观察板子上的LED灯以1秒的频次亮灭变化,至此,移植完成。OK!