Add C++ Gpio driver

This commit is contained in:
Thomas Klaehn
2020-12-17 10:51:20 +01:00
parent 75dda2e6eb
commit 4dd55be05c
3 changed files with 181 additions and 49 deletions

101
platform/stm32g0xx/Gpio.cc Normal file
View File

@@ -0,0 +1,101 @@
#include "stm32g0xx.h"
#include "platform/stm32g0xx/Gpio.h"
using namespace perinet::platform::stm32g0xx;
Gpio::Gpio(Port port, uint32_t pin, Mode mode, Pullup pullup, AlternateFunction alternate_function)
{
switch(port) {
case Port::PORT_A:
this->port = GPIOA;
/* Enable PORT A clock*/
SET_BIT(RCC->IOPENR, RCC_IOPENR_GPIOAEN);
/* Delay after an RCC peripheral clock enabling */
READ_BIT(RCC->IOPENR, RCC_IOPENR_GPIOAEN);
break;
case Port::PORT_B:
this->port = GPIOB;
/* Enable PORT B clock*/
SET_BIT(RCC->IOPENR, RCC_IOPENR_GPIOBEN);
/* Delay after an RCC peripheral clock enabling */
READ_BIT(RCC->IOPENR, RCC_IOPENR_GPIOBEN);
break;
case Port::PORT_C:
this->port = GPIOC;
/* Enable PORT C clock*/
SET_BIT(RCC->IOPENR, RCC_IOPENR_GPIOCEN);
/* Delay after an RCC peripheral clock enabling */
READ_BIT(RCC->IOPENR, RCC_IOPENR_GPIOCEN);
break;
case Port::PORT_D:
this->port = GPIOD;
/* Enable PORT D clock*/
SET_BIT(RCC->IOPENR, RCC_IOPENR_GPIODEN);
/* Delay after an RCC peripheral clock enabling */
READ_BIT(RCC->IOPENR, RCC_IOPENR_GPIODEN);
break;
case Port::PORT_F:
this->port = GPIOF;
/* Enable PORT F clock*/
SET_BIT(RCC->IOPENR, RCC_IOPENR_GPIOFEN);
/* Delay after an RCC peripheral clock enabling */
READ_BIT(RCC->IOPENR, RCC_IOPENR_GPIOFEN);
break;
}
this->pin = pin;
/* Configure the IO Speed */
volatile uint32_t temp = this->port->OSPEEDR;
temp &= ~(GPIO_OSPEEDR_OSPEED0 << (this->pin * 2u));
temp |= (static_cast<uint32_t>(Speed::FREQ_HIGH) << (this->pin * 2u));
this->port->OSPEEDR = temp;
/* Configure the IO Output Type */
temp = this->port->OTYPER;
temp &= ~(GPIO_OTYPER_OT0 << this->pin);
temp |= (((static_cast<uint32_t>(mode) & 0x00000010u) >> 4u) << this->pin);
this->port->OTYPER = temp;
/* Activate the Pull-up or Pull down resistor for the current IO */
temp = this->port->PUPDR;
temp &= ~(GPIO_PUPDR_PUPD0 << (this->pin * 2u));
temp |= ((static_cast<uint32_t>(pullup)) << (this->pin * 2u));
this->port->PUPDR = temp;
/* Configure Alternate function mapped with the current IO */
temp = this->port->AFR[this->pin >> 3u];
temp &= ~(0xFu << ((this->pin & 0x07u) * 4u));
temp |= ((static_cast<uint32_t>(alternate_function)) << ((this->pin & 0x07u) * 4u));
this->port->AFR[this->pin >> 3u] = temp;
/* Configure IO Direction mode (Input, Output, Alternate or Analog) */
temp = this->port->MODER;
temp &= ~(GPIO_MODER_MODE0 << (this->pin * 2u));
temp |= ((static_cast<uint32_t>(mode) & 0x00000003u) << (this->pin * 2u));
this->port->MODER = temp;
}
void Gpio::set()
{
this->port->BSRR = 1 << this->pin;
}
void Gpio::clear()
{
this->port->BRR = 1 << this->pin;
}
void Gpio::toggle()
{
// get current Output Data Register value
volatile uint32_t odr = this->port->ODR;
// Set selected pins that were at low level, and reset ones that were high
this->port->BSRR = ((odr & (1 << this->pin)) << 16) | (~odr & (1 << this->pin));
}
uint32_t Gpio::get()
{
return (this->port->IDR & (1 << this->pin)) >> this->pin;
}

76
platform/stm32g0xx/Gpio.h Normal file
View File

@@ -0,0 +1,76 @@
#ifndef __PLATFORM_STM32G0XX_GPIO_H__
#define __PLATFORM_STM32G0XX_GPIO_H__
#include <cstdint>
#include "stm32g071xx.h"
namespace perinet::platform::stm32g0xx {
class Gpio
{
public:
enum class Port
{
PORT_A,
PORT_B,
PORT_C,
PORT_D,
PORT_F
};
enum class Speed
{
FREQ_LOW = 0, // Low speed
FREQ_MEDIUM, // Medium speed
FREQ_HIGH, // High speed
FREQ_VERY_HIGH // Very high speed
};
enum class Mode
{
MODE_INPUT = 0x00, // Input Floating Mode
MODE_OUTPUT_PP = 0x01, // Output Push Pull Mode
MODE_AF_PP = 0x02, // Alternate Function Push Pull Mode
MODE_ANALOG = 0x03, // Analog Mode
MODE_OUTPUT_OD = 0x11, // Output Open Drain Mode
MODE_AF_OD = 0x12, // Alternate Function Open Drain Mode
};
enum class Pullup
{
NOPULL = 0, // No Pull-up or Pull-down activation
PULLUP, // Pull-up activation
PULLDOWN // Pull-down activation
};
enum class AlternateFunction
{
ALTERNATE_FUNCTION_0 = 0,
ALTERNATE_FUNCTION_1,
ALTERNATE_FUNCTION_2,
ALTERNATE_FUNCTION_3,
ALTERNATE_FUNCTION_4,
ALTERNATE_FUNCTION_5,
ALTERNATE_FUNCTION_6,
ALTERNATE_FUNCTION_7,
ALTERNATE_FUNCTION_8,
ALTERNATE_FUNCTION_9,
ALTERNATE_FUNCTION_10,
};
Gpio(Port, uint32_t, Mode=Mode::MODE_INPUT, Pullup=Pullup::NOPULL, AlternateFunction=AlternateFunction::ALTERNATE_FUNCTION_0);
uint32_t get();
void set();
void clear();
void toggle();
private:
GPIO_TypeDef *port;
uint32_t pin;
};
}
#endif