µGFX library fork

gos_x_threads_cortexm01.h 5.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. /*
  2. * This file is subject to the terms of the GFX License. If a copy of
  3. * the license was not distributed with this file, you can obtain one at:
  4. *
  5. * http://ugfx.org/license.html
  6. */
  7. /**
  8. * Thread Switching Functions for the Cortex M0 & M1
  9. *
  10. * Use the EABI calling standard (ARM's AAPCS) - Save r4 - r11
  11. * The context is saved at the current stack location and a pointer is maintained in the thread structure.
  12. */
  13. #if CORTEX_USE_FPU
  14. #if GFX_COMPILER_WARNING_TYPE == GFX_COMPILER_WARNING_DIRECT
  15. #warning "GOS Threads: You have specified GFX_CPU=GFX_CPU_CORTX_M? with no hardware floating point support but CORTEX_USE_FPU is TRUE. Try using GFX_CPU_GFX_CPU_CORTEX_M?_FP instead"
  16. #elif GFX_COMPILER_WARNING_TYPE == GFX_COMPILER_WARNING_MACRO
  17. COMPILER_WARNING("GOS Threads: You have specified GFX_CPU=GFX_CPU_CORTX_M? with no hardware floating point support but CORTEX_USE_FPU is TRUE. Try using GFX_CPU_GFX_CPU_CORTEX_M?_FP instead")
  18. #endif
  19. #endif
  20. #if GFX_COMPILER == GFX_COMPILER_GCC || GFX_COMPILER == GFX_COMPILER_CYGWIN || GFX_COMPILER == GFX_COMPILER_MINGW32 || GFX_COMPILER == GFX_COMPILER_MINGW64
  21. #define GFX_THREADS_DONE
  22. #define _gfxThreadsInit()
  23. static __attribute__((pcs("aapcs"),naked)) void _gfxTaskSwitch(thread *oldt, thread *newt) {
  24. __asm__ volatile ( "push {r4, r5, r6, r7, lr} \n\t"
  25. "mov r4, r8 \n\t"
  26. "mov r5, r9 \n\t"
  27. "mov r6, r10 \n\t"
  28. "mov r7, r11 \n\t"
  29. "push {r4, r5, r6, r7} \n\t"
  30. "mov r4, sp \n\t"
  31. "str r4, %[oldtcxt] \n\t"
  32. "ldr r4, %[newtcxt] \n\t"
  33. "mov sp, r4 \n\t"
  34. "pop {r4, r5, r6, r7} \n\t"
  35. "mov r8, r4 \n\t"
  36. "mov r9, r5 \n\t"
  37. "mov r10, r6 \n\t"
  38. "mov r11, r7 \n\t"
  39. "pop {r4, r5, r6, r7, pc} \n\t"
  40. : [newtcxt] "=m" (newt->cxt)
  41. : [oldtcxt] "m" (oldt->cxt)
  42. : "memory");
  43. }
  44. static __attribute__((pcs("aapcs"),naked)) void _gfxStartThread(thread *oldt, thread *newt) {
  45. newt->cxt = (void *)(((unsigned)newt + newt->size) & ~7);
  46. __asm__ volatile ( "push {r4, r5, r6, r7, lr} \n\t"
  47. "mov r4, r8 \n\t"
  48. "mov r5, r9 \n\t"
  49. "mov r6, r10 \n\t"
  50. "mov r7, r11 \n\t"
  51. "push {r4, r5, r6, r7} \n\t"
  52. "mov r4, sp \n\t"
  53. "str r4, %[oldtcxt] \n\t"
  54. "ldr r4, %[newtcxt] \n\t"
  55. "mov sp, r4 \n\t"
  56. : [newtcxt] "=m" (newt->cxt)
  57. : [oldtcxt] "m" (oldt->cxt)
  58. : "memory");
  59. // Run the users function
  60. gfxThreadExit(_gfxCurrentThread->fn(_gfxCurrentThread->param));
  61. }
  62. #elif GFX_COMPILER == GFX_COMPILER_KEIL || GFX_COMPILER == GFX_COMPILER_ARMCC
  63. #define GFX_THREADS_DONE
  64. #define _gfxThreadsInit()
  65. static __asm void _gfxTaskSwitch(thread *oldt, thread *newt) {
  66. PRESERVE8
  67. // Save the old context
  68. push {r4, r5, r6, r7, lr}
  69. mov r4, r8
  70. mov r5, r9
  71. mov r6, r10
  72. mov r7, r11
  73. push {r4, r5, r6, r7}
  74. mov r4, sp
  75. str r4, [r0,#__cpp(offsetof(thread,cxt))] // oldt->cxt
  76. // Load the new context
  77. ldr r4, [r1,#__cpp(offsetof(thread,cxt))] // newt->cxt
  78. mov sp, r4
  79. pop {r4, r5, r6, r7}
  80. mov r8, r4
  81. mov r9, r5
  82. mov r10, r6
  83. mov r11, r7
  84. pop {r4, r5, r6, r7, pc}
  85. }
  86. static __asm void _gfxStartThread(thread *oldt, thread *newt) {
  87. PRESERVE8
  88. // Calculate where to generate the new context
  89. // newt->cxt = (void *)(((unsigned)newt + newt->size) & ~7);
  90. ldr r2,[r1,#__cpp(offsetof(thread,size))]
  91. add r2,r2,r1
  92. and r2, r2, #0xFFFFFFF8
  93. str r2,[r1,#__cpp(offsetof(thread,cxt))]
  94. // Save the old context
  95. push {r4, r5, r6, r7, lr}
  96. mov r4, r8
  97. mov r5, r9
  98. mov r6, r10
  99. mov r7, r11
  100. push {r4, r5, r6, r7}
  101. mov r4, sp
  102. str r4, [r0,#__cpp(offsetof(thread,cxt))] // oldt->cxt
  103. // Load the new (imcomplete) context
  104. ldr r4, [r1,#__cpp(offsetof(thread,cxt))] // newt->cxt
  105. mov sp, r4
  106. // Run the users function - we save some code because gfxThreadExit() never returns
  107. // gfxThreadExit(_gfxCurrentThread->fn(_gfxCurrentThread->param));
  108. ldr r2,=__cpp(&_gfxCurrentThread)
  109. ldr r2,[r2,#0]
  110. ldr r0,[r2,#__cpp(offsetof(thread,param))]
  111. ldr r1,[r2,#__cpp(offsetof(thread,fn))]
  112. blx r1
  113. mov r4,r0
  114. bl __cpp(gfxThreadExit)
  115. ALIGN
  116. }
  117. #else
  118. #if GFX_COMPILER_WARNING_TYPE == GFX_COMPILER_WARNING_DIRECT
  119. #warning "GOS Threads: You have specified a specific CPU but your compiler is not supported. Defaulting to CLIB switching"
  120. #elif GFX_COMPILER_WARNING_TYPE == GFX_COMPILER_WARNING_MACRO
  121. COMPILER_WARNING("GOS Threads: You have specified a specific CPU but your compiler is not supported. Defaulting to CLIB switching")
  122. #endif
  123. #endif