225 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			225 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /**
 | |
|   ******************************************************************************
 | |
|   * File Name          : OSWrappers.cpp
 | |
|   ******************************************************************************
 | |
|   * @attention
 | |
|   *
 | |
|   * <h2><center>© Copyright (c) 2021 STMicroelectronics.
 | |
|   * All rights reserved.</center></h2>
 | |
|   *
 | |
|   * This software component is licensed by ST under Ultimate Liberty license
 | |
|   * SLA0044, the "License"; You may not use this file except in compliance with
 | |
|   * the License. You may obtain a copy of the License at:
 | |
|   *                             www.st.com/SLA0044
 | |
|   *
 | |
|   ******************************************************************************
 | |
|   */
 | |
| #include "touchgfx-config.h"
 | |
| #if ( TOUCHGFX_BAREMETAL != 0)
 | |
| #include <stm32f7xx_hal.h>
 | |
| #include <TouchGFXHAL.hpp>
 | |
| #endif // TOUCHGFX_BAREMETAL
 | |
| #if ( TOUCHGFX_FREERTOS != 0)
 | |
| #include <cassert>
 | |
| #include <cmsis_os2.h>
 | |
| #include <touchgfx/hal/HAL.hpp>
 | |
| #endif // TOUCHGFX_FREERTOS
 | |
| #include <touchgfx/hal/OSWrappers.hpp>
 | |
| 
 | |
| 
 | |
| #if (TOUCHGFX_BAREMETAL != 0)
 | |
| 	static volatile uint32_t fb_sem;
 | |
| 	static volatile uint32_t vsync_sem;
 | |
| #endif  // TOUCHGFX_BAREMETAL
 | |
| 
 | |
| #if (TOUCHGFX_FREERTOS != 0)
 | |
| 	#include <cmsis_os2.h>
 | |
| 	static osSemaphoreId_t frame_buffer_sem = NULL;
 | |
| 	static osMessageQueueId_t vsync_queue = NULL;
 | |
| 	// Just a dummy value to insert in the VSYNC queue.
 | |
| 	static uint32_t dummy = 0x5a;
 | |
| #endif //TOUCHGFX_FREERTOS
 | |
| 
 | |
| using namespace touchgfx;
 | |
| 
 | |
| /*
 | |
|  * Initialize frame buffer semaphore and queue/mutex for VSYNC signal.
 | |
|  */
 | |
| void OSWrappers::initialize()
 | |
