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;
}