-
Notifications
You must be signed in to change notification settings - Fork 81
/
Copy pathgpio.c
77 lines (71 loc) · 2.39 KB
/
gpio.c
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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
/*
* MIT License
*
* Copyright (c) 2020 Kirill Kotyagin
*/
#include "gpio.h"
static void _gpio_enable_port(GPIO_TypeDef *port) {
int portnum = (((uint32_t)port - GPIOA_BASE) / (GPIOB_BASE - GPIOA_BASE));
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN << portnum;
}
void gpio_pin_init(const gpio_pin_t *pin) {
if (pin->port) {
volatile uint32_t *crx = &pin->port->CRL + (pin->pin >> 3);
uint8_t crx_offset = (pin->pin & 0x07) << 2;
uint32_t modecfg = 0;
_gpio_enable_port(pin->port);
*crx &= ~((GPIO_CRL_CNF0 | GPIO_CRL_MODE0) << crx_offset);
if (pin->dir == gpio_dir_input) {
if (pin->pull == gpio_pull_floating) {
modecfg |= GPIO_CRL_CNF0_0;
} else {
modecfg |= GPIO_CRL_CNF0_1;
pin->port->BSRR = ((pin->pull == gpio_pull_up) ? GPIO_BSRR_BS0 : GPIO_BSRR_BR0) << pin->pin;
}
} else {
switch (pin->speed) {
case gpio_speed_unknown:
case gpio_speed_low:
modecfg |= GPIO_CRL_MODE0_1;
break;
case gpio_speed_medium:
modecfg |= GPIO_CRL_MODE0_0;
break;
case gpio_speed_high:
modecfg |= GPIO_CRL_MODE0;
break;
}
if (pin->output == gpio_output_od) {
modecfg |= GPIO_CRL_CNF0_0;
}
if (pin->func == gpio_func_alternate) {
modecfg |= GPIO_CRL_CNF0_1;
}
}
*crx |= (modecfg << crx_offset);
}
}
void gpio_pin_set(const gpio_pin_t *pin, int is_active) {
if (pin->port) {
pin->port->BSRR = (GPIO_BSRR_BS0 << pin->pin)
<< (!!is_active != (pin->polarity == gpio_polarity_low) ? 0 : GPIO_BSRR_BR0_Pos);
}
}
int gpio_pin_get(const gpio_pin_t *pin) {
if (pin->port) {
return (!!(pin->port->IDR & (GPIO_IDR_IDR0 << pin->pin))) != (pin->polarity == gpio_polarity_low);
}
return 0;
}
volatile uint32_t *gpio_pin_get_bitband_clear_addr(const gpio_pin_t *pin) {
volatile uint32_t result = 0;
if (pin->port) {
result = PERIPH_BB_BASE;
result += ((uint32_t)(&pin->port->BSRR) - PERIPH_BASE) << 5;
result += pin->pin << 2;
if (pin->polarity == gpio_polarity_high) {
result += GPIO_BSRR_BR0_Pos << 2;
}
}
return (volatile uint32_t*)result;
}