diff options
Diffstat (limited to 'firmware/targets/f6/furi_hal/furi_hal_spi.c')
-rw-r--r-- | firmware/targets/f6/furi_hal/furi_hal_spi.c | 155 |
1 files changed, 155 insertions, 0 deletions
diff --git a/firmware/targets/f6/furi_hal/furi_hal_spi.c b/firmware/targets/f6/furi_hal/furi_hal_spi.c new file mode 100644 index 00000000..8af2879f --- /dev/null +++ b/firmware/targets/f6/furi_hal/furi_hal_spi.c @@ -0,0 +1,155 @@ +#include "furi_hal_spi.h" +#include "furi_hal_resources.h" + +#include <stdbool.h> +#include <string.h> +#include <furi.h> + +#include <stm32wbxx_ll_spi.h> +#include <stm32wbxx_ll_utils.h> +#include <stm32wbxx_ll_cortex.h> + +#define TAG "FuriHalSpi" + +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); + + FURI_LOG_I(TAG, "Init OK"); +} + +void furi_hal_spi_bus_init(FuriHalSpiBus* bus) { + furi_assert(bus); + bus->callback(bus, FuriHalSpiBusEventInit); +} + +void furi_hal_spi_bus_deinit(FuriHalSpiBus* bus) { + furi_assert(bus); + bus->callback(bus, FuriHalSpiBusEventDeinit); +} + +void furi_hal_spi_bus_handle_init(FuriHalSpiBusHandle* handle) { + furi_assert(handle); + handle->callback(handle, FuriHalSpiBusHandleEventInit); +} + +void furi_hal_spi_bus_handle_deinit(FuriHalSpiBusHandle* handle) { + furi_assert(handle); + handle->callback(handle, FuriHalSpiBusHandleEventDeinit); +} + +void furi_hal_spi_acquire(FuriHalSpiBusHandle* handle) { + furi_assert(handle); + + handle->bus->callback(handle->bus, FuriHalSpiBusEventLock); + handle->bus->callback(handle->bus, FuriHalSpiBusEventActivate); + + furi_assert(handle->bus->current_handle == NULL); + + handle->bus->current_handle = handle; + handle->callback(handle, FuriHalSpiBusHandleEventActivate); +} + +void furi_hal_spi_release(FuriHalSpiBusHandle* handle) { + furi_assert(handle); + furi_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) { + furi_assert(handle); + furi_assert(handle->bus->current_handle == handle); + furi_assert(buffer); + furi_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) { + furi_assert(handle); + furi_assert(handle->bus->current_handle == handle); + furi_assert(buffer); + furi_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) { + furi_assert(handle); + furi_assert(handle->bus->current_handle == handle); + furi_assert(tx_buffer); + furi_assert(rx_buffer); + furi_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; +} |