This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Stack Pointer coming improperly in exception handler

Other Parts Discussed in Thread: MATHLIB, SYSBIOS, TCI6636K2H

Problem Definition:

With exception enabled, we don’t see the stack pointer being properly returned from the exception handler.

The stack pointer returned from the exception handler is always 2 functions above the place where the exception has occurred.

This issue is seen with our real time setup.

Recreation of issue in EVM:

We were able to recreate this issue with EVM. The project is attached.

Explanation of the code used in the project:

There are 10 functions defined in the .c file (Example_CallTrace.cpp). The functions are named function_level1() to function_level10()

In function_level10(), there is an exception triggered forcefully(line 106).

I have printed SP in every function from 1 to 10. Always in the exception handler, we always see the SP of the function_level8() instead of function_level10().

If I add a breakpoint at *ptr = 0x10; (line 106) and continue until the end of the function (line 107) using step in debug, I get the proper stack pointer. I have added both the console prints (with free run and with adding breakpoint and stepping in)

I hope the problem is understood.

CCS details:

-    I tried the experiment with compiler 7.3.19, bois 6_33_04_39 and following components:

**** Build of configuration Debug for project CallTrace ****

"E:\\ti\\ccsv5\\utils\\bin\\gmake" -k all

'Building file: ../CallTrace.cfg'

'Invoking: XDCtools'

"C:/ti/xdctools_3_23_03_53/xs" --xdcpath="C:/ti/dsplib_c66x_3_1_0_0/packages;C:/ti/edma3_lld_02_11_05_02/packages;C:/ti/imglib_c66x_3_1_0_1/packages;C:/ti/ipc_1_24_02_27/packages;C:/ti/mathlib_c66x_3_0_1_1/packages;C:/ti/mcsdk_2_00_09_21/demos;C:/ti/pdk_C6657_1_0_0_0/packages;C:/ti/pdk_C6670_1_0_0_21/packages;C:/ti/pdk_C6678_1_0_0_21/packages;C:/ti/bios_6_33_04_39/packages;C:/ti/uia_1_01_00_04/packages;E:/ti/xdais_7_21_01_07/packages;E:/ti/xdais_7_21_01_07/examples;" xdc.tools.configuro -o configPkg -t ti.targets.elf.C66 -p ti.platforms.evm6670 -r release -c "C:/ti/ccsv5/tools/compiler/c6000_7.3.19" "../CallTrace.cfg"

making package.mak (because of package.bld) ...

generating interfaces for package configPkg (because package/package.xdc.inc is older than package.xdc) ...

configuring CallTrace.xe66 from package/cfg/CallTrace_pe66.cfg ...

generating custom ti.sysbios library makefile ...

Starting build of library sources ...

making E:/Swaroop/Code/CallTrace/ExampleProjectTICallTrace/CallTrace/src/sysbios/sysbios.lib ...

Build of libraries done.

cle66 package/cfg/CallTrace_pe66.c ...

'Finished building: ../CallTrace.cfg'

' '

'Building file: ../Example_CallTrace.cpp'

'Invoking: C6000 Compiler'

"E:/ti/ccsv5/tools/compiler/c6000_7.4.4/bin/cl6x" -mv6600 -g --include_path="C:/ti/ccsv5/tools/compiler/c6000_7.3.19/include" --display_error_number --diag_warning=225 --abi=eabi --preproc_with_compile --preproc_dependency="Example_CallTrace.pp" --cmd_file="./configPkg/compiler.opt"  "../Example_CallTrace.cpp"

 

-    I also tried with compiler 7.4.4 and bios 6_37_05_35 and the following components:

**** Build of configuration Debug for project SPErrorProj ****

"E:\\ti\\ccsv5\\utils\\bin\\gmake" -k all

'Building file: ../CallTrace.cfg'

'Invoking: XDCtools'

"C:/ti/xdctools_3_25_06_96/xs" --xdcpath="C:/ti/dsplib_c66x_3_1_0_0/packages;C:/ti/edma3_lld_02_11_05_02/packages;C:/ti/imglib_c66x_3_1_0_1/packages;C:/ti/ipc_1_24_02_27/packages;C:/ti/mathlib_c66x_3_0_1_1/packages;C:/ti/mcsdk_2_00_09_21/demos;C:/ti/pdk_C6657_1_0_0_0/packages;C:/ti/pdk_C6670_1_0_0_21/packages;C:/ti/pdk_C6678_1_0_0_21/packages;C:/ti/bios_6_37_05_35/packages;E:/ti/uia_1_03_01_08/packages;E:/ti/xdais_7_21_01_07/packages;E:/ti/xdais_7_21_01_07/examples;E:/ti/ccsv5/ccs_base;" xdc.tools.configuro -o configPkg -t ti.targets.elf.C66 -p ti.platforms.evm6670 -r release -c "E:/ti/ccsv5/tools/compiler/c6000_7.4.4" "../CallTrace.cfg"

