From 0418e3d5c54ffa6dd66677d889d2fc33f9542561 Mon Sep 17 00:00:00 2001 From: Luca Date: Mon, 1 Sep 2025 01:55:18 -0700 Subject: [PATCH] Set up GPIO infrastructure --- .../GPIO/Reg/SHAL_GPIO_REG_F072xB.h | 126 ++++++++++++++++++ SHAL/Include/Peripheral/GPIO/SHAL_GPIO.h | 52 ++++++-- SHAL/Include/Peripheral/Timer/SHAL_TIM.h | 3 +- SHAL/Include/SHAL.h | 2 +- SHAL/Src/Peripheral/GPIO/SHAL_GPIO.cpp | 37 ++++- 5 files changed, 202 insertions(+), 18 deletions(-) diff --git a/SHAL/Include/Peripheral/GPIO/Reg/SHAL_GPIO_REG_F072xB.h b/SHAL/Include/Peripheral/GPIO/Reg/SHAL_GPIO_REG_F072xB.h index 0253ab6..fbd3528 100644 --- a/SHAL/Include/Peripheral/GPIO/Reg/SHAL_GPIO_REG_F072xB.h +++ b/SHAL/Include/Peripheral/GPIO/Reg/SHAL_GPIO_REG_F072xB.h @@ -10,11 +10,15 @@ #include "SHAL_CORE.h" +#define AVAILABLE_PORTS 3 +#define PINS_PER_PORT 16 + #define AVAILABLE_GPIO \ X(A0) X(A1) X(A2) X(A3) X(A4) X(A5) X(A6) X(A7) X(A8) X(A9) X(A10) X(A11) X(A12) X(A13) X(A14) X(A15) \ X(B0) X(B1) X(B2) X(B3) X(B4) X(B5) X(B6) X(B7) X(B8) X(B9) X(B10) X(B11) X(B12) X(B13) X(B14) X(B15) \ X(C0) X(C1) X(C2) X(C3) X(C4) X(C5) X(C6) X(C7) X(C8) X(C9) X(C10) X(C11) X(C12) X(C13) X(C14) X(C15) + //Build enum map of available GPIO pins enum class GPIO_Key { #define X(key) key, @@ -83,4 +87,126 @@ constexpr SHAL_Peripheral getGPIORegister(const GPIO_Key g){ __builtin_unreachable(); } +constexpr SHAL_Peripheral_Register getGPIORCCEnable(const GPIO_Key g){ + switch(g) { + case GPIO_Key::A0: + case GPIO_Key::A1: + case GPIO_Key::A2: + case GPIO_Key::A3: + case GPIO_Key::A4: + case GPIO_Key::A5: + case GPIO_Key::A6: + case GPIO_Key::A7: + case GPIO_Key::A8: + case GPIO_Key::A9: + case GPIO_Key::A10: + case GPIO_Key::A11: + case GPIO_Key::A12: + case GPIO_Key::A13: + case GPIO_Key::A14: + case GPIO_Key::A15: + return {&RCC->AHBENR, RCC_AHBENR_GPIOAEN_Pos}; + case GPIO_Key::B0: + case GPIO_Key::B1: + case GPIO_Key::B2: + case GPIO_Key::B3: + case GPIO_Key::B4: + case GPIO_Key::B5: + case GPIO_Key::B6: + case GPIO_Key::B7: + case GPIO_Key::B8: + case GPIO_Key::B9: + case GPIO_Key::B10: + case GPIO_Key::B11: + case GPIO_Key::B12: + case GPIO_Key::B13: + case GPIO_Key::B14: + case GPIO_Key::B15: + return {&RCC->AHBENR, RCC_AHBENR_GPIOBEN_Pos}; + case GPIO_Key::C0: + case GPIO_Key::C1: + case GPIO_Key::C2: + case GPIO_Key::C3: + case GPIO_Key::C4: + case GPIO_Key::C5: + case GPIO_Key::C6: + case GPIO_Key::C7: + case GPIO_Key::C8: + case GPIO_Key::C9: + case GPIO_Key::C10: + case GPIO_Key::C11: + case GPIO_Key::C12: + case GPIO_Key::C13: + case GPIO_Key::C14: + case GPIO_Key::C15: + return {&RCC->AHBENR, RCC_AHBENR_GPIOCEN_Pos}; + case GPIO_Key::INVALID: + case GPIO_Key::NUM_GPIO: + assert(false); + return SHAL_Peripheral_Register(nullptr,0); //Unreachable + } + __builtin_unreachable(); +} + +constexpr unsigned int getGPIOPortNumber(const GPIO_Key g){ + switch(g) { + case GPIO_Key::A0: + case GPIO_Key::A1: + case GPIO_Key::A2: + case GPIO_Key::A3: + case GPIO_Key::A4: + case GPIO_Key::A5: + case GPIO_Key::A6: + case GPIO_Key::A7: + case GPIO_Key::A8: + case GPIO_Key::A9: + case GPIO_Key::A10: + case GPIO_Key::A11: + case GPIO_Key::A12: + case GPIO_Key::A13: + case GPIO_Key::A14: + case GPIO_Key::A15: + return 0; + case GPIO_Key::B0: + case GPIO_Key::B1: + case GPIO_Key::B2: + case GPIO_Key::B3: + case GPIO_Key::B4: + case GPIO_Key::B5: + case GPIO_Key::B6: + case GPIO_Key::B7: + case GPIO_Key::B8: + case GPIO_Key::B9: + case GPIO_Key::B10: + case GPIO_Key::B11: + case GPIO_Key::B12: + case GPIO_Key::B13: + case GPIO_Key::B14: + case GPIO_Key::B15: + return 1; + case GPIO_Key::C0: + case GPIO_Key::C1: + case GPIO_Key::C2: + case GPIO_Key::C3: + case GPIO_Key::C4: + case GPIO_Key::C5: + case GPIO_Key::C6: + case GPIO_Key::C7: + case GPIO_Key::C8: + case GPIO_Key::C9: + case GPIO_Key::C10: + case GPIO_Key::C11: + case GPIO_Key::C12: + case GPIO_Key::C13: + case GPIO_Key::C14: + case GPIO_Key::C15: + return 2; + case GPIO_Key::INVALID: + case GPIO_Key::NUM_GPIO: + assert(false); + return 0; + } + __builtin_unreachable(); +} + #endif //SHMINGO_HAL_SHAL_GPIO_REG_F072XB_H diff --git a/SHAL/Include/Peripheral/GPIO/SHAL_GPIO.h b/SHAL/Include/Peripheral/GPIO/SHAL_GPIO.h index 569064d..29d0a62 100644 --- a/SHAL/Include/Peripheral/GPIO/SHAL_GPIO.h +++ b/SHAL/Include/Peripheral/GPIO/SHAL_GPIO.h @@ -11,17 +11,28 @@ #include "SHAL_GPIO_REG_F072xB.h" enum class PinMode { - INPUT_MODE = 0b00, - OUTPUT_MODE = 0b01, - ALTERNATE_FUNCTION_MODE = 0b10, - ANALOG_MODE = 0b11 + INPUT_MODE, + OUTPUT_MODE, + ALTERNATE_FUNCTION_MODE, + ANALOG_MODE, + INVALID }; -enum class PinValue { - HI = 1, - LOW = 0, -}; +unsigned long getPinMode(PinMode mode){ + switch(mode){ + case PinMode::INPUT_MODE: + return 0b00; + case PinMode::OUTPUT_MODE: + return 0b01; + case PinMode::ALTERNATE_FUNCTION_MODE: + return 0b10; + case PinMode::ANALOG_MODE: + return 0b11; + } +} + +//Abstraction of GPIO registers class GPIO{ public: @@ -36,10 +47,31 @@ private: friend class GPIOManager; - explicit GPIO(GPIO_Key key); + explicit GPIO(GPIO_Key key, PinMode pinMode); GPIO(); - GPIO_Key GPIO_KEY; + GPIO_Key m_GPIO_KEY = GPIO_Key::INVALID; + PinMode m_pinMode = PinMode::INVALID; + + GPIO_TypeDef* p_GPIORegister = nullptr; + unsigned long m_offset = 0; +}; + + +#define initGPIO(GPIO_KEY, PIN_MODE) GPIOManager::get(GPIO_KEY, PIN_MODE) + +//Manages instances of GPIO objects +class GPIOManager{ + +public: + + static GPIO& get(GPIO_Key, PinMode pinMode); + GPIOManager() = delete; + +private: + +inline static GPIO m_gpios[AVAILABLE_PORTS][PINS_PER_PORT] = {}; + }; #endif //SHMINGO_HAL_SHAL_GPIO_H diff --git a/SHAL/Include/Peripheral/Timer/SHAL_TIM.h b/SHAL/Include/Peripheral/Timer/SHAL_TIM.h index b0220a2..484b75e 100644 --- a/SHAL/Include/Peripheral/Timer/SHAL_TIM.h +++ b/SHAL/Include/Peripheral/Timer/SHAL_TIM.h @@ -47,7 +47,8 @@ private: }; -#define getTimer(timer_key) TimerManager::get(timer_key); + +#define getTimer(timer_key) TimerManager::get(timer_key) //Manages all timers so user does not have to personally initialize class TimerManager{ diff --git a/SHAL/Include/SHAL.h b/SHAL/Include/SHAL.h index d79a854..3b404b3 100644 --- a/SHAL/Include/SHAL.h +++ b/SHAL/Include/SHAL.h @@ -9,6 +9,6 @@ #define SHAL_H #include "SHAL_TIM.h" - +#include "SHAL_GPIO.h" #endif diff --git a/SHAL/Src/Peripheral/GPIO/SHAL_GPIO.cpp b/SHAL/Src/Peripheral/GPIO/SHAL_GPIO.cpp index a330046..c5c992a 100644 --- a/SHAL/Src/Peripheral/GPIO/SHAL_GPIO.cpp +++ b/SHAL/Src/Peripheral/GPIO/SHAL_GPIO.cpp @@ -4,22 +4,47 @@ #include "SHAL_GPIO.h" -GPIO::GPIO() { - +GPIO::GPIO(){ + //Do not initialize anything } -GPIO::GPIO(GPIO_Key key) { +GPIO::GPIO(GPIO_Key key, PinMode pinMode) : m_GPIO_KEY(key), + p_GPIORegister(static_cast(getGPIORegister(key).registers)), + m_offset(getGPIORegister(key).global_offset){ + volatile unsigned long* gpioEnable = getGPIORCCEnable(key).reg; + unsigned long gpioOffset = getGPIORCCEnable(key).offset; + + *gpioEnable |= (1 << gpioOffset); + + p_GPIORegister->MODER |= (getPinMode(pinMode) << (2 * m_offset)); } void GPIO::setLow() { - getGPIORegister(GPIO_KEY)->ODR &= ~(1 << getGPIOAPB(GPIO_KEY).offset); + p_GPIORegister->ODR &= ~(1 << m_offset); } void GPIO::setHigh() { - getGPIORegister(GPIO_KEY)->ODR |= (1 << getGPIOAPB(GPIO_KEY).offset); + p_GPIORegister->ODR |= (1 << m_offset); + } void GPIO::toggle() { - + p_GPIORegister->ODR ^= (1 << m_offset); +} + + + +GPIO &GPIOManager::get(GPIO_Key key, PinMode pinMode) { + + unsigned int gpioPort = getGPIOPortNumber(key); + unsigned long gpioPin = getGPIORegister(key).global_offset; //Use existing structs to get offset + + GPIO curr = m_gpios[gpioPort][gpioPin]; + + if(curr.m_GPIO_KEY == GPIO_Key::INVALID || curr.m_pinMode != pinMode){ + m_gpios[gpioPort][gpioPin] = GPIO(key,pinMode); + } + + return m_gpios[gpioPort][gpioPin]; }