/*================================================================================================== * Project : RTD AUTOSAR 4.4 * Platform : CORTEXM * Peripheral : Emios Flexio * Dependencies : none * * Autosar Version : 4.4.0 * Autosar Revision : ASR_REL_4_4_REV_0000 * Autosar Conf.Variant : * SW Version : 0.9.0 * Build Version : S32K3_RTD_0_9_0__ASR_REL_4_4_REV_0000_20210326 * * (c) Copyright 2020 - 2021 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 Emios_Pwm_Ip.c * * @addtogroup emios_pwm_ip Emios Pwm IPL * @{ */ #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 "Emios_Pwm_Ip.h" #include "Emios_Pwm_Ip_HwAccess.h" #include "Emios_Mcl_Ip.h" #include "SchM_Pwm.h" /*================================================================================================== * SOURCE FILE VERSION INFORMATION ==================================================================================================*/ #define EMIOS_PWM_IP_VENDOR_ID_C 43 #define EMIOS_PWM_IP_AR_RELEASE_MAJOR_VERSION_C 4 #define EMIOS_PWM_IP_AR_RELEASE_MINOR_VERSION_C 4 #define EMIOS_PWM_IP_AR_RELEASE_REVISION_VERSION_C 0 #define EMIOS_PWM_IP_SW_MAJOR_VERSION_C 0 #define EMIOS_PWM_IP_SW_MINOR_VERSION_C 9 #define EMIOS_PWM_IP_SW_PATCH_VERSION_C 0 /*================================================================================================== * FILE VERSION CHECKS ==================================================================================================*/ #ifndef DISABLE_MCAL_INTERMODULE_ASR_CHECK /* Check if header file and Emios_Mcl_Ip.h are of the same AUTOSAR version */ #if ((EMIOS_PWM_IP_AR_RELEASE_MAJOR_VERSION_C != EMIOS_MCL_IP_AR_RELEASE_MAJOR_VERSION_H) || \ (EMIOS_PWM_IP_AR_RELEASE_MINOR_VERSION_C != EMIOS_MCL_IP_AR_RELEASE_MINOR_VERSION_H)) #error "AUTOSAR Version Numbers of Emios_Pwm_Ip.c and Emios_Mcl_Ip.h are different" #endif /* Check if this source file and SchM_Pwm.h file are of the same Autosar version */ #if ((EMIOS_PWM_IP_AR_RELEASE_MAJOR_VERSION_C != SCHM_PWM_AR_RELEASE_MAJOR_VERSION) || \ (EMIOS_PWM_IP_AR_RELEASE_MINOR_VERSION_C != SCHM_PWM_AR_RELEASE_MINOR_VERSION)) #error "AutoSar Version Numbers of Emios_Pwm_Ip.c and SchM_Pwm.h are different" #endif #endif /* Check if source file and Emios_Pwm_Ip.h file are of the same vendor */ #if (EMIOS_PWM_IP_VENDOR_ID_C != EMIOS_PWM_IP_VENDOR_ID) #error "Vendor IDs of Emios_Pwm_Ip.c and Emios_Pwm_Ip.h are different." #endif /* Check if source file and Emios_Pwm_Ip.h file are of the same AUTOSAR version */ #if ((EMIOS_PWM_IP_AR_RELEASE_MAJOR_VERSION_C != EMIOS_PWM_IP_AR_RELEASE_MAJOR_VERSION) || \ (EMIOS_PWM_IP_AR_RELEASE_MINOR_VERSION_C != EMIOS_PWM_IP_AR_RELEASE_MINOR_VERSION) || \ (EMIOS_PWM_IP_AR_RELEASE_REVISION_VERSION_C != EMIOS_PWM_IP_AR_RELEASE_REVISION_VERSION)) #error "AUTOSAR version numbers of Emios_Pwm_Ip.c and Emios_Pwm_Ip.h are different." #endif /* Check if source file and Emios_Pwm_Ip.h file are of the same Software version */ #if ((EMIOS_PWM_IP_SW_MAJOR_VERSION_C != EMIOS_PWM_IP_SW_MAJOR_VERSION) || \ (EMIOS_PWM_IP_SW_MINOR_VERSION_C != EMIOS_PWM_IP_SW_MINOR_VERSION) || \ (EMIOS_PWM_IP_SW_PATCH_VERSION_C != EMIOS_PWM_IP_SW_PATCH_VERSION)) #error "Software version numbers of Emios_Pwm_Ip.c and Emios_Pwm_Ip.h are different." #endif /* Check if source file and Emios_Pwm_Ip_HwAccess.h file are of the same vendor */ #if (EMIOS_PWM_IP_VENDOR_ID_C != EMIOS_PWM_IP_HWACCESS_VENDOR_ID) #error "Vendor IDs of Emios_Pwm_Ip.c and Emios_Pwm_Ip_HwAccess.h are different." #endif /* Check if source file and Emios_Pwm_Ip_HwAccess.h file are of the same AUTOSAR version */ #if ((EMIOS_PWM_IP_AR_RELEASE_MAJOR_VERSION_C != EMIOS_PWM_IP_HWACCESS_AR_RELEASE_MAJOR_VERSION) || \ (EMIOS_PWM_IP_AR_RELEASE_MINOR_VERSION_C != EMIOS_PWM_IP_HWACCESS_AR_RELEASE_MINOR_VERSION) || \ (EMIOS_PWM_IP_AR_RELEASE_REVISION_VERSION_C != EMIOS_PWM_IP_HWACCESS_AR_RELEASE_REVISION_VERSION)) #error "AUTOSAR version numbers of Emios_Pwm_Ip.c and Emios_Pwm_Ip_HwAccess.h are different." #endif /* Check if source file and Emios_Pwm_Ip_HwAccess.h file are of the same Software version */ #if ((EMIOS_PWM_IP_SW_MAJOR_VERSION_C != EMIOS_PWM_IP_HWACCESS_SW_MAJOR_VERSION) || \ (EMIOS_PWM_IP_SW_MINOR_VERSION_C != EMIOS_PWM_IP_HWACCESS_SW_MINOR_VERSION) || \ (EMIOS_PWM_IP_SW_PATCH_VERSION_C != EMIOS_PWM_IP_HWACCESS_SW_PATCH_VERSION)) #error "Software version numbers of Emios_Pwm_Ip.c and Emios_Pwm_Ip_HwAccess.h are different." #endif /*================================================================================================== * LOCAL TYPEDEFS (STRUCTURES, UNIONS, ENUMS) ==================================================================================================*/ /*================================================================================================== * LOCAL MACROS ==================================================================================================*/ /*================================================================================================== * LOCAL CONSTANTS ==================================================================================================*/ /*================================================================================================== * LOCAL VARIABLES ==================================================================================================*/ /*================================================================================================== * GLOBAL CONSTANTS ==================================================================================================*/ /*================================================================================================== * GLOBAL VARIABLES ==================================================================================================*/ #define PWM_START_SEC_CONST_UNSPECIFIED #include "Pwm_MemMap.h" /** @brief Array with base addresses for Emios instances available on platform */ Emios_Pwm_Ip_HwAddrType *const Emios_Pwm_Ip_aBasePtr[EMIOS_PWM_INSTANCE_COUNT] = eMIOS_BASE_PTRS; #define PWM_STOP_SEC_CONST_UNSPECIFIED #include "Pwm_MemMap.h" #define PWM_START_SEC_VAR_INIT_UNSPECIFIED #include "Pwm_MemMap.h" /** @brief Array with notification handlers for all configurable channels */ Emios_Pwm_Ip_NotificationType const *Emios_Pwm_Ip_aNotificationPtr[EMIOS_PWM_INSTANCE_COUNT][EMIOS_PWM_CHANNEL_COUNT] = EMIOS_PWM_NOTIFICATION_HANDLERS; #define PWM_STOP_SEC_VAR_INIT_UNSPECIFIED #include "Pwm_MemMap.h" #if (EMIOS_PWM_IP_DEV_ERROR_DETECT == STD_ON) #define PWM_START_SEC_VAR_INIT_32 #include "Pwm_MemMap.h" /* Array with available pwm modes for each Emios channel */ static uint32 Emios_Pwm_Ip_ChannelModes[EMIOS_PWM_INSTANCE_COUNT][EMIOS_PWM_MODES] = EMIOS_PWM_CHANNEL_MODES; #define PWM_STOP_SEC_VAR_INIT_32 #include "Pwm_MemMap.h" #endif #define PWM_START_SEC_VAR_INIT_16 #include "Pwm_MemMap.h" /** @brief Array with period for OPWFMB channels */ uint16 Emios_Pwm_Ip_aPeriod[EMIOS_PWM_INSTANCE_COUNT][EMIOS_PWM_CHANNEL_COUNT] = EMIOS_PWM_INIT_VALUE_UINT16; uint16 Emios_Pwm_Ip_aRegA[EMIOS_PWM_INSTANCE_COUNT][EMIOS_PWM_CHANNEL_COUNT] = EMIOS_PWM_INIT_VALUE_UINT16; uint16 Emios_Pwm_Ip_aDaocDuty[EMIOS_PWM_INSTANCE_COUNT][EMIOS_PWM_CHANNEL_COUNT] = EMIOS_PWM_INIT_VALUE_UINT16; #define PWM_STOP_SEC_VAR_INIT_16 #include "Pwm_MemMap.h" #define PWM_START_SEC_VAR_INIT_8 #include "Pwm_MemMap.h" uint8 Emios_Pwm_Ip_aNotif[EMIOS_PWM_INSTANCE_COUNT][EMIOS_PWM_CHANNEL_COUNT] = EMIOS_PWM_INIT_VALUE_UINT8; uint8 Emios_Pwm_Ip_aCheckEnableNotif[EMIOS_PWM_INSTANCE_COUNT][EMIOS_PWM_CHANNEL_COUNT] = EMIOS_PWM_INIT_VALUE_UINT8; uint8 Emios_Pwm_Ip_aPolarity[EMIOS_PWM_INSTANCE_COUNT][EMIOS_PWM_CHANNEL_COUNT] = EMIOS_PWM_INIT_VALUE_UINT8; uint8 Emios_Pwm_Ip_aCheckState[EMIOS_PWM_INSTANCE_COUNT][EMIOS_PWM_CHANNEL_COUNT] = EMIOS_PWM_INIT_VALUE_UINT8; #define PWM_STOP_SEC_VAR_INIT_8 #include "Pwm_MemMap.h" /*================================================================================================== * LOCAL FUNCTION PROTOTYPES ==================================================================================================*/ /*================================================================================================== * LOCAL FUNCTIONS ==================================================================================================*/ #define PWM_START_SEC_CODE #include "Pwm_MemMap.h" #if (EMIOS_PWM_IP_DEV_ERROR_DETECT == STD_ON) /*---------------------Validation API------------------------*/ /*FUNCTION********************************************************************** * * Function Name : Emios_Pwm_Ip_ValidateMode * Description : Validate a eMIOS mode can run on the channel or not. *END**************************************************************************/ static inline boolean Emios_Pwm_Ip_ValidateMode(uint8 instance, uint8 channel, Emios_Pwm_Ip_PwmType mode) { return ((((Emios_Pwm_Ip_ChannelModes[instance][(uint8)mode] >> channel) & 0x01UL) == 1UL) ? TRUE : FALSE); } #endif /*FUNCTION********************************************************************** * * Function Name : Emios_Pwm_Ip_GetCounterBusPeriod * Description : Return the period for channel using an external counter bus. * Only used for channels in OPWMB/OPWMCB/OPWMT modes * *END**************************************************************************/ static uint16 Emios_Pwm_Ip_GetCounterBusPeriod(uint8 instance, uint8 channel, Emios_Pwm_Ip_CounterBusSourceType counterBus) { #if (EMIOS_PWM_IP_DEV_ERROR_DETECT == STD_ON) DevAssert(EMIOS_PWM_INSTANCE_COUNT > instance); DevAssert(EMIOS_PWM_CHANNEL_COUNT > channel); #endif const Emios_Pwm_Ip_HwAddrType *const base = Emios_Pwm_Ip_aBasePtr[instance]; uint16 chPeriod = 0U; if (EMIOS_PWM_BUS_A == counterBus) { chPeriod = Emios_Pwm_Ip_GetUCRegA(base, EMIOS_PWM_COUNTER_BUS_A); } else if (EMIOS_PWM_BUS_F == counterBus) { chPeriod = Emios_Pwm_Ip_GetUCRegA(base, EMIOS_PWM_COUNTER_BUS_F); } else if (EMIOS_PWM_BUS_BCDE == counterBus) { chPeriod = Emios_Pwm_Ip_GetUCRegA(base, (channel & (uint8)EMIOS_PWM_COUNTER_BUS_BCDE)); } else { /* Nothing to do. Internal Counter Cannot be selected for these modes. */ #if (EMIOS_PWM_IP_DEV_ERROR_DETECT == STD_ON) DevAssert(FALSE); #endif } return chPeriod; } /*FUNCTION********************************************************************** * * Function Name : Emios_Pwm_Ip_GetCounterBusMode * Description : Return the counter bus mode for channel using an external counter bus. * Only used for channels in OPWMB/OPWMCB/OPWMT modes * *END**************************************************************************/ static Emios_Pwm_Ip_MasterBusModeType Emios_Pwm_Ip_GetCounterBusMode(uint8 instance, uint8 channel, Emios_Pwm_Ip_CounterBusSourceType counterBus) { const Emios_Pwm_Ip_HwAddrType *const base = Emios_Pwm_Ip_aBasePtr[instance]; Emios_Pwm_Ip_MasterBusModeType counterBusMode = EMIOS_PWM_IP_MC_UP_COUNTER_START; switch (counterBus) { case EMIOS_PWM_BUS_A: counterBusMode = (Emios_Pwm_Ip_MasterBusModeType)Emios_Pwm_Ip_GetChannelPwmMode(base, EMIOS_PWM_COUNTER_BUS_A); break; case EMIOS_PWM_BUS_BCDE: counterBusMode = (Emios_Pwm_Ip_MasterBusModeType)Emios_Pwm_Ip_GetChannelPwmMode(base, (channel & (uint8)EMIOS_PWM_COUNTER_BUS_BCDE)); break; case EMIOS_PWM_BUS_F: counterBusMode = (Emios_Pwm_Ip_MasterBusModeType)Emios_Pwm_Ip_GetChannelPwmMode(base, EMIOS_PWM_COUNTER_BUS_F); break; default: /* internal counter bus */ counterBusMode = EMIOS_PWM_IP_NODEFINE_COUNTER; break; } return counterBusMode; } /*FUNCTION********************************************************************** * * Function Name : Emios_Pwm_Ip_InitPeriodDutyCycleMode * Description : Initial Output Pulse Width and Frequency Modulation Buffered (OPWFMB) Mode. * This mode provides waveforms with variable duty cycle and frequency. The internal channel counter * is automatically selected as the time base when this mode is selected. *END**************************************************************************/ static void Emios_Pwm_Ip_InitPeriodDutyCycleMode(uint8 instance, Emios_Pwm_Ip_ChannelConfigType const *userChCfg) { #if (EMIOS_PWM_IP_DEV_ERROR_DETECT == STD_ON) DevAssert(NULL_PTR != userChCfg); DevAssert(EMIOS_PWM_INSTANCE_COUNT > instance); DevAssert(EMIOS_PWM_CHANNEL_COUNT > userChCfg->channelId); /* Check Selected channel is set for OPWFMB */ DevAssert((userChCfg->mode == EMIOS_PWM_MODE_OPWFMB_FLAG) || (userChCfg->mode == EMIOS_PWM_MODE_OPWFMB_FLAG_BOTH)); /* Check that channel has internal counter for this mode */ DevAssert(TRUE == Emios_Pwm_Ip_ValidateMode(instance, userChCfg->channelId, EMIOS_PWM_HW_MODE_OPWFMB)); /* Validate opwfmb parametter */ DevAssert(EMIOS_PWM_MIN_CNT_VAL < userChCfg->periodCount); DevAssert(userChCfg->dutyCycle <= userChCfg->periodCount); #endif Emios_Pwm_Ip_HwAddrType *const base = Emios_Pwm_Ip_aBasePtr[instance]; /* Configure OPWFMB special parameters */ /* Configure Counter Bus used by this channel */ Emios_Pwm_Ip_SetCounterBus(base, userChCfg->channelId, userChCfg->timebase); /* Configure DutyCycle in reg A */ Emios_Pwm_Ip_SetUCRegA(base, userChCfg->channelId, userChCfg->dutyCycle); /* Configure Period in reg B */ Emios_Pwm_Ip_SetUCRegB(base, userChCfg->channelId, userChCfg->periodCount); /* Transition from GPIO mode to OPWFMB mode */ Emios_Pwm_Ip_SetPwmMode(base, userChCfg->channelId, userChCfg->mode); /* Configure output pin polarity */ Emios_Pwm_Ip_SetEdgePolarity(base, userChCfg->channelId,(userChCfg->outputPolarity == EMIOS_PWM_ACTIVE_HIGH) ? EMIOS_PWM_ACTIVE_LOW : EMIOS_PWM_ACTIVE_HIGH ); Emios_Pwm_Ip_aPeriod[instance][userChCfg->channelId] = userChCfg->periodCount; if (userChCfg->periodCount == userChCfg->dutyCycle) { /* 100% dutyCycle is desired. */ Emios_Pwm_Ip_aNotif[instance][userChCfg->channelId] = (uint8)1U; } else if(0U == userChCfg->dutyCycle) { /* 0% dutyCycle is desired. */ Emios_Pwm_Ip_aNotif[instance][userChCfg->channelId] = (uint8)1U; } else { Emios_Pwm_Ip_aNotif[instance][userChCfg->channelId] = (uint8)0U; } } /*FUNCTION********************************************************************** * * Function Name : Emios_Pwm_Ip_SetDutyCycleOpwfmb * Description : Set new duty cycle for the channel in OPWFMB mode * This function will check the specific duty cycle and set new duty cycle for * this channel * *END**************************************************************************/ static Emios_Pwm_Ip_StatusType Emios_Pwm_Ip_SetDutyCycleOpwfmb(uint8 instance, uint8 channel, uint16 newDutyCycle) { #if (EMIOS_PWM_IP_DEV_ERROR_DETECT == STD_ON) DevAssert(EMIOS_PWM_INSTANCE_COUNT > instance); DevAssert(EMIOS_PWM_CHANNEL_COUNT > channel); #endif Emios_Pwm_Ip_HwAddrType *const base = Emios_Pwm_Ip_aBasePtr[instance]; Emios_Pwm_Ip_StatusType ret = EMIOS_PWM_STATUS_SUCCESS; /* OPWFMB mode */ if ((newDutyCycle > Emios_Pwm_Ip_aPeriod[instance][channel]) && ((uint16)0U != Emios_Pwm_Ip_aPeriod[instance][channel])) { /* Duty cycle value should not be greater than the channel Period. */ ret = EMIOS_PWM_STATUS_ERROR; } else if ((uint16)0U == Emios_Pwm_Ip_aPeriod[instance][channel]) { /* Disable and clear interrupt flag */ Emios_Pwm_Ip_SetInterruptRequest(base, channel, FALSE); Emios_Pwm_Ip_ClearFlagEvent(base, channel); /* If new period is 0, set duty cycle to 0 */ Emios_Pwm_Ip_SetUCRegA(base, channel, (uint16)0U); Emios_Pwm_Ip_aNotif[instance][channel] = (uint8)1U; } else { if(newDutyCycle == 0U) { /* Disable and clear interrupt flag */ Emios_Pwm_Ip_SetInterruptRequest(base, channel, FALSE); Emios_Pwm_Ip_ClearFlagEvent(base, channel); Emios_Pwm_Ip_aNotif[instance][channel] = (uint8)1U; } else if (newDutyCycle == Emios_Pwm_Ip_aPeriod[instance][channel]) { /* Disable and clear interrupt flag */ Emios_Pwm_Ip_SetInterruptRequest(base, channel, FALSE); Emios_Pwm_Ip_ClearFlagEvent(base, channel); Emios_Pwm_Ip_aNotif[instance][channel] = (uint8)1U; } else { Emios_Pwm_Ip_aNotif[instance][channel] = (uint8)0U; Emios_Pwm_Ip_SetInterruptRequest(base, channel, (Emios_Pwm_Ip_aCheckEnableNotif[instance][channel] == 0U)? FALSE : TRUE); } Emios_Pwm_Ip_SetUCRegA(base, channel, newDutyCycle); } return ret; } /*FUNCTION********************************************************************** * * Function Name : Emios_Pwm_Ip_InitDeadTimeMode * Description : Initial Center Aligned Output Pulse Width Modulation with Dead Time Insertion Buffered (OPWMCB) Mode. * This operation mode generates a center aligned PWM with dead time insertion to the leading or trailing edge. * Allow smooth output signal generation when changing duty cycle and deadtime values. * * The time base selected for a channel configured to OPWMCB mode should be a channel configured to MCB Up/Down mode. * It is recommended to start the MCB channel time base after the OPWMCB mode is entered * in order to avoid missing A matches at the very first duty cycle. * * The internal counter runs in the internal prescaler ratio, while the selected time base * may be running in a different prescaler ratio. * *END**************************************************************************/ static void Emios_Pwm_Ip_InitDeadTimeMode(uint8 instance, Emios_Pwm_Ip_ChannelConfigType const *userChCfg) { #if (EMIOS_PWM_IP_DEV_ERROR_DETECT == STD_ON) DevAssert(NULL_PTR != userChCfg); DevAssert(EMIOS_PWM_INSTANCE_COUNT > instance); DevAssert(EMIOS_PWM_CHANNEL_COUNT > userChCfg->channelId); /* Check Selected channel is set for OPWMCB */ DevAssert((userChCfg->mode == EMIOS_PWM_MODE_OPWMCB_TRAIL_EDGE_FLAG) || (userChCfg->mode == EMIOS_PWM_MODE_OPWMCB_TRAIL_EDGE_FLAG_BOTH) || (userChCfg->mode == EMIOS_PWM_MODE_OPWMCB_LEAD_EDGE_FLAG) || (userChCfg->mode == EMIOS_PWM_MODE_OPWMCB_LEAD_EDGE_FLAG_BOTH)); /* Check selected channel supports OPWMCB mode */ DevAssert(TRUE == Emios_Pwm_Ip_ValidateMode(instance, userChCfg->channelId, EMIOS_PWM_HW_MODE_OPWMCB)); /* Check selected counter bus is configured in MCB Up-Down Mode */ DevAssert(EMIOS_PWM_IP_MCB_UP_DOWN_COUNTER == Emios_Pwm_Ip_GetCounterBusMode(instance, userChCfg->channelId, userChCfg->timebase)); /* Validate OPWMCB parametter */ DevAssert(((2U * Emios_Pwm_Ip_GetCounterBusPeriod(instance, userChCfg->channelId, userChCfg->timebase)) - 2U) >= userChCfg->dutyCycle); #endif Emios_Pwm_Ip_HwAddrType *const base = Emios_Pwm_Ip_aBasePtr[instance]; uint16 dutyCycle = 0U; if (userChCfg->periodCount == userChCfg->dutyCycle) { /* 100% dutyCycle is desired. */ dutyCycle = 1U; Emios_Pwm_Ip_aNotif[instance][userChCfg->channelId] = (uint8)1U; } else if((0U == userChCfg->dutyCycle) || (1U == userChCfg->dutyCycle)) { /* 0% dutyCycle is desired. */ dutyCycle = Emios_Pwm_Ip_GetCounterBusPeriod(instance, userChCfg->channelId, userChCfg->timebase) + (uint8)1U; Emios_Pwm_Ip_aNotif[instance][userChCfg->channelId] = (uint8)1U; } else { dutyCycle = (userChCfg->dutyCycle) >> (uint8)1U; dutyCycle = Emios_Pwm_Ip_GetCounterBusPeriod(instance, userChCfg->channelId, userChCfg->timebase) - dutyCycle; Emios_Pwm_Ip_aNotif[instance][userChCfg->channelId] = (uint8)0U; } /* Configure OPWMCB special parameters */ /* Configure Counter Bus used by this channel */ Emios_Pwm_Ip_SetCounterBus(base, userChCfg->channelId, userChCfg->timebase); /* Configure DutyCycle in reg A */ Emios_Pwm_Ip_SetUCRegA(base, userChCfg->channelId, dutyCycle); /* Configure DeadTime in reg B */ Emios_Pwm_Ip_SetUCRegB(base, userChCfg->channelId, userChCfg->deadTime); /* To avoid spike pulse If duty cycle = 100%, when enter mode, EDPOL bit get complement of polarity after that, EDPOL bit is restored valid value */ if (userChCfg->periodCount == userChCfg->dutyCycle) { Emios_Pwm_Ip_SetEdgePolarity(base, userChCfg->channelId,(userChCfg->outputPolarity == EMIOS_PWM_ACTIVE_HIGH) ? EMIOS_PWM_ACTIVE_LOW : EMIOS_PWM_ACTIVE_HIGH ); } else { Emios_Pwm_Ip_SetEdgePolarity(base, userChCfg->channelId, userChCfg->outputPolarity); } /* Transition from GPIO mode to OPWMCB mode */ Emios_Pwm_Ip_SetPwmMode(base, userChCfg->channelId, userChCfg->mode); /* Configure output pin polarity */ Emios_Pwm_Ip_SetEdgePolarity(base, userChCfg->channelId, userChCfg->outputPolarity); } /*FUNCTION********************************************************************** * * Function Name : Emios_Pwm_Ip_SetDutyCycleOpwmcb * Description : Set new duty cycle for the channel in OPWMCB mode * This function will check the specific duty cycle and set new duty cycle for * this channel * *END**************************************************************************/ static Emios_Pwm_Ip_StatusType Emios_Pwm_Ip_SetDutyCycleOpwmcb(uint8 instance, uint8 channel, uint16 newDutyCycle) { #if (EMIOS_PWM_IP_DEV_ERROR_DETECT == STD_ON) DevAssert(EMIOS_PWM_INSTANCE_COUNT > instance); DevAssert(EMIOS_PWM_CHANNEL_COUNT > channel); #endif Emios_Pwm_Ip_HwAddrType *const base = Emios_Pwm_Ip_aBasePtr[instance]; Emios_Pwm_Ip_StatusType ret = EMIOS_PWM_STATUS_SUCCESS; Emios_Pwm_Ip_PwmModeType chMode = Emios_Pwm_Ip_GetPwmMode(base, channel); uint16 chPeriod = Emios_Pwm_Ip_GetCounterBusPeriod(instance, channel, Emios_Pwm_Ip_GetCounterBus(base, channel)); /* OPWMCB mode */ if(newDutyCycle > ((chPeriod * 2U) - 2U)) { /* Duty cycle value should not be greater than the channel Period. */ ret = EMIOS_PWM_STATUS_ERROR; } else if(0U == newDutyCycle) { /* Disable and clear interrupt flag */ Emios_Pwm_Ip_SetInterruptRequest(base, channel, FALSE); Emios_Pwm_Ip_ClearFlagEvent(base, channel); Emios_Pwm_Ip_SetUCRegA(base, channel, chPeriod + 1U); Emios_Pwm_Ip_aNotif[instance][channel] = (uint8)1U; /* This statement is required to avoid limitation of 0% duty cycle (if call 100% to 0%) */ if(1U == Emios_Pwm_Ip_GetUCRegA(base, channel)) { if((chMode == EMIOS_PWM_MODE_OPWMCB_TRAIL_EDGE_FLAG) || (chMode == EMIOS_PWM_MODE_OPWMCB_TRAIL_EDGE_FLAG_BOTH)) { Emios_Pwm_Ip_SetForceMatchB(base, channel, TRUE); } else { Emios_Pwm_Ip_SetForceMatchA(base, channel, TRUE); } } } else if(newDutyCycle == ((chPeriod * 2U) - 2U)) { /* Disable and clear interrupt flag */ Emios_Pwm_Ip_SetInterruptRequest(base, channel, FALSE); Emios_Pwm_Ip_ClearFlagEvent(base, channel); Emios_Pwm_Ip_SetUCRegA(base, channel, 1U); Emios_Pwm_Ip_aNotif[instance][channel] = (uint8)1U; } else { Emios_Pwm_Ip_SetUCRegA(base, channel, (uint16)(chPeriod - (newDutyCycle >> 1U))); Emios_Pwm_Ip_aNotif[instance][channel] = (uint8)0U; Emios_Pwm_Ip_SetInterruptRequest(base, channel, (Emios_Pwm_Ip_aCheckEnableNotif[instance][channel] == 0U)? FALSE : TRUE); } return ret; } /*FUNCTION********************************************************************** * * Function Name : Emios_Pwm_Ip_InitEdgePlacementMode * Description : Initial Output Pulse Width Modulation Buffered (OPWMB) Mode. * OPWMB mode is used to generate pulses with programmable leading and trailing edge placement. * An external counter driven in MCB Up mode must be selected from one of the counter buses. * userChCfg defines the first edge and the second edge. The output signal polarity is defined * by outputPolarity in userChCfg. * *END**************************************************************************/ static void Emios_Pwm_Ip_InitEdgePlacementMode(uint8 instance, Emios_Pwm_Ip_ChannelConfigType const *userChCfg) { #if (EMIOS_PWM_IP_DEV_ERROR_DETECT == STD_ON) DevAssert(NULL_PTR != userChCfg); DevAssert(EMIOS_PWM_INSTANCE_COUNT > instance); DevAssert(EMIOS_PWM_CHANNEL_COUNT > userChCfg->channelId); /* Check Selected channel is set for OPWMB */ DevAssert((userChCfg->mode == EMIOS_PWM_MODE_OPWMB_FLAG) || (userChCfg->mode == EMIOS_PWM_MODE_OPWMB_FLAG_BOTH)); /* Check selected channel supports OPWMB mode */ DevAssert(TRUE == Emios_Pwm_Ip_ValidateMode(instance, userChCfg->channelId, EMIOS_PWM_HW_MODE_OPWMB)); /* Check selected counter bus is configured in MCB Up-Down Mode */ DevAssert(EMIOS_PWM_IP_MCB_UP_COUNTER == Emios_Pwm_Ip_GetCounterBusMode(instance, userChCfg->channelId, userChCfg->timebase)); /* Validate OPWMB parametter */ /* Phase Shift and DutyCycle cannot be bigger than the counter bus period */ DevAssert((Emios_Pwm_Ip_GetCounterBusPeriod(instance, userChCfg->channelId, userChCfg->timebase)) >= (userChCfg->phaseShift + userChCfg->dutyCycle)); DevAssert(EMIOS_PWM_MAX_CNT_VAL >= (uint32)((uint32)userChCfg->phaseShift + (uint32)userChCfg->dutyCycle)); #endif Emios_Pwm_Ip_HwAddrType *const base = Emios_Pwm_Ip_aBasePtr[instance]; Emios_Pwm_Ip_aRegA[instance][userChCfg->channelId] = userChCfg->phaseShift; /* Configure Counter Bus used by this channel */ Emios_Pwm_Ip_SetCounterBus(base, userChCfg->channelId, userChCfg->timebase); /* Configure Phase Shift in reg A */ Emios_Pwm_Ip_SetUCRegA(base, userChCfg->channelId, userChCfg->phaseShift); /* Configure Trailing edge in reg B */ Emios_Pwm_Ip_SetUCRegB(base, userChCfg->channelId, userChCfg->phaseShift + userChCfg->dutyCycle); /* Transition from GPIO mode to OPWMB mode */ Emios_Pwm_Ip_SetPwmMode(base, userChCfg->channelId, userChCfg->mode); /* Configure output pin polarity */ Emios_Pwm_Ip_SetEdgePolarity(base, userChCfg->channelId, userChCfg->outputPolarity); if (userChCfg->periodCount == userChCfg->dutyCycle) { /* 100% dutyCycle is desired. */ Emios_Pwm_Ip_aNotif[instance][userChCfg->channelId] = (uint8)1U; } else if((0U == userChCfg->dutyCycle) || (1U == userChCfg->dutyCycle)) { /* 0% dutyCycle is desired. */ Emios_Pwm_Ip_aNotif[instance][userChCfg->channelId] = (uint8)1U; } else { Emios_Pwm_Ip_aNotif[instance][userChCfg->channelId] = (uint8)0U; } } /*FUNCTION********************************************************************** * * Function Name : Emios_Pwm_Ip_SetDutyCycleOpwmb * Description : Set new duty cycle for the channel in OPWMB mode * This function will check the specific duty cycle and set new duty cycle for * this channel * *END**************************************************************************/ static Emios_Pwm_Ip_StatusType Emios_Pwm_Ip_SetDutyCycleOpwmb(uint8 instance, uint8 channel, uint16 newDutyCycle) { #if (EMIOS_PWM_IP_DEV_ERROR_DETECT == STD_ON) DevAssert(EMIOS_PWM_INSTANCE_COUNT > instance); DevAssert(EMIOS_PWM_CHANNEL_COUNT > channel); #endif Emios_Pwm_Ip_HwAddrType *const base = Emios_Pwm_Ip_aBasePtr[instance]; Emios_Pwm_Ip_StatusType ret = EMIOS_PWM_STATUS_SUCCESS; uint16 chPeriod = Emios_Pwm_Ip_GetCounterBusPeriod(instance, channel, Emios_Pwm_Ip_GetCounterBus(base, channel)); /* OPWMB mode */ if ((newDutyCycle + Emios_Pwm_Ip_aRegA[instance][channel]) > chPeriod) { /* New duty cycle puts trailing edge outside of counter bus period. */ ret = EMIOS_PWM_STATUS_ERROR; } else { if(newDutyCycle == 0U) { /* Disable and clear interrupt flag */ Emios_Pwm_Ip_SetInterruptRequest(base, channel, FALSE); Emios_Pwm_Ip_ClearFlagEvent(base, channel); Emios_Pwm_Ip_aNotif[instance][channel] = (uint8)1U; } else if (newDutyCycle == chPeriod) { /* Disable and clear interrupt flag */ Emios_Pwm_Ip_SetInterruptRequest(base, channel, FALSE); Emios_Pwm_Ip_ClearFlagEvent(base, channel); Emios_Pwm_Ip_aNotif[instance][channel] = (uint8)1U; } else { Emios_Pwm_Ip_aNotif[instance][channel] = (uint8)0U; Emios_Pwm_Ip_SetInterruptRequest(base, channel, (Emios_Pwm_Ip_aCheckEnableNotif[instance][channel] == 0U)? FALSE : TRUE); } Emios_Pwm_Ip_SetUCRegB(base, channel, (newDutyCycle + Emios_Pwm_Ip_aRegA[instance][channel])); } return ret; } /*FUNCTION********************************************************************** * * Function Name : Emios_Pwm_Ip_InitTriggerMode * Description : Initial Output Pulse Width Modulation with Trigger (OPWMT) Mode * OPWMT mode is intended to support the generation of Pulse Width Modulation signals where * the period is not modified while the signal is being output, but where the duty cycle will * be varied and must not create glitches. The mode is intended to be used in conjunction with * other channels executing in the same mode and sharing a common timebase. It will support each * channel with a fixed PWM leading edge position with respect to the other channels and the * ability to generate a trigger signal at any point in the period that can be output from * the module to initiate activity in other parts of the SoC such as starting ADC conversions. * * An external counter driven in either MC Up or MCB Up mode must be selected from one of the counter buses. * * The leading edge can be configured with any value within the range of the selected time base. Note that registers * loaded with 0x0 will not produce matches if the timebase is driven by a channel in MCB mode. * *END**************************************************************************/ static void Emios_Pwm_Ip_InitTriggerMode(uint8 instance, Emios_Pwm_Ip_ChannelConfigType const *userChCfg) { #if (EMIOS_PWM_IP_DEV_ERROR_DETECT == STD_ON) DevAssert(NULL_PTR != userChCfg); DevAssert(EMIOS_PWM_INSTANCE_COUNT > instance); DevAssert(EMIOS_PWM_CHANNEL_COUNT > userChCfg->channelId); /* Check Selected channel is set for OPWMT */ DevAssert(userChCfg->mode == EMIOS_PWM_MODE_OPWMT); /* Check selected channel supports OPWMT mode */ DevAssert(TRUE == Emios_Pwm_Ip_ValidateMode(instance, userChCfg->channelId, EMIOS_PWM_HW_MODE_OPWMT)); /* Check selected counter bus is configured in MCB Up Mode or MC Up mode */ DevAssert((EMIOS_PWM_IP_MCB_UP_COUNTER == Emios_Pwm_Ip_GetCounterBusMode(instance, userChCfg->channelId, userChCfg->timebase)) || (EMIOS_PWM_IP_MC_UP_COUNTER_START == Emios_Pwm_Ip_GetCounterBusMode(instance, userChCfg->channelId, userChCfg->timebase)) || (EMIOS_PWM_IP_MC_UP_COUNTER_END == Emios_Pwm_Ip_GetCounterBusMode(instance, userChCfg->channelId, userChCfg->timebase))); #endif Emios_Pwm_Ip_HwAddrType *const base = Emios_Pwm_Ip_aBasePtr[instance]; uint16 counterBusPeriod = Emios_Pwm_Ip_GetCounterBusPeriod(instance, userChCfg->channelId, userChCfg->timebase); uint16 trailingEdge = 0x0000U; uint8 counterStart = 0U; #if (EMIOS_PWM_IP_DEV_ERROR_DETECT == STD_ON) /* Validate OPWMT parameters */ /* Phase Shift must be in the counter bus period range. */ DevAssert(counterBusPeriod >= userChCfg->phaseShift); /* If 100% duty cycle must be implemented the maximum counter value for the time base is 0xFFFE */ DevAssert(EMIOS_PWM_MAX_CNT_VAL > counterBusPeriod); /* Duty cycle must not exceed the counter bus period. If 100% duty is desired dutycycle must be counterbus period +1U */ DevAssert((counterBusPeriod + 1U) >= userChCfg->dutyCycle); /* Trigger point must be inside the counter bus period */ DevAssert(counterBusPeriod >= userChCfg->triggerPosition); #endif if (EMIOS_PWM_IP_MCB_UP_COUNTER == Emios_Pwm_Ip_GetCounterBusMode(instance, userChCfg->channelId, userChCfg->timebase)) { counterStart = 1U; } else { counterStart = 0U; } if (counterBusPeriod == userChCfg->dutyCycle) { /* 100% dutyCycle is desired. Trailing edge must be placed outside counter bus period. */ trailingEdge = userChCfg->dutyCycle + 1U; Emios_Pwm_Ip_aNotif[instance][userChCfg->channelId] = (uint8)1U; } else if (0U == userChCfg->dutyCycle) { trailingEdge = userChCfg->phaseShift; Emios_Pwm_Ip_aNotif[instance][userChCfg->channelId] = (uint8)1U; } else { /* Calculate trailing edge postion. Wrap-around if dutyCycle extends the signal past the counterbus period. */ trailingEdge = (userChCfg->phaseShift + userChCfg->dutyCycle) % counterBusPeriod; Emios_Pwm_Ip_aNotif[instance][userChCfg->channelId] = (uint8)0U; } Emios_Pwm_Ip_aRegA[instance][userChCfg->channelId] = userChCfg->phaseShift + counterStart; /* Configure Counter Bus used by this channel */ Emios_Pwm_Ip_SetCounterBus(base, userChCfg->channelId, userChCfg->timebase); /* Configure Leading Edge in reg A */ Emios_Pwm_Ip_SetUCRegA(base, userChCfg->channelId, (userChCfg->phaseShift + counterStart)); /* Configure Trailing Edge in reg B */ Emios_Pwm_Ip_SetUCRegB(base, userChCfg->channelId, (trailingEdge + counterStart)); /* Configure Triggerpoint in reg ALTA */ Emios_Pwm_Ip_SetTrigger(base, userChCfg->channelId, (userChCfg->triggerPosition + counterStart)); /* To avoid spike pulse If duty cycle = 100%, when enter mode, EDPOL bit get complement of polarity after that, EDPOL bit is restored valid value */ if (counterBusPeriod == userChCfg->dutyCycle) { Emios_Pwm_Ip_SetEdgePolarity(base, userChCfg->channelId,(userChCfg->outputPolarity == EMIOS_PWM_ACTIVE_HIGH) ? EMIOS_PWM_ACTIVE_LOW : EMIOS_PWM_ACTIVE_HIGH ); } else { Emios_Pwm_Ip_SetEdgePolarity(base, userChCfg->channelId, userChCfg->outputPolarity); } /* Transition from GPIO mode to OPWMT mode */ Emios_Pwm_Ip_SetPwmMode(base, userChCfg->channelId, userChCfg->mode); /* Configure output pin polarity */ Emios_Pwm_Ip_SetEdgePolarity(base, userChCfg->channelId, userChCfg->outputPolarity); } /*FUNCTION********************************************************************** * * Function Name : Emios_Pwm_Ip_SetDutyCycleOpwmt * Description : Set new duty cycle for the channel in OPWMT mode * This function will check the specific duty cycle and set new duty cycle for * this channel * *END**************************************************************************/ static Emios_Pwm_Ip_StatusType Emios_Pwm_Ip_SetDutyCycleOpwmt(uint8 instance, uint8 channel, uint16 newDutyCycle) { #if (EMIOS_PWM_IP_DEV_ERROR_DETECT == STD_ON) DevAssert(EMIOS_PWM_INSTANCE_COUNT > instance); DevAssert(EMIOS_PWM_CHANNEL_COUNT > channel); #endif Emios_Pwm_Ip_HwAddrType *const base = Emios_Pwm_Ip_aBasePtr[instance]; Emios_Pwm_Ip_StatusType ret = EMIOS_PWM_STATUS_SUCCESS; uint16 chPeriod = Emios_Pwm_Ip_GetCounterBusPeriod(instance, channel, Emios_Pwm_Ip_GetCounterBus(base, channel)); /* OPWMT mode */ if (newDutyCycle > chPeriod) { /* Duty cycle value should not be greater than the channel Period. */ ret = EMIOS_PWM_STATUS_ERROR; } else { if (chPeriod == newDutyCycle) { /* 100% dutyCycle is desired. Trailing edge must be placed outside counter bus period. */ /* Disable and clear interrupt flag */ Emios_Pwm_Ip_SetInterruptRequest(base, channel, FALSE); Emios_Pwm_Ip_ClearFlagEvent(base, channel); Emios_Pwm_Ip_SetUCRegB(base, channel, (newDutyCycle + 1U)); Emios_Pwm_Ip_aNotif[instance][channel] = (uint8)1U; } else if(0U == newDutyCycle) { /* 0% dutyCycle is desired. */ /* Disable and clear interrupt flag */ Emios_Pwm_Ip_SetInterruptRequest(base, channel, FALSE); Emios_Pwm_Ip_ClearFlagEvent(base, channel); Emios_Pwm_Ip_SetUCRegB(base, channel, Emios_Pwm_Ip_aRegA[instance][channel]); Emios_Pwm_Ip_aNotif[instance][channel] = (uint8)1U; } else { /* Calculate trailing edge postion. Wrap-around if dutyCycle extends the signal past the counterbus period. */ Emios_Pwm_Ip_SetUCRegB(base, channel, (Emios_Pwm_Ip_aRegA[instance][channel] + newDutyCycle) % chPeriod); Emios_Pwm_Ip_aNotif[instance][channel] = (uint8)0U; Emios_Pwm_Ip_SetInterruptRequest(base, channel, (Emios_Pwm_Ip_aCheckEnableNotif[instance][channel] == 0U)? FALSE : TRUE); } } return ret; } /*FUNCTION********************************************************************** * * Function Name : Emios_Pwm_Ip_InitDoubleCompareMode * Description : Initial Double Action Output Compare (DAOC) Mode. * This mode provides waveforms with variable duty cycle and frequency. * In DAOC mode, at the end of period, the A register and B register need re-calculated to * enable next match A. This calculation and first pulse must be done by software. * Calculate the duty tick follow period and Duty cycle * Always enable interrupt. Because in this mode, the A register and B register is re-calculated * with period and duty at the end of period by software. * *END**************************************************************************/ static void Emios_Pwm_Ip_InitDoubleCompareMode(uint8 instance, Emios_Pwm_Ip_ChannelConfigType const *userChCfg) { #if (EMIOS_PWM_IP_DEV_ERROR_DETECT == STD_ON) DevAssert(NULL_PTR != userChCfg); DevAssert(EMIOS_PWM_INSTANCE_COUNT > instance); DevAssert(EMIOS_PWM_CHANNEL_COUNT > userChCfg->channelId); /* Check Selected channel is set for DAOC mode */ DevAssert((userChCfg->mode == EMIOS_PWM_MODE_DAOC_FLAG) || (userChCfg->mode == EMIOS_PWM_MODE_DAOC_FLAG_BOTH)); /* Validate opwfmb parametter */ DevAssert(EMIOS_PWM_MIN_CNT_VAL < userChCfg->periodCount); DevAssert(userChCfg->dutyCycle <= userChCfg->periodCount); #endif Emios_Pwm_Ip_HwAddrType *const base = Emios_Pwm_Ip_aBasePtr[instance]; Emios_Pwm_Ip_aPeriod[instance][userChCfg->channelId] = userChCfg->periodCount; Emios_Pwm_Ip_aPolarity[instance][userChCfg->channelId] = (userChCfg->outputPolarity == EMIOS_PWM_ACTIVE_HIGH)? 1U : 0U; uint16 daocRegA = 0U; uint16 counterMax = Emios_Pwm_Ip_GetUCRegA(base, Emios_Pwm_Ip_GetMasterBusChannel(instance, userChCfg->channelId)); /* FLAG event enabled */ Emios_Pwm_Ip_SetInterruptRequest(base, userChCfg->channelId, TRUE); /* Configure Counter Bus used by this channel */ Emios_Pwm_Ip_SetCounterBus(base, userChCfg->channelId, userChCfg->timebase); if (userChCfg->periodCount == userChCfg->dutyCycle) { Emios_Pwm_Ip_SetEdgePolarity(base, userChCfg->channelId,(userChCfg->outputPolarity == EMIOS_PWM_ACTIVE_HIGH) ? EMIOS_PWM_ACTIVE_LOW : EMIOS_PWM_ACTIVE_HIGH ); } else { Emios_Pwm_Ip_SetEdgePolarity(base, userChCfg->channelId, userChCfg->outputPolarity); } /* Transition from GPIO mode to DAOC mode */ Emios_Pwm_Ip_SetPwmMode(base, userChCfg->channelId, userChCfg->mode); /* Configure output pin polarity */ Emios_Pwm_Ip_SetEdgePolarity(base, userChCfg->channelId, userChCfg->outputPolarity); /* With Duty cycle 0% */ if(0U == userChCfg->dutyCycle) { daocRegA = 1U; Emios_Pwm_Ip_aDaocDuty[instance][userChCfg->channelId] = 0U; Emios_Pwm_Ip_SetForceMatchB(base, userChCfg->channelId, TRUE); /* Configure Leading Edge in reg A */ Emios_Pwm_Ip_SetUCRegA(base, userChCfg->channelId, daocRegA); /* Configure Trailing Edge in reg B */ Emios_Pwm_Ip_SetUCRegB(base, userChCfg->channelId, (userChCfg->dutyCycle + 1U)); Emios_Pwm_Ip_SetEdgePolarity(base, userChCfg->channelId, userChCfg->outputPolarity); Emios_Pwm_Ip_aNotif[instance][userChCfg->channelId] = (uint8)1U; } else if(userChCfg->dutyCycle == userChCfg->periodCount) { daocRegA = (Emios_Pwm_Ip_aPeriod[instance][userChCfg->channelId] + Emios_Pwm_Ip_GetUCRegA(base, userChCfg->channelId)) % counterMax; Emios_Pwm_Ip_aDaocDuty[instance][userChCfg->channelId] = 0U; Emios_Pwm_Ip_SetForceMatchA(base, userChCfg->channelId, TRUE); /* Configure Leading Edge in reg A */ Emios_Pwm_Ip_SetUCRegA(base, userChCfg->channelId, (daocRegA == 0U)? counterMax : daocRegA); /* Configure Trailing Edge in reg B */ Emios_Pwm_Ip_SetUCRegB(base, userChCfg->channelId, (daocRegA == 0U)? counterMax : daocRegA); /* Invert the EDGE POLARITY in control register */ Emios_Pwm_Ip_SetEdgePolarity(base, userChCfg->channelId,(userChCfg->outputPolarity == EMIOS_PWM_ACTIVE_HIGH) ? EMIOS_PWM_ACTIVE_LOW : EMIOS_PWM_ACTIVE_HIGH); Emios_Pwm_Ip_aNotif[instance][userChCfg->channelId] = (uint8)1U; } else { daocRegA = 1U; Emios_Pwm_Ip_aDaocDuty[instance][userChCfg->channelId] = userChCfg->dutyCycle; /* Configure Leading Edge in reg A */ Emios_Pwm_Ip_SetUCRegA(base, userChCfg->channelId, daocRegA); /* Configure Trailing Edge in reg B */ Emios_Pwm_Ip_SetUCRegB(base, userChCfg->channelId, (userChCfg->dutyCycle + 1U)); Emios_Pwm_Ip_SetEdgePolarity(base, userChCfg->channelId, userChCfg->outputPolarity); Emios_Pwm_Ip_aNotif[instance][userChCfg->channelId] = (uint8)0U; } } /*FUNCTION********************************************************************** * * Function Name : Emios_Pwm_Ip_SetDutyCycleDaoc * Description : Set new duty cycle for the channel in DAOC mode * This function will check the specific duty cycle and set new duty cycle for * this channel * *END**************************************************************************/ static Emios_Pwm_Ip_StatusType Emios_Pwm_Ip_SetDutyCycleDaoc(uint8 instance, uint8 channel, uint16 newDutyCycle) { #if (EMIOS_PWM_IP_DEV_ERROR_DETECT == STD_ON) DevAssert(EMIOS_PWM_INSTANCE_COUNT > instance); DevAssert(EMIOS_PWM_CHANNEL_COUNT > channel); #endif Emios_Pwm_Ip_HwAddrType *const base = Emios_Pwm_Ip_aBasePtr[instance]; Emios_Pwm_Ip_StatusType ret = EMIOS_PWM_STATUS_SUCCESS; uint16 daocRegA = 0U; uint16 counterMax = Emios_Pwm_Ip_GetUCRegA(base, Emios_Pwm_Ip_GetMasterBusChannel(instance, channel)); /* DAOC mode */ if ((newDutyCycle > Emios_Pwm_Ip_aPeriod[instance][channel]) && ((uint16)0U != Emios_Pwm_Ip_aPeriod[instance][channel])) { /* Duty cycle value should not be greater than the channel Period. */ ret = EMIOS_PWM_STATUS_ERROR; } else if (((uint16)0U == Emios_Pwm_Ip_aPeriod[instance][channel]) || ((uint16)0U == newDutyCycle)) { /* Disable and clear interrupt flag */ Emios_Pwm_Ip_SetInterruptRequest(base, channel, FALSE); Emios_Pwm_Ip_ClearFlagEvent(base, channel); /* If new period is 0, set duty cycle to 0 */ Emios_Pwm_Ip_aDaocDuty[instance][channel] = 0U; Emios_Pwm_Ip_SetForceMatchB(base, channel, TRUE); /* Configure Leading Edge in reg A */ Emios_Pwm_Ip_SetUCRegA(base, channel, 1U); /* Configure Trailing Edge in reg B */ Emios_Pwm_Ip_SetUCRegB(base, channel, (newDutyCycle + 1U)); Emios_Pwm_Ip_SetEdgePolarity(base, channel, (Emios_Pwm_Ip_aPolarity[instance][channel] == 1U)? EMIOS_PWM_ACTIVE_HIGH : EMIOS_PWM_ACTIVE_LOW); Emios_Pwm_Ip_aNotif[instance][channel] = (uint8)1U; } else if(newDutyCycle == Emios_Pwm_Ip_aPeriod[instance][channel]) { /* Disable and clear interrupt flag */ Emios_Pwm_Ip_SetInterruptRequest(base, channel, FALSE); Emios_Pwm_Ip_ClearFlagEvent(base, channel); Emios_Pwm_Ip_aDaocDuty[instance][channel] = 0U; daocRegA = (Emios_Pwm_Ip_aPeriod[instance][channel] + Emios_Pwm_Ip_GetUCRegA(base, channel)) % counterMax; Emios_Pwm_Ip_SetForceMatchA(base, channel, TRUE); /* Configure Leading Edge in reg A */ Emios_Pwm_Ip_SetUCRegA(base, channel, (daocRegA == 0U)? counterMax : daocRegA); /* Configure Trailing Edge in reg B */ Emios_Pwm_Ip_SetUCRegB(base, channel, (daocRegA == 0U)? counterMax : daocRegA); /* Invert the EDGE POLARITY in control register */ Emios_Pwm_Ip_SetEdgePolarity(base, channel,(Emios_Pwm_Ip_aPolarity[instance][channel] == 1U)? EMIOS_PWM_ACTIVE_LOW : EMIOS_PWM_ACTIVE_HIGH); Emios_Pwm_Ip_aNotif[instance][channel] = (uint8)1U; } else { Emios_Pwm_Ip_aDaocDuty[instance][channel] = newDutyCycle; /* Configure Leading Edge in reg A */ Emios_Pwm_Ip_SetUCRegA(base, channel, 1U); /* Configure Trailing Edge in reg B */ Emios_Pwm_Ip_SetUCRegB(base, channel, newDutyCycle + 1U); Emios_Pwm_Ip_SetEdgePolarity(base, channel, (Emios_Pwm_Ip_aPolarity[instance][channel] == 1U)? EMIOS_PWM_ACTIVE_HIGH : EMIOS_PWM_ACTIVE_LOW); Emios_Pwm_Ip_aNotif[instance][channel] = (uint8)0U; } return ret; } /*================================================================================================== * GLOBAL FUNCTIONS ==================================================================================================*/ /*FUNCTION********************************************************************** * * Function Name : Emios_Pwm_Ip_InitChannel * Description : Initialize PWM mode. * Select main mode * - EMIOS OPWFMB * Initialize Output Pulse Width and Frequency Modulation Buffered (OPWFMB) Mode. * This mode provides waveforms with variable duty cycle and frequency. The internal channel counter * is automatically selected as the time base when this mode is selected. * * - EMIOS OPWMB * Initialize Output Pulse Width Modulation Buffered (OPWMB) Mode. * OPWMB mode is used to generate pulses with programmable leading and trailing edge placement. * An external counter driven in MCB Up mode must be selected from one of the counter buses. * userChCfg defines the first edge and the second edge. The output signal polarity is defined * by outputPolarity in userChCfg. * * - EMIOS OPWMCB * Initialize Center Aligned Output Pulse Width Modulation with Dead Time Insertion Buffered (OPWMCB) Mode. * This operation mode generates a center aligned PWM with dead time insertion to the leading or trailing edge. * Allow smooth output signal generation when changing duty cycle and deadtime values. * * - EMIOS OPWMT * Initialize Output Pulse Width Modulation with Trigger (OPWMT) Mode * OPWMT mode is intended to support the generation of Pulse Width Modulation signals where * the period is not modified while the signal is being output, but where the duty cycle will * be varied and must not create glitches. The mode is intended to be used in conjunction with * other channels executing in the same mode and sharing a common timebase. It will support each * channel with a fixed PWM leading edge position with respect to the other channels and the * ability to generate a trigger signal at any point in the period that can be output from * the module to initiate activity in other parts of the SoC such as starting ADC conversions. * Implements : Emios_Pwm_Ip_InitChannel_Activity *END**************************************************************************/ void Emios_Pwm_Ip_InitChannel(uint8 instance, Emios_Pwm_Ip_ChannelConfigType const *userChCfg) { #if (EMIOS_PWM_IP_DEV_ERROR_DETECT == STD_ON) DevAssert(NULL_PTR != userChCfg); DevAssert(EMIOS_PWM_INSTANCE_COUNT > instance); /* Check that a valid notification structure is defined for interrupt mode */ if (EMIOS_PWM_INTERRUPT_REQUEST == userChCfg->irqMode) { DevAssert(NULL_PTR != userChCfg->userCallback.cbFunction); } #endif Emios_Pwm_Ip_HwAddrType *const base = Emios_Pwm_Ip_aBasePtr[instance]; uint8 channel = userChCfg->channelId; /* Disable channel pre-scaler (reset default) */ Emios_Pwm_Ip_aBasePtr[instance]->CH.UC[userChCfg->channelId].C = 0UL; /* Enable the Output Update for channel */ Emios_Pwm_Ip_SetOutputUpdate(base, channel, TRUE); #if (EMIOS_PWM_IP_DEV_ERROR_DETECT == STD_ON) /* Configure debug freeze enable */ if ((FALSE == Emios_Pwm_Ip_GetDebugMode(base)) && (TRUE == userChCfg->debugMode)) { DevAssert(FALSE); } else { Emios_Pwm_Ip_SetFreezeEnable(base, userChCfg->channelId, userChCfg->debugMode); } #endif /* Configure output disable feature */ if (EMIOS_PWM_OUTPUT_DISABLE_NONE != userChCfg->outputDisableSource) { Emios_Pwm_Ip_SetOutDisable(base, userChCfg->channelId, TRUE); Emios_Pwm_Ip_SetOutDisableSource(base, userChCfg->channelId, userChCfg->outputDisableSource); } /* Configure Interrupt/DMA request */ if (EMIOS_PWM_NOTIFICATION_DISABLED != userChCfg->irqMode) { if (EMIOS_PWM_INTERRUPT_REQUEST == userChCfg->irqMode) { /* Register the notification structure */ Emios_Pwm_Ip_aNotificationPtr[instance][userChCfg->channelId] = &(userChCfg->userCallback); } else { Emios_Pwm_Ip_SetDMARequest(base, userChCfg->channelId, TRUE); } } /* Configure counterBus, dutyCycle, period, trigger, phase shift for selected mode */ switch (userChCfg->mode) { case EMIOS_PWM_MODE_OPWFMB_FLAG: case EMIOS_PWM_MODE_OPWFMB_FLAG_BOTH: /* OPWFMB mode initialization */ Emios_Pwm_Ip_InitPeriodDutyCycleMode(instance, userChCfg); break; case EMIOS_PWM_MODE_OPWMCB_TRAIL_EDGE_FLAG: case EMIOS_PWM_MODE_OPWMCB_TRAIL_EDGE_FLAG_BOTH: case EMIOS_PWM_MODE_OPWMCB_LEAD_EDGE_FLAG: case EMIOS_PWM_MODE_OPWMCB_LEAD_EDGE_FLAG_BOTH: /* OPWMCB mode initialization */ Emios_Pwm_Ip_InitDeadTimeMode(instance, userChCfg); break; case EMIOS_PWM_MODE_OPWMB_FLAG: case EMIOS_PWM_MODE_OPWMB_FLAG_BOTH: /* OPWMB mode initialization */ Emios_Pwm_Ip_InitEdgePlacementMode(instance, userChCfg); break; case EMIOS_PWM_MODE_OPWMT: /* OPWMT mode initialization */ Emios_Pwm_Ip_InitTriggerMode(instance, userChCfg); break; case EMIOS_PWM_MODE_DAOC_FLAG: case EMIOS_PWM_MODE_DAOC_FLAG_BOTH: /* DAOC mode initialization */ Emios_Pwm_Ip_InitDoubleCompareMode(instance, userChCfg); break; default: /* Nothing to do. All Pwm mode are already treated. */ break; } /* Configure internal prescaler */ if (EMIOS_PWM_CLOCK_NONE != userChCfg->internalPs) { Emios_Pwm_Ip_SetExtendedPrescaler(base, userChCfg->channelId, userChCfg->internalPs); Emios_Pwm_Ip_SetPrescalerSource(base, userChCfg->channelId, userChCfg->internalPsSrc); Emios_Pwm_Ip_SetPrescalerEnable(base, userChCfg->channelId, TRUE); } /* Confirm the channel is active*/ Emios_Pwm_Ip_aCheckState[instance][userChCfg->channelId] = (uint8)1U; } /*FUNCTION********************************************************************** * * Function Name : Emios_Pwm_Ip_DeInitChannel * Description : Reset eMIOS channel to GPIO mode (reset default) * Implements : Emios_Pwm_Ip_DeInitChannel_Activity *END**************************************************************************/ void Emios_Pwm_Ip_DeInitChannel(uint8 instance, uint8 channel) { #if (EMIOS_PWM_IP_DEV_ERROR_DETECT == STD_ON) DevAssert(EMIOS_PWM_INSTANCE_COUNT > instance); DevAssert(EMIOS_PWM_CHANNEL_COUNT > channel); #endif Emios_Pwm_Ip_HwAddrType *const base = Emios_Pwm_Ip_aBasePtr[instance]; /* Clear control register 2 and stop clock for channel */ base->CH.UC[channel].C2 = 0UL; /* Clear control register for channel */ base->CH.UC[channel].C = 0UL; /* Clear An and Bn registers */ Emios_Pwm_Ip_SetUCRegA(base, channel, 0U); Emios_Pwm_Ip_SetUCRegB(base, channel, 0U); /* Clear ALTAn if in PWM Trigger mode */ if (Emios_Pwm_Ip_GetPwmMode(base, channel) == EMIOS_PWM_MODE_OPWMT) { Emios_Pwm_Ip_SetTrigger(base, channel, 0U); } Emios_Pwm_Ip_aCheckEnableNotif[instance][channel] = (uint8)0U; /* Confirm the channel is inactive*/ Emios_Pwm_Ip_aCheckState[instance][channel] = (uint8)0U; } /*FUNCTION********************************************************************** * * Function Name : Emios_Pwm_Ip_ForceMatchLeadingEdge * Description : Force the output flip-flop to the level corresponding to a match on Leading edge * In Center Aligned Output Pulse Width Modulation with Dead Time Insertion Buffered (OPWMCB) Mode * FORCMA has different behaviors depending upon the selected dead time * insertion mode, lead or trail. In lead dead time insertion FORCMA force a transition * in the output flipflop to the opposite of EDPOL. In trail dead time insertion the * output flip-flop is forced to the value of EDPOL bit. * FORCMA bit set does not set the internal time-base to 0x1 as a regular A1 match. * Implements : Emios_Pwm_Ip_ForceMatchLeadingEdge_Activity *END**************************************************************************/ void Emios_Pwm_Ip_ForceMatchLeadingEdge(uint8 instance, uint8 channel, boolean enable) { #if (EMIOS_PWM_IP_DEV_ERROR_DETECT == STD_ON) DevAssert(EMIOS_PWM_INSTANCE_COUNT > instance); DevAssert(EMIOS_PWM_CHANNEL_COUNT > channel); #endif Emios_Pwm_Ip_HwAddrType *const base = Emios_Pwm_Ip_aBasePtr[instance]; SchM_Enter_Pwm_PWM_EXCLUSIVE_AREA_14(); /* Force Match A bit */ Emios_Pwm_Ip_SetForceMatchA(base, channel, enable); SchM_Exit_Pwm_PWM_EXCLUSIVE_AREA_14(); } /*FUNCTION********************************************************************** * * Function Name : Emios_Pwm_Ip_ForceMatchTrailingEdge * Description : Force the output flipflop to the level corresponding to a match on Trailing edge * * In Center Aligned Output Pulse Width Modulation with Dead Time Insertion Buffered (OPWMCB) Mode * If FORCMB bit is set, the output flip-flop value depends upon the selected dead time * insertion mode. In lead dead time insertion FORCMB forces the output flip-flop to transition to EDPOL * bit value. In trail dead time insertion the output flip-flop is forced to the opposite of EDPOL bit value. * Implements : Emios_Pwm_Ip_ForceMatchTrailingEdge_Activity *END**************************************************************************/ void Emios_Pwm_Ip_ForceMatchTrailingEdge(uint8 instance, uint8 channel, boolean enable) { #if (EMIOS_PWM_IP_DEV_ERROR_DETECT == STD_ON) DevAssert(EMIOS_PWM_INSTANCE_COUNT > instance); DevAssert(EMIOS_PWM_CHANNEL_COUNT > channel); #endif Emios_Pwm_Ip_HwAddrType *const base = Emios_Pwm_Ip_aBasePtr[instance]; SchM_Enter_Pwm_PWM_EXCLUSIVE_AREA_15(); /* Force Match B bit */ Emios_Pwm_Ip_SetForceMatchB(base, channel, enable); SchM_Exit_Pwm_PWM_EXCLUSIVE_AREA_15(); } /*FUNCTION********************************************************************** * * Function Name : Emios_Pwm_Ip_GetPeriod * Description : Get period of waveforms in PWM mode. * Implements : Emios_Pwm_Ip_GetPeriod_Activity *END**************************************************************************/ uint16 Emios_Pwm_Ip_GetPeriod(uint8 instance, uint8 channel) { #if (EMIOS_PWM_IP_DEV_ERROR_DETECT == STD_ON) DevAssert(EMIOS_PWM_INSTANCE_COUNT > instance); DevAssert(EMIOS_PWM_CHANNEL_COUNT > channel); #endif const Emios_Pwm_Ip_HwAddrType *const base = Emios_Pwm_Ip_aBasePtr[instance]; Emios_Pwm_Ip_PwmModeType chMode = Emios_Pwm_Ip_GetPwmMode(base, channel); uint16 chPeriod = 0x00U; if ((chMode == EMIOS_PWM_MODE_OPWFMB_FLAG) || (chMode == EMIOS_PWM_MODE_OPWFMB_FLAG_BOTH)) { /* OPWFMB mode */ chPeriod = Emios_Pwm_Ip_GetUCRegB(base, channel); } else if ((chMode == EMIOS_PWM_MODE_DAOC_FLAG) || (chMode == EMIOS_PWM_MODE_DAOC_FLAG_BOTH)) { /* DAOC mode */ chPeriod = Emios_Pwm_Ip_aPeriod[instance][channel]; } else { /* OPWMCB mode or OPWMB or OPWMT mode */ chPeriod = Emios_Pwm_Ip_GetCounterBusPeriod(instance, channel, Emios_Pwm_Ip_GetCounterBus(base, channel)); } return chPeriod; } /*FUNCTION********************************************************************** * * Function Name : Emios_Pwm_Ip_SetPeriod * Description : Setup period of waveforms in OPWFMB mode. * With PWM mode, the OPWFMB(Output Pulse Width and Frequency Modulation Buffered) can set * period. All other PWM modes can not, because OPWFMB mode using internal counter. All other * modes use external timebase and their period is timebase period. * Implements : Emios_Pwm_Ip_SetPeriod_Activity *END**************************************************************************/ void Emios_Pwm_Ip_SetPeriod(uint8 instance, uint8 channel, uint16 newPeriod) { #if (EMIOS_PWM_IP_DEV_ERROR_DETECT == STD_ON) DevAssert(EMIOS_PWM_INSTANCE_COUNT > instance); DevAssert(EMIOS_PWM_CHANNEL_COUNT > channel); #endif Emios_Pwm_Ip_HwAddrType *const base = Emios_Pwm_Ip_aBasePtr[instance]; #if (EMIOS_PWM_IP_DEV_ERROR_DETECT == STD_ON) Emios_Pwm_Ip_PwmModeType chMode = Emios_Pwm_Ip_GetPwmMode(base, channel); #endif #if (EMIOS_PWM_IP_DEV_ERROR_DETECT == STD_ON) /* Check channel mode is OPWFMB */ DevAssert((EMIOS_PWM_MODE_OPWFMB_FLAG == chMode) || (EMIOS_PWM_MODE_OPWFMB_FLAG_BOTH == chMode) || (EMIOS_PWM_MODE_DAOC_FLAG == chMode) || (EMIOS_PWM_MODE_DAOC_FLAG_BOTH == chMode)); #endif SchM_Enter_Pwm_PWM_EXCLUSIVE_AREA_16(); /* If new period is 0, No change the period */ if((uint16)0U == newPeriod) { /* Do Nothing */ } else { /* Set new period */ Emios_Pwm_Ip_SetUCRegB(base, channel, newPeriod); } /* Store new period */ Emios_Pwm_Ip_aPeriod[instance][channel] = newPeriod; SchM_Exit_Pwm_PWM_EXCLUSIVE_AREA_16(); } /*FUNCTION********************************************************************** * * Function Name : Emios_Pwm_Ip_GetDutyCycle * Description : Get duty cycle of waveforms in PWM mode. Duty cycle is signal active time in a period. * Implements : Emios_Pwm_Ip_GetDutyCycle_Activity *END**************************************************************************/ uint16 Emios_Pwm_Ip_GetDutyCycle(uint8 instance, uint8 channel) { #if (EMIOS_PWM_IP_DEV_ERROR_DETECT == STD_ON) DevAssert(EMIOS_PWM_INSTANCE_COUNT > instance); DevAssert(EMIOS_PWM_CHANNEL_COUNT > channel); #endif const Emios_Pwm_Ip_HwAddrType *const base = Emios_Pwm_Ip_aBasePtr[instance]; Emios_Pwm_Ip_PwmModeType chMode = Emios_Pwm_Ip_GetPwmMode(base, channel); uint16 regAValue = Emios_Pwm_Ip_GetUCRegA(base, channel); uint16 regBValue = Emios_Pwm_Ip_GetUCRegB(base, channel); uint16 chPeriod = 0U; uint16 dutyCycle = 0U; switch (chMode) { case EMIOS_PWM_MODE_OPWFMB_FLAG: case EMIOS_PWM_MODE_OPWFMB_FLAG_BOTH: case EMIOS_PWM_MODE_OPWMCB_TRAIL_EDGE_FLAG: case EMIOS_PWM_MODE_OPWMCB_TRAIL_EDGE_FLAG_BOTH: case EMIOS_PWM_MODE_OPWMCB_LEAD_EDGE_FLAG: case EMIOS_PWM_MODE_OPWMCB_LEAD_EDGE_FLAG_BOTH: /* OPWFMB or OPWMCB mode */ dutyCycle = regAValue; break; case EMIOS_PWM_MODE_OPWMB_FLAG: case EMIOS_PWM_MODE_OPWMB_FLAG_BOTH: /* OPWMB mode */ dutyCycle = regBValue - regAValue; break; case EMIOS_PWM_MODE_OPWMT: /* OPWMT mode */ /* Get channel period */ chPeriod = Emios_Pwm_Ip_GetCounterBusPeriod(instance, channel, Emios_Pwm_Ip_GetCounterBus(base, channel)); if (regBValue > chPeriod) { /* 100% dutyCycle when B value is greater than channel period. */ dutyCycle = regBValue; } else if (regBValue < regAValue) { /* PhaseShift of signal wrapped around the duty cycle */ dutyCycle = (chPeriod - regAValue) + regBValue; } else { dutyCycle = regBValue - regAValue; } break; case EMIOS_PWM_MODE_DAOC_FLAG: case EMIOS_PWM_MODE_DAOC_FLAG_BOTH: /* DAOC mode */ dutyCycle = Emios_Pwm_Ip_aDaocDuty[instance][channel]; break; default: /* Nothing to do */ #if (EMIOS_PWM_IP_DEV_ERROR_DETECT == STD_ON) DevAssert(FALSE); #endif break; } return dutyCycle; } /*FUNCTION********************************************************************** * * Function Name : Emios_Pwm_Ip_SetDutyCycle * Description : Setup duty cycle of waveforms in OPWFMB mode. * Duty cycle should be not greater period value. When set duty cycle value greater period value * (and do not over 16 bits counter register) 100% duty cycle signal generated. * Implements : Emios_Pwm_Ip_SetDutyCycle_Activity *END**************************************************************************/ Emios_Pwm_Ip_StatusType Emios_Pwm_Ip_SetDutyCycle(uint8 instance, uint8 channel, uint16 newDutyCycle) { #if (EMIOS_PWM_IP_DEV_ERROR_DETECT == STD_ON) DevAssert(EMIOS_PWM_INSTANCE_COUNT > instance); DevAssert(EMIOS_PWM_CHANNEL_COUNT > channel); #endif const Emios_Pwm_Ip_HwAddrType *const base = Emios_Pwm_Ip_aBasePtr[instance]; Emios_Pwm_Ip_StatusType ret = EMIOS_PWM_STATUS_SUCCESS; Emios_Pwm_Ip_PwmModeType chMode = Emios_Pwm_Ip_GetPwmMode(base, channel); SchM_Enter_Pwm_PWM_EXCLUSIVE_AREA_17(); if ((chMode == EMIOS_PWM_MODE_OPWFMB_FLAG) || (chMode == EMIOS_PWM_MODE_OPWFMB_FLAG_BOTH)) { /* OPWFMB mode */ ret = Emios_Pwm_Ip_SetDutyCycleOpwfmb(instance, channel, newDutyCycle); } else if ((chMode == EMIOS_PWM_MODE_OPWMCB_TRAIL_EDGE_FLAG) || (chMode == EMIOS_PWM_MODE_OPWMCB_TRAIL_EDGE_FLAG_BOTH) || (chMode == EMIOS_PWM_MODE_OPWMCB_LEAD_EDGE_FLAG) || (chMode == EMIOS_PWM_MODE_OPWMCB_LEAD_EDGE_FLAG_BOTH)) { /* OPWMCB mode */ ret = Emios_Pwm_Ip_SetDutyCycleOpwmcb(instance, channel, newDutyCycle); } else if ((chMode == EMIOS_PWM_MODE_OPWMB_FLAG) || (chMode == EMIOS_PWM_MODE_OPWMB_FLAG_BOTH)) { /* OPWMB mode */ ret = Emios_Pwm_Ip_SetDutyCycleOpwmb(instance, channel, newDutyCycle); } else if((chMode == EMIOS_PWM_MODE_DAOC_FLAG) || (chMode == EMIOS_PWM_MODE_DAOC_FLAG_BOTH)) { /* DAOC mode */ ret = Emios_Pwm_Ip_SetDutyCycleDaoc(instance, channel, newDutyCycle); } else { /* OPWMT mode */ ret = Emios_Pwm_Ip_SetDutyCycleOpwmt(instance, channel, newDutyCycle); } SchM_Exit_Pwm_PWM_EXCLUSIVE_AREA_17(); return ret; } /*FUNCTION********************************************************************** * * Function Name : Emios_Pwm_Ip_GetPhaseShift * Description : Get Leading edge position of waveforms in OPWMB & OPWMT mode. * Implements : Emios_Pwm_Ip_GetPhaseShift_Activity *END**************************************************************************/ uint16 Emios_Pwm_Ip_GetPhaseShift(uint8 instance, uint8 channel) { #if (EMIOS_PWM_IP_DEV_ERROR_DETECT == STD_ON) DevAssert(EMIOS_PWM_INSTANCE_COUNT > instance); DevAssert(EMIOS_PWM_CHANNEL_COUNT > channel); #endif const Emios_Pwm_Ip_HwAddrType *const base = Emios_Pwm_Ip_aBasePtr[instance]; #if (EMIOS_PWM_IP_DEV_ERROR_DETECT == STD_ON) Emios_Pwm_Ip_PwmModeType chMode = Emios_Pwm_Ip_GetPwmMode(base, channel); DevAssert((EMIOS_PWM_MODE_OPWMB_FLAG == chMode) || (EMIOS_PWM_MODE_OPWMB_FLAG_BOTH == chMode) || (EMIOS_PWM_MODE_OPWMT == chMode)); #endif return Emios_Pwm_Ip_GetUCRegA(base, channel); } /*FUNCTION********************************************************************** * * Function Name : Emios_Pwm_Ip_SetPhaseShift * Description : Set Leading edge position of waveforms in OPWMB & OPWMT mode. * DutyCycle will be kept the same value. * Implements : Emios_Pwm_Ip_SetPhaseShift_Activity *END**************************************************************************/ Emios_Pwm_Ip_StatusType Emios_Pwm_Ip_SetPhaseShift(uint8 instance, uint8 channel, uint16 phaseShift) { #if (EMIOS_PWM_IP_DEV_ERROR_DETECT == STD_ON) DevAssert(EMIOS_PWM_INSTANCE_COUNT > instance); DevAssert(EMIOS_PWM_CHANNEL_COUNT > channel); #endif Emios_Pwm_Ip_StatusType status = EMIOS_PWM_STATUS_SUCCESS; Emios_Pwm_Ip_HwAddrType *const base = Emios_Pwm_Ip_aBasePtr[instance]; Emios_Pwm_Ip_PwmModeType chMode = Emios_Pwm_Ip_GetPwmMode(base, channel); uint16 chPeriod = 0U; uint16 dutyCycle = 0U; uint8 counterStart = 0U; #if (EMIOS_PWM_IP_DEV_ERROR_DETECT == STD_ON) DevAssert((EMIOS_PWM_MODE_OPWMB_FLAG == chMode) || (EMIOS_PWM_MODE_OPWMB_FLAG_BOTH == chMode) || (EMIOS_PWM_MODE_OPWMT == chMode)); #endif SchM_Enter_Pwm_PWM_EXCLUSIVE_AREA_18(); chPeriod = Emios_Pwm_Ip_GetCounterBusPeriod(instance, channel, Emios_Pwm_Ip_GetCounterBus(base, channel)); dutyCycle = Emios_Pwm_Ip_GetDutyCycle(instance, channel); if (EMIOS_PWM_IP_MCB_UP_COUNTER == Emios_Pwm_Ip_GetCounterBusMode(instance, channel, Emios_Pwm_Ip_GetCounterBus(base, channel))) { counterStart = 1U; } else { counterStart = 0U; } Emios_Pwm_Ip_aRegA[instance][channel] = phaseShift + counterStart; /* Check that phase shift can be applied to the selected channel */ if ((EMIOS_PWM_MODE_OPWMB_FLAG == chMode) || (EMIOS_PWM_MODE_OPWMB_FLAG_BOTH == chMode)) { if ((phaseShift + dutyCycle) > chPeriod) { status = EMIOS_PWM_STATUS_ERROR; } else { /* Set the new phase shift */ Emios_Pwm_Ip_SetUCRegA(base, channel, (phaseShift + counterStart)); /* Move trailing edge to keep the same duty cycle */ Emios_Pwm_Ip_SetUCRegB(base, channel, (phaseShift + dutyCycle + counterStart)); } } else if (EMIOS_PWM_MODE_OPWMT == chMode) { if (phaseShift > chPeriod) { status = EMIOS_PWM_STATUS_ERROR; } else { /* Set the new phase shift */ Emios_Pwm_Ip_SetUCRegA(base, channel, (phaseShift + counterStart)); /* Move trailing edge to keep the same duty cycle */ if (dutyCycle < (chPeriod + 1U)) { Emios_Pwm_Ip_SetUCRegB(base, channel, (((phaseShift + dutyCycle) % chPeriod) + counterStart)); } } } else { status = EMIOS_PWM_STATUS_ERROR; } SchM_Exit_Pwm_PWM_EXCLUSIVE_AREA_18(); return status; } /*FUNCTION********************************************************************** * * Function Name : Emios_Pwm_Ip_GetDeadTime * Description : Get Dead time value of waveforms in OPWMCB mode. * Implements : Emios_Pwm_Ip_GetDeadTime_Activity *END**************************************************************************/ uint16 Emios_Pwm_Ip_GetDeadTime(uint8 instance, uint8 channel) { #if (EMIOS_PWM_IP_DEV_ERROR_DETECT == STD_ON) DevAssert(EMIOS_PWM_INSTANCE_COUNT > instance); DevAssert(EMIOS_PWM_CHANNEL_COUNT > channel); #endif const Emios_Pwm_Ip_HwAddrType *const base = Emios_Pwm_Ip_aBasePtr[instance]; #if (EMIOS_PWM_IP_DEV_ERROR_DETECT == STD_ON) Emios_Pwm_Ip_PwmModeType chMode = Emios_Pwm_Ip_GetPwmMode(base, channel); DevAssert((chMode == EMIOS_PWM_MODE_OPWMCB_TRAIL_EDGE_FLAG) || (chMode == EMIOS_PWM_MODE_OPWMCB_TRAIL_EDGE_FLAG_BOTH) || (chMode == EMIOS_PWM_MODE_OPWMCB_LEAD_EDGE_FLAG) || (chMode == EMIOS_PWM_MODE_OPWMCB_LEAD_EDGE_FLAG_BOTH)); #endif /* Get the configured dead time */ return Emios_Pwm_Ip_GetUCRegB(base, channel); } /*FUNCTION********************************************************************** * * Function Name : Emios_Pwm_Ip_SetDeadTime * Description : Set Dead time value of waveforms in OPWMCB mode. New dead time should * be no greater than 0xFFFF (16 bits). * Implements : Emios_Pwm_Ip_SetDeadTime_Activity *END**************************************************************************/ void Emios_Pwm_Ip_SetDeadTime(uint8 instance, uint8 channel, uint16 newDeadTime) { #if (EMIOS_PWM_IP_DEV_ERROR_DETECT == STD_ON) DevAssert(EMIOS_PWM_INSTANCE_COUNT > instance); DevAssert(EMIOS_PWM_CHANNEL_COUNT > channel); #endif Emios_Pwm_Ip_HwAddrType *const base = Emios_Pwm_Ip_aBasePtr[instance]; #if (EMIOS_PWM_IP_DEV_ERROR_DETECT == STD_ON) Emios_Pwm_Ip_PwmModeType chMode = Emios_Pwm_Ip_GetPwmMode(base, channel); DevAssert((chMode == EMIOS_PWM_MODE_OPWMCB_TRAIL_EDGE_FLAG) || (chMode == EMIOS_PWM_MODE_OPWMCB_TRAIL_EDGE_FLAG_BOTH) || (chMode == EMIOS_PWM_MODE_OPWMCB_LEAD_EDGE_FLAG) || (chMode == EMIOS_PWM_MODE_OPWMCB_LEAD_EDGE_FLAG_BOTH)); #endif SchM_Enter_Pwm_PWM_EXCLUSIVE_AREA_19(); /* Set the new dead time */ Emios_Pwm_Ip_SetUCRegB(base, channel, newDeadTime); SchM_Exit_Pwm_PWM_EXCLUSIVE_AREA_19(); } /*FUNCTION********************************************************************** * * Function Name : Emios_Pwm_Ip_GetTriggerPlacement * Description : Get Trigger placement value in OPWMT mode * Implements : Emios_Pwm_Ip_GetTriggerPlacement_Activity *END**************************************************************************/ uint32 Emios_Pwm_Ip_GetTriggerPlacement(uint8 instance, uint8 channel) { #if (EMIOS_PWM_IP_DEV_ERROR_DETECT == STD_ON) DevAssert(EMIOS_PWM_INSTANCE_COUNT > instance); DevAssert(EMIOS_PWM_CHANNEL_COUNT > channel); #endif const Emios_Pwm_Ip_HwAddrType *const base = Emios_Pwm_Ip_aBasePtr[instance]; #if (EMIOS_PWM_IP_DEV_ERROR_DETECT == STD_ON) DevAssert(Emios_Pwm_Ip_GetPwmMode(base, channel) == EMIOS_PWM_MODE_OPWMT); #endif /* Get the configured trigger */ return Emios_Pwm_Ip_GetTrigger(base, channel); } /*FUNCTION********************************************************************** * * Function Name : Emios_Pwm_Ip_SetTriggerPlacement * Description : Set Trigger placement value in OPWMT mode. New trigger placement * should be no larger than 0xFFFFFF(24 bits). * Implements : Emios_Pwm_Ip_SetTriggerPlacement_Activity *END**************************************************************************/ void Emios_Pwm_Ip_SetTriggerPlacement(uint8 instance, uint8 channel, uint32 newTriggerPlacement) { #if (EMIOS_PWM_IP_DEV_ERROR_DETECT == STD_ON) DevAssert(EMIOS_PWM_INSTANCE_COUNT > instance); DevAssert(EMIOS_PWM_CHANNEL_COUNT > channel); #endif Emios_Pwm_Ip_HwAddrType *const base = Emios_Pwm_Ip_aBasePtr[instance]; uint8 counterStart = 0U; #if (EMIOS_PWM_IP_DEV_ERROR_DETECT == STD_ON) DevAssert(Emios_Pwm_Ip_GetPwmMode(base, channel) == EMIOS_PWM_MODE_OPWMT); /* Check selected counter bus is configured in MCB Up Mode or MC Up mode */ DevAssert((EMIOS_PWM_IP_MCB_UP_COUNTER == Emios_Pwm_Ip_GetCounterBusMode(instance, channel, Emios_Pwm_Ip_GetCounterBus(base, channel))) || (EMIOS_PWM_IP_MC_UP_COUNTER_START == Emios_Pwm_Ip_GetCounterBusMode(instance, channel, Emios_Pwm_Ip_GetCounterBus(base, channel))) || (EMIOS_PWM_IP_MC_UP_COUNTER_END == Emios_Pwm_Ip_GetCounterBusMode(instance, channel, Emios_Pwm_Ip_GetCounterBus(base, channel))) ); DevAssert((Emios_Pwm_Ip_GetCounterBusPeriod(instance, channel, Emios_Pwm_Ip_GetCounterBus(base, channel))) > newTriggerPlacement); #endif SchM_Enter_Pwm_PWM_EXCLUSIVE_AREA_20(); if (EMIOS_PWM_IP_MCB_UP_COUNTER == Emios_Pwm_Ip_GetCounterBusMode(instance, channel, Emios_Pwm_Ip_GetCounterBus(base, channel))) { counterStart = 1U; } else { counterStart = 0U; } /* Set the new trigger value */ Emios_Pwm_Ip_SetTrigger(base, channel, (uint16)(newTriggerPlacement + counterStart)); SchM_Exit_Pwm_PWM_EXCLUSIVE_AREA_20(); } /*FUNCTION********************************************************************** * * Function Name : Emios_Pwm_Ip_ChannelEnterDebugMode * Description : To set a channel enters freeze state, should be setting * Emios_Pwm_Ip_AllowEnterDebugMode first. * Implements : Emios_Pwm_Ip_ChannelEnterDebugMode_Activity *END**************************************************************************/ Emios_Pwm_Ip_StatusType Emios_Pwm_Ip_ChannelEnterDebugMode(uint8 instance, uint8 channel) { #if (EMIOS_PWM_IP_DEV_ERROR_DETECT == STD_ON) DevAssert(EMIOS_PWM_INSTANCE_COUNT > instance); DevAssert(EMIOS_PWM_CHANNEL_COUNT > channel); #endif Emios_Pwm_Ip_HwAddrType *const base = Emios_Pwm_Ip_aBasePtr[instance]; Emios_Pwm_Ip_StatusType ret = EMIOS_PWM_STATUS_SUCCESS; SchM_Enter_Pwm_PWM_EXCLUSIVE_AREA_21(); if (Emios_Pwm_Ip_GetDebugMode(base) == TRUE) { Emios_Pwm_Ip_SetFreezeEnable(base, channel, TRUE); } else { ret = EMIOS_PWM_STATUS_GLOBAL_FREEZE_DISABLED; } SchM_Exit_Pwm_PWM_EXCLUSIVE_AREA_21(); return ret; } /*FUNCTION********************************************************************** * * Function Name : Emios_Pwm_Ip_ChannelStopDebugMode * Description : Release a channel from freeze state * Implements : Emios_Pwm_Ip_ChannelStopDebugMode_Activity *END**************************************************************************/ void Emios_Pwm_Ip_ChannelStopDebugMode(uint8 instance, uint8 channel) { #if (EMIOS_PWM_IP_DEV_ERROR_DETECT == STD_ON) DevAssert(EMIOS_PWM_INSTANCE_COUNT > instance); DevAssert(EMIOS_PWM_CHANNEL_COUNT > channel); #endif Emios_Pwm_Ip_HwAddrType *const base = Emios_Pwm_Ip_aBasePtr[instance]; SchM_Enter_Pwm_PWM_EXCLUSIVE_AREA_22(); Emios_Pwm_Ip_SetFreezeEnable(base, channel, FALSE); SchM_Exit_Pwm_PWM_EXCLUSIVE_AREA_22(); } /*FUNCTION********************************************************************** * * Function Name : Emios_Pwm_Ip_GetFlagRequest * Description : Configure what the FLAG event should do. Generate Interrupt request, * Generate DMA request or do nothing. * Implements : Emios_Pwm_Ip_GetFlagRequest_Activity *END**************************************************************************/ Emios_Pwm_Ip_InterruptType Emios_Pwm_Ip_GetFlagRequest(uint8 instance, uint8 channel) { #if (EMIOS_PWM_IP_DEV_ERROR_DETECT == STD_ON) DevAssert(EMIOS_PWM_INSTANCE_COUNT > instance); DevAssert(EMIOS_PWM_CHANNEL_COUNT > channel); #endif const Emios_Pwm_Ip_HwAddrType *const base = Emios_Pwm_Ip_aBasePtr[instance]; Emios_Pwm_Ip_InterruptType eventType = EMIOS_PWM_NOTIFICATION_DISABLED; if (Emios_Pwm_Ip_GetInterruptRequest(base, channel) == TRUE) { if (Emios_Pwm_Ip_GetDMARequest(base, channel) == TRUE) { eventType = EMIOS_PWM_DMA_REQUEST; } else { eventType = EMIOS_PWM_INTERRUPT_REQUEST; } } return eventType; } /*FUNCTION********************************************************************** * * Function Name : Emios_Pwm_Ip_SetFlagRequest * Description : Configure what the FLAG event should do. Generate Interrupt request, * Generate DMA request or do nothing. * Implements : Emios_Pwm_Ip_SetFlagRequest_Activity *END**************************************************************************/ void Emios_Pwm_Ip_SetFlagRequest(uint8 instance, uint8 channel, Emios_Pwm_Ip_InterruptType event) { #if (EMIOS_PWM_IP_DEV_ERROR_DETECT == STD_ON) DevAssert(EMIOS_PWM_INSTANCE_COUNT > instance); DevAssert(EMIOS_PWM_CHANNEL_COUNT > channel); #endif Emios_Pwm_Ip_HwAddrType *const base = Emios_Pwm_Ip_aBasePtr[instance]; SchM_Enter_Pwm_PWM_EXCLUSIVE_AREA_23(); /* Clear Interrupt flag */ Emios_Pwm_Ip_ClearFlagEvent(base, channel); switch (event) { case EMIOS_PWM_INTERRUPT_REQUEST: if ((uint8)0U == Emios_Pwm_Ip_aNotif[instance][channel]) { Emios_Pwm_Ip_SetInterruptRequest(base, channel, TRUE); Emios_Pwm_Ip_SetDMARequest(base, channel, FALSE); Emios_Pwm_Ip_aCheckEnableNotif[instance][channel] = (uint8)1U; } break; case EMIOS_PWM_DMA_REQUEST: Emios_Pwm_Ip_SetInterruptRequest(base, channel, TRUE); Emios_Pwm_Ip_SetDMARequest(base, channel, TRUE); break; case EMIOS_PWM_NOTIFICATION_DISABLED: Emios_Pwm_Ip_SetInterruptRequest(base, channel, FALSE); Emios_Pwm_Ip_SetDMARequest(base, channel, FALSE); Emios_Pwm_Ip_aCheckEnableNotif[instance][channel] = (uint8)0U; break; default: /*Nothig to do. All cases are treated. */ break; } SchM_Exit_Pwm_PWM_EXCLUSIVE_AREA_23(); } /*FUNCTION********************************************************************** * * Function Name : Emios_Pwm_Ip_GetOutputState * Description : Get the Unified Channel output pin logic level * * Implements : Emios_Pwm_Ip_GetOutputState_Activity *END**************************************************************************/ Emios_Pwm_Ip_OutputStateType Emios_Pwm_Ip_GetOutputState(uint8 instance, uint8 channel) { #if (EMIOS_PWM_IP_DEV_ERROR_DETECT == STD_ON) DevAssert(EMIOS_PWM_INSTANCE_COUNT > instance); DevAssert(EMIOS_PWM_CHANNEL_COUNT > channel); #endif const Emios_Pwm_Ip_HwAddrType *const base = Emios_Pwm_Ip_aBasePtr[instance]; return (Emios_Pwm_Ip_GetOutputPinState(base, channel) == FALSE)? EMIOS_PWM_OUTPUT_STATE_LOW : EMIOS_PWM_OUTPUT_STATE_HIGH; } /*FUNCTION********************************************************************** * * Function Name : Emios_Pwm_Ip_SetOutputState * Description : Set the state of output pin * * *END**************************************************************************/ void Emios_Pwm_Ip_SetOutputState(uint8 instance, uint8 channel, Emios_Pwm_Ip_OutputStateType outputState) { #if (EMIOS_PWM_IP_DEV_ERROR_DETECT == STD_ON) DevAssert(EMIOS_PWM_INSTANCE_COUNT > instance); DevAssert(EMIOS_PWM_CHANNEL_COUNT > channel); #endif Emios_Pwm_Ip_HwAddrType *const base = Emios_Pwm_Ip_aBasePtr[instance]; SchM_Enter_Pwm_PWM_EXCLUSIVE_AREA_24(); /* Set output pin polarity */ if (EMIOS_PWM_OUTPUT_STATE_LOW == outputState) { Emios_Pwm_Ip_SetEdgePolarity(base, channel, (Emios_Pwm_Ip_PolarityType)EMIOS_PWM_ACTIVE_LOW); } else { Emios_Pwm_Ip_SetEdgePolarity(base, channel, (Emios_Pwm_Ip_PolarityType)EMIOS_PWM_ACTIVE_HIGH); } /* Enter GPIO output mode */ Emios_Pwm_Ip_SetPwmMode(base, channel, (Emios_Pwm_Ip_PwmModeType)EMIOS_PWM_MODE_GPO); /* Disable channel interrupts */ Emios_Pwm_Ip_SetInterruptRequest(base, channel, (boolean)FALSE); /* Clear pending interrupt flag for the channel */ Emios_Pwm_Ip_ClearFlagEvent(base, channel); SchM_Exit_Pwm_PWM_EXCLUSIVE_AREA_24(); } /*FUNCTION********************************************************************** * * Function Name : Emios_Pwm_Ip_SetOutputToNormal * Description : Set the polarity and mode for current channel as normal * * *END**************************************************************************/ void Emios_Pwm_Ip_SetOutputToNormal(uint8 instance, uint8 channel, uint16 dutyPercent, Emios_Pwm_Ip_PolarityType polarity, Emios_Pwm_Ip_PwmModeType mode) { #if (EMIOS_PWM_IP_DEV_ERROR_DETECT == STD_ON) DevAssert(EMIOS_PWM_INSTANCE_COUNT > instance); DevAssert(EMIOS_PWM_CHANNEL_COUNT > channel); #endif Emios_Pwm_Ip_HwAddrType *const base = Emios_Pwm_Ip_aBasePtr[instance]; SchM_Enter_Pwm_PWM_EXCLUSIVE_AREA_25(); if (EMIOS_PWM_MODE_GPO == Emios_Pwm_Ip_GetPwmMode(base, channel)) { if ((mode == EMIOS_PWM_MODE_OPWFMB_FLAG) || (mode == EMIOS_PWM_MODE_OPWFMB_FLAG_BOTH)) { Emios_Pwm_Ip_SetPwmMode(base, channel, mode); Emios_Pwm_Ip_SetEdgePolarity(base, channel,(polarity == EMIOS_PWM_ACTIVE_HIGH) ? EMIOS_PWM_ACTIVE_LOW : EMIOS_PWM_ACTIVE_HIGH ); } else if((mode == EMIOS_PWM_MODE_OPWMB_FLAG) || (mode == EMIOS_PWM_MODE_OPWMB_FLAG_BOTH)) { Emios_Pwm_Ip_SetPwmMode(base, channel, mode); Emios_Pwm_Ip_SetEdgePolarity(base, channel, polarity); } else { /* To avoid spike pulse If duty cycle = 100%, when enter mode, EDPOL bit get complement of polarity after that, EDPOL bit is restored valid value */ if(dutyPercent == 0x8000U) { Emios_Pwm_Ip_SetPwmModePol(base, channel,mode, (polarity == EMIOS_PWM_ACTIVE_HIGH) ? EMIOS_PWM_ACTIVE_LOW : EMIOS_PWM_ACTIVE_HIGH); Emios_Pwm_Ip_SetEdgePolarity(base, channel, polarity); } else { Emios_Pwm_Ip_SetPwmModePol(base, channel,mode, polarity); } } } else { /*Do Nothing*/ (void)polarity; (void)mode; } SchM_Exit_Pwm_PWM_EXCLUSIVE_AREA_25(); } /*FUNCTION********************************************************************** * * Function Name : Emios_Pwm_Ip_GetChannelMode * Description : Get mode of operation of the Unified Channel * *END**************************************************************************/ Emios_Pwm_Ip_PwmModeType Emios_Pwm_Ip_GetChannelMode(uint8 instance, uint8 channel) { #if (EMIOS_PWM_IP_DEV_ERROR_DETECT == STD_ON) DevAssert(EMIOS_PWM_INSTANCE_COUNT > instance); DevAssert(EMIOS_PWM_CHANNEL_COUNT > channel); #endif const Emios_Pwm_Ip_HwAddrType *const base = Emios_Pwm_Ip_aBasePtr[instance]; Emios_Pwm_Ip_PwmModeType channelMode = Emios_Pwm_Ip_GetPwmMode(base, channel); return channelMode; } /** * @brief Get master bus channel * * @param[in] instance The eMIOS group id * @param[in] channel The channel in this eMIOS group * @return Emios_Pwm_Ip_PwmModeType */ uint8 Emios_Pwm_Ip_GetMasterBusChannel(uint8 instance, uint8 channel) { #if (EMIOS_PWM_IP_DEV_ERROR_DETECT == STD_ON) DevAssert(EMIOS_PWM_INSTANCE_COUNT > instance); DevAssert(EMIOS_PWM_CHANNEL_COUNT > channel); #endif const Emios_Pwm_Ip_HwAddrType *const base = Emios_Pwm_Ip_aBasePtr[instance]; uint8 channelMaster = channel; Emios_Pwm_Ip_CounterBusSourceType counterBus = Emios_Pwm_Ip_GetCounterBus(base, channel); switch (counterBus) { case EMIOS_PWM_BUS_A: channelMaster = 23U; break; case EMIOS_PWM_BUS_F: channelMaster = 22U; break; case EMIOS_PWM_BUS_BCDE: channelMaster = (uint8)((channel >> 3U) * 8U); break; default: /* Internal bus is used */ channelMaster = channel; break; } return channelMaster; } /*FUNCTION********************************************************************** * * Function Name : Emios_Pwm_Ip_SetPreEnableClock * Description : Set Prescaler Enable bit. * *END**************************************************************************/ void Emios_Pwm_Ip_SetPreEnableClock(uint8 instance, uint8 channel, boolean value) { #if (EMIOS_PWM_IP_DEV_ERROR_DETECT == STD_ON) DevAssert(EMIOS_PWM_INSTANCE_COUNT > instance); DevAssert(EMIOS_PWM_CHANNEL_COUNT > channel); #endif Emios_Pwm_Ip_HwAddrType *const base = Emios_Pwm_Ip_aBasePtr[instance]; SchM_Enter_Pwm_PWM_EXCLUSIVE_AREA_26(); /* Set Prescaler Enable bit. */ Emios_Pwm_Ip_SetPrescalerEnable(base, channel, value); SchM_Exit_Pwm_PWM_EXCLUSIVE_AREA_26(); } /*FUNCTION********************************************************************** * * Function Name : Emios_Pwm_Ip_SetBusSelected * Description : Set Bus Select bits. * *END**************************************************************************/ void Emios_Pwm_Ip_SetBusSelected(uint8 instance, uint8 channel, Emios_Pwm_Ip_CounterBusSourceType value) { #if (EMIOS_PWM_IP_DEV_ERROR_DETECT == STD_ON) DevAssert(EMIOS_PWM_INSTANCE_COUNT > instance); DevAssert(EMIOS_PWM_CHANNEL_COUNT > channel); #endif Emios_Pwm_Ip_HwAddrType *const base = Emios_Pwm_Ip_aBasePtr[instance]; SchM_Enter_Pwm_PWM_EXCLUSIVE_AREA_27(); /* Set Bus Select bits.*/ Emios_Pwm_Ip_SetCounterBus(base, channel, value); SchM_Exit_Pwm_PWM_EXCLUSIVE_AREA_27(); } /*FUNCTION********************************************************************** * * Function Name : Emios_Pwm_Ip_SetClockPs * Description : This function set the value of the prescaler on eMios channels * *END**************************************************************************/ void Emios_Pwm_Ip_SetClockPs(uint8 instance, uint8 channel, Emios_Pwm_Ip_InternalClkPsType value) { #if (EMIOS_PWM_IP_DEV_ERROR_DETECT == STD_ON) DevAssert(EMIOS_PWM_INSTANCE_COUNT > instance); DevAssert(EMIOS_PWM_CHANNEL_COUNT > channel); #endif Emios_Pwm_Ip_HwAddrType *const base = Emios_Pwm_Ip_aBasePtr[instance]; SchM_Enter_Pwm_PWM_EXCLUSIVE_AREA_28(); /* Stop eMios channel - this will stop the internal counter */ Emios_Pwm_Ip_SetPrescalerEnable(base, channel, FALSE); /*Set Extended Prescaler bits */ Emios_Pwm_Ip_SetExtendedPrescaler(base, channel, value); /* Re-start eMios channel */ Emios_Pwm_Ip_SetPrescalerEnable(base, channel, TRUE); SchM_Exit_Pwm_PWM_EXCLUSIVE_AREA_28(); } /*FUNCTION********************************************************************** * * Function Name : Emios_Pwm_Ip_ComparatorTransferEnable * Description : The function shall enable the output update for the corresponding channel. * *END**************************************************************************/ void Emios_Pwm_Ip_ComparatorTransferEnable(uint8 instance, uint32 channelMask) { #if (EMIOS_PWM_IP_DEV_ERROR_DETECT == STD_ON) DevAssert(EMIOS_PWM_INSTANCE_COUNT > instance); #endif SchM_Enter_Pwm_PWM_EXCLUSIVE_AREA_29(); /* Enable the output update for the corresponding channel.*/ Emios_Mcl_Ip_ComparatorTransferEnable(instance, channelMask); SchM_Exit_Pwm_PWM_EXCLUSIVE_AREA_29(); } /*FUNCTION********************************************************************** * * Function Name : Emios_Pwm_Ip_ComparatorTransferDisable * Description : The function shall disable the output update for the corresponding channel. * *END**************************************************************************/ void Emios_Pwm_Ip_ComparatorTransferDisable(uint8 instance, uint32 channelMask) { #if (EMIOS_PWM_IP_DEV_ERROR_DETECT == STD_ON) DevAssert(EMIOS_PWM_INSTANCE_COUNT > instance); #endif SchM_Enter_Pwm_PWM_EXCLUSIVE_AREA_30(); /* Disable the output update for the corresponding channel.*/ Emios_Mcl_Ip_ComparatorTransferDisable(instance, channelMask); SchM_Exit_Pwm_PWM_EXCLUSIVE_AREA_30(); } /*FUNCTION********************************************************************** * * Function Name : Emios_Pwm_Ip_SyncUpdate * Description : This function updates the duty cycle and-or period for the specified PWM channel. * The value written does not take effect until calling SyncUpdate API. * *END**************************************************************************/ void Emios_Pwm_Ip_SyncUpdate(uint8 instance) { #if (EMIOS_PWM_IP_DEV_ERROR_DETECT == STD_ON) DevAssert(EMIOS_PWM_INSTANCE_COUNT > instance); #endif Emios_Pwm_Ip_HwAddrType *const base = Emios_Pwm_Ip_aBasePtr[instance]; /* Read OUDIS register */ uint32 oudisRegVal = (uint32)Emios_Pwm_Ip_GetOutputUpdateInstance(base); /* the mask of channels */ uint32 channelMask = (uint32)0U; /* Store the mode of channel */ Emios_Pwm_Ip_PwmModeType chMode; uint8 oudisDisable = 0U; uint8 channelId; /* Loop all channels available on each Emios instance */ for (channelId = 0U; channelId < EMIOS_PWM_CHANNEL_COUNT; channelId++) { oudisDisable = (uint8)((oudisRegVal & (uint32)((uint32)1U << channelId)) >> channelId); if (((uint8)0U != Emios_Pwm_Ip_aCheckState[instance][channelId]) && ((uint8)1U == oudisDisable)) { chMode = Emios_Pwm_Ip_GetPwmMode(base, channelId); /* This statement is required to avoid limitation of 0% duty cycle (if call 100% to 0%) */ if(1U == Emios_Pwm_Ip_GetUCRegA(base, channelId)) { if((chMode == EMIOS_PWM_MODE_OPWMCB_TRAIL_EDGE_FLAG) || (chMode == EMIOS_PWM_MODE_OPWMCB_TRAIL_EDGE_FLAG_BOTH)) { /* Enable the output update for the corresponding channel.*/ Emios_Mcl_Ip_ComparatorTransferEnable(instance, (uint32)((uint32)1U << channelId)); Emios_Pwm_Ip_SetForceMatchB(base, channelId, TRUE); } else if ((chMode == EMIOS_PWM_MODE_OPWMCB_LEAD_EDGE_FLAG) || (chMode == EMIOS_PWM_MODE_OPWMCB_LEAD_EDGE_FLAG_BOTH)) { /* Enable the output update for the corresponding channel.*/ Emios_Mcl_Ip_ComparatorTransferEnable(instance, (uint32)((uint32)1U << channelId)); Emios_Pwm_Ip_SetForceMatchA(base, channelId, TRUE); } else { /* Do Nothing */ } } /* Update OUDIS register value for synchronization */ channelMask |= (uint32)((uint32)1U << channelId); } } /* Write OUDIS register */ Emios_Mcl_Ip_ComparatorTransferEnable(instance, channelMask); } #define PWM_STOP_SEC_CODE #include "Pwm_MemMap.h" #ifdef __cplusplus } #endif /** @} */