µGFX library fork

gos_x_threads_cortexm47fp.h 3.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  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 M4 & M7 with hardware floating point
  9. *
  10. * Use the EABI calling standard (ARM's AAPCS) - Save r4 - r11 and floating point
  11. * The context is saved at the current stack location and a pointer is maintained in the thread structure.
  12. */
  13. #if GFX_COMPILER == GFX_COMPILER_GCC || GFX_COMPILER == GFX_COMPILER_CYGWIN || GFX_COMPILER == GFX_COMPILER_MINGW32 || GFX_COMPILER == GFX_COMPILER_MINGW64
  14. #define GFX_THREADS_DONE
  15. #define _gfxThreadsInit()
  16. static __attribute__((pcs("aapcs-vfp"),naked)) void _gfxTaskSwitch(thread *oldt, thread *newt) {
  17. __asm__ volatile ( "push {r4, r5, r6, r7, r8, r9, r10, r11, lr} \n\t"
  18. "vpush {s16-s31} \n\t"
  19. "str sp, %[oldtcxt] \n\t"
  20. "ldr sp, %[newtcxt] \n\t"
  21. "vpop {s16-s31} \n\t"
  22. "pop {r4, r5, r6, r7, r8, r9, r10, r11, pc} \n\t"
  23. : [newtcxt] "=m" (newt->cxt)
  24. : [oldtcxt] "m" (oldt->cxt)
  25. : "memory");
  26. }
  27. static __attribute__((pcs("aapcs-vfp"),naked)) void _gfxStartThread(thread *oldt, thread *newt) {
  28. newt->cxt = (void *)(((unsigned)newt + newt->size) & ~7);
  29. __asm__ volatile ( "push {r4, r5, r6, r7, r8, r9, r10, r11, lr} \n\t"
  30. "vpush {s16-s31} \n\t"
  31. "str sp, %[oldtcxt] \n\t"
  32. "ldr sp, %[newtcxt] \n\t"
  33. : [newtcxt] "=m" (newt->cxt)
  34. : [oldtcxt] "m" (oldt->cxt)
  35. : "memory");
  36. // Run the users function
  37. gfxThreadExit(_gfxCurrentThread->fn(_gfxCurrentThread->param));
  38. }
  39. #elif GFX_COMPILER == GFX_COMPILER_KEIL || GFX_COMPILER == GFX_COMPILER_ARMCC
  40. #define GFX_THREADS_DONE
  41. #define _gfxThreadsInit()
  42. static __asm void _gfxTaskSwitch(thread *oldt, thread *newt) {
  43. PRESERVE8
  44. // Save the old context
  45. push {r4, r5, r6, r7, r8, r9, r10, r11, lr}
  46. vpush {s16-s31}
  47. str sp, [r0,#__cpp(offsetof(thread,cxt))] // oldt->cxt
  48. // Load the new context
  49. ldr sp, [r1,#__cpp(offsetof(thread,cxt))] // newt->cxt
  50. vpop {s16-s31}
  51. pop {r4, r5, r6, r7, r8, r9, r10, r11, pc}
  52. }
  53. static __asm void _gfxStartThread(thread *oldt, thread *newt) {
  54. PRESERVE8
  55. // Calculate where to generate the new context
  56. // newt->cxt = (void *)(((unsigned)newt + newt->size) & ~7);
  57. ldr r2,[r1,#__cpp(offsetof(thread,size))]
  58. add r2,r2,r1
  59. and r2, r2, #0xFFFFFFF8
  60. str r2,[r1,#__cpp(offsetof(thread,cxt))]
  61. // Save the old context
  62. push {r4, r5, r6, r7, r8, r9, r10, r11, lr}
  63. vpush {s16-s31}
  64. str sp, [r0,#__cpp(offsetof(thread,cxt))] // oldt->cxt
  65. // Load the new (imcomplete) context
  66. ldr sp, [r1,#__cpp(offsetof(thread,cxt))] // newt->cxt
  67. // Run the users function - we save some code because gfxThreadExit() never returns
  68. // gfxThreadExit(_gfxCurrentThread->fn(_gfxCurrentThread->param));
  69. ldr r2,=__cpp(&_gfxCurrentThread)
  70. ldr r2,[r2,#0]
  71. ldr r0,[r2,#__cpp(offsetof(thread,param))]
  72. ldr r1,[r2,#__cpp(offsetof(thread,fn))]
  73. blx r1
  74. mov r4,r0
  75. bl __cpp(gfxThreadExit)
  76. ALIGN
  77. }
  78. #else
  79. #if GFX_COMPILER_WARNING_TYPE == GFX_COMPILER_WARNING_DIRECT
  80. #warning "GOS Threads: You have specified a specific CPU but your compiler is not supported. Defaulting to CLIB switching"
  81. #elif GFX_COMPILER_WARNING_TYPE == GFX_COMPILER_WARNING_MACRO
  82. COMPILER_WARNING("GOS Threads: You have specified a specific CPU but your compiler is not supported. Defaulting to CLIB switching")
  83. #endif
  84. #endif