目录
前言
使用的芯片:STM32F407ZG,正点原子探索者板
- 前面几篇博文已经对RT-Thread进行了大体的了解
在本专栏的前期工作基本已经准备好,对于BSP的制作与RT-Thread的继续学习将在本篇博客展开,写博客的目的也是在对自己的学习过程有一个总结。
如何看RT-Thread文档、RT的工程建立和BSP快速构建_追逐者-桥的博客-CSDN博客
RT-Thread中常用的指令_追逐者-桥的博客-CSDN博客
RT-Thread内核快速入门,内核实现与应用开发学习随笔记_追逐者-桥的博客-CSDN博客
RT-Thread改变打印串口(在BSP的基础上添加其他功能)_追逐者-桥的博客-CSDN博客
- 对于RT的学习将再这篇博文进行整理
本篇笔记主要记录了:
内核:内核基础、线程管理
设备和驱动:I/O口设备模型
示例程序:内核例程(线程)、外设例程(LED)
一、学习的重点内容
1.1、内核
1.1.1、内核基础
- 线程调度、时钟管理、线程间同步、线程间通讯、内存管理、I/O口设备管理
- 启动流程:
- 内存分布:
- 自动初始化机制:
- 内核对象模型
- 内核配置文件
配置主要是通过修改工程目录下的 rtconfig.h 文件来进行,用户可以通过打开 / 关闭该文件中的宏定义来对代码进行条件编译,最终达到系统配置和裁剪的目的
1.1.2、线程管理
线程属性:栈、状态、优先级、时间片、入口函数、错误码、状态转换
动态线程、静态线程、时间片轮转调度、调度器钩子函数
钩子函数中最好不要调用API
1.2、 设备和驱动
1.2.1、I/O口设备模型
1.2.2、PIN设备
芯片上的引脚分为4类:电源、时钟、控制、 I/O。
I/O口主要的特点
- 可编程中断:
- I/O口输入输出模式可控
PIN设备管理接口
- 获取引脚编号:使用API、使用宏定义、查看驱动文件
- 设置引脚模式:(上/下拉)输入、(开漏)输出
- 设置引脚电平:PIN_LOW、PIN_HIGH
- 读取引脚电平:
- 绑定引脚中断回调函数:中断触发方式
- 使能引脚中断:开启、关闭
- 脱离引脚中断回调函数:
二、示例程序
2.1、外设例程——Led
控制要求:
通过PIN设备管理接口控制LED亮灭,学会创建线程,使用之前创建的简单BSP程序
硬件I/O口:
BEEP——PF8
LED0——PF9
LED1——PF10
KEY0——PE4
KEY1——PE3
KEY2——PE2
程序代码
/*
* Copyright (c) 2022-7-27, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2022-7-27 Qiao first version
*/
#include <rtthread.h>
#include <rtdevice.h>
#include <board.h>
#include <stdlib.h>
/*
*获取引脚编号:使用(RT)API、使用宏定义、查看驱动文件
*这里采用使用宏定义
*/
#define BEEP GET_PIN(F, 8)
#define LED0 GET_PIN(F, 9)
#define LED1 GET_PIN(F, 10)
#define KEY0 GET_PIN(E, 4)
#define KEY1 GET_PIN(E, 3)
#define KEY2 GET_PIN(E, 2)
/*
*led线程控制块—rtdef.h
*/
#define LED_PRIORITY RT_THREAD_PRIORITY_MAX / 3 //rtconfig.h最大优先级
#define LED_STACK_SIZE 512
#define LED_TIMESLICE 50
static rt_thread_t led_tid = RT_NULL;
int main(void)
{
int count = 1;
/* set LED0 pin mode to output */
rt_pin_mode(LED0, PIN_MODE_OUTPUT);
while (count++)
{
rt_pin_write(LED0, PIN_HIGH);
// rt_kprintf("thread run count ");
rt_thread_mdelay(500);
rt_pin_write(LED0, PIN_LOW);
rt_thread_mdelay(500);
}
return RT_EOK;
}
static void led_entry(void *parameter)
{
rt_pin_mode(LED1, PIN_MODE_OUTPUT);
for(int i=1; i<20; i++)
{
/* 点亮LED1 */
rt_pin_write(LED1, PIN_LOW);
rt_kprintf("thread run count : %d\r\n", i);
rt_thread_mdelay(1000);
/* 熄灭LED1 */
rt_pin_write(LED1, PIN_HIGH);
rt_kprintf("led off!\r\n");
rt_thread_mdelay(1000);
}
}
static int led_thread_create(void)
{
rt_err_t ret = RT_EOK; //错误等级:无错误
led_tid = rt_thread_create("led",
led_entry,
RT_NULL,
LED_STACK_SIZE,
LED_PRIORITY - 1,
LED_TIMESLICE);
if(led_tid != RT_NULL)
{
rt_thread_startup(led_tid);
}
else
{
ret = RT_ERROR;
}
return ret;
}
INIT_APP_EXPORT(led_thread_create);
下载调试
使用ENV工具中的scons --target=mdk5,重新生成工程
观察LED灯的状态
发现会打印LED灯线程内的信息
PS可以查看线程,看到创建的led灯的线程
出现问题:
功能已实现,但是有问题,问题如下:
1、在不连接串口助手时:下载后可以自动启动
2、在打开串口助手时:在下载程序后必须重启才能运行程序
2.1、外设例程——PIN
程序
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
* Change Logs:
* Date Author Notes
* 2022-7-29 Qiao PIN
* 建立GPIO口中断实验
*/
#include <rtthread.h>
#include <rtdevice.h>
#include <board.h>
#include <led.h>
/*
*获取引脚编号:使用(RT)API、使用宏定义、查看驱动文件
*这里采用使用宏定义,必须添加<board.h>文件
*/
#define BEEP GET_PIN(F, 8)
#define KEY0 GET_PIN(E, 4)
#define KEY1 GET_PIN(E, 3)
#define KEY2 GET_PIN(E, 2)
void beep_on(void *args)
{
rt_kprintf("turn on beep!\n");
// rt_pin_write(BEEP, PIN_HIGH);
rt_pin_write(LED1, PIN_LOW);
}
void beep_off(void *args)
{
rt_kprintf("turn off beep!\n");
// rt_pin_write(BEEP, PIN_LOW);
rt_pin_write(LED1, PIN_HIGH);
}
static void pin_beep_irq(void)
{
/* BEEP的I/O口配置 */
rt_pin_mode(BEEP, PIN_MODE_OUTPUT);
rt_pin_write(BEEP, PIN_LOW);
/*
* 验证对于操作逻辑简单的设备,可以不经过设备驱动框架层,
* 直接将设备注册到 I/O 设备管理器中
*/
rt_pin_mode(KEY0, PIN_MODE_INPUT_PULLUP);
rt_pin_attach_irq(KEY0, PIN_IRQ_MODE_FALLING, beep_on, RT_NULL);
rt_pin_irq_enable(KEY0, PIN_IRQ_ENABLE);
rt_pin_mode(KEY1, PIN_MODE_INPUT_PULLUP);
rt_pin_attach_irq(KEY1, PIN_IRQ_MODE_FALLING, beep_off, RT_NULL);
rt_pin_irq_enable(KEY1, PIN_IRQ_ENABLE);
}
INIT_APP_EXPORT(pin_beep_irq);
下载调试
使用ENV工具中的scons --target=mdk5,重新生成工程
可以使用外部输入中断控制beep和灯的亮灭