44 RT-Thread Nano移植到stm32F103CBT6 (STD标准库)

RT-Thread Nano移植FinSH控制台 使用串口中断方式接收数据,实现了控制台的 getchar 函数,从而移植了 RT-Thread Nano 的 FinSH 组件,实现命令行交互功能。 阅读详情

一、前言

最近在学习rt-thread,然后网上有介绍用RT-Thread Studio和stm32cubex结合进行开发,还有用rt-thread nano提供的pack直接开发,但是这种方式真的不太行,对于新手而言,不能很好的了解整个代码的结构。

为此,就怀着跟前面网友一样的心思,准备要自己拷贝代码,一步一步来对rt-thread进行移植,然后发现还是挺简单的,如果rt-thread已经移植过相应的cpu的话,那简直移植的方便就超级简单了。

本文章把rt-thread nano移植到stm32f103c8t6,然后也是基于STD标准库进行移植的,网上比较多的是基于HAL库进行移植的,写该文章一是为了下次自己回来看的时候能记忆起来;二是也为新手提供一种思路,如果他们要学习的话。

然后再说说,为什么选用rt-thread,第一是因为国产;第二是因为它能有像Linux的控制台;第三我只想要用一个线程调用的核,所以就选用了它!!挺好的加入支持国产的道路。

二、rt-thread移植记录

  1. stm32-led工程准备。

本次移植RT-Thread Nano内核到一个stm32f103cBt6标准库的一个led工程中,所以需要准备一个点灯程序,其目录如下图示。

 

 

移植前的led点灯工程主程序,以及编译后的大小如下图示。移植前程序所占ROM大小为:2216+268=2484字节;所用RAM:3840+48=3888字节;

2.下载RT-Thread Nano内核

首先,到官网上下载RT-Thread Nano源码,如下图示,本次下载的是rt-thread-3.1.3。下载链接:https://www.rt-thread.org/page/download.html

3.拷贝文件到目标led工程

首先,在原有的led工程的目录下,建立一个RT-Thread目录,如下图示。

然后打开rt-thread-3.1.3,拷贝下面三个目录的内容到刚建好的RT-Thread目录中。

拷贝完成后,删除掉libcpu里面没用到的文件,留下有用的。

最后只剩下面这个cortex-m3目录。

然后打开rt-thread-3.1.3目录下的dsp木,把拷贝board.c和rtconfig.h到工程的RT-Thread目录下。

4.添加目录及文件到led的keil工程。

把board.c和rtconfig.h两个文件,添加这两个文件到User目录下。

5.编译工程解决错误

编译的时候肯定会出现这三个问题,打开代码,定位到这三个函数,把led工程原有的这三个函数注释掉,因为RT-Thread已经实现了这三个函数,所以导致重定义。

注释:HardFault_Handler,如下图示:

注释:PendSV_Handler和SysTick_Handler

然后编译,发现编译通过,然后继续移植。

6.更改board.c文件

RT-Thread系统框架下,设备的时钟及硬件初始化都是放在board.c文件中的,我们只需要在rt_hw_board_init函数配置好,系统时钟和滴答定时器。

然后我把自己的main函数的时钟初始化SystemInit函数拷贝到rt_hw_board_init函数中。

主函数改成这样。

int main(void)
{

	LED_Init(); //LED 端口初始化 
	

	while(1)
	{
		
		LED_SetRGBLight(RGBLED_MODE_Y);
        rt_thread_mdelay(1000);
		LED_SetRGBLight(RGBLED_MODE_G);
        rt_thread_mdelay(1000);

	}

	return 0;
}

然后对工程重新编译,给予RT-Thread 内核的led工程编译通过,下载到开发板,led正常一闪一闪。

编译前我把邮箱和信号量的宏注释掉,关闭了线程通信的方式,所以可以看到移植后,代码量ROM:4004+576=4580,RAM:4720+112=4832

7.添加Finish控制台

第一步:在rtconfig.h中确定RT_USING_CONSOLE和RT_USING_FINSH已经打开,如图所示。

第二步,串口初始化。

首先,在board.c实现rt_hw_console_getchar函数,然后再kservice实现rt_hw_console_output函数,下列使用的是标准库,如下图所示。

