1.移除单一引脚中断回调,使用设备框架通用回调机制。

This commit is contained in:
MacRsh
2024-01-31 22:42:21 +08:00
parent 7d5d7f2d3d
commit 7566385e31
3 changed files with 159 additions and 244 deletions

View File

@@ -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 */

View File

@@ -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翻转一次

View File

@@ -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.