Multi Task pada mikrokontroler STM32F103C8 dengan FreeRTOS STM32CubeMX

Real Time Operating System (RTOS), merupakan metode yang digunakan untuk menjalankan multi task atau thread pada mikrokontroler. Kali ini kita akan mempelajari penggunaan library FreeRTOS yang sudah disertakan di STM32CubeMX, sehingga lebih mudah dalam menggunakannya. Yang perlu disiapkan adalah :

  1. Blue Pill STM32F103C8T6
  2. Led
  3. Breadboad
  4. Kabel Jumper
  5. ST-Link Programmer

Pertama rakit dulu hardware di breadboard, pasang led pada pin GPIO yang mana saja bebas. Di sini akan dicontohkan led dipasang di PA0 dan PA1.

Kemudian buat project baru di STM32CubeMX dengan pengaturan sebagai berikut

  • Aktifkan library FreeRTOS
  • Aktifkan RCC -> HSE -> Crystal/Ceramic Resonator
  • SYS Timebase Source -> TIM1
  • Aktifkan GPIO_Out PA0 dan PA1
  • Dibagian ClockConfiguration Clock HCLK 72 MHz

Generate Code, dan buka projectdi Eclipse. Kita akan membuat 2 task yang berbeda interval waktu pengerjaanya.

Task 1 : Menyalakan blink LED 1 dengan interval 1 detik

Task2 : Menyalakan blink LED 2 dengan interval 200 mili detik

Jika tanpa RTOS, du Task tersebut tidak bisa dikerjakan bersamaan, melainkan akan mengerjakan Task 1 dulu sampai selesai, baru menyelesaikan Task 2. Tapi dengan RTOS kita dapat mengerjakan kedua Task secara bersamaan.

Buka file main.c. Kita harus membuat 2 Task di dalam program. Letakkan kode berikut dibagian atas program utama

osThreadId defaultTaskHandle;
osThreadId secondTaskHandle;

void StartDefaultTask(void const * argument);
void StartSecondTask(void const * argument);

Kemudian buat kode untuk memanggil task. Letakkan kode berikut didalam program utama. Ketika menggunakan FreeRTOS, Kita tidak perlu membuat program didalam loop while(1), karena semua eksekusi sudah dijalankan perintah ini.

  osThreadDef(defaultTask, StartDefaultTask, osPriorityNormal, 0, 128);
  defaultTaskHandle = osThreadCreate(osThread(defaultTask), NULL);

  osThreadDef(secondTask, StartSecondTask, osPriorityNormal, 0, 128);
  secondTaskHandle = osThreadCreate(osThread(secondTask), NULL);

Selanjutnya buat fungsi yang digunakan untuk mengerjakan Task. Teradapat 2 fungsi yang berisi task untuk mengedipkan LED dengan interval waktu yang berbeda. Letakkan kode ini dibagian bawah program utama.

//===============================================================================================================
/* StartDefaultTask function */
void StartDefaultTask(void const * argument)
{
  for(;;)
  {
	HAL_GPIO_WritePin(GPIOA,GPIO_PIN_0,LOW);
    osDelay(1000);

    HAL_GPIO_WritePin(GPIOA,GPIO_PIN_0,HIGH);
    osDelay(1000);
  }
}

//===============================================================================================================
/* StartSecondTask function */
void StartSecondTask(void const * argument)
{
  for(;;)
  {
	HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,LOW);
    osDelay(200);

    HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,HIGH);
    osDelay(200);
  }
}

Berikut Source Code keseluruhannya.


#include "main.h"
#include "stm32f1xx_hal.h"
#include "cmsis_os.h"

#define LOW  0
#define HIGH 1




void SystemClock_Config(void);
static void MX_GPIO_Init(void);

osThreadId defaultTaskHandle;
osThreadId secondTaskHandle;

void StartDefaultTask(void const * argument);
void StartSecondTask(void const * argument);


int main(void)
{

  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();

  osThreadDef(defaultTask, StartDefaultTask, osPriorityNormal, 0, 128);
  defaultTaskHandle = osThreadCreate(osThread(defaultTask), NULL);

  osThreadDef(secondTask, StartSecondTask, osPriorityNormal, 0, 128);
  secondTaskHandle = osThreadCreate(osThread(secondTask), NULL);

  osKernelStart();

  while (1)
  {
	  // Infinite loop, don't write code here
  }


}

//===============================================================================================================
/* StartDefaultTask function */
void StartDefaultTask(void const * argument)
{
  for(;;)
  {
	HAL_GPIO_WritePin(GPIOA,GPIO_PIN_0,LOW);
    osDelay(1000);

    HAL_GPIO_WritePin(GPIOA,GPIO_PIN_0,HIGH);
    osDelay(1000);
  }
}


//===============================================================================================================
/* StartSecondTask function */
void StartSecondTask(void const * argument)
{
  for(;;)
  {
	HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,LOW);
    osDelay(200);

    HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,HIGH);
    osDelay(200);
  }
}

//================================================================================================================

/** System Clock Configuration
*/
void SystemClock_Config(void)
{

  RCC_OscInitTypeDef RCC_OscInitStruct;
  RCC_ClkInitTypeDef RCC_ClkInitStruct;

    /**Initializes the CPU, AHB and APB busses clocks 
    */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

    /**Initializes the CPU, AHB and APB busses 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(__FILE__, __LINE__);
  }

    /**Configure the Systick interrupt time 
    */
  HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);

    /**Configure the Systick 
    */
  HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);

  /* SysTick_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(SysTick_IRQn, 15, 0);
}

/** Configure pins as 
        * Analog 
        * Input 
        * Output
        * EVENT_OUT
        * EXTI
*/
static void MX_GPIO_Init(void)
{

  GPIO_InitTypeDef GPIO_InitStruct;

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOD_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0|GPIO_PIN_1, GPIO_PIN_SET);

  /*Configure GPIO pins : PA0 PA1 */
  GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */



/**
  * @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.
  * @param  None
  * @retval None
  */
void _Error_Handler(char * file, int line)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  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

/**
  * @}
  */ 

/**
  * @}
*/ 

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

Berikut Video lengkapnya:

Selamat mencoba. Terima Kasih

Leave a Reply

Your email address will not be published. Required fields are marked *