FuriHal: replace HAL with LL in RFID Part 1. Drop F6. (#1049)

* FuriHal: new speaker HAL
* FuriHal: drop PWM
* FuriHal: move COMP1 to LL
* FuriHal: move COMP1 to LL backport to F6
* FuriHal: remove missing gpio_rfid_carrier from F6
* FurHal: use LL for system controls in flash HAL
* Drop F6 source tree
* Drop F6 from GitHub workflow
* Tie USE_FULL_ASSERT with APP_UNIT_TESTS
* Speaker: return to old volume calculation
* FreeRTOS: move TCB header to glue

Co-authored-by: DrZlo13 <who.just.the.doctor@gmail.com>
This commit is contained in:
あく
2022-03-23 20:59:20 +03:00
committed by GitHub
parent 3857cd7d5f
commit c4a0847c99
219 changed files with 402 additions and 31552 deletions

View File

@@ -1,21 +0,0 @@
#include <furi_hal.h>
#include <stm32wbxx_ll_utils.h>
void furi_hal_init() {
furi_hal_i2c_init();
furi_hal_light_init();
furi_hal_spi_init();
furi_hal_version_init();
}
void delay(float milliseconds) {
LL_mDelay((uint32_t)milliseconds);
}
void delay_us(float microseconds) {
microseconds = microseconds / 1000;
if(microseconds < 1) {
microseconds = 1;
}
LL_mDelay((uint32_t)microseconds);
}

View File

@@ -1,215 +0,0 @@
#include <furi_hal_gpio.h>
#include <stddef.h>
#include <assert.h>
#define GET_SYSCFG_EXTI_PORT(gpio) \
(((gpio) == (GPIOA)) ? LL_SYSCFG_EXTI_PORTA : \
((gpio) == (GPIOB)) ? LL_SYSCFG_EXTI_PORTB : \
((gpio) == (GPIOC)) ? LL_SYSCFG_EXTI_PORTC : \
((gpio) == (GPIOD)) ? LL_SYSCFG_EXTI_PORTD : \
((gpio) == (GPIOE)) ? LL_SYSCFG_EXTI_PORTE : \
LL_SYSCFG_EXTI_PORTH)
#define GPIO_PIN_MAP(pin, prefix) \
(((pin) == (LL_GPIO_PIN_0)) ? prefix##0 : \
((pin) == (LL_GPIO_PIN_1)) ? prefix##1 : \
((pin) == (LL_GPIO_PIN_2)) ? prefix##2 : \
((pin) == (LL_GPIO_PIN_3)) ? prefix##3 : \
((pin) == (LL_GPIO_PIN_4)) ? prefix##4 : \
((pin) == (LL_GPIO_PIN_5)) ? prefix##5 : \
((pin) == (LL_GPIO_PIN_6)) ? prefix##6 : \
((pin) == (LL_GPIO_PIN_7)) ? prefix##7 : \
((pin) == (LL_GPIO_PIN_8)) ? prefix##8 : \
((pin) == (LL_GPIO_PIN_9)) ? prefix##9 : \
((pin) == (LL_GPIO_PIN_10)) ? prefix##10 : \
((pin) == (LL_GPIO_PIN_11)) ? prefix##11 : \
((pin) == (LL_GPIO_PIN_12)) ? prefix##12 : \
((pin) == (LL_GPIO_PIN_13)) ? prefix##13 : \
((pin) == (LL_GPIO_PIN_14)) ? prefix##14 : \
prefix##15)
#define GET_SYSCFG_EXTI_LINE(pin) GPIO_PIN_MAP(pin, LL_SYSCFG_EXTI_LINE)
#define GET_EXTI_LINE(pin) GPIO_PIN_MAP(pin, LL_EXTI_LINE_)
static volatile GpioInterrupt gpio_interrupt[GPIO_NUMBER];
static uint8_t hal_gpio_get_pin_num(const GpioPin* gpio) {
uint8_t pin_num = 0;
for(pin_num = 0; pin_num < GPIO_NUMBER; pin_num++) {
if(gpio->pin & (1 << pin_num)) break;
}
return pin_num;
}
void hal_gpio_init_simple(const GpioPin* gpio, const GpioMode mode) {
hal_gpio_init(gpio, mode, GpioPullNo, GpioSpeedLow);
}
void hal_gpio_init(
const GpioPin* gpio,
const GpioMode mode,
const GpioPull pull,
const GpioSpeed speed) {
// we cannot set alternate mode in this function
assert(mode != GpioModeAltFunctionPushPull);
assert(mode != GpioModeAltFunctionOpenDrain);
hal_gpio_init_ex(gpio, mode, pull, speed, GpioAltFnUnused);
}
void hal_gpio_init_ex(
const GpioPin* gpio,
const GpioMode mode,
const GpioPull pull,
const GpioSpeed speed,
const GpioAltFn alt_fn) {
uint32_t sys_exti_port = GET_SYSCFG_EXTI_PORT(gpio->port);
uint32_t sys_exti_line = GET_SYSCFG_EXTI_LINE(gpio->pin);
uint32_t exti_line = GET_EXTI_LINE(gpio->pin);
// Configure gpio with interrupts disabled
__disable_irq();
// Set gpio speed
switch(speed) {
case GpioSpeedLow:
LL_GPIO_SetPinSpeed(gpio->port, gpio->pin, LL_GPIO_SPEED_FREQ_LOW);
break;
case GpioSpeedMedium:
LL_GPIO_SetPinSpeed(gpio->port, gpio->pin, LL_GPIO_SPEED_FREQ_MEDIUM);
break;
case GpioSpeedHigh:
LL_GPIO_SetPinSpeed(gpio->port, gpio->pin, LL_GPIO_SPEED_FREQ_HIGH);
break;
case GpioSpeedVeryHigh:
LL_GPIO_SetPinSpeed(gpio->port, gpio->pin, LL_GPIO_SPEED_FREQ_VERY_HIGH);
break;
}
// Set gpio pull mode
switch(pull) {
case GpioPullNo:
LL_GPIO_SetPinPull(gpio->port, gpio->pin, LL_GPIO_PULL_NO);
break;
case GpioPullUp:
LL_GPIO_SetPinPull(gpio->port, gpio->pin, LL_GPIO_PULL_UP);
break;
case GpioPullDown:
LL_GPIO_SetPinPull(gpio->port, gpio->pin, LL_GPIO_PULL_DOWN);
break;
}
// Set gpio mode
if(mode >= GpioModeInterruptRise) {
// Set pin in interrupt mode
LL_GPIO_SetPinMode(gpio->port, gpio->pin, LL_GPIO_MODE_INPUT);
LL_SYSCFG_SetEXTISource(sys_exti_port, sys_exti_line);
if(mode == GpioModeInterruptRise || mode == GpioModeInterruptRiseFall) {
LL_EXTI_EnableIT_0_31(exti_line);
LL_EXTI_EnableRisingTrig_0_31(exti_line);
}
if(mode == GpioModeInterruptFall || mode == GpioModeInterruptRiseFall) {
LL_EXTI_EnableIT_0_31(exti_line);
LL_EXTI_EnableFallingTrig_0_31(exti_line);
}
if(mode == GpioModeEventRise || mode == GpioModeEventRiseFall) {
LL_EXTI_EnableEvent_0_31(exti_line);
LL_EXTI_EnableRisingTrig_0_31(exti_line);
}
if(mode == GpioModeEventFall || mode == GpioModeEventRiseFall) {
LL_EXTI_EnableEvent_0_31(exti_line);
LL_EXTI_EnableFallingTrig_0_31(exti_line);
}
} else {
// Disable interrupts if set
if(LL_SYSCFG_GetEXTISource(sys_exti_line) == sys_exti_port &&
LL_EXTI_IsEnabledIT_0_31(exti_line)) {
LL_EXTI_DisableIT_0_31(exti_line);
LL_EXTI_DisableRisingTrig_0_31(exti_line);
LL_EXTI_DisableFallingTrig_0_31(exti_line);
}
// Prepare alternative part if any
if(mode == GpioModeAltFunctionPushPull || mode == GpioModeAltFunctionOpenDrain) {
// set alternate function
if(hal_gpio_get_pin_num(gpio) < 8) {
LL_GPIO_SetAFPin_0_7(gpio->port, gpio->pin, alt_fn);
} else {
LL_GPIO_SetAFPin_8_15(gpio->port, gpio->pin, alt_fn);
}
}
// Set not interrupt pin modes
switch(mode) {
case GpioModeInput:
LL_GPIO_SetPinMode(gpio->port, gpio->pin, LL_GPIO_MODE_INPUT);
break;
case GpioModeOutputPushPull:
LL_GPIO_SetPinOutputType(gpio->port, gpio->pin, LL_GPIO_OUTPUT_PUSHPULL);
LL_GPIO_SetPinMode(gpio->port, gpio->pin, LL_GPIO_MODE_OUTPUT);
break;
case GpioModeAltFunctionPushPull:
LL_GPIO_SetPinOutputType(gpio->port, gpio->pin, LL_GPIO_OUTPUT_PUSHPULL);
LL_GPIO_SetPinMode(gpio->port, gpio->pin, LL_GPIO_MODE_ALTERNATE);
break;
case GpioModeOutputOpenDrain:
LL_GPIO_SetPinOutputType(gpio->port, gpio->pin, LL_GPIO_OUTPUT_OPENDRAIN);
LL_GPIO_SetPinMode(gpio->port, gpio->pin, LL_GPIO_MODE_OUTPUT);
break;
case GpioModeAltFunctionOpenDrain:
LL_GPIO_SetPinOutputType(gpio->port, gpio->pin, LL_GPIO_OUTPUT_OPENDRAIN);
LL_GPIO_SetPinMode(gpio->port, gpio->pin, LL_GPIO_MODE_ALTERNATE);
break;
case GpioModeAnalog:
LL_GPIO_SetPinMode(gpio->port, gpio->pin, LL_GPIO_MODE_ANALOG);
break;
default:
break;
}
}
__enable_irq();
}
void hal_gpio_add_int_callback(const GpioPin* gpio, GpioExtiCallback cb, void* ctx) {
assert(gpio);
assert(cb);
__disable_irq();
uint8_t pin_num = hal_gpio_get_pin_num(gpio);
gpio_interrupt[pin_num].callback = cb;
gpio_interrupt[pin_num].context = ctx;
gpio_interrupt[pin_num].ready = true;
__enable_irq();
}
void hal_gpio_enable_int_callback(const GpioPin* gpio) {
assert(gpio);
__disable_irq();
uint8_t pin_num = hal_gpio_get_pin_num(gpio);
if(gpio_interrupt[pin_num].callback) {
gpio_interrupt[pin_num].ready = true;
}
__enable_irq();
}
void hal_gpio_disable_int_callback(const GpioPin* gpio) {
assert(gpio);
__disable_irq();
uint8_t pin_num = hal_gpio_get_pin_num(gpio);
gpio_interrupt[pin_num].ready = false;
__enable_irq();
}
void hal_gpio_remove_int_callback(const GpioPin* gpio) {
assert(gpio);
__disable_irq();
uint8_t pin_num = hal_gpio_get_pin_num(gpio);
gpio_interrupt[pin_num].callback = NULL;
gpio_interrupt[pin_num].context = NULL;
gpio_interrupt[pin_num].ready = false;
__enable_irq();
}

View File

@@ -1,264 +0,0 @@
#pragma once
#include "main.h"
#include "stdbool.h"
#include <stm32wbxx_ll_gpio.h>
#include <stm32wbxx_ll_system.h>
#include <stm32wbxx_ll_exti.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* Number of gpio on one port
*/
#define GPIO_NUMBER (16U)
/**
* Interrupt callback prototype
*/
typedef void (*GpioExtiCallback)(void* ctx);
/**
* Gpio interrupt type
*/
typedef struct {
GpioExtiCallback callback;
void* context;
volatile bool ready;
} GpioInterrupt;
/**
* Gpio modes
*/
typedef enum {
GpioModeInput,
GpioModeOutputPushPull,
GpioModeOutputOpenDrain,
GpioModeAltFunctionPushPull,
GpioModeAltFunctionOpenDrain,
GpioModeAnalog,
GpioModeInterruptRise,
GpioModeInterruptFall,
GpioModeInterruptRiseFall,
GpioModeEventRise,
GpioModeEventFall,
GpioModeEventRiseFall,
} GpioMode;
/**
* Gpio pull modes
*/
typedef enum {
GpioPullNo,
GpioPullUp,
GpioPullDown,
} GpioPull;
/**
* Gpio speed modes
*/
typedef enum {
GpioSpeedLow,
GpioSpeedMedium,
GpioSpeedHigh,
GpioSpeedVeryHigh,
} GpioSpeed;
/**
* Gpio alternate functions
*/
typedef enum {
GpioAltFn0MCO = 0, /*!< MCO Alternate Function mapping */
GpioAltFn0LSCO = 0, /*!< LSCO Alternate Function mapping */
GpioAltFn0JTMS_SWDIO = 0, /*!< JTMS-SWDIO Alternate Function mapping */
GpioAltFn0JTCK_SWCLK = 0, /*!< JTCK-SWCLK Alternate Function mapping */
GpioAltFn0JTDI = 0, /*!< JTDI Alternate Function mapping */
GpioAltFn0RTC_OUT = 0, /*!< RCT_OUT Alternate Function mapping */
GpioAltFn0JTD_TRACE = 0, /*!< JTDO-TRACESWO Alternate Function mapping */
GpioAltFn0NJTRST = 0, /*!< NJTRST Alternate Function mapping */
GpioAltFn0RTC_REFIN = 0, /*!< RTC_REFIN Alternate Function mapping */
GpioAltFn0TRACED0 = 0, /*!< TRACED0 Alternate Function mapping */
GpioAltFn0TRACED1 = 0, /*!< TRACED1 Alternate Function mapping */
GpioAltFn0TRACED2 = 0, /*!< TRACED2 Alternate Function mapping */
GpioAltFn0TRACED3 = 0, /*!< TRACED3 Alternate Function mapping */
GpioAltFn0TRIG_INOUT = 0, /*!< TRIG_INOUT Alternate Function mapping */
GpioAltFn0TRACECK = 0, /*!< TRACECK Alternate Function mapping */
GpioAltFn0SYS = 0, /*!< System Function mapping */
GpioAltFn1TIM1 = 1, /*!< TIM1 Alternate Function mapping */
GpioAltFn1TIM2 = 1, /*!< TIM2 Alternate Function mapping */
GpioAltFn1LPTIM1 = 1, /*!< LPTIM1 Alternate Function mapping */
GpioAltFn2TIM2 = 2, /*!< TIM2 Alternate Function mapping */
GpioAltFn2TIM1 = 2, /*!< TIM1 Alternate Function mapping */
GpioAltFn3SAI1 = 3, /*!< SAI1_CK1 Alternate Function mapping */
GpioAltFn3SPI2 = 3, /*!< SPI2 Alternate Function mapping */
GpioAltFn3TIM1 = 3, /*!< TIM1 Alternate Function mapping */
GpioAltFn4I2C1 = 4, /*!< I2C1 Alternate Function mapping */
GpioAltFn4I2C3 = 4, /*!< I2C3 Alternate Function mapping */
GpioAltFn5SPI1 = 5, /*!< SPI1 Alternate Function mapping */
GpioAltFn5SPI2 = 5, /*!< SPI2 Alternate Function mapping */
GpioAltFn6MCO = 6, /*!< MCO Alternate Function mapping */
GpioAltFn6LSCO = 6, /*!< LSCO Alternate Function mapping */
GpioAltFn6RF_DTB0 = 6, /*!< RF_DTB0 Alternate Function mapping */
GpioAltFn6RF_DTB1 = 6, /*!< RF_DTB1 Alternate Function mapping */
GpioAltFn6RF_DTB2 = 6, /*!< RF_DTB2 Alternate Function mapping */
GpioAltFn6RF_DTB3 = 6, /*!< RF_DTB3 Alternate Function mapping */
GpioAltFn6RF_DTB4 = 6, /*!< RF_DTB4 Alternate Function mapping */
GpioAltFn6RF_DTB5 = 6, /*!< RF_DTB5 Alternate Function mapping */
GpioAltFn6RF_DTB6 = 6, /*!< RF_DTB6 Alternate Function mapping */
GpioAltFn6RF_DTB7 = 6, /*!< RF_DTB7 Alternate Function mapping */
GpioAltFn6RF_DTB8 = 6, /*!< RF_DTB8 Alternate Function mapping */
GpioAltFn6RF_DTB9 = 6, /*!< RF_DTB9 Alternate Function mapping */
GpioAltFn6RF_DTB10 = 6, /*!< RF_DTB10 Alternate Function mapping */
GpioAltFn6RF_DTB11 = 6, /*!< RF_DTB11 Alternate Function mapping */
GpioAltFn6RF_DTB12 = 6, /*!< RF_DTB12 Alternate Function mapping */
GpioAltFn6RF_DTB13 = 6, /*!< RF_DTB13 Alternate Function mapping */
GpioAltFn6RF_DTB14 = 6, /*!< RF_DTB14 Alternate Function mapping */
GpioAltFn6RF_DTB15 = 6, /*!< RF_DTB15 Alternate Function mapping */
GpioAltFn6RF_DTB16 = 6, /*!< RF_DTB16 Alternate Function mapping */
GpioAltFn6RF_DTB17 = 6, /*!< RF_DTB17 Alternate Function mapping */
GpioAltFn6RF_DTB18 = 6, /*!< RF_DTB18 Alternate Function mapping */
GpioAltFn6RF_MISO = 6, /*!< RF_MISO Alternate Function mapping */
GpioAltFn6RF_MOSI = 6, /*!< RF_MOSI Alternate Function mapping */
GpioAltFn6RF_SCK = 6, /*!< RF_SCK Alternate Function mapping */
GpioAltFn6RF_NSS = 6, /*!< RF_NSS Alternate Function mapping */
GpioAltFn7USART1 = 7, /*!< USART1 Alternate Function mapping */
GpioAltFn8LPUART1 = 8, /*!< LPUART1 Alternate Function mapping */
GpioAltFn8IR = 8, /*!< IR Alternate Function mapping */
GpioAltFn9TSC = 9, /*!< TSC Alternate Function mapping */
GpioAltFn10QUADSPI = 10, /*!< QUADSPI Alternate Function mapping */
GpioAltFn10USB = 10, /*!< USB Alternate Function mapping */
GpioAltFn11LCD = 11, /*!< LCD Alternate Function mapping */
GpioAltFn12COMP1 = 12, /*!< COMP1 Alternate Function mapping */
GpioAltFn12COMP2 = 12, /*!< COMP2 Alternate Function mapping */
GpioAltFn12TIM1 = 12, /*!< TIM1 Alternate Function mapping */
GpioAltFn13SAI1 = 13, /*!< SAI1 Alternate Function mapping */
GpioAltFn14TIM2 = 14, /*!< TIM2 Alternate Function mapping */
GpioAltFn14TIM16 = 14, /*!< TIM16 Alternate Function mapping */
GpioAltFn14TIM17 = 14, /*!< TIM17 Alternate Function mapping */
GpioAltFn14LPTIM2 = 14, /*!< LPTIM2 Alternate Function mapping */
GpioAltFn15EVENTOUT = 15, /*!< EVENTOUT Alternate Function mapping */
GpioAltFnUnused = 16, /*!< just dummy value */
} GpioAltFn;
/**
* Gpio structure
*/
typedef struct {
GPIO_TypeDef* port;
uint16_t pin;
} GpioPin;
/**
* GPIO initialization function, simple version
* @param gpio GpioPin
* @param mode GpioMode
*/
void hal_gpio_init_simple(const GpioPin* gpio, const GpioMode mode);
/**
* GPIO initialization function, normal version
* @param gpio GpioPin
* @param mode GpioMode
* @param pull GpioPull
* @param speed GpioSpeed
*/
void hal_gpio_init(
const GpioPin* gpio,
const GpioMode mode,
const GpioPull pull,
const GpioSpeed speed);
/**
* GPIO initialization function, extended version
* @param gpio GpioPin
* @param mode GpioMode
* @param pull GpioPull
* @param speed GpioSpeed
* @param alt_fn GpioAltFn
*/
void hal_gpio_init_ex(
const GpioPin* gpio,
const GpioMode mode,
const GpioPull pull,
const GpioSpeed speed,
const GpioAltFn alt_fn);
/**
* Add and enable interrupt
* @param gpio GpioPin
* @param cb GpioExtiCallback
* @param ctx context for callback
*/
void hal_gpio_add_int_callback(const GpioPin* gpio, GpioExtiCallback cb, void* ctx);
/**
* Enable interrupt
* @param gpio GpioPin
*/
void hal_gpio_enable_int_callback(const GpioPin* gpio);
/**
* Disable interrupt
* @param gpio GpioPin
*/
void hal_gpio_disable_int_callback(const GpioPin* gpio);
/**
* Remove interrupt
* @param gpio GpioPin
*/
void hal_gpio_remove_int_callback(const GpioPin* gpio);
/**
* GPIO write pin
* @param gpio GpioPin
* @param state true / false
*/
static inline void hal_gpio_write(const GpioPin* gpio, const bool state) {
// writing to BSSR is an atomic operation
if(state == true) {
gpio->port->BSRR = gpio->pin;
} else {
gpio->port->BSRR = (uint32_t)gpio->pin << GPIO_NUMBER;
}
}
/**
* GPIO read pin
* @param gpio GpioPin
* @return true / false
*/
static inline bool hal_gpio_read(const GpioPin* gpio) {
if((gpio->port->IDR & gpio->pin) != 0x00U) {
return true;
} else {
return false;
}
}
/**
* Get RFID IN level
* @return false = LOW, true = HIGH
*/
bool hal_gpio_get_rfid_in_level();
#ifdef __cplusplus
}
#endif

View File

@@ -1,205 +0,0 @@
#include <furi_hal_i2c.h>
#include <furi_hal_version.h>
#include <stm32wbxx_ll_i2c.h>
#include <stm32wbxx_ll_gpio.h>
#include <stm32wbxx_ll_cortex.h>
#include <assert.h>
void furi_hal_i2c_init() {
furi_hal_i2c_bus_power.callback(&furi_hal_i2c_bus_power, FuriHalI2cBusEventInit);
}
void furi_hal_i2c_acquire(FuriHalI2cBusHandle* handle) {
handle->bus->callback(handle->bus, FuriHalI2cBusEventLock);
assert(handle->bus->current_handle == NULL);
handle->bus->current_handle = handle;
handle->bus->callback(handle->bus, FuriHalI2cBusEventActivate);
handle->callback(handle, FuriHalI2cBusHandleEventActivate);
}
void furi_hal_i2c_release(FuriHalI2cBusHandle* handle) {
assert(handle->bus->current_handle == handle);
handle->callback(handle, FuriHalI2cBusHandleEventDeactivate);
handle->bus->callback(handle->bus, FuriHalI2cBusEventDeactivate);
handle->bus->current_handle = NULL;
handle->bus->callback(handle->bus, FuriHalI2cBusEventUnlock);
}
bool furi_hal_i2c_tx(
FuriHalI2cBusHandle* handle,
uint8_t address,
const uint8_t* data,
uint8_t size,
uint32_t timeout) {
assert(handle->bus->current_handle == handle);
uint32_t time_left = timeout;
bool ret = true;
while(LL_I2C_IsActiveFlag_BUSY(handle->bus->i2c))
;
LL_I2C_HandleTransfer(
handle->bus->i2c,
address,
LL_I2C_ADDRSLAVE_7BIT,
size,
LL_I2C_MODE_AUTOEND,
LL_I2C_GENERATE_START_WRITE);
while(!LL_I2C_IsActiveFlag_STOP(handle->bus->i2c) || size > 0) {
if(LL_I2C_IsActiveFlag_TXIS(handle->bus->i2c)) {
LL_I2C_TransmitData8(handle->bus->i2c, (*data));
data++;
size--;
time_left = timeout;
}
if(LL_SYSTICK_IsActiveCounterFlag()) {
if(--time_left == 0) {
ret = false;
break;
}
}
}
LL_I2C_ClearFlag_STOP(handle->bus->i2c);
return ret;
}
bool furi_hal_i2c_rx(
FuriHalI2cBusHandle* handle,
uint8_t address,
uint8_t* data,
uint8_t size,
uint32_t timeout) {
assert(handle->bus->current_handle == handle);
uint32_t time_left = timeout;
bool ret = true;
while(LL_I2C_IsActiveFlag_BUSY(handle->bus->i2c))
;
LL_I2C_HandleTransfer(
handle->bus->i2c,
address,
LL_I2C_ADDRSLAVE_7BIT,
size,
LL_I2C_MODE_AUTOEND,
LL_I2C_GENERATE_START_READ);
while(!LL_I2C_IsActiveFlag_STOP(handle->bus->i2c) || size > 0) {
if(LL_I2C_IsActiveFlag_RXNE(handle->bus->i2c)) {
*data = LL_I2C_ReceiveData8(handle->bus->i2c);
data++;
size--;
time_left = timeout;
}
if(LL_SYSTICK_IsActiveCounterFlag()) {
if(--time_left == 0) {
ret = false;
break;
}
}
}
LL_I2C_ClearFlag_STOP(handle->bus->i2c);
return ret;
}
bool furi_hal_i2c_trx(
FuriHalI2cBusHandle* handle,
uint8_t address,
const uint8_t* tx_data,
uint8_t tx_size,
uint8_t* rx_data,
uint8_t rx_size,
uint32_t timeout) {
if(furi_hal_i2c_tx(handle, address, tx_data, tx_size, timeout) &&
furi_hal_i2c_rx(handle, address, rx_data, rx_size, timeout)) {
return true;
} else {
return false;
}
}
bool furi_hal_i2c_read_reg_8(
FuriHalI2cBusHandle* handle,
uint8_t i2c_addr,
uint8_t reg_addr,
uint8_t* data,
uint32_t timeout) {
assert(handle);
return furi_hal_i2c_trx(handle, i2c_addr, &reg_addr, 1, data, 1, timeout);
}
bool furi_hal_i2c_read_reg_16(
FuriHalI2cBusHandle* handle,
uint8_t i2c_addr,
uint8_t reg_addr,
uint16_t* data,
uint32_t timeout) {
assert(handle);
uint8_t reg_data[2];
bool ret = furi_hal_i2c_trx(handle, i2c_addr, &reg_addr, 1, reg_data, 2, timeout);
*data = (reg_data[0] << 8) | (reg_data[1]);
return ret;
}
bool furi_hal_i2c_read_mem(
FuriHalI2cBusHandle* handle,
uint8_t i2c_addr,
uint8_t mem_addr,
uint8_t* data,
uint8_t len,
uint32_t timeout) {
assert(handle);
return furi_hal_i2c_trx(handle, i2c_addr, &mem_addr, 1, data, len, timeout);
}
bool furi_hal_i2c_write_reg_8(
FuriHalI2cBusHandle* handle,
uint8_t i2c_addr,
uint8_t reg_addr,
uint8_t data,
uint32_t timeout) {
assert(handle);
uint8_t tx_data[2];
tx_data[0] = reg_addr;
tx_data[1] = data;
return furi_hal_i2c_tx(handle, i2c_addr, (const uint8_t*)&tx_data, 2, timeout);
}
bool furi_hal_i2c_write_reg_16(
FuriHalI2cBusHandle* handle,
uint8_t i2c_addr,
uint8_t reg_addr,
uint16_t data,
uint32_t timeout) {
assert(handle);
uint8_t tx_data[3];
tx_data[0] = reg_addr;
tx_data[1] = (data >> 8) & 0xFF;
tx_data[2] = data & 0xFF;
return furi_hal_i2c_tx(handle, i2c_addr, (const uint8_t*)&tx_data, 3, timeout);
}

View File

@@ -1,195 +0,0 @@
/**
* @file furi_hal_i2c.h
* I2C HAL API
*/
#pragma once
#include <stdbool.h>
#include <stdint.h>
#include <furi_hal_i2c_config.h>
#ifdef __cplusplus
extern "C" {
#endif
/** Init I2C
*/
void furi_hal_i2c_init();
/** Acquire i2c bus handle
*
* @return Instance of FuriHalI2cBus
*/
void furi_hal_i2c_acquire(FuriHalI2cBusHandle* handle);
/** Release i2c bus handle
*
* @param bus instance of FuriHalI2cBus aquired in `furi_hal_i2c_acquire`
*/
void furi_hal_i2c_release(FuriHalI2cBusHandle* handle);
/** Perform I2C tx transfer
*
* @param handle pointer to FuriHalI2cBusHandle instance
* @param address I2C slave address
* @param data pointer to data buffer
* @param size size of data buffer
* @param timeout timeout in ticks
*
* @return true on successful transfer, false otherwise
*/
bool furi_hal_i2c_tx(
FuriHalI2cBusHandle* handle,
const uint8_t address,
const uint8_t* data,
const uint8_t size,
uint32_t timeout);
/** Perform I2C rx transfer
*
* @param handle pointer to FuriHalI2cBusHandle instance
* @param address I2C slave address
* @param data pointer to data buffer
* @param size size of data buffer
* @param timeout timeout in ticks
*
* @return true on successful transfer, false otherwise
*/
bool furi_hal_i2c_rx(
FuriHalI2cBusHandle* handle,
const uint8_t address,
uint8_t* data,
const uint8_t size,
uint32_t timeout);
/** Perform I2C tx and rx transfers
*
* @param handle pointer to FuriHalI2cBusHandle instance
* @param address I2C slave address
* @param tx_data pointer to tx data buffer
* @param tx_size size of tx data buffer
* @param rx_data pointer to rx data buffer
* @param rx_size size of rx data buffer
* @param timeout timeout in ticks
*
* @return true on successful transfer, false otherwise
*/
bool furi_hal_i2c_trx(
FuriHalI2cBusHandle* handle,
const uint8_t address,
const uint8_t* tx_data,
const uint8_t tx_size,
uint8_t* rx_data,
const uint8_t rx_size,
uint32_t timeout);
/** Perform I2C device register read (8-bit)
*
* @param handle pointer to FuriHalI2cBusHandle instance
* @param i2c_addr I2C slave address
* @param reg_addr register address
* @param data pointer to register value
* @param timeout timeout in ticks
*
* @return true on successful transfer, false otherwise
*/
bool furi_hal_i2c_read_reg_8(
FuriHalI2cBusHandle* handle,
uint8_t i2c_addr,
uint8_t reg_addr,
uint8_t* data,
uint32_t timeout);
/** Perform I2C device register read (16-bit)
*
* @param handle pointer to FuriHalI2cBusHandle instance
* @param i2c_addr I2C slave address
* @param reg_addr register address
* @param data pointer to register value
* @param timeout timeout in ticks
*
* @return true on successful transfer, false otherwise
*/
bool furi_hal_i2c_read_reg_16(
FuriHalI2cBusHandle* handle,
uint8_t i2c_addr,
uint8_t reg_addr,
uint16_t* data,
uint32_t timeout);
/** Perform I2C device memory read
*
* @param handle pointer to FuriHalI2cBusHandle instance
* @param i2c_addr I2C slave address
* @param mem_addr memory start address
* @param data pointer to data buffer
* @param len size of data buffer
* @param timeout timeout in ticks
*
* @return true on successful transfer, false otherwise
*/
bool furi_hal_i2c_read_mem(
FuriHalI2cBusHandle* handle,
uint8_t i2c_addr,
uint8_t mem_addr,
uint8_t* data,
uint8_t len,
uint32_t timeout);
/** Perform I2C device register write (8-bit)
*
* @param handle pointer to FuriHalI2cBusHandle instance
* @param i2c_addr I2C slave address
* @param reg_addr register address
* @param data register value
* @param timeout timeout in ticks
*
* @return true on successful transfer, false otherwise
*/
bool furi_hal_i2c_write_reg_8(
FuriHalI2cBusHandle* handle,
uint8_t i2c_addr,
uint8_t reg_addr,
uint8_t data,
uint32_t timeout);
/** Perform I2C device register write (16-bit)
*
* @param handle pointer to FuriHalI2cBusHandle instance
* @param i2c_addr I2C slave address
* @param reg_addr register address
* @param data register value
* @param timeout timeout in ticks
*
* @return true on successful transfer, false otherwise
*/
bool furi_hal_i2c_write_reg_16(
FuriHalI2cBusHandle* handle,
uint8_t i2c_addr,
uint8_t reg_addr,
uint16_t data,
uint32_t timeout);
/** Perform I2C device memory
*
* @param handle pointer to FuriHalI2cBusHandle instance
* @param i2c_addr I2C slave address
* @param mem_addr memory start address
* @param data pointer to data buffer
* @param len size of data buffer
* @param timeout timeout in ticks
*
* @return true on successful transfer, false otherwise
*/
bool furi_hal_i2c_write_mem(
FuriHalI2cBusHandle* handle,
uint8_t i2c_addr,
uint8_t mem_addr,
uint8_t* data,
uint8_t len,
uint32_t timeout);
#ifdef __cplusplus
}
#endif

View File

@@ -1,149 +0,0 @@
#include "furi_hal_i2c_config.h"
#include <furi_hal_resources.h>
#include <furi_hal_version.h>
#include <stm32wbxx_ll_rcc.h>
#include <stm32wbxx_ll_bus.h>
/** Timing register value is computed with the STM32CubeMX Tool,
* Standard Mode @100kHz with I2CCLK = 64 MHz,
* rise time = 0ns, fall time = 0ns
*/
#define FURI_HAL_I2C_CONFIG_POWER_I2C_TIMINGS_100 0x10707DBC
/** Timing register value is computed with the STM32CubeMX Tool,
* Fast Mode @400kHz with I2CCLK = 64 MHz,
* rise time = 0ns, fall time = 0ns
*/
#define FURI_HAL_I2C_CONFIG_POWER_I2C_TIMINGS_400 0x00602173
static void furi_hal_i2c_bus_power_event(FuriHalI2cBus* bus, FuriHalI2cBusEvent event) {
if(event == FuriHalI2cBusEventInit) {
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_I2C1);
LL_RCC_SetI2CClockSource(LL_RCC_I2C1_CLKSOURCE_PCLK1);
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_I2C1);
bus->current_handle = NULL;
} else if(event == FuriHalI2cBusEventDeinit) {
} else if(event == FuriHalI2cBusEventLock) {
} else if(event == FuriHalI2cBusEventUnlock) {
} else if(event == FuriHalI2cBusEventActivate) {
LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_I2C1);
} else if(event == FuriHalI2cBusEventDeactivate) {
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_I2C1);
}
}
FuriHalI2cBus furi_hal_i2c_bus_power = {
.i2c = I2C1,
.current_handle = NULL,
.callback = furi_hal_i2c_bus_power_event,
};
static void furi_hal_i2c_bus_external_event(FuriHalI2cBus* bus, FuriHalI2cBusEvent event) {
if(event == FuriHalI2cBusEventActivate) {
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_I2C3);
LL_RCC_SetI2CClockSource(LL_RCC_I2C3_CLKSOURCE_PCLK1);
LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_I2C3);
} else if(event == FuriHalI2cBusEventDeactivate) {
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_I2C3);
}
}
FuriHalI2cBus furi_hal_i2c_bus_external = {
.i2c = I2C3,
.current_handle = NULL,
.callback = furi_hal_i2c_bus_external_event,
};
void furi_hal_i2c_bus_handle_power_event(
FuriHalI2cBusHandle* handle,
FuriHalI2cBusHandleEvent event) {
if(event == FuriHalI2cBusHandleEventActivate) {
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOA);
hal_gpio_init_ex(
&gpio_i2c_power_sda,
GpioModeAltFunctionOpenDrain,
GpioPullNo,
GpioSpeedLow,
GpioAltFn4I2C1);
hal_gpio_init_ex(
&gpio_i2c_power_scl,
GpioModeAltFunctionOpenDrain,
GpioPullNo,
GpioSpeedLow,
GpioAltFn4I2C1);
LL_I2C_InitTypeDef I2C_InitStruct = {0};
I2C_InitStruct.PeripheralMode = LL_I2C_MODE_I2C;
I2C_InitStruct.AnalogFilter = LL_I2C_ANALOGFILTER_ENABLE;
I2C_InitStruct.DigitalFilter = 0;
I2C_InitStruct.OwnAddress1 = 0;
I2C_InitStruct.TypeAcknowledge = LL_I2C_ACK;
I2C_InitStruct.OwnAddrSize = LL_I2C_OWNADDRESS1_7BIT;
if(furi_hal_version_get_hw_version() > 10) {
I2C_InitStruct.Timing = FURI_HAL_I2C_CONFIG_POWER_I2C_TIMINGS_400;
} else {
I2C_InitStruct.Timing = FURI_HAL_I2C_CONFIG_POWER_I2C_TIMINGS_100;
}
LL_I2C_Init(handle->bus->i2c, &I2C_InitStruct);
LL_I2C_EnableAutoEndMode(handle->bus->i2c);
LL_I2C_SetOwnAddress2(handle->bus->i2c, 0, LL_I2C_OWNADDRESS2_NOMASK);
LL_I2C_DisableOwnAddress2(handle->bus->i2c);
LL_I2C_DisableGeneralCall(handle->bus->i2c);
LL_I2C_EnableClockStretching(handle->bus->i2c);
LL_I2C_Enable(handle->bus->i2c);
} else if(event == FuriHalI2cBusHandleEventDeactivate) {
LL_I2C_Disable(handle->bus->i2c);
hal_gpio_write(&gpio_i2c_power_sda, 1);
hal_gpio_write(&gpio_i2c_power_scl, 1);
hal_gpio_init_ex(
&gpio_i2c_power_sda, GpioModeAnalog, GpioPullNo, GpioSpeedLow, GpioAltFnUnused);
hal_gpio_init_ex(
&gpio_i2c_power_scl, GpioModeAnalog, GpioPullNo, GpioSpeedLow, GpioAltFnUnused);
}
}
FuriHalI2cBusHandle furi_hal_i2c_handle_power = {
.bus = &furi_hal_i2c_bus_power,
.callback = furi_hal_i2c_bus_handle_power_event,
};
void furi_hal_i2c_bus_handle_external_event(
FuriHalI2cBusHandle* handle,
FuriHalI2cBusHandleEvent event) {
if(event == FuriHalI2cBusHandleEventActivate) {
hal_gpio_init_ex(
&gpio_ext_pc0, GpioModeAltFunctionOpenDrain, GpioPullNo, GpioSpeedLow, GpioAltFn4I2C3);
hal_gpio_init_ex(
&gpio_ext_pc1, GpioModeAltFunctionOpenDrain, GpioPullNo, GpioSpeedLow, GpioAltFn4I2C3);
LL_I2C_InitTypeDef I2C_InitStruct = {0};
I2C_InitStruct.PeripheralMode = LL_I2C_MODE_I2C;
I2C_InitStruct.AnalogFilter = LL_I2C_ANALOGFILTER_ENABLE;
I2C_InitStruct.DigitalFilter = 0;
I2C_InitStruct.OwnAddress1 = 0;
I2C_InitStruct.TypeAcknowledge = LL_I2C_ACK;
I2C_InitStruct.OwnAddrSize = LL_I2C_OWNADDRESS1_7BIT;
I2C_InitStruct.Timing = FURI_HAL_I2C_CONFIG_POWER_I2C_TIMINGS_100;
LL_I2C_Init(handle->bus->i2c, &I2C_InitStruct);
LL_I2C_EnableAutoEndMode(handle->bus->i2c);
LL_I2C_SetOwnAddress2(handle->bus->i2c, 0, LL_I2C_OWNADDRESS2_NOMASK);
LL_I2C_DisableOwnAddress2(handle->bus->i2c);
LL_I2C_DisableGeneralCall(handle->bus->i2c);
LL_I2C_EnableClockStretching(handle->bus->i2c);
LL_I2C_Enable(handle->bus->i2c);
} else if(event == FuriHalI2cBusHandleEventDeactivate) {
LL_I2C_Disable(handle->bus->i2c);
hal_gpio_write(&gpio_ext_pc0, 1);
hal_gpio_write(&gpio_ext_pc1, 1);
hal_gpio_init_ex(&gpio_ext_pc0, GpioModeAnalog, GpioPullNo, GpioSpeedLow, GpioAltFnUnused);
hal_gpio_init_ex(&gpio_ext_pc1, GpioModeAnalog, GpioPullNo, GpioSpeedLow, GpioAltFnUnused);
}
}
FuriHalI2cBusHandle furi_hal_i2c_handle_external = {
.bus = &furi_hal_i2c_bus_external,
.callback = furi_hal_i2c_bus_handle_external_event,
};

