mirror of
https://github.com/DarkFlippers/unleashed-firmware
synced 2024-12-26 20:53:07 +00:00
302 lines
13 KiB
C
302 lines
13 KiB
C
#include <furi_hal_bus.h>
|
|
#include <furi.h>
|
|
|
|
#include <stm32wbxx_ll_bus.h>
|
|
|
|
/* Bus bitmask definitions */
|
|
#define FURI_HAL_BUS_IGNORE (0x0U)
|
|
|
|
#define FURI_HAL_BUS_AHB1_GRP1 \
|
|
(LL_AHB1_GRP1_PERIPH_DMA1 | LL_AHB1_GRP1_PERIPH_DMA2 | LL_AHB1_GRP1_PERIPH_DMAMUX1 | \
|
|
LL_AHB1_GRP1_PERIPH_CRC | LL_AHB1_GRP1_PERIPH_TSC)
|
|
|
|
#if defined(ADC_SUPPORT_5_MSPS)
|
|
#define FURI_HAL_BUS_AHB2_GRP1 \
|
|
(LL_AHB2_GRP1_PERIPH_GPIOA | LL_AHB2_GRP1_PERIPH_GPIOB | LL_AHB2_GRP1_PERIPH_GPIOC | \
|
|
LL_AHB2_GRP1_PERIPH_GPIOD | LL_AHB2_GRP1_PERIPH_GPIOE | LL_AHB2_GRP1_PERIPH_GPIOH | \
|
|
LL_AHB2_GRP1_PERIPH_ADC | LL_AHB2_GRP1_PERIPH_AES1)
|
|
|
|
#define FURI_HAL_BUS_APB2_GRP1 \
|
|
(LL_APB2_GRP1_PERIPH_TIM1 | LL_APB2_GRP1_PERIPH_SPI1 | LL_APB2_GRP1_PERIPH_USART1 | \
|
|
LL_APB2_GRP1_PERIPH_TIM16 | LL_APB2_GRP1_PERIPH_TIM17 | LL_APB2_GRP1_PERIPH_SAI1)
|
|
#else
|
|
#define FURI_HAL_BUS_AHB2_GRP1 \
|
|
(LL_AHB2_GRP1_PERIPH_GPIOA | LL_AHB2_GRP1_PERIPH_GPIOB | LL_AHB2_GRP1_PERIPH_GPIOC | \
|
|
LL_AHB2_GRP1_PERIPH_GPIOD | LL_AHB2_GRP1_PERIPH_GPIOE | LL_AHB2_GRP1_PERIPH_GPIOH | \
|
|
LL_AHB2_GRP1_PERIPH_AES1)
|
|
|
|
#define FURI_HAL_BUS_APB2_GRP1 \
|
|
(LL_APB2_GRP1_PERIPH_ADC | LL_APB2_GRP1_PERIPH_TIM1 | LL_APB2_GRP1_PERIPH_SPI1 | \
|
|
LL_APB2_GRP1_PERIPH_USART1 | LL_APB2_GRP1_PERIPH_TIM16 | LL_APB2_GRP1_PERIPH_TIM17 | \
|
|
LL_APB2_GRP1_PERIPH_SAI1)
|
|
#endif
|
|
|
|
#define FURI_HAL_BUS_AHB3_GRP1 \
|
|
(LL_AHB3_GRP1_PERIPH_QUADSPI | LL_AHB3_GRP1_PERIPH_PKA | LL_AHB3_GRP1_PERIPH_AES2 | \
|
|
LL_AHB3_GRP1_PERIPH_RNG | LL_AHB3_GRP1_PERIPH_HSEM | LL_AHB3_GRP1_PERIPH_IPCC)
|
|
// LL_AHB3_GRP1_PERIPH_FLASH enabled by default
|
|
|
|
#define FURI_HAL_BUS_APB1_GRP1 \
|
|
(LL_APB1_GRP1_PERIPH_TIM2 | LL_APB1_GRP1_PERIPH_LCD | LL_APB1_GRP1_PERIPH_SPI2 | \
|
|
LL_APB1_GRP1_PERIPH_I2C1 | LL_APB1_GRP1_PERIPH_I2C3 | LL_APB1_GRP1_PERIPH_CRS | \
|
|
LL_APB1_GRP1_PERIPH_USB | LL_APB1_GRP1_PERIPH_LPTIM1)
|
|
|
|
#define FURI_HAL_BUS_APB1_GRP2 (LL_APB1_GRP2_PERIPH_LPUART1 | LL_APB1_GRP2_PERIPH_LPTIM2)
|
|
#define FURI_HAL_BUS_APB3_GRP1 (LL_APB3_GRP1_PERIPH_RF)
|
|
|
|
/* Test macro definitions */
|
|
#define FURI_HAL_BUS_IS_ALL_CLEAR(reg, value) (READ_BIT((reg), (value)) == 0UL)
|
|
#define FURI_HAL_BUS_IS_ALL_SET(reg, value) (READ_BIT((reg), (value)) == (value))
|
|
|
|
#define FURI_HAL_BUS_IS_CLOCK_ENABLED(bus, value, ...) \
|
|
(FURI_HAL_BUS_IS_ALL_SET(RCC->bus##ENR##__VA_ARGS__, (value)))
|
|
#define FURI_HAL_BUS_IS_CLOCK_DISABLED(bus, value, ...) \
|
|
(FURI_HAL_BUS_IS_ALL_CLEAR(RCC->bus##ENR##__VA_ARGS__, (value)))
|
|
|
|
#define FURI_HAL_BUS_IS_RESET_ASSERTED(bus, value, ...) \
|
|
(FURI_HAL_BUS_IS_ALL_SET(RCC->bus##RSTR##__VA_ARGS__, (value)))
|
|
#define FURI_HAL_BUS_IS_RESET_DEASSERTED(bus, value, ...) \
|
|
(FURI_HAL_BUS_IS_ALL_CLEAR(RCC->bus##RSTR##__VA_ARGS__, (value)))
|
|
|
|
#define FURI_HAL_BUS_IS_PERIPH_ENABLED(bus, value, ...) \
|
|
(FURI_HAL_BUS_IS_RESET_DEASSERTED(bus, (value), __VA_ARGS__) && \
|
|
FURI_HAL_BUS_IS_CLOCK_ENABLED(bus, (value), __VA_ARGS__))
|
|
|
|
#define FURI_HAL_BUS_IS_PERIPH_DISABLED(bus, value, ...) \
|
|
(FURI_HAL_BUS_IS_CLOCK_DISABLED(bus, (value), __VA_ARGS__) && \
|
|
FURI_HAL_BUS_IS_RESET_ASSERTED(bus, (value), __VA_ARGS__))
|
|
|
|
/* Control macro definitions */
|
|
#define FURI_HAL_BUS_RESET_ASSERT(bus, value, grp) LL_##bus##_GRP##grp##_ForceReset(value)
|
|
#define FURI_HAL_BUS_RESET_DEASSERT(bus, value, grp) LL_##bus##_GRP##grp##_ReleaseReset(value)
|
|
|
|
#define FURI_HAL_BUS_CLOCK_ENABLE(bus, value, grp) LL_##bus##_GRP##grp##_EnableClock(value)
|
|
#define FURI_HAL_BUS_CLOCK_DISABLE(bus, value, grp) LL_##bus##_GRP##grp##_DisableClock(value)
|
|
|
|
#define FURI_HAL_BUS_PERIPH_ENABLE(bus, value, grp) \
|
|
FURI_HAL_BUS_CLOCK_ENABLE(bus, value, grp); \
|
|
FURI_HAL_BUS_RESET_DEASSERT(bus, value, grp)
|
|
|
|
#define FURI_HAL_BUS_PERIPH_DISABLE(bus, value, grp) \
|
|
FURI_HAL_BUS_RESET_ASSERT(bus, value, grp); \
|
|
FURI_HAL_BUS_CLOCK_DISABLE(bus, value, grp)
|
|
|
|
#define FURI_HAL_BUS_PERIPH_RESET(bus, value, grp) \
|
|
FURI_HAL_BUS_RESET_ASSERT(bus, value, grp); \
|
|
FURI_HAL_BUS_RESET_DEASSERT(bus, value, grp)
|
|
|
|
static const uint32_t furi_hal_bus[] = {
|
|
[FuriHalBusAHB1_GRP1] = FURI_HAL_BUS_IGNORE,
|
|
[FuriHalBusDMA1] = LL_AHB1_GRP1_PERIPH_DMA1,
|
|
[FuriHalBusDMA2] = LL_AHB1_GRP1_PERIPH_DMA2,
|
|
[FuriHalBusDMAMUX1] = LL_AHB1_GRP1_PERIPH_DMAMUX1,
|
|
[FuriHalBusCRC] = LL_AHB1_GRP1_PERIPH_CRC,
|
|
[FuriHalBusTSC] = LL_AHB1_GRP1_PERIPH_TSC,
|
|
|
|
[FuriHalBusAHB2_GRP1] = FURI_HAL_BUS_IGNORE,
|
|
[FuriHalBusGPIOA] = LL_AHB2_GRP1_PERIPH_GPIOA,
|
|
[FuriHalBusGPIOB] = LL_AHB2_GRP1_PERIPH_GPIOB,
|
|
[FuriHalBusGPIOC] = LL_AHB2_GRP1_PERIPH_GPIOC,
|
|
[FuriHalBusGPIOD] = LL_AHB2_GRP1_PERIPH_GPIOD,
|
|
[FuriHalBusGPIOE] = LL_AHB2_GRP1_PERIPH_GPIOE,
|
|
[FuriHalBusGPIOH] = LL_AHB2_GRP1_PERIPH_GPIOH,
|
|
#if defined(ADC_SUPPORT_5_MSPS)
|
|
[FuriHalBusADC] = LL_AHB2_GRP1_PERIPH_ADC,
|
|
#endif
|
|
[FuriHalBusAES1] = LL_AHB2_GRP1_PERIPH_AES1,
|
|
|
|
[FuriHalBusAHB3_GRP1] = FURI_HAL_BUS_IGNORE,
|
|
[FuriHalBusQUADSPI] = LL_AHB3_GRP1_PERIPH_QUADSPI,
|
|
[FuriHalBusPKA] = LL_AHB3_GRP1_PERIPH_PKA,
|
|
[FuriHalBusAES2] = LL_AHB3_GRP1_PERIPH_AES2,
|
|
[FuriHalBusRNG] = LL_AHB3_GRP1_PERIPH_RNG,
|
|
[FuriHalBusHSEM] = LL_AHB3_GRP1_PERIPH_HSEM,
|
|
[FuriHalBusIPCC] = LL_AHB3_GRP1_PERIPH_IPCC,
|
|
[FuriHalBusFLASH] = LL_AHB3_GRP1_PERIPH_FLASH,
|
|
|
|
[FuriHalBusAPB1_GRP1] = FURI_HAL_BUS_APB1_GRP1,
|
|
[FuriHalBusTIM2] = LL_APB1_GRP1_PERIPH_TIM2,
|
|
[FuriHalBusLCD] = LL_APB1_GRP1_PERIPH_LCD,
|
|
[FuriHalBusSPI2] = LL_APB1_GRP1_PERIPH_SPI2,
|
|
[FuriHalBusI2C1] = LL_APB1_GRP1_PERIPH_I2C1,
|
|
[FuriHalBusI2C3] = LL_APB1_GRP1_PERIPH_I2C3,
|
|
[FuriHalBusCRS] = LL_APB1_GRP1_PERIPH_CRS,
|
|
[FuriHalBusUSB] = LL_APB1_GRP1_PERIPH_USB,
|
|
[FuriHalBusLPTIM1] = LL_APB1_GRP1_PERIPH_LPTIM1,
|
|
|
|
[FuriHalBusAPB1_GRP2] = FURI_HAL_BUS_APB1_GRP2,
|
|
[FuriHalBusLPUART1] = LL_APB1_GRP2_PERIPH_LPUART1,
|
|
[FuriHalBusLPTIM2] = LL_APB1_GRP2_PERIPH_LPTIM2,
|
|
|
|
[FuriHalBusAPB2_GRP1] = FURI_HAL_BUS_APB2_GRP1,
|
|
#if defined(ADC_SUPPORT_2_5_MSPS)
|
|
[FuriHalBusADC] = LL_APB2_GRP1_PERIPH_ADC,
|
|
#endif
|
|
[FuriHalBusTIM1] = LL_APB2_GRP1_PERIPH_TIM1,
|
|
[FuriHalBusSPI1] = LL_APB2_GRP1_PERIPH_SPI1,
|
|
[FuriHalBusUSART1] = LL_APB2_GRP1_PERIPH_USART1,
|
|
[FuriHalBusTIM16] = LL_APB2_GRP1_PERIPH_TIM16,
|
|
[FuriHalBusTIM17] = LL_APB2_GRP1_PERIPH_TIM17,
|
|
[FuriHalBusSAI1] = LL_APB2_GRP1_PERIPH_SAI1,
|
|
|
|
[FuriHalBusAPB3_GRP1] = FURI_HAL_BUS_IGNORE, // APB3_GRP1 clocking cannot be changed
|
|
[FuriHalBusRF] = LL_APB3_GRP1_PERIPH_RF,
|
|
};
|
|
|
|
void furi_hal_bus_init_early() {
|
|
FURI_CRITICAL_ENTER();
|
|
|
|
// FURI_HAL_BUS_PERIPH_DISABLE(AHB1, FURI_HAL_BUS_AHB1_GRP1, 1);
|
|
// FURI_HAL_BUS_PERIPH_DISABLE(AHB2, FURI_HAL_BUS_AHB2_GRP1, 1);
|
|
// FURI_HAL_BUS_PERIPH_DISABLE(AHB3, FURI_HAL_BUS_AHB3_GRP1, 1);
|
|
FURI_HAL_BUS_PERIPH_DISABLE(APB1, FURI_HAL_BUS_APB1_GRP1, 1);
|
|
FURI_HAL_BUS_PERIPH_DISABLE(APB1, FURI_HAL_BUS_APB1_GRP2, 2);
|
|
FURI_HAL_BUS_PERIPH_DISABLE(APB2, FURI_HAL_BUS_APB2_GRP1, 1);
|
|
|
|
FURI_HAL_BUS_RESET_ASSERT(APB3, FURI_HAL_BUS_APB3_GRP1, 1);
|
|
|
|
FURI_CRITICAL_EXIT();
|
|
}
|
|
|
|
void furi_hal_bus_deinit_early() {
|
|
FURI_CRITICAL_ENTER();
|
|
|
|
// FURI_HAL_BUS_PERIPH_ENABLE(AHB1, FURI_HAL_BUS_AHB1_GRP1, 1);
|
|
// FURI_HAL_BUS_PERIPH_ENABLE(AHB2, FURI_HAL_BUS_AHB2_GRP1, 1);
|
|
// FURI_HAL_BUS_PERIPH_ENABLE(AHB3, FURI_HAL_BUS_AHB3_GRP1, 1);
|
|
FURI_HAL_BUS_PERIPH_ENABLE(APB1, FURI_HAL_BUS_APB1_GRP1, 1);
|
|
FURI_HAL_BUS_PERIPH_ENABLE(APB1, FURI_HAL_BUS_APB1_GRP2, 2);
|
|
FURI_HAL_BUS_PERIPH_ENABLE(APB2, FURI_HAL_BUS_APB2_GRP1, 1);
|
|
|
|
FURI_HAL_BUS_RESET_DEASSERT(APB3, FURI_HAL_BUS_APB3_GRP1, 1);
|
|
|
|
FURI_CRITICAL_EXIT();
|
|
}
|
|
|
|
void furi_hal_bus_enable(FuriHalBus bus) {
|
|
furi_check(bus < FuriHalBusMAX);
|
|
const uint32_t value = furi_hal_bus[bus];
|
|
if(!value) {
|
|
return;
|
|
}
|
|
|
|
FURI_CRITICAL_ENTER();
|
|
if(bus < FuriHalBusAHB2_GRP1) {
|
|
// furi_check(FURI_HAL_BUS_IS_PERIPH_DISABLED(AHB1, value));
|
|
FURI_HAL_BUS_PERIPH_ENABLE(AHB1, value, 1);
|
|
} else if(bus < FuriHalBusAHB3_GRP1) {
|
|
// furi_check(FURI_HAL_BUS_IS_PERIPH_DISABLED(AHB2, value));
|
|
FURI_HAL_BUS_PERIPH_ENABLE(AHB2, value, 1);
|
|
} else if(bus < FuriHalBusAPB1_GRP1) {
|
|
// furi_check(FURI_HAL_BUS_IS_PERIPH_DISABLED(AHB3, value));
|
|
FURI_HAL_BUS_PERIPH_ENABLE(AHB3, value, 1);
|
|
} else if(bus < FuriHalBusAPB1_GRP2) {
|
|
furi_check(FURI_HAL_BUS_IS_PERIPH_DISABLED(APB1, value, 1));
|
|
FURI_HAL_BUS_PERIPH_ENABLE(APB1, value, 1);
|
|
} else if(bus < FuriHalBusAPB2_GRP1) {
|
|
furi_check(FURI_HAL_BUS_IS_PERIPH_DISABLED(APB1, value, 2));
|
|
FURI_HAL_BUS_PERIPH_ENABLE(APB1, value, 2);
|
|
} else if(bus < FuriHalBusAPB3_GRP1) {
|
|
furi_check(FURI_HAL_BUS_IS_PERIPH_DISABLED(APB2, value));
|
|
FURI_HAL_BUS_PERIPH_ENABLE(APB2, value, 1);
|
|
} else {
|
|
furi_check(FURI_HAL_BUS_IS_RESET_ASSERTED(APB3, value));
|
|
FURI_HAL_BUS_RESET_DEASSERT(APB3, FURI_HAL_BUS_APB3_GRP1, 1);
|
|
}
|
|
FURI_CRITICAL_EXIT();
|
|
}
|
|
|
|
void furi_hal_bus_reset(FuriHalBus bus) {
|
|
furi_check(bus < FuriHalBusMAX);
|
|
const uint32_t value = furi_hal_bus[bus];
|
|
if(!value) {
|
|
return;
|
|
}
|
|
|
|
FURI_CRITICAL_ENTER();
|
|
if(bus < FuriHalBusAHB2_GRP1) {
|
|
// furi_check(FURI_HAL_BUS_IS_PERIPH_ENABLED(AHB1, value));
|
|
FURI_HAL_BUS_PERIPH_RESET(AHB1, value, 1);
|
|
} else if(bus < FuriHalBusAHB3_GRP1) {
|
|
// furi_check(FURI_HAL_BUS_IS_PERIPH_ENABLED(AHB2, value));
|
|
FURI_HAL_BUS_PERIPH_RESET(AHB2, value, 1);
|
|
} else if(bus < FuriHalBusAPB1_GRP1) {
|
|
// furi_check(FURI_HAL_BUS_IS_PERIPH_ENABLED(AHB3, value));
|
|
FURI_HAL_BUS_PERIPH_RESET(AHB3, value, 1);
|
|
} else if(bus < FuriHalBusAPB1_GRP2) {
|
|
furi_check(FURI_HAL_BUS_IS_PERIPH_ENABLED(APB1, value, 1));
|
|
FURI_HAL_BUS_PERIPH_RESET(APB1, value, 1);
|
|
} else if(bus < FuriHalBusAPB2_GRP1) {
|
|
furi_check(FURI_HAL_BUS_IS_PERIPH_ENABLED(APB1, value, 2));
|
|
FURI_HAL_BUS_PERIPH_RESET(APB1, value, 2);
|
|
} else if(bus < FuriHalBusAPB3_GRP1) {
|
|
furi_check(FURI_HAL_BUS_IS_PERIPH_ENABLED(APB2, value));
|
|
FURI_HAL_BUS_PERIPH_RESET(APB2, value, 1);
|
|
} else {
|
|
furi_check(FURI_HAL_BUS_IS_RESET_DEASSERTED(APB3, value));
|
|
FURI_HAL_BUS_PERIPH_RESET(APB3, value, 1);
|
|
}
|
|
FURI_CRITICAL_EXIT();
|
|
}
|
|
|
|
void furi_hal_bus_disable(FuriHalBus bus) {
|
|
furi_check(bus < FuriHalBusMAX);
|
|
const uint32_t value = furi_hal_bus[bus];
|
|
if(!value) {
|
|
return;
|
|
}
|
|
|
|
FURI_CRITICAL_ENTER();
|
|
if(bus < FuriHalBusAHB2_GRP1) {
|
|
// furi_check(FURI_HAL_BUS_IS_PERIPH_ENABLED(AHB1, value));
|
|
FURI_HAL_BUS_PERIPH_DISABLE(AHB1, value, 1);
|
|
} else if(bus < FuriHalBusAHB3_GRP1) {
|
|
// furi_check(FURI_HAL_BUS_IS_PERIPH_ENABLED(AHB2, value));
|
|
FURI_HAL_BUS_PERIPH_DISABLE(AHB2, value, 1);
|
|
} else if(bus < FuriHalBusAPB1_GRP1) {
|
|
// furi_check(FURI_HAL_BUS_IS_PERIPH_ENABLED(AHB3, value));
|
|
FURI_HAL_BUS_PERIPH_DISABLE(AHB3, value, 1);
|
|
} else if(bus < FuriHalBusAPB1_GRP2) {
|
|
furi_check(FURI_HAL_BUS_IS_PERIPH_ENABLED(APB1, value, 1));
|
|
FURI_HAL_BUS_PERIPH_DISABLE(APB1, value, 1);
|
|
} else if(bus < FuriHalBusAPB2_GRP1) {
|
|
furi_check(FURI_HAL_BUS_IS_PERIPH_ENABLED(APB1, value, 2));
|
|
FURI_HAL_BUS_PERIPH_DISABLE(APB1, value, 2);
|
|
} else if(bus < FuriHalBusAPB3_GRP1) {
|
|
furi_check(FURI_HAL_BUS_IS_PERIPH_ENABLED(APB2, value));
|
|
FURI_HAL_BUS_PERIPH_DISABLE(APB2, value, 1);
|
|
} else {
|
|
furi_check(FURI_HAL_BUS_IS_RESET_DEASSERTED(APB3, value));
|
|
FURI_HAL_BUS_RESET_ASSERT(APB3, FURI_HAL_BUS_APB3_GRP1, 1);
|
|
}
|
|
FURI_CRITICAL_EXIT();
|
|
}
|
|
|
|
bool furi_hal_bus_is_enabled(FuriHalBus bus) {
|
|
furi_check(bus < FuriHalBusMAX);
|
|
const uint32_t value = furi_hal_bus[bus];
|
|
if(value == FURI_HAL_BUS_IGNORE) {
|
|
return true;
|
|
}
|
|
|
|
bool ret = false;
|
|
FURI_CRITICAL_ENTER();
|
|
if(bus < FuriHalBusAHB2_GRP1) {
|
|
ret = FURI_HAL_BUS_IS_PERIPH_ENABLED(AHB1, value);
|
|
} else if(bus < FuriHalBusAHB3_GRP1) {
|
|
ret = FURI_HAL_BUS_IS_PERIPH_ENABLED(AHB2, value);
|
|
} else if(bus < FuriHalBusAPB1_GRP1) {
|
|
ret = FURI_HAL_BUS_IS_PERIPH_ENABLED(AHB3, value);
|
|
} else if(bus < FuriHalBusAPB1_GRP2) {
|
|
ret = FURI_HAL_BUS_IS_PERIPH_ENABLED(APB1, value, 1);
|
|
} else if(bus < FuriHalBusAPB2_GRP1) {
|
|
ret = FURI_HAL_BUS_IS_PERIPH_ENABLED(APB1, value, 2);
|
|
} else if(bus < FuriHalBusAPB3_GRP1) {
|
|
ret = FURI_HAL_BUS_IS_PERIPH_ENABLED(APB2, value);
|
|
} else {
|
|
ret = FURI_HAL_BUS_IS_RESET_DEASSERTED(APB3, value);
|
|
}
|
|
FURI_CRITICAL_EXIT();
|
|
|
|
return ret;
|
|
}
|