This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

CoreDebug->DHCSR

Hi there,

We are using cortex M0 uC. We need to recognize at our code whether or not the debugger is attached.
We have found after a lot of search and effort that we cannot use CoreDebug->DHCSR with cortex M0.

We have found a different approach using the HardFault exception and software breakpoint
that indirect recognize if the debugger is attached.

In this approach using assembly if a hardware exception occurs due to a breakpoint
then no debugger is attach and the HardFault exception return to the program
skipping the breakpoint instruction.

Below is the assembly code we have found and slightly changed:

__asm("MOVS R0, #4");
__asm("MOV R1, __return_address()");
__asm("TST R0, R1");
__asm("BEQ _MSP");
__asm("MRS R0, PSP");
__asm("B _checkFaultInstruction");
__asm("_MSP: ");
__asm("MRS R0, MSP");
__asm("_checkFaultInstruction: ");
__asm("LDR R1, [R0,#24]");
__asm("LDRH R2, [R1]");
__asm("LDR R3,=0xBEAB");
__asm("CMP R2, R3");
__asm("BNE HardFault_HandlerC ");
__asm("ADDS R1, #2");
__asm("STR R1, [R0,#24]");
__asm("BX __return_address()");

The compiler is throwing the follows errors:

1) __asm("LDR R3,=0xBEAB"); -> error #29: expected an expression
We have replaced this instruction with:
__asm("MOV R3, 0xBEAB");
Does this instruction has the same effect?

2) __asm("BX __return_address()"); -> error #1084: This instruction not permitted in inline assembler.
How can we replace this unsupported instruction?

3) __asm("BNE HardFault_HandlerC "); -> error #114:label "HardFault_HandlerC" was reference but not defined
HardFault_HandlerC is a function name
4) __asm("BX __return_address()"); -> error #114:label "..." was reference but not defined

What is wrong with 3 and 4?

Thanks in advance.

Parents
  • #1:

    No, Because LDR R3, =0xBEAB

    or what ever is typed, tells the processor to access the memory location defined
    and get the data stored at the memory location and put it into register R3.

    the other thing you wrote places the immediate value typed in into R3 as typed in.
    # is for immediate value.

    There is more code you need to add if you are ever going to get that code to work.

    including some hard fault function that is missing in your project.

Reply
  • #1:

    No, Because LDR R3, =0xBEAB

    or what ever is typed, tells the processor to access the memory location defined
    and get the data stored at the memory location and put it into register R3.

    the other thing you wrote places the immediate value typed in into R3 as typed in.
    # is for immediate value.

    There is more code you need to add if you are ever going to get that code to work.

    including some hard fault function that is missing in your project.

Children
  • sorry, I noticed that you did not use # before.. Now I am not sure about my answer to part 1.

  • There is a document that I have used before as a example to add a assembler function:

    DUI0203J_rvct_developer_guide.pdf

    It is old but it did work for me to make a simple assembly function and call it from a C program.

    infocenter.arm.com/.../DUI0203J_rvct_developer_guide.pdf

    you can look at page 72 for an example.

  • I went and looked in a assembly book that I have. They give an example

    LDR R5, =0x1FF400 ; say this is ok for assembler

    The book refers to is as a pseudo operand.

    What the assembler is to create is a instruction that will look like

    LDR R5, [PC, #18] ; = OK for the assembler.

    In the location, that is indirectly addressed by the processor at PC + #18 (the value 18 may be different).

    Will be a 32 bit value stored 0x001FF400. and the register R5 will get the value from this memory location. when the instruction has been executed. The data stored at the address
    [PC, #18] is referred to as literal pool or a memory zone where the compiler can store data
    close to the code. The data must be somewhat near the code. The largest jump that can be made
    appears to be 4096. for this reason this is how the compiler can keep data close to to the data.

    A move instruction can only store apparently up to 16 bits, and 8 bits. the LDR looks like it
    can store all 32 bits because of the way it places the data into memory before fetching the data.

    -------------------------------------------------------------------------------

    If all you want to do is load 16 bits then the following move instruction will work:

    MOV.W Ri, #ImmNum

    and for 8 bits

    MOV Ri, #ImmNum

    Ri is one of the registers.

  • It uses an immediate form where it fits the 8-bit+shift form, and where it doesn't it loads the constant from a literal pool it creates. This usually resides after the subroutine return code, or after a unconditional branch.

    The bigger question is why?

    If you're just trying it for the purposes of your own testing, dig into the DWT/ITM units, or DBGMCU type stuff, it should be easy enough to find something to key off, without using assembler or handlers.

    If it's for software protection purposes, consider most hackers can actually code in assembler fluently, and read code without the source. It helps to have a skill level above that of your perceived threat.

  • According to the following link our replacement to the first error is ok.
    infocenter.arm.com/.../index.jsp

    any ideas for the rest ones?