stm32移植RT-Thread Nano实现Finsh全步骤
- 准备工作
- stm32f103裸机点灯源码
- keil安装RT-Thread Nano Pack。(RT-Thread 文档中心有下载连接,下载完毕直接点击安装)
步骤详解
-
添加RT-Thread Nano到工程 (这里的步骤见RT-Thread 文档中心,链接在文章头部) -
删除 stm32f10x_it.c 中的 HardFault_Handler 以及PendSV_Handler 函数,这两个函数已经由RT-Thread实现 -
此时会出现 #error "TODO 1: OS Tick Configuration. 错误,提醒你配置时钟 -
在board.c 中实现时钟的配置操作 rt_hw_board_init 函数 - a:注释掉提示代码#error "TODO 1: OS Tick Configuration." - b:添加系统时钟配置 SysTick_Config(SystemCoreClock / RT_TICK_PER_SECOND); - - c:在`board.c`中添加下列函数,添加完毕之后删除` `stm32f10x_it.c`中的SysTick_Handler`函数。
void SysTick_Handler()
{
rt_interrupt_enter();
rt_tick_increase();
rt_interrupt_leave();
}
5.此时RT-Thread内核已经移植完毕,在main函数中添加相关代码测试,记得添加RT-Thread头文件#include <rtthread.h>
int main(void)
{
/* LED 端口初始化 */
LED_GPIO_Config();
led1_thread = /* 线程控制块指针 */
rt_thread_create( "led1", /* 线程名字 */
led1_thread_entry, /* 线程入口函数 */
RT_NULL, /* 线程入口函数参数 */
512, /* 线程栈大小 */
3, /* 线程的优先级 */
20); /* 线程时间片 */
/* 启动线程,开启调度 */
if (led1_thread != RT_NULL)
rt_thread_startup(led1_thread);
else
return -1;
}
void led1_thread_entry( void *parameter)
{
while(1)
{
LED1_ON;
rt_thread_delay(500);
LED1_OFF;
rt_thread_delay(500);
}
}
这里已经完成内核移植测试,接下来移植finsh组件
finsh移植,finsh一般通过串口和用户交互
- 新建文件夹,串口实现初始化,并且添加头文件路径
-------------------------------
(bsp_usart.c)
------------------------------
#include "bsp_usart.h"
#include <rtthread.h>
/**
* @brief USART GPIO 配置,工作参数配置
* @param 无
* @retval 无
*/
void USART_Config( void )
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
// 打开串口GPIO的时钟
DEBUG_USART_GPIO_APBxClkCmd( DEBUG_USART_GPIO_CLK, ENABLE );
// 打开串口外设的时钟
DEBUG_USART_APBxClkCmd( DEBUG_USART_CLK, ENABLE );
// 将USART Tx的GPIO配置为推挽复用模式
GPIO_InitStructure.GPIO_Pin = DEBUG_USART_TX_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init( DEBUG_USART_TX_GPIO_PORT, &GPIO_InitStructure );
// 将USART Rx的GPIO配置为浮空输入模式
GPIO_InitStructure.GPIO_Pin = DEBUG_USART_RX_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init( DEBUG_USART_RX_GPIO_PORT, &GPIO_InitStructure );
// 配置串口的工作参数
// 配置波特率
USART_InitStructure.USART_BaudRate = DEBUG_USART_BAUDRATE;
// 配置 针数据字长
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( DEBUG_USARTx, &USART_InitStructure );
// 使能串口
USART_Cmd( DEBUG_USARTx, ENABLE );
}
-------------------------------
bsp_usart.h
-------------------------------
#ifndef __USART_H
#define __USART_H
#include "stm32f10x.h"
#include <stdio.h>
/**
* 串口宏定义,不同的串口挂载的总线和IO不一样,移植时需要修改这几个宏
* 1-修改总线时钟的宏,uart1挂载到apb2总线,其他uart挂载到apb1总线
* 2-修改GPIO的宏
*/
// 串口1-USART1
#define DEBUG_USARTx USART1
#define DEBUG_USART_CLK RCC_APB2Periph_USART1
#define DEBUG_USART_APBxClkCmd RCC_APB2PeriphClockCmd
#define DEBUG_USART_BAUDRATE 115200
// USART GPIO 引脚宏定义
#define DEBUG_USART_GPIO_CLK (RCC_APB2Periph_GPIOA)
#define DEBUG_USART_GPIO_APBxClkCmd RCC_APB2PeriphClockCmd
#define DEBUG_USART_TX_GPIO_PORT GPIOA
#define DEBUG_USART_TX_GPIO_PIN GPIO_Pin_9
#define DEBUG_USART_RX_GPIO_PORT GPIOA
#define DEBUG_USART_RX_GPIO_PIN GPIO_Pin_10
#define DEBUG_USART_IRQ USART1_IRQn
#define DEBUG_USART_IRQHandler USART1_IRQHandler
void USART_Config(void);
#endif /* __USART_H */
- 在
board.h 中有以下代码,所以在rtconfig.h 中定义RT_USING_CONSOLE ,打开下面代码,并且两个error提示注释掉
(board.c)
#ifdef RT_USING_CONSOLE
static int uart_init(void)
{
#error "TODO 2: Enable the hardware uart and config baudrate."
return 0;
}
INIT_BOARD_EXPORT(uart_init);
void rt_hw_console_output(const char *str)
{
#error "TODO 3: Output the string 'str' through the uart."
}
#endif
- 修改为以下代码,注意包含串口的头文件,以及头文件"stm32f10x.h"
(board.c)
static int uart_init(void)
{
//#error "TODO 2: Enable the hardware uart and config baudrate."
USART_Config();
return 0;
}
INIT_BOARD_EXPORT(uart_init);
void rt_hw_console_output(const char *str)
{
//#error "TODO 3: Output the string 'str' through the uart."
rt_enter_critical();
/* 直到字符串结束 */
while ( *str != '\0' )
{
/* 换行 */
//RT-Thread 系统中已有的打印均以 \n 结尾,而并非 \r\n,所以在字符输出时,需要在输出 \n 之前输出 \r,完成回车与换行,否则系统打印出来的信息将只有换行
if ( *str == '\n' )
{
USART_SendData( DEBUG_USARTx, '\r' );
while ( USART_GetFlagStatus( DEBUG_USARTx, USART_FLAG_TXE ) == RESET );
}
USART_SendData( DEBUG_USARTx, *str++ );
while ( USART_GetFlagStatus( DEBUG_USARTx, USART_FLAG_TXE ) == RESET );
}
/* 退出临界段 */
rt_exit_critical();
}
- 编译不报错代表
rt_kprintf 函数以及可以正常使用,在点灯线程里该代码测试。可以正常打印。
在nano上添加finsh组件
- 添加finsh源码到工程,然后在 rtconfig.h 中打开 finsh 相关选项,(这一步图解见RT-Thread 文档中心,链接在文章头部)
- 这里有报错,提示我们要实现
rt_hw_console_getchar ,双击报错进入相关文档
(finsh_port.c)
#include <rthw.h>
#include <rtconfig.h>
#include "stm32f10x.h"
#include "bsp_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)
{
/* Note: the initial value of ch must < 0 */
int ch = -1;
//查询方式实现,记得将Usart1初始化中的中断接收配置相关代码注释掉
/*等待串口1输入数据*/
if( USART_GetFlagStatus( DEBUG_USARTx, USART_FLAG_RXNE ) != RESET )
{
ch = ( int )USART_ReceiveData( DEBUG_USARTx );
USART_ClearFlag( DEBUG_USARTx, USART_FLAG_RXNE );
}
else
{
if( USART_GetFlagStatus( DEBUG_USARTx, USART_FLAG_ORE ) != RESET )
{
USART_ClearFlag( DEBUG_USARTx, USART_FLAG_ORE );
}
rt_thread_mdelay( 10 );
}
return ch;
//#error "TODO 4: Read a char from the uart and assign it to 'ch'."
return ch;
}
#endif /* RT_USING_FINSH */
到此finsh组件移植完毕
测试:使用软件 SecureCRT 7.3,一般的串口调试助手有时候可以,有时候不行,不清楚原因,在使用SecureCRT 7.3的时候要先让开发板工作,再打开串口。 一般的串口调试助手有时候只能读取一个字节,当然如果你不怕麻烦,一个字母一个字母输入也可以。
|