ADM/GW/RTD/src/Emios_Pwm_Ip.c
2024-08-08 10:00:15 +09:00

2156 lines
93 KiB
C

/*==================================================================================================
* 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
/** @} */