From 655aea948e8d1c5e77cd2a9b85cd45bf864df72d Mon Sep 17 00:00:00 2001 From: Rbb666 Date: Fri, 31 Jul 2026 15:22:03 +0800 Subject: [PATCH] feat(stm32): add GPIO and EXTI device model drivers Add device-tree GPIO/EXTI controllers, built-in DTB support for GCC and ArmClang, and BSP integration for STM32F407 RT-Spark and STM32H750 ART-Pi. Document how BSP users enable the DM drivers. --- .../libraries/HAL_Drivers/drivers/SConscript | 7 +- .../HAL_Drivers/drivers/dm/SConscript | 30 ++ .../HAL_Drivers/drivers/dm/builtin_fdt_ac6.c | 21 + .../HAL_Drivers/drivers/dm/builtin_fdt_gcc.S | 17 + .../HAL_Drivers/drivers/dm/drv_exti.c | 425 +++++++++++++++ .../HAL_Drivers/drivers/dm/drv_exti.h | 22 + .../HAL_Drivers/drivers/dm/drv_gpio.c | 501 ++++++++++++++++++ .../libraries/HAL_Drivers/drivers/drv_gpio.h | 4 + bsp/stm32/libraries/HAL_Drivers/drv_common.c | 28 +- bsp/stm32/stm32f407-rt-spark/Kconfig | 10 + bsp/stm32/stm32f407-rt-spark/README.md | 10 + bsp/stm32/stm32f407-rt-spark/README_EN.md | 10 + bsp/stm32/stm32f407-rt-spark/SConstruct | 22 + .../stm32f407-rt-spark/applications/main.c | 10 + .../board/dts/stm32f407-rt-spark.dts | 131 +++++ .../board/linker_scripts/link.lds | 5 + bsp/stm32/stm32f407-rt-spark/rtconfig.py | 2 + bsp/stm32/stm32h750-artpi/Kconfig | 10 + bsp/stm32/stm32h750-artpi/README.md | 12 +- bsp/stm32/stm32h750-artpi/SConstruct | 22 + bsp/stm32/stm32h750-artpi/applications/main.c | 12 +- .../board/dts/stm32h750-artpi.dts | 145 +++++ .../board/linker_scripts/link.lds | 5 + bsp/stm32/stm32h750-artpi/rtconfig.py | 2 + 24 files changed, 1456 insertions(+), 7 deletions(-) create mode 100644 bsp/stm32/libraries/HAL_Drivers/drivers/dm/SConscript create mode 100644 bsp/stm32/libraries/HAL_Drivers/drivers/dm/builtin_fdt_ac6.c create mode 100644 bsp/stm32/libraries/HAL_Drivers/drivers/dm/builtin_fdt_gcc.S create mode 100644 bsp/stm32/libraries/HAL_Drivers/drivers/dm/drv_exti.c create mode 100644 bsp/stm32/libraries/HAL_Drivers/drivers/dm/drv_exti.h create mode 100644 bsp/stm32/libraries/HAL_Drivers/drivers/dm/drv_gpio.c create mode 100644 bsp/stm32/stm32f407-rt-spark/board/dts/stm32f407-rt-spark.dts create mode 100644 bsp/stm32/stm32h750-artpi/board/dts/stm32h750-artpi.dts diff --git a/bsp/stm32/libraries/HAL_Drivers/drivers/SConscript b/bsp/stm32/libraries/HAL_Drivers/drivers/SConscript index bd717ad885..cabd8aad61 100644 --- a/bsp/stm32/libraries/HAL_Drivers/drivers/SConscript +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/SConscript @@ -11,7 +11,10 @@ src = [] src += ['drv_dma.c'] path = [cwd] -if GetDepend(['RT_USING_PIN']): +if GetDepend(['RT_USING_DM']): + group += SConscript(os.path.join('dm', 'SConscript')) + +elif GetDepend(['RT_USING_PIN']): src += ['drv_gpio.c'] if GetDepend(['RT_USING_SERIAL']): @@ -137,6 +140,6 @@ path += [os.path.join(cwd, 'config')] if GetDepend('BSP_USING_ON_CHIP_FLASH'): path += [os.path.join(cwd, 'drv_flash')] -group = DefineGroup('Drivers', src, depend = [''], CPPPATH = path) +group += DefineGroup('Drivers', src, depend = [''], CPPPATH = path) Return('group') diff --git a/bsp/stm32/libraries/HAL_Drivers/drivers/dm/SConscript b/bsp/stm32/libraries/HAL_Drivers/drivers/dm/SConscript new file mode 100644 index 0000000000..05003be161 --- /dev/null +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/dm/SConscript @@ -0,0 +1,30 @@ +Import('RTT_ROOT') +Import('rtconfig') + +from building import * +import os + +cwd = GetCurrentDir() +parent = os.path.dirname(cwd) +src = ['drv_exti.c'] + +if GetDepend(['BSP_USING_GPIO']): + src += ['drv_gpio.c'] +path = [ + cwd, + parent, + os.path.join(parent, 'config'), + os.path.join(RTT_ROOT, 'components', 'drivers', 'pin'), +] + +group = [] + +group += DefineGroup('STM32 DM Drivers', src, + depend = ['RT_USING_DM'], + CPPPATH = path) + +if rtconfig.PLATFORM == 'armclang': + group += DefineGroup('STM32 DM FDT', ['builtin_fdt_ac6.c'], + depend = ['RT_USING_BUILTIN_FDT'], CPPPATH = [cwd]) + +Return('group') diff --git a/bsp/stm32/libraries/HAL_Drivers/drivers/dm/builtin_fdt_ac6.c b/bsp/stm32/libraries/HAL_Drivers/drivers/dm/builtin_fdt_ac6.c new file mode 100644 index 0000000000..d2fabd6922 --- /dev/null +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/dm/builtin_fdt_ac6.c @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2006-2026, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#define FDT_STRINGIFY_(value) #value +#define FDT_STRINGIFY(value) FDT_STRINGIFY_(value) + +#ifdef RT_BUILTIN_FDT_PATH +__asm( + ".section .rodata.dtb, \"a\", %progbits\n" + ".balign 8\n" + ".global rt_hw_builtin_fdt\n" + ".type rt_hw_builtin_fdt, %object\n" + "rt_hw_builtin_fdt:\n" + ".incbin " FDT_STRINGIFY(RT_BUILTIN_FDT_PATH) "\n" + ".size rt_hw_builtin_fdt, . - rt_hw_builtin_fdt\n"); +#endif diff --git a/bsp/stm32/libraries/HAL_Drivers/drivers/dm/builtin_fdt_gcc.S b/bsp/stm32/libraries/HAL_Drivers/drivers/dm/builtin_fdt_gcc.S new file mode 100644 index 0000000000..99cb997180 --- /dev/null +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/dm/builtin_fdt_gcc.S @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2006-2026, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + + .section .rodata.dtb, "a", %progbits + .balign 8 + .global rt_hw_builtin_fdt + .type rt_hw_builtin_fdt, %object +rt_hw_builtin_fdt: +#ifdef RT_BUILTIN_FDT_PATH + .incbin RT_BUILTIN_FDT_PATH +#endif + .size rt_hw_builtin_fdt, . - rt_hw_builtin_fdt diff --git a/bsp/stm32/libraries/HAL_Drivers/drivers/dm/drv_exti.c b/bsp/stm32/libraries/HAL_Drivers/drivers/dm/drv_exti.c new file mode 100644 index 0000000000..4a0db6ad56 --- /dev/null +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/dm/drv_exti.c @@ -0,0 +1,425 @@ +/* + * Copyright (c) 2006-2026, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2026-07-29 RTT the first version + */ + +#include +#include + +#define DBG_TAG "drv.exti" +#define DBG_LVL DBG_INFO +#include + +#include +#include + +#include "drv_exti.h" + +#define STM32_EXTI_LINE_NR 16 +#define STM32_EXTI_GROUP_NR 16 + +#if defined(SOC_SERIES_STM32H7) +#define STM32_EXTI_IMR (EXTI->IMR1) +#define STM32_EXTI_RTSR (EXTI->RTSR1) +#define STM32_EXTI_FTSR (EXTI->FTSR1) +#else +#define STM32_EXTI_IMR (EXTI->IMR) +#define STM32_EXTI_RTSR (EXTI->RTSR) +#define STM32_EXTI_FTSR (EXTI->FTSR) +#endif + +struct stm32_exti_group +{ + struct stm32_exti *exti; + int parent_irq; + rt_uint32_t line_mask; + char name[RT_NAME_MAX]; +}; + +struct stm32_exti +{ + struct rt_pic parent; + struct rt_spinlock lock; + GPIO_TypeDef *owners[STM32_EXTI_LINE_NR]; + struct stm32_exti_group groups[STM32_EXTI_GROUP_NR]; + rt_uint8_t group_nr; +}; + +static struct stm32_exti _exti; + +static rt_uint32_t exti_line_mask(int line) +{ + return RT_BIT(line); +} + +static void exti_irq_mask(struct rt_pic_irq *pirq) +{ + STM32_EXTI_IMR &= ~exti_line_mask(pirq->hwirq); +} + +static void exti_irq_unmask(struct rt_pic_irq *pirq) +{ + STM32_EXTI_IMR |= exti_line_mask(pirq->hwirq); +} + +static void exti_irq_ack(struct rt_pic_irq *pirq) +{ + __HAL_GPIO_EXTI_CLEAR_IT(exti_line_mask(pirq->hwirq)); +} + +static rt_err_t exti_irq_set_trigger(struct rt_pic_irq *pirq, rt_uint32_t mode) +{ + rt_uint32_t mask = exti_line_mask(pirq->hwirq); + + switch (mode) + { + case RT_IRQ_MODE_EDGE_RISING: + STM32_EXTI_RTSR |= mask; + STM32_EXTI_FTSR &= ~mask; + break; + + case RT_IRQ_MODE_EDGE_FALLING: + STM32_EXTI_RTSR &= ~mask; + STM32_EXTI_FTSR |= mask; + break; + + case RT_IRQ_MODE_EDGE_BOTH: + STM32_EXTI_RTSR |= mask; + STM32_EXTI_FTSR |= mask; + break; + + default: + return -RT_ENOSYS; + } + + pirq->mode = mode; + + return RT_EOK; +} + +static int exti_irq_map(struct rt_pic *pic, int hwirq, rt_uint32_t mode) +{ + int irq; + struct rt_pic_irq *pirq; + + if (hwirq < 0 || hwirq >= STM32_EXTI_LINE_NR) + { + return -RT_EINVAL; + } + + pirq = rt_pic_find_irq(pic, hwirq); + irq = rt_pic_config_irq(pic, hwirq, hwirq); + + if (irq >= 0 && mode != RT_IRQ_MODE_NONE) + { + if (exti_irq_set_trigger(pirq, mode)) + { + irq = -RT_EINVAL; + } + } + + return irq; +} + +static rt_err_t exti_irq_parse(struct rt_pic *pic, + struct rt_ofw_cell_args *args, struct rt_pic_irq *out_pirq) +{ + if (args->args_count != 1 || args->args[0] >= pic->irq_nr) + { + return -RT_EINVAL; + } + + out_pirq->hwirq = args->args[0]; + out_pirq->mode = RT_IRQ_MODE_NONE; + + return RT_EOK; +} + +static const struct rt_pic_ops exti_ops = { + .name = "STM32-EXTI", + .irq_enable = exti_irq_unmask, + .irq_disable = exti_irq_mask, + .irq_ack = exti_irq_ack, + .irq_mask = exti_irq_mask, + .irq_unmask = exti_irq_unmask, + .irq_set_triger_mode = exti_irq_set_trigger, + .irq_map = exti_irq_map, + .irq_parse = exti_irq_parse, +}; + +static void exti_parent_isr(int vector, void *param) +{ + struct stm32_exti_group *group = param; + struct stm32_exti *exti = group->exti; + rt_uint32_t pending = STM32_EXTI_IMR & + __HAL_GPIO_EXTI_GET_IT(group->line_mask); + + RT_UNUSED(vector); + + while (pending) + { + int line = __rt_ffs(pending) - 1; + rt_uint32_t mask = exti_line_mask(line); + struct rt_pic_irq *pirq = rt_pic_find_irq(&exti->parent, line); + + pending &= ~mask; + __HAL_GPIO_EXTI_CLEAR_IT(mask); + if (pirq->irq >= 0) + { + rt_pic_handle_isr(pirq); + } + } +} + +struct stm32_exti *stm32_exti_get(struct rt_ofw_node *np) +{ + struct rt_pic *pic; + + if (!np || !(pic = rt_pic_dynamic_cast(rt_ofw_data(np))) || pic != &_exti.parent) + { + return RT_NULL; + } + + return &_exti; +} + +int stm32_exti_acquire(struct stm32_exti *exti, GPIO_TypeDef *gpio, + rt_base_t pin, rt_uint32_t irq_mode) +{ + int irq; + rt_ubase_t level; + + if (!exti || !gpio || pin < 0 || pin >= STM32_EXTI_LINE_NR) + { + return -RT_EINVAL; + } + + if (irq_mode != RT_IRQ_MODE_EDGE_RISING && + irq_mode != RT_IRQ_MODE_EDGE_FALLING && + irq_mode != RT_IRQ_MODE_EDGE_BOTH) + { + return -RT_ENOSYS; + } + + level = rt_spin_lock_irqsave(&exti->lock); + if (exti->owners[pin] && exti->owners[pin] != gpio) + { + rt_spin_unlock_irqrestore(&exti->lock, level); + return -RT_EBUSY; + } + exti->owners[pin] = gpio; + rt_spin_unlock_irqrestore(&exti->lock, level); + + __HAL_RCC_SYSCFG_CLK_ENABLE(); + irq = exti_irq_map(&exti->parent, pin, irq_mode); + if (irq < 0) + { + level = rt_spin_lock_irqsave(&exti->lock); + exti->owners[pin] = RT_NULL; + rt_spin_unlock_irqrestore(&exti->lock, level); + } + + return irq; +} + +rt_err_t stm32_exti_release(struct stm32_exti *exti, GPIO_TypeDef *gpio, + rt_base_t pin) +{ + rt_ubase_t level; + + if (!exti || !gpio || pin < 0 || pin >= STM32_EXTI_LINE_NR) + { + return -RT_EINVAL; + } + + level = rt_spin_lock_irqsave(&exti->lock); + if (exti->owners[pin] != gpio) + { + rt_spin_unlock_irqrestore(&exti->lock, level); + return -RT_EINVAL; + } + exti->owners[pin] = RT_NULL; + rt_spin_unlock_irqrestore(&exti->lock, level); + + exti_irq_mask(rt_pic_find_irq(&exti->parent, pin)); + + return RT_EOK; +} + +static void exti_init_fail(struct stm32_exti *exti) +{ + for (int i = 0; i < exti->group_nr; ++i) + { + struct stm32_exti_group *group = &exti->groups[i]; + + if (group->parent_irq >= 0) + { + rt_pic_irq_mask(group->parent_irq); + rt_pic_detach_irq(group->parent_irq, group); + } + } + + if (exti->parent.pirqs) + { + rt_pic_cancel_irq(&exti->parent); + } +} + +static rt_err_t exti_ofw_init(struct rt_ofw_node *np, + const struct rt_ofw_node_id *id) +{ + int irq_count, range_cells; + rt_err_t err = RT_EOK; + rt_uint32_t covered = 0; + struct stm32_exti *exti = &_exti; + + RT_UNUSED(id); + + if (exti->parent.ops) + { + return -RT_EBUSY; + } + + irq_count = rt_ofw_get_irq_count(np); + range_cells = rt_ofw_prop_count_of_u32(np, "line-ranges"); + if (irq_count <= 0 || irq_count > STM32_EXTI_GROUP_NR || + range_cells != irq_count * 2) + { + return -RT_EINVAL; + } + + exti->parent.priv_data = exti; + exti->parent.ops = &exti_ops; + rt_spin_lock_init(&exti->lock); + + if ((err = rt_pic_linear_irq(&exti->parent, STM32_EXTI_LINE_NR))) + { + exti->parent.ops = RT_NULL; + return err; + } + + for (int i = 0; i < irq_count; ++i) + { + rt_uint32_t start, count, range_mask; + struct stm32_exti_group *group = &exti->groups[i]; + + if (rt_ofw_prop_read_u32_index(np, "line-ranges", i * 2, &start) || + rt_ofw_prop_read_u32_index(np, "line-ranges", i * 2 + 1, &count) || + !count || start >= STM32_EXTI_LINE_NR || + count > STM32_EXTI_LINE_NR - start) + { + err = -RT_EINVAL; + break; + } + + range_mask = ((RT_BIT(count) - 1) << start); + if (covered & range_mask) + { + err = -RT_EINVAL; + break; + } + covered |= range_mask; + + group->exti = exti; + group->line_mask = range_mask; + group->parent_irq = rt_ofw_get_irq(np, i); + rt_snprintf(group->name, sizeof(group->name), "exti%d", i); + + if (group->parent_irq < 0 || + (err = rt_pic_attach_irq(group->parent_irq, exti_parent_isr, + group, group->name, RT_IRQ_F_NONE))) + { + if (group->parent_irq < 0) + { + err = group->parent_irq; + } + break; + } + ++exti->group_nr; + + for (int line = start; line < start + count; ++line) + { + int child_irq = rt_pic_config_irq(&exti->parent, line, line); + + /* Shared EXTI vectors must dispatch only lines with pending bits. */ + if (child_irq < 0) + { + err = child_irq; + break; + } + } + + if (err) + { + break; + } + } + + if (!err && covered != (RT_BIT(STM32_EXTI_LINE_NR) - 1)) + { + err = -RT_EINVAL; + } + + if (err) + { + exti_init_fail(exti); + exti->parent.ops = RT_NULL; + return err; + } + + rt_ofw_data(np) = &exti->parent; + rt_pic_user_extends(&exti->parent); + + for (int i = 0; i < exti->group_nr; ++i) + { + rt_pic_irq_unmask(exti->groups[i].parent_irq); + } + + return RT_EOK; +} + +static const struct rt_ofw_node_id exti_ofw_ids[] = { + { .compatible = "st,stm32-exti" }, + { /* sentinel */ } +}; +RT_PIC_OFW_DECLARE(stm32_exti, exti_ofw_ids, exti_ofw_init); + +void EXTI0_IRQHandler(void) +{ + rt_hw_nvic_dispatch(); +} + +void EXTI1_IRQHandler(void) +{ + rt_hw_nvic_dispatch(); +} + +void EXTI2_IRQHandler(void) +{ + rt_hw_nvic_dispatch(); +} + +void EXTI3_IRQHandler(void) +{ + rt_hw_nvic_dispatch(); +} + +void EXTI4_IRQHandler(void) +{ + rt_hw_nvic_dispatch(); +} + +void EXTI9_5_IRQHandler(void) +{ + rt_hw_nvic_dispatch(); +} + +void EXTI15_10_IRQHandler(void) +{ + rt_hw_nvic_dispatch(); +} diff --git a/bsp/stm32/libraries/HAL_Drivers/drivers/dm/drv_exti.h b/bsp/stm32/libraries/HAL_Drivers/drivers/dm/drv_exti.h new file mode 100644 index 0000000000..b0e07316ad --- /dev/null +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/dm/drv_exti.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2006-2026, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __DRV_EXTI_H__ +#define __DRV_EXTI_H__ + +#include +#include +#include + +struct stm32_exti; + +struct stm32_exti *stm32_exti_get(struct rt_ofw_node *np); +int stm32_exti_acquire(struct stm32_exti *exti, GPIO_TypeDef *gpio, + rt_base_t pin, rt_uint32_t irq_mode); +rt_err_t stm32_exti_release(struct stm32_exti *exti, GPIO_TypeDef *gpio, + rt_base_t pin); + +#endif /* __DRV_EXTI_H__ */ diff --git a/bsp/stm32/libraries/HAL_Drivers/drivers/dm/drv_gpio.c b/bsp/stm32/libraries/HAL_Drivers/drivers/dm/drv_gpio.c new file mode 100644 index 0000000000..86b3ea151a --- /dev/null +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/dm/drv_gpio.c @@ -0,0 +1,501 @@ +/* + * Copyright (c) 2006-2026, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2026-07-29 RTT the first version + */ + +#include +#include + +#define DBG_TAG "drv.gpio.dm" +#define DBG_LVL DBG_INFO +#include + +#include +#include +#include +#include + +#include "dev_pin_dm.h" +#include "drv_exti.h" + +#define STM32_GPIO_PIN_NR 16 + +struct stm32_gpio_irq +{ + int irq; + rt_uint8_t mode; + rt_bool_t acquired; + rt_bool_t pic_attached; + rt_bool_t enabled; + void (*handler)(void *args); + void *args; +}; + +struct stm32_gpio +{ + struct rt_device_pin parent; + GPIO_TypeDef *gpio; + struct stm32_exti *exti; + rt_uint32_t pulls[STM32_GPIO_PIN_NR]; + struct stm32_gpio_irq irqs[STM32_GPIO_PIN_NR]; +}; + +static struct stm32_gpio *device_to_stm32_gpio(struct rt_device *device) +{ + struct rt_device_pin *pin = rt_container_of(device, struct rt_device_pin, parent); + + return rt_container_of(pin, struct stm32_gpio, parent); +} + +static rt_err_t stm32_gpio_resolve(rt_uint64_t address, GPIO_TypeDef **out_gpio) +{ +#define STM32_GPIO_CASE(port) \ + if (address == (rt_ubase_t)GPIO##port) \ + { \ + __HAL_RCC_GPIO##port##_CLK_ENABLE(); \ + *out_gpio = GPIO##port; \ + return RT_EOK; \ + } + +#if defined(GPIOA) + STM32_GPIO_CASE(A); +#endif +#if defined(GPIOB) + STM32_GPIO_CASE(B); +#endif +#if defined(GPIOC) + STM32_GPIO_CASE(C); +#endif +#if defined(GPIOD) + STM32_GPIO_CASE(D); +#endif +#if defined(GPIOE) + STM32_GPIO_CASE(E); +#endif +#if defined(GPIOF) + STM32_GPIO_CASE(F); +#endif +#if defined(GPIOG) + STM32_GPIO_CASE(G); +#endif +#if defined(GPIOH) + STM32_GPIO_CASE(H); +#endif +#if defined(GPIOI) + STM32_GPIO_CASE(I); +#endif +#if defined(GPIOJ) + STM32_GPIO_CASE(J); +#endif +#if defined(GPIOK) + STM32_GPIO_CASE(K); +#endif + +#undef STM32_GPIO_CASE + + return -RT_EINVAL; +} + +static void stm32_gpio_mode(struct rt_device *device, rt_base_t pin, rt_uint8_t mode) +{ + GPIO_InitTypeDef gpio_init = { 0 }; + struct stm32_gpio *gpio = device_to_stm32_gpio(device); + + if (pin < 0 || pin >= STM32_GPIO_PIN_NR) + { + return; + } + + gpio_init.Pin = RT_BIT(pin); + gpio_init.Speed = GPIO_SPEED_FREQ_HIGH; + + switch (mode) + { + case PIN_MODE_OUTPUT: + gpio_init.Mode = GPIO_MODE_OUTPUT_PP; + gpio_init.Pull = GPIO_NOPULL; + break; + + case PIN_MODE_INPUT: + gpio_init.Mode = GPIO_MODE_INPUT; + gpio_init.Pull = GPIO_NOPULL; + break; + + case PIN_MODE_INPUT_PULLUP: + gpio_init.Mode = GPIO_MODE_INPUT; + gpio_init.Pull = GPIO_PULLUP; + break; + + case PIN_MODE_INPUT_PULLDOWN: + gpio_init.Mode = GPIO_MODE_INPUT; + gpio_init.Pull = GPIO_PULLDOWN; + break; + + case PIN_MODE_OUTPUT_OD: + gpio_init.Mode = GPIO_MODE_OUTPUT_OD; + gpio_init.Pull = GPIO_NOPULL; + break; + + default: + return; + } + + gpio->pulls[pin] = gpio_init.Pull; + HAL_GPIO_Init(gpio->gpio, &gpio_init); +} + +static void stm32_gpio_write(struct rt_device *device, rt_base_t pin, rt_uint8_t value) +{ + struct stm32_gpio *gpio = device_to_stm32_gpio(device); + + if (pin >= 0 && pin < STM32_GPIO_PIN_NR) + { + HAL_GPIO_WritePin(gpio->gpio, RT_BIT(pin), + value == PIN_LOW ? GPIO_PIN_RESET : GPIO_PIN_SET); + } +} + +static rt_ssize_t stm32_gpio_read(struct rt_device *device, rt_base_t pin) +{ + struct stm32_gpio *gpio = device_to_stm32_gpio(device); + + if (pin < 0 || pin >= STM32_GPIO_PIN_NR) + { + return -RT_EINVAL; + } + + return HAL_GPIO_ReadPin(gpio->gpio, RT_BIT(pin)) == GPIO_PIN_RESET ? PIN_LOW : PIN_HIGH; +} + +static rt_err_t stm32_gpio_irq_prepare(struct stm32_gpio *gpio, rt_base_t pin, + rt_uint8_t mode, GPIO_InitTypeDef *gpio_init, rt_uint32_t *irq_mode) +{ + gpio_init->Pin = RT_BIT(pin); + gpio_init->Pull = gpio->pulls[pin]; + gpio_init->Speed = GPIO_SPEED_FREQ_HIGH; + + switch (mode) + { + case PIN_IRQ_MODE_RISING: + gpio_init->Mode = GPIO_MODE_IT_RISING; + *irq_mode = RT_IRQ_MODE_EDGE_RISING; + break; + + case PIN_IRQ_MODE_FALLING: + gpio_init->Mode = GPIO_MODE_IT_FALLING; + *irq_mode = RT_IRQ_MODE_EDGE_FALLING; + break; + + case PIN_IRQ_MODE_RISING_FALLING: + gpio_init->Mode = GPIO_MODE_IT_RISING_FALLING; + *irq_mode = RT_IRQ_MODE_EDGE_BOTH; + break; + + default: + return -RT_ENOSYS; + } + + return RT_EOK; +} + +static void stm32_gpio_irq_handler(int vector, void *param) +{ + struct stm32_gpio_irq *irq = param; + + RT_UNUSED(vector); + + if (irq->handler) + { + irq->handler(irq->args); + } +} + +static rt_err_t stm32_gpio_attach_irq(struct rt_device *device, rt_base_t pin, + rt_uint8_t mode, void (*handler)(void *args), void *args) +{ + struct stm32_gpio_irq *irq; + struct stm32_gpio *gpio = device_to_stm32_gpio(device); + + if (pin < 0 || pin >= STM32_GPIO_PIN_NR || !handler) + { + return -RT_EINVAL; + } + + irq = &gpio->irqs[pin]; + if (irq->handler && (irq->handler != handler || irq->args != args)) + { + return -RT_EBUSY; + } + + irq->mode = mode; + irq->handler = handler; + irq->args = args; + + return RT_EOK; +} + +static rt_err_t stm32_gpio_irq_enable(struct rt_device *device, rt_base_t pin, + rt_uint8_t enabled) +{ + rt_err_t err, cleanup_err; + rt_bool_t was_enabled; + rt_uint32_t irq_mode; + struct stm32_gpio_irq *irq; + struct stm32_gpio *gpio = device_to_stm32_gpio(device); + GPIO_InitTypeDef gpio_init = { 0 }; + + if (pin < 0 || pin >= STM32_GPIO_PIN_NR) + { + return -RT_EINVAL; + } + + irq = &gpio->irqs[pin]; + if (enabled == PIN_IRQ_ENABLE) + { + if (!irq->handler) + { + return -RT_EINVAL; + } + if (irq->enabled) + { + return RT_EOK; + } + if ((err = stm32_gpio_irq_prepare(gpio, pin, irq->mode, + &gpio_init, &irq_mode))) + { + return err; + } + + if (!irq->acquired) + { + irq->irq = stm32_exti_acquire(gpio->exti, gpio->gpio, pin, + irq_mode); + if (irq->irq < 0) + { + return irq->irq; + } + irq->acquired = RT_TRUE; + } + + if (!irq->pic_attached) + { + err = rt_pic_attach_irq(irq->irq, stm32_gpio_irq_handler, + irq, "stm32-gpio", RT_IRQ_F_NONE); + if (err) + { + cleanup_err = stm32_exti_release(gpio->exti, gpio->gpio, + pin); + if (!cleanup_err) + { + irq->acquired = RT_FALSE; + irq->irq = -1; + } + + return cleanup_err ? cleanup_err : err; + } + irq->pic_attached = RT_TRUE; + } + + HAL_GPIO_Init(gpio->gpio, &gpio_init); + rt_pic_irq_unmask(irq->irq); + irq->enabled = RT_TRUE; + } + else if (enabled == PIN_IRQ_DISABLE) + { + if (!irq->acquired && !irq->pic_attached) + { + irq->enabled = RT_FALSE; + return RT_EOK; + } + + was_enabled = irq->enabled; + if (was_enabled) + { + rt_pic_irq_mask(irq->irq); + } + + if (irq->pic_attached) + { + err = rt_pic_detach_irq(irq->irq, irq); + if (err) + { + if (was_enabled) + { + rt_pic_irq_unmask(irq->irq); + } + return err; + } + irq->pic_attached = RT_FALSE; + } + + if (irq->acquired) + { + err = stm32_exti_release(gpio->exti, gpio->gpio, pin); + if (err) + { + cleanup_err = rt_pic_attach_irq(irq->irq, + stm32_gpio_irq_handler, irq, "stm32-gpio", + RT_IRQ_F_NONE); + if (!cleanup_err) + { + irq->pic_attached = RT_TRUE; + if (was_enabled) + { + rt_pic_irq_unmask(irq->irq); + } + } + else + { + irq->enabled = RT_FALSE; + } + + return cleanup_err ? cleanup_err : err; + } + irq->acquired = RT_FALSE; + irq->irq = -1; + HAL_GPIO_DeInit(gpio->gpio, RT_BIT(pin)); + } + + irq->enabled = RT_FALSE; + } + else + { + return -RT_EINVAL; + } + + return RT_EOK; +} + +static rt_err_t stm32_gpio_detach_irq(struct rt_device *device, rt_base_t pin) +{ + rt_err_t err; + struct stm32_gpio_irq *irq; + struct stm32_gpio *gpio = device_to_stm32_gpio(device); + + if (pin < 0 || pin >= STM32_GPIO_PIN_NR) + { + return -RT_EINVAL; + } + + irq = &gpio->irqs[pin]; + if ((irq->enabled || irq->pic_attached || irq->acquired) && + (err = stm32_gpio_irq_enable(device, pin, PIN_IRQ_DISABLE))) + { + return err; + } + + irq->handler = RT_NULL; + irq->args = RT_NULL; + irq->mode = 0; + + return RT_EOK; +} + +static rt_ssize_t stm32_gpio_parse(struct rt_device *device, + struct rt_ofw_cell_args *args, rt_uint32_t *flags) +{ + RT_UNUSED(device); + + if (args->args_count != 2 || args->args[0] >= STM32_GPIO_PIN_NR) + { + return -RT_EINVAL; + } + + if (flags) + { + *flags = args->args[1]; + } + + return args->args[0]; +} + +static const struct rt_pin_ops stm32_gpio_ops = { + .pin_mode = stm32_gpio_mode, + .pin_write = stm32_gpio_write, + .pin_read = stm32_gpio_read, + .pin_attach_irq = stm32_gpio_attach_irq, + .pin_detach_irq = stm32_gpio_detach_irq, + .pin_irq_enable = stm32_gpio_irq_enable, + .pin_parse = stm32_gpio_parse, +}; + +static rt_err_t stm32_gpio_probe(struct rt_platform_device *pdev) +{ + rt_err_t err; + rt_uint64_t address, size; + struct rt_ofw_node *exti_np; + struct rt_device *dev = &pdev->parent; + struct stm32_gpio *gpio = rt_calloc(1, sizeof(*gpio)); + + if (!gpio) + { + return -RT_ENOMEM; + } + + if ((err = rt_ofw_get_address(dev->ofw_node, 0, &address, &size)) || !size) + { + goto _fail; + } + + if ((err = stm32_gpio_resolve(address, &gpio->gpio))) + { + goto _fail; + } + + exti_np = rt_ofw_find_irq_parent(dev->ofw_node, RT_NULL); + if (!exti_np) + { + err = -RT_EINVAL; + goto _fail; + } + + gpio->exti = stm32_exti_get(exti_np); + rt_ofw_node_put(exti_np); + if (!gpio->exti) + { + err = -RT_EIO; + goto _fail; + } + + for (int i = 0; i < STM32_GPIO_PIN_NR; ++i) + { + gpio->irqs[i].irq = -1; + } + + gpio->parent.ops = &stm32_gpio_ops; + if ((err = pin_api_init(&gpio->parent, STM32_GPIO_PIN_NR))) + { + goto _fail; + } + + rt_dm_dev_bind_fwdata(dev, RT_NULL, &gpio->parent); + + return RT_EOK; + +_fail: + rt_free(gpio); + + return err; +} + +static const struct rt_ofw_node_id stm32_gpio_ofw_ids[] = { + { .compatible = "st,stm32-gpio" }, + { /* sentinel */ } +}; + +static struct rt_platform_driver stm32_gpio_driver = { + .name = "stm32-gpio", + .ids = stm32_gpio_ofw_ids, + .probe = stm32_gpio_probe, +}; + +static int stm32_gpio_driver_register(void) +{ + return rt_platform_driver_register(&stm32_gpio_driver); +} +INIT_SUBSYS_EXPORT(stm32_gpio_driver_register); diff --git a/bsp/stm32/libraries/HAL_Drivers/drivers/drv_gpio.h b/bsp/stm32/libraries/HAL_Drivers/drivers/drv_gpio.h index e7722aa173..d69e34ec52 100644 --- a/bsp/stm32/libraries/HAL_Drivers/drivers/drv_gpio.h +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/drv_gpio.h @@ -21,6 +21,8 @@ extern "C" { #endif +#ifndef RT_USING_DM + #define __STM32_PORT(port) GPIO##port##_BASE /** @@ -80,6 +82,8 @@ extern "C" { #define GET_PIN(PORTx,PIN) (rt_base_t)((16 * ( ((rt_base_t)__STM32_PORT(PORTx) - (rt_base_t)GPIOA_BASE)/(0x0400UL) )) + PIN) #endif +#endif /* !RT_USING_DM */ + struct pin_irq_map { rt_uint16_t pinbit; diff --git a/bsp/stm32/libraries/HAL_Drivers/drv_common.c b/bsp/stm32/libraries/HAL_Drivers/drv_common.c index e5e664f7d3..85752530c2 100644 --- a/bsp/stm32/libraries/HAL_Drivers/drv_common.c +++ b/bsp/stm32/libraries/HAL_Drivers/drv_common.c @@ -11,7 +11,14 @@ #include "drv_common.h" #include -#ifdef RT_USING_PIN +#ifdef RT_USING_BUILTIN_FDT +#include +#include + +extern const unsigned char rt_hw_builtin_fdt[]; +#endif + +#if defined(RT_USING_PIN) && !defined(RT_USING_DM) #include #endif @@ -196,7 +203,24 @@ rt_weak void rt_hw_board_init(void) rt_system_heap_init((void *)HEAP_BEGIN, (void *)HEAP_END); #endif -#ifdef RT_USING_PIN +#ifdef RT_USING_BUILTIN_FDT + if (rt_fdt_prefetch((void *)rt_hw_builtin_fdt) != RT_EOK || + rt_fdt_unflatten() != RT_EOK) + { + LOG_E("Builtin FDT initialization failed"); + RT_ASSERT(0); + } + +#ifdef RT_USING_PIC + if (rt_pic_init() != RT_EOK || rt_pic_irq_init() != RT_EOK) + { + LOG_E("PIC initialization failed"); + RT_ASSERT(0); + } +#endif +#endif + +#if defined(RT_USING_PIN) && !defined(RT_USING_DM) rt_hw_pin_init(); #endif diff --git a/bsp/stm32/stm32f407-rt-spark/Kconfig b/bsp/stm32/stm32f407-rt-spark/Kconfig index dd9f61c1d1..94919df482 100644 --- a/bsp/stm32/stm32f407-rt-spark/Kconfig +++ b/bsp/stm32/stm32f407-rt-spark/Kconfig @@ -11,13 +11,23 @@ config SOC_STM32F407ZG select SOC_SERIES_STM32F4 select RT_USING_COMPONENTS_INIT select RT_USING_USER_MAIN + select RT_USING_OFW if RT_USING_DM + select RT_USING_BUILTIN_FDT if RT_USING_DM + select RT_USING_PIC if RT_USING_DM + select RT_PIC_ARM_NVIC if RT_USING_DM + select RT_USING_PIN if RT_USING_DM default y config BOARD_STM32F407_SPARK bool default y +config RT_BUILTIN_FDT_PATH + string + default "board/dts/stm32f407-rt-spark.dtb" if RT_USING_DM + source "$(RTT_DIR)/Kconfig" + osource "$PKGS_DIR/Kconfig" rsource "../libraries/Kconfig" diff --git a/bsp/stm32/stm32f407-rt-spark/README.md b/bsp/stm32/stm32f407-rt-spark/README.md index 0f1ee88b81..511e72d682 100644 --- a/bsp/stm32/stm32f407-rt-spark/README.md +++ b/bsp/stm32/stm32f407-rt-spark/README.md @@ -113,6 +113,16 @@ msh > 本章节更多详细的介绍请参考 [STM32 系列 BSP 外设驱动使用教程](../docs/STM32系列BSP外设驱动使用教程.md)。 +### 启用设备模型(DM) + +本 BSP 通过 `RT_USING_DM` 在设备模型驱动和传统 BSP 驱动之间进行选择。启用 DM 后,GPIO 和 EXTI 使用设备树描述,传统的 STM32 GPIO 驱动不会参与构建。 + +1. 在当前 BSP 目录执行 `scons --menuconfig`。 +2. 进入 `Device Drivers`,选中 `Enable device driver model with device tree`。 +3. 保存配置后执行 `scons -jN` 构建 GCC 工程。 + +BSP 会随 `RT_USING_DM` 自动选择 OFW、内置 FDT、PIC、NVIC 和 PIN 框架,并使用 `board/dts/stm32f407-rt-spark.dts`。构建过程会生成并嵌入 DTB。 + ## 注意事项 暂无 diff --git a/bsp/stm32/stm32f407-rt-spark/README_EN.md b/bsp/stm32/stm32f407-rt-spark/README_EN.md index d38baf4846..a594528baa 100644 --- a/bsp/stm32/stm32f407-rt-spark/README_EN.md +++ b/bsp/stm32/stm32f407-rt-spark/README_EN.md @@ -113,6 +113,16 @@ This BSP only enables GPIO and Serial1 by default. If you want to use more advan For a more detailed description of this chapter, please refer to [STM32 Series BSP Peripheral Driver Tutorial](... /docs/STM32 Series BSP Peripheral Driver Tutorial.md). +### Enabling the Device Model (DM) + +This BSP uses `RT_USING_DM` to select either the device-model drivers or the legacy BSP drivers. When DM is enabled, GPIO and EXTI are described by the device tree and the legacy STM32 GPIO driver is excluded from the build. + +1. Run `scons --menuconfig` in this BSP directory. +2. Open `Device Drivers` and enable `Enable device driver model with device tree`. +3. Save the configuration and run `scons -jN` for a GCC build. + +The BSP automatically selects OFW, built-in FDT, PIC, NVIC, and PIN support with `RT_USING_DM`, and uses `board/dts/stm32f407-rt-spark.dts`. The build converts and embeds the DTB automatically. + ## Notes Not available at this time diff --git a/bsp/stm32/stm32f407-rt-spark/SConstruct b/bsp/stm32/stm32f407-rt-spark/SConstruct index 4fd099d3e0..067dd0d112 100644 --- a/bsp/stm32/stm32f407-rt-spark/SConstruct +++ b/bsp/stm32/stm32f407-rt-spark/SConstruct @@ -10,6 +10,7 @@ else: sys.path = sys.path + [os.path.join(RTT_ROOT, 'tools')] try: from building import * + import dtc except: print('Cannot found RT-Thread root directory, please check RTT_ROOT') print(RTT_ROOT) @@ -65,6 +66,27 @@ else: # prepare building environment objs = PrepareBuilding(env, RTT_ROOT, has_libcpu=False) +if GetDepend('RT_USING_BUILTIN_FDT'): + if os.getenv('DTC_PATH'): + os.environ['PATH'] = os.path.dirname(os.getenv('DTC_PATH')) + \ + os.pathsep + os.environ['PATH'] + + dtb_name = GetDepend('RT_BUILTIN_FDT_PATH').strip('"') + dts_name = os.path.splitext(dtb_name)[0] + '.dts' + dts_path = os.path.join(SDK_ROOT, dts_name) + dtc.dts_to_dtb(RTT_ROOT, [dts_name], + include_paths=[os.path.dirname(dts_path)]) + + if rtconfig.PLATFORM == 'gcc': + dtb_path = os.path.join(SDK_ROOT, dtb_name) + fdt_source = os.path.join(libraries_path_prefix, 'HAL_Drivers', + 'drivers', 'dm', 'builtin_fdt_gcc.S') + fdt_object = env.Object( + target=os.path.join(SDK_ROOT, 'build', 'dts', 'builtin_fdt_gcc.o'), + source=fdt_source) + env.Depends(fdt_object, dtb_path) + objs += fdt_object + rtconfig.BSP_LIBRARY_TYPE = None # include drivers diff --git a/bsp/stm32/stm32f407-rt-spark/applications/main.c b/bsp/stm32/stm32f407-rt-spark/applications/main.c index 38757e1edd..8c1e3f7ad0 100644 --- a/bsp/stm32/stm32f407-rt-spark/applications/main.c +++ b/bsp/stm32/stm32f407-rt-spark/applications/main.c @@ -16,10 +16,14 @@ #include #endif /* RT_USING_NANO */ +#ifndef RT_USING_DM #define GPIO_LED_B GET_PIN(F, 11) #define GPIO_LED_R GET_PIN(F, 12) +#endif + int main(void) { +#ifndef RT_USING_DM rt_pin_mode(GPIO_LED_R, PIN_MODE_OUTPUT); while (1) @@ -29,4 +33,10 @@ int main(void) rt_pin_write(GPIO_LED_R, PIN_LOW); rt_thread_mdelay(500); } +#else + while (1) + { + rt_thread_mdelay(1000); + } +#endif } diff --git a/bsp/stm32/stm32f407-rt-spark/board/dts/stm32f407-rt-spark.dts b/bsp/stm32/stm32f407-rt-spark/board/dts/stm32f407-rt-spark.dts new file mode 100644 index 0000000000..48d68dbd91 --- /dev/null +++ b/bsp/stm32/stm32f407-rt-spark/board/dts/stm32f407-rt-spark.dts @@ -0,0 +1,131 @@ +/dts-v1/; + +#include + +/ { + compatible = "st,stm32f407zg", "st,stm32f4"; + model = "RT-Thread STM32F407 RT-Spark"; + #address-cells = <1>; + #size-cells = <1>; + + aliases { + }; + + chosen { + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + compatible = "arm,cortex-m4"; + device_type = "cpu"; + reg = <0>; + }; + }; + + soc { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + interrupt-parent = <&nvic>; + + nvic: interrupt-controller@e000e100 { + compatible = "arm,v7m-nvic"; + reg = <0xe000e100 0xc00>; + interrupt-controller; + #interrupt-cells = <2>; + arm,num-irqs = <82>; + arm,num-irq-priority-bits = <4>; + }; + + exti: interrupt-controller@40013c00 { + compatible = "st,stm32-exti"; + reg = <0x40013c00 0x400>; + interrupt-controller; + #interrupt-cells = <1>; + #address-cells = <0>; + num-lines = <32>; + interrupts = <6 5>, <7 5>, <8 5>, <9 5>, + <10 5>, <23 5>, <40 5>; + interrupt-names = "line0", "line1", "line2", "line3", + "line4", "line5-9", "line10-15"; + line-ranges = <0 1>, <1 1>, <2 1>, <3 1>, + <4 1>, <5 5>, <10 6>; + }; + + gpioa: gpio@40020000 { + compatible = "st,stm32-gpio"; + reg = <0x40020000 0x400>; + gpio-controller; + #gpio-cells = <2>; + interrupt-parent = <&exti>; + }; + + gpiob: gpio@40020400 { + compatible = "st,stm32-gpio"; + reg = <0x40020400 0x400>; + gpio-controller; + #gpio-cells = <2>; + interrupt-parent = <&exti>; + }; + + gpioc: gpio@40020800 { + compatible = "st,stm32-gpio"; + reg = <0x40020800 0x400>; + gpio-controller; + #gpio-cells = <2>; + interrupt-parent = <&exti>; + }; + + gpiod: gpio@40020c00 { + compatible = "st,stm32-gpio"; + reg = <0x40020c00 0x400>; + gpio-controller; + #gpio-cells = <2>; + interrupt-parent = <&exti>; + }; + + gpioe: gpio@40021000 { + compatible = "st,stm32-gpio"; + reg = <0x40021000 0x400>; + gpio-controller; + #gpio-cells = <2>; + interrupt-parent = <&exti>; + }; + + gpiof: gpio@40021400 { + compatible = "st,stm32-gpio"; + reg = <0x40021400 0x400>; + gpio-controller; + #gpio-cells = <2>; + interrupt-parent = <&exti>; + }; + + gpiog: gpio@40021800 { + compatible = "st,stm32-gpio"; + reg = <0x40021800 0x400>; + gpio-controller; + #gpio-cells = <2>; + interrupt-parent = <&exti>; + }; + + gpioh: gpio@40021c00 { + compatible = "st,stm32-gpio"; + reg = <0x40021c00 0x400>; + gpio-controller; + #gpio-cells = <2>; + interrupt-parent = <&exti>; + }; + + gpioi: gpio@40022000 { + compatible = "st,stm32-gpio"; + reg = <0x40022000 0x400>; + gpio-controller; + #gpio-cells = <2>; + interrupt-parent = <&exti>; + }; + }; +}; diff --git a/bsp/stm32/stm32f407-rt-spark/board/linker_scripts/link.lds b/bsp/stm32/stm32f407-rt-spark/board/linker_scripts/link.lds index db56fb32d6..e3498025df 100644 --- a/bsp/stm32/stm32f407-rt-spark/board/linker_scripts/link.lds +++ b/bsp/stm32/stm32f407-rt-spark/board/linker_scripts/link.lds @@ -55,6 +55,11 @@ SECTIONS KEEP(*(SORT(.rti_fn*))) __rt_init_end = .; + /* section information for Open Firmware registration data */ + . = ALIGN(4); + KEEP(*(SORT(.rt_ofw_data.*))) + . = ALIGN(4); + . = ALIGN(4); PROVIDE(__ctors_start__ = .); diff --git a/bsp/stm32/stm32f407-rt-spark/rtconfig.py b/bsp/stm32/stm32f407-rt-spark/rtconfig.py index 83aea1098e..809369cabc 100644 --- a/bsp/stm32/stm32f407-rt-spark/rtconfig.py +++ b/bsp/stm32/stm32f407-rt-spark/rtconfig.py @@ -41,6 +41,7 @@ if PLATFORM == 'gcc': AS = PREFIX + 'gcc' AR = PREFIX + 'ar' CXX = PREFIX + 'g++' + CPP = PREFIX + 'gcc' LINK = PREFIX + 'gcc' TARGET_EXT = 'elf' SIZE = PREFIX + 'size' @@ -50,6 +51,7 @@ if PLATFORM == 'gcc': DEVICE = ' -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard -ffunction-sections -fdata-sections' CFLAGS = DEVICE + ' -Dgcc' AFLAGS = ' -c' + DEVICE + ' -x assembler-with-cpp -Wa,-mimplicit-it=thumb ' + CPPFLAGS = ' -E -P -x assembler-with-cpp' LFLAGS = DEVICE + ' -Wl,--gc-sections,-Map=rt-thread.map,-cref,-u,Reset_Handler -T board/linker_scripts/link.lds' CPATH = '' diff --git a/bsp/stm32/stm32h750-artpi/Kconfig b/bsp/stm32/stm32h750-artpi/Kconfig index 891b1195ab..3e3663d70e 100644 --- a/bsp/stm32/stm32h750-artpi/Kconfig +++ b/bsp/stm32/stm32h750-artpi/Kconfig @@ -12,6 +12,11 @@ config SOC_STM32H750XB select RT_USING_COMPONENTS_INIT select RT_USING_USER_MAIN select RT_USING_CACHE + select RT_USING_OFW if RT_USING_DM + select RT_USING_BUILTIN_FDT if RT_USING_DM + select RT_USING_PIC if RT_USING_DM + select RT_PIC_ARM_NVIC if RT_USING_DM + select RT_USING_PIN if RT_USING_DM default y config BOARD_STM32H750_ARTPI @@ -19,7 +24,12 @@ config BOARD_STM32H750_ARTPI select SOC_STM32H750XB default y +config RT_BUILTIN_FDT_PATH + string + default "board/dts/stm32h750-artpi.dtb" if RT_USING_DM + source "$(RTT_DIR)/Kconfig" + osource "$PKGS_DIR/Kconfig" rsource "../libraries/Kconfig" diff --git a/bsp/stm32/stm32h750-artpi/README.md b/bsp/stm32/stm32h750-artpi/README.md index 10b40325af..f07710752a 100644 --- a/bsp/stm32/stm32h750-artpi/README.md +++ b/bsp/stm32/stm32h750-artpi/README.md @@ -115,6 +115,16 @@ msh > 本章节更多详细的介绍请参考 [STM32 系列 BSP 外设驱动使用教程](../docs/STM32系列BSP外设驱动使用教程.md)。 +### 启用设备模型(DM) + +本 BSP 通过 `RT_USING_DM` 在设备模型驱动和传统 BSP 驱动之间进行选择。启用 DM 后,GPIO 和 EXTI 使用设备树描述,传统的 STM32 GPIO 驱动不会参与构建。 + +1. 在当前 BSP 目录执行 `scons --menuconfig`。 +2. 进入 `Device Drivers`,选中 `Enable device driver model with device tree`。 +3. 保存配置后执行 `scons -jN` 构建 GCC 工程。 + +BSP 会随 `RT_USING_DM` 自动选择 OFW、内置 FDT、PIC、NVIC 和 PIN 框架,并使用 `board/dts/stm32h750-artpi.dts`。构建过程会生成并嵌入 DTB。 + ## 注意事项 - 调试串口为串口4 映射说明 @@ -143,4 +153,4 @@ RT-Thread [社区论坛](https://club.rt-thread.org/)。 ## 贡献代码 -如果您对 ART-Pi 感兴趣,并有一些好玩的项目愿意与大家分享,欢迎给我们贡献代码,您可以参考 [ART-Pi 代码贡献手册](https://github.com/RT-Thread-Studio/sdk-bsp-stm32h750-realthread-artpi/blob/master/documents/UM5004-RT-Thread ART-Pi 代码贡献手册.md) 。 \ No newline at end of file +如果您对 ART-Pi 感兴趣,并有一些好玩的项目愿意与大家分享,欢迎给我们贡献代码,您可以参考 [ART-Pi 代码贡献手册](https://github.com/RT-Thread-Studio/sdk-bsp-stm32h750-realthread-artpi/blob/master/documents/UM5004-RT-Thread ART-Pi 代码贡献手册.md) 。 diff --git a/bsp/stm32/stm32h750-artpi/SConstruct b/bsp/stm32/stm32h750-artpi/SConstruct index 35ec081257..5a9aa10783 100644 --- a/bsp/stm32/stm32h750-artpi/SConstruct +++ b/bsp/stm32/stm32h750-artpi/SConstruct @@ -10,6 +10,7 @@ else: sys.path = sys.path + [os.path.join(RTT_ROOT, 'tools')] try: from building import * + import dtc except: print('Cannot found RT-Thread root directory, please check RTT_ROOT') print(RTT_ROOT) @@ -65,6 +66,27 @@ else: # prepare building environment objs = PrepareBuilding(env, RTT_ROOT, has_libcpu=False) +if GetDepend('RT_USING_BUILTIN_FDT'): + if os.getenv('DTC_PATH'): + os.environ['PATH'] = os.path.dirname(os.getenv('DTC_PATH')) + \ + os.pathsep + os.environ['PATH'] + + dtb_name = GetDepend('RT_BUILTIN_FDT_PATH').strip('"') + dts_name = os.path.splitext(dtb_name)[0] + '.dts' + dts_path = os.path.join(SDK_ROOT, dts_name) + dtc.dts_to_dtb(RTT_ROOT, [dts_name], + include_paths=[os.path.dirname(dts_path)]) + + if rtconfig.PLATFORM == 'gcc': + dtb_path = os.path.join(SDK_ROOT, dtb_name) + fdt_source = os.path.join(libraries_path_prefix, 'HAL_Drivers', + 'drivers', 'dm', 'builtin_fdt_gcc.S') + fdt_object = env.Object( + target=os.path.join(SDK_ROOT, 'build', 'dts', 'builtin_fdt_gcc.o'), + source=fdt_source) + env.Depends(fdt_object, dtb_path) + objs += fdt_object + rtconfig.BSP_LIBRARY_TYPE = None # include drivers diff --git a/bsp/stm32/stm32h750-artpi/applications/main.c b/bsp/stm32/stm32h750-artpi/applications/main.c index 8c8bef74a3..65200f447f 100644 --- a/bsp/stm32/stm32h750-artpi/applications/main.c +++ b/bsp/stm32/stm32h750-artpi/applications/main.c @@ -12,7 +12,9 @@ #include /* defined the LED0 pin: PI8 */ +#ifndef RT_USING_DM #define LED0_PIN GET_PIN(I, 8) +#endif #ifdef RT_USING_WIFI extern void wlan_autoconnect_init(void); @@ -20,21 +22,27 @@ int main(void) { +#ifndef RT_USING_DM /* set LED0 pin mode to output */ rt_pin_mode(LED0_PIN, PIN_MODE_OUTPUT); - #ifdef RT_USING_WIFI +#endif +#ifdef RT_USING_WIFI /* init Wi-Fi auto connect feature */ wlan_autoconnect_init(); /* enable auto reconnect on WLAN device */ rt_wlan_config_autoreconnect(RT_TRUE); - #endif +#endif while (1) { +#ifndef RT_USING_DM rt_pin_write(LED0_PIN, PIN_HIGH); rt_thread_mdelay(500); rt_pin_write(LED0_PIN, PIN_LOW); rt_thread_mdelay(500); +#else + rt_thread_mdelay(1000); +#endif } } diff --git a/bsp/stm32/stm32h750-artpi/board/dts/stm32h750-artpi.dts b/bsp/stm32/stm32h750-artpi/board/dts/stm32h750-artpi.dts new file mode 100644 index 0000000000..5b72508ba8 --- /dev/null +++ b/bsp/stm32/stm32h750-artpi/board/dts/stm32h750-artpi.dts @@ -0,0 +1,145 @@ +/dts-v1/; + +/ { + compatible = "st,stm32h750xb", "st,stm32h7"; + model = "RT-Thread STM32H750 ART-Pi"; + #address-cells = <1>; + #size-cells = <1>; + + aliases { + }; + + chosen { + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + compatible = "arm,cortex-m7"; + device_type = "cpu"; + reg = <0>; + }; + }; + + soc { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + interrupt-parent = <&nvic>; + + nvic: interrupt-controller@e000e100 { + compatible = "arm,v7m-nvic"; + reg = <0xe000e100 0xc00>; + interrupt-controller; + #interrupt-cells = <2>; + arm,num-irqs = <150>; + arm,num-irq-priority-bits = <4>; + }; + + exti: interrupt-controller@58000000 { + compatible = "st,stm32-exti"; + reg = <0x58000000 0x400>; + interrupt-controller; + #interrupt-cells = <1>; + #address-cells = <0>; + num-lines = <96>; + interrupts = <6 5>, <7 5>, <8 5>, <9 5>, + <10 5>, <23 5>, <40 5>; + interrupt-names = "line0", "line1", "line2", "line3", + "line4", "line5-9", "line10-15"; + line-ranges = <0 1>, <1 1>, <2 1>, <3 1>, + <4 1>, <5 5>, <10 6>; + }; + + gpioa: gpio@58020000 { + compatible = "st,stm32-gpio"; + reg = <0x58020000 0x400>; + gpio-controller; + #gpio-cells = <2>; + interrupt-parent = <&exti>; + }; + + gpiob: gpio@58020400 { + compatible = "st,stm32-gpio"; + reg = <0x58020400 0x400>; + gpio-controller; + #gpio-cells = <2>; + interrupt-parent = <&exti>; + }; + + gpioc: gpio@58020800 { + compatible = "st,stm32-gpio"; + reg = <0x58020800 0x400>; + gpio-controller; + #gpio-cells = <2>; + interrupt-parent = <&exti>; + }; + + gpiod: gpio@58020c00 { + compatible = "st,stm32-gpio"; + reg = <0x58020c00 0x400>; + gpio-controller; + #gpio-cells = <2>; + interrupt-parent = <&exti>; + }; + + gpioe: gpio@58021000 { + compatible = "st,stm32-gpio"; + reg = <0x58021000 0x400>; + gpio-controller; + #gpio-cells = <2>; + interrupt-parent = <&exti>; + }; + + gpiof: gpio@58021400 { + compatible = "st,stm32-gpio"; + reg = <0x58021400 0x400>; + gpio-controller; + #gpio-cells = <2>; + interrupt-parent = <&exti>; + }; + + gpiog: gpio@58021800 { + compatible = "st,stm32-gpio"; + reg = <0x58021800 0x400>; + gpio-controller; + #gpio-cells = <2>; + interrupt-parent = <&exti>; + }; + + gpioh: gpio@58021c00 { + compatible = "st,stm32-gpio"; + reg = <0x58021c00 0x400>; + gpio-controller; + #gpio-cells = <2>; + interrupt-parent = <&exti>; + }; + + gpioi: gpio@58022000 { + compatible = "st,stm32-gpio"; + reg = <0x58022000 0x400>; + gpio-controller; + #gpio-cells = <2>; + interrupt-parent = <&exti>; + }; + + gpioj: gpio@58022400 { + compatible = "st,stm32-gpio"; + reg = <0x58022400 0x400>; + gpio-controller; + #gpio-cells = <2>; + interrupt-parent = <&exti>; + }; + + gpiok: gpio@58022800 { + compatible = "st,stm32-gpio"; + reg = <0x58022800 0x400>; + gpio-controller; + #gpio-cells = <2>; + interrupt-parent = <&exti>; + }; + }; +}; diff --git a/bsp/stm32/stm32h750-artpi/board/linker_scripts/link.lds b/bsp/stm32/stm32h750-artpi/board/linker_scripts/link.lds index 4daa75f9c1..792b2eea4a 100644 --- a/bsp/stm32/stm32h750-artpi/board/linker_scripts/link.lds +++ b/bsp/stm32/stm32h750-artpi/board/linker_scripts/link.lds @@ -67,6 +67,11 @@ SECTIONS KEEP(*(SORT(.rti_fn*))) __rt_init_end = .; + /* section information for Open Firmware registration data */ + . = ALIGN(4); + KEEP(*(SORT(.rt_ofw_data.*))) + . = ALIGN(4); + . = ALIGN(4); PROVIDE(__ctors_start__ = .); diff --git a/bsp/stm32/stm32h750-artpi/rtconfig.py b/bsp/stm32/stm32h750-artpi/rtconfig.py index 10461925ab..9be7d2ccda 100644 --- a/bsp/stm32/stm32h750-artpi/rtconfig.py +++ b/bsp/stm32/stm32h750-artpi/rtconfig.py @@ -37,6 +37,7 @@ if PLATFORM == 'gcc': AS = PREFIX + 'gcc' AR = PREFIX + 'ar' CXX = PREFIX + 'g++' + CPP = PREFIX + 'gcc' LINK = PREFIX + 'gcc' TARGET_EXT = 'elf' SIZE = PREFIX + 'size' @@ -46,6 +47,7 @@ if PLATFORM == 'gcc': DEVICE = ' -mcpu=cortex-m7 -mthumb -mfpu=fpv5-d16 -mfloat-abi=hard -ffunction-sections -fdata-sections' CFLAGS = DEVICE + ' -Dgcc' AFLAGS = ' -c' + DEVICE + ' -x assembler-with-cpp -Wa,-mimplicit-it=thumb ' + CPPFLAGS = ' -E -P -x assembler-with-cpp' LFLAGS = DEVICE + ' -Wl,--gc-sections,-Map=rtthread.map,-cref,-u,Reset_Handler -T board/linker_scripts/link.lds' CPATH = ''