(个人记录)移植RT_Thread到f103c8t6板子上

目录

前言

一、F103ZET6代码更改配置到F103C8T6

1.keil内部设置更改

2.项目文件修改

​编辑

二、RTTHREAD手动移植

1.安装rtthread的pack包

2.相关配置文件修改

3.FINSH组件添加

总结



前言

注:个人记录,本人很菜,如果对你有帮助最好,没有的话我很抱歉,本人小菜鸡,欢迎指正,移植部分参考这位大佬的:RT-thread的STM32f103c8t6移植_stm32f103c8t6 rtthread-优快云博客

非常感谢!!

主要分为两个部分:

第一部分正点原子找的代码原先应用于f103zet6,修改到f103c8t6上;

第二部分进行RTThread的移植。


提示:以下是本篇文章正文内容,下面案例可供参考

一、F103ZET6代码更改配置到F103C8T6

此处使用的是正点原子资料的跑马灯实验代码

1.keil内部设置更改

首先打开工具栏的魔术棒(目标选项),将下方的芯片类型改成STM32F108C8,如果没有F103这个选项说明没有安装对应的芯片包,去官网下载安装即可。

其次点开C/C++选项卡,将Define中的STM32F10X_HD,USE_STDPERIPH_DRIVER改为STM32F10X_MD,USE_STDPERIPH_DRIVER;这是因为C8T6的芯片资源比ZET6小,不是同一种类型的芯片。

接着修改调试选项卡,将框起来的部分全部修改成图二所示的内容,不然调试起来会卡在系统函数里走不出来。

2.项目文件修改

此处的启动文件也是zet6用的,也需要修改成_md.s文件,如图一所示。

但是正点原子给的例程这边只给了一个.s文件,如图二所示,所以需要外部找一下。

完整的文件应该有这么多,我们这边用的是_md.s文件,如图所示。

最后再回到keil里将原来的_hd文件移除,换成_md.s文件。到此就换成了C8T6的代码

二、RTTHREAD手动移植

此处参考的另外一篇博客的内容,原内容地址:RT-thread的STM32f103c8t6移植_stm32f103c8t6 rtthread-优快云博客

网上找了不少的资料,大部分是用cube去进行移植的,我没有用过cube,所以好不容易找到了这一片在kuil上移植的。此外好像env工具可以便捷的进行移植,我这边还没有接触到。

1.安装rtthread的pack包

rtthread的pack包直接去官网下载即可,此处给出链接:

https://www.rt-thread.org/download/mdk/RealThread.RT-Thread.3.1.5.pack

下载完之后直接打开即可安装。备注:在keil5软件里也可以安装,但我没有尝试。

下载后依次打开图中对应红框,其中shell是相关的组件,kenel是系统的内核,device是相关的设备。此处可以先勾选kenel。然后点ok就完成内核的下载了。

2.相关配置文件修改

因为rtthread内核里的一些函数和我们自己的一些函数会有重定义,所以需要修改一些函数。

移植主要包括全局中断、上下文切换相关的API以及时钟节拍的移植。

1.首先要屏蔽掉原有的异常处理函数void SysTick_Handler(void)和悬挂处理函数void PendSV_Handler(void),这两个函数分别是cortex-M3自己的时钟节拍以及上下文切换函数,我们需要屏蔽掉以防重复定义。

2.在board.c文件的void rt_hw_board_init(void)函数当中注释蓝色的框内的代码,并且添加

SysTick_Config(SystemCoreClock / RT_TICK_PER_SECOND);

这个代码的意思是配置RTTHREAD每一个tick的时长。

接着在此文档中额外添加一个函数,然后在board.c文件中添加#include “stm32f103x.h”

void SysTick_Handler()
 
{
 
  rt_interrupt_enter();
 
  rt_tick_increase();
 
  rt_interrupt_leave();
 
}

至此内核就全部移植完成,可以自己调试试一下,如果有重复定义的错误,进入文件中将对应的函数注释掉就行。

3.FINSH组件添加

finsh组件很好用,可以脱离板子进行调试,非常便捷。

首先可以添加FINSH组件的源码,如上文添加内核一样,将shell选上。

接着需要实现串口初始化的函数,一般模板都会自带,但是为了防止冲突我还是直接复制了大佬写的代码。如下:

#include "usart.h"		 
#include <rtthread.h>
 
//int fputc(int ch,FILE *p)  //函数默认的,在使用printf函数时自动调用
//{
//	USART_SendData(USART1,(u8)ch);	
//	while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);
//	return ch;
//}
 
