kernel.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  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.h
  10. * \author zimmerli
  11. * \date 2020-01-10
  12. * \brief Kernel functions
  13. *
  14. */
  15. #ifndef KERNEL_H_
  16. #define KERNEL_H_
  17. #include <stdint.h>
  18. #include <stdarg.h>
  19. #include <string.h>
  20. #include <stdbool.h>
  21. /* FreeRTOS includes. */
  22. #include "FreeRTOS.h"
  23. //#include "FreeRTOS_CLI.h"
  24. #include "task.h"
  25. #include "semphr.h"
  26. #include <tsn_rtos_config.h>
  27. /*
  28. * Definitions
  29. */
  30. #define KERNEL_PRIO_BG 0
  31. #define KERNEL_PRIO_NORMAL 1
  32. #define KERNEL_PRIO_HIGH 2
  33. #define KERNEL_PRINTK_BLOCKTIME 1000
  34. #define KERNEL_TASK_FPU() portTASK_USES_FLOATING_POINT()
  35. #define ENDLESS_LOOP \
  36. while (1) { \
  37. portNOP(); \
  38. vTaskDelay(1000); \
  39. }
  40. typedef uintptr_t addr_t;
  41. ////////////////////////////////////////////////////////////////////////////////////////
  42. //TODO deprecated
  43. /*
  44. * Memory/Register access macro
  45. *
  46. * Access is expected to be aligned!
  47. */
  48. #define MEM8(addr) (*(volatile uint8_t *)(addr_t)(addr))
  49. #define MEM16(addr) (*(volatile uint16_t *)(addr_t)(addr))
  50. #define MEM32(addr) (*(volatile uint32_t *)(addr_t)(addr))
  51. #define MAC_LO(mac) (uint32_t)(mac[0] | (mac[1] << 8) | (mac[2] << 16) | (mac[3] << 24))
  52. #define MAC_HI(mac) (uint32_t)(mac[4] | (mac[5] << 8))
  53. ////////////////////////////////////////////////////////////////////////////////////////
  54. typedef void (*irq_callback_t)(void *context);
  55. /*
  56. * Platform specific
  57. *
  58. * functions must be defined in arch dependent code under arch/
  59. *
  60. */
  61. /**
  62. * \brief Initialize platform
  63. */
  64. void platform_init(void);
  65. /**
  66. * \brief Reboot platform
  67. */
  68. void platform_reset(void);
  69. /**
  70. * \brief wrapper to variadic function of platform printf
  71. *
  72. * @param format format string
  73. * @param arg argument list
  74. * @return number of printed bytes
  75. */
  76. int platform_vprintk(const char *format, va_list arg);
  77. /**
  78. * \brief Register interrupt handler
  79. *
  80. * @param id interrupt number
  81. * @param callback interrupt handler function
  82. * @param context pointer to object used by interrupt handler
  83. */
  84. void platform_register_irq(uint32_t id, irq_callback_t callback, void *context);
  85. /**
  86. * \brief Enable interupt
  87. *
  88. * @param id interrupt number
  89. */
  90. void platform_enable_irq(uint32_t id);
  91. ///////////////////////////////////
  92. //TODO old, deprecated
  93. /*
  94. * Kernel printk and logging
  95. */
  96. int printk(const char *format, ...);
  97. int printk_unsafe(const char *format, ...);
  98. ///////////////////////////////////
  99. char *_itoa(int value, char *str, int base);
  100. char *_ltoa(long value, char *str, int base);
  101. //use logs, logc, loge (see defines below); don't use internal_logk directly
  102. typedef enum {
  103. PRINT,
  104. ONE_LINE,
  105. START,
  106. CONT,
  107. END
  108. } log_mode;
  109. void internal_logk(log_mode mode, int level, const char *ctx, const char *file, int line, const char *func, const char *format, ...);
  110. 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);
  111. //log control
  112. //#define MAX_LOG_FORMAT_BUFFER_SIZE (128)
  113. //#define LOG_LIKEPRINT
  114. //TODO evtl Namen und Werte der Loglevel anpassen an "Standard" (see log4j)
  115. //log level
  116. #define LOG_LOWEST_LEVEL LOG_ALWAYS
  117. #define LOG_ALWAYS 1
  118. #define LOG_ERROR 2
  119. #define LOG_WARNING 3
  120. #define LOG_INFO 4
  121. #define LOG_DEBUG 5
  122. #define LOG_REGISTER 6
  123. #define LOG_HIGHEST_LEVEL LOG_REGISTER
  124. #ifndef MAX_LOG_LEVEL
  125. #define MAX_LOG_LEVEL LOG_REGISTER
  126. #endif
  127. #ifndef DEFAULT_LOG_LEVEL
  128. #define DEFAULT_LOG_LEVEL LOG_DEBUG
  129. #endif
  130. #ifndef LOG_FILEINFO
  131. #define LOG_FILEINFO 1
  132. #endif
  133. //TODO logs, logc, loge
  134. #ifdef LOG_LIKEPRINT
  135. #pragma GCC diagnostic ignored "-Wunused-variable"
  136. #define logk(level, ctx, format, ...) \
  137. do { \
  138. if (MAX_LOG_LEVEL >= level) \
  139. internal_logk(PRINT, level, ctx, NULL, 0, NULL, format, ##__VA_ARGS__); \
  140. } while (0)
  141. #define logs(level, ctx, format, ...) \
  142. do { \
  143. if (MAX_LOG_LEVEL >= level) \
  144. internal_logk(PRINT, level, ctx, NULL, 0, NULL, format, ##__VA_ARGS__); \
  145. } while (0)
  146. #define logc(level, format, ...) \
  147. do { \
  148. if (MAX_LOG_LEVEL >= level) \
  149. internal_logk(PRINT, level, NULL, NULL, 0, NULL, format, ##__VA_ARGS__); \
  150. } while (0)
  151. #define loge(level, format, ...) \
  152. do { \
  153. if (MAX_LOG_LEVEL >= level) \
  154. internal_logk(PRINT, level, NULL, NULL, 0, NULL, format, ##__VA_ARGS__); \
  155. } while (0)
  156. #else
  157. #if LOG_FILEINFO == 1
  158. #define __FILENAME__ (strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__)
  159. #define logk(level, ctx, format, ...) \
  160. do { \
  161. if (MAX_LOG_LEVEL >= level) \
  162. internal_logk(ONE_LINE, level, ctx, __FILENAME__, __LINE__, __FUNCTION__, format, ##__VA_ARGS__); \
  163. } while (0)
  164. #define logs(level, ctx, format, ...) \
  165. do { \
  166. if (MAX_LOG_LEVEL >= level) \
  167. internal_logk(START, level, ctx, __FILENAME__, __LINE__, __FUNCTION__, format, ##__VA_ARGS__); \
  168. } while (0)
  169. #define logc(level, format, ...) \
  170. do { \
  171. if (MAX_LOG_LEVEL >= level) \
  172. internal_logk(CONT, level, NULL, __FILENAME__, __LINE__, __FUNCTION__, format, ##__VA_ARGS__); \
  173. } while (0)
  174. #define loge(level, format, ...) \
  175. do { \
  176. if (MAX_LOG_LEVEL >= level) \
  177. internal_logk(END, level, NULL, __FILENAME__, __LINE__, __FUNCTION__, format, ##__VA_ARGS__); \
  178. } while (0)
  179. #else
  180. #define logk(level, ctx, format, ...) \
  181. do { \
  182. if (MAX_LOG_LEVEL >= level) \
  183. internal_logk(ONE_LINE, level, ctx, NULL, 0, NULL, format, ##__VA_ARGS__); \
  184. } while (0)
  185. #define logs(level, ctx, format, ...) \
  186. do { \
  187. if (MAX_LOG_LEVEL >= level) \
  188. internal_logk(START, level, ctx, NULL, 0, NULL, format, ##__VA_ARGS__); \
  189. } while (0)
  190. #define logc(level, format, ...) \
  191. do { \
  192. if (MAX_LOG_LEVEL >= level) \
  193. internal_logk(CONT, level, NULL, NULL, 0, NULL, format, ##__VA_ARGS__); \
  194. } while (0)
  195. #define loge(level, format, ...) \
  196. do { \
  197. if (MAX_LOG_LEVEL >= level) \
  198. internal_logk(END, level, NULL, NULL, 0, NULL, format, ##__VA_ARGS__); \
  199. } while (0)
  200. #endif
  201. #endif
  202. void set_runtime_max_loglevel(uint8_t level);
  203. void switch_loglevel_printmode(bool printmode);
  204. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  205. #define WREG32(addr, value, ctx, regname) \
  206. { \
  207. logk(LOG_REGISTER, ctx, "write to reg %s @ %#X%04X = %#X\n", regname, ((addr) >> 16), ((addr) & 0xFFFF), value); \
  208. MEM32(addr) = *((uint32_t *)&value); \
  209. }
  210. #define RREG32(addr, variable, ctx, regname) \
  211. { \
  212. uint32_t _reg = MEM32(addr); \
  213. logk(LOG_REGISTER, ctx, "read from reg %s @ %#X%04X = %#X\n", regname, ((addr) >> 16), ((addr) & 0xFFFF), _reg); \
  214. *((uint32_t *)(variable)) = _reg; \
  215. }
  216. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  217. ///////////////////////////////////
  218. /*
  219. * Kernel init
  220. */
  221. void kernel_init(addr_t addr, uint32_t size);
  222. void kernel_start(TaskFunction_t taskInitCode, uint16_t addStackSz);
  223. /*
  224. * create Task and assert if failed
  225. */
  226. //void kTaskCreatea(TaskFunction_t pxTaskCode, const char * const pcName, const configSTACK_DEPTH_TYPE usStackDepth, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pxCreatedTask);
  227. #define kTaskCreate_a(context, pxTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask) \
  228. { \
  229. uint32_t tmp; \
  230. tmp = xTaskCreate(pxTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask); \
  231. kassert(tmp == pdPASS); \
  232. }
  233. /*
  234. * create Task and return if failed
  235. */
  236. //void kTaskCreatea(TaskFunction_t pxTaskCode, const char * const pcName, const configSTACK_DEPTH_TYPE usStackDepth, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pxCreatedTask);
  237. #define kTaskCreate_r(context, pxTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask) \
  238. { \
  239. uint32_t tmp; \
  240. tmp = xTaskCreate(pxTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask); \
  241. if (tmp != pdPASS) \
  242. return; \
  243. }
  244. /*
  245. * create Task and print error if failed
  246. */
  247. //void kTaskCreatea(TaskFunction_t pxTaskCode, const char * const pcName, const configSTACK_DEPTH_TYPE usStackDepth, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pxCreatedTask);
  248. #define kTaskCreate_e(context, pxTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask) \
  249. { \
  250. uint32_t tmp; \
  251. tmp = xTaskCreate(pxTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask); \
  252. printf("starting task '%s' ... %s\n", pcName, (tmp == pdPASS ? "done" : "failed")); \
  253. }
  254. /*
  255. * Memory mgmt
  256. */
  257. void *kallocz(size_t size);
  258. void *kalloczl(size_t size, const char *ctx);
  259. char *kstrdup(char *str);
  260. void kfree(void *p);
  261. void kfreeN(void **pv);
  262. #define KfreeN(pointer) kfreeN((void **)&(pointer))
  263. struct netb_s *kalloc_netb(uint32_t timeout);
  264. void kfree_netb(struct netb_s *netb);
  265. UBaseType_t kavail_netb(void);
  266. /*
  267. * Assertion
  268. */
  269. #define kassert(condition) configASSERT(condition)
  270. //void kassert(int condition);
  271. uint32_t _ns_to_systicks(uint32_t time_ns, uint32_t busfreq);
  272. uint32_t _systicks_to_ns(uint32_t time_ticks, uint32_t busfreq);
  273. #define UNKNOWN_PORT (int32_t)(-1)
  274. //eth1 -> 0; eth2 -> 1
  275. int32_t interface_string2index(const char *pstring);
  276. //0 -> eth1; 1 -> eth2
  277. char *interface_index2string(int32_t index, char *str);
  278. //cpu -> 0; eth1 -> 1; eth2 -> 2
  279. int32_t interface_string2port(const char *pstring);
  280. //0 -> cpu; 1 -> eth1; 2 -> eth2
  281. char *interface_port2string(int32_t port, char *str);
  282. ///////////////////////////////////////////////////////////////////////////////
  283. ///////////////////////////////////////////////////////////////////////////////
  284. ///////////////////////////////////////////////////////////////////////////////
  285. //TODO verschieben nach klib.c/klib.h
  286. uint8_t *mac_string2int(const char *psMac, uint8_t *piMac);
  287. char *mac_int2string(char *psMac, uint8_t *piMac);
  288. //void mac_hilo2int(uint32_t machi, uint32_t maclo, uint8_t *piMac);
  289. int str2long(const char *context, long long int *value, const char *svalue, int base);
  290. const char *system_name_get(void);
  291. const char *system_desc_get(void);
  292. #endif /* KERNEL_H_ */