1.移除单一引脚中断回调,使用设备框架通用回调机制。
This commit is contained in:
132
device/pin.c
132
device/pin.c
@@ -10,88 +10,21 @@
|
||||
|
||||
#ifdef MR_USING_PIN
|
||||
|
||||
/**
|
||||
* @brief Pin irq structure.
|
||||
*/
|
||||
struct pin_irq
|
||||
{
|
||||
int number; /**< Pin number */
|
||||
int desc; /**< Device descriptor */
|
||||
int (*call)(int desc, void *args); /**< Callback function */
|
||||
struct mr_list list; /**< List */
|
||||
};
|
||||
void _mr_fast_pin_init(struct mr_dev *dev);
|
||||
|
||||
static int pin_set_mode(struct mr_pin *pin, int number, int mode)
|
||||
MR_INLINE int pin_set_mode(struct mr_pin *pin, int number, int mode)
|
||||
{
|
||||
struct mr_pin_ops *ops = (struct mr_pin_ops *)pin->dev.drv->ops;
|
||||
|
||||
/* Check number is valid */
|
||||
if (number < 0)
|
||||
{
|
||||
return MR_EINVAL;
|
||||
}
|
||||
|
||||
/* Configure pin mode */
|
||||
int ret = ops->configure(pin, number, mode);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Disable interrupt */
|
||||
mr_interrupt_disable();
|
||||
|
||||
/* If the irq exists, update it */
|
||||
for (struct mr_list *list = pin->irq_list.next; list != &pin->irq_list; list = list->next)
|
||||
{
|
||||
struct pin_irq *irq = (struct pin_irq *)MR_CONTAINER_OF(list, struct pin_irq, list);
|
||||
if (irq->number == number)
|
||||
{
|
||||
if (mode < MR_PIN_MODE_IRQ_RISING)
|
||||
{
|
||||
/* Remove irq */
|
||||
mr_list_remove(list);
|
||||
mr_free(irq);
|
||||
} else
|
||||
{
|
||||
/* Update irq */
|
||||
irq->desc = pin->dev.rd_call.desc;
|
||||
irq->call = pin->dev.rd_call.call;
|
||||
}
|
||||
|
||||
/* Enable interrupt */
|
||||
mr_interrupt_enable();
|
||||
return MR_EOK;
|
||||
}
|
||||
}
|
||||
|
||||
/* If not exist, allocate new irq */
|
||||
if (mode >= MR_PIN_MODE_IRQ_RISING)
|
||||
{
|
||||
/* Allocate irq */
|
||||
struct pin_irq *irq = (struct pin_irq *)mr_malloc(sizeof(struct pin_irq));
|
||||
if (irq == MR_NULL)
|
||||
{
|
||||
/* Enable interrupt */
|
||||
mr_interrupt_enable();
|
||||
return MR_ENOMEM;
|
||||
}
|
||||
irq->number = number;
|
||||
irq->desc = pin->dev.rd_call.desc;
|
||||
irq->call = pin->dev.rd_call.call;
|
||||
mr_list_init(&irq->list);
|
||||
mr_list_insert_before(&pin->irq_list, &irq->list);
|
||||
|
||||
/* Clear call */
|
||||
pin->dev.rd_call.call = MR_NULL;
|
||||
}
|
||||
|
||||
/* Enable interrupt */
|
||||
mr_interrupt_enable();
|
||||
return MR_EOK;
|
||||
return ops->configure(pin, number, mode);
|
||||
}
|
||||
|
||||
static ssize_t mr_pin_read(struct mr_dev *dev, int off, void *buf, size_t size, int async)
|
||||
static ssize_t mr_pin_read(struct mr_dev *dev, void *buf, size_t count)
|
||||
{
|
||||
struct mr_pin *pin = (struct mr_pin *)dev;
|
||||
struct mr_pin_ops *ops = (struct mr_pin_ops *)dev->drv->ops;
|
||||
@@ -99,22 +32,22 @@ static ssize_t mr_pin_read(struct mr_dev *dev, int off, void *buf, size_t size,
|
||||
ssize_t rd_size;
|
||||
|
||||
#ifdef MR_USING_PIN_CHECK
|
||||
/* Check offset is valid */
|
||||
if (off < 0)
|
||||
/* Check number is valid */
|
||||
if (dev->position < 0)
|
||||
{
|
||||
return MR_EINVAL;
|
||||
}
|
||||
#endif /* MR_USING_PIN_CHECK */
|
||||
|
||||
for (rd_size = 0; rd_size < size; rd_size += sizeof(*rd_buf))
|
||||
for (rd_size = 0; rd_size < count; rd_size += sizeof(*rd_buf))
|
||||
{
|
||||
*rd_buf = (uint8_t)ops->read(pin, off);
|
||||
*rd_buf = (uint8_t)ops->read(pin, dev->position);
|
||||
rd_buf++;
|
||||
}
|
||||
return rd_size;
|
||||
}
|
||||
|
||||
static ssize_t mr_pin_write(struct mr_dev *dev, int off, const void *buf, size_t size, int async)
|
||||
static ssize_t mr_pin_write(struct mr_dev *dev, const void *buf, size_t count)
|
||||
{
|
||||
struct mr_pin *pin = (struct mr_pin *)dev;
|
||||
struct mr_pin_ops *ops = (struct mr_pin_ops *)dev->drv->ops;
|
||||
@@ -122,34 +55,34 @@ static ssize_t mr_pin_write(struct mr_dev *dev, int off, const void *buf, size_t
|
||||
ssize_t wr_size;
|
||||
|
||||
#ifdef MR_USING_PIN_CHECK
|
||||
/* Check offset is valid */
|
||||
if (off < 0)
|
||||
/* Check number is valid */
|
||||
if (dev->position < 0)
|
||||
{
|
||||
return MR_EINVAL;
|
||||
}
|
||||
#endif /* MR_USING_PIN_CHECK */
|
||||
|
||||
for (wr_size = 0; wr_size < size; wr_size += sizeof(*wr_buf))
|
||||
for (wr_size = 0; wr_size < count; wr_size += sizeof(*wr_buf))
|
||||
{
|
||||
ops->write(pin, off, *wr_buf);
|
||||
ops->write(pin, dev->position, *wr_buf);
|
||||
wr_buf++;
|
||||
}
|
||||
return wr_size;
|
||||
}
|
||||
|
||||
static int mr_pin_ioctl(struct mr_dev *dev, int off, int cmd, void *args)
|
||||
static int mr_pin_ioctl(struct mr_dev *dev, int cmd, void *args)
|
||||
{
|
||||
struct mr_pin *pin = (struct mr_pin *)dev;
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
case MR_CTL_PIN_SET_MODE:
|
||||
case MR_IOC_PIN_SET_MODE:
|
||||
{
|
||||
if (args != MR_NULL)
|
||||
{
|
||||
struct mr_pin_config config = *((struct mr_pin_config *)args);
|
||||
|
||||
int ret = pin_set_mode(pin, off, config.mode);
|
||||
int ret = pin_set_mode(pin, dev->position, config.mode);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
@@ -167,25 +100,13 @@ static int mr_pin_ioctl(struct mr_dev *dev, int off, int cmd, void *args)
|
||||
|
||||
static ssize_t mr_pin_isr(struct mr_dev *dev, int event, void *args)
|
||||
{
|
||||
struct mr_pin *pin = (struct mr_pin *)dev;
|
||||
|
||||
switch (event)
|
||||
{
|
||||
case MR_ISR_PIN_EXTI_INT:
|
||||
{
|
||||
ssize_t number = *(int *)args;
|
||||
|
||||
/* If the irq exists, call it */
|
||||
for (struct mr_list *list = pin->irq_list.next; list != &pin->irq_list; list = list->next)
|
||||
{
|
||||
struct pin_irq *irq = (struct pin_irq *)MR_CONTAINER_OF(list, struct pin_irq, list);
|
||||
if (irq->number == number)
|
||||
{
|
||||
irq->call(irq->desc, &number);
|
||||
return MR_EEXIST;
|
||||
}
|
||||
}
|
||||
return MR_ENOTFOUND;
|
||||
return number;
|
||||
}
|
||||
default:
|
||||
{
|
||||
@@ -198,12 +119,12 @@ static ssize_t mr_pin_isr(struct mr_dev *dev, int event, void *args)
|
||||
* @brief This function registers a pin.
|
||||
*
|
||||
* @param pin The pin.
|
||||
* @param name The name of the pin.
|
||||
* @param path The path of the pin.
|
||||
* @param drv The driver of the pin.
|
||||
*
|
||||
* @return MR_EOK on success, otherwise an error code.
|
||||
* @return 0 on success, otherwise an error code.
|
||||
*/
|
||||
int mr_pin_register(struct mr_pin *pin, const char *name, struct mr_drv *drv)
|
||||
int mr_pin_register(struct mr_pin *pin, const char *path, struct mr_drv *drv)
|
||||
{
|
||||
static struct mr_dev_ops ops =
|
||||
{
|
||||
@@ -216,15 +137,18 @@ int mr_pin_register(struct mr_pin *pin, const char *name, struct mr_drv *drv)
|
||||
};
|
||||
|
||||
MR_ASSERT(pin != MR_NULL);
|
||||
MR_ASSERT(name != MR_NULL);
|
||||
MR_ASSERT(path != MR_NULL);
|
||||
MR_ASSERT(drv != MR_NULL);
|
||||
MR_ASSERT(drv->ops != MR_NULL);
|
||||
|
||||
/* Initialize the fields */
|
||||
mr_list_init(&pin->irq_list);
|
||||
|
||||
/* Register the pin */
|
||||
return mr_dev_register(&pin->dev, name, Mr_Dev_Type_Pin, MR_SFLAG_RDWR, &ops, drv);
|
||||
int ret = mr_dev_register(&pin->dev, path, MR_DEV_TYPE_PIN, MR_O_RDWR, &ops, drv);
|
||||
if (ret == MR_EOK)
|
||||
{
|
||||
/* Initialize the fast pin */
|
||||
_mr_fast_pin_init(&pin->dev);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* MR_USING_PIN */
|
||||
|
||||
@@ -20,21 +20,21 @@
|
||||
## 打开PIN设备
|
||||
|
||||
```c
|
||||
int mr_dev_open(const char *name, int oflags);
|
||||
int mr_dev_open(const char *path, int flags);
|
||||
```
|
||||
|
||||
| 参数 | 描述 |
|
||||
|---------|---------|
|
||||
| name | 设备名称 |
|
||||
| oflags | 打开设备的标志 |
|
||||
| path | 设备路径 |
|
||||
| flags | 打开设备的标志 |
|
||||
| **返回值** | |
|
||||
| `>=0` | 设备描述符 |
|
||||
| `<0` | 错误码 |
|
||||
|
||||
- `name`:PIN设备名称一般为:`pin`。
|
||||
- `oflags`:打开设备的标志,支持 `MR_OFLAG_RDONLY`、 `MR_OFLAG_WRONLY`、 `MR_OFLAG_RDWR`。
|
||||
- `path`:PIN设备路径一般为:`pin`。
|
||||
- `flags`:打开设备的标志,支持 `MR_O_RDONLY`、 `MR_O_WRONLY`、 `MR_O_RDWR`。
|
||||
|
||||
注:使用时应根据实际情况为不同的任务分别打开PIN设备,并使用适当的`oflags`进行管理和权限控制,以确保它们不会相互影响。
|
||||
注:使用时应根据实际情况为不同的任务分别打开PIN设备,并使用适当的`flags`进行管理和权限控制,以确保它们不会相互影响。
|
||||
|
||||
## 关闭PIN设备
|
||||
|
||||
@@ -67,11 +67,11 @@ int mr_dev_ioctl(int desc, int cmd, void *args);
|
||||
| `<0` | 错误码 |
|
||||
|
||||
- `cmd`:命令码,支持以下命令:
|
||||
- `MR_CTL_PIN_SET_NUMBER`:设置引脚编号。
|
||||
- `MR_CTL_PIN_SET_MODE`:设置引脚模式。
|
||||
- `MR_CTL_PIN_SET_EXTI_CALL`:设置外部中断回调函数。
|
||||
- `MR_CTL_PIN_GET_NUMBER`:获取引脚编号。
|
||||
- `MR_CTL_PIN_GET_EXTI_CALL`:获取外部中断回调函数。
|
||||
- `MR_IOC_PIN_SET_NUMBER`:设置引脚编号。
|
||||
- `MR_IOC_PIN_SET_MODE`:设置引脚模式。
|
||||
- `MR_IOC_PIN_SET_EXTI_CALL`:设置外部中断回调函数。
|
||||
- `MR_IOC_PIN_GET_NUMBER`:获取引脚编号。
|
||||
- `MR_IOC_PIN_GET_EXTI_CALL`:获取外部中断回调函数。
|
||||
|
||||
### 设置/获取引脚编号
|
||||
|
||||
@@ -89,11 +89,11 @@ int mr_dev_ioctl(int desc, int cmd, void *args);
|
||||
#define PIN_NUMBER 45
|
||||
|
||||
/* 设置引脚编号 */
|
||||
mr_dev_ioctl(ds, MR_CTL_PIN_SET_NUMBER, MR_MAKE_LOCAL(int, PIN_NUMBER));
|
||||
mr_dev_ioctl(ds, MR_IOC_PIN_SET_NUMBER, MR_MAKE_LOCAL(int, PIN_NUMBER));
|
||||
|
||||
/* 获取引脚编号 */
|
||||
int number;
|
||||
mr_dev_ioctl(ds, MR_CTL_PIN_GET_NUMBER, &number);
|
||||
mr_dev_ioctl(ds, MR_IOC_PIN_GET_NUMBER, &number);
|
||||
```
|
||||
|
||||
不依赖PIN接口:
|
||||
@@ -103,11 +103,11 @@ mr_dev_ioctl(ds, MR_CTL_PIN_GET_NUMBER, &number);
|
||||
#define PIN_NUMBER 45
|
||||
|
||||
/* 设置引脚编号 */
|
||||
mr_dev_ioctl(ds, MR_CTL_SET_OFFSET, MR_MAKE_LOCAL(int, PIN_NUMBER));
|
||||
mr_dev_ioctl(ds, MR_IOC_SPOS, MR_MAKE_LOCAL(int, PIN_NUMBER));
|
||||
|
||||
/* 获取引脚编号 */
|
||||
int number;
|
||||
mr_dev_ioctl(ds, MR_CTL_GET_OFFSET, &number);
|
||||
mr_dev_ioctl(ds, MR_IOC_GPOS, &number);
|
||||
```
|
||||
|
||||
### 设置引脚模式
|
||||
@@ -136,7 +136,7 @@ mr_dev_ioctl(ds, MR_CTL_GET_OFFSET, &number);
|
||||
#define PIN_MODE MR_PIN_MODE_OUTPUT
|
||||
|
||||
/* 设置引脚模式 */
|
||||
mr_dev_ioctl(ds, MR_CTL_PIN_SET_MODE, MR_MAKE_LOCAL(int, PIN_MODE));
|
||||
mr_dev_ioctl(ds, MR_IOC_PIN_SET_MODE, MR_MAKE_LOCAL(int, PIN_MODE));
|
||||
```
|
||||
|
||||
不依赖PIN接口:
|
||||
@@ -146,7 +146,7 @@ mr_dev_ioctl(ds, MR_CTL_PIN_SET_MODE, MR_MAKE_LOCAL(int, PIN_MODE));
|
||||
#define PIN_MODE 1
|
||||
|
||||
/* 设置引脚模式 */
|
||||
mr_dev_ioctl(ds, MR_CTL_SET_CONFIG, MR_MAKE_LOCAL(int, PIN_MODE));
|
||||
mr_dev_ioctl(ds, MR_IOC_SCFG, MR_MAKE_LOCAL(int, PIN_MODE));
|
||||
```
|
||||
|
||||
### 设置/获取外部中断回调函数
|
||||
@@ -154,22 +154,22 @@ mr_dev_ioctl(ds, MR_CTL_SET_CONFIG, MR_MAKE_LOCAL(int, PIN_MODE));
|
||||
```c
|
||||
#define PIN_NUMBER 45
|
||||
/* 定义外部中断回调函数 */
|
||||
int call(int desc, void *args)
|
||||
void fn(int desc, void *args)
|
||||
{
|
||||
/* 获取引脚编号 */
|
||||
ssize_t number = *(ssize_t *)args;
|
||||
|
||||
/* 处理外部中断事件 */
|
||||
|
||||
return MR_EOK;
|
||||
/* 获取引脚编号 */
|
||||
ssize_t number = *(ssize_t *)args;
|
||||
if (number == PIN_NUMBER)
|
||||
{
|
||||
/* 处理外部中断事件 */
|
||||
}
|
||||
}
|
||||
|
||||
/* 设置外部中断回调函数 */
|
||||
mr_dev_ioctl(ds, MR_CTL_PIN_SET_EXTI_CALL, call);
|
||||
mr_dev_ioctl(ds, MR_IOC_PIN_SET_EXTI_CALL, fn);
|
||||
|
||||
/* 获取外部中断回调函数 */
|
||||
int (*callback)(int desc, void *args);
|
||||
mr_dev_ioctl(ds, MR_CTL_PIN_GET_EXTI_CALL, &callback);
|
||||
void (*callback)(int desc, void *args);
|
||||
mr_dev_ioctl(ds, MR_IOC_PIN_GET_EXTI_CALL, &callback);
|
||||
```
|
||||
|
||||
不依赖PIN接口:
|
||||
@@ -177,33 +177,32 @@ mr_dev_ioctl(ds, MR_CTL_PIN_GET_EXTI_CALL, &callback);
|
||||
```c
|
||||
#define PIN_NUMBER 45
|
||||
/* 定义外部中断回调函数 */
|
||||
int call(int desc, void *args)
|
||||
void fn(int desc, void *args)
|
||||
{
|
||||
/* 获取引脚编号 */
|
||||
ssize_t number = *(ssize_t *)args;
|
||||
|
||||
/* 处理外部中断事件 */
|
||||
|
||||
return MR_EOK;
|
||||
/* 获取引脚编号 */
|
||||
ssize_t number = *(ssize_t *)args;
|
||||
if (number == PIN_NUMBER)
|
||||
{
|
||||
/* 处理外部中断事件 */
|
||||
}
|
||||
}
|
||||
|
||||
/* 设置外部中断回调函数 */
|
||||
mr_dev_ioctl(ds, MR_CTL_SET_RD_CALL, call);
|
||||
mr_dev_ioctl(ds, MR_IOC_SRCB, fn);
|
||||
|
||||
/* 获取外部中断回调函数 */
|
||||
int (*callback)(int desc, void *args);
|
||||
mr_dev_ioctl(ds, MR_CTL_GET_RD_CALL, &callback);
|
||||
void (*callback)(int desc, void *args);
|
||||
mr_dev_ioctl(ds, MR_IOC_GRCB, &callback);
|
||||
```
|
||||
|
||||
注:
|
||||
|
||||
- 设置外部中断模式前需要先配置回调函数,否则将成为无回调中断。
|
||||
- 即使PIN设备被关闭,回调函数也不会失效,直至引脚被设置为普通模式(PIN设备关闭时,外部中断将被忽略)。
|
||||
- 只要有引脚触发外部中断,即会调用所有回调函数,请一定检查是否引脚是否正确。
|
||||
|
||||
## 读取PIN设备引脚电平
|
||||
|
||||
```c
|
||||
ssize_t mr_dev_read(int desc, void *buf, size_t size);
|
||||
ssize_t mr_dev_read(int desc, void *buf, size_t count);
|
||||
```
|
||||
|
||||
| 参数 | 描述 |
|
||||
@@ -229,7 +228,7 @@ if (ret != sizeof(pin_level))
|
||||
## 写入PIN设备引脚电平
|
||||
|
||||
```c
|
||||
ssize_t mr_dev_write(int desc, const void *buf, size_t size);
|
||||
ssize_t mr_dev_write(int desc, const void *buf, size_t count);
|
||||
```
|
||||
|
||||
| 参数 | 描述 |
|
||||
@@ -263,68 +262,63 @@ if (ret != sizeof(pin_level))
|
||||
#define LED_PIN_NUMBER 45
|
||||
#define KEY_PIN_NUMBER 0
|
||||
|
||||
int key_call(int desc, void *args)
|
||||
/* 定义LED和KEY描述符 */
|
||||
int led_ds = -1;
|
||||
int key_ds = -1;
|
||||
|
||||
void key_call(int desc, void *args)
|
||||
{
|
||||
ssize_t number = *((ssize_t *)args);
|
||||
|
||||
if (number == KEY_PIN_NUMBER)
|
||||
{
|
||||
/* 打印回调函数描述符 */
|
||||
mr_printf("KEY callback, desc: %d\r\n", desc);
|
||||
/* 翻转LED引脚电平 */
|
||||
uint8_t level = 0;
|
||||
mr_dev_read(desc, &level, sizeof(level));
|
||||
level = !level;
|
||||
mr_dev_write(desc, &level, sizeof(level));
|
||||
return MR_EOK;
|
||||
mr_printf("KEY callback\r\n");
|
||||
}
|
||||
return MR_EINVAL;
|
||||
}
|
||||
|
||||
int led_key_init(void)
|
||||
void led_key_init(void)
|
||||
{
|
||||
int ret = MR_EOK;
|
||||
|
||||
/* 初始化LED */
|
||||
int led_ds = mr_dev_open("pin", MR_OFLAG_RDWR);
|
||||
led_ds = mr_dev_open("pin", MR_O_WRONLY);
|
||||
if (led_ds < 0)
|
||||
{
|
||||
mr_printf("led open failed: %s\r\n", mr_strerror(led_ds));
|
||||
return led_ds;
|
||||
return;
|
||||
}
|
||||
/* 打印LED描述符 */
|
||||
mr_printf("LED desc: %d\r\n", led_ds);
|
||||
/* 设置到LED引脚 */
|
||||
mr_dev_ioctl(led_ds, MR_CTL_PIN_SET_NUMBER, MR_MAKE_LOCAL(int, LED_PIN_NUMBER));
|
||||
mr_dev_ioctl(led_ds, MR_IOC_PIN_SET_NUMBER, MR_MAKE_LOCAL(int, LED_PIN_NUMBER));
|
||||
/* 设置LED引脚为推挽输出模式 */
|
||||
ret = mr_dev_ioctl(led_ds, MR_CTL_PIN_SET_MODE, MR_MAKE_LOCAL(int, MR_PIN_MODE_OUTPUT));
|
||||
ret = mr_dev_ioctl(led_ds, MR_IOC_PIN_SET_MODE, MR_MAKE_LOCAL(int, MR_PIN_MODE_OUTPUT));
|
||||
if (ret < 0)
|
||||
{
|
||||
mr_printf("led set mode failed: %s\r\n", mr_strerror(ret));
|
||||
return ret;
|
||||
return;
|
||||
}
|
||||
/* 设置KEY外部中断回调函数(为了演示描述符的继承机制,此处使用LED设备描述符配置KEY回调函数) */
|
||||
mr_dev_ioctl(led_ds, MR_CTL_PIN_SET_EXTI_CALL, key_call);
|
||||
|
||||
/* 初始化KEY */
|
||||
int key_ds = mr_dev_open("pin", MR_OFLAG_RDWR);
|
||||
key_ds = mr_dev_open("pin", MR_O_RDONLY);
|
||||
if (key_ds < 0)
|
||||
{
|
||||
mr_printf("key open failed: %s\r\n", mr_strerror(key_ds));
|
||||
return key_ds;
|
||||
return;
|
||||
}
|
||||
/* 打印KEY描述符 */
|
||||
mr_printf("KEY desc: %d\r\n", key_ds);
|
||||
/* 设置到KEY引脚 */
|
||||
mr_dev_ioctl(key_ds, MR_CTL_PIN_SET_NUMBER, MR_MAKE_LOCAL(int, KEY_PIN_NUMBER));
|
||||
/* 设置KEY引脚为外部中断(下降沿)模式(未重新配置回调函数,则使用上一次的结果,即LED设置的回调函数) */
|
||||
ret = mr_dev_ioctl(key_ds, MR_CTL_PIN_SET_MODE, MR_MAKE_LOCAL(int, MR_PIN_MODE_IRQ_FALLING));
|
||||
mr_dev_ioctl(key_ds, MR_IOC_PIN_SET_NUMBER, MR_MAKE_LOCAL(int, KEY_PIN_NUMBER));
|
||||
/* 设置KEY外部中断回调函数 */
|
||||
mr_dev_ioctl(key_ds, MR_IOC_PIN_SET_EXTI_CALL, key_call);
|
||||
/* 设置KEY引脚为外部中断(下降沿)模式 */
|
||||
ret = mr_dev_ioctl(key_ds, MR_IOC_PIN_SET_MODE, MR_MAKE_LOCAL(int, MR_PIN_MODE_IRQ_FALLING));
|
||||
if (ret < 0)
|
||||
{
|
||||
mr_printf("key set mode failed: %s\r\n", mr_strerror(ret));
|
||||
return ret;
|
||||
}
|
||||
return MR_EOK;
|
||||
}
|
||||
/* 导出到自动初始化(APP级) */
|
||||
MR_INIT_APP_EXPORT(led_key_init);
|
||||
@@ -336,9 +330,14 @@ int main(void)
|
||||
|
||||
while(1)
|
||||
{
|
||||
|
||||
/* 翻转LED引脚电平 */
|
||||
uint8_t level = 0;
|
||||
mr_dev_read(led_ds, &level, sizeof(level));
|
||||
level = !level;
|
||||
mr_dev_write(led_ds, &level, sizeof(level));
|
||||
mr_delay_ms(500);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
按下KEY后,LED将翻转。观察串口打印,可以看到LED和KEY的描述符。虽然KEY引脚的外部中断是KEY配置的,但未重新配置回调函数。故KEY引脚回调函数继承之前的配置,即LED配置的回调函数,所以KEY回调函数中打印的描述符为LED的描述符。
|
||||
按下KEY后,串口打印 "KEY callback",LED每500ms翻转一次。
|
||||
|
||||
@@ -20,22 +20,22 @@
|
||||
## Open PIN Device
|
||||
|
||||
```c
|
||||
int mr_dev_open(const char *name, int oflags);
|
||||
int mr_dev_open(const char *path, int flags);
|
||||
```
|
||||
|
||||
| Parameter | Description |
|
||||
|------------------|-------------------|
|
||||
| name | Device name |
|
||||
| oflags | Open device flags |
|
||||
| path | Device path |
|
||||
| flags | Open device flags |
|
||||
| **Return Value** | |
|
||||
| `>=0` | Device descriptor |
|
||||
| `<0` | Error code |
|
||||
|
||||
- `name`: The PIN device name is usually `"pin"`.
|
||||
- `oflags`: Open device flags, supports `MR_OFLAG_RDONLY`, `MR_OFLAG_WRONLY`, `MR_OFLAG_RDWR`.
|
||||
- `path`: The PIN device path is usually `"pin"`.
|
||||
- `flags`: Open device flags, supports `MR_O_RDONLY`, `MR_O_WRONLY`, `MR_O_RDWR`.
|
||||
|
||||
Note: When using, different tasks should open the PIN device separately according to actual situations and use
|
||||
appropriate `oflags` for management and permission control to ensure they won't interfere with each other.
|
||||
appropriate `flags` for management and permission control to ensure they won't interfere with each other.
|
||||
|
||||
## Close PIN Device
|
||||
|
||||
@@ -69,11 +69,11 @@ int mr_dev_ioctl(int desc, int cmd, void *args);
|
||||
| `<0` | Error code |
|
||||
|
||||
- `cmd`: Command code, supports:
|
||||
- `MR_CTL_PIN_SET_NUMBER`: Set pin number
|
||||
- `MR_CTL_PIN_SET_MODE`: Set pin mode
|
||||
- `MR_CTL_PIN_SET_EXTI_CALL`: Set external interrupt callback function
|
||||
- `MR_CTL_PIN_GET_NUMBER`: Get pin number
|
||||
- `MR_CTL_PIN_GET_EXTI_CALL`: Get external interrupt callback function
|
||||
- `MR_IOC_PIN_SET_NUMBER`: Set pin number
|
||||
- `MR_IOC_PIN_SET_MODE`: Set pin mode
|
||||
- `MR_IOC_PIN_SET_EXTI_CALL`: Set external interrupt callback function
|
||||
- `MR_IOC_PIN_GET_NUMBER`: Get pin number
|
||||
- `MR_IOC_PIN_GET_EXTI_CALL`: Get external interrupt callback function
|
||||
|
||||
### Set/Get Pin Number
|
||||
|
||||
@@ -93,11 +93,11 @@ Note: This rule may not apply to all MCUs. Special requirements need to check th
|
||||
#define PIN_NUMBER 45
|
||||
|
||||
/* Set pin number */
|
||||
mr_dev_ioctl(ds, MR_CTL_PIN_SET_NUMBER, MR_MAKE_LOCAL(int, PIN_NUMBER));
|
||||
mr_dev_ioctl(ds, MR_IOC_PIN_SET_NUMBER, MR_MAKE_LOCAL(int, PIN_NUMBER));
|
||||
|
||||
/* Get pin number */
|
||||
int number;
|
||||
mr_dev_ioctl(ds, MR_CTL_PIN_GET_NUMBER, &number);
|
||||
mr_dev_ioctl(ds, MR_IOC_PIN_GET_NUMBER, &number);
|
||||
```
|
||||
|
||||
Independent of PIN interface:
|
||||
@@ -107,11 +107,11 @@ Independent of PIN interface:
|
||||
#define PIN_NUMBER 45
|
||||
|
||||
/* Set pin number */
|
||||
mr_dev_ioctl(ds, MR_CTL_SET_OFFSET, MR_MAKE_LOCAL(int, PIN_NUMBER));
|
||||
mr_dev_ioctl(ds, MR_IOC_SPOS, MR_MAKE_LOCAL(int, PIN_NUMBER));
|
||||
|
||||
/* Get pin number */
|
||||
int number;
|
||||
mr_dev_ioctl(ds, MR_CTL_GET_OFFSET, &number);
|
||||
mr_dev_ioctl(ds, MR_IOC_GPOS, &number);
|
||||
```
|
||||
|
||||
### Set Pin Mode
|
||||
@@ -140,7 +140,7 @@ And 5 external interrupt modes:
|
||||
#define PIN_MODE MR_PIN_MODE_OUTPUT
|
||||
|
||||
/* Set pin mode */
|
||||
mr_dev_ioctl(ds, MR_CTL_PIN_SET_MODE, MR_MAKE_LOCAL(int, PIN_MODE));
|
||||
mr_dev_ioctl(ds, MR_IOC_PIN_SET_MODE, MR_MAKE_LOCAL(int, PIN_MODE));
|
||||
```
|
||||
|
||||
Independent of PIN interface:
|
||||
@@ -150,7 +150,7 @@ Independent of PIN interface:
|
||||
#define PIN_MODE 1
|
||||
|
||||
/* Set pin mode */
|
||||
mr_dev_ioctl(ds, MR_CTL_SET_CONFIG, MR_MAKE_LOCAL(int, PIN_MODE));
|
||||
mr_dev_ioctl(ds, MR_IOC_SCFG, MR_MAKE_LOCAL(int, PIN_MODE));
|
||||
```
|
||||
|
||||
### Set/Get External Interrupt Callback Function
|
||||
@@ -158,22 +158,22 @@ mr_dev_ioctl(ds, MR_CTL_SET_CONFIG, MR_MAKE_LOCAL(int, PIN_MODE));
|
||||
```c
|
||||
#define PIN_NUMBER 45
|
||||
/* Define external interrupt callback function */
|
||||
int call(int desc, void *args)
|
||||
void fn(int desc, void *args)
|
||||
{
|
||||
/* Get pin number */
|
||||
ssize_t number = *(ssize_t *)args;
|
||||
|
||||
/* Handle external interrupt event */
|
||||
|
||||
return MR_EOK;
|
||||
/* Get pin number */
|
||||
ssize_t number = *(ssize_t *)args;
|
||||
if (number == PIN_NUMBER)
|
||||
{
|
||||
/* Handle external interrupt event */
|
||||
}
|
||||
}
|
||||
|
||||
/* Set external interrupt callback function */
|
||||
mr_dev_ioctl(ds, MR_CTL_PIN_SET_EXTI_CALL, call);
|
||||
mr_dev_ioctl(ds, MR_IOC_PIN_SET_EXTI_CALL, fn);
|
||||
|
||||
/* Get external interrupt callback function */
|
||||
int (*callback)(int desc, void *args);
|
||||
mr_dev_ioctl(ds, MR_CTL_PIN_GET_EXTI_CALL, &callback);
|
||||
void (*callback)(int desc, void *args);
|
||||
mr_dev_ioctl(ds, MR_IOC_PIN_GET_EXTI_CALL, &callback);
|
||||
```
|
||||
|
||||
Independent of PIN interface:
|
||||
@@ -181,35 +181,32 @@ Independent of PIN interface:
|
||||
```c
|
||||
#define PIN_NUMBER 45
|
||||
/* Define external interrupt callback function */
|
||||
int call(int desc, void *args)
|
||||
void fn(int desc, void *args)
|
||||
{
|
||||
/* Get pin number */
|
||||
ssize_t number = *(ssize_t *)args;
|
||||
|
||||
/* Handle external interrupt event */
|
||||
|
||||
return MR_EOK;
|
||||
/* Get pin number */
|
||||
ssize_t number = *(ssize_t *)args;
|
||||
if (number == PIN_NUMBER)
|
||||
{
|
||||
/* Handle external interrupt event */
|
||||
}
|
||||
}
|
||||
|
||||
/* Set external interrupt callback function */
|
||||
mr_dev_ioctl(ds, MR_CTL_SET_RD_CALL, call);
|
||||
mr_dev_ioctl(ds, MR_IOC_SRCB, fn);
|
||||
|
||||
/* Get external interrupt callback function */
|
||||
int (*callback)(int desc, void *args);
|
||||
mr_dev_ioctl(ds, MR_CTL_GET_RD_CALL, &callback);
|
||||
void (*callback)(int desc, void *args);
|
||||
mr_dev_ioctl(ds, MR_IOC_GRCB, &callback);
|
||||
```
|
||||
|
||||
Note:
|
||||
|
||||
- Before setting the external interrupt mode, you need to configure the callback function, otherwise, it becomes a
|
||||
callback-free interrupt.
|
||||
- Even if the PIN device is closed, the callback function will not be invalid until the pin is set to a common mode (
|
||||
external interrupts will be ignored when the PIN device is closed).
|
||||
- All callbacks are called as soon as any pin triggers an external interrupt, be sure to check that the pin is correct.
|
||||
|
||||
## Read PIN Device Pin Level
|
||||
|
||||
```c
|
||||
ssize_t mr_dev_read(int desc, void *buf, size_t size);
|
||||
ssize_t mr_dev_read(int desc, void *buf, size_t count);
|
||||
```
|
||||
|
||||
| Parameter | Description |
|
||||
@@ -235,7 +232,7 @@ if (ret != sizeof(pin_level))
|
||||
## Write PIN Device Pin Level
|
||||
|
||||
```c
|
||||
ssize_t mr_dev_write(int desc, const void *buf, size_t size);
|
||||
ssize_t mr_dev_write(int desc, const void *buf, size_t count);
|
||||
```
|
||||
|
||||
| Parameter | Description |
|
||||
@@ -269,68 +266,63 @@ if (ret != sizeof(pin_level))
|
||||
#define LED_PIN_NUMBER 45
|
||||
#define KEY_PIN_NUMBER 0
|
||||
|
||||
int key_call(int desc, void *args)
|
||||
/* Define LED and KEY descriptors */
|
||||
int led_ds = -1;
|
||||
int key_ds = -1;
|
||||
|
||||
void key_call(int desc, void *args)
|
||||
{
|
||||
ssize_t number = *((ssize_t *)args);
|
||||
|
||||
if (number == KEY_PIN_NUMBER)
|
||||
{
|
||||
/* Print the callback function descriptor */
|
||||
mr_printf("KEY callback, desc: %d\r\n", desc);
|
||||
/* Toggle the LED pin level */
|
||||
uint8_t level = 0;
|
||||
mr_dev_read(desc, &level, sizeof(level));
|
||||
level = !level;
|
||||
mr_dev_write(desc, &level, sizeof(level));
|
||||
return MR_EOK;
|
||||
mr_printf("KEY callback\r\n");
|
||||
}
|
||||
return MR_EINVAL;
|
||||
}
|
||||
|
||||
int led_key_init(void)
|
||||
void led_key_init(void)
|
||||
{
|
||||
int ret = MR_EOK;
|
||||
|
||||
/* Initialize LED */
|
||||
int led_ds = mr_dev_open("pin", MR_OFLAG_RDWR);
|
||||
led_ds = mr_dev_open("pin", MR_O_WRONLY);
|
||||
if (led_ds < 0)
|
||||
{
|
||||
mr_printf("led open failed: %s\r\n", mr_strerror(led_ds));
|
||||
return led_ds;
|
||||
return;
|
||||
}
|
||||
/* Print LED descriptor */
|
||||
mr_printf("LED desc: %d\r\n", led_ds);
|
||||
/* Set to LED pin */
|
||||
mr_dev_ioctl(led_ds, MR_CTL_PIN_SET_NUMBER, MR_MAKE_LOCAL(int, LED_PIN_NUMBER));
|
||||
mr_dev_ioctl(led_ds, MR_IOC_PIN_SET_NUMBER, MR_MAKE_LOCAL(int, LED_PIN_NUMBER));
|
||||
/* Set LED pin to push-pull output mode */
|
||||
ret = mr_dev_ioctl(led_ds, MR_CTL_PIN_SET_MODE, MR_MAKE_LOCAL(int, MR_PIN_MODE_OUTPUT));
|
||||
ret = mr_dev_ioctl(led_ds, MR_IOC_PIN_SET_MODE, MR_MAKE_LOCAL(int, MR_PIN_MODE_OUTPUT));
|
||||
if (ret < 0)
|
||||
{
|
||||
mr_printf("led set mode failed: %s\r\n", mr_strerror(ret));
|
||||
return ret;
|
||||
return;
|
||||
}
|
||||
/* Set KEY external interrupt callback function (for demonstrating descriptor inheritance, use LED device descriptor to configure KEY callback function) */
|
||||
mr_dev_ioctl(led_ds, MR_CTL_PIN_SET_EXTI_CALL, key_call);
|
||||
|
||||
/* Initialize KEY */
|
||||
int key_ds = mr_dev_open("pin", MR_OFLAG_RDWR);
|
||||
key_ds = mr_dev_open("pin", MR_O_RDONLY);
|
||||
if (key_ds < 0)
|
||||
{
|
||||
mr_printf("key open failed: %s\r\n", mr_strerror(key_ds));
|
||||
return key_ds;
|
||||
return;
|
||||
}
|
||||
/* Print KEY descriptor */
|
||||
mr_printf("KEY desc: %d\r\n", key_ds);
|
||||
/* Set to KEY pin */
|
||||
mr_dev_ioctl(key_ds, MR_CTL_PIN_SET_NUMBER, MR_MAKE_LOCAL(int, KEY_PIN_NUMBER));
|
||||
mr_dev_ioctl(key_ds, MR_IOC_PIN_SET_NUMBER, MR_MAKE_LOCAL(int, KEY_PIN_NUMBER));
|
||||
/* Set KEY external interrupt callback function */
|
||||
mr_dev_ioctl(key_ds, MR_IOC_PIN_SET_EXTI_CALL, key_call);
|
||||
/* Set KEY pin to external interrupt (falling edge) mode (without reconfiguring the callback function, use the previous result, i.e. the callback function set by LED) */
|
||||
ret = mr_dev_ioctl(key_ds, MR_CTL_PIN_SET_MODE, MR_MAKE_LOCAL(int, MR_PIN_MODE_IRQ_FALLING));
|
||||
ret = mr_dev_ioctl(key_ds, MR_IOC_PIN_SET_MODE, MR_MAKE_LOCAL(int, MR_PIN_MODE_IRQ_FALLING));
|
||||
if (ret < 0)
|
||||
{
|
||||
mr_printf("key set mode failed: %s\r\n", mr_strerror(ret));
|
||||
return ret;
|
||||
}
|
||||
return MR_EOK;
|
||||
}
|
||||
/* Export to auto initialization (APP level) */
|
||||
MR_INIT_APP_EXPORT(led_key_init);
|
||||
@@ -342,14 +334,14 @@ int main(void)
|
||||
|
||||
while(1)
|
||||
{
|
||||
|
||||
/* Toggle LED pin level */
|
||||
uint8_t level = 0;
|
||||
mr_dev_read(led_ds, &level, sizeof(level));
|
||||
level = !level;
|
||||
mr_dev_write(led_ds, &level, sizeof(level));
|
||||
mr_delay_ms(500);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
After pressing the KEY, the LED will flip.
|
||||
Observe the serial port print, you can see the LED and KEY descriptors. Although the external interrupt of the KEY pin
|
||||
is configured by the KEY,
|
||||
no callback function is configured. Therefore, the KEY pin callback function inherits the previous configuration, that
|
||||
is, the callback function of the LED configuration,
|
||||
so the descriptor printed in the KEY callback function is the descriptor of the LED.
|
||||
After pressing the KEY, the serial port prints "KEY callback" and the LED flips every 500ms.
|
||||
|
||||
Reference in New Issue
Block a user