diff --git a/SHAL/Include/Core/SHAL_CORE.h b/SHAL/Include/Core/SHAL_CORE.h index 68ac2a0..1197ad7 100644 --- a/SHAL/Include/Core/SHAL_CORE.h +++ b/SHAL/Include/Core/SHAL_CORE.h @@ -70,12 +70,20 @@ bool SHAL_wait_for_condition_ms(Condition cond, uint32_t timeout_ms) { return false; // timeout } +//Sets bits starting from offset as the LSB void SHAL_set_bits(volatile uint32_t* reg, uint32_t size, uint32_t bits, uint32_t offset){ uint32_t mask = (1 << (size)) - 1; *reg &= ~(mask << offset); *reg |= bits << offset; } +//Sets bits starting from offset as the LSB (for uint16_t) +void SHAL_set_bits_16(volatile uint16_t* reg, uint32_t size, uint32_t bits, uint32_t offset){ + uint16_t mask = (1 << (size)) - 1; + *reg &= ~(mask << offset); + *reg |= bits << offset; +} + void SHAL_clear_bitmask(volatile uint32_t* reg, uint32_t mask){ *reg &= ~(mask); } diff --git a/SHAL/Include/Peripheral/I2C/Reg/SHAL_I2C_REG_L432KC.h b/SHAL/Include/Peripheral/I2C/Reg/SHAL_I2C_REG_L432KC.h index 243f7ee..0d8dae6 100644 --- a/SHAL/Include/Peripheral/I2C/Reg/SHAL_I2C_REG_L432KC.h +++ b/SHAL/Include/Peripheral/I2C/Reg/SHAL_I2C_REG_L432KC.h @@ -62,9 +62,6 @@ constexpr SHAL_I2C_Reset_Reg getI2CResetReg(const I2C_Pair pair){ __builtin_unreachable(); } -constexpr SHAL_I2C_Reset_Reg getI2CResetRe() { - return {&RCC->APB1RSTR1,RCC_APB1RSTR1_I2C1RST}; -} //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){ 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 975bff5..aa86e76 100644 --- a/SHAL/Include/Peripheral/UART/Reg/SHAL_UART_REG_F072xB.h +++ b/SHAL/Include/Peripheral/UART/Reg/SHAL_UART_REG_F072xB.h @@ -18,7 +18,7 @@ #define SHAL_UART4 UART(4) //Valid usart Tx and Rx pairings for STM32F072 -enum class UART_Pair : uint8_t{ +enum class UART_Pair_Key : uint8_t{ //UART1 Tx1A9_Rx1A10, Tx1B6_Rx1B7, @@ -41,65 +41,65 @@ enum class UART_Pair : uint8_t{ }; -constexpr SHAL_UART_Pair getUARTPair(const UART_Pair pair){ +constexpr SHAL_UART_Pair getUARTPair(const UART_Pair_Key pair){ switch(pair){ - 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: + case UART_Pair_Key::Tx1A9_Rx1A10: return {USART1, GPIO_Key::A9, GPIO_Key::A10, GPIO_Alternate_Function::AF1, GPIO_Alternate_Function::AF1}; + case UART_Pair_Key::Tx1B6_Rx1B7: return {USART1, GPIO_Key::B6, GPIO_Key::B7, GPIO_Alternate_Function::AF0, GPIO_Alternate_Function::AF0}; + case UART_Pair_Key::Tx2A2_Rx2A3: return {USART2, GPIO_Key::A2, GPIO_Key::A3, GPIO_Alternate_Function::AF1, GPIO_Alternate_Function::AF1}; + case UART_Pair_Key::Tx2A14_Rx2A15: return {USART2, GPIO_Key::A14, GPIO_Key::A15, GPIO_Alternate_Function::AF1, GPIO_Alternate_Function::AF1}; + case UART_Pair_Key::Tx3B10_Rx3B11: return {USART3, GPIO_Key::B10, GPIO_Key::B11, GPIO_Alternate_Function::AF4, GPIO_Alternate_Function::AF4}; + case UART_Pair_Key::Tx3C4_Rx3C5: return {USART3, GPIO_Key::C4, GPIO_Key::C5, GPIO_Alternate_Function::AF1, GPIO_Alternate_Function::AF1}; + case UART_Pair_Key::Tx3C10_Rx3C11: return {USART3, GPIO_Key::C10, GPIO_Key::C11, GPIO_Alternate_Function::AF1, GPIO_Alternate_Function::AF1}; + case UART_Pair_Key::Tx4A0_Rx4A1: return {USART4, GPIO_Key::A0, GPIO_Key::A1, GPIO_Alternate_Function::AF4, GPIO_Alternate_Function::AF4}; + case UART_Pair_Key::Tx4C10_Rx4C11: return {USART4, GPIO_Key::C10, GPIO_Key::C11, GPIO_Alternate_Function::AF0, GPIO_Alternate_Function::AF0}; + case UART_Pair_Key::NUM_PAIRS: + case UART_Pair_Key::INVALID: assert(false); return {nullptr, GPIO_Key::INVALID, GPIO_Key::INVALID, GPIO_Alternate_Function::AF0, GPIO_Alternate_Function::AF0}; } __builtin_unreachable(); } -constexpr uint8_t getUARTChannel(const UART_Pair pair){ +constexpr uint8_t getUARTChannel(const UART_Pair_Key pair){ switch(pair){ - case UART_Pair::Tx1A9_Rx1A10: - case UART_Pair::Tx1B6_Rx1B7: + case UART_Pair_Key::Tx1A9_Rx1A10: + case UART_Pair_Key::Tx1B6_Rx1B7: return 0; - case UART_Pair::Tx2A2_Rx2A3: - case UART_Pair::Tx2A14_Rx2A15: + case UART_Pair_Key::Tx2A2_Rx2A3: + case UART_Pair_Key::Tx2A14_Rx2A15: return 1; - case UART_Pair::Tx3B10_Rx3B11: - case UART_Pair::Tx3C4_Rx3C5: - case UART_Pair::Tx3C10_Rx3C11: + case UART_Pair_Key::Tx3B10_Rx3B11: + case UART_Pair_Key::Tx3C4_Rx3C5: + case UART_Pair_Key::Tx3C10_Rx3C11: return 2; - case UART_Pair::Tx4A0_Rx4A1: - case UART_Pair::Tx4C10_Rx4C11: + case UART_Pair_Key::Tx4A0_Rx4A1: + case UART_Pair_Key::Tx4C10_Rx4C11: return 3; - case UART_Pair::NUM_PAIRS: - case UART_Pair::INVALID: + case UART_Pair_Key::NUM_PAIRS: + case UART_Pair_Key::INVALID: assert(false); return 0; } __builtin_unreachable(); } -constexpr SHAL_UART_ENABLE_REG getUARTEnableReg(const UART_Pair pair){ +constexpr SHAL_UART_Enable_Register getUARTEnableReg(const UART_Pair_Key pair){ switch(pair){ - case UART_Pair::Tx1A9_Rx1A10: - case UART_Pair::Tx1B6_Rx1B7: + case UART_Pair_Key::Tx1A9_Rx1A10: + case UART_Pair_Key::Tx1B6_Rx1B7: return {&RCC->APB2ENR,RCC_APB2ENR_USART1EN}; - case UART_Pair::Tx2A2_Rx2A3: - case UART_Pair::Tx2A14_Rx2A15: + case UART_Pair_Key::Tx2A2_Rx2A3: + case UART_Pair_Key::Tx2A14_Rx2A15: return {&RCC->APB1ENR,RCC_APB1ENR_USART2EN}; - case UART_Pair::Tx3B10_Rx3B11: - case UART_Pair::Tx3C4_Rx3C5: - case UART_Pair::Tx3C10_Rx3C11: + case UART_Pair_Key::Tx3B10_Rx3B11: + case UART_Pair_Key::Tx3C4_Rx3C5: + case UART_Pair_Key::Tx3C10_Rx3C11: return {&RCC->APB1ENR,RCC_APB1ENR_USART3EN}; - case UART_Pair::Tx4A0_Rx4A1: - case UART_Pair::Tx4C10_Rx4C11: + case UART_Pair_Key::Tx4A0_Rx4A1: + case UART_Pair_Key::Tx4C10_Rx4C11: return {&RCC->APB1ENR,RCC_APB1ENR_USART4EN}; - case UART_Pair::NUM_PAIRS: - case UART_Pair::INVALID: + case UART_Pair_Key::NUM_PAIRS: + case UART_Pair_Key::INVALID: assert(false); return {nullptr, 0}; } diff --git a/SHAL/Include/Peripheral/UART/Reg/SHAL_UART_REG_L432KC.h b/SHAL/Include/Peripheral/UART/Reg/SHAL_UART_REG_L432KC.h new file mode 100644 index 0000000..74fca42 --- /dev/null +++ b/SHAL/Include/Peripheral/UART/Reg/SHAL_UART_REG_L432KC.h @@ -0,0 +1,104 @@ +// +// Created by Luca on 9/7/2025. +// + +#ifndef SHAL_UART_REG_L432KC_H +#define SHAL_UART_REG_L432KC_H + +#include +#include + +#include "SHAL_UART_TYPES.h" + +#define NUM_USART_LINES 4 + +#define SHAL_UART1 UART(1) +#define SHAL_UART2 UART(2) + + +//Valid usart Tx and Rx pairings for STM32L432KC +enum class UART_Pair_Key : uint8_t{ + //UART1 + Tx1A9_Rx1A10, + Tx1B6_Rx1B7, + + //UART2 + Tx2A2_Rx2A3, + + NUM_PAIRS, + INVALID +}; + + +static inline SHAL_UART_Pair getUARTPair(const UART_Pair_Key pair){ + switch(pair){ + case UART_Pair_Key::Tx1A9_Rx1A10: return {USART1, GPIO_Key::A9, GPIO_Key::A10, GPIO_Alternate_Function::AF7, GPIO_Alternate_Function::AF7}; + case UART_Pair_Key::Tx1B6_Rx1B7: return {USART1, GPIO_Key::B6, GPIO_Key::B7, GPIO_Alternate_Function::AF7, GPIO_Alternate_Function::AF7}; + case UART_Pair_Key::Tx2A2_Rx2A3: return {USART2, GPIO_Key::A2, GPIO_Key::A3, GPIO_Alternate_Function::AF7, GPIO_Alternate_Function::AF7}; + + case UART_Pair_Key::NUM_PAIRS: + case UART_Pair_Key::INVALID: + __builtin_unreachable(); + } + __builtin_unreachable(); +} + +static inline uint8_t getUARTChannel(const UART_Pair_Key pair){ //TODO remove? + switch(pair){ + case UART_Pair_Key::Tx1A9_Rx1A10: + case UART_Pair_Key::Tx1B6_Rx1B7: + return 0; + case UART_Pair_Key::Tx2A2_Rx2A3: + return 1; + case UART_Pair_Key::NUM_PAIRS: + case UART_Pair_Key::INVALID: + assert(false); + return 0; + } + __builtin_unreachable(); +} + +constexpr SHAL_UART_Enable_Register getUARTEnableReg(const UART_Pair_Key pair){ + switch(pair){ + case UART_Pair_Key::Tx1A9_Rx1A10: + case UART_Pair_Key::Tx1B6_Rx1B7: + return {&RCC->APB2ENR,RCC_APB2ENR_USART1EN}; + case UART_Pair_Key::Tx2A2_Rx2A3: + return {&RCC->APB1ENR1,RCC_APB1ENR1_USART2EN}; + case UART_Pair_Key::NUM_PAIRS: + case UART_Pair_Key::INVALID: + assert(false); + return {nullptr, 0}; + } + __builtin_unreachable(); +} + +static inline SHAL_UART_Control_Register_1 getUARTControlRegister1(UART_Pair_Key key){ + SHAL_UART_Control_Register_1 res = {nullptr, USART_CR1_UE, USART_CR1_TE, USART_CR1_RE}; + + res.reg = &getUARTPair(key).USARTReg->CR1; + return res; +}; + +static inline SHAL_UART_Baud_Rate_Generation_Register getUARTBaudRateGenerationRegister(UART_Pair_Key key){ + SHAL_UART_Baud_Rate_Generation_Register res = {nullptr, 1UL << 15}; //TODO un-hardcode if other devices have wider baud rate allowances + + res.reg = &getUARTPair(key).USARTReg->BRR; + return res; +}; + +static inline SHAL_UART_Transmit_Data_Register getUARTTransmitDataRegister(UART_Pair_Key key){ + SHAL_UART_Transmit_Data_Register res = {nullptr, 1UL << 15}; //TODO un-hardcode if other devices have wider baud rate allowances + + res.reg = &getUARTPair(key).USARTReg->TDR; + return res; +}; + +static inline SHAL_UART_ISR_FIFO_Disabled getUARTISRFifoDisabled(UART_Pair_Key key){ + SHAL_UART_ISR_FIFO_Disabled res = {nullptr, USART_ISR_TXE}; + + res.reg = &getUARTPair(key).USARTReg->ISR; + return res; +}; + +#endif //SHAL_UART_REG_F072XB_H diff --git a/SHAL/Include/Peripheral/UART/SHAL_UART.h b/SHAL/Include/Peripheral/UART/SHAL_UART.h index c8bced0..b9ffb3a 100644 --- a/SHAL/Include/Peripheral/UART/SHAL_UART.h +++ b/SHAL/Include/Peripheral/UART/SHAL_UART.h @@ -17,7 +17,7 @@ class SHAL_UART{ friend class UARTManager; public: - void init(SHAL_UART_Pair pair); + void init(UART_Pair_Key pair); //begins Tx and Usart TODO either modify this function or add a new one that supports Rx void begin(uint32_t baudRate) volatile; @@ -34,7 +34,7 @@ private: //Creates a SHAL_UART based on a pair of two valid U(S)ART pins - UART_Pair m_UARTPair = UART_Pair::INVALID; + UART_Pair_Key m_key = UART_Pair_Key::INVALID; }; diff --git a/SHAL/Include/Peripheral/UART/SHAL_UART_REG.h b/SHAL/Include/Peripheral/UART/SHAL_UART_REG.h index 390e10a..cf7b27e 100644 --- a/SHAL/Include/Peripheral/UART/SHAL_UART_REG.h +++ b/SHAL/Include/Peripheral/UART/SHAL_UART_REG.h @@ -47,7 +47,7 @@ #elif defined(STM32L431xx) #include "stm32l431xx.h" #elif defined(STM32L432xx) -#include "stm32l432xx.h" +#include "SHAL_UART_REG_L432KC.h" #elif defined(STM32L433xx) #include "stm32l433xx.h" #elif defined(STM32L442xx) diff --git a/SHAL/Include/Peripheral/UART/SHAL_UART_TYPES.h b/SHAL/Include/Peripheral/UART/SHAL_UART_TYPES.h index b6a658d..11dee29 100644 --- a/SHAL/Include/Peripheral/UART/SHAL_UART_TYPES.h +++ b/SHAL/Include/Peripheral/UART/SHAL_UART_TYPES.h @@ -19,9 +19,33 @@ struct SHAL_UART_Pair{ GPIO_Alternate_Function RxAlternateFunctionMask; }; -struct SHAL_UART_ENABLE_REG{ +struct SHAL_UART_Enable_Register{ volatile uint32_t* reg; uint32_t mask; }; +struct SHAL_UART_Control_Register_1 { + volatile uint32_t* reg; + uint32_t usart_enable_mask; + uint32_t transmit_enable_mask; + uint32_t receive_enable_mask; +}; + +struct SHAL_UART_Baud_Rate_Generation_Register { + volatile uint32_t* reg; + uint32_t offset; +}; + +struct SHAL_UART_Transmit_Data_Register { + volatile uint16_t* reg; + uint16_t offset; +}; + +struct SHAL_UART_ISR_FIFO_Disabled { + volatile uint32_t* reg; + uint32_t transmit_data_register_empty_mask; +}; + + + #endif //SHMINGO_HAL_SHAL_UART_TYPES_H diff --git a/SHAL/Src/STM32F0XX/Peripheral/UART/SHAL_UART.cpp b/SHAL/Src/STM32F0XX/Peripheral/UART/SHAL_UART.cpp index 237ea24..eff7709 100644 --- a/SHAL/Src/STM32F0XX/Peripheral/UART/SHAL_UART.cpp +++ b/SHAL/Src/STM32F0XX/Peripheral/UART/SHAL_UART.cpp @@ -10,7 +10,7 @@ #include "SHAL_UART.h" #include "SHAL_GPIO.h" -void SHAL_UART::init(const UART_Pair pair){ +void SHAL_UART::init(const UART_Pair_Key pair){ m_UARTPair = pair; @@ -26,7 +26,7 @@ void SHAL_UART::init(const UART_Pair 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 SHAL_UART channel + SHAL_UART_Enable_Register pairUARTEnable = getUARTEnableReg(pair); //Register and mask to enable the SHAL_UART channel *pairUARTEnable.reg |= pairUARTEnable.mask; //Enable SHAL_UART line diff --git a/SHAL/Src/STM32L4XX/Peripheral/UART/SHAL_UART.cpp b/SHAL/Src/STM32L4XX/Peripheral/UART/SHAL_UART.cpp index 237ea24..3d78e46 100644 --- a/SHAL/Src/STM32L4XX/Peripheral/UART/SHAL_UART.cpp +++ b/SHAL/Src/STM32L4XX/Peripheral/UART/SHAL_UART.cpp @@ -10,9 +10,9 @@ #include "SHAL_UART.h" #include "SHAL_GPIO.h" -void SHAL_UART::init(const UART_Pair pair){ +void SHAL_UART::init(UART_Pair_Key pair){ - m_UARTPair = pair; + m_key = pair; SHAL_UART_Pair uart_pair = getUARTPair(pair); //Get the UART_PAIR information to be initialized @@ -26,7 +26,7 @@ void SHAL_UART::init(const UART_Pair 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 SHAL_UART channel + SHAL_UART_Enable_Register pairUARTEnable = getUARTEnableReg(pair); //Register and mask to enable the SHAL_UART channel *pairUARTEnable.reg |= pairUARTEnable.mask; //Enable SHAL_UART line @@ -35,18 +35,23 @@ void SHAL_UART::init(const UART_Pair pair){ void SHAL_UART::begin(uint32_t baudRate) volatile { - USART_TypeDef* usart = getUARTPair(m_UARTPair).USARTReg; + USART_TypeDef* usart = getUARTPair(m_key).USARTReg; - usart->CR1 &= ~USART_CR1_UE; //Disable USART + auto control_reg = getUARTControlRegister1(m_key); + + SHAL_clear_bitmask(control_reg.reg, control_reg.usart_enable_mask); //Clear enable bit (turn off usart) usart->CR1 = 0; //Clear USART config - usart->CR1 = USART_CR1_TE | USART_CR1_RE; //Tx enable and Rx Enable + SHAL_apply_bitmask(control_reg.reg, control_reg.transmit_enable_mask); //Enable Tx + SHAL_apply_bitmask(control_reg.reg, control_reg.receive_enable_mask); //Enable Rx - usart->BRR = 8000000 / baudRate; //MAKE SURE ANY FUNCTION THAT CHANGES CLOCK UPDATES THIS! //TODO DO NOT HARDCODE THIS SHIT + auto baud_rate_reg = getUARTBaudRateGenerationRegister(m_key); - usart->CR1 |= USART_CR1_UE; + unsigned long adjustedBaudRate = 8000000 / baudRate; + SHAL_set_bits(baud_rate_reg.reg,16,adjustedBaudRate,baud_rate_reg.offset); //MAKE SURE ANY FUNCTION THAT CHANGES CLOCK UPDATES THIS! //TODO DO NOT HARDCODE THIS SHIT + SHAL_apply_bitmask(control_reg.reg, control_reg.usart_enable_mask); //Clear enable bit (turn off usart) } void SHAL_UART::sendString(const char *s) volatile { @@ -55,11 +60,14 @@ void SHAL_UART::sendString(const char *s) volatile { void SHAL_UART::sendChar(char c) volatile { - USART_TypeDef* usart = getUARTPair(m_UARTPair).USARTReg; + auto ISR_non_fifo = getUARTISRFifoDisabled(m_key); - while(!(usart->ISR & USART_ISR_TXE)); //Wait for usart to finish what it's doing + if(!SHAL_WAIT_FOR_CONDITION_US((*ISR_non_fifo.reg & ISR_non_fifo.transmit_data_register_empty_mask) == 0, 500)){ + return; + } - usart->TDR = c; //Send character + auto transmit_reg = getUARTTransmitDataRegister(m_key); + SHAL_set_bits_16(transmit_reg.reg,16,static_cast(c),transmit_reg.offset); } diff --git a/SHAL/Src/main.cpp b/SHAL/Src/main.cpp index a3bbea7..6a0f590 100644 --- a/SHAL/Src/main.cpp +++ b/SHAL/Src/main.cpp @@ -50,7 +50,7 @@ int main() { SHAL_init(); //Setup UART2 (used by nucleo devices for USB comms) - SHAL_UART2.init(UART_Pair::Tx2A2_Rx2A3); + SHAL_UART2.init(UART_Pair_Key::Tx2A2_Rx2A3); SHAL_UART2.begin(115200); SHAL_I2C1.init(I2C_Pair::SCL1B6_SDA1B7);