text: /**
   * @file lv_gpu_nxp_pxp_osa.c
   *
   */
  
  /**
   * SPDX-License-Identifier: MIT
   * Copyright 2020-2021 NXP
   */
  
  /*********************
   *      INCLUDES
   *********************/
  
  #include "lv_conf.h"
  
  #if LV_USE_GPU_NXP_PXP && LV_USE_GPU_NXP_PXP_AUTO_INIT
  
  #include "lv_gpu_nxp_pxp.h"
  #include "fsl_pxp.h"
  
  #if defined(FSL_RTOS_FREE_RTOS)
      #include "FreeRTOS.h"
      #include "semphr.h"
  #endif
  
  
  /*********************
   *      DEFINES
   *********************/
  
  /**********************
   *      TYPEDEFS
   **********************/
  
  /**********************
   *  STATIC PROTOTYPES
   **********************/
  static lv_res_t _lv_gpu_nxp_pxp_interrupt_init(void);
  static void _lv_gpu_nxp_pxp_interrupt_deinit(void);
  static void _lv_gpu_nxp_pxp_run(void);
  
  /**********************
   *  STATIC VARIABLES
   **********************/
  
  #if defined(FSL_RTOS_FREE_RTOS)
      static SemaphoreHandle_t s_pxpIdle;
  #else
      static volatile bool s_pxpIdle;
  #endif
  
  /**********************
   *      MACROS
   **********************/
  
  /**********************
   *   GLOBAL FUNCTIONS
   **********************/
  
  /**
   * PXP device interrupt handler. Used to check PXP task completion status.
   */
  void PXP_IRQHandler(void)
  {
  #if defined(FSL_RTOS_FREE_RTOS)
      BaseType_t taskAwake = pdFALSE;
  #endif
  
      if(kPXP_CompleteFlag & PXP_GetStatusFlags(LV_GPU_NXP_PXP_ID)) {
          PXP_ClearStatusFlags(LV_GPU_NXP_PXP_ID, kPXP_CompleteFlag);
  #if defined(FSL_RTOS_FREE_RTOS)
          xSemaphoreGiveFromISR(s_pxpIdle, &taskAwake);
          portYIELD_FROM_ISR(taskAwake);
  #else
          s_pxpIdle = true;
  #endif
  
      }
  }
  
  /**********************
   *   STATIC FUNCTIONS
   **********************/
  
  /**
   * PXP interrupt initialization.
   */
  static lv_res_t _lv_gpu_nxp_pxp_interrupt_init(void)
  {
  #if defined(FSL_RTOS_FREE_RTOS)
      s_pxpIdle = xSemaphoreCreateBinary();
      if(s_pxpIdle == NULL) {
          return LV_RES_INV;
      }
  
      NVIC_SetPriority(LV_GPU_NXP_PXP_IRQ_ID, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY + 1);
  #else
      s_pxpIdle = true;
  #endif
  
      NVIC_EnableIRQ(LV_GPU_NXP_PXP_IRQ_ID);
  
      return LV_RES_OK;
  }
  
  /**
   * PXP interrupt de-initialization.
   */
  static void _lv_gpu_nxp_pxp_interrupt_deinit(void)
  {
      NVIC_DisableIRQ(LV_GPU_NXP_PXP_IRQ_ID);
  #if defined(FSL_RTOS_FREE_RTOS)
      vSemaphoreDelete(s_pxpIdle);
  #endif
  }
  
  /**
   * Function to start PXP job. This function must wait for task complete.
   */
  static void _lv_gpu_nxp_pxp_run(void)
  {
  #if !defined(FSL_RTOS_FREE_RTOS)
      s_pxpIdle = false;
  #endif
  
      PXP_EnableInterrupts(LV_GPU_NXP_PXP_ID, kPXP_CompleteInterruptEnable);
      PXP_Start(LV_GPU_NXP_PXP_ID);
  
  #if defined(FSL_RTOS_FREE_RTOS)
      if(xSemaphoreTake(s_pxpIdle, portMAX_DELAY) != pdTRUE) {
          LV_LOG_ERROR("xSemaphoreTake error. Task halted.");
          for(; ;) ;
      }
  #else
      while(s_pxpIdle == false) {
      }
  #endif
  }
  
  lv_nxp_pxp_cfg_t pxp_default_cfg = {
      .pxp_interrupt_init = _lv_gpu_nxp_pxp_interrupt_init,
      .pxp_interrupt_deinit = _lv_gpu_nxp_pxp_interrupt_deinit,
      .pxp_run = _lv_gpu_nxp_pxp_run
  };
  
  #endif /* LV_USE_GPU_NXP_PXP && LV_USE_GPU_NXP_PXP_AUTO_INIT */
  