RT-Thread Nano入门学习笔记(1)

RT-Thread系列

Keil模拟器 STM32F103上手指南学习笔记

RT-Thread Studio快速上手

RT-Thread Nano入门学习笔记(2)

项目实战:快速打造一个桌面mini网络时钟

使用内置Git插件管理项目

文章目录

  • 1.RT-Thread Nano-添加源码
  • 2.RT-Thread Nano-启动运行流程分析
  • 3.RT-Thread Nano-rt_kprintf支持
  • 4.RT-Thread Nano-Finsh组件支持
  • 5.RT-Thread Nano-线程创建1和线程讲解2
    • (1)RT-Thread Nano-线程创建1
    • (2)RT-Thread Nano-线程讲解2
  • 6.RT-Thread Nano-自动初始化及MSH-EXPORT-1和2
    • (1)RT-Thread Nano-自动初始化及MSH-EXPORT-1
    • (2)RT-Thread Nano-自动初始化及MSH-EXPORT-1
  • 7.RT-Thread Nano-串口接收(信号量使用)编写1

1.RT-Thread Nano-添加源码

已完成,添加源码后进行相应的修改,编译无错误,截图如下:

RT-Thread Nano入门学习笔记(1)_第1张图片

RT-Thread Nano入门学习笔记(1)_第2张图片

仿真测试如下:

RT-Thread Nano入门学习笔记(1)_第3张图片

RT-Thread Nano入门学习笔记(1)_第4张图片

仿真显示高低电平如下,说明移植成功!

RT-Thread Nano入门学习笔记(1)_第5张图片

RT-Thread Nano入门学习笔记(1)_第6张图片

2.RT-Thread Nano-启动运行流程分析

已完成,截图证明如下:

设置断点进行仿真,查看运行流程:

首先是进入$sub$$main ()函数:

RT-Thread Nano入门学习笔记(1)_第7张图片

然后进行一些板子的初始化:

RT-Thread Nano入门学习笔记(1)_第8张图片

RT-Thread Nano入门学习笔记(1)_第9张图片

最后是调用rt_system_scheduler_start ( ) ;整个系统就启动了

总结:

先进入$sub$$main ()函数,然后再跳到rtthread startup()函数进行一些板子的初始化,然后调用rt_system_scheduler_start ();这样整个系统就启动了!

3.RT-Thread Nano-rt_kprintf支持

  • 实现rt_hw_console_output:
    实现finsh 组件输出一个字符,即在该函数中实现uart输出字符,在Usart.c文件中加入如下函数:
void rt_hw_console_output(const char *str)
{
	while(*str != '\0')
	{
		USART_SendData(USART1, *str++);
	
	  while(USART_GetFlagStatus(USART1, USART_FLAG_TC)== RESET);
	}
}

运行仿真可在UART #1中看到打印数据,如下:

RT-Thread Nano入门学习笔记(1)_第10张图片

  • 注意:RT-Thread 系统中已有的打印均以 \n 结尾,而并非 \r\n,所以在字符输出时,需要在输出 \n 之前输出 \r,完成回车与换行,否则系统打印出来的信息将只有换行,如下:
void rt_hw_console_output(const char *str)
{
	while(*str != '\0')
	{
		if(*str == '\n')
		{
				USART_SendData(USART1, '\r');
	
	      while(USART_GetFlagStatus(USART1, USART_FLAG_TC)== RESET);
		}
		USART_SendData(USART1, *str++);
	
	  while(USART_GetFlagStatus(USART1, USART_FLAG_TC)== RESET);
	}
}
  • 当rt scheduler lock nest> =1时,调度器停止调度

RT-Thread Nano入门学习笔记(1)_第11张图片

输出信息时要尽量禁止调度,那如何实现禁止调度呢?如下:

void rt_hw_console_output(const char *str)
{
	
	rt_enter_critical();

	while(*str != '\0')
	{
		if(*str == '\n')
		{
				USART_SendData(USART1, '\r');
	
	      while(USART_GetFlagStatus(USART1, USART_FLAG_TC)== RESET);
		}
		USART_SendData(USART1, *str++);
	
	  while(USART_GetFlagStatus(USART1, USART_FLAG_TC)== RESET);
	}
	rt_exit_critical();
}

RT-Thread Nano入门学习笔记(1)_第12张图片

4.RT-Thread Nano-Finsh组件支持

已完成,证明如下:

  • 前一小节已经完成输出,现在要实现输入,
    增加rt_hw_console_getchar()函数以实现RT-Thread Nano-Finsh组件支持,并且要去除串口1中断初始化。

RT-Thread Nano入门学习笔记(1)_第13张图片

char rt_hw_console_getchar(void)
{
    int ch = -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;
}

按tab键、输入help:

RT-Thread Nano入门学习笔记(1)_第14张图片

可以查看版本和线程:

RT-Thread Nano入门学习笔记(1)_第15张图片

  • 如果要添加命令,可以自己写一个函数,例如version命令(自带的了),在文件cmd.c中可查找到
