kernel.c 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449
  1. /*!
  2. * Copyright (C) Fraunhofer-Institut for Photonic Microsystems (IPMS)
  3. * Maria-Reiche-Str. 2
  4. * 01109 Dresden
  5. *
  6. * Unauthorized copying of this file, via any medium is strictly prohibited
  7. * Proprietary and confidential
  8. *
  9. * \file kernel.c
  10. * \author zimmerli
  11. * \date 2020-01-10
  12. * \brief Kernel functions
  13. *
  14. */
  15. #include "kernel.h"
  16. #include <stdarg.h>
  17. #include <string.h>
  18. #include <stdbool.h>
  19. #include <string.h>
  20. #include <stdlib.h>
  21. #include <stdio.h>
  22. #include <errno.h>
  23. #include <stdbool.h>
  24. #include <kernel/net/phydev.h>
  25. #include <kernel/net/netb.h>
  26. //check TSN RTOS configuration
  27. #include "config.h"
  28. // ----------------------------------------------------------------
  29. #define NETBUF_SZ 2048
  30. #define NETBUF_OFS_HEAD 64
  31. typedef struct netb_s *netb_ptr;
  32. /**
  33. * \brief Kernel management structure
  34. */
  35. struct kernel_s {
  36. TaskHandle_t task_init; //!< handle of init task
  37. SemaphoreHandle_t sem_print; //!< printk lock
  38. QueueHandle_t qeueue_netb; //!< queue of empty struct netb_s
  39. };
  40. /**
  41. * \brief Kernel management
  42. */
  43. struct kernel_s _kernel_data;
  44. // ----------------------------------------------------------------
  45. /**
  46. * \brief Initialize Kernel
  47. *
  48. * @param addr address of free memory to be used by network buffer
  49. * @param size size of memory to be used network buffer
  50. */
  51. void kernel_init(addr_t addr, uint32_t size)
  52. {
  53. addr_t endaddr;
  54. uint32_t minqsize;
  55. uint32_t tmp;
  56. netb_ptr netb;
  57. /* init printk semaphore */
  58. _kernel_data.sem_print = xSemaphoreCreateMutex();
  59. configASSERT(_kernel_data.sem_print != NULL);
  60. /* init netb */
  61. // create queue
  62. minqsize = size / NETBUF_SZ;
  63. _kernel_data.qeueue_netb = xQueueCreate(minqsize, sizeof(netb_ptr));
  64. configASSERT(_kernel_data.qeueue_netb != NULL);
  65. // check assumption sizeof(struct netb_s) <= NETBUF_OFS_HEAD
  66. configASSERT(sizeof(struct netb_s) <= NETBUF_OFS_HEAD);
  67. // set empty netb
  68. endaddr = addr + size - NETBUF_SZ;
  69. while (addr <= endaddr) {
  70. // set pointer
  71. netb = (netb_ptr)(addr);
  72. // fill data
  73. netb->head = addr + NETBUF_OFS_HEAD;
  74. netb->end = addr + NETBUF_SZ;
  75. netb->data = netb->head;
  76. netb->tail = netb->head;
  77. // send to queue
  78. tmp = xQueueSend(_kernel_data.qeueue_netb, &netb, 0);
  79. configASSERT(tmp == pdPASS);
  80. // inc addr
  81. addr += NETBUF_SZ;
  82. }
  83. }
  84. /**
  85. * \brief Start Kernel, start init task
  86. *
  87. * @param taskInitCode init function pointer
  88. * @param addStackSz stack size needed by init task, additional to configMINIMAL_STACK_SIZE
  89. */
  90. void kernel_start(TaskFunction_t taskInitCode, uint16_t addStackSz)
  91. {
  92. /* create sys task */
  93. kTaskCreate_a("KERNEL", taskInitCode, "init", configMINIMAL_STACK_SIZE + addStackSz, NULL, KERNEL_PRIO_HIGH, &_kernel_data.task_init);
  94. /* Start scheduler */
  95. vTaskStartScheduler();
  96. }
  97. // ----------------------------------------------------------------
  98. void swap(char *x, char *y)
  99. {
  100. char tmp = *x;
  101. *x = *y;
  102. *y = tmp;
  103. }
  104. /* A utility function to reverse a string */
  105. void reverse(char str[], int length)
  106. {
  107. int start = 0;
  108. int end = length - 1;
  109. while (start < end) {
  110. swap((str + start), (str + end));
  111. start++;
  112. end--;
  113. }
  114. }
  115. // Implementation of itoa()
  116. char *_itoa(int num, char *str, int base)
  117. {
  118. int i = 0;
  119. bool isNegative = false;
  120. /* Handle 0 explicitely, otherwise empty string is printed for 0 */
  121. if (num == 0) {
  122. str[i++] = '0';
  123. str[i] = '\0';
  124. return str;
  125. }
  126. // In standard itoa(), negative numbers are handled only with
  127. // base 10. Otherwise numbers are considered unsigned.
  128. if (num < 0 && base == 10) {
  129. isNegative = true;
  130. num = -num;
  131. }
  132. // Process individual digits
  133. while (num != 0) {
  134. int rem = num % base;
  135. str[i++] = (rem > 9) ? (rem - 10) + 'a' : rem + '0';
  136. num = num / base;
  137. }
  138. // If number is negative, append '-'
  139. if (isNegative)
  140. str[i++] = '-';
  141. str[i] = '\0'; // Append string terminator
  142. // Reverse the string
  143. reverse(str, i);
  144. return str;
  145. }
  146. #define BUFSIZE (sizeof(long) * 8 + 1)
  147. char *_ltoa(long N, char *str, int base)
  148. {
  149. register int i = 2;
  150. long uarg;
  151. char *tail, *head = str, buf[BUFSIZE];
  152. if (36 < base || 2 > base)
  153. base = 10; /* can only use 0-9, A-Z */
  154. tail = &buf[BUFSIZE - 1]; /* last character position */
  155. *tail-- = '\0';
  156. if (10 == base && N < 0L) {
  157. *head++ = '-';
  158. uarg = -N;
  159. } else
  160. uarg = N;
  161. if (uarg) {
  162. for (i = 1; uarg; ++i) {
  163. register ldiv_t r;
  164. r = ldiv(uarg, base);
  165. *tail-- = (char)(r.rem + ((9L < r.rem) ? ('A' - 10L) : '0'));
  166. uarg = r.quot;
  167. }
  168. } else
  169. *tail-- = '0';
  170. memcpy(head, ++tail, i);
  171. return str;
  172. }
  173. // ----------------------------------------------------------------
  174. static bool indent_enabled = true;
  175. void __internal_set_indent(void)
  176. {
  177. indent_enabled = true;
  178. }
  179. void __internal_unset_indent(void)
  180. {
  181. indent_enabled = false;
  182. }
  183. static uint8_t rt_max_log_level = DEFAULT_LOG_LEVEL;
  184. static bool rt_log_print_mode = false;
  185. void set_runtime_max_loglevel(uint8_t level)
  186. {
  187. rt_max_log_level = level;
  188. }
  189. void switch_loglevel_printmode(bool printmode)
  190. {
  191. rt_log_print_mode = printmode;
  192. }
  193. /**
  194. * \brief logging function
  195. *
  196. * @param format format string
  197. */
  198. void internal_logk(log_mode mode, int level, const char *ctx, const char *file, int line, const char *func, const char *format, ...)
  199. {
  200. (void)mode;
  201. (void)level;
  202. (void)ctx;
  203. (void)file;
  204. (void)line;
  205. (void)func;
  206. (void)format;
  207. }
  208. void internal_vlogk(log_mode mode, int level, const char *ctx, const char *file, int line, const char *func, const char *format, va_list args)
  209. {
  210. (void)mode;
  211. (void)level;
  212. (void)ctx;
  213. (void)file;
  214. (void)line;
  215. (void)func;
  216. (void)format;
  217. (void)args;
  218. }
  219. // ----------------------------------------------------------------
  220. void *kalloczl(size_t size, const char *ctx)
  221. {
  222. void *p = kallocz(size);
  223. logk(LOG_ALWAYS, ctx, "allocate %d bytes %s\n", size, p == NULL ? "failed" : "ok");
  224. return p;
  225. }
  226. /**
  227. * \brief Allocate and zero memory
  228. *
  229. * @param size needed size in bytes
  230. * @return pointer to memory, NULL on error
  231. */
  232. void *kallocz(size_t size)
  233. {
  234. void *p;
  235. // allocate and zero memory
  236. p = pvPortMalloc(size);
  237. if (p) {
  238. memset(p, 0, size);
  239. }
  240. return p;
  241. }
  242. /**
  243. * \brief Duplicate string to new memory location
  244. * @param str string to duplicate
  245. * @return pointer to the newly allocated string, or a null pointer if an error occurred.
  246. */
  247. char *kstrdup(char *str)
  248. {
  249. char *dup;
  250. size_t size = strlen(str) + 1;
  251. dup = pvPortMalloc(size);
  252. if (dup) {
  253. memcpy(dup, str, size);
  254. }
  255. return dup;
  256. }
  257. /**
  258. * \brief free memory
  259. *
  260. * @param pv pointer to memory
  261. */
  262. void kfree(void *pv)
  263. {
  264. vPortFree(pv);
  265. }
  266. void kfreeN(void **pv)
  267. {
  268. vPortFree(*pv);
  269. *pv = NULL;
  270. }
  271. /**
  272. * \brief Allocate free network buffer
  273. *
  274. * @param timeout timeout for allocation
  275. * @return pointer to network buffer, NULL on error
  276. */
  277. struct netb_s *kalloc_netb(uint32_t timeout)
  278. {
  279. uint32_t tmp;
  280. netb_ptr netb;
  281. tmp = xQueueReceive(_kernel_data.qeueue_netb, &netb, timeout);
  282. if (tmp != pdPASS)
  283. netb = NULL;
  284. if (netb)
  285. netb_set_empty(netb);
  286. return netb;
  287. }
  288. /**
  289. * \brief Free network buffer
  290. *
  291. * @param netb pointer to network buffer
  292. */
  293. void kfree_netb(struct netb_s *netb)
  294. {
  295. uint32_t tmp;
  296. /* simple check for consistency */
  297. configASSERT((addr_t)(netb) + NETBUF_OFS_HEAD == netb->head);
  298. /* enqueue to list */
  299. tmp = xQueueSend(_kernel_data.qeueue_netb, &netb, 0);
  300. configASSERT(tmp == pdPASS);
  301. }
  302. UBaseType_t kavail_netb()
  303. {
  304. return uxQueueMessagesWaiting(_kernel_data.qeueue_netb);
  305. }
  306. // ----------------------------------------------------------------
  307. /**
  308. * Kernel assertion, stop system on error
  309. *
  310. * @param condition assertion condition
  311. */
  312. //void kassert(int condition) {
  313. // configASSERT(condition);
  314. //}
  315. uint32_t _ns_to_systicks(uint32_t time_ns, uint32_t busfreq)
  316. {
  317. uint64_t tmp;
  318. tmp = busfreq;
  319. tmp *= time_ns;
  320. tmp /= 1000000000LL;
  321. return tmp;
  322. }
  323. uint32_t _systicks_to_ns(uint32_t time_ticks, uint32_t busfreq)
  324. {
  325. uint64_t tmp;
  326. tmp = time_ticks;
  327. tmp = tmp * 1000000000LL;
  328. tmp /= busfreq;
  329. return tmp;
  330. }
  331. const char interface_string[] = "eth";
  332. const char cpu_string[] = "cpu";
  333. //TODO avoid sscanf
  334. uint8_t *mac_string2int(const char *psMac, uint8_t *piMac)
  335. {
  336. if (sscanf(psMac, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &piMac[0], &piMac[1], &piMac[2], &piMac[3], &piMac[4], &piMac[5]) != 6) {
  337. return NULL;
  338. }
  339. return piMac;
  340. }
  341. //TODO avoid sprintf
  342. char *mac_int2string(char *psMac, uint8_t *piMac)
  343. {
  344. sprintf(psMac, "%02X:%02X:%02X:%02X:%02X:%02X", piMac[0], piMac[1], piMac[2], piMac[3], piMac[4], piMac[5]);
  345. return psMac;
  346. }
  347. //TODO return int --> return bool; in utils.[hc] verschieben
  348. int str2long(const char *context, long long int *value, const char *svalue, int base)
  349. {
  350. char *strend;
  351. *value = strtoll(svalue, &strend, base);
  352. if (svalue == strend) {
  353. logk(LOG_ALWAYS, "UTILS", "%s: number '%s' invalid (no digits found)\n", context, svalue);
  354. return 1;
  355. } else if (errno != 0 && *value == 0) {
  356. logk(LOG_ALWAYS, "UTILS", "%s: number '%lu' invalid (unspecified error occurred)\n", context, *value);
  357. return 1;
  358. } else if (errno == 0 && svalue && *strend != 0) {
  359. logk(LOG_ALWAYS, "UTILS", "%s: number '%lu' valid (but additional characters remain)\n", context, *value);
  360. return 0;
  361. }
  362. return 0;
  363. }
  364. const char *system_name_get()
  365. {
  366. return "TSN RTOS Fraunhofer";
  367. }
  368. const char *system_desc_get()
  369. {
  370. return "TSN RTOS for Fraunhofer TSN-EP / TSN-SE / TSN-SW devices";
  371. }