STM32标准库移植RT-Thread nano
STM32标准库移植RT-Thread Nano
哔哩哔哩教程链接:STM32F1标准库移植RT_Thread Nano
移植前的准备
- stm32标准库的裸机代码(最好带有点灯和串口)
- RT-Thread Nano Pack
- 自己的开发板
移植前的说明
本人是在读学生,正在学习阶段,移植过程中,会有疏漏与不足,请有缘看到的读者指出,且敬请谅解,我会积极更改错误之处
移植步骤
一、打开RT-Thread文档中心作为参考: RT-Thread文档中心
二、keil上安装RT-Thread Nano Pack
1.用Keil IDE内安装RT-Thread Nano Pack(在线安装)
(1)打开Keil,选择Pack Installer ,关闭提示窗口
(2)打开pack,选择安装(我这里已经安装所以显示Remove)
2.用离线安装包安装RT-Thread Nano Pack(离线安装)
(1)下载离线包:RT-Thread Nano Pack 离线安装包
(2)离线安装(双击下载好的安装包,进行安装)
表示安装完成
三、添加内核源码
通过以上三个步骤,完成勾选以后,点击OK,就可以完成内核的添加,在keil目录结构中,就能够看到如下所示的内容,表示内核添加成功
四、删除与逻辑冲突的中断相关的函数
1.打开stm32f10x_it.c 找到相关的中断的函数
2.对与逻辑冲突的中断的函数,进行注释或删除
3.添加systick的中断函数到board.c中
void SysTick_Handler()
{
rt_interrupt_enter();
rt_tick_increase();
rt_interrupt_leave();
}
五、删除RT-Thread中的部分代码,添加系统的时钟配置
1.注释或删除以下一行代码:
#error "TODO 1: OS Tick Configuration."
2.添加时钟配置
SysTick_Config(SystemCoreClock / RT_TICK_PER_SECOND);
3.board.c中添加需要的头文件
#include "stm32f10x.h"
#include "gpio.h"
#include "usart.h"
#include "delay.h"
通过以上步骤,就完成了在STM32标准库上进行RT-Thread Nano版本的移植,编译一下,0警告0错误
六、创建任务进行验证
1.在工程的user文件夹下,新建RT-Thread相关的头文件和源文件,并添加到工程中
2.编写user下的RT-Thread的源文件(我的是RT_Thread_demo.c)
(1)包含头文件
#include "stm32f10x.h"
#include "RT_Thread_demo.h"
#include <rtthread.h>
#include "delay.h"
#include "gpio.h"
#include "usart.h"
(2)编写需要用到的宏定义
#define TASK1_PRIO 1 /* 任务优先级 */
#define TASK1_STK_SIZE 128 /* 任务堆栈大小 */
static rt_thread_t Task1_Handler = RT_NULL; /* 任务句柄 */
void Task1(void *pvParameters); /* 任务函数 */
#define TASK2_PRIO 2 /* 任务优先级 */
#define TASK2_STK_SIZE 128 /* 任务堆栈大小 */
static rt_thread_t Task2_Handler = RT_NULL; /* 任务句柄 */
void Task2(void *pvParameters); /* 任务函数 */
#define TASK3_PRIO 3 /* 任务优先级 */
#define TASK3_STK_SIZE 128 /* 任务堆栈大小 */
static rt_thread_t Task3_Handler = RT_NULL; /* 任务句柄 */
void Task3(void *pvParameters); /* 任务函数 */
(3) 通过函数创建任务,并在main.c中调用
void RT_Thread_demo(void)
{
Task1_Handler = rt_thread_create("Task1_Handler",Task1,RT_NULL,TASK1_STK_SIZE,TASK1_PRIO,20);
rt_thread_startup(Task1_Handler);
Task2_Handler = rt_thread_create("Task2_Handler",Task2,RT_NULL,TASK2_STK_SIZE,TASK2_PRIO,20);
rt_thread_startup(Task2_Handler);
Task3_Handler = rt_thread_create("Task3_Handler",Task3,RT_NULL,TASK3_STK_SIZE,TASK3_PRIO,20);
rt_thread_startup(Task3_Handler);
}
(4) 编写任务函数
void Task1(void *parameter)
{
while(1)
{
LED1_Toggle;
//printf("Task1\r\n");
USART_SendString(USART1,(unsigned char*)"Task1\r\n");
rt_thread_mdelay(300);
}
rt_thread_delay(10);
}
void Task2(void *parameter)
{
while(1)
{
LED2_Toggle;
//printf("Task2\r\n");
USART_SendString(USART1,(unsigned char*)"Task2\r\n");
rt_thread_mdelay(600);
}
rt_thread_delay(10);
}
void Task3(void *parameter)
{
while(1)
{
LED3_Toggle;
//printf("Task3\r\n");
USART_SendString(USART1,(unsigned char*)"Task3\r\n");
rt_thread_mdelay(900);
}
rt_thread_delay(10);
}
(5) 模块初始化
把用到的初始化函数都放在board.c的rt_hw_board_init 中
通过以上步骤,已经完成对RT_Thread的移植。接下来调试验证
七、移植rt_kprintf函数
1. 在rtconfig.h中修改部分代码
(1)定义 RT_USING_CONSOLE
(2)删除或注释 uart_init 中的部分代码并加入usart的初始化函数(board.c中)
(3)删除rt_hw_console_output部分代码并修改
函数修改为:
void rt_hw_console_output(const char *str)
{
rt_enter_critical();
while(*str != '\0')
{
if(*str == '\n')
{
USART_SendData(RT_kprintf_USARTx,'\r');
while(USART_GetFlagStatus(RT_kprintf_USARTx, USART_FLAG_TXE) == RESET); //等待上一个字节发送完成
}
USART_SendData(RT_kprintf_USARTx, *str++); //发送一个字节
while(USART_GetFlagStatus(RT_kprintf_USARTx, USART_FLAG_TXE) == RESET); //等待上一个字节发送完成
}
rt_exit_critical();
}
八、finsh组件的移植
1. 添加组件源码
keil的目录结构中,会出现如下文件
2. rtconfig.h 中打开 finsh 选项
3. 修改 finsh_port.c 文件
#include <rthw.h>
#include <rtconfig.h>
#include "stm32f10x.h"
#include "usart.h"
#ifndef RT_USING_FINSH
#error Please uncomment the line <#include "finsh_config.h"> in the rtconfig.h
#endif
#ifdef RT_USING_FINSH
RT_WEAK char rt_hw_console_getchar(void)
{
int ch = -1;
//查询方式实现,记得将Usart1初始化中的中断接收配置相关代码注释掉
/*等待串口1输入数据*/
if( USART_GetFlagStatus( RT_kprintf_USARTx, USART_FLAG_RXNE ) != RESET )
{
ch = ( int )USART_ReceiveData( RT_kprintf_USARTx );
USART_ClearFlag( RT_kprintf_USARTx, USART_FLAG_RXNE );
}
else
{
if( USART_GetFlagStatus( RT_kprintf_USARTx, USART_FLAG_ORE ) != RESET )
{
USART_ClearFlag( RT_kprintf_USARTx, USART_FLAG_ORE );
}
rt_thread_mdelay( 10 );
}
return ch;
}
#endif /* RT_USING_FINSH */
4. 修改串口的初始化函数
void uart1_init(uint32_t bound)
{
GPIO_InitTypeDef GPIO_InitStructure; //GPIO
USART_InitTypeDef USART_InitStructure; //USART
NVIC_InitTypeDef NVIC_InitStructure; //NVIC
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //USART1_TX
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //USART1_RX
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入
GPIO_Init(GPIOA, &GPIO_InitStructure);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;//抢占优先级3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //子优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure);
USART_OverSampling8Cmd(USART1,ENABLE);
USART_InitStructure.USART_BaudRate = bound;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式
USART_Init(USART1, &USART_InitStructure); //初始化串口1
USART_Cmd(USART1, ENABLE); //使能串口1
}
通过以上步骤,对RT-Thread Nano版本的移植到此结束,希望大家相互学习,相互鼓励!!!!
九、keil调试验证
详细调试步骤,请移步至哔哩哔哩视频教程:STM32F1标准库移植RT_Thread Nano
九、烧录到开发板验证
详细步骤,请移步至哔哩哔哩视频教程:STM32F1标准库移植RT_Thread Nano