在CCS9.3下,对ICEAM3359板子写裸机工程,在GEL文件中均成功开启了GPIO1,GPIO2,GPIO3各自的时钟,且在工程中都能正确配置和使用0–3这四组IO口,想尝试测试下ECAP的PWM输出功能,于是在GEL文件中配置了如下功能:
//****************************************************
//PRCM module definitions
//****************************************************
#define PRCM_BASE_ADDR (0x44E00000)
#define CM_PER_L4LS_CLKSTCTRL (PRCM_BASE_ADDR + 0x000)
#define CM_PER_L3LS_CLKSTCTRL (PRCM_BASE_ADDR + 0x004)
#define CM_PER_L3_CLKSTCTRL (PRCM_BASE_ADDR + 0x00C)
#define CM_PER_EMIF_CLKCTRL (PRCM_BASE_ADDR + 0x028)
#define CM_PER_GPIO1_CLKCTRL (PRCM_BASE_ADDR + 0x0AC)
#define CM_PER_GPIO2_CLKCTRL (PRCM_BASE_ADDR + 0x0B0)
#define CM_PER_GPIO3_CLKCTRL (PRCM_BASE_ADDR + 0x0B4)
#define CM_PER_PWM0_CLKCTRL (PRCM_BASE_ADDR + 0x0D4)
#define CM_PER_PWM1_CLKCTRL (PRCM_BASE_ADDR + 0x0CC)
#define CM_PER_PWM2_CLKCTRL (PRCM_BASE_ADDR + 0x0D8)
#define CM_PER_EMIF_FW_CLKCTRL (PRCM_BASE_ADDR + 0x0D0)
/*配置PWM0和ECAP0外设*/
hotmenu PWM0_Config()
{
WR_MEM_32(CM_PER_PWM0_CLKCTRL,0x40002);
while(RD_MEM_32(CM_PER_PWM0_CLKCTRL) & 0x30000 != 0x0);/*等待模块进入全功能状态*/
WR_MEM_32(PWMSS0_SYSCONFIG,0x14);
WR_MEM_32(PWMSS0_CLKCONFIG,0x01);
while((RD_MEM_32(PWMSS0_CLKSTATUS) & 0x1) != 0x1);
GEL_TextOut("PWM0/ECAP0时钟启动成功\n","Output",1,1,1);
}
我在GEL中配置GPIO的时候,在 CM_PER_L4LS_CLKSTCTRL这个寄存器中有GPIO1–3的时钟开启状态位,检测这个状态位可判断相应的GPIO时钟是否处于激活状态,但发现在这个寄存器中没有ECAP的时钟状态位,为了便于比较,我把GEL中GPIO1–3的时钟配置代码贴出来:
WR_MEM_32(CM_PER_GPIO1_CLKCTRL,0x40002);
while(RD_MEM_32(CM_PER_GPIO1_CLKCTRL) & 0x30000 != 0x0); /*等待模块进入全功能状态*/
while((RD_MEM_32(CM_PER_L4LS_CLKSTCTRL) & 0x80000) != 0x80000);/*等待GPIO1的时钟激活*/
其中第三行就是用来判断GPIO1的时钟是否处于激活状态,但ECAP没有这样的位。
当我配置完GEL文件,工程中加入对ECAP寄存器的配置代码,并进入CCS调试模式后,程序每次运行到对ECAP寄存器进行配置的地方就会跑飞,在寄存器窗口中显示 Target failed to read 0x48304100,这个地址就是ECAP2的寄存器地址,根据这一现象,我判断ECAP模块的时钟实际上仍然没有开启,模块处于关闭状态,因而CCS无法读取到这个寄存器的相关位的值,那如果是这样的情况,ECAP模块的时钟还有哪里需要配置的呢,或者是不是我把时钟已经开启了,但仍然要去判断时钟状态,只不过我没有找到这个状态位是在哪个寄存器里面?
同样,在L4_PER里面,我数了下总共有超过32个,差不多有40多个低速外设,而在CM_PER_L4LS_CLKSTCTRL这个寄存器中,也才15个L4外设的时钟状态位,换句话说,还有几十个外设的时钟状态位找不到在哪里,如果我要配置这15个以外的外设的时钟,也是要必须判断相关的时钟状态位的吧,那相关的判断位是在哪个寄存器里面啊,没有这个状态位,会不会也会像上面ECAP那样的情况出现呢
Nancy Wang:
while((RD_MEM_32(PWMSS0_CLKSTATUS) & 0x1) != 0x1);是判断的eCAP_CLK_EN_ACK 吗?
请将相关完整的配置附件上传看看。
user18914063:
回复 Nancy Wang:
你指的是GEL文件吗,配置ECAP的就是上面的部分了,没别的了,其余的都是配置DDR,PLL之类的,
Nancy Wang:
回复 user18914063:
时钟配置看起来没有问题,但你配置的好像是ECAP0,不是ECAP2。 建议可以检查一下CM_PER_L4LS_CLKSTCTRL,参考 <PDK>\packages\ti\starterware\soc\am335x\am335x_prcm.c #if defined(BUILDCFG_MOD_PWMSS) case CHIPDB_MOD_ID_PWMSS: { switch(instNum) { case 0: enableModule(SOC_CM_PER_REGS, CM_PER_EPWMSS0_CLKCTRL, CM_PER_L4LS_CLKSTCTRL, CM_PER_L4LS_CLKSTCTRL_CLKACTIVITY_L4LS_GCLK); break; case 2: enableModule(SOC_CM_PER_REGS, CM_PER_EPWMSS2_CLKCTRL, CM_PER_L4LS_CLKSTCTRL, CM_PER_L4LS_CLKSTCTRL_CLKACTIVITY_L4LS_GCLK); break; } } void enableModule(uint32_t domainOffset, uint32_t clkCtrlReg, uint32_t clkStCtrlReg, uint32_t clkActMask) { /* Enable the module */ HW_WR_REG32(domainOffset + clkCtrlReg, PRCM_MODULEMODE_ENABLE); /* Check for module enable status */ while(PRCM_MODULEMODE_ENABLE != (HW_RD_REG32(domainOffset + clkCtrlReg) & PRCM_MODULEMODE_MASK)); /* Check clock activity – ungated */ while(clkActMask != (HW_RD_REG32(domainOffset + clkStCtrlReg) & clkActMask)); /* Check idle status value – should be in functional state */ while((PRCM_MODULE_IDLEST_FUNC << PRCM_IDLE_ST_SHIFT) != (HW_RD_REG32(domainOffset + clkCtrlReg) & PRCM_IDLE_ST_MASK)); } PWMSS 使用的是 PD_PER_L4LS_GCLK,所以CM_PER_L4LS_CLKSTCTRL 中没有单独的ecap时钟位,参考Table 15-2. PWMSS Connectivity Attributes & Table 15-3. PWMSS Clock Signals 看一下。