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