summaryrefslogtreecommitdiffstatshomepage
path: root/stmhal
diff options
context:
space:
mode:
authorDamien George <damien.p.george@gmail.com>2017-08-13 21:33:40 +1000
committerDamien George <damien.p.george@gmail.com>2017-08-13 21:33:40 +1000
commite52758da223e57b6cd9458f039f8ccc50ee76ddb (patch)
tree2d5218ad0e1f30c686f51f5807b5676fe0007fe5 /stmhal
parentbe2387885bf251fb44b6b64aeadff147a4ae7266 (diff)
parent9b39263b118a4be65c58bf9c396203fa535bebe1 (diff)
downloadmicropython-e52758da223e57b6cd9458f039f8ccc50ee76ddb.tar.gz
micropython-e52758da223e57b6cd9458f039f8ccc50ee76ddb.zip
Merge tag 'v1.8.1' into parse-bytecode
Many ESP8266 improvements, enhanced WebREPL, and support for STM32L4 MCUs This release brings general improvements and bug fixes, and some new features. There is now a uerror module for consistent errno handling across ports, as well as textual names of OS errors that are printed when an OSError is raised. There is support for frozen packages, via both frozen scripts and frozen bytecode. WebREPL on the ESP8266 is greatly improved with many bug fixes and now supports an unlimited (or very large) number of reconnects. The os module on the ESP8266 now has rename, chdir, getcwd and stat. The unix port now includes the ussl module by default. The stmhal port has support for STM32L4 MCUs including the STM32L476 Discovery board and the LimiFrog board. README: - add explicit note that subdirs contain more READMEs - add "make deplibs" to quick build section - "quick build": Use "make axtls" after all CODECONVENTIONS.md: - describe git commit messages conventions py core: - obj: add warning note about get_array return value and GC blocks - objstr: binary type of str/bytes for buffer protocol is 'B' - runtime: properly handle passing user mappings to ** keyword args - repl: if there're no better alternatives, try to complete "import" - mpz: fix bug with overflowing C-shift in division routine - mpz: do Python style division/modulo within bignum divmod routine - mpz: fix mpn_div so that it doesn't modify memory of denominator - vstr: vstr_null_terminated_str(): Extend string by at most one byte - vstr: change allocation policy, +16 to requested size, instead of *2 - add mperrno.h file with uPy defined errno constants - add uerrno module, with errno constants and dict - parse: add uerrno to list of modules to look for constants in - mperrno: add EAFNOSUPPORT definition - repl: fix handling of backslash in quotes when checking continuation - gc: gc_dump_alloc_table(): Show byte/str and (byte)array objects - gc: make (byte)array type dumping conditional on these types being enabled - gc: use '=' char for tail blocks when dumping heap - mperrno: add some more MP_Exxx constants, related to networking - moduerrno: add more constants to the errno module - add mp_errno_to_str() and use it to provide nicer OSError msgs - objfloat, py/modmath: ensure M_PI and M_E defined - emitglue: fix build on AArch64 (ARMv8, etc.) related to loading .mpy files - objexcept: don't convert errno to str in constructor, do it in print - moduerrno: add EACCES, pretty common error on Unix - gc: gc_dump_alloc_table(): dump heap offset instead of actual address - objstr: make dedicated splitlines function, supporting diff newlines - objstringio: add TODO comment about avoiding copying on .getvalue() - modstruct: raise ValueError on unsupported format char - stream: support both "exact size" and "one underlying call" operations - declare constant data as properly constant - stream: add mp_stream_close() helper function - mphal.h: provide default prototypes for mp_hal_delay_us/mp_hal_ticks_us - rework frozen modules support to support packages - objstr: implement str.center() - allow to stat and import frozen mpy files using new frozen "VFS" - makeqstrdata.py: allow to have double-quote characters in qstrs - objnamedtuple: allow passing field names as a tuple - moduerrno: add EEXIST, EISDIR, ECONNREFUSED - modstruct: allow to have "0s" in struct format extmod: - modlwip: convert errno's to use MP_Exxx symbols - modlwip: rework how Python accept callback is called - when including extmod headers, prefix path with extmod/ - modwebsocket: add close() method - modwebrepl: add close() method - moduos_dupterm: dumpterm subsystem is responsible for closing stream - modussl: make more compatible with non-default obj representations - machine_i2c: redo mp_hal_pin macros to use open_drain and od_low - virtpin: initial implementation of open-ended C-level Pin interface - vfs_fat: replace text error messages by POSIX error numbers - vfs_fat: add chdir() method - vfs_fat: add getcwd() method - vfs_fat: add vfs.stat() method - add machine time_pulse_us function (at C and Python level) - machine: add MICROPY_PY_MACHINE_PULSE config for time_pulse_us lib: - timeutils/timeutils: timeutils_mktime may accept negative time values drivers: - cc3000: rename timeval to cc3000_timeval, to avoid clash - add C-level function to read DHT11 and DHT22 devices - display/ssd1306: update SSD1306_SPI to work with new API tools: - make-frozen.py: properly escape hex chars when making C strings - make-frozen.py: quick fix to support package-modules - mpy-tool.py: add checks for critical configuration vars - make-frozen.py: update for latest changes in frozen modules support - mpy-tool.py: include .py extension in frozen filename - mpy-tool.py: don't strip directories from the frozen source name - upgrade upip to 0.7: SSL cert warning, use uerrno, better usage message tests: - run-tests: factor out list of supported external boards - disable memoryview tests that overflow int conversion - basics/string_splitlines: reinstate feature test for splitlines - struct1: add testcase for an unknown type char - add testcase for str.center() - extmod/vfs_fat_ramdisk: add testcases for chdir(), getcwd() - misc/recursive_iternext.py: increase depth N from 1000 to 2000 - misc/recursive_iternext.py: provide more fine-grained selection of N - pyb/rtc: make RTC test on pyboard more reliable by calling init() mpy-cross: - add -s option to specify the embedded source filename unix port: - mphalport: add mp_hal_delay_us() for consistency with other ports - enable uerrno module - add ability to include frozen bytecode in the build - mpconfigport_coverage.h: add dedicated config file for coverage build - unix_mphal: implement mp_hal_ticks_us() - support frozen packages - Makefile: nanbox build is not compatible with modussl, disable - enable "ussl" module - mpconfigport.mk: document MICROPY_STANDALONE make-level option - Makefile: "make axtls": automatically fetch submodules if missing windows port: - enable multi-processor compilation for msvc stmhal port: - l4: adapt DMA to be able to support STM32L4 MCU series - l4: adapt startup code, clock configuration and interrupts - l4: make CCM/DTCM RAM start-up conditional on MCU type - l4: add support for machine.sleep on STM32L4 MCUs - dma: make DAC DMA descriptors conditional on having a DAC - add board files for LIMIFROG board - for LIMIFROG board, add early-init function to get to DFU mode - dma: fix builds for boards with an F4 or F7 but no DAC - sdcard: fix initialisation of DMA TX so that writes work - can: allow to get existing CAN obj if constructed without args - fix clock configuration for STM32L476-discovery; also add I2C2 - convert to use internal errno symbols; enable uerrno module - for network drivers, convert to use MP_Exxx errno symbols - led: allow LEDs to be in PWM mode with TIM1 and channels 1-4 - i2c: expose I2CHandle3 for use by custom C code - sdcard: allow to do unaligned read-from/write-to SD card - support frozen packages using .mpy files - moduos: getcwd(): use mp_obj_new_exception_arg1() - dac: add DAC deinit() method - uart: fix wrong baudrate calculation for stm32l4 series esp8266 port: - scripts/: remove use of pin.PULL_NONE - scripts/inisetup: don't start WebREPL on boot in master branch - scripts/: add fill() to NeoPixel - scripts/webrepl: add optional password argument to webrepl.start() - scripts/webrepl: add start_foreground() method - main: bump heap size to 28K - mpconfigport: reduce various parser-related allocation params - help: add "sta_if.active(True)" command - convert to use new MP_Exxx errno symbols - enable uerrno module, weak linked also as errno - change to use internal errno's - moduos.c: addition of the rename method to module uos - scripts/port_diag: add network diagnostic output - scripts/webrepl_setup: show password placeholder char - scripts/webrepl_setup: add max password length check - README: add a very first start section - add APA102 serial individually controllable LEDs support - enable collections.OrderedDict - main: update _boot module loading for recent frozen modules refactors - scripts/port_diag: dump network interface IP settings - esp_mphal: fix NLR buffer leak in call_dupterm_read() - esp_mphal: handle Ctrl+C from dupterm (e.g. WebREPL) - esp_mphal: mp_uos_dupterm_deactivate() may raise exception - add mp_hal_pin_input() and mp_hal_pin_output() functions - modpybspi: configure pins when initialising an SPI object - xtirq: add xtirq.h for controlling xtensa irqs - ets_alt_task: don't run ets_loop_iter if irqs are disabled - modmachine: add disable_irq and enable_irq functions - enable DHT C-level driver - add dht.py script for high-level control of DHT11/DHT22 sensor - Makefile: document "disable" value for UART_OS - modnetwork: scan() is only supported by STA when it's enabled - modnetwork: protect scan() callback against memory errors - modnetwork: allow to press ctrl-C while scan() is running - uart: properly initialise UART0 RXD pin in uart_config - moduos: add chdir() and getcwd() functions - scripts/ntptime: allow to override NTP server - modmachine: add machine.time_pulse_us function - enable MICROPY_PY_IO_FILEIO to get compliant text/binary streams - moduos.c: add stat() to the module uos of esp8266 - rtc: set RTC user memory length to 0 on first boot - provide a dedicated variable to disable ets_loop_iter - modpybrtc: handle RTC overflow docs: - machine.UART: filter out unimplemented UART methods from esp8266 docs - esp8266/quickref: new way to get MAC address - esp8266/quickstart: remove i2c examples with stop=False - ustruct: describe supported type codes - ussl: add basic description of axTLS-based modussl - esp8266: Include ussl module in the docs - machine: make disable_irq and enable_irq docs available for all - library/machine: add documentation for machine.time_pulse_us - math, cmath: add port availability information - library/index: add intro paragraph regarding availability of modules - README: add some hints for PDF docs generation - wipy/tutorial: add note about screen key bindings on OS X - esp8266/quickref: update WebREPL section for 1.8.1 release - esp8266: fix ESP8266 Network tutorial - esp8266/quickref: use local image of Adafruit Huzzah board - esp8266/general: add note about RTC overflow travis: - install gcc-arm-none-eabi with --force-yes for now
Diffstat (limited to 'stmhal')
-rw-r--r--stmhal/Makefile12
-rw-r--r--stmhal/boards/LIMIFROG/board_init.c154
-rw-r--r--stmhal/boards/LIMIFROG/mpconfigboard.h71
-rw-r--r--stmhal/boards/LIMIFROG/mpconfigboard.mk4
-rw-r--r--stmhal/boards/LIMIFROG/pins.csv114
-rw-r--r--stmhal/boards/LIMIFROG/stm32l4xx_hal_conf.h373
-rw-r--r--stmhal/boards/PYBLITEV10/mpconfigboard.h4
-rw-r--r--stmhal/boards/PYBV10/mpconfigboard.h4
-rw-r--r--stmhal/boards/PYBV11/mpconfigboard.h4
-rw-r--r--stmhal/boards/PYBV3/mpconfigboard.h3
-rw-r--r--stmhal/boards/PYBV4/mpconfigboard.h4
-rw-r--r--stmhal/boards/STM32L476DISC/mpconfigboard.h8
-rw-r--r--stmhal/boards/stm32l476xe.ld134
-rw-r--r--stmhal/can.c63
-rw-r--r--stmhal/dac.c54
-rw-r--r--stmhal/dma.c425
-rw-r--r--stmhal/dma.h138
-rw-r--r--stmhal/i2c.c51
-rw-r--r--stmhal/i2c.h1
-rw-r--r--stmhal/led.c52
-rw-r--r--stmhal/main.c16
-rw-r--r--stmhal/modmachine.c42
-rw-r--r--stmhal/modnetwork.c1
-rw-r--r--stmhal/modnwcc3k.c18
-rw-r--r--stmhal/modnwwiznet5k.c18
-rw-r--r--stmhal/moduos.c2
-rw-r--r--stmhal/moduselect.c4
-rw-r--r--stmhal/modusocket.c12
-rw-r--r--stmhal/mpconfigport.h3
-rw-r--r--stmhal/mphalport.c8
-rw-r--r--stmhal/mphalport.h4
-rw-r--r--stmhal/pybstdio.c6
-rw-r--r--stmhal/sdcard.c85
-rw-r--r--stmhal/spi.c54
-rw-r--r--stmhal/startup_stm32.S205
-rw-r--r--stmhal/stm32_it.c41
-rw-r--r--stmhal/system_stm32.c140
-rw-r--r--stmhal/uart.c16
-rw-r--r--stmhal/usb.c10
39 files changed, 1934 insertions, 424 deletions
diff --git a/stmhal/Makefile b/stmhal/Makefile
index fffedd326c..1ad2783fca 100644
--- a/stmhal/Makefile
+++ b/stmhal/Makefile
@@ -284,24 +284,22 @@ endif
ifneq ($(FROZEN_MPY_DIR),)
# To use frozen bytecode, put your .py files in a subdirectory (eg frozen/) and
# then invoke make with FROZEN_MPY_DIR=frozen (be sure to build from scratch).
-FROZEN_MPY_PY_FILES := $(wildcard $(FROZEN_MPY_DIR)/*.py)
+FROZEN_MPY_PY_FILES := $(shell find $(FROZEN_MPY_DIR)/ -type f -name '*.py')
FROZEN_MPY_MPY_FILES := $(addprefix $(BUILD)/,$(FROZEN_MPY_PY_FILES:.py=.mpy))
CFLAGS += -DMICROPY_QSTR_EXTRA_POOL=mp_qstr_frozen_const_pool
CFLAGS += -DMICROPY_MODULE_FROZEN_MPY
-OBJ += $(BUILD)/$(FROZEN_MPY_DIR)/frozen_mpy.o
+OBJ += $(BUILD)/$(BUILD)/frozen_mpy.o
MPY_CROSS = ../mpy-cross/mpy-cross
MPY_TOOL = ../tools/mpy-tool.py
$(BUILD)/$(FROZEN_MPY_DIR)/%.mpy: $(FROZEN_MPY_DIR)/%.py
@$(ECHO) "MPY $<"
- $(Q)$(MPY_CROSS) -o $@ $^
+ $(Q)$(MKDIR) -p $(dir $@)
+ $(Q)$(MPY_CROSS) -o $@ -s $(^:$(FROZEN_MPY_DIR)/%=%) $^
-$(BUILD)/$(FROZEN_MPY_DIR)/frozen_mpy.c: $(FROZEN_MPY_MPY_FILES) $(BUILD)/genhdr/qstrdefs.generated.h
+$(BUILD)/frozen_mpy.c: $(FROZEN_MPY_MPY_FILES) $(BUILD)/genhdr/qstrdefs.generated.h
@$(ECHO) "Creating $@"
$(Q)$(PYTHON) $(MPY_TOOL) -f -q $(BUILD)/genhdr/qstrdefs.preprocessed.h $(FROZEN_MPY_MPY_FILES) > $@
-
-$(BUILD)/$(FROZEN_MPY_DIR)/frozen_mpy.o: $(BUILD)/$(FROZEN_MPY_DIR)/frozen_mpy.c
- $(call compile_c)
endif
.PHONY: deploy
diff --git a/stmhal/boards/LIMIFROG/board_init.c b/stmhal/boards/LIMIFROG/board_init.c
new file mode 100644
index 0000000000..72f9208424
--- /dev/null
+++ b/stmhal/boards/LIMIFROG/board_init.c
@@ -0,0 +1,154 @@
+// The code is this file allows the user to enter DFU mode when the board
+// starts up, by connecting POS10 on the external connector to GND.
+// The code itself is taken from the LimiFrog software repository found at
+// https://github.com/LimiFrog/LimiFrog-SW, and the original license header
+// is copied below.
+
+#include STM32_HAL_H
+
+static void LBF_DFU_If_Needed(void);
+
+void LIMIFROG_board_early_init(void) {
+ LBF_DFU_If_Needed();
+}
+
+/*******************************************************************************
+ * LBF_DFU_If_Needed.c
+ *
+ * (c)2015 LimiFrog / CYMEYA
+ * This program is licensed under the terms of the MIT License.
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND.
+ * Please refer to the License File LICENSE.txt located at the root of this
+ * project for full licensing conditions,
+ * or visit https://opensource.org/licenses/MIT.
+ ******************************************************************************/
+
+#define __LIMIFROG_02
+
+/* ==== BTLE (excl UART) ======================================== */
+// PC9 = BT_RST (active high)
+
+#define BT_RST_PIN GPIO_PIN_9
+#define BT_RST_PORT GPIOC
+
+// Position 10
+#ifdef __LIMIFROG_01
+ #define CONN_POS10_PIN GPIO_PIN_9
+ #define CONN_POS10_PORT GPIOB
+#else
+ #define CONN_POS10_PIN GPIO_PIN_8
+ #define CONN_POS10_PORT GPIOB
+#endif
+
+static inline void GPIO_HIGH(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
+{
+ GPIOx->BSRR = (uint32_t)GPIO_Pin;
+}
+
+static inline int IS_GPIO_RESET(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
+{
+ GPIO_PinState bitstatus;
+ if((GPIOx->IDR & GPIO_Pin) != (uint32_t)GPIO_PIN_RESET)
+ {
+ bitstatus = GPIO_PIN_SET;
+ }
+ else
+ {
+ bitstatus = GPIO_PIN_RESET;
+ }
+ return (bitstatus==GPIO_PIN_RESET);
+}
+
+/**************************************************************
+ RATIONALE FOR THIS FUNCTION :
+
+ - The STM32 embeds in ROM a bootloader that allows to
+ obtain code and boot from a number of different interfaces,
+ including USB in a mode called "DFU" (Device Frimware Update)
+ [see AN3606 from ST for full details]
+ This bootloader code is executed instead of the regular
+ application code when pin BOOT0 is pulled-up (which on
+ LimiFrog0.2 is achieved by pressing the general-purpose
+ pushbutton switch on the side.
+ - The bootloader monitors a number of IOs of the STM32 to decide
+ from which interface it should boot.
+ - Problem in LimiFrog (up to versions 0.2a at least): upon
+ power-up the BLE modules generates some activity on UART3,
+ which is part of the pins monitored by the STM32.
+ This misleads the bootloader in trying to boot from UART3
+ and, as a result, not continuing with booting from USB.
+
+ - This code implements an alternative solution to launch the
+ bootloader while making sure UART3 remains stable.
+ - The idea it to start application code with a check, prior to any
+ other applicative code, of whether USB bootload is required (as
+ flagged by a GPIO pulled low at reset, in the same way as BOOT0).
+ The hadware reset pin of BLE is asserted (so that now it won't
+ generate any acitivity on UART3), and if USB bootload is required :
+ bootload ROM is remapped at address 0x0, stack pointer is
+ updated and the code is branched to the start of the bootloader.
+ - This code is run prior to any applicative configuration of clocks,
+ IRQs etc. -- the STM32 is therefore still running from MSI
+
+ THIS FUNCTION MAY BE SUPPRESSED IF YOU NEVER NEED TO BOOT DFU MODE
+
+ ********************************************************************/
+
+static void LBF_DFU_If_Needed(void)
+{
+
+
+ GPIO_InitTypeDef GPIO_InitStruct;
+
+
+ // Initialize and assert pin BTLE_RST
+ // (hw reset to BLE module, so it won't drive UART3)
+
+ __GPIOC_CLK_ENABLE();
+ GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
+ GPIO_InitStruct.Pin = BT_RST_PIN;
+ HAL_GPIO_Init(BT_RST_PORT, &GPIO_InitStruct);
+
+ GPIO_HIGH(BT_RST_PORT, BT_RST_PIN); // assert BTLE reset
+
+
+ /* -- Bootloader will be called if position 10 on the extension port
+ is actively pulled low -- */
+ // Note - this is an arbitrary choice, code could be modified to
+ // monitor another GPIO of the STM32 and/or decide that active level
+ // is high rather than low
+
+
+ // Initialize Extension Port Position 10 = PB8 (bears I2C1_SCL)
+ // Use weak pull-up to detect if pin is externally pulled low
+
+ __GPIOB_CLK_ENABLE();
+ GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
+ GPIO_InitStruct.Pull = GPIO_PULLUP;
+ GPIO_InitStruct.Pin = CONN_POS10_PIN;
+ HAL_GPIO_Init(CONN_POS10_PORT, &GPIO_InitStruct);
+
+ // If selection pin pulled low...
+ if ( IS_GPIO_RESET(CONN_POS10_PORT, CONN_POS10_PIN ))
+
+ {
+ // Remap bootloader ROM (ie System Flash) to address 0x0
+ SYSCFG->MEMRMP = 0x00000001;
+
+ // Init stack pointer with value residing at ROM base
+ asm (
+ "LDR R0, =0x00000000\n\t" // load ROM base address"
+ "LDR SP,[R0, #0]\n\t" // assign main stack pointer"
+ );
+
+ // Jump to address pointed by 0x00000004 -- */
+
+ asm (
+ "LDR R0,[R0, #4]\n\t" // load bootloader address
+ "BX R0\n\t"
+ );
+
+ }
+}
diff --git a/stmhal/boards/LIMIFROG/mpconfigboard.h b/stmhal/boards/LIMIFROG/mpconfigboard.h
new file mode 100644
index 0000000000..782c9c90f8
--- /dev/null
+++ b/stmhal/boards/LIMIFROG/mpconfigboard.h
@@ -0,0 +1,71 @@
+#include STM32_HAL_H
+
+#define MICROPY_HW_BOARD_NAME "LIMIFROG"
+#define MICROPY_HW_MCU_NAME "STM32L476"
+
+#define MICROPY_HW_HAS_SWITCH (1)
+#define MICROPY_HW_HAS_FLASH (1)
+#define MICROPY_HW_HAS_SDCARD (0)
+#define MICROPY_HW_HAS_MMA7660 (0)
+#define MICROPY_HW_HAS_LIS3DSH (0)
+#define MICROPY_HW_HAS_LCD (0)
+#define MICROPY_HW_ENABLE_RNG (1)
+#define MICROPY_HW_ENABLE_RTC (1)
+#define MICROPY_HW_ENABLE_TIMER (1)
+#define MICROPY_HW_ENABLE_SERVO (0)
+#define MICROPY_HW_ENABLE_DAC (0)
+#define MICROPY_HW_ENABLE_CAN (0)
+
+#define MICROPY_BOARD_EARLY_INIT LIMIFROG_board_early_init
+void LIMIFROG_board_early_init(void);
+
+// MSI is used and is 4MHz
+#define MICROPY_HW_CLK_PLLM (1)
+#define MICROPY_HW_CLK_PLLN (40)
+#define MICROPY_HW_CLK_PLLP (RCC_PLLP_DIV7)
+#define MICROPY_HW_CLK_PLLR (RCC_PLLR_DIV2)
+#define MICROPY_HW_CLK_PLLQ (RCC_PLLQ_DIV2)
+
+#define MICROPY_HW_FLASH_LATENCY FLASH_LATENCY_4
+
+// USART config
+#define MICROPY_HW_UART3_PORT (GPIOC)
+#define MICROPY_HW_UART3_PINS (GPIO_PIN_10 | GPIO_PIN_11)
+
+// I2C busses
+#define MICROPY_HW_I2C1_SCL (pin_B8)
+#define MICROPY_HW_I2C1_SDA (pin_B9)
+#define MICROPY_HW_I2C2_SCL (pin_B10)
+#define MICROPY_HW_I2C2_SDA (pin_B11)
+// We use an array of baudrates and corresponding TIMINGR values.
+//
+// The value 0x90112626 was obtained from the DISCOVERY_I2C1_TIMING constant
+// defined in the STM32L4Cube file Drivers/BSP/STM32L476G-Discovery/stm32l476g_discovery.h
+#define MICROPY_HW_I2C_BAUDRATE_TIMING {{100000, 0x90112626}}
+#define MICROPY_HW_I2C_BAUDRATE_DEFAULT 100000
+#define MICROPY_HW_I2C_BAUDRATE_MAX 100000
+
+// SPI busses
+#define MICROPY_HW_SPI1_NSS (pin_A4)
+#define MICROPY_HW_SPI1_SCK (pin_A5)
+#define MICROPY_HW_SPI1_MISO (pin_A6)
+#define MICROPY_HW_SPI1_MOSI (pin_A7)
+
+#define MICROPY_HW_SPI3_NSS (pin_A15)
+#define MICROPY_HW_SPI3_SCK (pin_B3)
+#define MICROPY_HW_SPI3_MISO (pin_B4)
+#define MICROPY_HW_SPI3_MOSI (pin_B5)
+
+#define MICROPY_HW_USRSW_PIN (pin_A15)
+#define MICROPY_HW_USRSW_PULL (GPIO_NOPULL)
+#define MICROPY_HW_USRSW_EXTI_MODE (GPIO_MODE_IT_RISING)
+#define MICROPY_HW_USRSW_PRESSED (1)
+
+// LEDs
+#define MICROPY_HW_LED1 (pin_C3) // red
+#define MICROPY_HW_LED_OTYPE (GPIO_MODE_OUTPUT_PP)
+#define MICROPY_HW_LED_ON(pin) (pin->gpio->BSRR = pin->pin_mask)
+#define MICROPY_HW_LED_OFF(pin) (pin->gpio->BSRR = pin->pin_mask<<16)
+
+// USB config
+// #define MICROPY_HW_USB_OTG_ID_PIN (pin_C12) // This is not the official ID Pin which should be PA10
diff --git a/stmhal/boards/LIMIFROG/mpconfigboard.mk b/stmhal/boards/LIMIFROG/mpconfigboard.mk
new file mode 100644
index 0000000000..cb89e25f5b
--- /dev/null
+++ b/stmhal/boards/LIMIFROG/mpconfigboard.mk
@@ -0,0 +1,4 @@
+MCU_SERIES = l4
+CMSIS_MCU = STM32L476xx
+AF_FILE = boards/stm32l476_af.csv
+LD_FILE = boards/stm32l476xe.ld
diff --git a/stmhal/boards/LIMIFROG/pins.csv b/stmhal/boards/LIMIFROG/pins.csv
new file mode 100644
index 0000000000..52f96b669c
--- /dev/null
+++ b/stmhal/boards/LIMIFROG/pins.csv
@@ -0,0 +1,114 @@
+PA0,PA0
+PA1,PA1
+PA2,PA2
+PA3,PA3
+PA4,PA4
+PA5,PA5
+PA6,PA6
+PA7,PA7
+PA8,PA8
+PA9,PA9
+PA10,PA10
+PA11,PA11
+PA12,PA12
+PA13,PA13
+PA14,PA14
+PA15,PA15
+PB0,PB0
+PB1,PB1
+PB2,PB2
+PB3,PB3
+PB4,PB4
+PB5,PB5
+PB6,PB6
+PB7,PB7
+PB8,PB8
+PB9,PB9
+PB10,PB10
+PB11,PB11
+PB12,PB12
+PB13,PB13
+PB14,PB14
+PB15,PB15
+PC0,PC0
+PC1,PC1
+PC2,PC2
+PC3,PC3
+PC4,PC4
+PC5,PC5
+PC6,PC6
+PC7,PC7
+PC8,PC8
+PC9,PC9
+PC10,PC10
+PC11,PC11
+PC12,PC12
+PC13,PC13
+PC14,PC14
+PC15,PC15
+PD0,PD0
+PD1,PD1
+PD2,PD2
+PD3,PD3
+PD4,PD4
+PD5,PD5
+PD6,PD6
+PD7,PD7
+PD8,PD8
+PD9,PD9
+PD10,PD10
+PD11,PD11
+PD12,PD12
+PD13,PD13
+PD14,PD14
+PD15,PD15
+PE0,PE0
+PE1,PE1
+PE2,PE2
+PE3,PE3
+PE4,PE4
+PE5,PE5
+PE6,PE6
+PE7,PE7
+PE8,PE8
+PE9,PE9
+PE10,PE10
+PE11,PE11
+PE12,PE12
+PE13,PE13
+PE14,PE14
+PE15,PE15
+PF0,PF0
+PF1,PF1
+PF2,PF2
+PF3,PF3
+PF4,PF4
+PF5,PF5
+PF6,PF6
+PF7,PF7
+PF8,PF8
+PF9,PF9
+PF10,PF10
+PF11,PF11
+PF12,PF12
+PF13,PF13
+PF14,PF14
+PF15,PF15
+PG0,PG0
+PG1,PG1
+PG2,PG2
+PG3,PG3
+PG4,PG4
+PG5,PG5
+PG6,PG6
+PG7,PG7
+PG8,PG8
+PG9,PG9
+PG10,PG10
+PG11,PG11
+PG12,PG12
+PG13,PG13
+PG14,PG14
+PG15,PG15
+PH0,PH0
+PH1,PH1
diff --git a/stmhal/boards/LIMIFROG/stm32l4xx_hal_conf.h b/stmhal/boards/LIMIFROG/stm32l4xx_hal_conf.h
new file mode 100644
index 0000000000..9348e06790
--- /dev/null
+++ b/stmhal/boards/LIMIFROG/stm32l4xx_hal_conf.h
@@ -0,0 +1,373 @@
+/**
+ ******************************************************************************
+ * @file stm32l4xx_hal_conf.h
+ * @author MCD Application Team
+ * @version V1.2.0
+ * @date 25-November-2015
+ * @brief HAL configuration template file.
+ * This file should be copied to the application folder and renamed
+ * to stm32l4xx_hal_conf.h.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of STMicroelectronics nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM32L4xx_HAL_CONF_H
+#define __STM32L4xx_HAL_CONF_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+#define USE_USB_FS
+/* Exported types ------------------------------------------------------------*/
+/* Exported constants --------------------------------------------------------*/
+
+/* ########################## Module Selection ############################## */
+/**
+ * @brief This is the list of modules to be used in the HAL driver
+ */
+#define HAL_MODULE_ENABLED
+#define HAL_ADC_MODULE_ENABLED
+#define HAL_CAN_MODULE_ENABLED
+/* #define HAL_COMP_MODULE_ENABLED */
+#define HAL_CORTEX_MODULE_ENABLED
+/* #define HAL_CRC_MODULE_ENABLED */
+/* #define HAL_CRYP_MODULE_ENABLED */
+#define HAL_DAC_MODULE_ENABLED
+/* #define HAL_DFSDM_MODULE_ENABLED */
+#define HAL_DMA_MODULE_ENABLED
+/* #define HAL_FIREWALL_MODULE_ENABLED */
+#define HAL_FLASH_MODULE_ENABLED
+/* #define HAL_HCD_MODULE_ENABLED */
+/* #define HAL_NAND_MODULE_ENABLED */
+/* #define HAL_NOR_MODULE_ENABLED */
+/* #define HAL_SRAM_MODULE_ENABLED */
+#define HAL_GPIO_MODULE_ENABLED
+#define HAL_I2C_MODULE_ENABLED
+/* #define HAL_IRDA_MODULE_ENABLED */
+/* #define HAL_IWDG_MODULE_ENABLED */
+/* #define HAL_LCD_MODULE_ENABLED */
+/* #define HAL_LPTIM_MODULE_ENABLED */
+/* #define HAL_OPAMP_MODULE_ENABLED */
+#define HAL_PCD_MODULE_ENABLED
+#define HAL_PWR_MODULE_ENABLED
+/* #define HAL_QSPI_MODULE_ENABLED */
+#define HAL_RCC_MODULE_ENABLED
+#define HAL_RNG_MODULE_ENABLED
+#define HAL_RTC_MODULE_ENABLED
+/* #define HAL_SAI_MODULE_ENABLED */
+#define HAL_SD_MODULE_ENABLED
+/* #define HAL_SMARTCARD_MODULE_ENABLED */
+/* #define HAL_SMBUS_MODULE_ENABLED */
+#define HAL_SPI_MODULE_ENABLED
+/* #define HAL_SWPMI_MODULE_ENABLED */
+#define HAL_TIM_MODULE_ENABLED
+/* #define HAL_TSC_MODULE_ENABLED */
+#define HAL_UART_MODULE_ENABLED
+/* #define HAL_USART_MODULE_ENABLED */
+/* #define HAL_WWDG_MODULE_ENABLED */
+
+
+/* ########################## Oscillator Values adaptation ####################*/
+/**
+ * @brief Adjust the value of External High Speed oscillator (HSE) used in your application.
+ * This value is used by the RCC HAL module to compute the system frequency
+ * (when HSE is used as system clock source, directly or through the PLL).
+ */
+#if !defined (HSE_VALUE)
+ #define HSE_VALUE ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */
+#endif /* HSE_VALUE */
+
+#if !defined (HSE_STARTUP_TIMEOUT)
+ #define HSE_STARTUP_TIMEOUT ((uint32_t)100) /*!< Time out for HSE start up, in ms */
+#endif /* HSE_STARTUP_TIMEOUT */
+
+/**
+ * @brief Internal Multiple Speed oscillator (MSI) default value.
+ * This value is the default MSI range value after Reset.
+ */
+#if !defined (MSI_VALUE)
+ #define MSI_VALUE ((uint32_t)4000000) /*!< Value of the Internal oscillator in Hz*/
+#endif /* MSI_VALUE */
+
+/**
+ * @brief Internal High Speed oscillator (HSI) value.
+ * This value is used by the RCC HAL module to compute the system frequency
+ * (when HSI is used as system clock source, directly or through the PLL).
+ */
+#if !defined (HSI_VALUE)
+ #define HSI_VALUE ((uint32_t)16000000) /*!< Value of the Internal oscillator in Hz*/
+#endif /* HSI_VALUE */
+
+/**
+ * @brief Internal Low Speed oscillator (LSI) value.
+ */
+#if !defined (LSI_VALUE)
+ #define LSI_VALUE ((uint32_t)32000) /*!< LSI Typical Value in Hz*/
+#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz
+ The real value may vary depending on the variations
+ in voltage and temperature. */
+/**
+ * @brief External Low Speed oscillator (LSE) value.
+ * This value is used by the UART, RTC HAL module to compute the system frequency
+ */
+#if !defined (LSE_VALUE)
+ #define LSE_VALUE ((uint32_t)32768) /*!< Value of the External oscillator in Hz*/
+#endif /* LSE_VALUE */
+
+#if !defined (LSE_STARTUP_TIMEOUT)
+ #define LSE_STARTUP_TIMEOUT ((uint32_t)5000) /*!< Time out for LSE start up, in ms */
+#endif /* HSE_STARTUP_TIMEOUT */
+
+/**
+ * @brief External clock source for SAI1 peripheral
+ * This value is used by the RCC HAL module to compute the SAI1 & SAI2 clock source
+ * frequency.
+ */
+#if !defined (EXTERNAL_SAI1_CLOCK_VALUE)
+ #define EXTERNAL_SAI1_CLOCK_VALUE ((uint32_t)48000) /*!< Value of the SAI1 External clock source in Hz*/
+#endif /* EXTERNAL_SAI1_CLOCK_VALUE */
+
+/**
+ * @brief External clock source for SAI2 peripheral
+ * This value is used by the RCC HAL module to compute the SAI1 & SAI2 clock source
+ * frequency.
+ */
+#if !defined (EXTERNAL_SAI2_CLOCK_VALUE)
+ #define EXTERNAL_SAI2_CLOCK_VALUE ((uint32_t)48000) /*!< Value of the SAI2 External clock source in Hz*/
+#endif /* EXTERNAL_SAI2_CLOCK_VALUE */
+
+/* Tip: To avoid modifying this file each time you need to use different HSE,
+ === you can define the HSE value in your toolchain compiler preprocessor. */
+
+/* ########################### System Configuration ######################### */
+/**
+ * @brief This is the HAL system configuration section
+ */
+#define VDD_VALUE ((uint32_t)3300) /*!< Value of VDD in mv */
+#define TICK_INT_PRIORITY ((uint32_t)0x00) /*!< tick interrupt priority */
+#define USE_RTOS 0
+#define PREFETCH_ENABLE 1
+#define INSTRUCTION_CACHE_ENABLE 1
+#define DATA_CACHE_ENABLE 1
+
+/* ########################## Assert Selection ############################## */
+/**
+ * @brief Uncomment the line below to expanse the "assert_param" macro in the
+ * HAL drivers code
+ */
+/* #define USE_FULL_ASSERT 1 */
+
+/* Includes ------------------------------------------------------------------*/
+/**
+ * @brief Include module's header file
+ */
+
+#ifdef HAL_RCC_MODULE_ENABLED
+ #include "stm32l4xx_hal_rcc.h"
+#endif /* HAL_RCC_MODULE_ENABLED */
+
+#ifdef HAL_GPIO_MODULE_ENABLED
+ #include "stm32l4xx_hal_gpio.h"
+#endif /* HAL_GPIO_MODULE_ENABLED */
+
+#ifdef HAL_DMA_MODULE_ENABLED
+ #include "stm32l4xx_hal_dma.h"
+#endif /* HAL_DMA_MODULE_ENABLED */
+
+#ifdef HAL_DFSDM_MODULE_ENABLED
+ #include "stm32l4xx_hal_dfsdm.h"
+#endif /* HAL_DFSDM_MODULE_ENABLED */
+
+#ifdef HAL_CORTEX_MODULE_ENABLED
+ #include "stm32l4xx_hal_cortex.h"
+#endif /* HAL_CORTEX_MODULE_ENABLED */
+
+#ifdef HAL_ADC_MODULE_ENABLED
+ #include "stm32l4xx_hal_adc.h"
+#endif /* HAL_ADC_MODULE_ENABLED */
+
+#ifdef HAL_CAN_MODULE_ENABLED
+ #include "stm32l4xx_hal_can.h"
+#endif /* HAL_CAN_MODULE_ENABLED */
+
+#ifdef HAL_COMP_MODULE_ENABLED
+ #include "stm32l4xx_hal_comp.h"
+#endif /* HAL_COMP_MODULE_ENABLED */
+
+#ifdef HAL_CRC_MODULE_ENABLED
+ #include "stm32l4xx_hal_crc.h"
+#endif /* HAL_CRC_MODULE_ENABLED */
+
+#ifdef HAL_CRYP_MODULE_ENABLED
+ #include "stm32l4xx_hal_cryp.h"
+#endif /* HAL_CRYP_MODULE_ENABLED */
+
+#ifdef HAL_DAC_MODULE_ENABLED
+ #include "stm32l4xx_hal_dac.h"
+#endif /* HAL_DAC_MODULE_ENABLED */
+
+#ifdef HAL_FIREWALL_MODULE_ENABLED
+ #include "stm32l4xx_hal_firewall.h"
+#endif /* HAL_FIREWALL_MODULE_ENABLED */
+
+#ifdef HAL_FLASH_MODULE_ENABLED
+ #include "stm32l4xx_hal_flash.h"
+#endif /* HAL_FLASH_MODULE_ENABLED */
+
+#ifdef HAL_SRAM_MODULE_ENABLED
+ #include "stm32l4xx_hal_sram.h"
+#endif /* HAL_SRAM_MODULE_ENABLED */
+
+#ifdef HAL_NOR_MODULE_ENABLED
+ #include "stm32l4xx_hal_nor.h"
+#endif /* HAL_NOR_MODULE_ENABLED */
+
+#ifdef HAL_NAND_MODULE_ENABLED
+ #include "stm32l4xx_hal_nand.h"
+#endif /* HAL_NAND_MODULE_ENABLED */
+
+#ifdef HAL_I2C_MODULE_ENABLED
+ #include "stm32l4xx_hal_i2c.h"
+#endif /* HAL_I2C_MODULE_ENABLED */
+
+#ifdef HAL_IWDG_MODULE_ENABLED
+ #include "stm32l4xx_hal_iwdg.h"
+#endif /* HAL_IWDG_MODULE_ENABLED */
+
+#ifdef HAL_LCD_MODULE_ENABLED
+ #include "stm32l4xx_hal_lcd.h"
+#endif /* HAL_LCD_MODULE_ENABLED */
+
+#ifdef HAL_LPTIM_MODULE_ENABLED
+#include "stm32l4xx_hal_lptim.h"
+#endif /* HAL_LPTIM_MODULE_ENABLED */
+
+#ifdef HAL_OPAMP_MODULE_ENABLED
+#include "stm32l4xx_hal_opamp.h"
+#endif /* HAL_OPAMP_MODULE_ENABLED */
+
+#ifdef HAL_PWR_MODULE_ENABLED
+ #include "stm32l4xx_hal_pwr.h"
+#endif /* HAL_PWR_MODULE_ENABLED */
+
+#ifdef HAL_QSPI_MODULE_ENABLED
+ #include "stm32l4xx_hal_qspi.h"
+#endif /* HAL_QSPI_MODULE_ENABLED */
+
+#ifdef HAL_RNG_MODULE_ENABLED
+ #include "stm32l4xx_hal_rng.h"
+#endif /* HAL_RNG_MODULE_ENABLED */
+
+#ifdef HAL_RTC_MODULE_ENABLED
+ #include "stm32l4xx_hal_rtc.h"
+#endif /* HAL_RTC_MODULE_ENABLED */
+
+#ifdef HAL_SAI_MODULE_ENABLED
+ #include "stm32l4xx_hal_sai.h"
+#endif /* HAL_SAI_MODULE_ENABLED */
+
+#ifdef HAL_SD_MODULE_ENABLED
+ #include "stm32l4xx_hal_sd.h"
+#endif /* HAL_SD_MODULE_ENABLED */
+
+#ifdef HAL_SMBUS_MODULE_ENABLED
+ #include "stm32l4xx_hal_smbus.h"
+#endif /* HAL_SMBUS_MODULE_ENABLED */
+
+#ifdef HAL_SPI_MODULE_ENABLED
+ #include "stm32l4xx_hal_spi.h"
+#endif /* HAL_SPI_MODULE_ENABLED */
+
+#ifdef HAL_SWPMI_MODULE_ENABLED
+ #include "stm32l4xx_hal_swpmi.h"
+#endif /* HAL_SWPMI_MODULE_ENABLED */
+
+#ifdef HAL_TIM_MODULE_ENABLED
+ #include "stm32l4xx_hal_tim.h"
+#endif /* HAL_TIM_MODULE_ENABLED */
+
+#ifdef HAL_TSC_MODULE_ENABLED
+ #include "stm32l4xx_hal_tsc.h"
+#endif /* HAL_TSC_MODULE_ENABLED */
+
+#ifdef HAL_UART_MODULE_ENABLED
+ #include "stm32l4xx_hal_uart.h"
+#endif /* HAL_UART_MODULE_ENABLED */
+
+#ifdef HAL_USART_MODULE_ENABLED
+ #include "stm32l4xx_hal_usart.h"
+#endif /* HAL_USART_MODULE_ENABLED */
+
+#ifdef HAL_IRDA_MODULE_ENABLED
+ #include "stm32l4xx_hal_irda.h"
+#endif /* HAL_IRDA_MODULE_ENABLED */
+
+#ifdef HAL_SMARTCARD_MODULE_ENABLED
+ #include "stm32l4xx_hal_smartcard.h"
+#endif /* HAL_SMARTCARD_MODULE_ENABLED */
+
+#ifdef HAL_WWDG_MODULE_ENABLED
+ #include "stm32l4xx_hal_wwdg.h"
+#endif /* HAL_WWDG_MODULE_ENABLED */
+
+#ifdef HAL_PCD_MODULE_ENABLED
+ #include "stm32l4xx_hal_pcd.h"
+#endif /* HAL_PCD_MODULE_ENABLED */
+
+#ifdef HAL_HCD_MODULE_ENABLED
+ #include "stm32l4xx_hal_hcd.h"
+#endif /* HAL_HCD_MODULE_ENABLED */
+
+/* Exported macro ------------------------------------------------------------*/
+#ifdef USE_FULL_ASSERT
+/**
+ * @brief The assert_param macro is used for function's parameters check.
+ * @param expr: If expr is false, it calls assert_failed function
+ * which reports the name of the source file and the source
+ * line number of the call that failed.
+ * If expr is true, it returns no value.
+ * @retval None
+ */
+ #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__))
+/* Exported functions ------------------------------------------------------- */
+ void assert_failed(uint8_t* file, uint32_t line);
+#else
+ #define assert_param(expr) ((void)0)
+#endif /* USE_FULL_ASSERT */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __STM32L4xx_HAL_CONF_H */
+
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/boards/PYBLITEV10/mpconfigboard.h b/stmhal/boards/PYBLITEV10/mpconfigboard.h
index 97c972095a..83dcb938b3 100644
--- a/stmhal/boards/PYBLITEV10/mpconfigboard.h
+++ b/stmhal/boards/PYBLITEV10/mpconfigboard.h
@@ -71,8 +71,8 @@
#define MICROPY_HW_LED2 (pin_A14) // green
#define MICROPY_HW_LED3 (pin_A15) // yellow
#define MICROPY_HW_LED4 (pin_B4) // blue
-#define MICROPY_HW_LED3_PWM { TIM2, 2, GPIO_AF1_TIM2 }
-#define MICROPY_HW_LED4_PWM { TIM3, 3, GPIO_AF2_TIM3 }
+#define MICROPY_HW_LED3_PWM { TIM2, 2, TIM_CHANNEL_1, GPIO_AF1_TIM2 }
+#define MICROPY_HW_LED4_PWM { TIM3, 3, TIM_CHANNEL_1, GPIO_AF2_TIM3 }
#define MICROPY_HW_LED_OTYPE (GPIO_MODE_OUTPUT_PP)
#define MICROPY_HW_LED_ON(pin) (pin->gpio->BSRRL = pin->pin_mask)
#define MICROPY_HW_LED_OFF(pin) (pin->gpio->BSRRH = pin->pin_mask)
diff --git a/stmhal/boards/PYBV10/mpconfigboard.h b/stmhal/boards/PYBV10/mpconfigboard.h
index bc1d848b77..c654ec9a70 100644
--- a/stmhal/boards/PYBV10/mpconfigboard.h
+++ b/stmhal/boards/PYBV10/mpconfigboard.h
@@ -82,8 +82,8 @@
#define MICROPY_HW_LED2 (pin_A14) // green
#define MICROPY_HW_LED3 (pin_A15) // yellow
#define MICROPY_HW_LED4 (pin_B4) // blue
-#define MICROPY_HW_LED3_PWM { TIM2, 2, GPIO_AF1_TIM2 }
-#define MICROPY_HW_LED4_PWM { TIM3, 3, GPIO_AF2_TIM3 }
+#define MICROPY_HW_LED3_PWM { TIM2, 2, TIM_CHANNEL_1, GPIO_AF1_TIM2 }
+#define MICROPY_HW_LED4_PWM { TIM3, 3, TIM_CHANNEL_1, GPIO_AF2_TIM3 }
#define MICROPY_HW_LED_OTYPE (GPIO_MODE_OUTPUT_PP)
#define MICROPY_HW_LED_ON(pin) (pin->gpio->BSRRL = pin->pin_mask)
#define MICROPY_HW_LED_OFF(pin) (pin->gpio->BSRRH = pin->pin_mask)
diff --git a/stmhal/boards/PYBV11/mpconfigboard.h b/stmhal/boards/PYBV11/mpconfigboard.h
index b3c0983e34..9b5b7de27b 100644
--- a/stmhal/boards/PYBV11/mpconfigboard.h
+++ b/stmhal/boards/PYBV11/mpconfigboard.h
@@ -82,8 +82,8 @@
#define MICROPY_HW_LED2 (pin_A14) // green
#define MICROPY_HW_LED3 (pin_A15) // yellow
#define MICROPY_HW_LED4 (pin_B4) // blue
-#define MICROPY_HW_LED3_PWM { TIM2, 2, GPIO_AF1_TIM2 }
-#define MICROPY_HW_LED4_PWM { TIM3, 3, GPIO_AF2_TIM3 }
+#define MICROPY_HW_LED3_PWM { TIM2, 2, TIM_CHANNEL_1, GPIO_AF1_TIM2 }
+#define MICROPY_HW_LED4_PWM { TIM3, 3, TIM_CHANNEL_1, GPIO_AF2_TIM3 }
#define MICROPY_HW_LED_OTYPE (GPIO_MODE_OUTPUT_PP)
#define MICROPY_HW_LED_ON(pin) (pin->gpio->BSRRL = pin->pin_mask)
#define MICROPY_HW_LED_OFF(pin) (pin->gpio->BSRRH = pin->pin_mask)
diff --git a/stmhal/boards/PYBV3/mpconfigboard.h b/stmhal/boards/PYBV3/mpconfigboard.h
index 67877fd0b2..44fb221610 100644
--- a/stmhal/boards/PYBV3/mpconfigboard.h
+++ b/stmhal/boards/PYBV3/mpconfigboard.h
@@ -66,10 +66,13 @@
#define MICROPY_HW_USRSW_PRESSED (0)
// LEDs
+#define MICROPY_HW_LED_INVERTED (1) // LEDs are on when pin is driven low
#define MICROPY_HW_LED1 (pin_A8) // R1 - red
#define MICROPY_HW_LED2 (pin_A10) // R2 - red
#define MICROPY_HW_LED3 (pin_C4) // G1 - green
#define MICROPY_HW_LED4 (pin_C5) // G2 - green
+#define MICROPY_HW_LED1_PWM { TIM1, 1, TIM_CHANNEL_1, GPIO_AF1_TIM1 }
+#define MICROPY_HW_LED2_PWM { TIM1, 1, TIM_CHANNEL_3, GPIO_AF1_TIM1 }
#define MICROPY_HW_LED_OTYPE (GPIO_MODE_OUTPUT_PP)
#define MICROPY_HW_LED_ON(pin) (pin->gpio->BSRRH = pin->pin_mask)
#define MICROPY_HW_LED_OFF(pin) (pin->gpio->BSRRL = pin->pin_mask)
diff --git a/stmhal/boards/PYBV4/mpconfigboard.h b/stmhal/boards/PYBV4/mpconfigboard.h
index 7c75508ed4..cc931fb6bf 100644
--- a/stmhal/boards/PYBV4/mpconfigboard.h
+++ b/stmhal/boards/PYBV4/mpconfigboard.h
@@ -79,8 +79,8 @@
#define MICROPY_HW_LED2 (pin_A14) // green
#define MICROPY_HW_LED3 (pin_A15) // yellow
#define MICROPY_HW_LED4 (pin_B4) // blue
-#define MICROPY_HW_LED3_PWM { TIM2, 2, GPIO_AF1_TIM2 }
-#define MICROPY_HW_LED4_PWM { TIM3, 3, GPIO_AF2_TIM3 }
+#define MICROPY_HW_LED3_PWM { TIM2, 2, TIM_CHANNEL_1, GPIO_AF1_TIM2 }
+#define MICROPY_HW_LED4_PWM { TIM3, 3, TIM_CHANNEL_1, GPIO_AF2_TIM3 }
#define MICROPY_HW_LED_OTYPE (GPIO_MODE_OUTPUT_PP)
#define MICROPY_HW_LED_ON(pin) (pin->gpio->BSRRL = pin->pin_mask)
#define MICROPY_HW_LED_OFF(pin) (pin->gpio->BSRRH = pin->pin_mask)
diff --git a/stmhal/boards/STM32L476DISC/mpconfigboard.h b/stmhal/boards/STM32L476DISC/mpconfigboard.h
index f4617e67df..79857ccc26 100644
--- a/stmhal/boards/STM32L476DISC/mpconfigboard.h
+++ b/stmhal/boards/STM32L476DISC/mpconfigboard.h
@@ -16,11 +16,11 @@
#define MICROPY_HW_ENABLE_DAC (0)
#define MICROPY_HW_ENABLE_CAN (0)
-// HSE is 8MHz
-#define MICROPY_HW_CLK_PLLM (2)
+// MSI is used and is 4MHz
+#define MICROPY_HW_CLK_PLLM (1)
#define MICROPY_HW_CLK_PLLN (40)
#define MICROPY_HW_CLK_PLLP (RCC_PLLP_DIV7)
-#define MICROPY_HW_CLK_PLLR (RCC_PLLP_DIV7)
+#define MICROPY_HW_CLK_PLLR (RCC_PLLR_DIV2)
#define MICROPY_HW_CLK_PLLQ (RCC_PLLQ_DIV2)
#define MICROPY_HW_FLASH_LATENCY FLASH_LATENCY_4
@@ -32,6 +32,8 @@
// I2C busses
#define MICROPY_HW_I2C1_SCL (pin_B6)
#define MICROPY_HW_I2C1_SDA (pin_B7)
+#define MICROPY_HW_I2C2_SCL (pin_B10)
+#define MICROPY_HW_I2C2_SDA (pin_B11)
// We use an array of baudrates and corresponding TIMINGR values.
//
// The value 0x90112626 was obtained from the DISCOVERY_I2C1_TIMING constant
diff --git a/stmhal/boards/stm32l476xe.ld b/stmhal/boards/stm32l476xe.ld
new file mode 100644
index 0000000000..a4b1ce0974
--- /dev/null
+++ b/stmhal/boards/stm32l476xe.ld
@@ -0,0 +1,134 @@
+/*
+ GNU linker script for STM32L476XE
+*/
+
+/* Specify the memory areas */
+MEMORY
+{
+ FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 512K
+ FLASH_ISR (rx) : ORIGIN = 0x08000000, LENGTH = 0x0000800 /* sector 0, 2 KiB */
+ FLASH_FS (r) : ORIGIN = 0x08000800, LENGTH = 0x001F800 /* sectors 1-63 (2K each = 126 KiB) */
+ FLASH_TEXT (rx) : ORIGIN = 0x08020000, LENGTH = 0x0060000 /* Sector starting @ 64 */
+ RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 96K
+ SRAM2 (xrw) : ORIGIN = 0x10000000, LENGTH = 32K
+}
+
+ENTRY(Reset_Handler)
+
+/* produce a link error if there is not this amount of RAM for these sections */
+_minimum_stack_size = 2K;
+_minimum_heap_size = 16K;
+
+/* Define the top end of the stack. The stack is full descending so begins just
+ above last byte of RAM. Note that EABI requires the stack to be 8-byte
+ aligned for a call. */
+_estack = ORIGIN(RAM) + LENGTH(RAM);
+
+/* RAM extents for the garbage collector */
+_ram_end = ORIGIN(RAM) + LENGTH(RAM);
+_heap_end = 0x20014000; /* tunable */
+
+
+/* define output sections */
+SECTIONS
+{
+ /* The startup code goes first into FLASH */
+ .isr_vector :
+ {
+ . = ALIGN(4);
+ KEEP(*(.isr_vector)) /* Startup code */
+
+ . = ALIGN(4);
+ } >FLASH_ISR
+
+ /* The program code and other data goes into FLASH */
+ .text :
+ {
+ . = ALIGN(4);
+ *(.text) /* .text sections (code) */
+ *(.text*) /* .text* sections (code) */
+ *(.rodata) /* .rodata sections (constants, strings, etc.) */
+ *(.rodata*) /* .rodata* sections (constants, strings, etc.) */
+ /* *(.glue_7) */ /* glue arm to thumb code */
+ /* *(.glue_7t) */ /* glue thumb to arm code */
+
+ . = ALIGN(4);
+ _etext = .; /* define a global symbol at end of code */
+ } >FLASH_TEXT
+
+ /*
+ .ARM.extab :
+ {
+ *(.ARM.extab* .gnu.linkonce.armextab.*)
+ } >FLASH
+
+ .ARM :
+ {
+ __exidx_start = .;
+ *(.ARM.exidx*)
+ __exidx_end = .;
+ } >FLASH
+ */
+
+ /* used by the startup to initialize data */
+ _sidata = LOADADDR(.data);
+
+ /* This is the initialized data section
+ The program executes knowing that the data is in the RAM
+ but the loader puts the initial values in the FLASH (inidata).
+ It is one task of the startup to copy the initial values from FLASH to RAM. */
+ .data :
+ {
+ . = ALIGN(4);
+ _sdata = .; /* create a global symbol at data start; used by startup code in order to initialise the .data section in RAM */
+ _ram_start = .; /* create a global symbol at ram start for garbage collector */
+ *(.data) /* .data sections */
+ *(.data*) /* .data* sections */
+
+ . = ALIGN(4);
+ _edata = .; /* define a global symbol at data end; used by startup code in order to initialise the .data section in RAM */
+ } >RAM AT> FLASH_TEXT
+
+ /* Uninitialized data section */
+ .bss :
+ {
+ . = ALIGN(4);
+ _sbss = .; /* define a global symbol at bss start; used by startup code */
+ *(.bss)
+ *(.bss*)
+ *(COMMON)
+
+ . = ALIGN(4);
+ _ebss = .; /* define a global symbol at bss end; used by startup code and GC */
+ } >RAM
+
+ /* this is to define the start of the heap, and make sure we have a minimum size */
+ .heap :
+ {
+ . = ALIGN(4);
+ PROVIDE ( end = . );
+ PROVIDE ( _end = . );
+ _heap_start = .; /* define a global symbol at heap start */
+ . = . + _minimum_heap_size;
+ } >RAM
+
+ /* this just checks there is enough RAM for the stack */
+ .stack :
+ {
+ . = ALIGN(4);
+ . = . + _minimum_stack_size;
+ . = ALIGN(4);
+ } >RAM
+
+ /* Remove information from the standard libraries */
+ /*
+ /DISCARD/ :
+ {
+ libc.a ( * )
+ libm.a ( * )
+ libgcc.a ( * )
+ }
+ */
+
+ .ARM.attributes 0 : { *(.ARM.attributes) }
+}
diff --git a/stmhal/can.c b/stmhal/can.c
index b2330cd9c1..262c487f62 100644
--- a/stmhal/can.c
+++ b/stmhal/can.c
@@ -27,12 +27,12 @@
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
-#include <errno.h>
#include "py/nlr.h"
#include "py/objtuple.h"
#include "py/runtime.h"
#include "py/gc.h"
+#include "py/mperrno.h"
#include "py/mphal.h"
#include "bufhelper.h"
#include "can.h"
@@ -343,44 +343,61 @@ STATIC mp_obj_t pyb_can_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp
// check arguments
mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
- // create object
- pyb_can_obj_t *o = m_new_obj(pyb_can_obj_t);
- o->base.type = &pyb_can_type;
- o->is_enabled = false;
-
// work out port
- o->can_id = 0;
+ mp_uint_t can_idx;
if (MP_OBJ_IS_STR(args[0])) {
const char *port = mp_obj_str_get_str(args[0]);
if (0) {
#ifdef MICROPY_HW_CAN1_NAME
} else if (strcmp(port, MICROPY_HW_CAN1_NAME) == 0) {
- o->can_id = PYB_CAN_1;
+ can_idx = PYB_CAN_1;
#endif
#ifdef MICROPY_HW_CAN2_NAME
} else if (strcmp(port, MICROPY_HW_CAN2_NAME) == 0) {
- o->can_id = PYB_CAN_2;
+ can_idx = PYB_CAN_2;
#endif
} else {
- nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "CAN port %s does not exist", port));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "CAN(%s) does not exist", port));
}
} else {
- o->can_id = mp_obj_get_int(args[0]);
+ can_idx = mp_obj_get_int(args[0]);
+ }
+ if (can_idx < 1 || can_idx > MP_ARRAY_SIZE(MP_STATE_PORT(pyb_can_obj_all))) {
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "CAN(%d) does not exist", can_idx));
+ }
+
+ pyb_can_obj_t *self;
+ if (MP_STATE_PORT(pyb_can_obj_all)[can_idx - 1] == NULL) {
+ self = m_new_obj(pyb_can_obj_t);
+ self->base.type = &pyb_can_type;
+ self->can_id = can_idx;
+ self->is_enabled = false;
+ MP_STATE_PORT(pyb_can_obj_all)[can_idx - 1] = self;
+ } else {
+ self = MP_STATE_PORT(pyb_can_obj_all)[can_idx - 1];
}
- o->rxcallback0 = mp_const_none;
- o->rxcallback1 = mp_const_none;
- MP_STATE_PORT(pyb_can_obj_all)[o->can_id - 1] = o;
- o->rx_state0 = RX_STATE_FIFO_EMPTY;
- o->rx_state1 = RX_STATE_FIFO_EMPTY;
- if (n_args > 1 || n_kw > 0) {
- // start the peripheral
- mp_map_t kw_args;
- mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
- pyb_can_init_helper(o, n_args - 1, args + 1, &kw_args);
+ if (!self->is_enabled || n_args > 1) {
+ if (self->is_enabled) {
+ // The caller is requesting a reconfiguration of the hardware
+ // this can only be done if the hardware is in init mode
+ pyb_can_deinit(self);
+ }
+
+ self->rxcallback0 = mp_const_none;
+ self->rxcallback1 = mp_const_none;
+ self->rx_state0 = RX_STATE_FIFO_EMPTY;
+ self->rx_state1 = RX_STATE_FIFO_EMPTY;
+
+ if (n_args > 1 || n_kw > 0) {
+ // start the peripheral
+ mp_map_t kw_args;
+ mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
+ pyb_can_init_helper(self, n_args - 1, args + 1, &kw_args);
+ }
}
- return o;
+ return self;
}
STATIC mp_obj_t pyb_can_init(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
@@ -800,7 +817,7 @@ mp_uint_t can_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_t arg, int *err
ret |= MP_IOCTL_POLL_WR;
}
} else {
- *errcode = EINVAL;
+ *errcode = MP_EINVAL;
ret = -1;
}
return ret;
diff --git a/stmhal/dac.c b/stmhal/dac.c
index 6d7491c314..7493bb59ab 100644
--- a/stmhal/dac.c
+++ b/stmhal/dac.c
@@ -67,7 +67,7 @@
/// dac = DAC(1)
/// dac.write_timed(buf, 400 * len(buf), mode=DAC.CIRCULAR)
-#if MICROPY_HW_ENABLE_DAC
+#if defined(MICROPY_HW_ENABLE_DAC) && MICROPY_HW_ENABLE_DAC
STATIC DAC_HandleTypeDef DAC_Handle;
@@ -139,7 +139,7 @@ typedef enum {
typedef struct _pyb_dac_obj_t {
mp_obj_base_t base;
uint32_t dac_channel; // DAC_CHANNEL_1 or DAC_CHANNEL_2
- DMA_Stream_TypeDef *dma_stream; // DMA1_Stream5 or DMA1_Stream6
+ const dma_descr_t *tx_dma_descr;
uint16_t pin; // GPIO_PIN_4 or GPIO_PIN_5
uint8_t bits; // 8 or 12
uint8_t state;
@@ -162,7 +162,13 @@ STATIC mp_obj_t pyb_dac_init_helper(pyb_dac_obj_t *self, mp_uint_t n_args, const
HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
// DAC peripheral clock
+ #if defined(MCU_SERIES_F4) || defined(MCU_SERIES_F7)
__DAC_CLK_ENABLE();
+ #elif defined(MCU_SERIES_L4)
+ __HAL_RCC_DAC1_CLK_ENABLE();
+ #else
+ #error Unsupported Processor
+ #endif
// stop anything already going on
HAL_DAC_Stop(&DAC_Handle, self->dac_channel);
@@ -217,11 +223,11 @@ STATIC mp_obj_t pyb_dac_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp
if (dac_id == 1) {
dac->pin = GPIO_PIN_4;
dac->dac_channel = DAC_CHANNEL_1;
- dac->dma_stream = DMA_STREAM_DAC1;
+ dac->tx_dma_descr = &dma_DAC_1_TX;
} else if (dac_id == 2) {
dac->pin = GPIO_PIN_5;
dac->dac_channel = DAC_CHANNEL_2;
- dac->dma_stream = DMA_STREAM_DAC2;
+ dac->tx_dma_descr = &dma_DAC_2_TX;
} else {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "DAC %d does not exist", dac_id));
}
@@ -240,6 +246,21 @@ STATIC mp_obj_t pyb_dac_init(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *k
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_dac_init_obj, 1, pyb_dac_init);
+/// \method deinit()
+/// Turn off the DAC, enable other use of pin.
+STATIC mp_obj_t pyb_dac_deinit(mp_obj_t self_in) {
+ pyb_dac_obj_t *self = self_in;
+ if (self->dac_channel == DAC_CHANNEL_1) {
+ DAC_Handle.Instance->CR &= ~DAC_CR_EN1;
+ DAC_Handle.Instance->CR |= DAC_CR_BOFF1;
+ } else {
+ DAC_Handle.Instance->CR &= ~DAC_CR_EN2;
+ DAC_Handle.Instance->CR |= DAC_CR_BOFF2;
+ }
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_dac_deinit_obj, pyb_dac_deinit);
+
#if defined(TIM6)
/// \method noise(freq)
/// Generate a pseudo-random noise signal. A new random sample is written
@@ -371,9 +392,12 @@ mp_obj_t pyb_dac_write_timed(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_
__DMA1_CLK_ENABLE();
+ DMA_HandleTypeDef DMA_Handle;
+ /* Get currently configured dma */
+ dma_init_handle(&DMA_Handle, self->tx_dma_descr, (void*)NULL);
/*
- DMA_Cmd(self->dma_stream, DISABLE);
- while (DMA_GetCmdStatus(self->dma_stream) != DISABLE) {
+ DMA_Cmd(DMA_Handle->Instance, DISABLE);
+ while (DMA_GetCmdStatus(DMA_Handle->Instance) != DISABLE) {
}
DAC_Cmd(self->dac_channel, DISABLE);
@@ -389,18 +413,10 @@ mp_obj_t pyb_dac_write_timed(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_
DAC_Init(self->dac_channel, &DAC_InitStructure);
*/
- // DMA1_Stream[67] channel7 configuration
- DMA_HandleTypeDef DMA_Handle;
- DMA_Handle.Instance = self->dma_stream;
-
// Need to deinit DMA first
DMA_Handle.State = HAL_DMA_STATE_READY;
HAL_DMA_DeInit(&DMA_Handle);
- DMA_Handle.Init.Channel = DMA_CHANNEL_DAC1; // DAC1 & DAC2 both use the same channel
- DMA_Handle.Init.Direction = DMA_MEMORY_TO_PERIPH;
- DMA_Handle.Init.PeriphInc = DMA_PINC_DISABLE;
- DMA_Handle.Init.MemInc = DMA_MINC_ENABLE;
if (self->bits == 8) {
DMA_Handle.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
DMA_Handle.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
@@ -409,11 +425,6 @@ mp_obj_t pyb_dac_write_timed(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_
DMA_Handle.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
}
DMA_Handle.Init.Mode = args[2].u_int;
- DMA_Handle.Init.Priority = DMA_PRIORITY_HIGH;
- DMA_Handle.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
- DMA_Handle.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_HALFFULL;
- DMA_Handle.Init.MemBurst = DMA_MBURST_SINGLE;
- DMA_Handle.Init.PeriphBurst = DMA_PBURST_SINGLE;
HAL_DMA_Init(&DMA_Handle);
if (self->dac_channel == DAC_CHANNEL_1) {
@@ -444,8 +455,8 @@ mp_obj_t pyb_dac_write_timed(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_
/*
// enable DMA stream
- DMA_Cmd(self->dma_stream, ENABLE);
- while (DMA_GetCmdStatus(self->dma_stream) == DISABLE) {
+ DMA_Cmd(DMA_Handle->Instance, ENABLE);
+ while (DMA_GetCmdStatus(DMA_Handle->Instance) == DISABLE) {
}
// enable DAC channel
@@ -465,6 +476,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_dac_write_timed_obj, 1, pyb_dac_write_time
STATIC const mp_map_elem_t pyb_dac_locals_dict_table[] = {
// instance methods
{ MP_OBJ_NEW_QSTR(MP_QSTR_init), (mp_obj_t)&pyb_dac_init_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_deinit), (mp_obj_t)&pyb_dac_deinit_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_write), (mp_obj_t)&pyb_dac_write_obj },
#if defined(TIM6)
{ MP_OBJ_NEW_QSTR(MP_QSTR_noise), (mp_obj_t)&pyb_dac_noise_obj },
diff --git a/stmhal/dma.c b/stmhal/dma.c
index 2255e51601..9f3e87fb9e 100644
--- a/stmhal/dma.c
+++ b/stmhal/dma.c
@@ -33,11 +33,176 @@
#include "py/obj.h"
#include "irq.h"
-#define NSTREAMS_PER_CONTROLLER_LOG2 (3)
-#define NSTREAMS_PER_CONTROLLER (1 << NSTREAMS_PER_CONTROLLER_LOG2)
+typedef enum {
+ dma_id_not_defined=-1,
+ dma_id_0,
+ dma_id_1,
+ dma_id_2,
+ dma_id_3,
+ dma_id_4,
+ dma_id_5,
+ dma_id_6,
+ dma_id_7,
+ dma_id_8,
+ dma_id_9,
+ dma_id_10,
+ dma_id_11,
+ dma_id_12,
+ dma_id_13,
+ dma_id_14,
+ dma_id_15,
+} dma_id_t;
+
+typedef struct _dma_descr_t {
+ #if defined(MCU_SERIES_F4) || defined(MCU_SERIES_F7)
+ DMA_Stream_TypeDef *instance;
+ #elif defined(MCU_SERIES_L4)
+ DMA_Channel_TypeDef *instance;
+ #else
+ #error "Unsupported Processor"
+ #endif
+ uint32_t sub_instance;
+ uint32_t transfer_direction; // periph to memory or vice-versa
+ dma_id_t id;
+ const DMA_InitTypeDef *init;
+} dma_descr_t;
+
+// Default parameters to dma_init() shared by spi and i2c; Channel and Direction
+// vary depending on the peripheral instance so they get passed separately
+static const DMA_InitTypeDef dma_init_struct_spi_i2c = {
+ #if defined(MCU_SERIES_F4) || defined(MCU_SERIES_F7)
+ .Channel = 0,
+ #elif defined(MCU_SERIES_L4)
+ .Request = 0,
+ #endif
+ .Direction = 0,
+ .PeriphInc = DMA_PINC_DISABLE,
+ .MemInc = DMA_MINC_ENABLE,
+ .PeriphDataAlignment = DMA_PDATAALIGN_BYTE,
+ .MemDataAlignment = DMA_MDATAALIGN_BYTE,
+ .Mode = DMA_NORMAL,
+ .Priority = DMA_PRIORITY_LOW,
+ #if defined(MCU_SERIES_F4) || defined(MCU_SERIES_F7)
+ .FIFOMode = DMA_FIFOMODE_DISABLE,
+ .FIFOThreshold = DMA_FIFO_THRESHOLD_FULL,
+ .MemBurst = DMA_MBURST_INC4,
+ .PeriphBurst = DMA_PBURST_INC4
+ #endif
+};
+
+#if defined(MICROPY_HW_HAS_SDCARD) && MICROPY_HW_HAS_SDCARD
+// Parameters to dma_init() for SDIO tx and rx.
+static const DMA_InitTypeDef dma_init_struct_sdio = {
+ #if defined(MCU_SERIES_F4) || defined(MCU_SERIES_F7)
+ .Channel = 0,
+ #elif defined(MCU_SERIES_L4)
+ .Request = 0,
+ #endif
+ .Direction = 0,
+ .PeriphInc = DMA_PINC_DISABLE,
+ .MemInc = DMA_MINC_ENABLE,
+ .PeriphDataAlignment = DMA_PDATAALIGN_WORD,
+ .MemDataAlignment = DMA_MDATAALIGN_WORD,
+ #if defined(MCU_SERIES_F4) || defined(MCU_SERIES_F7)
+ .Mode = DMA_PFCTRL,
+ #elif defined(MCU_SERIES_L4)
+ .Mode = DMA_NORMAL,
+ #endif
+ .Priority = DMA_PRIORITY_VERY_HIGH,
+ #if defined(MCU_SERIES_F4) || defined(MCU_SERIES_F7)
+ .FIFOMode = DMA_FIFOMODE_ENABLE,
+ .FIFOThreshold = DMA_FIFO_THRESHOLD_FULL,
+ .MemBurst = DMA_MBURST_INC4,
+ .PeriphBurst = DMA_PBURST_INC4,
+ #endif
+};
+#endif
+
+#if defined(MICROPY_HW_ENABLE_DAC) && MICROPY_HW_ENABLE_DAC
+// Default parameters to dma_init() for DAC tx
+static const DMA_InitTypeDef dma_init_struct_dac = {
+ #if defined(MCU_SERIES_F4) || defined(MCU_SERIES_F7)
+ .Channel = 0,
+ #elif defined(MCU_SERIES_L4)
+ .Request = 0,
+ #endif
+ .Direction = 0,
+ .PeriphInc = DMA_PINC_DISABLE,
+ .MemInc = DMA_MINC_ENABLE,
+ .PeriphDataAlignment = DMA_PDATAALIGN_BYTE,
+ .MemDataAlignment = DMA_MDATAALIGN_BYTE,
+ .Mode = DMA_NORMAL,
+ .Priority = DMA_PRIORITY_HIGH,
+ #if defined(MCU_SERIES_F4) || defined(MCU_SERIES_F7)
+ .FIFOMode = DMA_FIFOMODE_DISABLE,
+ .FIFOThreshold = DMA_FIFO_THRESHOLD_HALFFULL,
+ .MemBurst = DMA_MBURST_SINGLE,
+ .PeriphBurst = DMA_PBURST_SINGLE,
+ #endif
+};
+#endif
+
+#if defined(MCU_SERIES_F4) || defined(MCU_SERIES_F7)
+
#define NCONTROLLERS (2)
+#define NSTREAMS_PER_CONTROLLER (8)
#define NSTREAM (NCONTROLLERS * NSTREAMS_PER_CONTROLLER)
+#define DMA_SUB_INSTANCE_AS_UINT8(dma_channel) (((dma_channel) & DMA_SxCR_CHSEL) >> 25)
+
+#define DMA1_ENABLE_MASK (0x00ff) // Bits in dma_enable_mask corresponding to DMA1
+#define DMA2_ENABLE_MASK (0xff00) // Bits in dma_enable_mask corresponding to DMA2
+
+// These descriptors are ordered by DMAx_Stream number, and within a stream by channel
+// number. The duplicate streams are ok as long as they aren't used at the same time.
+//
+// Currently I2C and SPI are synchronous and they call dma_init/dma_deinit
+// around each transfer.
+
+// DMA1 streams
+const dma_descr_t dma_I2C_1_RX = { DMA1_Stream0, DMA_CHANNEL_1, DMA_PERIPH_TO_MEMORY, dma_id_0, &dma_init_struct_spi_i2c };
+const dma_descr_t dma_SPI_3_RX = { DMA1_Stream2, DMA_CHANNEL_0, DMA_PERIPH_TO_MEMORY, dma_id_2, &dma_init_struct_spi_i2c };
+const dma_descr_t dma_I2C_3_RX = { DMA1_Stream2, DMA_CHANNEL_3, DMA_PERIPH_TO_MEMORY, dma_id_2, &dma_init_struct_spi_i2c };
+const dma_descr_t dma_I2C_2_RX = { DMA1_Stream2, DMA_CHANNEL_7, DMA_PERIPH_TO_MEMORY, dma_id_2, &dma_init_struct_spi_i2c };
+const dma_descr_t dma_SPI_2_RX = { DMA1_Stream3, DMA_CHANNEL_0, DMA_PERIPH_TO_MEMORY, dma_id_3, &dma_init_struct_spi_i2c };
+const dma_descr_t dma_SPI_2_TX = { DMA1_Stream4, DMA_CHANNEL_0, DMA_MEMORY_TO_PERIPH, dma_id_4, &dma_init_struct_spi_i2c };
+const dma_descr_t dma_I2C_3_TX = { DMA1_Stream4, DMA_CHANNEL_3, DMA_MEMORY_TO_PERIPH, dma_id_4, &dma_init_struct_spi_i2c };
+#if defined(MICROPY_HW_ENABLE_DAC) && MICROPY_HW_ENABLE_DAC
+const dma_descr_t dma_DAC_1_TX = { DMA1_Stream5, DMA_CHANNEL_7, DMA_MEMORY_TO_PERIPH, dma_id_5, &dma_init_struct_dac };
+const dma_descr_t dma_DAC_2_TX = { DMA1_Stream6, DMA_CHANNEL_7, DMA_MEMORY_TO_PERIPH, dma_id_6, &dma_init_struct_dac };
+#endif
+const dma_descr_t dma_SPI_3_TX = { DMA1_Stream7, DMA_CHANNEL_0, DMA_MEMORY_TO_PERIPH, dma_id_7, &dma_init_struct_spi_i2c };
+const dma_descr_t dma_I2C_1_TX = { DMA1_Stream7, DMA_CHANNEL_1, DMA_MEMORY_TO_PERIPH, dma_id_7, &dma_init_struct_spi_i2c };
+const dma_descr_t dma_I2C_2_TX = { DMA1_Stream7, DMA_CHANNEL_7, DMA_MEMORY_TO_PERIPH, dma_id_7, &dma_init_struct_spi_i2c };
+/* not preferred streams
+const dma_descr_t dma_SPI_3_RX = { DMA1_Stream0, DMA_CHANNEL_0, DMA_PERIPH_TO_MEMORY, dma_id_0, &dma_init_struct_spi_i2c };
+const dma_descr_t dma_I2C_1_TX = { DMA1_Stream6, DMA_CHANNEL_1, DMA_MEMORY_TO_PERIPH, dma_id_6, &dma_init_struct_spi_i2c };
+*/
+
+// DMA2 streams
+const dma_descr_t dma_SPI_1_RX = { DMA2_Stream2, DMA_CHANNEL_3, DMA_PERIPH_TO_MEMORY, dma_id_10, &dma_init_struct_spi_i2c };
+const dma_descr_t dma_SPI_5_RX = { DMA2_Stream3, DMA_CHANNEL_2, DMA_PERIPH_TO_MEMORY, dma_id_11, &dma_init_struct_spi_i2c };
+#if defined(MICROPY_HW_HAS_SDCARD) && MICROPY_HW_HAS_SDCARD
+const dma_descr_t dma_SDIO_0_RX= { DMA2_Stream3, DMA_CHANNEL_4, DMA_PERIPH_TO_MEMORY, dma_id_11, &dma_init_struct_sdio };
+#endif
+const dma_descr_t dma_SPI_4_RX = { DMA2_Stream3, DMA_CHANNEL_5, DMA_PERIPH_TO_MEMORY, dma_id_11, &dma_init_struct_spi_i2c };
+const dma_descr_t dma_SPI_5_TX = { DMA2_Stream4, DMA_CHANNEL_2, DMA_MEMORY_TO_PERIPH, dma_id_12, &dma_init_struct_spi_i2c };
+const dma_descr_t dma_SPI_4_TX = { DMA2_Stream4, DMA_CHANNEL_5, DMA_MEMORY_TO_PERIPH, dma_id_12, &dma_init_struct_spi_i2c };
+const dma_descr_t dma_SPI_6_TX = { DMA2_Stream5, DMA_CHANNEL_1, DMA_MEMORY_TO_PERIPH, dma_id_13, &dma_init_struct_spi_i2c };
+const dma_descr_t dma_SPI_1_TX = { DMA2_Stream5, DMA_CHANNEL_3, DMA_MEMORY_TO_PERIPH, dma_id_13, &dma_init_struct_spi_i2c };
+const dma_descr_t dma_SPI_6_RX = { DMA2_Stream6, DMA_CHANNEL_1, DMA_PERIPH_TO_MEMORY, dma_id_14, &dma_init_struct_spi_i2c };
+#if defined(MICROPY_HW_HAS_SDCARD) && MICROPY_HW_HAS_SDCARD
+const dma_descr_t dma_SDIO_0_TX= { DMA2_Stream6, DMA_CHANNEL_4, DMA_MEMORY_TO_PERIPH, dma_id_14, &dma_init_struct_sdio };
+#endif
+/* not preferred streams
+const dma_descr_t dma_SPI_1_TX = { DMA2_Stream3, DMA_CHANNEL_3, DMA_MEMORY_TO_PERIPH, dma_id_11, &dma_init_struct_spi_i2c };
+const dma_descr_t dma_SPI_1_RX = { DMA2_Stream0, DMA_CHANNEL_3, DMA_PERIPH_TO_MEMORY, dma_id_8, &dma_init_struct_spi_i2c };
+const dma_descr_t dma_SPI_4_RX = { DMA2_Stream0, DMA_CHANNEL_4, DMA_PERIPH_TO_MEMORY, dma_id_8, &dma_init_struct_spi_i2c };
+const dma_descr_t dma_SPI_4_TX = { DMA2_Stream1, DMA_CHANNEL_4, DMA_MEMORY_TO_PERIPH, dma_id_9, &dma_init_struct_spi_i2c };
+const dma_descr_t dma_SPI_5_RX = { DMA2_Stream5, DMA_CHANNEL_7, DMA_PERIPH_TO_MEMORY, dma_id_13, &dma_init_struct_spi_i2c };
+const dma_descr_t dma_SPI_5_TX = { DMA2_Stream6, DMA_CHANNEL_7, DMA_MEMORY_TO_PERIPH, dma_id_14, &dma_init_struct_spi_i2c };
+*/
+
static const uint8_t dma_irqn[NSTREAM] = {
DMA1_Stream0_IRQn,
DMA1_Stream1_IRQn,
@@ -57,71 +222,135 @@ static const uint8_t dma_irqn[NSTREAM] = {
DMA2_Stream7_IRQn,
};
-// Default parameters to dma_init() shared by spi and i2c; Channel and Direction
-// vary depending on the peripheral instance so they get passed separately
-const DMA_InitTypeDef dma_init_struct_spi_i2c = {
- .Channel = 0,
- .Direction = 0,
- .PeriphInc = DMA_PINC_DISABLE,
- .MemInc = DMA_MINC_ENABLE,
- .PeriphDataAlignment = DMA_PDATAALIGN_BYTE,
- .MemDataAlignment = DMA_MDATAALIGN_BYTE,
- .Mode = DMA_NORMAL,
- .Priority = DMA_PRIORITY_LOW,
- .FIFOMode = DMA_FIFOMODE_DISABLE,
- .FIFOThreshold = DMA_FIFO_THRESHOLD_FULL,
- .MemBurst = DMA_MBURST_INC4,
- .PeriphBurst = DMA_PBURST_INC4
+#elif defined(MCU_SERIES_L4)
+
+#define NCONTROLLERS (2)
+#define NSTREAMS_PER_CONTROLLER (7)
+#define NSTREAM (NCONTROLLERS * NSTREAMS_PER_CONTROLLER)
+
+#define DMA_SUB_INSTANCE_AS_UINT8(dma_request) (dma_request)
+
+#define DMA1_ENABLE_MASK (0x007f) // Bits in dma_enable_mask corresponfing to DMA1
+#define DMA2_ENABLE_MASK (0x3f80) // Bits in dma_enable_mask corresponding to DMA2
+
+// These descriptors are ordered by DMAx_Channel number, and within a channel by request
+// number. The duplicate streams are ok as long as they aren't used at the same time.
+
+// DMA1 streams
+//const dma_descr_t dma_ADC_1_RX = { DMA1_Channel1, DMA_REQUEST_0, DMA_PERIPH_TO_MEMORY, dma_id_0, NULL }; // unused
+//const dma_descr_t dma_ADC_2_RX = { DMA1_Channel2, DMA_REQUEST_0, DMA_PERIPH_TO_MEMORY, dma_id_1, NULL }; // unused
+const dma_descr_t dma_SPI_1_RX = { DMA1_Channel2, DMA_REQUEST_1, DMA_PERIPH_TO_MEMORY, dma_id_1, &dma_init_struct_spi_i2c };
+const dma_descr_t dma_I2C_3_TX = { DMA1_Channel2, DMA_REQUEST_3, DMA_MEMORY_TO_PERIPH, dma_id_1, &dma_init_struct_spi_i2c };
+//const dma_descr_t dma_ADC_3_RX = { DMA1_Channel3, DMA_REQUEST_0, DMA_PERIPH_TO_MEMORY, dma_id_2, NULL }; // unused
+const dma_descr_t dma_SPI_1_TX = { DMA1_Channel3, DMA_REQUEST_1, DMA_MEMORY_TO_PERIPH, dma_id_2, &dma_init_struct_spi_i2c };
+const dma_descr_t dma_I2C_3_RX = { DMA1_Channel3, DMA_REQUEST_3, DMA_PERIPH_TO_MEMORY, dma_id_2, &dma_init_struct_spi_i2c };
+#if MICROPY_HW_ENABLE_DAC
+const dma_descr_t dma_DAC_1_TX = { DMA1_Channel3, DMA_REQUEST_6, DMA_MEMORY_TO_PERIPH, dma_id_2, &dma_init_struct_dac };
+#endif
+const dma_descr_t dma_SPI_2_RX = { DMA1_Channel4, DMA_REQUEST_1, DMA_PERIPH_TO_MEMORY, dma_id_3, &dma_init_struct_spi_i2c };
+const dma_descr_t dma_I2C_2_TX = { DMA1_Channel4, DMA_REQUEST_3, DMA_MEMORY_TO_PERIPH, dma_id_3, &dma_init_struct_spi_i2c };
+#if MICROPY_HW_ENABLE_DAC
+const dma_descr_t dma_DAC_2_TX = { DMA1_Channel4, DMA_REQUEST_5, DMA_MEMORY_TO_PERIPH, dma_id_3, &dma_init_struct_dac };
+#endif
+const dma_descr_t dma_SPI_2_TX = { DMA1_Channel5, DMA_REQUEST_1, DMA_MEMORY_TO_PERIPH, dma_id_4, &dma_init_struct_spi_i2c };
+const dma_descr_t dma_I2C_2_RX = { DMA1_Channel5, DMA_REQUEST_3, DMA_PERIPH_TO_MEMORY, dma_id_4, &dma_init_struct_spi_i2c };
+const dma_descr_t dma_I2C_1_TX = { DMA1_Channel6, DMA_REQUEST_3, DMA_MEMORY_TO_PERIPH, dma_id_5, &dma_init_struct_spi_i2c };
+const dma_descr_t dma_I2C_1_RX = { DMA1_Channel7, DMA_REQUEST_3, DMA_PERIPH_TO_MEMORY, dma_id_6, &dma_init_struct_spi_i2c };
+
+// DMA2 streams
+const dma_descr_t dma_SPI_3_RX = { DMA2_Channel1, DMA_REQUEST_3, DMA_PERIPH_TO_MEMORY, dma_id_7, &dma_init_struct_spi_i2c };
+const dma_descr_t dma_SPI_3_TX = { DMA2_Channel2, DMA_REQUEST_3, DMA_MEMORY_TO_PERIPH, dma_id_8, &dma_init_struct_spi_i2c };
+/* not preferred streams
+const dma_descr_t dma_ADC_1_RX = { DMA2_Channel3, DMA_REQUEST_0, DMA_PERIPH_TO_MEMORY, dma_id_9, NULL };
+const dma_descr_t dma_SPI_1_RX = { DMA2_Channel3, DMA_REQUEST_4, DMA_PERIPH_TO_MEMORY, dma_id_9, &dma_init_struct_spi_i2c };
+const dma_descr_t dma_ADC_2_RX = { DMA2_Channel4, DMA_REQUEST_0, DMA_PERIPH_TO_MEMORY, dma_id_10, NULL };
+const dma_descr_t dma_DAC_1_TX = { DMA2_Channel4, DMA_REQUEST_3, DMA_MEMORY_TO_PERIPH, dma_id_10, &dma_init_struct_dac };
+const dma_descr_t dma_SPI_1_TX = { DMA2_Channel4, DMA_REQUEST_4, DMA_MEMORY_TO_PERIPH, dma_id_10, &dma_init_struct_spi_i2c };
+*/
+#if MICROPY_HW_HAS_SDCARD
+const dma_descr_t dma_SDIO_0_TX= { DMA2_Channel4, DMA_REQUEST_7, DMA_MEMORY_TO_PERIPH, dma_id_10, &dma_init_struct_sdio };
+#endif
+/* not preferred streams
+const dma_descr_t dma_ADC_3_RX = { DMA2_Channel5, DMA_REQUEST_0, DMA_PERIPH_TO_MEMORY, dma_id_11, NULL };
+const dma_descr_t dma_DAC_2_TX = { DMA2_Channel5, DMA_REQUEST_3, DMA_MEMORY_TO_PERIPH, dma_id_11, &dma_init_struct_dac };
+const dma_descr_t dma_SDIO_0_TX= { DMA2_Channel5, DMA_REQUEST_7, DMA_MEMORY_TO_PERIPH, dma_id_11, &dma_init_struct_sdio };
+const dma_descr_t dma_I2C_1_RX = { DMA2_Channel6, DMA_REQUEST_5, DMA_PERIPH_TO_MEMORY, dma_id_12, &dma_init_struct_spi_i2c };
+const dma_descr_t dma_I2C_1_TX = { DMA2_Channel7, DMA_REQUEST_5, DMA_MEMORY_TO_PERIPH, dma_id_13, &dma_init_struct_spi_i2c };
+*/
+
+static const uint8_t dma_irqn[NSTREAM] = {
+ DMA1_Channel1_IRQn,
+ DMA1_Channel2_IRQn,
+ DMA1_Channel3_IRQn,
+ DMA1_Channel4_IRQn,
+ DMA1_Channel5_IRQn,
+ DMA1_Channel6_IRQn,
+ DMA1_Channel7_IRQn,
+ DMA2_Channel1_IRQn,
+ DMA2_Channel2_IRQn,
+ DMA2_Channel3_IRQn,
+ DMA2_Channel4_IRQn,
+ DMA2_Channel5_IRQn,
+ DMA2_Channel6_IRQn,
+ DMA2_Channel7_IRQn,
};
+#endif
+
static DMA_HandleTypeDef *dma_handle[NSTREAM] = {NULL};
-static uint8_t dma_last_channel[NSTREAM];
+static uint8_t dma_last_sub_instance[NSTREAM];
static volatile uint32_t dma_enable_mask = 0;
-
volatile dma_idle_count_t dma_idle;
-#define DMA1_ENABLE_MASK 0x00ff // Bits in dma_enable_mask corresponfing to DMA1
-#define DMA2_ENABLE_MASK 0xff00 // Bits in dma_enable_mask corresponding to DMA2
#define DMA_INVALID_CHANNEL 0xff // Value stored in dma_last_channel which means invalid
-#define DMA_CHANNEL_AS_UINT8(dma_channel) (((dma_channel) & DMA_SxCR_CHSEL) >> 24)
-
-void DMA1_Stream0_IRQHandler(void) { IRQ_ENTER(DMA1_Stream0_IRQn); if (dma_handle[0] != NULL) { HAL_DMA_IRQHandler(dma_handle[0]); } IRQ_EXIT(DMA1_Stream0_IRQn); }
-void DMA1_Stream1_IRQHandler(void) { IRQ_ENTER(DMA1_Stream1_IRQn); if (dma_handle[1] != NULL) { HAL_DMA_IRQHandler(dma_handle[1]); } IRQ_EXIT(DMA1_Stream1_IRQn); }
-void DMA1_Stream2_IRQHandler(void) { IRQ_ENTER(DMA1_Stream2_IRQn); if (dma_handle[2] != NULL) { HAL_DMA_IRQHandler(dma_handle[2]); } IRQ_EXIT(DMA1_Stream2_IRQn); }
-void DMA1_Stream3_IRQHandler(void) { IRQ_ENTER(DMA1_Stream3_IRQn); if (dma_handle[3] != NULL) { HAL_DMA_IRQHandler(dma_handle[3]); } IRQ_EXIT(DMA1_Stream3_IRQn); }
-void DMA1_Stream4_IRQHandler(void) { IRQ_ENTER(DMA1_Stream4_IRQn); if (dma_handle[4] != NULL) { HAL_DMA_IRQHandler(dma_handle[4]); } IRQ_EXIT(DMA1_Stream4_IRQn); }
-void DMA1_Stream5_IRQHandler(void) { IRQ_ENTER(DMA1_Stream5_IRQn); if (dma_handle[5] != NULL) { HAL_DMA_IRQHandler(dma_handle[5]); } IRQ_EXIT(DMA1_Stream5_IRQn); }
-void DMA1_Stream6_IRQHandler(void) { IRQ_ENTER(DMA1_Stream6_IRQn); if (dma_handle[6] != NULL) { HAL_DMA_IRQHandler(dma_handle[6]); } IRQ_EXIT(DMA1_Stream6_IRQn); }
-void DMA1_Stream7_IRQHandler(void) { IRQ_ENTER(DMA1_Stream7_IRQn); if (dma_handle[7] != NULL) { HAL_DMA_IRQHandler(dma_handle[7]); } IRQ_EXIT(DMA1_Stream7_IRQn); }
-void DMA2_Stream0_IRQHandler(void) { IRQ_ENTER(DMA2_Stream0_IRQn); if (dma_handle[8] != NULL) { HAL_DMA_IRQHandler(dma_handle[8]); } IRQ_EXIT(DMA2_Stream0_IRQn); }
-void DMA2_Stream1_IRQHandler(void) { IRQ_ENTER(DMA2_Stream1_IRQn); if (dma_handle[9] != NULL) { HAL_DMA_IRQHandler(dma_handle[9]); } IRQ_EXIT(DMA2_Stream1_IRQn); }
-void DMA2_Stream2_IRQHandler(void) { IRQ_ENTER(DMA2_Stream2_IRQn); if (dma_handle[10] != NULL) { HAL_DMA_IRQHandler(dma_handle[10]); } IRQ_EXIT(DMA2_Stream2_IRQn); }
-void DMA2_Stream3_IRQHandler(void) { IRQ_ENTER(DMA2_Stream3_IRQn); if (dma_handle[11] != NULL) { HAL_DMA_IRQHandler(dma_handle[11]); } IRQ_EXIT(DMA2_Stream3_IRQn); }
-void DMA2_Stream4_IRQHandler(void) { IRQ_ENTER(DMA2_Stream4_IRQn); if (dma_handle[12] != NULL) { HAL_DMA_IRQHandler(dma_handle[12]); } IRQ_EXIT(DMA2_Stream4_IRQn); }
-void DMA2_Stream5_IRQHandler(void) { IRQ_ENTER(DMA2_Stream5_IRQn); if (dma_handle[13] != NULL) { HAL_DMA_IRQHandler(dma_handle[13]); } IRQ_EXIT(DMA2_Stream5_IRQn); }
-void DMA2_Stream6_IRQHandler(void) { IRQ_ENTER(DMA2_Stream6_IRQn); if (dma_handle[14] != NULL) { HAL_DMA_IRQHandler(dma_handle[14]); } IRQ_EXIT(DMA2_Stream6_IRQn); }
-void DMA2_Stream7_IRQHandler(void) { IRQ_ENTER(DMA2_Stream7_IRQn); if (dma_handle[15] != NULL) { HAL_DMA_IRQHandler(dma_handle[15]); } IRQ_EXIT(DMA2_Stream7_IRQn); }
-
#define DMA1_IS_CLK_ENABLED() ((RCC->AHB1ENR & RCC_AHB1ENR_DMA1EN) != 0)
#define DMA2_IS_CLK_ENABLED() ((RCC->AHB1ENR & RCC_AHB1ENR_DMA2EN) != 0)
-static int get_dma_id(DMA_Stream_TypeDef *dma_stream) {
- int dma_id;
- if (dma_stream < DMA2_Stream0) {
- dma_id = dma_stream - DMA1_Stream0;
- } else {
- dma_id = NSTREAMS_PER_CONTROLLER + (dma_stream - DMA2_Stream0);
- }
- return dma_id;
-}
+#if defined(MCU_SERIES_F4) || defined(MCU_SERIES_F7)
+
+void DMA1_Stream0_IRQHandler(void) { IRQ_ENTER(DMA1_Stream0_IRQn); if (dma_handle[dma_id_0] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_0]); } IRQ_EXIT(DMA1_Stream0_IRQn); }
+void DMA1_Stream1_IRQHandler(void) { IRQ_ENTER(DMA1_Stream1_IRQn); if (dma_handle[dma_id_1] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_1]); } IRQ_EXIT(DMA1_Stream1_IRQn); }
+void DMA1_Stream2_IRQHandler(void) { IRQ_ENTER(DMA1_Stream2_IRQn); if (dma_handle[dma_id_2] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_2]); } IRQ_EXIT(DMA1_Stream2_IRQn); }
+void DMA1_Stream3_IRQHandler(void) { IRQ_ENTER(DMA1_Stream3_IRQn); if (dma_handle[dma_id_3] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_3]); } IRQ_EXIT(DMA1_Stream3_IRQn); }
+void DMA1_Stream4_IRQHandler(void) { IRQ_ENTER(DMA1_Stream4_IRQn); if (dma_handle[dma_id_4] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_4]); } IRQ_EXIT(DMA1_Stream4_IRQn); }
+void DMA1_Stream5_IRQHandler(void) { IRQ_ENTER(DMA1_Stream5_IRQn); if (dma_handle[dma_id_5] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_5]); } IRQ_EXIT(DMA1_Stream5_IRQn); }
+void DMA1_Stream6_IRQHandler(void) { IRQ_ENTER(DMA1_Stream6_IRQn); if (dma_handle[dma_id_6] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_6]); } IRQ_EXIT(DMA1_Stream6_IRQn); }
+void DMA1_Stream7_IRQHandler(void) { IRQ_ENTER(DMA1_Stream7_IRQn); if (dma_handle[dma_id_7] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_7]); } IRQ_EXIT(DMA1_Stream7_IRQn); }
+void DMA2_Stream0_IRQHandler(void) { IRQ_ENTER(DMA2_Stream0_IRQn); if (dma_handle[dma_id_8] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_8]); } IRQ_EXIT(DMA2_Stream0_IRQn); }
+void DMA2_Stream1_IRQHandler(void) { IRQ_ENTER(DMA2_Stream1_IRQn); if (dma_handle[dma_id_9] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_9]); } IRQ_EXIT(DMA2_Stream1_IRQn); }
+void DMA2_Stream2_IRQHandler(void) { IRQ_ENTER(DMA2_Stream2_IRQn); if (dma_handle[dma_id_10] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_10]); } IRQ_EXIT(DMA2_Stream2_IRQn); }
+void DMA2_Stream3_IRQHandler(void) { IRQ_ENTER(DMA2_Stream3_IRQn); if (dma_handle[dma_id_11] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_11]); } IRQ_EXIT(DMA2_Stream3_IRQn); }
+void DMA2_Stream4_IRQHandler(void) { IRQ_ENTER(DMA2_Stream4_IRQn); if (dma_handle[dma_id_12] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_12]); } IRQ_EXIT(DMA2_Stream4_IRQn); }
+void DMA2_Stream5_IRQHandler(void) { IRQ_ENTER(DMA2_Stream5_IRQn); if (dma_handle[dma_id_13] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_13]); } IRQ_EXIT(DMA2_Stream5_IRQn); }
+void DMA2_Stream6_IRQHandler(void) { IRQ_ENTER(DMA2_Stream6_IRQn); if (dma_handle[dma_id_14] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_14]); } IRQ_EXIT(DMA2_Stream6_IRQn); }
+void DMA2_Stream7_IRQHandler(void) { IRQ_ENTER(DMA2_Stream7_IRQn); if (dma_handle[dma_id_15] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_15]); } IRQ_EXIT(DMA2_Stream7_IRQn); }
+
+#elif defined(MCU_SERIES_L4)
+
+void DMA1_Channel1_IRQHandler(void) { IRQ_ENTER(DMA1_Channel1_IRQn); if (dma_handle[dma_id_0] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_0]); } IRQ_EXIT(DMA1_Channel1_IRQn); }
+void DMA1_Channel2_IRQHandler(void) { IRQ_ENTER(DMA1_Channel2_IRQn); if (dma_handle[dma_id_1] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_1]); } IRQ_EXIT(DMA1_Channel2_IRQn); }
+void DMA1_Channel3_IRQHandler(void) { IRQ_ENTER(DMA1_Channel3_IRQn); if (dma_handle[dma_id_2] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_2]); } IRQ_EXIT(DMA1_Channel3_IRQn); }
+void DMA1_Channel4_IRQHandler(void) { IRQ_ENTER(DMA1_Channel4_IRQn); if (dma_handle[dma_id_3] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_3]); } IRQ_EXIT(DMA1_Channel4_IRQn); }
+void DMA1_Channel5_IRQHandler(void) { IRQ_ENTER(DMA1_Channel5_IRQn); if (dma_handle[dma_id_4] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_4]); } IRQ_EXIT(DMA1_Channel5_IRQn); }
+void DMA1_Channel6_IRQHandler(void) { IRQ_ENTER(DMA1_Channel6_IRQn); if (dma_handle[dma_id_5] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_5]); } IRQ_EXIT(DMA1_Channel6_IRQn); }
+void DMA1_Channel7_IRQHandler(void) { IRQ_ENTER(DMA1_Channel7_IRQn); if (dma_handle[dma_id_6] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_6]); } IRQ_EXIT(DMA1_Channel7_IRQn); }
+void DMA2_Channel1_IRQHandler(void) { IRQ_ENTER(DMA2_Channel1_IRQn); if (dma_handle[dma_id_7] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_7]); } IRQ_EXIT(DMA2_Channel1_IRQn); }
+void DMA2_Channel2_IRQHandler(void) { IRQ_ENTER(DMA2_Channel2_IRQn); if (dma_handle[dma_id_8] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_8]); } IRQ_EXIT(DMA2_Channel2_IRQn); }
+void DMA2_Channel3_IRQHandler(void) { IRQ_ENTER(DMA2_Channel3_IRQn); if (dma_handle[dma_id_9] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_9]); } IRQ_EXIT(DMA2_Channel3_IRQn); }
+void DMA2_Channel4_IRQHandler(void) { IRQ_ENTER(DMA2_Channel4_IRQn); if (dma_handle[dma_id_10] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_10]);} IRQ_EXIT(DMA2_Channel4_IRQn); }
+void DMA2_Channel5_IRQHandler(void) { IRQ_ENTER(DMA2_Channel5_IRQn); if (dma_handle[dma_id_11] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_11]);} IRQ_EXIT(DMA2_Channel5_IRQn); }
+void DMA2_Channel6_IRQHandler(void) { IRQ_ENTER(DMA2_Channel6_IRQn); if (dma_handle[dma_id_12] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_12]);} IRQ_EXIT(DMA2_Channel6_IRQn); }
+void DMA2_Channel7_IRQHandler(void) { IRQ_ENTER(DMA2_Channel7_IRQn); if (dma_handle[dma_id_13] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_13]);} IRQ_EXIT(DMA2_Channel7_IRQn); }
+
+#endif
// Resets the idle counter for the DMA controller associated with dma_id.
-static void dma_tickle(int dma_id) {
- dma_idle.counter[(dma_id >> NSTREAMS_PER_CONTROLLER_LOG2) & 1] = 1;
+static void dma_tickle(dma_id_t dma_id) {
+ dma_idle.counter[(dma_id < NSTREAMS_PER_CONTROLLER) ? 0 : 1] = 1;
}
-static void dma_enable_clock(int dma_id) {
+static void dma_enable_clock(dma_id_t dma_id) {
// We don't want dma_tick_handler() to turn off the clock right after we
// enable it, so we need to mark the channel in use in an atomic fashion.
mp_uint_t irq_state = MICROPY_BEGIN_ATOMIC_SECTION();
@@ -129,7 +358,7 @@ static void dma_enable_clock(int dma_id) {
dma_enable_mask |= (1 << dma_id);
MICROPY_END_ATOMIC_SECTION(irq_state);
- if (dma_id <= 7) {
+ if (dma_id < NSTREAMS_PER_CONTROLLER) {
if (((old_enable_mask & DMA1_ENABLE_MASK) == 0) && !DMA1_IS_CLK_ENABLED()) {
__DMA1_CLK_ENABLE();
@@ -137,7 +366,7 @@ static void dma_enable_clock(int dma_id) {
// in dma_last_channel (for DMA1) needs to be invalidated.
for (int channel = 0; channel < NSTREAMS_PER_CONTROLLER; channel++) {
- dma_last_channel[channel] = DMA_INVALID_CHANNEL;
+ dma_last_sub_instance[channel] = DMA_INVALID_CHANNEL;
}
}
} else {
@@ -148,13 +377,13 @@ static void dma_enable_clock(int dma_id) {
// in dma_last_channel (for DMA1) needs to be invalidated.
for (int channel = NSTREAMS_PER_CONTROLLER; channel < NSTREAM; channel++) {
- dma_last_channel[channel] = DMA_INVALID_CHANNEL;
+ dma_last_sub_instance[channel] = DMA_INVALID_CHANNEL;
}
}
}
}
-static void dma_disable_clock(int dma_id) {
+static void dma_disable_clock(dma_id_t dma_id) {
// We just mark the clock as disabled here, but we don't actually disable it.
// We wait for the timer to expire first, which means that back-to-back
// transfers don't have to initialize as much.
@@ -162,61 +391,69 @@ static void dma_disable_clock(int dma_id) {
dma_enable_mask &= ~(1 << dma_id);
}
-void dma_init(DMA_HandleTypeDef *dma, DMA_Stream_TypeDef *dma_stream, const DMA_InitTypeDef *dma_init, uint32_t dma_channel, uint32_t direction, void *data) {
- int dma_id = get_dma_id(dma_stream);
- //printf("dma_init(%p, %p(%d), 0x%x, 0x%x, %p)\n", dma, dma_stream, dma_id, (uint)dma_channel, (uint)direction, data);
+void dma_init_handle(DMA_HandleTypeDef *dma, const dma_descr_t *dma_descr, void *data) {
+ // initialise parameters
+ dma->Instance = dma_descr->instance;
+ dma->Init = *dma_descr->init;
+ dma->Init.Direction = dma_descr->transfer_direction;
+ #if defined(MCU_SERIES_L4)
+ dma->Init.Request = dma_descr->sub_instance;
+ #else
+ dma->Init.Channel = dma_descr->sub_instance;
+ #endif
+ // half of __HAL_LINKDMA(data, xxx, *dma)
+ // caller must implement other half by doing: data->xxx = dma
+ dma->Parent = data;
+}
+void dma_init(DMA_HandleTypeDef *dma, const dma_descr_t *dma_descr, void *data){
// Some drivers allocate the DMA_HandleTypeDef from the stack
// (i.e. dac, i2c, spi) and for those cases we need to clear the
// structure so we don't get random values from the stack)
memset(dma, 0, sizeof(*dma));
- // set global pointer for IRQ handler
- dma_handle[dma_id] = dma;
+ if (dma_descr != NULL) {
+ dma_id_t dma_id = dma_descr->id;
- // initialise parameters
- dma->Instance = dma_stream;
- dma->Init = *dma_init;
- dma->Init.Direction = direction;
- dma->Init.Channel = dma_channel;
+ dma_init_handle(dma, dma_descr, data);
+ // set global pointer for IRQ handler
+ dma_handle[dma_id] = dma;
- // half of __HAL_LINKDMA(data, xxx, *dma)
- // caller must implement other half by doing: data->xxx = dma
- dma->Parent = data;
+ dma_enable_clock(dma_id);
- dma_enable_clock(dma_id);
+ // if this stream was previously configured for this channel/request then we
+ // can skip most of the initialisation
+ uint8_t sub_inst = DMA_SUB_INSTANCE_AS_UINT8(dma_descr->sub_instance);
+ if (dma_last_sub_instance[dma_id] != sub_inst) {
+ dma_last_sub_instance[dma_id] = sub_inst;
- // if this stream was previously configured for this channel then we
- // can skip most of the initialisation
- uint8_t channel_uint8 = DMA_CHANNEL_AS_UINT8(dma_channel);
- if (dma_last_channel[dma_id] == channel_uint8) {
- goto same_channel;
- }
- dma_last_channel[dma_id] = channel_uint8;
+ // reset and configure DMA peripheral
+ if (HAL_DMA_GetState(dma) != HAL_DMA_STATE_RESET) {
+ HAL_DMA_DeInit(dma);
+ }
+ HAL_DMA_Init(dma);
+ HAL_NVIC_SetPriority(dma_irqn[dma_id], IRQ_PRI_DMA, IRQ_SUBPRI_DMA);
+ }
- // reset and configure DMA peripheral
- if (HAL_DMA_GetState(dma) != HAL_DMA_STATE_RESET) {
- HAL_DMA_DeInit(dma);
+ HAL_NVIC_EnableIRQ(dma_irqn[dma_id]);
}
- HAL_DMA_Init(dma);
- HAL_NVIC_SetPriority(dma_irqn[dma_id], IRQ_PRI_DMA, IRQ_SUBPRI_DMA);
-
-same_channel:
- HAL_NVIC_EnableIRQ(dma_irqn[dma_id]);
}
-void dma_deinit(DMA_HandleTypeDef *dma) {
- int dma_id = get_dma_id(dma->Instance);
- HAL_NVIC_DisableIRQ(dma_irqn[dma_id]);
- dma_handle[dma_id] = NULL;
+void dma_deinit(const dma_descr_t *dma_descr) {
+ if (dma_descr != NULL) {
+ HAL_NVIC_DisableIRQ(dma_irqn[dma_descr->id]);
+ dma_handle[dma_descr->id] = NULL;
- dma_disable_clock(dma_id);
+ dma_disable_clock(dma_descr->id);
+ }
}
-void dma_invalidate_channel(DMA_Stream_TypeDef *dma_stream, uint32_t dma_channel) {
- int dma_id = get_dma_id(dma_stream);
- if (dma_last_channel[dma_id] == DMA_CHANNEL_AS_UINT8(dma_channel)) {
- dma_last_channel[dma_id] = DMA_INVALID_CHANNEL;
+void dma_invalidate_channel(const dma_descr_t *dma_descr) {
+ if (dma_descr != NULL) {
+ dma_id_t dma_id = dma_descr->id;
+ if (dma_last_sub_instance[dma_id] == DMA_SUB_INSTANCE_AS_UINT8(dma_descr->sub_instance) ) {
+ dma_last_sub_instance[dma_id] = DMA_INVALID_CHANNEL;
+ }
}
}
diff --git a/stmhal/dma.h b/stmhal/dma.h
index 9561d1b529..5880029f3d 100644
--- a/stmhal/dma.h
+++ b/stmhal/dma.h
@@ -24,82 +24,58 @@
* THE SOFTWARE.
*/
-// These are ordered by DMAx_Stream number, and within a stream by channel
-// number. The duplicate streams are ok as long as they aren't used at the
-// same time.
-//
-// Currently I2C and SPI are synchronous and they call dma_init/dma_deinit
-// around each transfer.
-
-// DMA1 streams
-
-#define DMA_STREAM_I2C1_RX DMA1_Stream0
-#define DMA_CHANNEL_I2C1_RX DMA_CHANNEL_1
-
-#define DMA_STREAM_SPI3_RX DMA1_Stream2
-#define DMA_CHANNEL_SPI3_RX DMA_CHANNEL_0
-
-#define DMA_STREAM_I2C3_RX DMA1_Stream2
-#define DMA_CHANNEL_I2C3_RX DMA_CHANNEL_3
-
-#define DMA_STREAM_I2C2_RX DMA1_Stream2
-#define DMA_CHANNEL_I2C2_RX DMA_CHANNEL_7
-
-#define DMA_STREAM_SPI2_RX DMA1_Stream3
-#define DMA_CHANNEL_SPI2_RX DMA_CHANNEL_0
-
-#define DMA_STREAM_SPI2_TX DMA1_Stream4
-#define DMA_CHANNEL_SPI2_TX DMA_CHANNEL_0
-
-#define DMA_STREAM_I2C3_TX DMA1_Stream4
-#define DMA_CHANNEL_I2C3_TX DMA_CHANNEL_3
-
-#define DMA_STREAM_DAC1 DMA1_Stream5
-#define DMA_CHANNEL_DAC1 DMA_CHANNEL_7
-
-#define DMA_STREAM_DAC2 DMA1_Stream6
-#define DMA_CHANNEL_DAC2 DMA_CHANNEL_7
-
-#define DMA_STREAM_SPI3_TX DMA1_Stream7
-#define DMA_CHANNEL_SPI3_TX DMA_CHANNEL_0
-
-#define DMA_STREAM_I2C1_TX DMA1_Stream7
-#define DMA_CHANNEL_I2C1_TX DMA_CHANNEL_1
-
-#define DMA_STREAM_I2C2_TX DMA1_Stream7
-#define DMA_CHANNEL_I2C2_TX DMA_CHANNEL_7
-
-// DMA2 streams
-
-#define DMA_STREAM_SPI1_RX DMA2_Stream2
-#define DMA_CHANNEL_SPI1_RX DMA_CHANNEL_3
-
-#define DMA_STREAM_SPI5_RX DMA2_Stream3
-#define DMA_CHANNEL_SPI5_RX DMA_CHANNEL_2
-
-#define DMA_STREAM_SDIO_RX DMA2_Stream3
-#define DMA_CHANNEL_SDIO_RX DMA_CHANNEL_4
-
-#define DMA_STREAM_SPI4_RX DMA2_Stream3
-#define DMA_CHANNEL_SPI4_RX DMA_CHANNEL_5
-
-#define DMA_STREAM_SPI5_TX DMA2_Stream4
-#define DMA_CHANNEL_SPI5_TX DMA_CHANNEL_2
-
-#define DMA_STREAM_SPI4_TX DMA2_Stream4
-#define DMA_CHANNEL_SPI4_TX DMA_CHANNEL_5
-
-#define DMA_STREAM_SPI6_TX DMA2_Stream5
-#define DMA_CHANNEL_SPI6_TX DMA_CHANNEL_1
-
-#define DMA_STREAM_SPI1_TX DMA2_Stream5
-#define DMA_CHANNEL_SPI1_TX DMA_CHANNEL_3
-
-#define DMA_STREAM_SPI6_RX DMA2_Stream6
-#define DMA_CHANNEL_SPI6_RX DMA_CHANNEL_1
-
-#define DMA_STREAM_SDIO_TX DMA2_Stream6
-#define DMA_CHANNEL_SDIO_TX DMA_CHANNEL_4
+#ifndef __MICROPY_INCLUDED_STMHAL_DMA_H__
+#define __MICROPY_INCLUDED_STMHAL_DMA_H__
+
+typedef struct _dma_descr_t dma_descr_t;
+
+#if defined(MCU_SERIES_F4) || defined(MCU_SERIES_F7)
+
+extern const dma_descr_t dma_I2C_1_RX;
+extern const dma_descr_t dma_SPI_3_RX;
+extern const dma_descr_t dma_I2C_3_RX;
+extern const dma_descr_t dma_I2C_2_RX;
+extern const dma_descr_t dma_SPI_2_RX;
+extern const dma_descr_t dma_SPI_2_TX;
+extern const dma_descr_t dma_I2C_3_TX;
+extern const dma_descr_t dma_DAC_1_TX;
+extern const dma_descr_t dma_DAC_2_TX;
+extern const dma_descr_t dma_SPI_3_TX;
+extern const dma_descr_t dma_I2C_1_TX;
+extern const dma_descr_t dma_I2C_2_TX;
+extern const dma_descr_t dma_SPI_1_RX;
+extern const dma_descr_t dma_SPI_5_RX;
+extern const dma_descr_t dma_SDIO_0_RX;
+extern const dma_descr_t dma_SPI_4_RX;
+extern const dma_descr_t dma_SPI_5_TX;
+extern const dma_descr_t dma_SPI_4_TX;
+extern const dma_descr_t dma_SPI_6_TX;
+extern const dma_descr_t dma_SPI_1_TX;
+extern const dma_descr_t dma_SPI_6_RX;
+extern const dma_descr_t dma_SDIO_0_TX;
+
+#elif defined(MCU_SERIES_L4)
+
+extern const dma_descr_t dma_ADC_1_RX;
+extern const dma_descr_t dma_ADC_2_RX;
+extern const dma_descr_t dma_SPI_1_RX;
+extern const dma_descr_t dma_I2C_3_TX;
+extern const dma_descr_t dma_ADC_3_RX;
+extern const dma_descr_t dma_SPI_1_TX;
+extern const dma_descr_t dma_I2C_3_RX;
+extern const dma_descr_t dma_DAC_1_TX;
+extern const dma_descr_t dma_SPI_2_RX;
+extern const dma_descr_t dma_I2C_2_TX;
+extern const dma_descr_t dma_DAC_2_TX;
+extern const dma_descr_t dma_SPI_2_TX;
+extern const dma_descr_t dma_I2C_2_RX;
+extern const dma_descr_t dma_I2C_1_TX;
+extern const dma_descr_t dma_I2C_1_RX;
+extern const dma_descr_t dma_SPI_3_RX;
+extern const dma_descr_t dma_SPI_3_TX;
+extern const dma_descr_t dma_SDIO_1_TX;
+
+#endif
typedef union {
uint16_t enabled; // Used to test if both counters are == 0
@@ -113,9 +89,11 @@ extern volatile dma_idle_count_t dma_idle;
#define DMA_IDLE_TICK_MAX (8) // 128 msec
#define DMA_IDLE_TICK(tick) (((tick) & DMA_SYSTICK_MASK) == 0)
-extern const DMA_InitTypeDef dma_init_struct_spi_i2c;
-void dma_init(DMA_HandleTypeDef *dma, DMA_Stream_TypeDef *dma_stream, const DMA_InitTypeDef *dma_init, uint32_t dma_channel, uint32_t direction, void *data);
-void dma_deinit(DMA_HandleTypeDef *dma);
-void dma_invalidate_channel(DMA_Stream_TypeDef *dma_stream, uint32_t dma_channel);
+void dma_init(DMA_HandleTypeDef *dma, const dma_descr_t *dma_descr, void *data);
+void dma_init_handle(DMA_HandleTypeDef *dma, const dma_descr_t *dma_descr, void *data);
+void dma_deinit(const dma_descr_t *dma_descr);
+void dma_invalidate_channel(const dma_descr_t *dma_descr);
void dma_idle_handler(int controller);
+
+#endif //__MICROPY_INCLUDED_STMHAL_DMA_H__
diff --git a/stmhal/i2c.c b/stmhal/i2c.c
index 9f6506b017..1909f81606 100644
--- a/stmhal/i2c.c
+++ b/stmhal/i2c.c
@@ -101,25 +101,14 @@
/// i2c.mem_read(3, 0x42, 2) # read 3 bytes from memory of slave 0x42,
/// # starting at address 2 in the slave
/// i2c.mem_write('abc', 0x42, 2, timeout=1000)
-
-// Possible DMA configurations for I2C busses:
-// I2C1_TX: DMA1_Stream6.CHANNEL_1 or DMA1_Stream7.CHANNEL_1
-// I2C1_RX: DMA1_Stream0.CHANNEL_1 or DMA1_Stream5.CHANNEL_1
-// I2C2_TX: DMA1_Stream7.CHANNEL_7
-// I2C2_RX: DMA1_Stream2.CHANNEL_7 or DMA1_Stream3.CHANNEL_7
-// I2C3_TX: DMA1_Stream4.CHANNEL_3
-// I2C3_RX: DMA1_Stream2.CHANNEL_3
-
#define PYB_I2C_MASTER (0)
#define PYB_I2C_SLAVE (1)
typedef struct _pyb_i2c_obj_t {
mp_obj_base_t base;
I2C_HandleTypeDef *i2c;
- DMA_Stream_TypeDef *tx_dma_stream;
- uint32_t tx_dma_channel;
- DMA_Stream_TypeDef *rx_dma_stream;
- uint32_t rx_dma_channel;
+ const dma_descr_t *tx_dma_descr;
+ const dma_descr_t *rx_dma_descr;
} pyb_i2c_obj_t;
#if defined(MICROPY_HW_I2C1_SCL)
@@ -134,24 +123,24 @@ I2C_HandleTypeDef I2CHandle3 = {.Instance = NULL};
STATIC const pyb_i2c_obj_t pyb_i2c_obj[] = {
#if defined(MICROPY_HW_I2C1_SCL)
- {{&pyb_i2c_type}, &I2CHandle1, DMA_STREAM_I2C1_TX, DMA_CHANNEL_I2C1_TX, DMA_STREAM_I2C1_RX, DMA_CHANNEL_I2C1_RX},
+ {{&pyb_i2c_type}, &I2CHandle1, &dma_I2C_1_TX, &dma_I2C_1_RX},
#else
- {{&pyb_i2c_type}, NULL, NULL, 0, NULL, 0},
+ {{&pyb_i2c_type}, NULL, NULL, NULL},
#endif
#if defined(MICROPY_HW_I2C2_SCL)
- {{&pyb_i2c_type}, &I2CHandle2, DMA_STREAM_I2C2_TX, DMA_CHANNEL_I2C2_TX, DMA_STREAM_I2C2_RX, DMA_CHANNEL_I2C2_RX},
+ {{&pyb_i2c_type}, &I2CHandle2, &dma_I2C_2_TX, &dma_I2C_2_RX},
#else
- {{&pyb_i2c_type}, NULL, NULL, 0, NULL, 0},
+ {{&pyb_i2c_type}, NULL, NULL, NULL},
#endif
#if defined(MICROPY_HW_I2C3_SCL)
- {{&pyb_i2c_type}, &I2CHandle3, DMA_STREAM_I2C3_TX, DMA_CHANNEL_I2C3_TX, DMA_STREAM_I2C3_RX, DMA_CHANNEL_I2C3_RX},
+ {{&pyb_i2c_type}, &I2CHandle3, &dma_I2C_3_TX, &dma_I2C_3_RX},
#else
- {{&pyb_i2c_type}, NULL, NULL, 0, NULL, 0},
+ {{&pyb_i2c_type}, NULL, NULL, NULL},
#endif
};
#if defined(MICROPY_HW_I2C_BAUDRATE_TIMING)
-// The STM32F0, F3, and F7 use a TIMINGR register rather than ClockSpeed and
+// The STM32F0, F3, F7 and L4 use a TIMINGR register rather than ClockSpeed and
// DutyCycle.
STATIC const struct {
@@ -263,8 +252,8 @@ void i2c_init(I2C_HandleTypeDef *i2c) {
// invalidate the DMA channels so they are initialised on first use
const pyb_i2c_obj_t *self = &pyb_i2c_obj[i2c_unit - 1];
- dma_invalidate_channel(self->tx_dma_stream, self->tx_dma_channel);
- dma_invalidate_channel(self->rx_dma_stream, self->rx_dma_channel);
+ dma_invalidate_channel(self->tx_dma_descr);
+ dma_invalidate_channel(self->rx_dma_descr);
}
void i2c_deinit(I2C_HandleTypeDef *i2c) {
@@ -528,7 +517,7 @@ STATIC mp_obj_t pyb_i2c_send(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_
// if IRQs are enabled then we can use DMA
DMA_HandleTypeDef tx_dma;
if (query_irq() == IRQ_STATE_ENABLED) {
- dma_init(&tx_dma, self->tx_dma_stream, &dma_init_struct_spi_i2c, self->tx_dma_channel, DMA_MEMORY_TO_PERIPH, self->i2c);
+ dma_init(&tx_dma, self->tx_dma_descr, self->i2c);
self->i2c->hdmatx = &tx_dma;
self->i2c->hdmarx = NULL;
}
@@ -538,7 +527,7 @@ STATIC mp_obj_t pyb_i2c_send(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_
if (in_master_mode(self)) {
if (args[1].u_int == PYB_I2C_MASTER_ADDRESS) {
if (query_irq() == IRQ_STATE_ENABLED) {
- dma_deinit(&tx_dma);
+ dma_deinit(self->tx_dma_descr);
}
nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "addr argument required"));
}
@@ -561,7 +550,7 @@ STATIC mp_obj_t pyb_i2c_send(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_
if (status == HAL_OK) {
status = i2c_wait_dma_finished(self->i2c, args[2].u_int);
}
- dma_deinit(&tx_dma);
+ dma_deinit(self->tx_dma_descr);
}
if (status != HAL_OK) {
@@ -602,7 +591,7 @@ STATIC mp_obj_t pyb_i2c_recv(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_
// if IRQs are enabled then we can use DMA
DMA_HandleTypeDef rx_dma;
if (query_irq() == IRQ_STATE_ENABLED) {
- dma_init(&rx_dma, self->rx_dma_stream, &dma_init_struct_spi_i2c, self->rx_dma_channel, DMA_PERIPH_TO_MEMORY, self->i2c);
+ dma_init(&rx_dma, self->rx_dma_descr, self->i2c);
self->i2c->hdmatx = NULL;
self->i2c->hdmarx = &rx_dma;
}
@@ -632,7 +621,7 @@ STATIC mp_obj_t pyb_i2c_recv(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_
if (status == HAL_OK) {
status = i2c_wait_dma_finished(self->i2c, args[2].u_int);
}
- dma_deinit(&rx_dma);
+ dma_deinit(self->rx_dma_descr);
}
if (status != HAL_OK) {
@@ -696,14 +685,14 @@ STATIC mp_obj_t pyb_i2c_mem_read(mp_uint_t n_args, const mp_obj_t *pos_args, mp_
status = HAL_I2C_Mem_Read(self->i2c, i2c_addr, mem_addr, mem_addr_size, (uint8_t*)vstr.buf, vstr.len, args[3].u_int);
} else {
DMA_HandleTypeDef rx_dma;
- dma_init(&rx_dma, self->rx_dma_stream, &dma_init_struct_spi_i2c, self->rx_dma_channel, DMA_PERIPH_TO_MEMORY, self->i2c);
+ dma_init(&rx_dma, self->rx_dma_descr, self->i2c);
self->i2c->hdmatx = NULL;
self->i2c->hdmarx = &rx_dma;
status = HAL_I2C_Mem_Read_DMA(self->i2c, i2c_addr, mem_addr, mem_addr_size, (uint8_t*)vstr.buf, vstr.len);
if (status == HAL_OK) {
status = i2c_wait_dma_finished(self->i2c, args[3].u_int);
}
- dma_deinit(&rx_dma);
+ dma_deinit(self->rx_dma_descr);
}
if (status != HAL_OK) {
@@ -760,14 +749,14 @@ STATIC mp_obj_t pyb_i2c_mem_write(mp_uint_t n_args, const mp_obj_t *pos_args, mp
status = HAL_I2C_Mem_Write(self->i2c, i2c_addr, mem_addr, mem_addr_size, bufinfo.buf, bufinfo.len, args[3].u_int);
} else {
DMA_HandleTypeDef tx_dma;
- dma_init(&tx_dma, self->tx_dma_stream, &dma_init_struct_spi_i2c, self->tx_dma_channel, DMA_MEMORY_TO_PERIPH, self->i2c);
+ dma_init(&tx_dma, self->tx_dma_descr, self->i2c);
self->i2c->hdmatx = &tx_dma;
self->i2c->hdmarx = NULL;
status = HAL_I2C_Mem_Write_DMA(self->i2c, i2c_addr, mem_addr, mem_addr_size, bufinfo.buf, bufinfo.len);
if (status == HAL_OK) {
status = i2c_wait_dma_finished(self->i2c, args[3].u_int);
}
- dma_deinit(&tx_dma);
+ dma_deinit(self->tx_dma_descr);
}
if (status != HAL_OK) {
diff --git a/stmhal/i2c.h b/stmhal/i2c.h
index 849d3987c4..a159935e6a 100644
--- a/stmhal/i2c.h
+++ b/stmhal/i2c.h
@@ -29,6 +29,7 @@
extern I2C_HandleTypeDef I2CHandle1;
extern I2C_HandleTypeDef I2CHandle2;
+extern I2C_HandleTypeDef I2CHandle3;
extern const mp_obj_type_t pyb_i2c_type;
void i2c_init0(void);
diff --git a/stmhal/led.c b/stmhal/led.c
index fcdb88c9c3..fdf5b04d8e 100644
--- a/stmhal/led.c
+++ b/stmhal/led.c
@@ -41,6 +41,11 @@
///
/// The LED object controls an individual LED (Light Emitting Diode).
+// the default is that LEDs are not inverted, and pin driven high turns them on
+#ifndef MICROPY_HW_LED_INVERTED
+#define MICROPY_HW_LED_INVERTED (0)
+#endif
+
typedef struct _pyb_led_obj_t {
mp_obj_base_t base;
mp_uint_t led_id;
@@ -86,30 +91,34 @@ void led_init(void) {
|| defined(MICROPY_HW_LED4_PWM)
// The following is semi-generic code to control LEDs using PWM.
-// It currently supports TIM2 and TIM3, channel 1 only.
+// It currently supports TIM1, TIM2 and TIM3, channels 1-4.
// Configure by defining the relevant MICROPY_HW_LEDx_PWM macros in mpconfigboard.h.
// If they are not defined then PWM will not be available for that LED.
#define LED_PWM_ENABLED (1)
#ifndef MICROPY_HW_LED1_PWM
-#define MICROPY_HW_LED1_PWM { NULL, 0, 0 }
+#define MICROPY_HW_LED1_PWM { NULL, 0, 0, 0 }
#endif
#ifndef MICROPY_HW_LED2_PWM
-#define MICROPY_HW_LED2_PWM { NULL, 0, 0 }
+#define MICROPY_HW_LED2_PWM { NULL, 0, 0, 0 }
#endif
#ifndef MICROPY_HW_LED3_PWM
-#define MICROPY_HW_LED3_PWM { NULL, 0, 0 }
+#define MICROPY_HW_LED3_PWM { NULL, 0, 0, 0 }
#endif
#ifndef MICROPY_HW_LED4_PWM
-#define MICROPY_HW_LED4_PWM { NULL, 0, 0 }
+#define MICROPY_HW_LED4_PWM { NULL, 0, 0, 0 }
#endif
#define LED_PWM_TIM_PERIOD (10000) // TIM runs at 1MHz and fires every 10ms
+// this gives the address of the CCR register for channels 1-4
+#define LED_PWM_CCR(pwm_cfg) ((volatile uint32_t*)&(pwm_cfg)->tim->CCR1 + ((pwm_cfg)->tim_channel >> 2))
+
typedef struct _led_pwm_config_t {
TIM_TypeDef *tim;
uint8_t tim_id;
+ uint8_t tim_channel;
uint8_t alt_func;
} led_pwm_config_t;
@@ -143,6 +152,7 @@ STATIC void led_pwm_init(int led) {
// TIM configuration
switch (pwm_cfg->tim_id) {
+ case 1: __TIM1_CLK_ENABLE(); break;
case 2: __TIM2_CLK_ENABLE(); break;
case 3: __TIM3_CLK_ENABLE(); break;
default: assert(0);
@@ -153,21 +163,20 @@ STATIC void led_pwm_init(int led) {
tim.Init.Prescaler = timer_get_source_freq(pwm_cfg->tim_id) / 1000000 - 1; // TIM runs at 1MHz
tim.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
tim.Init.CounterMode = TIM_COUNTERMODE_UP;
+ tim.Init.RepetitionCounter = 0;
HAL_TIM_PWM_Init(&tim);
- // PWM configuration (only channel 1 supported at the moment)
+ // PWM configuration
TIM_OC_InitTypeDef oc_init;
oc_init.OCMode = TIM_OCMODE_PWM1;
oc_init.Pulse = 0; // off
- oc_init.OCPolarity = TIM_OCPOLARITY_HIGH;
+ oc_init.OCPolarity = MICROPY_HW_LED_INVERTED ? TIM_OCPOLARITY_LOW : TIM_OCPOLARITY_HIGH;
oc_init.OCFastMode = TIM_OCFAST_DISABLE;
- /* needed only for TIM1 and TIM8
- oc_init.OCNPolarity = TIM_OCNPOLARITY_HIGH;
- oc_init.OCIdleState = TIM_OCIDLESTATE_SET;
- oc_init.OCNIdleState = TIM_OCNIDLESTATE_SET;
- */
- HAL_TIM_PWM_ConfigChannel(&tim, &oc_init, TIM_CHANNEL_1);
- HAL_TIM_PWM_Start(&tim, TIM_CHANNEL_1);
+ oc_init.OCNPolarity = TIM_OCNPOLARITY_HIGH; // needed for TIM1 and TIM8
+ oc_init.OCIdleState = TIM_OCIDLESTATE_SET; // needed for TIM1 and TIM8
+ oc_init.OCNIdleState = TIM_OCNIDLESTATE_SET; // needed for TIM1 and TIM8
+ HAL_TIM_PWM_ConfigChannel(&tim, &oc_init, pwm_cfg->tim_channel);
+ HAL_TIM_PWM_Start(&tim, pwm_cfg->tim_channel);
// indicate that this LED is using PWM
led_pwm_state |= 1 << led;
@@ -236,8 +245,8 @@ int led_get_intensity(pyb_led_t led) {
#if LED_PWM_ENABLED
if (led_pwm_is_enabled(led)) {
- TIM_TypeDef *tim = led_pwm_config[led - 1].tim;
- mp_uint_t i = (tim->CCR1 * 255 + LED_PWM_TIM_PERIOD - 2) / (LED_PWM_TIM_PERIOD - 1);
+ const led_pwm_config_t *pwm_cfg = &led_pwm_config[led - 1];
+ mp_uint_t i = (*LED_PWM_CCR(pwm_cfg) * 255 + LED_PWM_TIM_PERIOD - 2) / (LED_PWM_TIM_PERIOD - 1);
if (i > 255) {
i = 255;
}
@@ -248,26 +257,25 @@ int led_get_intensity(pyb_led_t led) {
const pin_obj_t *led_pin = pyb_led_obj[led - 1].led_pin;
GPIO_TypeDef *gpio = led_pin->gpio;
- // TODO convert high/low to on/off depending on board
if (gpio->ODR & led_pin->pin_mask) {
// pin is high
- return 255;
+ return MICROPY_HW_LED_INVERTED ? 0 : 255;
} else {
// pin is low
- return 0;
+ return MICROPY_HW_LED_INVERTED ? 255 : 0;
}
}
void led_set_intensity(pyb_led_t led, mp_int_t intensity) {
#if LED_PWM_ENABLED
if (intensity > 0 && intensity < 255) {
- TIM_TypeDef *tim = led_pwm_config[led - 1].tim;
- if (tim != NULL) {
+ const led_pwm_config_t *pwm_cfg = &led_pwm_config[led - 1];
+ if (pwm_cfg->tim != NULL) {
// set intensity using PWM pulse width
if (!led_pwm_is_enabled(led)) {
led_pwm_init(led);
}
- tim->CCR1 = intensity * (LED_PWM_TIM_PERIOD - 1) / 255;
+ *LED_PWM_CCR(pwm_cfg) = intensity * (LED_PWM_TIM_PERIOD - 1) / 255;
return;
}
}
diff --git a/stmhal/main.c b/stmhal/main.c
index 329109cd3d..30dddaf989 100644
--- a/stmhal/main.c
+++ b/stmhal/main.c
@@ -367,13 +367,15 @@ int main(void) {
__GPIOC_CLK_ENABLE();
__GPIOD_CLK_ENABLE();
- #if defined(__HAL_RCC_DTCMRAMEN_CLK_ENABLE)
- // The STM32F746 doesn't really have CCM memory, but it does have DTCM,
- // which behaves more or less like normal SRAM.
- __HAL_RCC_DTCMRAMEN_CLK_ENABLE();
- #else
- // enable the CCM RAM
- __CCMDATARAMEN_CLK_ENABLE();
+ #if defined(MCU_SERIES_F4) || defined(MCU_SERIES_F7)
+ #if defined(__HAL_RCC_DTCMRAMEN_CLK_ENABLE)
+ // The STM32F746 doesn't really have CCM memory, but it does have DTCM,
+ // which behaves more or less like normal SRAM.
+ __HAL_RCC_DTCMRAMEN_CLK_ENABLE();
+ #else
+ // enable the CCM RAM
+ __CCMDATARAMEN_CLK_ENABLE();
+ #endif
#endif
#if defined(MICROPY_BOARD_EARLY_INIT)
diff --git a/stmhal/modmachine.c b/stmhal/modmachine.c
index 1e4862044a..0b01058fa5 100644
--- a/stmhal/modmachine.c
+++ b/stmhal/modmachine.c
@@ -190,6 +190,10 @@ STATIC mp_obj_t machine_freq(mp_uint_t n_args, const mp_obj_t *args) {
// set
mp_int_t wanted_sysclk = mp_obj_get_int(args[0]) / 1000000;
+ #if defined(MCU_SERIES_L4)
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_NotImplementedError, "machine.freq set not supported yet"));
+ #endif
+
// default PLL parameters that give 48MHz on PLL48CK
uint32_t m = HSE_VALUE / 1000000, n = 336, p = 2, q = 7;
uint32_t sysclk_source;
@@ -310,9 +314,12 @@ STATIC mp_obj_t machine_freq(mp_uint_t n_args, const mp_obj_t *args) {
// set PLL as system clock source if wanted
if (sysclk_source == RCC_SYSCLKSOURCE_PLLCLK) {
+ #if !defined(MICROPY_HW_FLASH_LATENCY)
+ #define MICROPY_HW_FLASH_LATENCY FLASH_LATENCY_5
+ #endif
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
- if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK) {
+ if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, MICROPY_HW_FLASH_LATENCY) != HAL_OK) {
goto fail;
}
}
@@ -344,6 +351,35 @@ STATIC mp_obj_t machine_freq(mp_uint_t n_args, const mp_obj_t *args) {
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_freq_obj, 0, 4, machine_freq);
STATIC mp_obj_t machine_sleep(void) {
+ #if defined(MCU_SERIES_L4)
+
+ // Enter Stop 1 mode
+ __HAL_RCC_WAKEUPSTOP_CLK_CONFIG(RCC_STOP_WAKEUPCLOCK_MSI);
+ HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
+
+ // reconfigure system clock after wakeup
+ // Enable Power Control clock
+ __HAL_RCC_PWR_CLK_ENABLE();
+
+ // Get the Oscillators configuration according to the internal RCC registers
+ RCC_OscInitTypeDef RCC_OscInitStruct = {0};
+ HAL_RCC_GetOscConfig(&RCC_OscInitStruct);
+ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;
+ RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
+ HAL_RCC_OscConfig(&RCC_OscInitStruct);
+
+ // Get the Clocks configuration according to the internal RCC registers
+ RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
+ uint32_t pFLatency = 0;
+ HAL_RCC_GetClockConfig(&RCC_ClkInitStruct, &pFLatency);
+
+ // Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 clock dividers
+ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK;
+ RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
+ HAL_RCC_ClockConfig(&RCC_ClkInitStruct, pFLatency);
+
+ #else
+
// takes longer to wake but reduces stop current
HAL_PWREx_EnableFlashPowerDown();
@@ -366,6 +402,8 @@ STATIC mp_obj_t machine_sleep(void) {
while (__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_PLL) {
}
+ #endif
+
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_0(machine_sleep_obj, machine_sleep);
@@ -373,7 +411,7 @@ MP_DEFINE_CONST_FUN_OBJ_0(machine_sleep_obj, machine_sleep);
STATIC mp_obj_t machine_deepsleep(void) {
rtc_init_finalise();
-#if defined(MCU_SERIES_F7)
+#if defined(MCU_SERIES_F7) || defined(MCU_SERIES_L4)
printf("machine.deepsleep not supported yet\n");
#else
// We need to clear the PWR wake-up-flag before entering standby, since
diff --git a/stmhal/modnetwork.c b/stmhal/modnetwork.c
index 86bf7379bb..4425461a07 100644
--- a/stmhal/modnetwork.c
+++ b/stmhal/modnetwork.c
@@ -27,7 +27,6 @@
#include <stdio.h>
#include <stdint.h>
#include <string.h>
-#include <errno.h>
#include "py/nlr.h"
#include "py/objlist.h"
diff --git a/stmhal/modnwcc3k.c b/stmhal/modnwcc3k.c
index 85dc0585a8..5910576029 100644
--- a/stmhal/modnwcc3k.c
+++ b/stmhal/modnwcc3k.c
@@ -26,7 +26,6 @@
#include <string.h>
#include <stdarg.h>
-#include <errno.h>
// CC3000 defines its own ENOBUFS (different to standard one!)
#undef ENOBUFS
@@ -36,6 +35,7 @@
#include "py/objlist.h"
#include "py/stream.h"
#include "py/runtime.h"
+#include "py/mperrno.h"
#include "netutils.h"
#include "modnetwork.h"
#include "pin.h"
@@ -126,7 +126,7 @@ STATIC int cc3k_gethostbyname(mp_obj_t nic, const char *name, mp_uint_t len, uin
if (ip == 0) {
// unknown host
- return ENOENT;
+ return MP_ENOENT;
}
out_ip[0] = ip >> 24;
@@ -139,7 +139,7 @@ STATIC int cc3k_gethostbyname(mp_obj_t nic, const char *name, mp_uint_t len, uin
STATIC int cc3k_socket_socket(mod_network_socket_obj_t *socket, int *_errno) {
if (socket->u_param.domain != MOD_NETWORK_AF_INET) {
- *_errno = EAFNOSUPPORT;
+ *_errno = MP_EAFNOSUPPORT;
return -1;
}
@@ -148,7 +148,7 @@ STATIC int cc3k_socket_socket(mod_network_socket_obj_t *socket, int *_errno) {
case MOD_NETWORK_SOCK_STREAM: type = SOCK_STREAM; break;
case MOD_NETWORK_SOCK_DGRAM: type = SOCK_DGRAM; break;
case MOD_NETWORK_SOCK_RAW: type = SOCK_RAW; break;
- default: *_errno = EINVAL; return -1;
+ default: *_errno = MP_EINVAL; return -1;
}
// open socket
@@ -202,7 +202,7 @@ STATIC int cc3k_socket_accept(mod_network_socket_obj_t *socket, mod_network_sock
socklen_t addr_len = sizeof(addr);
if ((fd = CC3000_EXPORT(accept)(socket->u_state, &addr, &addr_len)) < 0) {
if (fd == SOC_IN_PROGRESS) {
- *_errno = EAGAIN;
+ *_errno = MP_EAGAIN;
} else {
*_errno = -fd;
}
@@ -240,7 +240,7 @@ STATIC int cc3k_socket_connect(mod_network_socket_obj_t *socket, byte *ip, mp_ui
STATIC mp_uint_t cc3k_socket_send(mod_network_socket_obj_t *socket, const byte *buf, mp_uint_t len, int *_errno) {
if (cc3k_get_fd_closed_state(socket->u_state)) {
CC3000_EXPORT(closesocket)(socket->u_state);
- *_errno = EPIPE;
+ *_errno = MP_EPIPE;
return -1;
}
@@ -267,7 +267,7 @@ STATIC mp_uint_t cc3k_socket_recv(mod_network_socket_obj_t *socket, byte *buf, m
fd_set rfds;
FD_ZERO(&rfds);
FD_SET(socket->u_state, &rfds);
- timeval tv;
+ cc3000_timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 1;
int nfds = CC3000_EXPORT(select)(socket->u_state + 1, &rfds, NULL, NULL, &tv);
@@ -383,7 +383,7 @@ STATIC int cc3k_socket_ioctl(mod_network_socket_obj_t *socket, mp_uint_t request
}
// call cc3000 select with minimum timeout
- timeval tv;
+ cc3000_timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 1;
int nfds = CC3000_EXPORT(select)(fd + 1, &rfds, &wfds, &xfds, &tv);
@@ -405,7 +405,7 @@ STATIC int cc3k_socket_ioctl(mod_network_socket_obj_t *socket, mp_uint_t request
ret |= MP_IOCTL_POLL_HUP;
}
} else {
- *_errno = EINVAL;
+ *_errno = MP_EINVAL;
ret = -1;
}
return ret;
diff --git a/stmhal/modnwwiznet5k.c b/stmhal/modnwwiznet5k.c
index b6f18354b9..c8b5d628f4 100644
--- a/stmhal/modnwwiznet5k.c
+++ b/stmhal/modnwwiznet5k.c
@@ -27,11 +27,11 @@
#include <stdio.h>
#include <stdint.h>
#include <string.h>
-#include <errno.h>
#include "py/nlr.h"
#include "py/objlist.h"
#include "py/runtime.h"
+#include "py/mperrno.h"
#include "py/mphal.h"
#include "netutils.h"
#include "modnetwork.h"
@@ -93,20 +93,20 @@ STATIC int wiznet5k_gethostbyname(mp_obj_t nic, const char *name, mp_uint_t len,
return 0;
} else {
// failure
- return ENOENT;
+ return MP_ENOENT;
}
}
STATIC int wiznet5k_socket_socket(mod_network_socket_obj_t *socket, int *_errno) {
if (socket->u_param.domain != MOD_NETWORK_AF_INET) {
- *_errno = EAFNOSUPPORT;
+ *_errno = MP_EAFNOSUPPORT;
return -1;
}
switch (socket->u_param.type) {
case MOD_NETWORK_SOCK_STREAM: socket->u_param.type = Sn_MR_TCP; break;
case MOD_NETWORK_SOCK_DGRAM: socket->u_param.type = Sn_MR_UDP; break;
- default: *_errno = EINVAL; return -1;
+ default: *_errno = MP_EINVAL; return -1;
}
if (socket->u_param.fileno == -1) {
@@ -120,7 +120,7 @@ STATIC int wiznet5k_socket_socket(mod_network_socket_obj_t *socket, int *_errno)
}
if (socket->u_param.fileno == -1) {
// too many open sockets
- *_errno = EMFILE;
+ *_errno = MP_EMFILE;
return -1;
}
}
@@ -199,7 +199,7 @@ STATIC int wiznet5k_socket_accept(mod_network_socket_obj_t *socket, mod_network_
}
if (sr == SOCK_CLOSED || sr == SOCK_CLOSE_WAIT) {
wiznet5k_socket_close(socket);
- *_errno = ENOTCONN; // ??
+ *_errno = MP_ENOTCONN; // ??
return -1;
}
HAL_Delay(1);
@@ -277,13 +277,13 @@ STATIC mp_uint_t wiznet5k_socket_recvfrom(mod_network_socket_obj_t *socket, byte
STATIC int wiznet5k_socket_setsockopt(mod_network_socket_obj_t *socket, mp_uint_t level, mp_uint_t opt, const void *optval, mp_uint_t optlen, int *_errno) {
// TODO
- *_errno = EINVAL;
+ *_errno = MP_EINVAL;
return -1;
}
STATIC int wiznet5k_socket_settimeout(mod_network_socket_obj_t *socket, mp_uint_t timeout_ms, int *_errno) {
// TODO
- *_errno = EINVAL;
+ *_errno = MP_EINVAL;
return -1;
/*
@@ -297,7 +297,7 @@ STATIC int wiznet5k_socket_settimeout(mod_network_socket_obj_t *socket, mp_uint_
STATIC int wiznet5k_socket_ioctl(mod_network_socket_obj_t *socket, mp_uint_t request, mp_uint_t arg, int *_errno) {
// TODO
- *_errno = EINVAL;
+ *_errno = MP_EINVAL;
return -1;
}
diff --git a/stmhal/moduos.c b/stmhal/moduos.c
index 310b8d44fb..52d0a58425 100644
--- a/stmhal/moduos.c
+++ b/stmhal/moduos.c
@@ -107,7 +107,7 @@ STATIC mp_obj_t os_getcwd(void) {
FRESULT res = f_getcwd(buf, sizeof buf);
if (res != FR_OK) {
- nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(fresult_to_errno_table[res])));
+ nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(fresult_to_errno_table[res])));
}
return mp_obj_new_str(buf, strlen(buf), false);
diff --git a/stmhal/moduselect.c b/stmhal/moduselect.c
index 8923b4d505..e87478ae62 100644
--- a/stmhal/moduselect.c
+++ b/stmhal/moduselect.c
@@ -25,11 +25,11 @@
*/
#include <stdio.h>
-#include <errno.h>
#include "py/nlr.h"
#include "py/obj.h"
#include "py/objlist.h"
+#include "py/mperrno.h"
#include "py/mphal.h"
#include "pybioctl.h"
@@ -212,7 +212,7 @@ STATIC mp_obj_t poll_modify(mp_obj_t self_in, mp_obj_t obj_in, mp_obj_t eventmas
mp_obj_poll_t *self = self_in;
mp_map_elem_t *elem = mp_map_lookup(&self->poll_map, mp_obj_id(obj_in), MP_MAP_LOOKUP);
if (elem == NULL) {
- nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(ENOENT)));
+ nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(MP_ENOENT)));
}
((poll_obj_t*)elem->value)->flags = mp_obj_get_int(eventmask_in);
return mp_const_none;
diff --git a/stmhal/modusocket.c b/stmhal/modusocket.c
index 8da56fa8bb..9cc1f3314a 100644
--- a/stmhal/modusocket.c
+++ b/stmhal/modusocket.c
@@ -26,12 +26,12 @@
#include <stdio.h>
#include <string.h>
-#include <errno.h>
#include "py/nlr.h"
#include "py/objtuple.h"
#include "py/objlist.h"
#include "py/runtime.h"
+#include "py/mperrno.h"
#include "netutils.h"
#include "modnetwork.h"
@@ -116,7 +116,7 @@ STATIC mp_obj_t socket_listen(mp_obj_t self_in, mp_obj_t backlog) {
if (self->nic == MP_OBJ_NULL) {
// not connected
// TODO I think we can listen even if not bound...
- nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(ENOTCONN)));
+ nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(MP_ENOTCONN)));
}
int _errno;
@@ -186,7 +186,7 @@ STATIC mp_obj_t socket_send(mp_obj_t self_in, mp_obj_t buf_in) {
mod_network_socket_obj_t *self = self_in;
if (self->nic == MP_OBJ_NULL) {
// not connected
- nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(EPIPE)));
+ nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(MP_EPIPE)));
}
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ);
@@ -204,7 +204,7 @@ STATIC mp_obj_t socket_recv(mp_obj_t self_in, mp_obj_t len_in) {
mod_network_socket_obj_t *self = self_in;
if (self->nic == MP_OBJ_NULL) {
// not connected
- nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(ENOTCONN)));
+ nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(MP_ENOTCONN)));
}
mp_int_t len = mp_obj_get_int(len_in);
vstr_t vstr;
@@ -253,7 +253,7 @@ STATIC mp_obj_t socket_recvfrom(mp_obj_t self_in, mp_obj_t len_in) {
mod_network_socket_obj_t *self = self_in;
if (self->nic == MP_OBJ_NULL) {
// not connected
- nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(ENOTCONN)));
+ nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(MP_ENOTCONN)));
}
vstr_t vstr;
vstr_init_len(&vstr, mp_obj_get_int(len_in));
@@ -314,7 +314,7 @@ STATIC mp_obj_t socket_settimeout(mp_obj_t self_in, mp_obj_t timeout_in) {
mod_network_socket_obj_t *self = self_in;
if (self->nic == MP_OBJ_NULL) {
// not connected
- nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(ENOTCONN)));
+ nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(MP_ENOTCONN)));
}
mp_uint_t timeout;
if (timeout_in == mp_const_none) {
diff --git a/stmhal/mpconfigport.h b/stmhal/mpconfigport.h
index 6ec92acbfe..29e4bd8d87 100644
--- a/stmhal/mpconfigport.h
+++ b/stmhal/mpconfigport.h
@@ -61,6 +61,7 @@
#define MICROPY_STREAMS_NON_BLOCK (1)
#define MICROPY_MODULE_WEAK_LINKS (1)
#define MICROPY_CAN_OVERRIDE_BUILTINS (1)
+#define MICROPY_USE_INTERNAL_ERRNO (1)
#define MICROPY_PY_FUNCTION_ATTRS (1)
#define MICROPY_PY_BUILTINS_STR_UNICODE (1)
#define MICROPY_PY_BUILTINS_STR_SPLITLINES (1)
@@ -80,6 +81,7 @@
#define MICROPY_PY_CMATH (1)
#define MICROPY_PY_IO (1)
#define MICROPY_PY_IO_FILEIO (1)
+#define MICROPY_PY_UERRNO (1)
#define MICROPY_PY_UBINASCII (1)
#define MICROPY_PY_URANDOM (1)
#define MICROPY_PY_URANDOM_EXTRA_FUNCS (1)
@@ -141,6 +143,7 @@ extern const struct _mp_obj_module_t mp_module_network;
{ MP_OBJ_NEW_QSTR(MP_QSTR_socket), (mp_obj_t)&mp_module_usocket }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_struct), (mp_obj_t)&mp_module_ustruct }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_machine), (mp_obj_t)&machine_module }, \
+ { MP_OBJ_NEW_QSTR(MP_QSTR_errno), (mp_obj_t)&mp_module_uerrno }, \
// extra constants
#define MICROPY_PORT_CONSTANTS \
diff --git a/stmhal/mphalport.c b/stmhal/mphalport.c
index 7a86989ffd..cea0369213 100644
--- a/stmhal/mphalport.c
+++ b/stmhal/mphalport.c
@@ -1,7 +1,7 @@
-#include <errno.h>
#include <string.h>
#include "py/mpstate.h"
+#include "py/mperrno.h"
#include "py/mphal.h"
#include "usb.h"
#include "uart.h"
@@ -9,9 +9,9 @@
// this table converts from HAL_StatusTypeDef to POSIX errno
const byte mp_hal_status_to_errno_table[4] = {
[HAL_OK] = 0,
- [HAL_ERROR] = EIO,
- [HAL_BUSY] = EBUSY,
- [HAL_TIMEOUT] = ETIMEDOUT,
+ [HAL_ERROR] = MP_EIO,
+ [HAL_BUSY] = MP_EBUSY,
+ [HAL_TIMEOUT] = MP_ETIMEDOUT,
};
NORETURN void mp_hal_raise(HAL_StatusTypeDef status) {
diff --git a/stmhal/mphalport.h b/stmhal/mphalport.h
index 7b29f9c9c0..b155d9616e 100644
--- a/stmhal/mphalport.h
+++ b/stmhal/mphalport.h
@@ -45,7 +45,7 @@ void mp_hal_set_interrupt_char(int c); // -1 to disable
#include "stmhal/pin.h"
#define mp_hal_pin_obj_t pin_obj_t*
#define mp_hal_get_pin_obj(o) (pin_obj_t*)pin_find(o)
-#define mp_hal_pin_config_od(p) mp_hal_gpio_config((p)->gpio, (p)->pin, 5, 0, 0)
-#define mp_hal_pin_low(p) GPIO_clear_pin((p)->gpio, (p)->pin_mask)
+#define mp_hal_pin_open_drain(p) mp_hal_gpio_config((p)->gpio, (p)->pin, 5, 0, 0)
+#define mp_hal_pin_od_low(p) GPIO_clear_pin((p)->gpio, (p)->pin_mask)
#define mp_hal_pin_od_high(p) GPIO_set_pin((p)->gpio, (p)->pin_mask)
#define mp_hal_pin_read(p) GPIO_read_pin((p)->gpio, (p)->pin)
diff --git a/stmhal/pybstdio.c b/stmhal/pybstdio.c
index 72c164b36d..352b7c10c2 100644
--- a/stmhal/pybstdio.c
+++ b/stmhal/pybstdio.c
@@ -26,10 +26,10 @@
#include <stdio.h>
#include <string.h>
-#include <errno.h>
#include "py/obj.h"
#include "py/stream.h"
+#include "py/mperrno.h"
#include "py/mphal.h"
// TODO make stdin, stdout and stderr writable objects so they can
@@ -69,7 +69,7 @@ STATIC mp_uint_t stdio_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *er
}
return size;
} else {
- *errcode = EPERM;
+ *errcode = MP_EPERM;
return MP_STREAM_ERROR;
}
}
@@ -80,7 +80,7 @@ STATIC mp_uint_t stdio_write(mp_obj_t self_in, const void *buf, mp_uint_t size,
mp_hal_stdout_tx_strn_cooked(buf, size);
return size;
} else {
- *errcode = EPERM;
+ *errcode = MP_EPERM;
return MP_STREAM_ERROR;
}
}
diff --git a/stmhal/sdcard.c b/stmhal/sdcard.c
index 59fe3fac82..32c9df60a2 100644
--- a/stmhal/sdcard.c
+++ b/stmhal/sdcard.c
@@ -24,6 +24,8 @@
* THE SOFTWARE.
*/
+#include <string.h>
+
#include "py/nlr.h"
#include "py/runtime.h"
#include "lib/fatfs/ff.h"
@@ -63,6 +65,11 @@
#define SDIO_TRANSFER_CLK_DIV SDMMC_TRANSFER_CLK_DIV
+#elif defined(MCU_SERIES_L4)
+
+// The L4 series is not supported
+#error Unsupported Processor
+
#endif
// TODO: Since SDIO is fundamentally half-duplex, we really only need to
@@ -77,22 +84,6 @@
static SD_HandleTypeDef sd_handle;
static DMA_HandleTypeDef sd_rx_dma, sd_tx_dma;
-// Parameters to dma_init() for SDIO tx and rx.
-static const DMA_InitTypeDef dma_init_struct_sdio = {
- .Channel = 0,
- .Direction = 0,
- .PeriphInc = DMA_PINC_DISABLE,
- .MemInc = DMA_MINC_ENABLE,
- .PeriphDataAlignment = DMA_PDATAALIGN_WORD,
- .MemDataAlignment = DMA_MDATAALIGN_WORD,
- .Mode = DMA_PFCTRL,
- .Priority = DMA_PRIORITY_VERY_HIGH,
- .FIFOMode = DMA_FIFOMODE_ENABLE,
- .FIFOThreshold = DMA_FIFO_THRESHOLD_FULL,
- .MemBurst = DMA_MBURST_INC4,
- .PeriphBurst = DMA_PBURST_INC4,
-};
-
void sdcard_init(void) {
GPIO_InitTypeDef GPIO_Init_Structure;
@@ -203,11 +194,6 @@ void SDIO_IRQHandler(void) {
}
mp_uint_t sdcard_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blocks) {
- // check that dest pointer is aligned on a 4-byte boundary
- if (((uint32_t)dest & 3) != 0) {
- return SD_ERROR;
- }
-
// check that SD card is initialised
if (sd_handle.Instance == NULL) {
return SD_ERROR;
@@ -215,12 +201,29 @@ mp_uint_t sdcard_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blo
HAL_SD_ErrorTypedef err = SD_OK;
+ // check that dest pointer is aligned on a 4-byte boundary
+ uint8_t *orig_dest = NULL;
+ uint32_t saved_word;
+ if (((uint32_t)dest & 3) != 0) {
+ // Pointer is not aligned so it needs fixing.
+ // We could allocate a temporary block of RAM (as sdcard_write_blocks
+ // does) but instead we are going to use the dest buffer inplace. We
+ // are going to align the pointer, save the initial word at the aligned
+ // location, read into the aligned memory, move the memory back to the
+ // unaligned location, then restore the initial bytes at the aligned
+ // location. We should have no trouble doing this as those initial
+ // bytes at the aligned location should be able to be changed for the
+ // duration of this function call.
+ orig_dest = dest;
+ dest = (uint8_t*)((uint32_t)dest & ~3);
+ saved_word = *(uint32_t*)dest;
+ }
+
if (query_irq() == IRQ_STATE_ENABLED) {
// we must disable USB irqs to prevent MSC contention with SD card
uint32_t basepri = raise_irq_pri(IRQ_PRI_OTG_FS);
- dma_init(&sd_rx_dma, DMA_STREAM_SDIO_RX, &dma_init_struct_sdio,
- DMA_CHANNEL_SDIO_RX, DMA_PERIPH_TO_MEMORY, &sd_handle);
+ dma_init(&sd_rx_dma, &dma_SDIO_0_RX, &sd_handle);
sd_handle.hdmarx = &sd_rx_dma;
err = HAL_SD_ReadBlocks_BlockNumber_DMA(&sd_handle, (uint32_t*)dest, block_num, SDCARD_BLOCK_SIZE, num_blocks);
@@ -229,7 +232,7 @@ mp_uint_t sdcard_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blo
err = HAL_SD_CheckReadOperation(&sd_handle, 100000000);
}
- dma_deinit(sd_handle.hdmarx);
+ dma_deinit(&dma_SDIO_0_RX);
sd_handle.hdmarx = NULL;
restore_irq_pri(basepri);
@@ -237,15 +240,16 @@ mp_uint_t sdcard_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blo
err = HAL_SD_ReadBlocks_BlockNumber(&sd_handle, (uint32_t*)dest, block_num, SDCARD_BLOCK_SIZE, num_blocks);
}
+ if (orig_dest != NULL) {
+ // move the read data to the non-aligned position, and restore the initial bytes
+ memmove(orig_dest, dest, num_blocks * SDCARD_BLOCK_SIZE);
+ memcpy(dest, &saved_word, orig_dest - dest);
+ }
+
return err;
}
mp_uint_t sdcard_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t num_blocks) {
- // check that src pointer is aligned on a 4-byte boundary
- if (((uint32_t)src & 3) != 0) {
- return SD_ERROR;
- }
-
// check that SD card is initialised
if (sd_handle.Instance == NULL) {
return SD_ERROR;
@@ -253,12 +257,29 @@ mp_uint_t sdcard_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t n
HAL_SD_ErrorTypedef err = SD_OK;
+ // check that src pointer is aligned on a 4-byte boundary
+ if (((uint32_t)src & 3) != 0) {
+ // pointer is not aligned, so allocate a temporary block to do the write
+ uint8_t *src_aligned = m_new_maybe(uint8_t, SDCARD_BLOCK_SIZE);
+ if (src_aligned == NULL) {
+ return SD_ERROR;
+ }
+ for (size_t i = 0; i < num_blocks; ++i) {
+ memcpy(src_aligned, src + i * SDCARD_BLOCK_SIZE, SDCARD_BLOCK_SIZE);
+ err = sdcard_write_blocks(src_aligned, block_num + i, 1);
+ if (err != SD_OK) {
+ break;
+ }
+ }
+ m_del(uint8_t, src_aligned, SDCARD_BLOCK_SIZE);
+ return err;
+ }
+
if (query_irq() == IRQ_STATE_ENABLED) {
// we must disable USB irqs to prevent MSC contention with SD card
uint32_t basepri = raise_irq_pri(IRQ_PRI_OTG_FS);
- dma_init(&sd_tx_dma, DMA_STREAM_SDIO_TX, &dma_init_struct_sdio,
- DMA_CHANNEL_SDIO_TX, DMA_MEMORY_TO_PERIPH, &sd_handle);
+ dma_init(&sd_tx_dma, &dma_SDIO_0_TX, &sd_handle);
sd_handle.hdmatx = &sd_tx_dma;
err = HAL_SD_WriteBlocks_BlockNumber_DMA(&sd_handle, (uint32_t*)src, block_num, SDCARD_BLOCK_SIZE, num_blocks);
@@ -266,7 +287,7 @@ mp_uint_t sdcard_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t n
// wait for DMA transfer to finish, with a large timeout
err = HAL_SD_CheckWriteOperation(&sd_handle, 100000000);
}
- dma_deinit(sd_handle.hdmatx);
+ dma_deinit(&dma_SDIO_0_TX);
sd_handle.hdmatx = NULL;
restore_irq_pri(basepri);
diff --git a/stmhal/spi.c b/stmhal/spi.c
index 6285321a8b..387fc174c4 100644
--- a/stmhal/spi.c
+++ b/stmhal/spi.c
@@ -78,10 +78,8 @@
typedef struct _pyb_spi_obj_t {
mp_obj_base_t base;
SPI_HandleTypeDef *spi;
- DMA_Stream_TypeDef *tx_dma_stream;
- uint32_t tx_dma_channel;
- DMA_Stream_TypeDef *rx_dma_stream;
- uint32_t rx_dma_channel;
+ const dma_descr_t *tx_dma_descr;
+ const dma_descr_t *rx_dma_descr;
} pyb_spi_obj_t;
#if defined(MICROPY_HW_SPI1_SCK)
@@ -105,34 +103,34 @@ SPI_HandleTypeDef SPIHandle6 = {.Instance = NULL};
STATIC const pyb_spi_obj_t pyb_spi_obj[] = {
#if defined(MICROPY_HW_SPI1_SCK)
- {{&pyb_spi_type}, &SPIHandle1, DMA_STREAM_SPI1_TX, DMA_CHANNEL_SPI1_TX, DMA_STREAM_SPI1_RX, DMA_CHANNEL_SPI1_RX},
+ {{&pyb_spi_type}, &SPIHandle1, &dma_SPI_1_TX, &dma_SPI_1_RX},
#else
- {{&pyb_spi_type}, NULL, NULL, 0, NULL, 0},
+ {{&pyb_spi_type}, NULL, NULL, NULL},
#endif
#if defined(MICROPY_HW_SPI2_SCK)
- {{&pyb_spi_type}, &SPIHandle2, DMA_STREAM_SPI2_TX, DMA_CHANNEL_SPI2_TX, DMA_STREAM_SPI2_RX, DMA_CHANNEL_SPI2_RX},
+ {{&pyb_spi_type}, &SPIHandle2, &dma_SPI_2_TX, &dma_SPI_2_RX},
#else
- {{&pyb_spi_type}, NULL, NULL, 0, NULL, 0},
+ {{&pyb_spi_type}, NULL, NULL, NULL},
#endif
#if defined(MICROPY_HW_SPI3_SCK)
- {{&pyb_spi_type}, &SPIHandle3, DMA_STREAM_SPI3_TX, DMA_CHANNEL_SPI3_TX, DMA_STREAM_SPI3_RX, DMA_CHANNEL_SPI3_RX},
+ {{&pyb_spi_type}, &SPIHandle3, &dma_SPI_3_TX, &dma_SPI_3_RX},
#else
- {{&pyb_spi_type}, NULL, NULL, 0, NULL, 0},
+ {{&pyb_spi_type}, NULL, NULL, NULL},
#endif
#if defined(MICROPY_HW_SPI4_SCK)
- {{&pyb_spi_type}, &SPIHandle4, DMA_STREAM_SPI4_TX, DMA_CHANNEL_SPI4_TX, DMA_STREAM_SPI4_RX, DMA_CHANNEL_SPI4_RX},
+ {{&pyb_spi_type}, &SPIHandle4, &dma_SPI_4_TX, &dma_SPI_4_RX},
#else
- {{&pyb_spi_type}, NULL, NULL, 0, NULL, 0},
+ {{&pyb_spi_type}, NULL, NULL, NULL},
#endif
#if defined(MICROPY_HW_SPI5_SCK)
- {{&pyb_spi_type}, &SPIHandle5, DMA_STREAM_SPI5_TX, DMA_CHANNEL_SPI5_TX, DMA_STREAM_SPI5_RX, DMA_CHANNEL_SPI5_RX},
+ {{&pyb_spi_type}, &SPIHandle5, &dma_SPI_5_TX, &dma_SPI_5_RX},
#else
- {{&pyb_spi_type}, NULL, NULL, 0, NULL, 0},
+ {{&pyb_spi_type}, NULL, NULL, NULL},
#endif
#if defined(MICROPY_HW_SPI6_SCK)
- {{&pyb_spi_type}, &SPIHandle6, DMA_STREAM_SPI6_TX, DMA_CHANNEL_SPI6_TX, DMA_STREAM_SPI6_RX, DMA_CHANNEL_SPI6_RX},
+ {{&pyb_spi_type}, &SPIHandle6, &dma_SPI_6_TX, &dma_SPI_6_RX},
#else
- {{&pyb_spi_type}, NULL, NULL, 0, NULL, 0},
+ {{&pyb_spi_type}, NULL, NULL, NULL},
#endif
};
@@ -257,8 +255,8 @@ void spi_init(SPI_HandleTypeDef *spi, bool enable_nss_pin) {
// After calling HAL_SPI_Init() it seems that the DMA gets disconnected if
// it was previously configured. So we invalidate the DMA channel to force
// an initialisation the next time we use it.
- dma_invalidate_channel(self->tx_dma_stream, self->tx_dma_channel);
- dma_invalidate_channel(self->rx_dma_stream, self->rx_dma_channel);
+ dma_invalidate_channel(self->tx_dma_descr);
+ dma_invalidate_channel(self->rx_dma_descr);
}
void spi_deinit(SPI_HandleTypeDef *spi) {
@@ -553,14 +551,14 @@ STATIC mp_obj_t pyb_spi_send(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_
status = HAL_SPI_Transmit(self->spi, bufinfo.buf, bufinfo.len, args[1].u_int);
} else {
DMA_HandleTypeDef tx_dma;
- dma_init(&tx_dma, self->tx_dma_stream, &dma_init_struct_spi_i2c, self->tx_dma_channel, DMA_MEMORY_TO_PERIPH, self->spi);
+ dma_init(&tx_dma, self->tx_dma_descr, self->spi);
self->spi->hdmatx = &tx_dma;
self->spi->hdmarx = NULL;
status = HAL_SPI_Transmit_DMA(self->spi, bufinfo.buf, bufinfo.len);
if (status == HAL_OK) {
status = spi_wait_dma_finished(self->spi, args[1].u_int);
}
- dma_deinit(&tx_dma);
+ dma_deinit(self->tx_dma_descr);
}
if (status != HAL_OK) {
@@ -606,12 +604,12 @@ STATIC mp_obj_t pyb_spi_recv(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_
DMA_HandleTypeDef tx_dma, rx_dma;
if (self->spi->Init.Mode == SPI_MODE_MASTER) {
// in master mode the HAL actually does a TransmitReceive call
- dma_init(&tx_dma, self->tx_dma_stream, &dma_init_struct_spi_i2c, self->tx_dma_channel, DMA_MEMORY_TO_PERIPH, self->spi);
+ dma_init(&tx_dma, self->tx_dma_descr, self->spi);
self->spi->hdmatx = &tx_dma;
} else {
self->spi->hdmatx = NULL;
}
- dma_init(&rx_dma, self->rx_dma_stream, &dma_init_struct_spi_i2c, self->rx_dma_channel, DMA_PERIPH_TO_MEMORY, self->spi);
+ dma_init(&rx_dma, self->rx_dma_descr, self->spi);
self->spi->hdmarx = &rx_dma;
status = HAL_SPI_Receive_DMA(self->spi, (uint8_t*)vstr.buf, vstr.len);
@@ -619,9 +617,9 @@ STATIC mp_obj_t pyb_spi_recv(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_
status = spi_wait_dma_finished(self->spi, args[1].u_int);
}
if (self->spi->hdmatx != NULL) {
- dma_deinit(&tx_dma);
+ dma_deinit(self->tx_dma_descr);
}
- dma_deinit(&rx_dma);
+ dma_deinit(self->rx_dma_descr);
}
if (status != HAL_OK) {
@@ -701,16 +699,16 @@ STATIC mp_obj_t pyb_spi_send_recv(mp_uint_t n_args, const mp_obj_t *pos_args, mp
status = HAL_SPI_TransmitReceive(self->spi, bufinfo_send.buf, bufinfo_recv.buf, bufinfo_send.len, args[2].u_int);
} else {
DMA_HandleTypeDef tx_dma, rx_dma;
- dma_init(&tx_dma, self->tx_dma_stream, &dma_init_struct_spi_i2c, self->tx_dma_channel, DMA_MEMORY_TO_PERIPH, self->spi);
+ dma_init(&tx_dma, self->tx_dma_descr, self->spi);
self->spi->hdmatx = &tx_dma;
- dma_init(&rx_dma, self->rx_dma_stream, &dma_init_struct_spi_i2c, self->rx_dma_channel, DMA_PERIPH_TO_MEMORY, self->spi);
+ dma_init(&rx_dma, self->rx_dma_descr, self->spi);
self->spi->hdmarx = &rx_dma;
status = HAL_SPI_TransmitReceive_DMA(self->spi, bufinfo_send.buf, bufinfo_recv.buf, bufinfo_send.len);
if (status == HAL_OK) {
status = spi_wait_dma_finished(self->spi, args[2].u_int);
}
- dma_deinit(&tx_dma);
- dma_deinit(&rx_dma);
+ dma_deinit(self->tx_dma_descr);
+ dma_deinit(self->rx_dma_descr);
}
if (status != HAL_OK) {
diff --git a/stmhal/startup_stm32.S b/stmhal/startup_stm32.S
index 3c3783f7a0..25b0fdd392 100644
--- a/stmhal/startup_stm32.S
+++ b/stmhal/startup_stm32.S
@@ -44,10 +44,12 @@
*/
.syntax unified
-#if defined(MCU_SERIES_M7)
+#if defined(MCU_SERIES_F7)
.cpu cortex-m7
-#else
+#elif defined(MCU_SERIES_F4) || defined(MCU_SERIES_L4)
.cpu cortex-m4
+#else
+ #error "Unknown MCU Series"
#endif
.fpu softvfp
.thumb
@@ -164,7 +166,11 @@ g_pfnVectors:
/* External Interrupts */
.word WWDG_IRQHandler /* Window WatchDog */
+#if defined(MCU_SERIES_L4)
+ .word PVD_PVM_IRQHandler /* PVD and PVM through EXTI line detection */
+#else
.word PVD_IRQHandler /* PVD through EXTI Line detection */
+#endif
.word TAMP_STAMP_IRQHandler /* Tamper and TimeStamps through the EXTI line */
.word RTC_WKUP_IRQHandler /* RTC Wakeup through the EXTI line */
.word FLASH_IRQHandler /* FLASH */
@@ -174,6 +180,16 @@ g_pfnVectors:
.word EXTI2_IRQHandler /* EXTI Line2 */
.word EXTI3_IRQHandler /* EXTI Line3 */
.word EXTI4_IRQHandler /* EXTI Line4 */
+#if defined(MCU_SERIES_L4)
+ .word DMA1_Channel1_IRQHandler /* DMA1 Channel 1 */
+ .word DMA1_Channel2_IRQHandler /* DMA1 Channel 2 */
+ .word DMA1_Channel3_IRQHandler /* DMA1 Channel 3 */
+ .word DMA1_Channel4_IRQHandler /* DMA1 Channel 4 */
+ .word DMA1_Channel5_IRQHandler /* DMA1 Channel 5 */
+ .word DMA1_Channel6_IRQHandler /* DMA1 Channel 6 */
+ .word DMA1_Channel7_IRQHandler /* DMA1 Channel 7 */
+ .word ADC1_2_IRQHandler /* ADC1 and ADC2 */
+#else
.word DMA1_Stream0_IRQHandler /* DMA1 Stream 0 */
.word DMA1_Stream1_IRQHandler /* DMA1 Stream 1 */
.word DMA1_Stream2_IRQHandler /* DMA1 Stream 2 */
@@ -182,14 +198,21 @@ g_pfnVectors:
.word DMA1_Stream5_IRQHandler /* DMA1 Stream 5 */
.word DMA1_Stream6_IRQHandler /* DMA1 Stream 6 */
.word ADC_IRQHandler /* ADC1, ADC2 and ADC3s */
+#endif
.word CAN1_TX_IRQHandler /* CAN1 TX */
.word CAN1_RX0_IRQHandler /* CAN1 RX0 */
.word CAN1_RX1_IRQHandler /* CAN1 RX1 */
.word CAN1_SCE_IRQHandler /* CAN1 SCE */
.word EXTI9_5_IRQHandler /* External Line[9:5]s */
+#if defined(MCU_SERIES_L4)
+ .word TIM1_BRK_TIM15_IRQHandler /* TIM1 Break and TIM15 */
+ .word TIM1_UP_TIM16_IRQHandler /* TIM1 Update and TIM16 */
+ .word TIM1_TRG_COM_TIM17_IRQHandler /* TIM1 Trigger and Commutation and TIM17 */
+#else
.word TIM1_BRK_TIM9_IRQHandler /* TIM1 Break and TIM9 */
.word TIM1_UP_TIM10_IRQHandler /* TIM1 Update and TIM10 */
.word TIM1_TRG_COM_TIM11_IRQHandler /* TIM1 Trigger and Commutation and TIM11 */
+#endif
.word TIM1_CC_IRQHandler /* TIM1 Capture Compare */
.word TIM2_IRQHandler /* TIM2 */
.word TIM3_IRQHandler /* TIM3 */
@@ -205,13 +228,24 @@ g_pfnVectors:
.word USART3_IRQHandler /* USART3 */
.word EXTI15_10_IRQHandler /* External Line[15:10]s */
.word RTC_Alarm_IRQHandler /* RTC Alarm (A and B) through EXTI Line */
+#if defined(MCU_SERIES_L4)
+ .word DFSDM3_IRQHandler /* Digital filter for sigma delta modulator 3 */
+ .word TIM8_BRK_IRQHandler /* TIM8 Break */
+ .word TIM8_UP_IRQHandler /* TIM8 Update */
+ .word TIM8_TRG_COM_IRQHandler /* TIM8 Trigger and Commutation */
+#else
.word OTG_FS_WKUP_IRQHandler /* USB OTG FS Wakeup through EXTI line */
.word TIM8_BRK_TIM12_IRQHandler /* TIM8 Break and TIM12 */
.word TIM8_UP_TIM13_IRQHandler /* TIM8 Update and TIM13 */
.word TIM8_TRG_COM_TIM14_IRQHandler /* TIM8 Trigger and Commutation and TIM14 */
+#endif
.word TIM8_CC_IRQHandler /* TIM8 Capture Compare */
+#if defined(MCU_SERIES_L4)
+ .word ADC3_IRQHandler /* ADC3 global interrupt */
+#else
.word DMA1_Stream7_IRQHandler /* DMA1 Stream7 */
-#if defined(MCU_SERIES_F7)
+#endif
+#if defined(MCU_SERIES_F7) || defined(MCU_SERIES_L4)
.word FMC_IRQHandler /* FMC */
.word SDMMC1_IRQHandler /* SDMMC1 */
#else
@@ -224,6 +258,19 @@ g_pfnVectors:
.word UART5_IRQHandler /* UART5 */
.word TIM6_DAC_IRQHandler /* TIM6 and DAC1&2 underrun errors */
.word TIM7_IRQHandler /* TIM7 */
+#if defined(MCU_SERIES_L4)
+ .word DMA2_Channel1_IRQHandler /* DMA2 Channel 1 */
+ .word DMA2_Channel2_IRQHandler /* DMA2 Channel 2 */
+ .word DMA2_Channel3_IRQHandler /* DMA2 Channel 3 */
+ .word DMA2_Channel4_IRQHandler /* DMA2 Channel 4 */
+ .word DMA2_Channel5_IRQHandler /* DMA2 Channel 5 */
+ .word DFSDM0_IRQHandler /* Digital filter for sigma delta modulator 0 */
+ .word DFSDM1_IRQHandler /* Digital filter for sigma delta modulator 1 */
+ .word DFSDM2_IRQHandler /* Digital filter for sigma delta modulator 2 */
+ .word COMP_IRQHandler /* Comporator thru EXTI line */
+ .word LPTIM1_IRQHandler /* Low power timer 1 */
+ .word LPTIM2_IRQHandler /* Low power timer 2 */
+#else
.word DMA2_Stream0_IRQHandler /* DMA2 Stream 0 */
.word DMA2_Stream1_IRQHandler /* DMA2 Stream 1 */
.word DMA2_Stream2_IRQHandler /* DMA2 Stream 2 */
@@ -235,20 +282,40 @@ g_pfnVectors:
.word CAN2_RX0_IRQHandler /* CAN2 RX0 */
.word CAN2_RX1_IRQHandler /* CAN2 RX1 */
.word CAN2_SCE_IRQHandler /* CAN2 SCE */
+#endif
.word OTG_FS_IRQHandler /* USB OTG FS */
+#if defined(MCU_SERIES_L4)
+ .word DMA2_Channel6_IRQHandler /* DMA2 Channel 6 */
+ .word DMA2_Channel7_IRQHandler /* DMA2 Channel 7 */
+ .word LPUART1_IRQHandler /* Low power UART */
+ .word QUADSPI_IRQHandler /* Quad SPI */
+#else
.word DMA2_Stream5_IRQHandler /* DMA2 Stream 5 */
.word DMA2_Stream6_IRQHandler /* DMA2 Stream 6 */
.word DMA2_Stream7_IRQHandler /* DMA2 Stream 7 */
.word USART6_IRQHandler /* USART6 */
+#endif
.word I2C3_EV_IRQHandler /* I2C3 event */
.word I2C3_ER_IRQHandler /* I2C3 error */
+#if defined(MCU_SERIES_L4)
+ .word SAI1_IRQHandler /* Serial audio interface 1 */
+ .word SAI2_IRQHandler /* Serial audio interface 2 */
+ .word SWPMI1_IRQHandler /* Single wire protocole 1 */
+ .word TSC_IRQHandler /* Touch sensig controller */
+ .word LCD_IRQHandler /* LCD */
+#else
.word OTG_HS_EP1_OUT_IRQHandler /* USB OTG HS End Point 1 Out */
.word OTG_HS_EP1_IN_IRQHandler /* USB OTG HS End Point 1 In */
.word OTG_HS_WKUP_IRQHandler /* USB OTG HS Wakeup through EXTI */
.word OTG_HS_IRQHandler /* USB OTG HS */
.word DCMI_IRQHandler /* DCMI */
+#endif
.word 0 /* CRYP crypto */
+#if defined(MCU_SERIES_L4)
+ .word RNG_IRQHandler /* Random number generator */
+#else
.word HASH_RNG_IRQHandler /* Hash and Rng */
+#endif
.word FPU_IRQHandler /* FPU */
#if defined(MCU_SERIES_F7)
@@ -307,8 +374,13 @@ g_pfnVectors:
.weak WWDG_IRQHandler
.thumb_set WWDG_IRQHandler,Default_Handler
+#if defined(MCU_SERIES_L4)
+ .weak PVD_PVM_IRQHandler
+ .thumb_set PVD_PVM_IRQHandler,Default_Handler
+#else
.weak PVD_IRQHandler
.thumb_set PVD_IRQHandler,Default_Handler
+#endif
.weak TAMP_STAMP_IRQHandler
.thumb_set TAMP_STAMP_IRQHandler,Default_Handler
@@ -337,6 +409,31 @@ g_pfnVectors:
.weak EXTI4_IRQHandler
.thumb_set EXTI4_IRQHandler,Default_Handler
+#if defined(MCU_SERIES_L4)
+ .weak DMA1_Channel1_IRQHandler
+ .thumb_set DMA1_Channel1_IRQHandler,Default_Handler
+
+ .weak DMA1_Channel2_IRQHandler
+ .thumb_set DMA1_Channel2_IRQHandler,Default_Handler
+
+ .weak DMA1_Channel3_IRQHandler
+ .thumb_set DMA1_Channel3_IRQHandler,Default_Handler
+
+ .weak DMA1_Channel4_IRQHandler
+ .thumb_set DMA1_Channel4_IRQHandler,Default_Handler
+
+ .weak DMA1_Channel5_IRQHandler
+ .thumb_set DMA1_Channel5_IRQHandler,Default_Handler
+
+ .weak DMA1_Channel6_IRQHandler
+ .thumb_set DMA1_Channel6_IRQHandler,Default_Handler
+
+ .weak DMA1_Channel7_IRQHandler
+ .thumb_set DMA1_Channel7_IRQHandler,Default_Handler
+
+ .weak ADC1_2_IRQHandler
+ .thumb_set ADC1_2_IRQHandler,Default_Handler
+#else
.weak DMA1_Stream0_IRQHandler
.thumb_set DMA1_Stream0_IRQHandler,Default_Handler
@@ -360,6 +457,7 @@ g_pfnVectors:
.weak ADC_IRQHandler
.thumb_set ADC_IRQHandler,Default_Handler
+#endif
.weak CAN1_TX_IRQHandler
.thumb_set CAN1_TX_IRQHandler,Default_Handler
@@ -376,6 +474,16 @@ g_pfnVectors:
.weak EXTI9_5_IRQHandler
.thumb_set EXTI9_5_IRQHandler,Default_Handler
+#if defined(MCU_SERIES_L4)
+ .weak TIM1_BRK_TIM15_IRQHandler
+ .thumb_set TIM1_BRK_TIM15_IRQHandler,Default_Handler
+
+ .weak TIM1_UP_TIM16_IRQHandler
+ .thumb_set TIM1_UP_TIM16_IRQHandler,Default_Handler
+
+ .weak TIM1_TRG_COM_TIM17_IRQHandler
+ .thumb_set TIM1_TRG_COM_TIM17_IRQHandler,Default_Handler
+#else
.weak TIM1_BRK_TIM9_IRQHandler
.thumb_set TIM1_BRK_TIM9_IRQHandler,Default_Handler
@@ -384,6 +492,7 @@ g_pfnVectors:
.weak TIM1_TRG_COM_TIM11_IRQHandler
.thumb_set TIM1_TRG_COM_TIM11_IRQHandler,Default_Handler
+#endif
.weak TIM1_CC_IRQHandler
.thumb_set TIM1_CC_IRQHandler,Default_Handler
@@ -430,6 +539,19 @@ g_pfnVectors:
.weak RTC_Alarm_IRQHandler
.thumb_set RTC_Alarm_IRQHandler,Default_Handler
+#if defined(MCU_SERIES_L4)
+ .weak DFSDM3_IRQHandler
+ .thumb_set DFSDM3_IRQHandler,Default_Handler
+
+ .weak TIM8_BRK_IRQHandler
+ .thumb_set TIM8_BRK_IRQHandler,Default_Handler
+
+ .weak TIM8_UP_IRQHandler
+ .thumb_set TIM8_UP_IRQHandler,Default_Handler
+
+ .weak TIM8_TRG_COM_IRQHandler
+ .thumb_set TIM8_TRG_COM_IRQHandler,Default_Handler
+#else
.weak OTG_FS_WKUP_IRQHandler
.thumb_set OTG_FS_WKUP_IRQHandler,Default_Handler
@@ -441,14 +563,20 @@ g_pfnVectors:
.weak TIM8_TRG_COM_TIM14_IRQHandler
.thumb_set TIM8_TRG_COM_TIM14_IRQHandler,Default_Handler
+#endif
.weak TIM8_CC_IRQHandler
.thumb_set TIM8_CC_IRQHandler,Default_Handler
+#if defined(MCU_SERIES_L4)
+ .weak ADC3_IRQHandler
+ .thumb_set ADC3_IRQHandler,Default_Handler
+#else
.weak DMA1_Stream7_IRQHandler
.thumb_set DMA1_Stream7_IRQHandler,Default_Handler
+#endif
-#if defined(MCU_SERIES_F7)
+#if defined(MCU_SERIES_F7) || defined(MCU_SERIES_L4)
.weak FMC_IRQHandler
.thumb_set FMC_IRQHandler,Default_Handler
@@ -480,6 +608,40 @@ g_pfnVectors:
.weak TIM7_IRQHandler
.thumb_set TIM7_IRQHandler,Default_Handler
+#if defined(MCU_SERIES_L4)
+ .weak DMA2_Channel1_IRQHandler
+ .thumb_set DMA2_Channel1_IRQHandler,Default_Handler
+
+ .weak DMA2_Channel2_IRQHandler
+ .thumb_set DMA2_Channel2_IRQHandler,Default_Handler
+
+ .weak DMA2_Channel3_IRQHandler
+ .thumb_set DMA2_Channel3_IRQHandler,Default_Handler
+
+ .weak DMA2_Channel4_IRQHandler
+ .thumb_set DMA2_Channel4_IRQHandler,Default_Handler
+
+ .weak DMA2_Channel5_IRQHandler
+ .thumb_set DMA2_Channel5_IRQHandler,Default_Handler
+
+ .weak DFSDM0_IRQHandler
+ .thumb_set DFSDM0_IRQHandler,Default_Handler
+
+ .weak DFSDM1_IRQHandler
+ .thumb_set DFSDM1_IRQHandler,Default_Handler
+
+ .weak DFSDM2_IRQHandler
+ .thumb_set DFSDM2_IRQHandler,Default_Handler
+
+ .weak COMP_IRQHandler
+ .thumb_set COMP_IRQHandler,Default_Handler
+
+ .weak LPTIM1_IRQHandler
+ .thumb_set LPTIM1_IRQHandler,Default_Handler
+
+ .weak LPTIM2_IRQHandler
+ .thumb_set LPTIM2_IRQHandler,Default_Handler
+#else
.weak DMA2_Stream0_IRQHandler
.thumb_set DMA2_Stream0_IRQHandler,Default_Handler
@@ -512,10 +674,24 @@ g_pfnVectors:
.weak CAN2_SCE_IRQHandler
.thumb_set CAN2_SCE_IRQHandler,Default_Handler
+#endif
.weak OTG_FS_IRQHandler
.thumb_set OTG_FS_IRQHandler,Default_Handler
+#if defined(MCU_SERIES_L4)
+ .weak DMA2_Channel6_IRQHandler
+ .thumb_set DMA2_Channel6_IRQHandler,Default_Handler
+
+ .weak DMA2_Channel7_IRQHandler
+ .thumb_set DMA2_Channel7_IRQHandler,Default_Handler
+
+ .weak LPUART1_IRQHandler
+ .thumb_set LPUART1_IRQHandler,Default_Handler
+
+ .weak QUADSPI_IRQHandler
+ .thumb_set QUADSPI_IRQHandler,Default_Handler
+#else
.weak DMA2_Stream5_IRQHandler
.thumb_set DMA2_Stream5_IRQHandler,Default_Handler
@@ -527,6 +703,7 @@ g_pfnVectors:
.weak USART6_IRQHandler
.thumb_set USART6_IRQHandler,Default_Handler
+#endif
.weak I2C3_EV_IRQHandler
.thumb_set I2C3_EV_IRQHandler,Default_Handler
@@ -534,6 +711,25 @@ g_pfnVectors:
.weak I2C3_ER_IRQHandler
.thumb_set I2C3_ER_IRQHandler,Default_Handler
+#if defined(MCU_SERIES_L4)
+ .weak SAI1_IRQHandler
+ .thumb_set SAI1_IRQHandler,Default_Handler
+
+ .weak SAI2_IRQHandler
+ .thumb_set SAI2_IRQHandler,Default_Handler
+
+ .weak SWPMI1_IRQHandler
+ .thumb_set SWPMI1_IRQHandler,Default_Handler
+
+ .weak TSC_IRQHandler
+ .thumb_set TSC_IRQHandler,Default_Handler
+
+ .weak LCD_IRQHandler
+ .thumb_set LCD_IRQHandler,Default_Handler
+
+ .weak RNG_IRQHandler
+ .thumb_set RNG_IRQHandler,Default_Handler
+#else
.weak OTG_HS_EP1_OUT_IRQHandler
.thumb_set OTG_HS_EP1_OUT_IRQHandler,Default_Handler
@@ -551,6 +747,7 @@ g_pfnVectors:
.weak HASH_RNG_IRQHandler
.thumb_set HASH_RNG_IRQHandler,Default_Handler
+#endif
.weak FPU_IRQHandler
.thumb_set FPU_IRQHandler,Default_Handler
diff --git a/stmhal/stm32_it.c b/stmhal/stm32_it.c
index 4d3ffdffe2..c9af20ce58 100644
--- a/stmhal/stm32_it.c
+++ b/stmhal/stm32_it.c
@@ -477,6 +477,14 @@ void PVD_IRQHandler(void) {
IRQ_EXIT(PVD_IRQn);
}
+#if defined(MCU_SERIES_L4)
+void PVD_PVM_IRQHandler(void) {
+ IRQ_ENTER(PVD_PVM_IRQn);
+ Handle_EXTI_Irq(EXTI_PVD_OUTPUT);
+ IRQ_EXIT(PVD_PVM_IRQn);
+}
+#endif
+
void RTC_Alarm_IRQHandler(void) {
IRQ_ENTER(RTC_Alarm_IRQn);
Handle_EXTI_Irq(EXTI_RTC_ALARM);
@@ -510,6 +518,14 @@ void TIM1_BRK_TIM9_IRQHandler(void) {
IRQ_EXIT(TIM1_BRK_TIM9_IRQn);
}
+#if defined(MCU_SERIES_L4)
+void TIM1_BRK_TIM15_IRQHandler(void) {
+ IRQ_ENTER(TIM1_BRK_TIM15_IRQn);
+ timer_irq_handler(15);
+ IRQ_EXIT(TIM1_BRK_TIM15_IRQn);
+}
+#endif
+
void TIM1_UP_TIM10_IRQHandler(void) {
IRQ_ENTER(TIM1_UP_TIM10_IRQn);
timer_irq_handler(1);
@@ -517,12 +533,29 @@ void TIM1_UP_TIM10_IRQHandler(void) {
IRQ_EXIT(TIM1_UP_TIM10_IRQn);
}
+#if defined(MCU_SERIES_L4)
+void TIM1_UP_TIM16_IRQHandler(void) {
+ IRQ_ENTER(TIM1_UP_TIM16_IRQn);
+ timer_irq_handler(1);
+ timer_irq_handler(16);
+ IRQ_EXIT(TIM1_UP_TIM16_IRQn);
+}
+#endif
+
void TIM1_TRG_COM_TIM11_IRQHandler(void) {
IRQ_ENTER(TIM1_TRG_COM_TIM11_IRQn);
timer_irq_handler(11);
IRQ_EXIT(TIM1_TRG_COM_TIM11_IRQn);
}
+#if defined(MCU_SERIES_L4)
+void TIM1_TRG_COM_TIM17_IRQHandler(void) {
+ IRQ_ENTER(TIM1_TRG_COM_TIM17_IRQn);
+ timer_irq_handler(17);
+ IRQ_EXIT(TIM1_TRG_COM_TIM17_IRQn);
+}
+#endif
+
void TIM2_IRQHandler(void) {
IRQ_ENTER(TIM2_IRQn);
timer_irq_handler(2);
@@ -573,6 +606,14 @@ void TIM8_UP_TIM13_IRQHandler(void) {
IRQ_EXIT(TIM8_UP_TIM13_IRQn);
}
+#if defined(MCU_SERIES_L4)
+void TIM8_UP_IRQHandler(void) {
+ IRQ_ENTER(TIM8_UP_IRQn);
+ timer_irq_handler(8);
+ IRQ_EXIT(TIM8_UP_IRQn);
+}
+#endif
+
void TIM8_TRG_COM_TIM14_IRQHandler(void) {
IRQ_ENTER(TIM8_TRG_COM_TIM14_IRQn);
timer_irq_handler(14);
diff --git a/stmhal/system_stm32.c b/stmhal/system_stm32.c
index e286a15725..96caa7d36d 100644
--- a/stmhal/system_stm32.c
+++ b/stmhal/system_stm32.c
@@ -108,6 +108,30 @@ void __fatal_error(const char *msg);
* @{
*/
+#if defined(MCU_SERIES_F4) || defined(MCU_SERIES_F7)
+
+#define CONFIG_RCC_CR_1ST (RCC_CR_HSION)
+#define CONFIG_RCC_CR_2ND (RCC_CR_HSEON || RCC_CR_CSSON || RCC_CR_PLLON)
+#define CONFIG_RCC_PLLCFGR (0x24003010)
+
+#elif defined(MCU_SERIES_L4)
+
+#define CONFIG_RCC_CR_1ST (RCC_CR_MSION)
+#define CONFIG_RCC_CR_2ND (RCC_CR_HSEON || RCC_CR_CSSON || RCC_CR_HSION || RCC_CR_PLLON)
+#define CONFIG_RCC_PLLCFGR (0x00001000)
+/*
+ * FIXME Do not know why I have to define these arrays here! they should be defined in the
+ * hal_rcc-file!!
+ *
+ */
+const uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
+const uint8_t APBPrescTable[8] = {0, 0, 0, 0, 1, 2, 3, 4};
+const uint32_t MSIRangeTable[12] = {100000, 200000, 400000, 800000, 1000000, 2000000, \
+ 4000000, 8000000, 16000000, 24000000, 32000000, 48000000};
+#else
+#error Unknown processor
+#endif
+
/************************* Miscellaneous Configuration ************************/
/*!< Uncomment the following line if you need to relocate your vector Table in
@@ -172,23 +196,28 @@ void SystemInit(void)
SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */
#endif
/* Reset the RCC clock configuration to the default reset state ------------*/
+
/* Set HSION bit */
- RCC->CR |= (uint32_t)0x00000001;
+ RCC->CR |= CONFIG_RCC_CR_1ST;
/* Reset CFGR register */
RCC->CFGR = 0x00000000;
/* Reset HSEON, CSSON and PLLON bits */
- RCC->CR &= (uint32_t)0xFEF6FFFF;
+ RCC->CR &= ~ CONFIG_RCC_CR_2ND;
/* Reset PLLCFGR register */
- RCC->PLLCFGR = 0x24003010;
+ RCC->PLLCFGR = CONFIG_RCC_PLLCFGR;
/* Reset HSEBYP bit */
RCC->CR &= (uint32_t)0xFFFBFFFF;
/* Disable all interrupts */
+ #if defined(MCU_SERIES_F4) || defined(MCU_SERIES_F7)
RCC->CIR = 0x00000000;
+ #elif defined(MCU_SERIES_L4)
+ RCC->CIER = 0x00000000;
+ #endif
/* Configure the Vector Table location add offset address ------------------*/
#ifdef VECT_TAB_SRAM
@@ -204,7 +233,8 @@ void SystemInit(void)
/**
* @brief System Clock Configuration
- * The system Clock is configured as follow :
+ *
+ * The system Clock is configured for F4/F7 as follows:
* System Clock source = PLL (HSE)
* SYSCLK(Hz) = 168000000
* HCLK(Hz) = 168000000
@@ -219,15 +249,39 @@ void SystemInit(void)
* VDD(V) = 3.3
* Main regulator output voltage = Scale1 mode
* Flash Latency(WS) = 5
+ *
+ * The system Clock is configured for L4 as follows:
+ * System Clock source = PLL (MSI)
+ * SYSCLK(Hz) = 80000000
+ * HCLK(Hz) = 80000000
+ * AHB Prescaler = 1
+ * APB1 Prescaler = 1
+ * APB2 Prescaler = 1
+ * MSI Frequency(Hz) = MSI_VALUE (4000000)
+ * LSE Frequency(Hz) = 32768
+ * PLL_M = 1
+ * PLL_N = 40
+ * PLL_P = 7
+ * PLL_Q = 2
+ * PLL_R = 2 <= This is the source for SysClk, not as on F4/7 PLL_P
+ * Flash Latency(WS) = 4
* @param None
* @retval None
*
* PLL is configured as follows:
*
- * VCO_IN = HSE / M
- * VCO_OUT = HSE / M * N
- * PLLCLK = HSE / M * N / P
- * PLL48CK = HSE / M * N / Q
+ * VCO_IN
+ * F4/F7 = HSE / M
+ * L4 = MSI / M
+ * VCO_OUT
+ * F4/F7 = HSE / M * N
+ * L4 = MSI / M * N
+ * PLLCLK
+ * F4/F7 = HSE / M * N / P
+ * L4 = MSI / M * N / R
+ * PLL48CK
+ * F4/F7 = HSE / M * N / Q
+ * L4 = MSI / M * N / Q USB Clock is obtained over PLLSAI1
*
* SYSCLK = PLLCLK
* HCLK = SYSCLK / AHB_PRESC
@@ -261,6 +315,7 @@ void SystemClock_Config(void)
RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_OscInitTypeDef RCC_OscInitStruct;
+ #if defined(MCU_SERIES_F4) || defined(MCU_SERIES_F7)
/* Enable Power Control clock */
__PWR_CLK_ENABLE();
@@ -268,12 +323,29 @@ void SystemClock_Config(void)
clocked below the maximum system frequency, to update the voltage scaling value
regarding system frequency refer to product datasheet. */
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
+ #elif defined(MCU_SERIES_L4)
+ /* Enable the LSE Oscillator */
+ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE;
+ RCC_OscInitStruct.LSEState = RCC_LSE_ON;
+ if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
+ __fatal_error("HAL_RCC_OscConfig");
+ }
+ #endif
/* Enable HSE Oscillator and activate PLL with HSE as source */
+ #if defined(MCU_SERIES_F4) || defined(MCU_SERIES_F7)
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
- RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
+ #elif defined(MCU_SERIES_L4)
+ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE|RCC_OSCILLATORTYPE_MSI;
+ RCC_OscInitStruct.LSEState = RCC_LSE_ON;
+ RCC_OscInitStruct.MSIState = RCC_MSI_ON;
+ RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT;
+ RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_6;
+ RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_MSI;
+ #endif
+ RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
/* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2
clocks dividers */
RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
@@ -282,6 +354,8 @@ void SystemClock_Config(void)
#if defined(MICROPY_HW_CLK_LAST_FREQ) && MICROPY_HW_CLK_LAST_FREQ
#if defined(MCU_SERIES_F7)
#define FREQ_BKP BKP31R
+ #elif defined(MCU_SERIES_L4)
+ #error Unsupported Processor
#else
#define FREQ_BKP BKP19R
#endif
@@ -319,15 +393,23 @@ void SystemClock_Config(void)
RCC_ClkInitStruct.AHBCLKDivider = h; //RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = b1; //RCC_HCLK_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = b2; //RCC_HCLK_DIV2;
-#else
+#else // defined(MICROPY_HW_CLK_LAST_FREQ) && MICROPY_HW_CLK_LAST_FREQ
RCC_OscInitStruct.PLL.PLLM = MICROPY_HW_CLK_PLLM;
RCC_OscInitStruct.PLL.PLLN = MICROPY_HW_CLK_PLLN;
RCC_OscInitStruct.PLL.PLLP = MICROPY_HW_CLK_PLLP;
RCC_OscInitStruct.PLL.PLLQ = MICROPY_HW_CLK_PLLQ;
+ #if defined(MCU_SERIES_L4)
+ RCC_OscInitStruct.PLL.PLLR = MICROPY_HW_CLK_PLLR;
+ #endif
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
+ #if defined(MCU_SERIES_F4) || defined(MCU_SERIES_F7)
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
+ #elif defined(MCU_SERIES_L4)
+ RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
+ RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
+ #endif
#endif
if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
@@ -358,6 +440,44 @@ void SystemClock_Config(void)
RCC->DCKCFGR2 = 0;
#endif
+#if defined(MCU_SERIES_L4)
+ // Enable MSI-Hardware auto calibration mode with LSE
+ HAL_RCCEx_EnableMSIPLLMode();
+
+ RCC_PeriphCLKInitTypeDef PeriphClkInitStruct;
+ PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SAI1|RCC_PERIPHCLK_I2C1
+ |RCC_PERIPHCLK_USB |RCC_PERIPHCLK_ADC
+ |RCC_PERIPHCLK_RNG |RCC_PERIPHCLK_RTC;
+ PeriphClkInitStruct.I2c1ClockSelection = RCC_I2C1CLKSOURCE_PCLK1;
+ /* PLLSAI is used to clock USB, ADC, I2C1 and RNG. The frequency is
+ HSE(8MHz)/PLLM(2)*PLLSAI1N(24)/PLLSAIQ(2) = 48MHz. See the STM32CubeMx
+ application or the reference manual. */
+ PeriphClkInitStruct.Sai1ClockSelection = RCC_SAI1CLKSOURCE_PLLSAI1;
+ PeriphClkInitStruct.AdcClockSelection = RCC_ADCCLKSOURCE_PLLSAI1;
+ PeriphClkInitStruct.UsbClockSelection = RCC_USBCLKSOURCE_PLLSAI1;
+ PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
+ PeriphClkInitStruct.RngClockSelection = RCC_RNGCLKSOURCE_PLLSAI1;
+ PeriphClkInitStruct.PLLSAI1.PLLSAI1N = 24;
+ PeriphClkInitStruct.PLLSAI1.PLLSAI1P = RCC_PLLP_DIV7;
+ PeriphClkInitStruct.PLLSAI1.PLLSAI1Q = RCC_PLLQ_DIV2;
+ PeriphClkInitStruct.PLLSAI1.PLLSAI1R = RCC_PLLR_DIV2;
+ PeriphClkInitStruct.PLLSAI1.PLLSAI1ClockOut = RCC_PLLSAI1_SAI1CLK
+ |RCC_PLLSAI1_48M2CLK
+ |RCC_PLLSAI1_ADC1CLK;
+
+ if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
+ {
+ __fatal_error("HAL_RCCEx_PeriphCLKConfig");
+ }
+
+ __PWR_CLK_ENABLE();
+
+ HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);
+
+ HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);
+
+ HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
+#endif
}
void HAL_MspInit(void) {
diff --git a/stmhal/uart.c b/stmhal/uart.c
index 108236ca1a..210330e81a 100644
--- a/stmhal/uart.c
+++ b/stmhal/uart.c
@@ -27,11 +27,11 @@
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
-#include <errno.h>
#include "py/nlr.h"
#include "py/runtime.h"
#include "py/stream.h"
+#include "py/mperrno.h"
#include "py/mphal.h"
#include "uart.h"
#include "pybioctl.h"
@@ -579,11 +579,7 @@ STATIC mp_obj_t pyb_uart_init_helper(pyb_uart_obj_t *self, mp_uint_t n_args, con
} else {
actual_baudrate = HAL_RCC_GetPCLK1Freq();
}
- #if defined(MCU_SERIES_L4)
- actual_baudrate = (actual_baudrate << 5) / (self->uart.Instance->BRR >> 3);
- #else
actual_baudrate /= self->uart.Instance->BRR;
- #endif
// check we could set the baudrate within 5%
uint32_t baudrate_diff;
@@ -829,7 +825,7 @@ STATIC mp_uint_t pyb_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t size, i
// check that size is a multiple of character width
if (size & self->char_width) {
- *errcode = EIO;
+ *errcode = MP_EIO;
return MP_STREAM_ERROR;
}
@@ -844,7 +840,7 @@ STATIC mp_uint_t pyb_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t size, i
// wait for first char to become available
if (!uart_rx_wait(self, self->timeout)) {
// return EAGAIN error to indicate non-blocking (then read() method returns None)
- *errcode = EAGAIN;
+ *errcode = MP_EAGAIN;
return MP_STREAM_ERROR;
}
@@ -871,13 +867,13 @@ STATIC mp_uint_t pyb_uart_write(mp_obj_t self_in, const void *buf_in, mp_uint_t
// check that size is a multiple of character width
if (size & self->char_width) {
- *errcode = EIO;
+ *errcode = MP_EIO;
return MP_STREAM_ERROR;
}
// wait to be able to write the first character. EAGAIN causes write to return None
if (!uart_tx_wait(self, self->timeout)) {
- *errcode = EAGAIN;
+ *errcode = MP_EAGAIN;
return MP_STREAM_ERROR;
}
@@ -917,7 +913,7 @@ STATIC mp_uint_t pyb_uart_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_t a
ret |= MP_IOCTL_POLL_WR;
}
} else {
- *errcode = EINVAL;
+ *errcode = MP_EINVAL;
ret = MP_STREAM_ERROR;
}
return ret;
diff --git a/stmhal/usb.c b/stmhal/usb.c
index 1e1469c564..b786fb7584 100644
--- a/stmhal/usb.c
+++ b/stmhal/usb.c
@@ -26,7 +26,6 @@
#include <stdarg.h>
#include <string.h>
-#include <errno.h>
#include "usbd_core.h"
#include "usbd_desc.h"
@@ -37,6 +36,7 @@
#include "py/objstr.h"
#include "py/runtime.h"
#include "py/stream.h"
+#include "py/mperrno.h"
#include "bufhelper.h"
#include "usb.h"
#include "pybioctl.h"
@@ -483,7 +483,7 @@ STATIC mp_uint_t pyb_usb_vcp_read(mp_obj_t self_in, void *buf, mp_uint_t size, i
int ret = USBD_CDC_Rx((byte*)buf, size, 0);
if (ret == 0) {
// return EAGAIN error to indicate non-blocking
- *errcode = EAGAIN;
+ *errcode = MP_EAGAIN;
return MP_STREAM_ERROR;
}
return ret;
@@ -493,7 +493,7 @@ STATIC mp_uint_t pyb_usb_vcp_write(mp_obj_t self_in, const void *buf, mp_uint_t
int ret = USBD_CDC_Tx((const byte*)buf, size, 0);
if (ret == 0) {
// return EAGAIN error to indicate non-blocking
- *errcode = EAGAIN;
+ *errcode = MP_EAGAIN;
return MP_STREAM_ERROR;
}
return ret;
@@ -511,7 +511,7 @@ STATIC mp_uint_t pyb_usb_vcp_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_
ret |= MP_IOCTL_POLL_WR;
}
} else {
- *errcode = EINVAL;
+ *errcode = MP_EINVAL;
ret = MP_STREAM_ERROR;
}
return ret;
@@ -600,7 +600,7 @@ STATIC mp_uint_t pyb_usb_hid_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_
ret |= MP_IOCTL_POLL_WR;
}
} else {
- *errcode = EINVAL;
+ *errcode = MP_EINVAL;
ret = MP_STREAM_ERROR;
}
return ret;