/*==================================================================================================
* Project : RTD AUTOSAR 4.4
* Platform : CORTEXM
* Peripheral : S32K3
* Dependencies : none
*
* Autosar Version : 4.4.0
* Autosar Revision : ASR_REL_4_4_REV_0000
* Autosar Conf.Variant :
* SW Version : 2.0.0
* Build Version : S32K3_RTD_2_0_0_D2203_ASR_REL_4_4_REV_0000_20220331
*
* (c) Copyright 2020 - 2022 NXP Semiconductors
* All Rights Reserved.
*
* NXP Confidential. This software is owned or controlled by NXP and may only be
* used strictly in accordance with the applicable license terms. By expressly
* accepting such terms or by downloading, installing, activating and/or otherwise
* using the software, you are agreeing that you have read, and that you agree to
* comply with and are bound by, such license terms. If you do not agree to be
* bound by the applicable license terms, then you may not retain, install,
* activate or otherwise use the software.
==================================================================================================*/
/**
*   @file       bsp.c
*
*   @addtogroup bsp Bsp_Module
*
*   @{
*/

#ifdef __cplusplus
extern "C"{
#endif

/*==================================================================================================
*                                        INCLUDE FILES
* 1) system and project includes
* 2) needed interfaces from external units
* 3) internal and external interfaces from this unit
==================================================================================================*/
#include "bsp.h"
#include "Qspi_Ip.h"

/*==================================================================================================
*                         LOCAL TYPEDEFS (STRUCTURES, UNIONS, ENUMS)
==================================================================================================*/

/*=================================================================================================
*                                       LOCAL MACROS
=================================================================================================*/
/* CPU freq is 160MHz, so systick 160 count is 1usec. It's used for software time delay. */
#define SYSTICK_CNT_PER_USEC	160
/* CPU freq is 160MHz, so systick 160000 count is 1msec. It's used for software time delay. */
#define SYSTICK_CNT_PER_MSEC	160000

/*==================================================================================================
*                                      LOCAL CONSTANTS
==================================================================================================*/

/*==================================================================================================
*                                      LOCAL VARIABLES
==================================================================================================*/
uint32_t Qspi_Flash_TargetAddr = 0x00000000;
uint32_t Qspi_Flash_WriteTestData[16] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};
uint32_t Qspi_Flash_ReadTestData[16];
uint8_t Qspi_Flash_DeviceId[4];

volatile uint32_t Qspi_Erase_WaitLoopCnt = 0;
volatile uint32_t Qspi_Program_WaitLoopCnt = 0;

/*==================================================================================================
*                                      GLOBAL CONSTANTS
==================================================================================================*/

/*==================================================================================================
*                                      GLOBAL VARIABLES
==================================================================================================*/
uint32_t Task_Flag_1mS = 0;
uint32_t Task_Flag_10mS = 0;
uint32_t Task_Flag_100mS = 0;
uint32_t Task_Flag_1000mS = 0;
uint32_t Task_Flag_Cnt = 0;

/*==================================================================================================
*                                   LOCAL FUNCTION PROTOTYPES
==================================================================================================*/

/*==================================================================================================
*                                       External FUNCTIONS
==================================================================================================*/
extern void PIT_1_ISR(void);

/*==================================================================================================
*                                       LOCAL FUNCTIONS
==================================================================================================*/

/*==================================================================================================
*                                       Interrupts callback FUNCTIONS
==================================================================================================*/
/*================================================================================================*/
/**
 * @brief          PIT0 CH0 Notification function
 *
 * @details        Notification function that is invoked when PIT0 CH0 timeout occurs.
 *
 * @param[in]      channel, the channel number that triggers the interrupt.
 *
 * @return         none
 */
void Pit0Ch0_Notification(uint8 channel){
	(void)channel;
	/* toggle LED1 */
	//Siul2_Dio_Ip_TogglePins(LED2_PORT, 1<<LED2_PIN);
	Task_Flag_1mS = 1;
	if((Task_Flag_Cnt % 10) == 0)
		Task_Flag_10mS = 1;
	if((Task_Flag_Cnt % 100) == 0)
		Task_Flag_100mS = 1;
	if((Task_Flag_Cnt % 1000) == 0){
		Task_Flag_1000mS = 1;
		Task_Flag_Cnt = 0;
	}
	Task_Flag_Cnt++;
	return;
}

