Files
mr-library/document/device/pin/pin_EN.md

348 lines
9.7 KiB
Markdown
Raw Normal View History

2023-12-28 01:19:05 +08:00
# PIN Device
[中文](pin.md)
<!-- TOC -->
* [PIN Device](#pin-device)
* [Open PIN Device](#open-pin-device)
* [Close PIN Device](#close-pin-device)
* [Control PIN Device](#control-pin-device)
* [Set/Get Pin Number](#setget-pin-number)
* [Pin Number](#pin-number)
* [Set Pin Mode](#set-pin-mode)
* [Pin Mode](#pin-mode)
* [Set/Get External Interrupt Callback Function](#setget-external-interrupt-callback-function)
* [Read PIN Device Pin Level](#read-pin-device-pin-level)
* [Write PIN Device Pin Level](#write-pin-device-pin-level)
* [Usage Example:](#usage-example)
<!-- TOC -->
## Open PIN Device
```c
int mr_dev_open(const char *path, int flags);
2023-12-28 01:19:05 +08:00
```
| Parameter | Description |
|------------------|-------------------|
| path | Device path |
| flags | Open device flags |
2023-12-28 01:19:05 +08:00
| **Return Value** | |
| `>=0` | Device descriptor |
| `<0` | Error code |
- `path`: The PIN device path is usually `"pin"`.
- `flags`: Open device flags, supports `MR_O_RDONLY`, `MR_O_WRONLY`, `MR_O_RDWR`.
2023-12-28 01:19:05 +08:00
2024-01-16 04:03:40 +08:00
Note: When using, different tasks should open the PIN device separately according to actual situations and use
appropriate `flags` for management and permission control to ensure they won't interfere with each other.
2023-12-28 01:19:05 +08:00
## Close PIN Device
```c
int mr_dev_close(int desc);
```
| Parameter | Description |
|------------------|--------------------|
| desc | Device descriptor |
| **Return Value** | |
| `=0` | Close successfully |
| `<0` | Error code |
2024-01-16 04:03:40 +08:00
Note: Closing the device will not restore the previous configuration by default. The user needs to restore it according
to the actual situation.
2023-12-28 01:19:05 +08:00
## Control PIN Device
```c
int mr_dev_ioctl(int desc, int cmd, void *args);
```
| Parameter | Description |
|------------------|-------------------|
| desc | Device descriptor |
| cmd | Command code |
| args | Command parameter |
| **Return Value** | |
| `=0` | Set successfully |
| `<0` | Error code |
- `cmd`: Command code, supports:
- `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
2023-12-28 01:19:05 +08:00
### Set/Get Pin Number
#### Pin Number
2024-01-16 04:03:40 +08:00
Different MCUs have different GPIO quantities, functions, naming rules, etc. So MR uses digital numbers to define GPIO
pins for unified interfaces on different MCUs.
2023-12-28 01:19:05 +08:00
2024-01-16 04:03:40 +08:00
The default calculation formula is: `Number = Port * 16 + Pin`, where `Port` is the GPIO port number and `Pin` is the
GPIO pin number.
2023-12-28 01:19:05 +08:00
For example, `PC13` corresponds to `Port` C, `Pin` 13, then `Number = (C - A) * 16 + 13 = 32 + 13 = 45`.
Note: This rule may not apply to all MCUs. Special requirements need to check the low-level driver settings.
```c
/* Define pin number */
#define PIN_NUMBER 45
/* Set pin number */
mr_dev_ioctl(ds, MR_IOC_PIN_SET_NUMBER, MR_MAKE_LOCAL(int, PIN_NUMBER));
2023-12-28 01:19:05 +08:00
/* Get pin number */
int number;
mr_dev_ioctl(ds, MR_IOC_PIN_GET_NUMBER, &number);
2023-12-28 01:19:05 +08:00
```
2024-01-18 03:29:46 +08:00
Independent of PIN interface:
```c
/* Define pin number */
#define PIN_NUMBER 45
/* Set pin number */
mr_dev_ioctl(ds, MR_IOC_SPOS, MR_MAKE_LOCAL(int, PIN_NUMBER));
2024-01-18 03:29:46 +08:00
/* Get pin number */
int number;
mr_dev_ioctl(ds, MR_IOC_GPOS, &number);
2024-01-18 03:29:46 +08:00
```
2023-12-28 01:19:05 +08:00
### Set Pin Mode
#### Pin Mode
MR supports 6 common modes:
- `MR_PIN_MODE_NONE`: No mode, pin returns to default status
- `MR_PIN_MODE_OUTPUT`: Output mode, pin is push-pull output mode
- `MR_PIN_MODE_OUTPUT_OD`: Output mode, pin is open-drain output mode
- `MR_PIN_MODE_INPUT`: Input mode, pin is floating input mode
- `MR_PIN_MODE_INPUT_DOWN`: Input mode, pin is pull-down input mode
- `MR_PIN_MODE_INPUT_UP`: Input mode, pin is pull-up input mode
And 5 external interrupt modes:
- `MR_PIN_MODE_IRQ_RISING`: External interrupt mode, triggered on rising edge
- `MR_PIN_MODE_IRQ_FALLING`: External interrupt mode, triggered on falling edge
- `MR_PIN_MODE_IRQ_EDGE`: External interrupt mode, triggered on both edges
- `MR_PIN_MODE_IRQ_LOW`: External interrupt mode, triggered on low level
- `MR_PIN_MODE_IRQ_HIGH`: External interrupt mode, triggered on high level
```c
/* Define pin mode */
#define PIN_MODE MR_PIN_MODE_OUTPUT
/* Set pin mode */
mr_dev_ioctl(ds, MR_IOC_PIN_SET_MODE, MR_MAKE_LOCAL(int, PIN_MODE));
2023-12-28 01:19:05 +08:00
```
2024-01-18 03:29:46 +08:00
Independent of PIN interface:
```c
/* Define pin mode */
#define PIN_MODE 1
/* Set pin mode */
mr_dev_ioctl(ds, MR_IOC_SCFG, MR_MAKE_LOCAL(int, PIN_MODE));
2024-01-18 03:29:46 +08:00
```
2023-12-28 01:19:05 +08:00
### Set/Get External Interrupt Callback Function
```c
#define PIN_NUMBER 45
/* Define external interrupt callback function */
void fn(int desc, void *args)
2023-12-28 01:19:05 +08:00
{
/* Get pin number */
ssize_t number = *(ssize_t *)args;
if (number == PIN_NUMBER)
{
/* Handle external interrupt event */
}
2023-12-28 01:19:05 +08:00
}
/* Set external interrupt callback function */
mr_dev_ioctl(ds, MR_IOC_PIN_SET_EXTI_CALL, fn);
2023-12-28 01:19:05 +08:00
/* Get external interrupt callback function */
void (*callback)(int desc, void *args);
mr_dev_ioctl(ds, MR_IOC_PIN_GET_EXTI_CALL, &callback);
2023-12-28 01:19:05 +08:00
```
2024-01-18 03:29:46 +08:00
Independent of PIN interface:
```c
#define PIN_NUMBER 45
/* Define external interrupt callback function */
void fn(int desc, void *args)
2024-01-18 03:29:46 +08:00
{
/* Get pin number */
ssize_t number = *(ssize_t *)args;
if (number == PIN_NUMBER)
{
/* Handle external interrupt event */
}
2024-01-18 03:29:46 +08:00
}
/* Set external interrupt callback function */
mr_dev_ioctl(ds, MR_IOC_SRCB, fn);
2024-01-18 03:29:46 +08:00
/* Get external interrupt callback function */
void (*callback)(int desc, void *args);
mr_dev_ioctl(ds, MR_IOC_GRCB, &callback);
2024-01-18 03:29:46 +08:00
```
2023-12-28 01:19:05 +08:00
Note:
- All callbacks are called as soon as any pin triggers an external interrupt, be sure to check that the pin is correct.
2023-12-28 01:19:05 +08:00
## Read PIN Device Pin Level
```c
ssize_t mr_dev_read(int desc, void *buf, size_t count);
2023-12-28 01:19:05 +08:00
```
| Parameter | Description |
|------------------|-------------------|
| desc | Device descriptor |
| buf | Read data buffer |
2024-02-02 16:38:44 +08:00
| count | Read data size |
2023-12-28 01:19:05 +08:00
| **Return Value** | |
| `>=0` | Read data size |
| `<0` | Error code |
```c
/* Read pin level */
uint8_t pin_level;
int ret = mr_dev_read(ds, &pin_level, sizeof(pin_level));
/* Check if read successfully */
if (ret != sizeof(pin_level))
{
return ret;
}
```
## Write PIN Device Pin Level
```c
ssize_t mr_dev_write(int desc, const void *buf, size_t count);
2023-12-28 01:19:05 +08:00
```
| Parameter | Description |
|------------------|-------------------|
| desc | Device descriptor |
| buf | Write data buffer |
2024-02-02 16:38:44 +08:00
| count | Write data size |
2023-12-28 01:19:05 +08:00
| **Return Value** | |
| `>=0` | Write data size |
| `<0` | Error code |
2024-01-16 04:03:40 +08:00
- Level: `0`: Low level; `1`: High level.
2023-12-28 01:19:05 +08:00
```c
/* Write pin level */
2024-01-16 04:03:40 +08:00
uint8_t pin_level = 1;
2023-12-28 01:19:05 +08:00
int ret = mr_dev_write(ds, &pin_level, sizeof(pin_level));
/* Check if write successfully */
if (ret != sizeof(pin_level))
{
return ret;
}
```
## Usage Example:
```c
#include "include/mr_lib.h"
/* Define LED pin (PC13) and KEY pin (PA0) */
#define LED_PIN_NUMBER 45
#define KEY_PIN_NUMBER 0
/* Define LED and KEY descriptors */
int led_ds = -1;
int key_ds = -1;
void key_call(int desc, void *args)
2023-12-28 01:19:05 +08:00
{
ssize_t number = *((ssize_t *)args);
if (number == KEY_PIN_NUMBER)
{
/* Print the callback function descriptor */
mr_printf("KEY callback\r\n");
2023-12-28 01:19:05 +08:00
}
}
void led_key_init(void)
2023-12-28 01:19:05 +08:00
{
int ret = MR_EOK;
/* Initialize LED */
led_ds = mr_dev_open("pin", MR_O_WRONLY);
2023-12-28 01:19:05 +08:00
if (led_ds < 0)
{
mr_printf("led open failed: %s\r\n", mr_strerror(led_ds));
return;
2023-12-28 01:19:05 +08:00
}
/* Print LED descriptor */
mr_printf("LED desc: %d\r\n", led_ds);
/* Set to LED pin */
mr_dev_ioctl(led_ds, MR_IOC_PIN_SET_NUMBER, MR_MAKE_LOCAL(int, LED_PIN_NUMBER));
2023-12-28 01:19:05 +08:00
/* Set LED pin to push-pull output mode */
ret = mr_dev_ioctl(led_ds, MR_IOC_PIN_SET_MODE, MR_MAKE_LOCAL(int, MR_PIN_MODE_OUTPUT));
2023-12-28 01:19:05 +08:00
if (ret < 0)
{
mr_printf("led set mode failed: %s\r\n", mr_strerror(ret));
return;
2023-12-28 01:19:05 +08:00
}
/* Initialize KEY */
key_ds = mr_dev_open("pin", MR_O_RDONLY);
2023-12-28 01:19:05 +08:00
if (key_ds < 0)
{
mr_printf("key open failed: %s\r\n", mr_strerror(key_ds));
return;
2023-12-28 01:19:05 +08:00
}
/* Print KEY descriptor */
mr_printf("KEY desc: %d\r\n", key_ds);
/* Set to KEY pin */
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);
2023-12-28 01:19:05 +08:00
/* 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_IOC_PIN_SET_MODE, MR_MAKE_LOCAL(int, MR_PIN_MODE_IRQ_FALLING));
2023-12-28 01:19:05 +08:00
if (ret < 0)
{
mr_printf("key set mode failed: %s\r\n", mr_strerror(ret));
}
}
/* Export to auto initialization (APP level) */
MR_INIT_APP_EXPORT(led_key_init);
2023-12-28 01:19:05 +08:00
int main(void)
{
/* Auto initialization (led_key_init function will be automatically called here) */
mr_auto_init();
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);
2023-12-28 01:19:05 +08:00
}
}
```
After pressing the KEY, the serial port prints "KEY callback" and the LED flips every 500ms.