| {
 | |
| 	#if (TOUCHGFX_BAREMETAL != 0)
 | |
| 		fb_sem = 0;
 | |
| 		vsync_sem = 0;
 | |
| 	#endif  // TOUCHGFX_BAREMETAL
 | |
| 	#if (TOUCHGFX_FREERTOS != 0)
 | |
| 		// Create a queue of length 1
 | |
| 		frame_buffer_sem = osSemaphoreNew(1, 1, NULL); // Binary semaphore
 | |
| 		assert((frame_buffer_sem != NULL) && "Creation of framebuffer semaphore failed");
 | |
| 
 | |
| 		// Create a queue of length 1
 | |
| 		vsync_queue = osMessageQueueNew(1, 4, NULL);
 | |
| 		assert((vsync_queue != NULL) && "Creation of vsync message queue failed");
 | |
| 	#endif // TOUCHGFX_FREERTOS
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Take the frame buffer semaphore. Blocks until semaphore is available.
 | |
|  */
 | |
| void OSWrappers::takeFrameBufferSemaphore()
 | |
| {
 | |
| 	#if (TOUCHGFX_BAREMETAL != 0)
 | |
| 	  while(fb_sem);
 | |
| 	  fb_sem = 1;
 | |
| 	#endif  // TOUCHGFX_BAREMETAL
 | |
| 	#if (TOUCHGFX_FREERTOS != 0)
 | |
| 	    osSemaphoreAcquire(frame_buffer_sem, osWaitForever);
 | |
| 	#endif // TOUCHGFX_FREERTOS
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Release the frame buffer semaphore.
 | |
|  */
 | |
| void OSWrappers::giveFrameBufferSemaphore()
 | |
| {
 | |
| 	#if (TOUCHGFX_BAREMETAL != 0)
 | |
| 	  fb_sem = 0;
 | |
| 	#endif  // TOUCHGFX_BAREMETAL
 | |
| 	#if (TOUCHGFX_FREERTOS != 0)
 | |
| 	  osSemaphoreRelease(frame_buffer_sem);
 | |
| 	#endif // TOUCHGFX_FREERTOS
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Attempt to obtain the frame buffer semaphore. If semaphore is not available, do
 | |
|  * nothing.
 | |
|  *
 | |
|  * Note must return immediately! This function does not care who has the taken the semaphore,
 | |
|  * it only serves to make sure that the semaphore is taken by someone.
 | |
|  */
 | |
| void OSWrappers::tryTakeFrameBufferSemaphore()
 | |
| {
 | |
| 	#if (TOUCHGFX_BAREMETAL != 0)
 | |
| 	  fb_sem = 1;
 | |
| 	#endif  // TOUCHGFX_BAREMETAL
 | |
| 	#if (TOUCHGFX_FREERTOS != 0)
 | |
| 	    osSemaphoreAcquire(frame_buffer_sem, 0);
 | |
| 	#endif // TOUCHGFX_FREERTOS
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Release the frame buffer semaphore in a way that is safe in interrupt context. Called
 | |
|  * from ISR.
 | |
|  *
 | |
|  * Release the frame buffer semaphore in a way that is safe in interrupt context.
 | |
|  * Called from ISR.
 | |
|  */
 | |
| void OSWrappers::giveFrameBufferSemaphoreFromISR()
 | |
| {
 | |
| 	#if (TOUCHGFX_BAREMETAL != 0)
 | |
| 		fb_sem = 0;
 | |
| 	#endif  // TOUCHGFX_BAREMETAL
 | |
| 	#if (TOUCHGFX_FREERTOS != 0)
 | |
| 	    osSemaphoreRelease(frame_buffer_sem);
 | |
| 	#endif // TOUCHGFX_FREERTOS
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Signal that a VSYNC has occurred. Should make the vsync queue/mutex available.
 | |
|  *
 | |
|  * Note This function is called from an ISR, and should (depending on OS) trigger a
 | |
|  * scheduling.
 | |
|  */
 | |
| void OSWrappers::signalVSync()
 | |
| {
 | |
| 	#if (TOUCHGFX_BAREMETAL != 0)
 | |
| 	  vsync_sem = 1;
 | |
| 	#endif  // TOUCHGFX_BAREMETAL
 | |
| 	#if (TOUCHGFX_FREERTOS != 0)
 | |
| 	    osMessageQueuePut(vsync_queue, &dummy, 0, 0);
 | |
| 	#endif // TOUCHGFX_FREERTOS
 | |
| }
 | |
| 
 | |
| /*
 | |
|   * Signal that the rendering of the frame has completed. Used by
 | |
|   * some systems to avoid using any previous vsync.
 | |
|   */
 | |
| void OSWrappers::signalRenderingDone()
 | |
| {
 | |
| 	#if (TOUCHGFX_BAREMETAL != 0)
 | |
| 		vsync_sem = 0;
 | |
| 	#endif  // TOUCHGFX_BAREMETAL
 | |
| 	#if (TOUCHGFX_FREERTOS != 0)
 | |
| 		// Empty implementation for CMSIS V2
 | |
| 	#endif // TOUCHGFX_FREERTOS
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * This function checks if a VSync occurred after last rendering.
 | |
|  * The function is used in systems that cannot wait in  waitForVSync
 | |
|  * (because they are also checking other event sources.
 | |
|  *
 | |
|  * @note signalRenderingDone is typically used together with this function.
 | |
|  *
 | |
|  * @return True if VSync occurred.
 | |
|  */
 | |
| bool OSWrappers::isVSyncAvailable()
 | |
| {
 | |
| 	#if (TOUCHGFX_BAREMETAL != 0)
 | |
| 	  return vsync_sem;
 | |
| 	#endif  // TOUCHGFX_BAREMETAL
 | |
| 	#if (TOUCHGFX_FREERTOS != 0)
 | |
| 	  return true;
 | |
| 	#endif // TOUCHGFX_FREERTOS
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * This function check if a VSYNC has occured.
 | |
|  * If VSYNC has occured, signal TouchGFX to start a rendering
 | |
|  */
 | |
| void OSWrappers::waitForVSync()
 | |
| {
 | |
| 	#if (TOUCHGFX_BAREMETAL != 0)
 | |
| 	  if(vsync_sem)
 | |
| 	  {
 | |
| 		vsync_sem = 0;
 | |
| 		HAL::getInstance()->backPorchExited();
 | |
| 	  }
 | |
| 	#endif  // TOUCHGFX_BAREMETAL
 | |
| 
 | |
| 	#if (TOUCHGFX_FREERTOS != 0)
 | |
| 	  uint32_t dummyGet;
 | |
| 	  // First make sure the queue is empty, by trying to remove an element with 0 timeout.
 | |
| 	  osMessageQueueGet(vsync_queue, &dummyGet, 0, 0);
 | |
| 
 | |
| 	  // Then, wait for next VSYNC to occur.
 | |
| 	  osMessageQueueGet(vsync_queue, &dummyGet, 0, osWaitForever);
 | |
| 	#endif // TOUCHGFX_FREERTOS
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * A function that causes executing task to sleep for a number of milliseconds.
 | |
|  *
 | |
|  * A function that causes executing task to sleep for a number of milliseconds.
 | |
|  * This function is OPTIONAL. It is only used by the TouchGFX in the case of
 | |
|  * a specific frame refresh strategy (REFRESH_STRATEGY_OPTIM_SINGLE_BUFFER_TFT_CTRL).
 | |
|  * Due to backwards compatibility, in order for this function to be useable by the HAL
 | |
|  * the function must be explicitly registered:
 | |
|  * hal.registerTaskDelayFunction(&OSWrappers::taskDelay)
 | |
|  *
 | |
|  * see HAL::setFrameRefreshStrategy(FrameRefreshStrategy s)
 | |
|  * see HAL::registerTaskDelayFunction(void (*delayF)(uint16_t))
 | |
|  */
 | |
| void OSWrappers::taskDelay(uint16_t ms)
 | |
| {
 | |
| 	#if (TOUCHGFX_BAREMETAL != 0)
 | |
| 		HAL_Delay(ms);
 | |
| 	#endif  // TOUCHGFX_BAREMETAL
 | |
| 
 | |
| 	#if (TOUCHGFX_FREERTOS != 0)
 | |
| 		osDelay(static_cast<uint32_t>(ms));
 | |
| 	#endif // TOUCHGFX_FREERTOS
 | |
| 
 | |
| }
 | |
| 
 | |
| /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
 |