RTT PIN驱动框架分析


I/O设备模型框架

基础分析

设备驱动层:具体实现如stm32_pin_write_pin(int pin,int value){hal_write_pin(int pin,int value);}
设备驱动框架层:套壳,实现统一接口rt_write_pin(int pin,int value){hw_write_pin(stm32->write_pin,int pin,int value);}

PIN设备API

PIN设备通过PIN设备管理接口访问GPIO
PIN设备API

框架分析

project/rt-thread/components/drivers/pin/dev_pin.c下有驱动框架层

1
2
3
4
5
6
7
8
9
10
11
/* Get pin number by name, such as PA.0, P0.12 */
rt_base_t rt_pin_get(const char *name)
{
RT_ASSERT(_hw_pin.ops != RT_NULL);

if (_hw_pin.ops->pin_get == RT_NULL)
{
return -RT_ENOSYS;
}
return _hw_pin.ops->pin_get(name);
}

定位static struct rt_device_pin _hw_pin;,这个变量下有ops函数,找初始化赋值的地方

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
int rt_device_pin_register(const char *name, const struct rt_pin_ops *ops, void *user_data)
{
_hw_pin.parent.type = RT_Device_Class_Pin;
_hw_pin.parent.rx_indicate = RT_NULL;
_hw_pin.parent.tx_complete = RT_NULL;

#ifdef RT_USING_DEVICE_OPS
_hw_pin.parent.ops = &pin_ops;
#else
_hw_pin.parent.init = RT_NULL;
_hw_pin.parent.open = RT_NULL;
_hw_pin.parent.close = RT_NULL;
_hw_pin.parent.read = _pin_read;
_hw_pin.parent.write = _pin_write;
_hw_pin.parent.control = _pin_control;
#endif

_hw_pin.ops = ops;
_hw_pin.parent.user_data = user_data;

/* register a character device */
rt_device_register(&_hw_pin.parent, name, RT_DEVICE_FLAG_RDWR);

return 0;
}

这是注册函数,全局搜索找驱动层具体实现,在project/libraries/HAL_Drivers/drivers/drv_gpio.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
int rt_hw_pin_init(void)
{
#if defined(__HAL_RCC_GPIOA_CLK_ENABLE)
__HAL_RCC_GPIOA_CLK_ENABLE();
#endif

//... ...

return rt_device_pin_register("pin", &_stm32_pin_ops, RT_NULL);
}

static const struct rt_pin_ops _stm32_pin_ops =
{
stm32_pin_mode,
stm32_pin_write,
stm32_pin_read,
stm32_pin_attach_irq,
stm32_pin_dettach_irq,
stm32_pin_irq_enable,
stm32_pin_get,
RT_NULL,
};

由此可以实现驱动框架层到驱动层的具体实现,即_hw_pin.ops = _stm32_pin_ops;

rt_get_pin()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
/* e.g. PE.7 */
static rt_base_t stm32_pin_get(const char *name)
{
rt_base_t pin = 0;
int hw_port_num, hw_pin_num = 0;
int i, name_len;

name_len = rt_strlen(name);

if ((name_len < 4) || (name_len >= 6))
{
goto out;
}
if ((name[0] != 'P') || (name[2] != '.'))
{
goto out;
}

if ((name[1] >= 'A') && (name[1] <= 'Z'))
{
hw_port_num = (int)(name[1] - 'A');
}
else
{
goto out;
}

for (i = 3; i < name_len; i++)
{
hw_pin_num *= 10;
hw_pin_num += name[i] - '0';
}

pin = PIN_NUM(hw_port_num, hw_pin_num);

return pin;

out:
rt_kprintf("Px.y x:A~Z y:0-15, e.g. PA.0\n");
return -RT_EINVAL;
}

不止一种方式可以获取编号,后者直接使用rt_pin_write(后者在nano版下的也可以用)

1
#define GET_PIN(PORTx,PIN) (rt_uint64_t)((((rt_uint64_t)GPIO_PIN_##PIN) << 32) | (rt_uint64_t)(rt_ubase_t)GPIO##PORTx)

rt_pin_mode()

上层调用rt_pin_mode(),向下调用stm32_pin_mode()使用具体的驱动函数

1
2
3
4
5
6
/* RT-Thread Hardware PIN APIs */
void rt_pin_mode(rt_base_t pin, rt_uint8_t mode)
{
RT_ASSERT(_hw_pin.ops != RT_NULL);
_hw_pin.ops->pin_mode(&_hw_pin.parent, pin, mode);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
static void stm32_pin_mode(rt_device_t dev, rt_base_t pin, rt_uint8_t mode)
{
GPIO_InitTypeDef GPIO_InitStruct;

if (PIN_PORT(pin) >= PIN_STPORT_MAX)
{
return;
}

/* Configure GPIO_InitStructure */
GPIO_InitStruct.Pin = PIN_STPIN(pin);
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;

if (mode == PIN_MODE_OUTPUT)
{
/* output setting */
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
}
else if (mode == PIN_MODE_INPUT)
{
/* input setting: not pull. */
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
}
else if (mode == PIN_MODE_INPUT_PULLUP)
{
/* input setting: pull up. */
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
}
else if (mode == PIN_MODE_INPUT_PULLDOWN)
{
/* input setting: pull down. */
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
}
else if (mode == PIN_MODE_OUTPUT_OD)
{
/* output setting: od. */
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
GPIO_InitStruct.Pull = GPIO_NOPULL;
}

HAL_GPIO_Init(PIN_STPORT(pin), &GPIO_InitStruct);
}

中断

调用链HAL->pin_irq_hdr()
通过rt_pin_attach_irq()rt_pin_detach_irq()注册和注销中断回调函数

注销中断回调函数不会关闭中断
底层同样是stm32_pin_attach_irq()