基于keil环境下mm32f327单片机rtthread的移植

基于keil环境下mm32f327单片机rtthread的移植


前言

第十七届智能车竞赛赛前准备,为 mm32f3277G9p 移植rtthread系统。

RT-Thread Nano 是一个极简版的硬实时内核,它是由 C 语言开发,采用面向对象的编程思维,具有良好的代码风格,是一款可裁剪的、抢占式实时多任务的 RTOS。其内存资源占用极小,功能包括任务处理、软件定时器、信号量、邮箱和实时调度等相对完整的实时操作系统特性。适用于家电、消费电子、医疗设备、工控等领域大量使用的 32 位 ARM 入门级 MCU 的场合。

灵动微MM32F3277系列采用高性能的ARM®Cortex®-M3为内核的32位单片机微控制器,工作频率可达高达120MHz,内置SRAM及内存高速存储器,丰富的I/O端口和外设连接到外部总线。
灵动微MM32F3277包含多达3个12位的ADC、2个比较器、2个16位通用定时器、2个32位通用定时器、2个16位基本定时器和2个16位高级定时器。还包含标准的通信接口:2个I2C接口、3个I2S接口、3个SPI接口、1个USBOTG全速接口、1个CAN接口、1个SDIO接口、1个Ethernet接口和8个UART接口。

一、所需资源

1、rtthread源码: RT_Thread开源库
2、mm32f3277逐飞库: 逐飞开源库

二、创建工程目录

目录如下:
CODE (用于存放用户编写的驱动代码)
Library (用于存放工程依赖的库文件和启动文件)
MDK (存放keil工程文件)
USER (存放主程序文件main.c等)
​​​​文件目录
在USER文件夹下新建inc和src子文件夹用于存放.c和.h文件。
之后在inc文件夹下新建isr.h文件,在src文件夹下新建isr.c和main.c文件。

三、复制所需文件到相应文件夹

将下载好的逐飞库源码中Library文件夹下的文件移动到工程Library文件夹中并新建rtthread_library文件夹。
Library文件夹目录结构
将下载好的rtthread源码中图示目录复制到rtthread_library文件夹下并新建bsp文件夹
rtthread_library文件夹目录结构
在rtt源码目录的bsp文件夹下找到mm32f327x文件夹,将其中的rtconfig.h文件复制到新建的bsp文件夹下,之后对整个rtthread_library文件夹下的文件进行裁剪。
裁剪后目录如下:
Components目录:
Components目录
finsh目录
include文件夹不做修改

libcpu文件夹仅留下arm\cortex-m3路径下的文件
libcpu文件夹
src文件夹下文件:
src文件夹

四、创建keil工程

Keil 新建工程到 MDK 文件夹下。
芯片型号选择为 MM32F3277G9p 。
keil工程创建创建分组目录如下:
工程分组

五、添加文件到工程

在 USER 分组添加:
USER 目录子文件夹 src 中的 .c 文件;
Library\rtthread_libraries\bsp 目录下的 .h 文件;
USER

CODE 分组加入自己配置的外设驱动;
board 分组添加 :
Library\seekfree_libraries\board 文件夹下的 board.c 文件;
board

common 分组加入 :
Library\seekfree_libraries\common 下的所有.c文件;
common

startup分组下添加 :
Library\Device\MM32F327x\Source 下的 system_mm32f327x.c 文件;
Library\Device\MM32F327x\Source\KEIL_StartAsm下的startup_mm32f327x
.c文件;
在这里插入图片描述

doc分组添加工程的说明文档;
seekfree_libraries分组下添加:
Library\seekfree_libraries目录下的.c文件;
seekfree_libraries

seekfree_peripheral分组下添加:
Library\seekfree_peripheral目录下的.c文件;
seekfree_peripheral

MM32_HAL分组下添加:
Library\Device\MM32F327x\HAL_Lib\Src目录下的.c文件;
MM32_HAL

rtt_src分组下添加:
Library\rtthread_libraries\src目录下的.c文件;
rtt_src

rtt_inc分组下添加:
Library\rtthread_libraries\include和Library\rtthread_libraries\include\libc目录下的.h文件;
rtt_inc

rtt_lib分组下添加:
Library\rtthread_libraries\libcpu目录下的context_rvds.S和cpuport.c文件;
rtt_lib

rtt_componer分组下添加:
Library\rtthread_libraries\components\finsh目录下的所有文件;
rtt_componer
添加头文件路径如下:
头文件路径

六、更改相应的.c文件

isr.c文件:

