cpuport.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. /*
  2. * File : cpuport.c
  3. * This file is part of RT-Thread RTOS
  4. * COPYRIGHT (C) 2006 - 2013, RT-Thread Development Team
  5. *
  6. * The license and distribution terms for this file may be
  7. * found in the file LICENSE in this distribution or at
  8. * http://www.rt-thread.org/license/LICENSE
  9. *
  10. * Change Logs:
  11. * Date Author Notes
  12. * 2009-01-05 Bernard first version
  13. * 2011-02-14 onelife Modify for EFM32
  14. * 2011-06-17 onelife Merge all of the C source code into cpuport.c
  15. * 2012-12-23 aozima stack addr align to 8byte.
  16. * 2012-12-29 Bernard Add exception hook.
  17. * 2013-07-09 aozima enhancement hard fault exception handler.
  18. */
  19. #include <rtthread.h>
  20. #include "nds32.h"
  21. /*
  22. * Initialise the stack of a task to look exactly as if a call to
  23. * SAVE_CONTEXT had been called.
  24. *
  25. * See header file for description.
  26. *
  27. *
  28. * Stack Layout:
  29. * High |-----------------|
  30. * | $R5 |
  31. * |-----------------|
  32. * | . |
  33. * | . |
  34. * |-----------------|
  35. * | $R0 |
  36. * |-----------------|
  37. * | $R30 (LP) |
  38. * |-----------------|
  39. * | $R29 (GP) |
  40. * |-----------------|
  41. * | $R28 (FP) |
  42. * |-----------------|
  43. * | $R15 $R27 |
  44. * |-----------------|
  45. * | $R10 $R26 |
  46. * |-----------------|
  47. * | . |
  48. * | . |
  49. * |-----------------|
  50. * | $R6 |
  51. * |-----------------|
  52. * | $IFC_LP | (Option)
  53. * |-----------------|
  54. * | $LC/$LE/$LB | (Option)
  55. * | (ZOL) |
  56. * |-----------------|
  57. * | $IPSW |
  58. * |-----------------|
  59. * | $IPC |
  60. * |-----------------|
  61. * | Dummy word | (Option, only exist when IFC & ZOL both configured)
  62. * |-----------------|
  63. * | $FPU | (Option)
  64. * |-----------------|
  65. * Low
  66. *
  67. */
  68. struct stack_frame
  69. {
  70. rt_uint32_t topOfStack[34];
  71. };
  72. /* flag in interrupt handling */
  73. rt_uint32_t rt_interrupt_from_thread, rt_interrupt_to_thread;
  74. rt_uint32_t rt_thread_switch_interrupt_flag;
  75. /* exception hook */
  76. static rt_err_t (*rt_exception_hook)(void *context) = RT_NULL;
  77. rt_base_t rt_hw_interrupt_disable(void)
  78. {
  79. rt_base_t level = __nds32__mfsr(NDS32_SR_PSW);
  80. GIE_DISABLE();
  81. return level;
  82. }
  83. void rt_hw_interrupt_enable(rt_base_t level)
  84. {
  85. if (level & PSW_mskGIE)
  86. GIE_ENABLE();
  87. }
  88. /* For relax support, must initial $gp at task init*/
  89. extern uint32_t _SDA_BASE_ __attribute__ ((weak));
  90. /**************************************************************
  91. * This function will initialize thread stack
  92. *
  93. * @param tentry the entry of thread
  94. * @param parameter the parameter of entry
  95. * @param stack_addr the beginning stack address
  96. * @param texit the function will be called when thread exit
  97. *
  98. * @return stack address
  99. **************************************************************/
  100. rt_uint8_t *rt_hw_stack_init(void *tentry,
  101. void *parameter,
  102. rt_uint8_t *stack_addr,
  103. void *texit)
  104. {
  105. rt_int32_t i;
  106. rt_uint32_t *pxTopOfStack;
  107. pxTopOfStack = (rt_uint32_t *)RT_ALIGN_DOWN((rt_uint32_t)stack_addr, 4);
  108. /* Simulate the stack frame as it would be created by a context switch */
  109. /* R0 ~ R5 registers */
  110. for (i = 5; i >= 1; i--) /* R5, R4, R3, R2 and R1. */
  111. *--pxTopOfStack = (rt_uint32_t)0x01010101UL * i;
  112. *--pxTopOfStack = (rt_uint32_t)parameter; /* R0 : Argument */
  113. /* R6 ~ R30 registers */
  114. *--pxTopOfStack = (rt_uint32_t)texit; /* R30: $LP */
  115. *--pxTopOfStack = (rt_uint32_t)&_SDA_BASE_; /* R29: $GP */
  116. *--pxTopOfStack = (rt_uint32_t)0x2828282828; /* R28: $FP */
  117. #ifdef __NDS32_REDUCE_REGS__
  118. *--pxTopOfStack = (rt_uint32_t)0x1515151515; /* R15 */
  119. for (i = 10; i >= 6; i--) /* R10 ~ R6 */
  120. *--pxTopOfStack = (rt_uint32_t)0x01010101UL * i;
  121. #else
  122. for (i = 27; i >= 6; i--) /* R27 ~ R6 */
  123. *--pxTopOfStack = (rt_uint32_t)0x01010101UL * i;
  124. #endif
  125. /* IFC system register */
  126. #ifdef __TARGET_IFC_EXT
  127. *--pxTopOfStack = (rt_uint32_t)0x0; /* $IFC_LP */
  128. #endif
  129. /* ZOL system registers */
  130. #ifdef __TARGET_ZOL_EXT
  131. *--pxTopOfStack = (rt_uint32_t)0x0; /* $LC */
  132. *--pxTopOfStack = (rt_uint32_t)0x0; /* $LE */
  133. *--pxTopOfStack = (rt_uint32_t)0x0; /* $LB */
  134. #endif
  135. /* IPSW and IPC system registers */
  136. /* Default IPSW: enable GIE, set CPL to 7, clear IFCON */
  137. i = (__nds32__mfsr(NDS32_SR_PSW) | PSW_mskGIE | PSW_mskCPL) & ~PSW_mskIFCON;
  138. *--pxTopOfStack = (rt_uint32_t)i; /* $IPSW */
  139. *--pxTopOfStack = (rt_uint32_t)tentry; /* $IPC */
  140. /* Dummy word for 8-byte stack alignment */
  141. #if defined(__TARGET_IFC_EXT) && defined(__TARGET_ZOL_EXT)
  142. *--pxTopOfStack = (rt_uint32_t)0xFFFFFFFF; /* Dummy */
  143. #endif
  144. /* FPU registers */
  145. #ifdef __TARGET_FPU_EXT
  146. for (i = 0; i < FPU_REGS; i++)
  147. *--pxTopOfStack = (rt_uint32_t)0x0; /* FPU */
  148. #endif
  149. return (rt_uint8_t *)pxTopOfStack;
  150. }
  151. /**
  152. * This function set the hook, which is invoked on fault exception handling.
  153. *
  154. * @param exception_handle the exception handling hook function.
  155. */
  156. void rt_hw_exception_install(rt_err_t (*exception_handle)(void* context))
  157. {
  158. rt_exception_hook = exception_handle;
  159. }
  160. #ifdef RT_USING_CPU_FFS
  161. /**
  162. * This function finds the first bit set (beginning with the least significant bit)
  163. * in value and return the index of that bit.
  164. *
  165. * Bits are numbered starting at 1 (the least significant bit). A return value of
  166. * zero from any of these functions means that the argument was zero.
  167. *
  168. * @return return the index of the first bit set. If value is 0, then this function
  169. * shall return 0.
  170. */
  171. #if defined(__CC_ARM)
  172. __asm int __rt_ffs(int value)
  173. {
  174. CMP r0, #0x00
  175. BEQ exit
  176. RBIT r0, r0
  177. CLZ r0, r0
  178. ADDS r0, r0, #0x01
  179. exit
  180. BX lr
  181. }
  182. #elif defined(__IAR_SYSTEMS_ICC__)
  183. int __rt_ffs(int value)
  184. {
  185. if (value == 0) return value;
  186. __ASM("RBIT r0, r0");
  187. __ASM("CLZ r0, r0");
  188. __ASM("ADDS r0, r0, #0x01");
  189. }
  190. #elif defined(__GNUC__)
  191. int __rt_ffs(int value)
  192. {
  193. return __builtin_ffs(value);
  194. }
  195. #endif
  196. #endif