# 目录

# RTT 从这里开始

RT-Thread 文档中心 (opens new window)

启动第一个线程 (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);
 
}

1
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;
 }
        
}

1
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
Last Updated: 3/22/2022, 10:47:08 PM