How to access the memory mapped debug registers?

Now that the funny PABT-behaviour is found to be (probably) caused ny debug state, I'd like to exit debug state before return from PABT exception. The ARM v7-A/R ARM says that I should write RRQ to DBGDRCR, but it seems that in Cortex-A7 it's not accessible via CP14.

It should be accessible via memory-mapped registers, and the manual gives the offset, but offset from what?

I understood that the register offset is the register number multiplied by four, so for DBGDRCR the offset would be 36*4 = 144 (0x90).

In the TRM it says:

Table 10-26 Address mapping for debug trace components

Address range Componenta

0x00000 - 0x00FFF ROM table

0x01000 - 0x0FFFF Reserved

0x10000 - 0x10FFF CPU 0 Debug

0x11000 - 0x11FFF CPU 0 PMU

0x12000 - 0x12FFF CPU 1 Debug

0x13000 - 0x13FFF CPU 1 PMU

0x14000 - 0x14FFF CPU 2 Debug

0x15000 - 0x15FFF CPU 2 PMU

0x16000 - 0x16FFF CPU 3 debug

Are these too offsets from somewhere, or absolute addresses?

Do I write to DBGDRCR by just writing the value into address 0x100090 (core 0, assuming not locked)?

Or do I need to calculate the register address from the contents of DBGDRAR?

And what's the ROM table?

Parents
  • Yeah. The PABT-problem is solved.

    The debug state was not entered at all.

    I realized that everything worked as long as I used the 'raw write', but as soon as I called the interrupt driven serial I/O, bad things happened.

    And I found the cause: when the string has been written into the serial buffer, the tx interrupts are enabled and characters are read from the buffer and written into the tx FIFO (if it wasn't full) to put the ball rolling. It was done in serial_start_tx().

    void serial_start_tx()
    {
        uint32_t cpsr_store;
    
        // no messing with tx interrupt
        cpsr_store = disable_save_ints();
        // re-enable tx interrupts
        *((volatile uint32_t *)UART0_IMSC) |= (1<<5);
    
        (void) serial_tx();
    
        // Clear transmit interrupt - probably not needed
        //*((volatile uint32_t *)UART0_ICR) = (1<<5);
    
        restore_ints(cpsr_store);
    }
    

    To not mess up with the interrupts (simultaneous reading from the tx buffer by both serial_start_tx and tx interrupt) the IRQs were disabled before starting the transmission and restored after that, but there was a small bug in the restoring:

    static inline uint32_t disable_save_ints()
    {
        uint32_t status;
        asm volatile (
                "mrs %[var_reg], cpsr\n\t"
                "dsb\n\t"
                "cpsid aif\n\t"
                :[var_reg] "=r" (status)::
        );
        return status;
    }
    
    static inline void restore_ints(uint32_t status)
    {
        asm volatile (
                "msr cpsr_fsxc, %[var_reg]\n\t"
                :[var_reg] "=r" (status)::
        );
    }
    

    In the definition I promised that the restote_ints() doesn't return anything...

    This solved the problem:

    static inline void restore_ints(uint32_t status)
    {
        asm volatile (
                "msr cpsr_fsxc, %[var_reg]\n\t"
                ::[var_reg] "r" (status):
        );
    }
    

    The good news is that while debugging the problem, I learned A LOT about the debug HW!

Reply
  • Yeah. The PABT-problem is solved.

    The debug state was not entered at all.

    I realized that everything worked as long as I used the 'raw write', but as soon as I called the interrupt driven serial I/O, bad things happened.

    And I found the cause: when the string has been written into the serial buffer, the tx interrupts are enabled and characters are read from the buffer and written into the tx FIFO (if it wasn't full) to put the ball rolling. It was done in serial_start_tx().

    void serial_start_tx()
    {
        uint32_t cpsr_store;
    
        // no messing with tx interrupt
        cpsr_store = disable_save_ints();
        // re-enable tx interrupts
        *((volatile uint32_t *)UART0_IMSC) |= (1<<5);
    
        (void) serial_tx();
    
        // Clear transmit interrupt - probably not needed
        //*((volatile uint32_t *)UART0_ICR) = (1<<5);
    
        restore_ints(cpsr_store);
    }
    

    To not mess up with the interrupts (simultaneous reading from the tx buffer by both serial_start_tx and tx interrupt) the IRQs were disabled before starting the transmission and restored after that, but there was a small bug in the restoring:

    static inline uint32_t disable_save_ints()
    {
        uint32_t status;
        asm volatile (
                "mrs %[var_reg], cpsr\n\t"
                "dsb\n\t"
                "cpsid aif\n\t"
                :[var_reg] "=r" (status)::
        );
        return status;
    }
    
    static inline void restore_ints(uint32_t status)
    {
        asm volatile (
                "msr cpsr_fsxc, %[var_reg]\n\t"
                :[var_reg] "=r" (status)::
        );
    }
    

    In the definition I promised that the restote_ints() doesn't return anything...

    This solved the problem:

    static inline void restore_ints(uint32_t status)
    {
        asm volatile (
                "msr cpsr_fsxc, %[var_reg]\n\t"
                ::[var_reg] "r" (status):
        );
    }
    

    The good news is that while debugging the problem, I learned A LOT about the debug HW!

Children