# Developing with [新唐科技(Nuvoton)](https://www.nuvoton.com/)'s ARM Cortex-M Development Board ###### tags: `Nuvoton`, `NUC472`, `Cortex-M4`, `MCU`, `arm-none-eabi-gcc` ## Development Environment * My host is an Arch Linux (x86_64) system. The target chip is an ARM Cortex-M4 MCU. Therefore, install the `arm-none-eabi-` toolchain packages: * **arm-none-eabi-binutils** * **arm-none-eabi-gcc** * **arm-none-eabi-newlib** * **arm-none-eabi-gdb** * I prefer the Makefile tool. So, **make** is installed, too. * Also, need **OpenOCD** to flash and debug. * [Upstream OpenOCD](https://sourceforge.net/p/openocd/code/ci/master/tree/) must includes these commits at least: * [flash/nor/numicro: reorder the parts list](https://review.openocd.org/c/openocd/+/7339/2) * [flash: support Nuvoton M541 & NUC442/472 series](https://review.openocd.org/c/openocd/+/7329/6) * [tcl: add a configuration file for Nuvoton M541 & NUC442/472 series](https://review.openocd.org/c/openocd/+/7330/6) The commits have been merged into the master branch. * Or, [downstream Nuvoton OpenOCD](https://github.com/OpenNuvoton/OpenOCD-Nuvoton) ## Developing with NuTiny-SDK-NUC472 * [NuTiny-SDK-NUC472 User Manual](https://www.nuvoton.com/export/resource-files/UM_NuTiny-SDK-NUC472_EN_Rev1.02.pdf) ![](https://hackmd.io/_uploads/SkEwfDuLn.jpg) * The MCU is Nuvoton [NUC472HI8AE](https://www.nuvoton.com/products/microcontrollers/arm-cortex-m4-mcus/nuc400-series/nuc472hi8ae/) * However, Nuvoton marks it as **Not Recommended For New Designs (NRND)** * Recommended Part Number: [M487 Ethernet Series](https://www.nuvoton.com/products/microcontrollers/arm-cortex-m4-mcus/m487-ethernet-series/) * I still write this record, because the development board NuTiny-SDK-NUC472 is much cheaper then others. If someone give me the newer board (Cortex-M4), I may write another article for it. * Nuvoton has provided the NUC472/442 BSP at https://github.com/OpenNuvoton/NUC472_442BSP, which follows [Common Microcontroller Software Interface Standard (CMSIS)](https://developer.arm.com/tools-and-software/embedded/cmsis). ### Use the NUC472-NuTiny's LED Sample as the Example ```shell= $ git clone https://github.com/OpenNuvoton/NUC472_442BSP $ cd NUC472_442BSP/SampleCode/NUC472-NuTiny/LED/ ``` 1. Add the [Makefile](https://github.com/starnight/NUC472_442BSP/blob/master/SampleCode/NUC472-NuTiny/LED/Makefile) into the LED sample code directory. ```shell= [LED]$ ls -l total 20 drwxr-xr-x 2 zack zack 4096 Oct 22 14:32 GCC drwxr-xr-x 2 zack zack 4096 Oct 22 14:32 IAR drwxr-xr-x 2 zack zack 4096 Oct 22 14:32 KEIL -rw-r--r-- 1 zack zack 3420 Oct 22 14:32 main.c -rw-r--r-- 1 zack zack 3090 Oct 22 15:05 Makefile ``` PS. If it is [downstream Nuvoton OpenOCD](https://github.com/OpenNuvoton/OpenOCD-Nuvoton), the `TARGETCHIP` in the [Makefile](https://github.com/starnight/NUC472_442BSP/blob/master/SampleCode/NUC472-NuTiny/LED/Makefile) should be set as `"target/numicroM4.cfg"`. 2. Build the LED application with `make`: ```shell= [LED]$ make arm-none-eabi-gcc -I../../../../NUC472_442BSP/Library/CMSIS/Include -I../../../../NUC472_442BSP/Library/StdDriver/inc -I../../../../NUC472_442BSP/Library/Device/Nuvoton/NUC472_442/Include -I. -ggdb -Os -Wall -Wextra -Warray-bounds -mlittle-endian -mthumb -mcpu=cortex-m4 -mthumb-interwork -mfloat-abi=hard -mfpu=fpv4-sp-d16 -T../../../../NUC472_442BSP/Library/Device/Nuvoton/NUC472_442/Source/GCC/gcc_arm.ld main.c ../../../../NUC472_442BSP/Library/StdDriver/src/clk.c ../../../../NUC472_442BSP/Library/StdDriver/src/gpio.c ../../../../NUC472_442BSP/Library/StdDriver/src/sys.c ../../../../NUC472_442BSP/Library/Device/Nuvoton/NUC472_442/Source/system_NUC472_442.c ../../../../NUC472_442BSP/Library/Device/Nuvoton/NUC472_442/Source/GCC/startup_NUC472_442.S -o LED.elf ... arm-none-eabi-objcopy -O ihex LED.elf LED.hex arm-none-eabi-objcopy -O binary LED.elf LED.bin ``` 3. Connect the NuTiny-SDK-NUC472 to your host via the USB cable. 4. Flash the built image into NuTiny-SDK-NUC472 with `make flash`: ```shell $ make flash openocd -f "interface/nulink.cfg" -f "target/numicro_m4.cfg" \ -c "program LED.elf verify reset exit" Open On-Chip Debugger 0.12.0-rc2+dev-00007-gdc1e6d4d4 (2022-11-13-14:48) Licensed under GNU GPL v2 For bug reports, read http://openocd.org/doc/doxygen/bugs.html hla_swd Info : The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD Info : clock speed 1000 kHz Info : Nu-Link firmware_version 6535, product_id (0x00012009) Info : Adapter is Nu-Link Info : IDCODE: 0x2BA01477 Info : [NuMicro.cpu] Cortex-M4 r0p1 processor detected Info : [NuMicro.cpu] target has 6 breakpoints, 4 watchpoints Info : starting gdb server for NuMicro.cpu on 3333 Info : Listening on port 3333 for gdb connections [NuMicro.cpu] halted due to breakpoint, current mode: Thread xPSR: 0x01000000 pc: 0x00000f5c msp: 0x20010000 [NuMicro.cpu] halted due to debug-request, current mode: Thread xPSR: 0x01000000 pc: 0x00000f5c msp: 0x20010000 ** Programming Started ** Info : Device ID: 0x00047201 Info : Device Name: NUC472HI8AE Info : bank base = 0x00000000, size = 0x00080000 Warn : Adding extra erase range, 0x00001770 .. 0x000017ff Info : Nuvoton NuMicro: Sector Erase ... (0 to 2) Info : Nuvoton NuMicro: Flash Write ... ** Programming Finished ** ** Verify Started ** ** Verified OK ** ** Resetting Target ** shutdown command invoked ``` 5. After flash, the onboard LED should become blinking. ### CMSIS, Standard and Device Libraries for the Makefile NUC472/442 BSP provides the libraries: * CMSIS library is under path [`Library/CMSIS`](https://github.com/OpenNuvoton/NUC472_442BSP/tree/master/Library/CMSIS). * Standard library is under path [`Library/StdDriver`](https://github.com/OpenNuvoton/NUC472_442BSP/tree/master/Library/StdDriver). * NUC472/442's library is under path [`Library/Device/Nuvoton/NUC472_442`](https://github.com/OpenNuvoton/NUC472_442BSP/tree/master/Library/Device/Nuvoton/NUC472_442). * NUC472/442's system clock initialization is at [`Library/Device/Nuvoton/NUC472_442/Source/system_NUC472_442.c`](https://github.com/OpenNuvoton/NUC472_442BSP/blob/master/Library/Device/Nuvoton/NUC472_442/Source/system_NUC472_442.c). * NUC472/442's startup file is at [`Library/Device/Nuvoton/NUC472_442/Source/GCC/startup_NUC472_442.S`](https://github.com/OpenNuvoton/NUC472_442BSP/blob/master/Library/Device/Nuvoton/NUC472_442/Source/GCC/startup_NUC472_442.S). * NUC472/442's linker file is at [`Library/Device/Nuvoton/NUC472_442/Source/GCC/gcc_arm.ld`](https://github.com/OpenNuvoton/NUC472_442BSP/blob/master/Library/Device/Nuvoton/NUC472_442/Source/GCC/gcc_arm.ld). ### Debugging Debug with GDB via OpenOCD and Nu-Link. 1. Start the gdb server with Nu-Link and the numicro M4 configs: ```shell $ openocd -f "interface/nulink.cfg" -f "target/numicro_m4.cfg" Open On-Chip Debugger 0.12.0-rc2+dev-00007-gdc1e6d4d4 (2022-11-13-14:48) Licensed under GNU GPL v2 For bug reports, read http://openocd.org/doc/doxygen/bugs.html hla_swd Info : The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD Info : Listening on port 6666 for tcl connections Info : Listening on port 4444 for telnet connections Info : clock speed 1000 kHz Info : Nu-Link firmware_version 6535, product_id (0x00012009) Info : Adapter is Nu-Link Info : IDCODE: 0x2BA01477 Info : [NuMicro.cpu] Cortex-M4 r0p1 processor detected Info : [NuMicro.cpu] target has 6 breakpoints, 4 watchpoints Info : starting gdb server for NuMicro.cpu on 3333 Info : Listening on port 3333 for gdb connections [NuMicro.cpu] halted due to breakpoint, current mode: Thread xPSR: 0x01000000 pc: 0x00000f5c msp: 0x20010000 ``` It shows that the gdb server is listening on port **3333**. 2. Have the gdb client connecting to the gdb server to debug the `LED.elf` flashed on the MCU chip Nuvoton NUC472HI8AE: ```shell= $ arm-none-eabi-gdb LED.elf GNU gdb (GDB) 12.1 ... Reading symbols from LED.elf... (gdb) target remote localhost:3333 Remote debugging using localhost:3333 warning: Overlapping regions in memory map: ignoring Reset_Handler () at ../../../../NUC472_442BSP/Library/Device/Nuvoton/NUC472_442/Source/GCC/startup_NUC472_442.S:268 268 ldr r1, =__etext (gdb) hbreak main.c:86 Hardware assisted breakpoint 1 at 0x3a2: file main.c, line 86. (gdb) continue Continuing. Breakpoint 1, main () at main.c:86 86 PB10 = 0; (gdb) list 81 /* Configure PB.10 as Output mode */ 82 GPIO_SetMode(PB, BIT10, GPIO_MODE_OUTPUT); 83 84 while(1) 85 { 86 PB10 = 0; 87 CLK_SysTickDelay(500000); 88 PB10 = 1; 89 CLK_SysTickDelay(500000); 90 } (gdb) hbreak 88 Hardware assisted breakpoint 2 at 0x3ae: file main.c, line 88. (gdb) continue Continuing. halted: PC: 0x000003a4 Breakpoint 2, main () at main.c:88 88 PB10 = 1; (gdb) continue Continuing. halted: PC: 0x000003b0 Breakpoint 1, main () at main.c:86 86 PB10 = 0; (gdb) continue Continuing. halted: PC: 0x000003a4 Breakpoint 2, main () at main.c:88 88 PB10 = 1; (gdb) ``` Use `hbreak` (hardware-assisted breakpoint) to add a break point, instead of `break`. Reference: [5.1.1 Setting Breakpoints](https://sourceware.org/gdb/onlinedocs/gdb/Set-Breaks.html) ## Reference * [作業系統之前的程式 for stm32f4discovery (0) - 打造 linux 開發環境](https://descent-incoming.blogspot.com/2013/04/for-stm32f4discovery-0-linux.html) * [OpenOCD - Flash Commands](https://openocd.org/doc-release/html/Flash-Commands.html) * [OpenOCD - Flash Programming](https://openocd.sourceforge.io/doc/html/Flash-Programming.html)