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