C. How can I prevent this issue from affecting my application?
D. Are there plans to fix this issue?
Answers:
A.
Erratum RMU_E103 describes an issue with certain Series 0 EFM32 devices. Affected parts see a gap in the coverage of the brown-out and power-on reset sources around 1.3V . The exact gap in reset coverage will be part specific if present at all. If an affected device is operating in this problematic VDD range, the device will attempt to start up while well below the tested supply voltage for the microcontroller.
The device takes a short amount of time to start up. For a typical part at normal voltages this is 163 µS. If the startup succeeds, the device will then attempt to execute code, but may not be able to do so at low voltage. At this low voltage neither a successful startup or successful code execution is guaranteed.
Note that during fast voltage ramps, e.g. power-on and power down events, VDD will not be at a problematic voltage long enough for the device to start up. However, if VDD is held at around 1.3V for a sufficient duration, the device may enter this undefined state where code is being executed below tested voltages.
The workaround to this issue is to assert a pin reset during the low VDD event. If a pin reset is asserted, the device cannot attempt to start up. The reset pin should be driven low prior to VDD falling below the BOD reset threshold.
B.
RMU_E103 is an erratum that effects some devices from the following EFM32 Series 0 products:
EFM32 Zero Gecko
EFM32 Happy Gecko
EFM32 Wonder Gecko
EFM32 Leopard Gecko
EFM32 Tiny Gecko (Series 0 only)
EZR32 Happy Gecko
EZR32 Wonder Gecko
EZR32 Leopard Gecko
This erratum does not affect EFM32 Gecko, Giant gecko, or any EFM32 Series 1 devices.
C.
Steps can be taken to both detect if RMU_E103 is occurring on a specific device, and to prevent code from executing at low voltage.
To detect a gap in reset source coverage, Measure the current consumption of the device while gradually lowering VDD. If the device attempts to start up at low voltage, current consumption will increase. The diagram below shows an example VDD waveform that can test for code execution at low voltage and the corresponding spike in current consumption. Note that the current and voltage values are approximate and will vary across parts, applications, and environments.
Figure 1. VDD Test for RMU_E103 Current Consumption
To avoid code execution at low voltage, avoid slow VDD ramps during normal operation. If the application is likely to experience a slow VDD ramp or see low supply voltage for any significant duration of time, use an external device or user input to assert a pin reset at some VDD level > 1.96V (with sufficient time to engage the internal reset before VDD reaches 1.96V).
D.
A production screen has been implemented for EFM32 Tiny Gecko that catches devices susceptible to this condition and is implemented on material with date code 1909 and later. Silicon fixes are planned for the remaining devices.
C. How can I prevent this issue from affecting my application?
D. Are there plans to fix this issue?
Answers:
A.
Erratum RMU_E102 describes an issue with certain Series 0 EFM32 devices. Affected parts may see voltage regulator failure when subjected to the following scenario:
VDD begins to fall due to some external event
VDD and Regulator output (DECOUPLE) voltage decay to 0.8-1.2V
Power supply to VDD is restored and VDD returns to a nominal value prior to VDD and DECOUPLE reaching < 0.8V
In this type of sequence mentioned above , the voltage regulator may fail to re-initialize. If this occurs, the DECOUPLE pin will continue to decay to 0V, even after VDD has recovered. In this state, the core logic is not powered, and the device will be unable to execute code or respond to a pin reset. An affected device will successfully recover from this state if power cycled.
Additionally, if a pin reset is applied prior to the Brown out detector (BOD) asserting reset, the regulator will always re-initialize successfully. The BOD threshold varies between 1.74-1.96V, so a pin reset should be asserted before VDD drops below 1.96V. The pin-reset should be held low until VDD is >1.98V, which is the maximum power-on reset threshold.
The diagrams below demonstrate an example VDD waveform that can cause the regulator initialization to fail.
Figure 1. VDD Decay and Recovery
This figure shows the proper recovery sequence, or what will happen to a working device (not affected by RMU_E102) when VDD falls to 0.9V. Here, the regulator restarts after VDD is restored, and the DECOUPLE voltage returns to 1.8V.
Figure 2. VDD Decay and DECOUPLE failure
This figure shows the failure mode for a device affected by RMU_E102 when VDD falls to 0.9V. As you can see the regulator fails to re-initialize properly, and the DECOUPLE voltage continues to fall until reaching 0V. At this point a power-on reset must be performed to recover the device.
As mentioned above, there are two workarounds to the issue.
For a device that is already in lock-up, perform a power cycle to recover to a normal state. To do this VDD must be driven to 0V before powering back on.
For a device that may experience a drop in VDD to 0.8-1.2V, use an external device or user input to assert a pin reset at some VDD level > 1.96V (with sufficient time to engage the internal reset before VDD reaches 1.96V). Additionally, the reset should be held low until power is reconnected and VDD is greater than 1.98V.
B.
RMU_E102 is an erratum that effects some devices from the following EFM32 Series 0 products:
EFM32 Zero Gecko
EFM32 Happy Gecko
EFM32 Wonder Gecko
EFM32 Leopard Gecko
EFM32 Tiny Gecko (Series 0 only)
EZR32 Happy Gecko
EZR32 Wonder Gecko
EZR32 Leopard Gecko
This erratum does not affect EFM32 Gecko, Giant Gecko, or any EFM32 Series 1 devices.
C.
To avoid issues caused by RMU_E102, the following precautions should be taken.
Avoid and check for intermittent battery or power supply connections to VDD. The issue was originally discovered in situations where a loose battery connection during assembly caused VDD to repeatedly drop to ~.9V and then recover to a nominal value. This represents a worst-case scenario for inducing RMU_E102, as multiple VDD disconnections occurred within a very short time frame.
If your application is likely to experience frequent disconnects from the power supply, ensure that the reset pin is driven low prior to disconnecting.
D.
A production screen has been implemented for EFM32 Tiny Gecko that catches devices susceptible to this condition and is implemented on material with date code 1909 and later. Silicon fixes are planned for the remaining devices.
The first line specifies that the address of the following variable should be 0x0FE04000 + (127 << 2 ) = 0x0FE041FC. LOCKBITS_BASE is #defined in the CMSIS Cortex-M Peripheral Access Layer Header File for the device in question and is 0x0FE04000 for all current EFM32, EFR32, and EZR32 devices.
Naturally, the constant debug_lock_word sets the DLW to 0x0 (at the previously specified address), but what does the __root modifier do? As explained in the following IAR Technical Note...
__root prevents the linker from removing a variable or function if it is not referred to in the main() call-tree or in any interrupt call-tree. Short of perhaps checking the state of the debug_lock_word in firmware to enable/disable debugging features, there would usually be no reason for it to be referenced in main() or elsewhere, thus the need to prevent the linker from removing it.
Obviously, this same technique can be used for any of the other words in the lock bits page. For example, to have pin resets treated as hard instead of soft resets, it's necessary to clear bit 2 of lock bits page word 122, which is configuration word 0 (CLW0), and is done with (bit 1 of CLW0 enables the bootloader and remains set in this particular example):
Locations in user data space can be programmed with constant data in the same way. For example, a product and manufacturer name could be stored as follows:
A curious user might ask "How exactly do I know this works? The .hex file format is rather cryptic looking to the untrained eye. Is there a way to parse this .hex file output from the build process and verify the expected constants are there?"
Various binary tools can be used to dump and otherwise convert .hex files, but the output from the attached hexinfo program (attached to this article for Windows machines after compiling from the sources at https://github.com/bradgrantham/hex2bin) does the job conveniently enough:
Each contiguous region in the hex file can be associated with a section of the compiled binary data. The largest is, of course, the program code itself, while the three smaller regions correspond to the product_name, manufacturer_name, and debug_lock_word constant definitions at the addresses specified by the location #pragmas that precede them.
I've run into an interesting problem: If I attempt to read the pulse counter PCNTn_CNT register shortly after the edge which increments the counter, say in an interrupt handler triggered by the rising or falling edge of the GPIO pin used, the count value does not reflect the newly captured edge.
However, if I set a break point in my interrupt handler and step through the call to the PCNT_CounterGet() function, the value returned is correct! What's happening here?
This is a perfect example of the clock domain boundary crossing problem, which is what happens when a CPU running from one clock source reads a register clocked by another, asynchronous source. On EFM32 Series 0 devices, the CPU runs off the HFCORECLK while the pulse counter runs from either the LFACLK or the edges that appear on the PCNTn_S0 pin. These clocks are, of course, asynchronous, and the pulse counter runs at what is generally a much lower frequency than the HFCORECLK, so there is a sizable delay between when the PCNTn_CNT register gets updated after an edge and when the CPU core can actually see the new value.
Reading from and writing to asynchronous registers, i.e. those associated with the low-energy peripherals, is documented in section 5.2.4 Access to Low Energy Peripherals (Asynchronous Registers) of each device's reference manual, including use of the peripheral's FREEZE register, if present. Unfortunately, in the case of the pulse counter, the FREEZE register doesn't provide any help.
What really seems to be needed is some kind of flag bit indicating that an update to the CNT register is in progress. Of course, the logic driving this bit would have to use the same clock as the counter, creating a kind of Catch-22 situation.
Ultimately, the nature of this problem is that it takes some number of PCNTn_CLK clock ticks relative to HFCORECLK ticks to guarantee that the value read from the CNT register is up-to-date. Consequently, if there's no way to enforce this synchronization on the read side of the equation, can it be done by proxy using a write?
The answer is yes, thanks to the PCNTn_SYNCBUSY register, which indicates when writes to the TOPB, CMD, and CTRL registers are in progress. Given that SYNCBUSY effectively reflects the propagation of data from the HFCORECLK domain into the PCNTn_CLK domain, it's safe to assume that a synchronized write issued after the edge that triggers the GPIO interrupt in the customer's example above, will guarantee that the value read from PCNTn_CNT includes this edge.
Of course, to do this, it's necessary to know the correct register and the value to write — really rewrite — to it such that the pulse counter keeps running as configured. TOPB looks to be the best option because the value written to it is unlikely to change (or at least be changed infrequently) after initialization. So, given this, here's what the interrupt handler in question would now look like:
void GPIO_ODD_IRQHandler(void)
{
/*
* Rewrite TOP to reset value; this will account for the time
* needed for the read of CNT to reflect the most recent edge.
*/
PCNT_TopSet(PCNT1, _PCNT_TOP_RESETVALUE);
// Update number of pulses on LCD after each button push
SegmentLCD_Number(PCNT_CounterGet(PCNT1));
// Clear flag for PB9 interrupt
GPIO_IntClear(0x0200);
}
For convenience, TOP (via TOPB) is rewritten to its reset value. If it's not possible to know the specific value of TOP when the interrupt handler is running, simply reading TOP and rewriting that value via TOPB would also work:
/*
* Get current value of TOP and rewrite it to account for the time
* needed for the read of CNT to reflect the most recent edge.
*/
PCNT_TopSet(PCNT1, PCNT_TopGet(PCNT1));
Attached to this article is an example for the STK3800 Wonder Gecko Starter Kit (STK) — porting it to the STK3700 Giant Gecko or STK3600 Leopard Gecko boards would be trivial — that illustrates the use of SYNCBUSY (via the emlib PCNT_TopSet() function) to provide the synchronization needed to read CNT and have it reflect the most recent edge captured.
When the PCNT_TopSet() call is commented out of the interrupt handler, the first push of button 0 on the STK, while engaging the GPIO_ODD_IRQHandler(), will not be reflected in the count displayed on the LCD. However, setting a breakpoint in and then single-stepping through the interrupt handler allows enough LFACLK edges to propagate through the pulse counter so that the most recent edge increments the CNT register in time for the display to be updated.
To import the demo project Simplicity Studio...
In the IDE, go to the File -> Import...
Click the "More Import Options..." link at the bottom of the window
Expand the General folder and select "Existing Projects into Workspace"
Click the radio button next to "Select archive file:"
Click the Browse... button next to the active file selection field and choose the STK3800_pcnt_count.zip file with the project to import.
The Projects: dialog box, should have the selected project with a check mark next to it.
I ran into a discrepancy trying to get the pulse counter (PCNT2, specifically) up and running on an EFM32 Wonder Gecko device and just wanted to confirm that what I am seeing is correct. The reference manual section with the register description (section 24.5) shows the TOP and CNT fields as 16 bits. When I try to set the TOP register (through the TOPB register, e.g. PCNT2->TOPB = 0x1FF) only the lower byte is set. AN0024 says the pulse counter incorporates an 8-bit counter which is consistent with what I saw.
Can you please confirm that the register description in the reference manual is incorrect?
Actually, the Reference Manual description...
...is correct! What matters is which pulse counter you want to use. On any EFM32 device with multiple instances of a peripheral (the USART is another such example), it's critical to refer to the datasheet to see how that peripheral has been configured on the device in question.
In the case of Wonder Gecko, as the datasheet shows and to appropriate a line from Goerge Orwell's Animal Farm, "All pulse counters are equal, but some pulse counters are more equal than others."
So, in this case, the customer absolutely did observe the correct behavior because PCNT2 (and, likewise, PCNT1) are 8-bit instantiations of the peripheral. If, instead, the customer had tried PCNT0, it would've behaved as he initially expected when attempting to write a 16-bit value to the TOPB register.
Note also that emlib is aware of the width associated with each pulse counter instantiation. Attempts to write 16-bit values into the CNT or TOPB registers of PCNT1 or PCNT2 using the relevant emlib functions will generate an assertion upon execution when code is built using the debug configuration in Simplicity Studio. In this particular case, the customer wrote directly to the TOPB register, thus bypassing the error checking emlib would otherwise provide.
By convention, on all EFM32 Series 0 devices — except for the original Gecko, which has only a single 8-bit pulse counter — PCNT0 is 16 bits and PCNT1 and PCNT2, if present, are 8 bits.
A customer asked this question recently and was rightfully concerned because ARM's own documentation indicates that VTOR is optional in more thanoneplace. In particular, users will encounter this early on in the feature summary in the Cortex-M0+ Devices Generic User Guide:
Vector table relocation would seem to be a pretty important feature for a modern microcontroller core. This being the case, why is the VTOR optional on the Cortex-M0+? After all, the VTOR is present on the Cortex-M3 and Cortex-M4 cores used on all other EFM32 and EFR32 devices.
Understanding this requires a bit of a history lesson. When ARM defined the Cortex-M3, it was the first implementation of the ARMv7-M Instruction Set Architecture (ISA), its Thumb-2 opcodes, and the Nested Vectored Interrupt Controller. While the Cortex-M3 was a low-end core compared to contemporaneous ARM cores like the ARM9/10/11 and Cortex-A8, it was still appreciably bigger than existing 8- and 16-bit microcontroller cores.
To push further into the cost-sensitive microcontroller space, ARM introduced the Cortex-M0. This core, which, by naming convention, might appear to be just a stripped down Cortex-M3, actually has other architecturally significant deviations, the most obvious of which is its only partial implementations of the Thumb-1 and Thumb-2 instruction sets. Cortex-M0, in fact, implements what is called the ARMv6-M ISA and not the same v7-M variant as found on the Cortex-M3. Naturally, then, it should be no surprise as part of its cost reduction efforts, ARM found other things to remove from the M3 along the way to the M0, and one of these was vector table relocation, a rather exotic feature on 8- and 16-bit processor cores.
After being in the market for a few years, ARM took the M0, made a number of optimizations (e.g. reducing the pipeline from 3 to 2 stages), allowed several of the features on the M3 to be instantiated as options, and released the Cortex-M0+. The VTOR was one of those new, optional features, which gets back to the original question, "Do EFM32 devices with the Cortex-M0+ implement the Vector Table Offset Register?"
Simply put, the answer is "Yes" for all EFM32 devices based on the M0+ core: Zero Gecko, Happy Gecko, and the new Series 1 Tiny Gecko. This can be verified by checking the device-specific CMSIS header file. Each EFM32 derivative family has a directory of all relevant device header files in .\platform\Device\SiliconLabs under the specific version of the Gecko SDK Suite. Thus for Zero Gecko, the directory would be .\platform\Device\SiliconLabs\EFM32ZG\Include, and each header file therein, e.g. efm32zg108f4.h, contains the line...
#define __VTOR_PRESENT 1 /**< Presence of VTOR register in SCB */
The ADC circuit is a 300-800 ohm resistor in series with a 2 pF capacitor, plus ESD protection diodes. There is no loading, and the maximum leakage on the input pin is 50 nA. This applies to series 0 EFM32 parts: Gecko, Giant Gecko, Tiny Gecko, Leopard Gecko, Wonder Gecko, Zero Gecko, and Happy Gecko. The equivalent diagrams in single-ended and differential mode are shown below:
32-bit Knowledge Base
RMU_E103 POR/BOD Reset Issue
Questions:
A. What is Errata RMU_E103
B. What devices are affected?
C. How can I prevent this issue from affecting my application?
D. Are there plans to fix this issue?
Answers:
A.
Erratum RMU_E103 describes an issue with certain Series 0 EFM32 devices. Affected parts see a gap in the coverage of the brown-out and power-on reset sources around 1.3V . The exact gap in reset coverage will be part specific if present at all. If an affected device is operating in this problematic VDD range, the device will attempt to start up while well below the tested supply voltage for the microcontroller.
The device takes a short amount of time to start up. For a typical part at normal voltages this is 163 µS. If the startup succeeds, the device will then attempt to execute code, but may not be able to do so at low voltage. At this low voltage neither a successful startup or successful code execution is guaranteed.
Note that during fast voltage ramps, e.g. power-on and power down events, VDD will not be at a problematic voltage long enough for the device to start up. However, if VDD is held at around 1.3V for a sufficient duration, the device may enter this undefined state where code is being executed below tested voltages.
The workaround to this issue is to assert a pin reset during the low VDD event. If a pin reset is asserted, the device cannot attempt to start up. The reset pin should be driven low prior to VDD falling below the BOD reset threshold.
B.
RMU_E103 is an erratum that effects some devices from the following EFM32 Series 0 products:
This erratum does not affect EFM32 Gecko, Giant gecko, or any EFM32 Series 1 devices.
C.
Steps can be taken to both detect if RMU_E103 is occurring on a specific device, and to prevent code from executing at low voltage.
Figure 1. VDD Test for RMU_E103 Current Consumption
RMU_E102 POR/BOD Reset Issue
Questions:
A. What is Errata RMU_E102?
B. What devices are affected?
C. How can I prevent this issue from affecting my application?
D. Are there plans to fix this issue?
Answers:
A.
Erratum RMU_E102 describes an issue with certain Series 0 EFM32 devices. Affected parts may see voltage regulator failure when subjected to the following scenario:
In this type of sequence mentioned above , the voltage regulator may fail to re-initialize. If this occurs, the DECOUPLE pin will continue to decay to 0V, even after VDD has recovered. In this state, the core logic is not powered, and the device will be unable to execute code or respond to a pin reset. An affected device will successfully recover from this state if power cycled.
Additionally, if a pin reset is applied prior to the Brown out detector (BOD) asserting reset, the regulator will always re-initialize successfully. The BOD threshold varies between 1.74-1.96V, so a pin reset should be asserted before VDD drops below 1.96V. The pin-reset should be held low until VDD is >1.98V, which is the maximum power-on reset threshold.
The diagrams below demonstrate an example VDD waveform that can cause the regulator initialization to fail.
Figure 1. VDD Decay and Recovery
This figure shows the proper recovery sequence, or what will happen to a working device (not affected by RMU_E102) when VDD falls to 0.9V. Here, the regulator restarts after VDD is restored, and the DECOUPLE voltage returns to 1.8V.
Figure 2. VDD Decay and DECOUPLE failure
This figure shows the failure mode for a device affected by RMU_E102 when VDD falls to 0.9V. As you can see the regulator fails to re-initialize properly, and the DECOUPLE voltage continues to fall until reaching 0V. At this point a power-on reset must be performed to recover the device.
As mentioned above, there are two workarounds to the issue.
B.
RMU_E102 is an erratum that effects some devices from the following EFM32 Series 0 products:
This erratum does not affect EFM32 Gecko, Giant Gecko, or any EFM32 Series 1 devices.
C.
To avoid issues caused by RMU_E102, the following precautions should be taken.
How do I set the Debug Lock Word (DLW) or other locations in the lock bits or user data pages in my C program using IAR?
IAR provides a very convenient #pragma mechanism for locating variables at specific memory addresses:
This #pragma is then followed by the specific variable declaration. Programming the DLW to lock debug access is thus as simple as:
The first line specifies that the address of the following variable should be 0x0FE04000 + (127 << 2 ) = 0x0FE041FC. LOCKBITS_BASE is #defined in the CMSIS Cortex-M Peripheral Access Layer Header File for the device in question and is 0x0FE04000 for all current EFM32, EFR32, and EZR32 devices.
Naturally, the constant debug_lock_word sets the DLW to 0x0 (at the previously specified address), but what does the __root modifier do? As explained in the following IAR Technical Note...
https://www.iar.com/support/tech-notes/linker/the-linker-removing-functions-and-variables-or-external-not-found/
__root prevents the linker from removing a variable or function if it is not referred to in the main() call-tree or in any interrupt call-tree. Short of perhaps checking the state of the debug_lock_word in firmware to enable/disable debugging features, there would usually be no reason for it to be referenced in main() or elsewhere, thus the need to prevent the linker from removing it.
Obviously, this same technique can be used for any of the other words in the lock bits page. For example, to have pin resets treated as hard instead of soft resets, it's necessary to clear bit 2 of lock bits page word 122, which is configuration word 0 (CLW0), and is done with (bit 1 of CLW0 enables the bootloader and remains set in this particular example):
Locations in user data space can be programmed with constant data in the same way. For example, a product and manufacturer name could be stored as follows:
A curious user might ask "How exactly do I know this works? The .hex file format is rather cryptic looking to the untrained eye. Is there a way to parse this .hex file output from the build process and verify the expected constants are there?"
Various binary tools can be used to dump and otherwise convert .hex files, but the output from the attached hexinfo program (attached to this article for Windows machines after compiling from the sources at https://github.com/bradgrantham/hex2bin) does the job conveniently enough:
Each contiguous region in the hex file can be associated with a section of the compiled binary data. The largest is, of course, the program code itself, while the three smaller regions correspond to the product_name, manufacturer_name, and debug_lock_word constant definitions at the addresses specified by the location #pragmas that precede them.
How to Read the Pulse Counter (PCNT) in an Interrupt Handler on EFM32 Series 0 Devices
I've run into an interesting problem: If I attempt to read the pulse counter PCNTn_CNT register shortly after the edge which increments the counter, say in an interrupt handler triggered by the rising or falling edge of the GPIO pin used, the count value does not reflect the newly captured edge.
However, if I set a break point in my interrupt handler and step through the call to the PCNT_CounterGet() function, the value returned is correct! What's happening here?
This is a perfect example of the clock domain boundary crossing problem, which is what happens when a CPU running from one clock source reads a register clocked by another, asynchronous source. On EFM32 Series 0 devices, the CPU runs off the HFCORECLK while the pulse counter runs from either the LFACLK or the edges that appear on the PCNTn_S0 pin. These clocks are, of course, asynchronous, and the pulse counter runs at what is generally a much lower frequency than the HFCORECLK, so there is a sizable delay between when the PCNTn_CNT register gets updated after an edge and when the CPU core can actually see the new value.
Reading from and writing to asynchronous registers, i.e. those associated with the low-energy peripherals, is documented in section 5.2.4 Access to Low Energy Peripherals (Asynchronous Registers) of each device's reference manual, including use of the peripheral's FREEZE register, if present. Unfortunately, in the case of the pulse counter, the FREEZE register doesn't provide any help.
What really seems to be needed is some kind of flag bit indicating that an update to the CNT register is in progress. Of course, the logic driving this bit would have to use the same clock as the counter, creating a kind of Catch-22 situation.
Ultimately, the nature of this problem is that it takes some number of PCNTn_CLK clock ticks relative to HFCORECLK ticks to guarantee that the value read from the CNT register is up-to-date. Consequently, if there's no way to enforce this synchronization on the read side of the equation, can it be done by proxy using a write?
The answer is yes, thanks to the PCNTn_SYNCBUSY register, which indicates when writes to the TOPB, CMD, and CTRL registers are in progress. Given that SYNCBUSY effectively reflects the propagation of data from the HFCORECLK domain into the PCNTn_CLK domain, it's safe to assume that a synchronized write issued after the edge that triggers the GPIO interrupt in the customer's example above, will guarantee that the value read from PCNTn_CNT includes this edge.
Of course, to do this, it's necessary to know the correct register and the value to write — really rewrite — to it such that the pulse counter keeps running as configured. TOPB looks to be the best option because the value written to it is unlikely to change (or at least be changed infrequently) after initialization. So, given this, here's what the interrupt handler in question would now look like:
For convenience, TOP (via TOPB) is rewritten to its reset value. If it's not possible to know the specific value of TOP when the interrupt handler is running, simply reading TOP and rewriting that value via TOPB would also work:
Attached to this article is an example for the STK3800 Wonder Gecko Starter Kit (STK) — porting it to the STK3700 Giant Gecko or STK3600 Leopard Gecko boards would be trivial — that illustrates the use of SYNCBUSY (via the emlib PCNT_TopSet() function) to provide the synchronization needed to read CNT and have it reflect the most recent edge captured.
When the PCNT_TopSet() call is commented out of the interrupt handler, the first push of button 0 on the STK, while engaging the GPIO_ODD_IRQHandler(), will not be reflected in the count displayed on the LCD. However, setting a breakpoint in and then single-stepping through the interrupt handler allows enough LFACLK edges to propagate through the pulse counter so that the most recent edge increments the CNT register in time for the display to be updated.
To import the demo project Simplicity Studio...
How many bits wide is the Pulse Counter on EFM32 Series 0 Devices?
I ran into a discrepancy trying to get the pulse counter (PCNT2, specifically) up and running on an EFM32 Wonder Gecko device and just wanted to confirm that what I am seeing is correct. The reference manual section with the register description (section 24.5) shows the TOP and CNT fields as 16 bits. When I try to set the TOP register (through the TOPB register, e.g. PCNT2->TOPB = 0x1FF) only the lower byte is set. AN0024 says the pulse counter incorporates an 8-bit counter which is consistent with what I saw.
Can you please confirm that the register description in the reference manual is incorrect?
Actually, the Reference Manual description...
...is correct! What matters is which pulse counter you want to use. On any EFM32 device with multiple instances of a peripheral (the USART is another such example), it's critical to refer to the datasheet to see how that peripheral has been configured on the device in question.
In the case of Wonder Gecko, as the datasheet shows and to appropriate a line from Goerge Orwell's Animal Farm, "All pulse counters are equal, but some pulse counters are more equal than others."
So, in this case, the customer absolutely did observe the correct behavior because PCNT2 (and, likewise, PCNT1) are 8-bit instantiations of the peripheral. If, instead, the customer had tried PCNT0, it would've behaved as he initially expected when attempting to write a 16-bit value to the TOPB register.
Note also that emlib is aware of the width associated with each pulse counter instantiation. Attempts to write 16-bit values into the CNT or TOPB registers of PCNT1 or PCNT2 using the relevant emlib functions will generate an assertion upon execution when code is built using the debug configuration in Simplicity Studio. In this particular case, the customer wrote directly to the TOPB register, thus bypassing the error checking emlib would otherwise provide.
By convention, on all EFM32 Series 0 devices — except for the original Gecko, which has only a single 8-bit pulse counter — PCNT0 is 16 bits and PCNT1 and PCNT2, if present, are 8 bits.
Do EFM32 Devices with the Cortex-M0+ Core Implement the Vector Table Offset Register (VTOR)?
A customer asked this question recently and was rightfully concerned because ARM's own documentation indicates that VTOR is optional in more than one place. In particular, users will encounter this early on in the feature summary in the Cortex-M0+ Devices Generic User Guide:
Vector table relocation would seem to be a pretty important feature for a modern microcontroller core. This being the case, why is the VTOR optional on the Cortex-M0+? After all, the VTOR is present on the Cortex-M3 and Cortex-M4 cores used on all other EFM32 and EFR32 devices.
Understanding this requires a bit of a history lesson. When ARM defined the Cortex-M3, it was the first implementation of the ARMv7-M Instruction Set Architecture (ISA), its Thumb-2 opcodes, and the Nested Vectored Interrupt Controller. While the Cortex-M3 was a low-end core compared to contemporaneous ARM cores like the ARM9/10/11 and Cortex-A8, it was still appreciably bigger than existing 8- and 16-bit microcontroller cores.
To push further into the cost-sensitive microcontroller space, ARM introduced the Cortex-M0. This core, which, by naming convention, might appear to be just a stripped down Cortex-M3, actually has other architecturally significant deviations, the most obvious of which is its only partial implementations of the Thumb-1 and Thumb-2 instruction sets. Cortex-M0, in fact, implements what is called the ARMv6-M ISA and not the same v7-M variant as found on the Cortex-M3. Naturally, then, it should be no surprise as part of its cost reduction efforts, ARM found other things to remove from the M3 along the way to the M0, and one of these was vector table relocation, a rather exotic feature on 8- and 16-bit processor cores.
After being in the market for a few years, ARM took the M0, made a number of optimizations (e.g. reducing the pipeline from 3 to 2 stages), allowed several of the features on the M3 to be instantiated as options, and released the Cortex-M0+. The VTOR was one of those new, optional features, which gets back to the original question, "Do EFM32 devices with the Cortex-M0+ implement the Vector Table Offset Register?"
Simply put, the answer is "Yes" for all EFM32 devices based on the M0+ core: Zero Gecko, Happy Gecko, and the new Series 1 Tiny Gecko. This can be verified by checking the device-specific CMSIS header file. Each EFM32 derivative family has a directory of all relevant device header files in .\platform\Device\SiliconLabs under the specific version of the Gecko SDK Suite. Thus for Zero Gecko, the directory would be .\platform\Device\SiliconLabs\EFM32ZG\Include, and each header file therein, e.g. efm32zg108f4.h, contains the line...
...indicating the presence of VTOR in the core.
Series 0 ADC Input Impedance
The ADC circuit is a 300-800 ohm resistor in series with a 2 pF capacitor, plus ESD protection diodes. There is no loading, and the maximum leakage on the input pin is 50 nA. This applies to series 0 EFM32 parts: Gecko, Giant Gecko, Tiny Gecko, Leopard Gecko, Wonder Gecko, Zero Gecko, and Happy Gecko. The equivalent diagrams in single-ended and differential mode are shown below: