0
点赞
收藏
分享

微信扫一扫

15 | 边界:微服务的各种边界在架构演进中的作用?

豆丁趣 2023-07-13 阅读 76

文章目录


前言

cubemx_freertos
在这里插入图片描述


一、任务调度

文件

1.1 延时

1.1.1 相对延时

vTaskDelay(ticks1);

void appTask_led1(void *argument)
{
  /* USER CODE BEGIN appTask_led1 */
	TickType_t ticks1=pdMS_TO_TICKS(1000);
  /* Infinite loop */
  for(;;)
  {
		HAL_GPIO_TogglePin(LED0_GPIO_Port,LED0_Pin);
		
    vTaskDelay(ticks1);
  }
  /* USER CODE END appTask_led1 */
}

osDelay();

void appTask_led1(void *argument)
{
  /* USER CODE BEGIN appTask_led1 */
  /* Infinite loop */
  for(;;)
  {
		HAL_GPIO_TogglePin(LED0_GPIO_Port,LED0_Pin);
		osDelay(1000);
  }
  /* USER CODE END appTask_led1 */
}

1.1.2 绝对延时

vTaskDelayUntil(&wake_time,ticks2);

void appTask_led2(void *argument)
{
  /* USER CODE BEGIN appTask_led2 */
	TickType_t ticks2=pdMS_TO_TICKS(2000);	
	TickType_t wake_time=xTaskGetTickCount();
	
  /* Infinite loop */
  for(;;)
  {
	HAL_GPIO_TogglePin(LED1_GPIO_Port,LED1_Pin);
    vTaskDelayUntil(&wake_time,ticks2);		
  }
  /* USER CODE END appTask_led2 */
}

1.2 挂起和恢复

1.2.1 cmsis的挂起和恢复函数

osThreadSuspend

osThreadResume

void appTask_key1(void *argument)
{
  /* USER CODE BEGIN appTask_key1 */
  /* Infinite loop */
  for(;;)
  {
		if(HAL_GPIO_ReadPin(key0_GPIO_Port,key0_Pin)==GPIO_PIN_RESET)
		{
			osThreadSuspend(Task_led1Handle);
			
			
		}
    osDelay(20);
  }
  /* USER CODE END appTask_key1 */
}

void appTask_key2(void *argument)
{
  /* USER CODE BEGIN appTask_key2 */
  /* Infinite loop */
  for(;;)
  {
		if(HAL_GPIO_ReadPin(key1_GPIO_Port,key1_Pin)==GPIO_PIN_RESET)
		{
			osThreadResume(Task_led1Handle);
		}
    osDelay(20);
  }
  /* USER CODE END appTask_key2 */
}

1.2.2 freertos的挂起和恢复函数

vTaskSuspend

vTaskResume

void appTask_key1(void *argument)
{
  /* USER CODE BEGIN appTask_key1 */
  /* Infinite loop */
  for(;;)
  {
		if(HAL_GPIO_ReadPin(key0_GPIO_Port,key0_Pin)==GPIO_PIN_RESET)
		{
			vTaskSuspend((TaskHandle_t)Task_led1Handle);
			
		}
    osDelay(20);
  }
  /* USER CODE END appTask_key1 */
}
void appTask_key2(void *argument)
{
  /* USER CODE BEGIN appTask_key2 */
  /* Infinite loop */
  for(;;)
  {
		if(HAL_GPIO_ReadPin(key1_GPIO_Port,key1_Pin)==GPIO_PIN_RESET)
		{
			
			vTaskResume((TaskHandle_t)Task_led1Handle);

		}
    osDelay(20);
  }
  /* USER CODE END appTask_key2 */
}

1.3 删除

1.3.1 cmsis的删除任务函数

osThreadTerminate

void appTask_key1(void *argument)
{
  /* USER CODE BEGIN appTask_key1 */
  /* Infinite loop */
  for(;;)
  {
		if(HAL_GPIO_ReadPin(key0_GPIO_Port,key0_Pin)==GPIO_PIN_RESET)
		{
			osThreadTerminate(Task_led1Handle);
		}
    osDelay(20);
  }
  /* USER CODE END appTask_key1 */
}

1.3.2 freertos的删除任务函数

直接使用vTaskDelete会导致程序卡死,进入HardFault_Handler函数

二、Freertos任务与中断

三、消息队列

文件

在这里插入图片描述

3.1 写入和读取一个数据

osMessageQueuePut 将一个新的项目发送到队列的末尾
osMessageQueueGet 从队列的前面读取一个(读取以后会自动删除那个)

void appTask_led2(void *argument)
{
  /* USER CODE BEGIN appTask_led2 */

	uint32_t data = 0;		
  /* Infinite loop */
  for(;;)
  {
		data++;	
		osMessageQueuePut(myQueue01Handle,&data,0,0);
		osDelay(1000);
  }
  /* USER CODE END appTask_led2 */
}
void appTask_key1(void *argument)
{
  /* USER CODE BEGIN appTask_key1 */
	uint32_t receivedData = 0;
  /* Infinite loop */
  for(;;)
  {
		osMessageQueueGet(myQueue01Handle, &receivedData, 0, osWaitForever);
		/* 处理数据,这里我们只是简单地打印出来 */
		printf("Received data: %d\n", receivedData);

  }
  /* USER CODE END appTask_key1 */
}

