A student asked how to use the standard C libraries with one of my examples recently. He wanted to know how to use string functions such as strcat, strcpy and so on. This isn’t something I had tried before because my goal was to expose the lower level details of hardware I/O. Anyway, having fiddled around a bit on the command line I came up with this command for buidling code for the STM32L011 nucleo board
arm-none-eabi-gcc -static -mthumb -mcpu=cortex-m0plus main.c init.c serial.c -T linker_script.ld -o main.elf -nostartfiles
Breaking this down:
arm-none-eabi-gcc: Your cross compiler. Your PATH environment variable should include the directory this lives in.
-static: Don’t use DLL’s (run-time linking) i.e. include the library function code in the final executable image.
-mthumb: Generate thumb code rather than ARM code.
-mcpu=cortex-m0plus: The STM32L011 has a Cortex M0+ CPU
The list of C files
-T linker_script.ld: Use this linker script to define memory regions when building the output executable image.
-o main.elf: name the output file main.elf
–nostartfiles: Don’t include “standard” start and stop functions. The code includes our own custom start-up code
I wanted to be able to dump the output file onto the virtual disk emulated by the nucleo board. This is done as follows:
arm-none-eabi-objcopy -O binary main.elf main.bin
This creates a raw binary program image which can be dropped on to the virtual disk.
The code was based a previous serial example for the STM32L011. The main.c file is replaced with this:
/* * Serial: serial i/o routines for the STM32L011 */ #include "stm32l011.h" #include "serial.h" #include <string.h> void delay(int); void delay(int dly) { while( dly--); } void initClockHSI16() { // Use the HSI16 clock as the system clock - allows operation down to 1.5V RCC_CR &= ~BIT24; RCC_CR |= BIT0; // turn on HSI16 (16MHz clock) while ((RCC_CR & BIT2)==0); // wait for HSI to be ready // set HSI16 as system clock source RCC_CFGR |= BIT0; } void configPins() { // Enable PORTB where LED is connected RCC_IOPENR |= BIT1; GPIOB_MODER |= BIT6; // make bit3 an output GPIOB_MODER &= ~BIT7; // make bit3 an output } const char Str1[]="Hello "; const char Str2[]="World\r\n"; char CombinedString[50]; int main() { uint32_t Counter=0; initClockHSI16(); configPins(); initUART(9600); CombinedString[0]=0; CombinedString[49]=0; while(1) { GPIOB_ODR |= BIT3; delay(2000000); GPIOB_ODR &= ~BIT3; delay(2000000); strcpy(CombinedString,Str1); strcat(CombinedString,Str2); eputs(CombinedString); eputs("\r\n"); } return 0; }