diff --git a/boards/arduino/opta/CMakeLists.txt b/boards/arduino/opta/CMakeLists.txt new file mode 100644 index 00000000000..c4483abeb70 --- /dev/null +++ b/boards/arduino/opta/CMakeLists.txt @@ -0,0 +1,4 @@ +# Copyright (c) 2021 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +zephyr_sources(board_gpio_hse.c) diff --git a/boards/arduino/opta/Kconfig.arduino_opta b/boards/arduino/opta/Kconfig.arduino_opta index d591283a6ff..c9805a38100 100644 --- a/boards/arduino/opta/Kconfig.arduino_opta +++ b/boards/arduino/opta/Kconfig.arduino_opta @@ -1,5 +1,7 @@ # Copyright (c) 2023 Felipe Neves +# Copyright (c) 2024 DNDG srl # SPDX-License-Identifier: Apache-2.0 config BOARD_ARDUINO_OPTA - select SOC_STM32H747XX_M4 + select SOC_STM32H747XX_M4 if BOARD_ARDUINO_OPTA_STM32H747XX_M4 + select SOC_STM32H747XX_M7 if BOARD_ARDUINO_OPTA_STM32H747XX_M7 diff --git a/boards/arduino/opta/Kconfig.defconfig b/boards/arduino/opta/Kconfig.defconfig new file mode 100644 index 00000000000..f851c3d1047 --- /dev/null +++ b/boards/arduino/opta/Kconfig.defconfig @@ -0,0 +1,37 @@ +# Copyright 2024 Rahul Arasikere +# Copyright 2024 DNDG srl +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_ARDUINO_OPTA + +if USB_DEVICE_STACK + +config USB_DEVICE_PRODUCT + default "Arduino Opta" + +config USB_DEVICE_PID + default 0x0164 + +config USB_DEVICE_VID + default 0x35d1 + +config USB_DEVICE_INITIALIZE_AT_BOOT + default y + +if LOG + +# Logger cannot use itself to log +choice USB_CDC_ACM_LOG_LEVEL_CHOICE + default USB_CDC_ACM_LOG_LEVEL_OFF +endchoice + +# Set USB log level to error only +choice USB_DEVICE_LOG_LEVEL_CHOICE + default USB_DEVICE_LOG_LEVEL_ERR +endchoice + +endif # LOG + +endif # USB_DEVICE_STACK + +endif # BOARD_ARDUINO_OPTA diff --git a/boards/arduino/opta/arduino_opta-common.dtsi b/boards/arduino/opta/arduino_opta-common.dtsi new file mode 100644 index 00000000000..dcf957265c4 --- /dev/null +++ b/boards/arduino/opta/arduino_opta-common.dtsi @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2023 Felipe Neves + * Copyright (c) 2024 DNDG srl + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + leds { + compatible = "gpio-leds"; + + status_led_1: led_1 { + gpios = <&gpioi 0 GPIO_ACTIVE_HIGH>; + }; + status_led_2: led_2 { + gpios = <&gpioi 1 GPIO_ACTIVE_HIGH>; + }; + status_led_3: led_3 { + gpios = <&gpioi 3 GPIO_ACTIVE_HIGH>; + }; + status_led_4: led_4 { + gpios = <&gpioh 15 GPIO_ACTIVE_HIGH>; + }; + led_reset: led_g { + gpios = <&gpioh 12 GPIO_ACTIVE_HIGH>; + }; + led_reset_red: led_r { + gpios = <&gpioh 11 GPIO_ACTIVE_HIGH>; + }; + led_user: led_b { + gpios = <&gpioe 5 GPIO_ACTIVE_HIGH>; + }; + }; + + relays { + compatible = "gpio-power-switches"; + + output_d0: d0 { + gpios = <&gpioi 6 GPIO_ACTIVE_HIGH>; + }; + output_d1: d1 { + gpios = <&gpioi 5 GPIO_ACTIVE_HIGH>; + }; + output_d2: d2 { + gpios = <&gpioi 7 GPIO_ACTIVE_HIGH>; + }; + output_d3: d3 { + gpios = <&gpioi 4 GPIO_ACTIVE_HIGH>; + }; + }; + + gpio_keys { + compatible = "gpio-keys"; + + user_button: button { + gpios = <&gpioe 4 GPIO_ACTIVE_HIGH>; + zephyr,code = ; + }; + }; + + aliases { + sw0 = &user_button; + led0 = &status_led_1; + led1 = &status_led_2; + led2 = &status_led_3; + led3 = &status_led_4; + relay1 = &output_d0; + relay2 = &output_d1; + relay3 = &output_d2; + relay4 = &output_d3; + }; +}; + +&rcc { + d1cpre = <1>; + hpre = <2>; + d1ppre = <2>; + d2ppre1 = <2>; + d2ppre2 = <2>; + d3ppre = <2>; +}; + +&rtc { + status = "okay"; +}; + +&mailbox { + status = "okay"; +}; diff --git a/boards/arduino/opta/arduino_opta_stm32h747xx_m4.dts b/boards/arduino/opta/arduino_opta_stm32h747xx_m4.dts index bc74a2691f4..e2825752ddc 100644 --- a/boards/arduino/opta/arduino_opta_stm32h747xx_m4.dts +++ b/boards/arduino/opta/arduino_opta_stm32h747xx_m4.dts @@ -1,5 +1,6 @@ /* * Copyright (c) 2023 Felipe Neves + * Copyright (c) 2024 DNDG srl * * SPDX-License-Identifier: Apache-2.0 */ @@ -8,6 +9,7 @@ #include #include #include +#include "arduino_opta-common.dtsi" / { model = "Arduino OPTA M4 core Programmable Logic Controller"; @@ -18,36 +20,6 @@ zephyr,flash = &flash1; zephyr,code-partition = &slot0_partition; }; - - leds { - compatible = "gpio-leds"; - status_led_1: led_1 { - gpios = <&gpioi 0 GPIO_ACTIVE_LOW>; - }; - status_led_2: led_2 { - gpios = <&gpioi 1 GPIO_ACTIVE_LOW>; - }; - status_led_3: led_3 { - gpios = <&gpioi 3 GPIO_ACTIVE_LOW>; - }; - status_led_4: led_4 { - gpios = <&gpioh 15 GPIO_ACTIVE_LOW>; - }; - }; - - gpio_keys { - compatible = "gpio-keys"; - - user_button: button { - gpios = <&gpioe 4 GPIO_ACTIVE_HIGH>; - zephyr,code = ; - }; - }; - - aliases { - sw0 = &user_button; - led0 = &status_led_1; - }; }; &flash1 { @@ -64,11 +36,5 @@ }; &rcc { - d1cpre = <1>; - hpre = <2>; - d1ppre = <2>; - d2ppre1 = <2>; - d2ppre2 = <2>; - d3ppre = <2>; clock-frequency = ; }; diff --git a/boards/arduino/opta/arduino_opta_stm32h747xx_m4_defconfig b/boards/arduino/opta/arduino_opta_stm32h747xx_m4_defconfig index 629065e0ce0..40a10607fec 100644 --- a/boards/arduino/opta/arduino_opta_stm32h747xx_m4_defconfig +++ b/boards/arduino/opta/arduino_opta_stm32h747xx_m4_defconfig @@ -1,10 +1,10 @@ # Copyright (c) 2023 Felipe Neves # SPDX-License-Identifier: Apache-2.0 -# enable GPIO +# Enable GPIO CONFIG_GPIO=y -# clock configuration +# Clock configuration CONFIG_CLOCK_CONTROL=y # Enable MPU @@ -13,6 +13,5 @@ CONFIG_ARM_MPU=y # Enable HW stack protection CONFIG_HW_STACK_PROTECTION=y - # Use zephyr,code-partition as flash offset CONFIG_USE_DT_CODE_PARTITION=y diff --git a/boards/arduino/opta/arduino_opta_stm32h747xx_m7.dts b/boards/arduino/opta/arduino_opta_stm32h747xx_m7.dts new file mode 100644 index 00000000000..6f4fccb7024 --- /dev/null +++ b/boards/arduino/opta/arduino_opta_stm32h747xx_m7.dts @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2022 Benjamin Björnsson . + * Copyright (c) 2024 DNDG srl + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include +#include +#include +#include "arduino_opta-common.dtsi" + +/ { + model = "Arduino OPTA M7 core Programmable Logic Controller"; + compatible = "arduino,opta-m7"; + + chosen { + zephyr,console = &cdc_acm_uart0; + zephyr,sram = &sram0; + zephyr,flash = &flash0; + zephyr,code-partition = &slot0_partition; + }; +}; + +zephyr_udc0: &usbotg_fs { + pinctrl-0 = <&usb_otg_fs_dm_pa11 &usb_otg_fs_dp_pa12>; + pinctrl-names = "default"; + status = "okay"; + + cdc_acm_uart0: cdc_acm_uart0 { + compatible = "zephyr,cdc-acm-uart"; + }; +}; + +&clk_hse { + clock-frequency = ; + hse-bypass; + status = "okay"; +}; + +&clk_lse { + clock-frequency = <32768>; + lse-bypass; + status = "okay"; +}; + +&clk_hsi { + hsi-div = <1>; + status = "okay"; +}; + +&clk_hsi48 { + /* HSI48 required for USB */ + status = "okay"; +}; + +&pll { + div-m = <5>; + mul-n = <160>; + div-p = <2>; + div-r = <2>; + div-q = <10>; + clocks = <&clk_hse>; + status = "okay"; +}; + +&rcc { + clocks = <&pll>; + clock-frequency = ; +}; + +&flash0 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + slot0_partition: partition@40000 { + label = "image-0"; + reg = <0x00040000 DT_SIZE_K(768)>; + }; + }; +}; + +&usbotg_fs { + status = "okay"; +}; + +&usbotg_hs { + status = "disabled"; +}; + +&mac { + pinctrl-0 = < + ð_ref_clk_pa1 + ð_mdio_pa2 + ð_crs_dv_pa7 + ð_mdc_pc1 + ð_rxd0_pc4 + ð_rxd1_pc5 + ð_tx_en_pg11 + ð_txd1_pg12 + ð_txd0_pg13 + >; + pinctrl-names = "default"; +}; diff --git a/boards/arduino/opta/arduino_opta_stm32h747xx_m7.yaml b/boards/arduino/opta/arduino_opta_stm32h747xx_m7.yaml new file mode 100644 index 00000000000..e833d16f2ca --- /dev/null +++ b/boards/arduino/opta/arduino_opta_stm32h747xx_m7.yaml @@ -0,0 +1,21 @@ +identifier: arduino_opta/stm32h747xx/m7 +name: ARDUINO OPTA (M7) +type: mcu +arch: arm +toolchain: + - zephyr + - gnuarmemb + - xtools +ram: 512 +flash: 768 +supported: + - gpio +testing: + ignore_tags: + - mpu + - nfc + - net + - flash + - input + - mcumgr +vendor: arduino diff --git a/boards/arduino/opta/arduino_opta_stm32h747xx_m7_defconfig b/boards/arduino/opta/arduino_opta_stm32h747xx_m7_defconfig new file mode 100644 index 00000000000..dcb6d1edc87 --- /dev/null +++ b/boards/arduino/opta/arduino_opta_stm32h747xx_m7_defconfig @@ -0,0 +1,33 @@ +# Copyright (c) 2023 Felipe Neves +# Copyright (c) 2024 DNDG srl +# SPDX-License-Identifier: Apache-2.0 + +# Enable GPIO +CONFIG_GPIO=y + +# Clock configuration +CONFIG_CLOCK_CONTROL=y + +# Enable MPU +CONFIG_ARM_MPU=y + +# Enable HW stack protection +CONFIG_HW_STACK_PROTECTION=y + +# Use zephyr,code-partition as flash offset +CONFIG_USE_DT_CODE_PARTITION=y + +# Enable correct power supply +CONFIG_POWER_SUPPLY_SMPS_1V8_SUPPLIES_EXT_AND_LDO=y + +# Don't start M4 during the M7 boot (this is what the original Opta does) +CONFIG_STM32H7_BOOT_M4_AT_INIT=n + +# Enable console +CONFIG_SERIAL=y +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y +CONFIG_UART_LINE_CTRL=y + +# Enable USB Stack (needed for the console to work) +CONFIG_USB_DEVICE_STACK=y diff --git a/boards/arduino/opta/board.cmake b/boards/arduino/opta/board.cmake index 029ae806f4d..af211e0e775 100644 --- a/boards/arduino/opta/board.cmake +++ b/boards/arduino/opta/board.cmake @@ -2,4 +2,17 @@ board_runner_args(dfu-util "--pid=2341:0364" "--alt=0" "--dfuse") +if(CONFIG_BOARD_ARDUINO_OPTA_STM32H747XX_M7) + board_runner_args(openocd "--config=${BOARD_DIR}/support/openocd_opta_stm32h747xx_m7.cfg") + board_runner_args(openocd --target-handle=_CHIPNAME.cpu0) +elseif(CONFIG_BOARD_ARDUINO_OPTA_STM32H747XX_M4) + board_runner_args(openocd "--config=${BOARD_DIR}/support/openocd_opta_stm32h747xx_m4.cfg") + board_runner_args(openocd --target-handle=_CHIPNAME.cpu1) +endif() + +board_runner_args(stm32cubeprogrammer "--port=swd" "--reset-mode=hw") + +# Give priority to dfu-util to flash, ST-Link to debug. include(${ZEPHYR_BASE}/boards/common/dfu-util.board.cmake) +include(${ZEPHYR_BASE}/boards/common/stm32cubeprogrammer.board.cmake) +include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) \ No newline at end of file diff --git a/boards/arduino/opta/board_gpio_hse.c b/boards/arduino/opta/board_gpio_hse.c new file mode 100644 index 00000000000..2ee45f52dad --- /dev/null +++ b/boards/arduino/opta/board_gpio_hse.c @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2024 DNDG srl + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +static int board_gpio_hse(void) +{ + /* The external oscillator that drives the HSE clock should be enabled + * by setting the GPIOI1 pin. This function is registered at priority + * RE_KERNEL_1 to be executed before the standard STM clock + * setup code. + */ + + LL_AHB4_GRP1_EnableClock(LL_AHB4_GRP1_PERIPH_GPIOH); + + LL_GPIO_SetPinMode(GPIOH, LL_GPIO_PIN_1, LL_GPIO_MODE_OUTPUT); + LL_GPIO_SetPinSpeed(GPIOH, LL_GPIO_PIN_1, LL_GPIO_SPEED_FREQ_LOW); + LL_GPIO_SetPinOutputType(GPIOH, LL_GPIO_PIN_1, LL_GPIO_OUTPUT_PUSHPULL); + LL_GPIO_SetPinPull(GPIOH, LL_GPIO_PIN_1, LL_GPIO_PULL_UP); + LL_GPIO_SetOutputPin(GPIOH, LL_GPIO_PIN_1); + + return 0; +} + +SYS_INIT(board_gpio_hse, PRE_KERNEL_1, 0); diff --git a/boards/arduino/opta/doc/index.rst b/boards/arduino/opta/doc/index.rst index c50c7e27ec9..1b9e3bb014b 100644 --- a/boards/arduino/opta/doc/index.rst +++ b/boards/arduino/opta/doc/index.rst @@ -1,7 +1,7 @@ .. _arduino_opta_m4_board: -Arduino OPTA M4-Core -#################### +Arduino OPTA +############ Overview ******** @@ -15,14 +15,17 @@ such as Ladder Diagram (LD), Sequential Function Chart (SFC), Function Block Diagram (FBD), Structured Text (ST), and Instruction List (IL), making it an ideal device for automation engineers. -For Zephyr RTOS, only the M4 is supported for now, making the M7 run the PLC -tasks while the M4 core under Zephyr acts as a coprocessor. +For Zephyr RTOS, both cores are supported. It is also possible to run only on +the M4 making the M7 run the PLC tasks while the M4 core under Zephyr acts as +a coprocessor. Additionally, the device features: - Ethernet compliant with IEEE802.3-2002 - 16MB QSPI Flash - 4 x green color status LEDs +- 1 x green or red led over the reset push-button +- 1 x blue led over the user push-button (Opta Advanced only) - 1 x user push-button - 1 x reset push-button accessible via pinhole - 8 x analog inputs @@ -42,7 +45,29 @@ More information about STM32H747XIH6 can be found here: Supported Features ================== -The current Zephyr arduino_opta_m4 board configuration supports the following hardware features: +The ``arduino_opta/stm32h747xx/m7`` board target +supports the following hardware features: + ++-----------+------------+-------------------------------------+ +| Interface | Controller | Driver/Component | ++===========+============+=====================================+ +| NVIC | on-chip | nested vector interrupt controller | ++-----------+------------+-------------------------------------+ +| PINMUX | on-chip | pinmux | ++-----------+------------+-------------------------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+-------------------------------------+ +| FLASH | on-chip | flash memory | ++-----------+------------+-------------------------------------+ +| RNG | on-chip | True Random number generator | ++-----------+------------+-------------------------------------+ +| IPM | on-chip | virtual mailbox based on HSEM | ++-----------+------------+-------------------------------------+ +| USB | on-board | usb-fs | ++-----------+------------+-------------------------------------+ + +The ``arduino_opta/stm32h747xx/m4`` board target +supports the following hardware features: +-----------+------------+-------------------------------------+ | Interface | Controller | Driver/Component | @@ -62,32 +87,41 @@ The current Zephyr arduino_opta_m4 board configuration supports the following ha Other hardware features are not yet supported on Zephyr porting. -The default configuration per core can be found in the defconfig file: -:zephyr_file:`boards/arduino/opta/arduino_opta_stm32h747xx_m4_defconfig` +The default configuration per core can be found in the defconfig files: +:zephyr_file:`boards/arduino/opta/arduino_opta_stm32h747xx_m4_defconfig` and +:zephyr_file:`boards/arduino/opta/arduino_opta_stm32h747xx_m7_defconfig`. Pin Mapping =========== -ARDUINO OPTA M4 has access to the 9 GPIO controllers. These controllers are responsible for pin muxing, -input/output, pull-up, etc. +Both the M7 and M4 cores have access to the 9 GPIO controllers. These +controllers are responsible for pin muxing, input/output, pull-up, etc. For more details please refer to `ARDUINO-OPTA website`_. Default Zephyr Peripheral Mapping --------------------------------- -- Status LED1 : PI0 -- Status LED2 : PI1 -- Status LED3 : PI3 -- Status LED4 : PH15 -- User button : PE4 +- Status LED1: PI0 +- Status LED2: PI1 +- Status LED3: PI3 +- Status LED4: PH15 +- Green "reset" LED: PH12 +- Red "reset" LED: PH11 +- Blue LED: PE5 +- User button: PE4 +- Relay 1: PI6 +- Relay 2: PI5 +- Relay 3: PI7 +- Relay 4: PI4 System Clock ============ The STM32H747I System Clock can be driven by an internal or external oscillator, as well as by the main PLL clock. By default, the CPU2 (Cortex-M4) System clock -is driven at 240MHz. PLL clock is fed by a 25MHz high speed external clock. +is driven at 240MHz. PLL clock is fed by a 25MHz high speed external clock. The +M7 clock is driven at 400MHz. Resources sharing ================= @@ -121,9 +155,30 @@ indicating the board is in bootloader mode. By default: - - CPU2 (Cortex-M4) boot address is set to 0x08180000 (OB: BOOT_CM4_ADD0) + - CPU1 (Cortex-M7) boot address is set to 0x08040000 + - CPU2 (Cortex-M4) boot address is set to 0x08180000 -Zephyr flash configuration has been set to meet these default settings. +Zephyr flash configuration has been set to be compatible with the +"Flash split: 1.5MB M7 + 0.5MB M4" option in the Arduino IDE. The flash is +partitioned as follows: + + - 0x08000000-0x0803FFFF (256k) Arduino MCUboot-derived bootloader + - 0x08040000-0x0817FFFF (768k) M7 application + - 0x08040000-0x0817FFFF (512k) M4 application + + +Flashing an application to ARDUINO OPTA M7 +------------------------------------------ + +First, connect the device to your host computer using +the USB port to prepare it for flashing. Then build and flash your application. + +Here is an example for the :zephyr:code-sample:`blinky` application on M7 core. + +.. zephyr-app-commands:: + :zephyr-app: samples/basic/blinky + :board: arduino_opta/stm32h747xx/m7 + :goals: build flash Flashing an application to ARDUINO OPTA M4 ------------------------------------------ @@ -141,6 +196,9 @@ Here is an example for the :zephyr:code-sample:`blinky` application on M4 core. Starting the application on the ARDUINO OPTA M4 ----------------------------------------------- +If you also flashed an application to M7 the M4 processor is started at boot. +If not you will need to start the processor from an Arduino sketch. + Make sure the option bytes are set to prevent the M4 from auto-starting, and that the M7 side starts the M4 at the correct Flash address. @@ -161,8 +219,9 @@ at least the following code: Debugging ========= -Debugging is not yet supported by this board, since the debug port does -not have an easy access. +The debug port does not have an easy access but it is possible to open the +case and solder a standard 10-pin SWD connector to the board. After that +both flashing and debugging are available via ST-LINK (M7 core only). .. _ARDUINO-OPTA website: https://docs.arduino.cc/hardware/opta diff --git a/boards/arduino/opta/dts/bindings/gpio-power-switches.yaml b/boards/arduino/opta/dts/bindings/gpio-power-switches.yaml new file mode 100644 index 00000000000..580288b2382 --- /dev/null +++ b/boards/arduino/opta/dts/bindings/gpio-power-switches.yaml @@ -0,0 +1,16 @@ +# Copyright (c) 2024 DNDG srl +# SPDX-License-Identifier: Apache-2.0 + +description: | + This allows to define a group of relays (like in the original Opta) + or other kinds of power switches controlled by a GPIO. Each power + switch is defined in a child node of the gpio-power-switches node. + +compatible: "gpio-power-switches" + +child-binding: + description: GPIO power switch child node + properties: + gpios: + type: phandle-array + required: true diff --git a/boards/arduino/opta/support/openocd_opta_stm32h747xx_m7.cfg b/boards/arduino/opta/support/openocd_opta_stm32h747xx_m7.cfg new file mode 100644 index 00000000000..75d441d1809 --- /dev/null +++ b/boards/arduino/opta/support/openocd_opta_stm32h747xx_m7.cfg @@ -0,0 +1,28 @@ + +source [find interface/stlink.cfg] + +transport select hla_swd + +source [find target/stm32h7x.cfg] + +# Use connect_assert_srst here to be able to program +# even when core is in sleep mode +reset_config srst_only srst_nogate connect_assert_srst + +$_CHIPNAME.cpu0 configure -event gdb-attach { + echo "Debugger attaching: halting execution" + gdb_breakpoint_override hard +} + +$_CHIPNAME.cpu0 configure -event gdb-detach { + echo "Debugger detaching: resuming execution" + resume +} + +# Due to the use of connect_assert_srst, running gdb requires +# to reset halt just after openocd init. +rename init old_init +proc init {} { + old_init + reset halt +}