/*================================================================================================*/
/**
 * @brief          PIT0 CH0 Notification function
 *
 * @details        Notification function that is invoked when PIT0 CH0 timeout occurs.
 *
 * @param[in]      channel, the channel number that triggers the interrupt.
 *
 * @return         none
 */
void __attribute__((weak)) Pit0Ch2_Notification(uint8 channel){
	(void)channel;
	return;
}

/*================================================================================================*/
/**
 * @brief          PTF22 EMIOS1 CH6 ICU notification function for monitoring NCK2910 INTB signal
 * @details        PTF22 EMIOS1 CH6 ICU notification function for monitoring NCK2910 INTB signal
 * @param[in]      none
 * @return         none
 */
void __attribute__((weak)) NCK2910_Int_Notification(void){
	return;
}

/*================================================================================================*/
/**
 * @brief          PTC7 IRQ7 ICU notification function for monitoring NJJ29C2 IRQ signal
 * @details        PTC7 IRQ7 ICU notification function for monitoring NJJ29C2 IRQ signal
 * @param[in]      none
 * @return         none
 */
void __attribute__((weak)) NJJ29C2_IRQ_Notification(void){
	return;
}

/*==================================================================================================
*                                       GLOBAL FUNCTIONS
==================================================================================================*/
/*================================================================================================*/
/**
 * @brief          Minisecond time delay using CPU systick timer, which is a 24bit count-down timer
 * @details        Poll the systick timer to delay a period of time.
 * @param[in]      nMsec, count of mini-second to delay
 * @return         none.
 */
void OsIf_Delay_Ms(uint32_t nMsec){
	uint32 cnt1, cnt2, i;
	for(i=0; i<nMsec; i++){
		cnt1 = OsIf_GetCounter(OSIF_COUNTER_SYSTEM);
		cnt1 = (cnt1<<8);
		do {
			cnt2 = OsIf_GetCounter(OSIF_COUNTER_SYSTEM);
			cnt2 = (cnt2<<8);
		} while(cnt1 - cnt2 < (SYSTICK_CNT_PER_MSEC<<8));
	}
	return;
}

/*================================================================================================*/
/**
 * @brief          Microsecond time delay using CPU systick timer, which is a 24bit count-down timer
 * @details        Poll the systick timer to delay a period of time.
 * @param[in]      nUsec, count of micro-second to delay
 * @return         none.
 */
void OsIf_Delay_Us(uint32_t nUsec){
	uint32 cnt1, cnt2, i;
	for(i=0; i<nUsec; i++){
		cnt1 = OsIf_GetCounter(OSIF_COUNTER_SYSTEM);
		cnt1 = (cnt1<<8);
		do {
			cnt2 = OsIf_GetCounter(OSIF_COUNTER_SYSTEM);
			cnt2 = (cnt2<<8);
		} while(cnt1 - cnt2 < (SYSTICK_CNT_PER_USEC<<8));
	}
	return;
}

/*================================================================================================*/
/**
 * @brief          QSPI Flash test function
 * @details        Initialize QSPI instance, erase flash, read flash, read flash device ID.
 * @param[in]      none.
 * @return         E_OK or E_NOT_OK
 */
