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.
This commit is contained in:
parent
6b4f34204e
commit
655aea948e
|
|
@ -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')
|
||||
|
|
|
|||
|
|
@ -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')
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2026, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <rtconfig.h>
|
||||
|
||||
#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
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2026, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <rtconfig.h>
|
||||
|
||||
.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
|
||||
|
|
@ -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 <rtthread.h>
|
||||
#include <rtdevice.h>
|
||||
|
||||
#define DBG_TAG "drv.exti"
|
||||
#define DBG_LVL DBG_INFO
|
||||
#include <rtdbg.h>
|
||||
|
||||
#include <drivers/pic.h>
|
||||
#include <drivers/ofw_irq.h>
|
||||
|
||||
#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();
|
||||
}
|
||||
|
|
@ -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 <rtthread.h>
|
||||
#include <board.h>
|
||||
#include <drivers/ofw.h>
|
||||
|
||||
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__ */
|
||||
|
|
@ -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 <rtthread.h>
|
||||
#include <rtdevice.h>
|
||||
|
||||
#define DBG_TAG "drv.gpio.dm"
|
||||
#define DBG_LVL DBG_INFO
|
||||
#include <rtdbg.h>
|
||||
|
||||
#include <drivers/platform.h>
|
||||
#include <drivers/ofw.h>
|
||||
#include <drivers/ofw_irq.h>
|
||||
#include <drivers/pic.h>
|
||||
|
||||
#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);
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -11,7 +11,14 @@
|
|||
#include "drv_common.h"
|
||||
#include <board.h>
|
||||
|
||||
#ifdef RT_USING_PIN
|
||||
#ifdef RT_USING_BUILTIN_FDT
|
||||
#include <drivers/ofw_fdt.h>
|
||||
#include <drivers/pic.h>
|
||||
|
||||
extern const unsigned char rt_hw_builtin_fdt[];
|
||||
#endif
|
||||
|
||||
#if defined(RT_USING_PIN) && !defined(RT_USING_DM)
|
||||
#include <drv_gpio.h>
|
||||
#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
|
||||
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
||||
|
|
|
|||
|
|
@ -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。
|
||||
|
||||
## 注意事项
|
||||
|
||||
暂无
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -16,10 +16,14 @@
|
|||
#include <rtdevice.h>
|
||||
#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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,131 @@
|
|||
/dts-v1/;
|
||||
|
||||
#include <dt-bindings/pin/pin.h>
|
||||
|
||||
/ {
|
||||
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>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
@ -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__ = .);
|
||||
|
|
|
|||
|
|
@ -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 = ''
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
||||
|
|
|
|||
|
|
@ -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) 。
|
||||
如果您对 ART-Pi 感兴趣,并有一些好玩的项目愿意与大家分享,欢迎给我们贡献代码,您可以参考 [ART-Pi 代码贡献手册](https://github.com/RT-Thread-Studio/sdk-bsp-stm32h750-realthread-artpi/blob/master/documents/UM5004-RT-Thread ART-Pi 代码贡献手册.md) 。
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -12,7 +12,9 @@
|
|||
#include <board.h>
|
||||
|
||||
/* 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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
@ -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__ = .);
|
||||
|
|
|
|||
|
|
@ -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 = ''
|
||||
|
|
|
|||
Loading…
Reference in New Issue