/*********************************************************************************************************************
* COPYRIGHT NOTICE
* Copyright (c) 2019,逐飞科技
* All rights reserved.
* 技术讨论QQ群:一群:179029047(已满)  二群:244861897
*
* 以下所有内容版权均属逐飞科技所有,未经允许不得用于商业用途,
* 欢迎各位使用并传播本程序,修改内容时必须保留逐飞科技的版权声明。
*
* @file				isr
* @company			成都逐飞科技有限公司
* @author			逐飞科技(QQ3184284598)
* @version			查看doc内version文件 版本说明
* @Software			IAR 8.3 or MDK 5.28
* @Target core		MM32F3277
* @Taobao			https://seekfree.taobao.com/
* @date				2021-02-22
********************************************************************************************************************/

#include "headfile.h"
#include "isr.h"

void TIM1_UP_IRQHandler (void)
{
	uint32 state = TIM1->SR;														// 读取中断状态
	TIM1->SR &= ~state;																// 清空中断状态
}

void TIM8_UP_IRQHandler (void)
{
	uint32 state = TIM8->SR;														// 读取中断状态
	TIM8->SR &= ~state;																// 清空中断状态
}

void TIM2_IRQHandler (void)
{
	uint32 state = TIM2->SR;														// 读取中断状态
	TIM2->SR &= ~state;																// 清空中断状态
}

void TIM5_IRQHandler (void)
{
	uint32 state = TIM5->SR;														// 读取中断状态
	TIM5->SR &= ~state;																// 清空中断状态
}

void TIM3_IRQHandler (void)
{
	uint32 state = TIM3->SR;														// 读取中断状态
	TIM3->SR &= ~state;																// 清空中断状态
}

void TIM4_IRQHandler (void)
{
	uint32 state = TIM4->SR;														// 读取中断状态
	TIM4->SR &= ~state;																// 清空中断状态
}

void TIM6_IRQHandler (void)
{
	uint32 state = TIM6->SR;														// 读取中断状态
	TIM6->SR &= ~state;																// 清空中断状态
}

void TIM7_IRQHandler (void)
{
	uint32 state = TIM7->SR;														// 读取中断状态
	TIM7->SR &= ~state;																// 清空中断状态
}

//void UART1_IRQHandler(void)
//{
//	if(UART1->ISR & UART_ISR_TX_INTF)												// 串口发送缓冲空中断
//	{
//		UART1->ICR |= UART_ICR_TXICLR;												// 清除中断标志位
//	}
//	if(UART1->ISR & UART_ISR_RX_INTF)												// 串口接收缓冲中断
//	{
//		UART1->ICR |= UART_ICR_RXICLR;												// 清除中断标志位
//	}
//}

void UART2_IRQHandler(void)
{
	if(UART2->ISR & UART_ISR_TX_INTF)												// 串口发送缓冲空中断
	{
		UART2->ICR |= UART_ICR_TXICLR;												// 清除中断标志位
	}
	if(UART2->ISR & UART_ISR_RX_INTF)												// 串口接收缓冲中断
	{
		UART2->ICR |= UART_ICR_RXICLR;												// 清除中断标志位
	}
}

void UART3_IRQHandler(void)
{
	if(UART3->ISR & UART_ISR_TX_INTF)												// 串口发送缓冲空中断
	{
		UART3->ICR |= UART_ICR_TXICLR;												// 清除中断标志位
	}
	if(UART3->ISR & UART_ISR_RX_INTF)												// 串口接收缓冲中断
	{
		UART3->ICR |= UART_ICR_RXICLR;												// 清除中断标志位
	}
}

void UART4_IRQHandler(void)
{
	if(UART4->ISR & UART_ISR_TX_INTF)												// 串口发送缓冲空中断
	{
		UART4->ICR |= UART_ICR_TXICLR;												// 清除中断标志位
	}
	if(UART4->ISR & UART_ISR_RX_INTF)												// 串口接收缓冲中断
	{
		UART4->ICR |= UART_ICR_RXICLR;												// 清除中断标志位
	}
}

void UART5_IRQHandler(void)
{
	if(UART5->ISR & UART_ISR_TX_INTF)												// 串口发送缓冲空中断
	{
		UART5->ICR |= UART_ICR_TXICLR;												// 清除中断标志位
	}
	if(UART5->ISR & UART_ISR_RX_INTF)												// 串口接收缓冲中断
	{
		UART5->ICR |= UART_ICR_RXICLR;												// 清除中断标志位
	}
}

void UART6_IRQHandler(void)
{
	if(UART6->ISR & UART_ISR_TX_INTF)												// 串口发送缓冲空中断
	{
		UART6->ICR |= UART_ICR_TXICLR;												// 清除中断标志位
	}
	if(UART6->ISR & UART_ISR_RX_INTF)												// 串口接收缓冲中断
	{
		UART6->ICR |= UART_ICR_RXICLR;												// 清除中断标志位
	}
}

