STM32CUBEIDE FreeRTOS利用教程(十二):std dynamic memory 标准动态内存

[复制链接]
发表于 2025-11-15 08:21:05 | 显示全部楼层 |阅读模式
STM32CUBEIDE FreeRTOS利用教程(十二):std dynamic memory 标准动态内存

STM32CUBE开发情况集成了STM32 HAL库举行FreeRTOS设置和开发的组件,不必要用户本身举行FreeRTOS的移植。这里先容最简化的用户利用类应用教程。以STM32F401RCT6开发板为例,只用到USB,USART1少少的接口,表现FreeRTOS的各种利用过程。

利用教程(十一)设置FreeRTOS及相干情况,采取C语言标准的的方法申请/开释动态内存空间,作为USB假造串口吸收数据的数组空间,当USB假造串口吸收到数据时,通过信号量方式指示给任务,由任务将数据从USB假造串口发出,实现USB假造串口数据发送环回功能
FreeRTOS的教程较多,保举参考正点原子所出的《STM32F407 FreeRTOS开发手册》相识相干知识。


STM32CUBEIDE工程设置

选择TIM1(也可以是别的TIM)作为FreeRTOS利用体系占用的时钟源:


设置时钟树包罗USB的48MHz时钟:

设置PC13为低电平点灯的管脚:

设置USB串口:




设置UART1串口(但本例中不消到UART1):




FreeRTOS设置











生存并天生底子工程代码

在天生代码的这个部门可以看到FreeRTOS代码部门:

任务实现

基于前述的设置,main.c代码里会加载Free-RTOS的设置,并启动几个任务的调治,固然,此时的任务都是什么也不干。实现LED闪灯,就在LED闪灯任务里加入代码即可:
  1. void StartTask_TASK_LED_FLASH(void *argument)
  2. {
  3.   /* USER CODE BEGIN StartTask_TASK_LED_FLASH */
  4.   /* Infinite loop */
  5.   for(;;)
  6.   {
  7.     osDelay(1000);
  8.     HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
  9.   }
  10.   /* USER CODE END StartTask_TASK_LED_FLASH */
  11. }
复制代码
也就实现了LED闪灯功能,此中osDelay(1000);实现1秒时间的利用体系调治延时,也就是1秒实行一次LED灯的亮灭。osDelay(1);是最小的调治延时,为1毫秒。要实现更小的延时,则可以用微秒延时函数实现,参考《STM32 HAL us delay(微秒延时)的指令延时实现方式及优化》
在USB数据吸收回调函数里,开出了动态内存地区,举行数据转存和信号量设置:

  1. static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len)
  2. {
  3.   /* USER CODE BEGIN 6 */
  4.         extern uint8_t * USB_VCOM_BUFF;
  5.         extern uint32_t USB_VCOM_INDEX;
  6.         extern osSemaphoreId_t USB_VCOM_BinarySem01Handle;
  7.         extern BaseType_t USB_VCOM_pxHigherPriorityTaskWaken;
  8.         USB_VCOM_BUFF = malloc(*Len);
  9.         memcpy(USB_VCOM_BUFF, Buf, *Len);
  10.         USB_VCOM_INDEX = *Len;
  11.         xSemaphoreGiveFromISR(USB_VCOM_BinarySem01Handle, &USB_VCOM_pxHigherPriorityTaskWaken);
  12.   USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &Buf[0]);
  13.   USBD_CDC_ReceivePacket(&hUsbDeviceFS);
  14.   return (USBD_OK);
  15.   /* USER CODE END 6 */
  16. }
