Somewhat based on issue #2453, and my findings/progress/clarification requests…
PlatformIO is an amazing platform for handling processors–especially ones that tend to be “locked away” under proprietary and expensive compiler suites (Keil, IAR, etc.)
I recently got started on Nuvoton processors, and bought a dev board for the M252KG6AE processor. Nuvoton has a half-baked solution for Linux utilizing a customized Eclipse IDE and a customized OpenOCD–but honestly, it’s pretty poor. I’m not familiar with Eclipse IDE, and it’s mind-bogglingly complicated to try to get anything out of it.
Did some digging around, and found that I could get a verbose compile log of an example Nuvoton project–which helps CONSIDERABLY in figuring out why it doesn’t work or what to do…
I’ve spent a few days tinkering around with modifying the Platform and Frameworks by @maxgerhardt for the Gigadevice Beijing CPUs…and at long last was able to finally get a successful compile–with a few caveats.
Since the Nuvoton BSPs for these Cortex-M MCUs are also available in GCC flavor, we can use arm-none-eabi-gcc (as per the “official” Eclipse port) for compiling, as well as OpenOCD for programming and debugging (hopefully without requiring a custom OpenOCD–and even if so, oh well.)
My goals:
- To create a platform on PlatformIO for these Cortex-M MCUs, where they can be programmed without cumbersome or expensive tooling.
- To allow usage of the official Nuvoton CMSIS BSP (board support package) without modification (if at all possible)
For reference, here’s the verbose compile log from Eclipse IDE of a Nuvoton “PWM_DeadTime” example:
make all
Building file: /mnt/Files/Nuvoton/BSP - M251_M252_M254_M256_M258_Series_BSP_CMSIS_V3.02.001/SampleCode/StdDriver/PWM_DeadTime/main.c
Invoking: Cross ARM GNU C Compiler
arm-none-eabi-gcc -mcpu=cortex-m23 -march=armv8-m.base -mthumb -Os -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections -g -I"/mnt/Files/Nuvoton/BSP - M251_M252_M254_M256_M258_Series_BSP_CMSIS_V3.02.001/SampleCode/StdDriver/PWM_DeadTime/GCC/…/…/…/…/Library/CMSIS/Include" -I"/mnt/Files/Nuvoton/BSP - M251_M252_M254_M256_M258_Series_BSP_CMSIS_V3.02.001/SampleCode/StdDriver/PWM_DeadTime/GCC/…/…/…/…/Library/StdDriver/inc" -I"/mnt/Files/Nuvoton/BSP - M251_M252_M254_M256_M258_Series_BSP_CMSIS_V3.02.001/SampleCode/StdDriver/PWM_DeadTime/GCC/…/…/…/…/Library/Device/Nuvoton/M251/Include" -std=gnu11 -MMD -MP -MF"User/main.d" -MT"User/main.d" -c -o “User/main.o” “/mnt/Files/Nuvoton/BSP - M251_M252_M254_M256_M258_Series_BSP_CMSIS_V3.02.001/SampleCode/StdDriver/PWM_DeadTime/main.c”
Finished building: /mnt/Files/Nuvoton/BSP - M251_M252_M254_M256_M258_Series_BSP_CMSIS_V3.02.001/SampleCode/StdDriver/PWM_DeadTime/main.cBuilding file: /mnt/Files/Nuvoton/BSP - M251_M252_M254_M256_M258_Series_BSP_CMSIS_V3.02.001/Library/StdDriver/src/clk.c
Invoking: Cross ARM GNU C Compiler
arm-none-eabi-gcc -mcpu=cortex-m23 -march=armv8-m.base -mthumb -Os -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections -g -I"/mnt/Files/Nuvoton/BSP - M251_M252_M254_M256_M258_Series_BSP_CMSIS_V3.02.001/SampleCode/StdDriver/PWM_DeadTime/GCC/…/…/…/…/Library/CMSIS/Include" -I"/mnt/Files/Nuvoton/BSP - M251_M252_M254_M256_M258_Series_BSP_CMSIS_V3.02.001/SampleCode/StdDriver/PWM_DeadTime/GCC/…/…/…/…/Library/StdDriver/inc" -I"/mnt/Files/Nuvoton/BSP - M251_M252_M254_M256_M258_Series_BSP_CMSIS_V3.02.001/SampleCode/StdDriver/PWM_DeadTime/GCC/…/…/…/…/Library/Device/Nuvoton/M251/Include" -std=gnu11 -MMD -MP -MF"Library/Library/clk.d" -MT"Library/Library/clk.o" -c -o “Library/Library/clk.o” “/mnt/Files/Nuvoton/BSP - M251_M252_M254_M256_M258_Series_BSP_CMSIS_V3.02.001/Library/StdDriver/src/clk.c”
Finished building: /mnt/Files/Nuvoton/BSP - M251_M252_M254_M256_M258_Series_BSP_CMSIS_V3.02.001/Library/StdDriver/src/clk.cBuilding file: /mnt/Files/Nuvoton/BSP - M251_M252_M254_M256_M258_Series_BSP_CMSIS_V3.02.001/Library/StdDriver/src/gpio.c
Invoking: Cross ARM GNU C Compiler
arm-none-eabi-gcc -mcpu=cortex-m23 -march=armv8-m.base -mthumb -Os -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections -g -I"/mnt/Files/Nuvoton/BSP - M251_M252_M254_M256_M258_Series_BSP_CMSIS_V3.02.001/SampleCode/StdDriver/PWM_DeadTime/GCC/…/…/…/…/Library/CMSIS/Include" -I"/mnt/Files/Nuvoton/BSP - M251_M252_M254_M256_M258_Series_BSP_CMSIS_V3.02.001/SampleCode/StdDriver/PWM_DeadTime/GCC/…/…/…/…/Library/StdDriver/inc" -I"/mnt/Files/Nuvoton/BSP - M251_M252_M254_M256_M258_Series_BSP_CMSIS_V3.02.001/SampleCode/StdDriver/PWM_DeadTime/GCC/…/…/…/…/Library/Device/Nuvoton/M251/Include" -std=gnu11 -MMD -MP -MF"Library/Library/gpio.d" -MT"Library/Library/gpio.o" -c -o “Library/Library/gpio.o” “/mnt/Files/Nuvoton/BSP - M251_M252_M254_M256_M258_Series_BSP_CMSIS_V3.02.001/Library/StdDriver/src/gpio.c”
Finished building: /mnt/Files/Nuvoton/BSP - M251_M252_M254_M256_M258_Series_BSP_CMSIS_V3.02.001/Library/StdDriver/src/gpio.cBuilding file: /mnt/Files/Nuvoton/BSP - M251_M252_M254_M256_M258_Series_BSP_CMSIS_V3.02.001/Library/StdDriver/src/pwm.c
Invoking: Cross ARM GNU C Compiler
arm-none-eabi-gcc -mcpu=cortex-m23 -march=armv8-m.base -mthumb -Os -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections -g -I"/mnt/Files/Nuvoton/BSP - M251_M252_M254_M256_M258_Series_BSP_CMSIS_V3.02.001/SampleCode/StdDriver/PWM_DeadTime/GCC/…/…/…/…/Library/CMSIS/Include" -I"/mnt/Files/Nuvoton/BSP - M251_M252_M254_M256_M258_Series_BSP_CMSIS_V3.02.001/SampleCode/StdDriver/PWM_DeadTime/GCC/…/…/…/…/Library/StdDriver/inc" -I"/mnt/Files/Nuvoton/BSP - M251_M252_M254_M256_M258_Series_BSP_CMSIS_V3.02.001/SampleCode/StdDriver/PWM_DeadTime/GCC/…/…/…/…/Library/Device/Nuvoton/M251/Include" -std=gnu11 -MMD -MP -MF"Library/Library/pwm.d" -MT"Library/Library/pwm.o" -c -o “Library/Library/pwm.o” “/mnt/Files/Nuvoton/BSP - M251_M252_M254_M256_M258_Series_BSP_CMSIS_V3.02.001/Library/StdDriver/src/pwm.c”
Finished building: /mnt/Files/Nuvoton/BSP - M251_M252_M254_M256_M258_Series_BSP_CMSIS_V3.02.001/Library/StdDriver/src/pwm.cBuilding file: /mnt/Files/Nuvoton/BSP - M251_M252_M254_M256_M258_Series_BSP_CMSIS_V3.02.001/Library/StdDriver/src/retarget.c
Invoking: Cross ARM GNU C Compiler
arm-none-eabi-gcc -mcpu=cortex-m23 -march=armv8-m.base -mthumb -Os -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections -g -I"/mnt/Files/Nuvoton/BSP - M251_M252_M254_M256_M258_Series_BSP_CMSIS_V3.02.001/SampleCode/StdDriver/PWM_DeadTime/GCC/…/…/…/…/Library/CMSIS/Include" -I"/mnt/Files/Nuvoton/BSP - M251_M252_M254_M256_M258_Series_BSP_CMSIS_V3.02.001/SampleCode/StdDriver/PWM_DeadTime/GCC/…/…/…/…/Library/StdDriver/inc" -I"/mnt/Files/Nuvoton/BSP - M251_M252_M254_M256_M258_Series_BSP_CMSIS_V3.02.001/SampleCode/StdDriver/PWM_DeadTime/GCC/…/…/…/…/Library/Device/Nuvoton/M251/Include" -std=gnu11 -MMD -MP -MF"Library/Library/retarget.d" -MT"Library/Library/retarget.o" -c -o “Library/Library/retarget.o” “/mnt/Files/Nuvoton/BSP - M251_M252_M254_M256_M258_Series_BSP_CMSIS_V3.02.001/Library/StdDriver/src/retarget.c”
Finished building: /mnt/Files/Nuvoton/BSP - M251_M252_M254_M256_M258_Series_BSP_CMSIS_V3.02.001/Library/StdDriver/src/retarget.cBuilding file: /mnt/Files/Nuvoton/BSP - M251_M252_M254_M256_M258_Series_BSP_CMSIS_V3.02.001/Library/StdDriver/src/sys.c
Invoking: Cross ARM GNU C Compiler
arm-none-eabi-gcc -mcpu=cortex-m23 -march=armv8-m.base -mthumb -Os -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections -g -I"/mnt/Files/Nuvoton/BSP - M251_M252_M254_M256_M258_Series_BSP_CMSIS_V3.02.001/SampleCode/StdDriver/PWM_DeadTime/GCC/…/…/…/…/Library/CMSIS/Include" -I"/mnt/Files/Nuvoton/BSP - M251_M252_M254_M256_M258_Series_BSP_CMSIS_V3.02.001/SampleCode/StdDriver/PWM_DeadTime/GCC/…/…/…/…/Library/StdDriver/inc" -I"/mnt/Files/Nuvoton/BSP - M251_M252_M254_M256_M258_Series_BSP_CMSIS_V3.02.001/SampleCode/StdDriver/PWM_DeadTime/GCC/…/…/…/…/Library/Device/Nuvoton/M251/Include" -std=gnu11 -MMD -MP -MF"Library/Library/sys.d" -MT"Library/Library/sys.o" -c -o “Library/Library/sys.o” “/mnt/Files/Nuvoton/BSP - M251_M252_M254_M256_M258_Series_BSP_CMSIS_V3.02.001/Library/StdDriver/src/sys.c”
Finished building: /mnt/Files/Nuvoton/BSP - M251_M252_M254_M256_M258_Series_BSP_CMSIS_V3.02.001/Library/StdDriver/src/sys.cBuilding file: /mnt/Files/Nuvoton/BSP - M251_M252_M254_M256_M258_Series_BSP_CMSIS_V3.02.001/Library/StdDriver/src/uart.c
Invoking: Cross ARM GNU C Compiler
arm-none-eabi-gcc -mcpu=cortex-m23 -march=armv8-m.base -mthumb -Os -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections -g -I"/mnt/Files/Nuvoton/BSP - M251_M252_M254_M256_M258_Series_BSP_CMSIS_V3.02.001/SampleCode/StdDriver/PWM_DeadTime/GCC/…/…/…/…/Library/CMSIS/Include" -I"/mnt/Files/Nuvoton/BSP - M251_M252_M254_M256_M258_Series_BSP_CMSIS_V3.02.001/SampleCode/StdDriver/PWM_DeadTime/GCC/…/…/…/…/Library/StdDriver/inc" -I"/mnt/Files/Nuvoton/BSP - M251_M252_M254_M256_M258_Series_BSP_CMSIS_V3.02.001/SampleCode/StdDriver/PWM_DeadTime/GCC/…/…/…/…/Library/Device/Nuvoton/M251/Include" -std=gnu11 -MMD -MP -MF"Library/Library/uart.d" -MT"Library/Library/uart.o" -c -o “Library/Library/uart.o” “/mnt/Files/Nuvoton/BSP - M251_M252_M254_M256_M258_Series_BSP_CMSIS_V3.02.001/Library/StdDriver/src/uart.c”
Finished building: /mnt/Files/Nuvoton/BSP - M251_M252_M254_M256_M258_Series_BSP_CMSIS_V3.02.001/Library/StdDriver/src/uart.cBuilding file: /mnt/Files/Nuvoton/BSP - M251_M252_M254_M256_M258_Series_BSP_CMSIS_V3.02.001/Library/Device/Nuvoton/M251/Source/GCC/_syscalls.c
Invoking: Cross ARM GNU C Compiler
arm-none-eabi-gcc -mcpu=cortex-m23 -march=armv8-m.base -mthumb -Os -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections -g -I"/mnt/Files/Nuvoton/BSP - M251_M252_M254_M256_M258_Series_BSP_CMSIS_V3.02.001/SampleCode/StdDriver/PWM_DeadTime/GCC/…/…/…/…/Library/CMSIS/Include" -I"/mnt/Files/Nuvoton/BSP - M251_M252_M254_M256_M258_Series_BSP_CMSIS_V3.02.001/SampleCode/StdDriver/PWM_DeadTime/GCC/…/…/…/…/Library/StdDriver/inc" -I"/mnt/Files/Nuvoton/BSP - M251_M252_M254_M256_M258_Series_BSP_CMSIS_V3.02.001/SampleCode/StdDriver/PWM_DeadTime/GCC/…/…/…/…/Library/Device/Nuvoton/M251/Include" -std=gnu11 -MMD -MP -MF"CMSIS/CMSIS/GCC/_syscalls.d" -MT"CMSIS/CMSIS/GCC/_syscalls.o" -c -o “CMSIS/CMSIS/GCC/_syscalls.o” “/mnt/Files/Nuvoton/BSP - M251_M252_M254_M256_M258_Series_BSP_CMSIS_V3.02.001/Library/Device/Nuvoton/M251/Source/GCC/_syscalls.c”
Finished building: /mnt/Files/Nuvoton/BSP - M251_M252_M254_M256_M258_Series_BSP_CMSIS_V3.02.001/Library/Device/Nuvoton/M251/Source/GCC/_syscalls.cBuilding file: /mnt/Files/Nuvoton/BSP - M251_M252_M254_M256_M258_Series_BSP_CMSIS_V3.02.001/Library/Device/Nuvoton/M251/Source/GCC/startup_M251.S
Invoking: Cross ARM GNU Assembler
arm-none-eabi-gcc -mcpu=cortex-m23 -march=armv8-m.base -mthumb -Os -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections -g -x assembler-with-cpp -D__STARTUP_CLEAR_BSS -I"/mnt/Files/Nuvoton/BSP - M251_M252_M254_M256_M258_Series_BSP_CMSIS_V3.02.001/SampleCode/StdDriver/PWM_DeadTime/GCC/…/…/…/…/Library/CMSIS/Include" -I"/mnt/Files/Nuvoton/BSP - M251_M252_M254_M256_M258_Series_BSP_CMSIS_V3.02.001/SampleCode/StdDriver/PWM_DeadTime/GCC/…/…/…/…/Library/StdDriver/inc" -I"/mnt/Files/Nuvoton/BSP - M251_M252_M254_M256_M258_Series_BSP_CMSIS_V3.02.001/SampleCode/StdDriver/PWM_DeadTime/GCC/…/…/…/…/Library/Device/Nuvoton/M251/Include" -MMD -MP -MF"CMSIS/CMSIS/GCC/startup_M251.d" -MT"CMSIS/CMSIS/GCC/startup_M251.o" -c -o “CMSIS/CMSIS/GCC/startup_M251.o” “/mnt/Files/Nuvoton/BSP - M251_M252_M254_M256_M258_Series_BSP_CMSIS_V3.02.001/Library/Device/Nuvoton/M251/Source/GCC/startup_M251.S”
Finished building: /mnt/Files/Nuvoton/BSP - M251_M252_M254_M256_M258_Series_BSP_CMSIS_V3.02.001/Library/Device/Nuvoton/M251/Source/GCC/startup_M251.SBuilding file: /mnt/Files/Nuvoton/BSP - M251_M252_M254_M256_M258_Series_BSP_CMSIS_V3.02.001/Library/Device/Nuvoton/M251/Source/system_M251.c
Invoking: Cross ARM GNU C Compiler
arm-none-eabi-gcc -mcpu=cortex-m23 -march=armv8-m.base -mthumb -Os -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections -g -I"/mnt/Files/Nuvoton/BSP - M251_M252_M254_M256_M258_Series_BSP_CMSIS_V3.02.001/SampleCode/StdDriver/PWM_DeadTime/GCC/…/…/…/…/Library/CMSIS/Include" -I"/mnt/Files/Nuvoton/BSP - M251_M252_M254_M256_M258_Series_BSP_CMSIS_V3.02.001/SampleCode/StdDriver/PWM_DeadTime/GCC/…/…/…/…/Library/StdDriver/inc" -I"/mnt/Files/Nuvoton/BSP - M251_M252_M254_M256_M258_Series_BSP_CMSIS_V3.02.001/SampleCode/StdDriver/PWM_DeadTime/GCC/…/…/…/…/Library/Device/Nuvoton/M251/Include" -std=gnu11 -MMD -MP -MF"CMSIS/CMSIS/system_M251.d" -MT"CMSIS/CMSIS/system_M251.o" -c -o “CMSIS/CMSIS/system_M251.o” “/mnt/Files/Nuvoton/BSP - M251_M252_M254_M256_M258_Series_BSP_CMSIS_V3.02.001/Library/Device/Nuvoton/M251/Source/system_M251.c”
Finished building: /mnt/Files/Nuvoton/BSP - M251_M252_M254_M256_M258_Series_BSP_CMSIS_V3.02.001/Library/Device/Nuvoton/M251/Source/system_M251.cBuilding target: PWM_DeadTime.elf
Invoking: Cross ARM GNU C Linker
arm-none-eabi-gcc -mcpu=cortex-m23 -march=armv8-m.base -mthumb -Os -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections -g -T “/mnt/Files/Nuvoton/BSP - M251_M252_M254_M256_M258_Series_BSP_CMSIS_V3.02.001/Library/Device/Nuvoton/M251/Source/GCC/gcc_arm.ld” -Xlinker --gc-sections -Wl,-Map,“PWM_DeadTime.map” --specs=nano.specs -o “PWM_DeadTime.elf” ./User/main.o ./Library/Library/clk.o ./Library/Library/gpio.o ./Library/Library/pwm.o ./Library/Library/retarget.o ./Library/Library/sys.o ./Library/Library/uart.o ./CMSIS/CMSIS/GCC/_syscalls.o ./CMSIS/CMSIS/GCC/startup_M251.o ./CMSIS/CMSIS/system_M251.o
Finished building target: PWM_DeadTime.elfInvoking: Cross ARM GNU Create Flash Image
arm-none-eabi-objcopy -O ihex “PWM_DeadTime.elf” “PWM_DeadTime.hex”
Finished building: PWM_DeadTime.hexInvoking: Cross ARM GNU Print Size
arm-none-eabi-size --format=berkeley “PWM_DeadTime.elf”
text data bss dec hex filename
7816 128 56 8000 1f40 PWM_DeadTime.elf
Finished building: PWM_DeadTime.siz
What I noticed here is that it’s building the CMSIS BSP as well–then combining everything together. This seems to be how Nuvoton likes to do their BSP stuff. Not saying it’s great, or that it’s bad–just that’s how they seem to like to do it.
I have managed to cobble it together to the point of being able to compile the exact same program (have not yet tested whether or not it actually works on the target hardware!)
Problems I’m aware of:
- I had to rename the Nuvoton “_syscalls.c” to “_syscalls.c.nocompile” to get past a GCC “errno redefined”, as follows:
/home/user/.platformio/packages/toolchain-gccarmnoneeabi/bin/…/lib/gcc/arm-none-eabi/10.3.1/…/…/…/…/arm-none-eabi/bin/ld: .pio/build/M252KG6AE/libboot.a(_syscalls.o):(.bss.errno+0x0): multiple definition of `errno’; /home/user/.platformio/packages/toolchain-gccarmnoneeabi/bin/…/lib/gcc/arm-none-eabi/10.3.1/…/…/…/…/arm-none-eabi/lib/thumb/v8-m.base/nofp/libc_nano.a(lib_a-reent.o):(.bss.errno+0x0): first defined here
For whatever reason, this isn’t a problem on the stock Nuvoton compiler, and I notice that both have the “specs=nano.specs” on the final linker step. Unfortunately, it’s not in line with keeping the BSP untouched (for easy updating), nor is it a proper solution.
- I had to delete the “ARM” and “IAR” folders out of the device tree, as GCC was (understandably) failing compiling on the invalid syntax in those folders.
The crux of the issue is that I have to include the “system_M251.c” for a successful compile–and if I point the build libraries to the root “Source” folder, Scons goes down through all of the subfolders as well. Great feature–but I don’t know how to prevent it from traversing subfolders.
BUT…I’d rather not modify the Nuvoton BSP if at all possible, i.e. making it more of a seamless port over to PlatformIO.
Thoughts, solutions?
It appears that it shouldn’t be terribly difficult to make this work for most of the rest of Nuvoton’s 32-bit Cortex-M processors…which would be wonderful.
I would need some direction how to best handle that, whether (a la STSTM32) there’s a separate framework for each “subgroup” of processors…or whether they’re all shoehorned into a single large framework?