MSH_CMD_EXPORT(version, show RT-Thread version information);

RT-Thread Nano入门学习笔记(1)_第16张图片

5.RT-Thread Nano-线程创建1和线程讲解2

(1)RT-Thread Nano-线程创建1

已完成线程的创建:

自定义Task.c文件,存放线程:

#include "config.h"
#include "Task.h"

static rt_thread_t led_thread;

void led_thread_entry(void *parameter);

void TaskInit(void)
{
	//返回值还是需要的,否则无法通过rt_thread_startup启动
	led_thread =  rt_thread_create("ledThread",
                             led_thread_entry,
                             RT_NULL,
                             256,
                             2,
                             10);
	if(led_thread != RT_NULL)
	{
		rt_thread_startup(led_thread);
	}

void led_thread_entry(void *parameter)
{
	while(1)
	{
	  LedToggle(GPIOA,GPIO_Pin_1);
	  rt_thread_mdelay(2000);
		rt_kprintf("System running: %d s \n",rt_tick_get()/RT_TICK_PER_SECOND);
	}
}

main.c文件

int main(void)
{
	TaskInit();
	while(1)
	{		
		 LedToggle(GPIOA,GPIO_Pin_0);
	   rt_thread_mdelay(1000);
	}	
}

注意:线程不能强占住CPU,必须有要让出CPU的工作,否则会进入死循环

RT-Thread Nano入门学习笔记(1)_第17张图片

可查看当前运行的线程:

RT-Thread Nano入门学习笔记(1)_第18张图片

打印当前系统运行时间(每隔两秒打印一次)

void led_thread_entry(void *parameter)
{
	while(1)
	{
	  LedToggle(GPIOA,GPIO_Pin_1);
	  rt_thread_mdelay(2000);
	  rt_kprintf("System running: %d s \n",rt_tick_get()/RT_TICK_PER_SECOND);
	}

}

RT-Thread Nano入门学习笔记(1)_第19张图片

(2)RT-Thread Nano-线程讲解2

观察到新创建的线程名称被截断

RT-Thread Nano入门学习笔记(1)_第20张图片

此时可将reconfig.h文件中的#define RT_NAME_MAX 8修改为#define RT_NAME_MAX 16即可,如下:

RT-Thread Nano入门学习笔记(1)_第21张图片

将堆栈空间设置为4096,仿真运行之后在UART #1中运行list_thread命令没有看到我们建立的线程,说明线程没有建立成功,因为设置的堆栈太大了

RT-Thread Nano入门学习笔记(1)_第22张图片

我们实际设置的只有1024

RT-Thread Nano入门学习笔记(1)_第23张图片

将board.c中的#define RT_HEAP_SIZE 1024修改成#define RT_HEAP_SIZE 2048之后即可成功创建线程

RT-Thread Nano入门学习笔记(1)_第24张图片

6.RT-Thread Nano-自动初始化及MSH-EXPORT-1和2

(1)RT-Thread Nano-自动初始化及MSH-EXPORT-1

ChipInfo.c文件内容如下:

#include "config.h"
#include "ChipInfo.h"

uint32_t ChipUniqueID[3];

void GetChipID(void)
{
	ChipUniqueID[0]=*(volatile uint32_t *)(0x1FFFF7F0);//ID号高32位
	ChipUniqueID[1]=*(volatile uint32_t *)(0x1FFFF7EC);
	ChipUniqueID[2]=*(volatile uint32_t *)(0x1FFFF7E8);//ID号低字节
	rt_kprintf("\nChip ID is:0x%08X-%08X-%08X\n\n",ChipUniqueID[0],ChipUniqueID[1],ChipUniqueID[2]);
	
}
MSH_CMD_EXPORT(GetChipID, Get 96_bit unique Chip ID);

void GetFlashCapacity(void)
{
	rt_kprintf("\nChip Flash capacity is:%dK \n\n",*(volatile uint16_t *)(0x1FFFF7E0));
}
MSH_CMD_EXPORT(GetFlashCapacity, Get Chip Flash Capacity);

ChipInfo.h文件内容如下:

#ifndef __CHIPINFO_H__
#define __CHIPINFO_H__

void GetChipID(void);
void GetFlashCapacity(void);

#endif

还要记得在reconfig.h文件中加入#include "ChipInfo.h",如下:

RT-Thread Nano入门学习笔记(1)_第25张图片

连上开发板(stm32f103zet6)下载好程序:

RT-Thread Nano入门学习笔记(1)_第26张图片

RT-Thread Nano入门学习笔记(1)_第27张图片

RT-Thread Nano入门学习笔记(1)_第28张图片

下载安装好SecureCRT,如下:

RT-Thread Nano入门学习笔记(1)_第29张图片

连接

RT-Thread Nano入门学习笔记(1)_第30张图片

按下tab键并且运行GetChipID,如下:

RT-Thread Nano入门学习笔记(1)_第31张图片

运行GetFlashCapacity,如下:

RT-Thread Nano入门学习笔记(1)_第32张图片

可以观察到tshell达到100了,堆栈的利用率太高了,所以我们可以把线程的堆栈调大一点,即把

#define FINSH_THREAD_STACK_SIZE 512调成#define FINSH_THREAD_STACK_SIZE 1024

RT-Thread Nano入门学习笔记(1)_第33张图片

RT-Thread Nano入门学习笔记(1)_第34张图片

(2)RT-Thread Nano-自动初始化及MSH-EXPORT-1

修改GPIOA——>GPIOB,GPIO_Pin_5——>GPIO_Pin_8

添加BeepOn和BeepOff命令,并进行BeepGpioInit设置,如下:

INIT_BOARD_EXPORT(BeepGpioInit); 
//INIT_DEVICE_EXPORT(BeepGpioInit);
//INIT_ENV_EXPORT(BeepGpioInit);

void BeepOn(void)
{
	GPIO_SetBits(GPIOB,GPIO_Pin_8);
}
MSH_CMD_EXPORT(BeepOn, Control Beep On);

void BeepOff(void)
{
	GPIO_ResetBits(GPIOB,GPIO_Pin_8);
}
MSH_CMD_EXPORT(BeepOff, Control Beep Off);

测试是否成功:

RT-Thread Nano入门学习笔记(1)_第35张图片

查看STM32_Proj.map文件

RT-Thread Nano入门学习笔记(1)_第36张图片

RT-Thread Nano入门学习笔记(1)_第37张图片

RT-Thread Nano入门学习笔记(1)_第38张图片

7.RT-Thread Nano-串口接收(信号量使用)编写1

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-67h40myW-1625104968015)(C:\Users\xiaoyan\AppData\Roaming\Typora\typora-user-images\image-20210623191104565.png)]

