The official µGFX library repository.

gos_x_threads_cortexm01.h 4.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  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. #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"
  15. #endif
  16. #if GFX_COMPILER == GFX_COMPILER_GCC || GFX_COMPILER == GFX_COMPILER_CYGWIN || GFX_COMPILER == GFX_COMPILER_MINGW32 || GFX_COMPILER == GFX_COMPILER_MINGW64
  17. #define GFX_THREADS_DONE
  18. #define _gfxThreadsInit()
  19. static __attribute__((pcs("aapcs"),naked)) void _gfxTaskSwitch(thread *oldt, thread *newt) {
  20. __asm__ volatile ( "push {r4, r5, r6, r7, lr} \n\t"
  21. "mov r4, r8 \n\t"
  22. "mov r5, r9 \n\t"
  23. "mov r6, r10 \n\t"
  24. "mov r7, r11 \n\t"
  25. "push {r4, r5, r6, r7} \n\t"
  26. "mov r4, sp \n\t"
  27. "str r4, %[oldtcxt] \n\t"
  28. "ldr r4, %[newtcxt] \n\t"
  29. "mov sp, r4 \n\t"
  30. "pop {r4, r5, r6, r7} \n\t"
  31. "mov r8, r4 \n\t"
  32. "mov r9, r5 \n\t"
  33. "mov r10, r6 \n\t"
  34. "mov r11, r7 \n\t"
  35. "pop {r4, r5, r6, r7, pc} \n\t"
  36. : [newtcxt] "=m" (newt->cxt)
  37. : [oldtcxt] "m" (oldt->cxt)
  38. : "memory");
  39. }
  40. static __attribute__((pcs("aapcs"),naked)) void _gfxStartThread(thread *oldt, thread *newt) {
  41. newt->cxt = (void *)(((unsigned)newt + newt->size) & ~7);
  42. __asm__ volatile ( "push {r4, r5, r6, r7, lr} \n\t"
  43. "mov r4, r8 \n\t"
  44. "mov r5, r9 \n\t"
  45. "mov r6, r10 \n\t"
  46. "mov r7, r11 \n\t"
  47. "push {r4, r5, r6, r7} \n\t"
  48. "mov r4, sp \n\t"
  49. "str r4, %[oldtcxt] \n\t"
  50. "ldr r4, %[newtcxt] \n\t"
  51. "mov sp, r4 \n\t"
  52. : [newtcxt] "=m" (newt->cxt)
  53. : [oldtcxt] "m" (oldt->cxt)
  54. : "memory");
  55. // Run the users function
  56. gfxThreadExit(_gfxCurrentThread->fn(_gfxCurrentThread->param));
  57. }
  58. #elif GFX_COMPILER == GFX_COMPILER_KEIL || GFX_COMPILER == GFX_COMPILER_ARMCC
  59. #define GFX_THREADS_DONE
  60. #define _gfxThreadsInit()
  61. static __asm void _gfxTaskSwitch(thread *oldt, thread *newt) {
  62. PRESERVE8
  63. // Save the old context
  64. push {r4, r5, r6, r7, lr}
  65. mov r4, r8
  66. mov r5, r9
  67. mov r6, r10
  68. mov r7, r11
  69. push {r4, r5, r6, r7}
  70. mov r4, sp
  71. str r4, [r0,#__cpp(offsetof(thread,cxt))] // oldt->cxt
  72. // Load the new context
  73. ldr r4, [r1,#__cpp(offsetof(thread,cxt))] // newt->cxt
  74. mov sp, r4
  75. pop {r4, r5, r6, r7}
  76. mov r8, r4
  77. mov r9, r5
  78. mov r10, r6
  79. mov r11, r7
  80. pop {r4, r5, r6, r7, pc}
  81. }
  82. static __asm void _gfxStartThread(thread *oldt, thread *newt) {
  83. PRESERVE8
  84. // Calculate where to generate the new context
  85. // newt->cxt = (void *)(((unsigned)newt + newt->size) & ~7);
  86. ldr r2,[r1,#__cpp(offsetof(thread,size))]
  87. add r2,r2,r1
  88. and r2, r2, #0xFFFFFFF8
  89. str r2,[r1,#__cpp(offsetof(thread,cxt))]
  90. // Save the old context
  91. push {r4, r5, r6, r7, lr}
  92. mov r4, r8
  93. mov r5, r9
  94. mov r6, r10
  95. mov r7, r11
  96. push {r4, r5, r6, r7}
  97. mov r4, sp
  98. str r4, [r0,#__cpp(offsetof(thread,cxt))] // oldt->cxt
  99. // Load the new (imcomplete) context
  100. ldr r4, [r1,#__cpp(offsetof(thread,cxt))] // newt->cxt
  101. mov sp, r4
  102. // Run the users function - we save some code because gfxThreadExit() never returns
  103. // gfxThreadExit(_gfxCurrentThread->fn(_gfxCurrentThread->param));
  104. ldr r2,=__cpp(&_gfxCurrentThread)
  105. ldr r2,[r2,#0]
  106. ldr r0,[r2,#__cpp(offsetof(thread,param))]
  107. ldr r1,[r2,#__cpp(offsetof(thread,fn))]
  108. blx r1
  109. mov r4,r0
  110. bl __cpp(gfxThreadExit)
  111. ALIGN
  112. }
  113. #else
  114. #warning "GOS: Threads: You have specified a specific CPU but your compiler is not supported. Defaulting to CLIB switching"
  115. #endif