void UART7_IRQHandler(void)
{
	if(UART7->ISR & UART_ISR_TX_INTF)												// 串口发送缓冲空中断
	{
		UART7->ICR |= UART_ICR_TXICLR;												// 清除中断标志位
	}
	if(UART7->ISR & UART_ISR_RX_INTF)												// 串口接收缓冲中断
	{
		UART7->ICR |= UART_ICR_RXICLR;												// 清除中断标志位
	}
}

void UART8_IRQHandler(void)
{
	if(UART8->ISR & UART_ISR_TX_INTF)												// 串口发送缓冲空中断
	{
		UART8->ICR |= UART_ICR_TXICLR;												// 清除中断标志位
	}
	if(UART8->ISR & UART_ISR_RX_INTF)												// 串口接收缓冲中断
	{
		UART8->ICR |= UART_ICR_RXICLR;												// 清除中断标志位
		switch(camera_type)															// 查询摄像头类型 未初始化摄像头则此处会进入default
		{
			case CAMERA_BIN_UART: 													// 串口小钻风
				ov7725_cof_uart_interrupt();										// 调用串口小钻风的串口接收处理
				break;
			case CAMERA_GRAYSCALE: 													// 总钻风
				mt9v03x_uart_callback();											// 调用总钻风的串口接收处理
				break;
			default:
				break;
		}
	}
}

void EXTI0_IRQHandler(void)
{
	// 检测与清除中断标志可以根据实际应用进行删改
	EXTI_ClearFlag(EXTI_Line0);														// 清除 line0 触发标志
}

void EXTI1_IRQHandler(void)
{
	// 检测与清除中断标志可以根据实际应用进行删改
	EXTI_ClearFlag(EXTI_Line1);														// 清除 line1 触发标志
}

void EXTI2_IRQHandler(void)
{
	// 检测与清除中断标志可以根据实际应用进行删改
	EXTI_ClearFlag(EXTI_Line2);														// 清除 line2 触发标志
}

void EXTI3_IRQHandler(void)
{
	// 检测与清除中断标志可以根据实际应用进行删改
	EXTI_ClearFlag(EXTI_Line3);														// 清除 line3 触发标志
}

void EXTI4_IRQHandler(void)
{
	// 检测与清除中断标志可以根据实际应用进行删改
	EXTI_ClearFlag(EXTI_Line4);														// 清除 line4 触发标志
}

void EXTI9_5_IRQHandler(void)
{
	// 检测与清除中断标志可以根据实际应用进行删改
	if(EXTI_GetITStatus(EXTI_Line5))												// 检测 line5 是否触发
	{
		EXTI_ClearFlag(EXTI_Line5);													// 清除 line5 触发标志
	}
	if(EXTI_GetITStatus(EXTI_Line6))												// 检测 line6 是否触发
	{
		EXTI_ClearFlag(EXTI_Line6);													// 清除 line6 触发标志
	}
	if(EXTI_GetITStatus(EXTI_Line7))												// 检测 line7 是否触发
	{
		EXTI_ClearFlag(EXTI_Line7);													// 清除 line8 触发标志
	}
	if(EXTI_GetITStatus(EXTI_Line8))												// 检测 line8 是否触发
	{
		switch(camera_type)															// 查询摄像头类型 未初始化摄像头则此处会进入default
		{
			case CAMERA_BIN:  														// IIC小钻风
				ov7725_vsync();
				break;
			case CAMERA_BIN_UART:  													// 串口小钻风
				ov7725_uart_vsync();
				break;
			case CAMERA_GRAYSCALE: 													// 总钻风
				mt9v03x_vsync();
				break;
			default:
				break;
		}
		EXTI_ClearFlag(EXTI_Line8);													// 清除 line8 触发标志
	}
	if(EXTI_GetITStatus(EXTI_Line9))												// 检测 line9 是否触发
	{
		EXTI_ClearFlag(EXTI_Line9);													// 清除 line9 触发标志
	}
}

void EXTI15_10_IRQHandler (void)
{
	// 检测与清除中断标志可以根据实际应用进行删改
	if(EXTI_GetITStatus(EXTI_Line10))												// 检测 line10 是否触发
	{
		EXTI_ClearFlag(EXTI_Line10);												// 清除 line10 触发标志
	}
	if(EXTI_GetITStatus(EXTI_Line11))												// 检测 line11 是否触发
	{
		EXTI_ClearFlag(EXTI_Line11);												// 清除 line11 触发标志
	}
	if(EXTI_GetITStatus(EXTI_Line12))												// 检测 line12 是否触发
	{
		EXTI_ClearFlag(EXTI_Line12);												// 清除 line12 触发标志
	}
	if(EXTI_GetITStatus(EXTI_Line13))												// 检测 line13 是否触发
	{
		EXTI_ClearFlag(EXTI_Line13);												// 清除 line13 触发标志
	}
	if(EXTI_GetITStatus(EXTI_Line14))												// 检测 line14 是否触发
	{
		EXTI_ClearFlag(EXTI_Line14);												// 清除 line14 触发标志
	}
	if(EXTI_GetITStatus(EXTI_Line15))												// 检测 line15 是否触发
	{
		EXTI_ClearFlag(EXTI_Line15);												// 清除 line15 触发标志
	}
}