先定义一个信号量的指针EXT rt_sem_t usart2_recv_sem;,如下:

RT-Thread Nano入门学习笔记(1)_第39张图片

然后进行串口的配置

	USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
	USART_ITConfig(USART2, USART_IT_IDLE, ENABLE);

RT-Thread Nano入门学习笔记(1)_第40张图片

创建信号量的函数:

void TaskInit(void)
{
	//返回值还是需要的,否则无法通过rt_thread_startup启动
	led_thread =  rt_thread_create("ledThread",
                             led_thread_entry,
                             RT_NULL,
                             256,
                             5,
                             10);
	if(led_thread != RT_NULL)
	{
		rt_thread_startup(led_thread);
	}
  usart2_recv_thread = rt_thread_create("usart2_recv_thread",
                             usart2_recv_thread_entry,
                             RT_NULL,
                             512,
                             2,
                             10);
	
	
	if(usart2_recv_thread != RT_NULL)
	{
		rt_thread_startup(usart2_recv_thread);
	}
}

添加usart2_recv_thread_entry函数

void usart2_recv_thread_entry(void *parameter)
{
	  rt_err_t uwRet = RT_EOK;
		while(1)
		{
		    uwRet = rt_sem_take(usart2_recv_thread, RT_WAITING_FOREVER);
				if(RT_EOK == uwRet)
				{
					rt_kprintf("Usart2 Receive Data is %s\n",g_USART2_RxBuf);
					if(strstr((char*)g_USART2_RxBuf,"BeepOn") != NULL)
					{
						BeepOn();
					}
					if(strstr((char*)g_USART2_RxBuf,"BeepOff") != NULL)
					{
						BeepOff();
						
					}
					memset(g_USART2_RxBuf,0,USART2_RX_BUF_SIZE);
					g_USART2_RecPos = 0;
				}
		}
}

修改USART2_IRQHandler,串口2中断回调函数,如下图:

void USART2_IRQHandler(void)
{
	
	#if USART2_EN == 1 
		//用户代码
	uint RecCh;
	#endif
	if( USART_GetFlagStatus(USART2,USART_FLAG_RXNE)!=RESET )				// 串口接收数据 
	{		
		#if USART2_EN == 1 
					 //用户代码
		RecCh = (uint8)USART_ReceiveData(USART2);
		g_USART2_RxBuf[g_USART2_RecPos++] == RecCh;
		#endif
		USART_ClearFlag(USART2, USART_FLAG_RXNE);
	}
	if( USART_GetFlagStatus(USART2,USART_FLAG_ORE)==SET ) 				// 串口溢出错误
	{
			USART_ClearFlag(USART2, USART_FLAG_ORE);
	}
	if( USART_GetFlagStatus(USART2,USART_FLAG_IDLE)==SET ) 				// 串口溢出错误
	{
		#if USART2_EN == 1 
					 //用户代码
		g_USART2_RxBuf[g_USART2_RecPos] == '\0';
		rt_sem_release(usart2_recv_sem);
		
		#endif
		
		USART_ReceiveData(USART2);
	}
}

运行无误:

RT-Thread Nano入门学习笔记(1)_第41张图片

你可能感兴趣的:(南京集成电路实训暑期线上学习,RT-Thread)