From 55f03031b333e85e36d14982d1e01beb0a7f4cac Mon Sep 17 00:00:00 2001 From: Ea-r-th <39779954+Ea-r-th@users.noreply.github.com> Date: Tue, 9 Sep 2025 20:11:17 -0700 Subject: [PATCH 01/13] Added files for I2C --- CMakeLists.txt | 2 ++ SHAL/Include/Core/SHAL_CORE.h | 13 +++++++--- .../Include/Peripheral/I2C/Reg/SHAL_I2C_REG.h | 8 ++++++ .../Peripheral/I2C/Reg/SHAL_I2C_REG_F072xB.h | 20 +++++++++++++++ .../Peripheral/I2C/Reg/SHAL_I2C_TYPES.h | 25 +++++++++++++++++++ SHAL/Include/Peripheral/I2C/SHAL_I2C.h | 8 ++++++ .../Peripheral/UART/Reg/SHAL_UART_TYPES.h | 12 +-------- 7 files changed, 74 insertions(+), 14 deletions(-) create mode 100644 SHAL/Include/Peripheral/I2C/Reg/SHAL_I2C_REG.h create mode 100644 SHAL/Include/Peripheral/I2C/Reg/SHAL_I2C_REG_F072xB.h create mode 100644 SHAL/Include/Peripheral/I2C/Reg/SHAL_I2C_TYPES.h create mode 100644 SHAL/Include/Peripheral/I2C/SHAL_I2C.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 7f5496a..dd62483 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,6 +36,8 @@ set(PROJECT_INCLUDE_DIRECTORIES SHAL/Include/Peripheral/GPIO/Reg SHAL/Include/Peripheral/UART SHAL/Include/Peripheral/UART/Reg + SHAL/Include/Peripheral/I2C + SHAL/Include/Peripheral/I2C/Reg SHAL/Include/Peripheral/EXT/ ${CMAKE_CURRENT_SOURCE_DIR}/SHAL/Include ) diff --git a/SHAL/Include/Core/SHAL_CORE.h b/SHAL/Include/Core/SHAL_CORE.h index c37cda4..3c4ef85 100644 --- a/SHAL/Include/Core/SHAL_CORE.h +++ b/SHAL/Include/Core/SHAL_CORE.h @@ -13,9 +13,16 @@ //Universal structs and defines --------------------------- - - - +enum class AF_Mask : uint8_t{ + AF0, + AF1, + AF2, + AF3, + AF4, + AF5, + AF6, + AF7 +}; //--------------------------------------------------------- diff --git a/SHAL/Include/Peripheral/I2C/Reg/SHAL_I2C_REG.h b/SHAL/Include/Peripheral/I2C/Reg/SHAL_I2C_REG.h new file mode 100644 index 0000000..291321a --- /dev/null +++ b/SHAL/Include/Peripheral/I2C/Reg/SHAL_I2C_REG.h @@ -0,0 +1,8 @@ +// +// Created by Luca on 9/9/2025. +// + +#ifndef SHMINGO_HAL_SHAL_I2C_REG_H +#define SHMINGO_HAL_SHAL_I2C_REG_H + +#endif //SHMINGO_HAL_SHAL_I2C_REG_H diff --git a/SHAL/Include/Peripheral/I2C/Reg/SHAL_I2C_REG_F072xB.h b/SHAL/Include/Peripheral/I2C/Reg/SHAL_I2C_REG_F072xB.h new file mode 100644 index 0000000..ecee868 --- /dev/null +++ b/SHAL/Include/Peripheral/I2C/Reg/SHAL_I2C_REG_F072xB.h @@ -0,0 +1,20 @@ +// +// Created by Luca on 9/9/2025. +// + +#ifndef SHMINGO_HAL_SHAL_I2C_REG_F072XB_H +#define SHMINGO_HAL_SHAL_I2C_REG_F072XB_H + +#include "SHAL_CORE.h" + +enum class I2C_Pair : uint8_t{ + //I2C_1 + SCL1B6_SDA1B7, //AF1 + SCL1B8_SDA1B9, //AF1 + + //I2C_2 + SCL2B10_SDA2B11, //AF1 + SCL2B13_SDA2B14, //AF5 +}; + +#endif //SHMINGO_HAL_SHAL_I2C_REG_F072XB_H diff --git a/SHAL/Include/Peripheral/I2C/Reg/SHAL_I2C_TYPES.h b/SHAL/Include/Peripheral/I2C/Reg/SHAL_I2C_TYPES.h new file mode 100644 index 0000000..c88a007 --- /dev/null +++ b/SHAL/Include/Peripheral/I2C/Reg/SHAL_I2C_TYPES.h @@ -0,0 +1,25 @@ +// +// Created by Luca on 9/9/2025. +// + +#ifndef SHMINGO_HAL_SHAL_I2C_TYPES_H +#define SHMINGO_HAL_SHAL_I2C_TYPES_H + +#include "SHAL_CORE.h" +#include "SHAL_GPIO_REG.h" + +//Information necessary for I2C +struct SHAL_I2C_Pair { + I2C_TypeDef* I2CReg; + GPIO_Key SCL_Key; + GPIO_Key SDA_Key; + AF_Mask SCL_Mask; + AF_Mask SDA_Mask; +}; + +struct SHAL_I2C_Enable_REG{ + volatile uint32_t* reg; + uint32_t mask; +}; + +#endif //SHMINGO_HAL_SHAL_I2C_TYPES_H diff --git a/SHAL/Include/Peripheral/I2C/SHAL_I2C.h b/SHAL/Include/Peripheral/I2C/SHAL_I2C.h new file mode 100644 index 0000000..80476e9 --- /dev/null +++ b/SHAL/Include/Peripheral/I2C/SHAL_I2C.h @@ -0,0 +1,8 @@ +// +// Created by Luca on 9/9/2025. +// + +#ifndef SHMINGO_HAL_SHAL_I2C_H +#define SHMINGO_HAL_SHAL_I2C_H + +#endif //SHMINGO_HAL_SHAL_I2C_H diff --git a/SHAL/Include/Peripheral/UART/Reg/SHAL_UART_TYPES.h b/SHAL/Include/Peripheral/UART/Reg/SHAL_UART_TYPES.h index 1220373..a1d0a1f 100644 --- a/SHAL/Include/Peripheral/UART/Reg/SHAL_UART_TYPES.h +++ b/SHAL/Include/Peripheral/UART/Reg/SHAL_UART_TYPES.h @@ -8,20 +8,10 @@ #include "SHAL_CORE.h" #include "SHAL_GPIO_REG.h" -enum class AF_Mask : uint8_t{ - AF0, - AF1, - AF2, - AF3, - AF4, - AF5, - AF6, - AF7 -}; + //Represents a pair of pins usable for USART Tx + Rx in combination, and their alternate function mapping struct SHAL_UART_Pair{ - USART_TypeDef* USARTReg; GPIO_Key TxKey; GPIO_Key RxKey; From 316edd32d88948c186a71043c53a83058a001dfb Mon Sep 17 00:00:00 2001 From: Ea-r-th <39779954+Ea-r-th@users.noreply.github.com> Date: Wed, 10 Sep 2025 00:41:08 -0700 Subject: [PATCH 02/13] Before switch to GPIO functions over raw register manipulation for USART --- SHAL/Include/Core/SHAL_CORE.h | 11 +--- SHAL/Include/Peripheral/GPIO/SHAL_GPIO.h | 52 ++++++++++++++++--- .../Peripheral/I2C/Reg/SHAL_I2C_REG_F072xB.h | 42 +++++++++++++-- .../UART/Reg/SHAL_UART_REG_F072xB.h | 38 +++++++------- .../Peripheral/UART/Reg/SHAL_UART_TYPES.h | 4 +- SHAL/Src/Peripheral/GPIO/SHAL_GPIO.cpp | 47 ++++++++++------- SHAL/Src/Peripheral/I2C/SHAL_I2C.cpp | 4 ++ SHAL/Src/main.cpp | 2 +- 8 files changed, 137 insertions(+), 63 deletions(-) create mode 100644 SHAL/Src/Peripheral/I2C/SHAL_I2C.cpp diff --git a/SHAL/Include/Core/SHAL_CORE.h b/SHAL/Include/Core/SHAL_CORE.h index 3c4ef85..f668139 100644 --- a/SHAL/Include/Core/SHAL_CORE.h +++ b/SHAL/Include/Core/SHAL_CORE.h @@ -13,16 +13,7 @@ //Universal structs and defines --------------------------- -enum class AF_Mask : uint8_t{ - AF0, - AF1, - AF2, - AF3, - AF4, - AF5, - AF6, - AF7 -}; + //--------------------------------------------------------- diff --git a/SHAL/Include/Peripheral/GPIO/SHAL_GPIO.h b/SHAL/Include/Peripheral/GPIO/SHAL_GPIO.h index 01cbb93..597c3f6 100644 --- a/SHAL/Include/Peripheral/GPIO/SHAL_GPIO.h +++ b/SHAL/Include/Peripheral/GPIO/SHAL_GPIO.h @@ -11,16 +11,42 @@ #include "SHAL_EXTI_CALLBACK.h" - - enum class PinMode : uint8_t{ - INPUT_MODE, - OUTPUT_MODE, - ALTERNATE_FUNCTION_MODE, - ANALOG_MODE, - INVALID + INPUT_MODE = 0x00, + OUTPUT_MODE = 0x01, + ALTERNATE_FUNCTION_MODE = 0x02, + ANALOG_MODE = 0x03, + INVALID = 0x00, +}; + +enum class GPIO_Alternate_Function : uint8_t{ + AF0 = 0x00, + AF1 = 0x01, + AF2 = 0x02, + AF3 = 0x03, + AF4 = 0x04, + AF5 = 0x05, + AF6 = 0x06, + AF7 = 0x07, +}; + +enum class PinType : uint8_t{ + PUSH_PULL = 0x00, + OPEN_DRAIN = 0x01, +}; + +enum class InternalResistorType : uint8_t{ + NO_PULL = 0x00, + PULLUP = 0x01, + PULLDOWN = 0x02, +}; + +enum class OutputSpeed : uint8_t{ + LOW_SPEED = 0x00, + MEDIUM_SPEED = 0x01, + HIGH_SPEED = 0x02, + VERY_HIGH_SPEED = 0x03, }; -unsigned long getPinMode(PinMode mode); enum class TriggerMode : uint8_t{ RISING_EDGE, @@ -28,6 +54,8 @@ enum class TriggerMode : uint8_t{ RISING_FALLING_EDGE }; + + //Abstraction of GPIO registers class GPIO{ @@ -39,6 +67,14 @@ public: void setHigh(); void setLow(); + void setAlternateFunction(GPIO_Alternate_Function AF) volatile; + + void setPinType(PinType type) volatile; + + void setOutputSpeed(OutputSpeed speed) volatile; + + void setInternalResistor(InternalResistorType type) volatile; + private: friend class GPIOManager; diff --git a/SHAL/Include/Peripheral/I2C/Reg/SHAL_I2C_REG_F072xB.h b/SHAL/Include/Peripheral/I2C/Reg/SHAL_I2C_REG_F072xB.h index ecee868..7e458e8 100644 --- a/SHAL/Include/Peripheral/I2C/Reg/SHAL_I2C_REG_F072xB.h +++ b/SHAL/Include/Peripheral/I2C/Reg/SHAL_I2C_REG_F072xB.h @@ -2,10 +2,13 @@ // Created by Luca on 9/9/2025. // -#ifndef SHMINGO_HAL_SHAL_I2C_REG_F072XB_H -#define SHMINGO_HAL_SHAL_I2C_REG_F072XB_H +#ifndef SHAL_I2C_REG_F072XB_H +#define SHAL_I2C_REG_F072XB_H #include "SHAL_CORE.h" +#include + +#include "SHAL_I2C_TYPES.h" enum class I2C_Pair : uint8_t{ //I2C_1 @@ -15,6 +18,39 @@ enum class I2C_Pair : uint8_t{ //I2C_2 SCL2B10_SDA2B11, //AF1 SCL2B13_SDA2B14, //AF5 + + NUM_PAIRS, + INVALID }; -#endif //SHMINGO_HAL_SHAL_I2C_REG_F072XB_H +constexpr SHAL_I2C_Pair getI2CPair(const I2C_Pair pair){ + switch(pair){ + case I2C_Pair::SCL1B6_SDA1B7: return {I2C1,GPIO_Key::B6,GPIO_Key::B7,AF_Mask::AF1,AF_Mask::AF1}; + case I2C_Pair::SCL1B8_SDA1B9: return {I2C1,GPIO_Key::B8,GPIO_Key::B9,AF_Mask::AF1,AF_Mask::AF1}; + case I2C_Pair::SCL2B10_SDA2B11: return {I2C2,GPIO_Key::B10,GPIO_Key::B11,AF_Mask::AF1,AF_Mask::AF1}; + case I2C_Pair::SCL2B13_SDA2B14: return {I2C2,GPIO_Key::B13,GPIO_Key::B14,AF_Mask::AF5,AF_Mask::AF5}; + case I2C_Pair::NUM_PAIRS: + case I2C_Pair::INVALID: + assert(false); + return {nullptr,GPIO_Key::INVALID,GPIO_Key::INVALID,AF_Mask::AF0,AF_Mask::AF0}; + } + __builtin_unreachable(); +} + +constexpr SHAL_I2C_Enable_REG getI2CEnableReg(const I2C_Pair pair){ + switch(pair){ + case I2C_Pair::SCL1B6_SDA1B7: + case I2C_Pair::SCL1B8_SDA1B9: + return {&RCC->APB1ENR,RCC_APB1ENR_I2C1EN}; + case I2C_Pair::SCL2B10_SDA2B11: + case I2C_Pair::SCL2B13_SDA2B14: + return {&RCC->APB1ENR,RCC_APB1ENR_I2C2EN}; + case I2C_Pair::NUM_PAIRS: + case I2C_Pair::INVALID: + assert(false); + return {nullptr, 0}; + } + __builtin_unreachable(); +} + +#endif //SHAL_I2C_REG_F072XB_H diff --git a/SHAL/Include/Peripheral/UART/Reg/SHAL_UART_REG_F072xB.h b/SHAL/Include/Peripheral/UART/Reg/SHAL_UART_REG_F072xB.h index ff67299..63dd06e 100644 --- a/SHAL/Include/Peripheral/UART/Reg/SHAL_UART_REG_F072xB.h +++ b/SHAL/Include/Peripheral/UART/Reg/SHAL_UART_REG_F072xB.h @@ -38,19 +38,19 @@ enum class UART_Pair : uint8_t{ constexpr SHAL_UART_Pair getUARTPair(const UART_Pair pair){ switch(pair){ - case UART_Pair::Tx1A9_Rx1A10: return {USART1,GPIO_Key::A9,GPIO_Key::A10,AF_Mask::AF1,AF_Mask::AF1}; - case UART_Pair::Tx1B6_Rx1B7: return {USART1,GPIO_Key::B6,GPIO_Key::B7,AF_Mask::AF0,AF_Mask::AF0}; - case UART_Pair::Tx2A2_Rx2A3: return {USART2,GPIO_Key::A2,GPIO_Key::A3,AF_Mask::AF1,AF_Mask::AF1}; - case UART_Pair::Tx2A14_Rx2A15: return {USART2,GPIO_Key::A14,GPIO_Key::A15,AF_Mask::AF1,AF_Mask::AF1}; - case UART_Pair::Tx3B10_Rx3B11: return {USART3,GPIO_Key::B10,GPIO_Key::B11,AF_Mask::AF4,AF_Mask::AF4}; - case UART_Pair::Tx3C4_Rx3C5: return {USART3,GPIO_Key::C4,GPIO_Key::C5,AF_Mask::AF1,AF_Mask::AF1}; - case UART_Pair::Tx3C10_Rx3C11: return {USART3,GPIO_Key::C10,GPIO_Key::C11,AF_Mask::AF1,AF_Mask::AF1}; - case UART_Pair::Tx4A0_Rx4A1: return {USART4,GPIO_Key::A0,GPIO_Key::A1,AF_Mask::AF4,AF_Mask::AF4}; - case UART_Pair::Tx4C10_Rx4C11: return {USART4,GPIO_Key::C10,GPIO_Key::C11,AF_Mask::AF0,AF_Mask::AF0}; + case UART_Pair::Tx1A9_Rx1A10: return {USART1, GPIO_Key::A9, GPIO_Key::A10, GPIO_Alternate_Function::AF1, GPIO_Alternate_Function::AF1}; + case UART_Pair::Tx1B6_Rx1B7: return {USART1, GPIO_Key::B6, GPIO_Key::B7, GPIO_Alternate_Function::AF0, GPIO_Alternate_Function::AF0}; + case UART_Pair::Tx2A2_Rx2A3: return {USART2, GPIO_Key::A2, GPIO_Key::A3, GPIO_Alternate_Function::AF1, GPIO_Alternate_Function::AF1}; + case UART_Pair::Tx2A14_Rx2A15: return {USART2, GPIO_Key::A14, GPIO_Key::A15, GPIO_Alternate_Function::AF1, GPIO_Alternate_Function::AF1}; + case UART_Pair::Tx3B10_Rx3B11: return {USART3, GPIO_Key::B10, GPIO_Key::B11, GPIO_Alternate_Function::AF4, GPIO_Alternate_Function::AF4}; + case UART_Pair::Tx3C4_Rx3C5: return {USART3, GPIO_Key::C4, GPIO_Key::C5, GPIO_Alternate_Function::AF1, GPIO_Alternate_Function::AF1}; + case UART_Pair::Tx3C10_Rx3C11: return {USART3, GPIO_Key::C10, GPIO_Key::C11, GPIO_Alternate_Function::AF1, GPIO_Alternate_Function::AF1}; + case UART_Pair::Tx4A0_Rx4A1: return {USART4, GPIO_Key::A0, GPIO_Key::A1, GPIO_Alternate_Function::AF4, GPIO_Alternate_Function::AF4}; + case UART_Pair::Tx4C10_Rx4C11: return {USART4, GPIO_Key::C10, GPIO_Key::C11, GPIO_Alternate_Function::AF0, GPIO_Alternate_Function::AF0}; case UART_Pair::NUM_PAIRS: case UART_Pair::INVALID: assert(false); - return {nullptr,GPIO_Key::INVALID,GPIO_Key::INVALID,AF_Mask::AF0,AF_Mask::AF0}; + return {nullptr, GPIO_Key::INVALID, GPIO_Key::INVALID, GPIO_Alternate_Function::AF0, GPIO_Alternate_Function::AF0}; } __builtin_unreachable(); } @@ -101,16 +101,16 @@ constexpr SHAL_UART_ENABLE_REG getUARTEnableReg(const UART_Pair pair){ __builtin_unreachable(); } -constexpr uint32_t getAFMask(const AF_Mask mask){ +constexpr uint32_t getAFMask(const GPIO_Alternate_Function mask){ switch(mask){ - case AF_Mask::AF0: return 0x00; - case AF_Mask::AF1: return 0x01; - case AF_Mask::AF2: return 0x02; - case AF_Mask::AF3: return 0x03; - case AF_Mask::AF4: return 0x04; - case AF_Mask::AF5: return 0x05; - case AF_Mask::AF6: return 0x06; - case AF_Mask::AF7: return 0x07; + case GPIO_Alternate_Function::AF0: return 0x00; + case GPIO_Alternate_Function::AF1: return 0x01; + case GPIO_Alternate_Function::AF2: return 0x02; + case GPIO_Alternate_Function::AF3: return 0x03; + case GPIO_Alternate_Function::AF4: return 0x04; + case GPIO_Alternate_Function::AF5: return 0x05; + case GPIO_Alternate_Function::AF6: return 0x06; + case GPIO_Alternate_Function::AF7: return 0x07; } __builtin_unreachable(); } diff --git a/SHAL/Include/Peripheral/UART/Reg/SHAL_UART_TYPES.h b/SHAL/Include/Peripheral/UART/Reg/SHAL_UART_TYPES.h index a1d0a1f..8441948 100644 --- a/SHAL/Include/Peripheral/UART/Reg/SHAL_UART_TYPES.h +++ b/SHAL/Include/Peripheral/UART/Reg/SHAL_UART_TYPES.h @@ -15,8 +15,8 @@ struct SHAL_UART_Pair{ USART_TypeDef* USARTReg; GPIO_Key TxKey; GPIO_Key RxKey; - AF_Mask TxMask; - AF_Mask RxMask; + GPIO_Alternate_Function TxMask; + GPIO_Alternate_Function RxMask; }; struct SHAL_UART_ENABLE_REG{ diff --git a/SHAL/Src/Peripheral/GPIO/SHAL_GPIO.cpp b/SHAL/Src/Peripheral/GPIO/SHAL_GPIO.cpp index 2c6a2b8..82739d6 100644 --- a/SHAL/Src/Peripheral/GPIO/SHAL_GPIO.cpp +++ b/SHAL/Src/Peripheral/GPIO/SHAL_GPIO.cpp @@ -5,24 +5,6 @@ #include "SHAL_GPIO.h" #include "SHAL_EXTI_CALLBACK.h" -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; - case PinMode::INVALID: - assert(false); - return 0; - } - __builtin_unreachable(); -} - - GPIO::GPIO() : m_GPIO_KEY(GPIO_Key::INVALID){ @@ -41,8 +23,8 @@ GPIO::GPIO(GPIO_Key key, PinMode pinMode) : m_GPIO_KEY(key) { *gpioEnable |= (1 << gpioOffset); //Set enable flag - gpioRegister->MODER &= ~(0b11 << (2 * registerOffset)); //Clear any previous mode - gpioRegister->MODER |= (getPinMode(pinMode) << (2 * registerOffset)); //Set mode based on pinmode bit structure + gpioRegister->MODER &= ~(0x03 << (2 * registerOffset)); //Clear any previous mode + gpioRegister->MODER |= (static_cast(pinMode) << (2 * registerOffset)); //Set mode based on pinmode bit structure } void GPIO::setLow() { @@ -60,6 +42,31 @@ void GPIO::toggle() volatile { gpioPeripheral.reg->ODR ^= (1 << gpioPeripheral.global_offset); } +void GPIO::setPinType(PinType type) volatile { + SHAL_GPIO_Peripheral gpioPeripheral = getGPIORegister(m_GPIO_KEY); + gpioPeripheral.reg->OTYPER &= ~(1 << gpioPeripheral.global_offset); + gpioPeripheral.reg->OTYPER |= (static_cast(type) << gpioPeripheral.global_offset); +} + +void GPIO::setOutputSpeed(OutputSpeed speed) volatile { + SHAL_GPIO_Peripheral gpioPeripheral = getGPIORegister(m_GPIO_KEY); + gpioPeripheral.reg->OSPEEDR |= (static_cast(speed) << (2 * gpioPeripheral.global_offset)); +} + +void GPIO::setInternalResistor(InternalResistorType type) volatile { + SHAL_GPIO_Peripheral gpioPeripheral = getGPIORegister(m_GPIO_KEY); + gpioPeripheral.reg->PUPDR &= ~(0x03 << (2 * gpioPeripheral.global_offset)); + gpioPeripheral.reg->PUPDR |= (static_cast(type) << (2 * gpioPeripheral.global_offset)); +} + +void GPIO::setAlternateFunction(GPIO_Alternate_Function AF) volatile { + SHAL_GPIO_Peripheral gpioPeripheral = getGPIORegister(m_GPIO_KEY); + + int afrIndex = gpioPeripheral.global_offset < 8 ? 0 : 1; //Get index of AFR + + gpioPeripheral.reg->AFR[afrIndex] &= ~(0xF << (gpioPeripheral.global_offset * 4)); + gpioPeripheral.reg->AFR[afrIndex] |= (static_cast(AF) << (gpioPeripheral.global_offset * 4)); +} GPIO& GPIOManager::get(GPIO_Key key, PinMode pinMode) { diff --git a/SHAL/Src/Peripheral/I2C/SHAL_I2C.cpp b/SHAL/Src/Peripheral/I2C/SHAL_I2C.cpp new file mode 100644 index 0000000..65df69c --- /dev/null +++ b/SHAL/Src/Peripheral/I2C/SHAL_I2C.cpp @@ -0,0 +1,4 @@ +// +// Created by Luca on 9/9/2025. +// + diff --git a/SHAL/Src/main.cpp b/SHAL/Src/main.cpp index 9069cdd..3cb0c19 100644 --- a/SHAL/Src/main.cpp +++ b/SHAL/Src/main.cpp @@ -20,7 +20,7 @@ int main() { uart2->begin(115200); - useGPIOAsInterrupt(GPIO_Key::C3,TriggerMode::RISING_EDGE,c3Interrupt); + useGPIOAsInterrupt(GPIO_Key::C3,TriggerMode::RISING_EDGE, c3Interrupt); Timer timer2 = getTimer(Timer_Key::S_TIM2); From 2f8ba8d9ee3fe58a8cd63c040dcd19a03db663af Mon Sep 17 00:00:00 2001 From: Ea-r-th <39779954+Ea-r-th@users.noreply.github.com> Date: Wed, 10 Sep 2025 01:20:50 -0700 Subject: [PATCH 03/13] Major refactor for entire system - wrong branch but get over it --- .../Peripheral/GPIO/Reg/SHAL_GPIO_TYPES.h | 44 ++++++++++++- SHAL/Include/Peripheral/GPIO/SHAL_GPIO.h | 65 +++++-------------- .../Peripheral/I2C/Reg/SHAL_I2C_REG_F072xB.h | 10 +-- .../Peripheral/I2C/Reg/SHAL_I2C_TYPES.h | 4 +- .../Peripheral/UART/Reg/SHAL_UART_TYPES.h | 4 +- SHAL/Src/Peripheral/GPIO/SHAL_GPIO.cpp | 58 ++++++++--------- SHAL/Src/Peripheral/UART/SHAL_UART.cpp | 21 ++---- SHAL/Src/main.cpp | 11 ++-- 8 files changed, 106 insertions(+), 111 deletions(-) diff --git a/SHAL/Include/Peripheral/GPIO/Reg/SHAL_GPIO_TYPES.h b/SHAL/Include/Peripheral/GPIO/Reg/SHAL_GPIO_TYPES.h index a4fa55f..0dcbeb1 100644 --- a/SHAL/Include/Peripheral/GPIO/Reg/SHAL_GPIO_TYPES.h +++ b/SHAL/Include/Peripheral/GPIO/Reg/SHAL_GPIO_TYPES.h @@ -7,7 +7,6 @@ #include "SHAL_CORE.h" - struct SHAL_EXTIO_Register{ volatile uint32_t* EXT_ICR; uint32_t mask; @@ -24,6 +23,49 @@ struct SHAL_Peripheral_Register { unsigned long offset; }; +enum class PinMode : uint8_t{ + INPUT_MODE = 0x00, + OUTPUT_MODE = 0x01, + ALTERNATE_FUNCTION_MODE = 0x02, + ANALOG_MODE = 0x03, + INVALID = 0x00, +}; + +enum class GPIO_Alternate_Function : uint8_t{ + AF0 = 0x00, + AF1 = 0x01, + AF2 = 0x02, + AF3 = 0x03, + AF4 = 0x04, + AF5 = 0x05, + AF6 = 0x06, + AF7 = 0x07, +}; + +enum class PinType : uint8_t{ + PUSH_PULL = 0x00, + OPEN_DRAIN = 0x01, +}; + +enum class InternalResistorType : uint8_t{ + NO_PULL = 0x00, + PULLUP = 0x01, + PULLDOWN = 0x02, +}; + +enum class OutputSpeed : uint8_t{ + LOW_SPEED = 0x00, + MEDIUM_SPEED = 0x01, + HIGH_SPEED = 0x02, + VERY_HIGH_SPEED = 0x03, +}; + +enum class TriggerMode : uint8_t{ + RISING_EDGE, + FALLING_EDGE, + RISING_FALLING_EDGE +}; + #endif //SHMINGO_HAL_SHAL_GPIO_TYPES_H diff --git a/SHAL/Include/Peripheral/GPIO/SHAL_GPIO.h b/SHAL/Include/Peripheral/GPIO/SHAL_GPIO.h index 597c3f6..b8fdccf 100644 --- a/SHAL/Include/Peripheral/GPIO/SHAL_GPIO.h +++ b/SHAL/Include/Peripheral/GPIO/SHAL_GPIO.h @@ -11,48 +11,7 @@ #include "SHAL_EXTI_CALLBACK.h" -enum class PinMode : uint8_t{ - INPUT_MODE = 0x00, - OUTPUT_MODE = 0x01, - ALTERNATE_FUNCTION_MODE = 0x02, - ANALOG_MODE = 0x03, - INVALID = 0x00, -}; -enum class GPIO_Alternate_Function : uint8_t{ - AF0 = 0x00, - AF1 = 0x01, - AF2 = 0x02, - AF3 = 0x03, - AF4 = 0x04, - AF5 = 0x05, - AF6 = 0x06, - AF7 = 0x07, -}; - -enum class PinType : uint8_t{ - PUSH_PULL = 0x00, - OPEN_DRAIN = 0x01, -}; - -enum class InternalResistorType : uint8_t{ - NO_PULL = 0x00, - PULLUP = 0x01, - PULLDOWN = 0x02, -}; - -enum class OutputSpeed : uint8_t{ - LOW_SPEED = 0x00, - MEDIUM_SPEED = 0x01, - HIGH_SPEED = 0x02, - VERY_HIGH_SPEED = 0x03, -}; - -enum class TriggerMode : uint8_t{ - RISING_EDGE, - FALLING_EDGE, - RISING_FALLING_EDGE -}; @@ -67,6 +26,8 @@ public: void setHigh(); void setLow(); + void setPinMode(PinMode mode) volatile; + void setAlternateFunction(GPIO_Alternate_Function AF) volatile; void setPinType(PinType type) volatile; @@ -75,31 +36,39 @@ public: void setInternalResistor(InternalResistorType type) volatile; + + void useAsExternalInterrupt(TriggerMode mode, EXTICallback callback); + private: friend class GPIOManager; - explicit GPIO(GPIO_Key key, PinMode pinMode); + explicit GPIO(GPIO_Key key); GPIO(); GPIO_Key m_GPIO_KEY = GPIO_Key::INVALID; }; -//Init GPIO for normal use -#define initGPIO(GPIO_KEY, PIN_MODE) GPIOManager::get(GPIO_KEY, PIN_MODE) -//Init GPIO for use as an external interrupt -#define useGPIOAsInterrupt(GPIO_KEY, Trigger_Mode, Callback) GPIOManager::getInterruptGPIO(GPIO_KEY, Trigger_Mode, Callback) + + + +//Init GPIO for normal use +#define PIN_TO_KEY(name) GPIO_Key::name +#define PIN(name) GPIOManager::get(PIN_TO_KEY(name)) + +#define GET_GPIO(key) GPIOManager::get(key) + +#define GPIO_A //Manages instances of GPIO objects class GPIOManager{ public: - static GPIO& get(GPIO_Key, PinMode pinMode); + static GPIO& get(GPIO_Key); - static void getInterruptGPIO(GPIO_Key key, TriggerMode mode, EXTICallback callback); GPIOManager() = delete; diff --git a/SHAL/Include/Peripheral/I2C/Reg/SHAL_I2C_REG_F072xB.h b/SHAL/Include/Peripheral/I2C/Reg/SHAL_I2C_REG_F072xB.h index 7e458e8..53ed576 100644 --- a/SHAL/Include/Peripheral/I2C/Reg/SHAL_I2C_REG_F072xB.h +++ b/SHAL/Include/Peripheral/I2C/Reg/SHAL_I2C_REG_F072xB.h @@ -25,14 +25,14 @@ enum class I2C_Pair : uint8_t{ constexpr SHAL_I2C_Pair getI2CPair(const I2C_Pair pair){ switch(pair){ - case I2C_Pair::SCL1B6_SDA1B7: return {I2C1,GPIO_Key::B6,GPIO_Key::B7,AF_Mask::AF1,AF_Mask::AF1}; - case I2C_Pair::SCL1B8_SDA1B9: return {I2C1,GPIO_Key::B8,GPIO_Key::B9,AF_Mask::AF1,AF_Mask::AF1}; - case I2C_Pair::SCL2B10_SDA2B11: return {I2C2,GPIO_Key::B10,GPIO_Key::B11,AF_Mask::AF1,AF_Mask::AF1}; - case I2C_Pair::SCL2B13_SDA2B14: return {I2C2,GPIO_Key::B13,GPIO_Key::B14,AF_Mask::AF5,AF_Mask::AF5}; + case I2C_Pair::SCL1B6_SDA1B7: return {I2C1,GPIO_Key::B6,GPIO_Key::B7,GPIO_Alternate_Function::AF1,GPIO_Alternate_Function::AF1}; + case I2C_Pair::SCL1B8_SDA1B9: return {I2C1,GPIO_Key::B8,GPIO_Key::B9,GPIO_Alternate_Function::AF1,GPIO_Alternate_Function::AF1}; + case I2C_Pair::SCL2B10_SDA2B11: return {I2C2,GPIO_Key::B10,GPIO_Key::B11,GPIO_Alternate_Function::AF1,GPIO_Alternate_Function::AF1}; + case I2C_Pair::SCL2B13_SDA2B14: return {I2C2,GPIO_Key::B13,GPIO_Key::B14,GPIO_Alternate_Function::AF5,GPIO_Alternate_Function::AF5}; case I2C_Pair::NUM_PAIRS: case I2C_Pair::INVALID: assert(false); - return {nullptr,GPIO_Key::INVALID,GPIO_Key::INVALID,AF_Mask::AF0,AF_Mask::AF0}; + return {nullptr,GPIO_Key::INVALID,GPIO_Key::INVALID,GPIO_Alternate_Function::AF0,GPIO_Alternate_Function::AF0}; } __builtin_unreachable(); } diff --git a/SHAL/Include/Peripheral/I2C/Reg/SHAL_I2C_TYPES.h b/SHAL/Include/Peripheral/I2C/Reg/SHAL_I2C_TYPES.h index c88a007..3b93c27 100644 --- a/SHAL/Include/Peripheral/I2C/Reg/SHAL_I2C_TYPES.h +++ b/SHAL/Include/Peripheral/I2C/Reg/SHAL_I2C_TYPES.h @@ -13,8 +13,8 @@ struct SHAL_I2C_Pair { I2C_TypeDef* I2CReg; GPIO_Key SCL_Key; GPIO_Key SDA_Key; - AF_Mask SCL_Mask; - AF_Mask SDA_Mask; + GPIO_Alternate_Function SCL_Mask; + GPIO_Alternate_Function SDA_Mask; }; struct SHAL_I2C_Enable_REG{ diff --git a/SHAL/Include/Peripheral/UART/Reg/SHAL_UART_TYPES.h b/SHAL/Include/Peripheral/UART/Reg/SHAL_UART_TYPES.h index 8441948..b6a658d 100644 --- a/SHAL/Include/Peripheral/UART/Reg/SHAL_UART_TYPES.h +++ b/SHAL/Include/Peripheral/UART/Reg/SHAL_UART_TYPES.h @@ -15,8 +15,8 @@ struct SHAL_UART_Pair{ USART_TypeDef* USARTReg; GPIO_Key TxKey; GPIO_Key RxKey; - GPIO_Alternate_Function TxMask; - GPIO_Alternate_Function RxMask; + GPIO_Alternate_Function TxAlternateFunctionMask; + GPIO_Alternate_Function RxAlternateFunctionMask; }; struct SHAL_UART_ENABLE_REG{ diff --git a/SHAL/Src/Peripheral/GPIO/SHAL_GPIO.cpp b/SHAL/Src/Peripheral/GPIO/SHAL_GPIO.cpp index 82739d6..326a2ec 100644 --- a/SHAL/Src/Peripheral/GPIO/SHAL_GPIO.cpp +++ b/SHAL/Src/Peripheral/GPIO/SHAL_GPIO.cpp @@ -11,20 +11,12 @@ GPIO::GPIO() : m_GPIO_KEY(GPIO_Key::INVALID){ //Do not initialize anything } -GPIO::GPIO(GPIO_Key key, PinMode pinMode) : m_GPIO_KEY(key) { - - SHAL_GPIO_Peripheral gpioPeripheral = getGPIORegister(key); - - auto gpioRegister = gpioPeripheral.reg; - unsigned long registerOffset = gpioPeripheral.global_offset; +GPIO::GPIO(GPIO_Key key) : m_GPIO_KEY(key) { volatile unsigned long* gpioEnable = getGPIORCCEnable(key).reg; unsigned long gpioOffset = getGPIORCCEnable(key).offset; *gpioEnable |= (1 << gpioOffset); //Set enable flag - - gpioRegister->MODER &= ~(0x03 << (2 * registerOffset)); //Clear any previous mode - gpioRegister->MODER |= (static_cast(pinMode) << (2 * registerOffset)); //Set mode based on pinmode bit structure } void GPIO::setLow() { @@ -42,6 +34,8 @@ void GPIO::toggle() volatile { gpioPeripheral.reg->ODR ^= (1 << gpioPeripheral.global_offset); } + + void GPIO::setPinType(PinType type) volatile { SHAL_GPIO_Peripheral gpioPeripheral = getGPIORegister(m_GPIO_KEY); gpioPeripheral.reg->OTYPER &= ~(1 << gpioPeripheral.global_offset); @@ -68,41 +62,30 @@ void GPIO::setAlternateFunction(GPIO_Alternate_Function AF) volatile { gpioPeripheral.reg->AFR[afrIndex] |= (static_cast(AF) << (gpioPeripheral.global_offset * 4)); } - -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 - - if (m_gpios[gpioPort][gpioPin].m_GPIO_KEY == GPIO_Key::INVALID){ - m_gpios[gpioPort][gpioPin] = GPIO(key,pinMode); - } - - return m_gpios[gpioPort][gpioPin]; +void GPIO::setPinMode(PinMode mode) volatile { + SHAL_GPIO_Peripheral gpioPeripheral = getGPIORegister(m_GPIO_KEY); + gpioPeripheral.reg->MODER &= ~(0x03 << (2 * gpioPeripheral.global_offset)); //Clear any previous mode + gpioPeripheral.reg->MODER |= (static_cast(mode) << (2 * gpioPeripheral.global_offset)); //Set mode based on pinmode bit structure } -void GPIOManager::getInterruptGPIO(GPIO_Key key, TriggerMode triggerMode, EXTICallback callback) { +void GPIO::useAsExternalInterrupt(TriggerMode mode, EXTICallback callback) { - uint32_t gpioPort = getGPIOPortNumber(key); - uint32_t gpioPin = getGPIORegister(key).global_offset; //Use existing structs to get offset + uint32_t gpioPin = getGPIORegister(m_GPIO_KEY).global_offset; //Use existing structs to get offset - if (m_gpios[gpioPort][gpioPin].m_GPIO_KEY == GPIO_Key::INVALID){ - m_gpios[gpioPort][gpioPin] = GPIO(key,PinMode::INPUT_MODE); //Hardcode input mode for interrupt - } + setPinMode(PinMode::INPUT_MODE); //Explicitly set mode to input RCC->APB2ENR |= RCC_APB2ENR_SYSCFGCOMPEN; //Enable EXT, TODO check if this is different across STM32 models - NVIC_EnableIRQ(getGPIOEXTICR(key).IRQN); //Enable IRQN for pin + NVIC_EnableIRQ(getGPIOEXTICR(m_GPIO_KEY).IRQN); //Enable IRQN for pin EXTI->IMR |= (1 << gpioPin); //Enable correct EXTI line - SHAL_EXTIO_Register EXTILineEnable = getGPIOEXTICR(key); + SHAL_EXTIO_Register EXTILineEnable = getGPIOEXTICR(m_GPIO_KEY); *EXTILineEnable.EXT_ICR |= EXTILineEnable.mask; //Set bits to enable correct port on correct line TODO Find way to clear bits before - uint32_t rising_mask = 0x00; uint32_t falling_mask = 0x00; //Set rising and falling edge triggers based on pin offset (enabled EXTI line) - switch(triggerMode){ + switch(mode){ case TriggerMode::RISING_EDGE: rising_mask = 1 << gpioPin; break; @@ -119,7 +102,20 @@ void GPIOManager::getInterruptGPIO(GPIO_Key key, TriggerMode triggerMode, EXTICa EXTI->FTSR |= falling_mask; //Set callback - registerEXTICallback(key,callback); + registerEXTICallback(m_GPIO_KEY,callback); __enable_irq(); //Enable IRQ just in case +} + + +GPIO& GPIOManager::get(GPIO_Key key) { + + unsigned int gpioPort = getGPIOPortNumber(key); + unsigned long gpioPin = getGPIORegister(key).global_offset; //Use existing structs to get offset + + if (m_gpios[gpioPort][gpioPin].m_GPIO_KEY == GPIO_Key::INVALID){ + m_gpios[gpioPort][gpioPin] = GPIO(key); + } + + return m_gpios[gpioPort][gpioPin]; } \ No newline at end of file diff --git a/SHAL/Src/Peripheral/UART/SHAL_UART.cpp b/SHAL/Src/Peripheral/UART/SHAL_UART.cpp index 990ff41..093d471 100644 --- a/SHAL/Src/Peripheral/UART/SHAL_UART.cpp +++ b/SHAL/Src/Peripheral/UART/SHAL_UART.cpp @@ -17,24 +17,11 @@ UART::UART(const UART_Pair pair) : m_UARTPair(pair){ GPIO_Key Tx_Key = uart_pair.TxKey; //Tx pin GPIO_Key Rx_Key = uart_pair.RxKey; //Rx pin - uint8_t Tx_Pin = getGPIORegister(Tx_Key).global_offset; - uint8_t Rx_Pin = getGPIORegister(Rx_Key).global_offset; + GET_GPIO(Tx_Key).setPinMode(PinMode::ALTERNATE_FUNCTION_MODE); + GET_GPIO(Rx_Key).setPinMode(PinMode::ALTERNATE_FUNCTION_MODE); - initGPIO(Tx_Key,PinMode::ALTERNATE_FUNCTION_MODE); //Initialize Tx GPIO with alternate function (initializes GPIO port as well) - initGPIO(Rx_Key,PinMode::ALTERNATE_FUNCTION_MODE); //Initialize Rx GPIO with alternate function - - //Determine which AFR register (high or low) to write depending on pin - uint8_t TxAFR = Tx_Pin < 8 ? 0 : 1; //Use AFR[0] if pin < 8, AFR[1] if pin >= 8 - uint8_t RxAFR = Rx_Pin < 8 ? 0 : 1; - - /*Apply Alternate Function masks to the AFR registers for each GPIO to enable alternate functions - * The AFR register for GPIO_Typedef* is actually two registers - a low reg and high reg. - * The low reg handles pins 0-7, and the high reg handles 8-15. - * Each pin gets 4 bits in the register for AFR0 - AFR7. Hence 8 * 4 = 32 bits. - * Each AFR is a different function, look at the DATASHEET (not reference manual) to find these alternate function mappings - */ - getGPIORegister(Tx_Key).reg->AFR[TxAFR] |= getAFMask(uart_pair.TxMask) << (4 * (Tx_Pin % 8)); - getGPIORegister(Rx_Key).reg->AFR[RxAFR] |= getAFMask(uart_pair.RxMask) << (4 * (Rx_Pin % 8)); + GET_GPIO(Tx_Key).setAlternateFunction(uart_pair.TxAlternateFunctionMask); + GET_GPIO(Rx_Key).setAlternateFunction(uart_pair.RxAlternateFunctionMask); SHAL_UART_ENABLE_REG pairUARTEnable = getUARTEnableReg(pair); //Register and mask to enable the UART channel diff --git a/SHAL/Src/main.cpp b/SHAL/Src/main.cpp index 3cb0c19..2a19add 100644 --- a/SHAL/Src/main.cpp +++ b/SHAL/Src/main.cpp @@ -7,11 +7,12 @@ volatile GPIO* greenLED = nullptr; volatile UART* uart2; void c3Interrupt(){ - greenLED->toggle(); + PIN(A5).toggle(); + uart2->sendString("test"); } void tim2Handler(){ - blueLED->toggle(); + PIN(A4).toggle(); } int main() { @@ -20,12 +21,12 @@ int main() { uart2->begin(115200); - useGPIOAsInterrupt(GPIO_Key::C3,TriggerMode::RISING_EDGE, c3Interrupt); + PIN(C3).useAsExternalInterrupt(TriggerMode::RISING_EDGE,c3Interrupt); Timer timer2 = getTimer(Timer_Key::S_TIM2); - blueLED = &initGPIO(GPIO_Key::A4, PinMode::OUTPUT_MODE); - greenLED = &initGPIO(GPIO_Key::A5, PinMode::OUTPUT_MODE); + PIN(A4).setPinMode(PinMode::OUTPUT_MODE); + PIN(A5).setPinMode(PinMode::OUTPUT_MODE); timer2.setPrescaler(8000 - 1); timer2.setARR(1500 - 1); From 8f3bd7ebd8f4424d16adc0b258b8db89852511c4 Mon Sep 17 00:00:00 2001 From: Ea-r-th <39779954+Ea-r-th@users.noreply.github.com> Date: Wed, 10 Sep 2025 01:43:11 -0700 Subject: [PATCH 04/13] Refactored UART frontent retrieval system --- .../Device/ST/STM32F0xx/Include/stm32f072xb.h | 44 +++++++++---------- .../GPIO/Reg/SHAL_GPIO_REG_F072xB.h | 2 +- SHAL/Include/Peripheral/GPIO/SHAL_GPIO.h | 16 +++---- SHAL/Include/Peripheral/UART/SHAL_UART.h | 17 +++---- SHAL/Src/Peripheral/GPIO/SHAL_GPIO.cpp | 26 +++++------ SHAL/Src/Peripheral/UART/SHAL_UART.cpp | 28 ++++++------ SHAL/Src/main.cpp | 11 ++--- 7 files changed, 70 insertions(+), 74 deletions(-) diff --git a/Drivers/CMSIS/Device/ST/STM32F0xx/Include/stm32f072xb.h b/Drivers/CMSIS/Device/ST/STM32F0xx/Include/stm32f072xb.h index 849bade..cbcb0d8 100644 --- a/Drivers/CMSIS/Device/ST/STM32F0xx/Include/stm32f072xb.h +++ b/Drivers/CMSIS/Device/ST/STM32F0xx/Include/stm32f072xb.h @@ -369,16 +369,16 @@ typedef struct typedef struct { - __IO uint32_t MODER; /*!< GPIO port mode register, Address offset: 0x00 */ - __IO uint32_t OTYPER; /*!< GPIO port output type register, Address offset: 0x04 */ - __IO uint32_t OSPEEDR; /*!< GPIO port output speed register, Address offset: 0x08 */ - __IO uint32_t PUPDR; /*!< GPIO port pull-up/pull-down register, Address offset: 0x0C */ - __IO uint32_t IDR; /*!< GPIO port input data register, Address offset: 0x10 */ - __IO uint32_t ODR; /*!< GPIO port output data register, Address offset: 0x14 */ - __IO uint32_t BSRR; /*!< GPIO port bit set/reset register, Address offset: 0x1A */ - __IO uint32_t LCKR; /*!< GPIO port configuration lock register, Address offset: 0x1C */ - __IO uint32_t AFR[2]; /*!< GPIO alternate function low register, Address offset: 0x20-0x24 */ - __IO uint32_t BRR; /*!< GPIO bit reset register, Address offset: 0x28 */ + __IO uint32_t MODER; /*!< SHAL_GPIO port mode register, Address offset: 0x00 */ + __IO uint32_t OTYPER; /*!< SHAL_GPIO port output type register, Address offset: 0x04 */ + __IO uint32_t OSPEEDR; /*!< SHAL_GPIO port output speed register, Address offset: 0x08 */ + __IO uint32_t PUPDR; /*!< SHAL_GPIO port pull-up/pull-down register, Address offset: 0x0C */ + __IO uint32_t IDR; /*!< SHAL_GPIO port input data register, Address offset: 0x10 */ + __IO uint32_t ODR; /*!< SHAL_GPIO port output data register, Address offset: 0x14 */ + __IO uint32_t BSRR; /*!< SHAL_GPIO port bit set/reset register, Address offset: 0x1A */ + __IO uint32_t LCKR; /*!< SHAL_GPIO port configuration lock register, Address offset: 0x1C */ + __IO uint32_t AFR[2]; /*!< SHAL_GPIO alternate function low register, Address offset: 0x20-0x24 */ + __IO uint32_t BRR; /*!< SHAL_GPIO bit reset register, Address offset: 0x28 */ } GPIO_TypeDef; /** @@ -6490,7 +6490,7 @@ typedef struct /******************************************************************************/ /* */ -/* General Purpose IOs (GPIO) */ +/* General Purpose IOs (SHAL_GPIO) */ /* */ /******************************************************************************/ /******************* Bit definition for GPIO_MODER register *****************/ @@ -10933,7 +10933,7 @@ typedef struct ((INSTANCE) == DMA1_Channel6) || \ ((INSTANCE) == DMA1_Channel7)) -/****************************** GPIO Instances ********************************/ +/****************************** SHAL_GPIO Instances ********************************/ #define IS_GPIO_ALL_INSTANCE(INSTANCE) (((INSTANCE) == GPIOA) || \ ((INSTANCE) == GPIOB) || \ ((INSTANCE) == GPIOC) || \ @@ -10941,14 +10941,14 @@ typedef struct ((INSTANCE) == GPIOE) || \ ((INSTANCE) == GPIOF)) -/**************************** GPIO Alternate Function Instances ***************/ +/**************************** SHAL_GPIO Alternate Function Instances ***************/ #define IS_GPIO_AF_INSTANCE(INSTANCE) (((INSTANCE) == GPIOA) || \ ((INSTANCE) == GPIOB) || \ ((INSTANCE) == GPIOC) || \ ((INSTANCE) == GPIOD) || \ ((INSTANCE) == GPIOE)) -/****************************** GPIO Lock Instances ***************************/ +/****************************** SHAL_GPIO Lock Instances ***************************/ #define IS_GPIO_LOCK_INSTANCE(INSTANCE) (((INSTANCE) == GPIOA) || \ ((INSTANCE) == GPIOB)) @@ -11192,11 +11192,11 @@ typedef struct /****************************** TSC Instances *********************************/ #define IS_TSC_ALL_INSTANCE(INSTANCE) ((INSTANCE) == TSC) -/*********************** UART Instances : IRDA mode ***************************/ +/*********************** SHAL_UART Instances : IRDA mode ***************************/ #define IS_IRDA_INSTANCE(INSTANCE) (((INSTANCE) == USART1) || \ ((INSTANCE) == USART2)) -/********************* UART Instances : Smard card mode ***********************/ +/********************* SHAL_UART Instances : Smard card mode ***********************/ #define IS_SMARTCARD_INSTANCE(INSTANCE) (((INSTANCE) == USART1) || \ ((INSTANCE) == USART2)) @@ -11210,35 +11210,35 @@ typedef struct #define IS_USART_AUTOBAUDRATE_DETECTION_INSTANCE(INSTANCE) (((INSTANCE) == USART1) || \ ((INSTANCE) == USART2)) -/******************** UART Instances : Asynchronous mode **********************/ +/******************** SHAL_UART Instances : Asynchronous mode **********************/ #define IS_UART_INSTANCE(INSTANCE) (((INSTANCE) == USART1) || \ ((INSTANCE) == USART2) || \ ((INSTANCE) == USART3) || \ ((INSTANCE) == USART4)) -/******************** UART Instances : Half-Duplex mode **********************/ +/******************** SHAL_UART Instances : Half-Duplex mode **********************/ #define IS_UART_HALFDUPLEX_INSTANCE(INSTANCE) (((INSTANCE) == USART1) || \ ((INSTANCE) == USART2) || \ ((INSTANCE) == USART3) || \ ((INSTANCE) == USART4)) -/****************** UART Instances : Hardware Flow control ********************/ +/****************** SHAL_UART Instances : Hardware Flow control ********************/ #define IS_UART_HWFLOW_INSTANCE(INSTANCE) (((INSTANCE) == USART1) || \ ((INSTANCE) == USART2) || \ ((INSTANCE) == USART3) || \ ((INSTANCE) == USART4)) -/****************** UART Instances : LIN mode ********************/ +/****************** SHAL_UART Instances : LIN mode ********************/ #define IS_UART_LIN_INSTANCE(INSTANCE) (((INSTANCE) == USART1) || \ ((INSTANCE) == USART2)) -/****************** UART Instances : wakeup from stop mode ********************/ +/****************** SHAL_UART Instances : wakeup from stop mode ********************/ #define IS_UART_WAKEUP_FROMSTOP_INSTANCE(INSTANCE) (((INSTANCE) == USART1) || \ ((INSTANCE) == USART2)) /* Old macro definition maintained for legacy purpose */ #define IS_UART_WAKEUP_INSTANCE IS_UART_WAKEUP_FROMSTOP_INSTANCE -/****************** UART Instances : Driver enable detection ********************/ +/****************** SHAL_UART Instances : Driver enable detection ********************/ #define IS_UART_DRIVER_ENABLE_INSTANCE(INSTANCE) (((INSTANCE) == USART1) || \ ((INSTANCE) == USART2) || \ ((INSTANCE) == USART3) || \ 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 b05892f..c12c60a 100644 --- a/SHAL/Include/Peripheral/GPIO/Reg/SHAL_GPIO_REG_F072xB.h +++ b/SHAL/Include/Peripheral/GPIO/Reg/SHAL_GPIO_REG_F072xB.h @@ -20,7 +20,7 @@ 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 +//Build enum map of available SHAL_GPIO pins enum class GPIO_Key : uint8_t { #define X(key) key, AVAILABLE_GPIO diff --git a/SHAL/Include/Peripheral/GPIO/SHAL_GPIO.h b/SHAL/Include/Peripheral/GPIO/SHAL_GPIO.h index b8fdccf..793a597 100644 --- a/SHAL/Include/Peripheral/GPIO/SHAL_GPIO.h +++ b/SHAL/Include/Peripheral/GPIO/SHAL_GPIO.h @@ -15,8 +15,8 @@ -//Abstraction of GPIO registers -class GPIO{ +//Abstraction of SHAL_GPIO registers +class SHAL_GPIO{ public: @@ -43,8 +43,8 @@ private: friend class GPIOManager; - explicit GPIO(GPIO_Key key); - GPIO(); + explicit SHAL_GPIO(GPIO_Key key); + SHAL_GPIO(); GPIO_Key m_GPIO_KEY = GPIO_Key::INVALID; @@ -54,7 +54,7 @@ private: -//Init GPIO for normal use +//Init SHAL_GPIO for normal use #define PIN_TO_KEY(name) GPIO_Key::name #define PIN(name) GPIOManager::get(PIN_TO_KEY(name)) @@ -62,19 +62,19 @@ private: #define GPIO_A -//Manages instances of GPIO objects +//Manages instances of SHAL_GPIO objects class GPIOManager{ public: - static GPIO& get(GPIO_Key); + static SHAL_GPIO& get(GPIO_Key); GPIOManager() = delete; private: -inline static GPIO m_gpios[AVAILABLE_PORTS][PINS_PER_PORT] = {{}}; +inline static SHAL_GPIO m_gpios[AVAILABLE_PORTS][PINS_PER_PORT] = {{}}; }; diff --git a/SHAL/Include/Peripheral/UART/SHAL_UART.h b/SHAL/Include/Peripheral/UART/SHAL_UART.h index 2a6ebfc..6f35660 100644 --- a/SHAL/Include/Peripheral/UART/SHAL_UART.h +++ b/SHAL/Include/Peripheral/UART/SHAL_UART.h @@ -2,7 +2,7 @@ ****************************************************************************** * @file SHAL_TIM.h * @author Luca Lizaranzu - * @brief Relating to UART and USART object abstractions + * @brief Relating to SHAL_UART and USART object abstractions ****************************************************************************** */ @@ -11,11 +11,13 @@ #include "SHAL_UART_REG.h" -class UART{ +class SHAL_UART{ friend class UARTManager; public: + void init(UART_Pair pair); + //begins Tx and Usart TODO either modify this function or add a new one that supports Rx void begin(uint32_t baudRate) volatile; @@ -27,30 +29,29 @@ public: private: - UART() = default; //Initializer for array + SHAL_UART() = default; //Initializer for array - //Creates a UART based on a pair of two valid U(S)ART pins - explicit UART(UART_Pair pair); + //Creates a SHAL_UART based on a pair of two valid U(S)ART pins UART_Pair m_UARTPair = UART_Pair::INVALID; }; -#define getUART(uart_pair) UARTManager::get(uart_pair) +#define UART(num) UARTManager::get(num) class UARTManager{ public: - static UART& get(UART_Pair pair); + static SHAL_UART& get(uint8_t uart); UARTManager() = delete; private: - inline static UART m_UARTs[NUM_USART_LINES] = {}; + inline static SHAL_UART m_UARTs[NUM_USART_LINES] = {}; }; diff --git a/SHAL/Src/Peripheral/GPIO/SHAL_GPIO.cpp b/SHAL/Src/Peripheral/GPIO/SHAL_GPIO.cpp index 326a2ec..dea9db5 100644 --- a/SHAL/Src/Peripheral/GPIO/SHAL_GPIO.cpp +++ b/SHAL/Src/Peripheral/GPIO/SHAL_GPIO.cpp @@ -7,11 +7,11 @@ -GPIO::GPIO() : m_GPIO_KEY(GPIO_Key::INVALID){ +SHAL_GPIO::SHAL_GPIO() : m_GPIO_KEY(GPIO_Key::INVALID){ //Do not initialize anything } -GPIO::GPIO(GPIO_Key key) : m_GPIO_KEY(key) { +SHAL_GPIO::SHAL_GPIO(GPIO_Key key) : m_GPIO_KEY(key) { volatile unsigned long* gpioEnable = getGPIORCCEnable(key).reg; unsigned long gpioOffset = getGPIORCCEnable(key).offset; @@ -19,41 +19,41 @@ GPIO::GPIO(GPIO_Key key) : m_GPIO_KEY(key) { *gpioEnable |= (1 << gpioOffset); //Set enable flag } -void GPIO::setLow() { +void SHAL_GPIO::setLow() { auto gpioPeripheral = getGPIORegister(m_GPIO_KEY); gpioPeripheral.reg->ODR &= ~(1 << gpioPeripheral.global_offset); } -void GPIO::setHigh() { +void SHAL_GPIO::setHigh() { auto gpioPeripheral = getGPIORegister(m_GPIO_KEY); gpioPeripheral.reg->ODR |= (1 << gpioPeripheral.global_offset); } -void GPIO::toggle() volatile { +void SHAL_GPIO::toggle() volatile { SHAL_GPIO_Peripheral gpioPeripheral = getGPIORegister(m_GPIO_KEY); gpioPeripheral.reg->ODR ^= (1 << gpioPeripheral.global_offset); } -void GPIO::setPinType(PinType type) volatile { +void SHAL_GPIO::setPinType(PinType type) volatile { SHAL_GPIO_Peripheral gpioPeripheral = getGPIORegister(m_GPIO_KEY); gpioPeripheral.reg->OTYPER &= ~(1 << gpioPeripheral.global_offset); gpioPeripheral.reg->OTYPER |= (static_cast(type) << gpioPeripheral.global_offset); } -void GPIO::setOutputSpeed(OutputSpeed speed) volatile { +void SHAL_GPIO::setOutputSpeed(OutputSpeed speed) volatile { SHAL_GPIO_Peripheral gpioPeripheral = getGPIORegister(m_GPIO_KEY); gpioPeripheral.reg->OSPEEDR |= (static_cast(speed) << (2 * gpioPeripheral.global_offset)); } -void GPIO::setInternalResistor(InternalResistorType type) volatile { +void SHAL_GPIO::setInternalResistor(InternalResistorType type) volatile { SHAL_GPIO_Peripheral gpioPeripheral = getGPIORegister(m_GPIO_KEY); gpioPeripheral.reg->PUPDR &= ~(0x03 << (2 * gpioPeripheral.global_offset)); gpioPeripheral.reg->PUPDR |= (static_cast(type) << (2 * gpioPeripheral.global_offset)); } -void GPIO::setAlternateFunction(GPIO_Alternate_Function AF) volatile { +void SHAL_GPIO::setAlternateFunction(GPIO_Alternate_Function AF) volatile { SHAL_GPIO_Peripheral gpioPeripheral = getGPIORegister(m_GPIO_KEY); int afrIndex = gpioPeripheral.global_offset < 8 ? 0 : 1; //Get index of AFR @@ -62,13 +62,13 @@ void GPIO::setAlternateFunction(GPIO_Alternate_Function AF) volatile { gpioPeripheral.reg->AFR[afrIndex] |= (static_cast(AF) << (gpioPeripheral.global_offset * 4)); } -void GPIO::setPinMode(PinMode mode) volatile { +void SHAL_GPIO::setPinMode(PinMode mode) volatile { SHAL_GPIO_Peripheral gpioPeripheral = getGPIORegister(m_GPIO_KEY); gpioPeripheral.reg->MODER &= ~(0x03 << (2 * gpioPeripheral.global_offset)); //Clear any previous mode gpioPeripheral.reg->MODER |= (static_cast(mode) << (2 * gpioPeripheral.global_offset)); //Set mode based on pinmode bit structure } -void GPIO::useAsExternalInterrupt(TriggerMode mode, EXTICallback callback) { +void SHAL_GPIO::useAsExternalInterrupt(TriggerMode mode, EXTICallback callback) { uint32_t gpioPin = getGPIORegister(m_GPIO_KEY).global_offset; //Use existing structs to get offset @@ -108,13 +108,13 @@ void GPIO::useAsExternalInterrupt(TriggerMode mode, EXTICallback callback) { } -GPIO& GPIOManager::get(GPIO_Key key) { +SHAL_GPIO& GPIOManager::get(GPIO_Key key) { unsigned int gpioPort = getGPIOPortNumber(key); unsigned long gpioPin = getGPIORegister(key).global_offset; //Use existing structs to get offset if (m_gpios[gpioPort][gpioPin].m_GPIO_KEY == GPIO_Key::INVALID){ - m_gpios[gpioPort][gpioPin] = GPIO(key); + m_gpios[gpioPort][gpioPin] = SHAL_GPIO(key); } return m_gpios[gpioPort][gpioPin]; diff --git a/SHAL/Src/Peripheral/UART/SHAL_UART.cpp b/SHAL/Src/Peripheral/UART/SHAL_UART.cpp index 093d471..c8d1a52 100644 --- a/SHAL/Src/Peripheral/UART/SHAL_UART.cpp +++ b/SHAL/Src/Peripheral/UART/SHAL_UART.cpp @@ -2,7 +2,7 @@ ****************************************************************************** * @file SHAL_TIM.h * @author Luca Lizaranzu - * @brief Related to USART and UART abstractions + * @brief Related to USART and SHAL_UART abstractions ****************************************************************************** */ @@ -10,10 +10,13 @@ #include "SHAL_UART.h" #include "SHAL_GPIO.h" -UART::UART(const UART_Pair pair) : m_UARTPair(pair){ +void SHAL_UART::init(const UART_Pair pair){ + + m_UARTPair = pair; + SHAL_UART_Pair uart_pair = getUARTPair(pair); //Get the UART_PAIR information to be initialized - //Get the GPIO pins for this UART setup + //Get the SHAL_GPIO pins for this SHAL_UART setup GPIO_Key Tx_Key = uart_pair.TxKey; //Tx pin GPIO_Key Rx_Key = uart_pair.RxKey; //Rx pin @@ -23,12 +26,12 @@ UART::UART(const UART_Pair pair) : m_UARTPair(pair){ GET_GPIO(Tx_Key).setAlternateFunction(uart_pair.TxAlternateFunctionMask); GET_GPIO(Rx_Key).setAlternateFunction(uart_pair.RxAlternateFunctionMask); - SHAL_UART_ENABLE_REG pairUARTEnable = getUARTEnableReg(pair); //Register and mask to enable the UART channel + SHAL_UART_ENABLE_REG pairUARTEnable = getUARTEnableReg(pair); //Register and mask to enable the SHAL_UART channel - *pairUARTEnable.reg |= pairUARTEnable.mask; //Enable UART line + *pairUARTEnable.reg |= pairUARTEnable.mask; //Enable SHAL_UART line } -void UART::begin(uint32_t baudRate) volatile { +void SHAL_UART::begin(uint32_t baudRate) volatile { USART_TypeDef* usart = getUARTPair(m_UARTPair).USARTReg; @@ -44,11 +47,11 @@ void UART::begin(uint32_t baudRate) volatile { } -void UART::sendString(const char *s) volatile { +void SHAL_UART::sendString(const char *s) volatile { while (*s) sendChar(*s++); //Send chars while we haven't reached end of s } -void UART::sendChar(char c) volatile { +void SHAL_UART::sendChar(char c) volatile { USART_TypeDef* usart = getUARTPair(m_UARTPair).USARTReg; @@ -59,11 +62,6 @@ void UART::sendChar(char c) volatile { -UART& UARTManager::get(UART_Pair pair) { - - //Reassign if pair doesn't match - if(m_UARTs[getUARTChannel(pair)].m_UARTPair != pair) { - m_UARTs[getUARTChannel(pair)] = UART(pair); - } - return m_UARTs[getUARTChannel(pair)]; +SHAL_UART& UARTManager::get(uint8_t uart) { + return m_UARTs[uart]; } diff --git a/SHAL/Src/main.cpp b/SHAL/Src/main.cpp index 2a19add..898161a 100644 --- a/SHAL/Src/main.cpp +++ b/SHAL/Src/main.cpp @@ -2,13 +2,9 @@ #include "stm32f0xx.h" -volatile GPIO* blueLED = nullptr; -volatile GPIO* greenLED = nullptr; -volatile UART* uart2; - void c3Interrupt(){ PIN(A5).toggle(); - uart2->sendString("test"); + UART(2).sendString("New test"); } void tim2Handler(){ @@ -17,9 +13,10 @@ void tim2Handler(){ int main() { - uart2 = &getUART(UART_Pair::Tx2A2_Rx2A3); - uart2->begin(115200); + UART(2).init(UART_Pair::Tx2A2_Rx2A3); + + UART(2).begin(115200); PIN(C3).useAsExternalInterrupt(TriggerMode::RISING_EDGE,c3Interrupt); From 914fbf5a170e5e244df5e5530b804bd2c10a927f Mon Sep 17 00:00:00 2001 From: Ea-r-th <39779954+Ea-r-th@users.noreply.github.com> Date: Wed, 10 Sep 2025 01:53:16 -0700 Subject: [PATCH 05/13] Begin I2C implementation and finalize other changes --- .../Include/Peripheral/I2C/Reg/SHAL_I2C_REG.h | 42 +++++++++++++++++-- .../Peripheral/I2C/Reg/SHAL_I2C_REG_F072xB.h | 3 ++ SHAL/Include/Peripheral/I2C/SHAL_I2C.h | 36 ++++++++++++++++ .../Peripheral/UART/Reg/SHAL_UART_REG.h | 4 -- SHAL/Include/Peripheral/UART/SHAL_UART.h | 1 - 5 files changed, 78 insertions(+), 8 deletions(-) diff --git a/SHAL/Include/Peripheral/I2C/Reg/SHAL_I2C_REG.h b/SHAL/Include/Peripheral/I2C/Reg/SHAL_I2C_REG.h index 291321a..6ebdccb 100644 --- a/SHAL/Include/Peripheral/I2C/Reg/SHAL_I2C_REG.h +++ b/SHAL/Include/Peripheral/I2C/Reg/SHAL_I2C_REG.h @@ -2,7 +2,43 @@ // Created by Luca on 9/9/2025. // -#ifndef SHMINGO_HAL_SHAL_I2C_REG_H -#define SHMINGO_HAL_SHAL_I2C_REG_H +#ifndef SHAL_I2C_REG_H +#define SHAL_I2C_REG_H -#endif //SHMINGO_HAL_SHAL_I2C_REG_H +#if defined(STM32F030x6) +#include "stm32f030x6.h" +#elif defined(STM32F030x8) +#include "stm32f030x8.h" +#elif defined(STM32F031x6) +#include "stm32f031x6.h" +#elif defined(STM32F038xx) +#include "stm32f038xx.h" +#elif defined(STM32F042x6) +#include "stm32f042x6.h" +#elif defined(STM32F048xx) +#include "stm32f048xx.h" +#elif defined(STM32F051x8) +#include "stm32f051x8.h" +#elif defined(STM32F058xx) +#include "stm32f058xx.h" +#elif defined(STM32F070x6) +#include "stm32f070x6.h" +#elif defined(STM32F070xB) +#include "stm32f070xb.h" +#elif defined(STM32F071xB) +#include "stm32f071xb.h" +#elif defined(STM32F072xB) +#include "SHAL_I2C_REG_F072xB.h" +#elif defined(STM32F078xx) +#include "stm32f078xx.h" +#elif defined(STM32F091xC) + #include "stm32f091xc.h" +#elif defined(STM32F098xx) + #include "stm32f098xx.h" +#elif defined(STM32F030xC) + #include "stm32f030xc.h" +#else + #error "Please select first the target STM32F0xx device used in your application (in stm32f0xx.h file)" +#endif + +#endif //SHAL_I2C_REG_H diff --git a/SHAL/Include/Peripheral/I2C/Reg/SHAL_I2C_REG_F072xB.h b/SHAL/Include/Peripheral/I2C/Reg/SHAL_I2C_REG_F072xB.h index 53ed576..0e2d114 100644 --- a/SHAL/Include/Peripheral/I2C/Reg/SHAL_I2C_REG_F072xB.h +++ b/SHAL/Include/Peripheral/I2C/Reg/SHAL_I2C_REG_F072xB.h @@ -10,6 +10,9 @@ #include "SHAL_I2C_TYPES.h" +#define NUM_I2C_BUSES 2 + + enum class I2C_Pair : uint8_t{ //I2C_1 SCL1B6_SDA1B7, //AF1 diff --git a/SHAL/Include/Peripheral/I2C/SHAL_I2C.h b/SHAL/Include/Peripheral/I2C/SHAL_I2C.h index 80476e9..4a9768d 100644 --- a/SHAL/Include/Peripheral/I2C/SHAL_I2C.h +++ b/SHAL/Include/Peripheral/I2C/SHAL_I2C.h @@ -5,4 +5,40 @@ #ifndef SHMINGO_HAL_SHAL_I2C_H #define SHMINGO_HAL_SHAL_I2C_H +#include "SHAL_CORE.h" +#include "SHAL_I2C_REG.h" + + +class SHAL_I2C{ + + friend class I2CManager; + +public: + +private: + + SHAL_I2C() = default; + + I2C_Pair m_I2CPair = I2C_Pair::INVALID; //Initialize to invalid + +}; + + + + + +class I2CManager{ + +public: + + static SHAL_I2C& get(uint8_t i2c); + + I2CManager() = delete; + +private: + + inline static SHAL_I2C m_UARTs[NUM_I2C_BUSES] = {}; + +}; + #endif //SHMINGO_HAL_SHAL_I2C_H diff --git a/SHAL/Include/Peripheral/UART/Reg/SHAL_UART_REG.h b/SHAL/Include/Peripheral/UART/Reg/SHAL_UART_REG.h index ec6009c..a89c0da 100644 --- a/SHAL/Include/Peripheral/UART/Reg/SHAL_UART_REG.h +++ b/SHAL/Include/Peripheral/UART/Reg/SHAL_UART_REG.h @@ -5,10 +5,6 @@ #ifndef SHAL_UART_REG_H #define SHAL_UART_REG_H -// -// Created by Luca on 9/6/2025. -// - #if defined(STM32F030x6) #include "stm32f030x6.h" diff --git a/SHAL/Include/Peripheral/UART/SHAL_UART.h b/SHAL/Include/Peripheral/UART/SHAL_UART.h index 6f35660..e1cbb45 100644 --- a/SHAL/Include/Peripheral/UART/SHAL_UART.h +++ b/SHAL/Include/Peripheral/UART/SHAL_UART.h @@ -46,7 +46,6 @@ public: static SHAL_UART& get(uint8_t uart); - UARTManager() = delete; private: From 183be36c649e02d332f84aabbcef6ebadf039e02 Mon Sep 17 00:00:00 2001 From: Ea-r-th <39779954+Ea-r-th@users.noreply.github.com> Date: Sun, 14 Sep 2025 17:27:59 -0700 Subject: [PATCH 06/13] Beginnings of I2C object functions --- .../Peripheral/I2C/Reg/SHAL_I2C_REG_F072xB.h | 35 ++++++++++++++++++- .../Peripheral/I2C/Reg/SHAL_I2C_TYPES.h | 22 +++++++++++- SHAL/Include/Peripheral/I2C/SHAL_I2C.h | 10 ++++++ SHAL/Src/Peripheral/I2C/SHAL_I2C.cpp | 6 ++++ 4 files changed, 71 insertions(+), 2 deletions(-) diff --git a/SHAL/Include/Peripheral/I2C/Reg/SHAL_I2C_REG_F072xB.h b/SHAL/Include/Peripheral/I2C/Reg/SHAL_I2C_REG_F072xB.h index 0e2d114..4a9812c 100644 --- a/SHAL/Include/Peripheral/I2C/Reg/SHAL_I2C_REG_F072xB.h +++ b/SHAL/Include/Peripheral/I2C/Reg/SHAL_I2C_REG_F072xB.h @@ -40,7 +40,7 @@ constexpr SHAL_I2C_Pair getI2CPair(const I2C_Pair pair){ __builtin_unreachable(); } -constexpr SHAL_I2C_Enable_REG getI2CEnableReg(const I2C_Pair pair){ +constexpr SHAL_I2C_Enable_Reg getI2CEnableReg(const I2C_Pair pair){ switch(pair){ case I2C_Pair::SCL1B6_SDA1B7: case I2C_Pair::SCL1B8_SDA1B9: @@ -56,4 +56,37 @@ constexpr SHAL_I2C_Enable_REG getI2CEnableReg(const I2C_Pair pair){ __builtin_unreachable(); } +constexpr SHAL_I2C_Reset_Reg getI2CResetReg(const I2C_Pair pair){ + switch(pair){ + case I2C_Pair::SCL1B6_SDA1B7: + case I2C_Pair::SCL1B8_SDA1B9: + return {&RCC->APB1RSTR,RCC_APB1RSTR_I2C1RST}; + case I2C_Pair::SCL2B10_SDA2B11: + case I2C_Pair::SCL2B13_SDA2B14: + return {&RCC->APB1RSTR,RCC_APB1RSTR_I2C2RST}; + case I2C_Pair::NUM_PAIRS: + case I2C_Pair::INVALID: + assert(false); + return {nullptr, 0}; + } + __builtin_unreachable(); +} + +//Gets all the bits in the I2C timer register, these values should rarely be manually set, but I wanted to support it anyway +constexpr SHAL_I2C_Timing_Reg getI2CTimerReg(const I2C_Pair pair){ + switch(pair){ + case I2C_Pair::SCL1B6_SDA1B7: + case I2C_Pair::SCL1B8_SDA1B9: + return {&I2C1->TIMINGR,31,4,23,4,19,4,15,8,7,0}; + case I2C_Pair::SCL2B10_SDA2B11: + case I2C_Pair::SCL2B13_SDA2B14: + return {&I2C2->TIMINGR,31,4,23,4,19,4,15,8,7,0}; + case I2C_Pair::NUM_PAIRS: + case I2C_Pair::INVALID: + assert(false); + __builtin_unreachable(); + } + __builtin_unreachable(); +} + #endif //SHAL_I2C_REG_F072XB_H diff --git a/SHAL/Include/Peripheral/I2C/Reg/SHAL_I2C_TYPES.h b/SHAL/Include/Peripheral/I2C/Reg/SHAL_I2C_TYPES.h index 3b93c27..d0f0146 100644 --- a/SHAL/Include/Peripheral/I2C/Reg/SHAL_I2C_TYPES.h +++ b/SHAL/Include/Peripheral/I2C/Reg/SHAL_I2C_TYPES.h @@ -17,9 +17,29 @@ struct SHAL_I2C_Pair { GPIO_Alternate_Function SDA_Mask; }; -struct SHAL_I2C_Enable_REG{ +struct SHAL_I2C_Enable_Reg{ volatile uint32_t* reg; uint32_t mask; }; +struct SHAL_I2C_Reset_Reg{ + volatile uint32_t* reg; + uint32_t mask; +}; + +//Manual values for I2C timer register +struct SHAL_I2C_Timing_Reg{ + volatile uint32_t* reg; + uint8_t prescaler_offset; + uint8_t prescaler_width; + uint8_t dataSetupTime_offset; + uint8_t dataSetupTime_width; + uint8_t dataHoldTime_offset; + uint8_t dataHoldTime_width; + uint8_t SCLHighPeriod_offset; + uint8_t SCLHighPeriod_width; + uint8_t SCLLowPeriod_offset; + uint8_t SCLLowPeriod_width; +}; + #endif //SHMINGO_HAL_SHAL_I2C_TYPES_H diff --git a/SHAL/Include/Peripheral/I2C/SHAL_I2C.h b/SHAL/Include/Peripheral/I2C/SHAL_I2C.h index 4a9768d..9a9470c 100644 --- a/SHAL/Include/Peripheral/I2C/SHAL_I2C.h +++ b/SHAL/Include/Peripheral/I2C/SHAL_I2C.h @@ -15,6 +15,16 @@ class SHAL_I2C{ public: + void init(I2C_Pair pair) volatile; + + void masterTransmit(); + + //Manually set the clock configuration. Refer to your MCU's reference manual for examples + void setClockConfig(uint8_t prescaler, uint8_t dataSetupTime, uint8_t dataHoldTime, uint8_t SCLHighPeriod, uint8_t SCLLowPeriod); + + //Set clock configuration based on a value calculated from STM32CubeMX, or other similar tools + void setClockConfig(uint32_t configuration); + private: SHAL_I2C() = default; diff --git a/SHAL/Src/Peripheral/I2C/SHAL_I2C.cpp b/SHAL/Src/Peripheral/I2C/SHAL_I2C.cpp index 65df69c..c7f749c 100644 --- a/SHAL/Src/Peripheral/I2C/SHAL_I2C.cpp +++ b/SHAL/Src/Peripheral/I2C/SHAL_I2C.cpp @@ -2,3 +2,9 @@ // Created by Luca on 9/9/2025. // +#include "SHAL_I2C.h" + +void SHAL_I2C::init() volatile { + +} + From 25b56f9fcdcc4e3ecb0668fc9faa7948b8dda4d6 Mon Sep 17 00:00:00 2001 From: Ea-r-th <39779954+Ea-r-th@users.noreply.github.com> Date: Sun, 14 Sep 2025 23:06:28 -0700 Subject: [PATCH 07/13] Finished I2C --- .../Peripheral/I2C/Reg/SHAL_I2C_REG_F072xB.h | 4 +- .../Peripheral/I2C/Reg/SHAL_I2C_TYPES.h | 5 - SHAL/Include/Peripheral/I2C/SHAL_I2C.h | 17 ++- SHAL/Src/Peripheral/I2C/SHAL_I2C.cpp | 112 +++++++++++++++++- SHAL/Src/Peripheral/UART/SHAL_UART.cpp | 8 ++ 5 files changed, 133 insertions(+), 13 deletions(-) diff --git a/SHAL/Include/Peripheral/I2C/Reg/SHAL_I2C_REG_F072xB.h b/SHAL/Include/Peripheral/I2C/Reg/SHAL_I2C_REG_F072xB.h index 4a9812c..3a70ed7 100644 --- a/SHAL/Include/Peripheral/I2C/Reg/SHAL_I2C_REG_F072xB.h +++ b/SHAL/Include/Peripheral/I2C/Reg/SHAL_I2C_REG_F072xB.h @@ -77,10 +77,10 @@ constexpr SHAL_I2C_Timing_Reg getI2CTimerReg(const I2C_Pair pair){ switch(pair){ case I2C_Pair::SCL1B6_SDA1B7: case I2C_Pair::SCL1B8_SDA1B9: - return {&I2C1->TIMINGR,31,4,23,4,19,4,15,8,7,0}; + return {&I2C1->TIMINGR,31,23,19,15,7}; case I2C_Pair::SCL2B10_SDA2B11: case I2C_Pair::SCL2B13_SDA2B14: - return {&I2C2->TIMINGR,31,4,23,4,19,4,15,8,7,0}; + return {&I2C2->TIMINGR,31,23,19,15,7}; case I2C_Pair::NUM_PAIRS: case I2C_Pair::INVALID: assert(false); diff --git a/SHAL/Include/Peripheral/I2C/Reg/SHAL_I2C_TYPES.h b/SHAL/Include/Peripheral/I2C/Reg/SHAL_I2C_TYPES.h index d0f0146..d83ff4d 100644 --- a/SHAL/Include/Peripheral/I2C/Reg/SHAL_I2C_TYPES.h +++ b/SHAL/Include/Peripheral/I2C/Reg/SHAL_I2C_TYPES.h @@ -31,15 +31,10 @@ struct SHAL_I2C_Reset_Reg{ struct SHAL_I2C_Timing_Reg{ volatile uint32_t* reg; uint8_t prescaler_offset; - uint8_t prescaler_width; uint8_t dataSetupTime_offset; - uint8_t dataSetupTime_width; uint8_t dataHoldTime_offset; - uint8_t dataHoldTime_width; uint8_t SCLHighPeriod_offset; - uint8_t SCLHighPeriod_width; uint8_t SCLLowPeriod_offset; - uint8_t SCLLowPeriod_width; }; #endif //SHMINGO_HAL_SHAL_I2C_TYPES_H diff --git a/SHAL/Include/Peripheral/I2C/SHAL_I2C.h b/SHAL/Include/Peripheral/I2C/SHAL_I2C.h index 9a9470c..eec5694 100644 --- a/SHAL/Include/Peripheral/I2C/SHAL_I2C.h +++ b/SHAL/Include/Peripheral/I2C/SHAL_I2C.h @@ -17,7 +17,16 @@ public: void init(I2C_Pair pair) volatile; - void masterTransmit(); + /// + /// \param addr I2C address of slave device + /// \param reg Address of register in slave device to write to + /// \param data Data to write to slave register + void masterTransmit(uint8_t addr, uint8_t reg, uint8_t data); + + /// + /// \param addr I2C address of slave device + /// \param reg Register to read data from + uint8_t masterReceive(uint8_t addr, uint8_t reg); //Manually set the clock configuration. Refer to your MCU's reference manual for examples void setClockConfig(uint8_t prescaler, uint8_t dataSetupTime, uint8_t dataHoldTime, uint8_t SCLHighPeriod, uint8_t SCLLowPeriod); @@ -33,9 +42,7 @@ private: }; - - - +#define I2C(num) I2CManager::get(num) class I2CManager{ @@ -47,7 +54,7 @@ public: private: - inline static SHAL_I2C m_UARTs[NUM_I2C_BUSES] = {}; + inline static SHAL_I2C m_I2CBuses[NUM_I2C_BUSES] = {}; }; diff --git a/SHAL/Src/Peripheral/I2C/SHAL_I2C.cpp b/SHAL/Src/Peripheral/I2C/SHAL_I2C.cpp index c7f749c..4ae2440 100644 --- a/SHAL/Src/Peripheral/I2C/SHAL_I2C.cpp +++ b/SHAL/Src/Peripheral/I2C/SHAL_I2C.cpp @@ -3,8 +3,118 @@ // #include "SHAL_I2C.h" +#include "SHAL_GPIO.h" -void SHAL_I2C::init() volatile { +void SHAL_I2C::init(I2C_Pair pair) volatile { + m_I2CPair = pair; + SHAL_I2C_Pair I2CPair = getI2CPair(pair); //Get the UART_PAIR information to be initialized + + //Get the SHAL_GPIO pins for this SHAL_I2C setup + GPIO_Key SCL_Key = I2CPair.SCL_Key; //SCL pin + GPIO_Key SDA_Key = I2CPair.SDA_Key; //SDA pin + + GET_GPIO(SCL_Key).setPinMode(PinMode::ALTERNATE_FUNCTION_MODE); //Implicitly initializes and enables GPIO bus + GET_GPIO(SDA_Key).setPinMode(PinMode::ALTERNATE_FUNCTION_MODE); + + GET_GPIO(SCL_Key).setAlternateFunction(I2CPair.SCL_Mask); + GET_GPIO(SDA_Key).setAlternateFunction(I2CPair.SDA_Mask); + + //These may be abstracted further to support multiple I2C configurations + GET_GPIO(SCL_Key).setPinType(PinType::OPEN_DRAIN); + GET_GPIO(SDA_Key).setPinType(PinType::OPEN_DRAIN); + + GET_GPIO(SCL_Key).setOutputSpeed(OutputSpeed::HIGH_SPEED); + GET_GPIO(SDA_Key).setOutputSpeed(OutputSpeed::HIGH_SPEED); + + GET_GPIO(SCL_Key).setInternalResistor(InternalResistorType::PULLUP); + GET_GPIO(SDA_Key).setInternalResistor(InternalResistorType::PULLUP); + + SHAL_I2C_Enable_Reg pairI2CEnable = getI2CEnableReg(pair); //Register and mask to enable the I2C peripheral + SHAL_I2C_Reset_Reg pairI2CReset = getI2CResetReg(pair); + + *pairI2CReset.reg |= pairI2CReset.mask; //Reset peripheral + *pairI2CEnable.reg |= pairI2CEnable.mask; //Enable I2C peripheral clock + + I2CPair.I2CReg->CR1 |= I2C_CR1_PE; //Enable I2C peripheral } +void SHAL_I2C::setClockConfig(uint8_t prescaler, uint8_t dataSetupTime, uint8_t dataHoldTime, uint8_t SCLHighPeriod, uint8_t SCLLowPeriod) { + + SHAL_I2C_Timing_Reg clockReg = getI2CTimerReg(m_I2CPair); + + *clockReg.reg |= (prescaler << clockReg.prescaler_offset); + *clockReg.reg |= (dataSetupTime << clockReg.dataSetupTime_offset); + *clockReg.reg |= (dataHoldTime << clockReg.dataHoldTime_offset); + *clockReg.reg |= (SCLHighPeriod << clockReg.SCLHighPeriod_offset); + *clockReg.reg |= (SCLLowPeriod << clockReg.SCLLowPeriod_offset); +} + +void SHAL_I2C::setClockConfig(uint32_t configuration) { + *getI2CTimerReg(m_I2CPair).reg = configuration; +} + +void SHAL_I2C::masterTransmit(uint8_t addr, uint8_t reg, uint8_t data) { + + volatile I2C_TypeDef* I2CPeripheral = getI2CPair(m_I2CPair).I2CReg; + + //Wait until not busy + while (I2CPeripheral->ISR & I2C_ISR_BUSY); + + //Send start + slave address + I2CPeripheral->CR2 = (addr << 1) | (2 << I2C_CR2_NBYTES_Pos) | I2C_CR2_START | I2C_CR2_AUTOEND; //Pack bits in compliance with I2C format + + //Wait until TX ready + while (!(I2CPeripheral->ISR & I2C_ISR_TXIS)); + + //Send register address + I2CPeripheral->TXDR = reg; + + //Wait until TX ready + while (!(I2CPeripheral->ISR & I2C_ISR_TXIS)); + + //Send data to write to register + I2CPeripheral->TXDR = data; +} + + +uint8_t SHAL_I2C::masterReceive(uint8_t addr, uint8_t reg) { + + volatile I2C_TypeDef* I2CPeripheral = getI2CPair(m_I2CPair).I2CReg; + + //Send register address with write + + //Wait for bus + while (I2CPeripheral->ISR & I2C_ISR_BUSY); + + //Send start with I2C config + I2CPeripheral->CR2 = (addr << 1) | (1 << I2C_CR2_NBYTES_Pos) | I2C_CR2_START; + + //Wait for transmit + while (!(I2CPeripheral->ISR & I2C_ISR_TXIS)); + + //Set address to read from + I2CPeripheral->TXDR = reg; + + //Wait for transfer to complete + while (!(I2CPeripheral->ISR & I2C_ISR_TC)); + + //Restart in read mode, auto end + I2CPeripheral->CR2 = (addr << 1) | I2C_CR2_RD_WRN | + (1 << I2C_CR2_NBYTES_Pos) | + I2C_CR2_START | I2C_CR2_AUTOEND; + + //Wait + while (!(I2C1->ISR & I2C_ISR_RXNE)); + return (uint8_t)I2C1->RXDR; +} + +SHAL_I2C& I2CManager::get(uint8_t I2CBus) { + + if(I2CBus > NUM_I2C_BUSES - 1){ + assert(false); + //Memory fault + } + + return m_I2CBuses[I2CBus]; +} diff --git a/SHAL/Src/Peripheral/UART/SHAL_UART.cpp b/SHAL/Src/Peripheral/UART/SHAL_UART.cpp index c8d1a52..237ea24 100644 --- a/SHAL/Src/Peripheral/UART/SHAL_UART.cpp +++ b/SHAL/Src/Peripheral/UART/SHAL_UART.cpp @@ -29,6 +29,8 @@ void SHAL_UART::init(const UART_Pair pair){ SHAL_UART_ENABLE_REG pairUARTEnable = getUARTEnableReg(pair); //Register and mask to enable the SHAL_UART channel *pairUARTEnable.reg |= pairUARTEnable.mask; //Enable SHAL_UART line + + } void SHAL_UART::begin(uint32_t baudRate) volatile { @@ -63,5 +65,11 @@ void SHAL_UART::sendChar(char c) volatile { SHAL_UART& UARTManager::get(uint8_t uart) { + + if(uart > NUM_USART_LINES - 1){ + assert(false); + //Memory fault + } + return m_UARTs[uart]; } From b2d10f5e5e8c3afa68b875d203095730edabae01 Mon Sep 17 00:00:00 2001 From: Ea-r-th <39779954+Ea-r-th@users.noreply.github.com> Date: Mon, 15 Sep 2025 01:20:33 -0700 Subject: [PATCH 08/13] Unified all current peripheral implementation syntax with macros --- .../Peripheral/I2C/Reg/SHAL_I2C_REG_F072xB.h | 2 ++ .../Peripheral/Timer/Reg/SHAL_TIM_REG_F072xB.h | 11 +++++++++++ SHAL/Include/Peripheral/Timer/SHAL_TIM.h | 9 +++++++++ .../Peripheral/UART/Reg/SHAL_UART_REG_F072xB.h | 5 +++++ SHAL/Src/Peripheral/Timer/SHAL_TIM.cpp | 13 +++++++++++-- SHAL/Src/main.cpp | 17 +++++++---------- 6 files changed, 45 insertions(+), 12 deletions(-) diff --git a/SHAL/Include/Peripheral/I2C/Reg/SHAL_I2C_REG_F072xB.h b/SHAL/Include/Peripheral/I2C/Reg/SHAL_I2C_REG_F072xB.h index 3a70ed7..c3431a2 100644 --- a/SHAL/Include/Peripheral/I2C/Reg/SHAL_I2C_REG_F072xB.h +++ b/SHAL/Include/Peripheral/I2C/Reg/SHAL_I2C_REG_F072xB.h @@ -12,6 +12,8 @@ #define NUM_I2C_BUSES 2 +#define SHAL_I2C1 I2C(1) +#define SHAL_I2C2 I2C(2) enum class I2C_Pair : uint8_t{ //I2C_1 diff --git a/SHAL/Include/Peripheral/Timer/Reg/SHAL_TIM_REG_F072xB.h b/SHAL/Include/Peripheral/Timer/Reg/SHAL_TIM_REG_F072xB.h index 8b373ca..f4bf7cd 100644 --- a/SHAL/Include/Peripheral/Timer/Reg/SHAL_TIM_REG_F072xB.h +++ b/SHAL/Include/Peripheral/Timer/Reg/SHAL_TIM_REG_F072xB.h @@ -29,6 +29,17 @@ enum class Timer_Key : uint8_t { //For STM32F072 S_TIM_INVALID }; +#define SHAL_TIM1 TimerManager::get(Timer_Key::S_TIM1) +#define SHAL_TIM2 TimerManager::get(Timer_Key::S_TIM2) +#define SHAL_TIM3 TimerManager::get(Timer_Key::S_TIM3) +#define SHAL_TIM6 TimerManager::get(Timer_Key::S_TIM6) +#define SHAL_TIM7 TimerManager::get(Timer_Key::S_TIM7) +#define SHAL_TIM14 TimerManager::get(Timer_Key::S_TIM14) +#define SHAL_TIM15 TimerManager::get(Timer_Key::S_TIM15) +#define SHAL_TIM16 TimerManager::get(Timer_Key::S_TIM16) +#define SHAL_TIM17 TimerManager::get(Timer_Key::S_TIM17) + + //Get TIMER_KEY peripheral struct including bus register, enable mask, TIMER_KEY mask constexpr TIM_RCC_Enable getTimerRCC(Timer_Key t) { diff --git a/SHAL/Include/Peripheral/Timer/SHAL_TIM.h b/SHAL/Include/Peripheral/Timer/SHAL_TIM.h index 484b75e..8c431d0 100644 --- a/SHAL/Include/Peripheral/Timer/SHAL_TIM.h +++ b/SHAL/Include/Peripheral/Timer/SHAL_TIM.h @@ -18,6 +18,11 @@ class Timer { friend class TimerManager; public: + /// + /// \param prescaler The amount of times the base clock has to cycle before the timer adds one to the count + /// \param autoReload The number of timer counts before the count is reset and IRQ is called + void init(uint32_t prescaler, uint32_t autoReload); + //Starts the counter void start(); @@ -49,12 +54,16 @@ private: #define getTimer(timer_key) TimerManager::get(timer_key) +#define TIM(num) TimerManager::getTimerFromIndex(num) //Manages all timers so user does not have to personally initialize class TimerManager{ public: static Timer& get(Timer_Key); + + static Timer& getTimerFromIndex(uint8_t index){return timers[index];} + TimerManager() = delete; private: diff --git a/SHAL/Include/Peripheral/UART/Reg/SHAL_UART_REG_F072xB.h b/SHAL/Include/Peripheral/UART/Reg/SHAL_UART_REG_F072xB.h index 63dd06e..975bff5 100644 --- a/SHAL/Include/Peripheral/UART/Reg/SHAL_UART_REG_F072xB.h +++ b/SHAL/Include/Peripheral/UART/Reg/SHAL_UART_REG_F072xB.h @@ -12,6 +12,11 @@ #define NUM_USART_LINES 4 +#define SHAL_UART1 UART(1) +#define SHAL_UART2 UART(2) +#define SHAL_UART3 UART(3) +#define SHAL_UART4 UART(4) + //Valid usart Tx and Rx pairings for STM32F072 enum class UART_Pair : uint8_t{ //UART1 diff --git a/SHAL/Src/Peripheral/Timer/SHAL_TIM.cpp b/SHAL/Src/Peripheral/Timer/SHAL_TIM.cpp index fa0601d..24b39b2 100644 --- a/SHAL/Src/Peripheral/Timer/SHAL_TIM.cpp +++ b/SHAL/Src/Peripheral/Timer/SHAL_TIM.cpp @@ -6,8 +6,7 @@ #include Timer::Timer(Timer_Key t) : TIMER_KEY(t){ - TIM_RCC_Enable rcc = getTimerRCC(TIMER_KEY); - *rcc.busEnableReg |= (1 << rcc.offset); + } Timer::Timer() : TIMER_KEY(Timer_Key::S_TIM_INVALID){ @@ -37,6 +36,14 @@ void Timer::enableInterrupt() { NVIC_EnableIRQ(getIRQn(TIMER_KEY)); } +void Timer::init(uint32_t prescaler, uint32_t autoReload) { + TIM_RCC_Enable rcc = getTimerRCC(TIMER_KEY); + *rcc.busEnableReg |= (1 << rcc.offset); + + setPrescaler(prescaler); + setARR(autoReload); +} + Timer &TimerManager::get(Timer_Key timer_key) { @@ -52,3 +59,5 @@ Timer &TimerManager::get(Timer_Key timer_key) { return timers[static_cast(timer_key)]; } + + diff --git a/SHAL/Src/main.cpp b/SHAL/Src/main.cpp index 898161a..0b50bcc 100644 --- a/SHAL/Src/main.cpp +++ b/SHAL/Src/main.cpp @@ -13,23 +13,20 @@ void tim2Handler(){ int main() { + //Setup UART2 (used by nucleo devices for USB comms) + SHAL_UART2.init(UART_Pair::Tx2A2_Rx2A3); + SHAL_UART2.begin(115200); - UART(2).init(UART_Pair::Tx2A2_Rx2A3); - - UART(2).begin(115200); - + //Use pin C3 to trigger a function on external interrupt PIN(C3).useAsExternalInterrupt(TriggerMode::RISING_EDGE,c3Interrupt); - Timer timer2 = getTimer(Timer_Key::S_TIM2); + SHAL_TIM2.init(8000-1,1500-1); + SHAL_TIM2.setCallbackFunc(tim2Handler); + SHAL_TIM2.start(); PIN(A4).setPinMode(PinMode::OUTPUT_MODE); PIN(A5).setPinMode(PinMode::OUTPUT_MODE); - timer2.setPrescaler(8000 - 1); - timer2.setARR(1500 - 1); - timer2.setCallbackFunc(tim2Handler); - timer2.start(); - while (true) { __WFI(); } From d4136f0761f03286ca49e6491ce656720e30567d Mon Sep 17 00:00:00 2001 From: Ea-r-th <39779954+Ea-r-th@users.noreply.github.com> Date: Mon, 15 Sep 2025 23:48:16 -0700 Subject: [PATCH 09/13] Added delay functions --- SHAL/Include/Core/SHAL_CORE.h | 15 ++++++ SHAL/Include/Peripheral/I2C/SHAL_I2C.h | 30 +++++++---- SHAL/Include/SHAL.h | 1 + SHAL/Src/Core/SHAL_CORE.cpp | 31 +++++++++++ SHAL/Src/Peripheral/I2C/SHAL_I2C.cpp | 73 +++++++++++--------------- SHAL/Src/main.cpp | 10 ++++ 6 files changed, 109 insertions(+), 51 deletions(-) create mode 100644 SHAL/Src/Core/SHAL_CORE.cpp diff --git a/SHAL/Include/Core/SHAL_CORE.h b/SHAL/Include/Core/SHAL_CORE.h index f668139..256d0cc 100644 --- a/SHAL/Include/Core/SHAL_CORE.h +++ b/SHAL/Include/Core/SHAL_CORE.h @@ -11,9 +11,24 @@ #include +//Overall init function for SHAL -------------------------- + +void SHAL_init(); + +//--------------------------------------------------------- + + + + //Universal structs and defines --------------------------- +//Currently configures systick to count down in microseconds +void systick_init(); +//Max of 16ms, use SHAL_delay_ms for longer delay +void SHAL_delay_us(uint32_t us); + +void SHAL_delay_ms(uint32_t ms); //--------------------------------------------------------- diff --git a/SHAL/Include/Peripheral/I2C/SHAL_I2C.h b/SHAL/Include/Peripheral/I2C/SHAL_I2C.h index eec5694..a37f656 100644 --- a/SHAL/Include/Peripheral/I2C/SHAL_I2C.h +++ b/SHAL/Include/Peripheral/I2C/SHAL_I2C.h @@ -5,6 +5,8 @@ #ifndef SHMINGO_HAL_SHAL_I2C_H #define SHMINGO_HAL_SHAL_I2C_H +#include + #include "SHAL_CORE.h" #include "SHAL_I2C_REG.h" @@ -17,16 +19,26 @@ public: void init(I2C_Pair pair) volatile; - /// - /// \param addr I2C address of slave device - /// \param reg Address of register in slave device to write to - /// \param data Data to write to slave register - void masterTransmit(uint8_t addr, uint8_t reg, uint8_t data); + /// General I2C function to send commands to a device, then read back any returned data if necessary + /// \param addr address of slave device + /// \param writeData pointer to array of write commands + /// \param writeLen number of write commands + /// \param readData pointer to buffer to write received data to + /// \param readLen number of bytes to be read + void masterWriteRead(uint8_t addr,const uint8_t* writeData, size_t writeLen, uint8_t* readData, size_t readLen); + + /// Function to write an array of commands to an I2C device + /// \param addr Address of slave device + /// \param writeData Pointer to array of commands + /// \param writeLen Number of commands + void masterWrite(uint8_t addr, const uint8_t* writeData, uint8_t writeLen); + + /// Function to read bytes from an I2C device + /// \param addr Address of slave device + /// \param readBuffer Pointer to buffer where data will be placed + /// \param bytesToRead Number of bytes to read + void masterRead(uint8_t addr, uint8_t* readBuffer, uint8_t bytesToRead); - /// - /// \param addr I2C address of slave device - /// \param reg Register to read data from - uint8_t masterReceive(uint8_t addr, uint8_t reg); //Manually set the clock configuration. Refer to your MCU's reference manual for examples void setClockConfig(uint8_t prescaler, uint8_t dataSetupTime, uint8_t dataHoldTime, uint8_t SCLHighPeriod, uint8_t SCLLowPeriod); diff --git a/SHAL/Include/SHAL.h b/SHAL/Include/SHAL.h index 9756334..2e6d6de 100644 --- a/SHAL/Include/SHAL.h +++ b/SHAL/Include/SHAL.h @@ -11,5 +11,6 @@ #include "SHAL_TIM.h" #include "SHAL_GPIO.h" #include "SHAL_UART.h" +#include "SHAL_I2C.h" #endif diff --git a/SHAL/Src/Core/SHAL_CORE.cpp b/SHAL/Src/Core/SHAL_CORE.cpp new file mode 100644 index 0000000..550c317 --- /dev/null +++ b/SHAL/Src/Core/SHAL_CORE.cpp @@ -0,0 +1,31 @@ +// +// Created by Luca on 9/15/2025. +// + +#include "SHAL_CORE.h" + +void SHAL_init(){ + systick_init(); //Just this for now +} + + +void systick_init(){ + SysTick->CTRL = 0; //disable first + SysTick->LOAD = 0xFFFFFF; //max 24-bit + SysTick->VAL = 0; //clear + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_ENABLE_Msk; +} + +void SHAL_delay_us(uint32_t us){ + uint32_t start = SysTick->VAL; + uint32_t ticks = us * (SystemCoreClock / 1000000U); + + //handle wraparound with 24-bit mask + while (((start - SysTick->VAL) & 0x00FFFFFF) < ticks) { } +} + +void SHAL_delay_ms(uint32_t ms){ + while(ms-- > 0){ + SHAL_delay_us(1000); + } +} \ No newline at end of file diff --git a/SHAL/Src/Peripheral/I2C/SHAL_I2C.cpp b/SHAL/Src/Peripheral/I2C/SHAL_I2C.cpp index 4ae2440..62ec75c 100644 --- a/SHAL/Src/Peripheral/I2C/SHAL_I2C.cpp +++ b/SHAL/Src/Peripheral/I2C/SHAL_I2C.cpp @@ -54,59 +54,48 @@ void SHAL_I2C::setClockConfig(uint32_t configuration) { *getI2CTimerReg(m_I2CPair).reg = configuration; } -void SHAL_I2C::masterTransmit(uint8_t addr, uint8_t reg, uint8_t data) { - +void SHAL_I2C::masterWriteRead(uint8_t addr,const uint8_t* writeData, size_t writeLen, uint8_t* readData, size_t readLen) { volatile I2C_TypeDef* I2CPeripheral = getI2CPair(m_I2CPair).I2CReg; - //Wait until not busy + //Wait for I2C bus while (I2CPeripheral->ISR & I2C_ISR_BUSY); - //Send start + slave address - I2CPeripheral->CR2 = (addr << 1) | (2 << I2C_CR2_NBYTES_Pos) | I2C_CR2_START | I2C_CR2_AUTOEND; //Pack bits in compliance with I2C format + //Write phase + if (writeLen > 0) { + //Configure: NBYTES = wlen, write mode, START + I2CPeripheral->CR2 = (addr << 1) | + (writeLen << I2C_CR2_NBYTES_Pos) | + I2C_CR2_START; - //Wait until TX ready - while (!(I2CPeripheral->ISR & I2C_ISR_TXIS)); + for (size_t i = 0; i < writeLen; i++) { + while (!(I2CPeripheral->ISR & I2C_ISR_TXIS)); // TX ready + I2CPeripheral->TXDR = writeData[i]; + } - //Send register address - I2CPeripheral->TXDR = reg; + //Wait until transfer complete + while (!(I2CPeripheral->ISR & I2C_ISR_TC)); + } - //Wait until TX ready - while (!(I2CPeripheral->ISR & I2C_ISR_TXIS)); + //Read phase + if (readLen > 0) { + I2CPeripheral->CR2 = (addr << 1) | + I2C_CR2_RD_WRN | + (readLen << I2C_CR2_NBYTES_Pos) | + I2C_CR2_START | I2C_CR2_AUTOEND; - //Send data to write to register - I2CPeripheral->TXDR = data; + for (size_t i = 0; i < readLen; i++) { + while (!(I2CPeripheral->ISR & I2C_ISR_RXNE)); //RX ready + readData[i] = static_cast(I2CPeripheral->RXDR); + } + } } +void SHAL_I2C::masterWrite(uint8_t addr, const uint8_t *writeData, uint8_t writeLen) { + masterWriteRead(addr,writeData,writeLen,nullptr,0); +} -uint8_t SHAL_I2C::masterReceive(uint8_t addr, uint8_t reg) { - - volatile I2C_TypeDef* I2CPeripheral = getI2CPair(m_I2CPair).I2CReg; - - //Send register address with write - - //Wait for bus - while (I2CPeripheral->ISR & I2C_ISR_BUSY); - - //Send start with I2C config - I2CPeripheral->CR2 = (addr << 1) | (1 << I2C_CR2_NBYTES_Pos) | I2C_CR2_START; - - //Wait for transmit - while (!(I2CPeripheral->ISR & I2C_ISR_TXIS)); - - //Set address to read from - I2CPeripheral->TXDR = reg; - - //Wait for transfer to complete - while (!(I2CPeripheral->ISR & I2C_ISR_TC)); - - //Restart in read mode, auto end - I2CPeripheral->CR2 = (addr << 1) | I2C_CR2_RD_WRN | - (1 << I2C_CR2_NBYTES_Pos) | - I2C_CR2_START | I2C_CR2_AUTOEND; - - //Wait - while (!(I2C1->ISR & I2C_ISR_RXNE)); - return (uint8_t)I2C1->RXDR; +void SHAL_I2C::masterRead(uint8_t addr, uint8_t *readBuffer, uint8_t bytesToRead) { + masterWriteRead(addr,nullptr,0,readBuffer,bytesToRead); } SHAL_I2C& I2CManager::get(uint8_t I2CBus) { diff --git a/SHAL/Src/main.cpp b/SHAL/Src/main.cpp index 0b50bcc..32c6754 100644 --- a/SHAL/Src/main.cpp +++ b/SHAL/Src/main.cpp @@ -13,10 +13,14 @@ void tim2Handler(){ int main() { + SHAL_init(); + //Setup UART2 (used by nucleo devices for USB comms) SHAL_UART2.init(UART_Pair::Tx2A2_Rx2A3); SHAL_UART2.begin(115200); + SHAL_I2C1.init(I2C_Pair::SCL1B6_SDA1B7); + //Use pin C3 to trigger a function on external interrupt PIN(C3).useAsExternalInterrupt(TriggerMode::RISING_EDGE,c3Interrupt); @@ -27,6 +31,12 @@ int main() { PIN(A4).setPinMode(PinMode::OUTPUT_MODE); PIN(A5).setPinMode(PinMode::OUTPUT_MODE); + c3Interrupt(); + + SHAL_delay_ms(3000); + + c3Interrupt(); //test + while (true) { __WFI(); } From 7b32859c88b732ae8382b6aabe5e3be4ee2818e3 Mon Sep 17 00:00:00 2001 From: Ea-r-th <39779954+Ea-r-th@users.noreply.github.com> Date: Tue, 16 Sep 2025 00:38:36 -0700 Subject: [PATCH 10/13] Added I2C clock config --- SHAL/Include/Peripheral/I2C/SHAL_I2C.h | 2 ++ SHAL/Src/Core/SHAL_CORE.cpp | 27 ++++++++++++++++++-------- SHAL/Src/Peripheral/I2C/SHAL_I2C.cpp | 6 ++++++ SHAL/Src/main.cpp | 25 ++++++++++++++++++++---- 4 files changed, 48 insertions(+), 12 deletions(-) diff --git a/SHAL/Include/Peripheral/I2C/SHAL_I2C.h b/SHAL/Include/Peripheral/I2C/SHAL_I2C.h index a37f656..a765d45 100644 --- a/SHAL/Include/Peripheral/I2C/SHAL_I2C.h +++ b/SHAL/Include/Peripheral/I2C/SHAL_I2C.h @@ -27,6 +27,8 @@ public: /// \param readLen number of bytes to be read void masterWriteRead(uint8_t addr,const uint8_t* writeData, size_t writeLen, uint8_t* readData, size_t readLen); + uint8_t masterWriteReadByte(uint8_t addr, const uint8_t* writeData, size_t writeLen); + /// Function to write an array of commands to an I2C device /// \param addr Address of slave device /// \param writeData Pointer to array of commands diff --git a/SHAL/Src/Core/SHAL_CORE.cpp b/SHAL/Src/Core/SHAL_CORE.cpp index 550c317..2f6f1b3 100644 --- a/SHAL/Src/Core/SHAL_CORE.cpp +++ b/SHAL/Src/Core/SHAL_CORE.cpp @@ -10,18 +10,29 @@ void SHAL_init(){ void systick_init(){ - SysTick->CTRL = 0; //disable first - SysTick->LOAD = 0xFFFFFF; //max 24-bit - SysTick->VAL = 0; //clear + SysTick->CTRL = 0; //Disable first + SysTick->LOAD = 0xFFFFFF; //Max 24-bit + SysTick->VAL = 0; //Clear SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_ENABLE_Msk; } -void SHAL_delay_us(uint32_t us){ - uint32_t start = SysTick->VAL; - uint32_t ticks = us * (SystemCoreClock / 1000000U); - //handle wraparound with 24-bit mask - while (((start - SysTick->VAL) & 0x00FFFFFF) < ticks) { } +void SHAL_delay_us(uint32_t us){ + uint32_t ticks = us * (SystemCoreClock / 1000000U); + uint32_t start = SysTick->VAL; + + //Calculate target value (may wrap around) + uint32_t target = (start >= ticks) ? (start - ticks) : (start + 0x01000000 - ticks); + target &= 0x00FFFFFF; + + //Wait until we reach the target + if (start >= ticks) { + //No wraparound case + while (SysTick->VAL > target) {} + } else { + while (SysTick->VAL <= start) {} //Wait for wraparound + while (SysTick->VAL > target) {} //Wait for target + } } void SHAL_delay_ms(uint32_t ms){ diff --git a/SHAL/Src/Peripheral/I2C/SHAL_I2C.cpp b/SHAL/Src/Peripheral/I2C/SHAL_I2C.cpp index 62ec75c..722870f 100644 --- a/SHAL/Src/Peripheral/I2C/SHAL_I2C.cpp +++ b/SHAL/Src/Peripheral/I2C/SHAL_I2C.cpp @@ -98,6 +98,12 @@ void SHAL_I2C::masterRead(uint8_t addr, uint8_t *readBuffer, uint8_t bytesToRead masterWriteRead(addr,nullptr,0,readBuffer,bytesToRead); } +uint8_t SHAL_I2C::masterWriteReadByte(uint8_t addr, const uint8_t *writeData, size_t writeLen) { + uint8_t val = 0; + masterWriteRead(addr, writeData, writeLen, &val, 1); + return val; +} + SHAL_I2C& I2CManager::get(uint8_t I2CBus) { if(I2CBus > NUM_I2C_BUSES - 1){ diff --git a/SHAL/Src/main.cpp b/SHAL/Src/main.cpp index 32c6754..eaa702e 100644 --- a/SHAL/Src/main.cpp +++ b/SHAL/Src/main.cpp @@ -4,7 +4,7 @@ void c3Interrupt(){ PIN(A5).toggle(); - UART(2).sendString("New test"); + SHAL_UART2.sendString("New test"); } void tim2Handler(){ @@ -20,6 +20,7 @@ int main() { SHAL_UART2.begin(115200); SHAL_I2C1.init(I2C_Pair::SCL1B6_SDA1B7); + SHAL_I2C1.setClockConfig(0x2000090E); //Use pin C3 to trigger a function on external interrupt PIN(C3).useAsExternalInterrupt(TriggerMode::RISING_EDGE,c3Interrupt); @@ -31,11 +32,27 @@ int main() { PIN(A4).setPinMode(PinMode::OUTPUT_MODE); PIN(A5).setPinMode(PinMode::OUTPUT_MODE); - c3Interrupt(); + //Temporary setup for DHT20 - SHAL_delay_ms(3000); + PIN(A5).setLow(); - c3Interrupt(); //test + SHAL_delay_ms(5000); //Wait 100 ms from datasheet + + PIN(A5).setHigh(); + + uint8_t initByte[1] = {0x71}; + + uint8_t status = SHAL_I2C1.masterWriteReadByte(0x38,initByte,1); + + if ((status & 0x18) != 0x18) { + SHAL_UART2.sendString("DHT ready"); + } else { + SHAL_UART2.sendString("DHT broke"); + } + + PIN(A5).setLow(); + + //End setup while (true) { __WFI(); From 75132eb0401cd17dfd231124f8aeab4bc3278a43 Mon Sep 17 00:00:00 2001 From: Ea-r-th <39779954+Ea-r-th@users.noreply.github.com> Date: Tue, 16 Sep 2025 03:07:52 -0700 Subject: [PATCH 11/13] Changed I2C init order --- SHAL/Src/Peripheral/I2C/SHAL_I2C.cpp | 38 ++++++++++++++++++++++------ SHAL/Src/main.cpp | 2 +- 2 files changed, 31 insertions(+), 9 deletions(-) diff --git a/SHAL/Src/Peripheral/I2C/SHAL_I2C.cpp b/SHAL/Src/Peripheral/I2C/SHAL_I2C.cpp index 722870f..cc89305 100644 --- a/SHAL/Src/Peripheral/I2C/SHAL_I2C.cpp +++ b/SHAL/Src/Peripheral/I2C/SHAL_I2C.cpp @@ -5,15 +5,21 @@ #include "SHAL_I2C.h" #include "SHAL_GPIO.h" +#include "SHAL_UART.h" + void SHAL_I2C::init(I2C_Pair pair) volatile { m_I2CPair = pair; - SHAL_I2C_Pair I2CPair = getI2CPair(pair); //Get the UART_PAIR information to be initialized + SHAL_I2C_Pair I2CPair = getI2CPair(pair); //Get the I2C_PAIR information to be initialized //Get the SHAL_GPIO pins for this SHAL_I2C setup GPIO_Key SCL_Key = I2CPair.SCL_Key; //SCL pin GPIO_Key SDA_Key = I2CPair.SDA_Key; //SDA pin + SHAL_I2C_Enable_Reg pairI2CEnable = getI2CEnableReg(pair); //Register and mask to enable the I2C peripheral + + *pairI2CEnable.reg &= ~pairI2CEnable.mask; //Enable I2C peripheral clock + GET_GPIO(SCL_Key).setPinMode(PinMode::ALTERNATE_FUNCTION_MODE); //Implicitly initializes and enables GPIO bus GET_GPIO(SDA_Key).setPinMode(PinMode::ALTERNATE_FUNCTION_MODE); @@ -30,13 +36,12 @@ void SHAL_I2C::init(I2C_Pair pair) volatile { GET_GPIO(SCL_Key).setInternalResistor(InternalResistorType::PULLUP); GET_GPIO(SDA_Key).setInternalResistor(InternalResistorType::PULLUP); - SHAL_I2C_Enable_Reg pairI2CEnable = getI2CEnableReg(pair); //Register and mask to enable the I2C peripheral SHAL_I2C_Reset_Reg pairI2CReset = getI2CResetReg(pair); - *pairI2CReset.reg |= pairI2CReset.mask; //Reset peripheral *pairI2CEnable.reg |= pairI2CEnable.mask; //Enable I2C peripheral clock - I2CPair.I2CReg->CR1 |= I2C_CR1_PE; //Enable I2C peripheral + *pairI2CReset.reg |= pairI2CReset.mask; //Reset peripheral + *pairI2CReset.reg &= ~pairI2CReset.mask; //Reset peripheral } void SHAL_I2C::setClockConfig(uint8_t prescaler, uint8_t dataSetupTime, uint8_t dataHoldTime, uint8_t SCLHighPeriod, uint8_t SCLLowPeriod) { @@ -48,34 +53,48 @@ void SHAL_I2C::setClockConfig(uint8_t prescaler, uint8_t dataSetupTime, uint8_t *clockReg.reg |= (dataHoldTime << clockReg.dataHoldTime_offset); *clockReg.reg |= (SCLHighPeriod << clockReg.SCLHighPeriod_offset); *clockReg.reg |= (SCLLowPeriod << clockReg.SCLLowPeriod_offset); + + getI2CPair(m_I2CPair).I2CReg->CR1 |= I2C_CR1_PE; //Enable I2C peripheral } void SHAL_I2C::setClockConfig(uint32_t configuration) { *getI2CTimerReg(m_I2CPair).reg = configuration; + + getI2CPair(m_I2CPair).I2CReg->CR1 |= I2C_CR1_PE; //Enable I2C peripheral } void SHAL_I2C::masterWriteRead(uint8_t addr,const uint8_t* writeData, size_t writeLen, uint8_t* readData, size_t readLen) { volatile I2C_TypeDef* I2CPeripheral = getI2CPair(m_I2CPair).I2CReg; + SHAL_UART2.sendString("1\t\n"); + //Wait for I2C bus while (I2CPeripheral->ISR & I2C_ISR_BUSY); + SHAL_UART2.sendString("2\t\n"); + + //Write phase if (writeLen > 0) { //Configure: NBYTES = wlen, write mode, START - I2CPeripheral->CR2 = (addr << 1) | - (writeLen << I2C_CR2_NBYTES_Pos) | - I2C_CR2_START; + I2CPeripheral->CR2 = (addr << 1) | (writeLen << I2C_CR2_NBYTES_Pos) | I2C_CR2_START; + + SHAL_UART2.sendString("2.5\t\n"); for (size_t i = 0; i < writeLen; i++) { - while (!(I2CPeripheral->ISR & I2C_ISR_TXIS)); // TX ready + while(!(I2CPeripheral->ISR & I2C_ISR_TXIS)); //TX ready I2CPeripheral->TXDR = writeData[i]; } + SHAL_UART2.sendString("2.67\t\n"); + //Wait until transfer complete while (!(I2CPeripheral->ISR & I2C_ISR_TC)); } + SHAL_UART2.sendString("3\t\n"); + + //Read phase if (readLen > 0) { I2CPeripheral->CR2 = (addr << 1) | @@ -88,6 +107,9 @@ void SHAL_I2C::masterWriteRead(uint8_t addr,const uint8_t* writeData, size_t wri readData[i] = static_cast(I2CPeripheral->RXDR); } } + + SHAL_UART2.sendString("4\t\n"); + } void SHAL_I2C::masterWrite(uint8_t addr, const uint8_t *writeData, uint8_t writeLen) { diff --git a/SHAL/Src/main.cpp b/SHAL/Src/main.cpp index eaa702e..302378c 100644 --- a/SHAL/Src/main.cpp +++ b/SHAL/Src/main.cpp @@ -42,7 +42,7 @@ int main() { uint8_t initByte[1] = {0x71}; - uint8_t status = SHAL_I2C1.masterWriteReadByte(0x38,initByte,1); + uint8_t status = SHAL_I2C1.masterWriteReadByte(0xEE,initByte,1); if ((status & 0x18) != 0x18) { SHAL_UART2.sendString("DHT ready"); From 8ce717033a4ac0c2ce0811aec0056dc42d8383da Mon Sep 17 00:00:00 2001 From: Ea-r-th <39779954+Ea-r-th@users.noreply.github.com> Date: Wed, 17 Sep 2025 20:07:17 -0700 Subject: [PATCH 12/13] Added timeout wait functions to core --- SHAL/Include/Core/SHAL_CORE.h | 7 ++++ SHAL/Src/Core/SHAL_CORE.cpp | 20 ++++++++++ SHAL/Src/Peripheral/I2C/SHAL_I2C.cpp | 24 +++++------- SHAL/Src/main.cpp | 57 ++++++++++++++++++++-------- 4 files changed, 77 insertions(+), 31 deletions(-) diff --git a/SHAL/Include/Core/SHAL_CORE.h b/SHAL/Include/Core/SHAL_CORE.h index 256d0cc..9abbb29 100644 --- a/SHAL/Include/Core/SHAL_CORE.h +++ b/SHAL/Include/Core/SHAL_CORE.h @@ -22,6 +22,9 @@ void SHAL_init(); //Universal structs and defines --------------------------- +typedef bool (*condition_fn_t)(void); + + //Currently configures systick to count down in microseconds void systick_init(); @@ -30,6 +33,10 @@ void SHAL_delay_us(uint32_t us); void SHAL_delay_ms(uint32_t ms); +bool SHAL_wait_for_condition_us(condition_fn_t condition, uint32_t timeout_us); + +bool SHAL_wait_for_condition_ms(condition_fn_t condition, uint32_t timeout_ms); + //--------------------------------------------------------- diff --git a/SHAL/Src/Core/SHAL_CORE.cpp b/SHAL/Src/Core/SHAL_CORE.cpp index 2f6f1b3..6f44eb2 100644 --- a/SHAL/Src/Core/SHAL_CORE.cpp +++ b/SHAL/Src/Core/SHAL_CORE.cpp @@ -39,4 +39,24 @@ void SHAL_delay_ms(uint32_t ms){ while(ms-- > 0){ SHAL_delay_us(1000); } +} + +bool SHAL_wait_for_condition_us(condition_fn_t condition, uint32_t timeout_us){ + while (timeout_us--) { + if (condition()) { + return true; // Condition met + } + SHAL_delay_us(1); // Wait 1 µs + } + return false; // Timeout +} + +bool SHAL_wait_for_condition_ms(condition_fn_t condition, uint32_t timeout_ms){ + while (timeout_ms--) { + if (condition()) { + return true; // Condition met + } + SHAL_delay_ms(1); // Wait 1 µs + } + return false; // Timeout } \ No newline at end of file diff --git a/SHAL/Src/Peripheral/I2C/SHAL_I2C.cpp b/SHAL/Src/Peripheral/I2C/SHAL_I2C.cpp index cc89305..a6db22e 100644 --- a/SHAL/Src/Peripheral/I2C/SHAL_I2C.cpp +++ b/SHAL/Src/Peripheral/I2C/SHAL_I2C.cpp @@ -64,39 +64,34 @@ void SHAL_I2C::setClockConfig(uint32_t configuration) { } void SHAL_I2C::masterWriteRead(uint8_t addr,const uint8_t* writeData, size_t writeLen, uint8_t* readData, size_t readLen) { - volatile I2C_TypeDef* I2CPeripheral = getI2CPair(m_I2CPair).I2CReg; - SHAL_UART2.sendString("1\t\n"); + SHAL_UART2.sendString("Beginning of writeread\r\n"); + + + volatile I2C_TypeDef* I2CPeripheral = getI2CPair(m_I2CPair).I2CReg; //Wait for I2C bus while (I2CPeripheral->ISR & I2C_ISR_BUSY); - SHAL_UART2.sendString("2\t\n"); - - //Write phase if (writeLen > 0) { //Configure: NBYTES = wlen, write mode, START I2CPeripheral->CR2 = (addr << 1) | (writeLen << I2C_CR2_NBYTES_Pos) | I2C_CR2_START; - SHAL_UART2.sendString("2.5\t\n"); - for (size_t i = 0; i < writeLen; i++) { while(!(I2CPeripheral->ISR & I2C_ISR_TXIS)); //TX ready I2CPeripheral->TXDR = writeData[i]; } - SHAL_UART2.sendString("2.67\t\n"); - //Wait until transfer complete while (!(I2CPeripheral->ISR & I2C_ISR_TC)); } - SHAL_UART2.sendString("3\t\n"); - - //Read phase if (readLen > 0) { + + SHAL_UART2.sendString("Read initiated\r\n"); + I2CPeripheral->CR2 = (addr << 1) | I2C_CR2_RD_WRN | (readLen << I2C_CR2_NBYTES_Pos) | @@ -104,12 +99,11 @@ void SHAL_I2C::masterWriteRead(uint8_t addr,const uint8_t* writeData, size_t wri for (size_t i = 0; i < readLen; i++) { while (!(I2CPeripheral->ISR & I2C_ISR_RXNE)); //RX ready + SHAL_UART2.sendString("Read byte"); readData[i] = static_cast(I2CPeripheral->RXDR); } } - - SHAL_UART2.sendString("4\t\n"); - + SHAL_UART2.sendString("\r\n"); } void SHAL_I2C::masterWrite(uint8_t addr, const uint8_t *writeData, uint8_t writeLen) { diff --git a/SHAL/Src/main.cpp b/SHAL/Src/main.cpp index 302378c..0db2e09 100644 --- a/SHAL/Src/main.cpp +++ b/SHAL/Src/main.cpp @@ -3,8 +3,40 @@ void c3Interrupt(){ - PIN(A5).toggle(); - SHAL_UART2.sendString("New test"); + SHAL_UART2.sendString("Begin\r\n"); + + uint8_t cmd[3] = {0xAC, 0x33, 0x00}; + SHAL_I2C1.masterWrite(0x38, cmd, 3); + + SHAL_UART2.sendString("Hello\r\n"); + + SHAL_delay_ms(100); + + uint8_t buffer[7] = {0}; + + SHAL_UART2.sendString("Buffer created?\r\n"); + + //Read 7 bytes (status + 5 data + CRC) + SHAL_I2C1.masterRead(0x38, buffer, 7); + + SHAL_UART2.sendString("Read complete\r\n"); + + //Parse humidity (20 bits) + uint32_t rawHumidity = ((uint32_t)buffer[1] << 12) | + ((uint32_t)buffer[2] << 4) | + ((uint32_t)buffer[3] >> 4); + + // Parse temperature (20 bits) + uint32_t rawTemp = (((uint32_t)buffer[3] & 0x0F) << 16) | + ((uint32_t)buffer[4] << 8) | + ((uint32_t)buffer[5]); + + float humidity = (rawHumidity * 100.0f) / 1048576.0f; // 2^20 = 1048576 + float temperature = (rawTemp * 200.0f) / 1048576.0f - 50.0f; + + char buf[64]; + sprintf(buf, "Temp: %.2f C, Hum: %.2f %%\r\n", temperature, humidity); + SHAL_UART2.sendString(buf); } void tim2Handler(){ @@ -32,25 +64,18 @@ int main() { PIN(A4).setPinMode(PinMode::OUTPUT_MODE); PIN(A5).setPinMode(PinMode::OUTPUT_MODE); - //Temporary setup for DHT20 - PIN(A5).setLow(); - SHAL_delay_ms(5000); //Wait 100 ms from datasheet + SHAL_delay_ms(3000); //Wait 100 ms from datasheet - PIN(A5).setHigh(); + uint8_t cmd = 0x71; + uint8_t status = 0; - uint8_t initByte[1] = {0x71}; + SHAL_I2C1.masterWriteRead(0x38, &cmd, 1, &status, 1); - uint8_t status = SHAL_I2C1.masterWriteReadByte(0xEE,initByte,1); - - if ((status & 0x18) != 0x18) { - SHAL_UART2.sendString("DHT ready"); - } else { - SHAL_UART2.sendString("DHT broke"); - } - - PIN(A5).setLow(); + char statusString[32]; + sprintf(statusString, "Status = 0x%02X\r\n", status); + SHAL_UART2.sendString(statusString); //End setup From cb232ea55e112939e065a853291f589bfc1a95f2 Mon Sep 17 00:00:00 2001 From: Ea-r-th <39779954+Ea-r-th@users.noreply.github.com> Date: Thu, 18 Sep 2025 01:19:03 -0700 Subject: [PATCH 13/13] I2C tested, main file now contains rough sample for use with DHT20 --- SHAL/Include/Core/SHAL_CORE.h | 29 ++++++++++++++++-- SHAL/Src/Core/SHAL_CORE.cpp | 20 ------------ SHAL/Src/Peripheral/I2C/SHAL_I2C.cpp | 37 ++++++++++++++-------- SHAL/Src/main.cpp | 46 ++++++++++++++++------------ 4 files changed, 77 insertions(+), 55 deletions(-) diff --git a/SHAL/Include/Core/SHAL_CORE.h b/SHAL/Include/Core/SHAL_CORE.h index 9abbb29..c891dda 100644 --- a/SHAL/Include/Core/SHAL_CORE.h +++ b/SHAL/Include/Core/SHAL_CORE.h @@ -24,6 +24,13 @@ void SHAL_init(); typedef bool (*condition_fn_t)(void); +#define SHAL_WAIT_FOR_CONDITION_US(cond, timeout_us) \ + SHAL_wait_for_condition_us([&](){ return (cond); }, (timeout_us)) + +#define SHAL_WAIT_FOR_CONDITION_MS(cond, timeout_ms) \ + SHAL_wait_for_condition_ms([&](){ return (cond); }, (timeout_ms)) + + //Currently configures systick to count down in microseconds void systick_init(); @@ -33,9 +40,27 @@ void SHAL_delay_us(uint32_t us); void SHAL_delay_ms(uint32_t ms); -bool SHAL_wait_for_condition_us(condition_fn_t condition, uint32_t timeout_us); +template +bool SHAL_wait_for_condition_us(Condition cond, uint32_t timeout_us) { + while (timeout_us--) { + if (cond()) { + return true; // success + } + SHAL_delay_us(1); + } + return false; // timeout +} -bool SHAL_wait_for_condition_ms(condition_fn_t condition, uint32_t timeout_ms); +template +bool SHAL_wait_for_condition_ms(Condition cond, uint32_t timeout_ms) { + while (timeout_ms--) { + if (cond()) { + return true; // success + } + SHAL_delay_ms(1); + } + return false; // timeout +} //--------------------------------------------------------- diff --git a/SHAL/Src/Core/SHAL_CORE.cpp b/SHAL/Src/Core/SHAL_CORE.cpp index 6f44eb2..8f46a8f 100644 --- a/SHAL/Src/Core/SHAL_CORE.cpp +++ b/SHAL/Src/Core/SHAL_CORE.cpp @@ -40,23 +40,3 @@ void SHAL_delay_ms(uint32_t ms){ SHAL_delay_us(1000); } } - -bool SHAL_wait_for_condition_us(condition_fn_t condition, uint32_t timeout_us){ - while (timeout_us--) { - if (condition()) { - return true; // Condition met - } - SHAL_delay_us(1); // Wait 1 µs - } - return false; // Timeout -} - -bool SHAL_wait_for_condition_ms(condition_fn_t condition, uint32_t timeout_ms){ - while (timeout_ms--) { - if (condition()) { - return true; // Condition met - } - SHAL_delay_ms(1); // Wait 1 µs - } - return false; // Timeout -} \ No newline at end of file diff --git a/SHAL/Src/Peripheral/I2C/SHAL_I2C.cpp b/SHAL/Src/Peripheral/I2C/SHAL_I2C.cpp index a6db22e..b8ea899 100644 --- a/SHAL/Src/Peripheral/I2C/SHAL_I2C.cpp +++ b/SHAL/Src/Peripheral/I2C/SHAL_I2C.cpp @@ -65,13 +65,12 @@ void SHAL_I2C::setClockConfig(uint32_t configuration) { void SHAL_I2C::masterWriteRead(uint8_t addr,const uint8_t* writeData, size_t writeLen, uint8_t* readData, size_t readLen) { - SHAL_UART2.sendString("Beginning of writeread\r\n"); - - volatile I2C_TypeDef* I2CPeripheral = getI2CPair(m_I2CPair).I2CReg; - //Wait for I2C bus - while (I2CPeripheral->ISR & I2C_ISR_BUSY); + if(!SHAL_WAIT_FOR_CONDITION_MS((I2CPeripheral->ISR & I2C_ISR_BUSY) == 0, 100)){ + SHAL_UART2.sendString("I2C timed out waiting for not busy\r\n"); + return; + } //Write phase if (writeLen > 0) { @@ -79,12 +78,18 @@ void SHAL_I2C::masterWriteRead(uint8_t addr,const uint8_t* writeData, size_t wri I2CPeripheral->CR2 = (addr << 1) | (writeLen << I2C_CR2_NBYTES_Pos) | I2C_CR2_START; for (size_t i = 0; i < writeLen; i++) { - while(!(I2CPeripheral->ISR & I2C_ISR_TXIS)); //TX ready + if(!SHAL_WAIT_FOR_CONDITION_MS((I2CPeripheral->ISR & I2C_ISR_TXIS) != 0, 100)){ + SHAL_UART2.sendString("I2C timed out waiting for TX\r\n"); + return; + } I2CPeripheral->TXDR = writeData[i]; } //Wait until transfer complete - while (!(I2CPeripheral->ISR & I2C_ISR_TC)); + if(!SHAL_WAIT_FOR_CONDITION_MS((I2CPeripheral->ISR & I2C_ISR_TC) != 0, 100)){ + SHAL_UART2.sendString("I2C timed out waiting for TC\r\n"); + return; + } } //Read phase @@ -92,18 +97,24 @@ void SHAL_I2C::masterWriteRead(uint8_t addr,const uint8_t* writeData, size_t wri SHAL_UART2.sendString("Read initiated\r\n"); - I2CPeripheral->CR2 = (addr << 1) | - I2C_CR2_RD_WRN | - (readLen << I2C_CR2_NBYTES_Pos) | - I2C_CR2_START | I2C_CR2_AUTOEND; + I2CPeripheral->CR2 &= ~(I2C_CR2_NBYTES | I2C_CR2_SADD | I2C_CR2_RD_WRN); + I2CPeripheral->CR2 |= (addr << 1) | + I2C_CR2_RD_WRN | + (readLen << I2C_CR2_NBYTES_Pos) | + I2C_CR2_START | I2C_CR2_AUTOEND; for (size_t i = 0; i < readLen; i++) { - while (!(I2CPeripheral->ISR & I2C_ISR_RXNE)); //RX ready + if(!SHAL_WAIT_FOR_CONDITION_MS((I2CPeripheral->ISR & I2C_ISR_RXNE) != 0 , 100)){ + SHAL_UART2.sendString("I2C timed out waiting for RXNE\r\n"); + return; + } SHAL_UART2.sendString("Read byte"); readData[i] = static_cast(I2CPeripheral->RXDR); } } - SHAL_UART2.sendString("\r\n"); + else{ + I2CPeripheral->CR2 |= I2C_CR2_STOP; + } } void SHAL_I2C::masterWrite(uint8_t addr, const uint8_t *writeData, uint8_t writeLen) { diff --git a/SHAL/Src/main.cpp b/SHAL/Src/main.cpp index 0db2e09..db71ff0 100644 --- a/SHAL/Src/main.cpp +++ b/SHAL/Src/main.cpp @@ -1,6 +1,7 @@ #include "SHAL.h" #include "stm32f0xx.h" +#include void c3Interrupt(){ SHAL_UART2.sendString("Begin\r\n"); @@ -8,35 +9,36 @@ void c3Interrupt(){ uint8_t cmd[3] = {0xAC, 0x33, 0x00}; SHAL_I2C1.masterWrite(0x38, cmd, 3); - SHAL_UART2.sendString("Hello\r\n"); - SHAL_delay_ms(100); - uint8_t buffer[7] = {0}; - - SHAL_UART2.sendString("Buffer created?\r\n"); + uint8_t dht_buf[7] = {0}; //Read 7 bytes (status + 5 data + CRC) - SHAL_I2C1.masterRead(0x38, buffer, 7); - - SHAL_UART2.sendString("Read complete\r\n"); + SHAL_I2C1.masterRead(0x38, dht_buf, 7); //Parse humidity (20 bits) - uint32_t rawHumidity = ((uint32_t)buffer[1] << 12) | - ((uint32_t)buffer[2] << 4) | - ((uint32_t)buffer[3] >> 4); + uint32_t rawHumidity = ((uint32_t)dht_buf[1] << 12) | + ((uint32_t)dht_buf[2] << 4) | + ((uint32_t)dht_buf[3] >> 4); - // Parse temperature (20 bits) - uint32_t rawTemp = (((uint32_t)buffer[3] & 0x0F) << 16) | - ((uint32_t)buffer[4] << 8) | - ((uint32_t)buffer[5]); + uint32_t rawTemp = (((uint32_t)dht_buf[3] & 0x0F) << 16) | + ((uint32_t)dht_buf[4] << 8) | + ((uint32_t)dht_buf[5]); - float humidity = (rawHumidity * 100.0f) / 1048576.0f; // 2^20 = 1048576 - float temperature = (rawTemp * 200.0f) / 1048576.0f - 50.0f; + // Use 64-bit intermediate to avoid overflow + uint32_t hum_hundredths = (uint32_t)(((uint64_t)rawHumidity * 10000ULL) >> 20); + int32_t temp_hundredths = (int32_t)((((uint64_t)rawTemp * 20000ULL) >> 20) - 5000); - char buf[64]; - sprintf(buf, "Temp: %.2f C, Hum: %.2f %%\r\n", temperature, humidity); - SHAL_UART2.sendString(buf); + char out[80]; + sprintf(out, "rawH=0x%05lX rawT=0x%05lX\r\n", + (unsigned long)rawHumidity, (unsigned long)rawTemp); + SHAL_UART2.sendString(out); + + // print as X.YY + sprintf(out, "Temp: %ld.%02ld C, Hum: %ld.%02ld %%\r\n", + (long)(temp_hundredths / 100), (long)(abs(temp_hundredths % 100)), + (long)(hum_hundredths / 100), (long)(hum_hundredths % 100)); + SHAL_UART2.sendString(out); } void tim2Handler(){ @@ -77,6 +79,10 @@ int main() { sprintf(statusString, "Status = 0x%02X\r\n", status); SHAL_UART2.sendString(statusString); + + SHAL_delay_ms(10); + + c3Interrupt(); //End setup while (true) {