Hopefully fix flash flush and hopefully audio as well.

This commit is contained in:
Scott Shawcroft 2020-03-10 15:05:42 -07:00
parent 418333979a
commit ed5cdd7e09
No known key found for this signature in database
GPG Key ID: 9349BC7E64B1921E
8 changed files with 78 additions and 5 deletions

View File

@ -283,6 +283,9 @@ void common_hal_audiobusio_i2sout_play(audiobusio_i2sout_obj_t* self,
i2s_buffer_fill(self); i2s_buffer_fill(self);
NRF_I2S->RXTXD.MAXCNT = self->buffer_length / 4; NRF_I2S->RXTXD.MAXCNT = self->buffer_length / 4;
// Turn on the interrupt to the NVIC but not within the NVIC itself. This will wake the CPU and
// keep it awake until it is serviced without triggering an interrupt handler.
NRF_I2S->INTENSET = I2S_INTENSET_TXPTRUPD_Msk;
NRF_I2S->ENABLE = I2S_ENABLE_ENABLE_Enabled; NRF_I2S->ENABLE = I2S_ENABLE_ENABLE_Enabled;
NRF_I2S->TASKS_START = 1; NRF_I2S->TASKS_START = 1;
@ -305,6 +308,7 @@ bool common_hal_audiobusio_i2sout_get_paused(audiobusio_i2sout_obj_t* self) {
void common_hal_audiobusio_i2sout_stop(audiobusio_i2sout_obj_t* self) { void common_hal_audiobusio_i2sout_stop(audiobusio_i2sout_obj_t* self) {
NRF_I2S->TASKS_STOP = 1; NRF_I2S->TASKS_STOP = 1;
self->stopping = true; self->stopping = true;
NRF_I2S->INTENCLR = I2S_INTENSET_TXPTRUPD_Msk;
} }
bool common_hal_audiobusio_i2sout_get_playing(audiobusio_i2sout_obj_t* self) { bool common_hal_audiobusio_i2sout_get_playing(audiobusio_i2sout_obj_t* self) {
@ -316,7 +320,7 @@ bool common_hal_audiobusio_i2sout_get_playing(audiobusio_i2sout_obj_t* self) {
} }
void i2s_background(void) { void i2s_background(void) {
if (NRF_I2S->EVENTS_TXPTRUPD) { if (NVIC_GetPendingIRQ(I2S_IRQn) && NRF_I2S->EVENTS_TXPTRUPD) {
NRF_I2S->EVENTS_TXPTRUPD = 0; NRF_I2S->EVENTS_TXPTRUPD = 0;
if (instance) { if (instance) {
i2s_buffer_fill(instance); i2s_buffer_fill(instance);
@ -328,6 +332,7 @@ void i2s_background(void) {
void i2s_reset(void) { void i2s_reset(void) {
NRF_I2S->TASKS_STOP = 1; NRF_I2S->TASKS_STOP = 1;
NRF_I2S->INTENCLR = I2S_INTENSET_TXPTRUPD_Msk;
NRF_I2S->ENABLE = I2S_ENABLE_ENABLE_Disabled; NRF_I2S->ENABLE = I2S_ENABLE_ENABLE_Disabled;
NRF_I2S->PSEL.MCK = 0xFFFFFFFF; NRF_I2S->PSEL.MCK = 0xFFFFFFFF;
NRF_I2S->PSEL.SCK = 0xFFFFFFFF; NRF_I2S->PSEL.SCK = 0xFFFFFFFF;

View File

@ -72,6 +72,8 @@ STATIC void activate_audiopwmout_obj(audiopwmio_pwmaudioout_obj_t *self) {
} }
} }
STATIC void deactivate_audiopwmout_obj(audiopwmio_pwmaudioout_obj_t *self) { STATIC void deactivate_audiopwmout_obj(audiopwmio_pwmaudioout_obj_t *self) {
// Turn off the interrupts to the CPU.
self->pwm->INTENCLR = PWM_INTENSET_SEQSTARTED0_Msk | PWM_INTENSET_SEQSTARTED1_Msk;
for (size_t i=0; i < MP_ARRAY_SIZE(active_audio); i++) { for (size_t i=0; i < MP_ARRAY_SIZE(active_audio); i++) {
if (active_audio[i] == self) { if (active_audio[i] == self) {
active_audio[i] = NULL; active_audio[i] = NULL;
@ -149,6 +151,14 @@ STATIC void audiopwmout_background_obj(audiopwmio_pwmaudioout_obj_t *self) {
} }
void audiopwmout_background() { void audiopwmout_background() {
// Check the NVIC first because it is part of the CPU and fast to read.
if (!NVIC_GetPendingIRQ(PWM0_IRQn) &&
!NVIC_GetPendingIRQ(PWM1_IRQn) &&
!NVIC_GetPendingIRQ(PWM2_IRQn) &&
!NVIC_GetPendingIRQ(PWM3_IRQn)) {
return;
}
// Check our objects because the PWM could be active for some other reason.
for (size_t i=0; i < MP_ARRAY_SIZE(active_audio); i++) { for (size_t i=0; i < MP_ARRAY_SIZE(active_audio); i++) {
if (!active_audio[i]) continue; if (!active_audio[i]) continue;
audiopwmout_background_obj(active_audio[i]); audiopwmout_background_obj(active_audio[i]);
@ -260,6 +270,9 @@ void common_hal_audiopwmio_pwmaudioout_play(audiopwmio_pwmaudioout_obj_t* self,
self->pwm->EVENTS_SEQEND[0] = 0; self->pwm->EVENTS_SEQEND[0] = 0;
self->pwm->EVENTS_SEQEND[1] = 0; self->pwm->EVENTS_SEQEND[1] = 0;
self->pwm->EVENTS_STOPPED = 0; self->pwm->EVENTS_STOPPED = 0;
// Enable the SEQSTARTED interrupts so that they wake the CPU and keep it awake until serviced.
// We don't enable them in the NVIC because we don't actually want an interrupt routine to run.
self->pwm->INTENSET = PWM_INTENSET_SEQSTARTED0_Msk | PWM_INTENSET_SEQSTARTED1_Msk;
self->pwm->TASKS_SEQSTART[0] = 1; self->pwm->TASKS_SEQSTART[0] = 1;
self->playing = true; self->playing = true;
self->paused = false; self->paused = false;

View File

@ -67,7 +67,7 @@ uint32_t supervisor_flash_get_block_count(void) {
return CIRCUITPY_INTERNAL_FLASH_FILESYSTEM_SIZE / FILESYSTEM_BLOCK_SIZE ; return CIRCUITPY_INTERNAL_FLASH_FILESYSTEM_SIZE / FILESYSTEM_BLOCK_SIZE ;
} }
void supervisor_flash_flush(void) { void port_internal_flash_flush(void) {
if (_flash_page_addr == NO_CACHE) return; if (_flash_page_addr == NO_CACHE) return;
// Skip if data is the same // Skip if data is the same

View File

@ -34,7 +34,7 @@
#ifdef EXTERNAL_FLASH_DEVICE_COUNT #ifdef EXTERNAL_FLASH_DEVICE_COUNT
#include "supervisor/shared/external_flash/external_flash.h" #include "supervisor/shared/external_flash/external_flash.h"
#else #else
#include "supervisor/internal_flash.h" #include "supervisor/shared/internal_flash.h"
#endif #endif
void supervisor_flash_init(void); void supervisor_flash_init(void);

View File

@ -23,11 +23,12 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
*/ */
#include "external_flash.h" #include "supervisor/shared/external_flash/external_flash.h"
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
#include "supervisor/flash.h"
#include "supervisor/spi_flash_api.h" #include "supervisor/spi_flash_api.h"
#include "supervisor/shared/external_flash/common_commands.h" #include "supervisor/shared/external_flash/common_commands.h"
#include "extmod/vfs.h" #include "extmod/vfs.h"
@ -451,7 +452,7 @@ static void spi_flash_flush_keep_cache(bool keep_cache) {
#endif #endif
} }
void supervisor_flash_flush(void) { void supervisor_external_flash_flush(void) {
spi_flash_flush_keep_cache(true); spi_flash_flush_keep_cache(true);
} }

View File

@ -45,4 +45,6 @@
#define SPI_FLASH_MAX_BAUDRATE 8000000 #define SPI_FLASH_MAX_BAUDRATE 8000000
#endif #endif
void supervisor_external_flash_flush(void);
#endif // MICROPY_INCLUDED_SUPERVISOR_SHARED_EXTERNAL_FLASH_EXTERNAL_FLASH_H #endif // MICROPY_INCLUDED_SUPERVISOR_SHARED_EXTERNAL_FLASH_EXTERNAL_FLASH_H

View File

@ -28,6 +28,7 @@
#include "extmod/vfs_fat.h" #include "extmod/vfs_fat.h"
#include "py/runtime.h" #include "py/runtime.h"
#include "lib/oofatfs/ff.h" #include "lib/oofatfs/ff.h"
#include "supervisor/shared/tick.h"
#define VFS_INDEX 0 #define VFS_INDEX 0
@ -110,6 +111,8 @@ mp_uint_t flash_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_bloc
return supervisor_flash_read_blocks(dest, block_num - PART1_START_BLOCK, num_blocks); return supervisor_flash_read_blocks(dest, block_num - PART1_START_BLOCK, num_blocks);
} }
volatile bool filesystem_dirty;
mp_uint_t flash_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t num_blocks) { mp_uint_t flash_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t num_blocks) {
if (block_num == 0) { if (block_num == 0) {
if (num_blocks > 1) { if (num_blocks > 1) {
@ -118,10 +121,26 @@ mp_uint_t flash_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t nu
// can't write MBR, but pretend we did // can't write MBR, but pretend we did
return 0; return 0;
} else { } else {
if (!filesystem_dirty) {
// Turn on ticks so that we can flush after a period of time elapses.
supervisor_enable_tick();
filesystem_dirty = true;
}
return supervisor_flash_write_blocks(src, block_num - PART1_START_BLOCK, num_blocks); return supervisor_flash_write_blocks(src, block_num - PART1_START_BLOCK, num_blocks);
} }
} }
void supervisor_flash_flush(void) {
#if INTERNAL_FLASH_FILESYSTEM
port_internal_flash_flush();
#else
supervisor_external_flash_flush();
#endif
// Turn off ticks now that our filesystem has been flushed.
supervisor_disable_tick();
filesystem_dirty = false;
}
STATIC mp_obj_t supervisor_flash_obj_readblocks(mp_obj_t self, mp_obj_t block_num, mp_obj_t buf) { STATIC mp_obj_t supervisor_flash_obj_readblocks(mp_obj_t self, mp_obj_t block_num, mp_obj_t buf) {
mp_buffer_info_t bufinfo; mp_buffer_info_t bufinfo;
mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_WRITE); mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_WRITE);

View File

@ -0,0 +1,33 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2020 Scott Shawcroft, for Adafruit Industries LLC
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MICROPY_INCLUDED_SUPERVISOR_SHARED_INTERNAL_FLASH_H
#define MICROPY_INCLUDED_SUPERVISOR_SHARED_INTERNAL_FLASH_H
#include "supervisor/internal_flash.h" // This is per-port.
void port_internal_flash_flush(void);
#endif // MICROPY_INCLUDED_SUPERVISOR_SHARED_INTERNAL_FLASH_H