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.

CCS/EK-TM4C129EXL: Hardware watchpoint not triggering (follow up)

Part Number: EK-TM4C129EXL

Tool/software: Code Composer Studio

Hello,

This is a follow up of an older thread: CCS/EK-TM4C129EXL: Hardware watchpoint not triggering

We analyzed the behavior of the hardware watchpoint with the brand new CCS 8.0 again. The bug (or uncertainty) is still there. It is one because: Btw: address 0x40064004 is not a bit-banded address. TM4C129E data sheet p.115 says: peripheral bit-band alias is from 0x4200.0000 to 0x43FF.FFFF.

Which means 0x40064004 is a standard peripheral memory access. Data sheet chapter 10.3.1.2 explains data register operation to modify multiple bits (with a bit mask). Therefore the last "4" of address 0x40064004 means 0b100 which selects the lowest GPIODATA bit. This can then be set to 1 or 0. Same applies to 0x400643FC: 0x3FC = 0b1111111100, which selects all bits from 7 downto 0 to be changeable.

So if i choose 0x40064004 as the trigger address for the hardware watchpoint as recommended in the older thread, i can (sometimes) successfully trigger a hardware watchpoint on access to bit 0 of GPIO port N.

But if i choose 0x400643FC it doesn't trigger, although the memory browser correctly shows the change of register content. Unfortunately that doesn't work as we know.

What is even more weird: If i write to two bits simultaneously (e.g. bit 0 and bit 1 to switch on two LEDs on pin 0 and 1) the watchpoint on bit 0 ceases to get triggered. So it is only possible to trigger on one single bit access at a port, not multiple bits. 

There are even more problems: sometimes when debugging is terminated and restarted, a watchpoint is shown disabled but it stays working, even after all breakpoints have been removed!

And the next time debugging is restarted the watchpoint is still active. But it can't be removed because there is none! Huh? If the watchpoint is recreated again the execution resumes but now without stopping at the active watchpoint!...

Sorry, but this makes the hardware watchpoint useless for our applications.

Perhaps anybody has new suggestions or explanations?

Regards, Greg

//*****************************************************************************
// simple example to show weird hardware watchpoint behaviour on EK-TM4C129EXL
//*****************************************************************************

#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/sysctl.h"
#include "driverlib/gpio.h"


int main(void)
{
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPION);

    // wait > 3 clocks here
    SysCtlDelay(2);

    GPIOPinTypeGPIOOutput(GPIO_PORTN_BASE, GPIO_PIN_1|GPIO_PIN_0);
    GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_1|GPIO_PIN_0, 0x00);

    while(1)
    {
        GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_0, 1); // watchpoint 0x40064004 triggers correctly
        GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_1, 2);
        GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_1, 0);
        GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_0, 0); // watchpoint 0x40064004 triggers correctly
        GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_1|GPIO_PIN_0, 3); // watchpoint 0x40064004 DOES NOT trigger
        GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_1|GPIO_PIN_0, 0); // watchpoint 0x40064004 DOES NOT trigger
    }
}

  • Greg,

    I looked at the older forum thread and the bug report and I have the following comments. 

    The GPIOPinWrite() function actively performs the following routine:

    gpio.c said:

    void GPIOPinWrite(uint32_t ui32Port, uint8_t ui8Pins, uint8_t ui8Val)
    {
    //
    // Check the arguments.
    //
    ASSERT(_GPIOBaseValid(ui32Port));

    //
    // Write the pins.
    //
    HWREG(ui32Port + (GPIO_O_DATA + (ui8Pins << 2))) = ui8Val;
    }

    Therefore, it performs a CPU write to the address calculated from the expression between parenthesis: ui32Port + (GPIO_O_DATA + (ui8Pins << 2)) .

    The file hw_gpio.h defines GPIO_0_DATA as 0x0. Therefore, for your six write operations the addresses are:

    0x40064004
    0x40064008
    0x40064008
    0x40064004
    0x4006400C
    0x4006400C

    In the light of this and looking at the explanation shown in the previous thread, I think the watchpoint is being triggered correctly - i.e., only when the CPU explicitly writes to the address specified by the watchpoint. 

    I send at the bottom of this post a short clip I did with the running operation I am doing here, so perhaps you can try to spot anything I may be doing wrong. 

    Gregor Burmberger said:

    There are even more problems: sometimes when debugging is terminated and restarted, a watchpoint is shown disabled but it stays working, even after all breakpoints have been removed!

    And the next time debugging is restarted the watchpoint is still active. But it can't be removed because there is none! Huh? If the watchpoint is recreated again the execution resumes but now without stopping at the active watchpoint!...

    IIRC a breakpoint/watchpoint in a Cortex M core is usually set on the core itself and not on the IDE, therefore I would expect this strange behaviour if the hardware was not reset or powered down between subsequent debug launches. I have found myself in this situation a few times in the past.

    Also, just check if the option below is deactivated, which can also create some confusion if you leave a lingering watchpoint/breakpoint active when closing a debug session.

    Hope this helps,

    Rafael