View File

@@ -1,31 +0,0 @@
#pragma once
#include <furi_hal_i2c_types.h>
#ifdef __cplusplus
extern "C" {
#endif
/** Internal(power) i2c bus, I2C1, under reset when not used */
extern FuriHalI2cBus furi_hal_i2c_bus_power;
/** External i2c bus, I2C3, under reset when not used */
extern FuriHalI2cBus furi_hal_i2c_bus_external;
/** Handle for internal(power) i2c bus
* Bus: furi_hal_i2c_bus_external
* Pins: PA9(SCL) / PA10(SDA), float on release
* Params: 400khz
*/
extern FuriHalI2cBusHandle furi_hal_i2c_handle_power;
/** Handle for external i2c bus
* Bus: furi_hal_i2c_bus_external
* Pins: PC0(SCL) / PC1(SDA), float on release
* Params: 100khz
*/
extern FuriHalI2cBusHandle furi_hal_i2c_handle_external;
#ifdef __cplusplus
}
#endif

View File

@@ -1,51 +0,0 @@
#pragma once
#include <stm32wbxx_ll_i2c.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct FuriHalI2cBus FuriHalI2cBus;
typedef struct FuriHalI2cBusHandle FuriHalI2cBusHandle;
/** FuriHal i2c bus states */
typedef enum {
FuriHalI2cBusEventInit, /**< Bus initialization event, called on system start */
FuriHalI2cBusEventDeinit, /**< Bus deinitialization event, called on system stop */
FuriHalI2cBusEventLock, /**< Bus lock event, called before activation */
FuriHalI2cBusEventUnlock, /**< Bus unlock event, called after deactivation */
FuriHalI2cBusEventActivate, /**< Bus activation event, called before handle activation */
FuriHalI2cBusEventDeactivate, /**< Bus deactivation event, called after handle deactivation */
} FuriHalI2cBusEvent;
/** FuriHal i2c bus event callback */
typedef void (*FuriHalI2cBusEventCallback)(FuriHalI2cBus* bus, FuriHalI2cBusEvent event);
/** FuriHal i2c bus */
struct FuriHalI2cBus {
I2C_TypeDef* i2c;
FuriHalI2cBusHandle* current_handle;
FuriHalI2cBusEventCallback callback;
};
/** FuriHal i2c handle states */
typedef enum {
FuriHalI2cBusHandleEventActivate, /**< Handle activate: connect gpio and apply bus config */
FuriHalI2cBusHandleEventDeactivate, /**< Handle deactivate: disconnect gpio and reset bus config */
} FuriHalI2cBusHandleEvent;
/** FuriHal i2c handle event callback */
typedef void (*FuriHalI2cBusHandleEventCallback)(
FuriHalI2cBusHandle* handle,
FuriHalI2cBusHandleEvent event);
/** FuriHal i2c handle */
struct FuriHalI2cBusHandle {
FuriHalI2cBus* bus;
FuriHalI2cBusHandleEventCallback callback;
};
#ifdef __cplusplus
}
#endif

