Ron showed us how to program the USART of a STM32F030x. We’re using this micro controller in our project. It is proving to be a powerful learning experience to compare the STM32F030x to the nRF51822. They both use the Arm cortex-mo but the peripherals are very different. The obvious difference being the nRF51822 does a terrific job servicing BLE. Even on what I think of as “core” features like GPIO are implemented differently. In addition, the documentation approach is different. Yet the lessons learned are directly transferable.
The goal of this post is to turn on and off the LBL LED using a get/set property editor within Eclipse.
Thanks To Those That Went Before
- Thanks to Ron Sousa for his terrific instruction within the Embedded Systems section of Contextual Electronics. Ron has “been there, done that” providing insight into coding and what to think about when programming Embedded Systems. Ron has been extremely supportive and responsive. THANK YOU.
- I am continually grateful to Chris Gammell for founding and running Contextual Electronics as well as being an exceptional mentor. As Chris likes to say, signing up for Contextual Electronics signed me up to be an apprentice of Chris’s. It still amazes me to have gone from never seeing a solder gun or hearing about Ohm’s law to building PCBs that do stuff I want to use!
- The Nordic support team is AWESOME. There hasn’t been a challenge they haven’t willingly helped me with and provided excellent guidance in a very polite manner. For this post I am especially thankful to Vidar Berg and Aryan.
The LED_TEST Eclipse (managed make) project that I used is available in this GitHub repository.
The SVD File
Get/Set property viewers for Arm cortex-m micro controllers read a CMSIS-SVD file. This is an XML formatted file that as Arm notes in their introduction to SVD: The CMSIS System View Description format(CMSIS-SVD) formalizes the description of the system contained in ARM Cortex-M processor-based microcontrollers, in particular, the memory mapped registers of peripherals. The detail contained in system view descriptions is comparable to the data in device reference manuals. The information ranges from high level functional descriptions of a peripheral all the way down to the definition and purpose of an individual bit field in a memory mapped register.
An SVD viewer will be a tremendous help in learning how to program the nRF51822.
I have come across two SVD viewers:
- The Perspective Viewer
EmbSysRegView seems to be the popular way to get/set properties within Eclipse. It is what is shown in the above image. EmbSysRegView is an Eclipse plug-in. From the EmbSysRegView web site: EMBedded SYStems REGister VIEW is an Eclipse Plugin which is designed for monitoring and modifying memory values of embedded devices. Therefore it offers a structured display of the special functions registers (SFR).
EmbSysRegView Does Not Play Nice the nRF51822
Getting/setting register bits worked well for Ron when he used EmbSysRegView to view the STM32F030x SVD file.
When using EmbSysRegView with the nRF51822, register values were read-only. I could monitor register changes as I twiddled bits, but the goal of using EmbSysRegView to turn the LBL’s LED on/off is not possible.
I asked why I couldn’t set registry properties with EmbSysRegView on the Nordic DevZone. The reason is most likely what Aryan pointed out: Embsys also uses SVD file that comes with SDK and it looks like there is some format difference…(this could be a problem with the format of the SVD file or an interpretation problems with the EmbSysRegView). My guess it is a problem with how EmbSysRegView is interpreting the nRF51822’s SVD file because I was able to set register properties using the Peripherals View.
The Peripherals View
Luckily, Vidar Berg pointed out The Peripherals View is another Eclipse plug-in that provides a property get/set UI to an SVD file.
Getting to the Peripherals View requires specifying the device within the C/C++ build’s settings:
The Peripherals view relies on Packs to distribute device information (in the form of CMSIS-SVD files). Packs are installed into the Eclipse IDE using the Eclipse Packs Manager plug-in. Once the Packs Manager is installed, I updated the software, and installed v8.0.3 of the nRF_DeviceFamilyPack for the nRF51 Series.
If the pack is not in the Packs list, from Vidar Berg: The packs are kept up to date at http://developer.nordicsemi.com/ which is where the pack system will look for updates using these URLs at http://www.keil.com/pack/index.idx. Although I do not expect SVD file to be updated unless new peripherals were to be added in HW. Just checked the SVD from SDK 5.2.0 and it is still the same as the one in SDK 9.0.0. The SVD file is working with Keil, IAR and the peripheral viewever in Eclipse, so it appears to only be a problem between our .xml file and embsys.
The one I am using is located here.
Blink The LED
Now it’s time for fun. Instead of just the data sheets/documentation for the nRF51822, I can poke around with the registers. This will give me a firmer grasp on how to program GPIO pins.
The LED_TEST Eclipse project includes two very simple functions, led_Init(LED_pin); and led_Toggle(LED_pin);. Here’s the call graph for main.c that Doxygen created:
led_Init() calls the nRF51 SDK’s helper function nrf_gpio_cfg_output(). led_Toggle() calls nrf_gpio_pin_toggle().
Configure the GPIO Pin
The LED is attached to pin 13. The nrf_gpio_cfg_ouput() helper function takes out some of the guess work around configuring a GPIO pin for output. It sets bits in the NRF_GPIO->PIN_CNF register:
What I like about this view is it gives me a more “hands on” approach to configuring a GPIO pin. I see from the code the nRF51 SDK has defined a gob of macros to aid in the readability. The macros are in the nRF51_bitfields.h file that comes with the nRF51 SDK. Stuff like GPIO_PIN_CNF_DIR_Output and it’s closely related GPIO_PIN_CNF_DIR_Input make it much easier to correctly set the pin for output. Which bit in the PIN_CNF 32 bit register is handled by define macros such as GPIO_PIN_CNF_DIR_Pos.
Setting the GPIO pin with Pull-Up or Pull-Down
Ooh – and I had no idea that I could set the PULL bits (3-2) to be either PULL UP or PULL DOWN. To be fair, I would have if I had set a GPIO for reading using the APIs found in nrf_gpio.h. After all, void nrf_gpio_cfg_input(uint32_t pin_number, nrf_gpio_pin_pull_t pull_config); would have forced me to look at nrf_gpio_pull_t and found out about the different PULL states.
I played around with different PULL states using pin 8. Taking DMM measurements, when the PULL-UP (bits 3:2 set to 11) was set, the voltage on the pin measured the same as the power source (3.3V). When the PULL-DOWN (bits 3:2 set to 01) was set, the pin was set to GND.
There’s some functionality that I don’t understand – even after reading the documentation :-)…such as DRIVE, INPUT, SENSE….with these – I don’t know if that is TMI at this point or I’ll be spending days debugging something because I don’t understand every bit…hmmm…I struggle with when to move on when learning something new!
Turn LED ON
The nrf_gpio.h sets a pin to high using:
NRF_GPIO->OUTSET = (1UL << pin_number);
YIPPEE!!! The LED turned on:
To turn off the LED, set the appropriate bit of the GPIO’s OUTCLR register to 1:
NRF_GPIO->OUTCLR = (1UL << pin_number);
I can go to the Perspective View and set this bit in the same way I set the OUTSET register’s bit to 1 and the light turns off.
That was exciting. I now have a powerful tool to use when writing firmware for an Arm cortex-m.
One issue I did run into was in the UI for the Perspective View. There were several times when I attempted to change a bit value and it didn’t take, or the text saying if it had changed was incorrect. I attribute this to the UI. Eventually I could get what I wanted to work and tell it worked because the bit values shown were correct even if the text was incorrect.
Thank you for reading this far. Please find many things to smile about.