* RFID: pull antenna down when emulating * Rfid: fixed HID emulation by adding zero pulse every 4 bits * Rfid: HID emulation fixed with DSP based FSK oscillator. * Rfid: receive 125KHz clock for emulation timer from antenna and comparator * Rfid: commented unused variable * Firmware: rollback changes in f6. * Add F7 target based on F6. * F7/F6: update cube projects, apply changes to the targets, update linker scripts with correct RAM start values. * FuriHal: RFID init routine. * Scripts: update OTP tool for v11 board Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
		
			
				
	
	
		
			241 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			241 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
#include "furi-hal-spi.h"
 | 
						|
#include "furi-hal-resources.h"
 | 
						|
 | 
						|
#include <stdbool.h>
 | 
						|
#include <assert.h>
 | 
						|
 | 
						|
#include <stm32wbxx_ll_spi.h>
 | 
						|
#include <stm32wbxx_ll_utils.h>
 | 
						|
#include <stm32wbxx_ll_cortex.h>
 | 
						|
 | 
						|
extern void Enable_SPI(SPI_TypeDef* spi);
 | 
						|
 | 
						|
void furi_hal_spi_init() {
 | 
						|
    for(size_t i = 0; i < FuriHalSpiDeviceIdMax; ++i) {
 | 
						|
        hal_gpio_write(furi_hal_spi_devices[i].chip_select, true);
 | 
						|
        hal_gpio_init(
 | 
						|
            furi_hal_spi_devices[i].chip_select,
 | 
						|
            GpioModeOutputPushPull,
 | 
						|
            GpioPullNo,
 | 
						|
            GpioSpeedVeryHigh);
 | 
						|
    }
 | 
						|
 | 
						|
    hal_gpio_init_ex(
 | 
						|
        &gpio_spi_r_miso,
 | 
						|
        GpioModeAltFunctionPushPull,
 | 
						|
        GpioPullNo,
 | 
						|
        GpioSpeedVeryHigh,
 | 
						|
        GpioAltFn5SPI1);
 | 
						|
    hal_gpio_init_ex(
 | 
						|
        &gpio_spi_r_mosi,
 | 
						|
        GpioModeAltFunctionPushPull,
 | 
						|
        GpioPullNo,
 | 
						|
        GpioSpeedVeryHigh,
 | 
						|
        GpioAltFn5SPI1);
 | 
						|
    hal_gpio_init_ex(
 | 
						|
        &gpio_spi_r_sck,
 | 
						|
        GpioModeAltFunctionPushPull,
 | 
						|
        GpioPullNo,
 | 
						|
        GpioSpeedVeryHigh,
 | 
						|
        GpioAltFn5SPI1);
 | 
						|
 | 
						|
    hal_gpio_init_ex(
 | 
						|
        &gpio_spi_d_miso,
 | 
						|
        GpioModeAltFunctionPushPull,
 | 
						|
        GpioPullUp,
 | 
						|
        GpioSpeedVeryHigh,
 | 
						|
        GpioAltFn5SPI2);
 | 
						|
    hal_gpio_init_ex(
 | 
						|
        &gpio_spi_d_mosi,
 | 
						|
        GpioModeAltFunctionPushPull,
 | 
						|
        GpioPullUp,
 | 
						|
        GpioSpeedVeryHigh,
 | 
						|
        GpioAltFn5SPI2);
 | 
						|
    hal_gpio_init_ex(
 | 
						|
        &gpio_spi_d_sck,
 | 
						|
        GpioModeAltFunctionPushPull,
 | 
						|
        GpioPullUp,
 | 
						|
        GpioSpeedVeryHigh,
 | 
						|
        GpioAltFn5SPI2);
 | 
						|
}
 | 
						|
 | 
						|
void furi_hal_spi_bus_lock(const FuriHalSpiBus* bus) {
 | 
						|
    assert(bus);
 | 
						|
}
 | 
						|
 | 
						|
