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) { void i2s_background(void) {
if (NVIC_GetPendingIRQ(I2S_IRQn) && NRF_I2S->EVENTS_TXPTRUPD) { if (NVIC_GetPendingIRQ(I2S_IRQn) && NRF_I2S->EVENTS_TXPTRUPD) {
NRF_I2S->EVENTS_TXPTRUPD = 0; NRF_I2S->EVENTS_TXPTRUPD = 0;
NVIC_ClearPendingIRQ(I2S_IRQn);
if (instance) { if (instance) {
i2s_buffer_fill(instance); i2s_buffer_fill(instance);
} else { } else {

View File

@ -88,7 +88,6 @@ void audiopwmout_reset() {
} }
STATIC void fill_buffers(audiopwmio_pwmaudioout_obj_t *self, int buf) { 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]; uint16_t *dev_buffer = self->buffers[buf];
uint8_t *buffer; uint8_t *buffer;
uint32_t buffer_length; uint32_t buffer_length;
@ -145,8 +144,15 @@ STATIC void audiopwmout_background_obj(audiopwmio_pwmaudioout_obj_t *self) {
if (stopped) if (stopped)
self->pwm->TASKS_STOP = 1; self->pwm->TASKS_STOP = 1;
} else if (!self->paused && !self->single_buffer) { } else if (!self->paused && !self->single_buffer) {
if (self->pwm->EVENTS_SEQSTARTED[0]) fill_buffers(self, 1); if (self->pwm->EVENTS_SEQSTARTED[0]) {
if (self->pwm->EVENTS_SEQSTARTED[1]) fill_buffers(self, 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. // Caller validates that pins are free.
void common_hal_audiopwmio_pwmaudioout_construct(audiopwmio_pwmaudioout_obj_t* self, 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) { 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) { if (!self->pwm) {
mp_raise_RuntimeError(translate("All timers in use")); mp_raise_RuntimeError(translate("All timers in use"));
} }

View File

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

View File

@ -139,11 +139,15 @@ bool convert_frequency(uint32_t frequency, uint16_t *countertop, nrf_pwm_clk_t *
return false; 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, 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++) { for (size_t pwm_index = 0; pwm_index < MP_ARRAY_SIZE(pwms); pwm_index++) {
NRF_PWM_Type *pwm = 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 (pwm_already_in_use) {
if (variable_frequency) { if (variable_frequency) {
// Variable frequency requires exclusive use of a PWM, so try the next one. // 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++) { for (size_t chan = 0; chan < CHANNELS_PER_PWM; chan++) {
if (pwm->PSEL.OUT[chan] == 0xFFFFFFFF) { if (pwm->PSEL.OUT[chan] == 0xFFFFFFFF) {
// Channel is free. // Channel is free.
if(channel_out) if (channel_out) {
*channel_out = chan; *channel_out = chan;
if(pwm_already_in_use_out) }
if (pwm_already_in_use_out) {
*pwm_already_in_use_out = pwm_already_in_use; *pwm_already_in_use_out = pwm_already_in_use;
}
if (irq) {
*irq = pwm_irqs[pwm_index];
}
return pwm; return pwm;
} }
} }
} }
} else { } else {
// PWM not yet in use, so we can start to use it. Use channel 0. // PWM not yet in use, so we can start to use it. Use channel 0.
if(channel_out) if (channel_out) {
*channel_out = 0; *channel_out = 0;
if(pwm_already_in_use_out) }
if (pwm_already_in_use_out) {
*pwm_already_in_use_out = pwm_already_in_use; *pwm_already_in_use_out = pwm_already_in_use;
}
if (irq) {
*irq = pwm_irqs[pwm_index];
}
return pwm; return pwm;
} }
} }
@ -208,7 +222,7 @@ pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self,
int8_t channel; int8_t channel;
bool pwm_already_in_use; bool pwm_already_in_use;
self->pwm = pwmout_allocate(countertop, base_clock, variable_frequency, self->pwm = pwmout_allocate(countertop, base_clock, variable_frequency,
&channel, &pwm_already_in_use); &channel, &pwm_already_in_use, NULL);
if (self->pwm == NULL) { if (self->pwm == NULL) {
return PWMOUT_ALL_TIMERS_IN_USE; return PWMOUT_ALL_TIMERS_IN_USE;

View File

@ -42,7 +42,8 @@ typedef struct {
void pwmout_reset(void); void pwmout_reset(void);
NRF_PWM_Type *pwmout_allocate(uint16_t countertop, nrf_pwm_clk_t base_clock, 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); void pwmout_free_channel(NRF_PWM_Type *pwm, int8_t channel);
#endif // MICROPY_INCLUDED_NRF_COMMON_HAL_PULSEIO_PWMOUT_H #endif // MICROPY_INCLUDED_NRF_COMMON_HAL_PULSEIO_PWMOUT_H