# 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. Will be included in `v0.12.0-rc4(+)`.
* 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) 
* 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)