# 目录
# RTT 从这里开始
RT-Thread 文档中心 (opens new window)
使用RT-Thread Studio移植RT-Thread & 制作STM32通用BootLoader (opens new window)
# RTT 看门狗程序
https://club.rt-thread.org/ask/question/424006.html (opens new window)
# 用rtt 改写延迟函数
/**
*@brief 毫秒延时函数
*@param time_ms:要延时毫秒时间数
*@return 无
*/
void delay_ms( uint32 time_ms )
{
// u32 temp;
// SysTick->LOAD=(u32)time_ms*fac_ms; /*时间加载(SysTick->LOAD为24bit)*/
// SysTick->VAL =0x00; /*清空计数器*/
// SysTick->CTRL=0x01 ; /*开始倒数*/
// do
// {
// IWDG_Feed();
// temp=SysTick->CTRL;
// }
// while(temp&0x01&&!(temp&(1<<16))); /*等待时间到达*/
// SysTick->CTRL=0x00; /*关闭计数器*/
// SysTick->VAL =0X00;
rt_thread_mdelay(time_ms); /*清空计数器*/
}
/**
*@brief 微秒延时函数
*@param time_ms:要延时微秒时间数
*@return 无
*/
//void delay_us( uint32 time_us )
//{
// u32 temp;
// SysTick->LOAD=time_us*fac_us; /*时间加载*/
// SysTick->VAL=0x00; /*清空计数器*/
// SysTick->CTRL=0x01 ; /*开始倒数 */
// do
// {
// temp=SysTick->CTRL;
// IWDG_Feed();
// }
// while(temp&0x01&&!(temp&(1<<16))); /*等待时间到达*/
// SysTick->CTRL=0x00; /*关闭计数器*/
// SysTick->VAL =0X00; /*清空计数器*/
//}
//======================delay======================
// ref: rt_hw_us_delay() at drv_common.c(rt-thread 4.01)
//note:us_tick= 80, reload = 79,999. if us>999,(delta < us_tick * us) can't happend.
void delay_us(uint32 us)
{
rt_uint32_t start, now, delta, reload, us_tick;
//这个if另加的,原来一旦超过999就会死循环
if(us>999)
{
rt_kprintf("delay_us() arg error:us>999");
return;
}
start = SysTick->VAL;
reload = SysTick->LOAD;
us_tick = SystemCoreClock / 1000000UL; //80
do {
now = SysTick->VAL;
delta = start > now ? start - now : reload + start - now;
} while(delta < us_tick * us);
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# RT-Thread中支持静态和动态两种定义方式
用线程来举例的话,rt_thread_init对应静态定义方式,rt_thread_create对应动态定义方式。
使用静态定义方式时,必须先定义静态的线程控制块,并且定义好堆栈空间,然后调用rt_thread_init来完成线程的初始化工作。采用这种方式,线程控制块和堆栈占用的内存会放在RW段,这段空间在编译时就已经确定,它不是可以动态分配的,所以不能被释放。而只能使用rt_thread_detach函数将该线程控制块从对象管理器中脱离。
使用动态定义方式rt_thread_create时,RT-Thread会动态申请线程控制块和堆栈空间。在编译时,编译器是不会感知到这段空间的,只有在程序运行时,RT-Thread才会从系统堆中申请分配这段内存空间,当不需要使用该线程时,调用rt_thread_delete函数就会将这段申请的内存空间重新释放到内存堆中。
这两种方式各有利弊,
静态定义方式会占用RW空间,但是不需要动态分配内存,运行时效率高。 动态方式不会占用额外的RW空间,占用空间小,但是运行时需要动态分配内存,效率没有静态方式高。 总的来说,这两种方式就是空间和时间效率的平衡,可以根据实际环境需求选择采用具体的分配方式。
# RT-Thread Nano
RT-Thread Nano入门全套教程 (opens new window)
相关代码 (opens new window) 提取码:2qp7
RT-Thread基础学习(三)-RT-Thread Nano入门笔记 (opens new window)
# 互斥锁
https://blog.csdn.net/Sanjay_Wu/article/details/86687838 (opens new window)
/* 线程句柄 */
static rt_thread_t change_value_thread = RT_NULL;
static rt_thread_t show_value_thread = RT_NULL;
/* 互斥量句柄 */
static rt_mutex_t mutex = RT_NULL;
/* 全局变量,公共资源 */
char g_value = 'A';
/**************************************************************
函数名称 : change_value_thread_entry
函数功能 : 修改公共资源线程入口函数
输入参数 : parameter:入口参数
返回值 : 无
备注 : 无
**************************************************************/
void change_value_thread_entry(void *parameter)
{
while(1)
{
rt_mutex_take(mutex, RT_WAITING_FOREVER);/* 获取互斥量,一直等直到获取到 */
if(g_value < 'Z')
{
g_value++;
}
else
{
g_value = 'A';
}
rt_mutex_release(mutex); /* 释放互斥量 */
rt_thread_mdelay(1);
rt_thread_yield(); /* 放弃剩余时间片,进行一次线程切换 */
}
}
/**************************************************************
函数名称 : show_value_thread_entry
函数功能 : 打印g_value
输入参数 : parameter:入口参数
返回值 : 无
备注 : 无
**************************************************************/
void show_value_thread_entry(void *parameter)
{
while(1)
{
rt_mutex_take(mutex, RT_WAITING_FOREVER);/* 获取互斥量,一直等直到获取到 */
rt_kprintf("g_value:%c\r\n", g_value);
LED_R(0);
rt_thread_mdelay(2000);
LED_R(1);
rt_thread_mdelay(2000);
rt_mutex_release(mutex); /* 释放互斥量 */
}
}
void rtthread_mutex_test(void)
{
/* 创建一个互斥量,先进先出模式*/
mutex = rt_mutex_create("mutex_test", RT_IPC_FLAG_PRIO);
if(RT_NULL != mutex)
{
rt_kprintf("create mutex successful\r\n");
}
else
{
rt_kprintf("create mutex failed\r\n");
return;
}
/* 创建打印显示公共资源g_value线程 */
show_value_thread = rt_thread_create("show_value_thread",
show_value_thread_entry,
RT_NULL,
512,
3,
20
);
if(RT_NULL != show_value_thread)/* 创建成功,启动线程 */
{
rt_thread_startup(show_value_thread);;
}
else
{
rt_kprintf("create show_value_thread failed\r\n");
return;
}
/* 创建改变公共资源g_value线程 */
change_value_thread = rt_thread_create("change_value_thread",
change_value_thread_entry,
RT_NULL,
512,
4,
20
);
if(RT_NULL != change_value_thread)/* 创建成功,启动线程 */
{
rt_thread_startup(change_value_thread);
}
else
{
rt_kprintf("create change_value_thread failed\r\n");
return;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117