ARM MMU

好记性不如烂笔头,为方便以后查看代码及代码重复利用,这里贴出自己写的S3C2440 MMU代码库。使用友善MINI2440开发板,开发环境为RealView MDK 4.22。

 

Register 0, ID code register:

  1. unsigned int MMU_ReadID(void)
  2. {
  3. unsigned int id;
  4. __asm("mrc p15, 0, id, c0, c0, 0");
  5. return id;
  6. }


Register 0, cache type register:

  1. unsigned int MMU_ReadCacheType(void)
  2. {
  3. unsigned int type;
  4. __asm("mrc p15, 0, type, c0, c0, 1");
  5. return type;
  6. }


Register 1, control register:

  1. void MMU_EnterFastBusMode(void)
  2. {
  3. unsigned int r0;
  4. __asm{
  5. mrc p15, 0, r0, c1, c0, 0
  6. bic r0, r0, #(3<<30)
  7. mcr p15, 0, r0, c1, c0, 0
  8. }
  9. }
  10.  
  11. void MMU_EnterSyncMode(void)
  12. {
  13. unsigned int r0;
  14. __asm{
  15. mrc p15, 0, r0, c1, c0, 0
  16. bic r0, r0, #(1<<31)
  17. orr r0, r0, #(1<<30)
  18. mcr p15, 0, r0, c1, c0, 0
  19. }
  20. }
  21.  
  22. void MMU_EnterAsyncMode(void)
  23. {
  24. unsigned int r0;
  25. __asm{
  26. mrc p15, 0, r0, c1, c0, 0
  27. orr r0, r0, #(11<<30)
  28. mcr p15, 0, r0, c1, c0, 0
  29. }
  30. }
  31.  
  32.  
  33. void MMU_EnableICache(void)
  34. {
  35. unsigned int r0;
  36. __asm{
  37. mrc p15, 0, r0, c1, c0, 0
  38. orr r0, r0, #(1<<12)
  39. mcr p15, 0, r0, c1, c0, 0
  40. }
  41. }
  42.  
  43.  
  44. void MMU_DisableICache(void)
  45. {
  46. unsigned int r0;
  47. __asm{
  48. mrc p15, 0, r0, c1, c0, 0
  49. bic r0, r0, #(1<<12)
  50. mcr p15, 0, r0, c1, c0, 0
  51. }
  52. }
  53.  
  54.  
  55. void MMU_EnableDCache(void)
  56. {
  57. unsigned int r0;
  58. __asm{
  59. mrc p15, 0, r0, c1, c0, 0
  60. orr r0, r0, #(1<<2)
  61. mcr p15, 0, r0, c1, c0, 0
  62. }
  63. }
  64.  
  65.  
  66. void MMU_DisableDCache(void)
  67. {
  68. unsigned int r0;
  69. __asm{
  70. mrc p15, 0, r0, c1, c0, 0
  71. bic r0, r0, #(1<<2)
  72. mcr p15, 0, r0, c1, c0, 0
  73. }
  74. }
  75.  
  76. void MMU_EnableAlignFault(void)
  77. {
  78. unsigned int r0;
  79. __asm{
  80. mrc p15, 0, r0, c1, c0, 0
  81. orr r0, r0, #(1<<1)
  82. mcr p15, 0, r0, c1, c0, 0
  83. }
  84. }
  85.  
  86.  
  87. void MMU_DisableAlignFault(void)
  88. {
  89. unsigned int r0;
  90. __asm{
  91. mrc p15, 0, r0, c1, c0, 0
  92. bic r0, r0, #(1<<1)
  93. mcr p15, 0, r0, c1, c0, 0
  94. }
  95. }
  96.  
  97. void MMU_Enable(void)
  98. {
  99. unsigned int r0;
  100. __asm{
  101. mrc p15, 0, r0, c1, c0, 0
  102. orr r0, r0, #1
  103. mcr p15, 0, r0, c1, c0, 0
  104. }
  105. }
  106.  
  107.  
  108. void MMU_Disable(void)
  109. {
  110. unsigned int r0;
  111. __asm{
  112. mrc p15, 0, r0, c1, c0, 0
  113. bic r0, r0, #1
  114. mcr p15, 0, r0, c1, c0, 0
  115. }
  116. }