char rt_hw_console_getchar(void)
{
	int ch = -1;
	if (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) != RESET)
	{
		ch = (int)USART_ReceiveData(USART1);
	}
	else
	{
		if(USART_GetFlagStatus(USART1, USART_FLAG_ORE) != RESET)
		{
			USART_ClearFlag(USART1,USART_FLAG_TC);
		}
		rt_thread_mdelay(10);
	}
	return ch;	
}
RT_WEAK void rt_hw_console_output(const char *str)
{
    /* empty console output */
	rt_size_t i = 0, size = 0;
	char a = '\r';

	USART_ClearFlag(USART1, USART_FLAG_TC);
	
	size = rt_strlen(str);
	for (i = 0; i < size; i++)
	{
		if (*(str + i) == '\n') 
		{
			USART_SendByte(USART1, a);
		}
		USART_SendByte(USART1, *(str + i));
	}
}

 

然后实现串口初始化,如下图示。但这里有一个坑,因为默认的shell使用的是轮询的方式实现,所以串口初始化这里,不能启动中断接收,否则shell将不正常。



void uart1_init(u32 bound)
{
	//GPIO端口设置
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);	//使能USART1,GPIOA时钟

	//USART1_TX   GPIOA.9
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	//复用推挽输出
	GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9

	//USART1_RX	  GPIOA.10初始化
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//浮空输入
	GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10  

	//Usart1 NVIC 配置
	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2 ;//抢占优先级3
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;		//子优先级3
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
	NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器

	//USART 初始化设置
	USART_DeInit(USART1);
	USART_InitStructure.USART_BaudRate = bound;//串口波特率
	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_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断
	USART_Cmd(USART1, ENABLE);                    //使能串口1 
	USART_ClearFlag(USART1, USART_FLAG_TC);
}

然后,将初始化放在board.c的rt_hw_board_init函数里面,如下图示。

void rt_hw_board_init()
{
		SystemInit();				//配置系统时钟为72M 

	  /* System Tick Configuration */
    _SysTick_Config(SystemCoreClock / RT_TICK_PER_SECOND);

		NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	
		uart1_init(115200); 		//调试串口

    /* Call components board initial (use INIT_BOARD_EXPORT()) */
#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
}

到此,算是通过拷贝代码的方式将rt-thread搞到自己的开发板上了吧!

over!

 

RT-DETR论文阅读笔记(包括YOLO版本训练和官方版本训练) 目标检测是一项基础的视觉任务,涉及识别和定位图像中的对象。现代目标检测器有两种典型架构:基于CNN和基于Transformer。在过去几年中,基于CNN的目标检测器进行了广泛的研究。这些检测器的架构已从最初的两阶段发展到单阶段,并出现了基于锚点和无锚点两种检测范式。这些研究在检测速度和精度方面都取得了显著进展。自从提出以来,基于Transformer的目标检测器(DETRs)因其消除了各种手工制作的组件(例如非最大抑制NMS)而受到学术界的广泛关注。 阅读详情

相关推荐

RTThread Stm32 标准库参考工程.zip_RT-Thread STD库_rtos stm32_rtthread_rt

RTOS RT-THREAD标准库参考工程

【❗JS奇技淫巧❗】JavaScript:截取DataURL中的base64字符串

图片中的src是从dataURL里赋值过去的: "jpgbase64":"data:application/octet-stream;base64,/9j/4Q6PIHsic2VpaW5mbyI6eyJpcGMiOnsiaXAiOlsxMCw2Nyw4Miw5M10sImFsZyI6OSwiZW5jYmlnIjowLCJwZXJjZmciOnsicGVyZGV0dHlwZSI6MCwiZmFjZW91dG1vZGUiOjAsImZhY2ViZXN0bnVtIjowfSwidmVoY2ZnIj...

谁吃薄荷糖 30万+

基于STM32F103标准库移植RTTHread_NANO

基于STM32F103标准库移植RTTHread_NANO

3.5 Option

3.5 Option

agoldminer的博客 7546

ZYNQ:【1】深入理解PS端的TTC定时器(Part1:原理+官方案例讲解)

基于UG585详细讲解其中TTC的原理和使用案例。

Alex的技术博客 7887

无刷电机FOC控制入门:磁场、洛伦兹力与坐标转换详解

本文深入解析无刷电机FOC(磁场定向控制)的核心原理,从电磁学基础的磁场与洛伦兹力出发,详细阐述了如何通过Clarke变换、Park变换等坐标转换技术,将三相交流解耦为直流量进行控制,最终利用SVPWM技术实现平滑、高效的电机驱动。文章旨在帮助开发者理解FOC的物理本质与数学框架,为机器人、无人机等高性能应用奠定基础。

