1 | /* |
---|
2 | * Copyright (c) 2012 Sebastian Huber. All rights reserved. |
---|
3 | * |
---|
4 | * embedded brains GmbH |
---|
5 | * Obere Lagerstr. 30 |
---|
6 | * 82178 Puchheim |
---|
7 | * Germany |
---|
8 | * <rtems@embedded-brains.de> |
---|
9 | * |
---|
10 | * The license and distribution terms for this file may be |
---|
11 | * found in the file LICENSE in this distribution or at |
---|
12 | * http://www.rtems.com/license/LICENSE. |
---|
13 | */ |
---|
14 | |
---|
15 | #include <bsp/io.h> |
---|
16 | #include <bsp/rcc.h> |
---|
17 | |
---|
18 | #include <rtems.h> |
---|
19 | |
---|
20 | RTEMS_STATIC_ASSERT(sizeof(stm32f4_gpio_config) == 4, size_of_config); |
---|
21 | |
---|
22 | void stm32f4_gpio_set_clock(int pin, bool set) |
---|
23 | { |
---|
24 | int port = STM32F4_GPIO_PORT_OF_PIN(pin); |
---|
25 | stm32f4_rcc_index index = STM32F4_RCC_GPIOA + port; |
---|
26 | |
---|
27 | stm32f4_rcc_set_clock(index, set); |
---|
28 | } |
---|
29 | |
---|
30 | static void clear_and_set( |
---|
31 | volatile uint32_t *reg, |
---|
32 | unsigned index, |
---|
33 | unsigned width, |
---|
34 | uint32_t set |
---|
35 | ) |
---|
36 | { |
---|
37 | uint32_t mask = (1U << width) - 1U; |
---|
38 | unsigned shift = width * index; |
---|
39 | uint32_t val = *reg; |
---|
40 | |
---|
41 | val &= ~(mask << shift); |
---|
42 | val |= set << shift; |
---|
43 | |
---|
44 | *reg = val; |
---|
45 | } |
---|
46 | |
---|
47 | static void set_config(unsigned pin, const stm32f4_gpio_config *config) |
---|
48 | { |
---|
49 | unsigned port = STM32F4_GPIO_PORT_OF_PIN(pin); |
---|
50 | volatile stm32f4_gpio *gpio = STM32F4_GPIO(port); |
---|
51 | unsigned index = STM32F4_GPIO_INDEX_OF_PIN(pin); |
---|
52 | unsigned af_reg = index >> 3; |
---|
53 | unsigned af_index = index & 0x7; |
---|
54 | int set_or_clear_offset = config->fields.output ? 0 : 16; |
---|
55 | rtems_interrupt_level level; |
---|
56 | |
---|
57 | rtems_interrupt_disable(level); |
---|
58 | gpio->bsrr = 1U << (index + set_or_clear_offset); |
---|
59 | clear_and_set(&gpio->pupdr, index, 2, config->fields.pupd); |
---|
60 | clear_and_set(&gpio->otyper, index, 1, config->fields.otype); |
---|
61 | clear_and_set(&gpio->ospeedr, index, 2, config->fields.ospeed); |
---|
62 | clear_and_set(&gpio->afr [af_reg], af_index, 4, config->fields.af); |
---|
63 | clear_and_set(&gpio->moder, index, 2, config->fields.mode); |
---|
64 | rtems_interrupt_enable(level); |
---|
65 | } |
---|
66 | |
---|
67 | void stm32f4_gpio_set_config(const stm32f4_gpio_config *config) |
---|
68 | { |
---|
69 | int current = config->fields.pin_first; |
---|
70 | int last = config->fields.pin_last; |
---|
71 | |
---|
72 | while (current <= last) { |
---|
73 | stm32f4_gpio_set_clock(current, true); |
---|
74 | set_config(current, config); |
---|
75 | ++current; |
---|
76 | } |
---|
77 | } |
---|
78 | |
---|
79 | void stm32f4_gpio_set_config_array(const stm32f4_gpio_config *configs) |
---|
80 | { |
---|
81 | stm32f4_gpio_config terminal = STM32F4_GPIO_CONFIG_TERMINAL; |
---|
82 | |
---|
83 | while (configs->value != terminal.value) { |
---|
84 | stm32f4_gpio_set_config(configs); |
---|
85 | ++configs; |
---|
86 | } |
---|
87 | } |
---|
88 | |
---|
89 | void stm32f4_gpio_set_output(int pin, bool set) |
---|
90 | { |
---|
91 | int port = STM32F4_GPIO_PORT_OF_PIN(pin); |
---|
92 | volatile stm32f4_gpio *gpio = STM32F4_GPIO(port); |
---|
93 | int index = STM32F4_GPIO_INDEX_OF_PIN(pin); |
---|
94 | int set_or_clear_offset = set ? 0 : 16; |
---|
95 | |
---|
96 | gpio->bsrr = 1U << (index + set_or_clear_offset); |
---|
97 | } |
---|
98 | |
---|
99 | bool stm32f4_gpio_get_input(int pin) |
---|
100 | { |
---|
101 | int port = STM32F4_GPIO_PORT_OF_PIN(pin); |
---|
102 | volatile stm32f4_gpio *gpio = STM32F4_GPIO(port); |
---|
103 | int index = STM32F4_GPIO_INDEX_OF_PIN(pin); |
---|
104 | |
---|
105 | return (gpio->idr & (1U << index)) != 0; |
---|
106 | } |
---|