
/*********************************************************************
*
*       #include Section
*
**********************************************************************
*/
#include <stdlib.h>
#include <stdio.h>
#include "main.h"
#include "cmsis_os.h"
#include "USBH.h"
#include "USBH_HW_STM32H7xxHS.h"
#include "cy_utils.h"

/*********************************************************************
*
*       Defines, configurable
*
**********************************************************************
*/

/* The size of memory (in bytes) dedicated to the stack. The size
 * of memory is selected to satisfy RAM usage of Driver and a
 * few connected devices. Update this value with the optimal
 * memory pool size (strongly recommended) for the application.
 * For details on selecting the optimal memory pool size, refer
 * to the emUSB-Host User Guide & Reference Manual Memory pools
 * chapter.
 **/
#define USBH_ALLOC_SIZE             (0x8000U)
#define USB_MAIN_TASK_MEMORY_REQ    (500U)
#define USB_ISR_TASK_MEMORY_REQ     (500U)

/* Memory area used by the stack */
static uint32_t memory_pool[USBH_ALLOC_SIZE / 4U];

// Define categories of debug log messages that should be printed.
// For possible categories, see USBH_MCAT_... definitions in USBH.h
//
static const U8 _LogCategories[] = {
  USBH_MCAT_INIT,
  USBH_MCAT_APPLICATION
};

/*********************************************************************
*
*       Static code
*
**********************************************************************
*/

static void _CleanDCache(void *p, unsigned long NumBytes) {
	SCB_CleanDCache_by_Addr((uint32_t *)p, NumBytes);
}

static void _InvalidateDCache(void *p, unsigned long NumBytes) {
	SCB_InvalidateDCache_by_Addr((uint32_t *)p, NumBytes);
}

static const SEGGER_CACHE_CONFIG _CacheConfig = {
	32,                            // CacheLineSize of CPU
	NULL,                          // pfDMB
	_CleanDCache,                  // pfClean
	_InvalidateDCache              // pfInvalidate
};

// This function handles USB On The Go HS global interrupt.
void OTG_HS_IRQHandler(void)
{
	USBH_ServiceISR(0);
}

static int _CheckForValidDMAAddress(const void *p)
{
	//
	// DTCM RAM can't be used by DMA
	//
	if ((U32)p < 0x24000000 && (U32)p >= 0x20000000) {
	return 1;
	}
	return 0;
}


/***********************************************************************************
 *  Function Name: usbh_task
 ***********************************************************************************
 * Summary:
 * The function is responsibe for calling USBH_Task(). During the execution of the
 * program, exit from the infinite loop is not expected.
 *
 * Parameters:
 * arg - is not used in this function, is required by FreeRTOS
 *
 * Return:
 * void
 *
 **********************************************************************************/
static void usbh_task(void* arg)
{
	(void)arg;

	while(1)
	{
		USBH_Task();
	}
}

/***********************************************************************************
 *   Function Name: usbh_isr_task
 ***********************************************************************************
 * Summary:
 * The function is responsibe for calling USBH_ISRTask(). During the execution of
 * the program, exit from the infinite loop is not expected.
 *
 * Parameters:
 * arg - is not used in this function, is required by FreeRTOS
 *
 * Return:
 * void
 *
 **********************************************************************************/
static void usbh_isr_task(void* arg)
{
	(void)arg;

	while(1)
	{
		USBH_ISRTask();
	}
}

int SEGGER_vsnprintf (char* pBuffer, int BufferSize, const char* sFormat, va_list ParamList)
{
	return vsnprintf (pBuffer, BufferSize, sFormat, ParamList);
}

void USBH_X_Config(void)
{
	// Assigning memory should be the first thing
	//
	USBH_AssignMemory((void *) &memory_pool, USBH_ALLOC_SIZE);
	USBH_ConfigSupportExternalHubs(1);
	USBH_ConfigPowerOnGoodTime(300);  // Default values: 300 ms wait time before the hosts starts communicating with the device.

	// Define log and warn filter
	// Note: The terminal I/O emulation affects the timing
	// of your communication, since the debugger stops the target
	// for every terminal I/O unless you use RTT!
	//
	USBH_ConfigMsgFilter(USBH_WARN_FILTER_SET_ALL, 0, NULL);    // Output all warnings.
	USBH_ConfigMsgFilter(USBH_LOG_FILTER_SET, sizeof(_LogCategories), _LogCategories);

	// Initialize STM32H7_HS USB
	USBH_SetCacheConfig(&_CacheConfig, sizeof(_CacheConfig));  // Set cache configuration for USBH stack.
	USBH_STM32H7_HS_AddEx((void*)USB_OTG_HS, 0);
	USBH_STM32H7_HS_SetCheckAddress(_CheckForValidDMAAddress);

	// Enable USB_OTG_HS interrupt
	HAL_NVIC_SetPriority(OTG_HS_IRQn, 5, 0);
	HAL_NVIC_EnableIRQ(OTG_HS_IRQn);
}

void USBH_Start(void)
{
    BaseType_t rtos_task_status;

	// Initialize USBH stack
	USBH_Init();

	// Create two tasks which are mandatory for USBH operation
	// - usbh_task
	rtos_task_status = xTaskCreate(usbh_task, "usbh_task",
								   USB_MAIN_TASK_MEMORY_REQ, NULL,
								   configMAX_PRIORITIES - 2, NULL);
	if (rtos_task_status != pdPASS)
	{
		CY_ASSERT(0);
	}

	// - usbh_isr_task
	rtos_task_status = xTaskCreate(usbh_isr_task, "usbh_isr_task",
								   USB_ISR_TASK_MEMORY_REQ, NULL,
								   configMAX_PRIORITIES - 1, NULL);
	if (rtos_task_status != pdPASS)
	{
		CY_ASSERT(0);
	}
}

/********************************* EOF ******************************/