void DMA1_Channel1_IRQHandler(void)
{
	if(SET == DMA_GetFlagStatus(DMA1_FLAG_TC1))										// 判断触发通道
	{
		DMA_ClearFlag(DMA1_FLAG_TC1);												// 清空该通道中断标志
	}
}

void DMA1_Channel2_IRQHandler(void)
{
	if(SET == DMA_GetFlagStatus(DMA1_FLAG_TC2))										// 判断触发通道
	{
		DMA_ClearFlag(DMA1_FLAG_TC2);												// 清空该通道中断标志
	}
}

void DMA1_Channel3_IRQHandler(void)
{
	if(SET == DMA_GetFlagStatus(DMA1_FLAG_TC3))										// 判断触发通道
	{
		DMA_ClearFlag(DMA1_FLAG_TC3);												// 清空该通道中断标志
	}
}

void DMA1_Channel4_IRQHandler(void)
{
	if(SET == DMA_GetFlagStatus(DMA1_FLAG_TC4))										// 判断触发通道
	{
		DMA_ClearFlag(DMA1_FLAG_TC4);												// 清空该通道中断标志
		switch(camera_type)															// 查询摄像头类型 未初始化摄像头则此处会进入default
		{
			case CAMERA_BIN:  														// IIC小钻风
				ov7725_dma();
				break;
			case CAMERA_BIN_UART:  													// 串口小钻风
				ov7725_uart_dma();
				break;
			case CAMERA_GRAYSCALE: 													// 总钻风
				mt9v03x_dma();
				break;
			default:
				break;
		}
	}
}

void DMA1_Channel5_IRQHandler(void)
{
	if(SET == DMA_GetFlagStatus(DMA1_FLAG_TC5))										// 判断触发通道
	{
		DMA_ClearFlag(DMA1_FLAG_TC5);												// 清空该通道中断标志
	}
}

void DMA1_Channel6_IRQHandler(void)
{
	if(SET == DMA_GetFlagStatus(DMA1_FLAG_TC6))										// 判断触发通道
	{
		DMA_ClearFlag(DMA1_FLAG_TC6);												// 清空该通道中断标志
	}
}

void DMA1_Channel7_IRQHandler(void)
{
	if(SET == DMA_GetFlagStatus(DMA1_FLAG_TC7))										// 判断触发通道
	{
		DMA_ClearFlag(DMA1_FLAG_TC7);												// 清空该通道中断标志
	}
}

void DMA2_Channel1_IRQHandler(void)
{
	if(SET == DMA_GetFlagStatus(DMA2_FLAG_TC1))										// 判断触发通道
	{
		DMA_ClearFlag(DMA2_FLAG_TC1);												// 清空该通道中断标志
	}
}

void DMA2_Channel2_IRQHandler(void)
{
	if(SET == DMA_GetFlagStatus(DMA2_FLAG_TC2))										// 判断触发通道
	{
		DMA_ClearFlag(DMA2_FLAG_TC2);												// 清空该通道中断标志
	}
}

void DMA2_Channel3_IRQHandler(void)
{
	if(SET == DMA_GetFlagStatus(DMA2_FLAG_TC3))										// 判断触发通道
	{
		DMA_ClearFlag(DMA2_FLAG_TC3);												// 清空该通道中断标志
	}
}

void DMA2_Channel4_IRQHandler(void)
{
	if(SET == DMA_GetFlagStatus(DMA2_FLAG_TC4))										// 判断触发通道
	{
		DMA_ClearFlag(DMA2_FLAG_TC4);												// 清空该通道中断标志
	}
}

void DMA2_Channel5_IRQHandler(void)
{
	if(SET == DMA_GetFlagStatus(DMA2_FLAG_TC5))										// 判断触发通道
	{
		DMA_ClearFlag(DMA2_FLAG_TC5);												// 清空该通道中断标志
	}
}

