head.s分析(7):init_early_exception_vectors

本文介绍ADSP BF561 DSP处理器在uCLinux系统下如何设置早期异常向量表,并通过分析early_trap中断入口函数,探讨了异常处理流程及参数传递方式。

 

快乐虾

http://blog.youkuaiyun.com/lights_joy/

lights@hb165.com

 

本文适用于

ADI bf561 DSP

uclinux-2008r1.5-rc3 (移植到vdsp5)

Visual DSP++ 5.0(update 5)

 

欢迎转载,但请保留作者信息

 

#ifdef CONFIG_EARLY_PRINTK

     SP += -12;

     call.x _init_early_exception_vectors;

     SP += 12;

#endif

所调用的这个函数将设置EVT2-EVT15的中断向量。同时将所有的返回地址也指向同一个位置。

/*

 * Set up a temporary Event Vector Table, so if something bad happens before

 * the kernel is fully started, it doesn't vector off into somewhere we don't

 * know

 */

 

asmlinkage void __init init_early_exception_vectors(void)

{

     SSYNC();

 

     /* cannot program in software:

      * evt0 - emulation (jtag)

      * evt1 - reset

      */

     bfin_write_EVT2(early_trap);

     bfin_write_EVT3(early_trap);

     bfin_write_EVT5(early_trap);

     bfin_write_EVT6(early_trap);

     bfin_write_EVT7(early_trap);

     bfin_write_EVT8(early_trap);

     bfin_write_EVT9(early_trap);

     bfin_write_EVT10(early_trap);

     bfin_write_EVT11(early_trap);

     bfin_write_EVT12(early_trap);

     bfin_write_EVT13(early_trap);

     bfin_write_EVT14(early_trap);

     bfin_write_EVT15(early_trap);

     CSYNC();

 

     /* Set all the return from interrupt, exception, NMI to a known place

      * so if we do a RETI, RETX or RETN by mistake - we go somewhere known

      * Note - don't change RETS - we are in a subroutine, or

      * RETE - since it might screw up if emulator is attached

      */

     asm("/tRETI = %0; RETX = %0; RETN = %0;/n"

         : : "p"(early_trap));

 

}

其中RETI为中断服务的返回地址,RETX为异常中断的返回地址,RETN为不可屏蔽中断的返回地址。

early_trap这一中断入口的定义在linux-2.6.x/arch/blackfin/mach-common/entry.S中:

ENTRY(_early_trap)

     SAVE_ALL_SYS

     trace_buffer_stop(p0,r0)

 

     /* Turn caches off, to ensure we don't get double exceptions */

 

     P4.L = LO(IMEM_CONTROL);

     P4.H = HI(IMEM_CONTROL);

 

     R5 = [P4];              /* Control Register*/

     BITCLR(R5,ENICPLB_P);

     CLI R1;

     SSYNC;          /* SSYNC required before writing to IMEM_CONTROL. */

     .align 8;

     [P4] = R5;

     SSYNC;

 

     P4.L = LO(DMEM_CONTROL);

     P4.H = HI(DMEM_CONTROL);

     R5 = [P4];

     BITCLR(R5,ENDCPLB_P);

     SSYNC;          /* SSYNC required before writing to DMEM_CONTROL. */

     .align 8;

     [P4] = R5;

     SSYNC;

     STI R1;

 

     r0 = sp;        /* stack frame pt_regs pointer argument ==> r0 */

     r1 = RETX;

 

     SP += -12;

     call.x _early_trap_c;

     SP += 12;

ENDPROC(_early_trap)

这段代码功能比较简单,将寄存器入栈,关闭cache,然后调用c的函数early_trap_c,由于early_trap_c直接就panic,一旦进入这个中断入口就不会再退出,所有在这个中断服务中没有返回的指令。这里比较有意思的是调用early_trap_c时的参数传递。

early_trap_c的函数原型为:

asmlinkage void __init early_trap_c(struct pt_regs *fp, void *retaddr)

它将接受一个结构体的指针和一个返回地址作为参数。在参数传递过程中,对于少于三个参数的函数调用,使用R0来传递第一个参数,使用R1来传递第二个参数。因此在上述汇编代码中,有

     r0 = sp;        /* stack frame pt_regs pointer argument ==> r0 */

     r1 = RETX;

那么结构体的内容来自于哪里呢?先看看pt_regs的定义:

/* this struct defines the way the registers are stored on the

   stack during a system call. */

 

struct pt_regs {

     long orig_pc;

     long ipend;

     long seqstat;

     long rete;

     long retn;

     long retx;

     long pc;      /* PC == RETI */

     long rets;

     long reserved;          /* Used as scratch during system calls */

     long astat;

     long lb1;

     long lb0;

     long lt1;

     long lt0;

     long lc1;

     long lc0;

     long a1w;

     long a1x;