Register 2, translation table base (TTB) register:

  1. void MMU_SetTTB(void)
  2. {
  3. unsigned int r0 = (unsigned int)TTB;
  4. __asm("mcr p15, 0, r0, c2, c0, 0");
  5. }


Register 3, domain access control register:

  1. void MMU_SetDomain(unsigned int domain)
  2. {
  3. __asm("mcr p15, 0, domain, c3, c0, 0");
  4. }


Register 7, cache operations register:

  1. void MMU_InvalidICacheDCache(void)
  2. {
  3. unsigned int r0 = 0;
  4.  
  5. __asm("mcr p15, 0, r0, c7, c7, 0");
  6. }
  7.  
  8. void MMU_InvalidICache(void)
  9. {
  10. unsigned int r0 = 0;
  11.  
  12. __asm("mcr p15, 0, r0, c7, c5, 0");
  13. }
  14.  
  15. void MMU_InvalidICacheSingleEntry(unsigned int MVA)
  16. {
  17. __asm("mcr p15, 0, MVA, c7, c5, 1");
  18. }
  19.  
  20. void MMU_PrefechICacheLine(unsigned int MVA)
  21. {
  22. __asm("mcr p15, 0, MVA, c7, c13, 1");
  23. }
  24.  
  25. void MMU_InvalidDCache(void)
  26. {
  27. unsigned int r0 = 0;
  28.  
  29. __asm("mcr p15, 0, r0, c7, c6, 0");
  30. }
  31.  
  32. void MMU_InvalidDCacheSingleEntry(unsigned int MVA)
  33. {
  34. __asm("mcr p15, 0, MVA, c7, c6, 1");
  35. }
  36.  
  37. void MMU_CleanDCacheSingleEntry(unsigned int MVA)
  38. {
  39. __asm("mcr p15, 0, MVA, c7, c10, 1");
  40. }
  41.  
  42. void MMU_CleanInvalidDCacheEntry(unsigned int MVA)
  43. {
  44. __asm("mcr p15, 0, MVA, c7, c14, 1");
  45. }
  46.  
  47. void MMU_CleanDCacheSingleEntry2(unsigned int index)
  48. {
  49. __asm("mcr p15, 0, index, c7, c10, 2");
  50. }
  51.  
  52. void MMU_CleanInvalidDCacheEntry2(unsigned int index)
  53. {
  54. __asm("mcr p15, 0, index, c7, c14, 2");
  55. }
  56.  
  57. void MMU_DrainWriteBuffer(void)
  58. {
  59. unsigned int r0 = 0;
  60.  
  61. __asm("mcr p15, 0, r0, c7, c10, 4");
  62. }
  63.  
  64. void MMU_WaitForInterrupt(void)
  65. {
  66. unsigned int r0 = 0;
  67.  
  68. __asm("mcr p15, 0, r0, c7, c0, 4");
  69. }

 

Register 8, TLB operations register:

  1. void MMU_InvalidAllTLB(void)
  2. {
  3. unsigned int r0 = 0;
  4.  
  5. __asm("mcr p15, 0, r0, c8, c7, 0");
  6. }
  7.  
  8. void MMU_InvalidITLB(void)
  9. {
  10. unsigned int r0 = 0;
  11.  
  12. __asm("mcr p15, 0, r0, c8, c5, 0");
  13. }
  14.  
  15. void MMU_InvalidITLBSingleEntry(unsigned int MVA)
  16. {
  17. __asm("mcr p15, 0, MVA, c8, c5, 1");
  18. }
  19.  
  20. void MMU_InvalidDTLB(void)
  21. {
  22. unsigned int r0 = 0;
  23.  
  24. __asm("mcr p15, 0, r0, c8, c6, 0");
  25. }
  26.  
  27. void MMU_InvalidDTLBSingleEntry(unsigned int MVA)
  28. {
  29. __asm("mcr p15, 0, MVA, c8, c6, 1");
  30. }