#ifdef Will_never_be_defined
WWDG_IRQHandler
PVD_IRQHandler
TAMPER_IRQHandler
RTC_IRQHandler
FLASH_IRQHandler
RCC_CRS_IRQHandler
EXTI0_IRQHandler
EXTI1_IRQHandler
EXTI2_IRQHandler
EXTI3_IRQHandler
EXTI4_IRQHandler
DMA1_Channel1_IRQHandler
DMA1_Channel2_IRQHandler
DMA1_Channel3_IRQHandler
DMA1_Channel4_IRQHandler
DMA1_Channel5_IRQHandler
DMA1_Channel6_IRQHandler
DMA1_Channel7_IRQHandler
ADC1_2_IRQHandler
FlashCache_IRQHandler
CAN1_RX_IRQHandler
EXTI9_5_IRQHandler
TIM1_BRK_IRQHandler
TIM1_UP_IRQHandler
TIM1_TRG_COM_IRQHandler
TIM1_CC_IRQHandler
TIM2_IRQHandler
TIM3_IRQHandler
TIM4_IRQHandler
I2C1_IRQHandler
I2C2_IRQHandler
SPI1_IRQHandler
SPI2_IRQHandler
UART1_IRQHandler
UART2_IRQHandler
UART3_IRQHandler
EXTI15_10_IRQHandler
RTCAlarm_IRQHandler
OTG_FS_WKUP_IRQHandler
TIM8_BRK_IRQHandler
TIM8_UP_IRQHandler
TIM8_TRG_COM_IRQHandler
TIM8_CC_IRQHandler
ADC3_IRQHandler
SDIO_IRQHandler
TIM5_IRQHandler
SPI3_IRQHandler
UART4_IRQHandler
UART5_IRQHandler
TIM6_IRQHandler
TIM7_IRQHandler
DMA2_Channel1_IRQHandler
DMA2_Channel2_IRQHandler
DMA2_Channel3_IRQHandler
DMA2_Channel4_IRQHandler
DMA2_Channel5_IRQHandler
ETH_IRQHandler
COMP1_2_IRQHandler
OTG_FS_IRQHandler
UART6_IRQHandler
UART7_IRQHandler
UART8_IRQHandler
#endif

main.c文件:

/*********************************************************************************************************************
* COPYRIGHT NOTICE
* Copyright (c) 2019,逐飞科技
* All rights reserved.
* 技术讨论QQ群:一群:179029047(已满)  二群:244861897
*
* 以下所有内容版权均属逐飞科技所有,未经允许不得用于商业用途,
* 欢迎各位使用并传播本程序,修改内容时必须保留逐飞科技的版权声明。
*
* @file				main
* @company			成都逐飞科技有限公司
* @author			逐飞科技(QQ3184284598)
* @version			查看doc内version文件 版本说明
* @Software			IAR 8.3 or MDK 5.24
* @Target core		MM32F3277
* @Taobao			https://seekfree.taobao.com/
* @date				2021-02-22
********************************************************************************************************************/

#include "headfile.h"
#include "isr.h"
// **************************** 宏定义 ****************************

// **************************** 宏定义 ****************************

// **************************** 变量定义 ****************************

// **************************** 变量定义 ****************************

// **************************** 代码区域 ****************************
//-------------------------------------------------------------------------------------------------------------------
//  @brief      线程1入口
//  @param      parameter   参数
//  @return     void
//  Sample usage:
//-------------------------------------------------------------------------------------------------------------------
void thread1_entry(void *parameter)
{

    while(1)
    {
        rt_kprintf("dynamic thread is running.\n");
        rt_thread_mdelay(1000);
    }
}

//-------------------------------------------------------------------------------------------------------------------
//  @brief      线程2入口
//  @param      parameter   参数
//  @return     void
//  Sample usage:
//-------------------------------------------------------------------------------------------------------------------
void thread2_entry(void *parameter)
{

    while(1)
    {
        rt_kprintf("static thread is running.\n");
        rt_thread_mdelay(500);
    }
}



//-------------------------------------------------------------------------------------------------------------------
//  @brief      动态线程创建以及启动
//  @param      void        空
//  @return     void
//  Sample usage:
//-------------------------------------------------------------------------------------------------------------------
int dynamic_thread_example(void)
{
    //线程控制块指针
    rt_thread_t tid1;
    //创建动态线程
    tid1 = rt_thread_create("thread1",      //线程名称
            thread1_entry,                  //线程入口函数
            RT_NULL,                        //线程参数
            512,                            //512个字节的栈空间
            5,                              //线程优先级为5,数值越小,优先级越高,0为最高优先级。
                                            //可以通过修改rt_config.h中的RT_THREAD_PRIORITY_MAX宏定义(默认值为8)来修改最大支持的优先级
            5);                             //时间片为5

    rt_kprintf("create dynamic thread.\n");
    if(tid1 != RT_NULL)                     //线程创建成功
    {
        rt_kprintf("thread1 dynamic thread create OK.\n");
        rt_thread_startup(tid1);            //运行该线程
    }
    else                                    //线程创建失败
    {
        rt_kprintf("thread1 dynamic thread create ERROR.\n");
        return 1;
    }

    return 0;
}