weixin_29306011的博客 267

加速44%!RT-DETR量化无损压缩优秀实战

本文使用飞桨模型压缩工具 PaddleSlim 中的ACT,针对 RT-DETR 进行量化压缩及部署实战。模型精度持平的情况下,RT-DETR 模型体积压缩为原来的四分之一,GPU 推理加速44%。

PaddlePaddle 1665

【SigmaStar SSC335系列】空片用Flash_Tool烧写

简介 本文主要讲新拿到的PCBA,板上spi nand flash还是空的,如何在这种情况下烧录固件,这里讲解用官方Flash_Tool烧写的方式。 但只讲一些注意的地方和坑,其它的官方文档里说的比较清楚,不多说。 准备 Flash_Tool烧写软件 编译打包好烧写镜像 串口烧录小板 ----- 这个是个坑,在官方文档里并没有提及,刚开始用的平时调试的USB转串口,怎么都没反应,一度不知烧写软件不对还是硬件有问题,最后通过厂家技术支持才得知,除了专门的Flash_Tool外,还要专门的串口烧录器

老K 4699

STM32标准库移植RT-Thread Nano添加FinSH与控制台

添加过shell后 首先要在 rtconfig.h中定义 #define RT_USING_FINSH 为了方便,串口相关函数添加在board.c中 使用串口中断实现命令的接收 /* * Copyright (c) 2006-2019, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2017-0

点灯师的博客 2150

SQL实现数据仓库ETL:分层设计、增量抽取与性能优化实践

在数据仓库建设过程中,ETL(抽取、转换、加载)是数据流转的核心环节。传统观点常将ETL与专业工具或大数据框架绑定,但在中小规模数据场景下,基于SQL的ETL方案凭借低门槛、高可维护性和直观的排错体验,成为高效且务实的选择。本文从ETL的基础概念出发,阐述数据仓库分层(ODS、DWD、DWS、ADS)中每层ETL的定位与职责,重点剖析增量抽取策略(时间戳、主键、日志)下的SQL实现方式,以及数据清洗、去重和格式化的常见写法。同时,结合真实项目经验,分享慢SQL优化技巧、任务调度依赖设计、幂等性保障和常见问题

weixin_33290540的博客 346

Nginx反向代理MinIO私有桶签名失效?一招解决Host头校验问题

本文详细解析了Nginx反向代理MinIO私有桶时出现的签名失效问题,重点解决了Host头校验导致的"SignatureDoesNotMatch"错误。通过精准配置proxy_set_header保持Host头一致性,并提供了二级目录代理和调试指南,帮助开发者高效解决这一常见技术难题。

weixin_29201313的博客 321

Centos 7下编译安装Linux-3.18.44-rt47内核

获取源码以及补丁从Linux内核官网上下载3.18.44版本的内核源码,并且从rt.wiki上下载相对应的补丁,用于支持内核实时性。

几百个教授的专栏 1553

MATLAB新手必看:5分钟搞定直流无刷电机Simulink仿真(附完整模型下载)

本文为MATLAB新手提供直流无刷电机Simulink仿真的快速入门指南,涵盖从环境配置到速度控制闭环实现的完整流程。通过详细的模块选择和参数设置说明,帮助读者5分钟内搭建基础仿真模型,并附赠完整模型下载,助力快速掌握电机控制仿真技术。

efc123456的博客 984

STM32 + RT Thread OS 学习笔记[五]

1、  触摸屏驱动 触摸屏驱动的原理非常简单,从硬件得到坐标数据,数据加工(适配屏幕分辨率,偏移量调整),最后调用rtgui_server_post_event()函数向GUI服务端发送坐标信息。   奋斗板V3,使用的AD芯片是XPT2046,是RTGUI bsp/stm32f10x下的ADS7846芯片的下一代产品,功能及硬件连接上完全兼容。因此,我们只要确认与MCU的管脚连接,在代码上

的米-漠石's Blog 6313

PyQt(Python+Qt)学习随笔:PyQt界面派生类构造方法中super方法的使用

老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 在《第15.7节 PyQt入门学习:PyQt5应用构建详细过程介绍》和订阅专栏《第二章、PyQt5应用构建详细过程介绍》中,老猿介绍界面派生类的构造方法如下: class MediaPlayerWin(QtWidgets.QWidget,Ui_UI_PlayerWin): def __i...

老猿Python 2711

YOLOv13优化Faster_Block:卷积(Partial Convolution)、多层感知机(MLP)结构和残差连接

Faster_Block 代表了现代深度学习中效率与性能平衡的一个典型案例。它通过部分卷积技术巧妙地减少了计算开销,同时通过精心设计的架构保持了强大的特征学习能力。这种设计思想对于移动端部署、实时应用和大规模模型训练都具有重要意义。 未来的发展方向可能包括更智能的动态分割策略、与新兴硬件的深度适配,以及与其他先进技术(如自注意力机制、神经架构搜索等)的结合。Faster_Block 的成功展示了在深度学习领域,创新往往来自于对问题本质的深刻理解和巧妙的工程实现。

FJN110的博客 427

【TensorRT】onnx转成TensorRT开发踩坑记录(Win10+cuda11.1+TensorRT7.2.2.3)(持续更新)

本博客提供onnx模型转成TensorRT模型时的开发经验。

qq_42944019的博客 6082

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

Stm32学习笔记,3万字超详细

本文章主要记录本人在学习stm32过程中的笔记,也插入了不少的例程代码,方便到时候CV。绝大多数内容为本人手写,小部分来自stm32官方的中文参考手册以及网上其他文章;代码部分大多来自江科大和正点原子的例程,注释是我自己添加;配图来自江科大/正点原子/中文参考手册。笔记内容都是平时自己一点点添加,不知不觉都已经这么长了。其实每一个标题其实都可以发一篇,但是这样搞太琐碎了,所以还是就这样吧。

TheBszk的博客 10万+

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

RT-DETR实战:如何在T4 GPU上实现114FPS的实时目标检测(附完整配置流程)

本文详细解析了百度开源的RT-DETR(Real-Time Detection Transformer)模型,该模型在T4 GPU上实现了114FPS的实时目标检测性能。通过混合编码器设计和IoU感知查询机制,RT-DETR在精度和速度上均超越传统YOLO系列,并提供从环境配置到TensorRT加速的完整工程指南,助力开发者快速实现高效目标检测应用。

h0i1j2k3l的博客 644

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

RT-DETRv4: Painlessly Furthering Real-Time Object Detection with Vision Foundation Models无痛推进实时目标检测

RT-DETRv4: Painlessly Furthering Real-Time Object Detection with Vision Foundation Models——RT-DETRv4:借助视觉基础模型无痛推进实时目标检测

Together_CZ的博客 1702

signature=10a018ba048c61ca6c010bf78a410268,qtumcore-node/yarn.lock at master · qtumproject/qtumcore-...

# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.# yarn lockfile v1abbrev@1:version "1.1.1"resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987...

weixin_29097457的博客 8万+

玩转RT-Thread系列教程(1)--线程的使用

玩转RT-Thread系列教程(1)–线程的使用 一、什么是线程 我们或许都听说过多线程的概念,其实在多CUP处理器上才真正的存在多线程的概念,每个CPU同时运行处理多个不同的任务。 那在我们的单核CPU的单片机上如何使用“多线程”来处理同一时刻请求的不同任务,来做到”同时“进行呢? 这个时候就需要引入线程管理了。在多线程操作系统中,需要开发人员把一个复杂的应用分解成多个小的、可调度的、 序列化的程序单元。而在 RT-Thread 中,与上述子任务对应的程序实体就是线程。 RT-Thread 的线程调度器是

Rb的工作站 1万+

STM32 RT-Thread Nano(3)移植控制台与Finsh

本文介绍如何基于 Keil MDK 移植 RT-Thread 的控制台/Finsh。这样有利于开发过程中的调试,进行输入输出控制。 开发平台:Keil MDK 5.24 硬件平台:XNUCLEO-F103RB 移植系统:RT-Thread Nano V3.1.3 在 Nano 上添加 UART 控制台 在 RT-Thread Nano 上添加 UART 控制台打印功能后,就可...

killercoder 4450

【算法总结】数据结构

【splay】 〖模板代码〗 1 void rotate(int x,int& k) 2 { 3 int y=fa[x],z=fa[y],l,r; 4 l=(tr[y][1]==x);r=l^1; 5 if(y==k)k=x; 6 else tr[z][tr[z][1]==y]=x; 7 fa[x]=z;fa[y...

weixin_30794491的博客 463
上一篇: 43 ME3616物联网模块连接OneNet平台
下一篇: 45 STM32 IIC主机、从机通信实例(ma51t12b触摸按键芯片)
Chasing_Chasing
博客等级 码龄10年 233粉丝 87原创
评论 5
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值