n22_func.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. // See LICENSE for license details.
  2. #include <gd32vf103.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <unistd.h>
  7. #include "riscv_encoding.h"
  8. #include "n22_func.h"
  9. void switch_m2u_mode() {
  10. clear_csr(mstatus, MSTATUS_MPP);
  11. //printf("\nIn the m2u function, the mstatus is 0x%x\n", read_csr(mstatus));
  12. //printf("\nIn the m2u function, the mepc is 0x%x\n", read_csr(mepc));
  13. asm volatile ("la x6, 1f ":::"x6");
  14. asm volatile ("csrw mepc, x6":::);
  15. asm volatile ("mret":::);
  16. asm volatile ("1:":::);
  17. }
  18. uint32_t mtime_lo(void) {
  19. return *(volatile uint32_t *) (TMR_CTRL_ADDR + TMR_MTIME);
  20. }
  21. uint32_t mtime_hi(void) {
  22. return *(volatile uint32_t *) (TMR_CTRL_ADDR + TMR_MTIME + 4);
  23. }
  24. void enable_timer_interrupt(void) {
  25. *(volatile uint32_t *) (TMR_CTRL_ADDR + TMR_MTIME + 0xffc) = 1;
  26. }
  27. void clear_timer_interrupt(void) {
  28. *(volatile uint32_t *) (TMR_CTRL_ADDR + TMR_MTIME + 0xffc) = 0;
  29. }
  30. void close_timer(void) {
  31. *(volatile uint32_t *) (TMR_CTRL_ADDR + TMR_MTIME + 0xff8) = 1;
  32. }
  33. void open_timer(void) {
  34. *(volatile uint32_t *) (TMR_CTRL_ADDR + TMR_MTIME + 0xff8) = 0;
  35. }
  36. uint64_t get_timer_value() {
  37. while (1) {
  38. uint32_t hi = mtime_hi();
  39. uint32_t lo = mtime_lo();
  40. if (hi == mtime_hi())
  41. return ((uint64_t) hi << 32) | lo;
  42. }
  43. }
  44. uint32_t get_timer_freq() {
  45. return TMR_FREQ;
  46. }
  47. uint64_t get_instret_value() {
  48. while (1) {
  49. uint32_t hi = read_csr(minstreth);
  50. uint32_t lo = read_csr(minstret);
  51. if (hi == read_csr(minstreth))
  52. return ((uint64_t) hi << 32) | lo;
  53. }
  54. }
  55. uint64_t get_cycle_value() {
  56. while (1) {
  57. uint32_t hi = read_csr(mcycleh);
  58. uint32_t lo = read_csr(mcycle);
  59. if (hi == read_csr(mcycleh))
  60. return ((uint64_t) hi << 32) | lo;
  61. }
  62. }
  63. // Note that there are no assertions or bounds checking on these
  64. // parameter values.
  65. void eclic_init(uint32_t num_irq) {
  66. typedef volatile uint32_t vuint32_t;
  67. //clear cfg register
  68. *(volatile uint8_t*) (ECLIC_ADDR_BASE + ECLIC_CFG_OFFSET) = 0;
  69. //clear minthresh register
  70. *(volatile uint8_t*) (ECLIC_ADDR_BASE + ECLIC_MTH_OFFSET) = 0;
  71. //clear all IP/IE/ATTR/CTRL bits for all interrupt sources
  72. vuint32_t * ptr;
  73. vuint32_t * base = (vuint32_t*) (ECLIC_ADDR_BASE + ECLIC_INT_IP_OFFSET);
  74. vuint32_t * upper = (vuint32_t*) (base + num_irq * 4);
  75. for (ptr = base; ptr < upper; ptr = ptr + 4) {
  76. *ptr = 0;
  77. }
  78. eclic_set_nlbits(ECLIC_GROUP_LEVEL2_PRIO2);
  79. }
  80. void eclic_enable_interrupt(uint32_t source) {
  81. *(volatile uint8_t*) (ECLIC_ADDR_BASE + ECLIC_INT_IE_OFFSET + source * 4) =
  82. 1;
  83. }
  84. void eclic_disable_interrupt(uint32_t source) {
  85. *(volatile uint8_t*) (ECLIC_ADDR_BASE + ECLIC_INT_IE_OFFSET + source * 4) =
  86. 0;
  87. }
  88. void eclic_set_pending(uint32_t source) {
  89. *(volatile uint8_t*) (ECLIC_ADDR_BASE + ECLIC_INT_IP_OFFSET + source * 4) =
  90. 1;
  91. }
  92. void eclic_clear_pending(uint32_t source) {
  93. *(volatile uint8_t*) (ECLIC_ADDR_BASE + ECLIC_INT_IP_OFFSET + source * 4) =
  94. 0;
  95. }
  96. void eclic_set_intctrl(uint32_t source, uint8_t intctrl) {
  97. *(volatile uint8_t*) (ECLIC_ADDR_BASE + ECLIC_INT_CTRL_OFFSET + source * 4) =
  98. intctrl;
  99. }
  100. uint8_t eclic_get_intctrl(uint32_t source) {
  101. return *(volatile uint8_t*) (ECLIC_ADDR_BASE + ECLIC_INT_CTRL_OFFSET
  102. + source * 4);
  103. }
  104. void eclic_set_intattr(uint32_t source, uint8_t intattr) {
  105. *(volatile uint8_t*) (ECLIC_ADDR_BASE + ECLIC_INT_ATTR_OFFSET + source * 4) =
  106. intattr;
  107. }
  108. uint8_t eclic_get_intattr(uint32_t source) {
  109. return *(volatile uint8_t*) (ECLIC_ADDR_BASE + ECLIC_INT_ATTR_OFFSET
  110. + source * 4);
  111. }
  112. void eclic_set_ecliccfg(uint8_t ecliccfg) {
  113. *(volatile uint8_t*) (ECLIC_ADDR_BASE + ECLIC_CFG_OFFSET) = ecliccfg;
  114. }
  115. uint8_t eclic_get_ecliccfg() {
  116. return *(volatile uint8_t*) (ECLIC_ADDR_BASE + ECLIC_CFG_OFFSET);
  117. }
  118. void eclic_set_mth(uint8_t mth) {
  119. *(volatile uint8_t*) (ECLIC_ADDR_BASE + ECLIC_MTH_OFFSET) = mth;
  120. }
  121. uint8_t eclic_get_mth() {
  122. return *(volatile uint8_t*) (ECLIC_ADDR_BASE + ECLIC_MTH_OFFSET);
  123. }
  124. void eclic_set_nlbits(uint8_t nlbits) {
  125. //shift nlbits to correct position
  126. uint8_t nlbits_shifted = nlbits << ECLIC_CFG_NLBITS_LSB;
  127. //read the current ecliccfg
  128. uint8_t old_ecliccfg = eclic_get_ecliccfg();
  129. uint8_t new_ecliccfg = (old_ecliccfg & (~ECLIC_CFG_NLBITS_MASK))
  130. | (ECLIC_CFG_NLBITS_MASK & nlbits_shifted);
  131. eclic_set_ecliccfg(new_ecliccfg);
  132. }
  133. uint8_t eclic_get_nlbits(void) {
  134. //extract nlbits
  135. uint8_t nlbits = eclic_get_ecliccfg();
  136. nlbits = (nlbits & ECLIC_CFG_NLBITS_MASK) >> ECLIC_CFG_NLBITS_LSB;
  137. return nlbits;
  138. }
  139. //sets an interrupt level based encoding of nlbits and ECLICINTCTLBITS
  140. uint8_t eclic_set_int_level(uint32_t source, uint8_t level) {
  141. //extract nlbits
  142. uint8_t nlbits = eclic_get_nlbits();
  143. if (nlbits > ECLICINTCTLBITS) {
  144. nlbits = ECLICINTCTLBITS;
  145. }
  146. //shift level into correct bit position
  147. level = level << (8 - nlbits);
  148. //write to eclicintctrl
  149. uint8_t current_intctrl = eclic_get_intctrl(source);
  150. //shift intctrl left to mask off unused bits
  151. current_intctrl = current_intctrl << nlbits;
  152. //shift intctrl into correct bit position
  153. current_intctrl = current_intctrl >> nlbits;
  154. eclic_set_intctrl(source, (current_intctrl | level));
  155. return level;
  156. }
  157. //gets an interrupt level based encoding of nlbits
  158. uint8_t eclic_get_int_level(uint32_t source) {
  159. //extract nlbits
  160. uint8_t nlbits = eclic_get_nlbits();
  161. if (nlbits > ECLICINTCTLBITS) {
  162. nlbits = ECLICINTCTLBITS;
  163. }
  164. uint8_t intctrl = eclic_get_intctrl(source);
  165. //shift intctrl
  166. intctrl = intctrl >> (8 - nlbits);
  167. //shift intctrl
  168. uint8_t level = intctrl << (8 - nlbits);
  169. return level;
  170. }
  171. //sets an interrupt priority based encoding of nlbits and ECLICINTCTLBITS
  172. uint8_t eclic_set_int_priority(uint32_t source, uint8_t priority) {
  173. //extract nlbits
  174. uint8_t nlbits = eclic_get_nlbits();
  175. if (nlbits >= ECLICINTCTLBITS) {
  176. nlbits = ECLICINTCTLBITS;
  177. return 0;
  178. }
  179. //shift priority into correct bit position
  180. priority = priority << (8 - ECLICINTCTLBITS);
  181. //write to eclicintctrl
  182. uint8_t current_intctrl = eclic_get_intctrl(source);
  183. //shift intctrl right to mask off unused bits
  184. current_intctrl = current_intctrl >> (8 - nlbits);
  185. //shift intctrl into correct bit position
  186. current_intctrl = current_intctrl << (8 - nlbits);
  187. eclic_set_intctrl(source, (current_intctrl | priority));
  188. return priority;
  189. }
  190. //gets an interrupt priority based encoding of nlbits
  191. uint8_t eclic_get_int_priority(uint32_t source) {
  192. //extract nlbits
  193. uint8_t nlbits = eclic_get_nlbits();
  194. if (nlbits > ECLICINTCTLBITS) {
  195. nlbits = ECLICINTCTLBITS;
  196. }
  197. uint8_t intctrl = eclic_get_intctrl(source);
  198. //shift intctrl
  199. intctrl = intctrl << nlbits;
  200. //shift intctrl
  201. uint8_t priority = intctrl >> (nlbits + (8 - ECLICINTCTLBITS));
  202. return priority;
  203. }
  204. void eclic_mode_enable() {
  205. uint32_t mtvec_value = read_csr(mtvec);
  206. mtvec_value = mtvec_value & 0xFFFFFFC0;
  207. mtvec_value = mtvec_value | 0x00000003;
  208. write_csr(mtvec, mtvec_value);
  209. }
  210. void eclic_set_shv(uint32_t source, uint8_t shv) {
  211. uint8_t attr = eclic_get_intattr(source);
  212. if (shv) {
  213. attr |= 0x01;
  214. eclic_set_intattr(source, attr);
  215. }
  216. }
  217. void eclic_set_trig(uint32_t source, uint8_t trig) {
  218. uint8_t attr = eclic_get_intattr(source);
  219. if ((trig & 0x1)) {
  220. attr |= (trig << 1);
  221. eclic_set_intattr(source, attr);
  222. }
  223. }