Hi
I 'm verify AM243x EPWM function by using demo code epwm_duty_cycle_am243x-lp_r5fss0-0_freertos_ti-arm-clang in SDK8.3
When I look into TRM, it shows the maximum TBCLK = FICLK and FICLK = Main_SYS_CLK0/2 = 400MHz.


However, I found SDK setting FICLK is only set to 250MHZ. I try to generate 100KHz waveform by using FICLK=250Mhz and FICLK=400MHz. I got wrong the waveform (frequency) by using FICLK=400MHz
Please refer to following two pictures:
FICLK=250MHZ
FICLK=400MHz
The only change in these two codes is
Please refer to source code
/*
* Copyright (C) 2021 Texas Instruments Incorporated
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the
* distribution.
*
* Neither the name of Texas Instruments Incorporated nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <kernel/dpl/DebugP.h>
#include <kernel/dpl/AddrTranslateP.h>
#include <kernel/dpl/SemaphoreP.h>
#include <kernel/dpl/HwiP.h>
#include <drivers/epwm.h>
#include "ti_drivers_config.h"
#include "ti_drivers_open_close.h"
#include "ti_board_open_close.h"
/*
* This example uses the ePWM module to generate a signal for a specified time
* and with a specified duty cycle.
*
* The default parameters are : Frequency : 1kHz, Duty cycle : 25%,
* App run time : 60s (time for which signal is generated). All these parameters
* are configurable.
*
* In this example ePWM0 is used to generate the signal, the user can also
* select a different one.
*
* This example also showcases how to configure and use the ePWM module.
*/
/* Output channel - A or B */
#define APP_EPWM_OUTPUT_CH (EPWM_OUTPUT_CH_A)
/* Duty Cycle of PWM output signal in % - give value from 0 to 100 */
#define APP_EPWM_DUTY_CYCLE (25U)
/* Frequency of PWM output signal in Hz - 1 KHz is selected */
#define APP_EPWM_OUTPUT_FREQ (100U*1000U)
/* APP run time in seconds */
#define APP_EPWM_RUN_TIME (60U)
/* TB frequency in Hz - so that /4 divider is used */
//#define APP_EPWM_TB_FREQ (CONFIG_EPWM0_FCLK / 1U)
#define APP_EPWM_TB_FREQ (400000000)
/*
* PRD value - this determines the period
* PRD = (TBCLK/PWM FREQ) / 2
* /2 is added becasue up&down counter is selected. So period is 2 times
*/
#define APP_EPWM_PRD_VAL ((APP_EPWM_TB_FREQ / APP_EPWM_OUTPUT_FREQ) / 2U)
/*
* COMPA value - this determines the duty cycle
* COMPA = (PRD - ((dutycycle * PRD) / 100)
*/
#define APP_EPWM_COMPA_VAL (APP_EPWM_PRD_VAL - ((APP_EPWM_DUTY_CYCLE * \
APP_EPWM_PRD_VAL) / 100U))
/* Global variables and objects */
static HwiP_Object gEpwmHwiObject;
static SemaphoreP_Object gEpwmSyncSemObject;
/* Function Prototypes */
static void App_epwmIntrISR(void *handle);
static void App_epwmConfig(uint32_t epwmBaseAddr,
uint32_t epwmCh,
uint32_t epwmFuncClk);
/* variable to hold base address of EPWM that is used */
uint32_t gEpwmBaseAddr;
void epwm_duty_cycle_main(void *args)
{
int32_t status;
uint32_t numIsrCnt = (APP_EPWM_RUN_TIME * APP_EPWM_OUTPUT_FREQ);
HwiP_Params hwiPrms;
/* Open drivers to open the UART driver for console */
Drivers_open();
Board_driversOpen();
DebugP_log("EPWM Duty Cycle Test Started ...\r\n");
DebugP_log("Please refer EXAMPLES_DRIVERS_EPWM_DUTY_CYCLE example user \
guide for the test setup to probe EPWM signal. \r\n");
DebugP_log("App will wait for 60 seconds (using PWM period ISR) ...\r\n");
/* Address translate */
gEpwmBaseAddr = (uint32_t)AddrTranslateP_getLocalAddr(CONFIG_EPWM0_BASE_ADDR);
status = SemaphoreP_constructCounting(&gEpwmSyncSemObject, 0, numIsrCnt);
DebugP_assert(SystemP_SUCCESS == status);
/* Register & enable interrupt */
HwiP_Params_init(&hwiPrms);
hwiPrms.intNum = CONFIG_EPWM0_INTR;
hwiPrms.callback = &App_epwmIntrISR;
hwiPrms.isPulse = CONFIG_EPWM0_INTR_IS_PULSE;
status = HwiP_construct(&gEpwmHwiObject, &hwiPrms);
DebugP_assert(status == SystemP_SUCCESS);
/* Configure PWM */
App_epwmConfig(gEpwmBaseAddr, APP_EPWM_OUTPUT_CH, CONFIG_EPWM0_FCLK);
while(numIsrCnt > 0)
{
SemaphoreP_pend(&gEpwmSyncSemObject, SystemP_WAIT_FOREVER);
numIsrCnt--;
}
while(1);
EPWM_etIntrDisable(gEpwmBaseAddr);
EPWM_etIntrClear(gEpwmBaseAddr); /* Clear any pending interrupts if any */
HwiP_destruct(&gEpwmHwiObject);
SemaphoreP_destruct(&gEpwmSyncSemObject);
DebugP_log("EPWM Duty Cycle Test Passed!!\r\n");
DebugP_log("All tests have passed!!\r\n");
Board_driversClose();
Drivers_close();
}
static void App_epwmIntrISR(void *handle)
{
volatile uint16_t status;
status = EPWM_etIntrStatus(gEpwmBaseAddr);
if(status & EPWM_ETFLG_INT_MASK)
{
SemaphoreP_post(&gEpwmSyncSemObject);
EPWM_etIntrClear(gEpwmBaseAddr);
}
return;
}
static void App_epwmConfig(uint32_t epwmBaseAddr,
uint32_t epwmCh,
uint32_t epwmFuncClk)
{
EPWM_AqActionCfg aqConfig;
/* Configure Time base submodule */
EPWM_tbTimebaseClkCfg(epwmBaseAddr, APP_EPWM_TB_FREQ, epwmFuncClk);
EPWM_tbPwmFreqCfg(epwmBaseAddr, APP_EPWM_TB_FREQ, APP_EPWM_OUTPUT_FREQ,
EPWM_TB_COUNTER_DIR_UP_DOWN,
EPWM_SHADOW_REG_CTRL_ENABLE);
EPWM_tbSyncDisable(epwmBaseAddr);
EPWM_tbSetSyncOutMode(epwmBaseAddr, EPWM_TB_SYNC_OUT_EVT_SYNCIN);
EPWM_tbSetEmulationMode(epwmBaseAddr, EPWM_TB_EMU_MODE_FREE_RUN);
/* Configure counter compare submodule */
EPWM_counterComparatorCfg(epwmBaseAddr, EPWM_CC_CMP_A,
APP_EPWM_COMPA_VAL, EPWM_SHADOW_REG_CTRL_ENABLE,
EPWM_CC_CMP_LOAD_MODE_CNT_EQ_ZERO, TRUE);
EPWM_counterComparatorCfg(epwmBaseAddr, EPWM_CC_CMP_B,
APP_EPWM_COMPA_VAL, EPWM_SHADOW_REG_CTRL_ENABLE,
EPWM_CC_CMP_LOAD_MODE_CNT_EQ_ZERO, TRUE);
/* Configure Action Qualifier Submodule */
aqConfig.zeroAction = EPWM_AQ_ACTION_DONOTHING;
aqConfig.prdAction = EPWM_AQ_ACTION_DONOTHING;
aqConfig.cmpAUpAction = EPWM_AQ_ACTION_HIGH;
aqConfig.cmpADownAction = EPWM_AQ_ACTION_LOW;
aqConfig.cmpBUpAction = EPWM_AQ_ACTION_HIGH;
aqConfig.cmpBDownAction = EPWM_AQ_ACTION_LOW;
EPWM_aqActionOnOutputCfg(epwmBaseAddr, epwmCh, &aqConfig);
/* Configure Dead Band Submodule */
EPWM_deadbandBypass(epwmBaseAddr);
/* Configure Chopper Submodule */
EPWM_chopperEnable(epwmBaseAddr, FALSE);
/* Configure trip zone Submodule */
EPWM_tzTripEventDisable(epwmBaseAddr, EPWM_TZ_EVENT_ONE_SHOT, 0U);
EPWM_tzTripEventDisable(epwmBaseAddr, EPWM_TZ_EVENT_CYCLE_BY_CYCLE, 0U);
/* Configure event trigger Submodule */
EPWM_etIntrCfg(epwmBaseAddr, EPWM_ET_INTR_EVT_CNT_EQ_ZRO,
EPWM_ET_INTR_PERIOD_FIRST_EVT);
EPWM_etIntrEnable(epwmBaseAddr);
}
I would like to get confirm what is the maximum value of FICLK? or any limitation is EPWM resolution?
Regards
Andre
