Hopefully fix flash flush and hopefully audio as well.
This commit is contained in:
parent
418333979a
commit
ed5cdd7e09
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
Loading…
Reference in New Issue