普通任务通知事件创建创建及运行,参阅安富莱电子demo
#define BIT_0 (1 << 0)
#define BIT_1 (1 << 1)
static TaskHandle_t xHandleTaskUserIF = NULL;
static TaskHandle_t xHandleTaskMsgPro = NULL;
static void vTaskTaskUserIF(void *pvParameters)
{
uint8_t ucKeyCode;
uint8_t pcWriteBuffer[500];
while(1)
{
ucKeyCode = bsp_GetKey();
if (ucKeyCode != KEY_NONE)
{
switch (ucKeyCode)
{
/* K1键按下 打印任务执行情况 */
case KEY_DOWN_K1:
printf("=================================================\r\n");
printf("任务名 任务状态 优先级 剩余栈 任务序号\r\n");
vTaskList((char *)&pcWriteBuffer);
printf("%s\r\n", pcWriteBuffer);
printf("\r\n任务名 运行计数 使用率\r\n");
vTaskGetRunTimeStats((char *)&pcWriteBuffer);
printf("%s\r\n", pcWriteBuffer);
break;
/* K2键按下,直接发送事件标志设置给任务vTaskMsgPro,置位bit0 */
case KEY_DOWN_K2:
printf("K2键按下,任务vTaskMsgPro事件标志位bit0被置位 \r\n");
xTaskNotify(xHandleTaskMsgPro, /* 目标任务 */
BIT_0, /* 设置目标任务事件标志位bit0 */
eSetBits); /* 将目标任务的事件标志位与BIT_0进行或操作,
将结果赋值给事件标志位。*/
break;
/* K3键按下,直接发送事件标志设置给任务vTaskMsgPro,置位bit1 */
case KEY_DOWN_K3:
printf("K3键按下,任务vTaskMsgPro事件标志位bit1被置位 \r\n");
xTaskNotify(xHandleTaskMsgPro, /* 目标任务 */
BIT_1, /* 设置目标任务事件标志位bit0 */
eSetBits); /* 将目标任务的事件标志位与BIT_0进行或操作,
将结果赋值给事件标志位。*/
/* 其他的键值不处理 */
default:
break;
}
}
vTaskDelay(20);
}
}
static void vTaskMsgPro(void *pvParameters)
{
BaseType_t xResult;
const TickType_t xMaxBlockTime = pdMS_TO_TICKS(500); /* 设置最大等待时间为500ms */
uint32_t ulValue;
while(1)
{
/*
第一个参数 ulBitsToClearOnEntry的作用(函数执行前):
ulNotifiedValue &= ~ulBitsToClearOnEntry
简单的说就是参数ulBitsToClearOnEntry那个位是1,那么ulNotifiedValue
的那个位就会被清零。
这里ulBitsToClearOnEntry = 0x00000000就是函数执行前保留所有位。
第二个参数 ulBitsToClearOnExit的作用(函数退出前):
ulNotifiedValue &= ~ulBitsToClearOnExit
简单的说就是参数ulBitsToClearOnEntry那个位是1,那么ulNotifiedValue
的那个位就会被清零。
这里ulBitsToClearOnExi = 0xFFFFFFFF就是函数退出前清楚所有位。
注:ulNotifiedValue表示任务vTaskMsgPro的任务控制块里面的变量。
*/
xResult = xTaskNotifyWait(0x00000000,
0xFFFFFFFF,
&ulValue, /* 保存ulNotifiedValue到变量ulValue中 */
xMaxBlockTime); /* 最大允许延迟时间 */
if( xResult == pdPASS )
{
/* 接收到消息,检测那个位被按下 */
if((ulValue & BIT_0) != 0)
{
printf("接收到K2按键按下消息, ulNotifiedValue = 0x%08x\r\n", ulValue);
}
if((ulValue & BIT_1) != 0)
{
printf("接收到K3按键按下消息, ulNotifiedValue = 0x%08x\r\n", ulValue);
}
}
else
{
/* 超时 */
}
}
}
int main(void)
{
/*
在启动调度前,为了防止初始化STM32外设时有中断服务程序执行,这里禁止全局中断(除了NMI和HardFault)。
这样做的好处是:
1. 防止执行的中断服务程序中有FreeRTOS的API函数。
2. 保证系统正常启动,不受别的中断影响。
3. 关于是否关闭全局中断,大家根据自己的实际情况设置即可。
在移植文件port.c中的函数prvStartFirstTask中会重新开启全局中断。通过指令cpsie i开启,__set_PRIMASK(1)
和cpsie i是等效的。
*/
__set_PRIMASK(1);
/* 创建任务 ,具体创建任务参阅上一篇【FreeRTOS 任务】任务创建及运行 */
AppTaskCreate();
/* 启动调度,开始执行任务 */
vTaskStartScheduler();
/*
如果系统正常启动是不会运行到这里的,运行到这里极有可能是用于定时器任务或者空闲任务的
heap空间不足造成创建失败,此要加大FreeRTOSConfig.h文件中定义的heap大小:
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 17 * 1024 ) )
*/
while(1);
/* 以上函数 vTaskMsgPro 中的 xTaskNotify 任务通知API是在普通任务下使用,在中断中要使用以下两个函数释放*/
static void TIMx_IRQHandler(void)
{
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
xTaskNotifyFromISR( xHandleTaskMsgPro, /* 目标任务 */
BIT_0, /* 设置目标任务事件标志位 bit0 */
eSetBits, /* 将目标任务的事件标志位与 BIT_0 进行或操作, 将结果赋值给事件标志位 */
&xHigherPriorityTaskWoken);
/* 如果 xHigherPriorityTaskWoken = pdTRUE,那么退出中断后切到当前最高优先级任务执行 */
portYIELD_FROM_ISR(xHigherPriorityTaskWoken)
}
STM32CubeMX 二值信号量创建及运行
/* USER CODE BEGIN 4 */
osThreadId defaultTaskHandle = NULL;
osThreadId SignalTaskHandle = NULL;
void SignalTask(void const * argument)
{
/* USER CODE BEGIN 5 */
/* Infinite loop */
osEvent EventValue;
for(;;)
{
/* 参数说明:函数退出前进行按位与操作(默认0xFFFFFFFF),最大等待时间*/
/* 返回值:
//返回值是一个结构体
typedef struct {
osStatus status; ///< 返回状态信息
union {
uint32_t v; ///< 不理睬
void *p; ///< 不理睬
int32_t signals; ///< 事件消息
} value; ///< 联合体名称
union {
osMailQId mail_id; ///< 不理睬
osMessageQId message_id; ///< 不理睬
} def; ///< 不理睬
} osEvent;
*/
EventValue = osSignalWait (0xFFFFFFFF, osWaitForever);
if(EventValue.status == osEventSignal)
{
HAL_UART_Transmit(&huart1,"EventVa lue is copy\r\n",strlen("EventValue is copy\r\n"),1000);
switch (EventValue.value.signals)
{
case 0x01:
HAL_UART_Transmit(&huart1,"EventValue is 0x01\r\n",strlen("EventValue is 0x01\r\n"),1000);
break;
case 0x02:
HAL_UART_Transmit(&huart1,"EventValue is 0x02\r\n",strlen("EventValue is 0x02\r\n"),1000);
break;
case 0x03:
HAL_UART_Transmit(&huart1,"EventValue is 0x03\r\n",strlen("EventValue is 0x03\r\n"),1000);
break;
default:
HAL_UART_Transmit(&huart1,"EventValue is outside \r\n",strlen("EventValue is outside \r\n"),1000);
break;
}
}
}
/* USER CODE END 5 */
}
void StartDefaultTask(void const * argument)
{
/* USER CODE BEGIN 5 */
/* Infinite loop */
int32_t count = 0;
int8_t bits = 0x01;
for(;;)
{
HAL_UART_Transmit(&huart1,"StartDefaultTask\r\n",strlen("StartDefaultTask\r\n"),1000);
count++;
if(count == 10)
{
count = 0;
/* 参数说明:要通知任务的任务句柄,事件消息 */
/* STM32CubeMX 在 osSignalSet 函数体中封装好了 xTaskGenericNotifyFromISR 函数体,可以直接在中断中调用 */
osSignalSet (SignalTaskHandle, bits);
bits = bits + 1;
}
osDelay(100);
}
/* USER CODE END 5 */
}
/* USER CODE END 4 */
int main(void)
{
/* Create the thread(s) */
/* definition and creation of defaultTask */
osThreadDef(defaultTask, StartDefaultTask, osPriorityLow, 0, 128);
defaultTaskHandle = osThreadCreate(osThread(defaultTask), NULL);
osThreadDef(SignalTask, SignalTask, osPriorityHigh, 0, 128);
SignalTaskHandle = osThreadCreate(osThread(SignalTask), NULL);
/* USER CODE END RTOS_THREADS */
/* Start scheduler */
osKernelStart();
}