#define semSEMAPHORE_QUEUE_ITEM_LENGTH ( ( uint8_t ) 0U )
#define xSemaphoreCreateBinary() xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE )
#define semGIVE_BLOCK_TIME ( ( TickType_t ) 0U )
#define xSemaphoreGive( xSemaphore ) xQueueGenericSend( ( QueueHandle_t ) ( xSemaphore ), NULL, semGIVE_BLOCK_TIME, queueSEND_TO_BACK )
#define xSemaphoreTake( xSemaphore, xBlockTime ) xQueueGenericReceive( ( QueueHandle_t ) ( xSemaphore ), NULL, ( xBlockTime ), pdFALSE )
...
//非主要源码忽略
...
if( uxMessagesWaiting > ( UBaseType_t ) 0 )---1
{
pcOriginalReadPosition = pxQueue->u.pcReadFrom;
prvCopyDataFromQueue( pxQueue, pvBuffer );---2
if( xJustPeeking == pdFALSE )---3
{
traceQUEUE_RECEIVE( pxQueue );
/* Actually removing data, not just peeking. */
pxQueue->uxMessagesWaiting = uxMessagesWaiting - 1;----4
...
//互斥信号量相关的暂时忽略
...
if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )----5
{
if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
{
queueYIELD_IF_USING_PREEMPTION();
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else//xJustPeeking == pdTRUE ----6
{
traceQUEUE_PEEK( pxQueue );
pxQueue->u.pcReadFrom = pcOriginalReadPosition;
if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
{
if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
{
/* The task waiting has a higher priority than this task. */
queueYIELD_IF_USING_PREEMPTION();
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
taskEXIT_CRITICAL();
return pdPASS;----7
}
else----8
{
...
//这一部分就是设置阻塞时间
...
}
#define xSemaphoreCreateCounting( uxMaxCount, uxInitialCount ) xQueueCreateCountingSemaphore( ( uxMaxCount ), ( uxInitialCount ) )
QueueHandle_t xQueueCreateCountingSemaphore( const UBaseType_t uxMaxCount, const UBaseType_t uxInitialCount )
{
QueueHandle_t xHandle;
configASSERT( uxMaxCount != 0 );
configASSERT( uxInitialCount <= uxMaxCount );
xHandle = xQueueGenericCreate( uxMaxCount, queueSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_COUNTING_SEMAPHORE );
if( xHandle != NULL )
{
( ( Queue_t * ) xHandle )->uxMessagesWaiting = uxInitialCount;
traceCREATE_COUNTING_SEMAPHORE();
}
else
{
traceCREATE_COUNTING_SEMAPHORE_FAILED();
}
return xHandle;
}
QueueHandle_t xQueueCreateMutex( const uint8_t ucQueueType )
{
Queue_t *pxNewQueue;
const UBaseType_t uxMutexLength = ( UBaseType_t ) 1, uxMutexSize = ( UBaseType_t ) 0;
pxNewQueue = ( Queue_t * ) xQueueGenericCreate( uxMutexLength, uxMutexSize, ucQueueType );
prvInitialiseMutex( pxNewQueue );
return pxNewQueue;
}
static void prvInitialiseMutex( Queue_t *pxNewQueue )
{
if( pxNewQueue != NULL )
{
pxNewQueue->pxMutexHolder = NULL;----1
pxNewQueue->uxQueueType = queueQUEUE_IS_MUTEX;----2
/* In case this is a recursive mutex. */
pxNewQueue->u.uxRecursiveCallCount = 0;----3
traceCREATE_MUTEX( pxNewQueue );
/* Start with the semaphore in the expected state. */
( void ) xQueueGenericSend( pxNewQueue, NULL, ( TickType_t ) 0U, queueSEND_TO_BACK );----4
}
else
{
traceCREATE_MUTEX_FAILED();
}
}
#define pxMutexHolder pcTail
#define uxQueueType pcHead
#define queueQUEUE_IS_MUTEX NULL
实验目标:在中断和任务中分别实现二值信号量的发送和接收,
在任务中采用按键实现信号量的发送,在另一个任务中等待接
收信号量。在中断中,PC发送给串口信息,串口接收到信息后
将信号量发送给任务。
Binary_Handler = xSemaphoreCreateBinary();
if (Binary_Handler == NULL)
{
printf("Semaphore Binary Creat Failed!!!\r\n");
}
void key_task(void* pvParameters)
{
BaseType_t err;
while(1)
{
if (Key_Scan(KEY1_GPIO_PORT,KEY1_GPIO_PIN) == KEY_ON)
{
err = xSemaphoreGive(Binary_Handler);//发送新信号量
if (err != pdTRUE)//判断信号量是否发送成功
{
printf("信号量发送失败!\r\n");
}
}
vTaskDelay(10);
}
}
void task2_task(void* pvParameters)
{
u8 count = 0;
BaseType_t err;
while(1)
{
count++;//记录信号量接收次数
if (Binary_Handler != NULL)//判断句柄有效性
{
err = xSemaphoreTake(Binary_Handler,portMAX_DELAY);//接收信号量
if (err != pdTRUE)//判断是否接收成功
{
printf("接收信号量失败!!\r\n");
}
else//LED翻转 并且输出接收到的值
{
LED1 = ~LED1;
printf("count = %d Receive %s\r\n",count,USART_RX_BUF);
memset(USART_RX_BUF,0,USART_REC_LEN);
USART_RX_STA = 0;
}
}
else
{
vTaskDelay(10);
}
}
}
void USART1_IRQHandler(void) //串口1中断服务程序
{
u8 Res;
BaseType_t HigherPriorityTaskWoken=pdFALSE;//用以判断是否需要进行任务切换
BaseType_t err;
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断(接收到的数据必须是0x0d 0x0a结尾)
{
Res =USART_ReceiveData(USART1); //读取接收到的数据
if((USART_RX_STA&0x8000)==0)//接收未完成
{
if(USART_RX_STA&0x4000)//接收到了0x0d
{
if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始
else USART_RX_STA|=0x8000; //接收完成了
}
else //还没收到0X0D
{
if(Res==0x0d)USART_RX_STA|=0x4000;
else
{
USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;
USART_RX_STA++;
if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收
}
}
}
}
if ( (Binary_Handler!=NULL) && (USART_RX_STA&0x8000) )//判断是否接收完成
{
err = xSemaphoreGiveFromISR(Binary_Handler,&HigherPriorityTaskWoken);//从中断中发送信号量
if (err != pdTRUE)//判断是否出错
{
printf("Semaphore Give Failed!!!\r\n");
}
portYIELD_FROM_ISR(HigherPriorityTaskWoken);//根据HigherPriorityTaskWoken判断是否进行任务切换
}
}
#define LOW_TASK_PRIO 2
#define LOW_STACK_SIZE 50
TaskHandle_t LowTask_Handler;
void low_task(void *pvParameters);
#define MIDDLE_TASK_PRIO 3
#define MIDDLE_STACK_SIZE 50
TaskHandle_t MiddleTask_Handler;
void middle_task(void *pvParameters);
#define HIGH_TASK_PRIO 4
#define HIGH_STACK_SIZE 50
TaskHandle_t HighTask_Handler;
void high_task(void *pvParameters);
void low_task(void* pvParameters)
{
long i;
while(1)
{
printf("low task running\r\n");
xSemaphoreTake(Binary_Handler,portMAX_DELAY);
for (i=0; i<22222222; i++);
xSemaphoreGive(Binary_Handler);
printf("low task give semaphore\r\n");
vTaskDelay(1000);
}
}
void middle_task(void* pvParameters)
{
while(1)
{
printf("middle task running\r\n");
vTaskDelay(1000);
}
}
void high_task(void* pvParameters)
{
while(1)
{
printf("high task ask the semaphore\r\n");
xSemaphoreTake(Binary_Handler,portMAX_DELAY);
printf("high task running\r\n");
xSemaphoreGive(Binary_Handler);
vTaskDelay(1000);
}
}
void start_task(void *pvParameters)
{
Binary_Handler = xSemaphoreCreateBinary();
if (Binary_Handler == NULL)
{
printf("Semaphore Binary Creat Failed!!!\r\n");
}
xSemaphoreGive(Binary_Handler);
xTaskCreate((TaskFunction_t )high_task, //任务函数
(const char* )"high_task", //任务名称
(uint16_t )HIGH_STACK_SIZE, //任务堆栈大小
(void* )NULL, //传递给任务函数的参数
(UBaseType_t )HIGH_TASK_PRIO, //任务优先级
(TaskHandle_t* )&HighTask_Handler); //任务句柄
xTaskCreate((TaskFunction_t )middle_task, //任务函数
(const char* )"middle_task", //任务名称
(uint16_t )MIDDLE_STACK_SIZE, //任务堆栈大小
(void* )NULL, //传递给任务函数的参数
(UBaseType_t )MIDDLE_TASK_PRIO, //任务优先级
(TaskHandle_t* )&MiddleTask_Handler); //任务句柄
xTaskCreate((TaskFunction_t )low_task, //任务函数
(const char* )"low_task", //任务名称
(uint16_t )LOW_STACK_SIZE, //任务堆栈大小
(void* )NULL, //传递给任务函数的参数
(UBaseType_t )LOW_TASK_PRIO, //任务优先级
(TaskHandle_t* )&LowTask_Handler); //任务句柄
vTaskDelete(StartTask_Handler);
}
void start_task(void *pvParameters)
{
Mutex_Handler = xSemaphoreCreateMutex();
if (Mutex_Handler == NULL)
{
printf("Semaphore Binary Creat Failed!!!\r\n");
}
xSemaphoreGive(Mutex_Handler);
xTaskCreate((TaskFunction_t )high_task, //任务函数
(const char* )"high_task", //任务名称
(uint16_t )HIGH_STACK_SIZE, //任务堆栈大小
(void* )NULL, //传递给任务函数的参数
(UBaseType_t )HIGH_TASK_PRIO, //任务优先级
(TaskHandle_t* )&HighTask_Handler); //任务句柄
xTaskCreate((TaskFunction_t )middle_task, //任务函数
(const char* )"middle_task", //任务名称
(uint16_t )MIDDLE_STACK_SIZE, //任务堆栈大小
(void* )NULL, //传递给任务函数的参数
(UBaseType_t )MIDDLE_TASK_PRIO, //任务优先级
(TaskHandle_t* )&MiddleTask_Handler); //任务句柄
xTaskCreate((TaskFunction_t )low_task, //任务函数
(const char* )"low_task", //任务名称
(uint16_t )LOW_STACK_SIZE, //任务堆栈大小
(void* )NULL, //传递给任务函数的参数
(UBaseType_t )LOW_TASK_PRIO, //任务优先级
(TaskHandle_t* )&LowTask_Handler); //任务句柄
vTaskDelete(StartTask_Handler);
}
所谓计数型信号量,就是当有任务发送信号量的时候,uxMessagesWaiting +1(但必须满足uxMessagesWaiting
按键发送信号量
void key_task(void* pvParameters)
{
while(1)
{
if (Key_Scan(KEY1_GPIO_PORT,KEY1_GPIO_PIN) == KEY_ON)
{
xSemaphoreGive(Count_Handler);
//count = uxSemaphoreGetCount(Count_Handler);
//printf("count=%ld\r\n",count);
}
if (Key_Scan(KEY2_GPIO_PORT,KEY2_GPIO_PIN) == KEY_ON)
{
xSemaphoreTake(Count_Handler,10);
}
vTaskDelay(10);
}
}
void task2_task(void* pvParameters)
{
//BaseType_t err;
while(1)
{
count = uxSemaphoreGetCount(Count_Handler);
printf("count=%ld\r\n",count);
if (Count_Handler != NULL)
{
if (count > 5)
{
LED1 = 0;
}
else
{
LED1 = 1;
}
}
vTaskDelay(100);
}
}