making package.mak (because of package.bld) ...

generating interfaces for package configPkg (because package/package.xdc.inc is older than package.xdc) ...

configuring CallTrace.xe66 from package/cfg/CallTrace_pe66.cfg ...

generating custom ti.sysbios library makefile ...

Starting build of library sources ...

making E:/Swaroop/Code/CallTrace/ExampleProjectTISPError/SPErrorProj/src/sysbios.ae66 ...

gmake[1]: Entering directory `E:/Swaroop/Code/CallTrace/ExampleProjectTISPError/SPErrorProj/src/sysbios'

cle66 C:/ti/bios_6_37_05_35/packages/ti/sysbios/BIOS.c ...

asme66 C:/ti/bios_6_37_05_35/packages/ti/sysbios/family/c64p/Hwi_disp_always.s64P ...

asme66 C:/ti/bios_6_37_05_35/packages/ti/sysbios/family/c64p/Hwi_asm.s62 ...

asme66 C:/ti/bios_6_37_05_35/packages/ti/sysbios/family/c64p/Hwi_asm_switch.s62 ...

asme66 C:/ti/bios_6_37_05_35/packages/ti/sysbios/family/c64p/Clobber_asm.s62 ...

asme66 C:/ti/bios_6_37_05_35/packages/ti/sysbios/family/c64p/Exception_asm.s64P ...

asme66 C:/ti/bios_6_37_05_35/packages/ti/sysbios/family/c64p/MemoryProtect_asm.s64P ...

asme66 C:/ti/bios_6_37_05_35/packages/ti/sysbios/family/c62/TaskSupport_asm.s62 ...

asme66 C:/ti/bios_6_37_05_35/packages/ti/sysbios/timers/timer64/Timer_asm.s64P ...

asme66 C:/ti/bios_6_37_05_35/packages/ti/sysbios/timers/dmtimer/Timer_asm.s64P ...

asme66 C:/ti/bios_6_37_05_35/packages/ti/sysbios/../sk/sk_cwrap.asm ...

are66 BIOS.obj c64p_Hwi_disp_always.obj c64p_Hwi_asm.obj c64p_Hwi_asm_switch.obj c64p_Clobber_asm.obj c64p_Exception_asm.obj c64p_MemoryProtect_asm.obj c62_TaskSupport_asm.obj timer64_Timer_asm.obj dmtimer_Timer_asm.obj sk_sk_cwrap.obj ...

gmake[1]: Leaving directory `E:/Swaroop/Code/CallTrace/ExampleProjectTISPError/SPErrorProj/src/sysbios'

Build of libraries done.

cle66 package/cfg/CallTrace_pe66.c ...

'Finished building: ../CallTrace.cfg'

' '

'Building file: ../Example_CallTrace.cpp'

'Invoking: C6000 Compiler'

"E:/ti/ccsv5/tools/compiler/c6000_7.4.4/bin/cl6x" -mv6600 --abi=eabi -g --include_path="E:/ti/ccsv5/tools/compiler/c6000_7.4.4/include" --display_error_number --diag_warning=225 --diag_wrap=off --preproc_with_compile --preproc_dependency="Example_CallTrace.pp" --cmd_file="./configPkg/compiler.opt"  "../Example_CallTrace.cpp"

Console prints:

With FREE-RUN:

[C66xx_0] function_level0  : SP 0x00812818 : PC 0x00802ec8

function_level1  : SP 0x00812800 : PC 0x00802f54

function_level2  : SP 0x008127e8 : PC 0x00802f88

function_level3  : SP 0x008127d0 : PC 0x00802fc0

function_level4  : SP 0x008127b8 : PC 0x00802ff0

function_level5  : SP 0x008127a0 : PC 0x00803024

function_level6  : SP 0x00812788 : PC 0x00803054

function_level7  : SP 0x00812770 : PC 0x00803088

function_level8  : SP 0x00812758 : PC 0x008030c0

function_level9  : SP 0x00812740 : PC 0x008030f0

function_level10 : SP 0x00812718 : PC 0x0080312c

x20b04658

A16=0x8124e2 A17=0x30

A18=0x8124e0 A19=0x0

A20=0x6c A21=0x4c

A22=0x93272da9 A23=0x18002000

A24=0x0 A25=0x4

A26=0x0 A27=0x0

A28=0x80180088 A29=0x4000

A30=0x1 A31=0x58

