2

我是 Zephyr 的新手,我尝试将我所有的嵌入式软件都交给 Zephyr。我尝试了 Zephyr 文档和大量谷歌搜索,但很难弄清楚如何做到这一点。我试图了解“设备树”是如何工作的,以及如何在应用程序内部和 Zephyr 系统端外部使用它。我试着通过样品,看看它们是如何组合在一起的。现在我正在测试... zephyrproject/zephyr/samples/basic/button/。

我有一个输入(按钮)和一个可选输出(LED)。输入也可以是 ADC 多路复用器的模拟输入。我对其进行了一些修改,它做了它应该做的事情。但我想改变它来做更多的事情。我还想让这个中断(除其他外)让 CPU 脱离深度睡眠。工作完成后重新进入深度睡眠。

Question_1:如何禁用中断,将输入从中断输入更改为模拟输入(在中断/回调处理程序中)并启动ADC?然后,在另一个线程中,我想读取 ADC 并将输入更改回中断输入,启用它,做我想做的任何事情,然后回到深度睡眠。

如何以“Zephyr 方式”完成此操作(因此它可以在不同平台上工作),我在我的 nrf52dk_nrf52832(没有 Zephyr)上执行此操作,它可以满足我的需求。

输入来自带有一个输出的数字键盘,在按键按下时变为高电平,然后返回到每个按键都不同的模拟电平,松开按键时电平变为零。当然,目标是解码按下的键,并使用一条 io 行来完成。

问题_2:何时/如果这适用于 Zephyr;我该怎么做才能使其成为正确的 Zephyr 设备驱动程序?

最好有示例来执行此操作,所有操作都在应用程序中完成。还有一个是用 Zephyr“key_pad_device_driver”完成的。

(在我的非 Zephyr 系统中,我在中断后稍等片刻(大约 0.3 - 3 ms),然后读取 10 个模拟样本,丢弃两个最高和两个最低值,然后如果这些之间的跨度被接受,我取它们的平均值并锁定按下的键。这工作出奇的好)。

她是我的“button/src/main.c”的代码

/*
 * Copyright (c) 2016 Open-RnD Sp. z o.o.
 * Copyright (c) 2020 Nordic Semiconductor ASA
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr.h>
#include <device.h>
#include <drivers/gpio.h>
#include <sys/util.h>
#include <sys/printk.h>
#include <inttypes.h>

#define LED_ON_TIME 100

/*
 * Get button configuration from the devicetree sw0 alias.
 *
 * At least a GPIO device and pin number must be provided. The 'flags'
 * cell is optional.
 */

#define SW0_NODE    DT_ALIAS(sw0)

#if DT_NODE_HAS_STATUS(SW0_NODE, okay)
    #define SW0_GPIO_LABEL  DT_GPIO_LABEL(SW0_NODE, gpios)
    #define SW0_GPIO_PIN    DT_GPIO_PIN(SW0_NODE, gpios)
    #define SW0_GPIO_FLAGS  (GPIO_INPUT | DT_GPIO_FLAGS(SW0_NODE, gpios))
#else
    #error "Unsupported board: sw0 devicetree alias is not defined"
    #define SW0_GPIO_LABEL  ""
    #define SW0_GPIO_PIN    0
    #define SW0_GPIO_FLAGS  0
#endif

/* LED helpers, which use the led0 devicetree alias if it's available. */
static const struct device *initialize_led(void);

static struct gpio_callback button_cb_data;


K_SEM_DEFINE(kbd_pres_sem, 0, 1);   /* starts off "not available" */    // K_SEM_DEFINE(kbd_pres_sem, 1, 1);    /* starts off "available" */

void bp_cb(const struct device *dev, struct gpio_callback *cb, uint32_t pins)
{
    static int cp_cnt;

    printk("\n# bp_cb(): %d Button pressed at: %" PRIu32 "... ", cp_cnt++, k_cycle_get_32());
    k_sem_give(&kbd_pres_sem);  // Giving the semaphore increments its count, unless the count is already equal to the limit.
}

/*
 * The led0 devicetree alias is optional. If present, we'll use it
 * to turn on the LED whenever the button is pressed.
 */

#define LED0_NODE   DT_ALIAS(led0)

#if DT_NODE_HAS_STATUS(LED0_NODE, okay) && DT_NODE_HAS_PROP(LED0_NODE, gpios)
    #define LED0_GPIO_LABEL DT_GPIO_LABEL(LED0_NODE, gpios)
    #define LED0_GPIO_PIN   DT_GPIO_PIN(LED0_NODE, gpios)
    #define LED0_GPIO_FLAGS (GPIO_OUTPUT | DT_GPIO_FLAGS(LED0_NODE, gpios))
