When disabled, the pyb.I2C class saves around 8k of code space and 172
bytes of RAM. The same functionality is now available in machine.I2C
(for F4 and F7 MCUs).
It is still enabled by default.
This driver uses low-level register access to control the I2C peripheral
(ie it doesn't rely on the ST HAL) and provides the same C-level API as the
existing F7 hardware driver.
On this 32-bit arch there's no need to use the long version of the format
specifier. It's only there to appease the compiler which checks the type
of the args passed to printf. Removing the "l" saves a bit of code space.
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).
The problem is the existing code which tries to optimise the
reinitialisation of the DMA breaks the abstraction of the HAL. For the
STM32L4 the HAL's DMA setup code maintains two private vars (ChannelIndex,
DmaBaseAddress) and updates a hardware register (CCR).
In HAL_DMA_Init(), the CCR is updated to set the direction of the DMA.
This is a problem because, when using the SD Card interface, the same DMA
channel is used in both directions, so the direction bit in the CCR must
follow that.
A quick and effective fix for the L4 is to simply call HAL_DMA_DeInit() and
HAL_DMA_Init() every time.
ADC3 is used because the H7's internal ADC channels are connected to ADC3
and the uPy driver doesn't support more than one ADC.
Only 12-bit resolution is supported because 12 is hard-coded and 14/16 bits
are not recommended on some ADC3 pins (see errata).
Values from internal ADC channels are known to give wrong values at
present.
After calling HAL_SYSTICK_Config the SysTick IRQ priority is set to 15, the
lowest priority. This commit reconfigures the IRQ priority to the desired
TICK_INT_PRIORITY value.
By default the stm module is included in the build, but a board can now
define MICROPY_PY_STM to 0 to not include this module. This reduces the
firmware by about 7k.
To use HSE bypass mode the board should define:
#define MICROPY_HW_CLK_USE_BYPASS (1)
If this is not defined, or is defined to 0, then HSE oscillator mode is
used.
This patch allows a given board to configure which pins are used for the
CAN peripherals, in a similar way to all the other bus peripherals (I2C,
UART, SPI). To enable CAN on a board the mpconfigboard.h file should
define (for example):
#define MICROPY_HW_CAN1_TX (pin_B9)
#define MICROPY_HW_CAN1_RX (pin_B8)
#define MICROPY_HW_CAN2_TX (pin_B13)
#define MICROPY_HW_CAN2_RX (pin_B12)
And the board config file should no longer define MICROPY_HW_ENABLE_CAN.
The individual union members (like SPI, I2C) are never used, only the
generic "reg" entry is. And the union names can clash with macro
definitions in the HAL so better to remove them.
The only configuration that changes with this patch is that on L4 MCUs the
clock prescaler changed from ADC_CLOCK_ASYNC_DIV2 to ADC_CLOCK_ASYNC_DIV1
for the ADCAll object. This should be ok.
A value of DISABLE for EOCSelection is invalid. This would have been
interpreted instead as ADC_EOC_SEQ_CONV, but really it should be
ADC_EOC_SINGLE_CONV for the uses in this code. So this has been fixed.
ExternalTrigConv should be ADC_SOFTWARE_START because all ADC
conversions are started by software. This is now fixed.
This can be used to select the output buffer behaviour of the DAC. The
default values are chosen to retain backwards compatibility with existing
behaviour.
Thanks to @peterhinch for the initial idea to add this feature.
This patch moves the implementation of stream closure from a dedicated
method to the ioctl of the stream protocol, for each type that implements
closing. The benefits of this are:
1. Rounds out the stream ioctl function, which already includes flush,
seek and poll (among other things).
2. Makes calling mp_stream_close() on an object slightly more efficient
because it now no longer needs to lookup the close method and call it,
rather it just delegates straight to the ioctl function (if it exists).
3. Reduces code size and allows future types that implement the stream
protocol to be smaller because they don't need a dedicated close method.
Code size reduction is around 200 bytes smaller for x86 archs and around
30 bytes smaller for the bare-metal archs.
The main() function has a predefined type in C which is not so useful for
embedded contexts. This patch renames main() to stm32_main() so we can
define our own type signature for this function. The type signature is
defined to have a single argument which is the "reset_mode" and is passed
through as r0 from Reset_Handler. This allows, for example, a bootloader
to pass through information into the main application.
The Reset_Handler needs to copy the data section and zero the BSS, and
these operations should be as optimised as possible to reduce start up
time. The versions provided in this patch are about 2x faster (on a Cortex
M4) than the previous implementations.
Rather than pin objects themselves. The actual object is now pin_X_obj and
defines are provided so that pin_X is &pin_X_obj. This makes it so that
code that uses pin objects doesn't need to know if they are literals or
objects (that need pointers taken) or something else. They are just
entities that can be passed to the map_hal_pin_xxx functions. This mirrors
how the core handles constant objects (eg mp_const_none which is
&mp_const_none_obj) and allows for the possibility of different
implementations of the pin layer.
For example, prior to this patch there was the following:
extern const pin_obj_t pin_A0;
#define pyb_pin_X1 pin_A0
...
mp_hal_pin_high(&pin_A0);
and now there is:
extern const pin_obj_t pin_A0_obj;
#define pin_A0 (&pin_A0_obj)
#define pyb_pin_X1 pin_A0
...
mp_hal_pin_high(pin_A0);
This patch should have minimal effect on board configuration files. The
only change that may be needed is if a board has .c files that configure
pins.
This patch forces a board to explicitly define TEXT1_ADDR in order to
split the firmware into two separate pieces. Otherwise the default is now
to produce only a single continuous firmware image with all ISR, text and
data together.
This patch allows a particular board to independently specify the linker
scripts for 1) the MCU memory layout; 2) how the different firmware
sections are arranged in memory. Right now all boards follow the same
layout with two separate firmware section, one for the ISR and one for the
text and data. This leaves room for storage (filesystem data) to live
between the firmware sections.
The idea with this patch is to accommodate boards that don't have internal
flash storage and only need to have one continuous firmware section. Thus
the common.ld script is renamed to common_ifs.ld to make explicit that it
is used for cases where the board has internal flash storage.
Explicitly writing out the implementation of sys_tick_has_passed makes
these bdev files independent of systick.c and more reusable as a general
component. It also reduces the code size slightly.
The irq.h header is added to spibdev.c because it uses declarations in that
file (irq.h is usually included implicitly via mphalport.h but not always).
Taking the address assumes that the pin is an object (eg a struct), but it
could be a literal (eg an int). Not taking the address makes this driver
more general for other uses.
genhdr/pins.h is an internal header file that defines all of the pin
objects and it's cleaner to have pin.h include it (where the struct's for
these objects are defined) rather than an explicit include by every user.
The HAL requires strict aliasing optimisation to be turned on to function
correctly (at least for the SD card driver on F4 MCUs). This optimisation
was recently disabled with the addition of H7 support due to the H7 HAL
having errors with the strict aliasing optimisation enabled. But this is
now fixed in the latest stm32lib and so the optimisation can now be
re-enabled.
Thanks to @chuckbook for finding that there was a problem with the SD card
on F4 MCUs with the strict aliasing optimisation disabled.
The CMSIS files for the STM32 range provide macros to distinguish between
the different MCU series: STM32F4, STM32F7, STM32H7, STM32L4, etc. Prefer
to use these instead of custom ones.
This patch provides a custom (and simple) function to receive data on the
CAN bus, instead of the HAL function. This custom version calls
mp_handle_pending() while waiting for messages, which, among other things,
allows to interrupt the recv() method via KeyboardInterrupt.
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.
This patch alters the SPI-flash memory driver so that it uses the new
low-level C SPI protocol (from drivers/bus/spi.h) instead of the uPy SPI
protocol (from extmod/machine_spi.h). This allows the SPI-flash driver to
be used independently from the uPy runtime.
This patch takes the software SPI implementation from extmod/machine_spi.c
and moves it to a dedicated file in drivers/bus/softspi.c. This allows the
SPI driver to be used independently of the uPy runtime, making it a more
general component.
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 patch allows to completely compile-out support for USB, and no-USB is
now the default. If a board wants to enable USB it should define:
#define MICROPY_HW_ENABLE_USB (1)
And then one or more of the following to select the USB PHY:
#define MICROPY_HW_USB_FS (1)
#define MICROPY_HW_USB_HS (1)
#define MICROPY_HW_USB_HS_IN_FS (1)
Newer versions of the HAL use names which are cleaner and more
self-consistent amongst the HAL itself. This patch switches to use those
names in most places so it is easier to update the HAL in the future.
Prior to this patch the USBD driver did not handle the recipient correctly
for setup requests. It was not interpreting the req->wIndex field in the
right way: in some cases this field indicates the endpoint number but the
code was assuming it always indicated the interface number.
This patch fixes this. The only noticeable change is to the MSC
interface, which should now correctly respond to the USB_REQ_CLEAR_FEATURE
request and hence unmount properly from the host when requested.
mpconfigboard_common.h now sets the defaults so there is no longer a need
to explicitly list all configuration options in a board's mpconfigboard.h
file.
This file mirrors py/mpconfig.h but for board-level config options. It
provides a default configuration, to be overridden by a specific
mpconfigboard.h file, as well as setting up certain macros to automatically
configure a board.
The calls to rtc_init_start(), sdcard_init() and storage_init() are all
guarded by a check for first_soft_reset, so it's simpler to just put them
all before the soft-reset loop, without the check.
The call to machine_init() can also go before the soft-reset loop because
it is only needed to check the reset cause which can happen once at the
first boot. To allow this to work, the reset cause must be set to SOFT
upon a soft-reset, which is the role of the new function machine_deinit().
Upon boot the RTC early-init function should detect if LSE or LSI is
already selected/running and, if so, use it. When the LSI has previously
(in the previous reset cycle) been selected as the clock source the only
way to reliably tell is if the RTCSEL bits of the RCC_BDCR are set to the
correct LSI value. In particular the RCC_CSR bits for LSI control do not
indicate if the LSI is ready even if it is selected.
This patch removes the check on the RCC_CSR bits for the LSI being on and
ready and only uses the check on the RCC_BDCR to see if the LSI should be
used straightaway. This was tested on a PYBLITEv1.0 and with the patch the
LSI persists correctly as the RTC source as long as the backup domain
remains powered.
Previously, if LSE is selected but fails and the RTC falls back to LSI,
then the rtc_info flags would incorrectly state that LSE is used. This
patch fixes that by setting the bit in rtc_info only after the clock is
ready.
There is an underlying hardware SPI driver (built on top of the STM HAL)
and then on top of this sits the legacy pyb.SPI class as well as the
machine.SPI class. This patch improves the separation between these
layers, in particular decoupling machine.SPI from pyb.SPI.
The SPI sub-system is independent from the uPy state (eg the heap) and so
can safely persist across a soft reset. And this is actually necessary for
drivers that rely on SPI and that also need to persist across soft reset
(eg external SPI flash memory).
This patch adds support in the USBD configuration and CDC-MSC-HID class for
high-speed USB mode. To enable it the board configuration must define
USE_USB_HS, and either not define USE_USB_HS_IN_FS, or be an STM32F723 or
STM32F733 MCU which have a built-in HS PHY. High-speed mode is then
selected dynamically by passing "high_speed=True" to the pyb.usb_mode()
function, otherwise it defaults to full-speed mode.
This patch has been tested on an STM32F733.
By defining MICROPY_HW_USB_MAIN_DEV a given board can select to use either
USB_PHY_FS_ID or USB_PHY_HS_ID as the main USBD peripheral, on which the
REPL will appear. If not defined this will be automatically configured.
There's no need to have these as separate functions, they just take up
unnecessary code space and combining them allows to factor common code, and
also allows to support arbitrary string descriptor indices.
The routine waits for the DMA to finish, which is signalled from a DMA IRQ
handler. Using WFI makes the CPU sleep while waiting for the IRQ to arrive
which decreases power consumption. To make it work correctly the check for
the change in state must be atomic and so IRQs must be disabled during the
check. The key feature of the Cortex MCU that makes this possible is that
WFI will exit when an IRQ arrives even if IRQs are disabled.
This patch adds in internal config value MICROPY_HW_ENABLE_HW_I2C that is
automatically configured, and enabled only if one or more hardware I2C
ports are defined in the mpconfigboard.h file. If none are defined then
the pyb.I2C class is excluded from the build, along with all supporting
code. The machine.I2C class will still be available for software I2C.
Disabling all hardware I2C on an F4 board saves around 10,000 bytes of code
and 200 bytes of RAM.
This is a low-cost evaluation kit board from ST based on the STM32
Nucleo-144 form factor. It uses the STM32F746ZG MCU in the LQFP144
package. The MCU has 1MB of flash and 320kB of System RAM.
Cortex-M7 runs at up to 216MHz.