hallo,
aller Anfang ist schwer, besonders, wenn es so viele Möglichkeiten und
so viel widersprüchliche Tipps im Netz gibt. Deshalb versuche ich, den
STM32 mit möglichst wenig Werkzeug zu programmieren. Also keine standard
peripherals library oder IDE, nur arm-none-eabi-Pakete von Debian. Ob
mit oder ohne newlib wird sich noch zeigen.
Im Moment fehlt mir vor allem ein Linker Script, da geht es total
durcheinander. Per Default wird nach 0x8000 gelinkt, mit dem
redboot-Script aus der newlib nach 0x20000, aber am Anfang steht
"deregister_tm_clones"?! Für einen cortex-M3 würde ich 0x0 oder
0x08000000 erwarten (was ist besser?).
Die andere Frage: ist mein Machwerk noch halbwegs verständlich,
besonders "gpio.h" kombiniert mit "peri.ld"?
1 | CC = arm-none-eabi-gcc
|
2 | OBJCOPY = arm-none-eabi-objcopy
|
3 | OBJDUMP = arm-none-eabi-objdump
|
4 |
|
5 | CFLAGS = -mthumb -mcpu=cortex-m3 -Wall -Wextra -std=c99 -pedantic
|
6 | CFLAGS += -O2
|
7 | # CFLAGS += -nostdlib
|
8 | LDFLAGS = -T /usr/lib/arm-none-eabi/newlib/armv7-m/redboot.ld
|
9 |
|
10 | ELF = test
|
11 | SRC = main.c sleep.c
|
12 | OBJ = $(patsubst %.c, %.o, $(SRC))
|
13 |
|
14 |
|
15 | all: $(ELF)
|
16 |
|
17 | $(ELF): Makefile .depend peri.ld $(OBJ)
|
18 | $(CC) -o $(ELF) $(CFLAGS) $(OBJ) $(LDFLAGS) peri.ld
|
19 |
|
20 | dump:
|
21 | $(OBJDUMP) -d -t -C $(ELF)
|
22 |
|
23 | clean:
|
24 | rm -f $(ELF)
|
25 | rm -f $(OBJ)
|
26 | rm -f .depend
|
27 |
|
28 | .depend: $(SRC)
|
29 | $(CC) -MM $(SRC) > .depend
|
30 |
|
31 | -include .depend
|
1 | /* Linker script: memory map STM32F205C */
|
2 |
|
3 | _start = 0x8000;
|
4 |
|
5 | flash = 0x08000000;
|
6 | system_rom = 0x1FFF0000;
|
7 | otp_flash = 0x1FFF7800;
|
8 | option_bytes = 0x1FFFC000;
|
9 |
|
10 | ram = 0x20000000;
|
11 |
|
12 | peri = 0x40000000;
|
13 | tim2 = peri + 0x00000;
|
14 | tim3 = peri + 0x00400;
|
15 | gpioa = peri + 0x20000;
|
16 | gpiob = peri + 0x20400;
|
17 | gpioc = peri + 0x20800;
|
18 | gpiod = peri + 0x20C00;
|
19 | gpioe = peri + 0x21000;
|
20 | gpiof = peri + 0x21400;
|
21 | gpiog = peri + 0x21800;
|
22 | gpioh = peri + 0x21C00;
|
23 | gpioi = peri + 0x22000;
|
24 | crc = peri + 0x23000;
|
25 | rcc = peri + 0x23800;
|
26 |
|
27 | backup_ram = 0x40024000;
|
28 |
|
29 | scs = 0xE000E000;
|
30 | systick = scs + 0x010;
|
31 | scb = scs + 0xD00;
|
1 | /* STM32F205 GPIO */
|
2 | #include <stdint.h>
|
3 |
|
4 | #define __IO volatile
|
5 |
|
6 | /*!< Peripheral base address in the alias region
|
7 | #define PERIPH_BASE ((uint32_t)0x40000000)
|
8 | #define AHB1PERIPH_BASE (PERIPH_BASE + 0x00020000)
|
9 | #define GPIOD_BASE (AHB1PERIPH_BASE + 0x0C00)
|
10 | */
|
11 |
|
12 | typedef struct
|
13 | {
|
14 | __IO uint32_t moder; /* mode register */
|
15 | __IO uint32_t otyper; /* output type */
|
16 | __IO uint32_t ospeedr; /* output speed */
|
17 | __IO uint32_t pupdr; /* pull-up/pull-down */
|
18 | __IO uint32_t idr; /* input data */
|
19 | __IO uint32_t odr; /* output data */
|
20 | __IO uint32_t bsrr; /* bit set/reset register */
|
21 | __IO uint32_t lckr; /* configuration lock */
|
22 | __IO uint32_t afr[2]; /* alternate functions */
|
23 | } GPIO_struct;
|
24 |
|
25 | #define MODE_INPUT 0
|
26 | #define MODE_OUTPUT 1
|
27 | #define MODE_ALT 2
|
28 | #define MODE_ANALOG 3
|
29 | #define SPEED_LOW 0
|
30 | #define SPEED_MEDIUM 1
|
31 | #define SPEED_FAST 2
|
32 | #define SPEED_HIGH 3
|
33 | #define PULL_NONE 0
|
34 | #define PULL_UP 1
|
35 | #define PULL_DOWN 2
|
1 | /* test.h -- Board-spezifisches */
|
2 | #define LED_GELB_ON (0x01000000)
|
3 | #define LED_GELB_OFF (0x00000100)
|
4 |
|
5 | #define HSI_Hz ((int)16e6)
|
6 | #define HSE_Hz ((int)10e6)
|
7 |
|
8 | typedef struct {
|
9 | int pllclk; /* Hz */
|
10 | int apb1clk;
|
11 | int apb2clk;
|
12 | int fclk;
|
13 | int fclk_MHz;
|
14 | } board_struct;
|
15 |
|
16 | void msleep (int ms);
|
17 | void usleep (int us);
|
1 | #include "test.h"
|
2 | #include "gpio.h"
|
3 |
|
4 | extern GPIO_struct gpioa, gpiob, gpiod;
|
5 |
|
6 | void
|
7 | _exit (int rv __attribute__((unused)))
|
8 | {
|
9 | crash: goto crash;
|
10 | }
|
11 |
|
12 |
|
13 | int
|
14 | main (void)
|
15 | {
|
16 | for (;;) {
|
17 | gpiod.bsrr = LED_GELB_ON;
|
18 | msleep (200);
|
19 | gpiod.bsrr = LED_GELB_OFF;
|
20 | msleep (800);
|
21 | }
|
22 | /* return 0; */
|
23 | }
|
1 | #include <assert.h>
|
2 | #include "test.h"
|
3 | #include "scs.h"
|
4 |
|
5 | extern systick_struct systick;
|
6 |
|
7 | board_struct board = { .fclk_MHz = HSI_Hz / (int)1e6 };
|
8 |
|
9 |
|
10 | void
|
11 | msleep (int ms)
|
12 | {
|
13 | for (; ms > 0; ms--) usleep (1000);
|
14 | }
|
15 |
|
16 |
|
17 | void
|
18 | usleep (int us)
|
19 | {
|
20 | int ticks, t0;
|
21 |
|
22 | if (us < 0) return;
|
23 | //assert (us <= 1000);
|
24 |
|
25 | if (systick.csr & CLKSOURCE) {
|
26 | ticks = us * board.fclk_MHz;
|
27 | }
|
28 | else {
|
29 | ticks = (us * board.fclk_MHz) / 8; /* reset default */
|
30 | }
|
31 |
|
32 | t0 = systick.cvr - ticks;
|
33 | if (t0 < 0) {
|
34 | t0 += systick.rvr;
|
35 | while (systick.cvr < t0) __asm__("NOP");
|
36 | }
|
37 | while (systick.cvr > t0) __asm__("NOP");
|
38 | }
|