Hello,
I’ve been trying to set up the eHRPWMx outputs on my BeagleBone Black (started out with eHRPWM1 → P9_14) using only the PRU (no intervention/help from the Linux side, just setting registers on PRU code).
I’ve got a BeagleBone Black Wireless with the kernel (uname -r output) 4.9.83-bone10. I’ve posted this here since I think this is irrelevant of the bone being wireless, should apply to all BBBs (there’s also a sad story on the TI forums with a guy trying to solve this and not getting anywhere useful with a BBB, so I think it’s relevant):
To enable the eHRPWM from the PRU code I do the following in order (the GLB_ registers are just eHRPWM registers in correct addresses):
/////////////////////////////////////////////
///////////////// Code /////////////////
/////////////////////////////////////////////
#define CM_PER_BASE 0x44E00000
#define CM_EPWMSS1_REG ((volatile uint32_t *)(CM_PER_BASE + CM_PER_EPWMSS1_CLKCTRL))
#define CM_EPWMSS0_REG ((volatile uint32_t *)(CM_PER_BASE + CM_PER_EPWMSS0_CLKCTRL))
#define CM_EPWMSS2_REG ((volatile uint32_t *)(CM_PER_BASE + CM_PER_EPWMSS2_CLKCTRL))
#define PWMSS1_BASE 0x48302000
#define SYSCONFIG_REG ((volatile uint32_t *)(PWMSS1_BASE + 0x4))
#define CLKCONFIG_REG ((volatile uint32_t *)(PWMSS1_BASE + 0x8))
#define CLKSTATUS_REG ((volatile uint32_t *)(PWMSS1_BASE + 0xC))
…
// enable OCP (the below registers are defined in the well-known “pru_cfg.h”)
CT_CFG.SYSCFG_bit.STANDBY_INIT = 0;
…
(*CM_EPWMSS1_REG) = 0x2;
(*CLKCONFIG_REG) |= 0x100;
(*GLB_EHRPWM1_TBCTL) = 0xC030;
(*GLB_EHRPWM1_TBPHS) = 0;
(*GLB_EHRPWM1_TBCNT) = 0;
(*GLB_EHRPWM1_TBPRD) = 1000;
(*GLB_EHRPWM1_CMPA) = 500;
(*GLB_EHRPWM1_CMPCTL) = 0x0;
(*GLB_EHRPWM1_AQCTLA) = 0x32;
…
/////////////////////////////////////////////
///////////////// Code /////////////////
/////////////////////////////////////////////
Other than the “signal-the-host” stuff and some other irrelevant things this is the PRU main(). I use the default dtbo file named “BB-PWM1-00A0.dtbo” to test eHRPWM1A on P9_14. After a clean boot, if I run this, it doesn’t work → no output on the pin. I’ve pulled out all the registers that have the name pwm in it from the TRM and checked their values to see what’s wrong. There’s this pwmss1_tbclken bit of the pwmss_ctrl register in control module registers which just won’t turn on by action from the PRU (pwmss_ctrl will stay 0 even though I tried setting it to 0x7 to enable all 3 tbclken’s).
The reason why I think that pwmss1_tbclken was the problem → a while later I realized if after a clean boot, if I do the following on bash (on Linux side):
sudo su
sudo sh -c “echo 0 > /sys/class/pwm/pwmchip0/export”
sudo sh -c “echo 1000000 > /sys/class/pwm/pwmchip0/pwm0/period”
sudo sh -c “echo 500000 > /sys/class/pwm/pwmchip0/pwm0/duty_cycle”
sudo sh -c “echo 1 > /sys/class/pwm/pwmchip0/pwm0/enable”
exit
I get PWM output on P9_14 (like I knew I should). Right after this I check pwmss1_tbclken, it’s set! After this I run the exact same PRU code and I’ve got full control over the eHRPWM module (except pwmss1_tbclken, can’t change that from the PRU). Rerunning it with different prd and cmp values give different pwm waveforms etc.
It’s almost as if the Linux side driver does some kind of enable-control-of-CM_PER_EPWMSS1_CLKCTRL setting which I’m missing. I’ve checked the kernel driver from the repo below but haven’t been able to identify that sort of a register setting:
https://github.com/beagleboard/linux/blob/4.9/drivers/pwm/pwm-tiehrpwm.c
Is there such a setting that I’m missing? Some register that needs to be set before the PRU can access pwmss_ctrl? Or is it just that the PRU is not allowed to do what I’m trying to do? Running the Linux side script once at power-up is ofcourse a workaround that might work but I was thinking of using this in an industrial setting so direct PRU control of the peripheral from power-on onwards would be great.
Thanks in advance for the help,
Burak