ARM7 based quadrocopter
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

205 lines
6.1KB

  1. /***************************************************************************
  2. * sam7fc - Abort Handler with Register/Stackdump *
  3. * *
  4. * Copyright (C) 01/2008 by Olaf Rempel *
  5. * razzor@kopf-tisch.de *
  6. * *
  7. * This program is free software; you can redistribute it and/or modify *
  8. * it under the terms of the GNU General Public License as published by *
  9. * the Free Software Foundation; version 2 of the License *
  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 *
  17. * along with this program; if not, write to the *
  18. * Free Software Foundation, Inc., *
  19. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
  20. ***************************************************************************/
  21. #include <stdint.h>
  22. #include "AT91SAM7S256.h"
  23. #include "board.h"
  24. static void dbgu_putchar(char c)
  25. {
  26. while (!(*AT91C_DBGU_CSR & AT91C_US_TXEMPTY));
  27. *AT91C_DBGU_THR = c;
  28. if (c == '\n') {
  29. while (!(*AT91C_DBGU_CSR & AT91C_US_TXEMPTY));
  30. *AT91C_DBGU_THR = '\r';
  31. }
  32. }
  33. static void dbgu_puts(const char *p)
  34. {
  35. while (*p != '\0')
  36. dbgu_putchar(*p++);
  37. }
  38. static void dbgu_hexvar(const char *name, uint32_t var)
  39. {
  40. dbgu_puts(name);
  41. char buf[11];
  42. buf[0] = '0';
  43. buf[1] = 'x';
  44. uint32_t i;
  45. for (i = 9; i > 1; i--) {
  46. buf[i] = (var & 0x0F);
  47. buf[i] += (buf[i] < 0xa) ? '0' : ('a' - 0x0a);
  48. var >>= 4;
  49. }
  50. buf[10] = '\0';
  51. dbgu_puts(buf);
  52. }
  53. /*
  54. ARM7TDMI 32bit Undefined Address Instruction Fetch Abort
  55. (ASR:0x02020a01 AASR:0x80000008)
  56. --- Registerdump (cpsr:0xa0000013 - SVC):
  57. r0:0x00000002 r1:0x0000000c r2:0x00200038 r3:0x80000000
  58. r4:0x0020fffc r5:0x00101788 r6:0x00000180 r7:0x41000000
  59. r8:0x00008400 r9:0x00100004 sl:0x03000294 fp:0x0020fe84
  60. ip:0x0020fe10 sp:0x0020fe70 lr:0x00102174 pc:0x80000004
  61. --- Stackdump:
  62. 0x0020fe70: 0x0020fe7c 0x00101648 0x001015a8 0x0020feaf
  63. 0x0020fe80: 0x0020fec0 0x0020fe90 0x00101780 0x00101620
  64. 0x0020fe90: 0x00000002 0x00000000 0x00000030 0x00000000
  65. 0x0020fea0: 0x001029a8 0x307830b0 0x33383730 0x00303337
  66. */
  67. void at91_abt_handler(uint32_t cpsr, uint32_t *registers)
  68. {
  69. /* enable Debug Port with 115200 Baud (+0.16%) */
  70. AT91S_DBGU *dbgu = AT91C_BASE_DBGU;
  71. dbgu->DBGU_BRGR = BAUD_TO_DIV(115200);
  72. dbgu->DBGU_MR = AT91C_US_PAR_NONE | AT91C_US_CHMODE_NORMAL;
  73. dbgu->DBGU_CR = AT91C_US_RXEN | AT91C_US_TXEN | AT91C_US_RSTSTA;
  74. /* switch pins to UART */
  75. *AT91C_PIOA_PDR = AT91C_PA9_DRXD | AT91C_PA10_DTXD;
  76. AT91_REG asr = *AT91C_MC_ASR;
  77. if (asr & AT91C_MC_MST0)
  78. dbgu_puts("PDC ");
  79. else if (asr & AT91C_MC_MST1)
  80. dbgu_puts("ARM7TDMI ");
  81. switch (asr & AT91C_MC_ABTSZ) {
  82. case AT91C_MC_ABTSZ_BYTE:
  83. dbgu_puts("8bit ");
  84. break;
  85. case AT91C_MC_ABTSZ_HWORD:
  86. dbgu_puts("16bit ");
  87. break;
  88. case AT91C_MC_ABTSZ_WORD:
  89. dbgu_puts("32bit ");
  90. break;
  91. }
  92. if (asr & AT91C_MC_UNDADD)
  93. dbgu_puts("Undefined Address ");
  94. else if (asr & AT91C_MC_MISADD)
  95. dbgu_puts("Misaliged Address ");
  96. switch (asr & AT91C_MC_ABTTYP) {
  97. case AT91C_MC_ABTTYP_DATAR:
  98. dbgu_puts("Data Read ");
  99. break;
  100. case AT91C_MC_ABTTYP_DATAW:
  101. dbgu_puts("Data Write ");
  102. break;
  103. case AT91C_MC_ABTTYP_FETCH:
  104. dbgu_puts("Prefetch ");
  105. break;
  106. }
  107. dbgu_hexvar("Abort\n(ASR:", asr);
  108. dbgu_hexvar(" AASR:", *AT91C_MC_AASR);
  109. dbgu_puts(")\n");
  110. dbgu_hexvar("--- Registerdump (cpsr:", cpsr);
  111. dbgu_puts(" - ");
  112. switch (cpsr & 0x1F) {
  113. case 0x10: dbgu_puts("USR"); break;
  114. case 0x11: dbgu_puts("FIQ"); break;
  115. case 0x12: dbgu_puts("IRQ"); break;
  116. case 0x13: dbgu_puts("SVC"); break;
  117. case 0x17: dbgu_puts("ABT"); break;
  118. case 0x1B: dbgu_puts("UND"); break;
  119. case 0x1F: dbgu_puts("SYS"); break;
  120. }
  121. dbgu_hexvar("):\n r0:", registers[3]);
  122. dbgu_hexvar(" r1:", registers[4]);
  123. dbgu_hexvar(" r2:", registers[5]);
  124. dbgu_hexvar(" r3:", registers[6]);
  125. dbgu_hexvar("\n r4:", registers[7]);
  126. dbgu_hexvar(" r5:", registers[8]);
  127. dbgu_hexvar(" r6:", registers[9]);
  128. dbgu_hexvar(" r7:", registers[10]);
  129. dbgu_hexvar("\n r8:", registers[11]);
  130. dbgu_hexvar(" r9:", registers[12]);
  131. dbgu_hexvar(" sl:", registers[13]);
  132. dbgu_hexvar(" fp:", registers[14]);
  133. dbgu_hexvar("\n ip:", registers[15]);
  134. dbgu_hexvar(" sp:", registers[0]);
  135. dbgu_hexvar(" lr:", registers[1]);
  136. dbgu_hexvar(" pc:", registers[2]);
  137. dbgu_puts("\n--- Stackdump:");
  138. uint32_t *val = (uint32_t *)(registers[0] & ~0x0F);
  139. for ( ; val < (uint32_t *)(registers[0] & ~0x0F) +16; val++) {
  140. if (!((uint32_t)val & 0x0F)) {
  141. dbgu_hexvar("\n", (uint32_t)val);
  142. dbgu_putchar(':');
  143. }
  144. dbgu_hexvar(" ", *val);
  145. }
  146. dbgu_putchar('\n');
  147. }
  148. __attribute__((naked)) void ABT_Handler(void)
  149. {
  150. asm volatile (
  151. ".equ ARM_MODE_ABT, 0x17 \n\t"
  152. ".equ I_BIT, 0x80 \n\t"
  153. ".equ F_BIT, 0x40 \n\t"
  154. /* disable interrupts (F_BIT not set on entry) */
  155. "msr CPSR_c, #ARM_MODE_ABT | I_BIT | F_BIT \n\t"
  156. /* store all registers */
  157. "stmfd sp!, { r0-r12 } \n\t"
  158. /* saved cpsr (from aborted mode) */
  159. "mrs r0, SPSR \n\t"
  160. /* address of abort (pc) */
  161. "mov r3, lr \n\t"
  162. /* enter previous mode and get lr(r14), sp(r13) */
  163. "orr r1, r0, #I_BIT | F_BIT \n\t"
  164. "msr CPSR_c, r1 \n\t"
  165. "mov r1, sp \n\t"
  166. "mov r2, lr \n\t"
  167. /* return to abort mode */
  168. "msr CPSR_c, #ARM_MODE_ABT | I_BIT | F_BIT \n\t"
  169. /* store remaining registers (r1-r3 == r13-r15) */
  170. "stmfd sp!, { r1-r3 } \n\t"
  171. "mov r1, sp \n\t"
  172. /* execute C Handler (cpsr, *registers) */
  173. "ldr r5, =at91_abt_handler \n\t"
  174. "mov lr, pc \n\t"
  175. "bx r5 \n\t"
  176. "b . \n\t"
  177. );
  178. }