api-spi.h 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. #include "flipper_v2.h"
  2. /*
  3. struct used for handling SPI info.
  4. */
  5. typedef struct {
  6. SPI_HandleTypeDef* spi;
  7. PubSubCallback cb;
  8. void* ctx;
  9. } SpiHandle;
  10. /*
  11. For transmit/receive data use `spi_xfer` function.
  12. * `tx_data` and `rx_data` size must be equal (and equal `len`)
  13. * `cb` called after spi operation is completed, `(NULL, ctx)` passed to callback.
  14. */
  15. bool spi_xfer(
  16. SPI_HandleTypeDef* spi,
  17. uint8_t* tx_data,
  18. uint8_t* rx_data,
  19. size_t len,
  20. PubSubCallback cb,
  21. void* ctx);
  22. /*
  23. Blocking verison:
  24. */
  25. static inline bool
  26. spi_xfer_block(SPI_HandleTypeDef* spi, uint8_t* tx_data, uint8_t* rx_data, size_t len) {
  27. semaphoreInfo s;
  28. osSemaphore block = createSemaphoreStatic(s);
  29. if(!spi_xfer(spi, tx_data, rx_data, len, RELEASE_SEMAPHORE, (void*)block)) {
  30. osReleaseSemaphore(block);
  31. return false;
  32. }
  33. osWaitSemaphore(block);
  34. return false;
  35. }
  36. /*
  37. Common implementation of SPI bus: serial interface + CS pin
  38. */
  39. typedef struct {
  40. GpioPin* cs; ///< CS pin
  41. ValueMutex* spi; ///< <SpiHandle*>
  42. } SpiBus;
  43. /*
  44. For dedicated work with one device there is `SpiDevice` entity.
  45. It contains ValueMutex around SpiBus: after you acquire device
  46. you can acquire spi to work with it (don't forget SPI bus is shared
  47. around many device, release it after every transaction as quick as possible).
  48. */
  49. typedef struct {
  50. ValueMutex* bus; ///< <SpiBus*>
  51. } SpiDevice;
  52. ##SPI IRQ device
  53. /*
  54. Many devices (like CC1101 and NFC) present as SPI bus and IRQ line.
  55. For work with it there is special entity `SpiIrqDevice`.
  56. Use `subscribe_pubsub` for subscribinq to irq events.
  57. */
  58. typedef struct {
  59. ValueMutex* bus; ///< <SpiBus*>
  60. PubSub* irq;
  61. } SpiIrqDevice;
  62. /*
  63. Special implementation of SPI bus: serial interface + CS, Res, D/I lines.
  64. */
  65. typedef struct {
  66. GpioPin* cs; ///< CS pin
  67. GpioPin* res; ///< reset pin
  68. GpioPin* di; ///< D/I pin
  69. ValueMutex* spi; ///< <SPI_HandleTypeDef*>
  70. } DisplayBus;
  71. typedef struct {
  72. ValueMutex* bus; ///< <DisplayBus*>
  73. } DisplayDevice;
  74. /*
  75. # SPI devices (F2)
  76. * `/dev/sdcard` - SD card SPI, `SpiDevice`
  77. * `/dev/cc1101_bus` - Sub-GHz radio (CC1101), `SpiIrqDevice`
  78. * `/dev/nfc` - NFC (ST25R3916), `SpiIrqDevice`
  79. * `/dev/display` - `DisplayDevice`
  80. * `/dev/spiext` - External SPI (warning! Lock PA4, PA5, PA6, PA7)
  81. ### Application example
  82. ```C
  83. // Be careful, this function called from IRQ context
  84. void handle_irq(void* _arg, void* _ctx) {
  85. }
  86. void cc1101_example() {
  87. SpiIrqDevice* cc1101_device = open_input("/dev/cc1101_bus");
  88. if(cc1101_device == NULL) return; // bus not available, critical error
  89. subscribe_pubsub(cc1101_device->irq, handle_irq, NULL);
  90. {
  91. // acquire device as device bus
  92. SpiBus* spi_bus = acquire_mutex(cc1101_device->bus, 0);
  93. if(spi_bus == NULL) {
  94. printf("Device busy\n");
  95. // wait for device
  96. spi_bus = acquire_mutex_block(cc1101_device->bus);
  97. }
  98. // make transaction
  99. uint8_t request[4] = {0xDE, 0xAD, 0xBE, 0xEF};
  100. uint8_t response[4];
  101. {
  102. SPI_HandleTypeDef* spi = acquire_mutex_block(spi_bus->spi);
  103. gpio_write(spi_bus->cs, false);
  104. spi_xfer_block(spi, request, response, 4);
  105. gpio_write(spi_bus->cs, true);
  106. release_mutex(cc1101_device->spi, spi);
  107. }
  108. // release device (device bus)
  109. release_mutex(cc1101_device->bus, spi_bus);
  110. }
  111. }
  112. ```
  113. */