How many hardware breakpoints do Silicon Laboratories' Happy Gecko and Zero Gecko devices have?
ARM's Cortex M-series cores have brought about a great deal of software standardization in the microcontroller space, so it might be surprising to know that the cores themselves have a number of instantiation options that are left up to the system design team. A thorough reading of the relevant documentation, say the ARMv6-M Architecture Reference Manual in the case of the Cortex-M0+ core used on the Happy Gecko and Zero Gecko devices, will present the reader with many instances of the term "IMPLEMENTATION DEFINED" when device behavior is actually designer-specified.
Most of these instantiation options are fairly esoteric in nature and do not impact the end user's ability to use the device. "Most," however is the operative word, as there are options that specifically determine whether certain hardware resources are available to the end user. Bit-banding, for example, is not part of the standard Cortex-M0+ definition. Commercially available MCUs (including Happy Gecko and Zero Gecko) using this core do not include bit-banding, but ARM provides a bus wrapper that designers can instantiate to implement this feature on custom devices.
Designer-specified parameters also govern the number of certain resources that are available in the system. For example, the number of sources supported by the Nested Vectored Interrupt Controller is one such parameter and is obviously customized to handle the number of interrupt request lines coming from the peripherals on a given device.
Interestingly enough, the number of hardware breakpoint comparators available on a device using the Cortex-M0+ core is designer-specified. ARM has no minimum requirement because, perhaps, debug support is, in fact, entirely optional! The number of hardware breakpoints supported on commercially available MCUs with the Cortex-M0+ core varies from vendor to vendor, which begs the question if there is a way to determine how many are available on a given device.
Fortunately, as part of making debug support scalable to meet the needs of differing system requirements, ARM provides a standardized way to determine what debug resources are available. In the case of breakpoints, the number of available hardware comparators is reported in the Breakpoint Control Register (BP_CTRL) located at address 0xE0002000 in the System Control Space. These registers, however, are only accessible through the Debug Access Port (DAP) interface, so the easiest way to read them is simply to dump memory in the core address space with a debugger and examine the contents.
On Zero Gecko, here's the memory dump at 0xE0002000 showing the contents of the Breakpoint Control Register. Also notice the non-zero contents of the register at 0xE0002008, which will prove interesting later on in this article.
BP_CTRL includes three fields. Bit 0 is the ENABLE bit and functions in the expected fashion. Bit 1 is named KEY but is documented as RAZ (Reads As Zero) and SBO (Should Be One) for writes, meaning that the write to BP_CTRL is ignored unless this bit is 1. Of primary interest is the NUM_CODE field in Bits [7:4], which indicates the number of hardware breakpoint comparators present, which on Zero Gecko (and Happy Gecko) is 4.
So, finally, what's interesting about the value at 0xE0002008? This is the location of the first hardware breakpoint comparator register (BP_COMP0), and it, too, has three control fields. Bits [31:30] are BP_MATCH and determine on which halfwords of the compared address the breakpoint is taken. Bits [28:2] comprise the COMP field and correspond to bits [28:2] of the comparison address. Like BP_CTRL, bit 0 is the ENABLE bit for the comparator.
Thus, the value 0x400002D5 in the BP_COMP0 register at 0xE0002008 means that a breakpoint has been enabled (Bit 0 = 1) and will match on the upper half (Bits [31:30] = 10) of the word at address 0x000002D4 (Bits [28:2]). Simplicity Studio users know that code loaded into the device with the debugger stops at the main() function before executing in order to allow the user to set breakpoints or perform other tasks. In this case, 0x000002D4 corresponds to the location of main() in the example code just downloaded by the debugger.