diff --git a/boards/Kconfig b/boards/Kconfig index e84a90b2d57e6..36ba935921353 100644 --- a/boards/Kconfig +++ b/boards/Kconfig @@ -1916,6 +1916,15 @@ config ARCH_BOARD_NUCLEO_H743ZI ---help--- STMicro Nucleo H743ZI board based on the STMicro STM32H743ZI MCU. +config ARCH_BOARD_NUCLEO_H753ZI + bool "STM32H753 Nucleo H753ZI" + depends on ARCH_CHIP_STM32H753ZI + select ARCH_HAVE_LEDS + select ARCH_HAVE_BUTTONS + select ARCH_HAVE_IRQBUTTONS + ---help--- + STMicro Nucleo H753ZI board based on the STMicro STM32H753ZI MCU. + config ARCH_BOARD_NUCLEO_H743ZI2 bool "STM32H743 Nucleo H743ZI2" depends on ARCH_CHIP_STM32H743ZI @@ -3690,6 +3699,7 @@ config ARCH_BOARD default "weact-stm32h743" if ARCH_BOARD_WEACT_STM32H743 default "weact-stm32h750" if ARCH_BOARD_WEACT_STM32H750 default "nucleo-h743zi" if ARCH_BOARD_NUCLEO_H743ZI + default "nucleo-h753zi" if ARCH_BOARD_NUCLEO_H753ZI default "nucleo-h743zi2" if ARCH_BOARD_NUCLEO_H743ZI2 default "nucleo-h745zi" if ARCH_BOARD_NUCLEO_H745ZI default "stm32h745i-disco" if ARCH_BOARD_STM32H745I_DISCO @@ -4425,6 +4435,9 @@ endif if ARCH_BOARD_NUCLEO_H743ZI source "boards/arm/stm32h7/nucleo-h743zi/Kconfig" endif +if ARCH_BOARD_NUCLEO_H753ZI +source "boards/arm/stm32h7/nucleo-h753zi/Kconfig" +endif if ARCH_BOARD_NUCLEO_H743ZI2 source "boards/arm/stm32h7/nucleo-h743zi2/Kconfig" endif diff --git a/boards/arm/stm32h7/nucleo-h753zi/CMakeLists.txt b/boards/arm/stm32h7/nucleo-h753zi/CMakeLists.txt new file mode 100644 index 0000000000000..694928209ac02 --- /dev/null +++ b/boards/arm/stm32h7/nucleo-h753zi/CMakeLists.txt @@ -0,0 +1,23 @@ +# ############################################################################## +# boards/arm/stm32h7/nucleo-h753zi/CMakeLists.txt +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed to the Apache Software Foundation (ASF) under one or more contributor +# license agreements. See the NOTICE file distributed with this work for +# additional information regarding copyright ownership. The ASF licenses this +# file to you under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy of +# the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations under +# the License. +# +# ############################################################################## + +add_subdirectory(src) diff --git a/boards/arm/stm32h7/nucleo-h753zi/Kconfig b/boards/arm/stm32h7/nucleo-h753zi/Kconfig new file mode 100644 index 0000000000000..2b5c1f70b9649 --- /dev/null +++ b/boards/arm/stm32h7/nucleo-h753zi/Kconfig @@ -0,0 +1,1285 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +menu "Board Clock Configuration" + +choice + prompt "HSE clock source" + default NUCLEO_H753ZI_HSE_8MHZ + help + Select the HSE clock source for the Nucleo-H753ZI board. + 8 MHz: ST-LINK MCO (default, no hardware modification) + 25 MHz: External crystal X3 (requires hardware modification) + +config NUCLEO_H753ZI_HSE_8MHZ + bool "8 MHz from ST-LINK MCO" + help + Default Nucleo-H753ZI configuration. + Uses 8 MHz clock from ST-LINK MCO output (PH0-OSC_IN). + Solder Bridge Configuration: + SB45=ON, SB44=OFF, SB46=OFF, SB3=OFF, SB4=OFF + This is the factory default - no hardware changes needed. + System clocks with 8 MHz HSE: + - SYSCLK: 400 MHz + - HCLK: 200 MHz + - APB1/2/3/4: 100 MHz + - FDCAN: 25 MHz (via PLL2Q) + +config NUCLEO_H753ZI_HSE_25MHZ + bool "25 MHz external crystal X3" + help + Uses 25 MHz external crystal on X3 footprint. + Solder Bridge Configuration: + SB3=ON, SB4=ON, SB45=OFF, SB44=OFF, SB46=OFF + WARNING: Requires hardware modification: + - Install 25 MHz crystal at X3 footprint + - Reconfigure solder bridges as indicated above + System clocks with 25 MHz HSE: + - SYSCLK: 400 MHz + - HCLK: 200 MHz + - APB1/2/3/4: 100 MHz + - FDCAN: 25 MHz (direct from HSE) + +endchoice + +config STM32H7_BOARD_HSE_FREQUENCY + int + default 8000000 if NUCLEO_H753ZI_HSE_8MHZ + default 25000000 if NUCLEO_H753ZI_HSE_25MHZ + depends on STM32H7_HSE + +endmenu + +config NUCLEO_H753ZI_GPIO_DRIVER + bool "Enable Nucleo H753ZI board GPIO driver" + default n + select DEV_GPIO + help + This option enables the low-level GPIO driver for the + Nucleo H753ZI board. Other features like buttons or LEDs + will depend on this driver. + +choice + prompt "LED Control Mode" + default NUCLEO_H753ZI_LEDS_AUTO + help + Select how the onboard LEDs should be controlled. + +config NUCLEO_H753ZI_LEDS_AUTO + bool "Automatic LEDs (Kernel controlled)" + help + LEDs are automatically controlled by the kernel to indicate + system status (boot stages, interrupts, panics, etc.). + The LEDs will show: + - GREEN: System ready, signals + - ORANGE: Heap allocation, IRQs + - RED: Assertions, panics, idle + NOTE: You still need to manually enable: + Board Selection -> Board LED Status support + +config NUCLEO_H753ZI_LEDS_USER + bool "User-controlled LEDs" + select USERLED + select USERLED_LOWER + select BOARD_LATE_INITIALIZE + help + LEDs are controlled by user applications via /dev/userleds. + Applications can turn individual LEDs on/off as needed. + Kernel status indication is disabled. + NOTE: You must manually disable: + Board Selection -> Board LED Status support (to avoid + conflicts) + +config NUCLEO_H753ZI_LEDS_DISABLED + bool "LEDs disabled" + help + LED functionality is completely disabled to save resources. + NOTE: You should manually disable: + Board Selection -> Board LED Status support + +endchoice + +menu "Button Configuration" + +config NUCLEO_H753ZI_BUTTON_SUPPORT + bool "Enable button support" + default n + select ARCH_BUTTONS + help + Enable GPIO button support for the Nucleo-H753ZI board. + +config NUCLEO_H753ZI_BUTTON_COUNT + int "Number of buttons" + depends on NUCLEO_H753ZI_BUTTON_SUPPORT + default 1 + range 1 32 + help + Total number of buttons to configure (1-32). + The STM32H7 button driver supports up to 32 buttons using + a 32-bit bitmask for button states. + +config NUCLEO_H753ZI_BUTTON_BUILTIN + bool "Include built-in user button (PC13)" + depends on NUCLEO_H753ZI_BUTTON_SUPPORT + default y + help + Include the built-in blue user button connected to PC13. + This button will always be assigned as button index 0. + If enabled, you need (BUTTON_COUNT - 1) additional pins. + If disabled, you need exactly BUTTON_COUNT pins. + +config NUCLEO_H753ZI_BUTTON_PINS + string "Button GPIO pin list" + depends on NUCLEO_H753ZI_BUTTON_SUPPORT + default "" + help + Comma-separated list of GPIO pins for buttons. + Format: PORT+PIN (e.g., "PF15,PG14,PG9,PE0,PA0,PB12") + Number of pins required: + - With built-in: (BUTTON_COUNT - 1) pins + - Without built-in: BUTTON_COUNT pins + Example for 5 buttons with built-in enabled: + "PF15,PG14,PG9,PE0" + Common Nucleo-H753ZI pins: + Arduino Headers: PF15(D2), PG14(D1), PG9(D0), PE0(D34) + Morpho Headers: PA0-PA15, PB0-PB15, PC0-PC15, PD0-PD15, + PE0-PE15, PF0-PF15, PG0-PG15, PH0-PH1 + Note: All buttons assume pull-down resistor configuration. + +config NUCLEO_H753ZI_BUTTON_VALIDATION + bool "Validate pin configuration at compile time" + depends on NUCLEO_H753ZI_BUTTON_SUPPORT + default y + help + Perform compile-time validation of GPIO pin assignments. + +endmenu + +menu "SPI Configuration" + depends on STM32H7_SPI + +comment "SPI interfaces now use per-sensor CS registration system" +comment "No CS pins configured at SPI level - sensors register their own CS pins" + +if STM32H7_SPI1 + +menu "SPI1 Configuration" + +config NUCLEO_H753ZI_SPI1_ENABLE + bool "Enable SPI1" + default n + help + Enable SPI1 with configurable pins. + CS pins are now registered per-sensor. + +choice + prompt "SPI1 Pin Set" + depends on NUCLEO_H753ZI_SPI1_ENABLE + default NUCLEO_H753ZI_SPI1_PINSET_1 + help + Select which set of pins to use for SPI1. + Choose based on availability and board layout. + +config NUCLEO_H753ZI_SPI1_PINSET_1 + bool "Pin Set 1: PA5(SCK), PA6(MISO), PA7(MOSI)" + help + SPI1 Pin Set 1 (Arduino SPI connector compatible): + - SCK: PA5 (D13 - Arduino SCK) + - MISO: PA6 (D12 - Arduino MISO) + - MOSI: PA7 (D11 - Arduino MOSI) + This is the standard Arduino SPI pinout. + +config NUCLEO_H753ZI_SPI1_PINSET_2 + bool "Pin Set 2: PB3(SCK), PB4(MISO), PB5(MOSI)" + help + SPI1 Pin Set 2: + - SCK: PB3 + - MISO: PB4 + - MOSI: PB5 + +config NUCLEO_H753ZI_SPI1_PINSET_3 + bool "Pin Set 3: PG11(SCK), PG9(MISO), PD7(MOSI)" + help + SPI1 Pin Set 3: + - SCK: PG11 + - MISO: PG9 + - MOSI: PD7 + +endchoice + +endmenu + +endif + +if STM32H7_SPI2 + +menu "SPI2 Configuration" + +config NUCLEO_H753ZI_SPI2_ENABLE + bool "Enable SPI2" + default n + help + Enable SPI2 with configurable pins. + CS pins are now registered per-sensor. + +choice + prompt "SPI2 Pin Set" + depends on NUCLEO_H753ZI_SPI2_ENABLE + default NUCLEO_H753ZI_SPI2_PINSET_1 + help + Select which set of pins to use for SPI2. + +config NUCLEO_H753ZI_SPI2_PINSET_1 + bool "Pin Set 1: PB13(SCK), PB14(MISO), PB15(MOSI)" + help + SPI2 Pin Set 1: + - SCK: PB13 + - MISO: PB14 + - MOSI: PB15 + +config NUCLEO_H753ZI_SPI2_PINSET_2 + bool "Pin Set 2: PA12(SCK), PC2(MISO), PC1(MOSI)" + help + SPI2 Pin Set 2: + - SCK: PA12 + - MISO: PC2 + - MOSI: PC1 + +config NUCLEO_H753ZI_SPI2_PINSET_3 + bool "Pin Set 3: PD3(SCK), PC2(MISO), PC3(MOSI)" + help + SPI2 Pin Set 3: + - SCK: PD3 + - MISO: PC2 + - MOSI: PC3 + +endchoice + +endmenu + +endif + +if STM32H7_SPI3 + +menu "SPI3 Configuration" + +config NUCLEO_H753ZI_SPI3_ENABLE + bool "Enable SPI3" + default n + help + Enable SPI3 with configurable pins. + CS pins are now registered per-sensor. + +choice + prompt "SPI3 Pin Set" + depends on NUCLEO_H753ZI_SPI3_ENABLE + default NUCLEO_H753ZI_SPI3_PINSET_1 + help + Select which set of pins to use for SPI3. + +config NUCLEO_H753ZI_SPI3_PINSET_1 + bool "Pin Set 1: PC10(SCK), PC11(MISO), PC12(MOSI)" + help + SPI3 Pin Set 1: + - SCK: PC10 + - MISO: PC11 + - MOSI: PC12 + +config NUCLEO_H753ZI_SPI3_PINSET_2 + bool "Pin Set 2: PB3(SCK), PB4(MISO), PB5(MOSI)" + help + SPI3 Pin Set 2: + - SCK: PB3 + - MISO: PB4 + - MOSI: PB5 + +endchoice + +endmenu + +endif + +if STM32H7_SPI4 + +menu "SPI4 Configuration" + +config NUCLEO_H753ZI_SPI4_ENABLE + bool "Enable SPI4" + default n + help + Enable SPI4 with configurable pins. + CS pins are now registered per-sensor. + +choice + prompt "SPI4 Pin Set" + depends on NUCLEO_H753ZI_SPI4_ENABLE + default NUCLEO_H753ZI_SPI4_PINSET_1 + help + Select which set of pins to use for SPI4. + +config NUCLEO_H753ZI_SPI4_PINSET_1 + bool "Pin Set 1: PE12(SCK), PE13(MISO), PE14(MOSI)" + help + SPI4 Pin Set 1: + - SCK: PE12 + - MISO: PE13 + - MOSI: PE14 + +config NUCLEO_H753ZI_SPI4_PINSET_2 + bool "Pin Set 2: PE2(SCK), PE5(MISO), PE6(MOSI)" + help + SPI4 Pin Set 2: + - SCK: PE2 + - MISO: PE5 + - MOSI: PE6 + +endchoice + +endmenu + +endif + +if STM32H7_SPI5 + +menu "SPI5 Configuration" + +config NUCLEO_H753ZI_SPI5_ENABLE + bool "Enable SPI5" + default n + help + Enable SPI5 with configurable pins. + CS pins are now registered per-sensor. + +choice + prompt "SPI5 Pin Set" + depends on NUCLEO_H753ZI_SPI5_ENABLE + default NUCLEO_H753ZI_SPI5_PINSET_1 + help + Select which set of pins to use for SPI5. + +config NUCLEO_H753ZI_SPI5_PINSET_1 + bool "Pin Set 1: PF7(SCK), PF8(MISO), PF9(MOSI)" + help + SPI5 Pin Set 1: + - SCK: PF7 + - MISO: PF8 + - MOSI: PF9 + +config NUCLEO_H753ZI_SPI5_PINSET_2 + bool "Pin Set 2: PK0(SCK), PJ11(MISO), PJ10(MOSI)" + help + SPI5 Pin Set 2: + - SCK: PK0 + - MISO: PJ11 + - MOSI: PJ10 + +endchoice + +endmenu + +endif + +if STM32H7_SPI6 + +menu "SPI6 Configuration" + +config NUCLEO_H753ZI_SPI6_ENABLE + bool "Enable SPI6" + default n + help + Enable SPI6 with configurable pins. + CS pins are now registered per-sensor. + +choice + prompt "SPI6 Pin Set" + depends on NUCLEO_H753ZI_SPI6_ENABLE + default NUCLEO_H753ZI_SPI6_PINSET_1 + help + Select which set of pins to use for SPI6. + +config NUCLEO_H753ZI_SPI6_PINSET_1 + bool "Pin Set 1: PG13(SCK), PG12(MISO), PG14(MOSI)" + help + SPI6 Pin Set 1: + - SCK: PG13 + - MISO: PG12 + - MOSI: PG14 + +config NUCLEO_H753ZI_SPI6_PINSET_2 + bool "Pin Set 2: PA5(SCK), PA6(MISO), PA7(MOSI)" + help + SPI6 Pin Set 2: + - SCK: PA5 + - MISO: PA6 + - MOSI: PA7 + +endchoice + +endmenu + +endif + +endmenu + +menu "I2C Configuration" + depends on STM32H7_I2C + +config NUCLEO_H753ZI_I2C1_ENABLE + bool "Enable I2C1" + default n + depends on STM32H7_I2C1 + help + Enable I2C1 bus with configurable pinset selection. + +if NUCLEO_H753ZI_I2C1_ENABLE + +choice + prompt "I2C1 Pin Set" + default NUCLEO_H753ZI_I2C1_PINSET_1 + help + Select which pins to use for I2C1 SCL/SDA signals. + +config NUCLEO_H753ZI_I2C1_PINSET_1 + bool "Pin Set 1: PB6(SCL), PB7(SDA) - AF4" + help + I2C1 Pin Set 1 (Arduino D10/D9): + - SCL: PB6 (CN7-13, D10) - AF4 + - SDA: PB7 (CN7-21, D9) - AF4 + This is the default Arduino-compatible pinout. + WARNING: Conflicts with I2C4 Pinset 4 (same pins, AF6). + +config NUCLEO_H753ZI_I2C1_PINSET_2 + bool "Pin Set 2: PB8(SCL), PB9(SDA) - AF4" + help + I2C1 Pin Set 2 (Morpho): + - SCL: PB8 (CN7-2) - AF4 + - SDA: PB9 (CN7-4) - AF4 + WARNING: Conflicts with I2C4 Pinset 5 (same pins, AF6). + +endchoice + +config NUCLEO_H753ZI_I2C1_DEFAULT_FREQUENCY + int "I2C1 Default Bus Frequency (Hz)" + default 100000 + range 10000 1000000 + help + Default I2C1 bus frequency. + Individual devices can override this. + Standard speeds: + - 100000 (100 kHz): Standard mode + - 400000 (400 kHz): Fast mode + - 1000000 (1 MHz): Fast mode plus + +endif + +config NUCLEO_H753ZI_I2C2_ENABLE + bool "Enable I2C2" + default n + depends on STM32H7_I2C2 + help + Enable I2C2 bus with configurable pinset selection. + +if NUCLEO_H753ZI_I2C2_ENABLE + +choice + prompt "I2C2 Pin Set" + default NUCLEO_H753ZI_I2C2_PINSET_1 + help + Select which pins to use for I2C2 SCL/SDA signals. + +config NUCLEO_H753ZI_I2C2_PINSET_1 + bool "Pin Set 1: PB10(SCL), PB11(SDA) - AF4" + help + I2C2 Pin Set 1: + - SCL: PB10 - AF4 + - SDA: PB11 - AF4 + +config NUCLEO_H753ZI_I2C2_PINSET_2 + bool "Pin Set 2: PF1(SCL), PF0(SDA) - AF4" + help + I2C2 Pin Set 2: + - SCL: PF1 - AF4 + - SDA: PF0 - AF4 + +config NUCLEO_H753ZI_I2C2_PINSET_3 + bool "Pin Set 3: PH4(SCL), PH5(SDA) - AF4" + help + I2C2 Pin Set 3: + - SCL: PH4 - AF4 + - SDA: PH5 - AF4 + +endchoice + +config NUCLEO_H753ZI_I2C2_DEFAULT_FREQUENCY + int "I2C2 Default Bus Frequency (Hz)" + default 100000 + range 10000 1000000 + +endif + +config NUCLEO_H753ZI_I2C3_ENABLE + bool "Enable I2C3" + default n + depends on STM32H7_I2C3 + help + Enable I2C3 bus with configurable pinset selection. + +if NUCLEO_H753ZI_I2C3_ENABLE + +choice + prompt "I2C3 Pin Set" + default NUCLEO_H753ZI_I2C3_PINSET_1 + help + Select which pins to use for I2C3 SCL/SDA signals. + +config NUCLEO_H753ZI_I2C3_PINSET_1 + bool "Pin Set 1: PA8(SCL), PC9(SDA) - AF4" + help + I2C3 Pin Set 1: + - SCL: PA8 - AF4 + - SDA: PC9 - AF4 + +config NUCLEO_H753ZI_I2C3_PINSET_2 + bool "Pin Set 2: PH7(SCL), PH8(SDA) - AF4" + help + I2C3 Pin Set 2: + - SCL: PH7 - AF4 + - SDA: PH8 - AF4 + +endchoice + +config NUCLEO_H753ZI_I2C3_DEFAULT_FREQUENCY + int "I2C3 Default Bus Frequency (Hz)" + default 100000 + range 10000 1000000 + +endif + +config NUCLEO_H753ZI_I2C4_ENABLE + bool "Enable I2C4" + default n + depends on STM32H7_I2C4 + help + Enable I2C4 bus with configurable pinset selection. + +if NUCLEO_H753ZI_I2C4_ENABLE + +choice + prompt "I2C4 Pin Set" + default NUCLEO_H753ZI_I2C4_PINSET_1 + help + Select which pins to use for I2C4 SCL/SDA signals. + +config NUCLEO_H753ZI_I2C4_PINSET_1 + bool "Pin Set 1: PD12(SCL), PD13(SDA) - AF4" + help + I2C4 Pin Set 1: + - SCL: PD12 - AF4 + - SDA: PD13 - AF4 + +config NUCLEO_H753ZI_I2C4_PINSET_2 + bool "Pin Set 2: PF14(SCL), PF15(SDA) - AF4" + help + I2C4 Pin Set 2: + - SCL: PF14 - AF4 + - SDA: PF15 - AF4 + +config NUCLEO_H753ZI_I2C4_PINSET_3 + bool "Pin Set 3: PH11(SCL), PH12(SDA) - AF4" + help + I2C4 Pin Set 3: + - SCL: PH11 - AF4 + - SDA: PH12 - AF4 + +config NUCLEO_H753ZI_I2C4_PINSET_4 + bool "Pin Set 4: PB6(SCL), PB7(SDA) - AF6" + depends on !NUCLEO_H753ZI_I2C1_PINSET_1 + help + I2C4 Pin Set 4 (Alternate Function 6): + - SCL: PB6 - AF6 + - SDA: PB7 - AF6 + WARNING: These are the same physical pins as I2C1 Pinset 1. + Cannot use both I2C1 Pinset 1 (AF4) and I2C4 Pinset 4 (AF6). + OK to use with I2C1 Pinset 2 (different pins). + +config NUCLEO_H753ZI_I2C4_PINSET_5 + bool "Pin Set 5: PB8(SCL), PB9(SDA) - AF6" + depends on !NUCLEO_H753ZI_I2C1_PINSET_2 + help + I2C4 Pin Set 5 (Alternate Function 6): + - SCL: PB8 - AF6 + - SDA: PB9 - AF6 + WARNING: These are the same physical pins as I2C1 Pinset 2. + Cannot use both I2C1 Pinset 2 (AF4) and I2C4 Pinset 5 (AF6). + OK to use with I2C1 Pinset 1 (different pins). + +endchoice + +config NUCLEO_H753ZI_I2C4_DEFAULT_FREQUENCY + int "I2C4 Default Bus Frequency (Hz)" + default 100000 + range 10000 1000000 + +endif + +endmenu + +menu "SPI MODULES" + depends on STM32H7_SPI + +menu "MFRC522 RFID Reader Configuration" + depends on CL_MFRC522 + +config NUCLEO_H753ZI_MFRC522_ENABLE + bool "Enable MFRC522 RFID Reader" + default n + help + Enable MFRC522 13.56 MHz RFID reader with configurable SPI bus, + CS pin, and optional IRQ support. + +if NUCLEO_H753ZI_MFRC522_ENABLE + +choice + prompt "MFRC522 SPI Bus" + help + Select which SPI bus the MFRC522 is connected to. + +config NUCLEO_H753ZI_MFRC522_SPI1 + bool "Use SPI1" + depends on NUCLEO_H753ZI_SPI1_ENABLE + +config NUCLEO_H753ZI_MFRC522_SPI2 + bool "Use SPI2" + depends on NUCLEO_H753ZI_SPI2_ENABLE + +config NUCLEO_H753ZI_MFRC522_SPI3 + bool "Use SPI3" + depends on NUCLEO_H753ZI_SPI3_ENABLE + +config NUCLEO_H753ZI_MFRC522_SPI4 + bool "Use SPI4" + depends on NUCLEO_H753ZI_SPI4_ENABLE + +config NUCLEO_H753ZI_MFRC522_SPI5 + bool "Use SPI5" + depends on NUCLEO_H753ZI_SPI5_ENABLE + +config NUCLEO_H753ZI_MFRC522_SPI6 + bool "Use SPI6" + depends on NUCLEO_H753ZI_SPI6_ENABLE + +endchoice + +config NUCLEO_H753ZI_MFRC522_SPI_BUS + int + default 1 if NUCLEO_H753ZI_MFRC522_SPI1 + default 2 if NUCLEO_H753ZI_MFRC522_SPI2 + default 3 if NUCLEO_H753ZI_MFRC522_SPI3 + default 4 if NUCLEO_H753ZI_MFRC522_SPI4 + default 5 if NUCLEO_H753ZI_MFRC522_SPI5 + default 6 if NUCLEO_H753ZI_MFRC522_SPI6 + +config NUCLEO_H753ZI_MFRC522_DEVID + int "MFRC522 Device ID" + range 0 15 + default 0 + help + Device ID for MFRC522 within the selected SPI bus. + Range: 0-15 for each SPI bus. + This ID will be used to register the CS pin. + +config NUCLEO_H753ZI_MFRC522_CS_PIN + string "CS (Chip Select) GPIO Pin" + default "PA4" + help + GPIO pin for MFRC522 Chip Select. + Format: PORT+PIN (e.g., "PA4", "PB0", "PC5") + Common available pins: + - Arduino Headers: PF15(D2), PG14(D1), PG9(D0), PE0(D34) + - Morpho Headers: PA0-PA15, PB0-PB15, PC0-PC15, PD0-PD15, + PE0-PE15, PF0-PF15, PG0-PG15, PH0-PH1 + Avoid pins already used by selected SPI MISO/MOSI/SCK. + +choice + prompt "CS Pin Active Level" + default NUCLEO_H753ZI_MFRC522_CS_ACTIVE_LOW + help + Select whether the CS pin is active low or active high. + +config NUCLEO_H753ZI_MFRC522_CS_ACTIVE_LOW + bool "Active Low (standard)" + help + CS pin is active low (0V = selected, 3.3V = deselected). + This is the standard for MFRC522. + +config NUCLEO_H753ZI_MFRC522_CS_ACTIVE_HIGH + bool "Active High" + help + CS pin is active high (3.3V = selected, 0V = deselected). + Use only if your hardware requires it. + +endchoice + +config NUCLEO_H753ZI_MFRC522_IRQ_ENABLE + bool "Enable IRQ support" + default n + help + Enable interrupt-driven operation for MFRC522. + Allows the reader to signal when a card is detected. + +config NUCLEO_H753ZI_MFRC522_IRQ_PIN + string "IRQ GPIO Pin" + depends on NUCLEO_H753ZI_MFRC522_IRQ_ENABLE + default "PF2" + help + GPIO pin for MFRC522 interrupt signal. + Format: PORT+PIN (e.g., "PF2", "PE1", "PA3") + This pin should be connected to the MFRC522's IRQ output. + Choose a pin that supports external interrupts. + Common interrupt-capable pins: + - Arduino Headers: PF15(D2), PG14(D1), PG9(D0) + - Morpho Headers: Most PA/PB/PC/PD/PE/PF/PG pins + Avoid pins already used by SPI or CS. + +choice + prompt "IRQ Trigger Type" + depends on NUCLEO_H753ZI_MFRC522_IRQ_ENABLE + default NUCLEO_H753ZI_MFRC522_IRQ_FALLING_EDGE + help + Select the interrupt trigger type for MFRC522. + +config NUCLEO_H753ZI_MFRC522_IRQ_FALLING_EDGE + bool "Falling Edge" + help + Trigger interrupt on falling edge (3.3V to 0V transition). + This is the default for MFRC522. + +config NUCLEO_H753ZI_MFRC522_IRQ_RISING_EDGE + bool "Rising Edge" + help + Trigger interrupt on rising edge (0V to 3.3V transition). + +config NUCLEO_H753ZI_MFRC522_IRQ_BOTH_EDGES + bool "Both Edges" + help + Trigger interrupt on both rising and falling edges. + +endchoice + +endif + +endmenu + +menu "ST7796 LCD Display Configuration" + depends on LCD_ST7796 + +config NUCLEO_H753ZI_ST7796_ENABLE + bool "Enable ST7796 LCD Display" + default n + select SPI_CMDDATA + help + Enable ST7796 3.5" IPS LCD display (320x480) with configurable + SPI bus, CS pin, DC pin, RESET pin, and LED backlight pin. + +if NUCLEO_H753ZI_ST7796_ENABLE + +choice + prompt "ST7796 SPI Bus" + help + Select which SPI bus the ST7796 is connected to. + +config NUCLEO_H753ZI_ST7796_SPI1 + bool "Use SPI1" + depends on NUCLEO_H753ZI_SPI1_ENABLE + +config NUCLEO_H753ZI_ST7796_SPI2 + bool "Use SPI2" + depends on NUCLEO_H753ZI_SPI2_ENABLE + +config NUCLEO_H753ZI_ST7796_SPI3 + bool "Use SPI3" + depends on NUCLEO_H753ZI_SPI3_ENABLE + +config NUCLEO_H753ZI_ST7796_SPI4 + bool "Use SPI4" + depends on NUCLEO_H753ZI_SPI4_ENABLE + +config NUCLEO_H753ZI_ST7796_SPI5 + bool "Use SPI5" + depends on NUCLEO_H753ZI_SPI5_ENABLE + +config NUCLEO_H753ZI_ST7796_SPI6 + bool "Use SPI6" + depends on NUCLEO_H753ZI_SPI6_ENABLE + +endchoice + +config NUCLEO_H753ZI_ST7796_SPI_BUS + int + default 1 if NUCLEO_H753ZI_ST7796_SPI1 + default 2 if NUCLEO_H753ZI_ST7796_SPI2 + default 3 if NUCLEO_H753ZI_ST7796_SPI3 + default 4 if NUCLEO_H753ZI_ST7796_SPI4 + default 5 if NUCLEO_H753ZI_ST7796_SPI5 + default 6 if NUCLEO_H753ZI_ST7796_SPI6 + +config NUCLEO_H753ZI_ST7796_DEVID + int "ST7796 Device ID" + range 0 15 + default 0 + help + Device ID for ST7796 within the selected SPI bus. + Range: 0-15 for each SPI bus. + This ID will be used to register the CS pin. + +menu "ST7796 Pin Configuration" + +config NUCLEO_H753ZI_ST7796_CS_PIN + string "CS (Chip Select) GPIO Pin" + default "PA4" + help + GPIO pin for ST7796 Chip Select. + Format: PORT+PIN (e.g., "PA4", "PB0", "PC5") + Common available pins: + - Arduino Headers: PF15(D2), PG14(D1), PG9(D0), PE0(D34) + - Morpho Headers: PA0-PA15, PB0-PB15, PC0-PC15, PD0-PD15, + PE0-PE15, PF0-PF15, PG0-PG15, PH0-PH1 + Avoid pins already used by selected SPI MISO/MOSI/SCK. + +choice + prompt "CS Pin Active Level" + default NUCLEO_H753ZI_ST7796_CS_ACTIVE_LOW + help + Select whether the CS pin is active low or active high. + +config NUCLEO_H753ZI_ST7796_CS_ACTIVE_LOW + bool "Active Low (most common)" + help + CS pin is active low (0V = selected, 3.3V = deselected). + This is the standard for most SPI displays including ST7796. + +config NUCLEO_H753ZI_ST7796_CS_ACTIVE_HIGH + bool "Active High" + help + CS pin is active high (3.3V = selected, 0V = deselected). + Less common, use only if your hardware requires it. + +endchoice + +config NUCLEO_H753ZI_ST7796_DC_PIN + string "DC (Data/Command) GPIO Pin" + default "PA3" + help + GPIO pin for ST7796 Data/Command selection. + Format: PORT+PIN (e.g., "PA3", "PB1", "PC4") + This pin controls whether data sent to the display is + interpreted as commands or display data. + DC=0: Command + DC=1: Data + Choose a pin not used by SPI or CS. + +config NUCLEO_H753ZI_ST7796_RESET_PIN + string "RESET GPIO Pin" + default "PA2" + help + GPIO pin for ST7796 hardware reset. + Format: PORT+PIN (e.g., "PA2", "PB2", "PC3") + This pin is used to perform a hardware reset of the display. + Active low reset (pull low to reset, high for normal + operation). + Choose a pin not used by SPI, CS, or DC. + +config NUCLEO_H753ZI_ST7796_LED_PIN + string "LED (Backlight) GPIO Pin" + default "PA1" + help + GPIO pin for ST7796 backlight control. + Format: PORT+PIN (e.g., "PA1", "PB3", "PC2") + This pin controls the LCD backlight LED. + High = backlight on, Low = backlight off. + Note: Currently configured for direct 3.3V connection + without PWM. For PWM brightness control, additional + configuration will be needed. + Choose a pin not used by SPI, CS, DC, or RESET. + +endmenu + +menu "ST7796 Display Settings" + +choice + prompt "Color Depth" + default NUCLEO_H753ZI_ST7796_RGB565 + help + Select the color depth for the ST7796 display. + +config NUCLEO_H753ZI_ST7796_RGB444 + bool "12-bit RGB444" + help + 12-bit color depth (4096 colors). + Lower memory usage but reduced color quality. + +config NUCLEO_H753ZI_ST7796_RGB565 + bool "16-bit RGB565 (recommended)" + help + 16-bit color depth (65536 colors). + Good balance between color quality and memory usage. + This is the most common configuration. + +config NUCLEO_H753ZI_ST7796_RGB666 + bool "18-bit RGB666" + help + 18-bit color depth (262144 colors). + Higher color quality but increased memory usage and + slower SPI transfers. + +endchoice + +choice + prompt "Display Orientation" + default NUCLEO_H753ZI_ST7796_PORTRAIT + help + Select the display orientation. + +config NUCLEO_H753ZI_ST7796_PORTRAIT + bool "Portrait (320x480)" + help + Portrait orientation: 320 pixels wide, 480 pixels tall. + This is the natural orientation of the display. + +config NUCLEO_H753ZI_ST7796_LANDSCAPE + bool "Landscape (480x320)" + help + Landscape orientation: 480 pixels wide, 320 pixels tall. + 90 degree rotation from portrait. + +config NUCLEO_H753ZI_ST7796_RPORTRAIT + bool "Reverse Portrait (320x480)" + help + Reverse portrait orientation: 320 pixels wide, 480 pixels + tall. 180 degree rotation from portrait. + +config NUCLEO_H753ZI_ST7796_RLANDSCAPE + bool "Reverse Landscape (480x320)" + help + Reverse landscape orientation: 480 pixels wide, 320 pixels + tall. 270 degree rotation from portrait (or 90 degrees from + landscape). + +endchoice + +config NUCLEO_H753ZI_ST7796_BGR + bool "Use BGR color order instead of RGB" + default y + help + Enable this if your display shows colors incorrectly + (e.g., red appears as blue and vice versa). + Most ST7796 displays use RGB order, but some use BGR. + +config NUCLEO_H753ZI_ST7796_FREQUENCY + int "SPI Frequency (Hz)" + default 40000000 + range 1000000 80000000 + help + SPI bus frequency for ST7796 communication. + Recommended values: + - 40000000 (40 MHz): Safe default, works with most displays + - 60000000 (60 MHz): Faster, may work depending on wiring + - 80000000 (80 MHz): Maximum, requires good signal integrity + Lower frequencies (10-20 MHz) can be used if you experience + display issues or have long/poor quality connections. + +endmenu + +menu "ST7796 Framebuffer Configuration" + +config NUCLEO_H753ZI_ST7796_FB_SUPPORT + bool "Enable framebuffer support" + default y + depends on VIDEO_FB + help + Enable framebuffer support for ST7796. + This allows the display to be used with LVGL and other + graphics libraries that use the framebuffer interface. + +if NUCLEO_H753ZI_ST7796_FB_SUPPORT + +config NUCLEO_H753ZI_ST7796_FB_SIZE + int "Framebuffer size (in KB)" + default 300 + range 150 600 + help + Size of the framebuffer in kilobytes. + Full resolution requirements: + - RGB444 (12-bit): 300 KB (320x480x1.5 bytes) + - RGB565 (16-bit): 300 KB (320x480x2 bytes) + - RGB666 (18-bit): 450 KB (320x480x3 bytes) + For memory-constrained systems, you can reduce this + and implement partial screen updates. + +endif + +endmenu + +menu "ST7796 Orientation" + +choice + prompt "Display Rotation" + default NUCLEO_H753ZI_ST7796_ROTATION_0 + help + Select the display rotation angle. Use this if your display + is mounted upside down or needs rotation. + This rotation is applied AFTER the base orientation selected + in "Display Settings" above. + +config NUCLEO_H753ZI_ST7796_ROTATION_0 + bool "0 degrees (Normal)" + help + No rotation. Display orientation as configured in Display + Settings (Portrait, Landscape, etc). + Use this if your display is mounted correctly. + +config NUCLEO_H753ZI_ST7796_ROTATION_180 + bool "180 degrees (Flip)" + help + Rotate display 180 degrees. Use this if your display is + mounted upside down. + This flips both horizontal and vertical axes, effectively + rotating the entire display content 180 degrees. + Works with all orientation modes (Portrait, Landscape, etc). + +endchoice + +config NUCLEO_H753ZI_ST7796_ROTATION + int + default 0 if NUCLEO_H753ZI_ST7796_ROTATION_0 + default 180 if NUCLEO_H753ZI_ST7796_ROTATION_180 + help + Internal: Rotation angle in degrees. + +endmenu + +endif + +endmenu + +endmenu + +menu "I2C MODULES" + depends on STM32H7_I2C + +menu "SSD1306 OLED Display Configuration" + depends on LCD_SSD1306 + +config NUCLEO_H753ZI_SSD1306_ENABLE + bool "Enable SSD1306 OLED Display (I2C)" + default n + help + Enable SSD1306 OLED display via I2C interface. + The SSD1306 is a monochrome OLED display controller + commonly used in 128x64 and 128x32 pixel displays. + +if NUCLEO_H753ZI_SSD1306_ENABLE + +choice + prompt "SSD1306 I2C Bus" + default NUCLEO_H753ZI_SSD1306_I2C1 + help + Select which I2C bus the SSD1306 is connected to. + +config NUCLEO_H753ZI_SSD1306_I2C1 + bool "I2C1" + depends on STM32H7_I2C1 + select NUCLEO_H753ZI_I2C1_ENABLE + help + Use I2C1 bus for SSD1306 display. + +config NUCLEO_H753ZI_SSD1306_I2C2 + bool "I2C2" + depends on STM32H7_I2C2 + select NUCLEO_H753ZI_I2C2_ENABLE + help + Use I2C2 bus for SSD1306 display. + +config NUCLEO_H753ZI_SSD1306_I2C3 + bool "I2C3" + depends on STM32H7_I2C3 + select NUCLEO_H753ZI_I2C3_ENABLE + help + Use I2C3 bus for SSD1306 display. + +config NUCLEO_H753ZI_SSD1306_I2C4 + bool "I2C4" + depends on STM32H7_I2C4 + select NUCLEO_H753ZI_I2C4_ENABLE + help + Use I2C4 bus for SSD1306 display. + +endchoice + +config NUCLEO_H753ZI_SSD1306_I2C_BUS + int + default 1 if NUCLEO_H753ZI_SSD1306_I2C1 + default 2 if NUCLEO_H753ZI_SSD1306_I2C2 + default 3 if NUCLEO_H753ZI_SSD1306_I2C3 + default 4 if NUCLEO_H753ZI_SSD1306_I2C4 + +choice + prompt "SSD1306 I2C Address" + default NUCLEO_H753ZI_SSD1306_ADDR_3C + help + Select the I2C address of your SSD1306 module. + Check your hardware: + - Most modules use 0x3C (default) + - Some modules use 0x3D + - Address is determined by the SA0 pin state + +config NUCLEO_H753ZI_SSD1306_ADDR_3C + bool "0x3C (SA0 = GND) - Default" + help + I2C address 0x3C (60 decimal). + This is the most common address for SSD1306 modules. + Used when SA0 pin is connected to GND. + +config NUCLEO_H753ZI_SSD1306_ADDR_3D + bool "0x3D (SA0 = VDD)" + help + I2C address 0x3D (61 decimal). + Used when SA0 pin is connected to VDD. + +config NUCLEO_H753ZI_SSD1306_ADDR_CUSTOM + bool "Custom Address" + help + Specify a custom I2C address. + +endchoice + +config NUCLEO_H753ZI_SSD1306_ADDR_CUSTOM_VALUE + hex "Custom I2C Address" + depends on NUCLEO_H753ZI_SSD1306_ADDR_CUSTOM + default 0x3C + range 0x08 0x77 + help + Enter custom I2C address in hexadecimal format. + Valid range: 0x08 to 0x77 + +config NUCLEO_H753ZI_SSD1306_I2C_ADDR + hex + default 0x3C if NUCLEO_H753ZI_SSD1306_ADDR_3C + default 0x3D if NUCLEO_H753ZI_SSD1306_ADDR_3D + default NUCLEO_H753ZI_SSD1306_ADDR_CUSTOM_VALUE if NUCLEO_H753ZI_SSD1306_ADDR_CUSTOM + +config NUCLEO_H753ZI_SSD1306_I2C_FREQUENCY + int "I2C Bus Frequency (Hz)" + default 400000 + range 10000 1000000 + help + I2C bus frequency for SSD1306 communication. + Recommended speeds: + - 100000 (100 kHz): Standard mode (safer, slower) + - 400000 (400 kHz): Fast mode (recommended) + - 1000000 (1 MHz): Fast mode plus (if supported by module) + Higher frequencies provide faster screen updates. + +config NUCLEO_H753ZI_SSD1306_POWER_PERCENT + int "Display Power/Brightness (%)" + default 100 + range 0 100 + help + Display power/brightness level as percentage. + - 0%: Display off + - 50%: Half brightness + - 100%: Maximum brightness (recommended) + Note: This translates to the SSD1306 contrast setting. + Higher values = brighter display but more power consumption. + +config NUCLEO_H753ZI_SSD1306_POWER_LEVEL + int + default 0 if NUCLEO_H753ZI_SSD1306_POWER_PERCENT = 0 + default 1 if NUCLEO_H753ZI_SSD1306_POWER_PERCENT <= 100 + help + Internal: Converts percentage to NuttX power level. + - 0 = off + - 1 = on (brightness controlled by contrast) + +choice + prompt "Display Resolution" + default NUCLEO_H753ZI_SSD1306_128X64 + help + Select your SSD1306 display resolution. + +config NUCLEO_H753ZI_SSD1306_128X64 + bool "128x64 pixels" + help + Standard 0.96" OLED display (128x64 pixels). + This is the most common size. + +config NUCLEO_H753ZI_SSD1306_128X32 + bool "128x32 pixels" + help + Smaller 0.91" OLED display (128x32 pixels). + +endchoice + +config NUCLEO_H753ZI_SSD1306_FB_SIZE + int + default 1024 if NUCLEO_H753ZI_SSD1306_128X64 + default 512 if NUCLEO_H753ZI_SSD1306_128X32 + help + Internal: Framebuffer size in bytes. + 128x64 = 1024 bytes (128*64/8) + 128x32 = 512 bytes (128*32/8) + +config NUCLEO_H753ZI_SSD1306_DEVPATH + string "Device Path" + default "/dev/lcd0" + help + Device node path for SSD1306 display. + For multiple displays use different paths: + - /dev/lcd0 (first display) + - /dev/lcd1 (second display) + - /dev/oled0, /dev/oled1 (alternative naming) + The path should match the device number below. + +config NUCLEO_H753ZI_SSD1306_DEVNO + int "Device Number" + default 0 + range 0 7 + help + LCD device number for registration. + This number is passed to the NuttX LCD driver and should + typically match the number in the device path: + - Device 0 -> /dev/lcd0 + - Device 1 -> /dev/lcd1 + - etc. + For multiple SSD1306 displays, use different numbers for each. + +endif + +endmenu + +endmenu + +config STM32_ROMFS + bool "Automount built-in ROMFS image" + default n + depends on FS_ROMFS + help + Select STM32_ROMFS_IMAGEFILE, STM32_ROMFS_DEV_MINOR, + STM32_ROMFS_MOUNTPOINT + +config STM32_ROMFS_DEV_MINOR + int "Minor number for the block device backing the data" + depends on STM32_ROMFS + default 64 + +config STM32_ROMFS_MOUNTPOINT + string "Mount point of the custom ROMFS image" + depends on STM32_ROMFS + default "/rom" + +config STM32_ROMFS_IMAGEFILE + string "ROMFS image file to include in the build" + depends on STM32_ROMFS + default "../../../rom.img" diff --git a/boards/arm/stm32h7/nucleo-h753zi/configs/button_driver/defconfig b/boards/arm/stm32h7/nucleo-h753zi/configs/button_driver/defconfig new file mode 100644 index 0000000000000..b53e6adf4f8bc --- /dev/null +++ b/boards/arm/stm32h7/nucleo-h753zi/configs/button_driver/defconfig @@ -0,0 +1,70 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_NSH_DISABLE_IFCONFIG is not set +# CONFIG_NSH_DISABLE_PS is not set +# CONFIG_STANDARD_SERIAL is not set +# CONFIG_STM32H7_USE_LEGACY_PINMAP is not set +CONFIG_ARCH="arm" +CONFIG_ARCH_BOARD="nucleo-h753zi" +CONFIG_ARCH_BOARD_NUCLEO_H753ZI=y +CONFIG_ARCH_CHIP="stm32h7" +CONFIG_ARCH_CHIP_STM32H753ZI=y +CONFIG_ARCH_CHIP_STM32H7=y +CONFIG_ARCH_CHIP_STM32H7_CORTEXM7=y +CONFIG_ARCH_IRQBUTTONS=y +CONFIG_ARCH_LEDS_CPU_ACTIVITY=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_ARMV7M_DCACHE=y +CONFIG_ARMV7M_DCACHE_WRITETHROUGH=y +CONFIG_ARMV7M_DTCM=y +CONFIG_ARMV7M_ICACHE=y +CONFIG_BOARD_LATE_INITIALIZE=y +CONFIG_BOARD_LOOPSPERMSEC=43103 +CONFIG_BUILTIN=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_EXAMPLES_BUTTONS=y +CONFIG_EXAMPLES_BUTTONS_NAME0="PC13" +CONFIG_EXAMPLES_BUTTONS_NAME1="PB1" +CONFIG_EXAMPLES_BUTTONS_NAME2="PD0" +CONFIG_EXAMPLES_BUTTONS_NAME3="PG4" +CONFIG_EXAMPLES_BUTTONS_NAME4="PD5" +CONFIG_EXAMPLES_BUTTONS_NAME5="PE6" +CONFIG_EXAMPLES_BUTTONS_NAME6="PE3" +CONFIG_EXAMPLES_BUTTONS_NAME7="PD12" +CONFIG_EXAMPLES_BUTTONS_NAMES=y +CONFIG_EXPERIMENTAL=y +CONFIG_HAVE_CXX=y +CONFIG_HAVE_CXXINITIALIZE=y +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_INPUT=y +CONFIG_INPUT_BUTTONS=y +CONFIG_INPUT_BUTTONS_LOWER=y +CONFIG_INTELHEX_BINARY=y +CONFIG_LINE_MAX=64 +CONFIG_MM_REGIONS=4 +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_READLINE=y +CONFIG_NUCLEO_H753ZI_BUTTON_COUNT=8 +CONFIG_NUCLEO_H753ZI_BUTTON_PINS="PB1,PD0,PG4,PD5,PE6,PE3,PD12" +CONFIG_NUCLEO_H753ZI_BUTTON_SUPPORT=y +CONFIG_PREALLOC_TIMERS=4 +CONFIG_RAM_SIZE=245760 +CONFIG_RAM_START=0x20010000 +CONFIG_RAW_BINARY=y +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_WAITPID=y +CONFIG_START_DAY=6 +CONFIG_START_MONTH=12 +CONFIG_START_YEAR=2011 +CONFIG_STM32H7_USART3=y +CONFIG_SYSTEM_NSH=y +CONFIG_TASK_NAME_SIZE=0 +CONFIG_USART3_SERIAL_CONSOLE=y +CONFIG_USERLED=y +CONFIG_USERLED_LOWER=y diff --git a/boards/arm/stm32h7/nucleo-h753zi/configs/nsh/defconfig b/boards/arm/stm32h7/nucleo-h753zi/configs/nsh/defconfig new file mode 100644 index 0000000000000..86a2f4ba622f4 --- /dev/null +++ b/boards/arm/stm32h7/nucleo-h753zi/configs/nsh/defconfig @@ -0,0 +1,54 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_ARCH_LEDS is not set +# CONFIG_NSH_DISABLE_IFCONFIG is not set +# CONFIG_NSH_DISABLE_PS is not set +# CONFIG_STANDARD_SERIAL is not set +# CONFIG_STM32H7_USE_LEGACY_PINMAP is not set +CONFIG_ARCH="arm" +CONFIG_ARCH_BOARD="nucleo-h753zi" +CONFIG_ARCH_BOARD_NUCLEO_H753ZI=y +CONFIG_ARCH_CHIP="stm32h7" +CONFIG_ARCH_CHIP_STM32H753ZI=y +CONFIG_ARCH_CHIP_STM32H7=y +CONFIG_ARCH_CHIP_STM32H7_CORTEXM7=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_ARMV7M_DCACHE=y +CONFIG_ARMV7M_DCACHE_WRITETHROUGH=y +CONFIG_ARMV7M_DTCM=y +CONFIG_ARMV7M_ICACHE=y +CONFIG_BOARD_LOOPSPERMSEC=43103 +CONFIG_BUILTIN=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_EXAMPLES_GPIO=y +CONFIG_EXAMPLES_LEDS=y +CONFIG_EXPERIMENTAL=y +CONFIG_HAVE_CXX=y +CONFIG_HAVE_CXXINITIALIZE=y +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_INTELHEX_BINARY=y +CONFIG_LINE_MAX=64 +CONFIG_MM_REGIONS=4 +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_READLINE=y +CONFIG_NUCLEO_H753ZI_GPIO_DRIVER=y +CONFIG_NUCLEO_H753ZI_LEDS_USER=y +CONFIG_PREALLOC_TIMERS=4 +CONFIG_RAM_SIZE=245760 +CONFIG_RAM_START=0x20010000 +CONFIG_RAW_BINARY=y +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_WAITPID=y +CONFIG_START_DAY=6 +CONFIG_START_MONTH=12 +CONFIG_START_YEAR=2011 +CONFIG_STM32H7_USART3=y +CONFIG_SYSTEM_NSH=y +CONFIG_TASK_NAME_SIZE=0 +CONFIG_USART3_SERIAL_CONSOLE=y diff --git a/boards/arm/stm32h7/nucleo-h753zi/configs/socketcan/defconfig b/boards/arm/stm32h7/nucleo-h753zi/configs/socketcan/defconfig new file mode 100644 index 0000000000000..9966b9c40e3bb --- /dev/null +++ b/boards/arm/stm32h7/nucleo-h753zi/configs/socketcan/defconfig @@ -0,0 +1,74 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_STANDARD_SERIAL is not set +# CONFIG_STM32H7_USE_LEGACY_PINMAP is not set +CONFIG_ALLOW_BSD_COMPONENTS=y +CONFIG_ARCH="arm" +CONFIG_ARCH_BOARD="nucleo-h753zi" +CONFIG_ARCH_BOARD_NUCLEO_H753ZI=y +CONFIG_ARCH_CHIP="stm32h7" +CONFIG_ARCH_CHIP_STM32H753ZI=y +CONFIG_ARCH_CHIP_STM32H7=y +CONFIG_ARCH_CHIP_STM32H7_CORTEXM7=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_ARMV7M_DCACHE=y +CONFIG_ARMV7M_DCACHE_WRITETHROUGH=y +CONFIG_ARMV7M_DTCM=y +CONFIG_ARMV7M_ICACHE=y +CONFIG_BOARD_LATE_INITIALIZE=y +CONFIG_BOARD_LOOPSPERMSEC=43103 +CONFIG_BUILTIN=y +CONFIG_CANUTILS_CANDUMP=y +CONFIG_CANUTILS_CANDUMP_STACKSIZE=4096 +CONFIG_CANUTILS_CANSEND=y +CONFIG_CANUTILS_LIBCANUTILS=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_EXPERIMENTAL=y +CONFIG_FDCAN1_ARBI_BITRATE=500000 +CONFIG_FDCAN1_DATA_BITRATE=500000 +CONFIG_FS_PROCFS=y +CONFIG_FS_PROCFS_REGISTER=y +CONFIG_HAVE_CXX=y +CONFIG_HAVE_CXXINITIALIZE=y +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_INTELHEX_BINARY=y +CONFIG_IOB_NBUFFERS=24 +CONFIG_IOB_THROTTLE=0 +CONFIG_LINE_MAX=64 +CONFIG_MM_REGIONS=4 +CONFIG_NET=y +CONFIG_NETDEV_CAN_BITRATE_IOCTL=y +CONFIG_NETDEV_CAN_STATE_IOCTL=y +CONFIG_NETDEV_IFINDEX=y +CONFIG_NETDOWN_NOTIFIER=y +CONFIG_NET_CAN=y +CONFIG_NET_CAN_ERRORS=y +CONFIG_NET_CAN_NOTIFIER=y +CONFIG_NET_CAN_SOCK_OPTS=y +CONFIG_NET_CAN_WRITE_BUFFERS=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_DISABLE_VCONFIG=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_READLINE=y +CONFIG_PREALLOC_TIMERS=4 +CONFIG_RAM_SIZE=245760 +CONFIG_RAM_START=0x20010000 +CONFIG_RAW_BINARY=y +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_HPWORK=y +CONFIG_SCHED_WAITPID=y +CONFIG_SPI=y +CONFIG_START_DAY=6 +CONFIG_START_MONTH=12 +CONFIG_START_YEAR=2011 +CONFIG_STM32H7_FDCAN1=y +CONFIG_STM32H7_FDCAN_HPWORK=y +CONFIG_STM32H7_USART3=y +CONFIG_SYSTEM_NSH=y +CONFIG_TASK_NAME_SIZE=0 +CONFIG_USART3_SERIAL_CONSOLE=y diff --git a/boards/arm/stm32h7/nucleo-h753zi/include/board.h b/boards/arm/stm32h7/nucleo-h753zi/include/board.h new file mode 100644 index 0000000000000..d5d38aae05a26 --- /dev/null +++ b/boards/arm/stm32h7/nucleo-h753zi/include/board.h @@ -0,0 +1,1309 @@ +/**************************************************************************** + * boards/arm/stm32h7/nucleo-h753zi/include/board.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************/ + +/* GPIO PINOUT MAPPING FOR NUCLEO-H753ZI (MB1364) + * + * Pin usage table for STM32H753ZI on Nucleo board's on-board peripherals. + * Pins not listed here are, by default, free for general use. + * + * Based on the following documents: + * - Schematics: 19250.pdf + * + * |---------------------------------------------------------------------| + * |Function/Peripheral | Logical Name | STM32 Pin | A.F | Notes | + * |---------------------------------------------------------------------| + * | User Button | B1_USER | PC13 | - | | + * | LED1 (Green) | LD1 | PB0 | - | | + * | LED2 (Orange) | LD2 | PE1 | - | | + * | LED3 (Red) | LD3 | PB14 | - | | + * | Ethernet | RMII_MDIO | PA2 | AF11 | | + * | | RMII_MDC | PC1 | AF11 | | + * | | RMII_TX_EN | PG11 | AF11 | | + * | | RMII_TXD0 | PG13 | AF11 | | + * | | RMII_TXD1 | PG12 | AF11 | | + * | | RMII_RXD0 | PC4 | AF11 | | + * | | RMII_RXD1 | PC5 | AF11 | | + * | | RMII_CRS_DV | PA7 | AF11 | | + * | | RMII_REF_CLK | PA1 | AF11 | | + * | USB VCP | VCP_TX | PD8 | AF7 | USART3_TX | + * | | VCP_RX | PD9 | AF7 | USART3_RX | + * | USB OTG_FS | USB_FS_VBUS | PA9 | AF10 | | + * | | USB_FS_ID | PA10 | AF10 | | + * | | USB_FS_N | PA11 | AF10 | | + * | | USB_FS_P | PA12 | AF10 | | + * | Debug (ST-LINK) | SWCLK | PA14 | AF0 | | + * | | SWDIO | PA13 | AF0 | | + * | Zio Connector(I2C) | A4 | PB9 | AF4 | I2C1_SDA | + * | | A5 | PB8 | AF4 | I2C1_SCL | + * | External Clock HSE | HSE_IN | PH0 | - | 8 MHz MCO | + * | | HSE_OUT | PH1 | - | Reserved X3 | + * |----------------------------------------------------------------------| + * + */ + +#ifndef __BOARDS_ARM_STM32H7_NUCLEO_H753ZI_INCLUDE_BOARD_H +#define __BOARDS_ARM_STM32H7_NUCLEO_H753ZI_INCLUDE_BOARD_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#ifndef __ASSEMBLY__ +# include +#endif + +/* Do not include STM32 H7 header files here */ + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * SECTION 1: CLOCK CONFIGURATION + ****************************************************************************/ + +/* Oscillator Frequency Definitions */ + +#define STM32_HSI_FREQUENCY 64000000ul +#define STM32_CSI_FREQUENCY 4000000ul +#define STM32_LSI_FREQUENCY 32000ul +#define STM32_LSE_FREQUENCY 32768ul + +#ifdef CONFIG_NUCLEO_H753ZI_HSE_25MHZ +# define STM32_HSE_FREQUENCY 25000000ul +#else +# define STM32_HSE_FREQUENCY 8000000ul +#endif + +/* PLL Configuration + * + * Main PLL Configuration. + * + * PLL source is HSE + * + * When STM32_HSE_FREQUENCY / PLLM <= 2MHz VCOL must be selected. + * VCOH otherwise. + * + * PLL_VCOx = (STM32_HSE_FREQUENCY / PLLM) * PLLN + * Subject to: + * + * 1 <= PLLM <= 63 + * 4 <= PLLN <= 512 + * 150 MHz <= PLL_VCOL <= 420MHz + * 192 MHz <= PLL_VCOH <= 836MHz + * + * SYSCLK = PLL_VCO / PLLP + * CPUCLK = SYSCLK / D1CPRE + * Subject to + * + * PLLP1 = {2, 4, 6, 8, ..., 128} + * PLLP2,3 = {2, 3, 4, ..., 128} + * CPUCLK <= 480 MHz + */ + +#define STM32_BOARD_USEHSE +#define STM32_PLLCFG_PLLSRC RCC_PLLCKSELR_PLLSRC_HSE + +#ifdef CONFIG_NUCLEO_H753ZI_HSE_25MHZ + +/* PLL1 - 25 MHz HSE input, enable DIVP, DIVQ, DIVR + * + * CORRECTED: VCO limited to 836 MHz, SYSCLK limited to 400 MHz (VOS1) + * + * PLL1_input = 25 MHz / 5 = 5 MHz (within 4-8 MHz range) + * PLL1_VCO = 5 MHz * 160 = 800 MHz (within 192-836 MHz) + * + * PLL1P = PLL1_VCO/2 = 800 MHz / 2 = 400 MHz (SYSCLK) + * PLL1Q = PLL1_VCO/4 = 800 MHz / 4 = 200 MHz (SPI123, SDMMC) + * PLL1R = PLL1_VCO/4 = 800 MHz / 4 = 200 MHz + * + * Note: Same 400 MHz SYSCLK as 8 MHz config (VOS1 safe, NuttX default) + */ + +#define STM32_PLLCFG_PLL1CFG (RCC_PLLCFGR_PLL1VCOSEL_WIDE| \ + RCC_PLLCFGR_PLL1RGE_4_8_MHZ| \ + RCC_PLLCFGR_DIVP1EN| \ + RCC_PLLCFGR_DIVQ1EN| \ + RCC_PLLCFGR_DIVR1EN) +#define STM32_PLLCFG_PLL1M RCC_PLLCKSELR_DIVM1(5) +#define STM32_PLLCFG_PLL1N RCC_PLL1DIVR_N1(160) +#define STM32_PLLCFG_PLL1P RCC_PLL1DIVR_P1(2) +#define STM32_PLLCFG_PLL1Q RCC_PLL1DIVR_Q1(4) +#define STM32_PLLCFG_PLL1R RCC_PLL1DIVR_R1(4) + +#define STM32_VCO1_FREQUENCY ((STM32_HSE_FREQUENCY / 5) * 160) +#define STM32_PLL1P_FREQUENCY (STM32_VCO1_FREQUENCY / 2) +#define STM32_PLL1Q_FREQUENCY (STM32_VCO1_FREQUENCY / 4) +#define STM32_PLL1R_FREQUENCY (STM32_VCO1_FREQUENCY / 4) + +/* PLL2 - 25 MHz HSE input, enable DIVP, DIVQ, DIVR + * + * CORRECTED: Input range (was 4-8 MHz, needs 8-16 MHz) and FDCAN clock + * + * PLL2_input = 25 MHz / 2 = 12.5 MHz (within 8-16 MHz range) + * PLL2_VCO = 12.5 MHz * 48 = 600 MHz (within 192-836 MHz) + * + * PLL2P = PLL2_VCO/8 = 600 MHz / 8 = 75 MHz (ADC, SPI45) + * PLL2Q = PLL2_VCO/24 = 600 MHz / 24 = 25 MHz (FDCAN - not usedHSE direct) + * PLL2R = PLL2_VCO/3 = 600 MHz / 3 = 200 MHz + * + * Note: FDCAN uses HSE directly (25 MHz) for this configuration, + * but PLL2Q is configured to 25 MHz for consistency + */ + +#define STM32_PLLCFG_PLL2CFG (RCC_PLLCFGR_PLL2VCOSEL_WIDE| \ + RCC_PLLCFGR_PLL2RGE_8_16_MHZ| \ + RCC_PLLCFGR_DIVP2EN| \ + RCC_PLLCFGR_DIVQ2EN| \ + RCC_PLLCFGR_DIVR2EN) +#define STM32_PLLCFG_PLL2M RCC_PLLCKSELR_DIVM2(2) +#define STM32_PLLCFG_PLL2N RCC_PLL2DIVR_N2(48) +#define STM32_PLLCFG_PLL2P RCC_PLL2DIVR_P2(8) +#define STM32_PLLCFG_PLL2Q RCC_PLL2DIVR_Q2(24) +#define STM32_PLLCFG_PLL2R RCC_PLL2DIVR_R2(3) + +#define STM32_VCO2_FREQUENCY ((STM32_HSE_FREQUENCY / 2) * 48) +#define STM32_PLL2P_FREQUENCY (STM32_VCO2_FREQUENCY / 8) +#define STM32_PLL2Q_FREQUENCY (STM32_VCO2_FREQUENCY / 24) +#define STM32_PLL2R_FREQUENCY (STM32_VCO2_FREQUENCY / 3) + +/* PLL3 - 25 MHz HSE input, enable DIVP, DIVQ, DIVR + * + * CORRECTED: Input frequency limited to 8-16 MHz range + * + * PLL3_input = 25 MHz / 2 = 12.5 MHz (within 8-16 MHz range) + * PLL3_VCO = 12.5 MHz * 64 = 800 MHz (within 192-836 MHz) + * + * PLL3P = PLL3_VCO/2 = 800 MHz / 2 = 400 MHz + * PLL3Q = PLL3_VCO/32 = 800 MHz / 32 = 25 MHz + * PLL3R = PLL3_VCO/20 = 800 MHz / 20 = 40 MHz + */ + +#define STM32_PLLCFG_PLL3CFG (RCC_PLLCFGR_PLL3VCOSEL_WIDE| \ + RCC_PLLCFGR_PLL3RGE_8_16_MHZ| \ + RCC_PLLCFGR_DIVP3EN| \ + RCC_PLLCFGR_DIVQ3EN| \ + RCC_PLLCFGR_DIVR3EN) +#define STM32_PLLCFG_PLL3M RCC_PLLCKSELR_DIVM3(2) +#define STM32_PLLCFG_PLL3N RCC_PLL3DIVR_N3(64) +#define STM32_PLLCFG_PLL3P RCC_PLL3DIVR_P3(2) +#define STM32_PLLCFG_PLL3Q RCC_PLL3DIVR_Q3(32) +#define STM32_PLLCFG_PLL3R RCC_PLL3DIVR_R3(20) + +#define STM32_VCO3_FREQUENCY ((STM32_HSE_FREQUENCY / 2) * 64) +#define STM32_PLL3P_FREQUENCY (STM32_VCO3_FREQUENCY / 2) +#define STM32_PLL3Q_FREQUENCY (STM32_VCO3_FREQUENCY / 32) +#define STM32_PLL3R_FREQUENCY (STM32_VCO3_FREQUENCY / 20) + +#else /* CONFIG_NUCLEO_H753ZI_HSE_8MHZ (default) */ + +/* PLL1 - 8 MHz HSE input, enable DIVP, DIVQ, DIVR + * + * Calculation for 8 MHz HSE: + * Step 1: PLL1 input = HSE / DIVM1 = 8 MHz / 1 = 8 MHz + * Range: 8 MHz is within 4-16 MHz (RCC_PLLCFGR_PLL1RGE_4_8_MHZ) + * + * Step 2: VCO = PLL1_input * DIVN1 = 8 MHz * 100 = 800 MHz + * Range: 800 MHz is within 192-836 MHz (VCOH) + * + * PLL1P = VCO / DIVP1 = 800 MHz / 2 = 400 MHz (SYSCLK) + * PLL1Q = VCO / DIVQ1 = 800 MHz / 4 = 200 MHz + * PLL1R = VCO / DIVR1 = 800 MHz / 4 = 200 MHz + */ + +#define STM32_PLLCFG_PLL1CFG (RCC_PLLCFGR_PLL1VCOSEL_WIDE| \ + RCC_PLLCFGR_PLL1RGE_4_8_MHZ| \ + RCC_PLLCFGR_DIVP1EN| \ + RCC_PLLCFGR_DIVQ1EN| \ + RCC_PLLCFGR_DIVR1EN) +#define STM32_PLLCFG_PLL1M RCC_PLLCKSELR_DIVM1(1) +#define STM32_PLLCFG_PLL1N RCC_PLL1DIVR_N1(100) +#define STM32_PLLCFG_PLL1P RCC_PLL1DIVR_P1(2) +#define STM32_PLLCFG_PLL1Q RCC_PLL1DIVR_Q1(4) +#define STM32_PLLCFG_PLL1R RCC_PLL1DIVR_R1(4) + +#define STM32_VCO1_FREQUENCY ((STM32_HSE_FREQUENCY / 1) * 100) +#define STM32_PLL1P_FREQUENCY (STM32_VCO1_FREQUENCY / 2) +#define STM32_PLL1Q_FREQUENCY (STM32_VCO1_FREQUENCY / 4) +#define STM32_PLL1R_FREQUENCY (STM32_VCO1_FREQUENCY / 4) + +/* PLL2 - 8 MHz HSE input, enable DIVP, DIVQ, DIVR + * + * CRITICAL: PLL2Q must output 25 MHz for FDCAN compatibility + * + * Calculation for 8 MHz HSE: + * Step 1: PLL2 input = HSE / DIVM2 = 8 MHz / 1 = 8 MHz + * Range: 8 MHz is within 4-16 MHz (RCC_PLLCFGR_PLL2RGE_4_8_MHZ) + * + * Step 2: VCO = PLL2_input * DIVN2 = 8 MHz * 75 = 600 MHz + * Range: 600 MHz is within 192-836 MHz (VCOH) + * + * PLL2P = VCO / DIVP2 = 600 MHz / 8 = 75 MHz (ADC, SPI45) + * PLL2Q = VCO / DIVQ2 = 600 MHz / 24 = 25 MHz (FDCAN kernel clock) + * PLL2R = VCO / DIVR2 = 600 MHz / 3 = 200 MHz + */ + +#define STM32_PLLCFG_PLL2CFG (RCC_PLLCFGR_PLL2VCOSEL_WIDE| \ + RCC_PLLCFGR_PLL2RGE_4_8_MHZ| \ + RCC_PLLCFGR_DIVP2EN| \ + RCC_PLLCFGR_DIVQ2EN| \ + RCC_PLLCFGR_DIVR2EN) + +#define STM32_PLLCFG_PLL2M RCC_PLLCKSELR_DIVM2(1) +#define STM32_PLLCFG_PLL2N RCC_PLL2DIVR_N2(75) +#define STM32_PLLCFG_PLL2P RCC_PLL2DIVR_P2(8) +#define STM32_PLLCFG_PLL2Q RCC_PLL2DIVR_Q2(24) +#define STM32_PLLCFG_PLL2R RCC_PLL2DIVR_R2(3) + +#define STM32_VCO2_FREQUENCY ((STM32_HSE_FREQUENCY / 1) * 75) +#define STM32_PLL2P_FREQUENCY (STM32_VCO2_FREQUENCY / 8) +#define STM32_PLL2Q_FREQUENCY (STM32_VCO2_FREQUENCY / 24) +#define STM32_PLL2R_FREQUENCY (STM32_VCO2_FREQUENCY / 3) + +/* PLL3 - 8 MHz HSE input, enable DIVP, DIVQ, DIVR + * + * NOTE: PLL3 is not used for 8 MHz HSE configuration + * FDCAN clock is provided by PLL2Q (25 MHz) instead + * However, PLL3 must be defined for NuttX RCC code compatibility + * + * Step 1: PLL3 input = HSE / DIVM3 = 8 MHz / 2 = 4 MHz + * Range: 4 MHz is within 2-16 MHz (RCC_PLLCFGR_PLL3RGE_2_4_MHZ) + * + * Step 2: VCO = PLL3_input * DIVN3 = 4 MHz * 100 = 400 MHz + * Range: 400 MHz is within 192-836 MHz (VCOH) + * + * PLL3P = VCO / DIVP3 = 400 MHz / 2 = 200 MHz + * PLL3Q = VCO / DIVQ3 = 400 MHz / 16 = 25 MHz + * PLL3R = VCO / DIVR3 = 400 MHz / 10 = 40 MHz + */ + +#define STM32_PLLCFG_PLL3CFG (RCC_PLLCFGR_PLL3VCOSEL_WIDE| \ + RCC_PLLCFGR_PLL3RGE_2_4_MHZ| \ + RCC_PLLCFGR_DIVP3EN| \ + RCC_PLLCFGR_DIVQ3EN| \ + RCC_PLLCFGR_DIVR3EN) + +#define STM32_PLLCFG_PLL3M RCC_PLLCKSELR_DIVM3(2) +#define STM32_PLLCFG_PLL3N RCC_PLL3DIVR_N3(100) +#define STM32_PLLCFG_PLL3P RCC_PLL3DIVR_P3(2) +#define STM32_PLLCFG_PLL3Q RCC_PLL3DIVR_Q3(16) +#define STM32_PLLCFG_PLL3R RCC_PLL3DIVR_R3(10) + +#define STM32_VCO3_FREQUENCY ((STM32_HSE_FREQUENCY / 2) * 100) +#define STM32_PLL3P_FREQUENCY (STM32_VCO3_FREQUENCY / 2) +#define STM32_PLL3Q_FREQUENCY (STM32_VCO3_FREQUENCY / 16) +#define STM32_PLL3R_FREQUENCY (STM32_VCO3_FREQUENCY / 10) + +#endif /* CONFIG_NUCLEO_H753ZI_HSE_25MHZ */ + +/* System Clock Configuration + * + * SYSCLK = PLL1P + * CPUCLK = SYSCLK / 1 + */ + +#define STM32_RCC_D1CFGR_D1CPRE (RCC_D1CFGR_D1CPRE_SYSCLK) +#define STM32_SYSCLK_FREQUENCY (STM32_PLL1P_FREQUENCY) +#define STM32_CPUCLK_FREQUENCY (STM32_SYSCLK_FREQUENCY / 1) + +/* AHB and APB Clock Configuration + * + * AHB clock (HCLK) is SYSCLK/2 + * HCLK1 = HCLK2 = HCLK3 = HCLK4 + */ + +#define STM32_RCC_D1CFGR_HPRE RCC_D1CFGR_HPRE_SYSCLKd2 +#define STM32_ACLK_FREQUENCY (STM32_SYSCLK_FREQUENCY / 2) +#define STM32_HCLK_FREQUENCY (STM32_SYSCLK_FREQUENCY / 2) + +/* APB1 clock (PCLK1) is HCLK/2 */ + +#define STM32_RCC_D2CFGR_D2PPRE1 RCC_D2CFGR_D2PPRE1_HCLKd2 +#define STM32_PCLK1_FREQUENCY (STM32_HCLK_FREQUENCY/2) + +/* APB2 clock (PCLK2) is HCLK/2 */ + +#define STM32_RCC_D2CFGR_D2PPRE2 RCC_D2CFGR_D2PPRE2_HCLKd2 +#define STM32_PCLK2_FREQUENCY (STM32_HCLK_FREQUENCY/2) + +/* APB3 clock (PCLK3) is HCLK/2 */ + +#define STM32_RCC_D1CFGR_D1PPRE RCC_D1CFGR_D1PPRE_HCLKd2 +#define STM32_PCLK3_FREQUENCY (STM32_HCLK_FREQUENCY/2) + +/* APB4 clock (PCLK4) is HCLK/2 */ + +#define STM32_RCC_D3CFGR_D3PPRE RCC_D3CFGR_D3PPRE_HCLKd2 +#define STM32_PCLK4_FREQUENCY (STM32_HCLK_FREQUENCY/2) + +/* Timer Clock Frequencies + * + * Timers driven from APB1 will be twice PCLK1 + */ + +#define STM32_APB1_TIM2_CLKIN (2*STM32_PCLK1_FREQUENCY) +#define STM32_APB1_TIM3_CLKIN (2*STM32_PCLK1_FREQUENCY) +#define STM32_APB1_TIM4_CLKIN (2*STM32_PCLK1_FREQUENCY) +#define STM32_APB1_TIM5_CLKIN (2*STM32_PCLK1_FREQUENCY) +#define STM32_APB1_TIM6_CLKIN (2*STM32_PCLK1_FREQUENCY) +#define STM32_APB1_TIM7_CLKIN (2*STM32_PCLK1_FREQUENCY) +#define STM32_APB1_TIM12_CLKIN (2*STM32_PCLK1_FREQUENCY) +#define STM32_APB1_TIM13_CLKIN (2*STM32_PCLK1_FREQUENCY) +#define STM32_APB1_TIM14_CLKIN (2*STM32_PCLK1_FREQUENCY) + +/* Timers driven from APB2 will be twice PCLK2 */ + +#define STM32_APB2_TIM1_CLKIN (2*STM32_PCLK2_FREQUENCY) +#define STM32_APB2_TIM8_CLKIN (2*STM32_PCLK2_FREQUENCY) +#define STM32_APB2_TIM15_CLKIN (2*STM32_PCLK2_FREQUENCY) +#define STM32_APB2_TIM16_CLKIN (2*STM32_PCLK2_FREQUENCY) +#define STM32_APB2_TIM17_CLKIN (2*STM32_PCLK2_FREQUENCY) + +/* Kernel Clock Configuration + * + * Note: Refer to Table 54 in STM32H7 Reference Manual (RM0433) + */ + +/* According to the STM32H753ZI is recommended to use PCLK for I2C bus. + * I2C123 clock source - PCLK1 (100 MHz) + * #define STM32_RCC_D2CCIP2R_I2C123SRC RCC_D2CCIP2R_I2C123SEL_PCLK1 + * + * I2C4 clock source - PCLK4 (100 MHz) + * #define STM32_RCC_D3CCIPR_I2C4SRC RCC_D3CCIPR_I2C4SEL_PCLK4 + * + * However, it seems NuttX has a bug in the I2C driver that only allow I2C + * using HSI as clock source and it has to be configured at 16 MHz. + * + * Hence, this board will use the following workaround until the NuttX + * I2C driver is fixed. + */ + +#define STM32_HSI_FREQUENCY 16000000ul /* 64MHz / 4 = 16MHz */ + +/* I2C123 clock source - HSI (16 MHz) - Required by NuttX I2C driver */ + +#define STM32_RCC_D2CCIP2R_I2C123SRC RCC_D2CCIP2R_I2C123SEL_HSI + +/* I2C4 clock source - HSI (16 MHz) - Required by NuttX I2C driver */ + +#define STM32_RCC_D3CCIPR_I2C4SRC RCC_D3CCIPR_I2C4SEL_HSI + +/* SPI123 clock source - PLL1Q */ + +#define STM32_RCC_D2CCIP1R_SPI123SRC RCC_D2CCIP1R_SPI123SEL_PLL1 + +/* SPI45 clock source - PLL2P */ + +#define STM32_RCC_D2CCIP1R_SPI45SRC RCC_D2CCIP1R_SPI45SEL_PLL2 + +/* SPI6 clock source - PCLK4 */ + +#define STM32_RCC_D3CCIPR_SPI6SRC RCC_D3CCIPR_SPI6SEL_PCLK4 + +/* USB 1 and 2 clock source - HSI48 */ + +#define STM32_RCC_D2CCIP2R_USBSRC RCC_D2CCIP2R_USBSEL_HSI48 + +/* ADC 1 2 3 clock source - PLL2P */ + +#define STM32_RCC_D3CCIPR_ADCSRC RCC_D3CCIPR_ADCSEL_PLL2 + +/* FDCAN 1 2 clock source selection based on HSE config */ + +#ifdef CONFIG_NUCLEO_H753ZI_HSE_25MHZ +/* FDCAN 1 2 clock source - HSE (25 MHz direct) */ +# define STM32_RCC_D2CCIP1R_FDCANSEL RCC_D2CCIP1R_FDCANSEL_HSE +# define STM32_FDCANCLK STM32_HSE_FREQUENCY +#else +/* FDCAN 1 2 clock source - PLL2Q (25 MHz for CAN compliance) */ +# define STM32_RCC_D2CCIP1R_FDCANSEL RCC_D2CCIP1R_FDCANSEL_PLL2 +# define STM32_FDCANCLK STM32_PLL2Q_FREQUENCY +#endif + +/* SDMMC 1 2 clock source - PLL1Q */ + +#define STM32_RCC_D1CCIPR_SDMMCSEL RCC_D1CCIPR_SDMMC_PLL1 + +/* FMC clock source - HCLK */ + +#define BOARD_FMC_CLK RCC_D1CCIPR_FMCSEL_HCLK + +/* Flash Configuration ******************************************************/ + +/* FLASH wait states + * + * ------------ ---------- ----------- + * Vcore MAX ACLK WAIT STATES + * ------------ ---------- ----------- + * 1.15-1.26 V 70 MHz 0 + * (VOS1 level) 140 MHz 1 + * 210 MHz 2 + * 275 MHz 3 + * 480 MHz 4 + * 1.05-1.15 V 55 MHz 0 + * (VOS2 level) 110 MHz 1 + * 165 MHz 2 + * 220 MHz 3 + * 0.95-1.05 V 45 MHz 0 + * (VOS3 level) 90 MHz 1 + * 135 MHz 2 + * 180 MHz 3 + * 225 MHz 4 + * ------------ ---------- ----------- + */ + +#define BOARD_FLASH_WAITSTATES 4 + +/**************************************************************************** + * SECTION 2: COMMUNICATION BUSES + ****************************************************************************/ + +/**************************************************************************** + * UART/USART Configuration + ****************************************************************************/ + +/* USART3 (Nucleo Virtual Console) */ + +#define GPIO_USART3_RX (GPIO_USART3_RX_3 | GPIO_SPEED_100MHz) /* PD9 */ +#define GPIO_USART3_TX (GPIO_USART3_TX_3 | GPIO_SPEED_100MHz) /* PD8 */ + +/* USART6 (Arduino Serial Shield) */ + +#define GPIO_USART6_RX (GPIO_USART6_RX_2 | GPIO_SPEED_100MHz) /* PG9 */ +#define GPIO_USART6_TX (GPIO_USART6_TX_2 | GPIO_SPEED_100MHz) /* PG14 */ + +/* UART/USART DMA Mappings */ + +#define DMAMAP_USART3_RX DMAMAP_DMA12_USART3RX_0 +#define DMAMAP_USART3_TX DMAMAP_DMA12_USART3TX_1 +#define DMAMAP_USART6_RX DMAMAP_DMA12_USART6RX_1 +#define DMAMAP_USART6_TX DMAMAP_DMA12_USART6TX_0 + +/* TODO: Add USART1, USART2, UART4, UART5, UART7, UART8 configurations */ + +/**************************************************************************** + * SPI Configuration + ****************************************************************************/ + +/* SPI GPIO Definitions - Based on Kconfig selections */ + +#define GPIO_SPI_CS_SPEED GPIO_SPEED_50MHz /* CS pin speed */ + +/* SPI1 Pin Configurations */ + +#ifdef CONFIG_NUCLEO_H753ZI_SPI1_ENABLE +# ifdef CONFIG_NUCLEO_H753ZI_SPI1_PINSET_1 +# define GPIO_SPI1_SCK GPIO_SPI1_SCK_1 /* PA5 */ +# define GPIO_SPI1_MISO GPIO_SPI1_MISO_1 /* PA6 */ +# define GPIO_SPI1_MOSI GPIO_SPI1_MOSI_1 /* PA7 */ +# elif defined(CONFIG_NUCLEO_H753ZI_SPI1_PINSET_2) +# define GPIO_SPI1_SCK GPIO_SPI1_SCK_2 /* PB3 */ +# define GPIO_SPI1_MISO GPIO_SPI1_MISO_2 /* PB4 */ +# define GPIO_SPI1_MOSI GPIO_SPI1_MOSI_2 /* PB5 */ +# elif defined(CONFIG_NUCLEO_H753ZI_SPI1_PINSET_3) +# define GPIO_SPI1_SCK GPIO_SPI1_SCK_3 /* PG11 */ +# define GPIO_SPI1_MISO GPIO_SPI1_MISO_3 /* PG9 */ +# define GPIO_SPI1_MOSI GPIO_SPI1_MOSI_3 /* PD7 */ +# endif +#endif /* CONFIG_NUCLEO_H753ZI_SPI1_ENABLE */ + +/* SPI2 Pin Configurations */ + +#ifdef CONFIG_NUCLEO_H753ZI_SPI2_ENABLE +# ifdef CONFIG_NUCLEO_H753ZI_SPI2_PINSET_1 +# define GPIO_SPI2_SCK GPIO_SPI2_SCK_4 /* PB13 */ +# define GPIO_SPI2_MISO GPIO_SPI2_MISO_1 /* PB14 */ +# define GPIO_SPI2_MOSI GPIO_SPI2_MOSI_1 /* PB15 */ +# elif defined(CONFIG_NUCLEO_H753ZI_SPI2_PINSET_2) +# define GPIO_SPI2_SCK GPIO_SPI2_SCK_1 /* PA12 */ +# define GPIO_SPI2_MISO GPIO_SPI2_MISO_2 /* PC2 */ +# define GPIO_SPI2_MOSI GPIO_SPI2_MOSI_2 /* PC1 */ +# elif defined(CONFIG_NUCLEO_H753ZI_SPI2_PINSET_3) +# define GPIO_SPI2_SCK GPIO_SPI2_SCK_5 /* PD3 */ +# define GPIO_SPI2_MISO GPIO_SPI2_MISO_2 /* PC2 */ +# define GPIO_SPI2_MOSI GPIO_SPI2_MOSI_3 /* PC3 */ +# endif +#endif /* CONFIG_NUCLEO_H753ZI_SPI2_ENABLE */ + +/* SPI3 Pin Configurations */ + +#ifdef CONFIG_NUCLEO_H753ZI_SPI3_ENABLE +# ifdef CONFIG_NUCLEO_H753ZI_SPI3_PINSET_1 +# define GPIO_SPI3_SCK GPIO_SPI3_SCK_1 /* PB3 */ +# define GPIO_SPI3_MISO GPIO_SPI3_MISO_1 /* PB4 */ +# define GPIO_SPI3_MOSI GPIO_SPI3_MOSI_1 /* PB2 */ +# elif defined(CONFIG_NUCLEO_H753ZI_SPI3_PINSET_2) +# define GPIO_SPI3_SCK GPIO_SPI3_SCK_2 /* PC10 */ +# define GPIO_SPI3_MISO GPIO_SPI3_MISO_2 /* PC11 */ +# define GPIO_SPI3_MOSI GPIO_SPI3_MOSI_2 /* PC12 */ +# elif defined(CONFIG_NUCLEO_H753ZI_SPI3_PINSET_3) +# define GPIO_SPI3_SCK GPIO_SPI3_SCK_3 /* PB3 */ +# define GPIO_SPI3_MISO GPIO_SPI3_MISO_3 /* PB4 */ +# define GPIO_SPI3_MOSI GPIO_SPI3_MOSI_3 /* PB5 */ +# endif +#endif /* CONFIG_NUCLEO_H753ZI_SPI3_ENABLE */ + +/* SPI4 Pin Configurations */ + +#ifdef CONFIG_NUCLEO_H753ZI_SPI4_ENABLE +# ifdef CONFIG_NUCLEO_H753ZI_SPI4_PINSET_1 +# define GPIO_SPI4_SCK GPIO_SPI4_SCK_1 /* PE12 */ +# define GPIO_SPI4_MISO GPIO_SPI4_MISO_1 /* PE13 */ +# define GPIO_SPI4_MOSI GPIO_SPI4_MOSI_1 /* PE14 */ +# elif defined(CONFIG_NUCLEO_H753ZI_SPI4_PINSET_2) +# define GPIO_SPI4_SCK GPIO_SPI4_SCK_2 /* PE2 */ +# define GPIO_SPI4_MISO GPIO_SPI4_MISO_2 /* PE5 */ +# define GPIO_SPI4_MOSI GPIO_SPI4_MOSI_2 /* PE6 */ +# endif +#endif /* CONFIG_NUCLEO_H753ZI_SPI4_ENABLE */ + +/* SPI5 Pin Configurations */ + +#ifdef CONFIG_NUCLEO_H753ZI_SPI5_ENABLE +# ifdef CONFIG_NUCLEO_H753ZI_SPI5_PINSET_1 +# define GPIO_SPI5_SCK GPIO_SPI5_SCK_1 /* PF7 */ +# define GPIO_SPI5_MISO GPIO_SPI5_MISO_1 /* PF8 */ +# define GPIO_SPI5_MOSI GPIO_SPI5_MOSI_1 /* PF11 */ +# elif defined(CONFIG_NUCLEO_H753ZI_SPI5_PINSET_2) +# define GPIO_SPI5_SCK GPIO_SPI5_SCK_2 /* PF7 */ +# define GPIO_SPI5_MISO GPIO_SPI5_MISO_2 /* PF8 */ +# define GPIO_SPI5_MOSI GPIO_SPI5_MOSI_2 /* PF9 */ +# elif defined(CONFIG_NUCLEO_H753ZI_SPI5_PINSET_3) +# define GPIO_SPI5_SCK GPIO_SPI5_SCK_3 /* PH6 */ +# define GPIO_SPI5_MISO GPIO_SPI5_MISO_3 /* PH7 */ +# define GPIO_SPI5_MOSI GPIO_SPI5_MOSI_3 /* PF11 */ +# elif defined(CONFIG_NUCLEO_H753ZI_SPI5_PINSET_4) +# define GPIO_SPI5_SCK GPIO_SPI5_SCK_4 /* PK0 */ +# define GPIO_SPI5_MISO GPIO_SPI5_MISO_4 /* PJ11 */ +# define GPIO_SPI5_MOSI GPIO_SPI5_MOSI_4 /* PJ10 */ +# endif +#endif /* CONFIG_NUCLEO_H753ZI_SPI5_ENABLE */ + +/* SPI6 Pin Configurations */ + +#ifdef CONFIG_NUCLEO_H753ZI_SPI6_ENABLE +# ifdef CONFIG_NUCLEO_H753ZI_SPI6_PINSET_1 +# define GPIO_SPI6_SCK GPIO_SPI6_SCK_1 /* PG13 */ +# define GPIO_SPI6_MISO GPIO_SPI6_MISO_1 /* PG12 */ +# define GPIO_SPI6_MOSI GPIO_SPI6_MOSI_1 /* PG14 */ +# elif defined(CONFIG_NUCLEO_H753ZI_SPI6_PINSET_2) +# define GPIO_SPI6_SCK GPIO_SPI6_SCK_2 /* PA5 */ +# define GPIO_SPI6_MISO GPIO_SPI6_MISO_2 /* PA6 */ +# define GPIO_SPI6_MOSI GPIO_SPI6_MOSI_2 /* PA7 */ +# elif defined(CONFIG_NUCLEO_H753ZI_SPI6_PINSET_3) +# define GPIO_SPI6_SCK GPIO_SPI6_SCK_3 /* PB3 */ +# define GPIO_SPI6_MISO GPIO_SPI6_MISO_3 /* PB4 */ +# define GPIO_SPI6_MOSI GPIO_SPI6_MOSI_3 /* PB5 */ +# endif +#endif /* CONFIG_NUCLEO_H753ZI_SPI6_ENABLE */ + +/* SPI DMA Mappings */ + +#define DMAMAP_SPI3_RX DMAMAP_DMA12_SPI3RX_0 /* DMA1 */ +#define DMAMAP_SPI3_TX DMAMAP_DMA12_SPI3TX_0 /* DMA1 */ + +/**************************************************************************** + * I2C Pin Configurations + ****************************************************************************/ + +/* I2C1 Pin Configurations */ + +#ifdef CONFIG_NUCLEO_H753ZI_I2C1_ENABLE + +# ifdef CONFIG_NUCLEO_H753ZI_I2C1_PINSET_1 + /* AF4: I2C1 on PB6/PB7 (Arduino D10/D9) */ +# define GPIO_I2C1_SCL GPIO_I2C1_SCL_1 /* PB6 - AF4 */ +# define GPIO_I2C1_SDA GPIO_I2C1_SDA_1 /* PB7 - AF4 */ + +# elif defined(CONFIG_NUCLEO_H753ZI_I2C1_PINSET_2) + /* AF4: I2C1 on PB8/PB9 (Morpho) */ +# define GPIO_I2C1_SCL GPIO_I2C1_SCL_2 /* PB8 - AF4 */ +# define GPIO_I2C1_SDA GPIO_I2C1_SDA_2 /* PB9 - AF4 */ +# endif + +# define I2C1_FREQUENCY CONFIG_NUCLEO_H753ZI_I2C1_DEFAULT_FREQUENCY + +#endif /* CONFIG_NUCLEO_H753ZI_I2C1_ENABLE */ + +/* I2C2 Pin Configurations */ + +#ifdef CONFIG_NUCLEO_H753ZI_I2C2_ENABLE + +# ifdef CONFIG_NUCLEO_H753ZI_I2C2_PINSET_1 + /* AF4: I2C2 on PB10/PB11 */ +# define GPIO_I2C2_SCL GPIO_I2C2_SCL_1 /* PB10 - AF4 */ +# define GPIO_I2C2_SDA GPIO_I2C2_SDA_1 /* PB11 - AF4 */ + +# elif defined(CONFIG_NUCLEO_H753ZI_I2C2_PINSET_2) + /* AF4: I2C2 on PF1/PF0 */ +# define GPIO_I2C2_SCL GPIO_I2C2_SCL_2 /* PF1 - AF4 */ +# define GPIO_I2C2_SDA GPIO_I2C2_SDA_2 /* PF0 - AF4 */ + +# elif defined(CONFIG_NUCLEO_H753ZI_I2C2_PINSET_3) + /* AF4: I2C2 on PH4/PH5 */ +# define GPIO_I2C2_SCL GPIO_I2C2_SCL_3 /* PH4 - AF4 */ +# define GPIO_I2C2_SDA GPIO_I2C2_SDA_3 /* PH5 - AF4 */ +# endif + +# define I2C2_FREQUENCY CONFIG_NUCLEO_H753ZI_I2C2_DEFAULT_FREQUENCY + +#endif /* CONFIG_NUCLEO_H753ZI_I2C2_ENABLE */ + +/* I2C3 Pin Configurations */ + +#ifdef CONFIG_NUCLEO_H753ZI_I2C3_ENABLE + +# ifdef CONFIG_NUCLEO_H753ZI_I2C3_PINSET_1 + /* AF4: I2C3 on PA8/PC9 */ +# define GPIO_I2C3_SCL GPIO_I2C3_SCL_1 /* PA8 - AF4 */ +# define GPIO_I2C3_SDA GPIO_I2C3_SDA_1 /* PC9 - AF4 */ + +# elif defined(CONFIG_NUCLEO_H753ZI_I2C3_PINSET_2) + /* AF4: I2C3 on PH7/PH8 */ +# define GPIO_I2C3_SCL GPIO_I2C3_SCL_2 /* PH7 - AF4 */ +# define GPIO_I2C3_SDA GPIO_I2C3_SDA_2 /* PH8 - AF4 */ +# endif + +# define I2C3_FREQUENCY CONFIG_NUCLEO_H753ZI_I2C3_DEFAULT_FREQUENCY + +#endif /* CONFIG_NUCLEO_H753ZI_I2C3_ENABLE */ + +/* I2C4 Pin Configurations */ + +#ifdef CONFIG_NUCLEO_H753ZI_I2C4_ENABLE + +# ifdef CONFIG_NUCLEO_H753ZI_I2C4_PINSET_1 + /* AF4: I2C4 on PD12/PD13 */ +# define GPIO_I2C4_SCL GPIO_I2C4_SCL_1 /* PD12 - AF4 */ +# define GPIO_I2C4_SDA GPIO_I2C4_SDA_1 /* PD13 - AF4 */ + +# elif defined(CONFIG_NUCLEO_H753ZI_I2C4_PINSET_2) + /* AF4: I2C4 on PF14/PF15 */ +# define GPIO_I2C4_SCL GPIO_I2C4_SCL_2 /* PF14 - AF4 */ +# define GPIO_I2C4_SDA GPIO_I2C4_SDA_2 /* PF15 - AF4 */ + +# elif defined(CONFIG_NUCLEO_H753ZI_I2C4_PINSET_3) + /* AF4: I2C4 on PH11/PH12 */ +# define GPIO_I2C4_SCL GPIO_I2C4_SCL_3 /* PH11 - AF4 */ +# define GPIO_I2C4_SDA GPIO_I2C4_SDA_3 /* PH12 - AF4 */ + +# elif defined(CONFIG_NUCLEO_H753ZI_I2C4_PINSET_4) + /* AF6: I2C4 on PB6/PB7 (shared with I2C1!) */ +# define GPIO_I2C4_SCL GPIO_I2C4_SCL_4 /* PB6 - AF6 */ +# define GPIO_I2C4_SDA GPIO_I2C4_SDA_4 /* PB7 - AF6 */ + +# elif defined(CONFIG_NUCLEO_H753ZI_I2C4_PINSET_5) + /* AF6: I2C4 on PB8/PB9 (shared with I2C1!) */ +# define GPIO_I2C4_SCL GPIO_I2C4_SCL_5 /* PB8 - AF6 */ +# define GPIO_I2C4_SDA GPIO_I2C4_SDA_5 /* PB9 - AF6 */ +# endif + +# define I2C4_FREQUENCY CONFIG_NUCLEO_H753ZI_I2C4_DEFAULT_FREQUENCY + +#endif /* CONFIG_NUCLEO_H753ZI_I2C4_ENABLE */ + +/**************************************************************************** + * I3C Configuration (Placeholder) + ****************************************************************************/ + +/* TODO: Add I3C support when needed + * I3C1: SCL=PB6, SDA=PB7 (can share with I2C1) + * I3C2: SCL=PB10, SDA=PB11 + */ + +/**************************************************************************** + * I2S Configuration (Placeholder) + ****************************************************************************/ + +/* TODO: Add I2S support when needed + * I2S1: mapped to SPI1 pins with audio-specific AF + * I2S2: mapped to SPI2 pins with audio-specific AF + * I2S3: mapped to SPI3 pins with audio-specific AF + */ + +/**************************************************************************** + * CAN/FDCAN Configuration + ****************************************************************************/ + +/* FDCAN1 GPIO Configuration */ + +#define GPIO_CAN1_RX GPIO_CAN1_RX_2 /* PB8 */ +#define GPIO_CAN1_TX GPIO_CAN1_TX_2 /* PB9 */ + +/* TODO: Add FDCAN2 configuration when needed */ + +/**************************************************************************** + * Ethernet Configuration + ****************************************************************************/ + +/* PIN CONFLICTS + * + * -------------------------------------------------------------------------- + * | PB13 | RMII | JP6: ON | I2S_A_CK | + * | | TXD1 | | | + * -------------------------------------------------------------------------- + */ + +/* UM2407 REV 4, page 28/49 + * + * By default nucleo-h753 has Solder Bridges 'ON' (SBXY: ON). + * MCU pins are already connected to Ethernet connector. + * Hence, no connection for these pins from ST Zio or Morpho connectors + * + * ------------------------------------------------------------------------- + * | | | | | | + * | pin_name | function | Config | conflict | config when using| + * | | | ST ZIO CON | ST ZIO CON | ST ZIO or morpho | + * ------------------------------------------------------------------------- + * | PA1 | RMII ref. | SB57: ON | NO | SB57: OFF | + * | | clock | | | | + * ------------------------------------------------------------------------- + * | PA2 | RMII | SB72: ON | NO | SB72: OFF | + * | | MDIO | | | | + * ------------------------------------------------------------------------- + * | PC1 | RMII | SB64: ON | NO | SB64: OFF | + * | | MDC | | | | + * ------------------------------------------------------------------------- + * | PA7 | RMII RX | SB31: ON | NO | SB31: OFF | + * | | data valid | | | | + * ------------------------------------------------------------------------- + * | PC4 | RMII | SB36: ON | NO | SB36: OFF | + * | | RXD0 | | | | + * ------------------------------------------------------------------------- + * | PC5 | RMII | SB29: ON | NO | SB29: OFF | + * | | RXD1 | | | | + * ------------------------------------------------------------------------- + * | PG11 | RMII | SB27: ON | NO | SB27: OFF | + * | | TX enable | | | | + * ------------------------------------------------------------------------- + * | PG13 | RMII | SB30: ON | NO | SB30: OFF | + * | | TXD0 | | | | + * ------------------------------------------------------------------------- + * | PB13 | RMII | JP6: ON | I2S_A_CK | JP6: OFF | + * | | TXD1 | | | | + * ------------------------------------------------------------------------- + */ + +#define GPIO_ETH_RMII_REF_CLK \ + (GPIO_ETH_RMII_REF_CLK_0|GPIO_SPEED_100MHz) /* PA1*/ +#define GPIO_ETH_RMII_CRS_DV \ + (GPIO_ETH_RMII_CRS_DV_0 |GPIO_SPEED_100MHz) /* PA7*/ +#define GPIO_ETH_RMII_TX_EN \ + (GPIO_ETH_RMII_TX_EN_2 |GPIO_SPEED_100MHz) /* PG11*/ +#define GPIO_ETH_RMII_TXD0 \ + (GPIO_ETH_RMII_TXD0_2 |GPIO_SPEED_100MHz) /* PG13*/ +#define GPIO_ETH_RMII_TXD1 \ + (GPIO_ETH_RMII_TXD1_1 |GPIO_SPEED_100MHz) /* PB13*/ +#define GPIO_ETH_RMII_RXD0 \ + (GPIO_ETH_RMII_RXD0_0 |GPIO_SPEED_100MHz) /* PC4*/ +#define GPIO_ETH_RMII_RXD1 \ + (GPIO_ETH_RMII_RXD1_0 |GPIO_SPEED_100MHz) /* PC5*/ +#define GPIO_ETH_MDIO \ + (GPIO_ETH_MDIO_0 |GPIO_SPEED_100MHz) /* PA2*/ +#define GPIO_ETH_MDC \ + (GPIO_ETH_MDC_0 |GPIO_SPEED_100MHz) /* PC1*/ + +/* TODO: Add Ethernet PHY control pins (reset, interrupt, etc) */ + +/**************************************************************************** + * USB Configuration + ****************************************************************************/ + +/* USB OTG FS GPIO Definitions */ + +#define GPIO_OTGFS_DM (GPIO_OTGFS_DM_0 | GPIO_SPEED_100MHz) +#define GPIO_OTGFS_DP (GPIO_OTGFS_DP_0 | GPIO_SPEED_100MHz) +#define GPIO_OTGFS_ID (GPIO_OTGFS_ID_0 | GPIO_SPEED_100MHz) + +/* TODO: Add USB OTG HS configuration when needed */ + +/**************************************************************************** + * SDMMC Configuration + ****************************************************************************/ + +/* SDMMC Clock Configuration - Frequency Stability Across HSE Sources + * + * These SDMMC clock dividers remain valid for ALL HSE source configurations + * because PLL1Q is maintained at a constant 200 MHz regardless of HSE freq. + * + * Clock Frequency Verification Table: + * +----------------+--------+---------+-------------+------------------+ + * | HSE Source | VCO | PLL1Q | SDMMC Init | SDMMC Transfer | + * +----------------+--------+---------+-------------+------------------+ + * | ST-LINK 8MHz | 800MHz | 200MHz | 416 kHz | 50 MHz | + * | Crystal 25MHz | 800MHz | 200MHz | 416 kHz | 50 MHz | + * +----------------+--------+---------+-------------+------------------+ + * + * Calculation for 8 MHz HSE: + * SDMMC_Init = PLL1Q / (2*240) = 200MHz / 480 = 416 kHz (SD compliant) + * SDMMC_Xfer = PLL1Q / (2*2) = 200MHz / 4 = 50 MHz (25 MB/s) + * + * Calculation for 25 MHz HSE: + * SDMMC_Init = PLL1Q / (2*240) = 200MHz / 480 = 416 kHz (SD compliant) + * SDMMC_Xfer = PLL1Q / (2*2) = 200MHz / 4 = 50 MHz (25 MB/s) + */ + +/* Init 400kHz, PLL1Q/(2*240) */ + +#define STM32_SDMMC_INIT_CLKDIV (240 << STM32_SDMMC_CLKCR_CLKDIV_SHIFT) + +/* Transfer at max speed, PLL1Q/(2*2) */ + +#define STM32_SDMMC_MMCXFR_CLKDIV (2 << STM32_SDMMC_CLKCR_CLKDIV_SHIFT) +#define STM32_SDMMC_SDXFR_CLKDIV (2 << STM32_SDMMC_CLKCR_CLKDIV_SHIFT) +#define STM32_SDMMC_CLKCR_EDGE STM32_SDMMC_CLKCR_NEGEDGE + +/* SDMMC clock source - PLL1Q */ + +#define STM32_RCC_D1CCIPR_SDMMCSEL RCC_D1CCIPR_SDMMC_PLL1 + +/* TODO: Add SDMMC GPIO pin configurations when needed */ + +/**************************************************************************** + * LVDS Configuration (Placeholder) + ****************************************************************************/ + +/* TODO: Add LVDS support when needed + * STM32H753 does not have built-in LVDS + * Requires external LVDS serializer/deserializer + */ + +/**************************************************************************** + * 1-Wire Configuration (Placeholder) + ****************************************************************************/ + +/* TODO: Add 1-Wire (OneWire) support when needed + * Typically implemented via UART in half-duplex mode + * or using bit-banging on GPIO + */ + +/**************************************************************************** + * QSPI Configuration (Placeholder) + ****************************************************************************/ + +/* TODO: Add QSPI support when needed + * QSPI1: Available for external flash memory + */ + +/**************************************************************************** + * FMC Configuration (Placeholder) + ****************************************************************************/ + +/* TODO: Add FMC support when needed + * FMC: For external SRAM, NOR, NAND, PSRAM + */ + +/**************************************************************************** + * SAI Configuration (Placeholder) + ****************************************************************************/ + +/* TODO: Add SAI (Serial Audio Interface) support when needed + * SAI1, SAI2: For high-quality audio applications + */ + +/**************************************************************************** + * SECTION 3: GPIO (General Purpose I/O) + ****************************************************************************/ + +/**************************************************************************** + * Digital Output - LEDs + ****************************************************************************/ + +/* The Nucleo-H753ZI board has several LEDs. + * Only three are user-controllable: + * + * LD1 -> Green + * LD2 -> Orange + * LD3 -> Red + * + * Behavior depends on CONFIG_ARCH_LEDS: + * + * SYMBOL OWNER USAGE + * ---------------- -------- ------------------------------- + * CONFIG_ARCH_LEDS=n User /dev/leds + * boards/.../stm32_userleds.c + * apps/examples/leds + * + * CONFIG_ARCH_LEDS=y NuttX boards/.../stm32_autoleds.c + * + * For more information, check the Kconfig file or use menuconfig help. + */ + +/* LED index values for use with board_userled() */ + +#define BOARD_LED1 0 +#define BOARD_LED2 1 +#define BOARD_LED3 2 +#define BOARD_NLEDS 3 + +#define BOARD_LED_GREEN BOARD_LED1 +#define BOARD_LED_ORANGE BOARD_LED2 +#define BOARD_LED_RED BOARD_LED3 + +/* LED bits for use with board_userled_all() */ + +#define BOARD_LED1_BIT (1 << BOARD_LED1) +#define BOARD_LED2_BIT (1 << BOARD_LED2) +#define BOARD_LED3_BIT (1 << BOARD_LED3) + +/* If CONFIG_ARCH_LEDS is defined, usage by board port is defined in + * include/board.h and src/stm32_leds.c. + * The LEDs are used to encode OS-related events as follows: + * + * + * SYMBOL Meaning LED state + * Red Green Orange + * ---------------------- ---------------------- ----- ------ ------ + */ + +#define LED_STARTED 0 /* NuttX has been started OFF OFF OFF */ +#define LED_HEAPALLOCATE 1 /* Heap allocated OFF OFF ON */ +#define LED_IRQSENABLED 2 /* Interrupts enabled OFF ON OFF */ +#define LED_STACKCREATED 3 /* Idle stack created OFF ON ON */ +#define LED_INIRQ 4 /* In an interrupt N/C N/C GLOW */ +#define LED_SIGNAL 5 /* In a signal handler N/C GLOW N/C */ +#define LED_ASSERTION 6 /* An assertion failed GLOW N/C GLOW */ +#define LED_PANIC 7 /* System has crashed Blink OFF N/C */ +#define LED_IDLE 8 /* MCU is in sleep mode ON OFF OFF */ + +/* TODO: Add support for additional GPIO outputs (relays, external LEDs, + * etc) + */ + +/**************************************************************************** + * Digital Input - Buttons + ****************************************************************************/ + +/* Dynamic Button Configuration with EXTI Conflict Prevention + * + * Nucleo-H753ZI has only one User-Button. However, might be good to keep + * the system ready to support until 32 buttons. This is what will be done + * here. + * + * CRITICAL: STM32 EXTI lines are shared across ports! + * Only ONE pin NUMBER can be used as interrupt source at a time. + * Example of CONFLICT: + * PG3 + PE3 (both use EXTI3 -> only last one works) + * PG3 + PE4 (EXTI3 and EXTI4 -> both work) + * + * Example for a configuration for 10 buttons: + * PC13, PB1, PB2, PD0, PD4, PD5, PE6, PE7, PF8, PF9 + * EXTI: 13, 1, 2, 0, 4, 5, 6, 7, 8, 9 + * + * NO EXTERNAL INTERRUPTION CONFLICTS! + */ + +/* Define NUM_BUTTONS FIRST */ + +#ifdef CONFIG_NUCLEO_H753ZI_BUTTON_SUPPORT +# define NUM_BUTTONS CONFIG_NUCLEO_H753ZI_BUTTON_COUNT +#else +# define NUM_BUTTONS 0 +#endif + +/* Button definitions - only if enabled */ + +#ifdef CONFIG_NUCLEO_H753ZI_BUTTON_SUPPORT + +/* Built-in button */ + +# ifdef CONFIG_NUCLEO_H753ZI_BUTTON_BUILTIN +# define BUTTON_BUILT_IN 0 +# define BUTTON_BUILT_IN_BIT (1 << 0) +# endif + +/* External buttons */ + +# if NUM_BUTTONS > 1 +# define BUTTON_1 1 +# define BUTTON_1_BIT (1 << 1) +# endif +# if NUM_BUTTONS > 2 +# define BUTTON_2 2 +# define BUTTON_2_BIT (1 << 2) +# endif +# if NUM_BUTTONS > 3 +# define BUTTON_3 3 +# define BUTTON_3_BIT (1 << 3) +# endif +# if NUM_BUTTONS > 4 +# define BUTTON_4 4 +# define BUTTON_4_BIT (1 << 4) +# endif +# if NUM_BUTTONS > 5 +# define BUTTON_5 5 +# define BUTTON_5_BIT (1 << 5) +# endif +# if NUM_BUTTONS > 6 +# define BUTTON_6 6 +# define BUTTON_6_BIT (1 << 6) +# endif +# if NUM_BUTTONS > 7 +# define BUTTON_7 7 +# define BUTTON_7_BIT (1 << 7) +# endif +# if NUM_BUTTONS > 8 +# define BUTTON_8 8 +# define BUTTON_8_BIT (1 << 8) +# endif +# if NUM_BUTTONS > 9 +# define BUTTON_9 9 +# define BUTTON_9_BIT (1 << 9) +# endif +# if NUM_BUTTONS > 10 +# define BUTTON_10 10 +# define BUTTON_10_BIT (1 << 10) +# endif +# if NUM_BUTTONS > 11 +# define BUTTON_11 11 +# define BUTTON_11_BIT (1 << 11) +# endif +# if NUM_BUTTONS > 12 +# define BUTTON_12 12 +# define BUTTON_12_BIT (1 << 12) +# endif +# if NUM_BUTTONS > 13 +# define BUTTON_13 13 +# define BUTTON_13_BIT (1 << 13) +# endif +# if NUM_BUTTONS > 14 +# define BUTTON_14 14 +# define BUTTON_14_BIT (1 << 14) +# endif +# if NUM_BUTTONS > 15 +# define BUTTON_15 15 +# define BUTTON_15_BIT (1 << 15) +# endif +# if NUM_BUTTONS > 16 +# define BUTTON_16 16 +# define BUTTON_16_BIT (1 << 16) +# endif +# if NUM_BUTTONS > 17 +# define BUTTON_17 17 +# define BUTTON_17_BIT (1 << 17) +# endif +# if NUM_BUTTONS > 18 +# define BUTTON_18 18 +# define BUTTON_18_BIT (1 << 18) +# endif +# if NUM_BUTTONS > 19 +# define BUTTON_19 19 +# define BUTTON_19_BIT (1 << 19) +# endif +# if NUM_BUTTONS > 20 +# define BUTTON_20 20 +# define BUTTON_20_BIT (1 << 20) +# endif +# if NUM_BUTTONS > 21 +# define BUTTON_21 21 +# define BUTTON_21_BIT (1 << 21) +# endif +# if NUM_BUTTONS > 22 +# define BUTTON_22 22 +# define BUTTON_22_BIT (1 << 22) +# endif +# if NUM_BUTTONS > 23 +# define BUTTON_23 23 +# define BUTTON_23_BIT (1 << 23) +# endif +# if NUM_BUTTONS > 24 +# define BUTTON_24 24 +# define BUTTON_24_BIT (1 << 24) +# endif +# if NUM_BUTTONS > 25 +# define BUTTON_25 25 +# define BUTTON_25_BIT (1 << 25) +# endif +# if NUM_BUTTONS > 26 +# define BUTTON_26 26 +# define BUTTON_26_BIT (1 << 26) +# endif +# if NUM_BUTTONS > 27 +# define BUTTON_27 27 +# define BUTTON_27_BIT (1 << 27) +# endif +# if NUM_BUTTONS > 28 +# define BUTTON_28 28 +# define BUTTON_28_BIT (1 << 28) +# endif +# if NUM_BUTTONS > 29 +# define BUTTON_29 29 +# define BUTTON_29_BIT (1 << 29) +# endif +# if NUM_BUTTONS > 30 +# define BUTTON_30 30 +# define BUTTON_30_BIT (1 << 30) +# endif +# if NUM_BUTTONS > 31 +# define BUTTON_31 31 +# define BUTTON_31_BIT (1 << 31) +# endif + +/* IRQ button range */ + +# define MIN_IRQBUTTON 0 +# define MAX_IRQBUTTON (NUM_BUTTONS - 1) +# define NUM_IRQBUTTONS NUM_BUTTONS + +#else /* !CONFIG_NUCLEO_H753ZI_BUTTON_SUPPORT */ + +# define NUM_BUTTONS 0 +# define MIN_IRQBUTTON 0 +# define MAX_IRQBUTTON 0 +# define NUM_IRQBUTTONS 0 + +#endif /* CONFIG_NUCLEO_H753ZI_BUTTON_SUPPORT */ + +/* TODO: Add support for additional digital inputs (sensors, switches, etc) */ + +/**************************************************************************** + * Analog Input - ADC + ****************************************************************************/ + +/* ADC GPIO Definitions */ + +#define GPIO_ADC123_INP10 GPIO_ADC123_INP10_0 /* PC0 */ +#define GPIO_ADC123_INP12 GPIO_ADC123_INP12_0 /* PC2 */ +#define GPIO_ADC123_INP11 GPIO_ADC123_INP11_0 /* PC1 */ +#define GPIO_ADC12_INP13 GPIO_ADC12_INP13_0 /* PC3 */ +#define GPIO_ADC12_INP15 GPIO_ADC12_INP15_0 /* PA3 */ +#define GPIO_ADC12_INP18 GPIO_ADC12_INP18_0 /* PA4 */ +#define GPIO_ADC12_INP19 GPIO_ADC12_INP19_0 /* PA5 */ +#define GPIO_ADC12_INP14 GPIO_ADC12_INP14_0 /* PA2 */ +#define GPIO_ADC123_INP7 GPIO_ADC12_INP7_0 /* PA7 */ +#define GPIO_ADC12_INP5 GPIO_ADC12_INP5_0 /* PB1 */ +#define GPIO_ADC12_INP3 GPIO_ADC12_INP3_0 /* PA6 */ +#define GPIO_ADC12_INP4 GPIO_ADC12_INP4_0 /* PC4 */ +#define GPIO_ADC12_INP8 GPIO_ADC12_INP8_0 /* PC5 */ +#define GPIO_ADC2_INP2 GPIO_ADC2_INP2_0 /* PF13 */ + +/* TODO: Add ADC3 channel definitions when needed */ + +/**************************************************************************** + * Analog Output - DAC (Placeholder) + ****************************************************************************/ + +/* TODO: Add DAC support when needed + * DAC1_OUT1: PA4 + * DAC1_OUT2: PA5 + */ + +/**************************************************************************** + * PWM/Timer Output + ****************************************************************************/ + +/* Timer GPIO Definitions */ + +/* TIM1 */ + +#define GPIO_TIM1_CH1OUT (GPIO_TIM1_CH1OUT_2 | GPIO_SPEED_50MHz) /* PE9 */ +#define GPIO_TIM1_CH1NOUT (GPIO_TIM1_CH1NOUT_3 | GPIO_SPEED_50MHz) /* PE8 */ +#define GPIO_TIM1_CH2OUT (GPIO_TIM1_CH2OUT_2 | GPIO_SPEED_50MHz) /* PE11 */ +#define GPIO_TIM1_CH2NOUT (GPIO_TIM1_CH2NOUT_3 | GPIO_SPEED_50MHz) /* PE10 */ +#define GPIO_TIM1_CH3OUT (GPIO_TIM1_CH3OUT_2 | GPIO_SPEED_50MHz) /* PE13 */ +#define GPIO_TIM1_CH3NOUT (GPIO_TIM1_CH3NOUT_3 | GPIO_SPEED_50MHz) /* PE12 */ +#define GPIO_TIM1_CH4OUT (GPIO_TIM1_CH4OUT_2 | GPIO_SPEED_50MHz) /* PE14 */ + +/* TODO: Add TIM2-8, TIM12-17 PWM configurations when needed */ + +/**************************************************************************** + * External Interrupts (Additional) + ****************************************************************************/ + +/* TODO: Add support for additional external interrupt sources + * beyond buttons (sensors, alarms, etc) + */ + +/**************************************************************************** + * Function Prototypes + ****************************************************************************/ + +#ifdef CONFIG_STM32H7_SPI + +/** + * Name: stm32_spi_register_cs_device + * + * Description: + * Register a CS device for a specific SPI bus and device ID. + * + * Input Parameters: + * spi_bus - SPI bus number (1-6) + * devid - Device ID (0-15) + * cs_pin - CS pin string (e.g., "PF1") + * active_low - true if CS is active low, false if active high + * + * Returned Value: + * OK on success, negative errno on error + */ + +int stm32_spi_register_cs_device(int spi_bus, uint32_t devid, + const char *cs_pin, bool active_low); + +/** + * Name: stm32_spi_unregister_cs_device + * + * Description: + * Unregister a CS device. + * + * Input Parameters: + * spi_bus - SPI bus number (1-6) + * devid - Device ID + * + * Returned Value: + * OK on success, negative errno on error + */ + +int stm32_spi_unregister_cs_device(int spi_bus, uint32_t devid); + +#endif /* CONFIG_STM32H7_SPI */ + +int stm32_spi_initialize(void); + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __BOARDS_ARM_STM32H7_NUCLEO_H753ZI_INCLUDE_BOARD_H */ diff --git a/boards/arm/stm32h7/nucleo-h753zi/include/readme.txt b/boards/arm/stm32h7/nucleo-h753zi/include/readme.txt new file mode 100644 index 0000000000000..29741d2a5235f --- /dev/null +++ b/boards/arm/stm32h7/nucleo-h753zi/include/readme.txt @@ -0,0 +1,420 @@ +README +====== + +ST Nucleo-H753ZI Board Support for Apache NuttX +================================================ + + MCU: STM32H753ZIT6 (Arm Cortex-M7, 480 MHz max, 2 MB Flash, 1 MB RAM) + Board: NUCLEO-H753ZI (MB1364) + Vendor: STMicroelectronics + NuttX: 12.11+ + +References +---------- + + UM2407 - Nucleo-H753ZI User Manual (Rev 4) + DS12110 - STM32H753ZI Datasheet (Rev 9) + RM0433 - STM32H7x3 Reference Manual + +Board Overview +-------------- + + The Nucleo-H753ZI is a development board featuring the STM32H753ZIT6 + microcontroller with the following on-board resources: + + - 3 user LEDs: LD1 (Green/PB0), LD2 (Orange/PE1), LD3 (Red/PB14) + - 1 user push-button: B1 (PC13) + - ST-LINK/V3 debugger/programmer (provides 8 MHz MCO to MCU HSE) + - Ethernet connector (RMII interface) + - USB OTG FS connector + - Arduino Uno V3 expansion headers (Zio) + - ST Morpho expansion headers + +Menuconfig-Driven Architecture +------------------------------- + + This board support package is designed around a menuconfig-driven + architecture. Nearly all hardware options are selectable at build + time through Kconfig without modifying any source files. This + includes: + + Clock Source Selection + Via menuconfig: Board Clock Configuration -> HSE clock source + - 8 MHz (default): Uses ST-LINK MCO, no hardware changes needed + - 25 MHz: Uses external crystal at X3 (requires HW modification) + Both configurations produce identical system performance (see + Clock Configuration section below). + + SPI Bus and Pin Set Selection + Via menuconfig: SPI Configuration -> SPIx Configuration + - Enable/disable each SPI bus independently (SPI1-SPI6) + - Select alternative pin sets per bus (2-4 options per bus) + - CS pins are NOT configured at the SPI bus level; each + peripheral registers its own CS pin dynamically at runtime + + I2C Bus, Pin Set and Frequency Selection + Via menuconfig: I2C Configuration -> I2Cx Configuration + - Enable/disable each I2C bus independently (I2C1-I2C4) + - Select alternative pin sets per bus (2-5 options per bus) + - Configure default bus frequency per bus (100/400/1000 kHz) + - Kconfig prevents conflicting pin assignments at compile time + (e.g., I2C1 pinset 1 and I2C4 pinset 4 share PB6/PB7) + + LED Control Mode + Via menuconfig: LED Control Mode + - Automatic: Kernel controls LEDs to indicate OS state + - User: Application controls LEDs via /dev/userleds + - Disabled: LED subsystem completely disabled + + Button Configuration + Via menuconfig: Button Configuration + - Enable/disable button support + - Configure number of buttons (1-32) + - Include/exclude built-in button (PC13) + - Specify additional button GPIO pins via string + (e.g., "PF15,PG14,PG9,PE0") + - Compile-time EXTI conflict validation + + Peripheral Module Configuration + Via menuconfig: SPI MODULES / I2C MODULES + - ST7796 LCD (SPI): bus, CS pin, DC pin, RESET pin, LED pin, + color depth, orientation, rotation, framebuffer size, + SPI frequency + - MFRC522 RFID (SPI): bus, CS pin, CS polarity, IRQ pin, + IRQ trigger type + - SSD1306 OLED (I2C): bus, I2C address, frequency, + brightness, resolution (128x64 or 128x32), device path + +Clock Configuration +------------------- + + Available clock sources on Nucleo-H753ZI: + + HSI: 64 MHz RC factory-trimmed + CSI: 4 MHz RC oscillator + LSI: 32 kHz RC + HSE: 8 MHz from ST-LINK MCO (default) or 25 MHz crystal (X3) + LSE: 32.768 kHz crystal (X2) + HSI48: 48 MHz RC (dedicated for USB) + + Both HSE configurations produce identical system clocks: + + SYSCLK = 400 MHz (VOS1 maximum; VOS0 not used by NuttX default) + CPUCLK = 400 MHz + HCLK = 200 MHz (AHB, SYSCLK/2) + PCLK1 = 100 MHz (APB1, HCLK/2) + PCLK2 = 100 MHz (APB2, HCLK/2) + PCLK3 = 100 MHz (APB3, HCLK/2) + PCLK4 = 100 MHz (APB4, HCLK/2) + Timers = 200 MHz (2 x PCLK when APB prescaler != 1) + + PLL Summary (8 MHz HSE, default): + + PLL1: 8/1 * 100 = 800 MHz VCO + P = 400 MHz -> SYSCLK + Q = 200 MHz -> SPI1/2/3, SDMMC + R = 200 MHz + + PLL2: 8/1 * 75 = 600 MHz VCO + P = 75 MHz -> ADC1/2/3, SPI4/5 + Q = 25 MHz -> FDCAN1/2 + R = 200 MHz + + PLL3: 8/2 * 100 = 400 MHz VCO + P = 200 MHz + Q = 25 MHz + R = 40 MHz + + PLL Summary (25 MHz HSE, optional): + + PLL1: 25/5 * 160 = 800 MHz VCO (same outputs as 8 MHz config) + PLL2: 25/2 * 48 = 600 MHz VCO (same outputs; FDCAN via HSE direct) + PLL3: 25/2 * 64 = 800 MHz VCO + + Peripheral kernel clocks: + + I2C1/2/3/4 HSI 16 MHz (workaround: NuttX I2C driver requires HSI) + SPI1/2/3 PLL1Q 200 MHz + SPI4/5 PLL2P 75 MHz + SPI6 PCLK4 100 MHz + ADC1/2/3 PLL2P 75 MHz (within 80 MHz limit per DS12110) + FDCAN1/2 PLL2Q 25 MHz (8 MHz config) / HSE direct (25 MHz config) + SDMMC1/2 PLL1Q 200 MHz + USB1/2 HSI48 48 MHz + + FLASH wait states: 4 (conservative; safe for VOS1 up to 480 MHz HCLK). + Minimum required for 200 MHz HCLK at VOS1 is 2 wait states. + + Hardware configuration for 8 MHz HSE (factory default, no changes): + SB45=ON, SB44=OFF, SB46=OFF, SB3=OFF, SB4=OFF + + Hardware configuration for 25 MHz HSE (requires modification): + Install 25 MHz crystal at X3. + SB3=ON, SB4=ON, SB45=OFF, SB44=OFF, SB46=OFF + +GPIO Pin Mapping (On-board Peripherals) +---------------------------------------- + + Function Pin AF Notes + ---------------- ----- ---- ---------------------------- + LD1 (Green LED) PB0 - Output, active high + LD2 (Orange LED) PE1 - Output, active high + LD3 (Red LED) PB14 - Output, active high + B1 (User Button) PC13 EXTI Input, pull-down + USART3 TX (VCP) PD8 AF7 ST-LINK virtual COM port + USART3 RX (VCP) PD9 AF7 ST-LINK virtual COM port + USART6 TX PG14 AF7 + USART6 RX PG9 AF7 + I2C1 SCL (opt1) PB6 AF4 Arduino D10 + I2C1 SDA (opt1) PB7 AF4 Arduino D9 + I2C1 SCL (opt2) PB8 AF4 Morpho + I2C1 SDA (opt2) PB9 AF4 Morpho + FDCAN1 RX PB8 AF9 + FDCAN1 TX PB9 AF9 + USB OTG FS DM PA11 AF10 + USB OTG FS DP PA12 AF10 + USB VBUS PA9 - + ETH RMII REF_CLK PA1 AF11 + ETH RMII CRS_DV PA7 AF11 + ETH RMII TX_EN PG11 AF11 + ETH RMII TXD0 PG13 AF11 + ETH RMII TXD1 PB13 AF11 + ETH RMII RXD0 PC4 AF11 + ETH RMII RXD1 PC5 AF11 + ETH MDIO PA2 AF11 + ETH MDC PC1 AF11 + HSE IN PH0 - ST-LINK MCO (8 MHz default) + HSE OUT PH1 - Reserved (X3 crystal) + SWCLK PA14 AF0 + SWDIO PA13 AF0 + + Note: Ethernet requires solder bridge changes when using Zio/Morpho + headers. See UM2407 Rev 4, page 28 for solder bridge table. + +SPI Interfaces +-------------- + + Six SPI buses available (SPI1-SPI6). Each bus supports multiple + pin sets selectable via menuconfig. CS pins are registered + dynamically per peripheral. + + SPI bus -> kernel clock -> max SCK: + SPI1/2/3: PLL1Q (200 MHz) -> 100 MHz max SCK + SPI4/5: PLL2P (75 MHz) -> 37.5 MHz max SCK + SPI6: PCLK4 (100 MHz) -> 50 MHz max SCK + + SPI1 pin sets: + Set 1 (Arduino): PA5(SCK), PA6(MISO), PA7(MOSI) + Set 2: PB3(SCK), PB4(MISO), PB5(MOSI) + Set 3: PG11(SCK), PG9(MISO), PD7(MOSI) + + SPI2 pin sets: + Set 1: PB13(SCK), PB14(MISO), PB15(MOSI) + Set 2: PA12(SCK), PC2(MISO), PC1(MOSI) + Set 3: PD3(SCK), PC2(MISO), PC3(MOSI) + + SPI3 pin sets: + Set 1: PC10(SCK), PC11(MISO), PC12(MOSI) + Set 2: PB3(SCK), PB4(MISO), PB5(MOSI) + + SPI4 pin sets: + Set 1: PE12(SCK), PE13(MISO), PE14(MOSI) + Set 2: PE2(SCK), PE5(MISO), PE6(MOSI) + + SPI5 pin sets: + Set 1: PF7(SCK), PF8(MISO), PF9(MOSI) + Set 2: PK0(SCK), PJ11(MISO), PJ10(MOSI) + + SPI6 pin sets: + Set 1: PG13(SCK), PG12(MISO), PG14(MOSI) + Set 2: PA5(SCK), PA6(MISO), PA7(MOSI) + +I2C Interfaces +-------------- + + Four I2C buses available (I2C1-I2C4). All use HSI (16 MHz) as + kernel clock (NuttX I2C driver requirement). Bus frequency + configurable per bus via menuconfig (100/400/1000 kHz). + + I2C1 pin sets: + Set 1: PB6(SCL), PB7(SDA) - AF4 (Arduino D10/D9) + Set 2: PB8(SCL), PB9(SDA) - AF4 (Morpho) + + I2C2 pin sets: + Set 1: PB10(SCL), PB11(SDA) - AF4 + Set 2: PF1(SCL), PF0(SDA) - AF4 + Set 3: PH4(SCL), PH5(SDA) - AF4 + + I2C3 pin sets: + Set 1: PA8(SCL), PC9(SDA) - AF4 + Set 2: PH7(SCL), PH8(SDA) - AF4 + + I2C4 pin sets: + Set 1: PD12(SCL), PD13(SDA) - AF4 + Set 2: PF14(SCL), PF15(SDA) - AF4 + Set 3: PH11(SCL), PH12(SDA) - AF4 + Set 4: PB6(SCL), PB7(SDA) - AF6 (conflicts with I2C1 Set 1) + Set 5: PB8(SCL), PB9(SDA) - AF6 (conflicts with I2C1 Set 2) + + Kconfig enforces conflicting pin exclusions at build time. + +FDCAN (CAN FD) +-------------- + + FDCAN1: RX=PB8, TX=PB9 + Kernel clock: 25 MHz (PLL2Q for 8 MHz HSE; HSE direct for 25 MHz HSE) + Supported bitrates: 125 kbps, 250 kbps, 500 kbps, 1 Mbps (and FD rates) + +USB +--- + + USB OTG FS: PA11(DM), PA12(DP), PA9(VBUS), PG6(PWRON), PG7(OVERCURRENT) + Kernel clock: HSI48 (48 MHz, dedicated USB oscillator) + Supports: USB Device, USB Host, USB Monitor + +SDMMC +----- + + Kernel clock: PLL1Q (200 MHz) + Init frequency: 200 MHz / (2*240) = ~416 kHz + Transfer frequency: 200 MHz / (2*2) = 50 MHz (25 MB/s) + +ADC +--- + + ADC1/2/3 kernel clock: PLL2P (75 MHz, within 80 MHz HW limit) + Available channels exposed: INP3, INP4, INP5, INP7, INP8, INP10, + INP11, INP12, INP13, INP14, INP15, INP18, INP19 + +Supported Peripheral Modules +------------------------------ + + The following modules are supported with full Kconfig configuration: + + ST7796 (SPI LCD, 480x320 IPS) + Configurable: SPI bus, CS/DC/RESET/LED pins, CS polarity, + color depth (RGB444/RGB565/RGB666), orientation (portrait/landscape + and reverse variants), 180-degree rotation, SPI frequency, + framebuffer size. Framebuffer interface (/dev/fb0) compatible + with LVGL and other graphics libraries. + + SSD1306 (I2C OLED, 128x64 or 128x32) + Configurable: I2C bus, I2C address (0x3C/0x3D/custom), bus + frequency, brightness (0-100%), resolution, device path, + device number. + + MFRC522 (SPI RFID, 13.56 MHz) + Configurable: SPI bus, device ID, CS pin, CS polarity, + optional IRQ pin, IRQ trigger (falling/rising/both edges). + Device node: /dev/rfid0 + + NRF24L01 (SPI 2.4 GHz transceiver) + CS=PA4, CE=PF12, IRQ=PD15 + + MMC/SD Card (SPI) + CS=PD15, Card-detect=PF12 (EXTI) + + LSM6DSL (I2C 6-axis IMU) + INT1=PB4, INT2=PB5 + + LSM303AGR (I2C magnetometer/accelerometer) + LSM9DS1 (I2C 9-axis IMU) + LPS22HB (I2C pressure sensor, INT1=PB10) + PCA9635 (I2C LED controller, addr=0x40, bus=I2C1) + +Additional Features +------------------- + + PROGMEM MTD: Internal flash exposed as MTD character device + RTC: Hardware RTC driver (/dev/rtc0) + PWM: TIM1 configured (CH1-CH4 + complementary outputs on PE8-PE14) + ROMFS: Optional auto-mount of built-in ROMFS image + GPIO driver: /dev/gpioN support (BOARD_NGPIOIN=1, NGPIOOUT=3, NGPIOINT=1) + USB MSC: Mass storage class support + +LED Behavior (Automatic Mode) +------------------------------- + + LED_STARTED Red=OFF, Green=OFF, Orange=OFF + LED_HEAPALLOCATE Red=OFF, Green=OFF, Orange=ON + LED_IRQSENABLED Red=OFF, Green=ON, Orange=OFF + LED_STACKCREATED Red=OFF, Green=ON, Orange=ON + LED_INIRQ Red=N/C, Green=N/C, Orange=GLOW + LED_SIGNAL Red=N/C, Green=GLOW,Orange=N/C + LED_ASSERTION Red=GLOW,Green=N/C, Orange=GLOW + LED_PANIC Red=BLINK,Green=OFF,Orange=N/C + LED_IDLE Red=ON, Green=OFF, Orange=OFF + +Configurations +-------------- + + nsh + Basic NuttShell (NSH) via USART3/VCP at 115200 baud. + User-controlled LEDs (/dev/userleds) via examples/leds. + Generic GPIO driver (/dev/gpioN) via examples/gpio. + D-cache and I-cache enabled. DTCM enabled. + CONFIG_ARCH_LEDS disabled (user LED mode). + + button_driver + NuttShell via USART3/VCP at 115200 baud. + Demonstrates the menuconfig-driven button system with 11 buttons: + Button 0: built-in PC13 + Buttons 1-10: PB1, PD0, PG4, PD5, PE6, PE3, PD12, PF9, PD15, PE11 + Each button assigned to a unique EXTI line (no conflicts). + Automatic LEDs enabled (CONFIG_ARCH_LEDS_CPU_ACTIVITY). + User LEDs also available (/dev/userleds). + Button device at /dev/buttons via examples/buttons. + IRQ-driven button events (CONFIG_ARCH_IRQBUTTONS). + + socketcan + NuttShell via USART3/VCP at 115200 baud. + FDCAN1 configured as SocketCAN network interface. + Arbitration bitrate: 500 kbps. + Data bitrate: 500 kbps (CAN FD capable). + Includes canutils: candump, cansend. + Network stack enabled (CONFIG_NET_CAN). + CAN error frames, socket options, write buffers enabled. + HPWORK thread for FDCAN interrupt handling. + procfs mounted for runtime inspection. + +Source Organization +------------------- + + src/ + stm32_boot.c - Boot and early initialization + stm32_bringup.c - Driver registration (bringup) + stm32_appinitialize.c - Application-level initialization + stm32_boot_image.c - MCUboot image support + nucleo-h753zi.h - Board-internal definitions and prototypes + + drivers/driver_bus/ + stm32_spi.c - SPI bus initialization (SPI1-SPI6) + stm32_i2c.c - I2C bus initialization (I2C1-I2C4) + + drivers/driver_generic/ + stm32_adc.c - ADC setup + stm32_buttons.c - Button driver (up to 32 buttons) + stm32_gpio.c - Generic GPIO driver + stm32_pwm.c - PWM output setup + stm32_userleds.c - User LED driver + + drivers/driver_middleware/ + stm32_autoleds.c - Automatic LED OS state indication + stm32_composite.c - USB composite device + stm32_progmem.c - Internal flash MTD + stm32_reset.c - Board reset support + stm32_romfs_initialize.c- ROMFS auto-mount + stm32_uid.c - Unique device ID + stm32_usb.c - USB OTG FS initialization + stm32_usbmsc.c - USB mass storage class + + drivers/driver_modules/ + stm32_lsm303agr.c - LSM303AGR IMU driver + stm32_lsm6dsl.c - LSM6DSL IMU driver + stm32_lsm9ds1.c - LSM9DS1 IMU driver + stm32_mfrc522.c - MFRC522 RFID driver + stm32_mmcsd.c - MMC/SD card (SPI) driver + stm32_nrf24l01.c - NRF24L01 wireless driver + stm32_pca9635.c - PCA9635 LED controller driver + stm32_ssd1306.c - SSD1306 OLED driver + stm32_st7796.c - ST7796 LCD + framebuffer driver diff --git a/boards/arm/stm32h7/nucleo-h753zi/kernel/Makefile b/boards/arm/stm32h7/nucleo-h753zi/kernel/Makefile new file mode 100644 index 0000000000000..63432ee4e4f98 --- /dev/null +++ b/boards/arm/stm32h7/nucleo-h753zi/kernel/Makefile @@ -0,0 +1,94 @@ +############################################################################ +# boards/arm/stm32h7/nucleo-h753zi/kernel/Makefile +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +include $(TOPDIR)/Make.defs + +# The entry point name (if none is provided in the .config file) + +CONFIG_INIT_ENTRYPOINT ?= user_start +ENTRYPT = $(patsubst "%",%,$(CONFIG_INIT_ENTRYPOINT)) + +# Get the paths to the libraries and the links script path in format that +# is appropriate for the host OS + +USER_LIBPATHS = $(addprefix -L,$(call CONVERT_PATH,$(addprefix $(TOPDIR)$(DELIM),$(dir $(USERLIBS))))) +USER_LDSCRIPT = -T $(call CONVERT_PATH,$(BOARD_DIR)$(DELIM)scripts$(DELIM)memory.ld) +USER_LDSCRIPT += -T $(call CONVERT_PATH,$(BOARD_DIR)$(DELIM)scripts$(DELIM)user-space.ld) +USER_HEXFILE += $(call CONVERT_PATH,$(TOPDIR)$(DELIM)nuttx_user.hex) +USER_SRECFILE += $(call CONVERT_PATH,$(TOPDIR)$(DELIM)nuttx_user.srec) +USER_BINFILE += $(call CONVERT_PATH,$(TOPDIR)$(DELIM)nuttx_user.bin) + +USER_LDFLAGS = --undefined=$(ENTRYPT) --entry=$(ENTRYPT) $(USER_LDSCRIPT) +USER_LDLIBS = $(patsubst lib%,-l%,$(basename $(notdir $(USERLIBS)))) +USER_LIBGCC = "${shell "$(CC)" $(ARCHCPUFLAGS) -print-libgcc-file-name}" + +# Source files + +CSRCS = stm32_userspace.c +COBJS = $(CSRCS:.c=$(OBJEXT)) +OBJS = $(COBJS) + +# Targets: + +all: $(TOPDIR)$(DELIM)nuttx_user.elf $(TOPDIR)$(DELIM)User.map +.PHONY: nuttx_user.elf depend clean distclean + +$(COBJS): %$(OBJEXT): %.c + $(call COMPILE, $<, $@) + +# Create the nuttx_user.elf file containing all of the user-mode code + +nuttx_user.elf: $(OBJS) + $(Q) $(LD) -o $@ $(USER_LDFLAGS) $(USER_LIBPATHS) $(OBJS) --start-group $(USER_LDLIBS) --end-group $(USER_LIBGCC) + +$(TOPDIR)$(DELIM)nuttx_user.elf: nuttx_user.elf + @echo "LD: nuttx_user.elf" + $(Q) cp -a nuttx_user.elf $(TOPDIR)$(DELIM)nuttx_user.elf +ifeq ($(CONFIG_INTELHEX_BINARY),y) + @echo "CP: nuttx_user.hex" + $(Q) $(OBJCOPY) $(OBJCOPYARGS) -O ihex nuttx_user.elf $(USER_HEXFILE) +endif +ifeq ($(CONFIG_MOTOROLA_SREC),y) + @echo "CP: nuttx_user.srec" + $(Q) $(OBJCOPY) $(OBJCOPYARGS) -O srec nuttx_user.elf $(USER_SRECFILE) +endif +ifeq ($(CONFIG_RAW_BINARY),y) + @echo "CP: nuttx_user.bin" + $(Q) $(OBJCOPY) $(OBJCOPYARGS) -O binary nuttx_user.elf $(USER_BINFILE) +endif + +$(TOPDIR)$(DELIM)User.map: nuttx_user.elf + @echo "MK: User.map" + $(Q) $(NM) nuttx_user.elf >$(TOPDIR)$(DELIM)User.map + $(Q) $(CROSSDEV)size nuttx_user.elf + +.depend: + +depend: .depend + +clean: + $(call DELFILE, nuttx_user.elf) + $(call DELFILE, "$(TOPDIR)$(DELIM)nuttx_user.*") + $(call DELFILE, "$(TOPDIR)$(DELIM)User.map") + $(call CLEAN) + +distclean: clean diff --git a/boards/arm/stm32h7/nucleo-h753zi/kernel/stm32_userspace.c b/boards/arm/stm32h7/nucleo-h753zi/kernel/stm32_userspace.c new file mode 100644 index 0000000000000..1c8f709de071f --- /dev/null +++ b/boards/arm/stm32h7/nucleo-h753zi/kernel/stm32_userspace.c @@ -0,0 +1,102 @@ +/**************************************************************************** + * boards/arm/stm32h7/nucleo-h753zi/kernel/stm32_userspace.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include +#include +#include + +#if defined(CONFIG_BUILD_PROTECTED) && !defined(__KERNEL__) + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Configuration ************************************************************/ + +#ifndef CONFIG_NUTTX_USERSPACE +# error "CONFIG_NUTTX_USERSPACE not defined" +#endif + +#if CONFIG_NUTTX_USERSPACE != 0x08020000 +# error "CONFIG_NUTTX_USERSPACE must be 0x08020000 to match memory.ld" +#endif + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* These 'addresses' of these values are setup by the linker script. */ + +extern uint8_t _stext[]; /* Start of .text */ +extern uint8_t _etext[]; /* End_1 of .text + .rodata */ +extern const uint8_t _eronly[]; /* End+1 of read only section (.text + .rodata) */ +extern uint8_t _sdata[]; /* Start of .data */ +extern uint8_t _edata[]; /* End+1 of .data */ +extern uint8_t _sbss[]; /* Start of .bss */ +extern uint8_t _ebss[]; /* End+1 of .bss */ + +const struct userspace_s userspace locate_data(".userspace") = +{ + /* General memory map */ + + .us_entrypoint = CONFIG_INIT_ENTRYPOINT, + .us_textstart = (uintptr_t)_stext, + .us_textend = (uintptr_t)_etext, + .us_datasource = (uintptr_t)_eronly, + .us_datastart = (uintptr_t)_sdata, + .us_dataend = (uintptr_t)_edata, + .us_bssstart = (uintptr_t)_sbss, + .us_bssend = (uintptr_t)_ebss, + + /* Memory manager heap structure */ + + .us_heap = &g_mmheap, + + /* Task/thread startup routines */ + + .task_startup = nxtask_startup, + + /* Signal handler trampoline */ + + .signal_handler = up_signal_handler, + + /* User-space work queue support (declared in include/nuttx/wqueue.h) */ + +#ifdef CONFIG_LIBC_USRWORK + .work_usrstart = work_usrstart, +#endif +}; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +#endif /* CONFIG_BUILD_PROTECTED && !__KERNEL__ */ diff --git a/boards/arm/stm32h7/nucleo-h753zi/scripts/Make.defs b/boards/arm/stm32h7/nucleo-h753zi/scripts/Make.defs new file mode 100644 index 0000000000000..238179f4e2268 --- /dev/null +++ b/boards/arm/stm32h7/nucleo-h753zi/scripts/Make.defs @@ -0,0 +1,50 @@ +############################################################################ +# boards/arm/stm32h7/nucleo-h753zi/scripts/Make.defs +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +include $(TOPDIR)/.config +include $(TOPDIR)/tools/Config.mk +include $(TOPDIR)/arch/arm/src/armv7-m/Toolchain.defs + +ifeq ($(CONFIG_STM32_APP_FORMAT_MCUBOOT),y) + ifeq ($(CONFIG_MCUBOOT_BOOTLOADER),y) + LDSCRIPT = flash-mcuboot-loader.ld + else + LDSCRIPT = flash-mcuboot-app.ld + endif +else + LDSCRIPT = flash.ld +endif + +ARCHSCRIPT += $(BOARD_DIR)$(DELIM)scripts$(DELIM)$(LDSCRIPT) + +ARCHPICFLAGS = -fpic -msingle-pic-base -mpic-register=r10 + +CFLAGS := $(ARCHCFLAGS) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHINCLUDES) $(ARCHDEFINES) $(EXTRAFLAGS) +CPICFLAGS = $(ARCHPICFLAGS) $(CFLAGS) +CXXFLAGS := $(ARCHCXXFLAGS) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHXXINCLUDES) $(ARCHDEFINES) $(EXTRAFLAGS) +CXXPICFLAGS = $(ARCHPICFLAGS) $(CXXFLAGS) +CPPFLAGS := $(ARCHINCLUDES) $(ARCHDEFINES) $(EXTRAFLAGS) +AFLAGS := $(CFLAGS) -D__ASSEMBLY__ + +NXFLATLDFLAGS1 = -r -d -warn-common +NXFLATLDFLAGS2 = $(NXFLATLDFLAGS1) -T$(TOPDIR)/binfmt/libnxflat/gnu-nxflat-pcrel.ld -no-check-sections +LDNXFLATFLAGS = -e main -s 2048 diff --git a/boards/arm/stm32h7/nucleo-h753zi/scripts/flash-mcuboot-app.ld b/boards/arm/stm32h7/nucleo-h753zi/scripts/flash-mcuboot-app.ld new file mode 100644 index 0000000000000..a60c25b625eb0 --- /dev/null +++ b/boards/arm/stm32h7/nucleo-h753zi/scripts/flash-mcuboot-app.ld @@ -0,0 +1,203 @@ +/**************************************************************************** + * boards/arm/stm32h7/nucleo-h753zi/scripts/flash-mcuboot-app.ld + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/* The STM32H753ZI has 2048Kb of main FLASH memory. The flash memory is + * partitioned into a User Flash memory and a System Flash memory. Each + * of these memories has two banks: + * + * 1) User Flash memory: + * + * Bank 1: Start address 0x0800:0000 to 0x080F:FFFF with 8 sectors, 128Kb each + * Bank 2: Start address 0x0810:0000 to 0x081F:FFFF with 8 sectors, 128Kb each + * + * 2) System Flash memory: + * + * Bank 1: Start address 0x1FF0:0000 to 0x1FF1:FFFF with 1 x 128Kb sector + * Bank 1: Start address 0x1FF4:0000 to 0x1FF5:FFFF with 1 x 128Kb sector + * + * 3) User option bytes for user configuration, only in Bank 1. + * + * In the STM32H753ZI, two different boot spaces can be selected through + * the BOOT pin and the boot base address programmed in the BOOT_ADD0 and + * BOOT_ADD1 option bytes: + * + * 1) BOOT=0: Boot address defined by user option byte BOOT_ADD0[15:0]. + * ST programmed value: Flash memory at 0x0800:0000 + * 2) BOOT=1: Boot address defined by user option byte BOOT_ADD1[15:0]. + * ST programmed value: System bootloader at 0x1FF0:0000 + * + * TODO: Check next paragraph with nucleo schematics + * + * NuttX does not modify these option bytes. On the unmodified NUCLEO-H753ZI + * board, the BOOT0 pin is at ground so by default, the STM32 will boot + * to address 0x0800:0000 in FLASH. + * + * The STM32H753ZI also has 1024Kb of data SRAM. + * SRAM is split up into several blocks and into three power domains: + * + * 1) TCM SRAMs are dedicated to the Cortex-M7 and are accessible with + * 0 wait states by the Cortex-M7 and by MDMA through AHBS slave bus + * + * 1.1) 128Kb of DTCM-RAM beginning at address 0x2000:0000 + * + * The DTCM-RAM is organized as 2 x 64Kb DTCM-RAMs on 2 x 32 bit + * DTCM ports. The DTCM-RAM could be used for critical real-time + * data, such as interrupt service routines or stack / heap memory. + * Both DTCM-RAMs can be used in parallel (for load/store operations) + * thanks to the Cortex-M7 dual issue capability. + * + * 1.2) 64Kb of ITCM-RAM beginning at address 0x0000:0000 + * + * This RAM is connected to ITCM 64-bit interface designed for + * execution of critical real-times routines by the CPU. + * + * 2) AXI SRAM (D1 domain) accessible by all system masters except BDMA + * through D1 domain AXI bus matrix + * + * 2.1) 512Kb of SRAM beginning at address 0x2400:0000 + * + * 3) AHB SRAM (D2 domain) accessible by all system masters except BDMA + * through D2 domain AHB bus matrix + * + * 3.1) 128Kb of SRAM1 beginning at address 0x3000:0000 + * 3.2) 128Kb of SRAM2 beginning at address 0x3002:0000 + * 3.3) 32Kb of SRAM3 beginning at address 0x3004:0000 + * + * SRAM1 - SRAM3 are one contiguous block: 288Kb at address 0x3000:0000 + * + * 4) AHB SRAM (D3 domain) accessible by most of system masters + * through D3 domain AHB bus matrix + * + * 4.1) 64Kb of SRAM4 beginning at address 0x3800:0000 + * 4.1) 4Kb of backup RAM beginning at address 0x3880:0000 + * + * When booting from FLASH, FLASH memory is aliased to address 0x0000:0000 + * where the code expects to begin execution by jumping to the entry point in + * the 0x0800:0000 address range. + */ + +MEMORY +{ + itcm (rwx) : ORIGIN = 0x00000000, LENGTH = 64K + flash (rx) : ORIGIN = 0x08040200, LENGTH = 768K - 256K + dtcm1 (rwx) : ORIGIN = 0x20000000, LENGTH = 64K + dtcm2 (rwx) : ORIGIN = 0x20010000, LENGTH = 64K + sram (rwx) : ORIGIN = 0x24000000, LENGTH = 512K + sram1 (rwx) : ORIGIN = 0x30000000, LENGTH = 128K + sram2 (rwx) : ORIGIN = 0x30020000, LENGTH = 128K + sram3 (rwx) : ORIGIN = 0x30040000, LENGTH = 32K + sram4 (rwx) : ORIGIN = 0x38000000, LENGTH = 64K + bbram (rwx) : ORIGIN = 0x38800000, LENGTH = 4K +} + +OUTPUT_ARCH(arm) +EXTERN(_vectors) +ENTRY(_stext) +SECTIONS +{ + .text : + { + _stext = ABSOLUTE(.); + *(.vectors) + *(.text .text.*) + *(.fixup) + *(.gnu.warning) + *(.rodata .rodata.*) + *(.gnu.linkonce.t.*) + *(.glue_7) + *(.glue_7t) + *(.got) + *(.gcc_except_table) + *(.gnu.linkonce.r.*) + _etext = ABSOLUTE(.); + } > flash + + .init_section : + { + _sinit = ABSOLUTE(.); + KEEP(*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) + KEEP(*(.init_array EXCLUDE_FILE(*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o) .ctors)) + _einit = ABSOLUTE(.); + } > flash + + .ARM.extab : + { + *(.ARM.extab*) + } > flash + + __exidx_start = ABSOLUTE(.); + .ARM.exidx : + { + *(.ARM.exidx*) + } > flash + __exidx_end = ABSOLUTE(.); + + _eronly = ABSOLUTE(.); + + .data : + { + _sdata = ABSOLUTE(.); + *(.data .data.*) + *(.gnu.linkonce.d.*) + CONSTRUCTORS + . = ALIGN(4); + _edata = ABSOLUTE(.); + } > sram AT > flash + + .bss : + { + _sbss = ABSOLUTE(.); + *(.bss .bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + _ebss = ABSOLUTE(.); + } > sram + + /* Emit the the D3 power domain section for locating BDMA data + * + * Static data with locate_data(".sram4") will be located + * at start of SRAM4; the rest of SRAM4 will be added to the heap. + */ + + .sram4_reserve (NOLOAD) : + { + *(.sram4) + . = ALIGN(4); + _sram4_heap_start = ABSOLUTE(.); + } > sram4 + + /* Stabs debugging sections. */ + + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_info 0 : { *(.debug_info) } + .debug_line 0 : { *(.debug_line) } + .debug_pubnames 0 : { *(.debug_pubnames) } + .debug_aranges 0 : { *(.debug_aranges) } +} diff --git a/boards/arm/stm32h7/nucleo-h753zi/scripts/flash-mcuboot-loader.ld b/boards/arm/stm32h7/nucleo-h753zi/scripts/flash-mcuboot-loader.ld new file mode 100644 index 0000000000000..7041e776a0908 --- /dev/null +++ b/boards/arm/stm32h7/nucleo-h753zi/scripts/flash-mcuboot-loader.ld @@ -0,0 +1,203 @@ +/**************************************************************************** + * boards/arm/stm32h7/nucleo-h753zi/scripts/flash-mcuboot-laoder.ld + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/* The STM32H753ZI has 2048Kb of main FLASH memory. The flash memory is + * partitioned into a User Flash memory and a System Flash memory. Each + * of these memories has two banks: + * + * 1) User Flash memory: + * + * Bank 1: Start address 0x0800:0000 to 0x080F:FFFF with 8 sectors, 128Kb each + * Bank 2: Start address 0x0810:0000 to 0x081F:FFFF with 8 sectors, 128Kb each + * + * 2) System Flash memory: + * + * Bank 1: Start address 0x1FF0:0000 to 0x1FF1:FFFF with 1 x 128Kb sector + * Bank 1: Start address 0x1FF4:0000 to 0x1FF5:FFFF with 1 x 128Kb sector + * + * 3) User option bytes for user configuration, only in Bank 1. + * + * In the STM32H753ZI, two different boot spaces can be selected through + * the BOOT pin and the boot base address programmed in the BOOT_ADD0 and + * BOOT_ADD1 option bytes: + * + * 1) BOOT=0: Boot address defined by user option byte BOOT_ADD0[15:0]. + * ST programmed value: Flash memory at 0x0800:0000 + * 2) BOOT=1: Boot address defined by user option byte BOOT_ADD1[15:0]. + * ST programmed value: System bootloader at 0x1FF0:0000 + * + * TODO: Check next paragraph with nucleo schematics + * + * NuttX does not modify these option bytes. On the unmodified NUCLEO-H753ZI + * board, the BOOT0 pin is at ground so by default, the STM32 will boot + * to address 0x0800:0000 in FLASH. + * + * The STM32H753ZI also has 1024Kb of data SRAM. + * SRAM is split up into several blocks and into three power domains: + * + * 1) TCM SRAMs are dedicated to the Cortex-M7 and are accessible with + * 0 wait states by the Cortex-M7 and by MDMA through AHBS slave bus + * + * 1.1) 128Kb of DTCM-RAM beginning at address 0x2000:0000 + * + * The DTCM-RAM is organized as 2 x 64Kb DTCM-RAMs on 2 x 32 bit + * DTCM ports. The DTCM-RAM could be used for critical real-time + * data, such as interrupt service routines or stack / heap memory. + * Both DTCM-RAMs can be used in parallel (for load/store operations) + * thanks to the Cortex-M7 dual issue capability. + * + * 1.2) 64Kb of ITCM-RAM beginning at address 0x0000:0000 + * + * This RAM is connected to ITCM 64-bit interface designed for + * execution of critical real-times routines by the CPU. + * + * 2) AXI SRAM (D1 domain) accessible by all system masters except BDMA + * through D1 domain AXI bus matrix + * + * 2.1) 512Kb of SRAM beginning at address 0x2400:0000 + * + * 3) AHB SRAM (D2 domain) accessible by all system masters except BDMA + * through D2 domain AHB bus matrix + * + * 3.1) 128Kb of SRAM1 beginning at address 0x3000:0000 + * 3.2) 128Kb of SRAM2 beginning at address 0x3002:0000 + * 3.3) 32Kb of SRAM3 beginning at address 0x3004:0000 + * + * SRAM1 - SRAM3 are one contiguous block: 288Kb at address 0x3000:0000 + * + * 4) AHB SRAM (D3 domain) accessible by most of system masters + * through D3 domain AHB bus matrix + * + * 4.1) 64Kb of SRAM4 beginning at address 0x3800:0000 + * 4.1) 4Kb of backup RAM beginning at address 0x3880:0000 + * + * When booting from FLASH, FLASH memory is aliased to address 0x0000:0000 + * where the code expects to begin execution by jumping to the entry point in + * the 0x0800:0000 address range. + */ + +MEMORY +{ + itcm (rwx) : ORIGIN = 0x00000000, LENGTH = 64K + flash (rx) : ORIGIN = 0x08000000, LENGTH = 256K + dtcm1 (rwx) : ORIGIN = 0x20000000, LENGTH = 64K + dtcm2 (rwx) : ORIGIN = 0x20010000, LENGTH = 64K + sram (rwx) : ORIGIN = 0x24000000, LENGTH = 512K + sram1 (rwx) : ORIGIN = 0x30000000, LENGTH = 128K + sram2 (rwx) : ORIGIN = 0x30020000, LENGTH = 128K + sram3 (rwx) : ORIGIN = 0x30040000, LENGTH = 32K + sram4 (rwx) : ORIGIN = 0x38000000, LENGTH = 64K + bbram (rwx) : ORIGIN = 0x38800000, LENGTH = 4K +} + +OUTPUT_ARCH(arm) +EXTERN(_vectors) +ENTRY(_stext) +SECTIONS +{ + .text : + { + _stext = ABSOLUTE(.); + *(.vectors) + *(.text .text.*) + *(.fixup) + *(.gnu.warning) + *(.rodata .rodata.*) + *(.gnu.linkonce.t.*) + *(.glue_7) + *(.glue_7t) + *(.got) + *(.gcc_except_table) + *(.gnu.linkonce.r.*) + _etext = ABSOLUTE(.); + } > flash + + .init_section : + { + _sinit = ABSOLUTE(.); + KEEP(*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) + KEEP(*(.init_array EXCLUDE_FILE(*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o) .ctors)) + _einit = ABSOLUTE(.); + } > flash + + .ARM.extab : + { + *(.ARM.extab*) + } > flash + + __exidx_start = ABSOLUTE(.); + .ARM.exidx : + { + *(.ARM.exidx*) + } > flash + __exidx_end = ABSOLUTE(.); + + _eronly = ABSOLUTE(.); + + .data : + { + _sdata = ABSOLUTE(.); + *(.data .data.*) + *(.gnu.linkonce.d.*) + CONSTRUCTORS + . = ALIGN(4); + _edata = ABSOLUTE(.); + } > sram AT > flash + + .bss : + { + _sbss = ABSOLUTE(.); + *(.bss .bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + _ebss = ABSOLUTE(.); + } > sram + + /* Emit the the D3 power domain section for locating BDMA data + * + * Static data with locate_data(".sram4") will be located + * at start of SRAM4; the rest of SRAM4 will be added to the heap. + */ + + .sram4_reserve (NOLOAD) : + { + *(.sram4) + . = ALIGN(4); + _sram4_heap_start = ABSOLUTE(.); + } > sram4 + + /* Stabs debugging sections. */ + + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_info 0 : { *(.debug_info) } + .debug_line 0 : { *(.debug_line) } + .debug_pubnames 0 : { *(.debug_pubnames) } + .debug_aranges 0 : { *(.debug_aranges) } +} diff --git a/boards/arm/stm32h7/nucleo-h753zi/scripts/flash.ld b/boards/arm/stm32h7/nucleo-h753zi/scripts/flash.ld new file mode 100644 index 0000000000000..99d7e261175d6 --- /dev/null +++ b/boards/arm/stm32h7/nucleo-h753zi/scripts/flash.ld @@ -0,0 +1,203 @@ +/**************************************************************************** + * boards/arm/stm32h7/nucleo-h753zi/scripts/flash.ld + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/* The STM32H753ZI has 2048Kb of main FLASH memory. The flash memory is + * partitioned into a User Flash memory and a System Flash memory. Each + * of these memories has two banks: + * + * 1) User Flash memory: + * + * Bank 1: Start address 0x0800:0000 to 0x080F:FFFF with 8 sectors, 128Kb each + * Bank 2: Start address 0x0810:0000 to 0x081F:FFFF with 8 sectors, 128Kb each + * + * 2) System Flash memory: + * + * Bank 1: Start address 0x1FF0:0000 to 0x1FF1:FFFF with 1 x 128Kb sector + * Bank 1: Start address 0x1FF4:0000 to 0x1FF5:FFFF with 1 x 128Kb sector + * + * 3) User option bytes for user configuration, only in Bank 1. + * + * In the STM32H753ZI, two different boot spaces can be selected through + * the BOOT pin and the boot base address programmed in the BOOT_ADD0 and + * BOOT_ADD1 option bytes: + * + * 1) BOOT=0: Boot address defined by user option byte BOOT_ADD0[15:0]. + * ST programmed value: Flash memory at 0x0800:0000 + * 2) BOOT=1: Boot address defined by user option byte BOOT_ADD1[15:0]. + * ST programmed value: System bootloader at 0x1FF0:0000 + * + * TODO: Check next paragraph with nucleo schematics + * + * NuttX does not modify these option bytes. On the unmodified NUCLEO-H753ZI + * board, the BOOT0 pin is at ground so by default, the STM32 will boot + * to address 0x0800:0000 in FLASH. + * + * The STM32H753ZI also has 1024Kb of data SRAM. + * SRAM is split up into several blocks and into three power domains: + * + * 1) TCM SRAMs are dedicated to the Cortex-M7 and are accessible with + * 0 wait states by the Cortex-M7 and by MDMA through AHBS slave bus + * + * 1.1) 128Kb of DTCM-RAM beginning at address 0x2000:0000 + * + * The DTCM-RAM is organized as 2 x 64Kb DTCM-RAMs on 2 x 32 bit + * DTCM ports. The DTCM-RAM could be used for critical real-time + * data, such as interrupt service routines or stack / heap memory. + * Both DTCM-RAMs can be used in parallel (for load/store operations) + * thanks to the Cortex-M7 dual issue capability. + * + * 1.2) 64Kb of ITCM-RAM beginning at address 0x0000:0000 + * + * This RAM is connected to ITCM 64-bit interface designed for + * execution of critical real-times routines by the CPU. + * + * 2) AXI SRAM (D1 domain) accessible by all system masters except BDMA + * through D1 domain AXI bus matrix + * + * 2.1) 512Kb of SRAM beginning at address 0x2400:0000 + * + * 3) AHB SRAM (D2 domain) accessible by all system masters except BDMA + * through D2 domain AHB bus matrix + * + * 3.1) 128Kb of SRAM1 beginning at address 0x3000:0000 + * 3.2) 128Kb of SRAM2 beginning at address 0x3002:0000 + * 3.3) 32Kb of SRAM3 beginning at address 0x3004:0000 + * + * SRAM1 - SRAM3 are one contiguous block: 288Kb at address 0x3000:0000 + * + * 4) AHB SRAM (D3 domain) accessible by most of system masters + * through D3 domain AHB bus matrix + * + * 4.1) 64Kb of SRAM4 beginning at address 0x3800:0000 + * 4.1) 4Kb of backup RAM beginning at address 0x3880:0000 + * + * When booting from FLASH, FLASH memory is aliased to address 0x0000:0000 + * where the code expects to begin execution by jumping to the entry point in + * the 0x0800:0000 address range. + */ + +MEMORY +{ + itcm (rwx) : ORIGIN = 0x00000000, LENGTH = 64K + flash (rx) : ORIGIN = 0x08000000, LENGTH = 2048K + dtcm1 (rwx) : ORIGIN = 0x20000000, LENGTH = 64K + dtcm2 (rwx) : ORIGIN = 0x20010000, LENGTH = 64K + sram (rwx) : ORIGIN = 0x24000000, LENGTH = 512K + sram1 (rwx) : ORIGIN = 0x30000000, LENGTH = 128K + sram2 (rwx) : ORIGIN = 0x30020000, LENGTH = 128K + sram3 (rwx) : ORIGIN = 0x30040000, LENGTH = 32K + sram4 (rwx) : ORIGIN = 0x38000000, LENGTH = 64K + bbram (rwx) : ORIGIN = 0x38800000, LENGTH = 4K +} + +OUTPUT_ARCH(arm) +EXTERN(_vectors) +ENTRY(_stext) +SECTIONS +{ + .text : + { + _stext = ABSOLUTE(.); + *(.vectors) + *(.text .text.*) + *(.fixup) + *(.gnu.warning) + *(.rodata .rodata.*) + *(.gnu.linkonce.t.*) + *(.glue_7) + *(.glue_7t) + *(.got) + *(.gcc_except_table) + *(.gnu.linkonce.r.*) + _etext = ABSOLUTE(.); + } > flash + + .init_section : + { + _sinit = ABSOLUTE(.); + KEEP(*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) + KEEP(*(.init_array EXCLUDE_FILE(*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o) .ctors)) + _einit = ABSOLUTE(.); + } > flash + + .ARM.extab : + { + *(.ARM.extab*) + } > flash + + __exidx_start = ABSOLUTE(.); + .ARM.exidx : + { + *(.ARM.exidx*) + } > flash + __exidx_end = ABSOLUTE(.); + + _eronly = ABSOLUTE(.); + + .data : + { + _sdata = ABSOLUTE(.); + *(.data .data.*) + *(.gnu.linkonce.d.*) + CONSTRUCTORS + . = ALIGN(4); + _edata = ABSOLUTE(.); + } > sram AT > flash + + .bss : + { + _sbss = ABSOLUTE(.); + *(.bss .bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + _ebss = ABSOLUTE(.); + } > sram + + /* Emit the the D3 power domain section for locating BDMA data + * + * Static data with locate_data(".sram4") will be located + * at start of SRAM4; the rest of SRAM4 will be added to the heap. + */ + + .sram4_reserve (NOLOAD) : + { + *(.sram4) + . = ALIGN(4); + _sram4_heap_start = ABSOLUTE(.); + } > sram4 + + /* Stabs debugging sections. */ + + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_info 0 : { *(.debug_info) } + .debug_line 0 : { *(.debug_line) } + .debug_pubnames 0 : { *(.debug_pubnames) } + .debug_aranges 0 : { *(.debug_aranges) } +} diff --git a/boards/arm/stm32h7/nucleo-h753zi/scripts/kernel.space.ld b/boards/arm/stm32h7/nucleo-h753zi/scripts/kernel.space.ld new file mode 100644 index 0000000000000..83403ce296b89 --- /dev/null +++ b/boards/arm/stm32h7/nucleo-h753zi/scripts/kernel.space.ld @@ -0,0 +1,112 @@ +/**************************************************************************** + * boards/arm/stm32h7/nucleo-h753zi/scripts/kernel.space.ld + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/* NOTE: This depends on the memory.ld script having been included prior to + * this script. + */ + +OUTPUT_ARCH(arm) +ENTRY(_stext) +SECTIONS +{ + .text : { + _stext = ABSOLUTE(.); + *(.vectors) + *(.text .text.*) + *(.fixup) + *(.gnu.warning) + *(.rodata .rodata.*) + *(.gnu.linkonce.t.*) + *(.glue_7) + *(.glue_7t) + *(.got) + *(.gcc_except_table) + *(.gnu.linkonce.r.*) + _etext = ABSOLUTE(.); + } > kflash + + .init_section : { + _sinit = ABSOLUTE(.); + KEEP(*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) + KEEP(*(.init_array EXCLUDE_FILE(*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o) .ctors)) + _einit = ABSOLUTE(.); + } > kflash + + .ARM.extab : { + *(.ARM.extab*) + } > kflash + + __exidx_start = ABSOLUTE(.); + .ARM.exidx : { + *(.ARM.exidx*) + } > kflash + + __exidx_end = ABSOLUTE(.); + + _eronly = ABSOLUTE(.); + + .data : { + _sdata = ABSOLUTE(.); + *(.data .data.*) + *(.gnu.linkonce.d.*) + CONSTRUCTORS + . = ALIGN(4); + _edata = ABSOLUTE(.); + } > ksram AT > kflash + + .bss : { + _sbss = ABSOLUTE(.); + *(.bss .bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + _ebss = ABSOLUTE(.); + } > ksram + + /* Emit the the D3 power domain section for locating BDMA data + * + * Static data with locate_data(".sram4") will be located + * at start of SRAM4; the rest of SRAM4 will be added to the heap. + */ + + .sram4_reserve (NOLOAD) : + { + *(.sram4) + . = ALIGN(4); + _sram4_heap_start = ABSOLUTE(.); + } > sram4 + + /* Stabs debugging sections */ + + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_info 0 : { *(.debug_info) } + .debug_line 0 : { *(.debug_line) } + .debug_pubnames 0 : { *(.debug_pubnames) } + .debug_aranges 0 : { *(.debug_aranges) } +} diff --git a/boards/arm/stm32h7/nucleo-h753zi/scripts/memory.ld b/boards/arm/stm32h7/nucleo-h753zi/scripts/memory.ld new file mode 100644 index 0000000000000..ef69f2320b817 --- /dev/null +++ b/boards/arm/stm32h7/nucleo-h753zi/scripts/memory.ld @@ -0,0 +1,54 @@ +/**************************************************************************** + * boards/arm/stm32h7/nucleo-h753zi/scripts/memory.ld + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/* TODO: Add description for memory organisation */ + +MEMORY +{ + /* ITCM boot address */ + + itcm (rwx) : ORIGIN = 0x00000000, LENGTH = 64K + + /* 2048Kb FLASH */ + + kflash (rx) : ORIGIN = 0x08000000, LENGTH = 128K + uflash (rx) : ORIGIN = 0x08020000, LENGTH = 128K + xflash (rx) : ORIGIN = 0x08040000, LENGTH = 1792K + + /* 288Kb SRAM123 */ + + ksram (rwx) : ORIGIN = 0x30000000, LENGTH = 16K + usram (rwx) : ORIGIN = 0x30004000, LENGTH = 16K + xsram (rwx) : ORIGIN = 0x30008000, LENGTH = 288K - 32K + + /* 512Kb of contiguous AXI SRAM */ + + sram (rwx) : ORIGIN = 0x24000000, LENGTH = 512K + + /* DTCM SRAM */ + + dtcm1 (rwx) : ORIGIN = 0x20000000, LENGTH = 64K + dtcm2 (rwx) : ORIGIN = 0x20010000, LENGTH = 64K + + sram4 (rwx) : ORIGIN = 0x38000000, LENGTH = 64K + bbram (rwx) : ORIGIN = 0x38800000, LENGTH = 4K +} diff --git a/boards/arm/stm32h7/nucleo-h753zi/scripts/user-space.ld b/boards/arm/stm32h7/nucleo-h753zi/scripts/user-space.ld new file mode 100644 index 0000000000000..a8bc29f412c8e --- /dev/null +++ b/boards/arm/stm32h7/nucleo-h753zi/scripts/user-space.ld @@ -0,0 +1,101 @@ +/**************************************************************************** + * boards/arm/stm32h7/nucleo-h753zi/scripts/user-space.ld + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/* NOTE: This depends on the memory.ld script having been included prior to + * this script. + */ + +OUTPUT_ARCH(arm) +SECTIONS +{ + .userspace : { + *(.userspace) + } > uflash + + .text : { + _stext = ABSOLUTE(.); + *(.text .text.*) + *(.fixup) + *(.gnu.warning) + *(.rodata .rodata.*) + *(.gnu.linkonce.t.*) + *(.glue_7) + *(.glue_7t) + *(.got) + *(.gcc_except_table) + *(.gnu.linkonce.r.*) + _etext = ABSOLUTE(.); + } > uflash + + .init_section : { + _sinit = ABSOLUTE(.); + KEEP(*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) + KEEP(*(.init_array EXCLUDE_FILE(*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o) .ctors)) + _einit = ABSOLUTE(.); + } > uflash + + .ARM.extab : { + *(.ARM.extab*) + } > uflash + + __exidx_start = ABSOLUTE(.); + .ARM.exidx : { + *(.ARM.exidx*) + } > uflash + + __exidx_end = ABSOLUTE(.); + + _eronly = ABSOLUTE(.); + + .data : { + _sdata = ABSOLUTE(.); + *(.data .data.*) + *(.gnu.linkonce.d.*) + CONSTRUCTORS + . = ALIGN(4); + _edata = ABSOLUTE(.); + } > usram AT > uflash + + .bss : { + _sbss = ABSOLUTE(.); + *(.bss .bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + _ebss = ABSOLUTE(.); + } > usram + + /* Stabs debugging sections */ + + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_info 0 : { *(.debug_info) } + .debug_line 0 : { *(.debug_line) } + .debug_pubnames 0 : { *(.debug_pubnames) } + .debug_aranges 0 : { *(.debug_aranges) } +} diff --git a/boards/arm/stm32h7/nucleo-h753zi/src/CMakeLists.txt b/boards/arm/stm32h7/nucleo-h753zi/src/CMakeLists.txt new file mode 100644 index 0000000000000..18c29cc4e2a74 --- /dev/null +++ b/boards/arm/stm32h7/nucleo-h753zi/src/CMakeLists.txt @@ -0,0 +1,127 @@ +# ############################################################################## +# boards/arm/stm32h7/nucleo-h753zi/src/CMakeLists.txt +# ############################################################################## + +set(SRCS stm32_boot.c stm32_bringup.c stm32_appinitialize.c) + +if(CONFIG_ADC) + list(APPEND SRCS stm32_adc.c) +endif() + +if(CONFIG_ARCH_LEDS) + list(APPEND SRCS stm32_autoleds.c) +else() + list(APPEND SRCS stm32_userleds.c) +endif() + +if(CONFIG_ARCH_BUTTONS) + list(APPEND SRCS stm32_buttons.c) +endif() + +if(CONFIG_STM32_ROMFS) + list(APPEND SRCS stm32_romfs_initialize.c) +endif() + +if(CONFIG_STM32H7_I2C) + list(APPEND SRCS stm32_i2c.c) +endif() + +if(CONFIG_STM32H7_SPI) + list(APPEND SRCS stm32_spi.c) +endif() + +if(CONFIG_NUCLEO_H753ZI_MFRC522_ENABLE) + list(APPEND SRCS stm32_mfrc522.c) +endif() + +if(CONFIG_STM32H7_OTGFS) + list(APPEND SRCS stm32_usb.c) +endif() + +if(CONFIG_BOARDCTL_UNIQUEID) + list(APPEND SRCS stm32_uid.c) +endif() + +if(CONFIG_SENSORS_LSM6DSL) + list(APPEND SRCS stm32_lsm6dsl.c) +endif() + +if(CONFIG_SENSORS_LSM9DS1) + list(APPEND SRCS stm32_lsm9ds1.c) +endif() + +if(CONFIG_SENSORS_LSM303AGR) + list(APPEND SRCS stm32_lsm303agr.c) +endif() + +if(CONFIG_PCA9635PW) + list(APPEND SRCS stm32_pca9635.c) +endif() + +if(CONFIG_LCD_SSD1306) + list(APPEND SRCS stm32_ssd1306.c) +endif() + +if(CONFIG_LCD_ST7796) + list(APPEND SRCS stm32_st7796.c) +endif() + +if(CONFIG_STM32H7_PROGMEM) + list(APPEND SRCS stm32_progmem.c) +endif() + +if(CONFIG_WL_NRF24L01) + list(APPEND SRCS stm32_nrf24l01.c) +endif() + +if(CONFIG_NUCLEO_H753ZI_GPIO_DRIVER) + list(APPEND SRCS stm32_gpio.c) +endif() + +if(CONFIG_PWM) + list(APPEND SRCS stm32_pwm.c) +endif() + +if(CONFIG_BOARDCTL_RESET) + list(APPEND SRCS stm32_reset.c) +endif() + +if(CONFIG_BOARDCTL_BOOT_IMAGE) + list(APPEND SRCS stm32_boot_image.c) +endif() + +if(CONFIG_USBMSC) + list(APPEND SRCS stm32_usbmsc.c) +endif() + +if(CONFIG_USBDEV_COMPOSITE) + list(APPEND SRCS stm32_composite.c) +endif() + +if(CONFIG_MMCSD) + list(APPEND SRCS stm32_mmcsd.c) +endif() + +target_sources(board PRIVATE ${SRCS}) + +# Linker scripts +if(CONFIG_STM32_APP_FORMAT_MCUBOOT) + if(CONFIG_MCUBOOT_BOOTLOADER) + set_property( + GLOBAL PROPERTY LD_SCRIPT + "${NUTTX_BOARD_DIR}/scripts/flash-mcuboot-loader.ld") + else() + set_property( + GLOBAL PROPERTY LD_SCRIPT + "${NUTTX_BOARD_DIR}/scripts/flash-mcuboot-app.ld") + endif() +else() + set_property(GLOBAL PROPERTY LD_SCRIPT "${NUTTX_BOARD_DIR}/scripts/flash.ld") +endif() + +if(NOT CONFIG_BUILD_FLAT) + add_subdirectory(${NUTTX_BOARD_DIR}/kernel) + set_property( + GLOBAL PROPERTY LD_SCRIPT_USER ${NUTTX_BOARD_DIR}/scripts/memory.ld + ${NUTTX_BOARD_DIR}/scripts/user-space.ld) +endif() diff --git a/boards/arm/stm32h7/nucleo-h753zi/src/Makefile b/boards/arm/stm32h7/nucleo-h753zi/src/Makefile new file mode 100644 index 0000000000000..8d0ebb6e95e14 --- /dev/null +++ b/boards/arm/stm32h7/nucleo-h753zi/src/Makefile @@ -0,0 +1,107 @@ +############################################################################ +# boards/arm/stm32h7/nucleo-h753zi/src/Makefile +############################################################################ + +include $(TOPDIR)/Make.defs + +CSRCS = stm32_boot.c stm32_bringup.c stm32_appinitialize.c + +ifeq ($(CONFIG_ADC),y) + CSRCS += stm32_adc.c +endif + +ifeq ($(CONFIG_ARCH_LEDS),y) + CSRCS += stm32_autoleds.c +else + CSRCS += stm32_userleds.c +endif + +ifeq ($(CONFIG_ARCH_BUTTONS),y) + CSRCS += stm32_buttons.c +endif + +ifeq ($(CONFIG_STM32_ROMFS),y) + CSRCS += stm32_romfs_initialize.c +endif + +ifeq ($(CONFIG_STM32H7_I2C),y) + CSRCS += stm32_i2c.c +endif + +ifeq ($(CONFIG_STM32H7_SPI),y) + CSRCS += stm32_spi.c +endif + +ifeq ($(CONFIG_NUCLEO_H753ZI_MFRC522_ENABLE),y) + CSRCS += stm32_mfrc522.c +endif + +ifeq ($(CONFIG_STM32H7_OTGFS),y) + CSRCS += stm32_usb.c +endif + +ifeq ($(CONFIG_BOARDCTL_UNIQUEID),y) + CSRCS += stm32_uid.c +endif + +ifeq ($(CONFIG_SENSORS_LSM6DSL),y) + CSRCS += stm32_lsm6dsl.c +endif + +ifeq ($(CONFIG_SENSORS_LSM9DS1),y) + CSRCS += stm32_lsm9ds1.c +endif + +ifeq ($(CONFIG_SENSORS_LSM303AGR),y) + CSRCS += stm32_lsm303agr.c +endif + +ifeq ($(CONFIG_PCA9635PW),y) + CSRCS += stm32_pca9635.c +endif + +ifeq ($(CONFIG_LCD_SSD1306),y) + CSRCS += stm32_ssd1306.c +endif + +ifeq ($(CONFIG_LCD_ST7796),y) + CSRCS += stm32_st7796.c +endif + +ifeq ($(CONFIG_STM32H7_PROGMEM),y) + CSRCS += stm32_progmem.c +endif + +ifeq ($(CONFIG_WL_NRF24L01),y) + CSRCS += stm32_nrf24l01.c +endif + +ifeq ($(CONFIG_NUCLEO_H753ZI_GPIO_DRIVER),y) + CSRCS += stm32_gpio.c +endif + +ifeq ($(CONFIG_PWM),y) + CSRCS += stm32_pwm.c +endif + +ifeq ($(CONFIG_BOARDCTL_RESET),y) + CSRCS += stm32_reset.c +endif + +ifeq ($(CONFIG_BOARDCTL_BOOT_IMAGE),y) + CSRCS += stm32_boot_image.c +endif + +ifeq ($(CONFIG_USBMSC),y) + CSRCS += stm32_usbmsc.c +endif + +ifeq ($(CONFIG_USBDEV_COMPOSITE),y) + CSRCS += stm32_composite.c +endif + +ifeq ($(CONFIG_MMCSD),y) + CSRCS += stm32_mmcsd.c +endif + +include $(TOPDIR)/boards/Board.mk diff --git a/boards/arm/stm32h7/nucleo-h753zi/src/nucleo-h753zi.h b/boards/arm/stm32h7/nucleo-h753zi/src/nucleo-h753zi.h new file mode 100644 index 0000000000000..e18e5caab7cbc --- /dev/null +++ b/boards/arm/stm32h7/nucleo-h753zi/src/nucleo-h753zi.h @@ -0,0 +1,1236 @@ +/**************************************************************************** + * boards/arm/stm32h7/nucleo-h753zi/src/nucleo-h753zi.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __BOARDS_ARM_STM32H7_NUCLEO_H753ZI_SRC_NUCLEO_H753ZI_H +#define __BOARDS_ARM_STM32H7_NUCLEO_H753ZI_SRC_NUCLEO_H753ZI_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * SECTION 1: FEATURE CONFIGURATION + ****************************************************************************/ + +/* Core System Features */ + +#define HAVE_PROC 1 +#define HAVE_USBDEV 1 +#define HAVE_USBHOST 1 +#define HAVE_USBMONITOR 1 +#define HAVE_MTDCONFIG 1 +#define HAVE_PROGMEM_CHARDEV 1 +#define HAVE_RTC_DRIVER 1 + +/* USB Feature Dependencies */ + +#ifndef CONFIG_STM32H7_OTGFS +# undef HAVE_USBDEV +# undef HAVE_USBHOST +#endif + +#ifndef CONFIG_USBDEV +# undef HAVE_USBDEV +#endif + +#ifndef CONFIG_USBHOST +# undef HAVE_USBHOST +#endif + +#ifndef CONFIG_USBMONITOR +# undef HAVE_USBMONITOR +#endif + +#if !defined(HAVE_USBDEV) +# undef CONFIG_USBDEV_TRACE +#endif + +#if !defined(HAVE_USBHOST) +# undef CONFIG_USBHOST_TRACE +#endif + +#if !defined(CONFIG_USBDEV_TRACE) && !defined(CONFIG_USBHOST_TRACE) +# undef HAVE_USBMONITOR +#endif + +/* MTD Feature Dependencies */ + +#if !defined(CONFIG_STM32H7_PROGMEM) || !defined(CONFIG_MTD_PROGMEM) +# undef HAVE_PROGMEM_CHARDEV +#endif + +/* RTC Feature Dependencies */ + +#if !defined(CONFIG_RTC) || !defined(CONFIG_RTC_DRIVER) +# undef HAVE_RTC_DRIVER +#endif + +/* Flash-based Parameters */ + +#if defined(CONFIG_MMCSD) +# define FLASH_BASED_PARAMS +#endif + +/**************************************************************************** + * SECTION 2: DEVICE DRIVER PATHS + ****************************************************************************/ + +/* LED Driver */ + +#define LED_DRIVER_PATH "/dev/userleds" + +/* Button Driver */ + +#define BUTTONS_DRIVER_PATH "/dev/buttons" + +/* RTC Driver */ + +#define RTC_DRIVER_PATH "/dev/rtc0" + +/* CAN Driver */ + +#define CAN0_DRIVER_PATH "/dev/can0" + +/* Sensor Drivers */ + +#define MFRC522_DEVPATH "/dev/rfid0" + +/* Display Drivers */ + +#define ST7796_FB_PATH "/dev/fb0" + +/* Filesystem Paths */ + +#ifdef CONFIG_FS_PROCFS +# ifdef CONFIG_NSH_PROC_MOUNTPOINT +# define STM32_PROCFS_MOUNTPOINT CONFIG_NSH_PROC_MOUNTPOINT +# else +# define STM32_PROCFS_MOUNTPOINT "/proc" +# endif +#endif + +/* MTD Devices */ + +#define PROGMEM_MTD_MINOR 0 + +/**************************************************************************** + * SECTION 3: GPIO HARDWARE DEFINITIONS + ****************************************************************************/ + +/**************************************************************************** + * Board GPIO - LEDs + ****************************************************************************/ + +/* LED GPIO Definitions */ + +#define GPIO_LD1 (GPIO_OUTPUT | GPIO_PUSHPULL | GPIO_SPEED_50MHz | \ + GPIO_OUTPUT_CLEAR | GPIO_PORTB | GPIO_PIN0) +#define GPIO_LD2 (GPIO_OUTPUT | GPIO_PUSHPULL | GPIO_SPEED_50MHz | \ + GPIO_OUTPUT_CLEAR | GPIO_PORTE | GPIO_PIN1) +#define GPIO_LD3 (GPIO_OUTPUT | GPIO_PUSHPULL | GPIO_SPEED_50MHz | \ + GPIO_OUTPUT_CLEAR | GPIO_PORTB | GPIO_PIN14) + +/* LED Logical Name Aliases */ + +#define GPIO_LED_GREEN GPIO_LD1 +#define GPIO_LED_ORANGE GPIO_LD2 +#define GPIO_LED_RED GPIO_LD3 + +/**************************************************************************** + * Board GPIO - Buttons + ****************************************************************************/ + +#if defined(CONFIG_NUCLEO_H753ZI_BUTTON_SUPPORT) || \ + defined(CONFIG_NUCLEO_H753ZI_GPIO_DRIVER) +# define GPIO_BTN_BUILT_IN (GPIO_INPUT | GPIO_PULLDOWN | GPIO_EXTI | \ + GPIO_PORTC | GPIO_PIN13) +#endif + +/**************************************************************************** + * USB GPIO + ****************************************************************************/ + +#define GPIO_OTGFS_VBUS (GPIO_INPUT | GPIO_FLOAT | GPIO_SPEED_100MHz | \ + GPIO_OPENDRAIN | GPIO_PORTA | GPIO_PIN9) +#define GPIO_OTGFS_PWRON (GPIO_OUTPUT | GPIO_FLOAT | GPIO_SPEED_100MHz | \ + GPIO_PUSHPULL | GPIO_PORTG | GPIO_PIN6) + +#ifdef CONFIG_USBHOST +# define GPIO_OTGFS_OVER (GPIO_INPUT | GPIO_EXTI | GPIO_FLOAT | \ + GPIO_SPEED_100MHz | GPIO_PUSHPULL | \ + GPIO_PORTG | GPIO_PIN7) +#else +# define GPIO_OTGFS_OVER (GPIO_INPUT | GPIO_FLOAT | GPIO_SPEED_100MHz | \ + GPIO_PUSHPULL | GPIO_PORTG | GPIO_PIN7) +#endif + +/**************************************************************************** + * Generic GPIO Examples + ****************************************************************************/ + +/* GPIO Subsystem Definitions */ + +#define BOARD_NGPIOIN 1 +#define BOARD_NGPIOOUT 3 +#define BOARD_NGPIOINT 1 + +/* Placeholder - example for in, out and interrupt */ + +#define GPIO_IN1 (GPIO_INPUT | GPIO_FLOAT | GPIO_PORTE | \ + GPIO_PIN2) +#define GPIO_OUT1 (GPIO_OUTPUT | GPIO_PUSHPULL | \ + GPIO_SPEED_50MHz | GPIO_OUTPUT_SET | \ + GPIO_PORTE | GPIO_PIN4) +#define GPIO_INT1 (GPIO_INPUT | GPIO_FLOAT | GPIO_PORTE | \ + GPIO_PIN5) + +/**************************************************************************** + * SECTION 4: PERIPHERAL DEVICE CONFIGURATIONS + ****************************************************************************/ + +/**************************************************************************** + * Core Communication Buses - I2C Pin Configurations + ****************************************************************************/ + +/* I2C1 Pin Configurations */ + +#ifdef CONFIG_NUCLEO_H753ZI_I2C1_ENABLE + +# ifdef CONFIG_NUCLEO_H753ZI_I2C1_PINSET_1 + /* AF4: I2C1 on PB6/PB7 (Arduino D10/D9) */ +# define GPIO_I2C1_SCL GPIO_I2C1_SCL_1 /* PB6 - AF4 */ +# define GPIO_I2C1_SDA GPIO_I2C1_SDA_1 /* PB7 - AF4 */ + +# elif defined(CONFIG_NUCLEO_H753ZI_I2C1_PINSET_2) + /* AF4: I2C1 on PB8/PB9 (Morpho) */ +# define GPIO_I2C1_SCL GPIO_I2C1_SCL_2 /* PB8 - AF4 */ +# define GPIO_I2C1_SDA GPIO_I2C1_SDA_2 /* PB9 - AF4 */ +# endif + +# define I2C1_FREQUENCY CONFIG_NUCLEO_H753ZI_I2C1_DEFAULT_FREQUENCY + +#endif /* CONFIG_NUCLEO_H753ZI_I2C1_ENABLE */ + +/* I2C2 Pin Configurations */ + +#ifdef CONFIG_NUCLEO_H753ZI_I2C2_ENABLE + +# ifdef CONFIG_NUCLEO_H753ZI_I2C2_PINSET_1 + /* AF4: I2C2 on PB10/PB11 */ +# define GPIO_I2C2_SCL GPIO_I2C2_SCL_1 /* PB10 - AF4 */ +# define GPIO_I2C2_SDA GPIO_I2C2_SDA_1 /* PB11 - AF4 */ + +# elif defined(CONFIG_NUCLEO_H753ZI_I2C2_PINSET_2) + /* AF4: I2C2 on PF1/PF0 */ +# define GPIO_I2C2_SCL GPIO_I2C2_SCL_2 /* PF1 - AF4 */ +# define GPIO_I2C2_SDA GPIO_I2C2_SDA_2 /* PF0 - AF4 */ + +# elif defined(CONFIG_NUCLEO_H753ZI_I2C2_PINSET_3) + /* AF4: I2C2 on PH4/PH5 */ +# define GPIO_I2C2_SCL GPIO_I2C2_SCL_3 /* PH4 - AF4 */ +# define GPIO_I2C2_SDA GPIO_I2C2_SDA_3 /* PH5 - AF4 */ +# endif + +# define I2C2_FREQUENCY CONFIG_NUCLEO_H753ZI_I2C2_DEFAULT_FREQUENCY + +#endif /* CONFIG_NUCLEO_H753ZI_I2C2_ENABLE */ + +/* I2C3 Pin Configurations */ + +#ifdef CONFIG_NUCLEO_H753ZI_I2C3_ENABLE + +# ifdef CONFIG_NUCLEO_H753ZI_I2C3_PINSET_1 + /* AF4: I2C3 on PA8/PC9 */ +# define GPIO_I2C3_SCL GPIO_I2C3_SCL_1 /* PA8 - AF4 */ +# define GPIO_I2C3_SDA GPIO_I2C3_SDA_1 /* PC9 - AF4 */ + +# elif defined(CONFIG_NUCLEO_H753ZI_I2C3_PINSET_2) + /* AF4: I2C3 on PH7/PH8 */ +# define GPIO_I2C3_SCL GPIO_I2C3_SCL_2 /* PH7 - AF4 */ +# define GPIO_I2C3_SDA GPIO_I2C3_SDA_2 /* PH8 - AF4 */ +# endif + +# define I2C3_FREQUENCY CONFIG_NUCLEO_H753ZI_I2C3_DEFAULT_FREQUENCY + +#endif /* CONFIG_NUCLEO_H753ZI_I2C3_ENABLE */ + +/* I2C4 Pin Configurations */ + +#ifdef CONFIG_NUCLEO_H753ZI_I2C4_ENABLE + +# ifdef CONFIG_NUCLEO_H753ZI_I2C4_PINSET_1 + /* AF4: I2C4 on PD12/PD13 */ +# define GPIO_I2C4_SCL GPIO_I2C4_SCL_1 /* PD12 - AF4 */ +# define GPIO_I2C4_SDA GPIO_I2C4_SDA_1 /* PD13 - AF4 */ + +# elif defined(CONFIG_NUCLEO_H753ZI_I2C4_PINSET_2) + /* AF4: I2C4 on PF14/PF15 */ +# define GPIO_I2C4_SCL GPIO_I2C4_SCL_2 /* PF14 - AF4 */ +# define GPIO_I2C4_SDA GPIO_I2C4_SDA_2 /* PF15 - AF4 */ + +# elif defined(CONFIG_NUCLEO_H753ZI_I2C4_PINSET_3) + /* AF4: I2C4 on PH11/PH12 */ +# define GPIO_I2C4_SCL GPIO_I2C4_SCL_3 /* PH11 - AF4 */ +# define GPIO_I2C4_SDA GPIO_I2C4_SDA_3 /* PH12 - AF4 */ + +# elif defined(CONFIG_NUCLEO_H753ZI_I2C4_PINSET_4) + /* AF6: I2C4 on PB6/PB7 (shared with I2C1!) */ +# define GPIO_I2C4_SCL GPIO_I2C4_SCL_4 /* PB6 - AF6 */ +# define GPIO_I2C4_SDA GPIO_I2C4_SDA_4 /* PB7 - AF6 */ + +# elif defined(CONFIG_NUCLEO_H753ZI_I2C4_PINSET_5) + /* AF6: I2C4 on PB8/PB9 (shared with I2C1!) */ +# define GPIO_I2C4_SCL GPIO_I2C4_SCL_5 /* PB8 - AF6 */ +# define GPIO_I2C4_SDA GPIO_I2C4_SDA_5 /* PB9 - AF6 */ +# endif + +# define I2C4_FREQUENCY CONFIG_NUCLEO_H753ZI_I2C4_DEFAULT_FREQUENCY + +#endif /* CONFIG_NUCLEO_H753ZI_I2C4_ENABLE */ + +/**************************************************************************** + * Sensors + ****************************************************************************/ + +/* MFRC522 - SPI RFID Reader */ + +#ifdef CONFIG_NUCLEO_H753ZI_MFRC522_ENABLE + +/* Validate Kconfig */ + +# ifndef CONFIG_NUCLEO_H753ZI_MFRC522_SPI_BUS +# error "MFRC522 enabled but SPI bus not configured" +# endif + +# ifndef CONFIG_NUCLEO_H753ZI_MFRC522_DEVID +# error "MFRC522 enabled but device ID not configured" +# endif + +# ifndef CONFIG_NUCLEO_H753ZI_MFRC522_CS_PIN +# error "MFRC522 enabled but CS pin not configured" +# endif + +/* Device configuration (from Kconfig) */ + +# define MFRC522_SPI_BUS CONFIG_NUCLEO_H753ZI_MFRC522_SPI_BUS +# define MFRC522_DEVICE_ID CONFIG_NUCLEO_H753ZI_MFRC522_DEVID +# define MFRC522_CS_PIN CONFIG_NUCLEO_H753ZI_MFRC522_CS_PIN + +/* CS Active Level */ + +# if defined(CONFIG_NUCLEO_H753ZI_MFRC522_CS_ACTIVE_LOW) +# define MFRC522_CS_ACTIVE_LOW true +# elif defined(CONFIG_NUCLEO_H753ZI_MFRC522_CS_ACTIVE_HIGH) +# define MFRC522_CS_ACTIVE_LOW false +# else + /* Default to active low if neither is explicitly set */ +# define MFRC522_CS_ACTIVE_LOW true +# endif + +/* IRQ Configuration */ + +# ifdef CONFIG_NUCLEO_H753ZI_MFRC522_IRQ_ENABLE +# ifndef CONFIG_NUCLEO_H753ZI_MFRC522_IRQ_PIN +# error "MFRC522 IRQ enabled but IRQ pin not configured" +# endif +# define MFRC522_IRQ_PIN CONFIG_NUCLEO_H753ZI_MFRC522_IRQ_PIN +# define MFRC522_IRQ_ENABLED true +# else +# define MFRC522_IRQ_ENABLED false +# endif + +#endif /* CONFIG_NUCLEO_H753ZI_MFRC522_ENABLE */ + +/* LPS22HB - I2C Pressure Sensor */ + +#ifdef CONFIG_SENSORS_LPS22HB +# define GPIO_LPS22HB_INT1 (GPIO_INPUT | GPIO_FLOAT | GPIO_PORTB | \ + GPIO_PIN10) +#endif + +/* LSM6DSL - I2C 6-axis IMU */ + +#ifdef CONFIG_SENSORS_LSM6DSL +# define GPIO_LSM6DSL_INT1 (GPIO_INPUT | GPIO_FLOAT | GPIO_PORTB | \ + GPIO_PIN4) +# define GPIO_LSM6DSL_INT2 (GPIO_INPUT | GPIO_FLOAT | GPIO_PORTB | \ + GPIO_PIN5) +#endif + +/* LSM303AGR - I2C Magnetometer/Accelerometer */ + +/* TODO: Add LSM303AGR GPIO and I2C configurations when needed */ + +/* LSM9DS1 - I2C 9-axis IMU */ + +#ifdef CONFIG_SENSORS_LSM9DS1 +# define LMS9DS1_I2CBUS 1 +#endif + +/* TODO: Add new sensors here following this pattern: + * - Validate required Kconfig settings + * - Define GPIO pins (CS for SPI, INT pins, etc) + * - Define bus configuration (SPI/I2C bus number) + * - Add function prototype in SECTION 5 + * - Implement driver in src/stm32_yoursensor.c + */ + +/**************************************************************************** + * Displays + ****************************************************************************/ + +/* ST7796 - SPI LCD Display (480x320) */ + +#ifdef CONFIG_NUCLEO_H753ZI_ST7796_ENABLE + +/* Validate Kconfig */ + +# ifndef CONFIG_NUCLEO_H753ZI_ST7796_SPI_BUS +# error "ST7796 enabled but SPI bus not configured" +# endif + +# ifndef CONFIG_NUCLEO_H753ZI_ST7796_DEVID +# error "ST7796 enabled but device ID not configured" +# endif + +# ifndef CONFIG_NUCLEO_H753ZI_ST7796_CS_PIN +# error "ST7796 enabled but CS pin not configured" +# endif + +# ifndef CONFIG_NUCLEO_H753ZI_ST7796_DC_PIN +# error "ST7796 enabled but DC pin not configured" +# endif + +# ifndef CONFIG_NUCLEO_H753ZI_ST7796_RESET_PIN +# error "ST7796 enabled but RESET pin not configured" +# endif + +# ifndef CONFIG_NUCLEO_H753ZI_ST7796_LED_PIN +# error "ST7796 enabled but LED pin not configured" +# endif + +/* Device configuration (from Kconfig) */ + +# define ST7796_SPI_BUS CONFIG_NUCLEO_H753ZI_ST7796_SPI_BUS +# define ST7796_DEVICE_ID CONFIG_NUCLEO_H753ZI_ST7796_DEVID +# define ST7796_CS_PIN CONFIG_NUCLEO_H753ZI_ST7796_CS_PIN +# define ST7796_DC_PIN CONFIG_NUCLEO_H753ZI_ST7796_DC_PIN +# define ST7796_RESET_PIN CONFIG_NUCLEO_H753ZI_ST7796_RESET_PIN +# define ST7796_LED_PIN CONFIG_NUCLEO_H753ZI_ST7796_LED_PIN + +/* CS Active Level */ + +# if defined(CONFIG_NUCLEO_H753ZI_ST7796_CS_ACTIVE_LOW) +# define ST7796_CS_ACTIVE_LOW true +# elif defined(CONFIG_NUCLEO_H753ZI_ST7796_CS_ACTIVE_HIGH) +# define ST7796_CS_ACTIVE_LOW false +# else + /* Default to active low if neither is explicitly set */ +# define ST7796_CS_ACTIVE_LOW true +# endif + +#endif /* CONFIG_NUCLEO_H753ZI_ST7796_ENABLE */ + +/* SSD1306 - I2C OLED Display (128x64/128x32) */ + +#ifdef CONFIG_NUCLEO_H753ZI_SSD1306_ENABLE + +/* Hardware configuration from Kconfig */ + +# define NUCLEO_SSD1306_I2C_BUS CONFIG_NUCLEO_H753ZI_SSD1306_I2C_BUS +# define NUCLEO_SSD1306_I2C_ADDR CONFIG_NUCLEO_H753ZI_SSD1306_I2C_ADDR +# define NUCLEO_SSD1306_I2C_FREQUENCY \ + CONFIG_NUCLEO_H753ZI_SSD1306_I2C_FREQUENCY +# define NUCLEO_SSD1306_POWER_PERCENT \ + CONFIG_NUCLEO_H753ZI_SSD1306_POWER_PERCENT + +/* System configuration - from Kconfig */ + +# define NUCLEO_SSD1306_DEVPATH CONFIG_NUCLEO_H753ZI_SSD1306_DEVPATH +# define NUCLEO_SSD1306_DEVNO CONFIG_NUCLEO_H753ZI_SSD1306_DEVNO + +/* Device name for internal tracking */ + +# define NUCLEO_SSD1306_DEVNAME "ssd1306" + +#endif /* CONFIG_NUCLEO_H753ZI_SSD1306_ENABLE */ + +/* TODO: Add new displays here following ST7796/SSD1306 pattern: + * - Validate required Kconfig settings + * - Define GPIO pins (CS, DC, RESET, etc) + * - Define bus configuration (SPI/I2C) + * - Add function prototypes in SECTION 5 + * - Implement driver in src/stm32_yourdisplay.c + */ + +/**************************************************************************** + * Wireless Modules + ****************************************************************************/ + +/* NRF24L01 - SPI 2.4GHz Transceiver */ + +#ifdef CONFIG_WL_NRF24L01 +# define GPIO_NRF24L01_CS (GPIO_OUTPUT | GPIO_SPEED_50MHz | \ + GPIO_OUTPUT_SET | GPIO_PORTA | GPIO_PIN4) +# define GPIO_NRF24L01_CE (GPIO_OUTPUT | GPIO_SPEED_50MHz | \ + GPIO_OUTPUT_CLEAR | GPIO_PORTF | GPIO_PIN12) +# define GPIO_NRF24L01_IRQ (GPIO_INPUT | GPIO_FLOAT | GPIO_PORTD | \ + GPIO_PIN15) +#endif + +/* TODO: Add new wireless modules here following NRF24L01 pattern: + * - WiFi modules (ESP8266, ESP32-AT, etc) + * - LoRa modules (SX1276, SX1278, etc) + * - Bluetooth modules (HC-05, nRF52, etc) + * - Validate Kconfig settings + * - Define GPIO pins + * - Add function prototypes in SECTION 5 + * - Implement driver in src/stm32_yourwireless.c + */ + +/**************************************************************************** + * Storage Devices + ****************************************************************************/ + +/* MMCSD - SPI SD Card */ + +#ifdef CONFIG_MMCSD_SPI +# define GPIO_MMCSD_CS (GPIO_OUTPUT | GPIO_PUSHPULL | \ + GPIO_SPEED_50MHz | GPIO_OUTPUT_SET | \ + GPIO_PORTD | GPIO_PIN15) +# define GPIO_MMCSD_NCD (GPIO_INPUT | GPIO_PULLUP | GPIO_EXTI | \ + GPIO_PORTF | GPIO_PIN12) +#endif + +/* TODO: Add new storage devices here following MMCSD pattern: + * - QSPI Flash (W25Q, MX25, etc) + * - I2C EEPROM (AT24C, M24C, etc) + * - SPI Flash (AT25, SST25, etc) + * - Validate Kconfig settings + * - Define GPIO pins (CS, WP, HOLD, etc) + * - Add function prototypes in SECTION 5 + * - Implement driver in src/stm32_yourstorage.c + */ + +/**************************************************************************** + * Actuators & LED Controllers + ****************************************************************************/ + +/* PCA9635 - I2C LED Controller */ + +#ifdef CONFIG_PCA9635PW +# define PCA9635_I2CBUS 1 +# define PCA9635_I2CADDR 0x40 +#endif + +/* PWM Configuration */ + +#define NUCLEOH753ZI_PWMTIMER 1 + +/* TODO: Add new actuators here: + * - Servo controllers (PCA9685, etc) + * - Motor drivers (DRV8833, L298N, etc) + * - Relay modules + * - Define GPIO pins + * - Define bus configuration + * - Add function prototypes in SECTION 5 + * - Implement driver in src/stm32_youractuator.c + */ + +/**************************************************************************** + * SECTION 5: FUNCTION PROTOTYPES + ****************************************************************************/ + +/**************************************************************************** + * Core System Initialization + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_bringup + * + * Description: + * Perform architecture-specific initialization + * + * CONFIG_BOARD_LATE_INITIALIZE=y : + * Called from board_late_initialize(). + * + * CONFIG_BOARD_LATE_INITIALIZE=n && CONFIG_BOARDCTL=y && + * CONFIG_NSH_ARCHINIT: + * Called from the NSH library + * + ****************************************************************************/ + +int stm32_bringup(void); + +/**************************************************************************** + * Communication Bus Drivers - SPI + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_spi_initialize + * + * Description: + * Initialize SPI interfaces and CS pins. + * + * Returned Value: + * OK on success, negative errno on error + * + ****************************************************************************/ + +#ifdef CONFIG_STM32H7_SPI +int stm32_spi_initialize(void); + +/**************************************************************************** + * Name: stm32_spi_register_cs_device + * + * Description: + * Register a CS device for a specific SPI bus and device ID. + * + * Input Parameters: + * spi_bus - SPI bus number (1-6) + * devid - Device ID (0-15) + * cs_pin - CS pin string (e.g., "PF1") + * active_low - true if CS is active low, false if active high + * + * Returned Value: + * OK on success, negative errno on error + * + ****************************************************************************/ + +int stm32_spi_register_cs_device(int spi_bus, uint32_t devid, + const char *cs_pin, bool active_low); + +/**************************************************************************** + * Name: stm32_spi_unregister_cs_device + * + * Description: + * Unregister a CS device. + * + * Input Parameters: + * spi_bus - SPI bus number (1-6) + * devid - Device ID + * + * Returned Value: + * OK on success, negative errno on error + * + ****************************************************************************/ + +int stm32_spi_unregister_cs_device(int spi_bus, uint32_t devid); + +#ifdef CONFIG_SPI_CMDDATA + +/**************************************************************************** + * Name: stm32_spi_register_dc_pin + * + * Description: + * Register CMD/DATA pin for SPI devices (e.g., displays). + * + * Input Parameters: + * spi_bus - SPI bus number (1-6) + * devid - Device ID + * dc_pin - DC pin string (e.g., "PF2") + * + * Returned Value: + * OK on success, negative errno on error + * + ****************************************************************************/ + +int stm32_spi_register_dc_pin(int spi_bus, uint32_t devid, + const char *dc_pin); + +#endif /* CONFIG_SPI_CMDDATA */ +#endif /* CONFIG_STM32H7_SPI */ + +/**************************************************************************** + * Name: stm32_spidev_initialize + * + * Description: + * Called to configure SPI chip select GPIO pins for the Nucleo-H753ZI + * board. + * + ****************************************************************************/ + +#if defined(CONFIG_STM32H7_SPI1) || defined(CONFIG_STM32H7_SPI2) || \ + defined(CONFIG_STM32H7_SPI3) || defined(CONFIG_STM32H7_SPI4) || \ + defined(CONFIG_STM32H7_SPI5) || defined(CONFIG_STM32H7_SPI6) +void weak_function stm32_spidev_initialize(void); +#endif + +#ifdef CONFIG_SPI_DRIVER + +/**************************************************************************** + * Name: stm32_spidev_register_all + * + * Description: + * Register all SPI devices for userspace access. + * + * Returned Value: + * OK on success, negative errno on error + * + ****************************************************************************/ + +int stm32_spidev_register_all(void); + +#endif + +/**************************************************************************** + * Communication Bus Drivers - I2C + ****************************************************************************/ + +#ifdef CONFIG_STM32H7_I2C + +/**************************************************************************** + * Name: stm32_i2c_initialize + * + * Description: + * Initialize I2C buses based on Kconfig configuration. + * + * Returned Value: + * OK on success, negative errno on error + * + ****************************************************************************/ + +int stm32_i2c_initialize(void); + +/**************************************************************************** + * Name: stm32_i2c_register_device + * + * Description: + * Register an I2C device with specific address, frequency, and name. + * + * Input Parameters: + * i2c_bus - I2C bus number (1-4) + * addr - I2C slave address (7-bit, 0x08-0x77) + * frequency - Bus frequency for this device (Hz) + * name - Descriptive name for logging (can be NULL) + * + * Returned Value: + * OK on success, negative errno on error + * + ****************************************************************************/ + +int stm32_i2c_register_device(int i2c_bus, uint8_t addr, + uint32_t frequency, const char *name); + +/**************************************************************************** + * Name: stm32_i2c_unregister_device + * + * Description: + * Unregister an I2C device by address. + * + * Input Parameters: + * i2c_bus - I2C bus number (1-4) + * addr - I2C slave address to unregister + * + * Returned Value: + * OK on success, negative errno on error + * + ****************************************************************************/ + +int stm32_i2c_unregister_device(int i2c_bus, uint8_t addr); + +/**************************************************************************** + * Name: stm32_i2c_get_master + * + * Description: + * Get I2C master interface for a specific bus. + * + * Input Parameters: + * i2c_bus - I2C bus number (1-4) + * + * Returned Value: + * Pointer to I2C master interface, NULL if invalid or not initialized + * + ****************************************************************************/ + +struct i2c_master_s *stm32_i2c_get_master(int i2c_bus); + +#ifdef CONFIG_I2C_RESET + +/**************************************************************************** + * Name: stm32_i2c_scan_bus + * + * Description: + * Scan an I2C bus for connected devices (debugging). + * + * Input Parameters: + * i2c_bus - I2C bus number (1-4) + * + * Returned Value: + * Number of devices found, negative errno on error + * + ****************************************************************************/ + +int stm32_i2c_scan_bus(int i2c_bus); + +#endif + +/**************************************************************************** + * Name: stm32_i2c_list_devices + * + * Description: + * List all registered I2C devices on a specific bus (debugging). + * + * Input Parameters: + * i2c_bus - I2C bus number (1-4), or 0 for all buses + * + * Returned Value: + * Number of registered devices + * + ****************************************************************************/ + +int stm32_i2c_list_devices(int i2c_bus); + +#endif /* CONFIG_STM32H7_I2C */ + +/**************************************************************************** + * CAN/FDCAN Drivers + ****************************************************************************/ + +#ifdef CONFIG_STM32H7_FDCAN + +/**************************************************************************** + * Name: stm32_fdcansockinitialize + * + * Description: + * Initialize FDCAN socket interface. + * + * Input Parameters: + * intf - Interface number (0 for FDCAN1/can0, 1 for FDCAN2/can1) + * + * Returned Value: + * OK on success, negative errno on error + * + ****************************************************************************/ + +int stm32_fdcansockinitialize(int intf); + +#endif + +/**************************************************************************** + * USB Drivers + ****************************************************************************/ + +#ifdef CONFIG_STM32H7_OTGFS +void weak_function stm32_usbinitialize(void); +#endif + +#if defined(CONFIG_STM32H7_OTGFS) && defined(CONFIG_USBHOST) + +/**************************************************************************** + * Name: stm32_usbhost_initialize + * + * Description: + * Initialize USB host controller. + * + * Returned Value: + * OK on success, negative errno on error + * + ****************************************************************************/ + +int stm32_usbhost_initialize(void); + +#endif + +/**************************************************************************** + * Sensor Drivers + ****************************************************************************/ + +#ifdef CONFIG_NUCLEO_H753ZI_MFRC522_ENABLE + +/**************************************************************************** + * Name: stm32_mfrc522initialize + * + * Description: + * Initialize MFRC522 RFID reader. + * + * Input Parameters: + * devpath - Device path (e.g., "/dev/rfid0") + * + * Returned Value: + * OK on success, negative errno on error + * + ****************************************************************************/ + +int stm32_mfrc522initialize(const char *devpath); + +#endif + +#ifdef CONFIG_SENSORS_LSM6DSL + +/**************************************************************************** + * Name: stm32_lsm6dsl_initialize + * + * Description: + * Initialize LSM6DSL 6-axis IMU sensor. + * + * Input Parameters: + * devpath - Device path (e.g., "/dev/lsm6dsl0") + * + * Returned Value: + * OK on success, negative errno on error + * + ****************************************************************************/ + +int stm32_lsm6dsl_initialize(char *devpath); + +#endif + +#ifdef CONFIG_SENSORS_LSM303AGR + +/**************************************************************************** + * Name: stm32_lsm303agr_initialize + * + * Description: + * Initialize LSM303AGR magnetometer/accelerometer. + * + * Input Parameters: + * devpath - Device path + * + * Returned Value: + * OK on success, negative errno on error + * + ****************************************************************************/ + +int stm32_lsm303agr_initialize(char *devpath); + +#endif + +#ifdef CONFIG_SENSORS_LSM9DS1 + +/**************************************************************************** + * Name: stm32_lsm9ds1_initialize + * + * Description: + * Initialize LSM9DS1 9-axis IMU sensor. + * + * Input Parameters: + * devpath - Device path + * + * Returned Value: + * OK on success, negative errno on error + * + ****************************************************************************/ + +int stm32_lsm9ds1_initialize(char *devpath); + +#endif + +/**************************************************************************** + * Display Drivers + ****************************************************************************/ + +/**************************************************************************** + * ST7796 TFT Display Support + ****************************************************************************/ + +#if defined(CONFIG_LCD_ST7796) && defined(CONFIG_NUCLEO_H753ZI_ST7796_ENABLE) + +/**************************************************************************** + * Name: stm32_st7796initialize + * + * Description: + * Initialize and register the ST7796 LCD framebuffer driver. + * + * Input Parameters: + * devno - Device number (0 for /dev/fb0) + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +int stm32_st7796initialize(int devno); + +/**************************************************************************** + * Name: stm32_st7796_flush_fb + * + * Description: + * Flush the entire framebuffer to the display. This is needed for SPI + * displays to make the splashscreen visible after fb_register(). + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +int stm32_st7796_flush_fb(void); + +/**************************************************************************** + * Name: stm32_st7796_backlight + * + * Description: + * Control the ST7796 backlight LED. + * + * Input Parameters: + * on - true to turn on, false to turn off + * + * Returned Value: + * None + * + ****************************************************************************/ + +void stm32_st7796_backlight(bool on); + +/**************************************************************************** + * Name: stm32_st7796_power + * + * Description: + * Control the ST7796 display power. + * + * Input Parameters: + * on - true to turn on, false to turn off + * + * Returned Value: + * None + * + ****************************************************************************/ + +void stm32_st7796_power(bool on); + +/**************************************************************************** + * Name: stm32_st7796_reset_display + * + * Description: + * Perform hardware reset of the ST7796 display. + * + * Returned Value: + * None + * + ****************************************************************************/ + +void stm32_st7796_reset_display(void); + +/**************************************************************************** + * Name: stm32_st7796_cleanup + * + * Description: + * Cleanup ST7796 resources. + * + * Returned Value: + * OK on success, negative errno on error + * + ****************************************************************************/ + +int stm32_st7796_cleanup(void); + +#endif /* CONFIG_LCD_ST7796 && CONFIG_NUCLEO_H753ZI_ST7796_ENABLE */ + +#ifdef CONFIG_NUCLEO_H753ZI_SSD1306_ENABLE +/**************************************************************************** + * Name: stm32_ssd1306_get_devpath + * + * Description: + * Get the configured device path for SSD1306. + * + * Returned Value: + * Pointer to device path string + * + ****************************************************************************/ + +const char *stm32_ssd1306_get_devpath(void); + +/**************************************************************************** + * Name: stm32_ssd1306_set_power + * + * Description: + * Change SSD1306 display power at runtime. + * + * Input Parameters: + * percent - Power level 0-100% (0 = off, 1-100 = on with brightness) + * + * Returned Value: + * OK on success, negative errno on error + * + ****************************************************************************/ + +int stm32_ssd1306_set_power(int percent); + +/**************************************************************************** + * Name: stm32_ssd1306_set_brightness + * + * Description: + * Change SSD1306 display brightness at runtime (display must be on). + * + * Input Parameters: + * percent - Brightness level 0-100% + * + * Returned Value: + * OK on success, negative errno on error + * + ****************************************************************************/ + +int stm32_ssd1306_set_brightness(int percent); + +#endif /* CONFIG_NUCLEO_H753ZI_SSD1306_ENABLE */ + +/**************************************************************************** + * Wireless Drivers + ****************************************************************************/ + +#ifdef CONFIG_WL_NRF24L01 + +/**************************************************************************** + * Name: stm32_wlinitialize + * + * Description: + * Initialize NRF24L01 wireless module. + * + * Returned Value: + * OK on success, negative errno on error + * + ****************************************************************************/ + +int stm32_wlinitialize(void); + +#endif + +/**************************************************************************** + * Storage Drivers + ****************************************************************************/ + +#ifdef CONFIG_MMCSD_SPI + +/**************************************************************************** + * Name: stm32_mmcsd_initialize + * + * Description: + * Initialize MMC/SD card over SPI. + * + * Input Parameters: + * minor - Device minor number + * + * Returned Value: + * OK on success, negative errno on error + * + ****************************************************************************/ + +int stm32_mmcsd_initialize(int minor); + +#endif + +#ifdef CONFIG_MTD +#ifdef HAVE_PROGMEM_CHARDEV + +/**************************************************************************** + * Name: stm32_progmem_init + * + * Description: + * Initialize internal flash as MTD device. + * + * Returned Value: + * OK on success, negative errno on error + * + ****************************************************************************/ + +int stm32_progmem_init(void); + +#endif /* HAVE_PROGMEM_CHARDEV */ +#endif /* CONFIG_MTD */ + +/**************************************************************************** + * Actuator & LED Controller Drivers + ****************************************************************************/ + +#ifdef CONFIG_PCA9635PW + +/**************************************************************************** + * Name: stm32_pca9635_initialize + * + * Description: + * Initialize PCA9635 I2C LED controller. + * + * Returned Value: + * OK on success, negative errno on error + * + ****************************************************************************/ + +int stm32_pca9635_initialize(void); + +#endif + +#ifdef CONFIG_PWM + +/**************************************************************************** + * Name: stm32_pwm_setup + * + * Description: + * Initialize PWM outputs. + * + * Returned Value: + * OK on success, negative errno on error + * + ****************************************************************************/ + +int stm32_pwm_setup(void); + +#endif + +/**************************************************************************** + * GPIO & ADC Drivers + ****************************************************************************/ + +#ifdef CONFIG_DEV_GPIO + +/**************************************************************************** + * Name: stm32_gpio_initialize + * + * Description: + * Initialize GPIO drivers for use with /apps/examples/gpio + * + * Returned Value: + * OK on success, negative errno on error + * + ****************************************************************************/ + +int stm32_gpio_initialize(void); + +#endif + +#ifdef CONFIG_ADC + +/**************************************************************************** + * Name: stm32_adc_setup + * + * Description: + * Initialize ADC and register the ADC driver. + * + * Returned Value: + * OK on success, negative errno on error + * + ****************************************************************************/ + +int stm32_adc_setup(void); + +#endif + +#endif /* __BOARDS_ARM_STM32H7_NUCLEO_H753ZI_SRC_NUCLEO_H753ZI_H */ diff --git a/boards/arm/stm32h7/nucleo-h753zi/src/stm32_adc.c b/boards/arm/stm32h7/nucleo-h753zi/src/stm32_adc.c new file mode 100644 index 0000000000000..d56ebe5de64bd --- /dev/null +++ b/boards/arm/stm32h7/nucleo-h753zi/src/stm32_adc.c @@ -0,0 +1,270 @@ +/**************************************************************************** + * boards/arm/stm32h7/nucleo-h753zi/src/stm32_adc.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include + +#include "chip.h" +#include "stm32_gpio.h" +#include "stm32_adc.h" + +#include "nucleo-h753zi.h" + +#ifdef CONFIG_ADC + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Configuration ************************************************************/ + +/* Up to 3 ADC interfaces are supported */ + +#if defined(CONFIG_STM32H7_ADC1) || defined(CONFIG_STM32H7_ADC2) || \ + defined(CONFIG_STM32H7_ADC3) + +/* The number of ADC channels in the conversion list */ + +#define ADC1_NCHANNELS 7 +#define ADC2_NCHANNELS 5 +#define ADC3_NCHANNELS 1 + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +#ifdef CONFIG_STM32H7_ADC1 +/* Identifying number of each ADC channel: Variable Resistor. + * + * ADC1: {5, 10, 15, 18, 19, 7, 12}; + */ + +static const uint8_t g_adc1_chanlist[ADC1_NCHANNELS] = +{ + 5, 10, 15, 18, 19, 7, 12 +}; + +static const uint32_t g_adc1_pinlist[ADC1_NCHANNELS] = + { + GPIO_ADC12_INP5, + GPIO_ADC123_INP10, + GPIO_ADC12_INP15, + GPIO_ADC12_INP18, + GPIO_ADC12_INP19, + GPIO_ADC123_INP7, + GPIO_ADC123_INP12 + }; + +#endif /* CONFIG_STM32H7_ADC1 */ + +/**************************************************************************** + * ADC2 + ****************************************************************************/ +#ifdef CONFIG_STM32H7_ADC2 + +static const uint8_t g_adc2_chanlist[ADC2_NCHANNELS] = +{ + 2, 3, 14, 4, 8 +}; + +static const uint32_t g_adc2_pinlist[ADC2_NCHANNELS] = +{ + GPIO_ADC2_INP2, + GPIO_ADC12_INP3, + GPIO_ADC12_INP14, + GPIO_ADC12_INP4, + GPIO_ADC12_INP8 +}; +#endif /* CONFIG_STM32H7_ADC2 */ + +#ifdef CONFIG_STM32H7_ADC3 +/* Identifying number of each ADC channel: Variable Resistor. + * + * ADC3: {6,}; + */ + +static const uint8_t g_adc3_chanlist[ADC1_NCHANNELS] = +{ + 11 +}; + +/* Configurations of pins used by each ADC channels + * + * + * ADC3: {GPIO_ADC3_INP6} + */ + +static const uint32_t g_adc3_pinlist[ADC3_NCHANNELS] = +{ + GPIO_ADC123_INP11, +}; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_adc_setup + * + * Description: + * Initialize ADC and register the ADC driver. + * + ****************************************************************************/ + +int stm32_adc_setup(void) +{ +#if defined(CONFIG_STM32H7_ADC1) || defined(CONFIG_STM32H7_ADC3) + static bool initialized = false; + struct adc_dev_s *adc; + int ret; + int i; + char devname[] = "/dev/adc0"; + + /* Check if we have already initialized */ + + if (!initialized) + { +#endif +#if defined(CONFIG_STM32H7_ADC1) + /* Configure the pins as analog inputs for the selected channels */ + + for (i = 0; i < ADC1_NCHANNELS; i++) + { + if (g_adc1_pinlist[i] != 0) + { + stm32_configgpio(g_adc1_pinlist[i]); + } + } + + /* Call stm32_adcinitialize() to get an instance of the ADC interface */ + + adc = stm32h7_adc_initialize(1, g_adc1_chanlist, ADC1_NCHANNELS); + if (adc == NULL) + { + aerr("ERROR: Failed to get ADC1 interface\n"); + return -ENODEV; + } + + /* Register the ADC driver at "/dev/adc0" */ + + ret = adc_register(devname, adc); + if (ret < 0) + { + aerr("ERROR: adc_register(%s) failed: %d\n", devname, ret); + return ret; + } + + devname[8]++; +#endif + +#ifdef CONFIG_STM32H7_ADC2 + /* Configure the pins as analog inputs for the selected channels */ + + for (i = 0; i < ADC2_NCHANNELS; i++) + { + if (g_adc2_pinlist[i] != 0) + { + stm32_configgpio(g_adc2_pinlist[i]); + } + } + + /* Call stm32_adcinitialize() to get an instance of the ADC interface */ + + adc = stm32h7_adc_initialize(2, g_adc2_chanlist, ADC2_NCHANNELS); + if (adc == NULL) + { + aerr("ERROR: Failed to get ADC2 interface\n"); + return -ENODEV; + } + + /* Register the ADC driver at "/dev/adc[0-1]" */ + + ret = adc_register(devname, adc); + if (ret < 0) + { + aerr("ERROR: adc_register(%s) failed: %d\n", devname, ret); + return ret; + } + + devname[8]++; +#endif + +#if defined(CONFIG_STM32H7_ADC3) + /* Configure the pins as analog inputs for the selected channels */ + + for (i = 0; i < ADC3_NCHANNELS; i++) + { + if (g_adc3_pinlist[i] != 0) + { + stm32_configgpio(g_adc3_pinlist[i]); + } + } + + /* Call stm32_adcinitialize() to get an instance of the ADC interface */ + + adc = stm32h7_adc_initialize(3, g_adc3_chanlist, ADC3_NCHANNELS); + if (adc == NULL) + { + aerr("ERROR: Failed to get ADC3 interface\n"); + return -ENODEV; + } + + /* Register the ADC driver at "/dev/adc[0-2]" */ + + ret = adc_register(devname, adc); + if (ret < 0) + { + aerr("ERROR: adc_register(%s) failed: %d\n", devname, ret); + return ret; + } +#endif + +#if defined(CONFIG_STM32H7_ADC1) || defined(CONFIG_STM32H7_ADC2) || \ + defined(CONFIG_STM32H7_ADC3) + /* Now we are initialized */ + + initialized = true; + } + + return OK; +#else + return -ENOSYS; +#endif +} + +#endif /* CONFIG_STM32H7_ADC1 || CONFIG_STM32H7_ADC2 || CONFIG_STM32H7_ADC3 */ +#endif /* CONFIG_ADC */ diff --git a/boards/arm/stm32h7/nucleo-h753zi/src/stm32_appinitialize.c b/boards/arm/stm32h7/nucleo-h753zi/src/stm32_appinitialize.c new file mode 100644 index 0000000000000..0f63bdcb24295 --- /dev/null +++ b/boards/arm/stm32h7/nucleo-h753zi/src/stm32_appinitialize.c @@ -0,0 +1,78 @@ +/**************************************************************************** + * boards/arm/stm32h7/nucleo-h753zi/src/stm32_appinitialize.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include "nucleo-h753zi.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_app_initialize + * + * Description: + * Perform application specific initialization. This function is never + * called directly from application code, but only indirectly via the + * (non-standard) boardctl() interface using the command BOARDIOC_INIT. + * + * Input Parameters: + * arg - The boardctl() argument is passed to the board_app_initialize() + * implementation without modification. The argument has no + * meaning to NuttX; the meaning of the argument is a contract + * between the board-specific initialization logic and the + * matching application logic. The value could be such things as a + * mode enumeration value, a set of DIP switch switch settings, a + * pointer to configuration data read from a file or serial FLASH, + * or whatever you would like to do with it. Every implementation + * should accept zero/NULL as a default configuration. + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned on + * any failure to indicate the nature of the failure. + * + ****************************************************************************/ + +int board_app_initialize(uintptr_t arg) +{ +#ifdef CONFIG_BOARD_LATE_INITIALIZE + /* Board initialization already performed by board_late_initialize() */ + + return OK; +#else + /* Perform board-specific initialization */ + + return stm32_bringup(); +#endif +} diff --git a/boards/arm/stm32h7/nucleo-h753zi/src/stm32_autoleds.c b/boards/arm/stm32h7/nucleo-h753zi/src/stm32_autoleds.c new file mode 100644 index 0000000000000..df65cfd694d63 --- /dev/null +++ b/boards/arm/stm32h7/nucleo-h753zi/src/stm32_autoleds.c @@ -0,0 +1,179 @@ +/**************************************************************************** + * boards/arm/stm32h7/nucleo-h753zi/src/stm32_autoleds.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include + +#include +#include + +#include "stm32_gpio.h" +#include "nucleo-h753zi.h" + +/* Only compile when AUTO LEDs mode is enabled */ +#ifdef CONFIG_ARCH_LEDS + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* Indexed by BOARD_LED_ */ + +static const uint32_t g_ledmap[BOARD_NLEDS] = +{ + GPIO_LED_GREEN, + GPIO_LED_ORANGE, + GPIO_LED_RED, +}; + +static bool g_initialized; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static void phy_set_led(int led, bool state) +{ + /* Active High */ + + stm32_gpiowrite(g_ledmap[led], state); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_autoled_initialize + ****************************************************************************/ + +void board_autoled_initialize(void) +{ + int i; + + /* Configure the LED GPIOs for output. Initial state is OFF */ + + for (i = 0; i < nitems(g_ledmap); i++) + { + stm32_configgpio(g_ledmap[i]); + } + +#ifdef CONFIG_NUCLEO_H753ZI_LEDS_AUTO + + /* Log only when explicitly configured for AUTO mode */ + + ledinfo("Auto LEDs initialized for kernel status indication\n"); +#endif +} + +/**************************************************************************** + * Name: board_autoled_on + ****************************************************************************/ + +void board_autoled_on(int led) +{ + switch (led) + { + default: + break; + + case LED_HEAPALLOCATE: + phy_set_led(BOARD_LED_ORANGE, true); + break; + + case LED_IRQSENABLED: + phy_set_led(BOARD_LED_ORANGE, false); + phy_set_led(BOARD_LED_GREEN, true); + break; + + case LED_STACKCREATED: + phy_set_led(BOARD_LED_GREEN, true); + phy_set_led(BOARD_LED_ORANGE, true); + g_initialized = true; + break; + + case LED_INIRQ: + phy_set_led(BOARD_LED_ORANGE, true); + break; + + case LED_SIGNAL: + phy_set_led(BOARD_LED_GREEN, true); + break; + + case LED_ASSERTION: + phy_set_led(BOARD_LED_RED, true); + phy_set_led(BOARD_LED_ORANGE, true); + break; + + case LED_PANIC: + phy_set_led(BOARD_LED_RED, true); + break; + + case LED_IDLE : /* IDLE */ + phy_set_led(BOARD_LED_RED, true); + break; + } +} + +/**************************************************************************** + * Name: board_autoled_off + ****************************************************************************/ + +void board_autoled_off(int led) +{ + switch (led) + { + default: + break; + + case LED_SIGNAL: + phy_set_led(BOARD_LED_GREEN, false); + break; + + case LED_INIRQ: + phy_set_led(BOARD_LED_ORANGE, false); + break; + + case LED_ASSERTION: + phy_set_led(BOARD_LED_RED, false); + phy_set_led(BOARD_LED_ORANGE, false); + break; + + case LED_PANIC: + phy_set_led(BOARD_LED_RED, false); + break; + + case LED_IDLE : /* IDLE */ + phy_set_led(BOARD_LED_RED, false); + break; + } +} + +#endif /* CONFIG_ARCH_LEDS */ diff --git a/boards/arm/stm32h7/nucleo-h753zi/src/stm32_boot.c b/boards/arm/stm32h7/nucleo-h753zi/src/stm32_boot.c new file mode 100644 index 0000000000000..c2d2774582abe --- /dev/null +++ b/boards/arm/stm32h7/nucleo-h753zi/src/stm32_boot.c @@ -0,0 +1,93 @@ +/**************************************************************************** + * boards/arm/stm32h7/nucleo-h753zi/src/stm32_boot.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include + +#include "arm_internal.h" +#include "stm32_start.h" +#include "nucleo-h753zi.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_boardinitialize + * + * Description: + * All STM32 architectures must provide the following entry point. + * This entry point is called early in the initialization -- after all + * memory has been configured and mapped but before any devices have been + * initialized. + * + ****************************************************************************/ + +void stm32_boardinitialize(void) +{ +#ifdef CONFIG_ARCH_LEDS + /* Configure on-board LEDs if LED support has been selected. */ + + board_autoled_initialize(); +#endif + +#if defined(CONFIG_STM32H7_OTGFS) || defined(CONFIG_STM32H7_HOST) + /* Initialize USB */ + + stm32_usbinitialize(); +#endif + +#ifdef CONFIG_STM32H7_SPI + /* Configure SPI chip selects */ + + stm32_spidev_initialize(); +#endif +} + +/**************************************************************************** + * Name: board_late_initialize + * + * Description: + * If CONFIG_BOARD_LATE_INITIALIZE is selected, then an additional + * initialization call will be performed in the boot-up sequence to a + * function called board_late_initialize(). board_late_initialize() + * will be called immediately after up_initialize() is called and just + * before the initial application is started. This additional + * initialization phase may be used, for example, to initialize board- + * specific device drivers. + * + ****************************************************************************/ + +#ifdef CONFIG_BOARD_LATE_INITIALIZE +void board_late_initialize(void) +{ + stm32_bringup(); +} +#endif diff --git a/boards/arm/stm32h7/nucleo-h753zi/src/stm32_boot_image.c b/boards/arm/stm32h7/nucleo-h753zi/src/stm32_boot_image.c new file mode 100644 index 0000000000000..617977c07d87f --- /dev/null +++ b/boards/arm/stm32h7/nucleo-h753zi/src/stm32_boot_image.c @@ -0,0 +1,185 @@ +/**************************************************************************** + * boards/arm/stm32h7/nucleo-h753zi/src/stm32_boot_image.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include "nvic.h" +#include "arm_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* This structure represents the first two entries on NVIC vector table */ + +struct arm_vector_table +{ + uint32_t spr; /* Stack pointer on reset */ + uint32_t reset; /* Pointer to reset exception handler */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static void cleanup_arm_nvic(void); +static void systick_disable(void); + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: cleanup_arm_nvic + * + * Description: + * Acknowledge and disable all interrupts in NVIC + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void cleanup_arm_nvic(void) +{ + int i; + + /* Allow any pending interrupts to be recognized */ + + UP_ISB(); + cpsid(); + + /* Disable all interrupts */ + + for (i = 0; i < NR_IRQS; i += 32) + { + putreg32(0xffffffff, NVIC_IRQ_CLEAR(i)); + } + + /* Clear all pending interrupts */ + + for (i = 0; i < NR_IRQS; i += 32) + { + putreg32(0xffffffff, NVIC_IRQ_CLRPEND(i)); + } +} + +/**************************************************************************** + * Name: systick_disable + * + * Description: + * Disable the SysTick system timer + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void systick_disable(void) +{ + putreg32(0, NVIC_SYSTICK_CTRL); + putreg32(NVIC_SYSTICK_RELOAD_MASK, NVIC_SYSTICK_RELOAD); + putreg32(0, NVIC_SYSTICK_CURRENT); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_boot_image + * + * Description: + * This entry point is called by bootloader to jump to application image. + * + ****************************************************************************/ + +int board_boot_image(const char *path, uint32_t hdr_size) +{ + static struct arm_vector_table vt; + struct file file; + ssize_t bytes; + int ret; + + ret = file_open(&file, path, O_RDONLY | O_CLOEXEC); + if (ret < 0) + { + syslog(LOG_ERR, "Failed to open %s with: %d", path, ret); + return ret; + } + + bytes = file_pread(&file, &vt, sizeof(vt), hdr_size); + if (bytes != sizeof(vt)) + { + syslog(LOG_ERR, "Failed to read ARM vector table: %d", bytes); + return bytes < 0 ? bytes : -1; + } + + systick_disable(); + + cleanup_arm_nvic(); + +#ifdef CONFIG_ARMV7M_DCACHE + up_disable_dcache(); +#endif +#ifdef CONFIG_ARMV7M_ICACHE + up_disable_icache(); +#endif + +#ifdef CONFIG_ARM_MPU + mpu_control(false, false, false); +#endif + + /* Set main and process stack pointers */ + + __asm__ __volatile__("\tmsr msp, %0\n" + "\tmsr control, %1\n" + "\tisb\n" + "\tmov pc, %2\n" + : + : "r" (vt.spr), "r" (0), "r" (vt.reset)); + + return 0; +} diff --git a/boards/arm/stm32h7/nucleo-h753zi/src/stm32_bringup.c b/boards/arm/stm32h7/nucleo-h753zi/src/stm32_bringup.c new file mode 100644 index 0000000000000..810c70cdbed01 --- /dev/null +++ b/boards/arm/stm32h7/nucleo-h753zi/src/stm32_bringup.c @@ -0,0 +1,1547 @@ +/**************************************************************************** + * boards/arm/stm32h7/nucleo-h753zi/src/stm32_bringup.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/* System includes */ + +#include +#include +#include +#include +#include + +/* Filesystem includes */ + +#include + +/* Communication protocol includes */ + +#ifdef CONFIG_I2C +# include +#endif + +#ifdef CONFIG_SPI +# include +#endif + +/* STM32-specific includes */ + +#include "stm32_gpio.h" +#include "hardware/stm32_gpio.h" +#include "arm_internal.h" +#include "hardware/stm32h7x3xx_rcc.h" + +#ifdef CONFIG_STM32H7_I2C +# include "stm32_i2c.h" +#endif + +#ifdef CONFIG_STM32H7_SPI +# include "stm32_spi.h" +#endif + +/* Display includes */ + +#ifdef CONFIG_LCD_ST7796 +# include +# include +#endif + +#ifdef CONFIG_LCD_DEV +# include +#endif + +#ifdef CONFIG_LCD_SSD1306 +# include +# include +#endif + +#include +#include "nucleo-h753zi.h" + +/* USB-related includes */ + +#ifdef CONFIG_USBMONITOR +# include +#endif + +#ifdef CONFIG_STM32H7_OTGFS +# include "stm32_usbhost.h" +#endif + +#ifdef CONFIG_RNDIS +# include +#endif + +/* Input device includes */ + +#ifdef CONFIG_INPUT_BUTTONS +# include +#endif + +/* LED includes */ + +#ifdef CONFIG_USERLED +# include +#endif + +/* Timer-related includes */ + +#ifdef HAVE_RTC_DRIVER +# include +# include "stm32_rtc.h" +#endif + +#ifdef CONFIG_CAPTURE +# include +# include "stm32_capture.h" +#endif + +#ifdef CONFIG_STM32H7_IWDG +# include "stm32_wdg.h" +#endif + +/* Storage includes */ + +#ifdef CONFIG_STM32_ROMFS +# include "drivers/driver_middleware/stm32_romfs.h" +#endif + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* Initialization functions organized by name length (longest to shortest) */ + +static int nucleo_automotive_initialize(void); +static int nucleo_communication_initialize(void); +static int nucleo_connectivity_initialize(void); +static int nucleo_filesystem_initialize(void); +static int nucleo_watchdog_initialize(void); +static int nucleo_sensors_initialize(void); +static int nucleo_display_initialize(void); +static int nucleo_storage_initialize(void); +static int nucleo_timers_initialize(void); +static int nucleo_input_initialize(void); +static int nucleo_gpio_initialize(void); +static int nucleo_led_initialize(void); +static int nucleo_usb_initialize(void); +static int nucleo_rtc_initialize(void); +static int nucleo_adc_initialize(void); + +#if defined(CONFIG_I2C) && defined(CONFIG_SYSTEM_I2CTOOL) + static int nucleo_i2c_tools_initialize(void); +#endif + +#ifdef CONFIG_CAPTURE + static int nucleo_capture_initialize(void); +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nucleo_led_initialize + * + * Description: + * Initialize LED subsystem based on configuration + * Priority: HIGH (provides early visual feedback) + * + * Dependencies: None + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int nucleo_led_initialize(void) +{ + int ret = OK; + +#ifdef CONFIG_NUCLEO_H753ZI_LEDS_USER + + ret = userled_lower_initialize("/dev/userleds"); + if (ret < 0) + { + syslog(LOG_ERR, + "[ERROR: BRINGUP] - userled_lower_initialize() " + "failed: %d\n", ret); + } + else + { + syslog(LOG_INFO, + "[INFO: BRINGUP] - User LEDs initialized at " + "/dev/userleds\n"); + } + +#elif defined(CONFIG_NUCLEO_H753ZI_LEDS_AUTO) + + syslog(LOG_INFO, + "[INFO: BRINGUP] - Auto LEDs enabled for system status " + "indication\n"); + +#elif defined(CONFIG_NUCLEO_H753ZI_LEDS_DISABLED) + + syslog(LOG_INFO, + "[INFO: BRINGUP] - LEDs disabled by configuration\n"); + +#endif + + return ret; +} + +/**************************************************************************** + * Name: nucleo_filesystem_initialize + * + * Description: + * Initialize filesystem support (PROCFS, ROMFS) + * Priority: HIGH (required for logging and configuration) + * + * Dependencies: None + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int nucleo_filesystem_initialize(void) +{ + int ret = OK; + +#ifdef CONFIG_FS_PROCFS + + int local_ret = nx_mount(NULL, STM32_PROCFS_MOUNTPOINT, "procfs", 0, NULL); + if (local_ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to mount PROCFS: %d\n", local_ret); + if (ret == OK) + { + ret = local_ret; + } + } + else + { + syslog(LOG_INFO, + "PROCFS mounted at %s\n", STM32_PROCFS_MOUNTPOINT); + } + +#endif /* CONFIG_FS_PROCFS */ + +#ifdef CONFIG_STM32_ROMFS + + int local_ret = stm32_romfs_initialize(); + if (local_ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to mount ROMFS at %s: %d\n", + CONFIG_STM32_ROMFS_MOUNTPOINT, local_ret); + + if (ret == OK) + { + ret = local_ret; + } + } + else + { + syslog(LOG_INFO, + "ROMFS mounted at %s\n", CONFIG_STM32_ROMFS_MOUNTPOINT); + } +#endif + + return ret; +} + +/**************************************************************************** + * Name: nucleo_rtc_initialize + * + * Description: + * Initialize Real-Time Clock driver + * Priority: HIGH (time services for other subsystems) + * + * Dependencies: None + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int nucleo_rtc_initialize(void) +{ + int ret = OK; + +#ifdef HAVE_RTC_DRIVER + + struct rtc_lowerhalf_s *lower; + + lower = stm32_rtc_lowerhalf(); + if (!lower) + { + syslog(LOG_ERR, + "ERROR: Failed to instantiate RTC lower-half driver\n"); + return -ENOMEM; + } + + ret = rtc_initialize(0, lower); + if (ret < 0) + { + syslog(LOG_ERR, + "ERROR: Failed to bind/register RTC driver: %d\n", ret); + } + else + { + syslog(LOG_INFO, + "RTC driver registered as /dev/rtc0\n"); + } +#endif + + return ret; +} + +/**************************************************************************** + * Name: nucleo_gpio_initialize + * + * Description: + * Initialize GPIO driver for user applications + * Priority: HIGH (required by many other drivers) + * + * Dependencies: None + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int nucleo_gpio_initialize(void) +{ + int ret = OK; + +#ifdef CONFIG_DEV_GPIO + + ret = stm32_gpio_initialize(); + if (ret < 0) + { + syslog(LOG_ERR, + "ERROR: Failed to initialize GPIO driver: %d\n", ret); + } + else + { + syslog(LOG_INFO, + "GPIO driver initialized\n"); + } +#endif + + return ret; +} + +/**************************************************************************** + * Name: nucleo_automotive_initialize + * + * Description: + * Initialize automotive/industrial communication protocols (CAN, LIN, etc.) + * Priority: MEDIUM + * + * Dependencies: GPIO, Clock configuration + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int nucleo_automotive_initialize(void) +{ + int ret = OK; + +#ifdef CONFIG_STM32H7_FDCAN1 + + /* syslog(LOG_INFO, + * "[FDCAN1] Starting initialization...\n"); + */ + + /* Initialize FDCAN1 driver FIRST */ + + int local_ret = stm32_fdcansockinitialize(0); + if (local_ret < 0) + { + syslog(LOG_ERR, + "[FDCAN1] ERROR: Failed to initialize: %d\n", local_ret); + + if (ret == OK) + { + ret = local_ret; + } + } + else + { + syslog(LOG_INFO, + "[FDCAN1] Driver initialized as /dev/can0\n"); + + /* DEBUG + * + * NOW force GPIO configuration AFTER driver init + * syslog(LOG_INFO, + * "[FDCAN1] Forcing GPIO reconfiguration...\n"); + * + * syslog(LOG_INFO, + * "[FDCAN1] GPIO_CAN1_RX: 0x%08lx\n", + * (unsigned long)GPIO_CAN1_RX); + * + * syslog(LOG_INFO, + * "[FDCAN1] GPIO_CAN1_TX: 0x%08lx\n", + * (unsigned long)GPIO_CAN1_TX); + * + * + * Verify GPIO and RCC configuration + * syslog(LOG_INFO, + * + * uint32_t rcc_apb1henr = getreg32(STM32_RCC_APB1HENR); + * uint32_t rcc_d2ccip1r = getreg32(STM32_RCC_D2CCIP1R); + * + * uint32_t gpiob_otyper = getreg32(STM32_GPIOB_OTYPER); + * + * "[FDCAN1] POST-CONFIG:\n"); + * syslog(LOG_INFO, + * "[FDCAN1] RCC_APB1HENR: 0x%08lx (bit 8=%d)\n", + * (unsigned long)rcc_apb1henr, + * (int)((rcc_apb1henr >> 8) & 1)); + * syslog(LOG_INFO, "[FDCAN1] RCC_D2CCIP1R: 0x%08lx (clk_sel=%lu)\n", + * (unsigned long)rcc_d2ccip1r, + * (unsigned long)((rcc_d2ccip1r >> 28) & 0x3)); + * syslog(LOG_INFO, "[FDCAN1] GPIOB_MODER: 0x%08lx " + * "(PB8[17:16]=%lu, PB9[19:18]=%lu)\n", + * (unsigned long)gpiob_moder, + * (unsigned long)((gpiob_moder >> 16) & 0x3), + * (unsigned long)((gpiob_moder >> 18) & 0x3)); + * syslog(LOG_INFO, "[FDCAN1] GPIOB_AFRH: 0x%08lx " + * "(PB8[3:0]=%lu, PB9[7:4]=%lu)\n", + * (unsigned long)gpiob_afrh, + * (unsigned long)(gpiob_afrh & 0xf), + * (unsigned long)((gpiob_afrh >> 4) & 0xf)); + * syslog(LOG_INFO, "[FDCAN1] GPIOB_OTYPER: 0x%08lx " + * "(PB8[8]=%d, PB9[9]=%d)\n", + * (unsigned long)gpiob_otyper, + * (int)((gpiob_otyper >> 8) & 1), + * (int)((gpiob_otyper >> 9) & 1)); + * + * + * Expected values: + * MODER: PB8=10b (AF), PB9=10b (AF) + * AFRH: PB8=9 (AF9), PB9=9 (AF9) + * OTYPER: PB8=0 (push-pull), PB9=0 (push-pull) + */ + + stm32_configgpio(GPIO_CAN1_RX); /* PB8 */ + stm32_configgpio(GPIO_CAN1_TX); /* PB9 */ + + uint32_t gpiob_moder = getreg32(STM32_GPIOB_MODER); + uint32_t gpiob_afrh = getreg32(STM32_GPIOB_AFRH); + + if (((gpiob_moder >> 16) & 0x3) != 0x2 || + ((gpiob_moder >> 18) & 0x3) != 0x2) + { + syslog(LOG_ERR, + "[FDCAN1] ERROR: GPIO not in AF mode!\n"); + } + + if ((gpiob_afrh & 0xf) != 9 || ((gpiob_afrh >> 4) & 0xf) != 9) + { + syslog(LOG_ERR, + "[FDCAN1] ERROR: GPIO not set to AF9!\n"); + } + } +#endif + +#ifdef CONFIG_STM32H7_FDCAN2 + + /* Initialize FDCAN2 and register as /dev/can1 */ + + int local_ret = stm32_fdcansockinitialize(1); + if (local_ret < 0) + { + syslog(LOG_ERR, "[FDCAN2] ERROR: Failed to initialize: %d\n", + local_ret); + if (ret == OK) + { + ret = local_ret; + } + } + else + { + syslog(LOG_INFO, + "[FDCAN2] Initialized as /dev/can1\n"); + } +#endif + + /* Future: LIN, FlexRay initialization here */ + + return ret; +} + +/**************************************************************************** + * Name: nucleo_communication_initialize + * + * Description: + * Initialize general-purpose communication bus drivers (SPI, I2C) + * Priority: HIGH (required by sensors and other peripherals) + * + * Dependencies: GPIO + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int nucleo_communication_initialize(void) +{ + int ret = OK; + int local_ret; + + UNUSED(local_ret); + +#ifdef CONFIG_STM32H7_SPI + local_ret = stm32_spi_initialize(); + if (local_ret < 0) + { + syslog(LOG_ERR, "ERROR: stm32_spi_initialize failed: %d\n", + local_ret); + if (ret == OK) + { + ret = local_ret; + } + } + else + { + syslog(LOG_INFO, "SPI buses initialized\n"); + } +#endif + +#ifdef CONFIG_SPI_DRIVER + local_ret = stm32_spidev_register_all(); + if (local_ret < 0) + { + syslog(LOG_ERR, "ERROR: stm32_spidev_register_all failed: %d\n", + local_ret); + } + else + { + syslog(LOG_INFO, "SPI character drivers registered\n"); + } +#endif + +#ifdef CONFIG_STM32H7_I2C + local_ret = stm32_i2c_initialize(); + if (local_ret < 0) + { + syslog(LOG_ERR, "ERROR: I2C bus initialization failed: %d\n", + local_ret); + if (ret == OK) + { + ret = local_ret; + } + } + else + { + syslog(LOG_INFO, "I2C buses initialized\n"); +#if defined(CONFIG_I2C) && defined(CONFIG_SYSTEM_I2CTOOL) + local_ret = nucleo_i2c_tools_initialize(); + if (local_ret < 0) + { + syslog(LOG_ERR, "ERROR: I2C tools registration failed: %d\n", + local_ret); + } +#endif + } +#endif + + return ret; +} + +/**************************************************************************** + * Name: nucleo_input_initialize + * + * Description: + * Initialize input devices (buttons, etc.) + * Priority: MEDIUM + * + * Dependencies: GPIO + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int nucleo_input_initialize(void) +{ + int ret = OK; + +#ifdef CONFIG_INPUT_BUTTONS + + ret = btn_lower_initialize("/dev/buttons"); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: btn_lower_initialize() failed: %d\n", ret); + } + else + { + syslog(LOG_INFO, + "Buttons driver registered as /dev/buttons\n"); + } +#endif + + return ret; +} + +/**************************************************************************** + * Name: nucleo_usb_initialize + * + * Description: + * Initialize USB subsystem (host, device, monitoring) + * Priority: MEDIUM + * + * Dependencies: None + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int nucleo_usb_initialize(void) +{ + int ret = OK; + +#ifdef HAVE_USBHOST + + int local_ret = stm32_usbhost_initialize(); + if (local_ret != OK) + { + syslog(LOG_ERR, + "ERROR: Failed to initialize USB host: %d\n", local_ret); + if (ret == OK) + { + ret = local_ret; + } + } + else + { + syslog(LOG_INFO, + "USB host initialized\n"); + } +#endif + +#ifdef HAVE_USBMONITOR + + int local_ret = usbmonitor_start(); + if (local_ret != OK) + { + syslog(LOG_ERR, "ERROR: Failed to start USB monitor: %d\n", + local_ret); + if (ret == OK) + { + ret = local_ret; + } + } + else + { + syslog(LOG_INFO, + "USB monitor started\n"); + } +#endif + +#if defined(CONFIG_CDCACM) && !defined(CONFIG_CDCACM_CONSOLE) && \ + !defined(CONFIG_CDCACM_COMPOSITE) + + syslog(LOG_INFO, "Initializing CDC/ACM device\n"); + + int local_ret = cdcacm_initialize(0, NULL); + if (local_ret < 0) + { + syslog(LOG_ERR, "ERROR: cdcacm_initialize failed: %d\n", local_ret); + if (ret == OK) + { + ret = local_ret; + } + } + else + { + syslog(LOG_INFO, + "CDC/ACM device initialized\n"); + } +#endif + +#if defined(CONFIG_RNDIS) && !defined(CONFIG_RNDIS_COMPOSITE) + + uint8_t mac[6]; + mac[0] = 0xa0; + mac[1] = (CONFIG_NETINIT_MACADDR_2 >> (8 * 0)) & 0xff; + mac[2] = (CONFIG_NETINIT_MACADDR_1 >> (8 * 3)) & 0xff; + mac[3] = (CONFIG_NETINIT_MACADDR_1 >> (8 * 2)) & 0xff; + mac[4] = (CONFIG_NETINIT_MACADDR_1 >> (8 * 1)) & 0xff; + mac[5] = (CONFIG_NETINIT_MACADDR_1 >> (8 * 0)) & 0xff; + + int local_ret = usbdev_rndis_initialize(mac); + if (local_ret < 0) + { + syslog(LOG_ERR, "ERROR: RNDIS initialization failed: %d\n", + local_ret); + if (ret == OK) + { + ret = local_ret; + } + } + else + { + syslog(LOG_INFO, + "RNDIS USB device initialized\n"); + } +#endif + + return ret; +} + +/**************************************************************************** + * Name: nucleo_adc_initialize + * + * Description: + * Initialize Analog-to-Digital Converter + * Priority: MEDIUM + * + * Dependencies: GPIO + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int nucleo_adc_initialize(void) +{ + int ret = OK; + +#ifdef CONFIG_ADC + + ret = stm32_adc_setup(); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: stm32_adc_setup failed: %d\n", ret); + } + else + { + syslog(LOG_INFO, + "ADC driver initialized\n"); + } +#endif + + return ret; +} + +/**************************************************************************** + * Name: nucleo_sensors_initialize + * + * Description: + * Initialize sensor drivers (IMU, magnetometer, RFID, etc.) + * Priority: LOW (application-specific) + * + * Dependencies: I2C, SPI, GPIO + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int nucleo_sensors_initialize(void) +{ + int ret = OK; + +#ifdef CONFIG_SENSORS_LSM6DSL + + int local_ret = stm32_lsm6dsl_initialize("/dev/lsm6dsl0"); + if (local_ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to initialize LSM6DSL driver: %d\n", + local_ret); + if (ret == OK) + { + ret = local_ret; + } + } + else + { + syslog(LOG_INFO, + "LSM6DSL sensor initialized as /dev/lsm6dsl0\n"); + } +#endif + +#ifdef CONFIG_SENSORS_LSM9DS1 + + int local_ret = stm32_lsm9ds1_initialize(); + if (local_ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to initialize LSM9DS1 driver: %d\n", + local_ret); + if (ret == OK) + { + ret = local_ret; + } + } + else + { + syslog(LOG_INFO, + "LSM9DS1 sensor initialized\n"); + } +#endif + +#ifdef CONFIG_SENSORS_LSM303AGR + + int local_ret = stm32_lsm303agr_initialize("/dev/lsm303mag0"); + if (local_ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to initialize LSM303AGR driver: %d\n", + local_ret); + if (ret == OK) + { + ret = local_ret; + } + } + else + { + syslog(LOG_INFO, + "LSM303AGR magnetometer initialized as /dev/lsm303mag0\n"); + } +#endif + +#ifdef CONFIG_NUCLEO_H753ZI_MFRC522_ENABLE + + int local_ret = stm32_mfrc522initialize(MFRC522_DEVPATH); + if (local_ret < 0) + { + syslog(LOG_ERR, "ERROR: stm32_mfrc522initialize() failed: %d\n", + local_ret); + + if (ret == OK) + { + ret = local_ret; + } + } + else + { + syslog(LOG_INFO, + "MFRC522 RFID reader initialized successfully at %s\n", + MFRC522_DEVPATH); + } +#endif + + return ret; +} + +/**************************************************************************** + * Name: nucleo_display_initialize + * + * Description: + * Initialize display drivers (LCD, OLED, TFT, etc.) + * Priority: MEDIUM + * + * Dependencies: SPI, I2C, GPIO + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int nucleo_display_initialize(void) +{ + int ret = OK; + +#if defined(CONFIG_LCD_SSD1306) && \ + defined(CONFIG_NUCLEO_H753ZI_SSD1306_ENABLE) + + ret = board_lcd_initialize(); + if (ret == OK) + { + struct lcd_dev_s *lcd = board_lcd_getdev(NUCLEO_SSD1306_DEVNO); + if (lcd != NULL) + { +#ifdef CONFIG_LCD_DEV + + ret = lcddev_register(NUCLEO_SSD1306_DEVNO); + if (ret < 0) + { + syslog(LOG_ERR, + "ERROR: lcddev_register(%d) failed: %d\n", + NUCLEO_SSD1306_DEVNO, ret); + } + else + { + syslog(LOG_INFO, + "SSD1306 OLED registered at /dev/lcd%d\n", + NUCLEO_SSD1306_DEVNO); + } +#endif + } + } +#endif + +#if defined(CONFIG_LCD_ST7796) && \ + defined(CONFIG_NUCLEO_H753ZI_ST7796_ENABLE) + + /* syslog(LOG_INFO, "Initializing ST7796 TFT display...\n"); */ + + int local_ret = stm32_st7796initialize(0); + if (local_ret < 0) + { + syslog(LOG_ERR, "ERROR: stm32_st7796initialize() failed: %d\n", + local_ret); + if (ret == OK) + { + ret = local_ret; + } + } + else + { + /* syslog(LOG_INFO, + * "ST7796 TFT display initialized successfully at %s\n", + * ST7796_FB_PATH); + */ + + /* CRITICAL: Flush splashscreen from RAM to SPI display */ + + local_ret = stm32_st7796_flush_fb(); + if (local_ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to flush splashscreen: %d\n", + local_ret); + } + else + { + /* syslog(LOG_INFO, " + * ST7796: Splashscreen flushed to display\n"); + */ + } + + /* Enable backlight after flush */ + + stm32_st7796_backlight(true); + + /* syslog(LOG_INFO, + * "ST7796 backlight enabled\n"); + */ + } +#endif + + return ret; +} + +/**************************************************************************** + * Name: nucleo_connectivity_initialize + * + * Description: + * Initialize wireless connectivity modules (Wi-Fi, Bluetooth, etc.) + * Priority: LOW (application-specific) + * + * Dependencies: SPI, I2C, GPIO + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int nucleo_connectivity_initialize(void) +{ + int ret = OK; + +#ifdef CONFIG_PCA9635PW + + ret = stm32_pca9635_initialize(); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: stm32_pca9635_initialize failed: %d\n", ret); + } + else + { + syslog(LOG_INFO, "PCA9635 LED controller initialized\n"); + } +#endif + +#ifdef CONFIG_WL_NRF24L01 + + ret = stm32_wlinitialize(); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to initialize wireless driver: %d\n", + ret); + } + else + { + syslog(LOG_INFO, "NRF24L01 wireless driver initialized\n"); + } +#endif + + return ret; +} + +/**************************************************************************** + * Name: nucleo_storage_initialize + * + * Description: + * Initialize storage devices (SD card, flash, etc.) + * Priority: MEDIUM + * + * Dependencies: SPI (for SD cards), filesystem + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int nucleo_storage_initialize(void) +{ + int ret = OK; + +#ifdef CONFIG_MMCSD_SPI + + ret = stm32_mmcsd_initialize(CONFIG_NSH_MMCSDMINOR); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to initialize SD slot %d: %d\n", + CONFIG_NSH_MMCSDMINOR, ret); + } + else + { + syslog(LOG_INFO, "MMC/SD SPI driver initialized (slot %d)\n", + CONFIG_NSH_MMCSDMINOR); + } +#endif + +#ifdef CONFIG_MTD +#ifdef HAVE_PROGMEM_CHARDEV + + ret = stm32_progmem_init(); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to initialize MTD progmem: %d\n", ret); + } + else + { + syslog(LOG_INFO, "MTD program memory initialized\n"); + } +#endif +#endif + + return ret; +} + +/**************************************************************************** + * Name: nucleo_timers_initialize + * + * Description: + * Initialize timer-related drivers (PWM, capture, etc.) + * Priority: LOW + * + * Dependencies: GPIO + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int nucleo_timers_initialize(void) +{ + int ret = OK; + +#ifdef CONFIG_PWM + + int local_ret = stm32_pwm_setup(); + if (local_ret < 0) + { + syslog(LOG_ERR, "ERROR: stm32_pwm_setup() failed: %d\n", local_ret); + if (ret == OK) + { + ret = local_ret; + } + } + else + { + syslog(LOG_INFO, "PWM drivers initialized\n"); + } +#endif + +#ifdef CONFIG_CAPTURE + + int local_ret = nucleo_capture_initialize(); + if (local_ret < 0) + { + syslog(LOG_ERR, + "ERROR: nucleo_capture_initialize() failed: %d\n", + local_ret); + if (ret == OK) + { + ret = local_ret; + } + } + else + { + syslog(LOG_INFO, "Timer capture drivers initialized\n"); + } +#endif + + return ret; +} + +/**************************************************************************** + * Name: nucleo_watchdog_initialize + * + * Description: + * Initialize watchdog timer + * Priority: LOW (should be last - for system monitoring) + * + * Dependencies: None (intentionally independent) + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int nucleo_watchdog_initialize(void) +{ + int ret = OK; + +#ifdef CONFIG_STM32H7_IWDG + + ret = stm32_iwdginitialize("/dev/watchdog0", STM32_LSI_FREQUENCY); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to initialize watchdog: %d\n", ret); + } + else + { + syslog(LOG_INFO, "Watchdog initialized as /dev/watchdog0\n"); + } +#endif + + return ret; +} + +/**************************************************************************** + * Name: nucleo_i2c_tools_initialize + * + * Description: + * Initialize I2C tools for debugging and development. This registers the + * I2C buses as character drivers (e.g., /dev/i2c1) to allow tools like + * i2c-tools to interact with the bus from user space. + * + * Priority: LOW (development/debugging only) + * + * Dependencies: I2C hardware must be initialized first. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +#if defined(CONFIG_I2C) && defined(CONFIG_SYSTEM_I2CTOOL) +static int stm32_i2c_register(int bus) +{ + struct i2c_master_s *i2c; + int ret; + + /* Get the I2C bus instance */ + + i2c = stm32_i2cbus_initialize(bus); + if (i2c == NULL) + { + syslog(LOG_ERR, "ERROR: Failed to get I2C%d interface\n", bus); + return -ENODEV; + } + + /* Register the bus as a character driver (/dev/i2cN) */ + + ret = i2c_register(i2c, bus); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to register I2C%d driver: %d\n", + bus, ret); + + /* Only uninitialize if registration fails and no other + * peripheral is using this bus instance. + */ + + stm32_i2cbus_uninitialize(i2c); + return ret; + } + + syslog(LOG_INFO, "I2C%d registered for tools at /dev/i2c%d\n", bus, bus); + return OK; +} + +static int nucleo_i2c_tools_initialize(void) +{ + int ret = OK; + int local_ret; + +#ifdef CONFIG_STM32H7_I2C1 + local_ret = stm32_i2c_register(1); + if (local_ret < 0) + { + ret = local_ret; + } +#endif + +#ifdef CONFIG_STM32H7_I2C2 + local_ret = stm32_i2c_register(2); + if (local_ret < 0 && ret == OK) + { + ret = local_ret; + } +#endif + +#ifdef CONFIG_STM32H7_I2C3 + local_ret = stm32_i2c_register(3); + if (local_ret < 0 && ret == OK) + { + ret = local_ret; + } +#endif + +#ifdef CONFIG_STM32H7_I2C4 + local_ret = stm32_i2c_register(4); + if (local_ret < 0 && ret == OK) + { + ret = local_ret; + } +#endif + + return ret; +} +#endif + +/**************************************************************************** + * Name: nucleo_capture_initialize + * + * Description: + * Initialize and register capture drivers + * Priority: LOW + * + * Dependencies: Timer peripherals + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +#ifdef CONFIG_CAPTURE +static int nucleo_capture_initialize(void) +{ + int ret; + + struct cap_lowerhalf_s *lower[] = + { +#if defined(CONFIG_STM32H7_TIM1_CAP) + stm32_cap_initialize(1), +#endif +#if defined(CONFIG_STM32H7_TIM2_CAP) + stm32_cap_initialize(2), +#endif +#if defined(CONFIG_STM32H7_TIM3_CAP) + stm32_cap_initialize(3), +#endif +#if defined(CONFIG_STM32H7_TIM4_CAP) + stm32_cap_initialize(4), +#endif +#if defined(CONFIG_STM32H7_TIM5_CAP) + stm32_cap_initialize(5), +#endif +#if defined(CONFIG_STM32H7_TIM8_CAP) + stm32_cap_initialize(8), +#endif +#if defined(CONFIG_STM32H7_TIM12_CAP) + stm32_cap_initialize(12), +#endif +#if defined(CONFIG_STM32H7_TIM13_CAP) + stm32_cap_initialize(13), +#endif +#if defined(CONFIG_STM32H7_TIM14_CAP) + stm32_cap_initialize(14), +#endif +#if defined(CONFIG_STM32H7_TIM15_CAP) + stm32_cap_initialize(15), +#endif +#if defined(CONFIG_STM32H7_TIM16_CAP) + stm32_cap_initialize(16), +#endif +#if defined(CONFIG_STM32H7_TIM17_CAP) + stm32_cap_initialize(17), +#endif + }; + + size_t count = sizeof(lower) / sizeof(lower[0]); + + if (count == 0) + { + return OK; + } + + ret = cap_register_multiple("/dev/cap", lower, count); + if (ret == EINVAL) + { + syslog(LOG_ERR, "ERROR: cap_register_multiple path is invalid\n"); + } + else if (ret == EEXIST) + { + syslog(LOG_ERR, + "ERROR: cap_register_multiple inode already exists\n"); + } + else if (ret == ENOMEM) + { + syslog(LOG_ERR, + "ERROR: cap_register_multiple not enough memory\n"); + } + else if (ret < 0) + { + syslog(LOG_ERR, "ERROR: cap_register_multiple failed: %d\n", ret); + } + + return ret; +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_bringup + * + * Description: + * Perform architecture-specific initialization with dependency-aware + * ordering + * + * This function initializes all board-specific drivers and subsystems + * in a controlled manner, ensuring that dependencies between subsystems + * are respected and failures in one subsystem do not prevent + * initialization of others. + * + * INITIALIZATION PHASES WITH DEPENDENCY MANAGEMENT: + * + * Phase 1 - Basic System & Visual Feedback + * Phase 2 - Hardware Interfaces & Communication Protocols + * Phase 3 - User Interface & USB Services + * Phase 4 - Analog Measurement (ADC) + * Phase 5 - Display Drivers (LCD, OLED, TFT) + * Phase 6 - Sensors & Wireless Connectivity + * Phase 7 - Storage Devices (SD Card, Flash) + * Phase 8 - Timers, PWM & Signal Processing + * Phase 9 - System Monitoring (Watchdog) + * + * ERROR HANDLING STRATEGY: + * Individual subsystem failures are logged via syslog. + * The function continues to initialize other subsystems even if one fails. + * A single return value (ret) tracks the status of the first failure. + * + * Input Parameters: + * None + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +int stm32_bringup(void) +{ + int ret = OK; + int subsys_ret; + + /* syslog(LOG_INFO, + * "\n[INFO: BRINGUP] Nucleo-H753ZI initialization...\n"); + */ + + /* PHASE 1: BASIC SYSTEM & VISUAL FEEDBACK */ + + /* syslog(LOG_INFO, + * "[INFO: BRINGUP] Phase 1: Initializing basic system & " + * "visual feedback\n"); + */ + + subsys_ret = nucleo_led_initialize(); + if (subsys_ret != OK && ret == OK) + { + ret = subsys_ret; + } + + subsys_ret = nucleo_filesystem_initialize(); + if (subsys_ret != OK && ret == OK) + { + ret = subsys_ret; + } + + subsys_ret = nucleo_rtc_initialize(); + if (subsys_ret != OK && ret == OK) + { + ret = subsys_ret; + } + + /* PHASE 2: HARDWARE INTERFACES & COMMUNICATION PROTOCOLS */ + + /* syslog(LOG_INFO, + * "[INFO: BRINGUP] Phase 2: Initializing hardware interfaces & " + * "communication protocols\n"); + */ + + subsys_ret = nucleo_gpio_initialize(); + if (subsys_ret != OK && ret == OK) + { + ret = subsys_ret; + } + + subsys_ret = nucleo_communication_initialize(); + if (subsys_ret != OK && ret == OK) + { + ret = subsys_ret; + } + + subsys_ret = nucleo_automotive_initialize(); + if (subsys_ret != OK && ret == OK) + { + ret = subsys_ret; + } + + /* PHASE 3: USER INTERFACE & USB SERVICES */ + + /* syslog(LOG_INFO, + * "[INFO: BRINGUP] Phase 3: Initializing user interface & " + * "USB services\n"); + */ + + subsys_ret = nucleo_input_initialize(); + if (subsys_ret != OK && ret == OK) + { + ret = subsys_ret; + } + + subsys_ret = nucleo_usb_initialize(); + if (subsys_ret != OK && ret == OK) + { + ret = subsys_ret; + } + + /* PHASE 4: ANALOG MEASUREMENT (ADC) */ + + /* syslog(LOG_INFO, + * "[INFO: BRINGUP] Phase 4: Initializing analog measurement " + * "(ADC)\n"); + */ + + subsys_ret = nucleo_adc_initialize(); + if (subsys_ret != OK && ret == OK) + { + ret = subsys_ret; + } + + /* PHASE 5: DISPLAY DRIVERS (LCD, OLED, TFT) */ + + /* syslog(LOG_INFO, + * "[INFO: BRINGUP] Phase 5: Initializing display drivers\n"); + */ + + subsys_ret = nucleo_display_initialize(); + if (subsys_ret != OK && ret == OK) + { + ret = subsys_ret; + } + + /* PHASE 6: SENSORS & WIRELESS CONNECTIVITY */ + + /* syslog(LOG_INFO, + * "[INFO: BRINGUP] Phase 6: Initializing sensors & " + * "wireless connectivity\n"); + */ + + subsys_ret = nucleo_sensors_initialize(); + if (subsys_ret != OK && ret == OK) + { + ret = subsys_ret; + } + + subsys_ret = nucleo_connectivity_initialize(); + if (subsys_ret != OK && ret == OK) + { + ret = subsys_ret; + } + + /* PHASE 7: STORAGE DEVICES (SD CARD, FLASH) */ + + /* syslog(LOG_INFO, + * "[INFO: BRINGUP] Phase 7: Initializing storage devices " + * "(SD card, flash)\n"); + */ + + subsys_ret = nucleo_storage_initialize(); + if (subsys_ret != OK && ret == OK) + { + ret = subsys_ret; + } + + /* PHASE 8: TIMERS, PWM & SIGNAL PROCESSING */ + + /* syslog(LOG_INFO, + * "[INFO: BRINGUP] Phase 8: Initializing timers, PWM & " + * "signal processing\n"); + */ + + subsys_ret = nucleo_timers_initialize(); + if (subsys_ret != OK && ret == OK) + { + ret = subsys_ret; + } + + /* PHASE 9: SYSTEM MONITORING (WATCHDOG) */ + + /* syslog(LOG_INFO, + * "[INFO: BRINGUP] Phase 9: Initializing system monitoring " + * "(watchdog)\n"); + */ + + subsys_ret = nucleo_watchdog_initialize(); + if (subsys_ret != OK && ret == OK) + { + ret = subsys_ret; + } + + /* INITIALIZATION COMPLETE */ + + if (ret == OK) + { + syslog(LOG_INFO, + "[INFO: BRINGUP] Nucleo-H753ZI board initialization " + "completed successfully\n"); + } + else + { + syslog(LOG_WARNING, + "[WARNING: BRINGUP] Nucleo-H753ZI board initialization " + "completed with errors: %d\n", + ret); + syslog(LOG_INFO, + "[INFO: BRINGUP] System is functional, but some drivers " + "may be unavailable\n"); + } + + return ret; +} diff --git a/boards/arm/stm32h7/nucleo-h753zi/src/stm32_buttons.c b/boards/arm/stm32h7/nucleo-h753zi/src/stm32_buttons.c new file mode 100644 index 0000000000000..a59823ce59d59 --- /dev/null +++ b/boards/arm/stm32h7/nucleo-h753zi/src/stm32_buttons.c @@ -0,0 +1,806 @@ +/**************************************************************************** + * boards/arm/stm32h7/nucleo-h753zi/src/stm32_buttons.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "stm32_gpio.h" +#include "nucleo-h753zi.h" + +#ifdef CONFIG_NUCLEO_H753ZI_BUTTON_SUPPORT + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#if defined(CONFIG_INPUT_BUTTONS) && !defined(CONFIG_ARCH_IRQBUTTONS) +# error "The NuttX Buttons Driver depends on IRQ support to work!" +#endif + +#define MAX_PIN_CONFIG_LEN 512 + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* Dynamic button configuration array */ + +static uint32_t g_buttons[CONFIG_NUCLEO_H753ZI_BUTTON_COUNT]; +static int g_button_count = 0; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: get_exti_line + * + * Description: + * Extract EXTI line number from GPIO configuration. + * + * Input Parameters: + * gpio_config - STM32 GPIO configuration + * + * Returned Value: + * EXTI line number (0-15), or -1 on error + * + ****************************************************************************/ + +static int get_exti_line(uint32_t gpio_config) +{ + /* Extract pin number from GPIO_PIN mask */ + + uint32_t pin_mask = gpio_config & GPIO_PIN_MASK; + + switch (pin_mask) + { + case GPIO_PIN0: + return 0; + + case GPIO_PIN1: + return 1; + + case GPIO_PIN2: + return 2; + + case GPIO_PIN3: + return 3; + + case GPIO_PIN4: + return 4; + + case GPIO_PIN5: + return 5; + + case GPIO_PIN6: + return 6; + + case GPIO_PIN7: + return 7; + + case GPIO_PIN8: + return 8; + + case GPIO_PIN9: + return 9; + + case GPIO_PIN10: + return 10; + + case GPIO_PIN11: + return 11; + + case GPIO_PIN12: + return 12; + + case GPIO_PIN13: + return 13; + + case GPIO_PIN14: + return 14; + + case GPIO_PIN15: + return 15; + + default: + return -1; + } +} + +/**************************************************************************** + * Name: get_gpio_port_letter + * + * Description: + * Get port letter from GPIO configuration. + * + * Input Parameters: + * gpio_config - STM32 GPIO configuration + * + * Returned Value: + * Port letter ('A'-'H'), or '?' on error + * + ****************************************************************************/ + +static char get_gpio_port_letter(uint32_t gpio_config) +{ + uint32_t port = gpio_config & GPIO_PORT_MASK; + + switch (port) + { + case GPIO_PORTA: + return 'A'; + + case GPIO_PORTB: + return 'B'; + + case GPIO_PORTC: + return 'C'; + + case GPIO_PORTD: + return 'D'; + + case GPIO_PORTE: + return 'E'; + + case GPIO_PORTF: + return 'F'; + + case GPIO_PORTG: + return 'G'; + + case GPIO_PORTH: + return 'H'; + + default: + return '?'; + } +} + +/**************************************************************************** + * Name: parse_gpio_pin + * + * Description: + * Parse GPIO pin string like "PF15" into STM32 GPIO configuration. + * + * Input Parameters: + * pin_str - GPIO pin string (e.g., "PA0", "PF15", "PC13") + * error - Pointer to error code storage + * + * Returned Value: + * STM32 GPIO configuration value on success, 0 on error + * + ****************************************************************************/ + +static uint32_t parse_gpio_pin(FAR const char *pin_str, FAR int *error) +{ + size_t len; + char port; + FAR const char *pin_num_str; + FAR char *endptr; + long pin_num; + uint32_t port_base; + uint32_t gpio_pin; + + *error = 0; + + if (pin_str == NULL) + { + *error = -EINVAL; + return 0; + } + + /* Remove leading/trailing spaces */ + + while (*pin_str == ' ' || *pin_str == '\t') + { + pin_str++; + } + + len = strlen(pin_str); + if (len < 3 || len > 4) + { + *error = -EINVAL; + return 0; + } + + if (pin_str[0] != 'P') + { + *error = -EINVAL; + return 0; + } + + port = pin_str[1]; + if (port < 'A' || port > 'H') + { + *error = -EINVAL; + return 0; + } + + pin_num_str = &pin_str[2]; + pin_num = strtol(pin_num_str, &endptr, 10); + if (*endptr != '\0' || pin_num < 0 || pin_num > 15) + { + *error = -EINVAL; + return 0; + } + + /* Map port letter to STM32 port base */ + + switch (port) + { + case 'A': + port_base = GPIO_PORTA; + break; + + case 'B': + port_base = GPIO_PORTB; + break; + + case 'C': + port_base = GPIO_PORTC; + break; + + case 'D': + port_base = GPIO_PORTD; + break; + + case 'E': + port_base = GPIO_PORTE; + break; + + case 'F': + port_base = GPIO_PORTF; + break; + + case 'G': + port_base = GPIO_PORTG; + break; + + case 'H': + port_base = GPIO_PORTH; + break; + + default: + *error = -EINVAL; + return 0; + } + + /* Use correct STM32 GPIO pin macros */ + + switch (pin_num) + { + case 0: + gpio_pin = GPIO_PIN0; + break; + + case 1: + gpio_pin = GPIO_PIN1; + break; + + case 2: + gpio_pin = GPIO_PIN2; + break; + + case 3: + gpio_pin = GPIO_PIN3; + break; + + case 4: + gpio_pin = GPIO_PIN4; + break; + + case 5: + gpio_pin = GPIO_PIN5; + break; + + case 6: + gpio_pin = GPIO_PIN6; + break; + + case 7: + gpio_pin = GPIO_PIN7; + break; + + case 8: + gpio_pin = GPIO_PIN8; + break; + + case 9: + gpio_pin = GPIO_PIN9; + break; + + case 10: + gpio_pin = GPIO_PIN10; + break; + + case 11: + gpio_pin = GPIO_PIN11; + break; + + case 12: + gpio_pin = GPIO_PIN12; + break; + + case 13: + gpio_pin = GPIO_PIN13; + break; + + case 14: + gpio_pin = GPIO_PIN14; + break; + + case 15: + gpio_pin = GPIO_PIN15; + break; + + default: + *error = -EINVAL; + return 0; + } + + /* CRITICAL FIX: Use GPIO_PULLDOWN instead of GPIO_FLOAT + * + * The Nucleo-H753ZI board has external pull-down resistors on button + * pins. Using GPIO_FLOAT causes instability due to high impedance state + * combined with variable leakage current. GPIO_PULLDOWN ensures stable + * LOW state when button is not pressed, working in conjunction with the + * external pull-down for robust operation. + */ + + return (GPIO_INPUT | GPIO_PULLDOWN | GPIO_EXTI | port_base | gpio_pin); +} + +/**************************************************************************** + * Name: print_exti_conflict_error + * + * Description: + * Print detailed EXTI conflict error message. + * + * Input Parameters: + * conflicting_button - Index of button that conflicts + * current_button - Index of button being added + * pin_str - Pin string being added + * gpio_config - GPIO config of new pin + * exti_line - EXTI line that conflicts + * + ****************************************************************************/ + +static void print_exti_conflict_error(int conflicting_button, + int current_button, + FAR const char *pin_str, + uint32_t gpio_config, + int exti_line) +{ + char port1 = get_gpio_port_letter(g_buttons[conflicting_button]); + char port2 = get_gpio_port_letter(gpio_config); + int pin1 = get_exti_line(g_buttons[conflicting_button]); + int pin2 = get_exti_line(gpio_config); + int alt; + int i; + bool used; + + syslog(LOG_ERR, "\n"); + syslog(LOG_ERR, + "======================================================\n"); + syslog(LOG_ERR, " CRITICAL ERROR: EXTI LINE CONFLICT DETECTED!\n"); + syslog(LOG_ERR, + "======================================================\n"); + syslog(LOG_ERR, "\n"); + syslog(LOG_ERR, + "Button %d (P%c%d) and Button %d (%s = P%c%d) both use EXTI%d\n", + conflicting_button, port1, pin1, + current_button, pin_str, port2, pin2, + exti_line); + syslog(LOG_ERR, "\n"); + syslog(LOG_ERR, "EXPLANATION:\n"); + syslog(LOG_ERR, + " STM32 EXTI lines are shared across GPIO ports.\n"); + syslog(LOG_ERR, + " Only ONE pin per number can be used as interrupt source.\n"); + syslog(LOG_ERR, + " Example: PA3, PB3, PC3, PD3... all share EXTI3.\n"); + syslog(LOG_ERR, "\n"); + syslog(LOG_ERR, "WHAT WILL HAPPEN IF YOU IGNORE THIS:\n"); + syslog(LOG_ERR, " - The LAST pin (P%c%d) will work\n", port2, pin2); + syslog(LOG_ERR, + " - The FIRST pin (P%c%d) will NOT trigger interrupts\n", + port1, pin1); + syslog(LOG_ERR, " - You will see 'ghost' button presses\n"); + syslog(LOG_ERR, "\n"); + syslog(LOG_ERR, "SOLUTION:\n"); + syslog(LOG_ERR, + " Change one of the conflicting pins to a different number.\n"); + syslog(LOG_ERR, "\n"); + syslog(LOG_ERR, " Example fixes:\n"); + + /* Suggest alternative pins */ + + for (alt = 0; alt < 16; alt++) + { + if (alt == exti_line) + { + continue; + } + + /* Check if this EXTI is already used */ + + used = false; + for (i = 0; i < current_button; i++) + { + if (get_exti_line(g_buttons[i]) == alt) + { + used = true; + break; + } + } + + if (!used) + { + syslog(LOG_ERR, + " - Change P%c%d to P%c%d (EXTI%d is free)\n", + port2, pin2, port2, alt, alt); + break; + } + } + + syslog(LOG_ERR, "\n"); + syslog(LOG_ERR, "Current button configuration:\n"); + for (i = 0; i < current_button; i++) + { + int line = get_exti_line(g_buttons[i]); + char prt = get_gpio_port_letter(g_buttons[i]); + syslog(LOG_ERR, " Button %d: P%c%d (EXTI%d)%s\n", + i, prt, line, line, + (i == conflicting_button) ? " <- CONFLICT" : ""); + } + + syslog(LOG_ERR, " Button %d: %s (P%c%d, EXTI%d) <- CONFLICT\n", + current_button, pin_str, port2, pin2, exti_line); + syslog(LOG_ERR, "\n"); +} + +/**************************************************************************** + * Name: init_button_configs + * + * Description: + * Initialize button configuration from Kconfig settings with validation. + * + * Returned Value: + * OK on success, negative errno on error + * + ****************************************************************************/ + +static int init_button_configs(void) +{ + int expected_pins; + FAR const char *pins_config; + char pins_str[MAX_PIN_CONFIG_LEN]; + FAR char *pin; + int error; + uint32_t gpio_config; + int i; + int exti_line; + size_t config_len; + + /* EXTI conflict detection */ + + int exti_usage[16]; + + g_button_count = 0; + + /* Initialize EXTI tracking */ + + for (i = 0; i < 16; i++) + { + exti_usage[i] = -1; /* -1 = unused */ + } + + /* Calculate how many external pins we expect */ + +#ifdef CONFIG_NUCLEO_H753ZI_BUTTON_BUILTIN + g_buttons[g_button_count] = GPIO_BTN_BUILT_IN; + + /* Register built-in button EXTI */ + + exti_line = get_exti_line(GPIO_BTN_BUILT_IN); + if (exti_line >= 0) + { + exti_usage[exti_line] = g_button_count; + } + + g_button_count++; + expected_pins = CONFIG_NUCLEO_H753ZI_BUTTON_COUNT - 1; +#else + expected_pins = CONFIG_NUCLEO_H753ZI_BUTTON_COUNT; +#endif + + /* If no external pins needed, we're done */ + + if (expected_pins == 0) + { + return OK; + } + + /* Validate pin string is not empty */ + + pins_config = CONFIG_NUCLEO_H753ZI_BUTTON_PINS; + if (pins_config == NULL || strlen(pins_config) == 0) + { + syslog(LOG_ERR, "ERROR: Button pins not configured!\n"); + syslog(LOG_ERR, + "Expected %d GPIO pins but BUTTON_PINS is empty\n", + expected_pins); + syslog(LOG_ERR, + "Configure in: Board Selection -> Button Configuration\n"); + return -EINVAL; + } + + /* Validate configuration length */ + + config_len = strlen(pins_config); + if (config_len >= MAX_PIN_CONFIG_LEN) + { + syslog(LOG_ERR, + "ERROR: Pin configuration too long (%zu bytes, max %d)\n", + config_len, MAX_PIN_CONFIG_LEN - 1); + return -EINVAL; + } + + /* Make a copy for parsing (strtok modifies the string) */ + + strncpy(pins_str, pins_config, sizeof(pins_str) - 1); + pins_str[sizeof(pins_str) - 1] = '\0'; + + /* Parse and validate each pin */ + + pin = strtok(pins_str, ", \t\n\r"); + while (pin != NULL && g_button_count < CONFIG_NUCLEO_H753ZI_BUTTON_COUNT) + { + /* Parse GPIO pin */ + + gpio_config = parse_gpio_pin(pin, &error); + if (error != 0) + { + syslog(LOG_ERR, "ERROR: Invalid GPIO pin: \"%s\"\n", pin); + syslog(LOG_ERR, + "Use format: PORT+PIN (e.g., \"PA0\", \"PF15\")\n"); + syslog(LOG_ERR, "Valid ports: PA-PH, Valid pins: 0-15\n"); + return -EINVAL; + } + + /* Check for duplicate pins */ + + for (i = 0; i < g_button_count; i++) + { + if (g_buttons[i] == gpio_config) + { + syslog(LOG_ERR, "ERROR: Duplicate GPIO pin: \"%s\"\n", pin); + syslog(LOG_ERR, + "This pin is already used by Button %d\n", i); + return -EINVAL; + } + } + + /* Check for EXTI line conflicts */ + + exti_line = get_exti_line(gpio_config); + if (exti_line < 0) + { + syslog(LOG_ERR, + "ERROR: Failed to determine EXTI line for \"%s\"\n", + pin); + return -EINVAL; + } + + if (exti_usage[exti_line] >= 0) + { + /* EXTI conflict detected */ + + print_exti_conflict_error(exti_usage[exti_line], g_button_count, + pin, gpio_config, exti_line); + return -EINVAL; + } + + /* Register this EXTI line as used */ + + exti_usage[exti_line] = g_button_count; + + /* Add button */ + + g_buttons[g_button_count] = gpio_config; + g_button_count++; + + pin = strtok(NULL, ", \t\n\r"); + } + + /* Validate final count */ + + if (g_button_count != CONFIG_NUCLEO_H753ZI_BUTTON_COUNT) + { + syslog(LOG_ERR, "ERROR: Button count mismatch!\n"); + syslog(LOG_ERR, "Expected: %d, Got: %d\n", + CONFIG_NUCLEO_H753ZI_BUTTON_COUNT, g_button_count); + return -EINVAL; + } + + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_button_initialize + * + * Description: + * board_button_initialize() must be called to initialize button + * resources. After that, board_buttons() may be called to collect the + * current state of all buttons or board_button_irq() may be called to + * register button interrupt handlers. + * + ****************************************************************************/ + +uint32_t board_button_initialize(void) +{ + int ret; + int i; + + ret = init_button_configs(); + if (ret < 0) + { + syslog(LOG_ERR, "\n"); + syslog(LOG_ERR, + "======================================================\n"); + syslog(LOG_ERR, " BUTTON CONFIGURATION FAILED\n"); + syslog(LOG_ERR, + "======================================================\n"); + syslog(LOG_ERR, "\n"); + syslog(LOG_ERR, "Please fix the errors above and rebuild.\n"); + syslog(LOG_ERR, "\n"); + return 0; /* Return 0 to indicate failure */ + } + + /* Configure GPIO pins */ + + for (i = 0; i < g_button_count; i++) + { + ret = stm32_configgpio(g_buttons[i]); + if (ret < 0) + { + syslog(LOG_ERR, + "ERROR: Failed to configure GPIO for button %d " + "(ret=%d)\n", i, ret); + return 0; + } + } + + syslog(LOG_INFO, "Button driver initialized: %d buttons ready\n", + g_button_count); + + return g_button_count; +} + +/**************************************************************************** + * Name: board_buttons + * + * Description: + * board_buttons() may be called to collect the current state of all + * buttons. board_buttons() returns a 32-bit bit set with each bit + * associated with a button. See the BUTTON_*_BIT definitions in + * board.h for the meaning of each bit. + * + * Returned Value: + * 32-bit set of button states. Bit set = button pressed. + * + ****************************************************************************/ + +uint32_t board_buttons(void) +{ + uint32_t ret = 0; + bool pressed; + int i; + + /* Check the state of each button */ + + for (i = 0; i < g_button_count; i++) + { + /* With pull-down: HIGH = pressed, LOW = released */ + + pressed = stm32_gpioread(g_buttons[i]); + + /* Set bit if button is pressed */ + + if (pressed) + { + ret |= (1 << i); + } + } + + return ret; +} + +/**************************************************************************** + * Name: board_button_irq + * + * Description: + * board_button_irq() may be called to register an interrupt handler + * that will be called when a button is depressed or released. The ID + * value is a button enumeration value that uniquely identifies a button + * resource. See the BUTTON_* definitions in board.h for the meaning of + * enumeration value. + * + * Input Parameters: + * id - Button ID (0-based index) + * irqhandler - IRQ handler function + * arg - Argument passed to IRQ handler + * + * Returned Value: + * OK on success, negative errno on error + * + ****************************************************************************/ + +#ifdef CONFIG_ARCH_IRQBUTTONS +int board_button_irq(int id, xcpt_t irqhandler, FAR void *arg) +{ + int ret = -EINVAL; + + /* Validate button ID */ + + if (id < 0 || id >= g_button_count) + { + syslog(LOG_ERR, "Invalid button ID %d (valid: 0-%d)\n", + id, g_button_count - 1); + return ret; + } + + /* Register interrupt for both rising and falling edges */ + + ret = stm32_gpiosetevent(g_buttons[id], true, true, true, + irqhandler, arg); + + if (ret < 0) + { + syslog(LOG_ERR, + "Failed to register IRQ for button %d (ret=%d)\n", + id, ret); + } + + return ret; +} +#endif + +#endif /* CONFIG_NUCLEO_H753ZI_BUTTON_SUPPORT */ diff --git a/boards/arm/stm32h7/nucleo-h753zi/src/stm32_composite.c b/boards/arm/stm32h7/nucleo-h753zi/src/stm32_composite.c new file mode 100644 index 0000000000000..5a888f732ebae --- /dev/null +++ b/boards/arm/stm32h7/nucleo-h753zi/src/stm32_composite.c @@ -0,0 +1,349 @@ +/**************************************************************************** + * boards/arm/stm32h7/nucleo-h753zi/src/stm32_composite.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "stm32_otg.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define COMPOSITE0_DEV (3) + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +#ifdef CONFIG_USBMSC_COMPOSITE +static void *g_mschandle; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_mscclassobject + * + * Description: + * If the mass storage class driver is part of composite device, then + * its instantiation and configuration is a multi-step, board-specific, + * process (See comments for usbmsc_configure below). In this case, + * board-specific logic must provide board_mscclassobject(). + * + * board_mscclassobject() is called from the composite driver. It must + * encapsulate the instantiation and configuration of the mass storage + * class and the return the mass storage device's class driver instance + * to the composite driver. + * + * Input Parameters: + * classdev - The location to return the mass storage class' device + * instance. + * + * Returned Value: + * 0 on success; a negated errno on failure + * + ****************************************************************************/ + +#ifdef CONFIG_USBMSC_COMPOSITE +static int board_mscclassobject(int minor, + struct usbdev_devinfo_s *devinfo, + struct usbdevclass_driver_s **classdev) +{ + int ret; + + DEBUGASSERT(g_mschandle == NULL); + + /* Configure the mass storage device */ + + uinfo("Configuring with NLUNS=1\n"); + ret = usbmsc_configure(1, &g_mschandle); + if (ret < 0) + { + uerr("ERROR: usbmsc_configure failed: %d\n", -ret); + return ret; + } + + uinfo("MSC handle=%p\n", g_mschandle); + + /* Bind the LUN(s) */ + + uinfo("Bind LUN=0 to /dev/mmcsd0\n"); + ret = usbmsc_bindlun(g_mschandle, "/dev/mmcsd0", 0, 0, 0, false); + if (ret < 0) + { + uerr("ERROR: usbmsc_bindlun failed for LUN 1 at /dev/mmcsd0: %d\n", + ret); + usbmsc_uninitialize(g_mschandle); + g_mschandle = NULL; + return ret; + } + + /* Get the mass storage device's class object */ + + ret = usbmsc_classobject(g_mschandle, devinfo, classdev); + if (ret < 0) + { + uerr("ERROR: usbmsc_classobject failed: %d\n", -ret); + usbmsc_uninitialize(g_mschandle); + g_mschandle = NULL; + } + + return ret; +} +#endif + +/**************************************************************************** + * Name: board_mscuninitialize + * + * Description: + * Un-initialize the USB storage class driver. + * This is just an application specific wrapper for usbmsc_unitialize() + * that is called form the composite device logic. + * + * Input Parameters: + * classdev - The class driver instance previously given to the composite + * driver by board_mscclassobject(). + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef CONFIG_USBMSC_COMPOSITE +static void board_mscuninitialize(struct usbdevclass_driver_s *classdev) +{ + if (g_mschandle) + { + usbmsc_uninitialize(g_mschandle); + } + + g_mschandle = NULL; +} +#endif + +/**************************************************************************** + * Name: board_composite_connect + * + * Description: + * Connect the USB composite device on the specified USB device port for + * configuration 0. + * + * Input Parameters: + * port - The USB device port. + * + * Returned Value: + * A non-NULL handle value is returned on success. NULL is returned on + * any failure. + * + ****************************************************************************/ + +static void *board_composite0_connect(int port) +{ + struct composite_devdesc_s dev[COMPOSITE0_DEV]; + int ifnobase = 0; + int strbase = COMPOSITE_NSTRIDS; + int dev_idx = 0; + int epin = 1; + int epout = 1; + +#ifdef CONFIG_RNDIS_COMPOSITE + /* Configure the RNDIS USB device */ + + /* Ask the rndis driver to fill in the constants we didn't + * know here. + */ + + usbdev_rndis_get_composite_devdesc(&dev[dev_idx]); + + /* Interfaces */ + + dev[dev_idx].devinfo.ifnobase = ifnobase; + dev[dev_idx].minor = 0; + + /* Strings */ + + dev[dev_idx].devinfo.strbase = strbase; + + /* Endpoints */ + + dev[dev_idx].devinfo.epno[RNDIS_EP_INTIN_IDX] = epin++; + dev[dev_idx].devinfo.epno[RNDIS_EP_BULKIN_IDX] = epin++; + dev[dev_idx].devinfo.epno[RNDIS_EP_BULKOUT_IDX] = epout++; + + /* Count up the base numbers */ + + ifnobase += dev[dev_idx].devinfo.ninterfaces; + strbase += dev[dev_idx].devinfo.nstrings; + + dev_idx += 1; +#endif + +#ifdef CONFIG_CDCACM_COMPOSITE + /* Configure the CDC/ACM device */ + + /* Ask the cdcacm driver to fill in the constants we didn't + * know here. + */ + + cdcacm_get_composite_devdesc(&dev[dev_idx]); + + /* Overwrite and correct some values... */ + + /* The callback functions for the CDC/ACM class */ + + dev[dev_idx].classobject = cdcacm_classobject; + dev[dev_idx].uninitialize = cdcacm_uninitialize; + + /* Interfaces */ + + dev[dev_idx].devinfo.ifnobase = ifnobase; /* Offset to Interface-IDs */ + dev[dev_idx].minor = 0; /* The minor interface number */ + + /* Strings */ + + dev[dev_idx].devinfo.strbase = strbase; /* Offset to String Numbers */ + + /* Endpoints */ + + dev[dev_idx].devinfo.epno[CDCACM_EP_INTIN_IDX] = epin++; + dev[dev_idx].devinfo.epno[CDCACM_EP_BULKIN_IDX] = epin++; + dev[dev_idx].devinfo.epno[CDCACM_EP_BULKOUT_IDX] = epout++; + + /* Count up the base numbers */ + + ifnobase += dev[dev_idx].devinfo.ninterfaces; + strbase += dev[dev_idx].devinfo.nstrings; + + dev_idx += 1; +#endif + +#ifdef CONFIG_USBMSC_COMPOSITE + /* Configure the mass storage device device */ + + /* Ask the usbmsc driver to fill in the constants we didn't + * know here. + */ + + usbmsc_get_composite_devdesc(&dev[dev_idx]); + + /* Overwrite and correct some values... */ + + /* The callback functions for the USBMSC class */ + + dev[dev_idx].classobject = board_mscclassobject; + dev[dev_idx].uninitialize = board_mscuninitialize; + + /* Interfaces */ + + dev[dev_idx].devinfo.ifnobase = ifnobase; /* Offset to Interface-IDs */ + dev[dev_idx].minor = 0; /* The minor interface number */ + + /* Strings */ + + dev[dev_idx].devinfo.strbase = strbase; /* Offset to String Numbers */ + + /* Endpoints */ + + dev[dev_idx].devinfo.epno[USBMSC_EP_BULKIN_IDX] = epin++; + dev[dev_idx].devinfo.epno[USBMSC_EP_BULKOUT_IDX] = epout++; + + /* Count up the base numbers */ + + ifnobase += dev[dev_idx].devinfo.ninterfaces; + strbase += dev[dev_idx].devinfo.nstrings; + + dev_idx += 1; +#endif + + /* Sanity checks */ + + DEBUGASSERT(epin < STM32_NENDPOINTS); + DEBUGASSERT(epout < STM32_NENDPOINTS); + + return composite_initialize(composite_getdevdescs(), dev, dev_idx); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_composite_initialize + * + * Description: + * Perform architecture specific initialization of a composite USB device. + * + ****************************************************************************/ + +int board_composite_initialize(int port) +{ + return OK; +} + +/**************************************************************************** + * Name: board_composite_connect + * + * Description: + * Connect the USB composite device on the specified USB device port using + * the specified configuration. The interpretation of the configid is + * board specific. + * + * Input Parameters: + * port - The USB device port. + * configid - The USB composite configuration + * + * Returned Value: + * A non-NULL handle value is returned on success. NULL is returned on + * any failure. + * + ****************************************************************************/ + +void *board_composite_connect(int port, int configid) +{ + if (configid == 0) + { + return board_composite0_connect(port); + } + else + { + return NULL; + } +} diff --git a/boards/arm/stm32h7/nucleo-h753zi/src/stm32_gpio.c b/boards/arm/stm32h7/nucleo-h753zi/src/stm32_gpio.c new file mode 100644 index 0000000000000..4fe62b5ddce56 --- /dev/null +++ b/boards/arm/stm32h7/nucleo-h753zi/src/stm32_gpio.c @@ -0,0 +1,953 @@ +/**************************************************************************** + * boards/arm/stm32h7/nucleo-h753zi/src/stm32_gpio.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include "chip.h" +#include "stm32_gpio.h" +#include "nucleo-h753zi.h" + +#if defined(CONFIG_DEV_GPIO) && !defined(CONFIG_GPIO_LOWER_HALF) + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* GPIO Driver Validation and Debug Macros */ + +#define STM32_GPIO_VALIDATE_DEVICE(dev) \ + do { \ + DEBUGASSERT((dev) != NULL); \ + } while (0) + +#define STM32_GPIO_VALIDATE_VALUE_PTR(value) \ + do { \ + DEBUGASSERT((value) != NULL); \ + } while (0) + +#define STM32_GPIO_VALIDATE_INDEX(id, max) \ + do { \ + DEBUGASSERT((id) < (max)); \ + } while (0) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* Standard GPIO device structure + * + * This structure represents a basic GPIO pin device that can be used + * for either input or output operations. It contains the standard NuttX + * GPIO device structure plus an ID field to identify which specific + * GPIO pin this device represents in the board's GPIO arrays. + */ + +struct stm32gpio_dev_s +{ + struct gpio_dev_s gpio; /* Standard NuttX GPIO device structure */ + uint8_t id; /* Index into the GPIO configuration arrays */ +}; + +/* GPIO interrupt device structure + * + * This structure extends the basic GPIO device to add interrupt capability. + * It includes a callback function pointer that will be invoked when the + * GPIO interrupt is triggered. The structure embeds the basic GPIO device + * rather than inheriting from it to maintain compatibility with NuttX + * device management. + */ + +struct stm32gpint_dev_s +{ + struct stm32gpio_dev_s stm32gpio; /* Base GPIO device structure */ + pin_interrupt_t callback; /* User-provided interrupt callback */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* GPIO Input Operations */ + +static int stm32_gpin_read(struct gpio_dev_s *dev, bool *value); + +/* GPIO Output Operations */ + +static int stm32_gpout_read(struct gpio_dev_s *dev, bool *value); +static int stm32_gpout_write(struct gpio_dev_s *dev, bool value); + +/* GPIO Interrupt Operations */ + +static int stm32_gpint_read(struct gpio_dev_s *dev, bool *value); +static int stm32_gpint_attach(struct gpio_dev_s *dev, + pin_interrupt_t callback); +static int stm32_gpint_enable(struct gpio_dev_s *dev, bool enable); + +/* Interrupt Service Routine */ + +static int stm32_gpio_interrupt_handler(int irq, void *context, void *arg); + +/* Modular Initialization Functions */ + +static int stm32_gpio_init_input_pins(int *pincount); +static int stm32_gpio_init_output_pins(int *pincount); +static int stm32_gpio_init_interrupt_pins(int *pincount); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* GPIO Operations Tables + * + * These structures define the operations available for each type of GPIO. + * Each GPIO type (input, output, interrupt) has different capabilities: + * - Input: Only read operations + * - Output: Read and write operations + * - Interrupt: Read, attach callback, and enable/disable interrupt + */ + +static const struct gpio_operations_s g_gpin_ops = +{ + .go_read = stm32_gpin_read, + .go_write = NULL, /* Input pins cannot be written */ + .go_attach = NULL, /* Regular inputs don't support interrupts */ + .go_enable = NULL, +}; + +static const struct gpio_operations_s g_gpout_ops = +{ + .go_read = stm32_gpout_read, + .go_write = stm32_gpout_write, + .go_attach = NULL, /* Output pins don't support interrupts */ + .go_enable = NULL, +}; + +static const struct gpio_operations_s g_gpint_ops = +{ + .go_read = stm32_gpint_read, + .go_write = NULL, /* Interrupt pins are input-only */ + .go_attach = stm32_gpint_attach, + .go_enable = stm32_gpint_enable, +}; + +/* GPIO Pin Configuration Arrays and Device Instances + * + * These arrays map the logical GPIO numbers used by applications to the + * actual STM32 GPIO pin configurations. The configurations are defined + * in the board header file (nucleo-h753zi.h). + */ + +#if BOARD_NGPIOIN > 0 +static const uint32_t g_gpioinputs[BOARD_NGPIOIN] = +{ + GPIO_BTN_BUILT_IN, /* User button on PC13 - configured as input */ +}; + +static struct stm32gpio_dev_s g_gpin_devices[BOARD_NGPIOIN]; +#endif + +#if BOARD_NGPIOOUT > 0 +static const uint32_t g_gpiooutputs[BOARD_NGPIOOUT] = +{ + GPIO_LD1, /* Green LED on PB0 - configured as output */ + GPIO_LD2, /* Orange LED on PE1 - configured as output */ + GPIO_LD3, /* Red LED on PB14 - configured as output */ +}; + +static struct stm32gpio_dev_s g_gpout_devices[BOARD_NGPIOOUT]; +#endif + +#if BOARD_NGPIOINT > 0 +static const uint32_t g_gpiointinputs[BOARD_NGPIOINT] = +{ + GPIO_INT1, /* Custom interrupt pin - define in board header */ +}; + +static struct stm32gpint_dev_s g_gpint_devices[BOARD_NGPIOINT]; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_gpio_interrupt_handler + * + * Description: + * This is the common interrupt service routine for all GPIO interrupt + * pins. + * + * When a GPIO interrupt occurs, the STM32 interrupt controller will call + * this function with the appropriate arguments. This function then calls + * the user-provided callback function that was registered via the attach + * operation. + * + * The function performs minimal processing in interrupt context - it just + * validates the parameters and calls the user callback. All complex + * processing should be done in the callback function, preferably by + * posting to a work queue or semaphore. + * + * Input Parameters: + * irq -The interrupt request number (not used in this implementation) + * context -Saved processor context (not used in this implementation) + * arg -Pointer to the stm32gpint_dev_s structure for the triggering pin + * + * Returned Value: + * Always returns OK to indicate the interrupt was handled + * + * Assumptions: + * - Called in interrupt context, so keep processing minimal + * - The arg parameter points to a valid stm32gpint_dev_s structure + * - The callback function pointer is valid (checked by caller) + * + ****************************************************************************/ + +static int stm32_gpio_interrupt_handler(int irq, void *context, void *arg) +{ + struct stm32gpint_dev_s *stm32gpint = (struct stm32gpint_dev_s *)arg; + + DEBUGASSERT(stm32gpint != NULL && stm32gpint->callback != NULL); + + gpioinfo("GPIO interrupt %d triggered, calling callback %p\n", + stm32gpint->stm32gpio.id, stm32gpint->callback); + + /* Execute the user-registered callback function. + * The callback receives the GPIO device pointer and the pin ID. + */ + + stm32gpint->callback(&stm32gpint->stm32gpio.gpio, + stm32gpint->stm32gpio.id); + return OK; +} + +/**************************************************************************** + * Name: stm32_gpin_read + * + * Description: + * Read the current logical state of a GPIO input pin. + * + * This function reads the physical state of a GPIO pin configured as an + * input and returns the logical value (true for HIGH, false for LOW). + * The pin configuration (pull-up, pull-down, etc.) affects what voltage + * levels are interpreted as HIGH or LOW. + * + * For the Nucleo-H753ZI, this is typically used to read the user button + * state. The button is active-low (pressed = LOW voltage), but the + * logical interpretation depends on how the pin is configured in the + * board definitions. + * + * Input Parameters: + * dev - Pointer to the GPIO device structure + * value - Pointer to store the read value (true = HIGH, false = LOW) + * + * Returned Value: + * OK on success; a negated errno value on failure + * + * Assumptions: + * - The GPIO pin was previously configured as an input + * - The device structure is valid and properly initialized + * - The pin ID is within the valid range for input pins + * + ****************************************************************************/ + +static int stm32_gpin_read(struct gpio_dev_s *dev, bool *value) +{ + struct stm32gpio_dev_s *stm32gpio = (struct stm32gpio_dev_s *)dev; + + /* Validate all input parameters */ + + STM32_GPIO_VALIDATE_DEVICE(stm32gpio); + STM32_GPIO_VALIDATE_VALUE_PTR(value); + STM32_GPIO_VALIDATE_INDEX(stm32gpio->id, BOARD_NGPIOIN); + + gpioinfo("Reading GPIO input pin %d\n", stm32gpio->id); + + /* Read the current state of the input pin */ + + *value = stm32_gpioread(g_gpioinputs[stm32gpio->id]); + + gpioinfo("GPIO input %d state: %s\n", + stm32gpio->id, *value ? "HIGH" : "LOW"); + + return OK; +} + +/**************************************************************************** + * Name: stm32_gpout_read + * + * Description: + * Read the current logical state of a GPIO output pin. + * + * This function reads back the current state that was written to an output + * pin. This is useful for applications that need to know the current state + * of an output (for example, to toggle a LED state). The function reads + * the actual pin state, not just the last written value, so it reflects + * the real electrical state of the pin. + * + * For the Nucleo-H753ZI LEDs, this allows applications to check if a LED + * is currently on or off before deciding whether to toggle it. + * + * Input Parameters: + * dev - Pointer to the GPIO device structure + * value - Pointer to store the read value (true = HIGH, false = LOW) + * + * Returned Value: + * OK on success; a negated errno value on failure + * + * Assumptions: + * - The GPIO pin was previously configured as an output + * - The device structure is valid and properly initialized + * - The pin ID is within the valid range for output pins + * + ****************************************************************************/ + +static int stm32_gpout_read(struct gpio_dev_s *dev, bool *value) +{ + struct stm32gpio_dev_s *stm32gpio = (struct stm32gpio_dev_s *)dev; + + /* Validate all input parameters */ + + STM32_GPIO_VALIDATE_DEVICE(stm32gpio); + STM32_GPIO_VALIDATE_VALUE_PTR(value); + STM32_GPIO_VALIDATE_INDEX(stm32gpio->id, BOARD_NGPIOOUT); + + gpioinfo("Reading GPIO output pin %d current state\n", stm32gpio->id); + + /* Read the current output state of the pin */ + + *value = stm32_gpioread(g_gpiooutputs[stm32gpio->id]); + + gpioinfo("GPIO output %d current state: %s\n", + stm32gpio->id, *value ? "HIGH" : "LOW"); + + return OK; +} + +/**************************************************************************** + * Name: stm32_gpout_write + * + * Description: + * Write a logical value to a GPIO output pin. + * + * This is the core function that allows applications to control GPIO + * output pins. It sets the electrical state of the pin to either HIGH + * (3.3V) or LOW (0V) based on the boolean value provided. + * + * For the Nucleo-H753ZI LEDs: + * - Writing true (HIGH) will turn ON the LED (LED is active-high) + * - Writing false (LOW) will turn OFF the LED + * + * The function provides debug output to help with troubleshooting GPIO + * operations during development. In production builds with debug disabled, + * this overhead is eliminated by the compiler. + * + * This function is called by the NuttX GPIO framework when user + * applications perform write operations via ioctl(GPIOC_WRITE) + * or gpio_write() calls. + * + * Input Parameters: + * dev - Pointer to the GPIO device structure + * value - Value to write (true = HIGH/3.3V, false = LOW/0V) + * + * Returned Value: + * OK on success; a negated errno value on failure + * + * Assumptions: + * - The GPIO pin was previously configured as an output + * - The device structure is valid and properly initialized + * - The pin ID is within the valid range for output pins + * - The pin is not being used by another driver or function + * + ****************************************************************************/ + +static int stm32_gpout_write(struct gpio_dev_s *dev, bool value) +{ + struct stm32gpio_dev_s *stm32gpio = (struct stm32gpio_dev_s *)dev; + + /* Validate input parameters */ + + STM32_GPIO_VALIDATE_DEVICE(stm32gpio); + STM32_GPIO_VALIDATE_INDEX(stm32gpio->id, BOARD_NGPIOOUT); + + gpioinfo("Writing GPIO output pin %d: %s\n", + stm32gpio->id, value ? "HIGH" : "LOW"); + + /* Write the new state to the GPIO pin. + * This calls the STM32-specific GPIO write function which handles + * the low-level register manipulation to set the pin state. + */ + + stm32_gpiowrite(g_gpiooutputs[stm32gpio->id], value); + + gpioinfo("GPIO output %d write completed successfully\n", stm32gpio->id); + + return OK; +} + +/**************************************************************************** + * Name: stm32_gpint_read + * + * Description: + * Read the current logical state of a GPIO interrupt pin. + * + * This function allows reading the current state of a pin that is + * configured for interrupt generation. Even though the pin is primarily + * used for interrupts, it can still be read synchronously to check its + * current state. This is useful for: + * + * - Polling the pin state when interrupts are disabled + * - Checking initial pin state during initialization + * - Debouncing in software by reading multiple times + * - Diagnostics and debugging + * + * Note that this reads the actual pin electrical state, which may be + * different from the last interrupt trigger if the pin has changed + * since the interrupt occurred. + * + * Input Parameters: + * dev - Pointer to the GPIO device structure + * value - Pointer to store the read value (true = HIGH, false = LOW) + * + * Returned Value: + * OK on success; a negated errno value on failure + * + * Assumptions: + * - The GPIO pin was previously configured for interrupt input + * - The device structure is valid and properly initialized + * - The pin ID is within the valid range for interrupt pins + * + ****************************************************************************/ + +static int stm32_gpint_read(struct gpio_dev_s *dev, bool *value) +{ + struct stm32gpint_dev_s *stm32gpint = (struct stm32gpint_dev_s *)dev; + + /* Validate all input parameters */ + + STM32_GPIO_VALIDATE_DEVICE(stm32gpint); + STM32_GPIO_VALIDATE_VALUE_PTR(value); + STM32_GPIO_VALIDATE_INDEX(stm32gpint->stm32gpio.id, BOARD_NGPIOINT); + + gpioinfo("Reading GPIO interrupt pin %d current state\n", + stm32gpint->stm32gpio.id); + + /* Read the current state of the interrupt pin */ + + *value = stm32_gpioread(g_gpiointinputs[stm32gpint->stm32gpio.id]); + + gpioinfo("GPIO interrupt pin %d current state: %s\n", + stm32gpint->stm32gpio.id, *value ? "HIGH" : "LOW"); + + return OK; +} + +/**************************************************************************** + * Name: stm32_gpint_attach + * + * Description: + * Attach a callback function to a GPIO interrupt pin. + * + * This function registers a user-provided callback function that will be + * executed when the GPIO interrupt is triggered. The callback is stored + * in the device structure and will be called by the interrupt handler. + * + * Key behaviors: + * - Any existing interrupt is automatically disabled during attachment + * - The callback can be changed by calling attach again with a new + * function. + * + * - Setting callback to NULL effectively detaches the interrupt + * - The interrupt must be explicitly enabled after attachment using + * the enable operation + * + * The callback function will be called in interrupt context, so it should: + * - Be as fast as possible + * - Not call blocking functions + * - Consider posting to work queues for complex processing + * - Be reentrant if the same callback is used for multiple pins + * + * Input Parameters: + * dev - Pointer to the GPIO device structure + * callback - Function to call when interrupt occurs + * (can be NULL to detach) + * + * Returned Value: + * OK on success; a negated errno value on failure + * + * Assumptions: + * - The GPIO pin was previously configured for interrupt input + * - The device structure is valid and properly initialized + * - The callback function (if not NULL) is valid and reentrant + * + ****************************************************************************/ + +static int stm32_gpint_attach(struct gpio_dev_s *dev, + pin_interrupt_t callback) +{ + struct stm32gpint_dev_s *stm32gpint = (struct stm32gpint_dev_s *)dev; + + STM32_GPIO_VALIDATE_DEVICE(stm32gpint); + + gpioinfo("Attaching callback %p to GPIO interrupt pin %d\n", + callback, stm32gpint->stm32gpio.id); + + /* Disable any existing interrupt configuration before changing callback. + * This ensures we don't get spurious interrupts during the transition. + */ + + stm32_gpiosetevent(g_gpiointinputs[stm32gpint->stm32gpio.id], + false, false, false, NULL, NULL); + + /* Store the new callback function */ + + stm32gpint->callback = callback; + + if (callback != NULL) + { + gpioinfo("Callback attached successfully to GPIO interrupt %d\n", + stm32gpint->stm32gpio.id); + } + else + { + gpioinfo("Callback detached from GPIO interrupt %d\n", + stm32gpint->stm32gpio.id); + } + + return OK; +} + +/**************************************************************************** + * Name: stm32_gpint_enable + * + * Description: + * Enable or disable GPIO interrupt generation. + * + * This function controls whether the GPIO pin will actually generate + * interrupts when the configured event occurs. The pin must have a + * callback attached before enabling interrupts. + * + * When enabling: + * - Configures the pin for rising edge detection (button release) + * - Registers the interrupt handler with the STM32 interrupt controller + * - The interrupt will fire when the pin transitions from LOW to HIGH + * + * When disabling: + * - Removes interrupt configuration from the pin + * - No interrupts will be generated until re-enabled + * - The callback remains attached and can be re-enabled later + * + * For the Nucleo board button (if used as interrupt): + * - Button is typically active-low (pressed = LOW) + * - Rising edge = button release + * - Falling edge = button press + * - Configure based on desired behavior + * + * Input Parameters: + * dev - Pointer to the GPIO device structure + * enable - true to enable interrupts, false to disable + * + * Returned Value: + * OK on success; -EINVAL if no callback is attached when enabling + * + * Assumptions: + * - The GPIO pin was previously configured for interrupt input + * - For enable=true: a valid callback must be attached first + * - The device structure is valid and properly initialized + * + ****************************************************************************/ + +static int stm32_gpint_enable(struct gpio_dev_s *dev, bool enable) +{ + struct stm32gpint_dev_s *stm32gpint = (struct stm32gpint_dev_s *)dev; + + STM32_GPIO_VALIDATE_DEVICE(stm32gpint); + + if (enable) + { + /* Cannot enable interrupt without a callback function */ + + if (stm32gpint->callback == NULL) + { + gpioerr("ERROR: Cannot enable GPIO interrupt %d \n", + stm32gpint->stm32gpio.id); + return -EINVAL; + } + + gpioinfo("Enabling GPIO interrupt %d with rising edge detection\n", + stm32gpint->stm32gpio.id); + + /* Configure the interrupt for rising edge detection. + * Parameters: pin, rising, falling, filter, handler, arg + * - rising=true: interrupt on LOW->HIGH transition + * - falling=false: no interrupt on HIGH->LOW transition + * - filter=false: no input filtering + */ + + stm32_gpiosetevent(g_gpiointinputs[stm32gpint->stm32gpio.id], + true, false, false, + stm32_gpio_interrupt_handler, + &g_gpint_devices[stm32gpint->stm32gpio.id]); + + gpioinfo("GPIO interrupt %d enabled successfully\n", + stm32gpint->stm32gpio.id); + } + else + { + gpioinfo("Disabling GPIO interrupt %d\n", stm32gpint->stm32gpio.id); + + /* Disable the interrupt by clearing all event configuration */ + + stm32_gpiosetevent(g_gpiointinputs[stm32gpint->stm32gpio.id], + false, false, false, NULL, NULL); + + gpioinfo("GPIO interrupt %d disabled successfully\n", + stm32gpint->stm32gpio.id); + } + + return OK; +} + +/**************************************************************************** + * Name: stm32_gpio_init_input_pins + * + * Description: + * Initialize all GPIO input pins defined for this board. + * + * This function sets up each input pin by: + * 1. Initializing the device structure with proper type and operations + * 2. Registering the pin with the NuttX GPIO framework + * 3. Configuring the physical STM32 GPIO hardware + * + * After this initialization, applications can access the input pins + * via the /dev/gpio device interface using standard read operations. + * + * For Nucleo-H753ZI, this typically configures the user button (PC13) + * as a readable input that applications can poll. + * + * Input Parameters: + * pincount - Pointer to current pin count (updated by this function) + * + * Returned Value: + * Number of input pins initialized + * + * Side Effects: + * - Updates the pincount parameter with number of pins registered + * - Configures STM32 GPIO hardware registers + * - Registers devices with NuttX GPIO framework + * + ****************************************************************************/ + +static int stm32_gpio_init_input_pins(int *pincount) +{ +#if BOARD_NGPIOIN > 0 + int i; + int pins_initialized = 0; + + gpioinfo("Initializing %d GPIO input pins\n", BOARD_NGPIOIN); + + for (i = 0; i < BOARD_NGPIOIN; i++) + { + /* Initialize the GPIO device structure */ + + g_gpin_devices[i].gpio.gp_pintype = GPIO_INPUT_PIN; + g_gpin_devices[i].gpio.gp_ops = &g_gpin_ops; + g_gpin_devices[i].id = i; + + /* Register the GPIO pin with the NuttX GPIO framework */ + + gpio_pin_register(&g_gpin_devices[i].gpio, (*pincount)++); + + /* Configure the physical STM32 GPIO pin hardware */ + + stm32_configgpio(g_gpioinputs[i]); + + pins_initialized++; + + gpioinfo("GPIO input %d: configured and registered as /dev/gpio%d\n", + i, (*pincount) - 1); + } + + gpioinfo("GPIO input initialization completed: %d pins\n", + pins_initialized); + return pins_initialized; +#else + gpioinfo("No GPIO input pins configured for this board\n"); + return 0; +#endif +} + +/**************************************************************************** + * Name: stm32_gpio_init_output_pins + * + * Description: + * Initialize all GPIO output pins defined for this board. + * + * This function sets up each output pin by: + * 1. Initializing the device structure with output type and operations + * 2. Registering the pin with the NuttX GPIO framework + * 3. Setting initial state to LOW (off) for safety + * 4. Configuring the physical STM32 GPIO hardware + * + * The initial LOW state ensures that LEDs start in the OFF state and + * other outputs start in a safe condition. Applications can then control + * the outputs via write operations. + * + * For Nucleo-H753ZI, this configures the three onboard LEDs: + * - LD1 (Green LED on PB0) + * - LD2 (Orange LED on PE1) + * - LD3 (Red LED on PB14) + * + * After initialization, applications can control these LEDs via + * /dev/gpio device interface using ioctl(GPIOC_WRITE) calls. + * + * Input Parameters: + * pincount - Pointer to current pin count (updated by this function) + * + * Returned Value: + * Number of output pins initialized + * + * Side Effects: + * - Updates the pincount parameter with number of pins registered + * - Sets all output pins to LOW state initially + * - Configures STM32 GPIO hardware registers + * - Registers devices with NuttX GPIO framework + * + ****************************************************************************/ + +static int stm32_gpio_init_output_pins(int *pincount) +{ +#if BOARD_NGPIOOUT > 0 + int i; + int pins_initialized = 0; + + gpioinfo("Initializing %d GPIO output pins\n", BOARD_NGPIOOUT); + + for (i = 0; i < BOARD_NGPIOOUT; i++) + { + /* Initialize the GPIO device structure */ + + g_gpout_devices[i].gpio.gp_pintype = GPIO_OUTPUT_PIN; + g_gpout_devices[i].gpio.gp_ops = &g_gpout_ops; + g_gpout_devices[i].id = i; + + /* Register the GPIO pin with the NuttX GPIO framework */ + + gpio_pin_register(&g_gpout_devices[i].gpio, (*pincount)++); + + /* Initialize output to LOW for safety, then configure hardware. + * This ensures LEDs start OFF and other outputs start in safe state. + */ + + stm32_gpiowrite(g_gpiooutputs[i], false); + stm32_configgpio(g_gpiooutputs[i]); + + pins_initialized++; + + gpioinfo("GPIO output %d: configured as LOW at /dev/gpio%d\n", + i, (*pincount) - 1); + } + + gpioinfo("GPIO output initialization completed: %d pins\n", + pins_initialized); + + return pins_initialized; +#else + gpioinfo("No GPIO output pins configured for this board\n"); + return 0; +#endif +} + +/**************************************************************************** + * Name: stm32_gpio_init_interrupt_pins + * + * Description: + * Initialize all GPIO interrupt pins defined for this board. + * + * This function sets up each interrupt-capable pin by: + * 1. Initializing the extended device structure with interrupt capability + * 2. Registering the pin with the NuttX GPIO framework + * 3. Configuring the physical STM32 GPIO hardware for input + * 4. Setting up initial state (callback = NULL, interrupt disabled) + * + * Unlike simple input pins, interrupt pins require additional setup + * to support asynchronous event notification. The pin starts in a safe + * state with no callback attached and interrupts disabled. Applications + * must explicitly attach a callback and enable interrupts to receive + * asynchronous notifications. + * + * The interrupt pins can also be read synchronously like regular inputs, + * providing flexibility in how applications interact with them. + * + * Important: The actual interrupt configuration (edge detection, etc.) + * is done later when the interrupt is enabled, not during initialization. + * + * Input Parameters: + * pincount - Pointer to current pin count (updated by this function) + * + * Returned Value: + * Number of interrupt pins initialized + * + * Side Effects: + * - Updates the pincount parameter with number of pins registered + * - Configures STM32 GPIO hardware registers for input mode + * - Registers devices with NuttX GPIO framework + * - Initializes callback pointers to NULL for safety + * + ****************************************************************************/ + +static int stm32_gpio_init_interrupt_pins(int *pincount) +{ +#if BOARD_NGPIOINT > 0 + int i; + int pins_initialized = 0; + + gpioinfo("Initializing %d GPIO interrupt pins\n", BOARD_NGPIOINT); + + for (i = 0; i < BOARD_NGPIOINT; i++) + { + /* Initialize the GPIO interrupt device structure */ + + g_gpint_devices[i].stm32gpio.gpio.gp_pintype = GPIO_INTERRUPT_PIN; + g_gpint_devices[i].stm32gpio.gpio.gp_ops = &g_gpint_ops; + g_gpint_devices[i].stm32gpio.id = i; + + /* Safe initial state */ + + g_gpint_devices[i].callback = NULL; + + /* Register the GPIO pin with the NuttX GPIO framework */ + + gpio_pin_register(&g_gpint_devices[i].stm32gpio.gpio, (*pincount)++); + + /* Configure the physical STM32 GPIO pin for input. + * Interrupt configuration will be done later when enabled. + */ + + stm32_configgpio(g_gpiointinputs[i]); + + pins_initialized++; + + gpioinfo("GPIO interrupt %d: registered as /dev/gpio%d\n", + i, (*pincount) - 1); + } + + gpioinfo("GPIO interrupt initialization completed: %d pins\n", + pins_initialized); + + return pins_initialized; +#else + gpioinfo("No GPIO interrupt pins configured for this board\n"); + return 0; +#endif +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_gpio_initialize + * + * Description: + * Initialize the GPIO driver for the STM32H7 Nucleo board. + * + * This is the main initialization function that sets up all GPIO pins + * defined for the board. It coordinates the initialization of different + * types of GPIO pins (inputs, outputs, interrupts) and registers them + * with the NuttX GPIO framework. + * + * The function creates device nodes under /dev/gpio* that applications + * can use to interact with the GPIO pins. The numbering is sequential + * across all pin types (inputs first, then outputs, then interrupts). + * + * For the Nucleo-H753ZI board, this typically results in: + * - /dev/gpio0 : User button (input) + * - /dev/gpio1 : LD1 Green LED (output) + * - /dev/gpio2 : LD2 Orange LED (output) + * - /dev/gpio3 : LD3 Red LED (output) + * - /dev/gpio4 : Custom interrupt pin (interrupt) + * + * Applications can then use standard file operations: + * - open("/dev/gpio1", O_RDWR) + * - ioctl(fd, GPIOC_WRITE, 1) // Turn on LED + * - ioctl(fd, GPIOC_READ, &value) // Read current state + * - close(fd) + * + * This function is typically called during board initialization, before + * applications start running. + * + * Input Parameters: + * None + * + * Returned Value: + * OK on success; a negated errno value on failure + * + * Side Effects: + * - Configures STM32 GPIO hardware for all defined pins + * - Creates device nodes in /dev filesystem + * - Initializes all GPIO device structures + * - May enable GPIO peripheral clocks (handled by lower-level functions) + * + * Notes: + * - This function is only compiled if CONFIG_DEV_GPIO is enabled + * - Requires board-specific GPIO definitions in the board header file + * - Safe to call multiple times (GPIO framework handles re-registration) + * + ****************************************************************************/ + +int stm32_gpio_initialize(void) +{ + int total_pins = 0; + int pincount = 0; + + gpioinfo("Starting STM32H7 GPIO driver initialization\n"); + + /* Initialize each type of GPIO pin in logical order */ + + total_pins += stm32_gpio_init_input_pins(&pincount); + total_pins += stm32_gpio_init_output_pins(&pincount); + total_pins += stm32_gpio_init_interrupt_pins(&pincount); + + gpioinfo("STM32H7 GPIO driver initialization completed successfully\n"); + gpioinfo("Total GPIO pins initialized: %d\n", total_pins); + gpioinfo("GPIO devices available: /dev/gpio0 through /dev/gpio%d\n", + pincount - 1); + + return OK; +} + +#endif /* CONFIG_DEV_GPIO && !CONFIG_GPIO_LOWER_HALF */ diff --git a/boards/arm/stm32h7/nucleo-h753zi/src/stm32_i2c.c b/boards/arm/stm32h7/nucleo-h753zi/src/stm32_i2c.c new file mode 100644 index 0000000000000..73249ecbfe777 --- /dev/null +++ b/boards/arm/stm32h7/nucleo-h753zi/src/stm32_i2c.c @@ -0,0 +1,646 @@ +/**************************************************************************** + * boards/arm/stm32h7/nucleo-h753zi/src/stm32_i2c.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +#include "stm32_i2c.h" +#include +#include + +#include "nucleo-h753zi.h" + +#ifdef CONFIG_STM32H7_I2C + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define MAX_I2C_DEVICES_PER_BUS 16 +#define INVALID_I2C_ADDR 0xff + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* I2C device registration structure */ + +struct i2c_device_s +{ + uint8_t addr; /* I2C slave address (7-bit) */ + uint32_t frequency; /* Bus frequency for this device */ + char name[16]; /* Device instance name (for logging) */ + bool in_use; /* true = slot occupied */ +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* I2C master interfaces (cached after initialization) */ + +#ifdef CONFIG_STM32H7_I2C1 +static struct i2c_master_s *g_i2c1_master = NULL; +static struct i2c_device_s g_i2c1_devices[MAX_I2C_DEVICES_PER_BUS]; +#endif + +#ifdef CONFIG_STM32H7_I2C2 +static struct i2c_master_s *g_i2c2_master = NULL; +static struct i2c_device_s g_i2c2_devices[MAX_I2C_DEVICES_PER_BUS]; +#endif + +#ifdef CONFIG_STM32H7_I2C3 +static struct i2c_master_s *g_i2c3_master = NULL; +static struct i2c_device_s g_i2c3_devices[MAX_I2C_DEVICES_PER_BUS]; +#endif + +#ifdef CONFIG_STM32H7_I2C4 +static struct i2c_master_s *g_i2c4_master = NULL; +static struct i2c_device_s g_i2c4_devices[MAX_I2C_DEVICES_PER_BUS]; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: get_i2c_master_ptr + * + * Description: + * Get pointer to I2C master interface storage for a specific bus. + * + * Input Parameters: + * i2c_bus - I2C bus number (1-4) + * + * Returned Value: + * Pointer to I2C master pointer storage, NULL if invalid bus + * + ****************************************************************************/ + +static struct i2c_master_s **get_i2c_master_ptr(int i2c_bus) +{ + switch (i2c_bus) + { +#ifdef CONFIG_STM32H7_I2C1 + case 1: + return &g_i2c1_master; +#endif +#ifdef CONFIG_STM32H7_I2C2 + case 2: + return &g_i2c2_master; +#endif +#ifdef CONFIG_STM32H7_I2C3 + case 3: + return &g_i2c3_master; +#endif +#ifdef CONFIG_STM32H7_I2C4 + case 4: + return &g_i2c4_master; +#endif + default: + return NULL; + } +} + +/**************************************************************************** + * Name: get_i2c_devices_array + * + * Description: + * Get I2C devices array for a specific bus. + * + * Input Parameters: + * i2c_bus - I2C bus number (1-4) + * + * Returned Value: + * Pointer to I2C devices array, NULL if invalid bus + * + ****************************************************************************/ + +static struct i2c_device_s *get_i2c_devices_array(int i2c_bus) +{ + switch (i2c_bus) + { +#ifdef CONFIG_STM32H7_I2C1 + case 1: + return g_i2c1_devices; +#endif +#ifdef CONFIG_STM32H7_I2C2 + case 2: + return g_i2c2_devices; +#endif +#ifdef CONFIG_STM32H7_I2C3 + case 3: + return g_i2c3_devices; +#endif +#ifdef CONFIG_STM32H7_I2C4 + case 4: + return g_i2c4_devices; +#endif + default: + return NULL; + } +} + +/**************************************************************************** + * Name: validate_i2c_addr + * + * Description: + * Validate I2C 7-bit address. + * Reserved addresses: 0x00-0x07, 0x78-0x7F + * + * Input Parameters: + * addr - I2C address to validate + * + * Returned Value: + * true if valid, false if reserved or out of range + * + ****************************************************************************/ + +static bool validate_i2c_addr(uint8_t addr) +{ + /* I2C 7-bit addressing: + * 0x00-0x07: Reserved addresses + * 0x08-0x77: Valid addresses + * 0x78-0x7F: Reserved addresses + */ + + if (addr < 0x08 || addr > 0x77) + { + return false; + } + + return true; +} + +/**************************************************************************** + * Name: find_device_slot + * + * Description: + * Find a free slot in the I2C devices array. + * + * Input Parameters: + * devices - Pointer to I2C devices array + * + * Returned Value: + * Index of free slot, -ENOMEM if no slots available + * + ****************************************************************************/ + +static int find_device_slot(struct i2c_device_s *devices) +{ + int i; + + for (i = 0; i < MAX_I2C_DEVICES_PER_BUS; i++) + { + if (!devices[i].in_use) + { + return i; + } + } + + return -ENOMEM; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_i2c_initialize + * + * Description: + * Initialize I2C buses based on Kconfig configuration. + * Pins are selected via board.h pinset configuration. + * + * Returned Value: + * OK on success, negative errno on error + * + ****************************************************************************/ + +int stm32_i2c_initialize(void) +{ + syslog(LOG_INFO, "Initializing I2C interfaces\n"); + +#ifdef CONFIG_NUCLEO_H753ZI_I2C1_ENABLE + g_i2c1_master = stm32_i2cbus_initialize(1); + if (!g_i2c1_master) + { + syslog(LOG_ERR, "ERROR: Failed to initialize I2C1\n"); + return -ENODEV; + } + + memset(g_i2c1_devices, 0, sizeof(g_i2c1_devices)); + syslog(LOG_INFO, "I2C1 initialized successfully\n"); +#endif + +#ifdef CONFIG_NUCLEO_H753ZI_I2C2_ENABLE + g_i2c2_master = stm32_i2cbus_initialize(2); + if (!g_i2c2_master) + { + syslog(LOG_ERR, "ERROR: Failed to initialize I2C2\n"); + return -ENODEV; + } + + memset(g_i2c2_devices, 0, sizeof(g_i2c2_devices)); + syslog(LOG_INFO, "I2C2 initialized successfully\n"); +#endif + +#ifdef CONFIG_NUCLEO_H753ZI_I2C3_ENABLE + g_i2c3_master = stm32_i2cbus_initialize(3); + if (!g_i2c3_master) + { + syslog(LOG_ERR, "ERROR: Failed to initialize I2C3\n"); + return -ENODEV; + } + + memset(g_i2c3_devices, 0, sizeof(g_i2c3_devices)); + syslog(LOG_INFO, "I2C3 initialized successfully\n"); +#endif + +#ifdef CONFIG_NUCLEO_H753ZI_I2C4_ENABLE + g_i2c4_master = stm32_i2cbus_initialize(4); + if (!g_i2c4_master) + { + syslog(LOG_ERR, "ERROR: Failed to initialize I2C4\n"); + return -ENODEV; + } + + memset(g_i2c4_devices, 0, sizeof(g_i2c4_devices)); + syslog(LOG_INFO, "I2C4 initialized successfully\n"); +#endif + + syslog(LOG_INFO, "I2C initialization completed\n"); + return OK; +} + +/**************************************************************************** + * Name: stm32_i2c_register_device + * + * Description: + * Register an I2C device with specific address, frequency, and name. + * This function tracks device configurations for debugging and + * provides validation. + * + * Input Parameters: + * i2c_bus - I2C bus number (1-4) + * addr - I2C slave address (7-bit, 0x08-0x77) + * frequency - Bus frequency for this device (Hz) + * name - Descriptive name for logging (can be NULL) + * + * Returned Value: + * OK on success, negative errno on error + * + ****************************************************************************/ + +int stm32_i2c_register_device(int i2c_bus, uint8_t addr, + uint32_t frequency, const char *name) +{ + struct i2c_device_s *devices; + struct i2c_device_s *device; + int slot; + int i; + + /* Validate bus */ + + devices = get_i2c_devices_array(i2c_bus); + if (!devices) + { + syslog(LOG_ERR, "ERROR: Invalid I2C bus %d\n", i2c_bus); + return -EINVAL; + } + + /* Validate address */ + + if (!validate_i2c_addr(addr)) + { + syslog(LOG_ERR, + "ERROR: Invalid I2C address 0x%02x " + "(reserved or out of range)\n", addr); + syslog(LOG_ERR, " Valid range: 0x08-0x77\n"); + return -EINVAL; + } + + /* Check for duplicate address */ + + for (i = 0; i < MAX_I2C_DEVICES_PER_BUS; i++) + { + if (devices[i].in_use && devices[i].addr == addr) + { + syslog(LOG_WARNING, + "WARNING: Address 0x%02x already registered on I2C%d " + "as '%s'\n", addr, i2c_bus, devices[i].name); + syslog(LOG_WARNING, + " Allowing duplicate (multi-function device?)\n"); + + /* Continue anyway - might be multi-function device like LSM303 */ + } + } + + /* Find free slot */ + + slot = find_device_slot(devices); + if (slot < 0) + { + syslog(LOG_ERR, + "ERROR: No free slots for I2C%d devices " + "(max %d devices per bus)\n", + i2c_bus, MAX_I2C_DEVICES_PER_BUS); + return -ENOMEM; + } + + /* Register device */ + + device = &devices[slot]; + device->addr = addr; + device->frequency = frequency; + device->in_use = true; + + if (name != NULL) + { + strncpy(device->name, name, sizeof(device->name) - 1); + device->name[sizeof(device->name) - 1] = '\0'; + } + else + { + snprintf(device->name, sizeof(device->name), "dev_0x%02x", addr); + } + + syslog(LOG_INFO, "Registered I2C%d device [%d]: '%s' @ 0x%02x, %lu Hz\n", + i2c_bus, slot, device->name, addr, (unsigned long)frequency); + + return OK; +} + +/**************************************************************************** + * Name: stm32_i2c_unregister_device + * + * Description: + * Unregister an I2C device by address. + * + * Input Parameters: + * i2c_bus - I2C bus number (1-4) + * addr - I2C slave address to unregister + * + * Returned Value: + * OK on success, -ENOENT if not found, other negative errno on error + * + ****************************************************************************/ + +int stm32_i2c_unregister_device(int i2c_bus, uint8_t addr) +{ + struct i2c_device_s *devices; + int i; + + devices = get_i2c_devices_array(i2c_bus); + if (!devices) + { + return -EINVAL; + } + + /* Find and remove device */ + + for (i = 0; i < MAX_I2C_DEVICES_PER_BUS; i++) + { + if (devices[i].in_use && devices[i].addr == addr) + { + syslog(LOG_INFO, + "Unregistered I2C%d device [%d]: '%s' @ 0x%02x\n", + i2c_bus, i, devices[i].name, addr); + + memset(&devices[i], 0, sizeof(struct i2c_device_s)); + return OK; + } + } + + syslog(LOG_WARNING, "WARNING: Device 0x%02x not found on I2C%d\n", + addr, i2c_bus); + return -ENOENT; +} + +/**************************************************************************** + * Name: stm32_i2c_get_master + * + * Description: + * Get I2C master interface for a specific bus. + * This is the main function used by sensor drivers to get the I2C + * interface they need. + * + * Input Parameters: + * i2c_bus - I2C bus number (1-4) + * + * Returned Value: + * Pointer to I2C master interface, NULL if invalid bus or not initialized + * + ****************************************************************************/ + +struct i2c_master_s *stm32_i2c_get_master(int i2c_bus) +{ + struct i2c_master_s **master_ptr; + + master_ptr = get_i2c_master_ptr(i2c_bus); + if (!master_ptr) + { + syslog(LOG_ERR, "ERROR: Invalid I2C bus %d\n", i2c_bus); + return NULL; + } + + if (!(*master_ptr)) + { + syslog(LOG_ERR, "ERROR: I2C%d not initialized\n", i2c_bus); + return NULL; + } + + return *master_ptr; +} + +/**************************************************************************** + * Name: stm32_i2c_scan_bus + * + * Description: + * Scan an I2C bus for connected devices. + * Useful for debugging and hardware validation. + * + * Input Parameters: + * i2c_bus - I2C bus number (1-4) + * + * Returned Value: + * Number of devices found, negative errno on error + * + ****************************************************************************/ + +#ifdef CONFIG_I2C_RESET +int stm32_i2c_scan_bus(int i2c_bus) +{ + struct i2c_master_s *i2c; + struct i2c_msg_s msg; + uint8_t buffer[1]; + uint8_t addr; + int found = 0; + int ret; + + i2c = stm32_i2c_get_master(i2c_bus); + if (!i2c) + { + return -ENODEV; + } + + syslog(LOG_INFO, "Scanning I2C%d bus (addresses 0x08-0x77)...\n", + i2c_bus); + syslog(LOG_INFO, + " 0 1 2 3 4 5 6 7 8 9 A B C D E F\n"); + + for (addr = 0x00; addr <= 0x7f; addr++) + { + if ((addr & 0x0f) == 0) + { + syslog(LOG_INFO, "%02x: ", addr); + } + + /* Skip reserved addresses */ + + if (addr < 0x08 || addr > 0x77) + { + syslog(LOG_INFO, " "); + } + else + { + /* Try to communicate with device */ + + msg.frequency = 100000; /* 100 kHz for scanning */ + msg.addr = addr; + msg.flags = 0; + msg.buffer = buffer; + msg.length = 0; + + ret = I2C_TRANSFER(i2c, &msg, 1); + if (ret == OK) + { + syslog(LOG_INFO, "%02x ", addr); + found++; + } + else + { + syslog(LOG_INFO, "-- "); + } + } + + if ((addr & 0x0f) == 0x0f) + { + syslog(LOG_INFO, "\n"); + } + } + + syslog(LOG_INFO, "\nScan complete: %d devices found on I2C%d\n", + found, i2c_bus); + + return found; +} +#endif /* CONFIG_I2C_RESET */ + +/**************************************************************************** + * Name: stm32_i2c_list_devices + * + * Description: + * List all registered I2C devices on a specific bus. + * Useful for debugging. + * + * Input Parameters: + * i2c_bus - I2C bus number (1-4), or 0 for all buses + * + * Returned Value: + * Number of registered devices + * + ****************************************************************************/ + +int stm32_i2c_list_devices(int i2c_bus) +{ + struct i2c_device_s *devices; + int total = 0; + int bus; + int i; + int start_bus; + int end_bus; + + if (i2c_bus == 0) + { + /* List all buses */ + + start_bus = 1; + end_bus = 4; + } + else + { + /* List specific bus */ + + start_bus = i2c_bus; + end_bus = i2c_bus; + } + + syslog(LOG_INFO, "\nRegistered I2C Devices:\n"); + syslog(LOG_INFO, "%-5s %-4s %-12s %-8s %-10s\n", + "Bus", "Slot", "Name", "Address", "Frequency"); + syslog(LOG_INFO, "%-5s %-4s %-12s %-8s %-10s\n", + "---", "----", "------------", "--------", "----------"); + + for (bus = start_bus; bus <= end_bus; bus++) + { + devices = get_i2c_devices_array(bus); + if (!devices) + { + continue; + } + + for (i = 0; i < MAX_I2C_DEVICES_PER_BUS; i++) + { + if (devices[i].in_use) + { + syslog(LOG_INFO, + "I2C%-2d %-4d %-12s 0x%02x %-10lu\n", + bus, i, devices[i].name, devices[i].addr, + (unsigned long)devices[i].frequency); + total++; + } + } + } + + if (total == 0) + { + syslog(LOG_INFO, "(No devices registered)\n"); + } + else + { + syslog(LOG_INFO, "\nTotal: %d device(s)\n", total); + } + + return total; +} + +#endif /* CONFIG_STM32H7_I2C */ diff --git a/boards/arm/stm32h7/nucleo-h753zi/src/stm32_lsm303agr.c b/boards/arm/stm32h7/nucleo-h753zi/src/stm32_lsm303agr.c new file mode 100644 index 0000000000000..ba0133163bd85 --- /dev/null +++ b/boards/arm/stm32h7/nucleo-h753zi/src/stm32_lsm303agr.c @@ -0,0 +1,85 @@ +/**************************************************************************** + * boards/arm/stm32h7/nucleo-h753zi/src/stm32_lsm303agr.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include +#include + +#include +#include "stm32.h" +#include "nucleo-h753zi.h" +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef CONFIG_STM32H7_I2C1 +# error "LSM303AGR driver requires CONFIG_STM32H7_I2C1 to be enabled" +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_lsm303agr_initialize + * + * Description: + * Initialize I2C-based LSM303AGR. + * + ****************************************************************************/ + +int stm32_lsm303agr_initialize(char *devpath) +{ + struct i2c_master_s *i2c; + int ret = OK; + + sninfo("INFO: Initializing LMS303AGR sensor over I2C\n"); + +#if defined(CONFIG_STM32H7_I2C1) + i2c = stm32_i2cbus_initialize(1); + if (i2c == NULL) + { + return -ENODEV; + } + + ret = lsm303agr_sensor_register("/dev/lsm303agr0", i2c, + LSM303AGRMAGNETO_ADDR); + if (ret < 0) + { + snerr("ERROR: Failed to initialize LMS303AGR magneto driver %s\n", + devpath); + return -ENODEV; + } + + sninfo("INFO: LMS303AGR sensor has been initialized successfully\n"); +#endif + + return ret; +} diff --git a/boards/arm/stm32h7/nucleo-h753zi/src/stm32_lsm6dsl.c b/boards/arm/stm32h7/nucleo-h753zi/src/stm32_lsm6dsl.c new file mode 100644 index 0000000000000..18440d3b3fc8e --- /dev/null +++ b/boards/arm/stm32h7/nucleo-h753zi/src/stm32_lsm6dsl.c @@ -0,0 +1,91 @@ +/**************************************************************************** + * boards/arm/stm32h7/nucleo-h753zi/src/stm32_lsm6dsl.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include +#include + +#include +#include "stm32.h" +#include "nucleo-h753zi.h" +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef CONFIG_STM32H7_I2C1 +# error "LSM6DSL driver requires CONFIG_STM32H7_I2C1 to be enabled" +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_lsm6dsl_initialize + * + * Description: + * Initialize I2C-based LSM6DSL. + * + ****************************************************************************/ + +int stm32_lsm6dsl_initialize(char *devpath) +{ + struct i2c_master_s *i2c; + int ret = OK; + + sninfo("Initializing LMS6DSL!\n"); + + /* Configure the GPIO interrupt */ + + stm32_configgpio(GPIO_LPS22HB_INT1); + +#if defined(CONFIG_STM32H7_I2C1) + i2c = stm32_i2cbus_initialize(1); + if (i2c == NULL) + { + return -ENODEV; + } + + sninfo("INFO: Initializing LMS6DSL accelero-gyro sensor over I2C%d\n", + ret); + + ret = lsm6dsl_sensor_register(devpath, i2c, LSM6DSLACCEL_ADDR1); + if (ret < 0) + { + snerr("ERROR: Failed to initialize LMS6DSL accelero-gyro driver %s\n", + devpath); + return -ENODEV; + } + + sninfo("INFO: LMS6DSL sensor has been initialized successfully\n"); +#endif + + return ret; +} diff --git a/boards/arm/stm32h7/nucleo-h753zi/src/stm32_lsm9ds1.c b/boards/arm/stm32h7/nucleo-h753zi/src/stm32_lsm9ds1.c new file mode 100644 index 0000000000000..c8d8b467b6a88 --- /dev/null +++ b/boards/arm/stm32h7/nucleo-h753zi/src/stm32_lsm9ds1.c @@ -0,0 +1,107 @@ +/**************************************************************************** + * boards/arm/stm32h7/nucleo-h753zi/src/stm32_lsm9ds1.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include +#include + +#include +#include "stm32.h" +#include "nucleo-h753zi.h" +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef CONFIG_STM32H7_I2C1 +# error "LSM9DS1 driver requires CONFIG_STM32H7_I2C1 to be enabled" +#endif + +#define LSM9DS1MAG_DEVPATH "/dev/lsm9ds1mag0" +#define LSM9DS1ACC_DEVPATH "/dev/lsm9ds1acc0" +#define LSM9DS1GYR_DEVPATH "/dev/lsm9ds1gyr0" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_lsm9ds1_initialize + * + * Description: + * Initialize I2C-based LSM9DS1. + * + ****************************************************************************/ + +int stm32_lsm9ds1_initialize(void) +{ + struct i2c_master_s *i2c; + int ret = OK; + + sninfo("Initializing LMS9DS1!\n"); + +#if defined(CONFIG_STM32H7_I2C1) + i2c = stm32_i2cbus_initialize(LMS9DS1_I2CBUS); + if (i2c == NULL) + { + return -ENODEV; + } + + sninfo("INFO: Initializing LMS9DS1 9DoF sensor over I2C%d\n", + LMS9DS1_I2CBUS); + + ret = lsm9ds1mag_register(LSM9DS1MAG_DEVPATH, i2c, LSM9DS1MAG_ADDR1); + if (ret < 0) + { + snerr("ERROR: Failed to initialize LMS9DS1 mag driver %s\n", + LSM9DS1MAG_DEVPATH); + return -ENODEV; + } + + ret = lsm9ds1gyro_register(LSM9DS1GYR_DEVPATH, i2c, LSM9DS1GYRO_ADDR1); + if (ret < 0) + { + snerr("ERROR: Failed to initialize LMS9DS1 gyro driver %s\n", + LSM9DS1MAG_DEVPATH); + return -ENODEV; + } + + ret = lsm9ds1accel_register(LSM9DS1ACC_DEVPATH, i2c, LSM9DS1ACCEL_ADDR1); + if (ret < 0) + { + snerr("ERROR: Failed to initialize LMS9DS1 accel driver %s\n", + LSM9DS1MAG_DEVPATH); + return -ENODEV; + } + + sninfo("INFO: LMS9DS1 sensor has been initialized successfully\n"); +#endif + + return ret; +} diff --git a/boards/arm/stm32h7/nucleo-h753zi/src/stm32_mfrc522.c b/boards/arm/stm32h7/nucleo-h753zi/src/stm32_mfrc522.c new file mode 100644 index 0000000000000..89897421849e2 --- /dev/null +++ b/boards/arm/stm32h7/nucleo-h753zi/src/stm32_mfrc522.c @@ -0,0 +1,270 @@ +/**************************************************************************** + * boards/arm/stm32h7/nucleo-h753zi/src/stm32_mfrc522.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +#include "nucleo-h753zi.h" +#include "stm32_spi.h" + +#if defined(CONFIG_SPI) && defined(CONFIG_CL_MFRC522) && \ + defined(CONFIG_NUCLEO_H753ZI_MFRC522_ENABLE) + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Determine which SPI port to use based on Kconfig selection */ + +#ifdef CONFIG_NUCLEO_H753ZI_MFRC522_SPI1 +# define MFRC522_SPI_PORTNO 1 +# ifndef CONFIG_STM32H7_SPI1 +# error "MFRC522 configured for SPI1 but CONFIG_STM32H7_SPI1 not enabled" +# endif +# ifndef CONFIG_NUCLEO_H753ZI_SPI1_ENABLE +# error "MFRC522 on SPI1 needs CONFIG_NUCLEO_H753ZI_SPI1_ENABLE" +# endif +#elif defined(CONFIG_NUCLEO_H753ZI_MFRC522_SPI2) +# define MFRC522_SPI_PORTNO 2 +# ifndef CONFIG_STM32H7_SPI2 +# error "MFRC522 configured for SPI2 but CONFIG_STM32H7_SPI2 not enabled" +# endif +# ifndef CONFIG_NUCLEO_H753ZI_SPI2_ENABLE +# error "MFRC522 on SPI2 needs CONFIG_NUCLEO_H753ZI_SPI2_ENABLE" +# endif +#elif defined(CONFIG_NUCLEO_H753ZI_MFRC522_SPI3) +# define MFRC522_SPI_PORTNO 3 +# ifndef CONFIG_STM32H7_SPI3 +# error "MFRC522 configured for SPI3 but CONFIG_STM32H7_SPI3 not enabled" +# endif +# ifndef CONFIG_NUCLEO_H753ZI_SPI3_ENABLE +# error "MFRC522 on SPI3 needs CONFIG_NUCLEO_H753ZI_SPI3_ENABLE" +# endif +#elif defined(CONFIG_NUCLEO_H753ZI_MFRC522_SPI4) +# define MFRC522_SPI_PORTNO 4 +# ifndef CONFIG_STM32H7_SPI4 +# error "MFRC522 configured for SPI4 but CONFIG_STM32H7_SPI4 not enabled" +# endif +# ifndef CONFIG_NUCLEO_H753ZI_SPI4_ENABLE +# error "MFRC522 on SPI4 needs CONFIG_NUCLEO_H753ZI_SPI4_ENABLE" +# endif +#elif defined(CONFIG_NUCLEO_H753ZI_MFRC522_SPI5) +# define MFRC522_SPI_PORTNO 5 +# ifndef CONFIG_STM32H7_SPI5 +# error "MFRC522 configured for SPI5 but CONFIG_STM32H7_SPI5 not enabled" +# endif +# ifndef CONFIG_NUCLEO_H753ZI_SPI5_ENABLE +# error "MFRC522 on SPI5 needs CONFIG_NUCLEO_H753ZI_SPI5_ENABLE" +# endif +#elif defined(CONFIG_NUCLEO_H753ZI_MFRC522_SPI6) +# define MFRC522_SPI_PORTNO 6 +# ifndef CONFIG_STM32H7_SPI6 +# error "MFRC522 configured for SPI6 but CONFIG_STM32H7_SPI6 not enabled" +# endif +# ifndef CONFIG_NUCLEO_H753ZI_SPI6_ENABLE +# error "MFRC522 on SPI6 needs CONFIG_NUCLEO_H753ZI_SPI6_ENABLE" +# endif +#else +# error "No SPI port selected for MFRC522" +#endif + +/* Default device path if not specified */ + +#ifndef CONFIG_NUCLEO_H753ZI_MFRC522_DEVPATH +# define CONFIG_NUCLEO_H753ZI_MFRC522_DEVPATH "/dev/rfid0" +#endif + +/* Default CS pin configuration if not specified */ + +#ifndef CONFIG_NUCLEO_H753ZI_MFRC522_CS_PIN +# define CONFIG_NUCLEO_H753ZI_MFRC522_CS_PIN "PF1" +#endif + +/* Default active level (most MFRC522 modules are active low) */ + +#ifndef CONFIG_NUCLEO_H753ZI_MFRC522_CS_ACTIVE_LOW +# define CONFIG_NUCLEO_H753ZI_MFRC522_CS_ACTIVE_LOW true +#endif + +/* Device ID calculation - must match the scheme in stm32_spi.c + * SPI1: IDs 0-7, SPI2: IDs 8-15, SPI3: IDs 16-23, etc. + */ + +#ifndef CONFIG_NUCLEO_H753ZI_MFRC522_DEVID +# if MFRC522_SPI_PORTNO == 1 +# define CONFIG_NUCLEO_H753ZI_MFRC522_DEVID 0 +# elif MFRC522_SPI_PORTNO == 2 +# define CONFIG_NUCLEO_H753ZI_MFRC522_DEVID 8 +# elif MFRC522_SPI_PORTNO == 3 +# define CONFIG_NUCLEO_H753ZI_MFRC522_DEVID 16 +# elif MFRC522_SPI_PORTNO == 4 +# define CONFIG_NUCLEO_H753ZI_MFRC522_DEVID 24 +# elif MFRC522_SPI_PORTNO == 5 +# define CONFIG_NUCLEO_H753ZI_MFRC522_DEVID 32 +# elif MFRC522_SPI_PORTNO == 6 +# define CONFIG_NUCLEO_H753ZI_MFRC522_DEVID 40 +# endif +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_mfrc522initialize + * + * Description: + * Initialize and register the MFRC522 RFID driver. + * This function uses the board-specific CS registration system. + * + * Input Parameters: + * devpath - The full path to the driver to register. E.g., "/dev/rfid0". + * If NULL, the default path from Kconfig is used. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +int stm32_mfrc522initialize(FAR const char *devpath) +{ + FAR struct spi_dev_s *spi; + FAR const char *path; + int ret; + + path = devpath ? devpath : MFRC522_DEVPATH; + + syslog(LOG_INFO, + "Initializing MFRC522 on SPI%d, device ID: %d, path: %s\n", + MFRC522_SPI_PORTNO, CONFIG_NUCLEO_H753ZI_MFRC522_DEVID, path); + + /* Register the CS device with the SPI system */ + + ret = stm32_spi_register_cs_device( + MFRC522_SPI_PORTNO, + CONFIG_NUCLEO_H753ZI_MFRC522_DEVID, + CONFIG_NUCLEO_H753ZI_MFRC522_CS_PIN, + CONFIG_NUCLEO_H753ZI_MFRC522_CS_ACTIVE_LOW); + if (ret < 0) + { + syslog(LOG_ERR, + "ERROR: Failed to register CS device for MFRC522: %d\n", ret); + return ret; + } + + /* Initialize the SPI bus */ + + spi = stm32_spibus_initialize(MFRC522_SPI_PORTNO); + if (!spi) + { + syslog(LOG_ERR, "ERROR: Failed to initialize SPI%d\n", + MFRC522_SPI_PORTNO); + + /* Cleanup: unregister the CS device */ + + stm32_spi_unregister_cs_device(MFRC522_SPI_PORTNO, + CONFIG_NUCLEO_H753ZI_MFRC522_DEVID); + return -ENODEV; + } + + /* Register the MFRC522 driver */ + + ret = mfrc522_register(path, spi); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to register MFRC522 driver: %d\n", + ret); + + /* Cleanup: unregister the CS device */ + + stm32_spi_unregister_cs_device(MFRC522_SPI_PORTNO, + CONFIG_NUCLEO_H753ZI_MFRC522_DEVID); + return ret; + } + + syslog(LOG_INFO, "MFRC522 driver registered successfully at %s\n", path); + + /* Note: The MFRC522 driver will use device ID 0 by default for SPI + * transactions. Our CS registration system will handle CS control + * based on the registered device ID. If the driver uses a different + * device ID, you may need to modify the driver or use a different + * registration approach. + */ + + return OK; +} + +/**************************************************************************** + * Name: stm32_mfrc522_get_devid + * + * Description: + * Get the device ID used by the MFRC522 for CS pin control. + * This is useful for debugging or advanced applications. + * + * Returned Value: + * Device ID used by MFRC522 + * + ****************************************************************************/ + +uint32_t stm32_mfrc522_get_devid(void) +{ + return CONFIG_NUCLEO_H753ZI_MFRC522_DEVID; +} + +/**************************************************************************** + * Name: stm32_mfrc522_cleanup + * + * Description: + * Cleanup MFRC522 resources. This function can be called during + * shutdown or error recovery. + * + * Returned Value: + * OK on success, negative errno on error + * + ****************************************************************************/ + +int stm32_mfrc522_cleanup(void) +{ + int ret; + + ret = stm32_spi_unregister_cs_device(MFRC522_SPI_PORTNO, + MFRC522_DEVICE_ID); + if (ret < 0) + { + syslog(LOG_WARNING, + "WARNING: Failed to unregister MFRC522 CS device: %d\n", ret); + } + + return ret; +} + +#endif /* CONFIG_SPI && CONFIG_CL_MFRC522 && + * CONFIG_NUCLEO_H753ZI_MFRC522_ENABLE */ diff --git a/boards/arm/stm32h7/nucleo-h753zi/src/stm32_mmcsd.c b/boards/arm/stm32h7/nucleo-h753zi/src/stm32_mmcsd.c new file mode 100644 index 0000000000000..2294ccb930cea --- /dev/null +++ b/boards/arm/stm32h7/nucleo-h753zi/src/stm32_mmcsd.c @@ -0,0 +1,90 @@ +/**************************************************************************** + * boards/arm/stm32h7/nucleo-h753zi/src/stm32_mmcsd.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include + +#include "stm32_spi.h" + +#include "nucleo-h753zi.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifdef CONFIG_DISABLE_MOUNTPOINT +# error "SD driver requires CONFIG_DISABLE_MOUNTPOINT to be disabled" +#endif + +#ifndef CONFIG_STM32H7_SPI3 +# error "MMC/SD requires SPI3 enabled" +#endif + +#define MMCSD_SPI_PORT (3) + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_mmcsd_initialize + * + * Description: + * Initialize SPI-based SD card and card detect thread. + * + ****************************************************************************/ + +int stm32_mmcsd_initialize(int minor) +{ + struct spi_dev_s *spi; + int ret; + + mcinfo("INFO: Initializing mmcsd port %d minor %d\n", + MMCSD_SPI_PORT, minor); + + spi = stm32_spibus_initialize(MMCSD_SPI_PORT); + if (spi == NULL) + { + mcerr("ERROR: Failed to initialize SPI port %d\n", MMCSD_SPI_PORT); + return -ENODEV; + } + + ret = mmcsd_spislotinitialize(minor, 0, spi); + if (ret < 0) + { + mcerr("ERROR: Failed to bind SPI port %d to SD slot %d\n", + MMCSD_SPI_PORT, minor); + return ret; + } + + mcinfo("INFO: mmcsd card has been initialized successfully\n"); + return OK; +} diff --git a/boards/arm/stm32h7/nucleo-h753zi/src/stm32_nrf24l01.c b/boards/arm/stm32h7/nucleo-h753zi/src/stm32_nrf24l01.c new file mode 100644 index 0000000000000..e4b7cbf79ee23 --- /dev/null +++ b/boards/arm/stm32h7/nucleo-h753zi/src/stm32_nrf24l01.c @@ -0,0 +1,123 @@ +/**************************************************************************** + * boards/arm/stm32h7/nucleo-h753zi/src/stm32_nrf24l01.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include "arm_internal.h" +#include "chip.h" +#include "stm32.h" +#include "nucleo-h753zi.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define NRF24L01_SPI 3 + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int nrf24l01_irq_attach(xcpt_t isr, void *arg); +static void nrf24l01_chip_enable(bool enable); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static struct nrf24l01_config_s nrf_cfg = +{ + .irqattach = nrf24l01_irq_attach, + .chipenable = nrf24l01_chip_enable, +}; + +static xcpt_t g_isr; +static void *g_arg; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static int nrf24l01_irq_attach(xcpt_t isr, void *arg) +{ + wlinfo("Attach IRQ\n"); + g_isr = isr; + g_arg = arg; + stm32_gpiosetevent(GPIO_NRF24L01_IRQ, false, true, false, g_isr, g_arg); + return OK; +} + +static void nrf24l01_chip_enable(bool enable) +{ + wlinfo("CE:%d\n", enable); + stm32_gpiowrite(GPIO_NRF24L01_CE, enable); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +int stm32_wlinitialize(void) +{ + struct spi_dev_s *spidev; + int ret = OK; + + syslog(LOG_INFO, "Register the nRF24L01 module\n"); + + /* Setup CE & IRQ line IOs */ + + stm32_configgpio(GPIO_NRF24L01_CE); + stm32_configgpio(GPIO_NRF24L01_IRQ); + + /* Init SPI bus */ + + spidev = stm32_spibus_initialize(NRF24L01_SPI); + if (!spidev) + { + wlerr("ERROR: Failed to initialize SPI %d bus\n", NRF24L01_SPI); + ret = -ENODEV; + goto errout; + } + + ret = nrf24l01_register(spidev, &nrf_cfg); + if (ret != OK) + { + wlerr("ERROR: Failed to register initialize SPI bus\n"); + goto errout; + } + +errout: + return ret; +} diff --git a/boards/arm/stm32h7/nucleo-h753zi/src/stm32_pca9635.c b/boards/arm/stm32h7/nucleo-h753zi/src/stm32_pca9635.c new file mode 100644 index 0000000000000..c1ce7206644aa --- /dev/null +++ b/boards/arm/stm32h7/nucleo-h753zi/src/stm32_pca9635.c @@ -0,0 +1,84 @@ +/**************************************************************************** + * boards/arm/stm32h7/nucleo-h753zi/src/stm32_pca9635.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include + +#include + +#include "stm32.h" +#include "nucleo-h753zi.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_pca9635_initialize + * + * Description: + * This function is called by board initialization logic to configure the + * LED PWM chip. This function will register the driver as /dev/leddrv0. + * + * Input Parameters: + * None + * + * Returned Value: + * Zero is returned on success. Otherwise, a negated errno value is + * returned to indicate the nature of the failure. + * + ****************************************************************************/ + +int stm32_pca9635_initialize(void) +{ + struct i2c_master_s *i2c; + int ret; + + /* Get the I2C driver that interfaces with the pca9635 */ + + i2c = stm32_i2cbus_initialize(PCA9635_I2CBUS); + if (!i2c) + { + i2cerr("ERROR: Failed to initialize I2C%d\n", PCA9635_I2CBUS); + return -1; + } + + ret = pca9635pw_register("/dev/leddrv0", i2c, PCA9635_I2CADDR); + if (ret < 0) + { + snerr("ERROR: Failed to register PCA9635 driver: %d\n", ret); + return ret; + } + + return OK; +} diff --git a/boards/arm/stm32h7/nucleo-h753zi/src/stm32_progmem.c b/boards/arm/stm32h7/nucleo-h753zi/src/stm32_progmem.c new file mode 100644 index 0000000000000..bf434459f5b76 --- /dev/null +++ b/boards/arm/stm32h7/nucleo-h753zi/src/stm32_progmem.c @@ -0,0 +1,254 @@ +/**************************************************************************** + * boards/arm/stm32h7/nucleo-h753zi/src/stm32_progmem.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include "nucleo-h753zi.h" +#include + +#ifdef HAVE_PROGMEM_CHARDEV + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define PARTITION_LABEL_LEN 16 + +/* Configuration ************************************************************/ + +/* Make sure that support for MTD partitions is enabled */ +#ifdef CONFIG_MTD + +#ifndef CONFIG_MTD_PARTITION +# error "CONFIG_MTD_PARTITION is required" +#endif + +#endif +/**************************************************************************** + * Private Types + ****************************************************************************/ + +#if defined(CONFIG_STM32_PROGMEM_OTA_PARTITION) + +struct ota_partition_s +{ + uint32_t offset; /* Partition offset from the beginning of MTD */ + uint32_t size; /* Partition size in bytes */ + const char *devpath; /* Partition device path */ +}; + +#endif + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +#if defined(CONFIG_STM32_PROGMEM_OTA_PARTITION) +static struct mtd_dev_s *progmem_alloc_mtdpart(uint32_t mtd_offset, + uint32_t mtd_size); +static int init_ota_partitions(void); +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static struct mtd_dev_s *g_progmem_mtd; + +#if defined(CONFIG_STM32_PROGMEM_OTA_PARTITION) +static const struct ota_partition_s g_ota_partition_table[] = +{ + { + .offset = CONFIG_STM32_OTA_PRIMARY_SLOT_OFFSET, + .size = CONFIG_STM32_OTA_SLOT_SIZE, + .devpath = CONFIG_STM32_OTA_PRIMARY_SLOT_DEVPATH + }, + { + .offset = CONFIG_STM32_OTA_SECONDARY_SLOT_OFFSET, + .size = CONFIG_STM32_OTA_SLOT_SIZE, + .devpath = CONFIG_STM32_OTA_SECONDARY_SLOT_DEVPATH + }, + { + .offset = CONFIG_STM32_OTA_SCRATCH_OFFSET, + .size = CONFIG_STM32_OTA_SCRATCH_SIZE, + .devpath = CONFIG_STM32_OTA_SCRATCH_DEVPATH + } +}; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +#if defined(CONFIG_STM32_PROGMEM_OTA_PARTITION) + +/**************************************************************************** + * Name: sam_progmem_alloc_mtdpart + * + * Description: + * Allocate an MTD partition from FLASH. + * + * Input Parameters: + * mtd_offset - MTD Partition offset from the base address in FLASH. + * mtd_size - Size for the MTD partition. + * + * Returned Value: + * MTD partition data pointer on success, NULL on failure. + * + ****************************************************************************/ + +static struct mtd_dev_s *progmem_alloc_mtdpart(uint32_t mtd_offset, + uint32_t mtd_size) +{ + uint32_t blocks; + ssize_t startblock; + + ASSERT((mtd_offset % up_progmem_pagesize(0)) == 0); + ASSERT((mtd_size % up_progmem_pagesize(0)) == 0); + + finfo("\tMTD offset = 0x%"PRIx32"\n", mtd_offset); + finfo("\tMTD size = 0x%"PRIx32"\n", mtd_size); + + startblock = up_progmem_getpage(mtd_offset + up_progmem_getaddress(0)); + if (startblock < 0) + { + return NULL; + } + + blocks = mtd_size / up_progmem_pagesize(0); + + return mtd_partition(g_progmem_mtd, startblock, blocks); +} + +/**************************************************************************** + * Name: init_ota_partitions + * + * Description: + * Initialize partitions that are dedicated to firmware OTA update. + * + * Input Parameters: + * None. + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int init_ota_partitions(void) +{ + int i; + struct mtd_dev_s *mtd; + int ret = 0; + char path[PARTITION_LABEL_LEN + 1]; + + for (i = 0; i < nitems(g_ota_partition_table); ++i) + { + const struct ota_partition_s *part = &g_ota_partition_table[i]; + mtd = progmem_alloc_mtdpart(part->offset, part->size); + + strlcpy(path, (char *)part->devpath, PARTITION_LABEL_LEN); + + finfo("INFO: [label]: %s\n", path); + finfo("INFO: [offset]: 0x%08" PRIx32 "\n", part->offset); + finfo("INFO: [size]: 0x%08" PRIx32 "\n", part->size); + + if (!mtd) + { + ferr("ERROR: Failed to create MTD partition\n"); + ret = -1; + } + + ret = register_mtddriver(path, mtd, 0777, NULL); + if (ret < 0) + { + ferr("ERROR: Failed to register MTD @ %s\n", path); + ret = -1; + } + } + + return ret; +} +#endif /* CONFIG_STM32_PROGMEM_OTA_PARTITION */ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_progmem_init + * + * Initialize Progmem partition. Read partition information, and use + * these data for creating MTD. + * + * Input Parameters: + * None + * + * Returned Value: + * 0 if success or a negative value if fail. + * + ****************************************************************************/ + +int stm32_progmem_init(void) +{ + int ret = 0; + + g_progmem_mtd = progmem_initialize(); + if (g_progmem_mtd == NULL) + { + ferr("ERROR: Failed to get progmem flash MTD\n"); + ret = -EIO; + } + +#ifdef CONFIG_STM32_PROGMEM_OTA_PARTITION + ret = init_ota_partitions(); + if (ret < 0) + { + ferr("ERROR: Failed to create OTA partition from MTD\n"); + ret = -EIO; + } +#endif + + return ret; +} + +#endif /* HAVE_PROGMEM_CHARDEV */ diff --git a/boards/arm/stm32h7/nucleo-h753zi/src/stm32_pwm.c b/boards/arm/stm32h7/nucleo-h753zi/src/stm32_pwm.c new file mode 100644 index 0000000000000..7489d9400f78d --- /dev/null +++ b/boards/arm/stm32h7/nucleo-h753zi/src/stm32_pwm.c @@ -0,0 +1,110 @@ +/**************************************************************************** + * boards/arm/stm32h7/nucleo-h753zi/src/stm32_pwm.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include + +#include "chip.h" +#include "arm_internal.h" +#include "stm32_pwm.h" +#include "nucleo-h753zi.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Configuration ************************************************************/ + +#define HAVE_PWM 1 + +#ifndef CONFIG_PWM +# undef HAVE_PWM +#endif + +#ifndef CONFIG_STM32H7_TIM1 +# undef HAVE_PWM +#endif + +#ifndef CONFIG_STM32H7_TIM1_PWM +# undef HAVE_PWM +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_pwm_setup + * + * Description: + * Initialize PWM and register the PWM device. + * + ****************************************************************************/ + +int stm32_pwm_setup(void) +{ +#ifdef HAVE_PWM + static bool initialized = false; + struct pwm_lowerhalf_s *pwm; + int ret; + + /* Have we already initialized? */ + + if (!initialized) + { + /* Get an instance of the PWM interface */ + + pwm = stm32_pwminitialize(NUCLEOH753ZI_PWMTIMER); + if (!pwm) + { + tmrerr("ERROR: Failed to get the STM32 PWM lower half\n"); + return -ENODEV; + } + + /* Register the PWM driver at "/dev/pwm0" */ + + ret = pwm_register("/dev/pwm0", pwm); + if (ret < 0) + { + tmrerr("ERROR: pwm_register failed: %d\n", ret); + return ret; + } + + /* Now we are initialized */ + + initialized = true; + } + + return OK; +#else + return -ENODEV; +#endif +} diff --git a/boards/arm/stm32h7/nucleo-h753zi/src/stm32_reset.c b/boards/arm/stm32h7/nucleo-h753zi/src/stm32_reset.c new file mode 100644 index 0000000000000..5eb902c30fc6d --- /dev/null +++ b/boards/arm/stm32h7/nucleo-h753zi/src/stm32_reset.c @@ -0,0 +1,64 @@ +/**************************************************************************** + * boards/arm/stm32h7/nucleo-h753zi/src/stm32_reset.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#ifdef CONFIG_BOARDCTL_RESET + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_reset + * + * Description: + * Reset board. Support for this function is required by board-level + * logic if CONFIG_BOARDCTL_RESET is selected. + * + * Input Parameters: + * status - Status information provided with the reset event. This + * meaning of this status information is board-specific. If not + * used by a board, the value zero may be provided in calls to + * board_reset(). + * + * Returned Value: + * If this function returns, then it was not possible to power-off the + * board due to some constraints. The return value int this case is a + * board-specific reason for the failure to shutdown. + * + ****************************************************************************/ + +int board_reset(int status) +{ + up_systemreset(); + return 0; +} + +#endif /* CONFIG_BOARDCTL_RESET */ diff --git a/boards/arm/stm32h7/nucleo-h753zi/src/stm32_romfs.h b/boards/arm/stm32h7/nucleo-h753zi/src/stm32_romfs.h new file mode 100644 index 0000000000000..c0a6ebf6e3469 --- /dev/null +++ b/boards/arm/stm32h7/nucleo-h753zi/src/stm32_romfs.h @@ -0,0 +1,63 @@ +/**************************************************************************** + * boards/arm/stm32h7/nucleo-h753zi/src/stm32_romfs.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __BOARDS_ARM_STM32H7_NUCLEO_H753ZI_SRC_STM32_ROMFS_H +#define __BOARDS_ARM_STM32H7_NUCLEO_H753ZI_SRC_STM32_ROMFS_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#ifdef CONFIG_STM32_ROMFS + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define ROMFS_SECTOR_SIZE 64 + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_romfs_initialize + * + * Description: + * Registers built-in ROMFS image as block device and mounts it. + * + * Returned Value: + * Zero (OK) on success, a negated errno value on error. + * + * Assumptions/Limitations: + * Memory addresses [romfs_data_begin .. romfs_data_end) should contain + * ROMFS volume data, as included in the assembly snippet above (l. 84). + * + ****************************************************************************/ + +int stm32_romfs_initialize(void); + +#endif /* CONFIG_STM32_ROMFS */ + +#endif /* __BOARDS_ARM_STM32H7_NUCLEO_H753ZI_SRC_STM32_ROMFS_H */ diff --git a/boards/arm/stm32h7/nucleo-h753zi/src/stm32_romfs_initialize.c b/boards/arm/stm32h7/nucleo-h753zi/src/stm32_romfs_initialize.c new file mode 100644 index 0000000000000..6496a7707d8ef --- /dev/null +++ b/boards/arm/stm32h7/nucleo-h753zi/src/stm32_romfs_initialize.c @@ -0,0 +1,139 @@ +/**************************************************************************** + * boards/arm/stm32h7/nucleo-h753zi/src/stm32_romfs_initialize.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include "stm32_romfs.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef CONFIG_STM32_ROMFS +# error "CONFIG_STM32_ROMFS must be defined" +#else + +#ifndef CONFIG_STM32_ROMFS_IMAGEFILE +# error "CONFIG_STM32_ROMFS_IMAGEFILE must be defined" +#endif + +#ifndef CONFIG_STM32_ROMFS_DEV_MINOR +# error "CONFIG_STM32_ROMFS_DEV_MINOR must be defined" +#endif + +#ifndef CONFIG_STM32_ROMFS_MOUNTPOINT +# error "CONFIG_STM32_ROMFS_MOUNTPOINT must be defined" +#endif + +#define NSECTORS(size) (((size) + ROMFS_SECTOR_SIZE - 1)/ROMFS_SECTOR_SIZE) + +#define STR2(m) #m +#define STR(m) STR2(m) + +#define MKMOUNT_DEVNAME(m) "/dev/ram" STR(m) +#define MOUNT_DEVNAME MKMOUNT_DEVNAME(CONFIG_STM32_ROMFS_DEV_MINOR) + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +__asm__ ( + " .section .rodata \n" + " .balign 16 \n" + " .globl romfs_data_begin \n" + "romfs_data_begin: \n" + " .incbin " STR(CONFIG_STM32_ROMFS_IMAGEFILE)"\n" + " .balign " STR(ROMFS_SECTOR_SIZE) "\n" + " .globl romfs_data_end \n" + "romfs_data_end: \n" + ); + +extern const uint8_t romfs_data_begin[]; +extern const uint8_t romfs_data_end[]; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_romfs_initialize + * + * Description: + * Registers the aboveincluded binary file as block device. + * Then mounts the block device as ROMFS filesystems. + * + * Returned Value: + * Zero (OK) on success, a negated errno value on error. + * + * Assumptions/Limitations: + * Memory addresses [romfs_data_begin .. romfs_data_end) should contain + * ROMFS volume data, as included in the assembly snippet above (l. 84). + * + ****************************************************************************/ + +int stm32_romfs_initialize(void) +{ + size_t romfs_data_len; + int ret; + + /* Create a ROM disk for the /etc filesystem */ + + romfs_data_len = romfs_data_end - romfs_data_begin; + + ret = romdisk_register(CONFIG_STM32_ROMFS_DEV_MINOR, romfs_data_begin, + NSECTORS(romfs_data_len), ROMFS_SECTOR_SIZE); + if (ret < 0) + { + ferr("ERROR: romdisk_register failed: %d\n", -ret); + return ret; + } + + /* Mount the file system */ + + finfo("Mounting ROMFS filesystem at target=%s with source=%s\n", + CONFIG_STM32_ROMFS_MOUNTPOINT, MOUNT_DEVNAME); + + ret = nx_mount(MOUNT_DEVNAME, CONFIG_STM32_ROMFS_MOUNTPOINT, + "romfs", MS_RDONLY, NULL); + if (ret < 0) + { + ferr("ERROR: nx_mount(%s,%s,romfs) failed: %d\n", + MOUNT_DEVNAME, CONFIG_STM32_ROMFS_MOUNTPOINT, ret); + return ret; + } + + return OK; +} + +#endif /* CONFIG_STM32_ROMFS */ diff --git a/boards/arm/stm32h7/nucleo-h753zi/src/stm32_spi.c b/boards/arm/stm32h7/nucleo-h753zi/src/stm32_spi.c new file mode 100644 index 0000000000000..843f9105b1a12 --- /dev/null +++ b/boards/arm/stm32h7/nucleo-h753zi/src/stm32_spi.c @@ -0,0 +1,1037 @@ +/**************************************************************************** + * boards/arm/stm32h7/nucleo-h753zi/src/stm32_spi.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "stm32_gpio.h" +#include "stm32_spi.h" +#include "nucleo-h753zi.h" +#include + +#ifdef CONFIG_STM32H7_SPI + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define MAX_CS_DEVICES_PER_SPI 16 +#define INVALID_CS_PIN 0 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* CS pin registration structure */ + +struct spi_cs_device_s +{ + uint32_t gpio_config; /* GPIO configuration for CS pin */ + bool active_low; /* true = active low, false = active high */ + bool in_use; /* true = slot occupied */ +}; + +/* DC pin registration structure */ + +#ifdef CONFIG_SPI_CMDDATA +struct spi_dc_device_s +{ + uint32_t gpio_config; /* GPIO configuration for DC pin */ + bool in_use; /* true = slot occupied */ +}; +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* CS device registrations for each SPI bus */ + +#ifdef CONFIG_STM32H7_SPI1 +static struct spi_cs_device_s g_spi1_cs_devices[MAX_CS_DEVICES_PER_SPI]; +#ifdef CONFIG_SPI_CMDDATA +static struct spi_dc_device_s g_spi1_dc_devices[MAX_CS_DEVICES_PER_SPI]; +#endif +#endif + +#ifdef CONFIG_STM32H7_SPI2 +static struct spi_cs_device_s g_spi2_cs_devices[MAX_CS_DEVICES_PER_SPI]; +#ifdef CONFIG_SPI_CMDDATA +static struct spi_dc_device_s g_spi2_dc_devices[MAX_CS_DEVICES_PER_SPI]; +#endif +#endif + +#ifdef CONFIG_STM32H7_SPI3 +static struct spi_cs_device_s g_spi3_cs_devices[MAX_CS_DEVICES_PER_SPI]; +#ifdef CONFIG_SPI_CMDDATA +static struct spi_dc_device_s g_spi3_dc_devices[MAX_CS_DEVICES_PER_SPI]; +#endif +#endif + +#ifdef CONFIG_STM32H7_SPI4 +static struct spi_cs_device_s g_spi4_cs_devices[MAX_CS_DEVICES_PER_SPI]; +#ifdef CONFIG_SPI_CMDDATA +static struct spi_dc_device_s g_spi4_dc_devices[MAX_CS_DEVICES_PER_SPI]; +#endif +#endif + +#ifdef CONFIG_STM32H7_SPI5 +static struct spi_cs_device_s g_spi5_cs_devices[MAX_CS_DEVICES_PER_SPI]; +#ifdef CONFIG_SPI_CMDDATA +static struct spi_dc_device_s g_spi5_dc_devices[MAX_CS_DEVICES_PER_SPI]; +#endif +#endif + +#ifdef CONFIG_STM32H7_SPI6 +static struct spi_cs_device_s g_spi6_cs_devices[MAX_CS_DEVICES_PER_SPI]; +#ifdef CONFIG_SPI_CMDDATA +static struct spi_dc_device_s g_spi6_dc_devices[MAX_CS_DEVICES_PER_SPI]; +#endif +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: parse_gpio_pin + * + * Description: + * Parse GPIO pin string like "PA0" into STM32 GPIO configuration. + * + * Input Parameters: + * pin_str - GPIO pin string (e.g., "PA0", "PF15", "PC13") + * error - Pointer to error code storage + * + * Returned Value: + * STM32 GPIO configuration value on success, 0 on error + * + ****************************************************************************/ + +static uint32_t parse_gpio_pin(FAR const char *pin_str, FAR int *error) +{ + size_t len; + char port; + FAR const char *pin_num_str; + FAR char *endptr; + long pin_num; + uint32_t port_base; + uint32_t gpio_pin; + + *error = 0; + + if (pin_str == NULL) + { + *error = -EINVAL; + return 0; + } + + /* Remove leading/trailing spaces */ + + while (*pin_str == ' ' || *pin_str == '\t') + { + pin_str++; + } + + len = strlen(pin_str); + if (len < 3 || len > 4) + { + *error = -EINVAL; + return 0; + } + + if (pin_str[0] != 'P') + { + *error = -EINVAL; + return 0; + } + + port = pin_str[1]; + if (port < 'A' || port > 'H') + { + *error = -EINVAL; + return 0; + } + + pin_num_str = &pin_str[2]; + pin_num = strtol(pin_num_str, &endptr, 10); + if (*endptr != '\0' || pin_num < 0 || pin_num > 15) + { + *error = -EINVAL; + return 0; + } + + /* Map port letter to STM32 port base */ + + switch (port) + { + case 'A': + port_base = GPIO_PORTA; break; + case 'B': + port_base = GPIO_PORTB; break; + case 'C': + port_base = GPIO_PORTC; break; + case 'D': + port_base = GPIO_PORTD; break; + case 'E': + port_base = GPIO_PORTE; break; + case 'F': + port_base = GPIO_PORTF; break; + case 'G': + port_base = GPIO_PORTG; break; + case 'H': + port_base = GPIO_PORTH; break; + default: + *error = -EINVAL; + return 0; + } + + /* Use correct STM32 GPIO pin macros */ + + switch (pin_num) + { + case 0: + gpio_pin = GPIO_PIN0; break; + case 1: + gpio_pin = GPIO_PIN1; break; + case 2: + gpio_pin = GPIO_PIN2; break; + case 3: + gpio_pin = GPIO_PIN3; break; + case 4: + gpio_pin = GPIO_PIN4; break; + case 5: + gpio_pin = GPIO_PIN5; break; + case 6: + gpio_pin = GPIO_PIN6; break; + case 7: + gpio_pin = GPIO_PIN7; break; + case 8: + gpio_pin = GPIO_PIN8; break; + case 9: + gpio_pin = GPIO_PIN9; break; + case 10: + gpio_pin = GPIO_PIN10; break; + case 11: + gpio_pin = GPIO_PIN11; break; + case 12: + gpio_pin = GPIO_PIN12; break; + case 13: + gpio_pin = GPIO_PIN13; break; + case 14: + gpio_pin = GPIO_PIN14; break; + case 15: + gpio_pin = GPIO_PIN15; break; + default: + *error = -EINVAL; + return 0; + } + + return (GPIO_OUTPUT | GPIO_OUTPUT_SET | GPIO_SPEED_50MHz | GPIO_FLOAT | + port_base | gpio_pin); +} + +/**************************************************************************** + * Name: get_cs_devices_array + * + * Description: + * Get CS devices array for a specific SPI bus. + * + * Input Parameters: + * spi_bus - SPI bus number (1-6) + * + * Returned Value: + * Pointer to CS devices array, NULL if invalid bus + * + ****************************************************************************/ + +static struct spi_cs_device_s *get_cs_devices_array(int spi_bus) +{ + switch (spi_bus) + { +#ifdef CONFIG_STM32H7_SPI1 + case 1: + return g_spi1_cs_devices; +#endif +#ifdef CONFIG_STM32H7_SPI2 + case 2: + return g_spi2_cs_devices; +#endif +#ifdef CONFIG_STM32H7_SPI3 + case 3: + return g_spi3_cs_devices; +#endif +#ifdef CONFIG_STM32H7_SPI4 + case 4: + return g_spi4_cs_devices; +#endif +#ifdef CONFIG_STM32H7_SPI5 + case 5: + return g_spi5_cs_devices; +#endif +#ifdef CONFIG_STM32H7_SPI6 + case 6: + return g_spi6_cs_devices; +#endif + default: + return NULL; + } +} + +/**************************************************************************** + * Name: get_dc_devices_array + * + * Description: + * Get DC devices array for a specific SPI bus. + * + * Input Parameters: + * spi_bus - SPI bus number (1-6) + * + * Returned Value: + * Pointer to DC devices array, NULL if invalid bus + * + ****************************************************************************/ + +#ifdef CONFIG_SPI_CMDDATA +static struct spi_dc_device_s *get_dc_devices_array(int spi_bus) +{ + switch (spi_bus) + { +#ifdef CONFIG_STM32H7_SPI1 + case 1: + return g_spi1_dc_devices; +#endif +#ifdef CONFIG_STM32H7_SPI2 + case 2: + return g_spi2_dc_devices; +#endif +#ifdef CONFIG_STM32H7_SPI3 + case 3: + return g_spi3_dc_devices; +#endif +#ifdef CONFIG_STM32H7_SPI4 + case 4: + return g_spi4_dc_devices; +#endif +#ifdef CONFIG_STM32H7_SPI5 + case 5: + return g_spi5_dc_devices; +#endif +#ifdef CONFIG_STM32H7_SPI6 + case 6: + return g_spi6_dc_devices; +#endif + default: + return NULL; + } +} +#endif + +/**************************************************************************** + * Name: spi_cs_control + * + * Description: + * Control SPI chip select pin based on registered device. + * + * Input Parameters: + * spi_bus - SPI bus number (1-6) + * devid - Device ID within the bus + * selected - Select (true) or deselect (false) + * + ****************************************************************************/ + +static void spi_cs_control(int spi_bus, uint32_t devid, bool selected) +{ + struct spi_cs_device_s *cs_devices; + struct spi_cs_device_s *device; + bool pin_state; + uint32_t actual_devid = devid; + + cs_devices = get_cs_devices_array(spi_bus); + if (cs_devices == NULL) + { + spierr("ERROR: Invalid SPI bus %d\n", spi_bus); + return; + } + + /* Handle SPIDEV_* types */ + + if ((devid & 0xffff0000) != 0) + { + actual_devid = (devid & 0x0000ffff); + spiinfo("Detected SPIDEV type 0x%04lX, using index %lu for SPI%d\n", + (unsigned long)(devid >> 16), (unsigned long)actual_devid, + spi_bus); + } + else if (devid >= MAX_CS_DEVICES_PER_SPI) + { + spiwarn("WARNING: Device ID %lu >= maximum %d for SPI%d, " + "trying fallback to ID 0\n", + (unsigned long)devid, MAX_CS_DEVICES_PER_SPI, spi_bus); + + if (cs_devices[0].in_use) + { + actual_devid = 0; + spiinfo("SUCCESS: Using fallback device ID 0 for invalid ID %lu\n", + (unsigned long)devid); + } + else + { + spierr("ERROR: Device ID %lu >= maximum %d and no fallback " + "available for SPI%d\n", + (unsigned long)devid, MAX_CS_DEVICES_PER_SPI, spi_bus); + return; + } + } + + device = &cs_devices[actual_devid]; + if (!device->in_use) + { + spierr("ERROR: Device ID %lu (actual %lu) not registered for SPI%d\n", + (unsigned long)devid, (unsigned long)actual_devid, spi_bus); + return; + } + + /* Calculate pin state */ + + if (device->active_low) + { + pin_state = !selected; + } + else + { + pin_state = selected; + } + + stm32_gpiowrite(device->gpio_config, pin_state); + + spiinfo("SPI%d CS%lu->%lu: %s (pin %s)\n", + spi_bus, (unsigned long)devid, (unsigned long)actual_devid, + selected ? "SELECT" : "DESELECT", + pin_state ? "HIGH" : "LOW"); +} + +/**************************************************************************** + * Name: spi_dc_control + * + * Description: + * Control SPI DC (Data/Command) pin for registered device. + * + * Input Parameters: + * spi_bus - SPI bus number (1-6) + * devid - Device ID within the bus + * cmd - true = command mode, false = data mode + * + ****************************************************************************/ + +#ifdef CONFIG_SPI_CMDDATA +static void spi_dc_control(int spi_bus, uint32_t devid, bool cmd) +{ + struct spi_dc_device_s *dc_devices; + struct spi_dc_device_s *device; + uint32_t actual_devid = devid; + + dc_devices = get_dc_devices_array(spi_bus); + if (dc_devices == NULL) + { + spierr("ERROR: Invalid SPI bus %d for DC control\n", spi_bus); + return; + } + + /* Handle SPIDEV_* types */ + + if ((devid & 0xffff0000) != 0) + { + actual_devid = (devid & 0x0000ffff); + } + else if (devid >= MAX_CS_DEVICES_PER_SPI) + { + spierr("ERROR: Device ID %lu >= maximum %d for DC control on SPI%d\n", + (unsigned long)devid, MAX_CS_DEVICES_PER_SPI, spi_bus); + return; + } + + device = &dc_devices[actual_devid]; + if (!device->in_use) + { + spierr("ERROR: DC pin not registered for SPI%d device %lu\n", + spi_bus, (unsigned long)actual_devid); + return; + } + + /* Set DC pin: LOW for command, HIGH for data + * This is the standard convention for SPI displays + */ + + stm32_gpiowrite(device->gpio_config, !cmd); + + /* DEBUG SESSION + * spiinfo("SPI%d DC%lu: %s (pin %s)\n", + * spi_bus, (unsigned long)actual_devid, + * cmd ? "COMMAND" : "DATA", + * cmd ? "LOW" : "HIGH"); + * + * syslog(LOG_INFO, "SPI%d DC%lu: %s (pin %s) [GPIO=0x%08lx]\n", + * spi_bus, (unsigned long)actual_devid, + * cmd ? "COMMAND" : "DATA", + * cmd ? "LOW" : "HIGH", + * (unsigned long)device->gpio_config); + */ +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_spi_initialize + * + * Description: + * Initialize SPI interfaces. + * + * Returned Value: + * OK on success, negative errno on error + * + ****************************************************************************/ + +int stm32_spi_initialize(void) +{ + spiinfo("stm32_spi_initialize: Initializing SPI interfaces\n"); + +#ifdef CONFIG_STM32H7_SPI1 + memset(g_spi1_cs_devices, 0, sizeof(g_spi1_cs_devices)); +#ifdef CONFIG_SPI_CMDDATA + memset(g_spi1_dc_devices, 0, sizeof(g_spi1_dc_devices)); +#endif + spiinfo("SPI1 CS/DC registry initialized\n"); +#endif + +#ifdef CONFIG_STM32H7_SPI2 + memset(g_spi2_cs_devices, 0, sizeof(g_spi2_cs_devices)); +#ifdef CONFIG_SPI_CMDDATA + memset(g_spi2_dc_devices, 0, sizeof(g_spi2_dc_devices)); +#endif + spiinfo("SPI2 CS/DC registry initialized\n"); +#endif + +#ifdef CONFIG_STM32H7_SPI3 + memset(g_spi3_cs_devices, 0, sizeof(g_spi3_cs_devices)); +#ifdef CONFIG_SPI_CMDDATA + memset(g_spi3_dc_devices, 0, sizeof(g_spi3_dc_devices)); +#endif + spiinfo("SPI3 CS/DC registry initialized\n"); +#endif + +#ifdef CONFIG_STM32H7_SPI4 + memset(g_spi4_cs_devices, 0, sizeof(g_spi4_cs_devices)); +#ifdef CONFIG_SPI_CMDDATA + memset(g_spi4_dc_devices, 0, sizeof(g_spi4_dc_devices)); +#endif + spiinfo("SPI4 CS/DC registry initialized\n"); +#endif + +#ifdef CONFIG_STM32H7_SPI5 + memset(g_spi5_cs_devices, 0, sizeof(g_spi5_cs_devices)); +#ifdef CONFIG_SPI_CMDDATA + memset(g_spi5_dc_devices, 0, sizeof(g_spi5_dc_devices)); +#endif + spiinfo("SPI5 CS/DC registry initialized\n"); +#endif + +#ifdef CONFIG_STM32H7_SPI6 + memset(g_spi6_cs_devices, 0, sizeof(g_spi6_cs_devices)); +#ifdef CONFIG_SPI_CMDDATA + memset(g_spi6_dc_devices, 0, sizeof(g_spi6_dc_devices)); +#endif + spiinfo("SPI6 CS/DC registry initialized\n"); +#endif + + spiinfo("SPI initialization completed\n"); + return OK; +} + +/**************************************************************************** + * Name: stm32_spi_register_cs_device + * + * Description: + * Register a CS device for a specific SPI bus and device ID. + * + ****************************************************************************/ + +int stm32_spi_register_cs_device(int spi_bus, uint32_t devid, + const char *cs_pin, bool active_low) +{ + struct spi_cs_device_s *cs_devices; + struct spi_cs_device_s *device; + uint32_t gpio_config; + int error; + int ret; + + cs_devices = get_cs_devices_array(spi_bus); + if (cs_devices == NULL) + { + spierr("ERROR: Invalid SPI bus %d\n", spi_bus); + return -EINVAL; + } + + if (devid >= MAX_CS_DEVICES_PER_SPI) + { + spierr("ERROR: Device ID %lu >= maximum %d\n", + (unsigned long)devid, MAX_CS_DEVICES_PER_SPI); + return -EINVAL; + } + + device = &cs_devices[devid]; + if (device->in_use) + { + spierr("ERROR: Device ID %lu already registered for SPI%d\n", + (unsigned long)devid, spi_bus); + return -EBUSY; + } + + gpio_config = parse_gpio_pin(cs_pin, &error); + if (error != 0) + { + spierr("ERROR: Invalid CS pin '%s': %d\n", cs_pin, error); + return error; + } + + ret = stm32_configgpio(gpio_config); + if (ret < 0) + { + spierr("ERROR: Failed to configure CS pin %s: %d\n", cs_pin, ret); + return ret; + } + + stm32_gpiowrite(gpio_config, active_low ? true : false); + + device->gpio_config = gpio_config; + device->active_low = active_low; + device->in_use = true; + + spiinfo("Registered SPI%d device %lu: pin %s (%s)\n", + spi_bus, (unsigned long)devid, cs_pin, + active_low ? "active_low" : "active_high"); + + return OK; +} + +/**************************************************************************** + * Name: stm32_spi_register_dc_pin + * + * Description: + * Register a DC (Data/Command) pin for a specific SPI device. + * + ****************************************************************************/ + +#ifdef CONFIG_SPI_CMDDATA +int stm32_spi_register_dc_pin(int spi_bus, uint32_t devid, + const char *dc_pin) +{ + struct spi_dc_device_s *dc_devices; + struct spi_dc_device_s *device; + uint32_t gpio_config; + int error; + int ret; + + dc_devices = get_dc_devices_array(spi_bus); + if (dc_devices == NULL) + { + spierr("ERROR: Invalid SPI bus %d\n", spi_bus); + return -EINVAL; + } + + if (devid >= MAX_CS_DEVICES_PER_SPI) + { + spierr("ERROR: Device ID %lu >= maximum %d\n", + (unsigned long)devid, MAX_CS_DEVICES_PER_SPI); + return -EINVAL; + } + + device = &dc_devices[devid]; + if (device->in_use) + { + spierr("ERROR: DC pin already registered for SPI%d device %lu\n", + spi_bus, (unsigned long)devid); + return -EBUSY; + } + + gpio_config = parse_gpio_pin(dc_pin, &error); + if (error != 0) + { + spierr("ERROR: Invalid DC pin '%s': %d\n", dc_pin, error); + return error; + } + + ret = stm32_configgpio(gpio_config); + if (ret < 0) + { + spierr("ERROR: Failed to configure DC pin %s: %d\n", dc_pin, ret); + return ret; + } + + /* Initialize DC pin to data mode (HIGH) */ + + stm32_gpiowrite(gpio_config, true); + + device->gpio_config = gpio_config; + device->in_use = true; + + spiinfo("Registered SPI%d device %lu DC pin: %s\n", + spi_bus, (unsigned long)devid, dc_pin); + + return OK; +} +#endif + +/**************************************************************************** + * Name: stm32_spi_unregister_cs_device + * + * Description: + * Unregister a CS device. + * + ****************************************************************************/ + +int stm32_spi_unregister_cs_device(int spi_bus, uint32_t devid) +{ + struct spi_cs_device_s *cs_devices; + struct spi_cs_device_s *device; + + cs_devices = get_cs_devices_array(spi_bus); + if (cs_devices == NULL) + { + return -EINVAL; + } + + if (devid >= MAX_CS_DEVICES_PER_SPI) + { + return -EINVAL; + } + + device = &cs_devices[devid]; + if (!device->in_use) + { + return -ENOENT; + } + + device->gpio_config = INVALID_CS_PIN; + device->active_low = false; + device->in_use = false; + + spiinfo("Unregistered SPI%d device %lu\n", spi_bus, + (unsigned long)devid); + return OK; +} + +/**************************************************************************** + * Name: stm32_spidev_register_all + * + * Description: + * Register SPI devices for user access. + * + ****************************************************************************/ + +#ifdef CONFIG_SPI_DRIVER +int stm32_spidev_register_all(void) +{ + int ret = OK; + +#ifdef CONFIG_STM32H7_SPI1 + FAR struct spi_dev_s *spi1; + + spi1 = stm32_spibus_initialize(1); + if (spi1) + { + ret = spi_register(spi1, 1); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to register SPI1: %d\n", ret); + } + else + { + syslog(LOG_INFO, "SPI1 registered as /dev/spi1\n"); + } + } +#endif + +#ifdef CONFIG_STM32H7_SPI2 + FAR struct spi_dev_s *spi2; + + spi2 = stm32_spibus_initialize(2); + if (spi2) + { + ret = spi_register(spi2, 2); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to register SPI2: %d\n", ret); + } + else + { + syslog(LOG_INFO, "SPI2 registered as /dev/spi2\n"); + } + } +#endif + +#ifdef CONFIG_STM32H7_SPI3 + FAR struct spi_dev_s *spi3; + + spi3 = stm32_spibus_initialize(3); + if (spi3) + { + ret = spi_register(spi3, 3); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to register SPI3: %d\n", ret); + } + else + { + syslog(LOG_INFO, "SPI3 registered as /dev/spi3\n"); + } + } +#endif + +#ifdef CONFIG_STM32H7_SPI4 + FAR struct spi_dev_s *spi4; + + spi4 = stm32_spibus_initialize(4); + if (spi4) + { + ret = spi_register(spi4, 4); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to register SPI4: %d\n", ret); + } + else + { + syslog(LOG_INFO, "SPI4 registered as /dev/spi4\n"); + } + } +#endif + +#ifdef CONFIG_STM32H7_SPI5 + FAR struct spi_dev_s *spi5; + + spi5 = stm32_spibus_initialize(5); + if (spi5) + { + ret = spi_register(spi5, 5); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to register SPI5: %d\n", ret); + } + else + { + syslog(LOG_INFO, "SPI5 registered as /dev/spi5\n"); + } + } +#endif + +#ifdef CONFIG_STM32H7_SPI6 + FAR struct spi_dev_s *spi6; + + spi6 = stm32_spibus_initialize(6); + if (spi6) + { + ret = spi_register(spi6, 6); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to register SPI6: %d\n", ret); + } + else + { + syslog(LOG_INFO, "SPI6 registered as /dev/spi6\n"); + } + } +#endif + + return ret; +} +#endif + +/**************************************************************************** + * Name: stm32_spi1/2/3/4/5/6_select + * + * Description: + * SPI select functions - called by STM32 SPI driver + * + ****************************************************************************/ + +#ifdef CONFIG_STM32H7_SPI1 +void stm32_spi1select(FAR struct spi_dev_s *dev, uint32_t devid, + bool selected) +{ + spiinfo("SPI1 CS: devid=%lu, %s\n", + (unsigned long)devid, selected ? "SELECT" : "DESELECT"); + spi_cs_control(1, devid, selected); +} + +uint8_t stm32_spi1status(FAR struct spi_dev_s *dev, uint32_t devid) +{ + return SPI_STATUS_PRESENT; +} + +#ifdef CONFIG_SPI_CMDDATA +int stm32_spi1cmddata(FAR struct spi_dev_s *dev, uint32_t devid, bool cmd) +{ + spiinfo("SPI1 CMDDATA: devid=%lu, %s\n", + (unsigned long)devid, cmd ? "COMMAND" : "DATA"); + spi_dc_control(1, devid, cmd); + return OK; +} +#endif +#endif + +#ifdef CONFIG_STM32H7_SPI2 +void stm32_spi2select(FAR struct spi_dev_s *dev, uint32_t devid, + bool selected) +{ + spiinfo("SPI2 CS: devid=%lu, %s\n", + (unsigned long)devid, selected ? "SELECT" : "DESELECT"); + spi_cs_control(2, devid, selected); +} + +uint8_t stm32_spi2status(FAR struct spi_dev_s *dev, uint32_t devid) +{ + return SPI_STATUS_PRESENT; +} + +#ifdef CONFIG_SPI_CMDDATA +int stm32_spi2cmddata(FAR struct spi_dev_s *dev, uint32_t devid, bool cmd) +{ + spiinfo("SPI2 CMDDATA: devid=%lu, %s\n", + (unsigned long)devid, cmd ? "COMMAND" : "DATA"); + spi_dc_control(2, devid, cmd); + return OK; +} +#endif +#endif + +#ifdef CONFIG_STM32H7_SPI3 +void stm32_spi3select(FAR struct spi_dev_s *dev, uint32_t devid, + bool selected) +{ + spiinfo("SPI3 CS: devid=%lu, %s\n", + (unsigned long)devid, selected ? "SELECT" : "DESELECT"); + spi_cs_control(3, devid, selected); +} + +uint8_t stm32_spi3status(FAR struct spi_dev_s *dev, uint32_t devid) +{ + return SPI_STATUS_PRESENT; +} + +#ifdef CONFIG_SPI_CMDDATA +int stm32_spi3cmddata(FAR struct spi_dev_s *dev, uint32_t devid, bool cmd) +{ + spiinfo("SPI3 CMDDATA: devid=%lu, %s\n", + (unsigned long)devid, cmd ? "COMMAND" : "DATA"); + spi_dc_control(3, devid, cmd); + return OK; +} +#endif +#endif + +#ifdef CONFIG_STM32H7_SPI4 +void stm32_spi4select(FAR struct spi_dev_s *dev, uint32_t devid, + bool selected) +{ + spiinfo("SPI4 CS: devid=%lu, %s\n", + (unsigned long)devid, selected ? "SELECT" : "DESELECT"); + spi_cs_control(4, devid, selected); +} + +uint8_t stm32_spi4status(FAR struct spi_dev_s *dev, uint32_t devid) +{ + return SPI_STATUS_PRESENT; +} + +#ifdef CONFIG_SPI_CMDDATA +int stm32_spi4cmddata(FAR struct spi_dev_s *dev, uint32_t devid, bool cmd) +{ + spiinfo("SPI4 CMDDATA: devid=%lu, %s\n", + (unsigned long)devid, cmd ? "COMMAND" : "DATA"); + spi_dc_control(4, devid, cmd); + return OK; +} +#endif +#endif + +#ifdef CONFIG_STM32H7_SPI5 +void stm32_spi5select(FAR struct spi_dev_s *dev, uint32_t devid, + bool selected) +{ + spiinfo("SPI5 CS: devid=%lu, %s\n", + (unsigned long)devid, selected ? "SELECT" : "DESELECT"); + spi_cs_control(5, devid, selected); +} + +uint8_t stm32_spi5status(FAR struct spi_dev_s *dev, uint32_t devid) +{ + return SPI_STATUS_PRESENT; +} + +#ifdef CONFIG_SPI_CMDDATA +int stm32_spi5cmddata(FAR struct spi_dev_s *dev, uint32_t devid, bool cmd) +{ + spiinfo("SPI5 CMDDATA: devid=%lu, %s\n", + (unsigned long)devid, cmd ? "COMMAND" : "DATA"); + spi_dc_control(5, devid, cmd); + return OK; +} +#endif +#endif + +#ifdef CONFIG_STM32H7_SPI6 +void stm32_spi6select(FAR struct spi_dev_s *dev, uint32_t devid, + bool selected) +{ + spiinfo("SPI6 CS: devid=%lu, %s\n", + (unsigned long)devid, selected ? "SELECT" : "DESELECT"); + spi_cs_control(6, devid, selected); +} + +uint8_t stm32_spi6status(FAR struct spi_dev_s *dev, uint32_t devid) +{ + return SPI_STATUS_PRESENT; +} + +#ifdef CONFIG_SPI_CMDDATA +int stm32_spi6cmddata(FAR struct spi_dev_s *dev, uint32_t devid, bool cmd) +{ + spiinfo("SPI6 CMDDATA: devid=%lu, %s\n", + (unsigned long)devid, cmd ? "COMMAND" : "DATA"); + spi_dc_control(6, devid, cmd); + return OK; +} +#endif +#endif + +#endif /* CONFIG_STM32H7_SPI */ diff --git a/boards/arm/stm32h7/nucleo-h753zi/src/stm32_ssd1306.c b/boards/arm/stm32h7/nucleo-h753zi/src/stm32_ssd1306.c new file mode 100644 index 0000000000000..1baa42f18c6e3 --- /dev/null +++ b/boards/arm/stm32h7/nucleo-h753zi/src/stm32_ssd1306.c @@ -0,0 +1,760 @@ +/**************************************************************************** + * boards/arm/stm32h7/nucleo-h753zi/src/stm32_ssd1306.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * About this driver + ****************************************************************************/ + +/* This is the board-level driver for the SSD1306 OLED display. + * + * WHAT IS SSD1306? + * ---------------- + * The SSD1306 is a small monochrome OLED display controller. Common sizes + * are 128x64 or 128x32 pixels. It communicates via I2C or SPI. + * This driver uses I2C. + * + * DRIVER ARCHITECTURE IN NUTTX: + * ----------------------------- + * NuttX uses a layered driver architecture: + * + * +---------------------+ + * | Application | <- Your app opens /dev/lcd0 + * +---------------------+ + * | + * +---------------------+ + * | LCD Dev Layer | <- lcddev_register() creates /dev/lcdX + * +---------------------+ + * | + * +---------------------+ + * | SSD1306 Driver | <- ssd1306_initialize() from NuttX + * +---------------------+ + * | + * +---------------------+ + * | I2C Master | <- stm32_i2cbus_initialize() from arch + * +---------------------+ + * | + * +---------------------+ + * | Hardware (I2C2) | <- Physical pins PF0/PF1 + * +---------------------+ + * + * THIS FILE'S ROLE: + * ----------------- + * This file is the "glue" that connects the NuttX SSD1306 driver to our + * specific board (Nucleo-H753ZI). It: + * 1. Gets the I2C bus interface + * 2. Passes it to the SSD1306 driver + * 3. Provides helper functions for power control + * + * IMPORTANT: The lcddev_register() call must be made from stm32_bringup.c + * AFTER board_lcd_getdev() returns, NOT inside board_lcd_getdev(). + * This is because lcddev_register() internally calls board_lcd_getdev(), + * which would create infinite recursion. + * + * WHY /dev/lcdX AND NOT /dev/fbX? + * ------------------------------- + * - /dev/fbX (framebuffer): Used for displays that need a full memory + * buffer in RAM. Good for large color displays (like ST7796 480x320). + * + * - /dev/lcdX (LCD interface): Used for smaller displays with internal + * memory. The SSD1306 has 1KB RAM inside the chip itself, so we don't + * need a big framebuffer in our MCU's RAM. + * + * BRIGHTNESS CONTROL: + * ------------------- + * The SSD1306 requires 3 registers to effectively control brightness: + * - 0x81: Contrast (0-255) + * - 0xD9: Pre-charge period + * - 0xDB: VCOMH deselect level + * + * The NuttX driver only sets contrast (0x81), which has minimal visual + * effect. This driver sends all 3 commands directly via I2C for real + * brightness control. + */ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/* Standard C headers */ + +#include /* Error codes like ENODEV, EINVAL */ +#include /* For logging messages */ +#include /* Debug macros */ + +/* NuttX system headers */ + +#include /* Board-level interfaces */ + +/* LCD-related headers */ + +#include /* Generic LCD interface */ +#include /* SSD1306-specific driver */ + +/* I2C header */ + +#include /* I2C master interface */ + +/* Our board-specific header with pin definitions and prototypes */ + +#include "nucleo-h753zi.h" + +/**************************************************************************** + * Conditional Compilation + ****************************************************************************/ + +/* This entire file is only compiled if BOTH conditions are true: + * + * 1. CONFIG_LCD_SSD1306: The NuttX SSD1306 driver is enabled + * (menuconfig: Device Drivers -> LCD -> SSD1306) + * + * 2. CONFIG_NUCLEO_H753ZI_SSD1306_ENABLE: Our board-specific option + * (menuconfig: Board Selection -> I2C Devices -> SSD1306) + * + * If either is missing, this file compiles to nothing (empty). + */ + +#if defined(CONFIG_LCD_SSD1306) && \ + defined(CONFIG_NUCLEO_H753ZI_SSD1306_ENABLE) + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* These macros translate the Kconfig values (accessed via nucleo-h753zi.h) + * to simpler names used in this file. + * + * WHY THIS INDIRECTION? + * The Kconfig values have long names like NUCLEO_SSD1306_I2C_BUS. + * Using shorter names makes the code more readable. + * Also, if we ever need to change the source of these values, + * we only change it here. + */ + +#define SSD1306_I2C_BUS NUCLEO_SSD1306_I2C_BUS /* Which I2C: 1-4 */ +#define SSD1306_I2C_ADDR NUCLEO_SSD1306_I2C_ADDR /* 0x3C or 0x3D */ +#define SSD1306_I2C_FREQUENCY NUCLEO_SSD1306_I2C_FREQUENCY /* 100k or 400k */ +#define SSD1306_POWER_PERCENT NUCLEO_SSD1306_POWER_PERCENT /* 0-100% */ +#define SSD1306_DEVPATH NUCLEO_SSD1306_DEVPATH /* "/dev/lcd0" */ +#define SSD1306_DEVNO NUCLEO_SSD1306_DEVNO /* 0 */ +#define SSD1306_DEVNAME NUCLEO_SSD1306_DEVNAME /* "ssd1306" */ + +/* SSD1306 Command Bytes */ + +#define SSD1306_CMD_BYTE 0x00 /* Control byte: Co=0, D/C#=0 */ +#define SSD1306_CMD_SETCONTRAST 0x81 /* Set contrast control */ +#define SSD1306_CMD_SETPRECHARGE 0xd9 /* Set pre-charge period */ +#define SSD1306_CMD_SETVCOMDETECT 0xdb /* Set VCOMH deselect level */ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* These are module-level variables (static = only visible in this file). + * + * g_ssd1306_i2c: Pointer to the I2C master interface. We get this from + * our board's I2C driver and pass it to the SSD1306 driver. + * + * g_ssd1306_lcd: Pointer to the LCD device structure. The SSD1306 driver + * returns this, and we use it to control the display. + * + * Both start as NULL and are set during initialization. + */ + +static struct i2c_master_s *g_ssd1306_i2c = NULL; +static struct lcd_dev_s *g_ssd1306_lcd = NULL; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: ssd1306_send_cmd_arg + * + * Description: + * Send a command with one argument byte to the SSD1306 via I2C. + * + * Input Parameters: + * cmd - Command byte + * arg - Argument byte + * + * Returned Value: + * OK on success, negative errno on failure + * + ****************************************************************************/ + +static int ssd1306_send_cmd_arg(uint8_t cmd, uint8_t arg) +{ + struct i2c_msg_s msg; + uint8_t buf[3]; + int ret; + + if (!g_ssd1306_i2c) + { + return -ENODEV; + } + + /* SSD1306 I2C protocol for double-byte commands: + * [Control byte: 0x00] [Command] [Argument] + * + * Control byte 0x00 = Co=0 (continuous), D/C#=0 (command mode) + * This tells SSD1306 that following bytes are all commands. + */ + + buf[0] = SSD1306_CMD_BYTE; /* Control byte: command mode */ + buf[1] = cmd; + buf[2] = arg; + + msg.frequency = SSD1306_I2C_FREQUENCY; + msg.addr = SSD1306_I2C_ADDR; + msg.flags = 0; /* Write */ + msg.buffer = buf; + msg.length = 3; + + ret = I2C_TRANSFER(g_ssd1306_i2c, &msg, 1); + if (ret < 0) + { + syslog(LOG_ERR, "SSD1306: I2C cmd 0x%02x arg 0x%02x failed: %d\n", + cmd, arg, ret); + } + + return ret; +} + +/**************************************************************************** + * Name: ssd1306_set_brightness_raw + * + * Description: + * Set display brightness using all 3 required SSD1306 registers. + * This bypasses the NuttX driver to provide real brightness control. + * + * The SSD1306 brightness is controlled by: + * - Contrast register (0x81): 0-255, controls OLED segment current + * - Pre-charge period (0xD9): affects charge pump timing + * - VCOMH level (0xDB): affects voltage levels + * + * For effective dimming, all 3 must be adjusted together. + * + * Input Parameters: + * percent - Brightness 0-100% + * + * Returned Value: + * OK on success, negative errno on failure + * + ****************************************************************************/ + +static int ssd1306_set_brightness_raw(int percent) +{ + uint8_t contrast; + uint8_t precharge; + uint8_t vcomh; + int ret; + + /* Clamp to valid range */ + + if (percent < 0) + { + percent = 0; + } + else if (percent > 100) + { + percent = 100; + } + + /* Calculate register values based on percentage. + * + * Contrast: Linear scale 0-255 + * + * Pre-charge (0xD9): Controls charge/discharge time + * - Low nibble: phase 1 (1-15 DCLKs) + * - High nibble: phase 2 (1-15 DCLKs) + * - Range: 0x11 (dimmest) to 0xFF (brightest) + * + * VCOMH (0xDB): Deselect voltage level + * - 0x00 = 0.65 x VCC (dimmest) + * - 0x20 = 0.77 x VCC + * - 0x30 = 0.83 x VCC + * - 0x40 = 1.00 x VCC (brightest, may cause damage on some displays) + * + * Using linear interpolation for smoother transitions. + */ + + /* Contrast: direct linear mapping */ + + contrast = (uint8_t)((percent * 255) / 100); + + /* Pre-charge: scale from 0x11 to 0xF1 + * phase1 = 1 + (percent * 14 / 100) -> 1 to 15 + * phase2 = 1 + (percent * 14 / 100) -> 1 to 15 + */ + + { + uint8_t phase1; + uint8_t phase2; + + phase1 = 1 + (uint8_t)((percent * 14) / 100); + phase2 = 1 + (uint8_t)((percent * 14) / 100); + precharge = (phase2 << 4) | phase1; + } + + /* VCOMH: scale from 0x00 to 0x30 (avoid 0x40 for safety) + * Linear: 0x00 at 0%, 0x30 at 100% + */ + + vcomh = (uint8_t)((percent * 0x30) / 100); + + syslog(LOG_INFO, + "SSD1306: Brightness %d%% -> con=0x%02x pre=0x%02x vcom=0x%02x\n", + percent, contrast, precharge, vcomh); + + /* Send all three commands */ + + ret = ssd1306_send_cmd_arg(SSD1306_CMD_SETCONTRAST, contrast); + if (ret < 0) + { + return ret; + } + + ret = ssd1306_send_cmd_arg(SSD1306_CMD_SETPRECHARGE, precharge); + if (ret < 0) + { + return ret; + } + + ret = ssd1306_send_cmd_arg(SSD1306_CMD_SETVCOMDETECT, vcomh); + if (ret < 0) + { + return ret; + } + + return OK; +} + +/**************************************************************************** + * Name: calculate_power_level + * + * Description: + * Convert a percentage (0-100) to an SSD1306 power level. + * + * The SSD1306 driver only understands two power states: + * - 0 = display OFF (sleep mode, low power) + * - 1 = display ON (normal operation) + * + * So any percentage > 0 means "turn on", and 0 means "turn off". + * Brightness/contrast is a separate setting handled by the driver. + * + * Input Parameters: + * percent - Power level as percentage (0-100) + * + * Returned Value: + * 0 = power off, 1 = power on + * + ****************************************************************************/ + +static int calculate_power_level(int percent) +{ + if (percent <= 0) + { + return 0; /* Power off */ + } + else + { + return 1; /* Power on */ + } +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_lcd_initialize + * + * Description: + * Initialize the LCD hardware. This is called early during boot from + * stm32_bringup.c in the display initialization phase. + * + * This function does NOT initialize the display itself - it only + * prepares the I2C interface. The actual display initialization + * happens in board_lcd_getdev(). + * + * Why split into two functions? + * This follows the NuttX LCD driver pattern: + * - board_lcd_initialize(): Prepare the bus (I2C/SPI) + * - board_lcd_getdev(): Initialize and return the LCD device + * + * Returned Value: + * OK (0) on success + * Negative errno on failure (e.g., -ENODEV if I2C bus not available) + * + ****************************************************************************/ + +int board_lcd_initialize(void) +{ + int ret; + + /* Log what we're doing - helps with debugging */ + + lcdinfo("SSD1306: Initializing OLED display\n"); + lcdinfo("SSD1306: I2C Bus: I2C%d\n", SSD1306_I2C_BUS); + lcdinfo("SSD1306: Address: 0x%02X\n", SSD1306_I2C_ADDR); + lcdinfo("SSD1306: Frequency: %lu Hz\n", + (unsigned long)SSD1306_I2C_FREQUENCY); + lcdinfo("SSD1306: Brightness: %d%%\n", SSD1306_POWER_PERCENT); + + /* Step 1: Register I2C device for tracking and debugging + * + * This is OPTIONAL but useful. Our stm32_i2c.c driver keeps a list + * of all I2C devices on each bus. This helps when debugging to see + * what devices are registered. + * + * If this fails, we continue anyway - it's not critical. + */ + + ret = stm32_i2c_register_device(SSD1306_I2C_BUS, + SSD1306_I2C_ADDR, + SSD1306_I2C_FREQUENCY, + SSD1306_DEVNAME); + if (ret < 0) + { + syslog(LOG_WARNING, + "SSD1306: WARNING - Failed to register I2C device: %d\n", ret); + + /* Continue anyway - registration is optional */ + } + + /* Step 2: Get the I2C master interface + * + * stm32_i2c_get_master() returns a pointer to the I2C bus structure. + * This structure contains function pointers for I2C operations + * (transfer, reset, etc.) that the SSD1306 driver will use. + * + * If this fails, we cannot continue - we need I2C to talk to display. + */ + + g_ssd1306_i2c = stm32_i2c_get_master(SSD1306_I2C_BUS); + if (!g_ssd1306_i2c) + { + syslog(LOG_ERR, "SSD1306: ERROR - Failed to get I2C%d master\n", + SSD1306_I2C_BUS); + + /* Cleanup: unregister the device we registered in step 1 */ + + stm32_i2c_unregister_device(SSD1306_I2C_BUS, SSD1306_I2C_ADDR); + return -ENODEV; + } + + lcdinfo("SSD1306: I2C interface ready\n"); + return OK; +} + +/**************************************************************************** + * Name: board_lcd_getdev + * + * Description: + * Get the LCD device structure and initialize the display. + * + * This function: + * 1. Calls ssd1306_initialize() to init the display hardware + * 2. Turns on the display if configured to do so + * 3. Sets the brightness level from Kconfig (using direct I2C) + * + * IMPORTANT: Do NOT call lcddev_register() from inside this function! + * lcddev_register() internally calls board_lcd_getdev(), which would + * create infinite recursion. The lcddev_register() call must be made + * from stm32_bringup.c AFTER this function returns. + * + * Input Parameters: + * devno - Device number (0 for first LCD, 1 for second, etc.) + * This becomes the X in /dev/lcdX + * + * Returned Value: + * Pointer to lcd_dev_s structure on success + * NULL on failure + * + ****************************************************************************/ + +struct lcd_dev_s *board_lcd_getdev(int devno) +{ + int power_level; + + /* Safety check: make sure board_lcd_initialize() was called first */ + + if (!g_ssd1306_i2c) + { + syslog(LOG_ERR, + "SSD1306: ERROR - I2C not initialized. " + "Call board_lcd_initialize() first\n"); + return NULL; + } + + /* If already initialized, just return the existing device. + * This prevents re-initialization if called multiple times. + */ + + if (g_ssd1306_lcd != NULL) + { + return g_ssd1306_lcd; + } + + /* Step 1: Initialize the SSD1306 driver + * + * ssd1306_initialize() is provided by NuttX (drivers/lcd/ssd1306.c). + * It: + * - Sends initialization commands to the display via I2C + * - Allocates internal structures + * - Returns a lcd_dev_s pointer we can use to control the display + * + * Parameters: + * g_ssd1306_i2c: The I2C interface to use + * NULL: No SPI interface (we're using I2C) + * devno: Device number for this LCD + */ + + lcdinfo("SSD1306: Binding to I2C%d (device %d)\n", + SSD1306_I2C_BUS, devno); + + g_ssd1306_lcd = ssd1306_initialize(g_ssd1306_i2c, NULL, devno); + if (!g_ssd1306_lcd) + { + syslog(LOG_ERR, + "SSD1306: ERROR - ssd1306_initialize() failed\n"); + return NULL; + } + + lcdinfo("SSD1306: Driver initialized successfully\n"); + + /* Step 2: Turn on the display (if configured) + * + * The power level comes from Kconfig (SSD1306_POWER_PERCENT). + * - 0%: Keep display off + * - 1-100%: Turn display on + * + * setpower() is a function pointer in the lcd_dev_s structure. + * The SSD1306 driver implements it to send the "Display ON" command. + */ + + power_level = calculate_power_level(SSD1306_POWER_PERCENT); + + if (power_level > 0) + { + lcdinfo("SSD1306: Turning on display\n"); + g_ssd1306_lcd->setpower(g_ssd1306_lcd, power_level); + + /* Step 3: Set display brightness using direct I2C commands + * + * The NuttX setcontrast() only sends the contrast register (0x81), + * which has minimal visual effect on brightness. For real brightness + * control, we need to also adjust pre-charge and VCOMH registers. + */ + + ssd1306_set_brightness_raw(SSD1306_POWER_PERCENT); + } + else + { + lcdinfo("SSD1306: Display is OFF (power: 0%%)\n"); + } + + /* NOTE: Do NOT call lcddev_register() here! + * + * lcddev_register() internally calls board_lcd_getdev() to get + * the LCD device. If we call it here, we create infinite recursion: + * + * board_lcd_getdev() -> lcddev_register() -> board_lcd_getdev() -> ... + * + * The lcddev_register() call must be made from stm32_bringup.c + * AFTER this function returns successfully. + */ + + return g_ssd1306_lcd; +} + +/**************************************************************************** + * Name: board_lcd_uninitialize + * + * Description: + * Uninitialize the LCD and release resources. + * + * This should be called when the system is shutting down or if you + * need to reconfigure the LCD. It: + * - Turns off the display (saves power) + * - Unregisters the I2C device from our tracking system + * - Clears the global pointers + * + * Note: We don't uninitialize the I2C bus itself because other + * devices might be using it (sensors, etc.). + * + ****************************************************************************/ + +void board_lcd_uninitialize(void) +{ + lcdinfo("SSD1306: Uninitializing display\n"); + + /* Power off display to save energy */ + + if (g_ssd1306_lcd) + { + g_ssd1306_lcd->setpower(g_ssd1306_lcd, 0); + g_ssd1306_lcd = NULL; + } + + /* Unregister from our I2C device tracking system */ + + stm32_i2c_unregister_device(SSD1306_I2C_BUS, SSD1306_I2C_ADDR); + + /* Clear the I2C pointer but don't uninitialize the bus + * because other devices might be using it. + */ + + g_ssd1306_i2c = NULL; + + lcdinfo("SSD1306: Uninitialized\n"); +} + +/**************************************************************************** + * Name: stm32_ssd1306_get_devpath + * + * Description: + * Get the configured device path for the SSD1306. + * + * Useful when an application needs to know which /dev/lcdX to open. + * Instead of hardcoding "/dev/lcd0", the app can call this function. + * + * Example usage in an application: + * const char *path = stm32_ssd1306_get_devpath(); + * int fd = open(path, O_RDWR); + * + * Returned Value: + * Pointer to device path string (e.g., "/dev/lcd0") + * + ****************************************************************************/ + +const char *stm32_ssd1306_get_devpath(void) +{ + return SSD1306_DEVPATH; +} + +/**************************************************************************** + * Name: stm32_ssd1306_set_power + * + * Description: + * Change SSD1306 display power at runtime. + * + * This allows turning the display on/off after initialization. + * Useful for: + * - Power saving (turn off when not needed) + * - Screen blanking + * - User-controlled display toggle + * + * Input Parameters: + * percent - Power level 0-100% + * 0 = off, 1-100 = on (and sets brightness) + * + * Returned Value: + * OK on success + * -ENODEV if LCD not initialized + * -EINVAL if percentage is invalid + * + ****************************************************************************/ + +int stm32_ssd1306_set_power(int percent) +{ + int power_level; + + /* Check if the LCD was initialized */ + + if (!g_ssd1306_lcd) + { + syslog(LOG_ERR, "SSD1306: ERROR - Not initialized\n"); + return -ENODEV; + } + + /* Validate input range */ + + if (percent < 0 || percent > 100) + { + syslog(LOG_ERR, + "SSD1306: ERROR - Invalid power: %d (must be 0-100)\n", + percent); + return -EINVAL; + } + + /* Convert percentage to power level and apply */ + + power_level = calculate_power_level(percent); + + lcdinfo("SSD1306: Setting power to %d%%\n", percent); + + g_ssd1306_lcd->setpower(g_ssd1306_lcd, power_level); + + /* If turning on, also set brightness */ + + if (power_level > 0) + { + ssd1306_set_brightness_raw(percent); + } + + return OK; +} + +/**************************************************************************** + * Name: stm32_ssd1306_set_brightness + * + * Description: + * Change SSD1306 display brightness at runtime using direct I2C. + * + * This function provides real brightness control by adjusting all 3 + * required SSD1306 registers (contrast, pre-charge, VCOMH). + * + * Input Parameters: + * percent - Brightness level 0-100% + * + * Returned Value: + * OK on success + * -ENODEV if LCD not initialized + * -EINVAL if percentage is invalid + * + ****************************************************************************/ + +int stm32_ssd1306_set_brightness(int percent) +{ + /* Check if the I2C interface was initialized */ + + if (!g_ssd1306_i2c) + { + syslog(LOG_ERR, "SSD1306: ERROR - Not initialized\n"); + return -ENODEV; + } + + /* Validate input range */ + + if (percent < 0 || percent > 100) + { + syslog(LOG_ERR, + "SSD1306: ERROR - Invalid brightness: %d (must be 0-100)\n", + percent); + return -EINVAL; + } + + return ssd1306_set_brightness_raw(percent); +} + +#endif /* CONFIG_LCD_SSD1306 && CONFIG_NUCLEO_H753ZI_SSD1306_ENABLE */ diff --git a/boards/arm/stm32h7/nucleo-h753zi/src/stm32_st7796.c b/boards/arm/stm32h7/nucleo-h753zi/src/stm32_st7796.c new file mode 100644 index 0000000000000..02407f8d0960b --- /dev/null +++ b/boards/arm/stm32h7/nucleo-h753zi/src/stm32_st7796.c @@ -0,0 +1,700 @@ +/**************************************************************************** + * boards/arm/stm32h7/nucleo-h753zi/src/stm32_st7796.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "nucleo-h753zi.h" +#include "stm32_gpio.h" +#include "stm32_spi.h" + +#if defined(CONFIG_LCD_ST7796) && defined(CONFIG_NUCLEO_H753ZI_ST7796_ENABLE) + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* SPI port selection from Kconfig */ + +#ifdef CONFIG_NUCLEO_H753ZI_ST7796_SPI1 +# define ST7796_SPI_PORTNO 1 +# ifndef CONFIG_STM32H7_SPI1 +# error "ST7796 configured for SPI1 but CONFIG_STM32H7_SPI1 not enabled" +# endif +# ifndef CONFIG_NUCLEO_H753ZI_SPI1_ENABLE +# error "ST7796 configured for SPI1 but board SPI1 not enabled" +# endif +#elif defined(CONFIG_NUCLEO_H753ZI_ST7796_SPI2) +# define ST7796_SPI_PORTNO 2 +# ifndef CONFIG_STM32H7_SPI2 +# error "ST7796 configured for SPI2 but CONFIG_STM32H7_SPI2 not enabled" +# endif +# ifndef CONFIG_NUCLEO_H753ZI_SPI2_ENABLE +# error "ST7796 configured for SPI2 but board SPI2 not enabled" +# endif +#elif defined(CONFIG_NUCLEO_H753ZI_ST7796_SPI3) +# define ST7796_SPI_PORTNO 3 +# ifndef CONFIG_STM32H7_SPI3 +# error "ST7796 configured for SPI3 but CONFIG_STM32H7_SPI3 not enabled" +# endif +# ifndef CONFIG_NUCLEO_H753ZI_SPI3_ENABLE +# error "ST7796 configured for SPI3 but board SPI3 not enabled" +# endif +#elif defined(CONFIG_NUCLEO_H753ZI_ST7796_SPI4) +# define ST7796_SPI_PORTNO 4 +# ifndef CONFIG_STM32H7_SPI4 +# error "ST7796 configured for SPI4 but CONFIG_STM32H7_SPI4 not enabled" +# endif +# ifndef CONFIG_NUCLEO_H753ZI_SPI4_ENABLE +# error "ST7796 configured for SPI4 but board SPI4 not enabled" +# endif +#elif defined(CONFIG_NUCLEO_H753ZI_ST7796_SPI5) +# define ST7796_SPI_PORTNO 5 +# ifndef CONFIG_STM32H7_SPI5 +# error "ST7796 configured for SPI5 but CONFIG_STM32H7_SPI5 not enabled" +# endif +# ifndef CONFIG_NUCLEO_H753ZI_SPI5_ENABLE +# error "ST7796 configured for SPI5 but board SPI5 not enabled" +# endif +#elif defined(CONFIG_NUCLEO_H753ZI_ST7796_SPI6) +# define ST7796_SPI_PORTNO 6 +# ifndef CONFIG_STM32H7_SPI6 +# error "ST7796 configured for SPI6 but CONFIG_STM32H7_SPI6 not enabled" +# endif +# ifndef CONFIG_NUCLEO_H753ZI_SPI6_ENABLE +# error "ST7796 configured for SPI6 but board SPI6 not enabled" +# endif +#else +# error "No SPI port selected for ST7796" +#endif + +/* Verify CONFIG_SPI_CMDDATA is enabled */ + +#ifndef CONFIG_SPI_CMDDATA +# error "CONFIG_SPI_CMDDATA must be enabled for ST7796 driver" +#endif + +/* Pin configuration from Kconfig with defaults */ + +#ifndef CONFIG_NUCLEO_H753ZI_ST7796_CS_PIN +# define CONFIG_NUCLEO_H753ZI_ST7796_CS_PIN "PA4" +#endif + +#ifndef CONFIG_NUCLEO_H753ZI_ST7796_DC_PIN +# define CONFIG_NUCLEO_H753ZI_ST7796_DC_PIN "PA3" +#endif + +#ifndef CONFIG_NUCLEO_H753ZI_ST7796_RESET_PIN +# define CONFIG_NUCLEO_H753ZI_ST7796_RESET_PIN "PA2" +#endif + +#ifndef CONFIG_NUCLEO_H753ZI_ST7796_LED_PIN +# define CONFIG_NUCLEO_H753ZI_ST7796_LED_PIN "PA1" +#endif + +#ifndef CONFIG_NUCLEO_H753ZI_ST7796_CS_ACTIVE_LOW +# define CONFIG_NUCLEO_H753ZI_ST7796_CS_ACTIVE_LOW true +#endif + +#ifndef CONFIG_NUCLEO_H753ZI_ST7796_DEVID +# define CONFIG_NUCLEO_H753ZI_ST7796_DEVID 0 +#endif + +/* SPI frequency from Kconfig with default */ + +#ifndef CONFIG_NUCLEO_H753ZI_ST7796_FREQUENCY +# define CONFIG_NUCLEO_H753ZI_ST7796_FREQUENCY ST7796_SPI_MAXFREQUENCY +#endif + +/* Reset timing (from ST7796 datasheet) */ + +#define ST7796_RESET_DELAY_MS 10 +#define ST7796_RESET_HOLD_MS 10 +#define ST7796_RESET_RELEASE_MS 120 + +/* GPIO helper macros */ + +#define ST7796_GPIO_CONFIG_MASK 0xffff0000 +#define ST7796_GPIO_IN_FLOAT (GPIO_INPUT | GPIO_FLOAT | GPIO_SPEED_50MHz) + +/* Display resolution based on orientation from Kconfig */ + +#if defined(CONFIG_NUCLEO_H753ZI_ST7796_LANDSCAPE) || \ + defined(CONFIG_NUCLEO_H753ZI_ST7796_RLANDSCAPE) +# define ST7796_XRES ST7796_YRES_RAW +# define ST7796_YRES ST7796_XRES_RAW +#else +# define ST7796_XRES ST7796_XRES_RAW +# define ST7796_YRES ST7796_YRES_RAW +#endif + +/* Base MADCTL value based on orientation and BGR from Kconfig */ + +#if defined(CONFIG_NUCLEO_H753ZI_ST7796_LANDSCAPE) +# ifdef CONFIG_NUCLEO_H753ZI_ST7796_BGR +# define ST7796_MADCTL_BASE ST7796_MADCTL_LANDSCAPE_BGR +# else +# define ST7796_MADCTL_BASE ST7796_MADCTL_LANDSCAPE +# endif +#elif defined(CONFIG_NUCLEO_H753ZI_ST7796_RPORTRAIT) +# ifdef CONFIG_NUCLEO_H753ZI_ST7796_BGR +# define ST7796_MADCTL_BASE ST7796_MADCTL_RPORTRAIT_BGR +# else +# define ST7796_MADCTL_BASE ST7796_MADCTL_RPORTRAIT +# endif +#elif defined(CONFIG_NUCLEO_H753ZI_ST7796_RLANDSCAPE) +# ifdef CONFIG_NUCLEO_H753ZI_ST7796_BGR +# define ST7796_MADCTL_BASE ST7796_MADCTL_RLANDSCAPE_BGR +# else +# define ST7796_MADCTL_BASE ST7796_MADCTL_RLANDSCAPE +# endif +#else /* Portrait (default) */ +# ifdef CONFIG_NUCLEO_H753ZI_ST7796_BGR +# define ST7796_MADCTL_BASE ST7796_MADCTL_PORTRAIT_BGR +# else +# define ST7796_MADCTL_BASE ST7796_MADCTL_PORTRAIT +# endif +#endif + +/* Initial rotation from Kconfig */ + +#ifdef CONFIG_NUCLEO_H753ZI_ST7796_ROTATION_180 +# define ST7796_INIT_ROTATION 180 +#else +# define ST7796_INIT_ROTATION 0 +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static uint32_t g_reset_pin; +static uint32_t g_led_pin; +static bool g_st7796_initialized = false; +static FAR struct spi_dev_s *g_spi_dev = NULL; +static FAR struct fb_vtable_s *g_fb_vtable = NULL; + +/* Board-specific configuration passed to generic driver */ + +static struct st7796_config_s g_st7796_config = +{ + .frequency = CONFIG_NUCLEO_H753ZI_ST7796_FREQUENCY, + .xres = ST7796_XRES, + .yres = ST7796_YRES, + .bpp = 16, + .madctl = ST7796_MADCTL_BASE /* 0x28 -> will fix it */, + .rotation = ST7796_INIT_ROTATION, +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: parse_gpio_pin + * + * Description: + * Parse GPIO pin string like "PA0" into STM32 GPIO configuration. + * + ****************************************************************************/ + +static uint32_t parse_gpio_pin(FAR const char *pin_str, FAR int *error) +{ + size_t len; + char port; + FAR const char *pin_num_str; + FAR char *endptr; + long pin_num; + uint32_t port_base; + uint32_t gpio_pin; + + *error = 0; + + if (pin_str == NULL) + { + *error = -EINVAL; + return 0; + } + + while (*pin_str == ' ' || *pin_str == '\t') + { + pin_str++; + } + + len = strlen(pin_str); + if (len < 3 || len > 4) + { + *error = -EINVAL; + return 0; + } + + if (pin_str[0] != 'P') + { + *error = -EINVAL; + return 0; + } + + port = pin_str[1]; + if (port < 'A' || port > 'K') + { + *error = -EINVAL; + return 0; + } + + pin_num_str = &pin_str[2]; + pin_num = strtol(pin_num_str, &endptr, 10); + if (*endptr != '\0' || pin_num < 0 || pin_num > 15) + { + *error = -EINVAL; + return 0; + } + + switch (port) + { + case 'A': + port_base = GPIO_PORTA; break; + case 'B': + port_base = GPIO_PORTB; break; + case 'C': + port_base = GPIO_PORTC; break; + case 'D': + port_base = GPIO_PORTD; break; + case 'E': + port_base = GPIO_PORTE; break; + case 'F': + port_base = GPIO_PORTF; break; + case 'G': + port_base = GPIO_PORTG; break; + case 'H': + port_base = GPIO_PORTH; break; + default: + *error = -EINVAL; + return 0; + } + + switch (pin_num) + { + case 0: + gpio_pin = GPIO_PIN0; break; + case 1: + gpio_pin = GPIO_PIN1; break; + case 2: + gpio_pin = GPIO_PIN2; break; + case 3: + gpio_pin = GPIO_PIN3; break; + case 4: + gpio_pin = GPIO_PIN4; break; + case 5: + gpio_pin = GPIO_PIN5; break; + case 6: + gpio_pin = GPIO_PIN6; break; + case 7: + gpio_pin = GPIO_PIN7; break; + case 8: + gpio_pin = GPIO_PIN8; break; + case 9: + gpio_pin = GPIO_PIN9; break; + case 10: + gpio_pin = GPIO_PIN10; break; + case 11: + gpio_pin = GPIO_PIN11; break; + case 12: + gpio_pin = GPIO_PIN12; break; + case 13: + gpio_pin = GPIO_PIN13; break; + case 14: + gpio_pin = GPIO_PIN14; break; + case 15: + gpio_pin = GPIO_PIN15; break; + default: + *error = -EINVAL; + return 0; + } + + return (GPIO_OUTPUT | GPIO_OUTPUT_SET | GPIO_SPEED_50MHz | GPIO_FLOAT | + port_base | gpio_pin); +} + +/**************************************************************************** + * Name: stm32_st7796_gpio_initialize + * + * Description: + * Initialize GPIO pins for ST7796 (RESET, LED). + * + ****************************************************************************/ + +static int stm32_st7796_gpio_initialize(void) +{ + int ret; + int error; + + g_reset_pin = parse_gpio_pin(CONFIG_NUCLEO_H753ZI_ST7796_RESET_PIN, + &error); + if (error != 0) + { + syslog(LOG_ERR, "ERROR: Invalid RESET pin '%s': %d\n", + CONFIG_NUCLEO_H753ZI_ST7796_RESET_PIN, error); + return error; + } + + ret = stm32_configgpio(g_reset_pin); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to configure RESET pin: %d\n", ret); + return ret; + } + + g_led_pin = parse_gpio_pin(CONFIG_NUCLEO_H753ZI_ST7796_LED_PIN, &error); + if (error != 0) + { + syslog(LOG_ERR, "ERROR: Invalid LED pin '%s': %d\n", + CONFIG_NUCLEO_H753ZI_ST7796_LED_PIN, error); + return error; + } + + ret = stm32_configgpio(g_led_pin); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to configure LED pin: %d\n", ret); + return ret; + } + + stm32_gpiowrite(g_reset_pin, true); + stm32_gpiowrite(g_led_pin, false); /* Start with backlight OFF */ + + return OK; +} + +/**************************************************************************** + * Name: stm32_st7796_hardware_reset + * + * Description: + * Perform hardware reset of ST7796 display. + * + ****************************************************************************/ + +static void stm32_st7796_hardware_reset(void) +{ + stm32_gpiowrite(g_reset_pin, true); + nxsig_usleep(ST7796_RESET_DELAY_MS * 1000); + + stm32_gpiowrite(g_reset_pin, false); + nxsig_usleep(ST7796_RESET_HOLD_MS * 1000); + + stm32_gpiowrite(g_reset_pin, true); + nxsig_usleep(ST7796_RESET_RELEASE_MS * 1000); +} + +/**************************************************************************** + * Name: stm32_st7796_spi_initialize + * + * Description: + * Initialize SPI bus and register CS/DC pins for ST7796. + * + ****************************************************************************/ + +static int stm32_st7796_spi_initialize(void) +{ + int ret; + + stm32_st7796_hardware_reset(); + + ret = stm32_spi_register_cs_device(ST7796_SPI_PORTNO, + CONFIG_NUCLEO_H753ZI_ST7796_DEVID, + CONFIG_NUCLEO_H753ZI_ST7796_CS_PIN, + CONFIG_NUCLEO_H753ZI_ST7796_CS_ACTIVE_LOW); + + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to register CS: %d\n", ret); + return ret; + } + + ret = stm32_spi_register_dc_pin(ST7796_SPI_PORTNO, + CONFIG_NUCLEO_H753ZI_ST7796_DEVID, + CONFIG_NUCLEO_H753ZI_ST7796_DC_PIN); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to register DC: %d\n", ret); + stm32_spi_unregister_cs_device(ST7796_SPI_PORTNO, + CONFIG_NUCLEO_H753ZI_ST7796_DEVID); + return ret; + } + + g_spi_dev = stm32_spibus_initialize(ST7796_SPI_PORTNO); + if (g_spi_dev == NULL) + { + syslog(LOG_ERR, "ERROR: Failed to initialize SPI%d\n", + ST7796_SPI_PORTNO); + stm32_spi_unregister_cs_device(ST7796_SPI_PORTNO, + CONFIG_NUCLEO_H753ZI_ST7796_DEVID); + return -ENODEV; + } + + g_st7796_initialized = true; + + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_fbinitialize + * + * Description: + * Initialize the framebuffer video hardware. Called by fb_register(). + * + ****************************************************************************/ + +int up_fbinitialize(int display) +{ + if (!g_st7796_initialized || g_spi_dev == NULL) + { + syslog(LOG_ERR, "ERROR: ST7796 not initialized\n"); + return -ENODEV; + } + + if (display != 0) + { + syslog(LOG_ERR, "ERROR: Invalid display: %d\n", display); + return -EINVAL; + } + + g_fb_vtable = st7796_fbinitialize(g_spi_dev, &g_st7796_config); + if (g_fb_vtable == NULL) + { + syslog(LOG_ERR, "ERROR: st7796_fbinitialize() failed\n"); + return -ENODEV; + } + + return OK; +} + +/**************************************************************************** + * Name: up_fbgetvplane + * + * Description: + * Return a reference to the framebuffer object for the specified plane. + * + ****************************************************************************/ + +FAR struct fb_vtable_s *up_fbgetvplane(int display, int vplane) +{ + if (display != 0 || vplane != 0) + { + return NULL; + } + + return g_fb_vtable; +} + +/**************************************************************************** + * Name: up_fbuninitialize + * + * Description: + * Uninitialize the framebuffer hardware. + * + ****************************************************************************/ + +void up_fbuninitialize(int display) +{ + if (display != 0) + { + return; + } + + stm32_gpiowrite(g_led_pin, false); + g_fb_vtable = NULL; +} + +/**************************************************************************** + * Name: stm32_st7796initialize + * + * Description: + * Initialize and register the ST7796 LCD driver. + * Called from board bringup. + * + ****************************************************************************/ + +int stm32_st7796initialize(int devno) +{ + int ret; + + /* Step 1: Initialize GPIO pins (RESET, LED) */ + + ret = stm32_st7796_gpio_initialize(); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: GPIO init failed: %d\n", ret); + return ret; + } + + /* Step 2: Initialize SPI bus and register CS/DC */ + + ret = stm32_st7796_spi_initialize(); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: SPI init failed: %d\n", ret); + return ret; + } + + /* Step 3: Register framebuffer device + * This calls up_fbinitialize() which initializes the display + * and applies initial rotation from config + */ + + ret = fb_register(0, 0); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: fb_register() failed: %d\n", ret); + stm32_spi_unregister_cs_device(ST7796_SPI_PORTNO, + CONFIG_NUCLEO_H753ZI_ST7796_DEVID); + return ret; + } + + return OK; +} + +/**************************************************************************** + * Name: stm32_st7796_flush_fb + * + * Description: + * Flush the entire framebuffer to the display. Call this after + * fb_register() to make splashscreen visible on SPI displays. + * + ****************************************************************************/ + +int stm32_st7796_flush_fb(void) +{ + struct fb_area_s area; + + if (g_fb_vtable == NULL || g_fb_vtable->updatearea == NULL) + { + syslog(LOG_ERR, "ERROR: Framebuffer not ready for flush\n"); + return -ENODEV; + } + + area.x = 0; + area.y = 0; + area.w = ST7796_XRES; + area.h = ST7796_YRES; + + return g_fb_vtable->updatearea(g_fb_vtable, &area); +} + +/**************************************************************************** + * Name: stm32_st7796_backlight + * + * Description: + * Control backlight LED. + * + ****************************************************************************/ + +void stm32_st7796_backlight(bool on) +{ + stm32_gpiowrite(g_led_pin, on); +} + +/**************************************************************************** + * Name: stm32_st7796_power + * + * Description: + * Control display power. + * + ****************************************************************************/ + +void stm32_st7796_power(bool on) +{ + if (on) + { + stm32_st7796_hardware_reset(); + stm32_gpiowrite(g_led_pin, true); + } + else + { + stm32_gpiowrite(g_led_pin, false); + } +} + +/**************************************************************************** + * Name: stm32_st7796_reset_display + * + * Description: + * Public function to reset the display. + * + ****************************************************************************/ + +void stm32_st7796_reset_display(void) +{ + stm32_st7796_hardware_reset(); +} + +/**************************************************************************** + * Name: stm32_st7796_cleanup + * + * Description: + * Cleanup ST7796 resources. + * + ****************************************************************************/ + +int stm32_st7796_cleanup(void) +{ + int ret; + + stm32_gpiowrite(g_led_pin, false); + + stm32_configgpio((g_reset_pin & ST7796_GPIO_CONFIG_MASK) | + ST7796_GPIO_IN_FLOAT); + stm32_configgpio((g_led_pin & ST7796_GPIO_CONFIG_MASK) | + ST7796_GPIO_IN_FLOAT); + + ret = stm32_spi_unregister_cs_device(ST7796_SPI_PORTNO, + CONFIG_NUCLEO_H753ZI_ST7796_DEVID); + if (ret < 0) + { + syslog(LOG_WARNING, "WARNING: CS unregister failed: %d\n", ret); + } + + g_st7796_initialized = false; + g_spi_dev = NULL; + g_fb_vtable = NULL; + + return ret; +} + +#endif /* CONFIG_LCD_ST7796 && CONFIG_NUCLEO_H753ZI_ST7796_ENABLE */ diff --git a/boards/arm/stm32h7/nucleo-h753zi/src/stm32_uid.c b/boards/arm/stm32h7/nucleo-h753zi/src/stm32_uid.c new file mode 100644 index 0000000000000..9e76c34c082c8 --- /dev/null +++ b/boards/arm/stm32h7/nucleo-h753zi/src/stm32_uid.c @@ -0,0 +1,69 @@ +/**************************************************************************** + * boards/arm/stm32h7/nucleo-h753zi/src/stm32_uid.c + * + * SPDX-License-Identifier: BSD-3-Clause + * SPDX-FileCopyrightText: 2015 Marawan Ragab. All rights reserved. + * SPDX-FileContributor: Marawan Ragab + * SPDX-FileContributor: David Sidrane + * + * 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 NuttX 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 OWNER 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include "stm32_uid.h" + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +#if defined(CONFIG_BOARDCTL_UNIQUEID) +int board_uniqueid(uint8_t *uniqueid) +{ + if (uniqueid == NULL) + { + return -EINVAL; + } + + stm32_get_uniqueid(uniqueid); + return OK; +} +#endif diff --git a/boards/arm/stm32h7/nucleo-h753zi/src/stm32_usb.c b/boards/arm/stm32h7/nucleo-h753zi/src/stm32_usb.c new file mode 100644 index 0000000000000..bc94ce2b02171 --- /dev/null +++ b/boards/arm/stm32h7/nucleo-h753zi/src/stm32_usb.c @@ -0,0 +1,322 @@ +/**************************************************************************** + * boards/arm/stm32h7/nucleo-h753zi/src/stm32_usb.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "arm_internal.h" +#include "chip.h" +#include "stm32_gpio.h" +#include "stm32_otg.h" +#include "nucleo-h753zi.h" + +#ifdef CONFIG_STM32H7_OTGFS + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#if defined(CONFIG_USBDEV) || defined(CONFIG_USBHOST) +# define HAVE_USB 1 +#else +# warning "CONFIG_STM32_OTGFS is enabled but neither CONFIG_USBDEV nor CONFIG_USBHOST" +# undef HAVE_USB +#endif + +#ifndef CONFIG_NUCLEOH753ZI_USBHOST_PRIO +# define CONFIG_NUCLEOH753ZI_USBHOST_PRIO 100 +#endif + +#ifndef CONFIG_NUCLEOH753ZI_USBHOST_STACKSIZE +# define CONFIG_NUCLEOH753ZI_USBHOST_STACKSIZE 2048 +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +#ifdef CONFIG_USBHOST +static struct usbhost_connection_s *g_usbconn; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: usbhost_waiter + * + * Description: + * Wait for USB devices to be connected. + * + ****************************************************************************/ + +#ifdef CONFIG_USBHOST +static int usbhost_waiter(int argc, char *argv[]) +{ + struct usbhost_hubport_s *hport; + + uinfo("Running\n"); + for (; ; ) + { + /* Wait for the device to change state */ + + DEBUGVERIFY(CONN_WAIT(g_usbconn, &hport)); + uinfo("%s\n", hport->connected ? "connected" : "disconnected"); + + /* Did we just become connected? */ + + if (hport->connected) + { + /* Yes.. enumerate the newly connected device */ + + CONN_ENUMERATE(g_usbconn, hport); + } + } + + /* Keep the compiler from complaining */ + + return 0; +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_usbinitialize + * + * Description: + * Called from stm32_usbinitialize very early in initialization to setup + * USB-related GPIO pins for the nucleo-144 board. + * + ****************************************************************************/ + +void stm32_usbinitialize(void) +{ + /* The OTG FS has an internal soft pull-up. + * No GPIO configuration is required + */ + + /* Configure the OTG FS VBUS sensing GPIO, + * Power On, and Overcurrent GPIOs + */ + +#ifdef CONFIG_STM32H7_OTGFS + stm32_configgpio(GPIO_OTGFS_VBUS); + stm32_configgpio(GPIO_OTGFS_PWRON); + stm32_configgpio(GPIO_OTGFS_OVER); +#endif +} + +/**************************************************************************** + * Name: stm32_usbhost_initialize + * + * Description: + * Called at application startup time to initialize the USB host + * functionality. + * This function will start a thread that will monitor for device + * connection/disconnection events. + * + ****************************************************************************/ + +#ifdef CONFIG_USBHOST +int stm32_usbhost_initialize(void) +{ + int ret; + + /* First, register all of the class drivers needed to support the drivers + * that we care about: + */ + + uinfo("Register class drivers\n"); + +#ifdef CONFIG_USBHOST_HUB + /* Initialize USB hub class support */ + + ret = usbhost_hub_initialize(); + if (ret < 0) + { + uerr("ERROR: usbhost_hub_initialize failed: %d\n", ret); + } +#endif + +#ifdef CONFIG_USBHOST_MSC + /* Register the USB mass storage class class */ + + ret = usbhost_msc_initialize(); + if (ret != OK) + { + uerr("ERROR: Failed to register the mass storage class: %d\n", ret); + } +#endif + +#ifdef CONFIG_USBHOST_CDCACM + /* Register the CDC/ACM serial class */ + + ret = usbhost_cdcacm_initialize(); + if (ret != OK) + { + uerr("ERROR: Failed to register the CDC/ACM serial class: %d\n", ret); + } +#endif + +#ifdef CONFIG_USBHOST_HIDKBD + /* Initialize the HID keyboard class */ + + ret = usbhost_kbdinit(); + if (ret != OK) + { + uerr("ERROR: Failed to register the HID keyboard class\n"); + } +#endif + +#ifdef CONFIG_USBHOST_HIDMOUSE + /* Initialize the HID mouse class */ + + ret = usbhost_mouse_init(); + if (ret != OK) + { + uerr("ERROR: Failed to register the HID mouse class\n"); + } +#endif + + /* Then get an instance of the USB host interface */ + + uinfo("Initialize USB host\n"); + g_usbconn = stm32_otgfshost_initialize(0); + if (g_usbconn) + { + /* Start a thread to handle device connection. */ + + uinfo("Start usbhost_waiter\n"); + + ret = kthread_create("usbhost", CONFIG_NUCLEOH753ZI_USBHOST_PRIO, + CONFIG_NUCLEOH753ZI_USBHOST_STACKSIZE, + usbhost_waiter, NULL); + return ret < 0 ? -ENOEXEC : OK; + } + + return -ENODEV; +} +#endif + +/**************************************************************************** + * Name: stm32_usbhost_vbusdrive + * + * Description: + * Enable/disable driving of VBUS 5V output. This function must be + * provided be each platform that implements the STM32 OTG FS host + * interface + * + * "On-chip 5 V VBUS generation is not supported. For this reason, a + * charge pump or, if 5 V are available on the application board, a + * basic power switch, must be added externally to drive the 5 V VBUS + * line. The external charge pump can be driven by any GPIO output. + * When the application decides to power on VBUS using the chosen GPIO, + * it must also set the port power bit in the host port control and status + * register (PPWR bit in OTG_FS_HPRT). + * + * "The application uses this field to control power to this port, and + * the core clears this bit on an overcurrent condition." + * + * Input Parameters: + * iface - For future growth to handle multiple USB host interface. + * Should be zero. + * enable - true: enable VBUS power; false: disable VBUS power + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef CONFIG_USBHOST +void stm32_usbhost_vbusdrive(int iface, bool enable) +{ + DEBUGASSERT(iface == 0); + + /* Set the Power Switch by driving the active high enable pin */ + + stm32_gpiowrite(GPIO_OTGFS_PWRON, enable); +} +#endif + +/**************************************************************************** + * Name: stm32_setup_overcurrent + * + * Description: + * Setup to receive an interrupt-level callback if an overcurrent + * condition is detected. + * + * Input Parameters: + * handler - New overcurrent interrupt handler + * arg - The argument provided for the interrupt handler + * + * Returned Value: + * Zero (OK) is returned on success. Otherwise, a negated errno value + * is returned to indicate the nature of the failure. + * + ****************************************************************************/ + +#ifdef CONFIG_USBHOST +int stm32_setup_overcurrent(xcpt_t handler, void *arg) +{ + return stm32_gpiosetevent(GPIO_OTGFS_OVER, true, true, true, handler, arg); +} +#endif + +/**************************************************************************** + * Name: stm32_usbsuspend + * + * Description: + * Board logic must provide the stm32_usbsuspend logic if the USBDEV + * driver is used. This function is called whenever the USB enters or + * leaves suspend mode. This is an opportunity for the board logic to + * shutdown clocks, power, etc. while the USB is suspended. + * + ****************************************************************************/ + +#ifdef CONFIG_USBDEV +void stm32_usbsuspend(struct usbdev_s *dev, bool resume) +{ + uinfo("resume: %d\n", resume); +} +#endif + +#endif /* CONFIG_STM32_OTGFS */ diff --git a/boards/arm/stm32h7/nucleo-h753zi/src/stm32_usbmsc.c b/boards/arm/stm32h7/nucleo-h753zi/src/stm32_usbmsc.c new file mode 100644 index 0000000000000..22c06c5488360 --- /dev/null +++ b/boards/arm/stm32h7/nucleo-h753zi/src/stm32_usbmsc.c @@ -0,0 +1,61 @@ +/**************************************************************************** + * boards/arm/stm32h7/nucleo-h753zi/src/stm32_usbmsc.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_usbmsc_initialize + * + * Description: + * Perform architecture specific initialization as needed to establish + * the mass storage device that will be exported by the USB MSC device. + * + ****************************************************************************/ + +int board_usbmsc_initialize(int port) +{ + /* If system/usbmsc is built as an NSH command, then SD slot should + * already have been initialized in board_app_initialize() + * (see stm32_appinit.c). + * In this case, there is nothing further to be done here. + */ + +#ifndef CONFIG_NSH_BUILTIN_APPS + stm32_mmcsd_initialize(0); +#else + return OK; +#endif +} diff --git a/boards/arm/stm32h7/nucleo-h753zi/src/stm32_userleds.c b/boards/arm/stm32h7/nucleo-h753zi/src/stm32_userleds.c new file mode 100644 index 0000000000000..222ccb5c2f286 --- /dev/null +++ b/boards/arm/stm32h7/nucleo-h753zi/src/stm32_userleds.c @@ -0,0 +1,129 @@ +/**************************************************************************** + * boards/arm/stm32h7/nucleo-h753zi/src/stm32_userleds.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include + +#include +#include + +#include "stm32_gpio.h" +#include "nucleo-h753zi.h" + +#ifndef CONFIG_ARCH_LEDS + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* This array maps an LED number to GPIO pin configuration and is indexed by + * BOARD_LED_ + */ + +static const uint32_t g_ledcfg[BOARD_NLEDS] = +{ + GPIO_LED_GREEN, + GPIO_LED_ORANGE, + GPIO_LED_RED, +}; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_userled_initialize + * + * Description: + * If CONFIG_ARCH_LEDS is defined, then NuttX will control the on-board + * LEDs. If CONFIG_ARCH_LEDS is not defined, then the + * board_userled_initialize() is available to initialize the LED from user + * application logic. + * + ****************************************************************************/ + +uint32_t board_userled_initialize(void) +{ + int i; + + /* Configure LED1-3 GPIOs for output */ + + for (i = 0; i < nitems(g_ledcfg); i++) + { + stm32_configgpio(g_ledcfg[i]); + } + + return BOARD_NLEDS; +} + +/**************************************************************************** + * Name: board_userled + * + * Description: + * If CONFIG_ARCH_LEDS is defined, then NuttX will control the on-board + * LEDs. If CONFIG_ARCH_LEDS is not defined, then the board_userled() is + * available to control the LED from user application logic. + * + ****************************************************************************/ + +void board_userled(int led, bool ledon) +{ + if ((unsigned)led < nitems(g_ledcfg)) + { + stm32_gpiowrite(g_ledcfg[led], ledon); + } +} + +/**************************************************************************** + * Name: board_userled_all + * + * Description: + * If CONFIG_ARCH_LEDS is defined, then NuttX will control the on-board + * LEDs. If CONFIG_ARCH_LEDS is not defined, then board_userled_all() + * is available to control all LEDs from user application logic. + * This function allows controlling multiple LEDs simultaneously using + * a bitmask, which is more efficient than calling board_userled() + * individually for each LED. + * + ****************************************************************************/ + +void board_userled_all(uint32_t ledset) +{ + int i; + + /* Configure LED1-3 GPIOs for output */ + + for (i = 0; i < nitems(g_ledcfg); i++) + { + stm32_gpiowrite(g_ledcfg[i], (ledset & (1 << i)) != 0); + } +} + +#endif /* !CONFIG_ARCH_LEDS */