• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# BearPi-HM_Nano开发板OpenHarmony内核编程开发——信号量
2本示例将演示如何在BearPi-HM_Nano开发板上使用cmsis 2.0 接口通过信号量同时从不同的线程访问共享资源。
3
4
5## Semaphore API分析
6
7###  osSemaphoreNew()
8
9```c
10osSemaphoreId_t osSemaphoreNew(uint32_t max_count, uint32_t initial_count, const osSemaphoreAttr_t *attr)
11```
12**描述:**
13
14osSemaphoreNew 函数创建并初始化一个信号量对象,该对象用于管理对共享资源的访问,并返回指向信号量对象标识符的指针或在发生错误时返回 NULL 。可以在 RTOS 启动之前(调用 osKernelStart)安全地调用该函数,但不能在内核初始化之前(调用 osKernelInitialize)调用该函数。
15> **注意** :不能在中断服务中调用该函数。
16
17
18**参数:**
19
20|参数名|描述|
21|:--|:------|
22| max_count |可用令牌的最大数量。  |
23| initial_count |可用令牌的初始数量。  |
24| attr |信号量的属性; 空:默认值。  |
25
26###  osSemaphoreRelease()
27
28```c
29osStatus_t osSemaphoreRelease(osSemaphoreId_t semaphore_id)
30```
31**描述:**
32函数osSemaphoreRelease释放由参数semaphore_id指定的信号量令牌,最多释放个数为初始设置的最大值。
33
34> **注意** :该函数可以在中断服务例程中调用。
35
36
37**参数:**
38
39|参数名|描述|
40|:--|:------|
41| semaphore_id | 由osSemaphoreNew获得的信号量ID。  |
42
43
44###  osSemaphoreAcquire()
45
46```c
47osStatus_t osSemaphoreAcquire(osSemaphoreId_t semaphore_id, uint32_t timeout)
48```
49**描述:**
50阻塞函数osSemaphoreAcquire在超时时间结束前一直等待,直到由参数semaphore_id指定的信号量令牌可用为止。如果一个信号量令牌可用,该函数立即返回并递减可用的信号量令牌计数。
51
52> **注意** :如果参数timeout设置为0,可以在中断服务例程中调用。
53
54
55**参数:**
56
57|参数名|描述|
58|:--|:------|
59| semaphore_id | 由osSemaphoreNew获得的信号量ID。  |
60| timeout | 超时值。 |
61
62
63## 软件设计
64
65**主要代码分析**
66
67在SemaphoreExample()函数中,通过osSemaphoreNew()函数创建了g_semaphoreId信号量,并初始化信号量令牌数为4。Semaphore2Thread()和Semaphore3Thread()函数中,刚开始阻塞等待g_semaphoreId信号量中可用令牌。只有当Semaphore1Thread()函数中通过osSemaphoreRelease()函数释放两个信号量令牌后,Semaphore2Thread()和Semaphore3Thread()才能继续同步运行。若Semaphore1Thread()函数中只释放一个信号量令牌,那么Semaphore2Thread()和Semaphore3Thread()只能轮流执行。
68```c
69void Semaphore1Thread(void)
70{
71    while (1) {
72        // release Semaphores twice so that Semaphore2Thread and Semaphore3Thread can execute synchronously
73        osSemaphoreRelease(g_semaphoreId);
74
75        // if the Semaphore is released only once, Semaphore2Thread and Semaphore3Thread will run alternately.
76        osSemaphoreRelease(g_semaphoreId);
77
78        printf("Semaphore1Thread Release  Semap \n");
79        osDelay(THREAD_DELAY_1S);
80    }
81}
82void Semaphore2Thread(void)
83{
84    while (1) {
85        // wait Semaphore
86        osSemaphoreAcquire(g_semaphoreId, osWaitForever);
87
88        printf("Semaphore2Thread get Semap \n");
89        osDelay(THREAD_DELAY_10MS);
90    }
91}
92
93void Semaphore3Thread(void)
94{
95    while (1) {
96        // wait Semaphore
97        osSemaphoreAcquire(g_semaphoreId, osWaitForever);
98
99        printf("Semaphore3Thread get Semap \n");
100        osDelay(THREAD_DELAY_10MS);
101    }
102}
103
104/**
105 * @brief Main Entry of the Semaphore Example
106 *
107 */
108void SemaphoreExample(void)
109{
110    osThreadAttr_t attr;
111
112    attr.attr_bits = 0U;
113    attr.cb_mem = NULL;
114    attr.cb_size = 0U;
115    attr.stack_mem = NULL;
116    attr.stack_size = THREAD_STACK_SIZE;
117    attr.priority = THREAD_PRIO;
118
119    attr.name = "Semaphore1Thread";
120    if (osThreadNew((osThreadFunc_t)Semaphore1Thread, NULL, &attr) == NULL) {
121        printf("Failed to create Semaphore1Thread!\n");
122    }
123
124    attr.name = "Semaphore2Thread";
125    if (osThreadNew((osThreadFunc_t)Semaphore2Thread, NULL, &attr) == NULL) {
126        printf("Failed to create Semaphore2Thread!\n");
127    }
128
129    attr.name = "Semaphore3Thread";
130    if (osThreadNew((osThreadFunc_t)Semaphore3Thread, NULL, &attr) == NULL) {
131        printf("Failed to create Semaphore3Thread!\n");
132    }
133
134    g_semaphoreId = osSemaphoreNew(SEM_MAX_COUNT, 0, NULL);
135    if (g_semaphoreId == NULL) {
136        printf("Failed to create Semaphore!\n");
137    }
138}
139```
140
141## 编译调试
142
143### 修改 BUILD.gn 文件
144
145修改 `device\board\bearpi\bearpi_hm_nano\app`路径下 BUILD.gn 文件,指定 `semaphore_example` 参与编译。
146
147```r
148#"A1_kernal_thread:thread_example",
149#"A2_kernel_timer:timer_example",
150#"A3_kernel_event:event_example",
151#"A4_kernel_mutex:mutex_example",
152"A5_kernel_semaphore:semaphore_example",
153#"A6_kernel_message:message_example",
154```
155
156### 运行结果
157
158示例代码编译烧录后,按下开发板的RESET按键,通过串口助手查看日志,Semaphore1Thread一次释放两个信号量令牌,Semaphore2Thread和Semaphore3Thread同步执行。
159```
160Semaphore1Thread Release  Semap
161Semaphore2Thread get Semap
162Semaphore3Thread get Semap
163Semaphore1Thread Release  Semap
164Semaphore2Thread get Semap
165Semaphore3Thread get Semap
166Semaphore1Thread Release  Semap
167Semaphore2Thread get Semap
168Semaphore3Thread get Semap
169```
170