Skip to content

Commit dae9546

Browse files
committed
Initial files
0 parents  commit dae9546

File tree

12 files changed

+478
-0
lines changed

12 files changed

+478
-0
lines changed

Diff for: .gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
gen

Diff for: Makefile

+80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
# Makefile for all the examples in the STM32 Bare Library.
2+
3+
# Override this if you want to store temporary files outside of the source folder.
4+
GENDIR := ./gen/
5+
6+
# Sub-directories holding generated files.
7+
OBJDIR := $(GENDIR)/obj/
8+
ELFDIR := $(GENDIR)/elf/
9+
BINDIR := $(GENDIR)/bin/
10+
11+
# The cross-compilation toolchain prefix to use for gcc binaries.
12+
CROSS_PREFIX := arm-none-eabi
13+
AS := $(CROSS_PREFIX)-as
14+
CC := $(CROSS_PREFIX)-gcc
15+
LD := $(CROSS_PREFIX)-ld.bfd
16+
OBJCOPY := $(CROSS_PREFIX)-objcopy
17+
18+
# Debug symbols are enabled with -g, but since we compile ELFs down to bin files, these don't
19+
# affect the code size on-device.
20+
CCFLAGS := -mcpu=cortex-m3 -mthumb -g
21+
22+
# We rely on headers from Arm's CMSIS library for things like device register layouts. To
23+
# download the library, use `git clone https://github.com/ARM-software/CMSIS_5` in the parent
24+
# folder of the one this Makefile is in (not this folder, but the one above).
25+
CMSIS_DIR :=../CMSIS_5/
26+
ifeq ($(shell test -d $(CMSIS_DIR) ; echo $$?), 1)
27+
$(error "CMSIS not found at '$(CMSIS_DIR)' - try 'git clone https://github.com/ARM-software/CMSIS_5 $(CMSIS_DIR)'")
28+
endif
29+
30+
# Allow CMSIS core headers, and ones from this library.
31+
INCLUDES := \
32+
-isystem$(CMSIS_DIR)/CMSIS/Core/Include/ \
33+
-I./include
34+
35+
ASFLAGS :=
36+
37+
# Defines the offsets used when linking binaries for the STM32.
38+
LDFLAGS := -T stm32_linker_layout.lds
39+
40+
# Rule used when no target is specified.
41+
all: $(BINDIR)/examples/blink.bin $(BINDIR)/examples/hello_world.bin
42+
43+
clean:
44+
rm -rf $(GENDIR)
45+
46+
# Generic rules for generating different file types.
47+
$(OBJDIR)%.o: %.c
48+
@mkdir -p $(dir $@)
49+
$(CC) $(CCFLAGS) $(INCLUDES) -c $< -o $@
50+
51+
$(OBJDIR)%.o: %.s
52+
@mkdir -p $(dir $@)
53+
$(AS) $(ASFLAGS) $< -o $@
54+
55+
$(BINDIR)/%.bin: $(ELFDIR)/%.elf
56+
@mkdir -p $(dir $@)
57+
$(OBJCOPY) $< $@ -O binary
58+
59+
# Blink example rules.
60+
# The boot.s file need to be first in linking order, since it has to be at the start of
61+
# flash memory when the chip is reset.
62+
BLINK_SRCS := source/boot.s \
63+
$(wildcard examples/blink/*.c)
64+
BLINK_OBJS := $(addprefix $(OBJDIR), \
65+
$(patsubst %.c,%.o,$(patsubst %.s,%.o,$(BLINK_SRCS))))
66+
67+
# Link the blink example.
68+
$(ELFDIR)/examples/blink.elf: $(BLINK_OBJS)
69+
@mkdir -p $(dir $@)
70+
$(LD) $(LDFLAGS) -o $@ $(BLINK_OBJS)
71+
72+
# Hello world example rules.
73+
HELLO_WORLD_SRCS := source/boot.s \
74+
$(wildcard examples/hello_world/*.c)
75+
HELLO_WORLD_OBJS := $(addprefix $(OBJDIR), \
76+
$(patsubst %.c,%.o,$(patsubst %.s,%.o,$(HELLO_WORLD_SRCS))))
77+
78+
$(ELFDIR)/examples/hello_world.elf: $(HELLO_WORLD_OBJS)
79+
@mkdir -p $(dir $@)
80+
$(LD) $(LDFLAGS) -o $@ $(HELLO_WORLD_OBJS)

Diff for: README.md

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
git clone https://github.com/ARM-software/CMSIS_5

Diff for: examples/blink/blink_main.c

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/* Copyright 2017 Pete Warden. All Rights Reserved.
2+
Licensed under the Apache License, Version 2.0 (the "License");
3+
you may not use this file except in compliance with the License.
4+
You may obtain a copy of the License at
5+
http://www.apache.org/licenses/LICENSE-2.0
6+
Unless required by applicable law or agreed to in writing, software
7+
distributed under the License is distributed on an "AS IS" BASIS,
8+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9+
See the License for the specific language governing permissions and
10+
limitations under the License.
11+
==============================================================================*/
12+
13+
// This example shows how to write a minimal "Blue Pill" program that blinks the
14+
// LED continuously.
15+
16+
#include "led.h"
17+
#include "timers.h"
18+
19+
// You need a function named "OnReset" in your program to act like "main" in
20+
// traditional C. This will be called when the processor starts up.
21+
void OnReset(void) {
22+
// Before the LED can be accessed, the device registers need to be set up.
23+
LedInit();
24+
// We'll keep looping forever, turning the LED on and off.
25+
while (1) {
26+
LedOn();
27+
// This delay function is inefficient because it has the processor spin in
28+
// a loop executing no-ops, rather than going to sleep and saving power.
29+
// It's simpler to call though, so we'll use it for this example.
30+
BusyWaitMicroseconds(200 * 1000);
31+
LedOff();
32+
BusyWaitMicroseconds(200 * 1000);
33+
}
34+
}

Diff for: examples/hello_world/hello_world_main.c

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/* Copyright 2017 Pete Warden. All Rights Reserved.
2+
Licensed under the Apache License, Version 2.0 (the "License");
3+
you may not use this file except in compliance with the License.
4+
You may obtain a copy of the License at
5+
http://www.apache.org/licenses/LICENSE-2.0
6+
Unless required by applicable law or agreed to in writing, software
7+
distributed under the License is distributed on an "AS IS" BASIS,
8+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9+
See the License for the specific language governing permissions and
10+
limitations under the License.
11+
==============================================================================*/
12+
13+
// An example of writing a string to a connected debug system using Arm's
14+
// semihosting system. If you have openocd running and 'arm semihosting enable'
15+
// has been run, you should see "Hello World!" in the openocd console logs.
16+
17+
#include "debug_log.h"
18+
19+
// The function that's called when the chip is started.
20+
void OnReset(void) {
21+
// Output "Hello World!" to the OpenOCD console.
22+
// This call can take hundreds of milliseconds, so don't use it in
23+
// performance-critical code!
24+
DebugLog("Hello World!\n");
25+
}

Diff for: include/core_stm32.h

+109
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
/* Copyright 2017 Pete Warden. All Rights Reserved.
2+
Licensed under the Apache License, Version 2.0 (the "License");
3+
you may not use this file except in compliance with the License.
4+
You may obtain a copy of the License at
5+
http://www.apache.org/licenses/LICENSE-2.0
6+
Unless required by applicable law or agreed to in writing, software
7+
distributed under the License is distributed on an "AS IS" BASIS,
8+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9+
See the License for the specific language governing permissions and
10+
limitations under the License.
11+
==============================================================================*/
12+
13+
// Provides useful definitions for processor-specific parts of the STM32
14+
// platform, such as device register locations.
15+
16+
#ifndef INCLUDE_CORE_STM32_H
17+
#define INCLUDE_CORE_STM32_H
18+
19+
// We need a couple of STM32-specific definitions before we include the main M3
20+
// header file.
21+
typedef enum IRQn {
22+
NonMaskableInt_IRQn = -14,
23+
MemoryManagement_IRQn = -12,
24+
BusFault_IRQn = -11,
25+
UsageFault_IRQn = -10,
26+
SVCall_IRQn = -5,
27+
DebugMonitor_IRQn = -4,
28+
PendSV_IRQn = -2,
29+
SysTick_IRQn = -1,
30+
WWDG_IRQn = 0,
31+
PVD_IRQn = 1,
32+
TAMPER_IRQn = 2,
33+
RTC_IRQn = 3,
34+
FLASH_IRQn = 4,
35+
RCC_IRQn = 5,
36+
EXTI0_IRQn = 6,
37+
EXTI1_IRQn = 7,
38+
EXTI2_IRQn = 8,
39+
EXTI3_IRQn = 9,
40+
EXTI4_IRQn = 10,
41+
DMA1_Channel1_IRQn = 11,
42+
DMA1_Channel2_IRQn = 12,
43+
DMA1_Channel3_IRQn = 13,
44+
DMA1_Channel4_IRQn = 14,
45+
DMA1_Channel5_IRQn = 15,
46+
DMA1_Channel6_IRQn = 16,
47+
DMA1_Channel7_IRQn = 17,
48+
} IRQn_Type;
49+
#define __NVIC_PRIO_BITS 4
50+
51+
// This include relies on CMSIS being downloaded. See README for details.
52+
#include <core_cm3.h>
53+
54+
// Now define some device-specific structures. For more information, see
55+
// http://www.st.com/content/ccc/resource/technical/document/reference_manual/59/b9/ba/7f/11/af/43/d5/CD00171190.pdf/files/CD00171190.pdf/jcr:content/translations/en.CD00171190.pdf
56+
57+
// Reset and Clock Control Layout.
58+
typedef struct {
59+
__IO uint32_t CR; // Clock Control.
60+
__IO uint32_t CFGR; // Clock Configuration #1.
61+
__IO uint32_t CIR; // Clock Interrupt.
62+
__IO uint32_t APB2RSTR; // APB2 Peripheral Reset.
63+
__IO uint32_t APB1RSTR; // APB1 Peripheral Reset.
64+
__IO uint32_t AHBENR; // AHB Peripheral Clock.
65+
__IO uint32_t APB2ENR; // APB2 Peripheral Clock Enable.
66+
__IO uint32_t APB1ENR; // APB1 Peripheral Clock Enable.
67+
__IO uint32_t BDCR; // Backup Domain Control.
68+
__IO uint32_t CSR; // Clock Control and status.
69+
__IO uint32_t AHBRSTR; // AHB Peripheral Reset.
70+
__IO uint32_t CFGR2; // Clock Configuration #2.
71+
__IO uint32_t CFGR3; // Clock Configuration #3.
72+
} RCC_t;
73+
74+
// GPIO Control Layout.
75+
typedef struct {
76+
__IO uint32_t CRL; // Control Low.
77+
__IO uint32_t CRH; // Control High.
78+
__IO uint16_t IDR; // Port Input Data.
79+
__IO uint16_t UNUSED1; // Unused.
80+
__IO uint16_t ODR; // Output data register.
81+
__IO uint16_t UNUSED2; // Unused.
82+
__IO uint32_t BSRR; // Port Bit Set/Reset.
83+
__IO uint16_t BRR; // Bit Reset.
84+
__IO uint16_t UNUSED3; // Unused.
85+
__IO uint32_t LCKR; // Port Configuration Lock.
86+
} GPIO_t;
87+
88+
// Addresses of peripherals.
89+
#define RCC_BASE ((uint32_t)0x40021000)
90+
#define GPIOA_BASE ((uint32_t)0x40010800)
91+
#define GPIOB_BASE ((uint32_t)0x40010C00)
92+
#define GPIOC_BASE ((uint32_t)0x40011000)
93+
94+
// Globals for accessing peripherals.
95+
#define RCC ((RCC_t*)RCC_BASE)
96+
#define GPIOA ((GPIO_t*)GPIOA_BASE)
97+
#define GPIOB ((GPIO_t*)GPIOB_BASE)
98+
#define GPIOC ((GPIO_t*)GPIOC_BASE)
99+
100+
// Register access values.
101+
#define RCC_GPIOA_ENABLE (0x04)
102+
#define RCC_GPIOB_ENABLE (0x08)
103+
#define RCC_GPIOC_ENABLE (0x10)
104+
105+
#define GPIO_MODE_OUT_2 (0x02)
106+
#define GPIO_CONF_GP_UD (0x0)
107+
#define GPIO_CONF_GP_OD (0x4)
108+
109+
#endif // INCLUDE_CORE_STM32_H

Diff for: include/debug_log.h

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/* Copyright 2017 Pete Warden. All Rights Reserved.
2+
Licensed under the Apache License, Version 2.0 (the "License");
3+
you may not use this file except in compliance with the License.
4+
You may obtain a copy of the License at
5+
http://www.apache.org/licenses/LICENSE-2.0
6+
Unless required by applicable law or agreed to in writing, software
7+
distributed under the License is distributed on an "AS IS" BASIS,
8+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9+
See the License for the specific language governing permissions and
10+
limitations under the License.
11+
==============================================================================*/
12+
13+
// Output strings to a debug console, using semihosting.
14+
// You'll need to enable this option in the OpenOCD configuration using:
15+
// arm semihosting enable
16+
17+
#ifndef INCLUDE_DEBUG_LOG_H
18+
#define INCLUDE_DEBUG_LOG_H
19+
20+
// Writes a string to the OpenOCD debug console. This can take hundreds of
21+
// milliseconds, so don't call this in performance-intensive code.
22+
static inline void DebugLog(char* s) {
23+
asm("mov r0, #0x04\n" // SYS_WRITE0
24+
"mov r1, %[str]\n"
25+
"bkpt #0xAB\n"
26+
:
27+
: [str] "r"(s)
28+
: "r0", "r1");
29+
}
30+
31+
#endif // INCLUDE_DEBUG_LOG_H

Diff for: include/led.h

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/* Copyright 2017 Pete Warden. All Rights Reserved.
2+
Licensed under the Apache License, Version 2.0 (the "License");
3+
you may not use this file except in compliance with the License.
4+
You may obtain a copy of the License at
5+
http://www.apache.org/licenses/LICENSE-2.0
6+
Unless required by applicable law or agreed to in writing, software
7+
distributed under the License is distributed on an "AS IS" BASIS,
8+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9+
See the License for the specific language governing permissions and
10+
limitations under the License.
11+
==============================================================================*/
12+
13+
// Control the LED on a "Blue Pill" STM32-compatible board.
14+
15+
#ifndef INCLUDE_LED_H
16+
#define INCLUDE_LED_H
17+
18+
#include "core_stm32.h"
19+
20+
// Known location of the LED on the "Blue Pill" STM32 SoCs.
21+
#define LED_PORT (13)
22+
23+
// This needs to be called before the LED can be accessed.
24+
static inline void LedInit() {
25+
// Enable GPIOC.
26+
RCC->APB2ENR |= RCC_GPIOC_ENABLE;
27+
28+
// Set up speed and configuration.
29+
const int shift = (LED_PORT - 8) * 4;
30+
const uint32_t old_config = GPIOC->CRH;
31+
const uint32_t cleared_config = (old_config & ~(0xf << shift));
32+
GPIOC->CRH = cleared_config | ((GPIO_MODE_OUT_2 | GPIO_CONF_GP_OD) << shift);
33+
}
34+
35+
// LedInit() must be called before these will work.
36+
static inline void LedOn() { GPIOC->BSRR = (1 << (LED_PORT + 16)); }
37+
static inline void LedOff() { GPIOC->BSRR = (1 << LED_PORT); }
38+
39+
#endif // INCLUDE_LED_H

Diff for: include/timers.h

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/* Copyright 2017 Pete Warden. All Rights Reserved.
2+
Licensed under the Apache License, Version 2.0 (the "License");
3+
you may not use this file except in compliance with the License.
4+
You may obtain a copy of the License at
5+
http://www.apache.org/licenses/LICENSE-2.0
6+
Unless required by applicable law or agreed to in writing, software
7+
distributed under the License is distributed on an "AS IS" BASIS,
8+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9+
See the License for the specific language governing permissions and
10+
limitations under the License.
11+
==============================================================================*/
12+
13+
// Timer utilities for the "Blue Pill" STM32 board.
14+
15+
#ifndef INCLUDE_TIMERS_H
16+
#define INCLUDE_TIMERS_H
17+
18+
#include <stdint.h>
19+
20+
// Spin in a loop for roughly the specified number of microseconds. This is
21+
// using instruction timing, so it's not precise, and the processor will be
22+
// consuming power while this is running.
23+
static inline void BusyWaitMicroseconds(int32_t us) {
24+
// Each loop takes very roughly one microsecond on a Blue Pill.
25+
volatile int32_t count = us;
26+
for (; count > 0; --count)
27+
;
28+
}
29+
30+
#endif // INCLUDE_TIMERS_H

0 commit comments

Comments
 (0)