3 * \brief ADSP-BF533用のポストモーテムダンプルーチン群
5 * ハードウェアエラー用のハンドラと、例外用のハンドラからなる。いずれも呼び出されるとUARTから
8 #include "jsp_kernel.h"
12 * \brief UARTおよび付随するDMAの動作を停止し、すべての割り込みを禁止する。
14 * 最後にUART_IERをクリアするのは、UART割り込みを禁止すると同時にDMAも禁止するため。
15 * UART DMAは、UARTの割り込み線で駆動されているので、割り込みを禁止すればDMAリクエスト
18 * UARTの初期化をどうするか悩ましいが、ここではそのまま以前の設定を利用することにする。
20 * ポストモーテム・ダンプを目的としているので、この状態からの回復は考えない。
22 static void pm_occupy_uart()
25 asm( "cli r0;" : : : "R0" );
27 /* すべてのシステム割り込みソースを禁止する */
32 /* UART_IERをディセーブルにすることで、DMAを殺せる */
33 *pUART0_IER_CLEAR = 0xFFFFU;
39 * UARTの送信レジスタが空になるのを待って一文字出力する。
41 static void pm_putc( unsigned char c )
45 while ( ! ( *pUART0_LSR & THRE ) )
55 * UARTの受信レジスタにデータがあれば、読み込む。データが"!"なら真、
58 static BOOL is_ready()
61 if ( *pUART0_LSR & DR )
79 static void pm_putstr( char * s )
84 while( s[i] ) /* 末端のNULLが現れるまで出力 */
89 * \brief 1バイトをヘキサデシマルで出力する。
91 static void pm_puthex1byte( unsigned int data )
96 /* 8bit内のすべてのニブルを処理 */
100 nibble = ( data >> 4 ) & 0xF;
103 pm_putc( nibble + '0' );
105 pm_putc( nibble - 10 + 'A' );
114 static void pm_putrtn()
120 * \brief 4バイトをヘキサデシマルで出力する。
122 static void pm_puthex4byte( unsigned int data )
127 /* 32bit内のすべてのニブルを処理 */
128 for ( i=0; i<8; i++ )
131 nibble = ( data >> 28 ) & 0xF;
134 pm_putc( nibble + '0' );
136 pm_putc( nibble - 10 + 'A' );
146 * 例外が発生したときには真、そうでなければ偽。hwei_handler()に例外か否かを伝える。
148 * GCCが張り切ってlink/unlink命令の位置を最適化するため、hwei_hanlder()の
149 * 中で性格にfpを手繰れない。そのため、dummyをアクセスすることでlink/unlinkの位置
150 * 最適化の抑止を図る役目もある。効果があるかどうかは不明。
152 static volatile int expFlag =0;
154 * \brief ハードウェア・エラー・ハンドラ
156 * ハードウェア・エラー時に呼び出されて、ハードウェア・エラー・割り込みのポストモーテム処理を行う。
157 * 最初にFPを手繰って、割り込みのスタックフレームを探す。次にすべての割り込みを禁止し、
158 * UART0を占有したあと、ポーリングを使ってスタックに保存された各レジスタのダンプを行う。
159 * DEF_INH(INHNO_HW_ERROR, { TA_HLNG, hwei_handler });
162 void spurious_int_handler()
164 unsigned int * fp, *ptr ; /* フレーム・ポインタを手繰っていくための変数 */
165 unsigned int reg; /* システムレジスタを受け取るための変数 */
166 unsigned int imask, sic_imask0, sic_imask1, sic_imask2; /*マスク記録レジスタ*/
170 sic_imask0 = *pSIC_IMASK0;
171 sic_imask1 = *pSIC_IMASK1;
172 sic_imask2 = *pSIC_IMASK2;
173 /* UART0を初期化し、DMAと割り込みを禁止する */
180 pm_putstr( "Type '!' to display post mortem dump" ); pm_putrtn();
182 while ( ! is_ready() )
185 for ( i=0; i<100000000; i++)
186 asm volatile ("nop;");
189 pm_putstr( "Type '!' to display post mortem dump" ); pm_putrtn();
199 asm ( "%0=fp;" : "=d"((unsigned int)fp) );
202 * この関数を呼び出した関数 ( interrupt_dispatcher ) のFPを取得する。
203 * FPは呼び出し関数のFPの格納番地を指していることを利用する
207 * interrupt_dispatcher を呼び出した関数のFPを取得する。
208 * その関数は割り込みハンドラの入り口処理部に他ならない。
212 /* いまや、FPは割り込み受付時の保存されたレジスタ群を指している */
218 * 0 1 2 3 4 5 6 7 8 9
219 * -----------------------------------------------
220 * 00 P0 RTS FP R0 R1 R2 R3 R4 R5 R6
221 * 10 R7 P1 P2 P3 P4 P5 I3 I2 I1 I0
222 * 20 M3 M2 M1 M0 B3 B2 B1 B0 L3 L2
223 * 30 L1 L0 A0x A0w A1x A1w LC1 LC0 LT1 LT0
224 * 40 LB1 LB0 AST RETI
229 pm_putstr( "Spurious Exception !!" );
231 pm_putstr( "Spurious Interrupt !!" );
234 pm_putstr( "Registers On Stack :" ); pm_putrtn();
235 pm_putstr( "P0 " ); pm_puthex4byte( *(ptr--) ); pm_putrtn();
236 pm_putstr( "RETS " ); pm_puthex4byte( *(ptr--) ); pm_putrtn();
237 pm_putstr( "FP " ); pm_puthex4byte( *(ptr--) ); pm_putrtn();
238 pm_putstr( "R0 " ); pm_puthex4byte( *(ptr--) ); pm_putrtn();
239 pm_putstr( "R1 " ); pm_puthex4byte( *(ptr--) ); pm_putrtn();
240 pm_putstr( "R2 " ); pm_puthex4byte( *(ptr--) ); pm_putrtn();
241 pm_putstr( "R3 " ); pm_puthex4byte( *(ptr--) ); pm_putrtn();
242 pm_putstr( "R4 " ); pm_puthex4byte( *(ptr--) ); pm_putrtn();
243 pm_putstr( "R5 " ); pm_puthex4byte( *(ptr--) ); pm_putrtn();
244 pm_putstr( "R6 " ); pm_puthex4byte( *(ptr--) ); pm_putrtn();
245 pm_putstr( "R7 " ); pm_puthex4byte( *(ptr--) ); pm_putrtn();
246 pm_putstr( "P1 " ); pm_puthex4byte( *(ptr--) ); pm_putrtn();
247 pm_putstr( "P2 " ); pm_puthex4byte( *(ptr--) ); pm_putrtn();
248 pm_putstr( "P3 " ); pm_puthex4byte( *(ptr--) ); pm_putrtn();
249 pm_putstr( "P4 " ); pm_puthex4byte( *(ptr--) ); pm_putrtn();
250 pm_putstr( "P5 " ); pm_puthex4byte( *(ptr--) ); pm_putrtn();
251 pm_putstr( "I3 " ); pm_puthex4byte( *(ptr--) ); pm_putrtn();
252 pm_putstr( "I2 " ); pm_puthex4byte( *(ptr--) ); pm_putrtn();
253 pm_putstr( "I1 " ); pm_puthex4byte( *(ptr--) ); pm_putrtn();
254 pm_putstr( "I0 " ); pm_puthex4byte( *(ptr--) ); pm_putrtn();
255 pm_putstr( "M3 " ); pm_puthex4byte( *(ptr--) ); pm_putrtn();
256 pm_putstr( "M2 " ); pm_puthex4byte( *(ptr--) ); pm_putrtn();
257 pm_putstr( "M1 " ); pm_puthex4byte( *(ptr--) ); pm_putrtn();
258 pm_putstr( "M0 " ); pm_puthex4byte( *(ptr--) ); pm_putrtn();
259 pm_putstr( "B3 " ); pm_puthex4byte( *(ptr--) ); pm_putrtn();
260 pm_putstr( "B2 " ); pm_puthex4byte( *(ptr--) ); pm_putrtn();
261 pm_putstr( "B1 " ); pm_puthex4byte( *(ptr--) ); pm_putrtn();
262 pm_putstr( "B0 " ); pm_puthex4byte( *(ptr--) ); pm_putrtn();
263 pm_putstr( "L3 " ); pm_puthex4byte( *(ptr--) ); pm_putrtn();
264 pm_putstr( "L2 " ); pm_puthex4byte( *(ptr--) ); pm_putrtn();
265 pm_putstr( "L1 " ); pm_puthex4byte( *(ptr--) ); pm_putrtn();
266 pm_putstr( "L0 " ); pm_puthex4byte( *(ptr--) ); pm_putrtn();
267 pm_putstr( "A0 " ); pm_puthex1byte( *(ptr--) ); pm_putstr( ":" ); pm_puthex4byte( *(ptr--) ); pm_putrtn();
268 pm_putstr( "A1 " ); pm_puthex1byte( *(ptr--) ); pm_putstr( ":" ); pm_puthex4byte( *(ptr--) ); pm_putrtn();
269 pm_putstr( "LC1 " ); pm_puthex4byte( *(ptr--) ); pm_putrtn();
270 pm_putstr( "LC0 " ); pm_puthex4byte( *(ptr--) ); pm_putrtn();
271 pm_putstr( "LT1 " ); pm_puthex4byte( *(ptr--) ); pm_putrtn();
272 pm_putstr( "LT0 " ); pm_puthex4byte( *(ptr--) ); pm_putrtn();
273 pm_putstr( "LB1 " ); pm_puthex4byte( *(ptr--) ); pm_putrtn();
274 pm_putstr( "LB0 " ); pm_puthex4byte( *(ptr--) ); pm_putrtn();
275 pm_putstr( "ASTAT " ); pm_puthex4byte( *(ptr--) ); pm_putrtn();
276 pm_putstr( "RETI " ); pm_puthex4byte( *(ptr--) ); pm_putrtn();
278 pm_putstr( "System Registers :" ); pm_putrtn();
279 pm_putstr( "SIC_IMASK2:1:0 " ); pm_puthex4byte( sic_imask2 );pm_puthex4byte( sic_imask1 );pm_putstr( " : " );pm_puthex4byte( sic_imask0 ); pm_putrtn();
280 pm_putstr( "SIC_ISR1:0 " ); pm_puthex4byte( *pSIC_ISR1 );pm_putstr( " : " );pm_puthex4byte( *pSIC_ISR0 ); pm_putrtn();
281 pm_putstr( "IMASK " ); pm_puthex4byte( imask ); pm_putrtn();
282 pm_putstr( "ILAT " ); pm_puthex4byte( *pILAT ); pm_putrtn();
283 pm_putstr( "IPEND " ); pm_puthex4byte( *pIPEND ); pm_putrtn();
284 asm( "%0=SEQSTAT;" : "=d"(reg) );
285 pm_putstr( "SEQSTAT " ); pm_puthex4byte( reg ); pm_putrtn();
286 pm_putstr( " EXCAUSE " ); pm_puthex1byte( reg & 0x3F ); pm_putrtn();
287 pm_putstr( " HWERRCAUSE " ); pm_puthex1byte( (reg>>14)&0x1F ); pm_putrtn();
288 pm_putstr( "DMA0_IRQ_STATUS " ); pm_puthex4byte( *pDMA0_IRQ_STATUS ); pm_putrtn();
289 pm_putstr( "DMA1_IRQ_STATUS " ); pm_puthex4byte( *pDMA1_IRQ_STATUS ); pm_putrtn();
290 pm_putstr( "DMA2_IRQ_STATUS " ); pm_puthex4byte( *pDMA2_IRQ_STATUS ); pm_putrtn();
291 pm_putstr( "DMA3_IRQ_STATUS " ); pm_puthex4byte( *pDMA3_IRQ_STATUS ); pm_putrtn();
292 pm_putstr( "DMA4_IRQ_STATUS " ); pm_puthex4byte( *pDMA4_IRQ_STATUS ); pm_putrtn();
293 pm_putstr( "DMA5_IRQ_STATUS " ); pm_puthex4byte( *pDMA5_IRQ_STATUS ); pm_putrtn();
294 pm_putstr( "DMA6_IRQ_STATUS " ); pm_puthex4byte( *pDMA6_IRQ_STATUS ); pm_putrtn();
295 pm_putstr( "DMA7_IRQ_STATUS " ); pm_puthex4byte( *pDMA7_IRQ_STATUS ); pm_putrtn();
296 pm_putstr( "DMA8_IRQ_STATUS " ); pm_puthex4byte( *pDMA8_IRQ_STATUS ); pm_putrtn();
297 pm_putstr( "DMA9_IRQ_STATUS " ); pm_puthex4byte( *pDMA9_IRQ_STATUS ); pm_putrtn();
298 pm_putstr( "DMA10_IRQ_STATUS " ); pm_puthex4byte( *pDMA10_IRQ_STATUS ); pm_putrtn();
299 pm_putstr( "DMA11_IRQ_STATUS " ); pm_puthex4byte( *pDMA11_IRQ_STATUS ); pm_putrtn();
300 pm_putstr( "MDMA_D0_IRQ_STATUS " ); pm_puthex4byte( *pMDMA_D0_IRQ_STATUS ); pm_putrtn();
301 pm_putstr( "MDMA_S0_IRQ_STATUS " ); pm_puthex4byte( *pMDMA_S0_IRQ_STATUS ); pm_putrtn();
302 pm_putstr( "MDMA_D1_IRQ_STATUS " ); pm_puthex4byte( *pMDMA_D1_IRQ_STATUS ); pm_putrtn();
303 pm_putstr( "MDMA_S1_IRQ_STATUS " ); pm_puthex4byte( *pMDMA_S1_IRQ_STATUS ); pm_putrtn();
304 pm_putstr( "SPI0_STAT " ); pm_puthex4byte( *pSPI0_STAT ); pm_putrtn();
305 pm_putstr( "SPI1_STAT " ); pm_puthex4byte( *pSPI1_STAT ); pm_putrtn();
306 pm_putstr( "SPI2_STAT " ); pm_puthex4byte( *pSPI2_STAT ); pm_putrtn();
307 pm_putstr( "EPPI0_STATUS " ); pm_puthex4byte( *pEPPI0_STATUS ); pm_putrtn();
308 pm_putstr( "EPPI1_STATUS " ); pm_puthex4byte( *pEPPI1_STATUS ); pm_putrtn();
309 pm_putstr( "EPPI2_STATUS " ); pm_puthex4byte( *pEPPI2_STATUS ); pm_putrtn();
310 pm_putstr( "SPORT0_STAT " ); pm_puthex4byte( *pSPORT0_STAT ); pm_putrtn();
311 pm_putstr( "SPORT1_STAT " ); pm_puthex4byte( *pSPORT1_STAT ); pm_putrtn();
312 pm_putstr( "SPORT2_STAT " ); pm_puthex4byte( *pSPORT2_STAT ); pm_putrtn();
313 pm_putstr( "SPORT3_STAT " ); pm_puthex4byte( *pSPORT3_STAT ); pm_putrtn();
314 pm_putstr( "TIMER_STATUS0 " ); pm_puthex4byte( *pTIMER_STATUS0 ); pm_putrtn();
315 pm_putstr( "TIMER_STATUS1 " ); pm_puthex4byte( *pTIMER_STATUS1 ); pm_putrtn();
317 pm_putstr( "Calling Stack :" ); pm_putrtn();
321 pm_putstr( "Called from " ); pm_puthex4byte( *(fp+1) ); pm_putrtn();
330 * CPU例外ハンドラとしてcfgファイルに登録する。 hwei_handler()は呼ばれたら戻ってこないが、
331 * そのあとにもexpFlagに値を代入しているのは、最適化によってunlink命令の値がルーチン呼び出しの
334 * DEF_EXC(CPUEXC1, { TA_HLNG, excp_handler} );
337 void spurious_exc_handler(VP p_excinf)
340 spurious_int_handler();