Initial commit, demo works
This commit is contained in:
commit
7bc4391185
31 changed files with 3370 additions and 0 deletions
19
.gitmodules
vendored
Normal file
19
.gitmodules
vendored
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
[submodule "demo/fw/tinyprintf"]
|
||||
path = demo/fw/tinyprintf
|
||||
url = https://github.com/cjlano/tinyprintf
|
||||
[submodule "upstream/PyCortexMDebug"]
|
||||
path = upstream/PyCortexMDebug
|
||||
url = https://github.com/bnahill/PyCortexMDebug
|
||||
[submodule "upstream/stm32square"]
|
||||
path = upstream/stm32square
|
||||
url = https://gitlab.com/neinseg/stm32square
|
||||
branch = release
|
||||
[submodule "upstream/STM32CubeF4"]
|
||||
path = upstream/STM32CubeF4
|
||||
url = https://github.com/STMicroelectronics/STM32CubeF4
|
||||
[submodule "upstream/cmsis_device_f4"]
|
||||
path = upstream/cmsis_device_f4
|
||||
url = https://github.com/STMicroelectronics/cmsis_device_f4
|
||||
[submodule "upstream/CMSIS_5"]
|
||||
path = upstream/CMSIS_5
|
||||
url = https://github.com/ARM-software/CMSIS_5
|
||||
2
demo/fw/.gitignore
vendored
Normal file
2
demo/fw/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
build
|
||||
venv
|
||||
172
demo/fw/Makefile
Normal file
172
demo/fw/Makefile
Normal file
|
|
@ -0,0 +1,172 @@
|
|||
|
||||
########################################################################################################################
|
||||
# Dependency directories
|
||||
########################################################################################################################
|
||||
|
||||
CUBE_CMSIS_DIR ?= ../../upstream/cmsis_device_f4
|
||||
CMSIS_DIR ?= ../../upstream/CMSIS_5
|
||||
MUSL_DIR ?= ../../upstream/musl
|
||||
|
||||
########################################################################################################################
|
||||
# Sources
|
||||
########################################################################################################################
|
||||
|
||||
C_SOURCES := src/main.c
|
||||
C_SOURCES += src/con_usart.c
|
||||
C_SOURCES += src/serial.c
|
||||
C_SOURCES += src/spi.c
|
||||
C_SOURCES += src/gpio_helpers.c
|
||||
C_SOURCES += src/dma_util.c
|
||||
C_SOURCES += tinyprintf/tinyprintf.c
|
||||
|
||||
MUSL_SOURCES :=
|
||||
MUSL_SOURCES := $(addprefix $(MUSL_DIR)/src/,$(MUSL_SOURCES))
|
||||
|
||||
C_SOURCES += $(MUSL_SOURCES)
|
||||
|
||||
CXX_SOURCES +=
|
||||
|
||||
BUILDDIR ?= build
|
||||
BINARY := tachibana-demo.elf
|
||||
LDSCRIPT := stm32f407.ld
|
||||
|
||||
########################################################################################################################
|
||||
# Build parameters
|
||||
########################################################################################################################
|
||||
|
||||
PREFIX ?= arm-none-eabi-
|
||||
|
||||
DEBUG ?= 1
|
||||
|
||||
CC := $(PREFIX)gcc
|
||||
CXX := $(PREFIX)g++
|
||||
LD := $(PREFIX)gcc
|
||||
AR := $(PREFIX)ar
|
||||
AS := $(PREFIX)as
|
||||
SIZE := $(PREFIX)size
|
||||
NM := $(PREFIX)nm
|
||||
OBJCOPY := $(PREFIX)objcopy
|
||||
OBJDUMP := $(PREFIX)objdump
|
||||
GDB := $(PREFIX)gdb
|
||||
|
||||
HOST_CC ?= $(HOST_PREFIX)gcc
|
||||
HOST_CXX ?= $(HOST_PREFIX)g++
|
||||
HOST_LD ?= $(HOST_PREFIX)gcc
|
||||
HOST_AR ?= $(HOST_PREFIX)ar
|
||||
HOST_AS ?= $(HOST_PREFIX)as
|
||||
HOST_OBJCOPY ?= $(HOST_PREFIX)objcopy
|
||||
HOST_OBJDUMP ?= $(HOST_PREFIX)objdump
|
||||
|
||||
PYTHON3 ?= python3
|
||||
DOT ?= dot
|
||||
|
||||
CMSIS_DIR_ABS := $(abspath $(CMSIS_DIR))
|
||||
MSPDEBUG_DIR_ABS := $(abspath $(MSPDEBUG_DIR))
|
||||
LIBSODIUM_DIR_ABS := $(abspath $(LIBSODIUM_DIR))
|
||||
TINYAES_DIR_ABS := $(abspath $(TINYAES_DIR))
|
||||
MUSL_DIR_ABS := $(abspath $(MUSL_DIR))
|
||||
|
||||
ARCH_FLAGS ?= -mthumb -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16
|
||||
SYSTEM_FLAGS ?= -nostdlib -ffreestanding -nostartfiles
|
||||
|
||||
#CFLAGS += -I$(abspath musl_include_shims)
|
||||
CFLAGS += -I$(CUBE_CMSIS_DIR)/Include -I$(CMSIS_DIR)/CMSIS/Core/Include
|
||||
CFLAGS += -Itinyprintf
|
||||
COMMON_CFLAGS += -I$(BUILDDIR) -Isrc
|
||||
|
||||
COMMON_CFLAGS += -O0 -std=gnu11 -g -DSTM32F407xx -DSTM32F4 -DDEBUG=$(DEBUG)
|
||||
CFLAGS += $(ARCH_FLAGS) $(SYSTEM_FLAGS)
|
||||
#SIM_CFLAGS += -mthumb -mcpu=cortex-m4 -mfloat-abi=soft
|
||||
CFLAGS += -fno-common -ffunction-sections -fdata-sections
|
||||
|
||||
# for musl
|
||||
#CFLAGS += -Dhidden=
|
||||
|
||||
SIM_CFLAGS += -lm -DSIMULATION
|
||||
SIM_CFLAGS += -Wall -Wextra -Wpedantic -Wshadow -Wimplicit-function-declaration -Wundef -Wno-unused-parameter
|
||||
|
||||
INT_CFLAGS += -Wall -Wextra -Wpedantic -Wshadow -Wimplicit-function-declaration -Wundef -Wno-unused-parameter
|
||||
INT_CFLAGS += -Wredundant-decls -Wmissing-prototypes -Wstrict-prototypes
|
||||
|
||||
CXXFLAGS += -Os -g
|
||||
CXXFLAGS += $(ARCH_FLAGS) $(SYSTEM_FLAGS)
|
||||
CXXFLAGS += -fno-common -ffunction-sections -fdata-sections
|
||||
CXXFLAGS += -Wall -Wextra -Wshadow -Wundef -Wredundant-decls
|
||||
CXXFLAGS += -I.
|
||||
|
||||
LDFLAGS += $(ARCH_FLAGS) $(SYSTEM_FLAGS)
|
||||
|
||||
LIBS += -lgcc
|
||||
LDFLAGS += -Wl,--gc-sections
|
||||
|
||||
LINKMEM_FLAGS ?= --trim-stubs=startup_stm32f407xx.o --trace-sections .isr_vector --highlight-subdirs $(BUILDDIR)
|
||||
|
||||
OBJS := $(addprefix $(BUILDDIR)/,$(C_SOURCES:.c=.o) $(CXX_SOURCES:.cpp=.o))
|
||||
|
||||
ALL_OBJS := $(OBJS)
|
||||
ALL_OBJS += $(BUILDDIR)/src/startup_stm32f407xx.o
|
||||
ALL_OBJS += $(BUILDDIR)/src/system_stm32f4xx.o
|
||||
|
||||
########################################################################################################################
|
||||
# Rules
|
||||
########################################################################################################################
|
||||
|
||||
all: binsize
|
||||
|
||||
.PHONY: binsize
|
||||
binsize: $(BUILDDIR)/$(BINARY) $(BUILDDIR)/$(BINARY:.elf=-symbol-sizes.pdf)
|
||||
$(LD) -T$(LDSCRIPT) $(LDFLAGS) -Wl,--print-memory-usage -o /dev/null $(ALL_OBJS) $(LIBS)
|
||||
@echo
|
||||
@echo "▐▬▬▬▌ SyMbOL sIzE HiGhScORe LiSt ▐▬▬▬▌"
|
||||
$(NM) --print-size --size-sort --radix=d $< | tail -n 20
|
||||
|
||||
# $(BUILDDIR)/generated/dsss_butter_filter.h
|
||||
$(BUILDDIR)/generated: ; mkdir -p $@
|
||||
|
||||
.PRECIOUS: $(BUILDDIR)/$(BINARY)
|
||||
$(BUILDDIR)/$(BINARY) $(BUILDDIR)/$(BINARY:.elf=.map) &: $(ALL_OBJS)
|
||||
$(LD) -T$(LDSCRIPT) $(LDFLAGS) -o $@ -Wl,-Map=$(BUILDDIR)/$(BINARY:.elf=.map) $^ $(LIBS)
|
||||
|
||||
build/$(BINARY:.elf=-symbol-sizes.dot): $(ALL_OBJS)
|
||||
$(PYTHON3) tools/linkmem.py $(LINKMEM_FLAGS) $(LD) -T$(LDSCRIPT) $(LDFLAGS) $^ $(LIBS) > $@
|
||||
|
||||
%.pdf: %.dot
|
||||
$(DOT) -T pdf $< -o $@
|
||||
|
||||
%.dot: %.elf
|
||||
r2 -a arm -qc 'aa;agRd' $< 2>/dev/null >$@
|
||||
|
||||
$(BUILDDIR)/src/%.o: src/%.s
|
||||
mkdir -p $(@D)
|
||||
$(CC) $(COMMON_CFLAGS) $(CFLAGS) $(INT_CFLAGS) -o $@ -c $<
|
||||
|
||||
$(BUILDDIR)/src/%.o: src/%.c
|
||||
mkdir -p $(@D)
|
||||
$(CC) $(COMMON_CFLAGS) $(CFLAGS) $(INT_CFLAGS) -o $@ -c $<
|
||||
|
||||
$(BUILDDIR)/src/%.o: src/%.cpp
|
||||
mkdir -p $(@D)
|
||||
$(CXX) $(CXXFLAGS) -o $@ -c $<
|
||||
|
||||
$(BUILDDIR)/generated/%.o: $(BUILDDIR)/generated/%.c
|
||||
mkdir -p $(@D)
|
||||
$(CC) $(COMMON_CFLAGS) $(CFLAGS) $(INT_CFLAGS) -o $@ -c $<
|
||||
|
||||
$(BUILDDIR)/%.o: %.c
|
||||
mkdir -p $(@D)
|
||||
$(CC) $(COMMON_CFLAGS) $(CFLAGS) $(EXT_CFLAGS) -o $@ -c $<
|
||||
|
||||
clean:
|
||||
rm -rf $(BUILDDIR)/src
|
||||
rm -rf $(BUILDDIR)/generated
|
||||
rm -f $(BUILDDIR)/$(BINARY)
|
||||
rm -f $(BUILDDIR)/$(BINARY:.elf=.map)
|
||||
rm -f $(BUILDDIR)/$(BINARY:.elf=-symbol-sizes.dot)
|
||||
rm -f $(BUILDDIR)/$(BINARY:.elf=-symbol-sizes.pdf)
|
||||
|
||||
mrproper: clean
|
||||
rm -rf build
|
||||
|
||||
.PHONY: clean mrproper
|
||||
|
||||
-include $(OBJS:.o=.d)
|
||||
16
demo/fw/openocd.cfg
Normal file
16
demo/fw/openocd.cfg
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
telnet_port 4444
|
||||
gdb_port 3333
|
||||
|
||||
source [find interface/stlink-v2.cfg]
|
||||
#interface jlink
|
||||
#interface stlink-v2
|
||||
#adapter_khz 10000
|
||||
#transport select swd
|
||||
|
||||
#source /usr/share/openocd/scripts/target/stm32f0x.cfg
|
||||
source [find target/stm32f4x.cfg]
|
||||
|
||||
init
|
||||
arm semihosting enable
|
||||
|
||||
#flash bank sysflash.alias stm32f0x 0x00000000 0 0 0 $_TARGETNAME
|
||||
54
demo/fw/src/con_usart.c
Normal file
54
demo/fw/src/con_usart.c
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* This file is part of the tachibana project
|
||||
*
|
||||
* Copyright (C) 2021 jaseg <code@jaseg.de>
|
||||
*
|
||||
*
|
||||
* libusbhost is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <stm32f4_isr.h>
|
||||
#include "con_usart.h"
|
||||
|
||||
volatile struct usart_desc con_usart = {
|
||||
.le_usart = USART1,
|
||||
.le_usart_irqn = USART1_IRQn,
|
||||
.tx_dmas = DMA2_Stream7,
|
||||
.tx_dma_sn = 7,
|
||||
.tx_dma_ch = 4,
|
||||
.tx_dma = DMA2,
|
||||
.tx_dma_irqn = DMA2_Stream7_IRQn,
|
||||
};
|
||||
|
||||
void con_usart_init() {
|
||||
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN | RCC_AHB1ENR_DMA2EN;
|
||||
RCC->APB2ENR |= RCC_APB2ENR_USART1EN;
|
||||
|
||||
/* GPIO config: A9 (TX), A10 (RX) */
|
||||
GPIOA->MODER &= ~GPIO_MODER_MODER9_Msk & ~GPIO_MODER_MODER10_Msk;
|
||||
GPIOA->MODER |= (2<<GPIO_MODER_MODER9_Pos) | (2<<GPIO_MODER_MODER10_Pos);
|
||||
GPIOA->OSPEEDR &= ~GPIO_OSPEEDR_OSPEED9_Msk & ~GPIO_OSPEEDR_OSPEED10_Msk;
|
||||
GPIOA->OSPEEDR |= (2<<GPIO_OSPEEDR_OSPEED9_Pos) | (2<<GPIO_OSPEEDR_OSPEED10_Pos);
|
||||
GPIOA->AFR[1] &= ~GPIO_AFRH_AFSEL9_Msk & ~GPIO_AFRH_AFSEL10_Msk;
|
||||
GPIOA->AFR[1] |= (7<<GPIO_AFRH_AFSEL9_Pos) | (7<<GPIO_AFRH_AFSEL10_Pos);
|
||||
|
||||
usart_dma_init(&con_usart, CON_USART_BAUDRATE);
|
||||
}
|
||||
|
||||
void DMA2_Stream7_IRQHandler(void) {
|
||||
usart_dma_stream_irq(&con_usart);
|
||||
}
|
||||
|
||||
38
demo/fw/src/con_usart.h
Normal file
38
demo/fw/src/con_usart.h
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* This file is part of the tachibana project
|
||||
*
|
||||
* Copyright (C) 2021 jaseg <code@jaseg.de>
|
||||
*
|
||||
*
|
||||
* libusbhost is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __CON_USART_H__
|
||||
#define __CON_USART_H__
|
||||
|
||||
#include "serial.h"
|
||||
|
||||
extern volatile struct usart_desc con_usart;
|
||||
|
||||
#define con_printf(...) usart_printf(&con_usart, __VA_ARGS__)
|
||||
#define con_printf_blocking(...) usart_printf_blocking(&con_usart, __VA_ARGS__)
|
||||
|
||||
#ifndef CON_USART_BAUDRATE
|
||||
#define CON_USART_BAUDRATE 500000
|
||||
#endif
|
||||
|
||||
void con_usart_init(void);
|
||||
|
||||
#endif /* __CON_USART_H__ */
|
||||
46
demo/fw/src/dma_util.c
Normal file
46
demo/fw/src/dma_util.c
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
|
||||
#include <assert.h>
|
||||
|
||||
#include "dma_util.h"
|
||||
|
||||
uint8_t dma_get_isr_and_clear(DMA_TypeDef *dma, int ch) {
|
||||
uint8_t isr_val;
|
||||
switch(ch) {
|
||||
case 0:
|
||||
isr_val = dma->LISR & 0x3f;
|
||||
dma->LIFCR = isr_val;
|
||||
return isr_val;
|
||||
case 1:
|
||||
isr_val = dma->LISR>>6 & 0x3f;
|
||||
dma->LIFCR = isr_val<<6;
|
||||
return isr_val;
|
||||
case 2:
|
||||
isr_val = dma->LISR>>16 & 0x3f;
|
||||
dma->LIFCR = isr_val<<16;
|
||||
return isr_val;
|
||||
case 3:
|
||||
isr_val = dma->LISR>>6>>16 & 0x3f;
|
||||
dma->LIFCR = isr_val<<6<<16;
|
||||
return isr_val;
|
||||
case 4:
|
||||
isr_val = dma->HISR & 0x3f;
|
||||
dma->HIFCR = isr_val;
|
||||
return isr_val;
|
||||
case 5:
|
||||
isr_val = dma->HISR>>6 & 0x3f;
|
||||
dma->HIFCR = isr_val<<6;
|
||||
return isr_val;
|
||||
case 6:
|
||||
isr_val = dma->HISR>>16 & 0x3f;
|
||||
dma->HIFCR = isr_val<<16;
|
||||
return isr_val;
|
||||
case 7:
|
||||
isr_val = dma->HISR>>6>>16 & 0x3f;
|
||||
dma->HIFCR = isr_val<<6<<16;
|
||||
return isr_val;
|
||||
default:
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
10
demo/fw/src/dma_util.h
Normal file
10
demo/fw/src/dma_util.h
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
#ifndef __DMA_UTIL_H__
|
||||
#define __DMA_UTIL_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "jl_global.h"
|
||||
|
||||
uint8_t dma_get_isr_and_clear(DMA_TypeDef *dma, int ch);
|
||||
|
||||
#endif /* __DMA_UTIL_H__ */
|
||||
46
demo/fw/src/gpio_helpers.c
Normal file
46
demo/fw/src/gpio_helpers.c
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
|
||||
#include "gpio_helpers.h"
|
||||
|
||||
void gpio_pin_mode(GPIO_TypeDef *gpio, int pin, int mode) {
|
||||
gpio->MODER &= ~(3 << (2*pin));
|
||||
gpio->MODER |= mode << (2*pin);
|
||||
}
|
||||
|
||||
void gpio_pin_setup(GPIO_TypeDef *gpio, int pin, int mode, int speed, int pullups, int afsel) {
|
||||
int gpio_idx = ((uint32_t)gpio>>10) & 0xf;
|
||||
RCC->AHB1ENR |= 1<<gpio_idx;
|
||||
|
||||
gpio->MODER &= ~(3 << (2*pin));
|
||||
gpio->MODER |= mode << (2*pin);
|
||||
gpio->OSPEEDR &= ~(3 << (2*pin));
|
||||
gpio->OSPEEDR |= speed << (2*pin);
|
||||
gpio->PUPDR &= ~(3 << (2*pin));
|
||||
gpio->PUPDR |= pullups << (2*pin);
|
||||
gpio->AFR[pin>>3] &= ~(0xf << (4*(pin&7)));
|
||||
gpio->AFR[pin>>3] |= afsel << (4*(pin&7));
|
||||
gpio->BSRR = 1<<pin<<16;
|
||||
}
|
||||
|
||||
void gpio_pin_output(GPIO_TypeDef *gpio, int pin, int speed) {
|
||||
gpio_pin_setup(gpio, pin, 1, speed, 0, 0);
|
||||
}
|
||||
|
||||
void gpio_pin_tristate(GPIO_TypeDef *gpio, int pin, int tristate) {
|
||||
if (tristate)
|
||||
gpio->MODER &= ~(3 << (2*pin));
|
||||
else
|
||||
gpio->MODER |= 1 << (2*pin);
|
||||
}
|
||||
|
||||
void gpio_pin_input(GPIO_TypeDef *gpio, int pin, int pullups) {
|
||||
gpio_pin_setup(gpio, pin, 0, 0, pullups, 0);
|
||||
}
|
||||
|
||||
void gpio_pin_af(GPIO_TypeDef *gpio, int pin, int speed, int pullups, int afsel) {
|
||||
gpio_pin_setup(gpio, pin, 2, speed, pullups, afsel);
|
||||
}
|
||||
|
||||
void gpio_pin_analog(GPIO_TypeDef *gpio, int pin) {
|
||||
gpio_pin_setup(gpio, pin, 3, 0, 0, 0);
|
||||
}
|
||||
|
||||
14
demo/fw/src/gpio_helpers.h
Normal file
14
demo/fw/src/gpio_helpers.h
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
#ifndef __GPIO_HELPERS_H__
|
||||
#define __GPIO_HELPERS_H__
|
||||
|
||||
#include <stm32f407xx.h>
|
||||
|
||||
void gpio_pin_mode(GPIO_TypeDef *gpio, int pin, int mode);
|
||||
void gpio_pin_setup(GPIO_TypeDef *gpio, int pin, int mode, int speed, int pullups, int afsel);
|
||||
void gpio_pin_output(GPIO_TypeDef *gpio, int pin, int speed);
|
||||
void gpio_pin_input(GPIO_TypeDef *gpio, int pin, int pullups);
|
||||
void gpio_pin_af(GPIO_TypeDef *gpio, int pin, int speed, int pullups, int afsel);
|
||||
void gpio_pin_analog(GPIO_TypeDef *gpio, int pin);
|
||||
void gpio_pin_tristate(GPIO_TypeDef *gpio, int pin, int tristate);
|
||||
|
||||
#endif /* __GPIO_HELPERS_H__ */
|
||||
35
demo/fw/src/jl_global.h
Normal file
35
demo/fw/src/jl_global.h
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
#ifndef __jl_GLOBAL_H__
|
||||
#define __jl_GLOBAL_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifndef SIMULATION
|
||||
#include <stm32f407xx.h>
|
||||
#include <stm32f4_isr.h>
|
||||
#endif
|
||||
|
||||
#define UNUSED(x) ((void) x)
|
||||
#define ARRAY_LENGTH(x) (sizeof(x) / sizeof(x[0]))
|
||||
|
||||
#define unused_a __attribute__((unused))
|
||||
|
||||
extern unsigned int sysclk_speed;
|
||||
extern unsigned int apb1_speed;
|
||||
extern unsigned int apb2_speed;
|
||||
extern unsigned int auxclk_speed;
|
||||
extern unsigned int apb1_timer_speed;
|
||||
extern unsigned int apb2_timer_speed;
|
||||
|
||||
extern struct leds {
|
||||
unsigned int comm_tx;
|
||||
} leds;
|
||||
static inline uint16_t htole(uint16_t val) { return val; }
|
||||
|
||||
void __libc_init_array(void);
|
||||
|
||||
static inline void panic(void) {
|
||||
asm volatile ("bkpt");
|
||||
}
|
||||
|
||||
#endif /* __jl_GLOBAL_H__ */
|
||||
282
demo/fw/src/main.c
Normal file
282
demo/fw/src/main.c
Normal file
|
|
@ -0,0 +1,282 @@
|
|||
/*
|
||||
* This file is part of the tachibana project
|
||||
*
|
||||
* Copyright (C) 2021 jaseg <code@jaseg.de>
|
||||
*
|
||||
*
|
||||
* libusbhost is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <stm32f407xx.h>
|
||||
|
||||
#include "jl_global.h"
|
||||
#include "con_usart.h"
|
||||
#include "spi.h"
|
||||
|
||||
unsigned int sysclk_speed = 0;
|
||||
unsigned int apb1_speed = 0;
|
||||
unsigned int apb2_speed = 0;
|
||||
unsigned int auxclk_speed = 0;
|
||||
unsigned int apb1_timer_speed = 0;
|
||||
unsigned int apb2_timer_speed = 0;
|
||||
|
||||
struct leds leds;
|
||||
struct spi_fpga_if spif;
|
||||
|
||||
void __libc_init_array(void) { /* we don't need this. */ }
|
||||
void __assert_func (unused_a const char *file, unused_a int line, unused_a const char *function, unused_a const char *expr) {
|
||||
asm volatile ("bkpt");
|
||||
while(1) {}
|
||||
}
|
||||
|
||||
static void clock_setup(void)
|
||||
{
|
||||
/* 8MHz HSE clock as PLL source. */
|
||||
#define HSE_SPEED 8000000
|
||||
/* Divide by 8 -> 1 MHz */
|
||||
#define PLL_M 8
|
||||
/* Multiply by 336 -> 336 MHz VCO frequency */
|
||||
#define PLL_N 336
|
||||
/* Divide by 4 -> 84 MHz (max freq for our chip) */
|
||||
#define PLL_P 2
|
||||
/* Aux clock for USB OTG, SDIO, RNG: divide VCO frequency (336 MHz) by 7 -> 48 MHz (required by USB OTG) */
|
||||
#define PLL_Q 7
|
||||
|
||||
if (((RCC->CFGR & RCC_CFGR_SWS_Msk) >> RCC_CFGR_SW_Pos) != 0)
|
||||
asm volatile ("bkpt");
|
||||
if (RCC->CR & RCC_CR_HSEON)
|
||||
asm volatile ("bkpt");
|
||||
|
||||
RCC->CR |= RCC_CR_HSEON;
|
||||
while(!(RCC->CR & RCC_CR_HSERDY))
|
||||
;
|
||||
|
||||
RCC->APB1ENR |= RCC_APB1ENR_PWREN;
|
||||
|
||||
/* set voltage scale to 1 for max frequency
|
||||
* (0b0) scale 2 for fCLK <= 144 Mhz
|
||||
* (0b1) scale 1 for 144 Mhz < fCLK <= 168 Mhz
|
||||
*/
|
||||
PWR->CR |= PWR_CR_VOS;
|
||||
|
||||
/* set AHB prescaler to /1 (CFGR:bits 7:4) */
|
||||
RCC->CFGR |= (0 << RCC_CFGR_HPRE_Pos);
|
||||
/* set ABP1 prescaler to 4 -> 42MHz */
|
||||
RCC->CFGR |= (5 << RCC_CFGR_PPRE1_Pos);
|
||||
/* set ABP2 prescaler to 2 -> 84MHz */
|
||||
RCC->CFGR |= (4 << RCC_CFGR_PPRE2_Pos);
|
||||
|
||||
if (RCC->CR & RCC_CR_PLLON)
|
||||
asm volatile ("bkpt");
|
||||
/* Configure PLL */
|
||||
static_assert(PLL_P % 2 == 0);
|
||||
static_assert(PLL_P >= 2 && PLL_P <= 8);
|
||||
static_assert(PLL_N >= 50 && PLL_N <= 432);
|
||||
static_assert(PLL_M >= 2 && PLL_M <= 63);
|
||||
static_assert(PLL_Q >= 2 && PLL_Q <= 15);
|
||||
uint32_t old = RCC->PLLCFGR & ~(RCC_PLLCFGR_PLLM_Msk
|
||||
| RCC_PLLCFGR_PLLN_Msk
|
||||
| RCC_PLLCFGR_PLLP_Msk
|
||||
| RCC_PLLCFGR_PLLQ_Msk
|
||||
| RCC_PLLCFGR_PLLSRC);
|
||||
RCC->PLLCFGR = old | (PLL_M<<RCC_PLLCFGR_PLLM_Pos)
|
||||
| (PLL_N << RCC_PLLCFGR_PLLN_Pos)
|
||||
| ((PLL_P/2 - 1) << RCC_PLLCFGR_PLLP_Pos)
|
||||
| (PLL_Q << RCC_PLLCFGR_PLLQ_Pos)
|
||||
| RCC_PLLCFGR_PLLSRC; /* select HSE as PLL source */
|
||||
RCC->CR |= RCC_CR_PLLON;
|
||||
|
||||
sysclk_speed = HSE_SPEED / PLL_M * PLL_N / PLL_P;
|
||||
auxclk_speed = HSE_SPEED / PLL_M * PLL_N / PLL_Q;
|
||||
apb1_speed = sysclk_speed / 4;
|
||||
apb1_timer_speed = apb1_speed * 2;
|
||||
apb2_speed = sysclk_speed / 2;
|
||||
apb2_timer_speed = apb2_speed * 2;
|
||||
|
||||
/* Wait for main PLL */
|
||||
while(!(RCC->CR & RCC_CR_PLLRDY))
|
||||
;
|
||||
|
||||
/* Configure Flash: enable prefetch, insn cache, data cache; set latency = 5 wait states
|
||||
* See reference manual (RM0090), Section 3.5.1, Table 10 (p. 80)
|
||||
*/
|
||||
FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN | FLASH_ACR_DCEN | (5<<FLASH_ACR_LATENCY_Pos);
|
||||
|
||||
/* Select PLL as system clock source */
|
||||
RCC->CFGR &= ~RCC_CFGR_SW_Msk;
|
||||
RCC->CFGR |= 2 << RCC_CFGR_SW_Pos;
|
||||
|
||||
/* Wait for clock to switch over */
|
||||
while ((RCC->CFGR & RCC_CFGR_SWS_Msk)>>RCC_CFGR_SWS_Pos != 2)
|
||||
;
|
||||
}
|
||||
|
||||
static void led_setup(void)
|
||||
{
|
||||
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN | RCC_AHB1ENR_GPIOBEN;
|
||||
/* onboard leds */
|
||||
GPIOA->MODER |= (1<<GPIO_MODER_MODER6_Pos) | (1<<GPIO_MODER_MODER7_Pos);
|
||||
GPIOB->MODER |= (1<<GPIO_MODER_MODER11_Pos) | (1<<GPIO_MODER_MODER12_Pos) | (1<<GPIO_MODER_MODER13_Pos)| (1<<GPIO_MODER_MODER14_Pos);
|
||||
GPIOB->BSRR = 0xf << 11;
|
||||
}
|
||||
|
||||
static void spi_fpga_if_set_cs(bool val) {
|
||||
if (val)
|
||||
GPIOA->BSRR = 1<<4;
|
||||
else
|
||||
GPIOA->BSRR = 1<<(4+16);
|
||||
}
|
||||
|
||||
static void spi_fpga_setup(void)
|
||||
{
|
||||
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN;
|
||||
|
||||
/* SPI1: SCK -> PA5, MISO -> PA6, MOSI -> PA7, ~CS -> PA4 */
|
||||
GPIOA->MODER &= ~GPIO_MODER_MODER5_Msk & ~GPIO_MODER_MODER6_Msk & ~GPIO_MODER_MODER7_Msk & ~GPIO_MODER_MODER4_Msk;
|
||||
GPIOA->MODER |= (2<<GPIO_MODER_MODER5_Pos) /* SCK */
|
||||
| (2<<GPIO_MODER_MODER6_Pos) /* MISO */
|
||||
| (2<<GPIO_MODER_MODER7_Pos) /* MOSI */
|
||||
| (1<<GPIO_MODER_MODER4_Pos); /* CS */
|
||||
|
||||
GPIOA->OSPEEDR &= ~GPIO_OSPEEDR_OSPEED5_Msk & ~GPIO_OSPEEDR_OSPEED6_Msk
|
||||
& ~GPIO_OSPEEDR_OSPEED7_Msk & ~GPIO_OSPEEDR_OSPEED4_Msk;
|
||||
GPIOA->OSPEEDR |= (2<<GPIO_OSPEEDR_OSPEED5_Pos) /* SCK */
|
||||
| (2<<GPIO_OSPEEDR_OSPEED6_Pos) /* MISO */
|
||||
| (2<<GPIO_OSPEEDR_OSPEED7_Pos) /* MOSI */
|
||||
| (2<<GPIO_OSPEEDR_OSPEED4_Pos); /* CS */
|
||||
|
||||
GPIOA->AFR[0] &= ~GPIO_AFRL_AFSEL5_Msk & ~GPIO_AFRL_AFSEL6_Msk & ~GPIO_AFRL_AFSEL7_Msk;
|
||||
GPIOA->AFR[0] |= (5<<GPIO_AFRL_AFSEL5_Pos) | (5<<GPIO_AFRL_AFSEL6_Pos) | (5<<GPIO_AFRL_AFSEL7_Pos);
|
||||
|
||||
RCC->APB2ENR |= RCC_APB2ENR_SPI1EN;
|
||||
RCC->APB2RSTR |= RCC_APB2RSTR_SPI1RST;
|
||||
RCC->APB2RSTR &= ~RCC_APB2RSTR_SPI1RST;
|
||||
|
||||
spif_init(&spif, SPI1, &spi_fpga_if_set_cs);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
if (((SCB->CPACR>>20) & 0xf) != 0xf) {
|
||||
asm volatile ("bkpt");
|
||||
}
|
||||
|
||||
clock_setup();
|
||||
con_usart_init();
|
||||
con_printf("\033[0m\033[2J\033[HBooting...\r\n");
|
||||
|
||||
led_setup();
|
||||
|
||||
spi_fpga_setup();
|
||||
|
||||
#if DEBUG
|
||||
/* TIM1 CC1 (ADC trigger) on pin A8 */
|
||||
GPIOA->MODER &= ~GPIO_MODER_MODER8_Msk;
|
||||
GPIOA->MODER |= (2<<GPIO_MODER_MODER8_Pos);
|
||||
GPIOA->AFR[1] &= ~GPIO_AFRH_AFSEL8_Msk;
|
||||
GPIOA->AFR[1] |= 1<<GPIO_AFRH_AFSEL8_Pos;
|
||||
|
||||
GPIOA->MODER |= (1<<GPIO_MODER_MODER11_Pos) | (1<<GPIO_MODER_MODER12_Pos) | (1<<GPIO_MODER_MODER15_Pos);
|
||||
#endif
|
||||
|
||||
con_printf("Booted.\r\n");
|
||||
|
||||
unsigned int i = 0;
|
||||
int k = 0;
|
||||
con_printf("loop");
|
||||
while (23) {
|
||||
con_printf(" #%u", i);
|
||||
if (k == 0)
|
||||
spif_printf(&spif, "\33[1m");
|
||||
if (k == 1)
|
||||
spif_printf(&spif, "\33[4m");
|
||||
if (k == 2)
|
||||
spif_printf(&spif, "\33[1;4m");
|
||||
if (k >= 4 && k < 12)
|
||||
spif_printf(&spif, "\033[3%dm", k-4+1);
|
||||
if (k >= 12 && k < 20)
|
||||
spif_printf(&spif, "\033[9%dm", k-12+1);
|
||||
spif_printf(&spif, "loop #%u \033[4%dmloop #u \033[10%dmloop #u\033[0m\n", i, k%8, (k+1)%8);
|
||||
i++;
|
||||
k = (k + 1) % 40;
|
||||
if (k == 0) {
|
||||
spif_printf(&spif, "\033[H\033[0m\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\033[H");
|
||||
|
||||
uint8_t buf[128];
|
||||
spif_capture_read(&spif, sizeof(buf), buf);
|
||||
con_printf("\r\n");
|
||||
con_printf("\r\n");
|
||||
con_printf("buffer capture:\r\n");
|
||||
for (size_t e=0; e<sizeof(buf); e += 16) {
|
||||
uint8_t *p = buf + e;
|
||||
con_printf(" %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\r\n",
|
||||
p[0x00], buf[0x01], buf[0x02], buf[0x03], buf[0x04], buf[0x05], buf[0x06], buf[0x07],
|
||||
p[0x08], buf[0x09], buf[0x0a], buf[0x0b], buf[0x0c], buf[0x0d], buf[0x0e], buf[0x0f]);
|
||||
}
|
||||
con_printf("\r\n");
|
||||
con_printf("loop");
|
||||
}
|
||||
|
||||
for (int j=0; j<1000000; j++) {
|
||||
/* pass */
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void NMI_Handler(void) {
|
||||
asm volatile ("bkpt #1");
|
||||
}
|
||||
|
||||
void HardFault_Handler(void) {
|
||||
asm volatile ("bkpt #2");
|
||||
}
|
||||
|
||||
void MemManage_Handler(void) {
|
||||
asm volatile ("bkpt #3");
|
||||
}
|
||||
|
||||
void BusFault_Handler(void) {
|
||||
asm volatile ("bkpt #4");
|
||||
}
|
||||
|
||||
void UsageFault_Handler(void) {
|
||||
asm volatile ("bkpt #5");
|
||||
}
|
||||
|
||||
void SVC_Handler(void) {
|
||||
asm volatile ("bkpt #6");
|
||||
}
|
||||
|
||||
void DebugMon_Handler(void) {
|
||||
asm volatile ("bkpt #7");
|
||||
}
|
||||
|
||||
void PendSV_Handler(void) {
|
||||
asm volatile ("bkpt #8");
|
||||
}
|
||||
|
||||
void SysTick_Handler(void) {
|
||||
asm volatile ("bkpt #9");
|
||||
}
|
||||
|
||||
207
demo/fw/src/serial.c
Normal file
207
demo/fw/src/serial.c
Normal file
|
|
@ -0,0 +1,207 @@
|
|||
/*
|
||||
* This file is part of the tachibana project
|
||||
*
|
||||
* Copyright (C) 2021 jaseg <code@jaseg.de>
|
||||
*
|
||||
*
|
||||
* libusbhost is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "dma_util.h"
|
||||
#include "jl_global.h"
|
||||
#include "serial.h"
|
||||
|
||||
#include <tinyprintf.h>
|
||||
|
||||
static void usart_schedule_dma(volatile struct usart_desc *us);
|
||||
static void usart_dma_reset(volatile struct usart_desc *us);
|
||||
static void usart_putc_nonblocking_tpf(void *us, char c);
|
||||
static void usart_wait_chunk_free(volatile struct usart_desc *us);
|
||||
static void usart_putc_blocking_tpf(void *us, char c);
|
||||
|
||||
void usart_dma_reset(volatile struct usart_desc *us) {
|
||||
us->tx_buf.xfr_start = -1;
|
||||
us->tx_buf.xfr_end = 0;
|
||||
us->tx_buf.wr_pos = 0;
|
||||
us->tx_buf.wr_idx = 0;
|
||||
us->tx_buf.xfr_next = 0;
|
||||
us->tx_buf.wraparound = false;
|
||||
|
||||
for (size_t i=0; i<ARRAY_LENGTH(us->tx_buf.chunk_end); i++)
|
||||
us->tx_buf.chunk_end[i] = -1;
|
||||
}
|
||||
|
||||
void usart_dma_init(volatile struct usart_desc *us, unsigned int baudrate) {
|
||||
usart_dma_reset(us);
|
||||
|
||||
/* Configure DMA 1 Channel 2 to handle uart transmission */
|
||||
us->tx_dmas->PAR = (uint32_t)&(us->le_usart->DR);
|
||||
us->tx_dmas->CR =
|
||||
(us->tx_dma_ch<<DMA_SxCR_CHSEL_Pos)
|
||||
| (0<<DMA_SxCR_PL_Pos)
|
||||
| (1<<DMA_SxCR_DIR_Pos)
|
||||
| (0<<DMA_SxCR_MSIZE_Pos) /* 8 bit */
|
||||
| (0<<DMA_SxCR_PSIZE_Pos) /* 8 bit */
|
||||
| DMA_SxCR_MINC
|
||||
| DMA_SxCR_TCIE; /* Enable transfer complete interrupt. */
|
||||
|
||||
/* triggered on transfer completion. We use this to process the ADC data */
|
||||
NVIC_EnableIRQ(us->tx_dma_irqn);
|
||||
NVIC_SetPriority(us->tx_dma_irqn, 30);
|
||||
|
||||
us->le_usart->CR1 = USART_CR1_TE;
|
||||
/* Set divider for 115.2kBd @48MHz system clock. */
|
||||
us->le_usart->BRR = apb2_speed * 16 / baudrate / 16; /* 250kBd */
|
||||
us->le_usart->CR3 |= USART_CR3_DMAT; /* TX DMA enable */
|
||||
|
||||
/* And... go! */
|
||||
us->le_usart->CR1 |= USART_CR1_UE;
|
||||
}
|
||||
|
||||
void usart_schedule_dma(volatile struct usart_desc *us) {
|
||||
volatile struct dma_tx_buf *buf = &us->tx_buf;
|
||||
|
||||
ssize_t xfr_start, xfr_end, xfr_len;
|
||||
if (buf->wraparound) {
|
||||
buf->wraparound = false;
|
||||
xfr_start = 0;
|
||||
xfr_len = buf->xfr_end;
|
||||
xfr_end = buf->xfr_end;
|
||||
|
||||
} else {
|
||||
if (buf->chunk_end[buf->xfr_next] == -1)
|
||||
return; /* Nothing to trasnmit */
|
||||
|
||||
xfr_start = buf->xfr_end;
|
||||
xfr_end = buf->chunk_end[buf->xfr_next];
|
||||
buf->chunk_end[buf->xfr_next] = -1;
|
||||
buf->xfr_next = (buf->xfr_next + 1) % ARRAY_LENGTH(buf->chunk_end);
|
||||
|
||||
if (xfr_end > xfr_start) { /* no wraparound */
|
||||
xfr_len = xfr_end - xfr_start;
|
||||
|
||||
} else { /* wraparound */
|
||||
if (xfr_end != 0)
|
||||
buf->wraparound = true;
|
||||
xfr_len = sizeof(us->data) - xfr_start;
|
||||
}
|
||||
}
|
||||
|
||||
buf->xfr_start = xfr_start;
|
||||
buf->xfr_end = xfr_end;
|
||||
|
||||
us->comm_led = 100;
|
||||
|
||||
/* initiate transmission of new buffer */
|
||||
us->tx_dmas->M0AR = (uint32_t)(us->data + xfr_start);
|
||||
us->tx_dmas->NDTR = xfr_len;
|
||||
us->tx_dmas->CR |= DMA_SxCR_EN;
|
||||
}
|
||||
|
||||
void usart_dma_stream_irq(volatile struct usart_desc *us) {
|
||||
uint8_t iflags = dma_get_isr_and_clear(us->tx_dma, us->tx_dma_sn);
|
||||
|
||||
if (iflags & DMA_LISR_TCIF0) { /* Transfer complete */
|
||||
us->tx_dmas->CR &= ~DMA_SxCR_EN;
|
||||
//if (us->tx_buf.wraparound)
|
||||
usart_schedule_dma(us);
|
||||
}
|
||||
|
||||
if (iflags & DMA_LISR_FEIF0)
|
||||
us->tx_errors++;
|
||||
}
|
||||
|
||||
int usart_putc_nonblocking(volatile struct usart_desc *us, char c) {
|
||||
volatile struct dma_tx_buf *buf = &us->tx_buf;
|
||||
|
||||
if (buf->wr_pos == buf->xfr_start) {
|
||||
us->tx_byte_overruns++;
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
buf->data[buf->wr_pos] = c;
|
||||
buf->wr_pos = (buf->wr_pos + 1) % sizeof(us->data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usart_putc_blocking(volatile struct usart_desc *us, char c) {
|
||||
volatile struct dma_tx_buf *buf = &us->tx_buf;
|
||||
|
||||
while (buf->wr_pos == buf->xfr_start)
|
||||
;
|
||||
|
||||
buf->data[buf->wr_pos] = c;
|
||||
buf->wr_pos = (buf->wr_pos + 1) % sizeof(us->data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void usart_putc_nonblocking_tpf(void *us, char c) {
|
||||
usart_putc_nonblocking((struct usart_desc *)us, c);
|
||||
}
|
||||
|
||||
void usart_putc_blocking_tpf(void *us, char c) {
|
||||
usart_putc_blocking((struct usart_desc *)us, c);
|
||||
}
|
||||
|
||||
int usart_send_chunk_nonblocking(volatile struct usart_desc *us, const char *chunk, size_t chunk_len) {
|
||||
for (size_t i=0; i<chunk_len; i++)
|
||||
usart_putc_nonblocking(us, chunk[i]);
|
||||
|
||||
return usart_flush(us);
|
||||
}
|
||||
|
||||
void usart_wait_chunk_free(volatile struct usart_desc *us) {
|
||||
while (us->tx_buf.chunk_end[us->tx_buf.wr_idx] != -1)
|
||||
;
|
||||
}
|
||||
|
||||
int usart_flush(volatile struct usart_desc *us) {
|
||||
/* Find a free slot for this chunk */
|
||||
if (us->tx_buf.chunk_end[us->tx_buf.wr_idx] != -1) {
|
||||
us->tx_chunk_overruns++;
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
us->tx_buf.chunk_end[us->tx_buf.wr_idx] = us->tx_buf.wr_pos;
|
||||
us->tx_buf.wr_idx = (us->tx_buf.wr_idx + 1) % ARRAY_LENGTH(us->tx_buf.chunk_end);
|
||||
|
||||
if (!(us->tx_dmas->CR & DMA_SxCR_EN))
|
||||
usart_schedule_dma(us);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usart_printf(volatile struct usart_desc *us, const char *fmt, ...) {
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
tfp_format((void *)us, usart_putc_nonblocking_tpf, fmt, va);
|
||||
return usart_flush(us);
|
||||
}
|
||||
|
||||
int usart_printf_blocking_va(volatile struct usart_desc *us, const char *fmt, va_list va) {
|
||||
tfp_format((void *)us, usart_putc_blocking_tpf, fmt, va);
|
||||
usart_wait_chunk_free(us);
|
||||
return usart_flush(us);
|
||||
}
|
||||
|
||||
int usart_printf_blocking(volatile struct usart_desc *us, const char *fmt, ...) {
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
return usart_printf_blocking_va(us, fmt, va);
|
||||
}
|
||||
|
||||
84
demo/fw/src/serial.h
Normal file
84
demo/fw/src/serial.h
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* This file is part of the tachibana project
|
||||
*
|
||||
* Copyright (C) 2021 jaseg <code@jaseg.de>
|
||||
*
|
||||
*
|
||||
* libusbhost is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __SERIAL_H__
|
||||
#define __SERIAL_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdarg.h>
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "jl_global.h"
|
||||
|
||||
struct dma_tx_buf {
|
||||
/* The following fields are accessed only from DMA ISR */
|
||||
ssize_t xfr_start; /* Start index of running DMA transfer */
|
||||
ssize_t xfr_end; /* End index of running DMA transfer plus one */
|
||||
bool wraparound;
|
||||
ssize_t xfr_next;
|
||||
|
||||
/* The following fields are written only from non-interrupt code */
|
||||
ssize_t wr_pos; /* Next index to be written */
|
||||
ssize_t wr_idx;
|
||||
ssize_t chunk_end[8];
|
||||
|
||||
/* Make GCC shut up about the zero-size array member. */
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wpedantic"
|
||||
/* Written outside ISR by usart_send_chunk_nonblocking, read via DMA */
|
||||
uint8_t data[0];
|
||||
#pragma GCC diagnostic pop
|
||||
};
|
||||
|
||||
struct usart_desc {
|
||||
struct dma_tx_buf tx_buf;
|
||||
uint8_t data[512];
|
||||
|
||||
uint32_t tx_chunk_overruns, tx_byte_overruns;
|
||||
uint32_t tx_errors;
|
||||
|
||||
volatile uint8_t rx_buf[32];
|
||||
|
||||
int comm_led;
|
||||
|
||||
USART_TypeDef *le_usart;
|
||||
int le_usart_irqn;
|
||||
DMA_Stream_TypeDef *tx_dmas;
|
||||
int tx_dma_sn;
|
||||
int tx_dma_ch;
|
||||
DMA_TypeDef *tx_dma;
|
||||
int tx_dma_irqn;
|
||||
};
|
||||
|
||||
void usart_dma_init(volatile struct usart_desc *us, unsigned int baudrate);
|
||||
int usart_send_chunk_nonblocking(volatile struct usart_desc *us, const char *chunk, size_t chunk_len);
|
||||
int usart_putc_nonblocking(volatile struct usart_desc *us, char c);
|
||||
int usart_putc_blocking(volatile struct usart_desc *us, char c);
|
||||
|
||||
void usart_dma_stream_irq(volatile struct usart_desc *us);
|
||||
int usart_flush(volatile struct usart_desc *us);
|
||||
int usart_printf(volatile struct usart_desc *us, const char *fmt, ...);
|
||||
int usart_printf_blocking(volatile struct usart_desc *us, const char *fmt, ...);
|
||||
int usart_printf_blocking_va(volatile struct usart_desc *us, const char *fmt, va_list va);
|
||||
|
||||
#endif // __SERIAL_H__
|
||||
97
demo/fw/src/spi.c
Normal file
97
demo/fw/src/spi.c
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* This file is part of the tachibana project
|
||||
*
|
||||
* Copyright (C) 2021 jaseg <code@jaseg.de>
|
||||
*
|
||||
*
|
||||
* libusbhost is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <tinyprintf.h>
|
||||
|
||||
#include "spi.h"
|
||||
|
||||
static uint8_t spi_xfer(struct spi_fpga_if *spif, uint8_t b);
|
||||
static uint8_t spi_read(struct spi_fpga_if *spif);
|
||||
static void spi_write(struct spi_fpga_if *spif, uint8_t b);
|
||||
static void spi_putc_blocking_tpf(void *spif, char c);
|
||||
|
||||
uint8_t spi_xfer(struct spi_fpga_if *spif, uint8_t b) {
|
||||
while (!(spif->spi->SR & SPI_SR_TXE))
|
||||
;
|
||||
(void) spif->spi->DR; /* perform dummy read to clear RXNE flag */
|
||||
*((uint8_t *)&(spif->spi->DR)) = b;
|
||||
while (!(spif->spi->SR & SPI_SR_RXNE))
|
||||
;
|
||||
return *((uint8_t *)&(spif->spi->DR));
|
||||
}
|
||||
|
||||
uint8_t spi_read(struct spi_fpga_if *spif) {
|
||||
return spi_xfer(spif, 0);
|
||||
}
|
||||
|
||||
void spi_write(struct spi_fpga_if *spif, uint8_t b) {
|
||||
(void)spi_xfer(spif, b);
|
||||
}
|
||||
|
||||
void spif_init(struct spi_fpga_if *spif, SPI_TypeDef *spi, void (*cs)(bool val)) {
|
||||
spif->spi = spi;
|
||||
spif->cs = cs;
|
||||
spif->cs(1);
|
||||
|
||||
spi->CR1 = (4<<SPI_CR1_BR_Pos) | SPI_CR1_SSM | SPI_CR1_SSI | SPI_CR1_SPE | SPI_CR1_MSTR;
|
||||
}
|
||||
|
||||
void spif_command(struct spi_fpga_if *spif, uint8_t cmd, size_t arglen, const uint8_t *args, size_t outlen, uint8_t *out) {
|
||||
spif->cs(0);
|
||||
spi_write(spif, cmd);
|
||||
|
||||
size_t len_min = arglen < outlen ? arglen : outlen;
|
||||
for (size_t i=0; i<len_min; i++) {
|
||||
out[i] = spi_xfer(spif, args[i]);
|
||||
}
|
||||
|
||||
/* write remaining argument bytes if any, ... */
|
||||
for (size_t i=len_min; i<arglen; i++) {
|
||||
spi_write(spif, args[i]);
|
||||
}
|
||||
|
||||
/* ... or read remaining response bytes. */
|
||||
for (size_t i=len_min; i<outlen; i++) {
|
||||
out[i] = spi_read(spif);
|
||||
}
|
||||
|
||||
spif->cs(1);
|
||||
}
|
||||
|
||||
void spif_term_send(struct spi_fpga_if *spif, size_t buflen, const char *buf) {
|
||||
spif_command(spif, 0x23, buflen, (const uint8_t *)buf, 0, NULL);
|
||||
}
|
||||
|
||||
void spif_capture_read(struct spi_fpga_if *spif, size_t buflen, uint8_t *buf) {
|
||||
spif_command(spif, 0x22, 0, NULL, buflen, buf);
|
||||
}
|
||||
|
||||
static void spi_putc_blocking_tpf(void *spif, char c) {
|
||||
spif_term_send((struct spi_fpga_if *)spif, 1, &c);
|
||||
}
|
||||
|
||||
int spif_printf(struct spi_fpga_if *spif, const char *fmt, ...) {
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
tfp_format((void *)spif, spi_putc_blocking_tpf, fmt, va);
|
||||
return 0;
|
||||
}
|
||||
|
||||
22
demo/fw/src/spi.h
Normal file
22
demo/fw/src/spi.h
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
#ifndef __SPI_FLASH_H__
|
||||
#define __SPI_FLASH_H__
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <stm32f407xx.h>
|
||||
|
||||
struct spi_fpga_if {
|
||||
volatile SPI_TypeDef *spi;
|
||||
void (*cs)(bool val);
|
||||
};
|
||||
|
||||
void spif_init(struct spi_fpga_if *spif, SPI_TypeDef *spi, void (*cs)(bool val));
|
||||
void spif_command(struct spi_fpga_if *spif, uint8_t cmd, size_t arglen, const uint8_t *args, size_t outlen, uint8_t *out);
|
||||
|
||||
void spif_term_send(struct spi_fpga_if *spif, size_t buflen, const char *buf);
|
||||
void spif_capture_read(struct spi_fpga_if *spif, size_t buflen, uint8_t *buf);
|
||||
|
||||
int spif_printf(struct spi_fpga_if *spif, const char *fmt, ...);
|
||||
|
||||
#endif /* __SPI_FLASH_H__ */
|
||||
521
demo/fw/src/startup_stm32f407xx.s
Normal file
521
demo/fw/src/startup_stm32f407xx.s
Normal file
|
|
@ -0,0 +1,521 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* @file startup_stm32f407xx.s
|
||||
* @author MCD Application Team
|
||||
* @brief STM32F407xx Devices vector table for GCC based toolchains.
|
||||
* This module performs:
|
||||
* - Set the initial SP
|
||||
* - Set the initial PC == Reset_Handler,
|
||||
* - Set the vector table entries with the exceptions ISR address
|
||||
* - Branches to main in the C library (which eventually
|
||||
* calls main()).
|
||||
* After Reset the Cortex-M4 processor is in Thread mode,
|
||||
* priority is Privileged, and the Stack is set to Main.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2017 STMicroelectronics</center></h2>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of STMicroelectronics nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
.syntax unified
|
||||
.cpu cortex-m4
|
||||
.fpu softvfp
|
||||
.thumb
|
||||
|
||||
.global g_pfnVectors
|
||||
.global Default_Handler
|
||||
|
||||
/* start address for the initialization values of the .data section.
|
||||
defined in linker script */
|
||||
.word _sidata
|
||||
/* start address for the .data section. defined in linker script */
|
||||
.word _sdata
|
||||
/* end address for the .data section. defined in linker script */
|
||||
.word _edata
|
||||
/* start address for the .bss section. defined in linker script */
|
||||
.word _sbss
|
||||
/* end address for the .bss section. defined in linker script */
|
||||
.word _ebss
|
||||
/* stack used for SystemInit_ExtMemCtl; always internal RAM used */
|
||||
|
||||
/**
|
||||
* @brief This is the code that gets called when the processor first
|
||||
* starts execution following a reset event. Only the absolutely
|
||||
* necessary set is performed, after which the application
|
||||
* supplied main() routine is called.
|
||||
* @param None
|
||||
* @retval : None
|
||||
*/
|
||||
|
||||
.section .text.Reset_Handler
|
||||
.weak Reset_Handler
|
||||
.type Reset_Handler, %function
|
||||
Reset_Handler:
|
||||
ldr sp, =_estack /* set stack pointer */
|
||||
|
||||
/* Copy the data segment initializers from flash to SRAM */
|
||||
movs r1, #0
|
||||
b LoopCopyDataInit
|
||||
|
||||
CopyDataInit:
|
||||
ldr r3, =_sidata
|
||||
ldr r3, [r3, r1]
|
||||
str r3, [r0, r1]
|
||||
adds r1, r1, #4
|
||||
|
||||
LoopCopyDataInit:
|
||||
ldr r0, =_sdata
|
||||
ldr r3, =_edata
|
||||
adds r2, r0, r1
|
||||
cmp r2, r3
|
||||
bcc CopyDataInit
|
||||
ldr r2, =_sbss
|
||||
b LoopFillZerobss
|
||||
/* Zero fill the bss segment. */
|
||||
FillZerobss:
|
||||
movs r3, #0
|
||||
str r3, [r2], #4
|
||||
|
||||
LoopFillZerobss:
|
||||
ldr r3, = _ebss
|
||||
cmp r2, r3
|
||||
bcc FillZerobss
|
||||
|
||||
/* Call the clock system intitialization function.*/
|
||||
bl SystemInit
|
||||
/* Call static constructors */
|
||||
bl __libc_init_array
|
||||
/* Call the application's entry point.*/
|
||||
bl main
|
||||
bx lr
|
||||
.size Reset_Handler, .-Reset_Handler
|
||||
|
||||
/**
|
||||
* @brief This is the code that gets called when the processor receives an
|
||||
* unexpected interrupt. This simply enters an infinite loop, preserving
|
||||
* the system state for examination by a debugger.
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
.section .text.Default_Handler,"ax",%progbits
|
||||
Default_Handler:
|
||||
Infinite_Loop:
|
||||
b Infinite_Loop
|
||||
.size Default_Handler, .-Default_Handler
|
||||
/******************************************************************************
|
||||
*
|
||||
* The minimal vector table for a Cortex M3. Note that the proper constructs
|
||||
* must be placed on this to ensure that it ends up at physical address
|
||||
* 0x0000.0000.
|
||||
*
|
||||
*******************************************************************************/
|
||||
.section .isr_vector,"a",%progbits
|
||||
.type g_pfnVectors, %object
|
||||
.size g_pfnVectors, .-g_pfnVectors
|
||||
|
||||
|
||||
g_pfnVectors:
|
||||
.word _estack
|
||||
.word Reset_Handler
|
||||
.word NMI_Handler
|
||||
.word HardFault_Handler
|
||||
.word MemManage_Handler
|
||||
.word BusFault_Handler
|
||||
.word UsageFault_Handler
|
||||
.word 0
|
||||
.word 0
|
||||
.word 0
|
||||
.word 0
|
||||
.word SVC_Handler
|
||||
.word DebugMon_Handler
|
||||
.word 0
|
||||
.word PendSV_Handler
|
||||
.word SysTick_Handler
|
||||
|
||||
/* External Interrupts */
|
||||
.word WWDG_IRQHandler /* Window WatchDog */
|
||||
.word PVD_IRQHandler /* PVD through EXTI Line detection */
|
||||
.word TAMP_STAMP_IRQHandler /* Tamper and TimeStamps through the EXTI line */
|
||||
.word RTC_WKUP_IRQHandler /* RTC Wakeup through the EXTI line */
|
||||
.word FLASH_IRQHandler /* FLASH */
|
||||
.word RCC_IRQHandler /* RCC */
|
||||
.word EXTI0_IRQHandler /* EXTI Line0 */
|
||||
.word EXTI1_IRQHandler /* EXTI Line1 */
|
||||
.word EXTI2_IRQHandler /* EXTI Line2 */
|
||||
.word EXTI3_IRQHandler /* EXTI Line3 */
|
||||
.word EXTI4_IRQHandler /* EXTI Line4 */
|
||||
.word DMA1_Stream0_IRQHandler /* DMA1 Stream 0 */
|
||||
.word DMA1_Stream1_IRQHandler /* DMA1 Stream 1 */
|
||||
.word DMA1_Stream2_IRQHandler /* DMA1 Stream 2 */
|
||||
.word DMA1_Stream3_IRQHandler /* DMA1 Stream 3 */
|
||||
.word DMA1_Stream4_IRQHandler /* DMA1 Stream 4 */
|
||||
.word DMA1_Stream5_IRQHandler /* DMA1 Stream 5 */
|
||||
.word DMA1_Stream6_IRQHandler /* DMA1 Stream 6 */
|
||||
.word ADC_IRQHandler /* ADC1, ADC2 and ADC3s */
|
||||
.word CAN1_TX_IRQHandler /* CAN1 TX */
|
||||
.word CAN1_RX0_IRQHandler /* CAN1 RX0 */
|
||||
.word CAN1_RX1_IRQHandler /* CAN1 RX1 */
|
||||
.word CAN1_SCE_IRQHandler /* CAN1 SCE */
|
||||
.word EXTI9_5_IRQHandler /* External Line[9:5]s */
|
||||
.word TIM1_BRK_TIM9_IRQHandler /* TIM1 Break and TIM9 */
|
||||
.word TIM1_UP_TIM10_IRQHandler /* TIM1 Update and TIM10 */
|
||||
.word TIM1_TRG_COM_TIM11_IRQHandler /* TIM1 Trigger and Commutation and TIM11 */
|
||||
.word TIM1_CC_IRQHandler /* TIM1 Capture Compare */
|
||||
.word TIM2_IRQHandler /* TIM2 */
|
||||
.word TIM3_IRQHandler /* TIM3 */
|
||||
.word TIM4_IRQHandler /* TIM4 */
|
||||
.word I2C1_EV_IRQHandler /* I2C1 Event */
|
||||
.word I2C1_ER_IRQHandler /* I2C1 Error */
|
||||
.word I2C2_EV_IRQHandler /* I2C2 Event */
|
||||
.word I2C2_ER_IRQHandler /* I2C2 Error */
|
||||
.word SPI1_IRQHandler /* SPI1 */
|
||||
.word SPI2_IRQHandler /* SPI2 */
|
||||
.word USART1_IRQHandler /* USART1 */
|
||||
.word USART2_IRQHandler /* USART2 */
|
||||
.word USART3_IRQHandler /* USART3 */
|
||||
.word EXTI15_10_IRQHandler /* External Line[15:10]s */
|
||||
.word RTC_Alarm_IRQHandler /* RTC Alarm (A and B) through EXTI Line */
|
||||
.word OTG_FS_WKUP_IRQHandler /* USB OTG FS Wakeup through EXTI line */
|
||||
.word TIM8_BRK_TIM12_IRQHandler /* TIM8 Break and TIM12 */
|
||||
.word TIM8_UP_TIM13_IRQHandler /* TIM8 Update and TIM13 */
|
||||
.word TIM8_TRG_COM_TIM14_IRQHandler /* TIM8 Trigger and Commutation and TIM14 */
|
||||
.word TIM8_CC_IRQHandler /* TIM8 Capture Compare */
|
||||
.word DMA1_Stream7_IRQHandler /* DMA1 Stream7 */
|
||||
.word FSMC_IRQHandler /* FSMC */
|
||||
.word SDIO_IRQHandler /* SDIO */
|
||||
.word TIM5_IRQHandler /* TIM5 */
|
||||
.word SPI3_IRQHandler /* SPI3 */
|
||||
.word UART4_IRQHandler /* UART4 */
|
||||
.word UART5_IRQHandler /* UART5 */
|
||||
.word TIM6_DAC_IRQHandler /* TIM6 and DAC1&2 underrun errors */
|
||||
.word TIM7_IRQHandler /* TIM7 */
|
||||
.word DMA2_Stream0_IRQHandler /* DMA2 Stream 0 */
|
||||
.word DMA2_Stream1_IRQHandler /* DMA2 Stream 1 */
|
||||
.word DMA2_Stream2_IRQHandler /* DMA2 Stream 2 */
|
||||
.word DMA2_Stream3_IRQHandler /* DMA2 Stream 3 */
|
||||
.word DMA2_Stream4_IRQHandler /* DMA2 Stream 4 */
|
||||
.word ETH_IRQHandler /* Ethernet */
|
||||
.word ETH_WKUP_IRQHandler /* Ethernet Wakeup through EXTI line */
|
||||
.word CAN2_TX_IRQHandler /* CAN2 TX */
|
||||
.word CAN2_RX0_IRQHandler /* CAN2 RX0 */
|
||||
.word CAN2_RX1_IRQHandler /* CAN2 RX1 */
|
||||
.word CAN2_SCE_IRQHandler /* CAN2 SCE */
|
||||
.word OTG_FS_IRQHandler /* USB OTG FS */
|
||||
.word DMA2_Stream5_IRQHandler /* DMA2 Stream 5 */
|
||||
.word DMA2_Stream6_IRQHandler /* DMA2 Stream 6 */
|
||||
.word DMA2_Stream7_IRQHandler /* DMA2 Stream 7 */
|
||||
.word USART6_IRQHandler /* USART6 */
|
||||
.word I2C3_EV_IRQHandler /* I2C3 event */
|
||||
.word I2C3_ER_IRQHandler /* I2C3 error */
|
||||
.word OTG_HS_EP1_OUT_IRQHandler /* USB OTG HS End Point 1 Out */
|
||||
.word OTG_HS_EP1_IN_IRQHandler /* USB OTG HS End Point 1 In */
|
||||
.word OTG_HS_WKUP_IRQHandler /* USB OTG HS Wakeup through EXTI */
|
||||
.word OTG_HS_IRQHandler /* USB OTG HS */
|
||||
.word DCMI_IRQHandler /* DCMI */
|
||||
.word 0 /* CRYP crypto */
|
||||
.word HASH_RNG_IRQHandler /* Hash and Rng */
|
||||
.word FPU_IRQHandler /* FPU */
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Provide weak aliases for each Exception handler to the Default_Handler.
|
||||
* As they are weak aliases, any function with the same name will override
|
||||
* this definition.
|
||||
*
|
||||
*******************************************************************************/
|
||||
.weak NMI_Handler
|
||||
.thumb_set NMI_Handler,Default_Handler
|
||||
|
||||
.weak HardFault_Handler
|
||||
.thumb_set HardFault_Handler,Default_Handler
|
||||
|
||||
.weak MemManage_Handler
|
||||
.thumb_set MemManage_Handler,Default_Handler
|
||||
|
||||
.weak BusFault_Handler
|
||||
.thumb_set BusFault_Handler,Default_Handler
|
||||
|
||||
.weak UsageFault_Handler
|
||||
.thumb_set UsageFault_Handler,Default_Handler
|
||||
|
||||
.weak SVC_Handler
|
||||
.thumb_set SVC_Handler,Default_Handler
|
||||
|
||||
.weak DebugMon_Handler
|
||||
.thumb_set DebugMon_Handler,Default_Handler
|
||||
|
||||
.weak PendSV_Handler
|
||||
.thumb_set PendSV_Handler,Default_Handler
|
||||
|
||||
.weak SysTick_Handler
|
||||
.thumb_set SysTick_Handler,Default_Handler
|
||||
|
||||
.weak WWDG_IRQHandler
|
||||
.thumb_set WWDG_IRQHandler,Default_Handler
|
||||
|
||||
.weak PVD_IRQHandler
|
||||
.thumb_set PVD_IRQHandler,Default_Handler
|
||||
|
||||
.weak TAMP_STAMP_IRQHandler
|
||||
.thumb_set TAMP_STAMP_IRQHandler,Default_Handler
|
||||
|
||||
.weak RTC_WKUP_IRQHandler
|
||||
.thumb_set RTC_WKUP_IRQHandler,Default_Handler
|
||||
|
||||
.weak FLASH_IRQHandler
|
||||
.thumb_set FLASH_IRQHandler,Default_Handler
|
||||
|
||||
.weak RCC_IRQHandler
|
||||
.thumb_set RCC_IRQHandler,Default_Handler
|
||||
|
||||
.weak EXTI0_IRQHandler
|
||||
.thumb_set EXTI0_IRQHandler,Default_Handler
|
||||
|
||||
.weak EXTI1_IRQHandler
|
||||
.thumb_set EXTI1_IRQHandler,Default_Handler
|
||||
|
||||
.weak EXTI2_IRQHandler
|
||||
.thumb_set EXTI2_IRQHandler,Default_Handler
|
||||
|
||||
.weak EXTI3_IRQHandler
|
||||
.thumb_set EXTI3_IRQHandler,Default_Handler
|
||||
|
||||
.weak EXTI4_IRQHandler
|
||||
.thumb_set EXTI4_IRQHandler,Default_Handler
|
||||
|
||||
.weak DMA1_Stream0_IRQHandler
|
||||
.thumb_set DMA1_Stream0_IRQHandler,Default_Handler
|
||||
|
||||
.weak DMA1_Stream1_IRQHandler
|
||||
.thumb_set DMA1_Stream1_IRQHandler,Default_Handler
|
||||
|
||||
.weak DMA1_Stream2_IRQHandler
|
||||
.thumb_set DMA1_Stream2_IRQHandler,Default_Handler
|
||||
|
||||
.weak DMA1_Stream3_IRQHandler
|
||||
.thumb_set DMA1_Stream3_IRQHandler,Default_Handler
|
||||
|
||||
.weak DMA1_Stream4_IRQHandler
|
||||
.thumb_set DMA1_Stream4_IRQHandler,Default_Handler
|
||||
|
||||
.weak DMA1_Stream5_IRQHandler
|
||||
.thumb_set DMA1_Stream5_IRQHandler,Default_Handler
|
||||
|
||||
.weak DMA1_Stream6_IRQHandler
|
||||
.thumb_set DMA1_Stream6_IRQHandler,Default_Handler
|
||||
|
||||
.weak ADC_IRQHandler
|
||||
.thumb_set ADC_IRQHandler,Default_Handler
|
||||
|
||||
.weak CAN1_TX_IRQHandler
|
||||
.thumb_set CAN1_TX_IRQHandler,Default_Handler
|
||||
|
||||
.weak CAN1_RX0_IRQHandler
|
||||
.thumb_set CAN1_RX0_IRQHandler,Default_Handler
|
||||
|
||||
.weak CAN1_RX1_IRQHandler
|
||||
.thumb_set CAN1_RX1_IRQHandler,Default_Handler
|
||||
|
||||
.weak CAN1_SCE_IRQHandler
|
||||
.thumb_set CAN1_SCE_IRQHandler,Default_Handler
|
||||
|
||||
.weak EXTI9_5_IRQHandler
|
||||
.thumb_set EXTI9_5_IRQHandler,Default_Handler
|
||||
|
||||
.weak TIM1_BRK_TIM9_IRQHandler
|
||||
.thumb_set TIM1_BRK_TIM9_IRQHandler,Default_Handler
|
||||
|
||||
.weak TIM1_UP_TIM10_IRQHandler
|
||||
.thumb_set TIM1_UP_TIM10_IRQHandler,Default_Handler
|
||||
|
||||
.weak TIM1_TRG_COM_TIM11_IRQHandler
|
||||
.thumb_set TIM1_TRG_COM_TIM11_IRQHandler,Default_Handler
|
||||
|
||||
.weak TIM1_CC_IRQHandler
|
||||
.thumb_set TIM1_CC_IRQHandler,Default_Handler
|
||||
|
||||
.weak TIM2_IRQHandler
|
||||
.thumb_set TIM2_IRQHandler,Default_Handler
|
||||
|
||||
.weak TIM3_IRQHandler
|
||||
.thumb_set TIM3_IRQHandler,Default_Handler
|
||||
|
||||
.weak TIM4_IRQHandler
|
||||
.thumb_set TIM4_IRQHandler,Default_Handler
|
||||
|
||||
.weak I2C1_EV_IRQHandler
|
||||
.thumb_set I2C1_EV_IRQHandler,Default_Handler
|
||||
|
||||
.weak I2C1_ER_IRQHandler
|
||||
.thumb_set I2C1_ER_IRQHandler,Default_Handler
|
||||
|
||||
.weak I2C2_EV_IRQHandler
|
||||
.thumb_set I2C2_EV_IRQHandler,Default_Handler
|
||||
|
||||
.weak I2C2_ER_IRQHandler
|
||||
.thumb_set I2C2_ER_IRQHandler,Default_Handler
|
||||
|
||||
.weak SPI1_IRQHandler
|
||||
.thumb_set SPI1_IRQHandler,Default_Handler
|
||||
|
||||
.weak SPI2_IRQHandler
|
||||
.thumb_set SPI2_IRQHandler,Default_Handler
|
||||
|
||||
.weak USART1_IRQHandler
|
||||
.thumb_set USART1_IRQHandler,Default_Handler
|
||||
|
||||
.weak USART2_IRQHandler
|
||||
.thumb_set USART2_IRQHandler,Default_Handler
|
||||
|
||||
.weak USART3_IRQHandler
|
||||
.thumb_set USART3_IRQHandler,Default_Handler
|
||||
|
||||
.weak EXTI15_10_IRQHandler
|
||||
.thumb_set EXTI15_10_IRQHandler,Default_Handler
|
||||
|
||||
.weak RTC_Alarm_IRQHandler
|
||||
.thumb_set RTC_Alarm_IRQHandler,Default_Handler
|
||||
|
||||
.weak OTG_FS_WKUP_IRQHandler
|
||||
.thumb_set OTG_FS_WKUP_IRQHandler,Default_Handler
|
||||
|
||||
.weak TIM8_BRK_TIM12_IRQHandler
|
||||
.thumb_set TIM8_BRK_TIM12_IRQHandler,Default_Handler
|
||||
|
||||
.weak TIM8_UP_TIM13_IRQHandler
|
||||
.thumb_set TIM8_UP_TIM13_IRQHandler,Default_Handler
|
||||
|
||||
.weak TIM8_TRG_COM_TIM14_IRQHandler
|
||||
.thumb_set TIM8_TRG_COM_TIM14_IRQHandler,Default_Handler
|
||||
|
||||
.weak TIM8_CC_IRQHandler
|
||||
.thumb_set TIM8_CC_IRQHandler,Default_Handler
|
||||
|
||||
.weak DMA1_Stream7_IRQHandler
|
||||
.thumb_set DMA1_Stream7_IRQHandler,Default_Handler
|
||||
|
||||
.weak FSMC_IRQHandler
|
||||
.thumb_set FSMC_IRQHandler,Default_Handler
|
||||
|
||||
.weak SDIO_IRQHandler
|
||||
.thumb_set SDIO_IRQHandler,Default_Handler
|
||||
|
||||
.weak TIM5_IRQHandler
|
||||
.thumb_set TIM5_IRQHandler,Default_Handler
|
||||
|
||||
.weak SPI3_IRQHandler
|
||||
.thumb_set SPI3_IRQHandler,Default_Handler
|
||||
|
||||
.weak UART4_IRQHandler
|
||||
.thumb_set UART4_IRQHandler,Default_Handler
|
||||
|
||||
.weak UART5_IRQHandler
|
||||
.thumb_set UART5_IRQHandler,Default_Handler
|
||||
|
||||
.weak TIM6_DAC_IRQHandler
|
||||
.thumb_set TIM6_DAC_IRQHandler,Default_Handler
|
||||
|
||||
.weak TIM7_IRQHandler
|
||||
.thumb_set TIM7_IRQHandler,Default_Handler
|
||||
|
||||
.weak DMA2_Stream0_IRQHandler
|
||||
.thumb_set DMA2_Stream0_IRQHandler,Default_Handler
|
||||
|
||||
.weak DMA2_Stream1_IRQHandler
|
||||
.thumb_set DMA2_Stream1_IRQHandler,Default_Handler
|
||||
|
||||
.weak DMA2_Stream2_IRQHandler
|
||||
.thumb_set DMA2_Stream2_IRQHandler,Default_Handler
|
||||
|
||||
.weak DMA2_Stream3_IRQHandler
|
||||
.thumb_set DMA2_Stream3_IRQHandler,Default_Handler
|
||||
|
||||
.weak DMA2_Stream4_IRQHandler
|
||||
.thumb_set DMA2_Stream4_IRQHandler,Default_Handler
|
||||
|
||||
.weak ETH_IRQHandler
|
||||
.thumb_set ETH_IRQHandler,Default_Handler
|
||||
|
||||
.weak ETH_WKUP_IRQHandler
|
||||
.thumb_set ETH_WKUP_IRQHandler,Default_Handler
|
||||
|
||||
.weak CAN2_TX_IRQHandler
|
||||
.thumb_set CAN2_TX_IRQHandler,Default_Handler
|
||||
|
||||
.weak CAN2_RX0_IRQHandler
|
||||
.thumb_set CAN2_RX0_IRQHandler,Default_Handler
|
||||
|
||||
.weak CAN2_RX1_IRQHandler
|
||||
.thumb_set CAN2_RX1_IRQHandler,Default_Handler
|
||||
|
||||
.weak CAN2_SCE_IRQHandler
|
||||
.thumb_set CAN2_SCE_IRQHandler,Default_Handler
|
||||
|
||||
.weak OTG_FS_IRQHandler
|
||||
.thumb_set OTG_FS_IRQHandler,Default_Handler
|
||||
|
||||
.weak DMA2_Stream5_IRQHandler
|
||||
.thumb_set DMA2_Stream5_IRQHandler,Default_Handler
|
||||
|
||||
.weak DMA2_Stream6_IRQHandler
|
||||
.thumb_set DMA2_Stream6_IRQHandler,Default_Handler
|
||||
|
||||
.weak DMA2_Stream7_IRQHandler
|
||||
.thumb_set DMA2_Stream7_IRQHandler,Default_Handler
|
||||
|
||||
.weak USART6_IRQHandler
|
||||
.thumb_set USART6_IRQHandler,Default_Handler
|
||||
|
||||
.weak I2C3_EV_IRQHandler
|
||||
.thumb_set I2C3_EV_IRQHandler,Default_Handler
|
||||
|
||||
.weak I2C3_ER_IRQHandler
|
||||
.thumb_set I2C3_ER_IRQHandler,Default_Handler
|
||||
|
||||
.weak OTG_HS_EP1_OUT_IRQHandler
|
||||
.thumb_set OTG_HS_EP1_OUT_IRQHandler,Default_Handler
|
||||
|
||||
.weak OTG_HS_EP1_IN_IRQHandler
|
||||
.thumb_set OTG_HS_EP1_IN_IRQHandler,Default_Handler
|
||||
|
||||
.weak OTG_HS_WKUP_IRQHandler
|
||||
.thumb_set OTG_HS_WKUP_IRQHandler,Default_Handler
|
||||
|
||||
.weak OTG_HS_IRQHandler
|
||||
.thumb_set OTG_HS_IRQHandler,Default_Handler
|
||||
|
||||
.weak DCMI_IRQHandler
|
||||
.thumb_set DCMI_IRQHandler,Default_Handler
|
||||
|
||||
.weak HASH_RNG_IRQHandler
|
||||
.thumb_set HASH_RNG_IRQHandler,Default_Handler
|
||||
|
||||
.weak FPU_IRQHandler
|
||||
.thumb_set FPU_IRQHandler,Default_Handler
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
98
demo/fw/src/stm32f4_isr.h
Normal file
98
demo/fw/src/stm32f4_isr.h
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
|
||||
#ifndef __STM32F4_ISR_H__
|
||||
#define __STM32F4_ISR_H__
|
||||
|
||||
void Reset_Handler(void);
|
||||
void NMI_Handler(void);
|
||||
void HardFault_Handler(void);
|
||||
void MemManage_Handler(void);
|
||||
void BusFault_Handler(void);
|
||||
void UsageFault_Handler(void);
|
||||
void SVC_Handler(void);
|
||||
void DebugMon_Handler(void);
|
||||
void PendSV_Handler(void);
|
||||
void SysTick_Handler(void);
|
||||
|
||||
void WWDG_IRQHandler(void);
|
||||
void PVD_IRQHandler(void);
|
||||
void TAMP_STAMP_IRQHandler(void);
|
||||
void RTC_WKUP_IRQHandler(void);
|
||||
void FLASH_IRQHandler(void);
|
||||
void RCC_IRQHandler(void);
|
||||
void EXTI0_IRQHandler(void);
|
||||
void EXTI1_IRQHandler(void);
|
||||
void EXTI2_IRQHandler(void);
|
||||
void EXTI3_IRQHandler(void);
|
||||
void EXTI4_IRQHandler(void);
|
||||
void DMA1_Stream0_IRQHandler(void);
|
||||
void DMA1_Stream1_IRQHandler(void);
|
||||
void DMA1_Stream2_IRQHandler(void);
|
||||
void DMA1_Stream3_IRQHandler(void);
|
||||
void DMA1_Stream4_IRQHandler(void);
|
||||
void DMA1_Stream5_IRQHandler(void);
|
||||
void DMA1_Stream6_IRQHandler(void);
|
||||
void ADC_IRQHandler(void);
|
||||
void CAN1_TX_IRQHandler(void);
|
||||
void CAN1_RX0_IRQHandler(void);
|
||||
void CAN1_RX1_IRQHandler(void);
|
||||
void CAN1_SCE_IRQHandler(void);
|
||||
void EXTI9_5_IRQHandler(void);
|
||||
void TIM1_BRK_TIM9_IRQHandler(void);
|
||||
void TIM1_UP_TIM10_IRQHandler(void);
|
||||
void TIM1_TRG_COM_TIM11_IRQHandler(void);
|
||||
void TIM1_CC_IRQHandler(void);
|
||||
void TIM2_IRQHandler(void);
|
||||
void TIM3_IRQHandler(void);
|
||||
void TIM4_IRQHandler(void);
|
||||
void I2C1_EV_IRQHandler(void);
|
||||
void I2C1_ER_IRQHandler(void);
|
||||
void I2C2_EV_IRQHandler(void);
|
||||
void I2C2_ER_IRQHandler(void);
|
||||
void SPI1_IRQHandler(void);
|
||||
void SPI2_IRQHandler(void);
|
||||
void USART1_IRQHandler(void);
|
||||
void USART2_IRQHandler(void);
|
||||
void USART3_IRQHandler(void);
|
||||
void EXTI15_10_IRQHandler(void);
|
||||
void RTC_Alarm_IRQHandler(void);
|
||||
void OTG_FS_WKUP_IRQHandler(void);
|
||||
void TIM8_BRK_TIM12_IRQHandler(void);
|
||||
void TIM8_UP_TIM13_IRQHandler(void);
|
||||
void TIM8_TRG_COM_TIM14_IRQHandler(void);
|
||||
void TIM8_CC_IRQHandler(void);
|
||||
void DMA1_Stream7_IRQHandler(void);
|
||||
void FSMC_IRQHandler(void);
|
||||
void SDIO_IRQHandler(void);
|
||||
void TIM5_IRQHandler(void);
|
||||
void SPI3_IRQHandler(void);
|
||||
void UART4_IRQHandler(void);
|
||||
void UART5_IRQHandler(void);
|
||||
void TIM6_DAC_IRQHandler(void);
|
||||
void TIM7_IRQHandler(void);
|
||||
void DMA2_Stream0_IRQHandler(void);
|
||||
void DMA2_Stream1_IRQHandler(void);
|
||||
void DMA2_Stream2_IRQHandler(void);
|
||||
void DMA2_Stream3_IRQHandler(void);
|
||||
void DMA2_Stream4_IRQHandler(void);
|
||||
void ETH_IRQHandler(void);
|
||||
void ETH_WKUP_IRQHandler(void);
|
||||
void CAN2_TX_IRQHandler(void);
|
||||
void CAN2_RX0_IRQHandler(void);
|
||||
void CAN2_RX1_IRQHandler(void);
|
||||
void CAN2_SCE_IRQHandler(void);
|
||||
void OTG_FS_IRQHandler(void);
|
||||
void DMA2_Stream5_IRQHandler(void);
|
||||
void DMA2_Stream6_IRQHandler(void);
|
||||
void DMA2_Stream7_IRQHandler(void);
|
||||
void USART6_IRQHandler(void);
|
||||
void I2C3_EV_IRQHandler(void);
|
||||
void I2C3_ER_IRQHandler(void);
|
||||
void OTG_HS_EP1_OUT_IRQHandler(void);
|
||||
void OTG_HS_EP1_IN_IRQHandler(void);
|
||||
void OTG_HS_WKUP_IRQHandler(void);
|
||||
void OTG_HS_IRQHandler(void);
|
||||
void DCMI_IRQHandler(void);
|
||||
void HASH_RNG_IRQHandler(void);
|
||||
void FPU_IRQHandler(void);
|
||||
|
||||
#endif /* __STM32F4_ISR_H__ */
|
||||
742
demo/fw/src/system_stm32f4xx.c
Normal file
742
demo/fw/src/system_stm32f4xx.c
Normal file
|
|
@ -0,0 +1,742 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* @file system_stm32f4xx.c
|
||||
* @author MCD Application Team
|
||||
* @brief CMSIS Cortex-M4 Device Peripheral Access Layer System Source File.
|
||||
*
|
||||
* This file provides two functions and one global variable to be called from
|
||||
* user application:
|
||||
* - SystemInit(): This function is called at startup just after reset and
|
||||
* before branch to main program. This call is made inside
|
||||
* the "startup_stm32f4xx.s" file.
|
||||
*
|
||||
* - SystemCoreClock variable: Contains the core clock (HCLK), it can be used
|
||||
* by the user application to setup the SysTick
|
||||
* timer or configure other parameters.
|
||||
*
|
||||
* - SystemCoreClockUpdate(): Updates the variable SystemCoreClock and must
|
||||
* be called whenever the core clock is changed
|
||||
* during program execution.
|
||||
*
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2017 STMicroelectronics</center></h2>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of STMicroelectronics nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/** @addtogroup CMSIS
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup stm32f4xx_system
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup STM32F4xx_System_Private_Includes
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
#include "stm32f4xx.h"
|
||||
|
||||
#if !defined (HSE_VALUE)
|
||||
#define HSE_VALUE ((uint32_t)25000000) /*!< Default value of the External oscillator in Hz */
|
||||
#endif /* HSE_VALUE */
|
||||
|
||||
#if !defined (HSI_VALUE)
|
||||
#define HSI_VALUE ((uint32_t)16000000) /*!< Value of the Internal oscillator in Hz*/
|
||||
#endif /* HSI_VALUE */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup STM32F4xx_System_Private_TypesDefinitions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup STM32F4xx_System_Private_Defines
|
||||
* @{
|
||||
*/
|
||||
|
||||
/************************* Miscellaneous Configuration ************************/
|
||||
/*!< Uncomment the following line if you need to use external SRAM or SDRAM as data memory */
|
||||
#if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx) || defined(STM32F417xx)\
|
||||
|| defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\
|
||||
|| defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F412Zx) || defined(STM32F412Vx)
|
||||
/* #define DATA_IN_ExtSRAM */
|
||||
#endif /* STM32F40xxx || STM32F41xxx || STM32F42xxx || STM32F43xxx || STM32F469xx || STM32F479xx ||\
|
||||
STM32F412Zx || STM32F412Vx */
|
||||
|
||||
#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\
|
||||
|| defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx)
|
||||
/* #define DATA_IN_ExtSDRAM */
|
||||
#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F446xx || STM32F469xx ||\
|
||||
STM32F479xx */
|
||||
|
||||
/*!< Uncomment the following line if you need to relocate your vector Table in
|
||||
Internal SRAM. */
|
||||
/* #define VECT_TAB_SRAM */
|
||||
#define VECT_TAB_OFFSET 0x00 /*!< Vector Table base offset field.
|
||||
This value must be a multiple of 0x200. */
|
||||
/******************************************************************************/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup STM32F4xx_System_Private_Macros
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup STM32F4xx_System_Private_Variables
|
||||
* @{
|
||||
*/
|
||||
/* This variable is updated in three ways:
|
||||
1) by calling CMSIS function SystemCoreClockUpdate()
|
||||
2) by calling HAL API function HAL_RCC_GetHCLKFreq()
|
||||
3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency
|
||||
Note: If you use this function to configure the system clock; then there
|
||||
is no need to call the 2 first functions listed above, since SystemCoreClock
|
||||
variable is updated automatically.
|
||||
*/
|
||||
uint32_t SystemCoreClock = 16000000;
|
||||
const uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
|
||||
const uint8_t APBPrescTable[8] = {0, 0, 0, 0, 1, 2, 3, 4};
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup STM32F4xx_System_Private_FunctionPrototypes
|
||||
* @{
|
||||
*/
|
||||
|
||||
#if defined (DATA_IN_ExtSRAM) || defined (DATA_IN_ExtSDRAM)
|
||||
static void SystemInit_ExtMemCtl(void);
|
||||
#endif /* DATA_IN_ExtSRAM || DATA_IN_ExtSDRAM */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup STM32F4xx_System_Private_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Setup the microcontroller system
|
||||
* Initialize the FPU setting, vector table location and External memory
|
||||
* configuration.
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void SystemInit(void)
|
||||
{
|
||||
SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */
|
||||
__DSB();
|
||||
__ISB();
|
||||
|
||||
#if defined (DATA_IN_ExtSRAM) || defined (DATA_IN_ExtSDRAM)
|
||||
SystemInit_ExtMemCtl();
|
||||
#endif /* DATA_IN_ExtSRAM || DATA_IN_ExtSDRAM */
|
||||
|
||||
/* Configure the Vector Table location add offset address ------------------*/
|
||||
#ifdef VECT_TAB_SRAM
|
||||
SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */
|
||||
#else
|
||||
SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Update SystemCoreClock variable according to Clock Register Values.
|
||||
* The SystemCoreClock variable contains the core clock (HCLK), it can
|
||||
* be used by the user application to setup the SysTick timer or configure
|
||||
* other parameters.
|
||||
*
|
||||
* @note Each time the core clock (HCLK) changes, this function must be called
|
||||
* to update SystemCoreClock variable value. Otherwise, any configuration
|
||||
* based on this variable will be incorrect.
|
||||
*
|
||||
* @note - The system frequency computed by this function is not the real
|
||||
* frequency in the chip. It is calculated based on the predefined
|
||||
* constant and the selected clock source:
|
||||
*
|
||||
* - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(*)
|
||||
*
|
||||
* - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(**)
|
||||
*
|
||||
* - If SYSCLK source is PLL, SystemCoreClock will contain the HSE_VALUE(**)
|
||||
* or HSI_VALUE(*) multiplied/divided by the PLL factors.
|
||||
*
|
||||
* (*) HSI_VALUE is a constant defined in stm32f4xx_hal_conf.h file (default value
|
||||
* 16 MHz) but the real value may vary depending on the variations
|
||||
* in voltage and temperature.
|
||||
*
|
||||
* (**) HSE_VALUE is a constant defined in stm32f4xx_hal_conf.h file (its value
|
||||
* depends on the application requirements), user has to ensure that HSE_VALUE
|
||||
* is same as the real frequency of the crystal used. Otherwise, this function
|
||||
* may have wrong result.
|
||||
*
|
||||
* - The result of this function could be not correct when using fractional
|
||||
* value for HSE crystal.
|
||||
*
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void SystemCoreClockUpdate(void)
|
||||
{
|
||||
uint32_t tmp = 0, pllvco = 0, pllp = 2, pllsource = 0, pllm = 2;
|
||||
|
||||
/* Get SYSCLK source -------------------------------------------------------*/
|
||||
tmp = RCC->CFGR & RCC_CFGR_SWS;
|
||||
|
||||
switch (tmp)
|
||||
{
|
||||
case 0x00: /* HSI used as system clock source */
|
||||
SystemCoreClock = HSI_VALUE;
|
||||
break;
|
||||
case 0x04: /* HSE used as system clock source */
|
||||
SystemCoreClock = HSE_VALUE;
|
||||
break;
|
||||
case 0x08: /* PLL used as system clock source */
|
||||
|
||||
/* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N
|
||||
SYSCLK = PLL_VCO / PLL_P
|
||||
*/
|
||||
pllsource = (RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) >> 22;
|
||||
pllm = RCC->PLLCFGR & RCC_PLLCFGR_PLLM;
|
||||
|
||||
if (pllsource != 0)
|
||||
{
|
||||
/* HSE used as PLL clock source */
|
||||
pllvco = (HSE_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* HSI used as PLL clock source */
|
||||
pllvco = (HSI_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6);
|
||||
}
|
||||
|
||||
pllp = (((RCC->PLLCFGR & RCC_PLLCFGR_PLLP) >>16) + 1 ) *2;
|
||||
SystemCoreClock = pllvco/pllp;
|
||||
break;
|
||||
default:
|
||||
SystemCoreClock = HSI_VALUE;
|
||||
break;
|
||||
}
|
||||
/* Compute HCLK frequency --------------------------------------------------*/
|
||||
/* Get HCLK prescaler */
|
||||
tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4)];
|
||||
/* HCLK frequency */
|
||||
SystemCoreClock >>= tmp;
|
||||
}
|
||||
|
||||
#if defined (DATA_IN_ExtSRAM) && defined (DATA_IN_ExtSDRAM)
|
||||
#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\
|
||||
|| defined(STM32F469xx) || defined(STM32F479xx)
|
||||
/**
|
||||
* @brief Setup the external memory controller.
|
||||
* Called in startup_stm32f4xx.s before jump to main.
|
||||
* This function configures the external memories (SRAM/SDRAM)
|
||||
* This SRAM/SDRAM will be used as program data memory (including heap and stack).
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void SystemInit_ExtMemCtl(void)
|
||||
{
|
||||
__IO uint32_t tmp = 0x00;
|
||||
|
||||
register uint32_t tmpreg = 0, timeout = 0xFFFF;
|
||||
register __IO uint32_t index;
|
||||
|
||||
/* Enable GPIOC, GPIOD, GPIOE, GPIOF, GPIOG, GPIOH and GPIOI interface clock */
|
||||
RCC->AHB1ENR |= 0x000001F8;
|
||||
|
||||
/* Delay after an RCC peripheral clock enabling */
|
||||
tmp = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOCEN);
|
||||
|
||||
/* Connect PDx pins to FMC Alternate function */
|
||||
GPIOD->AFR[0] = 0x00CCC0CC;
|
||||
GPIOD->AFR[1] = 0xCCCCCCCC;
|
||||
/* Configure PDx pins in Alternate function mode */
|
||||
GPIOD->MODER = 0xAAAA0A8A;
|
||||
/* Configure PDx pins speed to 100 MHz */
|
||||
GPIOD->OSPEEDR = 0xFFFF0FCF;
|
||||
/* Configure PDx pins Output type to push-pull */
|
||||
GPIOD->OTYPER = 0x00000000;
|
||||
/* No pull-up, pull-down for PDx pins */
|
||||
GPIOD->PUPDR = 0x00000000;
|
||||
|
||||
/* Connect PEx pins to FMC Alternate function */
|
||||
GPIOE->AFR[0] = 0xC00CC0CC;
|
||||
GPIOE->AFR[1] = 0xCCCCCCCC;
|
||||
/* Configure PEx pins in Alternate function mode */
|
||||
GPIOE->MODER = 0xAAAA828A;
|
||||
/* Configure PEx pins speed to 100 MHz */
|
||||
GPIOE->OSPEEDR = 0xFFFFC3CF;
|
||||
/* Configure PEx pins Output type to push-pull */
|
||||
GPIOE->OTYPER = 0x00000000;
|
||||
/* No pull-up, pull-down for PEx pins */
|
||||
GPIOE->PUPDR = 0x00000000;
|
||||
|
||||
/* Connect PFx pins to FMC Alternate function */
|
||||
GPIOF->AFR[0] = 0xCCCCCCCC;
|
||||
GPIOF->AFR[1] = 0xCCCCCCCC;
|
||||
/* Configure PFx pins in Alternate function mode */
|
||||
GPIOF->MODER = 0xAA800AAA;
|
||||
/* Configure PFx pins speed to 50 MHz */
|
||||
GPIOF->OSPEEDR = 0xAA800AAA;
|
||||
/* Configure PFx pins Output type to push-pull */
|
||||
GPIOF->OTYPER = 0x00000000;
|
||||
/* No pull-up, pull-down for PFx pins */
|
||||
GPIOF->PUPDR = 0x00000000;
|
||||
|
||||
/* Connect PGx pins to FMC Alternate function */
|
||||
GPIOG->AFR[0] = 0xCCCCCCCC;
|
||||
GPIOG->AFR[1] = 0xCCCCCCCC;
|
||||
/* Configure PGx pins in Alternate function mode */
|
||||
GPIOG->MODER = 0xAAAAAAAA;
|
||||
/* Configure PGx pins speed to 50 MHz */
|
||||
GPIOG->OSPEEDR = 0xAAAAAAAA;
|
||||
/* Configure PGx pins Output type to push-pull */
|
||||
GPIOG->OTYPER = 0x00000000;
|
||||
/* No pull-up, pull-down for PGx pins */
|
||||
GPIOG->PUPDR = 0x00000000;
|
||||
|
||||
/* Connect PHx pins to FMC Alternate function */
|
||||
GPIOH->AFR[0] = 0x00C0CC00;
|
||||
GPIOH->AFR[1] = 0xCCCCCCCC;
|
||||
/* Configure PHx pins in Alternate function mode */
|
||||
GPIOH->MODER = 0xAAAA08A0;
|
||||
/* Configure PHx pins speed to 50 MHz */
|
||||
GPIOH->OSPEEDR = 0xAAAA08A0;
|
||||
/* Configure PHx pins Output type to push-pull */
|
||||
GPIOH->OTYPER = 0x00000000;
|
||||
/* No pull-up, pull-down for PHx pins */
|
||||
GPIOH->PUPDR = 0x00000000;
|
||||
|
||||
/* Connect PIx pins to FMC Alternate function */
|
||||
GPIOI->AFR[0] = 0xCCCCCCCC;
|
||||
GPIOI->AFR[1] = 0x00000CC0;
|
||||
/* Configure PIx pins in Alternate function mode */
|
||||
GPIOI->MODER = 0x0028AAAA;
|
||||
/* Configure PIx pins speed to 50 MHz */
|
||||
GPIOI->OSPEEDR = 0x0028AAAA;
|
||||
/* Configure PIx pins Output type to push-pull */
|
||||
GPIOI->OTYPER = 0x00000000;
|
||||
/* No pull-up, pull-down for PIx pins */
|
||||
GPIOI->PUPDR = 0x00000000;
|
||||
|
||||
/*-- FMC Configuration -------------------------------------------------------*/
|
||||
/* Enable the FMC interface clock */
|
||||
RCC->AHB3ENR |= 0x00000001;
|
||||
/* Delay after an RCC peripheral clock enabling */
|
||||
tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FMCEN);
|
||||
|
||||
FMC_Bank5_6->SDCR[0] = 0x000019E4;
|
||||
FMC_Bank5_6->SDTR[0] = 0x01115351;
|
||||
|
||||
/* SDRAM initialization sequence */
|
||||
/* Clock enable command */
|
||||
FMC_Bank5_6->SDCMR = 0x00000011;
|
||||
tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
|
||||
while((tmpreg != 0) && (timeout-- > 0))
|
||||
{
|
||||
tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
|
||||
}
|
||||
|
||||
/* Delay */
|
||||
for (index = 0; index<1000; index++);
|
||||
|
||||
/* PALL command */
|
||||
FMC_Bank5_6->SDCMR = 0x00000012;
|
||||
timeout = 0xFFFF;
|
||||
while((tmpreg != 0) && (timeout-- > 0))
|
||||
{
|
||||
tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
|
||||
}
|
||||
|
||||
/* Auto refresh command */
|
||||
FMC_Bank5_6->SDCMR = 0x00000073;
|
||||
timeout = 0xFFFF;
|
||||
while((tmpreg != 0) && (timeout-- > 0))
|
||||
{
|
||||
tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
|
||||
}
|
||||
|
||||
/* MRD register program */
|
||||
FMC_Bank5_6->SDCMR = 0x00046014;
|
||||
timeout = 0xFFFF;
|
||||
while((tmpreg != 0) && (timeout-- > 0))
|
||||
{
|
||||
tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
|
||||
}
|
||||
|
||||
/* Set refresh count */
|
||||
tmpreg = FMC_Bank5_6->SDRTR;
|
||||
FMC_Bank5_6->SDRTR = (tmpreg | (0x0000027C<<1));
|
||||
|
||||
/* Disable write protection */
|
||||
tmpreg = FMC_Bank5_6->SDCR[0];
|
||||
FMC_Bank5_6->SDCR[0] = (tmpreg & 0xFFFFFDFF);
|
||||
|
||||
#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)
|
||||
/* Configure and enable Bank1_SRAM2 */
|
||||
FMC_Bank1->BTCR[2] = 0x00001011;
|
||||
FMC_Bank1->BTCR[3] = 0x00000201;
|
||||
FMC_Bank1E->BWTR[2] = 0x0fffffff;
|
||||
#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx */
|
||||
#if defined(STM32F469xx) || defined(STM32F479xx)
|
||||
/* Configure and enable Bank1_SRAM2 */
|
||||
FMC_Bank1->BTCR[2] = 0x00001091;
|
||||
FMC_Bank1->BTCR[3] = 0x00110212;
|
||||
FMC_Bank1E->BWTR[2] = 0x0fffffff;
|
||||
#endif /* STM32F469xx || STM32F479xx */
|
||||
|
||||
(void)(tmp);
|
||||
}
|
||||
#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F469xx || STM32F479xx */
|
||||
#elif defined (DATA_IN_ExtSRAM) || defined (DATA_IN_ExtSDRAM)
|
||||
/**
|
||||
* @brief Setup the external memory controller.
|
||||
* Called in startup_stm32f4xx.s before jump to main.
|
||||
* This function configures the external memories (SRAM/SDRAM)
|
||||
* This SRAM/SDRAM will be used as program data memory (including heap and stack).
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void SystemInit_ExtMemCtl(void)
|
||||
{
|
||||
__IO uint32_t tmp = 0x00;
|
||||
#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\
|
||||
|| defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx)
|
||||
#if defined (DATA_IN_ExtSDRAM)
|
||||
register uint32_t tmpreg = 0, timeout = 0xFFFF;
|
||||
register __IO uint32_t index;
|
||||
|
||||
#if defined(STM32F446xx)
|
||||
/* Enable GPIOA, GPIOC, GPIOD, GPIOE, GPIOF, GPIOG interface
|
||||
clock */
|
||||
RCC->AHB1ENR |= 0x0000007D;
|
||||
#else
|
||||
/* Enable GPIOC, GPIOD, GPIOE, GPIOF, GPIOG, GPIOH and GPIOI interface
|
||||
clock */
|
||||
RCC->AHB1ENR |= 0x000001F8;
|
||||
#endif /* STM32F446xx */
|
||||
/* Delay after an RCC peripheral clock enabling */
|
||||
tmp = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOCEN);
|
||||
|
||||
#if defined(STM32F446xx)
|
||||
/* Connect PAx pins to FMC Alternate function */
|
||||
GPIOA->AFR[0] |= 0xC0000000;
|
||||
GPIOA->AFR[1] |= 0x00000000;
|
||||
/* Configure PDx pins in Alternate function mode */
|
||||
GPIOA->MODER |= 0x00008000;
|
||||
/* Configure PDx pins speed to 50 MHz */
|
||||
GPIOA->OSPEEDR |= 0x00008000;
|
||||
/* Configure PDx pins Output type to push-pull */
|
||||
GPIOA->OTYPER |= 0x00000000;
|
||||
/* No pull-up, pull-down for PDx pins */
|
||||
GPIOA->PUPDR |= 0x00000000;
|
||||
|
||||
/* Connect PCx pins to FMC Alternate function */
|
||||
GPIOC->AFR[0] |= 0x00CC0000;
|
||||
GPIOC->AFR[1] |= 0x00000000;
|
||||
/* Configure PDx pins in Alternate function mode */
|
||||
GPIOC->MODER |= 0x00000A00;
|
||||
/* Configure PDx pins speed to 50 MHz */
|
||||
GPIOC->OSPEEDR |= 0x00000A00;
|
||||
/* Configure PDx pins Output type to push-pull */
|
||||
GPIOC->OTYPER |= 0x00000000;
|
||||
/* No pull-up, pull-down for PDx pins */
|
||||
GPIOC->PUPDR |= 0x00000000;
|
||||
#endif /* STM32F446xx */
|
||||
|
||||
/* Connect PDx pins to FMC Alternate function */
|
||||
GPIOD->AFR[0] = 0x000000CC;
|
||||
GPIOD->AFR[1] = 0xCC000CCC;
|
||||
/* Configure PDx pins in Alternate function mode */
|
||||
GPIOD->MODER = 0xA02A000A;
|
||||
/* Configure PDx pins speed to 50 MHz */
|
||||
GPIOD->OSPEEDR = 0xA02A000A;
|
||||
/* Configure PDx pins Output type to push-pull */
|
||||
GPIOD->OTYPER = 0x00000000;
|
||||
/* No pull-up, pull-down for PDx pins */
|
||||
GPIOD->PUPDR = 0x00000000;
|
||||
|
||||
/* Connect PEx pins to FMC Alternate function */
|
||||
GPIOE->AFR[0] = 0xC00000CC;
|
||||
GPIOE->AFR[1] = 0xCCCCCCCC;
|
||||
/* Configure PEx pins in Alternate function mode */
|
||||
GPIOE->MODER = 0xAAAA800A;
|
||||
/* Configure PEx pins speed to 50 MHz */
|
||||
GPIOE->OSPEEDR = 0xAAAA800A;
|
||||
/* Configure PEx pins Output type to push-pull */
|
||||
GPIOE->OTYPER = 0x00000000;
|
||||
/* No pull-up, pull-down for PEx pins */
|
||||
GPIOE->PUPDR = 0x00000000;
|
||||
|
||||
/* Connect PFx pins to FMC Alternate function */
|
||||
GPIOF->AFR[0] = 0xCCCCCCCC;
|
||||
GPIOF->AFR[1] = 0xCCCCCCCC;
|
||||
/* Configure PFx pins in Alternate function mode */
|
||||
GPIOF->MODER = 0xAA800AAA;
|
||||
/* Configure PFx pins speed to 50 MHz */
|
||||
GPIOF->OSPEEDR = 0xAA800AAA;
|
||||
/* Configure PFx pins Output type to push-pull */
|
||||
GPIOF->OTYPER = 0x00000000;
|
||||
/* No pull-up, pull-down for PFx pins */
|
||||
GPIOF->PUPDR = 0x00000000;
|
||||
|
||||
/* Connect PGx pins to FMC Alternate function */
|
||||
GPIOG->AFR[0] = 0xCCCCCCCC;
|
||||
GPIOG->AFR[1] = 0xCCCCCCCC;
|
||||
/* Configure PGx pins in Alternate function mode */
|
||||
GPIOG->MODER = 0xAAAAAAAA;
|
||||
/* Configure PGx pins speed to 50 MHz */
|
||||
GPIOG->OSPEEDR = 0xAAAAAAAA;
|
||||
/* Configure PGx pins Output type to push-pull */
|
||||
GPIOG->OTYPER = 0x00000000;
|
||||
/* No pull-up, pull-down for PGx pins */
|
||||
GPIOG->PUPDR = 0x00000000;
|
||||
|
||||
#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\
|
||||
|| defined(STM32F469xx) || defined(STM32F479xx)
|
||||
/* Connect PHx pins to FMC Alternate function */
|
||||
GPIOH->AFR[0] = 0x00C0CC00;
|
||||
GPIOH->AFR[1] = 0xCCCCCCCC;
|
||||
/* Configure PHx pins in Alternate function mode */
|
||||
GPIOH->MODER = 0xAAAA08A0;
|
||||
/* Configure PHx pins speed to 50 MHz */
|
||||
GPIOH->OSPEEDR = 0xAAAA08A0;
|
||||
/* Configure PHx pins Output type to push-pull */
|
||||
GPIOH->OTYPER = 0x00000000;
|
||||
/* No pull-up, pull-down for PHx pins */
|
||||
GPIOH->PUPDR = 0x00000000;
|
||||
|
||||
/* Connect PIx pins to FMC Alternate function */
|
||||
GPIOI->AFR[0] = 0xCCCCCCCC;
|
||||
GPIOI->AFR[1] = 0x00000CC0;
|
||||
/* Configure PIx pins in Alternate function mode */
|
||||
GPIOI->MODER = 0x0028AAAA;
|
||||
/* Configure PIx pins speed to 50 MHz */
|
||||
GPIOI->OSPEEDR = 0x0028AAAA;
|
||||
/* Configure PIx pins Output type to push-pull */
|
||||
GPIOI->OTYPER = 0x00000000;
|
||||
/* No pull-up, pull-down for PIx pins */
|
||||
GPIOI->PUPDR = 0x00000000;
|
||||
#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F469xx || STM32F479xx */
|
||||
|
||||
/*-- FMC Configuration -------------------------------------------------------*/
|
||||
/* Enable the FMC interface clock */
|
||||
RCC->AHB3ENR |= 0x00000001;
|
||||
/* Delay after an RCC peripheral clock enabling */
|
||||
tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FMCEN);
|
||||
|
||||
/* Configure and enable SDRAM bank1 */
|
||||
#if defined(STM32F446xx)
|
||||
FMC_Bank5_6->SDCR[0] = 0x00001954;
|
||||
#else
|
||||
FMC_Bank5_6->SDCR[0] = 0x000019E4;
|
||||
#endif /* STM32F446xx */
|
||||
FMC_Bank5_6->SDTR[0] = 0x01115351;
|
||||
|
||||
/* SDRAM initialization sequence */
|
||||
/* Clock enable command */
|
||||
FMC_Bank5_6->SDCMR = 0x00000011;
|
||||
tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
|
||||
while((tmpreg != 0) && (timeout-- > 0))
|
||||
{
|
||||
tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
|
||||
}
|
||||
|
||||
/* Delay */
|
||||
for (index = 0; index<1000; index++);
|
||||
|
||||
/* PALL command */
|
||||
FMC_Bank5_6->SDCMR = 0x00000012;
|
||||
timeout = 0xFFFF;
|
||||
while((tmpreg != 0) && (timeout-- > 0))
|
||||
{
|
||||
tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
|
||||
}
|
||||
|
||||
/* Auto refresh command */
|
||||
#if defined(STM32F446xx)
|
||||
FMC_Bank5_6->SDCMR = 0x000000F3;
|
||||
#else
|
||||
FMC_Bank5_6->SDCMR = 0x00000073;
|
||||
#endif /* STM32F446xx */
|
||||
timeout = 0xFFFF;
|
||||
while((tmpreg != 0) && (timeout-- > 0))
|
||||
{
|
||||
tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
|
||||
}
|
||||
|
||||
/* MRD register program */
|
||||
#if defined(STM32F446xx)
|
||||
FMC_Bank5_6->SDCMR = 0x00044014;
|
||||
#else
|
||||
FMC_Bank5_6->SDCMR = 0x00046014;
|
||||
#endif /* STM32F446xx */
|
||||
timeout = 0xFFFF;
|
||||
while((tmpreg != 0) && (timeout-- > 0))
|
||||
{
|
||||
tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
|
||||
}
|
||||
|
||||
/* Set refresh count */
|
||||
tmpreg = FMC_Bank5_6->SDRTR;
|
||||
#if defined(STM32F446xx)
|
||||
FMC_Bank5_6->SDRTR = (tmpreg | (0x0000050C<<1));
|
||||
#else
|
||||
FMC_Bank5_6->SDRTR = (tmpreg | (0x0000027C<<1));
|
||||
#endif /* STM32F446xx */
|
||||
|
||||
/* Disable write protection */
|
||||
tmpreg = FMC_Bank5_6->SDCR[0];
|
||||
FMC_Bank5_6->SDCR[0] = (tmpreg & 0xFFFFFDFF);
|
||||
#endif /* DATA_IN_ExtSDRAM */
|
||||
#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F446xx || STM32F469xx || STM32F479xx */
|
||||
|
||||
#if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx) || defined(STM32F417xx)\
|
||||
|| defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\
|
||||
|| defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F412Zx) || defined(STM32F412Vx)
|
||||
|
||||
#if defined(DATA_IN_ExtSRAM)
|
||||
/*-- GPIOs Configuration -----------------------------------------------------*/
|
||||
/* Enable GPIOD, GPIOE, GPIOF and GPIOG interface clock */
|
||||
RCC->AHB1ENR |= 0x00000078;
|
||||
/* Delay after an RCC peripheral clock enabling */
|
||||
tmp = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIODEN);
|
||||
|
||||
/* Connect PDx pins to FMC Alternate function */
|
||||
GPIOD->AFR[0] = 0x00CCC0CC;
|
||||
GPIOD->AFR[1] = 0xCCCCCCCC;
|
||||
/* Configure PDx pins in Alternate function mode */
|
||||
GPIOD->MODER = 0xAAAA0A8A;
|
||||
/* Configure PDx pins speed to 100 MHz */
|
||||
GPIOD->OSPEEDR = 0xFFFF0FCF;
|
||||
/* Configure PDx pins Output type to push-pull */
|
||||
GPIOD->OTYPER = 0x00000000;
|
||||
/* No pull-up, pull-down for PDx pins */
|
||||
GPIOD->PUPDR = 0x00000000;
|
||||
|
||||
/* Connect PEx pins to FMC Alternate function */
|
||||
GPIOE->AFR[0] = 0xC00CC0CC;
|
||||
GPIOE->AFR[1] = 0xCCCCCCCC;
|
||||
/* Configure PEx pins in Alternate function mode */
|
||||
GPIOE->MODER = 0xAAAA828A;
|
||||
/* Configure PEx pins speed to 100 MHz */
|
||||
GPIOE->OSPEEDR = 0xFFFFC3CF;
|
||||
/* Configure PEx pins Output type to push-pull */
|
||||
GPIOE->OTYPER = 0x00000000;
|
||||
/* No pull-up, pull-down for PEx pins */
|
||||
GPIOE->PUPDR = 0x00000000;
|
||||
|
||||
/* Connect PFx pins to FMC Alternate function */
|
||||
GPIOF->AFR[0] = 0x00CCCCCC;
|
||||
GPIOF->AFR[1] = 0xCCCC0000;
|
||||
/* Configure PFx pins in Alternate function mode */
|
||||
GPIOF->MODER = 0xAA000AAA;
|
||||
/* Configure PFx pins speed to 100 MHz */
|
||||
GPIOF->OSPEEDR = 0xFF000FFF;
|
||||
/* Configure PFx pins Output type to push-pull */
|
||||
GPIOF->OTYPER = 0x00000000;
|
||||
/* No pull-up, pull-down for PFx pins */
|
||||
GPIOF->PUPDR = 0x00000000;
|
||||
|
||||
/* Connect PGx pins to FMC Alternate function */
|
||||
GPIOG->AFR[0] = 0x00CCCCCC;
|
||||
GPIOG->AFR[1] = 0x000000C0;
|
||||
/* Configure PGx pins in Alternate function mode */
|
||||
GPIOG->MODER = 0x00085AAA;
|
||||
/* Configure PGx pins speed to 100 MHz */
|
||||
GPIOG->OSPEEDR = 0x000CAFFF;
|
||||
/* Configure PGx pins Output type to push-pull */
|
||||
GPIOG->OTYPER = 0x00000000;
|
||||
/* No pull-up, pull-down for PGx pins */
|
||||
GPIOG->PUPDR = 0x00000000;
|
||||
|
||||
/*-- FMC/FSMC Configuration --------------------------------------------------*/
|
||||
/* Enable the FMC/FSMC interface clock */
|
||||
RCC->AHB3ENR |= 0x00000001;
|
||||
|
||||
#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)
|
||||
/* Delay after an RCC peripheral clock enabling */
|
||||
tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FMCEN);
|
||||
/* Configure and enable Bank1_SRAM2 */
|
||||
FMC_Bank1->BTCR[2] = 0x00001011;
|
||||
FMC_Bank1->BTCR[3] = 0x00000201;
|
||||
FMC_Bank1E->BWTR[2] = 0x0fffffff;
|
||||
#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx */
|
||||
#if defined(STM32F469xx) || defined(STM32F479xx)
|
||||
/* Delay after an RCC peripheral clock enabling */
|
||||
tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FMCEN);
|
||||
/* Configure and enable Bank1_SRAM2 */
|
||||
FMC_Bank1->BTCR[2] = 0x00001091;
|
||||
FMC_Bank1->BTCR[3] = 0x00110212;
|
||||
FMC_Bank1E->BWTR[2] = 0x0fffffff;
|
||||
#endif /* STM32F469xx || STM32F479xx */
|
||||
#if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx)|| defined(STM32F417xx)\
|
||||
|| defined(STM32F412Zx) || defined(STM32F412Vx)
|
||||
/* Delay after an RCC peripheral clock enabling */
|
||||
tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FSMCEN);
|
||||
/* Configure and enable Bank1_SRAM2 */
|
||||
FSMC_Bank1->BTCR[2] = 0x00001011;
|
||||
FSMC_Bank1->BTCR[3] = 0x00000201;
|
||||
FSMC_Bank1E->BWTR[2] = 0x0FFFFFFF;
|
||||
#endif /* STM32F405xx || STM32F415xx || STM32F407xx || STM32F417xx || STM32F412Zx || STM32F412Vx */
|
||||
|
||||
#endif /* DATA_IN_ExtSRAM */
|
||||
#endif /* STM32F405xx || STM32F415xx || STM32F407xx || STM32F417xx || STM32F427xx || STM32F437xx ||\
|
||||
STM32F429xx || STM32F439xx || STM32F469xx || STM32F479xx || STM32F412Zx || STM32F412Vx */
|
||||
(void)(tmp);
|
||||
}
|
||||
#endif /* DATA_IN_ExtSRAM && DATA_IN_ExtSDRAM */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
148
demo/fw/stm32f407.ld
Normal file
148
demo/fw/stm32f407.ld
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
MEMORY
|
||||
{
|
||||
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 512K
|
||||
RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 128K
|
||||
CCMRAM (rwx) : ORIGIN = 0x10000000, LENGTH = 64K
|
||||
BACKUP (rwx) : ORIGIN = 0x40024000, LENGTH = 4K
|
||||
}
|
||||
|
||||
/* Entry Point */
|
||||
ENTRY(Reset_Handler)
|
||||
|
||||
/* Highest address of the user mode stack */
|
||||
_estack = 0x20020000; /* end of RAM */
|
||||
/* Generate a link error if heap and stack don't fit into RAM */
|
||||
_Min_Heap_Size = 0x200;; /* required amount of heap */
|
||||
_Min_Stack_Size = 0x400;; /* required amount of stack */
|
||||
|
||||
/* Define output sections */
|
||||
SECTIONS
|
||||
{
|
||||
/* The startup code goes first into FLASH */
|
||||
.isr_vector :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
KEEP(*(.isr_vector)) /* Startup code */
|
||||
. = ALIGN(4);
|
||||
} >FLASH
|
||||
|
||||
/* The program code and other data goes into FLASH */
|
||||
.text :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
*(.text) /* .text sections (code) */
|
||||
*(.text*) /* .text* sections (code) */
|
||||
*(.glue_7) /* glue arm to thumb code */
|
||||
*(.glue_7t) /* glue thumb to arm code */
|
||||
*(.eh_frame)
|
||||
|
||||
KEEP (*(.init))
|
||||
KEEP (*(.fini))
|
||||
|
||||
. = ALIGN(4);
|
||||
_etext = .; /* define a global symbols at end of code */
|
||||
} >FLASH
|
||||
|
||||
/* Constant data goes into FLASH */
|
||||
.rodata :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
*(.rodata) /* .rodata sections (constants, strings, etc.) */
|
||||
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
|
||||
. = ALIGN(4);
|
||||
} >FLASH
|
||||
|
||||
.ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH
|
||||
.ARM : {
|
||||
__exidx_start = .;
|
||||
*(.ARM.exidx*)
|
||||
__exidx_end = .;
|
||||
} >FLASH
|
||||
|
||||
.preinit_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||
KEEP (*(.preinit_array*))
|
||||
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||
} >FLASH
|
||||
.init_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__init_array_start = .);
|
||||
KEEP (*(SORT(.init_array.*)))
|
||||
KEEP (*(.init_array*))
|
||||
PROVIDE_HIDDEN (__init_array_end = .);
|
||||
} >FLASH
|
||||
.fini_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||
KEEP (*(SORT(.fini_array.*)))
|
||||
KEEP (*(.fini_array*))
|
||||
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||
} >FLASH
|
||||
|
||||
/* used by the startup to initialize data */
|
||||
_sidata = LOADADDR(.data);
|
||||
|
||||
/* Initialized data sections goes into RAM, load LMA copy after code */
|
||||
.data :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
_sdata = .; /* create a global symbol at data start */
|
||||
*(.data) /* .data sections */
|
||||
*(.data*) /* .data* sections */
|
||||
|
||||
. = ALIGN(4);
|
||||
_edata = .; /* define a global symbol at data end */
|
||||
} >RAM AT> FLASH
|
||||
|
||||
_siccmram = LOADADDR(.ccmram);
|
||||
|
||||
/* CCM-RAM section
|
||||
*
|
||||
* IMPORTANT NOTE!
|
||||
* If initialized variables will be placed in this section,
|
||||
* the startup code needs to be modified to copy the init-values.
|
||||
*/
|
||||
.ccmram :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
_sccmram = .; /* create a global symbol at ccmram start */
|
||||
*(.ccmram)
|
||||
*(.ccmram*)
|
||||
|
||||
. = ALIGN(4);
|
||||
_eccmram = .; /* create a global symbol at ccmram end */
|
||||
} >CCMRAM AT> FLASH
|
||||
|
||||
|
||||
/* Uninitialized data section */
|
||||
. = ALIGN(4);
|
||||
.bss :
|
||||
{
|
||||
/* This is used by the startup in order to initialize the .bss secion */
|
||||
_sbss = .; /* define a global symbol at bss start */
|
||||
__bss_start__ = _sbss;
|
||||
*(.bss)
|
||||
*(.bss*)
|
||||
*(COMMON)
|
||||
|
||||
. = ALIGN(4);
|
||||
_ebss = .; /* define a global symbol at bss end */
|
||||
__bss_end__ = _ebss;
|
||||
} >RAM
|
||||
|
||||
/* User_heap_stack section, used to check that there is enough RAM left */
|
||||
._user_heap_stack :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
PROVIDE ( end = . );
|
||||
PROVIDE ( _end = . );
|
||||
. = . + _Min_Heap_Size;
|
||||
. = . + _Min_Stack_Size;
|
||||
. = ALIGN(4);
|
||||
} >RAM
|
||||
|
||||
.ARM.attributes 0 : { *(.ARM.attributes) }
|
||||
}
|
||||
|
||||
|
||||
1
demo/fw/tinyprintf
Submodule
1
demo/fw/tinyprintf
Submodule
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 2ee30120ec15e321566b43f83c731d060bb437f5
|
||||
126
demo/fw/tools/ldparser.py
Normal file
126
demo/fw/tools/ldparser.py
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
|
||||
import sys
|
||||
|
||||
import pyparsing as pp
|
||||
from pyparsing import pyparsing_common as ppc
|
||||
|
||||
LPAREN, RPAREN, LBRACE, RBRACE, LBROK, RBROK, COLON, SEMICOLON, EQUALS, COMMA = map(pp.Suppress, '(){}<>:;=,')
|
||||
|
||||
parse_suffix_int = lambda lit: int(lit[:-1]) * (10**(3*(1 + 'kmgtpe'.find(lit[-1].lower()))))
|
||||
si_suffix = pp.oneOf('k m g t p e', caseless=True)
|
||||
|
||||
numeric_literal = pp.Regex('0x[0-9a-fA-F]+').setName('hex int').setParseAction(pp.tokenMap(int, 16)) \
|
||||
| (pp.Regex('[0-9]+[kKmMgGtTpPeE]')).setName('size int').setParseAction(pp.tokenMap(parse_suffix_int)) \
|
||||
| pp.Word(pp.nums).setName('int').setParseAction(pp.tokenMap(int))
|
||||
access_def = pp.Regex('[rR]?[wW]?[xX]?').setName('access literal').setParseAction(pp.tokenMap(str.lower))
|
||||
|
||||
origin_expr = pp.Suppress(pp.CaselessKeyword('ORIGIN')) + EQUALS + numeric_literal
|
||||
length_expr = pp.Suppress(pp.CaselessKeyword('LENGTH')) + EQUALS + numeric_literal
|
||||
mem_expr = pp.Group(ppc.identifier + LPAREN + access_def + RPAREN + COLON + origin_expr + COMMA + length_expr)
|
||||
mem_contents = pp.ZeroOrMore(mem_expr)
|
||||
|
||||
mem_toplevel = pp.CaselessKeyword("MEMORY") + pp.Group(LBRACE + pp.Optional(mem_contents, []) + RBRACE)
|
||||
|
||||
glob = pp.Word(pp.alphanums + '._*')
|
||||
match_expr = pp.Forward()
|
||||
assignment = pp.Forward()
|
||||
funccall = pp.Group(pp.Word(pp.alphas + '_') + LPAREN + (assignment | numeric_literal | match_expr | glob | ppc.identifier) + RPAREN + pp.Optional(SEMICOLON))
|
||||
value = numeric_literal | funccall | ppc.identifier | '.'
|
||||
formula = (value + pp.oneOf('+ = * / %') + value) | value
|
||||
# suppress stray semicolons
|
||||
assignment << (SEMICOLON | pp.Group((ppc.identifier | '.') + EQUALS + (formula | value) + pp.Optional(SEMICOLON)))
|
||||
match_expr << (glob + LPAREN + pp.OneOrMore(funccall | glob) + RPAREN)
|
||||
|
||||
section_contents = pp.ZeroOrMore(assignment | funccall | match_expr);
|
||||
|
||||
section_name = pp.Regex('\.[a-zA-Z0-9_.]+')
|
||||
section_def = pp.Group(section_name + pp.Optional(numeric_literal) + COLON + LBRACE + pp.Group(section_contents) +
|
||||
RBRACE + pp.Optional(RBROK + ppc.identifier + pp.Optional('AT' + RBROK + ppc.identifier)))
|
||||
sec_contents = pp.ZeroOrMore(section_def | assignment)
|
||||
|
||||
sections_toplevel = pp.Group(pp.CaselessKeyword("SECTIONS").suppress() + LBRACE + sec_contents + RBRACE)
|
||||
|
||||
toplevel_elements = mem_toplevel | funccall | sections_toplevel | assignment
|
||||
ldscript = pp.Group(pp.ZeroOrMore(toplevel_elements))
|
||||
ldscript.ignore(pp.cppStyleComment)
|
||||
|
||||
if __name__ == '__main__':
|
||||
import argparse
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('linker_script', type=argparse.FileType('r'))
|
||||
args = parser.parse_args()
|
||||
|
||||
#print(mem_expr.parseString('FLASH (rx) : ORIGIN = 0x0800000, LENGTH = 512K', parseAll=True))
|
||||
# print(ldscript.parseString('''
|
||||
# /* Entry Point */
|
||||
# ENTRY(Reset_Handler)
|
||||
#
|
||||
# /* Highest address of the user mode stack */
|
||||
# _estack = 0x20020000; /* end of RAM */
|
||||
# /* Generate a link error if heap and stack don't fit into RAM */
|
||||
# _Min_Heap_Size = 0x200;; /* required amount of heap */
|
||||
# _Min_Stack_Size = 0x400;; /* required amount of stack */
|
||||
# ''', parseAll=True))
|
||||
|
||||
print(ldscript.parseFile(args.linker_script, parseAll=True))
|
||||
#print(funccall.parseString('KEEP(*(.isr_vector))'))
|
||||
#print(section_contents.parseString('''
|
||||
# . = ALIGN(4);
|
||||
# KEEP(*(.isr_vector)) /* Startup code */
|
||||
# . = ALIGN(4);
|
||||
# ''', parseAll=True))
|
||||
|
||||
#print(section_def.parseString('''
|
||||
# .text :
|
||||
# {
|
||||
# . = ALIGN(4);
|
||||
# *(.text) /* .text sections (code) */
|
||||
# *(.text*) /* .text* sections (code) */
|
||||
# *(.glue_7) /* glue arm to thumb code */
|
||||
# *(.glue_7t) /* glue thumb to arm code */
|
||||
# *(.eh_frame)
|
||||
#
|
||||
# KEEP (*(.init))
|
||||
# KEEP (*(.fini))
|
||||
#
|
||||
# . = ALIGN(4);
|
||||
# _etext = .; /* define a global symbols at end of code */
|
||||
# } >FLASH
|
||||
# ''', parseAll=True))
|
||||
|
||||
#print(section_def.parseString('.ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH', parseAll=True))
|
||||
|
||||
#print(assignment.parseString('__preinit_array_start = .', parseAll=True))
|
||||
#print(assignment.parseString('a = 23', parseAll=True))
|
||||
#print(funccall.parseString('foo (a=23)', parseAll=True))
|
||||
#print(funccall.parseString('PROVIDE_HIDDEN (__preinit_array_start = .);', parseAll=True))
|
||||
#print(section_def.parseString('''
|
||||
# .preinit_array :
|
||||
# {
|
||||
# PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||
# KEEP (*(.preinit_array*))
|
||||
# PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||
# } >FLASH''', parseAll=True))
|
||||
#print(match_expr.parseString('*(SORT(.init_array.*))', parseAll=True))
|
||||
#print(funccall.parseString('KEEP (*(SORT(.init_array.*)))', parseAll=True))
|
||||
#print(section_def.parseString('''
|
||||
# .init_array :
|
||||
# {
|
||||
# PROVIDE_HIDDEN (__init_array_start = .);
|
||||
# KEEP (*(SORT(.init_array.*)))
|
||||
# KEEP (*(.init_array*))
|
||||
# PROVIDE_HIDDEN (__init_array_end = .);
|
||||
# } >FLASH
|
||||
# ''', parseAll=True))
|
||||
|
||||
#print(match_expr.parseString('*(.ARM.extab* .gnu.linkonce.armextab.*)', parseAll=True))
|
||||
#print(formula.parseString('. + _Min_Heap_Size', parseAll=True))
|
||||
#print(assignment.parseString('. = . + _Min_Heap_Size;', parseAll=True))
|
||||
#print(sections_toplevel.parseString('''
|
||||
# SECTIONS
|
||||
# {
|
||||
# .ARMattributes : { }
|
||||
# }
|
||||
# ''', parseAll=True))
|
||||
#sys.exit(0)
|
||||
|
||||
276
demo/fw/tools/linkmem.py
Normal file
276
demo/fw/tools/linkmem.py
Normal file
|
|
@ -0,0 +1,276 @@
|
|||
|
||||
import tempfile
|
||||
import os
|
||||
from os import path
|
||||
import sys
|
||||
import re
|
||||
import subprocess
|
||||
from contextlib import contextmanager
|
||||
from collections import defaultdict
|
||||
import colorsys
|
||||
|
||||
import cxxfilt
|
||||
from elftools.elf.elffile import ELFFile
|
||||
from elftools.elf.enums import ENUM_ST_SHNDX
|
||||
from elftools.elf.descriptions import describe_symbol_type, describe_sh_type
|
||||
import libarchive
|
||||
import matplotlib.cm
|
||||
|
||||
@contextmanager
|
||||
def chdir(newdir):
|
||||
old_cwd = os.getcwd()
|
||||
try:
|
||||
os.chdir(newdir)
|
||||
yield
|
||||
finally:
|
||||
os.chdir(old_cwd)
|
||||
|
||||
def keep_last(it, first=None):
|
||||
last = first
|
||||
for elem in it:
|
||||
yield last, elem
|
||||
last = elem
|
||||
|
||||
def delim(start, end, it, first_only=True):
|
||||
found = False
|
||||
for elem in it:
|
||||
if end(elem):
|
||||
if first_only:
|
||||
return
|
||||
found = False
|
||||
elif start(elem):
|
||||
found = True
|
||||
elif found:
|
||||
yield elem
|
||||
|
||||
def delim_prefix(start, end, it):
|
||||
yield from delim(lambda l: l.startswith(start), lambda l: end is not None and l.startswith(end), it)
|
||||
|
||||
def trace_source_files(linker, cmdline, trace_sections=[], total_sections=['.text', '.data', '.rodata']):
|
||||
with tempfile.TemporaryDirectory() as tempdir:
|
||||
out_path = path.join(tempdir, 'output.elf')
|
||||
output = subprocess.check_output([linker, '-o', out_path, f'-Wl,--print-map', *cmdline])
|
||||
lines = [ line.strip() for line in output.decode().splitlines() ]
|
||||
# FIXME also find isr vector table references
|
||||
|
||||
defs = {}
|
||||
objs = defaultdict(lambda: 0)
|
||||
aliases = {}
|
||||
sec_name = None
|
||||
last_loc = None
|
||||
last_sym = None
|
||||
line_cont = None
|
||||
for last_line, line in keep_last(delim_prefix('Linker script and memory map', 'OUTPUT', lines), first=''):
|
||||
if not line or line.startswith('LOAD '):
|
||||
sec_name = None
|
||||
continue
|
||||
|
||||
# first part of continuation line
|
||||
if m := re.match('^(\.[0-9a-zA-Z-_.]+)$', line):
|
||||
line_cont = line
|
||||
sec_name = None
|
||||
continue
|
||||
|
||||
if line_cont:
|
||||
line = line_cont + ' ' + line
|
||||
line_cont = None
|
||||
|
||||
# -ffunction-sections/-fdata-sections section
|
||||
if m := re.match('^(\.[0-9a-zA-Z-_.]+)\.([0-9a-zA-Z-_.]+)\s+(0x[0-9a-f]+)\s+(0x[0-9a-f]+)\s+(\S+)$', line):
|
||||
sec, sym, loc, size, obj = m.groups()
|
||||
*_, sym = sym.rpartition('.')
|
||||
sym = cxxfilt.demangle(sym)
|
||||
size = int(size, 16)
|
||||
obj = path.abspath(obj)
|
||||
|
||||
if sec not in total_sections:
|
||||
size = 0
|
||||
|
||||
objs[obj] += size
|
||||
defs[sym] = (sec, size, obj)
|
||||
|
||||
sec_name, last_loc, last_sym = sec, loc, sym
|
||||
continue
|
||||
|
||||
# regular (no -ffunction-sections/-fdata-sections) section
|
||||
if m := re.match('^(\.[0-9a-zA-Z-_]+)\s+(0x[0-9a-f]+)\s+(0x[0-9a-f]+)\s+(\S+)$', line):
|
||||
sec, _loc, size, obj = m.groups()
|
||||
size = int(size, 16)
|
||||
obj = path.abspath(obj)
|
||||
|
||||
if sec in total_sections:
|
||||
objs[obj] += size
|
||||
|
||||
sec_name = sec
|
||||
last_loc, last_sym = None, None
|
||||
continue
|
||||
|
||||
# symbol def
|
||||
if m := re.match('^(0x[0-9a-f]+)\s+(\S+)$', line):
|
||||
loc, sym = m.groups()
|
||||
sym = cxxfilt.demangle(sym)
|
||||
loc = int(loc, 16)
|
||||
if sym in defs:
|
||||
continue
|
||||
|
||||
if loc == last_loc:
|
||||
assert last_sym is not None
|
||||
aliases[sym] = last_sym
|
||||
else:
|
||||
assert sec_name
|
||||
defs[sym] = (sec_name, None, obj)
|
||||
last_loc, last_sym = loc, sym
|
||||
|
||||
continue
|
||||
|
||||
refs = defaultdict(lambda: set())
|
||||
for sym, (sec, size, obj) in defs.items():
|
||||
fn, _, member = re.match('^([^()]+)(\((.+)\))?$', obj).groups()
|
||||
fn = path.abspath(fn)
|
||||
|
||||
if member:
|
||||
subprocess.check_call(['ar', 'x', '--output', tempdir, fn, member])
|
||||
fn = path.join(tempdir, member)
|
||||
|
||||
with open(fn, 'rb') as f:
|
||||
elf = ELFFile(f)
|
||||
|
||||
symtab = elf.get_section_by_name('.symtab')
|
||||
|
||||
symtab_demangled = { cxxfilt.demangle(nsym.name).replace(' ', ''): i
|
||||
for i, nsym in enumerate(symtab.iter_symbols()) }
|
||||
|
||||
s = set()
|
||||
sec_map = { sec.name: i for i, sec in enumerate(elf.iter_sections()) }
|
||||
matches = [ i for name, i in sec_map.items() if re.match(f'\.rel\..*\.{sym}', name) ]
|
||||
if matches:
|
||||
sec = elf.get_section(matches[0])
|
||||
for reloc in sec.iter_relocations():
|
||||
refsym = symtab.get_symbol(reloc['r_info_sym'])
|
||||
name = refsym.name if refsym.name else elf.get_section(refsym['st_shndx']).name.split('.')[-1]
|
||||
s.add(name)
|
||||
refs[sym] = s
|
||||
|
||||
for tsec in trace_sections:
|
||||
matches = [ i for name, i in sec_map.items() if name == f'.rel{tsec}' ]
|
||||
s = set()
|
||||
if matches:
|
||||
sec = elf.get_section(matches[0])
|
||||
for reloc in sec.iter_relocations():
|
||||
refsym = symtab.get_symbol(reloc['r_info_sym'])
|
||||
s.add(refsym.name)
|
||||
refs[tsec.replace('.', '_')] |= s
|
||||
|
||||
return objs, aliases, defs, refs
|
||||
|
||||
@contextmanager
|
||||
def wrap(leader='', print=print, left='{', right='}'):
|
||||
print(leader, left)
|
||||
yield lambda *args, **kwargs: print(' ', *args, **kwargs)
|
||||
print(right)
|
||||
|
||||
def mangle(name):
|
||||
return re.sub('[^a-zA-Z0-9_]', '_', name)
|
||||
|
||||
hexcolor = lambda r, g, b, *_a: f'#{int(r*255):02x}{int(g*255):02x}{int(b*255):02x}'
|
||||
def vhex(val):
|
||||
r,g,b,_a = matplotlib.cm.viridis(1.0-val)
|
||||
fc = hexcolor(r, g, b)
|
||||
h,s,v = colorsys.rgb_to_hsv(r,g,b)
|
||||
cc = '#000000' if v > 0.8 else '#ffffff'
|
||||
return fc, cc
|
||||
|
||||
if __name__ == '__main__':
|
||||
import argparse
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--trace-sections', type=str, action='append', default=[])
|
||||
parser.add_argument('--trim-stubs', type=str, action='append', default=[])
|
||||
parser.add_argument('--highlight-subdirs', type=str, default=None)
|
||||
parser.add_argument('linker_binary')
|
||||
parser.add_argument('linker_args', nargs=argparse.REMAINDER)
|
||||
args = parser.parse_args()
|
||||
|
||||
trace_sections = args.trace_sections
|
||||
trace_sections_mangled = { sec.replace('.', '_') for sec in trace_sections }
|
||||
objs, aliases, syms, refs = trace_source_files(args.linker_binary, args.linker_args, trace_sections)
|
||||
|
||||
clusters = defaultdict(lambda: [])
|
||||
for sym, (sec, size, obj) in syms.items():
|
||||
clusters[obj].append((sym, sec, size))
|
||||
|
||||
max_ssize = max(size or 0 for _sec, size, _obj in syms.values())
|
||||
max_osize = max(objs.values())
|
||||
|
||||
subdir_prefix = path.abspath(args.highlight_subdirs) + '/' if args.highlight_subdirs else '### NO HIGHLIGHT ###'
|
||||
first_comp = lambda le_path: path.dirname(le_path).partition(os.sep)[0]
|
||||
subdir_colors = sorted({ first_comp(obj[len(subdir_prefix):]) for obj in objs if obj.startswith(subdir_prefix) })
|
||||
subdir_colors = { path: hexcolor(*matplotlib.cm.Pastel1(i/len(subdir_colors))) for i, path in enumerate(subdir_colors) }
|
||||
|
||||
subdir_sizes = defaultdict(lambda: 0)
|
||||
for obj, size in objs.items():
|
||||
if not isinstance(size, int):
|
||||
continue
|
||||
if obj.startswith(subdir_prefix):
|
||||
subdir_sizes[first_comp(obj[len(subdir_prefix):])] += size
|
||||
else:
|
||||
subdir_sizes['<others>'] += size
|
||||
|
||||
print('Subdir sizes:', file=sys.stderr)
|
||||
for subdir, size in sorted(subdir_sizes.items(), key=lambda x: x[1]):
|
||||
print(f'{subdir:>20}: {size:>6,d} B', file=sys.stderr)
|
||||
|
||||
def lookup_highlight(path):
|
||||
if args.highlight_subdirs:
|
||||
if obj.startswith(subdir_prefix):
|
||||
highlight_head = first_comp(path[len(subdir_prefix):])
|
||||
return subdir_colors[highlight_head], highlight_head
|
||||
else:
|
||||
return '#e0e0e0', None
|
||||
else:
|
||||
return '#ddf7f4', None
|
||||
|
||||
with wrap('digraph G', print) as lvl1print:
|
||||
print('size="23.4,16.5!";')
|
||||
print('graph [fontsize=40];')
|
||||
print('node [fontsize=40];')
|
||||
#print('ratio="fill";')
|
||||
|
||||
print('rankdir=LR;')
|
||||
print('ranksep=5;')
|
||||
print('nodesep=0.2;')
|
||||
print()
|
||||
|
||||
for i, (obj, obj_syms) in enumerate(clusters.items()):
|
||||
with wrap(f'subgraph cluster_{i}', lvl1print) as lvl2print:
|
||||
print('style = "filled";')
|
||||
highlight_color, highlight_head = lookup_highlight(obj)
|
||||
print(f'bgcolor = "{highlight_color}";')
|
||||
print('pencolor = none;')
|
||||
fc, cc = vhex(objs[obj]/max_osize)
|
||||
highlight_subdir_part = f'<font face="carlito" color="{cc}" point-size="40">{highlight_head} / </font>' if highlight_head else ''
|
||||
lvl2print(f'label = <<table border="0"><tr><td border="0" cellpadding="5" bgcolor="{fc}">'
|
||||
f'{highlight_subdir_part}'
|
||||
f'<font face="carlito" color="{cc}"><b>{path.basename(obj)} ({objs[obj]}B)</b></font>'
|
||||
f'</td></tr></table>>;')
|
||||
lvl2print()
|
||||
for sym, sec, size in obj_syms:
|
||||
has_size = isinstance(size, int) and size > 0
|
||||
size_s = f' ({size}B)' if has_size else ''
|
||||
fc, cc = vhex(size/max_ssize) if has_size else ('#ffffff', '#000000')
|
||||
shape = 'box' if sec == '.text' else 'oval'
|
||||
lvl2print(f'{mangle(sym)}[label = "{sym}{size_s}", style="rounded,filled", shape="{shape}", fillcolor="{fc}", fontname="carlito", fontcolor="{cc}" color=none];')
|
||||
lvl1print()
|
||||
|
||||
edges = set()
|
||||
for start, ends in refs.items():
|
||||
for end in ends:
|
||||
end = aliases.get(end, end)
|
||||
if (start in syms or start in trace_sections_mangled) and end in syms:
|
||||
edges.add((start, end))
|
||||
|
||||
for start, end in edges:
|
||||
lvl1print(f'{mangle(start)} -> {mangle(end)} [style="bold", color="#333333"];')
|
||||
|
||||
for sec in trace_sections:
|
||||
lvl1print(f'{sec.replace(".", "_")} [label = "section {sec}", shape="box", style="filled,bold"];')
|
||||
|
||||
62
demo/fw/tools/linksize.py
Normal file
62
demo/fw/tools/linksize.py
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
def parse_linker_script(data):
|
||||
pass
|
||||
|
||||
def link(groups):
|
||||
defined_symbols = {}
|
||||
undefined_symbols = set()
|
||||
for group, files in groups:
|
||||
while True:
|
||||
found_something = False
|
||||
|
||||
for fn in files:
|
||||
symbols = load_symbols(fn)
|
||||
for symbol in symbols:
|
||||
if symbol in defined_symbols:
|
||||
|
||||
if not group or not found_something:
|
||||
break
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
import argparse
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('-T', '--script', type=str, help='Linker script to use')
|
||||
parser.add_argument('-o', '--output', type=str, help='Output file to produce')
|
||||
args, rest = parser.parse_known_intermixed_args()
|
||||
print(rest)
|
||||
|
||||
addprefix = lambda *xs: [ prefix + opt for opt in xs for prefix in ('', '-Wl,') ]
|
||||
START_GROUP = addprefix('-(', '--start-group')
|
||||
END_GROUP = addprefix('-)', '--end-group')
|
||||
GROUP_OPTS = [*START_GROUP, *END_GROUP]
|
||||
input_files = [ arg for arg in rest if not arg.startswith('-') or arg in GROUP_OPTS ]
|
||||
|
||||
def input_file_iter(input_files):
|
||||
group = False
|
||||
files = []
|
||||
for arg in input_files:
|
||||
if arg in START_GROUP:
|
||||
assert not group
|
||||
|
||||
if files:
|
||||
yield False, files # nested -Wl,--start-group
|
||||
group, files = True, []
|
||||
|
||||
elif arg in END_GROUP:
|
||||
assert group # missing -Wl,--start-group
|
||||
if files:
|
||||
yield True, files
|
||||
group, files = False, []
|
||||
|
||||
else:
|
||||
files.append(arg)
|
||||
|
||||
assert not group # missing -Wl,--end-group
|
||||
if files:
|
||||
yield False, files
|
||||
|
||||
|
||||
|
||||
118
demo/fw/tools/linktracer.py
Normal file
118
demo/fw/tools/linktracer.py
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import re
|
||||
import subprocess
|
||||
import tempfile
|
||||
import pprint
|
||||
|
||||
ARCHIVE_RE = r'([^(]*)(\([^)]*\))?'
|
||||
|
||||
def trace_source_files(linker, cmdline):
|
||||
with tempfile.NamedTemporaryFile() as mapfile:
|
||||
output = subprocess.check_output([linker, f'-Wl,--Map={mapfile.name}', *cmdline])
|
||||
|
||||
# intentionally use generator here
|
||||
idx = 0
|
||||
lines = [ line.rstrip() for line in mapfile.read().decode().splitlines() if line.strip() ]
|
||||
|
||||
for idx, line in enumerate(lines[idx:], start=idx):
|
||||
#print('Dropping', line)
|
||||
if line == 'Linker script and memory map':
|
||||
break
|
||||
|
||||
idx += 1
|
||||
objects = []
|
||||
symbols = {}
|
||||
sections = {}
|
||||
current_object = None
|
||||
last_offset = None
|
||||
last_symbol = None
|
||||
cont_sec = None
|
||||
cont_ind = None
|
||||
current_section = None
|
||||
for idx, line in enumerate(lines[idx:], start=idx):
|
||||
print(f'Processing >{line}')
|
||||
if line.startswith('LOAD'):
|
||||
_load, obj = line.split()
|
||||
objects.append(obj)
|
||||
continue
|
||||
|
||||
if line.startswith('OUTPUT'):
|
||||
break
|
||||
|
||||
m = re.match(r'^( ?)([^ ]+)? +(0x[0-9a-z]+) +(0x[0-9a-z]+)?(.*)?$', line)
|
||||
if m is None:
|
||||
m = re.match(r'^( ?)([^ ]+)?$', line)
|
||||
if m:
|
||||
cont_ind, cont_sec = m.groups()
|
||||
else:
|
||||
cont_ind, cont_sec = None, None
|
||||
last_offset, last_symbol = None, None
|
||||
continue
|
||||
indent, sec, offx, size, sym_or_src = m.groups()
|
||||
if sec is None:
|
||||
sec = cont_sec
|
||||
ind = cont_ind
|
||||
cont_sec = None
|
||||
cont_ind = None
|
||||
print(f'vals: indent={indent} sec={sec} offx={offx} size={size} sym_or_src={sym_or_src}')
|
||||
if not re.match('^[a-zA-Z_0-9<>():*]+$', sym_or_src):
|
||||
continue
|
||||
|
||||
if indent == '':
|
||||
print(f'Section: {sec} 0x{size:x}')
|
||||
current_section = sec
|
||||
sections[sec] = size
|
||||
last_offset = None
|
||||
last_symbol = None
|
||||
continue
|
||||
|
||||
if offx is not None:
|
||||
offx = int(offx, 16)
|
||||
if size is not None:
|
||||
size = int(size, 16)
|
||||
|
||||
if size is not None and sym_or_src is not None:
|
||||
# archive/object line
|
||||
archive, _member = re.match(ARCHIVE_RE, sym_or_src).groups()
|
||||
current_object = archive
|
||||
last_offset = offx
|
||||
else:
|
||||
if sym_or_src is not None:
|
||||
assert size is None
|
||||
if last_offset is not None:
|
||||
last_size = offx - last_offset
|
||||
symbols[last_symbol] = (last_size, current_section)
|
||||
print(f'Symbol: {last_symbol} 0x{last_size:x} @{current_section}')
|
||||
last_offset = offx
|
||||
last_symbol = sym_or_src
|
||||
|
||||
idx += 1
|
||||
|
||||
for idx, line in enumerate(lines[idx:], start=idx):
|
||||
if line == 'Cross Reference Table':
|
||||
break
|
||||
|
||||
idx += 1
|
||||
|
||||
# map which symbol was pulled from which object in the end
|
||||
used_defs = {}
|
||||
for line in lines:
|
||||
*left, right = line.split()
|
||||
|
||||
archive, _member = re.match(ARCHIVE_RE, right).groups()
|
||||
if left:
|
||||
used_defs[''.join(left)] = archive
|
||||
|
||||
#pprint.pprint(symbols)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import argparse
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('linker_binary')
|
||||
parser.add_argument('linker_args', nargs=argparse.REMAINDER)
|
||||
args = parser.parse_args()
|
||||
|
||||
source_files = trace_source_files(args.linker_binary, args.linker_args)
|
||||
|
||||
129
demo/fw/tools/mapparse.py
Normal file
129
demo/fw/tools/mapparse.py
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
|
||||
import re
|
||||
from collections import defaultdict, namedtuple
|
||||
|
||||
Section = namedtuple('Section', ['name', 'offset', 'objects'])
|
||||
ObjectEntry = namedtuple('ObjectEntry', ['filename', 'object', 'offset', 'size'])
|
||||
FileEntry = namedtuple('FileEntry', ['section', 'object', 'offset', 'length'])
|
||||
|
||||
class Memory:
|
||||
def __init__(self, name, origin, length, attrs=''):
|
||||
self.name, self.origin, self.length, self.attrs = name, origin, length, attrs
|
||||
self.sections = {}
|
||||
self.files = defaultdict(lambda: [])
|
||||
self.totals = defaultdict(lambda: 0)
|
||||
|
||||
def add_toplevel(self, name, offx, length):
|
||||
self.sections[name] = Section(offx, length, [])
|
||||
|
||||
def add_obj(self, name, offx, length, fn, obj):
|
||||
base_section, sep, subsec = name[1:].partition('.')
|
||||
base_section = '.'+base_section
|
||||
if base_section in self.sections:
|
||||
sec = secname, secoffx, secobjs = self.sections[base_section]
|
||||
secobjs.append(ObjectEntry(fn, obj, offx, length))
|
||||
else:
|
||||
sec = None
|
||||
self.files[fn].append(FileEntry(sec, obj, offx, length))
|
||||
self.totals[fn] += length
|
||||
|
||||
class MapFile:
|
||||
def __init__(self, s):
|
||||
self._lines = s.splitlines()
|
||||
self.memcfg = {}
|
||||
self.defaultmem = Memory('default', 0, 0xffffffffffffffff)
|
||||
self._parse()
|
||||
|
||||
def __getitem__(self, offx_or_name):
|
||||
''' Lookup a memory area by name or address '''
|
||||
if offx_or_name in self.memcfg:
|
||||
return self.memcfg[offx_or_name]
|
||||
|
||||
elif isinstance(offx_or_name, int):
|
||||
for mem in self.memcfg.values():
|
||||
if mem.origin <= offx_or_name < mem.origin+mem.length:
|
||||
return mem
|
||||
else:
|
||||
return self.defaultmem
|
||||
|
||||
raise ValueError('Invalid argument type for indexing')
|
||||
|
||||
def _skip(self, regex):
|
||||
matcher = re.compile(regex)
|
||||
for l in self:
|
||||
if matcher.match(l):
|
||||
break
|
||||
|
||||
def __iter__(self):
|
||||
while self._lines:
|
||||
yield self._lines.pop(0)
|
||||
|
||||
def _parse(self):
|
||||
self._skip('^Memory Configuration')
|
||||
|
||||
# Parse memory segmentation info
|
||||
self._skip('^Name')
|
||||
for l in self:
|
||||
if not l:
|
||||
break
|
||||
name, origin, length, *attrs = l.split()
|
||||
if not name.startswith('*'):
|
||||
self.memcfg[name] = Memory(name, int(origin, 16), int(length, 16), attrs[0] if attrs else '')
|
||||
|
||||
# Parse section information
|
||||
toplevel_m = re.compile('^(\.[a-zA-Z0-9_.]+)\s+(0x[0-9a-fA-F]+)\s+(0x[0-9a-fA-F]+)')
|
||||
secondlevel_m = re.compile('^ (\.[a-zA-Z0-9_.]+)\s+(0x[0-9a-fA-F]+)\s+(0x[0-9a-fA-F]+)\s+(.*)$')
|
||||
secondlevel_linebreak_m = re.compile('^ (\.[a-zA-Z0-9_.]+)\n')
|
||||
filelike = re.compile('^(/?[^()]*\.[a-zA-Z0-9-_]+)(\(.*\))?')
|
||||
linebreak_section = None
|
||||
for l in self:
|
||||
# Toplevel section
|
||||
match = toplevel_m.match(l)
|
||||
if match:
|
||||
name, offx, length = match.groups()
|
||||
offx, length = int(offx, 16), int(length, 16)
|
||||
self[offx].add_toplevel(name, offx, length)
|
||||
|
||||
match = secondlevel_linebreak_m.match(l)
|
||||
if match:
|
||||
linebreak_section, = match.groups()
|
||||
continue
|
||||
|
||||
if linebreak_section:
|
||||
l = ' {} {}'.format(linebreak_section, l)
|
||||
linebreak_section = None
|
||||
|
||||
# Second-level section
|
||||
match = secondlevel_m.match(l)
|
||||
if match:
|
||||
name, offx, length, misc = match.groups()
|
||||
match = filelike.match(misc)
|
||||
if match:
|
||||
fn, obj = match.groups()
|
||||
obj = obj.strip('()') if obj else None
|
||||
offx, length = int(offx, 16), int(length, 16)
|
||||
self[offx].add_obj(name, offx, length, fn, obj)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import argparse
|
||||
parser = argparse.ArgumentParser(description='Parser GCC map file')
|
||||
parser.add_argument('mapfile', type=argparse.FileType('r'), help='The GCC .map file to parse')
|
||||
parser.add_argument('-m', '--memory', type=str, help='The memory segments to print, comma-separated')
|
||||
args = parser.parse_args()
|
||||
mf = MapFile(args.mapfile.read())
|
||||
args.mapfile.close()
|
||||
|
||||
mems = args.memory.split(',') if args.memory else mf.memcfg.keys()
|
||||
|
||||
for name in mems:
|
||||
mem = mf.memcfg[name]
|
||||
print('Symbols by file for memory', name)
|
||||
for tot, fn in reversed(sorted( (tot, fn) for fn, tot in mem.totals.items() )):
|
||||
print(' {:>8} {}'.format(tot, fn))
|
||||
for length, offx, sec, obj in reversed(sorted(( (length, offx, sec, obj) for sec, obj, offx, length in
|
||||
mem.files[fn] ), key=lambda e: e[0] )):
|
||||
name = sec.name if sec else None
|
||||
print(' {:>8} {:>#08x} {}'.format(length, offx, obj))
|
||||
#print('{:>16} 0x{:016x} 0x{:016x} ({:>24}) {}'.format(name, origin, length, length, attrs))
|
||||
|
||||
1
upstream/CMSIS_5
Submodule
1
upstream/CMSIS_5
Submodule
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 3623c466819b80d9af6b0830e92f1f21a75d8243
|
||||
1
upstream/PyCortexMDebug
Submodule
1
upstream/PyCortexMDebug
Submodule
|
|
@ -0,0 +1 @@
|
|||
Subproject commit e672ff4e0514802383e064972d75657a5e46e294
|
||||
1
upstream/STM32CubeF4
Submodule
1
upstream/STM32CubeF4
Submodule
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 2f3b26f16559f7af495727a98253067a31182cfc
|
||||
1
upstream/cmsis_device_f4
Submodule
1
upstream/cmsis_device_f4
Submodule
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 3d7a3c1bae597f1ff36431145a2e34ae82fdeecb
|
||||
1
upstream/stm32square
Submodule
1
upstream/stm32square
Submodule
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 8bb6e8c614fd3e1ee90bddfbd191e8a8c4e72207
|
||||
Loading…
Add table
Add a link
Reference in a new issue