#endif

K_SEM_DEFINE(led_blink_sem, 0, 1);  /* starts off "not available" */    // K_SEM_DEFINE(led_blink_sem, 1, 1);   /* starts off "available" */
const struct device *button;
const struct device *led;

void main(void)
{
    int ret;
    int bp_cnt = 0;;

    if((button = device_get_binding(SW0_GPIO_LABEL)) == NULL){
        printk("Error: didn't find %s device\n", SW0_GPIO_LABEL);
        return;
    }

    if((ret = gpio_pin_configure(button, SW0_GPIO_PIN, SW0_GPIO_FLAGS)) != 0){
        printk("Error %d: failed to configure %s pin %d\n",
               ret, SW0_GPIO_LABEL, SW0_GPIO_PIN);
        return;
    }

    if((ret = gpio_pin_interrupt_configure(button, SW0_GPIO_PIN, GPIO_INT_EDGE_TO_ACTIVE)) != 0){
        printk("Error %d: failed to configure interrupt on %s pin %d edg %x\n",
               ret, SW0_GPIO_LABEL, SW0_GPIO_PIN, GPIO_INT_EDGE_TO_ACTIVE);
        return;
    }

    gpio_init_callback(&button_cb_data, bp_cb, BIT(SW0_GPIO_PIN));
    gpio_add_callback(button, &button_cb_data);
    printk("\tSet up button at %s pin %d edg 0x%x\n", SW0_GPIO_LABEL, SW0_GPIO_PIN, GPIO_INT_EDGE_TO_ACTIVE);

    led = initialize_led();

    printk("\tPress the button, ");
    while(1){
        k_sem_take(&kbd_pres_sem, K_FOREVER);   // Taking the semaphore decrements its count, unless the semaphore is unavailable (i.e. at zero).
        printk("# main(): %d Button press detected at: %" PRIu32 "... ", bp_cnt++, k_cycle_get_32());
        k_sem_give(&led_blink_sem);     // Giving the semaphore increments its count, unless the count is already equal to the limit.
    }
}

#ifdef LED0_GPIO_LABEL
    void led_handler(void)
    {
        int lb_cnt = 0;
        
        printk("\t######## led_handler: Start #########\n");

        while(1){
            gpio_pin_set(led, LED0_GPIO_PIN, 1);    // ledd off
            k_sem_take(&led_blink_sem, K_FOREVER);  // Taking the semaphore decrements its count, unless the semaphore is unavailable (i.e. at zero).

            printk(" # led_handler(): %d Led blink", lb_cnt++);
        
            gpio_pin_set(led, LED0_GPIO_PIN, 0);    // ledd on

            k_msleep(LED_ON_TIME);  // k_msleep(3000);

        }
    }

    #define STACKSIZE 1024  /* size of stack area used by each thread */
    #define PRIORITY 7  /* scheduling priority used by each thread */

    K_THREAD_DEFINE(led_handler_id, STACKSIZE, led_handler, NULL, NULL, NULL, PRIORITY, 0, 0);

#endif  /* LED0_GPIO_LABEL */

static const struct device *initialize_led(void)
{
    #ifdef LED0_GPIO_LABEL
        const struct device *led;
        int ret;

        led = device_get_binding(LED0_GPIO_LABEL);
        if (led == NULL) {
            printk("Didn't find LED device %s\n", LED0_GPIO_LABEL);
            return NULL;
        }

        ret = gpio_pin_configure(led, LED0_GPIO_PIN, LED0_GPIO_FLAGS);
        if (ret != 0) {
            printk("Error %d: failed to configure LED device %s pin %d flg %x\n",
            ret, LED0_GPIO_LABEL, LED0_GPIO_PIN, LED0_GPIO_FLAGS);
            return NULL;
        }

        printk("\tSet up LED at %s pin %d flg 0x%x\n", LED0_GPIO_LABEL, LED0_GPIO_PIN, LED0_GPIO_FLAGS);

        return led;
        
    #else  /* !defined(LED0_GPIO_LABEL) */
        printk("No LED device was defined\n");
        return NULL;
    #endif  /* LED0_GPIO_LABEL */
}

Zephyr 应用程序还有更多配置内容,但对于能够回答这个问题的应用程序,我认为现在并不重要。但我认为答案确实需要一些配置才能工作。

4

0 回答 0