When the power supply is active and then attempting to measure frequency, the PWMs that drive the PSU seems to be blown out. I can’t see an immediate reason why though.
Just to get the context right…
Can you help me understand, when you say, “blown out”, if you are saying that configuration registers are overwritten, or perhaps saying that there is hardware damage?
Thanks!
I’m guessing that the measure freq command is changing values or settings in a way that causes the PWM that controls voltage and current level to stop running. After measure freq on any pin the voltage PWM seems to go to 0 or 1, and the current seems to go to 0.
Oh, good! The PWM going to both (randomly) 0
or 1
suggests this is not destroying hardware, but is “just” a firmware bug.
On what BP model does this happen?
I’m doing docs updates with a 5 rev 10 and noticed it there when running the autosnip scripts. I have not tested on other hardware, but I can’t imagine it doesn’t impact all hardware.
It’s probably something really simple like a config command resetting all the PWM modules, but I didn’t find it on a quick look.
I see it happening on a BP6 rev2. The following code looks wrong for the RP2350
freq.c:244 static uint8_t freq_irq_disable_bitmask;
The bitmask should be at least 12 bits because of the additional PWM slices.
The SDK APIs take a uint32_t
I also don’t understand the name: …disable… even though it is passed to an …enable.. API and the bits are set for the active frequency PWMs. I see that it may affect the other pwms. since their bits are 0.
Something like this seems to work. Please make sure it is correct.
pwm_hw->en is the bitmap of enabled pwm
// we pre-calculate the disable bitmask for the enable function
// to avoid blowing out active PWM when we're done with a FREQ measure
static uint32_t freq_irq_disable_bitmask;
// frequency measurement
int64_t freq_timer_callback(alarm_id_t id, void* user_data) {
// disable all at once (but leave any other PWM slices running)
// turn off only the ones we turned on and don't turn on any other that weren't running already
pwm_set_mask_enabled(freq_irq_disable_bitmask & pwm_hw->en);
for (uint8_t i = 0; i < count_of(bio2bufiopin); i++) {
if (system_config.freq_active & (0x01 << i)) {
uint slice_num = pwm_gpio_to_slice_num(bio2bufiopin[i]);
gpio_set_function(bio2bufiopin[i], GPIO_FUNC_SIO);
uint16_t counter = (uint16_t)pwm_get_counter(slice_num);
float freq = counter * 100.f;
system_config.freq_config[i].period = freq;
}
}
return 0;
}
// trigger all frequency measurements at once using only one delay
void freq_measure_period_irq(void) {
uint32_t mask = 0;
// dont do anything if user has no active freq measurements
if (system_config.freq_active == 0) {
return;
}
for (uint8_t i = 0; i < count_of(bio2bufiopin); i++) {
if (system_config.freq_active & (0x01 << i)) {
uint slice_num = pwm_gpio_to_slice_num(bio2bufiopin[i]);
pwm_config cfg = pwm_get_default_config();
pwm_config_set_clkdiv_mode(&cfg, PWM_DIV_B_RISING);
pwm_config_set_clkdiv(&cfg, 1);
pwm_init(slice_num, &cfg, false);
gpio_set_function(bio2bufiopin[i], GPIO_FUNC_PWM);
pwm_set_counter(slice_num, 0);
// build mask, slices 0-7...
mask |= (0x01 << slice_num);
}
// we pre-calculate the disable bitmask for the enable function
// to avoid blowing out active PWM when we're done with a FREQ measure
if (system_config.pwm_active & (0x01 << i)) {
uint slice_num = pwm_gpio_to_slice_num(bio2bufiopin[i]);
// build mask, slices 0-7...
mask |= (0x01 << slice_num);
//freq_irq_disable_bitmask = (0x01 << slice_num);
}
}
freq_irq_disable_bitmask = ~mask;
//set the mask and the ones already running
pwm_set_mask_enabled(mask | pwm_hw->en);
add_alarm_in_ms(10, freq_timer_callback, NULL, false);
}
Thank you so much. Extending the variable width and retaining the existing PWM settings with pwm_hw->en is the solution. The PSU settings were being blown out by the set_mask_enabled function.