Register 9, cache lockdown register:

  1. unsigned int MMU_ReadDCacheLockdownBase(void)
  2. {
  3. unsigned int r0;
  4.  
  5. __asm("mrc p15, 0, r0, c9, c0, 0");
  6. r0 >>= 26;
  7.  
  8. return r0;
  9. }
  10.  
  11. void MMU_WriteDCacheLockdownBase(unsigned int index)
  12. {
  13. index <<= 26;
  14. __asm("mcr p15, 0, index, c9, c0, 0");
  15. }
  16.  
  17.  
  18. unsigned int MMU_ReadICacheLockdownBase(void)
  19. {
  20. unsigned int r0;
  21.  
  22. __asm("mrc p15, 0, r0, c9, c0, 1");
  23. r0 >>= 26;
  24.  
  25. return r0;
  26. }
  27.  
  28. void MMU_WriteICacheLockdownBase(unsigned int index)
  29. {
  30. index <<= 26;
  31. __asm("mcr p15, 0, index, c9, c0, 1");
  32. }


Register 13, FCSE PID register:

  1. unsigned int MMU_ReadPID(void)
  2. {
  3. unsigned int pid;
  4.  
  5. __asm("mrc p15, 0, pid, c13, c0, 0");
  6.  
  7. return (pid >> 25);
  8. }
  9.  
  10. void MMU_WritePID(unsigned int pid)
  11. {
  12. pid <<= 25;
  13. __asm("mcr p15, 0, pid, c13, c0, 0");
  14. }


设置Memory Translation Table:

  1. void MMU_SetMTT(unsigned int vStart, unsigned int vEnd, unsigned int pStart, unsigned int attr)
  2. {
  3. unsigned int vaddr, paddr;
  4.  
  5. vaddr = vStart;
  6. paddr = pStart;
  7. while(vaddr != (vEnd + 1))
  8. {
  9. TTB[vaddr >> 20] = (paddr & 0xFFF00000) | attr;
  10. vaddr += 0x100000;
  11. paddr += 0x100000;
  12. }
  13. }


MMU初始化:

  1. void MMU_Init(void)
  2. {
  3. MMU_DisableICache();
  4. MMU_DisableDCache();
  5.  
  6. MMU_SetTTB();
  7. MMU_SetDomain(0xFFFFFFFF);
  8. MMU_InvalidAllTLB();
  9. MMU_EnableAlignFault();
  10.  
  11. MMU_SetMTT(0x00000000, 0x001FFFFF, 0x00000000, RW_CB);
  12. MMU_SetMTT(0x30000000, 0x33FFFFFF, 0x30000000, RW_CB);
  13. MMU_SetMTT(0x40000000, 0x4FFFFFFF, 0x40000000, RW_NCNB);
  14. MMU_SetMTT(0x50000000, 0x5FFFFFFF, 0x50000000, RW_NCNB);
  15.  
  16. MMU_EnableICache();
  17. MMU_EnableDCache();
  18. MMU_Enable();
  19. }

 

在本代码中需要注意的是,如果直接使用S3C2440.s的话,在C代码中调用上述代码会导致Undefine异常。因为进入main()之前,启动代码已经将处理器模式设置为USER模式了,而在USER模式下是无法操作CP15处理器的,所以产生异常。如果要在C中正常调用上述嵌入汇编,则需要将启动代码S3C2440.s中处理器模式设置为USER模式的那段代码注释掉,直接以SVC模式运行,就能正常执行,如下:

 

  1. ; Enter Supervisor Mode and set its Stack Pointer
  2. MSR CPSR_c, #Mode_SVC:OR:I_Bit:OR:F_Bit
  3. MOV SP, R0
  4. SUB R0, R0, #SVC_Stack_Size
  5.  
  6. ; Enter User Mode and set its Stack Pointer
  7. ; MSR CPSR_c, #Mode_USR
  8. ; MOV SP, R0
  9. ; SUB SL, SP, #USR_Stack_Size
  10.  
  11. ; Enter User Mode and set its Stack Pointer
  12. ; MSR CPSR_c, #Mode_USR
  13. ; IF :DEF:__MICROLIB
  14.  
  15. ; EXPORT __initial_sp
  16.  
  17. ; ELSE
  18.  
  19. ; MOV SP, R0
  20. ; SUB SL, SP, #USR_Stack_Size
  21.  
  22. ; ENDIF

 

或者不修改处理器模式,而直接将以下汇编插入到S3C2440.s中Clock设置代码的后面,一样能运行:

 

  1. mrc p15, 0, r0, c1, c0, 0
  2. orr r0, r0, #0xc0000000
  3. mcr p15, 0, r0, c1, c0, 0



posted on 2022-07-19 16:50  sudochen  阅读(59)  评论(0编辑  收藏  举报

导航