View File

@@ -1,49 +0,0 @@
#include <furi_hal_light.h>
#include <lp5562.h>
#define LED_CURRENT_RED 50
#define LED_CURRENT_GREEN 50
#define LED_CURRENT_BLUE 50
#define LED_CURRENT_WHITE 150
void furi_hal_light_init() {
furi_hal_i2c_acquire(&furi_hal_i2c_handle_power);
lp5562_reset(&furi_hal_i2c_handle_power);
lp5562_set_channel_current(&furi_hal_i2c_handle_power, LP5562ChannelRed, LED_CURRENT_RED);
lp5562_set_channel_current(&furi_hal_i2c_handle_power, LP5562ChannelGreen, LED_CURRENT_GREEN);
lp5562_set_channel_current(&furi_hal_i2c_handle_power, LP5562ChannelBlue, LED_CURRENT_BLUE);
lp5562_set_channel_current(&furi_hal_i2c_handle_power, LP5562ChannelWhite, LED_CURRENT_WHITE);
lp5562_set_channel_value(&furi_hal_i2c_handle_power, LP5562ChannelRed, 0x00);
lp5562_set_channel_value(&furi_hal_i2c_handle_power, LP5562ChannelGreen, 0x00);
lp5562_set_channel_value(&furi_hal_i2c_handle_power, LP5562ChannelBlue, 0x00);
lp5562_set_channel_value(&furi_hal_i2c_handle_power, LP5562ChannelWhite, 0x00);
lp5562_enable(&furi_hal_i2c_handle_power);
lp5562_configure(&furi_hal_i2c_handle_power);
furi_hal_i2c_release(&furi_hal_i2c_handle_power);
}
void furi_hal_light_set(Light light, uint8_t value) {
furi_hal_i2c_acquire(&furi_hal_i2c_handle_power);
switch(light) {
case LightRed:
lp5562_set_channel_value(&furi_hal_i2c_handle_power, LP5562ChannelRed, value);
break;
case LightGreen:
lp5562_set_channel_value(&furi_hal_i2c_handle_power, LP5562ChannelGreen, value);
break;
case LightBlue:
lp5562_set_channel_value(&furi_hal_i2c_handle_power, LP5562ChannelBlue, value);
break;
case LightBacklight:
lp5562_set_channel_value(&furi_hal_i2c_handle_power, LP5562ChannelWhite, value);
break;
default:
break;
}
furi_hal_i2c_release(&furi_hal_i2c_handle_power);
}

