main.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. /*
  2. demonstration of memory corruption with USB and SPI on a STM32H743
  3. */
  4. #pragma GCC optimize("O0")
  5. #include "ch.h"
  6. #include "hal.h"
  7. #include "hal.h"
  8. #include "chprintf.h"
  9. #include "ccportab.h"
  10. #include "portab.h"
  11. #include "usbcfg.h"
  12. #include <string.h>
  13. #include <stdarg.h>
  14. #include <stdio.h>
  15. #define HAL_SPI_USE_POLLED 0
  16. // printf to USB
  17. static void uprintf(const char *fmt, ...)
  18. {
  19. va_list ap;
  20. char umsg[200];
  21. va_start(ap, fmt);
  22. uint32_t n = chvsnprintf(umsg, sizeof(umsg), fmt, ap);
  23. va_end(ap);
  24. chnWriteTimeout(&SDU1, (const uint8_t *)umsg, n, chTimeMS2I(100));
  25. }
  26. /*
  27. * SPI TX and RX buffers.
  28. */
  29. CC_ALIGN(32) uint8_t txbuf[512];
  30. CC_ALIGN(32) uint8_t rxbuf[512];
  31. static SPIConfig spicfg = {
  32. false,
  33. NULL,
  34. 0,
  35. 0,
  36. 0, // cfg1 filled in below
  37. SPI_CFG2_CPOL | SPI_CFG2_CPHA
  38. };
  39. #define LINE_NSS PAL_LINE(GPIOF, 5U)
  40. static bool data_ok;
  41. /*
  42. SPI transfer, send send_len bytes, and receive recv_len response
  43. */
  44. static void spi_transfer(const uint8_t *send, uint32_t send_len,
  45. uint8_t *recv, uint32_t recv_len)
  46. {
  47. uint16_t len = send_len + recv_len;
  48. osalDbgAssert(len < sizeof(txbuf), "transfer too large");
  49. spiAcquireBus(&PORTAB_SPI1);
  50. spiStart(&PORTAB_SPI1, &spicfg);
  51. memset(txbuf, 0, len);
  52. memset(rxbuf, 0, len);
  53. if (send_len) {
  54. memcpy(txbuf, send, send_len);
  55. }
  56. cacheBufferFlush(txbuf, len);
  57. memset(rxbuf, 0x41, sizeof(rxbuf));
  58. cacheBufferFlush(rxbuf, sizeof(rxbuf));
  59. cacheBufferInvalidate(rxbuf, len);
  60. palWriteLine(LINE_NSS, 0);
  61. #if HAL_SPI_USE_POLLED == 1
  62. for (uint16_t i=0; i<len; i++) {
  63. uint8_t ret = spiPolledExchange(&PORTAB_SPI1, txbuf[i]);
  64. rxbuf[i] = ret;
  65. }
  66. #else
  67. spiExchange(&PORTAB_SPI1, len, txbuf, rxbuf);
  68. #endif
  69. palWriteLine(LINE_NSS, 1);
  70. if (recv_len) {
  71. memcpy(recv, &rxbuf[send_len], recv_len);
  72. }
  73. spiReleaseBus(&PORTAB_SPI1);
  74. // the spiStop is not needed, but is done by ArduPilot, so is
  75. // included here
  76. spiStop(&PORTAB_SPI1);
  77. }
  78. /*
  79. calculate cfg1 register for SPI given required bus speed
  80. */
  81. static uint32_t get_spi_cfg1(uint32_t bus_speed)
  82. {
  83. uint32_t spi_clock_freq = STM32_SPI1CLK;
  84. // find first divisor that brings us below the desired SPI clock
  85. uint32_t i = 0;
  86. while (spi_clock_freq > bus_speed && i<7) {
  87. spi_clock_freq >>= 1;
  88. i++;
  89. }
  90. // assuming the bitrate bits are consecutive in the CR1 register,
  91. // we can just multiply by MBR_0 to get the right bits for the desired
  92. // scaling
  93. return (i * SPI_CFG1_MBR_0) | SPI_CFG1_DSIZE_VALUE(7); // 8 bit transfers
  94. }
  95. struct {
  96. uint32_t counter;
  97. uint32_t corrupt_count;
  98. mutex_t mtx;
  99. } results;
  100. /*
  101. LED blinker thread
  102. */
  103. static THD_WORKING_AREA(waThread1, 128);
  104. static THD_FUNCTION(Thread1, arg) {
  105. (void)arg;
  106. chRegSetThreadName("blinker");
  107. while (true) {
  108. palToggleLine(HAL_GPIO_PIN_LED_GREEN);
  109. // use rapid blink when we have corruption
  110. uint16_t time = results.corrupt_count?50:500;
  111. chThdSleepMilliseconds(time);
  112. }
  113. }
  114. /*
  115. * Application entry point.
  116. */
  117. int main(void) {
  118. halInit();
  119. chSysInit();
  120. portab_setup();
  121. #ifdef HAL_GPIO_PIN_nVDD_5V_PERIPH_EN
  122. palWriteLine(HAL_GPIO_PIN_nVDD_5V_PERIPH_EN, 0);
  123. #endif
  124. #ifdef HAL_GPIO_PIN_nVDD_5V_HIPOWER_EN
  125. palWriteLine(HAL_GPIO_PIN_nVDD_5V_HIPOWER_EN, 0);
  126. #endif
  127. #ifdef HAL_GPIO_PIN_VDD_3V3_SENSORS_EN
  128. palWriteLine(HAL_GPIO_PIN_VDD_3V3_SENSORS_EN, 1);
  129. #endif
  130. // run SPI at 4MHz
  131. spicfg.cfg1 = get_spi_cfg1(4000000U);
  132. sduObjectInit(&PORTAB_SDU1);
  133. sduStart(&PORTAB_SDU1, &serusbcfg);
  134. usbDisconnectBus(serusbcfg.usbp);
  135. chThdSleepMilliseconds(1500);
  136. usbStart(serusbcfg.usbp, &usbcfg);
  137. usbConnectBus(serusbcfg.usbp);
  138. chMtxObjectInit(&results.mtx);
  139. chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO, Thread1, NULL);
  140. while (true) {
  141. palToggleLine(HAL_GPIO_PIN_LED_BLUE);
  142. chMtxLock(&results.mtx);
  143. results.counter++;
  144. chMtxUnlock(&results.mtx);
  145. uint8_t reg = 0x9f;
  146. uint8_t val[18];
  147. spi_transfer(&reg, 1, val, sizeof(val));
  148. for (uint8_t i=0; i<sizeof(val); i++) {
  149. uprintf("%02x ", val[i]);
  150. }
  151. uprintf("\n");
  152. bool new_data_ok = true;
  153. for (uint8_t i=0; i<9; i++) {
  154. if (val[i] == 0) {
  155. new_data_ok = false;
  156. }
  157. }
  158. data_ok = new_data_ok;
  159. if (data_ok) {
  160. chThdSleepMilliseconds(500);
  161. } else {
  162. chThdSleepMilliseconds(50);
  163. }
  164. }
  165. return 0;
  166. }