Clear the pending IRQ in the NVIC as well.

This commit is contained in:
Scott Shawcroft 2020-03-10 16:57:41 -07:00
parent 00d5f63e7c
commit affd3fcc2a
No known key found for this signature in database
GPG Key ID: 9349BC7E64B1921E
5 changed files with 37 additions and 12 deletions

View File

@ -322,6 +322,7 @@ bool common_hal_audiobusio_i2sout_get_playing(audiobusio_i2sout_obj_t* self) {
void i2s_background(void) {
if (NVIC_GetPendingIRQ(I2S_IRQn) && NRF_I2S->EVENTS_TXPTRUPD) {
NRF_I2S->EVENTS_TXPTRUPD = 0;
NVIC_ClearPendingIRQ(I2S_IRQn);
if (instance) {
i2s_buffer_fill(instance);
} else {

View File

@ -88,7 +88,6 @@ void audiopwmout_reset() {
}
STATIC void fill_buffers(audiopwmio_pwmaudioout_obj_t *self, int buf) {
self->pwm->EVENTS_SEQSTARTED[1-buf] = 0;
uint16_t *dev_buffer = self->buffers[buf];
uint8_t *buffer;
uint32_t buffer_length;
@ -145,8 +144,15 @@ STATIC void audiopwmout_background_obj(audiopwmio_pwmaudioout_obj_t *self) {
if (stopped)
self->pwm->TASKS_STOP = 1;
} else if (!self->paused && !self->single_buffer) {
if (self->pwm->EVENTS_SEQSTARTED[0]) fill_buffers(self, 1);
if (self->pwm->EVENTS_SEQSTARTED[1]) fill_buffers(self, 0);
if (self->pwm->EVENTS_SEQSTARTED[0]) {
fill_buffers(self, 1);
self->pwm->EVENTS_SEQSTARTED[0] = 0;
}
if (self->pwm->EVENTS_SEQSTARTED[1]) {
fill_buffers(self, 0);
self->pwm->EVENTS_SEQSTARTED[1] = 0;
}
NVIC_ClearPendingIRQ(self->pwm_irq);
}
}
@ -168,7 +174,8 @@ void audiopwmout_background() {
// Caller validates that pins are free.
void common_hal_audiopwmio_pwmaudioout_construct(audiopwmio_pwmaudioout_obj_t* self,
const mcu_pin_obj_t* left_channel, const mcu_pin_obj_t* right_channel, uint16_t quiescent_value) {
self->pwm = pwmout_allocate(256, PWM_PRESCALER_PRESCALER_DIV_1, true, NULL, NULL);
self->pwm = pwmout_allocate(256, PWM_PRESCALER_PRESCALER_DIV_1, true, NULL, NULL,
&self->pwm_irq);
if (!self->pwm) {
mp_raise_RuntimeError(translate("All timers in use"));
}

View File

@ -44,6 +44,8 @@ typedef struct {
uint8_t sample_channel_count;
uint8_t bytes_per_sample;
IRQn_Type pwm_irq;
bool playing;
bool stopping;
bool paused;

View File

@ -139,11 +139,15 @@ bool convert_frequency(uint32_t frequency, uint16_t *countertop, nrf_pwm_clk_t *
return false;
}
// We store these in an array because we cannot compute them.
static IRQn_Type pwm_irqs[4] = {PWM0_IRQn, PWM1_IRQn, PWM2_IRQn, PWM3_IRQn};
NRF_PWM_Type *pwmout_allocate(uint16_t countertop, nrf_pwm_clk_t base_clock,
bool variable_frequency, int8_t *channel_out, bool *pwm_already_in_use_out) {
bool variable_frequency, int8_t *channel_out, bool *pwm_already_in_use_out,
IRQn_Type* irq) {
for (size_t pwm_index = 0; pwm_index < MP_ARRAY_SIZE(pwms); pwm_index++) {
NRF_PWM_Type *pwm = pwms[pwm_index];
bool pwm_already_in_use = pwm->ENABLE & SPIM_ENABLE_ENABLE_Msk;
bool pwm_already_in_use = pwm->ENABLE & PWM_ENABLE_ENABLE_Msk;
if (pwm_already_in_use) {
if (variable_frequency) {
// Variable frequency requires exclusive use of a PWM, so try the next one.
@ -156,20 +160,30 @@ NRF_PWM_Type *pwmout_allocate(uint16_t countertop, nrf_pwm_clk_t base_clock,
for (size_t chan = 0; chan < CHANNELS_PER_PWM; chan++) {
if (pwm->PSEL.OUT[chan] == 0xFFFFFFFF) {
// Channel is free.
if(channel_out)
if (channel_out) {
*channel_out = chan;
if(pwm_already_in_use_out)
}
if (pwm_already_in_use_out) {
*pwm_already_in_use_out = pwm_already_in_use;
}
if (irq) {
*irq = pwm_irqs[pwm_index];
}
return pwm;
}
}
}
} else {
// PWM not yet in use, so we can start to use it. Use channel 0.
if(channel_out)
if (channel_out) {
*channel_out = 0;
if(pwm_already_in_use_out)
}
if (pwm_already_in_use_out) {
*pwm_already_in_use_out = pwm_already_in_use;
}
if (irq) {
*irq = pwm_irqs[pwm_index];
}
return pwm;
}
}
@ -208,7 +222,7 @@ pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self,
int8_t channel;
bool pwm_already_in_use;
self->pwm = pwmout_allocate(countertop, base_clock, variable_frequency,
&channel, &pwm_already_in_use);
&channel, &pwm_already_in_use, NULL);
if (self->pwm == NULL) {
return PWMOUT_ALL_TIMERS_IN_USE;

View File

@ -42,7 +42,8 @@ typedef struct {
void pwmout_reset(void);
NRF_PWM_Type *pwmout_allocate(uint16_t countertop, nrf_pwm_clk_t base_clock,
bool variable_frequency, int8_t *channel_out, bool *pwm_already_in_use_out);
bool variable_frequency, int8_t *channel_out, bool *pwm_already_in_use_out,
IRQn_Type *irq);
void pwmout_free_channel(NRF_PWM_Type *pwm, int8_t channel);
#endif // MICROPY_INCLUDED_NRF_COMMON_HAL_PULSEIO_PWMOUT_H