Util.cpp 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. #include <errno.h>
  2. #include <fcntl.h>
  3. #include <stdarg.h>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <sys/stat.h>
  7. #include <time.h>
  8. #include <unistd.h>
  9. #include <AP_HAL/AP_HAL.h>
  10. #include "Heat_Pwm.h"
  11. #include "ToneAlarm_Disco.h"
  12. #include "Util.h"
  13. using namespace Linux;
  14. extern const AP_HAL::HAL& hal;
  15. #if CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_DISCO
  16. ToneAlarm_Disco Util::_toneAlarm;
  17. #else
  18. ToneAlarm Util::_toneAlarm;
  19. #endif
  20. void Util::init(int argc, char * const *argv) {
  21. saved_argc = argc;
  22. saved_argv = argv;
  23. #ifdef HAL_UTILS_HEAT
  24. #if HAL_UTILS_HEAT == HAL_LINUX_HEAT_PWM
  25. _heat = new Linux::HeatPwm(HAL_LINUX_HEAT_PWM_NUM,
  26. HAL_LINUX_HEAT_KP,
  27. HAL_LINUX_HEAT_KI,
  28. HAL_LINUX_HEAT_PERIOD_NS);
  29. #else
  30. #error Unrecognized Heat
  31. #endif // #if
  32. #else
  33. _heat = new Linux::Heat();
  34. #endif // #ifdef
  35. }
  36. // set current IMU temperatue in degrees C
  37. void Util::set_imu_temp(float current)
  38. {
  39. _heat->set_imu_temp(current);
  40. }
  41. // set target IMU temperatue in degrees C
  42. void Util::set_imu_target_temp(int8_t *target)
  43. {
  44. _heat->set_imu_target_temp(target);
  45. }
  46. /**
  47. return commandline arguments, if available
  48. */
  49. void Util::commandline_arguments(uint8_t &argc, char * const *&argv)
  50. {
  51. argc = saved_argc;
  52. argv = saved_argv;
  53. }
  54. void Util::set_hw_rtc(uint64_t time_utc_usec)
  55. {
  56. #if CONFIG_HAL_BOARD_SUBTYPE != HAL_BOARD_SUBTYPE_LINUX_NONE
  57. // call superclass method to set time. We've guarded this so we
  58. // don't reset the HW clock time on people's laptops.
  59. AP_HAL::Util::set_hw_rtc(time_utc_usec);
  60. #endif
  61. }
  62. bool Util::is_chardev_node(const char *path)
  63. {
  64. struct stat st;
  65. if (!path || lstat(path, &st) < 0) {
  66. return false;
  67. }
  68. return S_ISCHR(st.st_mode);
  69. }
  70. /*
  71. always report 256k of free memory. Using mallinfo() isn't useful as
  72. it only reported the current heap, which auto-expands. What we're
  73. trying to do here is ensure that code which checks for free memory
  74. before allocating objects does allow the allocation
  75. */
  76. uint32_t Util::available_memory(void)
  77. {
  78. return 256*1024;
  79. }
  80. #ifndef HAL_LINUX_DEFAULT_SYSTEM_ID
  81. #define HAL_LINUX_DEFAULT_SYSTEM_ID "linux-unknown"
  82. #endif
  83. /*
  84. get a (hopefully unique) machine ID
  85. */
  86. bool Util::get_system_id_unformatted(uint8_t buf[], uint8_t &len)
  87. {
  88. char *cbuf = (char *)buf;
  89. // try first to use machine-id file. Most systems will have this
  90. const char *paths[] = { "/etc/machine-id", "/var/lib/dbus/machine-id" };
  91. for (uint8_t i=0; i<ARRAY_SIZE(paths); i++) {
  92. int fd = open(paths[i], O_RDONLY);
  93. if (fd == -1) {
  94. continue;
  95. }
  96. ssize_t ret = read(fd, buf, len);
  97. close(fd);
  98. if (ret <= 0) {
  99. continue;
  100. }
  101. len = ret;
  102. char *p = strchr(cbuf, '\n');
  103. if (p) {
  104. *p = 0;
  105. }
  106. len = strnlen(cbuf, len);
  107. return true;
  108. }
  109. // fallback to hostname
  110. if (gethostname(cbuf, len) != 0) {
  111. // use a default name so this always succeeds. Without it we can't
  112. // implement some features (such as UAVCAN)
  113. strncpy(cbuf, HAL_LINUX_DEFAULT_SYSTEM_ID, len);
  114. }
  115. len = strnlen(cbuf, len);
  116. return true;
  117. }
  118. /*
  119. as get_system_id_unformatted will already be ascii, we use the same
  120. ID here
  121. */
  122. bool Util::get_system_id(char buf[40])
  123. {
  124. uint8_t len = 40;
  125. return get_system_id_unformatted((uint8_t *)buf, len);
  126. }
  127. int Util::write_file(const char *path, const char *fmt, ...)
  128. {
  129. errno = 0;
  130. int fd = open(path, O_WRONLY | O_CLOEXEC);
  131. if (fd == -1) {
  132. return -errno;
  133. }
  134. va_list args;
  135. va_start(args, fmt);
  136. int ret = vdprintf(fd, fmt, args);
  137. int errno_bkp = errno;
  138. close(fd);
  139. va_end(args);
  140. if (ret < 1) {
  141. return -errno_bkp;
  142. }
  143. return ret;
  144. }
  145. int Util::read_file(const char *path, const char *fmt, ...)
  146. {
  147. errno = 0;
  148. FILE *file = fopen(path, "re");
  149. if (!file) {
  150. return -errno;
  151. }
  152. va_list args;
  153. va_start(args, fmt);
  154. int ret = vfscanf(file, fmt, args);
  155. int errno_bkp = errno;
  156. fclose(file);
  157. va_end(args);
  158. if (ret < 1) {
  159. return -errno_bkp;
  160. }
  161. return ret;
  162. }
  163. const char *Linux::Util::_hw_names[UTIL_NUM_HARDWARES] = {
  164. [UTIL_HARDWARE_RPI1] = "BCM2708",
  165. [UTIL_HARDWARE_RPI2] = "BCM2709",
  166. [UTIL_HARDWARE_RPI4] = "BCM2711",
  167. [UTIL_HARDWARE_BEBOP] = "Mykonos3 board",
  168. [UTIL_HARDWARE_BEBOP2] = "Milos board",
  169. [UTIL_HARDWARE_DISCO] = "Evinrude board",
  170. };
  171. #define MAX_SIZE_LINE 50
  172. int Util::get_hw_arm32()
  173. {
  174. char buffer[MAX_SIZE_LINE] = { 0 };
  175. FILE *f = fopen("/proc/cpuinfo", "r");
  176. if (f == nullptr) {
  177. return -errno;
  178. }
  179. while (fgets(buffer, MAX_SIZE_LINE, f) != nullptr) {
  180. if (strstr(buffer, "Hardware") == nullptr) {
  181. continue;
  182. }
  183. for (uint8_t i = 0; i < UTIL_NUM_HARDWARES; i++) {
  184. if (strstr(buffer, _hw_names[i]) == nullptr) {
  185. continue;
  186. }
  187. fclose(f);
  188. return i;
  189. }
  190. }
  191. fclose(f);
  192. return -ENOENT;
  193. }
  194. #ifdef ENABLE_HEAP
  195. void *Util::allocate_heap_memory(size_t size)
  196. {
  197. struct heap *new_heap = (struct heap*)malloc(sizeof(struct heap));
  198. if (new_heap != nullptr) {
  199. new_heap->max_heap_size = size;
  200. new_heap->current_heap_usage = 0;
  201. }
  202. return (void *)new_heap;
  203. }
  204. void *Util::heap_realloc(void *h, void *ptr, size_t new_size)
  205. {
  206. if (h == nullptr) {
  207. return nullptr;
  208. }
  209. struct heap *heapp = (struct heap*)h;
  210. // extract appropriate headers
  211. size_t old_size = 0;
  212. heap_allocation_header *old_header = nullptr;
  213. if (ptr != nullptr) {
  214. old_header = ((heap_allocation_header *)ptr) - 1;
  215. old_size = old_header->allocation_size;
  216. }
  217. if ((heapp->current_heap_usage + new_size - old_size) > heapp->max_heap_size) {
  218. // fail the allocation as we don't have the memory. Note that we don't simulate fragmentation
  219. return nullptr;
  220. }
  221. heapp->current_heap_usage -= old_size;
  222. if (new_size == 0) {
  223. free(old_header);
  224. return nullptr;
  225. }
  226. heap_allocation_header *new_header = (heap_allocation_header *)malloc(new_size + sizeof(heap_allocation_header));
  227. if (new_header == nullptr) {
  228. // total failure to allocate, this is very surprising in SITL
  229. return nullptr;
  230. }
  231. heapp->current_heap_usage += new_size;
  232. new_header->allocation_size = new_size;
  233. void *new_mem = new_header + 1;
  234. if (ptr == nullptr) {
  235. return new_mem;
  236. }
  237. memcpy(new_mem, ptr, old_size > new_size ? new_size : old_size);
  238. free(old_header);
  239. return new_mem;
  240. }
  241. #endif // ENABLE_HEAP