View File

@@ -1,17 +0,0 @@
#pragma once
#include <stdbool.h>
#include <stdint.h>
#include <furi_hal_resources.h>
#ifdef __cplusplus
extern "C" {
#endif
void furi_hal_light_init();
void furi_hal_light_set(Light light, uint8_t value);
#ifdef __cplusplus
}
#endif

View File

@@ -1,44 +0,0 @@
#include "furi_hal_resources.h"
#include "main.h"
const GpioPin vibro_gpio = {.port = VIBRO_GPIO_Port, .pin = VIBRO_Pin};
const GpioPin ibutton_gpio = {.port = iBTN_GPIO_Port, .pin = iBTN_Pin};
const GpioPin gpio_cc1101_g0 = {.port = CC1101_G0_GPIO_Port, .pin = CC1101_G0_Pin};
const GpioPin gpio_rf_sw_0 = {.port = RF_SW_0_GPIO_Port, .pin = RF_SW_0_Pin};
const GpioPin gpio_subghz_cs = {.port = CC1101_CS_GPIO_Port, .pin = CC1101_CS_Pin};
const GpioPin gpio_display_cs = {.port = DISPLAY_CS_GPIO_Port, .pin = DISPLAY_CS_Pin};
const GpioPin gpio_display_rst = {.port = DISPLAY_RST_GPIO_Port, .pin = DISPLAY_RST_Pin};
const GpioPin gpio_display_di = {.port = DISPLAY_DI_GPIO_Port, .pin = DISPLAY_DI_Pin};
const GpioPin gpio_sdcard_cs = {.port = SD_CS_GPIO_Port, .pin = SD_CS_Pin};
const GpioPin gpio_nfc_cs = {.port = NFC_CS_GPIO_Port, .pin = NFC_CS_Pin};
const GpioPin gpio_spi_d_miso = {.port = SPI_D_MISO_GPIO_Port, .pin = SPI_D_MISO_Pin};
const GpioPin gpio_spi_d_mosi = {.port = SPI_D_MOSI_GPIO_Port, .pin = SPI_D_MOSI_Pin};
const GpioPin gpio_spi_d_sck = {.port = SPI_D_SCK_GPIO_Port, .pin = SPI_D_SCK_Pin};
const GpioPin gpio_spi_r_miso = {.port = SPI_R_MISO_GPIO_Port, .pin = SPI_R_MISO_Pin};
const GpioPin gpio_spi_r_mosi = {.port = SPI_R_MOSI_GPIO_Port, .pin = SPI_R_MOSI_Pin};
const GpioPin gpio_spi_r_sck = {.port = SPI_R_SCK_GPIO_Port, .pin = SPI_R_SCK_Pin};
const GpioPin gpio_ext_pc0 = {.port = GPIOC, .pin = LL_GPIO_PIN_0};
const GpioPin gpio_ext_pc1 = {.port = GPIOC, .pin = LL_GPIO_PIN_1};
const GpioPin gpio_ext_pc3 = {.port = GPIOC, .pin = LL_GPIO_PIN_3};
const GpioPin gpio_ext_pb2 = {.port = GPIOB, .pin = LL_GPIO_PIN_2};
const GpioPin gpio_ext_pb3 = {.port = GPIOB, .pin = LL_GPIO_PIN_3};
const GpioPin gpio_ext_pa4 = {.port = GPIOA, .pin = LL_GPIO_PIN_4};
const GpioPin gpio_ext_pa6 = {.port = GPIOA, .pin = LL_GPIO_PIN_6};
const GpioPin gpio_ext_pa7 = {.port = GPIOA, .pin = LL_GPIO_PIN_7};
const GpioPin gpio_rfid_pull = {.port = RFID_PULL_GPIO_Port, .pin = RFID_PULL_Pin};
const GpioPin gpio_rfid_carrier_out = {.port = RFID_OUT_GPIO_Port, .pin = RFID_OUT_Pin};
const GpioPin gpio_rfid_data_in = {.port = RFID_RF_IN_GPIO_Port, .pin = RFID_RF_IN_Pin};
const GpioPin gpio_infrared_rx = {.port = IR_RX_GPIO_Port, .pin = IR_RX_Pin};
const GpioPin gpio_infrared_tx = {.port = IR_TX_GPIO_Port, .pin = IR_TX_Pin};
const GpioPin gpio_usart_tx = {.port = USART1_TX_Port, .pin = USART1_TX_Pin};
const GpioPin gpio_usart_rx = {.port = USART1_RX_Port, .pin = USART1_RX_Pin};
const GpioPin gpio_i2c_power_sda = {.port = GPIOA, .pin = LL_GPIO_PIN_10};
const GpioPin gpio_i2c_power_scl = {.port = GPIOA, .pin = LL_GPIO_PIN_9};

View File

@@ -1,73 +0,0 @@
#pragma once
#include <stm32wbxx.h>
#include <stm32wbxx_ll_gpio.h>
#include <furi_hal_gpio.h>
#ifdef __cplusplus
extern "C" {
#endif
/* Input Keys */
typedef enum {
InputKeyUp,
InputKeyDown,
InputKeyRight,
InputKeyLeft,
InputKeyOk,
InputKeyBack,
} InputKey;
/* Light */
typedef enum {
LightRed,
LightGreen,
LightBlue,
LightBacklight,
} Light;
extern const GpioPin vibro_gpio;
extern const GpioPin ibutton_gpio;
extern const GpioPin gpio_cc1101_g0;
extern const GpioPin gpio_rf_sw_0;
extern const GpioPin gpio_subghz_cs;
extern const GpioPin gpio_display_cs;
extern const GpioPin gpio_display_rst;
extern const GpioPin gpio_display_di;
extern const GpioPin gpio_sdcard_cs;
extern const GpioPin gpio_nfc_cs;
extern const GpioPin gpio_spi_d_miso;
extern const GpioPin gpio_spi_d_mosi;
extern const GpioPin gpio_spi_d_sck;
extern const GpioPin gpio_spi_r_miso;
extern const GpioPin gpio_spi_r_mosi;
extern const GpioPin gpio_spi_r_sck;
extern const GpioPin gpio_ext_pc0;
extern const GpioPin gpio_ext_pc1;
extern const GpioPin gpio_ext_pc3;
extern const GpioPin gpio_ext_pb2;
extern const GpioPin gpio_ext_pb3;
extern const GpioPin gpio_ext_pa4;
extern const GpioPin gpio_ext_pa6;
extern const GpioPin gpio_ext_pa7;
extern const GpioPin gpio_rfid_pull;
extern const GpioPin gpio_rfid_carrier_out;
extern const GpioPin gpio_rfid_data_in;
extern const GpioPin gpio_infrared_rx;
extern const GpioPin gpio_infrared_tx;
extern const GpioPin gpio_usart_tx;
extern const GpioPin gpio_usart_rx;
extern const GpioPin gpio_i2c_power_sda;
extern const GpioPin gpio_i2c_power_scl;
#ifdef __cplusplus
}
#endif

View File

@@ -1,151 +0,0 @@
#include "furi_hal_spi.h"
#include "furi_hal_resources.h"
#include <stdbool.h>
#include <string.h>
#include <assert.h>
#include <stm32wbxx_ll_spi.h>
#include <stm32wbxx_ll_utils.h>
#include <stm32wbxx_ll_cortex.h>
void furi_hal_spi_init() {
furi_hal_spi_bus_init(&furi_hal_spi_bus_r);
furi_hal_spi_bus_init(&furi_hal_spi_bus_d);
furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_subghz);
furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_nfc);
furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_display);
furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_sd_fast);
furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_sd_slow);
}
void furi_hal_spi_bus_init(FuriHalSpiBus* bus) {
assert(bus);
bus->callback(bus, FuriHalSpiBusEventInit);
}
void furi_hal_spi_bus_deinit(FuriHalSpiBus* bus) {
assert(bus);
bus->callback(bus, FuriHalSpiBusEventDeinit);
}
void furi_hal_spi_bus_handle_init(FuriHalSpiBusHandle* handle) {
assert(handle);
handle->callback(handle, FuriHalSpiBusHandleEventInit);
}
void furi_hal_spi_bus_handle_deinit(FuriHalSpiBusHandle* handle) {
assert(handle);
handle->callback(handle, FuriHalSpiBusHandleEventDeinit);
}
void furi_hal_spi_acquire(FuriHalSpiBusHandle* handle) {
assert(handle);
handle->bus->callback(handle->bus, FuriHalSpiBusEventLock);
handle->bus->callback(handle->bus, FuriHalSpiBusEventActivate);
assert(handle->bus->current_handle == NULL);
handle->bus->current_handle = handle;
handle->callback(handle, FuriHalSpiBusHandleEventActivate);
}
void furi_hal_spi_release(FuriHalSpiBusHandle* handle) {
assert(handle);
assert(handle->bus->current_handle == handle);
// Handle event and unset handle
handle->callback(handle, FuriHalSpiBusHandleEventDeactivate);
handle->bus->current_handle = NULL;
// Bus events
handle->bus->callback(handle->bus, FuriHalSpiBusEventDeactivate);
handle->bus->callback(handle->bus, FuriHalSpiBusEventUnlock);
}
static void furi_hal_spi_bus_end_txrx(FuriHalSpiBusHandle* handle, uint32_t timeout) {
while(LL_SPI_GetTxFIFOLevel(handle->bus->spi) != LL_SPI_TX_FIFO_EMPTY)
;
while(LL_SPI_IsActiveFlag_BSY(handle->bus->spi))
;
while(LL_SPI_GetRxFIFOLevel(handle->bus->spi) != LL_SPI_RX_FIFO_EMPTY) {
LL_SPI_ReceiveData8(handle->bus->spi);
}
}
bool furi_hal_spi_bus_rx(
FuriHalSpiBusHandle* handle,
uint8_t* buffer,
size_t size,
uint32_t timeout) {
assert(handle);
assert(handle->bus->current_handle == handle);
assert(buffer);
assert(size > 0);
return furi_hal_spi_bus_trx(handle, buffer, buffer, size, timeout);
}
bool furi_hal_spi_bus_tx(
FuriHalSpiBusHandle* handle,
uint8_t* buffer,
size_t size,
uint32_t timeout) {
assert(handle);
assert(handle->bus->current_handle == handle);
assert(buffer);
assert(size > 0);
bool ret = true;
while(size > 0) {
if(LL_SPI_IsActiveFlag_TXE(handle->bus->spi)) {
LL_SPI_TransmitData8(handle->bus->spi, *buffer);
buffer++;
size--;
}
}
furi_hal_spi_bus_end_txrx(handle, timeout);
LL_SPI_ClearFlag_OVR(handle->bus->spi);
return ret;
}
bool furi_hal_spi_bus_trx(
FuriHalSpiBusHandle* handle,
uint8_t* tx_buffer,
uint8_t* rx_buffer,
size_t size,
uint32_t timeout) {
assert(handle);
assert(handle->bus->current_handle == handle);
assert(tx_buffer);
assert(rx_buffer);
assert(size > 0);
bool ret = true;
size_t tx_size = size;
bool tx_allowed = true;
while(size > 0) {
if(tx_size > 0 && LL_SPI_IsActiveFlag_TXE(handle->bus->spi) && tx_allowed) {
LL_SPI_TransmitData8(handle->bus->spi, *tx_buffer);
tx_buffer++;
tx_size--;
tx_allowed = false;
}
if(LL_SPI_IsActiveFlag_RXNE(handle->bus->spi)) {
*rx_buffer = LL_SPI_ReceiveData8(handle->bus->spi);
rx_buffer++;
size--;
tx_allowed = true;
}
}
furi_hal_spi_bus_end_txrx(handle, timeout);
return ret;
}