B0=0x0 B1=0x0

B2=0x80fa69 B3=0x8030d8

B4=0x0 B5=0x10

B6=0x31 B7=0x813128

B8=0x812480 B9=0x3a

B10=0x812758 B11=0x8013

B12=0x0 B13=0xf8

B14=0x0 B15=0x812758

B16=0x30 B17=0x81270c

B18=0x80f30b B19=0x78

B20=0x69 B21=0x69

B22=0xffffffff B23=0x0

B24=0x14280800 B25=0x18000800

B26=0x84820 B27=0x40010100

B28=0xc1820841 B29=0x20000482

B30=0x70 B31=0xffffffff

NTSR=0x1000c

ITSR=0x0

IRP=0x0

SSR=0x0

AMR=0x0

RILC=0x0

ILC=0x0

Exception at 0x803112

EFR=0x40000000 NRP=0x803112

UMC Exception MPFAR=0x0 MPFSR=0x110

Supervisor Write violation, Fault ID=0x1

Inside Exception : SP 0x00812758 : PC 0x008030d8 : NRP 0x00803112

ti.sysbios.family.c64p.Exception: line 248: E_exceptionMin: pc = 0x00000000, sp = 0x00812758.

To see more exception detail, use ROV or set 'ti.sysbios.family.c64p.Exception.enablePrint = true;'

xdc.runtime.Error.raise: terminating execution

 

With adding Debug point and stepping in for lines 106 and 107:

[C66xx_0] function_level0  : SP 0x00812818 : PC 0x00802ec8

function_level1  : SP 0x00812800 : PC 0x00802f54

function_level2  : SP 0x008127e8 : PC 0x00802f88

function_level3  : SP 0x008127d0 : PC 0x00802fc0

function_level4  : SP 0x008127b8 : PC 0x00802ff0

function_level5  : SP 0x008127a0 : PC 0x00803024

function_level6  : SP 0x00812788 : PC 0x00803054

function_level7  : SP 0x00812770 : PC 0x00803088

function_level8  : SP 0x00812758 : PC 0x008030c0

function_level9  : SP 0x00812740 : PC 0x008030f0

function_level10 : SP 0x00812718 : PC 0x0080312c

x20b04658

A16=0x8124e2 A17=0x30

A18=0x8124e0 A19=0x0

A20=0x6c A21=0x4c

A22=0x93272da9 A23=0x18002000

A24=0x0 A25=0x4

A26=0x0 A27=0x0

A28=0x80180088 A29=0x4000

A30=0x1 A31=0x58

B0=0x0 B1=0x0

B2=0x80fa69 B3=0x803144

B4=0x0 B5=0x10

B6=0x31 B7=0x813128

B8=0x812480 B9=0x3a

B10=0x812758 B11=0x8013

B12=0x0 B13=0xf8

B14=0x0 B15=0x812718

B16=0x30 B17=0x81270c

B18=0x80f30b B19=0x78

B20=0x69 B21=0x69

B22=0xffffffff B23=0x0

B24=0x14280800 B25=0x18000800

B26=0x84820 B27=0x40010100

B28=0xc1820841 B29=0x20000482

B30=0x70 B31=0xffffffff

NTSR=0x1000c

ITSR=0x0

IRP=0x0

SSR=0x0

AMR=0x0

RILC=0x0

ILC=0x0

Exception at 0x80314c

EFR=0x40000000 NRP=0x80314c

UMC Exception MPFAR=0x0 MPFSR=0x110

Supervisor Write violation, Fault ID=0x1

Inside Exception : SP 0x00812718 : PC 0x00803144 : NRP 0x0080314c

ti.sysbios.family.c64p.Exception: line 248: E_exceptionMin: pc = 0x00000000, sp = 0x00812718.

To see more exception detail, use ROV or set 'ti.sysbios.family.c64p.Exception.enablePrint = true;'

