Skip to content

Commit

Permalink
added systick and clock examples
Browse files Browse the repository at this point in the history
  • Loading branch information
fcayci committed Mar 15, 2017
0 parents commit 7469fa4
Show file tree
Hide file tree
Showing 8 changed files with 608 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
*.o
*.bin
*.elf
*.hex
*.lst
32 changes: 32 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# stm32f1-bare-metal

Bare-metal programming for a STM32F1-based board. (Cortex-M3)

Tested on EasyMx Pro v7 board with STM32F107 chip.

# Install
* Toolchain - [GNU ARM Toolchain](https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads)
* (Windows only) - [MinGW and MSYS ](http://www.mingw.org/)
* Programmer - [STLink](https://github.com/texane/stlink)

# Compile
* Browse into any of the project directory `cd systick` and run `make` to compile.
```
Cleaning...
Building systick.c
text data bss dec hex filename
384 0 0 384 180 systick.elf
Successfully finished...
```

# Program
* Run `make burn` to program the chip.
```
...
...
Flash written and verified! jolly good!
```

## Projects
* systick - SysTick Timer example
* clock - An example to bump the clock up to 72 Mhz
208 changes: 208 additions & 0 deletions clock/clock.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
/*
* clock.c
*
* Description:
* Clock example to set the MCU speed to 72 MHz
* GPIOD Pin1 is the blinking LED
*
* Author: Furkan Cayci
*
* Project Setup:
* EasyMX Pro V7 board
* Cortex-M3 arch
* STM32F107 chip
*/

/*************************************************
* Definitions
*************************************************/
// Define some types for readibility
#define int32_t int
#define int16_t short
#define int8_t char
#define uint32_t unsigned int
#define uint16_t unsigned short
#define uint8_t unsigned char

#define HSE_Value ((uint32_t) 25000000) /* Value of the External oscillator in Hz */
#define HSI_Value ((uint32_t) 8000000) /* Value of the Internal oscillator in Hz*/

// Define the base addresses for peripherals
#define PERIPH_BASE ((uint32_t) 0x40000000)
#define SRAM_BASE ((uint32_t) 0x20000000)

#define APB1PERIPH_BASE PERIPH_BASE
#define APB2PERIPH_BASE (PERIPH_BASE + 0x10000)
#define AHBPERIPH_BASE (PERIPH_BASE + 0x20000)

#define GPIOD_BASE (APB2PERIPH_BASE + 0x1400) // GPIOD base address is 0x40011400
#define RCC_BASE (AHBPERIPH_BASE + 0x1000) // RCC base address is 0x40021000
#define FLASH_BASE (AHBPERIPH_BASE + 0x2000) // FLASH base address is 0x40022000

#define STACKINIT 0x20008000
#define DELAY 7200000

#define GPIOD ((GPIO_type *) GPIOD_BASE)
#define RCC ((RCC_type *) RCC_BASE)
#define FLASH ((FLASH_type *) FLASH_BASE)

/*
* Register Addresses
*/
typedef struct
{
uint32_t CRL; /* GPIO port configuration register low, Address offset: 0x00 */
uint32_t CRH; /* GPIO port configuration register high, Address offset: 0x04 */
uint32_t IDR; /* GPIO port input data register, Address offset: 0x08 */
uint32_t ODR; /* GPIO port output data register, Address offset: 0x0C */
uint32_t BSRR; /* GPIO port bit set/reset register, Address offset: 0x10 */
uint32_t BRR; /* GPIO port bit reset register, Address offset: 0x14 */
uint32_t LCKR; /* GPIO port configuration lock register, Address offset: 0x18 */
} GPIO_type;

typedef struct
{
uint32_t CR; /* RCC clock control register, Address offset: 0x00 */
uint32_t CFGR; /* RCC clock configuration register, Address offset: 0x04 */
uint32_t CIR; /* RCC clock interrupt register, Address offset: 0x08 */
uint32_t APB2RSTR; /* RCC APB2 peripheral reset register, Address offset: 0x0C */
uint32_t APB1RSTR; /* RCC APB1 peripheral reset register, Address offset: 0x10 */
uint32_t AHBENR; /* RCC AHB peripheral clock enable register, Address offset: 0x14 */
uint32_t APB2ENR; /* RCC APB2 peripheral clock enable register, Address offset: 0x18 */
uint32_t APB1ENR; /* RCC APB1 peripheral clock enable register, Address offset: 0x1C */
uint32_t BDCR; /* RCC backup domain control register, Address offset: 0x20 */
uint32_t CSR; /* RCC control/status register, Address offset: 0x24 */
uint32_t AHBRSTR; /* RCC AHB peripheral clock reset register, Address offset: 0x28 */
uint32_t CFGR2; /* RCC clock configuration register2, Address offset: 0x2C */
} RCC_type;

typedef struct
{
uint32_t ACR;
uint32_t KEYR;
uint32_t OPTKEYR;
uint32_t SR;
uint32_t CR;
uint32_t AR;
uint32_t RESERVED;
uint32_t OBR;
uint32_t WRPR;
} FLASH_type;

// Function declarations. Add your functions here
void nmi_handler(void);
void set_system_clock_to_25Mhz(void);
void set_system_clock_to_72Mhz(void);
int32_t main(void);
void delay(volatile uint32_t s);

/*************************************************
* Vector Table
*************************************************/
// Attribute puts table in .vector section
// which is the beginning of .text section in the linker script
// Add other vectors in order here
// Vector table can be found on page 197 in RM0008
uint32_t (* const vector_table[])
__attribute__ ((section(".vectors"))) = {
((uint32_t *) STACKINIT), /* 0x00 Stack Pointer */
((uint32_t *) main), /* 0x04 Reset */
0, /* 0x08 NMI */
0, /* 0x0C Hardfault */
};

/*
* By default 8 MHz internal clock is used (HSI)
* Set up as 25 MHz
*
* 25 MHz External clock is selected as the source clock (HSE)
*/
void set_system_clock_to_25Mhz(void)
{
// Enable HSE
RCC->CR |= (1 << 16);
// Wait untill HSE settles down
while (!(RCC->CR & (1 << 17)));
// Choose HSE as the system clock
RCC->CFGR |= (1 << 0);
}

/*
* By default 8 MHz internal clock is used (HSI)
* Set up as 72 MHz
*
* HSE -> PreDiv2 -> Pll2Mul -> PreDiv1 -> PllMul -> System Clock
* Set Prediv1Src = PLL2, Set PllSrc as Prediv1
*
* 25 MHz External clock is selected as the source clock (HSE)
* It is divided by 5 with PreDiv2, then muliplied by 8 with Pll2Mul
* Then it is divided by 5 with PreDiv1, then multiplied by 9 with PllMul
* Then choose Pll as the clock source
*
* 25Mhz / 5 * 8 / 5 * 9 = 72 MHz
*/
void set_system_clock_to_72Mhz(void)
{
// Necessary wait states for Flash for high speeds
FLASH->ACR = 0x12;
// Enable HSE
RCC->CR |= (1 << 16);
// Wait untill HSE settles down
while (!(RCC->CR & (1 << 17)));
// Set PREDIV2 division factor to 5
RCC->CFGR2 |= (0b0100 << 4);
// Set PLL2 multiplication factor to 8
RCC->CFGR2 |= (0b0110 << 8);
// Enable PLL2
RCC->CR |= (1 << 26);
// Wait untill PLL2 settles down
while (!(RCC->CR & (1 << 27)));
// Set PLL2 as PREDIV1 clock source
RCC->CFGR2 |= (1 << 16);
// Set PREDIV1 division factor to 5
RCC->CFGR2 |= (0b0100 << 0);
// Select Prediv1 as PLL source
RCC->CFGR |= (1 << 16);
// Set PLL1 multiplication factor to 9
RCC->CFGR |= (0b0111 << 18);
// Set APB1 to 36MHz
RCC->CFGR |= 1 << 10;
// Enable PLL
RCC->CR |= (1 << 24);
// Wait untill PLL settles down
while (!(RCC->CR & (1 << 25)));
// Finally, choose PLL as the system clock
RCC->CFGR |= (0b10 << 0);
}

/*************************************************
* Main code starts from here
*************************************************/
int32_t main(void)
{
// Set clock to 72 MHz
set_system_clock_to_72Mhz();

// Set Bit 5 to enable GPIOD clock
RCC->APB2ENR |= (1 << 5);

// Set GPIOD Pin1 output
GPIOD->CRL &= ~(0xF << 4);
GPIOD->CRL |= (0x2 << 4);

// Set GPIOD Pin1
GPIOD->ODR |= (1 << 1);

while(1){
delay(DELAY);
GPIOD->ODR ^= (1 << 1);
}

// Should never reach here
return 0;
}

void delay(volatile uint32_t s)
{
for(s; s>0; s--);
}
64 changes: 64 additions & 0 deletions clock/makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
TARGET = clock
SRCS = clock.c

OBJS = $(addsuffix .o, $(basename $(SRCS)))
INCLUDES = -I.

LINKER_SCRIPT = stm32.ld

CFLAGS += -mcpu=cortex-m3 -mthumb # Processor setup
CFLAGS += -O0 # Optimization is off
CFLAGS += -g3 # Generate debug information
CFLAGS += -fno-common -Wall
CFLAGS += -ffunction-sections -fdata-sections -Wl,--gc-sections

LDFLAGS += -nostartfiles -T$(LINKER_SCRIPT)

CROSS_COMPILE = arm-none-eabi-
CC = $(CROSS_COMPILE)gcc
LD = $(CROSS_COMPILE)ld
OBJDUMP = $(CROSS_COMPILE)objdump
OBJCOPY = $(CROSS_COMPILE)objcopy
SIZE = $(CROSS_COMPILE)size

all: clean $(SRCS) build size
@echo "Successfully finished..."

build: $(TARGET).elf $(TARGET).hex $(TARGET).bin $(TARGET).lst

$(TARGET).elf: $(OBJS)
@$(CC) $(LDFLAGS) $(OBJS) -o $@

%.o: %.c
@echo "Building" $<
@$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@

%.o: %.s
@echo "Building" $<
@$(CC) $(CFLAGS) -c $< -o $@

%.hex: %.elf
@$(OBJCOPY) -O ihex $< $@

%.bin: %.elf
@$(OBJCOPY) -O binary $< $@

%.lst: %.elf
@$(OBJDUMP) -x -S $(TARGET).elf > $@

size: $(TARGET).elf
@$(SIZE) $(TARGET).elf

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

clean:
@echo "Cleaning..."
@rm -f $(TARGET).elf
@rm -f $(TARGET).bin
@rm -f $(TARGET).map
@rm -f $(TARGET).hex
@rm -f $(TARGET).lst
@rm -f $(TARGET).o

.PHONY: all build size clean burn
25 changes: 25 additions & 0 deletions clock/stm32.ld
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
MEMORY {
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 64K
rom (rx) : ORIGIN = 0x08000000, LENGTH = 256K
}

SECTIONS {
. = 0x08000000; /* From 0x08000000 */
.text :
{
*(.vectors) /* Vector table */
*(.text) /* Program code */
*(.rodata) /* Read only data */
} >rom

. = 0x20000000; /* From 0x20000000 */
.data :
{
*(.data) /* Data memory */
} >ram AT > rom

.bss :
{
*(.bss) /* Zero-filled run time allocate data memory */
} >ram AT > rom
}
Loading

0 comments on commit 7469fa4

Please sign in to comment.