     long a0w;

     long a0x;

     long b3;

     long b2;

     long b1;

     long b0;

     long l3;

     long l2;

     long l1;

     long l0;

     long m3;

     long m2;

     long m1;

     long m0;

     long i3;

     long i2;

     long i1;

     long i0;

     long usp;

     long fp;

     long p5;

     long p4;

     long p3;

     long p2;

     long p1;

     long p0;

     long r7;

     long r6;

     long r5;

     long r4;

     long r3;

     long r2;

     long r1;

     long r0;

     long orig_r0;

     long orig_p0;

     long syscfg;

};

再看看SAVE_ALL_SYS的定义:

#define SAVE_ALL_SYS        save_context_no_interrupts

#define save_context_no_interrupts                      /

     [--sp] = SYSCFG;                     /

     [--sp] = P0;  /* orig_p0 */                    /

     [--sp] = R0;  /* orig_r0 */                    /

     [--sp] = ( R7:0, P5:0 );                       /

     [--sp] = fp;                     /

     [--sp] = usp;                    /

                       /

     [--sp] = i0;                     /

     [--sp] = i1;                     /

     [--sp] = i2;                     /

     [--sp] = i3;                     /

                       /

     [--sp] = m0;                     /

     [--sp] = m1;                     /

     [--sp] = m2;                     /

     [--sp] = m3;                     /

                       /

     [--sp] = l0;                     /

     [--sp] = l1;                     /

     [--sp] = l2;                     /

     [--sp] = l3;                     /

                       /

     [--sp] = b0;                     /

     [--sp] = b1;                     /

     [--sp] = b2;                     /

     [--sp] = b3;                     /

     [--sp] = a0.x;                       /

     [--sp] = a0.w;                       /

     [--sp] = a1.x;                       /

     [--sp] = a1.w;                       /

                       /

     [--sp] = LC0;                    /

     [--sp] = LC1;                    /

     [--sp] = LT0;                    /

     [--sp] = LT1;                    /

     [--sp] = LB0;                    /

     [--sp] = LB1;                    /

                       /

     [--sp] = ASTAT;                      /

                       /

     [--sp] = r0;  /* Skip reserved */                       /

     [--sp] = RETS;                       /

     r0 = RETI;                       /

     [--sp] = r0;                     /

     [--sp] = RETX;                       /

     [--sp] = RETN;                       /

     [--sp] = RETE;                       /

     [--sp] = SEQSTAT;                    /

     [--sp] = r0;  /* Skip IPEND as well. */                      /

     [--sp] = r0;  /*orig_pc*/                      /

     /* Clear all L registers.  */                      /

     r0 = 0 (x);                      /

     l0 = r0;                    /

     l1 = r0;                    /

     l2 = r0;                    /

     l3 = r0;                    /

//.endm

入栈顺序刚好和pt_regs结构体的成员次序相反,由于入栈操作时SP指针是向下增长的,而结构体成员的排列则是向上增长的,因此入栈操作即相当于对结构体的成员一一赋值。

最后看看early_trap_c的实现:

asmlinkage void __init early_trap_c(struct pt_regs *fp, void *retaddr)

{

     /* This can happen before the uart is initialized, so initialize

      * the UART now

      */

     if (likely(early_console == NULL))

         setup_early_printk(DEFAULT_EARLY_PORT);

 

     dump_bfin_mem(fp);

     show_regs(fp);

     dump_bfin_trace_buffer();

 

     panic("Died early");

}

输出寄存器的内容,然后panic

 

1       参考资料

head.s分析(1):保存u-boot传递过来的指针(2009-1-19)

head.s分析(2)SYSCFG配置(2009-1-19)

head.s分析(3):数据及指针寄存器清0(2009-1-19)

head.s分析(4):关闭CACHE(2009-01-19)

head.s分析(5):关闭串口(2009-01-19)

head.s分析(6):栈指针初始化(2009-01-19)

 

 

