mmu.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457
  1. /*
  2. * File : mmu.c
  3. * This file is part of RT-Thread RTOS
  4. * COPYRIGHT (C) 2017, RT-Thread Development 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. * 2018-02-08 RT-Thread the first version
  23. */
  24. #include "mmu.h"
  25. /*----- Keil -----------------------------------------------------------------*/
  26. #ifdef __CC_ARM
  27. void mmu_setttbase(rt_uint32_t i)
  28. {
  29. register rt_uint32_t value;
  30. /* Invalidates all TLBs.Domain access is selected as
  31. * client by configuring domain access register,
  32. * in that case access controlled by permission value
  33. * set by page table entry
  34. */
  35. value = 0;
  36. __asm volatile{ mcr p15, 0, value, c8, c7, 0 }
  37. value = 0x55555555;
  38. __asm volatile { mcr p15, 0, value, c3, c0, 0 }
  39. __asm volatile { mcr p15, 0, i, c2, c0, 0 }
  40. }
  41. void mmu_set_domain(rt_uint32_t i)
  42. {
  43. __asm volatile { mcr p15, 0, i, c3, c0, 0 }
  44. }
  45. void mmu_enable()
  46. {
  47. register rt_uint32_t value;
  48. __asm volatile
  49. {
  50. mrc p15, 0, value, c1, c0, 0
  51. orr value, value, #0x01
  52. mcr p15, 0, value, c1, c0, 0
  53. }
  54. }
  55. void mmu_disable()
  56. {
  57. register rt_uint32_t value;
  58. __asm volatile
  59. {
  60. mrc p15, 0, value, c1, c0, 0
  61. bic value, value, #0x01
  62. mcr p15, 0, value, c1, c0, 0
  63. }
  64. }
  65. void mmu_enable_icache()
  66. {
  67. register rt_uint32_t value;
  68. __asm volatile
  69. {
  70. mrc p15, 0, value, c1, c0, 0
  71. orr value, value, #0x1000
  72. mcr p15, 0, value, c1, c0, 0
  73. }
  74. }
  75. void mmu_enable_dcache()
  76. {
  77. register rt_uint32_t value;
  78. __asm volatile
  79. {
  80. mrc p15, 0, value, c1, c0, 0
  81. orr value, value, #0x04
  82. mcr p15, 0, value, c1, c0, 0
  83. }
  84. }
  85. void mmu_disable_icache()
  86. {
  87. register rt_uint32_t value;
  88. __asm volatile
  89. {
  90. mrc p15, 0, value, c1, c0, 0
  91. bic value, value, #0x1000
  92. mcr p15, 0, value, c1, c0, 0
  93. }
  94. }
  95. void mmu_disable_dcache()
  96. {
  97. register rt_uint32_t value;
  98. __asm volatile
  99. {
  100. mrc p15, 0, value, c1, c0, 0
  101. bic value, value, #0x04
  102. mcr p15, 0, value, c1, c0, 0
  103. }
  104. }
  105. void mmu_enable_alignfault()
  106. {
  107. register rt_uint32_t value;
  108. __asm volatile
  109. {
  110. mrc p15, 0, value, c1, c0, 0
  111. orr value, value, #0x02
  112. mcr p15, 0, value, c1, c0, 0
  113. }
  114. }
  115. void mmu_disable_alignfault()
  116. {
  117. register rt_uint32_t value;
  118. __asm volatile
  119. {
  120. mrc p15, 0, value, c1, c0, 0
  121. bic value, value, #0x02
  122. mcr p15, 0, value, c1, c0, 0
  123. }
  124. }
  125. void mmu_clean_invalidated_cache_index(int index)
  126. {
  127. __asm volatile { mcr p15, 0, index, c7, c14, 2 }
  128. }
  129. void mmu_clean_invalidated_dcache(rt_uint32_t buffer, rt_uint32_t size)
  130. {
  131. unsigned int ptr;
  132. ptr = buffer & ~(CACHE_LINE_SIZE - 1);
  133. while (ptr < buffer + size)
  134. {
  135. __asm volatile { MCR p15, 0, ptr, c7, c14, 1 }
  136. ptr += CACHE_LINE_SIZE;
  137. }
  138. }
  139. void mmu_clean_dcache(rt_uint32_t buffer, rt_uint32_t size)
  140. {
  141. unsigned int ptr;
  142. ptr = buffer & ~(CACHE_LINE_SIZE - 1);
  143. while (ptr < buffer + size)
  144. {
  145. __asm volatile { MCR p15, 0, ptr, c7, c10, 1 }
  146. ptr += CACHE_LINE_SIZE;
  147. }
  148. }
  149. void mmu_invalidate_dcache(rt_uint32_t buffer, rt_uint32_t size)
  150. {
  151. unsigned int ptr;
  152. ptr = buffer & ~(CACHE_LINE_SIZE - 1);
  153. while (ptr < buffer + size)
  154. {
  155. __asm volatile { MCR p15, 0, ptr, c7, c6, 1 }
  156. ptr += CACHE_LINE_SIZE;
  157. }
  158. }
  159. void mmu_invalidate_tlb()
  160. {
  161. register rt_uint32_t value;
  162. value = 0;
  163. __asm volatile { mcr p15, 0, value, c8, c7, 0 }
  164. }
  165. void mmu_invalidate_icache()
  166. {
  167. register rt_uint32_t value;
  168. value = 0;
  169. __asm volatile { mcr p15, 0, value, c7, c5, 0 }
  170. }
  171. void mmu_invalidate_dcache_all()
  172. {
  173. register rt_uint32_t value;
  174. value = 0;
  175. __asm volatile { mcr p15, 0, value, c7, c6, 0 }
  176. }
  177. /*----- GNU ------------------------------------------------------------------*/
  178. #elif defined(__GNUC__) || defined(__ICCARM__)
  179. void mmu_setttbase(register rt_uint32_t i)
  180. {
  181. register rt_uint32_t value;
  182. /* Invalidates all TLBs.Domain access is selected as
  183. * client by configuring domain access register,
  184. * in that case access controlled by permission value
  185. * set by page table entry
  186. */
  187. value = 0;
  188. asm volatile("mcr p15, 0, %0, c8, c7, 0"::"r"(value));
  189. value = 0x55555555;
  190. asm volatile("mcr p15, 0, %0, c3, c0, 0"::"r"(value));
  191. asm volatile("mcr p15, 0, %0, c2, c0, 0"::"r"(i));
  192. }
  193. void mmu_set_domain(register rt_uint32_t i)
  194. {
  195. asm volatile("mcr p15,0, %0, c3, c0, 0": :"r"(i));
  196. }
  197. void mmu_enable()
  198. {
  199. asm volatile
  200. (
  201. "mrc p15, 0, r0, c1, c0, 0 \n"
  202. "orr r0, r0, #0x1 \n"
  203. "mcr p15, 0, r0, c1, c0, 0 \n"
  204. :::"r0"
  205. );
  206. }
  207. void mmu_disable()
  208. {
  209. asm volatile
  210. (
  211. "mrc p15, 0, r0, c1, c0, 0 \n"
  212. "bic r0, r0, #0x1 \n"
  213. "mcr p15, 0, r0, c1, c0, 0 \n"
  214. :::"r0"
  215. );
  216. }
  217. void mmu_enable_icache()
  218. {
  219. asm volatile
  220. (
  221. "mrc p15, 0, r0, c1, c0, 0 \n"
  222. "orr r0, r0, #(1<<12) \n"
  223. "mcr p15, 0, r0, c1, c0, 0 \n"
  224. :::"r0"
  225. );
  226. }
  227. void mmu_enable_dcache()
  228. {
  229. asm volatile
  230. (
  231. "mrc p15, 0, r0, c1, c0, 0 \n"
  232. "orr r0, r0, #(1<<2) \n"
  233. "mcr p15, 0, r0, c1, c0, 0 \n"
  234. :::"r0"
  235. );
  236. }
  237. void mmu_disable_icache()
  238. {
  239. asm volatile
  240. (
  241. "mrc p15, 0, r0, c1, c0, 0 \n"
  242. "bic r0, r0, #(1<<12) \n"
  243. "mcr p15, 0, r0, c1, c0, 0 \n"
  244. :::"r0"
  245. );
  246. }
  247. void mmu_disable_dcache()
  248. {
  249. asm volatile
  250. (
  251. "mrc p15, 0, r0, c1, c0, 0 \n"
  252. "bic r0, r0, #(1<<2) \n"
  253. "mcr p15, 0, r0, c1, c0, 0 \n"
  254. :::"r0"
  255. );
  256. }
  257. void mmu_enable_alignfault()
  258. {
  259. asm volatile
  260. (
  261. "mrc p15, 0, r0, c1, c0, 0 \n"
  262. "orr r0, r0, #1 \n"
  263. "mcr p15, 0, r0, c1, c0, 0 \n"
  264. :::"r0"
  265. );
  266. }
  267. void mmu_disable_alignfault()
  268. {
  269. asm volatile
  270. (
  271. "mrc p15, 0, r0, c1, c0, 0 \n"
  272. "bic r0, r0, #1 \n"
  273. "mcr p15, 0, r0, c1, c0, 0 \n"
  274. :::"r0"
  275. );
  276. }
  277. void mmu_clean_invalidated_cache_index(int index)
  278. {
  279. asm volatile("mcr p15, 0, %0, c7, c14, 2": :"r"(index));
  280. }
  281. void mmu_clean_invalidated_dcache(rt_uint32_t buffer, rt_uint32_t size)
  282. {
  283. unsigned int ptr;
  284. ptr = buffer & ~(CACHE_LINE_SIZE - 1);
  285. while (ptr < buffer + size)
  286. {
  287. asm volatile("mcr p15, 0, %0, c7, c14, 1": :"r"(ptr));
  288. ptr += CACHE_LINE_SIZE;
  289. }
  290. }
  291. void mmu_clean_dcache(rt_uint32_t buffer, rt_uint32_t size)
  292. {
  293. unsigned int ptr;
  294. ptr = buffer & ~(CACHE_LINE_SIZE - 1);
  295. while (ptr < buffer + size)
  296. {
  297. asm volatile("mcr p15, 0, %0, c7, c10, 1": :"r"(ptr));
  298. ptr += CACHE_LINE_SIZE;
  299. }
  300. }
  301. void mmu_invalidate_dcache(rt_uint32_t buffer, rt_uint32_t size)
  302. {
  303. unsigned int ptr;
  304. ptr = buffer & ~(CACHE_LINE_SIZE - 1);
  305. while (ptr < buffer + size)
  306. {
  307. asm volatile("mcr p15, 0, %0, c7, c6, 1": :"r"(ptr));
  308. ptr += CACHE_LINE_SIZE;
  309. }
  310. }
  311. void mmu_invalidate_tlb()
  312. {
  313. asm volatile("mcr p15, 0, %0, c8, c7, 0": :"r"(0));
  314. }
  315. void mmu_invalidate_icache()
  316. {
  317. asm volatile("mcr p15, 0, %0, c7, c5, 0": :"r"(0));
  318. }
  319. void mmu_invalidate_dcache_all()
  320. {
  321. asm volatile("mcr p15, 0, %0, c7, c6, 0": :"r"(0));
  322. }
  323. #endif
  324. /* level1 page table */
  325. #if defined(__ICCARM__)
  326. #pragma data_alignment=(16*1024)
  327. static volatile rt_uint32_t _page_table[4 * 1024];
  328. #else
  329. static volatile rt_uint32_t _page_table[4 * 1024] \
  330. __attribute__((aligned(16 * 1024)));
  331. #endif
  332. void mmu_setmtt(rt_uint32_t vaddrStart, rt_uint32_t vaddrEnd,
  333. rt_uint32_t paddrStart, rt_uint32_t attr)
  334. {
  335. volatile rt_uint32_t *pTT;
  336. volatile int nSec;
  337. int i = 0;
  338. pTT = (rt_uint32_t *)_page_table + (vaddrStart >> 20);
  339. nSec = (vaddrEnd >> 20) - (vaddrStart >> 20);
  340. for (i = 0; i <= nSec; i++)
  341. {
  342. *pTT = attr | (((paddrStart >> 20) + i) << 20);
  343. pTT++;
  344. }
  345. }
  346. void rt_hw_mmu_init(struct mem_desc *mdesc, rt_uint32_t size)
  347. {
  348. /* disable I/D cache */
  349. mmu_disable_dcache();
  350. mmu_disable_icache();
  351. mmu_disable();
  352. mmu_invalidate_tlb();
  353. /* set page table */
  354. for (; size > 0; size--)
  355. {
  356. mmu_setmtt(mdesc->vaddr_start, mdesc->vaddr_end,
  357. mdesc->paddr_start, mdesc->attr);
  358. mdesc++;
  359. }
  360. /* set MMU table address */
  361. mmu_setttbase((rt_uint32_t)_page_table);
  362. /* enables MMU */
  363. mmu_enable();
  364. /* enable Instruction Cache */
  365. mmu_enable_icache();
  366. /* enable Data Cache */
  367. mmu_enable_dcache();
  368. mmu_invalidate_icache();
  369. mmu_invalidate_dcache_all();
  370. }