stm32_util.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  1. /*
  2. * This file is free software: you can redistribute it and/or modify it
  3. * under the terms of the GNU General Public License as published by the
  4. * Free Software Foundation, either version 3 of the License, or
  5. * (at your option) any later version.
  6. *
  7. * This file is distributed in the hope that it will be useful, but
  8. * WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. * See the GNU General Public License for more details.
  11. *
  12. * You should have received a copy of the GNU General Public License along
  13. * with this program. If not, see <http://www.gnu.org/licenses/>.
  14. */
  15. #include "stm32_util.h"
  16. #include <stdint.h>
  17. #include <stdio.h>
  18. #include <string.h>
  19. #include <stm32_dma.h>
  20. #include <hrt.h>
  21. static int64_t utc_time_offset;
  22. /*
  23. setup the timer capture digital filter for a channel
  24. */
  25. void stm32_timer_set_input_filter(stm32_tim_t *tim, uint8_t channel, uint8_t filter_mode)
  26. {
  27. switch (channel) {
  28. case 0:
  29. tim->CCMR1 |= STM32_TIM_CCMR1_IC1F(filter_mode);
  30. break;
  31. case 1:
  32. tim->CCMR1 |= STM32_TIM_CCMR1_IC2F(filter_mode);
  33. break;
  34. case 2:
  35. tim->CCMR2 |= STM32_TIM_CCMR2_IC3F(filter_mode);
  36. break;
  37. case 3:
  38. tim->CCMR2 |= STM32_TIM_CCMR2_IC4F(filter_mode);
  39. break;
  40. }
  41. }
  42. /*
  43. set the input source of a timer channel
  44. */
  45. void stm32_timer_set_channel_input(stm32_tim_t *tim, uint8_t channel, uint8_t input_source)
  46. {
  47. switch (channel) {
  48. case 0:
  49. tim->CCER &= ~STM32_TIM_CCER_CC1E;
  50. tim->CCMR1 &= ~STM32_TIM_CCMR1_CC1S_MASK;
  51. tim->CCMR1 |= STM32_TIM_CCMR1_CC1S(input_source);
  52. tim->CCER |= STM32_TIM_CCER_CC1E;
  53. break;
  54. case 1:
  55. tim->CCER &= ~STM32_TIM_CCER_CC2E;
  56. tim->CCMR1 &= ~STM32_TIM_CCMR1_CC2S_MASK;
  57. tim->CCMR1 |= STM32_TIM_CCMR1_CC2S(input_source);
  58. tim->CCER |= STM32_TIM_CCER_CC2E;
  59. break;
  60. case 2:
  61. tim->CCER &= ~STM32_TIM_CCER_CC3E;
  62. tim->CCMR2 &= ~STM32_TIM_CCMR2_CC3S_MASK;
  63. tim->CCMR2 |= STM32_TIM_CCMR2_CC3S(input_source);
  64. tim->CCER |= STM32_TIM_CCER_CC3E;
  65. break;
  66. case 3:
  67. tim->CCER &= ~STM32_TIM_CCER_CC4E;
  68. tim->CCMR2 &= ~STM32_TIM_CCMR2_CC4S_MASK;
  69. tim->CCMR2 |= STM32_TIM_CCMR2_CC4S(input_source);
  70. tim->CCER |= STM32_TIM_CCER_CC4E;
  71. break;
  72. }
  73. }
  74. #if CH_DBG_ENABLE_STACK_CHECK == TRUE && !defined(HAL_BOOTLOADER_BUILD)
  75. void show_stack_usage(void)
  76. {
  77. thread_t *tp;
  78. tp = chRegFirstThread();
  79. do {
  80. uint32_t stklimit = (uint32_t)tp->wabase;
  81. uint8_t *p = (uint8_t *)tp->wabase;
  82. while (*p == CH_DBG_STACK_FILL_VALUE) {
  83. p++;
  84. }
  85. uint32_t stack_left = ((uint32_t)p) - stklimit;
  86. printf("%s %u\n", tp->name, (unsigned)stack_left);
  87. tp = chRegNextThread(tp);
  88. } while (tp != NULL);
  89. }
  90. #endif
  91. /*
  92. set the utc time
  93. */
  94. void stm32_set_utc_usec(uint64_t time_utc_usec)
  95. {
  96. uint64_t now = hrt_micros64();
  97. if (now <= time_utc_usec) {
  98. utc_time_offset = time_utc_usec - now;
  99. }
  100. }
  101. /*
  102. get system clock in UTC microseconds
  103. */
  104. uint64_t stm32_get_utc_usec()
  105. {
  106. return hrt_micros64() + utc_time_offset;
  107. }
  108. struct utc_tm {
  109. uint8_t tm_year; // since 1900
  110. uint8_t tm_mon; // zero based
  111. uint8_t tm_mday; // zero based
  112. uint8_t tm_hour;
  113. uint8_t tm_min;
  114. uint8_t tm_sec;
  115. };
  116. /*
  117. return true if a year is a leap year
  118. */
  119. static bool is_leap(uint32_t y)
  120. {
  121. y += 1900;
  122. return (y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0);
  123. }
  124. static const uint8_t ndays[2][12] ={
  125. {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
  126. {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}};
  127. /*
  128. parse a seconds since 1970 into a utc_tm structure
  129. code based on _der_gmtime from samba
  130. */
  131. static void parse_utc_seconds(uint64_t utc_sec, struct utc_tm *tm)
  132. {
  133. uint32_t secday = utc_sec % (3600U * 24U);
  134. uint32_t days = utc_sec / (3600U * 24U);
  135. memset(tm, 0, sizeof(*tm));
  136. tm->tm_sec = secday % 60U;
  137. tm->tm_min = (secday % 3600U) / 60U;
  138. tm->tm_hour = secday / 3600U;
  139. tm->tm_year = 70;
  140. if (days > (2000 * 365)) {
  141. // don't look for dates too far into the future
  142. return;
  143. }
  144. while (true) {
  145. unsigned dayinyear = (is_leap(tm->tm_year) ? 366 : 365);
  146. if (days < dayinyear) {
  147. break;
  148. }
  149. tm->tm_year += 1;
  150. days -= dayinyear;
  151. }
  152. tm->tm_mon = 0;
  153. while (true) {
  154. unsigned daysinmonth = ndays[is_leap(tm->tm_year)?1:0][tm->tm_mon];
  155. if (days < daysinmonth) {
  156. break;
  157. }
  158. days -= daysinmonth;
  159. tm->tm_mon++;
  160. }
  161. tm->tm_mday = days + 1;
  162. }
  163. /*
  164. get time for fat filesystem. This is based on
  165. rtcConvertDateTimeToFAT from the ChibiOS RTC driver. We don't use
  166. the hw RTC clock as it is very inaccurate
  167. */
  168. uint32_t get_fattime()
  169. {
  170. if (utc_time_offset == 0) {
  171. // return a fixed time
  172. return ((uint32_t)0 | (1 << 16)) | (1 << 21);
  173. }
  174. uint64_t utc_usec = stm32_get_utc_usec();
  175. uint64_t utc_sec = utc_usec / 1000000UL;
  176. struct utc_tm tm;
  177. parse_utc_seconds(utc_sec, &tm);
  178. uint32_t fattime;
  179. fattime = tm.tm_sec >> 1U;
  180. fattime |= tm.tm_min << 5U;
  181. fattime |= tm.tm_hour << 11U;
  182. fattime |= tm.tm_mday << 16U;
  183. fattime |= (tm.tm_mon+1) << 21U;
  184. fattime |= (uint32_t)((tm.tm_year-80) << 25U);
  185. return fattime;
  186. }
  187. #if !defined(NO_FASTBOOT)
  188. // get RTC backup registers starting at given idx
  189. void get_rtc_backup(uint8_t idx, uint32_t *v, uint8_t n)
  190. {
  191. while (n--) {
  192. #if defined(STM32F1)
  193. __IO uint32_t *dr = (__IO uint32_t *)&BKP->DR1;
  194. *v++ = (dr[n/2]&0xFFFF) | (dr[n/2+1]<<16);
  195. #else
  196. *v++ = ((__IO uint32_t *)&RTC->BKP0R)[idx++];
  197. #endif
  198. }
  199. }
  200. // set n RTC backup registers starting at given idx
  201. void set_rtc_backup(uint8_t idx, const uint32_t *v, uint8_t n)
  202. {
  203. #if !defined(STM32F1)
  204. if ((RCC->BDCR & RCC_BDCR_RTCEN) == 0) {
  205. RCC->BDCR |= STM32_RTCSEL;
  206. RCC->BDCR |= RCC_BDCR_RTCEN;
  207. }
  208. #ifdef PWR_CR_DBP
  209. PWR->CR |= PWR_CR_DBP;
  210. #else
  211. PWR->CR1 |= PWR_CR1_DBP;
  212. #endif
  213. #endif
  214. while (n--) {
  215. #if defined(STM32F1)
  216. __IO uint32_t *dr = (__IO uint32_t *)&BKP->DR1;
  217. dr[n/2] = (*v) & 0xFFFF;
  218. dr[n/2+1] = (*v) >> 16;
  219. #else
  220. ((__IO uint32_t *)&RTC->BKP0R)[idx++] = *v++;
  221. #endif
  222. }
  223. }
  224. // see if RTC registers is setup for a fast reboot
  225. enum rtc_boot_magic check_fast_reboot(void)
  226. {
  227. uint32_t v;
  228. get_rtc_backup(0, &v, 1);
  229. return (enum rtc_boot_magic)v;
  230. }
  231. // set RTC register for a fast reboot
  232. void set_fast_reboot(enum rtc_boot_magic v)
  233. {
  234. uint32_t vv = (uint32_t)v;
  235. set_rtc_backup(0, &vv, 1);
  236. }
  237. #else // NO_FASTBOOT
  238. // set n RTC backup registers starting at given idx
  239. void set_rtc_backup(uint8_t idx, const uint32_t *v, uint8_t n)
  240. {
  241. }
  242. // get RTC backup registers starting at given idx
  243. void get_rtc_backup(uint8_t idx, uint32_t *v, uint8_t n)
  244. {
  245. return 0;
  246. }
  247. #endif // NO_FASTBOOT
  248. /*
  249. enable peripheral power if needed This is done late to prevent
  250. problems with CTS causing SiK radios to stay in the bootloader. A
  251. SiK radio will stay in the bootloader if CTS is held to GND on boot
  252. */
  253. void peripheral_power_enable(void)
  254. {
  255. #if defined(HAL_GPIO_PIN_nVDD_5V_PERIPH_EN) || defined(HAL_GPIO_PIN_nVDD_5V_HIPOWER_EN) || defined(HAL_GPIO_PIN_VDD_3V3_SENSORS_EN) || defined(HAL_GPIO_PIN_nVDD_3V3_SD_CARD_EN) || defined(HAL_GPIO_PIN_VDD_3V3_SD_CARD_EN)
  256. // we don't know what state the bootloader had the CTS pin in, so
  257. // wait here with it pulled up from the PAL table for enough time
  258. // for the radio to be definately powered down
  259. uint8_t i;
  260. for (i=0; i<100; i++) {
  261. // use a loop as this may be a 16 bit timer
  262. chThdSleep(chTimeMS2I(1));
  263. }
  264. #ifdef HAL_GPIO_PIN_nVDD_5V_PERIPH_EN
  265. palWriteLine(HAL_GPIO_PIN_nVDD_5V_PERIPH_EN, 0);
  266. #endif
  267. #ifdef HAL_GPIO_PIN_nVDD_5V_HIPOWER_EN
  268. palWriteLine(HAL_GPIO_PIN_nVDD_5V_HIPOWER_EN, 0);
  269. #endif
  270. #ifdef HAL_GPIO_PIN_VDD_3V3_SENSORS_EN
  271. // the TBS-Colibri-F7 needs PE3 low at power on
  272. palWriteLine(HAL_GPIO_PIN_VDD_3V3_SENSORS_EN, 1);
  273. #endif
  274. #ifdef HAL_GPIO_PIN_nVDD_3V3_SD_CARD_EN
  275. // the TBS-Colibri-F7 needs PG7 low for SD card
  276. palWriteLine(HAL_GPIO_PIN_nVDD_3V3_SD_CARD_EN, 0);
  277. #endif
  278. #ifdef HAL_GPIO_PIN_VDD_3V3_SD_CARD_EN
  279. // others need it active high
  280. palWriteLine(HAL_GPIO_PIN_VDD_3V3_SD_CARD_EN, 1);
  281. #endif
  282. for (i=0; i<20; i++) {
  283. // give 20ms for sensors to settle
  284. chThdSleep(chTimeMS2I(1));
  285. }
  286. #endif
  287. }
  288. #if defined(STM32F7) || defined(STM32H7) || defined(STM32F4)
  289. /*
  290. read mode of a pin. This allows a pin config to be read, changed and
  291. then written back
  292. */
  293. iomode_t palReadLineMode(ioline_t line)
  294. {
  295. ioportid_t port = PAL_PORT(line);
  296. uint8_t pad = PAL_PAD(line);
  297. iomode_t ret = 0;
  298. ret |= (port->MODER >> (pad*2)) & 0x3;
  299. ret |= ((port->OTYPER >> pad)&1) << 2;
  300. ret |= ((port->OSPEEDR >> (pad*2))&3) << 3;
  301. ret |= ((port->PUPDR >> (pad*2))&3) << 5;
  302. if (pad < 8) {
  303. ret |= ((port->AFRL >> (pad*4))&0xF) << 7;
  304. } else {
  305. ret |= ((port->AFRH >> ((pad-8)*4))&0xF) << 7;
  306. }
  307. return ret;
  308. }
  309. #endif
  310. void stm32_cacheBufferInvalidate(const void *p, size_t size)
  311. {
  312. cacheBufferInvalidate(p, size);
  313. }
  314. void stm32_cacheBufferFlush(const void *p, size_t size)
  315. {
  316. cacheBufferFlush(p, size);
  317. }