The Nuvoton M051 is Nuvoton’s entry-level industrial/controls Cortex-M0 microcontrollers. In this family, there are 20 MCUs — tightly packed together around the $1 price point, yet gesticulating wildly in terms of functionality (1-8 PWM channels and ADC channels, 4-64 KB of flash — some devices don’t even have a flash peripheral for in-field updates).
All have 4 KB of RAM (good to see in this price range), a 50 MHz maximum core clock speed (via an on-board PLL via an internal 22 MHz oscillator), and four 32-bit-wide timers (which no other MCU in my round-up can claim). If that’s not enough parentheticals, the M052LDN selected for this review also has
- Two UARTs (with LIN support and 16-byte-deep TX and RX FIFOs)
- Two SPI modules (with 4-byte FIFOs)
- Two I2c modules (with wake-up support)
- Eight channels of ADC (12 bit, 760 ksps sampling rate)
- Eight channels of 16-bit PWM (with center alignment, complementary outputs, programmable dead zones, and ADC triggering)
- External bus interface (for off-chip memory-mapped peripherals)
- 48-pin LQFP (with 40 I/O — with a dedicated register for each pin’s data value, making it look “bit-addressable”)
- 4 KB of data flash and 8 KB of program flash (with hardware bootloader support)
Nuvoton ships their ARM microcontrollers with a BSP that supports both Keil MDK and IAR. All the examples they provide include project files for EW and µVision — for which neither I have a strong affinity: Keil µVision is well-liked among a narrow constituency, but for many, it is a product from a bygone era of expensive, proprietary compilers and IDEs. IAR EW is cut from the same cloth. It’s a pity that both of these companies have really really good compilers — but ARM-GCC is used by every ARM MCU vendor for their in-house development environment, and even products like TrueSTUDIO — an expensive, third-party IDE made by Atolic — boast about their ARM-GCC use.
For this review, I’m using Coocox, which is a heavily-modified (and — let’s be honest: dumbed-down) Eclipse environment that’s built specifically for simplified embedded development. We’re not on a Cortex M
When you create the part, CooCox takes you to a repository view, allowing you to add software components. The only thing you’ll need is the M051_BSP_CMSIS component.
Nuvoton provides a CMSIS-complaint start-up system, as well as simple, no-nonsense peripheral drivers. Many vendors use struct-based peripheral libraries these days; there’s a lot of power and flexibility there, but also a lot of verbosity. The Nuvoton peripheral library uses a simple, functional programming model that’s much better suited to small M0 microcontrollers like this, which don’t offer much configuration options the bigger guys have. Want to set pin P0.2 as an output?
GPIO_SetMode(P0, 2, GPIO_PMD_OUTPUT);
I love that their GPIO peripheral has a dedicated data register for each pin, as it makes you feel like you’re operating on a bit-aware 8051:
P02 ^= 1; // toggle P0.2
if(P01 == false)
There are similarly nice programming constructs and functions for configuring most peripherals. For example, to mux a UART RX pin, enable a UART clock, open the UART at a given baud rate, and enable interrupts we’re interested in:
SYS->P3_MFP |= SYS_MFP_P30_RXD0;
CLK_SetModuleClock(UART0_MODULE, CLK_CLKSEL1_UART_S_HIRC, CLK_CLKDIV_UART(12));
UART_EnableInt(UART0, UART_IER_RDA_IEN_Msk | UART_IER_RLS_IEN_Msk | UART_IER_BUF_ERR_IEN_Msk);
It’s certainly not the least-verbose SDK I’ve seen, but I feel like I have more intuition about how to use their SDK than I do for most ARM peripheral libraries — and that’s good, because there’s essentially no documentation for this. Nuvoton gives you demo programs and the docs embedded in the code, but that’s it. I found a Windows Help file (??) floating around on their site, but it didn’t seem to work on my computer. That was the sole piece of documentation I was able to find through official channels, though I believe if you’re using the BSP in CoIDE, it will give you access to Doxygen-created documentation for the modules (that’s effectively the same as just reading the docs in the code).
If you’re using CoIDE, be careful — the peripheral drivers in their repository are old and seem to have bugs in them; while working on the DMX project, I noticed the PWM driver assigned one of my PWM channels to run off the wrong clock source. This bug has long since been fixed in the official Nuvoton BSP, so you’ll probably want to copy it over the existing one in CoIDE when you create your project.
After just complaining that Nuvoton’s SDK has no documentation, this may seem insane, but I’d call the overall documentation for the ecosystem “decent” when compared to other ARM MCUs I tested; many provide nothing more than an API docset functionally equivalent to reading the docs in the code, plus a reference manual that’s nothing more than a list of register descriptions. Very few vendors provide good, concept-oriented documentation that helps you understand how to tie all the separate modules together to accomplish something.
Nuvoton is no different in regards to their SDK, but they provide tons of sample code that is straightforward, and more importantly, the device datasheet and reference manual are much better than some vendors — detailed step-by-step instructions are given outlining the procedures to configure each peripheral, supporting the most common modes. I also appreciated attention to detail such as the peripheral’s interrupt tables that explained all the interrupt flags, how to enable them, and how to clear them.
Code Generation Tool
Nuvoton ships a basic pin-muxing tool, but it’s potentially clunkier to use than a datasheet plus a text editor. The tool doesn’t provide support for clock gating, let alone peripheral initialization, and it’s written in some weird web-based framework that makes the entire layout fixed size. While the “save config” button may give you piece of mind that you’ll be able to recall your configuration at a later date, you’ll be sorely disappointed when you attempt this feat — trying to load a saved configuration file always results in a file format error.
CooCox has a separate pin configuration tool, called CoSmart, and it’s fantastic. Unfortunately, it doesn’t seem to have been updated with the current-generation BSP; the code it produces will not compile against the BSP in CoIDE.
Luckily, if you can figure out which pin config register you need to use, Nuvoton’s SDK provides predefined masks that make it next to trivial.
Blah blah blah
Nuvoton has joined the “snap apart” club, and I couldn’t be happier.