Std_ReturnType QSPI_Flash_InitTest(void){
	Qspi_Ip_StatusType Qspi_Status = STATUS_QSPI_IP_SUCCESS;
	Qspi_Erase_WaitLoopCnt = 0;
	Qspi_Program_WaitLoopCnt = 0;

	Qspi_Status |= Qspi_Ip_Init(QSPI_INSTANCE_0, &QspiConfigSet_BOARD_InitPeripherals_paFlashCfg[0], &QspiConfigSet_BOARD_InitPeripherals_paFlashConnectionCfg[0]);

	Qspi_Status |= Qspi_Ip_GetMemoryStatus(QSPI_INSTANCE_0);

	Qspi_Status |= Qspi_Ip_ReadId(QSPI_INSTANCE_0, Qspi_Flash_DeviceId);
	if(Qspi_Status != STATUS_QSPI_IP_SUCCESS)
		return Qspi_Status;

	/* Erase a flash sector with size 0x1000 (4KB) */
	Qspi_Status |= Qspi_Ip_EraseBlock(QSPI_INSTANCE_0, Qspi_Flash_TargetAddr, 0x1000);
	if(Qspi_Status != STATUS_QSPI_IP_SUCCESS)
		return Qspi_Status;
	/* Poll QSPI Flash status until it's not Busy. */
	do{
		Qspi_Status = Qspi_Ip_GetMemoryStatus(QSPI_INSTANCE_0);
		Qspi_Erase_WaitLoopCnt++;
	}while(Qspi_Status == STATUS_QSPI_IP_BUSY);

	/* Program an array into QSPI flash with size 64 Bytes. */
	Qspi_Status |= Qspi_Ip_Program(QSPI_INSTANCE_0, Qspi_Flash_TargetAddr, (uint8 *)(&Qspi_Flash_WriteTestData[0]), 64);
	if(Qspi_Status != STATUS_QSPI_IP_SUCCESS)
		return Qspi_Status;
	/* Poll QSPI Flash status until it's not Busy. */
	do{
		Qspi_Status = Qspi_Ip_GetMemoryStatus(QSPI_INSTANCE_0);
		Qspi_Program_WaitLoopCnt++;
	}while(Qspi_Status == STATUS_QSPI_IP_BUSY);

	Qspi_Status |= Qspi_Ip_Read(QSPI_INSTANCE_0, Qspi_Flash_TargetAddr, (uint8 *)(&Qspi_Flash_ReadTestData[0]), 64);

	for(uint32_t i=0; i<16; i++){
		if(Qspi_Flash_ReadTestData[i] != Qspi_Flash_WriteTestData[i]){
			Qspi_Status = STATUS_QSPI_IP_ERROR_PROGRAM_VERIFY;
			break;
		}
	}

	if(STATUS_QSPI_IP_SUCCESS == Qspi_Status){
		printf("QSPI Flash ProgramVerify test OK.\r\n");
	} else {
		printf("QSPI Flash ProgramVerify test fail.\r\n");
	}
	return (Std_ReturnType)Qspi_Status;
}

/**
 * @brief          board initialization
 *
 * @details        Initialization for MCU clocks, pins, peripherals and other devices on the board.
 *
 * @param[in]      none.
 *
 * @return         0 means OK£¬ otherwise not OK.
 */