串口1中断服务程序
注意,读取USARTx->SR能避免莫名其妙的错误   	
//u8 USART1_RX_BUF[USART1_REC_LEN];     //接收缓冲,最大USART_REC_LEN个字节.
接收状态
bit15,	接收完成标志
bit14,	接收到0x0d
bit13~0,	接收到的有效字节数目
//u16 USART1_RX_STA=0;       //接收状态标记
 
 
/*******************************************************************************
* 函 数 名         : USART1_Init
* 函数功能		   : USART1初始化函数
* 输    入         : bound:波特率
* 输    出         : 无
*******************************************************************************/ 
int USART1_Init(void)
{
   //GPIO端口设置
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	//NVIC_InitTypeDef NVIC_InitStructure;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
 
	
	/*  配置GPIO的模式和IO口 */
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;//TX			   //串口输出PA9
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;	    //复用推挽输出
	GPIO_Init(GPIOA,&GPIO_InitStructure);  /* 初始化串口输入IO */
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;//RX			 //串口输入PA10
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;		  //模拟输入
	GPIO_Init(GPIOA,&GPIO_InitStructure); /* 初始化GPIO */
	
 
	//USART1 初始化设置
	USART_InitStructure.USART_BaudRate = 115200;//波特率设置
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
	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 
	
	USART_ClearFlag(USART1, USART_FLAG_TC);
		
//	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启相关中断
 
//	//Usart1 NVIC 配置
//	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;//串口1中断通道
//	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;//抢占优先级3
//	NVIC_InitStructure.NVIC_IRQChannelSubPriority =3;		//子优先级3
//	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
//	NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器、	
	
	return 0;
}
 

usart.h文件

#ifndef _usart_H
#define _usart_H
 
#include "system.h" 
#include "stdio.h" 
 
//#define USART1_REC_LEN		200  	//定义最大接收字节数 200
 
//extern u8  USART1_RX_BUF[USART1_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符 
//extern u16 USART1_RX_STA;         		//接收状态标记
int USART1_Init(void);
 
#endif
 
 

其次修改board.c中的串口初始化代码,将原来的代码改成如下:

static int uart_init(void)
 
{
           USART1_Init();
    return 0;
 
}
 
INIT_BOARD_EXPORT(uart_init);
 
void rt_hw_console_output(const char *str)
 
{
 
    rt_enter_critical();
 
    /* 直到字符串结束 */
 
    while ( *str != '\0' )
 
    {
 
        /* 换行 */
        //RT-Thread 系统中已有的打印均以 \n 结尾,而并非 \r\n,所以在字符输出时,需要在输出 \n 之前输出 \r,完成回车与换行,否则系统打印出来的信息将只有换行
 
        if ( *str == '\n' )
        {
 
            USART_SendData(USART1, '\r' );
            while ( USART_GetFlagStatus( USART1, USART_FLAG_TXE ) == RESET );
        }
 
        USART_SendData( USART1, *str++ );
        while ( USART_GetFlagStatus( USART1, USART_FLAG_TXE ) == RESET );
 
    }
 
    /* 退出临界段 */
 
    rt_exit_critical();
 
}

接着修改finsh_port.c文件的代码替换如下:

/*
 
 * Copyright (c) 2006-2021, RT-Thread Development Team
 
 *
 
 * SPDX-License-Identifier: Apache-2.0
 
 *
 
 * Change Logs:
 
 * Date           Author       Notes
 
 */
 
 
 
#include <rthw.h>
 
#include <rtconfig.h>
 
#include "system.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)
 
{
 
/* Note: the initial value of ch must < 0 */
 
    int ch = -1;
 
 
 
  //查询方式实现,记得将Usart1初始化中的中断接收配置相关代码注释掉
 
    /*等待串口1输入数据*/
 
    if( USART_GetFlagStatus(USART1, USART_FLAG_RXNE ) != RESET )
 
    {
 
        ch = ( int )USART_ReceiveData( USART1 );
 
        USART_ClearFlag( USART1, USART_FLAG_RXNE );
 
    }
 
    else
 
    {
 
        if( USART_GetFlagStatus( USART1, USART_FLAG_ORE ) != RESET )
 
        {
 
            USART_ClearFlag( USART1, USART_FLAG_ORE );
 
        }
 
        rt_thread_mdelay( 10 );
 
    }
 
    return ch;
 
}
 
 
 
#endif /* RT_USING_FINSH */

最后更改一下配置文件中的宏定义,将rtconfig.h中的RT_USING_CONSOLE宏定义打开,以及包含#include “finsh_config.h”

修改完就可以正常运行了。调试就可以出现串口,具体使用方法此处不赘述。


总结

个人的一次学习的总结,仅供参考,本人很菜,如果有问题很抱歉。移植部分主要参考了上文链接中的大佬的步骤。很感谢大佬!

其次这个方法移植的话只能在keil中运行,因为他的RTTHREAD对应的系统文件不在我们自己的项目文件里,实际上在keil的路径那边,所以如果移到别的编译器里面就没法识别到RTTHREAD的相关文件了。我个人觉得还是项目文件中有对应的系统代码会好一点,目前正在琢磨。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值