I'm unable to advance the PWM state machine from Initial to Active. Currently, I'm using the following:
#define PWM_PERIOD 0x003D0900u // 20ms @ 200MHz (50Hz)
#define PWM_MAX 0x400u
void pwm_setup(uint16_t duty)
{
/* Disable counter */
CT_IEP0.global_cfg_reg_bit.cnt_enable = 0;
/* Switch to 32-bit mode */
CT_IEP0.cmp_cfg_reg_bit.shadow_en = 0;
CT_IEP0.cmp_cfg_reg_bit.shadow_en = 1;
/* Reset Count register */
CT_IEP0.count_reg0_bit.count_lo = 0xFFFFFFFF;
CT_IEP0.count_reg1_bit.count_hi = 0xFFFFFFFF;
/* Clear overflow status register */
CT_IEP0.global_status_reg_bit.cnt_ovf = 1;
/* Clear compare status */
CT_IEP0.cmp_status_reg_bit.cmp_status = 0xFFFF;
/* Set compare value */
CT_IEP0.cmp0_reg1_bit.cmp0_1 = PWM_PERIOD;
/* Enable CMP0 and reset on event */
CT_IEP0.cmp_cfg_reg_bit.cmp_en = (1u << 8) | (1u << 0);
CT_IEP0.cmp_cfg_reg_bit.cmp0_rst_cnt_en = 1;
/* Set increment value */
CT_IEP0.global_cfg_reg_bit.default_inc = 1;
/* Disable compensation */
CT_IEP0.compen_reg_bit.compen_cnt = 0;
/* Reset trip */
CT_CFG_EXT.pwm1_bit.pwm1_trip_reset = 1;
/* Duty-cycle low then high (Ouput LOW -> PWM HIGH) */
CT_IEP0.cmp8_reg1_bit.cmp8_1 = (duty * PWM_PERIOD) / PWM_MAX;
CT_CFG_EXT.pwm1_0_bit.pwm1_0_neg_init = STATE_L;
CT_CFG_EXT.pwm1_0_bit.pwm1_0_neg_act = STATE_H;
CT_CFG_EXT.pwm1_0_bit.pwm1_0_neg_trip = STATE_H;
/* Enable counter */
CT_IEP0.global_cfg_reg_bit.cnt_enable = 1;
}
void main(void)
{
volatile uint16_t duty, duty_prev, sw_pwm;
duty = duty_prev = 0;
sw_pwm = 0;
while (1) {
if (duty != duty_prev) {
duty_prev = duty;
cmp0_ovf = cmp8_ovf = 0;
pwm_set_duty(duty);
} else {
uint16_t status = CT_IEP0.cmp_status_reg_bit.cmp_status;
CT_IEP0.cmp_status_reg_bit.cmp_status = status;
if (sw_pwm == 0) {
if (status & (1u << 0)) {
cmp0_ovf++;
}
if (status & (1u << 8)) {
cmp8_ovf++;
}
} else {
if (duty == 0) {
CT_CFG_EXT.pwm1_0_bit.pwm1_0_neg_init = STATE_H;
} else if (duty >= (PWM_MAX - 1)) {
CT_CFG_EXT.pwm1_0_bit.pwm1_0_neg_init = STATE_L ;
} else {
if (status & (1u << 0)) {
cmp0_ovf++;
CT_CFG_EXT.pwm1_0_bit.pwm1_0_neg_init = STATE_L;
}
if (status & (1u << 8)) {
cmp8_ovf++;
CT_CFG_EXT.pwm1_0_bit.pwm1_0_neg_init = STATE_H;
}
}
}
}
}
Using CCS, I've proven that the pin-mux and register selections are correct:
- When I set sw_pwm to 1, I get the expected PWM output on the desired pin varying with changes to duty
- This proves that I have the right pin, the right pinmux and the IEP comparator is working
- When I set sw_pwm to 0, it appears that pwm1_0_neg is stuck in the Initial state
I can further confirm this by using CCS to modify CT_CFG_EXT.pwm1_0_bit.pwm1_0_neg_init and I see corresponding change at the output pin.
I've also experimented with enabling *ALL* IEP comparators, but that did not help.
Am I missing an enable bit for PWM somewhere? (The am65xx datasheet lists a few additional registers that appear to be missing from the J721e)
EDIT: Add missing pwm1_trip_reset, this was present in my testing, but missed in the above copy/paste
