portmacro.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355
  1. /*
  2. * SPDX-FileCopyrightText: 2020 Amazon.com, Inc. or its affiliates
  3. *
  4. * SPDX-License-Identifier: MIT
  5. *
  6. * SPDX-FileContributor: 2016-2022 Espressif Systems (Shanghai) CO LTD
  7. */
  8. /*
  9. * FreeRTOS Kernel V10.4.3
  10. * Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  11. *
  12. * Permission is hereby granted, free of charge, to any person obtaining a copy of
  13. * this software and associated documentation files (the "Software"), to deal in
  14. * the Software without restriction, including without limitation the rights to
  15. * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  16. * the Software, and to permit persons to whom the Software is furnished to do so,
  17. * subject to the following conditions:
  18. *
  19. * The above copyright notice and this permission notice shall be included in all
  20. * copies or substantial portions of the Software.
  21. *
  22. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  23. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  24. * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  25. * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  26. * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  27. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  28. *
  29. * http://www.FreeRTOS.org
  30. * http://aws.amazon.com/freertos
  31. *
  32. * 1 tab == 4 spaces!
  33. */
  34. #ifndef PORTMACRO_H
  35. #define PORTMACRO_H
  36. #ifndef __ASSEMBLER__
  37. #include "sdkconfig.h"
  38. #include <stdint.h>
  39. #include <stdlib.h>
  40. #include <stdbool.h>
  41. #include <stdio.h>
  42. #include "spinlock.h"
  43. #include "soc/interrupt_core0_reg.h"
  44. #include "esp_macros.h"
  45. #include "esp_attr.h"
  46. #include "esp_cpu.h"
  47. #include "esp_rom_sys.h"
  48. #include "esp_heap_caps.h"
  49. #include "esp_system.h" /* required by esp_get_...() functions in portable.h. [refactor-todo] Update portable.h */
  50. #include "esp_newlib.h"
  51. #include "rtthread.h"
  52. /* [refactor-todo] These includes are not directly used in this file. They are kept into to prevent a breaking change. Remove these. */
  53. #include <limits.h>
  54. /* [refactor-todo] introduce a port wrapper function to avoid including esp_timer.h into the public header */
  55. #if CONFIG_FREERTOS_RUN_TIME_STATS_USING_ESP_TIMER
  56. #include "esp_timer.h"
  57. #endif
  58. #ifdef __cplusplus
  59. extern "C" {
  60. #endif
  61. /* --------------------------------------------------- Port Types ------------------------------------------------------
  62. * - Port specific types.
  63. * - The settings in this file configure FreeRTOS correctly for the given hardware and compiler.
  64. * - These settings should not be altered.
  65. * - The port types must come first as they are used further down in this file
  66. * ------------------------------------------------------------------------------------------------------------------ */
  67. #define portCHAR char
  68. #define portFLOAT float
  69. #define portDOUBLE double
  70. #define portLONG long
  71. #define portSHORT short
  72. #define portSTACK_TYPE rt_ubase_t
  73. #define portBASE_TYPE rt_base_t
  74. typedef portSTACK_TYPE StackType_t;
  75. typedef rt_base_t BaseType_t;
  76. typedef rt_ubase_t UBaseType_t;
  77. typedef rt_tick_t TickType_t;
  78. #define portMAX_DELAY (TickType_t) RT_TICK_MAX
  79. struct rt_semaphore_wrapper
  80. {
  81. struct rt_semaphore sem;
  82. rt_uint16_t max_value;
  83. };
  84. /* ----------------------------------------------- Port Configurations -------------------------------------------------
  85. * - Configurations values supplied by each port
  86. * - Required by FreeRTOS
  87. * ------------------------------------------------------------------------------------------------------------------ */
  88. #define portTICK_PERIOD_MS ((TickType_t) (1000 / configTICK_RATE_HZ))
  89. #define portBYTE_ALIGNMENT RT_ALIGN_SIZE
  90. #define portNOP() __asm volatile (" nop ")
  91. /* ---------------------------------------------- Forward Declarations -------------------------------------------------
  92. * - Forward declarations of all the port functions and macros need to implement the FreeRTOS porting interface
  93. * - These must come before definition/declaration of the FreeRTOS porting interface
  94. * ------------------------------------------------------------------------------------------------------------------ */
  95. // --------------------- Interrupts ------------------------
  96. /**
  97. * @brief Checks if the current core is in an ISR context
  98. *
  99. * - ISR context consist of Low/Mid priority ISR, or time tick ISR
  100. * - High priority ISRs aren't detected here, but they normally cannot call C code, so that should not be an issue anyway.
  101. *
  102. * @note [refactor-todo] Check if this should be inlined
  103. * @return
  104. * - pdTRUE if in ISR
  105. * - pdFALSE otherwise
  106. */
  107. BaseType_t xPortInIsrContext(void);
  108. /**
  109. * @brief Check if in ISR context from High priority ISRs
  110. *
  111. * - Called from High priority ISR
  112. * - Checks if the previous context (before high priority interrupt) was in ISR context (meaning low/med priority)
  113. *
  114. * @note [refactor-todo] Check if this should be inlined
  115. * @return
  116. * - pdTRUE if in previous in ISR context
  117. * - pdFALSE otherwise
  118. */
  119. BaseType_t xPortInterruptedFromISRContext(void);
  120. /* ---------------------- Spinlocks ------------------------
  121. - Spinlocks added to match API with SMP FreeRTOS. Single core RISC-V does not need spin locks
  122. - Because single core does not have a primitive spinlock data type, we have to implement one here
  123. * @note [refactor-todo] Refactor critical section API so that this is no longer required
  124. * ------------------------------------------------------ */
  125. /**
  126. * @brief Spinlock object
  127. * Owner:
  128. * - Set to 0 if uninitialized
  129. * - Set to portMUX_FREE_VAL when free
  130. * - Set to CORE_ID_REGVAL_PRO or CORE_ID_REGVAL_AP when locked
  131. * - Any other value indicates corruption
  132. * Count:
  133. * - 0 if unlocked
  134. * - Recursive count if locked
  135. *
  136. * @note Not a true spinlock as single core RISC-V does not have atomic compare and set instruction
  137. * @note Keep portMUX_INITIALIZER_UNLOCKED in sync with this struct
  138. */
  139. typedef struct {
  140. uint32_t owner;
  141. uint32_t count;
  142. } portMUX_TYPE;
  143. /**< Spinlock initializer */
  144. #define portMUX_INITIALIZER_UNLOCKED { \
  145. .owner = portMUX_FREE_VAL, \
  146. .count = 0, \
  147. }
  148. #define portMUX_FREE_VAL SPINLOCK_FREE /**< Spinlock is free. [refactor-todo] check if this is still required */
  149. #define portMUX_NO_TIMEOUT SPINLOCK_WAIT_FOREVER /**< When passed for 'timeout_cycles', spin forever if necessary. [refactor-todo] check if this is still required */
  150. #define portMUX_TRY_LOCK SPINLOCK_NO_WAIT /**< Try to acquire the spinlock a single time only. [refactor-todo] check if this is still required */
  151. #define portMUX_INITIALIZE(mux) ({ \
  152. (mux)->owner = portMUX_FREE_VAL; \
  153. (mux)->count = 0; \
  154. })
  155. // ------------------ Critical Sections --------------------
  156. /**
  157. * @brief Enter a critical section
  158. *
  159. * - Simply disable interrupts
  160. * - Can be nested
  161. */
  162. void vPortEnterCritical(void);
  163. /**
  164. * @brief Exit a critical section
  165. *
  166. * - Reenables interrupts
  167. * - Can be nested
  168. */
  169. void vPortExitCritical(void);
  170. // ---------------------- Yielding -------------------------
  171. /**
  172. * @brief Perform a context switch from a task
  173. *
  174. * @note [refactor-todo] The rest of ESP-IDF should call taskYield() instead
  175. */
  176. #define vPortYield(void) rt_thread_yield()
  177. /**
  178. * @brief Checks if the current core can yield
  179. *
  180. * - A core cannot yield if its in an ISR or in a critical section
  181. *
  182. * @note [refactor-todo] See if this can be separated from port macro
  183. * @note [refactor-todo] Check if this function should be renamed (due to bool return type)
  184. * @return true Core can yield
  185. * @return false Core cannot yield
  186. */
  187. FORCE_INLINE_ATTR bool xPortCanYield(void);
  188. // ----------------------- System --------------------------
  189. /**
  190. * @brief Get the tick rate per second
  191. *
  192. * @note [refactor-todo] make this inline
  193. * @note [refactor-todo] Check if this function should be renamed (due to uint return type)
  194. * @return uint32_t Tick rate in Hz
  195. */
  196. uint32_t xPortGetTickRateHz(void);
  197. /**
  198. * @brief Set a watchpoint to watch the last 32 bytes of the stack
  199. *
  200. * Callback to set a watchpoint on the end of the stack. Called every context switch to change the stack watchpoint
  201. * around.
  202. *
  203. * @param pxStackStart Pointer to the start of the stack
  204. */
  205. void vPortSetStackWatchpoint(void *pxStackStart);
  206. /**
  207. * @brief Get the current core's ID
  208. *
  209. * @note Added to be compatible with SMP API
  210. * @note [refactor-todo] IDF should call a FreeRTOS like macro instead of port function directly
  211. * @return BaseType_t Core ID
  212. */
  213. FORCE_INLINE_ATTR BaseType_t xPortGetCoreID(void)
  214. {
  215. return (BaseType_t) esp_cpu_get_core_id();
  216. }
  217. /* ------------------------------------------- FreeRTOS Porting Interface ----------------------------------------------
  218. * - Contains all the mappings of the macros required by FreeRTOS
  219. * - Most come after forward declare as porting macros map to declared functions
  220. * - Maps to forward declared functions
  221. * ------------------------------------------------------------------------------------------------------------------ */
  222. // --------------------- Interrupts ------------------------
  223. #define portDISABLE_INTERRUPTS() vPortEnterCritical()
  224. #define portENABLE_INTERRUPTS() vPortExitCritical()
  225. #define portSET_INTERRUPT_MASK_FROM_ISR() rt_hw_interrupt_disable()
  226. #define portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedStatusValue) rt_hw_interrupt_enable(uxSavedStatusValue)
  227. // ------------------ Critical Sections --------------------
  228. #define portENTER_CRITICAL(mux) {(void)mux; vPortEnterCritical();}
  229. #define portEXIT_CRITICAL(mux) {(void)mux; vPortExitCritical();}
  230. #define portTRY_ENTER_CRITICAL(mux, timeout) ({ \
  231. (void)mux; (void)timeout; \
  232. vPortEnterCritical(); \
  233. BaseType_t ret = pdPASS; \
  234. ret; \
  235. })
  236. //In single-core RISC-V, we can use the same critical section API
  237. #define portENTER_CRITICAL_ISR(mux) portENTER_CRITICAL(mux)
  238. #define portEXIT_CRITICAL_ISR(mux) portEXIT_CRITICAL(mux)
  239. #define portTRY_ENTER_CRITICAL_ISR(mux, timeout) portTRY_ENTER_CRITICAL(mux, timeout)
  240. /* [refactor-todo] on RISC-V, both ISR and non-ISR cases result in the same call. We can redefine this macro */
  241. #define portENTER_CRITICAL_SAFE(mux) ({ \
  242. if (xPortInIsrContext()) { \
  243. portENTER_CRITICAL_ISR(mux); \
  244. } else { \
  245. portENTER_CRITICAL(mux); \
  246. } \
  247. })
  248. #define portEXIT_CRITICAL_SAFE(mux) ({ \
  249. if (xPortInIsrContext()) { \
  250. portEXIT_CRITICAL_ISR(mux); \
  251. } else { \
  252. portEXIT_CRITICAL(mux); \
  253. } \
  254. })
  255. #define portTRY_ENTER_CRITICAL_SAFE(mux, timeout) portENTER_CRITICAL_SAFE(mux, timeout)
  256. // ---------------------- Yielding -------------------------
  257. #define portYIELD() rt_thread_yield()
  258. #define portYIELD_FROM_ISR_NO_ARG() rt_thread_yield()
  259. #define portYIELD_FROM_ISR_ARG(xHigherPriorityTaskWoken) ({ \
  260. if (xHigherPriorityTaskWoken == pdTRUE) { \
  261. rt_thread_yield(); \
  262. } \
  263. })
  264. /**
  265. * @note The macro below could be used when passing a single argument, or without any argument,
  266. * it was developed to support both usages of portYIELD inside of an ISR. Any other usage form
  267. * might result in undesired behavior
  268. */
  269. #if defined(__cplusplus) && (__cplusplus > 201703L)
  270. #define portYIELD_FROM_ISR(...) CHOOSE_MACRO_VA_ARG(portYIELD_FROM_ISR_ARG, portYIELD_FROM_ISR_NO_ARG __VA_OPT__(,) __VA_ARGS__)(__VA_ARGS__)
  271. #else
  272. #define portYIELD_FROM_ISR(...) CHOOSE_MACRO_VA_ARG(portYIELD_FROM_ISR_ARG, portYIELD_FROM_ISR_NO_ARG, ##__VA_ARGS__)(__VA_ARGS__)
  273. #endif
  274. /* --------------------------------------------- Inline Implementations ------------------------------------------------
  275. * - Implementation of inline functions of the forward declares
  276. * - Should come after forward declare and FreeRTOS Porting interface, as implementation may use both.
  277. * - For implementation of non-inlined functions, see port.c, port_common.c, or other assembly files
  278. * ------------------------------------------------------------------------------------------------------------------ */
  279. // --------------------- Interrupts ------------------------
  280. // ---------------------- Yielding -------------------------
  281. FORCE_INLINE_ATTR bool xPortCanYield(void)
  282. {
  283. rt_base_t level = rt_interrupt_get_nest();
  284. return (level == 0);
  285. }
  286. #define FREERTOS_PRIORITY_TO_RTTHREAD(priority) ( configMAX_PRIORITIES - 1 - ( priority ) )
  287. #define RTTHREAD_PRIORITY_TO_FREERTOS(priority) ( RT_THREAD_PRIORITY_MAX - 1 - ( priority ) )
  288. /* Use this macro to calculate the buffer size when allocating a queue statically
  289. * To ensure the buffer can fit the desired number of messages
  290. */
  291. #define QUEUE_BUFFER_SIZE( uxQueueLength, uxItemSize ) ( ( RT_ALIGN( uxItemSize, RT_ALIGN_SIZE ) + sizeof( void * ) ) * uxQueueLength )
  292. BaseType_t rt_err_to_freertos(rt_err_t rt_err);
  293. #if CONFIG_APPTRACE_SV_ENABLE
  294. extern int xPortSwitchFlag;
  295. #define os_task_switch_is_pended(_cpu_) (xPortSwitchFlag)
  296. #else
  297. #define os_task_switch_is_pended(_cpu_) (false)
  298. #endif
  299. #ifdef __cplusplus
  300. }
  301. #endif
  302. #endif //__ASSEMBLER__
  303. #endif /* PORTMACRO_H */