How many hardware breakpoints are available on Silicon Laboratories' devices which use the Cortex-M3, like Giant Gecko?
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 ARM Cortex-M3 Processor Technical Reference Manual in the case of Giant Gecko, will present the reader with instances of the term "IMPLEMENTATION DEFINED" or "IMPLEMENTATION SPECIFIC" 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. As a case in point, the Memory Protection Unit (MPU) is an implementation-specific feature present on every EFM32 family member with the Cortex-M3 except for Tiny Gecko.
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-M3 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-M3 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 FlashPatch Control Register (FP_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 Giant Gecko, for example, here's the memory dump at 0xE0002000 showing the contents of the FlashPatch Control Register. Also notice the non-zero contents of the register at 0xE0002008, which will prove interesting later on in this article.
FP_CTRL includes five 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 FP_CTRL is ignored unless this bit is 1. Of primary interest are the fields in bits [7:4], [11:8], and [14:12], which are referred to as NUM_CODE1, NUM_LIT, and NUM_CODE2, respectively.
ARM defines two implementations of the Flash Patch and Breakpoint (FPB) Unit for the Cortex-M3 that are referred to as reduced and standard. The number of available comparators for each one is shown in the following table:
The NUM_CODE2 field is always 0 for Cortex-M3 devices. Later cores that implement the ARM v7-M architecture combine NUM_CODE1 and NUM_CODE2 such that NUM_CODE2 would have some value when there are 16 or more breakpoint comparators available. With this information in hand, it's clear from the memory dump above that Giant Gecko has a standard Cortex-M3 FPB implementation with 2 literal address and 6 breakpoint comparators.
Literal address comparators are used by the FPB to remap addresses within flash for the purpose of code patching (the "P" in FPB). The standard Cortex-M3 FPB has 2 literal address comparators, and the registers for these are always mapped after the 6 breakpoint comparators.
So, finally, what's interesting about the value at 0xE0002008? This is the location of the first hardware breakpoint comparator register (FP_COMP0), and it, too, has three control fields. Bits [31:30] are REPLACE and determine on which halfwords of the compared address the breakpoint is taken or if the address is remapped (literal comparators). Bits [28:2] comprise the COMP field and correspond to bits [28:2] of the comparison address. Like FP_CTRL, bit 0 is the ENABLE bit for the comparator.
Thus, the value 0x400014F5 in the FP_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 0x000014F4 (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, 0x000014F4 corresponds to the location of main() in the example code just downloaded by the debugger.