1. 准备工作
1.1 硬件准备
- ME32G030AC8T6开发板一张。
- 调试器(如J-Link、ST-Link等)
- 必要的连接线缆,ME32G030的开发板一端就是标准20p的简牛插座,和J-Link直接对插即可,如图:
1.2 软件准备
- Keil MDK或IAR Embedded Workbench开发环境
- RT-Thread Nano源码包(可从RT-Thread官网下载)
- 目标MCU的BSP(板级支持包),下载地址:https://pan.baidu.com/s/1SJxSOUxW8at4NxEcjggahA 提取码:6967
2. 创建基础工程
- 在开发环境中创建一个新的工程,或者直接copy一份sdk的测试工程也可以。
- 添加必要的lib库文件。
3. 添加RT-Thread Nano到工程
3.1 复制RT-Thread Nano文件
将RT-Thread Nano的以下目录复制到你的工程目录中:
rtthread-nano/
3.2 添加文件到工程
在开发环境中添加以下文件到工程:
- rtthread-nano/src/*.c
- rtthread-nano/libcpu/arm/cortex-m0/*.c
3.3 包含头文件路径
添加以下头文件路径到工程设置:
- rtthread-nano/include
- rtthread-nano/libcpu/arm/cortex-m0
配置好的工程目录如下图:
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正常运行
同时可以观察板子上的LED灯以1秒的频次亮灭变化,至此,移植完成。OK!