void furi_hal_spi_bus_unlock(const FuriHalSpiBus* bus) {
 | 
						|
    assert(bus);
 | 
						|
}
 | 
						|
 | 
						|
void furi_hal_spi_bus_configure(const FuriHalSpiBus* bus, const LL_SPI_InitTypeDef* config) {
 | 
						|
    assert(bus);
 | 
						|
    LL_SPI_DeInit((SPI_TypeDef*)bus->spi);
 | 
						|
    LL_SPI_Init((SPI_TypeDef*)bus->spi, (LL_SPI_InitTypeDef*)config);
 | 
						|
    LL_SPI_SetRxFIFOThreshold((SPI_TypeDef*)bus->spi, LL_SPI_RX_FIFO_TH_QUARTER);
 | 
						|
    LL_SPI_Enable((SPI_TypeDef*)bus->spi);
 | 
						|
}
 | 
						|
 | 
						|
void furi_hal_spi_bus_end_txrx(const FuriHalSpiBus* bus, uint32_t timeout) {
 | 
						|
    while(LL_SPI_GetTxFIFOLevel((SPI_TypeDef*)bus->spi) != LL_SPI_TX_FIFO_EMPTY)
 | 
						|
        ;
 | 
						|
    while(LL_SPI_IsActiveFlag_BSY((SPI_TypeDef*)bus->spi))
 | 
						|
        ;
 | 
						|
    while(LL_SPI_GetRxFIFOLevel((SPI_TypeDef*)bus->spi) != LL_SPI_RX_FIFO_EMPTY) {
 | 
						|
        LL_SPI_ReceiveData8((SPI_TypeDef*)bus->spi);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
bool furi_hal_spi_bus_rx(const FuriHalSpiBus* bus, uint8_t* buffer, size_t size, uint32_t timeout) {
 | 
						|
    assert(bus);
 | 
						|
    assert(buffer);
 | 
						|
    assert(size > 0);
 | 
						|
 | 
						|
    return furi_hal_spi_bus_trx(bus, buffer, buffer, size, timeout);
 | 
						|
}
 | 
						|
 | 
						|
bool furi_hal_spi_bus_tx(const FuriHalSpiBus* bus, uint8_t* buffer, size_t size, uint32_t timeout) {
 | 
						|
    assert(bus);
 | 
						|
    assert(buffer);
 | 
						|
    assert(size > 0);
 | 
						|
    bool ret = true;
 | 
						|
 | 
						|
    while(size > 0) {
 | 
						|
        if(LL_SPI_IsActiveFlag_TXE((SPI_TypeDef*)bus->spi)) {
 | 
						|
            LL_SPI_TransmitData8((SPI_TypeDef*)bus->spi, *buffer);
 | 
						|
            buffer++;
 | 
						|
            size--;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    furi_hal_spi_bus_end_txrx(bus, timeout);
 | 
						|
    LL_SPI_ClearFlag_OVR((SPI_TypeDef*)bus->spi);
 | 
						|
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
bool furi_hal_spi_bus_trx(
 | 
						|
    const FuriHalSpiBus* bus,
 | 
						|
    uint8_t* tx_buffer,
 | 
						|
    uint8_t* rx_buffer,
 | 
						|
    size_t size,
 | 
						|
    uint32_t timeout) {
 | 
						|
    assert(bus);
 | 
						|
    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((SPI_TypeDef*)bus->spi) && tx_allowed) {
 | 
						|
            LL_SPI_TransmitData8((SPI_TypeDef*)bus->spi, *tx_buffer);
 | 
						|
            tx_buffer++;
 | 
						|
            tx_size--;
 | 
						|
            tx_allowed = false;
 | 
						|
        }
 | 
						|
 | 
						|
        if(LL_SPI_IsActiveFlag_RXNE((SPI_TypeDef*)bus->spi)) {
 | 
						|
            *rx_buffer = LL_SPI_ReceiveData8((SPI_TypeDef*)bus->spi);
 | 
						|
            rx_buffer++;
 | 
						|
            size--;
 | 
						|
            tx_allowed = true;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    furi_hal_spi_bus_end_txrx(bus, timeout);
 | 
						|
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
void furi_hal_spi_device_configure(const FuriHalSpiDevice* device) {
 | 
						|
    assert(device);
 | 
						|
    assert(device->config);
 | 
						|
 | 
						|
    furi_hal_spi_bus_configure(device->bus, device->config);
 | 
						|
}
 | 
						|
 | 
						|
const FuriHalSpiDevice* furi_hal_spi_device_get(FuriHalSpiDeviceId device_id) {
 | 
						|
    assert(device_id < FuriHalSpiDeviceIdMax);
 | 
						|
 | 
						|
    const FuriHalSpiDevice* device = &furi_hal_spi_devices[device_id];
 | 
						|
    assert(device);
 | 
						|
 | 
						|
    furi_hal_spi_bus_lock(device->bus);
 | 
						|
    furi_hal_spi_device_configure(device);
 | 
						|
 | 
						|
    return device;
 | 
						|
}
 | 
						|
 | 
						|
void furi_hal_spi_device_return(const FuriHalSpiDevice* device) {
 | 
						|
    furi_hal_spi_bus_unlock(device->bus);
 | 
						|
}
 | 
						|
 | 
						|
bool furi_hal_spi_device_rx(
 | 
						|
    const FuriHalSpiDevice* device,
 | 
						|
    uint8_t* buffer,
 | 
						|
    size_t size,
 | 
						|
    uint32_t timeout) {
 | 
						|
    assert(device);
 | 
						|
    assert(buffer);
 | 
						|
    assert(size > 0);
 | 
						|
 | 
						|
    if(device->chip_select) {
 | 
						|
        hal_gpio_write(device->chip_select, false);
 | 
						|
    }
 | 
						|
 | 
						|
    bool ret = furi_hal_spi_bus_rx(device->bus, buffer, size, timeout);
 | 
						|
 | 
						|
    if(device->chip_select) {
 | 
						|
        hal_gpio_write(device->chip_select, true);
 | 
						|
    }
 | 
						|
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
bool furi_hal_spi_device_tx(
 | 
						|
    const FuriHalSpiDevice* device,
 | 
						|
    uint8_t* buffer,
 | 
						|
    size_t size,
 | 
						|
    uint32_t timeout) {
 | 
						|
    assert(device);
 | 
						|
    assert(buffer);
 | 
						|
    assert(size > 0);
 | 
						|
 | 
						|
    if(device->chip_select) {
 | 
						|
        hal_gpio_write(device->chip_select, false);
 | 
						|
    }
 | 
						|
 | 
						|
    bool ret = furi_hal_spi_bus_tx(device->bus, buffer, size, timeout);
 | 
						|
 | 
						|
    if(device->chip_select) {
 | 
						|
        hal_gpio_write(device->chip_select, true);
 | 
						|
    }
 | 
						|
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
bool furi_hal_spi_device_trx(
 | 
						|
    const FuriHalSpiDevice* device,
 | 
						|
    uint8_t* tx_buffer,
 | 
						|
    uint8_t* rx_buffer,
 | 
						|
    size_t size,
 | 
						|
    uint32_t timeout) {
 | 
						|
    assert(device);
 | 
						|
    assert(tx_buffer);
 | 
						|
    assert(rx_buffer);
 | 
						|
    assert(size > 0);
 | 
						|
 | 
						|
    if(device->chip_select) {
 | 
						|
        hal_gpio_write(device->chip_select, false);
 | 
						|
    }
 | 
						|
 | 
						|
    bool ret = furi_hal_spi_bus_trx(device->bus, tx_buffer, rx_buffer, size, timeout);
 | 
						|
 | 
						|
    if(device->chip_select) {
 | 
						|
        hal_gpio_write(device->chip_select, true);
 | 
						|
    }
 | 
						|
 | 
						|
    return ret;
 | 
						|
}
 |