Skip to content

Instantly share code, notes, and snippets.

@mohamed
Created September 18, 2023 09:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mohamed/ecda6ae2ea8430f7454e8e5279b6992c to your computer and use it in GitHub Desktop.
Save mohamed/ecda6ae2ea8430f7454e8e5279b6992c to your computer and use it in GitHub Desktop.
Compiling baremetal C program for Arm Cortex-M0+

Compiling baremetal C program for Arm Cortex-M0+

  1. Install Arm GNU GCC compiler. Download the tar.xv archive from: https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads Define the environmet variable $ARM_GCC_ROOT to point to the location where you extract this archive. This guide was tested with arm-gnu-toolchain-11.3.rel1-x86_64-arm-none-eabi

  2. Update your $PATH and $LD_LIBRARY_PATH as follows:

    setenv PATH $ARM_GCC_ROOT/bin:$PATH
    setenv LD_LIBRARY_PATH $ARM_GCC_ROOT/lib:$LD_LIBRARY_PATH
    
  3. Clone Arm CMSIS 5 as follows:

    git clone https://github.com/ARM-software/CMSIS_5
    cd CMSIS_5
    setenv CMSIS_ROOT `pwd`
    
  4. Create a makefile named Makefile with the following content:

    SYSROOT    = $(ARM_GCC_ROOT)/arm-none-eabi
    TEST      ?= hello
    # See: https://interrupt.memfault.com/blog/arm-semihosting
    ARM_FLAGS  = --specs=rdimon.specs -mcpu=cortex-m0plus
    CC         = arm-none-eabi-gcc --sysroot=$(SYSROOT) $(ARM_FLAGS)
    CFLAGS     = -std=c99 -O2
    CPPFLAGS   = -I$(CMSIS_ROOT)/Device/ARM/ARMCM0plus/Include
    CPPFLAGS  += -I$(CMSIS_ROOT)/CMSIS/Core/Include
    CPPFLAGS  += -DARMCM0P
    LDFLAGS    = -T$(CMSIS_ROOT)/Device/ARM/ARMCM0plus/Source/GCC/gcc_arm.ld
    SRCS       = hello.c
    SRCS      += $(wildcard $(CMSIS_ROOT)/Device/ARM/ARMCM0plus/Source/*.c)
    BINS       = $(TEST).elf
    .PHONY: all clean
    all: $(BINS)
    $(TEST).elf: $(SRCS)
        $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) $^ -o $@
    
    clean:
        $(RM) $(BINS)
    
  5. Create a test program called hello.c as follows:

     #include <stdio.h>
     #include <stdint.h>
    
     #include <ARMCM0plus.h>
    
     uint32_t volatile msTicks = 0;
    
     void SysTick_Handler (void) { }
    
     void WaitForInterrupt (void)  {
       uint32_t curTicks;
    
       curTicks = msTicks;
       while (msTicks == curTicks) {
         __WFI();
       }
     }
    
     void Device_Initialization (void) {
       SystemInit();
       SysTick_Config (SystemCoreClock / 1000);
       NVIC_SetPriority (1, 1);
       NVIC_EnableIRQ (1);
     }
    
    
     int main (void) {
       int sum = 0, i = 0;
       Device_Initialization ();
       printf("Hello World!\n");
       for (i = 0; i < 10; i++)  {
         WaitForInterrupt();
         printf("Interrupt received!\n");
       }
       for (int i = 0; i < 1000; i++) {
         sum += i + (i & 1);
       }
       printf("sum = %d\n", sum);
       return 0;
     }
    
  6. Compile as follows:

     make clean all
    
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment