Part Number: AM2431
Other Parts Discussed in Thread: SYSCONFIG
Tool/software:
Hi,
I am trying to use SDDF based on single_chip_servo_am243x-lp_r5fss0-0_nortos of motor control SDK.
In the example, the SDDF is ICSSG0 and PRU0. And on my board it is ICSSG1 PRU1, the chip is AM2431-ALV.
So the issue is that gSddfChSamps stays 0 and rtuSddfIrqHandler is never triggered after the initialization.
The modification is as follows,
1. mclk_iep_sync.c
/*
* Copyright (C) 2023 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 EXPgResS 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 "stdint.h"
#include "math.h"
#include "stdio.h"
#include <drivers/pruicss.h>
#include <drivers/hw_include/hw_types.h>
#include <drivers/hw_include/cslr_soc.h>
#define USED_IEP_BASE CSL_PRU_ICSSG1_IEP0_BASE
void init_IEP0_SYNC(void)
{
#if 0 // FL: move to R5
// ************************************* padconfig *************************************
// unlock PADMMR config register
// partition 0
HW_WR_REG32(0x000f1008, 0x68EF3490); // Kick 0
HW_WR_REG32(0x000f100C, 0xD172BC5A); // Kick 1
// partition 1
HW_WR_REG32(0x000f5008, 0x68EF3490); // Kick 0
HW_WR_REG32(0x000f500C, 0xD172BC5A); // Kick 1
// ICSS_G0
// IEP SYNC0 -> BP.45
HW_WR_REG32(0x000F41AC, 0x00010000 + 2); // mode 2 = SYNC0
// IEP SYNC1 -> BP.18
HW_WR_REG32(0x000F41A4, 0x00010000 + 2); // mode 2 = SYNC1
#endif
#if 0 // FL: move to R5
// ************************************* clock config **********************************
// core clock options:
// ICSSG0_CLKMUX_SEL: bit 0 = 1 PLL0, bit 0 = 0 PLL2
// MAIN_PLL0_HSDIV9: 2 (333 MHz), 3 (250 MHz)
// MAIN_PLL2_HSDIV2: 5 (300 MHz), 7 (225 MHz)
// ICSSG_CFG: iep_clk to follow core clock
//
// iep clock options
// ICSSG0_CLKMUX_SEL: bit 16-17:
// 0h - MAIN_PLL2_HSDIV5_CLKOUT
// 1h - MAIN_PLL0_HSDIV6_CLKOUT
// 7h - SYSCLK0 (500 MHz) - not recommended!!!
// recommend to run both clocks from same PLL0
// e.g. PLL0 iep_clk = 500 MHz, core_clock = 333 MHz
// configure ICSS clocks
// unlock CTRLMMR config register
// partition 2
HW_WR_REG32(0x43009008, 0x68EF3490 ); // Kick 0
HW_WR_REG32(0x4300900c, 0xD172BC5A ); // Kick 1
// ICSS_G1_CLKMUX_SEL:
// 1h - MAIN_PLL0_HSDIV9_CLKOUT,
HW_WR_REG32(0x43008044, 0x00000001 ); // Kick 1
/* .if(0)
; run iep_clk with core clock
ldi32 r2, 0x00026030
ldi32 r3, 0x00000001
sbbo &r3, r2, 0, 4
.endif
*/
// unlock PLL0 ctrl register
HW_WR_REG32(0x00680010, 0x68EF3490 ); // Kick 0
HW_WR_REG32(0x00680014, 0xD172BC5A ); // Kick 1
// set MAIN_PLL0_HSDIV9 to 2 for core_clock =333MHz (3 for 250 MHz)
HW_WR_REG8(0x006800a4, 2);
// set MAIN_PLL0_HSDIV6_CLKOUT iep_clock from PLL0 (1 = 500 MHz, 2 = 333 MHz, 3 = 250 MHz)
HW_WR_REG8(0x00680098, 2);
// unlock PLL2 ctrl register
HW_WR_REG32(0x00682010, 0x68EF3490 ); // Kick 0
HW_WR_REG32(0x00682014, 0xD172BC5A ); // Kick 1
// set core clock MAIN_PLL2_HSDIV0 to 5 for 300 MHz (7 for 225 MHz, 5 for 300 MHz)
HW_WR_REG8(0x00682080, 5);
// set MAIN_PLL2_HSDIV5_CLKOUT iep_clock from PLL2 (5= 300 MHz)
HW_WR_REG8(0x00682094, 5);
#endif
// ************************************* iep config **********************************
#if 0 // FL: PRU code
// reset iep0 timer
HW_WR_REG8(CSL_ICSS_G_PR1_IEP0_SLV_REGS_BASE+CSL_ICSS_G_PR1_IEP0_SLV_GLOBAL_CFG_REG, 0x20);
HW_WR_REG32(CSL_ICSS_G_PR1_IEP0_SLV_REGS_BASE+CSL_ICSS_G_PR1_IEP0_SLV_COUNT_REG0, 0xffffffff);
HW_WR_REG32(CSL_ICSS_G_PR1_IEP0_SLV_REGS_BASE+CSL_ICSS_G_PR1_IEP0_SLV_COUNT_REG1, 0xffffffff);
// set CMP0 period - 64 kHZ 15625 ns, - cycle as we start from 0
HW_WR_REG32(CSL_ICSS_G_PR1_IEP0_SLV_REGS_BASE+CSL_ICSS_G_PR1_IEP0_SLV_CMP0_REG0, 15625-3);
HW_WR_REG32(CSL_ICSS_G_PR1_IEP0_SLV_REGS_BASE+CSL_ICSS_G_PR1_IEP0_SLV_CMP0_REG1, 15625-3);
// set CMP1 period - SYNC01 trigger
HW_WR_REG32(CSL_ICSS_G_PR1_IEP0_SLV_REGS_BASE+CSL_ICSS_G_PR1_IEP0_SLV_CMP1_REG0, 99);
// set CMP2 period - SYNC1 trigger - with 6 ns delay - only used in independent mode
HW_WR_REG32(CSL_ICSS_G_PR1_IEP0_SLV_REGS_BASE+CSL_ICSS_G_PR1_IEP0_SLV_CMP2_REG0, 99);
// Set sync ctrl register: SYNC1 dependent, cyclic generation , SYNC0 and SYNC1 enable, SYNC enable
HW_WR_REG32(CSL_ICSS_G_PR1_IEP0_SLV_REGS_BASE+CSL_ICSS_G_PR1_IEP0_SLV_SYNC_CTRL_REG, 0x00A7);
// Set SYNC0/1 high pulse time in iep clok cycles ( 7 clocks for 20 MHz at 300 MHz iep clk)
HW_WR_REG32(CSL_ICSS_G_PR1_IEP0_SLV_REGS_BASE+CSL_ICSS_G_PR1_IEP0_SLV_SYNC_PWIDTH_REG, 0x0006);
// Set SYNC0/1 period ( 15 clocks for 20 MHz at 300 MHz iep clk)
HW_WR_REG32(CSL_ICSS_G_PR1_IEP0_SLV_REGS_BASE+CSL_ICSS_G_PR1_IEP0_SLV_SYNC0_PERIOD_REG, 14);
// Set delay between SYNC0 and SYNC1 in clock cycles 2 = 3 clock cycles
HW_WR_REG32(CSL_ICSS_G_PR1_IEP0_SLV_REGS_BASE+CSL_ICSS_G_PR1_IEP0_SLV_SYNC1_DELAY_REG, 2);
// Set offset from cpm1 hit
HW_WR_REG32(CSL_ICSS_G_PR1_IEP0_SLV_REGS_BASE+CSL_ICSS_G_PR1_IEP0_SLV_SYNC_START_REG, 0);
// set enable cmp1 and cmp2 for sync start trigger generation
HW_WR_REG32(CSL_ICSS_G_PR1_IEP0_SLV_REGS_BASE+CSL_ICSS_G_PR1_IEP0_SLV_CMP_CFG_REG, 0x000000c);
// set enable cmp1 and cmp2 for sync start trigger generation
HW_WR_REG32(CSL_ICSS_G_PR1_IEP0_SLV_REGS_BASE+CSL_ICSS_G_PR1_IEP0_SLV_CMP_CFG_REG, 0x000000c);
// start iep0_timer - increment by 1 , start
HW_WR_REG8(CSL_ICSS_G_PR1_IEP0_SLV_REGS_BASE+CSL_ICSS_G_PR1_IEP0_SLV_GLOBAL_CFG_REG, 0x0111);
#endif
// reset iep0 timer
HW_WR_REG8(USED_IEP_BASE+CSL_ICSS_G_PR1_IEP0_SLV_GLOBAL_CFG_REG, 0x20);
HW_WR_REG32(USED_IEP_BASE+CSL_ICSS_G_PR1_IEP0_SLV_COUNT_REG0, 0xffffffff);
HW_WR_REG32(USED_IEP_BASE+CSL_ICSS_G_PR1_IEP0_SLV_COUNT_REG1, 0xffffffff);
// set CMP0 period - 64 kHZ 15625 ns, - cycle as we start from 0
HW_WR_REG32(USED_IEP_BASE+CSL_ICSS_G_PR1_IEP0_SLV_CMP0_REG0, 15625-3);
HW_WR_REG32(USED_IEP_BASE+CSL_ICSS_G_PR1_IEP0_SLV_CMP0_REG1, 15625-3);
// set CMP1 period - SYNC01 trigger
HW_WR_REG32(USED_IEP_BASE+CSL_ICSS_G_PR1_IEP0_SLV_CMP1_REG0, 99);
// set CMP2 period - SYNC1 trigger - with 6 ns delay - only used in independent mode
HW_WR_REG32(USED_IEP_BASE+CSL_ICSS_G_PR1_IEP0_SLV_CMP2_REG0, 99);
// Set sync ctrl register: SYNC1 dependent, cyclic generation , SYNC0 and SYNC1 enable, SYNC enable
HW_WR_REG32(USED_IEP_BASE+CSL_ICSS_G_PR1_IEP0_SLV_SYNC_CTRL_REG, 0x00A7);
// Set SYNC0/1 high pulse time in iep clok cycles ( 7 clocks for 20 MHz at 300 MHz iep clk)
//HW_WR_REG32(USED_IEP_BASE+CSL_ICSS_G_PR1_IEP0_SLV_SYNC_PWIDTH_REG, 0x0006);
// Set SYNC0/1 high pulse time in iep clok cycles ( 5 clocks for 20 MHz at 200 MHz iep clk)
HW_WR_REG32(USED_IEP_BASE+CSL_ICSS_G_PR1_IEP0_SLV_SYNC_PWIDTH_REG, 0x0004);
// Set SYNC0/1 period ( 15 clocks for 20 MHz at 300 MHz iep clk)
//HW_WR_REG32(USED_IEP_BASE+CSL_ICSS_G_PR1_IEP0_SLV_SYNC0_PERIOD_REG, 14);
// Set SYNC0/1 period ( 10 clocks for 20 MHz at 300 MHz iep clk)
HW_WR_REG32(USED_IEP_BASE+CSL_ICSS_G_PR1_IEP0_SLV_SYNC0_PERIOD_REG, 9);
// Set delay between SYNC0 and SYNC1 in clock cycles 2 = 3 clock cycles
HW_WR_REG32(USED_IEP_BASE+CSL_ICSS_G_PR1_IEP0_SLV_SYNC1_DELAY_REG, 2);
// Set offset from cpm1 hit
HW_WR_REG32(USED_IEP_BASE+CSL_ICSS_G_PR1_IEP0_SLV_SYNC_START_REG, 0);
// set enable cmp1 and cmp2 for sync start trigger generation
///HW_WR_REG32(USED_IEP_BASE+CSL_ICSS_G_PR1_IEP0_SLV_CMP_CFG_REG, 0x000000c);
// set enable cmp1 and cmp2 for sync start trigger generation
HW_WR_REG32(USED_IEP_BASE+CSL_ICSS_G_PR1_IEP0_SLV_CMP_CFG_REG, 0x00000Dc);
// set default and compensation increment to 1
HW_WR_REG8(USED_IEP_BASE+CSL_ICSS_G_PR1_IEP0_SLV_GLOBAL_CFG_REG, 0x0110);
// ************************************* task manager *************************************
//
return;
}
void start_IEP0(void)
{
uint8_t regVal;
// start iep0_timer
regVal = HW_RD_REG8(USED_IEP_BASE+CSL_ICSS_G_PR1_IEP0_SLV_GLOBAL_CFG_REG);
regVal += 0x1;
HW_WR_REG8(USED_IEP_BASE+CSL_ICSS_G_PR1_IEP0_SLV_GLOBAL_CFG_REG, regVal);
}
#if 0 // FL: PRU code
/**
* main.c
*/
int main(void)
{
__asm(" tsen 0");
init_IEP0_SYNC();
while (1){};
return 0;
}
#endif
In this file all CSL_PRU_ICSSG0_IPE0_BASE is changed to CSL_PRU_ICSSG1_IEP1_BASE.
// Set SYNC0/1 high pulse time in iep clok cycles ( 7 clocks for 20 MHz at 300 MHz iep clk)
//HW_WR_REG32(USED_IEP_BASE+CSL_ICSS_G_PR1_IEP0_SLV_SYNC_PWIDTH_REG, 0x0006);
// Set SYNC0/1 high pulse time in iep clok cycles ( 5 clocks for 20 MHz at 200 MHz iep clk)
HW_WR_REG32(USED_IEP_BASE+CSL_ICSS_G_PR1_IEP0_SLV_SYNC_PWIDTH_REG, 0x0004);
// Set SYNC0/1 period ( 15 clocks for 20 MHz at 300 MHz iep clk)
//HW_WR_REG32(USED_IEP_BASE+CSL_ICSS_G_PR1_IEP0_SLV_SYNC0_PERIOD_REG, 14);
// Set SYNC0/1 period ( 10 clocks for 20 MHz at 300 MHz iep clk)
HW_WR_REG32(USED_IEP_BASE+CSL_ICSS_G_PR1_IEP0_SLV_SYNC0_PERIOD_REG, 9);
Clock is also updated because the base clock and IEP clock is changed to 200Mhz. PRG1_PRU1_PGI16(V12) can successfully output 20Mhz clock.
2. sddf.c
/*
* Copyright (C) 2023 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 <stdio.h>
#include <kernel/dpl/DebugP.h>
#include "ti_drivers_config.h"
#include "ti_drivers_open_close.h"
#include "ti_board_open_close.h"
#include <stdint.h>
#include <drivers/hw_include/csl_types.h>
#include <drivers/hw_include/hw_types.h>
#include <drivers/pruicss.h>
#include <drivers/sciclient.h>
#include "tisddf_pruss_intc_mapping.h" /* INTC configuration */
#include "current_sense/sdfm/firmware/sdfm_pru_bin.h" /* SDDF image data */
#include "current_sense/sdfm/firmware/sdfm_rtu_bin.h"
#include "sddf.h"
#include "current_sense/sdfm/include/sdfm_api.h"
/* PRU SDDF FW image info */
typedef struct PRUSDDF_PruFwImageInfo_s {
const uint32_t *pPruImemImg;
const uint32_t pruImemImgSz;
} PRUSDDF_PruFwImageInfo;
/* TISCI ICSSG Core clock selection options */
static uint32_t gIcssCoreClkSel[ICSSGn_CORE_CLK_SEL_NUMSEL] = {
TISCI_DEV_PRU_ICSSG0_CORE_CLK_PARENT_HSDIV4_16FFT_MAIN_2_HSDIVOUT0_CLK,
TISCI_DEV_PRU_ICSSG0_CORE_CLK_PARENT_POSTDIV4_16FF_MAIN_0_HSDIVOUT9_CLK
};
/* TISCI ICSSG IEP clock selection options */
static uint32_t gIcssIepClkSel[ICSSGn_IEP_CLK_SEL_NUMSEL] = {
TISCI_DEV_PRU_ICSSG0_IEP_CLK_PARENT_POSTDIV4_16FF_MAIN_2_HSDIVOUT5_CLK,
TISCI_DEV_PRU_ICSSG0_IEP_CLK_PARENT_POSTDIV4_16FF_MAIN_0_HSDIVOUT6_CLK,
TISCI_DEV_PRU_ICSSG0_IEP_CLK_PARENT_BOARD_0_CP_GEMAC_CPTS0_RFT_CLK_OUT,
TISCI_DEV_PRU_ICSSG0_IEP_CLK_PARENT_BOARD_0_CPTS0_RFT_CLK_OUT,
TISCI_DEV_PRU_ICSSG0_IEP_CLK_PARENT_BOARD_0_MCU_EXT_REFCLK0_OUT,
TISCI_DEV_PRU_ICSSG0_IEP_CLK_PARENT_BOARD_0_EXT_REFCLK1_OUT,
TISCI_DEV_PRU_ICSSG0_IEP_CLK_PARENT_WIZ16B2M4CT_MAIN_0_IP1_LN0_TXMCLK,
TISCI_DEV_PRU_ICSSG0_IEP_CLK_PARENT_K3_PLL_CTRL_WRAP_MAIN_0_CHIP_DIV1_CLK_CLK
};
/* Number of PRU images */
#define PRU_SDDF_NUM_PRU_IMAGE ( 3 )
/* PRU SDDF image info */
static PRUSDDF_PruFwImageInfo gPruFwImageInfo[PRU_SDDF_NUM_PRU_IMAGE] =
{
{pru_SDFM_PRU0_image_0, sizeof(pru_SDFM_PRU0_image_0)}, /* PRU FW */
{pru_SDFM_RTU0_image_0, sizeof(pru_SDFM_RTU0_image_0)}, /* RTU FW */
{NULL, 0}
};
/* ICSS INTC configuration */
static const PRUICSS_IntcInitData gPruicssIntcInitdata = PRUICSS_INTC_INITDATA;
/*
* ======== cfgIcssgClkCfg ========
*/
/* Configure ICSSG clock selection */
int32_t cfgIcssgClkCfg(
uint8_t icssInstId,
uint8_t coreClkSel, /* ICSSG internal Core clock source select, ICSSG_CORE_SYNC_REG:CORE_VBUSP_SYNC_EN */
uint8_t icssCoreClkSel, /* ICSSG external Core clock source select, CTRLMMR_ICSSGn_CLKSEL:CORE_CLKSEL, (used if coreClkSel==0) */
uint64_t icssCoreClkFreqHz, /* ICSSG external Core clock frequency, (used if !=0 && coreClkSel==0) */
uint8_t iepClkSel, /* ICSSG internal IEP clock source select, ICSSG_IEPCLK_REG:IEP_OCP_CLK_EN */
uint8_t icssIepClkSel, /* ICSSG internal IEP clock source select, CTRLMMR_ICSSGn_CLKSEL:IEP_CLKSEL, (used if iepClkSel==0) */
uint64_t icssIepClkFreqHz /* ICSSG external IEP clock frequency, (used if !=0 && icssIepClkSel==0) */
)
{
const PRUICSS_HwAttrs *hwAttrs;
uint32_t instance;
CSL_IcssCfgRegs *pIcssCfgRegs;
uint64_t moduleId, clockId;
uint32_t numParents = 0U;
uint32_t parent;
uint32_t regVal;
uint32_t ret;
hwAttrs = PRUICSS_getAttrs(icssInstId);
instance = hwAttrs->instance;
if (instance == PRUICSS_INSTANCE_ONE) {
pIcssCfgRegs = (CSL_IcssCfgRegs *)CSL_PRU_ICSSG0_PR1_CFG_SLV_BASE;
/* Select ICSSG external Core clock source */
if (coreClkSel == CORE_CLK_SEL_ICSSGn_CORE_CLK) {
moduleId = TISCI_DEV_PRU_ICSSG0;
clockId = TISCI_DEV_PRU_ICSSG0_CORE_CLK;
ret = Sciclient_pmGetModuleClkNumParent(moduleId,
clockId,
&numParents,
SystemP_WAIT_FOREVER);
if ((ret == CSL_PASS) && (numParents > 1U)) {
/* Get TISCI parent clock ID */
if (icssCoreClkSel < ICSSGn_CORE_CLK_SEL_NUMSEL) {
parent = gIcssCoreClkSel[icssCoreClkSel];
}
else {
return SDDF_ERR_CFG_ICSSG_CLKCFG;
}
/* Configure Core clock mux */
ret = Sciclient_pmSetModuleClkParent(moduleId,
clockId,
parent,
SystemP_WAIT_FOREVER);
if (ret != CSL_PASS) {
return SDDF_ERR_CFG_ICSSG_CLKCFG;
}
if (icssCoreClkFreqHz != 0) {
/* Configure Clock frequency */
ret = Sciclient_pmSetModuleClkFreq(moduleId, clockId, icssCoreClkFreqHz, TISCI_MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE, SystemP_WAIT_FOREVER);
if (ret != CSL_PASS) {
return SDDF_ERR_CFG_ICSSG_CLKCFG;
}
}
}
else {
return SDDF_ERR_CFG_ICSSG_CLKCFG;
}
}
/* Select ICSSG internal Core clock source */
regVal = HW_RD_REG32(&pIcssCfgRegs->CORE_SYNC_REG);
regVal &= ~CSL_ICSSCFG_CORE_SYNC_REG_CORE_VBUSP_SYNC_EN_MASK;
regVal |= (coreClkSel << CSL_ICSSCFG_CORE_SYNC_REG_CORE_VBUSP_SYNC_EN_SHIFT) & CSL_ICSSCFG_CORE_SYNC_REG_CORE_VBUSP_SYNC_EN_MASK;
HW_WR_REG32(&pIcssCfgRegs->CORE_SYNC_REG, regVal);
/* Select ICSSG external IEP clock source */
if (iepClkSel == IEP_CLK_SEL_ICSSGn_IEP_CLK) {
moduleId = TISCI_DEV_PRU_ICSSG0;
clockId = TISCI_DEV_PRU_ICSSG0_IEP_CLK;
ret = Sciclient_pmGetModuleClkNumParent(moduleId,
clockId,
&numParents,
SystemP_WAIT_FOREVER);
if ((ret == CSL_PASS) && (numParents > 1U)) {
/* Get TISCI parent clock ID */
if (icssIepClkSel < ICSSGn_IEP_CLK_SEL_NUMSEL) {
parent = gIcssIepClkSel[icssIepClkSel];
}
else {
return SDDF_ERR_CFG_ICSSG_CLKCFG;
}
/* Configure Core clock mux */
ret = Sciclient_pmSetModuleClkParent(moduleId,
clockId,
parent,
SystemP_WAIT_FOREVER);
if (ret != CSL_PASS) {
return SDDF_ERR_CFG_ICSSG_CLKCFG;
}
if (icssIepClkFreqHz != 0) {
/* Configure Clock frequency */
ret = Sciclient_pmSetModuleClkFreq(moduleId, clockId, icssIepClkFreqHz, TISCI_MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE, SystemP_WAIT_FOREVER);
if (ret != CSL_PASS) {
return SDDF_ERR_CFG_ICSSG_CLKCFG;
}
}
}
else {
return SDDF_ERR_CFG_ICSSG_CLKCFG;
}
}
/* Select ICSSG internal IEP clock source */
regVal = HW_RD_REG32(&pIcssCfgRegs->IEPCLK);
regVal &= ~CSL_ICSSCFG_IEPCLK_OCP_EN_MASK;
regVal |= (iepClkSel << CSL_ICSSCFG_IEPCLK_OCP_EN_SHIFT) & CSL_ICSSCFG_IEPCLK_OCP_EN_MASK;
HW_WR_REG32(&pIcssCfgRegs->IEPCLK, regVal);
}
else if (instance == PRUICSS_INSTANCE_TWO) {
pIcssCfgRegs = (CSL_IcssCfgRegs *)CSL_PRU_ICSSG1_PR1_CFG_SLV_BASE;
/* Select ICSSG external Core clock source */
if (coreClkSel == CORE_CLK_SEL_ICSSGn_CORE_CLK) {
moduleId = TISCI_DEV_PRU_ICSSG1;
clockId = TISCI_DEV_PRU_ICSSG1_CORE_CLK;
ret = Sciclient_pmGetModuleClkNumParent(moduleId,
clockId,
&numParents,
SystemP_WAIT_FOREVER);
if ((ret == CSL_PASS) && (numParents > 1U)) {
if (icssCoreClkSel == ICSSGn_CORE_CLK_SEL_MAIN_PLL2_HSDIV0_CLKOUT) {
parent = TISCI_DEV_PRU_ICSSG1_CORE_CLK_PARENT_HSDIV4_16FFT_MAIN_2_HSDIVOUT0_CLK;
}
else if (icssCoreClkSel == ICSSGn_CORE_CLK_SEL_MAIN_PLL0_HSDIV9_CLKOUT) {
parent = TISCI_DEV_PRU_ICSSG1_CORE_CLK_PARENT_POSTDIV4_16FF_MAIN_0_HSDIVOUT9_CLK;
}
else {
return SDDF_ERR_CFG_ICSSG_CLKCFG;
}
ret = Sciclient_pmSetModuleClkParent(moduleId,
clockId,
parent,
SystemP_WAIT_FOREVER);
if (ret != CSL_PASS) {
return SDDF_ERR_CFG_ICSSG_CLKCFG;
}
}
else {
return SDDF_ERR_CFG_ICSSG_CLKCFG;
}
}
/* Select ICSSG internal Core clock source */
regVal = HW_RD_REG32(&pIcssCfgRegs->CORE_SYNC_REG);
regVal &= ~CSL_ICSSCFG_CORE_SYNC_REG_CORE_VBUSP_SYNC_EN_MASK;
regVal |= (coreClkSel << CSL_ICSSCFG_CORE_SYNC_REG_CORE_VBUSP_SYNC_EN_SHIFT) & CSL_ICSSCFG_CORE_SYNC_REG_CORE_VBUSP_SYNC_EN_MASK;
HW_WR_REG32(&pIcssCfgRegs->CORE_SYNC_REG, regVal);
/* Select ICSSG external IEP clock source */
if (iepClkSel == IEP_CLK_SEL_ICSSGn_IEP_CLK) {
moduleId = TISCI_DEV_PRU_ICSSG1;
clockId = TISCI_DEV_PRU_ICSSG1_IEP_CLK;
ret = Sciclient_pmGetModuleClkNumParent(moduleId,
clockId,
&numParents,
SystemP_WAIT_FOREVER);
if ((ret == CSL_PASS) && (numParents > 1U)) {
if (icssIepClkSel == ICSSGn_IEP_CLK_SEL_MAIN_PLL2_HSDIV5_CLKOUT) {
parent = TISCI_DEV_PRU_ICSSG1_IEP_CLK_PARENT_POSTDIV4_16FF_MAIN_2_HSDIVOUT5_CLK;
}
else if (icssIepClkSel == ICSSGn_IEP_CLK_SEL_MAIN_PLL0_HSDIV6_CLKOUT) {
parent = TISCI_DEV_PRU_ICSSG1_IEP_CLK_PARENT_POSTDIV4_16FF_MAIN_0_HSDIVOUT6_CLK;
}
else {
return SDDF_ERR_CFG_ICSSG_CLKCFG;
}
ret = Sciclient_pmSetModuleClkParent(moduleId,
clockId,
parent,
SystemP_WAIT_FOREVER);
if (ret != CSL_PASS) {
return SDDF_ERR_CFG_ICSSG_CLKCFG;
}
}
else {
return SDDF_ERR_CFG_ICSSG_CLKCFG;
}
}
/* Select ICSSG internal IEP clock source */
regVal = HW_RD_REG32(&pIcssCfgRegs->IEPCLK);
regVal &= ~CSL_ICSSCFG_IEPCLK_OCP_EN_MASK;
regVal |= (iepClkSel << CSL_ICSSCFG_IEPCLK_OCP_EN_SHIFT) & CSL_ICSSCFG_IEPCLK_OCP_EN_MASK;
HW_WR_REG32(&pIcssCfgRegs->IEPCLK, regVal);
}
else {
return SDDF_ERR_CFG_ICSSG_CLKCFG;
}
return SDDF_ERR_NERR;
}
/*
* ======== initIcss ========
*/
/* Initialize ICSSG */
int32_t initIcss(
uint8_t icssInstId,
uint8_t sliceId,
uint8_t saMuxMode,
PRUICSS_Handle *pPruIcssHandle
)
{
PRUICSS_Handle pruIcssHandle;
int32_t size;
const PRUICSS_HwAttrs *hwAttrs;
CSL_IcssCfgRegs *pIcssCfgRegs;
uint32_t instance;
uint32_t regVal;
int32_t status;
/* Open ICSS PRU instance */
pruIcssHandle = PRUICSS_open(icssInstId);
if (pruIcssHandle == NULL) {
return SDDF_ERR_INIT_ICSSG;
}
/* Disable slice PRU cores */
if (sliceId == ICSSG_SLICE_ID_0)
{
status = PRUICSS_disableCore(pruIcssHandle, PRUICSS_PRU0);
if (status != SystemP_SUCCESS) {
return SDDF_ERR_INIT_ICSSG;
}
status = PRUICSS_disableCore(pruIcssHandle, PRUICSS_RTU_PRU0);
if (status != SystemP_SUCCESS) {
return SDDF_ERR_INIT_ICSSG;
}
}
else if (sliceId == ICSSG_SLICE_ID_1)
{
status = PRUICSS_disableCore(pruIcssHandle, PRUICSS_PRU1);
if (status != SystemP_SUCCESS) {
return SDDF_ERR_INIT_ICSSG;
}
status = PRUICSS_disableCore(pruIcssHandle, PRUICSS_RTU_PRU1);
if (status != SystemP_SUCCESS) {
return SDDF_ERR_INIT_ICSSG;
}
}
else
{
return SDDF_ERR_INIT_ICSSG;
}
/* Reset slice memories */
size = PRUICSS_initMemory(pruIcssHandle, PRUICSS_IRAM_PRU(sliceId));
if (size == 0)
{
return SDDF_ERR_INIT_ICSSG;
}
size = PRUICSS_initMemory(pruIcssHandle, PRUICSS_IRAM_RTU_PRU(sliceId));
if (size == 0)
{
return SDDF_ERR_INIT_ICSSG;
}
size = PRUICSS_initMemory(pruIcssHandle, PRUICSS_IRAM_TX_PRU(sliceId));
if (size == 0)
{
return SDDF_ERR_INIT_ICSSG;
}
size = PRUICSS_initMemory(pruIcssHandle, PRUICSS_DATARAM(sliceId));
if (size == 0)
{
return SDDF_ERR_INIT_ICSSG;
}
/* Set ICSS pin mux */
PRUICSS_setSaMuxMode(pruIcssHandle, saMuxMode);
/* Initialize ICSS INTC */
status = PRUICSS_intcInit(pruIcssHandle, &gPruicssIntcInitdata);
if (status != SystemP_SUCCESS) {
return SDDF_ERR_INIT_ICSSG;
}
/* Enable SDDF load sharing */
hwAttrs = PRUICSS_getAttrs(icssInstId);
instance = hwAttrs->instance;
/* Determine ICSSG instance */
if (instance == PRUICSS_INSTANCE_ONE)
{
pIcssCfgRegs = (CSL_IcssCfgRegs *)CSL_PRU_ICSSG0_PR1_CFG_SLV_BASE;
}
else if (instance == PRUICSS_INSTANCE_TWO)
{
pIcssCfgRegs = (CSL_IcssCfgRegs *)CSL_PRU_ICSSG1_PR1_CFG_SLV_BASE;
}
else
{
return SDDF_ERR_INIT_ICSSG;
}
/* Configure selected ICSSG slice for SD load sharing */
if (sliceId == ICSSG_SLICE_ID_0)
{
regVal = HW_RD_REG32(&pIcssCfgRegs->SDPRU0CLKDIV);
regVal |= CSL_ICSSCFG_SDPRU0CLKDIV_PRU0_SD_SHARE_EN_MASK;
HW_WR_REG32(&pIcssCfgRegs->SDPRU0CLKDIV, regVal);
}
else if (sliceId == ICSSG_SLICE_ID_1)
{
regVal = HW_RD_REG32(&pIcssCfgRegs->SDPRU1CLKDIV);
regVal |= CSL_ICSSCFG_SDPRU1CLKDIV_PRU1_SD_SHARE_EN_MASK;
HW_WR_REG32(&pIcssCfgRegs->SDPRU1CLKDIV, regVal);
}
else
{
return SDDF_ERR_INIT_ICSSG;
}
*pPruIcssHandle = pruIcssHandle;
return SDDF_ERR_NERR;
}
/*
* ======== initPruSddf ========
*/
/* Initialize PRU core for SDDF */
int32_t initPruSddf(
PRUICSS_Handle pruIcssHandle,
uint8_t pruInstId,
SdfmPrms *pSddfPrms,
sdfm_handle *pHSddf
)
{
uint8_t sliceId;
uint32_t pruIMem;
PRUSDDF_PruFwImageInfo *pPruFwImageInfo;
int32_t size;
const uint32_t *sourceMem; /* Source memory[ Array of uint32_t ] */
uint32_t imemOffset;
uint32_t byteLen; /* Total number of bytes to be written */
uint8_t pruId; // FL: remove Host FW init since FW changing
int32_t status;
/* Reset PRU */
status = PRUICSS_resetCore(pruIcssHandle, pruInstId);
if (status != SystemP_SUCCESS) {
return SDDF_ERR_INIT_PRU_SDDF;
}
/* Calculate slice ID */
sliceId = pruInstId - (uint8_t)pruInstId/ICSSG_NUM_SLICE * ICSSG_NUM_SLICE;
/* Determine PRU DMEM address */
PRUICSS_DATARAM(sliceId);
/* Determine PRU FW image and PRU IMEM address */
switch (pruInstId)
{
case PRUICSS_PRU0:
case PRUICSS_PRU1:
pPruFwImageInfo = &gPruFwImageInfo[0];
pruIMem = PRUICSS_IRAM_PRU(sliceId);
// dmemOffset = PRU_ICSSG_SDDF_CTRL_BASE;
break;
case PRUICSS_RTU_PRU0:
case PRUICSS_RTU_PRU1:
pPruFwImageInfo = &gPruFwImageInfo[1];
pruIMem = PRUICSS_IRAM_RTU_PRU(sliceId);
// dmemOffset = RTU_ICSSG_SDDF_CTRL_BASE;
break;
case PRUICSS_TX_PRU0:
case PRUICSS_TX_PRU1:
pPruFwImageInfo = NULL;
break;
default:
pPruFwImageInfo = NULL;
break;
}
if ((pPruFwImageInfo == NULL) ||
(pPruFwImageInfo->pPruImemImg == NULL))
{
return SDDF_ERR_INIT_PRU_SDDF;
}
/* Write DMEM */
//sourceMem = (uint32_t *)pPruFwImageInfo->pPruDmemImg;
// byteLen = pPruFwImageInfo->pruDmemImgSz;
//size = PRUICSS_writeMemory(pruIcssHandle, pruDMem, dmemOffset, sourceMem, byteLen);
//if (size == 0)
// {
/// return SDDF_ERR_INIT_PRU_SDDF;
//}
/* Write IMEM */
imemOffset = 0;
sourceMem = (uint32_t *)pPruFwImageInfo->pPruImemImg;
byteLen = pPruFwImageInfo->pruImemImgSz;
size = PRUICSS_writeMemory(pruIcssHandle, pruIMem, imemOffset, sourceMem, byteLen);
if (size == 0)
{
return SDDF_ERR_INIT_PRU_SDDF;
}
/* Enable PRU */
status = PRUICSS_enableCore(pruIcssHandle, pruInstId);
if (status != SystemP_SUCCESS) {
return SDDF_ERR_INIT_PRU_SDDF;
}
/* Translate PRU ID to SDFM API */
if (sliceId == PRUICSS_PRU0) {
pruId = PRU_ID_0;
}
else if (sliceId == PRUICSS_PRU1) {
pruId = PRU_ID_1;
}
else {
return SDDF_ERR_INIT_PRU_SDDF;
}
/* Initialize SDDF PRU FW */
status = initSddf(pruId, pruInstId, pSddfPrms, pHSddf, pruIcssHandle);
if (status != SDDF_ERR_NERR) {
return SDDF_ERR_INIT_PRU_SDDF;
}
return SDDF_ERR_NERR;
}
/* Initialize SDDF PRU FW */
int32_t initSddf(
uint8_t pruId, uint8_t pruInstId,
SdfmPrms *pSdfmPrms,
sdfm_handle *pHSdfm, PRUICSS_Handle pruIcssHandle
)
{
sdfm_handle hSdfm;
/* Initialize SDFM instance */
hSdfm = SDFM_init(pruIcssHandle, pruId, pruInstId);
if (hSdfm == NULL) {
return SDDF_ERR_INIT_SDDF;
}
uint32_t i;
i = SDFM_getFirmwareVersion(hSdfm);
DebugP_log("\n\n\n");
DebugP_log("SDFM firmware version \t: %x.%x.%x (%s)\n\n", (i >> 24) & 0x7F,
(i >> 16) & 0xFF, i & 0xFFFF, i & (1 << 31) ? "internal" : "release");
if (hSdfm == NULL)
{
return SDDF_ERR_INIT_SDDF;
}
uint8_t SDFM_CH;
hSdfm->iepClock = pSdfmPrms->iep_clock;
hSdfm->sdfmClock = pSdfmPrms->sd_clock;
hSdfm->sampleOutputInterface = (SDFM_SampleOutInterface *)(pSdfmPrms->samplesBaseAddress);
uint32_t sampleOutputInterfaceGlobalAddr = CPU0_BTCM_SOCVIEW(pSdfmPrms->samplesBaseAddress);
hSdfm->pSdfmInterface->sampleBufferBaseAdd = sampleOutputInterfaceGlobalAddr;
hSdfm->iepInc = 1; /* Default IEP increment 1 */
uint8_t acc_filter = 0; //SINC3 filter
uint8_t ecap_divider = 0x09; //IEP at 200MHz: SD clock = 200/10=20Mhz
// uint8_t ecap_divider = 0x0F; //IEP at 300MHz: SD clock = 300/15=20Mhz
/*IEP base address*/
// ICSSG1 RTU1
hSdfm->pruicssIep = (void *)(((PRUICSS_HwAttrs *)(pruIcssHandle->hwAttrs))->iep1RegBase);
//hSdfm->pruicssIep = (void *)(((PRUICSS_HwAttrs *)(pruIcssHandle->hwAttrs))->iep0RegBase);
/*configure IEP count for one epwm period*/
SDFM_configIepCount(hSdfm, pSdfmPrms->epwm_out_freq);
/*configure ecap as PWM code for generate 20 MHz sdfm clock*/
SDFM_configEcap(hSdfm, ecap_divider);
/*set Noraml current OSR */
SDFM_setFilterOverSamplingRatio(hSdfm, pSdfmPrms->FilterOsr);
/*below configuration for all three channel*/
switch (pruInstId)
{
case PRUICSS_PRU0:
case PRUICSS_PRU1:
SDFM_CH = 3;
break;
case PRUICSS_RTU_PRU0:
case PRUICSS_RTU_PRU1:
SDFM_CH = 0;
break;
case PRUICSS_TX_PRU0:
case PRUICSS_TX_PRU1:
SDFM_CH = 6;
break;
default:
SDFM_CH = 0;
break;
}
for(int i = SDFM_CH; i< SDFM_CH + NUM_CH_SUPPORTED_PER_AXIS; i++)
{
SDFM_setEnableChannel(hSdfm, i);
}
SDFM_enableEpwmSync(hSdfm, 0);
for(SDFM_CH = 0; SDFM_CH < NUM_CH_SUPPORTED_PER_AXIS; SDFM_CH++)
{
/*set comparator osr or Over current osr*/
SDFM_setCompFilterOverSamplingRatio(hSdfm, SDFM_CH, pSdfmPrms->ComFilterOsr);
/*set ACC source or filter type*/
SDFM_configDataFilter(hSdfm, SDFM_CH, acc_filter);
/*set clock source for all three channel*/
SDFM_selectClockSource(hSdfm, SDFM_CH, pSdfmPrms->clkPrms[SDFM_CH].clk_source);
/*set clock inversion */
SDFM_setClockInversion(hSdfm, SDFM_CH, pSdfmPrms->clkPrms[SDFM_CH].clk_inv);
/*set threshold values */
SDFM_setCompFilterThresholds(hSdfm, SDFM_CH, pSdfmPrms->comThresholds[SDFM_CH]);
if(pSdfmPrms->en_com)
{
SDFM_enableComparator(hSdfm, SDFM_CH);
}
else
{
SDFM_disableComparator(hSdfm, SDFM_CH);
}
}
/*GPIO pin configuration for threshold measurment*/
///sdfm_configure_gpio_pin(hSdfm);
SDFM_setSampleTriggerTime(hSdfm, pSdfmPrms->firstSampTrigTime);
if(pSdfmPrms->en_second_update)
{
SDFM_enableDoubleSampling(hSdfm, pSdfmPrms->secondSampTrigTime);
}
else
{
SDFM_disableDoubleSampling(hSdfm);
}
/* Enable (global) SDFM */
SDFM_enable(hSdfm);
*pHSdfm = hSdfm;
return SDDF_ERR_NERR;
}
In this file function initSddf,
the defualt value of ecap_divider is changed to 9 for 20Mhz output based on 200Mhz clk.
pruicssIep is changed to IEP1
hSdfm->pruicssIep = (void *)(((PRUICSS_HwAttrs *)(pruIcssHandle->hwAttrs))->iep1RegBase);
3. single_chip_servo.c
In this file I removed all endat related code.
ICSSG and PRU is changed to ICSSG1 PRU1.
/* Test ICSSG instance ID */ #define TEST_ICSSG_INST_ID ( CONFIG_PRU_ICSS0 ) /* Test ICSSG slice ID */ #define TEST_ICSSG_SLICE_ID ( ICSSG_SLICE_ID_1 ) /* Test PRU core instance IDs */ #define TEST_PRU_INST_ID ( PRUICSS_PRU1 ) #define TEST_RTU_INST_ID ( PRUICSS_RTU_PRU1 ) /* R5F interrupt settings for ICSSG */ #define ICSSG_PRU_SDDF_INT_NUM ( CSLR_R5FSS0_CORE0_INTR_PRU_ICSSG1_PR1_HOST_INTR_PEND_3 ) /* VIM interrupt number */ #define ICSSG_RTU_SDDF_INT_NUM ( CSLR_R5FSS0_CORE0_INTR_PRU_ICSSG1_PR1_HOST_INTR_PEND_4 ) /* VIM interrupt number */ #define ICSSG_TX_PRU_SDDF_INT_NUM ( CSLR_R5FSS0_CORE0_INTR_PRU_ICSSG1_PR1_HOST_INTR_PEND_5 ) /* VIM interrupt number */
IEP clock is changed to 200Mhz
/* Test Sdfm parameters */
SdfmPrms gTestSdfmPrms = {
200000000, /*Value of IEP clock*/
20000000, /*Value of SD clock (It should be exact equal to sd clock value)*/
0, /*enable double update*/
10, /*first sample trigger time*/
0, /*second sample trigger time*/
APP_EPWM_OUTPUT_FREQ, /*PWM output frequency*/
{{3500, 1000}, /*threshold parameters(High, low )*/
{3500, 1000},
{3500, 1000}},
{{0,0}, /*clock sourse & clock inversion for all channels*/
{0,0},
{0,0}},
15, /*Over current osr: The effect count is OSR + 1*/
64, /*Normal current osr */
0, /*comparator enable*/
(uint32_t)&gSddfChSamps /*Output samples base address*/
};
In function init_sddf, CSL_PRU_ICSSG0_PR1_CFG_SLV_BASE is changed to CSL_PRU_ICSSG1_PR1_CFG_SLV_BASE
/* Configure g_mux_en to PRUICSS_G_MUX_EN in ICSSG_SA_MX_REG Register. */
HW_WR_REG32((CSL_PRU_ICSSG1_PR1_CFG_SLV_BASE+0x40), PRUICSS_G_MUX_EN);
The rest is PWM related changes. The PWM interuppt App_epwmIntrISR can be entered normally, and PWM output stays 50%.
Thanks,
Jianyu








