forked from lvd2/bluepill-serial-monster
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgpio.c
64 lines (59 loc) · 1.98 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
/*
* 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;
}