CMSIS-RTOS2 文档翻译 之 参考(CMSIS-RTOS2 API 之 信号量)

xiaoxiao2021-02-28  68

信号量 CMSIS-RTOS2 API

同时从不同线程访问共享资源。更多...

数据结构

struct  osSemaphoreAttr_t 信号量的属性结构体。 更多... 

类型定义

typedef void * osSemaphoreId_t 

函数

osSemaphoreId_t osSemaphoreNew (uint32_t max_count, uint32_t initial_count, const osSemaphoreAttr_t *attr) 创建并初始化信号量对象。更多... const char * osSemaphoreGetName (osSemaphoreId_t semaphore_id) 获取信号量对象的名称。更多... osStatus_t osSemaphoreAcquire (osSemaphoreId_t semaphore_id, uint32_t timeout) 如果没有令牌可用,则获取信号量标记或超时。更多... osStatus_t osSemaphoreRelease (osSemaphoreId_t semaphore_id) 释放一个信号量令牌直到最初的最大数量。更多... uint32_t osSemaphoreGetCount (osSemaphoreId_t semaphore_id) 获取当前的信号量令牌计数。更多... osStatus_t osSemaphoreDelete (osSemaphoreId_t semaphore_id) 删除一个信号量对象。更多... 

描述

信号量用于管理和保护对共享资源的访问。信号量与互斥锁非常相似。尽管互斥锁允许一次只有一个线程访问共享资源,但信号量可用于允许固定数量的线程/ ISR 访问共享资源池。使用信号量可以管理对一组相同外设的访问(例如多个 DMA 通道)。

CMSIS-RTOS 信号量

信号量对象应初始化为可用令牌的最大数量。这个可用资源的数量被指定为 osSemaphoreNew 函数的参数。每次使用 osSemaphoreAcquire(处于可用状态)获得信号量标记时,信号量计数递减。当信号量计数为 0(即耗尽状态)时,不能获得更多的信号量标记。尝试获取信号量标记的线程/ISR 需要等待,直到下一个标记为空。信号量与 osSemaphoreRelease 一起发布,增加信号量计数。

CMSIS-RTOS 信号量状态 注意 可以从中断服务例程调用函数 osSemaphoreAcquire ,osSemaphoreGetCount 和 osSemaphoreRelease 。 有关 RTX5 配置选项,请参阅信号量配置。

信号量用例

由于其灵活性,信号量涵盖了广泛的同步应用程序。同时,它们也许是要了解的最具挑战性的 RTOS 对象。下面解释一下信号量的用例,取自 Allen B . Downey 的小信号小册子,该小册子可以免费下载。

非二制信号量(复用)

多路复用限制了可以访问代码的关键部分的线程数量。例如,这可能是访问只支持有限数量的呼叫的 DMA 资源的函数。

要允许多个线程运行该函数,请将信号量初始化为可允许的最大线程数。信号量中的令牌数表示可能输入的附加线程的数量。如果这个数字为零,那么下一个尝试访问该函数的线程将不得不等待,直到其他线程退出并释放其令牌。当所有线程退出时,令牌编号返回 n 。以下示例显示了可能访问该资源的其中一个线程的代码:

osSemaphoreId_t multiplex_id; void thread_n ( void) { multiplex_id = osSemaphoreNew(3, 3, NULL); while(1) { osSemaphoreAcquire(multiplex_id, osWaitForever); // do something osSemaphoreRelease(multiplex_id); } }

生产者/消费者信号量

生产者 - 消费者问题可以使用两个信号量来解决。

第一个信号量(empty_id)对可用(空)缓冲区进行倒计数,即生产者线程可以通过从这个缓冲区获取可用缓冲区时隙。

第二个信号量(filled_id)对使用过的(填充的)缓冲区进行计数,即消费者线程可以通过从这个缓冲区获取可用数据来等待。

线程在给定序列中获取和释放两个信号量的正确行为是至关重要的。根据这个例子,可以有多个生产者和/或消费者线程同时运行。

#define BUFFER_SIZE 10 osSemaphoreId_t empty_id = osSemaphoreNew(BUFFER_SIZE, BUFFER_SIZE, NULL); osSemaphoreId_t filled_id = osSemaphoreNew(BUFFER_SIZE, 0, NULL); void producer_thread ( void) { while(1) { osSemaphoreAcquire(empty_id, osWaitForever); // produce data osSemaphoreRelease(filled_id); } } void consumer_thread ( void) { while(1) { osSemaphoreAcquire(filled_id, osWaitForever); // consume data osSemaphoreRelease(empty_id); } }

数据结构文档

struct osSemaphoreAttr_t

用于配置信号量的属性。

有关使用的详细信息,请参阅内存管理

osSemaphoreAttr_t::cb_memosSemaphoreAttr_t::cb_size Data Fieldsconst char *name信号量的名称

指向具有人类可读名称的信号量对象的字符串。默认值:NULL 。

uint32_tattr_bits属性位

保留以供将来使用(设为'0')。默认值:0 。

void *cb_mem内存控制块

指向信号量控制块对象的内存位置的指针。这可以选择用于自定义内存管理系统。默认值:NULL(使用内核内存管理)。

uint32_tcb_size为控制块提供的内存大小

内存块的大小与 cb_mem 一起传递。必须是信号量控制块对象的大小或更大。

类型定义文档

osSemaphoreId_t

信号量标识标识信号量。

返回者:

osSemaphoreNew

函数文档

osSemaphoreId_t osSemaphoreNew(uint32_t max_count,  uint32_t initial_count,  const osSemaphoreAttr_t * attr  )   参数 [in]max_count可用令牌的最大数量。[in]initial_count可用令牌的初始数量。[in]attr信号量属性; NULL:默认值。 返回 信号标识以供其他功能参考,或者在发生错误时使用 NULL 。

osSemaphoreNew 函数创建并初始化一个信号量对象,该对象用于管理对共享资源的访问,并返回指向信号量对象标识符的指针或在发生错误时返回 NULL 。它可以在 RTOS 启动之前(调用 osKernelStart)安全地调用,但不能在它初始化之前(调用 osKernelInitialize)调用

参数 max_count 指定可用令牌的最大数量。max_count 值为 1 会创建一个二制信号量。

参数 initial_count 设置可用令牌的初始数量。

参数 attr 指定了额外的信号量属性。如果设置为 NULL ,则会使用默认属性。

注意 该函数不能从中断服务程序调用。

代码示例

#include "cmsis_os2.h" // CMSIS RTOS header file void Thread_Semaphore ( void *argument); // thread function osThreadId_t tid_Thread_Semaphore; // thread id osSemaphoreId_t sid_Thread_Semaphore; // semaphore id int Init_Semaphore ( void) { sid_Thread_Semaphore = osSemaphoreNew(2, 2, NULL); if (!sid_Thread_Semaphore) { ; // Semaphore object not created, handle failure } tid_Thread_Semaphore = osThreadNew (Thread_Semaphore, NULL, NULL); if (!tid_Thread_Semaphore) { return(-1); } return(0); } void Thread_Semaphore ( void *argument) { osStatus_t val; while (1) { ; // Insert thread code here... val = osSemaphoreAcquire (sid_Thread_Semaphore, 10); // wait for max. 10 ticks for semaphore token to get available switch (val) { case osOK: ; // Use protected code here... osSemaphoreRelease (sid_Thread_Semaphore); // Return a token back to a semaphore break; case osErrorResource: break; case osErrorParameter: break; default: break; } osThreadYield (); // suspend thread } } const char * osSemaphoreGetName(osSemaphoreId_t semaphore_id)  参数 [in]semaphore_id由 osSemaphoreNew 获得的信号量 ID 。 返回 名称为 NULL 终止的字符串。

函数 osSemaphoreGetName 返回指向由参数 semaphore_id 标识的信号量的名称字符串的指针,或者在出现错误时返回 NULL 。

注意 该函数不能从中断服务程序调用。 osStatus_t osSemaphoreAcquire(osSemaphoreId_t semaphore_id,  uint32_t timeout  )   参数 [in]semaphore_id由 osSemaphoreNew 获得的信号量 ID 。[in]timeout超时值或 0 在没有超时的情况下。 返回 状态代码,指示该函数的执行状态。

阻塞函数 osSemaphoreAcquire 一直等待,直到由参数 semaphore_id 指定的信号量对象的标记变为可用。如果令牌可用,该函数立即返回并减少令牌计数。

参数超时指定系统等待获取令牌的时间。系统等待时,调用此函数的线程将进入 BLOCKED 状态。参数超时可以有以下值:

当超时为 0 时,函数立即返回(即尝试语义)。当超时设置为 osWaitForever 时,函数将等待无限的时间,直到信号量变为可用(即等待语义)。所有其他值都指定了内核中的超时时间(即定时等待语义)。

可能的 osStatus_t 返回值:

osOK: 该令牌已被获得。osErrorTimeout: 在给定的时间内无法获得令牌。osErrorResource: 未指定超时时无法获取令牌。osErrorParameter: 参数 semaphore_id 不正确。 注意 如果参数 timeout 设置为 0 ,可以从中断服务例程调用。

代码示例

请参阅 osSemaphoreNew 。

osStatus_t osSemaphoreRelease(osSemaphoreId_t semaphore_id)  参数 [in]semaphore_id由 osSemaphoreNew 获得的信号量 ID 。 返回 状态代码,指示该函数的执行状态。

函数 osSemaphoreRelease 释放由参数 semaphore_id 指定的信号量对象的标记。令牌只能在创建时指定的最大数量发布,请参阅 osSemaphoreNew 。 当前等待此信号量对象标记的其他线程将被置于 READY 状态。

可能的 osStatus_t 返回值:

osOK: 令牌已被正确释放并且计数增加。osErrorResource: 已达到最大令牌计数。osErrorParameter: 参数 semaphore_id 不正确。 注意 这个函数可以从中断服务程序中调用。

代码示例

请参阅 osSemaphoreNew 。

uint32_t osSemaphoreGetCount(osSemaphoreId_t semaphore_id)  参数 [in]semaphore_id由 osSemaphoreNew 获得的信号量 ID 。 返回 可用的令牌数量。

函数 osSemaphoreGetCount 返回由参数 semaphore_id 指定的信号量对象的可用令牌的数量。如果发生错误,则返回 0 。

注意 这个函数可以从中断服务程序中调用。 osStatus_t osSemaphoreDelete(osSemaphoreId_t semaphore_id)  参数 [in]semaphore_id由 osSemaphoreNew 获得的信号量 ID 。 返回 状态代码,指示该函数的执行状态。

函数 osSemaphoreDelete 删除由参数 semaphore_id 指定的信号量对象。它释放信号量处理获得的内部内存。在这次调用之后,semaphore_id 不再有效并且不能使用。可以使用函数 osSemaphoreNew 再次创建信号量。

可能的 osStatus_t 返回值:

osOK: 信号量对象已被删除。osErrorParameter: 参数 semaphore_id 是 NULL 或无效的。osErrorResource: 由参数 semaphore_id 指定的信号量处于无效信号量状态。osErrorISR: osSemaphoreDelete 不能从中断服务程序调用。 注意 该函数不能从中断服务程序调用。
转载请注明原文地址: https://www.6miu.com/read-2623684.html

最新回复(0)