Loading

zephyr学习:zephyr 按键+串口通信

 

参考:应用程序开发 — Zephyr Project Documentation --- Application Development — Zephyr Project Documentation

硬件: 立创实战派开发板(esp32-s3)

注:代码已上传github  cc1234github/lichuang_shizhanpai_zephyr: use lichuang shizhan board study zephyr

 

1. 创建App工作空间

1.1 官方app_demo

官方给出了一个app文件的例子,我们可以使用这个文件来创建自己的zephyr App 工作空间,git地址如下:

cd <home>/zephyrproject
git clone https://github.com/zephyrproject-rtos/example-application my-app

 

1.2 app 文件结构

app中应该包含下面这些文件内容:

image

  • CMakeLists.txt:此文件告诉构建系统在哪里可以找到其他应用程序文件,并将应用程序目录与 Zephyr 的 CMake 构建系统链接。
  • app.overlay: 设备树覆盖文件,可以覆盖调用的那个板子上的硬件信息。
  • prj.conf: 工程配置项,一般配置软件功能
  • VERSION:版本
  • SRC: c文件

 

然后工程文件也是可以创建到三个地方的:

  • 1. 放到west工作区zephyr源码下面,但是这样会污染zephyr工程,下次更新zephyr时比较麻烦。❌
  • image
  • 2. 放到west工作区,但是单独放文件,编译方便,✔️
  • image
  • 3. 不放在west工作区,放到任意地方,需要配置环境变量✔️
  • image

 

我选择了第三种方式:

 注意:在zephyr源文件之外的地方编译工程需要添加几个环境变量

image

  •  ZEPHYR_BASE:zephyr主文件夹的地方
  •  ZEPHYR_SDK_INSTALL_DIR :指定编译工具的位置
  • ZEPHYR_TOOLCHAIN_VARIANT : 指定编译工具链

下载了app-demo工程文件后,结构如下:包含了很多东西,大部分都暂时用不上

image

 

2. 自定义板子

由于zephyr中没有立创实战派这个板子,我打算自定义一个。

  1. 先去zephyr源码中找到资源类似的板子(直接搜esp32-s3)

image

  2. 复制到工程后,放置目录如下( boards\espressif\lc_shizhanpai ),修改文件名字。

image

  3. 修改board.yml,把名字改成和文件一样的

image

  4. 修改Kconfig.lc_shizhanpai 的SOC,开发板用的 N16R8

image

  5. 因为改了芯片,所以头文件也要改

image

  6. 引脚复用也改成开发板的  lc_shizhanpai-pinctrl.dtsi

/*
 * Copyright (c) 2022 Espressif Systems (Shanghai) Co., Ltd.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr/dt-bindings/pinctrl/esp-pinctrl-common.h>
#include <dt-bindings/pinctrl/esp32s3-pinctrl.h>
#include <zephyr/dt-bindings/pinctrl/esp32s3-gpio-sigmap.h>

&pinctrl {
    uart0_default: uart0_default {
        group1 {
            pinmux = <UART0_TX_GPIO43>;
            output-high;
        };
        group2 {
            pinmux = <UART0_RX_GPIO44>;
            bias-pull-up;
        };
    };

    uart1_default: uart1_default {
        group1 {
            pinmux = <UART1_TX_GPIO17>;
            output-high;
        };
        group2 {
            pinmux = <UART1_RX_GPIO18>;
            bias-pull-up;
        };
    };
};

  7. 修改procpu的device tree,只用procpu这一个内核

/ {
    model = "lc_shizhanpai PROCPU";
    compatible = "espressif,esp32s3";

    aliases {
        sw2 = &button0;
    };

    chosen {
        zephyr,sram = &sram1;
        zephyr,console = &uart0;
        zephyr,shell-uart = &uart0;
        zephyr,flash = &flash0;
        zephyr,code-partition = &slot0_partition;
    };

    buttons {
        compatible = "gpio-keys";
        button0: button_0 {
            gpios = <&gpio0 0 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
            label = "BOOT Button";
            zephyr,code = <INPUT_KEY_0>;
        };
    };
};

&uart0 {
    status = "okay";
    current-speed = <115200>;
    pinctrl-0 = <&uart0_default>;
    pinctrl-names = "default";
};
&gpio0 {
    status = "okay";
};

&gpio1 {
    status = "okay";
};
&timer0 {
    status = "disabled";
};

&timer1 {
    status = "disabled";
};

&timer2 {
    status = "disabled";
};

&timer3 {
    status = "disabled";
};
&usb_serial { status = "disabled"; };

 

3. app程序

 main.c 

主要就是获取sw2这个节点,然后调用一个中断,每次中断按下就会打印当前的主程序运行周期

#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/devicetree.h>
#include <zephyr/sys/printk.h>
#include <zephyr/logging/log.h>

// 注册一个日志模块
LOG_MODULE_REGISTER(Button, LOG_LEVEL_INF);

/*
 * Get button configuration from the devicetree sw0 alias. This is mandatory.
 */
