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
- Tools like Altium, PowerPCB, Eagle, etc
- End-result is gerber files, send to printing houses
- Example prototype printing: https://www.youtube.com/watch?v=qDbFOsLjMD8
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