我的代码在烧录后,启动监视器显示ELF file SHA256: 9fa0bcf41 Rebooting... ESP-ROM:esp32c3-api1-20210207 Build:Feb 7 2021 rst:0xc (RTC_SW_CPU_RST),boot:0xd (SPI_FAST_FLASH_BOOT) Saved PC:0x4038086a --- 0x4038086a: esp_restart_noos at F:/esp/Espressif/frameworks/esp-idf-v5.5/components/esp_system/port/soc/esp32c3/system_internal.c:115 SPIWP:0xee mode:DIO, clock div:1 load:0x3fcd5820,len:0x15c0 load:0x403cbf10,len:0xc34 load:0x403ce710,len:0x2ff0 entry 0x403cbf1a I (35) boot: ESP-IDF HEAD-HASH-NOTFOUND 2nd stage bootloader I (35) boot: compile time Sep 3 2025 14:38:23 I (35) boot: chip revision: v0.4 I (36) boot: efuse block revision: v1.3 I (40) boot.esp32c3: SPI Speed : 80MHz I (44) boot.esp32c3: SPI Mode : DIO I (47) boot.esp32c3: SPI Flash Size : 2MB I (51) boot: Enabling RNG early entropy source... I (56) boot: Partition Table: I (58) boot: ## Label Usage Type ST Offset Length I (65) boot: 0 nvs WiFi data 01 02 00009000 00006000 I (71) boot: 1 phy_init RF data 01 01 0000f000 00001000 I (78) boot: 2 factory factory app 00 00 00010000 00100000 I (84) boot: End of partition table I (87) esp_image: segment 0: paddr=00010020 vaddr=3c090020 size=1f3f8h (127992) map I (115) esp_image: segment 1: paddr=0002f420 vaddr=3fc93c00 size=00bf8h ( 3064) load I (116) esp_image: segment 2: paddr=00030020 vaddr=42000020 size=8ea70h (584304) map I (212) esp_image: segment 3: paddr=000bea98 vaddr=3fc947f8 size=0156ch ( 5484) load I (213) esp_image: segment 4: paddr=000c000c vaddr=40380000 size=13b74h ( 80756) load I (231) esp_image: segment 5: paddr=000d3b88 vaddr=50000000 size=00020h ( 32) load I (237) boot: Loaded app from partition at offset 0x10000 I (237) boot: Disabling RNG early entropy source... I (248) cpu_start: Unicore app I (257) cpu_start: Pro cpu start user code I (257) cpu_start: cpu freq: 160000000 Hz I (257) app_init: Application information: I (257) app_init: Project name: hidd_demos I (261) app_init: App version: 1 I (265) app_init: Compile time: Sep 3 2025 14:37:57 I (270) app_init: ELF file SHA256: 9fa0bcf41... I (274) app_init: ESP-IDF: HEAD-HASH-NOTFOUND I (279) efuse_init: Min chip rev: v0.3 I (283) efuse_init: Max chip rev: v1.99 I (287) efuse_init: Chip rev: v0.4 I (291) heap_init: Initializing. RAM available for dynamic allocation: I (297) heap_init: At 3FC9A4B0 len 00025B50 (150 KiB): RAM I (302) heap_init: At 3FCC0000 len 0001C710 (113 KiB): Retention RAM I (308) heap_init: At 3FCDC710 len 00002950 (10 KiB): Retention RAM I (314) heap_init: At 50000020 len 00001FC8 (7 KiB): RTCRAM I (320) spi_flash: detected chip: generic I (323) spi_flash: flash io: dio W (326) spi_flash: Detected size(4096k) larger than the size in the binary image header(2048k). Using the size in the binary image header. I (338) sleep_gpio: Configure to isolate all GPIO pins in sleep state I (344) sleep_gpio: Enable automatic switching of GPIO sleep configuration I (351) coexist: coex firmware version: 831ec70 I (370) coexist: coexist rom version 9387209 I (370) main_task: Started on CPU0 I (370) main_task: Calling app_main() I (370) BLE_INIT: BT controller compile version [4713a69] I (370) BLE_INIT: Feature Config, ADV:1, BLE_50:0, DTM:1, SCAN:1, CCA:0, SMP:1, CONNECT:1 I (380) BLE_INIT: Bluetooth MAC: 90:e5:b1:46:9c:06 I (380) phy_init: phy_version 1201,bae5dd99,Mar 3 2025,15:36:21 Guru Meditation Error: Core 0 panic'ed (Load access fault). Exception was unhandled. Core 0 register dump: MEPC : 0x400587d2 RA : 0x4200cd86 SP : 0x3fc9d110 GP : 0x3fc94400 --- 0x400587d2: __strtok_r in ROM --- 0x4200cd86: ble_hid_init_config at F:/esp/Espressif/frameworks/esp-idf-v5.5/components/esp_hid/src/ble_hidd.c:687 TP : 0x3fc9d270 T0 : 0x4005890e T1 : 0x0000000f T2 : 0x0000902d --- 0x4005890e: _data_end_btdm_rom in ROM S0/FP : 0x3c0a72b0 S1 : 0x3fcad454 A0 : 0x3fcaeed0 A1 : 0x09ff0106 A2 : 0x0000a101 A3 : 0x3fcaeed0 A4 : 0x3fcb8fd1 A5 : 0x3fcaeed0 A6 : 0x00000000 A7 : 0x0000000f S2 : 0x3fcaeed0 S3 : 0x00000000 S4 : 0x3fc9d1a4 S5 : 0x00000000 S6 : 0x0000a101 S7 : 0x00000000 S8 : 0x00000000 S9 : 0x00000000 S10 : 0x00000000 S11 : 0x00000000 T3 : 0x00000000 T4 : 0x0000d740 T5 : 0x00000000 T6 : 0x8c154c98 MSTATUS : 0x00001881 MTVEC : 0x40380001 MCAUSE : 0x00000005 MTVAL : 0x09ff0106 --- 0x40380001: _vector_table at F:/esp/Espressif/frameworks/esp-idf-v5.5/components/riscv/vectors_intc.S:54 MHARTID : 0x00000000 Stack memory: 3fc9d110: 0x00000000 0x00000000 0x3fc970a4 0x3fc9d1a4 0x4200bdfe 0x3fca90d8 0x00000000 0x4200cfc8 --- 0x4200bdfe: hidd_event_adapter at F:/esp/ble_hid_device_demo/main/ble_hidd_demo_main.c:300 --- 0x4200cfc8: esp_ble_hidd_dev_init at F:/esp/Espressif/frameworks/esp-idf-v5.5/components/esp_hid/src/ble_hidd.c:984 3fc9d130: 0x00000000 0x00000000 0x3fc9d17c 0x00000005 0x3c095358 0x00000001 0x00001000 0x7fffffff 3fc9d150: 0x00000000 0x00000001 0x0000002c 0x4200bdfe 0x3fc9d1a4 0x00000001 0x3fca90d8 0x4200c41c --- 0x4200bdfe: hidd_event_adapter at F:/esp/ble_hid_device_demo/main/ble_hidd_demo_main.c:300 --- 0x4200c41c: esp_hidd_dev_init at F:/esp/Espressif/frameworks/esp-idf-v5.5/components/esp_hid/src/esp_hidd.c:32 3fc9d170: 0x00000000 0x00000003 0x00000000 0x00000000 0x00000000 0x00000003 0x3c093000 0x4200c202 --- 0x4200c202: app_main at F:/esp/ble_hid_device_demo/main/ble_hidd_demo_main.c:355 3fc9d190: 0x00000000 0x3fc9d20c 0x3c093534 0x4208e948 0x00001800 0x56781234 0x00000100 0x3c094c7c --- 0x4208e948: log_level_get at F:/esp/Espressif/frameworks/esp-idf-v5.5/components/log/src/log_level/tag_log_level/tag_log_level.c:81 3fc9d1b0: 0x3c094f38 0x3c094f4c 0x3c0a72b0 0x00000026 0x5a5aa5a5 0x02505080 0x00171000 0x00000601 3fc9d1d0: 0x001e0000 0x01000000 0x00000000 0x000b0000 0x00000001 0x00640000 0x00000000 0x01010000 3fc9d1f0: 0x004b0005 0x00000000 0x01000000 0x01000001 0x01010001 0x00000000 0x00000000 0x00000100 3fc9d210: 0x3c093534 0x00000003 0x3c093000 0x4208deec 0x00000000 0x00001388 0x00000001 0x00000000 --- 0x4208deec: main_task at F:/esp/Espressif/frameworks/esp-idf-v5.5/components/freertos/app_startup.c:209 3fc9d230: 0x00000000 0x00000000 0x00000000 0x4038b784 0x00000000 0x00000000 0x00000000 0x00000000 --- 0x4038b784: vPortTaskWrapper at F:/esp/Espressif/frameworks/esp-idf-v5.5/components/freertos/FreeRTOS-Kernel/portable/riscv/port.c:258 3fc9d250: 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 3fc9d270: 0xa5a5a5a5 0xa5a5a5a5 0x00000150 0x3fc9d040 0x00000000 0x3fc95f40 0x3fc95f40 0x3fc9d27c 3fc9d290: 0x3fc95f38 0x00000018 0x00000000 0x00000000 0x3fc9d27c 0x00000000 0x00000001 0x3fc9c278 3fc9d2b0: 0x6e69616d 0x00000000 0x00000000 0x00000000 0x3fc9d270 0x00000001 0x00000000 0x00000000 3fc9d2d0: 0x00000000 0x00000000 0x3fc9aae8 0x3fc9ab50 0x3fc9abb8 0x00000000 0x00000000 0x00000001 3fc9d2f0: 0x00000000 0x00000000 0x00000000 0x420058be 0x00000000 0x00000000 0x00000000 0x00000000 --- 0x420058be: esp_cleanup_r at F:/esp/Espressif/frameworks/esp-idf-v5.5/components/newlib/src/newlib_init.c:42 3fc9d310: 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 3fc9d330: 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 3fc9d350: 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 3fc9d370: 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 3fc9d390: 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 3fc9d3b0: 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000600 3fc9d3d0: 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 3fc9d3f0: 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 3fc9d410: 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 3fc9d430: 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 3fc9d450: 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 3fc9d470: 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 3fc9d490: 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 3fc9d4b0: 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 3fc9d4d0: 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 3fc9d4f0: 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5
09-04
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

嵌云阁主

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值