3.2 写入和读取一个段数据 (指针) (分配内存法)

osMessageQueuePut
osMessageQueueGet

pvPortMalloc
vPortFree

#define ARRAY_SIZE 20
void appTask_led2(void *argument)
{
  /* USER CODE BEGIN appTask_led2 */


  /* Infinite loop */
  for(;;)
  {
		uint32_t* array = (uint32_t*)pvPortMalloc(ARRAY_SIZE * sizeof(uint32_t));
    for (int i = 0; i < ARRAY_SIZE; i++) 
		{
        array[i] = i;
    }

		osMessageQueuePut(myQueue01Handle, &array, 0, 0);
		osDelay(1000);
  }
  /* USER CODE END appTask_led2 */
}
void appTask_key1(void *argument)
{
  /* USER CODE BEGIN appTask_key1 */
  /* Infinite loop */
  for(;;)
  {
		uint32_t* receivedArray;
    osMessageQueueGet(myQueue01Handle, &receivedArray, 0, osWaitForever);
    // Process the array
    for (int i = 0; i < ARRAY_SIZE; i++) {
        printf("Received: %d\n", receivedArray[i]);
			HAL_Delay(10);
    }
		vPortFree(receivedArray);

  }
  /* USER CODE END appTask_key1 */
}

四、二值信号量

文件

在这里插入图片描述

void appTask_led2(void *argument)
{
  /* USER CODE BEGIN appTask_led2 */
  /* Infinite loop */
  for(;;)
  {
		osSemaphoreAcquire(Bin_key0_readyHandle,osWaitForever);
		printf("hello world\n");
		
  }
  /* USER CODE END appTask_led2 */
}
void appTask_key1(void *argument)
{
  /* USER CODE BEGIN appTask_key1 */
  /* Infinite loop */
  for(;;)
  {
		if(HAL_GPIO_ReadPin(key0_GPIO_Port,key0_Pin)==GPIO_PIN_RESET)
		{
			osSemaphoreRelease(Bin_key0_readyHandle);
		}
  }
  /* USER CODE END appTask_key1 */
}

但是

有效方案是:
在使用那个二值信号量的任务主循环之前先调用一次, osSemaphoreAcquire(Bin_key0_readyHandle,0);
要注意位置!!

void appTask_led2(void *argument)
{
  /* USER CODE BEGIN appTask_led2 */
  /* Infinite loop */
	osSemaphoreAcquire(Bin_key0_readyHandle,0);
  for(;;)
  {
		osSemaphoreAcquire(Bin_key0_readyHandle,osWaitForever);
		printf("hello world\n");
  }
  /* USER CODE END appTask_led2 */
}

五、互斥量

在这里插入图片描述

void appTask_led2(void *argument)
{
  /* USER CODE BEGIN appTask_led2 */
  /* Infinite loop */

  for(;;)
  {
		osMutexAcquire(usart_MutexHandle, osWaitForever);
		// Use the UART here...
		printf("hello world user cc\n");		
		osMutexRelease(usart_MutexHandle);
		osDelay(20);
		
  }
  /* USER CODE END appTask_led2 */
}
void appTask_key1(void *argument)
{
  /* USER CODE BEGIN appTask_key1 */
  /* Infinite loop */
  for(;;)
  {
		osMutexAcquire(usart_MutexHandle, osWaitForever);
		printf("hello\n");		
		osMutexRelease(usart_MutexHandle);
		osDelay(5);
  }
  /* USER CODE END appTask_key1 */
}

六、事件组

文件
在这里插入图片描述

6.1 设置位

void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
	if (huart->Instance == USART1)
	{
		memcpy(MainBuf_1, RxBuf_1, Size);	//将接收缓冲区的数据复制到主缓冲区
		
		/* 再次启动 DMA */
		HAL_UARTEx_ReceiveToIdle_DMA(&huart1, (uint8_t *) RxBuf_1, RxBuf_SIZE_1);
		__HAL_DMA_DISABLE_IT(&hdma_usart1_rx, DMA_IT_HT);
		
		if(MainBuf_1[0]==1)
		{
			osEventFlagsSet(myEvent01Handle,EVENT_0_BIT);
		}
		if(MainBuf_1[0]==2)
		{
			osEventFlagsSet(myEvent01Handle,EVENT_1_BIT);
		}
	}

}

6.2 等待位

当两个标志位都被置为的时候才能进行任务。
flags 得到的值是EVENT_0_BIT和EVENT_1_BIT相与的值。

所以

#define EVENT_0_BIT (1 << 0) // Event bit 0, which corresponds to event 1

#define EVENT_1_BIT (1 << 1) // Event bit 1, which corresponds to event 2

其他的就应该 (1<<?)

  for(;;)
  {
		
		uint32_t flags = osEventFlagsWait(myEvent01Handle,EVENT_0_BIT|EVENT_1_BIT,osFlagsWaitAll,osWaitForever);

		if (flags & EVENT_0_BIT) 
		{
      // Event 1 has occurred
			printf("over 1\n");
    	}
    		if (flags & EVENT_1_BIT) {
      		// Event 2 has occurred
			printf("over 2\n");
    	}
		printf("over 5\n");		
		
  	}

七、任务通知

7.1 CMSIS-RTOS API 线程标志

无需配置cubemx

#include "FreeRTOS.h"
#include "task.h"
#include "main.h"
#include "cmsis_os.h"
#define Thread_0_BIT (1 << 0)  // Event bit 0, which corresponds to event 1
#define Thread_1_BIT (1 << 1)  // Event bit 1, which corresponds to event 2

extern osThreadId_t Task_led2Handle;

void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
	if (huart->Instance == USART1)
	{
		memcpy(MainBuf_1, RxBuf_1, Size);	//将接收缓冲区的数据复制到主缓冲区
		/* 再次启动 DMA */
		HAL_UARTEx_ReceiveToIdle_DMA(&huart1, (uint8_t *) RxBuf_1, RxBuf_SIZE_1);
		__HAL_DMA_DISABLE_IT(&hdma_usart1_rx, DMA_IT_HT);
		if(MainBuf_1[0]==1)
		{
			osThreadFlagsSet(Task_led2Handle,Thread_0_BIT);
			//xTaskNotifyFromISR()
		}
		if(MainBuf_1[0]==2)
		{
			osThreadFlagsSet(Task_led2Handle,Thread_1_BIT);
		}
	}
}

void appTask_led2(void *argument)
{
  /* USER CODE BEGIN appTask_led2 */
  /* Infinite loop */
#define Thread_0_BIT (1 << 0)  // Event bit 0, which corresponds to event 1
#define Thread_1_BIT (1 << 1)  // Event bit 1, which corresponds to event 2
  for(;;)
  {
		uint32_t flags = osThreadFlagsWait(Thread_0_BIT|Thread_1_BIT,osFlagsWaitAny,osWaitForever);
		if (flags & Thread_0_BIT) 
		{
		// Event 1 has occurred
			printf("over 1\n");
		}
		if (flags & Thread_1_BIT) {
				// Event 2 has occurred
			printf("over 2\n");
		}
		printf("over 5\n");		
		
  }
  /* USER CODE END appTask_led2 */
}

任务通知(线程标志)和事件组在功能上确实有很多相似之处,都可以用于通知线程某种状态的发生。然而,它们之间还是有一些关键的区别:

7.2 Free-RTOS API 任务通知 (待填)

八、流缓冲区 (待填)

九、消息缓冲区 (待填)

十、软件定时器

10.1 任务中开启定时器

10.1.1 周期定时器

在这里插入图片描述

#include "FreeRTOS.h"
#include "task.h"
#include "main.h"
#include "cmsis_os.h"
#define Thread_0_BIT (1 << 0)  // Event bit 0, which corresponds to event 1
#define Thread_1_BIT (1 << 1)  // Event bit 1, which corresponds to event 2

extern osThreadId_t Task_led2Handle;

extern osTimerId_t myTimer01Handle;

void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
	if (huart->Instance == USART1)
	{
		memcpy(MainBuf_1, RxBuf_1, Size);	//将接收缓冲区的数据复制到主缓冲区
		
		/* 再次启动 DMA */
		HAL_UARTEx_ReceiveToIdle_DMA(&huart1, (uint8_t *) RxBuf_1, RxBuf_SIZE_1);
		__HAL_DMA_DISABLE_IT(&hdma_usart1_rx, DMA_IT_HT);
		
		if(MainBuf_1[0]==1)
		{
			osThreadFlagsSet(Task_led2Handle,Thread_0_BIT);
			
		}
		if(MainBuf_1[0]==2)
		{
			osThreadFlagsSet(Task_led2Handle,Thread_1_BIT);
		}
		
	}

}
void appTask_led2(void *argument)
{
  /* USER CODE BEGIN appTask_led2 */
  /* Infinite loop */
#define Thread_0_BIT (1 << 0)  // Event bit 0, which corresponds to event 1
#define Thread_1_BIT (1 << 1)  // Event bit 1, which corresponds to event 2
  for(;;)
  {
		uint32_t flags = osThreadFlagsWait(Thread_0_BIT,osFlagsWaitAny,osWaitForever);
		osTimerStart(myTimer01Handle,1000);
		
  }
  /* USER CODE END appTask_led2 */
}
void Callback01(void *argument)
{
  /* USER CODE BEGIN Callback01 */
		HAL_GPIO_TogglePin(LED0_GPIO_Port,LED0_Pin);
		HAL_GPIO_TogglePin(LED1_GPIO_Port,LED1_Pin);
  /* USER CODE END Callback01 */
}

10.1.2单次定时器

在这里插入图片描述

10.2 中断中开启定时器 (待填)

十一、空闲任务与低功耗 (待填)


总结

举报

相关推荐

0 条评论