uint32_t Bsp_Init(void){
	uint32_t retCode = 0;
	/* initialize OSIF so that OSIF timer delay can be used in RTD driver */
	OsIf_Init(NULL);

	/* Initialize Clock settings */
	retCode = Clock_Ip_Init(&Clock_Ip_aClockConfig[0]);
	if(CLOCK_IP_SUCCESS != retCode)
		return retCode;

	/* Configure all pads */
	retCode = Siul2_Port_Ip_Init(NUM_OF_CONFIGURED_PINS0, g_pin_mux_InitConfigArr0);
	if(retCode != E_OK)
		return retCode;

	/* GPIO pads configuration take effective after the following code */
	IP_DCM_GPR->DCMRWF1 |= DCM_GPR_DCMRWF1_STANDBY_IO_CONFIG_MASK;

	/* LPUART0 initialization */
	Console_SerialPort_Init();
	printf("**************************************** \r\n");
	printf("************ Clock init done *********** \r\n");
	printf("Reset source DES=0x%08X, FES=0x%08X.\r\n", (unsigned int)(IP_MC_RGM->DES), (unsigned int)(IP_MC_RGM->FES));
	printf("Reset count FREC=%d.\r\n", (unsigned int)(IP_MC_RGM->FREC));
	IP_MC_RGM->DES = 0xFFFFFFFF;
	IP_MC_RGM->FES = 0xFFFFFFFF;
	if(IP_MC_RGM->FREC >= 7)
		IP_MC_RGM->FREC = 0x0F;

	/* Initialize PIT timer and start PIT timer */
	/* PIT0 instance initialization */
	Pit_Ip_Init(PIT_0_IP_INSTANCE_NUMBER, &PIT_0_InitConfig_PB);
	/* PIT0 channel0 initialization */
	Pit_Ip_InitChannel(PIT_0_IP_INSTANCE_NUMBER, &PIT_0_ChannelConfig_PB[0]);
	/* Start PIT0 channel0, PIT0 clocks from AIPS_SLOW_CLK 40MHz, so here the timeout 40000 means 1mS */
	Pit_Ip_StartChannel(PIT_0_IP_INSTANCE_NUMBER, 0, 40000);
	/* Enable PIT0 channel0 interrupt */
	Pit_Ip_EnableChannelInterrupt(PIT_0_IP_INSTANCE_NUMBER, 0);
	/* Install PIT0 ISR into the vector table. */
	//IntCtrl_Ip_InstallHandler(PIT0_IRQn, PIT_0_ISR, NULL_PTR);
	/* Enable PIT0 interrupt */
	//IntCtrl_Ip_EnableIrq(PIT0_IRQn);

	/* PIT1 instance initialization */
	Pit_Ip_Init(PIT_1_IP_INSTANCE_NUMBER, &PIT_1_InitConfig_PB);
	/* PIT1 channel0 initialization for lin timeout counting*/
	Pit_Ip_InitChannel(PIT_1_IP_INSTANCE_NUMBER, &PIT_1_ChannelConfig_PB[0]);
	/* PIT1 channel1 initialization for lin timeout counting*/
	Pit_Ip_InitChannel(PIT_1_IP_INSTANCE_NUMBER, &PIT_1_ChannelConfig_PB[1]);
	/* PIT1 channel2 initialization for lin timeout counting*/
	Pit_Ip_InitChannel(PIT_1_IP_INSTANCE_NUMBER, &PIT_1_ChannelConfig_PB[2]);
	/* PIT1 channel3 initialization for lin timeout counting*/
	Pit_Ip_InitChannel(PIT_1_IP_INSTANCE_NUMBER, &PIT_1_ChannelConfig_PB[3]);
	/* Enable PIT1 channel0 interrupt */
	Pit_Ip_EnableChannelInterrupt(PIT_1_IP_INSTANCE_NUMBER, 0);
	/* Enable PIT1 channel0 interrupt */
	Pit_Ip_EnableChannelInterrupt(PIT_1_IP_INSTANCE_NUMBER, 1);
	/* Enable PIT1 channel0 interrupt */
	Pit_Ip_EnableChannelInterrupt(PIT_1_IP_INSTANCE_NUMBER, 2);
	/* Enable PIT1 channel0 interrupt */
	Pit_Ip_EnableChannelInterrupt(PIT_1_IP_INSTANCE_NUMBER, 3);

	/* SPI instance initialization */
	Lpspi_Ip_Init(&Lpspi_Ip_PhyUnitConfig_SpiPhyUnit_0_Instance_0_BOARD_InitPeripherals);
	Lpspi_Ip_Init(&Lpspi_Ip_PhyUnitConfig_SpiPhyUnit_1_Instance_1_BOARD_InitPeripherals);
	Lpspi_Ip_Init(&Lpspi_Ip_PhyUnitConfig_SpiPhyUnit_2_Instance_2_BOARD_InitPeripherals);
	Lpspi_Ip_Init(&Lpspi_Ip_PhyUnitConfig_SpiPhyUnit_3_Instance_3_BOARD_InitPeripherals);
	Lpspi_Ip_Init(&Lpspi_Ip_PhyUnitConfig_SpiPhyUnit_4_Instance_4_BOARD_InitPeripherals);
	Lpspi_Ip_Init(&Lpspi_Ip_PhyUnitConfig_SpiPhyUnit_5_Instance_5_BOARD_InitPeripherals);

	retCode |= IntCtrl_Ip_Init(&IntCtrlConfig_0);
	retCode |= IntCtrl_Ip_ConfigIrqRouting(&intRouteConfig);

	/* Install PIT1 ISR into the vector table. */
	IntCtrl_Ip_InstallHandler(PIT1_IRQn, PIT_1_ISR, NULL_PTR);
	/* Enable PIT1 interrupt */
	IntCtrl_Ip_EnableIrq(PIT1_IRQn);

	return retCode;
}


#ifdef __cplusplus
}
#endif

/** @} */