#define SW0_NODE    DT_ALIAS(sw2)
#if !DT_NODE_HAS_STATUS_OKAY(SW0_NODE)
#error "Unsupported board: sw0 devicetree alias is not defined"
#endif
static const struct gpio_dt_spec button = GPIO_DT_SPEC_GET_OR(SW0_NODE, gpios,
                                  {0});
static struct gpio_callback button_cb_data;


void button_pressed(const struct device *dev, struct gpio_callback *cb,
            uint32_t pins)
{
    LOG_INF("Button pressed at %" PRIu32 "\n", k_cycle_get_32());
}

int main(void)
{
    int ret;

    if (!gpio_is_ready_dt(&button)) {
        LOG_INF("Error: button device %s is not ready\n",
               button.port->name);
        return 0;
    }

    ret = gpio_pin_interrupt_configure_dt(&button,
                          GPIO_INT_EDGE_TO_ACTIVE);
    if (ret != 0) {
        LOG_INF("Error %d: failed to configure interrupt on %s pin %d\n",
            ret, button.port->name, button.pin);
        return 0;
    }

    gpio_init_callback(&button_cb_data, button_pressed, BIT(button.pin));
    gpio_add_callback(button.port, &button_cb_data);
    LOG_INF("Set up button at %s pin %d\n", button.port->name, button.pin);

    while (1) {
        k_msleep(1);
    }
}

 

app.overlay

app.overlay 文件 我这里暂时没用,因为上面我自定义了板子,我直接在DTS里面去改了

 

CMakeLists.txt  

添加了指定板子 和 设置BOARD_ROOT 

  • set (BOARD  xxx) 方便编译烧录
  • BOARD_ROOT  zephyr会在这个下面去找我自己定义的板子,不设置会找不到板子
#-------------------------------------------------------------------------------
# Zephyr Example Application
#
# Copyright (c) 2021 Nordic Semiconductor ASA
# SPDX-License-Identifier: Apache-2.0

cmake_minimum_required(VERSION 3.13.1)

# 指定板子,build/flash 时直接使用west build,不用指定板子了
set(BOARD lc_shizhanpai)            
# 设定 BOARD_ROOT 指向工作空间的目录(不然会找不到自己定义的板子)
get_filename_component(PARENT_DIR ${CMAKE_CURRENT_SOURCE_DIR} DIRECTORY)
list(APPEND BOARD_ROOT ${PARENT_DIR})


find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})   # 查找 Zephyr 包
project(my_led LANGUAGES C)                             # 定义工程
target_sources(app PRIVATE src/main.c)         

 

prj.conf

CONFIG_MAIN_STACK_SIZE=4096
CONFIG_LOG=y
CONFIG_LOG_DEFAULT_LEVEL=3
CONFIG_GPIO=y

 

4. 编译烧录

每按一次按键,就打印一次

image

 

posted @ 2025-07-25 16:25  cc_record  阅读(178)  评论(0)    收藏  举报