View File

@@ -1,290 +0,0 @@
#include <furi_hal_spi_config.h>
#include <furi_hal_resources.h>
/* SPI Presets */
const LL_SPI_InitTypeDef furi_hal_spi_preset_2edge_low_8m = {
.Mode = LL_SPI_MODE_MASTER,
.TransferDirection = LL_SPI_FULL_DUPLEX,
.DataWidth = LL_SPI_DATAWIDTH_8BIT,
.ClockPolarity = LL_SPI_POLARITY_LOW,
.ClockPhase = LL_SPI_PHASE_2EDGE,
.NSS = LL_SPI_NSS_SOFT,
.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV8,
.BitOrder = LL_SPI_MSB_FIRST,
.CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE,
.CRCPoly = 7,
};
const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_8m = {
.Mode = LL_SPI_MODE_MASTER,
.TransferDirection = LL_SPI_FULL_DUPLEX,
.DataWidth = LL_SPI_DATAWIDTH_8BIT,
.ClockPolarity = LL_SPI_POLARITY_LOW,
.ClockPhase = LL_SPI_PHASE_1EDGE,
.NSS = LL_SPI_NSS_SOFT,
.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV8,
.BitOrder = LL_SPI_MSB_FIRST,
.CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE,
.CRCPoly = 7,
};
const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_4m = {
.Mode = LL_SPI_MODE_MASTER,
.TransferDirection = LL_SPI_FULL_DUPLEX,
.DataWidth = LL_SPI_DATAWIDTH_8BIT,
.ClockPolarity = LL_SPI_POLARITY_LOW,
.ClockPhase = LL_SPI_PHASE_1EDGE,
.NSS = LL_SPI_NSS_SOFT,
.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV16,
.BitOrder = LL_SPI_MSB_FIRST,
.CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE,
.CRCPoly = 7,
};
const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_16m = {
.Mode = LL_SPI_MODE_MASTER,
.TransferDirection = LL_SPI_FULL_DUPLEX,
.DataWidth = LL_SPI_DATAWIDTH_8BIT,
.ClockPolarity = LL_SPI_POLARITY_LOW,
.ClockPhase = LL_SPI_PHASE_1EDGE,
.NSS = LL_SPI_NSS_SOFT,
.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV2,
.BitOrder = LL_SPI_MSB_FIRST,
.CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE,
.CRCPoly = 7,
};
const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_2m = {
.Mode = LL_SPI_MODE_MASTER,
.TransferDirection = LL_SPI_FULL_DUPLEX,
.DataWidth = LL_SPI_DATAWIDTH_8BIT,
.ClockPolarity = LL_SPI_POLARITY_LOW,
.ClockPhase = LL_SPI_PHASE_1EDGE,
.NSS = LL_SPI_NSS_SOFT,
.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV32,
.BitOrder = LL_SPI_MSB_FIRST,
.CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE,
.CRCPoly = 7,
};
/* SPI Buses */
static void furi_hal_spi_bus_r_event_callback(FuriHalSpiBus* bus, FuriHalSpiBusEvent event) {
if(event == FuriHalSpiBusEventInit) {
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SPI1);
LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_SPI1);
bus->current_handle = NULL;
} else if(event == FuriHalSpiBusEventDeinit) {
} else if(event == FuriHalSpiBusEventLock) {
} else if(event == FuriHalSpiBusEventUnlock) {
} else if(event == FuriHalSpiBusEventActivate) {
LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_SPI1);
} else if(event == FuriHalSpiBusEventDeactivate) {
LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_SPI1);
}
}
FuriHalSpiBus furi_hal_spi_bus_r = {
.spi = SPI1,
.callback = furi_hal_spi_bus_r_event_callback,
};
static void furi_hal_spi_bus_d_event_callback(FuriHalSpiBus* bus, FuriHalSpiBusEvent event) {
if(event == FuriHalSpiBusEventInit) {
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_SPI2);
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_SPI2);
bus->current_handle = NULL;
} else if(event == FuriHalSpiBusEventDeinit) {
} else if(event == FuriHalSpiBusEventLock) {
} else if(event == FuriHalSpiBusEventUnlock) {
} else if(event == FuriHalSpiBusEventActivate) {
LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_SPI2);
} else if(event == FuriHalSpiBusEventDeactivate) {
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_SPI2);
}
}
FuriHalSpiBus furi_hal_spi_bus_d = {
.spi = SPI2,
.callback = furi_hal_spi_bus_d_event_callback,
};
/* SPI Bus Handles */
inline static void furi_hal_spi_bus_r_handle_event_callback(
FuriHalSpiBusHandle* handle,
FuriHalSpiBusHandleEvent event,
const LL_SPI_InitTypeDef* preset) {
if(event == FuriHalSpiBusHandleEventInit) {
hal_gpio_write(handle->cs, true);
hal_gpio_init(handle->cs, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh);
} else if(event == FuriHalSpiBusHandleEventDeinit) {
hal_gpio_write(handle->cs, true);
hal_gpio_init(handle->cs, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
} else if(event == FuriHalSpiBusHandleEventActivate) {
LL_SPI_Init(handle->bus->spi, (LL_SPI_InitTypeDef*)preset);
LL_SPI_SetRxFIFOThreshold(handle->bus->spi, LL_SPI_RX_FIFO_TH_QUARTER);
LL_SPI_Enable(handle->bus->spi);
hal_gpio_init_ex(
handle->miso,
GpioModeAltFunctionPushPull,
GpioPullNo,
GpioSpeedVeryHigh,
GpioAltFn5SPI1);
hal_gpio_init_ex(
handle->mosi,
GpioModeAltFunctionPushPull,
GpioPullNo,
GpioSpeedVeryHigh,
GpioAltFn5SPI1);
hal_gpio_init_ex(
handle->sck,
GpioModeAltFunctionPushPull,
GpioPullNo,
GpioSpeedVeryHigh,
GpioAltFn5SPI1);
hal_gpio_write(handle->cs, false);
} else if(event == FuriHalSpiBusHandleEventDeactivate) {
hal_gpio_write(handle->cs, true);
hal_gpio_init(handle->miso, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
hal_gpio_init(handle->mosi, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
hal_gpio_init(handle->sck, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
LL_SPI_Disable(handle->bus->spi);
}
}
static void furi_hal_spi_bus_handle_subghz_event_callback(
FuriHalSpiBusHandle* handle,
FuriHalSpiBusHandleEvent event) {
furi_hal_spi_bus_r_handle_event_callback(handle, event, &furi_hal_spi_preset_1edge_low_8m);
}
FuriHalSpiBusHandle furi_hal_spi_bus_handle_subghz = {
.bus = &furi_hal_spi_bus_r,
.callback = furi_hal_spi_bus_handle_subghz_event_callback,
.miso = &gpio_spi_r_miso,
.mosi = &gpio_spi_r_mosi,
.sck = &gpio_spi_r_sck,
.cs = &gpio_subghz_cs,
};
static void furi_hal_spi_bus_handle_nfc_event_callback(
FuriHalSpiBusHandle* handle,
FuriHalSpiBusHandleEvent event) {
furi_hal_spi_bus_r_handle_event_callback(handle, event, &furi_hal_spi_preset_2edge_low_8m);
}
FuriHalSpiBusHandle furi_hal_spi_bus_handle_nfc = {
.bus = &furi_hal_spi_bus_r,
.callback = furi_hal_spi_bus_handle_nfc_event_callback,
.miso = &gpio_spi_r_miso,
.mosi = &gpio_spi_r_mosi,
.sck = &gpio_spi_r_sck,
.cs = &gpio_nfc_cs,
};
static void furi_hal_spi_bus_handle_external_event_callback(
FuriHalSpiBusHandle* handle,
FuriHalSpiBusHandleEvent event) {
furi_hal_spi_bus_r_handle_event_callback(handle, event, &furi_hal_spi_preset_1edge_low_2m);
}
FuriHalSpiBusHandle furi_hal_spi_bus_handle_external = {
.bus = &furi_hal_spi_bus_r,
.callback = furi_hal_spi_bus_handle_external_event_callback,
.miso = &gpio_ext_pa6,
.mosi = &gpio_ext_pa7,
.sck = &gpio_ext_pb3,
.cs = &gpio_ext_pa4,
};
inline static void furi_hal_spi_bus_d_handle_event_callback(
FuriHalSpiBusHandle* handle,
FuriHalSpiBusHandleEvent event,
const LL_SPI_InitTypeDef* preset) {
if(event == FuriHalSpiBusHandleEventInit) {
hal_gpio_write(handle->cs, true);
hal_gpio_init(handle->cs, GpioModeOutputPushPull, GpioPullUp, GpioSpeedVeryHigh);
hal_gpio_init_ex(
handle->miso,
GpioModeAltFunctionPushPull,
GpioPullNo,
GpioSpeedVeryHigh,
GpioAltFn5SPI2);
hal_gpio_init_ex(
handle->mosi,
GpioModeAltFunctionPushPull,
GpioPullNo,
GpioSpeedVeryHigh,
GpioAltFn5SPI2);
hal_gpio_init_ex(
handle->sck,
GpioModeAltFunctionPushPull,
GpioPullNo,
GpioSpeedVeryHigh,
GpioAltFn5SPI2);
} else if(event == FuriHalSpiBusHandleEventDeinit) {
hal_gpio_write(handle->cs, true);
hal_gpio_init(handle->cs, GpioModeAnalog, GpioPullUp, GpioSpeedLow);
} else if(event == FuriHalSpiBusHandleEventActivate) {
LL_SPI_Init(handle->bus->spi, (LL_SPI_InitTypeDef*)preset);
LL_SPI_SetRxFIFOThreshold(handle->bus->spi, LL_SPI_RX_FIFO_TH_QUARTER);
LL_SPI_Enable(handle->bus->spi);
hal_gpio_write(handle->cs, false);
} else if(event == FuriHalSpiBusHandleEventDeactivate) {
hal_gpio_write(handle->cs, true);
LL_SPI_Disable(handle->bus->spi);
}
}
static void furi_hal_spi_bus_handle_display_event_callback(
FuriHalSpiBusHandle* handle,
FuriHalSpiBusHandleEvent event) {
furi_hal_spi_bus_d_handle_event_callback(handle, event, &furi_hal_spi_preset_1edge_low_4m);
}
FuriHalSpiBusHandle furi_hal_spi_bus_handle_display = {
.bus = &furi_hal_spi_bus_d,
.callback = furi_hal_spi_bus_handle_display_event_callback,
.miso = &gpio_spi_d_miso,
.mosi = &gpio_spi_d_mosi,
.sck = &gpio_spi_d_sck,
.cs = &gpio_display_cs,
};
static void furi_hal_spi_bus_handle_sd_fast_event_callback(
FuriHalSpiBusHandle* handle,
FuriHalSpiBusHandleEvent event) {
furi_hal_spi_bus_d_handle_event_callback(handle, event, &furi_hal_spi_preset_1edge_low_16m);
}
FuriHalSpiBusHandle furi_hal_spi_bus_handle_sd_fast = {
.bus = &furi_hal_spi_bus_d,
.callback = furi_hal_spi_bus_handle_sd_fast_event_callback,
.miso = &gpio_spi_d_miso,
.mosi = &gpio_spi_d_mosi,
.sck = &gpio_spi_d_sck,
.cs = &gpio_sdcard_cs,
};
static void furi_hal_spi_bus_handle_sd_slow_event_callback(
FuriHalSpiBusHandle* handle,
FuriHalSpiBusHandleEvent event) {
furi_hal_spi_bus_d_handle_event_callback(handle, event, &furi_hal_spi_preset_1edge_low_2m);
}
FuriHalSpiBusHandle furi_hal_spi_bus_handle_sd_slow = {
.bus = &furi_hal_spi_bus_d,
.callback = furi_hal_spi_bus_handle_sd_slow_event_callback,
.miso = &gpio_spi_d_miso,
.mosi = &gpio_spi_d_mosi,
.sck = &gpio_spi_d_sck,
.cs = &gpio_sdcard_cs,
};

View File

@@ -1,61 +0,0 @@
#pragma once
#include <furi_hal_spi_types.h>
#ifdef __cplusplus
extern "C" {
#endif
/** Preset for ST25R916 */
extern const LL_SPI_InitTypeDef furi_hal_spi_preset_2edge_low_8m;
/** Preset for CC1101 */
extern const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_8m;
/** Preset for ST7567 (Display) */
extern const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_4m;
/** Preset for SdCard in fast mode */
extern const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_16m;
/** Preset for SdCard in slow mode */
extern const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_2m;
/** Furi Hal Spi Bus R (Radio: CC1101, Nfc, External)*/
extern FuriHalSpiBus furi_hal_spi_bus_r;
/** Furi Hal Spi Bus D (Display, SdCard) */
extern FuriHalSpiBus furi_hal_spi_bus_d;
/** CC1101 on `furi_hal_spi_bus_r` */
extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_subghz;
/** ST25R3916 on `furi_hal_spi_bus_r` */
extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_nfc;
/** External on `furi_hal_spi_bus_r`
* Preset: `furi_hal_spi_preset_1edge_low_2m`
*
* miso: pa6
* mosi: pa7
* sck: pb3
* cs: pa4 (software controlled)
*
* @warning not initialized by default, call `furi_hal_spi_bus_handle_init` to initialize
* Bus pins are floating on inactive state, CS high after initialization
*
*/
extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_external;
/** ST7567(Display) on `furi_hal_spi_bus_d` */
extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_display;
/** SdCard in fast mode on `furi_hal_spi_bus_d` */
extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_sd_fast;
/** SdCard in slow mode on `furi_hal_spi_bus_d` */
extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_sd_slow;
#ifdef __cplusplus
}
#endif

View File

@@ -1,64 +0,0 @@
#pragma once
#include <stdint.h>
#include <stddef.h>
#include <furi_hal_gpio.h>
#include <stm32wbxx_ll_spi.h>
#include <stm32wbxx_ll_rcc.h>
#include <stm32wbxx_ll_bus.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct FuriHalSpiBus FuriHalSpiBus;
typedef struct FuriHalSpiBusHandle FuriHalSpiBusHandle;
/** FuriHal spi bus states */
typedef enum {
FuriHalSpiBusEventInit, /**< Bus initialization event, called on system start */
FuriHalSpiBusEventDeinit, /**< Bus deinitialization event, called on system stop */
FuriHalSpiBusEventLock, /**< Bus lock event, called before activation */
FuriHalSpiBusEventUnlock, /**< Bus unlock event, called after deactivation */
FuriHalSpiBusEventActivate, /**< Bus activation event, called before handle activation */
FuriHalSpiBusEventDeactivate, /**< Bus deactivation event, called after handle deactivation */
} FuriHalSpiBusEvent;
/** FuriHal spi bus event callback */
typedef void (*FuriHalSpiBusEventCallback)(FuriHalSpiBus* bus, FuriHalSpiBusEvent event);
/** FuriHal spi bus */
struct FuriHalSpiBus {
SPI_TypeDef* spi;
FuriHalSpiBusEventCallback callback;
FuriHalSpiBusHandle* current_handle;
};
/** FuriHal spi handle states */
typedef enum {
FuriHalSpiBusHandleEventInit, /**< Handle init, called on system start, initialize gpio for idle state */
FuriHalSpiBusHandleEventDeinit, /**< Handle deinit, called on system stop, deinitialize gpio for default state */
FuriHalSpiBusHandleEventActivate, /**< Handle activate: connect gpio and apply bus config */
FuriHalSpiBusHandleEventDeactivate, /**< Handle deactivate: disconnect gpio and reset bus config */
} FuriHalSpiBusHandleEvent;
/** FuriHal spi handle event callback */
typedef void (*FuriHalSpiBusHandleEventCallback)(
FuriHalSpiBusHandle* handle,
FuriHalSpiBusHandleEvent event);
/** FuriHal spi handle */
struct FuriHalSpiBusHandle {
FuriHalSpiBus* bus;
FuriHalSpiBusHandleEventCallback callback;
const GpioPin* miso;
const GpioPin* mosi;
const GpioPin* sck;
const GpioPin* cs;
};
#ifdef __cplusplus
}
#endif

View File

@@ -1,268 +0,0 @@
#include <furi_hal_version.h>
#include <stm32wbxx.h>
#include <stm32wbxx_ll_rtc.h>
#include <stm32wbxx_ll_system.h>
#include <stdio.h>
#define FURI_HAL_VERSION_OTP_HEADER_MAGIC 0xBABE
#define FURI_HAL_VERSION_OTP_ADDRESS OTP_AREA_BASE
/** OTP V0 Structure: prototypes and early EVT */
typedef struct {
uint8_t board_version;
uint8_t board_target;
uint8_t board_body;
uint8_t board_connect;
uint32_t header_timestamp;
char name[FURI_HAL_VERSION_NAME_LENGTH];
} FuriHalVersionOTPv0;
/** OTP V1 Structure: late EVT, DVT */
typedef struct {
/* First 64 bits: header */
uint16_t header_magic;
uint8_t header_version;
uint8_t header_reserved;
uint32_t header_timestamp;
/* Second 64 bits: board info */
uint8_t board_version; /** Board version */
uint8_t board_target; /** Board target firmware */
uint8_t board_body; /** Board body */
uint8_t board_connect; /** Board interconnect */
uint8_t board_color; /** Board color */
uint8_t board_region; /** Board region */
uint16_t board_reserved; /** Reserved for future use, 0x0000 */
/* Third 64 bits: Unique Device Name */
char name[FURI_HAL_VERSION_NAME_LENGTH]; /** Unique Device Name */
} FuriHalVersionOTPv1;
/** OTP V2 Structure: DVT2, PVT, Production */
typedef struct {
/* Early First 64 bits: header */
uint16_t header_magic;
uint8_t header_version;
uint8_t header_reserved;
uint32_t header_timestamp;
/* Early Second 64 bits: board info */
uint8_t board_version; /** Board version */
uint8_t board_target; /** Board target firmware */
uint8_t board_body; /** Board body */
uint8_t board_connect; /** Board interconnect */
uint8_t board_display; /** Board display */
uint8_t board_reserved2_0; /** Reserved for future use, 0x00 */
uint16_t board_reserved2_1; /** Reserved for future use, 0x0000 */
/* Late Third 64 bits: device info */
uint8_t board_color; /** Board color */
uint8_t board_region; /** Board region */
uint16_t board_reserved3_0; /** Reserved for future use, 0x0000 */
uint32_t board_reserved3_1; /** Reserved for future use, 0x00000000 */
/* Late Fourth 64 bits: Unique Device Name */
char name[FURI_HAL_VERSION_NAME_LENGTH]; /** Unique Device Name */
} FuriHalVersionOTPv2;
/** Represenation Model: */
typedef struct {
uint32_t timestamp;
uint8_t board_version; /** Board version */
uint8_t board_target; /** Board target firmware */
uint8_t board_body; /** Board body */
uint8_t board_connect; /** Board interconnect */
uint8_t board_color; /** Board color */
uint8_t board_region; /** Board region */
uint8_t board_display; /** Board display */
char name[FURI_HAL_VERSION_ARRAY_NAME_LENGTH]; /** \0 terminated name */
char device_name[FURI_HAL_VERSION_DEVICE_NAME_LENGTH]; /** device name for special needs */
uint8_t ble_mac[6];
} FuriHalVersion;
static FuriHalVersion furi_hal_version = {0};
static void furi_hal_version_set_name(const char* name) {
furi_hal_version.device_name[0] = 0;
}
static void furi_hal_version_load_otp_default() {
furi_hal_version_set_name(NULL);
}
static void furi_hal_version_load_otp_v0() {
const FuriHalVersionOTPv0* otp = (FuriHalVersionOTPv0*)FURI_HAL_VERSION_OTP_ADDRESS;
furi_hal_version.timestamp = otp->header_timestamp;
furi_hal_version.board_version = otp->board_version;
furi_hal_version.board_target = otp->board_target;
furi_hal_version.board_body = otp->board_body;
furi_hal_version.board_connect = otp->board_connect;
furi_hal_version_set_name(otp->name);
}
static void furi_hal_version_load_otp_v1() {
const FuriHalVersionOTPv1* otp = (FuriHalVersionOTPv1*)FURI_HAL_VERSION_OTP_ADDRESS;
furi_hal_version.timestamp = otp->header_timestamp;
furi_hal_version.board_version = otp->board_version;
furi_hal_version.board_target = otp->board_target;
furi_hal_version.board_body = otp->board_body;
furi_hal_version.board_connect = otp->board_connect;
furi_hal_version.board_color = otp->board_color;
furi_hal_version.board_region = otp->board_region;
furi_hal_version_set_name(otp->name);
}
static void furi_hal_version_load_otp_v2() {
const FuriHalVersionOTPv2* otp = (FuriHalVersionOTPv2*)FURI_HAL_VERSION_OTP_ADDRESS;
// 1st block, programmed afer baking
furi_hal_version.timestamp = otp->header_timestamp;
// 2nd block, programmed afer baking
furi_hal_version.board_version = otp->board_version;
furi_hal_version.board_target = otp->board_target;
furi_hal_version.board_body = otp->board_body;
furi_hal_version.board_connect = otp->board_connect;
furi_hal_version.board_display = otp->board_display;
// 3rd and 4th blocks, programmed on FATP stage
if(otp->board_color != 0xFF) {
furi_hal_version.board_color = otp->board_color;
furi_hal_version.board_region = otp->board_region;
furi_hal_version_set_name(otp->name);
} else {
furi_hal_version.board_color = 0;
furi_hal_version.board_region = 0;
furi_hal_version_set_name(NULL);
}
}
void furi_hal_version_init() {
switch(furi_hal_version_get_otp_version()) {
case FuriHalVersionOtpVersionUnknown:
furi_hal_version_load_otp_default();
break;
case FuriHalVersionOtpVersionEmpty:
furi_hal_version_load_otp_default();
break;
case FuriHalVersionOtpVersion0:
furi_hal_version_load_otp_v0();
break;
case FuriHalVersionOtpVersion1:
furi_hal_version_load_otp_v1();
break;
case FuriHalVersionOtpVersion2:
furi_hal_version_load_otp_v2();
break;
default:
furi_hal_version_load_otp_default();
}
}
bool furi_hal_version_do_i_belong_here() {
return furi_hal_version_get_hw_target() == 7;
}
const char* furi_hal_version_get_model_name() {
return "Flipper Zero";
}
const FuriHalVersionOtpVersion furi_hal_version_get_otp_version() {
if(*(uint64_t*)FURI_HAL_VERSION_OTP_ADDRESS == 0xFFFFFFFF) {
return FuriHalVersionOtpVersionEmpty;
} else {
if(((FuriHalVersionOTPv1*)FURI_HAL_VERSION_OTP_ADDRESS)->header_magic ==
FURI_HAL_VERSION_OTP_HEADER_MAGIC) {
// Version 1+
uint8_t version = ((FuriHalVersionOTPv1*)FURI_HAL_VERSION_OTP_ADDRESS)->header_version;
if(version >= FuriHalVersionOtpVersion1 && version <= FuriHalVersionOtpVersion2) {
return version;
} else {
return FuriHalVersionOtpVersionUnknown;
}
} else if(((FuriHalVersionOTPv0*)FURI_HAL_VERSION_OTP_ADDRESS)->board_version <= 10) {
// Version 0
return FuriHalVersionOtpVersion0;
} else {
// Version Unknown
return FuriHalVersionOtpVersionUnknown;
}
}
}
const uint8_t furi_hal_version_get_hw_version() {
return furi_hal_version.board_version;
}
const uint8_t furi_hal_version_get_hw_target() {
return furi_hal_version.board_target;
}
const uint8_t furi_hal_version_get_hw_body() {
return furi_hal_version.board_body;
}
const FuriHalVersionColor furi_hal_version_get_hw_color() {
return furi_hal_version.board_color;
}
const uint8_t furi_hal_version_get_hw_connect() {
return furi_hal_version.board_connect;
}
const FuriHalVersionRegion furi_hal_version_get_hw_region() {
return furi_hal_version.board_region;
}
const FuriHalVersionDisplay furi_hal_version_get_hw_display() {
return furi_hal_version.board_display;
}
const uint32_t furi_hal_version_get_hw_timestamp() {
return furi_hal_version.timestamp;
}
const char* furi_hal_version_get_name_ptr() {
return *furi_hal_version.name == 0x00 ? NULL : furi_hal_version.name;
}
const char* furi_hal_version_get_device_name_ptr() {
return furi_hal_version.device_name + 1;
}
const char* furi_hal_version_get_ble_local_device_name_ptr() {
return furi_hal_version.device_name;
}
const uint8_t* furi_hal_version_get_ble_mac() {
return furi_hal_version.ble_mac;
}
const struct Version* furi_hal_version_get_firmware_version(void) {
return version_get();
}
const struct Version* furi_hal_version_get_bootloader_version(void) {
#ifdef NO_BOOTLOADER
return 0;
#else
/* Backup register which points to structure in flash memory */
return (const struct Version*)LL_RTC_BAK_GetRegister(RTC, LL_RTC_BKP_DR1);
#endif
}
size_t furi_hal_version_uid_size() {
return 64 / 8;
}
const uint8_t* furi_hal_version_uid() {
return (const uint8_t*)UID64_BASE;
}

View File

@@ -1,108 +0,0 @@
#pragma once
#include <stm32wbxx.h>
#include <stm32wbxx_ll_gpio.h>
#include <stm32wbxx_ll_spi.h>
#define BUTTON_BACK_GPIO_Port GPIOC
#define BUTTON_BACK_Pin LL_GPIO_PIN_13
#define BUTTON_DOWN_GPIO_Port GPIOC
#define BUTTON_DOWN_Pin LL_GPIO_PIN_6
#define BUTTON_LEFT_GPIO_Port GPIOB
#define BUTTON_LEFT_Pin LL_GPIO_PIN_11
#define BUTTON_OK_GPIO_Port GPIOH
#define BUTTON_OK_Pin LL_GPIO_PIN_3
#define BUTTON_RIGHT_GPIO_Port GPIOB
#define BUTTON_RIGHT_Pin LL_GPIO_PIN_12
#define BUTTON_UP_GPIO_Port GPIOB
#define BUTTON_UP_Pin LL_GPIO_PIN_10
#define CC1101_CS_GPIO_Port GPIOD
#define CC1101_CS_Pin LL_GPIO_PIN_0
#define CC1101_G0_GPIO_Port GPIOA
#define CC1101_G0_Pin LL_GPIO_PIN_1
#define DISPLAY_CS_GPIO_Port GPIOC
#define DISPLAY_CS_Pin LL_GPIO_PIN_11
#define DISPLAY_DI_GPIO_Port GPIOB
#define DISPLAY_DI_Pin LL_GPIO_PIN_1
#define DISPLAY_RST_GPIO_Port GPIOB
#define DISPLAY_RST_Pin LL_GPIO_PIN_0
#define IR_RX_GPIO_Port GPIOA
#define IR_RX_Pin LL_GPIO_PIN_0
#define IR_TX_GPIO_Port GPIOB
#define IR_TX_Pin LL_GPIO_PIN_9
#define NFC_CS_GPIO_Port GPIOE
#define NFC_CS_Pin LL_GPIO_PIN_4
#define PA4_GPIO_Port GPIOA
#define PA4_Pin LL_GPIO_PIN_4
#define PA6_GPIO_Port GPIOA
#define PA6_Pin LL_GPIO_PIN_6
#define PA7_GPIO_Port GPIOA
#define PA7_Pin LL_GPIO_PIN_7
#define PB2_GPIO_Port GPIOB
#define PB2_Pin LL_GPIO_PIN_2
#define PB3_GPIO_Port GPIOB
#define PB3_Pin LL_GPIO_PIN_3
#define PC0_GPIO_Port GPIOC
#define PC0_Pin LL_GPIO_PIN_0
#define PC1_GPIO_Port GPIOC
#define PC1_Pin LL_GPIO_PIN_1
#define PC3_GPIO_Port GPIOC
#define PC3_Pin LL_GPIO_PIN_3
#define PERIPH_POWER_GPIO_Port GPIOA
#define PERIPH_POWER_Pin LL_GPIO_PIN_3
#define QUARTZ_32MHZ_IN_GPIO_Port GPIOC
#define QUARTZ_32MHZ_IN_Pin LL_GPIO_PIN_14
#define QUARTZ_32MHZ_OUT_GPIO_Port GPIOC
#define QUARTZ_32MHZ_OUT_Pin LL_GPIO_PIN_15
#define RFID_OUT_GPIO_Port GPIOB
#define RFID_OUT_Pin LL_GPIO_PIN_13
#define RFID_PULL_GPIO_Port GPIOA
#define RFID_PULL_Pin LL_GPIO_PIN_2
#define RFID_RF_IN_GPIO_Port GPIOC
#define RFID_RF_IN_Pin LL_GPIO_PIN_5
#define RFID_TUNE_GPIO_Port GPIOA
#define RFID_TUNE_Pin LL_GPIO_PIN_8
#define RF_SW_0_GPIO_Port GPIOC
#define RF_SW_0_Pin LL_GPIO_PIN_4
#define SD_CD_GPIO_Port GPIOC
#define SD_CD_Pin LL_GPIO_PIN_10
#define SD_CS_GPIO_Port GPIOC
#define SD_CS_Pin LL_GPIO_PIN_12
#define SPEAKER_GPIO_Port GPIOB
#define SPEAKER_Pin LL_GPIO_PIN_8
#define VIBRO_GPIO_Port GPIOA
#define VIBRO_Pin LL_GPIO_PIN_15
#define iBTN_GPIO_Port GPIOB
#define iBTN_Pin LL_GPIO_PIN_14
#define USART1_TX_Pin LL_GPIO_PIN_6
#define USART1_TX_Port GPIOB
#define USART1_RX_Pin LL_GPIO_PIN_7
#define USART1_RX_Port GPIOB
#define SPI_D_MISO_GPIO_Port GPIOC
#define SPI_D_MISO_Pin LL_GPIO_PIN_2
#define SPI_D_MOSI_GPIO_Port GPIOB
#define SPI_D_MOSI_Pin LL_GPIO_PIN_15
#define SPI_D_SCK_GPIO_Port GPIOD
#define SPI_D_SCK_Pin LL_GPIO_PIN_1
#define SPI_R_MISO_GPIO_Port GPIOB
#define SPI_R_MISO_Pin LL_GPIO_PIN_4
#define SPI_R_MOSI_GPIO_Port GPIOB
#define SPI_R_MOSI_Pin LL_GPIO_PIN_5
#define SPI_R_SCK_GPIO_Port GPIOA
#define SPI_R_SCK_Pin LL_GPIO_PIN_5

View File

@@ -1,187 +0,0 @@
/**
*****************************************************************************
**
** File : stm32wb55xx_flash_cm4.ld
**
** Abstract : System Workbench Minimal System calls file
**
** For more information about which c-functions
** need which of these lowlevel functions
** please consult the Newlib libc-manual
**
** Environment : System Workbench for MCU
**
** Distribution: The file is distributed “as is,” without any warranty
** of any kind.
**
*****************************************************************************
**
** <h2><center>&copy; COPYRIGHT(c) 2019 Ac6</center></h2>
**
** Redistribution and use in source and binary forms, with or without modification,
** are permitted provided that the following conditions are met:
** 1. Redistributions of source code must retain the above copyright notice,
** this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright notice,
** this list of conditions and the following disclaimer in the documentation
** and/or other materials provided with the distribution.
** 3. Neither the name of Ac6 nor the names of its contributors
** may be used to endorse or promote products derived from this software
** without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
** DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
*****************************************************************************
*/
/* Entry Point */
ENTRY(Reset_Handler)
/* Highest address of the user mode stack */
_estack = 0x20030000; /* end of RAM */
/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 0x200; /* required amount of heap */
_Min_Stack_Size = 0x400; /* required amount of stack */
/* Specify the memory areas */
MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 32K
RAM1 (xrw) : ORIGIN = 0x20000008, LENGTH = 0x2FFF8
RAM_SHARED (xrw) : ORIGIN = 0x20030000, LENGTH = 10K
}
/* Define output sections */
SECTIONS
{
/* The startup code goes first into FLASH */
.isr_vector :
{
. = ALIGN(4);
KEEP(*(.isr_vector)) /* Startup code */
. = ALIGN(4);
} >FLASH
/* The program code and other data goes into FLASH */
.text :
{
. = ALIGN(4);
*(.text) /* .text sections (code) */
*(.text*) /* .text* sections (code) */
*(.glue_7) /* glue arm to thumb code */
*(.glue_7t) /* glue thumb to arm code */
*(.eh_frame)
KEEP (*(.init))
KEEP (*(.fini))
. = ALIGN(4);
_etext = .; /* define a global symbols at end of code */
} >FLASH
/* Constant data goes into FLASH */
.rodata :
{
. = ALIGN(4);
*(.rodata) /* .rodata sections (constants, strings, etc.) */
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
. = ALIGN(4);
} >FLASH
.ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH
.ARM : {
__exidx_start = .;
*(.ARM.exidx*)
__exidx_end = .;
} >FLASH
.preinit_array :
{
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array*))
PROVIDE_HIDDEN (__preinit_array_end = .);
} >FLASH
.init_array :
{
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array*))
PROVIDE_HIDDEN (__init_array_end = .);
} >FLASH
.fini_array :
{
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(SORT(.fini_array.*)))
KEEP (*(.fini_array*))
PROVIDE_HIDDEN (__fini_array_end = .);
} >FLASH
/* used by the startup to initialize data */
_sidata = LOADADDR(.data);
/* Initialized data sections goes into RAM, load LMA copy after code */
.data :
{
. = ALIGN(4);
_sdata = .; /* create a global symbol at data start */
*(.data) /* .data sections */
*(.data*) /* .data* sections */
. = ALIGN(4);
_edata = .; /* define a global symbol at data end */
} >RAM1 AT> FLASH
/* Uninitialized data section */
. = ALIGN(4);
.bss :
{
/* This is used by the startup in order to initialize the .bss secion */
_sbss = .; /* define a global symbol at bss start */
__bss_start__ = _sbss;
*(.bss)
*(.bss*)
*(COMMON)
. = ALIGN(4);
_ebss = .; /* define a global symbol at bss end */
__bss_end__ = _ebss;
} >RAM1
/* User_heap_stack section, used to check that there is enough RAM left */
._user_heap_stack :
{
. = ALIGN(8);
PROVIDE ( end = . );
PROVIDE ( _end = . );
. = . + _Min_Heap_Size;
. = . + _Min_Stack_Size;
. = ALIGN(8);
} >RAM1
/* Remove information from the standard libraries */
/DISCARD/ :
{
libc.a ( * )
libm.a ( * )
libgcc.a ( * )
}
.ARM.attributes 0 : { *(.ARM.attributes) }
MAPPING_TABLE (NOLOAD) : { *(MAPPING_TABLE) } >RAM_SHARED
MB_MEM1 (NOLOAD) : { *(MB_MEM1) } >RAM_SHARED
MB_MEM2 (NOLOAD) : { _sMB_MEM2 = . ; *(MB_MEM2) ; _eMB_MEM2 = . ; } >RAM_SHARED
}

