/** @file gpio.c * Module handling General Purpose Input/Output (GPIO) pins * * The module provides functions to configure the gpio pins and read from/ * write to them */ //--includes-------------------------------------------------------------------- #include "gpio.h" #include "gpio_regs.h" #include "rcc.h" //--local definitions----------------------------------------------------------- static volatile struct GPIO* regs = (struct GPIO*)GPIO_BASE_ADDRESS; //--local variables------------------------------------------------------------- //--public functions------------------------------------------------------------ /** * Use the provided mask to generate its equivalent with 3 bits of padding * between each initial bit. This new mask matches the registers layout and * allow for direct application of the mode and config. Outputs are disabled * prior to confiiguration to avoid any glitches. The relevant clocks are * automatically enabled for the ports used */ void gpio_configure(enum GpioPort port, enum GpioPin pin_mask, enum GpioMode mode, enum GpioConfig config) { //ensure gpio port is enabled rcc_enable(RCC_AHB_NONE, RCC_APB1_NONE, RCC_APB2_IOPA << port); //reset outputs before configuring anything regs->PORTS[port].BRR.word |= pin_mask; //clear config for selected port, then apply new config, 8 first pins uint32_t mask = 0; for (uint8_t i=0; i<8; ++i) { if (pin_mask & (0x1 << i)) { mask |= 0x1 << (i * 4); } } regs->PORTS[port].CRL.word &= ~(0xF * mask); regs->PORTS[port].CRL.word |= (config << 2) | (mode << 0) * mask; //clear config for selected port, then apply new config, 8 last pins mask = 0; pin_mask = pin_mask >> 8; for (uint8_t i=0; i<8; ++i) { if (pin_mask & (0x1 << i)) { mask |= 0x1 << (i * 4); } } regs->PORTS[port].CRH.word &= ~(0xF * mask); regs->PORTS[port].CRH.word |= (config << 2) | (mode << 0) * mask; } void gpio_reset(enum GpioPort port, enum GpioPin pin_mask) { gpio_configure(port, pin_mask, GPIO_MODE_INPUT, GPIO_CONFIG_IN_FLOATING); } void gpio_write(enum GpioPort port, enum GpioPin pin_mask, bool value) { if (value) { regs->PORTS[port].BSRR.word |= pin_mask; } else { regs->PORTS[port].BRR.word |= pin_mask; } } bool gpio_read(enum GpioPort port, enum GpioPin pin_mask) { return (regs->PORTS[port].IDR.word & pin_mask) == pin_mask; } //--local functions-------------------------------------------------------------