xdc.runtime.Error.raise: terminating execution

  • Hi,

    Can someone please answer this question.

    Thanks,

    Hari

  • Hi Hari,

    If you look at the PC in the 2 exception dumps, it is different. In the first case (where SP is 0x00812758), the PC is 0x008030d8. Can you check if this PC corresponds to function8 ?

    Also, which board are you running on ?

    Best,
    Ashish
  • Hi,

    I am using TMDXEVM6618LXE EVM board. I had posted this on the private e2e forum, from where Cesar(from TI), redirected to post this on public e2e forum.

    If you see the prints, I have printed SP and PC in each of the function in both the cases.

    For the question:

    In the first case (where SP is 0x00812758), the PC is 0x008030d8

    function_level7  : SP 0x00812770 : PC 0x00803088

    function_level8  : SP 0x00812758 : PC 0x008030c0

    function_level9  : SP 0x00812740 : PC 0x008030f0

    function_level10 : SP 0x00812718 : PC 0x0080312c

    So it seems the PC is somewhere in funciton_level8 itself.

     

    It is very easy to run this case on EVM(using the project attached) and recreate. We are struggling with this issue in real time. Hence, please help in quick resolution of the problem.

    Also, please explain the detailed path once the exception happens until it enters the Exception_asm.s64P.

    Thanks,

    Hari

  • Hi Hari,

    Let me try to find a TMDXEVM6618LXE EVM and repro the problem. I will get back to you once I do that.

    Best,
    Ashish
  • Hi Hari,

    I was able to reproduce this behavior on a TCI6636K2H board. We believe what is happening is that it takes several cycles after "*ptr = 0x10" assignment for the exception to trigger. Due to this delay, the execution starts to return along the call chain i.e. function 10 returns to function 9 and so on. If you add enough "nop" instructions after "*ptr = 0x10", you will notice the SP will be correct. Alternatively, if you add a "_mfence()" barrier, you will notice the SP is as expected.

    I believe a delay is expected between the faulting instruction starting execution and the exception interrupt triggering (due to instr pipeline effects), but am not sure how many cycles that is. I am going to try to contact the C66 H/W team to learn more about this. I will get back to you when I hear back from them.

    Best,
    Ashish
  • Hi Ashish,

    I am sure you know about this, but just bringing it to notice that, in real time, it is not known where the exception hits. Yes, I tried adding delays and it works fine, as mentioned. But, we need a solution for this problem which works in the real time.

    Once the exception is hit at *ptr = 0x10, what is the path taken before the code reaches the exception_asm file. If you go step in the code it enters a HWI and after that there are series of execution for which the code is not available. Can you please explain that part.

    Thanks,

    Hari

  • Hi Hari,

    Can you explain your use case ? Are you wanting to return from an NMI generated by a CPU exception and therefore trying to determine the SP and PC when the exception occurred ?

    Hari Swaroop KV said:

    I am sure you know about this, but just bringing it to notice that, in real time, it is not known where the exception hits. Yes, I tried adding delays and it works fine, as mentioned. But, we need a solution for this problem which works in the real time.

    Like you said, it cannot be known where the exception actually occurred. By the time the exception is triggered, the PC will have progressed and will not point to the instruction that caused the exception. And if any subsequent instruction in the pipeline updates SP (which it does in your example) then, even the SP would have changed. So, the answer to your original question is that the change in SP is expected.

    Section 7.3 of the C66 User Guide explains the HW behavior when an exception occurs (including the delays) in great detail and should be a good read.

    Hari Swaroop KV said:

    Once the exception is hit at *ptr = 0x10, what is the path taken before the code reaches the exception_asm file. If you go step in the code it enters a HWI and after that there are series of execution for which the code is not available. Can you please explain that part.

    As you know the CPU exceptions are delivered to the CPU as NMI (Interrupt #1). We have an interrupt vector routine with the label ti_sysbios_family_c64p_Hwi_int1 for the NMI interrupt. This routine serves as a wrapper function and jumps to the Exception_dispatch() asm function. The dispatch function copies all the registers into a structure in memory and then calls a C routine that will print an exception dump (print all the regs that were copied and saved by the dispatcher). The C routine is also responsible for calling any exception hooks registered by the app.

    Best,

    Ashish

  • Our use case is to generate the call trace using the SP and PC in the exception handler context.

    For this, when there is a exception hit, we need proper SP and PC to be printed.

    Ashish:

    Like you said, it cannot be known where the exception actually occurred. By the time the exception is triggered, the PC will have progressed and will not point to the instruction that caused the exception. And if any subsequent instruction in the pipeline updates SP (which it does in your example) then, even the SP would have changed. So, the answer to your original question is that the change in SP is expected.

    So, do we conclude that SP in exception handler will not always be correct?

  • Hi Hari,

    Well, the SP is not incorrect. It is just not guaranteed to be the same as when the exception occurred.

    Best,
    Ashish
  • If the SP comes incorrect, then we cannot get the place of exception. 

    So, we need a method to get the proper value of SP at the time of exception. Exception module of TI looses significance if SP and PC doesn't come properly at the time of exception. How to debug issues if the SP is coming coming right.

    Is there any workaround for this? We need a fix/workaround for this issue.

  • Hi Hari,

    I dont see a workaround that will ensure you get the exact SP when the exception occurred.

    The exception module is still useful in that it gives you an idea where the exception occurred. The PC is within one execution packet of the exception causing instruction.

    Best,
    Ashish