View File

@@ -1,264 +0,0 @@
#include <target.h>
#include <stm32wbxx.h>
#include <stm32wbxx_ll_system.h>
#include <stm32wbxx_ll_bus.h>
#include <stm32wbxx_ll_utils.h>
#include <stm32wbxx_ll_rcc.h>
#include <stm32wbxx_ll_rtc.h>
#include <stm32wbxx_ll_pwr.h>
#include <stm32wbxx_ll_gpio.h>
#include <stm32wbxx_hal_flash.h>
#include <lib/toolbox/version.h>
#include <furi_hal.h>
#include <u8g2.h>
#include <u8g2_glue.h>
const uint8_t I_DFU_128x50[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x07, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x38, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0xC0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8F, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x7F, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x75, 0x00, 0x00, 0xF0, 0x3F, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0x0A, 0x00, 0x00, 0x0F, 0x60, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0xE0, 0x0F, 0x00, 0xC0, 0xE0, 0x4F, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x18, 0x00, 0x30, 0x1E, 0x90, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x18, 0x00, 0x8C, 0x01, 0xA0, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x81, 0xFF, 0x19, 0x00, 0x63, 0x00, 0xC0, 0xF0, 0x07,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x60, 0x5E, 0x1F, 0x80, 0x18, 0x00, 0xE0, 0x0E, 0x18,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x18, 0xAF, 0x0F, 0x40, 0x06, 0x00, 0xF8, 0x01, 0x20,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x06, 0x57, 0x01, 0x20, 0x01, 0x00, 0x78, 0x00, 0x3E,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x81, 0xAF, 0x02, 0x90, 0x00, 0x00, 0x38, 0x80, 0x41,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x80, 0x57, 0x01, 0x48, 0x00, 0x00, 0x10, 0x60, 0x40,
0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x10, 0x80, 0xAB, 0x00, 0x24, 0x00, 0x00, 0x08, 0x10, 0x40,
0x3F, 0x00, 0x00, 0x00, 0x00, 0x38, 0x0C, 0xC0, 0x57, 0x01, 0x12, 0x00, 0x00, 0x04, 0x08, 0x40,
0xC0, 0x0F, 0x00, 0x00, 0xC0, 0x07, 0x03, 0xF0, 0xAB, 0x00, 0x0A, 0x00, 0x00, 0x02, 0x04, 0x40,
0x00, 0xF0, 0x1F, 0x80, 0x3F, 0xC0, 0x00, 0xFC, 0x55, 0x01, 0x05, 0xE0, 0x00, 0x01, 0x04, 0x40,
0x00, 0x00, 0xE0, 0x7F, 0x00, 0x30, 0x00, 0xFF, 0xAB, 0x00, 0x05, 0xE0, 0x80, 0x00, 0x02, 0x40,
0x0F, 0x00, 0x00, 0x00, 0x80, 0x0F, 0xE0, 0xCF, 0x55, 0x81, 0x02, 0xF0, 0x40, 0x00, 0x02, 0x40,
0xF0, 0x0F, 0x00, 0x00, 0x7F, 0x00, 0xFE, 0xC3, 0xAB, 0x80, 0x02, 0x78, 0x20, 0x00, 0x01, 0x40,
0x00, 0xF0, 0xFF, 0xFF, 0x00, 0xF0, 0xFF, 0xC0, 0xD5, 0x81, 0x01, 0x7E, 0x10, 0x80, 0x00, 0x20,
0x00, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0x0F, 0xE0, 0xFA, 0x83, 0xC1, 0x3F, 0x08, 0x80, 0x00, 0x20,
0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x01, 0xD8, 0x07, 0x83, 0xF1, 0x1F, 0x04, 0x40, 0x00, 0x20,
0x00, 0xE0, 0xFF, 0xFF, 0xFF, 0x0F, 0x80, 0xC7, 0x01, 0x83, 0xF1, 0x0F, 0x00, 0x20, 0x00, 0x10,
0xE0, 0xFF, 0xFF, 0xFF, 0x3F, 0xC0, 0x7F, 0x40, 0x80, 0x83, 0xE1, 0x01, 0x00, 0x20, 0x00, 0x18,
0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x3F, 0x00, 0x20, 0xFC, 0x83, 0x01, 0x00, 0x00, 0x10, 0x00, 0x18,
0xFF, 0xFF, 0xFF, 0x3F, 0xF0, 0x00, 0x00, 0x10, 0xD7, 0x01, 0x03, 0x00, 0x00, 0x08, 0x00, 0x1C,
0xFF, 0xFF, 0x01, 0x00, 0x0F, 0x00, 0x00, 0x88, 0xAB, 0x02, 0xE3, 0x01, 0x00, 0x08, 0x00, 0x0C,
0xFF, 0x07, 0x00, 0xE0, 0x00, 0x00, 0x00, 0xC4, 0x55, 0x05, 0x1E, 0x00, 0x00, 0x04, 0x00, 0x0E,
0x7F, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0xA3, 0xAB, 0x02, 0x06, 0x00, 0x00, 0x02, 0x00, 0x0F,
0x0F, 0x00, 0x80, 0x03, 0x00, 0x00, 0xC0, 0x10, 0x57, 0x05, 0x02, 0x00, 0x00, 0x01, 0x80, 0x07,
0x03, 0x00, 0x70, 0x00, 0x00, 0x00, 0x30, 0x08, 0xAB, 0x0A, 0x02, 0x00, 0xC0, 0x00, 0xC0, 0x07,
0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x0C, 0x84, 0x57, 0x15, 0x01, 0x00, 0x30, 0x00, 0xE0, 0x07,
0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0xC3, 0xFF, 0x2A, 0x01, 0x00, 0x0C, 0x00, 0xF0, 0x0F,
0x00, 0xC0, 0x00, 0x00, 0x00, 0xE0, 0xC0, 0xE0, 0xFE, 0x55, 0x01, 0x82, 0x03, 0x00, 0xF8, 0x15,
0x00, 0x30, 0x00, 0x00, 0x00, 0x1C, 0x30, 0x78, 0xFE, 0xAA, 0x01, 0x7C, 0x00, 0x00, 0xFC, 0x23,
0x00, 0x0E, 0x00, 0x00, 0xC0, 0x03, 0x0C, 0x3C, 0x7F, 0x5D, 0x01, 0x00, 0x00, 0x00, 0xFF, 0x45,
0xC0, 0x01, 0x00, 0x00, 0x3E, 0x00, 0x02, 0x8F, 0xBF, 0xAE, 0x03, 0x00, 0x00, 0xC0, 0xFF, 0x82,
0x30, 0x00, 0x00, 0xC0, 0x01, 0x80, 0xC1, 0x43, 0xFE, 0x5D, 0x01, 0x00, 0x00, 0xF0, 0xFF, 0x05,
0x0F, 0x00, 0x80, 0x3F, 0x00, 0x60, 0xF0, 0x31, 0xF6, 0xAE, 0x03, 0x00, 0x00, 0xFA, 0xAF, 0x02,
0xFC, 0xFF, 0x7F, 0x00, 0x00, 0x18, 0x7C, 0x08, 0x23, 0xFF, 0x05, 0x00, 0x00, 0xFD, 0x55, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0x1F, 0x84, 0x30, 0xFE, 0x0A, 0x00, 0x00, 0xAA, 0xAA, 0x00,
0x00, 0x00, 0x00, 0x00, 0x80, 0xF1, 0x07, 0x43, 0x18, 0xFF, 0x15, 0x00, 0x00, 0x54, 0x15, 0x00,
0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0x80, 0x20, 0x8C, 0xFF, 0xAA, 0x00, 0x00, 0x00, 0x00, 0x00,
};
// Boot request enum
#define BOOT_REQUEST_TAINTED 0x00000000
#define BOOT_REQUEST_CLEAN 0xDADEDADE
#define BOOT_REQUEST_DFU 0xDF00B000
// Boot to DFU pin
#define BOOT_DFU_PORT GPIOB
#define BOOT_DFU_PIN LL_GPIO_PIN_11
// USB pins
#define BOOT_USB_PORT GPIOA
#define BOOT_USB_DM_PIN LL_GPIO_PIN_11
#define BOOT_USB_DP_PIN LL_GPIO_PIN_12
#define BOOT_USB_PIN (BOOT_USB_DM_PIN | BOOT_USB_DP_PIN)
#define RTC_CLOCK_IS_READY() (LL_RCC_LSE_IsReady() && LL_RCC_LSI1_IsReady())
void target_led_control(char* c) {
furi_hal_light_set(LightRed, 0x00);
furi_hal_light_set(LightGreen, 0x00);
furi_hal_light_set(LightBlue, 0x00);
do {
if(*c == 'R') {
furi_hal_light_set(LightRed, 0xFF);
} else if(*c == 'G') {
furi_hal_light_set(LightGreen, 0xFF);
} else if(*c == 'B') {
furi_hal_light_set(LightBlue, 0xFF);
} else if(*c == '.') {
LL_mDelay(125);
furi_hal_light_set(LightRed, 0x00);
furi_hal_light_set(LightGreen, 0x00);
furi_hal_light_set(LightBlue, 0x00);
LL_mDelay(125);
} else if(*c == '-') {
LL_mDelay(250);
furi_hal_light_set(LightRed, 0x00);
furi_hal_light_set(LightGreen, 0x00);
furi_hal_light_set(LightBlue, 0x00);
LL_mDelay(250);
} else if(*c == '|') {
furi_hal_light_set(LightRed, 0x00);
furi_hal_light_set(LightGreen, 0x00);
furi_hal_light_set(LightBlue, 0x00);
}
c++;
} while(*c != 0);
}
void target_clock_init() {
LL_Init1msTick(4000000);
LL_SetSystemCoreClock(4000000);
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOA);
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOB);
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOC);
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOD);
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOE);
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOH);
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SPI1);
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_SPI2);
}
void target_gpio_init() {
// USB D+
LL_GPIO_SetPinMode(BOOT_USB_PORT, BOOT_USB_DP_PIN, LL_GPIO_MODE_OUTPUT);
LL_GPIO_SetPinSpeed(BOOT_USB_PORT, BOOT_USB_DP_PIN, LL_GPIO_SPEED_FREQ_VERY_HIGH);
LL_GPIO_SetPinOutputType(BOOT_USB_PORT, BOOT_USB_DP_PIN, LL_GPIO_OUTPUT_OPENDRAIN);
// USB D-
LL_GPIO_SetPinMode(BOOT_USB_PORT, BOOT_USB_DM_PIN, LL_GPIO_MODE_OUTPUT);
LL_GPIO_SetPinSpeed(BOOT_USB_PORT, BOOT_USB_DM_PIN, LL_GPIO_SPEED_FREQ_VERY_HIGH);
LL_GPIO_SetPinOutputType(BOOT_USB_PORT, BOOT_USB_DM_PIN, LL_GPIO_OUTPUT_OPENDRAIN);
// Button: back
LL_GPIO_SetPinMode(BOOT_DFU_PORT, BOOT_DFU_PIN, LL_GPIO_MODE_INPUT);
LL_GPIO_SetPinPull(BOOT_DFU_PORT, BOOT_DFU_PIN, LL_GPIO_PULL_UP);
}
void target_rtc_init() {
// LSE and RTC
LL_PWR_EnableBkUpAccess();
if(!RTC_CLOCK_IS_READY()) {
// Start LSI1 needed for CSS
LL_RCC_LSI1_Enable();
// Try to start LSE normal way
LL_RCC_LSE_SetDriveCapability(LL_RCC_LSEDRIVE_HIGH);
LL_RCC_LSE_Enable();
uint32_t c = 0;
while(!RTC_CLOCK_IS_READY() && c < 200) {
LL_mDelay(10);
c++;
}
// Plan B: reset backup domain
if(!RTC_CLOCK_IS_READY()) {
target_led_control("-R.R.R.");
LL_RCC_ForceBackupDomainReset();
LL_RCC_ReleaseBackupDomainReset();
NVIC_SystemReset();
}
// Set RTC domain clock to LSE
LL_RCC_SetRTCClockSource(LL_RCC_RTC_CLKSOURCE_LSE);
// Enable LSE CSS
LL_RCC_LSE_EnableCSS();
}
// Enable clocking
LL_RCC_EnableRTC();
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_RTCAPB);
}
void target_version_save(void) {
LL_RTC_BAK_SetRegister(RTC, LL_RTC_BKP_DR1, (uint32_t)version_get());
}
void target_usb_wire_reset() {
LL_GPIO_ResetOutputPin(BOOT_USB_PORT, BOOT_USB_PIN);
}
void target_display_init() {
// Prepare gpio
hal_gpio_init_simple(&gpio_display_rst, GpioModeOutputPushPull);
hal_gpio_init_simple(&gpio_display_di, GpioModeOutputPushPull);
// Initialize
u8g2_t fb;
u8g2_Setup_st756x_flipper(&fb, U8G2_R0, u8x8_hw_spi_stm32, u8g2_gpio_and_delay_stm32);
u8g2_InitDisplay(&fb);
// Create payload
u8g2_ClearBuffer(&fb);
u8g2_SetDrawColor(&fb, 0x01);
u8g2_DrawXBM(&fb, 0, 64 - 50, 128, 50, I_DFU_128x50);
#ifndef SLIM_BOOTLOADER
u8g2_SetFont(&fb, u8g2_font_helvB08_tf);
u8g2_DrawStr(&fb, 2, 8, "Update & Recovery Mode");
u8g2_DrawStr(&fb, 2, 21, "DFU started");
#endif
// Send buffer
u8g2_SetPowerSave(&fb, 0);
u8g2_SendBuffer(&fb);
}
void target_init() {
target_clock_init();
target_gpio_init();
furi_hal_init();
target_led_control("RGB");
target_rtc_init();
target_version_save();
target_usb_wire_reset();
// Errata 2.2.9, Flash OPTVERR flag is always set after system reset
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS);
}
int target_is_dfu_requested() {
if(LL_RTC_BAK_GetRegister(RTC, LL_RTC_BKP_DR0) == BOOT_REQUEST_TAINTED) {
// Default system state is tainted
// We must ensure that MCU is cleanly booted
LL_RTC_BAK_SetRegister(RTC, LL_RTC_BKP_DR0, BOOT_REQUEST_CLEAN);
NVIC_SystemReset();
} else if(LL_RTC_BAK_GetRegister(RTC, LL_RTC_BKP_DR0) == BOOT_REQUEST_DFU) {
return 1;
}
LL_mDelay(100);
if(!LL_GPIO_IsInputPinSet(BOOT_DFU_PORT, BOOT_DFU_PIN)) {
return 1;
}
return 0;
}
void target_switch(void* offset) {
asm volatile("ldr r3, [%0] \n"
"msr msp, r3 \n"
"ldr r3, [%1] \n"
"mov pc, r3 \n"
:
: "r"(offset), "r"(offset + 0x4)
: "r3");
}
void target_switch2dfu() {
target_led_control("B");
furi_hal_light_set(LightBacklight, 0xFF);
target_display_init();
// Mark system as tainted, it will be soon
LL_RTC_BAK_SetRegister(RTC, LL_RTC_BKP_DR0, BOOT_REQUEST_TAINTED);
// Remap memory to system bootloader
LL_SYSCFG_SetRemapMemory(LL_SYSCFG_REMAP_SYSTEMFLASH);
// Jump
target_switch(0x0);
}
void target_switch2os() {
target_led_control("G");
SCB->VTOR = OS_OFFSET;
target_switch((void*)(BOOT_ADDRESS + OS_OFFSET));
}

