88 lines
2.4 KiB
C
88 lines
2.4 KiB
C
/** @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-------------------------------------------------------------
|