在 ALIENTEK 阿波罗STM32F429开发板上使用 openvela 点亮 LED(二)
摘要 本指南详细介绍了在ALIENTEK阿波罗STM32F429开发板上使用openvela框架实现LED控制的方法。与之前方案不同,本文通过创建独立的APP_DEMOS_LED选项而非复用EXAMPLES_LEDS,使新增Demo逻辑更清晰。
在 ALIENTEK 阿波罗STM32F429开发板上使用 openvela 点亮 LED(二)
文章目录
一、概述
本指南(参考在STM32F411 上使用 openvela 点亮 LED)将引导您基于 ALIENTEK 阿波罗STM32F429开发板上,在 openvela 的 packages/demos 目录下添加、配置并运行一个自定义的 LED 控制应用。区别于在 ALIENTEK 阿波罗STM32F429开发板上使用 openvela 点亮 LED(一),本文创建了一个独立的 APP_DEMOS_LED 选项,而不是复用 EXAMPLES_LEDS,这使得新增的 Demo 逻辑清晰,配置简单,避免了不必要的依赖和混淆。
二、准备工作
在开始之前,请确保您已完成以下准备工作:
- 获取源码:参考文档快速入门下载最新代码。
- 了解
openvela架构:建议您预先阅读 openvela 架构以理解其分层设计。 - 查阅系统启动流程文档,获取更详细的启动时序和函数调用关系图。
- 准备好硬件及配套软件。
- 已完成前期的移植验证操作。
三、新增 Demo
本章将指导您如何在 openvela 的 packages/demos 目录下添加、配置并运行一个自定义的 LED 控制应用。
1、核心步骤概述
在 openvela 中集成一个新应用,主要遵循以下流程:
- 创建应用文件:在
packages/demos/下创建新目录,并编写应用的 C 源码、Kconfig和Makefile。 - 注册应用到编译系统:创建并编辑
packages/demos/Make.defs文件,让构建系统能够发现您的新应用。 - 配置与编译:创建
apollo-stm32f429i/configs/leds_demo/deconfig,启用新应用的配置,并编译生成包含新应用的固件。 - 运行与验证:烧录固件,并通过终端命令运行您的 Demo。
2、创建 Demo 源码及配置文件
-
创建
leds目录:# 确保当前位于 openvela 源码根目录 mkdir -p packages/demos/leds -
创建 C 语言源文件 (
packages/demos/led/leds_main.c): 此文件是 Demo 的核心逻辑,它通过ioctl系统调用与底层 LED 驱动进行交互。/**************************************************************************** * packages/demos/leds/leds_main.c ****************************************************************************/ /**************************************************************************** * Included Files ****************************************************************************/ #include <nuttx/config.h> #include <sys/ioctl.h> #include <stdbool.h> #include <stdlib.h> #include <stdio.h> #include <fcntl.h> #include <sched.h> #include <errno.h> #include <signal.h> #include <unistd.h> #include <nuttx/leds/userled.h> /**************************************************************************** * Private Data ****************************************************************************/ static bool g_led_daemon_started; /**************************************************************************** * Private Functions ****************************************************************************/ /**************************************************************************** * Name: sigterm_action ****************************************************************************/ static void sigterm_action(int signo, siginfo_t *siginfo, void *arg) { if (signo == SIGTERM) { printf("SIGTERM received\n"); g_led_daemon_started = false; printf("led_daemon: Terminated.\n"); } else { printf("\nsigterm_action: Received signo=%d siginfo=%p arg=%p\n", signo, siginfo, arg); } } /**************************************************************************** * Name: led_daemon ****************************************************************************/ static int led_daemon(int argc, char *argv[]) { userled_set_t supported; userled_set_t ledset; int ret; int fd; int loop_num; pid_t mypid; struct sigaction act; /* SIGTERM handler */ memset(&act, 0, sizeof(struct sigaction)); act.sa_sigaction = sigterm_action; act.sa_flags = SA_SIGINFO; sigemptyset(&act.sa_mask); sigaddset(&act.sa_mask, SIGTERM); ret = sigaction(SIGTERM, &act, NULL); if (ret != 0) { fprintf(stderr, "Failed to install SIGTERM handler, errno=%d\n", errno); return (EXIT_FAILURE + 1); } /* Indicate that we are running */ mypid = getpid(); g_led_daemon_started = true; printf("\nled_daemon (pid# %d): Running\n", mypid); /* Open the LED driver */ printf("led_daemon: Opening %s\n", CONFIG_APP_DEMOS_LEDS_DEVPATH); fd = open(CONFIG_APP_DEMOS_LEDS_DEVPATH, O_WRONLY); if (fd < 0) { int errcode = errno; printf("led_daemon: ERROR: Failed to open %s: %d\n", CONFIG_APP_DEMOS_LEDS_DEVPATH, errcode); goto errout; } /* Get the set of LEDs supported */ ret = ioctl(fd, ULEDIOC_SUPPORTED, (unsigned long)((uintptr_t)&supported)); if (ret < 0) { int errcode = errno; printf("led_daemon: ERROR: ioctl(ULEDIOC_SUPPORTED) failed: %d\n", errcode); goto errout_with_fd; } /* Excluded any LEDs that not supported AND not in the set of LEDs the * user asked us to use. */ printf("led_daemon: Supported LEDs 0x%02x\n", (unsigned int)supported); supported &= CONFIG_APP_DEMOS_LEDS_LEDSET; /* Now loop for a while, changing the LED set */ loop_num = 5; while (g_led_daemon_started == true) { ledset = (1 << (loop_num % 2) ) & supported; printf("led_daemon: LED set 0x%02x\n", (unsigned int)ledset); ret = ioctl(fd, ULEDIOC_SETALL, (unsigned long)ledset); if (ret < 0) { printf("ioctl(ULEDIOC_SETALL) failed: %d\n", ret); close(fd); return -1; } sleep(1); if (loop_num-- == 0) { goto sigtermout; } } /* treats signal termination of the task * task terminated by a SIGTERM */ sigtermout: g_led_daemon_started = false; close(fd); printf("led_daemon: Terminating\n"); printf("LED Demo finished.\n"); exit(EXIT_SUCCESS); errout_with_fd: close(fd); errout: g_led_daemon_started = false; printf("led_daemon: Terminating\n"); return EXIT_FAILURE; } /**************************************************************************** * Public Functions ****************************************************************************/ /**************************************************************************** * leds_main ****************************************************************************/ int main(int argc, FAR char *argv[]) { int ret; printf("leds_main: Starting the led_daemon\n"); if (g_led_daemon_started) { printf("leds_main: led_daemon already running\n"); return EXIT_SUCCESS; } ret = task_create("led_daemon", CONFIG_APP_DEMOS_LEDS_PRIORITY, CONFIG_APP_DEMOS_LEDS_STACKSIZE, led_daemon, NULL); if (ret < 0) { int errcode = errno; printf("leds_main: ERROR: Failed to start led_daemon: %d\n", errcode); return EXIT_FAILURE; } printf("leds_main: led_daemon started\n"); return EXIT_SUCCESS; } -
创建 Kconfig 文件。此文件用于在 menuconfig 中生成一个独立的配置选项来控制是否编译此 Demo。
packages/demos/leds/Kconfig:# Defines the configuration option for the custom LED Demo. # This will appear under "Application Configuration -> Demos". config APP_DEMOS_LEDS bool "Custom LED control demo" default n depends on USERLED # This demo requires the base USERLED driver ---help--- Enable this to build the custom LED control demo, which demonstrates how to turn an LED on and off via ioctl. if APP_DEMOS_LEDS config APP_DEMOS_LEDS_PROGNAME string "Program name" default "leds_demo" ---help--- This is the name of the program that will be used when the NSH ELF program is installed. config APP_DEMOS_LEDS_PRIORITY int "LED task priority" default 100 config APP_DEMOS_LEDS_STACKSIZE int "LED stack size" default DEFAULT_TASK_STACKSIZE config APP_DEMOS_LEDS_DEVPATH string "LED device path" default "/dev/userleds" config APP_DEMOS_LEDS_LEDSET hex "Subset of LEDs to use" default 0x0f endif # APP_DEMOS_LEDS
说明:我们创建了一个独立的 APP_DEMOS_LED 选项,而不是复用 EXAMPLES_LEDS,这使得新增的 Demo 逻辑清晰,配置简单,避免了不必要的依赖和混淆。
-
创建
Makefile文件: 此文件定义了本应用的编译规则,如程序名、优先级和堆栈大小。packages/demos/leds/Makefile:include $(APPDIR)/Make.defs ifeq ($(CONFIG_APP_DEMOS_LEDS), y) # Application details, linked to the Kconfig option PROGNAME = $(CONFIG_APP_DEMOS_LEDS_PROGNAME) PRIORITY = $(CONFIG_APP_DEMOS_LEDS_PRIORITY) STACKSIZE = $(CONFIG_APP_DEMOS_LEDS_STACKSIZE) MODULE = $(CONFIG_APP_DEMOS_LEDS) # Source file for the application MAINSRC = leds_main.c endif include $(APPDIR)/Application.mk
3、注册新 Demo 到编译系统
编辑 packages/demos/ 目录下的 Make.defs 文件,将我们的 led Demo 加入编译列表。
-
打开 packages/demos/leds/Make.defs 文件。
-
在文件末尾添加以下代码:
ifneq ($(CONFIG_APP_DEMOS_LEDS),) CONFIGURED_APPS += $(APPDIR)/packages/demos/leds endif
4、创建新的配置
以为ALIENTEK 阿波罗STM32F429开发板移植openvela :: 二、代码实现步骤 :: 1.创建代码目录结构 为基础,在nuttx/boards/arm/stm32/apollo-stm32f429i/configs目录下,创建一个名为 leds_demo的新目录,并在此目录中创建LED示例的默认配置文件deconfig。
nuttx/boards/arm/stm32/apollo-stm32f429i/configs/leds_demo/deconfig
#
# 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_FPU is not set
# CONFIG_ARCH_LEDS is not set
# CONFIG_NSH_ARGCAT is not set
# CONFIG_NSH_CMDOPT_HEXDUMP is not set
CONFIG_APP_DEMOS_LEDS=y
CONFIG_ARCH="arm"
CONFIG_ARCH_BOARD="apollo-stm32f429i"
CONFIG_ARCH_BOARD_APOLLO_STM32F429I=y
CONFIG_ARCH_BUTTONS=y
CONFIG_ARCH_CHIP="stm32"
CONFIG_ARCH_CHIP_STM32=y
CONFIG_ARCH_CHIP_STM32F429I=y
CONFIG_ARCH_STACKDUMP=y
CONFIG_BOARD_LATE_INITIALIZE=y
CONFIG_BOARD_LOOPSPERMSEC=13984
CONFIG_BUILTIN=y
CONFIG_DEBUG_SYMBOLS=y
CONFIG_EXAMPLES_LEDS=y
CONFIG_FS_PROCFS=y
CONFIG_HAVE_CXX=y
CONFIG_HAVE_CXXINITIALIZE=y
CONFIG_INIT_ENTRYPOINT="nsh_main"
CONFIG_INTELHEX_BINARY=y
CONFIG_MM_REGIONS=2
CONFIG_NSH_BUILTIN_APPS=y
CONFIG_NSH_FILEIOSIZE=512
CONFIG_NSH_READLINE=y
CONFIG_PREALLOC_TIMERS=4
CONFIG_RAM_SIZE=114688
CONFIG_RAM_START=0x20000000
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_STM32_DISABLE_IDLE_SLEEP_DURING_DEBUG=y
CONFIG_STM32_JTAG_SW_ENABLE=y
CONFIG_STM32_PWR=y
CONFIG_STM32_USART1=y
CONFIG_SYSTEM_NSH=y
CONFIG_TASK_NAME_SIZE=0
CONFIG_USART1_SERIAL_CONSOLE=y
CONFIG_USERLED=y
CONFIG_USERLED_LOWER=y
四、运行Demo
1、编译代码
切换到 openvela 的根目录,distclean 之后 build:
# (Optional but recommended) Clean previous build artifacts
./build.sh nuttx/boards/arm/stm32/apollo-stm32f429i/configs/leds_demo distclean
# Build the project with the new configuration
./build.sh apollo-stm32f429i:leds_demo -j8
编译完成后,生成的文件位于 nuttx 目录下,包括:
- nuttx.bin
- nuttx.hex
2、烧录固件
参考在 STM32F411 上使用 openvela 点亮 LED: : 四、运行Demo::5、烧录固件
3、连接串口
参考在 STM32F411 上使用 openvela 点亮 LED: : 四、运行Demo::6、连接串口
4、运行 LED 示例
-
重新打开 minicom,连接成功后,在 Minicom 终端中按回车,您会看到
nsh>提示符。 -
运行 LED 示例,请输入以下命令:
leds_demo -
您将看到开发板上的用户 LED 开始交替闪烁,同时串口终端会输出运行日志。
leds_demo_new
openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。
更多推荐

所有评论(0)