View File

@@ -1,50 +0,0 @@
TOOLCHAIN = arm
BOOT_ADDRESS = 0x08000000
FW_ADDRESS = 0x08008000
OS_OFFSET = 0x00008000
FLASH_ADDRESS = 0x08000000
OPENOCD_OPTS = -f interface/stlink.cfg -c "transport select hla_swd" -f ../debug/stm32wbx.cfg -c "init"
BOOT_CFLAGS = -DBOOT_ADDRESS=$(BOOT_ADDRESS) -DFW_ADDRESS=$(FW_ADDRESS) -DOS_OFFSET=$(OS_OFFSET)
MCU_FLAGS = -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard
CFLAGS += $(MCU_FLAGS) $(BOOT_CFLAGS) -DSTM32WB55xx -Wall -fdata-sections -ffunction-sections
LDFLAGS += $(MCU_FLAGS) -specs=nosys.specs -specs=nano.specs
HARDWARE_TARGET = 6
CUBE_DIR = $(PROJECT_ROOT)/lib/STM32CubeWB
# ST HAL
CFLAGS += -DUSE_FULL_LL_DRIVER
ASM_SOURCES += $(CUBE_DIR)/Drivers/CMSIS/Device/ST/STM32WBxx/Source/Templates/gcc/startup_stm32wb55xx_cm4.s
C_SOURCES += $(CUBE_DIR)/Drivers/CMSIS/Device/ST/STM32WBxx/Source/Templates/system_stm32wbxx.c
C_SOURCES += $(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_utils.c
C_SOURCES += $(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_gpio.c
C_SOURCES += $(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_i2c.c
C_SOURCES += $(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_spi.c
CFLAGS += -I$(CUBE_DIR)/Drivers/CMSIS/Include
CFLAGS += -I$(CUBE_DIR)/Drivers/CMSIS/Device/ST/STM32WBxx/Include
CFLAGS += -I$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Inc
LDFLAGS += -T$(TARGET_DIR)/stm32wb55xx_flash_cm4.ld
# Drivers
DRIVERS_DIR = $(PROJECT_ROOT)//lib/drivers
CFLAGS += -I$(DRIVERS_DIR)
C_SOURCES += $(DRIVERS_DIR)/lp5562.c
# API-HAL
CFLAGS += -I$(TARGET_DIR)/furi_hal
C_SOURCES += $(wildcard $(TARGET_DIR)/furi_hal/*.c)
# Version generation
C_SOURCES += $(PROJECT_ROOT)/lib/toolbox/version.c
ASM_SOURCES += $(wildcard $(TARGET_DIR)/*.s)
C_SOURCES += $(wildcard $(TARGET_DIR)/*.c)
CPP_SOURCES += $(wildcard $(TARGET_DIR)/*.cpp)
SVD_FILE = $(PROJECT_ROOT)/debug/STM32WB55_CM4.svd