Util.cpp 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  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. * Code by Andrew Tridgell and Siddharth Bharat Purohit
  16. */
  17. #include <AP_HAL/AP_HAL.h>
  18. #include <AP_Math/AP_Math.h>
  19. #include "Util.h"
  20. #include <ch.h>
  21. #include "RCOutput.h"
  22. #include "hwdef/common/stm32_util.h"
  23. #include "hwdef/common/watchdog.h"
  24. #include "hwdef/common/flash.h"
  25. #include <AP_ROMFS/AP_ROMFS.h>
  26. #include "sdcard.h"
  27. #if HAL_WITH_IO_MCU
  28. #include <AP_BoardConfig/AP_BoardConfig.h>
  29. #include <AP_IOMCU/AP_IOMCU.h>
  30. extern AP_IOMCU iomcu;
  31. #endif
  32. extern const AP_HAL::HAL& hal;
  33. using namespace ChibiOS;
  34. #if CH_CFG_USE_HEAP == TRUE
  35. /**
  36. how much free memory do we have in bytes.
  37. */
  38. uint32_t Util::available_memory(void)
  39. {
  40. // from malloc.c in hwdef
  41. return mem_available();
  42. }
  43. /*
  44. Special Allocation Routines
  45. */
  46. void* Util::malloc_type(size_t size, AP_HAL::Util::Memory_Type mem_type)
  47. {
  48. if (mem_type == AP_HAL::Util::MEM_DMA_SAFE) {
  49. return malloc_dma(size);
  50. } else if (mem_type == AP_HAL::Util::MEM_FAST) {
  51. return malloc_fastmem(size);
  52. } else {
  53. return calloc(1, size);
  54. }
  55. }
  56. void Util::free_type(void *ptr, size_t size, AP_HAL::Util::Memory_Type mem_type)
  57. {
  58. if (ptr != NULL) {
  59. chHeapFree(ptr);
  60. }
  61. }
  62. #ifdef ENABLE_HEAP
  63. void *Util::allocate_heap_memory(size_t size)
  64. {
  65. void *buf = malloc(size);
  66. if (buf == nullptr) {
  67. return nullptr;
  68. }
  69. memory_heap_t *heap = (memory_heap_t *)malloc(sizeof(memory_heap_t));
  70. if (heap != nullptr) {
  71. chHeapObjectInit(heap, buf, size);
  72. }
  73. return heap;
  74. }
  75. void *Util::heap_realloc(void *heap, void *ptr, size_t new_size)
  76. {
  77. if (heap == nullptr) {
  78. return nullptr;
  79. }
  80. if (new_size == 0) {
  81. if (ptr != nullptr) {
  82. chHeapFree(ptr);
  83. }
  84. return nullptr;
  85. }
  86. if (ptr == nullptr) {
  87. return chHeapAlloc((memory_heap_t *)heap, new_size);
  88. }
  89. void *new_mem = chHeapAlloc((memory_heap_t *)heap, new_size);
  90. if (new_mem != nullptr) {
  91. memcpy(new_mem, ptr, chHeapGetSize(ptr) > new_size ? new_size : chHeapGetSize(ptr));
  92. chHeapFree(ptr);
  93. }
  94. return new_mem;
  95. }
  96. #endif // ENABLE_HEAP
  97. #endif // CH_CFG_USE_HEAP
  98. /*
  99. get safety switch state
  100. */
  101. Util::safety_state Util::safety_switch_state(void)
  102. {
  103. #if HAL_USE_PWM == TRUE
  104. return ((RCOutput *)hal.rcout)->_safety_switch_state();
  105. #else
  106. return SAFETY_NONE;
  107. #endif
  108. }
  109. void Util::set_imu_temp(float current)
  110. {
  111. #if HAL_HAVE_IMU_HEATER
  112. if (!heater.target || *heater.target == -1) {
  113. return;
  114. }
  115. // average over temperatures to remove noise
  116. heater.count++;
  117. heater.sum += current;
  118. // update once a second
  119. uint32_t now = AP_HAL::millis();
  120. if (now - heater.last_update_ms < 1000) {
  121. #if defined(HAL_HEATER_GPIO_PIN)
  122. // output as duty cycle to local pin. Use a random sequence to
  123. // prevent a periodic change to magnetic field
  124. bool heater_on = (get_random16() < uint32_t(heater.output) * 0xFFFFU / 100U);
  125. hal.gpio->write(HAL_HEATER_GPIO_PIN, heater_on);
  126. #endif
  127. return;
  128. }
  129. heater.last_update_ms = now;
  130. current = heater.sum / heater.count;
  131. heater.sum = 0;
  132. heater.count = 0;
  133. // experimentally tweaked for Pixhawk2
  134. const float kI = 0.3f;
  135. const float kP = 200.0f;
  136. float target = (float)(*heater.target);
  137. // limit to 65 degrees to prevent damage
  138. target = constrain_float(target, 0, 65);
  139. float err = target - current;
  140. heater.integrator += kI * err;
  141. heater.integrator = constrain_float(heater.integrator, 0, 70);
  142. heater.output = constrain_float(kP * err + heater.integrator, 0, 100);
  143. //hal.console->printf("integrator %.1f out=%.1f temp=%.2f err=%.2f\n", heater.integrator, heater.output, current, err);
  144. #if HAL_WITH_IO_MCU
  145. if (AP_BoardConfig::io_enabled()) {
  146. // tell IOMCU to setup heater
  147. iomcu.set_heater_duty_cycle(heater.output);
  148. }
  149. #endif
  150. #endif // HAL_HAVE_IMU_HEATER
  151. }
  152. void Util::set_imu_target_temp(int8_t *target)
  153. {
  154. #if HAL_HAVE_IMU_HEATER
  155. heater.target = target;
  156. #endif
  157. }
  158. #ifdef HAL_PWM_ALARM
  159. struct Util::ToneAlarmPwmGroup Util::_toneAlarm_pwm_group = HAL_PWM_ALARM;
  160. bool Util::toneAlarm_init()
  161. {
  162. _toneAlarm_pwm_group.pwm_cfg.period = 1000;
  163. pwmStart(_toneAlarm_pwm_group.pwm_drv, &_toneAlarm_pwm_group.pwm_cfg);
  164. return true;
  165. }
  166. void Util::toneAlarm_set_buzzer_tone(float frequency, float volume, uint32_t duration_ms)
  167. {
  168. if (is_zero(frequency) || is_zero(volume)) {
  169. pwmDisableChannel(_toneAlarm_pwm_group.pwm_drv, _toneAlarm_pwm_group.chan);
  170. } else {
  171. pwmChangePeriod(_toneAlarm_pwm_group.pwm_drv,
  172. roundf(_toneAlarm_pwm_group.pwm_cfg.frequency/frequency));
  173. pwmEnableChannel(_toneAlarm_pwm_group.pwm_drv, _toneAlarm_pwm_group.chan, roundf(volume*_toneAlarm_pwm_group.pwm_cfg.frequency/frequency)/2);
  174. }
  175. }
  176. #endif // HAL_PWM_ALARM
  177. /*
  178. set HW RTC in UTC microseconds
  179. */
  180. void Util::set_hw_rtc(uint64_t time_utc_usec)
  181. {
  182. stm32_set_utc_usec(time_utc_usec);
  183. }
  184. /*
  185. get system clock in UTC microseconds
  186. */
  187. uint64_t Util::get_hw_rtc() const
  188. {
  189. return stm32_get_utc_usec();
  190. }
  191. #if !defined(HAL_NO_FLASH_SUPPORT) && !defined(HAL_NO_ROMFS_SUPPORT)
  192. bool Util::flash_bootloader()
  193. {
  194. uint32_t fw_size;
  195. const char *fw_name = "bootloader.bin";
  196. EXPECT_DELAY_MS(11000);
  197. uint8_t *fw = AP_ROMFS::find_decompress(fw_name, fw_size);
  198. if (!fw) {
  199. hal.console->printf("failed to find %s\n", fw_name);
  200. return false;
  201. }
  202. // make sure size is multiple of 32
  203. fw_size = (fw_size + 31U) & ~31U;
  204. const uint32_t addr = hal.flash->getpageaddr(0);
  205. if (!memcmp(fw, (const void*)addr, fw_size)) {
  206. hal.console->printf("Bootloader up-to-date\n");
  207. free(fw);
  208. return true;
  209. }
  210. hal.console->printf("Erasing\n");
  211. if (!hal.flash->erasepage(0)) {
  212. hal.console->printf("Erase failed\n");
  213. free(fw);
  214. return false;
  215. }
  216. hal.console->printf("Flashing %s @%08x\n", fw_name, (unsigned int)addr);
  217. const uint8_t max_attempts = 10;
  218. for (uint8_t i=0; i<max_attempts; i++) {
  219. bool ok = hal.flash->write(addr, fw, fw_size);
  220. if (!ok) {
  221. hal.console->printf("Flash failed! (attempt=%u/%u)\n",
  222. i+1,
  223. max_attempts);
  224. hal.scheduler->delay(1000);
  225. continue;
  226. }
  227. hal.console->printf("Flash OK\n");
  228. free(fw);
  229. return true;
  230. }
  231. hal.console->printf("Flash failed after %u attempts\n", max_attempts);
  232. free(fw);
  233. return false;
  234. }
  235. #endif // !HAL_NO_FLASH_SUPPORT && !HAL_NO_ROMFS_SUPPORT
  236. /*
  237. display system identifer - board type and serial number
  238. */
  239. bool Util::get_system_id(char buf[40])
  240. {
  241. uint8_t serialid[12];
  242. char board_name[14];
  243. memcpy(serialid, (const void *)UDID_START, 12);
  244. strncpy(board_name, CHIBIOS_SHORT_BOARD_NAME, 13);
  245. board_name[13] = 0;
  246. // this format is chosen to match the format used by HAL_PX4
  247. snprintf(buf, 40, "%s %02X%02X%02X%02X %02X%02X%02X%02X %02X%02X%02X%02X",
  248. board_name,
  249. (unsigned)serialid[3], (unsigned)serialid[2], (unsigned)serialid[1], (unsigned)serialid[0],
  250. (unsigned)serialid[7], (unsigned)serialid[6], (unsigned)serialid[5], (unsigned)serialid[4],
  251. (unsigned)serialid[11], (unsigned)serialid[10], (unsigned)serialid[9],(unsigned)serialid[8]);
  252. buf[39] = 0;
  253. return true;
  254. }
  255. bool Util::get_system_id_unformatted(uint8_t buf[], uint8_t &len)
  256. {
  257. len = MIN(12, len);
  258. memcpy(buf, (const void *)UDID_START, len);
  259. return true;
  260. }
  261. #ifdef USE_POSIX
  262. /*
  263. initialise filesystem
  264. */
  265. bool Util::fs_init(void)
  266. {
  267. return sdcard_retry();
  268. }
  269. #endif
  270. // return true if the reason for the reboot was a watchdog reset
  271. bool Util::was_watchdog_reset() const
  272. {
  273. return stm32_was_watchdog_reset();
  274. }