问题描述
我是 Zephyr 的新手,我尝试将我所有的嵌入式软件都交给 Zephyr。 我尝试了 Zephyr 文档和大量的谷歌搜索,但很难弄清楚如何做到这一点。 我试图了解“设备树”是如何工作的,以及如何在应用程序内部和外部 Zephyr 系统端使用它。 我试着通过样品,看看它们是如何组合在一起的。 现在我正在测试... zephyrproject/zephyr/samples/basic/button/。
我有一个输入(按钮)和一个可选输出(LED)。输入也可以是 ADC 多路复用器的模拟输入。 我稍微修改了一下,它做了它应该做的。 但我想改变它以做更多。 我也想让这个中断(除其他外)使 cpu 脱离深度睡眠。并在工作完成后重新进入深度睡眠。
问题_1: 如何禁用中断,并将输入从中断输入更改为模拟输入(在中断/回调处理程序中)并启动 ADC? 然后,在另一个线程中,我想读取 ADC 并将输入更改回中断输入,启用它,做任何我想做的事情,然后回到深度睡眠。
如何以“Zephyr 方式”完成此操作(因此它可以在不同平台上运行),我在我的 nrf52dk_nrf52832(没有 Zephyr)上执行此操作,并且它可以满足我的要求。
输入来自数字键盘,有一个输出,在按键时变高,然后返回到每个键不同的模拟电平,释放键时电平变为零。当然,我们的目标是解码按下的键,并用一行 io 来完成。
问题 2: 当/如果这适用于 Zephyr;我该怎么做才能使它成为合适的 Zephyr 设备驱动程序?
最好有示例来执行此操作,所有操作都在应用程序中完成。还有一个是用 Zephyr“key_pad_device_driver”完成的。
(在我的非 Zephyr 系统中,我在中断后稍等(大约 0.3 - 3 毫秒),然后读取 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,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,1); /* starts off "not available" */ // K_SEM_DEFINE(led_blink_sem,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,GPIO_INT_EDGE_TO_ACTIVE)) != 0){
printk("Error %d: Failed to configure interrupt on %s pin %d edg %x\n",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",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,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,PRIORITY,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_FLAGS);
if (ret != 0) {
printk("Error %d: Failed to configure LED device %s pin %d flg %x\n",LED0_GPIO_LABEL,LED0_GPIO_FLAGS);
return NULL;
}
printk("\tSet up LED at %s pin %d flg 0x%x\n",LED0_GPIO_FLAGS);
return led;
#else /* !defined(LED0_GPIO_LABEL) */
printk("No LED device was defined\n");
return NULL;
#endif /* LED0_GPIO_LABEL */
}
Zephyr 应用程序还有一些配置内容,但对于能够回答这个问题的应用程序,我认为现在并不重要。 但我认为答案确实需要一些配置才能起作用。
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)