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