//-------------------------------------------------------------------------------------------------------------------
//  @brief      静态线程创建以及启动
//  @param      void        空
//  @return     void
//  Sample usage:
//-------------------------------------------------------------------------------------------------------------------
static rt_uint8_t thread2_stack[1024];  //线程栈数组
struct rt_thread thread2_thread;        //线程控制块
int static_thread_example(void)
{
    rt_err_t res;
    //创建静态线程
    res = rt_thread_init(
                &thread2_thread,                //线程控制块
                "thread2",                      //线程名称
                thread2_entry,                  //线程入口函数
                RT_NULL,                        //线程参数
                thread2_stack,                  //栈的起始地址
                sizeof(thread2_stack),          //栈大小
                3,                              //线程优先级为3,数值越小,优先级越高,0为最高优先级。
                                                //可以通过修改rt_config.h中的RT_THREAD_PRIORITY_MAX宏定义(默认值为8)来修改最大支持的优先级
                5                               //时间片为5
            );

    rt_kprintf("create static thread.\n");

    if(res == RT_EOK)                                       //线程创建成功
    {
        rt_kprintf("thread2 static thread create OK\n");
        rt_thread_startup(&thread2_thread);                 //运行该线程

    }
    else                                                    //线程创建失败
    {
        rt_kprintf("thread2 static thread create ERROR\n");
        return 1;
    }
    return 0;
}

//使用INIT_APP_EXPORT宏自动初始化,也可以通过在其他线程内调用dynamic_thread_example函数进行初始化
INIT_APP_EXPORT(dynamic_thread_example);     //应用初始化

//使用INIT_APP_EXPORT宏自动初始化,也可以通过在其他线程内调用static_thread_example函数进行初始化
INIT_APP_EXPORT(static_thread_example);      //应用初始化

//静态创建方法
//当我们没有开启RT_USING_HEAP宏定义我们只能使用静态的方法创建线程、信号量、互斥量等等
//或者当我们想要指定控制块控制块或者栈的位置的时候,也可以用静态创建方法



//动态创建方法
//动态创建务必开启RT_USING_HEAP宏定义
//动态创建好处在于我们不用自己定义控制块或者栈数组,创建的时候填写的参数更加的少非常的方便
//如果HEAP大小不够了,可以在board.c中找到RT_HEAP_SIZE宏进行修改



int main(void)
{
	//此处编写用户代码(例如:外设初始化代码等)
	gpio_init(H2, GPO, 0, GPO_PUSH_PULL);
	//此处编写用户代码(例如:外设初始化代码等)

	while(1)
	{
		rt_thread_mdelay(100);
    gpio_toggle(H2);
	}
}
// **************************** 代码区域 ****************************

board.c文件:

/*********************************************************************************************************************
* COPYRIGHT NOTICE
* Copyright (c) 2019,逐飞科技
* All rights reserved.
* 技术讨论QQ群:一群:179029047(已满)  二群:244861897
*
* 以下所有内容版权均属逐飞科技所有,未经允许不得用于商业用途,
* 欢迎各位使用并传播本程序,修改内容时必须保留逐飞科技的版权声明。
*
* @file				board.c
* @company			成都逐飞科技有限公司
* @author			逐飞科技(QQ3184284598)
* @version			查看doc内version文件 版本说明
* @Software			IAR 8.32.4 or MDK 5.28
* @Target core		MM32F3277
* @Taobao			https://seekfree.taobao.com/
* @date				2021-02-22
********************************************************************************************************************/

#include "board.h"
#include "zf_uart.h"
#include <rtthread.h>
#include "mm32_reg_redefine_v1.h"

extern uint32_t SystemCoreClock;

//finsh组件接收串口数据,是通过在串口中断内发送邮件,finsh线程接收邮件进行获取的
rt_mailbox_t uart_mb;

static uint32_t systick_config(rt_uint32_t ticks)
{
    if ((ticks - 1) > 0xFFFFFF)
    {
        return 1;
    }

    SysTick->LOAD = ticks - 1; 
    nvic_init(SysTick_IRQn, 3, ENABLE);
    SysTick->VAL  = 0;
    SysTick->CTRL = 0x07;  
    
    return 0;
}

#if defined(RT_USING_USER_MAIN) && defined(RT_USING_HEAP)
#define RT_HEAP_SIZE 700

static uint32_t rt_heap[RT_HEAP_SIZE];     // heap default size: 4K(1024 * 4)
RT_WEAK void *rt_heap_begin_get(void)
{
    return rt_heap;
}

RT_WEAK void *rt_heap_end_get(void)
{
    return rt_heap + RT_HEAP_SIZE;
}
#endif


