embox
288 строк · 7.6 Кб
1/**
2* @file stm32_gpio_l0x0.c
3* @brief
4* @author Vadim Deryabkin
5* @version
6* @date 07.02.2021
7*/
8
9#include <assert.h>10#include <string.h>11
12#include <embox/unit.h>13#include <lib/libds/array.h>14
15#include <kernel/irq.h>16
17#include <drivers/gpio/gpio_driver.h>18
19#include "stm32_gpio_conf_l0x0.h"20
21static gpio_struct *get_gpio (unsigned char port) {22uint8_t *p = (uint8_t *)GPIOA;23p += 1024 * port;24return (gpio_struct *)p;25}
26
27static void set_gpio_mode_output (gpio_struct* GPIO, gpio_mask_t pins) {28uint32_t buf_mode = 0;29uint32_t msk_mode = 0;30for (int i = 0; i < PINS_NUMBER; i++) {31if (pins & (1 << i)) {32buf_mode |= M_PP(i);33msk_mode |= M_MSK(i);34}35}36
37GPIO->MODER &= ~msk_mode;38GPIO->MODER |= buf_mode;39}
40
41static void set_gpio_mode_input (gpio_struct* GPIO, gpio_mask_t pins) {42uint32_t msk_mode = 0;43for (int i = 0; i < PINS_NUMBER; i++) {44if (pins & (1 << i)) {45msk_mode |= M_MSK(i);46}47}48
49GPIO->MODER &= ~msk_mode;50}
51
52static void set_gpio_mode_pull_up (gpio_struct* GPIO, gpio_mask_t pins) {53uint32_t buf_mode = 0;54uint32_t msk_mode = 0;55for (int i = 0; i < PINS_NUMBER; i++) {56if (pins & (1 << i)) {57buf_mode |= P_PU(i);58msk_mode |= P_MSK(i);59}60}61
62GPIO->PUPDR &= ~msk_mode;63GPIO->PUPDR |= buf_mode;64}
65
66static void set_gpio_mode_pull_down (gpio_struct* GPIO, gpio_mask_t pins) {67uint32_t buf_mode = 0;68uint32_t msk_mode = 0;69for (int i = 0; i < PINS_NUMBER; i++) {70if (pins & (1 << i)) {71buf_mode |= P_PD(i);72msk_mode |= P_MSK(i);73}74}75
76GPIO->PUPDR &= ~msk_mode;77GPIO->PUPDR |= buf_mode;78}
79
80static void set_gpio_high_spped (gpio_struct* GPIO, gpio_mask_t pins) {81uint32_t buf_mode = 0;82uint32_t msk_mode = 0;83for (int i = 0; i < PINS_NUMBER; i++) {84if (pins & (1 << i)) {85buf_mode |= S_HS(i);86msk_mode |= S_MSK(i);87}88}89
90GPIO->OSPEEDR &= ~msk_mode;91GPIO->OSPEEDR |= buf_mode;92}
93
94static void set_gpio_mode_alt_func (gpio_struct* GPIO, gpio_mask_t pins,95uint32_t func) {96uint32_t buf_mode = 0;97uint32_t msk_mode = 0;98for (int i = 0; i < PINS_NUMBER / 2; i++) {99if (pins & (1 << i)) {100buf_mode |= L_AF(i, func);101msk_mode |= L_AF_MSK(i);102}103}104
105GPIO->AFRL &= ~msk_mode;106GPIO->AFRL |= buf_mode;107
108buf_mode = 0;109msk_mode = 0;110for (int i = PINS_NUMBER / 2; i < PINS_NUMBER; i++) {111if (pins & (1 << i)) {112buf_mode |= H_AF(i, func);113msk_mode |= H_AF_MSK(i);114}115}116
117GPIO->AFRH &= ~msk_mode;118GPIO->AFRH |= buf_mode;119
120buf_mode = 0;121msk_mode = 0;122for (int i = 0; i < PINS_NUMBER; i++) {123if (pins & (1 << i)) {124buf_mode |= M_ALT(i);125msk_mode |= M_MSK(i);126}127}128
129GPIO->MODER &= ~msk_mode;130GPIO->MODER |= buf_mode;131}
132
133static void set_gpio_mode_open_drain (gpio_struct* GPIO, gpio_mask_t pins) {134GPIO->OTYPER |= pins;135}
136
137static void set_gpio_mode_push_pull (gpio_struct* GPIO, gpio_mask_t pins) {138GPIO->OTYPER &= ~pins;139}
140
141static void set_gpio_it_rising (gpio_mask_t pins) {142EXTI->RTSR |= pins;143}
144
145static void reset_gpio_it_rising (gpio_mask_t pins) {146EXTI->RTSR &= ~pins;147}
148
149static void set_gpio_it_falling (gpio_mask_t pins) {150EXTI->FTSR |= pins;151}
152
153static void reset_gpio_it_falling (gpio_mask_t pins) {154EXTI->FTSR &= ~pins;155}
156
157static void set_exti_interrupt (unsigned char port, gpio_mask_t pins) {158for (int i = 0; i < PINS_NUMBER; i++) {159if (pins & (1 << i)) {160SYSCFG->EXTICR[i / 4] &= ~(0xF << 4 * (i % 4)); // DocID025023 Rev 4, 147/779.161SYSCFG->EXTICR[i / 4] |= port << 4 * (i % 4);162}163}164
165EXTI->PR = pins;166EXTI->EMR |= pins;167EXTI->IMR |= pins;168}
169
170static void reset_exti_interrupt (unsigned char port, gpio_mask_t pins) {171EXTI->EMR &= ~pins;172EXTI->IMR &= ~pins;173EXTI->PR = pins;174}
175
176static int stm32_gpio_setup_mode(unsigned char port, gpio_mask_t pins, int mode) {177assert(!((port == GPIO_PORT_F) || (port == GPIO_PORT_G) || (port > GPIO_PORT_H)));178
179set_gpio_pwr(port);180
181gpio_struct* GPIO = get_gpio(port);182
183set_gpio_high_spped(GPIO, pins);184
185if (mode & GPIO_MODE_OUT) {186set_gpio_mode_output(GPIO, pins);187
188if (mode & GPIO_MODE_OUT_OPEN_DRAIN) set_gpio_mode_open_drain(GPIO, pins);189if (mode & GPIO_MODE_OUT_PUSH_PULL) set_gpio_mode_push_pull(GPIO, pins);190reset_exti_interrupt(port, pins);191} else if (mode & GPIO_MODE_IN) {192set_gpio_mode_input(GPIO, pins);193
194if (mode & GPIO_MODE_IN_PULL_UP) set_gpio_mode_pull_up(GPIO, pins);195if (mode & GPIO_MODE_IN_PULL_DOWN) set_gpio_mode_pull_down(GPIO, pins);196reset_exti_interrupt(port, pins);197} else if (mode & GPIO_MODE_OUT_ALTERNATE) {198uint32_t func = GPIO_GET_ALTERNATE(mode);199set_gpio_mode_alt_func(GPIO, pins, func);200
201if (mode & GPIO_MODE_IN_PULL_UP) set_gpio_mode_pull_up(GPIO, pins);202if (mode & GPIO_MODE_IN_PULL_DOWN) set_gpio_mode_pull_down(GPIO, pins);203if (mode & GPIO_MODE_OUT_PUSH_PULL) set_gpio_mode_push_pull(GPIO, pins);204if (mode & GPIO_MODE_OUT_OPEN_DRAIN) set_gpio_mode_open_drain(GPIO, pins);205
206reset_exti_interrupt(port, pins);207} else if (mode & GPIO_MODE_INT_MODE_RISING_FALLING) {208if ((mode & GPIO_MODE_INT_MODE_RISING_FALLING) ==209GPIO_MODE_INT_MODE_RISING_FALLING) {210set_gpio_it_rising(pins);211set_gpio_it_falling(pins);212} else if (mode & GPIO_MODE_INT_MODE_RISING) {213set_gpio_it_rising(pins);214reset_gpio_it_falling(pins);215} else if (mode & GPIO_MODE_INT_MODE_FALLING) {216reset_gpio_it_rising(pins);217set_gpio_it_falling(pins);218}219
220set_exti_interrupt(port, pins);221}222
223return 0;224}
225
226static void stm32_gpio_set(unsigned char port, gpio_mask_t pins, char level) {227assert(!((port == GPIO_PORT_F) || (port == GPIO_PORT_G) || (port > GPIO_PORT_H)));228
229gpio_struct* GPIO = get_gpio(port);230
231if (level) {232GPIO->BSRR = pins;233} else {234GPIO->BRR = pins;235}236}
237
238static gpio_mask_t stm32_gpio_get(unsigned char port, gpio_mask_t pins) {239assert(!((port == GPIO_PORT_F) || (port == GPIO_PORT_G) || (port > GPIO_PORT_H)));240
241gpio_struct* GPIO = get_gpio(port);242
243return GPIO->IDR & pins;244}
245
246
247static struct gpio_chip stm32_gpio_chip = {248.setup_mode = stm32_gpio_setup_mode,249.get = stm32_gpio_get,250.set = stm32_gpio_set,251.nports = STM32_GPIO_PORTS_COUNT252};253
254irq_return_t stm32_gpio_irq_handler(unsigned int irq_nr, void *data) {255uint16_t pending = EXTI->PR;256EXTI->PR = 0xFFFF;257
258/* Notify all GPIO ports about interrupt */259for (int i = 0; i < STM32_GPIO_PORTS_COUNT; i++) {260gpio_handle_irq(&stm32_gpio_chip, i, pending);261}262
263return IRQ_HANDLED;264}
265
266static const unsigned char exti_irqs[] = {267EXTI0_1_IRQ, EXTI2_3_IRQ, EXTI4_15_IRQ268};269
270static int stm32_gpio_init(void) {271int res, i;272
273for (i = 0; i < ARRAY_SIZE(exti_irqs); i++) {274res = irq_attach(exti_irqs[i], stm32_gpio_irq_handler, 0, NULL,275"STM32 EXTI irq handler");276if (res < 0) {277return -1;278}279}280
281return gpio_register_chip(&stm32_gpio_chip, STM32_GPIO_CHIP_ID);282}
283
284EMBOX_UNIT_INIT(stm32_gpio_init);285
286STATIC_IRQ_ATTACH(EXTI0_1_IRQ, stm32_gpio_irq_handler, NULL);287STATIC_IRQ_ATTACH(EXTI2_3_IRQ, stm32_gpio_irq_handler, NULL);288STATIC_IRQ_ATTACH(EXTI4_15_IRQ, stm32_gpio_irq_handler, NULL);289