GPS Device
Loading...
Searching...
No Matches
stm32f401re_gpio.c
Go to the documentation of this file.
1
11
12#include "stm32f401re_gpio.h"
13#include "common.h"
14#include "stm32f401re.h"
15#include "stm32f401re_rcc.h"
16#include "arm_cortex_m4_nvic.h"
17
18/* ---- Forward declarations for internal helpers ---- */
19static void gpio_set_pclk(GPIO_REGDEF_ts const *gpio_port, EN_STATUS_te en_status);
21static uint8_t get_exti_position(GPIO_CFG_ts const *gpio_cfg);
22
27
29void gpio_init(GPIO_CFG_ts *gpio_cfg) {
30 // Enable the clock for the GPIO peripheral
31 gpio_set_pclk(gpio_cfg->port, ENABLE);
32
33 // Configure GPIO output type
34 gpio_cfg->port->GPIO_OTYPER &= ~(0b1 << gpio_cfg->pin);
35 gpio_cfg->port->GPIO_OTYPER |= gpio_cfg->output_type << gpio_cfg->pin;
36
37 // Configure GPIO speed
38 gpio_cfg->port->GPIO_OSPEEDR &= ~(0b11 << gpio_cfg->pin * 2);
39 gpio_cfg->port->GPIO_OSPEEDR |= gpio_cfg->output_speed << gpio_cfg->pin * 2;
40
41 // Configure GPIO pull-up pull-down
42 gpio_cfg->port->GPIO_PUPDR &= ~(0b11 << gpio_cfg->pin * 2);
43 gpio_cfg->port->GPIO_PUPDR |= gpio_cfg->pull_mode << gpio_cfg->pin * 2;
44
45 // Configure GPIO alternate function (2 bits per pin in AFR[0] for pins 0-7, AFR[1] for pins 8-15)
46 uint32_t afr_index = gpio_cfg->pin >> 3; // pin / 8 selects AFR[0] or AFR[1]
47 uint32_t afr_shift = (gpio_cfg->pin & 0x7) * 4; // (pin % 8) * 4 gives the bit offset
48
49 gpio_cfg->port->GPIO_AFR[afr_index] &= ~(0xFu << afr_shift);
50 gpio_cfg->port->GPIO_AFR[afr_index] |= ((uint32_t)gpio_cfg->alternate_function << afr_shift);
51
52 // Configure GPIO mode
53 if(gpio_cfg->mode != GPIO_MODE_INTERRUPT) {
54 gpio_cfg->port->GPIO_MODER &= ~(0b11 << gpio_cfg->pin * 2);
55 gpio_cfg->port->GPIO_MODER |= gpio_cfg->mode << gpio_cfg->pin * 2;
56 }
57 else {
58 // Enable the peripheral clock for SYSCFG
59 RCC->RCC_APB2ENR |= (0b1 << 14);
60
61 // Route the GPIO pin to the EXTI line via SYSCFG_EXTICRx
62 if(gpio_cfg->pin < 4) {
63 SYSCFG->SYSCFG_EXTICR1 &= ~(0b1111 << gpio_cfg->pin * 4);
64 SYSCFG->SYSCFG_EXTICR1 |= (get_syscfg_code(gpio_cfg->port)) << gpio_cfg->pin * 4;
65 }
66 else if(gpio_cfg->pin < 8) {
67 SYSCFG->SYSCFG_EXTICR2 &= ~(0b1111 << (gpio_cfg->pin - 4) * 4);
68 SYSCFG->SYSCFG_EXTICR2 |= (get_syscfg_code(gpio_cfg->port)) << (gpio_cfg->pin - 4) * 4;
69 }
70 else if(gpio_cfg->pin < 12) {
71 SYSCFG->SYSCFG_EXTICR3 &= ~(0b1111 << (gpio_cfg->pin - 8) * 4);
72 SYSCFG->SYSCFG_EXTICR3 |= (get_syscfg_code(gpio_cfg->port)) << (gpio_cfg->pin - 8) * 4;
73 }
74 else {
75 SYSCFG->SYSCFG_EXTICR4 &= ~(0b1111 << (gpio_cfg->pin - 12) * 4);
76 SYSCFG->SYSCFG_EXTICR4 |= (get_syscfg_code(gpio_cfg->port)) << (gpio_cfg->pin - 12) * 4;
77 }
78
79 // Unmask the EXTI line for this pin
80 EXTI->EXTI_IMR |= 0b1 << gpio_cfg->pin;
81
82 // Configure edge trigger
83 switch(gpio_cfg->interrupt_trigger) {
85 EXTI->EXTI_RTSR |= 0b1 << gpio_cfg->pin;
86 break;
88 EXTI->EXTI_FTSR |= 0b1 << gpio_cfg->pin;
89 break;
91 EXTI->EXTI_RTSR |= 0b1 << gpio_cfg->pin;
92 EXTI->EXTI_FTSR |= 0b1 << gpio_cfg->pin;
93 break;
94 }
95
96 // Enable the corresponding NVIC interrupt line
97 uint8_t exti_position = get_exti_position(gpio_cfg);
98 nvic_set_interrupt(exti_position, ENABLE);
99 }
100}
101
103void gpio_deinit(GPIO_REGDEF_ts const *gpio_port) {
104 if(gpio_port == GPIOA) {
106 }
107 else if(gpio_port == GPIOB) {
109 }
110 else if(gpio_port == GPIOC) {
112 }
113 else if(gpio_port == GPIOD) {
115 }
116 else if(gpio_port == GPIOE) {
118 }
119 else if(gpio_port == GPIOH) {
121 }
122
123 gpio_set_pclk(gpio_port, DISABLE);
124}
125
127void gpio_write(GPIO_REGDEF_ts *gpio_port, uint8_t gpio_pin, PIN_STATUS_te pin_status) {
128 switch(pin_status) {
129 case HIGH:
130 gpio_port->GPIO_ODR |= (0x1 << gpio_pin);
131 break;
132 case LOW:
133 gpio_port->GPIO_ODR &= ~(0x1 << gpio_pin);
134 break;
135 }
136}
137
139PIN_STATUS_te gpio_read(GPIO_REGDEF_ts const *gpio_port, uint8_t gpio_pin) {
140 PIN_STATUS_te status = (gpio_port->GPIO_IDR >> gpio_pin) & 0x1;
141 return status;
142}
143
146 EXTI->EXTI_PR = 0x1 << exti_line;
147}
148
150void gpio_get_name(GPIO_REGDEF_ts const *gpio_port, char *name) {
151 const char gpio[] = "GPIO";
152 uint8_t gpio_len = get_str_len(gpio);
153 uint8_t pos_counter = 0;
154
155 while(pos_counter < gpio_len) {
156 name[pos_counter] = gpio[pos_counter];
157 pos_counter++;
158 }
159
160 if(gpio_port == GPIOA) name[pos_counter] = 'A';
161 else if(gpio_port == GPIOB) name[pos_counter] = 'B';
162 else if(gpio_port == GPIOC) name[pos_counter] = 'C';
163 else if(gpio_port == GPIOD) name[pos_counter] = 'D';
164 else if(gpio_port == GPIOE) name[pos_counter] = 'E';
165 else if(gpio_port == GPIOH) name[pos_counter] = 'H';
166 pos_counter++;
167
168 name[pos_counter] = '\0';
169}
170
172
177
188static void gpio_set_pclk(GPIO_REGDEF_ts const *gpio_port, EN_STATUS_te en_status) {
189 if(gpio_port == GPIOA) {
191 }
192 else if(gpio_port == GPIOB) {
194 }
195 else if(gpio_port == GPIOC) {
197 }
198 else if(gpio_port == GPIOD) {
200 }
201 else if(gpio_port == GPIOE) {
203 }
204 else if(gpio_port == GPIOH) {
206 }
207}
208
222 if(gpio_port == GPIOA) return PA;
223 else if(gpio_port == GPIOB) return PB;
224 else if(gpio_port == GPIOC) return PC;
225 else if(gpio_port == GPIOD) return PD;
226 else if(gpio_port == GPIOE) return PE;
227 return PH;
228}
229
244static uint8_t get_exti_position(GPIO_CFG_ts const *gpio_cfg) {
245 if(gpio_cfg->pin == 0) return EXTI0_IRQn;
246 else if(gpio_cfg->pin == 1) return EXTI1_IRQn;
247 else if(gpio_cfg->pin == 2) return EXTI2_IRQn;
248 else if(gpio_cfg->pin == 3) return EXTI3_IRQn;
249 else if(gpio_cfg->pin == 4) return EXTI4_IRQn;
250 else if(gpio_cfg->pin < 10 && gpio_cfg->pin > 4) return EXTI9_5_IRQn;
251 return EXTI15_10_IRQn;
252}
253
Arm Cortex-M4 NVIC driver public API.
Common utility module public API.
uint32_t get_str_len(char const *str)
Returns the length of a string, excluding the null terminator.
Definition common.c:22
PIN_STATUS_te
Represents the logical level of a GPIO pin.
Definition common.h:84
EN_STATUS_te
Represents an enabled or disabled state.
Definition common.h:95
@ HIGH
Definition common.h:89
@ LOW
Definition common.h:86
@ ENABLE
Definition common.h:100
@ DISABLE
Definition common.h:97
void nvic_set_interrupt(IRQn_te interrupt_line, EN_STATUS_te en_status)
Enables or disables an interrupt line in the NVIC.
static PORT_CODES_ts get_syscfg_code(GPIO_REGDEF_ts const *port)
Returns the SYSCFG port code for a GPIO port instance.
static uint8_t get_exti_position(GPIO_CFG_ts const *gpio_cfg)
Returns the IRQ number for the EXTI line corresponding to a GPIO pin.
static void gpio_set_pclk(GPIO_REGDEF_ts const *gpio_port, EN_STATUS_te en_status)
Enables or disables the peripheral clock for a GPIO port.
PIN_STATUS_te gpio_read(GPIO_REGDEF_ts const *gpio_port, uint8_t gpio_pin)
Reads the current logic level of a GPIO input pin.
void gpio_write(GPIO_REGDEF_ts *gpio_port, uint8_t gpio_pin, PIN_STATUS_te pin_status)
Drives a GPIO output pin high or low.
void gpio_deinit(GPIO_REGDEF_ts const *gpio_port)
Deinitializes a GPIO port by resetting its registers to reset values.
void gpio_get_name(GPIO_REGDEF_ts const *gpio_port, char *name)
Returns the name string of a GPIO port.
void gpio_init(GPIO_CFG_ts *gpio_cfg)
Initializes a GPIO pin according to the given configuration.
void gpio_clear_interrupt(EXTI_LINES_te exti_line)
Clears the EXTI pending flag for the given interrupt line.
@ GPIO_INTERRUPT_TRIGGER_RE
@ GPIO_INTERRUPT_TRIGGER_RFE
@ GPIO_INTERRUPT_TRIGGER_FE
@ GPIO_MODE_INTERRUPT
void rcc_set_pclk_ahb1(RCC_AHB1ENR_te periph_position, EN_STATUS_te en_status)
Enables or disables the peripheral clock for an AHB1 peripheral.
void rcc_reset_periph_ahb1(RCC_AHB1RSTR_te periph_position)
Resets an AHB1 peripheral via RCC_AHB1RSTR.
#define GPIOC
#define SYSCFG
#define GPIOB
#define RCC
#define GPIOD
#define EXTI
#define GPIOA
#define GPIOH
#define GPIOE
@ RCC_AHB1RSTR_GPIOHRST
@ RCC_AHB1RSTR_GPIODRST
@ RCC_AHB1RSTR_GPIOBRST
@ RCC_AHB1RSTR_GPIOARST
@ RCC_AHB1RSTR_GPIOCRST
@ RCC_AHB1RSTR_GPIOERST
@ RCC_AHB1ENR_GPIOAEN
@ RCC_AHB1ENR_GPIOCEN
@ RCC_AHB1ENR_GPIOHEN
@ RCC_AHB1ENR_GPIOBEN
@ RCC_AHB1ENR_GPIOEEN
@ RCC_AHB1ENR_GPIODEN
PORT_CODES_ts
SYSCFG port codes for EXTICRx routing.
EXTI_LINES_te
EXTI line numbers.
@ PH
@ PE
@ PB
@ PC
@ PA
@ PD
@ EXTI2_IRQn
@ EXTI15_10_IRQn
@ EXTI9_5_IRQn
@ EXTI0_IRQn
@ EXTI4_IRQn
@ EXTI3_IRQn
@ EXTI1_IRQn
STM32F401RE MCU-specific peripheral register definitions and bit position enumerations.
STM32F401RE GPIO driver public API.
STM32F401RE RCC driver public API.
Configuration structure for initializing a GPIO pin.
GPIO_REGDEF_ts * port
GPIO_PULL_MODE_te pull_mode
GPIO_ALTERNATE_FUNCTION_te alternate_function
GPIO_INTERRUPT_TRIGGER_te interrupt_trigger
GPIO_OUTPUT_TYPE_te output_type
GPIO_PIN_te pin
GPIO_OUTPUT_SPEED_te output_speed
GPIO_MODE_te mode
GPIO peripheral register map.
Definition stm32f401re.h:95
uint32_t volatile GPIO_IDR
uint32_t volatile GPIO_ODR
uint32_t volatile GPIO_PUPDR
Definition stm32f401re.h:99
uint32_t volatile GPIO_OTYPER
Definition stm32f401re.h:97
uint32_t volatile GPIO_AFR[2]
uint32_t volatile GPIO_MODER
Definition stm32f401re.h:96
uint32_t volatile GPIO_OSPEEDR
Definition stm32f401re.h:98