Programming microcontrollers

an introduction

by Sergey Lyubka

for Dublin C/C++ User Group

A little bit of history

  • 1969: BUSICOM + Intel, Marcian Hoff, Federico Faggin
  • 1971: Intel buys a license. i4004, 6000 ops/second
  • 1972: CTC order. Intel + TI, i8008. 16k RAM, 300k ops
  • 1974: i8080, 64k RAM, 75 instr, $360. Motorola 6800

(*) from the book by Milan Verle 

i8008

i8080

A little bit of history (cont)

  • 1975: WESCON exhibition, MOS 6501/6502 damping
    • ​6502: $25, Intel/Motorola cut prices $179 -> $70
  • 1976: Federico Faggin founds Zilog, Z80
    • ​i8080 compatibility
  • 6502 success: KIM-1, Apple I, Apple II, Atari, Commodore, Acorn, Oric, Galeb, Orao, Ultra
  • 6800, 6502, Z80 dominated 8-bit MCU market

(*) from the book by Milan Verle 

Motorola 6800

Zilog Z80

MOS 6502

A little bit of history (cont)

  • 1970: Gary Boone of TI - first MCU 
  • All the essential circuits to form a calculator - only the display and the keypad were not incorporated
  • Breakthrough invention called TMS1802NC
  • 5k transistors, 375 bytes ROM, and 16 bytes RAM

MCU vs CPU

  • Microcontroller == MCU == uC
  • In order that the microprocessor may be used, other components such as memory must be added to it
  • In order to communicate with peripheral environment, the microprocessor must use specialised circuits added as external chips
  • Those external chips is called "I/O peripherals"
  • I/O interfaces are standardised
  • Microprocessor + peripherals + memory in one chip == microcontroller == a computer
  • It saves the time and space needed to design a device
  • Typical uC price - about 1$

A microcontroller

(*) from the book by Milan Verle 

Hardware control

  • Hardware control is performed by the CPU
  • CPU reads/writes into registers
  • There are two types of registers:
    • Core CPU registers, e.g. r0,r1.. on ARM, eax,ebx  on x86
    • Hardware registers: memory-mapped
  • Both are documented in the MCU datasheet

SFR - special function register

(*) from the book by Milan Verle 

Hardware registers

  • For example, the speed of the serial communication (UART) port is configured by the byte at address 0x1234
  • Possible values, initial state, etc - is documented in the datasheet

uC, modules, devboards

  • Typically MCUs are part of some electronic device
  • Device manufacturing goes over severals steps:
    • prototyping
    • hardware design
    • firmware development
    • product development

uC, modules, devboards (cont)

Microcontrollers

Development boards

Arduino nano

(few peripherals)

STM32F429I

(tons of peripherals)

PCB design

PCB manufacturing

Development board

is our friend

  • Get the development board
  • Get the datasheet
  • Setup the development environment
  • Typically, each MCU vendor supplies the SDK
  • We will NOT be using the SDK
  • Instead, we'll implement a bare-metal example

Blink example: bootstrap

.cpu cortex-m0
.thumb

.thumb_func
.global _start
_start:
stacktop: .word 0x20001000
.word reset
.word hang
.word hang
.word hang
.word hang

.thumb_func
reset:
    bl main
    b hang

.thumb_func
.globl hang
hang:   b .

.align
.end

Blink example: main.c

#define LED 13  // Blue LED
#define PORT 6

#define RCC ((volatile unsigned *) 0x40023800)
enum { AHB1ENR = 12 };
#define GPIO(port) ((volatile unsigned *) (0x40020000 + (port) *0x400))
#define GPIOG GPIO(PORT)
enum { MODER = 0, TYPER = 1, SPEEDR = 2, BSRR = 6, AFRL = 8, AFRH = 9 };

int main(void) {
  RCC[AHB1ENR] |= 1 << PORT;        // Enable clock on GPIOG
  GPIOG[MODER] |= 1 << (LED * 2);   // GPIO mode
  GPIOG[SPEEDR] |= 1 << (LED * 2);  // Medium speed
  GPIOG[TYPER] &= ~(1 << LED);      // Output push-pull

  for (;;) {
    GPIOG[BSRR] |= 1 << LED;
    for (volatile unsigned int i = 0; i < 1 << 18;) i++;
    GPIOG[BSRR] |= 1 << (16 + LED);
    for (volatile unsigned int i = 0; i < 1 << 18;) i++;
  }

  return 0;
}

Blink example: Makefile

TARGET	= blink
ARCH	= arm-none-eabi
CFLAGS	= -W -Wall -O2 -g -nostdlib -nostartfiles -ffreestanding  -mcpu=cortex-m0 -mthumb
AFLAGS	= --warn --fatal-warnings -mcpu=cortex-m0
OBJS	= obj/bootstrap.o obj/main.o

all : $(TARGET).bin

$(TARGET).bin: $(TARGET).elf
	$(ARCH)-objcopy -O binary $< $@

$(TARGET).elf: $(OBJS)
	$(ARCH)-ld $^ -T link.ld -o $@
# $(ARCH)-objdump -D $@ > $(TARGET).lst

obj/%.o: %.c
	@mkdir -p $(dir $@)
	$(ARCH)-gcc $(CFLAGS) -c $< -o $@

obj/%.o: %.s
	@mkdir -p $(dir $@)
	$(ARCH)-as $(AFLAGS) $< -o $@

flash: $(TARGET).bin
	st-flash write $< 0x8000000

clean:
	@rm -rf *.{bin,elf,map,lst} obj *.tgz

Thank you.

Programming microcontrollers

By Sergey Lyubka

Programming microcontrollers

  • 779