void rt_hw_board_init()
{
    systick_config(SystemCoreClock / RT_TICK_PER_SECOND);
    
    board_init(1);
    
    /* 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
    
    uart_mb = rt_mb_create("uart_mb", 10, RT_IPC_FLAG_FIFO);
}


void SysTick_Handler(void)
{
    rt_interrupt_enter();

    rt_tick_increase();


    rt_interrupt_leave();
}

void rt_hw_console_output(const char *str)
{
    while(RT_NULL != *str)
    {
        if('\n' == *str)
        {
            uart_putchar(DEBUG_UART, '\r');
        }
        uart_putchar(DEBUG_UART, *str++);
    }
}



char rt_hw_console_getchar(void)
{
    uint32 dat;
    //等待邮件
    rt_mb_recv(uart_mb, &dat, RT_WAITING_FOREVER);
    //uart_getchar(DEBUG_UART, &dat);
    return (char)dat;
}

//-------------------------------------------------------------------------------------------------------------------
// @brief		核心板初始化
// @param		debug_enable	是否开启默认 debug 输出 DEBUG_UART 默认 UART1 
// @return		void
// Sample usage:				board_init(TRUE);
//-------------------------------------------------------------------------------------------------------------------
void board_init (bool debug_enable)
{
	if(debug_enable)
    {
        uart_init(DEBUG_UART, DEBUG_UART_BAUD, DEBUG_UART_TX, DEBUG_UART_RX);					// 默认初始化 UART1 用以支持 printf 输出
    }

    uart_rx_irq(DEBUG_UART, 1);
}

void UART1_IRQHandler(void)
{
    uint8 dat;
    rt_interrupt_enter();
	if(UART1->ISR & UART_ISR_TX_INTF)		// 串口发送缓冲空中断
	{
		UART1->ICR |= UART_ICR_TXICLR;		// 清除中断标志位
	}
	if(UART1->ISR & UART_ISR_RX_INTF)		// 串口接收缓冲中断
	{
		uart_getchar(DEBUG_UART, &dat);
        rt_mb_send(uart_mb, dat);           // 发送邮件
        UART1->ICR |= UART_ICR_RXICLR;		// 清除中断标志位
	}
    rt_interrupt_leave();
}



rtconfig.h文件:

/* RT-Thread config file */

#ifndef __RTTHREAD_CFG_H__
#define __RTTHREAD_CFG_H__

#if defined(__CC_ARM) || defined(__CLANG_ARM)
//#include "RTE_Components.h" // 用来开关 FinSH 组件,仅 MDK 会产生该文件


#if defined(RTE_USING_FINSH)
#define RT_USING_FINSH
#endif //RTE_USING_FINSH

#endif //(__CC_ARM) || (__CLANG_ARM)



// <<< Use Configuration Wizard in Context Menu >>>
// <h>Basic Configuration
// <o>Maximal level of thread priority <8-256>
//  <i>Default: 32
#define RT_THREAD_PRIORITY_MAX  8
// <o>OS tick per second
//  <i>Default: 1000   (1ms)
#define RT_TICK_PER_SECOND  1000
// <o>Alignment size for CPU architecture data access
//  <i>Default: 4
#define RT_ALIGN_SIZE   4
// <o>the max length of object name<2-16>
//  <i>Default: 8
#define RT_NAME_MAX    8
// <c1>Using RT-Thread components initialization
//  <i>Using RT-Thread components initialization
#define RT_USING_COMPONENTS_INIT
// </c>

#define RT_USING_USER_MAIN

// <o>the stack size of main thread<1-4086>
//  <i>Default: 512
#define RT_MAIN_THREAD_STACK_SIZE     512

// </h>

// <h>Debug Configuration
// <c1>enable kernel debug configuration
//  <i>Default: enable kernel debug configuration
//#define RT_DEBUG
// </c>
// <o>enable components initialization debug configuration<0-1>
//  <i>Default: 0
#define RT_DEBUG_INIT 0
// <c1>thread stack over flow detect
//  <i> Diable Thread stack over flow detect
//#define RT_USING_OVERFLOW_CHECK
// </c>
// </h>

// <h>Hook Configuration
// <c1>using hook
//  <i>using hook
//#define RT_USING_HOOK
// </c>
// <c1>using idle hook
//  <i>using idle hook
//#define RT_USING_IDLE_HOOK
// </c>
// </h>

// <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        3
// <o>The stack size of timer thread <0-8192>
//  <i>Default: 512
#define RT_TIMER_THREAD_STACK_SIZE  256
// </e>

// <h>IPC(Inter-process communication) Configuration
// <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>Dynamic Heap Management
//  <i>Dynamic Heap Management
#define RT_USING_HEAP
// </c>
// <c1>using small memory
//  <i>using small memory
#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>

#define RT_USING_FINSH


#if defined(RT_USING_FINSH)
    #define FINSH_USING_MSH
    #define FINSH_USING_MSH_ONLY
    // <h>Finsh Configuration
    // <o>the priority of finsh thread <1-7>
    //  <i>the priority of finsh thread
    //  <i>Default: 6
    #define __FINSH_THREAD_PRIORITY     4
    #define FINSH_THREAD_PRIORITY       (RT_THREAD_PRIORITY_MAX / 8 * __FINSH_THREAD_PRIORITY + 1)
    // <o>the stack of finsh thread <1-4096>
    //  <i>the stack of finsh thread
    //  <i>Default: 4096  (4096Byte)
    #define FINSH_THREAD_STACK_SIZE     768
    // <o>the history lines of finsh thread <1-32>
    //  <i>the history lines of finsh thread
    //  <i>Default: 5
    #define FINSH_HISTORY_LINES         1

    #define FINSH_USING_SYMTAB
    // </h>
#endif

// <<< end of configuration section >>>

#endif

common.c文件:

/*********************************************************************************************************************
* COPYRIGHT NOTICE
* Copyright (c) 2019,逐飞科技
* All rights reserved.
* 技术讨论QQ群:一群:179029047(已满)  二群:244861897
*
* 以下所有内容版权均属逐飞科技所有,未经允许不得用于商业用途,
* 欢迎各位使用并传播本程序,修改内容时必须保留逐飞科技的版权声明。
*
* @file				common.c
* @company			成都逐飞科技有限公司
* @author			逐飞科技(QQ3184284598)
* @version			查看doc内version文件 版本说明
* @Software			IAR 8.32.4 or MDK 5.28
* @Target core		MM32F3277
* @Taobao			https://seekfree.taobao.com/
* @date				2021-02-22
********************************************************************************************************************/
 
#include "common.h"
#include "hal_misc.h"

CAMERA_TYPE_enum camera_type;													// 摄像头类型变量
uint8 *camera_buffer_addr;														// 摄像头缓冲区地址指针

//-------------------------------------------------------------------------------------------------------------------
// @brief		中断初始化
// @param		irqn			中断号,可以查看 reg_common.h 文件中的 IRQn_Type 枚举体定义
// @param		priority		选择该中断优先级 范围 [0-7]
// @param		status			使能或者失能
// @return		void
// Sample usage:				nvic_init(EXTI0_IRQn, 0, ENABLE);				// 外部中断0使能,抢占优先级最高
//-------------------------------------------------------------------------------------------------------------------
void nvic_init(IRQn_Type irqn, uint8 priority, FunctionalState status)
{
	NVIC_InitTypeDef NVIC_InitStructure;

	NVIC_InitStructure.NVIC_IRQChannel = irqn;                                  // 中断号设置
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority= priority & 0x07;		// 抢占优先级值越小,优先级越高
	NVIC_InitStructure.NVIC_IRQChannelSubPriority= 0;							// 响应优先级值越小,优先级越高
	NVIC_InitStructure.NVIC_IRQChannelCmd = status;								// 使能
	NVIC_Init(&NVIC_InitStructure);
}

//-------------------------------------------------------------------------------------------------------------------
// @brief		全局中断使能
// @return		void
// Sample usage:				nvic_interrput_enable();
//-------------------------------------------------------------------------------------------------------------------
void nvic_interrput_enable (void)
{
	__ASM volatile("cpsie i");
}

//-------------------------------------------------------------------------------------------------------------------
// @brief		全局中断失能
// @return		void
// Sample usage:				nvic_interrput_disable();
//-------------------------------------------------------------------------------------------------------------------
void nvic_interrput_disable (void)
{
	__ASM volatile("cpsid i");
}

void NMI_Handler(void)
{
	while(1);
}
//void HardFault_Handler(void)
//{
//	//硬件上访  可能是数组越界或者使用了未初始化的设备
//	//这里提示大家一个问题,经常有人说我的外设初始化了怎么就是要进HardFault呢
//	//很多是因为自己开了中断,然后在中断里面使用了外设,然后他的初始化顺序是先初始化中断然后再初始化外设
//	//那么问题就来了,中断初始化完成之后会部分中断直接进入中断函数或者满足调节也会进入中断函数,那么就会造成中断里面使用到的外设还没被初始化
//	//所以大家需要注意这个问题
//	while(1);
//}
void MemManage_Handler(void)
{
	while(1);
}
void BusFault_Handler(void)
{
	while(1);
}
void UsageFault_Handler(void)
{
	while(1);
}
void SVC_Handler(void)
{
	while(1);
}
void DebugMon_Handler(void)
{
	while(1);
}
//void PendSV_Handler(void)
//{
//	while(1);
//}

headfile.h文件添加“#include “rtthread.h””

//RTT头文件
#include “rtthread.h”

七、编译运行

可看到板载led持续闪烁
串口持续打印如下数据:
串口打印数据

工程源码链接: MM32_RT_thread_Demo.

  • 4
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值