Whoa. I have just spent an excessively long time…so long I have lost count of the days….attempting to blink an LED on the Ladybug Blue Lite (LBL) A2 PCB. I can now say…YIPPEE! the LED light will now blink. This blog post is the story of the (mind) numbing path I stumbled up to blinking the LED on the (LBL) Alpha 2 PCB.
This was the first time I would be trying out a micro controller that I soldered onto a PCB. Well, actually I am using a BLE module. Instead of using the nRF51822 chip directly, I decided to use the MDBT40 BLE module from Raytac. I don’t know anything about BLE radios so it is best to leave it to a chip integrator that has been certified.
Thanks to Those That Went Before
- THANK YOU to Ron Sousa for the course he is running as part of Contextual Electronics. If he had not focused our attention and practice on a “similar” ARM Cortex-m0 SOIC – an STM32 micro controller, I doubt if I would have been able to figure out/understand how the NVMC registers worked and how to write to them (I discuss this below. It was a key part of the debugging process)
- THANK YOU to folks like Erik Midtown on the Nordic DevZone blog for posting very helpful info. Like this.
I don’t know why the term “flash programming” bothers me. Perhaps because of the results I get when Googling “flash programming.” Whatever. Somehow I must get the bits that make up the executable of the LED_TEST binary copied onto the nRF51822 that the MDB40T encapsulates.
The programmer sends bits back and forth between my Mac and the micro controller. A terrific feature of the nRF51 DK is it’s Debug out support. Debug out support allows me to flash program and debug programs on external nRF51822’s – like the LBL. YIPPEE! I don’t need an additional programmer/debugger like SEGGER’s J-LINK.
My Brief Intro To SWD
When I was growing up, my family lived in non-English speaking countries. Most of the conversational language I picked up came from listening and observing. I find observing a wire protocol to be daunting since it is at a lower level than say asking for a drink of water. So my first search was for SWD documentation.
The language/protocol “spoken” between the debugger and the nRF51822 chip within the MDB40T is the very popular two wire protocol Serial Wire Debug (SWD). Arm’s specification can be downloaded here if you signed up for an account. I also included the specification in the Specifications folder of the LBL GitHub repository.
Another SWD reference I found surprisingly useful was the reference manual for the STM32F0xxxx . I also included this document in the Specifications folder. I was surprised by how well the document condensed down what was needed for me to start understanding what the heck would be spoken between the debugger and the nRF51822. I was introduced to this reference manual by Ron Sousa in his embedded systems course within Contextual Electronics.
Lucky for us, the Saleae logic analyzer can decompose SWD traffic. A change log on Salae’s web site noted the version of the Logic UI I needed to run on my Mac was at least version 1.2.2. The most recent version is identified as 1.1.5. Saleae has a beta version (1.2.3 as of this post) available here. I updated to the beta version to use the SWD protocol analyzer. A caveat: Given the records I reviewed and compared with the SWD documentation, I believe there are mistakes in some of the bit interpretations. I say “I believe” versus “there are” because I reached a saturation point and moved on once I got an idea on why I could not initially program the LBL.
The other thing I looked at – not carefully enough at first – was the schematic as it related to debug-out and debug-in and the MDBT40 reference design. The nRF51-DK Hardware Files 1_1_0 2 (also in GitHub) shows the pinouts of P20:
The nRF51-DK User Guid v1_0.pdf (also in GitHub) talks about debug output in section 5.10. There are two connectors on the board – P19 and P20 – that can be hooked up to external nRF51822’s. I chose to use the P20 because the P19 requires a cable/connector I do not have. I used standard male shield header pins for the P20
Debugging Flash Programming
I’m finally ready to debug why flash programming doesn’t work
I actually didn’t do this first…the first thing I did was to go down debugging the SWD protocol. That was not the right thing to do. Always check connectivity first!
And there it was. The circled pins are the pins on the BLE module exposed for SWDIO and SWCLK traffic. On the first soldering go around, I was too light with the amount of solder paste. Note the SWDIO and SWCLK pins weren’t connected to the pads:
Applying more solder:
While I am unskilled at reading SWD traffic, the packets pointed to a lack of connection because the host can’t connect to the nRF51822’s access port. As in – knock, knock, knock…no one is answering.
|Operation||read||AccessPort||DRW||0b 1011 1111||OK||0b 1111 1011 1111 1111 0110 1111 1110 1110|
|Operation||read||AccessPort||RAZ_WI||0b 1011 0111||OK||0b 1111 1111 0111 0111 1101 1111 1101 1101|
|Operation||read||AccessPort||RAZ_WI||0b 1011 0111||OK||0b 1110 0111 1111 1111 1011 1111 1101 1101|
|Operation||read||AccessPort||RAZ_WI||0b 1011 0111||OK||0b 0100 1111 1110 1111 1101 1111 1101 1101|
but still… flash programming STILL failed…
Instead of JLink running through the GDBServer, I tried connecting using JLink Commander in a terminal window. The JLink Commander executable is called JLinkEXE on the Mac. It got installed and the PATH system variable updated on my Mac when I installed all the Eclipse goo which I discussed in previous posts, like this one.
To start the connection, I typed in:
jlinkexe -device nrf51422_xxac
The problem was the device name was incorrect. I had gotten the device name from earlier Eclipse builds that worked on Adafruit’s Bluefruit LE friend as well as the nRF51 DK. Unfortunately, these devices could still be flash programmed with the nrf5142_xxac device name.
It turns out the current MDBT40 modules I have include 16kB RAM instead of 32kB RAM:
- nRF51422_xxAA: 256kB of Flash and 16kB of RAM
- nRF51422_xxAC: 256kB of Flash and 32kB of RAM
Available commands are:
f Firmware info
Sleep Waits the given time (in milliseconds). Syntax: Sleep <delay>
s Single step the target chip
st Show hardware status
hwinfo Show hardware info
mem Read memory. Syntax: mem [<Zone>:]<Addr>, <NumBytes> (hex)
mem8 Read 8-bit items. Syntax: mem8 [<Zone>:]<Addr>, <NumBytes> (hex)
mem16 Read 16-bit items. Syntax: mem16 [<Zone>:]<Addr>, <NumItems> (hex)
mem32 Read 32-bit items. Syntax: mem32 [<Zone>:]<Addr>, <NumItems> (hex)
w1 Write 8-bit items. Syntax: w1 [<Zone>:]<Addr>, <Data> (hex)
w2 Write 16-bit items. Syntax: w2 [<Zone>:]<Addr>, <Data> (hex)
w4 Write 32-bit items. Syntax: w4 [<Zone>:]<Addr>, <Data> (hex)
erase Erase internal flash of selected device. Syntax: Erase
The return from both was an error that talked about
“No matching RAMcode found.”
Info: J-Link: Flash download: Restarting flash programming due to program error (possibly skipped erasure of half-way erased sector). Info: J-Link: Flash download: Skip optimizations disabled for second try. Error while programming flash: Programming failed.
Looking at a Nordic DevZone post under the section Troubleshooting tips I saw that I could try erasing the flash by writing directly to the registers. Besides, this gave me an opportunity to better understand how to program to the registers:
J-Link>w4 4001e504 2
J-Link>w4 4001e50c 1
From above, w4 is the command to JLinkExe to write a 32 bit chunk-o-data to an address. In the case of the first command, the address is 0x4001e504.
The Functional Description 6.1 section notes: “Before a write can be performed the NVM must be enabled for writing in CONFIG.WEN. Similarly, before an erase can be performed the NVM must be enabled for erasing in CONFIG.EEN.”
Looking at the documentation on the NVMC (Non-Volatile Memory Controller) in the nRF51_Series_Reference_manual v3.0.pdf (also on GitHub) – Section 6, the base register for the NVMC peripheral is 0x4001E00.
OK, I’m in the right “ball park.”
Going to Table 4, the Config register is 0x504. The first write is to the Config register of the NVMC peripheral. A 2 is written. Looking at Table 6:Config setting 0x504 to 2 enables erase.
Now that erase is enabled, time erase all. 0x50c does an erase all which is documented in Table 9: ERASEALL. a 1 written to this memory address starts a chip erase.
And YIPPEE! This worked. Checking some of the bytes of memory with this command:
returned 0xFF 0xFF….. flash was erased.
Running J-Link erase and loadfile
I could continue this route – basically programming the erase and loadfile functionality using registers commands- but…why am I getting “No matching RAMcode found” when I tried the erase or loadfile commands? How am I going to load and debug from within Eclipse?
Oh – wait – RAMcode is J-Link’s error info for a device’s code to handle these functions. Apparently everyone (except me?) is familiar with the term “RAMcode.” In hindsight, what it is makes sense but at the time I thought running in a circle flailing my arms up and down was the definition. Oh. Well…and that is how I concluded to try a different device name. I tried the device name used in the “Automating Tasks by Modifying the Makefiles” section of the Nordic DevZone post:
JLinkEXE -device nrf51822
and… wait for it… YIPPEE!!! it worked!
What seems to happen is the device is actually nrf51822_xxAA instead of nrf5182_xxAC.
Now while this experience was mind number, I found blundering through figuring this out to be satisfying in the sense that my determination out maneuvered my lack of skill/knowlege. I was determined to figure this out. I did. I’m happy about that.
That’s it for now. Please find many things to smile about.