Compare commits
12 Commits
64fb4e4a23
...
gpio
| Author | SHA1 | Date | |
|---|---|---|---|
| a599aa5a4e | |||
| a02ec044ce | |||
| 368eac7616 | |||
| b2c41e2cb4 | |||
| 84ab921291 | |||
| 06f0b9303c | |||
| 465055fc53 | |||
| 40ee0e6834 | |||
| a0ef9c8b32 | |||
| d763965cb8 | |||
| f6e21fbd88 | |||
| 8b4402e4c8 |
@@ -34,6 +34,9 @@ set(PROJECT_INCLUDE_DIRECTORIES
|
|||||||
SHAL/Include/Peripheral/Timer/Reg
|
SHAL/Include/Peripheral/Timer/Reg
|
||||||
SHAL/Include/Peripheral/GPIO
|
SHAL/Include/Peripheral/GPIO
|
||||||
SHAL/Include/Peripheral/GPIO/Reg
|
SHAL/Include/Peripheral/GPIO/Reg
|
||||||
|
SHAL/Include/Peripheral/UART
|
||||||
|
SHAL/Include/Peripheral/UART/Reg
|
||||||
|
SHAL/Include/Peripheral/EXT/
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/SHAL/Include
|
${CMAKE_CURRENT_SOURCE_DIR}/SHAL/Include
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -47,11 +47,6 @@
|
|||||||
*/
|
*/
|
||||||
/* This variable is updated in three ways:
|
/* This variable is updated in three ways:
|
||||||
1) by calling CMSIS function SystemCoreClockUpdate()
|
1) by calling CMSIS function SystemCoreClockUpdate()
|
||||||
3) by calling HAL API function HAL_RCC_GetHCLKFreq()
|
|
||||||
3) by calling HAL API function HAL_RCC_ClockConfig()
|
|
||||||
Note: If you use this function to configure the system clock; then there
|
|
||||||
is no need to call the 2 first functions listed above, since SystemCoreClock
|
|
||||||
variable is updated automatically.
|
|
||||||
*/
|
*/
|
||||||
extern uint32_t SystemCoreClock; /*!< System Clock Frequency (Core Clock) */
|
extern uint32_t SystemCoreClock; /*!< System Clock Frequency (Core Clock) */
|
||||||
extern const uint8_t AHBPrescTable[16]; /*!< AHB prescalers table values */
|
extern const uint8_t AHBPrescTable[16]; /*!< AHB prescalers table values */
|
||||||
|
|||||||
@@ -13,20 +13,9 @@
|
|||||||
|
|
||||||
//Universal structs and defines ---------------------------
|
//Universal structs and defines ---------------------------
|
||||||
|
|
||||||
struct SHAL_Peripheral {
|
|
||||||
void* registers;
|
|
||||||
unsigned long global_offset;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SHAL_Peripheral_Register {
|
|
||||||
volatile uint32_t* reg;
|
|
||||||
unsigned long offset;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SHAL_EXTIO_Register{
|
|
||||||
volatile uint32_t* EXT_ICR;
|
|
||||||
unsigned long mask;
|
|
||||||
};
|
|
||||||
|
|
||||||
//---------------------------------------------------------
|
//---------------------------------------------------------
|
||||||
|
|
||||||
@@ -55,7 +44,6 @@ struct SHAL_EXTIO_Register{
|
|||||||
#include "stm32f071xb.h"
|
#include "stm32f071xb.h"
|
||||||
#elif defined(STM32F072xB)
|
#elif defined(STM32F072xB)
|
||||||
#include "stm32f072xb.h"
|
#include "stm32f072xb.h"
|
||||||
#include "SHAL_TIM_REG_F072xB.h"
|
|
||||||
#elif defined(STM32F078xx)
|
#elif defined(STM32F078xx)
|
||||||
#include "stm32f078xx.h"
|
#include "stm32f078xx.h"
|
||||||
#elif defined(STM32F091xC)
|
#elif defined(STM32F091xC)
|
||||||
|
|||||||
41
SHAL/Include/Peripheral/EXT/SHAL_EXTI_CALLBACK.h
Normal file
41
SHAL/Include/Peripheral/EXT/SHAL_EXTI_CALLBACK.h
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* @file SHAL_TIM.h
|
||||||
|
* @author Luca Lizaranzu
|
||||||
|
* @brief Callbacks for external interrupts
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SHAL_EXTI_CALLBACK_H
|
||||||
|
#define SHAL_EXTI_CALLBACK_H
|
||||||
|
|
||||||
|
#include "SHAL_CORE.h"
|
||||||
|
#include "SHAL_GPIO_REG.h"
|
||||||
|
|
||||||
|
#define DEFINE_EXTI_IRQ(EXTI_Channel) \
|
||||||
|
extern "C" void EXTI##EXTI_Channel##_IRQHandler(void) { \
|
||||||
|
if (EXTI->PR & (1 << EXTI_Channel)) { \
|
||||||
|
EXTI->PR |= (1 << EXTI_Channel); /*clear flag */ \
|
||||||
|
auto cb = EXTI_callbacks[EXTI_Channel]; \
|
||||||
|
if (cb) cb(); \
|
||||||
|
}; \
|
||||||
|
};
|
||||||
|
|
||||||
|
#define DEFINE_MULTI_EXTI_IRQ(EXTI_Channel_Min, EXTI_Channel_Max) \
|
||||||
|
extern "C" void EXTI##EXTI_Channel_Min##_##EXTI_Channel_Max##_IRQHandler(void) { \
|
||||||
|
for(uint8_t line = EXTI_Channel_Min; line <= EXTI_Channel_Max; line++){ \
|
||||||
|
if (EXTI->PR & (1 << line)) { \
|
||||||
|
EXTI->PR |= (1 << line); /*clear flag */ \
|
||||||
|
auto cb = EXTI_callbacks[line]; \
|
||||||
|
if (cb) cb(); \
|
||||||
|
}; \
|
||||||
|
} \
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef void (*EXTICallback)(); //Typedef for callback function
|
||||||
|
|
||||||
|
[[maybe_unused]] static EXTICallback EXTI_callbacks[NUM_EXTI_LINES] = {nullptr}; //Timer IRQ Callback table
|
||||||
|
|
||||||
|
void registerEXTICallback(GPIO_Key key, EXTICallback callback);
|
||||||
|
|
||||||
|
#endif //SHAL_EXTI_CALLBACK_H
|
||||||
47
SHAL/Include/Peripheral/GPIO/Reg/SHAL_GPIO_REG.h
Normal file
47
SHAL/Include/Peripheral/GPIO/Reg/SHAL_GPIO_REG.h
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
//
|
||||||
|
// Created by Luca on 9/6/2025.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef SHAL_GPIO_REG_H
|
||||||
|
#define SHAL_GPIO_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_GPIO_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 //SHMINGO_HAL_SHAL_GPIO_REG_H
|
||||||
@@ -2,16 +2,17 @@
|
|||||||
// Created by Luca on 8/29/2025.
|
// Created by Luca on 8/29/2025.
|
||||||
//
|
//
|
||||||
|
|
||||||
#ifndef SHMINGO_HAL_SHAL_GPIO_REG_F072XB_H
|
#ifndef SHAL_GPIO_REG_F072XB_H
|
||||||
#define SHMINGO_HAL_SHAL_GPIO_REG_F072XB_H
|
#define SHAL_GPIO_REG_F072XB_H
|
||||||
|
|
||||||
#include <stm32f072xb.h>
|
#include <stm32f072xb.h>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
#include "SHAL_CORE.h"
|
#include "SHAL_GPIO_TYPES.h"
|
||||||
|
|
||||||
#define AVAILABLE_PORTS 3
|
#define AVAILABLE_PORTS 3
|
||||||
#define PINS_PER_PORT 16
|
#define PINS_PER_PORT 16
|
||||||
|
#define NUM_EXTI_LINES 16
|
||||||
|
|
||||||
#define AVAILABLE_GPIO \
|
#define AVAILABLE_GPIO \
|
||||||
X(A0) X(A1) X(A2) X(A3) X(A4) X(A5) X(A6) X(A7) X(A8) X(A9) X(A10) X(A11) X(A12) X(A13) X(A14) X(A15) \
|
X(A0) X(A1) X(A2) X(A3) X(A4) X(A5) X(A6) X(A7) X(A8) X(A9) X(A10) X(A11) X(A12) X(A13) X(A14) X(A15) \
|
||||||
@@ -29,7 +30,8 @@ enum class GPIO_Key : uint8_t {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
constexpr SHAL_Peripheral getGPIORegister(const GPIO_Key g){
|
|
||||||
|
constexpr SHAL_GPIO_Peripheral getGPIORegister(const GPIO_Key g){
|
||||||
switch(g) {
|
switch(g) {
|
||||||
case GPIO_Key::A0: return {GPIOA,0};
|
case GPIO_Key::A0: return {GPIOA,0};
|
||||||
case GPIO_Key::A1: return {GPIOA,1};
|
case GPIO_Key::A1: return {GPIOA,1};
|
||||||
@@ -82,66 +84,66 @@ constexpr SHAL_Peripheral getGPIORegister(const GPIO_Key g){
|
|||||||
case GPIO_Key::INVALID:
|
case GPIO_Key::INVALID:
|
||||||
case GPIO_Key::NUM_GPIO:
|
case GPIO_Key::NUM_GPIO:
|
||||||
assert(false);
|
assert(false);
|
||||||
return SHAL_Peripheral(nullptr,0); //Unreachable
|
return SHAL_GPIO_Peripheral(nullptr,0); //Unreachable
|
||||||
}
|
}
|
||||||
__builtin_unreachable();
|
__builtin_unreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr SHAL_EXTIO_Register getGPIOEXTICR(const GPIO_Key g){
|
constexpr SHAL_EXTIO_Register getGPIOEXTICR(const GPIO_Key g){
|
||||||
switch(g) {
|
switch(g) {
|
||||||
case GPIO_Key::A0: return {&SYSCFG->EXTICR[0],SYSCFG_EXTICR1_EXTI0_PA};
|
case GPIO_Key::A0: return {&SYSCFG->EXTICR[0],SYSCFG_EXTICR1_EXTI0_PA,EXTI0_1_IRQn};
|
||||||
case GPIO_Key::A1: return {&SYSCFG->EXTICR[0],SYSCFG_EXTICR1_EXTI1_PA};
|
case GPIO_Key::A1: return {&SYSCFG->EXTICR[0],SYSCFG_EXTICR1_EXTI1_PA,EXTI0_1_IRQn};
|
||||||
case GPIO_Key::A2: return {&SYSCFG->EXTICR[0],SYSCFG_EXTICR1_EXTI2_PA};
|
case GPIO_Key::A2: return {&SYSCFG->EXTICR[0],SYSCFG_EXTICR1_EXTI2_PA,EXTI2_3_IRQn};
|
||||||
case GPIO_Key::A3: return {&SYSCFG->EXTICR[0],SYSCFG_EXTICR1_EXTI3_PA};
|
case GPIO_Key::A3: return {&SYSCFG->EXTICR[0],SYSCFG_EXTICR1_EXTI3_PA,EXTI2_3_IRQn};
|
||||||
case GPIO_Key::A4: return {&SYSCFG->EXTICR[1],SYSCFG_EXTICR2_EXTI4_PA};
|
case GPIO_Key::A4: return {&SYSCFG->EXTICR[1],SYSCFG_EXTICR2_EXTI4_PA,EXTI4_15_IRQn};
|
||||||
case GPIO_Key::A5: return {&SYSCFG->EXTICR[1],SYSCFG_EXTICR2_EXTI5_PA};
|
case GPIO_Key::A5: return {&SYSCFG->EXTICR[1],SYSCFG_EXTICR2_EXTI5_PA,EXTI4_15_IRQn};
|
||||||
case GPIO_Key::A6: return {&SYSCFG->EXTICR[1],SYSCFG_EXTICR2_EXTI6_PA};
|
case GPIO_Key::A6: return {&SYSCFG->EXTICR[1],SYSCFG_EXTICR2_EXTI6_PA,EXTI4_15_IRQn};
|
||||||
case GPIO_Key::A7: return {&SYSCFG->EXTICR[1],SYSCFG_EXTICR2_EXTI7_PA};
|
case GPIO_Key::A7: return {&SYSCFG->EXTICR[1],SYSCFG_EXTICR2_EXTI7_PA,EXTI4_15_IRQn};
|
||||||
case GPIO_Key::A8: return {&SYSCFG->EXTICR[2],SYSCFG_EXTICR3_EXTI8_PA};
|
case GPIO_Key::A8: return {&SYSCFG->EXTICR[2],SYSCFG_EXTICR3_EXTI8_PA,EXTI4_15_IRQn};
|
||||||
case GPIO_Key::A9: return {&SYSCFG->EXTICR[2],SYSCFG_EXTICR3_EXTI9_PA};
|
case GPIO_Key::A9: return {&SYSCFG->EXTICR[2],SYSCFG_EXTICR3_EXTI9_PA,EXTI4_15_IRQn};
|
||||||
case GPIO_Key::A10: return {&SYSCFG->EXTICR[2],SYSCFG_EXTICR3_EXTI10_PA};
|
case GPIO_Key::A10: return {&SYSCFG->EXTICR[2],SYSCFG_EXTICR3_EXTI10_PA,EXTI4_15_IRQn};
|
||||||
case GPIO_Key::A11: return {&SYSCFG->EXTICR[2],SYSCFG_EXTICR3_EXTI11_PA};
|
case GPIO_Key::A11: return {&SYSCFG->EXTICR[2],SYSCFG_EXTICR3_EXTI11_PA,EXTI4_15_IRQn};
|
||||||
case GPIO_Key::A12: return {&SYSCFG->EXTICR[3],SYSCFG_EXTICR4_EXTI12_PA};
|
case GPIO_Key::A12: return {&SYSCFG->EXTICR[3],SYSCFG_EXTICR4_EXTI12_PA,EXTI4_15_IRQn};
|
||||||
case GPIO_Key::A13: return {&SYSCFG->EXTICR[3],SYSCFG_EXTICR4_EXTI13_PA};
|
case GPIO_Key::A13: return {&SYSCFG->EXTICR[3],SYSCFG_EXTICR4_EXTI13_PA,EXTI4_15_IRQn};
|
||||||
case GPIO_Key::A14: return {&SYSCFG->EXTICR[3],SYSCFG_EXTICR4_EXTI14_PA};
|
case GPIO_Key::A14: return {&SYSCFG->EXTICR[3],SYSCFG_EXTICR4_EXTI14_PA,EXTI4_15_IRQn};
|
||||||
case GPIO_Key::A15: return {&SYSCFG->EXTICR[3],SYSCFG_EXTICR4_EXTI15_PA};
|
case GPIO_Key::A15: return {&SYSCFG->EXTICR[3],SYSCFG_EXTICR4_EXTI15_PA,EXTI4_15_IRQn};
|
||||||
case GPIO_Key::B0: return {&SYSCFG->EXTICR[0],SYSCFG_EXTICR1_EXTI0_PB};
|
case GPIO_Key::B0: return {&SYSCFG->EXTICR[0],SYSCFG_EXTICR1_EXTI0_PB,EXTI0_1_IRQn};
|
||||||
case GPIO_Key::B1: return {&SYSCFG->EXTICR[0],SYSCFG_EXTICR1_EXTI1_PB};
|
case GPIO_Key::B1: return {&SYSCFG->EXTICR[0],SYSCFG_EXTICR1_EXTI1_PB,EXTI0_1_IRQn};
|
||||||
case GPIO_Key::B2: return {&SYSCFG->EXTICR[0],SYSCFG_EXTICR1_EXTI2_PB};
|
case GPIO_Key::B2: return {&SYSCFG->EXTICR[0],SYSCFG_EXTICR1_EXTI2_PB,EXTI2_3_IRQn};
|
||||||
case GPIO_Key::B3: return {&SYSCFG->EXTICR[0],SYSCFG_EXTICR1_EXTI3_PB};
|
case GPIO_Key::B3: return {&SYSCFG->EXTICR[0],SYSCFG_EXTICR1_EXTI3_PB,EXTI2_3_IRQn};
|
||||||
case GPIO_Key::B4: return {&SYSCFG->EXTICR[1],SYSCFG_EXTICR2_EXTI4_PB};
|
case GPIO_Key::B4: return {&SYSCFG->EXTICR[1],SYSCFG_EXTICR2_EXTI4_PB,EXTI4_15_IRQn};
|
||||||
case GPIO_Key::B5: return {&SYSCFG->EXTICR[1],SYSCFG_EXTICR2_EXTI5_PB};
|
case GPIO_Key::B5: return {&SYSCFG->EXTICR[1],SYSCFG_EXTICR2_EXTI5_PB,EXTI4_15_IRQn};
|
||||||
case GPIO_Key::B6: return {&SYSCFG->EXTICR[1],SYSCFG_EXTICR2_EXTI6_PB};
|
case GPIO_Key::B6: return {&SYSCFG->EXTICR[1],SYSCFG_EXTICR2_EXTI6_PB,EXTI4_15_IRQn};
|
||||||
case GPIO_Key::B7: return {&SYSCFG->EXTICR[1],SYSCFG_EXTICR2_EXTI7_PB};
|
case GPIO_Key::B7: return {&SYSCFG->EXTICR[1],SYSCFG_EXTICR2_EXTI7_PB,EXTI4_15_IRQn};
|
||||||
case GPIO_Key::B8: return {&SYSCFG->EXTICR[2],SYSCFG_EXTICR3_EXTI8_PB};
|
case GPIO_Key::B8: return {&SYSCFG->EXTICR[2],SYSCFG_EXTICR3_EXTI8_PB,EXTI4_15_IRQn};
|
||||||
case GPIO_Key::B9: return {&SYSCFG->EXTICR[2],SYSCFG_EXTICR3_EXTI9_PB};
|
case GPIO_Key::B9: return {&SYSCFG->EXTICR[2],SYSCFG_EXTICR3_EXTI9_PB,EXTI4_15_IRQn};
|
||||||
case GPIO_Key::B10: return {&SYSCFG->EXTICR[2],SYSCFG_EXTICR3_EXTI10_PB};
|
case GPIO_Key::B10: return {&SYSCFG->EXTICR[2],SYSCFG_EXTICR3_EXTI10_PB,EXTI4_15_IRQn};
|
||||||
case GPIO_Key::B11: return {&SYSCFG->EXTICR[2],SYSCFG_EXTICR3_EXTI11_PB};
|
case GPIO_Key::B11: return {&SYSCFG->EXTICR[2],SYSCFG_EXTICR3_EXTI11_PB,EXTI4_15_IRQn};
|
||||||
case GPIO_Key::B12: return {&SYSCFG->EXTICR[3],SYSCFG_EXTICR4_EXTI12_PB};
|
case GPIO_Key::B12: return {&SYSCFG->EXTICR[3],SYSCFG_EXTICR4_EXTI12_PB,EXTI4_15_IRQn};
|
||||||
case GPIO_Key::B13: return {&SYSCFG->EXTICR[3],SYSCFG_EXTICR4_EXTI13_PB};
|
case GPIO_Key::B13: return {&SYSCFG->EXTICR[3],SYSCFG_EXTICR4_EXTI13_PB,EXTI4_15_IRQn};
|
||||||
case GPIO_Key::B14: return {&SYSCFG->EXTICR[3],SYSCFG_EXTICR4_EXTI14_PB};
|
case GPIO_Key::B14: return {&SYSCFG->EXTICR[3],SYSCFG_EXTICR4_EXTI14_PB,EXTI4_15_IRQn};
|
||||||
case GPIO_Key::B15: return {&SYSCFG->EXTICR[3],SYSCFG_EXTICR4_EXTI15_PB};
|
case GPIO_Key::B15: return {&SYSCFG->EXTICR[3],SYSCFG_EXTICR4_EXTI15_PB,EXTI4_15_IRQn};
|
||||||
case GPIO_Key::C0: return {&SYSCFG->EXTICR[0],SYSCFG_EXTICR1_EXTI0_PC};
|
case GPIO_Key::C0: return {&SYSCFG->EXTICR[0],SYSCFG_EXTICR1_EXTI0_PC,EXTI0_1_IRQn};
|
||||||
case GPIO_Key::C1: return {&SYSCFG->EXTICR[0],SYSCFG_EXTICR1_EXTI1_PC};
|
case GPIO_Key::C1: return {&SYSCFG->EXTICR[0],SYSCFG_EXTICR1_EXTI1_PC,EXTI0_1_IRQn};
|
||||||
case GPIO_Key::C2: return {&SYSCFG->EXTICR[0],SYSCFG_EXTICR1_EXTI2_PC};
|
case GPIO_Key::C2: return {&SYSCFG->EXTICR[0],SYSCFG_EXTICR1_EXTI2_PC,EXTI2_3_IRQn};
|
||||||
case GPIO_Key::C3: return {&SYSCFG->EXTICR[0],SYSCFG_EXTICR1_EXTI3_PC};
|
case GPIO_Key::C3: return {&SYSCFG->EXTICR[0],SYSCFG_EXTICR1_EXTI3_PC,EXTI2_3_IRQn};
|
||||||
case GPIO_Key::C4: return {&SYSCFG->EXTICR[1],SYSCFG_EXTICR2_EXTI4_PC};
|
case GPIO_Key::C4: return {&SYSCFG->EXTICR[1],SYSCFG_EXTICR2_EXTI4_PC,EXTI4_15_IRQn};
|
||||||
case GPIO_Key::C5: return {&SYSCFG->EXTICR[1],SYSCFG_EXTICR2_EXTI5_PC};
|
case GPIO_Key::C5: return {&SYSCFG->EXTICR[1],SYSCFG_EXTICR2_EXTI5_PC,EXTI4_15_IRQn};
|
||||||
case GPIO_Key::C6: return {&SYSCFG->EXTICR[1],SYSCFG_EXTICR2_EXTI6_PC};
|
case GPIO_Key::C6: return {&SYSCFG->EXTICR[1],SYSCFG_EXTICR2_EXTI6_PC,EXTI4_15_IRQn};
|
||||||
case GPIO_Key::C7: return {&SYSCFG->EXTICR[1],SYSCFG_EXTICR2_EXTI7_PC};
|
case GPIO_Key::C7: return {&SYSCFG->EXTICR[1],SYSCFG_EXTICR2_EXTI7_PC,EXTI4_15_IRQn};
|
||||||
case GPIO_Key::C8: return {&SYSCFG->EXTICR[2],SYSCFG_EXTICR3_EXTI8_PC};
|
case GPIO_Key::C8: return {&SYSCFG->EXTICR[2],SYSCFG_EXTICR3_EXTI8_PC,EXTI4_15_IRQn};
|
||||||
case GPIO_Key::C9: return {&SYSCFG->EXTICR[2],SYSCFG_EXTICR3_EXTI9_PC};
|
case GPIO_Key::C9: return {&SYSCFG->EXTICR[2],SYSCFG_EXTICR3_EXTI9_PC,EXTI4_15_IRQn};
|
||||||
case GPIO_Key::C10: return {&SYSCFG->EXTICR[2],SYSCFG_EXTICR3_EXTI10_PC};
|
case GPIO_Key::C10: return {&SYSCFG->EXTICR[2],SYSCFG_EXTICR3_EXTI10_PC,EXTI4_15_IRQn};
|
||||||
case GPIO_Key::C11: return {&SYSCFG->EXTICR[2],SYSCFG_EXTICR3_EXTI11_PC};
|
case GPIO_Key::C11: return {&SYSCFG->EXTICR[2],SYSCFG_EXTICR3_EXTI11_PC,EXTI4_15_IRQn};
|
||||||
case GPIO_Key::C12: return {&SYSCFG->EXTICR[3],SYSCFG_EXTICR4_EXTI12_PC};
|
case GPIO_Key::C12: return {&SYSCFG->EXTICR[3],SYSCFG_EXTICR4_EXTI12_PC,EXTI4_15_IRQn};
|
||||||
case GPIO_Key::C13: return {&SYSCFG->EXTICR[3],SYSCFG_EXTICR4_EXTI13_PC};
|
case GPIO_Key::C13: return {&SYSCFG->EXTICR[3],SYSCFG_EXTICR4_EXTI13_PC,EXTI4_15_IRQn};
|
||||||
case GPIO_Key::C14: return {&SYSCFG->EXTICR[3],SYSCFG_EXTICR4_EXTI14_PC};
|
case GPIO_Key::C14: return {&SYSCFG->EXTICR[3],SYSCFG_EXTICR4_EXTI14_PC,EXTI4_15_IRQn};
|
||||||
case GPIO_Key::C15: return {&SYSCFG->EXTICR[3],SYSCFG_EXTICR4_EXTI15_PC};
|
case GPIO_Key::C15: return {&SYSCFG->EXTICR[3],SYSCFG_EXTICR4_EXTI15_PC,EXTI4_15_IRQn};
|
||||||
|
|
||||||
case GPIO_Key::INVALID:
|
case GPIO_Key::INVALID:
|
||||||
case GPIO_Key::NUM_GPIO:
|
case GPIO_Key::NUM_GPIO:
|
||||||
assert(false);
|
assert(false);
|
||||||
return SHAL_EXTIO_Register(nullptr,0); //Unreachable
|
return SHAL_EXTIO_Register(nullptr,0, EXTI4_15_IRQn); //Unreachable
|
||||||
}
|
}
|
||||||
__builtin_unreachable();
|
__builtin_unreachable();
|
||||||
}
|
}
|
||||||
@@ -207,7 +209,7 @@ constexpr SHAL_Peripheral_Register getGPIORCCEnable(const GPIO_Key g){
|
|||||||
__builtin_unreachable();
|
__builtin_unreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr unsigned int getGPIOPortNumber(const GPIO_Key g){
|
constexpr uint32_t getGPIOPortNumber(const GPIO_Key g){
|
||||||
switch(g) {
|
switch(g) {
|
||||||
case GPIO_Key::A0:
|
case GPIO_Key::A0:
|
||||||
case GPIO_Key::A1:
|
case GPIO_Key::A1:
|
||||||
@@ -268,4 +270,6 @@ constexpr unsigned int getGPIOPortNumber(const GPIO_Key g){
|
|||||||
__builtin_unreachable();
|
__builtin_unreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif //SHMINGO_HAL_SHAL_GPIO_REG_F072XB_H
|
#endif //SHMINGO_HAL_SHAL_GPIO_REG_F072XB_H
|
||||||
|
|||||||
29
SHAL/Include/Peripheral/GPIO/Reg/SHAL_GPIO_TYPES.h
Normal file
29
SHAL/Include/Peripheral/GPIO/Reg/SHAL_GPIO_TYPES.h
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
//
|
||||||
|
// Created by Luca on 9/6/2025.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef SHAL_GPIO_TYPES_H
|
||||||
|
#define SHAL_GPIO_TYPES_H
|
||||||
|
|
||||||
|
#include "SHAL_CORE.h"
|
||||||
|
|
||||||
|
|
||||||
|
struct SHAL_EXTIO_Register{
|
||||||
|
volatile uint32_t* EXT_ICR;
|
||||||
|
uint32_t mask;
|
||||||
|
IRQn_Type IRQN;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SHAL_GPIO_Peripheral {
|
||||||
|
GPIO_TypeDef * reg;
|
||||||
|
unsigned long global_offset;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SHAL_Peripheral_Register {
|
||||||
|
volatile uint32_t* reg;
|
||||||
|
unsigned long offset;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif //SHMINGO_HAL_SHAL_GPIO_TYPES_H
|
||||||
@@ -2,13 +2,16 @@
|
|||||||
// Created by Luca on 8/29/2025.
|
// Created by Luca on 8/29/2025.
|
||||||
//
|
//
|
||||||
|
|
||||||
#ifndef SHMINGO_HAL_SHAL_GPIO_H
|
#ifndef SHAL_GPIO_H
|
||||||
#define SHMINGO_HAL_SHAL_GPIO_H
|
#define SHAL_GPIO_H
|
||||||
|
|
||||||
#include "SHAL_CORE.h"
|
#include "SHAL_GPIO_REG.h"
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include "SHAL_GPIO_REG_F072xB.h"
|
|
||||||
|
#include "SHAL_EXTI_CALLBACK.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
enum class PinMode : uint8_t{
|
enum class PinMode : uint8_t{
|
||||||
INPUT_MODE,
|
INPUT_MODE,
|
||||||
@@ -17,15 +20,20 @@ enum class PinMode : uint8_t{
|
|||||||
ANALOG_MODE,
|
ANALOG_MODE,
|
||||||
INVALID
|
INVALID
|
||||||
};
|
};
|
||||||
|
|
||||||
unsigned long getPinMode(PinMode mode);
|
unsigned long getPinMode(PinMode mode);
|
||||||
|
|
||||||
|
enum class TriggerMode : uint8_t{
|
||||||
|
RISING_EDGE,
|
||||||
|
FALLING_EDGE,
|
||||||
|
RISING_FALLING_EDGE
|
||||||
|
};
|
||||||
|
|
||||||
//Abstraction of GPIO registers
|
//Abstraction of GPIO registers
|
||||||
class GPIO{
|
class GPIO{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
void toggle();
|
void toggle() volatile;
|
||||||
|
|
||||||
//TODO replace stupid offset hack from APB
|
//TODO replace stupid offset hack from APB
|
||||||
void setHigh();
|
void setHigh();
|
||||||
@@ -42,15 +50,21 @@ private:
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//Init GPIO for normal use
|
||||||
#define initGPIO(GPIO_KEY, PIN_MODE) GPIOManager::get(GPIO_KEY, PIN_MODE)
|
#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)
|
||||||
|
|
||||||
//Manages instances of GPIO objects
|
//Manages instances of GPIO objects
|
||||||
class GPIOManager{
|
class GPIOManager{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
static GPIO& get(GPIO_Key, PinMode pinMode);
|
static GPIO& get(GPIO_Key, PinMode pinMode);
|
||||||
|
|
||||||
|
static void getInterruptGPIO(GPIO_Key key, TriggerMode mode, EXTICallback callback);
|
||||||
|
|
||||||
GPIOManager() = delete;
|
GPIOManager() = delete;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -59,4 +73,5 @@ inline static GPIO m_gpios[AVAILABLE_PORTS][PINS_PER_PORT] = {{}};
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif //SHMINGO_HAL_SHAL_GPIO_H
|
#endif //SHMINGO_HAL_SHAL_GPIO_H
|
||||||
|
|||||||
44
SHAL/Include/Peripheral/Timer/Reg/SHAL_TIM_REG.h
Normal file
44
SHAL/Include/Peripheral/Timer/Reg/SHAL_TIM_REG.h
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
//
|
||||||
|
// Created by Luca on 9/7/2025.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef SHMINGO_HAL_SHAL_TIM_REG_H
|
||||||
|
#define SHMINGO_HAL_SHAL_TIM_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_TIM_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 //SHMINGO_HAL_SHAL_TIM_REG_H
|
||||||
@@ -13,6 +13,7 @@
|
|||||||
#include <stm32f072xb.h>
|
#include <stm32f072xb.h>
|
||||||
|
|
||||||
#include "SHAL_CORE.h"
|
#include "SHAL_CORE.h"
|
||||||
|
#include "SHAL_TIM_TYPES.h"
|
||||||
|
|
||||||
enum class Timer_Key : uint8_t { //For STM32F072
|
enum class Timer_Key : uint8_t { //For STM32F072
|
||||||
S_TIM1,
|
S_TIM1,
|
||||||
@@ -30,7 +31,7 @@ enum class Timer_Key : uint8_t { //For STM32F072
|
|||||||
|
|
||||||
|
|
||||||
//Get TIMER_KEY peripheral struct including bus register, enable mask, TIMER_KEY mask
|
//Get TIMER_KEY peripheral struct including bus register, enable mask, TIMER_KEY mask
|
||||||
constexpr SHAL_Peripheral_Register getTimerRCC(Timer_Key t) {
|
constexpr TIM_RCC_Enable getTimerRCC(Timer_Key t) {
|
||||||
switch(t) {
|
switch(t) {
|
||||||
case Timer_Key::S_TIM1: return {&RCC->APB2ENR, RCC_APB2ENR_TIM1EN_Pos};
|
case Timer_Key::S_TIM1: return {&RCC->APB2ENR, RCC_APB2ENR_TIM1EN_Pos};
|
||||||
case Timer_Key::S_TIM2: return {&RCC->APB1ENR, RCC_APB1ENR_TIM2EN_Pos};
|
case Timer_Key::S_TIM2: return {&RCC->APB1ENR, RCC_APB1ENR_TIM2EN_Pos};
|
||||||
|
|||||||
15
SHAL/Include/Peripheral/Timer/Reg/SHAL_TIM_TYPES.h
Normal file
15
SHAL/Include/Peripheral/Timer/Reg/SHAL_TIM_TYPES.h
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
//
|
||||||
|
// Created by Luca on 9/7/2025.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef SHMINGO_HAL_SHAL_TIM_TYPES_H
|
||||||
|
#define SHMINGO_HAL_SHAL_TIM_TYPES_H
|
||||||
|
|
||||||
|
#include "SHAL_CORE.h"
|
||||||
|
|
||||||
|
struct TIM_RCC_Enable{
|
||||||
|
volatile uint32_t* busEnableReg;
|
||||||
|
uint32_t offset;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //SHMINGO_HAL_SHAL_TIM_TYPES_H
|
||||||
@@ -7,10 +7,11 @@
|
|||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef SHMINGO_HAL_SHAL_TIM_CALLBACK_H
|
#ifndef SHAL_TIM_CALLBACK_H
|
||||||
#define SHMINGO_HAL_SHAL_TIM_CALLBACK_H
|
#define SHAL_TIM_CALLBACK_H
|
||||||
|
|
||||||
#include "SHAL/Include/Core/SHAL_CORE.h"
|
#include "SHAL_CORE.h"
|
||||||
|
#include "SHAL_TIM_REG.h"
|
||||||
|
|
||||||
#define DEFINE_TIMER_IRQ(key, irq_handler) \
|
#define DEFINE_TIMER_IRQ(key, irq_handler) \
|
||||||
extern "C" void irq_handler(void) { \
|
extern "C" void irq_handler(void) { \
|
||||||
|
|||||||
50
SHAL/Include/Peripheral/UART/Reg/SHAL_UART_REG.h
Normal file
50
SHAL/Include/Peripheral/UART/Reg/SHAL_UART_REG.h
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
//
|
||||||
|
// Created by Luca on 9/7/2025.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef SHAL_UART_REG_H
|
||||||
|
#define SHAL_UART_REG_H
|
||||||
|
|
||||||
|
//
|
||||||
|
// Created by Luca on 9/6/2025.
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
#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_UART_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 //SHMINGO_HAL_SHAL_UART_REG_H
|
||||||
118
SHAL/Include/Peripheral/UART/Reg/SHAL_UART_REG_F072xB.h
Normal file
118
SHAL/Include/Peripheral/UART/Reg/SHAL_UART_REG_F072xB.h
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
//
|
||||||
|
// Created by Luca on 9/7/2025.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef SHAL_UART_REG_F072XB_H
|
||||||
|
#define SHAL_UART_REG_F072XB_H
|
||||||
|
|
||||||
|
#include <stm32f072xb.h>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
#include "SHAL_UART_TYPES.h"
|
||||||
|
|
||||||
|
#define NUM_USART_LINES 4
|
||||||
|
|
||||||
|
//Valid usart Tx and Rx pairings for STM32F072
|
||||||
|
enum class UART_Pair : uint8_t{
|
||||||
|
//UART1
|
||||||
|
Tx1A9_Rx1A10,
|
||||||
|
Tx1B6_Rx1B7,
|
||||||
|
|
||||||
|
//UART2
|
||||||
|
Tx2A2_Rx2A3,
|
||||||
|
Tx2A14_Rx2A15,
|
||||||
|
|
||||||
|
//UART3
|
||||||
|
Tx3B10_Rx3B11,
|
||||||
|
Tx3C4_Rx3C5,
|
||||||
|
Tx3C10_Rx3C11,
|
||||||
|
|
||||||
|
//UART4
|
||||||
|
Tx4A0_Rx4A1,
|
||||||
|
Tx4C10_Rx4C11,
|
||||||
|
|
||||||
|
NUM_PAIRS,
|
||||||
|
INVALID
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
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::NUM_PAIRS:
|
||||||
|
case UART_Pair::INVALID:
|
||||||
|
assert(false);
|
||||||
|
return {nullptr,GPIO_Key::INVALID,GPIO_Key::INVALID,AF_Mask::AF0,AF_Mask::AF0};
|
||||||
|
}
|
||||||
|
__builtin_unreachable();
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr uint8_t getUARTChannel(const UART_Pair pair){
|
||||||
|
switch(pair){
|
||||||
|
case UART_Pair::Tx1A9_Rx1A10:
|
||||||
|
case UART_Pair::Tx1B6_Rx1B7:
|
||||||
|
return 0;
|
||||||
|
case UART_Pair::Tx2A2_Rx2A3:
|
||||||
|
case UART_Pair::Tx2A14_Rx2A15:
|
||||||
|
return 1;
|
||||||
|
case UART_Pair::Tx3B10_Rx3B11:
|
||||||
|
case UART_Pair::Tx3C4_Rx3C5:
|
||||||
|
case UART_Pair::Tx3C10_Rx3C11:
|
||||||
|
return 2;
|
||||||
|
case UART_Pair::Tx4A0_Rx4A1:
|
||||||
|
case UART_Pair::Tx4C10_Rx4C11:
|
||||||
|
return 3;
|
||||||
|
case UART_Pair::NUM_PAIRS:
|
||||||
|
case UART_Pair::INVALID:
|
||||||
|
assert(false);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
__builtin_unreachable();
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr SHAL_UART_ENABLE_REG getUARTEnableReg(const UART_Pair pair){
|
||||||
|
switch(pair){
|
||||||
|
case UART_Pair::Tx1A9_Rx1A10:
|
||||||
|
case UART_Pair::Tx1B6_Rx1B7:
|
||||||
|
return {&RCC->APB2ENR,RCC_APB2ENR_USART1EN};
|
||||||
|
case UART_Pair::Tx2A2_Rx2A3:
|
||||||
|
case UART_Pair::Tx2A14_Rx2A15:
|
||||||
|
return {&RCC->APB1ENR,RCC_APB1ENR_USART2EN};
|
||||||
|
case UART_Pair::Tx3B10_Rx3B11:
|
||||||
|
case UART_Pair::Tx3C4_Rx3C5:
|
||||||
|
case UART_Pair::Tx3C10_Rx3C11:
|
||||||
|
return {&RCC->APB1ENR,RCC_APB1ENR_USART3EN};
|
||||||
|
case UART_Pair::Tx4A0_Rx4A1:
|
||||||
|
case UART_Pair::Tx4C10_Rx4C11:
|
||||||
|
return {&RCC->APB1ENR,RCC_APB1ENR_USART4EN};
|
||||||
|
case UART_Pair::NUM_PAIRS:
|
||||||
|
case UART_Pair::INVALID:
|
||||||
|
assert(false);
|
||||||
|
return {nullptr, 0};
|
||||||
|
}
|
||||||
|
__builtin_unreachable();
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr uint32_t getAFMask(const AF_Mask 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;
|
||||||
|
}
|
||||||
|
__builtin_unreachable();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //SHMINGO_HAL_SHAL_UART_REG_F072XB_H
|
||||||
37
SHAL/Include/Peripheral/UART/Reg/SHAL_UART_TYPES.h
Normal file
37
SHAL/Include/Peripheral/UART/Reg/SHAL_UART_TYPES.h
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
//
|
||||||
|
// Created by Luca on 9/7/2025.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef SHAL_UART_TYPES_H
|
||||||
|
#define SHAL_UART_TYPES_H
|
||||||
|
|
||||||
|
#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;
|
||||||
|
AF_Mask TxMask;
|
||||||
|
AF_Mask RxMask;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SHAL_UART_ENABLE_REG{
|
||||||
|
volatile uint32_t* reg;
|
||||||
|
uint32_t mask;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //SHMINGO_HAL_SHAL_UART_TYPES_H
|
||||||
57
SHAL/Include/Peripheral/UART/SHAL_UART.h
Normal file
57
SHAL/Include/Peripheral/UART/SHAL_UART.h
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* @file SHAL_TIM.h
|
||||||
|
* @author Luca Lizaranzu
|
||||||
|
* @brief Relating to UART and USART object abstractions
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SHMINGO_HAL_SHAL_UART_H
|
||||||
|
#define SHMINGO_HAL_SHAL_UART_H
|
||||||
|
|
||||||
|
#include "SHAL_UART_REG.h"
|
||||||
|
|
||||||
|
class UART{
|
||||||
|
|
||||||
|
friend class UARTManager;
|
||||||
|
public:
|
||||||
|
|
||||||
|
//begins Tx and Usart TODO either modify this function or add a new one that supports Rx
|
||||||
|
void begin(uint32_t baudRate) volatile;
|
||||||
|
|
||||||
|
//Sends a string
|
||||||
|
void sendString(const char* s) volatile;
|
||||||
|
|
||||||
|
//Sends a char
|
||||||
|
void sendChar(char c) volatile;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
UART() = default; //Initializer for array
|
||||||
|
|
||||||
|
//Creates a UART based on a pair of two valid U(S)ART pins
|
||||||
|
explicit UART(UART_Pair pair);
|
||||||
|
|
||||||
|
UART_Pair m_UARTPair = UART_Pair::INVALID;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#define getUART(uart_pair) UARTManager::get(uart_pair)
|
||||||
|
|
||||||
|
class UARTManager{
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
static UART& get(UART_Pair pair);
|
||||||
|
|
||||||
|
|
||||||
|
UARTManager() = delete;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
inline static UART m_UARTs[NUM_USART_LINES] = {};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //SHMINGO_HAL_SHAL_UART_H
|
||||||
@@ -10,5 +10,6 @@
|
|||||||
|
|
||||||
#include "SHAL_TIM.h"
|
#include "SHAL_TIM.h"
|
||||||
#include "SHAL_GPIO.h"
|
#include "SHAL_GPIO.h"
|
||||||
|
#include "SHAL_UART.h"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
40
SHAL/Src/EXT/SHAL_EXTI_CALLBACK.cpp
Normal file
40
SHAL/Src/EXT/SHAL_EXTI_CALLBACK.cpp
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
//
|
||||||
|
// Created by Luca on 9/3/2025.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "SHAL_EXTI_CALLBACK.h"
|
||||||
|
|
||||||
|
#if defined(STM32F030x6)
|
||||||
|
#elif defined(STM32F030x8)
|
||||||
|
#elif defined(STM32F031x6)
|
||||||
|
#elif defined(STM32F038xx)
|
||||||
|
#elif defined(STM32F042x6)
|
||||||
|
#elif defined(STM32F048xx)
|
||||||
|
#elif defined(STM32F051x8)
|
||||||
|
#elif defined(STM32F058xx)
|
||||||
|
#elif defined(STM32F070x6)
|
||||||
|
#elif defined(STM32F070xB)
|
||||||
|
#elif defined(STM32F071xB)
|
||||||
|
#elif defined(STM32F072xB)
|
||||||
|
|
||||||
|
DEFINE_MULTI_EXTI_IRQ(0,1);
|
||||||
|
DEFINE_MULTI_EXTI_IRQ(2,3);
|
||||||
|
DEFINE_MULTI_EXTI_IRQ(4,15);
|
||||||
|
|
||||||
|
#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
|
||||||
|
|
||||||
|
|
||||||
|
//Link function to EXTI line
|
||||||
|
void registerEXTICallback(GPIO_Key key, EXTICallback callback){
|
||||||
|
EXTI_callbacks[getGPIORegister(key).global_offset] = callback;
|
||||||
|
}
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#include "SHAL_GPIO.h"
|
#include "SHAL_GPIO.h"
|
||||||
|
#include "SHAL_EXTI_CALLBACK.h"
|
||||||
|
|
||||||
unsigned long getPinMode(PinMode mode){
|
unsigned long getPinMode(PinMode mode){
|
||||||
switch(mode){
|
switch(mode){
|
||||||
@@ -31,9 +31,9 @@ GPIO::GPIO() : m_GPIO_KEY(GPIO_Key::INVALID){
|
|||||||
|
|
||||||
GPIO::GPIO(GPIO_Key key, PinMode pinMode) : m_GPIO_KEY(key) {
|
GPIO::GPIO(GPIO_Key key, PinMode pinMode) : m_GPIO_KEY(key) {
|
||||||
|
|
||||||
SHAL_Peripheral gpioPeripheral = getGPIORegister(key);
|
SHAL_GPIO_Peripheral gpioPeripheral = getGPIORegister(key);
|
||||||
|
|
||||||
auto gpioRegister = static_cast<GPIO_TypeDef*>(gpioPeripheral.registers);
|
auto gpioRegister = gpioPeripheral.reg;
|
||||||
unsigned long registerOffset = gpioPeripheral.global_offset;
|
unsigned long registerOffset = gpioPeripheral.global_offset;
|
||||||
|
|
||||||
volatile unsigned long* gpioEnable = getGPIORCCEnable(key).reg;
|
volatile unsigned long* gpioEnable = getGPIORCCEnable(key).reg;
|
||||||
@@ -47,17 +47,17 @@ GPIO::GPIO(GPIO_Key key, PinMode pinMode) : m_GPIO_KEY(key) {
|
|||||||
|
|
||||||
void GPIO::setLow() {
|
void GPIO::setLow() {
|
||||||
auto gpioPeripheral = getGPIORegister(m_GPIO_KEY);
|
auto gpioPeripheral = getGPIORegister(m_GPIO_KEY);
|
||||||
static_cast<GPIO_TypeDef*>(gpioPeripheral.registers)->ODR &= ~(1 << gpioPeripheral.global_offset);
|
gpioPeripheral.reg->ODR &= ~(1 << gpioPeripheral.global_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPIO::setHigh() {
|
void GPIO::setHigh() {
|
||||||
auto gpioPeripheral = getGPIORegister(m_GPIO_KEY);
|
auto gpioPeripheral = getGPIORegister(m_GPIO_KEY);
|
||||||
static_cast<GPIO_TypeDef*>(gpioPeripheral.registers)->ODR |= (1 << gpioPeripheral.global_offset);
|
gpioPeripheral.reg->ODR |= (1 << gpioPeripheral.global_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPIO::toggle() {
|
void GPIO::toggle() volatile {
|
||||||
auto gpioPeripheral = getGPIORegister(m_GPIO_KEY);
|
SHAL_GPIO_Peripheral gpioPeripheral = getGPIORegister(m_GPIO_KEY);
|
||||||
static_cast<GPIO_TypeDef*>(gpioPeripheral.registers)->ODR ^= (1 << gpioPeripheral.global_offset);
|
gpioPeripheral.reg->ODR ^= (1 << gpioPeripheral.global_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -73,3 +73,46 @@ GPIO& GPIOManager::get(GPIO_Key key, PinMode pinMode) {
|
|||||||
|
|
||||||
return m_gpios[gpioPort][gpioPin];
|
return m_gpios[gpioPort][gpioPin];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GPIOManager::getInterruptGPIO(GPIO_Key key, TriggerMode triggerMode, EXTICallback callback) {
|
||||||
|
|
||||||
|
uint32_t gpioPort = getGPIOPortNumber(key);
|
||||||
|
uint32_t 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::INPUT_MODE); //Hardcode input mode for interrupt
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
EXTI->IMR |= (1 << gpioPin); //Enable correct EXTI line
|
||||||
|
|
||||||
|
SHAL_EXTIO_Register EXTILineEnable = getGPIOEXTICR(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){
|
||||||
|
case TriggerMode::RISING_EDGE:
|
||||||
|
rising_mask = 1 << gpioPin;
|
||||||
|
break;
|
||||||
|
case TriggerMode::FALLING_EDGE:
|
||||||
|
falling_mask = 1 << gpioPin;
|
||||||
|
break;
|
||||||
|
case TriggerMode::RISING_FALLING_EDGE:
|
||||||
|
falling_mask = 1 << gpioPin;
|
||||||
|
falling_mask = 1 << gpioPin;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Set triggers
|
||||||
|
EXTI->RTSR |= rising_mask;
|
||||||
|
EXTI->FTSR |= falling_mask;
|
||||||
|
|
||||||
|
//Set callback
|
||||||
|
registerEXTICallback(key,callback);
|
||||||
|
|
||||||
|
__enable_irq(); //Enable IRQ just in case
|
||||||
|
}
|
||||||
@@ -6,8 +6,8 @@
|
|||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
Timer::Timer(Timer_Key t) : TIMER_KEY(t){
|
Timer::Timer(Timer_Key t) : TIMER_KEY(t){
|
||||||
SHAL_Peripheral_Register rcc = getTimerRCC(TIMER_KEY);
|
TIM_RCC_Enable rcc = getTimerRCC(TIMER_KEY);
|
||||||
*rcc.reg |= (1 << rcc.offset);
|
*rcc.busEnableReg |= (1 << rcc.offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
Timer::Timer() : TIMER_KEY(Timer_Key::S_TIM_INVALID){
|
Timer::Timer() : TIMER_KEY(Timer_Key::S_TIM_INVALID){
|
||||||
|
|||||||
82
SHAL/Src/Peripheral/UART/SHAL_UART.cpp
Normal file
82
SHAL/Src/Peripheral/UART/SHAL_UART.cpp
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* @file SHAL_TIM.h
|
||||||
|
* @author Luca Lizaranzu
|
||||||
|
* @brief Related to USART and UART abstractions
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "SHAL_UART.h"
|
||||||
|
#include "SHAL_GPIO.h"
|
||||||
|
|
||||||
|
UART::UART(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
|
||||||
|
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;
|
||||||
|
|
||||||
|
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));
|
||||||
|
|
||||||
|
SHAL_UART_ENABLE_REG pairUARTEnable = getUARTEnableReg(pair); //Register and mask to enable the UART channel
|
||||||
|
|
||||||
|
*pairUARTEnable.reg |= pairUARTEnable.mask; //Enable UART line
|
||||||
|
}
|
||||||
|
|
||||||
|
void UART::begin(uint32_t baudRate) volatile {
|
||||||
|
|
||||||
|
USART_TypeDef* usart = getUARTPair(m_UARTPair).USARTReg;
|
||||||
|
|
||||||
|
usart->CR1 &= ~USART_CR1_UE; //Disable USART
|
||||||
|
|
||||||
|
usart->CR1 = 0; //Clear USART config
|
||||||
|
|
||||||
|
usart->CR1 = USART_CR1_TE | USART_CR1_RE; //Tx enable and Rx Enable
|
||||||
|
|
||||||
|
usart->BRR = 8000000 / baudRate; //MAKE SURE ANY FUNCTION THAT CHANGES CLOCK UPDATES THIS!
|
||||||
|
|
||||||
|
usart->CR1 |= USART_CR1_UE;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void 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 {
|
||||||
|
|
||||||
|
USART_TypeDef* usart = getUARTPair(m_UARTPair).USARTReg;
|
||||||
|
|
||||||
|
while(!(usart->ISR & USART_ISR_TXE)); //Wait for usart to finish what it's doing
|
||||||
|
|
||||||
|
usart->TDR = c; //Send character
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
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)];
|
||||||
|
}
|
||||||
@@ -91,11 +91,6 @@
|
|||||||
*/
|
*/
|
||||||
/* This variable is updated in three ways:
|
/* This variable is updated in three ways:
|
||||||
1) by calling CMSIS function SystemCoreClockUpdate()
|
1) by calling CMSIS function SystemCoreClockUpdate()
|
||||||
2) by calling HAL API function HAL_RCC_GetHCLKFreq()
|
|
||||||
3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency
|
|
||||||
Note: If you use this function to configure the system clock; then there
|
|
||||||
is no need to call the 2 first functions listed above, since SystemCoreClock
|
|
||||||
variable is updated automatically.
|
|
||||||
*/
|
*/
|
||||||
uint32_t SystemCoreClock = 8000000;
|
uint32_t SystemCoreClock = 8000000;
|
||||||
|
|
||||||
|
|||||||
@@ -2,14 +2,12 @@
|
|||||||
#include "stm32f0xx.h"
|
#include "stm32f0xx.h"
|
||||||
|
|
||||||
|
|
||||||
GPIO* blueLED = nullptr;
|
volatile GPIO* blueLED = nullptr;
|
||||||
GPIO* greenLED = nullptr;
|
volatile GPIO* greenLED = nullptr;
|
||||||
|
volatile UART* uart2;
|
||||||
|
|
||||||
extern "C" void EXTI0_1_IRQHandler(void) {
|
void c3Interrupt(){
|
||||||
if (EXTI->PR & (1 << 0)) { //Check pending flag
|
|
||||||
EXTI->PR |= (1 << 0); //Clear it by writing 1
|
|
||||||
greenLED->toggle();
|
greenLED->toggle();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void tim2Handler(){
|
void tim2Handler(){
|
||||||
@@ -17,7 +15,12 @@ void tim2Handler(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
RCC->AHBENR |= RCC_AHBENR_GPIOBEN;
|
|
||||||
|
uart2 = &getUART(UART_Pair::Tx2A2_Rx2A3);
|
||||||
|
|
||||||
|
uart2->begin(115200);
|
||||||
|
|
||||||
|
useGPIOAsInterrupt(GPIO_Key::C3,TriggerMode::RISING_EDGE,c3Interrupt);
|
||||||
|
|
||||||
Timer timer2 = getTimer(Timer_Key::S_TIM2);
|
Timer timer2 = getTimer(Timer_Key::S_TIM2);
|
||||||
|
|
||||||
@@ -29,18 +32,6 @@ int main() {
|
|||||||
timer2.setCallbackFunc(tim2Handler);
|
timer2.setCallbackFunc(tim2Handler);
|
||||||
timer2.start();
|
timer2.start();
|
||||||
|
|
||||||
RCC->APB2ENR |= RCC_APB2ENR_SYSCFGCOMPEN; //Enable SYSCFG clock (needed for EXTI)
|
|
||||||
|
|
||||||
SYSCFG->EXTICR[0] &= ~SYSCFG_EXTICR1_EXTI0; //Clear EXTI0 mapping
|
|
||||||
SYSCFG->EXTICR[0] |= SYSCFG_EXTICR1_EXTI0_PB; //Map PA0 -> EXTI0
|
|
||||||
|
|
||||||
EXTI->IMR |= (1 << 0); //Unmask EXTI0
|
|
||||||
EXTI->RTSR |= (1 << 0); //Trigger on rising edge
|
|
||||||
|
|
||||||
NVIC_EnableIRQ(EXTI0_1_IRQn); //EXTI lines 0 and 1 share an IRQ vector
|
|
||||||
|
|
||||||
__enable_irq();
|
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
__WFI();
|
__WFI();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user