vfp.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. /*
  2. * File : vfp.c
  3. * This file is part of RT-Thread RTOS
  4. * COPYRIGHT (C) 2006, RT-Thread Develop Team
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License along
  17. * with this program; if not, write to the Free Software Foundation, Inc.,
  18. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  19. *
  20. * Change Logs:
  21. * Date Author Notes
  22. * 2014-11-07 weety first version
  23. */
  24. #include <rthw.h>
  25. #include <rtthread.h>
  26. #include "vfp.h"
  27. #ifdef RT_USING_VFP
  28. rt_uint32_t vfpregs_offset = offsetof(struct rt_thread, vfpregs);
  29. struct vfp_context *last_vfp_context = RT_NULL;
  30. int vfp_switch(rt_uint32_t cmd, struct rt_thread *thread)
  31. {
  32. rt_uint32_t fpexc;
  33. //rt_kprintf("%s:%d, %x\n", __func__, cmd, thread);
  34. switch (cmd) {
  35. case THREAD_INIT:
  36. {
  37. struct vfp_context *vfp = &thread->vfpregs;
  38. rt_memset(vfp, 0, sizeof(struct vfp_context));
  39. vfp->fpexc = FPEXC_EN;
  40. vfp->fpscr = FPSCR_RN;
  41. if (last_vfp_context == vfp)
  42. last_vfp_context = RT_NULL;
  43. vmsr(FPEXC, vmrs(FPEXC) & ~FPEXC_EN);
  44. break;
  45. }
  46. case THREAD_EXIT:
  47. {
  48. /* release case: Per-thread VFP cleanup. */
  49. struct vfp_context *vfp = &thread->vfpregs;
  50. if (last_vfp_context == vfp)
  51. last_vfp_context = RT_NULL;
  52. break;
  53. }
  54. default:
  55. break;
  56. }
  57. return 0;
  58. }
  59. int vfp_thread_init(struct rt_thread *thread)
  60. {
  61. return vfp_switch(THREAD_INIT, thread);
  62. }
  63. int vfp_thread_exit(struct rt_thread *thread)
  64. {
  65. return vfp_switch(THREAD_EXIT, thread);
  66. }
  67. rt_uint32_t read_vfp_regs(rt_uint32_t *buf)
  68. {
  69. rt_uint32_t value;
  70. rt_uint32_t length;
  71. asm volatile ("vldmia %0!, {d0-d15}"
  72. :
  73. :"r"(buf)
  74. :"cc");
  75. length = 32;
  76. #ifdef RT_USING_VFPv3
  77. asm volatile ("vmrs %0, mvfr0"
  78. :"=r"(value)
  79. :);
  80. if ((value & MVFR0_A_SIMD_MASK) == 2)
  81. {
  82. asm volatile ("vldmia %0!, {d16-d31}"
  83. :
  84. :"r"(buf)
  85. :"cc");
  86. length = 64;
  87. }
  88. else
  89. {
  90. length = 32;
  91. }
  92. #endif
  93. return length;
  94. }
  95. void vfp_exception(rt_uint32_t instruction, rt_uint32_t fpexc)
  96. {
  97. int i = 0;
  98. int length = 0;
  99. rt_uint32_t fpscr, fpsid;
  100. #ifdef RT_USING_VFPv3
  101. unsigned long long vfp_regs[32];
  102. #else
  103. unsigned long long vfp_regs[16];
  104. #endif
  105. rt_kprintf("VFP: exception: instruction %08x fpexc %08x\n", instruction, fpexc);
  106. fpsid = vmrs(FPSID);
  107. fpscr = vmrs(FPSCR);
  108. rt_kprintf("VFP: exception: fpsid %08x fpscr %08x\n", fpsid, fpscr);
  109. length = read_vfp_regs((rt_uint32_t *)vfp_regs);
  110. rt_kprintf("VFP: exception registers: {s0~s%d}\n", length - 1);
  111. for(i = 0; i < length; i++)
  112. {
  113. if (i && !(i & 0x3))
  114. rt_kprintf("\n");
  115. rt_kprintf("0x%08x ", ((rt_uint32_t *)vfp_regs)[i]);
  116. }
  117. rt_kprintf("\n");
  118. }
  119. void vfp_init(void)
  120. {
  121. int ret = 0;
  122. unsigned int value;
  123. asm volatile ("mrc p15, 0, %0, c1, c0, 2"
  124. :"=r"(value)
  125. :);
  126. value |= 0xf00000;/*enable CP10, CP11 user access*/
  127. asm volatile("mcr p15, 0, %0, c1, c0, 2"
  128. :
  129. :"r"(value));
  130. #if 0
  131. asm volatile("fmrx %0, fpexc"
  132. :"=r"(value));
  133. value |=(1<<30);
  134. asm volatile("fmxr fpexc, %0"
  135. :
  136. :"r"(value));
  137. #endif
  138. }
  139. #endif