If you have been following the Feabhas blog for some time, you may remember that in April of last year I posted about my experiences of using the MQTT protocol. The demonstration code was ran the ARM Cortex-M3 based mbed platform.
For those that are not familiar with the mbed, it is an “Arduino-like” development platform for small microcontroller embedded systems. The variant I’m using is built using an NXP LPC1768 Cortex-M3 device, which offers a plethora of connection options, ranging from simple GPIO, through I2C and SPI, right up to CAN, USB and Ethernet. With a similar conceptual model to Arduino’s, the drivers for all these drivers are supplied in a well-tested (C++) library. The mbed is connect to a PC via a USB cable (which also powers it), so allows the mbed to act as a great rapid prototyping platform. [I have never been a big fan of the 8-bit Arduino (personal choice no need to flame me ) and have never used the newer ARM Cortex-M based Arduino’s, such as the Due.]
However, in its early guise, there were two limitations when targeting an mbed (say compared to the Arduino).
First was the development environment; initially all software development was done through a web-based IDE. This is great for cross-platform support; especially for me being an Apple fanboy. Personally I never had a problem using the online IDE, especially as I am used to using offline environments such as Keil’s uVision, IAR’s Embedded Workbench and Eclipse. Over the years the mbed IDE has evolved and makes life very easy for importing other mbed developers libraries, creating your own libraries and even have an integrated distributed version control feature. But the need Internet connection inhibit the ability to develop code on a long flight or train journey for example.
Second, the output from the build process is a “.bin” (binary) file, which you save on to the mbed (the PC sees the mbed as a USB storage device). You then press the reset button on the mbed to execute your program. I guessing you’re well ahead of me here, but of course that means there is no on-target debug capabilities (breakpoints, single-step, variable and memory viewing, etc.). Now of course one could argue, as we have a well-defined set of driver libraries and if we followed aTest-Driven-Development (TDD) process that we don’t need target debugging (there is support for printf style debugging via the USB support serial mode); but that is a discussion/debate for another session! I would hazard a guess most embedded developers would prefer at least the option of target based source code debugging?
To address the first issue, an export capability was added to the mbed IDE, which would create a complete project ready to build for a number of toolchains (e.g. Keil, IAR, CodeSourcery, etc.). This was a great addition, especially for people prototyping with the mbed but developing their own board based around the LPC1700 family (where they would typically be using JTAG/SWP connections to their target). But for the mbed platform, the project output was a “.bin” file which, again, you dropped on to the mbed and reset to run, so still no on-target debug.
However, last summer I was involved in a meeting at ARM HQ in Cambridge, UK where a new project was discussed. That project is CMSIS-DAP, which was launched as part of the CMSIS 3.0 update. DAP stands for “Debug Access Port” and is interface firmware that allows you to connect a Cortex device with CoreSight to a host PC using just a USB connection (it eliminates the traditional ULINK,J-Link emulator). For mbed users, the most useful aspect is that this firmware update can be applied to the mbed finally allowing on-target debug through an off-line tool such as Keil’s uVision and IAR’s EW.
The process to export a project from the mbed IDE and into uVision is well documented. I had a little bit of fun and games getting the serial driver to recognize the mbed Serial Port (a common problem), but the supplied serial driver on the mbed site (and a couple of unplug-plugin cycles) it was sorted. I am pleased to say the project built without a hitch and “hey presto” I had target debugging for the first time on the mbed.
This, naturally, perked my interest is using the mbed as a general Cortex-M3 target, without the supporting mbed libraries (i.e. a barebones system). In previous posts I have been discussing such aspects of the Cortex-M3 (e.g. HardFault handler, MPU configuration, etc.) utilizing CMSIS. I previously created a youtube video about setting up a minimal CMSIS project using uVision, so I thought that would make a first good test of CMSIS-DAP.
To build a minimal CMSIS project for the mbed, we need the following device specific CMSIS files (ignoring the core CMSIS files, e.g. core_cm3.h, etc.):
Following the process in the youtube video (except selecting the device NXP/LPC1768 rather than the generic ARM/Cortex-M3), I had no difficulty building the project with all the pre-configured settings for the NXP/LPC1768 from Keil.
To download and debug on the target, select Project Options (Alt+F7); Debug tab and select “CMSIS-DAP Debugger” as the option.
The next step is to create the “Hello World” of embedded programmed (the blinking LED). This is the default mbed project, as shown:
To program this up in CMSIS, we can use SysTick for the delay, and all we need to know is how to access LED1 via GPIO. LED1 is wired to Port0:Pin18 (P0_18). So the following code is enough to recreate “Blinky”:
Note the extern “C” is required as I have a C++ main rather than a C (see the earlier posting on weak linkage if you need to understand this further).
Finally, here’s a snapshot of the running project on the mbed with an active breakpoint:
I have also hooked the mbed back up to the DS18B20 temperature sensor and have it currently reporting the office temperature at my desk – find it here on cosm (the fishtank has gone to a good home at GlamoRose Cakes in Swindon, UK).
As always, I hope this proved interesting and all comments welcome.
- TDD in C with Ceedling and WSL2 – performance issues - October 7, 2021
- C++20 modules with GCC11 - August 18, 2021
- Modern Embedded C++ – Deprecation of volatile - May 12, 2021