复制代码
的main.c在USB数据处置惩罚任务里,发送完数据后开释内存空间:

  1. void StartTask_TASK_USB_VCOM(void *argument)
  2. {
  3.   /* USER CODE BEGIN StartTask_TASK_USB_VCOM */
  4.   BaseType_t err_stu = pdFALSE;
  5.   /* Infinite loop */
  6.   for(;;)
  7.   {
  8.     osDelay(10);
  9.     USB_VCOM_xBlockTime = 0; //Block(waiting) time to get semaphore
  10.     err_stu = xSemaphoreTake(USB_VCOM_BinarySem01Handle, USB_VCOM_xBlockTime);
  11.     if(err_stu==pdTRUE)
  12.     {
  13.             usbprintarray(USB_VCOM_BUFF, USB_VCOM_INDEX);
  14.             USB_VCOM_INDEX = 0;
  15.             free(USB_VCOM_BUFF);
  16.     }
  17.   }
  18.   /* USER CODE END StartTask_TASK_USB_VCOM */
  19. }
复制代码
main.c文件的完备代码为:
  1. /* USER CODE BEGIN Header *//**  ******************************************************************************  * @file           : main.c  * @brief          : Main program body  ******************************************************************************  * @attention  *  * Copyright (c) 2023 STMicroelectronics.  * All rights reserved.  *  * This software is licensed under terms that can be found in the LICENSE file  * in the root directory of this software component.  * If no LICENSE file comes with this software, it is provided AS-IS.  *  ******************************************************************************  *///Example 12: LED flash + USB VCOM loop back with dynamic memory apply/release in standard mode//Written by Pegasus Yu/* USER CODE END Header *//* Includes ------------------------------------------------------------------*/#include "main.h"#include "cmsis_os.h"#include "usb_device.h"/* Private includes ----------------------------------------------------------*//* USER CODE BEGIN Includes */#include "semphr.h"/* USER CODE END Includes *//* Private typedef -----------------------------------------------------------*//* USER CODE BEGIN PTD */__IO float usDelayBase = 7.63238716; //For STM32F401RCT6 working in 84MHz main clockvoid PY_Delay_us_t(uint32_t Delay){  __IO uint32_t delayReg;  __IO uint32_t usNum = (uint32_t)(Delay*usDelayBase);  delayReg = 0;  while(delayReg!=usNum) delayReg++;}/* USER CODE END PTD *//* Private define ------------------------------------------------------------*//* USER CODE BEGIN PD *//* USER CODE END PD *//* Private macro -------------------------------------------------------------*//* USER CODE BEGIN PM *//* USER CODE END PM *//* Private variables ---------------------------------------------------------*/UART_HandleTypeDef huart1;DMA_HandleTypeDef hdma_usart1_rx;/* Definitions for defaultTask */osThreadId_t defaultTaskHandle;const osThreadAttr_t defaultTask_attributes = {  .name = "defaultTask",  .stack_size = 128 * 4,  .priority = (osPriority_t) osPriorityNormal,};/* Definitions for TASK_LED_FLASH */osThreadId_t TASK_LED_FLASHHandle;const osThreadAttr_t TASK_LED_FLASH_attributes = {  .name = "TASK_LED_FLASH",  .stack_size = 128 * 4,  .priority = (osPriority_t) osPriorityLow,};/* Definitions for TASK_UART1 */osThreadId_t TASK_UART1Handle;const osThreadAttr_t TASK_UART1_attributes = {  .name = "TASK_UART1",  .stack_size = 128 * 4,  .priority = (osPriority_t) osPriorityLow,};/* Definitions for TASK_USB_VCOM */osThreadId_t TASK_USB_VCOMHandle;const osThreadAttr_t TASK_USB_VCOM_attributes = {  .name = "TASK_USB_VCOM",  .stack_size = 128 * 4,  .priority = (osPriority_t) osPriorityLow,};/* Definitions for USB_VCOM_BinarySem01 */osSemaphoreId_t USB_VCOM_BinarySem01Handle;const osSemaphoreAttr_t USB_VCOM_BinarySem01_attributes = {  .name = "USB_VCOM_BinarySem01"};/* USER CODE BEGIN PV *//* USER CODE END PV *//* Private function prototypes -----------------------------------------------*/void SystemClock_Config(void);static void MX_GPIO_Init(void);static void MX_DMA_Init(void);static void MX_USART1_UART_Init(void);void StartDefaultTask(void *argument);void StartTask_TASK_LED_FLASH(void *argument);void StartTask_TASK_UART1(void *argument);void StartTask_TASK_USB_VCOM(void *argument);/* USER CODE BEGIN PFP *//* USER CODE END PFP *//* Private user code ---------------------------------------------------------*//* USER CODE BEGIN 0 */uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len);void usbprintstring(char * data){        if(CDC_Transmit_FS((uint8_t *)data, strlen(data))==USBD_BUSY)        {                PY_Delay_us_t(1000000);            CDC_Transmit_FS((uint8_t *)data, strlen(data));        }}void usbprintarray(uint8_t * data, uint16_t len){        if(CDC_Transmit_FS(data, len)==USBD_BUSY)        {                PY_Delay_us_t(1000000);                CDC_Transmit_FS(data, len);        }}uint8_t * USB_VCOM_BUFF;uint32_t USB_VCOM_INDEX;BaseType_t USB_VCOM_pxHigherPriorityTaskWaken;TickType_t USB_VCOM_xBlockTime = 0;/* USER CODE END 0 *//**  * @brief  The application entry point.  * @retval int  */int main(void){  /* USER CODE BEGIN 1 */  /* USER CODE END 1 */  /* MCU Configuration--------------------------------------------------------*/  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */  HAL_Init();  /* USER CODE BEGIN Init */  /* USER CODE END Init */  /* Configure the system clock */  SystemClock_Config();  /* USER CODE BEGIN SysInit */  /* USER CODE END SysInit */  /* Initialize all configured peripherals */  MX_GPIO_Init();  MX_DMA_Init();  MX_USART1_UART_Init();  /* USER CODE BEGIN 2 */  /* USER CODE END 2 */  /* Init scheduler */  osKernelInitialize();  /* USER CODE BEGIN RTOS_MUTEX */  /* add mutexes, ... */  /* USER CODE END RTOS_MUTEX */  /* Create the semaphores(s) */  /* creation of USB_VCOM_BinarySem01 */  USB_VCOM_BinarySem01Handle = osSemaphoreNew(1, 0, &USB_VCOM_BinarySem01_attributes);  /* USER CODE BEGIN RTOS_SEMAPHORES */  /* add semaphores, ... */  /* USER CODE END RTOS_SEMAPHORES */  /* USER CODE BEGIN RTOS_TIMERS */  /* start timers, add new ones, ... */  /* USER CODE END RTOS_TIMERS */  /* USER CODE BEGIN RTOS_QUEUES */  /* add queues, ... */  /* USER CODE END RTOS_QUEUES */  /* Create the thread(s) */  /* creation of defaultTask */  defaultTaskHandle = osThreadNew(StartDefaultTask, NULL, &defaultTask_attributes);  /* creation of TASK_LED_FLASH */  TASK_LED_FLASHHandle = osThreadNew(StartTask_TASK_LED_FLASH, NULL, &TASK_LED_FLASH_attributes);  /* creation of TASK_UART1 */  TASK_UART1Handle = osThreadNew(StartTask_TASK_UART1, NULL, &TASK_UART1_attributes);  /* creation of TASK_USB_VCOM */  TASK_USB_VCOMHandle = osThreadNew(StartTask_TASK_USB_VCOM, NULL, &TASK_USB_VCOM_attributes);  /* USER CODE BEGIN RTOS_THREADS */  /* add threads, ... */  /* USER CODE END RTOS_THREADS */  /* USER CODE BEGIN RTOS_EVENTS */  /* add events, ... */  /* USER CODE END RTOS_EVENTS */  /* Start scheduler */  osKernelStart();  /* We should never get here as control is now taken by the scheduler */  /* Infinite loop */  /* USER CODE BEGIN WHILE */  while (1)  {    /* USER CODE END WHILE */    /* USER CODE BEGIN 3 */  }  /* USER CODE END 3 */}/**  * @brief System Clock Configuration  * @retval None  */void SystemClock_Config(void){  RCC_OscInitTypeDef RCC_OscInitStruct = {0};  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};  /** Configure the main internal regulator output voltage  */  __HAL_RCC_PWR_CLK_ENABLE();  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE2);  /** Initializes the RCC Oscillators according to the specified parameters  * in the RCC_OscInitTypeDef structure.  */  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;  RCC_OscInitStruct.HSEState = RCC_HSE_ON;  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;  RCC_OscInitStruct.PLL.PLLM = 25;  RCC_OscInitStruct.PLL.PLLN = 336;  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV4;  RCC_OscInitStruct.PLL.PLLQ = 7;  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)  {    Error_Handler();  }  /** Initializes the CPU, AHB and APB buses clocks  */  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)  {    Error_Handler();  }}/**  * @brief USART1 Initialization Function  * @param None  * @retval None  */static void MX_USART1_UART_Init(void){  /* USER CODE BEGIN USART1_Init 0 */  /* USER CODE END USART1_Init 0 */  /* USER CODE BEGIN USART1_Init 1 */  /* USER CODE END USART1_Init 1 */  huart1.Instance = USART1;  huart1.Init.BaudRate = 115200;  huart1.Init.WordLength = UART_WORDLENGTH_8B;  huart1.Init.StopBits = UART_STOPBITS_1;  huart1.Init.Parity = UART_PARITY_NONE;  huart1.Init.Mode = UART_MODE_TX_RX;  huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;  huart1.Init.OverSampling = UART_OVERSAMPLING_16;  if (HAL_UART_Init(&huart1) != HAL_OK)  {    Error_Handler();  }  /* USER CODE BEGIN USART1_Init 2 */  /* USER CODE END USART1_Init 2 */}/**  * Enable DMA controller clock  */static void MX_DMA_Init(void){  /* DMA controller clock enable */  __HAL_RCC_DMA2_CLK_ENABLE();  /* DMA interrupt init */  /* DMA2_Stream2_IRQn interrupt configuration */  HAL_NVIC_SetPriority(DMA2_Stream2_IRQn, 5, 0);  HAL_NVIC_EnableIRQ(DMA2_Stream2_IRQn);}/**  * @brief GPIO Initialization Function  * @param None  * @retval None  */static void MX_GPIO_Init(void){  GPIO_InitTypeDef GPIO_InitStruct = {0};/* USER CODE BEGIN MX_GPIO_Init_1 *//* USER CODE END MX_GPIO_Init_1 */  /* GPIO Ports Clock Enable */  __HAL_RCC_GPIOC_CLK_ENABLE();  __HAL_RCC_GPIOH_CLK_ENABLE();  __HAL_RCC_GPIOA_CLK_ENABLE();  /*Configure GPIO pin Output Level */  HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET);  /*Configure GPIO pin : LED_Pin */  GPIO_InitStruct.Pin = LED_Pin;  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;  GPIO_InitStruct.Pull = GPIO_NOPULL;  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;  HAL_GPIO_Init(LED_GPIO_Port, &GPIO_InitStruct);/* USER CODE BEGIN MX_GPIO_Init_2 *//* USER CODE END MX_GPIO_Init_2 */}/* USER CODE BEGIN 4 *//* USER CODE END 4 *//* USER CODE BEGIN Header_StartDefaultTask *//**  * @brief  Function implementing the defaultTask thread.  * @param  argument: Not used  * @retval None  *//* USER CODE END Header_StartDefaultTask */void StartDefaultTask(void *argument){  /* init code for USB_DEVICE */  MX_USB_DEVICE_Init();  /* USER CODE BEGIN 5 */  /* Infinite loop */  for(;;)  {    osDelay(1);  }  /* USER CODE END 5 */}/* USER CODE BEGIN Header_StartTask_TASK_LED_FLASH *//*** @brief Function implementing the TASK_LED_FLASH thread.* @param argument: Not used* @retval None*//* USER CODE END Header_StartTask_TASK_LED_FLASH */void StartTask_TASK_LED_FLASH(void *argument)
  2. {
  3.   /* USER CODE BEGIN StartTask_TASK_LED_FLASH */
  4.   /* Infinite loop */
  5.   for(;;)
  6.   {
  7.     osDelay(1000);
  8.     HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
  9.   }
  10.   /* USER CODE END StartTask_TASK_LED_FLASH */
  11. }
  12. /* USER CODE BEGIN Header_StartTask_TASK_UART1 *//*** @brief Function implementing the TASK_UART1 thread.* @param argument: Not used* @retval None*//* USER CODE END Header_StartTask_TASK_UART1 */void StartTask_TASK_UART1(void *argument){  /* USER CODE BEGIN StartTask_TASK_UART1 */  /* Infinite loop */  for(;;)  {    osDelay(1);  }  /* USER CODE END StartTask_TASK_UART1 */}/* USER CODE BEGIN Header_StartTask_TASK_USB_VCOM *//*** @brief Function implementing the TASK_USB_VCOM thread.* @param argument: Not used* @retval None*//* USER CODE END Header_StartTask_TASK_USB_VCOM */void StartTask_TASK_USB_VCOM(void *argument)
  13. {
  14.   /* USER CODE BEGIN StartTask_TASK_USB_VCOM */
  15.   BaseType_t err_stu = pdFALSE;
  16.   /* Infinite loop */
  17.   for(;;)
  18.   {
  19.     osDelay(10);
  20.     USB_VCOM_xBlockTime = 0; //Block(waiting) time to get semaphore
  21.     err_stu = xSemaphoreTake(USB_VCOM_BinarySem01Handle, USB_VCOM_xBlockTime);
  22.     if(err_stu==pdTRUE)
  23.     {
  24.             usbprintarray(USB_VCOM_BUFF, USB_VCOM_INDEX);
  25.             USB_VCOM_INDEX = 0;
  26.             free(USB_VCOM_BUFF);
  27.     }
  28.   }
  29.   /* USER CODE END StartTask_TASK_USB_VCOM */
  30. }
  31. /**  * @brief  Period elapsed callback in non blocking mode  * @note   This function is called  when TIM1 interrupt took place, inside  * HAL_TIM_IRQHandler(). It makes a direct call to HAL_IncTick() to increment  * a global variable "uwTick" used as application time base.  * @param  htim : TIM handle  * @retval None  */void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){  /* USER CODE BEGIN Callback 0 */  /* USER CODE END Callback 0 */  if (htim->Instance == TIM1) {    HAL_IncTick();  }  /* USER CODE BEGIN Callback 1 */  /* USER CODE END Callback 1 */}/**  * @brief  This function is executed in case of error occurrence.  * @retval None  */void Error_Handler(void){  /* USER CODE BEGIN Error_Handler_Debug */  /* User can add his own implementation to report the HAL error return state */  __disable_irq();  while (1)  {  }  /* USER CODE END Error_Handler_Debug */}#ifdef  USE_FULL_ASSERT/**  * @brief  Reports the name of the source file and the source line number  *         where the assert_param error has occurred.  * @param  file: pointer to the source file name  * @param  line: assert_param error line source number  * @retval None  */void assert_failed(uint8_t *file, uint32_t line){  /* USER CODE BEGIN 6 */  /* User can add his own implementation to report the file name and line number,     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */  /* USER CODE END 6 */}#endif /* USE_FULL_ASSERT */
复制代码
例程下载

STM32 STM32CUBEIDE FreeRTOS利用教程(十二):std dynamic memory标准动态内存 例程
例程测试

例程测试效果如下:

–End–

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
继续阅读请点击广告

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
回复

使用道具 举报

×
登录参与点评抽奖,加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表