The pyb.Flash() class can now be used to construct objects which reference
sections of the flash storage, starting at a certain offset and going for a
certain length. Such objects also support the extended block protocol.
The signature for the constructor is: pyb.Flash(start=-1, len=-1).
This commit refactors and generalises the boot-mount routine on stm32 so
that it can mount filesystems of arbitrary type. That is, it no longer
assumes that the filesystem is FAT. It does this by using mp_vfs_mount()
which does auto-detection of the filesystem type.
Instead of checking each callback (currently storage and dma) explicitly
for each SysTick IRQ, use a simple circular function table indexed by the
lower bits of the millisecond tick counter. This allows callbacks to be
easily enabled/disabled at runtime, and scales well to a large number of
callbacks.
The flash-IRQ handler is used to flush the storage cache, ie write
outstanding block data from RAM to flash. This is triggered by a timeout,
or by a direct call to flush all storage caches.
Prior to this commit, a timeout could trigger the cache flushing to occur
during the execution of a read/write to external SPI flash storage. In
such a case the storage subsystem would break down.
SPI storage transfers are already protected against USB IRQs, so by
changing the priority of the flash IRQ to that of the USB IRQ (what is
done in this commit) the SPI transfers can be protected against any
timeouts triggering a cache flush (the cache flush would be postponed until
after the transfer finished, but note that in the case of SPI writes the
timeout is rescheduled after the transfer finishes).
The handling of internal flash sync'ing needs to be changed to directly
call flash_bdev_irq_handler() sync may be called with the IRQ priority
already raised (eg when called from a USB MSC IRQ handler).
With this and previous patches the stm32 port can now be compiled using
object representation D (nan boxing). Note that native code and frozen mpy
files with float constants are currently not supported with this object
representation.
If no block devices are defined by a board then storage support will be
disabled. This means there is no filesystem provided by either the
internal flash or external SPI flash. But the VFS system can still be
enabled and filesystems provided on external devices like an SD card.
For a given IRQn (eg UART) there's no need to carry around both a PRI and
SUBPRI value (eg IRQ_PRI_UART, IRQ_SUBPRI_UART). Instead, the IRQ_PRI_UART
value has been changed in this patch to be the encoded hardware value,
using NVIC_EncodePriority. This way the NVIC_SetPriority function can be
used directly, instead of going through HAL_NVIC_SetPriority which must do
extra processing to encode the PRI+SUBPRI.
For a priority grouping of 4 (4 bits for preempt priority, 0 bits for the
sub-priority), which is used in the stm32 port, the IRQ_PRI_xxx constants
remain unchanged in their value.
This patch also "fixes" the use of raise_irq_pri() which should be passed
the encoded value (but as mentioned above the unencoded value is the same
as the encoded value for priority grouping 4, so there was no bug from this
error).
This config variable controls whether to support storage on the internal
flash of the MCU. It is enabled by default and should be explicitly
disabled by boards that don't want internal flash storage.
It makes it cleaner, and simpler to support multiple different block
devices. It also allows to easily extend a given block device with new
ioctl operations.
Prior to this patch, storage.c was a combination of code that handled
either internal flash or external SPI flash and exposed one of them as a
block device for the local storage. It was also exposed to the USB MSC.
This patch splits out the flash and SPI code to separate files, which each
provide a general block-device interface (at the C level). Then storage.c
just picks one of them to use as the local storage medium. The aim of this
factoring is to allow to add new block devices in the future and allow for
easier configurability.
This is to keep the top-level directory clean, to make it clear what is
core and what is a port, and to allow the repository to grow with new ports
in a sustainable way.