api-hal-spi.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. #include "api-hal-spi.h"
  2. #include <api-hal-resources.h>
  3. #include <stdbool.h>
  4. #include <string.h>
  5. #include <spi.h>
  6. #include <furi.h>
  7. extern void Enable_SPI(SPI_HandleTypeDef* spi);
  8. void api_hal_spi_init() {
  9. // Spi structure is const, but mutex is not
  10. // Need some hell-ish casting to make it work
  11. *(osMutexId_t*)spi_r.mutex = osMutexNew(NULL);
  12. *(osMutexId_t*)spi_d.mutex = osMutexNew(NULL);
  13. //
  14. for (size_t i=0; i<ApiHalSpiDeviceIdMax; ++i) {
  15. hal_gpio_init(
  16. api_hal_spi_devices[i].chip_select,
  17. GpioModeOutputPushPull,
  18. GpioPullNo,
  19. GpioSpeedVeryHigh
  20. );
  21. }
  22. }
  23. void api_hal_spi_bus_lock(const ApiHalSpiBus* bus) {
  24. furi_assert(bus);
  25. if (bus->mutex) {
  26. osMutexAcquire(*bus->mutex, osWaitForever);
  27. }
  28. }
  29. void api_hal_spi_bus_unlock(const ApiHalSpiBus* bus) {
  30. furi_assert(bus);
  31. if (bus->mutex) {
  32. osMutexRelease(*bus->mutex);
  33. }
  34. }
  35. bool api_hal_spi_bus_rx(const ApiHalSpiBus* bus, uint8_t* buffer, size_t size, uint32_t timeout) {
  36. furi_assert(bus);
  37. furi_assert(buffer);
  38. furi_assert(size > 0);
  39. HAL_StatusTypeDef ret = HAL_SPI_Receive((SPI_HandleTypeDef *)bus->spi, buffer, size, HAL_MAX_DELAY);
  40. return ret == HAL_OK;
  41. }
  42. bool api_hal_spi_bus_tx(const ApiHalSpiBus* bus, uint8_t* buffer, size_t size, uint32_t timeout) {
  43. furi_assert(bus);
  44. furi_assert(buffer);
  45. furi_assert(size > 0);
  46. HAL_StatusTypeDef ret = HAL_SPI_Transmit((SPI_HandleTypeDef *)bus->spi, buffer, size, HAL_MAX_DELAY);
  47. return ret == HAL_OK;
  48. }
  49. bool api_hal_spi_bus_trx(const ApiHalSpiBus* bus, uint8_t* tx_buffer, uint8_t* rx_buffer, size_t size, uint32_t timeout) {
  50. furi_assert(bus);
  51. furi_assert(tx_buffer);
  52. furi_assert(rx_buffer);
  53. furi_assert(size > 0);
  54. HAL_StatusTypeDef ret = HAL_SPI_TransmitReceive((SPI_HandleTypeDef *)bus->spi, tx_buffer, rx_buffer, size, HAL_MAX_DELAY);
  55. return ret == HAL_OK;
  56. }
  57. const ApiHalSpiDevice* api_hal_spi_device_get(ApiHalSpiDeviceId device_id) {
  58. furi_assert(device_id < ApiHalSpiDeviceIdMax);
  59. const ApiHalSpiDevice* device = &api_hal_spi_devices[device_id];
  60. assert(device);
  61. api_hal_spi_bus_lock(device->bus);
  62. if (device->config) {
  63. memcpy((SPI_InitTypeDef*)&device->bus->spi->Init, device->config, sizeof(SPI_InitTypeDef));
  64. if(HAL_SPI_Init((SPI_HandleTypeDef *)device->bus->spi) != HAL_OK) {
  65. Error_Handler();
  66. }
  67. Enable_SPI((SPI_HandleTypeDef *)device->bus->spi);
  68. }
  69. return device;
  70. }
  71. void api_hal_spi_device_return(const ApiHalSpiDevice* device) {
  72. api_hal_spi_bus_unlock(device->bus);
  73. }
  74. bool api_hal_spi_device_rx(const ApiHalSpiDevice* device, uint8_t* buffer, size_t size, uint32_t timeout) {
  75. furi_assert(device);
  76. furi_assert(buffer);
  77. furi_assert(size > 0);
  78. if (device->chip_select) {
  79. hal_gpio_write(device->chip_select, false);
  80. }
  81. bool ret = api_hal_spi_bus_rx(device->bus, buffer, size, HAL_MAX_DELAY);
  82. if (device->chip_select) {
  83. hal_gpio_write(device->chip_select, true);
  84. }
  85. return ret;
  86. }
  87. bool api_hal_spi_device_tx(const ApiHalSpiDevice* device, uint8_t* buffer, size_t size, uint32_t timeout) {
  88. furi_assert(device);
  89. furi_assert(buffer);
  90. furi_assert(size > 0);
  91. if (device->chip_select) {
  92. hal_gpio_write(device->chip_select, false);
  93. }
  94. bool ret = api_hal_spi_bus_tx(device->bus, buffer, size, HAL_MAX_DELAY);
  95. if (device->chip_select) {
  96. hal_gpio_write(device->chip_select, true);
  97. }
  98. return ret;
  99. }
  100. bool api_hal_spi_device_trx(const ApiHalSpiDevice* device, uint8_t* tx_buffer, uint8_t* rx_buffer, size_t size, uint32_t timeout) {
  101. furi_assert(device);
  102. furi_assert(tx_buffer);
  103. furi_assert(rx_buffer);
  104. furi_assert(size > 0);
  105. if (device->chip_select) {
  106. hal_gpio_write(device->chip_select, false);
  107. }
  108. bool ret = api_hal_spi_bus_trx(device->bus, tx_buffer, rx_buffer, size, HAL_MAX_DELAY);
  109. if (device->chip_select) {
  110. hal_gpio_write(device->chip_select, true);
  111. }
  112. return ret;
  113. }
  114. void api_hal_spi_apply_config(const SPIDevice* device) {
  115. osKernelLock();
  116. memcpy((SPI_InitTypeDef*)&device->bus->spi->Init, &device->config, sizeof(SPI_InitTypeDef));
  117. if(HAL_SPI_Init((SPI_HandleTypeDef*)device->bus->spi) != HAL_OK) {
  118. Error_Handler();
  119. }
  120. Enable_SPI((SPI_HandleTypeDef*)device->bus->spi);
  121. osKernelUnlock();
  122. }
  123. bool api_hal_spi_config_are_actual(const SPIDevice* device) {
  124. return (memcmp(&device->config, &device->bus->spi->Init, sizeof(SPI_InitTypeDef)) == 0);
  125. }
  126. void api_hal_spi_config_device(const SPIDevice* device) {
  127. if(!api_hal_spi_config_are_actual(device)) {
  128. api_hal_spi_apply_config(device);
  129. }
  130. }
  131. void api_hal_spi_lock_device(const SPIDevice* device) {
  132. api_hal_spi_bus_lock(device->bus);
  133. api_hal_spi_config_device(device);
  134. }
  135. void api_hal_spi_unlock_device(const SPIDevice* device) {
  136. api_hal_spi_bus_unlock(device->bus);
  137. }